Extend batched shutdown to include the in-progress downloads dialog.
[chromium-blink-merge.git] / sql / statement.cc
blobda2c58fd69d10da0d86bdd0ea9b03ed3d4e7115d
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.
5 #include "sql/statement.h"
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"
12 namespace sql {
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 succeeded_(false) {
22 Statement::Statement(scoped_refptr<Connection::StatementRef> ref)
23 : ref_(ref),
24 succeeded_(false) {
27 Statement::~Statement() {
28 // Free the resources associated with this statement. We assume there's only
29 // one statement active for a given sqlite3_stmt at any time, so this won't
30 // mess with anything.
31 Reset(true);
34 void Statement::Assign(scoped_refptr<Connection::StatementRef> ref) {
35 Reset(true);
36 ref_ = ref;
39 void Statement::Clear() {
40 Assign(new Connection::StatementRef(NULL, NULL, false));
41 succeeded_ = false;
44 bool Statement::CheckValid() const {
45 // Allow operations to fail silently if a statement was invalidated
46 // because the database was closed by an error handler.
47 DLOG_IF(FATAL, !ref_->was_valid())
48 << "Cannot call mutating statements on an invalid statement.";
49 return is_valid();
52 bool Statement::Run() {
53 ref_->AssertIOAllowed();
54 if (!CheckValid())
55 return false;
57 return CheckError(sqlite3_step(ref_->stmt())) == SQLITE_DONE;
60 bool Statement::Step() {
61 ref_->AssertIOAllowed();
62 if (!CheckValid())
63 return false;
65 return CheckError(sqlite3_step(ref_->stmt())) == SQLITE_ROW;
68 void Statement::Reset(bool clear_bound_vars) {
69 ref_->AssertIOAllowed();
70 if (is_valid()) {
71 // We don't call CheckError() here because sqlite3_reset() returns
72 // the last error that Step() caused thereby generating a second
73 // spurious error callback.
74 if (clear_bound_vars)
75 sqlite3_clear_bindings(ref_->stmt());
76 sqlite3_reset(ref_->stmt());
79 succeeded_ = false;
82 bool Statement::Succeeded() const {
83 if (!is_valid())
84 return false;
86 return succeeded_;
89 bool Statement::BindNull(int col) {
90 if (!is_valid())
91 return false;
93 return CheckOk(sqlite3_bind_null(ref_->stmt(), col + 1));
96 bool Statement::BindBool(int col, bool val) {
97 return BindInt(col, val ? 1 : 0);
100 bool Statement::BindInt(int col, int val) {
101 if (!is_valid())
102 return false;
104 return CheckOk(sqlite3_bind_int(ref_->stmt(), col + 1, val));
107 bool Statement::BindInt64(int col, int64 val) {
108 if (!is_valid())
109 return false;
111 return CheckOk(sqlite3_bind_int64(ref_->stmt(), col + 1, val));
114 bool Statement::BindDouble(int col, double val) {
115 if (!is_valid())
116 return false;
118 return CheckOk(sqlite3_bind_double(ref_->stmt(), col + 1, val));
121 bool Statement::BindCString(int col, const char* val) {
122 if (!is_valid())
123 return false;
125 return CheckOk(
126 sqlite3_bind_text(ref_->stmt(), col + 1, val, -1, SQLITE_TRANSIENT));
129 bool Statement::BindString(int col, const std::string& val) {
130 if (!is_valid())
131 return false;
133 return CheckOk(sqlite3_bind_text(ref_->stmt(),
134 col + 1,
135 val.data(),
136 val.size(),
137 SQLITE_TRANSIENT));
140 bool Statement::BindString16(int col, const string16& value) {
141 return BindString(col, UTF16ToUTF8(value));
144 bool Statement::BindBlob(int col, const void* val, int val_len) {
145 if (!is_valid())
146 return false;
148 return CheckOk(
149 sqlite3_bind_blob(ref_->stmt(), col + 1, val, val_len, SQLITE_TRANSIENT));
152 int Statement::ColumnCount() const {
153 if (!is_valid())
154 return 0;
156 return sqlite3_column_count(ref_->stmt());
159 ColType Statement::ColumnType(int col) const {
160 // Verify that our enum matches sqlite's values.
161 COMPILE_ASSERT(COLUMN_TYPE_INTEGER == SQLITE_INTEGER, integer_no_match);
162 COMPILE_ASSERT(COLUMN_TYPE_FLOAT == SQLITE_FLOAT, float_no_match);
163 COMPILE_ASSERT(COLUMN_TYPE_TEXT == SQLITE_TEXT, integer_no_match);
164 COMPILE_ASSERT(COLUMN_TYPE_BLOB == SQLITE_BLOB, blob_no_match);
165 COMPILE_ASSERT(COLUMN_TYPE_NULL == SQLITE_NULL, null_no_match);
167 return static_cast<ColType>(sqlite3_column_type(ref_->stmt(), col));
170 ColType Statement::DeclaredColumnType(int col) const {
171 std::string column_type(sqlite3_column_decltype(ref_->stmt(), col));
172 StringToLowerASCII(&column_type);
174 if (column_type == "integer")
175 return COLUMN_TYPE_INTEGER;
176 else if (column_type == "float")
177 return COLUMN_TYPE_FLOAT;
178 else if (column_type == "text")
179 return COLUMN_TYPE_TEXT;
180 else if (column_type == "blob")
181 return COLUMN_TYPE_BLOB;
183 return COLUMN_TYPE_NULL;
186 bool Statement::ColumnBool(int col) const {
187 return !!ColumnInt(col);
190 int Statement::ColumnInt(int col) const {
191 if (!CheckValid())
192 return 0;
194 return sqlite3_column_int(ref_->stmt(), col);
197 int64 Statement::ColumnInt64(int col) const {
198 if (!CheckValid())
199 return 0;
201 return sqlite3_column_int64(ref_->stmt(), col);
204 double Statement::ColumnDouble(int col) const {
205 if (!CheckValid())
206 return 0;
208 return sqlite3_column_double(ref_->stmt(), col);
211 std::string Statement::ColumnString(int col) const {
212 if (!CheckValid())
213 return std::string();
215 const char* str = reinterpret_cast<const char*>(
216 sqlite3_column_text(ref_->stmt(), col));
217 int len = sqlite3_column_bytes(ref_->stmt(), col);
219 std::string result;
220 if (str && len > 0)
221 result.assign(str, len);
222 return result;
225 string16 Statement::ColumnString16(int col) const {
226 if (!CheckValid())
227 return string16();
229 std::string s = ColumnString(col);
230 return !s.empty() ? UTF8ToUTF16(s) : string16();
233 int Statement::ColumnByteLength(int col) const {
234 if (!CheckValid())
235 return 0;
237 return sqlite3_column_bytes(ref_->stmt(), col);
240 const void* Statement::ColumnBlob(int col) const {
241 if (!CheckValid())
242 return NULL;
244 return sqlite3_column_blob(ref_->stmt(), col);
247 bool Statement::ColumnBlobAsString(int col, std::string* blob) {
248 if (!CheckValid())
249 return false;
251 const void* p = ColumnBlob(col);
252 size_t len = ColumnByteLength(col);
253 blob->resize(len);
254 if (blob->size() != len) {
255 return false;
257 blob->assign(reinterpret_cast<const char*>(p), len);
258 return true;
261 bool Statement::ColumnBlobAsString16(int col, string16* val) const {
262 if (!CheckValid())
263 return false;
265 const void* data = ColumnBlob(col);
266 size_t len = ColumnByteLength(col) / sizeof(char16);
267 val->resize(len);
268 if (val->size() != len)
269 return false;
270 val->assign(reinterpret_cast<const char16*>(data), len);
271 return true;
274 bool Statement::ColumnBlobAsVector(int col, std::vector<char>* val) const {
275 val->clear();
277 if (!CheckValid())
278 return false;
280 const void* data = sqlite3_column_blob(ref_->stmt(), col);
281 int len = sqlite3_column_bytes(ref_->stmt(), col);
282 if (data && len > 0) {
283 val->resize(len);
284 memcpy(&(*val)[0], data, len);
286 return true;
289 bool Statement::ColumnBlobAsVector(
290 int col,
291 std::vector<unsigned char>* val) const {
292 return ColumnBlobAsVector(col, reinterpret_cast< std::vector<char>* >(val));
295 const char* Statement::GetSQLStatement() {
296 return sqlite3_sql(ref_->stmt());
299 bool Statement::CheckOk(int err) const {
300 // Binding to a non-existent variable is evidence of a serious error.
301 // TODO(gbillock,shess): make this invalidate the statement so it
302 // can't wreak havoc.
303 if (err == SQLITE_RANGE)
304 DLOG(FATAL) << "Bind value out of range";
305 return err == SQLITE_OK;
308 int Statement::CheckError(int err) {
309 // Please don't add DCHECKs here, OnSqliteError() already has them.
310 succeeded_ = (err == SQLITE_OK || err == SQLITE_ROW || err == SQLITE_DONE);
311 if (!succeeded_ && ref_.get() && ref_->connection())
312 return ref_->connection()->OnSqliteError(err, this);
313 return err;
316 } // namespace sql