SQLiteStatementImpl.cpp 7.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312
  1. //
  2. // SQLiteStatementImpl.cpp
  3. //
  4. // $Id: //poco/Main/Data/SQLite/src/SQLiteStatementImpl.cpp#8 $
  5. //
  6. // Library: SQLite
  7. // Package: SQLite
  8. // Module: SQLiteStatementImpl
  9. //
  10. // Copyright (c) 2006, Applied Informatics Software Engineering GmbH.
  11. // and Contributors.
  12. //
  13. // SPDX-License-Identifier: BSL-1.0
  14. //
  15. #include "Poco/Data/SQLite/SQLiteStatementImpl.h"
  16. #include "Poco/Data/SQLite/Utility.h"
  17. #include "Poco/Data/SQLite/SQLiteException.h"
  18. #include "Poco/String.h"
  19. #include <cstdlib>
  20. #include <cstring>
  21. #if defined(POCO_UNBUNDLED)
  22. #include <sqlite3.h>
  23. #else
  24. #include "sqlite3.h"
  25. #endif
  26. namespace Poco {
  27. namespace Data {
  28. namespace SQLite {
  29. const int SQLiteStatementImpl::POCO_SQLITE_INV_ROW_CNT = std::numeric_limits<std::size_t>::max();
  30. SQLiteStatementImpl::SQLiteStatementImpl(Poco::Data::SessionImpl& rSession, sqlite3* pDB):
  31. StatementImpl(rSession),
  32. _pDB(pDB),
  33. _pStmt(0),
  34. _stepCalled(false),
  35. _nextResponse(0),
  36. _affectedRowCount(POCO_SQLITE_INV_ROW_CNT),
  37. _canBind(false),
  38. _isExtracted(false),
  39. _canCompile(true)
  40. {
  41. _columns.resize(1);
  42. }
  43. SQLiteStatementImpl::~SQLiteStatementImpl()
  44. {
  45. try
  46. {
  47. clear();
  48. }
  49. catch (...)
  50. {
  51. poco_unexpected();
  52. }
  53. }
  54. void SQLiteStatementImpl::compileImpl()
  55. {
  56. if (!_pLeftover)
  57. {
  58. _bindBegin = bindings().begin();
  59. }
  60. std::string statement(toString());
  61. sqlite3_stmt* pStmt = 0;
  62. const char* pSql = _pLeftover ? _pLeftover->c_str() : statement.c_str();
  63. if (0 == std::strlen(pSql))
  64. throw InvalidSQLStatementException("Empty statements are illegal");
  65. int rc = SQLITE_OK;
  66. const char* pLeftover = 0;
  67. bool queryFound = false;
  68. do
  69. {
  70. rc = sqlite3_prepare_v2(_pDB, pSql, -1, &pStmt, &pLeftover);
  71. if (rc != SQLITE_OK)
  72. {
  73. if (pStmt) sqlite3_finalize(pStmt);
  74. pStmt = 0;
  75. std::string errMsg = sqlite3_errmsg(_pDB);
  76. Utility::throwException(rc, errMsg);
  77. }
  78. else if (rc == SQLITE_OK && pStmt)
  79. {
  80. queryFound = true;
  81. }
  82. else if (rc == SQLITE_OK && !pStmt) // comment/whitespace ignore
  83. {
  84. pSql = pLeftover;
  85. if (std::strlen(pSql) == 0)
  86. {
  87. // empty statement or an conditional statement! like CREATE IF NOT EXISTS
  88. // this is valid
  89. queryFound = true;
  90. }
  91. }
  92. } while (rc == SQLITE_OK && !pStmt && !queryFound);
  93. //Finalization call in clear() invalidates the pointer, so the value is remembered here.
  94. //For last statement in a batch (or a single statement), pLeftover == "", so the next call
  95. // to compileImpl() shall return false immediately when there are no more statements left.
  96. std::string leftOver(pLeftover);
  97. trimInPlace(leftOver);
  98. clear();
  99. _pStmt = pStmt;
  100. if (!leftOver.empty())
  101. {
  102. _pLeftover = new std::string(leftOver);
  103. _canCompile = true;
  104. }
  105. else _canCompile = false;
  106. _pBinder = new Binder(_pStmt);
  107. _pExtractor = new Extractor(_pStmt);
  108. if (SQLITE_DONE == _nextResponse && _isExtracted)
  109. {
  110. //if this is not the first compile and there has already been extraction
  111. //during previous step, switch to the next set if there is one provided
  112. if (hasMoreDataSets())
  113. {
  114. activateNextDataSet();
  115. _isExtracted = false;
  116. }
  117. }
  118. int colCount = sqlite3_column_count(_pStmt);
  119. if (colCount)
  120. {
  121. std::size_t curDataSet = currentDataSet();
  122. if (curDataSet >= _columns.size()) _columns.resize(curDataSet + 1);
  123. for (int i = 0; i < colCount; ++i)
  124. {
  125. MetaColumn mc(i, sqlite3_column_name(_pStmt, i), Utility::getColumnType(_pStmt, i));
  126. _columns[curDataSet].push_back(mc);
  127. }
  128. }
  129. }
  130. void SQLiteStatementImpl::bindImpl()
  131. {
  132. _stepCalled = false;
  133. _nextResponse = 0;
  134. if (_pStmt == 0) return;
  135. sqlite3_reset(_pStmt);
  136. int paramCount = sqlite3_bind_parameter_count(_pStmt);
  137. BindIt bindEnd = bindings().end();
  138. if (0 == paramCount || bindEnd == _bindBegin)
  139. {
  140. _canBind = false;
  141. return;
  142. }
  143. std::size_t availableCount = 0;
  144. Bindings::difference_type bindCount = 0;
  145. Bindings::iterator it = _bindBegin;
  146. for (; it != bindEnd; ++it)
  147. {
  148. availableCount += (*it)->numOfColumnsHandled();
  149. if (availableCount <= paramCount) ++bindCount;
  150. else break;
  151. }
  152. Bindings::difference_type remainingBindCount = bindEnd - _bindBegin;
  153. if (bindCount < remainingBindCount)
  154. {
  155. bindEnd = _bindBegin + bindCount;
  156. _canBind = true;
  157. }
  158. else if (bindCount > remainingBindCount)
  159. throw ParameterCountMismatchException();
  160. std::size_t boundRowCount;
  161. if (_bindBegin != bindings().end())
  162. {
  163. boundRowCount = (*_bindBegin)->numOfRowsHandled();
  164. Bindings::iterator oldBegin = _bindBegin;
  165. for (std::size_t pos = 1; _bindBegin != bindEnd && (*_bindBegin)->canBind(); ++_bindBegin)
  166. {
  167. if (boundRowCount != (*_bindBegin)->numOfRowsHandled())
  168. throw BindingException("Size mismatch in Bindings. All Bindings MUST have the same size");
  169. (*_bindBegin)->bind(pos);
  170. pos += (*_bindBegin)->numOfColumnsHandled();
  171. }
  172. if ((*oldBegin)->canBind())
  173. {
  174. //container binding will come back for more, so we must rewind
  175. _bindBegin = oldBegin;
  176. _canBind = true;
  177. }
  178. else _canBind = false;
  179. }
  180. }
  181. void SQLiteStatementImpl::clear()
  182. {
  183. _columns[currentDataSet()].clear();
  184. _affectedRowCount = POCO_SQLITE_INV_ROW_CNT;
  185. if (_pStmt)
  186. {
  187. sqlite3_finalize(_pStmt);
  188. _pStmt=0;
  189. }
  190. _pLeftover = 0;
  191. }
  192. bool SQLiteStatementImpl::hasNext()
  193. {
  194. if (_stepCalled)
  195. return (_nextResponse == SQLITE_ROW);
  196. // _pStmt is allowed to be null for conditional SQL statements
  197. if (_pStmt == 0)
  198. {
  199. _stepCalled = true;
  200. _nextResponse = SQLITE_DONE;
  201. return false;
  202. }
  203. _stepCalled = true;
  204. _nextResponse = sqlite3_step(_pStmt);
  205. if (_affectedRowCount == POCO_SQLITE_INV_ROW_CNT) _affectedRowCount = 0;
  206. if (!sqlite3_stmt_readonly(_pStmt))
  207. _affectedRowCount += sqlite3_changes(_pDB);
  208. if (_nextResponse != SQLITE_ROW && _nextResponse != SQLITE_OK && _nextResponse != SQLITE_DONE)
  209. Utility::throwException(_nextResponse);
  210. _pExtractor->reset();//clear the cached null indicators
  211. return (_nextResponse == SQLITE_ROW);
  212. }
  213. std::size_t SQLiteStatementImpl::next()
  214. {
  215. if (SQLITE_ROW == _nextResponse)
  216. {
  217. poco_assert (columnsReturned() == sqlite3_column_count(_pStmt));
  218. Extractions& extracts = extractions();
  219. Extractions::iterator it = extracts.begin();
  220. Extractions::iterator itEnd = extracts.end();
  221. std::size_t pos = 0; // sqlite starts with pos 0 for results!
  222. for (; it != itEnd; ++it)
  223. {
  224. (*it)->extract(pos);
  225. pos += (*it)->numOfColumnsHandled();
  226. _isExtracted = true;
  227. }
  228. _stepCalled = false;
  229. if (_affectedRowCount == POCO_SQLITE_INV_ROW_CNT) _affectedRowCount = 0;
  230. _affectedRowCount += (*extracts.begin())->numOfRowsHandled();
  231. }
  232. else if (SQLITE_DONE == _nextResponse)
  233. {
  234. throw Poco::Data::DataException("No data received");
  235. }
  236. else
  237. {
  238. Utility::throwException(_nextResponse, std::string("Iterator Error: trying to access the next value"));
  239. }
  240. return 1u;
  241. }
  242. std::size_t SQLiteStatementImpl::columnsReturned() const
  243. {
  244. return (std::size_t) _columns[currentDataSet()].size();
  245. }
  246. const MetaColumn& SQLiteStatementImpl::metaColumn(std::size_t pos) const
  247. {
  248. std::size_t curDataSet = currentDataSet();
  249. poco_assert (pos >= 0 && pos <= _columns[curDataSet].size());
  250. return _columns[curDataSet][pos];
  251. }
  252. int SQLiteStatementImpl::affectedRowCount() const
  253. {
  254. if (_affectedRowCount != POCO_SQLITE_INV_ROW_CNT) return _affectedRowCount;
  255. return _pStmt == 0 || sqlite3_stmt_readonly(_pStmt) ? 0 : sqlite3_changes(_pDB);
  256. }
  257. } } } // namespace Poco::Data::SQLite