63d1e87ec57a1a8b2c4e502b2eb0ee3598453480
[WebKit-https.git] / WebCore / platform / sql / SQLiteDatabase.cpp
1 /*
2  * Copyright (C) 2006 Apple Computer, Inc.  All rights reserved.
3  *
4  * Redistribution and use in source and binary forms, with or without
5  * modification, are permitted provided that the following conditions
6  * are met:
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.
12  *
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. 
24  */
25
26 #include "config.h"
27 #include "SQLiteDatabase.h"
28
29 #include "Logging.h"
30 #include "SQLiteAuthorizer.h"
31 #include "SQLiteStatement.h"
32
33 #include <sqlite3.h>
34
35 namespace WebCore {
36
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;
42
43
44 SQLiteDatabase::SQLiteDatabase()
45     : m_db(0)
46     , m_transactionInProgress(false)
47 {
48 #ifndef NDEBUG
49     memset(&m_openingThread, 0, sizeof(pthread_t));
50 #endif
51 }
52
53 SQLiteDatabase::~SQLiteDatabase()
54 {
55     close();
56 }
57
58 bool SQLiteDatabase::open(const String& filename)
59 {
60     close();
61     
62     //SQLite expects a null terminator on its UTF16 strings
63     m_path = filename.copy();
64     
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));
69         sqlite3_close(m_db);
70         m_db = 0;
71         return false;
72     }
73
74 #ifndef NDEBUG
75     if (isOpen())
76         m_openingThread = pthread_self();
77 #endif
78     
79     if (!SQLiteStatement(*this, "PRAGMA temp_store = MEMORY;").executeCommand())
80         LOG_ERROR("SQLite database could not set temp_store to memory");
81
82     return isOpen();
83 }
84
85 void SQLiteDatabase::close()
86 {
87     if (m_db) {
88         sqlite3_close(m_db);
89         m_path.truncate(0);
90         m_db = 0;
91     }
92 #ifndef NDEBUG
93     memset(&m_openingThread, 0, sizeof(pthread_t));
94 #endif
95 }
96
97 void SQLiteDatabase::setFullsync(bool fsync) 
98 {
99     if (fsync) 
100         executeCommand("PRAGMA fullfsync = 1;");
101     else
102         executeCommand("PRAGMA fullfsync = 0;");
103 }
104
105 void SQLiteDatabase::setSynchronous(SynchronousPragma sync)
106 {
107     executeCommand(String::format("PRAGMA synchronous = %i", sync));
108 }
109
110 void SQLiteDatabase::setBusyTimeout(int ms)
111 {
112     if (m_db)
113         sqlite3_busy_timeout(m_db, ms);
114     else
115         LOG(SQLDatabase, "BusyTimeout set on non-open database");
116 }
117
118 void SQLiteDatabase::setBusyHandler(int(*handler)(void*, int))
119 {
120     if (m_db)
121         sqlite3_busy_handler(m_db, handler, NULL);
122     else
123         LOG(SQLDatabase, "Busy handler set on non-open database");
124 }
125
126 bool SQLiteDatabase::executeCommand(const String& sql)
127 {
128     return SQLiteStatement(*this, sql).executeCommand();
129 }
130
131 bool SQLiteDatabase::returnsAtLeastOneResult(const String& sql)
132 {
133     return SQLiteStatement(*this, sql).returnsAtLeastOneResult();
134 }
135
136 bool SQLiteDatabase::tableExists(const String& tablename)
137 {
138     if (!isOpen())
139         return false;
140         
141     String statement = "SELECT name FROM sqlite_master WHERE type = 'table' AND name = '" + tablename + "';";
142     
143     SQLiteStatement sql(*this, statement);
144     sql.prepare();
145     return sql.step() == SQLITE_ROW;
146 }
147
148 void SQLiteDatabase::clearAllTables()
149 {
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");
154         return;
155     }
156     
157     for (Vector<String>::iterator table = tables.begin(); table != tables.end(); ++table ) {
158         if (*table == "sqlite_sequence")
159             continue;
160         if (!executeCommand("DROP TABLE " + *table))
161             LOG(SQLDatabase, "Unable to drop table %s", (*table).ascii().data());
162     }
163 }
164
165 void SQLiteDatabase::runVacuumCommand()
166 {
167     if (!executeCommand("VACUUM;"))
168         LOG(SQLDatabase, "Unable to vacuum database - %s", lastErrorMsg());
169 }
170
171 int64_t SQLiteDatabase::lastInsertRowID()
172 {
173     if (!m_db)
174         return 0;
175     return sqlite3_last_insert_rowid(m_db);
176 }
177
178 int SQLiteDatabase::lastChanges()
179 {
180     if (!m_db)
181         return 0;
182     return sqlite3_changes(m_db);
183 }
184
185 int SQLiteDatabase::lastError()
186 {
187     return m_db ? sqlite3_errcode(m_db) : SQLITE_ERROR;
188 }
189
190 const char* SQLiteDatabase::lastErrorMsg()
191
192     return sqlite3_errmsg(m_db);
193 }
194
195 int SQLiteDatabase::authorizerFunction(void* userData, int actionCode, const char* parameter1, const char* parameter2, const char* /*databaseName*/, const char* /*trigger_or_view*/)
196 {
197     SQLiteAuthorizer* auth = static_cast<SQLiteAuthorizer*>(userData);
198     ASSERT(auth);
199
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);
217         case SQLITE_DELETE:
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);
235         case SQLITE_INSERT:
236             return auth->allowInsert(parameter1);
237         case SQLITE_PRAGMA:
238             return auth->allowPragma(parameter1, parameter2);
239         case SQLITE_READ:
240             return auth->allowRead(parameter1, parameter2);
241         case SQLITE_SELECT:
242             return auth->allowSelect();
243         case SQLITE_TRANSACTION:
244             return auth->allowTransaction();
245         case SQLITE_UPDATE:
246             return auth->allowUpdate(parameter1, parameter2);
247         case SQLITE_ATTACH:
248             return auth->allowAttach(parameter1);
249         case SQLITE_DETACH:
250             return auth->allowDetach(parameter1);
251         case SQLITE_ALTER_TABLE:
252             return auth->allowAlterTable(parameter1, parameter2);
253         case SQLITE_REINDEX:
254             return auth->allowReindex(parameter1);
255 #if SQLITE_VERSION_NUMBER >= 3003013 
256         case SQLITE_ANALYZE:
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);
264 #endif
265         default:
266             ASSERT_NOT_REACHED();
267             return SQLAuthDeny;
268     }
269 }
270
271 void SQLiteDatabase::setAuthorizer(PassRefPtr<SQLiteAuthorizer> auth)
272 {
273     if (!m_db) {
274         LOG_ERROR("Attempt to set an authorizer on a non-open SQL database");
275         ASSERT_NOT_REACHED();
276         return;
277     }
278
279     MutexLocker locker(m_authorizerLock);
280
281     m_authorizer = auth;
282     if (m_authorizer)
283         sqlite3_set_authorizer(m_db, SQLiteDatabase::authorizerFunction, m_authorizer.get());
284     else
285         sqlite3_set_authorizer(m_db, NULL, 0);
286 }
287
288 void SQLiteDatabase::lock()
289 {
290     m_lockingMutex.lock();
291 }
292
293 void SQLiteDatabase::unlock()
294 {
295     m_lockingMutex.unlock();
296 }
297
298 } // namespace WebCore
299
300