2 * Copyright (C) 2006 Apple Computer, Inc. All rights reserved.
4 * Redistribution and use in source and binary forms, with or without
5 * modification, are permitted provided that the following conditions
7 * 1. Redistributions of source code must retain the above copyright
8 * notice, this list of conditions and the following disclaimer.
9 * 2. Redistributions in binary form must reproduce the above copyright
10 * notice, this list of conditions and the following disclaimer in the
11 * documentation and/or other materials provided with the distribution.
13 * THIS SOFTWARE IS PROVIDED BY APPLE COMPUTER, INC. ``AS IS'' AND ANY
14 * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
15 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
16 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE COMPUTER, INC. OR
17 * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
18 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
19 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
20 * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
21 * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
22 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
23 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
27 #include "SQLiteDatabase.h"
30 #include "SQLiteAuthorizer.h"
31 #include "SQLiteStatement.h"
37 const int SQLResultDone = SQLITE_DONE;
38 const int SQLResultError = SQLITE_ERROR;
39 const int SQLResultOk = SQLITE_OK;
40 const int SQLResultRow = SQLITE_ROW;
41 const int SQLResultSchema = SQLITE_SCHEMA;
44 SQLiteDatabase::SQLiteDatabase()
46 , m_transactionInProgress(false)
49 memset(&m_openingThread, 0, sizeof(pthread_t));
53 SQLiteDatabase::~SQLiteDatabase()
58 bool SQLiteDatabase::open(const String& filename)
62 //SQLite expects a null terminator on its UTF16 strings
63 m_path = filename.copy();
65 m_lastError = sqlite3_open16(m_path.charactersWithNullTermination(), &m_db);
66 if (m_lastError != SQLITE_OK) {
67 LOG_ERROR("SQLite database failed to load from %s\nCause - %s", filename.ascii().data(),
68 sqlite3_errmsg(m_db));
76 m_openingThread = pthread_self();
79 if (!SQLiteStatement(*this, "PRAGMA temp_store = MEMORY;").executeCommand())
80 LOG_ERROR("SQLite database could not set temp_store to memory");
85 void SQLiteDatabase::close()
93 memset(&m_openingThread, 0, sizeof(pthread_t));
97 void SQLiteDatabase::setFullsync(bool fsync)
100 executeCommand("PRAGMA fullfsync = 1;");
102 executeCommand("PRAGMA fullfsync = 0;");
105 void SQLiteDatabase::setSynchronous(SynchronousPragma sync)
107 executeCommand(String::format("PRAGMA synchronous = %i", sync));
110 void SQLiteDatabase::setBusyTimeout(int ms)
113 sqlite3_busy_timeout(m_db, ms);
115 LOG(SQLDatabase, "BusyTimeout set on non-open database");
118 void SQLiteDatabase::setBusyHandler(int(*handler)(void*, int))
121 sqlite3_busy_handler(m_db, handler, NULL);
123 LOG(SQLDatabase, "Busy handler set on non-open database");
126 bool SQLiteDatabase::executeCommand(const String& sql)
128 return SQLiteStatement(*this, sql).executeCommand();
131 bool SQLiteDatabase::returnsAtLeastOneResult(const String& sql)
133 return SQLiteStatement(*this, sql).returnsAtLeastOneResult();
136 bool SQLiteDatabase::tableExists(const String& tablename)
141 String statement = "SELECT name FROM sqlite_master WHERE type = 'table' AND name = '" + tablename + "';";
143 SQLiteStatement sql(*this, statement);
145 return sql.step() == SQLITE_ROW;
148 void SQLiteDatabase::clearAllTables()
150 String query = "SELECT name FROM sqlite_master WHERE type='table';";
151 Vector<String> tables;
152 if (!SQLiteStatement(*this, query).returnTextResults16(0, tables)) {
153 LOG(SQLDatabase, "Unable to retrieve list of tables from database");
157 for (Vector<String>::iterator table = tables.begin(); table != tables.end(); ++table ) {
158 if (*table == "sqlite_sequence")
160 if (!executeCommand("DROP TABLE " + *table))
161 LOG(SQLDatabase, "Unable to drop table %s", (*table).ascii().data());
165 void SQLiteDatabase::runVacuumCommand()
167 if (!executeCommand("VACUUM;"))
168 LOG(SQLDatabase, "Unable to vacuum database - %s", lastErrorMsg());
171 int64_t SQLiteDatabase::lastInsertRowID()
175 return sqlite3_last_insert_rowid(m_db);
178 int SQLiteDatabase::lastChanges()
182 return sqlite3_changes(m_db);
185 int SQLiteDatabase::lastError()
187 return m_db ? sqlite3_errcode(m_db) : SQLITE_ERROR;
190 const char* SQLiteDatabase::lastErrorMsg()
192 return sqlite3_errmsg(m_db);
195 int SQLiteDatabase::authorizerFunction(void* userData, int actionCode, const char* parameter1, const char* parameter2, const char* /*databaseName*/, const char* /*trigger_or_view*/)
197 SQLiteAuthorizer* auth = static_cast<SQLiteAuthorizer*>(userData);
200 switch (actionCode) {
201 case SQLITE_CREATE_INDEX:
202 return auth->createIndex(parameter1, parameter2);
203 case SQLITE_CREATE_TABLE:
204 return auth->createTable(parameter1);
205 case SQLITE_CREATE_TEMP_INDEX:
206 return auth->createTempIndex(parameter1, parameter2);
207 case SQLITE_CREATE_TEMP_TABLE:
208 return auth->createTempTable(parameter1);
209 case SQLITE_CREATE_TEMP_TRIGGER:
210 return auth->createTempTrigger(parameter1, parameter2);
211 case SQLITE_CREATE_TEMP_VIEW:
212 return auth->createTempView(parameter1);
213 case SQLITE_CREATE_TRIGGER:
214 return auth->createTrigger(parameter1, parameter2);
215 case SQLITE_CREATE_VIEW:
216 return auth->createView(parameter1);
218 return auth->allowDelete(parameter1);
219 case SQLITE_DROP_INDEX:
220 return auth->dropIndex(parameter1, parameter2);
221 case SQLITE_DROP_TABLE:
222 return auth->dropTable(parameter1);
223 case SQLITE_DROP_TEMP_INDEX:
224 return auth->dropTempIndex(parameter1, parameter2);
225 case SQLITE_DROP_TEMP_TABLE:
226 return auth->dropTempTable(parameter1);
227 case SQLITE_DROP_TEMP_TRIGGER:
228 return auth->dropTempTrigger(parameter1, parameter2);
229 case SQLITE_DROP_TEMP_VIEW:
230 return auth->dropTempView(parameter1);
231 case SQLITE_DROP_TRIGGER:
232 return auth->dropTrigger(parameter1, parameter2);
233 case SQLITE_DROP_VIEW:
234 return auth->dropView(parameter1);
236 return auth->allowInsert(parameter1);
238 return auth->allowPragma(parameter1, parameter2);
240 return auth->allowRead(parameter1, parameter2);
242 return auth->allowSelect();
243 case SQLITE_TRANSACTION:
244 return auth->allowTransaction();
246 return auth->allowUpdate(parameter1, parameter2);
248 return auth->allowAttach(parameter1);
250 return auth->allowDetach(parameter1);
251 case SQLITE_ALTER_TABLE:
252 return auth->allowAlterTable(parameter1, parameter2);
254 return auth->allowReindex(parameter1);
255 #if SQLITE_VERSION_NUMBER >= 3003013
257 return auth->allowAnalyze(parameter1);
258 case SQLITE_CREATE_VTABLE:
259 return auth->createVTable(parameter1, parameter2);
260 case SQLITE_DROP_VTABLE:
261 return auth->dropVTable(parameter1, parameter2);
262 case SQLITE_FUNCTION:
263 return auth->allowFunction(parameter1);
266 ASSERT_NOT_REACHED();
271 void SQLiteDatabase::setAuthorizer(PassRefPtr<SQLiteAuthorizer> auth)
274 LOG_ERROR("Attempt to set an authorizer on a non-open SQL database");
275 ASSERT_NOT_REACHED();
279 MutexLocker locker(m_authorizerLock);
283 sqlite3_set_authorizer(m_db, SQLiteDatabase::authorizerFunction, m_authorizer.get());
285 sqlite3_set_authorizer(m_db, NULL, 0);
288 void SQLiteDatabase::lock()
290 m_lockingMutex.lock();
293 void SQLiteDatabase::unlock()
295 m_lockingMutex.unlock();
298 } // namespace WebCore