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(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 std::exception &e)
00294 {
00295
00296 d->errmsg = QString::fromUtf8( e.what() );
00297 KexiDBDrvDbg << "pqxxSqlConnection::drv_executeSQL:exception - " << e.what() << endl;
00298 }
00299 catch(...)
00300 {
00301 d->errmsg = i18n("Unknown error.");
00302 }
00303
00304 return ok;
00305 }
00306
00307
00308
00309 bool pqxxSqlConnection::drv_isDatabaseUsed() const
00310 {
00311 if (d->pqxxsql->is_open())
00312 {
00313 return true;
00314 }
00315 return false;
00316 }
00317
00318
00319
00320 Q_ULLONG pqxxSqlConnection::drv_lastInsertRowID()
00321 {
00322 if (d->res)
00323 {
00324 pqxx::oid theOid = d->res->inserted_oid();
00325
00326 if (theOid != pqxx::oid_none)
00327 {
00328 return (Q_ULLONG)theOid;
00329 }
00330 else
00331 {
00332 return 0;
00333 }
00334 }
00335 return 0;
00336 }
00337
00338
00339 bool pqxxSqlConnection::drv_containsTable( const QString &tableName )
00340 {
00341 bool success;
00342 return resultExists(QString("select 1 from pg_class where relkind='r' and relname LIKE %1")
00343 .arg(driver()->escapeString(tableName)), success) && success;
00344 }
00345
00346 bool pqxxSqlConnection::drv_getTablesList( QStringList &list )
00347 {
00348 KexiDB::Cursor *cursor;
00349 m_sql = "select lower(relname) from pg_class where relkind='r'";
00350 if (!(cursor = executeQuery( m_sql ))) {
00351 KexiDBDrvWarn << "pqxxSqlConnection::drv_getTablesList(): !executeQuery()" << endl;
00352 return false;
00353 }
00354 list.clear();
00355 cursor->moveFirst();
00356 while (!cursor->eof() && !cursor->error()) {
00357 list += cursor->value(0).toString();
00358 cursor->moveNext();
00359 }
00360 if (cursor->error()) {
00361 deleteCursor(cursor);
00362 return false;
00363 }
00364 return deleteCursor(cursor);
00365 }
00366
00367
00368 TransactionData* pqxxSqlConnection::drv_beginTransaction()
00369 {
00370 return new pqxxTransactionData(this, false);
00371 }
00372
00373 bool pqxxSqlConnection::drv_commitTransaction(TransactionData *tdata)
00374 {
00375 bool result = true;
00376 try {
00377 static_cast<pqxxTransactionData*>(tdata)->data->commit();
00378 }
00379 catch (const std::exception &e)
00380 {
00381
00382 d->errmsg = QString::fromUtf8( e.what() );
00383 result = false;
00384 }
00385 catch (...) {
00387 setError();
00388 result = false;
00389 }
00390 if (m_trans == tdata)
00391 m_trans = 0;
00392 return result;
00393 }
00394
00395 bool pqxxSqlConnection::drv_rollbackTransaction(TransactionData *tdata)
00396 {
00397 bool result = true;
00398 try {
00399 static_cast<pqxxTransactionData*>(tdata)->data->abort();
00400 }
00401 catch (const std::exception &e)
00402 {
00403
00404 d->errmsg = QString::fromUtf8( e.what() );
00405
00406 result = false;
00407 }
00408 catch (...) {
00409 d->errmsg = i18n("Unknown error.");
00410 result = false;
00411 }
00412 if (m_trans == tdata)
00413 m_trans = 0;
00414 return result;
00415 }
00416
00417 int pqxxSqlConnection::serverResult()
00418 {
00419 return d->resultCode;
00420 }
00421
00422 QString pqxxSqlConnection::serverResultName()
00423 {
00424 return QString::null;
00425 }
00426
00427 void pqxxSqlConnection::drv_clearServerResult()
00428 {
00429 d->resultCode = 0;
00430 }
00431
00432 QString pqxxSqlConnection::serverErrorMsg()
00433 {
00434 return d->errmsg;
00435 }
00436
00437 PreparedStatement::Ptr pqxxSqlConnection::prepareStatement(PreparedStatement::StatementType type,
00438 FieldList& fields)
00439 {
00440 return new pqxxPreparedStatement(type, *d, fields);
00441 }
00442 #include "pqxxconnection.moc"
|