OLD | NEW |
1 // Copyright (c) 2011 The Chromium Authors. All rights reserved. | 1 // Copyright (c) 2011 The Chromium Authors. All rights reserved. |
2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
4 | 4 |
5 #include "sql/statement.h" | 5 #include "sql/statement.h" |
6 | 6 |
7 #include "base/logging.h" | 7 #include "base/logging.h" |
8 #include "base/utf_string_conversions.h" | 8 #include "base/utf_string_conversions.h" |
9 #include "third_party/sqlite/sqlite3.h" | 9 #include "third_party/sqlite/sqlite3.h" |
10 | 10 |
(...skipping 17 matching lines...) Expand all Loading... |
28 // one statement active for a given sqlite3_stmt at any time, so this won't | 28 // one statement active for a given sqlite3_stmt at any time, so this won't |
29 // mess with anything. | 29 // mess with anything. |
30 Reset(); | 30 Reset(); |
31 } | 31 } |
32 | 32 |
33 void Statement::Assign(scoped_refptr<Connection::StatementRef> ref) { | 33 void Statement::Assign(scoped_refptr<Connection::StatementRef> ref) { |
34 Reset(); | 34 Reset(); |
35 ref_ = ref; | 35 ref_ = ref; |
36 } | 36 } |
37 | 37 |
| 38 bool Statement::CheckValid() const { |
| 39 if (!is_valid()) |
| 40 DLOG(FATAL) << "Cannot call mutating statements on an invalid statement."; |
| 41 return is_valid(); |
| 42 } |
| 43 |
38 bool Statement::Run() { | 44 bool Statement::Run() { |
39 if (!is_valid()) | 45 if (!CheckValid()) |
40 return false; | 46 return false; |
| 47 |
41 return CheckError(sqlite3_step(ref_->stmt())) == SQLITE_DONE; | 48 return CheckError(sqlite3_step(ref_->stmt())) == SQLITE_DONE; |
42 } | 49 } |
43 | 50 |
44 bool Statement::Step() { | 51 bool Statement::Step() { |
45 if (!is_valid()) | 52 if (!CheckValid()) |
46 return false; | 53 return false; |
| 54 |
47 return CheckError(sqlite3_step(ref_->stmt())) == SQLITE_ROW; | 55 return CheckError(sqlite3_step(ref_->stmt())) == SQLITE_ROW; |
48 } | 56 } |
49 | 57 |
50 void Statement::Reset() { | 58 void Statement::Reset() { |
51 if (is_valid()) { | 59 if (is_valid()) { |
52 // We don't call CheckError() here because sqlite3_reset() returns | 60 // We don't call CheckError() here because sqlite3_reset() returns |
53 // the last error that Step() caused thereby generating a second | 61 // the last error that Step() caused thereby generating a second |
54 // spurious error callback. | 62 // spurious error callback. |
55 sqlite3_clear_bindings(ref_->stmt()); | 63 sqlite3_clear_bindings(ref_->stmt()); |
56 sqlite3_reset(ref_->stmt()); | 64 sqlite3_reset(ref_->stmt()); |
57 } | 65 } |
| 66 |
58 succeeded_ = false; | 67 succeeded_ = false; |
59 } | 68 } |
60 | 69 |
61 bool Statement::Succeeded() const { | 70 bool Statement::Succeeded() const { |
62 if (!is_valid()) | 71 if (!is_valid()) |
63 return false; | 72 return false; |
| 73 |
64 return succeeded_; | 74 return succeeded_; |
65 } | 75 } |
66 | 76 |
67 bool Statement::BindNull(int col) { | 77 bool Statement::BindNull(int col) { |
68 if (is_valid()) { | 78 if (!is_valid()) |
69 int err = CheckError(sqlite3_bind_null(ref_->stmt(), col + 1)); | 79 return false; |
70 return err == SQLITE_OK; | 80 |
71 } | 81 return CheckOk(sqlite3_bind_null(ref_->stmt(), col + 1)); |
72 return false; | |
73 } | 82 } |
74 | 83 |
75 bool Statement::BindBool(int col, bool val) { | 84 bool Statement::BindBool(int col, bool val) { |
76 return BindInt(col, val ? 1 : 0); | 85 return BindInt(col, val ? 1 : 0); |
77 } | 86 } |
78 | 87 |
79 bool Statement::BindInt(int col, int val) { | 88 bool Statement::BindInt(int col, int val) { |
80 if (is_valid()) { | 89 if (!is_valid()) |
81 int err = CheckError(sqlite3_bind_int(ref_->stmt(), col + 1, val)); | 90 return false; |
82 return err == SQLITE_OK; | 91 |
83 } | 92 return CheckOk(sqlite3_bind_int(ref_->stmt(), col + 1, val)); |
84 return false; | |
85 } | 93 } |
86 | 94 |
87 bool Statement::BindInt64(int col, int64 val) { | 95 bool Statement::BindInt64(int col, int64 val) { |
88 if (is_valid()) { | 96 if (!is_valid()) |
89 int err = CheckError(sqlite3_bind_int64(ref_->stmt(), col + 1, val)); | 97 return false; |
90 return err == SQLITE_OK; | 98 |
91 } | 99 return CheckOk(sqlite3_bind_int64(ref_->stmt(), col + 1, val)); |
92 return false; | |
93 } | 100 } |
94 | 101 |
95 bool Statement::BindDouble(int col, double val) { | 102 bool Statement::BindDouble(int col, double val) { |
96 if (is_valid()) { | 103 if (!is_valid()) |
97 int err = CheckError(sqlite3_bind_double(ref_->stmt(), col + 1, val)); | 104 return false; |
98 return err == SQLITE_OK; | 105 |
99 } | 106 return CheckOk(sqlite3_bind_double(ref_->stmt(), col + 1, val)); |
100 return false; | |
101 } | 107 } |
102 | 108 |
103 bool Statement::BindCString(int col, const char* val) { | 109 bool Statement::BindCString(int col, const char* val) { |
104 if (is_valid()) { | 110 if (!is_valid()) |
105 int err = CheckError(sqlite3_bind_text(ref_->stmt(), col + 1, val, -1, | 111 return false; |
106 SQLITE_TRANSIENT)); | 112 |
107 return err == SQLITE_OK; | 113 return CheckOk( |
108 } | 114 sqlite3_bind_text(ref_->stmt(), col + 1, val, -1, SQLITE_TRANSIENT)); |
109 return false; | |
110 } | 115 } |
111 | 116 |
112 bool Statement::BindString(int col, const std::string& val) { | 117 bool Statement::BindString(int col, const std::string& val) { |
113 if (is_valid()) { | 118 if (!is_valid()) |
114 int err = CheckError(sqlite3_bind_text(ref_->stmt(), col + 1, val.data(), | 119 return false; |
115 val.size(), SQLITE_TRANSIENT)); | 120 |
116 return err == SQLITE_OK; | 121 return CheckOk(sqlite3_bind_text(ref_->stmt(), |
117 } | 122 col + 1, |
118 return false; | 123 val.data(), |
| 124 val.size(), |
| 125 SQLITE_TRANSIENT)); |
119 } | 126 } |
120 | 127 |
121 bool Statement::BindString16(int col, const string16& value) { | 128 bool Statement::BindString16(int col, const string16& value) { |
122 return BindString(col, UTF16ToUTF8(value)); | 129 return BindString(col, UTF16ToUTF8(value)); |
123 } | 130 } |
124 | 131 |
125 bool Statement::BindBlob(int col, const void* val, int val_len) { | 132 bool Statement::BindBlob(int col, const void* val, int val_len) { |
126 if (is_valid()) { | 133 if (!is_valid()) |
127 int err = CheckError(sqlite3_bind_blob(ref_->stmt(), col + 1, | 134 return false; |
128 val, val_len, SQLITE_TRANSIENT)); | 135 |
129 return err == SQLITE_OK; | 136 return CheckOk( |
130 } | 137 sqlite3_bind_blob(ref_->stmt(), col + 1, val, val_len, SQLITE_TRANSIENT)); |
131 return false; | |
132 } | 138 } |
133 | 139 |
134 int Statement::ColumnCount() const { | 140 int Statement::ColumnCount() const { |
135 if (!is_valid()) { | 141 if (!is_valid()) |
136 NOTREACHED(); | |
137 return 0; | 142 return 0; |
138 } | 143 |
139 return sqlite3_column_count(ref_->stmt()); | 144 return sqlite3_column_count(ref_->stmt()); |
140 } | 145 } |
141 | 146 |
142 ColType Statement::ColumnType(int col) const { | 147 ColType Statement::ColumnType(int col) const { |
143 // Verify that our enum matches sqlite's values. | 148 // Verify that our enum matches sqlite's values. |
144 COMPILE_ASSERT(COLUMN_TYPE_INTEGER == SQLITE_INTEGER, integer_no_match); | 149 COMPILE_ASSERT(COLUMN_TYPE_INTEGER == SQLITE_INTEGER, integer_no_match); |
145 COMPILE_ASSERT(COLUMN_TYPE_FLOAT == SQLITE_FLOAT, float_no_match); | 150 COMPILE_ASSERT(COLUMN_TYPE_FLOAT == SQLITE_FLOAT, float_no_match); |
146 COMPILE_ASSERT(COLUMN_TYPE_TEXT == SQLITE_TEXT, integer_no_match); | 151 COMPILE_ASSERT(COLUMN_TYPE_TEXT == SQLITE_TEXT, integer_no_match); |
147 COMPILE_ASSERT(COLUMN_TYPE_BLOB == SQLITE_BLOB, blob_no_match); | 152 COMPILE_ASSERT(COLUMN_TYPE_BLOB == SQLITE_BLOB, blob_no_match); |
148 COMPILE_ASSERT(COLUMN_TYPE_NULL == SQLITE_NULL, null_no_match); | 153 COMPILE_ASSERT(COLUMN_TYPE_NULL == SQLITE_NULL, null_no_match); |
149 | 154 |
150 return static_cast<ColType>(sqlite3_column_type(ref_->stmt(), col)); | 155 return static_cast<ColType>(sqlite3_column_type(ref_->stmt(), col)); |
151 } | 156 } |
152 | 157 |
153 bool Statement::ColumnBool(int col) const { | 158 bool Statement::ColumnBool(int col) const { |
154 return !!ColumnInt(col); | 159 return !!ColumnInt(col); |
155 } | 160 } |
156 | 161 |
157 int Statement::ColumnInt(int col) const { | 162 int Statement::ColumnInt(int col) const { |
158 if (!is_valid()) { | 163 if (!CheckValid()) |
159 NOTREACHED(); | |
160 return 0; | 164 return 0; |
161 } | 165 |
162 return sqlite3_column_int(ref_->stmt(), col); | 166 return sqlite3_column_int(ref_->stmt(), col); |
163 } | 167 } |
164 | 168 |
165 int64 Statement::ColumnInt64(int col) const { | 169 int64 Statement::ColumnInt64(int col) const { |
166 if (!is_valid()) { | 170 if (!CheckValid()) |
167 NOTREACHED(); | |
168 return 0; | 171 return 0; |
169 } | 172 |
170 return sqlite3_column_int64(ref_->stmt(), col); | 173 return sqlite3_column_int64(ref_->stmt(), col); |
171 } | 174 } |
172 | 175 |
173 double Statement::ColumnDouble(int col) const { | 176 double Statement::ColumnDouble(int col) const { |
174 if (!is_valid()) { | 177 if (!CheckValid()) |
175 NOTREACHED(); | |
176 return 0; | 178 return 0; |
177 } | 179 |
178 return sqlite3_column_double(ref_->stmt(), col); | 180 return sqlite3_column_double(ref_->stmt(), col); |
179 } | 181 } |
180 | 182 |
181 std::string Statement::ColumnString(int col) const { | 183 std::string Statement::ColumnString(int col) const { |
182 if (!is_valid()) { | 184 if (!CheckValid()) |
183 NOTREACHED(); | |
184 return ""; | 185 return ""; |
185 } | 186 |
186 const char* str = reinterpret_cast<const char*>( | 187 const char* str = reinterpret_cast<const char*>( |
187 sqlite3_column_text(ref_->stmt(), col)); | 188 sqlite3_column_text(ref_->stmt(), col)); |
188 int len = sqlite3_column_bytes(ref_->stmt(), col); | 189 int len = sqlite3_column_bytes(ref_->stmt(), col); |
189 | 190 |
190 std::string result; | 191 std::string result; |
191 if (str && len > 0) | 192 if (str && len > 0) |
192 result.assign(str, len); | 193 result.assign(str, len); |
193 return result; | 194 return result; |
194 } | 195 } |
195 | 196 |
196 string16 Statement::ColumnString16(int col) const { | 197 string16 Statement::ColumnString16(int col) const { |
197 if (!is_valid()) { | 198 if (!CheckValid()) |
198 NOTREACHED(); | |
199 return string16(); | 199 return string16(); |
200 } | 200 |
201 std::string s = ColumnString(col); | 201 std::string s = ColumnString(col); |
202 return !s.empty() ? UTF8ToUTF16(s) : string16(); | 202 return !s.empty() ? UTF8ToUTF16(s) : string16(); |
203 } | 203 } |
204 | 204 |
205 int Statement::ColumnByteLength(int col) const { | 205 int Statement::ColumnByteLength(int col) const { |
206 if (!is_valid()) { | 206 if (!CheckValid()) |
207 NOTREACHED(); | |
208 return 0; | 207 return 0; |
209 } | 208 |
210 return sqlite3_column_bytes(ref_->stmt(), col); | 209 return sqlite3_column_bytes(ref_->stmt(), col); |
211 } | 210 } |
212 | 211 |
213 const void* Statement::ColumnBlob(int col) const { | 212 const void* Statement::ColumnBlob(int col) const { |
214 if (!is_valid()) { | 213 if (!CheckValid()) |
215 NOTREACHED(); | |
216 return NULL; | 214 return NULL; |
217 } | |
218 | 215 |
219 return sqlite3_column_blob(ref_->stmt(), col); | 216 return sqlite3_column_blob(ref_->stmt(), col); |
220 } | 217 } |
221 | 218 |
222 bool Statement::ColumnBlobAsString(int col, std::string* blob) { | 219 bool Statement::ColumnBlobAsString(int col, std::string* blob) { |
223 if (!is_valid()) { | 220 if (!CheckValid()) |
224 NOTREACHED(); | |
225 return false; | 221 return false; |
226 } | 222 |
227 const void* p = ColumnBlob(col); | 223 const void* p = ColumnBlob(col); |
228 size_t len = ColumnByteLength(col); | 224 size_t len = ColumnByteLength(col); |
229 blob->resize(len); | 225 blob->resize(len); |
230 if (blob->size() != len) { | 226 if (blob->size() != len) { |
231 return false; | 227 return false; |
232 } | 228 } |
233 blob->assign(reinterpret_cast<const char*>(p), len); | 229 blob->assign(reinterpret_cast<const char*>(p), len); |
234 return true; | 230 return true; |
235 } | 231 } |
236 | 232 |
237 void Statement::ColumnBlobAsVector(int col, std::vector<char>* val) const { | 233 bool Statement::ColumnBlobAsVector(int col, std::vector<char>* val) const { |
238 val->clear(); | 234 val->clear(); |
239 if (!is_valid()) { | 235 |
240 NOTREACHED(); | 236 if (!CheckValid()) |
241 return; | 237 return false; |
242 } | |
243 | 238 |
244 const void* data = sqlite3_column_blob(ref_->stmt(), col); | 239 const void* data = sqlite3_column_blob(ref_->stmt(), col); |
245 int len = sqlite3_column_bytes(ref_->stmt(), col); | 240 int len = sqlite3_column_bytes(ref_->stmt(), col); |
246 if (data && len > 0) { | 241 if (data && len > 0) { |
247 val->resize(len); | 242 val->resize(len); |
248 memcpy(&(*val)[0], data, len); | 243 memcpy(&(*val)[0], data, len); |
249 } | 244 } |
| 245 return true; |
250 } | 246 } |
251 | 247 |
252 void Statement::ColumnBlobAsVector( | 248 bool Statement::ColumnBlobAsVector( |
253 int col, | 249 int col, |
254 std::vector<unsigned char>* val) const { | 250 std::vector<unsigned char>* val) const { |
255 ColumnBlobAsVector(col, reinterpret_cast< std::vector<char>* >(val)); | 251 return ColumnBlobAsVector(col, reinterpret_cast< std::vector<char>* >(val)); |
256 } | 252 } |
257 | 253 |
258 const char* Statement::GetSQLStatement() { | 254 const char* Statement::GetSQLStatement() { |
259 return sqlite3_sql(ref_->stmt()); | 255 return sqlite3_sql(ref_->stmt()); |
260 } | 256 } |
261 | 257 |
| 258 bool Statement::CheckOk(int err) const { |
| 259 return err == SQLITE_OK; |
| 260 } |
| 261 |
262 int Statement::CheckError(int err) { | 262 int Statement::CheckError(int err) { |
263 // Please don't add DCHECKs here, OnSqliteError() already has them. | 263 // Please don't add DCHECKs here, OnSqliteError() already has them. |
264 succeeded_ = (err == SQLITE_OK || err == SQLITE_ROW || err == SQLITE_DONE); | 264 succeeded_ = (err == SQLITE_OK || err == SQLITE_ROW || err == SQLITE_DONE); |
265 if (!succeeded_ && is_valid()) | 265 if (!succeeded_ && is_valid()) |
266 return ref_->connection()->OnSqliteError(err, this); | 266 return ref_->connection()->OnSqliteError(err, this); |
267 return err; | 267 return err; |
268 } | 268 } |
269 | 269 |
270 } // namespace sql | 270 } // namespace sql |
OLD | NEW |