• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 // Copyright (c) 2010 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 "app/sql/statement.h"
6 
7 #include "base/logging.h"
8 #include "base/utf_string_conversions.h"
9 #ifdef ANDROID
10 #include "sqlite3.h"
11 #else
12 #include "third_party/sqlite/sqlite3.h"
13 #endif
14 
15 namespace sql {
16 
17 // This empty constructor initializes our reference with an empty one so that
18 // we don't have to NULL-check the ref_ to see if the statement is valid: we
19 // only have to check the ref's validity bit.
Statement()20 Statement::Statement()
21     : ref_(new Connection::StatementRef),
22       succeeded_(false) {
23 }
24 
Statement(scoped_refptr<Connection::StatementRef> ref)25 Statement::Statement(scoped_refptr<Connection::StatementRef> ref)
26     : ref_(ref),
27       succeeded_(false) {
28 }
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();
35 }
36 
Assign(scoped_refptr<Connection::StatementRef> ref)37 void Statement::Assign(scoped_refptr<Connection::StatementRef> ref) {
38   Reset();
39   ref_ = ref;
40 }
41 
Run()42 bool Statement::Run() {
43   if (!is_valid())
44     return false;
45   return CheckError(sqlite3_step(ref_->stmt())) == SQLITE_DONE;
46 }
47 
Step()48 bool Statement::Step() {
49   if (!is_valid())
50     return false;
51   return CheckError(sqlite3_step(ref_->stmt())) == SQLITE_ROW;
52 }
53 
Reset()54 void Statement::Reset() {
55   if (is_valid()) {
56     // We don't call CheckError() here because sqlite3_reset() returns
57     // the last error that Step() caused thereby generating a second
58     // spurious error callback.
59     sqlite3_clear_bindings(ref_->stmt());
60     sqlite3_reset(ref_->stmt());
61   }
62   succeeded_ = false;
63 }
64 
Succeeded() const65 bool Statement::Succeeded() const {
66   if (!is_valid())
67     return false;
68   return succeeded_;
69 }
70 
BindNull(int col)71 bool Statement::BindNull(int col) {
72   if (is_valid()) {
73     int err = CheckError(sqlite3_bind_null(ref_->stmt(), col + 1));
74     return err == SQLITE_OK;
75   }
76   return false;
77 }
78 
BindBool(int col,bool val)79 bool Statement::BindBool(int col, bool val) {
80   return BindInt(col, val ? 1 : 0);
81 }
82 
BindInt(int col,int val)83 bool Statement::BindInt(int col, int val) {
84   if (is_valid()) {
85     int err = CheckError(sqlite3_bind_int(ref_->stmt(), col + 1, val));
86     return err == SQLITE_OK;
87   }
88   return false;
89 }
90 
BindInt64(int col,int64 val)91 bool Statement::BindInt64(int col, int64 val) {
92   if (is_valid()) {
93     int err = CheckError(sqlite3_bind_int64(ref_->stmt(), col + 1, val));
94     return err == SQLITE_OK;
95   }
96   return false;
97 }
98 
BindDouble(int col,double val)99 bool Statement::BindDouble(int col, double val) {
100   if (is_valid()) {
101     int err = CheckError(sqlite3_bind_double(ref_->stmt(), col + 1, val));
102     return err == SQLITE_OK;
103   }
104   return false;
105 }
106 
BindCString(int col,const char * val)107 bool Statement::BindCString(int col, const char* val) {
108   if (is_valid()) {
109     int err = CheckError(sqlite3_bind_text(ref_->stmt(), col + 1, val, -1,
110                          SQLITE_TRANSIENT));
111     return err == SQLITE_OK;
112   }
113   return false;
114 }
115 
BindString(int col,const std::string & val)116 bool Statement::BindString(int col, const std::string& val) {
117   if (is_valid()) {
118     int err = CheckError(sqlite3_bind_text(ref_->stmt(), col + 1, val.data(),
119                                            val.size(), SQLITE_TRANSIENT));
120     return err == SQLITE_OK;
121   }
122   return false;
123 }
124 
BindString16(int col,const string16 & value)125 bool Statement::BindString16(int col, const string16& value) {
126   return BindString(col, UTF16ToUTF8(value));
127 }
128 
BindBlob(int col,const void * val,int val_len)129 bool Statement::BindBlob(int col, const void* val, int val_len) {
130   if (is_valid()) {
131     int err = CheckError(sqlite3_bind_blob(ref_->stmt(), col + 1,
132                          val, val_len, SQLITE_TRANSIENT));
133     return err == SQLITE_OK;
134   }
135   return false;
136 }
137 
ColumnCount() const138 int Statement::ColumnCount() const {
139   if (!is_valid()) {
140     NOTREACHED();
141     return 0;
142   }
143   return sqlite3_column_count(ref_->stmt());
144 }
145 
ColumnType(int col) const146 ColType Statement::ColumnType(int col) const {
147   // Verify that our enum matches sqlite's values.
148   COMPILE_ASSERT(COLUMN_TYPE_INTEGER == SQLITE_INTEGER, integer_no_match);
149   COMPILE_ASSERT(COLUMN_TYPE_FLOAT == SQLITE_FLOAT, float_no_match);
150   COMPILE_ASSERT(COLUMN_TYPE_TEXT == SQLITE_TEXT, integer_no_match);
151   COMPILE_ASSERT(COLUMN_TYPE_BLOB == SQLITE_BLOB, blob_no_match);
152   COMPILE_ASSERT(COLUMN_TYPE_NULL == SQLITE_NULL, null_no_match);
153 
154   return static_cast<ColType>(sqlite3_column_type(ref_->stmt(), col));
155 }
156 
ColumnBool(int col) const157 bool Statement::ColumnBool(int col) const {
158   return !!ColumnInt(col);
159 }
160 
ColumnInt(int col) const161 int Statement::ColumnInt(int col) const {
162   if (!is_valid()) {
163     NOTREACHED();
164     return 0;
165   }
166   return sqlite3_column_int(ref_->stmt(), col);
167 }
168 
ColumnInt64(int col) const169 int64 Statement::ColumnInt64(int col) const {
170   if (!is_valid()) {
171     NOTREACHED();
172     return 0;
173   }
174   return sqlite3_column_int64(ref_->stmt(), col);
175 }
176 
ColumnDouble(int col) const177 double Statement::ColumnDouble(int col) const {
178   if (!is_valid()) {
179     NOTREACHED();
180     return 0;
181   }
182   return sqlite3_column_double(ref_->stmt(), col);
183 }
184 
ColumnString(int col) const185 std::string Statement::ColumnString(int col) const {
186   if (!is_valid()) {
187     NOTREACHED();
188     return "";
189   }
190   const char* str = reinterpret_cast<const char*>(
191       sqlite3_column_text(ref_->stmt(), col));
192   int len = sqlite3_column_bytes(ref_->stmt(), col);
193 
194   std::string result;
195   if (str && len > 0)
196     result.assign(str, len);
197   return result;
198 }
199 
ColumnString16(int col) const200 string16 Statement::ColumnString16(int col) const {
201   if (!is_valid()) {
202     NOTREACHED();
203     return string16();
204   }
205   std::string s = ColumnString(col);
206   return !s.empty() ? UTF8ToUTF16(s) : string16();
207 }
208 
ColumnByteLength(int col) const209 int Statement::ColumnByteLength(int col) const {
210   if (!is_valid()) {
211     NOTREACHED();
212     return 0;
213   }
214   return sqlite3_column_bytes(ref_->stmt(), col);
215 }
216 
ColumnBlob(int col) const217 const void* Statement::ColumnBlob(int col) const {
218   if (!is_valid()) {
219     NOTREACHED();
220     return NULL;
221   }
222 
223   return sqlite3_column_blob(ref_->stmt(), col);
224 }
225 
ColumnBlobAsString(int col,std::string * blob)226 bool Statement::ColumnBlobAsString(int col, std::string* blob) {
227   if (!is_valid()) {
228     NOTREACHED();
229     return false;
230   }
231   const void* p = ColumnBlob(col);
232   size_t len = ColumnByteLength(col);
233   blob->resize(len);
234   if (blob->size() != len) {
235     return false;
236   }
237   blob->assign(reinterpret_cast<const char*>(p), len);
238   return true;
239 }
240 
ColumnBlobAsVector(int col,std::vector<char> * val) const241 void Statement::ColumnBlobAsVector(int col, std::vector<char>* val) const {
242   val->clear();
243   if (!is_valid()) {
244     NOTREACHED();
245     return;
246   }
247 
248   const void* data = sqlite3_column_blob(ref_->stmt(), col);
249   int len = sqlite3_column_bytes(ref_->stmt(), col);
250   if (data && len > 0) {
251     val->resize(len);
252     memcpy(&(*val)[0], data, len);
253   }
254 }
255 
ColumnBlobAsVector(int col,std::vector<unsigned char> * val) const256 void Statement::ColumnBlobAsVector(
257     int col,
258     std::vector<unsigned char>* val) const {
259   ColumnBlobAsVector(col, reinterpret_cast< std::vector<char>* >(val));
260 }
261 
GetSQLStatement()262 const char* Statement::GetSQLStatement() {
263   return sqlite3_sql(ref_->stmt());
264 }
265 
CheckError(int err)266 int Statement::CheckError(int err) {
267   // Please don't add DCHECKs here, OnSqliteError() already has them.
268   succeeded_ = (err == SQLITE_OK || err == SQLITE_ROW || err == SQLITE_DONE);
269   if (!succeeded_ && is_valid())
270     return ref_->connection()->OnSqliteError(err, this);
271   return err;
272 }
273 
274 }  // namespace sql
275