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.
4
5 #include "sql/statement.h"
6
7 #include <stddef.h>
8 #include <stdint.h>
9
10 #include "base/logging.h"
11 #include "base/numerics/safe_conversions.h"
12 #include "base/strings/string_util.h"
13 #include "base/strings/utf_string_conversions.h"
14 #include "third_party/sqlite/sqlite3.h"
15
16 namespace sql {
17
18 // This empty constructor initializes our reference with an empty one so that
19 // we don't have to null-check the ref_ to see if the statement is valid: we
20 // only have to check the ref's validity bit.
Statement()21 Statement::Statement()
22 : ref_(base::MakeRefCounted<Database::StatementRef>(nullptr,
23 nullptr,
24 false)),
25 stepped_(false),
26 succeeded_(false) {}
27
Statement(scoped_refptr<Database::StatementRef> ref)28 Statement::Statement(scoped_refptr<Database::StatementRef> ref)
29 : ref_(std::move(ref)), stepped_(false), succeeded_(false) {}
30
~Statement()31 Statement::~Statement() {
32 // Free the resources associated with this statement. We assume there's only
33 // one statement active for a given sqlite3_stmt at any time, so this won't
34 // mess with anything.
35 Reset(true);
36 }
37
Assign(scoped_refptr<Database::StatementRef> ref)38 void Statement::Assign(scoped_refptr<Database::StatementRef> ref) {
39 Reset(true);
40 ref_ = std::move(ref);
41 }
42
Clear()43 void Statement::Clear() {
44 Assign(base::MakeRefCounted<Database::StatementRef>(nullptr, nullptr, false));
45 succeeded_ = false;
46 }
47
CheckValid() const48 bool Statement::CheckValid() const {
49 // Allow operations to fail silently if a statement was invalidated
50 // because the database was closed by an error handler.
51 DLOG_IF(FATAL, !ref_->was_valid())
52 << "Cannot call mutating statements on an invalid statement.";
53 return is_valid();
54 }
55
StepInternal()56 int Statement::StepInternal() {
57 if (!CheckValid())
58 return SQLITE_ERROR;
59
60 base::Optional<base::ScopedBlockingCall> scoped_blocking_call;
61 ref_->InitScopedBlockingCall(FROM_HERE, &scoped_blocking_call);
62
63 stepped_ = true;
64 int ret = sqlite3_step(ref_->stmt());
65 return CheckError(ret);
66 }
67
Run()68 bool Statement::Run() {
69 DCHECK(!stepped_);
70 return StepInternal() == SQLITE_DONE;
71 }
72
Step()73 bool Statement::Step() {
74 return StepInternal() == SQLITE_ROW;
75 }
76
Reset(bool clear_bound_vars)77 void Statement::Reset(bool clear_bound_vars) {
78 base::Optional<base::ScopedBlockingCall> scoped_blocking_call;
79 ref_->InitScopedBlockingCall(FROM_HERE, &scoped_blocking_call);
80 if (is_valid()) {
81 if (clear_bound_vars)
82 sqlite3_clear_bindings(ref_->stmt());
83
84 // StepInternal() cannot track success because statements may be reset
85 // before reaching SQLITE_DONE. Don't call CheckError() because
86 // sqlite3_reset() returns the last step error, which StepInternal() already
87 // checked.
88 sqlite3_reset(ref_->stmt());
89 }
90
91 // Potentially release dirty cache pages if an autocommit statement made
92 // changes.
93 if (ref_->database())
94 ref_->database()->ReleaseCacheMemoryIfNeeded(false);
95
96 succeeded_ = false;
97 stepped_ = false;
98 }
99
Succeeded() const100 bool Statement::Succeeded() const {
101 return is_valid() && succeeded_;
102 }
103
BindNull(int col)104 bool Statement::BindNull(int col) {
105 DCHECK(!stepped_);
106
107 return is_valid() && CheckOk(sqlite3_bind_null(ref_->stmt(), col + 1));
108 }
109
BindBool(int col,bool val)110 bool Statement::BindBool(int col, bool val) {
111 return BindInt(col, val ? 1 : 0);
112 }
113
BindInt(int col,int val)114 bool Statement::BindInt(int col, int val) {
115 DCHECK(!stepped_);
116
117 return is_valid() && CheckOk(sqlite3_bind_int(ref_->stmt(), col + 1, val));
118 }
119
BindInt64(int col,int64_t val)120 bool Statement::BindInt64(int col, int64_t val) {
121 DCHECK(!stepped_);
122
123 return is_valid() && CheckOk(sqlite3_bind_int64(ref_->stmt(), col + 1, val));
124 }
125
BindDouble(int col,double val)126 bool Statement::BindDouble(int col, double val) {
127 DCHECK(!stepped_);
128
129 return is_valid() && CheckOk(sqlite3_bind_double(ref_->stmt(), col + 1, val));
130 }
131
BindCString(int col,const char * val)132 bool Statement::BindCString(int col, const char* val) {
133 DCHECK(!stepped_);
134
135 return is_valid() && CheckOk(sqlite3_bind_text(ref_->stmt(), col + 1, val, -1,
136 SQLITE_TRANSIENT));
137 }
138
BindString(int col,const std::string & val)139 bool Statement::BindString(int col, const std::string& val) {
140 DCHECK(!stepped_);
141
142 return is_valid() &&
143 CheckOk(sqlite3_bind_text(ref_->stmt(), col + 1, val.data(),
144 base::checked_cast<int>(val.size()),
145 SQLITE_TRANSIENT));
146 }
147
BindString16(int col,const base::string16 & value)148 bool Statement::BindString16(int col, const base::string16& value) {
149 return BindString(col, base::UTF16ToUTF8(value));
150 }
151
BindBlob(int col,const void * val,int val_len)152 bool Statement::BindBlob(int col, const void* val, int val_len) {
153 DCHECK(!stepped_);
154
155 return is_valid() && CheckOk(sqlite3_bind_blob(ref_->stmt(), col + 1, val,
156 val_len, SQLITE_TRANSIENT));
157 }
158
ColumnCount() const159 int Statement::ColumnCount() const {
160 if (!is_valid())
161 return 0;
162 return sqlite3_column_count(ref_->stmt());
163 }
164
165 // Verify that our enum matches sqlite's values.
166 static_assert(static_cast<int>(ColumnType::kInteger) == SQLITE_INTEGER,
167 "INTEGER mismatch");
168 static_assert(static_cast<int>(ColumnType::kFloat) == SQLITE_FLOAT,
169 "FLOAT mismatch");
170 static_assert(static_cast<int>(ColumnType::kText) == SQLITE_TEXT,
171 "TEXT mismatch");
172 static_assert(static_cast<int>(ColumnType::kBlob) == SQLITE_BLOB,
173 "BLOB mismatch");
174 static_assert(static_cast<int>(ColumnType::kNull) == SQLITE_NULL,
175 "NULL mismatch");
176
GetColumnType(int col) const177 ColumnType Statement::GetColumnType(int col) const {
178 return static_cast<enum ColumnType>(sqlite3_column_type(ref_->stmt(), col));
179 }
180
ColumnBool(int col) const181 bool Statement::ColumnBool(int col) const {
182 return static_cast<bool>(ColumnInt(col));
183 }
184
ColumnInt(int col) const185 int Statement::ColumnInt(int col) const {
186 if (!CheckValid())
187 return 0;
188 return sqlite3_column_int(ref_->stmt(), col);
189 }
190
ColumnInt64(int col) const191 int64_t Statement::ColumnInt64(int col) const {
192 if (!CheckValid())
193 return 0;
194 return sqlite3_column_int64(ref_->stmt(), col);
195 }
196
ColumnDouble(int col) const197 double Statement::ColumnDouble(int col) const {
198 if (!CheckValid())
199 return 0;
200 return sqlite3_column_double(ref_->stmt(), col);
201 }
202
ColumnString(int col) const203 std::string Statement::ColumnString(int col) const {
204 if (!CheckValid())
205 return std::string();
206
207 const char* str = reinterpret_cast<const char*>(
208 sqlite3_column_text(ref_->stmt(), col));
209 int len = sqlite3_column_bytes(ref_->stmt(), col);
210
211 std::string result;
212 if (str && len > 0)
213 result.assign(str, len);
214 return result;
215 }
216
ColumnString16(int col) const217 base::string16 Statement::ColumnString16(int col) const {
218 if (!CheckValid())
219 return base::string16();
220
221 std::string s = ColumnString(col);
222 return !s.empty() ? base::UTF8ToUTF16(s) : base::string16();
223 }
224
ColumnByteLength(int col) const225 int Statement::ColumnByteLength(int col) const {
226 if (!CheckValid())
227 return 0;
228 return sqlite3_column_bytes(ref_->stmt(), col);
229 }
230
ColumnBlob(int col) const231 const void* Statement::ColumnBlob(int col) const {
232 if (!CheckValid())
233 return nullptr;
234
235 return sqlite3_column_blob(ref_->stmt(), col);
236 }
237
ColumnBlobAsString(int col,std::string * blob) const238 bool Statement::ColumnBlobAsString(int col, std::string* blob) const {
239 if (!CheckValid())
240 return false;
241
242 const void* p = ColumnBlob(col);
243 size_t len = ColumnByteLength(col);
244 blob->resize(len);
245 if (blob->size() != len) {
246 return false;
247 }
248 blob->assign(reinterpret_cast<const char*>(p), len);
249 return true;
250 }
251
ColumnBlobAsString16(int col,base::string16 * val) const252 bool Statement::ColumnBlobAsString16(int col, base::string16* val) const {
253 if (!CheckValid())
254 return false;
255
256 const void* data = ColumnBlob(col);
257 size_t len = ColumnByteLength(col) / sizeof(base::char16);
258 val->resize(len);
259 if (val->size() != len)
260 return false;
261 val->assign(reinterpret_cast<const base::char16*>(data), len);
262 return true;
263 }
264
ColumnBlobAsVector(int col,std::vector<char> * val) const265 bool Statement::ColumnBlobAsVector(int col, std::vector<char>* val) const {
266 val->clear();
267
268 if (!CheckValid())
269 return false;
270
271 const void* data = sqlite3_column_blob(ref_->stmt(), col);
272 int len = sqlite3_column_bytes(ref_->stmt(), col);
273 if (data && len > 0) {
274 val->resize(len);
275 memcpy(&(*val)[0], data, len);
276 }
277 return true;
278 }
279
ColumnBlobAsVector(int col,std::vector<unsigned char> * val) const280 bool Statement::ColumnBlobAsVector(
281 int col,
282 std::vector<unsigned char>* val) const {
283 return ColumnBlobAsVector(col, reinterpret_cast< std::vector<char>* >(val));
284 }
285
GetSQLStatement()286 const char* Statement::GetSQLStatement() {
287 return sqlite3_sql(ref_->stmt());
288 }
289
CheckOk(int err) const290 bool Statement::CheckOk(int err) const {
291 // Binding to a non-existent variable is evidence of a serious error.
292 // TODO(gbillock,shess): make this invalidate the statement so it
293 // can't wreak havoc.
294 DCHECK_NE(err, SQLITE_RANGE) << "Bind value out of range";
295 return err == SQLITE_OK;
296 }
297
CheckError(int err)298 int Statement::CheckError(int err) {
299 // Please don't add DCHECKs here, OnSqliteError() already has them.
300 succeeded_ = (err == SQLITE_OK || err == SQLITE_ROW || err == SQLITE_DONE);
301 if (!succeeded_ && ref_.get() && ref_->database())
302 return ref_->database()->OnSqliteError(err, this, nullptr);
303 return err;
304 }
305
306 } // namespace sql
307