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

📄 qsql_psql.cpp

📁 Linux下的基于X11的图形开发环境。
💻 CPP
📖 第 1 页 / 共 2 页
字号:
/******************************************************************************** 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 <qsqlrecord.h>#include <qregexp.h>#include <qdatetime.h>#include <qpointarray.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 errno#include <math.h>extern#if defined (QT_PLUGIN)Q_EXPORT#endifQPtrDict<QSqlDriverExtension> *qt_driver_extension_dict;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;}QSqlError qMakeError( const QString& err, int type, const QPSQLPrivate* p ){    return QSqlError("QPSQL: " + err, QString(PQerrorMessage( p->connection )), type);}QVariant::Type qDecodePSQLType( int t ){    QVariant::Type type = QVariant::Invalid;    switch ( t ) {    case BOOLOID	:	type = QVariant::Bool;	break;    case INT8OID	:    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 POINTOID       :	type = QVariant::Point;	break;    case BOXOID         :	type = QVariant::Rect;	break;    case POLYGONOID     :    case LINEOID        :    case LSEGOID        :    case PATHOID        :	type = QVariant::PointArray;	break;	//    case ZPBITOID	: // 7.x	//    case VARBITOID	: // 7.x    case OIDOID         :	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 BYTEAOID       :    case CASHOID        :    case INETOID        :    case CIDROID        :    case CIRCLEOID      :	type = QVariant::String;	break;    }    return type;}QVariant::Type qFieldType( QPSQLPrivate* p, int i ){    QVariant::Type type = qDecodePSQLType( PQftype( p->result, i ) );    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 conversionsQPoint 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();}QDate qDateFromUInt( uint dt ){    int y,m,d;    QDate::julianToGregorian( dt, y, m, d );    return QDate( y, m, d );}/* // ### this should be obsolete?QTime qTimeFromDouble( double tm ){    int hour = ((int)tm / ( 60 * 60 ) );    int min = (((int) (tm / 60)) % 60 );    int sec = (((int) tm) % 60 );    return QTime( hour, min, sec );}*/QVariant QPSQLResult::data( int i ){    int ptype = PQftype( d->result, i );    QVariant::Type type = qDecodePSQLType( ptype );    QString val;    if ( d->isUtf8 ) {	val = QString::fromUtf8( PQgetvalue( d->result, at(), i ) );    } else {	val = QString::fromLocal8Bit( PQgetvalue( d->result, at(), i ) );    }    switch ( type ) {    case QVariant::Bool:	{	    QVariant b ( (bool)(val == "t"), 0 );	    return ( b );	}    case QVariant::String:	if ( PQgetisnull( d->result, at(), i ) ) {	    return QVariant( QString() );	} else {	    return QVariant( val );	}    case QVariant::Int:	if ( ptype == INT8OID )	    // keep these as strings so we don't lose precision	    return QVariant( val );	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() );	// strip the timezone	if ( val.at( val.length() - 3 ) == '+' )	    val.truncate( val.length() - 3 );	return QVariant( QTime::fromString( val, Qt::ISODate ) );    case QVariant::DateTime:	if ( val.length() < 10 )	    return QVariant( QDateTime() );	// remove the timezone	if ( val.at( val.length() - 3 ) == '+' )	    val.truncate( val.length() - 3 );	// milliseconds are sometimes returned with 2 digits only	if ( val.at( val.length() - 3 ).isPunct() )	    val += '0';	if ( val.isEmpty() )	    return QVariant( QDateTime() );	else	    return QVariant( QDateTime::fromString( val, 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: {	QByteArray ba;	((QSqlDriver*)driver())->beginTransaction();	Oid oid = val.toInt();	int fd = lo_open( d->connection, oid, INV_READ );#ifdef QT_CHECK_RANGE	if ( fd < 0) {	    qWarning( "QPSQLResult::data: unable to open large object for read" );	    ((QSqlDriver*)driver())->commitTransaction();	    return QVariant( ba );	}#endif	int size = 0;	int retval = lo_lseek( d->connection, fd, 0L, SEEK_END );	if ( retval >= 0 ) {	    size = lo_tell( d->connection, fd );	    lo_lseek( d->connection, fd, 0L, SEEK_SET );	}	if ( size == 0 ) {	    lo_close( d->connection, fd );	    ((QSqlDriver*)driver())->commitTransaction();	    return QVariant( ba );	}	char * buf = new char[ size ];#ifdef Q_OS_WIN32	// ### For some reason lo_read() fails if we try to read more than	// ### 32760 bytes	char * p = buf;	int nread = 0;	while( size < nread ){		retval = lo_read( d->connection, fd, p, 32760 );		nread += retval;		p += retval;	}#else	retval = lo_read( d->connection, fd, buf, size );#endif	if (retval < 0) {	    qWarning( "QPSQLResult::data: unable to read large object" );	} else {	    ba.duplicate( buf, size );	}	delete [] buf;	lo_close( d->connection, fd );	((QSqlDriver*)driver())->commitTransaction();	return QVariant( ba );    }    default:    case QVariant::Invalid:#ifdef QT_CHECK_RANGE	qWarning("QPSQLResult::data: unknown data type");#endif	;    }    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;    setActive( FALSE );    setAt( QSql::BeforeFirst );    if ( d->result )	PQclear( d->result );    if ( d->isUtf8 ) {	d->result = PQexec( d->connection, query.utf8().data() );    } else {	d->result = PQexec( d->connection, query.local8Bit().data() );    }    int status =  PQresultStatus( d->result );    if ( status == PGRES_COMMAND_OK || status == PGRES_TUPLES_OK ) {	setSelect( (status == PGRES_TUPLES_OK) );	currentSize = PQntuples( d->result );	setActive( TRUE );	return TRUE;    }    setLastError( qMakeError( "Unable to create query", QSqlError::Statement, d ) );    return FALSE;}int QPSQLResult::size(){    return currentSize;}int QPSQLResult::numRowsAffected(){    return isSelect() ? size() : QString( PQcmdTuples( d->result ) ).toInt();}///////////////////////////////////////////////////////////////////QPSQLDriver::QPSQLDriver( QObject * parent, const char * name )    : QSqlDriver(parent,name ? name : "QPSQL"), pro( QPSQLDriver::Version6 ){    init();}void QPSQLDriver::init(){    if ( !qt_driver_extension_dict )	qt_driver_extension_dict = new QPtrDict<QSqlDriverExtension>;    qt_driver_extension_dict->insert( this, new QPSQLDriverExtension(this) );    d = new QPSQLPrivate();}QPSQLDriver::~QPSQLDriver(){    if ( d->connection )	PQfinish( d->connection );    delete d;    if ( qt_driver_extension_dict ) {	if ( !qt_driver_extension_dict->isEmpty() ) {	    QSqlDriverExtension *ext = qt_driver_extension_dict->take( this );	    delete ext;	}	if ( qt_driver_extension_dict->isEmpty() ) {	    delete qt_driver_extension_dict;	    qt_driver_extension_dict = 0;	}    }}

⌨️ 快捷键说明

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