OLD | NEW |
1 /* | 1 /* |
2 * Copyright (C) 2007, 2013 Apple Inc. All rights reserved. | 2 * Copyright (C) 2007, 2013 Apple Inc. All rights reserved. |
3 * | 3 * |
4 * Redistribution and use in source and binary forms, with or without | 4 * Redistribution and use in source and binary forms, with or without |
5 * modification, are permitted provided that the following conditions | 5 * modification, are permitted provided that the following conditions |
6 * are met: | 6 * are met: |
7 * | 7 * |
8 * 1. Redistributions of source code must retain the above copyright | 8 * 1. Redistributions of source code must retain the above copyright |
9 * notice, this list of conditions and the following disclaimer. | 9 * notice, this list of conditions and the following disclaimer. |
10 * 2. Redistributions in binary form must reproduce the above copyright | 10 * 2. Redistributions in binary form must reproduce the above copyright |
(...skipping 82 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
93 void SQLStatementBackend::trace(Visitor* visitor) | 93 void SQLStatementBackend::trace(Visitor* visitor) |
94 { | 94 { |
95 visitor->trace(m_resultSet); | 95 visitor->trace(m_resultSet); |
96 } | 96 } |
97 | 97 |
98 AbstractSQLStatement* SQLStatementBackend::frontend() | 98 AbstractSQLStatement* SQLStatementBackend::frontend() |
99 { | 99 { |
100 return m_frontend.get(); | 100 return m_frontend.get(); |
101 } | 101 } |
102 | 102 |
103 PassRefPtr<SQLError> SQLStatementBackend::sqlError() const | 103 SQLErrorData* SQLStatementBackend::sqlError() const |
104 { | 104 { |
105 return m_error; | 105 return m_error.get(); |
106 } | 106 } |
107 | 107 |
108 SQLResultSet* SQLStatementBackend::sqlResultSet() const | 108 SQLResultSet* SQLStatementBackend::sqlResultSet() const |
109 { | 109 { |
110 return m_resultSet->isValid() ? m_resultSet.get() : 0; | 110 return m_resultSet->isValid() ? m_resultSet.get() : 0; |
111 } | 111 } |
112 | 112 |
113 bool SQLStatementBackend::execute(DatabaseBackend* db) | 113 bool SQLStatementBackend::execute(DatabaseBackend* db) |
114 { | 114 { |
115 ASSERT(!m_resultSet->isValid()); | 115 ASSERT(!m_resultSet->isValid()); |
116 | 116 |
117 // If we're re-running this statement after a quota violation, we need to cl
ear that error now | 117 // If we're re-running this statement after a quota violation, we need to cl
ear that error now |
118 clearFailureDueToQuota(); | 118 clearFailureDueToQuota(); |
119 | 119 |
120 // This transaction might have been marked bad while it was being set up on
the main thread, | 120 // This transaction might have been marked bad while it was being set up on
the main thread, |
121 // so if there is still an error, return false. | 121 // so if there is still an error, return false. |
122 if (m_error) | 122 if (m_error) |
123 return false; | 123 return false; |
124 | 124 |
125 db->setAuthorizerPermissions(m_permissions); | 125 db->setAuthorizerPermissions(m_permissions); |
126 | 126 |
127 SQLiteDatabase* database = &db->sqliteDatabase(); | 127 SQLiteDatabase* database = &db->sqliteDatabase(); |
128 | 128 |
129 SQLiteStatement statement(*database, m_statement); | 129 SQLiteStatement statement(*database, m_statement); |
130 int result = statement.prepare(); | 130 int result = statement.prepare(); |
131 | 131 |
132 if (result != SQLResultOk) { | 132 if (result != SQLResultOk) { |
133 WTF_LOG(StorageAPI, "Unable to verify correctness of statement %s - erro
r %i (%s)", m_statement.ascii().data(), result, database->lastErrorMsg()); | 133 WTF_LOG(StorageAPI, "Unable to verify correctness of statement %s - erro
r %i (%s)", m_statement.ascii().data(), result, database->lastErrorMsg()); |
134 if (result == SQLResultInterrupt) | 134 if (result == SQLResultInterrupt) |
135 m_error = SQLError::create(SQLError::DATABASE_ERR, "could not prepar
e statement", result, "interrupted"); | 135 m_error = SQLErrorData::create(SQLError::DATABASE_ERR, "could not pr
epare statement", result, "interrupted"); |
136 else | 136 else |
137 m_error = SQLError::create(SQLError::SYNTAX_ERR, "could not prepare
statement", result, database->lastErrorMsg()); | 137 m_error = SQLErrorData::create(SQLError::SYNTAX_ERR, "could not prep
are statement", result, database->lastErrorMsg()); |
138 db->reportExecuteStatementResult(1, m_error->code(), result); | 138 db->reportExecuteStatementResult(1, m_error->code(), result); |
139 return false; | 139 return false; |
140 } | 140 } |
141 | 141 |
142 // FIXME: If the statement uses the ?### syntax supported by sqlite, the bin
d parameter count is very likely off from the number of question marks. | 142 // FIXME: If the statement uses the ?### syntax supported by sqlite, the bin
d parameter count is very likely off from the number of question marks. |
143 // If this is the case, they might be trying to do something fishy or malici
ous | 143 // If this is the case, they might be trying to do something fishy or malici
ous |
144 if (statement.bindParameterCount() != m_arguments.size()) { | 144 if (statement.bindParameterCount() != m_arguments.size()) { |
145 WTF_LOG(StorageAPI, "Bind parameter count doesn't match number of questi
on marks"); | 145 WTF_LOG(StorageAPI, "Bind parameter count doesn't match number of questi
on marks"); |
146 m_error = SQLError::create(db->isInterrupted() ? SQLError::DATABASE_ERR
: SQLError::SYNTAX_ERR, "number of '?'s in statement string does not match argum
ent count"); | 146 m_error = SQLErrorData::create(db->isInterrupted() ? SQLError::DATABASE_
ERR : SQLError::SYNTAX_ERR, "number of '?'s in statement string does not match a
rgument count"); |
147 db->reportExecuteStatementResult(2, m_error->code(), 0); | 147 db->reportExecuteStatementResult(2, m_error->code(), 0); |
148 return false; | 148 return false; |
149 } | 149 } |
150 | 150 |
151 for (unsigned i = 0; i < m_arguments.size(); ++i) { | 151 for (unsigned i = 0; i < m_arguments.size(); ++i) { |
152 result = statement.bindValue(i + 1, m_arguments[i]); | 152 result = statement.bindValue(i + 1, m_arguments[i]); |
153 if (result == SQLResultFull) { | 153 if (result == SQLResultFull) { |
154 setFailureDueToQuota(db); | 154 setFailureDueToQuota(db); |
155 return false; | 155 return false; |
156 } | 156 } |
157 | 157 |
158 if (result != SQLResultOk) { | 158 if (result != SQLResultOk) { |
159 WTF_LOG(StorageAPI, "Failed to bind value index %i to statement for
query '%s'", i + 1, m_statement.ascii().data()); | 159 WTF_LOG(StorageAPI, "Failed to bind value index %i to statement for
query '%s'", i + 1, m_statement.ascii().data()); |
160 db->reportExecuteStatementResult(3, SQLError::DATABASE_ERR, result); | 160 db->reportExecuteStatementResult(3, SQLError::DATABASE_ERR, result); |
161 m_error = SQLError::create(SQLError::DATABASE_ERR, "could not bind v
alue", result, database->lastErrorMsg()); | 161 m_error = SQLErrorData::create(SQLError::DATABASE_ERR, "could not bi
nd value", result, database->lastErrorMsg()); |
162 return false; | 162 return false; |
163 } | 163 } |
164 } | 164 } |
165 | 165 |
166 // Step so we can fetch the column names. | 166 // Step so we can fetch the column names. |
167 result = statement.step(); | 167 result = statement.step(); |
168 if (result == SQLResultRow) { | 168 if (result == SQLResultRow) { |
169 int columnCount = statement.columnCount(); | 169 int columnCount = statement.columnCount(); |
170 SQLResultSetRowList* rows = m_resultSet->rows(); | 170 SQLResultSetRowList* rows = m_resultSet->rows(); |
171 | 171 |
172 for (int i = 0; i < columnCount; i++) | 172 for (int i = 0; i < columnCount; i++) |
173 rows->addColumn(statement.getColumnName(i)); | 173 rows->addColumn(statement.getColumnName(i)); |
174 | 174 |
175 do { | 175 do { |
176 for (int i = 0; i < columnCount; i++) | 176 for (int i = 0; i < columnCount; i++) |
177 rows->addResult(statement.getColumnValue(i)); | 177 rows->addResult(statement.getColumnValue(i)); |
178 | 178 |
179 result = statement.step(); | 179 result = statement.step(); |
180 } while (result == SQLResultRow); | 180 } while (result == SQLResultRow); |
181 | 181 |
182 if (result != SQLResultDone) { | 182 if (result != SQLResultDone) { |
183 db->reportExecuteStatementResult(4, SQLError::DATABASE_ERR, result); | 183 db->reportExecuteStatementResult(4, SQLError::DATABASE_ERR, result); |
184 m_error = SQLError::create(SQLError::DATABASE_ERR, "could not iterat
e results", result, database->lastErrorMsg()); | 184 m_error = SQLErrorData::create(SQLError::DATABASE_ERR, "could not it
erate results", result, database->lastErrorMsg()); |
185 return false; | 185 return false; |
186 } | 186 } |
187 } else if (result == SQLResultDone) { | 187 } else if (result == SQLResultDone) { |
188 // Didn't find anything, or was an insert | 188 // Didn't find anything, or was an insert |
189 if (db->lastActionWasInsert()) | 189 if (db->lastActionWasInsert()) |
190 m_resultSet->setInsertId(database->lastInsertRowID()); | 190 m_resultSet->setInsertId(database->lastInsertRowID()); |
191 } else if (result == SQLResultFull) { | 191 } else if (result == SQLResultFull) { |
192 // Return the Quota error - the delegate will be asked for more space an
d this statement might be re-run | 192 // Return the Quota error - the delegate will be asked for more space an
d this statement might be re-run |
193 setFailureDueToQuota(db); | 193 setFailureDueToQuota(db); |
194 return false; | 194 return false; |
195 } else if (result == SQLResultConstraint) { | 195 } else if (result == SQLResultConstraint) { |
196 db->reportExecuteStatementResult(6, SQLError::CONSTRAINT_ERR, result); | 196 db->reportExecuteStatementResult(6, SQLError::CONSTRAINT_ERR, result); |
197 m_error = SQLError::create(SQLError::CONSTRAINT_ERR, "could not execute
statement due to a constaint failure", result, database->lastErrorMsg()); | 197 m_error = SQLErrorData::create(SQLError::CONSTRAINT_ERR, "could not exec
ute statement due to a constaint failure", result, database->lastErrorMsg()); |
198 return false; | 198 return false; |
199 } else { | 199 } else { |
200 db->reportExecuteStatementResult(5, SQLError::DATABASE_ERR, result); | 200 db->reportExecuteStatementResult(5, SQLError::DATABASE_ERR, result); |
201 m_error = SQLError::create(SQLError::DATABASE_ERR, "could not execute st
atement", result, database->lastErrorMsg()); | 201 m_error = SQLErrorData::create(SQLError::DATABASE_ERR, "could not execut
e statement", result, database->lastErrorMsg()); |
202 return false; | 202 return false; |
203 } | 203 } |
204 | 204 |
205 // FIXME: If the spec allows triggers, and we want to be "accurate" in a dif
ferent way, we'd use | 205 // FIXME: If the spec allows triggers, and we want to be "accurate" in a dif
ferent way, we'd use |
206 // sqlite3_total_changes() here instead of sqlite3_changed, because that inc
ludes rows modified from within a trigger | 206 // sqlite3_total_changes() here instead of sqlite3_changed, because that inc
ludes rows modified from within a trigger |
207 // For now, this seems sufficient | 207 // For now, this seems sufficient |
208 m_resultSet->setRowsAffected(database->lastChanges()); | 208 m_resultSet->setRowsAffected(database->lastChanges()); |
209 | 209 |
210 db->reportExecuteStatementResult(0, -1, 0); // OK | 210 db->reportExecuteStatementResult(0, -1, 0); // OK |
211 return true; | 211 return true; |
212 } | 212 } |
213 | 213 |
214 void SQLStatementBackend::setVersionMismatchedError(DatabaseBackend* database) | 214 void SQLStatementBackend::setVersionMismatchedError(DatabaseBackend* database) |
215 { | 215 { |
216 ASSERT(!m_error && !m_resultSet->isValid()); | 216 ASSERT(!m_error && !m_resultSet->isValid()); |
217 database->reportExecuteStatementResult(7, SQLError::VERSION_ERR, 0); | 217 database->reportExecuteStatementResult(7, SQLError::VERSION_ERR, 0); |
218 m_error = SQLError::create(SQLError::VERSION_ERR, "current version of the da
tabase and `oldVersion` argument do not match"); | 218 m_error = SQLErrorData::create(SQLError::VERSION_ERR, "current version of th
e database and `oldVersion` argument do not match"); |
219 } | 219 } |
220 | 220 |
221 void SQLStatementBackend::setFailureDueToQuota(DatabaseBackend* database) | 221 void SQLStatementBackend::setFailureDueToQuota(DatabaseBackend* database) |
222 { | 222 { |
223 ASSERT(!m_error && !m_resultSet->isValid()); | 223 ASSERT(!m_error && !m_resultSet->isValid()); |
224 database->reportExecuteStatementResult(8, SQLError::QUOTA_ERR, 0); | 224 database->reportExecuteStatementResult(8, SQLError::QUOTA_ERR, 0); |
225 m_error = SQLError::create(SQLError::QUOTA_ERR, "there was not enough remain
ing storage space, or the storage quota was reached and the user declined to all
ow more space"); | 225 m_error = SQLErrorData::create(SQLError::QUOTA_ERR, "there was not enough re
maining storage space, or the storage quota was reached and the user declined to
allow more space"); |
226 } | 226 } |
227 | 227 |
228 void SQLStatementBackend::clearFailureDueToQuota() | 228 void SQLStatementBackend::clearFailureDueToQuota() |
229 { | 229 { |
230 if (lastExecutionFailedDueToQuota()) | 230 if (lastExecutionFailedDueToQuota()) |
231 m_error = nullptr; | 231 m_error = nullptr; |
232 } | 232 } |
233 | 233 |
234 bool SQLStatementBackend::lastExecutionFailedDueToQuota() const | 234 bool SQLStatementBackend::lastExecutionFailedDueToQuota() const |
235 { | 235 { |
236 return m_error && m_error->code() == SQLError::QUOTA_ERR; | 236 return m_error && m_error->code() == SQLError::QUOTA_ERR; |
237 } | 237 } |
238 | 238 |
239 } // namespace WebCore | 239 } // namespace WebCore |
OLD | NEW |