summaryrefslogtreecommitdiffstats
path: root/tqtinterface/qt4/src/sql/drivers/psql/tqsql_psql.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'tqtinterface/qt4/src/sql/drivers/psql/tqsql_psql.cpp')
-rw-r--r--tqtinterface/qt4/src/sql/drivers/psql/tqsql_psql.cpp1117
1 files changed, 0 insertions, 1117 deletions
diff --git a/tqtinterface/qt4/src/sql/drivers/psql/tqsql_psql.cpp b/tqtinterface/qt4/src/sql/drivers/psql/tqsql_psql.cpp
deleted file mode 100644
index 7809749..0000000
--- a/tqtinterface/qt4/src/sql/drivers/psql/tqsql_psql.cpp
+++ /dev/null
@@ -1,1117 +0,0 @@
-/****************************************************************************
-**
-** Implementation of PostgreSQL driver classes
-**
-** Created : 001103
-**
-** Copyright (C) 2010 Timothy Pearson and (C) 1992-2008 Trolltech ASA.
-**
-** This file is part of the sql module of the TQt GUI Toolkit.
-**
-** This file may be used under the terms of the GNU General
-** Public License versions 2.0 or 3.0 as published by the Free
-** Software Foundation and appearing in the files LICENSE.GPL2
-** and LICENSE.GPL3 included in the packaging of this file.
-** Alternatively you may (at your option) use any later version
-** of the GNU General Public License if such license has been
-** publicly approved by Trolltech ASA (or its successors, if any)
-** and the KDE Free TQt Foundation.
-**
-** 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.
-**
-** This file may be used under the terms of the Q Public License as
-** defined by Trolltech ASA and appearing in the file LICENSE.TQPL
-** included in the packaging of this file. Licensees holding valid TQt
-** Commercial licenses may use this file in accordance with the TQt
-** Commercial License Agreement provided with the Software.
-**
-** This file is provided "AS IS" with NO WARRANTY OF ANY KIND,
-** INCLUDING THE WARRANTIES OF DESIGN, MERCHANTABILITY AND FITNESS FOR
-** A PARTICULAR PURPOSE. Trolltech reserves all rights not granted
-** herein.
-**
-**********************************************************************/
-
-#include "tqsql_psql.h"
-#include <private/tqsqlextension_p.h>
-
-#include <math.h>
-
-#include <tqpointarray.h>
-#include <tqsqlrecord.h>
-#include <tqregexp.h>
-#include <tqdatetime.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
-#ifdef open
-# undef open
-#endif
-
-TQPtrDict<TQSqlDriverExtension> *qSqlDriverExtDict();
-TQPtrDict<TQSqlOpenExtension> *qSqlOpenExtDict();
-
-class TQPSTQLPrivate
-{
-public:
- TQPSTQLPrivate():connection(0), result(0), isUtf8(FALSE) {}
- PGconn *connection;
- PGresult *result;
- bool isUtf8;
-};
-
-class TQPSTQLDriverExtension : public TQSqlDriverExtension
-{
-public:
- TQPSTQLDriverExtension( TQPSTQLDriver *dri )
- : TQSqlDriverExtension(), driver(dri) { }
- ~TQPSTQLDriverExtension() {}
-
- bool isOpen() const;
-private:
- TQPSTQLDriver *driver;
-};
-
-bool TQPSTQLDriverExtension::isOpen() const
-{
- return PQstatus( driver->connection() ) == CONNECTION_OK;
-}
-
-class TQPSTQLOpenExtension : public TQSqlOpenExtension
-{
-public:
- TQPSTQLOpenExtension( TQPSTQLDriver *dri )
- : TQSqlOpenExtension(), driver(dri) { }
- ~TQPSTQLOpenExtension() {}
-
- bool open( const TQString& db,
- const TQString& user,
- const TQString& password,
- const TQString& host,
- int port,
- const TQString& connOpts );
-private:
- TQPSTQLDriver *driver;
-};
-
-bool TQPSTQLOpenExtension::open( const TQString& db,
- const TQString& user,
- const TQString& password,
- const TQString& host,
- int port,
- const TQString& connOpts )
-{
- return driver->open( db, user, password, host, port, connOpts );
-}
-
-static TQSqlError qMakeError( const TQString& err, int type, const TQPSTQLPrivate* p )
-{
- const char *s = PQerrorMessage(p->connection);
- TQString msg = p->isUtf8 ? TQString::fromUtf8(s) : TQString::fromLocal8Bit(s);
- return TQSqlError("TQPSQL: " + err, msg, type);
-}
-
-static TQVariant::Type qDecodePSTQLType( int t )
-{
- TQVariant::Type type = TQVariant::Invalid;
- switch ( t ) {
- case BOOLOID :
- type = TQVariant::Bool;
- break;
- case INT8OID :
- type = TQVariant::LongLong;
- break;
- case INT2OID :
- // case INT2VECTOROID : // 7.x
- case INT4OID :
- type = TQVariant::Int;
- break;
- case NUMERICOID :
- case FLOAT4OID :
- case FLOAT8OID :
- type = TQVariant::Double;
- break;
- case ABSTIMEOID :
- case RELTIMEOID :
- case DATEOID :
- type = TQVariant::Date;
- break;
- case TIMEOID :
-#ifdef TIMETZOID // 7.x
- case TIMETZOID :
-#endif
- type = TQVariant::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 = TQVariant::DateTime;
- break;
- // case ZPBITOID : // 7.x
- // case VARBITOID : // 7.x
- case OIDOID :
- case BYTEAOID :
- type = TQVariant::ByteArray;
- break;
- case REGPROCOID :
- case TIDOID :
- case XIDOID :
- case CIDOID :
- // case OIDVECTOROID : // 7.x
- case UNKNOWNOID :
- // case TINTERVALOID : // 7.x
- type = TQVariant::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 = TQVariant::String;
- break;
- }
- return type;
-}
-
-TQPSTQLResult::TQPSTQLResult( const TQPSTQLDriver* db, const TQPSTQLPrivate* p )
-: TQSqlResult( db ),
- currentSize( 0 )
-{
- d = new TQPSTQLPrivate();
- (*d) = (*p);
-}
-
-TQPSTQLResult::~TQPSTQLResult()
-{
- cleanup();
- delete d;
-}
-
-PGresult* TQPSTQLResult::result()
-{
- return d->result;
-}
-
-void TQPSTQLResult::cleanup()
-{
- if ( d->result )
- PQclear( d->result );
- d->result = 0;
- setAt( -1 );
- currentSize = 0;
- setActive( FALSE );
-}
-
-bool TQPSTQLResult::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 TQPSTQLResult::fetchFirst()
-{
- return fetch( 0 );
-}
-
-bool TQPSTQLResult::fetchLast()
-{
- return fetch( PQntuples( d->result ) - 1 );
-}
-
-// some Postgres conversions
-static TQPoint pointFromString( const TQString& 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 TQPoint( x, y ) ;
- } else
- return TQPoint();
-}
-
-TQVariant TQPSTQLResult::data( int i )
-{
- if ( i >= PQnfields( d->result ) ) {
- qWarning( "TQPSTQLResult::data: column %d out of range", i );
- return TQVariant();
- }
- int ptype = PQftype( d->result, i );
- TQVariant::Type type = qDecodePSTQLType( ptype );
- const TQString val = ( d->isUtf8 && ptype != BYTEAOID ) ?
- TQString::fromUtf8( PQgetvalue( d->result, at(), i ) ) :
- TQString::fromLocal8Bit( PQgetvalue( d->result, at(), i ) );
- if ( PQgetisnull( d->result, at(), i ) ) {
- TQVariant v;
- v.cast( type );
- return v;
- }
- switch ( type ) {
- case TQVariant::Bool:
- {
- TQVariant b ( (bool)(val == "t"), 0 );
- return ( b );
- }
- case TQVariant::String:
- return TQVariant( val );
- case TQVariant::LongLong:
- if ( val[0] == '-' )
- return TQVariant( val.toLongLong() );
- else
- return TQVariant( val.toULongLong() );
- case TQVariant::Int:
- return TQVariant( val.toInt() );
- case TQVariant::Double:
- if ( ptype == NUMERICOID )
- return TQVariant( val );
- return TQVariant( val.toDouble() );
- case TQVariant::Date:
- if ( val.isEmpty() ) {
- return TQVariant( TQDate() );
- } else {
- return TQVariant( TQDate::fromString( val, TQt::ISODate ) );
- }
- case TQVariant::Time:
- if ( val.isEmpty() )
- return TQVariant( TQTime() );
- if ( val.at( val.length() - 3 ) == '+' )
- // strip the timezone
- return TQVariant( TQTime::fromString( val.left( val.length() - 3 ), TQt::ISODate ) );
- return TQVariant( TQTime::fromString( val, TQt::ISODate ) );
- case TQVariant::DateTime: {
- if ( val.length() < 10 )
- return TQVariant( TQDateTime() );
- // remove the timezone
- TQString 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 TQVariant( TQDateTime() );
- else
- return TQVariant( TQDateTime::fromString( dtval, TQt::ISODate ) );
- }
- case TQVariant::Point:
- return TQVariant( pointFromString( val ) );
- case TQVariant::Rect: // format '(x,y),(x',y')'
- {
- int pivot = val.find( "),(" );
- if ( pivot != -1 )
- return TQVariant( TQRect( pointFromString( val.mid(pivot+2,val.length()) ), pointFromString( val.mid(0,pivot+1) ) ) );
- return TQVariant( TQRect() );
- }
- case TQVariant::PointArray: // format '((x,y),(x1,y1),...,(xn,yn))'
- {
- TQRegExp pointPattern("\\([0-9-]*,[0-9-]*\\)");
- int points = val.contains( pointPattern );
- TQPointArray 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, TQPoint() );
- } else {
- parray.setPoint( i, TQPoint() );
- break;
- }
- idx = end+2;
- }
- return TQVariant( parray );
- }
- case TQVariant::ByteArray: {
- if ( ptype == BYTEAOID ) {
- uint i = 0;
- int index = 0;
- uint len = val.length();
- static const TQChar backslash( '\\' );
- TQByteArray ba( (int)len );
- while ( i < len ) {
- if ( val.at( i ) == backslash ) {
- if ( val.at( i + 1 ).isDigit() ) {
- ba[ index++ ] = (char)(val.mid( i + 1, 3 ).toInt( 0, 8 ));
- i += 4;
- } else {
- ba[ index++ ] = val.at( i + 1 );
- i += 2;
- }
- } else {
- ba[ index++ ] = val.at( i++ ).tqunicode();
- }
- }
- ba.resize( index );
- return TQVariant( ba );
- }
-
- TQByteArray ba;
- ((TQSqlDriver*)driver())->beginTransaction();
- Oid oid = val.toInt();
- int fd = lo_open( d->connection, oid, INV_READ );
-#ifdef TQT_CHECK_RANGE
- if ( fd < 0) {
- qWarning( "TQPSTQLResult::data: unable to open large object for read" );
- ((TQSqlDriver*)driver())->commitTransaction();
- return TQVariant( 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 );
- ((TQSqlDriver*)driver())->commitTransaction();
- return TQVariant( ba );
- }
- char * buf = new char[ size ];
-
-#ifdef TQ_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( "TQPSTQLResult::data: unable to read large object" );
- } else {
- ba.duplicate( buf, size );
- }
- delete [] buf;
- lo_close( d->connection, fd );
- ((TQSqlDriver*)driver())->commitTransaction();
- return TQVariant( ba );
- }
- default:
- case TQVariant::Invalid:
-#ifdef TQT_CHECK_RANGE
- qWarning("TQPSTQLResult::data: unknown data type");
-#endif
- ;
- }
- return TQVariant();
-}
-
-bool TQPSTQLResult::isNull( int field )
-{
- PQgetvalue( d->result, at(), field );
- return PQgetisnull( d->result, at(), field );
-}
-
-bool TQPSTQLResult::reset ( const TQString& query )
-{
- cleanup();
- if ( !driver() )
- return FALSE;
- if ( !driver()->isOpen() || driver()->isOpenError() )
- return FALSE;
- setActive( FALSE );
- setAt( TQSql::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 = PQresultqStatus( d->result );
- if ( status == PGRES_COMMAND_OK || status == PGRES_TUPLES_OK ) {
- if ( status == PGRES_TUPLES_OK ) {
- setSelect( TRUE );
- currentSize = PQntuples( d->result );
- } else {
- setSelect( FALSE );
- currentSize = -1;
- }
- setActive( TRUE );
- return TRUE;
- }
- setLastError( qMakeError( "Unable to create query", TQSqlError::Statement, d ) );
- return FALSE;
-}
-
-int TQPSTQLResult::size()
-{
- return currentSize;
-}
-
-int TQPSTQLResult::numRowsAffected()
-{
- return TQString( PQcmdTuples( d->result ) ).toInt();
-}
-
-///////////////////////////////////////////////////////////////////
-
-static bool setEncodingUtf8( PGconn* connection )
-{
- PGresult* result = PQexec( connection, "SET CLIENT_ENCODING TO 'UNICODE'" );
- int status = PQresultqStatus( result );
- PQclear( result );
- return status == PGRES_COMMAND_OK;
-}
-
-static void setDatestyle( PGconn* connection )
-{
- PGresult* result = PQexec( connection, "SET DATESTYLE TO 'ISO'" );
-#ifdef TQT_CHECK_RANGE
- int status = PQresultqStatus( result );
- if ( status != PGRES_COMMAND_OK )
- qWarning( "%s", PQerrorMessage( connection ) );
-#endif
- PQclear( result );
-}
-
-static TQPSTQLDriver::Protocol getPSTQLVersion( PGconn* connection )
-{
- PGresult* result = PQexec( connection, "select version()" );
- int status = PQresultqStatus( result );
- if ( status == PGRES_COMMAND_OK || status == PGRES_TUPLES_OK ) {
- TQString val( PQgetvalue( result, 0, 0 ) );
- PQclear( result );
- TQRegExp rx( "(\\d+)\\.(\\d+)" );
- rx.setMinimal ( TRUE ); // enforce non-greedy RegExp
- if ( rx.search( val ) != -1 ) {
- int vMaj = rx.cap( 1 ).toInt();
- int vMin = rx.cap( 2 ).toInt();
- if ( vMaj < 6 ) {
-#ifdef TQT_CHECK_RANGE
- qWarning( "This version of PostgreSQL is not supported and may not work." );
-#endif
- return TQPSTQLDriver::Version6;
- }
- if ( vMaj == 6 ) {
- return TQPSTQLDriver::Version6;
- } else if ( vMaj == 7 ) {
- if ( vMin < 1 )
- return TQPSTQLDriver::Version7;
- else if ( vMin < 3 )
- return TQPSTQLDriver::Version71;
- }
- return TQPSTQLDriver::Version73;
- }
- } else {
-#ifdef TQT_CHECK_RANGE
- qWarning( "This version of PostgreSQL is not supported and may not work." );
-#endif
- }
-
- return TQPSTQLDriver::Version6;
-}
-
-TQPSTQLDriver::TQPSTQLDriver( TQObject * parent, const char * name )
- : TQSqlDriver(parent,name ? name : "TQPSQL"), pro( TQPSTQLDriver::Version6 )
-{
- init();
-}
-
-TQPSTQLDriver::TQPSTQLDriver( PGconn * conn, TQObject * parent, const char * name )
- : TQSqlDriver(parent,name ? name : "TQPSQL"), pro( TQPSTQLDriver::Version6 )
-{
- init();
- d->connection = conn;
- if ( conn ) {
- pro = getPSTQLVersion( d->connection );
- setOpen( TRUE );
- setOpenError( FALSE );
- }
-}
-
-void TQPSTQLDriver::init()
-{
- qSqlDriverExtDict()->insert( this, new TQPSTQLDriverExtension(this) );
- qSqlOpenExtDict()->insert( this, new TQPSTQLOpenExtension(this) );
-
- d = new TQPSTQLPrivate();
-}
-
-TQPSTQLDriver::~TQPSTQLDriver()
-{
- if ( d->connection )
- PQfinish( d->connection );
- delete d;
- if ( !qSqlDriverExtDict()->isEmpty() ) {
- TQSqlDriverExtension *ext = qSqlDriverExtDict()->take( this );
- delete ext;
- }
- if ( !qSqlOpenExtDict()->isEmpty() ) {
- TQSqlOpenExtension *ext = qSqlOpenExtDict()->take( this );
- delete ext;
- }
-}
-
-PGconn* TQPSTQLDriver::connection()
-{
- return d->connection;
-}
-
-
-bool TQPSTQLDriver::hasFeature( DriverFeature f ) const
-{
- switch ( f ) {
- case Transactions:
- return TRUE;
- case QuerySize:
- return TRUE;
- case BLOB:
- return pro >= TQPSTQLDriver::Version71;
- case Unicode:
- return d->isUtf8;
- default:
- return FALSE;
- }
-}
-
-bool TQPSTQLDriver::open( const TQString&,
- const TQString&,
- const TQString&,
- const TQString&,
- int )
-{
- qWarning("TQPSTQLDriver::open(): This version of open() is no longer supported." );
- return FALSE;
-}
-
-bool TQPSTQLDriver::open( const TQString & db,
- const TQString & user,
- const TQString & password,
- const TQString & host,
- int port,
- const TQString& connOpts )
-{
- if ( isOpen() )
- close();
- TQString connectString;
- if ( host.length() )
- connectString.append( "host=" ).append( host );
- if ( db.length() )
- connectString.append( " dbname=" ).append( db );
- if ( user.length() )
- connectString.append( " user=" ).append( user );
- if ( password.length() )
- connectString.append( " password=" ).append( password );
- if ( port > -1 )
- connectString.append( " port=" ).append( TQString::number( port ) );
-
- // add any connect options - the server will handle error detection
- if ( !connOpts.isEmpty() )
- connectString += " " + TQStringList::split( ';', connOpts ).join( " " );
-
- d->connection = PQconnectdb( connectString.local8Bit().data() );
- if ( PQstatus( d->connection ) == CONNECTION_BAD ) {
- setLastError( qMakeError("Unable to connect", TQSqlError::Connection, d ) );
- setOpenError( TRUE );
- return FALSE;
- }
-
- pro = getPSTQLVersion( d->connection );
- d->isUtf8 = setEncodingUtf8( d->connection );
- setDatestyle( d->connection );
-
- setOpen( TRUE );
- setOpenError( FALSE );
- return TRUE;
-}
-
-void TQPSTQLDriver::close()
-{
- if ( isOpen() ) {
- if (d->connection)
- PQfinish( d->connection );
- d->connection = 0;
- setOpen( FALSE );
- setOpenError( FALSE );
- }
-}
-
-TQSqlQuery TQPSTQLDriver::createQuery() const
-{
- return TQSqlQuery( new TQPSTQLResult( this, d ) );
-}
-
-bool TQPSTQLDriver::beginTransaction()
-{
- if ( !isOpen() ) {
-#ifdef TQT_CHECK_RANGE
- qWarning( "TQPSTQLDriver::beginTransaction: Database not open" );
-#endif
- return FALSE;
- }
- PGresult* res = PQexec( d->connection, "BEGIN" );
- if ( !res || PQresultqStatus( res ) != PGRES_COMMAND_OK ) {
- PQclear( res );
- setLastError( qMakeError( "Could not begin transaction", TQSqlError::Transaction, d ) );
- return FALSE;
- }
- PQclear( res );
- return TRUE;
-}
-
-bool TQPSTQLDriver::commitTransaction()
-{
- if ( !isOpen() ) {
-#ifdef TQT_CHECK_RANGE
- qWarning( "TQPSTQLDriver::commitTransaction: Database not open" );
-#endif
- return FALSE;
- }
- PGresult* res = PQexec( d->connection, "COMMIT" );
- if ( !res || PQresultqStatus( res ) != PGRES_COMMAND_OK ) {
- PQclear( res );
- setLastError( qMakeError( "Could not commit transaction", TQSqlError::Transaction, d ) );
- return FALSE;
- }
- PQclear( res );
- return TRUE;
-}
-
-bool TQPSTQLDriver::rollbackTransaction()
-{
- if ( !isOpen() ) {
-#ifdef TQT_CHECK_RANGE
- qWarning( "TQPSTQLDriver::rollbackTransaction: Database not open" );
-#endif
- return FALSE;
- }
- PGresult* res = PQexec( d->connection, "ROLLBACK" );
- if ( !res || PQresultqStatus( res ) != PGRES_COMMAND_OK ) {
- setLastError( qMakeError( "Could not rollback transaction", TQSqlError::Transaction, d ) );
- PQclear( res );
- return FALSE;
- }
- PQclear( res );
- return TRUE;
-}
-
-TQStringList TQPSTQLDriver::tables( const TQString& typeName ) const
-{
- TQStringList tl;
- if ( !isOpen() )
- return tl;
- int type = typeName.toInt();
- TQSqlQuery t = createQuery();
- t.setForwardOnly( TRUE );
-
- if ( typeName.isEmpty() || ((type & (int)TQSql::Tables) == (int)TQSql::Tables) ) {
-
- TQString query("select relname from pg_class where (relkind = 'r') "
- "and (relname !~ '^Inv') "
- "and (relname !~ '^pg_') ");
- if (pro >= TQPSTQLDriver::Version73)
- query.append("and (relnamespace not in "
- "(select oid from pg_namespace where nspname = 'information_schema')) "
- "and pg_table_is_visible(pg_class.oid) ");
- t.exec(query);
- while ( t.next() )
- tl.append( t.value(0).toString() );
- }
- if ( (type & (int)TQSql::Views) == (int)TQSql::Views ) {
- TQString query("select relname from pg_class where ( relkind = 'v' ) "
- "and ( relname !~ '^Inv' ) "
- "and ( relname !~ '^pg_' ) ");
- if (pro >= TQPSTQLDriver::Version73)
- query.append("and (relnamespace not in "
- "(select oid from pg_namespace where nspname = 'information_schema')) "
- "and pg_table_is_visible(pg_class.oid) ");
- t.exec(query);
- while ( t.next() )
- tl.append( t.value(0).toString() );
- }
- if ( (type & (int)TQSql::SystemTables) == (int)TQSql::SystemTables ) {
- TQString query( "select relname from pg_class where ( relkind = 'r' ) "
- "and ( relname like 'pg_%' ) " );
- if (pro >= TQPSTQLDriver::Version73)
- query.append( "and pg_table_is_visible(pg_class.oid) " );
- t.exec(query);
- while ( t.next() )
- tl.append( t.value(0).toString() );
- }
-
- return tl;
-}
-
-TQSqlIndex TQPSTQLDriver::primaryIndex( const TQString& tablename ) const
-{
- TQSqlIndex idx( tablename );
- if ( !isOpen() )
- return idx;
- TQSqlQuery i = createQuery();
- TQString stmt;
-
- switch( pro ) {
- case TQPSTQLDriver::Version6:
- stmt = "select pg_att1.attname, int(pg_att1.atttypid), pg_att2.attnum, pg_cl.relname "
- "from pg_attribute pg_att1, pg_attribute pg_att2, pg_class pg_cl, pg_index pg_ind "
- "where lower(pg_cl.relname) = '%1_pkey' ";
- break;
- case TQPSTQLDriver::Version7:
- case TQPSTQLDriver::Version71:
- stmt = "select pg_att1.attname, pg_att1.atttypid::int, pg_cl.relname "
- "from pg_attribute pg_att1, pg_attribute pg_att2, pg_class pg_cl, pg_index pg_ind "
- "where lower(pg_cl.relname) = '%1_pkey' ";
- break;
- case TQPSTQLDriver::Version73:
- stmt = "select pg_att1.attname, pg_att1.atttypid::int, pg_cl.relname "
- "from pg_attribute pg_att1, pg_attribute pg_att2, pg_class pg_cl, pg_index pg_ind "
- "where lower(pg_cl.relname) = '%1_pkey' "
- "and pg_table_is_visible(pg_cl.oid) "
- "and pg_att1.attisdropped = false ";
- break;
- }
- stmt += "and pg_cl.oid = pg_ind.indexrelid "
- "and pg_att2.attrelid = pg_ind.indexrelid "
- "and pg_att1.attrelid = pg_ind.indrelid "
- "and pg_att1.attnum = pg_ind.indkey[pg_att2.attnum-1] "
- "order by pg_att2.attnum";
-
- i.exec( stmt.arg( tablename.lower() ) );
- while ( i.isActive() && i.next() ) {
- TQSqlField f( i.value(0).toString(), qDecodePSTQLType( i.value(1).toInt() ) );
- idx.append( f );
- idx.setName( i.value(2).toString() );
- }
- return idx;
-}
-
-TQSqlRecord TQPSTQLDriver::record( const TQString& tablename ) const
-{
- TQSqlRecord fil;
- if ( !isOpen() )
- return fil;
- TQString stmt;
- switch( pro ) {
- case TQPSTQLDriver::Version6:
- stmt = "select pg_attribute.attname, int(pg_attribute.atttypid) "
- "from pg_class, pg_attribute "
- "where lower(pg_class.relname) = '%1' "
- "and pg_attribute.attnum > 0 "
- "and pg_attribute.attrelid = pg_class.oid ";
- break;
- case TQPSTQLDriver::Version7:
- case TQPSTQLDriver::Version71:
- stmt = "select pg_attribute.attname, pg_attribute.atttypid::int "
- "from pg_class, pg_attribute "
- "where lower(pg_class.relname) = '%1' "
- "and pg_attribute.attnum > 0 "
- "and pg_attribute.attrelid = pg_class.oid ";
- break;
- case TQPSTQLDriver::Version73:
- stmt = "select pg_attribute.attname, pg_attribute.atttypid::int "
- "from pg_class, pg_attribute "
- "where lower(pg_class.relname) = '%1' "
- "and pg_table_is_visible(pg_class.oid) "
- "and pg_attribute.attnum > 0 "
- "and pg_attribute.attisdropped = false "
- "and pg_attribute.attrelid = pg_class.oid ";
- break;
- }
-
- TQSqlQuery fi = createQuery();
- fi.exec( stmt.arg( tablename.lower() ) );
- while ( fi.next() ) {
- TQSqlField f( fi.value(0).toString(), qDecodePSTQLType( fi.value(1).toInt() ) );
- fil.append( f );
- }
- return fil;
-}
-
-TQSqlRecord TQPSTQLDriver::record( const TQSqlQuery& query ) const
-{
- TQSqlRecord fil;
- if ( !isOpen() )
- return fil;
- if ( query.isActive() && query.driver() == this ) {
- TQPSTQLResult* result = (TQPSTQLResult*)query.result();
- int count = PQnfields( result->d->result );
- for ( int i = 0; i < count; ++i ) {
- TQString name = PQfname( result->d->result, i );
- TQVariant::Type type = qDecodePSTQLType( PQftype( result->d->result, i ) );
- TQSqlField rf( name, type );
- fil.append( rf );
- }
- }
- return fil;
-}
-
-TQSqlRecordInfo TQPSTQLDriver::recordInfo( const TQString& tablename ) const
-{
- TQSqlRecordInfo info;
- if ( !isOpen() )
- return info;
-
- TQString stmt;
- switch( pro ) {
- case TQPSTQLDriver::Version6:
- stmt = "select pg_attribute.attname, int(pg_attribute.atttypid), pg_attribute.attnotnull, "
- "pg_attribute.attlen, pg_attribute.atttypmod, int(pg_attribute.attrelid), pg_attribute.attnum "
- "from pg_class, pg_attribute "
- "where lower(pg_class.relname) = '%1' "
- "and pg_attribute.attnum > 0 "
- "and pg_attribute.attrelid = pg_class.oid ";
- break;
- case TQPSTQLDriver::Version7:
- stmt = "select pg_attribute.attname, pg_attribute.atttypid::int, pg_attribute.attnotnull, "
- "pg_attribute.attlen, pg_attribute.atttypmod, pg_attribute.attrelid::int, pg_attribute.attnum "
- "from pg_class, pg_attribute "
- "where lower(pg_class.relname) = '%1' "
- "and pg_attribute.attnum > 0 "
- "and pg_attribute.attrelid = pg_class.oid ";
- break;
- case TQPSTQLDriver::Version71:
- stmt = "select pg_attribute.attname, pg_attribute.atttypid::int, pg_attribute.attnotnull, "
- "pg_attribute.attlen, pg_attribute.atttypmod, pg_attrdef.adsrc "
- "from pg_class, pg_attribute "
- "left join pg_attrdef on (pg_attrdef.adrelid = pg_attribute.attrelid and pg_attrdef.adnum = pg_attribute.attnum) "
- "where lower(pg_class.relname) = '%1' "
- "and pg_attribute.attnum > 0 "
- "and pg_attribute.attrelid = pg_class.oid "
- "order by pg_attribute.attnum ";
- break;
- case TQPSTQLDriver::Version73:
- stmt = "select pg_attribute.attname, pg_attribute.atttypid::int, pg_attribute.attnotnull, "
- "pg_attribute.attlen, pg_attribute.atttypmod, pg_attrdef.adsrc "
- "from pg_class, pg_attribute "
- "left join pg_attrdef on (pg_attrdef.adrelid = pg_attribute.attrelid and pg_attrdef.adnum = pg_attribute.attnum) "
- "where lower(pg_class.relname) = '%1' "
- "and pg_table_is_visible(pg_class.oid) "
- "and pg_attribute.attnum > 0 "
- "and pg_attribute.attrelid = pg_class.oid "
- "and pg_attribute.attisdropped = false "
- "order by pg_attribute.attnum ";
- break;
- }
-
- TQSqlQuery query = createQuery();
- query.exec( stmt.arg( tablename.lower() ) );
- if ( pro >= TQPSTQLDriver::Version71 ) {
- while ( query.next() ) {
- int len = query.value( 3 ).toInt();
- int precision = query.value( 4 ).toInt();
- // swap length and precision if length == -1
- if ( len == -1 && precision > -1 ) {
- len = precision - 4;
- precision = -1;
- }
- TQString defVal = query.value( 5 ).toString();
- if ( !defVal.isEmpty() && defVal.startsWith( "'" ) )
- defVal = defVal.mid( 1, defVal.length() - 2 );
- info.append( TQSqlFieldInfo( query.value( 0 ).toString(),
- qDecodePSTQLType( query.value( 1 ).toInt() ),
- query.value( 2 ).toBool(),
- len,
- precision,
- defVal,
- query.value( 1 ).toInt() ) );
- }
- } else {
- // Postgres < 7.1 cannot handle outer joins
- while ( query.next() ) {
- TQString defVal;
- TQString stmt2 = "select pg_attrdef.adsrc from pg_attrdef where "
- "pg_attrdef.adrelid = %1 and pg_attrdef.adnum = %2 ";
- TQSqlQuery query2 = createQuery();
- query2.exec( stmt2.arg( query.value( 5 ).toInt() ).arg( query.value( 6 ).toInt() ) );
- if ( query2.isActive() && query2.next() )
- defVal = query2.value( 0 ).toString();
- if ( !defVal.isEmpty() && defVal.startsWith( "'" ) )
- defVal = defVal.mid( 1, defVal.length() - 2 );
- int len = query.value( 3 ).toInt();
- int precision = query.value( 4 ).toInt();
- // swap length and precision if length == -1
- if ( len == -1 && precision > -1 ) {
- len = precision - 4;
- precision = -1;
- }
- info.append( TQSqlFieldInfo( query.value( 0 ).toString(),
- qDecodePSTQLType( query.value( 1 ).toInt() ),
- query.value( 2 ).toBool(),
- len,
- precision,
- defVal,
- query.value( 1 ).toInt() ) );
- }
- }
-
- return info;
-}
-
-TQSqlRecordInfo TQPSTQLDriver::recordInfo( const TQSqlQuery& query ) const
-{
- TQSqlRecordInfo info;
- if ( !isOpen() )
- return info;
- if ( query.isActive() && query.driver() == this ) {
- TQPSTQLResult* result = (TQPSTQLResult*)query.result();
- int count = PQnfields( result->d->result );
- for ( int i = 0; i < count; ++i ) {
- TQString name = PQfname( result->d->result, i );
- int len = PQfsize( result->d->result, i );
- int precision = PQfmod( result->d->result, i );
- // swap length and precision if length == -1
- if ( len == -1 && precision > -1 ) {
- len = precision - 4;
- precision = -1;
- }
- info.append( TQSqlFieldInfo( name,
- qDecodePSTQLType( PQftype( result->d->result, i ) ),
- -1,
- len,
- precision,
- TQVariant(),
- PQftype( result->d->result, i ) ) );
- }
- }
- return info;
-}
-
-TQString TQPSTQLDriver::formatValue( const TQSqlField* field,
- bool ) const
-{
- TQString r;
- if ( field->isNull() ) {
- r = nullText();
- } else {
- switch ( field->type() ) {
- case TQVariant::DateTime:
- if ( field->value().toDateTime().isValid() ) {
- TQDate dt = field->value().toDateTime().date();
- TQTime tm = field->value().toDateTime().time();
- // msecs need to be right aligned otherwise psql
- // interpretes them wrong
- r = "'" + TQString::number( dt.year() ) + "-" +
- TQString::number( dt.month() ) + "-" +
- TQString::number( dt.day() ) + " " +
- tm.toString() + "." +
- TQString::number( tm.msec() ).rightJustify( 3, '0' ) + "'";
- } else {
- r = nullText();
- }
- break;
- case TQVariant::Time:
- if ( field->value().toTime().isValid() ) {
- r = field->value().toTime().toString( TQt::ISODate );
- } else {
- r = nullText();
- }
- case TQVariant::String:
- case TQVariant::CString: {
- switch ( field->value().type() ) {
- case TQVariant::Rect: {
- TQRect rec = field->value().toRect();
- // upper right corner then lower left according to psql docs
- r = "'(" + TQString::number( rec.right() ) +
- "," + TQString::number( rec.bottom() ) +
- "),(" + TQString::number( rec.left() ) +
- "," + TQString::number( rec.top() ) + ")'";
- break;
- }
- case TQVariant::Point: {
- TQPoint p = field->value().toPoint();
- r = "'(" + TQString::number( p.x() ) +
- "," + TQString::number( p.y() ) + ")'";
- break;
- }
- case TQVariant::PointArray: {
- TQPointArray pa = field->value().toPointArray();
- r = "' ";
- for ( int i = 0; i < (int)pa.size(); ++i ) {
- r += "(" + TQString::number( pa[i].x() ) +
- "," + TQString::number( pa[i].y() ) + "),";
- }
- r.truncate( r.length() - 1 );
- r += "'";
- break;
- }
- default:
- // Escape '\' characters
- r = TQSqlDriver::formatValue( field );
- r.replace( "\\", "\\\\" );
- break;
- }
- break;
- }
- case TQVariant::Bool:
- if ( field->value().toBool() )
- r = "TRUE";
- else
- r = "FALSE";
- break;
- case TQVariant::ByteArray: {
- TQByteArray ba = field->value().asByteArray();
- TQString res;
- r = "'";
- unsigned char uc;
- for ( int i = 0; i < (int)ba.size(); ++i ) {
- uc = (unsigned char) ba[ i ];
- if ( uc > 40 && uc < 92 ) {
- r += uc;
- } else {
- r += "\\\\";
- r += TQString::number( (unsigned char) ba[ i ], 8 ).rightJustify( 3, '0', TRUE );
- }
- }
- r += "'";
- break;
- }
- default:
- r = TQSqlDriver::formatValue( field );
- break;
- }
- }
- return r;
-}