📄 qsql_psql.cpp
字号:
#ifdef QT_CHECK_RANGE qWarning( "This version of PostgreSQL is not supported and may not work." );#endif } return QPSQLDriver::Version6;}QPSQLDriver::QPSQLDriver( QObject * parent, const char * name ) : QSqlDriver(parent,name ? name : "QPSQL"), pro( QPSQLDriver::Version6 ){ init();}QPSQLDriver::QPSQLDriver( PGconn * conn, QObject * parent, const char * name ) : QSqlDriver(parent,name ? name : "QPSQL"), pro( QPSQLDriver::Version6 ){ init(); d->connection = conn; if ( conn ) { pro = getPSQLVersion( d->connection ); setOpen( TRUE ); setOpenError( FALSE ); }}void QPSQLDriver::init(){ qSqlDriverExtDict()->insert( this, new QPSQLDriverExtension(this) ); qSqlOpenExtDict()->insert( this, new QPSQLOpenExtension(this) ); d = new QPSQLPrivate();}QPSQLDriver::~QPSQLDriver(){ if ( d->connection ) PQfinish( d->connection ); delete d; if ( !qSqlDriverExtDict()->isEmpty() ) { QSqlDriverExtension *ext = qSqlDriverExtDict()->take( this ); delete ext; } if ( !qSqlOpenExtDict()->isEmpty() ) { QSqlOpenExtension *ext = qSqlOpenExtDict()->take( this ); delete ext; }}PGconn* QPSQLDriver::connection(){ return d->connection;}bool QPSQLDriver::hasFeature( DriverFeature f ) const{ switch ( f ) { case Transactions: return TRUE; case QuerySize: return TRUE; case BLOB: return pro >= QPSQLDriver::Version71; case Unicode: return d->isUtf8; default: return FALSE; }}bool QPSQLDriver::open( const QString&, const QString&, const QString&, const QString&, int ){ qWarning("QPSQLDriver::open(): This version of open() is no longer supported." ); return FALSE;}bool QPSQLDriver::open( const QString & db, const QString & user, const QString & password, const QString & host, int port, const QString& connOpts ){ if ( isOpen() ) close(); QString 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( QString::number( port ) ); // add any connect options - the server will handle error detection if ( !connOpts.isEmpty() ) connectString += " " + QStringList::split( ';', connOpts ).join( " " ); d->connection = PQconnectdb( connectString.local8Bit().data() ); if ( PQstatus( d->connection ) == CONNECTION_BAD ) { setLastError( qMakeError("Unable to connect", QSqlError::Connection, d ) ); setOpenError( TRUE ); return FALSE; } pro = getPSQLVersion( d->connection ); d->isUtf8 = setEncodingUtf8( d->connection ); setDatestyle( d->connection ); setOpen( TRUE ); setOpenError( FALSE ); return TRUE;}void QPSQLDriver::close(){ if ( isOpen() ) { PQfinish( d->connection ); d->connection = 0; setOpen( FALSE ); setOpenError( FALSE ); }}QSqlQuery QPSQLDriver::createQuery() const{ return QSqlQuery( new QPSQLResult( this, d ) );}bool QPSQLDriver::beginTransaction(){ if ( !isOpen() ) {#ifdef QT_CHECK_RANGE qWarning( "QPSQLDriver::beginTransaction: Database not open" );#endif return FALSE; } PGresult* res = PQexec( d->connection, "BEGIN" ); if ( !res || PQresultStatus( res ) != PGRES_COMMAND_OK ) { PQclear( res ); setLastError( qMakeError( "Could not begin transaction", QSqlError::Transaction, d ) ); return FALSE; } PQclear( res ); return TRUE;}bool QPSQLDriver::commitTransaction(){ if ( !isOpen() ) {#ifdef QT_CHECK_RANGE qWarning( "QPSQLDriver::commitTransaction: Database not open" );#endif return FALSE; } PGresult* res = PQexec( d->connection, "COMMIT" ); if ( !res || PQresultStatus( res ) != PGRES_COMMAND_OK ) { PQclear( res ); setLastError( qMakeError( "Could not commit transaction", QSqlError::Transaction, d ) ); return FALSE; } PQclear( res ); return TRUE;}bool QPSQLDriver::rollbackTransaction(){ if ( !isOpen() ) {#ifdef QT_CHECK_RANGE qWarning( "QPSQLDriver::rollbackTransaction: Database not open" );#endif return FALSE; } PGresult* res = PQexec( d->connection, "ROLLBACK" ); if ( !res || PQresultStatus( res ) != PGRES_COMMAND_OK ) { setLastError( qMakeError( "Could not rollback transaction", QSqlError::Transaction, d ) ); PQclear( res ); return FALSE; } PQclear( res ); return TRUE;}QStringList QPSQLDriver::tables( const QString& typeName ) const{ QStringList tl; if ( !isOpen() ) return tl; int type = typeName.toInt(); QSqlQuery t = createQuery(); t.setForwardOnly( TRUE ); if ( typeName.isEmpty() || ((type & (int)QSql::Tables) == (int)QSql::Tables) ) { t.exec( "select relname from pg_class where ( relkind = 'r' ) " "and ( relname !~ '^Inv' ) " "and ( relname !~ '^pg_' ) " ); while ( t.next() ) tl.append( t.value(0).toString() ); } if ( (type & (int)QSql::Views) == (int)QSql::Views ) { t.exec( "select relname from pg_class where ( relkind = 'v' ) " "and ( relname !~ '^Inv' ) " "and ( relname !~ '^pg_' ) " ); while ( t.next() ) tl.append( t.value(0).toString() ); } if ( (type & (int)QSql::SystemTables) == (int)QSql::SystemTables ) { t.exec( "select relname from pg_class where ( relkind = 'r' ) " "and ( relname like 'pg_%' ) " ); while ( t.next() ) tl.append( t.value(0).toString() ); } return tl;}QSqlIndex QPSQLDriver::primaryIndex( const QString& tablename ) const{ QSqlIndex idx( tablename ); if ( !isOpen() ) return idx; QSqlQuery i = createQuery(); QString stmt; switch( pro ) { case QPSQLDriver::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 QPSQLDriver::Version7: case QPSQLDriver::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 QPSQLDriver::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_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() ) { QSqlField f( i.value(0).toString(), qDecodePSQLType( i.value(1).toInt() ) ); idx.append( f ); idx.setName( i.value(2).toString() ); } return idx;}QSqlRecord QPSQLDriver::record( const QString& tablename ) const{ QSqlRecord fil; if ( !isOpen() ) return fil; QString stmt; switch( pro ) { case QPSQLDriver::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 QPSQLDriver::Version7: case QPSQLDriver::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 QPSQLDriver::Version73: 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.attisdropped = false " "and pg_attribute.attrelid = pg_class.oid "; break; } QSqlQuery fi = createQuery(); fi.exec( stmt.arg( tablename.lower() ) ); while ( fi.next() ) { QSqlField f( fi.value(0).toString(), qDecodePSQLType( fi.value(1).toInt() ) ); fil.append( f ); } return fil;}QSqlRecord QPSQLDriver::record( const QSqlQuery& query ) const{ QSqlRecord fil; if ( !isOpen() ) return fil; if ( query.isActive() && query.driver() == this ) { QPSQLResult* result = (QPSQLResult*)query.result(); int count = PQnfields( result->d->result ); for ( int i = 0; i < count; ++i ) { QString name = PQfname( result->d->result, i ); QVariant::Type type = qDecodePSQLType( PQftype( result->d->result, i ) ); QSqlField rf( name, type ); fil.append( rf ); } } return fil;}QSqlRecordInfo QPSQLDriver::recordInfo( const QString& tablename ) const{ QSqlRecordInfo info; if ( !isOpen() ) return info; QString stmt; switch( pro ) { case QPSQLDriver::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 QPSQLDriver::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 QPSQLDriver::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 QPSQLDriver::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_attribute.attnum > 0 " "and pg_attribute.attrelid = pg_class.oid " "and pg_attribute.attisdropped = false " "order by pg_attribute.attnum "; break; } QSqlQuery query = createQuery(); query.exec( stmt.arg( tablename.lower() ) ); if ( pro >= QPSQLDriver::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; } QString defVal = query.value( 5 ).toString(); if ( !defVal.isEmpty() && defVal.startsWith( "'" ) ) defVal = defVal.mid( 1, defVal.length() - 2 ); info.append( QSqlFieldInfo( query.value( 0 ).toString(), qDecodePSQLType( 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() ) { QString defVal; QString stmt2 = "select pg_attrdef.adsrc from pg_attrdef where " "pg_attrdef.adrelid = %1 and pg_attrdef.adnum = %2 "; QSqlQuery 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( QSqlFieldInfo( query.value( 0 ).toString(), qDecodePSQLType( query.value( 1 ).toInt() ), query.value( 2 ).toBool(), len, precision, defVal, query.value( 1 ).toInt() ) ); } } return info;}QSqlRecordInfo QPSQLDriver::recordInfo( const QSqlQuery& query ) const{ QSqlRecordInfo info; if ( !isOpen() ) return info; if ( query.isActive() && query.driver() == this ) { QPSQLResult* result = (QPSQLResult*)query.result(); int count = PQnfields( result->d->result ); for ( int i = 0; i < count; ++i ) { QString 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( QSqlFieldInfo( name, qDecodePSQLType( PQftype( result->d->result, i ) ), -1, len, precision, QVariant(), PQftype( result->d->result, i ) ) ); } } return info;}QString QPSQLDriver::formatValue( const QSqlField* field, bool ) const{ QString r; if ( field->isNull() ) { r = nullText(); } else { switch ( field->type() ) { case QVariant::DateTime: if ( field->value().toDateTime().isValid() ) { QDate dt = field->value().toDateTime().date(); QTime tm = field->value().toDateTime().time(); // msecs need to be right aligned otherwise psql // interpretes them wrong r = "'" + QString::number( dt.year() ) + "-" + QString::number( dt.month() ) + "-" + QString::number( dt.day() ) + " " + tm.toString() + "." + QString::number( tm.msec() ).rightJustify( 3, '0' ) + "'"; } else { r = nullText(); } break; case QVariant::Time: if ( field->value().toTime().isValid() ) { r = field->value().toTime().toString( Qt::ISODate ); } else { r = nullText(); } case QVariant::String: case QVariant::CString: { switch ( field->value().type() ) { case QVariant::Rect: { QRect rec = field->value().toRect(); // upper right corner then lower left according to psql docs r = "'(" + QString::number( rec.right() ) + "," + QString::number( rec.bottom() ) + "),(" + QString::number( rec.left() ) + "," + QString::number( rec.top() ) + ")'"; break; } case QVariant::Point: { QPoint p = field->value().toPoint(); r = "'(" + QString::number( p.x() ) + "," + QString::number( p.y() ) + ")'"; break; } case QVariant::PointArray: { QPointArray pa = field->value().toPointArray(); r = "' "; for ( int i = 0; i < (int)pa.size(); ++i ) { r += "(" + QString::number( pa[i].x() ) + "," + QString::number( pa[i].y() ) + "),"; } r.truncate( r.length() - 1 ); r += "'"; break; } default: // Escape '\' characters r = QSqlDriver::formatValue( field ); r.replace( "\\", "\\\\" ); break; } break; } case QVariant::Bool: if ( field->value().toBool() ) r = "TRUE"; else r = "FALSE"; break; case QVariant::ByteArray: { QByteArray ba = field->value().asByteArray(); QString 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 += QString::number( (unsigned char) ba[ i ], 8 ).rightJustify( 3, '0', TRUE ); } } r += "'"; break; } default: r = QSqlDriver::formatValue( field ); break; } } return r;}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -