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

📄 qsql_sqlite.cpp

📁 奇趣公司比较新的qt/emd版本
💻 CPP
📖 第 1 页 / 共 2 页
字号:
/******************************************************************************** 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_sqlite.h"#include <qcoreapplication.h>#include <qvariant.h>#include <qsqlerror.h>#include <qsqlfield.h>#include <qsqlindex.h>#include <qsqlquery.h>#include <qstringlist.h>#include <qvector.h>#include <qdebug.h>#if defined Q_OS_WIN# include <qt_windows.h>#else# include <unistd.h>#endif#include <sqlite3.h>Q_DECLARE_METATYPE(sqlite3*)Q_DECLARE_METATYPE(sqlite3_stmt*)static QVariant::Type qGetColumnType(const QString &tpName){    const QString typeName = tpName.toLower();    if (typeName == QLatin1String("integer")        || typeName == QLatin1String("int"))        return QVariant::Int;    if (typeName == QLatin1String("double")        || typeName == QLatin1String("float")        || typeName.startsWith(QLatin1String("numeric")))        return QVariant::Double;    if (typeName == QLatin1String("blob"))        return QVariant::ByteArray;    return QVariant::String;}static QSqlError qMakeError(sqlite3 *access, const QString &descr, QSqlError::ErrorType type,                            int errorCode = -1){    return QSqlError(descr,                     QString::fromUtf16(static_cast<const ushort *>(sqlite3_errmsg16(access))),                     type, errorCode);}class QSQLiteDriverPrivate{public:    inline QSQLiteDriverPrivate() : access(0) {}    sqlite3 *access;};class QSQLiteResultPrivate{public:    QSQLiteResultPrivate(QSQLiteResult *res);    void cleanup();    bool fetchNext(QSqlCachedResult::ValueCache &values, int idx, bool initialFetch);    // initializes the recordInfo and the cache    void initColumns(bool emptyResultset);    void finalize();    QSQLiteResult* q;    sqlite3 *access;    sqlite3_stmt *stmt;    uint skippedStatus: 1; // the status of the fetchNext() that's skipped    uint skipRow: 1; // skip the next fetchNext()?    uint utf8: 1;    QSqlRecord rInf;};static const uint initial_cache_size = 128;QSQLiteResultPrivate::QSQLiteResultPrivate(QSQLiteResult* res) : q(res), access(0),    stmt(0), skippedStatus(false), skipRow(false), utf8(false){}void QSQLiteResultPrivate::cleanup(){    finalize();    rInf.clear();    skippedStatus = false;    skipRow = false;    q->setAt(QSql::BeforeFirstRow);    q->setActive(false);    q->cleanup();}void QSQLiteResultPrivate::finalize(){    if (!stmt)        return;    sqlite3_finalize(stmt);    stmt = 0;}void QSQLiteResultPrivate::initColumns(bool emptyResultset){    int nCols = sqlite3_column_count(stmt);    if (nCols <= 0)        return;    q->init(nCols);    for (int i = 0; i < nCols; ++i) {        QString colName = QString::fromUtf16(                    static_cast<const ushort *>(sqlite3_column_name16(stmt, i))                    ).remove(QLatin1Char('"'));        // must use typeName for resolving the type to match QSqliteDriver::record        QString typeName = QString::fromUtf16(                    static_cast<const ushort *>(sqlite3_column_decltype16(stmt, i)));        int dotIdx = colName.lastIndexOf(QLatin1Char('.'));        QSqlField fld(colName.mid(dotIdx == -1 ? 0 : dotIdx + 1), qGetColumnType(typeName));        // sqlite3_column_type is documented to have undefined behavior if the result set is empty        int stp = emptyResultset ? -1 : sqlite3_column_type(stmt, i);        fld.setSqlType(stp);        rInf.append(fld);    }}bool QSQLiteResultPrivate::fetchNext(QSqlCachedResult::ValueCache &values, int idx, bool initialFetch){    int res;    int i;    if (skipRow) {        // already fetched        Q_ASSERT(!initialFetch);        skipRow = false;        return skippedStatus;    }    skipRow = initialFetch;    res = sqlite3_step(stmt);    switch(res) {    case SQLITE_ROW:        // check to see if should fill out columns        if (rInf.isEmpty())            // must be first call.            initColumns(false);        if (idx < 0 && !initialFetch)            return true;        for (i = 0; i < rInf.count(); ++i) {            switch (sqlite3_column_type(stmt, i)) {            case SQLITE_BLOB:                values[i + idx] = QByteArray(static_cast<const char *>(                            sqlite3_column_blob(stmt, i)),                            sqlite3_column_bytes(stmt, i));                break;            case SQLITE_INTEGER:                values[i + idx] = sqlite3_column_int64(stmt, i);                break;            case SQLITE_FLOAT:                values[i + idx] = sqlite3_column_double(stmt, i);                break;            case SQLITE_NULL:                values[i + idx] = QVariant(QVariant::String);                break;            default:                values[i + idx] = QString::fromUtf16(static_cast<const ushort *>(                            sqlite3_column_text16(stmt, i)),                            sqlite3_column_bytes16(stmt, i) / sizeof(ushort));                break;            }        }        return true;    case SQLITE_DONE:        if (rInf.isEmpty())            // must be first call.            initColumns(true);        q->setAt(QSql::AfterLastRow);        sqlite3_reset(stmt);        return false;    case SQLITE_ERROR:        // SQLITE_ERROR is a generic error code and we must call sqlite3_reset()        // to get the specific error message.        res = sqlite3_reset(stmt);        q->setLastError(qMakeError(access, QCoreApplication::translate("QSQLiteResult",                        "Unable to fetch row"), QSqlError::ConnectionError, res));        q->setAt(QSql::AfterLastRow);        return false;    case SQLITE_MISUSE:    case SQLITE_BUSY:    default:        // something wrong, don't get col info, but still return false        q->setLastError(qMakeError(access, QCoreApplication::translate("QSQLiteResult",                        "Unable to fetch row"), QSqlError::ConnectionError, res));        sqlite3_reset(stmt);        q->setAt(QSql::AfterLastRow);        return false;    }    return false;}QSQLiteResult::QSQLiteResult(const QSQLiteDriver* db)    : QSqlCachedResult(db){    d = new QSQLiteResultPrivate(this);    d->access = db->d->access;}QSQLiteResult::~QSQLiteResult(){    d->cleanup();    delete d;}void QSQLiteResult::virtual_hook(int id, void *data){    if (id == DetachFromResultSet) {        if (d->stmt)            sqlite3_reset(d->stmt);        return;    }    QSqlResult::virtual_hook(id, data);}bool QSQLiteResult::reset(const QString &query){    if (!prepare(query))        return false;    return exec();}bool QSQLiteResult::prepare(const QString &query){    if (!driver() || !driver()->isOpen() || driver()->isOpenError())        return false;    d->cleanup();    setSelect(false);#if (SQLITE_VERSION_NUMBER >= 3003011)    int res = sqlite3_prepare16_v2(d->access, query.constData(), (query.size() + 1) * sizeof(QChar),                                   &d->stmt, 0);#else    int res = sqlite3_prepare16(d->access, query.constData(), (query.size() + 1) * sizeof(QChar),                                &d->stmt, 0);#endif    if (res != SQLITE_OK) {        setLastError(qMakeError(d->access, QCoreApplication::translate("QSQLiteResult",                     "Unable to execute statement"), QSqlError::StatementError, res));        d->finalize();        return false;    }    return true;}bool QSQLiteResult::exec(){    const QVector<QVariant> values = boundValues();    d->skippedStatus = false;    d->skipRow = false;    d->rInf.clear();    clearValues();    setLastError(QSqlError());    int res = sqlite3_reset(d->stmt);    if (res != SQLITE_OK) {        setLastError(qMakeError(d->access, QCoreApplication::translate("QSQLiteResult",                     "Unable to reset statement"), QSqlError::StatementError, res));        d->finalize();        return false;    }    int paramCount = sqlite3_bind_parameter_count(d->stmt);    if (paramCount == values.count()) {        for (int i = 0; i < paramCount; ++i) {            res = SQLITE_OK;            const QVariant value = values.at(i);            if (value.isNull()) {                res = sqlite3_bind_null(d->stmt, i + 1);            } else {                switch (value.type()) {                case QVariant::ByteArray: {                    const QByteArray *ba = static_cast<const QByteArray*>(value.constData());

⌨️ 快捷键说明

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