summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorChristian Ehrlicher <ch.ehrlicher@gmx.de>2021-01-01 20:07:29 +0100
committerChristian Ehrlicher <ch.ehrlicher@gmx.de>2021-01-10 13:02:14 +0100
commitb211148e4b4167483e1a78a45ae8fef97e5a4f2d (patch)
tree884d9e657a8a5e5ae2cbde9b3f781bcf3855968d
parent161e8f4d5dbaa568975d61d770144484e14a62e0 (diff)
Sql ODBC driver: add direct support for float and short datatype
This patch adds native support for SQL_REAL (float) and SQL_SMALLINT (short). Previously those datatypes were mapped to double and integer. [ChangeLog][QtSql] The ODBC driver now properly maps QMetaType::Float to real sql datatype and QMetaType::Short to smallint Fixes: QTBUG-8963 Fixes: QTBUG-57279 Change-Id: Ifec4c609734dbe6165c1ebdadb461c2aae47ba78 Reviewed-by: Andy Shaw <andy.shaw@qt.io>
-rw-r--r--src/plugins/sqldrivers/odbc/qsql_odbc.cpp53
-rw-r--r--tests/auto/sql/kernel/qsqldatabase/tst_qsqldatabase.cpp37
2 files changed, 86 insertions, 4 deletions
diff --git a/src/plugins/sqldrivers/odbc/qsql_odbc.cpp b/src/plugins/sqldrivers/odbc/qsql_odbc.cpp
index dd6eaab9cf..026a970cf0 100644
--- a/src/plugins/sqldrivers/odbc/qsql_odbc.cpp
+++ b/src/plugins/sqldrivers/odbc/qsql_odbc.cpp
@@ -347,12 +347,16 @@ static QMetaType qDecodeODBCType(SQLSMALLINT sqltype, bool isSigned = true)
switch (sqltype) {
case SQL_DECIMAL:
case SQL_NUMERIC:
- case SQL_REAL:
- case SQL_FLOAT:
- case SQL_DOUBLE:
+ case SQL_FLOAT: // 24 or 53 bits precision
+ case SQL_DOUBLE:// 53 bits
type = QMetaType::Double;
break;
+ case SQL_REAL: // 24 bits
+ type = QMetaType::Float;
+ break;
case SQL_SMALLINT:
+ type = isSigned ? QMetaType::Short : QMetaType::UShort;
+ break;
case SQL_INTEGER:
case SQL_BIT:
type = isSigned ? QMetaType::Int : QMetaType::UInt;
@@ -1220,9 +1224,11 @@ QVariant QODBCResult::data(int field)
d->fieldCache[i] = qGetBigIntData(d->hStmt, i, false);
break;
case QMetaType::Int:
+ case QMetaType::Short:
d->fieldCache[i] = qGetIntData(d->hStmt, i);
- break;
+ break;
case QMetaType::UInt:
+ case QMetaType::UShort:
d->fieldCache[i] = qGetIntData(d->hStmt, i, false);
break;
case QMetaType::QDate:
@@ -1513,6 +1519,30 @@ bool QODBCResult::exec()
0,
*ind == SQL_NULL_DATA ? ind : NULL);
break;
+ case QMetaType::Short:
+ r = SQLBindParameter(d->hStmt,
+ i + 1,
+ qParamType[bindValueType(i) & QSql::InOut],
+ SQL_C_SSHORT,
+ SQL_SMALLINT,
+ 0,
+ 0,
+ const_cast<void *>(val.constData()),
+ 0,
+ *ind == SQL_NULL_DATA ? ind : NULL);
+ break;
+ case QMetaType::UShort:
+ r = SQLBindParameter(d->hStmt,
+ i + 1,
+ qParamType[bindValueType(i) & QSql::InOut],
+ SQL_C_USHORT,
+ SQL_NUMERIC,
+ 15,
+ 0,
+ const_cast<void *>(val.constData()),
+ 0,
+ *ind == SQL_NULL_DATA ? ind : NULL);
+ break;
case QMetaType::Double:
r = SQLBindParameter(d->hStmt,
i + 1,
@@ -1525,6 +1555,18 @@ bool QODBCResult::exec()
0,
*ind == SQL_NULL_DATA ? ind : NULL);
break;
+ case QMetaType::Float:
+ r = SQLBindParameter(d->hStmt,
+ i + 1,
+ qParamType[bindValueType(i) & QSql::InOut],
+ SQL_C_FLOAT,
+ SQL_REAL,
+ 0,
+ 0,
+ const_cast<void *>(val.constData()),
+ 0,
+ *ind == SQL_NULL_DATA ? ind : NULL);
+ break;
case QMetaType::LongLong:
r = SQLBindParameter(d->hStmt,
i + 1,
@@ -1705,8 +1747,11 @@ bool QODBCResult::exec()
QTime(dt.hour, dt.minute, dt.second, dt.fraction / 1000000)));
break; }
case QMetaType::Bool:
+ case QMetaType::Short:
+ case QMetaType::UShort:
case QMetaType::Int:
case QMetaType::UInt:
+ case QMetaType::Float:
case QMetaType::Double:
case QMetaType::QByteArray:
case QMetaType::LongLong:
diff --git a/tests/auto/sql/kernel/qsqldatabase/tst_qsqldatabase.cpp b/tests/auto/sql/kernel/qsqldatabase/tst_qsqldatabase.cpp
index f5a158e3c1..0ef4caeafa 100644
--- a/tests/auto/sql/kernel/qsqldatabase/tst_qsqldatabase.cpp
+++ b/tests/auto/sql/kernel/qsqldatabase/tst_qsqldatabase.cpp
@@ -99,6 +99,8 @@ private slots:
void recordSQLServer();
void recordIBase_data() {generic_data("QIBASE"); }
void recordIBase();
+ void recordODBC_data() { generic_data("QODBC"); }
+ void recordODBC();
void eventNotificationIBase_data() { generic_data("QIBASE"); }
void eventNotificationIBase();
@@ -1016,6 +1018,41 @@ void tst_QSqlDatabase::recordIBase()
commonFieldTest(fieldDefs, db, fieldCount);
}
+void tst_QSqlDatabase::recordODBC()
+{
+ QFETCH(QString, dbName);
+ QSqlDatabase db = QSqlDatabase::database(dbName);
+ CHECK_DATABASE(db);
+
+ static QDateTime dt(QDate::currentDate(), QTime(1, 2, 3, 0));
+ static const FieldDef fieldDefs[] = {
+ FieldDef("decimal(10, 9)", QMetaType::Double, 1.123456789),
+ FieldDef("numeric(5, 2)", QMetaType::Double, 123.67),
+ FieldDef("float", QMetaType::Double, 1.123456789),
+ FieldDef("double precision", QMetaType::Double, 1.123456789),
+ FieldDef("real", QMetaType::Float, 1.12345),
+
+// FieldDef("tinyint", QMetaType::Char, 127), // not supported by psqlODBC
+ FieldDef("smallint", QMetaType::Short, 32767),
+ FieldDef("integer", QMetaType::Int, 2147483647),
+ FieldDef("bigint", QMetaType::LongLong, Q_INT64_C(9223372036854775807)),
+
+ FieldDef("date", QMetaType::QDate, QDate::currentDate()),
+ FieldDef("timestamp", QMetaType::QDateTime, dt, false),
+ FieldDef("time", QMetaType::QTime, dt.time()),
+ FieldDef("char(20)", QMetaType::QString, "Blah"),
+ FieldDef("varchar(20)", QMetaType::QString, "BlahBlah"),
+ FieldDef("text", QMetaType::QString, QString("blah6")),
+
+ FieldDef()
+ };
+
+ const int fieldCount = createFieldTable(fieldDefs, db);
+ QVERIFY(fieldCount > 0);
+
+ commonFieldTest(fieldDefs, db, fieldCount);
+}
+
void tst_QSqlDatabase::recordSQLite()
{
QFETCH(QString, dbName);