summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--src/plugins/sqldrivers/psql/qsql_psql.cpp51
-rw-r--r--tests/auto/sql/kernel/qsqldatabase/tst_qsqldatabase.cpp42
2 files changed, 55 insertions, 38 deletions
diff --git a/src/plugins/sqldrivers/psql/qsql_psql.cpp b/src/plugins/sqldrivers/psql/qsql_psql.cpp
index f67c78b2bb..b4eb69e6cf 100644
--- a/src/plugins/sqldrivers/psql/qsql_psql.cpp
+++ b/src/plugins/sqldrivers/psql/qsql_psql.cpp
@@ -57,29 +57,7 @@
#include <libpq-fe.h>
#include <pg_config.h>
-#include <stdlib.h>
-#include <math.h>
-// below code taken from an example at http://www.gnu.org/software/hello/manual/autoconf/Function-Portability.html
-#ifndef isnan
- # define isnan(x) \
- (sizeof (x) == sizeof (long double) ? isnan_ld (x) \
- : sizeof (x) == sizeof (double) ? isnan_d (x) \
- : isnan_f (x))
- static inline int isnan_f (float x) { return x != x; }
- static inline int isnan_d (double x) { return x != x; }
- static inline int isnan_ld (long double x) { return x != x; }
-#endif
-
-#ifndef isinf
- # define isinf(x) \
- (sizeof (x) == sizeof (long double) ? isinf_ld (x) \
- : sizeof (x) == sizeof (double) ? isinf_d (x) \
- : isinf_f (x))
- static inline int isinf_f (float x) { return isnan (x - x); }
- static inline int isinf_d (double x) { return isnan (x - x); }
- static inline int isinf_ld (long double x) { return isnan (x - x); }
-#endif
-
+#include <cmath>
// workaround for postgres defining their OIDs in a private header file
#define QBOOLOID 16
@@ -135,7 +113,7 @@ static const StatementId InvalidStatementId = 0;
class QPSQLResultPrivate;
-class QPSQLResult: public QSqlResult
+class QPSQLResult final : public QSqlResult
{
Q_DECLARE_PRIVATE(QPSQLResult)
@@ -164,7 +142,7 @@ protected:
bool exec() override;
};
-class QPSQLDriverPrivate : public QSqlDriverPrivate
+class QPSQLDriverPrivate final : public QSqlDriverPrivate
{
Q_DECLARE_PUBLIC(QPSQLDriver)
public:
@@ -671,7 +649,7 @@ QVariant QPSQLResult::data(int i)
return QString::fromLatin1(val).toULongLong();
case QVariant::Int:
return atoi(val);
- case QVariant::Double:
+ case QVariant::Double: {
if (ptype == QNUMERICOID) {
if (numericalPrecisionPolicy() != QSql::HighPrecision) {
QVariant retval;
@@ -689,7 +667,12 @@ QVariant QPSQLResult::data(int i)
}
return QString::fromLatin1(val);
}
+ if (qstricmp(val, "Infinity") == 0)
+ return qInf();
+ if (qstricmp(val, "-Infinity") == 0)
+ return -qInf();
return QString::fromLatin1(val).toDouble();
+ }
case QVariant::Date:
if (val[0] == '\0') {
return QVariant(QDate());
@@ -1497,18 +1480,10 @@ QSqlRecord QPSQLDriver::record(const QString& tablename) const
template <class FloatType>
inline void assignSpecialPsqlFloatValue(FloatType val, QString *target)
{
- if (isnan(val)) {
- *target = QLatin1String("'NaN'");
- } else {
- switch (isinf(val)) {
- case 1:
- *target = QLatin1String("'Infinity'");
- break;
- case -1:
- *target = QLatin1String("'-Infinity'");
- break;
- }
- }
+ if (qIsNaN(val))
+ *target = QStringLiteral("'NaN'");
+ else if (qIsInf(val))
+ *target = (val < 0) ? QStringLiteral("'-Infinity'") : QStringLiteral("'Infinity'");
}
QString QPSQLDriver::formatValue(const QSqlField &field, bool trimStrings) const
diff --git a/tests/auto/sql/kernel/qsqldatabase/tst_qsqldatabase.cpp b/tests/auto/sql/kernel/qsqldatabase/tst_qsqldatabase.cpp
index 427bc092a5..89978319a0 100644
--- a/tests/auto/sql/kernel/qsqldatabase/tst_qsqldatabase.cpp
+++ b/tests/auto/sql/kernel/qsqldatabase/tst_qsqldatabase.cpp
@@ -126,6 +126,8 @@ private slots:
void formatValueTrimStrings();
void precisionPolicy_data() { generic_data(); }
void precisionPolicy();
+ void infinityAndNan_data() { generic_data(); }
+ void infinityAndNan();
void multipleThreads_data() { generic_data(); }
void multipleThreads();
@@ -1467,6 +1469,46 @@ void tst_QSqlDatabase::precisionPolicy()
db.setNumericalPrecisionPolicy(oldPrecision);
}
+void tst_QSqlDatabase::infinityAndNan()
+{
+ QFETCH(QString, dbName);
+ QSqlDatabase db = QSqlDatabase::database(dbName);
+ CHECK_DATABASE(db);
+
+ if (tst_Databases::getDatabaseType(db) != QSqlDriver::PostgreSQL)
+ QSKIP("checking for infinity/nan currently only works for PostgreSQL");
+
+ QSqlQuery q(db);
+ const QString tableName(qTableName("infititytest", __FILE__, db));
+ tst_Databases::safeDropTables(db, {tableName});
+ QVERIFY_SQL(q, exec(QString("CREATE TABLE %1 (id smallint, val double precision)").arg(tableName)));
+
+ QVERIFY_SQL(q, prepare(QString("INSERT INTO %1 VALUES (?, ?)").arg(tableName)));
+
+ q.bindValue(0, 1);
+ q.bindValue(1, qQNaN());
+ QVERIFY_SQL(q, exec());
+ q.bindValue(0, 2);
+ q.bindValue(1, qInf());
+ QVERIFY_SQL(q, exec());
+ q.bindValue(0, 3);
+ q.bindValue(1, -qInf());
+ QVERIFY_SQL(q, exec());
+
+ QVERIFY_SQL(q, exec(QString("SELECT val FROM %1 ORDER BY id").arg(tableName)));
+
+ QVERIFY_SQL(q, next());
+ QVERIFY(qIsNaN(q.value(0).toDouble()));
+
+ QVERIFY_SQL(q, next());
+ QVERIFY(qIsInf(q.value(0).toDouble()));
+ QVERIFY(q.value(0).toDouble() > 0);
+
+ QVERIFY_SQL(q, next());
+ QVERIFY(qIsInf(q.value(0).toDouble()));
+ QVERIFY(q.value(0).toDouble() < 0);
+}
+
// This test needs a ODBC data source containing MYSQL in it's name
void tst_QSqlDatabase::mysqlOdbc_unsignedIntegers()
{