Disable failing NavigationPopupTest
[chromium-blink-merge.git] / sql / statement.cc
blob038ebde0885670d136c454485d70a4cabe63450d
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 int Statement::StepInternal(bool timer_flag) {
55 ref_->AssertIOAllowed();
56 if (!CheckValid())
57 return SQLITE_ERROR;
59 const bool was_stepped = stepped_;
60 stepped_ = true;
61 int ret = SQLITE_ERROR;
62 if (!ref_->connection()) {
63 ret = sqlite3_step(ref_->stmt());
64 } else {
65 if (!timer_flag) {
66 ret = sqlite3_step(ref_->stmt());
67 } else {
68 const base::TimeTicks before = ref_->connection()->Now();
69 ret = sqlite3_step(ref_->stmt());
70 const base::TimeTicks after = ref_->connection()->Now();
71 const bool read_only = !!sqlite3_stmt_readonly(ref_->stmt());
72 ref_->connection()->RecordTimeAndChanges(after - before, read_only);
75 if (!was_stepped)
76 ref_->connection()->RecordOneEvent(Connection::EVENT_STATEMENT_RUN);
78 if (ret == SQLITE_ROW)
79 ref_->connection()->RecordOneEvent(Connection::EVENT_STATEMENT_ROWS);
81 return CheckError(ret);
84 bool Statement::Run() {
85 DCHECK(!stepped_);
86 return StepInternal(true) == SQLITE_DONE;
89 bool Statement::RunWithoutTimers() {
90 DCHECK(!stepped_);
91 return StepInternal(false) == SQLITE_DONE;
94 bool Statement::Step() {
95 return StepInternal(true) == SQLITE_ROW;
98 void Statement::Reset(bool clear_bound_vars) {
99 ref_->AssertIOAllowed();
100 if (is_valid()) {
101 if (clear_bound_vars)
102 sqlite3_clear_bindings(ref_->stmt());
104 // StepInternal() cannot track success because statements may be reset
105 // before reaching SQLITE_DONE. Don't call CheckError() because
106 // sqlite3_reset() returns the last step error, which StepInternal() already
107 // checked.
108 const int rc =sqlite3_reset(ref_->stmt());
109 if (rc == SQLITE_OK && ref_->connection())
110 ref_->connection()->RecordOneEvent(Connection::EVENT_STATEMENT_SUCCESS);
113 succeeded_ = false;
114 stepped_ = false;
117 bool Statement::Succeeded() const {
118 if (!is_valid())
119 return false;
121 return succeeded_;
124 bool Statement::BindNull(int col) {
125 DCHECK(!stepped_);
126 if (!is_valid())
127 return false;
129 return CheckOk(sqlite3_bind_null(ref_->stmt(), col + 1));
132 bool Statement::BindBool(int col, bool val) {
133 return BindInt(col, val ? 1 : 0);
136 bool Statement::BindInt(int col, int val) {
137 DCHECK(!stepped_);
138 if (!is_valid())
139 return false;
141 return CheckOk(sqlite3_bind_int(ref_->stmt(), col + 1, val));
144 bool Statement::BindInt64(int col, int64_t val) {
145 DCHECK(!stepped_);
146 if (!is_valid())
147 return false;
149 return CheckOk(sqlite3_bind_int64(ref_->stmt(), col + 1, val));
152 bool Statement::BindDouble(int col, double val) {
153 DCHECK(!stepped_);
154 if (!is_valid())
155 return false;
157 return CheckOk(sqlite3_bind_double(ref_->stmt(), col + 1, val));
160 bool Statement::BindCString(int col, const char* val) {
161 DCHECK(!stepped_);
162 if (!is_valid())
163 return false;
165 return CheckOk(
166 sqlite3_bind_text(ref_->stmt(), col + 1, val, -1, SQLITE_TRANSIENT));
169 bool Statement::BindString(int col, const std::string& val) {
170 DCHECK(!stepped_);
171 if (!is_valid())
172 return false;
174 return CheckOk(sqlite3_bind_text(ref_->stmt(),
175 col + 1,
176 val.data(),
177 val.size(),
178 SQLITE_TRANSIENT));
181 bool Statement::BindString16(int col, const base::string16& value) {
182 return BindString(col, base::UTF16ToUTF8(value));
185 bool Statement::BindBlob(int col, const void* val, int val_len) {
186 DCHECK(!stepped_);
187 if (!is_valid())
188 return false;
190 return CheckOk(
191 sqlite3_bind_blob(ref_->stmt(), col + 1, val, val_len, SQLITE_TRANSIENT));
194 int Statement::ColumnCount() const {
195 if (!is_valid())
196 return 0;
198 return sqlite3_column_count(ref_->stmt());
201 ColType Statement::ColumnType(int col) const {
202 // Verify that our enum matches sqlite's values.
203 static_assert(COLUMN_TYPE_INTEGER == SQLITE_INTEGER, "integer no match");
204 static_assert(COLUMN_TYPE_FLOAT == SQLITE_FLOAT, "float no match");
205 static_assert(COLUMN_TYPE_TEXT == SQLITE_TEXT, "integer no match");
206 static_assert(COLUMN_TYPE_BLOB == SQLITE_BLOB, "blob no match");
207 static_assert(COLUMN_TYPE_NULL == SQLITE_NULL, "null no match");
209 return static_cast<ColType>(sqlite3_column_type(ref_->stmt(), col));
212 ColType Statement::DeclaredColumnType(int col) const {
213 std::string column_type(sqlite3_column_decltype(ref_->stmt(), col));
214 base::StringToLowerASCII(&column_type);
216 if (column_type == "integer")
217 return COLUMN_TYPE_INTEGER;
218 else if (column_type == "float")
219 return COLUMN_TYPE_FLOAT;
220 else if (column_type == "text")
221 return COLUMN_TYPE_TEXT;
222 else if (column_type == "blob")
223 return COLUMN_TYPE_BLOB;
225 return COLUMN_TYPE_NULL;
228 bool Statement::ColumnBool(int col) const {
229 return !!ColumnInt(col);
232 int Statement::ColumnInt(int col) const {
233 if (!CheckValid())
234 return 0;
236 return sqlite3_column_int(ref_->stmt(), col);
239 int64_t Statement::ColumnInt64(int col) const {
240 if (!CheckValid())
241 return 0;
243 return sqlite3_column_int64(ref_->stmt(), col);
246 double Statement::ColumnDouble(int col) const {
247 if (!CheckValid())
248 return 0;
250 return sqlite3_column_double(ref_->stmt(), col);
253 std::string Statement::ColumnString(int col) const {
254 if (!CheckValid())
255 return std::string();
257 const char* str = reinterpret_cast<const char*>(
258 sqlite3_column_text(ref_->stmt(), col));
259 int len = sqlite3_column_bytes(ref_->stmt(), col);
261 std::string result;
262 if (str && len > 0)
263 result.assign(str, len);
264 return result;
267 base::string16 Statement::ColumnString16(int col) const {
268 if (!CheckValid())
269 return base::string16();
271 std::string s = ColumnString(col);
272 return !s.empty() ? base::UTF8ToUTF16(s) : base::string16();
275 int Statement::ColumnByteLength(int col) const {
276 if (!CheckValid())
277 return 0;
279 return sqlite3_column_bytes(ref_->stmt(), col);
282 const void* Statement::ColumnBlob(int col) const {
283 if (!CheckValid())
284 return NULL;
286 return sqlite3_column_blob(ref_->stmt(), col);
289 bool Statement::ColumnBlobAsString(int col, std::string* blob) {
290 if (!CheckValid())
291 return false;
293 const void* p = ColumnBlob(col);
294 size_t len = ColumnByteLength(col);
295 blob->resize(len);
296 if (blob->size() != len) {
297 return false;
299 blob->assign(reinterpret_cast<const char*>(p), len);
300 return true;
303 bool Statement::ColumnBlobAsString16(int col, base::string16* val) const {
304 if (!CheckValid())
305 return false;
307 const void* data = ColumnBlob(col);
308 size_t len = ColumnByteLength(col) / sizeof(base::char16);
309 val->resize(len);
310 if (val->size() != len)
311 return false;
312 val->assign(reinterpret_cast<const base::char16*>(data), len);
313 return true;
316 bool Statement::ColumnBlobAsVector(int col, std::vector<char>* val) const {
317 val->clear();
319 if (!CheckValid())
320 return false;
322 const void* data = sqlite3_column_blob(ref_->stmt(), col);
323 int len = sqlite3_column_bytes(ref_->stmt(), col);
324 if (data && len > 0) {
325 val->resize(len);
326 memcpy(&(*val)[0], data, len);
328 return true;
331 bool Statement::ColumnBlobAsVector(
332 int col,
333 std::vector<unsigned char>* val) const {
334 return ColumnBlobAsVector(col, reinterpret_cast< std::vector<char>* >(val));
337 const char* Statement::GetSQLStatement() {
338 return sqlite3_sql(ref_->stmt());
341 bool Statement::CheckOk(int err) const {
342 // Binding to a non-existent variable is evidence of a serious error.
343 // TODO(gbillock,shess): make this invalidate the statement so it
344 // can't wreak havoc.
345 if (err == SQLITE_RANGE)
346 DLOG(FATAL) << "Bind value out of range";
347 return err == SQLITE_OK;
350 int Statement::CheckError(int err) {
351 // Please don't add DCHECKs here, OnSqliteError() already has them.
352 succeeded_ = (err == SQLITE_OK || err == SQLITE_ROW || err == SQLITE_DONE);
353 if (!succeeded_ && ref_.get() && ref_->connection())
354 return ref_->connection()->OnSqliteError(err, this, NULL);
355 return err;
358 } // namespace sql