diff options
Diffstat (limited to 'src/sql/drivers/odbc/qsql_odbc.cpp')
-rw-r--r-- | src/sql/drivers/odbc/qsql_odbc.cpp | 175 |
1 files changed, 113 insertions, 62 deletions
diff --git a/src/sql/drivers/odbc/qsql_odbc.cpp b/src/sql/drivers/odbc/qsql_odbc.cpp index 8db06e6831..139b2a8f2b 100644 --- a/src/sql/drivers/odbc/qsql_odbc.cpp +++ b/src/sql/drivers/odbc/qsql_odbc.cpp @@ -1,31 +1,37 @@ /**************************************************************************** ** -** Copyright (C) 2015 The Qt Company Ltd. -** Contact: http://www.qt.io/licensing/ +** 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:LGPL21$ +** $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 http://www.qt.io/terms-conditions. For further -** information use the contact form at http://www.qt.io/contact-us. +** 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 2.1 or version 3 as published by the Free -** Software Foundation and appearing in the file LICENSE.LGPLv21 and -** LICENSE.LGPLv3 included in the packaging of this file. Please review the -** following information to ensure the GNU Lesser General Public License -** requirements will be met: https://www.gnu.org/licenses/lgpl.html and -** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** 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. ** -** As a special exception, The Qt Company gives you certain additional -** rights. These rights are described in The Qt Company LGPL Exception -** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** 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$ ** @@ -50,6 +56,7 @@ #include <QDebug> #include <QSqlQuery> #include <QtSql/private/qsqldriver_p.h> +#include <QtSql/private/qsqlresult_p.h> QT_BEGIN_NAMESPACE @@ -106,6 +113,8 @@ inline static QVarLengthArray<SQLTCHAR> toSQLTCHAR(const QString &input) class QODBCDriverPrivate : public QSqlDriverPrivate { + Q_DECLARE_PUBLIC(QODBCDriver) + public: enum DefaultCase{Lower, Mixed, Upper, Sensitive}; QODBCDriverPrivate() @@ -143,23 +152,62 @@ private: QChar quote; }; -class QODBCPrivate +class QODBCResultPrivate; + +class QODBCResult: public QSqlResult +{ + Q_DECLARE_PRIVATE(QODBCResult) + +public: + QODBCResult(const QODBCDriver *db); + virtual ~QODBCResult(); + + bool prepare(const QString &query) Q_DECL_OVERRIDE; + bool exec() Q_DECL_OVERRIDE; + + QVariant lastInsertId() const Q_DECL_OVERRIDE; + QVariant handle() const Q_DECL_OVERRIDE; + +protected: + bool fetchNext() Q_DECL_OVERRIDE; + bool fetchFirst() Q_DECL_OVERRIDE; + bool fetchLast() Q_DECL_OVERRIDE; + bool fetchPrevious() Q_DECL_OVERRIDE; + bool fetch(int i) Q_DECL_OVERRIDE; + bool reset(const QString &query) Q_DECL_OVERRIDE; + QVariant data(int field) Q_DECL_OVERRIDE; + bool isNull(int field) 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 QODBCResultPrivate: public QSqlResultPrivate { + Q_DECLARE_PUBLIC(QODBCResult) + public: - QODBCPrivate(QODBCDriverPrivate *dpp) - : hStmt(0), useSchema(false), hasSQLFetchScroll(true), driverPrivate(dpp), userForwardOnly(false) + Q_DECLARE_SQLDRIVER_PRIVATE(QODBCDriver) + QODBCResultPrivate(QODBCResult *q, const QODBCDriver *db) + : QSqlResultPrivate(q, db), + hStmt(0), + useSchema(false), + hasSQLFetchScroll(true) { - unicode = dpp->unicode; - useSchema = dpp->useSchema; - disconnectCount = dpp->disconnectCount; - hasSQLFetchScroll = dpp->hasSQLFetchScroll; + unicode = drv_d_func()->unicode; + useSchema = drv_d_func()->useSchema; + disconnectCount = drv_d_func()->disconnectCount; + hasSQLFetchScroll = drv_d_func()->hasSQLFetchScroll; } inline void clearValues() { fieldCache.fill(QVariant()); fieldCacheIdx = 0; } - SQLHANDLE dpEnv() const { return driverPrivate ? driverPrivate->hEnv : 0;} - SQLHANDLE dpDbc() const { return driverPrivate ? driverPrivate->hDbc : 0;} + SQLHANDLE dpEnv() const { return drv_d_func() ? drv_d_func()->hEnv : 0;} + SQLHANDLE dpDbc() const { return drv_d_func() ? drv_d_func()->hDbc : 0;} SQLHANDLE hStmt; bool unicode; @@ -170,23 +218,19 @@ public: int fieldCacheIdx; int disconnectCount; bool hasSQLFetchScroll; - QODBCDriverPrivate *driverPrivate; - bool userForwardOnly; - bool isStmtHandleValid(const QSqlDriver *driver); - void updateStmtHandleState(const QSqlDriver *driver); + bool isStmtHandleValid(); + void updateStmtHandleState(); }; -bool QODBCPrivate::isStmtHandleValid(const QSqlDriver *driver) +bool QODBCResultPrivate::isStmtHandleValid() { - const QODBCDriver *odbcdriver = static_cast<const QODBCDriver*> (driver); - return disconnectCount == odbcdriver->d_func()->disconnectCount; + return disconnectCount == drv_d_func()->disconnectCount; } -void QODBCPrivate::updateStmtHandleState(const QSqlDriver *driver) +void QODBCResultPrivate::updateStmtHandleState() { - const QODBCDriver *odbcdriver = static_cast<const QODBCDriver*> (driver); - disconnectCount = odbcdriver->d_func()->disconnectCount; + disconnectCount = drv_d_func()->disconnectCount; } static QString qWarnODBCHandle(int handleType, SQLHANDLE handle, int *nativeCode = 0) @@ -261,7 +305,7 @@ static QString qODBCWarn(const SQLHANDLE hStmt, const SQLHANDLE envHandle = 0, return result; } -static QString qODBCWarn(const QODBCPrivate* odbc, int *nativeCode = 0) +static QString qODBCWarn(const QODBCResultPrivate* odbc, int *nativeCode = 0) { return qODBCWarn(odbc->hStmt, odbc->dpEnv(), odbc->dpDbc(), nativeCode); } @@ -271,7 +315,7 @@ static QString qODBCWarn(const QODBCDriverPrivate* odbc, int *nativeCode = 0) return qODBCWarn(0, odbc->hEnv, odbc->hDbc, nativeCode); } -static void qSqlWarning(const QString& message, const QODBCPrivate* odbc) +static void qSqlWarning(const QString& message, const QODBCResultPrivate* odbc) { qWarning() << message << "\tError:" << qODBCWarn(odbc); } @@ -286,7 +330,7 @@ static void qSqlWarning(const QString &message, const SQLHANDLE hStmt) qWarning() << message << "\tError:" << qODBCWarn(hStmt); } -static QSqlError qMakeError(const QString& err, QSqlError::ErrorType type, const QODBCPrivate* p) +static QSqlError qMakeError(const QString& err, QSqlError::ErrorType type, const QODBCResultPrivate* p) { int nativeCode = -1; QString message = qODBCWarn(p, &nativeCode); @@ -626,7 +670,7 @@ static QSqlField qMakeFieldInfo(const SQLHANDLE hStmt, const QODBCDriverPrivate* return f; } -static QSqlField qMakeFieldInfo(const QODBCPrivate* p, int i ) +static QSqlField qMakeFieldInfo(const QODBCResultPrivate* p, int i ) { QString errorMessage; const QSqlField result = qMakeFieldInfo(p->hStmt, i, &errorMessage); @@ -911,26 +955,25 @@ QString QODBCDriverPrivate::adjustCase(const QString &identifier) const //////////////////////////////////////////////////////////////////////////// -QODBCResult::QODBCResult(const QODBCDriver * db, QODBCDriverPrivate* p) -: QSqlResult(db) +QODBCResult::QODBCResult(const QODBCDriver *db) + : QSqlResult(*new QODBCResultPrivate(this, db)) { - d = new QODBCPrivate(p); } QODBCResult::~QODBCResult() { - if (d->hStmt && d->isStmtHandleValid(driver()) && driver()->isOpen()) { + Q_D(QODBCResult); + if (d->hStmt && d->isStmtHandleValid() && driver()->isOpen()) { SQLRETURN r = SQLFreeHandle(SQL_HANDLE_STMT, d->hStmt); if (r != SQL_SUCCESS) qSqlWarning(QLatin1String("QODBCDriver: Unable to free statement handle ") + QString::number(r), d); } - - delete d; } bool QODBCResult::reset (const QString& query) { + Q_D(QODBCResult); setActive(false); setAt(QSql::BeforeFirstRow); d->rInf.clear(); @@ -940,7 +983,7 @@ bool QODBCResult::reset (const QString& query) // Always reallocate the statement handle - the statement attributes // are not reset if SQLFreeStmt() is called which causes some problems. SQLRETURN r; - if (d->hStmt && d->isStmtHandleValid(driver())) { + if (d->hStmt && d->isStmtHandleValid()) { r = SQLFreeHandle(SQL_HANDLE_STMT, d->hStmt); if (r != SQL_SUCCESS) { qSqlWarning(QLatin1String("QODBCResult::reset: Unable to free statement handle"), d); @@ -955,9 +998,9 @@ bool QODBCResult::reset (const QString& query) return false; } - d->updateStmtHandleState(driver()); + d->updateStmtHandleState(); - if (d->userForwardOnly) { + if (isForwardOnly()) { r = SQLSetStmtAttr(d->hStmt, SQL_ATTR_CURSOR_TYPE, (SQLPOINTER)SQL_CURSOR_FORWARD_ONLY, @@ -987,7 +1030,7 @@ bool QODBCResult::reset (const QString& query) SQLULEN isScrollable = 0; r = SQLGetStmtAttr(d->hStmt, SQL_ATTR_CURSOR_SCROLLABLE, &isScrollable, SQL_IS_INTEGER, 0); if(r == SQL_SUCCESS || r == SQL_SUCCESS_WITH_INFO) - QSqlResult::setForwardOnly(isScrollable==SQL_NONSCROLLABLE); + setForwardOnly(isScrollable == SQL_NONSCROLLABLE); SQLSMALLINT count = 0; SQLNumResultCols(d->hStmt, &count); @@ -1007,6 +1050,7 @@ bool QODBCResult::reset (const QString& query) bool QODBCResult::fetch(int i) { + Q_D(QODBCResult); if (!driver()->isOpen()) return false; @@ -1043,6 +1087,7 @@ bool QODBCResult::fetch(int i) bool QODBCResult::fetchNext() { + Q_D(QODBCResult); SQLRETURN r; d->clearValues(); @@ -1065,6 +1110,7 @@ bool QODBCResult::fetchNext() bool QODBCResult::fetchFirst() { + Q_D(QODBCResult); if (isForwardOnly() && at() != QSql::BeforeFirstRow) return false; SQLRETURN r; @@ -1087,6 +1133,7 @@ bool QODBCResult::fetchFirst() bool QODBCResult::fetchPrevious() { + Q_D(QODBCResult); if (isForwardOnly()) return false; SQLRETURN r; @@ -1106,6 +1153,7 @@ bool QODBCResult::fetchPrevious() bool QODBCResult::fetchLast() { + Q_D(QODBCResult); SQLRETURN r; d->clearValues(); @@ -1145,6 +1193,7 @@ bool QODBCResult::fetchLast() QVariant QODBCResult::data(int field) { + Q_D(QODBCResult); if (field >= d->rInf.count() || field < 0) { qWarning() << "QODBCResult::data: column" << field << "out of range"; return QVariant(); @@ -1245,6 +1294,7 @@ QVariant QODBCResult::data(int field) bool QODBCResult::isNull(int field) { + Q_D(const QODBCResult); if (field < 0 || field > d->fieldCache.size()) return true; if (field <= d->fieldCacheIdx) { @@ -1263,6 +1313,7 @@ int QODBCResult::size() int QODBCResult::numRowsAffected() { + Q_D(QODBCResult); SQLLEN affectedRowCount = 0; SQLRETURN r = SQLRowCount(d->hStmt, &affectedRowCount); if (r == SQL_SUCCESS) @@ -1274,12 +1325,13 @@ int QODBCResult::numRowsAffected() bool QODBCResult::prepare(const QString& query) { + Q_D(QODBCResult); setActive(false); setAt(QSql::BeforeFirstRow); SQLRETURN r; d->rInf.clear(); - if (d->hStmt && d->isStmtHandleValid(driver())) { + if (d->hStmt && d->isStmtHandleValid()) { r = SQLFreeHandle(SQL_HANDLE_STMT, d->hStmt); if (r != SQL_SUCCESS) { qSqlWarning(QLatin1String("QODBCResult::prepare: Unable to close statement"), d); @@ -1294,9 +1346,9 @@ bool QODBCResult::prepare(const QString& query) return false; } - d->updateStmtHandleState(driver()); + d->updateStmtHandleState(); - if (d->userForwardOnly) { + if (isForwardOnly()) { r = SQLSetStmtAttr(d->hStmt, SQL_ATTR_CURSOR_TYPE, (SQLPOINTER)SQL_CURSOR_FORWARD_ONLY, @@ -1328,6 +1380,7 @@ bool QODBCResult::prepare(const QString& query) bool QODBCResult::exec() { + Q_D(QODBCResult); setActive(false); setAt(QSql::BeforeFirstRow); d->rInf.clear(); @@ -1408,7 +1461,7 @@ bool QODBCResult::exec() dt->minute = qdt.time().minute(); dt->second = qdt.time().second(); - int precision = d->driverPrivate->datetime_precision - 20; // (20 includes a separating period) + int precision = d->drv_d_func()->datetime_precision - 20; // (20 includes a separating period) if (precision <= 0) { dt->fraction = 0; } else { @@ -1424,7 +1477,7 @@ bool QODBCResult::exec() qParamType[bindValueType(i) & QSql::InOut], SQL_C_TIMESTAMP, SQL_TIMESTAMP, - d->driverPrivate->datetime_precision, + d->drv_d_func()->datetime_precision, precision, (void *) dt, 0, @@ -1608,7 +1661,7 @@ bool QODBCResult::exec() SQLULEN isScrollable = 0; r = SQLGetStmtAttr(d->hStmt, SQL_ATTR_CURSOR_SCROLLABLE, &isScrollable, SQL_IS_INTEGER, 0); if(r == SQL_SUCCESS || r == SQL_SUCCESS_WITH_INFO) - QSqlResult::setForwardOnly(isScrollable==SQL_NONSCROLLABLE); + setForwardOnly(isScrollable == SQL_NONSCROLLABLE); SQLSMALLINT count = 0; SQLNumResultCols(d->hStmt, &count); @@ -1677,6 +1730,7 @@ bool QODBCResult::exec() QSqlRecord QODBCResult::record() const { + Q_D(const QODBCResult); if (!isActive() || !isSelect()) return QSqlRecord(); return d->rInf; @@ -1684,9 +1738,10 @@ QSqlRecord QODBCResult::record() const QVariant QODBCResult::lastInsertId() const { + Q_D(const QODBCResult); QString sql; - switch (d->driverPrivate->dbmsType) { + switch (driver()->dbmsType()) { case QSqlDriver::MSSqlServer: case QSqlDriver::Sybase: sql = QLatin1String("SELECT @@IDENTITY;"); @@ -1716,11 +1771,13 @@ QVariant QODBCResult::lastInsertId() const QVariant QODBCResult::handle() const { + Q_D(const QODBCResult); return QVariant(qRegisterMetaType<SQLHANDLE>("SQLHANDLE"), &d->hStmt); } bool QODBCResult::nextResult() { + Q_D(QODBCResult); setActive(false); setAt(QSql::BeforeFirstRow); d->rInf.clear(); @@ -1765,16 +1822,11 @@ void QODBCResult::virtual_hook(int id, void *data) void QODBCResult::detachFromResultSet() { + Q_D(QODBCResult); if (d->hStmt) SQLCloseCursor(d->hStmt); } -void QODBCResult::setForwardOnly(bool forward) -{ - d->userForwardOnly = forward; - QSqlResult::setForwardOnly(forward); -} - //////////////////////////////////////// @@ -2185,8 +2237,7 @@ void QODBCDriverPrivate::checkDateTimePrecision() QSqlResult *QODBCDriver::createResult() const { - Q_D(const QODBCDriver); - return new QODBCResult(this, const_cast<QODBCDriverPrivate*>(d)); + return new QODBCResult(this); } bool QODBCDriver::beginTransaction() |