tests/auto/qsqlquery/tst_qsqlquery.cpp
changeset 0 1918ee327afb
child 3 41300fa6a67c
equal deleted inserted replaced
-1:000000000000 0:1918ee327afb
       
     1 /****************************************************************************
       
     2 **
       
     3 ** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
       
     4 ** All rights reserved.
       
     5 ** Contact: Nokia Corporation (qt-info@nokia.com)
       
     6 **
       
     7 ** This file is part of the test suite of the Qt Toolkit.
       
     8 **
       
     9 ** $QT_BEGIN_LICENSE:LGPL$
       
    10 ** No Commercial Usage
       
    11 ** This file contains pre-release code and may not be distributed.
       
    12 ** You may use this file in accordance with the terms and conditions
       
    13 ** contained in the Technology Preview License Agreement accompanying
       
    14 ** this package.
       
    15 **
       
    16 ** GNU Lesser General Public License Usage
       
    17 ** Alternatively, this file may be used under the terms of the GNU Lesser
       
    18 ** General Public License version 2.1 as published by the Free Software
       
    19 ** Foundation and appearing in the file LICENSE.LGPL included in the
       
    20 ** packaging of this file.  Please review the following information to
       
    21 ** ensure the GNU Lesser General Public License version 2.1 requirements
       
    22 ** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
       
    23 **
       
    24 ** In addition, as a special exception, Nokia gives you certain additional
       
    25 ** rights.  These rights are described in the Nokia Qt LGPL Exception
       
    26 ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
       
    27 **
       
    28 ** If you have questions regarding the use of this file, please contact
       
    29 ** Nokia at qt-info@nokia.com.
       
    30 **
       
    31 **
       
    32 **
       
    33 **
       
    34 **
       
    35 **
       
    36 **
       
    37 **
       
    38 ** $QT_END_LICENSE$
       
    39 **
       
    40 ****************************************************************************/
       
    41 
       
    42 #include <QtTest/QtTest>
       
    43 #include <QtSql/QtSql>
       
    44 
       
    45 #include "../qsqldatabase/tst_databases.h"
       
    46 
       
    47 //TESTED_FILES=
       
    48 
       
    49 class tst_QSqlQuery : public QObject
       
    50 {
       
    51     Q_OBJECT
       
    52 
       
    53 public:
       
    54     tst_QSqlQuery();
       
    55     virtual ~tst_QSqlQuery();
       
    56 
       
    57 public slots:
       
    58     void initTestCase();
       
    59     void cleanupTestCase();
       
    60     void init();
       
    61     void cleanup();
       
    62 
       
    63 private slots:
       
    64     void value_data() { generic_data(); }
       
    65     void value();
       
    66     void isValid_data() { generic_data(); }
       
    67     void isValid();
       
    68     void isActive_data() { generic_data(); }
       
    69     void isActive();
       
    70     void isSelect_data() { generic_data(); }
       
    71     void isSelect();
       
    72     void numRowsAffected_data() { generic_data(); }
       
    73     void numRowsAffected();
       
    74     void size_data() { generic_data(); }
       
    75     void size();
       
    76     void isNull_data() { generic_data(); }
       
    77     void isNull();
       
    78     void query_exec_data() { generic_data(); }
       
    79     void query_exec();
       
    80     void execErrorRecovery_data() { generic_data(); }
       
    81     void execErrorRecovery();
       
    82     void first_data() { generic_data(); }
       
    83     void first();
       
    84     void next_data() { generic_data(); }
       
    85     void next();
       
    86     void prev_data() { generic_data(); }
       
    87     void prev();
       
    88     void last_data() { generic_data(); }
       
    89     void last();
       
    90     void seek_data() { generic_data(); }
       
    91     void seek();
       
    92     void transaction_data() { generic_data(); }
       
    93     void transaction();
       
    94     void record_data() { generic_data(); }
       
    95     void record();
       
    96     void record_sqlite_data() { generic_data("QSQLITE"); }
       
    97     void record_sqlite();
       
    98     void finish_data() { generic_data(); }
       
    99     void finish();
       
   100     void sqlite_finish_data() { generic_data(); }
       
   101     void sqlite_finish();
       
   102     void nextResult_data() { generic_data(); }
       
   103     void nextResult();
       
   104 
       
   105     // forwardOnly mode need special treatment
       
   106     void forwardOnly_data() { generic_data(); }
       
   107     void forwardOnly();
       
   108 
       
   109     // bug specific tests
       
   110     void bitField_data() {generic_data("QTDS"); }
       
   111     void bitField();
       
   112     void nullBlob_data() { generic_data("QOCI"); }
       
   113     void nullBlob();
       
   114     void blob_data() { generic_data(); }
       
   115     void blob();
       
   116     void rawField_data() { generic_data("QOCI"); }
       
   117     void rawField();
       
   118     void precision_data() { generic_data(); }
       
   119     void precision();
       
   120     void nullResult_data() { generic_data(); }
       
   121     void nullResult();
       
   122     void joins_data() { generic_data(); }
       
   123     void joins();
       
   124     void outValues_data() { generic_data(); }
       
   125     void outValues();
       
   126     void char1Select_data() { generic_data(); }
       
   127     void char1Select();
       
   128     void char1SelectUnicode_data() { generic_data(); }
       
   129     void char1SelectUnicode();
       
   130     void synonyms_data() { generic_data(); }
       
   131     void synonyms();
       
   132     void oraOutValues_data() { generic_data("QOCI"); }
       
   133     void oraOutValues();
       
   134     void mysqlOutValues_data() { generic_data("QMYSQL"); }
       
   135     void mysqlOutValues();
       
   136     void oraClob_data() { generic_data("QOCI"); }
       
   137     void oraClob();
       
   138     void oraLong_data() { generic_data("QOCI"); }
       
   139     void oraLong();
       
   140     void outValuesDB2_data() { generic_data("QDB2"); }
       
   141     void outValuesDB2();
       
   142     void storedProceduresIBase_data() {generic_data("QIBASE"); }
       
   143     void storedProceduresIBase();
       
   144     void oraRowId_data() { generic_data("QOCI"); }
       
   145     void oraRowId();
       
   146     void prepare_bind_exec_data() { generic_data(); }
       
   147     void prepare_bind_exec();
       
   148     void prepared_select_data() { generic_data(); }
       
   149     void prepared_select();
       
   150     void sqlServerLongStrings_data() { generic_data(); }
       
   151     void sqlServerLongStrings();
       
   152     void invalidQuery_data() { generic_data(); }
       
   153     void invalidQuery();
       
   154     void batchExec_data() { generic_data(); }
       
   155     void batchExec();
       
   156     void oraArrayBind_data() { generic_data(); }
       
   157     void oraArrayBind();
       
   158     void lastInsertId_data() { generic_data(); }
       
   159     void lastInsertId();
       
   160     void lastQuery_data() { generic_data(); }
       
   161     void lastQuery();
       
   162     void bindWithDoubleColonCastOperator_data() { generic_data(); }
       
   163     void bindWithDoubleColonCastOperator();
       
   164     void queryOnInvalidDatabase_data() { generic_data(); }
       
   165     void queryOnInvalidDatabase();
       
   166     void createQueryOnClosedDatabase_data() { generic_data(); }
       
   167     void createQueryOnClosedDatabase();
       
   168     void seekForwardOnlyQuery_data() { generic_data(); }
       
   169     void seekForwardOnlyQuery();
       
   170     void reExecutePreparedForwardOnlyQuery_data() { generic_data(); }
       
   171     void reExecutePreparedForwardOnlyQuery();
       
   172     void blobsPreparedQuery_data() { generic_data(); }
       
   173     void blobsPreparedQuery();
       
   174     void emptyTableNavigate_data() { generic_data(); }
       
   175     void emptyTableNavigate();
       
   176 
       
   177 #ifdef NOT_READY_YET
       
   178     void task_229811();
       
   179     void task_229811_data() { generic_data(); }
       
   180     void task_234422_data() {  generic_data(); }
       
   181     void task_234422();
       
   182 #endif
       
   183     void task_217003_data() { generic_data(); }
       
   184     void task_217003();
       
   185 
       
   186     void task_250026_data() { generic_data("QODBC"); }
       
   187     void task_250026();
       
   188     void task_205701_data() { generic_data("QMYSQL"); }
       
   189     void task_205701();
       
   190 
       
   191     void task_233829_data() { generic_data("QPSQL"); }
       
   192     void task_233829();
       
   193 
       
   194     void sqlServerReturn0_data() { generic_data(); }
       
   195     void sqlServerReturn0();
       
   196 
       
   197 private:
       
   198     // returns all database connections
       
   199     void generic_data(const QString &engine=QString());
       
   200     void dropTestTables( QSqlDatabase db );
       
   201     void createTestTables( QSqlDatabase db );
       
   202     void populateTestTables( QSqlDatabase db );
       
   203 
       
   204     tst_Databases dbs;
       
   205 };
       
   206 
       
   207 tst_QSqlQuery::tst_QSqlQuery()
       
   208 {
       
   209 }
       
   210 
       
   211 tst_QSqlQuery::~tst_QSqlQuery()
       
   212 {
       
   213 }
       
   214 
       
   215 void tst_QSqlQuery::initTestCase()
       
   216 {
       
   217     dbs.open();
       
   218 
       
   219     for ( QStringList::ConstIterator it = dbs.dbNames.begin(); it != dbs.dbNames.end(); ++it ) {
       
   220         QSqlDatabase db = QSqlDatabase::database(( *it ) );
       
   221         CHECK_DATABASE( db );
       
   222         dropTestTables( db ); //in case of leftovers
       
   223         createTestTables( db );
       
   224         populateTestTables( db );
       
   225     }
       
   226 }
       
   227 
       
   228 void tst_QSqlQuery::cleanupTestCase()
       
   229 {
       
   230     for ( QStringList::ConstIterator it = dbs.dbNames.begin(); it != dbs.dbNames.end(); ++it ) {
       
   231         QSqlDatabase db = QSqlDatabase::database(( *it ) );
       
   232         CHECK_DATABASE( db );
       
   233         dropTestTables( db );
       
   234     }
       
   235 
       
   236     dbs.close();
       
   237 }
       
   238 
       
   239 void tst_QSqlQuery::init()
       
   240 {
       
   241 }
       
   242 
       
   243 void tst_QSqlQuery::cleanup()
       
   244 {
       
   245     QFETCH( QString, dbName );
       
   246     QSqlDatabase db = QSqlDatabase::database( dbName );
       
   247     CHECK_DATABASE( db );
       
   248 
       
   249     if ( QTest::currentTestFunction() == QLatin1String( "numRowsAffected" )
       
   250             || QTest::currentTestFunction() == QLatin1String( "transactions" )
       
   251             || QTest::currentTestFunction() == QLatin1String( "size" )
       
   252             || QTest::currentTestFunction() == QLatin1String( "isActive" )
       
   253             || QTest::currentTestFunction() == QLatin1String( "lastInsertId" ) ) {
       
   254         populateTestTables( db );
       
   255     }
       
   256 
       
   257     if ( QTest::currentTestFailed() && ( db.driverName().startsWith( "QOCI" )
       
   258                                          || db.driverName().startsWith( "QODBC" ) ) ) {
       
   259         //since Oracle ODBC totally craps out on error, we init again
       
   260         db.close();
       
   261         db.open();
       
   262     }
       
   263 }
       
   264 
       
   265 void tst_QSqlQuery::generic_data(const QString& engine)
       
   266 {
       
   267     if ( dbs.fillTestTable(engine) == 0 ) {
       
   268         if(engine.isEmpty())
       
   269            QSKIP( "No database drivers are available in this Qt configuration", SkipAll );
       
   270         else
       
   271            QSKIP( (QString("No database drivers of type %1 are available in this Qt configuration").arg(engine)).toLocal8Bit(), SkipAll );
       
   272     }
       
   273 }
       
   274 
       
   275 void tst_QSqlQuery::dropTestTables( QSqlDatabase db )
       
   276 {
       
   277     QStringList tablenames;
       
   278     // drop all the table in case a testcase failed
       
   279     tablenames <<  qTableName( "qtest" )
       
   280                << qTableName( "qtest_null" )
       
   281                << qTableName( "qtest_blob" )
       
   282                << qTableName( "qtest_bittest" )
       
   283                << qTableName( "qtest_nullblob" )
       
   284                << qTableName( "qtest_rawtest" )
       
   285                << qTableName( "qtest_precision" )
       
   286                << qTableName( "qtest_prepare" )
       
   287                << qTableName( "qtestj1" )
       
   288                << qTableName( "qtestj2" )
       
   289                << qTableName( "char1Select" )
       
   290                << qTableName( "char1SelectUnicode" )
       
   291                << qTableName( "qxmltest" )
       
   292                << qTableName( "qtest_exerr" )
       
   293                << qTableName( "qtest_empty" )
       
   294                << qTableName( "clobby" )
       
   295                << qTableName( "bindtest" )
       
   296                << qTableName( "more_results" )
       
   297                << qTableName( "blobstest" )
       
   298                << qTableName( "oraRowId" )
       
   299                << qTableName( "qtest_batch" );
       
   300 
       
   301     if ( db.driverName().startsWith("QPSQL") )
       
   302         tablenames << qTableName("task_233829");
       
   303 
       
   304     if ( db.driverName().startsWith("QSQLITE") )
       
   305         tablenames << qTableName( "record_sqlite" );
       
   306 
       
   307     if ( tst_Databases::isSqlServer( db ) || db.driverName().startsWith( "QOCI" ) )
       
   308         tablenames << qTableName( "qtest_longstr" );
       
   309 
       
   310     tablenames <<  qTableName( "qtest_lockedtable" );
       
   311 
       
   312     tablenames <<  qTableName( "Planet" );
       
   313 
       
   314     tablenames << qTableName( "task_250026" );
       
   315     tablenames << qTableName( "task_234422" );
       
   316 
       
   317     if (tst_Databases::isSqlServer( db )) {
       
   318         QSqlQuery q( db );
       
   319         q.exec("DROP PROCEDURE " + qTableName("test141895_proc"));
       
   320     }
       
   321 
       
   322     tablenames << qTableName("test141895");
       
   323 
       
   324     tst_Databases::safeDropTables( db, tablenames );
       
   325 }
       
   326 
       
   327 void tst_QSqlQuery::createTestTables( QSqlDatabase db )
       
   328 {
       
   329     QSqlQuery q( db );
       
   330 
       
   331     if ( db.driverName().startsWith( "QMYSQL" ) )
       
   332         // ### stupid workaround until we find a way to hardcode this
       
   333         // in the MySQL server startup script
       
   334         q.exec( "set table_type=innodb" );
       
   335     else if(tst_Databases::isPostgreSQL(db))
       
   336         QVERIFY_SQL( q, exec("set client_min_messages='warning'"));
       
   337 
       
   338     if(tst_Databases::isPostgreSQL(db))
       
   339         QVERIFY_SQL( q, exec( "create table " + qTableName( "qtest" ) + " (id serial NOT NULL, t_varchar varchar(20), t_char char(20), primary key(id)) WITH OIDS" ) );
       
   340     else
       
   341         QVERIFY_SQL( q, exec( "create table " + qTableName( "qtest" ) + " (id int "+tst_Databases::autoFieldName(db) +" NOT NULL, t_varchar varchar(20), t_char char(20), primary key(id))" ) );
       
   342 
       
   343     if ( tst_Databases::isSqlServer( db ) || db.driverName().startsWith( "QTDS" ) )
       
   344         QVERIFY_SQL( q, exec( "create table " + qTableName( "qtest_null" ) + " (id int null, t_varchar varchar(20) null)" ) );
       
   345     else
       
   346         QVERIFY_SQL( q, exec( "create table " + qTableName( "qtest_null" ) + " (id int, t_varchar varchar(20))" ) );
       
   347 }
       
   348 
       
   349 void tst_QSqlQuery::populateTestTables( QSqlDatabase db )
       
   350 {
       
   351     QSqlQuery q( db );
       
   352     q.exec( "delete from " + qTableName( "qtest" ) );
       
   353     QVERIFY_SQL( q, exec( "insert into " + qTableName( "qtest" ) + " values (1, 'VarChar1', 'Char1')" ) );
       
   354     QVERIFY_SQL( q, exec( "insert into " + qTableName( "qtest" ) + " values (2, 'VarChar2', 'Char2')" ) );
       
   355     QVERIFY_SQL( q, exec( "insert into " + qTableName( "qtest" ) + " values (3, 'VarChar3', 'Char3')" ) );
       
   356     QVERIFY_SQL( q, exec( "insert into " + qTableName( "qtest" ) + " values (4, 'VarChar4', 'Char4')" ) );
       
   357     QVERIFY_SQL( q, exec( "insert into " + qTableName( "qtest" ) + " values (5, 'VarChar5', 'Char5')" ) );
       
   358 
       
   359     q.exec( "delete from " + qTableName( "qtest_null" ) );
       
   360     QVERIFY_SQL( q, exec( "insert into " + qTableName( "qtest_null" ) + " values (0, NULL)" ) );
       
   361     QVERIFY_SQL( q, exec( "insert into " + qTableName( "qtest_null" ) + " values (1, 'n')" ) );
       
   362     QVERIFY_SQL( q, exec( "insert into " + qTableName( "qtest_null" ) + " values (2, 'i')" ) );
       
   363     QVERIFY_SQL( q, exec( "insert into " + qTableName( "qtest_null" ) + " values (3, NULL)" ) );
       
   364 }
       
   365 
       
   366 // There were problems with char fields of size 1
       
   367 void tst_QSqlQuery::char1Select()
       
   368 {
       
   369     QFETCH( QString, dbName );
       
   370     QSqlDatabase db = QSqlDatabase::database( dbName );
       
   371     CHECK_DATABASE( db );
       
   372 
       
   373     {
       
   374         QSqlQuery q( db );
       
   375         QVERIFY_SQL( q, exec( "create table " + qTableName( "char1Select" ) + " (id char(1))" ) );
       
   376         QVERIFY_SQL( q, exec( "insert into " + qTableName( "char1Select" ) + " values ('a')" ) );
       
   377         QVERIFY_SQL( q, exec( "select * from " + qTableName( "char1Select" ) ) );
       
   378         QVERIFY( q.next() );
       
   379 
       
   380         if ( db.driverName().startsWith( "QIBASE" ) )
       
   381             QCOMPARE( q.value( 0 ).toString().left( 1 ), QString( "a" ) );
       
   382         else
       
   383             QCOMPARE( q.value( 0 ).toString(), QString( "a" ) );
       
   384 
       
   385         QVERIFY( !q.next() );
       
   386     }
       
   387 }
       
   388 
       
   389 void tst_QSqlQuery::char1SelectUnicode()
       
   390 {
       
   391     QFETCH( QString, dbName );
       
   392     QSqlDatabase db = QSqlDatabase::database( dbName );
       
   393     CHECK_DATABASE( db );
       
   394 
       
   395     if(db.driverName().startsWith("QDB2"))
       
   396         QSKIP("Needs someone with more Unicode knowledge than I have to fix", SkipSingle);
       
   397 
       
   398     if ( db.driver()->hasFeature( QSqlDriver::Unicode ) ) {
       
   399         QString uniStr( QChar( 'का' ) );
       
   400         QSqlQuery q( db );
       
   401 
       
   402         if ( db.driverName().startsWith( "QMYSQL" ) && tst_Databases::getMySqlVersion( db ).section( QChar('.'), 0, 0 ).toInt()<5 )
       
   403             QSKIP( "Test requires MySQL >= 5.0", SkipSingle );
       
   404 
       
   405         QString createQuery;
       
   406 
       
   407         if ( tst_Databases::isSqlServer( db ) )
       
   408             createQuery = "create table " + qTableName( "char1SelectUnicode" ) + "(id nchar(1))";
       
   409         else if ( db.driverName().startsWith( "QDB2" )
       
   410                   || db.driverName().startsWith( "QOCI" )
       
   411                   || db.driverName().startsWith( "QPSQL" ) )
       
   412             createQuery = "create table " + qTableName( "char1SelectUnicode" ) + " (id char(3))";
       
   413         else if ( db.driverName().startsWith( "QIBASE" ) )
       
   414             createQuery = "create table " + qTableName( "char1SelectUnicode" ) +
       
   415                           " (id char(1) character set unicode_fss)";
       
   416         else if ( db.driverName().startsWith( "QMYSQL" ) )
       
   417             createQuery = "create table " + qTableName( "char1SelectUnicode" ) + " (id char(1)) "
       
   418                           "default character set 'utf8'";
       
   419         else
       
   420             createQuery = "create table " + qTableName( "char1SelectUnicode" ) + " (id char(1))";
       
   421 
       
   422         QVERIFY_SQL( q, exec( createQuery ) );
       
   423 
       
   424         QVERIFY_SQL( q, prepare( "insert into " + qTableName( "char1SelectUnicode" ) + " values(?)" ) );
       
   425 
       
   426         q.bindValue( 0, uniStr );
       
   427 
       
   428         QVERIFY_SQL( q, exec() );
       
   429 
       
   430         QVERIFY_SQL( q, exec( "select * from " + qTableName( "char1SelectUnicode" ) ) );
       
   431 
       
   432         QVERIFY( q.next() );
       
   433 
       
   434         if ( !q.value( 0 ).toString().isEmpty() )
       
   435             QCOMPARE( q.value( 0 ).toString()[ 0 ].unicode(), uniStr[0].unicode() );
       
   436 
       
   437         QCOMPARE( q.value( 0 ).toString().trimmed(), uniStr );
       
   438 
       
   439         QVERIFY( !q.next() );
       
   440     }
       
   441     else
       
   442         QSKIP( "Database not unicode capable", SkipSingle );
       
   443 }
       
   444 
       
   445 void tst_QSqlQuery::oraRowId()
       
   446 {
       
   447     QFETCH( QString, dbName );
       
   448     QSqlDatabase db = QSqlDatabase::database( dbName );
       
   449     CHECK_DATABASE( db );
       
   450 
       
   451     QSqlQuery q( db );
       
   452     QVERIFY_SQL( q, exec( "select rowid from " + qTableName( "qtest" ) ) );
       
   453     QVERIFY( q.next() );
       
   454     QCOMPARE( q.value( 0 ).type(), QVariant::String );
       
   455     QVERIFY( !q.value( 0 ).toString().isEmpty() );
       
   456 
       
   457     QVERIFY_SQL( q, exec( "create table " + qTableName( "oraRowId" ) + " (id char(1))" ) );
       
   458 
       
   459     QVERIFY_SQL( q, exec( "insert into " + qTableName( "oraRowId" ) + " values('a')" ) );
       
   460     QVariant v1 = q.lastInsertId();
       
   461     QVERIFY( v1.isValid() );
       
   462 
       
   463     QVERIFY_SQL( q, exec( "insert into " + qTableName( "oraRowId" ) + " values('b')" ) );
       
   464     QVariant v2 = q.lastInsertId();
       
   465     QVERIFY( v2.isValid() );
       
   466 
       
   467     QVERIFY_SQL( q, prepare( "select * from " + qTableName( "oraRowId" ) + " where rowid = ?" ) );
       
   468     q.addBindValue( v1 );
       
   469     QVERIFY_SQL( q, exec() );
       
   470     QVERIFY( q.next() );
       
   471     QCOMPARE( q.value( 0 ).toString(), QString( "a" ) );
       
   472 
       
   473     q.addBindValue( v2 );
       
   474     QVERIFY_SQL( q, exec() );
       
   475     QVERIFY( q.next() );
       
   476     QCOMPARE( q.value( 0 ).toString(), QString( "b" ) );
       
   477 }
       
   478 
       
   479 void tst_QSqlQuery::mysqlOutValues()
       
   480 {
       
   481     QFETCH( QString, dbName );
       
   482     QSqlDatabase db = QSqlDatabase::database( dbName );
       
   483     CHECK_DATABASE( db );
       
   484 
       
   485     QSqlQuery q( db );
       
   486 
       
   487     if ( db.driverName().startsWith( "QMYSQL" ) && tst_Databases::getMySqlVersion( db ).section( QChar('.'), 0, 0 ).toInt()<5 )
       
   488         QSKIP( "Test requires MySQL >= 5.0", SkipSingle );
       
   489 
       
   490     q.exec( "drop function " + qTableName( "hello" ) );
       
   491 
       
   492     QVERIFY_SQL( q, exec( "create function " + qTableName( "hello" ) + " (s char(20)) returns varchar(50) return concat('Hello ', s)" ) );
       
   493 
       
   494     QVERIFY_SQL( q, exec( "select " + qTableName( "hello" ) + "('world')" ) );
       
   495     QVERIFY_SQL( q, next() );
       
   496 
       
   497     QCOMPARE( q.value( 0 ).toString(), QString( "Hello world" ) );
       
   498 
       
   499     QVERIFY_SQL( q, prepare( "select " + qTableName( "hello" ) + "('harald')" ) );
       
   500     QVERIFY_SQL( q, exec() );
       
   501     QVERIFY_SQL( q, next() );
       
   502 
       
   503     QCOMPARE( q.value( 0 ).toString(), QString( "Hello harald" ) );
       
   504 
       
   505     QVERIFY_SQL( q, exec( "drop function " + qTableName( "hello" ) ) );
       
   506 
       
   507     q.exec( "drop procedure " + qTableName( "qtestproc" ) );
       
   508 
       
   509     QVERIFY_SQL( q, exec( "create procedure " + qTableName( "qtestproc" ) + " () "
       
   510                             "BEGIN select * from " + qTableName( "qtest" ) + " order by id; END" ) );
       
   511     QVERIFY_SQL( q, exec( "call " + qTableName( "qtestproc" ) + "()" ) );
       
   512     QVERIFY_SQL( q, next() );
       
   513     QCOMPARE( q.value( 1 ).toString(), QString( "VarChar1" ) );
       
   514 
       
   515     QVERIFY_SQL( q, exec( "drop procedure " + qTableName( "qtestproc" ) ) );
       
   516 
       
   517     QVERIFY_SQL( q, exec( "create procedure " + qTableName( "qtestproc" ) + " (OUT param1 INT) "
       
   518                             "BEGIN set param1 = 42; END" ) );
       
   519 
       
   520     QVERIFY_SQL( q, exec( "call " + qTableName( "qtestproc" ) + " (@out)" ) );
       
   521     QVERIFY_SQL( q, exec( "select @out" ) );
       
   522     QCOMPARE( q.record().fieldName( 0 ), QString( "@out" ) );
       
   523     QVERIFY_SQL( q, next() );
       
   524     QCOMPARE( q.value( 0 ).toInt(), 42 );
       
   525 
       
   526     QVERIFY_SQL( q, exec( "drop procedure " + qTableName( "qtestproc" ) ) );
       
   527 }
       
   528 
       
   529 void tst_QSqlQuery::oraOutValues()
       
   530 {
       
   531     QFETCH( QString, dbName );
       
   532     QSqlDatabase db = QSqlDatabase::database( dbName );
       
   533     CHECK_DATABASE( db );
       
   534 
       
   535     if ( !db.driver()->hasFeature( QSqlDriver::PreparedQueries ) ) {
       
   536         QSKIP( "Test requires prepared query support", SkipSingle );
       
   537         return;
       
   538     }
       
   539 
       
   540     QSqlQuery q( db );
       
   541 
       
   542     q.setForwardOnly( true );
       
   543 
       
   544     /*** outvalue int ***/
       
   545     QVERIFY_SQL( q, exec( "create or replace procedure " + qTableName( "tst_outValues" ) + "(x out int) is\n"
       
   546                             "begin\n"
       
   547                             "    x := 42;\n"
       
   548                             "end;\n" ) );
       
   549     QVERIFY( q.prepare( "call " + qTableName( "tst_outvalues" ) + "(?)" ) );
       
   550     q.addBindValue( 0, QSql::Out );
       
   551     QVERIFY_SQL( q, exec() );
       
   552     QCOMPARE( q.boundValue( 0 ).toInt(), 42 );
       
   553 
       
   554     // bind a null value, make sure the OCI driver resets the null flag
       
   555     q.addBindValue( QVariant( QVariant::Int ), QSql::Out );
       
   556     QVERIFY_SQL( q, exec() );
       
   557     QCOMPARE( q.boundValue( 0 ).toInt(), 42 );
       
   558     QVERIFY( !q.boundValue( 0 ).isNull() );
       
   559 
       
   560     /*** outvalue varchar ***/
       
   561     QVERIFY_SQL( q, exec( "create or replace procedure " + qTableName( "tst_outValues" ) + "(x out varchar) is\n"
       
   562                             "begin\n"
       
   563                             "    x := 'blah';\n"
       
   564                             "end;\n" ) );
       
   565     QVERIFY( q.prepare( "call " + qTableName( "tst_outvalues" ) + "(?)" ) );
       
   566     QString s1( "12345" );
       
   567     s1.reserve( 512 );
       
   568     q.addBindValue( s1, QSql::Out );
       
   569     QVERIFY_SQL( q, exec() );
       
   570     QCOMPARE( q.boundValue( 0 ).toString(), QString( "blah" ) );
       
   571 
       
   572     /*** in/outvalue numeric ***/
       
   573     QVERIFY_SQL( q, exec( "create or replace procedure " + qTableName( "tst_outValues" ) + "(x in out numeric) is\n"
       
   574                             "begin\n"
       
   575                             "    x := x + 10;\n"
       
   576                             "end;\n" ) );
       
   577     QVERIFY( q.prepare( "call " + qTableName( "tst_outvalues" ) + "(?)" ) );
       
   578     q.addBindValue( 10, QSql::Out );
       
   579     QVERIFY_SQL( q, exec() );
       
   580     QCOMPARE( q.boundValue( 0 ).toInt(), 20 );
       
   581 
       
   582     /*** in/outvalue varchar ***/
       
   583     QVERIFY_SQL( q, exec( "create or replace procedure " + qTableName( "tst_outValues" ) + "(x in out varchar) is\n"
       
   584                             "begin\n"
       
   585                             "    x := 'homer';\n"
       
   586                             "end;\n" ) );
       
   587     QVERIFY( q.prepare( "call " + qTableName( "tst_outvalues" ) + "(?)" ) );
       
   588     q.addBindValue( QString( "maggy" ), QSql::Out );
       
   589     QVERIFY_SQL( q, exec() );
       
   590     QCOMPARE( q.boundValue( 0 ).toString(), QString( "homer" ) );
       
   591 
       
   592     /*** in/outvalue varchar ***/
       
   593     QVERIFY_SQL( q, exec( "create or replace procedure " + qTableName( "tst_outValues" ) + "(x in out varchar) is\n"
       
   594                             "begin\n"
       
   595                             "    x := NULL;\n"
       
   596                             "end;\n" ) );
       
   597     QVERIFY( q.prepare( "call " + qTableName( "tst_outvalues" ) + "(?)" ) );
       
   598     q.addBindValue( QString( "maggy" ), QSql::Out );
       
   599     QVERIFY_SQL( q, exec() );
       
   600     QVERIFY( q.boundValue( 0 ).isNull() );
       
   601 
       
   602     /*** in/outvalue int ***/
       
   603     QVERIFY_SQL( q, exec( "create or replace procedure " + qTableName( "tst_outValues" ) + "(x in out int) is\n"
       
   604                             "begin\n"
       
   605                             "    x := NULL;\n"
       
   606                             "end;\n" ) );
       
   607     QVERIFY( q.prepare( "call " + qTableName( "tst_outvalues" ) + "(?)" ) );
       
   608     q.addBindValue( 42, QSql::Out );
       
   609     QVERIFY_SQL( q, exec() );
       
   610     QVERIFY( q.boundValue( 0 ).isNull() );
       
   611 
       
   612     /*** in/outvalue varchar ***/
       
   613     QVERIFY_SQL( q, exec( "create or replace procedure " + qTableName( "tst_outValues" ) + "(x in varchar, y out varchar) is\n"
       
   614                             "begin\n"
       
   615                             "    y := x||'bubulalakikikokololo';\n"
       
   616                             "end;\n" ) );
       
   617     QVERIFY( q.prepare( "call " + qTableName( "tst_outvalues" ) + "(?, ?)" ) );
       
   618     q.addBindValue( QString( "fifi" ), QSql::In );
       
   619     QString out;
       
   620     out.reserve( 50 );
       
   621     q.addBindValue( out, QSql::Out );
       
   622     QVERIFY_SQL( q, exec() );
       
   623     QCOMPARE( q.boundValue( 1 ).toString(), QString( "fifibubulalakikikokololo" ) );
       
   624 }
       
   625 
       
   626 void tst_QSqlQuery::oraClob()
       
   627 {
       
   628     QFETCH( QString, dbName );
       
   629     QSqlDatabase db = QSqlDatabase::database( dbName );
       
   630     CHECK_DATABASE( db );
       
   631 
       
   632     QSqlQuery q( db );
       
   633 
       
   634     // simple short string
       
   635     QVERIFY_SQL( q, exec( "create table " + qTableName( "clobby" ) + "(id int primary key, cl clob, bl blob)" ) );
       
   636     QVERIFY_SQL( q, prepare( "insert into " + qTableName( "clobby" ) + " (id, cl, bl) values(?, ?, ?)" ) );
       
   637     q.addBindValue( 1 );
       
   638     q.addBindValue( "bubu" );
       
   639     q.addBindValue( QByteArray("bubu") );
       
   640     QVERIFY_SQL( q, exec() );
       
   641 
       
   642     QVERIFY_SQL( q, exec( "select bl, cl from " + qTableName( "clobby" ) + " where id = 1" ) );
       
   643     QVERIFY( q.next() );
       
   644     QCOMPARE( q.value( 0 ).toString(), QString( "bubu" ) );
       
   645     QCOMPARE( q.value( 1 ).toString(), QString( "bubu" ) );
       
   646 
       
   647     // simple short string with binding
       
   648     QVERIFY_SQL( q, prepare( "insert into " + qTableName( "clobby" ) + " (id, cl, bl) values(?, ?, ?)" ) );
       
   649     q.addBindValue( 2 );
       
   650     q.addBindValue( "lala", QSql::Binary );
       
   651     q.addBindValue( QByteArray("lala"), QSql::Binary );
       
   652     QVERIFY_SQL( q, exec() );
       
   653 
       
   654     QVERIFY_SQL( q, exec( "select bl, cl from " + qTableName( "clobby" ) + " where id = 2" ) );
       
   655     QVERIFY( q.next() );
       
   656     QCOMPARE( q.value( 0 ).toString(), QString( "lala" ) );
       
   657     QCOMPARE( q.value( 1 ).toString(), QString( "lala" ) );
       
   658 
       
   659     // loooong string
       
   660     QString loong;
       
   661     loong.fill( QLatin1Char( 'A' ), 25000 );
       
   662     QVERIFY_SQL( q, prepare( "insert into " + qTableName( "clobby" ) + " (id, cl, bl) values(?, ?, ?)" ) );
       
   663     q.addBindValue( 3 );
       
   664     q.addBindValue( loong, QSql::Binary );
       
   665     q.addBindValue( loong.toLatin1(), QSql::Binary );
       
   666     QVERIFY_SQL( q, exec() );
       
   667 
       
   668     QVERIFY_SQL( q, exec( "select bl, cl from " + qTableName( "clobby" ) + " where id = 3" ) );
       
   669     QVERIFY( q.next() );
       
   670     QCOMPARE( q.value( 0 ).toString().count(), loong.count() );
       
   671     QVERIFY( q.value( 0 ).toString() == loong );
       
   672     QCOMPARE( q.value( 1 ).toByteArray().count(), loong.toLatin1().count() );
       
   673     QVERIFY( q.value( 1 ).toByteArray() == loong.toLatin1() );
       
   674 }
       
   675 
       
   676 void tst_QSqlQuery::storedProceduresIBase()
       
   677 {
       
   678     QFETCH( QString, dbName );
       
   679     QSqlDatabase db = QSqlDatabase::database( dbName );
       
   680     CHECK_DATABASE( db );
       
   681 
       
   682     QSqlQuery q( db );
       
   683     q.exec( "drop procedure " + qTableName( "TESTPROC" ) );
       
   684 
       
   685     QVERIFY_SQL( q, exec( "create procedure " + qTableName( "TESTPROC" ) +
       
   686                             " RETURNS (x integer, y varchar(20)) "
       
   687                             "AS BEGIN "
       
   688                             "  x = 42; "
       
   689                             "  y = 'Hello Anders'; "
       
   690                             "END" ) );
       
   691 
       
   692     QVERIFY_SQL( q, prepare( "execute procedure " + qTableName( "TestProc" ) ) );
       
   693     QVERIFY_SQL( q, exec() );
       
   694 
       
   695     // check for a valid result set
       
   696     QSqlRecord rec = q.record();
       
   697     QCOMPARE( rec.count(), 2 );
       
   698     QCOMPARE( rec.fieldName( 0 ).toUpper(), QString( "X" ) );
       
   699     QCOMPARE( rec.fieldName( 1 ).toUpper(), QString( "Y" ) );
       
   700 
       
   701     // the first next shall suceed
       
   702     QVERIFY_SQL( q, next() );
       
   703     QCOMPARE( q.value( 0 ).toInt(), 42 );
       
   704     QCOMPARE( q.value( 1 ).toString(), QString( "Hello Anders" ) );
       
   705 
       
   706     // the second next shall fail
       
   707     QVERIFY( !q.next() );
       
   708 
       
   709     q.exec( "drop procedure " + qTableName( "TestProc" ) );
       
   710 }
       
   711 
       
   712 void tst_QSqlQuery::outValuesDB2()
       
   713 {
       
   714     QFETCH( QString, dbName );
       
   715     QSqlDatabase db = QSqlDatabase::database( dbName );
       
   716     CHECK_DATABASE( db );
       
   717 
       
   718     if ( !db.driver()->hasFeature( QSqlDriver::PreparedQueries ) ) {
       
   719         QSKIP( "Test requires prepared query support", SkipSingle );
       
   720         return;
       
   721     }
       
   722 
       
   723     QSqlQuery q( db );
       
   724 
       
   725     q.setForwardOnly( true );
       
   726 
       
   727     q.exec( "drop procedure " + qTableName( "tst_outValues" ) ); //non-fatal
       
   728     QVERIFY_SQL( q, exec( "CREATE PROCEDURE " + qTableName( "tst_outValues" ) +
       
   729                             " (OUT x int, OUT x2 double, OUT x3 char(20))\n"
       
   730                             "LANGUAGE SQL\n"
       
   731                             "P1: BEGIN\n"
       
   732                             " SET x = 42;\n"
       
   733                             " SET x2 = 4.2;\n"
       
   734                             " SET x3 = 'Homer';\n"
       
   735                             "END P1" ) );
       
   736 
       
   737     QVERIFY_SQL( q, prepare( "call " + qTableName( "tst_outValues" ) + "(?, ?, ?)" ) );
       
   738 
       
   739     q.addBindValue( 0, QSql::Out );
       
   740     q.addBindValue( 0.0, QSql::Out );
       
   741     q.addBindValue( "Simpson", QSql::Out );
       
   742 
       
   743     QVERIFY_SQL( q, exec() );
       
   744 
       
   745     QCOMPARE( q.boundValue( 0 ).toInt(), 42 );
       
   746     QCOMPARE( q.boundValue( 1 ).toDouble(), 4.2 );
       
   747     QCOMPARE( q.boundValue( 2 ).toString().trimmed(), QString( "Homer" ) );
       
   748 }
       
   749 
       
   750 void tst_QSqlQuery::outValues()
       
   751 {
       
   752     QFETCH( QString, dbName );
       
   753     QSqlDatabase db = QSqlDatabase::database( dbName );
       
   754     CHECK_DATABASE( db );
       
   755 
       
   756     if ( !db.driver()->hasFeature( QSqlDriver::PreparedQueries ) ) {
       
   757         QSKIP( "Test requires prepared query support", SkipSingle );
       
   758         return;
       
   759     }
       
   760 
       
   761     QSqlQuery q( db );
       
   762 
       
   763     q.setForwardOnly( true );
       
   764 
       
   765     if ( db.driverName().startsWith( "QOCI" ) ) {
       
   766         QVERIFY_SQL( q, exec( "create or replace procedure " + qTableName( "tst_outValues" ) + "(x out int) is\n"
       
   767                                 "begin\n"
       
   768                                 "    x := 42;\n"
       
   769                                 "end;\n" ) );
       
   770         QVERIFY( q.prepare( "call " + qTableName( "tst_outvalues" ) + "(?)" ) );
       
   771     } else if ( db.driverName().startsWith( "QDB2" ) ) {
       
   772         q.exec( "drop procedure " + qTableName( "tst_outValues" ) ); //non-fatal
       
   773         QVERIFY_SQL( q, exec( "CREATE PROCEDURE " + qTableName( "tst_outValues" ) + " (OUT x int)\n"
       
   774                                 "LANGUAGE SQL\n"
       
   775                                 "P1: BEGIN\n"
       
   776                                 " SET x = 42;\n"
       
   777                                 "END P1" ) );
       
   778         QVERIFY( q.prepare( "call " + qTableName( "tst_outValues" ) + "(?)" ) );
       
   779     } else if ( tst_Databases::isSqlServer( db ) ) {
       
   780         q.exec( "drop procedure " + qTableName( "tst_outValues" ) );  //non-fatal
       
   781         QVERIFY_SQL( q, exec( "create procedure " + qTableName( "tst_outValues" ) + " (@x int out) as\n"
       
   782                                 "begin\n"
       
   783                                 "    set @x = 42\n"
       
   784                                 "end\n" ) );
       
   785         QVERIFY( q.prepare( "{call " + qTableName( "tst_outvalues" ) + "(?)}" ) );
       
   786     } else {
       
   787         QSKIP( "Don't know how to create a stored procedure for this database server, please fix this test", SkipSingle );
       
   788         return;
       
   789     }
       
   790 
       
   791     q.addBindValue( 0, QSql::Out );
       
   792 
       
   793     QVERIFY_SQL( q, exec() );
       
   794 
       
   795     QCOMPARE( q.boundValue( 0 ).toInt(), 42 );
       
   796 }
       
   797 
       
   798 void tst_QSqlQuery::blob()
       
   799 {
       
   800     static const int BLOBSIZE = 1024 * 10;
       
   801     static const int BLOBCOUNT = 2;
       
   802 
       
   803     QFETCH( QString, dbName );
       
   804     QSqlDatabase db = QSqlDatabase::database( dbName );
       
   805     CHECK_DATABASE( db );
       
   806 
       
   807     if ( !db.driver()->hasFeature( QSqlDriver::BLOB ) )
       
   808         QSKIP( "DBMS not BLOB capable", SkipSingle );
       
   809 
       
   810     //don' make it too big otherwise sybase and mysql will complain
       
   811     QByteArray ba( BLOBSIZE, 0 );
       
   812 
       
   813     int i;
       
   814 
       
   815     for ( i = 0; i < ( int )ba.size(); ++i )
       
   816         ba[i] = i % 256;
       
   817 
       
   818     QSqlQuery q( db );
       
   819 
       
   820     q.setForwardOnly( true );
       
   821 
       
   822     QString queryString = QString( "create table " + qTableName( "qtest_blob" ) +
       
   823                                    " (id int not null primary key, t_blob %1)" ).arg( tst_Databases::blobTypeName( db, BLOBSIZE ) );
       
   824     QVERIFY_SQL( q, exec( queryString ) );
       
   825 
       
   826     QVERIFY_SQL( q, prepare( "insert into " + qTableName( "qtest_blob" ) + " (id, t_blob) values (?, ?)" ) );
       
   827 
       
   828     for ( i = 0; i < BLOBCOUNT; ++i ) {
       
   829         q.addBindValue( i );
       
   830         q.addBindValue( ba );
       
   831         QVERIFY_SQL( q, exec() );
       
   832     }
       
   833 
       
   834     QVERIFY_SQL( q, exec( "select * from " + qTableName( "qtest_blob" ) ) );
       
   835 
       
   836     for ( i = 0; i < BLOBCOUNT; ++i ) {
       
   837         QVERIFY( q.next() );
       
   838         QByteArray res = q.value( 1 ).toByteArray();
       
   839         QVERIFY2( res.size() >= ba.size(),
       
   840                   QString( "array sizes differ, expected %1, got %2" ).arg( ba.size() ).arg( res.size() ).toLatin1() );
       
   841 
       
   842         for ( int i2 = 0; i2 < ( int )ba.size(); ++i2 ) {
       
   843             if ( res[i2] != ba[i2] )
       
   844                 QFAIL( QString( "ByteArrays differ at position %1, expected %2, got %3" ).arg(
       
   845                            i2 ).arg(( int )( unsigned char )ba[i2] ).arg(( int )( unsigned char )res[i2] ).toLatin1() );
       
   846         }
       
   847     }
       
   848 }
       
   849 
       
   850 void tst_QSqlQuery::value()
       
   851 {
       
   852     QFETCH( QString, dbName );
       
   853     QSqlDatabase db = QSqlDatabase::database( dbName );
       
   854     CHECK_DATABASE( db );
       
   855 
       
   856     QSqlQuery q( db );
       
   857     QVERIFY_SQL( q, exec( "select id, t_varchar, t_char from " + qTableName( "qtest" ) + " order by id" ) );
       
   858     int i = 1;
       
   859 
       
   860     while ( q.next() ) {
       
   861         QCOMPARE( q.value( 0 ).toInt(), i );
       
   862 
       
   863         if ( db.driverName().startsWith( "QIBASE" ) )
       
   864             QVERIFY( q.value( 1 ).toString().startsWith( "VarChar" + QString::number( i ) ) );
       
   865         else if ( q.value( 1 ).toString().right( 1 ) == " " )
       
   866             QCOMPARE( q.value( 1 ).toString(), ( "VarChar" + QString::number( i ) + "            " ) );
       
   867         else
       
   868             QCOMPARE( q.value( 1 ).toString(), ( "VarChar" + QString::number( i ) ) );
       
   869 
       
   870         if ( db.driverName().startsWith( "QIBASE" ) )
       
   871             QVERIFY( q.value( 2 ).toString().startsWith( "Char" + QString::number( i ) ) );
       
   872         else if ( q.value( 2 ).toString().right( 1 ) != " " )
       
   873             QCOMPARE( q.value( 2 ).toString(), ( "Char" + QString::number( i ) ) );
       
   874         else
       
   875             QCOMPARE( q.value( 2 ).toString(), ( "Char" + QString::number( i ) + "               " ) );
       
   876 
       
   877         i++;
       
   878     }
       
   879 }
       
   880 
       
   881 void tst_QSqlQuery::record()
       
   882 {
       
   883     QFETCH( QString, dbName );
       
   884     QSqlDatabase db = QSqlDatabase::database( dbName );
       
   885     CHECK_DATABASE( db );
       
   886 
       
   887     QSqlQuery q( db );
       
   888     QVERIFY( q.record().isEmpty() );
       
   889     QVERIFY_SQL( q, exec( "select id, t_varchar, t_char from " + qTableName( "qtest" ) + " order by id" ) );
       
   890     QSqlRecord rec = q.record();
       
   891     QCOMPARE( q.record().fieldName( 0 ).toLower(), QString( "id" ) );
       
   892     QCOMPARE( q.record().fieldName( 1 ).toLower(), QString( "t_varchar" ) );
       
   893     QCOMPARE( q.record().fieldName( 2 ).toLower(), QString( "t_char" ) );
       
   894     QVERIFY( !q.record().value( 0 ).isValid() );
       
   895     QVERIFY( !q.record().value( 1 ).isValid() );
       
   896     QVERIFY( !q.record().value( 2 ).isValid() );
       
   897 
       
   898     QVERIFY( q.next() );
       
   899     QVERIFY( q.next() );
       
   900 
       
   901     QCOMPARE( q.record().fieldName( 0 ).toLower(), QString( "id" ) );
       
   902     QCOMPARE( q.value( 0 ).toInt(), 2 );
       
   903 }
       
   904 
       
   905 void tst_QSqlQuery::isValid()
       
   906 {
       
   907     QFETCH( QString, dbName );
       
   908     QSqlDatabase db = QSqlDatabase::database( dbName );
       
   909     CHECK_DATABASE( db );
       
   910 
       
   911     QSqlQuery q( db );
       
   912     QVERIFY( !q.isValid() );
       
   913     QVERIFY_SQL( q, exec( "select * from " + qTableName( "qtest" ) ) );
       
   914     QVERIFY( q.first() );
       
   915     QVERIFY( q.isValid() );
       
   916 }
       
   917 
       
   918 void tst_QSqlQuery::isActive()
       
   919 {
       
   920     QFETCH( QString, dbName );
       
   921     QSqlDatabase db = QSqlDatabase::database( dbName );
       
   922     CHECK_DATABASE( db );
       
   923 
       
   924     QSqlQuery q( db );
       
   925     QVERIFY( !q.isActive() );
       
   926     QVERIFY_SQL( q, exec( "select * from " + qTableName( "qtest" ) ) );
       
   927     QVERIFY( q.isActive() );
       
   928     QVERIFY( q.last() );
       
   929 
       
   930     if ( !tst_Databases::isMSAccess( db ) )
       
   931         // Access is stupid enough to let you scroll over boundaries
       
   932         QVERIFY( !q.next() );
       
   933 
       
   934     QVERIFY( q.isActive() );
       
   935 
       
   936     QVERIFY_SQL( q, exec( "insert into " + qTableName( "qtest" ) + " values (41, 'VarChar41', 'Char41')" ) );
       
   937 
       
   938     QVERIFY( q.isActive() );
       
   939 
       
   940     QVERIFY_SQL( q, exec( "update " + qTableName( "qtest" ) + " set id = 42 where id = 41" ) );
       
   941 
       
   942     QVERIFY( q.isActive() );
       
   943 
       
   944     QVERIFY_SQL( q, exec( "delete from " + qTableName( "qtest" ) + " where id = 42" ) );
       
   945 
       
   946     QVERIFY( q.isActive() );
       
   947 }
       
   948 
       
   949 void tst_QSqlQuery::numRowsAffected()
       
   950 {
       
   951     QFETCH( QString, dbName );
       
   952     QSqlDatabase db = QSqlDatabase::database( dbName );
       
   953     CHECK_DATABASE( db );
       
   954 
       
   955     QSqlQuery q( db );
       
   956     QCOMPARE( q.numRowsAffected(), -1 );
       
   957 
       
   958     QVERIFY_SQL( q, exec( "select * from " + qTableName( "qtest" ) ) );
       
   959     int i = 0;
       
   960 
       
   961     while ( q.next() )
       
   962         ++i;
       
   963 
       
   964     if ( q.numRowsAffected() == -1 || q.numRowsAffected() == 0 )
       
   965         QSKIP("Database doesn't support numRowsAffected", SkipSingle);
       
   966 
       
   967     if ( q.numRowsAffected() != -1 && q.numRowsAffected() != 0 && q.numRowsAffected() != i ) {
       
   968         // the value is undefined for SELECT, this check is just here for curiosity
       
   969         qDebug( "Expected numRowsAffected to be -1, 0 or %d, got %d", i, q.numRowsAffected() );
       
   970     }
       
   971 
       
   972     QVERIFY_SQL( q, exec( "update " + qTableName( "qtest" ) + " set id = 100 where id = 1" ) );
       
   973 
       
   974     QCOMPARE( q.numRowsAffected(), 1 );
       
   975     QCOMPARE( q.numRowsAffected(), 1 ); // yes, we check twice
       
   976 
       
   977     QVERIFY_SQL( q, exec( "update " + qTableName( "qtest" ) + " set id = id + 100" ) );
       
   978     QCOMPARE( q.numRowsAffected(), i );
       
   979     QCOMPARE( q.numRowsAffected(), i ); // yes, we check twice
       
   980 
       
   981     QVERIFY_SQL( q, exec( "insert into " + qTableName( "qtest" ) + " values (42000, 'homer', 'marge')" ) );
       
   982     QCOMPARE( q.numRowsAffected(), 1 );
       
   983     QCOMPARE( q.numRowsAffected(), 1 ); // yes, we check twice
       
   984 
       
   985     QSqlQuery q2( db );
       
   986     QVERIFY_SQL( q2, exec( "insert into " + qTableName( "qtest" ) + " values (42001, 'homer', 'marge')" ) );
       
   987 
       
   988     if ( !db.driverName().startsWith( "QSQLITE2" ) ) {
       
   989         // SQLite 2.x accumulates changed rows in nested queries. See task 33794
       
   990         QCOMPARE( q2.numRowsAffected(), 1 );
       
   991         QCOMPARE( q2.numRowsAffected(), 1 ); // yes, we check twice
       
   992     }
       
   993 }
       
   994 
       
   995 void tst_QSqlQuery::size()
       
   996 {
       
   997     QFETCH( QString, dbName );
       
   998     QSqlDatabase db = QSqlDatabase::database( dbName );
       
   999     CHECK_DATABASE( db );
       
  1000 
       
  1001     QSqlQuery q( db );
       
  1002     QCOMPARE( q.size(), -1 );
       
  1003 
       
  1004     QVERIFY_SQL( q, exec( "select * from " + qTableName( "qtest" ) ) );
       
  1005     int i = 0;
       
  1006 
       
  1007     while ( q.next() )
       
  1008         ++i;
       
  1009 
       
  1010     if ( db.driver()->hasFeature( QSqlDriver::QuerySize ) ) {
       
  1011         QCOMPARE( q.size(), i );
       
  1012         QCOMPARE( q.size(), i ); // yes, twice
       
  1013     } else {
       
  1014         QCOMPARE( q.size(), -1 );
       
  1015         QCOMPARE( q.size(), -1 ); // yes, twice
       
  1016     }
       
  1017 
       
  1018     QSqlQuery q2( "select * from " + qTableName( "qtest" ), db );
       
  1019 
       
  1020     if ( db.driver()->hasFeature( QSqlDriver::QuerySize ) )
       
  1021         QCOMPARE( q.size(), i );
       
  1022     else
       
  1023         QCOMPARE( q.size(), -1 );
       
  1024 
       
  1025     q2.clear();
       
  1026 
       
  1027     QVERIFY_SQL( q, exec( "update " + qTableName( "qtest" ) + " set id = 100 where id = 1" ) );
       
  1028     QCOMPARE( q.size(), -1 );
       
  1029     QCOMPARE( q.size(), -1 ); // yes, twice
       
  1030 }
       
  1031 
       
  1032 void tst_QSqlQuery::isSelect()
       
  1033 {
       
  1034     QFETCH( QString, dbName );
       
  1035     QSqlDatabase db = QSqlDatabase::database( dbName );
       
  1036     CHECK_DATABASE( db );
       
  1037 
       
  1038     QSqlQuery q( db );
       
  1039     QVERIFY_SQL( q, exec( "select * from " + qTableName( "qtest" ) ) );
       
  1040     QVERIFY( q.isSelect() );
       
  1041 
       
  1042     QVERIFY_SQL( q, exec( "update " + qTableName( "qtest" ) + " set id = 1 where id = 1" ) );
       
  1043     QVERIFY( q.isSelect() == false );
       
  1044 }
       
  1045 
       
  1046 void tst_QSqlQuery::first()
       
  1047 {
       
  1048     QFETCH( QString, dbName );
       
  1049     QSqlDatabase db = QSqlDatabase::database( dbName );
       
  1050     CHECK_DATABASE( db );
       
  1051 
       
  1052     QSqlQuery q( db );
       
  1053     QVERIFY( q.at() == QSql::BeforeFirstRow );
       
  1054     QVERIFY_SQL( q, exec( "select * from " + qTableName( "qtest" ) ) );
       
  1055     QVERIFY( q.last() );
       
  1056     QVERIFY_SQL( q, first() );
       
  1057     QVERIFY( q.at() == 0 );
       
  1058 }
       
  1059 
       
  1060 void tst_QSqlQuery::next()
       
  1061 {
       
  1062     QFETCH( QString, dbName );
       
  1063     QSqlDatabase db = QSqlDatabase::database( dbName );
       
  1064     CHECK_DATABASE( db );
       
  1065 
       
  1066     QSqlQuery q( db );
       
  1067     QVERIFY( q.at() == QSql::BeforeFirstRow );
       
  1068     QVERIFY_SQL( q, exec( "select * from " + qTableName( "qtest" ) ) );
       
  1069     QVERIFY( q.first() );
       
  1070     QVERIFY( q.next() );
       
  1071     QVERIFY( q.at() == 1 );
       
  1072 }
       
  1073 
       
  1074 void tst_QSqlQuery::prev()
       
  1075 {
       
  1076     QFETCH( QString, dbName );
       
  1077     QSqlDatabase db = QSqlDatabase::database( dbName );
       
  1078     CHECK_DATABASE( db );
       
  1079 
       
  1080     QSqlQuery q( db );
       
  1081     QVERIFY( q.at() == QSql::BeforeFirstRow );
       
  1082     QVERIFY_SQL( q, exec( "select * from " + qTableName( "qtest" ) ) );
       
  1083     QVERIFY( q.first() );
       
  1084     QVERIFY( q.next() );
       
  1085     QVERIFY( q.previous() );
       
  1086     QVERIFY( q.at() == 0 );
       
  1087 }
       
  1088 
       
  1089 void tst_QSqlQuery::last()
       
  1090 {
       
  1091     QFETCH( QString, dbName );
       
  1092     QSqlDatabase db = QSqlDatabase::database( dbName );
       
  1093     CHECK_DATABASE( db );
       
  1094 
       
  1095     QSqlQuery q( db );
       
  1096     QCOMPARE( q.at(), int( QSql::BeforeFirstRow ) );
       
  1097     QVERIFY_SQL( q, exec( "select * from " + qTableName( "qtest" ) ) );
       
  1098     int i = 0;
       
  1099 
       
  1100     while ( q.next() )
       
  1101         i++;
       
  1102 
       
  1103     QCOMPARE( q.at(), int( QSql::AfterLastRow ) );
       
  1104 
       
  1105     QVERIFY( q.last() );
       
  1106 
       
  1107     if ( !tst_Databases::isMSAccess( db ) )
       
  1108         // Access doesn't return the correct position
       
  1109         QCOMPARE( q.at(), ( i-1 ) );
       
  1110 
       
  1111     QSqlQuery q2( "select * from " + qTableName( "qtest" ), db );
       
  1112 
       
  1113     QVERIFY( q2.last() );
       
  1114 
       
  1115     if ( !tst_Databases::isMSAccess( db ) )
       
  1116         // Access doesn't return the correct position
       
  1117         QCOMPARE( q.at(), ( i-1 ) );
       
  1118 }
       
  1119 
       
  1120 void tst_QSqlQuery::seek()
       
  1121 {
       
  1122     QFETCH( QString, dbName );
       
  1123     QSqlDatabase db = QSqlDatabase::database( dbName );
       
  1124     CHECK_DATABASE( db );
       
  1125     QSqlQuery q( db );
       
  1126     QVERIFY( q.at() == QSql::BeforeFirstRow );
       
  1127     QVERIFY_SQL( q, exec( QString( "select id from %1 order by id" ).arg( qTableName( "qtest" ) ) ) );
       
  1128 
       
  1129     // NB! The order of the calls below are important!
       
  1130     QVERIFY( q.last() );
       
  1131     QVERIFY( !q.seek( QSql::BeforeFirstRow ) );
       
  1132     QCOMPARE( q.at(), int( QSql::BeforeFirstRow ) );
       
  1133     QVERIFY( q.seek( 0 ) );
       
  1134     QCOMPARE( q.at(), 0 );
       
  1135     QCOMPARE( q.value( 0 ).toInt(), 1 );
       
  1136 
       
  1137     QVERIFY( q.seek( 1 ) );
       
  1138     QCOMPARE( q.at(), 1 );
       
  1139     QCOMPARE( q.value( 0 ).toInt(), 2 );
       
  1140 
       
  1141     QVERIFY( q.seek( 3 ) );
       
  1142     QCOMPARE( q.at(), 3 );
       
  1143     QCOMPARE( q.value( 0 ).toInt(), 4 );
       
  1144 
       
  1145     QVERIFY( q.seek( -2, true ) );
       
  1146     QCOMPARE( q.at(), 1 );
       
  1147     QVERIFY( q.seek( 0 ) );
       
  1148     QCOMPARE( q.at(), 0 );
       
  1149     QCOMPARE( q.value( 0 ).toInt(), 1 );
       
  1150 }
       
  1151 
       
  1152 void tst_QSqlQuery::seekForwardOnlyQuery()
       
  1153 {
       
  1154     QFETCH( QString, dbName );
       
  1155     QSqlDatabase db = QSqlDatabase::database( dbName );
       
  1156     CHECK_DATABASE( db );
       
  1157 
       
  1158     QSqlQuery q( db );
       
  1159     q.setForwardOnly( false );
       
  1160     QVERIFY( !q.isForwardOnly() );
       
  1161 
       
  1162     QVERIFY( q.at() == QSql::BeforeFirstRow );
       
  1163     QVERIFY_SQL( q, exec( QString( "select id from %1 order by id" ).arg( qTableName( "qtest" ) ) ) );
       
  1164 
       
  1165     QSqlRecord rec;
       
  1166 
       
  1167     // NB! The order of the calls below are important!
       
  1168     QVERIFY( q.seek( 0 ) );
       
  1169     QCOMPARE( q.at(), 0 );
       
  1170     rec = q.record();
       
  1171     QCOMPARE( rec.value( 0 ).toInt(), 1 );
       
  1172 
       
  1173     QVERIFY( q.seek( 1 ) );
       
  1174     QCOMPARE( q.at(), 1 );
       
  1175     rec = q.record();
       
  1176     QCOMPARE( rec.value( 0 ).toInt(), 2 );
       
  1177 
       
  1178     // Make a jump!
       
  1179     QVERIFY( q.seek( 3 ) );
       
  1180     QCOMPARE( q.at(), 3 );
       
  1181     rec = q.record();
       
  1182     QCOMPARE( rec.value( 0 ).toInt(), 4 );
       
  1183 
       
  1184     // Last record in result set
       
  1185     QVERIFY( q.seek( 4 ) );
       
  1186     QCOMPARE( q.at(), 4 );
       
  1187     rec = q.record();
       
  1188     QCOMPARE( rec.value( 0 ).toInt(), 5 );
       
  1189 }
       
  1190 
       
  1191 // tests the forward only mode;
       
  1192 void tst_QSqlQuery::forwardOnly()
       
  1193 {
       
  1194     QFETCH( QString, dbName );
       
  1195     QSqlDatabase db = QSqlDatabase::database( dbName );
       
  1196     CHECK_DATABASE( db );
       
  1197 
       
  1198     QSqlQuery q( db );
       
  1199     q.setForwardOnly( true );
       
  1200     QVERIFY( q.isForwardOnly() );
       
  1201     QVERIFY( q.at() == QSql::BeforeFirstRow );
       
  1202     QVERIFY_SQL( q, exec( "select * from " + qTableName( "qtest" ) + " order by id" ) );
       
  1203     QVERIFY( q.at() == QSql::BeforeFirstRow );
       
  1204     QVERIFY( q.first() );
       
  1205     QCOMPARE( q.at(), 0 );
       
  1206     QCOMPARE( q.value( 0 ).toInt(), 1 );
       
  1207     QVERIFY( q.next() );
       
  1208     QCOMPARE( q.at(), 1 );
       
  1209     QCOMPARE( q.value( 0 ).toInt(), 2 );
       
  1210     QVERIFY( q.next() );
       
  1211     QCOMPARE( q.at(), 2 );
       
  1212     QCOMPARE( q.value( 0 ).toInt(), 3 );
       
  1213 
       
  1214     // lets make some mistakes to see how robust it is
       
  1215     QTest::ignoreMessage( QtWarningMsg, "QSqlQuery::seek: cannot seek backwards in a forward only query" );
       
  1216     QVERIFY( q.first() == false );
       
  1217     QCOMPARE( q.at(), 2 );
       
  1218     QCOMPARE( q.value( 0 ).toInt(), 3 );
       
  1219     QTest::ignoreMessage( QtWarningMsg, "QSqlQuery::seek: cannot seek backwards in a forward only query" );
       
  1220     QVERIFY( q.previous() == false );
       
  1221     QCOMPARE( q.at(), 2 );
       
  1222     QCOMPARE( q.value( 0 ).toInt(), 3 );
       
  1223     QVERIFY( q.next() );
       
  1224     QCOMPARE( q.at(), 3 );
       
  1225     QCOMPARE( q.value( 0 ).toInt(), 4 );
       
  1226 
       
  1227     QVERIFY_SQL( q, exec( "select * from " + qTableName( "qtest" ) ) );
       
  1228     int i = 0;
       
  1229 
       
  1230     while ( q.next() )
       
  1231         i++;
       
  1232 
       
  1233     QVERIFY( q.at() == QSql::AfterLastRow );
       
  1234 
       
  1235     QSqlQuery q2 = q;
       
  1236 
       
  1237     QVERIFY( q2.isForwardOnly() );
       
  1238 
       
  1239     QVERIFY_SQL( q, exec( "select * from " + qTableName( "qtest" ) + " order by id" ) );
       
  1240 
       
  1241     QVERIFY( q.isForwardOnly() );
       
  1242 
       
  1243     QVERIFY( q2.isForwardOnly() );
       
  1244 
       
  1245     QCOMPARE( q.at(), int( QSql::BeforeFirstRow ) );
       
  1246 
       
  1247     QVERIFY_SQL( q, seek( 3 ) );
       
  1248 
       
  1249     QCOMPARE( q.at(), 3 );
       
  1250 
       
  1251     QCOMPARE( q.value( 0 ).toInt(), 4 );
       
  1252 
       
  1253     QTest::ignoreMessage( QtWarningMsg, "QSqlQuery::seek: cannot seek backwards in a forward only query" );
       
  1254 
       
  1255     QVERIFY( q.seek( 0 ) == false );
       
  1256 
       
  1257     QCOMPARE( q.value( 0 ).toInt(), 4 );
       
  1258 
       
  1259     QCOMPARE( q.at(), 3 );
       
  1260 
       
  1261     QVERIFY( q.last() );
       
  1262 
       
  1263     QCOMPARE( q.at(), i-1 );
       
  1264 
       
  1265     QTest::ignoreMessage( QtWarningMsg, "QSqlQuery::seek: cannot seek backwards in a forward only query" );
       
  1266 
       
  1267     QVERIFY( q.first() == false );
       
  1268 
       
  1269     QCOMPARE( q.at(), i-1 );
       
  1270 
       
  1271     QVERIFY( q.next() == false );
       
  1272 
       
  1273     QCOMPARE( q.at(), int( QSql::AfterLastRow ) );
       
  1274 }
       
  1275 
       
  1276 void tst_QSqlQuery::query_exec()
       
  1277 {
       
  1278     QFETCH( QString, dbName );
       
  1279     QSqlDatabase db = QSqlDatabase::database( dbName );
       
  1280     CHECK_DATABASE( db );
       
  1281 
       
  1282     QSqlQuery q( db );
       
  1283     QVERIFY( !q.isValid() );
       
  1284     QVERIFY( !q.isActive() );
       
  1285     QVERIFY_SQL( q, exec( "select * from " + qTableName( "qtest" ) ) );
       
  1286     QVERIFY( q.isActive() );
       
  1287     QVERIFY( q.next() );
       
  1288     QVERIFY( q.isValid() );
       
  1289 }
       
  1290 
       
  1291 void tst_QSqlQuery::isNull()
       
  1292 {
       
  1293     QFETCH( QString, dbName );
       
  1294     QSqlDatabase db = QSqlDatabase::database( dbName );
       
  1295     CHECK_DATABASE( db );
       
  1296 
       
  1297     QSqlQuery q( db );
       
  1298     QVERIFY_SQL( q, exec( "select id, t_varchar from " + qTableName( "qtest_null" ) + " order by id" ) );
       
  1299     QVERIFY( q.next() );
       
  1300     QVERIFY( !q.isNull( 0 ) );
       
  1301     QVERIFY( q.isNull( 1 ) );
       
  1302     QCOMPARE( q.value( 0 ).toInt(), 0 );
       
  1303     QCOMPARE( q.value( 1 ).toString(), QString() );
       
  1304     QVERIFY( !q.value( 0 ).isNull() );
       
  1305     QVERIFY( q.value( 1 ).isNull() );
       
  1306 
       
  1307     QVERIFY( q.next() );
       
  1308     QVERIFY( !q.isNull( 0 ) );
       
  1309     QVERIFY( !q.isNull( 1 ) );
       
  1310 }
       
  1311 
       
  1312 /*! TDS specific BIT field test */
       
  1313 void tst_QSqlQuery::bitField()
       
  1314 {
       
  1315     QFETCH( QString, dbName );
       
  1316     QSqlDatabase db = QSqlDatabase::database( dbName );
       
  1317     CHECK_DATABASE( db );
       
  1318 
       
  1319     if ( !db.driverName().startsWith( "QTDS" ) )
       
  1320         QSKIP( "TDS specific test", SkipSingle );
       
  1321 
       
  1322     QSqlQuery q( db );
       
  1323 
       
  1324     QVERIFY_SQL( q, exec( "create table " + qTableName( "qtest_bittest" ) + " (bitty bit)" ) );
       
  1325 
       
  1326     QVERIFY_SQL( q, exec( "insert into " + qTableName( "qtest_bittest" ) + " values (0)" ) );
       
  1327 
       
  1328     QVERIFY_SQL( q, exec( "insert into " + qTableName( "qtest_bittest" ) + " values (1)" ) );
       
  1329 
       
  1330     QVERIFY_SQL( q, exec( "select bitty from " + qTableName( "qtest_bittest" ) ) );
       
  1331 
       
  1332     QVERIFY( q.next() );
       
  1333 
       
  1334     QVERIFY( q.value( 0 ).toInt() == 0 );
       
  1335 
       
  1336     QVERIFY( q.next() );
       
  1337 
       
  1338     QVERIFY( q.value( 0 ).toInt() == 1 );
       
  1339 }
       
  1340 
       
  1341 
       
  1342 /*! Oracle specific NULL BLOB test */
       
  1343 void tst_QSqlQuery::nullBlob()
       
  1344 {
       
  1345     QFETCH( QString, dbName );
       
  1346     QSqlDatabase db = QSqlDatabase::database( dbName );
       
  1347     CHECK_DATABASE( db );
       
  1348 
       
  1349     QSqlQuery q( db );
       
  1350     QVERIFY_SQL( q, exec( "create table " + qTableName( "qtest_nullblob" ) + " (id int primary key, bb blob)" ) );
       
  1351     QVERIFY_SQL( q, exec( "insert into " + qTableName( "qtest_nullblob" ) + " values (0, EMPTY_BLOB())" ) );
       
  1352     QVERIFY_SQL( q, exec( "insert into " + qTableName( "qtest_nullblob" ) + " values (1, NULL)" ) );
       
  1353     QVERIFY_SQL( q, exec( "insert into " + qTableName( "qtest_nullblob" ) + " values (2, 'aabbcc00112233445566')" ) );
       
  1354     // necessary otherwise oracle will bombard you with internal errors
       
  1355     q.setForwardOnly( true );
       
  1356     QVERIFY_SQL( q, exec( "select * from " + qTableName( "qtest_nullblob" ) + " order by id" ) );
       
  1357 
       
  1358     QVERIFY( q.next() );
       
  1359     QCOMPARE(( int )q.value( 1 ).toByteArray().size(), 0 );
       
  1360     QVERIFY( !q.isNull( 1 ) );
       
  1361 
       
  1362     QVERIFY( q.next() );
       
  1363     QCOMPARE(( int )q.value( 1 ).toByteArray().size(), 0 );
       
  1364     QVERIFY( q.isNull( 1 ) );
       
  1365 
       
  1366     QVERIFY( q.next() );
       
  1367     QCOMPARE(( int )q.value( 1 ).toByteArray().size(), 10 );
       
  1368     QVERIFY( !q.isNull( 1 ) );
       
  1369 }
       
  1370 
       
  1371 /* Oracle specific RAW field test */
       
  1372 void tst_QSqlQuery::rawField()
       
  1373 {
       
  1374     QFETCH( QString, dbName );
       
  1375     QSqlDatabase db = QSqlDatabase::database( dbName );
       
  1376     CHECK_DATABASE( db );
       
  1377 
       
  1378     QSqlQuery q( db );
       
  1379     q.setForwardOnly( true );
       
  1380     QVERIFY_SQL( q, exec( "create table " + qTableName( "qtest_rawtest" ) +
       
  1381                             " (id int, col raw(20))" ) );
       
  1382     QVERIFY_SQL( q, exec( "insert into " + qTableName( "qtest_rawtest" ) + " values (0, NULL)" ) );
       
  1383     QVERIFY_SQL( q, exec( "insert into " + qTableName( "qtest_rawtest" ) + " values (1, '00aa1100ddeeff')" ) );
       
  1384     QVERIFY_SQL( q, exec( "select col from " + qTableName( "qtest_rawtest" ) + " order by id" ) );
       
  1385     QVERIFY( q.next() );
       
  1386     QVERIFY( q.isNull( 0 ) );
       
  1387     QCOMPARE(( int )q.value( 0 ).toByteArray().size(), 0 );
       
  1388     QVERIFY( q.next() );
       
  1389     QVERIFY( !q.isNull( 0 ) );
       
  1390     QCOMPARE(( int )q.value( 0 ).toByteArray().size(), 7 );
       
  1391 }
       
  1392 
       
  1393 // test whether we can fetch values with more than DOUBLE precision
       
  1394 // note that MySQL's 3.x highest precision is that of a double, although
       
  1395 // you can define field with higher precision
       
  1396 void tst_QSqlQuery::precision()
       
  1397 {
       
  1398     QFETCH( QString, dbName );
       
  1399     QSqlDatabase db = QSqlDatabase::database( dbName );
       
  1400     CHECK_DATABASE( db );
       
  1401 
       
  1402     static const char* precStr = "1.2345678901234567891";
       
  1403 
       
  1404     if ( db.driverName().startsWith( "QIBASE" ) )
       
  1405         QSKIP( "DB unable to store high precision", SkipSingle );
       
  1406 
       
  1407     {
       
  1408         // need a new scope for SQLITE
       
  1409         QSqlQuery q( db );
       
  1410 
       
  1411         if ( tst_Databases::isMSAccess( db ) )
       
  1412             QVERIFY_SQL( q, exec( "create table " + qTableName( "qtest_precision" ) + " (col1 number)" ) );
       
  1413         else
       
  1414             QVERIFY_SQL( q, exec( "create table " + qTableName( "qtest_precision" ) + " (col1 numeric(21, 20))" ) );
       
  1415 
       
  1416         QVERIFY_SQL( q, exec( "insert into " + qTableName( "qtest_precision" ) + " (col1) values (1.2345678901234567891)" ) );
       
  1417 
       
  1418         QVERIFY_SQL( q, exec( "select * from " + qTableName( "qtest_precision" ) ) );
       
  1419         QVERIFY( q.next() );
       
  1420 
       
  1421         QString val = q.value( 0 ).toString();
       
  1422 
       
  1423         if ( !val.startsWith( "1.2345678901234567891" ) ) {
       
  1424             int i = 0;
       
  1425 
       
  1426             while ( precStr[i] != 0 && *( precStr + i ) == val[i].toLatin1() )
       
  1427                 i++;
       
  1428 
       
  1429             // MySQL and TDS have crappy precisions by default
       
  1430             if ( db.driverName().startsWith( "QMYSQL" ) ) {
       
  1431                 if ( i < 17 )
       
  1432                     QWARN( "MySQL didn't return the right precision" );
       
  1433             } else if ( db.driverName().startsWith( "QTDS" ) ) {
       
  1434                 if ( i < 18 )
       
  1435                     QWARN( "TDS didn't return the right precision" );
       
  1436             } else {
       
  1437                 QWARN( QString( tst_Databases::dbToString( db ) + " didn't return the right precision (" +
       
  1438                                 QString::number( i ) + " out of 21), " + val ).toLatin1() );
       
  1439             }
       
  1440         }
       
  1441     } // SQLITE scope
       
  1442 }
       
  1443 
       
  1444 void tst_QSqlQuery::nullResult()
       
  1445 {
       
  1446     QFETCH( QString, dbName );
       
  1447     QSqlDatabase db = QSqlDatabase::database( dbName );
       
  1448     CHECK_DATABASE( db );
       
  1449 
       
  1450     QSqlQuery q( db );
       
  1451     QVERIFY_SQL( q, exec( "select * from " + qTableName( "qtest" ) + " where id > 50000" ) );
       
  1452 
       
  1453     if ( q.driver()->hasFeature( QSqlDriver::QuerySize ) )
       
  1454         QCOMPARE( q.size(), 0 );
       
  1455 
       
  1456     QVERIFY( q.next() == false );
       
  1457 
       
  1458     QVERIFY( q.first() == false );
       
  1459     QVERIFY( q.last() == false );
       
  1460     QVERIFY( q.previous() == false );
       
  1461     QVERIFY( q.seek( 10 ) == false );
       
  1462     QVERIFY( q.seek( 0 ) == false );
       
  1463 }
       
  1464 
       
  1465 // this test is just an experiment to see whether we can do query-based transactions
       
  1466 // the real transaction test is in tst_QSqlDatabase
       
  1467 void tst_QSqlQuery::transaction()
       
  1468 {
       
  1469     // query based transaction is not really possible with Qt
       
  1470     QSKIP( "only tested manually by trained staff", SkipAll );
       
  1471 
       
  1472     QFETCH( QString, dbName );
       
  1473     QSqlDatabase db = QSqlDatabase::database( dbName );
       
  1474     CHECK_DATABASE( db );
       
  1475 
       
  1476     if ( !db.driver()->hasFeature( QSqlDriver::Transactions ) )
       
  1477         QSKIP( "DBMS not transaction capable", SkipSingle );
       
  1478 
       
  1479     // this is the standard SQL
       
  1480     QString startTransactionStr( "start transaction" );
       
  1481 
       
  1482     if ( db.driverName().startsWith( "QMYSQL" ) )
       
  1483         startTransactionStr = "begin work";
       
  1484 
       
  1485     QSqlQuery q( db );
       
  1486 
       
  1487     QSqlQuery q2( db );
       
  1488 
       
  1489     // test a working transaction
       
  1490     q.exec( startTransactionStr );
       
  1491 
       
  1492     QVERIFY_SQL( q, exec( "insert into" + qTableName( "qtest" ) + " values (40, 'VarChar40', 'Char40')" ) );
       
  1493 
       
  1494     QVERIFY_SQL( q, exec( "select * from" + qTableName( "qtest" ) + " where id = 40" ) );
       
  1495 
       
  1496     QVERIFY( q.next() );
       
  1497 
       
  1498     QCOMPARE( q.value( 0 ).toInt(), 40 );
       
  1499 
       
  1500     QVERIFY_SQL( q, exec( "commit" ) );
       
  1501 
       
  1502     QVERIFY_SQL( q, exec( "select * from" + qTableName( "qtest" ) + " where id = 40" ) );
       
  1503 
       
  1504     QVERIFY( q.next() );
       
  1505 
       
  1506     QCOMPARE( q.value( 0 ).toInt(), 40 );
       
  1507 
       
  1508     // test a rollback
       
  1509     q.exec( startTransactionStr );
       
  1510 
       
  1511     QVERIFY_SQL( q, exec( "insert into" + qTableName( "qtest" ) + " values (41, 'VarChar41', 'Char41')" ) );
       
  1512 
       
  1513     QVERIFY_SQL( q, exec( "select * from" + qTableName( "qtest" ) + " where id = 41" ) );
       
  1514 
       
  1515     QVERIFY( q.next() );
       
  1516 
       
  1517     QCOMPARE( q.value( 0 ).toInt(), 41 );
       
  1518 
       
  1519     if ( !q.exec( "rollback" ) ) {
       
  1520         if ( db.driverName().startsWith( "QMYSQL" ) ) {
       
  1521             qDebug( "MySQL: " + tst_Databases::printError( q.lastError() ) );
       
  1522             QSKIP( "MySQL transaction failed ", SkipSingle ); //non-fatal
       
  1523         } else
       
  1524             QFAIL( "Could not rollback transaction: " + tst_Databases::printError( q.lastError() ) );
       
  1525     }
       
  1526 
       
  1527     QVERIFY_SQL( q, exec( "select * from" + qTableName( "qtest" ) + " where id = 41" ) );
       
  1528 
       
  1529     QVERIFY( q.next() == false );
       
  1530 
       
  1531     // test concurrent access
       
  1532     q.exec( startTransactionStr );
       
  1533     QVERIFY_SQL( q, exec( "insert into" + qTableName( "qtest" ) + " values (42, 'VarChar42', 'Char42')" ) );
       
  1534     QVERIFY_SQL( q, exec( "select * from" + qTableName( "qtest" ) + " where id = 42" ) );
       
  1535     QVERIFY( q.next() );
       
  1536     QCOMPARE( q.value( 0 ).toInt(), 42 );
       
  1537 
       
  1538     QVERIFY_SQL( q2, exec( "select * from" + qTableName( "qtest" ) + " where id = 42" ) );
       
  1539 
       
  1540     if ( q2.next() )
       
  1541         qDebug( QString( "DBMS '%1' doesn't support query based transactions with concurrent access" ).arg(
       
  1542                     tst_Databases::dbToString( db ) ).toLatin1() );
       
  1543 
       
  1544     QVERIFY_SQL( q, exec( "commit" ) );
       
  1545 
       
  1546     QVERIFY_SQL( q2, exec( "select * from" + qTableName( "qtest" ) + " where id = 42" ) );
       
  1547 
       
  1548     QVERIFY( q2.next() );
       
  1549 
       
  1550     QCOMPARE( q2.value( 0 ).toInt(), 42 );
       
  1551 }
       
  1552 
       
  1553 void tst_QSqlQuery::joins()
       
  1554 {
       
  1555     QFETCH( QString, dbName );
       
  1556     QSqlDatabase db = QSqlDatabase::database( dbName );
       
  1557     CHECK_DATABASE( db );
       
  1558 
       
  1559     if ( db.driverName().startsWith( "QOCI" )
       
  1560             || db.driverName().startsWith( "QTDS" )
       
  1561             || db.driverName().startsWith( "QODBC" )
       
  1562             || db.driverName().startsWith( "QIBASE" ) ) {
       
  1563         // Oracle broken beyond recognition - cannot outer join on more than
       
  1564         // one table.
       
  1565         QSKIP( "DBMS cannot understand standard SQL", SkipSingle );
       
  1566         return;
       
  1567     }
       
  1568 
       
  1569     QSqlQuery q( db );
       
  1570 
       
  1571     QVERIFY_SQL( q, exec( "create table " + qTableName( "qtestj1" ) + " (id1 int, id2 int)" ) );
       
  1572     QVERIFY_SQL( q, exec( "create table " + qTableName( "qtestj2" ) + " (id int, name varchar(20))" ) );
       
  1573     QVERIFY_SQL( q, exec( "insert into " + qTableName( "qtestj1" ) + " values (1, 1)" ) );
       
  1574     QVERIFY_SQL( q, exec( "insert into " + qTableName( "qtestj1" ) + " values (1, 2)" ) );
       
  1575     QVERIFY_SQL( q, exec( "insert into " + qTableName( "qtestj2" ) + " values(1, 'trenton')" ) );
       
  1576     QVERIFY_SQL( q, exec( "insert into " + qTableName( "qtestj2" ) + " values(2, 'marius')" ) );
       
  1577 
       
  1578     QVERIFY_SQL( q, exec( "select qtestj1.id1, qtestj1.id2, qtestj2.id, qtestj2.name, qtestj3.id, qtestj3.name "
       
  1579                             "from " + qTableName( "qtestj1" ) + " qtestj1 left outer join " + qTableName( "qtestj2" ) +
       
  1580                             " qtestj2 on (qtestj1.id1 = qtestj2.id) "
       
  1581                             "left outer join " + qTableName( "qtestj2" ) + " as qtestj3 on (qtestj1.id2 = qtestj3.id)" ) );
       
  1582 
       
  1583     QVERIFY( q.next() );
       
  1584     QCOMPARE( q.value( 0 ).toInt(), 1 );
       
  1585     QCOMPARE( q.value( 1 ).toInt(), 1 );
       
  1586     QCOMPARE( q.value( 2 ).toInt(), 1 );
       
  1587     QCOMPARE( q.value( 3 ).toString(), QString( "trenton" ) );
       
  1588     QCOMPARE( q.value( 4 ).toInt(), 1 );
       
  1589     QCOMPARE( q.value( 5 ).toString(), QString( "trenton" ) );
       
  1590 
       
  1591     QVERIFY( q.next() );
       
  1592     QCOMPARE( q.value( 0 ).toInt(), 1 );
       
  1593     QCOMPARE( q.value( 1 ).toInt(), 2 );
       
  1594     QCOMPARE( q.value( 2 ).toInt(), 1 );
       
  1595     QCOMPARE( q.value( 3 ).toString(), QString( "trenton" ) );
       
  1596     QCOMPARE( q.value( 4 ).toInt(), 2 );
       
  1597     QCOMPARE( q.value( 5 ).toString(), QString( "marius" ) );
       
  1598 }
       
  1599 
       
  1600 void tst_QSqlQuery::synonyms()
       
  1601 {
       
  1602     QFETCH( QString, dbName );
       
  1603     QSqlDatabase db = QSqlDatabase::database( dbName );
       
  1604     CHECK_DATABASE( db );
       
  1605 
       
  1606     QSqlQuery q(db);
       
  1607     QVERIFY_SQL( q, exec("select a.id, a.t_char, a.t_varchar from " + qTableName( "qtest" ) + " a where a.id = 1") );
       
  1608     QVERIFY( q.next() );
       
  1609     QCOMPARE( q.value( 0 ).toInt(), 1 );
       
  1610     QCOMPARE( q.value( 1 ).toString().trimmed(), QString( "Char1" ) );
       
  1611     QCOMPARE( q.value( 2 ).toString().trimmed(), QString( "VarChar1" ) );
       
  1612 
       
  1613     QSqlRecord rec = q.record();
       
  1614     QCOMPARE(( int )rec.count(), 3 );
       
  1615     QCOMPARE( rec.field( 0 ).name().toLower(), QString( "id" ) );
       
  1616     QCOMPARE( rec.field( 1 ).name().toLower(), QString( "t_char" ) );
       
  1617     QCOMPARE( rec.field( 2 ).name().toLower(), QString( "t_varchar" ) );
       
  1618 }
       
  1619 
       
  1620 // It doesn't make sense to split this into several tests
       
  1621 void tst_QSqlQuery::prepare_bind_exec()
       
  1622 {
       
  1623     QFETCH( QString, dbName );
       
  1624     QSqlDatabase db = QSqlDatabase::database( dbName );
       
  1625     CHECK_DATABASE( db );
       
  1626     if(db.driverName().startsWith("QIBASE") && (db.databaseName() == "silence.nokia.troll.no:c:\\ibase\\testdb_ascii" || db.databaseName() == "/opt/interbase/qttest.gdb"))
       
  1627         QSKIP("Can't transliterate extended unicode to ascii", SkipSingle);
       
  1628     if(db.driverName().startsWith("QDB2"))
       
  1629         QSKIP("Needs someone with more Unicode knowledge than I have to fix", SkipSingle);
       
  1630 
       
  1631     {
       
  1632         // new scope for SQLITE
       
  1633         static const QString utf8str = QString::fromUtf8( "काचं शक्नोम्यत्तुम् । नोपहिनस्ति माम् ॥" );
       
  1634 
       
  1635         static const QString values[6] = { "Harry", "Trond", "Mark", "Ma?rk", "?", ":id" };
       
  1636 
       
  1637         bool useUnicode = db.driver()->hasFeature( QSqlDriver::Unicode );
       
  1638 
       
  1639         QSqlQuery q( db );
       
  1640 
       
  1641         if ( db.driverName().startsWith( "QMYSQL" ) && tst_Databases::getMySqlVersion( db ).section( QChar('.'), 0, 0 ).toInt()<5 )
       
  1642             useUnicode = false;
       
  1643 
       
  1644         QString createQuery;
       
  1645 
       
  1646         if(tst_Databases::isPostgreSQL(db))
       
  1647             QVERIFY_SQL( q, exec("set client_min_messages='warning'"));
       
  1648 
       
  1649         if ( tst_Databases::isSqlServer( db ) || db.driverName().startsWith( "QTDS" ) )
       
  1650             createQuery = "create table " + qTableName( "qtest_prepare" ) + " (id int primary key, name nvarchar(200) null)";
       
  1651         else if ( tst_Databases::isMySQL(db) && useUnicode )
       
  1652             createQuery = "create table " + qTableName( "qtest_prepare" ) + " (id int not null primary key, name varchar(200) character set utf8)";
       
  1653         else
       
  1654             createQuery = "create table " + qTableName( "qtest_prepare" ) + " (id int not null primary key, name varchar(200))";
       
  1655 
       
  1656         QVERIFY_SQL( q, exec( createQuery ) );
       
  1657 
       
  1658         QVERIFY( q.prepare( "insert into " + qTableName( "qtest_prepare" ) + " (id, name) values (:id, :name)" ) );
       
  1659         int i;
       
  1660 
       
  1661         for ( i = 0; i < 6; ++i ) {
       
  1662             q.bindValue( ":name", values[i] );
       
  1663             q.bindValue( ":id", i );
       
  1664             QVERIFY_SQL( q, exec() );
       
  1665             QMap<QString, QVariant> m = q.boundValues();
       
  1666             QCOMPARE(( int ) m.count(), 2 );
       
  1667             QCOMPARE( m[":name"].toString(), values[i] );
       
  1668             QCOMPARE( m[":id"].toInt(), i );
       
  1669         }
       
  1670 
       
  1671         q.bindValue( ":id", 8 );
       
  1672 
       
  1673         QVERIFY_SQL( q, exec() );
       
  1674 
       
  1675         if ( useUnicode ) {
       
  1676             q.bindValue( ":id", 7 );
       
  1677             q.bindValue( ":name", utf8str );
       
  1678             QVERIFY_SQL( q, exec() );
       
  1679         }
       
  1680 
       
  1681         QVERIFY_SQL( q, exec( "SELECT * FROM " + qTableName( "qtest_prepare" ) + " order by id" ) );
       
  1682 
       
  1683         for ( i = 0; i < 6; ++i ) {
       
  1684             QVERIFY( q.next() );
       
  1685             QCOMPARE( q.value( 0 ).toInt(), i );
       
  1686             QCOMPARE( q.value( 1 ).toString().trimmed(), values[ i ] );
       
  1687         }
       
  1688 
       
  1689         if ( useUnicode ) {
       
  1690             QVERIFY_SQL( q, next() );
       
  1691             QCOMPARE( q.value( 0 ).toInt(), 7 );
       
  1692             QCOMPARE( q.value( 1 ).toString(), utf8str );
       
  1693         }
       
  1694 
       
  1695         QVERIFY_SQL( q, next() );
       
  1696 
       
  1697         QCOMPARE( q.value( 0 ).toInt(), 8 );
       
  1698         QCOMPARE( q.value( 1 ).toString(), values[5] );
       
  1699 
       
  1700         QVERIFY( q.prepare( "insert into " + qTableName( "qtest_prepare" ) + " (id, name) values (:id, 'Bart')" ) );
       
  1701         q.bindValue( ":id", 99 );
       
  1702         QVERIFY_SQL( q, exec() );
       
  1703         q.bindValue( ":id", 100 );
       
  1704         QVERIFY_SQL( q, exec() );
       
  1705         QVERIFY( q.exec( "select * from " + qTableName( "qtest_prepare" ) + " where id > 98 order by id" ) );
       
  1706 
       
  1707         for ( i = 99; i <= 100; ++i ) {
       
  1708             QVERIFY( q.next() );
       
  1709             QCOMPARE( q.value( 0 ).toInt(), i );
       
  1710             QCOMPARE( q.value( 1 ).toString().trimmed(), QString( "Bart" ) );
       
  1711         }
       
  1712 
       
  1713         /*** SELECT stuff ***/
       
  1714         QVERIFY( q.prepare( "select * from " + qTableName( "qtest_prepare" ) + " where id = :id" ) );
       
  1715 
       
  1716         for ( i = 0; i < 6; ++i ) {
       
  1717             q.bindValue( ":id", i );
       
  1718             QVERIFY_SQL( q, exec() );
       
  1719             QVERIFY_SQL( q, next() );
       
  1720             QCOMPARE( q.value( 0 ).toInt(), i );
       
  1721             QCOMPARE( q.value( 1 ).toString().trimmed(), values[ i ] );
       
  1722             QSqlRecord rInf = q.record();
       
  1723             QCOMPARE(( int )rInf.count(), 2 );
       
  1724             QCOMPARE( rInf.field( 0 ).name().toUpper(), QString( "ID" ) );
       
  1725             QCOMPARE( rInf.field( 1 ).name().toUpper(), QString( "NAME" ) );
       
  1726             QVERIFY( !q.next() );
       
  1727         }
       
  1728 
       
  1729         QVERIFY_SQL( q, exec( "DELETE FROM " + qTableName( "qtest_prepare" ) ) );
       
  1730 
       
  1731         QVERIFY( q.prepare( "insert into " + qTableName( "qtest_prepare" ) + " (id, name) values (?, ?)" ) );
       
  1732         q.bindValue( 0, 0 );
       
  1733         q.bindValue( 1, values[ 0 ] );
       
  1734         QVERIFY_SQL( q, exec() );
       
  1735         q.addBindValue( 1 );
       
  1736         q.addBindValue( values[ 1 ] );
       
  1737         QVERIFY_SQL( q, exec() );
       
  1738         q.addBindValue( 2 );
       
  1739         q.addBindValue( values[ 2 ] );
       
  1740         QVERIFY_SQL( q, exec() );
       
  1741         q.addBindValue( 3 );
       
  1742         q.addBindValue( values[ 3 ] );
       
  1743         QVERIFY_SQL( q, exec() );
       
  1744         q.addBindValue( 4 );
       
  1745         q.addBindValue( values[ 4 ] );
       
  1746         QVERIFY_SQL( q, exec() );
       
  1747         q.bindValue( 1, values[ 5 ] );
       
  1748         q.bindValue( 0, 5 );
       
  1749         QVERIFY_SQL( q, exec() );
       
  1750         q.bindValue( 0, 6 );
       
  1751         q.bindValue( 1, QString() );
       
  1752         QVERIFY_SQL( q, exec() );
       
  1753 
       
  1754         if ( db.driver()->hasFeature( QSqlDriver::Unicode ) ) {
       
  1755             q.bindValue( 0, 7 );
       
  1756             q.bindValue( 1, utf8str );
       
  1757             QVERIFY_SQL( q, exec() );
       
  1758         }
       
  1759 
       
  1760         QVERIFY_SQL( q, exec( "SELECT * FROM " + qTableName( "qtest_prepare" ) + " order by id" ) );
       
  1761 
       
  1762         for ( i = 0; i < 6; ++i ) {
       
  1763             QVERIFY( q.next() );
       
  1764             QCOMPARE( q.value( 0 ).toInt(), i );
       
  1765             QCOMPARE( q.value( 1 ).toString().trimmed(), values[ i ] );
       
  1766         }
       
  1767 
       
  1768         QVERIFY( q.next() );
       
  1769 
       
  1770         QCOMPARE( q.value( 0 ).toInt(), 6 );
       
  1771         QVERIFY( q.isNull( 1 ) );
       
  1772 
       
  1773         if ( useUnicode ) {
       
  1774             QVERIFY( q.next() );
       
  1775             QCOMPARE( q.value( 0 ).toInt(), 7 );
       
  1776             QCOMPARE( q.value( 1 ).toString(), utf8str );
       
  1777         }
       
  1778 
       
  1779         QVERIFY( q.prepare( "insert into " + qTableName( "qtest_prepare" ) + " (id, name) values (?, 'Bart')" ) );
       
  1780 
       
  1781         q.bindValue( 0, 99 );
       
  1782         QVERIFY_SQL( q, exec() );
       
  1783         q.addBindValue( 100 );
       
  1784         QVERIFY_SQL( q, exec() );
       
  1785         QVERIFY( q.exec( "select * from " + qTableName( "qtest_prepare" ) + " where id > 98 order by id" ) );
       
  1786 
       
  1787         for ( i = 99; i <= 100; ++i ) {
       
  1788             QVERIFY( q.next() );
       
  1789             QCOMPARE( q.value( 0 ).toInt(), i );
       
  1790             QCOMPARE( q.value( 1 ).toString().trimmed(), QString( "Bart" ) );
       
  1791         }
       
  1792 
       
  1793         /* insert a duplicate id and make sure the db bails out */
       
  1794         QVERIFY( q.prepare( "insert into " + qTableName( "qtest_prepare" ) + " (id, name) values (?, ?)" ) );
       
  1795 
       
  1796         q.addBindValue( 99 );
       
  1797 
       
  1798         q.addBindValue( "something silly" );
       
  1799 
       
  1800         QVERIFY( !q.exec() );
       
  1801 
       
  1802         QVERIFY( q.lastError().isValid() );
       
  1803 
       
  1804         QVERIFY( !q.isActive() );
       
  1805 
       
  1806     } // end of SQLite scope
       
  1807 }
       
  1808 
       
  1809 void tst_QSqlQuery::prepared_select()
       
  1810 {
       
  1811     QFETCH( QString, dbName );
       
  1812     QSqlDatabase db = QSqlDatabase::database( dbName );
       
  1813     CHECK_DATABASE( db );
       
  1814 
       
  1815     QSqlQuery q( db );
       
  1816     QVERIFY_SQL( q, prepare( "select a.id, a.t_char, a.t_varchar from " + qTableName( "qtest" ) + " a where a.id = ?" ) );
       
  1817 
       
  1818     q.bindValue( 0, 1 );
       
  1819     QVERIFY_SQL( q, exec() );
       
  1820     QCOMPARE( q.at(), ( int )QSql::BeforeFirstRow );
       
  1821     QVERIFY( q.next() );
       
  1822     QCOMPARE( q.value( 0 ).toInt(), 1 );
       
  1823 
       
  1824     q.bindValue( 0, 2 );
       
  1825     QVERIFY_SQL( q, exec() );
       
  1826     QCOMPARE( q.at(), ( int )QSql::BeforeFirstRow );
       
  1827     QVERIFY( q.next() );
       
  1828     QCOMPARE( q.value( 0 ).toInt(), 2 );
       
  1829 
       
  1830     q.bindValue( 0, 3 );
       
  1831     QVERIFY_SQL( q, exec() );
       
  1832     QCOMPARE( q.at(), ( int )QSql::BeforeFirstRow );
       
  1833     QVERIFY( q.next() );
       
  1834     QCOMPARE( q.value( 0 ).toInt(), 3 );
       
  1835 
       
  1836     QVERIFY_SQL( q, prepare( "select a.id, a.t_char, a.t_varchar from " + qTableName( "qtest" ) + " a where a.id = ?" ) );
       
  1837     QCOMPARE( q.at(), ( int )QSql::BeforeFirstRow );
       
  1838     QVERIFY( !q.first() );
       
  1839 }
       
  1840 
       
  1841 void tst_QSqlQuery::sqlServerLongStrings()
       
  1842 {
       
  1843     QFETCH( QString, dbName );
       
  1844     QSqlDatabase db = QSqlDatabase::database( dbName );
       
  1845     CHECK_DATABASE( db );
       
  1846 
       
  1847     if ( !tst_Databases::isSqlServer( db ) )
       
  1848         QSKIP( "SQL Server specific test", SkipSingle );
       
  1849 
       
  1850     QSqlQuery q( db );
       
  1851 
       
  1852     QVERIFY_SQL( q, exec( "CREATE TABLE " + qTableName( "qtest_longstr" ) + " (id int primary key, longstring ntext)" ) );
       
  1853 
       
  1854     QVERIFY_SQL( q, prepare( "INSERT INTO " + qTableName( "qtest_longstr" ) + " VALUES (?, ?)" ) );
       
  1855 
       
  1856     q.addBindValue( 0 );
       
  1857 
       
  1858     q.addBindValue( QString::fromLatin1( "bubu" ) );
       
  1859 
       
  1860     QVERIFY_SQL( q, exec() );
       
  1861 
       
  1862     QString testStr;
       
  1863 
       
  1864     testStr.fill( QLatin1Char( 'a' ), 85000 );
       
  1865 
       
  1866     q.addBindValue( 1 );
       
  1867 
       
  1868     q.addBindValue( testStr );
       
  1869 
       
  1870     QVERIFY_SQL( q, exec() );
       
  1871 
       
  1872     QVERIFY_SQL( q, exec( "select * from " + qTableName( "qtest_longstr" ) ) );
       
  1873 
       
  1874     QVERIFY_SQL( q, next() );
       
  1875 
       
  1876     QCOMPARE( q.value( 0 ).toInt(), 0 );
       
  1877 
       
  1878     QCOMPARE( q.value( 1 ).toString(), QString::fromLatin1( "bubu" ) );
       
  1879 
       
  1880     QVERIFY_SQL( q, next() );
       
  1881 
       
  1882     QCOMPARE( q.value( 0 ).toInt(), 1 );
       
  1883 
       
  1884     QCOMPARE( q.value( 1 ).toString(), testStr );
       
  1885 }
       
  1886 
       
  1887 void tst_QSqlQuery::invalidQuery()
       
  1888 {
       
  1889     QFETCH( QString, dbName );
       
  1890     QSqlDatabase db = QSqlDatabase::database( dbName );
       
  1891     CHECK_DATABASE( db );
       
  1892 
       
  1893     QSqlQuery q( db );
       
  1894 
       
  1895     QVERIFY( !q.exec() );
       
  1896 
       
  1897     QVERIFY( !q.exec( "blahfasel" ) );
       
  1898     QVERIFY( q.lastError().type() != QSqlError::NoError );
       
  1899     QVERIFY( !q.next() );
       
  1900     QVERIFY( !q.isActive() );
       
  1901 
       
  1902     if ( !db.driverName().startsWith( "QOCI" ) && !db.driverName().startsWith( "QDB2" ) && !db.driverName().startsWith( "QODBC" ) ) {
       
  1903         // oracle and db2 just prepares everything without complaining
       
  1904         if ( db.driver()->hasFeature( QSqlDriver::PreparedQueries ) )
       
  1905             QVERIFY( !q.prepare( "blahfasel" ) );
       
  1906     }
       
  1907 
       
  1908     QVERIFY( !q.exec() );
       
  1909 
       
  1910     QVERIFY( !q.isActive() );
       
  1911     QVERIFY( !q.next() );
       
  1912 }
       
  1913 
       
  1914 class ResultHelper: public QSqlResult
       
  1915 {
       
  1916 
       
  1917 public:
       
  1918     ResultHelper(): QSqlResult( 0 ) {} // don't call, it's only for stupid compilers
       
  1919 
       
  1920     bool execBatch( bool bindArray = false )
       
  1921     {
       
  1922         return QSqlResult::execBatch( bindArray );
       
  1923     }
       
  1924 };
       
  1925 
       
  1926 void tst_QSqlQuery::batchExec()
       
  1927 {
       
  1928     QFETCH( QString, dbName );
       
  1929     QSqlDatabase db = QSqlDatabase::database( dbName );
       
  1930     CHECK_DATABASE( db );
       
  1931 
       
  1932     if ( !db.driver()->hasFeature( QSqlDriver::BatchOperations ) )
       
  1933         QSKIP( "Database can't do BatchOperations", SkipSingle );
       
  1934 
       
  1935     QSqlQuery q( db );
       
  1936     QString tableName = qTableName( "qtest_batch" );
       
  1937 
       
  1938     QVERIFY_SQL( q, exec( "create table " + tableName + " (id int, name varchar(20), dt date, num numeric(8, 4))" ) );
       
  1939     QVERIFY_SQL( q, prepare( "insert into " + tableName + " (id, name, dt, num) values (?, ?, ?, ?)" ) );
       
  1940 
       
  1941     QVariantList intCol;
       
  1942     intCol << 1 << 2 << QVariant( QVariant::Int );
       
  1943 
       
  1944     QVariantList charCol;
       
  1945     charCol << QLatin1String( "harald" ) << QLatin1String( "boris" ) << QVariant( QVariant::String );
       
  1946 
       
  1947     QVariantList dateCol;
       
  1948     QDateTime dt = QDateTime( QDate::currentDate(), QTime( 1, 2, 3 ) );
       
  1949     dateCol << dt << dt.addDays( -1 ) << QVariant( QVariant::DateTime );
       
  1950 
       
  1951     QVariantList numCol;
       
  1952     numCol << 2.3 << 3.4 << QVariant( QVariant::Double );
       
  1953 
       
  1954     q.addBindValue( intCol );
       
  1955     q.addBindValue( charCol );
       
  1956     q.addBindValue( dateCol );
       
  1957     q.addBindValue( numCol );
       
  1958 
       
  1959     QVERIFY_SQL( q, execBatch() );
       
  1960     QVERIFY_SQL( q, exec( "select id, name, dt, num from " + tableName + " order by id" ) );
       
  1961 
       
  1962     QVERIFY( q.next() );
       
  1963     QCOMPARE( q.value( 0 ).toInt(), 1 );
       
  1964     QCOMPARE( q.value( 1 ).toString(), QString( "harald" ) );
       
  1965     QCOMPARE( q.value( 2 ).toDateTime(), dt );
       
  1966     QCOMPARE( q.value( 3 ).toDouble(), 2.3 );
       
  1967 
       
  1968     QVERIFY( q.next() );
       
  1969     QCOMPARE( q.value( 0 ).toInt(), 2 );
       
  1970     QCOMPARE( q.value( 1 ).toString(), QString( "boris" ) );
       
  1971     QCOMPARE( q.value( 2 ).toDateTime(), dt.addDays( -1 ) );
       
  1972     QCOMPARE( q.value( 3 ).toDouble(), 3.4 );
       
  1973 
       
  1974     QVERIFY( q.next() );
       
  1975     QVERIFY( q.value( 0 ).isNull() );
       
  1976     QVERIFY( q.value( 1 ).isNull() );
       
  1977     QVERIFY( q.value( 2 ).isNull() );
       
  1978     QVERIFY( q.value( 3 ).isNull() );
       
  1979 }
       
  1980 
       
  1981 void tst_QSqlQuery::oraArrayBind()
       
  1982 {
       
  1983     QFETCH( QString, dbName );
       
  1984     QSqlDatabase db = QSqlDatabase::database( dbName );
       
  1985     CHECK_DATABASE( db );
       
  1986 
       
  1987     if ( !db.driver()->hasFeature( QSqlDriver::BatchOperations ) )
       
  1988         QSKIP( "Database can't do BatchOperations", SkipSingle );
       
  1989 
       
  1990     QSqlQuery q( db );
       
  1991 
       
  1992     QVERIFY_SQL( q, exec( "CREATE OR REPLACE PACKAGE ora_array_test "
       
  1993                             "IS "
       
  1994                             "TYPE names_type IS TABLE OF VARCHAR(64) NOT NULL INDEX BY BINARY_INTEGER; "
       
  1995                             "names_tab names_type; "
       
  1996                             "PROCEDURE set_name(name_in IN VARCHAR2, row_in in INTEGER); "
       
  1997                             "PROCEDURE get_name(row_in IN INTEGER, str_out OUT VARCHAR2); "
       
  1998                             "PROCEDURE get_table(tbl OUT names_type); "
       
  1999                             "PROCEDURE set_table(tbl IN names_type); "
       
  2000                             "END ora_array_test; " ) );
       
  2001 
       
  2002     QVERIFY_SQL( q, exec( "CREATE OR REPLACE PACKAGE BODY ora_array_test "
       
  2003                             "IS "
       
  2004                             "PROCEDURE set_name(name_in IN VARCHAR2, row_in in INTEGER) "
       
  2005                             "IS "
       
  2006                             "BEGIN "
       
  2007                             "names_tab(row_in) := name_in; "
       
  2008                             "END set_name; "
       
  2009 
       
  2010                             "PROCEDURE get_name(row_in IN INTEGER, str_out OUT VARCHAR2) "
       
  2011                             "IS "
       
  2012                             "BEGIN "
       
  2013                             "str_out := names_tab(row_in); "
       
  2014                             "END get_name; "
       
  2015 
       
  2016                             "PROCEDURE get_table(tbl OUT names_type) "
       
  2017                             "IS "
       
  2018                             "BEGIN "
       
  2019                             "tbl:=names_tab; "
       
  2020                             "END get_table; "
       
  2021 
       
  2022                             "PROCEDURE set_table(tbl IN names_type) "
       
  2023                             "IS "
       
  2024                             "BEGIN "
       
  2025                             "names_tab := tbl; "
       
  2026                             "END set_table; "
       
  2027                             "END ora_array_test; " ) );
       
  2028 
       
  2029     QVariantList list;
       
  2030 
       
  2031     list << QString( "lorem" ) << QString( "ipsum" ) << QString( "dolor" ) << QString( "sit" ) << QString( "amet" );
       
  2032 
       
  2033     QVERIFY_SQL( q, prepare( "BEGIN "
       
  2034                                "ora_array_test.set_table(?); "
       
  2035                                "END;" ) );
       
  2036 
       
  2037     q.bindValue( 0, list, QSql::In );
       
  2038 
       
  2039     QVERIFY_SQL( q, execBatch( QSqlQuery::ValuesAsColumns ) );
       
  2040 
       
  2041     QVERIFY_SQL( q, prepare( "BEGIN "
       
  2042                                "ora_array_test.get_table(?); "
       
  2043                                "END;" ) );
       
  2044 
       
  2045     list.clear();
       
  2046 
       
  2047     list << QString( 64,' ' ) << QString( 64,' ' ) << QString( 64,' ' ) << QString( 64,' ' ) << QString( 64,' ' );
       
  2048 
       
  2049     q.bindValue( 0, list, QSql::Out );
       
  2050 
       
  2051     QVERIFY_SQL( q, execBatch( QSqlQuery::ValuesAsColumns ) );
       
  2052 
       
  2053     QVariantList out_list = q.boundValue( 0 ).toList();
       
  2054 
       
  2055     QCOMPARE( out_list.at( 0 ).toString(), QString( "lorem" ) );
       
  2056 
       
  2057     QCOMPARE( out_list.at( 1 ).toString(), QString( "ipsum" ) );
       
  2058 
       
  2059     QCOMPARE( out_list.at( 2 ).toString(), QString( "dolor" ) );
       
  2060 
       
  2061     QCOMPARE( out_list.at( 3 ).toString(), QString( "sit" ) );
       
  2062 
       
  2063     QCOMPARE( out_list.at( 4 ).toString(), QString( "amet" ) );
       
  2064 
       
  2065     QVERIFY_SQL( q, exec( "DROP PACKAGE ora_array_test" ) );
       
  2066 }
       
  2067 
       
  2068 /*
       
  2069     Tests that QSqlDatabase::record and QSqlQuery::record returns the same thing
       
  2070     otherwise our models get confused.
       
  2071  */
       
  2072 void tst_QSqlQuery::record_sqlite()
       
  2073 {
       
  2074     QFETCH( QString, dbName );
       
  2075     QSqlDatabase db = QSqlDatabase::database( dbName );
       
  2076     CHECK_DATABASE( db );
       
  2077 
       
  2078     QSqlQuery q( db );
       
  2079 
       
  2080     QVERIFY_SQL( q, exec( "create table "+qTableName( "record_sqlite" )+"(id integer primary key, name varchar, title int)" ) );
       
  2081 
       
  2082     QSqlRecord rec = db.record( qTableName( "record_sqlite" ) );
       
  2083 
       
  2084     QCOMPARE( rec.count(), 3 );
       
  2085     QCOMPARE( rec.field( 0 ).type(), QVariant::Int );
       
  2086     QCOMPARE( rec.field( 1 ).type(), QVariant::String );
       
  2087     QCOMPARE( rec.field( 2 ).type(), QVariant::Int );
       
  2088 
       
  2089     /* important - select from an empty table */
       
  2090     QVERIFY_SQL( q, exec( "select id, name, title from "+qTableName( "record_sqlite" ) ) );
       
  2091 
       
  2092     rec = q.record();
       
  2093     QCOMPARE( rec.count(), 3 );
       
  2094     QCOMPARE( rec.field( 0 ).type(), QVariant::Int );
       
  2095     QCOMPARE( rec.field( 1 ).type(), QVariant::String );
       
  2096     QCOMPARE( rec.field( 2 ).type(), QVariant::Int );
       
  2097 }
       
  2098 
       
  2099 void tst_QSqlQuery::oraLong()
       
  2100 {
       
  2101     QFETCH( QString, dbName );
       
  2102     QSqlDatabase db = QSqlDatabase::database( dbName );
       
  2103     CHECK_DATABASE( db );
       
  2104 
       
  2105     QSqlQuery q( db );
       
  2106 
       
  2107     QString aLotOfText( 127000, QLatin1Char( 'H' ) );
       
  2108 
       
  2109     QVERIFY_SQL( q, exec( "create table " + qTableName( "qtest_longstr" ) + " (id int primary key, astr long)" ) );
       
  2110     QVERIFY_SQL( q, prepare( "insert into " + qTableName( "qtest_longstr" ) + " (id, astr) values (?, ?)" ) );
       
  2111     q.addBindValue( 1 );
       
  2112     q.addBindValue( aLotOfText );
       
  2113     QVERIFY_SQL( q, exec() );
       
  2114 
       
  2115     QVERIFY_SQL( q, exec( "select id,astr from " + qTableName( "qtest_longstr" ) ) );
       
  2116 
       
  2117     QVERIFY( q.next() );
       
  2118     QCOMPARE( q.value( 0 ).toInt(), 1 );
       
  2119     QCOMPARE( q.value( 1 ).toString(), aLotOfText );
       
  2120 }
       
  2121 
       
  2122 void tst_QSqlQuery::execErrorRecovery()
       
  2123 {
       
  2124     QFETCH( QString, dbName );
       
  2125     QSqlDatabase db = QSqlDatabase::database( dbName );
       
  2126     CHECK_DATABASE( db );
       
  2127 
       
  2128     QSqlQuery q( db );
       
  2129 
       
  2130     QVERIFY_SQL( q, exec( "create table " + qTableName( "qtest_exerr" ) + " (id int not null primary key)" ) );
       
  2131     QVERIFY_SQL( q, prepare( "insert into " + qTableName( "qtest_exerr" ) + " values (?)" ) );
       
  2132 
       
  2133     q.addBindValue( 1 );
       
  2134     QVERIFY_SQL( q, exec() );
       
  2135 
       
  2136     q.addBindValue( 1 ); // binding the same pkey - should fail
       
  2137     QVERIFY( !q.exec() );
       
  2138 
       
  2139     q.addBindValue( 2 ); // this should work again
       
  2140     QVERIFY_SQL( q, exec() );
       
  2141 }
       
  2142 
       
  2143 void tst_QSqlQuery::lastInsertId()
       
  2144 {
       
  2145     QFETCH( QString, dbName );
       
  2146     QSqlDatabase db = QSqlDatabase::database( dbName );
       
  2147     CHECK_DATABASE( db );
       
  2148 
       
  2149     if ( !db.driver()->hasFeature( QSqlDriver::LastInsertId ) )
       
  2150         QSKIP( "Database doesn't support lastInsertId", SkipSingle );
       
  2151 
       
  2152     QSqlQuery q( db );
       
  2153 
       
  2154     QVERIFY_SQL( q, exec( "insert into " + qTableName( "qtest" ) + " values (41, 'VarChar41', 'Char41')" ) );
       
  2155 
       
  2156     QVariant v = q.lastInsertId();
       
  2157 
       
  2158     QVERIFY( v.isValid() );
       
  2159 }
       
  2160 
       
  2161 void tst_QSqlQuery::lastQuery()
       
  2162 {
       
  2163     QFETCH( QString, dbName );
       
  2164     QSqlDatabase db = QSqlDatabase::database( dbName );
       
  2165     CHECK_DATABASE( db );
       
  2166 
       
  2167     QSqlQuery q( db );
       
  2168     QString sql = "select * from " + qTableName( "qtest" );
       
  2169     QVERIFY_SQL( q, exec( sql ) );
       
  2170     QCOMPARE( q.lastQuery(), sql );
       
  2171     QCOMPARE( q.executedQuery(), sql );
       
  2172 }
       
  2173 
       
  2174 void tst_QSqlQuery::bindWithDoubleColonCastOperator()
       
  2175 {
       
  2176     QFETCH( QString, dbName );
       
  2177     QSqlDatabase db = QSqlDatabase::database( dbName );
       
  2178     CHECK_DATABASE( db );
       
  2179 
       
  2180     // Only PostgreSQL support the double-colon cast operator
       
  2181 
       
  2182     if ( !db.driverName().startsWith( "QPSQL" ) ) {
       
  2183         QSKIP( "Test requires PostgreSQL", SkipSingle );
       
  2184         return;
       
  2185     }
       
  2186 
       
  2187     QString tablename = qTableName( "bindtest" );
       
  2188 
       
  2189     QSqlQuery q( db );
       
  2190 
       
  2191     QVERIFY_SQL( q, exec( "create table " + tablename + " (id1 int, id2 int, id3 int, fld1 int, fld2 int)" ) );
       
  2192     QVERIFY_SQL( q, exec( "insert into " + tablename + " values (1, 2, 3, 10, 5)" ) );
       
  2193 
       
  2194     QVERIFY_SQL( q, prepare( "select sum((fld1 - fld2)::int) from " + tablename + " where id1 = :myid1 and id2 =:myid2 and id3=:myid3" ) );
       
  2195     q.bindValue( ":myid1", 1 );
       
  2196     q.bindValue( ":myid2", 2 );
       
  2197     q.bindValue( ":myid3", 3 );
       
  2198 
       
  2199     QVERIFY_SQL( q, exec() );
       
  2200     QVERIFY_SQL( q, next() );
       
  2201 
       
  2202     if ( db.driver()->hasFeature( QSqlDriver::PreparedQueries ) )
       
  2203         QCOMPARE( q.executedQuery(), QString( "select sum((fld1 - fld2)::int) from " + tablename + " where id1 = ? and id2 =? and id3=?" ) );
       
  2204     else
       
  2205         QCOMPARE( q.executedQuery(), QString( "select sum((fld1 - fld2)::int) from " + tablename + " where id1 = 1 and id2 =2 and id3=3" ) );
       
  2206 }
       
  2207 
       
  2208 /* For task 157397: Using QSqlQuery with an invalid QSqlDatabase
       
  2209    does not set the last error of the query.
       
  2210    This test function will output some warnings, that's ok.
       
  2211 */
       
  2212 void tst_QSqlQuery::queryOnInvalidDatabase()
       
  2213 {
       
  2214     {
       
  2215         QTest::ignoreMessage( QtWarningMsg, "QSqlDatabase: INVALID driver not loaded" );
       
  2216         QSqlDatabase db = QSqlDatabase::addDatabase( "INVALID", "invalidConnection" );
       
  2217         QVERIFY2( db.lastError().isValid(),
       
  2218                   qPrintable( QString( "db.lastError().isValid() should be true!" ) ) );
       
  2219 
       
  2220         QTest::ignoreMessage( QtWarningMsg, "QSqlQuery::exec: database not open" );
       
  2221         QSqlQuery query( "SELECT 1 AS ID", db );
       
  2222         QVERIFY2( query.lastError().isValid(),
       
  2223                   qPrintable( QString( "query.lastError().isValid() should be true!" ) ) );
       
  2224     }
       
  2225 
       
  2226     QSqlDatabase::removeDatabase( "invalidConnection" );
       
  2227 
       
  2228     {
       
  2229         QSqlDatabase db = QSqlDatabase::database( "this connection does not exist" );
       
  2230         QTest::ignoreMessage( QtWarningMsg, "QSqlQuery::exec: database not open" );
       
  2231         QSqlQuery query( "SELECT 1 AS ID", db );
       
  2232         QVERIFY2( query.lastError().isValid(),
       
  2233                   qPrintable( QString( "query.lastError().isValid() should be true!" ) ) );
       
  2234     }
       
  2235 }
       
  2236 
       
  2237 /* For task 159138: Error on instantiating a sql-query before explicitly
       
  2238    opening the database. This is something we don't support, so this isn't
       
  2239    really a bug. However some of the drivers are nice enough to support it.
       
  2240 */
       
  2241 void tst_QSqlQuery::createQueryOnClosedDatabase()
       
  2242 {
       
  2243     QFETCH( QString, dbName );
       
  2244     QSqlDatabase db = QSqlDatabase::database( dbName );
       
  2245     CHECK_DATABASE( db );
       
  2246 
       
  2247     // Only supported by these drivers
       
  2248 
       
  2249     if ( !db.driverName().startsWith( "QPSQL" )
       
  2250             && !db.driverName().startsWith( "QOCI" )
       
  2251             && !db.driverName().startsWith( "QMYSQL" )
       
  2252             && !db.driverName().startsWith( "QDB2" ) ) {
       
  2253         QSKIP( "Test is specific for PostgreSQL, Oracle, MySql and DB2", SkipSingle );
       
  2254         return;
       
  2255     }
       
  2256 
       
  2257     db.close();
       
  2258 
       
  2259     QSqlQuery q( db );
       
  2260     db.open();
       
  2261     QVERIFY_SQL( q, exec( QString( "select * from %1 where id = 1" ).arg( qTableName( "qtest" ) ) ) );
       
  2262 
       
  2263     QVERIFY_SQL( q, next() );
       
  2264     QCOMPARE( q.value( 0 ).toInt(), 1 );
       
  2265     QCOMPARE( q.value( 1 ).toString().trimmed(), QLatin1String( "VarChar1" ) );
       
  2266     QCOMPARE( q.value( 2 ).toString().trimmed(), QLatin1String( "Char1" ) );
       
  2267 
       
  2268     db.close();
       
  2269     QVERIFY2( !q.exec( QString( "select * from %1 where id = 1" ).arg( qTableName( "qtest" ) ) ),
       
  2270               qPrintable( QString( "This can't happen! The query should not have been executed!" ) ) );
       
  2271 }
       
  2272 
       
  2273 void tst_QSqlQuery::reExecutePreparedForwardOnlyQuery()
       
  2274 {
       
  2275     QFETCH( QString, dbName );
       
  2276     QSqlDatabase db = QSqlDatabase::database( dbName );
       
  2277     CHECK_DATABASE( db );
       
  2278 
       
  2279     QSqlQuery q( db );
       
  2280     q.setForwardOnly( true );
       
  2281 
       
  2282     QVERIFY_SQL( q, prepare( QString( "SELECT id, t_varchar, t_char FROM %1 WHERE id = :id" ).arg( qTableName( "qtest" ) ) ) );
       
  2283     q.bindValue( ":id", 1 );
       
  2284     QVERIFY_SQL( q, exec() );
       
  2285 
       
  2286     // Do something, like iterate over the result, or skip to the end
       
  2287     QVERIFY_SQL( q, last() );
       
  2288 
       
  2289     QVERIFY_SQL( q, exec() );
       
  2290     /* This was broken with SQLite because the cache size was set to 0 in the 2nd execute.
       
  2291        When forwardOnly is set we don't cahce the entire result, but we do cache the current row
       
  2292        but this requires the cache size to be equal to the column count.
       
  2293     */
       
  2294     QVERIFY_SQL( q, next() );
       
  2295     QCOMPARE( q.value( 0 ).toInt(), 1 );
       
  2296     QCOMPARE( q.value( 1 ).toString().trimmed(), QString( "VarChar1" ) );
       
  2297     QCOMPARE( q.value( 2 ).toString().trimmed(), QString( "Char1" ) );
       
  2298 }
       
  2299 
       
  2300 void tst_QSqlQuery::finish()
       
  2301 {
       
  2302     QFETCH( QString, dbName );
       
  2303     QSqlDatabase db = QSqlDatabase::database( dbName );
       
  2304     CHECK_DATABASE( db );
       
  2305 
       
  2306     QSqlQuery q( db );
       
  2307     QVERIFY_SQL( q, prepare( "SELECT id FROM " + qTableName( "qtest" ) + " WHERE id = ?" ) );
       
  2308 
       
  2309     int id = 4;
       
  2310     q.bindValue( 0, id );
       
  2311     QVERIFY_SQL( q, exec() );
       
  2312     QVERIFY( q.isActive() );
       
  2313     QVERIFY_SQL( q, next() );
       
  2314     QCOMPARE( q.value( 0 ).toInt(), id );
       
  2315 
       
  2316     q.finish();
       
  2317     QVERIFY( !q.isActive() ); // query is now inactive
       
  2318     QCOMPARE( q.boundValue( 0 ).toInt(), id ); // bound values are retained
       
  2319 
       
  2320     QVERIFY_SQL( q, exec() ); // no prepare necessary
       
  2321     QVERIFY( q.isActive() );
       
  2322     QVERIFY_SQL( q, next() );
       
  2323     QCOMPARE( q.value( 0 ).toInt(), id );
       
  2324 
       
  2325     q.finish();
       
  2326     QVERIFY( !q.isActive() );
       
  2327 
       
  2328     QVERIFY_SQL( q, exec( "SELECT id FROM " + qTableName( "qtest" ) + " WHERE id = 1" ) );
       
  2329     QVERIFY( q.isActive() );
       
  2330     QVERIFY_SQL( q, next() );
       
  2331     QCOMPARE( q.value( 0 ).toInt(), 1 );
       
  2332     QCOMPARE( q.record().count(), 1 );
       
  2333 }
       
  2334 
       
  2335 void tst_QSqlQuery::sqlite_finish()
       
  2336 {
       
  2337     QFETCH( QString, dbName );
       
  2338     QSqlDatabase db = QSqlDatabase::database( dbName );
       
  2339     CHECK_DATABASE( db );
       
  2340     if (db.driverName() != QLatin1String("QSQLITE")) {
       
  2341         QSKIP("Sqlite3 specific test", SkipSingle);
       
  2342         return;
       
  2343     }
       
  2344 
       
  2345     if ( db.databaseName().startsWith( ':' ) )
       
  2346         QSKIP( "This test requires a database on the filesystem, not in-memory", SkipAll );
       
  2347 
       
  2348     {
       
  2349         QSqlDatabase db2 = QSqlDatabase::addDatabase( "QSQLITE", "sqlite_finish_sqlite" );
       
  2350         db2.setDatabaseName( db.databaseName() );
       
  2351         QVERIFY_SQL( db2, open() );
       
  2352 
       
  2353         QString tableName = qTableName( "qtest_lockedtable" );
       
  2354         QSqlQuery q( db );
       
  2355 
       
  2356         tst_Databases::safeDropTable( db, tableName );
       
  2357         q.exec( "CREATE TABLE " + tableName + " (pk_id INTEGER PRIMARY KEY, whatever TEXT)" );
       
  2358         q.exec( "INSERT INTO " + tableName + " values(1, 'whatever')" );
       
  2359         q.exec( "INSERT INTO " + tableName + " values(2, 'whatever more')" );
       
  2360 
       
  2361         // This creates a read-lock in the database
       
  2362         QVERIFY_SQL( q, exec( "SELECT * FROM " + tableName + " WHERE pk_id = 1 or pk_id = 2" ) );
       
  2363         QVERIFY_SQL( q, next() );
       
  2364 
       
  2365         // The DELETE will fail because of the read-lock
       
  2366         QSqlQuery q2( db2 );
       
  2367         QVERIFY( !q2.exec( "DELETE FROM " + tableName + " WHERE pk_id=2" ) );
       
  2368         QCOMPARE( q2.numRowsAffected(), -1 );
       
  2369 
       
  2370         // The DELETE will succeed now because finish() removes the lock
       
  2371         q.finish();
       
  2372         QVERIFY_SQL( q2, exec( "DELETE FROM " + tableName + " WHERE pk_id=2" ) );
       
  2373         QCOMPARE( q2.numRowsAffected(), 1 );
       
  2374 
       
  2375         tst_Databases::safeDropTable( db, tableName );
       
  2376     }
       
  2377 
       
  2378     QSqlDatabase::removeDatabase( "sqlite_finish_sqlite" );
       
  2379 }
       
  2380 
       
  2381 void tst_QSqlQuery::nextResult()
       
  2382 {
       
  2383     QFETCH( QString, dbName );
       
  2384     QSqlDatabase db = QSqlDatabase::database( dbName );
       
  2385     CHECK_DATABASE( db );
       
  2386 
       
  2387     if ( !db.driver()->hasFeature( QSqlDriver::MultipleResultSets ) || !db.driver()->hasFeature( QSqlDriver::BatchOperations ) )
       
  2388         QSKIP( "DBMS does not support multiple result sets or batch operations", SkipSingle );
       
  2389 
       
  2390     QSqlQuery q( db );
       
  2391 
       
  2392     if ( db.driverName().startsWith( "QMYSQL" ) && tst_Databases::getMySqlVersion( db ).section( QChar('.'), 0, 0 ).toInt()<5 )
       
  2393         QSKIP( "Test requires MySQL >= 5.0", SkipSingle );
       
  2394 
       
  2395     enum DriverType { ODBC, MYSQL, DB2 };
       
  2396     DriverType driverType = ODBC;
       
  2397 
       
  2398     if ( db.driverName().startsWith( "QMYSQL" ) )
       
  2399         driverType = MYSQL;
       
  2400     else if ( db.driverName().startsWith( "QDB2" ) )
       
  2401         driverType = DB2;
       
  2402 
       
  2403     QString tableName = qTableName( "more_results" );
       
  2404 
       
  2405     QVERIFY_SQL( q, exec( "CREATE TABLE " + tableName + " (id integer, text varchar(20), num numeric(6, 3), empty varchar(10));" ) );
       
  2406 
       
  2407     QVERIFY_SQL( q, exec( "INSERT INTO " + tableName + " VALUES(1, 'one', 1.1, '');" ) );
       
  2408 
       
  2409     QVERIFY_SQL( q, exec( "INSERT INTO " + tableName + " VALUES(2, 'two', 2.2, '');" ) );
       
  2410 
       
  2411     QVERIFY_SQL( q, exec( "INSERT INTO " + tableName + " VALUES(3, 'three', 3.3, '');" ) );
       
  2412 
       
  2413     QVERIFY_SQL( q, exec( "INSERT INTO " + tableName + " VALUES(4, 'four', 4.4, '');" ) );
       
  2414 
       
  2415     QStringList tstStrings;
       
  2416 
       
  2417     tstStrings << "one" << "two" << "three" << "four";
       
  2418 
       
  2419     // Query that returns only one result set, nothing special about this
       
  2420     QVERIFY_SQL( q, exec( QString( "SELECT * FROM %1;" ).arg( tableName ) ) );
       
  2421 
       
  2422     QVERIFY( q.next() );                // Move to first row of the result set
       
  2423 
       
  2424     QVERIFY( !q.nextResult() );         // No more result sets are available
       
  2425 
       
  2426     QVERIFY( !q.isActive() );           // So the query is no longer active
       
  2427 
       
  2428     QVERIFY( !q.next() );               // ... and no data is available as the call
       
  2429 
       
  2430     // to nextResult() discarded the result set
       
  2431 
       
  2432     // Query that returns two result sets (batch sql)
       
  2433     // When working with multiple result sets SQL Server insists on non-scrollable cursors
       
  2434     if ( driverType == ODBC )
       
  2435         q.setForwardOnly( true );
       
  2436 
       
  2437     QVERIFY_SQL( q, exec( "SELECT id FROM " + tableName + "; SELECT text, num FROM " + tableName + ';' ) );
       
  2438 
       
  2439     QCOMPARE( q.record().count(), 1 );  // Check that the meta data is as expected
       
  2440 
       
  2441     QCOMPARE( q.record().field( 0 ).name().toUpper(), QString( "ID" ) );
       
  2442 
       
  2443     QCOMPARE( q.record().field( 0 ).type(), QVariant::Int );
       
  2444 
       
  2445     QVERIFY( q.nextResult() );          // Discards first result set and move to the next
       
  2446 
       
  2447     QCOMPARE( q.record().count(), 2 );  // New meta data should be available
       
  2448 
       
  2449     QCOMPARE( q.record().field( 0 ).name().toUpper(), QString( "TEXT" ) );
       
  2450 
       
  2451     QCOMPARE( q.record().field( 0 ).type(), QVariant::String );
       
  2452 
       
  2453     QCOMPARE( q.record().field( 1 ).name().toUpper(), QString( "NUM" ) );
       
  2454 
       
  2455     if ( driverType == MYSQL )
       
  2456         QCOMPARE( q.record().field( 1 ).type(), QVariant::String );
       
  2457     else
       
  2458         QCOMPARE( q.record().field( 1 ).type(), QVariant::Double );
       
  2459 
       
  2460     QVERIFY( q.next() );                    // Move to first row of the second result set
       
  2461 
       
  2462     QFAIL_SQL(q, nextResult()); // No more result sets after this
       
  2463 
       
  2464     QVERIFY( !q.isActive() );               // So the query is no longer active
       
  2465 
       
  2466     QVERIFY( !q.next() );                   // ... and no data is available as the call to
       
  2467 
       
  2468     // nextResult() discarded the result set
       
  2469 
       
  2470     // Query that returns one result set, a count of affected rows and then another result set
       
  2471     QString query1 = QString( "SELECT id, text, num, empty FROM %1 WHERE id <= 3" ).arg( tableName );
       
  2472 
       
  2473     QString query2 = QString( "UPDATE %1 SET empty = 'Yatta!'" ).arg( tableName );
       
  2474 
       
  2475     QString query3 = QString( "SELECT id, empty FROM %1 WHERE id <=2" ).arg( tableName );
       
  2476 
       
  2477     QVERIFY_SQL( q, exec( QString( "%1; %2; %3;" ).arg( query1 ).arg( query2 ).arg( query3 ) ) );
       
  2478 
       
  2479     // Check result set returned by first statement
       
  2480     QVERIFY( q.isSelect() );            // The first statement is a select
       
  2481 
       
  2482     for ( int i = 0; i < 3; i++ ) {
       
  2483         QVERIFY_SQL( q, next() );
       
  2484         QCOMPARE( q.value( 0 ).toInt(), 1+i );
       
  2485         QCOMPARE( q.value( 1 ).toString(), tstStrings.at( i ) );
       
  2486         QCOMPARE( q.value( 2 ).toDouble(), 1.1*( i+1 ) );
       
  2487         QVERIFY( q.value( 3 ).toString().isEmpty() );
       
  2488     }
       
  2489 
       
  2490     QVERIFY_SQL( q, nextResult() );
       
  2491 
       
  2492     QVERIFY( !q.isSelect() );           // The second statement isn't a SELECT
       
  2493     QVERIFY( !q.next() );               // ... so no result set is available
       
  2494     QCOMPARE( q.numRowsAffected(), 4 ); // 4 rows was affected by the UPDATE
       
  2495 
       
  2496     // Check result set returned by third statement
       
  2497     QVERIFY_SQL( q, nextResult() );
       
  2498     QVERIFY( q.isSelect() );            // The third statement is a SELECT
       
  2499 
       
  2500     for ( int i = 0; i < 2; i++ ) {
       
  2501         QVERIFY_SQL( q, next() );
       
  2502         QCOMPARE( q.value( 0 ).toInt(), 1+i );
       
  2503         QCOMPARE( q.value( 1 ).toString(), QString( "Yatta!" ) );
       
  2504     }
       
  2505 
       
  2506     // Stored procedure with multiple result sets
       
  2507     QString procName = qTableName( "proc_more_res" );
       
  2508 
       
  2509     q.exec( QString( "DROP PROCEDURE %1;" ).arg( procName ) );
       
  2510 
       
  2511     if ( driverType == MYSQL )
       
  2512         QVERIFY_SQL( q, exec( QString( "CREATE PROCEDURE %1()"
       
  2513                                          "\nBEGIN"
       
  2514                                          "\nSELECT id, text FROM %2;"
       
  2515                                          "\nSELECT empty, num, text, id FROM %3;"
       
  2516                                          "\nEND" ).arg( procName ).arg( tableName ).arg( tableName ) ) );
       
  2517     else if ( driverType == DB2 )
       
  2518         QVERIFY_SQL( q, exec( QString( "CREATE PROCEDURE %1()"
       
  2519                                          "\nRESULT SETS 2"
       
  2520                                          "\nLANGUAGE SQL"
       
  2521                                          "\np1:BEGIN"
       
  2522                                          "\nDECLARE cursor1 CURSOR WITH RETURN FOR SELECT id, text FROM %2;"
       
  2523                                          "\nDECLARE cursor2 CURSOR WITH RETURN FOR SELECT empty, num, text, id FROM %3;"
       
  2524                                          "\nOPEN cursor1;"
       
  2525                                          "\nOPEN cursor2;"
       
  2526                                          "\nEND p1" ).arg( procName ).arg( tableName ).arg( tableName ) ) );
       
  2527     else
       
  2528         QVERIFY_SQL( q, exec( QString( "CREATE PROCEDURE %1"
       
  2529                                          "\nAS"
       
  2530                                          "\nSELECT id, text FROM %2"
       
  2531                                          "\nSELECT empty, num, text, id FROM %3" ).arg( procName ).arg( tableName ).arg( tableName ) ) );
       
  2532 
       
  2533     if ( driverType == MYSQL || driverType == DB2 ) {
       
  2534         q.setForwardOnly( true );
       
  2535         QVERIFY_SQL( q, exec( QString( "CALL %1()" ).arg( procName ) ) );
       
  2536     } else {
       
  2537         QVERIFY_SQL( q, exec( QString( "EXEC %1" ).arg( procName ) ) );
       
  2538     }
       
  2539 
       
  2540     for ( int i = 0; i < 4; i++ ) {
       
  2541         QVERIFY_SQL( q, next() );
       
  2542         QCOMPARE( q.value( 0 ).toInt(), i+1 );
       
  2543         QCOMPARE( q.value( 1 ).toString(), tstStrings.at( i ) );
       
  2544     }
       
  2545 
       
  2546     QVERIFY_SQL( q, nextResult() );
       
  2547 
       
  2548     QVERIFY_SQL( q, isActive() );
       
  2549 
       
  2550     for ( int i = 0; i < 4; i++ ) {
       
  2551         QVERIFY_SQL( q, next() );
       
  2552         QCOMPARE( q.value( 0 ).toString(), QString( "Yatta!" ) );
       
  2553         QCOMPARE( q.value( 1 ).toDouble(), 1.1*( 1+i ) );
       
  2554         QCOMPARE( q.value( 2 ).toString(), tstStrings.at( i ) );
       
  2555         QCOMPARE( q.value( 3 ).toInt(), 1+i );
       
  2556     }
       
  2557 
       
  2558     // MySQL also counts the CALL itself as a result
       
  2559     if ( driverType == MYSQL ) {
       
  2560         QVERIFY( q.nextResult() );
       
  2561         QVERIFY( !q.isSelect() );           // ... but it's not a select
       
  2562         QCOMPARE( q.numRowsAffected(), 0 ); // ... and no rows are affected (at least not with this procedure)
       
  2563     }
       
  2564 
       
  2565     QVERIFY( !q.nextResult() );
       
  2566 
       
  2567     QVERIFY( !q.isActive() );
       
  2568 
       
  2569     q.exec( QString( "DROP PROCEDURE %1;" ).arg( procName ) );
       
  2570 }
       
  2571 
       
  2572 
       
  2573 // For task 190311. Problem: Truncation happens on the 2nd execution if that BLOB is larger
       
  2574 // than the BLOB on the 1st execution. This was only for MySQL, but the test is general
       
  2575 // enough to be run with all backends.
       
  2576 void tst_QSqlQuery::blobsPreparedQuery()
       
  2577 {
       
  2578     QFETCH( QString, dbName );
       
  2579     QSqlDatabase db = QSqlDatabase::database( dbName );
       
  2580     CHECK_DATABASE( db );
       
  2581 
       
  2582     if ( !db.driver()->hasFeature( QSqlDriver::BLOB ) || !db.driver()->hasFeature( QSqlDriver::PreparedQueries ) )
       
  2583         QSKIP( "DBMS does not support BLOBs or prepared queries", SkipSingle );
       
  2584 
       
  2585     QString tableName = qTableName( "blobstest" );
       
  2586 
       
  2587     QSqlQuery q( db );
       
  2588     q.setForwardOnly( true ); // This is needed to make the test work with DB2.
       
  2589     QString shortBLOB( "abc" );
       
  2590     QString longerBLOB( "abcdefghijklmnopqrstuvxyz¿äëïöü¡  " );
       
  2591 
       
  2592     // In PostgreSQL a BLOB is not called a BLOB, but a BYTEA! :-)
       
  2593     // ... and in SQL Server it can be called a lot, but IMAGE will do.
       
  2594     QString typeName( "BLOB" );
       
  2595     if ( db.driverName().startsWith( "QPSQL" ) )
       
  2596         typeName = "BYTEA";
       
  2597     else if ( db.driverName().startsWith( "QODBC" ) && tst_Databases::isSqlServer( db ))
       
  2598         typeName = "IMAGE";
       
  2599 
       
  2600     QVERIFY_SQL( q, exec( QString( "CREATE TABLE %1(id INTEGER, data %2)" ).arg( tableName ).arg( typeName ) ) );
       
  2601     q.prepare( QString( "INSERT INTO %1(id, data) VALUES(:id, :data)" ).arg( tableName ) );
       
  2602     q.bindValue( ":id", 1 );
       
  2603     q.bindValue( ":data", shortBLOB.toAscii() );
       
  2604     QVERIFY_SQL( q, exec() );
       
  2605 
       
  2606     q.bindValue( ":id", 2 );
       
  2607     q.bindValue( ":data", longerBLOB.toAscii() );
       
  2608     QVERIFY_SQL( q, exec() );
       
  2609 
       
  2610     // Two executions and result sets
       
  2611     q.prepare( QString( "SELECT data FROM %1 WHERE id = ?" ).arg( tableName ) );
       
  2612     q.bindValue( 0, QVariant( 1 ) );
       
  2613     QVERIFY_SQL( q, exec() );
       
  2614     QVERIFY_SQL( q, next() );
       
  2615     QCOMPARE( q.value( 0 ).toString(), shortBLOB );
       
  2616 
       
  2617     q.bindValue( 0, QVariant( 2 ) );
       
  2618     QVERIFY_SQL( q, exec() );
       
  2619     QVERIFY_SQL( q, next() );
       
  2620     QCOMPARE( q.value( 0 ).toString(), longerBLOB );
       
  2621 
       
  2622     // Only one execution and result set
       
  2623     q.prepare( QString( "SELECT id, data FROM %1 ORDER BY id" ).arg( tableName ) );
       
  2624     QVERIFY_SQL( q, exec() );
       
  2625     QVERIFY_SQL( q, next() );
       
  2626     QCOMPARE( q.value( 1 ).toString(), shortBLOB );
       
  2627     QVERIFY_SQL( q, next() );
       
  2628     QCOMPARE( q.value( 1 ).toString(), longerBLOB );
       
  2629 }
       
  2630 
       
  2631 // There were problems with navigating past the end of a table returning an error on mysql
       
  2632 void tst_QSqlQuery::emptyTableNavigate()
       
  2633 {
       
  2634     QFETCH( QString, dbName );
       
  2635     QSqlDatabase db = QSqlDatabase::database( dbName );
       
  2636     CHECK_DATABASE( db );
       
  2637 
       
  2638     {
       
  2639         QSqlQuery q( db );
       
  2640         QVERIFY_SQL( q, exec( "create table " + qTableName( "qtest_empty" ) + " (id char(10))" ) );
       
  2641         QVERIFY_SQL( q, prepare( "select * from " + qTableName( "qtest_empty" ) ) );
       
  2642         QVERIFY_SQL( q, exec() );
       
  2643         QVERIFY( !q.next() );
       
  2644         QCOMPARE( q.lastError().isValid(), false );
       
  2645     }
       
  2646 }
       
  2647 
       
  2648 void tst_QSqlQuery::task_217003()
       
  2649 {
       
  2650     QFETCH( QString, dbName );
       
  2651     QSqlDatabase db = QSqlDatabase::database( dbName );
       
  2652     CHECK_DATABASE( db );
       
  2653     QSqlQuery q( db );
       
  2654 
       
  2655     QVERIFY_SQL( q, exec( "create table " + qTableName( "Planet" ) + " (Name varchar(20))" ) );
       
  2656     QVERIFY_SQL( q, exec( "insert into " + qTableName( "Planet" ) + " VALUES ('Mercury')" ) );
       
  2657     QVERIFY_SQL( q, exec( "insert into " + qTableName( "Planet" ) + " VALUES ('Venus')" ) );
       
  2658     QVERIFY_SQL( q, exec( "insert into " + qTableName( "Planet" ) + " VALUES ('Earth')" ) );
       
  2659     QVERIFY_SQL( q, exec( "insert into " + qTableName( "Planet" ) + " VALUES ('Mars')" ) );
       
  2660 
       
  2661     QVERIFY_SQL( q, exec( "SELECT Name FROM "+qTableName( "Planet" ) ) );
       
  2662     QVERIFY_SQL( q, seek( 3 ) );
       
  2663     QCOMPARE( q.value( 0 ).toString(), QString( "Mars" ) );
       
  2664     QVERIFY_SQL( q, seek( 1 ) );
       
  2665     QCOMPARE( q.value( 0 ).toString(), QString( "Venus" ) );
       
  2666     QVERIFY_SQL( q, exec( "SELECT Name FROM "+qTableName( "Planet" ) ) );
       
  2667     QVERIFY_SQL( q, seek( 3 ) );
       
  2668     QCOMPARE( q.value( 0 ).toString(), QString( "Mars" ) );
       
  2669     QVERIFY_SQL( q, seek( 0 ) );
       
  2670     QCOMPARE( q.value( 0 ).toString(), QString( "Mercury" ) );
       
  2671     QVERIFY_SQL( q, seek( 1 ) );
       
  2672     QCOMPARE( q.value( 0 ).toString(), QString( "Venus" ) );
       
  2673 }
       
  2674 
       
  2675 void tst_QSqlQuery::task_250026()
       
  2676 {
       
  2677     QString data258, data1026;
       
  2678     QFETCH( QString, dbName );
       
  2679     QSqlDatabase db = QSqlDatabase::database( dbName );
       
  2680     CHECK_DATABASE( db );
       
  2681     QSqlQuery q( db );
       
  2682 
       
  2683     QString tableName = qTableName( "task_250026" );
       
  2684 
       
  2685     if ( !q.exec( "create table " + tableName + " (longfield varchar(1100))" ) ) {
       
  2686         qDebug() << "Error" << q.lastError();
       
  2687         QSKIP( "Db doesn't support \"1100\" as a size for fields", SkipSingle );
       
  2688     }
       
  2689 
       
  2690     data258.fill( 'A', 258 );
       
  2691     data1026.fill( 'A', 1026 );
       
  2692     QVERIFY_SQL( q, prepare( "insert into " + tableName + "(longfield) VALUES (:longfield)" ) );
       
  2693     q.bindValue( "longfield", data258 );
       
  2694     QVERIFY_SQL( q, exec() );
       
  2695     q.bindValue( "longfield", data1026 );
       
  2696     QVERIFY_SQL( q, exec() );
       
  2697     QVERIFY_SQL( q, exec( "select * from " + tableName ) );
       
  2698     QVERIFY_SQL( q, next() );
       
  2699     QCOMPARE( q.value( 0 ).toString().length(), data258.length() );
       
  2700     QVERIFY_SQL( q, next() );
       
  2701 	QCOMPARE( q.value( 0 ).toString().length(), data1026.length() );
       
  2702 }
       
  2703 
       
  2704 void tst_QSqlQuery::task_205701()
       
  2705 {
       
  2706     QSqlDatabase qsdb = QSqlDatabase::addDatabase("QMYSQL", "atest");
       
  2707     qsdb.setHostName("test");
       
  2708     qsdb.setDatabaseName("test");
       
  2709     qsdb.setUserName("test");
       
  2710     qsdb.setPassword("test");
       
  2711     qsdb.open();
       
  2712 
       
  2713 //     {
       
  2714         QSqlQuery query(qsdb);
       
  2715 //     }
       
  2716     QSqlDatabase::removeDatabase("atest");
       
  2717 }
       
  2718 
       
  2719 #ifdef NOT_READY_YET
       
  2720 // For task: 229811
       
  2721 void tst_QSqlQuery::task_229811()
       
  2722 {
       
  2723     QFETCH( QString, dbName );
       
  2724     QSqlDatabase db = QSqlDatabase::database( dbName );
       
  2725     CHECK_DATABASE( db );
       
  2726 
       
  2727     if (!db.driverName().startsWith( "QODBC" )) return;
       
  2728 
       
  2729     QSqlQuery q( db );
       
  2730 
       
  2731     QString tableName = qTableName( "task_229811" );
       
  2732 
       
  2733     if ( !q.exec( "CREATE TABLE " + tableName + " (Word varchar(20))" ) ) {
       
  2734         qDebug() << "Warning" << q.lastError();
       
  2735     }
       
  2736 
       
  2737     QVERIFY_SQL( q, exec( "INSERT INTO " + tableName + " values ('Albert')" ) );
       
  2738     QVERIFY_SQL( q, exec( "INSERT INTO " + tableName + " values ('Beehive')" ) );
       
  2739     QVERIFY_SQL( q, exec( "INSERT INTO " + tableName + " values ('Alimony')" ) );
       
  2740     QVERIFY_SQL( q, exec( "INSERT INTO " + tableName + " values ('Bohemian')" ) );
       
  2741     QVERIFY_SQL( q, exec( "INSERT INTO " + tableName + " values ('AllStars')" ) );
       
  2742 
       
  2743 
       
  2744     QString stmt = "SELECT * FROM " + tableName  +  " WHERE Word LIKE :name";
       
  2745     QVERIFY_SQL(q,prepare(stmt));
       
  2746     q.bindValue(":name", "A%");
       
  2747     QVERIFY_SQL(q,exec());
       
  2748 
       
  2749     QVERIFY(q.isActive());
       
  2750     QVERIFY(q.isSelect());
       
  2751     QVERIFY(q.first());
       
  2752 
       
  2753     QSqlRecord rec = q.record();
       
  2754     QCOMPARE(rec.field(0).value().toString(), QString("Albert"));
       
  2755     QVERIFY(q.next());
       
  2756     rec = q.record();
       
  2757     QCOMPARE(rec.field(0).value().toString(), QString("Alimony"));
       
  2758     QVERIFY(q.next());
       
  2759     rec = q.record();
       
  2760     QCOMPARE(rec.field(0).value().toString(),QString("AllStars"));
       
  2761 
       
  2762     q.exec("DROP TABLE " + tableName );
       
  2763 }
       
  2764 
       
  2765 void tst_QSqlQuery::task_234422()
       
  2766 {
       
  2767     QFETCH( QString, dbName );
       
  2768     QSqlDatabase db = QSqlDatabase::database( dbName );
       
  2769     CHECK_DATABASE( db );
       
  2770 
       
  2771     QSqlQuery query(db);
       
  2772     QStringList m_airlines;
       
  2773     QStringList m_countries;
       
  2774 
       
  2775     m_airlines << "Lufthansa" << "SAS" << "United" << "KLM" << "Aeroflot";
       
  2776     m_countries << "DE" << "SE" << "US" << "NL" << "RU";
       
  2777 
       
  2778     QString tableName = qTableName( "task_234422" );
       
  2779 
       
  2780     QVERIFY_SQL(query,exec("CREATE TABLE " + tableName + " (id int primary key, "
       
  2781                 "name varchar(20), homecountry varchar(2))"));
       
  2782     for (int i = 0; i < m_airlines.count(); ++i) {
       
  2783         QVERIFY(query.exec(QString("INSERT INTO " + tableName + " values(%1, '%2', '%3')")
       
  2784                     .arg(i).arg(m_airlines[i], m_countries[i])));
       
  2785     }
       
  2786 
       
  2787     QVERIFY_SQL(query, exec("SELECT name FROM " + tableName));
       
  2788     QVERIFY(query.isSelect());
       
  2789     QVERIFY(query.first());
       
  2790     QVERIFY(query.next());
       
  2791     QCOMPARE(query.at(), 1);
       
  2792 
       
  2793     QSqlQuery query2(query);
       
  2794 
       
  2795     QVERIFY_SQL(query2,exec());
       
  2796     QVERIFY(query2.first());
       
  2797     QCOMPARE(query2.at(), 0);
       
  2798     QCOMPARE(query.at(), 1);
       
  2799 }
       
  2800 
       
  2801 #endif
       
  2802 
       
  2803 void tst_QSqlQuery::task_233829()
       
  2804 {
       
  2805     QFETCH( QString, dbName );
       
  2806     QSqlDatabase db = QSqlDatabase::database( dbName );
       
  2807     CHECK_DATABASE( db );
       
  2808 
       
  2809     QSqlQuery q( db );
       
  2810     QString tableName = qTableName("task_233829");
       
  2811     QVERIFY_SQL(q,exec("CREATE TABLE " + tableName  + "(dbl1 double precision,dbl2 double precision) without oids;"));
       
  2812 
       
  2813     QString queryString("INSERT INTO " + tableName +"(dbl1, dbl2) VALUES(?,?)");
       
  2814 
       
  2815     double k = 0.0;
       
  2816     QVERIFY_SQL(q,prepare(queryString));
       
  2817     q.bindValue(0,0.0 / k); // nan
       
  2818     q.bindValue(1,0.0 / k); // nan
       
  2819     QVERIFY_SQL(q,exec());
       
  2820 }
       
  2821 
       
  2822 void tst_QSqlQuery::sqlServerReturn0()
       
  2823 {
       
  2824     QFETCH( QString, dbName );
       
  2825     QSqlDatabase db = QSqlDatabase::database( dbName );
       
  2826     CHECK_DATABASE( db );
       
  2827     if (!tst_Databases::isSqlServer( db ))
       
  2828         QSKIP("SQL Server specific test", SkipSingle);
       
  2829 
       
  2830     QString tableName(qTableName("test141895")), procName(qTableName("test141895_proc"));
       
  2831     QSqlQuery q( db );
       
  2832     q.exec("DROP TABLE " + tableName);
       
  2833     q.exec("DROP PROCEDURE " + procName);
       
  2834     QVERIFY_SQL(q, exec("CREATE TABLE "+tableName+" (id integer)"));
       
  2835     QVERIFY_SQL(q, exec("INSERT INTO "+tableName+" (id) VALUES (1)"));
       
  2836     QVERIFY_SQL(q, exec("INSERT INTO "+tableName+" (id) VALUES (2)"));
       
  2837     QVERIFY_SQL(q, exec("INSERT INTO "+tableName+" (id) VALUES (2)"));
       
  2838     QVERIFY_SQL(q, exec("INSERT INTO "+tableName+" (id) VALUES (3)"));
       
  2839     QVERIFY_SQL(q, exec("INSERT INTO "+tableName+" (id) VALUES (1)"));
       
  2840     QVERIFY_SQL(q, exec("CREATE PROCEDURE "+procName+
       
  2841         " AS "
       
  2842         "SELECT * FROM "+tableName+" WHERE ID = 2 "
       
  2843         "RETURN 0"));
       
  2844 
       
  2845     QVERIFY_SQL(q, exec("{CALL "+procName+"}"));
       
  2846 
       
  2847     QVERIFY_SQL(q, next());
       
  2848 }
       
  2849 
       
  2850 QTEST_MAIN( tst_QSqlQuery )
       
  2851 #include "tst_qsqlquery.moc"