Skip to content

Commit cf42232

Browse files
committed
功能增强:DuckDB 配置参数灵活化支持
1 parent 2db43f4 commit cf42232

File tree

13 files changed

+477
-31
lines changed

13 files changed

+477
-31
lines changed

.gitignore

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -31,6 +31,7 @@
3131
*.out
3232
*.app
3333

34+
trantor/
3435
build/
3536
cmake-build-debug/
3637
cmake-build-debug-visual-studio/

lib/src/ConfigLoader.cc

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -572,6 +572,19 @@ static void loadDbClients(const Json::Value &dbClients)
572572
auto autoBatch = client.get("auto_batch", false).asBool();
573573

574574
std::unordered_map<std::string, std::string> options;
575+
// DuckDB使用config_options字段名(若存在则优先使用)[dq 2025-11-19]
576+
if (type == "duckdb")
577+
{
578+
auto configOptions = client.get("config_options", Json::Value());
579+
if (configOptions.isObject() && !configOptions.empty())
580+
{
581+
for (const auto &key : configOptions.getMemberNames())
582+
{
583+
options[key] = configOptions[key].asString();
584+
}
585+
}
586+
}
587+
// PostgreSQL等使用connect_options
575588
if (connectOptions.isObject() && !connectOptions.empty())
576589
{
577590
for (const auto &key : connectOptions.getMemberNames())

lib/src/HttpAppFrameworkImpl.cc

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1002,7 +1002,8 @@ void HttpAppFrameworkImpl::addDbClient(
10021002
}
10031003
else if (dbType == "duckdb")
10041004
{
1005-
addDbClient(orm::DuckdbConfig{connectionNum, filename, name, timeout});
1005+
// 传递配置选项到DuckdbConfig [dq 2025-11-19]
1006+
addDbClient(orm::DuckdbConfig{connectionNum, filename, name, timeout, std::move(options)});
10061007
}
10071008
else
10081009
{

orm_lib/inc/drogon/orm/DbClient.h

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -132,6 +132,12 @@ class DROGON_EXPORT DbClient : public trantor::NonCopyable
132132
const std::string &connInfo,
133133
size_t connNum);
134134

135+
// DuckDB with config options support [dq 2025-11-19]
136+
static std::shared_ptr<DbClient> newDuckDbClient(
137+
const std::string &connInfo,
138+
size_t connNum,
139+
const std::unordered_map<std::string, std::string> &configOptions);
140+
135141
/// Async and nonblocking method
136142
/**
137143
* @param sql is the SQL statement to be executed;

orm_lib/inc/drogon/orm/DbConfig.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -65,6 +65,7 @@ struct DuckdbConfig
6565
std::string filename;
6666
std::string name;
6767
double timeout;
68+
std::unordered_map<std::string, std::string> configOptions; // DuckDB配置选项 [dq 2025-11-19]
6869
};
6970

7071
using DbConfig = std::variant<PostgresConfig, MysqlConfig, Sqlite3Config, DuckdbConfig>;

orm_lib/src/DbClient.cc

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -119,3 +119,25 @@ std::shared_ptr<DbClient> DbClient::newDuckDbClient(const std::string &connInfo,
119119
(void)(connNum);
120120
#endif
121121
}
122+
123+
// DuckDB with config options support [dq 2025-11-19]
124+
std::shared_ptr<DbClient> DbClient::newDuckDbClient(
125+
const std::string &connInfo,
126+
size_t connNum,
127+
const std::unordered_map<std::string, std::string> &configOptions)
128+
{
129+
#if USE_DUCKDB
130+
auto client = std::make_shared<DbClientImpl>(connInfo,
131+
connNum,
132+
ClientType::DuckDB,
133+
configOptions);
134+
client->init();
135+
return client;
136+
#else
137+
LOG_FATAL << "DuckDB is not supported!";
138+
exit(1);
139+
(void)(connInfo);
140+
(void)(connNum);
141+
(void)(configOptions);
142+
#endif
143+
}

orm_lib/src/DbClientImpl.cc

Lines changed: 25 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -75,6 +75,29 @@ DbClientImpl::DbClientImpl(const std::string &connInfo,
7575
assert(connNum > 0);
7676
}
7777

78+
// DuckDB配置构造函数实现 [dq 2025-11-19]
79+
DbClientImpl::DbClientImpl(const std::string &connInfo,
80+
size_t connNum,
81+
ClientType type,
82+
const std::unordered_map<std::string, std::string> &configOptions)
83+
: numberOfConnections_(connNum),
84+
#if LIBPQ_SUPPORTS_BATCH_MODE
85+
autoBatch_(false),
86+
#endif
87+
configOptions_(configOptions), // 存储配置选项
88+
loops_(type == ClientType::Sqlite3 || type == ClientType::DuckDB
89+
? 1
90+
: (connNum < std::thread::hardware_concurrency()
91+
? connNum
92+
: std::thread::hardware_concurrency()),
93+
"DbLoop")
94+
{
95+
type_ = type;
96+
connectionInfo_ = connInfo;
97+
LOG_TRACE << "type=" << (int)type;
98+
assert(connNum > 0);
99+
}
100+
78101
void DbClientImpl::init()
79102
{
80103
// LOG_DEBUG << loops_.getLoopNum();
@@ -434,7 +457,8 @@ DbConnectionPtr DbClientImpl::newConnection(trantor::EventLoop *loop)
434457
#if USE_DUCKDB
435458
connPtr = std::make_shared<DuckdbConnection>(loop,
436459
connectionInfo_,
437-
sharedMutexPtr_);
460+
sharedMutexPtr_,
461+
configOptions_); // 传递配置选项 [dq 2025-11-19]
438462
#else
439463
return nullptr;
440464
#endif

orm_lib/src/DbClientImpl.h

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -40,6 +40,12 @@ class DbClientImpl : public DbClient,
4040
#else
4141
ClientType type);
4242
#endif
43+
// DuckDB配置构造函数 [dq 2025-11-19]
44+
DbClientImpl(const std::string &connInfo,
45+
size_t connNum,
46+
ClientType type,
47+
const std::unordered_map<std::string, std::string> &configOptions);
48+
4349
~DbClientImpl() noexcept override;
4450
void execSql(const char *sql,
4551
size_t sqlLength,
@@ -74,6 +80,7 @@ class DbClientImpl : public DbClient,
7480
#if LIBPQ_SUPPORTS_BATCH_MODE
7581
bool autoBatch_{false};
7682
#endif
83+
std::unordered_map<std::string, std::string> configOptions_; // DuckDB配置选项 [dq 2025-11-19]
7784
DbConnectionPtr newConnection(trantor::EventLoop *loop);
7885

7986
void makeTrans(

orm_lib/src/DbClientManager.cc

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -144,9 +144,11 @@ void DbClientManager::createDbClients(
144144
else if (std::holds_alternative<DuckdbConfig>(dbInfo.config_))
145145
{
146146
auto &cfg = std::get<DuckdbConfig>(dbInfo.config_);
147+
// 使用带配置选项的工厂方法 [dq 2025-11-19]
147148
dbClientsMap_[cfg.name] =
148149
drogon::orm::DbClient::newDuckDbClient(dbInfo.connectionInfo_,
149-
cfg.connectionNumber);
150+
cfg.connectionNumber,
151+
cfg.configOptions); // 传递配置选项
150152
if (cfg.timeout > 0.0)
151153
{
152154
dbClientsMap_[cfg.name]->setTimeout(cfg.timeout);

orm_lib/src/duckdb_impl/DuckdbConnection.cc

Lines changed: 46 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -44,8 +44,12 @@ void DuckdbConnection::onError(
4444
DuckdbConnection::DuckdbConnection(
4545
trantor::EventLoop *loop,
4646
const std::string &connInfo,
47-
const std::shared_ptr<SharedMutex> &sharedMutex)
48-
: DbConnection(loop), sharedMutexPtr_(sharedMutex), connInfo_(connInfo)
47+
const std::shared_ptr<SharedMutex> &sharedMutex,
48+
const std::unordered_map<std::string, std::string> &configOptions) // 新增配置参数支持 [dq 2025-11-19]
49+
: DbConnection(loop),
50+
sharedMutexPtr_(sharedMutex),
51+
connInfo_(connInfo),
52+
configOptions_(configOptions) // 存储配置选项 [dq 2025-11-19]
4953
{
5054
}
5155

@@ -74,17 +78,56 @@ void DuckdbConnection::init()
7478

7579
loop_->runInLoop([this, filename = std::move(filename)]() {
7680
duckdb_database db;
81+
duckdb_config config;
7782
duckdb_connection conn;
7883

84+
// create the configuration object
85+
if (duckdb_create_config(&config) == DuckDBError) {
86+
LOG_FATAL << "Failed to config DuckDB database: " << filename;
87+
auto thisPtr = shared_from_this();
88+
closeCallback_(thisPtr);
89+
return;
90+
}
91+
92+
// 应用配置选项(使用传入的配置,或使用默认值)[dq 2025-11-19]
93+
// 定义默认值
94+
std::unordered_map<std::string, std::string> defaultConfig = {
95+
{"access_mode", "READ_WRITE"},
96+
{"threads", "4"}, // 默认改为4以避免过度占用资源
97+
{"max_memory", "4GB"},
98+
};
99+
100+
// 合并用户配置和默认配置(用户配置优先)
101+
for (const auto& [key, defaultValue] : defaultConfig) {
102+
auto it = configOptions_.find(key);
103+
const std::string& value = (it != configOptions_.end()) ? it->second : defaultValue;
104+
105+
if (duckdb_set_config(config, key.c_str(), value.c_str()) == DuckDBError) {
106+
LOG_WARN << "Failed to set DuckDB config option: " << key << "=" << value;
107+
}
108+
}
109+
110+
// 应用其他用户自定义的配置选项
111+
for (const auto& [key, value] : configOptions_) {
112+
if (defaultConfig.find(key) == defaultConfig.end()) {
113+
if (duckdb_set_config(config, key.c_str(), value.c_str()) == DuckDBError) {
114+
LOG_WARN << "Failed to set DuckDB config option: " << key << "=" << value;
115+
}
116+
}
117+
}
118+
79119
// 打开数据库
80-
auto state = duckdb_open(filename.c_str(), &db);
120+
//auto state = duckdb_open(filename.c_str(), &db);
121+
auto state = duckdb_open_ext(filename.c_str(), &db, config, NULL);
81122
if (state == DuckDBError)
82123
{
83124
LOG_FATAL << "Failed to open DuckDB database: " << filename;
125+
duckdb_destroy_config(&config);
84126
auto thisPtr = shared_from_this();
85127
closeCallback_(thisPtr);
86128
return;
87129
}
130+
duckdb_destroy_config(&config);
88131

89132
// 创建连接
90133
state = duckdb_connect(db, &conn);

0 commit comments

Comments
 (0)