From 7756deee83fad1f6332564446deef51c1ad4b17d Mon Sep 17 00:00:00 2001 From: "He, Wanchen" Date: Sat, 7 May 2022 20:55:56 +0800 Subject: [PATCH 01/11] Support setting result format. --- orm_lib/inc/drogon/orm/DbClient.h | 1 + orm_lib/inc/drogon/orm/SqlBinder.h | 22 +++++ orm_lib/src/DbClientImpl.cc | 21 +++-- orm_lib/src/DbClientImpl.h | 2 + orm_lib/src/DbClientLockFree.cc | 33 ++++++-- orm_lib/src/DbClientLockFree.h | 2 + orm_lib/src/DbConnection.h | 8 +- orm_lib/src/SqlBinder.cc | 2 + orm_lib/src/TransactionImpl.cc | 81 +++++++++++-------- orm_lib/src/TransactionImpl.h | 9 ++- orm_lib/src/mysql_impl/MysqlConnection.h | 18 +++-- orm_lib/src/postgresql_impl/PgConnection.cc | 35 +++++++- orm_lib/src/postgresql_impl/PgConnection.h | 64 ++++++++------- orm_lib/src/sqlite3_impl/Sqlite3Connection.cc | 4 +- orm_lib/src/sqlite3_impl/Sqlite3Connection.h | 18 +++-- 15 files changed, 226 insertions(+), 94 deletions(-) diff --git a/orm_lib/inc/drogon/orm/DbClient.h b/orm_lib/inc/drogon/orm/DbClient.h index 89b3f12390..f2a8290ada 100644 --- a/orm_lib/inc/drogon/orm/DbClient.h +++ b/orm_lib/inc/drogon/orm/DbClient.h @@ -350,6 +350,7 @@ class DROGON_EXPORT DbClient : public trantor::NonCopyable std::vector &¶meters, std::vector &&length, std::vector &&format, + int resultFormat, ResultCallback &&rcb, std::function &&exceptCallback) = 0; diff --git a/orm_lib/inc/drogon/orm/SqlBinder.h b/orm_lib/inc/drogon/orm/SqlBinder.h index 3335e6ffbd..455ee37cfa 100644 --- a/orm_lib/inc/drogon/orm/SqlBinder.h +++ b/orm_lib/inc/drogon/orm/SqlBinder.h @@ -115,6 +115,11 @@ enum class Mode NonBlocking, Blocking }; +enum class ResultFormat +{ + Text = 0, + Binary = 1 +}; namespace internal { @@ -511,6 +516,22 @@ class DROGON_EXPORT SqlBinder : public trantor::NonCopyable return *this; } + self &operator<<(const ResultFormat &resultFormat) + { + resultFormat_ = resultFormat; + return *this; + } + self &operator<<(ResultFormat &resultFormat) + { + resultFormat_ = resultFormat; + return *this; + } + self &operator<<(ResultFormat &&resultFormat) + { + resultFormat_ = resultFormat; + return *this; + } + template self &operator<<(const std::optional ¶meter) { @@ -592,6 +613,7 @@ class DROGON_EXPORT SqlBinder : public trantor::NonCopyable std::vector formats_; std::vector> objs_; Mode mode_{Mode::NonBlocking}; + ResultFormat resultFormat_{ResultFormat::Text}; std::shared_ptr callbackHolder_; DrogonDbExceptionCallback exceptionCallback_; ExceptPtrCallback exceptionPtrCallback_; diff --git a/orm_lib/src/DbClientImpl.cc b/orm_lib/src/DbClientImpl.cc index 730c7c75fc..2679f94fac 100644 --- a/orm_lib/src/DbClientImpl.cc +++ b/orm_lib/src/DbClientImpl.cc @@ -123,6 +123,7 @@ void DbClientImpl::execSql( std::vector &¶meters, std::vector &&length, std::vector &&format, + int resultFormat, ResultCallback &&rcb, std::function &&exceptCallback) { @@ -138,6 +139,7 @@ void DbClientImpl::execSql( std::move(parameters), std::move(length), std::move(format), + resultFormat, std::move(rcb), std::move(exceptCallback)); return; @@ -147,7 +149,7 @@ void DbClientImpl::execSql( { std::lock_guard guard(connectionsMutex_); - if (readyConnections_.size() == 0) + if (readyConnections_.empty()) { if (sqlCmdBuffer_.size() > 200000) { @@ -163,6 +165,7 @@ void DbClientImpl::execSql( std::move(parameters), std::move(length), std::move(format), + resultFormat, std::move(rcb), std::move(exceptCallback)); sqlCmdBuffer_.push_back(std::move(cmd)); @@ -183,8 +186,10 @@ void DbClientImpl::execSql( std::move(parameters), std::move(length), std::move(format), + resultFormat, std::move(rcb), - std::move(exceptCallback)); + std::move(exceptCallback), + true); return; } if (busy) @@ -368,8 +373,10 @@ void DbClientImpl::handleNewTask(const DbConnectionPtr &connPtr) std::move(cmd->parameters_), std::move(cmd->lengths_), std::move(cmd->formats_), + cmd->resultFormat_, std::move(cmd->callback_), - std::move(cmd->exceptionCallback_)); + std::move(cmd->exceptionCallback_), + true); return; } } @@ -487,6 +494,7 @@ void DbClientImpl::execSqlWithTimeout( std::vector &¶meters, std::vector &&length, std::vector &&format, + int resultFormat, ResultCallback &&rcb, std::function &&ecb) { @@ -536,7 +544,7 @@ void DbClientImpl::execSqlWithTimeout( { std::lock_guard guard(connectionsMutex_); - if (readyConnections_.size() == 0) + if (readyConnections_.empty()) { if (sqlCmdBuffer_.size() > 200000) { @@ -552,6 +560,7 @@ void DbClientImpl::execSqlWithTimeout( std::move(parameters), std::move(length), std::move(format), + resultFormat, std::move(resultCallback), std::move(exceptionCallback)); sqlCmdBuffer_.emplace_back(command); @@ -573,8 +582,10 @@ void DbClientImpl::execSqlWithTimeout( std::move(parameters), std::move(length), std::move(format), + resultFormat, std::move(resultCallback), - std::move(exceptionCallback)); + std::move(exceptionCallback), + true); timeoutFlagPtr->runTimer(); return; } diff --git a/orm_lib/src/DbClientImpl.h b/orm_lib/src/DbClientImpl.h index 09ad0c994d..4f99d9b69f 100644 --- a/orm_lib/src/DbClientImpl.h +++ b/orm_lib/src/DbClientImpl.h @@ -47,6 +47,7 @@ class DbClientImpl : public DbClient, std::vector &¶meters, std::vector &&length, std::vector &&format, + int resultFormat, ResultCallback &&rcb, std::function &&exceptCallback) override; @@ -99,6 +100,7 @@ class DbClientImpl : public DbClient, std::vector &¶meters, std::vector &&length, std::vector &&format, + int resultFormat, ResultCallback &&rcb, std::function &&exceptCallback); }; diff --git a/orm_lib/src/DbClientLockFree.cc b/orm_lib/src/DbClientLockFree.cc index de0d248462..b62cae6917 100644 --- a/orm_lib/src/DbClientLockFree.cc +++ b/orm_lib/src/DbClientLockFree.cc @@ -93,6 +93,7 @@ void DbClientLockFree::execSql( std::vector &¶meters, std::vector &&length, std::vector &&format, + int resultFormat, ResultCallback &&rcb, std::function &&exceptCallback) { @@ -109,6 +110,7 @@ void DbClientLockFree::execSql( std::move(parameters), std::move(length), std::move(format), + resultFormat, std::move(rcb), std::move(exceptCallback)); return; @@ -128,6 +130,7 @@ void DbClientLockFree::execSql( std::move(parameters), std::move(length), std::move(format), + resultFormat, [rcb = std::move(rcb), this](const Result &r) { if (sqlCmdBuffer_.empty()) { @@ -139,7 +142,8 @@ void DbClientLockFree::execSql( [rcb = std::move(rcb), r]() { rcb(r); }); } }, - std::move(exceptCallback)); + std::move(exceptCallback), + true); return; } } @@ -158,6 +162,7 @@ void DbClientLockFree::execSql( std::move(parameters), std::move(length), std::move(format), + resultFormat, [rcb = std::move(rcb), this](const Result &r) { if (sqlCmdBuffer_.empty()) { @@ -169,7 +174,8 @@ void DbClientLockFree::execSql( [rcb = std::move(rcb), r]() { rcb(r); }); } }, - std::move(exceptCallback)); + std::move(exceptCallback), + true); return; } } @@ -190,8 +196,10 @@ void DbClientLockFree::execSql( std::move(parameters), std::move(length), std::move(format), + resultFormat, std::move(rcb), - std::move(exceptCallback)); + std::move(exceptCallback), + true); return; } } @@ -216,6 +224,7 @@ void DbClientLockFree::execSql( std::move(parameters), std::move(length), std::move(format), + resultFormat, [rcb = std::move(rcb), this](const Result &r) { if (sqlCmdBuffer_.empty()) { @@ -396,8 +405,10 @@ void DbClientLockFree::handleNewTask(const DbConnectionPtr &conn) std::move(cmd->parameters_), std::move(cmd->lengths_), std::move(cmd->formats_), + cmd->resultFormat_, std::move(cmd->callback_), - std::move(cmd->exceptionCallback_)); + std::move(cmd->exceptionCallback_), + true); #endif return; } @@ -501,6 +512,7 @@ void DbClientLockFree::execSqlWithTimeout( std::vector &¶meters, std::vector &&length, std::vector &&format, + int resultFormat, ResultCallback &&rcb, std::function &&ecb) { @@ -557,6 +569,7 @@ void DbClientLockFree::execSqlWithTimeout( std::move(parameters), std::move(length), std::move(format), + resultFormat, [resultCallback = std::move(resultCallback), this](const Result &r) { if (sqlCmdBuffer_.empty()) @@ -570,7 +583,8 @@ void DbClientLockFree::execSqlWithTimeout( r]() { resultCallback(r); }); } }, - std::move(exceptionCallback)); + std::move(exceptionCallback), + true); timeoutFlagPtr->runTimer(); return; } @@ -590,6 +604,7 @@ void DbClientLockFree::execSqlWithTimeout( std::move(parameters), std::move(length), std::move(format), + resultFormat, [resultCallback = std::move(resultCallback), this](const Result &r) { if (sqlCmdBuffer_.empty()) @@ -603,7 +618,8 @@ void DbClientLockFree::execSqlWithTimeout( r]() { resultCallback(r); }); } }, - std::move(exceptionCallback)); + std::move(exceptionCallback), + true); timeoutFlagPtr->runTimer(); return; } @@ -625,8 +641,10 @@ void DbClientLockFree::execSqlWithTimeout( std::move(parameters), std::move(length), std::move(format), + resultFormat, std::move(resultCallback), - std::move(exceptionCallback)); + std::move(exceptionCallback), + true); timeoutFlagPtr->runTimer(); return; } @@ -651,6 +669,7 @@ void DbClientLockFree::execSqlWithTimeout( std::move(parameters), std::move(length), std::move(format), + resultFormat, [resultCallback = std::move(resultCallback), this](const Result &r) { if (sqlCmdBuffer_.empty()) { diff --git a/orm_lib/src/DbClientLockFree.h b/orm_lib/src/DbClientLockFree.h index 1e2e4d715c..97ee57708c 100644 --- a/orm_lib/src/DbClientLockFree.h +++ b/orm_lib/src/DbClientLockFree.h @@ -50,6 +50,7 @@ class DbClientLockFree : public DbClient, std::vector &¶meters, std::vector &&length, std::vector &&format, + int resultFormat, ResultCallback &&rcb, std::function &&exceptCallback) override; @@ -94,6 +95,7 @@ class DbClientLockFree : public DbClient, std::vector &¶meters, std::vector &&length, std::vector &&format, + int resultFormat, ResultCallback &&rcb, std::function &&ecb); void handleNewTask(const DbConnectionPtr &conn); diff --git a/orm_lib/src/DbConnection.h b/orm_lib/src/DbConnection.h index c49838a2a0..4b418ad720 100644 --- a/orm_lib/src/DbConnection.h +++ b/orm_lib/src/DbConnection.h @@ -52,6 +52,7 @@ struct SqlCmd std::vector parameters_; std::vector lengths_; std::vector formats_; + int resultFormat_{0}; QueryCallback callback_; ExceptPtrCallback exceptionCallback_; std::string preparingStatement_; @@ -63,6 +64,7 @@ struct SqlCmd std::vector &¶meters, std::vector &&length, std::vector &&format, + int resultFormat, QueryCallback &&cb, ExceptPtrCallback &&exceptCb) : sql_(std::move(sql)), @@ -70,6 +72,7 @@ struct SqlCmd parameters_(std::move(parameters)), lengths_(std::move(length)), formats_(std::move(format)), + resultFormat_(resultFormat), callback_(std::move(cb)), exceptionCallback_(std::move(exceptCb)) { @@ -111,8 +114,11 @@ class DbConnection : public trantor::NonCopyable std::vector &¶meters, std::vector &&length, std::vector &&format, + int resultFormat, ResultCallback &&rcb, - std::function &&exceptCallback) = 0; + std::function &&exceptCallback, + bool usePreparedStmt) = 0; + virtual void batchSql( std::deque> &&sqlCommands) = 0; diff --git a/orm_lib/src/SqlBinder.cc b/orm_lib/src/SqlBinder.cc index b93a2bd716..b62568321c 100644 --- a/orm_lib/src/SqlBinder.cc +++ b/orm_lib/src/SqlBinder.cc @@ -39,6 +39,7 @@ void SqlBinder::exec() std::move(parameters_), std::move(lengths_), std::move(formats_), + (int)resultFormat_, [holder = std::move(callbackHolder_), objs = std::move(objs_), sqlptr = std::move(sqlPtr_)](const Result &r) mutable { @@ -87,6 +88,7 @@ void SqlBinder::exec() std::move(parameters_), std::move(lengths_), std::move(formats_), + (int)resultFormat_, [pro](const Result &r) { pro->set_value(r); }, [pro](const std::exception_ptr &exception) { try diff --git a/orm_lib/src/TransactionImpl.cc b/orm_lib/src/TransactionImpl.cc index 0f55142400..59a47c6096 100644 --- a/orm_lib/src/TransactionImpl.cc +++ b/orm_lib/src/TransactionImpl.cc @@ -52,6 +52,7 @@ TransactionImpl::~TransactionImpl() {}, {}, {}, + 0, [commitCb](const Result &) { LOG_TRACE << "Transaction committed!"; if (commitCb) @@ -73,7 +74,8 @@ TransactionImpl::~TransactionImpl() commitCb(false); } } - }); + }, + true); }); } else @@ -91,6 +93,7 @@ void TransactionImpl::execSqlInLoop( std::vector &¶meters, std::vector &&length, std::vector &&format, + int resultFormat, ResultCallback &&rcb, std::function &&exceptCallback) { @@ -104,6 +107,7 @@ void TransactionImpl::execSqlInLoop( std::move(parameters), std::move(length), std::move(format), + resultFormat, std::move(rcb), std::move(exceptCallback)); return; @@ -113,18 +117,20 @@ void TransactionImpl::execSqlInLoop( { isWorking_ = true; thisPtr_ = thisPtr; - connectionPtr_->execSql(std::move(sql), - paraNum, - std::move(parameters), - std::move(length), - std::move(format), - std::move(rcb), - [exceptCallback, - thisPtr](const std::exception_ptr &ePtr) { - thisPtr->rollback(); - if (exceptCallback) - exceptCallback(ePtr); - }); + connectionPtr_->execSql( + std::move(sql), + paraNum, + std::move(parameters), + std::move(length), + std::move(format), + resultFormat, + std::move(rcb), + [exceptCallback, thisPtr](const std::exception_ptr &ePtr) { + thisPtr->rollback(); + if (exceptCallback) + exceptCallback(ePtr); + }, + true); } else { @@ -135,6 +141,7 @@ void TransactionImpl::execSqlInLoop( cmdPtr->parameters_ = std::move(parameters); cmdPtr->lengths_ = std::move(length); cmdPtr->formats_ = std::move(format); + cmdPtr->resultFormat_ = resultFormat; cmdPtr->callback_ = std::move(rcb); cmdPtr->exceptionCallback_ = std::move(exceptCallback); cmdPtr->thisPtr_ = thisPtr; @@ -186,6 +193,7 @@ void TransactionImpl::rollback() {}, {}, {}, + 0, [thisPtr](const Result &) { LOG_TRACE << "Transaction roll back!"; thisPtr->isCommitedOrRolledback_ = true; @@ -195,7 +203,8 @@ void TransactionImpl::rollback() // clearupCb(); LOG_ERROR << "Transaction roll back error"; thisPtr->isCommitedOrRolledback_ = true; - }); + }, + true); }); } @@ -218,6 +227,7 @@ void TransactionImpl::execNewTask() std::move(cmd->parameters_), std::move(cmd->lengths_), std::move(cmd->formats_), + cmd->resultFormat_, [callback = std::move(cmd->callback_), cmd, thisPtr]( const Result &r) { if (cmd->isRollbackCmd_) @@ -236,7 +246,8 @@ void TransactionImpl::execNewTask() } if (cmd->exceptionCallback_) cmd->exceptionCallback_(ePtr); - }); + }, + true); return; } isWorking_ = false; @@ -285,11 +296,13 @@ void TransactionImpl::doBegin() {}, {}, {}, + 0, [](const Result &) { LOG_TRACE << "Transaction begin!"; }, [thisPtr](const std::exception_ptr &) { LOG_ERROR << "Error occurred in transaction begin"; thisPtr->isCommitedOrRolledback_ = true; - }); + }, + true); }); } @@ -299,6 +312,7 @@ void TransactionImpl::execSqlInLoopWithTimeout( std::vector &¶meters, std::vector &&length, std::vector &&format, + int resultFormat, ResultCallback &&rcb, std::function &&ecb) { @@ -346,22 +360,24 @@ void TransactionImpl::execSqlInLoopWithTimeout( { isWorking_ = true; thisPtr_ = thisPtr; - connectionPtr_->execSql(std::move(sql), - paraNum, - std::move(parameters), - std::move(length), - std::move(format), - std::move(resultCallback), - [ecpPtr, timeoutFlagPtr, thisPtr]( - const std::exception_ptr &ePtr) { - thisPtr->rollback(); - if (timeoutFlagPtr->done()) - return; - if (*ecpPtr) - { - (*ecpPtr)(ePtr); - } - }); + connectionPtr_->execSql( + std::move(sql), + paraNum, + std::move(parameters), + std::move(length), + std::move(format), + resultFormat, + std::move(resultCallback), + [ecpPtr, timeoutFlagPtr, thisPtr](const std::exception_ptr &ePtr) { + thisPtr->rollback(); + if (timeoutFlagPtr->done()) + return; + if (*ecpPtr) + { + (*ecpPtr)(ePtr); + } + }, + true); } else { @@ -372,6 +388,7 @@ void TransactionImpl::execSqlInLoopWithTimeout( cmdPtr->parameters_ = std::move(parameters); cmdPtr->lengths_ = std::move(length); cmdPtr->formats_ = std::move(format); + cmdPtr->resultFormat_ = resultFormat; cmdPtr->callback_ = std::move(resultCallback); cmdPtr->exceptionCallback_ = [ecpPtr, timeoutFlagPtr](const std::exception_ptr &ePtr) { diff --git a/orm_lib/src/TransactionImpl.h b/orm_lib/src/TransactionImpl.h index 0be310f5c0..0ea1d51d22 100644 --- a/orm_lib/src/TransactionImpl.h +++ b/orm_lib/src/TransactionImpl.h @@ -59,6 +59,7 @@ class TransactionImpl : public Transaction, std::vector &¶meters, std::vector &&length, std::vector &&format, + int resultFormat, ResultCallback &&rcb, std::function &&exceptCallback) override @@ -70,6 +71,7 @@ class TransactionImpl : public Transaction, std::move(parameters), std::move(length), std::move(format), + resultFormat, std::move(rcb), std::move(exceptCallback)); } @@ -82,6 +84,7 @@ class TransactionImpl : public Transaction, parameters = std::move(parameters), length = std::move(length), format = std::move(format), + resultFormat, rcb = std::move(rcb), exceptCallback = std::move(exceptCallback)]() mutable { thisPtr->execSqlInLoop(std::move(sql), @@ -89,6 +92,7 @@ class TransactionImpl : public Transaction, std::move(parameters), std::move(length), std::move(format), + resultFormat, std::move(rcb), std::move(exceptCallback)); }); @@ -101,6 +105,7 @@ class TransactionImpl : public Transaction, std::vector &¶meters, std::vector &&length, std::vector &&format, + int resultFormat, ResultCallback &&rcb, std::function &&exceptCallback); void execSqlInLoopWithTimeout( @@ -109,6 +114,7 @@ class TransactionImpl : public Transaction, std::vector &¶meters, std::vector &&length, std::vector &&format, + int resultFormat, ResultCallback &&rcb, std::function &&exceptCallback); @@ -133,10 +139,11 @@ class TransactionImpl : public Transaction, struct SqlCmd { std::string_view sql_; - size_t parametersNumber_; + size_t parametersNumber_{0}; std::vector parameters_; std::vector lengths_; std::vector formats_; + int resultFormat_{0}; QueryCallback callback_; ExceptPtrCallback exceptionCallback_; bool isRollbackCmd_{false}; diff --git a/orm_lib/src/mysql_impl/MysqlConnection.h b/orm_lib/src/mysql_impl/MysqlConnection.h index 4ec0c618a8..51ba5a504f 100644 --- a/orm_lib/src/mysql_impl/MysqlConnection.h +++ b/orm_lib/src/mysql_impl/MysqlConnection.h @@ -44,14 +44,16 @@ class MysqlConnection : public DbConnection, { } - void execSql(std::string_view &&sql, - size_t paraNum, - std::vector &¶meters, - std::vector &&length, - std::vector &&format, - ResultCallback &&rcb, - std::function - &&exceptCallback) override + void execSql( + std::string_view &&sql, + size_t paraNum, + std::vector &¶meters, + std::vector &&length, + std::vector &&format, + int /* resultFormat */, + ResultCallback &&rcb, + std::function &&exceptCallback, + bool /* usePreparedStmt */) override { if (loop_->isInLoopThread()) { diff --git a/orm_lib/src/postgresql_impl/PgConnection.cc b/orm_lib/src/postgresql_impl/PgConnection.cc index 59d080cc71..a32e5dbc3e 100644 --- a/orm_lib/src/postgresql_impl/PgConnection.cc +++ b/orm_lib/src/postgresql_impl/PgConnection.cc @@ -203,7 +203,9 @@ void PgConnection::execSqlInLoop( std::vector &&length, std::vector &&format, ResultCallback &&rcb, - std::function &&exceptCallback) + std::function &&exceptCallback, + int resultFormat, + bool usePreparedStmt) { LOG_TRACE << sql; loop_->assertInLoopThread(); @@ -236,7 +238,7 @@ void PgConnection::execSqlInLoop( } flush(); } - else + else if (usePreparedStmt) { auto iter = preparedStatementsMap_.find(sql_); if (iter != preparedStatementsMap_.end()) @@ -248,7 +250,7 @@ void PgConnection::execSqlInLoop( parameters.data(), length.data(), format.data(), - 0) == 0) + resultFormat) == 0) { LOG_ERROR << "send query error: " << PQerrorMessage(connectionPtr_.get()); @@ -288,6 +290,31 @@ void PgConnection::execSqlInLoop( parameters_ = std::move(parameters); lengths_ = std::move(length); formats_ = std::move(format); + resultFormat_ = resultFormat; + } + flush(); + } + else + { + if (PQsendQueryParams(connectionPtr_.get(), + sql_.data(), + static_cast(paraNum), + nullptr, + parameters.data(), + length.data(), + format.data(), + resultFormat) == 0) + { + LOG_ERROR << "send query error: " + << PQerrorMessage(connectionPtr_.get()); + if (isWorking_) + { + isWorking_ = false; + handleFatalError(); + callback_ = nullptr; + idleCb_(); + } + return; } flush(); } @@ -380,7 +407,7 @@ void PgConnection::doAfterPreparing() parameters_.data(), lengths_.data(), formats_.data(), - 0) == 0) + resultFormat_) == 0) { LOG_ERROR << "send query error: " << PQerrorMessage(connectionPtr_.get()); diff --git a/orm_lib/src/postgresql_impl/PgConnection.h b/orm_lib/src/postgresql_impl/PgConnection.h index b962ec297e..b15960275a 100644 --- a/orm_lib/src/postgresql_impl/PgConnection.h +++ b/orm_lib/src/postgresql_impl/PgConnection.h @@ -47,14 +47,16 @@ class PgConnection : public DbConnection, void init() override; - void execSql(std::string_view &&sql, - size_t paraNum, - std::vector &¶meters, - std::vector &&length, - std::vector &&format, - ResultCallback &&rcb, - std::function - &&exceptCallback) override + void execSql( + std::string_view &&sql, + size_t paraNum, + std::vector &¶meters, + std::vector &&length, + std::vector &&format, + int resultFormat, + ResultCallback &&rcb, + std::function &&exceptCallback, + bool usePreparedStmt) override { if (loop_->isInLoopThread()) { @@ -64,28 +66,33 @@ class PgConnection : public DbConnection, std::move(length), std::move(format), std::move(rcb), - std::move(exceptCallback)); + std::move(exceptCallback), + resultFormat, + usePreparedStmt); } else { auto thisPtr = shared_from_this(); - loop_->queueInLoop( - [thisPtr, - sql = std::move(sql), - paraNum, - parameters = std::move(parameters), - length = std::move(length), - format = std::move(format), - rcb = std::move(rcb), - exceptCallback = std::move(exceptCallback)]() mutable { - thisPtr->execSqlInLoop(std::move(sql), - paraNum, - std::move(parameters), - std::move(length), - std::move(format), - std::move(rcb), - std::move(exceptCallback)); - }); + loop_->queueInLoop([thisPtr, + sql = std::move(sql), + paraNum, + parameters = std::move(parameters), + length = std::move(length), + format = std::move(format), + rcb = std::move(rcb), + exceptCallback = std::move(exceptCallback), + resultFormat, + usePreparedStmt]() mutable { + thisPtr->execSqlInLoop(std::move(sql), + paraNum, + std::move(parameters), + std::move(length), + std::move(format), + std::move(rcb), + std::move(exceptCallback), + resultFormat, + usePreparedStmt); + }); } } @@ -126,13 +133,16 @@ class PgConnection : public DbConnection, std::vector &&length, std::vector &&format, ResultCallback &&rcb, - std::function &&exceptCallback); + std::function &&exceptCallback, + int resultFormat = 0, + bool usePreparedStmt = true); void doAfterPreparing(); std::string statementName_; int parametersNumber_{0}; std::vector parameters_; std::vector lengths_; std::vector formats_; + int resultFormat_{0}; int flush(); void handleFatalError(); std::set preparedStatements_; diff --git a/orm_lib/src/sqlite3_impl/Sqlite3Connection.cc b/orm_lib/src/sqlite3_impl/Sqlite3Connection.cc index 8ad70c7474..1cf410b503 100644 --- a/orm_lib/src/sqlite3_impl/Sqlite3Connection.cc +++ b/orm_lib/src/sqlite3_impl/Sqlite3Connection.cc @@ -96,8 +96,10 @@ void Sqlite3Connection::execSql( std::vector &¶meters, std::vector &&length, std::vector &&format, + int /* resultFormat */, ResultCallback &&rcb, - std::function &&exceptCallback) + std::function &&exceptCallback, + bool /* usePreparedStmt */) { auto thisPtr = shared_from_this(); loopThread_.getLoop()->queueInLoop( diff --git a/orm_lib/src/sqlite3_impl/Sqlite3Connection.h b/orm_lib/src/sqlite3_impl/Sqlite3Connection.h index 8f3ed834af..a6177580d4 100644 --- a/orm_lib/src/sqlite3_impl/Sqlite3Connection.h +++ b/orm_lib/src/sqlite3_impl/Sqlite3Connection.h @@ -46,14 +46,16 @@ class Sqlite3Connection : public DbConnection, void init() override; - void execSql(std::string_view &&sql, - size_t paraNum, - std::vector &¶meters, - std::vector &&length, - std::vector &&format, - ResultCallback &&rcb, - std::function - &&exceptCallback) override; + void execSql( + std::string_view &&sql, + size_t paraNum, + std::vector &¶meters, + std::vector &&length, + std::vector &&format, + int /* resultFormat */, + ResultCallback &&rcb, + std::function &&exceptCallback, + bool /* usePreparedStmt */) override; void batchSql(std::deque> &&) override { From 71338f35ab45c1255026ce524706d74e8cee4ff7 Mon Sep 17 00:00:00 2001 From: "He, Wanchen" Date: Sat, 7 May 2022 22:32:23 +0800 Subject: [PATCH 02/11] Support disabling pg prepared statement. --- orm_lib/inc/drogon/orm/DbClient.h | 3 ++- orm_lib/inc/drogon/orm/SqlBinder.h | 28 +++++++++++++++++++++++ orm_lib/src/DbClientImpl.cc | 16 ++++++++----- orm_lib/src/DbClientImpl.h | 24 +++++++++++--------- orm_lib/src/DbClientLockFree.cc | 30 +++++++++++++++---------- orm_lib/src/DbClientLockFree.h | 24 +++++++++++--------- orm_lib/src/DbConnection.h | 1 + orm_lib/src/SqlBinder.cc | 6 +++-- orm_lib/src/TransactionImpl.cc | 18 +++++++++------ orm_lib/src/TransactionImpl.h | 36 +++++++++++++++++------------- 10 files changed, 121 insertions(+), 65 deletions(-) diff --git a/orm_lib/inc/drogon/orm/DbClient.h b/orm_lib/inc/drogon/orm/DbClient.h index f2a8290ada..ee83718a4f 100644 --- a/orm_lib/inc/drogon/orm/DbClient.h +++ b/orm_lib/inc/drogon/orm/DbClient.h @@ -352,7 +352,8 @@ class DROGON_EXPORT DbClient : public trantor::NonCopyable std::vector &&format, int resultFormat, ResultCallback &&rcb, - std::function &&exceptCallback) = 0; + std::function &&exceptCallback, + bool usePreparedStmt) = 0; protected: ClientType type_; diff --git a/orm_lib/inc/drogon/orm/SqlBinder.h b/orm_lib/inc/drogon/orm/SqlBinder.h index 455ee37cfa..35fdcc1e66 100644 --- a/orm_lib/inc/drogon/orm/SqlBinder.h +++ b/orm_lib/inc/drogon/orm/SqlBinder.h @@ -120,6 +120,10 @@ enum class ResultFormat Text = 0, Binary = 1 }; +enum class SqlOption +{ + DisablePreparedStmt +}; namespace internal { @@ -532,6 +536,29 @@ class DROGON_EXPORT SqlBinder : public trantor::NonCopyable return *this; } + self &setSqlOption(SqlOption option) + { + switch (option) + { + case SqlOption::DisablePreparedStmt: + usePreparedStmt_ = false; + break; + } + return *this; + } + self &operator<<(const SqlOption &option) + { + return setSqlOption(option); + } + self &operator<<(SqlOption &option) + { + return setSqlOption(option); + } + self &operator<<(SqlOption &&option) + { + return setSqlOption(option); + } + template self &operator<<(const std::optional ¶meter) { @@ -620,6 +647,7 @@ class DROGON_EXPORT SqlBinder : public trantor::NonCopyable bool execed_{false}; bool destructed_{false}; bool isExceptionPtr_{false}; + bool usePreparedStmt_{true}; ClientType type_; }; diff --git a/orm_lib/src/DbClientImpl.cc b/orm_lib/src/DbClientImpl.cc index 2679f94fac..4480d0289f 100644 --- a/orm_lib/src/DbClientImpl.cc +++ b/orm_lib/src/DbClientImpl.cc @@ -125,7 +125,8 @@ void DbClientImpl::execSql( std::vector &&format, int resultFormat, ResultCallback &&rcb, - std::function &&exceptCallback) + std::function &&exceptCallback, + bool usePreparedStmt) { assert(paraNum == parameters.size()); assert(paraNum == length.size()); @@ -141,7 +142,8 @@ void DbClientImpl::execSql( std::move(format), resultFormat, std::move(rcb), - std::move(exceptCallback)); + std::move(exceptCallback), + usePreparedStmt); return; } DbConnectionPtr conn; @@ -189,7 +191,7 @@ void DbClientImpl::execSql( resultFormat, std::move(rcb), std::move(exceptCallback), - true); + usePreparedStmt); return; } if (busy) @@ -376,7 +378,7 @@ void DbClientImpl::handleNewTask(const DbConnectionPtr &connPtr) cmd->resultFormat_, std::move(cmd->callback_), std::move(cmd->exceptionCallback_), - true); + cmd->usePreparedStatement_); return; } } @@ -496,7 +498,8 @@ void DbClientImpl::execSqlWithTimeout( std::vector &&format, int resultFormat, ResultCallback &&rcb, - std::function &&ecb) + std::function &&ecb, + bool usePreparedStmt) { DbConnectionPtr conn; assert(timeout_ > 0.0); @@ -563,6 +566,7 @@ void DbClientImpl::execSqlWithTimeout( resultFormat, std::move(resultCallback), std::move(exceptionCallback)); + command->usePreparedStatement_ = usePreparedStmt; sqlCmdBuffer_.emplace_back(command); *cmd = command; } @@ -585,7 +589,7 @@ void DbClientImpl::execSqlWithTimeout( resultFormat, std::move(resultCallback), std::move(exceptionCallback), - true); + usePreparedStmt); timeoutFlagPtr->runTimer(); return; } diff --git a/orm_lib/src/DbClientImpl.h b/orm_lib/src/DbClientImpl.h index 4f99d9b69f..9cbf29e1c3 100644 --- a/orm_lib/src/DbClientImpl.h +++ b/orm_lib/src/DbClientImpl.h @@ -41,16 +41,17 @@ class DbClientImpl : public DbClient, ClientType type); #endif ~DbClientImpl() noexcept override; - void execSql(const char *sql, - size_t sqlLength, - size_t paraNum, - std::vector &¶meters, - std::vector &&length, - std::vector &&format, - int resultFormat, - ResultCallback &&rcb, - std::function - &&exceptCallback) override; + void execSql( + const char *sql, + size_t sqlLength, + size_t paraNum, + std::vector &¶meters, + std::vector &&length, + std::vector &&format, + int resultFormat, + ResultCallback &&rcb, + std::function &&exceptCallback, + bool usePreparedStmt) override; std::shared_ptr newTransaction( const std::function &commitCallback = std::function()) noexcept(false) override; @@ -102,7 +103,8 @@ class DbClientImpl : public DbClient, std::vector &&format, int resultFormat, ResultCallback &&rcb, - std::function &&exceptCallback); + std::function &&exceptCallback, + bool usePreparedStmt); }; } // namespace orm diff --git a/orm_lib/src/DbClientLockFree.cc b/orm_lib/src/DbClientLockFree.cc index b62cae6917..1adff68a3d 100644 --- a/orm_lib/src/DbClientLockFree.cc +++ b/orm_lib/src/DbClientLockFree.cc @@ -95,7 +95,8 @@ void DbClientLockFree::execSql( std::vector &&format, int resultFormat, ResultCallback &&rcb, - std::function &&exceptCallback) + std::function &&exceptCallback, + bool usePreparedStmt) { assert(paraNum == parameters.size()); assert(paraNum == length.size()); @@ -112,7 +113,8 @@ void DbClientLockFree::execSql( std::move(format), resultFormat, std::move(rcb), - std::move(exceptCallback)); + std::move(exceptCallback), + usePreparedStmt); return; } if (!connections_.empty() && sqlCmdBuffer_.empty() && @@ -143,7 +145,7 @@ void DbClientLockFree::execSql( } }, std::move(exceptCallback), - true); + usePreparedStmt); return; } } @@ -175,7 +177,7 @@ void DbClientLockFree::execSql( } }, std::move(exceptCallback), - true); + usePreparedStmt); return; } } @@ -199,7 +201,7 @@ void DbClientLockFree::execSql( resultFormat, std::move(rcb), std::move(exceptCallback), - true); + usePreparedStmt); return; } } @@ -218,7 +220,7 @@ void DbClientLockFree::execSql( } // LOG_TRACE << "Push query to buffer"; - sqlCmdBuffer_.emplace_back(std::make_shared( + auto cmdPtr = std::make_shared( std::string_view{sql, sqlLength}, paraNum, std::move(parameters), @@ -235,7 +237,9 @@ void DbClientLockFree::execSql( loop_->queueInLoop([rcb = std::move(rcb), r]() { rcb(r); }); } }, - std::move(exceptCallback))); + std::move(exceptCallback)); + cmdPtr->usePreparedStatement_ = usePreparedStmt; + sqlCmdBuffer_.emplace_back(std::move(cmdPtr)); } std::shared_ptr DbClientLockFree::newTransaction( @@ -408,7 +412,7 @@ void DbClientLockFree::handleNewTask(const DbConnectionPtr &conn) cmd->resultFormat_, std::move(cmd->callback_), std::move(cmd->exceptionCallback_), - true); + cmd->usePreparedStatement_); #endif return; } @@ -514,7 +518,8 @@ void DbClientLockFree::execSqlWithTimeout( std::vector &&format, int resultFormat, ResultCallback &&rcb, - std::function &&ecb) + std::function &&ecb, + bool usePreparedStmt) { auto commandPtr = std::make_shared>(); auto ecpPtr = @@ -584,7 +589,7 @@ void DbClientLockFree::execSqlWithTimeout( } }, std::move(exceptionCallback), - true); + usePreparedStmt); timeoutFlagPtr->runTimer(); return; } @@ -619,7 +624,7 @@ void DbClientLockFree::execSqlWithTimeout( } }, std::move(exceptionCallback), - true); + usePreparedStmt); timeoutFlagPtr->runTimer(); return; } @@ -644,7 +649,7 @@ void DbClientLockFree::execSqlWithTimeout( resultFormat, std::move(resultCallback), std::move(exceptionCallback), - true); + usePreparedStmt); timeoutFlagPtr->runTimer(); return; } @@ -682,6 +687,7 @@ void DbClientLockFree::execSqlWithTimeout( } }, std::move(exceptionCallback)); + cmdPtr->usePreparedStatement_ = usePreparedStmt; sqlCmdBuffer_.emplace_back(cmdPtr); *commandPtr = cmdPtr; timeoutFlagPtr->runTimer(); diff --git a/orm_lib/src/DbClientLockFree.h b/orm_lib/src/DbClientLockFree.h index 97ee57708c..897f6b639d 100644 --- a/orm_lib/src/DbClientLockFree.h +++ b/orm_lib/src/DbClientLockFree.h @@ -44,16 +44,17 @@ class DbClientLockFree : public DbClient, #endif ~DbClientLockFree() noexcept override; - void execSql(const char *sql, - size_t sqlLength, - size_t paraNum, - std::vector &¶meters, - std::vector &&length, - std::vector &&format, - int resultFormat, - ResultCallback &&rcb, - std::function - &&exceptCallback) override; + void execSql( + const char *sql, + size_t sqlLength, + size_t paraNum, + std::vector &¶meters, + std::vector &&length, + std::vector &&format, + int resultFormat, + ResultCallback &&rcb, + std::function &&exceptCallback, + bool usePreparedStmt) override; std::shared_ptr newTransaction( const std::function &commitCallback = std::function()) noexcept(false) override; @@ -97,7 +98,8 @@ class DbClientLockFree : public DbClient, std::vector &&format, int resultFormat, ResultCallback &&rcb, - std::function &&ecb); + std::function &&ecb, + bool usePreparedStmt); void handleNewTask(const DbConnectionPtr &conn); #if LIBPQ_SUPPORTS_BATCH_MODE size_t connectionPos_{0}; // Used for pg batch mode. diff --git a/orm_lib/src/DbConnection.h b/orm_lib/src/DbConnection.h index 4b418ad720..c7dcbbfd06 100644 --- a/orm_lib/src/DbConnection.h +++ b/orm_lib/src/DbConnection.h @@ -55,6 +55,7 @@ struct SqlCmd int resultFormat_{0}; QueryCallback callback_; ExceptPtrCallback exceptionCallback_; + bool usePreparedStatement_{true}; std::string preparingStatement_; #if LIBPQ_SUPPORTS_BATCH_MODE bool isChanging_{false}; diff --git a/orm_lib/src/SqlBinder.cc b/orm_lib/src/SqlBinder.cc index b62568321c..f629352b87 100644 --- a/orm_lib/src/SqlBinder.cc +++ b/orm_lib/src/SqlBinder.cc @@ -73,7 +73,8 @@ void SqlBinder::exec() if (exceptPtrCb) exceptPtrCb(exception); } - }); + }, + usePreparedStmt_); } else { @@ -99,7 +100,8 @@ void SqlBinder::exec() { assert(0); } - }); + }, + usePreparedStmt_); try { diff --git a/orm_lib/src/TransactionImpl.cc b/orm_lib/src/TransactionImpl.cc index 59a47c6096..c98e4c930c 100644 --- a/orm_lib/src/TransactionImpl.cc +++ b/orm_lib/src/TransactionImpl.cc @@ -95,7 +95,8 @@ void TransactionImpl::execSqlInLoop( std::vector &&format, int resultFormat, ResultCallback &&rcb, - std::function &&exceptCallback) + std::function &&exceptCallback, + bool usePreparedStmt) { loop_->assertInLoopThread(); if (!isCommitedOrRolledback_) @@ -109,7 +110,8 @@ void TransactionImpl::execSqlInLoop( std::move(format), resultFormat, std::move(rcb), - std::move(exceptCallback)); + std::move(exceptCallback), + usePreparedStmt); return; } auto thisPtr = shared_from_this(); @@ -130,7 +132,7 @@ void TransactionImpl::execSqlInLoop( if (exceptCallback) exceptCallback(ePtr); }, - true); + usePreparedStmt); } else { @@ -144,6 +146,7 @@ void TransactionImpl::execSqlInLoop( cmdPtr->resultFormat_ = resultFormat; cmdPtr->callback_ = std::move(rcb); cmdPtr->exceptionCallback_ = std::move(exceptCallback); + cmdPtr->usePreparedStmt_ = usePreparedStmt; cmdPtr->thisPtr_ = thisPtr; thisPtr->sqlCmdBuffer_.push_back(std::move(cmdPtr)); } @@ -247,7 +250,7 @@ void TransactionImpl::execNewTask() if (cmd->exceptionCallback_) cmd->exceptionCallback_(ePtr); }, - true); + cmd->usePreparedStmt_); return; } isWorking_ = false; @@ -314,7 +317,8 @@ void TransactionImpl::execSqlInLoopWithTimeout( std::vector &&format, int resultFormat, ResultCallback &&rcb, - std::function &&ecb) + std::function &&ecb, + bool usePreparedStmt) { auto thisPtr = shared_from_this(); std::weak_ptr weakPtr = thisPtr; @@ -377,7 +381,7 @@ void TransactionImpl::execSqlInLoopWithTimeout( (*ecpPtr)(ePtr); } }, - true); + usePreparedStmt); } else { @@ -399,7 +403,7 @@ void TransactionImpl::execSqlInLoopWithTimeout( (*ecpPtr)(ePtr); } }; - + cmdPtr->usePreparedStmt_ = usePreparedStmt; cmdPtr->thisPtr_ = thisPtr; thisPtr->sqlCmdBuffer_.push_back(cmdPtr); *commandPtr = cmdPtr; diff --git a/orm_lib/src/TransactionImpl.h b/orm_lib/src/TransactionImpl.h index 0ea1d51d22..5661c9bbf7 100644 --- a/orm_lib/src/TransactionImpl.h +++ b/orm_lib/src/TransactionImpl.h @@ -53,16 +53,17 @@ class TransactionImpl : public Transaction, private: DbConnectionPtr connectionPtr_; - void execSql(const char *sql, - size_t sqlLength, - size_t paraNum, - std::vector &¶meters, - std::vector &&length, - std::vector &&format, - int resultFormat, - ResultCallback &&rcb, - std::function - &&exceptCallback) override + void execSql( + const char *sql, + size_t sqlLength, + size_t paraNum, + std::vector &¶meters, + std::vector &&length, + std::vector &&format, + int resultFormat, + ResultCallback &&rcb, + std::function &&exceptCallback, + bool usePreparedStmt) override { if (loop_->isInLoopThread()) { @@ -73,7 +74,8 @@ class TransactionImpl : public Transaction, std::move(format), resultFormat, std::move(rcb), - std::move(exceptCallback)); + std::move(exceptCallback), + usePreparedStmt); } else { @@ -85,6 +87,7 @@ class TransactionImpl : public Transaction, length = std::move(length), format = std::move(format), resultFormat, + usePreparedStmt, rcb = std::move(rcb), exceptCallback = std::move(exceptCallback)]() mutable { thisPtr->execSqlInLoop(std::move(sql), @@ -94,7 +97,8 @@ class TransactionImpl : public Transaction, std::move(format), resultFormat, std::move(rcb), - std::move(exceptCallback)); + std::move(exceptCallback), + usePreparedStmt); }); } } @@ -107,7 +111,8 @@ class TransactionImpl : public Transaction, std::vector &&format, int resultFormat, ResultCallback &&rcb, - std::function &&exceptCallback); + std::function &&exceptCallback, + bool usePreparedStmt); void execSqlInLoopWithTimeout( std::string_view &&sql, size_t paraNum, @@ -116,8 +121,8 @@ class TransactionImpl : public Transaction, std::vector &&format, int resultFormat, ResultCallback &&rcb, - std::function &&exceptCallback); - + std::function &&exceptCallback, + bool usePreparedStmt); std::shared_ptr newTransaction( const std::function &) noexcept(false) override { @@ -147,6 +152,7 @@ class TransactionImpl : public Transaction, QueryCallback callback_; ExceptPtrCallback exceptionCallback_; bool isRollbackCmd_{false}; + bool usePreparedStmt_{true}; std::shared_ptr thisPtr_; }; From e48db688142306ce11fb472df338e824853d843e Mon Sep 17 00:00:00 2001 From: "He, Wanchen" Date: Sun, 8 May 2022 00:30:05 +0800 Subject: [PATCH 03/11] Add test. --- orm_lib/tests/db_test.cc | 85 ++++++++++++++++++++++++++++++++++++++-- 1 file changed, 82 insertions(+), 3 deletions(-) diff --git a/orm_lib/tests/db_test.cc b/orm_lib/tests/db_test.cc index 086a8cca25..579c08448f 100644 --- a/orm_lib/tests/db_test.cc +++ b/orm_lib/tests/db_test.cc @@ -379,7 +379,45 @@ DROGON_TEST(PostgreTest) "postgresql1", "pg", "postgresql"); - /// 2.6 clean up + + /// 2.6. Test pg options with plain sql + clientPtr->execSqlAsync( + "select 12345::int", + [TEST_CTX](const Result &r) { + MANDATE(r[0][0].length() == sizeof(int)); + int i = *(int *)r[0][0].c_str(); + MANDATE(ntohl(i) == 12345); + SUCCESS(); + }, + [TEST_CTX](const DrogonDbException &e) { + FAULT( + "postgresql - DbClient pg special options" + "what():" + + std::string(e.base().what())); + }, + ResultFormat::Binary, + SqlOption::DisablePreparedStmt); + + /// 2.7. Test pg options + clientPtr->execSqlAsync( + "select $1::int", + [TEST_CTX](const Result &r) { + MANDATE(r[0][0].length() == sizeof(int)); + int i = *(int *)r[0][0].c_str(); + MANDATE(ntohl(i) == 12345); + SUCCESS(); + }, + [TEST_CTX](const DrogonDbException &e) { + FAULT( + "postgresql - DbClient pg special options" + "what():" + + std::string(e.base().what())); + }, + 12345, + ResultFormat::Binary, + SqlOption::DisablePreparedStmt); + + /// 2.8 clean up clientPtr->execSqlAsync( "truncate table users restart identity", [TEST_CTX](const Result &r) { SUCCESS(); }, @@ -464,7 +502,27 @@ DROGON_TEST(PostgreTest) { SUCCESS(); } - /// 3.6 clean up + + /// 3.6. Test pg options + try + { + auto r = clientPtr->execSqlSync("select $1::int", + 12345, + ResultFormat::Binary, + SqlOption::DisablePreparedStmt); + MANDATE(r[0][0].length() == sizeof(int)); + int i = *(int *)r[0][0].c_str(); + MANDATE(ntohl(i) == 12345); + } + catch (const DrogonDbException &e) + { + FAULT( + "postgresql - DbClient pg special options" + "what():" + + std::string(e.base().what())); + } + + /// 3.7 clean up try { auto r = @@ -557,7 +615,28 @@ DROGON_TEST(PostgreTest) { SUCCESS(); } - /// 4.6 clean up + + /// 4.6. Test pg options + f = clientPtr->execSqlAsyncFuture("select $1::int", + 12345, + ResultFormat::Binary, + SqlOption::DisablePreparedStmt); + try + { + auto r = f.get(); + MANDATE(r[0][0].length() == sizeof(int)); + int i = *(int *)r[0][0].c_str(); + MANDATE(ntohl(i) == 12345); + } + catch (const DrogonDbException &e) + { + FAULT( + "postgresql - DbClient pg special options" + "what():" + + std::string(e.base().what())); + } + + /// 4.7 clean up f = clientPtr->execSqlAsyncFuture("truncate table users restart identity"); try { From 72dd42273455cfe79c46baeb999a3aa990ec59f2 Mon Sep 17 00:00:00 2001 From: "He, Wanchen" Date: Sun, 8 May 2022 01:04:06 +0800 Subject: [PATCH 04/11] Support resultFormat when no sql parameters. --- orm_lib/src/postgresql_impl/PgConnection.cc | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/orm_lib/src/postgresql_impl/PgConnection.cc b/orm_lib/src/postgresql_impl/PgConnection.cc index a32e5dbc3e..305a7413ba 100644 --- a/orm_lib/src/postgresql_impl/PgConnection.cc +++ b/orm_lib/src/postgresql_impl/PgConnection.cc @@ -222,7 +222,14 @@ void PgConnection::execSqlInLoop( if (paraNum == 0) { isPreparingStatement_ = false; - if (PQsendQuery(connectionPtr_.get(), sql_.data()) == 0) + if (PQsendQueryParams(connectionPtr_.get(), + sql_.data(), + 0, + nullptr, + nullptr, + nullptr, + nullptr, + resultFormat) == 0) { LOG_ERROR << "send query error: " << PQerrorMessage(connectionPtr_.get()); From bb13681bd895342cabda56e44fa97db299df7355 Mon Sep 17 00:00:00 2001 From: "He, Wanchen" Date: Sun, 8 May 2022 11:54:25 +0800 Subject: [PATCH 05/11] Fix missing parameters. --- orm_lib/src/DbClientImpl.cc | 9 +++++---- orm_lib/src/DbClientLockFree.cc | 10 +++++----- orm_lib/src/DbConnection.h | 8 +++++--- orm_lib/src/postgresql_impl/PgBatchConnection.cc | 7 +++++-- 4 files changed, 20 insertions(+), 14 deletions(-) diff --git a/orm_lib/src/DbClientImpl.cc b/orm_lib/src/DbClientImpl.cc index 4480d0289f..07551d85eb 100644 --- a/orm_lib/src/DbClientImpl.cc +++ b/orm_lib/src/DbClientImpl.cc @@ -169,7 +169,8 @@ void DbClientImpl::execSql( std::move(format), resultFormat, std::move(rcb), - std::move(exceptCallback)); + std::move(exceptCallback), + usePreparedStmt); sqlCmdBuffer_.push_back(std::move(cmd)); } } @@ -378,7 +379,7 @@ void DbClientImpl::handleNewTask(const DbConnectionPtr &connPtr) cmd->resultFormat_, std::move(cmd->callback_), std::move(cmd->exceptionCallback_), - cmd->usePreparedStatement_); + cmd->usePreparedStmt_); return; } } @@ -565,8 +566,8 @@ void DbClientImpl::execSqlWithTimeout( std::move(format), resultFormat, std::move(resultCallback), - std::move(exceptionCallback)); - command->usePreparedStatement_ = usePreparedStmt; + std::move(exceptionCallback), + usePreparedStmt); sqlCmdBuffer_.emplace_back(command); *cmd = command; } diff --git a/orm_lib/src/DbClientLockFree.cc b/orm_lib/src/DbClientLockFree.cc index 1adff68a3d..f6a36a81b5 100644 --- a/orm_lib/src/DbClientLockFree.cc +++ b/orm_lib/src/DbClientLockFree.cc @@ -237,8 +237,8 @@ void DbClientLockFree::execSql( loop_->queueInLoop([rcb = std::move(rcb), r]() { rcb(r); }); } }, - std::move(exceptCallback)); - cmdPtr->usePreparedStatement_ = usePreparedStmt; + std::move(exceptCallback), + usePreparedStmt); sqlCmdBuffer_.emplace_back(std::move(cmdPtr)); } @@ -412,7 +412,7 @@ void DbClientLockFree::handleNewTask(const DbConnectionPtr &conn) cmd->resultFormat_, std::move(cmd->callback_), std::move(cmd->exceptionCallback_), - cmd->usePreparedStatement_); + cmd->usePreparedStmt_); #endif return; } @@ -686,8 +686,8 @@ void DbClientLockFree::execSqlWithTimeout( r]() { resultCallback(r); }); } }, - std::move(exceptionCallback)); - cmdPtr->usePreparedStatement_ = usePreparedStmt; + std::move(exceptionCallback), + usePreparedStmt); sqlCmdBuffer_.emplace_back(cmdPtr); *commandPtr = cmdPtr; timeoutFlagPtr->runTimer(); diff --git a/orm_lib/src/DbConnection.h b/orm_lib/src/DbConnection.h index c7dcbbfd06..7a74620871 100644 --- a/orm_lib/src/DbConnection.h +++ b/orm_lib/src/DbConnection.h @@ -55,7 +55,7 @@ struct SqlCmd int resultFormat_{0}; QueryCallback callback_; ExceptPtrCallback exceptionCallback_; - bool usePreparedStatement_{true}; + bool usePreparedStmt_{true}; std::string preparingStatement_; #if LIBPQ_SUPPORTS_BATCH_MODE bool isChanging_{false}; @@ -67,7 +67,8 @@ struct SqlCmd std::vector &&format, int resultFormat, QueryCallback &&cb, - ExceptPtrCallback &&exceptCb) + ExceptPtrCallback &&exceptCb, + bool usePreparedStmt = true) : sql_(std::move(sql)), parametersNumber_(paraNum), parameters_(std::move(parameters)), @@ -75,7 +76,8 @@ struct SqlCmd formats_(std::move(format)), resultFormat_(resultFormat), callback_(std::move(cb)), - exceptionCallback_(std::move(exceptCb)) + exceptionCallback_(std::move(exceptCb)), + usePreparedStmt_(usePreparedStmt) { } }; diff --git a/orm_lib/src/postgresql_impl/PgBatchConnection.cc b/orm_lib/src/postgresql_impl/PgBatchConnection.cc index 631ef6907c..7f5b0ae430 100644 --- a/orm_lib/src/postgresql_impl/PgBatchConnection.cc +++ b/orm_lib/src/postgresql_impl/PgBatchConnection.cc @@ -230,7 +230,9 @@ void PgConnection::execSqlInLoop( std::vector &&length, std::vector &&format, ResultCallback &&rcb, - std::function &&exceptCallback) + std::function &&exceptCallback, + int resultFormat, + bool /* usePreparedStmt not supported in batch mode yet */) { LOG_TRACE << sql; isWorking_ = true; @@ -240,6 +242,7 @@ void PgConnection::execSqlInLoop( std::move(parameters), std::move(length), std::move(format), + resultFormat, std::move(rcb), std::move(exceptCallback))); if (batchSqlCommands_.size() == 1 && !channel_.isWriting()) @@ -349,7 +352,7 @@ void PgConnection::sendBatchedSql() cmd->parameters_.data(), cmd->lengths_.data(), cmd->formats_.data(), - 0) == 0) + cmd->resultFormat) == 0) { isWorking_ = false; handleFatalError(true); From 1374f6ef00ad70c6cee29b1d31985a9fd8ecb541 Mon Sep 17 00:00:00 2001 From: "He, Wanchen" Date: Sun, 8 May 2022 23:15:24 +0800 Subject: [PATCH 06/11] Fix SqlBinder move ctor. --- orm_lib/inc/drogon/orm/SqlBinder.h | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/orm_lib/inc/drogon/orm/SqlBinder.h b/orm_lib/inc/drogon/orm/SqlBinder.h index 35fdcc1e66..e829e98f22 100644 --- a/orm_lib/inc/drogon/orm/SqlBinder.h +++ b/orm_lib/inc/drogon/orm/SqlBinder.h @@ -332,6 +332,7 @@ class DROGON_EXPORT SqlBinder : public trantor::NonCopyable parameters_(std::move(that.parameters_)), lengths_(std::move(that.lengths_)), formats_(std::move(that.formats_)), + resultFormat_(that.resultFormat_), objs_(std::move(that.objs_)), mode_(that.mode_), callbackHolder_(std::move(that.callbackHolder_)), @@ -340,6 +341,7 @@ class DROGON_EXPORT SqlBinder : public trantor::NonCopyable execed_(that.execed_), destructed_(that.destructed_), isExceptionPtr_(that.isExceptionPtr_), + usePreparedStmt_(that.usePreparedStmt_), type_(that.type_) { // set the execed_ to true to avoid the same sql being executed twice. @@ -638,9 +640,9 @@ class DROGON_EXPORT SqlBinder : public trantor::NonCopyable std::vector parameters_; std::vector lengths_; std::vector formats_; + ResultFormat resultFormat_{ResultFormat::Text}; std::vector> objs_; Mode mode_{Mode::NonBlocking}; - ResultFormat resultFormat_{ResultFormat::Text}; std::shared_ptr callbackHolder_; DrogonDbExceptionCallback exceptionCallback_; ExceptPtrCallback exceptionPtrCallback_; From 766182576b4ea0e041ff3fd8dd22acc4ba3a88a5 Mon Sep 17 00:00:00 2001 From: "He, Wanchen" Date: Fri, 29 Jul 2022 23:15:53 +0800 Subject: [PATCH 07/11] Fix typo. --- orm_lib/src/postgresql_impl/PgBatchConnection.cc | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/orm_lib/src/postgresql_impl/PgBatchConnection.cc b/orm_lib/src/postgresql_impl/PgBatchConnection.cc index 7f5b0ae430..e200293120 100644 --- a/orm_lib/src/postgresql_impl/PgBatchConnection.cc +++ b/orm_lib/src/postgresql_impl/PgBatchConnection.cc @@ -352,7 +352,7 @@ void PgConnection::sendBatchedSql() cmd->parameters_.data(), cmd->lengths_.data(), cmd->formats_.data(), - cmd->resultFormat) == 0) + cmd->resultFormat_) == 0) { isWorking_ = false; handleFatalError(true); From 13e76658890bf9246dbd5cf6818f4d90bf6a5e7f Mon Sep 17 00:00:00 2001 From: "He, Wanchen" Date: Fri, 29 Jul 2022 23:23:27 +0800 Subject: [PATCH 08/11] Fix missing parameters. --- orm_lib/src/DbClientLockFree.cc | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/orm_lib/src/DbClientLockFree.cc b/orm_lib/src/DbClientLockFree.cc index f6a36a81b5..626409ce28 100644 --- a/orm_lib/src/DbClientLockFree.cc +++ b/orm_lib/src/DbClientLockFree.cc @@ -391,8 +391,10 @@ void DbClientLockFree::handleNewTask(const DbConnectionPtr &conn) std::move(cmd->parameters_), std::move(cmd->lengths_), std::move(cmd->formats_), + cmd->resultFormat_, std::move(cmd->callback_), - std::move(cmd->exceptionCallback_)); + std::move(cmd->exceptionCallback_), + cmd->usePreparedStmt_); } else { From 39ca8937b21ddd85f26fe4cf44537286b71b4dfc Mon Sep 17 00:00:00 2001 From: "He, Wanchen" Date: Mon, 23 Jan 2023 16:39:46 +0800 Subject: [PATCH 09/11] Rebase master. Add old execSql() overload. --- orm_lib/src/DbConnection.h | 20 ++++++++++++++++++++ 1 file changed, 20 insertions(+) diff --git a/orm_lib/src/DbConnection.h b/orm_lib/src/DbConnection.h index 7a74620871..284499e02d 100644 --- a/orm_lib/src/DbConnection.h +++ b/orm_lib/src/DbConnection.h @@ -122,6 +122,26 @@ class DbConnection : public trantor::NonCopyable std::function &&exceptCallback, bool usePreparedStmt) = 0; + void execSql( + string_view &&sql, + size_t paraNum, + std::vector &¶meters, + std::vector &&length, + std::vector &&format, + ResultCallback &&rcb, + std::function &&exceptCallback) + { + execSql(std::move(sql), + paraNum, + std::move(parameters), + std::move(length), + std::move(format), + 0, + std::move(rcb), + std::move(exceptCallback), + true); + } + virtual void batchSql( std::deque> &&sqlCommands) = 0; From 1a12358d701505bd41919034824dff08292786c5 Mon Sep 17 00:00:00 2001 From: "He, Wanchen" Date: Fri, 10 May 2024 16:44:56 +0800 Subject: [PATCH 10/11] Format. --- orm_lib/inc/drogon/orm/SqlBinder.h | 5 +++++ orm_lib/src/TransactionImpl.h | 1 + 2 files changed, 6 insertions(+) diff --git a/orm_lib/inc/drogon/orm/SqlBinder.h b/orm_lib/inc/drogon/orm/SqlBinder.h index e829e98f22..52d6b7d4d8 100644 --- a/orm_lib/inc/drogon/orm/SqlBinder.h +++ b/orm_lib/inc/drogon/orm/SqlBinder.h @@ -527,11 +527,13 @@ class DROGON_EXPORT SqlBinder : public trantor::NonCopyable resultFormat_ = resultFormat; return *this; } + self &operator<<(ResultFormat &resultFormat) { resultFormat_ = resultFormat; return *this; } + self &operator<<(ResultFormat &&resultFormat) { resultFormat_ = resultFormat; @@ -548,14 +550,17 @@ class DROGON_EXPORT SqlBinder : public trantor::NonCopyable } return *this; } + self &operator<<(const SqlOption &option) { return setSqlOption(option); } + self &operator<<(SqlOption &option) { return setSqlOption(option); } + self &operator<<(SqlOption &&option) { return setSqlOption(option); diff --git a/orm_lib/src/TransactionImpl.h b/orm_lib/src/TransactionImpl.h index 5661c9bbf7..6bdaefedd3 100644 --- a/orm_lib/src/TransactionImpl.h +++ b/orm_lib/src/TransactionImpl.h @@ -123,6 +123,7 @@ class TransactionImpl : public Transaction, ResultCallback &&rcb, std::function &&exceptCallback, bool usePreparedStmt); + std::shared_ptr newTransaction( const std::function &) noexcept(false) override { From 7d477da4e766bfbd289af05a8c23f77388cc77b2 Mon Sep 17 00:00:00 2001 From: "He, Wanchen" Date: Fri, 10 May 2024 16:49:42 +0800 Subject: [PATCH 11/11] Fix std. --- orm_lib/src/DbConnection.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/orm_lib/src/DbConnection.h b/orm_lib/src/DbConnection.h index 284499e02d..5f3fcd19dc 100644 --- a/orm_lib/src/DbConnection.h +++ b/orm_lib/src/DbConnection.h @@ -123,7 +123,7 @@ class DbConnection : public trantor::NonCopyable bool usePreparedStmt) = 0; void execSql( - string_view &&sql, + std::string_view &&sql, size_t paraNum, std::vector &¶meters, std::vector &&length,