SQLite support only one statement at a time

SQLite driver support only one statement at a time. This fix makes the
exec and prepare call failed if more than one statements are given.
This is bug fix for QTBUG-21884. Also the behaviour is documented in
the API specification.

Task-number: QTBUG-21884
Change-Id: If1e25a0dd9f9ee38961ef478fc7909f6b05e360a
Reviewed-by: Yunqiao Yin <charles.yin@nokia.com>
This commit is contained in:
Honglei Zhang 2011-11-18 10:50:07 +02:00 committed by Qt by Nokia
parent d1e7294cd2
commit 1d3cfdbfa1
3 changed files with 62 additions and 2 deletions

View File

@ -322,12 +322,14 @@ bool QSQLiteResult::prepare(const QString &query)
setSelect(false); setSelect(false);
const void *pzTail = NULL;
#if (SQLITE_VERSION_NUMBER >= 3003011) #if (SQLITE_VERSION_NUMBER >= 3003011)
int res = sqlite3_prepare16_v2(d->access, query.constData(), (query.size() + 1) * sizeof(QChar), int res = sqlite3_prepare16_v2(d->access, query.constData(), (query.size() + 1) * sizeof(QChar),
&d->stmt, 0); &d->stmt, &pzTail);
#else #else
int res = sqlite3_prepare16(d->access, query.constData(), (query.size() + 1) * sizeof(QChar), int res = sqlite3_prepare16(d->access, query.constData(), (query.size() + 1) * sizeof(QChar),
&d->stmt, 0); &d->stmt, &pzTail);
#endif #endif
if (res != SQLITE_OK) { if (res != SQLITE_OK) {
@ -335,6 +337,11 @@ bool QSQLiteResult::prepare(const QString &query)
"Unable to execute statement"), QSqlError::StatementError, res)); "Unable to execute statement"), QSqlError::StatementError, res));
d->finalize(); d->finalize();
return false; return false;
} else if (pzTail && !QString(reinterpret_cast<const QChar *>(pzTail)).trimmed().isEmpty()) {
setLastError(qMakeError(d->access, QCoreApplication::translate("QSQLiteResult",
"Unable to execute multiple statements at a time"), QSqlError::StatementError, SQLITE_MISUSE));
d->finalize();
return false;
} }
return true; return true;
} }

View File

@ -338,6 +338,9 @@ bool QSqlQuery::isNull(int field) const
Note that the last error for this query is reset when exec() is Note that the last error for this query is reset when exec() is
called. called.
For SQLite, the query string can contain only one statement at a time.
If more than one statements is give, the function returns false.
Example: Example:
\snippet doc/src/snippets/sqldatabase/sqldatabase.cpp 34 \snippet doc/src/snippets/sqldatabase/sqldatabase.cpp 34
@ -887,6 +890,9 @@ void QSqlQuery::clear()
syntactically wrong query succeeds, but every consecutive exec() syntactically wrong query succeeds, but every consecutive exec()
will fail. will fail.
For SQLite, the query string can contain only one statement at a time.
If more than one statements are give, the function returns false.
Example: Example:
\snippet doc/src/snippets/sqldatabase/sqldatabase.cpp 9 \snippet doc/src/snippets/sqldatabase/sqldatabase.cpp 9

View File

@ -213,6 +213,8 @@ private slots:
void QTBUG_5765(); void QTBUG_5765();
void QTBUG_14132_data() { generic_data("QOCI"); } void QTBUG_14132_data() { generic_data("QOCI"); }
void QTBUG_14132(); void QTBUG_14132();
void QTBUG_21884_data() { generic_data("QSQLITE"); }
void QTBUG_21884();
void sqlite_constraint_data() { generic_data("QSQLITE"); } void sqlite_constraint_data() { generic_data("QSQLITE"); }
void sqlite_constraint(); void sqlite_constraint();
@ -323,6 +325,7 @@ void tst_QSqlQuery::dropTestTables( QSqlDatabase db )
<< qTableName("bug6421", __FILE__).toUpper() << qTableName("bug6421", __FILE__).toUpper()
<< qTableName("bug5765", __FILE__) << qTableName("bug5765", __FILE__)
<< qTableName("bug6852", __FILE__) << qTableName("bug6852", __FILE__)
<< qTableName("bug21884", __FILE__)
<< qTableName( "qtest_lockedtable", __FILE__ ) << qTableName( "qtest_lockedtable", __FILE__ )
<< qTableName( "Planet", __FILE__ ) << qTableName( "Planet", __FILE__ )
<< qTableName( "task_250026", __FILE__ ) << qTableName( "task_250026", __FILE__ )
@ -3083,6 +3086,50 @@ void tst_QSqlQuery::QTBUG_5765()
QCOMPARE(q.value(0).toInt(), 123); QCOMPARE(q.value(0).toInt(), 123);
} }
/**
* This test case tests multiple statements in one execution.
* Sqlite driver doesn't support multiple statement at one time.
* If more than one statement is given, the exec or prepare function
* return failure to the client.
*/
void tst_QSqlQuery::QTBUG_21884()
{
QFETCH(QString, dbName);
QSqlDatabase db = QSqlDatabase::database(dbName);
CHECK_DATABASE(db);
QSqlQuery q(db);
QStringList stList;
QString tableName(qTableName("bug21884", __FILE__ ));
stList << "create table " + tableName + "(id integer primary key, note string)";
stList << "select * from " + tableName + ";";
stList << "select * from " + tableName + "; \t\n\r";
stList << "drop table " + tableName;
foreach (const QString& st, stList) {
QVERIFY_SQL(q, exec(st));
}
foreach (const QString& st, stList) {
QVERIFY_SQL(q, prepare(st));
QVERIFY_SQL(q, exec());
}
stList.clear();
stList << "create table " + tableName + "(id integer primary key); select * from " + tableName;
stList << "create table " + tableName + "(id integer primary key); syntax error!;";
stList << "create table " + tableName + "(id integer primary key);;";
stList << "create table " + tableName + "(id integer primary key);\'\"\a\b\b\v";
foreach (const QString&st , stList) {
QVERIFY2(!q.prepare(st), qPrintable(QString("the statement is expected to fail! ") + st));
QVERIFY2(!q.exec(st), qPrintable(QString("the statement is expected to fail! ") + st));
}
}
void tst_QSqlQuery::oraOCINumber() void tst_QSqlQuery::oraOCINumber()
{ {
QFETCH( QString, dbName ); QFETCH( QString, dbName );