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