aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorfusion32 <marcopuzziello@gmail.com>2025-10-10 15:14:02 -0300
committerfusion32 <marcopuzziello@gmail.com>2025-10-10 15:22:27 -0300
commit46c653293381dcc1188013d3e2c3f7587a199dc4 (patch)
tree0b9776f73d6e2afcd9104cf400dc5e345fcdcbea
parentcc4873e33866ba86561774a7e55449d59367661e (diff)
downloadquerymanager-46c653293381dcc1188013d3e2c3f7587a199dc4.tar.gz
querymanager-46c653293381dcc1188013d3e2c3f7587a199dc4.zip
organize database configs and schema files + compilation guards
-rw-r--r--Makefile16
-rw-r--r--config.cfg51
-rw-r--r--sqlite/README.txt (renamed from sql/README.txt)0
-rw-r--r--sqlite/init.sql (renamed from sql/init.sql)2
-rw-r--r--sqlite/schema.sql (renamed from sql/schema.sql)0
-rw-r--r--src/connections.cc2
-rw-r--r--src/database_mysql.cc6
-rw-r--r--src/database_postgres.cc6
-rw-r--r--src/database_pq.cc4
-rw-r--r--src/database_sqlite.cc19
-rw-r--r--src/querymanager.cc148
-rw-r--r--src/querymanager.hh40
12 files changed, 203 insertions, 91 deletions
diff --git a/Makefile b/Makefile
index 0ba1f30..0fca315 100644
--- a/Makefile
+++ b/Makefile
@@ -23,11 +23,17 @@ endif
DATABASE ?= sqlite
ifeq ($(DATABASE), sqlite)
DATABASEOBJ = $(BUILDDIR)/database_sqlite.obj $(BUILDDIR)/sqlite3.obj
+ CFLAGS += -DDATABASE_SQLITE=1
else ifeq ($(DATABASE), postgres)
- DATABASEOBJ = $(BUILDDIR)/database_pq.obj
+ DATABASEOBJ = $(BUILDDIR)/database_postgres.obj
+ CFLAGS += -DDATABASE_POSTGRESQL=1
LFLAGS += -lpq
+else ifeq ($(DATABASE), mariadb)
+ DATABASEOBJ = $(BUILDDIR)/database_mysql.obj
+ CFLAGS += -DDATABASE_MYSQL=1 -DDATABASE_MARIADB=1
+ LFLAGS += -lmariadb
else
- $(error Unsupported DATABASE: `$(DATABASE)`. Valid options are `sqlite` or `postgres`)
+ $(error Unsupported DATABASE: `$(DATABASE)`. Valid options are `sqlite`, `postgres`, or `mariadb`)
endif
$(BUILDDIR)/$(OUTPUTEXE): $(BUILDDIR)/connections.obj $(BUILDDIR)/hostcache.obj $(BUILDDIR)/query.obj $(BUILDDIR)/querymanager.obj $(BUILDDIR)/sha256.obj $(DATABASEOBJ)
@@ -58,7 +64,11 @@ $(BUILDDIR)/database_sqlite.obj: $(SRCDIR)/database_sqlite.cc $(SRCDIR)/queryman
@mkdir -p $(@D)
$(CXX) -c $(CXXFLAGS) -o $@ $<
-$(BUILDDIR)/database_pq.obj: $(SRCDIR)/database_pq.cc $(SRCDIR)/querymanager.hh
+$(BUILDDIR)/database_postgres.obj: $(SRCDIR)/database_postgres.cc $(SRCDIR)/querymanager.hh
+ @mkdir -p $(@D)
+ $(CXX) -c $(CXXFLAGS) -o $@ $<
+
+$(BUILDDIR)/database_mysql.obj: $(SRCDIR)/database_mysql.cc $(SRCDIR)/querymanager.hh
@mkdir -p $(@D)
$(CXX) -c $(CXXFLAGS) -o $@ $<
diff --git a/config.cfg b/config.cfg
index 30ca4cd..076c535 100644
--- a/config.cfg
+++ b/config.cfg
@@ -1,23 +1,36 @@
# HostCache Config
-MaxCachedHostNames = 100
-HostNameExpireTime = 30m
+MaxCachedHostNames = 100
+HostNameExpireTime = 30m
-# Database Config
-MaxCachedStatements = 100
-DatabaseFile = "tibia.db"
-# TODO(fusion): This is not great. Probably switch to database specific options?
-#DatabaseHost = "localhost"
-#DatabasePort = 5432
-#DatabaseUser = "postgres"
-#DatabasePassword = ""
-#DatabaseName = "tibia"
-#DatabaseTLS = true
+# SQLite Config
+SQLite.File = "tibia.db"
+SQLite.MaxCachedStatements = 100
+
+# PostgreSQL Config
+#PostgreSQL.UnixSocket = ""
+#PostgreSQL.Host = "localhost"
+#PostgreSQL.Port = 5432
+#PostgreSQL.User = "postgres"
+#PostgreSQL.Password = ""
+#PostgreSQL.Database = "tibia"
+#PostgreSQL.TLS = true
+#PostgreSQL.MaxCachedStatements = 100
+
+# MySQL/MariaDB Config
+#MySQL.UnixSocket = ""
+#MySQL.Host = "localhost"
+#MySQL.Port = 3306
+#MySQL.User = "mysql"
+#MySQL.Password = ""
+#MySQL.Database = "tibia"
+#MySQL.TLS = true
+#MySQL.MaxCachedStatements = 100
# Connection Config
-QueryManagerPort = 7173
-QueryManagerPassword = "a6glaf0c"
-QueryWorkerThreads = 1
-QueryBufferSize = 1M
-QueryMaxAttempts = 3
-MaxConnections = 25
-MaxConnectionIdleTime = 5m
+QueryManagerPort = 7173
+QueryManagerPassword = "a6glaf0c"
+QueryWorkerThreads = 1
+QueryBufferSize = 1M
+QueryMaxAttempts = 3
+MaxConnections = 25
+MaxConnectionIdleTime = 5m
diff --git a/sql/README.txt b/sqlite/README.txt
index 26f782a..26f782a 100644
--- a/sql/README.txt
+++ b/sqlite/README.txt
diff --git a/sql/init.sql b/sqlite/init.sql
index 589c4e3..dc30adf 100644
--- a/sql/init.sql
+++ b/sqlite/init.sql
@@ -1,7 +1,7 @@
-- NOTE(fusion): The query manager WON'T automatically run this but the game
-- server still requires at least the world config to be able to boot up. It
-- is probably a good idea to keep this separated from `schema.sql` and then
--- running it with `sqlite3 -echo tibia.db < sql/init.sql`, although it is
+-- running it with `sqlite3 -echo tibia.db < sqlite/init.sql`, although it is
-- not mandatory.
-- Because this isn't automatically managed, all queries are wrapped in a
-- transaction to avoid partial writes in case of errors.
diff --git a/sql/schema.sql b/sqlite/schema.sql
index 677d778..677d778 100644
--- a/sql/schema.sql
+++ b/sqlite/schema.sql
diff --git a/src/connections.cc b/src/connections.cc
index b08b52a..0760514 100644
--- a/src/connections.cc
+++ b/src/connections.cc
@@ -612,7 +612,7 @@ void ProcessConnections(void){
ASSERT(NumFds > 0);
int NumEvents = poll(Fds, NumFds, -1);
if(NumEvents == -1){
- if(errno != ETIMEDOUT){
+ if(errno != ETIMEDOUT && errno != EINTR){
LOG_ERR("Failed to poll connections: (%d) %s",
errno, strerrordesc_np(errno));
}
diff --git a/src/database_mysql.cc b/src/database_mysql.cc
new file mode 100644
index 0000000..583bb7d
--- /dev/null
+++ b/src/database_mysql.cc
@@ -0,0 +1,6 @@
+#if DATABASE_MYSQL
+#include "querymanager.hh"
+
+// TODO
+
+#endif //DATABASE_MYSQL
diff --git a/src/database_postgres.cc b/src/database_postgres.cc
new file mode 100644
index 0000000..3b24967
--- /dev/null
+++ b/src/database_postgres.cc
@@ -0,0 +1,6 @@
+#if DATABASE_POSTGRESQL
+#include "querymanager.hh"
+
+// TODO
+
+#endif //DATABASE_POSTGRESQL
diff --git a/src/database_pq.cc b/src/database_pq.cc
deleted file mode 100644
index 69cc45e..0000000
--- a/src/database_pq.cc
+++ /dev/null
@@ -1,4 +0,0 @@
-#include "querymanager.hh"
-
-// TODO(fusion):
-
diff --git a/src/database_sqlite.cc b/src/database_sqlite.cc
index 8a5e526..37a62e0 100644
--- a/src/database_sqlite.cc
+++ b/src/database_sqlite.cc
@@ -1,3 +1,4 @@
+#if DATABASE_SQLITE
#include "querymanager.hh"
#include "sqlite3.h"
@@ -43,8 +44,8 @@ public:
static void EnsureStatementCache(TDatabase *Database){
if(Database->CachedStatements == NULL){
- ASSERT(g_Config.MaxCachedStatements > 0);
- Database->MaxCachedStatements = g_Config.MaxCachedStatements;
+ ASSERT(g_Config.SQLite.MaxCachedStatements > 0);
+ Database->MaxCachedStatements = g_Config.SQLite.MaxCachedStatements;
Database->CachedStatements = (TCachedStatement*)calloc(
Database->MaxCachedStatements, sizeof(TCachedStatement));
}
@@ -233,8 +234,8 @@ static bool InitDatabaseSchema(TDatabase *Database){
return false;
}
- if(!ExecFile(Database, "sql/schema.sql")){
- LOG_ERR("Failed to execute \"sql/schema.sql\"");
+ if(!ExecFile(Database, "sqlite/schema.sql")){
+ LOG_ERR("Failed to execute \"sqlite/schema.sql\"");
return false;
}
@@ -255,7 +256,7 @@ static bool UpgradeDatabaseSchema(TDatabase *Database, int UserVersion){
char FileName[256];
int NewVersion = UserVersion;
while(true){
- snprintf(FileName, sizeof(FileName), "sql/upgrade-%d.sql", NewVersion);
+ snprintf(FileName, sizeof(FileName), "sqlite/upgrade-%d.sql", NewVersion);
if(FileExists(FileName)){
NewVersion += 1;
}else{
@@ -346,9 +347,9 @@ void DatabaseClose(TDatabase *Database){
TDatabase *DatabaseOpen(void){
TDatabase *Database = (TDatabase*)calloc(1, sizeof(TDatabase));
int Flags = SQLITE_OPEN_READWRITE | SQLITE_OPEN_CREATE | SQLITE_OPEN_NOMUTEX;
- if(sqlite3_open_v2(g_Config.DatabaseFile, &Database->Handle, Flags, NULL) != SQLITE_OK){
+ if(sqlite3_open_v2(g_Config.SQLite.File, &Database->Handle, Flags, NULL) != SQLITE_OK){
LOG_ERR("Failed to open database at \"%s\": %s\n",
- g_Config.DatabaseFile, sqlite3_errmsg(Database->Handle));
+ g_Config.SQLite.File, sqlite3_errmsg(Database->Handle));
DatabaseClose(Database);
return NULL;
}
@@ -357,7 +358,7 @@ TDatabase *DatabaseOpen(void){
LOG_ERR("Failed to open database file \"%s\" with WRITE PERMISSIONS."
" Make sure it has the appropriate permissions and is owned"
" by the same user running the query manager.",
- g_Config.DatabaseFile);
+ g_Config.SQLite.File);
DatabaseClose(Database);
return NULL;
}
@@ -2482,3 +2483,5 @@ bool CheckOnlineRecord(TDatabase *Database, int WorldID, int NumCharacters, bool
*NewRecord = sqlite3_changes(Database->Handle) > 0;
return true;
}
+
+#endif //DATABASE_SQLITE
diff --git a/src/querymanager.cc b/src/querymanager.cc
index 6c1fffe..004bc35 100644
--- a/src/querymanager.cc
+++ b/src/querymanager.cc
@@ -67,6 +67,9 @@ int64 GetClockMonotonicMS(void){
QueryPerformanceFrequency(&Frequency);
return (int64)((Counter.QuadPart * 1000) / Frequency.QuadPart);
#else
+ // NOTE(fusion): The coarse monotonic clock has a larger resolution but is
+ // supposed to be faster, even avoiding system calls in some cases. It should
+ // be fine for millisecond precision which is what we're using.
struct timespec Time;
clock_gettime(CLOCK_MONOTONIC_COARSE, &Time);
return ((int64)Time.tv_sec * 1000)
@@ -374,22 +377,46 @@ bool ReadConfig(const char *FileName, TConfig *Config){
ReadIntegerConfig(&Config->MaxCachedHostNames, Val);
}else if(StringEqCI(Key, "HostNameExpireTime")){
ReadDurationConfig(&Config->HostNameExpireTime, Val);
- }else if(StringEqCI(Key, "MaxCachedStatements")){
- ReadIntegerConfig(&Config->MaxCachedStatements, Val);
- }else if(StringEqCI(Key, "DatabaseFile")){
- ReadStringBufConfig(Config->DatabaseFile, Val);
- }else if(StringEqCI(Key, "DatabaseHost")){
- ReadStringBufConfig(Config->DatabaseHost, Val);
- }else if(StringEqCI(Key, "DatabasePort")){
- ReadIntegerConfig(&Config->DatabasePort, Val);
- }else if(StringEqCI(Key, "DatabaseUser")){
- ReadStringBufConfig(Config->DatabaseUser, Val);
- }else if(StringEqCI(Key, "DatabasePassword")){
- ReadStringBufConfig(Config->DatabasePassword, Val);
- }else if(StringEqCI(Key, "DatabaseName")){
- ReadStringBufConfig(Config->DatabaseName, Val);
- }else if(StringEqCI(Key, "DatabaseTLS")){
- ReadBooleanConfig(&Config->DatabaseTLS, Val);
+#if DATABASE_SQLITE
+ }else if(StringEqCI(Key, "SQLite.File")){
+ ReadStringBufConfig(Config->SQLite.File, Val);
+ }else if(StringEqCI(Key, "SQLite.MaxCachedStatements")){
+ ReadIntegerConfig(&Config->SQLite.MaxCachedStatements, Val);
+#elif DATABASE_POSTGRESQL
+ }else if(StringEqCI(Key, "PostgreSQL.UnixSocket")){
+ ReadStringBufConfig(Config->PostgreSQL.UnixSocket, Val);
+ }else if(StringEqCI(Key, "PostgreSQL.Host")){
+ ReadStringBufConfig(Config->PostgreSQL.Host, Val);
+ }else if(StringEqCI(Key, "PostgreSQL.Port")){
+ ReadIntegerConfig(&Config->PostgreSQL.Port, Val);
+ }else if(StringEqCI(Key, "PostgreSQL.User")){
+ ReadStringBufConfig(Config->PostgreSQL.User, Val);
+ }else if(StringEqCI(Key, "PostgreSQL.Password")){
+ ReadStringBufConfig(Config->PostgreSQL.Password, Val);
+ }else if(StringEqCI(Key, "PostgreSQL.Database")){
+ ReadStringBufConfig(Config->PostgreSQL.Database, Val);
+ }else if(StringEqCI(Key, "PostgreSQL.TLS")){
+ ReadBooleanConfig(&Config->PostgreSQL.TLS, Val);
+ }else if(StringEqCI(Key, "PostgreSQL.MaxCachedStatements")){
+ ReadIntegerConfig(&Config->PostgreSQL.MaxCachedStatements, Val);
+#elif DATABASE_MYSQL
+ }else if(StringEqCI(Key, "MySQL.UnixSocket")){
+ ReadStringBufConfig(Config->MySQL.UnixSocket, Val);
+ }else if(StringEqCI(Key, "MySQL.Host")){
+ ReadStringBufConfig(Config->MySQL.Host, Val);
+ }else if(StringEqCI(Key, "MySQL.Port")){
+ ReadIntegerConfig(&Config->MySQL.Port, Val);
+ }else if(StringEqCI(Key, "MySQL.User")){
+ ReadStringBufConfig(Config->MySQL.User, Val);
+ }else if(StringEqCI(Key, "MySQL.Password")){
+ ReadStringBufConfig(Config->MySQL.Password, Val);
+ }else if(StringEqCI(Key, "MySQL.Database")){
+ ReadStringBufConfig(Config->MySQL.Database, Val);
+ }else if(StringEqCI(Key, "MySQL.TLS")){
+ ReadBooleanConfig(&Config->MySQL.TLS, Val);
+ }else if(StringEqCI(Key, "MySQL.MaxCachedStatements")){
+ ReadIntegerConfig(&Config->MySQL.MaxCachedStatements, Val);
+#endif
}else if(StringEqCI(Key, "QueryManagerPort")){
ReadIntegerConfig(&Config->QueryManagerPort, Val);
}else if(StringEqCI(Key, "QueryManagerPassword")){
@@ -445,27 +472,41 @@ int main(int argc, const char **argv){
g_StartTimeMS = GetClockMonotonicMS();
// HostCache Config
- g_Config.MaxCachedHostNames = 100;
- g_Config.HostNameExpireTime = 30 * 60 * 1000; // milliseconds
+ g_Config.MaxCachedHostNames = 100;
+ g_Config.HostNameExpireTime = 30 * 60 * 1000; // milliseconds
// Database Config
- g_Config.MaxCachedStatements = 100;
- StringBufCopy(g_Config.DatabaseFile, "tibia.db");
- StringBufCopy(g_Config.DatabaseHost, "localhost");
- g_Config.DatabasePort = 5432;
- StringBufCopy(g_Config.DatabaseUser, "tibia");
- StringBufCopy(g_Config.DatabasePassword, "");
- StringBufCopy(g_Config.DatabaseName, "");
- g_Config.DatabaseTLS = true;
+#if DATABASE_SQLITE
+ StringBufCopy(g_Config.SQLite.File, "tibia.db");
+ g_Config.SQLite.MaxCachedStatements = 100;
+#elif DATABASE_POSTGRESQL
+ StringBufCopy(g_Config.PostgreSQL.UnixSocket, "");
+ StringBufCopy(g_Config.PostgreSQL.Host, "localhost");
+ g_Config.PostgreSQL.Port = 5432;
+ StringBufCopy(g_Config.PostgreSQL.User, "postgres");
+ StringBufCopy(g_Config.PostgreSQL.Password, "");
+ StringBufCopy(g_Config.PostgreSQL.Database, "tibia");
+ g_Config.PostgreSQL.TLS = true;
+ g_Config.PostgreSQL.MaxCachedStatements = 100;
+#elif DATABASE_MYSQL
+ StringBufCopy(g_Config.MySQL.UnixSocket, "");
+ StringBufCopy(g_Config.MySQL.Host, "localhost");
+ g_Config.MySQL.Port = 5432;
+ StringBufCopy(g_Config.MySQL.User, "postgres");
+ StringBufCopy(g_Config.MySQL.Password, "");
+ StringBufCopy(g_Config.MySQL.Database, "tibia");
+ g_Config.MySQL.TLS = true;
+ g_Config.MySQL.MaxCachedStatements = 100;
+#endif
// Connection Config
- g_Config.QueryManagerPort = 7174;
+ g_Config.QueryManagerPort = 7174;
StringBufCopy(g_Config.QueryManagerPassword, "");
- g_Config.QueryWorkerThreads = 1;
- g_Config.QueryBufferSize = (int)MB(1);
- g_Config.QueryMaxAttempts = 2;
- g_Config.MaxConnections = 50;
- g_Config.MaxConnectionIdleTime = 60 * 1000; // milliseconds
+ g_Config.QueryWorkerThreads = 1;
+ g_Config.QueryBufferSize = (int)MB(1);
+ g_Config.QueryMaxAttempts = 3;
+ g_Config.MaxConnections = 25;
+ g_Config.MaxConnectionIdleTime = 60 * 1000; // milliseconds
LOG("Tibia Query Manager v0.2");
if(!ReadConfig("config.cfg", &g_Config)){
@@ -473,21 +514,34 @@ int main(int argc, const char **argv){
}
// NOTE(fusion): Print config values for debugging purposes.
- LOG("Max cached host names: %d", g_Config.MaxCachedHostNames);
- LOG("Host name expire time: %dms", g_Config.HostNameExpireTime);
- LOG("Max cached statements: %d", g_Config.MaxCachedStatements);
- LOG("Database file: \"%s\"", g_Config.DatabaseFile);
- LOG("Database host: \"%s\"", g_Config.DatabaseHost);
- LOG("Database port: %d", g_Config.DatabasePort);
- LOG("Database user: \"%s\"", g_Config.DatabaseUser);
- LOG("Database name: \"%s\"", g_Config.DatabaseName);
- LOG("Database TLS: %s", g_Config.DatabaseTLS ? "true" : "false");
- LOG("Query manager port: %d", g_Config.QueryManagerPort);
- LOG("Query worker threads: %d", g_Config.QueryWorkerThreads);
- LOG("Query buffer size: %d", g_Config.QueryBufferSize);
- LOG("Query max attempts: %d", g_Config.QueryMaxAttempts);
- LOG("Max connections: %d", g_Config.MaxConnections);
- LOG("Max connection idle time: %dms", g_Config.MaxConnectionIdleTime);
+ LOG("Max cached host names: %d", g_Config.MaxCachedHostNames);
+ LOG("Host name expire time: %dms", g_Config.HostNameExpireTime);
+#if DATABASE_SQLITE
+ LOG("SQLite file: \"%s\"", g_Config.SQLite.File);
+ LOG("SQLite max cached statements: %d", g_Config.SQLite.MaxCachedStatements);
+#elif DATABASE_POSTGRESQL
+ LOG("PostgreSQL unix socket: \"%s\"", g_Config.PostgreSQL.UnixSocket);
+ LOG("PostgreSQL host: \"%s\"", g_Config.PostgreSQL.Host);
+ LOG("PostgreSQL port: %d", g_Config.PostgreSQL.Port);
+ LOG("PostgreSQL user: \"%s\"", g_Config.PostgreSQL.User);
+ LOG("PostgreSQL database: \"%s\"", g_Config.PostgreSQL.Database);
+ LOG("PostgreSQL TLS: %s", g_Config.PostgreSQL.TLS ? "true" : "false");
+ LOG("PostgreSQL max cached statements: %d", g_Config.PostgreSQL.MaxCachedStatements);
+#elif DATABASE_MYSQL
+ LOG("MySQL unix socket: \"%s\"", g_Config.MySQL.UnixSocket);
+ LOG("MySQL host: \"%s\"", g_Config.MySQL.Host);
+ LOG("MySQL port: %d", g_Config.MySQL.Port);
+ LOG("MySQL user: \"%s\"", g_Config.MySQL.User);
+ LOG("MySQL database: \"%s\"", g_Config.MySQL.Database);
+ LOG("MySQL TLS: %s", g_Config.MySQL.TLS ? "true" : "false");
+ LOG("MySQL max cached statements: %d", g_Config.MySQL.MaxCachedStatements);
+#endif
+ LOG("Query manager port: %d", g_Config.QueryManagerPort);
+ LOG("Query worker threads: %d", g_Config.QueryWorkerThreads);
+ LOG("Query buffer size: %d", g_Config.QueryBufferSize);
+ LOG("Query max attempts: %d", g_Config.QueryMaxAttempts);
+ LOG("Max connections: %d", g_Config.MaxConnections);
+ LOG("Max connection idle time: %dms", g_Config.MaxConnectionIdleTime);
if(!CheckSHA256()){
return EXIT_FAILURE;
diff --git a/src/querymanager.hh b/src/querymanager.hh
index 15234e9..2ae12b1 100644
--- a/src/querymanager.hh
+++ b/src/querymanager.hh
@@ -75,20 +75,44 @@ typedef size_t usize;
TRAP(); \
}while(0)
+#if !DATABASE_SQLITE && !DATABASE_POSTGRESQL && !DATABASE_MYSQL
+# error "No database system defined."
+#endif
+
struct TConfig{
// HostCache Config
int MaxCachedHostNames;
int HostNameExpireTime;
// Database Config
- int MaxCachedStatements;
- char DatabaseFile[100];
- char DatabaseHost[100];
- int DatabasePort;
- char DatabaseUser[30];
- char DatabasePassword[30];
- char DatabaseName[30];
- bool DatabaseTLS;
+#if DATABASE_SQLITE
+ struct{
+ char File[100];
+ int MaxCachedStatements;
+ } SQLite;
+#elif DATABASE_POSTGRESQL
+ struct{
+ char UnixSocket[100];
+ char Host[100];
+ int Port;
+ char User[30];
+ char Password[30];
+ char Database[30];
+ bool TLS;
+ int MaxCachedStatements;
+ } PostgreSQL;
+#elif DATABASE_MYSQL
+ struct{
+ char UnixSocket[100];
+ char Host[100];
+ int Port;
+ char User[30];
+ char Password[30];
+ char Database[30];
+ bool TLS;
+ int MaxCachedStatements;
+ } MySQL;
+#endif
// Connection Config
int QueryManagerPort;