diff options
Diffstat (limited to 'tests/auto/qsqldatabase/tst_qsqldatabase.cpp')
| -rw-r--r-- | tests/auto/qsqldatabase/tst_qsqldatabase.cpp | 170 |
1 files changed, 132 insertions, 38 deletions
diff --git a/tests/auto/qsqldatabase/tst_qsqldatabase.cpp b/tests/auto/qsqldatabase/tst_qsqldatabase.cpp index 03847b7..f85ebc5 100644 --- a/tests/auto/qsqldatabase/tst_qsqldatabase.cpp +++ b/tests/auto/qsqldatabase/tst_qsqldatabase.cpp @@ -180,6 +180,8 @@ private slots: void odbc_uintfield(); void odbc_bindBoolean_data() { generic_data("QODBC"); } void odbc_bindBoolean(); + void odbc_testqGetString_data() { generic_data("QODBC"); } + void odbc_testqGetString(); void oci_serverDetach_data() { generic_data("QOCI"); } void oci_serverDetach(); // For task 154518 @@ -187,6 +189,8 @@ private slots: void oci_xmltypeSupport(); void oci_fieldLength_data() { generic_data("QOCI"); } void oci_fieldLength(); + void oci_synonymstest_data() { generic_data("QOCI"); } + void oci_synonymstest(); void sqlite_bindAndFetchUInt_data() { generic_data("QSQLITE"); } void sqlite_bindAndFetchUInt(); @@ -249,7 +253,7 @@ struct FieldDef { // excluding the primary key field static int createFieldTable(const FieldDef fieldDefs[], QSqlDatabase db) { - tst_Databases::safeDropTables(db, QStringList() << qTableName("qtestfields")); + tst_Databases::safeDropTable(db, qTableName("qtestfields")); QSqlQuery q(db); // construct a create table statement consisting of all fieldtypes QString qs = "create table " + qTableName("qtestfields"); @@ -347,19 +351,28 @@ void tst_QSqlDatabase::dropTestTables(QSqlDatabase db) << qTableName("numericfields") << qTableName("qtest_ibaseblobs") << qTableName("qtestBindBool") + << qTableName("testqGetString") << qTableName("qtest_sqlguid") << qTableName("uint_table") << qTableName("uint_test") << qTableName("bug_249059"); QSqlQuery q(0, db); - if (db.driverName().startsWith("QPSQL")) + if (db.driverName().startsWith("QPSQL")) { q.exec("drop schema " + qTableName("qtestschema") + " cascade"); + q.exec("drop schema " + qTableName("qtestScHeMa") + " cascade"); + } if (testWhiteSpaceNames(db.driverName())) - tableNames << (qTableName("qtest") + " test"); + tableNames << db.driver()->escapeIdentifier(qTableName("qtest") + " test", QSqlDriver::TableName); tst_Databases::safeDropTables(db, tableNames); + + if (db.driverName().startsWith("QOCI")) { + q.exec("drop user "+qTableName("CREATOR")+" cascade"); + q.exec("drop user "+qTableName("APPUSER")+" cascade"); + + } } void tst_QSqlDatabase::populateTestTables(QSqlDatabase db) @@ -508,10 +521,6 @@ void tst_QSqlDatabase::tables() QVERIFY(tables.contains(qTableName("qtest"), Qt::CaseInsensitive)); QVERIFY(!tables.contains("sql_features", Qt::CaseInsensitive)); //check for postgres 7.4 internal tables if (views) { - if (db.driverName().startsWith("QMYSQL")) - // MySQL doesn't differentiate between tables and views when calling QSqlDatabase::tables() - // May be fixable by doing a select on informational_schema.tables instead of using the client library api - QEXPECT_FAIL("", "MySQL driver thinks that views are tables", Continue); QVERIFY(!tables.contains(qTableName("qtest_view"), Qt::CaseInsensitive)); } if (tempTables) @@ -519,10 +528,6 @@ void tst_QSqlDatabase::tables() tables = db.tables(QSql::Views); if (views) { - if (db.driverName().startsWith("QMYSQL")) - // MySQL doesn't give back anything when calling QSqlDatabase::tables() with QSql::Views - // May be fixable by doing a select on informational_schema.views instead of using the client library api - QEXPECT_FAIL("", "MySQL driver thinks that views are tables", Continue); if(!tables.contains(qTableName("qtest_view"), Qt::CaseInsensitive)) qDebug() << "failed to find" << qTableName("qtest_view") << "in" << tables; QVERIFY(tables.contains(qTableName("qtest_view"), Qt::CaseInsensitive)); @@ -543,11 +548,6 @@ void tst_QSqlDatabase::tables() QVERIFY(tables.contains(qTableName("temp_tab"), Qt::CaseInsensitive)); QVERIFY(tables.contains(qTableName("qtest"), Qt::CaseInsensitive)); - if (tst_Databases::isMSAccess(db)) - QSqlQuery("drop table " + qTableName("qtest_view"), db); - else - QSqlQuery("drop view " + qTableName("qtest_view"), db); - if (db.driverName().startsWith("QPSQL")) { QVERIFY(tables.contains(qTableName("qtest") + " test")); } @@ -563,19 +563,19 @@ void tst_QSqlDatabase::whitespaceInIdentifiers() QString tableName = qTableName("qtest") + " test"; QVERIFY(db.tables().contains(tableName, Qt::CaseInsensitive)); - QSqlRecord rec = db.record(tableName); + QSqlRecord rec = db.record(db.driver()->escapeIdentifier(tableName, QSqlDriver::TableName)); QCOMPARE(rec.count(), 1); QCOMPARE(rec.fieldName(0), QString("test test")); if(db.driverName().startsWith("QOCI")) - QCOMPARE(rec.field(0).type(), QVariant::String); + QCOMPARE(rec.field(0).type(), QVariant::Double); else QCOMPARE(rec.field(0).type(), QVariant::Int); - QSqlIndex idx = db.primaryIndex(tableName); + QSqlIndex idx = db.primaryIndex(db.driver()->escapeIdentifier(tableName, QSqlDriver::TableName)); QCOMPARE(idx.count(), 1); QCOMPARE(idx.fieldName(0), QString("test test")); if(db.driverName().startsWith("QOCI")) - QCOMPARE(idx.field(0).type(), QVariant::String); + QCOMPARE(idx.field(0).type(), QVariant::Double); else QCOMPARE(idx.field(0).type(), QVariant::Int); } else { @@ -923,7 +923,7 @@ void tst_QSqlDatabase::recordOCI() FieldDef("varchar(20)", QVariant::String, QString("blah2")), FieldDef("nchar(20)", QVariant::String, QString("blah3")), FieldDef("nvarchar2(20)", QVariant::String, QString("blah4")), - FieldDef("number(10,5)", QVariant::String, 1.1234567), + FieldDef("number(10,5)", QVariant::Double, 1.1234567), FieldDef("date", QVariant::DateTime, dt), #ifdef QT3_SUPPORT //X? FieldDef("long raw", QVariant::ByteArray, QByteArray(Q3CString("blah5"))), @@ -1085,8 +1085,8 @@ void tst_QSqlDatabase::recordMySQL() FieldDef("bigint unsigned", QVariant::ULongLong, Q_UINT64_C(18446744073709551615)), FieldDef("float", QVariant::Double, 1.12345), FieldDef("double", QVariant::Double, 1.123456789), - FieldDef("decimal(10, 9)", QVariant::String,1.123456789), - FieldDef("numeric(5, 2)", QVariant::String, 123.67), + FieldDef("decimal(10, 9)", QVariant::Double,1.123456789), + FieldDef("numeric(5, 2)", QVariant::Double, 123.67), FieldDef("date", QVariant::Date, QDate::currentDate()), FieldDef("datetime", QVariant::DateTime, dt), FieldDef("timestamp", QVariant::DateTime, dt, false), @@ -1528,7 +1528,7 @@ void tst_QSqlDatabase::psql_escapedIdentifiers() QSqlQuery q(db); QString schemaName = qTableName("qtestScHeMa"); - QString tableName = qTableName("qtestTaBlE"); + QString tableName = qTableName("qtest"); QString field1Name = QString("fIeLdNaMe"); QString field2Name = QString("ZuLu"); @@ -1546,7 +1546,7 @@ void tst_QSqlDatabase::psql_escapedIdentifiers() rec.append(fld1); rec.append(fld2); - QVERIFY_SQL(q, exec(drv->sqlStatement(QSqlDriver::SelectStatement, schemaName + '.' + tableName, rec, false))); + QVERIFY_SQL(q, exec(drv->sqlStatement(QSqlDriver::SelectStatement, db.driver()->escapeIdentifier(schemaName, QSqlDriver::TableName) + '.' + db.driver()->escapeIdentifier(tableName, QSqlDriver::TableName), rec, false))); rec = q.record(); QCOMPARE(rec.count(), 2); @@ -1641,62 +1641,84 @@ void tst_QSqlDatabase::precisionPolicy() QSKIP("Driver or database doesn't support setting precision policy", SkipSingle); // Create a test table with some data - QVERIFY_SQL(q, exec(QString("CREATE TABLE %1 (id smallint, num numeric(20,0))").arg(tableName))); + QVERIFY_SQL(q, exec(QString("CREATE TABLE %1 (id smallint, num numeric(18,5))").arg(tableName))); QVERIFY_SQL(q, prepare(QString("INSERT INTO %1 VALUES (?, ?)").arg(tableName))); q.bindValue(0, 1); q.bindValue(1, 123); QVERIFY_SQL(q, exec()); q.bindValue(0, 2); - q.bindValue(1, QString("18500000000000000000")); + q.bindValue(1, 1850000000000.0001); QVERIFY_SQL(q, exec()); // These are expected to pass + q.setNumericalPrecisionPolicy(QSql::HighPrecision); QString query = QString("SELECT num FROM %1 WHERE id = 1").arg(tableName); QVERIFY_SQL(q, exec(query)); QVERIFY_SQL(q, next()); + if(db.driverName().startsWith("QSQLITE")) + QEXPECT_FAIL("", "SQLite returns this value as determined by contents of the field, not the declaration", Continue); QCOMPARE(q.value(0).type(), QVariant::String); q.setNumericalPrecisionPolicy(QSql::LowPrecisionInt64); QVERIFY_SQL(q, exec(query)); QVERIFY_SQL(q, next()); + if(q.value(0).type() != QVariant::LongLong) + QEXPECT_FAIL("", "SQLite returns this value as determined by contents of the field, not the declaration", Continue); QCOMPARE(q.value(0).type(), QVariant::LongLong); QCOMPARE(q.value(0).toLongLong(), (qlonglong)123); q.setNumericalPrecisionPolicy(QSql::LowPrecisionInt32); QVERIFY_SQL(q, exec(query)); + if(db.driverName().startsWith("QOCI")) + QEXPECT_FAIL("", "Oracle fails to move to next when data columns are oversize", Abort); QVERIFY_SQL(q, next()); + if(db.driverName().startsWith("QSQLITE")) + QEXPECT_FAIL("", "SQLite returns this value as determined by contents of the field, not the declaration", Continue); QCOMPARE(q.value(0).type(), QVariant::Int); QCOMPARE(q.value(0).toInt(), 123); q.setNumericalPrecisionPolicy(QSql::LowPrecisionDouble); QVERIFY_SQL(q, exec(query)); QVERIFY_SQL(q, next()); + if(db.driverName().startsWith("QSQLITE")) + QEXPECT_FAIL("", "SQLite returns this value as determined by contents of the field, not the declaration", Continue); QCOMPARE(q.value(0).type(), QVariant::Double); QCOMPARE(q.value(0).toDouble(), (double)123); query = QString("SELECT num FROM %1 WHERE id = 2").arg(tableName); QVERIFY_SQL(q, exec(query)); QVERIFY_SQL(q, next()); + if(db.driverName().startsWith("QSQLITE")) + QEXPECT_FAIL("", "SQLite returns this value as determined by contents of the field, not the declaration", Continue); QCOMPARE(q.value(0).type(), QVariant::Double); - QCOMPARE(q.value(0).toDouble(), QString("18500000000000000000").toDouble()); + QCOMPARE(q.value(0).toDouble(), QString("1850000000000.0001").toDouble()); // Postgres returns invalid QVariants on overflow q.setNumericalPrecisionPolicy(QSql::HighPrecision); QVERIFY_SQL(q, exec(query)); QVERIFY_SQL(q, next()); + if(db.driverName().startsWith("QSQLITE")) + QEXPECT_FAIL("", "SQLite returns this value as determined by contents of the field, not the declaration", Continue); QCOMPARE(q.value(0).type(), QVariant::String); q.setNumericalPrecisionPolicy(QSql::LowPrecisionInt64); + QEXPECT_FAIL("QOCI", "Oracle fails here, to retrieve next", Continue); QVERIFY_SQL(q, exec(query)); QVERIFY_SQL(q, next()); - QCOMPARE(q.value(0).type(), QVariant::Invalid); + if(db.driverName().startsWith("QSQLITE")) + QEXPECT_FAIL("", "SQLite returns this value as determined by contents of the field, not the declaration", Continue); + QCOMPARE(q.value(0).type(), QVariant::LongLong); - q.setNumericalPrecisionPolicy(QSql::LowPrecisionInt32); - QVERIFY_SQL(q, exec(query)); - if(db.driverName().startsWith("QOCI")) - QEXPECT_FAIL("", "Oracle fails to move to next when data columns are oversize", Abort); - QVERIFY_SQL(q, next()); - QCOMPARE(q.value(0).type(), QVariant::Invalid); + QSql::NumericalPrecisionPolicy oldPrecision= db.numericalPrecisionPolicy(); + db.setNumericalPrecisionPolicy(QSql::LowPrecisionInt64); + QSqlQuery q2(db); + q2.exec(QString("SELECT num FROM %1 WHERE id = 2").arg(tableName)); + QVERIFY_SQL(q2, exec(query)); + QVERIFY_SQL(q2, next()); + if(db.driverName().startsWith("QSQLITE")) + QEXPECT_FAIL("", "SQLite returns this value as determined by contents of the field, not the declaration", Continue); + QCOMPARE(q2.value(0).type(), QVariant::LongLong); + db.setNumericalPrecisionPolicy(oldPrecision); } // This test needs a ODBC data source containing MYSQL in it's name @@ -2005,6 +2027,44 @@ void tst_QSqlDatabase::odbc_bindBoolean() QCOMPARE(q.value(1).toBool(), false); } +void tst_QSqlDatabase::odbc_testqGetString() +{ + QFETCH(QString, dbName); + QSqlDatabase db = QSqlDatabase::database(dbName); + CHECK_DATABASE(db); + + QSqlQuery q(db); + QVERIFY_SQL(q, exec("CREATE TABLE " + qTableName("testqGetString") + "(id int, vcvalue varchar(65538))")); + + QString largeString; + largeString.fill('A', 65536); + + // Bind and insert + QVERIFY_SQL(q, prepare("INSERT INTO " + qTableName("testqGetString") + " VALUES(?, ?)")); + q.bindValue(0, 1); + q.bindValue(1, largeString); + QVERIFY_SQL(q, exec()); + q.bindValue(0, 2); + q.bindValue(1, largeString+QLatin1Char('B')); + QVERIFY_SQL(q, exec()); + q.bindValue(0, 3); + q.bindValue(1, largeString+QLatin1Char('B')+QLatin1Char('C')); + QVERIFY_SQL(q, exec()); + + // Retrive + QVERIFY_SQL(q, exec("SELECT id, vcvalue FROM " + qTableName("testqGetString") + " ORDER BY id")); + QVERIFY_SQL(q, next()); + QCOMPARE(q.value(0).toInt(), 1); + QCOMPARE(q.value(1).toString().length(), 65536); + QVERIFY_SQL(q, next()); + QCOMPARE(q.value(0).toInt(), 2); + QCOMPARE(q.value(1).toString().length(), 65537); + QVERIFY_SQL(q, next()); + QCOMPARE(q.value(0).toInt(), 3); + QCOMPARE(q.value(1).toString().length(), 65538); +} + + void tst_QSqlDatabase::mysql_multiselect() { QFETCH(QString, dbName); @@ -2110,6 +2170,36 @@ void tst_QSqlDatabase::oci_fieldLength() QCOMPARE(q.record().field(1).length(), 40); } +void tst_QSqlDatabase::oci_synonymstest() +{ + QFETCH(QString, dbName); + QSqlDatabase db = QSqlDatabase::database(dbName); + CHECK_DATABASE(db); + + QSqlQuery q(db); + QString creator(qTableName("CREATOR")), appuser(qTableName("APPUSER")), table1(qTableName("TABLE1")); +// QVERIFY_SQL(q, exec("drop public synonym "+table1)); + QVERIFY_SQL(q, exec(QLatin1String("create user "+creator+" identified by "+creator+" default tablespace users temporary tablespace temp"))); + QVERIFY_SQL(q, exec(QLatin1String("grant CONNECT to "+creator))); + QVERIFY_SQL(q, exec(QLatin1String("grant RESOURCE to "+creator))); + QSqlDatabase db2=db.cloneDatabase(db, QLatin1String("oci_synonymstest")); + db2.close(); + QVERIFY_SQL(db2, open(creator,creator)); + QSqlQuery q2(db2); + QVERIFY_SQL(q2, exec("create table "+table1+"(id int primary key)")); + QVERIFY_SQL(q, exec(QLatin1String("create user "+appuser+" identified by "+appuser+" default tablespace users temporary tablespace temp"))); + QVERIFY_SQL(q, exec(QLatin1String("grant CREATE ANY SYNONYM to "+appuser))); + QVERIFY_SQL(q, exec(QLatin1String("grant CONNECT to "+appuser))); + QVERIFY_SQL(q2, exec(QLatin1String("grant select, insert, update, delete on "+table1+" to "+appuser))); + QSqlDatabase db3=db.cloneDatabase(db, QLatin1String("oci_synonymstest2")); + db3.close(); + QVERIFY_SQL(db3, open(appuser,appuser)); + QSqlQuery q3(db3); + QVERIFY_SQL(q3, exec("create synonym "+appuser+'.'+qTableName("synonyms")+" for "+creator+'.'+table1)); + QVERIFY_SQL(db3, tables().filter(qTableName("synonyms"), Qt::CaseInsensitive).count() >= 1); +} + + // This test isn't really necessary as SQL_GUID / uniqueidentifier is // already tested in recordSQLServer(). void tst_QSqlDatabase::odbc_uniqueidentifier() @@ -2255,18 +2345,22 @@ void tst_QSqlDatabase::eventNotificationPSQL() QSqlDatabase db = QSqlDatabase::database(dbName); CHECK_DATABASE(db); +#if defined(Q_OS_LINUX) + QSKIP( "Event support doesn't work on linux", SkipAll ); +#endif + QSqlQuery query(db); QString procedureName = qTableName("posteventProc"); - QSqlDriver *driver=db.driver(); - QVERIFY_SQL(*driver, subscribeToNotification(procedureName)); + QSqlDriver &driver=*(db.driver()); + QVERIFY_SQL(driver, subscribeToNotification(procedureName)); QSignalSpy spy(db.driver(), SIGNAL(notification(const QString&))); query.exec(QString("NOTIFY \"%1\"").arg(procedureName)); QCoreApplication::processEvents(); QCOMPARE(spy.count(), 1); QList<QVariant> arguments = spy.takeFirst(); QVERIFY(arguments.at(0).toString() == procedureName); - QVERIFY_SQL(*driver, unsubscribeFromNotification(procedureName)); + QVERIFY_SQL(driver, unsubscribeFromNotification(procedureName)); } void tst_QSqlDatabase::sqlite_bindAndFetchUInt() |
