1 /*
2 * Copyright (C) 2006, 2007, 2008 Apple 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 "modules/webdatabase/sqlite/SQLiteStatement.h"
28
29 #include <sqlite3.h>
30 #include "platform/Logging.h"
31 #include "modules/webdatabase/sqlite/SQLValue.h"
32 #include "wtf/Assertions.h"
33 #include "wtf/text/CString.h"
34
35 // SQLite 3.6.16 makes sqlite3_prepare_v2 automatically retry preparing the statement
36 // once if the database scheme has changed. We rely on this behavior.
37 #if SQLITE_VERSION_NUMBER < 3006016
38 #error SQLite version 3.6.16 or newer is required
39 #endif
40
41 namespace WebCore {
42
SQLiteStatement(SQLiteDatabase & db,const String & sql)43 SQLiteStatement::SQLiteStatement(SQLiteDatabase& db, const String& sql)
44 : m_database(db)
45 , m_query(sql)
46 , m_statement(0)
47 #ifndef NDEBUG
48 , m_isPrepared(false)
49 #endif
50 {
51 }
52
~SQLiteStatement()53 SQLiteStatement::~SQLiteStatement()
54 {
55 finalize();
56 }
57
prepare()58 int SQLiteStatement::prepare()
59 {
60 ASSERT(!m_isPrepared);
61
62 CString query = m_query.stripWhiteSpace().utf8();
63
64 ThreadState::SafePointScope scope(ThreadState::HeapPointersOnStack);
65 MutexLocker databaseLock(m_database.databaseMutex());
66 if (m_database.isInterrupted())
67 return SQLITE_INTERRUPT;
68
69 WTF_LOG(SQLDatabase, "SQL - prepare - %s", query.data());
70
71 // Pass the length of the string including the null character to sqlite3_prepare_v2;
72 // this lets SQLite avoid an extra string copy.
73 size_t lengthIncludingNullCharacter = query.length() + 1;
74
75 const char* tail = 0;
76 int error = sqlite3_prepare_v2(m_database.sqlite3Handle(), query.data(), lengthIncludingNullCharacter, &m_statement, &tail);
77
78 if (error != SQLITE_OK)
79 WTF_LOG(SQLDatabase, "sqlite3_prepare16 failed (%i)\n%s\n%s", error, query.data(), sqlite3_errmsg(m_database.sqlite3Handle()));
80 else if (tail && *tail)
81 error = SQLITE_ERROR;
82
83 #ifndef NDEBUG
84 m_isPrepared = error == SQLITE_OK;
85 #endif
86 return error;
87 }
88
step()89 int SQLiteStatement::step()
90 {
91 ThreadState::SafePointScope scope(ThreadState::HeapPointersOnStack);
92 MutexLocker databaseLock(m_database.databaseMutex());
93 if (m_database.isInterrupted())
94 return SQLITE_INTERRUPT;
95 //ASSERT(m_isPrepared);
96
97 if (!m_statement)
98 return SQLITE_OK;
99
100 // The database needs to update its last changes count before each statement
101 // in order to compute properly the lastChanges() return value.
102 m_database.updateLastChangesCount();
103
104 WTF_LOG(SQLDatabase, "SQL - step - %s", m_query.ascii().data());
105 int error = sqlite3_step(m_statement);
106 if (error != SQLITE_DONE && error != SQLITE_ROW) {
107 WTF_LOG(SQLDatabase, "sqlite3_step failed (%i)\nQuery - %s\nError - %s",
108 error, m_query.ascii().data(), sqlite3_errmsg(m_database.sqlite3Handle()));
109 }
110
111 return error;
112 }
113
finalize()114 int SQLiteStatement::finalize()
115 {
116 #ifndef NDEBUG
117 m_isPrepared = false;
118 #endif
119 if (!m_statement)
120 return SQLITE_OK;
121 WTF_LOG(SQLDatabase, "SQL - finalize - %s", m_query.ascii().data());
122 int result = sqlite3_finalize(m_statement);
123 m_statement = 0;
124 return result;
125 }
126
executeCommand()127 bool SQLiteStatement::executeCommand()
128 {
129 if (!m_statement && prepare() != SQLITE_OK)
130 return false;
131 ASSERT(m_isPrepared);
132 if (step() != SQLITE_DONE) {
133 finalize();
134 return false;
135 }
136 finalize();
137 return true;
138 }
139
bindText(int index,const String & text)140 int SQLiteStatement::bindText(int index, const String& text)
141 {
142 ASSERT(m_isPrepared);
143 ASSERT(index > 0);
144 ASSERT(static_cast<unsigned>(index) <= bindParameterCount());
145
146 // SQLite treats uses zero pointers to represent null strings, which means we need to make sure to map null WTFStrings to zero pointers.
147 ASSERT(!String().charactersWithNullTermination().data());
148 return sqlite3_bind_text16(m_statement, index, text.charactersWithNullTermination().data(), sizeof(UChar) * text.length(), SQLITE_TRANSIENT);
149 }
150
bindDouble(int index,double number)151 int SQLiteStatement::bindDouble(int index, double number)
152 {
153 ASSERT(m_isPrepared);
154 ASSERT(index > 0);
155 ASSERT(static_cast<unsigned>(index) <= bindParameterCount());
156
157 return sqlite3_bind_double(m_statement, index, number);
158 }
159
bindNull(int index)160 int SQLiteStatement::bindNull(int index)
161 {
162 ASSERT(m_isPrepared);
163 ASSERT(index > 0);
164 ASSERT(static_cast<unsigned>(index) <= bindParameterCount());
165
166 return sqlite3_bind_null(m_statement, index);
167 }
168
bindValue(int index,const SQLValue & value)169 int SQLiteStatement::bindValue(int index, const SQLValue& value)
170 {
171 switch (value.type()) {
172 case SQLValue::StringValue:
173 return bindText(index, value.string());
174 case SQLValue::NumberValue:
175 return bindDouble(index, value.number());
176 case SQLValue::NullValue:
177 return bindNull(index);
178 }
179
180 ASSERT_NOT_REACHED();
181 return SQLITE_ERROR;
182 }
183
bindParameterCount() const184 unsigned SQLiteStatement::bindParameterCount() const
185 {
186 ASSERT(m_isPrepared);
187 if (!m_statement)
188 return 0;
189 return sqlite3_bind_parameter_count(m_statement);
190 }
191
columnCount()192 int SQLiteStatement::columnCount()
193 {
194 ASSERT(m_isPrepared);
195 if (!m_statement)
196 return 0;
197 return sqlite3_data_count(m_statement);
198 }
199
getColumnName(int col)200 String SQLiteStatement::getColumnName(int col)
201 {
202 ASSERT(col >= 0);
203 if (!m_statement)
204 if (prepareAndStep() != SQLITE_ROW)
205 return String();
206 if (columnCount() <= col)
207 return String();
208 return String(reinterpret_cast<const UChar*>(sqlite3_column_name16(m_statement, col)));
209 }
210
getColumnValue(int col)211 SQLValue SQLiteStatement::getColumnValue(int col)
212 {
213 ASSERT(col >= 0);
214 if (!m_statement)
215 if (prepareAndStep() != SQLITE_ROW)
216 return SQLValue();
217 if (columnCount() <= col)
218 return SQLValue();
219
220 // SQLite is typed per value. optional column types are
221 // "(mostly) ignored"
222 sqlite3_value* value = sqlite3_column_value(m_statement, col);
223 switch (sqlite3_value_type(value)) {
224 case SQLITE_INTEGER: // SQLValue and JS don't represent integers, so use FLOAT -case
225 case SQLITE_FLOAT:
226 return SQLValue(sqlite3_value_double(value));
227 case SQLITE_BLOB: // SQLValue and JS don't represent blobs, so use TEXT -case
228 case SQLITE_TEXT: {
229 const UChar* string = reinterpret_cast<const UChar*>(sqlite3_value_text16(value));
230 unsigned length = WTF::lengthOfNullTerminatedString(string);
231 return SQLValue(StringImpl::create8BitIfPossible(string, length));
232 }
233 case SQLITE_NULL:
234 return SQLValue();
235 default:
236 break;
237 }
238 ASSERT_NOT_REACHED();
239 return SQLValue();
240 }
241
getColumnText(int col)242 String SQLiteStatement::getColumnText(int col)
243 {
244 ASSERT(col >= 0);
245 if (!m_statement)
246 if (prepareAndStep() != SQLITE_ROW)
247 return String();
248 if (columnCount() <= col)
249 return String();
250 const UChar* string = reinterpret_cast<const UChar*>(sqlite3_column_text16(m_statement, col));
251 return StringImpl::create8BitIfPossible(string, sqlite3_column_bytes16(m_statement, col) / sizeof(UChar));
252 }
253
getColumnInt(int col)254 int SQLiteStatement::getColumnInt(int col)
255 {
256 ASSERT(col >= 0);
257 if (!m_statement)
258 if (prepareAndStep() != SQLITE_ROW)
259 return 0;
260 if (columnCount() <= col)
261 return 0;
262 return sqlite3_column_int(m_statement, col);
263 }
264
getColumnInt64(int col)265 int64_t SQLiteStatement::getColumnInt64(int col)
266 {
267 ASSERT(col >= 0);
268 if (!m_statement)
269 if (prepareAndStep() != SQLITE_ROW)
270 return 0;
271 if (columnCount() <= col)
272 return 0;
273 return sqlite3_column_int64(m_statement, col);
274 }
275
276 } // namespace WebCore
277