Database System 0.1.0
Advanced C++20 Database System with Multi-Backend Support
Loading...
Searching...
No Matches
connection_pool_demo.cpp
Go to the documentation of this file.
1// BSD 3-Clause License
2// Copyright (c) 2025, 🍀☀🌕🌥 🌊
3// See the LICENSE file in the project root for full license information.
4
26#include <iostream>
27#include <memory>
28#include <string>
29#include <thread>
30#include <vector>
31#include <mutex>
32#include <variant>
33
36
37using namespace database;
38
39static std::mutex cout_mutex;
40
44static void thread_print(int thread_id, const std::string& msg)
45{
46 std::lock_guard<std::mutex> lock(cout_mutex);
47 std::cout << " [thread " << thread_id << "] " << msg << std::endl;
48}
49
54static void worker(int thread_id, const std::string& connection_string)
55{
56 // Each thread creates its own context and manager
57 auto context = std::make_shared<database_context>();
58 auto db = std::make_shared<database_manager>(context);
59 db->set_mode(database_types::postgres);
60
61 auto connect_result = db->connect_result(connection_string);
62 if (!connect_result.is_ok())
63 {
64 thread_print(thread_id, "Connection failed");
65 return;
66 }
67 thread_print(thread_id, "Connected");
68
69 // Insert a row identifying this thread
70 std::string insert_sql
71 = "INSERT INTO pool_demo (thread_id, message) VALUES ("
72 + std::to_string(thread_id) + ", 'Hello from thread "
73 + std::to_string(thread_id) + "')";
74
75 auto insert_result = db->execute_query_result(insert_sql);
76 if (insert_result.is_ok())
77 {
78 thread_print(thread_id, "Row inserted");
79 }
80 else
81 {
82 thread_print(thread_id, "Insert failed");
83 }
84
85 // Read back all rows (each thread sees the current state)
86 auto select_result = db->select_query_result(
87 "SELECT thread_id, message FROM pool_demo ORDER BY thread_id");
88 if (select_result.is_ok())
89 {
90 thread_print(thread_id,
91 "Read " + std::to_string(select_result.value().size()) + " row(s)");
92 }
93
94 db->disconnect_result();
95 thread_print(thread_id, "Disconnected");
96}
97
98int main()
99{
100 std::cout << "=== connection_pool_demo example ===" << std::endl;
101
102 std::string connection_string
103 = "host=localhost port=5432 dbname=example_db user=user password=password";
104
105 // Setup: create the demo table using a single connection
106 {
107 auto context = std::make_shared<database_context>();
108 auto db = std::make_shared<database_manager>(context);
109 db->set_mode(database_types::postgres);
110
111 auto connect_result = db->connect_result(connection_string);
112 if (!connect_result.is_ok())
113 {
114 std::cerr << "Setup connection failed. Ensure PostgreSQL is running."
115 << std::endl;
116 return 1;
117 }
118
119 db->create_query_result(R"(
120 CREATE TABLE IF NOT EXISTS pool_demo (
121 id SERIAL PRIMARY KEY,
122 thread_id INTEGER NOT NULL,
123 message VARCHAR(200)
124 )
125 )");
126 db->execute_query_result("DELETE FROM pool_demo");
127 db->disconnect_result();
128 std::cout << "Setup complete" << std::endl;
129 }
130
131 // Launch multiple threads, each with its own connection
132 const int num_threads = 4;
133 std::vector<std::thread> threads;
134 threads.reserve(num_threads);
135
136 std::cout << "\nLaunching " << num_threads << " worker threads..." << std::endl;
137
138 for (int i = 0; i < num_threads; ++i)
139 {
140 threads.emplace_back(worker, i, connection_string);
141 }
142
143 // Wait for all threads to complete
144 for (auto& t : threads)
145 {
146 t.join();
147 }
148 std::cout << "\nAll threads completed" << std::endl;
149
150 // Final verification: read all inserted rows
151 {
152 auto context = std::make_shared<database_context>();
153 auto db = std::make_shared<database_manager>(context);
154 db->set_mode(database_types::postgres);
155
156 auto connect_result = db->connect_result(connection_string);
157 if (connect_result.is_ok())
158 {
159 auto result = db->select_query_result(
160 "SELECT thread_id, message FROM pool_demo ORDER BY thread_id");
161 if (result.is_ok())
162 {
163 std::cout << "\nFinal table contents (" << result.value().size()
164 << " rows):" << std::endl;
165 for (const auto& row : result.value())
166 {
167 for (const auto& [col, val] : row)
168 {
169 std::cout << " " << col << " = ";
170 std::visit([](const auto& v) { std::cout << v; }, val);
171 std::cout << " ";
172 }
173 std::cout << std::endl;
174 }
175 }
176 db->disconnect_result();
177 }
178 }
179
180 std::cout << "\n=== connection_pool_demo example completed ===" << std::endl;
181 return 0;
182}
static std::mutex cout_mutex
static void worker(int thread_id, const std::string &connection_string)
Worker function: creates its own connection, inserts data, reads it back, and disconnects.
static void thread_print(int thread_id, const std::string &msg)
Thread-safe print helper.
int main()
Dependency injection container for database system components.