91 lines
2.4 KiB
C++
91 lines
2.4 KiB
C++
|
|
#include "sqlite_statement.h"
|
||
|
|
#include <iostream>
|
||
|
|
|
||
|
|
// Constructor: Prepares the SQL statement
|
||
|
|
SQLiteStatement::SQLiteStatement(sqlite3 *db, const std::string &query)
|
||
|
|
: db_(db), stmt_(nullptr) {
|
||
|
|
if (db == nullptr) {
|
||
|
|
throw std::invalid_argument("Database connection is null");
|
||
|
|
}
|
||
|
|
|
||
|
|
if (sqlite3_prepare_v2(db, query.c_str(), -1, &stmt_, nullptr) != SQLITE_OK) {
|
||
|
|
std::cerr << "Error preparing SQL statement:" << "\"" + query + "\""
|
||
|
|
<< std::endl;
|
||
|
|
std::cerr << "Error message:" << sqlite3_errmsg(db) << std::endl;
|
||
|
|
|
||
|
|
if (stmt_) {
|
||
|
|
sqlite3_finalize(stmt_);
|
||
|
|
}
|
||
|
|
|
||
|
|
throw std::runtime_error("Failed to prepare SQLite statement: " + query);
|
||
|
|
}
|
||
|
|
}
|
||
|
|
|
||
|
|
// Destructor: Finalizes the statement
|
||
|
|
SQLiteStatement::~SQLiteStatement() { finalize(); }
|
||
|
|
|
||
|
|
// Bind integer value
|
||
|
|
bool SQLiteStatement::bind(int index, int value) {
|
||
|
|
return sqlite3_bind_int(stmt_, index, value) == SQLITE_OK;
|
||
|
|
}
|
||
|
|
|
||
|
|
// Bind double value
|
||
|
|
bool SQLiteStatement::bind(int index, double value) {
|
||
|
|
return sqlite3_bind_double(stmt_, index, value) == SQLITE_OK;
|
||
|
|
}
|
||
|
|
|
||
|
|
// Bind text value
|
||
|
|
bool SQLiteStatement::bind(int index, const std::string &value) {
|
||
|
|
return sqlite3_bind_text(stmt_, index, value.c_str(), -1, SQLITE_TRANSIENT) ==
|
||
|
|
SQLITE_OK;
|
||
|
|
}
|
||
|
|
|
||
|
|
// Bind NULL value
|
||
|
|
bool SQLiteStatement::bindNull(int index) {
|
||
|
|
return sqlite3_bind_null(stmt_, index) == SQLITE_OK;
|
||
|
|
}
|
||
|
|
|
||
|
|
// Run the statement
|
||
|
|
// step() returns true if there are more rows
|
||
|
|
bool SQLiteStatement::execute() { return step() == false; }
|
||
|
|
|
||
|
|
// Execute the statement
|
||
|
|
bool SQLiteStatement::step() {
|
||
|
|
int rc = sqlite3_step(stmt_);
|
||
|
|
|
||
|
|
if (rc == SQLITE_ROW) {
|
||
|
|
return true;
|
||
|
|
}
|
||
|
|
if (rc == SQLITE_DONE) {
|
||
|
|
return false;
|
||
|
|
}
|
||
|
|
|
||
|
|
std::cerr << "Failed to step:" << sqlite3_errmsg(db_) << std::endl;
|
||
|
|
return false;
|
||
|
|
}
|
||
|
|
|
||
|
|
// Get the number of rows affected
|
||
|
|
int SQLiteStatement::changes() { return sqlite3_changes(db_); }
|
||
|
|
|
||
|
|
// Reset the statement for re-use
|
||
|
|
void SQLiteStatement::reset() { sqlite3_reset(stmt_); }
|
||
|
|
|
||
|
|
// Finalize and clean up the statement
|
||
|
|
void SQLiteStatement::finalize() {
|
||
|
|
if (stmt_) {
|
||
|
|
sqlite3_finalize(stmt_);
|
||
|
|
stmt_ = nullptr;
|
||
|
|
}
|
||
|
|
}
|
||
|
|
|
||
|
|
// Adapter for sqlite3_column_count
|
||
|
|
int SQLiteStatement::getColumnCount() const {
|
||
|
|
return sqlite3_column_count(stmt_);
|
||
|
|
}
|
||
|
|
|
||
|
|
// Adapter for sqlite3_column_text
|
||
|
|
std::string SQLiteStatement::getColumnText(int column_index) const {
|
||
|
|
const unsigned char *text = sqlite3_column_text(stmt_, column_index);
|
||
|
|
return text ? reinterpret_cast<const char *>(text) : "";
|
||
|
|
}
|