From a290f3b64a4a77018845612eef15baa98fc0833a Mon Sep 17 00:00:00 2001 From: Bill King Date: Thu, 18 Jun 2009 13:57:51 +1000 Subject: Stage 2 of incorporating database level precision policy. All autotests pass now for all databases except DB2 (untested). --- src/sql/drivers/ibase/qsql_ibase.cpp | 36 +++++++++++++++++++++++++++- src/sql/drivers/mysql/qsql_mysql.cpp | 3 +++ src/sql/drivers/oci/qsql_oci.cpp | 2 +- src/sql/drivers/sqlite/qsql_sqlite.cpp | 2 +- src/sql/drivers/sqlite2/qsql_sqlite2.cpp | 2 +- src/sql/kernel/qsqlcachedresult.cpp | 13 ++++++++++ src/sql/kernel/qsqlcachedresult_p.h | 1 + src/sql/kernel/qsqlresult.cpp | 2 +- tests/auto/qsqldatabase/tst_databases.h | 8 +++---- tests/auto/qsqldatabase/tst_qsqldatabase.cpp | 22 ++++++++++++++--- 10 files changed, 79 insertions(+), 12 deletions(-) diff --git a/src/sql/drivers/ibase/qsql_ibase.cpp b/src/sql/drivers/ibase/qsql_ibase.cpp index 0698f26..259a247 100644 --- a/src/sql/drivers/ibase/qsql_ibase.cpp +++ b/src/sql/drivers/ibase/qsql_ibase.cpp @@ -1103,6 +1103,19 @@ bool QIBaseResult::gotoNext(QSqlCachedResult::ValueCache& row, int rowIdx) // null value QVariant v; v.convert(qIBaseTypeName2(d->sqlda->sqlvar[i].sqltype, d->sqlda->sqlvar[i].sqlscale < 0)); + if(v.type() == QVariant::Double) { + switch(numericalPrecisionPolicy()) { + case QSql::LowPrecisionInt32: + v.convert(QVariant::Int); + break; + case QSql::LowPrecisionInt64: + v.convert(QVariant::LongLong); + break; + case QSql::HighPrecision: + v.convert(QVariant::String); + break; + } + } row[idx] = v; continue; } @@ -1168,6 +1181,27 @@ bool QIBaseResult::gotoNext(QSqlCachedResult::ValueCache& row, int rowIdx) row[idx] = QVariant(); break; } + if (d->sqlda->sqlvar[i].sqlscale < 0) { + QVariant v = row[idx]; + switch(numericalPrecisionPolicy()) { + case QSql::LowPrecisionInt32: + if(v.convert(QVariant::Int)) + row[idx]=v; + break; + case QSql::LowPrecisionInt64: + if(v.convert(QVariant::LongLong)) + row[idx]=v; + break; + case QSql::LowPrecisionDouble: + if(v.convert(QVariant::Double)) + row[idx]=v; + break; + case QSql::HighPrecision: + if(v.convert(QVariant::String)) + row[idx]=v; + break; + } + } } return true; @@ -1339,7 +1373,6 @@ bool QIBaseDriver::hasFeature(DriverFeature f) const case LastInsertId: case BatchOperations: case SimpleLocking: - case LowPrecisionNumbers: case FinishQuery: case MultipleResultSets: return false; @@ -1349,6 +1382,7 @@ bool QIBaseDriver::hasFeature(DriverFeature f) const case Unicode: case BLOB: case EventNotifications: + case LowPrecisionNumbers: return true; } return false; diff --git a/src/sql/drivers/mysql/qsql_mysql.cpp b/src/sql/drivers/mysql/qsql_mysql.cpp index 46726a5..bfd65fc 100644 --- a/src/sql/drivers/mysql/qsql_mysql.cpp +++ b/src/sql/drivers/mysql/qsql_mysql.cpp @@ -254,6 +254,9 @@ static QVariant::Type qDecodeMYSQLType(int mysqltype, uint flags) case FIELD_TYPE_FLOAT : case FIELD_TYPE_DOUBLE : case FIELD_TYPE_DECIMAL : +#if defined(FIELD_TYPE_NEWDECIMAL) + case FIELD_TYPE_NEWDECIMAL: +#endif type = QVariant::Double; break; case FIELD_TYPE_DATE : diff --git a/src/sql/drivers/oci/qsql_oci.cpp b/src/sql/drivers/oci/qsql_oci.cpp index ca4b286..d5fb10f 100644 --- a/src/sql/drivers/oci/qsql_oci.cpp +++ b/src/sql/drivers/oci/qsql_oci.cpp @@ -1899,7 +1899,7 @@ void QOCIResult::virtual_hook(int id, void *data) QOCICols::execBatch(d, boundValues(), *reinterpret_cast(data)); break; default: - QSqlResult::virtual_hook(id, data); + QSqlCachedResult::virtual_hook(id, data); } } diff --git a/src/sql/drivers/sqlite/qsql_sqlite.cpp b/src/sql/drivers/sqlite/qsql_sqlite.cpp index 1a05873..05f5ab3 100644 --- a/src/sql/drivers/sqlite/qsql_sqlite.cpp +++ b/src/sql/drivers/sqlite/qsql_sqlite.cpp @@ -289,7 +289,7 @@ void QSQLiteResult::virtual_hook(int id, void *data) sqlite3_reset(d->stmt); break; default: - QSqlResult::virtual_hook(id, data); + QSqlCachedResult::virtual_hook(id, data); } } diff --git a/src/sql/drivers/sqlite2/qsql_sqlite2.cpp b/src/sql/drivers/sqlite2/qsql_sqlite2.cpp index 790c1ef..1989c45 100644 --- a/src/sql/drivers/sqlite2/qsql_sqlite2.cpp +++ b/src/sql/drivers/sqlite2/qsql_sqlite2.cpp @@ -260,7 +260,7 @@ void QSQLite2Result::virtual_hook(int id, void *data) d->finalize(); break; default: - QSqlResult::virtual_hook(id, data); + QSqlCachedResult::virtual_hook(id, data); } } diff --git a/src/sql/kernel/qsqlcachedresult.cpp b/src/sql/kernel/qsqlcachedresult.cpp index 3cace06..ca51dc0 100644 --- a/src/sql/kernel/qsqlcachedresult.cpp +++ b/src/sql/kernel/qsqlcachedresult.cpp @@ -294,4 +294,17 @@ QSqlCachedResult::ValueCache &QSqlCachedResult::cache() return d->cache; } +void QSqlCachedResult::virtual_hook(int id, void *data) +{ + switch (id) { + case QSqlResult::DetachFromResultSet: + case QSqlResult::SetNumericalPrecision: + cleanup(); + break; + default: + QSqlResult::virtual_hook(id, data); + } +} + + QT_END_NAMESPACE diff --git a/src/sql/kernel/qsqlcachedresult_p.h b/src/sql/kernel/qsqlcachedresult_p.h index d19435c..a384b2e 100644 --- a/src/sql/kernel/qsqlcachedresult_p.h +++ b/src/sql/kernel/qsqlcachedresult_p.h @@ -89,6 +89,7 @@ protected: int colCount() const; ValueCache &cache(); + void virtual_hook(int id, void *data); private: bool cacheNext(); QSqlCachedResultPrivate *d; diff --git a/src/sql/kernel/qsqlresult.cpp b/src/sql/kernel/qsqlresult.cpp index 1c1595d..93c9d9f 100644 --- a/src/sql/kernel/qsqlresult.cpp +++ b/src/sql/kernel/qsqlresult.cpp @@ -905,7 +905,6 @@ QVariant QSqlResult::lastInsertId() const */ void QSqlResult::virtual_hook(int, void *) { - Q_ASSERT(false); } /*! \internal @@ -971,6 +970,7 @@ void QSqlResult::detachFromResultSet() void QSqlResult::setNumericalPrecisionPolicy(QSql::NumericalPrecisionPolicy policy) { d->precisionPolicy = policy; + virtual_hook(SetNumericalPrecision, &policy); } /*! \internal diff --git a/tests/auto/qsqldatabase/tst_databases.h b/tests/auto/qsqldatabase/tst_databases.h index 77d1d5b..b193303 100644 --- a/tests/auto/qsqldatabase/tst_databases.h +++ b/tests/auto/qsqldatabase/tst_databases.h @@ -249,10 +249,10 @@ public: // addDb( "QODBC3", "DRIVER={SQL Native Client};SERVER=silence.nokia.troll.no\\SQLEXPRESS", "troll", "trond", "" ); // addDb( "QODBC", "DRIVER={MySQL ODBC 3.51 Driver};SERVER=mysql5-nokia.trolltech.com.au;DATABASE=testdb", "testuser", "Ee4Gabf6_", "" ); -// addDb( "QODBC", "DRIVER={FreeTDS};SERVER=horsehead.nokia.troll.no;DATABASE=testdb;PORT=4101;UID=troll;PWD=trondk", "troll", "trondk", "" ); -// addDb( "QODBC", "DRIVER={FreeTDS};SERVER=silence.nokia.troll.no;DATABASE=testdb;PORT=2392;UID=troll;PWD=trond", "troll", "trond", "" ); -// addDb( "QODBC", "DRIVER={FreeTDS};SERVER=bq-winserv2003-x86-01.apac.nokia.com;DATABASE=testdb;PORT=1433;UID=testuser;PWD=Ee4Gabf6_", "testuser", "Ee4Gabf6_", "" ); -// addDb( "QODBC", "DRIVER={FreeTDS};SERVER=bq-winserv2008-x86-01.apac.nokia.com;DATABASE=testdb;PORT=1433;UID=testuser;PWD=Ee4Gabf6_", "testuser", "Ee4Gabf6_", "" ); +// addDb( "QODBC", "DRIVER={FreeTDS};SERVER=horsehead.nokia.troll.no;DATABASE=testdb;PORT=4101;UID=troll;PWD=trondk;TDS_Version=8.0", "troll", "trondk", "" ); +// addDb( "QODBC", "DRIVER={FreeTDS};SERVER=silence.nokia.troll.no;DATABASE=testdb;PORT=2392;UID=troll;PWD=trond;TDS_Version=8.0", "troll", "trond", "" ); +// addDb( "QODBC", "DRIVER={FreeTDS};SERVER=bq-winserv2003-x86-01.apac.nokia.com;DATABASE=testdb;PORT=1433;UID=testuser;PWD=Ee4Gabf6_;TDS_Version=8.0", "testuser", "Ee4Gabf6_", "" ); +// addDb( "QODBC", "DRIVER={FreeTDS};SERVER=bq-winserv2008-x86-01.apac.nokia.com;DATABASE=testdb;PORT=1433;UID=testuser;PWD=Ee4Gabf6_;TDS_Version=8.0", "testuser", "Ee4Gabf6_", "" ); // addDb( "QTDS7", "testdb", "testuser", "Ee4Gabf6_", "bq-winserv2003" ); // addDb( "QTDS7", "testdb", "testuser", "Ee4Gabf6_", "bq-winserv2008" ); } diff --git a/tests/auto/qsqldatabase/tst_qsqldatabase.cpp b/tests/auto/qsqldatabase/tst_qsqldatabase.cpp index 13ec263..cce4602 100644 --- a/tests/auto/qsqldatabase/tst_qsqldatabase.cpp +++ b/tests/auto/qsqldatabase/tst_qsqldatabase.cpp @@ -1625,7 +1625,7 @@ void tst_QSqlDatabase::precisionPolicy() q.bindValue(1, 123); QVERIFY_SQL(q, exec()); q.bindValue(0, 2); - q.bindValue(1, QString("1850000000000.0001")); + q.bindValue(1, 1850000000000.0001); QVERIFY_SQL(q, exec()); // These are expected to pass @@ -1633,29 +1633,39 @@ void tst_QSqlDatabase::precisionPolicy() 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)); 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("1850000000000.0001").toDouble()); @@ -1663,21 +1673,27 @@ void tst_QSqlDatabase::precisionPolicy() 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()); + 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); QSql::NumericalPrecisionPolicy oldPrecision= db.numericalPrecisionPolicy(); - db.setNumericalPrecisionPolicy(QSql::LowPrecisionDouble); + 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()); - QCOMPARE(q2.value(0).type(), QVariant::Double); + 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); } -- cgit v0.12