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

📄 qsql_psql.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_psql.h"#include <qcoreapplication.h>#include <qvariant.h>#include <qdatetime.h>#include <qregexp.h>#include <qsqlerror.h>#include <qsqlfield.h>#include <qsqlindex.h>#include <qsqlrecord.h>#include <qsqlquery.h>#include <qstringlist.h>#include <libpq-fe.h>#include <stdlib.h>#include <math.h>// workaround for postgres defining their OIDs in a private header file#define QBOOLOID 16#define QINT8OID 20#define QINT2OID 21#define QINT4OID 23#define QNUMERICOID 1700#define QFLOAT4OID 700#define QFLOAT8OID 701#define QABSTIMEOID 702#define QRELTIMEOID 703#define QDATEOID 1082#define QTIMEOID 1083#define QTIMETZOID 1266#define QTIMESTAMPOID 1114#define QTIMESTAMPTZOID 1184#define QOIDOID 2278#define QBYTEAOID 17#define QREGPROCOID 24#define QXIDOID 28#define QCIDOID 29Q_DECLARE_METATYPE(PGconn*)Q_DECLARE_METATYPE(PGresult*)/* This is a compile time switch - if PQfreemem is declared, the compiler will use that one,   otherwise it'll run in this template */template <typename T>inline void PQfreemem(T *t, int = 0) { free(t); }inline void qPQfreemem(void *buffer){    PQfreemem(buffer);}class QPSQLDriverPrivate{public:    QPSQLDriverPrivate(): connection(0), isUtf8(false), pro(QPSQLDriver::Version6) {}    PGconn *connection;    bool isUtf8;    QPSQLDriver::Protocol pro;    void appendTables(QStringList &tl, QSqlQuery &t, QChar type);};void QPSQLDriverPrivate::appendTables(QStringList &tl, QSqlQuery &t, QChar type){    QString query;    if (pro >= QPSQLDriver::Version73) {        query = QString::fromLatin1("select pg_class.relname, pg_namespace.nspname from pg_class "                  "left join pg_namespace on (pg_class.relnamespace = pg_namespace.oid) "                  "where (pg_class.relkind = '%1') and (pg_class.relname !~ '^Inv') "                  "and (pg_class.relname !~ '^pg_') "                  "and (pg_namespace.nspname != 'information_schema') ").arg(type);    } else {        query = QString::fromLatin1("select relname, null from pg_class where (relkind = 'r') "                  "and (relname !~ '^Inv') "                  "and (relname !~ '^pg_') ");    }    t.exec(query);    while (t.next()) {        QString schema = t.value(1).toString();        if (schema.isEmpty() || schema == QLatin1String("public"))            tl.append(t.value(0).toString());        else            tl.append(t.value(0).toString().prepend(QLatin1Char('.')).prepend(schema));    }}class QPSQLResultPrivate{public:    QPSQLResultPrivate(QPSQLResult *qq): q(qq), driver(0), result(0), currentSize(-1) {}    QPSQLResult *q;    const QPSQLDriverPrivate *driver;    PGresult *result;    int currentSize;    bool processResults();};static QSqlError qMakeError(const QString& err, QSqlError::ErrorType type,                            const QPSQLDriverPrivate *p){    const char *s = PQerrorMessage(p->connection);    QString msg = p->isUtf8 ? QString::fromUtf8(s) : QString::fromLocal8Bit(s);    return QSqlError(QLatin1String("QPSQL: ") + err, msg, type);}bool QPSQLResultPrivate::processResults(){    if (!result)        return false;    int status = PQresultStatus(result);    if (status == PGRES_TUPLES_OK) {        q->setSelect(true);        q->setActive(true);        currentSize = PQntuples(result);        return true;    } else if (status == PGRES_COMMAND_OK) {        q->setSelect(false);        q->setActive(true);        currentSize = -1;        return true;    }    q->setLastError(qMakeError(QCoreApplication::translate("QPSQLResult",                    "Unable to create query"), QSqlError::StatementError, driver));    return false;}static QVariant::Type qDecodePSQLType(int t){    QVariant::Type type = QVariant::Invalid;    switch (t) {    case QBOOLOID:        type = QVariant::Bool;        break;    case QINT8OID:        type = QVariant::LongLong;        break;    case QINT2OID:    case QINT4OID:    case QOIDOID:    case QREGPROCOID:    case QXIDOID:    case QCIDOID:        type = QVariant::Int;        break;    case QNUMERICOID:    case QFLOAT4OID:    case QFLOAT8OID:        type = QVariant::Double;        break;    case QABSTIMEOID:    case QRELTIMEOID:    case QDATEOID:        type = QVariant::Date;        break;    case QTIMEOID:    case QTIMETZOID:        type = QVariant::Time;        break;    case QTIMESTAMPOID:    case QTIMESTAMPTZOID:        type = QVariant::DateTime;        break;    case QBYTEAOID:        type = QVariant::ByteArray;        break;    default:        type = QVariant::String;        break;    }    return type;}QPSQLResult::QPSQLResult(const QPSQLDriver* db, const QPSQLDriverPrivate* p)    : QSqlResult(db){    d = new QPSQLResultPrivate(this);    d->driver = p;}QPSQLResult::~QPSQLResult(){    cleanup();    delete d;}QVariant QPSQLResult::handle() const{    return qVariantFromValue(d->result);}void QPSQLResult::cleanup(){    if (d->result)        PQclear(d->result);    d->result = 0;    setAt(QSql::BeforeFirstRow);    d->currentSize = -1;    setActive(false);}bool QPSQLResult::fetch(int i){    if (!isActive())        return false;    if (i < 0)        return false;    if (i >= d->currentSize)        return false;    if (at() == i)        return true;    setAt(i);    return true;}bool QPSQLResult::fetchFirst(){    return fetch(0);}bool QPSQLResult::fetchLast(){    return fetch(PQntuples(d->result) - 1);}QVariant QPSQLResult::data(int i){    if (i >= PQnfields(d->result)) {        qWarning("QPSQLResult::data: column %d out of range", i);        return QVariant();    }    int ptype = PQftype(d->result, i);    QVariant::Type type = qDecodePSQLType(ptype);    const char *val = PQgetvalue(d->result, at(), i);    if (PQgetisnull(d->result, at(), i))        return QVariant(type);    switch (type) {    case QVariant::Bool:        return QVariant((bool)(val[0] == 't'));    case QVariant::String:        return d->driver->isUtf8 ? QString::fromUtf8(val) : QString::fromAscii(val);    case QVariant::LongLong:        if (val[0] == '-')            return QString::fromLatin1(val).toLongLong();        else            return QString::fromLatin1(val).toULongLong();    case QVariant::Int:        return atoi(val);    case QVariant::Double:        if (ptype == QNUMERICOID)            return QString::fromAscii(val);        return strtod(val, 0);    case QVariant::Date:        if (val[0] == '\0') {            return QVariant(QDate());        } else {#ifndef QT_NO_DATESTRING            return QVariant(QDate::fromString(QString::fromLatin1(val), Qt::ISODate));#else            return QVariant(QString::fromLatin1(val));#endif        }    case QVariant::Time: {        const QString str = QString::fromLatin1(val);#ifndef QT_NO_DATESTRING        if (str.isEmpty())            return QVariant(QTime());        if (str.at(str.length() - 3) == QLatin1Char('+'))            // strip the timezone            return QVariant(QTime::fromString(str.left(str.length() - 3), Qt::ISODate));        return QVariant(QTime::fromString(str, Qt::ISODate));#else        return QVariant(str);#endif    }    case QVariant::DateTime: {        QString dtval = QString::fromLatin1(val);#ifndef QT_NO_DATESTRING        if (dtval.length() < 10)            return QVariant(QDateTime());        // remove the timezone        if (dtval.at(dtval.length() - 3) == QLatin1Char('+'))            dtval.chop(3);        // milliseconds are sometimes returned with 2 digits only        if (dtval.at(dtval.length() - 3).isPunct())            dtval += QLatin1Char('0');        if (dtval.isEmpty())            return QVariant(QDateTime());        else            return QVariant(QDateTime::fromString(dtval, Qt::ISODate));#else        return QVariant(dtval);#endif    }    case QVariant::ByteArray: {        size_t len;        unsigned char *data = PQunescapeBytea((unsigned char*)val, &len);        QByteArray ba((const char*)data, len);        qPQfreemem(data);        return QVariant(ba);    }    default:    case QVariant::Invalid:        qWarning("QPSQLResult::data: unknown data type");    }    return QVariant();}bool QPSQLResult::isNull(int field){    PQgetvalue(d->result, at(), field);    return PQgetisnull(d->result, at(), field);}bool QPSQLResult::reset (const QString& query){    cleanup();    if (!driver())        return false;    if (!driver()->isOpen() || driver()->isOpenError())        return false;    d->result = PQexec(d->driver->connection,                       d->driver->isUtf8 ? query.toUtf8().constData()                                         : query.toLocal8Bit().constData());    return d->processResults();}int QPSQLResult::size(){    return d->currentSize;}int QPSQLResult::numRowsAffected(){    return QString::fromLatin1(PQcmdTuples(d->result)).toInt();}QVariant QPSQLResult::lastInsertId() const{    if (isActive()) {        Oid id = PQoidValue(d->result);        if (id != InvalidOid)            return QVariant(id);    }    return QVariant();}QSqlRecord QPSQLResult::record() const{    QSqlRecord info;    if (!isActive() || !isSelect())        return info;    int count = PQnfields(d->result);    for (int i = 0; i < count; ++i) {        QSqlField f;        if (d->driver->isUtf8)            f.setName(QString::fromUtf8(PQfname(d->result, i)));        else            f.setName(QString::fromLocal8Bit(PQfname(d->result, i)));        f.setType(qDecodePSQLType(PQftype(d->result, i)));        int len = PQfsize(d->result, i);        int precision = PQfmod(d->result, i);        // swap length and precision if length == -1        if (len == -1 && precision > -1) {            len = precision - 4;            precision = -1;        }        f.setLength(len);        f.setPrecision(precision);        f.setSqlType(PQftype(d->result, i));        info.append(f);    }    return info;}///////////////////////////////////////////////////////////////////static bool setEncodingUtf8(PGconn* connection){    PGresult* result = PQexec(connection, "SET CLIENT_ENCODING TO 'UNICODE'");    int status = PQresultStatus(result);    PQclear(result);    return status == PGRES_COMMAND_OK;}static void setDatestyle(PGconn* connection){    PGresult* result = PQexec(connection, "SET DATESTYLE TO 'ISO'");    int status =  PQresultStatus(result);    if (status != PGRES_COMMAND_OK)        qWarning("%s", PQerrorMessage(connection));    PQclear(result);}static QPSQLDriver::Protocol getPSQLVersion(PGconn* connection){    PGresult* result = PQexec(connection, "select version()");    int status =  PQresultStatus(result);    if (status == PGRES_COMMAND_OK || status == PGRES_TUPLES_OK) {        QString val = QString::fromAscii(PQgetvalue(result, 0, 0));        PQclear(result);        QRegExp rx(QLatin1String("(\\d+)\\.(\\d+)"));        rx.setMinimal(true); // enforce non-greedy RegExp        if (rx.indexIn(val) != -1) {            int vMaj = rx.cap(1).toInt();            int vMin = rx.cap(2).toInt();            if (vMaj < 6) {                qWarning("This version of PostgreSQL is not supported and may not work.");                return QPSQLDriver::Version6;            }            if (vMaj == 6) {                return QPSQLDriver::Version6;            } else if (vMaj == 7) {                if (vMin < 1)                    return QPSQLDriver::Version7;                else if (vMin < 3)                    return QPSQLDriver::Version71;            }            return QPSQLDriver::Version73;        }    } else {        qWarning("This version of PostgreSQL is not supported and may not work.");    }    return QPSQLDriver::Version6;}QPSQLDriver::QPSQLDriver(QObject *parent)    : QSqlDriver(parent){    init();}

⌨️ 快捷键说明

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