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 }