diff options
Diffstat (limited to 'src/sql/drivers/db2')
-rw-r--r-- | src/sql/drivers/db2/qsql_db2.cpp | 1700 | ||||
-rw-r--r-- | src/sql/drivers/db2/qsql_db2.pri | 8 | ||||
-rw-r--r-- | src/sql/drivers/db2/qsql_db2_p.h | 103 |
3 files changed, 0 insertions, 1811 deletions
diff --git a/src/sql/drivers/db2/qsql_db2.cpp b/src/sql/drivers/db2/qsql_db2.cpp deleted file mode 100644 index 4ccc3aca9e..0000000000 --- a/src/sql/drivers/db2/qsql_db2.cpp +++ /dev/null @@ -1,1700 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2016 The Qt Company Ltd. -** Contact: https://www.qt.io/licensing/ -** -** This file is part of the QtSql module of the Qt Toolkit. -** -** $QT_BEGIN_LICENSE:LGPL$ -** Commercial License Usage -** Licensees holding valid commercial Qt licenses may use this file in -** accordance with the commercial license agreement provided with the -** Software or, alternatively, in accordance with the terms contained in -** a written agreement between you and The Qt Company. For licensing terms -** and conditions see https://www.qt.io/terms-conditions. For further -** information use the contact form at https://www.qt.io/contact-us. -** -** GNU Lesser General Public License Usage -** Alternatively, this file may be used under the terms of the GNU Lesser -** General Public License version 3 as published by the Free Software -** Foundation and appearing in the file LICENSE.LGPL3 included in the -** packaging of this file. Please review the following information to -** ensure the GNU Lesser General Public License version 3 requirements -** will be met: https://www.gnu.org/licenses/lgpl-3.0.html. -** -** GNU General Public License Usage -** Alternatively, this file may be used under the terms of the GNU -** General Public License version 2.0 or (at your option) the GNU General -** Public license version 3 or any later version approved by the KDE Free -** Qt Foundation. The licenses are as published by the Free Software -** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3 -** included in the packaging of this file. Please review the following -** information to ensure the GNU General Public License requirements will -** be met: https://www.gnu.org/licenses/gpl-2.0.html and -** https://www.gnu.org/licenses/gpl-3.0.html. -** -** $QT_END_LICENSE$ -** -****************************************************************************/ - -#include "qsql_db2_p.h" -#include <qcoreapplication.h> -#include <qdatetime.h> -#include <qsqlfield.h> -#include <qsqlerror.h> -#include <qsqlindex.h> -#include <qsqlrecord.h> -#include <qstringlist.h> -#include <qvarlengtharray.h> -#include <qvector.h> -#include <QDebug> -#include <QtSql/private/qsqldriver_p.h> -#include <QtSql/private/qsqlresult_p.h> - -#if defined(Q_CC_BOR) -// DB2's sqlsystm.h (included through sqlcli1.h) defines the SQL_BIGINT_TYPE -// and SQL_BIGUINT_TYPE to wrong the types for Borland; so do the defines to -// the right type before including the header -#define SQL_BIGINT_TYPE qint64 -#define SQL_BIGUINT_TYPE quint64 -#endif - -#define UNICODE - -#include <sqlcli1.h> - -#include <string.h> - -QT_BEGIN_NAMESPACE - -static const int COLNAMESIZE = 255; -static const SQLSMALLINT qParamType[4] = { SQL_PARAM_INPUT, SQL_PARAM_INPUT, SQL_PARAM_OUTPUT, SQL_PARAM_INPUT_OUTPUT }; - -class QDB2DriverPrivate : public QSqlDriverPrivate -{ - Q_DECLARE_PUBLIC(QDB2Driver) - -public: - QDB2DriverPrivate() : QSqlDriverPrivate(), hEnv(0), hDbc(0) { dbmsType = QSqlDriver::DB2; } - SQLHANDLE hEnv; - SQLHANDLE hDbc; - QString user; -}; - -class QDB2ResultPrivate; - -class QDB2Result: public QSqlResult -{ - Q_DECLARE_PRIVATE(QDB2Result) - -public: - QDB2Result(const QDB2Driver *drv); - ~QDB2Result(); - bool prepare(const QString &query) Q_DECL_OVERRIDE; - bool exec() Q_DECL_OVERRIDE; - QVariant handle() const Q_DECL_OVERRIDE; - -protected: - QVariant data(int field) Q_DECL_OVERRIDE; - bool reset(const QString &query) Q_DECL_OVERRIDE; - bool fetch(int i) Q_DECL_OVERRIDE; - bool fetchNext() Q_DECL_OVERRIDE; - bool fetchFirst() Q_DECL_OVERRIDE; - bool fetchLast() Q_DECL_OVERRIDE; - bool isNull(int i) Q_DECL_OVERRIDE; - int size() Q_DECL_OVERRIDE; - int numRowsAffected() Q_DECL_OVERRIDE; - QSqlRecord record() const Q_DECL_OVERRIDE; - void virtual_hook(int id, void *data) Q_DECL_OVERRIDE; - void detachFromResultSet() Q_DECL_OVERRIDE; - bool nextResult() Q_DECL_OVERRIDE; -}; - -class QDB2ResultPrivate: public QSqlResultPrivate -{ - Q_DECLARE_PUBLIC(QDB2Result) - -public: - Q_DECLARE_SQLDRIVER_PRIVATE(QDB2Driver) - QDB2ResultPrivate(QDB2Result *q, const QDB2Driver *drv) - : QSqlResultPrivate(q, drv), - hStmt(0) - {} - ~QDB2ResultPrivate() - { - emptyValueCache(); - } - void clearValueCache() - { - for (int i = 0; i < valueCache.count(); ++i) { - delete valueCache[i]; - valueCache[i] = NULL; - } - } - void emptyValueCache() - { - clearValueCache(); - valueCache.clear(); - } - - SQLHANDLE hStmt; - QSqlRecord recInf; - QVector<QVariant*> valueCache; -}; - -static QString qFromTChar(SQLTCHAR* str) -{ - return QString((const QChar *)str); -} - -// dangerous!! (but fast). Don't use in functions that -// require out parameters! -static SQLTCHAR* qToTChar(const QString& str) -{ - return (SQLTCHAR*)str.utf16(); -} - -static QString qWarnDB2Handle(int handleType, SQLHANDLE handle) -{ - SQLINTEGER nativeCode; - SQLSMALLINT msgLen; - SQLRETURN r = SQL_ERROR; - SQLTCHAR state[SQL_SQLSTATE_SIZE + 1]; - SQLTCHAR description[SQL_MAX_MESSAGE_LENGTH]; - r = SQLGetDiagRec(handleType, - handle, - 1, - (SQLTCHAR*) state, - &nativeCode, - (SQLTCHAR*) description, - SQL_MAX_MESSAGE_LENGTH - 1, /* in bytes, not in characters */ - &msgLen); - if (r == SQL_SUCCESS || r == SQL_SUCCESS_WITH_INFO) - return QString(qFromTChar(description)); - return QString(); -} - -static QString qDB2Warn(const QDB2DriverPrivate* d) -{ - return (qWarnDB2Handle(SQL_HANDLE_ENV, d->hEnv) + QLatin1Char(' ') - + qWarnDB2Handle(SQL_HANDLE_DBC, d->hDbc)); -} - -static QString qDB2Warn(const QDB2ResultPrivate* d) -{ - return (qWarnDB2Handle(SQL_HANDLE_ENV, d->drv_d_func()->hEnv) + QLatin1Char(' ') - + qWarnDB2Handle(SQL_HANDLE_DBC, d->drv_d_func()->hDbc) - + qWarnDB2Handle(SQL_HANDLE_STMT, d->hStmt)); -} - -static void qSqlWarning(const QString& message, const QDB2DriverPrivate* d) -{ - qWarning("%s\tError: %s", message.toLocal8Bit().constData(), - qDB2Warn(d).toLocal8Bit().constData()); -} - -static void qSqlWarning(const QString& message, const QDB2ResultPrivate* d) -{ - qWarning("%s\tError: %s", message.toLocal8Bit().constData(), - qDB2Warn(d).toLocal8Bit().constData()); -} - -static QSqlError qMakeError(const QString& err, QSqlError::ErrorType type, - const QDB2DriverPrivate* p) -{ - return QSqlError(QLatin1String("QDB2: ") + err, qDB2Warn(p), type); -} - -static QSqlError qMakeError(const QString& err, QSqlError::ErrorType type, - const QDB2ResultPrivate* p) -{ - return QSqlError(QLatin1String("QDB2: ") + err, qDB2Warn(p), type); -} - -static QVariant::Type qDecodeDB2Type(SQLSMALLINT sqltype) -{ - QVariant::Type type = QVariant::Invalid; - switch (sqltype) { - case SQL_REAL: - case SQL_FLOAT: - case SQL_DOUBLE: - case SQL_DECIMAL: - case SQL_NUMERIC: - type = QVariant::Double; - break; - case SQL_SMALLINT: - case SQL_INTEGER: - case SQL_BIT: - case SQL_TINYINT: - type = QVariant::Int; - break; - case SQL_BIGINT: - type = QVariant::LongLong; - break; - case SQL_BLOB: - case SQL_BINARY: - case SQL_VARBINARY: - case SQL_LONGVARBINARY: - case SQL_CLOB: - case SQL_DBCLOB: - type = QVariant::ByteArray; - break; - case SQL_DATE: - case SQL_TYPE_DATE: - type = QVariant::Date; - break; - case SQL_TIME: - case SQL_TYPE_TIME: - type = QVariant::Time; - break; - case SQL_TIMESTAMP: - case SQL_TYPE_TIMESTAMP: - type = QVariant::DateTime; - break; - case SQL_WCHAR: - case SQL_WVARCHAR: - case SQL_WLONGVARCHAR: - case SQL_CHAR: - case SQL_VARCHAR: - case SQL_LONGVARCHAR: - type = QVariant::String; - break; - default: - type = QVariant::ByteArray; - break; - } - return type; -} - -static QSqlField qMakeFieldInfo(const QDB2ResultPrivate* d, int i) -{ - SQLSMALLINT colNameLen; - SQLSMALLINT colType; - SQLUINTEGER colSize; - SQLSMALLINT colScale; - SQLSMALLINT nullable; - SQLRETURN r = SQL_ERROR; - SQLTCHAR colName[COLNAMESIZE]; - r = SQLDescribeCol(d->hStmt, - i+1, - colName, - (SQLSMALLINT) COLNAMESIZE, - &colNameLen, - &colType, - &colSize, - &colScale, - &nullable); - - if (r != SQL_SUCCESS) { - qSqlWarning(QString::fromLatin1("qMakeFieldInfo: Unable to describe column %1").arg(i), d); - return QSqlField(); - } - QSqlField f(qFromTChar(colName), qDecodeDB2Type(colType)); - // nullable can be SQL_NO_NULLS, SQL_NULLABLE or SQL_NULLABLE_UNKNOWN - if (nullable == SQL_NO_NULLS) - f.setRequired(true); - else if (nullable == SQL_NULLABLE) - f.setRequired(false); - // else required is unknown - f.setLength(colSize == 0 ? -1 : int(colSize)); - f.setPrecision(colScale == 0 ? -1 : int(colScale)); - f.setSqlType(int(colType)); - return f; -} - -static int qGetIntData(SQLHANDLE hStmt, int column, bool& isNull) -{ - SQLINTEGER intbuf; - isNull = false; - SQLINTEGER lengthIndicator = 0; - SQLRETURN r = SQLGetData(hStmt, - column + 1, - SQL_C_SLONG, - (SQLPOINTER) &intbuf, - 0, - &lengthIndicator); - if ((r != SQL_SUCCESS && r != SQL_SUCCESS_WITH_INFO) || lengthIndicator == SQL_NULL_DATA) { - isNull = true; - return 0; - } - return int(intbuf); -} - -static double qGetDoubleData(SQLHANDLE hStmt, int column, bool& isNull) -{ - SQLDOUBLE dblbuf; - isNull = false; - SQLINTEGER lengthIndicator = 0; - SQLRETURN r = SQLGetData(hStmt, - column+1, - SQL_C_DOUBLE, - (SQLPOINTER) &dblbuf, - 0, - &lengthIndicator); - if ((r != SQL_SUCCESS && r != SQL_SUCCESS_WITH_INFO) || lengthIndicator == SQL_NULL_DATA) { - isNull = true; - return 0.0; - } - - return (double) dblbuf; -} - -static SQLBIGINT qGetBigIntData(SQLHANDLE hStmt, int column, bool& isNull) -{ - SQLBIGINT lngbuf = Q_INT64_C(0); - isNull = false; - SQLINTEGER lengthIndicator = 0; - SQLRETURN r = SQLGetData(hStmt, - column+1, - SQL_C_SBIGINT, - (SQLPOINTER) &lngbuf, - 0, - &lengthIndicator); - if ((r != SQL_SUCCESS && r != SQL_SUCCESS_WITH_INFO) || lengthIndicator == SQL_NULL_DATA) - isNull = true; - - return lngbuf; -} - -static QString qGetStringData(SQLHANDLE hStmt, int column, int colSize, bool& isNull) -{ - QString fieldVal; - SQLRETURN r = SQL_ERROR; - SQLINTEGER lengthIndicator = 0; - - if (colSize <= 0) - colSize = 255; - else if (colSize > 65536) // limit buffer size to 64 KB - colSize = 65536; - else - colSize++; // make sure there is room for more than the 0 termination - SQLTCHAR* buf = new SQLTCHAR[colSize]; - - while (true) { - r = SQLGetData(hStmt, - column + 1, - SQL_C_WCHAR, - (SQLPOINTER)buf, - colSize * sizeof(SQLTCHAR), - &lengthIndicator); - if (r == SQL_SUCCESS || r == SQL_SUCCESS_WITH_INFO) { - if (lengthIndicator == SQL_NULL_DATA || lengthIndicator == SQL_NO_TOTAL) { - fieldVal.clear(); - isNull = true; - break; - } - fieldVal += qFromTChar(buf); - } else if (r == SQL_NO_DATA) { - break; - } else { - qWarning("qGetStringData: Error while fetching data (%d)", r); - fieldVal.clear(); - break; - } - } - delete[] buf; - return fieldVal; -} - -static QByteArray qGetBinaryData(SQLHANDLE hStmt, int column, SQLINTEGER& lengthIndicator, bool& isNull) -{ - QByteArray fieldVal; - SQLSMALLINT colNameLen; - SQLSMALLINT colType; - SQLUINTEGER colSize; - SQLSMALLINT colScale; - SQLSMALLINT nullable; - SQLRETURN r = SQL_ERROR; - - SQLTCHAR colName[COLNAMESIZE]; - r = SQLDescribeCol(hStmt, - column+1, - colName, - COLNAMESIZE, - &colNameLen, - &colType, - &colSize, - &colScale, - &nullable); - if (r != SQL_SUCCESS) - qWarning("qGetBinaryData: Unable to describe column %d", column); - // SQLDescribeCol may return 0 if size cannot be determined - if (!colSize) - colSize = 255; - else if (colSize > 65536) // read the field in 64 KB chunks - colSize = 65536; - char * buf = new char[colSize]; - while (true) { - r = SQLGetData(hStmt, - column+1, - colType == SQL_DBCLOB ? SQL_C_CHAR : SQL_C_BINARY, - (SQLPOINTER) buf, - colSize, - &lengthIndicator); - if (r == SQL_SUCCESS || r == SQL_SUCCESS_WITH_INFO) { - if (lengthIndicator == SQL_NULL_DATA) { - isNull = true; - break; - } else { - int rSize; - r == SQL_SUCCESS ? rSize = lengthIndicator : rSize = colSize; - if (lengthIndicator == SQL_NO_TOTAL) // size cannot be determined - rSize = colSize; - fieldVal.append(QByteArray(buf, rSize)); - if (r == SQL_SUCCESS) // the whole field was read in one chunk - break; - } - } else { - break; - } - } - delete [] buf; - return fieldVal; -} - -static void qSplitTableQualifier(const QString & qualifier, QString * catalog, - QString * schema, QString * table) -{ - if (!catalog || !schema || !table) - return; - QStringList l = qualifier.split(QLatin1Char('.')); - if (l.count() > 3) - return; // can't possibly be a valid table qualifier - int i = 0, n = l.count(); - if (n == 1) { - *table = qualifier; - } else { - for (QStringList::Iterator it = l.begin(); it != l.end(); ++it) { - if (n == 3) { - if (i == 0) - *catalog = *it; - else if (i == 1) - *schema = *it; - else if (i == 2) - *table = *it; - } else if (n == 2) { - if (i == 0) - *schema = *it; - else if (i == 1) - *table = *it; - } - i++; - } - } -} - -// creates a QSqlField from a valid hStmt generated -// by SQLColumns. The hStmt has to point to a valid position. -static QSqlField qMakeFieldInfo(const SQLHANDLE hStmt) -{ - bool isNull; - int type = qGetIntData(hStmt, 4, isNull); - QSqlField f(qGetStringData(hStmt, 3, -1, isNull), qDecodeDB2Type(type)); - int required = qGetIntData(hStmt, 10, isNull); // nullable-flag - // required can be SQL_NO_NULLS, SQL_NULLABLE or SQL_NULLABLE_UNKNOWN - if (required == SQL_NO_NULLS) - f.setRequired(true); - else if (required == SQL_NULLABLE) - f.setRequired(false); - // else we don't know. - f.setLength(qGetIntData(hStmt, 6, isNull)); // column size - f.setPrecision(qGetIntData(hStmt, 8, isNull)); // precision - f.setSqlType(type); - return f; -} - -static bool qMakeStatement(QDB2ResultPrivate* d, bool forwardOnly, bool setForwardOnly = true) -{ - SQLRETURN r; - if (!d->hStmt) { - r = SQLAllocHandle(SQL_HANDLE_STMT, - d->drv_d_func()->hDbc, - &d->hStmt); - if (r != SQL_SUCCESS) { - qSqlWarning(QLatin1String("QDB2Result::reset: Unable to allocate statement handle"), d); - return false; - } - } else { - r = SQLFreeStmt(d->hStmt, SQL_CLOSE); - if (r != SQL_SUCCESS) { - qSqlWarning(QLatin1String("QDB2Result::reset: Unable to close statement handle"), d); - return false; - } - } - - if (!setForwardOnly) - return true; - - if (forwardOnly) { - r = SQLSetStmtAttr(d->hStmt, - SQL_ATTR_CURSOR_TYPE, - (SQLPOINTER) SQL_CURSOR_FORWARD_ONLY, - SQL_IS_UINTEGER); - } else { - r = SQLSetStmtAttr(d->hStmt, - SQL_ATTR_CURSOR_TYPE, - (SQLPOINTER) SQL_CURSOR_STATIC, - SQL_IS_UINTEGER); - } - if (r != SQL_SUCCESS && r != SQL_SUCCESS_WITH_INFO) { - qSqlWarning(QString::fromLatin1("QDB2Result::reset: Unable to set %1 attribute.").arg( - forwardOnly ? QLatin1String("SQL_CURSOR_FORWARD_ONLY") - : QLatin1String("SQL_CURSOR_STATIC")), d); - return false; - } - return true; -} - -QVariant QDB2Result::handle() const -{ - Q_D(const QDB2Result); - return QVariant(qRegisterMetaType<SQLHANDLE>("SQLHANDLE"), &d->hStmt); -} - -/************************************/ - -QDB2Result::QDB2Result(const QDB2Driver *drv) - : QSqlResult(*new QDB2ResultPrivate(this, drv)) -{ -} - -QDB2Result::~QDB2Result() -{ - Q_D(const QDB2Result); - if (d->hStmt) { - SQLRETURN r = SQLFreeHandle(SQL_HANDLE_STMT, d->hStmt); - if (r != SQL_SUCCESS) - qSqlWarning(QLatin1String("QDB2Driver: Unable to free statement handle ") - + QString::number(r), d); - } -} - -bool QDB2Result::reset (const QString& query) -{ - Q_D(QDB2Result); - setActive(false); - setAt(QSql::BeforeFirstRow); - SQLRETURN r; - - d->recInf.clear(); - d->emptyValueCache(); - - if (!qMakeStatement(d, isForwardOnly())) - return false; - - r = SQLExecDirect(d->hStmt, - qToTChar(query), - (SQLINTEGER) query.length()); - if (r != SQL_SUCCESS && r != SQL_SUCCESS_WITH_INFO) { - setLastError(qMakeError(QCoreApplication::translate("QDB2Result", - "Unable to execute statement"), QSqlError::StatementError, d)); - return false; - } - SQLSMALLINT count = 0; - r = SQLNumResultCols(d->hStmt, &count); - if (count) { - setSelect(true); - for (int i = 0; i < count; ++i) { - d->recInf.append(qMakeFieldInfo(d, i)); - } - } else { - setSelect(false); - } - d->valueCache.resize(count); - d->valueCache.fill(NULL); - setActive(true); - return true; -} - -bool QDB2Result::prepare(const QString& query) -{ - Q_D(QDB2Result); - setActive(false); - setAt(QSql::BeforeFirstRow); - SQLRETURN r; - - d->recInf.clear(); - d->emptyValueCache(); - - if (!qMakeStatement(d, isForwardOnly())) - return false; - - r = SQLPrepare(d->hStmt, - qToTChar(query), - (SQLINTEGER) query.length()); - - if (r != SQL_SUCCESS) { - setLastError(qMakeError(QCoreApplication::translate("QDB2Result", - "Unable to prepare statement"), QSqlError::StatementError, d)); - return false; - } - return true; -} - -bool QDB2Result::exec() -{ - Q_D(QDB2Result); - QList<QByteArray> tmpStorage; // holds temporary ptrs - QVarLengthArray<SQLINTEGER, 32> indicators(boundValues().count()); - - memset(indicators.data(), 0, indicators.size() * sizeof(SQLINTEGER)); - setActive(false); - setAt(QSql::BeforeFirstRow); - SQLRETURN r; - - d->recInf.clear(); - d->emptyValueCache(); - - if (!qMakeStatement(d, isForwardOnly(), false)) - return false; - - - QVector<QVariant> &values = boundValues(); - int i; - for (i = 0; i < values.count(); ++i) { - // bind parameters - only positional binding allowed - SQLINTEGER *ind = &indicators[i]; - if (values.at(i).isNull()) - *ind = SQL_NULL_DATA; - if (bindValueType(i) & QSql::Out) - values[i].detach(); - - switch (values.at(i).type()) { - case QVariant::Date: { - QByteArray ba; - ba.resize(sizeof(DATE_STRUCT)); - DATE_STRUCT *dt = (DATE_STRUCT *)ba.constData(); - QDate qdt = values.at(i).toDate(); - dt->year = qdt.year(); - dt->month = qdt.month(); - dt->day = qdt.day(); - r = SQLBindParameter(d->hStmt, - i + 1, - qParamType[bindValueType(i) & 3], - SQL_C_DATE, - SQL_DATE, - 0, - 0, - (void *) dt, - 0, - *ind == SQL_NULL_DATA ? ind : NULL); - tmpStorage.append(ba); - break; } - case QVariant::Time: { - QByteArray ba; - ba.resize(sizeof(TIME_STRUCT)); - TIME_STRUCT *dt = (TIME_STRUCT *)ba.constData(); - QTime qdt = values.at(i).toTime(); - dt->hour = qdt.hour(); - dt->minute = qdt.minute(); - dt->second = qdt.second(); - r = SQLBindParameter(d->hStmt, - i + 1, - qParamType[bindValueType(i) & 3], - SQL_C_TIME, - SQL_TIME, - 0, - 0, - (void *) dt, - 0, - *ind == SQL_NULL_DATA ? ind : NULL); - tmpStorage.append(ba); - break; } - case QVariant::DateTime: { - QByteArray ba; - ba.resize(sizeof(TIMESTAMP_STRUCT)); - TIMESTAMP_STRUCT * dt = (TIMESTAMP_STRUCT *)ba.constData(); - QDateTime qdt = values.at(i).toDateTime(); - dt->year = qdt.date().year(); - dt->month = qdt.date().month(); - dt->day = qdt.date().day(); - dt->hour = qdt.time().hour(); - dt->minute = qdt.time().minute(); - dt->second = qdt.time().second(); - dt->fraction = qdt.time().msec() * 1000000; - r = SQLBindParameter(d->hStmt, - i + 1, - qParamType[bindValueType(i) & 3], - SQL_C_TIMESTAMP, - SQL_TIMESTAMP, - 0, - 0, - (void *) dt, - 0, - *ind == SQL_NULL_DATA ? ind : NULL); - tmpStorage.append(ba); - break; } - case QVariant::Int: - r = SQLBindParameter(d->hStmt, - i + 1, - qParamType[bindValueType(i) & 3], - SQL_C_SLONG, - SQL_INTEGER, - 0, - 0, - (void *)values.at(i).constData(), - 0, - *ind == SQL_NULL_DATA ? ind : NULL); - break; - case QVariant::Double: - r = SQLBindParameter(d->hStmt, - i + 1, - qParamType[bindValueType(i) & 3], - SQL_C_DOUBLE, - SQL_DOUBLE, - 0, - 0, - (void *)values.at(i).constData(), - 0, - *ind == SQL_NULL_DATA ? ind : NULL); - break; - case QVariant::ByteArray: { - int len = values.at(i).toByteArray().size(); - if (*ind != SQL_NULL_DATA) - *ind = len; - r = SQLBindParameter(d->hStmt, - i + 1, - qParamType[bindValueType(i) & 3], - SQL_C_BINARY, - SQL_LONGVARBINARY, - len, - 0, - (void *)values.at(i).toByteArray().constData(), - len, - ind); - break; } - case QVariant::String: - { - QString str(values.at(i).toString()); - if (*ind != SQL_NULL_DATA) - *ind = str.length() * sizeof(QChar); - if (bindValueType(i) & QSql::Out) { - QByteArray ba((char*)str.utf16(), str.capacity() * sizeof(QChar)); - r = SQLBindParameter(d->hStmt, - i + 1, - qParamType[bindValueType(i) & 3], - SQL_C_WCHAR, - SQL_WVARCHAR, - str.length(), - 0, - (void *)ba.constData(), - ba.size(), - ind); - tmpStorage.append(ba); - } else { - void *data = (void*)str.utf16(); - int len = str.length(); - r = SQLBindParameter(d->hStmt, - i + 1, - qParamType[bindValueType(i) & 3], - SQL_C_WCHAR, - SQL_WVARCHAR, - len, - 0, - data, - len * sizeof(QChar), - ind); - } - break; - } - default: { - QByteArray ba = values.at(i).toString().toLatin1(); - int len = ba.length() + 1; - if (*ind != SQL_NULL_DATA) - *ind = ba.length(); - r = SQLBindParameter(d->hStmt, - i + 1, - qParamType[bindValueType(i) & 3], - SQL_C_CHAR, - SQL_VARCHAR, - len, - 0, - (void *) ba.constData(), - len, - ind); - tmpStorage.append(ba); - break; } - } - if (r != SQL_SUCCESS) { - qWarning("QDB2Result::exec: unable to bind variable: %s", - qDB2Warn(d).toLocal8Bit().constData()); - setLastError(qMakeError(QCoreApplication::translate("QDB2Result", - "Unable to bind variable"), QSqlError::StatementError, d)); - return false; - } - } - - r = SQLExecute(d->hStmt); - if (r != SQL_SUCCESS && r != SQL_SUCCESS_WITH_INFO) { - qWarning("QDB2Result::exec: Unable to execute statement: %s", - qDB2Warn(d).toLocal8Bit().constData()); - setLastError(qMakeError(QCoreApplication::translate("QDB2Result", - "Unable to execute statement"), QSqlError::StatementError, d)); - return false; - } - SQLSMALLINT count = 0; - r = SQLNumResultCols(d->hStmt, &count); - if (count) { - setSelect(true); - for (int i = 0; i < count; ++i) { - d->recInf.append(qMakeFieldInfo(d, i)); - } - } else { - setSelect(false); - } - setActive(true); - d->valueCache.resize(count); - d->valueCache.fill(NULL); - - //get out parameters - if (!hasOutValues()) - return true; - - for (i = 0; i < values.count(); ++i) { - switch (values[i].type()) { - case QVariant::Date: { - DATE_STRUCT ds = *((DATE_STRUCT *)tmpStorage.takeFirst().constData()); - values[i] = QVariant(QDate(ds.year, ds.month, ds.day)); - break; } - case QVariant::Time: { - TIME_STRUCT dt = *((TIME_STRUCT *)tmpStorage.takeFirst().constData()); - values[i] = QVariant(QTime(dt.hour, dt.minute, dt.second)); - break; } - case QVariant::DateTime: { - TIMESTAMP_STRUCT dt = *((TIMESTAMP_STRUCT *)tmpStorage.takeFirst().constData()); - values[i] = QVariant(QDateTime(QDate(dt.year, dt.month, dt.day), - QTime(dt.hour, dt.minute, dt.second, dt.fraction / 1000000))); - break; } - case QVariant::Int: - case QVariant::Double: - case QVariant::ByteArray: - break; - case QVariant::String: - if (bindValueType(i) & QSql::Out) - values[i] = QString((const QChar *)tmpStorage.takeFirst().constData()); - break; - default: { - values[i] = QString::fromLatin1(tmpStorage.takeFirst().constData()); - break; } - } - if (indicators[i] == SQL_NULL_DATA) - values[i] = QVariant(values[i].type()); - } - return true; -} - -bool QDB2Result::fetch(int i) -{ - Q_D(QDB2Result); - if (isForwardOnly() && i < at()) - return false; - if (i == at()) - return true; - d->clearValueCache(); - int actualIdx = i + 1; - if (actualIdx <= 0) { - setAt(QSql::BeforeFirstRow); - return false; - } - SQLRETURN r; - if (isForwardOnly()) { - bool ok = true; - while (ok && i > at()) - ok = fetchNext(); - return ok; - } else { - r = SQLFetchScroll(d->hStmt, - SQL_FETCH_ABSOLUTE, - actualIdx); - } - if (r != SQL_SUCCESS && r != SQL_SUCCESS_WITH_INFO && r != SQL_NO_DATA) { - setLastError(qMakeError(QCoreApplication::translate("QDB2Result", - "Unable to fetch record %1").arg(i), QSqlError::StatementError, d)); - return false; - } - else if (r == SQL_NO_DATA) - return false; - setAt(i); - return true; -} - -bool QDB2Result::fetchNext() -{ - Q_D(QDB2Result); - SQLRETURN r; - d->clearValueCache(); - r = SQLFetchScroll(d->hStmt, - SQL_FETCH_NEXT, - 0); - if (r != SQL_SUCCESS && r != SQL_SUCCESS_WITH_INFO) { - if (r != SQL_NO_DATA) - setLastError(qMakeError(QCoreApplication::translate("QDB2Result", - "Unable to fetch next"), QSqlError::StatementError, d)); - return false; - } - setAt(at() + 1); - return true; -} - -bool QDB2Result::fetchFirst() -{ - Q_D(QDB2Result); - if (isForwardOnly() && at() != QSql::BeforeFirstRow) - return false; - if (isForwardOnly()) - return fetchNext(); - d->clearValueCache(); - SQLRETURN r; - r = SQLFetchScroll(d->hStmt, - SQL_FETCH_FIRST, - 0); - if (r != SQL_SUCCESS && r != SQL_SUCCESS_WITH_INFO) { - if(r!= SQL_NO_DATA) - setLastError(qMakeError(QCoreApplication::translate("QDB2Result", "Unable to fetch first"), - QSqlError::StatementError, d)); - return false; - } - setAt(0); - return true; -} - -bool QDB2Result::fetchLast() -{ - Q_D(QDB2Result); - d->clearValueCache(); - - int i = at(); - if (i == QSql::AfterLastRow) { - if (isForwardOnly()) { - return false; - } else { - if (!fetch(0)) - return false; - i = at(); - } - } - - while (fetchNext()) - ++i; - - if (i == QSql::BeforeFirstRow) { - setAt(QSql::AfterLastRow); - return false; - } - - if (!isForwardOnly()) - return fetch(i); - - setAt(i); - return true; -} - - -QVariant QDB2Result::data(int field) -{ - Q_D(QDB2Result); - if (field >= d->recInf.count()) { - qWarning("QDB2Result::data: column %d out of range", field); - return QVariant(); - } - SQLRETURN r = 0; - SQLINTEGER lengthIndicator = 0; - bool isNull = false; - const QSqlField info = d->recInf.field(field); - - if (!info.isValid() || field >= d->valueCache.size()) - return QVariant(); - - if (d->valueCache[field]) - return *d->valueCache[field]; - - - QVariant* v = 0; - switch (info.type()) { - case QVariant::LongLong: - v = new QVariant((qint64) qGetBigIntData(d->hStmt, field, isNull)); - break; - case QVariant::Int: - v = new QVariant(qGetIntData(d->hStmt, field, isNull)); - break; - case QVariant::Date: { - DATE_STRUCT dbuf; - r = SQLGetData(d->hStmt, - field + 1, - SQL_C_DATE, - (SQLPOINTER) &dbuf, - 0, - &lengthIndicator); - if ((r == SQL_SUCCESS || r == SQL_SUCCESS_WITH_INFO) && (lengthIndicator != SQL_NULL_DATA)) { - v = new QVariant(QDate(dbuf.year, dbuf.month, dbuf.day)); - } else { - v = new QVariant(QDate()); - isNull = true; - } - break; } - case QVariant::Time: { - TIME_STRUCT tbuf; - r = SQLGetData(d->hStmt, - field + 1, - SQL_C_TIME, - (SQLPOINTER) &tbuf, - 0, - &lengthIndicator); - if ((r == SQL_SUCCESS || r == SQL_SUCCESS_WITH_INFO) && (lengthIndicator != SQL_NULL_DATA)) { - v = new QVariant(QTime(tbuf.hour, tbuf.minute, tbuf.second)); - } else { - v = new QVariant(QTime()); - isNull = true; - } - break; } - case QVariant::DateTime: { - TIMESTAMP_STRUCT dtbuf; - r = SQLGetData(d->hStmt, - field + 1, - SQL_C_TIMESTAMP, - (SQLPOINTER) &dtbuf, - 0, - &lengthIndicator); - if ((r == SQL_SUCCESS || r == SQL_SUCCESS_WITH_INFO) && (lengthIndicator != SQL_NULL_DATA)) { - v = new QVariant(QDateTime(QDate(dtbuf.year, dtbuf.month, dtbuf.day), - QTime(dtbuf.hour, dtbuf.minute, dtbuf.second, dtbuf.fraction / 1000000))); - } else { - v = new QVariant(QDateTime()); - isNull = true; - } - break; } - case QVariant::ByteArray: - v = new QVariant(qGetBinaryData(d->hStmt, field, lengthIndicator, isNull)); - break; - case QVariant::Double: - { - switch(numericalPrecisionPolicy()) { - case QSql::LowPrecisionInt32: - v = new QVariant(qGetIntData(d->hStmt, field, isNull)); - break; - case QSql::LowPrecisionInt64: - v = new QVariant((qint64) qGetBigIntData(d->hStmt, field, isNull)); - break; - case QSql::LowPrecisionDouble: - v = new QVariant(qGetDoubleData(d->hStmt, field, isNull)); - break; - case QSql::HighPrecision: - default: - // length + 1 for the comma - v = new QVariant(qGetStringData(d->hStmt, field, info.length() + 1, isNull)); - break; - } - break; - } - case QVariant::String: - default: - v = new QVariant(qGetStringData(d->hStmt, field, info.length(), isNull)); - break; - } - if (isNull) - *v = QVariant(info.type()); - d->valueCache[field] = v; - return *v; -} - -bool QDB2Result::isNull(int i) -{ - Q_D(const QDB2Result); - if (i >= d->valueCache.size()) - return true; - - if (d->valueCache[i]) - return d->valueCache[i]->isNull(); - return data(i).isNull(); -} - -int QDB2Result::numRowsAffected() -{ - Q_D(const QDB2Result); - SQLINTEGER affectedRowCount = 0; - SQLRETURN r = SQLRowCount(d->hStmt, &affectedRowCount); - if (r == SQL_SUCCESS || r == SQL_SUCCESS_WITH_INFO) - return affectedRowCount; - else - qSqlWarning(QLatin1String("QDB2Result::numRowsAffected: Unable to count affected rows"), d); - return -1; -} - -int QDB2Result::size() -{ - return -1; -} - -QSqlRecord QDB2Result::record() const -{ - Q_D(const QDB2Result); - if (isActive()) - return d->recInf; - return QSqlRecord(); -} - -bool QDB2Result::nextResult() -{ - Q_D(QDB2Result); - setActive(false); - setAt(QSql::BeforeFirstRow); - d->recInf.clear(); - d->emptyValueCache(); - setSelect(false); - - SQLRETURN r = SQLMoreResults(d->hStmt); - if (r != SQL_SUCCESS && r != SQL_SUCCESS_WITH_INFO) { - if (r != SQL_NO_DATA) { - setLastError(qMakeError(QCoreApplication::translate("QODBCResult", - "Unable to fetch last"), QSqlError::ConnectionError, d)); - } - return false; - } - - SQLSMALLINT fieldCount = 0; - r = SQLNumResultCols(d->hStmt, &fieldCount); - setSelect(fieldCount > 0); - for (int i = 0; i < fieldCount; ++i) - d->recInf.append(qMakeFieldInfo(d, i)); - - d->valueCache.resize(fieldCount); - d->valueCache.fill(NULL); - setActive(true); - - return true; -} - -void QDB2Result::virtual_hook(int id, void *data) -{ - QSqlResult::virtual_hook(id, data); -} - -void QDB2Result::detachFromResultSet() -{ - Q_D(QDB2Result); - if (d->hStmt) - SQLCloseCursor(d->hStmt); -} - -/************************************/ - -QDB2Driver::QDB2Driver(QObject* parent) - : QSqlDriver(*new QDB2DriverPrivate, parent) -{ -} - -QDB2Driver::QDB2Driver(Qt::HANDLE env, Qt::HANDLE con, QObject* parent) - : QSqlDriver(*new QDB2DriverPrivate, parent) -{ - Q_D(QDB2Driver); - d->hEnv = reinterpret_cast<intptr_t>(env); - d->hDbc = reinterpret_cast<intptr_t>(con); - if (env && con) { - setOpen(true); - setOpenError(false); - } -} - -QDB2Driver::~QDB2Driver() -{ - close(); -} - -bool QDB2Driver::open(const QString& db, const QString& user, const QString& password, const QString& host, int port, - const QString& connOpts) -{ - Q_D(QDB2Driver); - if (isOpen()) - close(); - SQLRETURN r; - r = SQLAllocHandle(SQL_HANDLE_ENV, - SQL_NULL_HANDLE, - &d->hEnv); - if (r != SQL_SUCCESS && r != SQL_SUCCESS_WITH_INFO) { - qSqlWarning(QLatin1String("QDB2Driver::open: Unable to allocate environment"), d); - setOpenError(true); - return false; - } - - r = SQLAllocHandle(SQL_HANDLE_DBC, - d->hEnv, - &d->hDbc); - if (r != SQL_SUCCESS && r != SQL_SUCCESS_WITH_INFO) { - qSqlWarning(QLatin1String("QDB2Driver::open: Unable to allocate connection"), d); - setOpenError(true); - return false; - } - - QString protocol; - // Set connection attributes - const QStringList opts(connOpts.split(QLatin1Char(';'), QString::SkipEmptyParts)); - for (int i = 0; i < opts.count(); ++i) { - const QString tmp(opts.at(i)); - int idx; - if ((idx = tmp.indexOf(QLatin1Char('='))) == -1) { - qWarning("QDB2Driver::open: Illegal connect option value '%s'", - tmp.toLocal8Bit().constData()); - continue; - } - - const QString opt(tmp.left(idx)); - const QString val(tmp.mid(idx + 1).simplified()); - - SQLUINTEGER v = 0; - r = SQL_SUCCESS; - if (opt == QLatin1String("SQL_ATTR_ACCESS_MODE")) { - if (val == QLatin1String("SQL_MODE_READ_ONLY")) { - v = SQL_MODE_READ_ONLY; - } else if (val == QLatin1String("SQL_MODE_READ_WRITE")) { - v = SQL_MODE_READ_WRITE; - } else { - qWarning("QDB2Driver::open: Unknown option value '%s'", - tmp.toLocal8Bit().constData()); - continue; - } - r = SQLSetConnectAttr(d->hDbc, SQL_ATTR_ACCESS_MODE, reinterpret_cast<SQLPOINTER>(v), 0); - } else if (opt == QLatin1String("SQL_ATTR_LOGIN_TIMEOUT")) { - v = val.toUInt(); - r = SQLSetConnectAttr(d->hDbc, SQL_ATTR_LOGIN_TIMEOUT, reinterpret_cast<SQLPOINTER>(v), 0); - } else if (opt.compare(QLatin1String("PROTOCOL"), Qt::CaseInsensitive) == 0) { - protocol = tmp; - } - else { - qWarning("QDB2Driver::open: Unknown connection attribute '%s'", - tmp.toLocal8Bit().constData()); - } - if (r != SQL_SUCCESS && r != SQL_SUCCESS_WITH_INFO) - qSqlWarning(QString::fromLatin1("QDB2Driver::open: " - "Unable to set connection attribute '%1'").arg(opt), d); - } - - if (protocol.isEmpty()) - protocol = QLatin1String("PROTOCOL=TCPIP"); - - if (port < 0 ) - port = 50000; - - QString connQStr; - connQStr = protocol + QLatin1String(";DATABASE=") + db + QLatin1String(";HOSTNAME=") + host - + QLatin1String(";PORT=") + QString::number(port) + QLatin1String(";UID=") + user - + QLatin1String(";PWD=") + password; - - - SQLTCHAR connOut[SQL_MAX_OPTION_STRING_LENGTH]; - SQLSMALLINT cb; - - r = SQLDriverConnect(d->hDbc, - NULL, - qToTChar(connQStr), - (SQLSMALLINT) connQStr.length(), - connOut, - SQL_MAX_OPTION_STRING_LENGTH, - &cb, - SQL_DRIVER_NOPROMPT); - if (r != SQL_SUCCESS && r != SQL_SUCCESS_WITH_INFO) { - setLastError(qMakeError(tr("Unable to connect"), - QSqlError::ConnectionError, d)); - setOpenError(true); - return false; - } - - d->user = user; - setOpen(true); - setOpenError(false); - return true; -} - -void QDB2Driver::close() -{ - Q_D(QDB2Driver); - SQLRETURN r; - if (d->hDbc) { - // Open statements/descriptors handles are automatically cleaned up by SQLDisconnect - if (isOpen()) { - r = SQLDisconnect(d->hDbc); - if (r != SQL_SUCCESS) - qSqlWarning(QLatin1String("QDB2Driver::close: Unable to disconnect datasource"), d); - } - r = SQLFreeHandle(SQL_HANDLE_DBC, d->hDbc); - if (r != SQL_SUCCESS) - qSqlWarning(QLatin1String("QDB2Driver::close: Unable to free connection handle"), d); - d->hDbc = 0; - } - - if (d->hEnv) { - r = SQLFreeHandle(SQL_HANDLE_ENV, d->hEnv); - if (r != SQL_SUCCESS) - qSqlWarning(QLatin1String("QDB2Driver::close: Unable to free environment handle"), d); - d->hEnv = 0; - } - setOpen(false); - setOpenError(false); -} - -QSqlResult *QDB2Driver::createResult() const -{ - return new QDB2Result(this); -} - -QSqlRecord QDB2Driver::record(const QString& tableName) const -{ - Q_D(const QDB2Driver); - QSqlRecord fil; - if (!isOpen()) - return fil; - - SQLHANDLE hStmt; - QString catalog, schema, table; - qSplitTableQualifier(tableName, &catalog, &schema, &table); - if (schema.isEmpty()) - schema = d->user; - - if (isIdentifierEscaped(catalog, QSqlDriver::TableName)) - catalog = stripDelimiters(catalog, QSqlDriver::TableName); - else - catalog = catalog.toUpper(); - - if (isIdentifierEscaped(schema, QSqlDriver::TableName)) - schema = stripDelimiters(schema, QSqlDriver::TableName); - else - schema = schema.toUpper(); - - if (isIdentifierEscaped(table, QSqlDriver::TableName)) - table = stripDelimiters(table, QSqlDriver::TableName); - else - table = table.toUpper(); - - SQLRETURN r = SQLAllocHandle(SQL_HANDLE_STMT, - d->hDbc, - &hStmt); - if (r != SQL_SUCCESS) { - qSqlWarning(QLatin1String("QDB2Driver::record: Unable to allocate handle"), d); - return fil; - } - - r = SQLSetStmtAttr(hStmt, - SQL_ATTR_CURSOR_TYPE, - (SQLPOINTER) SQL_CURSOR_FORWARD_ONLY, - SQL_IS_UINTEGER); - - - //Aside: szSchemaName and szTableName parameters of SQLColumns - //are case sensitive search patterns, so no escaping is used. - r = SQLColumns(hStmt, - NULL, - 0, - qToTChar(schema), - schema.length(), - qToTChar(table), - table.length(), - NULL, - 0); - - if (r != SQL_SUCCESS) - qSqlWarning(QLatin1String("QDB2Driver::record: Unable to execute column list"), d); - r = SQLFetchScroll(hStmt, - SQL_FETCH_NEXT, - 0); - while (r == SQL_SUCCESS) { - fil.append(qMakeFieldInfo(hStmt)); - r = SQLFetchScroll(hStmt, - SQL_FETCH_NEXT, - 0); - } - - r = SQLFreeHandle(SQL_HANDLE_STMT, hStmt); - if (r != SQL_SUCCESS) - qSqlWarning(QLatin1String("QDB2Driver: Unable to free statement handle ") - + QString::number(r), d); - - return fil; -} - -QStringList QDB2Driver::tables(QSql::TableType type) const -{ - Q_D(const QDB2Driver); - QStringList tl; - if (!isOpen()) - return tl; - - SQLHANDLE hStmt; - - SQLRETURN r = SQLAllocHandle(SQL_HANDLE_STMT, - d->hDbc, - &hStmt); - if (r != SQL_SUCCESS && r != SQL_SUCCESS_WITH_INFO) { - qSqlWarning(QLatin1String("QDB2Driver::tables: Unable to allocate handle"), d); - return tl; - } - r = SQLSetStmtAttr(hStmt, - SQL_ATTR_CURSOR_TYPE, - (SQLPOINTER)SQL_CURSOR_FORWARD_ONLY, - SQL_IS_UINTEGER); - - QString tableType; - if (type & QSql::Tables) - tableType += QLatin1String("TABLE,"); - if (type & QSql::Views) - tableType += QLatin1String("VIEW,"); - if (type & QSql::SystemTables) - tableType += QLatin1String("SYSTEM TABLE,"); - if (tableType.isEmpty()) - return tl; - tableType.chop(1); - - r = SQLTables(hStmt, - NULL, - 0, - NULL, - 0, - NULL, - 0, - qToTChar(tableType), - tableType.length()); - - if (r != SQL_SUCCESS && r != SQL_SUCCESS_WITH_INFO) - qSqlWarning(QLatin1String("QDB2Driver::tables: Unable to execute table list"), d); - r = SQLFetchScroll(hStmt, - SQL_FETCH_NEXT, - 0); - while (r == SQL_SUCCESS) { - bool isNull; - QString fieldVal = qGetStringData(hStmt, 2, -1, isNull); - QString userVal = qGetStringData(hStmt, 1, -1, isNull); - QString user = d->user; - if ( isIdentifierEscaped(user, QSqlDriver::TableName)) - user = stripDelimiters(user, QSqlDriver::TableName); - else - user = user.toUpper(); - - if (userVal != user) - fieldVal = userVal + QLatin1Char('.') + fieldVal; - tl.append(fieldVal); - r = SQLFetchScroll(hStmt, - SQL_FETCH_NEXT, - 0); - } - - r = SQLFreeHandle(SQL_HANDLE_STMT, hStmt); - if (r != SQL_SUCCESS) - qSqlWarning(QLatin1String("QDB2Driver::tables: Unable to free statement handle ") - + QString::number(r), d); - return tl; -} - -QSqlIndex QDB2Driver::primaryIndex(const QString& tablename) const -{ - Q_D(const QDB2Driver); - QSqlIndex index(tablename); - if (!isOpen()) - return index; - QSqlRecord rec = record(tablename); - - SQLHANDLE hStmt; - SQLRETURN r = SQLAllocHandle(SQL_HANDLE_STMT, - d->hDbc, - &hStmt); - if (r != SQL_SUCCESS) { - qSqlWarning(QLatin1String("QDB2Driver::primaryIndex: Unable to list primary key"), d); - return index; - } - QString catalog, schema, table; - qSplitTableQualifier(tablename, &catalog, &schema, &table); - - if (isIdentifierEscaped(catalog, QSqlDriver::TableName)) - catalog = stripDelimiters(catalog, QSqlDriver::TableName); - else - catalog = catalog.toUpper(); - - if (isIdentifierEscaped(schema, QSqlDriver::TableName)) - schema = stripDelimiters(schema, QSqlDriver::TableName); - else - schema = schema.toUpper(); - - if (isIdentifierEscaped(table, QSqlDriver::TableName)) - table = stripDelimiters(table, QSqlDriver::TableName); - else - table = table.toUpper(); - - r = SQLSetStmtAttr(hStmt, - SQL_ATTR_CURSOR_TYPE, - (SQLPOINTER)SQL_CURSOR_FORWARD_ONLY, - SQL_IS_UINTEGER); - - r = SQLPrimaryKeys(hStmt, - NULL, - 0, - qToTChar(schema), - schema.length(), - qToTChar(table), - table.length()); - r = SQLFetchScroll(hStmt, - SQL_FETCH_NEXT, - 0); - - bool isNull; - QString cName, idxName; - // Store all fields in a StringList because the driver can't detail fields in this FETCH loop - while (r == SQL_SUCCESS) { - cName = qGetStringData(hStmt, 3, -1, isNull); // column name - idxName = qGetStringData(hStmt, 5, -1, isNull); // pk index name - index.append(rec.field(cName)); - index.setName(idxName); - r = SQLFetchScroll(hStmt, - SQL_FETCH_NEXT, - 0); - } - r = SQLFreeHandle(SQL_HANDLE_STMT, hStmt); - if (r!= SQL_SUCCESS) - qSqlWarning(QLatin1String("QDB2Driver: Unable to free statement handle ") - + QString::number(r), d); - return index; -} - -bool QDB2Driver::hasFeature(DriverFeature f) const -{ - switch (f) { - case QuerySize: - case NamedPlaceholders: - case BatchOperations: - case LastInsertId: - case SimpleLocking: - case EventNotifications: - case CancelQuery: - return false; - case BLOB: - case Transactions: - case MultipleResultSets: - case PreparedQueries: - case PositionalPlaceholders: - case LowPrecisionNumbers: - case FinishQuery: - return true; - case Unicode: - return true; - } - return false; -} - -bool QDB2Driver::beginTransaction() -{ - if (!isOpen()) { - qWarning("QDB2Driver::beginTransaction: Database not open"); - return false; - } - return setAutoCommit(false); -} - -bool QDB2Driver::commitTransaction() -{ - Q_D(QDB2Driver); - if (!isOpen()) { - qWarning("QDB2Driver::commitTransaction: Database not open"); - return false; - } - SQLRETURN r = SQLEndTran(SQL_HANDLE_DBC, - d->hDbc, - SQL_COMMIT); - if (r != SQL_SUCCESS) { - setLastError(qMakeError(tr("Unable to commit transaction"), - QSqlError::TransactionError, d)); - return false; - } - return setAutoCommit(true); -} - -bool QDB2Driver::rollbackTransaction() -{ - Q_D(QDB2Driver); - if (!isOpen()) { - qWarning("QDB2Driver::rollbackTransaction: Database not open"); - return false; - } - SQLRETURN r = SQLEndTran(SQL_HANDLE_DBC, - d->hDbc, - SQL_ROLLBACK); - if (r != SQL_SUCCESS) { - setLastError(qMakeError(tr("Unable to rollback transaction"), - QSqlError::TransactionError, d)); - return false; - } - return setAutoCommit(true); -} - -bool QDB2Driver::setAutoCommit(bool autoCommit) -{ - Q_D(QDB2Driver); - SQLUINTEGER ac = autoCommit ? SQL_AUTOCOMMIT_ON : SQL_AUTOCOMMIT_OFF; - SQLRETURN r = SQLSetConnectAttr(d->hDbc, - SQL_ATTR_AUTOCOMMIT, - reinterpret_cast<SQLPOINTER>(ac), - sizeof(ac)); - if (r != SQL_SUCCESS) { - setLastError(qMakeError(tr("Unable to set autocommit"), - QSqlError::TransactionError, d)); - return false; - } - return true; -} - -QString QDB2Driver::formatValue(const QSqlField &field, bool trimStrings) const -{ - if (field.isNull()) - return QLatin1String("NULL"); - - switch (field.type()) { - case QVariant::DateTime: { - // Use an escape sequence for the datetime fields - if (field.value().toDateTime().isValid()) { - QDate dt = field.value().toDateTime().date(); - QTime tm = field.value().toDateTime().time(); - // Dateformat has to be "yyyy-MM-dd hh:mm:ss", with leading zeroes if month or day < 10 - return QLatin1Char('\'') + QString::number(dt.year()) + QLatin1Char('-') - + QString::number(dt.month()) + QLatin1Char('-') - + QString::number(dt.day()) + QLatin1Char('-') - + QString::number(tm.hour()) + QLatin1Char('.') - + QString::number(tm.minute()).rightJustified(2, QLatin1Char('0'), true) - + QLatin1Char('.') - + QString::number(tm.second()).rightJustified(2, QLatin1Char('0'), true) - + QLatin1Char('.') - + QString::number(tm.msec() * 1000).rightJustified(6, QLatin1Char('0'), true) - + QLatin1Char('\''); - } else { - return QLatin1String("NULL"); - } - } - case QVariant::ByteArray: { - QByteArray ba = field.value().toByteArray(); - QString res = QString::fromLatin1("BLOB(X'"); - static const char hexchars[] = "0123456789abcdef"; - for (int i = 0; i < ba.size(); ++i) { - uchar s = (uchar) ba[i]; - res += QLatin1Char(hexchars[s >> 4]); - res += QLatin1Char(hexchars[s & 0x0f]); - } - res += QLatin1String("')"); - return res; - } - default: - return QSqlDriver::formatValue(field, trimStrings); - } -} - -QVariant QDB2Driver::handle() const -{ - Q_D(const QDB2Driver); - return QVariant(qRegisterMetaType<SQLHANDLE>("SQLHANDLE"), &d->hDbc); -} - -QString QDB2Driver::escapeIdentifier(const QString &identifier, IdentifierType) const -{ - QString res = identifier; - if(!identifier.isEmpty() && !identifier.startsWith(QLatin1Char('"')) && !identifier.endsWith(QLatin1Char('"')) ) { - res.replace(QLatin1Char('"'), QLatin1String("\"\"")); - res.prepend(QLatin1Char('"')).append(QLatin1Char('"')); - res.replace(QLatin1Char('.'), QLatin1String("\".\"")); - } - return res; -} - -QT_END_NAMESPACE diff --git a/src/sql/drivers/db2/qsql_db2.pri b/src/sql/drivers/db2/qsql_db2.pri deleted file mode 100644 index c9e65e2c2e..0000000000 --- a/src/sql/drivers/db2/qsql_db2.pri +++ /dev/null @@ -1,8 +0,0 @@ -HEADERS += $$PWD/qsql_db2_p.h -SOURCES += $$PWD/qsql_db2.cpp - -unix { - !contains(LIBS, .*db2.*):LIBS += -ldb2 -} else { - !contains(LIBS, .*db2.*):LIBS += -ldb2cli -} diff --git a/src/sql/drivers/db2/qsql_db2_p.h b/src/sql/drivers/db2/qsql_db2_p.h deleted file mode 100644 index fa6d739479..0000000000 --- a/src/sql/drivers/db2/qsql_db2_p.h +++ /dev/null @@ -1,103 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2016 The Qt Company Ltd. -** Contact: https://www.qt.io/licensing/ -** -** This file is part of the QtSql module of the Qt Toolkit. -** -** $QT_BEGIN_LICENSE:LGPL$ -** Commercial License Usage -** Licensees holding valid commercial Qt licenses may use this file in -** accordance with the commercial license agreement provided with the -** Software or, alternatively, in accordance with the terms contained in -** a written agreement between you and The Qt Company. For licensing terms -** and conditions see https://www.qt.io/terms-conditions. For further -** information use the contact form at https://www.qt.io/contact-us. -** -** GNU Lesser General Public License Usage -** Alternatively, this file may be used under the terms of the GNU Lesser -** General Public License version 3 as published by the Free Software -** Foundation and appearing in the file LICENSE.LGPL3 included in the -** packaging of this file. Please review the following information to -** ensure the GNU Lesser General Public License version 3 requirements -** will be met: https://www.gnu.org/licenses/lgpl-3.0.html. -** -** GNU General Public License Usage -** Alternatively, this file may be used under the terms of the GNU -** General Public License version 2.0 or (at your option) the GNU General -** Public license version 3 or any later version approved by the KDE Free -** Qt Foundation. The licenses are as published by the Free Software -** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3 -** included in the packaging of this file. Please review the following -** information to ensure the GNU General Public License requirements will -** be met: https://www.gnu.org/licenses/gpl-2.0.html and -** https://www.gnu.org/licenses/gpl-3.0.html. -** -** $QT_END_LICENSE$ -** -****************************************************************************/ - -#ifndef QSQL_DB2_H -#define QSQL_DB2_H - -// -// W A R N I N G -// ------------- -// -// This file is not part of the Qt API. It exists purely as an -// implementation detail. This header file may change from version to -// version without notice, or even be removed. -// -// We mean it. -// - -#include <QtCore/qglobal.h> - -#ifdef QT_PLUGIN -#define Q_EXPORT_SQLDRIVER_DB2 -#else -#define Q_EXPORT_SQLDRIVER_DB2 Q_SQL_EXPORT -#endif - -#include <QtSql/qsqldriver.h> - -QT_BEGIN_NAMESPACE - -class QDB2DriverPrivate; - -class Q_EXPORT_SQLDRIVER_DB2 QDB2Driver : public QSqlDriver -{ - Q_DECLARE_PRIVATE(QDB2Driver) - Q_OBJECT - friend class QDB2ResultPrivate; - -public: - explicit QDB2Driver(QObject* parent = 0); - QDB2Driver(Qt::HANDLE env, Qt::HANDLE con, QObject* parent = 0); - ~QDB2Driver(); - bool hasFeature(DriverFeature) const Q_DECL_OVERRIDE; - void close() Q_DECL_OVERRIDE; - QSqlRecord record(const QString &tableName) const Q_DECL_OVERRIDE; - QStringList tables(QSql::TableType type) const Q_DECL_OVERRIDE; - QSqlResult *createResult() const Q_DECL_OVERRIDE; - QSqlIndex primaryIndex(const QString &tablename) const Q_DECL_OVERRIDE; - bool beginTransaction() Q_DECL_OVERRIDE; - bool commitTransaction() Q_DECL_OVERRIDE; - bool rollbackTransaction() Q_DECL_OVERRIDE; - QString formatValue(const QSqlField &field, bool trimStrings) const Q_DECL_OVERRIDE; - QVariant handle() const Q_DECL_OVERRIDE; - bool open(const QString &db, - const QString &user, - const QString &password, - const QString &host, - int port, - const QString& connOpts) Q_DECL_OVERRIDE; - QString escapeIdentifier(const QString &identifier, IdentifierType type) const Q_DECL_OVERRIDE; - -private: - bool setAutoCommit(bool autoCommit); -}; - -QT_END_NAMESPACE - -#endif // QSQL_DB2_H |