Home | History | Annotate | Download | only in sql
      1 // Copyright (c) 2010 The Chromium Authors. All rights reserved.
      2 // Use of this source code is governed by a BSD-style license that can be
      3 // found in the LICENSE file.
      4 
      5 #include "app/sql/statement.h"
      6 
      7 #include "base/logging.h"
      8 #include "base/utf_string_conversions.h"
      9 #ifdef ANDROID
     10 #include "sqlite3.h"
     11 #else
     12 #include "third_party/sqlite/sqlite3.h"
     13 #endif
     14 
     15 namespace sql {
     16 
     17 // This empty constructor initializes our reference with an empty one so that
     18 // we don't have to NULL-check the ref_ to see if the statement is valid: we
     19 // only have to check the ref's validity bit.
     20 Statement::Statement()
     21     : ref_(new Connection::StatementRef),
     22       succeeded_(false) {
     23 }
     24 
     25 Statement::Statement(scoped_refptr<Connection::StatementRef> ref)
     26     : ref_(ref),
     27       succeeded_(false) {
     28 }
     29 
     30 Statement::~Statement() {
     31   // Free the resources associated with this statement. We assume there's only
     32   // one statement active for a given sqlite3_stmt at any time, so this won't
     33   // mess with anything.
     34   Reset();
     35 }
     36 
     37 void Statement::Assign(scoped_refptr<Connection::StatementRef> ref) {
     38   Reset();
     39   ref_ = ref;
     40 }
     41 
     42 bool Statement::Run() {
     43   if (!is_valid())
     44     return false;
     45   return CheckError(sqlite3_step(ref_->stmt())) == SQLITE_DONE;
     46 }
     47 
     48 bool Statement::Step() {
     49   if (!is_valid())
     50     return false;
     51   return CheckError(sqlite3_step(ref_->stmt())) == SQLITE_ROW;
     52 }
     53 
     54 void Statement::Reset() {
     55   if (is_valid()) {
     56     // We don't call CheckError() here because sqlite3_reset() returns
     57     // the last error that Step() caused thereby generating a second
     58     // spurious error callback.
     59     sqlite3_clear_bindings(ref_->stmt());
     60     sqlite3_reset(ref_->stmt());
     61   }
     62   succeeded_ = false;
     63 }
     64 
     65 bool Statement::Succeeded() const {
     66   if (!is_valid())
     67     return false;
     68   return succeeded_;
     69 }
     70 
     71 bool Statement::BindNull(int col) {
     72   if (is_valid()) {
     73     int err = CheckError(sqlite3_bind_null(ref_->stmt(), col + 1));
     74     return err == SQLITE_OK;
     75   }
     76   return false;
     77 }
     78 
     79 bool Statement::BindBool(int col, bool val) {
     80   return BindInt(col, val ? 1 : 0);
     81 }
     82 
     83 bool Statement::BindInt(int col, int val) {
     84   if (is_valid()) {
     85     int err = CheckError(sqlite3_bind_int(ref_->stmt(), col + 1, val));
     86     return err == SQLITE_OK;
     87   }
     88   return false;
     89 }
     90 
     91 bool Statement::BindInt64(int col, int64 val) {
     92   if (is_valid()) {
     93     int err = CheckError(sqlite3_bind_int64(ref_->stmt(), col + 1, val));
     94     return err == SQLITE_OK;
     95   }
     96   return false;
     97 }
     98 
     99 bool Statement::BindDouble(int col, double val) {
    100   if (is_valid()) {
    101     int err = CheckError(sqlite3_bind_double(ref_->stmt(), col + 1, val));
    102     return err == SQLITE_OK;
    103   }
    104   return false;
    105 }
    106 
    107 bool Statement::BindCString(int col, const char* val) {
    108   if (is_valid()) {
    109     int err = CheckError(sqlite3_bind_text(ref_->stmt(), col + 1, val, -1,
    110                          SQLITE_TRANSIENT));
    111     return err == SQLITE_OK;
    112   }
    113   return false;
    114 }
    115 
    116 bool Statement::BindString(int col, const std::string& val) {
    117   if (is_valid()) {
    118     int err = CheckError(sqlite3_bind_text(ref_->stmt(), col + 1, val.data(),
    119                                            val.size(), SQLITE_TRANSIENT));
    120     return err == SQLITE_OK;
    121   }
    122   return false;
    123 }
    124 
    125 bool Statement::BindString16(int col, const string16& value) {
    126   return BindString(col, UTF16ToUTF8(value));
    127 }
    128 
    129 bool Statement::BindBlob(int col, const void* val, int val_len) {
    130   if (is_valid()) {
    131     int err = CheckError(sqlite3_bind_blob(ref_->stmt(), col + 1,
    132                          val, val_len, SQLITE_TRANSIENT));
    133     return err == SQLITE_OK;
    134   }
    135   return false;
    136 }
    137 
    138 int Statement::ColumnCount() const {
    139   if (!is_valid()) {
    140     NOTREACHED();
    141     return 0;
    142   }
    143   return sqlite3_column_count(ref_->stmt());
    144 }
    145 
    146 ColType Statement::ColumnType(int col) const {
    147   // Verify that our enum matches sqlite's values.
    148   COMPILE_ASSERT(COLUMN_TYPE_INTEGER == SQLITE_INTEGER, integer_no_match);
    149   COMPILE_ASSERT(COLUMN_TYPE_FLOAT == SQLITE_FLOAT, float_no_match);
    150   COMPILE_ASSERT(COLUMN_TYPE_TEXT == SQLITE_TEXT, integer_no_match);
    151   COMPILE_ASSERT(COLUMN_TYPE_BLOB == SQLITE_BLOB, blob_no_match);
    152   COMPILE_ASSERT(COLUMN_TYPE_NULL == SQLITE_NULL, null_no_match);
    153 
    154   return static_cast<ColType>(sqlite3_column_type(ref_->stmt(), col));
    155 }
    156 
    157 bool Statement::ColumnBool(int col) const {
    158   return !!ColumnInt(col);
    159 }
    160 
    161 int Statement::ColumnInt(int col) const {
    162   if (!is_valid()) {
    163     NOTREACHED();
    164     return 0;
    165   }
    166   return sqlite3_column_int(ref_->stmt(), col);
    167 }
    168 
    169 int64 Statement::ColumnInt64(int col) const {
    170   if (!is_valid()) {
    171     NOTREACHED();
    172     return 0;
    173   }
    174   return sqlite3_column_int64(ref_->stmt(), col);
    175 }
    176 
    177 double Statement::ColumnDouble(int col) const {
    178   if (!is_valid()) {
    179     NOTREACHED();
    180     return 0;
    181   }
    182   return sqlite3_column_double(ref_->stmt(), col);
    183 }
    184 
    185 std::string Statement::ColumnString(int col) const {
    186   if (!is_valid()) {
    187     NOTREACHED();
    188     return "";
    189   }
    190   const char* str = reinterpret_cast<const char*>(
    191       sqlite3_column_text(ref_->stmt(), col));
    192   int len = sqlite3_column_bytes(ref_->stmt(), col);
    193 
    194   std::string result;
    195   if (str && len > 0)
    196     result.assign(str, len);
    197   return result;
    198 }
    199 
    200 string16 Statement::ColumnString16(int col) const {
    201   if (!is_valid()) {
    202     NOTREACHED();
    203     return string16();
    204   }
    205   std::string s = ColumnString(col);
    206   return !s.empty() ? UTF8ToUTF16(s) : string16();
    207 }
    208 
    209 int Statement::ColumnByteLength(int col) const {
    210   if (!is_valid()) {
    211     NOTREACHED();
    212     return 0;
    213   }
    214   return sqlite3_column_bytes(ref_->stmt(), col);
    215 }
    216 
    217 const void* Statement::ColumnBlob(int col) const {
    218   if (!is_valid()) {
    219     NOTREACHED();
    220     return NULL;
    221   }
    222 
    223   return sqlite3_column_blob(ref_->stmt(), col);
    224 }
    225 
    226 bool Statement::ColumnBlobAsString(int col, std::string* blob) {
    227   if (!is_valid()) {
    228     NOTREACHED();
    229     return false;
    230   }
    231   const void* p = ColumnBlob(col);
    232   size_t len = ColumnByteLength(col);
    233   blob->resize(len);
    234   if (blob->size() != len) {
    235     return false;
    236   }
    237   blob->assign(reinterpret_cast<const char*>(p), len);
    238   return true;
    239 }
    240 
    241 void Statement::ColumnBlobAsVector(int col, std::vector<char>* val) const {
    242   val->clear();
    243   if (!is_valid()) {
    244     NOTREACHED();
    245     return;
    246   }
    247 
    248   const void* data = sqlite3_column_blob(ref_->stmt(), col);
    249   int len = sqlite3_column_bytes(ref_->stmt(), col);
    250   if (data && len > 0) {
    251     val->resize(len);
    252     memcpy(&(*val)[0], data, len);
    253   }
    254 }
    255 
    256 void Statement::ColumnBlobAsVector(
    257     int col,
    258     std::vector<unsigned char>* val) const {
    259   ColumnBlobAsVector(col, reinterpret_cast< std::vector<char>* >(val));
    260 }
    261 
    262 const char* Statement::GetSQLStatement() {
    263   return sqlite3_sql(ref_->stmt());
    264 }
    265 
    266 int Statement::CheckError(int err) {
    267   // Please don't add DCHECKs here, OnSqliteError() already has them.
    268   succeeded_ = (err == SQLITE_OK || err == SQLITE_ROW || err == SQLITE_DONE);
    269   if (!succeeded_ && is_valid())
    270     return ref_->connection()->OnSqliteError(err, this);
    271   return err;
    272 }
    273 
    274 }  // namespace sql
    275