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 "SQLiteStatement.h"
28
29 #include "Logging.h"
30 #include "SQLValue.h"
31 #include <sqlite3.h>
32 #include <wtf/Assertions.h>
33
34 namespace WebCore {
35
36 #if SQLITE_VERSION_NUMBER < 3003009
37
38 // FIXME: This overload helps us compile with older versions of SQLite 3, but things like quotas will not work.
sqlite3_prepare16_v2(sqlite3 * db,const void * zSql,int nBytes,sqlite3_stmt ** ppStmt,const void ** pzTail)39 static inline int sqlite3_prepare16_v2(sqlite3* db, const void* zSql, int nBytes, sqlite3_stmt** ppStmt, const void** pzTail)
40 {
41 return sqlite3_prepare16(db, zSql, nBytes, ppStmt, pzTail);
42 }
43
44 #endif
45
SQLiteStatement(SQLiteDatabase & db,const String & sql)46 SQLiteStatement::SQLiteStatement(SQLiteDatabase& db, const String& sql)
47 : m_database(db)
48 , m_query(sql)
49 , m_statement(0)
50 #ifndef NDEBUG
51 , m_isPrepared(false)
52 #endif
53 {
54 }
55
~SQLiteStatement()56 SQLiteStatement::~SQLiteStatement()
57 {
58 finalize();
59 }
60
prepare()61 int SQLiteStatement::prepare()
62 {
63 ASSERT(!m_isPrepared);
64 const void* tail;
65 LOG(SQLDatabase, "SQL - prepare - %s", m_query.ascii().data());
66 int error = sqlite3_prepare16_v2(m_database.sqlite3Handle(), m_query.charactersWithNullTermination(), -1, &m_statement, &tail);
67 if (error != SQLITE_OK)
68 LOG(SQLDatabase, "sqlite3_prepare16 failed (%i)\n%s\n%s", error, m_query.ascii().data(), sqlite3_errmsg(m_database.sqlite3Handle()));
69 #ifndef NDEBUG
70 m_isPrepared = error == SQLITE_OK;
71 #endif
72 return error;
73 }
74
step()75 int SQLiteStatement::step()
76 {
77 ASSERT(m_isPrepared);
78 if (!m_statement)
79 return SQLITE_OK;
80 LOG(SQLDatabase, "SQL - step - %s", m_query.ascii().data());
81 int error = sqlite3_step(m_statement);
82 if (error != SQLITE_DONE && error != SQLITE_ROW) {
83 LOG(SQLDatabase, "sqlite3_step failed (%i)\nQuery - %s\nError - %s",
84 error, m_query.ascii().data(), sqlite3_errmsg(m_database.sqlite3Handle()));
85 }
86 return error;
87 }
88
finalize()89 int SQLiteStatement::finalize()
90 {
91 #ifndef NDEBUG
92 m_isPrepared = false;
93 #endif
94 if (!m_statement)
95 return SQLITE_OK;
96 LOG(SQLDatabase, "SQL - finalize - %s", m_query.ascii().data());
97 int result = sqlite3_finalize(m_statement);
98 m_statement = 0;
99 return result;
100 }
101
reset()102 int SQLiteStatement::reset()
103 {
104 ASSERT(m_isPrepared);
105 if (!m_statement)
106 return SQLITE_OK;
107 LOG(SQLDatabase, "SQL - reset - %s", m_query.ascii().data());
108 return sqlite3_reset(m_statement);
109 }
110
executeCommand()111 bool SQLiteStatement::executeCommand()
112 {
113 if (!m_statement && prepare() != SQLITE_OK)
114 return false;
115 ASSERT(m_isPrepared);
116 if (step() != SQLITE_DONE) {
117 finalize();
118 return false;
119 }
120 finalize();
121 return true;
122 }
123
returnsAtLeastOneResult()124 bool SQLiteStatement::returnsAtLeastOneResult()
125 {
126 if (!m_statement && prepare() != SQLITE_OK)
127 return false;
128 ASSERT(m_isPrepared);
129 if (step() != SQLITE_ROW) {
130 finalize();
131 return false;
132 }
133 finalize();
134 return true;
135
136 }
137
bindBlob(int index,const void * blob,int size)138 int SQLiteStatement::bindBlob(int index, const void* blob, int size)
139 {
140 ASSERT(m_isPrepared);
141 ASSERT(index > 0);
142 ASSERT(static_cast<unsigned>(index) <= bindParameterCount());
143 ASSERT(blob);
144 ASSERT(size >= 0);
145
146 if (!m_statement)
147 return SQLITE_ERROR;
148
149 return sqlite3_bind_blob(m_statement, index, blob, size, SQLITE_TRANSIENT);
150 }
151
bindText(int index,const String & text)152 int SQLiteStatement::bindText(int index, const String& text)
153 {
154 ASSERT(m_isPrepared);
155 ASSERT(index > 0);
156 ASSERT(static_cast<unsigned>(index) <= bindParameterCount());
157
158 // String::characters() returns 0 for the empty string, which SQLite
159 // treats as a null, so we supply a non-null pointer for that case.
160 UChar anyCharacter = 0;
161 const UChar* characters;
162 if (text.isEmpty() && !text.isNull())
163 characters = &anyCharacter;
164 else
165 characters = text.characters();
166
167 return sqlite3_bind_text16(m_statement, index, characters, sizeof(UChar) * text.length(), SQLITE_TRANSIENT);
168 }
169
170
bindInt64(int index,int64_t integer)171 int SQLiteStatement::bindInt64(int index, int64_t integer)
172 {
173 ASSERT(m_isPrepared);
174 ASSERT(index > 0);
175 ASSERT(static_cast<unsigned>(index) <= bindParameterCount());
176
177 return sqlite3_bind_int64(m_statement, index, integer);
178 }
179
bindDouble(int index,double number)180 int SQLiteStatement::bindDouble(int index, double number)
181 {
182 ASSERT(m_isPrepared);
183 ASSERT(index > 0);
184 ASSERT(static_cast<unsigned>(index) <= bindParameterCount());
185
186 return sqlite3_bind_double(m_statement, index, number);
187 }
188
bindNull(int index)189 int SQLiteStatement::bindNull(int index)
190 {
191 ASSERT(m_isPrepared);
192 ASSERT(index > 0);
193 ASSERT(static_cast<unsigned>(index) <= bindParameterCount());
194
195 return sqlite3_bind_null(m_statement, index);
196 }
197
bindValue(int index,const SQLValue & value)198 int SQLiteStatement::bindValue(int index, const SQLValue& value)
199 {
200 switch (value.type()) {
201 case SQLValue::StringValue:
202 return bindText(index, value.string());
203 case SQLValue::NumberValue:
204 return bindDouble(index, value.number());
205 case SQLValue::NullValue:
206 return bindNull(index);
207 }
208
209 ASSERT_NOT_REACHED();
210 return SQLITE_ERROR;
211 }
212
bindParameterCount() const213 unsigned SQLiteStatement::bindParameterCount() const
214 {
215 ASSERT(m_isPrepared);
216 if (!m_statement)
217 return 0;
218 return sqlite3_bind_parameter_count(m_statement);
219 }
220
columnCount()221 int SQLiteStatement::columnCount()
222 {
223 ASSERT(m_isPrepared);
224 if (!m_statement)
225 return 0;
226 return sqlite3_data_count(m_statement);
227 }
228
getColumnName(int col)229 String SQLiteStatement::getColumnName(int col)
230 {
231 ASSERT(col >= 0);
232 if (!m_statement)
233 if (prepareAndStep() != SQLITE_ROW)
234 return String();
235 if (columnCount() <= col)
236 return String();
237 return String(reinterpret_cast<const UChar*>(sqlite3_column_name16(m_statement, col)));
238 }
239
getColumnValue(int col)240 SQLValue SQLiteStatement::getColumnValue(int col)
241 {
242 ASSERT(col >= 0);
243 if (!m_statement)
244 if (prepareAndStep() != SQLITE_ROW)
245 return SQLValue();
246 if (columnCount() <= col)
247 return SQLValue();
248
249 // SQLite is typed per value. optional column types are
250 // "(mostly) ignored"
251 sqlite3_value* value = sqlite3_column_value(m_statement, col);
252 switch (sqlite3_value_type(value)) {
253 case SQLITE_INTEGER: // SQLValue and JS don't represent integers, so use FLOAT -case
254 case SQLITE_FLOAT:
255 return SQLValue(sqlite3_value_double(value));
256 case SQLITE_BLOB: // SQLValue and JS don't represent blobs, so use TEXT -case
257 case SQLITE_TEXT:
258 return SQLValue(String(reinterpret_cast<const UChar*>(sqlite3_value_text16(value))));
259 case SQLITE_NULL:
260 return SQLValue();
261 default:
262 break;
263 }
264 ASSERT_NOT_REACHED();
265 return SQLValue();
266 }
267
getColumnText(int col)268 String SQLiteStatement::getColumnText(int col)
269 {
270 ASSERT(col >= 0);
271 if (!m_statement)
272 if (prepareAndStep() != SQLITE_ROW)
273 return String();
274 if (columnCount() <= col)
275 return String();
276 return String(reinterpret_cast<const UChar*>(sqlite3_column_text16(m_statement, col)));
277 }
278
getColumnDouble(int col)279 double SQLiteStatement::getColumnDouble(int col)
280 {
281 ASSERT(col >= 0);
282 if (!m_statement)
283 if (prepareAndStep() != SQLITE_ROW)
284 return 0.0;
285 if (columnCount() <= col)
286 return 0.0;
287 return sqlite3_column_double(m_statement, col);
288 }
289
getColumnInt(int col)290 int SQLiteStatement::getColumnInt(int col)
291 {
292 ASSERT(col >= 0);
293 if (!m_statement)
294 if (prepareAndStep() != SQLITE_ROW)
295 return 0;
296 if (columnCount() <= col)
297 return 0;
298 return sqlite3_column_int(m_statement, col);
299 }
300
getColumnInt64(int col)301 int64_t SQLiteStatement::getColumnInt64(int col)
302 {
303 ASSERT(col >= 0);
304 if (!m_statement)
305 if (prepareAndStep() != SQLITE_ROW)
306 return 0;
307 if (columnCount() <= col)
308 return 0;
309 return sqlite3_column_int64(m_statement, col);
310 }
311
getColumnBlobAsVector(int col,Vector<char> & result)312 void SQLiteStatement::getColumnBlobAsVector(int col, Vector<char>& result)
313 {
314 ASSERT(col >= 0);
315
316 if (!m_statement && prepareAndStep() != SQLITE_ROW) {
317 result.clear();
318 return;
319 }
320
321 if (columnCount() <= col) {
322 result.clear();
323 return;
324 }
325
326 const void* blob = sqlite3_column_blob(m_statement, col);
327 if (!blob) {
328 result.clear();
329 return;
330 }
331
332 int size = sqlite3_column_bytes(m_statement, col);
333 result.resize((size_t)size);
334 for (int i = 0; i < size; ++i)
335 result[i] = ((const unsigned char*)blob)[i];
336 }
337
getColumnBlob(int col,int & size)338 const void* SQLiteStatement::getColumnBlob(int col, int& size)
339 {
340 ASSERT(col >= 0);
341
342 size = 0;
343
344 if (finalize() != SQLITE_OK)
345 LOG(SQLDatabase, "Finalize failed");
346 if (prepare() != SQLITE_OK) {
347 LOG(SQLDatabase, "Prepare failed");
348 return 0;
349 }
350 if (step() != SQLITE_ROW) {
351 LOG(SQLDatabase, "Step wasn't a row");
352 return 0;
353 }
354
355 if (columnCount() <= col)
356 return 0;
357
358 const void* blob = sqlite3_column_blob(m_statement, col);
359 if (!blob)
360 return 0;
361
362 size = sqlite3_column_bytes(m_statement, col);
363 return blob;
364 }
365
returnTextResults(int col,Vector<String> & v)366 bool SQLiteStatement::returnTextResults(int col, Vector<String>& v)
367 {
368 ASSERT(col >= 0);
369
370 v.clear();
371
372 if (m_statement)
373 finalize();
374 if (prepare() != SQLITE_OK)
375 return false;
376
377 while (step() == SQLITE_ROW)
378 v.append(getColumnText(col));
379 bool result = true;
380 if (m_database.lastError() != SQLITE_DONE) {
381 result = false;
382 LOG(SQLDatabase, "Error reading results from database query %s", m_query.ascii().data());
383 }
384 finalize();
385 return result;
386 }
387
returnIntResults(int col,Vector<int> & v)388 bool SQLiteStatement::returnIntResults(int col, Vector<int>& v)
389 {
390 v.clear();
391
392 if (m_statement)
393 finalize();
394 if (prepare() != SQLITE_OK)
395 return false;
396
397 while (step() == SQLITE_ROW)
398 v.append(getColumnInt(col));
399 bool result = true;
400 if (m_database.lastError() != SQLITE_DONE) {
401 result = false;
402 LOG(SQLDatabase, "Error reading results from database query %s", m_query.ascii().data());
403 }
404 finalize();
405 return result;
406 }
407
returnInt64Results(int col,Vector<int64_t> & v)408 bool SQLiteStatement::returnInt64Results(int col, Vector<int64_t>& v)
409 {
410 v.clear();
411
412 if (m_statement)
413 finalize();
414 if (prepare() != SQLITE_OK)
415 return false;
416
417 while (step() == SQLITE_ROW)
418 v.append(getColumnInt64(col));
419 bool result = true;
420 if (m_database.lastError() != SQLITE_DONE) {
421 result = false;
422 LOG(SQLDatabase, "Error reading results from database query %s", m_query.ascii().data());
423 }
424 finalize();
425 return result;
426 }
427
returnDoubleResults(int col,Vector<double> & v)428 bool SQLiteStatement::returnDoubleResults(int col, Vector<double>& v)
429 {
430 v.clear();
431
432 if (m_statement)
433 finalize();
434 if (prepare() != SQLITE_OK)
435 return false;
436
437 while (step() == SQLITE_ROW)
438 v.append(getColumnDouble(col));
439 bool result = true;
440 if (m_database.lastError() != SQLITE_DONE) {
441 result = false;
442 LOG(SQLDatabase, "Error reading results from database query %s", m_query.ascii().data());
443 }
444 finalize();
445 return result;
446 }
447
isExpired()448 bool SQLiteStatement::isExpired()
449 {
450 return !m_statement || sqlite3_expired(m_statement);
451 }
452
453 } // namespace WebCore
454