bool ODBCStatementImpl::hasNext() { if (hasData()) { if (!extractions().size()) makeInternalExtractors(); if (!_prepared) doPrepare(); if (_stepCalled) return _stepCalled = nextRowReady(); makeStep(); if (!nextRowReady()) { if (hasMoreDataSets()) activateNextDataSet(); else return false; if (SQL_NO_DATA == SQLMoreResults(_stmt)) return false; addPreparation(); doPrepare(); fixupExtraction(); makeStep(); } else if (Utility::isError(_nextResponse)) checkError(_nextResponse, "SQLFetch()"); return true; } return false; }
void SQLiteStatementImpl::compileImpl() { if (!_pLeftover) { _bindBegin = bindings().begin(); } std::string statement(toString()); sqlite3_stmt* pStmt = 0; const char* pSql = _pLeftover ? _pLeftover->c_str() : statement.c_str(); if (0 == std::strlen(pSql)) throw InvalidSQLStatementException("Empty statements are illegal"); int rc = SQLITE_OK; const char* pLeftover = 0; bool queryFound = false; do { rc = sqlite3_prepare_v2(_pDB, pSql, -1, &pStmt, &pLeftover); if (rc != SQLITE_OK) { if (pStmt) sqlite3_finalize(pStmt); pStmt = 0; std::string errMsg = sqlite3_errmsg(_pDB); Utility::throwException(_pDB, rc, errMsg); } else if (rc == SQLITE_OK && pStmt) { queryFound = true; } else if (rc == SQLITE_OK && !pStmt) // comment/whitespace ignore { pSql = pLeftover; if (std::strlen(pSql) == 0) { // empty statement or an conditional statement! like CREATE IF NOT EXISTS // this is valid queryFound = true; } } } while (rc == SQLITE_OK && !pStmt && !queryFound); //Finalization call in clear() invalidates the pointer, so the value is remembered here. //For last statement in a batch (or a single statement), pLeftover == "", so the next call // to compileImpl() shall return false immediately when there are no more statements left. std::string leftOver(pLeftover); trimInPlace(leftOver); clear(); _pStmt = pStmt; if (!leftOver.empty()) { _pLeftover = new std::string(leftOver); _canCompile = true; } else _canCompile = false; _pBinder = new Binder(_pStmt); _pExtractor = new Extractor(_pStmt); if (SQLITE_DONE == _nextResponse && _isExtracted) { //if this is not the first compile and there has already been extraction //during previous step, switch to the next set if there is one provided if (hasMoreDataSets()) { activateNextDataSet(); _isExtracted = false; } } int colCount = sqlite3_column_count(_pStmt); if (colCount) { std::size_t curDataSet = currentDataSet(); if (curDataSet >= _columns.size()) _columns.resize(curDataSet + 1); for (int i = 0; i < colCount; ++i) { MetaColumn mc(i, sqlite3_column_name(_pStmt, i), Utility::getColumnType(_pStmt, i)); _columns[curDataSet].push_back(mc); } } }