00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020 #include "sqliteconnection.h"
00021 #include "sqliteconnection_p.h"
00022 #include "sqlitecursor.h"
00023 #include "sqlitepreparedstatement.h"
00024
00025 #include "sqlite.h"
00026
00027 #ifndef SQLITE2
00028 # include "kexisql.h"
00029 #endif
00030
00031 #include <kexidb/driver.h>
00032 #include <kexidb/cursor.h>
00033 #include <kexidb/error.h>
00034
00035 #include <qfile.h>
00036 #include <qdir.h>
00037
00038 #include <kgenericfactory.h>
00039 #include <kdebug.h>
00040
00041
00042 #undef KexiDBDrvDbg
00043 #define KexiDBDrvDbg if (0) kdDebug()
00044
00045 using namespace KexiDB;
00046
00047 SQLiteConnectionInternal::SQLiteConnectionInternal(Connection *connection)
00048 : ConnectionInternal(connection)
00049 , data(0)
00050 , data_owned(true)
00051 , errmsg_p(0)
00052 , res(SQLITE_OK)
00053 , temp_st(0x10000)
00054 #ifdef SQLITE3
00055 , result_name(0)
00056 #endif
00057 {
00058 }
00059
00060 SQLiteConnectionInternal::~SQLiteConnectionInternal()
00061 {
00062 if (data_owned && data) {
00063 free( data );
00064 data = 0;
00065 }
00066
00067
00068
00069
00070 }
00071
00072 void SQLiteConnectionInternal::storeResult()
00073 {
00074 if (errmsg_p) {
00075 errmsg = errmsg_p;
00076 sqlite_free(errmsg_p);
00077 errmsg_p = 0;
00078 }
00079 #ifdef SQLITE3
00080 errmsg = (data && res!=SQLITE_OK) ? sqlite3_errmsg(data) : 0;
00081 #endif
00082 }
00083
00085 SQLiteConnection::SQLiteConnection( Driver *driver, ConnectionData &conn_data )
00086 : Connection( driver, conn_data )
00087 ,d(new SQLiteConnectionInternal(this))
00088 {
00089 }
00090
00091 SQLiteConnection::~SQLiteConnection()
00092 {
00093 KexiDBDrvDbg << "SQLiteConnection::~SQLiteConnection()" << endl;
00094
00095
00096 destroy();
00097 delete d;
00098 KexiDBDrvDbg << "SQLiteConnection::~SQLiteConnection() ok" << endl;
00099 }
00100
00101 bool SQLiteConnection::drv_connect()
00102 {
00103 KexiDBDrvDbg << "SQLiteConnection::connect()" << endl;
00104 return true;
00105 }
00106
00107 bool SQLiteConnection::drv_disconnect()
00108 {
00109 KexiDBDrvDbg << "SQLiteConnection::disconnect()" << endl;
00110 return true;
00111 }
00112
00113 bool SQLiteConnection::drv_getDatabasesList( QStringList &list )
00114 {
00115
00116 list.append( m_data->fileName() );
00117 return true;
00118 }
00119
00120 bool SQLiteConnection::drv_containsTable( const QString &tableName )
00121 {
00122 bool success;
00123 return resultExists(QString("select name from sqlite_master where type='table' and name LIKE %1")
00124 .arg(driver()->escapeString(tableName)), success) && success;
00125 }
00126
00127 bool SQLiteConnection::drv_getTablesList( QStringList &list )
00128 {
00129 KexiDB::Cursor *cursor;
00130 m_sql = "select lower(name) from sqlite_master where type='table'";
00131 if (!(cursor = executeQuery( m_sql ))) {
00132 KexiDBWarn << "Connection::drv_getTablesList(): !executeQuery()" << endl;
00133 return false;
00134 }
00135 list.clear();
00136 cursor->moveFirst();
00137 while (!cursor->eof() && !cursor->error()) {
00138 list += cursor->value(0).toString();
00139 cursor->moveNext();
00140 }
00141 if (cursor->error()) {
00142 deleteCursor(cursor);
00143 return false;
00144 }
00145 return deleteCursor(cursor);
00146 }
00147
00148 bool SQLiteConnection::drv_createDatabase( const QString &dbName )
00149 {
00150
00151 return drv_useDatabase(dbName);
00152 #if 0
00153 d->data = sqlite_open( QFile::encodeName( m_data->fileName() ), 0,
00154 &d->errmsg_p );
00155 d->storeResult();
00156 return d->data != 0;
00157 #endif
00158 }
00159
00160 bool SQLiteConnection::drv_useDatabase( const QString &dbName, bool *cancelled,
00161 MessageHandler* msgHandler )
00162 {
00163 Q_UNUSED(dbName);
00164 #ifndef KEXI_FUTURE_FEATURES
00165 Q_UNUSED(cancelled);
00166 Q_UNUSED(msgHandler);
00167 #endif
00168
00169 #ifdef SQLITE2
00170 d->data = sqlite_open( QFile::encodeName( m_data->fileName() ), 0,
00171 &d->errmsg_p );
00172 d->storeResult();
00173 return d->data != 0;
00174 #else //SQLITE3
00175
00177 int exclusiveFlag = Connection::isReadOnly() ? SQLITE_OPEN_READONLY : SQLITE_OPEN_WRITE_LOCKED;
00179 int allowReadonly = 1;
00180 # ifdef KEXI_FUTURE_FEATURES
00181 const bool wasReadOnly = Connection::isReadOnly();
00182 # endif
00183
00184 d->res = sqlite3_open(
00185
00186 QFile::encodeName( m_data->fileName() ),
00187 &d->data,
00188 exclusiveFlag,
00189 allowReadonly
00190 );
00191 d->storeResult();
00192
00193 #ifdef KEXI_FUTURE_FEATURES
00194 if (d->res == SQLITE_OK && cancelled && !wasReadOnly && allowReadonly && isReadOnly()) {
00195
00196 if (KMessageBox::Continue !=
00197 askQuestion(
00198 futureI18n("Do you want to open file \"%1\" as read-only?")
00199 .arg(QDir::convertSeparators(m_data->fileName()))
00200 + "\n\n"
00201 + i18n("The file is probably already open on this or another computer.") + " "
00202 + i18n("Could not gain exclusive access for writing the file."),
00203 KMessageBox::WarningContinueCancel, KMessageBox::Continue,
00204 KGuiItem(futureI18n("Open As Read-Only"), "fileopen"), KStdGuiItem::cancel(),
00205 "askBeforeOpeningFileReadOnly", KMessageBox::Notify, msgHandler ))
00206 {
00207 clearError();
00208 if (!drv_closeDatabase())
00209 return false;
00210 *cancelled = true;
00211 return false;
00212 }
00213 }
00214 #endif
00215
00216 if (d->res == SQLITE_CANTOPEN_WITH_LOCKED_READWRITE) {
00217 setError(ERR_ACCESS_RIGHTS,
00218 i18n("The file is probably already open on this or another computer.")+"\n\n"
00219 + i18n("Could not gain exclusive access for reading and writing the file.") + " "
00220 + i18n("Check the file's permissions and whether it is already opened and locked by another application."));
00221 }
00222 else if (d->res == SQLITE_CANTOPEN_WITH_LOCKED_WRITE) {
00223 setError(ERR_ACCESS_RIGHTS,
00224 i18n("The file is probably already open on this or another computer.")+"\n\n"
00225 + i18n("Could not gain exclusive access for writing the file.") + " "
00226 + i18n("Check the file's permissions and whether it is already opened and locked by another application."));
00227 }
00228 return d->res == SQLITE_OK;
00229 #endif
00230 }
00231
00232 bool SQLiteConnection::drv_closeDatabase()
00233 {
00234 if (!d->data)
00235 return false;
00236
00237 #ifdef SQLITE2
00238 sqlite_close(d->data);
00239 d->data = 0;
00240 return true;
00241 #else
00242 const int res = sqlite_close(d->data);
00243 if (SQLITE_OK == res) {
00244 d->data = 0;
00245 return true;
00246 }
00247 if (SQLITE_BUSY==res) {
00248 setError(ERR_OTHER);
00249 }
00250 return false;
00251 #endif
00252 }
00253
00254 bool SQLiteConnection::drv_dropDatabase( const QString &dbName )
00255 {
00256 if (QFile(m_data->fileName()).exists() && !QDir().remove(m_data->fileName())) {
00257 setError(ERR_ACCESS_RIGHTS, i18n("Could not remove file \"%1\".")
00258 .arg(QDir::convertSeparators(dbName)) + " "
00259 + i18n("Check the file's permissions and whether it is already opened and locked by another application."));
00260 return false;
00261 }
00262 return true;
00263 }
00264
00265
00266 Cursor* SQLiteConnection::prepareQuery( const QString& statement, uint cursor_options )
00267 {
00268 return new SQLiteCursor( this, statement, cursor_options );
00269 }
00270
00271 Cursor* SQLiteConnection::prepareQuery( QuerySchema& query, uint cursor_options )
00272 {
00273 return new SQLiteCursor( this, query, cursor_options );
00274 }
00275
00276 bool SQLiteConnection::drv_executeSQL( const QString& statement )
00277 {
00278
00279
00280
00281 #ifdef SQLITE_UTF8
00282 d->temp_st = statement.utf8();
00283 #else
00284 d->temp_st = statement.local8Bit();
00285 #endif
00286
00287 d->res = sqlite_exec(
00288 d->data,
00289 (const char*)d->temp_st,
00290 0,
00291 0,
00292 &d->errmsg_p );
00293 d->storeResult();
00294 return d->res==SQLITE_OK;
00295 }
00296
00297 Q_ULLONG SQLiteConnection::drv_lastInsertRowID()
00298 {
00299 return (Q_ULLONG)sqlite_last_insert_rowid(d->data);
00300 }
00301
00302 int SQLiteConnection::serverResult()
00303 {
00304 return d->res==0 ? Connection::serverResult() : d->res;
00305 }
00306
00307 QString SQLiteConnection::serverResultName()
00308 {
00309 QString r =
00310 #ifdef SQLITE2
00311 QString::fromLatin1( sqlite_error_string(d->res) );
00312 #else //SQLITE3
00313 QString::null;
00314 #endif
00315 return r.isEmpty() ? Connection::serverResultName() : r;
00316 }
00317
00318 void SQLiteConnection::drv_clearServerResult()
00319 {
00320 if (!d)
00321 return;
00322 d->res = SQLITE_OK;
00323 #ifdef SQLITE2
00324 d->errmsg_p = 0;
00325 #else
00326
00327 #endif
00328 }
00329
00330 QString SQLiteConnection::serverErrorMsg()
00331 {
00332 return d->errmsg.isEmpty() ? Connection::serverErrorMsg() : d->errmsg;
00333 }
00334
00335 PreparedStatement::Ptr SQLiteConnection::prepareStatement(PreparedStatement::StatementType type,
00336 FieldList& fields)
00337 {
00338
00339 return new SQLitePreparedStatement(type, *d, fields);
00340
00341 }
00342
00343 bool SQLiteConnection::isReadOnly() const
00344 {
00345 #ifdef SQLITE2
00346 return Connection::isReadOnly();
00347 #else
00348 return d->data ? sqlite3_is_readonly(d->data) : false;
00349 #endif
00350 }
00351
00352 #include "sqliteconnection.moc"