diff --git a/src/sql/drivers/psql/qsql_psql.cpp b/src/sql/drivers/psql/qsql_psql.cpp index c052e4c2e7..722595ad52 100644 --- a/src/sql/drivers/psql/qsql_psql.cpp +++ b/src/sql/drivers/psql/qsql_psql.cpp @@ -104,6 +104,11 @@ #define QXIDOID 28 #define QCIDOID 29 +#define QBITOID 1560 +#define QVARBITOID 1562 + +#define VARHDRSZ 4 + /* This is a compile time switch - if PQfreemem is declared, the compiler will use that one, otherwise it'll run in this template */ template @@ -533,17 +538,33 @@ QSqlRecord QPSQLResult::record() const f.setName(QString::fromUtf8(PQfname(d->result, i))); else f.setName(QString::fromLocal8Bit(PQfname(d->result, i))); - f.setType(qDecodePSQLType(PQftype(d->result, i))); + int ptype = PQftype(d->result, i); + f.setType(qDecodePSQLType(ptype)); int len = PQfsize(d->result, i); int precision = PQfmod(d->result, i); - // swap length and precision if length == -1 - if (len == -1 && precision > -1) { - len = precision - 4; + + switch (ptype) { + case QNUMERICOID: + if (precision != -1) { + len = (precision >> 16); + precision = ((precision - VARHDRSZ) & 0xffff); + } + break; + case QBITOID: + case QVARBITOID: + len = precision; precision = -1; + break; + default: + if (len == -1 && precision >= VARHDRSZ) { + len = precision - VARHDRSZ; + precision = -1; + } } + f.setLength(len); f.setPrecision(precision); - f.setSqlType(PQftype(d->result, i)); + f.setSqlType(ptype); info.append(f); } return info; diff --git a/tests/auto/sql/kernel/qsqlquery/tst_qsqlquery.cpp b/tests/auto/sql/kernel/qsqlquery/tst_qsqlquery.cpp index 301c7bca51..824f042ffc 100644 --- a/tests/auto/sql/kernel/qsqlquery/tst_qsqlquery.cpp +++ b/tests/auto/sql/kernel/qsqlquery/tst_qsqlquery.cpp @@ -195,6 +195,9 @@ private slots: void task_233829_data() { generic_data("QPSQL"); } void task_233829(); + void QTBUG_12477_data() { generic_data("QPSQL"); } + void QTBUG_12477(); + void sqlServerReturn0_data() { generic_data(); } void sqlServerReturn0(); @@ -3012,6 +3015,47 @@ void tst_QSqlQuery::task_233829() QVERIFY_SQL(q,exec()); } +void tst_QSqlQuery::QTBUG_12477() +{ + QFETCH(QString, dbName); + QSqlDatabase db = QSqlDatabase::database(dbName); + CHECK_DATABASE(db); + if (!db.driverName().startsWith("QPSQL")) + QSKIP("PostgreSQL specific test"); + + QSqlQuery q(db); + QVERIFY_SQL(q, exec("SELECT 1::bit, '10101010000111101101'::varbit, " + "'10101111011'::varbit(15), '22222.20'::numeric(16,2), " + "'333333'::numeric(18), '444444'::numeric")); + QVERIFY_SQL(q, next()); + QSqlRecord r = q.record(); + QSqlField f; + + f = r.field(0); + QCOMPARE(f.length(), 1); + QCOMPARE(f.precision(), -1); + + f = r.field(1); + QCOMPARE(f.length(), -1); + QCOMPARE(f.precision(), -1); + + f = r.field(2); + QCOMPARE(f.length(), 15); + QCOMPARE(f.precision(), -1); + + f = r.field(3); + QCOMPARE(f.length(), 16); + QCOMPARE(f.precision(), 2); + + f = r.field(4); + QCOMPARE(f.length(), 18); + QCOMPARE(f.precision(), 0); + + f = r.field(5); + QCOMPARE(f.length(), -1); + QCOMPARE(f.precision(), -1); +} + void tst_QSqlQuery::sqlServerReturn0() { QFETCH( QString, dbName );