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