Adding support to get the last inserted row
This commit is contained in:
parent
6e99fc1ab4
commit
539d94e724
@ -33,26 +33,23 @@ namespace sql {
|
||||
class result {
|
||||
public:
|
||||
static result success;
|
||||
result() : result(success) { }
|
||||
result(std::string query, int code, std::string msg) : _code(code), _msg(std::move(msg)), _sql(std::move(query)) { }
|
||||
result(int code, const std::string &msg) : _code(code), _msg(std::move(msg)) { }
|
||||
result(const result& ref) : _code(ref._code), _msg(ref._msg), _sql(ref._sql) { }
|
||||
result(result&& ref) : _code(ref._code), _msg(std::move(ref._msg)), _sql(std::move(ref._sql)) { }
|
||||
virtual ~result() { };
|
||||
|
||||
int code() const { return _code; }
|
||||
std::string msg() const { return _msg; }
|
||||
std::string sql() const { return _sql; }
|
||||
result() : result{success} { }
|
||||
result(std::string query, int code, int64_t last_insert_rowid, std::string msg)
|
||||
: code_{code}, msg_{std::move(msg)}, sql_{std::move(query)}, last_insert_rowid_{last_insert_rowid} { }
|
||||
|
||||
result(const result&) = default;
|
||||
result(result&&) = default;
|
||||
result& operator=(const result&) = default;
|
||||
result& operator=(result&&) = default;
|
||||
|
||||
int code() const { return this->code_; }
|
||||
std::string msg() const { return this->msg_; }
|
||||
std::string sql() const { return this->sql_; }
|
||||
int64_t last_insert_rowid() const { return this->last_insert_rowid_; };
|
||||
|
||||
//Returns true on success
|
||||
operator bool() const { return _code == 0; }
|
||||
|
||||
result&operator=(const result& other) {
|
||||
this->_code = other._code;
|
||||
this->_msg = other._msg;
|
||||
this->_sql = other._sql;
|
||||
return *this;
|
||||
}
|
||||
operator bool() const { return code_ == 0; }
|
||||
|
||||
std::string fmtStr() const {
|
||||
std::stringstream s;
|
||||
@ -60,9 +57,10 @@ namespace sql {
|
||||
return s.str();
|
||||
}
|
||||
private:
|
||||
int _code = 0;
|
||||
std::string _msg{};
|
||||
std::string _sql{};
|
||||
int code_{0};
|
||||
int64_t last_insert_rowid_{0};
|
||||
std::string msg_{};
|
||||
std::string sql_{};
|
||||
};
|
||||
|
||||
enum SqlType {
|
||||
|
@ -26,8 +26,9 @@ MySQLManager::~MySQLManager() {}
|
||||
#define MYSQL_PREFIX "mysql://"
|
||||
inline result parse_url(const string& url, std::map<std::string, std::string>& connect_map) {
|
||||
string target_url;
|
||||
if(url.find(MYSQL_PREFIX) != 0)
|
||||
return {ERROR_MYSQL_INVLID_URL, "Missing mysql:// at begin"};
|
||||
if(url.find(MYSQL_PREFIX) != 0) {
|
||||
return {"", ERROR_MYSQL_INVLID_URL, -1, "Missing mysql:// at begin"};
|
||||
}
|
||||
|
||||
auto index_parms = url.find('?');
|
||||
if(index_parms == string::npos) {
|
||||
@ -184,7 +185,7 @@ result MySQLManager::connect(const std::string &url) {
|
||||
|
||||
if(!parse_mysql_data(url, error, host, port, database, properties)) {
|
||||
error = "URL parsing failed: " + error;
|
||||
return {ERROR_MYSQL_INVLID_URL, error};
|
||||
return {"", ERROR_MYSQL_INVLID_URL, -1, error};
|
||||
}
|
||||
|
||||
size_t connections = 4;
|
||||
@ -192,17 +193,17 @@ result MySQLManager::connect(const std::string &url) {
|
||||
try {
|
||||
connections = stol(properties["connections"]);
|
||||
} catch(std::exception& ex) {
|
||||
return {ERROR_MYSQL_INVLID_PROPERTIES, "could not parse connection count"};
|
||||
return {"", ERROR_MYSQL_INVLID_PROPERTIES, -1, "could not parse connection count"};
|
||||
}
|
||||
}
|
||||
|
||||
string username, password;
|
||||
if(properties.count("userName") > 0) username = properties["userName"];
|
||||
if(properties.count("username") > 0) username = properties["username"];
|
||||
if(username.empty()) return {ERROR_MYSQL_INVLID_PROPERTIES, "missing username property"};
|
||||
if(username.empty()) return {"", ERROR_MYSQL_INVLID_PROPERTIES, -1, "missing username property"};
|
||||
|
||||
if(properties.count("password") > 0) password = properties["password"];
|
||||
if(password.empty()) return {ERROR_MYSQL_INVLID_PROPERTIES, "missing password property"};
|
||||
if(password.empty()) return {"", ERROR_MYSQL_INVLID_PROPERTIES, -1, "missing password property"};
|
||||
|
||||
//debugMessage(LOG_GENERAL, R"([MYSQL] Starting {} connections to {}:{} with database "{}" as user "{}")", connections, host, port, database, username);
|
||||
|
||||
@ -210,7 +211,7 @@ result MySQLManager::connect(const std::string &url) {
|
||||
auto connection = make_shared<Connection>();
|
||||
connection->handle = mysql_init(nullptr);
|
||||
if(!connection->handle)
|
||||
return {-1, "failed to allocate connection " + to_string(index)};
|
||||
return {"", -1, -1, "failed to allocate connection " + to_string(index)};
|
||||
|
||||
{
|
||||
uint32_t reconnect{true};
|
||||
@ -221,7 +222,7 @@ result MySQLManager::connect(const std::string &url) {
|
||||
|
||||
auto result = mysql_real_connect(connection->handle, host.c_str(), username.c_str(), password.c_str(), database.c_str(), port, nullptr, 0); //CLIENT_MULTI_RESULTS | CLIENT_MULTI_STATEMENTS
|
||||
if(!result)
|
||||
return {-1, "failed to connect to server with connection " + to_string(index) + ": " + mysql_error(connection->handle)};
|
||||
return {"", -1, -1, "failed to connect to server with connection " + to_string(index) + ": " + mysql_error(connection->handle)};
|
||||
|
||||
connection->used = false;
|
||||
this->connections.push_back(connection);
|
||||
@ -230,12 +231,12 @@ result MySQLManager::connect(const std::string &url) {
|
||||
}
|
||||
|
||||
bool MySQLManager::connected() {
|
||||
lock_guard<mutex> lock(this->connections_lock);
|
||||
lock_guard<mutex> lock(this->connections_mutex);
|
||||
return !this->connections.empty();
|
||||
}
|
||||
|
||||
result MySQLManager::disconnect() {
|
||||
lock_guard<mutex> lock(this->connections_lock);
|
||||
lock_guard<mutex> lock(this->connections_mutex);
|
||||
this->disconnecting = true;
|
||||
|
||||
this->connections.clear();
|
||||
@ -634,14 +635,14 @@ AcquiredConnection::~AcquiredConnection() {
|
||||
}
|
||||
|
||||
{
|
||||
lock_guard lock(this->owner->connections_lock);
|
||||
lock_guard lock(this->owner->connections_mutex);
|
||||
this->owner->connections_condition.notify_one();
|
||||
}
|
||||
}
|
||||
std::unique_ptr<AcquiredConnection> MySQLManager::next_connection() {
|
||||
unique_ptr<AcquiredConnection> result;
|
||||
{
|
||||
unique_lock connections_lock(this->connections_lock);
|
||||
unique_lock connections_lock(this->connections_mutex);
|
||||
|
||||
while(!result) {
|
||||
size_t available_connections = 0;
|
||||
@ -676,118 +677,136 @@ std::unique_ptr<AcquiredConnection> MySQLManager::next_connection() {
|
||||
}
|
||||
|
||||
void MySQLManager::connection_closed(const std::shared_ptr<sql::mysql::Connection> &connection) {
|
||||
bool call_disconnect = false;
|
||||
bool call_disconnect;
|
||||
{
|
||||
unique_lock connections_lock(this->connections_lock);
|
||||
auto index = find(this->connections.begin(), this->connections.end(), connection);
|
||||
if(index == this->connections.end()) return;
|
||||
unique_lock connections_lock{this->connections_mutex};
|
||||
auto index = std::find(this->connections.begin(), this->connections.end(), connection);
|
||||
if(index == this->connections.end()) {
|
||||
return;
|
||||
}
|
||||
|
||||
this->connections.erase(index);
|
||||
call_disconnect = this->connections.empty();
|
||||
}
|
||||
|
||||
auto dl = this->listener_disconnected;
|
||||
if(call_disconnect && dl)
|
||||
if(call_disconnect && dl) {
|
||||
dl(this->disconnecting);
|
||||
}
|
||||
}
|
||||
|
||||
result MySQLManager::executeCommand(std::shared_ptr<CommandData> _ptr) {
|
||||
auto ptr = static_pointer_cast<MySQLCommand>(_ptr);
|
||||
if(!ptr) { return {-1, "invalid command handle"}; }
|
||||
result MySQLManager::executeCommand(std::shared_ptr<CommandData> command_data) {
|
||||
auto mysql_data = static_pointer_cast<MySQLCommand>(command_data);
|
||||
if(!mysql_data) {
|
||||
return {"", -1, -1, "invalid command handle"};
|
||||
}
|
||||
|
||||
std::lock_guard<threads::Mutex> lock(ptr->lock);
|
||||
auto command = ptr->sql_command;
|
||||
std::lock_guard<threads::Mutex> lock(mysql_data->lock);
|
||||
auto command = mysql_data->sql_command;
|
||||
|
||||
auto variables = ptr->variables;
|
||||
auto variables = mysql_data->variables;
|
||||
vector<variable> mapped_variables;
|
||||
if(!sql::mysql::evaluate_sql_query(command, variables, mapped_variables))
|
||||
return {ptr->sql_command, -1, "Could not map sqlite vars to mysql!"};
|
||||
if(!sql::mysql::evaluate_sql_query(command, variables, mapped_variables)) {
|
||||
return {mysql_data->sql_command, -1, -1, "Could not map sqlite vars to mysql!"};
|
||||
}
|
||||
|
||||
FreeGuard<BindMemory> bind_parameter_memory{nullptr};
|
||||
if(!sql::mysql::create_bind(bind_parameter_memory.ptr, mapped_variables))
|
||||
return {ptr->sql_command, -1, "Failed to allocate bind memory!"};
|
||||
if(!sql::mysql::create_bind(bind_parameter_memory.ptr, mapped_variables)) {
|
||||
return {mysql_data->sql_command, -1, -1, "Failed to allocate bind memory!"};
|
||||
}
|
||||
|
||||
ResultBind bind_result_data{0, nullptr, nullptr};
|
||||
|
||||
auto connection = this->next_connection();
|
||||
if(!connection) return {ptr->sql_command, -1, "Could not get a valid connection!"};
|
||||
if(!connection) {
|
||||
return {mysql_data->sql_command, -1, -1, "Could not get a valid connection!"};
|
||||
}
|
||||
|
||||
StatementGuard stmt_guard{mysql_stmt_init(connection->connection->handle)};
|
||||
if(!stmt_guard.stmt)
|
||||
return {ptr->sql_command, -1, "failed to allocate statement"};
|
||||
if(!stmt_guard.stmt) {
|
||||
return {mysql_data->sql_command, -1, -1, "failed to allocate statement"};
|
||||
}
|
||||
|
||||
if(mysql_stmt_prepare(stmt_guard.stmt, command.c_str(), command.length())) {
|
||||
auto errc = mysql_stmt_errno(stmt_guard.stmt);
|
||||
if(errc == CR_SERVER_GONE_ERROR || errc == CR_SERVER_LOST || errc == CR_CONNECTION_ERROR)
|
||||
if(errc == CR_SERVER_GONE_ERROR || errc == CR_SERVER_LOST || errc == CR_CONNECTION_ERROR) {
|
||||
this->connection_closed(connection->connection);
|
||||
}
|
||||
|
||||
return {ptr->sql_command, -1, "failed to prepare statement: " + string(mysql_stmt_error(stmt_guard.stmt))};
|
||||
return {mysql_data->sql_command, -1, -1, "failed to prepare statement: " + string(mysql_stmt_error(stmt_guard.stmt))};
|
||||
}
|
||||
|
||||
/* validate all parameters */
|
||||
auto parameter_count = mysql_stmt_param_count(stmt_guard.stmt);
|
||||
if(parameter_count != mapped_variables.size())
|
||||
return {ptr->sql_command, -1, "invalid parameter count. Statement contains " + to_string(parameter_count) + " parameters but only " + to_string(mapped_variables.size()) + " are given."};
|
||||
if(parameter_count != mapped_variables.size()) {
|
||||
return {mysql_data->sql_command, -1, -1, "invalid parameter count. Statement contains " + to_string(parameter_count) + " parameters but only " + to_string(mapped_variables.size()) + " are given."};
|
||||
}
|
||||
|
||||
if(bind_parameter_memory.ptr) {
|
||||
if(mysql_stmt_bind_param(stmt_guard.stmt, (MYSQL_BIND*) bind_parameter_memory.ptr))
|
||||
return {ptr->sql_command, -1, "failed to bind parameters to statement: " + string(mysql_stmt_error(stmt_guard.stmt))};
|
||||
} else if(parameter_count > 0)
|
||||
return {ptr->sql_command, -1, "invalid parameter count. Statement contains " + to_string(parameter_count) + " parameters but only " + to_string(mapped_variables.size()) + " are given (bind nullptr)."};
|
||||
if(mysql_stmt_bind_param(stmt_guard.stmt, (MYSQL_BIND*) bind_parameter_memory.ptr)) {
|
||||
return {mysql_data->sql_command, -1, -1, "failed to bind parameters to statement: " + string(mysql_stmt_error(stmt_guard.stmt))};
|
||||
}
|
||||
} else if(parameter_count > 0) {
|
||||
return {mysql_data->sql_command, -1, -1, "invalid parameter count. Statement contains " + to_string(parameter_count) + " parameters but only " + to_string(mapped_variables.size()) + " are given (bind nullptr)."};
|
||||
}
|
||||
|
||||
|
||||
if(mysql_stmt_execute(stmt_guard.stmt)) {
|
||||
auto errc = mysql_stmt_errno(stmt_guard.stmt);
|
||||
if(errc == CR_SERVER_GONE_ERROR || errc == CR_SERVER_LOST || errc == CR_CONNECTION_ERROR)
|
||||
if(errc == CR_SERVER_GONE_ERROR || errc == CR_SERVER_LOST || errc == CR_CONNECTION_ERROR) {
|
||||
this->connection_closed(connection->connection);
|
||||
|
||||
return {ptr->sql_command, -1, "failed to execute query statement: " + string(mysql_stmt_error(stmt_guard.stmt))};
|
||||
}
|
||||
|
||||
return result::success;
|
||||
return {mysql_data->sql_command, -1, -1, "failed to execute query statement: " + string(mysql_stmt_error(stmt_guard.stmt))};
|
||||
}
|
||||
|
||||
result MySQLManager::queryCommand(shared_ptr<CommandData> _ptr, const QueryCallback &fn) {
|
||||
auto ptr = static_pointer_cast<MySQLCommand>(_ptr);
|
||||
if(!ptr) { return {-1, "invalid command handle"}; }
|
||||
auto insert_row_id = mysql_stmt_insert_id(stmt_guard.stmt);
|
||||
return {mysql_data->sql_command, 0, (int64_t) insert_row_id, "success"};
|
||||
}
|
||||
|
||||
std::lock_guard<threads::Mutex> lock(ptr->lock);
|
||||
auto command = ptr->sql_command;
|
||||
result MySQLManager::queryCommand(shared_ptr<CommandData> command_data, const QueryCallback &fn) {
|
||||
auto mysql_data = static_pointer_cast<MySQLCommand>(command_data);
|
||||
if(!mysql_data) {
|
||||
return {"", -1, -1, "invalid command handle"};
|
||||
}
|
||||
|
||||
auto variables = ptr->variables;
|
||||
std::lock_guard<threads::Mutex> lock(mysql_data->lock);
|
||||
auto command = mysql_data->sql_command;
|
||||
|
||||
auto variables = mysql_data->variables;
|
||||
vector<variable> mapped_variables;
|
||||
if(!sql::mysql::evaluate_sql_query(command, variables, mapped_variables)) return {ptr->sql_command, -1, "Could not map sqlite vars to mysql!"};
|
||||
if(!sql::mysql::evaluate_sql_query(command, variables, mapped_variables)) return {mysql_data->sql_command, -1, -1, "Could not map sqlite vars to mysql!"};
|
||||
|
||||
FreeGuard<BindMemory> bind_parameter_memory{nullptr};
|
||||
if(!sql::mysql::create_bind(bind_parameter_memory.ptr, mapped_variables)) return {ptr->sql_command, -1, "Failed to allocate bind memory!"};
|
||||
if(!sql::mysql::create_bind(bind_parameter_memory.ptr, mapped_variables)) return {mysql_data->sql_command, -1, -1, "Failed to allocate bind memory!"};
|
||||
|
||||
ResultBind bind_result_data{0, nullptr, nullptr};
|
||||
|
||||
auto connection = this->next_connection();
|
||||
if(!connection) return {ptr->sql_command, -1, "Could not get a valid connection!"};
|
||||
if(!connection) return {mysql_data->sql_command, -1, -1, "Could not get a valid connection!"};
|
||||
|
||||
StatementGuard stmt_guard{mysql_stmt_init(connection->connection->handle)};
|
||||
if(!stmt_guard.stmt)
|
||||
return {ptr->sql_command, -1, "failed to allocate statement"};
|
||||
return {mysql_data->sql_command, -1, -1, "failed to allocate statement"};
|
||||
|
||||
if(mysql_stmt_prepare(stmt_guard.stmt, command.c_str(), command.length())) {
|
||||
auto errc = mysql_stmt_errno(stmt_guard.stmt);
|
||||
if(errc == CR_SERVER_GONE_ERROR || errc == CR_SERVER_LOST || errc == CR_CONNECTION_ERROR)
|
||||
this->connection_closed(connection->connection);
|
||||
|
||||
return {ptr->sql_command, -1, "failed to prepare statement: " + string(mysql_stmt_error(stmt_guard.stmt))};
|
||||
return {mysql_data->sql_command, -1, -1, "failed to prepare statement: " + string(mysql_stmt_error(stmt_guard.stmt))};
|
||||
}
|
||||
|
||||
/* validate all parameters */
|
||||
{
|
||||
auto parameter_count = mysql_stmt_param_count(stmt_guard.stmt);
|
||||
if(parameter_count != mapped_variables.size())
|
||||
return {ptr->sql_command, -1, "invalid parameter count. Statement contains " + to_string(parameter_count) + " parameters but only " + to_string(mapped_variables.size()) + " are given."};
|
||||
return {mysql_data->sql_command, -1, -1, "invalid parameter count. Statement contains " + to_string(parameter_count) + " parameters but only " + to_string(mapped_variables.size()) + " are given."};
|
||||
}
|
||||
|
||||
if(bind_parameter_memory.ptr) {
|
||||
if(mysql_stmt_bind_param(stmt_guard.stmt, (MYSQL_BIND*) bind_parameter_memory.ptr))
|
||||
return {ptr->sql_command, -1, "failed to bind parameters to statement: " + string(mysql_stmt_error(stmt_guard.stmt))};
|
||||
return {mysql_data->sql_command, -1, -1, "failed to bind parameters to statement: " + string(mysql_stmt_error(stmt_guard.stmt))};
|
||||
}
|
||||
|
||||
if(mysql_stmt_execute(stmt_guard.stmt)) {
|
||||
@ -795,7 +814,7 @@ result MySQLManager::queryCommand(shared_ptr<CommandData> _ptr, const QueryCallb
|
||||
if(errc == CR_SERVER_GONE_ERROR || errc == CR_SERVER_LOST || errc == CR_CONNECTION_ERROR)
|
||||
this->connection_closed(connection->connection);
|
||||
|
||||
return {ptr->sql_command, -1, "failed to execute query statement: " + string(mysql_stmt_error(stmt_guard.stmt))};
|
||||
return {mysql_data->sql_command, -1, -1, "failed to execute query statement: " + string(mysql_stmt_error(stmt_guard.stmt))};
|
||||
}
|
||||
|
||||
//if(mysql_stmt_store_result(stmt_guard.stmt))
|
||||
@ -803,7 +822,7 @@ result MySQLManager::queryCommand(shared_ptr<CommandData> _ptr, const QueryCallb
|
||||
|
||||
ResultGuard result_guard{mysql_stmt_result_metadata(stmt_guard.stmt)};
|
||||
if(!result_guard.result)
|
||||
return {ptr->sql_command, -1, "failed to query result metadata: " + string(mysql_stmt_error(stmt_guard.stmt))};
|
||||
return {mysql_data->sql_command, -1, -1, "failed to query result metadata: " + string(mysql_stmt_error(stmt_guard.stmt))};
|
||||
|
||||
|
||||
auto field_count = mysql_num_fields(result_guard.result);
|
||||
@ -813,13 +832,13 @@ result MySQLManager::queryCommand(shared_ptr<CommandData> _ptr, const QueryCallb
|
||||
{
|
||||
auto field_meta = mysql_fetch_fields(result_guard.result);
|
||||
if(!field_meta && field_count > 0)
|
||||
return {ptr->sql_command, -1, "failed to fetch field meta"};
|
||||
return {mysql_data->sql_command, -1, -1, "failed to fetch field meta"};
|
||||
|
||||
if(!sql::mysql::create_result_bind(field_count, field_meta, bind_result_data))
|
||||
return {ptr->sql_command, -1, "failed to allocate result buffer"};
|
||||
return {mysql_data->sql_command, -1, -1, "failed to allocate result buffer"};
|
||||
|
||||
if(mysql_stmt_bind_result(stmt_guard.stmt, (MYSQL_BIND*) bind_result_data.memory))
|
||||
return {ptr->sql_command, -1, "failed to bind response buffer to statement: " + string(mysql_stmt_error(stmt_guard.stmt))};
|
||||
return {mysql_data->sql_command, -1, -1, "failed to bind response buffer to statement: " + string(mysql_stmt_error(stmt_guard.stmt))};
|
||||
|
||||
for(size_t index = 0; index < field_count; index++) {
|
||||
field_names.ptr[index] = field_meta[index].name; // field_meta cant be null because it has been checked above
|
||||
@ -846,11 +865,11 @@ result MySQLManager::queryCommand(shared_ptr<CommandData> _ptr, const QueryCallb
|
||||
if(errc == CR_SERVER_GONE_ERROR || errc == CR_SERVER_LOST || errc == CR_CONNECTION_ERROR)
|
||||
this->connection_closed(connection->connection);
|
||||
|
||||
return {ptr->sql_command, -1, "failed to fetch response row " + to_string(row_id) + ": " + string(mysql_stmt_error(stmt_guard.stmt))};
|
||||
return {mysql_data->sql_command, -1, -1, "failed to fetch response row " + to_string(row_id) + ": " + string(mysql_stmt_error(stmt_guard.stmt))};
|
||||
} else if(stmt_code == MYSQL_NO_DATA)
|
||||
;
|
||||
else if(stmt_code == MYSQL_DATA_TRUNCATED)
|
||||
return {ptr->sql_command, -1, "response data has been truncated"};
|
||||
return {mysql_data->sql_command, -1, -1, "response data has been truncated"};
|
||||
}
|
||||
return result::success;
|
||||
}
|
@ -65,17 +65,17 @@ namespace sql::mysql {
|
||||
protected:
|
||||
std::shared_ptr<CommandData> copyCommandData(std::shared_ptr<CommandData> ptr) override;
|
||||
std::shared_ptr<CommandData> allocateCommandData() override;
|
||||
result executeCommand(std::shared_ptr<CommandData> ptr) override;
|
||||
result queryCommand(std::shared_ptr<CommandData> ptr, const QueryCallback &fn) override;
|
||||
result executeCommand(std::shared_ptr<CommandData> command_data) override;
|
||||
result queryCommand(std::shared_ptr<CommandData> command_data, const QueryCallback &fn) override;
|
||||
|
||||
public:
|
||||
std::unique_ptr<AcquiredConnection> next_connection();
|
||||
void connection_closed(const std::shared_ptr<Connection>& /* connection */);
|
||||
|
||||
std::mutex connections_lock;
|
||||
std::mutex connections_mutex;
|
||||
std::condition_variable connections_condition;
|
||||
std::deque<std::shared_ptr<Connection>> connections;
|
||||
|
||||
bool disconnecting = false;
|
||||
bool disconnecting{false};
|
||||
};
|
||||
}
|
@ -17,7 +17,7 @@ result SqliteManager::connect(const std::string &string) {
|
||||
|
||||
auto result = sqlite3_open(url.c_str(), &this->database);
|
||||
if(!this->database)
|
||||
return {"connect", -1, "could not open database. Code: " + to_string(result)};
|
||||
return {"connect", -1, -1, "could not open database. Code: " + to_string(result)};
|
||||
return result::success;
|
||||
}
|
||||
|
||||
@ -26,15 +26,17 @@ bool SqliteManager::connected() {
|
||||
}
|
||||
|
||||
result SqliteManager::disconnect() {
|
||||
if(!this->database)
|
||||
return {"disconnect", -1, "database not open"};
|
||||
if(!this->database) {
|
||||
return {"disconnect", -1, -1, "database not open"};
|
||||
}
|
||||
|
||||
this->pool->threads()->wait_for();
|
||||
auto result = sqlite3_close(this->database);
|
||||
if(result == 0) {
|
||||
this->database = nullptr;
|
||||
return result::success;
|
||||
};
|
||||
return {"disconnect", -1, "Failed to close database. Code: " + to_string(result)};
|
||||
return {"disconnect", -1, -1, "Failed to close database. Code: " + to_string(result)};
|
||||
}
|
||||
|
||||
std::shared_ptr<CommandData> SqliteManager::allocateCommandData() {
|
||||
@ -104,8 +106,9 @@ result SqliteManager::queryCommand(std::shared_ptr<CommandData> _ptr, const Quer
|
||||
sqlite3_reset(stmt.get());
|
||||
} else {
|
||||
ptr->stmt = this->allocateStatement(ptr->sql_command);
|
||||
if(!ptr->stmt)
|
||||
return {_ptr->sql_command,1, sqlite3_errmsg(ptr->sqlHandle<SqliteManager>()->database)};
|
||||
if(!ptr->stmt) {
|
||||
return {_ptr->sql_command, 1, -1, sqlite3_errmsg(ptr->sqlHandle<SqliteManager>()->database)};
|
||||
}
|
||||
stmt = ptr->stmt;
|
||||
}
|
||||
|
||||
@ -135,35 +138,42 @@ result SqliteManager::queryCommand(std::shared_ptr<CommandData> _ptr, const Quer
|
||||
}
|
||||
}
|
||||
|
||||
if(result != SQLITE_DONE && !userQuit) return {_ptr->sql_command,result, sqlite3_errstr(result)};
|
||||
return {_ptr->sql_command,0, "success"};
|
||||
if(result != SQLITE_DONE && !userQuit) {
|
||||
return {_ptr->sql_command, result, -1, sqlite3_errstr(result)};
|
||||
}
|
||||
return {_ptr->sql_command,0, 0, "success"};
|
||||
}
|
||||
|
||||
result SqliteManager::executeCommand(std::shared_ptr<CommandData> _ptr) {
|
||||
auto ptr = static_pointer_cast<SqliteCommand>(_ptr);
|
||||
std::lock_guard<threads::Mutex> lock(ptr->lock);
|
||||
result SqliteManager::executeCommand(std::shared_ptr<CommandData> command_data) {
|
||||
auto sql_command = static_pointer_cast<SqliteCommand>(command_data);
|
||||
std::lock_guard<threads::Mutex> lock(sql_command->lock);
|
||||
|
||||
result res;
|
||||
sqlite3_stmt* stmt;
|
||||
if(ptr->stmt){
|
||||
stmt = ptr->stmt.get();
|
||||
result res{};
|
||||
sqlite3_stmt* stmt{};
|
||||
if(sql_command->stmt){
|
||||
stmt = sql_command->stmt.get();
|
||||
sqlite3_reset(stmt);
|
||||
} else {
|
||||
ptr->stmt = this->allocateStatement(ptr->sql_command);
|
||||
if(!ptr->stmt)
|
||||
return {_ptr->sql_command,1, sqlite3_errmsg(ptr->sqlHandle<SqliteManager>()->database)};
|
||||
stmt = ptr->stmt.get();
|
||||
sql_command->stmt = this->allocateStatement(sql_command->sql_command);
|
||||
if(!sql_command->stmt) {
|
||||
return {sql_command->sql_command, 1, -1, sqlite3_errmsg(sql_command->sqlHandle<SqliteManager>()->database)};
|
||||
}
|
||||
stmt = sql_command->stmt.get();
|
||||
}
|
||||
|
||||
int varIndex = 0;
|
||||
for(const auto& var : ptr->variables)
|
||||
bindVariable(stmt, varIndex, var);
|
||||
int variable_index{0};
|
||||
for(const auto& var : sql_command->variables) {
|
||||
bindVariable(stmt, variable_index, var);
|
||||
}
|
||||
|
||||
int result = sqlite3_step(stmt);
|
||||
|
||||
//logCritical(0, "Changes: {} SQL: {}", sqlite3_changes(this->database), ptr->sql_command);
|
||||
if(result == SQLITE_DONE)
|
||||
return {_ptr->sql_command,0, "success"};
|
||||
if(result == SQLITE_ROW) return {_ptr->sql_command,-1, "query has a result"};
|
||||
return {_ptr->sql_command, 1, sqlite3_errstr(result)};
|
||||
if(result == SQLITE_DONE) {
|
||||
auto last_row = sqlite3_last_insert_rowid(this->database);
|
||||
return {sql_command->sql_command, 0, last_row, "success"};
|
||||
} else if(result == SQLITE_ROW) {
|
||||
return {sql_command->sql_command, -1, -1, "query has a result"};
|
||||
} else {
|
||||
return {sql_command->sql_command, 1, -1, sqlite3_errstr(result)};
|
||||
}
|
||||
}
|
@ -21,7 +21,7 @@ namespace sql {
|
||||
protected:
|
||||
std::shared_ptr<CommandData> copyCommandData(std::shared_ptr<CommandData> ptr) override;
|
||||
std::shared_ptr<CommandData> allocateCommandData() override;
|
||||
result executeCommand(std::shared_ptr<CommandData> ptr) override;
|
||||
result executeCommand(std::shared_ptr<CommandData> command_data) override;
|
||||
result queryCommand(std::shared_ptr<CommandData> ptr, const QueryCallback&fn) override;
|
||||
|
||||
private:
|
||||
|
Loading…
x
Reference in New Issue
Block a user