summaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
authorThiago A. Correa <thiago.correa@gmail.com>2012-07-13 14:28:18 -0300
committerThe Qt Project <gerrit-noreply@qt-project.org>2012-10-08 08:58:03 +0200
commitd408593c1acbdde72b03e6a99816451224d7839d (patch)
treea53a01475a325dd7a0dfff3183d2c996f54552a0 /src
parent7d94d08f91004e4c48904ca192c16c2c4cc129d0 (diff)
Fix error when inserting to tables with datetime fields with QODBC
SQL Server 10 introduced stricter rules for TIMESTAMP validation, making it necessary to specify the decimal digits. Other databases might do the same as well, so this patch introduces a check for the TIMESTAMP column size and adjusts the decimal digits parameter as needed. Task-number: QTBUG-2192 Change-Id: If6d798c6c928ebda75bc474e49a07fbbfbe5816c Reviewed-by: Mark Brand <mabrand@mabrand.nl> (cherry picked from qtbase/b8b79a0f37ec74fd5b4ad829e522a384ba3622ae)
Diffstat (limited to 'src')
-rw-r--r--src/sql/drivers/odbc/qsql_odbc.cpp46
1 files changed, 42 insertions, 4 deletions
diff --git a/src/sql/drivers/odbc/qsql_odbc.cpp b/src/sql/drivers/odbc/qsql_odbc.cpp
index 44c5f0ca5b..62ab8184a5 100644
--- a/src/sql/drivers/odbc/qsql_odbc.cpp
+++ b/src/sql/drivers/odbc/qsql_odbc.cpp
@@ -54,6 +54,7 @@
#include <qstringlist.h>
#include <qvarlengtharray.h>
#include <qvector.h>
+#include <qmath.h>
#include <QDebug>
#include <QSqlQuery>
@@ -115,7 +116,7 @@ class QODBCDriverPrivate
public:
enum DefaultCase{Lower, Mixed, Upper, Sensitive};
QODBCDriverPrivate()
- : hEnv(0), hDbc(0), unicode(false), useSchema(false), disconnectCount(0), isMySqlServer(false),
+ : hEnv(0), hDbc(0), unicode(false), useSchema(false), disconnectCount(0), datetime_precision(19), isMySqlServer(false),
isMSSqlServer(false), isFreeTDSDriver(false), hasSQLFetchScroll(true),
hasMultiResultSets(false), isQuoteInitialized(false), quote(QLatin1Char('"'))
{
@@ -127,6 +128,7 @@ public:
bool unicode;
bool useSchema;
int disconnectCount;
+ int datetime_precision;
bool isMySqlServer;
bool isMSSqlServer;
bool isFreeTDSDriver;
@@ -139,6 +141,7 @@ public:
void checkHasSQLFetchScroll();
void checkHasMultiResults();
void checkSchemaUsage();
+ void checkDateTimePrecision();
bool setConnectionOptions(const QString& connOpts);
void splitTableQualifier(const QString &qualifier, QString &catalog,
QString &schema, QString &table);
@@ -1401,14 +1404,25 @@ bool QODBCResult::exec()
dt->hour = qdt.time().hour();
dt->minute = qdt.time().minute();
dt->second = qdt.time().second();
- dt->fraction = qdt.time().msec() * 1000000;
+
+ int precision = d->driverPrivate->datetime_precision - 20; // (20 includes a separating period)
+ if (precision <= 0) {
+ dt->fraction = 0;
+ } else {
+ dt->fraction = qdt.time().msec() * 1000000;
+
+ // (How many leading digits do we want to keep? With SQL Server 2005, this should be 3: 123000000)
+ int keep = (int)qPow(10.0, 9 - qMin(9, precision));
+ dt->fraction /= keep * keep;
+ }
+
r = SQLBindParameter(d->hStmt,
i + 1,
qParamType[(QFlag)(bindValueType(i)) & QSql::InOut],
SQL_C_TIMESTAMP,
SQL_TIMESTAMP,
- 19,
- 0,
+ d->driverPrivate->datetime_precision,
+ precision,
(void *) dt,
0,
*ind == SQL_NULL_DATA ? ind : NULL);
@@ -1895,6 +1909,7 @@ bool QODBCDriver::open(const QString & db,
d->checkSqlServer();
d->checkHasSQLFetchScroll();
d->checkHasMultiResults();
+ d->checkDateTimePrecision();
setOpen(true);
setOpenError(false);
if(d->isMSSqlServer) {
@@ -2130,6 +2145,29 @@ void QODBCDriverPrivate::checkHasMultiResults()
#endif
}
+void QODBCDriverPrivate::checkDateTimePrecision()
+{
+ SQLINTEGER columnSize;
+ SQLHANDLE hStmt;
+
+ SQLRETURN r = SQLAllocHandle(SQL_HANDLE_STMT, hDbc, &hStmt);
+ if (r != SQL_SUCCESS) {
+ return;
+ }
+
+ r = SQLGetTypeInfo(hStmt, SQL_TIMESTAMP);
+ if (r == SQL_SUCCESS || r == SQL_SUCCESS_WITH_INFO) {
+ r = SQLFetch(hStmt);
+ if ( r == SQL_SUCCESS || r == SQL_SUCCESS_WITH_INFO )
+ {
+ if (SQLGetData(hStmt, 3, SQL_INTEGER, &columnSize, sizeof(columnSize), 0) == SQL_SUCCESS) {
+ datetime_precision = (int)columnSize;
+ }
+ }
+ }
+ SQLFreeHandle(SQL_HANDLE_STMT, hStmt);
+}
+
QSqlResult *QODBCDriver::createResult() const
{
return new QODBCResult(this, d);