• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 "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"
11 
12 namespace sql {
13 
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.
Statement()17 Statement::Statement()
18     : ref_(new Connection::StatementRef(NULL, NULL, false)),
19       stepped_(false),
20       succeeded_(false) {
21 }
22 
Statement(scoped_refptr<Connection::StatementRef> ref)23 Statement::Statement(scoped_refptr<Connection::StatementRef> ref)
24     : ref_(ref),
25       stepped_(false),
26       succeeded_(false) {
27 }
28 
~Statement()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);
34 }
35 
Assign(scoped_refptr<Connection::StatementRef> ref)36 void Statement::Assign(scoped_refptr<Connection::StatementRef> ref) {
37   Reset(true);
38   ref_ = ref;
39 }
40 
Clear()41 void Statement::Clear() {
42   Assign(new Connection::StatementRef(NULL, NULL, false));
43   succeeded_ = false;
44 }
45 
CheckValid() const46 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();
52 }
53 
Run()54 bool Statement::Run() {
55   DCHECK(!stepped_);
56   ref_->AssertIOAllowed();
57   if (!CheckValid())
58     return false;
59 
60   stepped_ = true;
61   return CheckError(sqlite3_step(ref_->stmt())) == SQLITE_DONE;
62 }
63 
Step()64 bool Statement::Step() {
65   ref_->AssertIOAllowed();
66   if (!CheckValid())
67     return false;
68 
69   stepped_ = true;
70   return CheckError(sqlite3_step(ref_->stmt())) == SQLITE_ROW;
71 }
72 
Reset(bool clear_bound_vars)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());
82   }
83 
84   succeeded_ = false;
85   stepped_ = false;
86 }
87 
Succeeded() const88 bool Statement::Succeeded() const {
89   if (!is_valid())
90     return false;
91 
92   return succeeded_;
93 }
94 
BindNull(int col)95 bool Statement::BindNull(int col) {
96   DCHECK(!stepped_);
97   if (!is_valid())
98     return false;
99 
100   return CheckOk(sqlite3_bind_null(ref_->stmt(), col + 1));
101 }
102 
BindBool(int col,bool val)103 bool Statement::BindBool(int col, bool val) {
104   return BindInt(col, val ? 1 : 0);
105 }
106 
BindInt(int col,int val)107 bool Statement::BindInt(int col, int val) {
108   DCHECK(!stepped_);
109   if (!is_valid())
110     return false;
111 
112   return CheckOk(sqlite3_bind_int(ref_->stmt(), col + 1, val));
113 }
114 
BindInt64(int col,int64 val)115 bool Statement::BindInt64(int col, int64 val) {
116   DCHECK(!stepped_);
117   if (!is_valid())
118     return false;
119 
120   return CheckOk(sqlite3_bind_int64(ref_->stmt(), col + 1, val));
121 }
122 
BindDouble(int col,double val)123 bool Statement::BindDouble(int col, double val) {
124   DCHECK(!stepped_);
125   if (!is_valid())
126     return false;
127 
128   return 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   if (!is_valid())
134     return false;
135 
136   return CheckOk(
137       sqlite3_bind_text(ref_->stmt(), col + 1, val, -1, SQLITE_TRANSIENT));
138 }
139 
BindString(int col,const std::string & val)140 bool Statement::BindString(int col, const std::string& val) {
141   DCHECK(!stepped_);
142   if (!is_valid())
143     return false;
144 
145   return CheckOk(sqlite3_bind_text(ref_->stmt(),
146                                    col + 1,
147                                    val.data(),
148                                    val.size(),
149                                    SQLITE_TRANSIENT));
150 }
151 
BindString16(int col,const base::string16 & value)152 bool Statement::BindString16(int col, const base::string16& value) {
153   return BindString(col, base::UTF16ToUTF8(value));
154 }
155 
BindBlob(int col,const void * val,int val_len)156 bool Statement::BindBlob(int col, const void* val, int val_len) {
157   DCHECK(!stepped_);
158   if (!is_valid())
159     return false;
160 
161   return CheckOk(
162       sqlite3_bind_blob(ref_->stmt(), col + 1, val, val_len, SQLITE_TRANSIENT));
163 }
164 
ColumnCount() const165 int Statement::ColumnCount() const {
166   if (!is_valid())
167     return 0;
168 
169   return sqlite3_column_count(ref_->stmt());
170 }
171 
ColumnType(int col) const172 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);
179 
180   return static_cast<ColType>(sqlite3_column_type(ref_->stmt(), col));
181 }
182 
DeclaredColumnType(int col) const183 ColType Statement::DeclaredColumnType(int col) const {
184   std::string column_type(sqlite3_column_decltype(ref_->stmt(), col));
185   StringToLowerASCII(&column_type);
186 
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;
195 
196   return COLUMN_TYPE_NULL;
197 }
198 
ColumnBool(int col) const199 bool Statement::ColumnBool(int col) const {
200   return !!ColumnInt(col);
201 }
202 
ColumnInt(int col) const203 int Statement::ColumnInt(int col) const {
204   if (!CheckValid())
205     return 0;
206 
207   return sqlite3_column_int(ref_->stmt(), col);
208 }
209 
ColumnInt64(int col) const210 int64 Statement::ColumnInt64(int col) const {
211   if (!CheckValid())
212     return 0;
213 
214   return sqlite3_column_int64(ref_->stmt(), col);
215 }
216 
ColumnDouble(int col) const217 double Statement::ColumnDouble(int col) const {
218   if (!CheckValid())
219     return 0;
220 
221   return sqlite3_column_double(ref_->stmt(), col);
222 }
223 
ColumnString(int col) const224 std::string Statement::ColumnString(int col) const {
225   if (!CheckValid())
226     return std::string();
227 
228   const char* str = reinterpret_cast<const char*>(
229       sqlite3_column_text(ref_->stmt(), col));
230   int len = sqlite3_column_bytes(ref_->stmt(), col);
231 
232   std::string result;
233   if (str && len > 0)
234     result.assign(str, len);
235   return result;
236 }
237 
ColumnString16(int col) const238 base::string16 Statement::ColumnString16(int col) const {
239   if (!CheckValid())
240     return base::string16();
241 
242   std::string s = ColumnString(col);
243   return !s.empty() ? base::UTF8ToUTF16(s) : base::string16();
244 }
245 
ColumnByteLength(int col) const246 int Statement::ColumnByteLength(int col) const {
247   if (!CheckValid())
248     return 0;
249 
250   return sqlite3_column_bytes(ref_->stmt(), col);
251 }
252 
ColumnBlob(int col) const253 const void* Statement::ColumnBlob(int col) const {
254   if (!CheckValid())
255     return NULL;
256 
257   return sqlite3_column_blob(ref_->stmt(), col);
258 }
259 
ColumnBlobAsString(int col,std::string * blob)260 bool Statement::ColumnBlobAsString(int col, std::string* blob) {
261   if (!CheckValid())
262     return false;
263 
264   const void* p = ColumnBlob(col);
265   size_t len = ColumnByteLength(col);
266   blob->resize(len);
267   if (blob->size() != len) {
268     return false;
269   }
270   blob->assign(reinterpret_cast<const char*>(p), len);
271   return true;
272 }
273 
ColumnBlobAsString16(int col,base::string16 * val) const274 bool Statement::ColumnBlobAsString16(int col, base::string16* val) const {
275   if (!CheckValid())
276     return false;
277 
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;
285 }
286 
ColumnBlobAsVector(int col,std::vector<char> * val) const287 bool Statement::ColumnBlobAsVector(int col, std::vector<char>* val) const {
288   val->clear();
289 
290   if (!CheckValid())
291     return false;
292 
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);
298   }
299   return true;
300 }
301 
ColumnBlobAsVector(int col,std::vector<unsigned char> * val) const302 bool Statement::ColumnBlobAsVector(
303     int col,
304     std::vector<unsigned char>* val) const {
305   return ColumnBlobAsVector(col, reinterpret_cast< std::vector<char>* >(val));
306 }
307 
GetSQLStatement()308 const char* Statement::GetSQLStatement() {
309   return sqlite3_sql(ref_->stmt());
310 }
311 
CheckOk(int err) const312 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;
319 }
320 
CheckError(int err)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;
327 }
328 
329 }  // namespace sql
330