| 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 |