Skip to content

Commit 197662f

Browse files
committed
Fixed #9
1 parent 61c5224 commit 197662f

2 files changed

Lines changed: 61 additions & 95 deletions

File tree

src/connection.cpp

Lines changed: 57 additions & 95 deletions
Original file line numberDiff line numberDiff line change
@@ -64,6 +64,54 @@ game_data* createGameDataDBConnection(param_archive* ar) {
6464
return x;
6565
}
6666

67+
bool Connection::throwQueryError(game_state& gs, mariadb::connection_ref connection, size_t errorID, r_string errorMessage, r_string queryString) {
68+
if (connection->account()->hasErrorHandler()) {
69+
for (auto& it : connection->account()->getErrorHandlers()) {
70+
auto res = sqf::call(it, { errorMessage, errorID, queryString });
71+
72+
if (res.type_enum() == game_data_type::BOOL && static_cast<bool>(res)) return true; //error was handled
73+
}
74+
}
75+
auto exText = r_string("Intercept-DB exception ") + errorMessage + "\nat\n" + queryString;
76+
gs.set_script_error(game_state::game_evaluator::evaluator_error_type::foreign,
77+
exText);
78+
return false; //error was not handled and we threw it
79+
}
80+
81+
GameDataDBAsyncResult* Connection::pushAsyncQuery(game_state& gs, mariadb::connection_ref connection, auto_array<game_value> boundValues, r_string queryString) {
82+
auto gd_res = new GameDataDBAsyncResult();
83+
gd_res->data = std::make_shared<GameDataDBAsyncResult::dataT>();
84+
gd_res->data->fut = Threading::get().pushTask(connection,
85+
[queryString, boundValues, result = gd_res->data, &gs](mariadb::connection_ref con) -> bool {
86+
try {
87+
auto statement = con->create_statement(queryString);
88+
uint32_t idx = 0;
89+
for (auto& it : boundValues) {
90+
91+
switch (it.type_enum()) {
92+
case game_data_type::SCALAR: statement->set_float(idx++, static_cast<float>(it)); break;
93+
case game_data_type::BOOL: statement->set_boolean(idx++, static_cast<bool>(it)); break;
94+
case game_data_type::STRING: statement->set_string(idx++, static_cast<r_string>(it)); break;
95+
default:;
96+
}
97+
}
98+
result->res = statement->query();
99+
return true;
100+
}
101+
catch (mariadb::exception::connection& x) {
102+
invoker_lock l;
103+
throwQueryError(gs, con, static_cast<size_t>(x.error_id()), static_cast<r_string>(x.what()), queryString);
104+
return false;
105+
}
106+
catch (std::out_of_range& x) {
107+
invoker_lock l;
108+
throwQueryError(gs, con, 1337, static_cast<r_string>(x.what()), queryString);
109+
return false;
110+
}
111+
});
112+
return gd_res;
113+
}
114+
67115
game_value Connection::cmd_createConnectionArray(game_state& gs, game_value_parameter right) {
68116
if (right.size() < 5) {
69117
gs.set_script_error(game_state::game_evaluator::evaluator_error_type::dim,
@@ -167,34 +215,22 @@ game_value Connection::cmd_execute(game_state& gs, game_value_parameter con, gam
167215
for (auto& it : query->boundValues) {
168216

169217
switch (it.type_enum()) {
170-
case game_data_type::SCALAR: statement->set_float(idx++, static_cast<float>(it)); break;
171-
case game_data_type::BOOL: statement->set_boolean(idx++, static_cast<bool>(it)); break;
172-
case game_data_type::STRING: statement->set_string(idx++, static_cast<r_string>(it)); break;
173-
default:;
218+
case game_data_type::SCALAR: statement->set_float(idx++, static_cast<float>(it)); break;
219+
case game_data_type::BOOL: statement->set_boolean(idx++, static_cast<bool>(it)); break;
220+
case game_data_type::STRING: statement->set_string(idx++, static_cast<r_string>(it)); break;
221+
default:;
174222
}
175223
}
176224

177225
auto res = statement->query();
178-
//#TODO handle error in create_statement and in query()
179-
180226

181227
auto gd_res = new GameDataDBResult();
182228
gd_res->res = res;
183-
184229
return gd_res;
185230
} catch (mariadb::exception::connection& x) {
186-
if (session->account()->hasErrorHandler()) {
187-
for (auto& it : session->account()->getErrorHandlers()) {
188-
189-
auto res = sqf::call(it, { static_cast<r_string>(x.what()), static_cast<size_t>(x.error_id()), query->getQueryString() });
190-
191-
if (res.type_enum() == game_data_type::BOOL && static_cast<bool>(res)) return {}; //If returned true then error was handled.
192-
}
193-
}
194-
auto exText = r_string("Intercept-DB exception ") + x.what() + "\nat\n" + query->getQueryString();
195-
gs.set_script_error(game_state::game_evaluator::evaluator_error_type::foreign,
196-
exText);
197-
//#TODO does this log to RPT? I hope so.
231+
throwQueryError(gs, session, static_cast<size_t>(x.error_id()), static_cast<r_string>(x.what()), query->getQueryString());
232+
} catch (std::out_of_range& x) {
233+
throwQueryError(gs, session, 1337, static_cast<r_string>(x.what()), query->getQueryString());
198234
}
199235
return {}; //burp
200236

@@ -203,44 +239,7 @@ game_value Connection::cmd_execute(game_state& gs, game_value_parameter con, gam
203239

204240
auto& cs = gs.get_vm_context()->callstack;
205241

206-
auto gd_res = new GameDataDBAsyncResult();
207-
gd_res->data = std::make_shared<GameDataDBAsyncResult::dataT>();
208-
209-
210-
211-
gd_res->data->fut = Threading::get().pushTask(session,
212-
[stmt = query->getQueryString(), boundV = query->boundValues, result = gd_res->data, &gs](mariadb::connection_ref con) -> bool {
213-
try {
214-
auto statement = con->create_statement(stmt);
215-
uint32_t idx = 0;
216-
for (auto& it : boundV) {
217-
218-
switch (it.type_enum()) {
219-
case game_data_type::SCALAR: statement->set_float(idx++, static_cast<float>(it)); break;
220-
case game_data_type::BOOL: statement->set_boolean(idx++, static_cast<bool>(it)); break;
221-
case game_data_type::STRING: statement->set_string(idx++, static_cast<r_string>(it)); break;
222-
}
223-
}
224-
result->res = statement->query();
225-
return true;
226-
} catch (mariadb::exception::connection& x) {
227-
invoker_lock l;
228-
if (con->account()->hasErrorHandler()) {
229-
for (auto& it : con->account()->getErrorHandlers()) {
230-
231-
auto res = sqf::call(it, { static_cast<r_string>(x.what()), static_cast<size_t>(x.error_id()), stmt });
232-
233-
if (res.type_enum() == game_data_type::BOOL && static_cast<bool>(res)) return false; //If returned true then error was handled.
234-
}
235-
}
236-
auto exText = r_string("Intercept-DB exception ") + x.what() + "\nat\n" + stmt;
237-
gs.set_script_error(game_state::game_evaluator::evaluator_error_type::foreign,
238-
exText);
239-
sqf::diag_log(exText);
240-
241-
return false;
242-
}
243-
});
242+
auto gd_res = pushAsyncQuery(gs, session, query->boundValues, query->getQueryString());
244243

245244
auto newItem = new callstack_item_WaitForQueryResult(gd_res);
246245
newItem->_parent = cs.back();
@@ -259,45 +258,8 @@ game_value Connection::cmd_executeAsync(game_state& gs, game_value_parameter con
259258
auto session = con.get_as<GameDataDBConnection>()->session;
260259
auto query = qu.get_as<GameDataDBQuery>();
261260

262-
auto gd_res = new GameDataDBAsyncResult();
263-
gd_res->data = std::make_shared<GameDataDBAsyncResult::dataT>();
264-
gd_res->data->fut = Threading::get().pushTask(session,
265-
[stmt = query->getQueryString(), boundV = query->boundValues, result = gd_res->data, &gs](mariadb::connection_ref con) -> bool
266-
{
267-
__itt_task_begin(domainConnection, __itt_null, __itt_null, connection_cmd_executeAsync_task);
268-
try {
269-
auto statement = con->create_statement(stmt);
270-
uint32_t idx = 0;
271-
for (auto& it : boundV) {
272-
273-
switch (it.type_enum()) {
274-
case game_data_type::SCALAR: statement->set_float(idx++, static_cast<float>(it)); break;
275-
case game_data_type::BOOL: statement->set_boolean(idx++, static_cast<bool>(it)); break;
276-
case game_data_type::STRING: statement->set_string(idx++, static_cast<r_string>(it)); break;
277-
}
278-
}
279-
result->res = statement->query();
280-
__itt_task_end(domainConnection);
281-
return true;
282-
} catch (mariadb::exception::connection& x) {
283-
invoker_lock l;
284-
if (con->account()->hasErrorHandler()) {
285-
for (auto& it : con->account()->getErrorHandlers()) {
286-
287-
auto res = sqf::call(it, { static_cast<r_string>(x.what()), static_cast<size_t>(x.error_id()), stmt });
288-
289-
if (res.type_enum() == game_data_type::BOOL && static_cast<bool>(res)) return false; //If returned true then error was handled.
290-
}
291-
}
292-
auto exText = r_string("Intercept-DB exception ") + x.what() + "\nat\n" + stmt;
293-
sqf::diag_log(exText);
294-
gs.set_script_error(game_state::game_evaluator::evaluator_error_type::foreign,
295-
exText);
296261

297-
__itt_task_end(domainConnection);
298-
return false;
299-
}
300-
}, true);
262+
auto gd_res = pushAsyncQuery(gs, session, query->boundValues, query->getQueryString());
301263
Threading::get().pushAsyncWork(gd_res);
302264
__itt_task_end(domainConnection);
303265
return gd_res;

src/connection.h

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,16 @@
11
#pragma once
22
#include <intercept.hpp>
3+
#include "mariadb++/connection.hpp"
4+
#include "res.h"
35
using namespace intercept;
46
using namespace intercept::types;
57

68

79

810
class Connection {
911
public:
12+
static bool throwQueryError(game_state& gs, mariadb::connection_ref connection, size_t errorID, r_string errorMessage, r_string queryString);
13+
static [[nodiscard]] GameDataDBAsyncResult* pushAsyncQuery(game_state& gs, mariadb::connection_ref connection, auto_array<game_value> boundValues, r_string queryString);
1014

1115
static game_value cmd_createConnectionArray(game_state&, game_value_parameter right);
1216
static game_value cmd_createConnectionConfig(game_state&, game_value_parameter right);

0 commit comments

Comments
 (0)