From 3370ab9119df09ca14f7d4641c555e60c1b3f478 Mon Sep 17 00:00:00 2001 From: Milian Wolff Date: Mon, 22 Aug 2016 14:32:05 +0200 Subject: Never return char variants when reading prepared MySQL statements This has undesired effects when converting a QSqlRecord to JSON. A char(0) e.g. has special semantics that are undesired when reading a Tinyint column. I don't think that returning bool for the special case of a Tinyint(1) is required. This also did not happen before, and is also not happening when not using a prepared statement. Instead, a plain int/uint QVariant is returned. This patch extends tst_QSqlQuery::integralTypesMysql to also cover reading and writing booleans from/to a MySQL table column of type Tinyint(1). Additionally, the reading is now also done with a prepared statement and we also check the raw variant value. The broken behavior fixed by this patch was introduced by me in commit 194403a3483b7317cc9511bc8b2ab307775643c5. Change-Id: I028a3abd83fdd2b42d98d478950d205e5b6bbeb5 Task-number: QTBUG-53397 Reviewed-by: Andy Shaw --- tests/auto/sql/kernel/qsqlquery/tst_qsqlquery.cpp | 45 ++++++++++++++++------- 1 file changed, 31 insertions(+), 14 deletions(-) (limited to 'tests') diff --git a/tests/auto/sql/kernel/qsqlquery/tst_qsqlquery.cpp b/tests/auto/sql/kernel/qsqlquery/tst_qsqlquery.cpp index f1c4333ccd..ba3cfb243a 100644 --- a/tests/auto/sql/kernel/qsqlquery/tst_qsqlquery.cpp +++ b/tests/auto/sql/kernel/qsqlquery/tst_qsqlquery.cpp @@ -4007,12 +4007,14 @@ void runIntegralTypesMysqlTest(QSqlDatabase &db, const QString &tableName, const QVERIFY_SQL(q, exec("DROP TABLE IF EXISTS " + tableName)); QVERIFY_SQL(q, exec("CREATE TABLE " + tableName + " (id " + type + ")")); - const int steps = 20; - const T increment = max / steps - min / steps; + const int steps = (max == min + 1) ? 2 : 20; + const T increment = (max == min + 1) ? 1 : (max / steps - min / steps); // insert some values QVector values; + QVector variantValues; values.resize(steps); + variantValues.resize(steps); T v = min; if (withPreparedStatement) { QVERIFY_SQL(q, prepare("INSERT INTO " + tableName + " (id) VALUES (?)")); @@ -4025,17 +4027,30 @@ void runIntegralTypesMysqlTest(QSqlDatabase &db, const QString &tableName, const QVERIFY_SQL(q, exec("INSERT INTO " + tableName + " (id) VALUES (" + QString::number(v) + ")")); } values[i] = v; + variantValues[i] = QVariant::fromValue(v); v += increment; } // ensure we can read them back properly - QVERIFY_SQL(q, exec("SELECT id FROM " + tableName)); + if (withPreparedStatement) { + QVERIFY_SQL(q, prepare("SELECT id FROM " + tableName)); + QVERIFY_SQL(q, exec()); + } else { + QVERIFY_SQL(q, exec("SELECT id FROM " + tableName)); + } QVector actualValues; + QVector actualVariantValues; actualValues.reserve(values.size()); while (q.next()) { - actualValues << q.value(0).value(); + QVariant value = q.value(0); + actualVariantValues << value; + actualValues << value.value(); + QVERIFY(actualVariantValues.last().userType() != qMetaTypeId()); + QVERIFY(actualVariantValues.last().userType() != qMetaTypeId()); + QVERIFY(actualVariantValues.last().userType() != qMetaTypeId()); } QCOMPARE(actualValues, values); + QCOMPARE(actualVariantValues, variantValues); } void tst_QSqlQuery::integralTypesMysql() @@ -4046,16 +4061,18 @@ void tst_QSqlQuery::integralTypesMysql() for (int i = 0; i < 2; ++i) { const bool withPreparedStatement = (i == 1); - runIntegralTypesMysqlTest(db, "tinyIntTest", "TINYINT", withPreparedStatement); - runIntegralTypesMysqlTest(db, "unsignedTinyIntTest", "TINYINT UNSIGNED", withPreparedStatement); - runIntegralTypesMysqlTest(db, "smallIntTest", "SMALLINT", withPreparedStatement); - runIntegralTypesMysqlTest(db, "unsignedSmallIntTest", "SMALLINT UNSIGNED", withPreparedStatement); - runIntegralTypesMysqlTest(db, "mediumIntTest", "MEDIUMINT", withPreparedStatement, -(1 << 23), (1 << 23) - 1); - runIntegralTypesMysqlTest(db, "unsignedMediumIntTest", "MEDIUMINT UNSIGNED", withPreparedStatement, 0, (1 << 24) - 1); - runIntegralTypesMysqlTest(db, "intTest", "INT", withPreparedStatement); - runIntegralTypesMysqlTest(db, "unsignedIntTest", "INT UNSIGNED", withPreparedStatement); - runIntegralTypesMysqlTest(db, "bigIntTest", "BIGINT", withPreparedStatement); - runIntegralTypesMysqlTest(db, "unsignedBigIntTest", "BIGINT UNSIGNED", withPreparedStatement); + runIntegralTypesMysqlTest(db, "tinyInt1Test", "TINYINT(1)", withPreparedStatement); + runIntegralTypesMysqlTest(db, "unsignedTinyInt1Test", "TINYINT(1) UNSIGNED", withPreparedStatement); + runIntegralTypesMysqlTest(db, "tinyIntTest", "TINYINT", withPreparedStatement); + runIntegralTypesMysqlTest(db, "unsignedTinyIntTest", "TINYINT UNSIGNED", withPreparedStatement); + runIntegralTypesMysqlTest(db, "smallIntTest", "SMALLINT", withPreparedStatement); + runIntegralTypesMysqlTest(db, "unsignedSmallIntTest", "SMALLINT UNSIGNED", withPreparedStatement); + runIntegralTypesMysqlTest(db, "mediumIntTest", "MEDIUMINT", withPreparedStatement, -(1 << 23), (1 << 23) - 1); + runIntegralTypesMysqlTest(db, "unsignedMediumIntTest", "MEDIUMINT UNSIGNED", withPreparedStatement, 0, (1 << 24) - 1); + runIntegralTypesMysqlTest(db, "intTest", "INT", withPreparedStatement); + runIntegralTypesMysqlTest(db, "unsignedIntTest", "INT UNSIGNED", withPreparedStatement); + runIntegralTypesMysqlTest(db, "bigIntTest", "BIGINT", withPreparedStatement); + runIntegralTypesMysqlTest(db, "unsignedBigIntTest", "BIGINT UNSIGNED", withPreparedStatement); } } -- cgit v1.2.3