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