82 std::cout <<
"=== transaction_management example ===" << std::endl;
85 auto context = std::make_shared<database_context>();
86 auto db_manager = std::make_shared<database_manager>(context);
87 db_manager->set_mode(database_types::postgres);
89 std::string connection_string
90 =
"host=localhost port=5432 dbname=example_db user=user password=password";
92 auto connect_result = db_manager->connect_result(connection_string);
93 if (!connect_result.is_ok())
95 std::cerr <<
"Connection failed. Ensure PostgreSQL is running." << std::endl;
98 std::cout <<
"Connected" << std::endl;
101 db_manager->create_query_result(R
"(
102 CREATE TABLE IF NOT EXISTS accounts (
103 id SERIAL PRIMARY KEY,
104 name VARCHAR(100) NOT NULL,
105 balance DECIMAL(12,2) NOT NULL DEFAULT 0.00
108 db_manager->execute_query_result("DELETE FROM accounts");
109 db_manager->execute_query_result(
110 "INSERT INTO accounts (name, balance) VALUES ('Alice', 1000.00)");
111 db_manager->execute_query_result(
112 "INSERT INTO accounts (name, balance) VALUES ('Bob', 500.00)");
117 std::cout <<
"\n--- Scenario 1: Successful transfer ---" << std::endl;
119 auto begin_result = db_manager->begin_transaction();
120 if (!begin_result.is_ok())
122 std::cerr <<
"Failed to begin transaction" << std::endl;
125 std::cout <<
"Transaction started, in_transaction = "
126 << std::boolalpha << db_manager->in_transaction() << std::endl;
129 db_manager->execute_query_result(
130 "UPDATE accounts SET balance = balance - 200 WHERE name = 'Alice'");
131 db_manager->execute_query_result(
132 "UPDATE accounts SET balance = balance + 200 WHERE name = 'Bob'");
134 auto commit_result = db_manager->commit_transaction();
135 if (commit_result.is_ok())
137 std::cout <<
"Transaction committed" << std::endl;
141 auto result = db_manager->select_query_result(
142 "SELECT name, balance FROM accounts ORDER BY name");
145 for (
const auto& row : result.value())
147 for (
const auto& [col, val] : row)
149 std::cout <<
" " << col <<
" = ";
150 std::visit([](
const auto& v) { std::cout << v; }, val);
153 std::cout << std::endl;
161 std::cout <<
"\n--- Scenario 2: Rollback on error ---" << std::endl;
163 auto begin_result = db_manager->begin_transaction();
164 if (!begin_result.is_ok())
166 std::cerr <<
"Failed to begin transaction" << std::endl;
171 db_manager->execute_query_result(
172 "UPDATE accounts SET balance = balance - 5000 WHERE name = 'Alice'");
175 auto check = db_manager->select_query_result(
176 "SELECT balance FROM accounts WHERE name = 'Alice'");
178 bool should_rollback =
false;
179 if (check.is_ok() && !check.value().empty())
181 const auto& balance_val = check.value()[0].at(
"balance");
184 [&should_rollback](
const auto& v)
186 using T = std::decay_t<
decltype(v)>;
187 if constexpr (std::is_same_v<T, double>)
189 should_rollback = (v < 0.0);
191 else if constexpr (std::is_same_v<T, std::string>)
194 should_rollback = (!v.empty() && v[0] ==
'-');
202 std::cout <<
"Business rule violation detected, rolling back" << std::endl;
203 db_manager->rollback_transaction();
204 std::cout <<
"Transaction rolled back, in_transaction = "
205 << std::boolalpha << db_manager->in_transaction() << std::endl;
209 db_manager->commit_transaction();
210 std::cout <<
"Transaction committed (balance was not negative)" << std::endl;
214 auto result = db_manager->select_query_result(
215 "SELECT name, balance FROM accounts ORDER BY name");
218 std::cout <<
"Balances after rollback:" << std::endl;
219 for (
const auto& row : result.value())
221 for (
const auto& [col, val] : row)
223 std::cout <<
" " << col <<
" = ";
224 std::visit([](
const auto& v) { std::cout << v; }, val);
227 std::cout << std::endl;
235 std::cout <<
"\n--- Scenario 3: RAII transaction guard ---" << std::endl;
240 std::cout <<
"Guard started transaction" << std::endl;
242 db_manager->execute_query_result(
243 "INSERT INTO accounts (name, balance) VALUES ('Carol', 750.00)");
247 std::cout <<
"Guard committed transaction" << std::endl;
249 catch (
const std::exception& e)
251 std::cerr <<
"Transaction error: " << e.what() << std::endl;
255 auto result = db_manager->select_query_result(
256 "SELECT name, balance FROM accounts ORDER BY name");
259 std::cout <<
"Accounts after guard commit:" << std::endl;
260 for (
const auto& row : result.value())
262 for (
const auto& [col, val] : row)
264 std::cout <<
" " << col <<
" = ";
265 std::visit([](
const auto& v) { std::cout << v; }, val);
268 std::cout << std::endl;
274 db_manager->disconnect_result();
275 std::cout <<
"\nDisconnected" << std::endl;
277 std::cout <<
"=== transaction_management example completed ===" << std::endl;
Dependency injection container for database system components.