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