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 15namespace 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. 20Statement::Statement() 21 : ref_(new Connection::StatementRef), 22 succeeded_(false) { 23} 24 25Statement::Statement(scoped_refptr<Connection::StatementRef> ref) 26 : ref_(ref), 27 succeeded_(false) { 28} 29 30Statement::~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 37void Statement::Assign(scoped_refptr<Connection::StatementRef> ref) { 38 Reset(); 39 ref_ = ref; 40} 41 42bool Statement::Run() { 43 if (!is_valid()) 44 return false; 45 return CheckError(sqlite3_step(ref_->stmt())) == SQLITE_DONE; 46} 47 48bool Statement::Step() { 49 if (!is_valid()) 50 return false; 51 return CheckError(sqlite3_step(ref_->stmt())) == SQLITE_ROW; 52} 53 54void 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 65bool Statement::Succeeded() const { 66 if (!is_valid()) 67 return false; 68 return succeeded_; 69} 70 71bool 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 79bool Statement::BindBool(int col, bool val) { 80 return BindInt(col, val ? 1 : 0); 81} 82 83bool 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 91bool 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 99bool 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 107bool 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 116bool 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 125bool Statement::BindString16(int col, const string16& value) { 126 return BindString(col, UTF16ToUTF8(value)); 127} 128 129bool 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 138int Statement::ColumnCount() const { 139 if (!is_valid()) { 140 NOTREACHED(); 141 return 0; 142 } 143 return sqlite3_column_count(ref_->stmt()); 144} 145 146ColType 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 157bool Statement::ColumnBool(int col) const { 158 return !!ColumnInt(col); 159} 160 161int 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 169int64 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 177double 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 185std::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 200string16 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 209int 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 217const 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 226bool 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 241void 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 256void Statement::ColumnBlobAsVector( 257 int col, 258 std::vector<unsigned char>* val) const { 259 ColumnBlobAsVector(col, reinterpret_cast< std::vector<char>* >(val)); 260} 261 262const char* Statement::GetSQLStatement() { 263 return sqlite3_sql(ref_->stmt()); 264} 265 266int 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