2007-11-12 Justin Haygood <jhaygood@reaktix.com>
[WebKit-https.git] / WebCore / platform / sql / SQLiteDatabase.cpp
1 /*
2  * Copyright (C) 2006 Apple Computer, Inc.  All rights reserved.
3  * Copyright (C) 2007 Justin Haygood (jhaygood@reaktix.com)
4  *
5  * Redistribution and use in source and binary forms, with or without
6  * modification, are permitted provided that the following conditions
7  * are met:
8  * 1. Redistributions of source code must retain the above copyright
9  *    notice, this list of conditions and the following disclaimer.
10  * 2. Redistributions in binary form must reproduce the above copyright
11  *    notice, this list of conditions and the following disclaimer in the
12  *    documentation and/or other materials provided with the distribution.
13  *
14  * THIS SOFTWARE IS PROVIDED BY APPLE COMPUTER, INC. ``AS IS'' AND ANY
15  * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
16  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
17  * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL APPLE COMPUTER, INC. OR
18  * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
19  * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
20  * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
21  * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
22  * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
23  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
24  * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 
25  */
26
27 #include "config.h"
28 #include "SQLiteDatabase.h"
29
30 #include "Logging.h"
31 #include "SQLiteAuthorizer.h"
32 #include "SQLiteStatement.h"
33
34 #include <sqlite3.h>
35
36 namespace WebCore {
37
38 const int SQLResultDone = SQLITE_DONE;
39 const int SQLResultError = SQLITE_ERROR;
40 const int SQLResultOk = SQLITE_OK;
41 const int SQLResultRow = SQLITE_ROW;
42 const int SQLResultSchema = SQLITE_SCHEMA;
43
44
45 SQLiteDatabase::SQLiteDatabase()
46     : m_db(0)
47     , m_transactionInProgress(false)
48     , m_openingThread(0)
49 {
50 }
51
52 SQLiteDatabase::~SQLiteDatabase()
53 {
54     close();
55 }
56
57 bool SQLiteDatabase::open(const String& filename)
58 {
59     close();
60     
61     //SQLite expects a null terminator on its UTF16 strings
62     m_path = filename.copy();
63     
64     m_lastError = sqlite3_open16(m_path.charactersWithNullTermination(), &m_db);
65     if (m_lastError != SQLITE_OK) {
66         LOG_ERROR("SQLite database failed to load from %s\nCause - %s", filename.ascii().data(),
67             sqlite3_errmsg(m_db));
68         sqlite3_close(m_db);
69         m_db = 0;
70         return false;
71     }
72
73     if (isOpen())
74         m_openingThread = currentThread();
75     
76     if (!SQLiteStatement(*this, "PRAGMA temp_store = MEMORY;").executeCommand())
77         LOG_ERROR("SQLite database could not set temp_store to memory");
78
79     return isOpen();
80 }
81
82 void SQLiteDatabase::close()
83 {
84     if (m_db) {
85         sqlite3_close(m_db);
86         m_path.truncate(0);
87         m_db = 0;
88     }
89
90     m_openingThread = 0;
91 }
92
93 void SQLiteDatabase::setFullsync(bool fsync) 
94 {
95     if (fsync) 
96         executeCommand("PRAGMA fullfsync = 1;");
97     else
98         executeCommand("PRAGMA fullfsync = 0;");
99 }
100
101 void SQLiteDatabase::setSynchronous(SynchronousPragma sync)
102 {
103     executeCommand(String::format("PRAGMA synchronous = %i", sync));
104 }
105
106 void SQLiteDatabase::setBusyTimeout(int ms)
107 {
108     if (m_db)
109         sqlite3_busy_timeout(m_db, ms);
110     else
111         LOG(SQLDatabase, "BusyTimeout set on non-open database");
112 }
113
114 void SQLiteDatabase::setBusyHandler(int(*handler)(void*, int))
115 {
116     if (m_db)
117         sqlite3_busy_handler(m_db, handler, NULL);
118     else
119         LOG(SQLDatabase, "Busy handler set on non-open database");
120 }
121
122 bool SQLiteDatabase::executeCommand(const String& sql)
123 {
124     return SQLiteStatement(*this, sql).executeCommand();
125 }
126
127 bool SQLiteDatabase::returnsAtLeastOneResult(const String& sql)
128 {
129     return SQLiteStatement(*this, sql).returnsAtLeastOneResult();
130 }
131
132 bool SQLiteDatabase::tableExists(const String& tablename)
133 {
134     if (!isOpen())
135         return false;
136         
137     String statement = "SELECT name FROM sqlite_master WHERE type = 'table' AND name = '" + tablename + "';";
138     
139     SQLiteStatement sql(*this, statement);
140     sql.prepare();
141     return sql.step() == SQLITE_ROW;
142 }
143
144 void SQLiteDatabase::clearAllTables()
145 {
146     String query = "SELECT name FROM sqlite_master WHERE type='table';";
147     Vector<String> tables;
148     if (!SQLiteStatement(*this, query).returnTextResults16(0, tables)) {
149         LOG(SQLDatabase, "Unable to retrieve list of tables from database");
150         return;
151     }
152     
153     for (Vector<String>::iterator table = tables.begin(); table != tables.end(); ++table ) {
154         if (*table == "sqlite_sequence")
155             continue;
156         if (!executeCommand("DROP TABLE " + *table))
157             LOG(SQLDatabase, "Unable to drop table %s", (*table).ascii().data());
158     }
159 }
160
161 void SQLiteDatabase::runVacuumCommand()
162 {
163     if (!executeCommand("VACUUM;"))
164         LOG(SQLDatabase, "Unable to vacuum database - %s", lastErrorMsg());
165 }
166
167 int64_t SQLiteDatabase::lastInsertRowID()
168 {
169     if (!m_db)
170         return 0;
171     return sqlite3_last_insert_rowid(m_db);
172 }
173
174 int SQLiteDatabase::lastChanges()
175 {
176     if (!m_db)
177         return 0;
178     return sqlite3_changes(m_db);
179 }
180
181 int SQLiteDatabase::lastError()
182 {
183     return m_db ? sqlite3_errcode(m_db) : SQLITE_ERROR;
184 }
185
186 const char* SQLiteDatabase::lastErrorMsg()
187
188     return sqlite3_errmsg(m_db);
189 }
190
191 int SQLiteDatabase::authorizerFunction(void* userData, int actionCode, const char* parameter1, const char* parameter2, const char* /*databaseName*/, const char* /*trigger_or_view*/)
192 {
193     SQLiteAuthorizer* auth = static_cast<SQLiteAuthorizer*>(userData);
194     ASSERT(auth);
195
196     switch (actionCode) {
197         case SQLITE_CREATE_INDEX:
198             return auth->createIndex(parameter1, parameter2);
199         case SQLITE_CREATE_TABLE:
200             return auth->createTable(parameter1);
201         case SQLITE_CREATE_TEMP_INDEX:
202             return auth->createTempIndex(parameter1, parameter2);
203         case SQLITE_CREATE_TEMP_TABLE:
204             return auth->createTempTable(parameter1);
205         case SQLITE_CREATE_TEMP_TRIGGER:
206             return auth->createTempTrigger(parameter1, parameter2);
207         case SQLITE_CREATE_TEMP_VIEW:
208             return auth->createTempView(parameter1);
209         case SQLITE_CREATE_TRIGGER:
210             return auth->createTrigger(parameter1, parameter2);
211         case SQLITE_CREATE_VIEW:
212             return auth->createView(parameter1);
213         case SQLITE_DELETE:
214             return auth->allowDelete(parameter1);
215         case SQLITE_DROP_INDEX:
216             return auth->dropIndex(parameter1, parameter2);
217         case SQLITE_DROP_TABLE:
218             return auth->dropTable(parameter1);
219         case SQLITE_DROP_TEMP_INDEX:
220             return auth->dropTempIndex(parameter1, parameter2);
221         case SQLITE_DROP_TEMP_TABLE:
222             return auth->dropTempTable(parameter1);
223         case SQLITE_DROP_TEMP_TRIGGER:
224             return auth->dropTempTrigger(parameter1, parameter2);
225         case SQLITE_DROP_TEMP_VIEW:
226             return auth->dropTempView(parameter1);
227         case SQLITE_DROP_TRIGGER:
228             return auth->dropTrigger(parameter1, parameter2);
229         case SQLITE_DROP_VIEW:
230             return auth->dropView(parameter1);
231         case SQLITE_INSERT:
232             return auth->allowInsert(parameter1);
233         case SQLITE_PRAGMA:
234             return auth->allowPragma(parameter1, parameter2);
235         case SQLITE_READ:
236             return auth->allowRead(parameter1, parameter2);
237         case SQLITE_SELECT:
238             return auth->allowSelect();
239         case SQLITE_TRANSACTION:
240             return auth->allowTransaction();
241         case SQLITE_UPDATE:
242             return auth->allowUpdate(parameter1, parameter2);
243         case SQLITE_ATTACH:
244             return auth->allowAttach(parameter1);
245         case SQLITE_DETACH:
246             return auth->allowDetach(parameter1);
247         case SQLITE_ALTER_TABLE:
248             return auth->allowAlterTable(parameter1, parameter2);
249         case SQLITE_REINDEX:
250             return auth->allowReindex(parameter1);
251 #if SQLITE_VERSION_NUMBER >= 3003013 
252         case SQLITE_ANALYZE:
253             return auth->allowAnalyze(parameter1);
254         case SQLITE_CREATE_VTABLE:
255             return auth->createVTable(parameter1, parameter2);
256         case SQLITE_DROP_VTABLE:
257             return auth->dropVTable(parameter1, parameter2);
258         case SQLITE_FUNCTION:
259             return auth->allowFunction(parameter1);
260 #endif
261         default:
262             ASSERT_NOT_REACHED();
263             return SQLAuthDeny;
264     }
265 }
266
267 void SQLiteDatabase::setAuthorizer(PassRefPtr<SQLiteAuthorizer> auth)
268 {
269     if (!m_db) {
270         LOG_ERROR("Attempt to set an authorizer on a non-open SQL database");
271         ASSERT_NOT_REACHED();
272         return;
273     }
274
275     MutexLocker locker(m_authorizerLock);
276
277     m_authorizer = auth;
278     if (m_authorizer)
279         sqlite3_set_authorizer(m_db, SQLiteDatabase::authorizerFunction, m_authorizer.get());
280     else
281         sqlite3_set_authorizer(m_db, NULL, 0);
282 }
283
284 void SQLiteDatabase::lock()
285 {
286     m_lockingMutex.lock();
287 }
288
289 void SQLiteDatabase::unlock()
290 {
291     m_lockingMutex.unlock();
292 }
293
294 } // namespace WebCore