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