?? qsql_psql.cpp
字號:
/******************************************************************************** Implementation of PostgreSQL driver classes**** Created : 001103**** Copyright (C) 1992-2002 Trolltech AS. All rights reserved.**** This file is part of the sql module of the Qt GUI Toolkit.**** This file may be distributed under the terms of the Q Public License** as defined by Trolltech AS of Norway and appearing in the file** LICENSE.QPL included in the packaging of this file.**** This file may be distributed and/or modified under the terms of the** GNU General Public License version 2 as published by the Free Software** Foundation and appearing in the file LICENSE.GPL included in the** packaging of this file.**** Licensees holding valid Qt Enterprise Edition licenses may use this** file in accordance with the Qt Commercial License Agreement provided** with the Software.**** This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE** WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.**** See http://www.trolltech.com/pricing.html or email sales@trolltech.com for** information about Qt Commercial License Agreements.** See http://www.trolltech.com/qpl/ for QPL licensing information.** See http://www.trolltech.com/gpl/ for GPL licensing information.**** Contact info@trolltech.com if any conditions of this licensing are** not clear to you.************************************************************************/#include "qsql_psql.h"#include <private/qsqlextension_p.h>#include <math.h>#include <qpointarray.h>#include <qsqlrecord.h>#include <qregexp.h>#include <qdatetime.h>// PostgreSQL header <utils/elog.h> included by <postgres.h> redefines DEBUG.#if defined(DEBUG)# undef DEBUG#endif#include <postgres.h>#include <libpq/libpq-fs.h>// PostgreSQL header <catalog/pg_type.h> redefines errno erroneously.#if defined(errno)# undef errno#endif#define errno qt_psql_errno#include <catalog/pg_type.h>#undef errnoQPtrDict<QSqlDriverExtension> *qSqlDriverExtDict();QPtrDict<QSqlOpenExtension> *qSqlOpenExtDict();class QPSQLPrivate{public: QPSQLPrivate():connection(0), result(0), isUtf8(FALSE) {} PGconn *connection; PGresult *result; bool isUtf8;};class QPSQLDriverExtension : public QSqlDriverExtension{public: QPSQLDriverExtension( QPSQLDriver *dri ) : QSqlDriverExtension(), driver(dri) { } ~QPSQLDriverExtension() {} bool isOpen() const;private: QPSQLDriver *driver;};bool QPSQLDriverExtension::isOpen() const{ return PQstatus( driver->connection() ) == CONNECTION_OK;}class QPSQLOpenExtension : public QSqlOpenExtension{public: QPSQLOpenExtension( QPSQLDriver *dri ) : QSqlOpenExtension(), driver(dri) { } ~QPSQLOpenExtension() {} bool open( const QString& db, const QString& user, const QString& password, const QString& host, int port, const QString& connOpts );private: QPSQLDriver *driver;};bool QPSQLOpenExtension::open( const QString& db, const QString& user, const QString& password, const QString& host, int port, const QString& connOpts ){ return driver->open( db, user, password, host, port, connOpts );}static QSqlError qMakeError( const QString& err, int type, const QPSQLPrivate* p ){ const char *s = PQerrorMessage(p->connection); QString msg = p->isUtf8 ? QString::fromUtf8(s) : QString::fromLocal8Bit(s); return QSqlError("QPSQL: " + err, msg, type);}static QVariant::Type qDecodePSQLType( int t ){ QVariant::Type type = QVariant::Invalid; switch ( t ) { case BOOLOID : type = QVariant::Bool; break; case INT8OID : type = QVariant::LongLong; break; case INT2OID : // case INT2VECTOROID : // 7.x case INT4OID : type = QVariant::Int; break; case NUMERICOID : case FLOAT4OID : case FLOAT8OID : type = QVariant::Double; break; case ABSTIMEOID : case RELTIMEOID : case DATEOID : type = QVariant::Date; break; case TIMEOID :#ifdef TIMETZOID // 7.x case TIMETZOID :#endif type = QVariant::Time; break; case TIMESTAMPOID :#ifdef DATETIMEOID // Postgres 6.x datetime workaround. // DATETIMEOID == TIMESTAMPOID (only the names have changed) case DATETIMEOID :#endif#ifdef TIMESTAMPTZOID // Postgres 7.2 workaround // TIMESTAMPTZOID == TIMESTAMPOID == DATETIMEOID case TIMESTAMPTZOID :#endif type = QVariant::DateTime; break; // case ZPBITOID : // 7.x // case VARBITOID : // 7.x case OIDOID : case BYTEAOID : type = QVariant::ByteArray; break; case REGPROCOID : case TIDOID : case XIDOID : case CIDOID : // case OIDVECTOROID : // 7.x case UNKNOWNOID : // case TINTERVALOID : // 7.x type = QVariant::Invalid; break; default: case CHAROID : case BPCHAROID : // case LZTEXTOID : // 7.x case VARCHAROID : case TEXTOID : case NAMEOID : case CASHOID : case INETOID : case CIDROID : case CIRCLEOID : type = QVariant::String; break; } return type;}QPSQLResult::QPSQLResult( const QPSQLDriver* db, const QPSQLPrivate* p ): QSqlResult( db ), currentSize( 0 ){ d = new QPSQLPrivate(); (*d) = (*p);}QPSQLResult::~QPSQLResult(){ cleanup(); delete d;}PGresult* QPSQLResult::result(){ return d->result;}void QPSQLResult::cleanup(){ if ( d->result ) PQclear( d->result ); d->result = 0; setAt( -1 ); currentSize = 0; setActive( FALSE );}bool QPSQLResult::fetch( int i ){ if ( !isActive() ) return FALSE; if ( i < 0 ) return FALSE; if ( i >= 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 );}// some Postgres conversionsstatic QPoint pointFromString( const QString& s){ // format '(x,y)' int pivot = s.find( ',' ); if ( pivot != -1 ) { int x = s.mid( 1, pivot-1 ).toInt(); int y = s.mid( pivot+1, s.length()-pivot-2 ).toInt(); return QPoint( x, y ) ; } else return QPoint();}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 QString val = ( d->isUtf8 && ptype != BYTEAOID ) ? QString::fromUtf8( PQgetvalue( d->result, at(), i ) ) : QString::fromLocal8Bit( PQgetvalue( d->result, at(), i ) ); if ( PQgetisnull( d->result, at(), i ) ) { QVariant v; v.cast( type ); return v; } switch ( type ) { case QVariant::Bool: { QVariant b ( (bool)(val == "t"), 0 ); return ( b ); } case QVariant::String: return QVariant( val ); case QVariant::LongLong: if ( val[0] == '-' ) return QVariant( val.toLongLong() ); else return QVariant( val.toULongLong() ); case QVariant::Int: return QVariant( val.toInt() ); case QVariant::Double: if ( ptype == NUMERICOID ) return QVariant( val ); return QVariant( val.toDouble() ); case QVariant::Date: if ( val.isEmpty() ) { return QVariant( QDate() ); } else { return QVariant( QDate::fromString( val, Qt::ISODate ) ); } case QVariant::Time: if ( val.isEmpty() ) return QVariant( QTime() ); if ( val.at( val.length() - 3 ) == '+' ) // strip the timezone return QVariant( QTime::fromString( val.left( val.length() - 3 ), Qt::ISODate ) ); return QVariant( QTime::fromString( val, Qt::ISODate ) ); case QVariant::DateTime: { if ( val.length() < 10 ) return QVariant( QDateTime() ); // remove the timezone QString dtval = val; if ( dtval.at( dtval.length() - 3 ) == '+' ) dtval.truncate( dtval.length() - 3 ); // milliseconds are sometimes returned with 2 digits only if ( dtval.at( dtval.length() - 3 ).isPunct() ) dtval += '0'; if ( dtval.isEmpty() ) return QVariant( QDateTime() ); else return QVariant( QDateTime::fromString( dtval, Qt::ISODate ) ); } case QVariant::Point: return QVariant( pointFromString( val ) ); case QVariant::Rect: // format '(x,y),(x',y')' { int pivot = val.find( "),(" ); if ( pivot != -1 ) return QVariant( QRect( pointFromString( val.mid(pivot+2,val.length()) ), pointFromString( val.mid(0,pivot+1) ) ) ); return QVariant( QRect() ); } case QVariant::PointArray: // format '((x,y),(x1,y1),...,(xn,yn))' { QRegExp pointPattern("\\([0-9-]*,[0-9-]*\\)"); int points = val.contains( pointPattern ); QPointArray parray( points ); int idx = 1; for ( int i = 0; i < points; i++ ){ int start = val.find( pointPattern, idx ); int end = -1; if ( start != -1 ) { end = val.find( ')', start+1 ); if ( end != -1 ) { parray.setPoint( i, pointFromString( val.mid(idx, end-idx+1) ) ); } else parray.setPoint( i, QPoint() ); } else { parray.setPoint( i, QPoint() ); break; } idx = end+2; } return QVariant( parray ); } case QVariant::ByteArray: { if ( ptype == BYTEAOID ) { uint i = 0; int index = 0; uint len = val.length(); static const QChar backslash( '\\' ); QByteArray ba( (int)len ); while ( i < len ) {
?? 快捷鍵說明
復制代碼
Ctrl + C
搜索代碼
Ctrl + F
全屏模式
F11
切換主題
Ctrl + Shift + D
顯示快捷鍵
?
增大字號
Ctrl + =
減小字號
Ctrl + -