kexi
pqxxconnection.cpp00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020 #include "pqxxconnection.h"
00021 #include <qvariant.h>
00022 #include <qfile.h>
00023 #include <kdebug.h>
00024 #include <kexidb/error.h>
00025 #include <kexidb/global.h>
00026 #include <klocale.h>
00027 #include <string>
00028 #include "pqxxpreparedstatement.h"
00029 #include "pqxxconnection_p.h"
00030 using namespace KexiDB;
00031
00032 pqxxTransactionData::pqxxTransactionData(Connection *conn, bool nontransaction)
00033 : TransactionData(conn)
00034 {
00035 if (nontransaction)
00036 data = new pqxx::nontransaction(*static_cast<pqxxSqlConnection*>(conn)->d->pqxxsql );
00037 else
00038 data = new pqxx::transaction<>(*static_cast<pqxxSqlConnection*>(conn)->d->pqxxsql );
00039 if (!static_cast<pqxxSqlConnection*>(conn)->m_trans) {
00040 static_cast<pqxxSqlConnection*>(conn)->m_trans = this;
00041 }
00042 }
00043
00044 pqxxTransactionData::~pqxxTransactionData()
00045 {
00046 if (static_cast<pqxxSqlConnection*>(m_conn)->m_trans == this) {
00047 static_cast<pqxxSqlConnection*>(m_conn)->m_trans = 0;
00048 }
00049 delete data;
00050 data = 0;
00051 }
00052
00053
00054
00055 pqxxSqlConnection::pqxxSqlConnection(Driver *driver, ConnectionData &conn_data)
00056 : Connection(driver,conn_data)
00057 , d( new pqxxSqlConnectionInternal(this) )
00058 , m_trans(0)
00059 {
00060 }
00061
00062
00063
00064 pqxxSqlConnection::~pqxxSqlConnection()
00065 {
00066
00067 destroy();
00068 delete d;
00069 }
00070
00071
00072
00073 Cursor* pqxxSqlConnection::prepareQuery( const QString& statement, uint cursor_options)
00074 {
00075 Q_UNUSED(cursor_options);
00076 return new pqxxSqlCursor(this, statement, 1);
00077 }
00078
00079
00080
00081 Cursor* pqxxSqlConnection::prepareQuery( QuerySchema& query, uint cursor_options)
00082 {
00083 Q_UNUSED(cursor_options);
00084 return new pqxxSqlCursor(this, query, 1);
00085 }
00086
00087
00088
00089 QString pqxxSqlConnection::escapeName(const QString &name) const
00090 {
00091 return QString("\"" + name + "\"");
00092 }
00093
00094
00095
00096
00097 bool pqxxSqlConnection::drv_connect(KexiDB::ServerVersionInfo& version)
00098 {
00099 KexiDBDrvDbg << "pqxxSqlConnection::drv_connect" << endl;
00100 version.clear();
00101 d->version = &version;
00102 #ifdef __GNUC__
00103 #warning pqxxSqlConnection::drv_connect implement setting version info when we drop libpqxx for libpq
00104 #endif
00105 return true;
00106 }
00107
00108
00109
00110
00111 bool pqxxSqlConnection::drv_disconnect()
00112 {
00113 KexiDBDrvDbg << "pqxxSqlConnection::drv_disconnect: " << endl;
00114 return true;
00115 }
00116
00117
00118
00119 bool pqxxSqlConnection::drv_getDatabasesList( QStringList &list )
00120 {
00121
00122
00123 if (executeSQL("SELECT datname FROM pg_database WHERE datallowconn = TRUE"))
00124 {
00125 std::string N;
00126 for (pqxx::result::const_iterator c = d->res->begin(); c != d->res->end(); ++c)
00127 {
00128
00129 c[0].to(N);
00130
00131 list << QString::fromLatin1 (N.c_str());
00132 }
00133 return true;
00134 }
00135
00136 return false;
00137 }
00138
00139
00140
00141 bool pqxxSqlConnection::drv_createDatabase( const QString &dbName )
00142 {
00143 KexiDBDrvDbg << "pqxxSqlConnection::drv_createDatabase: " << dbName << endl;
00144
00145 if (executeSQL("CREATE DATABASE " + escapeName(dbName)))
00146 return true;
00147
00148 return false;
00149 }
00150
00151
00152
00153 bool pqxxSqlConnection::drv_useDatabase( const QString &dbName, bool *cancelled,
00154 MessageHandler* msgHandler )
00155 {
00156 Q_UNUSED(cancelled);
00157 Q_UNUSED(msgHandler);
00158 KexiDBDrvDbg << "pqxxSqlConnection::drv_useDatabase: " << dbName << endl;
00159
00160 QString conninfo;
00161 QString socket;
00162 QStringList sockets;
00163
00164 if (data()->hostName.isEmpty() || data()->hostName == "localhost")
00165 {
00166 if (data()->localSocketFileName.isEmpty())
00167 {
00168 sockets.append("/tmp/.s.PGSQL.5432");
00169
00170 for(QStringList::ConstIterator it = sockets.constBegin(); it != sockets.constEnd(); it++)
00171 {
00172 if(QFile(*it).exists())
00173 {
00174 socket = (*it);
00175 break;
00176 }
00177 }
00178 }
00179 else
00180 {
00181 socket=data()->localSocketFileName;
00182 }
00183 }
00184 else
00185 {
00186 conninfo = "host='" + data()->hostName + "'";
00187 }
00188
00189
00190 if (data()->port == 0)
00191 data()->port = 5432;
00192
00193 conninfo += QString::fromLatin1(" port='%1'").arg(data()->port);
00194
00195 conninfo += QString::fromLatin1(" dbname='%1'").arg(dbName);
00196
00197 if (!data()->userName.isNull())
00198 conninfo += QString::fromLatin1(" user='%1'").arg(data()->userName);
00199
00200 if (!data()->password.isNull())
00201 conninfo += QString::fromLatin1(" password='%1'").arg(data()->password);
00202
00203 try
00204 {
00205 d->pqxxsql = new pqxx::connection( conninfo.latin1() );
00206 drv_executeSQL( "SET DEFAULT_WITH_OIDS TO ON" );
00207
00208 if (d->version) {
00210 }
00211 return true;
00212 }
00213 catch(const std::exception &e)
00214 {
00215 KexiDBDrvDbg << "pqxxSqlConnection::drv_useDatabase:exception - " << e.what() << endl;
00216 d->errmsg = QString::fromUtf8( e.what() );
00217
00218 }
00219 catch(...)
00220 {
00221 d->errmsg = i18n("Unknown error.");
00222 }
00223 return false;
00224 }
00225
00226
00227
00228 bool pqxxSqlConnection::drv_closeDatabase()
00229 {
00230 KexiDBDrvDbg << "pqxxSqlConnection::drv_closeDatabase" << endl;
00231
00232
00233 delete d->pqxxsql;
00234 return true;
00235
00236
00237
00238
00239
00240
00241
00242
00243 }
00244
00245
00246
00247 bool pqxxSqlConnection::drv_dropDatabase( const QString &dbName )
00248 {
00249 KexiDBDrvDbg << "pqxxSqlConnection::drv_dropDatabase: " << dbName << endl;
00250
00251
00252 if (executeSQL("DROP DATABASE " + escapeName(dbName)))
00253 return true;
00254
00255 return false;
00256 }
00257
00258
00259
00260 bool pqxxSqlConnection::drv_executeSQL( const QString& statement )
00261 {
00262
00263 bool ok = false;
00264
00265
00266 delete d->res;
00267 d->res = 0;
00268
00269
00270 try
00271 {
00272
00273 const bool implicityStarted = !m_trans;
00274 if (implicityStarted)
00275 (void)new pqxxTransactionData(this, true);
00276
00277
00278
00279
00280 d->res = new pqxx::result(m_trans->data->exec(std::string(statement.utf8())));
00281
00282
00283 if (implicityStarted) {
00284 pqxxTransactionData *t = m_trans;
00285 drv_commitTransaction(t);
00286 delete t;
00287
00288 }
00289
00290
00291 ok = true;
00292 }
00293 catch(const pqxx::sql_error& sqlerr) {
00294 KexiDBDrvDbg << "pqxxSqlConnection::drv_executeSQL: sql_error exception - " << sqlerr.query().c_str() << endl;
00295 }
00296 catch (const pqxx::broken_connection& bcerr) {
00297 KexiDBDrvDbg << "pqxxSqlConnection::drv_executeSQL: broken_connection exception" << endl;
00298 }
00299 catch (const std::exception &e)
00300 {
00301
00302 d->errmsg = QString::fromUtf8( e.what() );
00303 KexiDBDrvDbg << "pqxxSqlConnection::drv_executeSQL:exception - " << e.what() << endl;
00304 }
00305 catch(...)
00306 {
00307 d->errmsg = i18n("Unknown error.");
00308 }
00309
00310 return ok;
00311 }
00312
00313
00314
00315 bool pqxxSqlConnection::drv_isDatabaseUsed() const
00316 {
00317 if (d->pqxxsql->is_open())
00318 {
00319 return true;
00320 }
00321 return false;
00322 }
00323
00324
00325
00326 Q_ULLONG pqxxSqlConnection::drv_lastInsertRowID()
00327 {
00328 if (d->res)
00329 {
00330 pqxx::oid theOid = d->res->inserted_oid();
00331
00332 if (theOid != pqxx::oid_none)
00333 {
00334 return (Q_ULLONG)theOid;
00335 }
00336 else
00337 {
00338 return 0;
00339 }
00340 }
00341 return 0;
00342 }
00343
00344
00345 bool pqxxSqlConnection::drv_containsTable( const QString &tableName )
00346 {
00347 bool success;
00348 return resultExists(QString("select 1 from pg_class where relkind='r' and relname LIKE %1")
00349 .arg(driver()->escapeString(tableName)), success) && success;
00350 }
00351
00352 bool pqxxSqlConnection::drv_getTablesList( QStringList &list )
00353 {
00354 KexiDB::Cursor *cursor;
00355 m_sql = "select lower(relname) from pg_class where relkind='r'";
00356 if (!(cursor = executeQuery( m_sql ))) {
00357 KexiDBDrvWarn << "pqxxSqlConnection::drv_getTablesList(): !executeQuery()" << endl;
00358 return false;
00359 }
00360 list.clear();
00361 cursor->moveFirst();
00362 while (!cursor->eof() && !cursor->error()) {
00363 list += cursor->value(0).toString();
00364 cursor->moveNext();
00365 }
00366 if (cursor->error()) {
00367 deleteCursor(cursor);
00368 return false;
00369 }
00370 return deleteCursor(cursor);
00371 }
00372
00373
00374 TransactionData* pqxxSqlConnection::drv_beginTransaction()
00375 {
00376 return new pqxxTransactionData(this, false);
00377 }
00378
00379 bool pqxxSqlConnection::drv_commitTransaction(TransactionData *tdata)
00380 {
00381 bool result = true;
00382 try {
00383 static_cast<pqxxTransactionData*>(tdata)->data->commit();
00384 }
00385 catch (const std::exception &e)
00386 {
00387
00388 d->errmsg = QString::fromUtf8( e.what() );
00389 result = false;
00390 }
00391 catch (...) {
00393 setError();
00394 result = false;
00395 }
00396 if (m_trans == tdata)
00397 m_trans = 0;
00398 return result;
00399 }
00400
00401 bool pqxxSqlConnection::drv_rollbackTransaction(TransactionData *tdata)
00402 {
00403 bool result = true;
00404 try {
00405 static_cast<pqxxTransactionData*>(tdata)->data->abort();
00406 }
00407 catch (const std::exception &e)
00408 {
00409
00410 d->errmsg = QString::fromUtf8( e.what() );
00411
00412 result = false;
00413 }
00414 catch (...) {
00415 d->errmsg = i18n("Unknown error.");
00416 result = false;
00417 }
00418 if (m_trans == tdata)
00419 m_trans = 0;
00420 return result;
00421 }
00422
00423 int pqxxSqlConnection::serverResult()
00424 {
00425 return d->resultCode;
00426 }
00427
00428 QString pqxxSqlConnection::serverResultName()
00429 {
00430 return QString::null;
00431 }
00432
00433 void pqxxSqlConnection::drv_clearServerResult()
00434 {
00435 d->resultCode = 0;
00436 }
00437
00438 QString pqxxSqlConnection::serverErrorMsg()
00439 {
00440 return d->errmsg;
00441 }
00442
00443 PreparedStatement::Ptr pqxxSqlConnection::prepareStatement(PreparedStatement::StatementType type,
00444 FieldList& fields)
00445 {
00446 return new pqxxPreparedStatement(type, *d, fields);
00447 }
00448 #include "pqxxconnection.moc"
|