From 2f48981801e57eff625033929d560f1baf5069fa Mon Sep 17 00:00:00 2001 From: Jonathan Romano Date: Mon, 7 Nov 2022 04:26:15 -0500 Subject: [PATCH] Address socket issues with MariaDB Use a new method of determining how to send the connection information to the database --- dDatabase/Database.cpp | 29 +++++++++++++++++++++++++---- 1 file changed, 25 insertions(+), 4 deletions(-) diff --git a/dDatabase/Database.cpp b/dDatabase/Database.cpp index 91589377..1ce6966f 100644 --- a/dDatabase/Database.cpp +++ b/dDatabase/Database.cpp @@ -14,8 +14,6 @@ std::string Database::database; void Database::Connect(const string& host, const string& database, const string& username, const string& password) { //To bypass debug issues: - std::string newHost = "tcp://" + host; - const char* szHost = newHost.c_str(); const char* szDatabase = database.c_str(); const char* szUsername = username.c_str(); const char* szPassword = password.c_str(); @@ -23,7 +21,24 @@ void Database::Connect(const string& host, const string& database, const string& driver = sql::mariadb::get_driver_instance(); sql::Properties properties; - properties["hostName"] = szHost; + // The mariadb connector is *supposed* to handle unix:// and pipe:// prefixes to hostName, but there are bugs where + // 1) it tries to parse a database from the connection string (like in tcp://localhost:3001/darkflame) based on the + // presence of a / + // 2) even avoiding that, the connector still assumes you're connecting with a tcp socket + // So, what we do in the presence of a unix socket or pipe is to set the hostname to the protocol and localhost, + // which avoids parsing errors while still ensuring the correct connection type is used, and then setting the appropriate + // property manually (which the URL parsing fails to do) + const std::string UNIX_PROTO = "unix://"; + const std::string PIPE_PROTO = "pipe://"; + if (host.find(UNIX_PROTO) == 0) { + properties["hostName"] = "unix://localhost"; + properties["localSocket"] = host.substr(UNIX_PROTO.length()).c_str(); + } else if (host.find(PIPE_PROTO) == 0) { + properties["hostName"] = "pipe://localhost"; + properties["pipe"] = host.substr(PIPE_PROTO.length()).c_str(); + } else { + properties["hostName"] = host.c_str(); + } properties["user"] = szUsername; properties["password"] = szPassword; properties["autoReconnect"] = "true"; @@ -35,7 +50,13 @@ void Database::Connect(const string& host, const string& database, const string& } void Database::Connect() { - con = driver->connect(Database::props["hostName"].c_str(), Database::props["user"].c_str(), Database::props["password"].c_str()); + // `connect(const Properties& props)` segfaults in windows debug, but + // `connect(const SQLString& host, const SQLString& user, const SQLString& pwd)` doesn't handle pipes/unix sockets correctly + if (Database::props.find("localSocket") != Database::props.end() || Database::props.find("pipe") != Database::props.end()) { + con = driver->connect(Database::props); + } else { + con = driver->connect(Database::props["hostName"].c_str(), Database::props["user"].c_str(), Database::props["password"].c_str()); + } con->setSchema(Database::database.c_str()); }