diff --git a/hikyuu_cpp/hikyuu/utilities/db_connect/DBConnect.h b/hikyuu_cpp/hikyuu/utilities/db_connect/DBConnect.h index 532ccaa2..fb6591e0 100644 --- a/hikyuu_cpp/hikyuu/utilities/db_connect/DBConnect.h +++ b/hikyuu_cpp/hikyuu/utilities/db_connect/DBConnect.h @@ -11,6 +11,7 @@ #define HIKYUU_DB_CONNECT_H #include "DBConnectBase.h" +#include "SQLException.h" #include "DBCondition.h" #include "SQLStatementBase.h" #include "TransAction.h" diff --git a/hikyuu_cpp/hikyuu/utilities/db_connect/DBConnectBase.h b/hikyuu_cpp/hikyuu/utilities/db_connect/DBConnectBase.h index c6c37834..d44dcdf0 100644 --- a/hikyuu_cpp/hikyuu/utilities/db_connect/DBConnectBase.h +++ b/hikyuu_cpp/hikyuu/utilities/db_connect/DBConnectBase.h @@ -14,6 +14,7 @@ #include "../../utilities/Parameter.h" #include "DBCondition.h" #include "SQLStatementBase.h" +#include "SQLException.h" namespace hku { @@ -275,6 +276,13 @@ void DBConnectBase::save(T& item, bool autotrans) { if (autotrans) { commit(); } + + } catch (hku::SQLException& e) { + if (autotrans) { + rollback(); + } + SQL_THROW(e.errcode(), "failed save! sql: {}! {}", st->getSqlString(), e.what()); + } catch (std::exception& e) { if (autotrans) { rollback(); @@ -312,6 +320,12 @@ void DBConnectBase::batchSave(InputIterator first, InputIterator last, bool auto commit(); } + } catch (hku::SQLException& e) { + if (autotrans) { + rollback(); + } + SQL_THROW(e.errcode(), "failed batch save! sql: {}! {}", st->getSqlString(), e.what()); + } catch (std::exception& e) { if (autotrans) { rollback(); @@ -390,11 +404,17 @@ void DBConnectBase::batchUpdate(InputIterator first, InputIterator last, bool au commit(); } + } catch (hku::SQLException& e) { + if (autotrans) { + rollback(); + } + SQL_THROW(e.errcode(), "failed batch update! sql: {}! {}", st->getSqlString(), e.what()); + } catch (std::exception& e) { if (autotrans) { rollback(); } - HKU_THROW("failed batch save! sql: {}! {}", st->getSqlString(), e.what()); + HKU_THROW("failed batch update! sql: {}! {}", st->getSqlString(), e.what()); } catch (...) { if (autotrans) { @@ -439,6 +459,13 @@ void DBConnectBase::remove(T& item, bool autotrans) { if (autotrans) { commit(); } + + } catch (hku::SQLException& e) { + if (autotrans) { + rollback(); + } + SQL_THROW(e.errcode(), "failed delete! sql: {}! {}", st->getSqlString(), e.what()); + } catch (std::exception& e) { if (autotrans) { rollback(); @@ -472,6 +499,13 @@ void DBConnectBase::batchRemove(InputIterator first, InputIterator last, bool au if (autotrans) { commit(); } + + } catch (hku::SQLException& e) { + if (autotrans) { + rollback(); + } + SQL_THROW(e.errcode(), "failed batch delete! {}", e.what()); + } catch (std::exception& e) { if (autotrans) { rollback(); @@ -496,11 +530,16 @@ inline void DBConnectBase::remove(const std::string& tablename, const std::strin try { exec(sql); + } catch (hku::SQLException& e) { + if (autotrans) { + rollback(); + } + SQL_THROW(e.errcode(), "Failed exec sql: {}! {}", sql, e.what()); } catch (std::exception& e) { if (autotrans) { rollback(); } - HKU_THROW(R"(Failed exec sql: {}! {})", sql, e.what()); + HKU_THROW("Failed exec sql: {}! {}", sql, e.what()); } catch (...) { if (autotrans) { rollback(); diff --git a/hikyuu_cpp/hikyuu/utilities/db_connect/sqlite/SQLiteException.h b/hikyuu_cpp/hikyuu/utilities/db_connect/SQLException.h similarity index 57% rename from hikyuu_cpp/hikyuu/utilities/db_connect/sqlite/SQLiteException.h rename to hikyuu_cpp/hikyuu/utilities/db_connect/SQLException.h index 42e769d6..cc6bc16a 100644 --- a/hikyuu_cpp/hikyuu/utilities/db_connect/sqlite/SQLiteException.h +++ b/hikyuu_cpp/hikyuu/utilities/db_connect/SQLException.h @@ -12,25 +12,24 @@ namespace hku { -/** SQLite 处理异常 */ -class SQLiteException : public hku::exception { +/** SQL 数据库引擎处理异常 */ +class SQLException : public hku::exception { public: - SQLiteException() = delete; + SQLException() = delete; /** * 构造 SQLite 异常 * @param errcode SQLite错误码 * @param msg SQLite错误信息 */ - SQLiteException(int errcode, const std::string& msg) - : hku::exception(msg), m_errcode(errcode) {} + SQLException(int errcode, const std::string& msg) : hku::exception(msg), m_errcode(errcode) {} /** * 构造 SQLite 异常 * @param errcode SQLite错误码 * @param msg SQLite错误信息 */ - SQLiteException(int errcode, const char* msg) : hku::exception(msg), m_errcode(errcode) {} + SQLException(int errcode, const char* msg) : hku::exception(msg), m_errcode(errcode) {} /** 获取 SQLite 错误码 */ int errcode() const { @@ -41,20 +40,20 @@ private: int m_errcode; }; -#define SQLITE_CHECK(expr, errcode, ...) \ +#define SQL_CHECK(expr, errcode, ...) \ do { \ if (!(expr)) { \ - throw SQLiteException( \ + throw SQLException( \ errcode, fmt::format("CHECK({}) {} [{}] ({}:{})", #expr, fmt::format(__VA_ARGS__), \ __FUNCTION__, __FILE__, __LINE__)); \ } \ } while (0) -#define SQLITE_THROW(errcode, ...) \ - do { \ - throw SQLiteException(errcode, \ - fmt::format("EXCEPTION: {} [{}] ({}:{})", fmt::format(__VA_ARGS__), \ - __FUNCTION__, __FILE__, __LINE__)); \ +#define SQL_THROW(errcode, ...) \ + do { \ + throw SQLException(errcode, \ + fmt::format("EXCEPTION: {} [{}] ({}:{})", fmt::format(__VA_ARGS__), \ + __FUNCTION__, __FILE__, __LINE__)); \ } while (0) } // namespace hku \ No newline at end of file diff --git a/hikyuu_cpp/hikyuu/utilities/db_connect/mysql/MySQLConnect.cpp b/hikyuu_cpp/hikyuu/utilities/db_connect/mysql/MySQLConnect.cpp index 325abb41..faf1bfb5 100755 --- a/hikyuu_cpp/hikyuu/utilities/db_connect/mysql/MySQLConnect.cpp +++ b/hikyuu_cpp/hikyuu/utilities/db_connect/mysql/MySQLConnect.cpp @@ -73,14 +73,14 @@ void MySQLConnect::exec(const string& sql_string) { if (ping()) { ret = mysql_query(m_mysql, sql_string.c_str()); } else { - MYSQL_THROW(ret, "SQL error:{}! error code:{}, error msg: {}", sql_string, ret, - mysql_error(m_mysql)); + SQL_THROW(ret, "SQL error:{}! error code:{}, error msg: {}", sql_string, ret, + mysql_error(m_mysql)); } } if (ret) { - MYSQL_THROW(ret, "SQL error:{}! error code:{}, error msg: {}", sql_string, ret, - mysql_error(m_mysql)); + SQL_THROW(ret, "SQL error:{}! error code:{}, error msg: {}", sql_string, ret, + mysql_error(m_mysql)); } do { @@ -98,8 +98,8 @@ void MySQLConnect::exec(const string& sql_string) { HKU_TRACE("num_rows: {}", num_rows); #endif } else { - MYSQL_THROW(ret, "mysql_field_count error:{}! error code:{}, error msg: {}", - sql_string, ret, mysql_error(m_mysql)); + SQL_THROW(ret, "mysql_field_count error:{}! error code:{}, error msg: {}", + sql_string, ret, mysql_error(m_mysql)); } } } while (!mysql_next_result(m_mysql)); diff --git a/hikyuu_cpp/hikyuu/utilities/db_connect/mysql/MySQLConnect.h b/hikyuu_cpp/hikyuu/utilities/db_connect/mysql/MySQLConnect.h index c1a0b6b0..7c525108 100755 --- a/hikyuu_cpp/hikyuu/utilities/db_connect/mysql/MySQLConnect.h +++ b/hikyuu_cpp/hikyuu/utilities/db_connect/mysql/MySQLConnect.h @@ -13,7 +13,6 @@ #include "../DBConnectBase.h" #include "MySQLStatement.h" -#include "MySQLException.h" #if defined(_MSC_VER) #include diff --git a/hikyuu_cpp/hikyuu/utilities/db_connect/mysql/MySQLException.h b/hikyuu_cpp/hikyuu/utilities/db_connect/mysql/MySQLException.h deleted file mode 100644 index 38a659b5..00000000 --- a/hikyuu_cpp/hikyuu/utilities/db_connect/mysql/MySQLException.h +++ /dev/null @@ -1,59 +0,0 @@ -/* - * Copyright(C) 2021 hikyuu.org - * - * Create on: 2021-06-26 - * Author: fasiondog - */ - -#pragma once - -#include -#include "hikyuu/exception.h" - -namespace hku { - -/** MYSQL 处理异常 */ -class MySQLException : public hku::exception { -public: - MySQLException() = delete; - - /** - * 构造 MYSQL 异常 - * @param errcode MYSQL 错误码 - * @param msg MYSQL 错误信息 - */ - MySQLException(int errcode, const std::string& msg) : hku::exception(msg), m_errcode(errcode) {} - - /** - * 构造 MYSQL 异常 - * @param errcode MYSQL 错误码 - * @param msg MYSQL 错误信息 - */ - MySQLException(int errcode, const char* msg) : hku::exception(msg), m_errcode(errcode) {} - - /** 获取 MYSQL 错误码 */ - int errcode() const { - return m_errcode; - } - -private: - int m_errcode; -}; - -#define MYSQL_CHECK(expr, errcode, ...) \ - do { \ - if (!(expr)) { \ - throw MySQLException( \ - errcode, fmt::format("CHECK({}) {} [{}] ({}:{})", #expr, fmt::format(__VA_ARGS__), \ - __FUNCTION__, __FILE__, __LINE__)); \ - } \ - } while (0) - -#define MYSQL_THROW(errcode, ...) \ - do { \ - throw MySQLException(errcode, \ - fmt::format("EXCEPTION: {} [{}] ({}:{})", fmt::format(__VA_ARGS__), \ - __FUNCTION__, __FILE__, __LINE__)); \ - } while (0) - -} // namespace hku \ No newline at end of file diff --git a/hikyuu_cpp/hikyuu/utilities/db_connect/mysql/MySQLStatement.cpp b/hikyuu_cpp/hikyuu/utilities/db_connect/mysql/MySQLStatement.cpp index 85c24a42..68b06ad1 100755 --- a/hikyuu_cpp/hikyuu/utilities/db_connect/mysql/MySQLStatement.cpp +++ b/hikyuu_cpp/hikyuu/utilities/db_connect/mysql/MySQLStatement.cpp @@ -26,8 +26,8 @@ MySQLStatement::MySQLStatement(DBConnectBase* driver, const string& sql_statemen std::string stmt_errorstr(mysql_stmt_error(m_stmt)); mysql_stmt_close(m_stmt); m_stmt = nullptr; - MYSQL_THROW(ret, "Failed prepare sql statement: {}! error msg: {}!", sql_statement, - stmt_errorstr); + SQL_THROW(ret, "Failed prepare sql statement: {}! error msg: {}!", sql_statement, + stmt_errorstr); } auto param_count = mysql_stmt_param_count(m_stmt); @@ -57,7 +57,7 @@ MySQLStatement::~MySQLStatement() { void MySQLStatement::_reset() { if (m_needs_reset) { int ret = mysql_stmt_reset(m_stmt); - MYSQL_CHECK(ret == 0, ret, "Failed reset statement! {}", mysql_stmt_error(m_stmt)); + SQL_CHECK(ret == 0, ret, "Failed reset statement! {}", mysql_stmt_error(m_stmt)); // m_param_bind.clear(); // m_result_bind.clear(); // m_param_buffer.clear(); @@ -73,10 +73,10 @@ void MySQLStatement::sub_exec() { int ret = 0; if (m_param_bind.size() > 0) { ret = mysql_stmt_bind_param(m_stmt, m_param_bind.data()); - MYSQL_CHECK(ret == 0, ret, "Failed mysql_stmt_bind_param! {}", mysql_stmt_error(m_stmt)); + SQL_CHECK(ret == 0, ret, "Failed mysql_stmt_bind_param! {}", mysql_stmt_error(m_stmt)); } ret = mysql_stmt_execute(m_stmt); - MYSQL_CHECK(ret == 0, ret, "Failed mysql_stmt_execute: {}", mysql_stmt_error(m_stmt)); + SQL_CHECK(ret == 0, ret, "Failed mysql_stmt_execute: {}", mysql_stmt_error(m_stmt)); } void MySQLStatement::_bindResult() { @@ -148,17 +148,17 @@ bool MySQLStatement::sub_moveNext() { m_has_bind_result = true; ret = mysql_stmt_bind_result(m_stmt, m_result_bind.data()); - MYSQL_CHECK(ret == 0, ret, "Failed mysql_stmt_bind_result! {}", mysql_stmt_error(m_stmt)); + SQL_CHECK(ret == 0, ret, "Failed mysql_stmt_bind_result! {}", mysql_stmt_error(m_stmt)); ret = mysql_stmt_store_result(m_stmt); - MYSQL_CHECK(ret == 0, ret, "Failed mysql_stmt_store_result! {}", mysql_stmt_error(m_stmt)); + SQL_CHECK(ret == 0, ret, "Failed mysql_stmt_store_result! {}", mysql_stmt_error(m_stmt)); } ret = mysql_stmt_fetch(m_stmt); if (ret == 0) { return true; } else if (ret == 1) { - MYSQL_THROW(ret, "Error occurred in mysql_stmt_fetch! {}", mysql_stmt_error(m_stmt)); + SQL_THROW(ret, "Error occurred in mysql_stmt_fetch! {}", mysql_stmt_error(m_stmt)); } return false; } diff --git a/hikyuu_cpp/hikyuu/utilities/db_connect/sqlite/SQLiteConnect.cpp b/hikyuu_cpp/hikyuu/utilities/db_connect/sqlite/SQLiteConnect.cpp index 8432ec49..f320141c 100644 --- a/hikyuu_cpp/hikyuu/utilities/db_connect/sqlite/SQLiteConnect.cpp +++ b/hikyuu_cpp/hikyuu/utilities/db_connect/sqlite/SQLiteConnect.cpp @@ -32,14 +32,14 @@ SQLiteConnect::SQLiteConnect(const Parameter& param) : DBConnectBase(param), m_d flags = getParam("flags"); } int rc = sqlite3_open_v2(m_dbname.c_str(), &m_db, flags, NULL); - SQLITE_CHECK(rc == SQLITE_OK, rc, sqlite3_errmsg(m_db)); + SQL_CHECK(rc == SQLITE_OK, rc, sqlite3_errmsg(m_db)); sqlite3_busy_handler(m_db, sqlite_busy_call_back, (void*)m_db); } catch (std::out_of_range& e) { HKU_FATAL("Can't get database name! {}", e.what()); close(); throw; - } catch (SQLiteException& e) { + } catch (SQLException& e) { HKU_FATAL("Failed open database: {})! SQLite3 errcode: {}, errmsg: {}", m_dbname, e.errcode(), e.what()); close(); @@ -72,7 +72,7 @@ bool SQLiteConnect::ping() { void SQLiteConnect::exec(const string& sql_string) { int rc = sqlite3_exec(m_db, sql_string.c_str(), NULL, NULL, NULL); - SQLITE_CHECK(rc == SQLITE_OK, rc, "SQL error: {}! ({})", sqlite3_errmsg(m_db), sql_string); + SQL_CHECK(rc == SQLITE_OK, rc, "SQL error: {}! ({})", sqlite3_errmsg(m_db), sql_string); } SQLStatementPtr SQLiteConnect::getStatement(const string& sql_statement) { diff --git a/hikyuu_cpp/hikyuu/utilities/db_connect/sqlite/SQLiteConnect.h b/hikyuu_cpp/hikyuu/utilities/db_connect/sqlite/SQLiteConnect.h index 6efe66be..ace592bf 100644 --- a/hikyuu_cpp/hikyuu/utilities/db_connect/sqlite/SQLiteConnect.h +++ b/hikyuu_cpp/hikyuu/utilities/db_connect/sqlite/SQLiteConnect.h @@ -13,7 +13,6 @@ #include #include "../DBConnectBase.h" #include "SQLiteStatement.h" -#include "SQLiteException.h" namespace hku { diff --git a/hikyuu_cpp/hikyuu/utilities/db_connect/sqlite/SQLiteStatement.cpp b/hikyuu_cpp/hikyuu/utilities/db_connect/sqlite/SQLiteStatement.cpp index 5c710c4e..2ba60dca 100644 --- a/hikyuu_cpp/hikyuu/utilities/db_connect/sqlite/SQLiteStatement.cpp +++ b/hikyuu_cpp/hikyuu/utilities/db_connect/sqlite/SQLiteStatement.cpp @@ -23,8 +23,8 @@ SQLiteStatement::SQLiteStatement(DBConnectBase* driver, const string& sql_statem sqlite3_prepare_v2(m_db, m_sql_string.c_str(), m_sql_string.size() + 1, &m_stmt, NULL); if (status != SQLITE_OK) { sqlite3_finalize(m_stmt); - SQLITE_THROW(status, "Failed prepare sql statement: {}! error msg: {}", m_sql_string, - sqlite3_errmsg(m_db)); + SQL_THROW(status, "Failed prepare sql statement: {}! error msg: {}", m_sql_string, + sqlite3_errmsg(m_db)); } HKU_CHECK(m_stmt != 0, "Invalid SQL statement: {}", m_sql_string); @@ -39,7 +39,7 @@ void SQLiteStatement::_reset() { int status = sqlite3_reset(m_stmt); if (status != SQLITE_OK) { m_step_status = SQLITE_DONE; - SQLITE_THROW(status, sqlite3_errmsg(m_db)); + SQL_THROW(status, sqlite3_errmsg(m_db)); } m_needs_reset = false; m_step_status = SQLITE_DONE; @@ -52,7 +52,7 @@ void SQLiteStatement::sub_exec() { m_step_status = sqlite3_step(m_stmt); m_needs_reset = true; if (m_step_status != SQLITE_DONE && m_step_status != SQLITE_ROW) { - SQLITE_THROW(m_step_status, sqlite3_errmsg(m_db)); + SQL_THROW(m_step_status, sqlite3_errmsg(m_db)); } } @@ -68,7 +68,7 @@ bool SQLiteStatement::sub_moveNext() { } else if (m_step_status == SQLITE_ROW) { return true; } else { - SQLITE_THROW(m_step_status, sqlite3_errmsg(m_db)); + SQL_THROW(m_step_status, sqlite3_errmsg(m_db)); } } } else { @@ -85,31 +85,31 @@ int SQLiteStatement::sub_getNumColumns() const { void SQLiteStatement::sub_bindNull(int idx) { _reset(); int status = sqlite3_bind_null(m_stmt, idx + 1); - SQLITE_CHECK(status == SQLITE_OK, status, sqlite3_errmsg(m_db)); + SQL_CHECK(status == SQLITE_OK, status, sqlite3_errmsg(m_db)); } void SQLiteStatement::sub_bindInt(int idx, int64_t value) { _reset(); int status = sqlite3_bind_int64(m_stmt, idx + 1, value); - SQLITE_CHECK(status == SQLITE_OK, status, sqlite3_errmsg(m_db)); + SQL_CHECK(status == SQLITE_OK, status, sqlite3_errmsg(m_db)); } void SQLiteStatement::sub_bindText(int idx, const string& item) { _reset(); int status = sqlite3_bind_text(m_stmt, idx + 1, item.c_str(), -1, SQLITE_TRANSIENT); - SQLITE_CHECK(status == SQLITE_OK, status, sqlite3_errmsg(m_db)); + SQL_CHECK(status == SQLITE_OK, status, sqlite3_errmsg(m_db)); } void SQLiteStatement::sub_bindDouble(int idx, double item) { _reset(); int status = sqlite3_bind_double(m_stmt, idx + 1, item); - SQLITE_CHECK(status == SQLITE_OK, status, sqlite3_errmsg(m_db)); + SQL_CHECK(status == SQLITE_OK, status, sqlite3_errmsg(m_db)); } void SQLiteStatement::sub_bindBlob(int idx, const string& item) { _reset(); int status = sqlite3_bind_blob(m_stmt, idx + 1, item.data(), item.size(), SQLITE_TRANSIENT); - SQLITE_CHECK(status == SQLITE_OK, status, sqlite3_errmsg(m_db)); + SQL_CHECK(status == SQLITE_OK, status, sqlite3_errmsg(m_db)); } void SQLiteStatement::sub_getColumnAsInt64(int idx, int64_t& item) {