统一SQLException

This commit is contained in:
fasiondog 2021-06-30 02:01:16 +08:00
parent 55d5f7cdc1
commit f04c8dbec3
10 changed files with 81 additions and 103 deletions

View File

@ -11,6 +11,7 @@
#define HIKYUU_DB_CONNECT_H #define HIKYUU_DB_CONNECT_H
#include "DBConnectBase.h" #include "DBConnectBase.h"
#include "SQLException.h"
#include "DBCondition.h" #include "DBCondition.h"
#include "SQLStatementBase.h" #include "SQLStatementBase.h"
#include "TransAction.h" #include "TransAction.h"

View File

@ -14,6 +14,7 @@
#include "../../utilities/Parameter.h" #include "../../utilities/Parameter.h"
#include "DBCondition.h" #include "DBCondition.h"
#include "SQLStatementBase.h" #include "SQLStatementBase.h"
#include "SQLException.h"
namespace hku { namespace hku {
@ -275,6 +276,13 @@ void DBConnectBase::save(T& item, bool autotrans) {
if (autotrans) { if (autotrans) {
commit(); commit();
} }
} catch (hku::SQLException& e) {
if (autotrans) {
rollback();
}
SQL_THROW(e.errcode(), "failed save! sql: {}! {}", st->getSqlString(), e.what());
} catch (std::exception& e) { } catch (std::exception& e) {
if (autotrans) { if (autotrans) {
rollback(); rollback();
@ -312,6 +320,12 @@ void DBConnectBase::batchSave(InputIterator first, InputIterator last, bool auto
commit(); commit();
} }
} catch (hku::SQLException& e) {
if (autotrans) {
rollback();
}
SQL_THROW(e.errcode(), "failed batch save! sql: {}! {}", st->getSqlString(), e.what());
} catch (std::exception& e) { } catch (std::exception& e) {
if (autotrans) { if (autotrans) {
rollback(); rollback();
@ -390,11 +404,17 @@ void DBConnectBase::batchUpdate(InputIterator first, InputIterator last, bool au
commit(); commit();
} }
} catch (hku::SQLException& e) {
if (autotrans) {
rollback();
}
SQL_THROW(e.errcode(), "failed batch update! sql: {}! {}", st->getSqlString(), e.what());
} catch (std::exception& e) { } catch (std::exception& e) {
if (autotrans) { if (autotrans) {
rollback(); rollback();
} }
HKU_THROW("failed batch save! sql: {}! {}", st->getSqlString(), e.what()); HKU_THROW("failed batch update! sql: {}! {}", st->getSqlString(), e.what());
} catch (...) { } catch (...) {
if (autotrans) { if (autotrans) {
@ -439,6 +459,13 @@ void DBConnectBase::remove(T& item, bool autotrans) {
if (autotrans) { if (autotrans) {
commit(); commit();
} }
} catch (hku::SQLException& e) {
if (autotrans) {
rollback();
}
SQL_THROW(e.errcode(), "failed delete! sql: {}! {}", st->getSqlString(), e.what());
} catch (std::exception& e) { } catch (std::exception& e) {
if (autotrans) { if (autotrans) {
rollback(); rollback();
@ -472,6 +499,13 @@ void DBConnectBase::batchRemove(InputIterator first, InputIterator last, bool au
if (autotrans) { if (autotrans) {
commit(); commit();
} }
} catch (hku::SQLException& e) {
if (autotrans) {
rollback();
}
SQL_THROW(e.errcode(), "failed batch delete! {}", e.what());
} catch (std::exception& e) { } catch (std::exception& e) {
if (autotrans) { if (autotrans) {
rollback(); rollback();
@ -496,11 +530,16 @@ inline void DBConnectBase::remove(const std::string& tablename, const std::strin
try { try {
exec(sql); exec(sql);
} catch (hku::SQLException& e) {
if (autotrans) {
rollback();
}
SQL_THROW(e.errcode(), "Failed exec sql: {}! {}", sql, e.what());
} catch (std::exception& e) { } catch (std::exception& e) {
if (autotrans) { if (autotrans) {
rollback(); rollback();
} }
HKU_THROW(R"(Failed exec sql: {}! {})", sql, e.what()); HKU_THROW("Failed exec sql: {}! {}", sql, e.what());
} catch (...) { } catch (...) {
if (autotrans) { if (autotrans) {
rollback(); rollback();

View File

@ -12,25 +12,24 @@
namespace hku { namespace hku {
/** SQLite 处理异常 */ /** SQL 数据库引擎处理异常 */
class SQLiteException : public hku::exception { class SQLException : public hku::exception {
public: public:
SQLiteException() = delete; SQLException() = delete;
/** /**
* SQLite * SQLite
* @param errcode SQLite错误码 * @param errcode SQLite错误码
* @param msg SQLite错误信息 * @param msg SQLite错误信息
*/ */
SQLiteException(int errcode, const std::string& msg) SQLException(int errcode, const std::string& msg) : hku::exception(msg), m_errcode(errcode) {}
: hku::exception(msg), m_errcode(errcode) {}
/** /**
* SQLite * SQLite
* @param errcode SQLite错误码 * @param errcode SQLite错误码
* @param msg 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 错误码 */ /** 获取 SQLite 错误码 */
int errcode() const { int errcode() const {
@ -41,20 +40,20 @@ private:
int m_errcode; int m_errcode;
}; };
#define SQLITE_CHECK(expr, errcode, ...) \ #define SQL_CHECK(expr, errcode, ...) \
do { \ do { \
if (!(expr)) { \ if (!(expr)) { \
throw SQLiteException( \ throw SQLException( \
errcode, fmt::format("CHECK({}) {} [{}] ({}:{})", #expr, fmt::format(__VA_ARGS__), \ errcode, fmt::format("CHECK({}) {} [{}] ({}:{})", #expr, fmt::format(__VA_ARGS__), \
__FUNCTION__, __FILE__, __LINE__)); \ __FUNCTION__, __FILE__, __LINE__)); \
} \ } \
} while (0) } while (0)
#define SQLITE_THROW(errcode, ...) \ #define SQL_THROW(errcode, ...) \
do { \ do { \
throw SQLiteException(errcode, \ throw SQLException(errcode, \
fmt::format("EXCEPTION: {} [{}] ({}:{})", fmt::format(__VA_ARGS__), \ fmt::format("EXCEPTION: {} [{}] ({}:{})", fmt::format(__VA_ARGS__), \
__FUNCTION__, __FILE__, __LINE__)); \ __FUNCTION__, __FILE__, __LINE__)); \
} while (0) } while (0)
} // namespace hku } // namespace hku

View File

@ -73,14 +73,14 @@ void MySQLConnect::exec(const string& sql_string) {
if (ping()) { if (ping()) {
ret = mysql_query(m_mysql, sql_string.c_str()); ret = mysql_query(m_mysql, sql_string.c_str());
} else { } else {
MYSQL_THROW(ret, "SQL error{}! error code{}, error msg: {}", sql_string, ret, SQL_THROW(ret, "SQL error{}! error code{}, error msg: {}", sql_string, ret,
mysql_error(m_mysql)); mysql_error(m_mysql));
} }
} }
if (ret) { if (ret) {
MYSQL_THROW(ret, "SQL error{}! error code{}, error msg: {}", sql_string, ret, SQL_THROW(ret, "SQL error{}! error code{}, error msg: {}", sql_string, ret,
mysql_error(m_mysql)); mysql_error(m_mysql));
} }
do { do {
@ -98,8 +98,8 @@ void MySQLConnect::exec(const string& sql_string) {
HKU_TRACE("num_rows: {}", num_rows); HKU_TRACE("num_rows: {}", num_rows);
#endif #endif
} else { } else {
MYSQL_THROW(ret, "mysql_field_count error{}! error code{}, error msg: {}", SQL_THROW(ret, "mysql_field_count error{}! error code{}, error msg: {}",
sql_string, ret, mysql_error(m_mysql)); sql_string, ret, mysql_error(m_mysql));
} }
} }
} while (!mysql_next_result(m_mysql)); } while (!mysql_next_result(m_mysql));

View File

@ -13,7 +13,6 @@
#include "../DBConnectBase.h" #include "../DBConnectBase.h"
#include "MySQLStatement.h" #include "MySQLStatement.h"
#include "MySQLException.h"
#if defined(_MSC_VER) #if defined(_MSC_VER)
#include <mysql.h> #include <mysql.h>

View File

@ -1,59 +0,0 @@
/*
* Copyright(C) 2021 hikyuu.org
*
* Create on: 2021-06-26
* Author: fasiondog
*/
#pragma once
#include <fmt/format.h>
#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

View File

@ -26,8 +26,8 @@ MySQLStatement::MySQLStatement(DBConnectBase* driver, const string& sql_statemen
std::string stmt_errorstr(mysql_stmt_error(m_stmt)); std::string stmt_errorstr(mysql_stmt_error(m_stmt));
mysql_stmt_close(m_stmt); mysql_stmt_close(m_stmt);
m_stmt = nullptr; m_stmt = nullptr;
MYSQL_THROW(ret, "Failed prepare sql statement: {}! error msg: {}!", sql_statement, SQL_THROW(ret, "Failed prepare sql statement: {}! error msg: {}!", sql_statement,
stmt_errorstr); stmt_errorstr);
} }
auto param_count = mysql_stmt_param_count(m_stmt); auto param_count = mysql_stmt_param_count(m_stmt);
@ -57,7 +57,7 @@ MySQLStatement::~MySQLStatement() {
void MySQLStatement::_reset() { void MySQLStatement::_reset() {
if (m_needs_reset) { if (m_needs_reset) {
int ret = mysql_stmt_reset(m_stmt); 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_param_bind.clear();
// m_result_bind.clear(); // m_result_bind.clear();
// m_param_buffer.clear(); // m_param_buffer.clear();
@ -73,10 +73,10 @@ void MySQLStatement::sub_exec() {
int ret = 0; int ret = 0;
if (m_param_bind.size() > 0) { if (m_param_bind.size() > 0) {
ret = mysql_stmt_bind_param(m_stmt, m_param_bind.data()); 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); 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() { void MySQLStatement::_bindResult() {
@ -148,17 +148,17 @@ bool MySQLStatement::sub_moveNext() {
m_has_bind_result = true; m_has_bind_result = true;
ret = mysql_stmt_bind_result(m_stmt, m_result_bind.data()); 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); 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); ret = mysql_stmt_fetch(m_stmt);
if (ret == 0) { if (ret == 0) {
return true; return true;
} else if (ret == 1) { } 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; return false;
} }

View File

@ -32,14 +32,14 @@ SQLiteConnect::SQLiteConnect(const Parameter& param) : DBConnectBase(param), m_d
flags = getParam<int>("flags"); flags = getParam<int>("flags");
} }
int rc = sqlite3_open_v2(m_dbname.c_str(), &m_db, flags, NULL); 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); sqlite3_busy_handler(m_db, sqlite_busy_call_back, (void*)m_db);
} catch (std::out_of_range& e) { } catch (std::out_of_range& e) {
HKU_FATAL("Can't get database name! {}", e.what()); HKU_FATAL("Can't get database name! {}", e.what());
close(); close();
throw; throw;
} catch (SQLiteException& e) { } catch (SQLException& e) {
HKU_FATAL("Failed open database: {})! SQLite3 errcode: {}, errmsg: {}", m_dbname, HKU_FATAL("Failed open database: {})! SQLite3 errcode: {}, errmsg: {}", m_dbname,
e.errcode(), e.what()); e.errcode(), e.what());
close(); close();
@ -72,7 +72,7 @@ bool SQLiteConnect::ping() {
void SQLiteConnect::exec(const string& sql_string) { void SQLiteConnect::exec(const string& sql_string) {
int rc = sqlite3_exec(m_db, sql_string.c_str(), NULL, NULL, NULL); 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) { SQLStatementPtr SQLiteConnect::getStatement(const string& sql_statement) {

View File

@ -13,7 +13,6 @@
#include <sqlite3.h> #include <sqlite3.h>
#include "../DBConnectBase.h" #include "../DBConnectBase.h"
#include "SQLiteStatement.h" #include "SQLiteStatement.h"
#include "SQLiteException.h"
namespace hku { namespace hku {

View File

@ -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); sqlite3_prepare_v2(m_db, m_sql_string.c_str(), m_sql_string.size() + 1, &m_stmt, NULL);
if (status != SQLITE_OK) { if (status != SQLITE_OK) {
sqlite3_finalize(m_stmt); sqlite3_finalize(m_stmt);
SQLITE_THROW(status, "Failed prepare sql statement: {}! error msg: {}", m_sql_string, SQL_THROW(status, "Failed prepare sql statement: {}! error msg: {}", m_sql_string,
sqlite3_errmsg(m_db)); sqlite3_errmsg(m_db));
} }
HKU_CHECK(m_stmt != 0, "Invalid SQL statement: {}", m_sql_string); HKU_CHECK(m_stmt != 0, "Invalid SQL statement: {}", m_sql_string);
@ -39,7 +39,7 @@ void SQLiteStatement::_reset() {
int status = sqlite3_reset(m_stmt); int status = sqlite3_reset(m_stmt);
if (status != SQLITE_OK) { if (status != SQLITE_OK) {
m_step_status = SQLITE_DONE; m_step_status = SQLITE_DONE;
SQLITE_THROW(status, sqlite3_errmsg(m_db)); SQL_THROW(status, sqlite3_errmsg(m_db));
} }
m_needs_reset = false; m_needs_reset = false;
m_step_status = SQLITE_DONE; m_step_status = SQLITE_DONE;
@ -52,7 +52,7 @@ void SQLiteStatement::sub_exec() {
m_step_status = sqlite3_step(m_stmt); m_step_status = sqlite3_step(m_stmt);
m_needs_reset = true; m_needs_reset = true;
if (m_step_status != SQLITE_DONE && m_step_status != SQLITE_ROW) { 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) { } else if (m_step_status == SQLITE_ROW) {
return true; return true;
} else { } else {
SQLITE_THROW(m_step_status, sqlite3_errmsg(m_db)); SQL_THROW(m_step_status, sqlite3_errmsg(m_db));
} }
} }
} else { } else {
@ -85,31 +85,31 @@ int SQLiteStatement::sub_getNumColumns() const {
void SQLiteStatement::sub_bindNull(int idx) { void SQLiteStatement::sub_bindNull(int idx) {
_reset(); _reset();
int status = sqlite3_bind_null(m_stmt, idx + 1); 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) { void SQLiteStatement::sub_bindInt(int idx, int64_t value) {
_reset(); _reset();
int status = sqlite3_bind_int64(m_stmt, idx + 1, value); 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) { void SQLiteStatement::sub_bindText(int idx, const string& item) {
_reset(); _reset();
int status = sqlite3_bind_text(m_stmt, idx + 1, item.c_str(), -1, SQLITE_TRANSIENT); 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) { void SQLiteStatement::sub_bindDouble(int idx, double item) {
_reset(); _reset();
int status = sqlite3_bind_double(m_stmt, idx + 1, item); 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) { void SQLiteStatement::sub_bindBlob(int idx, const string& item) {
_reset(); _reset();
int status = sqlite3_bind_blob(m_stmt, idx + 1, item.data(), item.size(), SQLITE_TRANSIENT); 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) { void SQLiteStatement::sub_getColumnAsInt64(int idx, int64_t& item) {