⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 qsql_odbc.cpp

📁 奇趣公司比较新的qt/emd版本
💻 CPP
📖 第 1 页 / 共 5 页
字号:
/******************************************************************************** Copyright (C) 1992-2007 Trolltech ASA. All rights reserved.**** This file is part of the QtSql module of the Qt Toolkit.**** This file may be used under the terms of the GNU General Public** License version 2.0 as published by the Free Software Foundation** and appearing in the file LICENSE.GPL included in the packaging of** this file.  Please review the following information to ensure GNU** General Public Licensing requirements will be met:** http://trolltech.com/products/qt/licenses/licensing/opensource/**** If you are unsure which license is appropriate for your use, please** review the following information:** http://trolltech.com/products/qt/licenses/licensing/licensingoverview** or contact the sales department at sales@trolltech.com.**** In addition, as a special exception, Trolltech gives you certain** additional rights. These rights are described in the Trolltech GPL** Exception version 1.0, which can be found at** http://www.trolltech.com/products/qt/gplexception/ and in the file** GPL_EXCEPTION.txt in this package.**** In addition, as a special exception, Trolltech, as the sole copyright** holder for Qt Designer, grants users of the Qt/Eclipse Integration** plug-in the right for the Qt/Eclipse Integration to link to** functionality provided by Qt Designer and its related libraries.**** Trolltech reserves all rights not expressly granted herein.**** This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE** WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.******************************************************************************/#include "qsql_odbc.h"#include <qsqlrecord.h>#if defined (Q_OS_WIN32)#include <qt_windows.h>#endif#include <qcoreapplication.h>#include <qvariant.h>#include <qdatetime.h>#include <qsqlerror.h>#include <qsqlfield.h>#include <qsqlindex.h>#include <qstringlist.h>#include <qvarlengtharray.h>#include <qvector.h>#include <string.h>// undefine this to prevent initial check of the ODBC driver#define ODBC_CHECK_DRIVER#if defined(Q_ODBC_VERSION_2)//crude hack to get non-unicode capable driver managers to work# undef UNICODE# define SQLTCHAR SQLCHAR# define SQL_C_WCHAR SQL_C_CHAR#endif// newer platform SDKs use SQLLEN instead of SQLINTEGER#if defined(SQLLEN) || defined(Q_OS_WIN64)# define QSQLLEN SQLLEN#else# define QSQLLEN SQLINTEGER#endif#if defined(SQLULEN) || defined(Q_OS_WIN64)# define QSQLULEN SQLULEN#else# define QSQLULEN SQLUINTEGER#endifstatic const int COLNAMESIZE = 256;//Map Qt parameter types to ODBC typesstatic const SQLSMALLINT qParamType[4] = { SQL_PARAM_INPUT, SQL_PARAM_INPUT, SQL_PARAM_OUTPUT, SQL_PARAM_INPUT_OUTPUT };class QODBCDriverPrivate{public:    QODBCDriverPrivate()    : hEnv(0), hDbc(0), useSchema(false), disconnectCount(0), isMySqlServer(false)    {        sql_char_type = sql_varchar_type = sql_longvarchar_type = QVariant::ByteArray;        unicode = false;    }    SQLHANDLE hEnv;    SQLHANDLE hDbc;    uint unicode :1;    uint useSchema :1;    QVariant::Type sql_char_type;    QVariant::Type sql_varchar_type;    QVariant::Type sql_longvarchar_type;    int disconnectCount;    bool isMySqlServer;    bool checkDriver() const;    void checkUnicode();    void checkMySqlServer();    void checkSchemaUsage();    bool setConnectionOptions(const QString& connOpts);    void splitTableQualifier(const QString &qualifier, QString &catalog,                             QString &schema, QString &table);};class QODBCPrivate{public:    QODBCPrivate()    : hEnv(0), hDbc(0), hStmt(0), useSchema(false)    {        sql_char_type = sql_varchar_type = sql_longvarchar_type = QVariant::ByteArray;        unicode = false;    }    inline void clearValues()    { fieldCache.fill(QVariant()); fieldCacheIdx = 0; }    SQLHANDLE hEnv;    SQLHANDLE hDbc;    SQLHANDLE hStmt;    uint unicode :1;    uint useSchema :1;    QVariant::Type sql_char_type;    QVariant::Type sql_varchar_type;    QVariant::Type sql_longvarchar_type;    QSqlRecord rInf;    QVector<QVariant> fieldCache;    int fieldCacheIdx;    int disconnectCount;    bool isStmtHandleValid(const QSqlDriver *driver);    void updateStmtHandleState(const QSqlDriver *driver);};bool QODBCPrivate::isStmtHandleValid(const QSqlDriver *driver){    const QODBCDriver *odbcdriver = static_cast<const QODBCDriver*> (driver);    return disconnectCount == odbcdriver->d->disconnectCount;}void QODBCPrivate::updateStmtHandleState(const QSqlDriver *driver){    const QODBCDriver *odbcdriver = static_cast<const QODBCDriver*> (driver);    disconnectCount = odbcdriver->d->disconnectCount;}static QString qWarnODBCHandle(int handleType, SQLHANDLE handle, int *nativeCode = 0){    SQLINTEGER nativeCode_ = 0;    SQLSMALLINT msgLen = 0;    SQLRETURN r = SQL_NO_DATA;    SQLTCHAR state_[SQL_SQLSTATE_SIZE+1];    SQLTCHAR description_[SQL_MAX_MESSAGE_LENGTH + 1];    QString result;    int i = 1;    description_[0] = 0;    do {    r = SQLGetDiagRec(handleType,                         handle,                         i,                         (SQLTCHAR*)state_,                         &nativeCode_,                         (SQLTCHAR*)description_,                         SQL_MAX_MESSAGE_LENGTH, /* in bytes, not in characters */                         &msgLen);    description_[SQL_MAX_MESSAGE_LENGTH] = 0;    if (r == SQL_SUCCESS || r == SQL_SUCCESS_WITH_INFO) {        if (nativeCode)            *nativeCode = nativeCode_;            if (i != 1)                result += QLatin1Char(' ');#ifdef UNICODE            result += QString((const QChar*)description_, msgLen);#else            result += QString::fromLocal8Bit((const char*)description_);#endif        } else if (r == SQL_ERROR || r == SQL_INVALID_HANDLE) {            return result;    }        ++i;    } while (r != SQL_NO_DATA);    return result;}static QString qODBCWarn(const QODBCPrivate* odbc, int *nativeCode = 0){    return (qWarnODBCHandle(SQL_HANDLE_ENV, odbc->hEnv) + QLatin1String(" ")             + qWarnODBCHandle(SQL_HANDLE_DBC, odbc->hDbc) + QLatin1String(" ")             + qWarnODBCHandle(SQL_HANDLE_STMT, odbc->hStmt, nativeCode));}static QString qODBCWarn(const QODBCDriverPrivate* odbc, int *nativeCode = 0){    return (qWarnODBCHandle(SQL_HANDLE_ENV, odbc->hEnv) + QLatin1String(" ")             + qWarnODBCHandle(SQL_HANDLE_DBC, odbc->hDbc, nativeCode));}static void qSqlWarning(const QString& message, const QODBCPrivate* odbc){    qWarning("%s\tError: %s", message.toLocal8Bit().constData(),             qODBCWarn(odbc).toLocal8Bit().constData());}static void qSqlWarning(const QString &message, const QODBCDriverPrivate *odbc){    qWarning("%s\tError: %s", message.toLocal8Bit().constData(),             qODBCWarn(odbc).toLocal8Bit().constData());}static QSqlError qMakeError(const QString& err, QSqlError::ErrorType type, const QODBCPrivate* p){    int nativeCode = -1;    QString message = qODBCWarn(p, &nativeCode);    return QSqlError(QLatin1String("QODBC3: ") + err, message, type, nativeCode);}static QSqlError qMakeError(const QString& err, QSqlError::ErrorType type,                            const QODBCDriverPrivate* p){    int nativeCode = -1;    QString message = qODBCWarn(p, &nativeCode);    return QSqlError(QLatin1String("QODBC3: ") + err, qODBCWarn(p), type, nativeCode);}template<class T>static QVariant::Type qDecodeODBCType(SQLSMALLINT sqltype, const T* p, bool isSigned = true){    QVariant::Type type = QVariant::Invalid;    switch (sqltype) {    case SQL_DECIMAL:    case SQL_NUMERIC:    case SQL_REAL:    case SQL_FLOAT:    case SQL_DOUBLE:        type = QVariant::Double;        break;    case SQL_SMALLINT:    case SQL_INTEGER:    case SQL_BIT:    case SQL_TINYINT:        type = isSigned ? QVariant::Int : QVariant::UInt;        break;    case SQL_BIGINT:        type = isSigned ? QVariant::LongLong : QVariant::ULongLong;        break;    case SQL_BINARY:    case SQL_VARBINARY:    case SQL_LONGVARBINARY:        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;#ifndef Q_ODBC_VERSION_2    case SQL_WCHAR:    case SQL_WVARCHAR:    case SQL_WLONGVARCHAR:        type = QVariant::String;        break;#endif    case SQL_CHAR:        type = p->sql_char_type;        break;    case SQL_VARCHAR:        type = p->sql_varchar_type;        break;    case SQL_LONGVARCHAR:        type = p->sql_longvarchar_type;        break;    default:        type = QVariant::ByteArray;        break;    }    return type;}static QString qGetStringData(SQLHANDLE hStmt, int column, int colSize, bool unicode = false){    QString fieldVal;    SQLRETURN r = SQL_ERROR;    QSQLLEN lengthIndicator = 0;    // NB! colSize must be a multiple of 2 for unicode enabled DBs    if (colSize <= 0) {        colSize = 256;    } 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        if (unicode) {            colSize *= 2; // a tiny bit faster, since it saves a SQLGetData() call        }    }    char* buf = new char[colSize];    while (true) {        r = SQLGetData(hStmt,                        column+1,                        unicode ? SQL_C_WCHAR : SQL_C_CHAR,                        (SQLPOINTER)buf,                        colSize,                        &lengthIndicator);        if (r == SQL_SUCCESS || r == SQL_SUCCESS_WITH_INFO) {            if (lengthIndicator == SQL_NULL_DATA || lengthIndicator == SQL_NO_TOTAL) {                fieldVal = QString();                break;            }            // if SQL_SUCCESS_WITH_INFO is returned, indicating that            // more data can be fetched, the length indicator does NOT            // contain the number of bytes returned - it contains the            // total number of bytes that CAN be fetched            // 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);            } else {                buf[rSize] = 0;                fieldVal += QString::fromAscii(buf);            }            if (lengthIndicator < colSize) {                // workaround for Drivermanagers that don't return SQL_NO_DATA                break;            }        } else if (r == SQL_NO_DATA) {            break;        } else {            qWarning("qGetStringData: Error while fetching data (%d)", r);            fieldVal = QString();            break;        }    }    delete[] buf;    return fieldVal;}static QVariant qGetBinaryData(SQLHANDLE hStmt, int column){    QByteArray fieldVal;    SQLSMALLINT colNameLen;    SQLSMALLINT colType;    QSQLULEN colSize;    SQLSMALLINT colScale;    SQLSMALLINT nullable;    QSQLLEN lengthIndicator = 0;    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;    fieldVal.resize(colSize);

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -