ChromeOS: Fix crash if login profile triggers client auth.
[chromium-blink-merge.git] / sql / statement.cc
blob7001d171ee36fc8e6b41248b424a4762b78cc33b
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 stepped_(false),
20 succeeded_(false) {
23 Statement::Statement(scoped_refptr<Connection::StatementRef> ref)
24 : ref_(ref),
25 stepped_(false),
26 succeeded_(false) {
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);
36 void Statement::Assign(scoped_refptr<Connection::StatementRef> ref) {
37 Reset(true);
38 ref_ = ref;
41 void Statement::Clear() {
42 Assign(new Connection::StatementRef(NULL, NULL, false));
43 succeeded_ = false;
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();
54 bool Statement::Run() {
55 DCHECK(!stepped_);
56 ref_->AssertIOAllowed();
57 if (!CheckValid())
58 return false;
60 stepped_ = true;
61 return CheckError(sqlite3_step(ref_->stmt())) == SQLITE_DONE;
64 bool Statement::Step() {
65 ref_->AssertIOAllowed();
66 if (!CheckValid())
67 return false;
69 stepped_ = true;
70 return CheckError(sqlite3_step(ref_->stmt())) == SQLITE_ROW;
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());
84 succeeded_ = false;
85 stepped_ = false;
88 bool Statement::Succeeded() const {
89 if (!is_valid())
90 return false;
92 return succeeded_;
95 bool Statement::BindNull(int col) {
96 DCHECK(!stepped_);
97 if (!is_valid())
98 return false;
100 return CheckOk(sqlite3_bind_null(ref_->stmt(), col + 1));
103 bool Statement::BindBool(int col, bool val) {
104 return BindInt(col, val ? 1 : 0);
107 bool Statement::BindInt(int col, int val) {
108 DCHECK(!stepped_);
109 if (!is_valid())
110 return false;
112 return CheckOk(sqlite3_bind_int(ref_->stmt(), col + 1, val));
115 bool Statement::BindInt64(int col, int64 val) {
116 DCHECK(!stepped_);
117 if (!is_valid())
118 return false;
120 return CheckOk(sqlite3_bind_int64(ref_->stmt(), col + 1, val));
123 bool Statement::BindDouble(int col, double val) {
124 DCHECK(!stepped_);
125 if (!is_valid())
126 return false;
128 return CheckOk(sqlite3_bind_double(ref_->stmt(), col + 1, val));
131 bool Statement::BindCString(int col, const char* val) {
132 DCHECK(!stepped_);
133 if (!is_valid())
134 return false;
136 return CheckOk(
137 sqlite3_bind_text(ref_->stmt(), col + 1, val, -1, SQLITE_TRANSIENT));
140 bool Statement::BindString(int col, const std::string& val) {
141 DCHECK(!stepped_);
142 if (!is_valid())
143 return false;
145 return CheckOk(sqlite3_bind_text(ref_->stmt(),
146 col + 1,
147 val.data(),
148 val.size(),
149 SQLITE_TRANSIENT));
152 bool Statement::BindString16(int col, const base::string16& value) {
153 return BindString(col, base::UTF16ToUTF8(value));
156 bool Statement::BindBlob(int col, const void* val, int val_len) {
157 DCHECK(!stepped_);
158 if (!is_valid())
159 return false;
161 return CheckOk(
162 sqlite3_bind_blob(ref_->stmt(), col + 1, val, val_len, SQLITE_TRANSIENT));
165 int Statement::ColumnCount() const {
166 if (!is_valid())
167 return 0;
169 return sqlite3_column_count(ref_->stmt());
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);
180 return static_cast<ColType>(sqlite3_column_type(ref_->stmt(), col));
183 ColType Statement::DeclaredColumnType(int col) const {
184 std::string column_type(sqlite3_column_decltype(ref_->stmt(), col));
185 StringToLowerASCII(&column_type);
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;
196 return COLUMN_TYPE_NULL;
199 bool Statement::ColumnBool(int col) const {
200 return !!ColumnInt(col);
203 int Statement::ColumnInt(int col) const {
204 if (!CheckValid())
205 return 0;
207 return sqlite3_column_int(ref_->stmt(), col);
210 int64 Statement::ColumnInt64(int col) const {
211 if (!CheckValid())
212 return 0;
214 return sqlite3_column_int64(ref_->stmt(), col);
217 double Statement::ColumnDouble(int col) const {
218 if (!CheckValid())
219 return 0;
221 return sqlite3_column_double(ref_->stmt(), col);
224 std::string Statement::ColumnString(int col) const {
225 if (!CheckValid())
226 return std::string();
228 const char* str = reinterpret_cast<const char*>(
229 sqlite3_column_text(ref_->stmt(), col));
230 int len = sqlite3_column_bytes(ref_->stmt(), col);
232 std::string result;
233 if (str && len > 0)
234 result.assign(str, len);
235 return result;
238 base::string16 Statement::ColumnString16(int col) const {
239 if (!CheckValid())
240 return base::string16();
242 std::string s = ColumnString(col);
243 return !s.empty() ? base::UTF8ToUTF16(s) : base::string16();
246 int Statement::ColumnByteLength(int col) const {
247 if (!CheckValid())
248 return 0;
250 return sqlite3_column_bytes(ref_->stmt(), col);
253 const void* Statement::ColumnBlob(int col) const {
254 if (!CheckValid())
255 return NULL;
257 return sqlite3_column_blob(ref_->stmt(), col);
260 bool Statement::ColumnBlobAsString(int col, std::string* blob) {
261 if (!CheckValid())
262 return false;
264 const void* p = ColumnBlob(col);
265 size_t len = ColumnByteLength(col);
266 blob->resize(len);
267 if (blob->size() != len) {
268 return false;
270 blob->assign(reinterpret_cast<const char*>(p), len);
271 return true;
274 bool Statement::ColumnBlobAsString16(int col, base::string16* val) const {
275 if (!CheckValid())
276 return false;
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;
287 bool Statement::ColumnBlobAsVector(int col, std::vector<char>* val) const {
288 val->clear();
290 if (!CheckValid())
291 return false;
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);
299 return true;
302 bool Statement::ColumnBlobAsVector(
303 int col,
304 std::vector<unsigned char>* val) const {
305 return ColumnBlobAsVector(col, reinterpret_cast< std::vector<char>* >(val));
308 const char* Statement::GetSQLStatement() {
309 return sqlite3_sql(ref_->stmt());
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;
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;
329 } // namespace sql