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 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 53 SQLiteStatement::~SQLiteStatement() 54 { 55 finalize(); 56 } 57 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 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 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 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 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 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 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 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 184 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 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 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 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 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 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 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