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