File indexing completed on 2025-02-23 05:15:21
0001 // 0002 // Copyright (C) 2004-2006 Maciej Sobczak, Stephen Hutton, David Courtney 0003 // Distributed under the Boost Software License, Version 1.0. 0004 // (See accompanying file LICENSE_1_0.txt or copy at 0005 // http://www.boost.org/LICENSE_1_0.txt) 0006 // 0007 0008 #define SOCI_SQLITE3_SOURCE 0009 #include "soci/sqlite3/soci-sqlite3.h" 0010 // std 0011 #include <algorithm> 0012 #include <cctype> 0013 #include <cstring> 0014 #include <functional> 0015 #include <sstream> 0016 #include <string> 0017 0018 #ifdef _MSC_VER 0019 #pragma warning(disable:4355) 0020 #endif 0021 0022 // This is used instead of tolower() just to avoid warnings about int to char 0023 // casts inside MSVS std::transform() implementation. 0024 char toLowerCh(char c) { 0025 return static_cast<char>( std::tolower(c) ); 0026 } 0027 0028 using namespace soci; 0029 using namespace soci::details; 0030 using namespace sqlite_api; 0031 0032 sqlite3_statement_backend::sqlite3_statement_backend( 0033 sqlite3_session_backend &session) 0034 : session_(session) 0035 , stmt_(0) 0036 , dataCache_() 0037 , useData_(0) 0038 , databaseReady_(false) 0039 , boundByName_(false) 0040 , boundByPos_(false) 0041 , hasVectorIntoElements_(false) 0042 , rowsAffectedBulk_(-1LL) 0043 { 0044 } 0045 0046 void sqlite3_statement_backend::alloc() 0047 { 0048 // ... 0049 } 0050 0051 void sqlite3_statement_backend::clean_up() 0052 { 0053 rowsAffectedBulk_ = -1LL; 0054 0055 if (stmt_) 0056 { 0057 sqlite3_finalize(stmt_); 0058 stmt_ = 0; 0059 databaseReady_ = false; 0060 } 0061 } 0062 0063 void sqlite3_statement_backend::prepare(std::string const & query, 0064 statement_type /* eType */) 0065 { 0066 clean_up(); 0067 0068 char const* tail = 0; // unused; 0069 int const res = sqlite3_prepare_v2(session_.conn_, 0070 query.c_str(), 0071 static_cast<int>(query.size()), 0072 &stmt_, 0073 &tail); 0074 if (res != SQLITE_OK) 0075 { 0076 char const* zErrMsg = sqlite3_errmsg(session_.conn_); 0077 0078 std::ostringstream ss; 0079 ss << "sqlite3_statement_backend::prepare: " 0080 << zErrMsg; 0081 throw sqlite3_soci_error(ss.str(), res); 0082 } 0083 databaseReady_ = true; 0084 } 0085 0086 // sqlite3_reset needs to be called before a prepared statment can 0087 // be executed a second time. 0088 void sqlite3_statement_backend::reset_if_needed() 0089 { 0090 if (stmt_ && databaseReady_ == false) 0091 { 0092 reset(); 0093 } 0094 } 0095 0096 void sqlite3_statement_backend::reset() 0097 { 0098 int const res = sqlite3_reset(stmt_); 0099 if (SQLITE_OK == res) 0100 { 0101 databaseReady_ = true; 0102 } 0103 } 0104 0105 // This is used by bulk operations 0106 statement_backend::exec_fetch_result 0107 sqlite3_statement_backend::load_rowset(int totalRows) 0108 { 0109 statement_backend::exec_fetch_result retVal = ef_success; 0110 0111 int i = 0; 0112 int numCols = 0; 0113 0114 // just a hack because in some case, describe() is not called, so columns_ is empty 0115 if (columns_.empty()) 0116 { 0117 numCols = sqlite3_column_count(stmt_); 0118 data_type type; 0119 std::string name; 0120 for (int c = 1; c <= numCols; ++c) 0121 describe_column(c, type, name); 0122 } 0123 else 0124 numCols = static_cast<int>(columns_.size()); 0125 0126 0127 if (!databaseReady_) 0128 { 0129 retVal = ef_no_data; 0130 } 0131 else 0132 { 0133 // make the vector big enough to hold the data we need 0134 dataCache_.resize(totalRows); 0135 for (sqlite3_recordset::iterator it = dataCache_.begin(), 0136 end = dataCache_.end(); it != end; ++it) 0137 { 0138 (*it).resize(numCols); 0139 } 0140 0141 for (i = 0; i < totalRows && databaseReady_; ++i) 0142 { 0143 int const res = sqlite3_step(stmt_); 0144 0145 if (SQLITE_DONE == res) 0146 { 0147 databaseReady_ = false; 0148 retVal = ef_no_data; 0149 break; 0150 } 0151 else if (SQLITE_ROW == res) 0152 { 0153 for (int c = 0; c < numCols; ++c) 0154 { 0155 const sqlite3_column_info &coldef = columns_[c]; 0156 sqlite3_column &col = dataCache_[i][c]; 0157 0158 if (sqlite3_column_type(stmt_, c) == SQLITE_NULL) 0159 { 0160 col.isNull_ = true; 0161 continue; 0162 } 0163 0164 col.isNull_ = false; 0165 col.type_ = coldef.type_; 0166 0167 switch (coldef.type_) 0168 { 0169 case dt_string: 0170 case dt_date: 0171 col.buffer_.size_ = sqlite3_column_bytes(stmt_, c); 0172 col.buffer_.data_ = new char[col.buffer_.size_+1]; 0173 memcpy(col.buffer_.data_, sqlite3_column_text(stmt_, c), col.buffer_.size_+1); 0174 break; 0175 0176 case dt_double: 0177 col.double_ = sqlite3_column_double(stmt_, c); 0178 break; 0179 0180 case dt_integer: 0181 col.int32_ = sqlite3_column_int(stmt_, c); 0182 break; 0183 0184 case dt_long_long: 0185 case dt_unsigned_long_long: 0186 col.int64_ = sqlite3_column_int64(stmt_, c); 0187 break; 0188 0189 case dt_blob: 0190 col.buffer_.size_ = sqlite3_column_bytes(stmt_, c); 0191 col.buffer_.data_ = (col.buffer_.size_ > 0 ? new char[col.buffer_.size_] : NULL); 0192 memcpy(col.buffer_.data_, sqlite3_column_blob(stmt_, c), col.buffer_.size_); 0193 break; 0194 0195 case dt_xml: 0196 throw soci_error("XML data type is not supported"); 0197 } 0198 } 0199 } 0200 else 0201 { 0202 char const* zErrMsg = sqlite3_errmsg(session_.conn_); 0203 std::ostringstream ss; 0204 ss << "sqlite3_statement_backend::loadRS: " 0205 << zErrMsg; 0206 throw sqlite3_soci_error(ss.str(), res); 0207 } 0208 } 0209 } 0210 // if we read less than requested then shrink the vector 0211 dataCache_.resize(i); 0212 0213 return retVal; 0214 } 0215 0216 // This is used for non-bulk operations 0217 statement_backend::exec_fetch_result 0218 sqlite3_statement_backend::load_one() 0219 { 0220 if( !databaseReady_ ) 0221 return ef_no_data; 0222 0223 statement_backend::exec_fetch_result retVal = ef_success; 0224 int const res = sqlite3_step(stmt_); 0225 0226 if (SQLITE_DONE == res) 0227 { 0228 databaseReady_ = false; 0229 retVal = ef_no_data; 0230 } 0231 else if (SQLITE_ROW == res) 0232 { 0233 } 0234 else 0235 { 0236 char const* zErrMsg = sqlite3_errmsg(session_.conn_); 0237 0238 std::ostringstream ss; 0239 ss << "sqlite3_statement_backend::loadOne: " 0240 << zErrMsg; 0241 throw sqlite3_soci_error(ss.str(), res); 0242 } 0243 return retVal; 0244 } 0245 0246 // Execute statements once for every row of useData 0247 statement_backend::exec_fetch_result 0248 sqlite3_statement_backend::bind_and_execute(int number) 0249 { 0250 statement_backend::exec_fetch_result retVal = ef_no_data; 0251 0252 long long rowsAffectedBulkTemp = 0; 0253 0254 rowsAffectedBulk_ = -1; 0255 0256 int const rows = static_cast<int>(useData_.size()); 0257 for (int row = 0; row < rows; ++row) 0258 { 0259 sqlite3_reset(stmt_); 0260 0261 int const totalPositions = static_cast<int>(useData_[0].size()); 0262 for (int pos = 1; pos <= totalPositions; ++pos) 0263 { 0264 int bindRes = SQLITE_OK; 0265 const sqlite3_column &col = useData_[row][pos-1]; 0266 if (col.isNull_) 0267 { 0268 bindRes = sqlite3_bind_null(stmt_, pos); 0269 } 0270 else 0271 { 0272 switch (col.type_) 0273 { 0274 case dt_string: 0275 bindRes = sqlite3_bind_text(stmt_, pos, col.buffer_.constData_, static_cast<int>(col.buffer_.size_), NULL); 0276 break; 0277 0278 case dt_date: 0279 bindRes = sqlite3_bind_text(stmt_, pos, col.buffer_.constData_, static_cast<int>(col.buffer_.size_), SQLITE_TRANSIENT); 0280 break; 0281 0282 case dt_double: 0283 bindRes = sqlite3_bind_double(stmt_, pos, col.double_); 0284 break; 0285 0286 case dt_integer: 0287 bindRes = sqlite3_bind_int(stmt_, pos, col.int32_); 0288 break; 0289 0290 case dt_long_long: 0291 case dt_unsigned_long_long: 0292 bindRes = sqlite3_bind_int64(stmt_, pos, col.int64_); 0293 break; 0294 0295 case dt_blob: 0296 bindRes = sqlite3_bind_blob(stmt_, pos, col.buffer_.constData_, static_cast<int>(col.buffer_.size_), NULL); 0297 break; 0298 0299 case dt_xml: 0300 throw soci_error("XML data type is not supported"); 0301 } 0302 } 0303 0304 if (SQLITE_OK != bindRes) 0305 { 0306 // preserve the number of rows affected so far. 0307 rowsAffectedBulk_ = rowsAffectedBulkTemp; 0308 throw sqlite3_soci_error("Failure to bind on bulk operations", bindRes); 0309 } 0310 } 0311 0312 // Handle the case where there are both into and use elements 0313 // in the same query and one of the into binds to a vector object. 0314 if (1 == rows && number != rows) 0315 { 0316 return load_rowset(number); 0317 } 0318 0319 databaseReady_=true; // Mark sqlite engine is ready to perform sqlite3_step 0320 retVal = load_one(); // execute each bound line 0321 rowsAffectedBulkTemp += get_affected_rows(); 0322 } 0323 0324 rowsAffectedBulk_ = rowsAffectedBulkTemp; 0325 return retVal; 0326 } 0327 0328 statement_backend::exec_fetch_result 0329 sqlite3_statement_backend::execute(int number) 0330 { 0331 if (stmt_ == NULL) 0332 { 0333 throw soci_error("No sqlite statement created"); 0334 } 0335 0336 sqlite3_reset(stmt_); 0337 databaseReady_ = true; 0338 0339 statement_backend::exec_fetch_result retVal = ef_no_data; 0340 0341 if (useData_.empty() == false) 0342 { 0343 retVal = bind_and_execute(number); 0344 } 0345 else 0346 { 0347 retVal = fetch(number); 0348 } 0349 0350 return retVal; 0351 } 0352 0353 statement_backend::exec_fetch_result 0354 sqlite3_statement_backend::fetch(int number) 0355 { 0356 if (hasVectorIntoElements_ || number == 0) 0357 return load_rowset(number); 0358 else 0359 return load_one(); 0360 0361 } 0362 0363 long long sqlite3_statement_backend::get_affected_rows() 0364 { 0365 if (rowsAffectedBulk_ >= 0) 0366 { 0367 return rowsAffectedBulk_; 0368 } 0369 return sqlite3_changes(session_.conn_); 0370 } 0371 0372 int sqlite3_statement_backend::get_number_of_rows() 0373 { 0374 return static_cast<int>(dataCache_.size()); 0375 } 0376 0377 std::string sqlite3_statement_backend::get_parameter_name(int index) const 0378 { 0379 // Notice that SQLite host parameters are counted from 1, not 0. 0380 char const* name = sqlite3_bind_parameter_name(stmt_, index + 1); 0381 if (!name) 0382 return std::string(); 0383 0384 // SQLite returns parameters with the leading colon which is inconsistent 0385 // with the other backends, so get rid of it as well several other 0386 // characters which can be used for named parameters with SQLite. 0387 switch (*name) 0388 { 0389 case ':': 0390 case '?': 0391 case '@': 0392 case '$': 0393 name++; 0394 break; 0395 } 0396 0397 return name; 0398 } 0399 0400 std::string sqlite3_statement_backend::rewrite_for_procedure_call( 0401 std::string const &query) 0402 { 0403 return query; 0404 } 0405 0406 int sqlite3_statement_backend::prepare_for_describe() 0407 { 0408 return sqlite3_column_count(stmt_); 0409 } 0410 0411 typedef std::map<std::string, data_type> sqlite3_data_type_map; 0412 static sqlite3_data_type_map get_data_type_map() 0413 { 0414 sqlite3_data_type_map m; 0415 0416 // Spaces are removed from decltype before looking up in this map, so we don't use them here as well 0417 0418 // dt_blob 0419 m["blob"] = dt_blob; 0420 0421 // dt_date 0422 m["date"] = dt_date; 0423 m["time"] = dt_date; 0424 m["datetime"] = dt_date; 0425 m["timestamp"] = dt_date; 0426 0427 // dt_double 0428 m["decimal"] = dt_double; 0429 m["double"] = dt_double; 0430 m["doubleprecision"] = dt_double; 0431 m["float"] = dt_double; 0432 m["number"] = dt_double; 0433 m["numeric"] = dt_double; 0434 m["real"] = dt_double; 0435 0436 // dt_integer 0437 m["boolean"] = dt_integer; 0438 m["int"] = dt_integer; 0439 m["integer"] = dt_integer; 0440 m["int2"] = dt_integer; 0441 m["mediumint"] = dt_integer; 0442 m["smallint"] = dt_integer; 0443 m["tinyint"] = dt_integer; 0444 0445 // dt_long_long 0446 m["bigint"] = dt_long_long; 0447 m["int8"] = dt_long_long; 0448 0449 // dt_string 0450 m["char"] = dt_string; 0451 m["character"] = dt_string; 0452 m["clob"] = dt_string; 0453 m["nativecharacter"] = dt_string; 0454 m["nchar"] = dt_string; 0455 m["nvarchar"] = dt_string; 0456 m["text"] = dt_string; 0457 m["varchar"] = dt_string; 0458 m["varyingcharacter"] = dt_string; 0459 0460 // dt_unsigned_long_long 0461 m["unsignedbigint"] = dt_unsigned_long_long; 0462 0463 0464 return m; 0465 } 0466 0467 void sqlite3_statement_backend::describe_column(int colNum, data_type & type, 0468 std::string & columnName) 0469 { 0470 static const sqlite3_data_type_map dataTypeMap = get_data_type_map(); 0471 0472 if (columns_.size() < (size_t)colNum) 0473 columns_.resize(colNum); 0474 sqlite3_column_info &coldef = columns_[colNum - 1]; 0475 0476 if (!coldef.name_.empty()) 0477 { 0478 columnName = coldef.name_; 0479 type = coldef.type_; 0480 return; 0481 } 0482 0483 coldef.name_ = columnName = sqlite3_column_name(stmt_, colNum - 1); 0484 0485 // This is a hack, but the sqlite3 type system does not 0486 // have a date or time field. Also it does not reliably 0487 // id other data types. It has a tendency to see everything 0488 // as text. sqlite3_column_decltype returns the text that is 0489 // used in the create table statement 0490 char const* declType = sqlite3_column_decltype(stmt_, colNum-1); 0491 0492 if ( declType == NULL ) 0493 { 0494 static char const* s_char = "char"; 0495 declType = s_char; 0496 } 0497 0498 std::string dt = declType; 0499 0500 // remove extra characters for example "(20)" in "varchar(20)" and all spaces 0501 dt.erase(std::remove_if(dt.begin(), dt.end(), [](char const c) { return std::isspace(c); }), dt.end()); 0502 0503 std::string::iterator siter = std::find_if(dt.begin(), dt.end(), [](char const c) { return !std::isalnum(c); }); 0504 if (siter != dt.end()) 0505 dt.resize(siter - dt.begin()); 0506 0507 // do all comparisons in lower case 0508 std::transform(dt.begin(), dt.end(), dt.begin(), toLowerCh); 0509 0510 sqlite3_data_type_map::const_iterator iter = dataTypeMap.find(dt); 0511 if (iter != dataTypeMap.end()) 0512 { 0513 coldef.type_ = type = iter->second; 0514 return; 0515 } 0516 0517 // try to get it from the weak ass type system 0518 0519 // total hack - execute the statment once to get the column types 0520 // then clear so it can be executed again 0521 sqlite3_step(stmt_); 0522 0523 int const sqlite3_type = sqlite3_column_type(stmt_, colNum-1); 0524 switch (sqlite3_type) 0525 { 0526 case SQLITE_INTEGER: 0527 type = dt_integer; 0528 break; 0529 case SQLITE_FLOAT: 0530 type = dt_double; 0531 break; 0532 case SQLITE_BLOB: 0533 case SQLITE_TEXT: 0534 type = dt_string; 0535 break; 0536 default: 0537 type = dt_string; 0538 break; 0539 } 0540 coldef.type_ = type; 0541 0542 sqlite3_reset(stmt_); 0543 } 0544 0545 sqlite3_standard_into_type_backend * 0546 sqlite3_statement_backend::make_into_type_backend() 0547 { 0548 return new sqlite3_standard_into_type_backend(*this); 0549 } 0550 0551 sqlite3_standard_use_type_backend * sqlite3_statement_backend::make_use_type_backend() 0552 { 0553 return new sqlite3_standard_use_type_backend(*this); 0554 } 0555 0556 sqlite3_vector_into_type_backend * 0557 sqlite3_statement_backend::make_vector_into_type_backend() 0558 { 0559 hasVectorIntoElements_ = true; 0560 return new sqlite3_vector_into_type_backend(*this); 0561 } 0562 0563 sqlite3_vector_use_type_backend * 0564 sqlite3_statement_backend::make_vector_use_type_backend() 0565 { 0566 return new sqlite3_vector_use_type_backend(*this); 0567 }