summaryrefslogtreecommitdiffstats
path: root/tests/auto/sql/kernel/qsqlquery/tst_qsqlquery.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'tests/auto/sql/kernel/qsqlquery/tst_qsqlquery.cpp')
-rw-r--r--tests/auto/sql/kernel/qsqlquery/tst_qsqlquery.cpp204
1 files changed, 177 insertions, 27 deletions
diff --git a/tests/auto/sql/kernel/qsqlquery/tst_qsqlquery.cpp b/tests/auto/sql/kernel/qsqlquery/tst_qsqlquery.cpp
index 7ab17802b9..89033c30e0 100644
--- a/tests/auto/sql/kernel/qsqlquery/tst_qsqlquery.cpp
+++ b/tests/auto/sql/kernel/qsqlquery/tst_qsqlquery.cpp
@@ -1,5 +1,5 @@
// Copyright (C) 2022 The Qt Company Ltd.
-// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
#include <QTest>
#include <QtSql/QtSql>
@@ -77,6 +77,9 @@ private slots:
void psql_forwardOnlyQueryResultsLost_data() { generic_data("QPSQL"); }
void psql_forwardOnlyQueryResultsLost();
+ void positionalBindingEnabled_data() { generic_data(); }
+ void positionalBindingEnabled();
+
// Bug-specific tests:
void oci_nullBlob_data() { generic_data("QOCI"); }
void oci_nullBlob();
@@ -253,6 +256,12 @@ private slots:
void ibaseDateTimeWithTZ();
void ibaseTimeStampTzArray_data() { generic_data("QIBASE"); }
void ibaseTimeStampTzArray();
+ void ibaseInt128_data() { generic_data("QIBASE"); }
+ void ibaseInt128();
+
+
+ void psqlJsonOperator_data() { generic_data("QPSQL"); }
+ void psqlJsonOperator();
// Double addDatabase() with same name leaves system in a state that breaks
// invalidQuery() if run later; so put this one last !
@@ -1869,52 +1878,54 @@ void tst_QSqlQuery::oci_rawField()
// Test whether we can fetch values with more than DOUBLE precision
// note that SQLite highest precision is that of a double, although
// you can define field with higher precision:
+// Test whether we can fetch values with more than DOUBLE precision
+// note that SQLite highest precision is that of a double, although
+// you can define field with higher precision:
void tst_QSqlQuery::precision()
{
QFETCH(QString, dbName);
QSqlDatabase db = QSqlDatabase::database(dbName);
CHECK_DATABASE(db);
const QSqlDriver::DbmsType dbType = tst_Databases::getDatabaseType(db);
- if (dbType == QSqlDriver::Interbase)
- QSKIP("DB unable to store high precision");
const auto tidier = qScopeGuard([db, oldPrecision = db.driver()->numericalPrecisionPolicy()]() {
db.driver()->setNumericalPrecisionPolicy(oldPrecision);
});
+ int digits = 21;
+ int decimals = 20;
+ std::array<QLatin1String, 2> precStrings = { "1.2345678901234567891"_L1,
+ "-1.2345678901234567891"_L1 };
+ if (dbType == QSqlDriver::SQLite) {
+ // SQLite 3.45 does not return more, even when speicfied
+ digits = 17;
+ decimals = 16;
+ precStrings = { "1.2345678901234567"_L1, "-1.2345678901234567"_L1 };
+ } else if (dbType == QSqlDriver::Sybase)
+ decimals = 18;
db.driver()->setNumericalPrecisionPolicy(QSql::HighPrecision);
TableScope ts(db, "qtest_precision", __FILE__);
- static const QLatin1String precStr("1.2345678901234567891");
-
- {
- // need a new scope for SQLITE
- QSqlQuery q(db);
- QVERIFY_SQL(q, exec(QLatin1String(tst_Databases::isMSAccess(db)
- ? "CREATE TABLE %1 (col1 number)"
- : "CREATE TABLE %1 (col1 numeric(21, 20))")
- .arg(ts.tableName())));
-
- QVERIFY_SQL(q, exec(QLatin1String("INSERT INTO %1 (col1) VALUES (%2)")
- .arg(ts.tableName(), precStr)));
+ QSqlQuery q(db);
+ QString stmt = "CREATE TABLE %1 (col1 numeric("_L1 + QString::number(digits) + ", "_L1 +
+ QString::number(decimals) + "))"_L1;
+ if (tst_Databases::isMSAccess(db))
+ stmt = "CREATE TABLE %1 (col1 number)"_L1;
+ QVERIFY_SQL(q, exec(stmt.arg(ts.tableName())));
+ for (const auto &precStr : precStrings) {
+ QVERIFY_SQL(q, exec("DELETE FROM %1"_L1.arg(ts.tableName())));
+ QVERIFY_SQL(q, exec("INSERT INTO %1 (col1) VALUES (%2)"_L1.arg(ts.tableName(), precStr)));
QVERIFY_SQL(q, exec("SELECT * FROM " + ts.tableName()));
QVERIFY(q.next());
const QString val = q.value(0).toString();
if (!val.startsWith(precStr)) {
int i = 0;
- while (i < val.size() && precStr[i] != 0 && precStr[i] == val[i].toLatin1())
+ while (i < val.size() && precStr[i] != 0 && precStr[i] == val[i])
++i;
-
- // TDS has crappy precisions by default
- if (dbType == QSqlDriver::Sybase) {
- if (i < 18)
- qWarning("TDS didn't return the right precision");
- } else {
- qWarning() << tst_Databases::dbToString(db) << "didn't return the right precision ("
- << i << "out of 21)," << val;
- }
+ qWarning() << tst_Databases::dbToString(db) << "didn't return the right precision ("
+ << i << "out of " << digits << ")," << val;
}
- } // SQLITE scope
+ }
}
void tst_QSqlQuery::nullResult()
@@ -4454,7 +4465,7 @@ void tst_QSqlQuery::aggregateFunctionTypes()
.arg(tableName)));
QVERIFY_SQL(q, exec("SELECT MAX(txt) FROM " + tableName));
- QVERIFY(q.next());
+ QVERIFY_SQL(q, next());
if (dbType == QSqlDriver::SQLite)
QCOMPARE(q.record().field(0).metaType().id(), QMetaType::UnknownType);
else
@@ -4469,6 +4480,19 @@ void tst_QSqlQuery::aggregateFunctionTypes()
QVERIFY(q.next());
QCOMPARE(q.value(0).toString(), QLatin1String("upper"));
QCOMPARE(q.record().field(0).metaType().id(), QMetaType::QString);
+
+ QVERIFY_SQL(q, exec(QLatin1String("DELETE FROM %1").arg(tableName)));
+ QVERIFY_SQL(q, exec(QString::fromUtf8("INSERT INTO %1 (id, txt) VALUES (1, 'löW€RÄ')")
+ .arg(tableName)));
+ QVERIFY_SQL(q, exec("SELECT LOWER(txt) FROM " + tableName));
+ QVERIFY(q.next());
+ QCOMPARE(q.value(0).toString(), QString::fromUtf8("löw€rä"));
+ QCOMPARE(q.record().field(0).metaType().id(), QMetaType::QString);
+
+ QVERIFY_SQL(q, exec("SELECT UPPER(txt) FROM " + tableName));
+ QVERIFY(q.next());
+ QCOMPARE(q.value(0).toString(), QString::fromUtf8("LÖW€RÄ"));
+ QCOMPARE(q.record().field(0).metaType().id(), QMetaType::QString);
}
}
@@ -5015,6 +5039,54 @@ void tst_QSqlQuery::ibaseTimeStampTzArray()
#endif // QT_CONFIG(timezone)
}
+void tst_QSqlQuery::ibaseInt128()
+{
+ QFETCH(QString, dbName);
+ QSqlDatabase db = QSqlDatabase::database(dbName);
+ CHECK_DATABASE(db);
+
+ TableScope ts(db, "int128test", __FILE__);
+ db.setNumericalPrecisionPolicy(QSql::HighPrecision);
+ QSqlQuery q(db);
+ if (!q.exec("CREATE TABLE " + ts.tableName() + " (id INT PRIMARY KEY, price NUMERIC(20, 4))"))
+ QSKIP("Need at least Firebird 4 for this test - skipping");
+
+ QVERIFY_SQL(q, exec("INSERT INTO " + ts.tableName() + "(id,price) values(1,40001.1234)"));
+ QVERIFY_SQL(q, prepare("INSERT INTO " + ts.tableName() + "(id,price) values(2,:amount)"));
+ q.bindValue(":amount", 12345.67890);
+ QVERIFY_SQL(q, exec());
+ {
+ QSqlQuery q2(db);
+ q2.setNumericalPrecisionPolicy(QSql::LowPrecisionDouble);
+ QVERIFY_SQL(q2, exec("SELECT price FROM " + ts.tableName() + " ORDER BY id"));
+ QVERIFY_SQL(q2, next());
+ QCOMPARE(q2.value(0).metaType().id(), QMetaType::Double);
+ QCOMPARE(q2.value(0).toDouble(), 40001.1234);
+ QVERIFY_SQL(q2, next());
+ QCOMPARE(q2.value("price").metaType().id(), QMetaType::Double);
+ QCOMPARE(q2.value("price").toDouble(), 12345.6789);
+ QVERIFY_SQL(q2, exec("SELECT sum(price) FROM " + ts.tableName()));
+ QVERIFY_SQL(q2, next());
+ QCOMPARE(q2.value(0).metaType().id(), QMetaType::Double);
+ QCOMPARE(q2.value(0).toDouble(), 52346.8023);
+ }
+ {
+ QSqlQuery q2(db);
+ q2.setNumericalPrecisionPolicy(QSql::HighPrecision);
+ QVERIFY_SQL(q2, exec("SELECT price FROM " + ts.tableName() + " ORDER BY id"));
+ QVERIFY_SQL(q2, next());
+ QCOMPARE(q2.value(0).metaType().id(), QMetaType::QString);
+ QCOMPARE(q2.value(0).toString(), "40001.1234");
+ QVERIFY_SQL(q2, next());
+ QCOMPARE(q2.value("price").metaType().id(), QMetaType::QString);
+ QCOMPARE(q2.value("price").toString(), "12345.6789");
+ QVERIFY_SQL(q2, exec("SELECT sum(price) FROM " + ts.tableName()));
+ QVERIFY_SQL(q2, next());
+ QCOMPARE(q2.value(0).metaType().id(), QMetaType::QString);
+ QCOMPARE(q2.value(0).toString(), "52346.8023");
+ }
+}
+
void tst_QSqlQuery::ibase_executeBlock()
{
QFETCH(QString, dbName);
@@ -5035,5 +5107,83 @@ void tst_QSqlQuery::ibase_executeBlock()
QCOMPARE(qry.value(0).toInt(), 4);
}
+void tst_QSqlQuery::positionalBindingEnabled()
+{
+ QFETCH(QString, dbName);
+ QSqlDatabase db = QSqlDatabase::database(dbName);
+ QSqlDriver::DbmsType dbType = tst_Databases::getDatabaseType(db);
+ CHECK_DATABASE(db);
+ TableScope ts(db, "positionalBinding", __FILE__);
+ const QString &tableName = ts.tableName();
+
+ QSqlQuery qry(db);
+ QVERIFY_SQL(qry, exec("CREATE TABLE " + tableName + " (integer_col integer)"));
+ QVERIFY_SQL(qry, exec("INSERT INTO " + tableName + "(integer_col) VALUES(42)"));
+
+ qry.setPositionalBindingEnabled(true);
+ QCOMPARE(qry.isPositionalBindingEnabled(), true);
+ QVERIFY_SQL(qry, prepare("SELECT integer_col FROM " + tableName + " WHERE integer_col = :integer_val"));
+ qry.bindValue(":integer_val", 42);
+ QVERIFY_SQL(qry, exec());
+ QVERIFY_SQL(qry, next());
+ QCOMPARE(qry.value(0).toInt(), 42);
+ QVERIFY_SQL(qry, prepare("SELECT integer_col FROM " + tableName + " WHERE integer_col = ?"));
+ qry.bindValue(0, 42);
+ QVERIFY_SQL(qry, exec());
+ QVERIFY_SQL(qry, next());
+ QCOMPARE(qry.value(0).toInt(), 42);
+
+ qry.setPositionalBindingEnabled(false);
+ QCOMPARE(qry.isPositionalBindingEnabled(), false);
+ QVERIFY_SQL(qry, prepare("SELECT integer_col FROM " + tableName + " WHERE integer_col = :integer_val"));
+ qry.bindValue(":integer_val", 42);
+ QVERIFY_SQL(qry, exec());
+ QVERIFY_SQL(qry, next());
+ QCOMPARE(qry.value(0).toInt(), 42);
+ // the next query will only work when the underlying database support question mark notation natively
+ if (dbType == QSqlDriver::PostgreSQL) {
+ QVERIFY(!qry.prepare("SELECT integer_col FROM " + tableName + " WHERE integer_col = ?"));
+ qry.bindValue(0, 42);
+ QVERIFY(!qry.exec());
+ QVERIFY(!qry.next());
+ } else {
+ QVERIFY_SQL(qry, prepare("SELECT integer_col FROM " + tableName + " WHERE integer_col = ?"));
+ qry.bindValue(0, 42);
+ QVERIFY_SQL(qry, exec());
+ QVERIFY_SQL(qry, next());
+ QCOMPARE(qry.value(0).toInt(), 42);
+ }
+}
+
+void tst_QSqlQuery::psqlJsonOperator()
+{
+ QFETCH(QString, dbName);
+ QSqlDatabase db = QSqlDatabase::database(dbName);
+ CHECK_DATABASE(db);
+ TableScope ts(db, "qTableName", __FILE__);
+ const QString &tableName = ts.tableName();
+
+ QSqlQuery qry(db);
+ qry.setPositionalBindingEnabled(false); // don't allow / handle '?' as placeholder
+ QVERIFY_SQL(qry, exec("CREATE TABLE " + tableName + " (integer_col integer, json_col jsonb)"));
+ QVERIFY_SQL(qry, exec("INSERT INTO " + tableName + "(integer_col, json_col) VALUES(42, '{\"a\": [1, 2]}')"));
+ QVERIFY_SQL(qry, exec("INSERT INTO " + tableName + "(integer_col, json_col) VALUES(43, '{\"b\": [3, 4]}')"));
+
+ QVERIFY_SQL(qry, prepare("SELECT integer_col, json_col FROM " + tableName + " WHERE json_col @? '$.a[*] ? (@ == 1)' and integer_col = :int"));
+ qry.bindValue(":int", 42);
+ QVERIFY_SQL(qry, exec());
+ QVERIFY_SQL(qry, next());
+ QCOMPARE(qry.value(0).toInt(), 42);
+ QCOMPARE(qry.value(1).toByteArray(), "{\"a\": [1, 2]}");
+
+ QVERIFY_SQL(qry, prepare("SELECT integer_col, json_col FROM " + tableName + " WHERE json_col ? 'b' and integer_col = :int"));
+ qry.bindValue(":int", 43);
+ QVERIFY_SQL(qry, exec());
+ QVERIFY_SQL(qry, next());
+ QCOMPARE(qry.value(0).toInt(), 43);
+ QCOMPARE(qry.value(1).toByteArray(), "{\"b\": [3, 4]}");
+}
+
+
QTEST_MAIN(tst_QSqlQuery)
#include "tst_qsqlquery.moc"