// Copyright (c) 2010 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

#include "app/sql/statement.h"

#include "base/logging.h"
#include "base/utf_string_conversions.h"
#ifdef ANDROID
#include "sqlite3.h"
#else
#include "third_party/sqlite/sqlite3.h"
#endif

namespace sql {

// This empty constructor initializes our reference with an empty one so that
// we don't have to NULL-check the ref_ to see if the statement is valid: we
// only have to check the ref's validity bit.
Statement::Statement()
    : ref_(new Connection::StatementRef),
      succeeded_(false) {
}

Statement::Statement(scoped_refptr<Connection::StatementRef> ref)
    : ref_(ref),
      succeeded_(false) {
}

Statement::~Statement() {
  // Free the resources associated with this statement. We assume there's only
  // one statement active for a given sqlite3_stmt at any time, so this won't
  // mess with anything.
  Reset();
}

void Statement::Assign(scoped_refptr<Connection::StatementRef> ref) {
  Reset();
  ref_ = ref;
}

bool Statement::Run() {
  if (!is_valid())
    return false;
  return CheckError(sqlite3_step(ref_->stmt())) == SQLITE_DONE;
}

bool Statement::Step() {
  if (!is_valid())
    return false;
  return CheckError(sqlite3_step(ref_->stmt())) == SQLITE_ROW;
}

void Statement::Reset() {
  if (is_valid()) {
    // We don't call CheckError() here because sqlite3_reset() returns
    // the last error that Step() caused thereby generating a second
    // spurious error callback.
    sqlite3_clear_bindings(ref_->stmt());
    sqlite3_reset(ref_->stmt());
  }
  succeeded_ = false;
}

bool Statement::Succeeded() const {
  if (!is_valid())
    return false;
  return succeeded_;
}

bool Statement::BindNull(int col) {
  if (is_valid()) {
    int err = CheckError(sqlite3_bind_null(ref_->stmt(), col + 1));
    return err == SQLITE_OK;
  }
  return false;
}

bool Statement::BindBool(int col, bool val) {
  return BindInt(col, val ? 1 : 0);
}

bool Statement::BindInt(int col, int val) {
  if (is_valid()) {
    int err = CheckError(sqlite3_bind_int(ref_->stmt(), col + 1, val));
    return err == SQLITE_OK;
  }
  return false;
}

bool Statement::BindInt64(int col, int64 val) {
  if (is_valid()) {
    int err = CheckError(sqlite3_bind_int64(ref_->stmt(), col + 1, val));
    return err == SQLITE_OK;
  }
  return false;
}

bool Statement::BindDouble(int col, double val) {
  if (is_valid()) {
    int err = CheckError(sqlite3_bind_double(ref_->stmt(), col + 1, val));
    return err == SQLITE_OK;
  }
  return false;
}

bool Statement::BindCString(int col, const char* val) {
  if (is_valid()) {
    int err = CheckError(sqlite3_bind_text(ref_->stmt(), col + 1, val, -1,
                         SQLITE_TRANSIENT));
    return err == SQLITE_OK;
  }
  return false;
}

bool Statement::BindString(int col, const std::string& val) {
  if (is_valid()) {
    int err = CheckError(sqlite3_bind_text(ref_->stmt(), col + 1, val.data(),
                                           val.size(), SQLITE_TRANSIENT));
    return err == SQLITE_OK;
  }
  return false;
}

bool Statement::BindString16(int col, const string16& value) {
  return BindString(col, UTF16ToUTF8(value));
}

bool Statement::BindBlob(int col, const void* val, int val_len) {
  if (is_valid()) {
    int err = CheckError(sqlite3_bind_blob(ref_->stmt(), col + 1,
                         val, val_len, SQLITE_TRANSIENT));
    return err == SQLITE_OK;
  }
  return false;
}

int Statement::ColumnCount() const {
  if (!is_valid()) {
    NOTREACHED();
    return 0;
  }
  return sqlite3_column_count(ref_->stmt());
}

ColType Statement::ColumnType(int col) const {
  // Verify that our enum matches sqlite's values.
  COMPILE_ASSERT(COLUMN_TYPE_INTEGER == SQLITE_INTEGER, integer_no_match);
  COMPILE_ASSERT(COLUMN_TYPE_FLOAT == SQLITE_FLOAT, float_no_match);
  COMPILE_ASSERT(COLUMN_TYPE_TEXT == SQLITE_TEXT, integer_no_match);
  COMPILE_ASSERT(COLUMN_TYPE_BLOB == SQLITE_BLOB, blob_no_match);
  COMPILE_ASSERT(COLUMN_TYPE_NULL == SQLITE_NULL, null_no_match);

  return static_cast<ColType>(sqlite3_column_type(ref_->stmt(), col));
}

bool Statement::ColumnBool(int col) const {
  return !!ColumnInt(col);
}

int Statement::ColumnInt(int col) const {
  if (!is_valid()) {
    NOTREACHED();
    return 0;
  }
  return sqlite3_column_int(ref_->stmt(), col);
}

int64 Statement::ColumnInt64(int col) const {
  if (!is_valid()) {
    NOTREACHED();
    return 0;
  }
  return sqlite3_column_int64(ref_->stmt(), col);
}

double Statement::ColumnDouble(int col) const {
  if (!is_valid()) {
    NOTREACHED();
    return 0;
  }
  return sqlite3_column_double(ref_->stmt(), col);
}

std::string Statement::ColumnString(int col) const {
  if (!is_valid()) {
    NOTREACHED();
    return "";
  }
  const char* str = reinterpret_cast<const char*>(
      sqlite3_column_text(ref_->stmt(), col));
  int len = sqlite3_column_bytes(ref_->stmt(), col);

  std::string result;
  if (str && len > 0)
    result.assign(str, len);
  return result;
}

string16 Statement::ColumnString16(int col) const {
  if (!is_valid()) {
    NOTREACHED();
    return string16();
  }
  std::string s = ColumnString(col);
  return !s.empty() ? UTF8ToUTF16(s) : string16();
}

int Statement::ColumnByteLength(int col) const {
  if (!is_valid()) {
    NOTREACHED();
    return 0;
  }
  return sqlite3_column_bytes(ref_->stmt(), col);
}

const void* Statement::ColumnBlob(int col) const {
  if (!is_valid()) {
    NOTREACHED();
    return NULL;
  }

  return sqlite3_column_blob(ref_->stmt(), col);
}

bool Statement::ColumnBlobAsString(int col, std::string* blob) {
  if (!is_valid()) {
    NOTREACHED();
    return false;
  }
  const void* p = ColumnBlob(col);
  size_t len = ColumnByteLength(col);
  blob->resize(len);
  if (blob->size() != len) {
    return false;
  }
  blob->assign(reinterpret_cast<const char*>(p), len);
  return true;
}

void Statement::ColumnBlobAsVector(int col, std::vector<char>* val) const {
  val->clear();
  if (!is_valid()) {
    NOTREACHED();
    return;
  }

  const void* data = sqlite3_column_blob(ref_->stmt(), col);
  int len = sqlite3_column_bytes(ref_->stmt(), col);
  if (data && len > 0) {
    val->resize(len);
    memcpy(&(*val)[0], data, len);
  }
}

void Statement::ColumnBlobAsVector(
    int col,
    std::vector<unsigned char>* val) const {
  ColumnBlobAsVector(col, reinterpret_cast< std::vector<char>* >(val));
}

const char* Statement::GetSQLStatement() {
  return sqlite3_sql(ref_->stmt());
}

int Statement::CheckError(int err) {
  // Please don't add DCHECKs here, OnSqliteError() already has them.
  succeeded_ = (err == SQLITE_OK || err == SQLITE_ROW || err == SQLITE_DONE);
  if (!succeeded_ && is_valid())
    return ref_->connection()->OnSqliteError(err, this);
  return err;
}

}  // namespace sql
