diff options
Diffstat (limited to 'tqtinterface/qt4/src/sql/drivers')
-rw-r--r-- | tqtinterface/qt4/src/sql/drivers/cache/tqsqlcachedresult.cpp | 259 | ||||
-rw-r--r-- | tqtinterface/qt4/src/sql/drivers/cache/tqsqlcachedresult.h | 104 | ||||
-rw-r--r-- | tqtinterface/qt4/src/sql/drivers/ibase/tqsql_ibase.cpp | 1078 | ||||
-rw-r--r-- | tqtinterface/qt4/src/sql/drivers/ibase/tqsql_ibase.h | 117 | ||||
-rw-r--r-- | tqtinterface/qt4/src/sql/drivers/mysql/tqsql_mysql.cpp | 775 | ||||
-rw-r--r-- | tqtinterface/qt4/src/sql/drivers/mysql/tqsql_mysql.h | 131 | ||||
-rw-r--r-- | tqtinterface/qt4/src/sql/drivers/odbc/tqsql_odbc.cpp | 2035 | ||||
-rw-r--r-- | tqtinterface/qt4/src/sql/drivers/odbc/tqsql_odbc.h | 165 | ||||
-rw-r--r-- | tqtinterface/qt4/src/sql/drivers/psql/tqsql_psql.cpp | 1117 | ||||
-rw-r--r-- | tqtinterface/qt4/src/sql/drivers/psql/tqsql_psql.h | 131 | ||||
-rw-r--r-- | tqtinterface/qt4/src/sql/drivers/sqlite/tqsql_sqlite.cpp | 513 | ||||
-rw-r--r-- | tqtinterface/qt4/src/sql/drivers/sqlite/tqsql_sqlite.h | 90 |
12 files changed, 0 insertions, 6515 deletions
diff --git a/tqtinterface/qt4/src/sql/drivers/cache/tqsqlcachedresult.cpp b/tqtinterface/qt4/src/sql/drivers/cache/tqsqlcachedresult.cpp deleted file mode 100644 index 39195e9..0000000 --- a/tqtinterface/qt4/src/sql/drivers/cache/tqsqlcachedresult.cpp +++ /dev/null @@ -1,259 +0,0 @@ -/**************************************************************************** -** -** Implementation of cached TQt SQL result classes -** -** -** 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 "tqsqlcachedresult.h" -#include <tqdatetime.h> - -#ifndef TQT_NO_SQL -static const uint initial_cache_size = 128; - -class TQtSqlCachedResultPrivate -{ -public: - TQtSqlCachedResultPrivate(); - bool seek(int i); - void init(int count, bool fo); - void cleanup(); - TQtSqlCachedResult::RowCache* next(); - void revertLast(); - - TQtSqlCachedResult::RowsetCache *cache; - TQtSqlCachedResult::RowCache *current; - int rowCacheEnd; - int colCount; - bool forwardOnly; -}; - -TQtSqlCachedResultPrivate::TQtSqlCachedResultPrivate(): - cache(0), current(0), rowCacheEnd(0), colCount(0), forwardOnly(FALSE) -{ -} - -void TQtSqlCachedResultPrivate::cleanup() -{ - if (cache) { - for (int i = 0; i < rowCacheEnd; ++i) - delete (*cache)[i]; - delete cache; - cache = 0; - } - if (forwardOnly) - delete current; - current = 0; - forwardOnly = FALSE; - colCount = 0; - rowCacheEnd = 0; -} - -void TQtSqlCachedResultPrivate::init(int count, bool fo) -{ - cleanup(); - forwardOnly = fo; - colCount = count; - if (fo) - current = new TQtSqlCachedResult::RowCache(count); - else - cache = new TQtSqlCachedResult::RowsetCache(initial_cache_size); -} - -TQtSqlCachedResult::RowCache *TQtSqlCachedResultPrivate::next() -{ - if (forwardOnly) - return current; - - TQ_ASSERT(cache); - current = new TQtSqlCachedResult::RowCache(colCount); - if (rowCacheEnd == (int)cache->size()) - cache->resize(cache->size() * 2); - cache->insert(rowCacheEnd++, current); - return current; -} - -bool TQtSqlCachedResultPrivate::seek(int i) -{ - if (forwardOnly || i < 0) - return FALSE; - if (i >= rowCacheEnd) - return FALSE; - current = (*cache)[i]; - return TRUE; -} - -void TQtSqlCachedResultPrivate::revertLast() -{ - if (forwardOnly) - return; - --rowCacheEnd; - delete current; - current = 0; -} - -////////////// - -TQtSqlCachedResult::TQtSqlCachedResult(const TQSqlDriver * db ): TQSqlResult ( db ) -{ - d = new TQtSqlCachedResultPrivate(); -} - -TQtSqlCachedResult::~TQtSqlCachedResult() -{ - delete d; -} - -void TQtSqlCachedResult::init(int colCount) -{ - d->init(colCount, isForwardOnly()); -} - -bool TQtSqlCachedResult::fetch(int i) -{ - if ((!isActive()) || (i < 0)) - return FALSE; - if (at() == i) - return TRUE; - if (d->forwardOnly) { - // speed hack - do not copy values if not needed - if (at() > i || at() == TQSql::AfterLast) - return FALSE; - while(at() < i - 1) { - if (!gotoNext(0)) - return FALSE; - setAt(at() + 1); - } - if (!gotoNext(d->current)) - return FALSE; - setAt(at() + 1); - return TRUE; - } - if (d->seek(i)) { - setAt(i); - return TRUE; - } - setAt(d->rowCacheEnd - 1); - while (at() < i) { - if (!cacheNext()) - return FALSE; - } - return TRUE; -} - -bool TQtSqlCachedResult::fetchNext() -{ - if (d->seek(at() + 1)) { - setAt(at() + 1); - return TRUE; - } - return cacheNext(); -} - -bool TQtSqlCachedResult::fetchPrev() -{ - return fetch(at() - 1); -} - -bool TQtSqlCachedResult::fetchFirst() -{ - if (d->forwardOnly && at() != TQSql::BeforeFirst) { - return FALSE; - } - if (d->seek(0)) { - setAt(0); - return TRUE; - } - return cacheNext(); -} - -bool TQtSqlCachedResult::fetchLast() -{ - if (at() == TQSql::AfterLast) { - if (d->forwardOnly) - return FALSE; - else - return fetch(d->rowCacheEnd - 1); - } - - int i = at(); - while (fetchNext()) - i++; /* brute force */ - if (d->forwardOnly && at() == TQSql::AfterLast) { - setAt(i); - return TRUE; - } else { - return fetch(d->rowCacheEnd - 1); - } -} - -TQVariant TQtSqlCachedResult::data(int i) -{ - if (!d->current || i >= (int)d->current->size() || i < 0) - return TQVariant(); - - return (*d->current)[i]; -} - -bool TQtSqlCachedResult::isNull(int i) -{ - if (!d->current || i >= (int)d->current->size() || i < 0) - return TRUE; - - return (*d->current)[i].isNull(); -} - -void TQtSqlCachedResult::cleanup() -{ - setAt(TQSql::BeforeFirst); - setActive(FALSE); - d->cleanup(); -} - -bool TQtSqlCachedResult::cacheNext() -{ - if (!gotoNext(d->next())) { - d->revertLast(); - return FALSE; - } - setAt(at() + 1); - return TRUE; -} - -int TQtSqlCachedResult::colCount() const -{ - return d->colCount; -} -#endif // TQT_NO_SQL diff --git a/tqtinterface/qt4/src/sql/drivers/cache/tqsqlcachedresult.h b/tqtinterface/qt4/src/sql/drivers/cache/tqsqlcachedresult.h deleted file mode 100644 index c066770..0000000 --- a/tqtinterface/qt4/src/sql/drivers/cache/tqsqlcachedresult.h +++ /dev/null @@ -1,104 +0,0 @@ -/**************************************************************************** -** -** Definition of shared TQt SQL module classes -** -** 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. -** -**********************************************************************/ - -#ifndef TQSQLCACHEDRESULT_H -#define TQSQLCACHEDRESULT_H - -// -// W A R N I N G -// ------------- -// -// This file is not part of the TQt API. It exists for the convenience -// of other TQt classes. This header file may change from version to -// version without notice, or even be removed. -// -// We mean it. -// -// - -#include <tqglobal.h> -#include <tqvariant.h> -#include <tqptrvector.h> -#include <tqvaluevector.h> -#include <tqsqlresult.h> - -#if !defined( TQT_MODULE_SQL ) || defined( TQT_LICENSE_PROFESSIONAL ) -#define TQM_EXPORT_SQL -#else -#define TQM_EXPORT_SQL TQ_EXPORT -#endif - -#ifndef TQT_NO_SQL - -class TQtSqlCachedResultPrivate; - -class TQM_EXPORT_SQL TQtSqlCachedResult: public TQSqlResult -{ -public: - virtual ~TQtSqlCachedResult(); - - typedef TQValueVector<TQVariant> RowCache; - typedef TQPtrVector<RowCache> RowsetCache; - -protected: - TQtSqlCachedResult(const TQSqlDriver * db); - - void init(int colCount); - void cleanup(); - bool cacheNext(); - - virtual bool gotoNext(RowCache* row) = 0; - - TQVariant data(int i); - bool isNull(int i); - bool fetch(int i); - bool fetchNext(); - bool fetchPrev(); - bool fetchFirst(); - bool fetchLast(); - - int colCount() const; - -private: - TQtSqlCachedResultPrivate *d; -}; - - -#endif - -#endif diff --git a/tqtinterface/qt4/src/sql/drivers/ibase/tqsql_ibase.cpp b/tqtinterface/qt4/src/sql/drivers/ibase/tqsql_ibase.cpp deleted file mode 100644 index 735363c..0000000 --- a/tqtinterface/qt4/src/sql/drivers/ibase/tqsql_ibase.cpp +++ /dev/null @@ -1,1078 +0,0 @@ -/**************************************************************************** -** -** Implementation of Interbase driver classes. -** -** Copyright (C) 2010 Timothy Pearson and (C) 1992-2008 Trolltech ASA. -** -** This file is part of the sql module of the TQt GUI Toolkit. -** EDITIONS: FREE, ENTERPRISE -** -** This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE -** WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. -** -****************************************************************************/ - -#include "tqsql_ibase.h" - -#include <tqdatetime.h> -#include <private/tqsqlextension_p.h> - -#include <ibase.h> -#include <stdlib.h> -#include <limits.h> -#include <math.h> - -#define TQIBASE_DRIVER_NAME "TQIBASE" - -class TQIBasePreparedExtension : public TQSqlExtension -{ -public: - TQIBasePreparedExtension(TQIBaseResult *r) - : result(r) {} - - bool prepare(const TQString &query) - { - return result->prepare(query); - } - - bool exec() - { - return result->exec(); - } - - TQIBaseResult *result; -}; - -static bool getIBaseError(TQString& msg, ISC_STATUS* status, long &sqlcode) -{ - if (status[0] != 1 || status[1] <= 0) - return FALSE; - - sqlcode = isc_sqlcode(status); - char buf[512]; - isc_sql_interprete(sqlcode, buf, 512); - msg = TQString::fromUtf8(buf); - return TRUE; -} - -static void createDA(XSTQLDA *&sqlda) -{ - sqlda = (XSTQLDA *) malloc(XSTQLDA_LENGTH(1)); - sqlda->sqln = 1; - sqlda->sqld = 0; - sqlda->version = STQLDA_VERSION1; - sqlda->sqlvar[0].sqlind = 0; - sqlda->sqlvar[0].sqldata = 0; -} - -static void enlargeDA(XSTQLDA *&sqlda, int n) -{ - free(sqlda); - sqlda = (XSTQLDA *) malloc(XSTQLDA_LENGTH(n)); - sqlda->sqln = n; - sqlda->version = STQLDA_VERSION1; -} - -static void initDA(XSTQLDA *sqlda) -{ - for (int i = 0; i < sqlda->sqld; ++i) { - switch (sqlda->sqlvar[i].sqltype & ~1) { - case STQL_INT64: - case STQL_LONG: - case STQL_SHORT: - case STQL_FLOAT: - case STQL_DOUBLE: - case STQL_TIMESTAMP: - case STQL_TYPE_TIME: - case STQL_TYPE_DATE: - case STQL_TEXT: - case STQL_BLOB: - sqlda->sqlvar[i].sqldata = (char*)malloc(sqlda->sqlvar[i].sqllen); - break; - case STQL_VARYING: - sqlda->sqlvar[i].sqldata = (char*)malloc(sqlda->sqlvar[i].sqllen + sizeof(short)); - break; - default: - // not supported - do not bind. - sqlda->sqlvar[i].sqldata = 0; - break; - } - if (sqlda->sqlvar[i].sqltype & 1) { - sqlda->sqlvar[i].sqlind = (short*)malloc(sizeof(short)); - *(sqlda->sqlvar[i].sqlind) = 0; - } else { - sqlda->sqlvar[i].sqlind = 0; - } - } -} - -static void delDA(XSTQLDA *&sqlda) -{ - if (!sqlda) - return; - for (int i = 0; i < sqlda->sqld; ++i) { - free(sqlda->sqlvar[i].sqlind); - free(sqlda->sqlvar[i].sqldata); - } - free(sqlda); - sqlda = 0; -} - -static TQVariant::Type qIBaseTypeName(int iType) -{ - switch (iType) { - case blr_varying: - case blr_varying2: - case blr_text: - case blr_cstring: - case blr_cstring2: - return TQVariant::String; - case blr_sql_time: - return TQVariant::Time; - case blr_sql_date: - return TQVariant::Date; - case blr_timestamp: - return TQVariant::DateTime; - case blr_blob: - return TQVariant::ByteArray; - case blr_quad: - case blr_short: - case blr_long: - return TQVariant::Int; - case blr_int64: - return TQVariant::LongLong; - case blr_float: - case blr_d_float: - case blr_double: - return TQVariant::Double; - } - return TQVariant::Invalid; -} - -static TQVariant::Type qIBaseTypeName2(int iType) -{ - switch(iType & ~1) { - case STQL_VARYING: - case STQL_TEXT: - return TQVariant::String; - case STQL_LONG: - case STQL_SHORT: - return TQVariant::Int; - case STQL_INT64: - return TQVariant::LongLong; - case STQL_FLOAT: - case STQL_DOUBLE: - return TQVariant::Double; - case STQL_TIMESTAMP: - return TQVariant::DateTime; - case STQL_TYPE_DATE: - return TQVariant::Date; - case STQL_TYPE_TIME: - return TQVariant::Time; - default: - return TQVariant::Invalid; - } -} - -static ISC_TIME toTime(const TQTime &t) -{ - static const TQTime midnight(0, 0, 0, 0); - return (ISC_TIME)midnight.msecsTo(t) * 10; -} - -static ISC_DATE toDate(const TQDate &d) -{ - static const TQDate basedate(1858, 11, 17); - return (ISC_DATE)basedate.daysTo(d); -} - -static ISC_TIMESTAMP toTimeStamp(const TQDateTime &dt) -{ - ISC_TIMESTAMP ts; - ts.timestamp_time = toTime(dt.time()); - ts.timestamp_date = toDate(dt.date()); - return ts; -} - -static TQTime toTQTime(ISC_TIME time) -{ - // have to demangle the structure ourselves because isc_decode_time - // strips the msecs - static const TQTime t; - return t.addMSecs(time / 10); -} - -static TQDate toTQDate(ISC_DATE d) -{ - static const TQDate bd(1858, 11, 17); - return bd.addDays(d); -} - -static TQDateTime toTQDateTime(ISC_TIMESTAMP *ts) -{ - return TQDateTime(toTQDate(ts->timestamp_date), toTQTime(ts->timestamp_time)); -} - -class TQIBaseDriverPrivate -{ -public: - TQIBaseDriverPrivate(TQIBaseDriver *d): q(d) - { - ibase = 0; - trans = 0; - } - - bool isError(const TQString &msg = TQString::null, TQSqlError::Type typ = TQSqlError::Unknown) - { - TQString imsg; - long sqlcode; - if (!getIBaseError(imsg, status, sqlcode)) - return FALSE; - - q->setLastError(TQSqlError(msg, imsg, typ, (int)sqlcode)); - return TRUE; - } - -public: - TQIBaseDriver* q; - isc_db_handle ibase; - isc_tr_handle trans; - ISC_STATUS status[20]; -}; - -class TQIBaseResultPrivate -{ -public: - TQIBaseResultPrivate(TQIBaseResult *d, const TQIBaseDriver *ddb); - ~TQIBaseResultPrivate() { cleanup(); } - - void cleanup(); - bool isError(const TQString &msg = TQString::null, TQSqlError::Type typ = TQSqlError::Unknown) - { - TQString imsg; - long sqlcode; - if (!getIBaseError(imsg, status, sqlcode)) - return FALSE; - - q->setLastError(TQSqlError(msg, imsg, typ, (int)sqlcode)); - return TRUE; - } - - bool transaction(); - bool commit(); - - bool isSelect(); - TQVariant fetchBlob(ISC_TQUAD *bId); - void writeBlob(int i, const TQByteArray &ba); - -public: - TQIBaseResult *q; - const TQIBaseDriver *db; - ISC_STATUS status[20]; - isc_tr_handle trans; - //indicator whether we have a local transaction or a transaction on driver level - bool localTransaction; - isc_stmt_handle stmt; - isc_db_handle ibase; - XSTQLDA *sqlda; // output sqlda - XSTQLDA *inda; // input parameters - int queryType; -}; - -TQIBaseResultPrivate::TQIBaseResultPrivate(TQIBaseResult *d, const TQIBaseDriver *ddb): - q(d), db(ddb), trans(0), stmt(0), ibase(ddb->d->ibase), sqlda(0), inda(0), queryType(-1) -{ - localTransaction = (ddb->d->ibase == 0); -} - -void TQIBaseResultPrivate::cleanup() -{ - if (stmt) { - isc_dsql_free_statement(status, &stmt, DSTQL_drop); - stmt = 0; - } - - commit(); - if (!localTransaction) - trans = 0; - - delDA(sqlda); - delDA(inda); - - queryType = -1; - q->cleanup(); -} - -void TQIBaseResultPrivate::writeBlob(int i, const TQByteArray &ba) -{ - isc_blob_handle handle = 0; - ISC_TQUAD *bId = (ISC_TQUAD*)inda->sqlvar[i].sqldata; - isc_create_blob2(status, &ibase, &trans, &handle, bId, 0, 0); - if (!isError("Unable to create BLOB", TQSqlError::Statement)) { - uint i = 0; - while (i < ba.size()) { - isc_put_segment(status, &handle, TQMIN(ba.size() - i, SHRT_MAX), ba.data()); - if (isError("Unable to write BLOB")) - break; - i += SHRT_MAX; - } - } - isc_close_blob(status, &handle); -} - -TQVariant TQIBaseResultPrivate::fetchBlob(ISC_TQUAD *bId) -{ - isc_blob_handle handle = 0; - - isc_open_blob2(status, &ibase, &trans, &handle, bId, 0, 0); - if (isError("Unable to open BLOB", TQSqlError::Statement)) - return TQVariant(); - - unsigned short len = 0; - TQByteArray ba(255); - ISC_STATUS stat = isc_get_segment(status, &handle, &len, ba.size(), ba.data()); - while (status[1] == isc_segment) { - uint osize = ba.size(); - // double the amount of data fetched on each iteration - ba.resize(TQMIN(ba.size() * 2, SHRT_MAX)); - stat = isc_get_segment(status, &handle, &len, osize, ba.data() + osize); - } - bool isErr = isError("Unable to read BLOB", TQSqlError::Statement); - isc_close_blob(status, &handle); - if (isErr) - return TQVariant(); - - if (ba.size() > 255) - ba.resize(ba.size() / 2 + len); - else - ba.resize(len); - - return ba; -} - -bool TQIBaseResultPrivate::isSelect() -{ - char acBuffer[9]; - char qType = isc_info_sql_stmt_type; - isc_dsql_sql_info(status, &stmt, 1, &qType, sizeof(acBuffer), acBuffer); - if (isError("Could not get query info", TQSqlError::Statement)) - return FALSE; - int iLength = isc_vax_integer(&acBuffer[1], 2); - queryType = isc_vax_integer(&acBuffer[3], iLength); - return (queryType == isc_info_sql_stmt_select); -} - -bool TQIBaseResultPrivate::transaction() -{ - if (trans) - return TRUE; - if (db->d->trans) { - localTransaction = FALSE; - trans = db->d->trans; - return TRUE; - } - localTransaction = TRUE; - - isc_start_transaction(status, &trans, 1, &ibase, 0, NULL); - if (isError("Could not start transaction", TQSqlError::Statement)) - return FALSE; - - return TRUE; -} - -// does nothing if the transaction is on the -// driver level -bool TQIBaseResultPrivate::commit() -{ - if (!trans) - return FALSE; - // don't commit driver's transaction, the driver will do it for us - if (!localTransaction) - return TRUE; - - isc_commit_transaction(status, &trans); - trans = 0; - return !isError("Unable to commit transaction", TQSqlError::Statement); -} - -////////// - -TQIBaseResult::TQIBaseResult(const TQIBaseDriver* db): - TQtSqlCachedResult(db) -{ - d = new TQIBaseResultPrivate(this, db); - setExtension(new TQIBasePreparedExtension(this)); -} - -TQIBaseResult::~TQIBaseResult() -{ - delete d; -} - -bool TQIBaseResult::prepare(const TQString& query) -{ - //qDebug("prepare: %s", query.ascii()); - if (!driver() || !driver()->isOpen() || driver()->isOpenError()) - return FALSE; - d->cleanup(); - setActive(FALSE); - setAt(TQSql::BeforeFirst); - - createDA(d->sqlda); - createDA(d->inda); - - if (!d->transaction()) - return FALSE; - - isc_dsql_allocate_statement(d->status, &d->ibase, &d->stmt); - if (d->isError("Could not allocate statement", TQSqlError::Statement)) - return FALSE; - isc_dsql_prepare(d->status, &d->trans, &d->stmt, 0, query.utf8().data(), 3, d->sqlda); - if (d->isError("Could not prepare statement", TQSqlError::Statement)) - return FALSE; - - isc_dsql_describe_bind(d->status, &d->stmt, 1, d->inda); - if (d->isError("Could not describe input statement", TQSqlError::Statement)) - return FALSE; - if (d->inda->sqld > d->inda->sqln) { - enlargeDA(d->inda, d->inda->sqld); - - isc_dsql_describe_bind(d->status, &d->stmt, 1, d->inda); - if (d->isError("Could not describe input statement", TQSqlError::Statement)) - return FALSE; - } - initDA(d->inda); - if (d->sqlda->sqld > d->sqlda->sqln) { - // need more field descriptors - enlargeDA(d->sqlda, d->sqlda->sqld); - - isc_dsql_describe(d->status, &d->stmt, 1, d->sqlda); - if (d->isError("Could not describe statement", TQSqlError::Statement)) - return FALSE; - } - initDA(d->sqlda); - - setSelect(d->isSelect()); - if (!isSelect()) { - free(d->sqlda); - d->sqlda = 0; - } - - return TRUE; -} - -bool TQIBaseResult::exec() -{ - if (!driver() || !driver()->isOpen() || driver()->isOpenError()) - return FALSE; - setActive(FALSE); - setAt(TQSql::BeforeFirst); - - if (d->inda && extension()->index.count() > 0) { - TQMap<int, TQString>::ConstIterator it; - if ((int)extension()->index.count() > d->inda->sqld) { - qWarning("TQIBaseResult::exec: Parameter mismatch, expected %d, got %d parameters", d->inda->sqld, extension()->index.count()); - return FALSE; - } - int para = 0; - for (it = extension()->index.constBegin(); it != extension()->index.constEnd(); ++it, ++para) { - if (para >= d->inda->sqld) - break; - if (!d->inda->sqlvar[para].sqldata) - continue; - const TQVariant val(extension()->values[it.data()].value); - if (d->inda->sqlvar[para].sqltype & 1) { - if (val.isNull()) { - // set null indicator - *(d->inda->sqlvar[para].sqlind) = 1; - // and set the value to 0, otherwise it would count as empty string. - *((short*)d->inda->sqlvar[para].sqldata) = 0; - continue; - } - // a value of 0 means non-null. - *(d->inda->sqlvar[para].sqlind) = 0; - } - switch(d->inda->sqlvar[para].sqltype & ~1) { - case STQL_INT64: - if (d->inda->sqlvar[para].sqlscale < 0) - *((TQ_LLONG*)d->inda->sqlvar[para].sqldata) = TQ_LLONG(val.toDouble() * - pow(10.0, d->inda->sqlvar[para].sqlscale * -1)); - else - *((TQ_LLONG*)d->inda->sqlvar[para].sqldata) = val.toLongLong(); - break; - case STQL_LONG: - *((long*)d->inda->sqlvar[para].sqldata) = (long)val.toLongLong(); - break; - case STQL_SHORT: - *((short*)d->inda->sqlvar[para].sqldata) = (short)val.toInt(); - break; - case STQL_FLOAT: - *((float*)d->inda->sqlvar[para].sqldata) = (float)val.toDouble(); - break; - case STQL_DOUBLE: - *((double*)d->inda->sqlvar[para].sqldata) = val.toDouble(); - break; - case STQL_TIMESTAMP: - *((ISC_TIMESTAMP*)d->inda->sqlvar[para].sqldata) = toTimeStamp(val.toDateTime()); - break; - case STQL_TYPE_TIME: - *((ISC_TIME*)d->inda->sqlvar[para].sqldata) = toTime(val.toTime()); - break; - case STQL_TYPE_DATE: - *((ISC_DATE*)d->inda->sqlvar[para].sqldata) = toDate(val.toDate()); - break; - case STQL_VARYING: { - TQCString str(val.toString().utf8()); // keep a copy of the string alive in this scope - short buflen = d->inda->sqlvar[para].sqllen; - if (str.length() < (uint)buflen) - buflen = str.length(); - *(short*)d->inda->sqlvar[para].sqldata = buflen; // first two bytes is the length - memcpy(d->inda->sqlvar[para].sqldata + sizeof(short), str.data(), buflen); - break; } - case STQL_TEXT: { - TQCString str(val.toString().utf8().leftJustify(d->inda->sqlvar[para].sqllen, ' ', TRUE)); - memcpy(d->inda->sqlvar[para].sqldata, str.data(), d->inda->sqlvar[para].sqllen); - break; } - case STQL_BLOB: - d->writeBlob(para, val.toByteArray()); - break; - default: - break; - } - } - } - - if (colCount()) { - isc_dsql_free_statement(d->status, &d->stmt, DSTQL_close); - if (d->isError("Unable to close statement")) - return FALSE; - cleanup(); - } - if (d->sqlda) - init(d->sqlda->sqld); - isc_dsql_execute2(d->status, &d->trans, &d->stmt, 1, d->inda, 0); - if (d->isError("Unable to execute query")) - return FALSE; - - setActive(TRUE); - return TRUE; -} - -bool TQIBaseResult::reset (const TQString& query) -{ -// qDebug("reset: %s", query.ascii()); - if (!driver() || !driver()->isOpen() || driver()->isOpenError()) - return FALSE; - d->cleanup(); - setActive(FALSE); - setAt(TQSql::BeforeFirst); - - createDA(d->sqlda); - - if (!d->transaction()) - return FALSE; - - isc_dsql_allocate_statement(d->status, &d->ibase, &d->stmt); - if (d->isError("Could not allocate statement", TQSqlError::Statement)) - return FALSE; - isc_dsql_prepare(d->status, &d->trans, &d->stmt, 0, query.utf8().data(), 3, d->sqlda); - if (d->isError("Could not prepare statement", TQSqlError::Statement)) - return FALSE; - - if (d->sqlda->sqld > d->sqlda->sqln) { - // need more field descriptors - int n = d->sqlda->sqld; - free(d->sqlda); - d->sqlda = (XSTQLDA *) malloc(XSTQLDA_LENGTH(n)); - d->sqlda->sqln = n; - d->sqlda->version = STQLDA_VERSION1; - - isc_dsql_describe(d->status, &d->stmt, 1, d->sqlda); - if (d->isError("Could not describe statement", TQSqlError::Statement)) - return FALSE; - } - - initDA(d->sqlda); - - setSelect(d->isSelect()); - if (isSelect()) { - init(d->sqlda->sqld); - } else { - free(d->sqlda); - d->sqlda = 0; - } - - isc_dsql_execute(d->status, &d->trans, &d->stmt, 1, 0); - if (d->isError("Unable to execute query")) - return FALSE; - - // commit non-select queries (if they are local) - if (!isSelect() && !d->commit()) - return FALSE; - - setActive(TRUE); - return TRUE; -} - -bool TQIBaseResult::gotoNext(TQtSqlCachedResult::RowCache* row) -{ - ISC_STATUS stat = isc_dsql_fetch(d->status, &d->stmt, 1, d->sqlda); - - if (stat == 100) { - // no more rows - setAt(TQSql::AfterLast); - return FALSE; - } - if (d->isError("Could not fetch next item", TQSqlError::Statement)) - return FALSE; - if (!row) // not interested in actual values - return TRUE; - - TQ_ASSERT(row); - TQ_ASSERT((int)row->size() == d->sqlda->sqld); - for (int i = 0; i < d->sqlda->sqld; ++i) { - char *buf = d->sqlda->sqlvar[i].sqldata; - int size = d->sqlda->sqlvar[i].sqllen; - TQ_ASSERT(buf); - - if ((d->sqlda->sqlvar[i].sqltype & 1) && *d->sqlda->sqlvar[i].sqlind) { - // null value - TQVariant v; - v.cast(qIBaseTypeName2(d->sqlda->sqlvar[i].sqltype)); - (*row)[i] = v; - continue; - } - - switch(d->sqlda->sqlvar[i].sqltype & ~1) { - case STQL_VARYING: - // pascal strings - a short with a length information followed by the data - (*row)[i] = TQString::fromUtf8(buf + sizeof(short), *(short*)buf); - break; - case STQL_INT64: - if (d->sqlda->sqlvar[i].sqlscale < 0) - (*row)[i] = *(TQ_LLONG*)buf * pow(10.0, d->sqlda->sqlvar[i].sqlscale); - else - (*row)[i] = TQVariant(*(TQ_LLONG*)buf); - break; - case STQL_LONG: - if (sizeof(int) == sizeof(long)) //dear compiler: please optimize me out. - (*row)[i] = TQVariant((int)(*(long*)buf)); - else - (*row)[i] = TQVariant((TQ_LLONG)(*(long*)buf)); - break; - case STQL_SHORT: - (*row)[i] = TQVariant((int)(*(short*)buf)); - break; - case STQL_FLOAT: - (*row)[i] = TQVariant((double)(*(float*)buf)); - break; - case STQL_DOUBLE: - (*row)[i] = TQVariant(*(double*)buf); - break; - case STQL_TIMESTAMP: - (*row)[i] = toTQDateTime((ISC_TIMESTAMP*)buf); - break; - case STQL_TYPE_TIME: - (*row)[i] = toTQTime(*(ISC_TIME*)buf); - break; - case STQL_TYPE_DATE: - (*row)[i] = toTQDate(*(ISC_DATE*)buf); - break; - case STQL_TEXT: - (*row)[i] = TQString::fromUtf8(buf, size); - break; - case STQL_BLOB: - (*row)[i] = d->fetchBlob((ISC_TQUAD*)buf); - break; - default: - // unknown type - don't even try to fetch - (*row)[i] = TQVariant(); - break; - } - } - - return TRUE; -} - -int TQIBaseResult::size() -{ - static char sizeInfo[] = {isc_info_sql_records}; - char buf[33]; - - if (!isActive() || !isSelect()) - return -1; - - isc_dsql_sql_info(d->status, &d->stmt, sizeof(sizeInfo), sizeInfo, sizeof(buf), buf); - for (char* c = buf + 3; *c != isc_info_end; /*nothing*/) { - char ct = *c++; - short len = isc_vax_integer(c, 2); - c += 2; - int val = isc_vax_integer(c, len); - c += len; - if (ct == isc_info_req_select_count) - return val; - } - return -1; -} - -int TQIBaseResult::numRowsAffected() -{ - static char acCountInfo[] = {isc_info_sql_records}; - char cCountType; - - switch (d->queryType) { - case isc_info_sql_stmt_select: - cCountType = isc_info_req_select_count; - break; - case isc_info_sql_stmt_update: - cCountType = isc_info_req_update_count; - break; - case isc_info_sql_stmt_delete: - cCountType = isc_info_req_delete_count; - break; - case isc_info_sql_stmt_insert: - cCountType = isc_info_req_insert_count; - break; - } - - char acBuffer[33]; - int iResult = -1; - isc_dsql_sql_info(d->status, &d->stmt, sizeof(acCountInfo), acCountInfo, sizeof(acBuffer), acBuffer); - if (d->isError("Could not get statement info", TQSqlError::Statement)) - return -1; - for (char *pcBuf = acBuffer + 3; *pcBuf != isc_info_end; /*nothing*/) { - char cType = *pcBuf++; - short sLength = isc_vax_integer (pcBuf, 2); - pcBuf += 2; - int iValue = isc_vax_integer (pcBuf, sLength); - pcBuf += sLength; - - if (cType == cCountType) { - iResult = iValue; - break; - } - } - return iResult; -} - -/*********************************/ - -TQIBaseDriver::TQIBaseDriver(TQObject * parent, const char * name) - : TQSqlDriver(parent, name ? name : TQIBASE_DRIVER_NAME) -{ - d = new TQIBaseDriverPrivate(this); -} - -TQIBaseDriver::TQIBaseDriver(void *connection, TQObject *parent, const char *name) - : TQSqlDriver(parent, name ? name : TQIBASE_DRIVER_NAME) -{ - d = new TQIBaseDriverPrivate(this); - d->ibase = (isc_db_handle)(long int)connection; - setOpen(TRUE); - setOpenError(FALSE); -} - -TQIBaseDriver::~TQIBaseDriver() -{ - delete d; -} - -bool TQIBaseDriver::hasFeature(DriverFeature f) const -{ - switch (f) { - case Transactions: -// case QuerySize: - case PreparedQueries: - case PositionalPlaceholders: - case Unicode: - case BLOB: - return TRUE; - default: - return FALSE; - } -} - -bool TQIBaseDriver::open(const TQString & db, - const TQString & user, - const TQString & password, - const TQString & host, - int /*port*/, - const TQString & /* connOpts */) -{ - if (isOpen()) - close(); - - static const char enc[8] = "UTF_FSS"; - TQCString usr = user.local8Bit(); - TQCString pass = password.local8Bit(); - usr.truncate(255); - pass.truncate(255); - - TQByteArray ba(usr.length() + pass.length() + sizeof(enc) + 6); - int i = -1; - ba[++i] = isc_dpb_version1; - ba[++i] = isc_dpb_user_name; - ba[++i] = usr.length(); - memcpy(&ba[++i], usr.data(), usr.length()); - i += usr.length(); - ba[i] = isc_dpb_password; - ba[++i] = pass.length(); - memcpy(&ba[++i], pass.data(), pass.length()); - i += pass.length(); - ba[i] = isc_dpb_lc_ctype; - ba[++i] = sizeof(enc) - 1; - memcpy(&ba[++i], enc, sizeof(enc) - 1); - i += sizeof(enc) - 1; - - TQString ldb; - if (!host.isEmpty()) - ldb += host + ":"; - ldb += db; - isc_attach_database(d->status, 0, (char*)ldb.latin1(), &d->ibase, i, ba.data()); - if (d->isError("Error opening database", TQSqlError::Connection)) { - setOpenError(TRUE); - return FALSE; - } - - setOpen(TRUE); - return TRUE; -} - -void TQIBaseDriver::close() -{ - if (isOpen()) { - isc_detach_database(d->status, &d->ibase); - d->ibase = 0; - setOpen(FALSE); - setOpenError(FALSE); - } -} - -TQSqlQuery TQIBaseDriver::createQuery() const -{ - return TQSqlQuery(new TQIBaseResult(this)); -} - -bool TQIBaseDriver::beginTransaction() -{ - if (!isOpen() || isOpenError()) - return FALSE; - if (d->trans) - return FALSE; - - isc_start_transaction(d->status, &d->trans, 1, &d->ibase, 0, NULL); - return !d->isError("Could not start transaction", TQSqlError::Transaction); -} - -bool TQIBaseDriver::commitTransaction() -{ - if (!isOpen() || isOpenError()) - return FALSE; - if (!d->trans) - return FALSE; - - isc_commit_transaction(d->status, &d->trans); - d->trans = 0; - return !d->isError("Unable to commit transaction", TQSqlError::Transaction); -} - -bool TQIBaseDriver::rollbackTransaction() -{ - if (!isOpen() || isOpenError()) - return FALSE; - if (!d->trans) - return FALSE; - - isc_rollback_transaction(d->status, &d->trans); - d->trans = 0; - return !d->isError("Unable to rollback transaction", TQSqlError::Transaction); -} - -TQStringList TQIBaseDriver::tables(const TQString& typeName) const -{ - TQStringList res; - if (!isOpen()) - return res; - - int type = typeName.isEmpty() ? (int)TQSql::Tables | (int)TQSql::Views : typeName.toInt(); - TQString typeFilter; - - if (type == (int)TQSql::SystemTables) { - typeFilter += "RDB$SYSTEM_FLAG != 0"; - } else if (type == ((int)TQSql::SystemTables | (int)TQSql::Views)) { - typeFilter += "RDB$SYSTEM_FLAG != 0 OR RDB$VIEW_BLR NOT NULL"; - } else { - if (!(type & (int)TQSql::SystemTables)) - typeFilter += "RDB$SYSTEM_FLAG = 0 AND "; - if (!(type & (int)TQSql::Views)) - typeFilter += "RDB$VIEW_BLR IS NULL AND "; - if (!(type & (int)TQSql::Tables)) - typeFilter += "RDB$VIEW_BLR IS NOT NULL AND "; - if (!typeFilter.isEmpty()) - typeFilter.truncate(typeFilter.length() - 5); - } - if (!typeFilter.isEmpty()) - typeFilter.prepend("where "); - - TQSqlQuery q = createQuery(); - q.setForwardOnly(TRUE); - if (!q.exec("select rdb$relation_name from rdb$relations " + typeFilter)) - return res; - while(q.next()) - res << q.value(0).toString().stripWhiteSpace(); - - return res; -} - -TQSqlRecord TQIBaseDriver::record(const TQString& tablename) const -{ - TQSqlRecord rec; - if (!isOpen()) - return rec; - - TQSqlQuery q = createQuery(); - q.setForwardOnly(TRUE); - - q.exec("SELECT a.RDB$FIELD_NAME, b.RDB$FIELD_TYPE " - "FROM RDB$RELATION_FIELDS a, RDB$FIELDS b " - "WHERE b.RDB$FIELD_NAME = a.RDB$FIELD_SOURCE " - "AND a.RDB$RELATION_NAME = '" + tablename.upper()+ "' " - "ORDER BY RDB$FIELD_POSITION"); - while (q.next()) { - TQSqlField field(q.value(0).toString().stripWhiteSpace(), qIBaseTypeName(q.value(1).toInt())); - rec.append(field); - } - - return rec; -} - -TQSqlRecordInfo TQIBaseDriver::recordInfo(const TQString& tablename) const -{ - TQSqlRecordInfo rec; - if (!isOpen()) - return rec; - - TQSqlQuery q = createQuery(); - q.setForwardOnly(TRUE); - - q.exec("SELECT a.RDB$FIELD_NAME, b.RDB$FIELD_TYPE, b.RDB$FIELD_LENGTH, b.RDB$FIELD_SCALE, " - "b.RDB$FIELD_PRECISION, a.RDB$NULL_FLAG " - "FROM RDB$RELATION_FIELDS a, RDB$FIELDS b " - "WHERE b.RDB$FIELD_NAME = a.RDB$FIELD_SOURCE " - "AND a.RDB$RELATION_NAME = '" + tablename.upper() + "' " - "ORDER BY a.RDB$FIELD_POSITION"); - - while (q.next()) { - TQVariant::Type type = qIBaseTypeName(q.value(1).toInt()); - TQSqlFieldInfo field(q.value(0).toString().stripWhiteSpace(), type, q.value(5).toInt(), - q.value(2).toInt(), q.value(4).toInt(), TQVariant()); - - rec.append(field); - } - - return rec; -} - -TQSqlIndex TQIBaseDriver::primaryIndex(const TQString &table) const -{ - TQSqlIndex index(table); - if (!isOpen()) - return index; - - TQSqlQuery q = createQuery(); - q.setForwardOnly(TRUE); - q.exec("SELECT a.RDB$INDEX_NAME, b.RDB$FIELD_NAME, d.RDB$FIELD_TYPE " - "FROM RDB$RELATION_CONSTRAINTS a, RDB$INDEX_SEGMENTS b, RDB$RELATION_FIELDS c, RDB$FIELDS d " - "WHERE a.RDB$CONSTRAINT_TYPE = 'PRIMARY KEY' " - "AND a.RDB$RELATION_NAME = '" + table.upper() + "' " - "AND a.RDB$INDEX_NAME = b.RDB$INDEX_NAME " - "AND c.RDB$RELATION_NAME = a.RDB$RELATION_NAME " - "AND c.RDB$FIELD_NAME = b.RDB$FIELD_NAME " - "AND d.RDB$FIELD_NAME = c.RDB$FIELD_SOURCE " - "ORDER BY b.RDB$FIELD_POSITION"); - - while (q.next()) { - TQSqlField field(q.value(1).toString().stripWhiteSpace(), qIBaseTypeName(q.value(2).toInt())); - index.append(field); //TODO: asc? desc? - index.setName(q.value(0).toString()); - } - - return index; -} - -TQSqlRecord TQIBaseDriver::record(const TQSqlQuery& query) const -{ - TQSqlRecord rec; - if (query.isActive() && query.driver() == this) { - TQIBaseResult* result = (TQIBaseResult*)query.result(); - if (!result->d->sqlda) - return rec; - XSTQLVAR v; - for (int i = 0; i < result->d->sqlda->sqld; ++i) { - v = result->d->sqlda->sqlvar[i]; - TQSqlField f(TQString::tqfromLatin1(v.sqlname, v.sqlname_length).stripWhiteSpace(), - qIBaseTypeName2(result->d->sqlda->sqlvar[i].sqltype)); - rec.append(f); - } - } - return rec; -} - -TQSqlRecordInfo TQIBaseDriver::recordInfo(const TQSqlQuery& query) const -{ - TQSqlRecordInfo rec; - if (query.isActive() && query.driver() == this) { - TQIBaseResult* result = (TQIBaseResult*)query.result(); - if (!result->d->sqlda) - return rec; - XSTQLVAR v; - for (int i = 0; i < result->d->sqlda->sqld; ++i) { - v = result->d->sqlda->sqlvar[i]; - TQSqlFieldInfo f(TQString::tqfromLatin1(v.sqlname, v.sqlname_length).stripWhiteSpace(), - qIBaseTypeName2(result->d->sqlda->sqlvar[i].sqltype), - -1, v.sqllen, TQABS(v.sqlscale), TQVariant(), v.sqltype); - rec.append(f); - } - } - return rec; -} - -TQString TQIBaseDriver::formatValue(const TQSqlField* field, bool trimStrings) const -{ - switch (field->type()) { - case TQVariant::DateTime: { - TQDateTime datetime = field->value().toDateTime(); - if (datetime.isValid()) - return "'" + TQString::number(datetime.date().year()) + "-" + - TQString::number(datetime.date().month()) + "-" + - TQString::number(datetime.date().day()) + " " + - TQString::number(datetime.time().hour()) + ":" + - TQString::number(datetime.time().minute()) + ":" + - TQString::number(datetime.time().second()) + "." + - TQString::number(datetime.time().msec()).rightJustify(3, '0', TRUE) + "'"; - else - return "NULL"; - } - case TQVariant::Time: { - TQTime time = field->value().toTime(); - if (time.isValid()) - return "'" + TQString::number(time.hour()) + ":" + - TQString::number(time.minute()) + ":" + - TQString::number(time.second()) + "." + - TQString::number(time.msec()).rightJustify(3, '0', TRUE) + "'"; - else - return "NULL"; - } - case TQVariant::Date: { - TQDate date = field->value().toDate(); - if (date.isValid()) - return "'" + TQString::number(date.year()) + "-" + - TQString::number(date.month()) + "-" + - TQString::number(date.day()) + "'"; - else - return "NULL"; - } - default: - return TQSqlDriver::formatValue(field, trimStrings); - } -} diff --git a/tqtinterface/qt4/src/sql/drivers/ibase/tqsql_ibase.h b/tqtinterface/qt4/src/sql/drivers/ibase/tqsql_ibase.h deleted file mode 100644 index e720c1c..0000000 --- a/tqtinterface/qt4/src/sql/drivers/ibase/tqsql_ibase.h +++ /dev/null @@ -1,117 +0,0 @@ -/**************************************************************************** -** -** Definition of Interbase driver classes -** -** Created : 030911 -** -** 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. -** -**********************************************************************/ - -#ifndef TQSQL_IBASE_H -#define TQSQL_IBASE_H - -#include "tqsqlresult.h" -#include "tqsqldriver.h" -#include "../cache/tqsqlcachedresult.h" - - -class TQIBaseDriverPrivate; -class TQIBaseResultPrivate; -class TQIBaseDriver; - -class TQIBaseResult : public TQtSqlCachedResult -{ - friend class TQIBaseDriver; - friend class TQIBaseResultPrivate; - -public: - TQIBaseResult(const TQIBaseDriver* db); - virtual ~TQIBaseResult(); - - bool prepare(const TQString& query); - bool exec(); - -protected: - bool gotoNext(TQtSqlCachedResult::RowCache* row); - bool reset (const TQString& query); - int size(); - int numRowsAffected(); - -private: - TQIBaseResultPrivate* d; -}; - -class TQIBaseDriver : public TQSqlDriver -{ - friend class TQIBaseDriverPrivate; - friend class TQIBaseResultPrivate; - friend class TQIBaseResult; -public: - TQIBaseDriver(TQObject *parent = 0, const char *name = 0); - TQIBaseDriver(void *connection, TQObject *parent = 0, const char *name = 0); - virtual ~TQIBaseDriver(); - bool hasFeature(DriverFeature f) const; - bool open(const TQString & db, - const TQString & user, - const TQString & password, - const TQString & host, - int port, - const TQString & connOpts); - bool open( const TQString & db, - const TQString & user, - const TQString & password, - const TQString & host, - int port ) { return open (db, user, password, host, port, TQString()); } - void close(); - TQSqlQuery createQuery() const; - bool beginTransaction(); - bool commitTransaction(); - bool rollbackTransaction(); - TQStringList tables(const TQString& typeName) const; - - TQSqlRecord record(const TQString& tablename) const; - TQSqlRecordInfo recordInfo(const TQString& tablename) const; - TQSqlIndex primaryIndex(const TQString &table) const; - TQSqlRecord record(const TQSqlQuery& query) const; - TQSqlRecordInfo recordInfo(const TQSqlQuery& query) const; - - TQString formatValue(const TQSqlField* field, bool trimStrings) const; - -private: - TQIBaseDriverPrivate* d; -}; - - -#endif - diff --git a/tqtinterface/qt4/src/sql/drivers/mysql/tqsql_mysql.cpp b/tqtinterface/qt4/src/sql/drivers/mysql/tqsql_mysql.cpp deleted file mode 100644 index 98cccb2..0000000 --- a/tqtinterface/qt4/src/sql/drivers/mysql/tqsql_mysql.cpp +++ /dev/null @@ -1,775 +0,0 @@ -/**************************************************************************** -** -** Implementation of MYSQL 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_mysql.h" -#include <private/tqsqlextension_p.h> - -#include <tqdatetime.h> -#include <tqvaluevector.h> -#include <tqsqlrecord.h> - -#define TQMYSTQL_DRIVER_NAME "TQMYSQL3" - -#ifdef TQ_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 TQ_NO_MYSTQL_EMBEDDED -#endif - -TQPtrDict<TQSqlOpenExtension> *qSqlOpenExtDict(); - -static int qMySqlConnectionCount = 0; -static bool qMySqlInitHandledByUser = FALSE; - -class TQMYSTQLOpenExtension : public TQSqlOpenExtension -{ -public: - TQMYSTQLOpenExtension( TQMYSTQLDriver *dri ) - : TQSqlOpenExtension(), driver(dri) {} - ~TQMYSTQLOpenExtension() {} - - bool open( const TQString& db, - const TQString& user, - const TQString& password, - const TQString& host, - int port, - const TQString& connOpts ); - -private: - TQMYSTQLDriver *driver; -}; - -bool TQMYSTQLOpenExtension::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 TQMYSTQLDriverPrivate -{ -public: - TQMYSTQLDriverPrivate() : mysql(0) {} - MYSQL* mysql; -}; - -class TQMYSTQLResultPrivate : public TQMYSTQLDriverPrivate -{ -public: - TQMYSTQLResultPrivate() : TQMYSTQLDriverPrivate(), result(0) {} - MYSTQL_RES* result; - MYSTQL_ROW row; - TQValueVector<TQVariant::Type> fieldTypes; -}; - -TQSqlError qMakeError( const TQString& err, int type, const TQMYSTQLDriverPrivate* p ) -{ - return TQSqlError(TQMYSTQL_DRIVER_NAME ": " + err, TQString(mysql_error( p->mysql )), type, mysql_errno( p->mysql )); -} - -TQVariant::Type qDecodeMYSTQLType( 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; -} - -TQMYSTQLResult::TQMYSTQLResult( const TQMYSTQLDriver* db ) -: TQSqlResult( db ) -{ - d = new TQMYSTQLResultPrivate(); - d->mysql = db->d->mysql; -} - -TQMYSTQLResult::~TQMYSTQLResult() -{ - cleanup(); - delete d; -} - -MYSTQL_RES* TQMYSTQLResult::result() -{ - return d->result; -} - -void TQMYSTQLResult::cleanup() -{ - if ( d->result ) { - mysql_free_result( d->result ); - } - d->result = NULL; - d->row = NULL; - setAt( -1 ); - setActive( FALSE ); -} - -bool TQMYSTQLResult::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 TQMYSTQLResult::fetchNext() -{ - d->row = mysql_fetch_row( d->result ); - if ( !d->row ) - return FALSE; - setAt( at() + 1 ); - return TRUE; -} - -bool TQMYSTQLResult::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 TQMYSTQLResult::fetchFirst() -{ - if ( isForwardOnly() ) // again, fake it - return fetchNext(); - return fetch( 0 ); -} - -TQVariant TQMYSTQLResult::data( int field ) -{ - if ( !isSelect() || field >= (int) d->fieldTypes.count() ) { - qWarning( "TQMYSTQLResult::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 TQT_CHECK_RANGE - qWarning("TQMYSTQLResult::data: unknown data type"); -#endif - return TQVariant(); -} - -bool TQMYSTQLResult::isNull( int field ) -{ - if ( d->row[field] == NULL ) - return TRUE; - return FALSE; -} - -bool TQMYSTQLResult::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++) { - MYSTQL_FIELD* field = mysql_fetch_field_direct( d->result, i ); - if ( field->type == FIELD_TYPE_DECIMAL ) - d->fieldTypes[i] = TQVariant::String; - else - d->fieldTypes[i] = qDecodeMYSTQLType( field->type, field->flags ); - } - } - setActive( TRUE ); - return TRUE; -} - -int TQMYSTQLResult::size() -{ - return isSelect() ? (int)mysql_num_rows( d->result ) : -1; -} - -int TQMYSTQLResult::numRowsAffected() -{ - return (int)mysql_affected_rows( d->mysql ); -} - -///////////////////////////////////////////////////////// -static void qServerEnd() -{ -#ifndef TQ_NO_MYSTQL_EMBEDDED -# if MYSTQL_VERSION_ID >= 40000 - mysql_server_end(); -# endif // MYSTQL_VERSION_ID -#endif // TQ_NO_MYSTQL_EMBEDDED -} - -static void qServerInit() -{ -#ifndef TQ_NO_MYSTQL_EMBEDDED -# if MYSTQL_VERSION_ID >= 40000 - if ( qMySqlInitHandledByUser || qMySqlConnectionCount > 1 ) - return; - - // this should only be called once - // has no effect on client/server library - // but is vital for the embedded lib - if ( mysql_server_init( 0, 0, 0 ) ) { -# ifdef TQT_CHECK_RANGE - qWarning( "TQMYSTQLDriver::qServerInit: unable to start server." ); -# endif - } - -# endif // MYSTQL_VERSION_ID -#endif // TQ_NO_MYSTQL_EMBEDDED -} - -TQMYSTQLDriver::TQMYSTQLDriver( TQObject * parent, const char * name ) - : TQSqlDriver( parent, name ? name : TQMYSTQL_DRIVER_NAME ) -{ - init(); - qServerInit(); -} - -/*! - Create a driver instance with an already open connection handle. -*/ - -TQMYSTQLDriver::TQMYSTQLDriver( MYSQL * con, TQObject * parent, const char * name ) - : TQSqlDriver( parent, name ? name : TQMYSTQL_DRIVER_NAME ) -{ - init(); - if ( con ) { - d->mysql = (MYSQL *) con; - setOpen( TRUE ); - setOpenError( FALSE ); - if (qMySqlConnectionCount == 1) - qMySqlInitHandledByUser = TRUE; - } else { - qServerInit(); - } -} - -void TQMYSTQLDriver::init() -{ - qSqlOpenExtDict()->insert( this, new TQMYSTQLOpenExtension(this) ); - d = new TQMYSTQLDriverPrivate(); - d->mysql = 0; - qMySqlConnectionCount++; -} - -TQMYSTQLDriver::~TQMYSTQLDriver() -{ - qMySqlConnectionCount--; - if (qMySqlConnectionCount == 0 && !qMySqlInitHandledByUser) - qServerEnd(); - - delete d; - if ( !qSqlOpenExtDict()->isEmpty() ) { - TQSqlOpenExtension *ext = qSqlOpenExtDict()->take( this ); - delete ext; - } -} - -bool TQMYSTQLDriver::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 TQMYSTQLDriver::open( const TQString&, - const TQString&, - const TQString&, - const TQString&, - int ) -{ - qWarning("TQMYSTQLDriver::open(): This version of open() is no longer supported." ); - return FALSE; -} - -bool TQMYSTQLDriver::open( const TQString& db, - const TQString& user, - const TQString& password, - const TQString& host, - int port, - const TQString& connOpts ) -{ - if ( isOpen() ) - close(); - - unsigned int optionFlags = 0; - - TQStringList raw = TQStringList::split( ';', connOpts ); - TQStringList opts; - TQStringList::ConstIterator it; - - // extract the real options from the string - for ( it = raw.begin(); it != raw.end(); ++it ) { - TQString tmp( *it ); - int idx; - if ( (idx = tmp.find( '=' )) != -1 ) { - TQString val( tmp.mid( idx + 1 ) ); - val.simplifyWhiteSpace(); - if ( val == "TRUE" || val == "1" ) - opts << tmp.left( idx ); - else - qWarning( "TQMYSTQLDriver::open: Illegal connect option value '%s'", tmp.latin1() ); - } else { - opts << tmp; - } - } - - for ( it = opts.begin(); it != opts.end(); ++it ) { - TQString opt( (*it).upper() ); - if ( opt == "CLIENT_COMPRESS" ) - optionFlags |= CLIENT_COMPRESS; - else if ( opt == "CLIENT_FOUND_ROWS" ) - optionFlags |= CLIENT_FOUND_ROWS; - else if ( opt == "CLIENT_IGNORE_SPACE" ) - optionFlags |= CLIENT_IGNORE_SPACE; - else if ( opt == "CLIENT_INTERACTIVE" ) - optionFlags |= CLIENT_INTERACTIVE; - else if ( opt == "CLIENT_NO_SCHEMA" ) - optionFlags |= CLIENT_NO_SCHEMA; - else if ( opt == "CLIENT_ODBC" ) - optionFlags |= CLIENT_ODBC; - else if ( opt == "CLIENT_SSL" ) - optionFlags |= CLIENT_SSL; - else - qWarning( "TQMYSTQLDriver::open: Unknown connect option '%s'", (*it).latin1() ); - } - - if ( (d->mysql = mysql_init((MYSQL*) 0)) && - mysql_real_connect( d->mysql, - host, - user, - password, - db.isNull() ? TQString("") : db, - (port > -1) ? port : 0, - NULL, - optionFlags ) ) - { - 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 TQMYSTQLDriver::close() -{ - if ( isOpen() ) { - mysql_close( d->mysql ); - setOpen( FALSE ); - setOpenError( FALSE ); - } -} - -TQSqlQuery TQMYSTQLDriver::createQuery() const -{ - return TQSqlQuery( new TQMYSTQLResult( this ) ); -} - -TQStringList TQMYSTQLDriver::tables( const TQString& typeName ) const -{ - TQStringList tl; - if ( !isOpen() ) - return tl; - if ( !typeName.isEmpty() && !(typeName.toInt() & (int)TQSql::Tables) ) - return tl; - - MYSTQL_RES* tableRes = mysql_list_tables( d->mysql, NULL ); - MYSTQL_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 TQMYSTQLDriver::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 TQMYSTQLDriver::record( const TQString& tablename ) const -{ - TQSqlRecord fil; - if ( !isOpen() ) - return fil; - MYSTQL_RES* r = mysql_list_fields( d->mysql, tablename.local8Bit().data(), 0); - if ( !r ) { - return fil; - } - MYSTQL_FIELD* field; - while ( (field = mysql_fetch_field( r ))) { - TQSqlField f ( TQString( field->name ) , qDecodeMYSTQLType( (int)field->type, field->flags ) ); - fil.append ( f ); - } - mysql_free_result( r ); - return fil; -} - -TQSqlRecord TQMYSTQLDriver::record( const TQSqlQuery& query ) const -{ - TQSqlRecord fil; - if ( !isOpen() ) - return fil; - if ( query.isActive() && query.isSelect() && query.driver() == this ) { - TQMYSTQLResult* result = (TQMYSTQLResult*)query.result(); - TQMYSTQLResultPrivate* p = result->d; - if ( !mysql_errno( p->mysql ) ) { - for ( ;; ) { - MYSTQL_FIELD* f = mysql_fetch_field( p->result ); - if ( f ) { - TQSqlField fi( TQString((const char*)f->name), qDecodeMYSTQLType( f->type, f->flags ) ); - fil.append( fi ); - } else - break; - } - } - mysql_field_seek( p->result, 0 ); - } - return fil; -} - -TQSqlRecordInfo TQMYSTQLDriver::recordInfo( const TQString& tablename ) const -{ - TQSqlRecordInfo info; - if ( !isOpen() ) - return info; - MYSTQL_RES* r = mysql_list_fields( d->mysql, tablename.local8Bit().data(), 0); - if ( !r ) { - return info; - } - MYSTQL_FIELD* field; - while ( (field = mysql_fetch_field( r ))) { - info.append ( TQSqlFieldInfo( TQString( field->name ), - qDecodeMYSTQLType( (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 TQMYSTQLDriver::recordInfo( const TQSqlQuery& query ) const -{ - TQSqlRecordInfo info; - if ( !isOpen() ) - return info; - if ( query.isActive() && query.isSelect() && query.driver() == this ) { - TQMYSTQLResult* result = (TQMYSTQLResult*)query.result(); - TQMYSTQLResultPrivate* p = result->d; - if ( !mysql_errno( p->mysql ) ) { - for ( ;; ) { - MYSTQL_FIELD* field = mysql_fetch_field( p->result ); - if ( field ) { - info.append ( TQSqlFieldInfo( TQString( field->name ), - qDecodeMYSTQLType( (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* TQMYSTQLDriver::mysql() -{ - return d->mysql; -} - -bool TQMYSTQLDriver::beginTransaction() -{ -#ifndef CLIENT_TRANSACTIONS - return FALSE; -#endif - if ( !isOpen() ) { -#ifdef TQT_CHECK_RANGE - qWarning( "TQMYSTQLDriver::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 TQMYSTQLDriver::commitTransaction() -{ -#ifndef CLIENT_TRANSACTIONS - return FALSE; -#endif - if ( !isOpen() ) { -#ifdef TQT_CHECK_RANGE - qWarning( "TQMYSTQLDriver::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 TQMYSTQLDriver::rollbackTransaction() -{ -#ifndef CLIENT_TRANSACTIONS - return FALSE; -#endif - if ( !isOpen() ) { -#ifdef TQT_CHECK_RANGE - qWarning( "TQMYSTQLDriver::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 TQMYSTQLDriver::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/tqtinterface/qt4/src/sql/drivers/mysql/tqsql_mysql.h b/tqtinterface/qt4/src/sql/drivers/mysql/tqsql_mysql.h deleted file mode 100644 index 385d900..0000000 --- a/tqtinterface/qt4/src/sql/drivers/mysql/tqsql_mysql.h +++ /dev/null @@ -1,131 +0,0 @@ -/**************************************************************************** -** -** Definition of MySQL 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. -** -**********************************************************************/ - -#ifndef TQSQL_MYSTQL_H -#define TQSQL_MYSTQL_H - -#include <tqsqldriver.h> -#include <tqsqlresult.h> -#include <tqsqlfield.h> -#include <tqsqlindex.h> - -#if defined (TQ_OS_WIN32) -#include <tqt_windows.h> -#endif - -#include <mysql.h> - -#ifdef TQT_PLUGIN -#define TQ_EXPORT_STQLDRIVER_MYSQL -#else -#define TQ_EXPORT_STQLDRIVER_MYSQL TQ_EXPORT -#endif - -class TQMYSTQLDriverPrivate; -class TQMYSTQLResultPrivate; -class TQMYSTQLDriver; -class TQSqlRecordInfo; - -class TQMYSTQLResult : public TQSqlResult -{ - friend class TQMYSTQLDriver; -public: - TQMYSTQLResult( const TQMYSTQLDriver* db ); - ~TQMYSTQLResult(); - - MYSTQL_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: - TQMYSTQLResultPrivate* d; -}; - -class TQ_EXPORT_STQLDRIVER_MYSQL TQMYSTQLDriver : public TQSqlDriver -{ - friend class TQMYSTQLResult; -public: - TQMYSTQLDriver( TQObject * parent=0, const char * name=0 ); - TQMYSTQLDriver( MYSQL * con, TQObject * parent=0, const char * name=0 ); - ~TQMYSTQLDriver(); - 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(); - 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(); - TQMYSTQLDriverPrivate* d; -}; - - -#endif diff --git a/tqtinterface/qt4/src/sql/drivers/odbc/tqsql_odbc.cpp b/tqtinterface/qt4/src/sql/drivers/odbc/tqsql_odbc.cpp deleted file mode 100644 index 8e75f90..0000000 --- a/tqtinterface/qt4/src/sql/drivers/odbc/tqsql_odbc.cpp +++ /dev/null @@ -1,2035 +0,0 @@ -/**************************************************************************** -** -** Implementation of ODBC 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_odbc.h" -#include <tqsqlrecord.h> - -#if defined (TQ_OS_WIN32) -#include <tqt_windows.h> -#include <tqapplication.h> -#endif -#include <tqdatetime.h> -#include <private/tqsqlextension_p.h> -#include <private/tqinternal_p.h> -#include <stdlib.h> - -// undefine this to prevent initial check of the ODBC driver -#define ODBC_CHECK_DRIVER - -#if defined(TQ_ODBC_VERSION_2) -//crude hack to get non-tqunicode capable driver managers to work -# undef UNICODE -# define STQLTCHAR STQLCHAR -# define STQL_C_WCHAR STQL_C_CHAR -#endif - -// newer platform SDKs use STQLLEN instead of STQLINTEGER -#ifdef STQLLEN -# define TQSTQLLEN STQLLEN -#else -# define TQSTQLLEN STQLINTEGER -#endif - -#ifdef STQLULEN -# define TQSQLULEN STQLULEN -#else -# define TQSQLULEN STQLUINTEGER -#endif - - -static const TQSTQLLEN COLNAMESIZE = 256; -//Map TQt parameter types to ODBC types -static const STQLSMALLINT qParamType[ 4 ] = { STQL_PARAM_INPUT, STQL_PARAM_INPUT, STQL_PARAM_OUTPUT, STQL_PARAM_INPUT_OUTPUT }; - -class TQODBCPrivate -{ -public: - TQODBCPrivate() - : hEnv(0), hDbc(0), hStmt(0), useSchema(FALSE) - { - sql_char_type = sql_varchar_type = sql_longvarchar_type = TQVariant::CString; - tqunicode = FALSE; - } - - STQLHANDLE hEnv; - STQLHANDLE hDbc; - STQLHANDLE hStmt; - - bool tqunicode; - bool useSchema; - TQVariant::Type sql_char_type; - TQVariant::Type sql_varchar_type; - TQVariant::Type sql_longvarchar_type; - - TQSqlRecordInfo rInf; - - bool checkDriver() const; - void checkUnicode(); - void checkSchemaUsage(); - bool setConnectionOptions( const TQString& connOpts ); - void splitTableQualifier(const TQString &qualifier, TQString &catalog, - TQString &schema, TQString &table); -}; - -class TQODBCPreparedExtension : public TQSqlExtension -{ -public: - TQODBCPreparedExtension( TQODBCResult * r ) - : result( r ) {} - - bool prepare( const TQString& query ) - { - return result->prepare( query ); - } - - bool exec() - { - return result->exec(); - } - - TQODBCResult * result; -}; - -TQPtrDict<TQSqlOpenExtension> *qSqlOpenExtDict(); - -class TQODBCOpenExtension : public TQSqlOpenExtension -{ -public: - TQODBCOpenExtension( TQODBCDriver *dri ) - : TQSqlOpenExtension(), driver(dri) {} - ~TQODBCOpenExtension() {} - - bool open( const TQString& db, - const TQString& user, - const TQString& password, - const TQString& host, - int port, - const TQString& connOpts ); -private: - TQODBCDriver *driver; -}; - -bool TQODBCOpenExtension::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 TQString qWarnODBCHandle(int handleType, STQLHANDLE handle) -{ - STQLINTEGER nativeCode_; - STQLSMALLINT msgLen; - STQLRETURN r = STQL_ERROR; - STQLTCHAR state_[STQL_STQLSTATE_SIZE+1]; - STQLTCHAR description_[STQL_MAX_MESSAGE_LENGTH]; - r = STQLGetDiagRec( handleType, - handle, - 1, - (STQLTCHAR*)state_, - &nativeCode_, - (STQLTCHAR*)description_, - STQL_MAX_MESSAGE_LENGTH-1, /* in bytes, not in characters */ - &msgLen); - if ( r == STQL_SUCCESS || r == STQL_SUCCESS_WITH_INFO ) -#ifdef UNICODE - return TQString( (const TQChar*)description_, (uint)msgLen ); -#else - return TQString::fromLocal8Bit( (const char*)description_ ); -#endif - return TQString::null; -} - -static TQString qODBCWarn( const TQODBCPrivate* odbc) -{ - return ( qWarnODBCHandle( STQL_HANDLE_ENV, odbc->hEnv ) + " " - + qWarnODBCHandle( STQL_HANDLE_DBC, odbc->hDbc ) + " " - + qWarnODBCHandle( STQL_HANDLE_STMT, odbc->hStmt ) ); -} - -static void qSqlWarning( const TQString& message, const TQODBCPrivate* odbc ) -{ -#ifdef TQT_CHECK_RANGE - qWarning( "%s\tError: %s", message.local8Bit().data(), qODBCWarn( odbc ).local8Bit().data() ); -#endif -} - -static TQSqlError qMakeError( const TQString& err, int type, const TQODBCPrivate* p ) -{ - return TQSqlError( "TQODBC3: " + err, qODBCWarn(p), type ); -} - -static TQVariant::Type qDecodeODBCType( STQLSMALLINT sqltype, const TQODBCPrivate* p ) -{ - TQVariant::Type type = TQVariant::Invalid; - switch ( sqltype ) { - case STQL_DECIMAL: - case STQL_NUMERIC: - case STQL_REAL: - case STQL_FLOAT: - case STQL_DOUBLE: - type = TQVariant::Double; - break; - case STQL_SMALLINT: - case STQL_INTEGER: - case STQL_BIT: - case STQL_TINYINT: - type = TQVariant::Int; - break; - case STQL_BIGINT: - type = TQVariant::LongLong; - break; - case STQL_BINARY: - case STQL_VARBINARY: - case STQL_LONGVARBINARY: - type = TQVariant::ByteArray; - break; - case STQL_DATE: - case STQL_TYPE_DATE: - type = TQVariant::Date; - break; - case STQL_TIME: - case STQL_TYPE_TIME: - type = TQVariant::Time; - break; - case STQL_TIMESTAMP: - case STQL_TYPE_TIMESTAMP: - type = TQVariant::DateTime; - break; -#ifndef TQ_ODBC_VERSION_2 - case STQL_WCHAR: - case STQL_WVARCHAR: - case STQL_WLONGVARCHAR: - type = TQVariant::String; - break; -#endif - case STQL_CHAR: - type = p->sql_char_type; - break; - case STQL_VARCHAR: - type = p->sql_varchar_type; - break; - case STQL_LONGVARCHAR: - type = p->sql_longvarchar_type; - break; - default: - type = TQVariant::CString; - break; - } - return type; -} - -static TQString qGetStringData( STQLHANDLE hStmt, int column, int colSize, bool& isNull, bool tqunicode = FALSE ) -{ - TQString fieldVal; - STQLRETURN r = STQL_ERROR; - TQSTQLLEN lengthIndicator = 0; - - if ( colSize <= 0 ) { - colSize = 256; - } else if ( colSize > 65536 ) { // limit buffer size to 64 KB - colSize = 65536; - } else { - colSize++; // make sure there is room for more than the 0 termination - if ( tqunicode ) { - colSize *= 2; // a tiny bit faster, since it saves a STQLGetData() call - } - } - char* buf = new char[ colSize ]; - while ( TRUE ) { - r = STQLGetData( hStmt, - column+1, - tqunicode ? STQL_C_WCHAR : STQL_C_CHAR, - (STQLPOINTER)buf, - (TQSTQLLEN)colSize, - &lengthIndicator ); - if ( r == STQL_SUCCESS || r == STQL_SUCCESS_WITH_INFO ) { - if ( lengthIndicator == STQL_NULL_DATA || lengthIndicator == STQL_NO_TOTAL ) { - fieldVal = TQString::null; - isNull = TRUE; - break; - } - // if STQL_SUCCESS_WITH_INFO is returned, indicating that - // more data can be fetched, the length indicator does NOT - // contain the number of bytes returned - it contains the - // total number of bytes that CAN be fetched - // colSize-1: remove 0 termination when there is more data to fetch - int rSize = (r == STQL_SUCCESS_WITH_INFO) ? (tqunicode ? colSize-2 : colSize-1) : lengthIndicator; - if ( tqunicode ) { - fieldVal += TQString( (TQChar*) buf, rSize / 2 ); - } else { - buf[ rSize ] = 0; - fieldVal += buf; - } - if ( lengthIndicator < colSize ) { - // workaround for Drivermanagers that don't return STQL_NO_DATA - break; - } - } else if ( r == STQL_NO_DATA ) { - break; - } else { -#ifdef TQT_CHECK_RANGE - qWarning( "qGetStringData: Error while fetching data (%d)", r ); -#endif - fieldVal = TQString::null; - break; - } - } - delete[] buf; - return fieldVal; -} - -static TQByteArray qGetBinaryData( STQLHANDLE hStmt, int column, TQSTQLLEN& lengthIndicator, bool& isNull ) -{ - TQByteArray fieldVal; - STQLSMALLINT colNameLen; - STQLSMALLINT colType; - TQSQLULEN colSize; - STQLSMALLINT colScale; - STQLSMALLINT nullable; - STQLRETURN r = STQL_ERROR; - - STQLTCHAR colName[COLNAMESIZE]; - r = STQLDescribeCol( hStmt, - column+1, - colName, - COLNAMESIZE, - &colNameLen, - &colType, - &colSize, - &colScale, - &nullable ); -#ifdef TQT_CHECK_RANGE - if ( r != STQL_SUCCESS ) - qWarning( "qGetBinaryData: Unable to describe column %d", column ); -#endif - // STQLDescribeCol may return 0 if size cannot be determined - if (!colSize) { - colSize = 256; - } - if ( colSize > 65536 ) { // read the field in 64 KB chunks - colSize = 65536; - } - char * buf = new char[ colSize ]; - while ( TRUE ) { - r = STQLGetData( hStmt, - column+1, - STQL_C_BINARY, - (STQLPOINTER) buf, - (TQSTQLLEN)colSize, - &lengthIndicator ); - if ( r == STQL_SUCCESS || r == STQL_SUCCESS_WITH_INFO ) { - if ( lengthIndicator == STQL_NULL_DATA ) { - isNull = TRUE; - break; - } else { - int rSize; - r == STQL_SUCCESS ? rSize = lengthIndicator : rSize = colSize; - if ( lengthIndicator == STQL_NO_TOTAL ) { // size cannot be determined - rSize = colSize; - } - // NB! This is not a memleak - the mem will be deleted by TQByteArray when - // no longer ref'd - char * tmp = (char *) malloc( rSize + fieldVal.size() ); - if ( fieldVal.size() ) { - memcpy( tmp, fieldVal.data(), fieldVal.size() ); - } - memcpy( tmp + fieldVal.size(), buf, rSize ); - fieldVal = fieldVal.assign( tmp, fieldVal.size() + rSize ); - - if ( r == STQL_SUCCESS ) { // the whole field was read in one chunk - break; - } - } - } else { - break; - } - } - delete [] buf; - return fieldVal; -} - -static int qGetIntData( STQLHANDLE hStmt, int column, bool& isNull ) -{ - TQSTQLLEN intbuf = 0; - isNull = FALSE; - TQSTQLLEN lengthIndicator = 0; - STQLRETURN r = STQLGetData( hStmt, - column+1, - STQL_C_SLONG, - (STQLPOINTER)&intbuf, - (TQSTQLLEN)0, - &lengthIndicator ); - if ( ( r != STQL_SUCCESS && r != STQL_SUCCESS_WITH_INFO ) || lengthIndicator == STQL_NULL_DATA ) { - isNull = TRUE; - return 0; - } - return (int)intbuf; -} - -static double qGetDoubleData( STQLHANDLE hStmt, int column, bool& isNull ) -{ - STQLDOUBLE dblbuf; - TQSTQLLEN lengthIndicator = 0; - isNull = FALSE; - STQLRETURN r = STQLGetData( hStmt, - column+1, - STQL_C_DOUBLE, - (STQLPOINTER)&dblbuf, - (TQSTQLLEN)0, - &lengthIndicator ); - if ( ( r != STQL_SUCCESS && r != STQL_SUCCESS_WITH_INFO ) || lengthIndicator == STQL_NULL_DATA ) { - isNull = TRUE; - return 0.0; - } - - return (double) dblbuf; -} - -static STQLBIGINT qGetBigIntData( STQLHANDLE hStmt, int column, bool& isNull ) -{ - STQLBIGINT lngbuf = TQ_INT64_C( 0 ); - isNull = FALSE; - TQSTQLLEN lengthIndicator = 0; - STQLRETURN r = STQLGetData( hStmt, - column+1, - STQL_C_SBIGINT, - (STQLPOINTER) &lngbuf, - (TQSTQLLEN)0, - &lengthIndicator ); - if ( ( r != STQL_SUCCESS && r != STQL_SUCCESS_WITH_INFO ) || lengthIndicator == STQL_NULL_DATA ) - isNull = TRUE; - - return lngbuf; -} - -// creates a TQSqlFieldInfo from a valid hStmt generated -// by STQLColumns. The hStmt has to point to a valid position. -static TQSqlFieldInfo qMakeFieldInfo( const STQLHANDLE hStmt, const TQODBCPrivate* p ) -{ - bool isNull; - TQString fname = qGetStringData( hStmt, 3, -1, isNull, p->tqunicode ); - int type = qGetIntData( hStmt, 4, isNull ); // column type - int required = qGetIntData( hStmt, 10, isNull ); // nullable-flag - // required can be STQL_NO_NULLS, STQL_NULLABLE or STQL_NULLABLE_UNKNOWN - if ( required == STQL_NO_NULLS ) { - required = 1; - } else if ( required == STQL_NULLABLE ) { - required = 0; - } else { - required = -1; - } - int size = qGetIntData( hStmt, 6, isNull ); // column size - int prec = qGetIntData( hStmt, 8, isNull ); // precision - return TQSqlFieldInfo( fname, qDecodeODBCType( type, p ), required, size, prec, TQVariant(), type ); -} - -static TQSqlFieldInfo qMakeFieldInfo( const TQODBCPrivate* p, int i ) -{ - STQLSMALLINT colNameLen; - STQLSMALLINT colType; - TQSQLULEN colSize; - STQLSMALLINT colScale; - STQLSMALLINT nullable; - STQLRETURN r = STQL_ERROR; - STQLTCHAR colName[ COLNAMESIZE ]; - r = STQLDescribeCol( p->hStmt, - i+1, - colName, - (TQSQLULEN)COLNAMESIZE, - &colNameLen, - &colType, - &colSize, - &colScale, - &nullable); - - if ( r != STQL_SUCCESS ) { -#ifdef TQT_CHECK_RANGE - qSqlWarning( TQString("qMakeField: Unable to describe column %1").arg(i), p ); -#endif - return TQSqlFieldInfo(); - } -#ifdef UNICODE - TQString qColName( (const TQChar*)colName, (uint)colNameLen ); -#else - TQString qColName = TQString::fromLocal8Bit( (const char*)colName ); -#endif - // nullable can be STQL_NO_NULLS, STQL_NULLABLE or STQL_NULLABLE_UNKNOWN - int required = -1; - if ( nullable == STQL_NO_NULLS ) { - required = 1; - } else if ( nullable == STQL_NULLABLE ) { - required = 0; - } - TQVariant::Type type = qDecodeODBCType( colType, p ); - return TQSqlFieldInfo( qColName, - type, - required, - (int)colSize == 0 ? -1 : (int)colSize, - (int)colScale == 0 ? -1 : (int)colScale, - TQVariant(), - (int)colType ); -} - -bool TQODBCPrivate::setConnectionOptions( const TQString& connOpts ) -{ - // Set any connection attributes - TQStringList raw = TQStringList::split( ';', connOpts ); - TQStringList opts; - STQLRETURN r = STQL_SUCCESS; - TQMap<TQString, TQString> connMap; - for ( TQStringList::ConstIterator it = raw.begin(); it != raw.end(); ++it ) { - TQString tmp( *it ); - int idx; - if ( (idx = tmp.find( '=' )) != -1 ) - connMap[ tmp.left( idx ) ] = tmp.mid( idx + 1 ).simplifyWhiteSpace(); - else - qWarning( "TQODBCDriver::open: Illegal connect option value '%s'", tmp.latin1() ); - } - if ( connMap.count() ) { - TQMap<TQString, TQString>::ConstIterator it; - TQString opt, val; - STQLUINTEGER v = 0; - for ( it = connMap.begin(); it != connMap.end(); ++it ) { - opt = it.key().upper(); - val = it.data().upper(); - r = STQL_SUCCESS; - if ( opt == "STQL_ATTR_ACCESS_MODE" ) { - if ( val == "STQL_MODE_READ_ONLY" ) { - v = STQL_MODE_READ_ONLY; - } else if ( val == "STQL_MODE_READ_WRITE" ) { - v = STQL_MODE_READ_WRITE; - } else { - qWarning( TQString( "TQODBCDriver::open: Unknown option value '%1'" ).arg( *it ) ); - break; - } - r = STQLSetConnectAttr( hDbc, STQL_ATTR_ACCESS_MODE, (STQLPOINTER) v, 0 ); - } else if ( opt == "STQL_ATTR_CONNECTION_TIMEOUT" ) { - v = val.toUInt(); - r = STQLSetConnectAttr( hDbc, STQL_ATTR_CONNECTION_TIMEOUT, (STQLPOINTER) v, 0 ); - } else if ( opt == "STQL_ATTR_LOGIN_TIMEOUT" ) { - v = val.toUInt(); - r = STQLSetConnectAttr( hDbc, STQL_ATTR_LOGIN_TIMEOUT, (STQLPOINTER) v, 0 ); - } else if ( opt == "STQL_ATTR_CURRENT_CATALOG" ) { - val.ucs2(); // 0 terminate - r = STQLSetConnectAttr( hDbc, STQL_ATTR_CURRENT_CATALOG, -#ifdef UNICODE - (STQLWCHAR*) val.tqunicode(), -#else - (STQLCHAR*) val.latin1(), -#endif - STQL_NTS ); - } else if ( opt == "STQL_ATTR_METADATA_ID" ) { - if ( val == "STQL_TRUE" ) { - v = STQL_TRUE; - } else if ( val == "STQL_FALSE" ) { - v = STQL_FALSE; - } else { - qWarning( TQString( "TQODBCDriver::open: Unknown option value '%1'" ).arg( *it ) ); - break; - } - r = STQLSetConnectAttr( hDbc, STQL_ATTR_METADATA_ID, (STQLPOINTER) v, 0 ); - } else if ( opt == "STQL_ATTR_PACKET_SIZE" ) { - v = val.toUInt(); - r = STQLSetConnectAttr( hDbc, STQL_ATTR_PACKET_SIZE, (STQLPOINTER) v, 0 ); - } else if ( opt == "STQL_ATTR_TRACEFILE" ) { - val.ucs2(); // 0 terminate - r = STQLSetConnectAttr( hDbc, STQL_ATTR_TRACEFILE, -#ifdef UNICODE - (STQLWCHAR*) val.tqunicode(), -#else - (STQLCHAR*) val.latin1(), -#endif - STQL_NTS ); - } else if ( opt == "STQL_ATTR_TRACE" ) { - if ( val == "STQL_OPT_TRACE_OFF" ) { - v = STQL_OPT_TRACE_OFF; - } else if ( val == "STQL_OPT_TRACE_ON" ) { - v = STQL_OPT_TRACE_ON; - } else { - qWarning( TQString( "TQODBCDriver::open: Unknown option value '%1'" ).arg( *it ) ); - break; - } - r = STQLSetConnectAttr( hDbc, STQL_ATTR_TRACE, (STQLPOINTER) v, 0 ); - } -#ifdef TQT_CHECK_RANGE - else { - qWarning( TQString("TQODBCDriver::open: Unknown connection attribute '%1'").arg( opt ) ); - } -#endif - if ( r != STQL_SUCCESS && r != STQL_SUCCESS_WITH_INFO ) { -#ifdef TQT_CHECK_RANGE - qSqlWarning( TQString("TQODBCDriver::open: Unable to set connection attribute '%1'").arg( opt ), this ); -#endif - return FALSE; - } - } - } - return TRUE; -} - -void TQODBCPrivate::splitTableQualifier(const TQString & qualifier, TQString &catalog, - TQString &schema, TQString &table) -{ - if (!useSchema) { - table = qualifier; - return; - } - TQStringList l = TQStringList::split( ".", qualifier, TRUE ); - if ( l.count() > 3 ) - return; // can't possibly be a valid table qualifier - int i = 0, n = l.count(); - if ( n == 1 ) { - table = qualifier; - } else { - for ( TQStringList::Iterator it = l.begin(); it != l.end(); ++it ) { - if ( n == 3 ) { - if ( i == 0 ) { - catalog = *it; - } else if ( i == 1 ) { - schema = *it; - } else if ( i == 2 ) { - table = *it; - } - } else if ( n == 2 ) { - if ( i == 0 ) { - schema = *it; - } else if ( i == 1 ) { - table = *it; - } - } - i++; - } - } -} - -//////////////////////////////////////////////////////////////////////////// - -TQODBCResult::TQODBCResult( const TQODBCDriver * db, TQODBCPrivate* p ) -: TQSqlResult(db) -{ - d = new TQODBCPrivate(); - (*d) = (*p); - setExtension( new TQODBCPreparedExtension( this ) ); -} - -TQODBCResult::~TQODBCResult() -{ - if ( d->hStmt && driver()->isOpen() ) { - STQLRETURN r = STQLFreeHandle( STQL_HANDLE_STMT, d->hStmt ); -#ifdef TQT_CHECK_RANGE - if ( r != STQL_SUCCESS ) - qSqlWarning( "TQODBCDriver: Unable to free statement handle " + TQString::number(r), d ); -#endif - } - - delete d; -} - -bool TQODBCResult::reset ( const TQString& query ) -{ - setActive( FALSE ); - setAt( TQSql::BeforeFirst ); - STQLRETURN r; - - d->rInf.clear(); - // Always reallocate the statement handle - the statement attributes - // are not reset if STQLFreeStmt() is called which causes some problems. - if ( d->hStmt ) { - r = STQLFreeHandle( STQL_HANDLE_STMT, d->hStmt ); - if ( r != STQL_SUCCESS ) { -#ifdef TQT_CHECK_RANGE - qSqlWarning( "TQODBCResult::reset: Unable to free statement handle", d ); -#endif - return FALSE; - } - } - r = STQLAllocHandle( STQL_HANDLE_STMT, - d->hDbc, - &d->hStmt ); - if ( r != STQL_SUCCESS ) { -#ifdef TQT_CHECK_RANGE - qSqlWarning( "TQODBCResult::reset: Unable to allocate statement handle", d ); -#endif - return FALSE; - } - - if ( isForwardOnly() ) { - r = STQLSetStmtAttr( d->hStmt, - STQL_ATTR_CURSOR_TYPE, - (STQLPOINTER)STQL_CURSOR_FORWARD_ONLY, - STQL_IS_UINTEGER ); - } else { - r = STQLSetStmtAttr( d->hStmt, - STQL_ATTR_CURSOR_TYPE, - (STQLPOINTER)STQL_CURSOR_STATIC, - STQL_IS_UINTEGER ); - } - if ( r != STQL_SUCCESS && r != STQL_SUCCESS_WITH_INFO ) { -#ifdef TQT_CHECK_RANGE - qSqlWarning( "TQODBCResult::reset: Unable to set 'STQL_CURSOR_STATIC' as statement attribute. Please check your ODBC driver configuration", d ); -#endif - return FALSE; - } - -#ifdef UNICODE - r = STQLExecDirect( d->hStmt, - (STQLWCHAR*) query.tqunicode(), - (STQLINTEGER) query.length() ); -#else - TQCString query8 = query.local8Bit(); - r = STQLExecDirect( d->hStmt, - (STQLCHAR*) query8.data(), - (STQLINTEGER) query8.length() ); -#endif - if ( r != STQL_SUCCESS && r != STQL_SUCCESS_WITH_INFO ) { - setLastError( qMakeError( "Unable to execute statement", TQSqlError::Statement, d ) ); - return FALSE; - } - STQLSMALLINT count; - r = STQLNumResultCols( d->hStmt, &count ); - if ( count ) { - setSelect( TRUE ); - for ( int i = 0; i < count; ++i ) { - d->rInf.append( qMakeFieldInfo( d, i ) ); - } - } else { - setSelect( FALSE ); - } - setActive( TRUE ); - return TRUE; -} - -bool TQODBCResult::fetch(int i) -{ - if ( isForwardOnly() && i < at() ) - return FALSE; - if ( i == at() ) - return TRUE; - fieldCache.clear(); - nullCache.clear(); - int actualIdx = i + 1; - if ( actualIdx <= 0 ) { - setAt( TQSql::BeforeFirst ); - return FALSE; - } - STQLRETURN r; - if ( isForwardOnly() ) { - bool ok = TRUE; - while ( ok && i > at() ) - ok = fetchNext(); - return ok; - } else { - r = STQLFetchScroll( d->hStmt, - STQL_FETCH_ABSOLUTE, - actualIdx ); - } - if ( r != STQL_SUCCESS ){ - return FALSE; - } - setAt( i ); - return TRUE; -} - -bool TQODBCResult::fetchNext() -{ - STQLRETURN r; - fieldCache.clear(); - nullCache.clear(); - r = STQLFetchScroll( d->hStmt, - STQL_FETCH_NEXT, - 0 ); - if ( r != STQL_SUCCESS ) - return FALSE; - setAt( at() + 1 ); - return TRUE; -} - -bool TQODBCResult::fetchFirst() -{ - if ( isForwardOnly() && at() != TQSql::BeforeFirst ) - return FALSE; - STQLRETURN r; - fieldCache.clear(); - nullCache.clear(); - if ( isForwardOnly() ) { - return fetchNext(); - } - r = STQLFetchScroll( d->hStmt, - STQL_FETCH_FIRST, - 0 ); - if ( r != STQL_SUCCESS ) - return FALSE; - setAt( 0 ); - return TRUE; -} - -bool TQODBCResult::fetchPrior() -{ - if ( isForwardOnly() ) - return FALSE; - STQLRETURN r; - fieldCache.clear(); - nullCache.clear(); - r = STQLFetchScroll( d->hStmt, - STQL_FETCH_PRIOR, - 0 ); - if ( r != STQL_SUCCESS ) - return FALSE; - setAt( at() - 1 ); - return TRUE; -} - -bool TQODBCResult::fetchLast() -{ - STQLRETURN r; - fieldCache.clear(); - nullCache.clear(); - - if ( isForwardOnly() ) { - // cannot seek to last row in forwardOnly mode, so we have to use brute force - int i = at(); - if ( i == TQSql::AfterLast ) - return FALSE; - if ( i == TQSql::BeforeFirst ) - i = 0; - while ( fetchNext() ) - ++i; - setAt( i ); - return TRUE; - } - - r = STQLFetchScroll( d->hStmt, - STQL_FETCH_LAST, - 0 ); - if ( r != STQL_SUCCESS ) { - return FALSE; - } - STQLINTEGER currRow; - r = STQLGetStmtAttr( d->hStmt, - STQL_ROW_NUMBER, - &currRow, - STQL_IS_INTEGER, - 0 ); - if ( r != STQL_SUCCESS ) - return FALSE; - setAt( currRow-1 ); - return TRUE; -} - -TQVariant TQODBCResult::data( int field ) -{ - if ( field >= (int) d->rInf.count() ) { - qWarning( "TQODBCResult::data: column %d out of range", field ); - return TQVariant(); - } - if ( fieldCache.contains( field ) ) - return fieldCache[ field ]; - STQLRETURN r(0); - TQSTQLLEN lengthIndicator = 0; - bool isNull = FALSE; - int current = fieldCache.count(); - for ( ; current < (field + 1); ++current ) { - const TQSqlFieldInfo info = d->rInf[ current ]; - switch ( info.type() ) { - case TQVariant::LongLong: - fieldCache[ current ] = TQVariant( (TQ_LLONG) qGetBigIntData( d->hStmt, current, isNull ) ); - nullCache[ current ] = isNull; - break; - case TQVariant::Int: - fieldCache[ current ] = TQVariant( qGetIntData( d->hStmt, current, isNull ) ); - nullCache[ current ] = isNull; - break; - case TQVariant::Date: - DATE_STRUCT dbuf; - r = STQLGetData( d->hStmt, - current+1, - STQL_C_DATE, - (STQLPOINTER)&dbuf, - (TQSTQLLEN)0, - &lengthIndicator ); - if ( ( r == STQL_SUCCESS || r == STQL_SUCCESS_WITH_INFO ) && ( lengthIndicator != STQL_NULL_DATA ) ) { - fieldCache[ current ] = TQVariant( TQDate( dbuf.year, dbuf.month, dbuf.day ) ); - nullCache[ current ] = FALSE; - } else { - fieldCache[ current ] = TQVariant( TQDate() ); - nullCache[ current ] = TRUE; - } - break; - case TQVariant::Time: - TIME_STRUCT tbuf; - r = STQLGetData( d->hStmt, - current+1, - STQL_C_TIME, - (STQLPOINTER)&tbuf, - (TQSTQLLEN)0, - &lengthIndicator ); - if ( ( r == STQL_SUCCESS || r == STQL_SUCCESS_WITH_INFO ) && ( lengthIndicator != STQL_NULL_DATA ) ) { - fieldCache[ current ] = TQVariant( TQTime( tbuf.hour, tbuf.minute, tbuf.second ) ); - nullCache[ current ] = FALSE; - } else { - fieldCache[ current ] = TQVariant( TQTime() ); - nullCache[ current ] = TRUE; - } - break; - case TQVariant::DateTime: - TIMESTAMP_STRUCT dtbuf; - r = STQLGetData( d->hStmt, - current+1, - STQL_C_TIMESTAMP, - (STQLPOINTER)&dtbuf, - (TQSTQLLEN)0, - &lengthIndicator ); - if ( ( r == STQL_SUCCESS || r == STQL_SUCCESS_WITH_INFO ) && ( lengthIndicator != STQL_NULL_DATA ) ) { - fieldCache[ current ] = TQVariant( TQDateTime( TQDate( dtbuf.year, dtbuf.month, dtbuf.day ), TQTime( dtbuf.hour, dtbuf.minute, dtbuf.second, dtbuf.fraction / 1000000 ) ) ); - nullCache[ current ] = FALSE; - } else { - fieldCache[ current ] = TQVariant( TQDateTime() ); - nullCache[ current ] = TRUE; - } - break; - case TQVariant::ByteArray: { - isNull = FALSE; - TQByteArray val = qGetBinaryData( d->hStmt, current, lengthIndicator, isNull ); - fieldCache[ current ] = TQVariant( val ); - nullCache[ current ] = isNull; - break; } - case TQVariant::String: - isNull = FALSE; - fieldCache[ current ] = TQVariant( qGetStringData( d->hStmt, current, - info.length(), isNull, TRUE ) ); - nullCache[ current ] = isNull; - break; - case TQVariant::Double: - if ( info.typeID() == STQL_DECIMAL || info.typeID() == STQL_NUMERIC ) - // bind Double values as string to prevent loss of precision - fieldCache[ current ] = TQVariant( qGetStringData( d->hStmt, current, - info.length() + 1, isNull, FALSE ) ); // length + 1 for the comma - else - fieldCache[ current ] = TQVariant( qGetDoubleData( d->hStmt, current, isNull ) ); - nullCache[ current ] = isNull; - break; - case TQVariant::CString: - default: - isNull = FALSE; - fieldCache[ current ] = TQVariant( qGetStringData( d->hStmt, current, - info.length(), isNull, FALSE ) ); - nullCache[ current ] = isNull; - break; - } - } - return fieldCache[ --current ]; -} - -bool TQODBCResult::isNull( int field ) -{ - if ( !fieldCache.contains( field ) ) { - // since there is no good way to find out whether the value is NULL - // without fetching the field we'll fetch it here. - // (data() also sets the NULL flag) - data( field ); - } - return nullCache[ field ]; -} - -int TQODBCResult::size() -{ - return -1; -} - -int TQODBCResult::numRowsAffected() -{ - TQSTQLLEN affectedRowCount(0); - STQLRETURN r = STQLRowCount( d->hStmt, &affectedRowCount ); - if ( r == STQL_SUCCESS ) - return affectedRowCount; -#ifdef TQT_CHECK_RANGE - else - qSqlWarning( "TQODBCResult::numRowsAffected: Unable to count affected rows", d ); -#endif - return -1; -} - -bool TQODBCResult::prepare( const TQString& query ) -{ - setActive( FALSE ); - setAt( TQSql::BeforeFirst ); - STQLRETURN r; - - d->rInf.clear(); - if ( d->hStmt ) { - r = STQLFreeHandle( STQL_HANDLE_STMT, d->hStmt ); - if ( r != STQL_SUCCESS ) { -#ifdef TQT_CHECK_RANGE - qSqlWarning( "TQODBCResult::prepare: Unable to close statement", d ); -#endif - return FALSE; - } - } - r = STQLAllocHandle( STQL_HANDLE_STMT, - d->hDbc, - &d->hStmt ); - if ( r != STQL_SUCCESS ) { -#ifdef TQT_CHECK_RANGE - qSqlWarning( "TQODBCResult::prepare: Unable to allocate statement handle", d ); -#endif - return FALSE; - } - - if ( isForwardOnly() ) { - r = STQLSetStmtAttr( d->hStmt, - STQL_ATTR_CURSOR_TYPE, - (STQLPOINTER)STQL_CURSOR_FORWARD_ONLY, - STQL_IS_UINTEGER ); - } else { - r = STQLSetStmtAttr( d->hStmt, - STQL_ATTR_CURSOR_TYPE, - (STQLPOINTER)STQL_CURSOR_STATIC, - STQL_IS_UINTEGER ); - } - if ( r != STQL_SUCCESS && r != STQL_SUCCESS_WITH_INFO ) { -#ifdef TQT_CHECK_RANGE - qSqlWarning( "TQODBCResult::prepare: Unable to set 'STQL_CURSOR_STATIC' as statement attribute. Please check your ODBC driver configuration", d ); -#endif - return FALSE; - } - -#ifdef UNICODE - r = STQLPrepare( d->hStmt, - (STQLWCHAR*) query.tqunicode(), - (STQLINTEGER) query.length() ); -#else - TQCString query8 = query.local8Bit(); - r = STQLPrepare( d->hStmt, - (STQLCHAR*) query8.data(), - (STQLINTEGER) query8.length() ); -#endif - - if ( r != STQL_SUCCESS ) { -#ifdef TQT_CHECK_RANGE - qSqlWarning( "TQODBCResult::prepare: Unable to prepare statement", d ); -#endif - return FALSE; - } - return TRUE; -} - -bool TQODBCResult::exec() -{ - STQLRETURN r; - TQPtrList<TQVirtualDestructor> tmpStorage; // holds temporary ptrs. which will be deleted on fu exit - tmpStorage.setAutoDelete( TRUE ); - - setActive( FALSE ); - setAt( TQSql::BeforeFirst ); - d->rInf.clear(); - - if ( !d->hStmt ) { -#ifdef TQT_CHECK_RANGE - qSqlWarning( "TQODBCResult::exec: No statement handle available", d ); -#endif - return FALSE; - } else { - r = STQLFreeStmt( d->hStmt, STQL_CLOSE ); - if ( r != STQL_SUCCESS ) { - qSqlWarning( "TQODBCResult::exec: Unable to close statement handle", d ); - return FALSE; - } - } - - // bind parameters - only positional binding allowed - if ( extension()->index.count() > 0 ) { - TQMap<int, TQString>::Iterator it; - int para = 1; - TQVariant val; - for ( it = extension()->index.begin(); it != extension()->index.end(); ++it ) { - val = extension()->values[ it.data() ].value; - TQSTQLLEN *ind = new TQSTQLLEN( STQL_NTS ); - tmpStorage.append( qAutoDeleter(ind) ); - if ( val.isNull() ) { - *ind = STQL_NULL_DATA; - } - switch ( val.type() ) { - case TQVariant::Date: { - DATE_STRUCT * dt = new DATE_STRUCT; - tmpStorage.append( qAutoDeleter(dt) ); - TQDate qdt = val.toDate(); - dt->year = qdt.year(); - dt->month = qdt.month(); - dt->day = qdt.day(); - r = STQLBindParameter( d->hStmt, - para, - qParamType[ (int)extension()->values[ it.data() ].typ ], - STQL_C_DATE, - STQL_DATE, - 0, - 0, - (void *) dt, - (TQSTQLLEN)0, - *ind == STQL_NULL_DATA ? ind : NULL ); - break; } - case TQVariant::Time: { - TIME_STRUCT * dt = new TIME_STRUCT; - tmpStorage.append( qAutoDeleter(dt) ); - TQTime qdt = val.toTime(); - dt->hour = qdt.hour(); - dt->minute = qdt.minute(); - dt->second = qdt.second(); - r = STQLBindParameter( d->hStmt, - para, - qParamType[ (int)extension()->values[ it.data() ].typ ], - STQL_C_TIME, - STQL_TIME, - 0, - 0, - (void *) dt, - (TQSTQLLEN)0, - *ind == STQL_NULL_DATA ? ind : NULL ); - break; } - case TQVariant::DateTime: { - TIMESTAMP_STRUCT * dt = new TIMESTAMP_STRUCT; - tmpStorage.append( qAutoDeleter(dt) ); - TQDateTime qdt = val.toDateTime(); - dt->year = qdt.date().year(); - dt->month = qdt.date().month(); - dt->day = qdt.date().day(); - dt->hour = qdt.time().hour(); - dt->minute = qdt.time().minute(); - dt->second = qdt.time().second(); - dt->fraction = 0; - r = STQLBindParameter( d->hStmt, - para, - qParamType[ (int)extension()->values[ it.data() ].typ ], - STQL_C_TIMESTAMP, - STQL_TIMESTAMP, - 0, - 0, - (void *) dt, - (TQSTQLLEN)0, - *ind == STQL_NULL_DATA ? ind : NULL ); - break; } - case TQVariant::Int: { - int * v = new int( val.toInt() ); - tmpStorage.append( qAutoDeleter(v) ); - r = STQLBindParameter( d->hStmt, - para, - qParamType[ (int)extension()->values[ it.data() ].typ ], - STQL_C_SLONG, - STQL_INTEGER, - 0, - 0, - (void *) v, - (TQSTQLLEN)0, - *ind == STQL_NULL_DATA ? ind : NULL ); - break; } - case TQVariant::Double: { - double * v = new double( val.toDouble() ); - tmpStorage.append( qAutoDeleter(v) ); - r = STQLBindParameter( d->hStmt, - para, - qParamType[ (int)extension()->values[ it.data() ].typ ], - STQL_C_DOUBLE, - STQL_DOUBLE, - 0, - 0, - (void *) v, - (TQSTQLLEN)0, - *ind == STQL_NULL_DATA ? ind : NULL ); - break; } - case TQVariant::ByteArray: { - if ( *ind != STQL_NULL_DATA ) { - *ind = val.asByteArray().size(); - } - r = STQLBindParameter( d->hStmt, - para, - qParamType[ (int)extension()->values[ it.data() ].typ ], - STQL_C_BINARY, - STQL_LONGVARBINARY, - val.asByteArray().size(), - 0, - (void *) val.asByteArray().data(), - (TQSTQLLEN)val.asByteArray().size(), - ind ); - break; } -#ifndef TQ_ODBC_VERSION_2 - case TQVariant::String: - if ( d->tqunicode ) { - TQString * str = new TQString( val.asString() ); - str->ucs2(); - int len = str->length()*2; - tmpStorage.append( qAutoDeleter(str) ); - r = STQLBindParameter( d->hStmt, - para, - qParamType[ (int)extension()->values[ it.data() ].typ ], - STQL_C_WCHAR, - len > 8000 ? STQL_WLONGVARCHAR : STQL_WVARCHAR, - len > 8000 ? len : 0, - 0, - (void *) str->tqunicode(), - (TQSTQLLEN) len, - ind ); - break; - } -#endif - // fall through - default: { - TQCString * str = new TQCString( val.asString().local8Bit() ); - tmpStorage.append( qAutoDeleter(str) ); - r = STQLBindParameter( d->hStmt, - para, - qParamType[ (int)extension()->values[ it.data() ].typ ], - STQL_C_CHAR, - str->length() > 4000 ? STQL_LONGVARCHAR : STQL_VARCHAR, - str->length() + 1, - 0, - (void *) str->data(), - (TQSTQLLEN)(str->length() + 1), - ind ); - break; } - } - para++; - if ( r != STQL_SUCCESS ) { -#ifdef TQT_CHECK_RANGE - qWarning( "TQODBCResult::exec: unable to bind variable: %s", qODBCWarn( d ).local8Bit().data() ); -#endif - setLastError( qMakeError( "Unable to bind variable", TQSqlError::Statement, d ) ); - return FALSE; - } - } - } - r = STQLExecute( d->hStmt ); - if ( r != STQL_SUCCESS && r != STQL_SUCCESS_WITH_INFO ) { -#ifdef TQT_CHECK_RANGE - qWarning( "TQODBCResult::exec: Unable to execute statement: %s", qODBCWarn( d ).local8Bit().data() ); -#endif - setLastError( qMakeError( "Unable to execute statement", TQSqlError::Statement, d ) ); - return FALSE; - } - STQLSMALLINT count; - r = STQLNumResultCols( d->hStmt, &count ); - if ( count ) { - setSelect( TRUE ); - for ( int i = 0; i < count; ++i ) { - d->rInf.append( qMakeFieldInfo( d, i ) ); - } - } else { - setSelect( FALSE ); - } - setActive( TRUE ); - - //get out parameters - if ( extension()->index.count() > 0 ) { - TQMap<int, TQString>::Iterator it; - for ( it = extension()->index.begin(); it != extension()->index.end(); ++it ) { - - STQLINTEGER* indPtr = qAutoDeleterData( (TQAutoDeleter<STQLINTEGER>*)tmpStorage.getFirst() ); - if ( !indPtr ) - return FALSE; - bool isNull = (*indPtr == STQL_NULL_DATA); - tmpStorage.removeFirst(); - - TQVariant::Type type = extension()->values[ it.data() ].value.type(); - if ( isNull ) { - TQVariant v; - v.cast(type); - extension()->values[ it.data() ].value = v; - if (type != TQVariant::ByteArray) - tmpStorage.removeFirst(); - continue; - } - - switch (type) { - case TQVariant::Date: { - DATE_STRUCT * ds = qAutoDeleterData( (TQAutoDeleter<DATE_STRUCT>*)tmpStorage.getFirst() ); - extension()->values[ it.data() ].value = TQVariant( TQDate( ds->year, ds->month, ds->day ) ); - break; } - case TQVariant::Time: { - TIME_STRUCT * dt = qAutoDeleterData( (TQAutoDeleter<TIME_STRUCT>*)tmpStorage.getFirst() ); - extension()->values[ it.data() ].value = TQVariant( TQTime( dt->hour, dt->minute, dt->second ) ); - break; } - case TQVariant::DateTime: { - TIMESTAMP_STRUCT * dt = qAutoDeleterData( (TQAutoDeleter<TIMESTAMP_STRUCT>*)tmpStorage.getFirst() ); - extension()->values[ it.data() ].value = TQVariant( TQDateTime( TQDate( dt->year, dt->month, dt->day ), - TQTime( dt->hour, dt->minute, dt->second ) ) ); - break; } - case TQVariant::Int: { - int * v = qAutoDeleterData( (TQAutoDeleter<int>*)tmpStorage.getFirst() ); - extension()->values[ it.data() ].value = TQVariant( *v ); - break; } - case TQVariant::Double: { - double * v = qAutoDeleterData( (TQAutoDeleter<double>*)tmpStorage.getFirst() ); - extension()->values[ it.data() ].value = TQVariant( *v ); - break; } - case TQVariant::ByteArray: - break; - case TQVariant::String: - if ( d->tqunicode ) { - TQString * str = qAutoDeleterData( (TQAutoDeleter<TQString>*)tmpStorage.getFirst() ); - extension()->values[ it.data() ].value = TQVariant( *str ); - break; - } - // fall through - default: { - TQCString * str = qAutoDeleterData( (TQAutoDeleter<TQCString>*)tmpStorage.getFirst() ); - extension()->values[ it.data() ].value = TQVariant( *str ); - break; } - } - if (type != TQVariant::ByteArray) - tmpStorage.removeFirst(); - } - } - - return TRUE; -} - -//////////////////////////////////////// - - -TQODBCDriver::TQODBCDriver( TQObject * parent, const char * name ) - : TQSqlDriver(parent,name ? name : "TQODBC") -{ - init(); -} - -TQODBCDriver::TQODBCDriver( STQLHANDLE env, STQLHANDLE con, TQObject * parent, const char * name ) - : TQSqlDriver(parent,name ? name : "TQODBC") -{ - init(); - d->hEnv = env; - d->hDbc = con; - if ( env && con ) { - setOpen( TRUE ); - setOpenError( FALSE ); - } -} - -void TQODBCDriver::init() -{ - qSqlOpenExtDict()->insert( this, new TQODBCOpenExtension(this) ); - d = new TQODBCPrivate(); -} - -TQODBCDriver::~TQODBCDriver() -{ - cleanup(); - delete d; - if ( !qSqlOpenExtDict()->isEmpty() ) { - TQSqlOpenExtension *ext = qSqlOpenExtDict()->take( this ); - delete ext; - } -} - -bool TQODBCDriver::hasFeature( DriverFeature f ) const -{ - switch ( f ) { - case Transactions: { - if ( !d->hDbc ) - return FALSE; - STQLUSMALLINT txn; - STQLSMALLINT t; - int r = STQLGetInfo( d->hDbc, - (STQLUSMALLINT)STQL_TXN_CAPABLE, - &txn, - sizeof(txn), - &t); - if ( r != STQL_SUCCESS || txn == STQL_TC_NONE ) - return FALSE; - else - return TRUE; - } - case QuerySize: - return FALSE; - case BLOB: - return TRUE; - case Unicode: - return d->tqunicode; - case PreparedQueries: - return TRUE; - case PositionalPlaceholders: - return TRUE; - default: - return FALSE; - } -} - -bool TQODBCDriver::open( const TQString&, - const TQString&, - const TQString&, - const TQString&, - int ) -{ - qWarning("TQODBCDriver::open(): This version of open() is no longer supported." ); - return FALSE; -} - -bool TQODBCDriver::open( const TQString & db, - const TQString & user, - const TQString & password, - const TQString &, - int, - const TQString& connOpts ) -{ - if ( isOpen() ) - close(); - STQLRETURN r; - r = STQLAllocHandle( STQL_HANDLE_ENV, - STQL_NULL_HANDLE, - &d->hEnv); - if ( r != STQL_SUCCESS && r != STQL_SUCCESS_WITH_INFO ) { -#ifdef TQT_CHECK_RANGE - qSqlWarning( "TQODBCDriver::open: Unable to allocate environment", d ); -#endif - setOpenError( TRUE ); - return FALSE; - } - r = STQLSetEnvAttr( d->hEnv, - STQL_ATTR_ODBC_VERSION, - (STQLPOINTER)STQL_OV_ODBC2, - STQL_IS_UINTEGER ); - r = STQLAllocHandle( STQL_HANDLE_DBC, - d->hEnv, - &d->hDbc); - if ( r != STQL_SUCCESS && r != STQL_SUCCESS_WITH_INFO ) { -#ifdef TQT_CHECK_RANGE - qSqlWarning( "TQODBCDriver::open: Unable to allocate connection", d ); -#endif - setOpenError( TRUE ); - return FALSE; - } - - if ( !d->setConnectionOptions( connOpts ) ) - return FALSE; - - // Create the connection string - TQString connTQStr; - // support the "DRIVER={SQL SERVER};SERVER=blah" syntax - if ( db.contains(".dsn") ) - connTQStr = "FILEDSN=" + db; - else if ( db.contains( "DRIVER" ) || db.contains( "SERVER" ) ) - connTQStr = db; - else - connTQStr = "DSN=" + db; - connTQStr += ";UID=" + user + ";PWD=" + password; - STQLSMALLINT cb; - STQLTCHAR connOut[1024]; - r = STQLDriverConnect( d->hDbc, - NULL, -#ifdef UNICODE - (STQLWCHAR*)connTQStr.tqunicode(), -#else - (STQLCHAR*)connTQStr.latin1(), -#endif - (STQLSMALLINT)connTQStr.length(), - connOut, - 1024, - &cb, - STQL_DRIVER_NOPROMPT ); - if ( r != STQL_SUCCESS && r != STQL_SUCCESS_WITH_INFO ) { - setLastError( qMakeError( "Unable to connect", TQSqlError::Connection, d ) ); - setOpenError( TRUE ); - return FALSE; - } - - if ( !d->checkDriver() ) { - setLastError( qMakeError( "Unable to connect - Driver doesn't support all needed functionality", TQSqlError::Connection, d ) ); - setOpenError( TRUE ); - return FALSE; - } - - d->checkUnicode(); - d->checkSchemaUsage(); - - setOpen( TRUE ); - setOpenError( FALSE ); - return TRUE; -} - -void TQODBCDriver::close() -{ - cleanup(); - setOpen( FALSE ); - setOpenError( FALSE ); -} - -void TQODBCDriver::cleanup() -{ - STQLRETURN r; - if ( !d ) - return; - - if( d->hDbc ) { - // Open statements/descriptors handles are automatically cleaned up by STQLDisconnect - if ( isOpen() ) { - r = STQLDisconnect( d->hDbc ); -#ifdef TQT_CHECK_RANGE - if ( r != STQL_SUCCESS ) - qSqlWarning( "TQODBCDriver::disconnect: Unable to disconnect datasource", d ); -#endif - } - - r = STQLFreeHandle( STQL_HANDLE_DBC, d->hDbc ); -#ifdef TQT_CHECK_RANGE - if ( r != STQL_SUCCESS ) - qSqlWarning( "TQODBCDriver::cleanup: Unable to free connection handle", d ); -#endif - d->hDbc = 0; - } - - if ( d->hEnv ) { - r = STQLFreeHandle( STQL_HANDLE_ENV, d->hEnv ); -#ifdef TQT_CHECK_RANGE - if ( r != STQL_SUCCESS ) - qSqlWarning( "TQODBCDriver::cleanup: Unable to free environment handle", d ); -#endif - d->hEnv = 0; - } -} - -// checks whether the server can return char, varchar and longvarchar -// as two byte tqunicode characters -void TQODBCPrivate::checkUnicode() -{ -#if defined(TQ_WS_WIN) - if ( !qt_wintqunicode ) { - tqunicode = FALSE; - return; - } -#endif - STQLRETURN r; - STQLUINTEGER fFunc; - - tqunicode = FALSE; - r = STQLGetInfo( hDbc, - STQL_CONVERT_CHAR, - (STQLPOINTER)&fFunc, - sizeof(fFunc), - NULL ); - if ( ( r == STQL_SUCCESS || r == STQL_SUCCESS_WITH_INFO ) && ( fFunc & STQL_CVT_WCHAR ) ) { - sql_char_type = TQVariant::String; - tqunicode = TRUE; - } - - r = STQLGetInfo( hDbc, - STQL_CONVERT_VARCHAR, - (STQLPOINTER)&fFunc, - sizeof(fFunc), - NULL ); - if ( ( r == STQL_SUCCESS || r == STQL_SUCCESS_WITH_INFO ) && ( fFunc & STQL_CVT_WVARCHAR ) ) { - sql_varchar_type = TQVariant::String; - tqunicode = TRUE; - } - - r = STQLGetInfo( hDbc, - STQL_CONVERT_LONGVARCHAR, - (STQLPOINTER)&fFunc, - sizeof(fFunc), - NULL ); - if ( ( r == STQL_SUCCESS || r == STQL_SUCCESS_WITH_INFO ) && ( fFunc & STQL_CVT_WLONGVARCHAR ) ) { - sql_longvarchar_type = TQVariant::String; - tqunicode = TRUE; - } -} - -bool TQODBCPrivate::checkDriver() const -{ -#ifdef ODBC_CHECK_DRIVER - // do not query for STQL_API_STQLFETCHSCROLL because it can't be used at this time - static const STQLUSMALLINT reqFunc[] = { - STQL_API_STQLDESCRIBECOL, STQL_API_STQLGETDATA, STQL_API_STQLCOLUMNS, - STQL_API_STQLGETSTMTATTR, STQL_API_STQLGETDIAGREC, STQL_API_STQLEXECDIRECT, - STQL_API_STQLGETINFO, STQL_API_STQLTABLES, 0 - }; - - // these functions are optional - static const STQLUSMALLINT optFunc[] = { - STQL_API_STQLNUMRESULTCOLS, STQL_API_STQLROWCOUNT, 0 - }; - - STQLRETURN r; - STQLUSMALLINT sup; - - - int i; - // check the required functions - for ( i = 0; reqFunc[ i ] != 0; ++i ) { - - r = STQLGetFunctions( hDbc, reqFunc[ i ], &sup ); - -#ifdef TQT_CHECK_RANGE - if ( r != STQL_SUCCESS ) { - qSqlWarning( "TQODBCDriver::checkDriver: Cannot get list of supported functions", this ); - return FALSE; - } -#endif - if ( sup == STQL_FALSE ) { -#ifdef TQT_CHECK_RANGE - qWarning ( "TQODBCDriver::open: Warning - Driver doesn't support all needed functionality (%d). " - "Please look at the TQt SQL Module Driver documentation for more information.", reqFunc[ i ] ); -#endif - return FALSE; - } - } - - // these functions are optional and just generate a warning - for ( i = 0; optFunc[ i ] != 0; ++i ) { - - r = STQLGetFunctions( hDbc, optFunc[ i ], &sup ); - -#ifdef TQT_CHECK_RANGE - if ( r != STQL_SUCCESS ) { - qSqlWarning( "TQODBCDriver::checkDriver: Cannot get list of supported functions", this ); - return FALSE; - } -#endif - if ( sup == STQL_FALSE ) { -#ifdef TQT_CHECK_RANGE - qWarning( "TQODBCDriver::checkDriver: Warning - Driver doesn't support some non-critical functions (%d)", optFunc[ i ] ); -#endif - return TRUE; - } - } -#endif //ODBC_CHECK_DRIVER - - return TRUE; -} - -void TQODBCPrivate::checkSchemaUsage() -{ - STQLRETURN r; - STQLUINTEGER val; - - r = STQLGetInfo(hDbc, - STQL_SCHEMA_USAGE, - (STQLPOINTER) &val, - sizeof(val), - NULL); - if (r == STQL_SUCCESS || r == STQL_SUCCESS_WITH_INFO) - useSchema = (val != 0); -} - -TQSqlQuery TQODBCDriver::createQuery() const -{ - return TQSqlQuery( new TQODBCResult( this, d ) ); -} - -bool TQODBCDriver::beginTransaction() -{ - if ( !isOpen() ) { -#ifdef TQT_CHECK_RANGE - qWarning(" TQODBCDriver::beginTransaction: Database not open" ); -#endif - return FALSE; - } - STQLUINTEGER ac(STQL_AUTOCOMMIT_OFF); - STQLRETURN r = STQLSetConnectAttr( d->hDbc, - STQL_ATTR_AUTOCOMMIT, - (STQLPOINTER)ac, - sizeof(ac) ); - if ( r != STQL_SUCCESS ) { - setLastError( qMakeError( "Unable to disable autocommit", TQSqlError::Transaction, d ) ); - return FALSE; - } - return TRUE; -} - -bool TQODBCDriver::commitTransaction() -{ - if ( !isOpen() ) { -#ifdef TQT_CHECK_RANGE - qWarning(" TQODBCDriver::commitTransaction: Database not open" ); -#endif - return FALSE; - } - STQLRETURN r = STQLEndTran( STQL_HANDLE_DBC, - d->hDbc, - STQL_COMMIT ); - if ( r != STQL_SUCCESS ) { - setLastError( qMakeError("Unable to commit transaction", TQSqlError::Transaction, d ) ); - return FALSE; - } - return endTrans(); -} - -bool TQODBCDriver::rollbackTransaction() -{ - if ( !isOpen() ) { -#ifdef TQT_CHECK_RANGE - qWarning(" TQODBCDriver::rollbackTransaction: Database not open" ); -#endif - return FALSE; - } - STQLRETURN r = STQLEndTran( STQL_HANDLE_DBC, - d->hDbc, - STQL_ROLLBACK ); - if ( r != STQL_SUCCESS ) { - setLastError( qMakeError( "Unable to rollback transaction", TQSqlError::Transaction, d ) ); - return FALSE; - } - return endTrans(); -} - -bool TQODBCDriver::endTrans() -{ - STQLUINTEGER ac(STQL_AUTOCOMMIT_ON); - STQLRETURN r = STQLSetConnectAttr( d->hDbc, - STQL_ATTR_AUTOCOMMIT, - (STQLPOINTER)ac, - sizeof(ac)); - if ( r != STQL_SUCCESS ) { - setLastError( qMakeError( "Unable to enable autocommit", TQSqlError::Transaction, d ) ); - return FALSE; - } - return TRUE; -} - -TQStringList TQODBCDriver::tables( const TQString& typeName ) const -{ - TQStringList tl; - if ( !isOpen() ) - return tl; - int type = typeName.toInt(); - STQLHANDLE hStmt; - - STQLRETURN r = STQLAllocHandle( STQL_HANDLE_STMT, - d->hDbc, - &hStmt ); - if ( r != STQL_SUCCESS ) { -#ifdef TQT_CHECK_RANGE - qSqlWarning( "TQODBCDriver::tables: Unable to allocate handle", d ); -#endif - return tl; - } - r = STQLSetStmtAttr( hStmt, - STQL_ATTR_CURSOR_TYPE, - (STQLPOINTER)STQL_CURSOR_FORWARD_ONLY, - STQL_IS_UINTEGER ); - TQString tableType; - if ( typeName.isEmpty() || ((type & (int)TQSql::Tables) == (int)TQSql::Tables) ) - tableType += "TABLE,"; - if ( (type & (int)TQSql::Views) == (int)TQSql::Views ) - tableType += "VIEW,"; - if ( (type & (int)TQSql::SystemTables) == (int)TQSql::SystemTables ) - tableType += "SYSTEM TABLE,"; - if ( tableType.isEmpty() ) - return tl; - tableType.truncate( tableType.length() - 1 ); - - r = STQLTables( hStmt, - NULL, - 0, - NULL, - 0, - NULL, - 0, -#ifdef UNICODE - (STQLWCHAR*)tableType.tqunicode(), -#else - (STQLCHAR*)tableType.latin1(), -#endif - tableType.length() /* characters, not bytes */ ); - -#ifdef TQT_CHECK_RANGE - if ( r != STQL_SUCCESS ) - qSqlWarning( "TQODBCDriver::tables Unable to execute table list", d ); -#endif - r = STQLFetchScroll( hStmt, - STQL_FETCH_NEXT, - 0); - while ( r == STQL_SUCCESS ) { - bool isNull; - TQString fieldVal = qGetStringData( hStmt, 2, -1, isNull, d->tqunicode ); - tl.append( fieldVal ); - r = STQLFetchScroll( hStmt, - STQL_FETCH_NEXT, - 0); - } - - r = STQLFreeHandle( STQL_HANDLE_STMT, hStmt ); - if ( r!= STQL_SUCCESS ) - qSqlWarning( "TQODBCDriver: Unable to free statement handle" + TQString::number(r), d ); - return tl; -} - -TQSqlIndex TQODBCDriver::primaryIndex( const TQString& tablename ) const -{ - TQSqlIndex index( tablename ); - if ( !isOpen() ) - return index; - bool usingSpecialColumns = FALSE; - TQSqlRecord rec = record( tablename ); - - STQLHANDLE hStmt; - STQLRETURN r = STQLAllocHandle( STQL_HANDLE_STMT, - d->hDbc, - &hStmt ); - if ( r != STQL_SUCCESS ) { -#ifdef TQT_CHECK_RANGE - qSqlWarning( "TQODBCDriver::primaryIndex: Unable to list primary key", d ); -#endif - return index; - } - TQString catalog, schema, table; - d->splitTableQualifier( tablename, catalog, schema, table ); - r = STQLSetStmtAttr( hStmt, - STQL_ATTR_CURSOR_TYPE, - (STQLPOINTER)STQL_CURSOR_FORWARD_ONLY, - STQL_IS_UINTEGER ); - r = STQLPrimaryKeys( hStmt, -#ifdef UNICODE - catalog.length() == 0 ? NULL : (STQLWCHAR*)catalog.tqunicode(), -#else - catalog.length() == 0 ? NULL : (STQLCHAR*)catalog.latin1(), -#endif - catalog.length(), -#ifdef UNICODE - schema.length() == 0 ? NULL : (STQLWCHAR*)schema.tqunicode(), -#else - schema.length() == 0 ? NULL : (STQLCHAR*)schema.latin1(), -#endif - schema.length(), -#ifdef UNICODE - (STQLWCHAR*)table.tqunicode(), -#else - (STQLCHAR*)table.latin1(), -#endif - table.length() /* in characters, not in bytes */); - - // if the STQLPrimaryKeys() call does not succeed (e.g the driver - // does not support it) - try an alternative method to get hold of - // the primary index (e.g MS Access and FoxPro) - if ( r != STQL_SUCCESS ) { - r = STQLSpecialColumns( hStmt, - STQL_BEST_ROWID, -#ifdef UNICODE - catalog.length() == 0 ? NULL : (STQLWCHAR*)catalog.tqunicode(), -#else - catalog.length() == 0 ? NULL : (STQLCHAR*)catalog.latin1(), -#endif - catalog.length(), -#ifdef UNICODE - schema.length() == 0 ? NULL : (STQLWCHAR*)schema.tqunicode(), -#else - schema.length() == 0 ? NULL : (STQLCHAR*)schema.latin1(), -#endif - schema.length(), -#ifdef UNICODE - (STQLWCHAR*)table.tqunicode(), -#else - (STQLCHAR*)table.latin1(), -#endif - - table.length(), - STQL_SCOPE_CURROW, - STQL_NULLABLE ); - - if ( r != STQL_SUCCESS ) { -#ifdef TQT_CHECK_RANGE - qSqlWarning( "TQODBCDriver::primaryIndex: Unable to execute primary key list", d ); -#endif - } else { - usingSpecialColumns = TRUE; - } - } - r = STQLFetchScroll( hStmt, - STQL_FETCH_NEXT, - 0 ); - bool isNull; - int fakeId = 0; - TQString cName, idxName; - // Store all fields in a StringList because some drivers can't detail fields in this FETCH loop - while ( r == STQL_SUCCESS ) { - if ( usingSpecialColumns ) { - cName = qGetStringData( hStmt, 1, -1, isNull, d->tqunicode ); // column name - idxName = TQString::number( fakeId++ ); // invent a fake index name - } else { - cName = qGetStringData( hStmt, 3, -1, isNull, d->tqunicode ); // column name - idxName = qGetStringData( hStmt, 5, -1, isNull, d->tqunicode ); // pk index name - } - TQSqlField *fld = rec.field(cName); - if (fld) - index.append(*fld); - index.setName( idxName ); - r = STQLFetchScroll( hStmt, - STQL_FETCH_NEXT, - 0 ); - } - r = STQLFreeHandle( STQL_HANDLE_STMT, hStmt ); - if ( r!= STQL_SUCCESS ) - qSqlWarning( "TQODBCDriver: Unable to free statement handle" + TQString::number(r), d ); - return index; -} - -TQSqlRecord TQODBCDriver::record( const TQString& tablename ) const -{ - return recordInfo( tablename ).toRecord(); -} - -TQSqlRecord TQODBCDriver::record( const TQSqlQuery& query ) const -{ - return recordInfo( query ).toRecord(); -} - -TQSqlRecordInfo TQODBCDriver::recordInfo( const TQString& tablename ) const -{ - TQSqlRecordInfo fil; - if ( !isOpen() ) - return fil; - - STQLHANDLE hStmt; - TQString catalog, schema, table; - d->splitTableQualifier( tablename, catalog, schema, table ); - STQLRETURN r = STQLAllocHandle( STQL_HANDLE_STMT, - d->hDbc, - &hStmt ); - if ( r != STQL_SUCCESS ) { -#ifdef TQT_CHECK_RANGE - qSqlWarning( "TQODBCDriver::record: Unable to allocate handle", d ); -#endif - return fil; - } - r = STQLSetStmtAttr( hStmt, - STQL_ATTR_CURSOR_TYPE, - (STQLPOINTER)STQL_CURSOR_FORWARD_ONLY, - STQL_IS_UINTEGER ); - r = STQLColumns( hStmt, -#ifdef UNICODE - catalog.length() == 0 ? NULL : (STQLWCHAR*)catalog.tqunicode(), -#else - catalog.length() == 0 ? NULL : (STQLCHAR*)catalog.latin1(), -#endif - catalog.length(), -#ifdef UNICODE - schema.length() == 0 ? NULL : (STQLWCHAR*)schema.tqunicode(), -#else - schema.length() == 0 ? NULL : (STQLCHAR*)schema.latin1(), -#endif - schema.length(), -#ifdef UNICODE - (STQLWCHAR*)table.tqunicode(), -#else - (STQLCHAR*)table.latin1(), -#endif - table.length(), - NULL, - 0 ); -#ifdef TQT_CHECK_RANGE - if ( r != STQL_SUCCESS ) - qSqlWarning( "TQODBCDriver::record: Unable to execute column list", d ); -#endif - r = STQLFetchScroll( hStmt, - STQL_FETCH_NEXT, - 0); - // Store all fields in a StringList because some drivers can't detail fields in this FETCH loop - while ( r == STQL_SUCCESS ) { - - fil.append( qMakeFieldInfo( hStmt, d ) ); - - r = STQLFetchScroll( hStmt, - STQL_FETCH_NEXT, - 0); - } - - r = STQLFreeHandle( STQL_HANDLE_STMT, hStmt ); - if ( r!= STQL_SUCCESS ) - qSqlWarning( "TQODBCDriver: Unable to free statement handle " + TQString::number(r), d ); - - return fil; -} - -TQSqlRecordInfo TQODBCDriver::recordInfo( const TQSqlQuery& query ) const -{ - TQSqlRecordInfo fil; - if ( !isOpen() ) - return fil; - if ( query.isActive() && query.driver() == this ) { - TQODBCResult* result = (TQODBCResult*)query.result(); - fil = result->d->rInf; - } - return fil; -} - -STQLHANDLE TQODBCDriver::environment() -{ - return d->hEnv; -} - -STQLHANDLE TQODBCDriver::connection() -{ - return d->hDbc; -} - -TQString TQODBCDriver::formatValue( const TQSqlField* field, - bool trimStrings ) const -{ - TQString r; - if ( field->isNull() ) { - r = nullText(); - } else if ( field->type() == TQVariant::DateTime ) { - // Use an escape sequence for the datetime fields - if ( field->value().toDateTime().isValid() ){ - TQDate dt = field->value().toDateTime().date(); - TQTime tm = field->value().toDateTime().time(); - // Dateformat has to be "yyyy-MM-dd hh:mm:ss", with leading zeroes if month or day < 10 - r = "{ ts '" + - TQString::number(dt.year()) + "-" + - TQString::number(dt.month()).rightJustify( 2, '0', TRUE ) + "-" + - TQString::number(dt.day()).rightJustify( 2, '0', TRUE ) + " " + - tm.toString() + - "' }"; - } else - r = nullText(); - } else if ( field->type() == TQVariant::ByteArray ) { - TQByteArray ba = field->value().toByteArray(); - TQString res; - static const char hexchars[] = "0123456789abcdef"; - for ( uint i = 0; i < ba.size(); ++i ) { - uchar s = (uchar) ba[(int)i]; - res += hexchars[s >> 4]; - res += hexchars[s & 0x0f]; - } - r = "0x" + res; - } else { - r = TQSqlDriver::formatValue( field, trimStrings ); - } - return r; -} diff --git a/tqtinterface/qt4/src/sql/drivers/odbc/tqsql_odbc.h b/tqtinterface/qt4/src/sql/drivers/odbc/tqsql_odbc.h deleted file mode 100644 index cb09743..0000000 --- a/tqtinterface/qt4/src/sql/drivers/odbc/tqsql_odbc.h +++ /dev/null @@ -1,165 +0,0 @@ -/**************************************************************************** -** -** Definition of ODBC 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. -** -**********************************************************************/ - -#ifndef TQSQL_ODBC_H -#define TQSQL_ODBC_H - -#include <tqmap.h> -#include <tqstring.h> -#include <tqsqldriver.h> -#include <tqsqlfield.h> -#include <tqsqlresult.h> -#include <tqsqlindex.h> - -#if defined (TQ_OS_WIN32) -#include <tqt_windows.h> -#endif - -#if defined (TQ_OS_MAC) -// assume we use iodbc on MAC -// comment next line out if you use a -// tqunicode compatible manager -# define TQ_ODBC_VERSION_2 -#endif - -#ifdef TQT_PLUGIN -#define TQ_EXPORT_STQLDRIVER_ODBC -#else -#define TQ_EXPORT_STQLDRIVER_ODBC TQ_EXPORT -#endif - -#ifdef TQ_OS_UNIX -#define HAVE_LONG_LONG 1 // force UnixODBC NOT to fall back to a struct for BIGINTs -#endif - -#if defined(TQ_CC_BOR) -// workaround for Borland to make sure that STQLBIGINT is defined -# define _MSC_VER 900 -#endif -#include <sql.h> -#if defined(TQ_CC_BOR) -# undef _MSC_VER -#endif - -#ifndef TQ_ODBC_VERSION_2 -#include <sqlucode.h> -#endif - -#include <sqlext.h> - -class TQODBCPrivate; -class TQODBCDriver; -class TQSqlRecordInfo; - -class TQODBCResult : public TQSqlResult -{ - friend class TQODBCDriver; -public: - TQODBCResult( const TQODBCDriver * db, TQODBCPrivate* p ); - ~TQODBCResult(); - - STQLHANDLE statement(); - bool prepare( const TQString& query ); - bool exec(); - -protected: - bool fetchNext(); - bool fetchFirst(); - bool fetchLast(); - bool fetchPrior(); - bool fetch(int i); - bool reset ( const TQString& query ); - TQVariant data( int field ); - bool isNull( int field ); - int size(); - int numRowsAffected(); -private: - TQODBCPrivate* d; - typedef TQMap<int,TQVariant> FieldCache; - FieldCache fieldCache; - typedef TQMap<int,bool> NullCache; - NullCache nullCache; -}; - -class TQ_EXPORT_STQLDRIVER_ODBC TQODBCDriver : public TQSqlDriver -{ -public: - TQODBCDriver( TQObject * parent=0, const char * name=0 ); - TQODBCDriver( STQLHANDLE env, STQLHANDLE con, TQObject * parent=0, const char * name=0 ); - ~TQODBCDriver(); - 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(); - TQSqlQuery createQuery() const; - TQStringList tables( const TQString& user ) 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; - TQSqlIndex primaryIndex( const TQString& tablename ) const; - STQLHANDLE environment(); - STQLHANDLE connection(); - - TQString formatValue( const TQSqlField* field, - bool trimStrings ) const; - // ### 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(); - bool endTrans(); - void cleanup(); - TQODBCPrivate* d; -}; - -#endif 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; -} diff --git a/tqtinterface/qt4/src/sql/drivers/psql/tqsql_psql.h b/tqtinterface/qt4/src/sql/drivers/psql/tqsql_psql.h deleted file mode 100644 index 6afbc96..0000000 --- a/tqtinterface/qt4/src/sql/drivers/psql/tqsql_psql.h +++ /dev/null @@ -1,131 +0,0 @@ -/**************************************************************************** -** -** Definition 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. -** -**********************************************************************/ - -#ifndef TQSQL_PSTQL_H -#define TQSQL_PSTQL_H - -#include <tqsqlresult.h> -#include <tqsqlfield.h> -#include <tqsqldriver.h> -#include <libpq-fe.h> - -#ifdef TQT_PLUGIN -#define TQ_EXPORT_STQLDRIVER_PSQL -#else -#define TQ_EXPORT_STQLDRIVER_PSQL TQ_EXPORT -#endif - -class TQPSTQLPrivate; -class TQPSTQLDriver; -class TQSqlRecordInfo; - -class TQPSTQLResult : public TQSqlResult -{ - friend class TQPSTQLDriver; -public: - TQPSTQLResult( const TQPSTQLDriver* db, const TQPSTQLPrivate* p ); - ~TQPSTQLResult(); - PGresult* result(); -protected: - void cleanup(); - bool fetch( int i ); - bool fetchFirst(); - bool fetchLast(); - TQVariant data( int i ); - bool isNull( int field ); - bool reset ( const TQString& query ); - int size(); - int numRowsAffected(); -private: - int currentSize; - TQPSTQLPrivate* d; -}; - -class TQ_EXPORT_STQLDRIVER_PSQL TQPSTQLDriver : public TQSqlDriver -{ -public: - enum Protocol { - Version6 = 6, - Version7 = 7, - Version71 = 8, - Version73 = 9 - }; - - TQPSTQLDriver( TQObject * parent=0, const char * name=0 ); - TQPSTQLDriver( PGconn * conn, TQObject * parent=0, const char * name=0 ); - ~TQPSTQLDriver(); - 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(); - 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; - - Protocol protocol() const { return pro; } - PGconn* connection(); - TQString formatValue( const TQSqlField* field, - bool trimStrings ) const; - - // ### 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(); - Protocol pro; - TQPSTQLPrivate* d; -}; - -#endif diff --git a/tqtinterface/qt4/src/sql/drivers/sqlite/tqsql_sqlite.cpp b/tqtinterface/qt4/src/sql/drivers/sqlite/tqsql_sqlite.cpp deleted file mode 100644 index bf330e3..0000000 --- a/tqtinterface/qt4/src/sql/drivers/sqlite/tqsql_sqlite.cpp +++ /dev/null @@ -1,513 +0,0 @@ -/**************************************************************************** -** -** Implementation of STQLite driver classes. -** -** Copyright (C) 2010 Timothy Pearson and (C) 1992-2008 Trolltech ASA. -** -** This file is part of the sql module of the TQt GUI Toolkit. -** EDITIONS: FREE, ENTERPRISE -** -** This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE -** WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. -** -****************************************************************************/ - -#include "tqsql_sqlite.h" - -#include <tqdatetime.h> -#include <tqregexp.h> -#include <tqfile.h> - -#if (TQT_VERSION-0 < 0x030000) -# include <tqvector.h> -# if !defined TQ_WS_WIN32 -# include <unistd.h> -# endif -# include "../../../3rdparty/libraries/sqlite/sqlite.h" -#else -# include <tqptrvector.h> -# if !defined TQ_WS_WIN32 -# include <unistd.h> -# endif -# include <sqlite.h> -#endif - -typedef struct sqlite_vm sqlite_vm; - -#define TQSQLITE_DRIVER_NAME "TQSQLITE" - -static TQSqlVariant::Type nameToType(const TQString& typeName) -{ - TQString tName = typeName.upper(); - if (tName.startsWith("INT")) - return TQSqlVariant::Int; - if (tName.startsWith("FLOAT") || tName.startsWith("NUMERIC")) - return TQSqlVariant::Double; - if (tName.startsWith("BOOL")) - return TQSqlVariant::Bool; - // STQLite is typeless - consider everything else as string - return TQSqlVariant::String; -} - -class TQSTQLiteDriverPrivate -{ -public: - TQSTQLiteDriverPrivate(); - sqlite *access; - bool utf8; -}; - -TQSTQLiteDriverPrivate::TQSTQLiteDriverPrivate() : access(0) -{ - utf8 = (qstrcmp(sqlite_encoding, "UTF-8") == 0); -} - -class TQSTQLiteResultPrivate -{ -public: - TQSTQLiteResultPrivate(TQSTQLiteResult *res); - void cleanup(); - bool fetchNext(TQtSqlCachedResult::RowCache *row); - bool isSelect(); - // initializes the recordInfo and the cache - void init(const char **cnames, int numCols, TQtSqlCachedResult::RowCache **row = 0); - void finalize(); - - TQSTQLiteResult* q; - sqlite *access; - - // and we have too keep our own struct for the data (sqlite works via - // callback. - const char *currentTail; - sqlite_vm *currentMachine; - - uint skippedtqStatus: 1; // the status of the fetchNext() that's skipped - TQtSqlCachedResult::RowCache *skipRow; - - uint utf8: 1; - TQSqlRecordInfo rInf; -}; - -static const uint initial_cache_size = 128; - -TQSTQLiteResultPrivate::TQSTQLiteResultPrivate(TQSTQLiteResult* res) : q(res), access(0), currentTail(0), - currentMachine(0), skippedtqStatus(FALSE), skipRow(0), utf8(FALSE) -{ -} - -void TQSTQLiteResultPrivate::cleanup() -{ - finalize(); - rInf.clear(); - currentTail = 0; - currentMachine = 0; - skippedtqStatus = FALSE; - delete skipRow; - skipRow = 0; - q->setAt(TQSql::BeforeFirst); - q->setActive(FALSE); - q->cleanup(); -} - -void TQSTQLiteResultPrivate::finalize() -{ - if (!currentMachine) - return; - - char* err = 0; - int res = sqlite_finalize(currentMachine, &err); - if (err) { - q->setLastError(TQSqlError("Unable to fetch results", err, TQSqlError::Statement, res)); - sqlite_freemem(err); - } - currentMachine = 0; -} - -// called on first fetch -void TQSTQLiteResultPrivate::init(const char **cnames, int numCols, TQtSqlCachedResult::RowCache **row) -{ - if (!cnames) - return; - - rInf.clear(); - if (numCols <= 0) - return; - - for (int i = 0; i < numCols; ++i) { - const char* lastDot = strrchr(cnames[i], '.'); - const char* fieldName = lastDot ? lastDot + 1 : cnames[i]; - rInf.append(TQSqlFieldInfo(fieldName, nameToType(cnames[i+numCols]))); - } - // skip the first fetch - if (row && !*row) { - *row = new TQtSqlCachedResult::RowCache(numCols); - skipRow = *row; - } -} - -bool TQSTQLiteResultPrivate::fetchNext(TQtSqlCachedResult::RowCache* row) -{ - // may be caching. - const char **fvals; - const char **cnames; - int colNum; - int res; - int i; - - if (skipRow) { - // already fetched - if (row) - *row = *skipRow; - delete skipRow; - skipRow = 0; - return skippedtqStatus; - } - - if (!currentMachine) - return FALSE; - - // keep trying while busy, wish I could implement this better. - while ((res = sqlite_step(currentMachine, &colNum, &fvals, &cnames)) == STQLITE_BUSY) { - // sleep instead requesting result again immidiately. -#if defined TQ_WS_WIN32 - Sleep(1000); -#else - sleep(1); -#endif - } - - switch(res) { - case STQLITE_ROW: - // check to see if should fill out columns - if (rInf.isEmpty()) - // must be first call. - init(cnames, colNum, &row); - if (!fvals) - return FALSE; - if (!row) - return TRUE; - for (i = 0; i < colNum; ++i) - (*row)[i] = utf8 ? TQString::fromUtf8(fvals[i]) : TQString(fvals[i]); - return TRUE; - case STQLITE_DONE: - if (rInf.isEmpty()) - // must be first call. - init(cnames, colNum); - q->setAt(TQSql::AfterLast); - return FALSE; - case STQLITE_ERROR: - case STQLITE_MISUSE: - default: - // something wrong, don't get col info, but still return false - finalize(); // finalize to get the error message. - q->setAt(TQSql::AfterLast); - return FALSE; - } - return FALSE; -} - -TQSTQLiteResult::TQSTQLiteResult(const TQSTQLiteDriver* db) -: TQtSqlCachedResult(db) -{ - d = new TQSTQLiteResultPrivate(this); - d->access = db->d->access; - d->utf8 = db->d->utf8; -} - -TQSTQLiteResult::~TQSTQLiteResult() -{ - d->cleanup(); - delete d; -} - -/* - Execute \a query. -*/ -bool TQSTQLiteResult::reset (const TQString& query) -{ - // this is where we build a query. - if (!driver()) - return FALSE; - if (!driver()-> isOpen() || driver()->isOpenError()) - return FALSE; - - d->cleanup(); - - // Um, ok. callback based so.... pass private static function for this. - setSelect(FALSE); - char *err = 0; - int res = sqlite_compile(d->access, - d->utf8 ? (const char*)query.utf8().data() : query.ascii(), - &(d->currentTail), - &(d->currentMachine), - &err); - if (res != STQLITE_OK || err) { - setLastError(TQSqlError("Unable to execute statement", err, TQSqlError::Statement, res)); - sqlite_freemem(err); - } - //if (*d->currentTail != '\000' then there is more sql to eval - if (!d->currentMachine) { - setActive(FALSE); - return FALSE; - } - // we have to fetch one row to find out about - // the structure of the result set - d->skippedtqStatus = d->fetchNext(0); - setSelect(!d->rInf.isEmpty()); - if (isSelect()) - init(d->rInf.count()); - setActive(TRUE); - return TRUE; -} - -bool TQSTQLiteResult::gotoNext(TQtSqlCachedResult::RowCache* row) -{ - return d->fetchNext(row); -} - -int TQSTQLiteResult::size() -{ - return -1; -} - -int TQSTQLiteResult::numRowsAffected() -{ - return sqlite_changes(d->access); -} - -///////////////////////////////////////////////////////// - -TQSTQLiteDriver::TQSTQLiteDriver(TQObject * parent, const char * name) - : TQSqlDriver(parent, name ? name : TQSQLITE_DRIVER_NAME) -{ - d = new TQSTQLiteDriverPrivate(); -} - -TQSTQLiteDriver::TQSTQLiteDriver(sqlite *connection, TQObject *parent, const char *name) - : TQSqlDriver(parent, name ? name : TQSQLITE_DRIVER_NAME) -{ - d = new TQSTQLiteDriverPrivate(); - d->access = connection; - setOpen(TRUE); - setOpenError(FALSE); -} - - -TQSTQLiteDriver::~TQSTQLiteDriver() -{ - delete d; -} - -bool TQSTQLiteDriver::hasFeature(DriverFeature f) const -{ - switch (f) { - case Transactions: - return TRUE; -#if (TQT_VERSION-0 >= 0x030000) - case Unicode: - return d->utf8; -#endif -// case BLOB: - default: - return FALSE; - } -} - -/* - STQLite dbs have no user name, passwords, hosts or ports. - just file names. -*/ -bool TQSTQLiteDriver::open(const TQString & db, const TQString &, const TQString &, const TQString &, int, const TQString &) -{ - if (isOpen()) - close(); - - if (db.isEmpty()) - return FALSE; - - char* err = 0; - d->access = sqlite_open(TQFile::encodeName(db), 0, &err); - if (err) { - setLastError(TQSqlError("Error to open database", err, TQSqlError::Connection)); - sqlite_freemem(err); - err = 0; - } - - if (d->access) { - setOpen(TRUE); - setOpenError(FALSE); - return TRUE; - } - setOpenError(TRUE); - return FALSE; -} - -void TQSTQLiteDriver::close() -{ - if (isOpen()) { - sqlite_close(d->access); - d->access = 0; - setOpen(FALSE); - setOpenError(FALSE); - } -} - -TQSqlQuery TQSTQLiteDriver::createQuery() const -{ - return TQSqlQuery(new TQSTQLiteResult(this)); -} - -bool TQSTQLiteDriver::beginTransaction() -{ - if (!isOpen() || isOpenError()) - return FALSE; - - char* err; - int res = sqlite_exec(d->access, "BEGIN", 0, this, &err); - - if (res == STQLITE_OK) - return TRUE; - - setLastError(TQSqlError("Unable to begin transaction", err, TQSqlError::Transaction, res)); - sqlite_freemem(err); - return FALSE; -} - -bool TQSTQLiteDriver::commitTransaction() -{ - if (!isOpen() || isOpenError()) - return FALSE; - - char* err; - int res = sqlite_exec(d->access, "COMMIT", 0, this, &err); - - if (res == STQLITE_OK) - return TRUE; - - setLastError(TQSqlError("Unable to commit transaction", err, TQSqlError::Transaction, res)); - sqlite_freemem(err); - return FALSE; -} - -bool TQSTQLiteDriver::rollbackTransaction() -{ - if (!isOpen() || isOpenError()) - return FALSE; - - char* err; - int res = sqlite_exec(d->access, "ROLLBACK", 0, this, &err); - - if (res == STQLITE_OK) - return TRUE; - - setLastError(TQSqlError("Unable to rollback Transaction", err, TQSqlError::Transaction, res)); - sqlite_freemem(err); - return FALSE; -} - -TQStringList TQSTQLiteDriver::tables(const TQString &typeName) const -{ - TQStringList res; - if (!isOpen()) - return res; - int type = typeName.toInt(); - - TQSqlQuery q = createQuery(); - q.setForwardOnly(TRUE); -#if (TQT_VERSION-0 >= 0x030000) - if ((type & (int)TQSql::Tables) && (type & (int)TQSql::Views)) - q.exec("SELECT name FROM sqlite_master WHERE type='table' OR type='view'"); - else if (typeName.isEmpty() || (type & (int)TQSql::Tables)) - q.exec("SELECT name FROM sqlite_master WHERE type='table'"); - else if (type & (int)TQSql::Views) - q.exec("SELECT name FROM sqlite_master WHERE type='view'"); -#else - q.exec("SELECT name FROM sqlite_master WHERE type='table' OR type='view'"); -#endif - - - if (q.isActive()) { - while(q.next()) - res.append(q.value(0).toString()); - } - -#if (TQT_VERSION-0 >= 0x030000) - if (type & (int)TQSql::SystemTables) { - // there are no internal tables beside this one: - res.append("sqlite_master"); - } -#endif - - return res; -} - -TQSqlIndex TQSTQLiteDriver::primaryIndex(const TQString &tblname) const -{ - TQSqlRecordInfo rec(recordInfo(tblname)); // expensive :( - - if (!isOpen()) - return TQSqlIndex(); - - TQSqlQuery q = createQuery(); - q.setForwardOnly(TRUE); - // finrst find a UNITQUE INDEX - q.exec("PRAGMA index_list('" + tblname + "');"); - TQString indexname; - while(q.next()) { - if (q.value(2).toInt()==1) { - indexname = q.value(1).toString(); - break; - } - } - if (indexname.isEmpty()) - return TQSqlIndex(); - - q.exec("PRAGMA index_info('" + indexname + "');"); - - TQSqlIndex index(tblname, indexname); - while(q.next()) { - TQString name = q.value(2).toString(); - TQSqlVariant::Type type = TQSqlVariant::Invalid; - if (rec.contains(name)) - type = rec.find(name).type(); - index.append(TQSqlField(name, type)); - } - return index; -} - -TQSqlRecordInfo TQSTQLiteDriver::recordInfo(const TQString &tbl) const -{ - if (!isOpen()) - return TQSqlRecordInfo(); - - TQSqlQuery q = createQuery(); - q.setForwardOnly(TRUE); - q.exec("SELECT * FROM " + tbl + " LIMIT 1"); - return recordInfo(q); -} - -TQSqlRecord TQSTQLiteDriver::record(const TQString &tblname) const -{ - if (!isOpen()) - return TQSqlRecord(); - - return recordInfo(tblname).toRecord(); -} - -TQSqlRecord TQSTQLiteDriver::record(const TQSqlQuery& query) const -{ - if (query.isActive() && query.driver() == this) { - TQSTQLiteResult* result = (TQSTQLiteResult*)query.result(); - return result->d->rInf.toRecord(); - } - return TQSqlRecord(); -} - -TQSqlRecordInfo TQSTQLiteDriver::recordInfo(const TQSqlQuery& query) const -{ - if (query.isActive() && query.driver() == this) { - TQSTQLiteResult* result = (TQSTQLiteResult*)query.result(); - return result->d->rInf; - } - return TQSqlRecordInfo(); -} diff --git a/tqtinterface/qt4/src/sql/drivers/sqlite/tqsql_sqlite.h b/tqtinterface/qt4/src/sql/drivers/sqlite/tqsql_sqlite.h deleted file mode 100644 index 6100089..0000000 --- a/tqtinterface/qt4/src/sql/drivers/sqlite/tqsql_sqlite.h +++ /dev/null @@ -1,90 +0,0 @@ -/**************************************************************************** -** -** Definition of STQLite driver classes. -** -** Copyright (C) 2010 Timothy Pearson and (C) 1992-2008 Trolltech ASA. -** -** This file is part of the sql module of the TQt GUI Toolkit. -** EDITIONS: FREE, ENTERPRISE -** -** This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE -** WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. -** -****************************************************************************/ - -#ifndef TQSQL_STQLITE_H -#define TQSQL_STQLITE_H - -#include <tqsqldriver.h> -#include <tqsqlresult.h> -#include <tqsqlrecord.h> -#include <tqsqlindex.h> -#include "../cache/tqsqlcachedresult.h" - -#if (TQT_VERSION-0 >= 0x030000) -typedef TQVariant TQSqlVariant; -#endif - -#if defined (TQ_OS_WIN32) -# include <tqt_windows.h> -#endif - -class TQSTQLiteDriverPrivate; -class TQSTQLiteResultPrivate; -class TQSTQLiteDriver; -struct sqlite; - -class TQSTQLiteResult : public TQtSqlCachedResult -{ - friend class TQSTQLiteDriver; - friend class TQSTQLiteResultPrivate; -public: - TQSTQLiteResult(const TQSTQLiteDriver* db); - ~TQSTQLiteResult(); - -protected: - bool gotoNext(TQtSqlCachedResult::RowCache* row); - bool reset (const TQString& query); - int size(); - int numRowsAffected(); - -private: - TQSTQLiteResultPrivate* d; -}; - -class TQSTQLiteDriver : public TQSqlDriver -{ - friend class TQSTQLiteResult; -public: - TQSTQLiteDriver(TQObject *parent = 0, const char *name = 0); - TQSTQLiteDriver(sqlite *connection, TQObject *parent = 0, const char *name = 0); - ~TQSTQLiteDriver(); - bool hasFeature(DriverFeature f) const; - bool open(const TQString & db, - const TQString & user, - const TQString & password, - const TQString & host, - int port, - const TQString & connOpts); - bool open( const TQString & db, - const TQString & user, - const TQString & password, - const TQString & host, - int port ) { return open (db, user, password, host, port, TQString()); } - void close(); - TQSqlQuery createQuery() const; - bool beginTransaction(); - bool commitTransaction(); - bool rollbackTransaction(); - TQStringList tables(const TQString& user) const; - - TQSqlRecord record(const TQString& tablename) const; - TQSqlRecordInfo recordInfo(const TQString& tablename) const; - TQSqlIndex primaryIndex(const TQString &table) const; - TQSqlRecord record(const TQSqlQuery& query) const; - TQSqlRecordInfo recordInfo(const TQSqlQuery& query) const; - -private: - TQSTQLiteDriverPrivate* d; -}; -#endif |