/*! Prepares the SQL query \a query for execution. Returns true if the query is prepared successfully; otherwise returns false. The query may contain placeholders for binding values. Both Oracle style colon-name (e.g., \c{:surname}), and ODBC style (\c{?}) placeholders are supported; but they cannot be mixed in the same query. See the \l{QSqlQuery examples}{Detailed Description} for examples. Portability note: Some databases choose to delay preparing a query until it is executed the first time. In this case, preparing a syntactically wrong query succeeds, but every consecutive exec() will fail. For SQLite, the query string can contain only one statement at a time. If more than one statement is given, the function returns false. Example: \snippet sqldatabase/sqldatabase.cpp 9 \sa exec(), bindValue(), addBindValue() */ bool QSqlQuery::prepare(const QString& query) { if (d->ref.load() != 1) { bool fo = isForwardOnly(); *this = QSqlQuery(driver()->createResult()); setForwardOnly(fo); d->sqlResult->setNumericalPrecisionPolicy(d->sqlResult->numericalPrecisionPolicy()); } else { d->sqlResult->setActive(false); d->sqlResult->setLastError(QSqlError()); d->sqlResult->setAt(QSql::BeforeFirstRow); d->sqlResult->setNumericalPrecisionPolicy(d->sqlResult->numericalPrecisionPolicy()); } if (!driver()) { qWarning("QSqlQuery::prepare: no driver"); return false; } if (!driver()->isOpen() || driver()->isOpenError()) { qWarning("QSqlQuery::prepare: database not open"); return false; } if (query.isEmpty()) { qWarning("QSqlQuery::prepare: empty query"); return false; } #ifdef QT_DEBUG_SQL qDebug("\n QSqlQuery::prepare: %s", query.toLocal8Bit().constData()); #endif return d->sqlResult->savePrepare(query); }
bool embeddedResult::fetchLast() { if(!d->driver) return false; if (isForwardOnly()) { // fake this since MySQL can't seek on forward only queries bool success = fetchNext(); // did we move at all? while (fetchNext()) {}; return success; } my_ulonglong numRows; if (d->preparedQuery) { #if MYSQL_VERSION_ID >= 40108 numRows = mysql_stmt_num_rows(d->stmt); #else numRows = 0; #endif } else { numRows = mysql_num_rows(d->result); } if (at() == int(numRows)) return true; if (!numRows) return false; return fetch(numRows - 1); }
bool QSqlQuery::prev() { if ( !isSelect() || !isActive() ) return FALSE; if ( isForwardOnly() ) { #ifdef QT_CHECK_RANGE qWarning("QSqlQuery::seek: cannot seek backwards in a forward only query" ); #endif return FALSE; } beforeSeek(); checkDetach(); bool b = FALSE; switch ( at() ) { case QSql::BeforeFirst: afterSeek(); return FALSE; case QSql::AfterLast: b = d->sqlResult->fetchLast(); afterSeek(); return b; default: if ( !d->sqlResult->fetchPrev() ) { d->sqlResult->setAt( QSql::BeforeFirst ); afterSeek(); return FALSE; } afterSeek(); return TRUE; } }
bool embeddedResult::fetchFirst() { if (at() == 0) return true; if (isForwardOnly()) return (at() == QSql::BeforeFirstRow) ? fetchNext() : false; return fetch(0); }
/*! Retrieves the first record in the result, if available, and positions the query on the retrieved record. Note that the result must be in the \l{isActive()}{active} state and isSelect() must return true before calling this function or it will do nothing and return false. Returns true if successful. If unsuccessful the query position is set to an invalid position and false is returned. \sa next(), previous(), last(), seek(), at(), isActive(), isValid() */ bool QSqlQuery::first() { if (!isSelect() || !isActive()) return false; if (isForwardOnly() && at() > QSql::BeforeFirstRow) { qWarning("QSqlQuery::seek: cannot seek backwards in a forward only query"); return false; } bool b = false; b = d->sqlResult->fetchFirst(); return b; }
bool QMYSQLResult::fetchLast() { if ( isForwardOnly() ) { // fake this since MySQL can't seek on forward only queries bool success = fetchNext(); // did we move at all? while ( fetchNext() ); return success; } my_ulonglong numRows = mysql_num_rows( d->result ); if ( !numRows ) return FALSE; return fetch( numRows - 1 ); }
bool QSqlQuery::first() { if ( !isSelect() || !isActive() ) return FALSE; if ( isForwardOnly() && at() > QSql::BeforeFirst ) { #ifdef QT_CHECK_RANGE qWarning("QSqlQuery::seek: cannot seek backwards in a forward only query" ); #endif return FALSE; } beforeSeek(); checkDetach(); bool b = FALSE; b = d->sqlResult->fetchFirst(); afterSeek(); return b; }
bool ZSqliteCipherCachedResult::cacheNext() { if (d->atEnd) return false; if(isForwardOnly()) { d->cache.clear(); d->cache.resize(d->colCount); } if (!gotoNext(d->cache, d->nextIndex())) { d->revertLast(); d->atEnd = true; return false; } setAt(at() + 1); return true; }
bool embeddedResult::fetch(int i) { if(!d->driver) return false; if (isForwardOnly()) { // fake a forward seek if (at() < i) { int x = i - at(); while (--x && fetchNext()) {}; return fetchNext(); } else { return false; } } if (at() == i) return true; if (d->preparedQuery) { #if MYSQL_VERSION_ID >= 40108 mysql_stmt_data_seek(d->stmt, i); int nRC = mysql_stmt_fetch(d->stmt); if (nRC) { #ifdef MYSQL_DATA_TRUNCATED if (nRC == 1 || nRC == MYSQL_DATA_TRUNCATED) #else if (nRC == 1) #endif setLastError(qMakeStmtError(QCoreApplication::translate("embeddedResult", "Unable to fetch data"), QSqlError::StatementError, d->stmt)); return false; } #else return false; #endif } else { mysql_data_seek(d->result, i); d->row = mysql_fetch_row(d->result); if (!d->row) return false; } setAt(i); return true; }
bool QMYSQLResult::fetch( int i ) { if ( isForwardOnly() ) { // fake a forward seek if ( at() < i ) { int x = i - at(); while ( --x && fetchNext() ); return fetchNext(); } else { return FALSE; } } if ( at() == i ) return TRUE; mysql_data_seek( d->result, i ); d->row = mysql_fetch_row( d->result ); if ( !d->row ) return FALSE; setAt( i ); return TRUE; }
bool QMYSQLResult::reset ( const QString& query ) { if ( !driver() ) return FALSE; if ( !driver()-> isOpen() || driver()->isOpenError() ) return FALSE; cleanup(); const char *encQuery = query.ascii(); if ( mysql_real_query( d->mysql, encQuery, qstrlen(encQuery) ) ) { setLastError( qMakeError("Unable to execute query", QSqlError::Statement, d ) ); return FALSE; } if ( isForwardOnly() ) { if ( isActive() || isValid() ) // have to empty the results from previous query fetchLast(); d->result = mysql_use_result( d->mysql ); } else { d->result = mysql_store_result( d->mysql ); } if ( !d->result && mysql_field_count( d->mysql ) > 0 ) { setLastError( qMakeError( "Unable to store result", QSqlError::Statement, d ) ); return FALSE; } int numFields = mysql_field_count( d->mysql ); setSelect( !( numFields == 0) ); d->fieldTypes.resize( numFields ); if ( isSelect() ) { for( int i = 0; i < numFields; i++) { MYSQL_FIELD* field = mysql_fetch_field_direct( d->result, i ); if ( field->type == FIELD_TYPE_DECIMAL ) d->fieldTypes[i] = QVariant::String; else d->fieldTypes[i] = qDecodeMYSQLType( field->type, field->flags ); } } setActive( TRUE ); return TRUE; }
bool QSqlQuery::exec(const QString& query) { #ifdef QT_DEBUG_SQL QElapsedTimer t; t.start(); #endif if (d->ref.load() != 1) { bool fo = isForwardOnly(); *this = QSqlQuery(driver()->createResult()); d->sqlResult->setNumericalPrecisionPolicy(d->sqlResult->numericalPrecisionPolicy()); setForwardOnly(fo); } else { d->sqlResult->clear(); d->sqlResult->setActive(false); d->sqlResult->setLastError(QSqlError()); d->sqlResult->setAt(QSql::BeforeFirstRow); d->sqlResult->setNumericalPrecisionPolicy(d->sqlResult->numericalPrecisionPolicy()); } d->sqlResult->setQuery(query.trimmed()); if (!driver()->isOpen() || driver()->isOpenError()) { qWarning("QSqlQuery::exec: database not open"); return false; } if (query.isEmpty()) { qWarning("QSqlQuery::exec: empty query"); return false; } bool retval = d->sqlResult->reset(query); #ifdef QT_DEBUG_SQL qDebug().nospace() << "Executed query (" << t.elapsed() << "ms, " << d->sqlResult->size() << " results, " << d->sqlResult->numRowsAffected() << " affected): " << d->sqlResult->lastQuery(); #endif return retval; }
/*! Retrieves the previous record in the result, if available, and positions the query on the retrieved record. Note that the result must be in the \l{isActive()}{active} state and isSelect() must return true before calling this function or it will do nothing and return false. The following rules apply: \list \li If the result is currently located before the first record, there is no change and false is returned. \li If the result is currently located after the last record, an attempt is made to retrieve the last record. \li If the result is somewhere in the middle, an attempt is made to retrieve the previous record. \endlist If the record could not be retrieved, the result is positioned before the first record and false is returned. If the record is successfully retrieved, true is returned. \sa next(), first(), last(), seek(), at(), isActive(), isValid() */ bool QSqlQuery::previous() { if (!isSelect() || !isActive()) return false; if (isForwardOnly()) { qWarning("QSqlQuery::seek: cannot seek backwards in a forward only query"); return false; } bool b = false; switch (at()) { case QSql::BeforeFirstRow: return false; case QSql::AfterLastRow: b = d->sqlResult->fetchLast(); return b; default: if (!d->sqlResult->fetchPrevious()) { d->sqlResult->setAt(QSql::BeforeFirstRow); return false; } return true; } }
void ZSqliteCipherCachedResult::init(int colCount) { d->init(colCount, isForwardOnly()); }
bool QMYSQLResult::fetchFirst() { if ( isForwardOnly() ) // again, fake it return fetchNext(); return fetch( 0 ); }
/*! Retrieves the record at position \a index, if available, and positions the query on the retrieved record. The first record is at position 0. Note that the query must be in an \l{isActive()} {active} state and isSelect() must return true before calling this function. If \a relative is false (the default), the following rules apply: \list \li If \a index is negative, the result is positioned before the first record and false is returned. \li Otherwise, an attempt is made to move to the record at position \a index. If the record at position \a index could not be retrieved, the result is positioned after the last record and false is returned. If the record is successfully retrieved, true is returned. \endlist If \a relative is true, the following rules apply: \list \li If the result is currently positioned before the first record or on the first record, and \a index is negative, there is no change, and false is returned. \li If the result is currently located after the last record, and \a index is positive, there is no change, and false is returned. \li If the result is currently located somewhere in the middle, and the relative offset \a index moves the result below zero, the result is positioned before the first record and false is returned. \li Otherwise, an attempt is made to move to the record \a index records ahead of the current record (or \a index records behind the current record if \a index is negative). If the record at offset \a index could not be retrieved, the result is positioned after the last record if \a index >= 0, (or before the first record if \a index is negative), and false is returned. If the record is successfully retrieved, true is returned. \endlist \sa next(), previous(), first(), last(), at(), isActive(), isValid() */ bool QSqlQuery::seek(int index, bool relative) { if (!isSelect() || !isActive()) return false; int actualIdx; if (!relative) { // arbitrary seek if (index < 0) { d->sqlResult->setAt(QSql::BeforeFirstRow); return false; } actualIdx = index; } else { switch (at()) { // relative seek case QSql::BeforeFirstRow: if (index > 0) actualIdx = index; else { return false; } break; case QSql::AfterLastRow: if (index < 0) { d->sqlResult->fetchLast(); actualIdx = at() + index; } else { return false; } break; default: if ((at() + index) < 0) { d->sqlResult->setAt(QSql::BeforeFirstRow); return false; } actualIdx = at() + index; break; } } // let drivers optimize if (isForwardOnly() && actualIdx < at()) { qWarning("QSqlQuery::seek: cannot seek backwards in a forward only query"); return false; } if (actualIdx == (at() + 1) && at() != QSql::BeforeFirstRow) { if (!d->sqlResult->fetchNext()) { d->sqlResult->setAt(QSql::AfterLastRow); return false; } return true; } if (actualIdx == (at() - 1)) { if (!d->sqlResult->fetchPrevious()) { d->sqlResult->setAt(QSql::BeforeFirstRow); return false; } return true; } if (!d->sqlResult->fetch(actualIdx)) { d->sqlResult->setAt(QSql::AfterLastRow); return false; } return true; }
/*! Retrieves the record at position (offset) \a i, if available, and positions the query on the retrieved record. The first record is at position 0. Note that the query must be in an active state and isSelect() must return TRUE before calling this function. If \a relative is FALSE (the default), the following rules apply: \list \i If \a i is negative, the result is positioned before the first record and FALSE is returned. \i Otherwise, an attempt is made to move to the record at position \a i. If the record at position \a i could not be retrieved, the result is positioned after the last record and FALSE is returned. If the record is successfully retrieved, TRUE is returned. \endlist If \a relative is TRUE, the following rules apply: \list \i If the result is currently positioned before the first record or on the first record, and \a i is negative, there is no change, and FALSE is returned. \i If the result is currently located after the last record, and \a i is positive, there is no change, and FALSE is returned. \i If the result is currently located somewhere in the middle, and the relative offset \a i moves the result below zero, the result is positioned before the first record and FALSE is returned. \i Otherwise, an attempt is made to move to the record \a i records ahead of the current record (or \a i records behind the current record if \a i is negative). If the record at offset \a i could not be retrieved, the result is positioned after the last record if \a i >= 0, (or before the first record if \a i is negative), and FALSE is returned. If the record is successfully retrieved, TRUE is returned. \endlist \sa next() prev() first() last() at() isActive() isValid() */ bool QSqlQuery::seek( int i, bool relative ) { if ( !isSelect() || !isActive() ) return FALSE; beforeSeek(); checkDetach(); int actualIdx; if ( !relative ) { // arbitrary seek if ( i < 0 ) { d->sqlResult->setAt( QSql::BeforeFirst ); afterSeek(); return FALSE; } actualIdx = i; } else { switch ( at() ) { // relative seek case QSql::BeforeFirst: if ( i > 0 ) actualIdx = i; else { afterSeek(); return FALSE; } break; case QSql::AfterLast: if ( i < 0 ) { d->sqlResult->fetchLast(); actualIdx = at() + i; } else { afterSeek(); return FALSE; } break; default: if ( ( at() + i ) < 0 ) { d->sqlResult->setAt( QSql::BeforeFirst ); afterSeek(); return FALSE; } actualIdx = at() + i; break; } } // let drivers optimize if ( isForwardOnly() && actualIdx < at() ) { #ifdef QT_CHECK_RANGE qWarning("QSqlQuery::seek: cannot seek backwards in a forward only query" ); #endif afterSeek(); return FALSE; } if ( actualIdx == ( at() + 1 ) && at() != QSql::BeforeFirst ) { if ( !d->sqlResult->fetchNext() ) { d->sqlResult->setAt( QSql::AfterLast ); afterSeek(); return FALSE; } afterSeek(); return TRUE; } if ( actualIdx == ( at() - 1 ) ) { if ( !d->sqlResult->fetchPrev() ) { d->sqlResult->setAt( QSql::BeforeFirst ); afterSeek(); return FALSE; } afterSeek(); return TRUE; } if ( !d->sqlResult->fetch( actualIdx ) ) { d->sqlResult->setAt( QSql::AfterLast ); afterSeek(); return FALSE; } afterSeek(); return TRUE; }
void QtSqlCachedResult::init(int colCount) { d->init(colCount, isForwardOnly()); }