Home | History | Annotate | Download | only in sqlite
      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