Go to the documentation of this file.00001
00002
00003
00004
00005
00006
00007
00008 #include "Statement.h"
00009 #include "SqliteException.h"
00010 #include "InvalidUseException.h"
00011 #include <utility>
00012 #include <tuple>
00013
00014 namespace sqlite
00015 {
00016
00017 Statement::Statement():
00018 stmt(NULL),
00019 db(NULL),
00020 cols(0),
00021 hrow(false),
00022 dn(false)
00023 {
00024 }
00025
00026 Statement::Statement(const std::string& sql, Database& db):
00027 stmt(NULL),
00028 db(&db),
00029 hrow(false),
00030 dn(false)
00031 {
00032 const char* a;
00033 throw_sqlite_status(sqlite3_prepare_v2(db.cobj(), sql.c_str(), -1, &stmt, &a), db.cobj());
00034 if (stmt == NULL)
00035 {
00036 cols = 0;
00037 }
00038 else
00039 {
00040 cols = sqlite3_column_count(stmt);
00041 db.register_statement(*this);
00042 }
00043 }
00044
00045 Statement::~Statement()
00046 {
00047 finalize();
00048 }
00049
00050 Statement& Statement::operator =(Statement && other)
00051 {
00052 finalize();
00053 stmt = other.stmt;
00054 dn = other.dn;
00055 hrow = other.hrow;
00056 db = other.db;
00057 cols = other.cols;
00058 db->unregister_statement(other);
00059 other.stmt = NULL;
00060 if (stmt != NULL)
00061 db->register_statement(*this);
00062 return *this;
00063 }
00064
00065 Statement::Statement(Statement && other)
00066 : stmt(NULL),
00067 db(NULL)
00068 {
00069 *this = std::move(other);
00070 }
00071
00072 bool Statement::done()
00073 {
00074 if (stmt == NULL)
00075 throw InvalidUseException("Call for done after finalization");
00076 return dn;
00077 }
00078
00079 bool Statement::has_row()
00080 {
00081 if (stmt == NULL)
00082 throw InvalidUseException("Call for has_row after finalization");
00083 return hrow;
00084 }
00085
00086 void Statement::step()
00087 {
00088 if (stmt == NULL)
00089 throw InvalidUseException("Call for step after finalization");
00090 dn = false;
00091 hrow = false;
00092 int status = sqlite3_step(stmt);
00093 if (status == SQLITE_ROW)
00094 {
00095 hrow = true;
00096 dn = false;
00097 return;
00098 }
00099 if (status == SQLITE_DONE)
00100 {
00101 reset_internal();
00102 hrow = false;
00103 dn = true;
00104 return;
00105 }
00106 if (status == SQLITE_BUSY)
00107 {
00108 std::string msg(sqlite3_errmsg(db->cobj()));
00109 reset_nothrow();
00110 throw SqliteException(status, msg);
00111 }
00112 if (status == SQLITE_MISUSE)
00113 {
00114 reset_nothrow();
00115 throw_sqlite_status(status, db->cobj());
00116 }
00117 reset_internal();
00118 }
00119
00120 void Statement::reset()
00121 {
00122 if (stmt == NULL)
00123 throw InvalidUseException("Call for reset after finalization");
00124 if (dn)
00125 {
00126 dn = false;
00127 hrow = false;
00128 }
00129 else if (hrow)
00130 {
00131 reset_internal();
00132 hrow = false;
00133 dn = false;
00134 }
00135 }
00136
00137 void Statement::reset_internal()
00138 {
00139 throw_sqlite_status(sqlite3_reset(stmt), db->cobj());
00140 }
00141
00142 void Statement::reset_nothrow()
00143 {
00144 sqlite3_reset(stmt);
00145 }
00146
00147 double Statement::val_double(int col_index)
00148 {
00149 check_value_conditions(col_index);
00150 return sqlite3_column_double(stmt, col_index);
00151 }
00152
00153 int64_t Statement::val_int64(int col_index)
00154 {
00155 check_value_conditions(col_index);
00156 return sqlite3_column_int64(stmt, col_index);
00157 }
00158
00159 int Statement::val_int(int col_index)
00160 {
00161 check_value_conditions(col_index);
00162 return sqlite3_column_int(stmt, col_index);
00163 }
00164
00165 std::string Statement::val_string(int col_index)
00166 {
00167 check_value_conditions(col_index);
00168 const unsigned char* ptr = sqlite3_column_text(stmt, col_index);
00169 const char* cptr = reinterpret_cast<const char*>(ptr);
00170 return std::string(cptr);
00171 }
00172
00173 void Statement::bind_double(int param_index, double value)
00174 {
00175 throw_sqlite_status(sqlite3_bind_double(stmt, param_index, value), db->cobj());
00176 }
00177
00178 void Statement::bind_int(int param_index, int value)
00179 {
00180 throw_sqlite_status(sqlite3_bind_int(stmt, param_index, value), db->cobj());
00181 }
00182
00183 void Statement::bind_int64(int param_index, int64_t value)
00184 {
00185 throw_sqlite_status(sqlite3_bind_int64(stmt, param_index, value), db->cobj());
00186 }
00187
00188 void Statement::bind_string(int param_index, const std::string& value)
00189 {
00190 throw_sqlite_status(sqlite3_bind_text(stmt, param_index, value.c_str(), value.size(), SQLITE_TRANSIENT), db->cobj());
00191 }
00192
00193 Statement::ColType<double> coldouble()
00194 {
00195 return Statement::coldouble;
00196 }
00197
00198 Statement::ColType<int> colint()
00199 {
00200 return Statement::colint;
00201 }
00202
00203 Statement::ColType<int64_t> colint64()
00204 {
00205 return Statement::colint64;
00206 }
00207
00208 Statement::ColType<std::string> colstr()
00209 {
00210 return Statement::colstring;
00211 }
00212
00213 void Statement::check_value_conditions(int col)
00214 {
00215 if (stmt == NULL)
00216 throw InvalidUseException("Call for value after finalization");
00217 if (!hrow)
00218 throw InvalidUseException("Asking for row data with no row available");
00219 if (col < 0 || col >= cols)
00220 throw InvalidUseException("Column index out of bounds");
00221 }
00222
00223 void Statement::finalize()
00224 {
00225 if (stmt == NULL)
00226 return;
00227 sqlite3_finalize(stmt);
00228 db->unregister_statement(*this);
00229 stmt = NULL;
00230 }
00231
00232 void execute_sql(std::string sql, Database& db)
00233 {
00234 Statement st(sql, db);
00235 st.step();
00236 }
00237
00238 }
00239
00240
00241
00242
00243