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