From 5fffa30386502b5423e45c2ed5e6af756b11c7b4 Mon Sep 17 00:00:00 2001 From: Michele Calgaro Date: Tue, 28 May 2024 10:17:01 +0900 Subject: Rename nt* sql related files to equivalent tq* Signed-off-by: Michele Calgaro --- src/sql/drivers/mysql/qsql_mysql.cpp | 832 ---------------------------------- src/sql/drivers/mysql/qsql_mysql.h | 132 ------ src/sql/drivers/mysql/tqsql_mysql.cpp | 832 ++++++++++++++++++++++++++++++++++ src/sql/drivers/mysql/tqsql_mysql.h | 132 ++++++ 4 files changed, 964 insertions(+), 964 deletions(-) delete mode 100644 src/sql/drivers/mysql/qsql_mysql.cpp delete mode 100644 src/sql/drivers/mysql/qsql_mysql.h create mode 100644 src/sql/drivers/mysql/tqsql_mysql.cpp create mode 100644 src/sql/drivers/mysql/tqsql_mysql.h (limited to 'src/sql/drivers/mysql') diff --git a/src/sql/drivers/mysql/qsql_mysql.cpp b/src/sql/drivers/mysql/qsql_mysql.cpp deleted file mode 100644 index dc5a40cac..000000000 --- a/src/sql/drivers/mysql/qsql_mysql.cpp +++ /dev/null @@ -1,832 +0,0 @@ -/**************************************************************************** -** -** Implementation of MYSQL driver classes -** -** Created : 001103 -** -** Copyright (C) 1992-2008 Trolltech ASA. All rights reserved. -** -** 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 "qsql_mysql.h" -#include - -#include -#include -#include - -#define TQMYSQL_DRIVER_NAME "TQMYSQL3" - -#ifdef Q_OS_WIN32 -// comment the next line out if you want to use MySQL/embedded on Win32 systems. -// note that it will crash if you don't statically link to the mysql/e library! -# define Q_NO_MYSQL_EMBEDDED -#endif - -TQPtrDict *tqSqlOpenExtDict(); - -static int qMySqlConnectionCount = 0; -static bool qMySqlInitHandledByUser = FALSE; - -class TQMYSQLOpenExtension : public TQSqlOpenExtension -{ -public: - TQMYSQLOpenExtension( TQMYSQLDriver *dri ) - : TQSqlOpenExtension(), driver(dri) {} - ~TQMYSQLOpenExtension() {} - - bool open( const TQString& db, - const TQString& user, - const TQString& password, - const TQString& host, - int port, - const TQString& connOpts ); - -private: - TQMYSQLDriver *driver; -}; - -bool TQMYSQLOpenExtension::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 ); -} - -class TQMYSQLDriverPrivate -{ -public: - TQMYSQLDriverPrivate() : mysql(0) {} - MYSQL* mysql; -}; - -class TQMYSQLResultPrivate : public TQMYSQLDriverPrivate -{ -public: - TQMYSQLResultPrivate() : TQMYSQLDriverPrivate(), result(0) {} - MYSQL_RES* result; - MYSQL_ROW row; - TQValueVector fieldTypes; -}; - -TQSqlError qMakeError( const TQString& err, int type, const TQMYSQLDriverPrivate* p ) -{ - return TQSqlError(TQMYSQL_DRIVER_NAME ": " + err, TQString(mysql_error( p->mysql )), type, mysql_errno( p->mysql )); -} - -TQVariant::Type qDecodeMYSQLType( int mysqltype, uint flags ) -{ - TQVariant::Type type; - switch ( mysqltype ) { - case FIELD_TYPE_TINY : - case FIELD_TYPE_SHORT : - case FIELD_TYPE_LONG : - case FIELD_TYPE_INT24 : - type = (flags & UNSIGNED_FLAG) ? TQVariant::UInt : TQVariant::Int; - break; - case FIELD_TYPE_YEAR : - type = TQVariant::Int; - break; - case FIELD_TYPE_LONGLONG : - type = (flags & UNSIGNED_FLAG) ? TQVariant::ULongLong : TQVariant::LongLong; - break; - case FIELD_TYPE_DECIMAL : - case FIELD_TYPE_FLOAT : - case FIELD_TYPE_DOUBLE : - type = TQVariant::Double; - break; - case FIELD_TYPE_DATE : - type = TQVariant::Date; - break; - case FIELD_TYPE_TIME : - type = TQVariant::Time; - break; - case FIELD_TYPE_DATETIME : - case FIELD_TYPE_TIMESTAMP : - type = TQVariant::DateTime; - break; - case FIELD_TYPE_BLOB : - case FIELD_TYPE_TINY_BLOB : - case FIELD_TYPE_MEDIUM_BLOB : - case FIELD_TYPE_LONG_BLOB : - type = (flags & BINARY_FLAG) ? TQVariant::ByteArray : TQVariant::CString; - break; - default: - case FIELD_TYPE_ENUM : - case FIELD_TYPE_SET : - case FIELD_TYPE_STRING : - case FIELD_TYPE_VAR_STRING : - type = TQVariant::String; - break; - } - return type; -} - -TQMYSQLResult::TQMYSQLResult( const TQMYSQLDriver* db ) -: TQSqlResult( db ) -{ - d = new TQMYSQLResultPrivate(); - d->mysql = db->d->mysql; -} - -TQMYSQLResult::~TQMYSQLResult() -{ - cleanup(); - delete d; -} - -MYSQL_RES* TQMYSQLResult::result() -{ - return d->result; -} - -void TQMYSQLResult::cleanup() -{ - if ( d->result ) { - mysql_free_result( d->result ); - } - d->result = NULL; - d->row = NULL; - setAt( -1 ); - setActive( FALSE ); -} - -bool TQMYSQLResult::fetch( int i ) -{ - if ( isForwardOnly() ) { // fake a forward seek - if ( at() < i ) { - int x = i - at(); - while ( --x && fetchNext() ); - return fetchNext(); - } else { - return FALSE; - } - } - if ( at() == i ) - return TRUE; - mysql_data_seek( d->result, i ); - d->row = mysql_fetch_row( d->result ); - if ( !d->row ) - return FALSE; - setAt( i ); - return TRUE; -} - -bool TQMYSQLResult::fetchNext() -{ - d->row = mysql_fetch_row( d->result ); - if ( !d->row ) - return FALSE; - setAt( at() + 1 ); - return TRUE; -} - -bool TQMYSQLResult::fetchLast() -{ - if ( isForwardOnly() ) { // fake this since MySQL can't seek on forward only queries - bool success = fetchNext(); // did we move at all? - while ( fetchNext() ); - return success; - } - my_ulonglong numRows = mysql_num_rows( d->result ); - if ( !numRows ) - return FALSE; - return fetch( numRows - 1 ); -} - -bool TQMYSQLResult::fetchFirst() -{ - if ( isForwardOnly() ) // again, fake it - return fetchNext(); - return fetch( 0 ); -} - -TQVariant TQMYSQLResult::data( int field ) -{ - if ( !isSelect() || field >= (int) d->fieldTypes.count() ) { - tqWarning( "TQMYSQLResult::data: column %d out of range", field ); - return TQVariant(); - } - - TQString val( d->row[field] ); - switch ( d->fieldTypes.at( field ) ) { - case TQVariant::LongLong: - return TQVariant( val.toLongLong() ); - case TQVariant::ULongLong: - return TQVariant( val.toULongLong() ); - case TQVariant::Int: - return TQVariant( val.toInt() ); - case TQVariant::UInt: - return TQVariant( val.toUInt() ); - case TQVariant::Double: - 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() ); - } else { - return TQVariant( TQTime::fromString( val, TQt::ISODate ) ); - } - case TQVariant::DateTime: - if ( val.isEmpty() ) - return TQVariant( TQDateTime() ); - if ( val.length() == 14u ) - // TIMESTAMPS have the format yyyyMMddhhmmss - val.insert(4, "-").insert(7, "-").insert(10, 'T').insert(13, ':').insert(16, ':'); - return TQVariant( TQDateTime::fromString( val, TQt::ISODate ) ); - case TQVariant::ByteArray: { - unsigned long* fl = mysql_fetch_lengths( d->result ); - TQByteArray ba; - ba.duplicate( d->row[field], fl[field] ); - return TQVariant( ba ); - } - default: - case TQVariant::String: - case TQVariant::CString: - return TQVariant( val ); - } -#ifdef QT_CHECK_RANGE - tqWarning("TQMYSQLResult::data: unknown data type"); -#endif - return TQVariant(); -} - -bool TQMYSQLResult::isNull( int field ) -{ - if ( d->row[field] == NULL ) - return TRUE; - return FALSE; -} - -bool TQMYSQLResult::reset ( const TQString& query ) -{ - if ( !driver() ) - return FALSE; - if ( !driver()-> isOpen() || driver()->isOpenError() ) - return FALSE; - cleanup(); - - const char *encQuery = query.ascii(); - if ( mysql_real_query( d->mysql, encQuery, tqstrlen(encQuery) ) ) { - setLastError( qMakeError("Unable to execute query", TQSqlError::Statement, d ) ); - return FALSE; - } - if ( isForwardOnly() ) { - if ( isActive() || isValid() ) // have to empty the results from previous query - fetchLast(); - d->result = mysql_use_result( d->mysql ); - } else { - d->result = mysql_store_result( d->mysql ); - } - if ( !d->result && mysql_field_count( d->mysql ) > 0 ) { - setLastError( qMakeError( "Unable to store result", TQSqlError::Statement, d ) ); - return FALSE; - } - int numFields = mysql_field_count( d->mysql ); - setSelect( !( numFields == 0) ); - d->fieldTypes.resize( numFields ); - if ( isSelect() ) { - for( int i = 0; i < numFields; i++) { - MYSQL_FIELD* field = mysql_fetch_field_direct( d->result, i ); - if ( field->type == FIELD_TYPE_DECIMAL ) - d->fieldTypes[i] = TQVariant::String; - else - d->fieldTypes[i] = qDecodeMYSQLType( field->type, field->flags ); - } - } - setActive( TRUE ); - return TRUE; -} - -int TQMYSQLResult::size() -{ - return isSelect() ? (int)mysql_num_rows( d->result ) : -1; -} - -int TQMYSQLResult::numRowsAffected() -{ - return (int)mysql_affected_rows( d->mysql ); -} - -///////////////////////////////////////////////////////// -static void qServerEnd() -{ -#ifndef Q_NO_MYSQL_EMBEDDED -#if !defined(MARIADB_BASE_VERSION) && !defined(MARIADB_VERSION_ID) -# if MYSQL_VERSION_ID > 40000 -# if (MYSQL_VERSION_ID >= 40110 && MYSQL_VERSION_ID < 50000) || MYSQL_VERSION_ID >= 50003 - mysql_library_end(); -# else - mysql_server_end(); -# endif -# endif -#endif -#endif -} - -static void qServerInit() -{ -#ifndef Q_NO_MYSQL_EMBEDDED -# if MYSQL_VERSION_ID >= 40000 - if (qMySqlInitHandledByUser || qMySqlConnectionCount > 1) - return; - - if ( -# if (MYSQL_VERSION_ID >= 40110 && MYSQL_VERSION_ID < 50000) || MYSQL_VERSION_ID >= 50003 - mysql_library_init(0, 0, 0) -# else - mysql_server_init(0, 0, 0) -# endif - ) { - tqWarning("TQMYSQLDriver::qServerInit: unable to start server."); - } -# endif // MYSQL_VERSION_ID -#endif // Q_NO_MYSQL_EMBEDDED - -#if defined(MARIADB_BASE_VERSION) || defined(MARIADB_VERSION_ID) - tqAddPostRoutine(mysql_server_end); -#endif -} - -TQMYSQLDriver::TQMYSQLDriver( TQObject * parent, const char * name ) - : TQSqlDriver( parent, name ? name : TQMYSQL_DRIVER_NAME ) -{ - init(); - qServerInit(); -} - -/*! - Create a driver instance with an already open connection handle. -*/ - -TQMYSQLDriver::TQMYSQLDriver( MYSQL * con, TQObject * parent, const char * name ) - : TQSqlDriver( parent, name ? name : TQMYSQL_DRIVER_NAME ) -{ - init(); - if ( con ) { - d->mysql = (MYSQL *) con; - setOpen( TRUE ); - setOpenError( FALSE ); - if (qMySqlConnectionCount == 1) - qMySqlInitHandledByUser = TRUE; - } else { - qServerInit(); - } -} - -void TQMYSQLDriver::init() -{ - tqSqlOpenExtDict()->insert( this, new TQMYSQLOpenExtension(this) ); - d = new TQMYSQLDriverPrivate(); - d->mysql = 0; - qMySqlConnectionCount++; -} - -TQMYSQLDriver::~TQMYSQLDriver() -{ - qMySqlConnectionCount--; - if (qMySqlConnectionCount == 0 && !qMySqlInitHandledByUser) - qServerEnd(); - - delete d; - if ( !tqSqlOpenExtDict()->isEmpty() ) { - TQSqlOpenExtension *ext = tqSqlOpenExtDict()->take( this ); - delete ext; - } -} - -bool TQMYSQLDriver::hasFeature( DriverFeature f ) const -{ - switch ( f ) { - case Transactions: -// CLIENT_TRANSACTION should be defined in all recent mysql client libs > 3.23.34 -#ifdef CLIENT_TRANSACTIONS - if ( d->mysql ) { - if ( ( d->mysql->server_capabilities & CLIENT_TRANSACTIONS ) == CLIENT_TRANSACTIONS ) - return TRUE; - } -#endif - return FALSE; - case QuerySize: - return TRUE; - case BLOB: - return TRUE; - case Unicode: - return FALSE; - default: - return FALSE; - } -} - -bool TQMYSQLDriver::open( const TQString&, - const TQString&, - const TQString&, - const TQString&, - int ) -{ - tqWarning("TQMYSQLDriver::open(): This version of open() is no longer supported." ); - return FALSE; -} - -bool TQMYSQLDriver::open( const TQString& db, - const TQString& user, - const TQString& password, - const TQString& host, - int port, - const TQString& connOpts ) -{ - if ( isOpen() ) - close(); - - unsigned int clientOptionFlags = 0; - - TQStringList raw = TQStringList::split( ';', connOpts ); - TQStringList opts; - TQStringList::ConstIterator it; - TQString ssl_key, ssl_cert, ssl_ca, ssl_capath, ssl_cipher; - - // extract the real options from the string - for ( it = raw.begin(); it != raw.end(); ++it ) { - TQString tmp( *it ), name; - int idx; - if ( (idx = tmp.find( '=' )) != -1 ) { - TQString val( tmp.mid( idx + 1 ) ); - val.simplifyWhiteSpace(); - name = tmp.left( idx ); - if (name == "MYSQL_SSL_KEY") - ssl_key = val; - else if (name == "MYSQL_SSL_CERT") - ssl_cert = val; - else if (name == "MYSQL_SSL_CA") - ssl_ca = val; - else if (name == "MYSQL_SSL_CAPATH") - ssl_capath = val; - else if (name == "MYSQL_SSL_CIPHER") - ssl_capath = val; - else if ( val == "TRUE" || val == "1" ) - opts << tmp.left( idx ); - else - tqWarning( "TQMYSQLDriver::open: Illegal connect option value '%s'", tmp.latin1() ); - } else { - opts << tmp; - } - } - - if (!(d->mysql = mysql_init((MYSQL*) 0))) { - setLastError( qMakeError( "Unable to connect", TQSqlError::Connection, d ) ); - mysql_close( d->mysql ); - setOpenError( TRUE ); - return FALSE; - } - - bool reconnect = 0; - for ( it = opts.begin(); it != opts.end(); ++it ) { - TQString opt( (*it).upper() ); - if ( opt == "CLIENT_COMPRESS" ) - clientOptionFlags |= CLIENT_COMPRESS; - else if ( opt == "CLIENT_FOUND_ROWS" ) - clientOptionFlags |= CLIENT_FOUND_ROWS; - else if ( opt == "CLIENT_IGNORE_SPACE" ) - clientOptionFlags |= CLIENT_IGNORE_SPACE; - else if ( opt == "CLIENT_INTERACTIVE" ) - clientOptionFlags |= CLIENT_INTERACTIVE; - else if ( opt == "CLIENT_NO_SCHEMA" ) - clientOptionFlags |= CLIENT_NO_SCHEMA; - else if ( opt == "CLIENT_ODBC" ) - clientOptionFlags |= CLIENT_ODBC; - else if ( opt == "CLIENT_SSL" ) - clientOptionFlags |= CLIENT_SSL; - else if ( opt == "MYSQL_OPT_RECONNECT" ) - reconnect = 1; - else - tqWarning( "TQMYSQLDriver::open: Unknown connect option '%s'", (*it).latin1() ); - } - - if (clientOptionFlags & CLIENT_SSL) { - mysql_ssl_set(d->mysql, - ssl_key.isEmpty()? static_cast(0):ssl_key.local8Bit().data(), - ssl_cert.isEmpty()? static_cast(0):ssl_cert.local8Bit().data(), - ssl_ca.isEmpty()? static_cast(0):ssl_ca.local8Bit().data(), - ssl_capath.isEmpty()? static_cast(0):ssl_capath.local8Bit().data(), - ssl_cipher.isEmpty()? static_cast(0):ssl_cipher.local8Bit().data() - ); - } - mysql_options(d->mysql, MYSQL_OPT_RECONNECT, &reconnect); - - if ( mysql_real_connect( d->mysql, - host, - user, - password, - db.isNull() ? TQString("") : db, - (port > -1) ? port : 0, - NULL, - clientOptionFlags ) ) - { - if ( !db.isEmpty() && mysql_select_db( d->mysql, db )) { - setLastError( qMakeError("Unable open database '" + db + "'", TQSqlError::Connection, d ) ); - mysql_close( d->mysql ); - setOpenError( TRUE ); - return FALSE; - } - } else { - setLastError( qMakeError( "Unable to connect", TQSqlError::Connection, d ) ); - mysql_close( d->mysql ); - setOpenError( TRUE ); - return FALSE; - } - setOpen( TRUE ); - setOpenError( FALSE ); - return TRUE; -} - -void TQMYSQLDriver::close() -{ - if ( isOpen() ) { - mysql_close( d->mysql ); - setOpen( FALSE ); - setOpenError( FALSE ); - } -} - -bool TQMYSQLDriver::ping() -{ - if ( !isOpen() ) { - return FALSE; - } - - if (mysql_ping( d->mysql )) { - return TRUE; - } - else { - setLastError( qMakeError("Unable to execute ping", TQSqlError::Statement, d ) ); - return FALSE; - } -} - -TQSqlQuery TQMYSQLDriver::createQuery() const -{ - return TQSqlQuery( new TQMYSQLResult( this ) ); -} - -TQStringList TQMYSQLDriver::tables( const TQString& typeName ) const -{ - TQStringList tl; - if ( !isOpen() ) - return tl; - if ( !typeName.isEmpty() && !(typeName.toInt() & (int)TQSql::Tables) ) - return tl; - - MYSQL_RES* tableRes = mysql_list_tables( d->mysql, NULL ); - MYSQL_ROW row; - int i = 0; - while ( tableRes && TRUE ) { - mysql_data_seek( tableRes, i ); - row = mysql_fetch_row( tableRes ); - if ( !row ) - break; - tl.append( TQString(row[0]) ); - i++; - } - mysql_free_result( tableRes ); - return tl; -} - -TQSqlIndex TQMYSQLDriver::primaryIndex( const TQString& tablename ) const -{ - TQSqlIndex idx; - if ( !isOpen() ) - return idx; - TQSqlQuery i = createQuery(); - TQString stmt( "show index from %1;" ); - TQSqlRecord fil = record( tablename ); - i.exec( stmt.arg( tablename ) ); - while ( i.isActive() && i.next() ) { - if ( i.value(2).toString() == "PRIMARY" ) { - idx.append( *fil.field( i.value(4).toString() ) ); - idx.setCursorName( i.value(0).toString() ); - idx.setName( i.value(2).toString() ); - } - } - return idx; -} - -TQSqlRecord TQMYSQLDriver::record( const TQString& tablename ) const -{ - TQSqlRecord fil; - if ( !isOpen() ) - return fil; - MYSQL_RES* r = mysql_list_fields( d->mysql, tablename.local8Bit().data(), 0); - if ( !r ) { - return fil; - } - MYSQL_FIELD* field; - while ( (field = mysql_fetch_field( r ))) { - TQSqlField f ( TQString( field->name ) , qDecodeMYSQLType( (int)field->type, field->flags ) ); - fil.append ( f ); - } - mysql_free_result( r ); - return fil; -} - -TQSqlRecord TQMYSQLDriver::record( const TQSqlQuery& query ) const -{ - TQSqlRecord fil; - if ( !isOpen() ) - return fil; - if ( query.isActive() && query.isSelect() && query.driver() == this ) { - TQMYSQLResult* result = (TQMYSQLResult*)query.result(); - TQMYSQLResultPrivate* p = result->d; - if ( !mysql_errno( p->mysql ) ) { - for ( ;; ) { - MYSQL_FIELD* f = mysql_fetch_field( p->result ); - if ( f ) { - TQSqlField fi( TQString((const char*)f->name), qDecodeMYSQLType( f->type, f->flags ) ); - fil.append( fi ); - } else - break; - } - } - mysql_field_seek( p->result, 0 ); - } - return fil; -} - -TQSqlRecordInfo TQMYSQLDriver::recordInfo( const TQString& tablename ) const -{ - TQSqlRecordInfo info; - if ( !isOpen() ) - return info; - MYSQL_RES* r = mysql_list_fields( d->mysql, tablename.local8Bit().data(), 0); - if ( !r ) { - return info; - } - MYSQL_FIELD* field; - while ( (field = mysql_fetch_field( r ))) { - info.append ( TQSqlFieldInfo( TQString( field->name ), - qDecodeMYSQLType( (int)field->type, field->flags ), - IS_NOT_NULL( field->flags ), - (int)field->length, - (int)field->decimals, - TQString( field->def ), - (int)field->type ) ); - } - mysql_free_result( r ); - return info; -} - -TQSqlRecordInfo TQMYSQLDriver::recordInfo( const TQSqlQuery& query ) const -{ - TQSqlRecordInfo info; - if ( !isOpen() ) - return info; - if ( query.isActive() && query.isSelect() && query.driver() == this ) { - TQMYSQLResult* result = (TQMYSQLResult*)query.result(); - TQMYSQLResultPrivate* p = result->d; - if ( !mysql_errno( p->mysql ) ) { - for ( ;; ) { - MYSQL_FIELD* field = mysql_fetch_field( p->result ); - if ( field ) { - info.append ( TQSqlFieldInfo( TQString( field->name ), - qDecodeMYSQLType( (int)field->type, field->flags ), - IS_NOT_NULL( field->flags ), - (int)field->length, - (int)field->decimals, - TQVariant(), - (int)field->type ) ); - - } else - break; - } - } - mysql_field_seek( p->result, 0 ); - } - return info; -} - -MYSQL* TQMYSQLDriver::mysql() -{ - return d->mysql; -} - -bool TQMYSQLDriver::beginTransaction() -{ -#ifndef CLIENT_TRANSACTIONS - return FALSE; -#endif - if ( !isOpen() ) { -#ifdef QT_CHECK_RANGE - tqWarning( "TQMYSQLDriver::beginTransaction: Database not open" ); -#endif - return FALSE; - } - if ( mysql_query( d->mysql, "BEGIN WORK" ) ) { - setLastError( qMakeError("Unable to begin transaction", TQSqlError::Statement, d ) ); - return FALSE; - } - return TRUE; -} - -bool TQMYSQLDriver::commitTransaction() -{ -#ifndef CLIENT_TRANSACTIONS - return FALSE; -#endif - if ( !isOpen() ) { -#ifdef QT_CHECK_RANGE - tqWarning( "TQMYSQLDriver::commitTransaction: Database not open" ); -#endif - return FALSE; - } - if ( mysql_query( d->mysql, "COMMIT" ) ) { - setLastError( qMakeError("Unable to commit transaction", TQSqlError::Statement, d ) ); - return FALSE; - } - return TRUE; -} - -bool TQMYSQLDriver::rollbackTransaction() -{ -#ifndef CLIENT_TRANSACTIONS - return FALSE; -#endif - if ( !isOpen() ) { -#ifdef QT_CHECK_RANGE - tqWarning( "TQMYSQLDriver::rollbackTransaction: Database not open" ); -#endif - return FALSE; - } - if ( mysql_query( d->mysql, "ROLLBACK" ) ) { - setLastError( qMakeError("Unable to rollback transaction", TQSqlError::Statement, d ) ); - return FALSE; - } - return TRUE; -} - -TQString TQMYSQLDriver::formatValue( const TQSqlField* field, bool trimStrings ) const -{ - TQString r; - if ( field->isNull() ) { - r = nullText(); - } else { - switch( field->type() ) { - case TQVariant::ByteArray: { - - const TQByteArray ba = field->value().toByteArray(); - // buffer has to be at least length*2+1 bytes - char* buffer = new char[ ba.size() * 2 + 1 ]; - /*uint escapedSize =*/ mysql_escape_string( buffer, ba.data(), ba.size() ); - r.append("'").append(buffer).append("'"); - delete[] buffer; - } - break; - case TQVariant::String: - case TQVariant::CString: { - // Escape '\' characters - r = TQSqlDriver::formatValue( field ); - r.replace( "\\", "\\\\" ); - break; - } - default: - r = TQSqlDriver::formatValue( field, trimStrings ); - } - } - return r; -} diff --git a/src/sql/drivers/mysql/qsql_mysql.h b/src/sql/drivers/mysql/qsql_mysql.h deleted file mode 100644 index f2266af03..000000000 --- a/src/sql/drivers/mysql/qsql_mysql.h +++ /dev/null @@ -1,132 +0,0 @@ -/**************************************************************************** -** -** Definition of MySQL driver classes -** -** Created : 001103 -** -** Copyright (C) 1992-2008 Trolltech ASA. All rights reserved. -** -** 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. -** -**********************************************************************/ - -#ifndef TQSQL_MYSQL_H -#define TQSQL_MYSQL_H - -#include -#include -#include -#include - -#if defined (Q_OS_WIN32) -#include -#endif - -#include - -#ifdef QT_PLUGIN -#define Q_EXPORT_SQLDRIVER_MYSQL -#else -#define Q_EXPORT_SQLDRIVER_MYSQL TQ_EXPORT -#endif - -class TQMYSQLDriverPrivate; -class TQMYSQLResultPrivate; -class TQMYSQLDriver; -class TQSqlRecordInfo; - -class TQMYSQLResult : public TQSqlResult -{ - friend class TQMYSQLDriver; -public: - TQMYSQLResult( const TQMYSQLDriver* db ); - ~TQMYSQLResult(); - - MYSQL_RES* result(); -protected: - void cleanup(); - bool fetch( int i ); - bool fetchNext(); - bool fetchLast(); - bool fetchFirst(); - TQVariant data( int field ); - bool isNull( int field ); - bool reset ( const TQString& query ); - int size(); - int numRowsAffected(); -private: - TQMYSQLResultPrivate* d; -}; - -class Q_EXPORT_SQLDRIVER_MYSQL TQMYSQLDriver : public TQSqlDriver -{ - friend class TQMYSQLResult; -public: - TQMYSQLDriver( TQObject * parent=0, const char * name=0 ); - TQMYSQLDriver( MYSQL * con, TQObject * parent=0, const char * name=0 ); - ~TQMYSQLDriver(); - bool hasFeature( DriverFeature f ) const; - bool open( const TQString & db, - const TQString & user = TQString::null, - const TQString & password = TQString::null, - const TQString & host = TQString::null, - int port = -1 ); - void close(); - bool ping(); - TQSqlQuery createQuery() const; - TQStringList tables( const TQString& user ) const; - TQSqlIndex primaryIndex( const TQString& tablename ) const; - TQSqlRecord record( const TQString& tablename ) const; - TQSqlRecord record( const TQSqlQuery& query ) const; - TQSqlRecordInfo recordInfo( const TQString& tablename ) const; - TQSqlRecordInfo recordInfo( const TQSqlQuery& query ) const; - TQString formatValue( const TQSqlField* field, - bool trimStrings ) const; - MYSQL* mysql(); - // ### remove me for 4.0 - bool open( const TQString& db, - const TQString& user, - const TQString& password, - const TQString& host, - int port, - const TQString& connOpts ); - -protected: - bool beginTransaction(); - bool commitTransaction(); - bool rollbackTransaction(); -private: - void init(); - TQMYSQLDriverPrivate* d; -}; - - -#endif diff --git a/src/sql/drivers/mysql/tqsql_mysql.cpp b/src/sql/drivers/mysql/tqsql_mysql.cpp new file mode 100644 index 000000000..3854a5bb3 --- /dev/null +++ b/src/sql/drivers/mysql/tqsql_mysql.cpp @@ -0,0 +1,832 @@ +/**************************************************************************** +** +** Implementation of MYSQL driver classes +** +** Created : 001103 +** +** Copyright (C) 1992-2008 Trolltech ASA. All rights reserved. +** +** 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_mysql.h" +#include + +#include +#include +#include + +#define TQMYSQL_DRIVER_NAME "TQMYSQL3" + +#ifdef Q_OS_WIN32 +// comment the next line out if you want to use MySQL/embedded on Win32 systems. +// note that it will crash if you don't statically link to the mysql/e library! +# define Q_NO_MYSQL_EMBEDDED +#endif + +TQPtrDict *tqSqlOpenExtDict(); + +static int qMySqlConnectionCount = 0; +static bool qMySqlInitHandledByUser = FALSE; + +class TQMYSQLOpenExtension : public TQSqlOpenExtension +{ +public: + TQMYSQLOpenExtension( TQMYSQLDriver *dri ) + : TQSqlOpenExtension(), driver(dri) {} + ~TQMYSQLOpenExtension() {} + + bool open( const TQString& db, + const TQString& user, + const TQString& password, + const TQString& host, + int port, + const TQString& connOpts ); + +private: + TQMYSQLDriver *driver; +}; + +bool TQMYSQLOpenExtension::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 ); +} + +class TQMYSQLDriverPrivate +{ +public: + TQMYSQLDriverPrivate() : mysql(0) {} + MYSQL* mysql; +}; + +class TQMYSQLResultPrivate : public TQMYSQLDriverPrivate +{ +public: + TQMYSQLResultPrivate() : TQMYSQLDriverPrivate(), result(0) {} + MYSQL_RES* result; + MYSQL_ROW row; + TQValueVector fieldTypes; +}; + +TQSqlError qMakeError( const TQString& err, int type, const TQMYSQLDriverPrivate* p ) +{ + return TQSqlError(TQMYSQL_DRIVER_NAME ": " + err, TQString(mysql_error( p->mysql )), type, mysql_errno( p->mysql )); +} + +TQVariant::Type qDecodeMYSQLType( int mysqltype, uint flags ) +{ + TQVariant::Type type; + switch ( mysqltype ) { + case FIELD_TYPE_TINY : + case FIELD_TYPE_SHORT : + case FIELD_TYPE_LONG : + case FIELD_TYPE_INT24 : + type = (flags & UNSIGNED_FLAG) ? TQVariant::UInt : TQVariant::Int; + break; + case FIELD_TYPE_YEAR : + type = TQVariant::Int; + break; + case FIELD_TYPE_LONGLONG : + type = (flags & UNSIGNED_FLAG) ? TQVariant::ULongLong : TQVariant::LongLong; + break; + case FIELD_TYPE_DECIMAL : + case FIELD_TYPE_FLOAT : + case FIELD_TYPE_DOUBLE : + type = TQVariant::Double; + break; + case FIELD_TYPE_DATE : + type = TQVariant::Date; + break; + case FIELD_TYPE_TIME : + type = TQVariant::Time; + break; + case FIELD_TYPE_DATETIME : + case FIELD_TYPE_TIMESTAMP : + type = TQVariant::DateTime; + break; + case FIELD_TYPE_BLOB : + case FIELD_TYPE_TINY_BLOB : + case FIELD_TYPE_MEDIUM_BLOB : + case FIELD_TYPE_LONG_BLOB : + type = (flags & BINARY_FLAG) ? TQVariant::ByteArray : TQVariant::CString; + break; + default: + case FIELD_TYPE_ENUM : + case FIELD_TYPE_SET : + case FIELD_TYPE_STRING : + case FIELD_TYPE_VAR_STRING : + type = TQVariant::String; + break; + } + return type; +} + +TQMYSQLResult::TQMYSQLResult( const TQMYSQLDriver* db ) +: TQSqlResult( db ) +{ + d = new TQMYSQLResultPrivate(); + d->mysql = db->d->mysql; +} + +TQMYSQLResult::~TQMYSQLResult() +{ + cleanup(); + delete d; +} + +MYSQL_RES* TQMYSQLResult::result() +{ + return d->result; +} + +void TQMYSQLResult::cleanup() +{ + if ( d->result ) { + mysql_free_result( d->result ); + } + d->result = NULL; + d->row = NULL; + setAt( -1 ); + setActive( FALSE ); +} + +bool TQMYSQLResult::fetch( int i ) +{ + if ( isForwardOnly() ) { // fake a forward seek + if ( at() < i ) { + int x = i - at(); + while ( --x && fetchNext() ); + return fetchNext(); + } else { + return FALSE; + } + } + if ( at() == i ) + return TRUE; + mysql_data_seek( d->result, i ); + d->row = mysql_fetch_row( d->result ); + if ( !d->row ) + return FALSE; + setAt( i ); + return TRUE; +} + +bool TQMYSQLResult::fetchNext() +{ + d->row = mysql_fetch_row( d->result ); + if ( !d->row ) + return FALSE; + setAt( at() + 1 ); + return TRUE; +} + +bool TQMYSQLResult::fetchLast() +{ + if ( isForwardOnly() ) { // fake this since MySQL can't seek on forward only queries + bool success = fetchNext(); // did we move at all? + while ( fetchNext() ); + return success; + } + my_ulonglong numRows = mysql_num_rows( d->result ); + if ( !numRows ) + return FALSE; + return fetch( numRows - 1 ); +} + +bool TQMYSQLResult::fetchFirst() +{ + if ( isForwardOnly() ) // again, fake it + return fetchNext(); + return fetch( 0 ); +} + +TQVariant TQMYSQLResult::data( int field ) +{ + if ( !isSelect() || field >= (int) d->fieldTypes.count() ) { + tqWarning( "TQMYSQLResult::data: column %d out of range", field ); + return TQVariant(); + } + + TQString val( d->row[field] ); + switch ( d->fieldTypes.at( field ) ) { + case TQVariant::LongLong: + return TQVariant( val.toLongLong() ); + case TQVariant::ULongLong: + return TQVariant( val.toULongLong() ); + case TQVariant::Int: + return TQVariant( val.toInt() ); + case TQVariant::UInt: + return TQVariant( val.toUInt() ); + case TQVariant::Double: + 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() ); + } else { + return TQVariant( TQTime::fromString( val, TQt::ISODate ) ); + } + case TQVariant::DateTime: + if ( val.isEmpty() ) + return TQVariant( TQDateTime() ); + if ( val.length() == 14u ) + // TIMESTAMPS have the format yyyyMMddhhmmss + val.insert(4, "-").insert(7, "-").insert(10, 'T').insert(13, ':').insert(16, ':'); + return TQVariant( TQDateTime::fromString( val, TQt::ISODate ) ); + case TQVariant::ByteArray: { + unsigned long* fl = mysql_fetch_lengths( d->result ); + TQByteArray ba; + ba.duplicate( d->row[field], fl[field] ); + return TQVariant( ba ); + } + default: + case TQVariant::String: + case TQVariant::CString: + return TQVariant( val ); + } +#ifdef QT_CHECK_RANGE + tqWarning("TQMYSQLResult::data: unknown data type"); +#endif + return TQVariant(); +} + +bool TQMYSQLResult::isNull( int field ) +{ + if ( d->row[field] == NULL ) + return TRUE; + return FALSE; +} + +bool TQMYSQLResult::reset ( const TQString& query ) +{ + if ( !driver() ) + return FALSE; + if ( !driver()-> isOpen() || driver()->isOpenError() ) + return FALSE; + cleanup(); + + const char *encQuery = query.ascii(); + if ( mysql_real_query( d->mysql, encQuery, tqstrlen(encQuery) ) ) { + setLastError( qMakeError("Unable to execute query", TQSqlError::Statement, d ) ); + return FALSE; + } + if ( isForwardOnly() ) { + if ( isActive() || isValid() ) // have to empty the results from previous query + fetchLast(); + d->result = mysql_use_result( d->mysql ); + } else { + d->result = mysql_store_result( d->mysql ); + } + if ( !d->result && mysql_field_count( d->mysql ) > 0 ) { + setLastError( qMakeError( "Unable to store result", TQSqlError::Statement, d ) ); + return FALSE; + } + int numFields = mysql_field_count( d->mysql ); + setSelect( !( numFields == 0) ); + d->fieldTypes.resize( numFields ); + if ( isSelect() ) { + for( int i = 0; i < numFields; i++) { + MYSQL_FIELD* field = mysql_fetch_field_direct( d->result, i ); + if ( field->type == FIELD_TYPE_DECIMAL ) + d->fieldTypes[i] = TQVariant::String; + else + d->fieldTypes[i] = qDecodeMYSQLType( field->type, field->flags ); + } + } + setActive( TRUE ); + return TRUE; +} + +int TQMYSQLResult::size() +{ + return isSelect() ? (int)mysql_num_rows( d->result ) : -1; +} + +int TQMYSQLResult::numRowsAffected() +{ + return (int)mysql_affected_rows( d->mysql ); +} + +///////////////////////////////////////////////////////// +static void qServerEnd() +{ +#ifndef Q_NO_MYSQL_EMBEDDED +#if !defined(MARIADB_BASE_VERSION) && !defined(MARIADB_VERSION_ID) +# if MYSQL_VERSION_ID > 40000 +# if (MYSQL_VERSION_ID >= 40110 && MYSQL_VERSION_ID < 50000) || MYSQL_VERSION_ID >= 50003 + mysql_library_end(); +# else + mysql_server_end(); +# endif +# endif +#endif +#endif +} + +static void qServerInit() +{ +#ifndef Q_NO_MYSQL_EMBEDDED +# if MYSQL_VERSION_ID >= 40000 + if (qMySqlInitHandledByUser || qMySqlConnectionCount > 1) + return; + + if ( +# if (MYSQL_VERSION_ID >= 40110 && MYSQL_VERSION_ID < 50000) || MYSQL_VERSION_ID >= 50003 + mysql_library_init(0, 0, 0) +# else + mysql_server_init(0, 0, 0) +# endif + ) { + tqWarning("TQMYSQLDriver::qServerInit: unable to start server."); + } +# endif // MYSQL_VERSION_ID +#endif // Q_NO_MYSQL_EMBEDDED + +#if defined(MARIADB_BASE_VERSION) || defined(MARIADB_VERSION_ID) + tqAddPostRoutine(mysql_server_end); +#endif +} + +TQMYSQLDriver::TQMYSQLDriver( TQObject * parent, const char * name ) + : TQSqlDriver( parent, name ? name : TQMYSQL_DRIVER_NAME ) +{ + init(); + qServerInit(); +} + +/*! + Create a driver instance with an already open connection handle. +*/ + +TQMYSQLDriver::TQMYSQLDriver( MYSQL * con, TQObject * parent, const char * name ) + : TQSqlDriver( parent, name ? name : TQMYSQL_DRIVER_NAME ) +{ + init(); + if ( con ) { + d->mysql = (MYSQL *) con; + setOpen( TRUE ); + setOpenError( FALSE ); + if (qMySqlConnectionCount == 1) + qMySqlInitHandledByUser = TRUE; + } else { + qServerInit(); + } +} + +void TQMYSQLDriver::init() +{ + tqSqlOpenExtDict()->insert( this, new TQMYSQLOpenExtension(this) ); + d = new TQMYSQLDriverPrivate(); + d->mysql = 0; + qMySqlConnectionCount++; +} + +TQMYSQLDriver::~TQMYSQLDriver() +{ + qMySqlConnectionCount--; + if (qMySqlConnectionCount == 0 && !qMySqlInitHandledByUser) + qServerEnd(); + + delete d; + if ( !tqSqlOpenExtDict()->isEmpty() ) { + TQSqlOpenExtension *ext = tqSqlOpenExtDict()->take( this ); + delete ext; + } +} + +bool TQMYSQLDriver::hasFeature( DriverFeature f ) const +{ + switch ( f ) { + case Transactions: +// CLIENT_TRANSACTION should be defined in all recent mysql client libs > 3.23.34 +#ifdef CLIENT_TRANSACTIONS + if ( d->mysql ) { + if ( ( d->mysql->server_capabilities & CLIENT_TRANSACTIONS ) == CLIENT_TRANSACTIONS ) + return TRUE; + } +#endif + return FALSE; + case QuerySize: + return TRUE; + case BLOB: + return TRUE; + case Unicode: + return FALSE; + default: + return FALSE; + } +} + +bool TQMYSQLDriver::open( const TQString&, + const TQString&, + const TQString&, + const TQString&, + int ) +{ + tqWarning("TQMYSQLDriver::open(): This version of open() is no longer supported." ); + return FALSE; +} + +bool TQMYSQLDriver::open( const TQString& db, + const TQString& user, + const TQString& password, + const TQString& host, + int port, + const TQString& connOpts ) +{ + if ( isOpen() ) + close(); + + unsigned int clientOptionFlags = 0; + + TQStringList raw = TQStringList::split( ';', connOpts ); + TQStringList opts; + TQStringList::ConstIterator it; + TQString ssl_key, ssl_cert, ssl_ca, ssl_capath, ssl_cipher; + + // extract the real options from the string + for ( it = raw.begin(); it != raw.end(); ++it ) { + TQString tmp( *it ), name; + int idx; + if ( (idx = tmp.find( '=' )) != -1 ) { + TQString val( tmp.mid( idx + 1 ) ); + val.simplifyWhiteSpace(); + name = tmp.left( idx ); + if (name == "MYSQL_SSL_KEY") + ssl_key = val; + else if (name == "MYSQL_SSL_CERT") + ssl_cert = val; + else if (name == "MYSQL_SSL_CA") + ssl_ca = val; + else if (name == "MYSQL_SSL_CAPATH") + ssl_capath = val; + else if (name == "MYSQL_SSL_CIPHER") + ssl_capath = val; + else if ( val == "TRUE" || val == "1" ) + opts << tmp.left( idx ); + else + tqWarning( "TQMYSQLDriver::open: Illegal connect option value '%s'", tmp.latin1() ); + } else { + opts << tmp; + } + } + + if (!(d->mysql = mysql_init((MYSQL*) 0))) { + setLastError( qMakeError( "Unable to connect", TQSqlError::Connection, d ) ); + mysql_close( d->mysql ); + setOpenError( TRUE ); + return FALSE; + } + + bool reconnect = 0; + for ( it = opts.begin(); it != opts.end(); ++it ) { + TQString opt( (*it).upper() ); + if ( opt == "CLIENT_COMPRESS" ) + clientOptionFlags |= CLIENT_COMPRESS; + else if ( opt == "CLIENT_FOUND_ROWS" ) + clientOptionFlags |= CLIENT_FOUND_ROWS; + else if ( opt == "CLIENT_IGNORE_SPACE" ) + clientOptionFlags |= CLIENT_IGNORE_SPACE; + else if ( opt == "CLIENT_INTERACTIVE" ) + clientOptionFlags |= CLIENT_INTERACTIVE; + else if ( opt == "CLIENT_NO_SCHEMA" ) + clientOptionFlags |= CLIENT_NO_SCHEMA; + else if ( opt == "CLIENT_ODBC" ) + clientOptionFlags |= CLIENT_ODBC; + else if ( opt == "CLIENT_SSL" ) + clientOptionFlags |= CLIENT_SSL; + else if ( opt == "MYSQL_OPT_RECONNECT" ) + reconnect = 1; + else + tqWarning( "TQMYSQLDriver::open: Unknown connect option '%s'", (*it).latin1() ); + } + + if (clientOptionFlags & CLIENT_SSL) { + mysql_ssl_set(d->mysql, + ssl_key.isEmpty()? static_cast(0):ssl_key.local8Bit().data(), + ssl_cert.isEmpty()? static_cast(0):ssl_cert.local8Bit().data(), + ssl_ca.isEmpty()? static_cast(0):ssl_ca.local8Bit().data(), + ssl_capath.isEmpty()? static_cast(0):ssl_capath.local8Bit().data(), + ssl_cipher.isEmpty()? static_cast(0):ssl_cipher.local8Bit().data() + ); + } + mysql_options(d->mysql, MYSQL_OPT_RECONNECT, &reconnect); + + if ( mysql_real_connect( d->mysql, + host, + user, + password, + db.isNull() ? TQString("") : db, + (port > -1) ? port : 0, + NULL, + clientOptionFlags ) ) + { + if ( !db.isEmpty() && mysql_select_db( d->mysql, db )) { + setLastError( qMakeError("Unable open database '" + db + "'", TQSqlError::Connection, d ) ); + mysql_close( d->mysql ); + setOpenError( TRUE ); + return FALSE; + } + } else { + setLastError( qMakeError( "Unable to connect", TQSqlError::Connection, d ) ); + mysql_close( d->mysql ); + setOpenError( TRUE ); + return FALSE; + } + setOpen( TRUE ); + setOpenError( FALSE ); + return TRUE; +} + +void TQMYSQLDriver::close() +{ + if ( isOpen() ) { + mysql_close( d->mysql ); + setOpen( FALSE ); + setOpenError( FALSE ); + } +} + +bool TQMYSQLDriver::ping() +{ + if ( !isOpen() ) { + return FALSE; + } + + if (mysql_ping( d->mysql )) { + return TRUE; + } + else { + setLastError( qMakeError("Unable to execute ping", TQSqlError::Statement, d ) ); + return FALSE; + } +} + +TQSqlQuery TQMYSQLDriver::createQuery() const +{ + return TQSqlQuery( new TQMYSQLResult( this ) ); +} + +TQStringList TQMYSQLDriver::tables( const TQString& typeName ) const +{ + TQStringList tl; + if ( !isOpen() ) + return tl; + if ( !typeName.isEmpty() && !(typeName.toInt() & (int)TQSql::Tables) ) + return tl; + + MYSQL_RES* tableRes = mysql_list_tables( d->mysql, NULL ); + MYSQL_ROW row; + int i = 0; + while ( tableRes && TRUE ) { + mysql_data_seek( tableRes, i ); + row = mysql_fetch_row( tableRes ); + if ( !row ) + break; + tl.append( TQString(row[0]) ); + i++; + } + mysql_free_result( tableRes ); + return tl; +} + +TQSqlIndex TQMYSQLDriver::primaryIndex( const TQString& tablename ) const +{ + TQSqlIndex idx; + if ( !isOpen() ) + return idx; + TQSqlQuery i = createQuery(); + TQString stmt( "show index from %1;" ); + TQSqlRecord fil = record( tablename ); + i.exec( stmt.arg( tablename ) ); + while ( i.isActive() && i.next() ) { + if ( i.value(2).toString() == "PRIMARY" ) { + idx.append( *fil.field( i.value(4).toString() ) ); + idx.setCursorName( i.value(0).toString() ); + idx.setName( i.value(2).toString() ); + } + } + return idx; +} + +TQSqlRecord TQMYSQLDriver::record( const TQString& tablename ) const +{ + TQSqlRecord fil; + if ( !isOpen() ) + return fil; + MYSQL_RES* r = mysql_list_fields( d->mysql, tablename.local8Bit().data(), 0); + if ( !r ) { + return fil; + } + MYSQL_FIELD* field; + while ( (field = mysql_fetch_field( r ))) { + TQSqlField f ( TQString( field->name ) , qDecodeMYSQLType( (int)field->type, field->flags ) ); + fil.append ( f ); + } + mysql_free_result( r ); + return fil; +} + +TQSqlRecord TQMYSQLDriver::record( const TQSqlQuery& query ) const +{ + TQSqlRecord fil; + if ( !isOpen() ) + return fil; + if ( query.isActive() && query.isSelect() && query.driver() == this ) { + TQMYSQLResult* result = (TQMYSQLResult*)query.result(); + TQMYSQLResultPrivate* p = result->d; + if ( !mysql_errno( p->mysql ) ) { + for ( ;; ) { + MYSQL_FIELD* f = mysql_fetch_field( p->result ); + if ( f ) { + TQSqlField fi( TQString((const char*)f->name), qDecodeMYSQLType( f->type, f->flags ) ); + fil.append( fi ); + } else + break; + } + } + mysql_field_seek( p->result, 0 ); + } + return fil; +} + +TQSqlRecordInfo TQMYSQLDriver::recordInfo( const TQString& tablename ) const +{ + TQSqlRecordInfo info; + if ( !isOpen() ) + return info; + MYSQL_RES* r = mysql_list_fields( d->mysql, tablename.local8Bit().data(), 0); + if ( !r ) { + return info; + } + MYSQL_FIELD* field; + while ( (field = mysql_fetch_field( r ))) { + info.append ( TQSqlFieldInfo( TQString( field->name ), + qDecodeMYSQLType( (int)field->type, field->flags ), + IS_NOT_NULL( field->flags ), + (int)field->length, + (int)field->decimals, + TQString( field->def ), + (int)field->type ) ); + } + mysql_free_result( r ); + return info; +} + +TQSqlRecordInfo TQMYSQLDriver::recordInfo( const TQSqlQuery& query ) const +{ + TQSqlRecordInfo info; + if ( !isOpen() ) + return info; + if ( query.isActive() && query.isSelect() && query.driver() == this ) { + TQMYSQLResult* result = (TQMYSQLResult*)query.result(); + TQMYSQLResultPrivate* p = result->d; + if ( !mysql_errno( p->mysql ) ) { + for ( ;; ) { + MYSQL_FIELD* field = mysql_fetch_field( p->result ); + if ( field ) { + info.append ( TQSqlFieldInfo( TQString( field->name ), + qDecodeMYSQLType( (int)field->type, field->flags ), + IS_NOT_NULL( field->flags ), + (int)field->length, + (int)field->decimals, + TQVariant(), + (int)field->type ) ); + + } else + break; + } + } + mysql_field_seek( p->result, 0 ); + } + return info; +} + +MYSQL* TQMYSQLDriver::mysql() +{ + return d->mysql; +} + +bool TQMYSQLDriver::beginTransaction() +{ +#ifndef CLIENT_TRANSACTIONS + return FALSE; +#endif + if ( !isOpen() ) { +#ifdef QT_CHECK_RANGE + tqWarning( "TQMYSQLDriver::beginTransaction: Database not open" ); +#endif + return FALSE; + } + if ( mysql_query( d->mysql, "BEGIN WORK" ) ) { + setLastError( qMakeError("Unable to begin transaction", TQSqlError::Statement, d ) ); + return FALSE; + } + return TRUE; +} + +bool TQMYSQLDriver::commitTransaction() +{ +#ifndef CLIENT_TRANSACTIONS + return FALSE; +#endif + if ( !isOpen() ) { +#ifdef QT_CHECK_RANGE + tqWarning( "TQMYSQLDriver::commitTransaction: Database not open" ); +#endif + return FALSE; + } + if ( mysql_query( d->mysql, "COMMIT" ) ) { + setLastError( qMakeError("Unable to commit transaction", TQSqlError::Statement, d ) ); + return FALSE; + } + return TRUE; +} + +bool TQMYSQLDriver::rollbackTransaction() +{ +#ifndef CLIENT_TRANSACTIONS + return FALSE; +#endif + if ( !isOpen() ) { +#ifdef QT_CHECK_RANGE + tqWarning( "TQMYSQLDriver::rollbackTransaction: Database not open" ); +#endif + return FALSE; + } + if ( mysql_query( d->mysql, "ROLLBACK" ) ) { + setLastError( qMakeError("Unable to rollback transaction", TQSqlError::Statement, d ) ); + return FALSE; + } + return TRUE; +} + +TQString TQMYSQLDriver::formatValue( const TQSqlField* field, bool trimStrings ) const +{ + TQString r; + if ( field->isNull() ) { + r = nullText(); + } else { + switch( field->type() ) { + case TQVariant::ByteArray: { + + const TQByteArray ba = field->value().toByteArray(); + // buffer has to be at least length*2+1 bytes + char* buffer = new char[ ba.size() * 2 + 1 ]; + /*uint escapedSize =*/ mysql_escape_string( buffer, ba.data(), ba.size() ); + r.append("'").append(buffer).append("'"); + delete[] buffer; + } + break; + case TQVariant::String: + case TQVariant::CString: { + // Escape '\' characters + r = TQSqlDriver::formatValue( field ); + r.replace( "\\", "\\\\" ); + break; + } + default: + r = TQSqlDriver::formatValue( field, trimStrings ); + } + } + return r; +} diff --git a/src/sql/drivers/mysql/tqsql_mysql.h b/src/sql/drivers/mysql/tqsql_mysql.h new file mode 100644 index 000000000..a0d3ca93b --- /dev/null +++ b/src/sql/drivers/mysql/tqsql_mysql.h @@ -0,0 +1,132 @@ +/**************************************************************************** +** +** Definition of MySQL driver classes +** +** Created : 001103 +** +** Copyright (C) 1992-2008 Trolltech ASA. All rights reserved. +** +** 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. +** +**********************************************************************/ + +#ifndef TQSQL_MYSQL_H +#define TQSQL_MYSQL_H + +#include +#include +#include +#include + +#if defined (Q_OS_WIN32) +#include +#endif + +#include + +#ifdef QT_PLUGIN +#define Q_EXPORT_SQLDRIVER_MYSQL +#else +#define Q_EXPORT_SQLDRIVER_MYSQL TQ_EXPORT +#endif + +class TQMYSQLDriverPrivate; +class TQMYSQLResultPrivate; +class TQMYSQLDriver; +class TQSqlRecordInfo; + +class TQMYSQLResult : public TQSqlResult +{ + friend class TQMYSQLDriver; +public: + TQMYSQLResult( const TQMYSQLDriver* db ); + ~TQMYSQLResult(); + + MYSQL_RES* result(); +protected: + void cleanup(); + bool fetch( int i ); + bool fetchNext(); + bool fetchLast(); + bool fetchFirst(); + TQVariant data( int field ); + bool isNull( int field ); + bool reset ( const TQString& query ); + int size(); + int numRowsAffected(); +private: + TQMYSQLResultPrivate* d; +}; + +class Q_EXPORT_SQLDRIVER_MYSQL TQMYSQLDriver : public TQSqlDriver +{ + friend class TQMYSQLResult; +public: + TQMYSQLDriver( TQObject * parent=0, const char * name=0 ); + TQMYSQLDriver( MYSQL * con, TQObject * parent=0, const char * name=0 ); + ~TQMYSQLDriver(); + bool hasFeature( DriverFeature f ) const; + bool open( const TQString & db, + const TQString & user = TQString::null, + const TQString & password = TQString::null, + const TQString & host = TQString::null, + int port = -1 ); + void close(); + bool ping(); + TQSqlQuery createQuery() const; + TQStringList tables( const TQString& user ) const; + TQSqlIndex primaryIndex( const TQString& tablename ) const; + TQSqlRecord record( const TQString& tablename ) const; + TQSqlRecord record( const TQSqlQuery& query ) const; + TQSqlRecordInfo recordInfo( const TQString& tablename ) const; + TQSqlRecordInfo recordInfo( const TQSqlQuery& query ) const; + TQString formatValue( const TQSqlField* field, + bool trimStrings ) const; + MYSQL* mysql(); + // ### remove me for 4.0 + bool open( const TQString& db, + const TQString& user, + const TQString& password, + const TQString& host, + int port, + const TQString& connOpts ); + +protected: + bool beginTransaction(); + bool commitTransaction(); + bool rollbackTransaction(); +private: + void init(); + TQMYSQLDriverPrivate* d; +}; + + +#endif -- cgit v1.2.3