diff options
author | tpearson <tpearson@283d02a7-25f6-0310-bc7c-ecb5cbfe19da> | 2010-01-20 01:29:50 +0000 |
---|---|---|
committer | tpearson <tpearson@283d02a7-25f6-0310-bc7c-ecb5cbfe19da> | 2010-01-20 01:29:50 +0000 |
commit | 8362bf63dea22bbf6736609b0f49c152f975eb63 (patch) | |
tree | 0eea3928e39e50fae91d4e68b21b1e6cbae25604 /kexi/kexidb/drivers/pqxx/pqxxconnection.cpp | |
download | koffice-8362bf63dea22bbf6736609b0f49c152f975eb63.tar.gz koffice-8362bf63dea22bbf6736609b0f49c152f975eb63.zip |
Added old abandoned KDE3 version of koffice
git-svn-id: svn://anonsvn.kde.org/home/kde/branches/trinity/applications/koffice@1077364 283d02a7-25f6-0310-bc7c-ecb5cbfe19da
Diffstat (limited to 'kexi/kexidb/drivers/pqxx/pqxxconnection.cpp')
-rw-r--r-- | kexi/kexidb/drivers/pqxx/pqxxconnection.cpp | 448 |
1 files changed, 448 insertions, 0 deletions
diff --git a/kexi/kexidb/drivers/pqxx/pqxxconnection.cpp b/kexi/kexidb/drivers/pqxx/pqxxconnection.cpp new file mode 100644 index 00000000..8465bcf4 --- /dev/null +++ b/kexi/kexidb/drivers/pqxx/pqxxconnection.cpp @@ -0,0 +1,448 @@ +/* This file is part of the KDE project + Copyright (C) 2003 Adam Pigg <adam@piggz.co.uk> + + This program is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public + License as published by the Free Software Foundation; either + version 2 of the License, or (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public License + along with this program; see the file COPYING. If not, write to + the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301, USA. +*/ + +#include "pqxxconnection.h" +#include <qvariant.h> +#include <qfile.h> +#include <kdebug.h> +#include <kexidb/error.h> +#include <kexidb/global.h> +#include <klocale.h> +#include <string> +#include "pqxxpreparedstatement.h" +#include "pqxxconnection_p.h" +using namespace KexiDB; + +pqxxTransactionData::pqxxTransactionData(Connection *conn, bool nontransaction) + : TransactionData(conn) +{ + if (nontransaction) + data = new pqxx::nontransaction(*static_cast<pqxxSqlConnection*>(conn)->d->pqxxsql /* todo: add name? */); + else + data = new pqxx::transaction<>(*static_cast<pqxxSqlConnection*>(conn)->d->pqxxsql /* todo: add name? */); + if (!static_cast<pqxxSqlConnection*>(conn)->m_trans) { + static_cast<pqxxSqlConnection*>(conn)->m_trans = this; + } +} + +pqxxTransactionData::~pqxxTransactionData() +{ + if (static_cast<pqxxSqlConnection*>(m_conn)->m_trans == this) { + static_cast<pqxxSqlConnection*>(m_conn)->m_trans = 0; + } + delete data; + data = 0; +} + +//================================================================================== + +pqxxSqlConnection::pqxxSqlConnection(Driver *driver, ConnectionData &conn_data) + : Connection(driver,conn_data) + , d( new pqxxSqlConnectionInternal(this) ) + , m_trans(0) +{ +} + +//================================================================================== +//Do any tidying up before the object is deleted +pqxxSqlConnection::~pqxxSqlConnection() +{ + //delete m_trans; + destroy(); + delete d; +} + +//================================================================================== +//Return a new query based on a query statment +Cursor* pqxxSqlConnection::prepareQuery( const QString& statement, uint cursor_options) +{ + Q_UNUSED(cursor_options); + return new pqxxSqlCursor(this, statement, 1); //Always used buffered cursor +} + +//================================================================================== +//Return a new query based on a query object +Cursor* pqxxSqlConnection::prepareQuery( QuerySchema& query, uint cursor_options) +{ + Q_UNUSED(cursor_options); + return new pqxxSqlCursor(this, query, 1);//Always used buffered cursor +} + +//================================================================================== +//Properly escaped a database object name +QString pqxxSqlConnection::escapeName(const QString &name) const +{ + return QString("\"" + name + "\""); +} + +//================================================================================== +//Made this a noop +//We tell kexi we are connected, but we wont actually connect until we use a database! +bool pqxxSqlConnection::drv_connect(KexiDB::ServerVersionInfo& version) +{ + KexiDBDrvDbg << "pqxxSqlConnection::drv_connect" << endl; + version.clear(); + d->version = &version; //remember for later... +#ifdef __GNUC__ +#warning pqxxSqlConnection::drv_connect implement setting version info when we drop libpqxx for libpq +#endif + return true; +} + +//================================================================================== +//Made this a noop +//We tell kexi wehave disconnected, but it is actually handled by closeDatabse +bool pqxxSqlConnection::drv_disconnect() +{ + KexiDBDrvDbg << "pqxxSqlConnection::drv_disconnect: " << endl; + return true; +} + +//================================================================================== +//Return a list of database names +bool pqxxSqlConnection::drv_getDatabasesList( QStringList &list ) +{ +// KexiDBDrvDbg << "pqxxSqlConnection::drv_getDatabaseList" << endl; + + if (executeSQL("SELECT datname FROM pg_database WHERE datallowconn = TRUE")) + { + std::string N; + for (pqxx::result::const_iterator c = d->res->begin(); c != d->res->end(); ++c) + { + // Read value of column 0 into a string N + c[0].to(N); + // Copy the result into the return list + list << QString::fromLatin1 (N.c_str()); + } + return true; + } + + return false; +} + +//================================================================================== +//Create a new database +bool pqxxSqlConnection::drv_createDatabase( const QString &dbName ) +{ + KexiDBDrvDbg << "pqxxSqlConnection::drv_createDatabase: " << dbName << endl; + + if (executeSQL("CREATE DATABASE " + escapeName(dbName))) + return true; + + return false; +} + +//================================================================================== +//Use this as our connection instead of connect +bool pqxxSqlConnection::drv_useDatabase( const QString &dbName, bool *cancelled, + MessageHandler* msgHandler ) +{ + Q_UNUSED(cancelled); + Q_UNUSED(msgHandler); + KexiDBDrvDbg << "pqxxSqlConnection::drv_useDatabase: " << dbName << endl; + + QString conninfo; + QString socket; + QStringList sockets; + + if (data()->hostName.isEmpty() || data()->hostName == "localhost") + { + if (data()->localSocketFileName.isEmpty()) + { + sockets.append("/tmp/.s.PGSQL.5432"); + + for(QStringList::ConstIterator it = sockets.constBegin(); it != sockets.constEnd(); it++) + { + if(QFile(*it).exists()) + { + socket = (*it); + break; + } + } + } + else + { + socket=data()->localSocketFileName; //data()->fileName(); + } + } + else + { + conninfo = "host='" + data()->hostName + "'"; + } + + //Build up the connection string + if (data()->port == 0) + data()->port = 5432; + + conninfo += QString::fromLatin1(" port='%1'").arg(data()->port); + + conninfo += QString::fromLatin1(" dbname='%1'").arg(dbName); + + if (!data()->userName.isNull()) + conninfo += QString::fromLatin1(" user='%1'").arg(data()->userName); + + if (!data()->password.isNull()) + conninfo += QString::fromLatin1(" password='%1'").arg(data()->password); + + try + { + d->pqxxsql = new pqxx::connection( conninfo.latin1() ); + drv_executeSQL( "SET DEFAULT_WITH_OIDS TO ON" ); //Postgres 8.1 changed the default to no oids but we need them + + if (d->version) { +//! @todo set version using the connection pointer when we drop libpqxx for libpq + } + return true; + } + catch(const std::exception &e) + { + KexiDBDrvDbg << "pqxxSqlConnection::drv_useDatabase:exception - " << e.what() << endl; + d->errmsg = QString::fromUtf8( e.what() ); + + } + catch(...) + { + d->errmsg = i18n("Unknown error."); + } + return false; +} + +//================================================================================== +//Here we close the database connection +bool pqxxSqlConnection::drv_closeDatabase() +{ + KexiDBDrvDbg << "pqxxSqlConnection::drv_closeDatabase" << endl; +// if (isConnected()) +// { + delete d->pqxxsql; + return true; +// } +/* js: not needed, right? + else + { + d->errmsg = "Not connected to database backend"; + d->res = ERR_NO_CONNECTION; + } + return false;*/ +} + +//================================================================================== +//Drops the given database +bool pqxxSqlConnection::drv_dropDatabase( const QString &dbName ) +{ + KexiDBDrvDbg << "pqxxSqlConnection::drv_dropDatabase: " << dbName << endl; + + //FIXME Maybe should check that dbname is no the currentdb + if (executeSQL("DROP DATABASE " + escapeName(dbName))) + return true; + + return false; +} + +//================================================================================== +//Execute an SQL statement +bool pqxxSqlConnection::drv_executeSQL( const QString& statement ) +{ +// KexiDBDrvDbg << "pqxxSqlConnection::drv_executeSQL: " << statement << endl; + bool ok = false; + + // Clear the last result information... + delete d->res; + d->res = 0; + +// KexiDBDrvDbg << "About to try" << endl; + try + { + //Create a transaction + const bool implicityStarted = !m_trans; + if (implicityStarted) + (void)new pqxxTransactionData(this, true); + + // m_trans = new pqxx::nontransaction(*m_pqxxsql); +// KexiDBDrvDbg << "About to execute" << endl; + //Create a result object through the transaction + d->res = new pqxx::result(m_trans->data->exec(std::string(statement.utf8()))); +// KexiDBDrvDbg << "Executed" << endl; + //Commit the transaction + if (implicityStarted) { + pqxxTransactionData *t = m_trans; + drv_commitTransaction(t); + delete t; +// m_trans = 0; + } + + //If all went well then return true, errors picked up by the catch block + ok = true; + } + catch(const pqxx::sql_error& sqlerr) { + KexiDBDrvDbg << "pqxxSqlConnection::drv_executeSQL: sql_error exception - " << sqlerr.query().c_str() << endl; + } + catch (const pqxx::broken_connection& bcerr) { + KexiDBDrvDbg << "pqxxSqlConnection::drv_executeSQL: broken_connection exception" << endl; + } + catch (const std::exception &e) + { + //If an error ocurred then put the error description into _dbError + d->errmsg = QString::fromUtf8( e.what() ); + KexiDBDrvDbg << "pqxxSqlConnection::drv_executeSQL:exception - " << e.what() << endl; + } + catch(...) + { + d->errmsg = i18n("Unknown error."); + } + //KexiDBDrvDbg << "EXECUTE SQL OK: OID was " << (d->res ? d->res->inserted_oid() : 0) << endl; + return ok; +} + +//================================================================================== +//Return true if currently connected to a database, ignoring the m_is_connected falg. +bool pqxxSqlConnection::drv_isDatabaseUsed() const +{ + if (d->pqxxsql->is_open()) + { + return true; + } + return false; +} + +//================================================================================== +//Return the oid of the last insert - only works if sql was insert of 1 row +Q_ULLONG pqxxSqlConnection::drv_lastInsertRowID() +{ + if (d->res) + { + pqxx::oid theOid = d->res->inserted_oid(); + + if (theOid != pqxx::oid_none) + { + return (Q_ULLONG)theOid; + } + else + { + return 0; + } + } + return 0; +} + +//<queries taken from pqxxMigrate> +bool pqxxSqlConnection::drv_containsTable( const QString &tableName ) +{ + bool success; + return resultExists(QString("select 1 from pg_class where relkind='r' and relname LIKE %1") + .arg(driver()->escapeString(tableName)), success) && success; +} + +bool pqxxSqlConnection::drv_getTablesList( QStringList &list ) +{ + KexiDB::Cursor *cursor; + m_sql = "select lower(relname) from pg_class where relkind='r'"; + if (!(cursor = executeQuery( m_sql ))) { + KexiDBDrvWarn << "pqxxSqlConnection::drv_getTablesList(): !executeQuery()" << endl; + return false; + } + list.clear(); + cursor->moveFirst(); + while (!cursor->eof() && !cursor->error()) { + list += cursor->value(0).toString(); + cursor->moveNext(); + } + if (cursor->error()) { + deleteCursor(cursor); + return false; + } + return deleteCursor(cursor); +} +//</taken from pqxxMigrate> + +TransactionData* pqxxSqlConnection::drv_beginTransaction() +{ + return new pqxxTransactionData(this, false); +} + +bool pqxxSqlConnection::drv_commitTransaction(TransactionData *tdata) +{ + bool result = true; + try { + static_cast<pqxxTransactionData*>(tdata)->data->commit(); + } + catch (const std::exception &e) + { + //If an error ocurred then put the error description into _dbError + d->errmsg = QString::fromUtf8( e.what() ); + result = false; + } + catch (...) { + //! @todo + setError(); + result = false; + } + if (m_trans == tdata) + m_trans = 0; + return result; +} + +bool pqxxSqlConnection::drv_rollbackTransaction(TransactionData *tdata) +{ + bool result = true; + try { + static_cast<pqxxTransactionData*>(tdata)->data->abort(); + } + catch (const std::exception &e) + { + //If an error ocurred then put the error description into _dbError + d->errmsg = QString::fromUtf8( e.what() ); + + result = false; + } + catch (...) { + d->errmsg = i18n("Unknown error."); + result = false; + } + if (m_trans == tdata) + m_trans = 0; + return result; +} + +int pqxxSqlConnection::serverResult() +{ + return d->resultCode; +} + +QString pqxxSqlConnection::serverResultName() +{ + return QString::null; +} + +void pqxxSqlConnection::drv_clearServerResult() +{ + d->resultCode = 0; +} + +QString pqxxSqlConnection::serverErrorMsg() +{ + return d->errmsg; +} + +PreparedStatement::Ptr pqxxSqlConnection::prepareStatement(PreparedStatement::StatementType type, + FieldList& fields) +{ + return new pqxxPreparedStatement(type, *d, fields); +} +#include "pqxxconnection.moc" |