Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(154)

Side by Side Diff: sql/statement.cc

Issue 40733003: [sql] Complain about statement mutations after stepping has started. (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: Created 7 years, 1 month ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
« no previous file with comments | « sql/statement.h ('k') | no next file » | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. 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 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/strings/string_util.h" 8 #include "base/strings/string_util.h"
9 #include "base/strings/utf_string_conversions.h" 9 #include "base/strings/utf_string_conversions.h"
10 #include "third_party/sqlite/sqlite3.h" 10 #include "third_party/sqlite/sqlite3.h"
11 11
12 namespace sql { 12 namespace sql {
13 13
14 // This empty constructor initializes our reference with an empty one so that 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 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. 16 // only have to check the ref's validity bit.
17 Statement::Statement() 17 Statement::Statement()
18 : ref_(new Connection::StatementRef(NULL, NULL, false)), 18 : ref_(new Connection::StatementRef(NULL, NULL, false)),
19 stepped_(false),
19 succeeded_(false) { 20 succeeded_(false) {
20 } 21 }
21 22
22 Statement::Statement(scoped_refptr<Connection::StatementRef> ref) 23 Statement::Statement(scoped_refptr<Connection::StatementRef> ref)
23 : ref_(ref), 24 : ref_(ref),
25 stepped_(false),
24 succeeded_(false) { 26 succeeded_(false) {
25 } 27 }
26 28
27 Statement::~Statement() { 29 Statement::~Statement() {
28 // Free the resources associated with this statement. We assume there's only 30 // Free the resources associated with this statement. We assume there's only
29 // one statement active for a given sqlite3_stmt at any time, so this won't 31 // one statement active for a given sqlite3_stmt at any time, so this won't
30 // mess with anything. 32 // mess with anything.
31 Reset(true); 33 Reset(true);
32 } 34 }
33 35
34 void Statement::Assign(scoped_refptr<Connection::StatementRef> ref) { 36 void Statement::Assign(scoped_refptr<Connection::StatementRef> ref) {
35 Reset(true); 37 Reset(true);
36 ref_ = ref; 38 ref_ = ref;
37 } 39 }
38 40
39 void Statement::Clear() { 41 void Statement::Clear() {
40 Assign(new Connection::StatementRef(NULL, NULL, false)); 42 Assign(new Connection::StatementRef(NULL, NULL, false));
41 succeeded_ = false; 43 succeeded_ = false;
42 } 44 }
43 45
44 bool Statement::CheckValid() const { 46 bool Statement::CheckValid() const {
45 // Allow operations to fail silently if a statement was invalidated 47 // Allow operations to fail silently if a statement was invalidated
46 // because the database was closed by an error handler. 48 // because the database was closed by an error handler.
47 DLOG_IF(FATAL, !ref_->was_valid()) 49 DLOG_IF(FATAL, !ref_->was_valid())
48 << "Cannot call mutating statements on an invalid statement."; 50 << "Cannot call mutating statements on an invalid statement.";
49 return is_valid(); 51 return is_valid();
50 } 52 }
51 53
52 bool Statement::Run() { 54 bool Statement::Run() {
55 DCHECK(!stepped_);
53 ref_->AssertIOAllowed(); 56 ref_->AssertIOAllowed();
54 if (!CheckValid()) 57 if (!CheckValid())
55 return false; 58 return false;
56 59
60 stepped_ = true;
57 return CheckError(sqlite3_step(ref_->stmt())) == SQLITE_DONE; 61 return CheckError(sqlite3_step(ref_->stmt())) == SQLITE_DONE;
58 } 62 }
59 63
60 bool Statement::Step() { 64 bool Statement::Step() {
61 ref_->AssertIOAllowed(); 65 ref_->AssertIOAllowed();
62 if (!CheckValid()) 66 if (!CheckValid())
63 return false; 67 return false;
64 68
69 stepped_ = true;
65 return CheckError(sqlite3_step(ref_->stmt())) == SQLITE_ROW; 70 return CheckError(sqlite3_step(ref_->stmt())) == SQLITE_ROW;
66 } 71 }
67 72
68 void Statement::Reset(bool clear_bound_vars) { 73 void Statement::Reset(bool clear_bound_vars) {
69 ref_->AssertIOAllowed(); 74 ref_->AssertIOAllowed();
70 if (is_valid()) { 75 if (is_valid()) {
71 // We don't call CheckError() here because sqlite3_reset() returns 76 // We don't call CheckError() here because sqlite3_reset() returns
72 // the last error that Step() caused thereby generating a second 77 // the last error that Step() caused thereby generating a second
73 // spurious error callback. 78 // spurious error callback.
74 if (clear_bound_vars) 79 if (clear_bound_vars)
75 sqlite3_clear_bindings(ref_->stmt()); 80 sqlite3_clear_bindings(ref_->stmt());
76 sqlite3_reset(ref_->stmt()); 81 sqlite3_reset(ref_->stmt());
77 } 82 }
78 83
79 succeeded_ = false; 84 succeeded_ = false;
85 stepped_ = false;
80 } 86 }
81 87
82 bool Statement::Succeeded() const { 88 bool Statement::Succeeded() const {
Scott Hess - ex-Googler 2013/10/24 19:51:37 Almost tempted to put: DCHECK(stepped_); here.
Greg Billock 2013/10/24 21:49:50 Hmmmm. I hear you. Maybe a follow-up try run with
Scott Hess - ex-Googler 2013/10/25 17:50:36 Fails SQLStatementTest.Run :-). Thinking more abo
83 if (!is_valid()) 89 if (!is_valid())
84 return false; 90 return false;
85 91
86 return succeeded_; 92 return succeeded_;
87 } 93 }
88 94
89 bool Statement::BindNull(int col) { 95 bool Statement::BindNull(int col) {
96 DCHECK(!stepped_);
90 if (!is_valid()) 97 if (!is_valid())
91 return false; 98 return false;
92 99
93 return CheckOk(sqlite3_bind_null(ref_->stmt(), col + 1)); 100 return CheckOk(sqlite3_bind_null(ref_->stmt(), col + 1));
94 } 101 }
95 102
96 bool Statement::BindBool(int col, bool val) { 103 bool Statement::BindBool(int col, bool val) {
104 DCHECK(!stepped_);
97 return BindInt(col, val ? 1 : 0); 105 return BindInt(col, val ? 1 : 0);
98 } 106 }
99 107
100 bool Statement::BindInt(int col, int val) { 108 bool Statement::BindInt(int col, int val) {
101 if (!is_valid()) 109 if (!is_valid())
102 return false; 110 return false;
103 111
104 return CheckOk(sqlite3_bind_int(ref_->stmt(), col + 1, val)); 112 return CheckOk(sqlite3_bind_int(ref_->stmt(), col + 1, val));
105 } 113 }
106 114
107 bool Statement::BindInt64(int col, int64 val) { 115 bool Statement::BindInt64(int col, int64 val) {
116 DCHECK(!stepped_);
108 if (!is_valid()) 117 if (!is_valid())
109 return false; 118 return false;
110 119
111 return CheckOk(sqlite3_bind_int64(ref_->stmt(), col + 1, val)); 120 return CheckOk(sqlite3_bind_int64(ref_->stmt(), col + 1, val));
112 } 121 }
113 122
114 bool Statement::BindDouble(int col, double val) { 123 bool Statement::BindDouble(int col, double val) {
124 DCHECK(!stepped_);
115 if (!is_valid()) 125 if (!is_valid())
116 return false; 126 return false;
117 127
118 return CheckOk(sqlite3_bind_double(ref_->stmt(), col + 1, val)); 128 return CheckOk(sqlite3_bind_double(ref_->stmt(), col + 1, val));
119 } 129 }
120 130
121 bool Statement::BindCString(int col, const char* val) { 131 bool Statement::BindCString(int col, const char* val) {
132 DCHECK(!stepped_);
122 if (!is_valid()) 133 if (!is_valid())
123 return false; 134 return false;
124 135
125 return CheckOk( 136 return CheckOk(
126 sqlite3_bind_text(ref_->stmt(), col + 1, val, -1, SQLITE_TRANSIENT)); 137 sqlite3_bind_text(ref_->stmt(), col + 1, val, -1, SQLITE_TRANSIENT));
127 } 138 }
128 139
129 bool Statement::BindString(int col, const std::string& val) { 140 bool Statement::BindString(int col, const std::string& val) {
141 DCHECK(!stepped_);
130 if (!is_valid()) 142 if (!is_valid())
131 return false; 143 return false;
132 144
133 return CheckOk(sqlite3_bind_text(ref_->stmt(), 145 return CheckOk(sqlite3_bind_text(ref_->stmt(),
134 col + 1, 146 col + 1,
135 val.data(), 147 val.data(),
136 val.size(), 148 val.size(),
137 SQLITE_TRANSIENT)); 149 SQLITE_TRANSIENT));
138 } 150 }
139 151
140 bool Statement::BindString16(int col, const string16& value) { 152 bool Statement::BindString16(int col, const string16& value) {
141 return BindString(col, UTF16ToUTF8(value)); 153 return BindString(col, UTF16ToUTF8(value));
142 } 154 }
143 155
144 bool Statement::BindBlob(int col, const void* val, int val_len) { 156 bool Statement::BindBlob(int col, const void* val, int val_len) {
157 DCHECK(!stepped_);
145 if (!is_valid()) 158 if (!is_valid())
146 return false; 159 return false;
147 160
148 return CheckOk( 161 return CheckOk(
149 sqlite3_bind_blob(ref_->stmt(), col + 1, val, val_len, SQLITE_TRANSIENT)); 162 sqlite3_bind_blob(ref_->stmt(), col + 1, val, val_len, SQLITE_TRANSIENT));
150 } 163 }
151 164
152 int Statement::ColumnCount() const { 165 int Statement::ColumnCount() const {
153 if (!is_valid()) 166 if (!is_valid())
154 return 0; 167 return 0;
(...skipping 152 matching lines...) Expand 10 before | Expand all | Expand 10 after
307 320
308 int Statement::CheckError(int err) { 321 int Statement::CheckError(int err) {
309 // Please don't add DCHECKs here, OnSqliteError() already has them. 322 // Please don't add DCHECKs here, OnSqliteError() already has them.
310 succeeded_ = (err == SQLITE_OK || err == SQLITE_ROW || err == SQLITE_DONE); 323 succeeded_ = (err == SQLITE_OK || err == SQLITE_ROW || err == SQLITE_DONE);
311 if (!succeeded_ && ref_.get() && ref_->connection()) 324 if (!succeeded_ && ref_.get() && ref_->connection())
312 return ref_->connection()->OnSqliteError(err, this, NULL); 325 return ref_->connection()->OnSqliteError(err, this, NULL);
313 return err; 326 return err;
314 } 327 }
315 328
316 } // namespace sql 329 } // namespace sql
OLDNEW
« no previous file with comments | « sql/statement.h ('k') | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698