mirror of
https://gitee.com/an-tao/drogon.git
synced 2024-11-30 02:37:57 +08:00
Fix failing to connect to DB if parameters contains spaces (#589)
This commit is contained in:
parent
bbb338bf12
commit
ada35c43fa
@ -251,6 +251,7 @@ if(pg_FOUND OR MySQL_FOUND OR SQLite3_FOUND)
|
||||
orm_lib/src/DbClientImpl.cc
|
||||
orm_lib/src/DbClientLockFree.cc
|
||||
orm_lib/src/DbClientManager.cc
|
||||
orm_lib/src/DbConnection.cc
|
||||
orm_lib/src/Exception.cc
|
||||
orm_lib/src/Field.cc
|
||||
orm_lib/src/Result.cc
|
||||
|
@ -1,7 +1,7 @@
|
||||
/**
|
||||
*
|
||||
* DbClientManager.cc
|
||||
* An Tao
|
||||
* @file DbClientManager.cc
|
||||
* @author An Tao
|
||||
*
|
||||
* Copyright 2018, An Tao. All rights reserved.
|
||||
* https://github.com/an-tao/drogon
|
||||
@ -22,6 +22,26 @@
|
||||
using namespace drogon::orm;
|
||||
using namespace drogon;
|
||||
|
||||
inline std::string escapeConnString(const std::string &str)
|
||||
{
|
||||
bool beQuoted = str.empty() || (str.find(' ') != std::string::npos);
|
||||
|
||||
std::string escaped;
|
||||
escaped.reserve(str.size());
|
||||
for (auto ch : str)
|
||||
{
|
||||
if (ch == '\'')
|
||||
escaped.push_back('\\');
|
||||
else if (ch == '\\')
|
||||
escaped.push_back('\\');
|
||||
escaped.push_back(ch);
|
||||
}
|
||||
|
||||
if (beQuoted)
|
||||
return "'" + escaped + "'";
|
||||
return escaped;
|
||||
}
|
||||
|
||||
void DbClientManager::createDbClients(
|
||||
const std::vector<trantor::EventLoop *> &ioloops)
|
||||
{
|
||||
@ -97,22 +117,23 @@ void DbClientManager::createDbClient(const std::string &dbType,
|
||||
const bool isFast,
|
||||
const std::string &characterSet)
|
||||
{
|
||||
auto connStr = utils::formattedString("host=%s port=%u dbname=%s user=%s",
|
||||
host.c_str(),
|
||||
port,
|
||||
databaseName.c_str(),
|
||||
userName.c_str());
|
||||
auto connStr =
|
||||
utils::formattedString("host=%s port=%u dbname=%s user=%s",
|
||||
escapeConnString(host).c_str(),
|
||||
port,
|
||||
escapeConnString(databaseName).c_str(),
|
||||
escapeConnString(userName).c_str());
|
||||
if (!password.empty())
|
||||
{
|
||||
connStr += " password=";
|
||||
connStr += password;
|
||||
connStr += escapeConnString(password);
|
||||
}
|
||||
std::string type = dbType;
|
||||
std::transform(type.begin(), type.end(), type.begin(), tolower);
|
||||
if (!characterSet.empty())
|
||||
{
|
||||
connStr += " client_encoding=";
|
||||
connStr += characterSet;
|
||||
connStr += escapeConnString(characterSet);
|
||||
}
|
||||
DbInfo info;
|
||||
info.connectionInfo_ = connStr;
|
||||
|
57
orm_lib/src/DbConnection.cc
Normal file
57
orm_lib/src/DbConnection.cc
Normal file
@ -0,0 +1,57 @@
|
||||
/**
|
||||
*
|
||||
* @file DbConnection.cc
|
||||
* @author Martin Chang
|
||||
*
|
||||
* Copyright 2020, Martin Chang. All rights reserved.
|
||||
* https://github.com/an-tao/drogon
|
||||
* Use of this source code is governed by a MIT license
|
||||
* that can be found in the License file.
|
||||
*
|
||||
* Drogon
|
||||
*
|
||||
*/
|
||||
|
||||
#include "DbConnection.h"
|
||||
|
||||
#include <regex>
|
||||
|
||||
using namespace drogon::orm;
|
||||
|
||||
std::map<std::string, std::string> DbConnection::parseConnString(
|
||||
const std::string& connInfo)
|
||||
{
|
||||
const static std::regex re(
|
||||
R"((\w+) *= *('(?:[^\n]|\\[^\n])+'|(?:\S|\\\S)+))");
|
||||
std::smatch what;
|
||||
std::map<std::string, std::string> params;
|
||||
std::string str = connInfo;
|
||||
|
||||
while (std::regex_search(str, what, re))
|
||||
{
|
||||
assert(what.size() == 3);
|
||||
std::string key = what[1];
|
||||
std::string rawValue = what[2];
|
||||
std::string value;
|
||||
bool quoted =
|
||||
!rawValue.empty() && rawValue[0] == '\'' && rawValue.back() == '\'';
|
||||
|
||||
value.reserve(rawValue.size());
|
||||
for (size_t i = 0; i < rawValue.size(); i++)
|
||||
{
|
||||
if (quoted && (i == 0 || i == rawValue.size() - 1))
|
||||
continue;
|
||||
else if (rawValue[i] == '\\' && i != rawValue.size() - 1)
|
||||
{
|
||||
value.push_back(rawValue[i + 1]);
|
||||
i += 1;
|
||||
continue;
|
||||
}
|
||||
|
||||
value.push_back(rawValue[i]);
|
||||
}
|
||||
params[key] = value;
|
||||
str = what.suffix().str();
|
||||
}
|
||||
return params;
|
||||
}
|
@ -1,7 +1,7 @@
|
||||
/**
|
||||
*
|
||||
* DbConnection.h
|
||||
* An Tao
|
||||
* @file DbConnection.h
|
||||
* @author An Tao
|
||||
*
|
||||
* Copyright 2018, An Tao. All rights reserved.
|
||||
* https://github.com/an-tao/drogon
|
||||
@ -134,6 +134,9 @@ class DbConnection : public trantor::NonCopyable
|
||||
DbConnectionCallback okCallback_{[](const DbConnectionPtr &) {}};
|
||||
std::function<void(const std::exception_ptr &)> exceptionCallback_;
|
||||
bool isWorking_{false};
|
||||
|
||||
static std::map<std::string, std::string> parseConnString(
|
||||
const std::string &);
|
||||
};
|
||||
|
||||
} // namespace orm
|
||||
|
@ -1,7 +1,7 @@
|
||||
/**
|
||||
*
|
||||
* MysqlConnection.cc
|
||||
* An Tao
|
||||
* @file MysqlConnection.cc
|
||||
* @author An Tao
|
||||
*
|
||||
* Copyright 2018, An Tao. All rights reserved.
|
||||
* https://github.com/an-tao/drogon
|
||||
@ -57,20 +57,12 @@ MysqlConnection::MysqlConnection(trantor::EventLoop *loop,
|
||||
mysql_options(mysqlPtr_.get(), MYSQL_OPT_NONBLOCK, 0);
|
||||
|
||||
// Get the key and value
|
||||
std::regex r(" *= *");
|
||||
auto tmpStr = std::regex_replace(connInfo, r, "=");
|
||||
|
||||
auto keyValues = utils::splitString(tmpStr, " ");
|
||||
for (auto const &kvs : keyValues)
|
||||
auto connParams = parseConnString(connInfo);
|
||||
for (auto const &kv : connParams)
|
||||
{
|
||||
auto kv = utils::splitString(kvs, "=");
|
||||
assert(kv.size() == 2);
|
||||
auto key = kv[0];
|
||||
auto value = kv[1];
|
||||
if (value[0] == '\'' && value[value.length() - 1] == '\'')
|
||||
{
|
||||
value = value.substr(1, value.length() - 2);
|
||||
}
|
||||
auto key = kv.first;
|
||||
auto value = kv.second;
|
||||
|
||||
std::transform(key.begin(), key.end(), key.begin(), tolower);
|
||||
// LOG_TRACE << key << "=" << value;
|
||||
if (key == "host")
|
||||
|
@ -1,7 +1,7 @@
|
||||
/**
|
||||
*
|
||||
* Sqlite3Connection.cc
|
||||
* An Tao
|
||||
* @file Sqlite3Connection.cc
|
||||
* @author An Tao
|
||||
*
|
||||
* Copyright 2018, An Tao. All rights reserved.
|
||||
* https://github.com/an-tao/drogon
|
||||
@ -55,21 +55,12 @@ Sqlite3Connection::Sqlite3Connection(
|
||||
}
|
||||
});
|
||||
// Get the key and value
|
||||
std::regex r(" *= *");
|
||||
auto tmpStr = std::regex_replace(connInfo, r, "=");
|
||||
std::string host, user, passwd, dbname, port;
|
||||
auto keyValues = utils::splitString(tmpStr, " ");
|
||||
auto connParams = parseConnString(connInfo);
|
||||
std::string filename;
|
||||
for (auto const &kvs : keyValues)
|
||||
for (auto const &kv : connParams)
|
||||
{
|
||||
auto kv = utils::splitString(kvs, "=");
|
||||
assert(kv.size() == 2);
|
||||
auto key = kv[0];
|
||||
auto value = kv[1];
|
||||
if (value[0] == '\'' && value[value.length() - 1] == '\'')
|
||||
{
|
||||
value = value.substr(1, value.length() - 2);
|
||||
}
|
||||
auto key = kv.first;
|
||||
auto value = kv.second;
|
||||
std::transform(key.begin(), key.end(), key.begin(), tolower);
|
||||
if (key == "filename")
|
||||
{
|
||||
|
Loading…
Reference in New Issue
Block a user