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

📄 qsql_odbc.cpp

📁 qt-x11-opensource-src-4.1.4.tar.gz源码
💻 CPP
📖 第 1 页 / 共 5 页
字号:
/******************************************************************************** Copyright (C) 1992-2006 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://www.trolltech.com/products/qt/opensource.html**** If you are unsure which license is appropriate for your use, please** review the following information:** http://www.trolltech.com/products/qt/licensing.html or contact the** sales department at sales@trolltech.com.**** 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 = 255;//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)    {        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;    bool checkDriver() const;    void checkUnicode();    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;};static QString qWarnODBCHandle(int handleType, SQLHANDLE handle, int *nativeCode = 0){    SQLINTEGER nativeCode_ = 0;    SQLSMALLINT msgLen = 0;    SQLRETURN r = SQL_ERROR;    SQLTCHAR state_[SQL_SQLSTATE_SIZE+1];    SQLTCHAR description_[SQL_MAX_MESSAGE_LENGTH + 1];    description_[0] = 0;    r = SQLGetDiagRec(handleType,                         handle,                         1,                         (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_;#ifdef UNICODE        return QString((const QChar*)description_, msgLen);#else        return QString::fromLocal8Bit((const char*)description_);#endif    }    return QString();}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){    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 = QVariant::Int;        break;    case SQL_BIGINT:        type = QVariant::LongLong;        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);    ulong read = 0;    while (true) {        r = SQLGetData(hStmt,                        column+1,                        SQL_C_BINARY,                        (SQLPOINTER)(fieldVal.constData() + read),                        colSize,                        &lengthIndicator);        if (r != SQL_SUCCESS && r != SQL_SUCCESS_WITH_INFO)            break;        if (lengthIndicator == SQL_NULL_DATA)            return QVariant(QVariant::ByteArray);        if (lengthIndicator > QSQLLEN(colSize) || lengthIndicator == SQL_NO_TOTAL) {            read += colSize;            colSize = 65536;        } else {            read += lengthIndicator;        }        if (r == SQL_SUCCESS) { // the whole field was read in one chunk            fieldVal.resize(read);            break;        }        fieldVal.resize(fieldVal.size() + colSize);    }    return fieldVal;}static QVariant qGetIntData(SQLHANDLE hStmt, int column){    SQLINTEGER intbuf = 0;    QSQLLEN 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) {        return QVariant(QVariant::Int);    }    return QVariant(int(intbuf));}

⌨️ 快捷键说明

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