/*
 * 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 Computer, 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 "modules/webdatabase/SQLStatementBackend.h"

#include "modules/webdatabase/Database.h"
#include "modules/webdatabase/SQLError.h"
#include "modules/webdatabase/SQLStatement.h"
#include "modules/webdatabase/StorageLog.h"
#include "modules/webdatabase/sqlite/SQLiteDatabase.h"
#include "modules/webdatabase/sqlite/SQLiteStatement.h"
#include "platform/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
//         // HeapDeque<Member<SQLStatementBackend>> m_statementQueue
//         // points to ...
//     --> SQLStatementBackend
//         // Member<SQLStatement> m_frontend points to ...
//     --> SQLStatement
//
//     After grabbing the statement for execution (in
//     SQLTransactionBackend::getNextStatement()):
//     ======================================================================
//     SQLTransactionBackend
//         // Member<SQLStatementBackend> m_currentStatementBackend
//         // points to ...
//     --> SQLStatementBackend
//         // Member<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 SQLStatementBackend and
//     SQLStatement.
//
//     Note: unlike with SQLTransaction, there is no JS representation of
//     SQLStatement.  Hence, there is no GC dependency at play here.

namespace blink {

SQLStatementBackend* SQLStatementBackend::Create(
    SQLStatement* frontend,
    const String& statement,
    const Vector<SQLValue>& arguments,
    int permissions) {
  return new SQLStatementBackend(frontend, statement, arguments, permissions);
}

SQLStatementBackend::SQLStatementBackend(SQLStatement* frontend,
                                         const String& statement,
                                         const Vector<SQLValue>& arguments,
                                         int permissions)
    : frontend_(frontend),
      statement_(statement.IsolatedCopy()),
      arguments_(arguments),
      has_callback_(frontend_->HasCallback()),
      has_error_callback_(frontend_->HasErrorCallback()),
      result_set_(SQLResultSet::Create()),
      permissions_(permissions) {
  DCHECK(IsMainThread());

  frontend_->SetBackend(this);
}

void SQLStatementBackend::Trace(blink::Visitor* visitor) {
  visitor->Trace(frontend_);
  visitor->Trace(result_set_);
}

SQLStatement* SQLStatementBackend::GetFrontend() {
  return frontend_.Get();
}

SQLErrorData* SQLStatementBackend::SqlError() const {
  return error_.get();
}

SQLResultSet* SQLStatementBackend::SqlResultSet() const {
  return result_set_->IsValid() ? result_set_.Get() : nullptr;
}

bool SQLStatementBackend::Execute(Database* db) {
  DCHECK(!result_set_->IsValid());

  // 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 (error_)
    return false;

  db->SetAuthorizerPermissions(permissions_);

  SQLiteDatabase* database = &db->SqliteDatabase();

  SQLiteStatement statement(*database, statement_);
  int result = statement.Prepare();

  if (result != kSQLResultOk) {
    STORAGE_DVLOG(1) << "Unable to verify correctness of statement "
                     << statement_ << " - error " << result << " ("
                     << database->LastErrorMsg() << ")";
    if (result == kSQLResultInterrupt)
      error_ = SQLErrorData::Create(SQLError::kDatabaseErr,
                                    "could not prepare statement", result,
                                    "interrupted");
    else
      error_ = SQLErrorData::Create(SQLError::kSyntaxErr,
                                    "could not prepare statement", result,
                                    database->LastErrorMsg());
    db->ReportExecuteStatementResult(1, error_->Code(), result);
    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() != arguments_.size()) {
    STORAGE_DVLOG(1)
        << "Bind parameter count doesn't match number of question marks";
    error_ = SQLErrorData::Create(
        SQLError::kSyntaxErr,
        "number of '?'s in statement string does not match argument count");
    db->ReportExecuteStatementResult(2, error_->Code(), 0);
    return false;
  }

  for (unsigned i = 0; i < arguments_.size(); ++i) {
    result = statement.BindValue(i + 1, arguments_[i]);
    if (result == kSQLResultFull) {
      SetFailureDueToQuota(db);
      return false;
    }

    if (result != kSQLResultOk) {
      STORAGE_DVLOG(1) << "Failed to bind value index " << (i + 1)
                       << " to statement for query " << statement_;
      db->ReportExecuteStatementResult(3, SQLError::kDatabaseErr, result);
      error_ =
          SQLErrorData::Create(SQLError::kDatabaseErr, "could not bind value",
                               result, database->LastErrorMsg());
      return false;
    }
  }

  // Step so we can fetch the column names.
  result = statement.Step();
  if (result == kSQLResultRow) {
    int column_count = statement.ColumnCount();
    SQLResultSetRowList* rows = result_set_->rows();

    for (int i = 0; i < column_count; i++)
      rows->AddColumn(statement.GetColumnName(i));

    do {
      for (int i = 0; i < column_count; i++)
        rows->AddResult(statement.GetColumnValue(i));

      result = statement.Step();
    } while (result == kSQLResultRow);

    if (result != kSQLResultDone) {
      db->ReportExecuteStatementResult(4, SQLError::kDatabaseErr, result);
      error_ = SQLErrorData::Create(SQLError::kDatabaseErr,
                                    "could not iterate results", result,
                                    database->LastErrorMsg());
      return false;
    }
  } else if (result == kSQLResultDone) {
    // Didn't find anything, or was an insert
    if (db->LastActionWasInsert())
      result_set_->SetInsertId(database->LastInsertRowID());
  } else if (result == kSQLResultFull) {
    // Return the Quota error - the delegate will be asked for more space and
    // this statement might be re-run.
    SetFailureDueToQuota(db);
    return false;
  } else if (result == kSQLResultConstraint) {
    db->ReportExecuteStatementResult(6, SQLError::kConstraintErr, result);
    error_ = SQLErrorData::Create(
        SQLError::kConstraintErr,
        "could not execute statement due to a constraint failure", result,
        database->LastErrorMsg());
    return false;
  } else {
    db->ReportExecuteStatementResult(5, SQLError::kDatabaseErr, result);
    error_ = SQLErrorData::Create(SQLError::kDatabaseErr,
                                  "could not execute statement", result,
                                  database->LastErrorMsg());
    return false;
  }

  // FIXME: If the spec allows triggers, and we want to be "accurate" in a
  // different way, we'd use sqlite3_total_changes() here instead of
  // sqlite3_changed, because that includes rows modified from within a trigger.
  // For now, this seems sufficient.
  result_set_->SetRowsAffected(database->LastChanges());

  db->ReportExecuteStatementResult(0, -1, 0);  // OK
  return true;
}

void SQLStatementBackend::SetVersionMismatchedError(Database* database) {
  DCHECK(!error_);
  DCHECK(!result_set_->IsValid());
  database->ReportExecuteStatementResult(7, SQLError::kVersionErr, 0);
  error_ = SQLErrorData::Create(
      SQLError::kVersionErr,
      "current version of the database and `oldVersion` argument do not match");
}

void SQLStatementBackend::SetFailureDueToQuota(Database* database) {
  DCHECK(!error_);
  DCHECK(!result_set_->IsValid());
  database->ReportExecuteStatementResult(8, SQLError::kQuotaErr, 0);
  error_ = SQLErrorData::Create(SQLError::kQuotaErr,
                                "there was not enough remaining storage "
                                "space, or the storage quota was reached and "
                                "the user declined to allow more space");
}

void SQLStatementBackend::ClearFailureDueToQuota() {
  if (LastExecutionFailedDueToQuota())
    error_ = nullptr;
}

bool SQLStatementBackend::LastExecutionFailedDueToQuota() const {
  return error_ && error_->Code() == SQLError::kQuotaErr;
}

}  // namespace blink
