Skip to content

Commit 5b714bb

Browse files
committed
Implement statement specific options
1 parent 96f31a1 commit 5b714bb

7 files changed

Lines changed: 56 additions & 15 deletions

File tree

docs/intro/config-file.rst

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,10 @@ The InterceptDB Config file
2727
isThisALongQuery=1 AND
2828
queriesCanBeMultiline=1 AND
2929
thatsWhyILikeYAML=5;
30+
queryWithOptions:
31+
query: SELECT NOW(), tinyIntValue FROM MyTable;
32+
parseDateType: array #I want this specific statement to return DateTime values in array format
33+
parseTinyintAsBool: true #I want this specific statement to return my tinyInt as a boolean in dbResultTo(Parsed)Array
3034
3135
global:
3236
enableDynamicQueries: true #Allow queries to be created from SQF, if false only statements from config are allowed
@@ -47,4 +51,4 @@ Config has to be in ``Arma 3/@InterceptDB/config.yaml`` Other subfolders or rena
4751

4852
The config is loaded at preInit. If anything on the config loading fails, a error will be printed to the RPT.
4953

50-
#TODO if people need it, add ability to set connection options in config.
54+
Per-statement options take precendence over global options

src/config.cpp

Lines changed: 12 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -83,7 +83,17 @@ void Config::reloadConfig() {
8383

8484
for (auto& it : config["statements"]) {
8585
r_string stmtName = it.first.as<r_string>();
86-
statements[stmtName] = it.second.as<r_string>();
86+
if (it.IsMap()) {
87+
if (!it["query"]) throw std::runtime_error(("statement "+stmtName+" has no 'query' entry").c_str());
88+
89+
statements[stmtName] = {
90+
it["query"].as<r_string>(),
91+
it["parseTinyintAsBool"].as<bool>(false),
92+
dateTypeFromString(config["global"]["parseDateType"].as<r_string>("string"sv))
93+
};
94+
} else {
95+
statements[stmtName] = {it.second.as<r_string>()};
96+
}
8797
}
8898

8999
#pragma endregion statements
@@ -92,6 +102,7 @@ void Config::reloadConfig() {
92102

93103
if (!config["global"].IsMap()) throw std::runtime_error("Config Global entry is not a map");
94104

105+
95106
dynamicQueriesEnabled = config["global"]["enableDynamicQueries"].as<bool>(true);
96107
parseTinyintAsBool = config["global"]["parseTinyintAsBool"].as<bool>(false);
97108
dateType = dateTypeFromString(config["global"]["parseDateType"].as<r_string>("string"sv));

src/config.h

Lines changed: 15 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -16,16 +16,29 @@ enum class ConfigDateType {
1616

1717
ConfigDateType dateTypeFromString(std::string_view str);
1818

19+
class ConfigStatement {
20+
public:
21+
r_string query;
22+
bool parseTinyintAsBool = false;
23+
ConfigDateType dateType = ConfigDateType::humanString;
24+
};
25+
1926

2027
class Config : public intercept::singleton<Config> {
2128

2229
public:
2330
void reloadConfig();
2431

32+
ConfigStatement getStatement(r_string name) {
33+
auto found = statements.find(name);
34+
if (found == statements.end()) return ConfigStatement();
35+
return found->second;
36+
}
37+
2538
r_string getQuery(r_string name) {
2639
auto found = statements.find(name);
2740
if (found == statements.end()) return r_string();
28-
return found->second;
41+
return found->second.query;
2942
}
3043

3144
mariadb::account_ref getAccount(r_string name) {
@@ -58,7 +71,7 @@ class Config : public intercept::singleton<Config> {
5871

5972
private:
6073
std::map<intercept::types::r_string, mariadb::account_ref> accounts;
61-
std::map<intercept::types::r_string, intercept::types::r_string> statements;
74+
std::map<intercept::types::r_string, ConfigStatement> statements;
6275
std::map<intercept::types::r_string, std::filesystem::path> schemas;
6376
bool dynamicQueriesEnabled = true;
6477
bool parseTinyintAsBool = false;

src/connection.cpp

Lines changed: 8 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -78,10 +78,13 @@ bool Connection::throwQueryError(game_state& gs, mariadb::connection_ref connect
7878
return false; //error was not handled and we threw it
7979
}
8080

81-
GameDataDBAsyncResult* Connection::pushAsyncQuery(game_state& gs, mariadb::connection_ref connection, auto_array<game_value> boundValues, r_string queryString) {
81+
GameDataDBAsyncResult* Connection::pushAsyncQuery(game_state& gs, mariadb::connection_ref connection, ref<GameDataDBQuery> query) {
8282
auto gd_res = new GameDataDBAsyncResult();
8383
gd_res->data = std::make_shared<GameDataDBAsyncResult::dataT>();
8484

85+
auto_array<game_value> boundValues = query->boundValues;
86+
r_string queryString = query->getQueryString();
87+
gd_res->data->statementName = query->isConfigQuery ? query->queryString : r_string{};
8588

8689
//If we give them to task, it will destruct the array after task is done, and may call dealloc int he pool allocator
8790
std::vector<
@@ -209,6 +212,7 @@ class callstack_item_WaitForQueryResult : public vm_context::callstack_item {
209212
//push result onto stack.
210213
auto gd_res = new GameDataDBResult();
211214
gd_res->res = res->data->res;
215+
gd_res->statementName = res->data->statementName;
212216
s->get_vm_context()->scriptStack[_stackEndAtStart] = game_value(gd_res);
213217
d1 = 2; //done
214218
//#TODO fix this. Cannot currently because task wants invoker lock, which it won't get while we freeze the game here
@@ -268,6 +272,7 @@ game_value Connection::cmd_execute(game_state& gs, game_value_parameter con, gam
268272

269273
auto gd_res = new GameDataDBResult();
270274
gd_res->res = res;
275+
gd_res->statementName = query->isConfigQuery ? query->queryString : r_string{};
271276
return gd_res;
272277
} catch (mariadb::exception::connection& x) {
273278
throwQueryError(gs, session, static_cast<size_t>(x.error_id()), static_cast<r_string>(x.what()), query->getQueryString());
@@ -281,7 +286,7 @@ game_value Connection::cmd_execute(game_state& gs, game_value_parameter con, gam
281286

282287
auto& cs = gs.get_vm_context()->callstack;
283288

284-
auto gd_res = pushAsyncQuery(gs, session, query->boundValues, query->getQueryString());
289+
auto gd_res = pushAsyncQuery(gs, session, query);
285290

286291
auto newItem = new callstack_item_WaitForQueryResult(gd_res);
287292
newItem->_parent = cs.back();
@@ -300,7 +305,7 @@ game_value Connection::cmd_executeAsync(game_state& gs, game_value_parameter con
300305
auto session = con.get_as<GameDataDBConnection>()->session;
301306
auto query = qu.get_as<GameDataDBQuery>();
302307

303-
auto gd_res = pushAsyncQuery(gs, session, query->boundValues, query->getQueryString());
308+
auto gd_res = pushAsyncQuery(gs, session, query);
304309
Threading::get().pushAsyncWork(gd_res);
305310
__itt_task_end(domainConnection);
306311
return gd_res;

src/connection.h

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@
22
#include <intercept.hpp>
33
#include "mariadb++/connection.hpp"
44
#include "res.h"
5+
#include "query.h"
56
using namespace intercept;
67
using namespace intercept::types;
78

@@ -10,7 +11,7 @@ using namespace intercept::types;
1011
class Connection {
1112
public:
1213
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);
14+
static [[nodiscard]] GameDataDBAsyncResult* pushAsyncQuery(game_state& gs, mariadb::connection_ref connection, ref<GameDataDBQuery> query);
1415

1516
static game_value cmd_createConnectionArray(game_state&, game_value_parameter right);
1617
static game_value cmd_createConnectionConfig(game_state&, game_value_parameter right);

src/res.cpp

Lines changed: 12 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -150,12 +150,15 @@ game_value Result::cmd_lastInsertId(game_state&, game_value_parameter right) {
150150
}
151151

152152
game_value Result::cmd_toArray(game_state&, game_value_parameter right) {
153-
auto& res = right.get_as<GameDataDBResult>()->res;
153+
auto& gdRes = right.get_as<GameDataDBResult>();
154+
auto& res = gdRes->res;
154155
if (!res) return auto_array<game_value>();
155156
auto_array<game_value> result;
156157

157-
const auto [dateParser, dateTimeParser, timeParser] = getDateParser(Config::get().getDateType());
158-
const auto parseTinyintAsBool = Config::get().getTinyintAsBool();
158+
const auto [dateParser, dateTimeParser, timeParser] = getDateParser(
159+
gdRes->statementName.empty() ? Config::get().getDateType() : Config::get().getStatement(gdRes->statementName).dateType);
160+
const auto parseTinyintAsBool =
161+
gdRes->statementName.empty() ? Config::get().getTinyintAsBool() : Config::get().getStatement(gdRes->statementName).parseTinyintAsBool;
159162

160163
while (res->next()) {
161164
auto_array<game_value> row;
@@ -204,12 +207,15 @@ game_value Result::cmd_toArray(game_state&, game_value_parameter right) {
204207
}
205208

206209
game_value Result::cmd_toParsedArray(game_state& state, game_value_parameter right) {
207-
auto& res = right.get_as<GameDataDBResult>()->res;
210+
auto& gdRes = right.get_as<GameDataDBResult>();
211+
auto& res = gdRes->res;
208212
if (!res) return auto_array<game_value>();
209213
auto_array<game_value> result;
210214

211-
const auto [dateParser, dateTimeParser, timeParser] = getDateParser(Config::get().getDateType());
212-
const auto parseTinyintAsBool = Config::get().getTinyintAsBool();
215+
const auto [dateParser, dateTimeParser, timeParser] = getDateParser(
216+
gdRes->statementName.empty() ? Config::get().getDateType() : Config::get().getStatement(gdRes->statementName).dateType);
217+
const auto parseTinyintAsBool =
218+
gdRes->statementName.empty() ? Config::get().getTinyintAsBool() : Config::get().getStatement(gdRes->statementName).parseTinyintAsBool;
213219

214220
while (res->next()) {
215221
auto_array<game_value> row;

src/res.h

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,6 @@ using namespace intercept::types;
99

1010
class Result {
1111
public:
12-
1312
static game_value cmd_affectedRows(game_state&, game_value_parameter right);
1413
static game_value cmd_lastInsertId(game_state&, game_value_parameter right);
1514
static game_value cmd_toArray(game_state&, game_value_parameter right);
@@ -70,6 +69,7 @@ class GameDataDBResult : public game_data {
7069
}
7170

7271
mariadb::result_set_ref res;
72+
r_string statementName; //Is null if this was not a statement from config
7373
};
7474

7575
class GameDataDBAsyncResult : public game_data {
@@ -113,6 +113,7 @@ class GameDataDBAsyncResult : public game_data {
113113
struct dataT {
114114
std::future<bool> fut;
115115
mariadb::result_set_ref res;
116+
r_string statementName; //Is null if this was not a statement from config
116117
game_value callback;
117118
game_value callbackArgs;
118119
};

0 commit comments

Comments
 (0)