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>
This commit is contained in:
Christian Ehrlicher 2021-01-01 20:07:29 +01:00
parent 161e8f4d5d
commit b211148e4b
2 changed files with 86 additions and 4 deletions

View File

@ -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:

View File

@ -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);