diff options
author | Christian Ehrlicher <ch.ehrlicher@gmx.de> | 2021-01-01 20:07:29 +0100 |
---|---|---|
committer | Christian Ehrlicher <ch.ehrlicher@gmx.de> | 2021-01-10 13:02:14 +0100 |
commit | b211148e4b4167483e1a78a45ae8fef97e5a4f2d (patch) | |
tree | 884d9e657a8a5e5ae2cbde9b3f781bcf3855968d | |
parent | 161e8f4d5dbaa568975d61d770144484e14a62e0 (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.cpp | 53 | ||||
-rw-r--r-- | tests/auto/sql/kernel/qsqldatabase/tst_qsqldatabase.cpp | 37 |
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); |