Home | History | Annotate | Download | only in sql
      1 // Copyright (c) 2012 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 "sql/statement.h"
      6 
      7 #include "base/logging.h"
      8 #include "base/strings/string_util.h"
      9 #include "base/strings/utf_string_conversions.h"
     10 #include "third_party/sqlite/sqlite3.h"
     11 
     12 namespace sql {
     13 
     14 // This empty constructor initializes our reference with an empty one so that
     15 // we don't have to NULL-check the ref_ to see if the statement is valid: we
     16 // only have to check the ref's validity bit.
     17 Statement::Statement()
     18     : ref_(new Connection::StatementRef(NULL, NULL, false)),
     19       stepped_(false),
     20       succeeded_(false) {
     21 }
     22 
     23 Statement::Statement(scoped_refptr<Connection::StatementRef> ref)
     24     : ref_(ref),
     25       stepped_(false),
     26       succeeded_(false) {
     27 }
     28 
     29 Statement::~Statement() {
     30   // Free the resources associated with this statement. We assume there's only
     31   // one statement active for a given sqlite3_stmt at any time, so this won't
     32   // mess with anything.
     33   Reset(true);
     34 }
     35 
     36 void Statement::Assign(scoped_refptr<Connection::StatementRef> ref) {
     37   Reset(true);
     38   ref_ = ref;
     39 }
     40 
     41 void Statement::Clear() {
     42   Assign(new Connection::StatementRef(NULL, NULL, false));
     43   succeeded_ = false;
     44 }
     45 
     46 bool Statement::CheckValid() const {
     47   // Allow operations to fail silently if a statement was invalidated
     48   // because the database was closed by an error handler.
     49   DLOG_IF(FATAL, !ref_->was_valid())
     50       << "Cannot call mutating statements on an invalid statement.";
     51   return is_valid();
     52 }
     53 
     54 bool Statement::Run() {
     55   DCHECK(!stepped_);
     56   ref_->AssertIOAllowed();
     57   if (!CheckValid())
     58     return false;
     59 
     60   stepped_ = true;
     61   return CheckError(sqlite3_step(ref_->stmt())) == SQLITE_DONE;
     62 }
     63 
     64 bool Statement::Step() {
     65   ref_->AssertIOAllowed();
     66   if (!CheckValid())
     67     return false;
     68 
     69   stepped_ = true;
     70   return CheckError(sqlite3_step(ref_->stmt())) == SQLITE_ROW;
     71 }
     72 
     73 void Statement::Reset(bool clear_bound_vars) {
     74   ref_->AssertIOAllowed();
     75   if (is_valid()) {
     76     // We don't call CheckError() here because sqlite3_reset() returns
     77     // the last error that Step() caused thereby generating a second
     78     // spurious error callback.
     79     if (clear_bound_vars)
     80       sqlite3_clear_bindings(ref_->stmt());
     81     sqlite3_reset(ref_->stmt());
     82   }
     83 
     84   succeeded_ = false;
     85   stepped_ = false;
     86 }
     87 
     88 bool Statement::Succeeded() const {
     89   if (!is_valid())
     90     return false;
     91 
     92   return succeeded_;
     93 }
     94 
     95 bool Statement::BindNull(int col) {
     96   DCHECK(!stepped_);
     97   if (!is_valid())
     98     return false;
     99 
    100   return CheckOk(sqlite3_bind_null(ref_->stmt(), col + 1));
    101 }
    102 
    103 bool Statement::BindBool(int col, bool val) {
    104   return BindInt(col, val ? 1 : 0);
    105 }
    106 
    107 bool Statement::BindInt(int col, int val) {
    108   DCHECK(!stepped_);
    109   if (!is_valid())
    110     return false;
    111 
    112   return CheckOk(sqlite3_bind_int(ref_->stmt(), col + 1, val));
    113 }
    114 
    115 bool Statement::BindInt64(int col, int64 val) {
    116   DCHECK(!stepped_);
    117   if (!is_valid())
    118     return false;
    119 
    120   return CheckOk(sqlite3_bind_int64(ref_->stmt(), col + 1, val));
    121 }
    122 
    123 bool Statement::BindDouble(int col, double val) {
    124   DCHECK(!stepped_);
    125   if (!is_valid())
    126     return false;
    127 
    128   return CheckOk(sqlite3_bind_double(ref_->stmt(), col + 1, val));
    129 }
    130 
    131 bool Statement::BindCString(int col, const char* val) {
    132   DCHECK(!stepped_);
    133   if (!is_valid())
    134     return false;
    135 
    136   return CheckOk(
    137       sqlite3_bind_text(ref_->stmt(), col + 1, val, -1, SQLITE_TRANSIENT));
    138 }
    139 
    140 bool Statement::BindString(int col, const std::string& val) {
    141   DCHECK(!stepped_);
    142   if (!is_valid())
    143     return false;
    144 
    145   return CheckOk(sqlite3_bind_text(ref_->stmt(),
    146                                    col + 1,
    147                                    val.data(),
    148                                    val.size(),
    149                                    SQLITE_TRANSIENT));
    150 }
    151 
    152 bool Statement::BindString16(int col, const base::string16& value) {
    153   return BindString(col, base::UTF16ToUTF8(value));
    154 }
    155 
    156 bool Statement::BindBlob(int col, const void* val, int val_len) {
    157   DCHECK(!stepped_);
    158   if (!is_valid())
    159     return false;
    160 
    161   return CheckOk(
    162       sqlite3_bind_blob(ref_->stmt(), col + 1, val, val_len, SQLITE_TRANSIENT));
    163 }
    164 
    165 int Statement::ColumnCount() const {
    166   if (!is_valid())
    167     return 0;
    168 
    169   return sqlite3_column_count(ref_->stmt());
    170 }
    171 
    172 ColType Statement::ColumnType(int col) const {
    173   // Verify that our enum matches sqlite's values.
    174   COMPILE_ASSERT(COLUMN_TYPE_INTEGER == SQLITE_INTEGER, integer_no_match);
    175   COMPILE_ASSERT(COLUMN_TYPE_FLOAT == SQLITE_FLOAT, float_no_match);
    176   COMPILE_ASSERT(COLUMN_TYPE_TEXT == SQLITE_TEXT, integer_no_match);
    177   COMPILE_ASSERT(COLUMN_TYPE_BLOB == SQLITE_BLOB, blob_no_match);
    178   COMPILE_ASSERT(COLUMN_TYPE_NULL == SQLITE_NULL, null_no_match);
    179 
    180   return static_cast<ColType>(sqlite3_column_type(ref_->stmt(), col));
    181 }
    182 
    183 ColType Statement::DeclaredColumnType(int col) const {
    184   std::string column_type(sqlite3_column_decltype(ref_->stmt(), col));
    185   base::StringToLowerASCII(&column_type);
    186 
    187   if (column_type == "integer")
    188     return COLUMN_TYPE_INTEGER;
    189   else if (column_type == "float")
    190     return COLUMN_TYPE_FLOAT;
    191   else if (column_type == "text")
    192     return COLUMN_TYPE_TEXT;
    193   else if (column_type == "blob")
    194     return COLUMN_TYPE_BLOB;
    195 
    196   return COLUMN_TYPE_NULL;
    197 }
    198 
    199 bool Statement::ColumnBool(int col) const {
    200   return !!ColumnInt(col);
    201 }
    202 
    203 int Statement::ColumnInt(int col) const {
    204   if (!CheckValid())
    205     return 0;
    206 
    207   return sqlite3_column_int(ref_->stmt(), col);
    208 }
    209 
    210 int64 Statement::ColumnInt64(int col) const {
    211   if (!CheckValid())
    212     return 0;
    213 
    214   return sqlite3_column_int64(ref_->stmt(), col);
    215 }
    216 
    217 double Statement::ColumnDouble(int col) const {
    218   if (!CheckValid())
    219     return 0;
    220 
    221   return sqlite3_column_double(ref_->stmt(), col);
    222 }
    223 
    224 std::string Statement::ColumnString(int col) const {
    225   if (!CheckValid())
    226     return std::string();
    227 
    228   const char* str = reinterpret_cast<const char*>(
    229       sqlite3_column_text(ref_->stmt(), col));
    230   int len = sqlite3_column_bytes(ref_->stmt(), col);
    231 
    232   std::string result;
    233   if (str && len > 0)
    234     result.assign(str, len);
    235   return result;
    236 }
    237 
    238 base::string16 Statement::ColumnString16(int col) const {
    239   if (!CheckValid())
    240     return base::string16();
    241 
    242   std::string s = ColumnString(col);
    243   return !s.empty() ? base::UTF8ToUTF16(s) : base::string16();
    244 }
    245 
    246 int Statement::ColumnByteLength(int col) const {
    247   if (!CheckValid())
    248     return 0;
    249 
    250   return sqlite3_column_bytes(ref_->stmt(), col);
    251 }
    252 
    253 const void* Statement::ColumnBlob(int col) const {
    254   if (!CheckValid())
    255     return NULL;
    256 
    257   return sqlite3_column_blob(ref_->stmt(), col);
    258 }
    259 
    260 bool Statement::ColumnBlobAsString(int col, std::string* blob) {
    261   if (!CheckValid())
    262     return false;
    263 
    264   const void* p = ColumnBlob(col);
    265   size_t len = ColumnByteLength(col);
    266   blob->resize(len);
    267   if (blob->size() != len) {
    268     return false;
    269   }
    270   blob->assign(reinterpret_cast<const char*>(p), len);
    271   return true;
    272 }
    273 
    274 bool Statement::ColumnBlobAsString16(int col, base::string16* val) const {
    275   if (!CheckValid())
    276     return false;
    277 
    278   const void* data = ColumnBlob(col);
    279   size_t len = ColumnByteLength(col) / sizeof(base::char16);
    280   val->resize(len);
    281   if (val->size() != len)
    282     return false;
    283   val->assign(reinterpret_cast<const base::char16*>(data), len);
    284   return true;
    285 }
    286 
    287 bool Statement::ColumnBlobAsVector(int col, std::vector<char>* val) const {
    288   val->clear();
    289 
    290   if (!CheckValid())
    291     return false;
    292 
    293   const void* data = sqlite3_column_blob(ref_->stmt(), col);
    294   int len = sqlite3_column_bytes(ref_->stmt(), col);
    295   if (data && len > 0) {
    296     val->resize(len);
    297     memcpy(&(*val)[0], data, len);
    298   }
    299   return true;
    300 }
    301 
    302 bool Statement::ColumnBlobAsVector(
    303     int col,
    304     std::vector<unsigned char>* val) const {
    305   return ColumnBlobAsVector(col, reinterpret_cast< std::vector<char>* >(val));
    306 }
    307 
    308 const char* Statement::GetSQLStatement() {
    309   return sqlite3_sql(ref_->stmt());
    310 }
    311 
    312 bool Statement::CheckOk(int err) const {
    313   // Binding to a non-existent variable is evidence of a serious error.
    314   // TODO(gbillock,shess): make this invalidate the statement so it
    315   // can't wreak havoc.
    316   if (err == SQLITE_RANGE)
    317     DLOG(FATAL) << "Bind value out of range";
    318   return err == SQLITE_OK;
    319 }
    320 
    321 int Statement::CheckError(int err) {
    322   // Please don't add DCHECKs here, OnSqliteError() already has them.
    323   succeeded_ = (err == SQLITE_OK || err == SQLITE_ROW || err == SQLITE_DONE);
    324   if (!succeeded_ && ref_.get() && ref_->connection())
    325     return ref_->connection()->OnSqliteError(err, this, NULL);
    326   return err;
    327 }
    328 
    329 }  // namespace sql
    330