diff options
Diffstat (limited to 'tests/auto/sql/kernel/qsqlquery/tst_qsqlquery.cpp')
-rw-r--r-- | tests/auto/sql/kernel/qsqlquery/tst_qsqlquery.cpp | 418 |
1 files changed, 401 insertions, 17 deletions
diff --git a/tests/auto/sql/kernel/qsqlquery/tst_qsqlquery.cpp b/tests/auto/sql/kernel/qsqlquery/tst_qsqlquery.cpp index 1a0340f153..baf2551dfb 100644 --- a/tests/auto/sql/kernel/qsqlquery/tst_qsqlquery.cpp +++ b/tests/auto/sql/kernel/qsqlquery/tst_qsqlquery.cpp @@ -94,6 +94,10 @@ private slots: // forwardOnly mode need special treatment void forwardOnly_data() { generic_data(); } void forwardOnly(); + void forwardOnlyMultipleResultSet_data() { generic_data(); } + void forwardOnlyMultipleResultSet(); + void psql_forwardOnlyQueryResultsLost_data() { generic_data("QPSQL"); } + void psql_forwardOnlyQueryResultsLost(); // bug specific tests void tds_bitField_data() { generic_data("QTDS"); } @@ -248,6 +252,9 @@ private slots: void QTBUG_57138_data() { generic_data("QSQLITE"); } void QTBUG_57138(); + void dateTime_data(); + void dateTime(); + private: // returns all database connections void generic_data(const QString &engine=QString()); @@ -724,6 +731,30 @@ void tst_QSqlQuery::oraOutValues() q.addBindValue( out, QSql::Out ); QVERIFY_SQL( q, exec() ); QCOMPARE( q.boundValue( 1 ).toString(), QString( "fifibubulalakikikokololo" ) ); + + /*** in/outvalue date ***/ + QVERIFY_SQL(q, exec("create or replace procedure " + tst_outValues + "(x in date, y out date) is\n" + "begin\n" + " y := x;\n" + "end;\n")); + QVERIFY(q.prepare("call " + tst_outValues + "(?, ?)")); + const QDate date = QDate::currentDate(); + q.addBindValue(date, QSql::In); + q.addBindValue(QVariant(QDate()), QSql::Out); + QVERIFY_SQL(q, exec()); + QCOMPARE(q.boundValue(1).toDate(), date); + + /*** in/outvalue timestamp ***/ + QVERIFY_SQL(q, exec("create or replace procedure " + tst_outValues + "(x in timestamp, y out timestamp) is\n" + "begin\n" + " y := x;\n" + "end;\n")); + QVERIFY(q.prepare("call " + tst_outValues + "(?, ?)")); + const QDateTime dt = QDateTime::currentDateTime(); + q.addBindValue(dt, QSql::In); + q.addBindValue(QVariant(QVariant::DateTime), QSql::Out); + QVERIFY_SQL(q, exec()); + QCOMPARE(q.boundValue(1).toDateTime(), dt); } void tst_QSqlQuery::oraClob() @@ -1332,6 +1363,8 @@ void tst_QSqlQuery::forwardOnly() QVERIFY( q.isForwardOnly() ); QVERIFY( q.at() == QSql::BeforeFirstRow ); QVERIFY_SQL( q, exec( "select * from " + qtest + " order by id" ) ); + if (!q.isForwardOnly()) + QSKIP("DBMS doesn't support forward-only queries"); QVERIFY( q.at() == QSql::BeforeFirstRow ); QVERIFY( q.first() ); QCOMPARE( q.at(), 0 ); @@ -1405,6 +1438,209 @@ void tst_QSqlQuery::forwardOnly() QCOMPARE( q.at(), int( QSql::AfterLastRow ) ); } +void tst_QSqlQuery::forwardOnlyMultipleResultSet() +{ + QFETCH(QString, dbName); + QSqlDatabase db = QSqlDatabase::database(dbName); + CHECK_DATABASE(db); + + QSqlDriver::DbmsType dbType = tst_Databases::getDatabaseType(db); + + if (!db.driver()->hasFeature(QSqlDriver::MultipleResultSets)) + QSKIP("DBMS doesn't support multiple result sets"); + + QSqlQuery q(db); + q.setForwardOnly(true); + QVERIFY_SQL(q, exec("select id, t_varchar from " + qtest + " order by id;" // 1. + "select id, t_varchar, t_char from " + qtest + " where id<4 order by id;" // 2. + "update " + qtest + " set t_varchar='VarChar555' where id=5;" // 3. + "select * from " + qtest + " order by id;" // 4. + "select * from " + qtest + " where id=5 order by id;" // 5. + "select * from " + qtest + " where id=-1 order by id;" // 6. + "select * from " + qtest + " order by id")); // 7. + + if (!q.isForwardOnly()) + QSKIP("DBMS doesn't support forward-only queries"); + + // 1. Result set with 2 columns and 5 rows + QVERIFY(q.at() == QSql::BeforeFirstRow); + QCOMPARE(q.isActive(), true); + QCOMPARE(q.isSelect(), true); + + // Test record() of first result set + QSqlRecord record = q.record(); + QCOMPARE(record.count(), 2); + QCOMPARE(record.indexOf("id"), 0); + QCOMPARE(record.indexOf("t_varchar"), 1); + if (dbType != QSqlDriver::PostgreSQL) { // tableName() is not available in forward-only mode of QPSQL + QCOMPARE(record.field(0).tableName(), qtest); // BUG: This fails for Microsoft SQL Server 2016 (QODBC), need fix + QCOMPARE(record.field(1).tableName(), qtest); + } + + // Test navigation + QVERIFY(q.first()); + QCOMPARE(q.at(), 0); + QCOMPARE(q.value(0).toInt(), 1); + + QVERIFY(q.next()); + QCOMPARE(q.at(), 1); + QCOMPARE(q.value(0).toInt(), 2); + + QVERIFY(q.seek(3)); + QCOMPARE(q.at(), 3); + QCOMPARE(q.value(0).toInt(), 4); + + QTest::ignoreMessage(QtWarningMsg, "QSqlQuery::seek: cannot seek backwards in a forward only query"); + QVERIFY(q.first() == false); + QCOMPARE(q.at(), 3); + QCOMPARE(q.value(0).toInt(), 4); + + QTest::ignoreMessage(QtWarningMsg, "QSqlQuery::seek: cannot seek backwards in a forward only query"); + QVERIFY(q.previous() == false); + QCOMPARE(q.at(), 3); + QCOMPARE(q.value(0).toInt(), 4); + + QTest::ignoreMessage(QtWarningMsg, "QSqlQuery::seek: cannot seek backwards in a forward only query"); + QVERIFY(q.seek(1) == false); + QCOMPARE(q.at(), 3); + QCOMPARE(q.value(0).toInt(), 4); + + QVERIFY(q.last()); + QCOMPARE(q.at(), 4); + + // Try move after last row + QVERIFY(q.next() == false); + QCOMPARE(q.at(), QSql::AfterLastRow); + QCOMPARE(q.isActive(), true); + + // 2. Result set with 3 columns and 3 rows + QVERIFY(q.nextResult()); + QVERIFY(q.at() == QSql::BeforeFirstRow); + QCOMPARE(q.isActive(), true); + QCOMPARE(q.isSelect(), true); + + // Test record() of second result set + record = q.record(); + QCOMPARE(record.count(), 3); + QCOMPARE(record.indexOf("id"), 0); + QCOMPARE(record.indexOf("t_varchar"), 1); + QCOMPARE(record.indexOf("t_char"), 2); + + // Test iteration + QVERIFY(q.at() == QSql::BeforeFirstRow); + int index = 0; + while (q.next()) { + QCOMPARE(q.at(), index); + QCOMPARE(q.value(0).toInt(), index+1); + index++; + } + QVERIFY(q.at() == QSql::AfterLastRow); + QCOMPARE(index, 3); + + // 3. Update statement + QVERIFY(q.nextResult()); + QVERIFY(q.at() == QSql::BeforeFirstRow); + QCOMPARE(q.isActive(), true); + QCOMPARE(q.isSelect(), false); + QCOMPARE(q.numRowsAffected(), 1); + + // 4. Result set with 5 rows + QVERIFY(q.nextResult()); + QVERIFY(q.at() == QSql::BeforeFirstRow); + QCOMPARE(q.isActive(), true); + QCOMPARE(q.isSelect(), true); + + // Test forward seek(n) + QVERIFY(q.seek(2)); + QCOMPARE(q.at(), 2); + QCOMPARE(q.value(0).toInt(), 3); + + // Test value(string) + QCOMPARE(q.value("id").toInt(), 3); + QCOMPARE(q.value("t_varchar").toString(), "VarChar3"); + QCOMPARE(q.value("t_char").toString().trimmed(), "Char3"); + + // Next 2 rows of current result set will be + // discarded by next call of nextResult() + + // 5. Result set with 1 row + QVERIFY(q.nextResult()); + QVERIFY(q.at() == QSql::BeforeFirstRow); + QCOMPARE(q.isActive(), true); + QCOMPARE(q.isSelect(), true); + QVERIFY(q.first()); + QCOMPARE(q.at(), 0); + QCOMPARE(q.value(0).toInt(), 5); + QVERIFY(q.next() == false); + QVERIFY(q.at() == QSql::AfterLastRow); + + // 6. Result set without rows + QVERIFY(q.nextResult()); + QVERIFY(q.at() == QSql::BeforeFirstRow); + QCOMPARE(q.isActive(), true); + QCOMPARE(q.isSelect(), true); + QVERIFY(q.next() == false); + + // 7. Result set with 5 rows + QVERIFY(q.nextResult()); + QVERIFY(q.at() == QSql::BeforeFirstRow); + QCOMPARE(q.isActive(), true); + QCOMPARE(q.isSelect(), true); + + // Just skip it, so we move after last result set. + QVERIFY(q.nextResult() == false); + QVERIFY(q.at() == QSql::BeforeFirstRow); + QCOMPARE(q.isActive(), false); + + // See if we can execute another query + QVERIFY_SQL(q, exec("select id from " + qtest + " where id=5")); + QVERIFY(q.at() == QSql::BeforeFirstRow); + QCOMPARE(q.isActive(), true); + QCOMPARE(q.isSelect(), true); + QVERIFY(q.first()); + QCOMPARE(q.at(), 0); + QCOMPARE(q.value("id").toInt(), 5); + QCOMPARE(q.record().count(), 1); + QCOMPARE(q.record().indexOf("id"), 0); +} + +void tst_QSqlQuery::psql_forwardOnlyQueryResultsLost() +{ + QFETCH(QString, dbName); + QSqlDatabase db = QSqlDatabase::database(dbName); + CHECK_DATABASE(db); + + QSqlQuery q1(db); + q1.setForwardOnly(true); + QVERIFY_SQL(q1, exec("select * from " + qtest + " where id<=3 order by id")); + if (!q1.isForwardOnly()) + QSKIP("DBMS doesn't support forward-only queries"); + + // Read first row of q1 + QVERIFY(q1.next()); + QCOMPARE(q1.at(), 0); + QCOMPARE(q1.value(0).toInt(), 1); + + // Executing another query on the same db connection + // will cause the query results of q1 to be lost. + QSqlQuery q2(db); + q2.setForwardOnly(true); + QVERIFY_SQL(q2, exec("select * from " + qtest + " where id>3 order by id")); + + QTest::ignoreMessage(QtWarningMsg, "QPSQLDriver::getResult: Query results lost - " + "probably discarded on executing another SQL query."); + + // Reading next row of q1 will not possible. + QVERIFY(!q1.next()); + QCOMPARE(q1.at(), QSql::AfterLastRow); + QVERIFY(q1.lastError().type() != QSqlError::NoError); + + // See if we can read rows from q2 + QVERIFY(q2.seek(1)); + QCOMPARE(q2.at(), 1); + QCOMPARE(q2.value(0).toInt(), 5); +} + void tst_QSqlQuery::query_exec() { QFETCH( QString, dbName ); @@ -2163,8 +2399,8 @@ void tst_QSqlQuery::batchExec() QSqlQuery q( db ); const QString tableName = qTableName("qtest_batch", __FILE__, db); - QVERIFY_SQL( q, exec( "create table " + tableName + " (id int, name varchar(20), dt date, num numeric(8, 4))" ) ); - QVERIFY_SQL( q, prepare( "insert into " + tableName + " (id, name, dt, num) values (?, ?, ?, ?)" ) ); + QVERIFY_SQL(q, exec("create table " + tableName + " (id int, name varchar(20), dt date, num numeric(8, 4), dtstamp TIMESTAMP(3))")); + QVERIFY_SQL(q, prepare("insert into " + tableName + " (id, name, dt, num, dtstamp) values (?, ?, ?, ?, ?)")); QVariantList intCol; intCol << 1 << 2 << QVariant( QVariant::Int ); @@ -2179,31 +2415,54 @@ void tst_QSqlQuery::batchExec() QVariantList numCol; numCol << 2.3 << 3.4 << QVariant( QVariant::Double ); - q.addBindValue( intCol ); + QVariantList timeStampCol; + const QDateTime dtStamp = QDateTime(QDate::currentDate(), QTime(1, 2, 3, 4)); + timeStampCol << dtStamp << dtStamp.addDays(-1) << QVariant(QVariant::DateTime); + + q.addBindValue(intCol); q.addBindValue( charCol ); q.addBindValue( dateCol ); q.addBindValue( numCol ); + q.addBindValue(timeStampCol); QVERIFY_SQL( q, execBatch() ); - QVERIFY_SQL( q, exec( "select id, name, dt, num from " + tableName + " order by id" ) ); + QVERIFY_SQL(q, exec("select id, name, dt, num, dtstamp from " + tableName + " order by id")); QVERIFY( q.next() ); QCOMPARE( q.value( 0 ).toInt(), 1 ); QCOMPARE( q.value( 1 ).toString(), QString( "harald" ) ); QCOMPARE( q.value( 2 ).toDateTime(), dt ); QCOMPARE( q.value( 3 ).toDouble(), 2.3 ); + QCOMPARE(q.value(4).toDateTime(), dtStamp); QVERIFY( q.next() ); QCOMPARE( q.value( 0 ).toInt(), 2 ); QCOMPARE( q.value( 1 ).toString(), QString( "boris" ) ); QCOMPARE( q.value( 2 ).toDateTime(), dt.addDays( -1 ) ); QCOMPARE( q.value( 3 ).toDouble(), 3.4 ); + QCOMPARE(q.value(4).toDateTime(), dtStamp.addDays(-1)); QVERIFY( q.next() ); QVERIFY( q.value( 0 ).isNull() ); QVERIFY( q.value( 1 ).isNull() ); QVERIFY( q.value( 2 ).isNull() ); QVERIFY( q.value( 3 ).isNull() ); + QVERIFY(q.value(4).isNull()); + + const QString procName = qTableName("qtest_batch_proc", __FILE__, db); + QVERIFY_SQL(q, exec("create or replace procedure " + procName + " (x in timestamp, y out timestamp) is\n" + "begin\n" + " y := x;\n" + "end;\n")); + QVERIFY(q.prepare("call " + procName + "(?, ?)")); + q.addBindValue(timeStampCol, QSql::In); + QVariantList emptyDateTimes; + emptyDateTimes.reserve(timeStampCol.size()); + for (int i = 0; i < timeStampCol.size(); i++) + emptyDateTimes << QVariant(QDateTime()); + q.addBindValue(emptyDateTimes, QSql::Out); + QVERIFY_SQL(q, execBatch()); + QCOMPARE(q.boundValue(1).toList(), timeStampCol); } void tst_QSqlQuery::QTBUG_43874() @@ -2658,8 +2917,8 @@ void tst_QSqlQuery::nextResult() QSqlDatabase db = QSqlDatabase::database( dbName ); CHECK_DATABASE( db ); const QSqlDriver::DbmsType dbType = tst_Databases::getDatabaseType(db); - if ( !db.driver()->hasFeature( QSqlDriver::MultipleResultSets ) || !db.driver()->hasFeature( QSqlDriver::BatchOperations ) ) - QSKIP( "DBMS does not support multiple result sets or batch operations"); + if (!db.driver()->hasFeature(QSqlDriver::MultipleResultSets)) + QSKIP("DBMS does not support multiple result sets"); QSqlQuery q( db ); @@ -2772,7 +3031,10 @@ void tst_QSqlQuery::nextResult() // Stored procedure with multiple result sets const QString procName(qTableName("proc_more_res", __FILE__, db)); - q.exec( QString( "DROP PROCEDURE %1;" ).arg( procName ) ); + if (dbType == QSqlDriver::PostgreSQL) + q.exec(QString("DROP FUNCTION %1(refcursor, refcursor);").arg(procName)); + else + q.exec(QString("DROP PROCEDURE %1;").arg(procName)); if (dbType == QSqlDriver::MySqlServer) QVERIFY_SQL( q, exec( QString( "CREATE PROCEDURE %1()" @@ -2790,6 +3052,16 @@ void tst_QSqlQuery::nextResult() "\nOPEN cursor1;" "\nOPEN cursor2;" "\nEND p1" ).arg( procName ).arg( tableName ).arg( tableName ) ) ); + else if (dbType == QSqlDriver::PostgreSQL) + QVERIFY_SQL(q, exec(QString("CREATE FUNCTION %1(ref1 refcursor, ref2 refcursor)" + "\nRETURNS SETOF refcursor AS $$" + "\nBEGIN" + "\nOPEN ref1 FOR SELECT id, text FROM %2;" + "\nRETURN NEXT ref1;" + "\nOPEN ref2 FOR SELECT empty, num, text, id FROM %2;" + "\nRETURN NEXT ref2;" + "\nEND;" + "\n$$ LANGUAGE plpgsql").arg(procName).arg(tableName))); else QVERIFY_SQL( q, exec( QString( "CREATE PROCEDURE %1" "\nAS" @@ -2799,10 +3071,32 @@ void tst_QSqlQuery::nextResult() if (dbType == QSqlDriver::MySqlServer || dbType == QSqlDriver::DB2) { q.setForwardOnly( true ); QVERIFY_SQL( q, exec( QString( "CALL %1()" ).arg( procName ) ) ); + } else if (dbType == QSqlDriver::PostgreSQL) { + // Returning multiple result sets from PostgreSQL stored procedure: + // http://sqlines.com/postgresql/how-to/return_result_set_from_stored_procedure + QVERIFY_SQL(q, exec(QString("BEGIN;" + "SELECT %1('cur1', 'cur2');" + "FETCH ALL IN cur1;" + "FETCH ALL IN cur2;" + "COMMIT;").arg(procName))); } else { QVERIFY_SQL( q, exec( QString( "EXEC %1" ).arg( procName ) ) ); } + if (dbType == QSqlDriver::PostgreSQL) { + // First result set - start of transaction + QVERIFY(!q.isSelect()); + QCOMPARE(q.numRowsAffected(), 0); + QVERIFY(q.nextResult()); + // Second result set contains cursor names + QVERIFY(q.isSelect()); + QVERIFY(q.next()); + QCOMPARE(q.value(0).toString(), "cur1"); + QVERIFY(q.next()); + QCOMPARE(q.value(0).toString(), "cur2"); + QVERIFY(q.nextResult()); + } + for ( int i = 0; i < 4; i++ ) { QVERIFY_SQL( q, next() ); QCOMPARE( q.value( 0 ).toInt(), i+1 ); @@ -2827,12 +3121,21 @@ void tst_QSqlQuery::nextResult() QVERIFY( !q.isSelect() ); // ... but it's not a select QCOMPARE( q.numRowsAffected(), 0 ); // ... and no rows are affected (at least not with this procedure) } + if (dbType == QSqlDriver::PostgreSQL) { + // Last result set - commit transaction + QVERIFY(q.nextResult()); + QVERIFY(!q.isSelect()); + QCOMPARE(q.numRowsAffected(), 0); + } QVERIFY( !q.nextResult() ); QVERIFY( !q.isActive() ); - q.exec( QString( "DROP PROCEDURE %1;" ).arg( procName ) ); + if (dbType == QSqlDriver::PostgreSQL) + q.exec(QString("DROP FUNCTION %1(refcursor, refcursor);").arg(procName)); + else + q.exec(QString("DROP PROCEDURE %1;").arg(procName)); } @@ -2919,16 +3222,14 @@ void tst_QSqlQuery::timeStampParsing() QFETCH(QString, dbName); QSqlDatabase db = QSqlDatabase::database(dbName); CHECK_DATABASE(db); + const QString tableName(qTableName("timeStampParsing", __FILE__, db)); + tst_Databases::safeDropTable(db, tableName); QSqlQuery q(db); - QVERIFY_SQL(q, exec( - "CREATE TABLE \"main\".\"datetest\" (" - "\"id\" integer NOT NULL PRIMARY KEY AUTOINCREMENT," - "\"datefield\" timestamp);" - )); - QVERIFY_SQL(q, exec( - "INSERT INTO datetest (datefield) VALUES (current_timestamp);" - )); - QVERIFY_SQL(q, exec("SELECT * FROM datetest;")); + QVERIFY_SQL(q, exec(QStringLiteral("CREATE TABLE ") + tableName + + QStringLiteral(" (id integer, datefield timestamp)"))); + QVERIFY_SQL(q, exec(QStringLiteral("INSERT INTO ") + tableName + + QStringLiteral(" (datefield) VALUES (current_timestamp)"))); + QVERIFY_SQL(q, exec(QStringLiteral("SELECT * FROM ") + tableName)); while (q.next()) QVERIFY(q.value(1).toDateTime().isValid()); } @@ -4167,5 +4468,88 @@ void tst_QSqlQuery::QTBUG_57138() QCOMPARE(q.value(2).toDateTime(), tzoffset); } +void tst_QSqlQuery::dateTime_data() +{ + QTest::addColumn<QString>("dbName"); + QTest::addColumn<QString>("tableName"); + QTest::addColumn<QString>("createTableString"); + QTest::addColumn<QList<QDateTime> >("initialDateTimes"); + QTest::addColumn<QList<QDateTime> >("expectedDateTimes"); + + // Using time zones which are highly unlikely to be the same as the testing machine's one + // as it could pass as a result despite it. + // +8.5 hours from UTC to North Korea + const QTimeZone afterUTCTimeZone(30600); + // -8 hours from UTC to Belize + const QTimeZone beforeUTCTimeZone(-28800); + const QTimeZone utcTimeZone("UTC"); + const QDateTime dt(QDate(2015, 5, 18), QTime(4, 26, 30)); + const QDateTime dtWithMS(QDate(2015, 5, 18), QTime(4, 26, 30, 500)); + const QDateTime dtWithAfterTZ(QDate(2015, 5, 18), QTime(4, 26, 30, 500), afterUTCTimeZone); + const QDateTime dtWithBeforeTZ(QDate(2015, 5, 18), QTime(4, 26, 30, 500), beforeUTCTimeZone); + const QDateTime dtWithUTCTZ(QDate(2015, 5, 18), QTime(4, 26, 30, 500), utcTimeZone); + const QList<QDateTime> dateTimes = { dt, dtWithMS, dtWithAfterTZ, dtWithBeforeTZ, dtWithUTCTZ }; + const QList<QDateTime> expectedDateTimesLocalTZ = { dt, dtWithMS, dtWithAfterTZ.toLocalTime(), + dtWithBeforeTZ.toLocalTime(), + dtWithUTCTZ.toLocalTime() }; + const QList<QDateTime> expectedTimeStampDateTimes = { dt, dtWithMS, dtWithMS, dtWithMS, dtWithMS }; + const QList<QDateTime> expectedDateTimes = { dt, dt, dt, dt, dt }; + + for (const QString &dbName : qAsConst(dbs.dbNames)) { + QSqlDatabase db = QSqlDatabase::database(dbName); + if (!db.isValid()) + continue; + const QString tableNameTSWithTimeZone(qTableName("dateTimeTSWithTimeZone", __FILE__, db)); + const QString tableNameTSWithLocalTimeZone(qTableName("dateTimeTSWithLocalTimeZone", __FILE__, db)); + const QString tableNameTS(qTableName("dateTimeTS", __FILE__, db)); + const QString tableNameDate(qTableName("dateTimeDate", __FILE__, db)); + QTest::newRow(QString(dbName + " timestamp with time zone").toLatin1()) + << dbName << tableNameTSWithTimeZone + << QStringLiteral(" (dt TIMESTAMP WITH TIME ZONE)") + << dateTimes << dateTimes; + QTest::newRow(QString(dbName + " timestamp with local time zone").toLatin1()) + << dbName << tableNameTSWithTimeZone + << QStringLiteral(" (dt TIMESTAMP WITH LOCAL TIME ZONE)") + << dateTimes << expectedDateTimesLocalTZ; + QTest::newRow(QString(dbName + "timestamp").toLatin1()) + << dbName << tableNameTS << QStringLiteral(" (dt TIMESTAMP(3))") + << dateTimes << expectedTimeStampDateTimes; + QTest::newRow(QString(dbName + "date").toLatin1()) + << dbName << tableNameDate << QStringLiteral(" (dt DATE)") + << dateTimes << expectedDateTimes; + } +} + +void tst_QSqlQuery::dateTime() +{ + QFETCH(QString, dbName); + QSqlDatabase db = QSqlDatabase::database(dbName); + CHECK_DATABASE(db); + + QSqlDriver::DbmsType dbType = tst_Databases::getDatabaseType(db); + if (dbType != QSqlDriver::Oracle) + QSKIP("Implemented only for Oracle"); + + QFETCH(QString, tableName); + QFETCH(QString, createTableString); + QFETCH(QList<QDateTime>, initialDateTimes); + QFETCH(QList<QDateTime>, expectedDateTimes); + + tst_Databases::safeDropTable(db, tableName); + + QSqlQuery q(db); + QVERIFY_SQL(q, exec("CREATE TABLE " + tableName + createTableString)); + for (const QDateTime &dt : qAsConst(initialDateTimes)) { + QVERIFY_SQL(q, prepare("INSERT INTO " + tableName + " values(:dt)")); + q.bindValue(":dt", dt); + QVERIFY_SQL(q, exec()); + } + QVERIFY_SQL(q, exec("SELECT * FROM " + tableName)); + for (const QDateTime &dt : qAsConst(expectedDateTimes)) { + QVERIFY(q.next()); + QCOMPARE(q.value(0).toDateTime(), dt); + } +} + QTEST_MAIN( tst_QSqlQuery ) #include "tst_qsqlquery.moc" |