/*
 * Copyright (C) 2007, 2013 Apple Inc. All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions
 * are met:
 *
 * 1.  Redistributions of source code must retain the above copyright
 *     notice, this list of conditions and the following disclaimer.
 * 2.  Redistributions in binary form must reproduce the above copyright
 *     notice, this list of conditions and the following disclaimer in the
 *     documentation and/or other materials provided with the distribution.
 * 3.  Neither the name of Apple Inc. ("Apple") nor the names of
 *     its contributors may be used to endorse or promote products derived
 *     from this software without specific prior written permission.
 *
 * THIS SOFTWARE IS PROVIDED BY APPLE AND ITS CONTRIBUTORS "AS IS" AND ANY
 * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
 * DISCLAIMED. IN NO EVENT SHALL APPLE OR ITS CONTRIBUTORS BE LIABLE FOR ANY
 * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
 * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 */
#include "config.h"
#include "SQLStatement.h"

#include "Database.h"
#include "Document.h"
#include "Logging.h"
#include "SQLError.h"
#include "SQLResultSet.h"
#include "SQLStatementCallback.h"
#include "SQLStatementErrorCallback.h"
#include "SQLValue.h"
#include "SQLiteDatabase.h"
#include "SQLiteStatement.h"
#include <wtf/text/CString.h>


// The Life-Cycle of a SQLStatement i.e. Who's keeping the SQLStatement alive?
// ==========================================================================
// The RefPtr chain goes something like this:
//
//     At birth (in SQLTransactionBackend::executeSQL()):
//     =================================================
//     SQLTransactionBackend           // Deque<RefPtr<SQLStatement>> m_statementQueue points to ...
//     --> SQLStatement         // std::unique_ptr<SQLStatement> m_frontend points to ...
//         --> SQLStatement
//
//     After grabbing the statement for execution (in SQLTransactionBackend::getNextStatement()):
//     =========================================================================================
//     SQLTransactionBackend           // RefPtr<SQLStatement> m_currentStatementBackend points to ...
//     --> SQLStatement         // std::unique_ptr<SQLStatement> m_frontend points to ...
//         --> SQLStatement
//
//     Then we execute the statement in SQLTransactionBackend::runCurrentStatementAndGetNextState().
//     And we callback to the script in SQLTransaction::deliverStatementCallback() if
//     necessary.
//     - Inside SQLTransaction::deliverStatementCallback(), we operate on a raw SQLStatement*.
//       This pointer is valid because it is owned by SQLTransactionBackend's
//       SQLTransactionBackend::m_currentStatementBackend.
//
//     After we're done executing the statement (in SQLTransactionBackend::getNextStatement()):
//     =======================================================================================
//     When we're done executing, we'll grab the next statement. But before we
//     do that, getNextStatement() nullify SQLTransactionBackend::m_currentStatementBackend.
//     This will trigger the deletion of the SQLStatement and SQLStatement.
//
//     Note: unlike with SQLTransaction, there is no JS representation of SQLStatement.
//     Hence, there is no GC dependency at play here.

namespace WebCore {

SQLStatement::SQLStatement(Database& database, const String& statement, Vector<SQLValue>&& arguments, RefPtr<SQLStatementCallback>&& callback, RefPtr<SQLStatementErrorCallback>&& errorCallback, int permissions)
    : m_statement(statement.isolatedCopy())
    , m_arguments(WTFMove(arguments))
    , m_statementCallbackWrapper(WTFMove(callback), &database.document())
    , m_statementErrorCallbackWrapper(WTFMove(errorCallback), &database.document())
    , m_permissions(permissions)
{
}

SQLStatement::~SQLStatement() = default;

SQLError* SQLStatement::sqlError() const
{
    return m_error.get();
}

SQLResultSet* SQLStatement::sqlResultSet() const
{
    return m_resultSet.get();
}

bool SQLStatement::execute(Database& db)
{
    ASSERT(!m_resultSet);

    // If we're re-running this statement after a quota violation, we need to clear that error now
    clearFailureDueToQuota();

    // This transaction might have been marked bad while it was being set up on the main thread,
    // so if there is still an error, return false.
    if (m_error)
        return false;

    db.setAuthorizerPermissions(m_permissions);

    SQLiteDatabase& database = db.sqliteDatabase();

    auto statement = database.prepareStatementSlow(m_statement);
    if (!statement) {
        LOG(StorageAPI, "Unable to verify correctness of statement %s - error %i (%s)", m_statement.ascii().data(), statement.error(), database.lastErrorMsg());
        if (statement.error() == SQLITE_INTERRUPT)
            m_error = SQLError::create(SQLError::DATABASE_ERR, "could not prepare statement", statement.error(), "interrupted");
        else
            m_error = SQLError::create(SQLError::SYNTAX_ERR, "could not prepare statement", statement.error(), database.lastErrorMsg());
        return false;
    }

    // FIXME: If the statement uses the ?### syntax supported by sqlite, the bind parameter count is very likely off from the number of question marks.
    // If this is the case, they might be trying to do something fishy or malicious
    if (statement->bindParameterCount() != m_arguments.size()) {
        LOG(StorageAPI, "Bind parameter count doesn't match number of question marks");
        m_error = SQLError::create(SQLError::SYNTAX_ERR, "number of '?'s in statement string does not match argument count"_s);
        return false;
    }

    for (unsigned i = 0; i < m_arguments.size(); ++i) {
        int result = statement->bindValue(i + 1, m_arguments[i]);
        if (result == SQLITE_FULL) {
            setFailureDueToQuota();
            return false;
        }

        if (result != SQLITE_OK) {
            LOG(StorageAPI, "Failed to bind value index %i to statement for query '%s'", i + 1, m_statement.ascii().data());
            m_error = SQLError::create(SQLError::DATABASE_ERR, "could not bind value", result, database.lastErrorMsg());
            return false;
        }
    }

    auto resultSet = SQLResultSet::create();

    // Step so we can fetch the column names.
    int result = statement->step();
    switch (result) {
    case SQLITE_ROW: {
        int columnCount = statement->columnCount();
        auto& rows = resultSet->rows();

        for (int i = 0; i < columnCount; i++)
            rows.addColumn(statement->columnName(i));

        do {
            for (int i = 0; i < columnCount; i++)
                rows.addResult(statement->columnValue(i));

            result = statement->step();
        } while (result == SQLITE_ROW);

        if (result != SQLITE_DONE) {
            m_error = SQLError::create(SQLError::DATABASE_ERR, "could not iterate results", result, database.lastErrorMsg());
            return false;
        }
        break;
    }
    case SQLITE_DONE: {
        // Didn't find anything, or was an insert
        if (db.lastActionWasInsert())
            resultSet->setInsertId(database.lastInsertRowID());
        break;
    }
    case SQLITE_FULL:
        // Return the Quota error - the delegate will be asked for more space and this statement might be re-run
        setFailureDueToQuota();
        return false;
    case SQLITE_CONSTRAINT:
        m_error = SQLError::create(SQLError::CONSTRAINT_ERR, "could not execute statement due to a constaint failure", result, database.lastErrorMsg());
        return false;
    default:
        m_error = SQLError::create(SQLError::DATABASE_ERR, "could not execute statement", result, database.lastErrorMsg());
        return false;
    }

    // rowsAffected should be 0 for read only statements (e.g. SELECT statement). However, SQLiteDatabase::lastChanges() returns
    // the number of changes made by the most recent INSERT, UPDATE or DELETE statement.
    if (!statement->isReadOnly())
        resultSet->setRowsAffected(database.lastChanges());

    m_resultSet = WTFMove(resultSet);
    return true;
}

bool SQLStatement::performCallback(SQLTransaction& transaction)
{
    // Call the appropriate statement callback and track if it resulted in an error,
    // because then we need to jump to the transaction error callback.

    if (m_error) {
        if (auto errorCallback = m_statementErrorCallbackWrapper.unwrap()) {
            auto result = errorCallback->handleEvent(transaction, *m_error);

            // The spec says:
            // "If the error callback returns false, then move on to the next statement..."
            // "Otherwise, the error callback did not return false, or there was no error callback"
            // Therefore an exception and returning true are the same thing - so, return true on an exception

            switch (result.type()) {
            case CallbackResultType::Success:
                return result.releaseReturnValue();
            case CallbackResultType::ExceptionThrown:
            case CallbackResultType::UnableToExecute:
                return true;
            }
        }
        return false;
    }
    
    if (auto callback = m_statementCallbackWrapper.unwrap()) {
        ASSERT(m_resultSet);

        auto result = callback->handleEvent(transaction, *m_resultSet);
        return result.type() == CallbackResultType::ExceptionThrown;
    }

    return false;
}

void SQLStatement::setDatabaseDeletedError()
{
    ASSERT(!m_error && !m_resultSet);
    m_error = SQLError::create(SQLError::UNKNOWN_ERR, "unable to execute statement, because the user deleted the database"_s);
}

void SQLStatement::setVersionMismatchedError()
{
    ASSERT(!m_error && !m_resultSet);
    m_error = SQLError::create(SQLError::VERSION_ERR, "current version of the database and `oldVersion` argument do not match"_s);
}

void SQLStatement::setFailureDueToQuota()
{
    ASSERT(!m_error && !m_resultSet);
    m_error = SQLError::create(SQLError::QUOTA_ERR, "there was not enough remaining storage space, or the storage quota was reached and the user declined to allow more space"_s);
}

void SQLStatement::clearFailureDueToQuota()
{
    if (lastExecutionFailedDueToQuota())
        m_error = nullptr;
}

bool SQLStatement::lastExecutionFailedDueToQuota() const
{
    return m_error && m_error->code() == SQLError::QUOTA_ERR;
}

} // namespace WebCore
