1/* 2 * Copyright (C) 2007 Apple Inc. All rights reserved. 3 * Copyright (C) 2010 Google Inc. All rights reserved. 4 * 5 * Redistribution and use in source and binary forms, with or without 6 * modification, are permitted provided that the following conditions 7 * are met: 8 * 9 * 1. Redistributions of source code must retain the above copyright 10 * notice, this list of conditions and the following disclaimer. 11 * 2. Redistributions in binary form must reproduce the above copyright 12 * notice, this list of conditions and the following disclaimer in the 13 * documentation and/or other materials provided with the distribution. 14 * 3. Neither the name of Apple Inc. ("Apple") nor the names of 15 * its contributors may be used to endorse or promote products derived 16 * from this software without specific prior written permission. 17 * 18 * THIS SOFTWARE IS PROVIDED BY APPLE AND ITS CONTRIBUTORS "AS IS" AND ANY 19 * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED 20 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 21 * DISCLAIMED. IN NO EVENT SHALL APPLE OR ITS CONTRIBUTORS BE LIABLE FOR ANY 22 * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES 23 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; 24 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND 25 * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 26 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF 27 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 28 */ 29 30#include "config.h" 31#include "SQLStatementSync.h" 32 33#if ENABLE(SQL_DATABASE) 34 35#include "DatabaseSync.h" 36#include "SQLException.h" 37#include "SQLResultSet.h" 38#include "SQLValue.h" 39#include "SQLiteDatabase.h" 40#include "SQLiteStatement.h" 41#include <wtf/PassRefPtr.h> 42#include <wtf/RefPtr.h> 43 44namespace WebCore { 45 46SQLStatementSync::SQLStatementSync(const String& statement, const Vector<SQLValue>& arguments, int permissions) 47 : m_statement(statement) 48 , m_arguments(arguments) 49 , m_permissions(permissions) 50{ 51 ASSERT(!m_statement.isEmpty()); 52} 53 54PassRefPtr<SQLResultSet> SQLStatementSync::execute(DatabaseSync* db, ExceptionCode& ec) 55{ 56 db->setAuthorizerPermissions(m_permissions); 57 58 SQLiteDatabase* database = &db->sqliteDatabase(); 59 60 SQLiteStatement statement(*database, m_statement); 61 int result = statement.prepare(); 62 if (result != SQLResultOk) { 63 ec = (result == SQLResultInterrupt ? SQLException::DATABASE_ERR : SQLException::SYNTAX_ERR); 64 db->setLastErrorMessage("could not prepare statement", result, database->lastErrorMsg()); 65 return 0; 66 } 67 68 if (statement.bindParameterCount() != m_arguments.size()) { 69 ec = (db->isInterrupted()? SQLException::DATABASE_ERR : SQLException::SYNTAX_ERR); 70 db->setLastErrorMessage("number of '?'s in statement string does not match argument count"); 71 return 0; 72 } 73 74 for (unsigned i = 0; i < m_arguments.size(); ++i) { 75 result = statement.bindValue(i + 1, m_arguments[i]); 76 if (result == SQLResultFull) { 77 ec = SQLException::QUOTA_ERR; 78 db->setLastErrorMessage("there was not enough remaining storage space"); 79 return 0; 80 } 81 82 if (result != SQLResultOk) { 83 ec = SQLException::DATABASE_ERR; 84 db->setLastErrorMessage("could not bind value", result, database->lastErrorMsg()); 85 return 0; 86 } 87 } 88 89 RefPtr<SQLResultSet> resultSet = SQLResultSet::create(); 90 91 // Step so we can fetch the column names. 92 result = statement.step(); 93 if (result == SQLResultRow) { 94 int columnCount = statement.columnCount(); 95 SQLResultSetRowList* rows = resultSet->rows(); 96 97 for (int i = 0; i < columnCount; i++) 98 rows->addColumn(statement.getColumnName(i)); 99 100 do { 101 for (int i = 0; i < columnCount; i++) 102 rows->addResult(statement.getColumnValue(i)); 103 104 result = statement.step(); 105 } while (result == SQLResultRow); 106 107 if (result != SQLResultDone) { 108 ec = SQLException::DATABASE_ERR; 109 db->setLastErrorMessage("could not iterate results", result, database->lastErrorMsg()); 110 return 0; 111 } 112 } else if (result == SQLResultDone) { 113 // Didn't find anything, or was an insert. 114 if (db->lastActionWasInsert()) 115 resultSet->setInsertId(database->lastInsertRowID()); 116 } else if (result == SQLResultFull) { 117 // Quota error, the delegate will be asked for more space and this statement might be re-run. 118 ec = SQLException::QUOTA_ERR; 119 db->setLastErrorMessage("there was not enough remaining storage space"); 120 return 0; 121 } else if (result == SQLResultConstraint) { 122 ec = SQLException::CONSTRAINT_ERR; 123 db->setLastErrorMessage("statement failed due to a constraint failure"); 124 return 0; 125 } else { 126 ec = SQLException::DATABASE_ERR; 127 db->setLastErrorMessage("could not execute statement", result, database->lastErrorMsg()); 128 return 0; 129 } 130 131 resultSet->setRowsAffected(database->lastChanges()); 132 return resultSet.release(); 133} 134 135} // namespace WebCore 136 137#endif // ENABLE(SQL_DATABASE) 138