Reviewed by Hyatt
[WebKit-https.git] / WebCore / loader / icon / SQLDatabase.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 "SQLDatabase.h"
28
29 #include "SQLStatement.h"
30
31 #include "Logging.h"
32
33 namespace WebCore {
34
35 SQLDatabase::SQLDatabase()
36     : m_db(0)
37 {
38
39 }
40
41 bool SQLDatabase::open(const String& filename)
42 {
43     close();
44     
45     //SQLite expects a null terminator on its UTF16 strings
46     m_path = filename;
47     m_path.append(UChar(0));
48     
49     m_lastError = sqlite3_open16(m_path.characters(), &m_db);
50     if (m_lastError != SQLITE_OK) {
51         LOG_ERROR("SQLite database failed to load from %s\nCause - %s", filename.ascii().data(),
52             sqlite3_errmsg(m_db));
53         sqlite3_close(m_db);
54         m_db = 0;
55     }
56     if (!SQLStatement(*this, "PRAGMA temp_store = MEMORY;").executeCommand())
57         LOG_ERROR("SQLite database could not set temp_store to memory");
58
59     return isOpen();
60 }
61
62 void SQLDatabase::close()
63 {
64     if (m_db) {
65         sqlite3_close(m_db);
66         m_path.truncate(0);
67         m_db = 0;
68     }
69 }
70
71 void SQLDatabase::setFullsync(bool fsync) 
72 {
73     if (fsync) 
74         executeCommand("PRAGMA fullfsync = 1;");
75     else
76         executeCommand("PRAGMA fullfsync = 0;");
77 }
78
79 void SQLDatabase::setSynchronous(SynchronousPragma sync)
80 {
81     executeCommand(String::sprintf("PRAGMA synchronous = %i", sync));
82 }
83
84 void SQLDatabase::setBusyTimeout(int ms)
85 {
86     if (m_db)
87         sqlite3_busy_timeout(m_db, ms);
88     else
89         LOG(IconDatabase, "BusyTimeout set on non-open database");
90 }
91
92 void SQLDatabase::setBusyHandler(int(*handler)(void*, int))
93 {
94     if (m_db)
95         sqlite3_busy_handler(m_db, handler, NULL);
96     else
97         LOG(IconDatabase, "Busy handler set on non-open database");
98 }
99
100 bool SQLDatabase::executeCommand(const String& sql)
101 {
102     return SQLStatement(*this, sql).executeCommand();
103 }
104
105 bool SQLDatabase::returnsAtLeastOneResult(const String& sql)
106 {
107     return SQLStatement(*this, sql).returnsAtLeastOneResult();
108 }
109
110 bool SQLDatabase::tableExists(const String& tablename)
111 {
112     if (!isOpen())
113         return false;
114         
115     String statement = "SELECT name FROM sqlite_master WHERE type = 'table' AND name = '" + tablename + "';";
116     
117     SQLStatement sql(*this, statement);
118     sql.prepare();
119     return sql.step() == SQLITE_ROW;
120 }
121
122 void SQLDatabase::clearAllTables()
123 {
124     String query = "SELECT name FROM sqlite_master WHERE type='table';";
125     Vector<String> tables;
126     if (!SQLStatement(*this, query).returnTextResults16(0, tables)) {
127         LOG(IconDatabase, "Unable to retrieve list of tables from database");
128         return;
129     }
130     
131     for (Vector<String>::iterator table = tables.begin(); table != tables.end(); ++table ) {
132         if (*table == "sqlite_sequence")
133             continue;
134         if (!executeCommand("DROP TABLE " + *table))
135             LOG(IconDatabase, "Unable to drop table %s", (*table).ascii().data());
136     }
137 }
138
139 void SQLDatabase::runVacuumCommand()
140 {
141     if (!executeCommand("VACUUM;"))
142         LOG(IconDatabase, "Unable to vacuum database - %s", lastErrorMsg());
143 }
144
145 int64_t SQLDatabase::lastInsertRowID()
146 {
147     if (!m_db)
148         return 0;
149     return sqlite3_last_insert_rowid(m_db);
150 }
151
152 int SQLDatabase::lastChanges()
153 {
154     if (!m_db)
155         return 0;
156     return sqlite3_changes(m_db);
157 }
158
159 } // namespace WebCore
160
161