From b19372c11549bc1f88b3e59fa94745645503b8e6 Mon Sep 17 00:00:00 2001 From: Bill King Date: Tue, 1 Sep 2009 13:08:02 +1000 Subject: Fixes determination of end of odbc string on deficient driver Ported this fix backwards from 4.6 to 4.5 Adds some cleanups (using QVarLengthArray), and reverting to the initial and correct calculation (when the driver doesn't deem fit to return SQL_NO_DATA). --- src/sql/drivers/odbc/qsql_odbc.cpp | 12 ++++---- tests/auto/qsqldatabase/tst_qsqldatabase.cpp | 41 ++++++++++++++++++++++++++++ 2 files changed, 47 insertions(+), 6 deletions(-) diff --git a/src/sql/drivers/odbc/qsql_odbc.cpp b/src/sql/drivers/odbc/qsql_odbc.cpp index ae522ee..a5c713d 100644 --- a/src/sql/drivers/odbc/qsql_odbc.cpp +++ b/src/sql/drivers/odbc/qsql_odbc.cpp @@ -314,12 +314,12 @@ static QString qGetStringData(SQLHANDLE hStmt, int column, int colSize, bool uni colSize *= 2; // a tiny bit faster, since it saves a SQLGetData() call } } - char* buf = new char[colSize]; + QVarLengthArray buf(colSize); while (true) { r = SQLGetData(hStmt, column+1, unicode ? SQL_C_WCHAR : SQL_C_CHAR, - (SQLPOINTER)buf, + (SQLPOINTER)buf.data(), colSize, &lengthIndicator); if (r == SQL_SUCCESS || r == SQL_SUCCESS_WITH_INFO) { @@ -334,11 +334,12 @@ static QString qGetStringData(SQLHANDLE hStmt, int column, int colSize, bool uni // colSize-1: remove 0 termination when there is more data to fetch int rSize = (r == SQL_SUCCESS_WITH_INFO) ? (unicode ? colSize-2 : colSize-1) : lengthIndicator; if (unicode) { - fieldVal += QString((QChar*) buf, rSize / 2); + fieldVal += QString((const QChar*) buf.constData(), rSize / 2); } else { - fieldVal += QString::fromAscii(buf, rSize); + fieldVal += QString::fromAscii(buf.constData(), rSize); } - if (lengthIndicator - fieldVal.size() <= 0) { + memset(buf.data(), 0, colSize); + if (lengthIndicator < colSize) { // workaround for Drivermanagers that don't return SQL_NO_DATA break; } @@ -350,7 +351,6 @@ static QString qGetStringData(SQLHANDLE hStmt, int column, int colSize, bool uni break; } } - delete[] buf; return fieldVal; } diff --git a/tests/auto/qsqldatabase/tst_qsqldatabase.cpp b/tests/auto/qsqldatabase/tst_qsqldatabase.cpp index 782bff8..9ca48f5 100644 --- a/tests/auto/qsqldatabase/tst_qsqldatabase.cpp +++ b/tests/auto/qsqldatabase/tst_qsqldatabase.cpp @@ -180,6 +180,8 @@ private slots: void odbc_uintfield(); void odbc_bindBoolean_data() { generic_data("QODBC"); } void odbc_bindBoolean(); + void odbc_testqGetString_data() { generic_data("QODBC"); } + void odbc_testqGetString(); void oci_serverDetach_data() { generic_data("QOCI"); } void oci_serverDetach(); // For task 154518 @@ -347,6 +349,7 @@ void tst_QSqlDatabase::dropTestTables(QSqlDatabase db) << qTableName("numericfields") << qTableName("qtest_ibaseblobs") << qTableName("qtestBindBool") + << qTableName("testqGetString") << qTableName("qtest_sqlguid") << qTableName("uint_table") << qTableName("uint_test") @@ -2005,6 +2008,44 @@ void tst_QSqlDatabase::odbc_bindBoolean() QCOMPARE(q.value(1).toBool(), false); } +void tst_QSqlDatabase::odbc_testqGetString() +{ + QFETCH(QString, dbName); + QSqlDatabase db = QSqlDatabase::database(dbName); + CHECK_DATABASE(db); + + QSqlQuery q(db); + QVERIFY_SQL(q, exec("CREATE TABLE " + qTableName("testqGetString") + "(id int, vcvalue varchar(65538))")); + + QString largeString; + largeString.fill('A', 65536); + + // Bind and insert + QVERIFY_SQL(q, prepare("INSERT INTO " + qTableName("testqGetString") + " VALUES(?, ?)")); + q.bindValue(0, 1); + q.bindValue(1, largeString); + QVERIFY_SQL(q, exec()); + q.bindValue(0, 2); + q.bindValue(1, largeString+QLatin1Char('B')); + QVERIFY_SQL(q, exec()); + q.bindValue(0, 3); + q.bindValue(1, largeString+QLatin1Char('B')+QLatin1Char('C')); + QVERIFY_SQL(q, exec()); + + // Retrive + QVERIFY_SQL(q, exec("SELECT id, vcvalue FROM " + qTableName("testqGetString") + " ORDER BY id")); + QVERIFY_SQL(q, next()); + QCOMPARE(q.value(0).toInt(), 1); + QCOMPARE(q.value(1).toString().length(), 65536); + QVERIFY_SQL(q, next()); + QCOMPARE(q.value(0).toInt(), 2); + QCOMPARE(q.value(1).toString().length(), 65537); + QVERIFY_SQL(q, next()); + QCOMPARE(q.value(0).toInt(), 3); + QCOMPARE(q.value(1).toString().length(), 65538); +} + + void tst_QSqlDatabase::mysql_multiselect() { QFETCH(QString, dbName); -- cgit v0.12