@@ -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 + " \n at\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+
67115game_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 () + " \n at\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 () + " \n at\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 () + " \n at\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;
0 commit comments