// Copyright 2016 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 "components/password_manager/core/browser/sql_table_builder.h"

#include <algorithm>
#include <set>
#include <utility>

#include "base/numerics/safe_conversions.h"
#include "base/stl_util.h"
#include "base/strings/string_util.h"
#include "base/strings/stringprintf.h"
#include "sql/database.h"
#include "sql/transaction.h"

namespace password_manager {

namespace {

// Appends |name| to |list_of_names|, separating items with ", ".
void Append(const std::string& name, std::string* list_of_names) {
  if (list_of_names->empty())
    *list_of_names = name;
  else
    *list_of_names += ", " + name;
}

}  // namespace

// static
unsigned constexpr SQLTableBuilder::kInvalidVersion;

struct SQLTableBuilder::Column {
  std::string name;
  std::string type;
  // Whether this column is part of the table's PRIMARY KEY constraint.
  bool part_of_primary_key;
  // Whether this column is part of the table's UNIQUE constraint.
  bool part_of_unique_key;
  // The first version this column is part of.
  unsigned min_version;
  // The last version this column is part of. The value of kInvalidVersion
  // means that it is part of all versions since |min_version|.
  unsigned max_version;
  // Renaming of a column is stored as a sequence of one removed and one added
  // column in |columns_|. To distinguish it from an unrelated removal and
  // addition, the following bit is set to true for the added columns which
  // are part of renaming. Those columns will get the data of their
  // predecessors. If the bit is false, the column will be filled with the
  // default value on creation.
  bool gets_previous_data;
};

struct SQLTableBuilder::Index {
  // The name of this index.
  std::string name;
  // The names of columns this index is built from.
  std::vector<std::string> columns;
  // The first version this index is part of.
  unsigned min_version;
  // The last version this index is part of. The value of kInvalidVersion
  // means that it is part of all versions since |min_version|.
  unsigned max_version;
};

SQLTableBuilder::SQLTableBuilder(const std::string& table_name)
    : table_name_(table_name) {}

SQLTableBuilder::~SQLTableBuilder() = default;

void SQLTableBuilder::AddColumn(std::string name, std::string type) {
  DCHECK(FindLastColumnByName(name) == columns_.rend());
  columns_.push_back({std::move(name), std::move(type), false, false,
                      sealed_version_ + 1, kInvalidVersion, false});
}

void SQLTableBuilder::AddColumnToPrimaryKey(std::string name,
                                            std::string type) {
  AddColumn(std::move(name), std::move(type));
  columns_.back().part_of_primary_key = true;
}

void SQLTableBuilder::AddColumnToUniqueKey(std::string name, std::string type) {
  AddColumn(std::move(name), std::move(type));
  columns_.back().part_of_unique_key = true;
}

void SQLTableBuilder::RenameColumn(const std::string& old_name,
                                   const std::string& new_name) {
  auto old_column = FindLastColumnByName(old_name);
  DCHECK(old_column != columns_.rend());
  if (old_name == new_name)  // The easy case.
    return;

  DCHECK(FindLastColumnByName(new_name) == columns_.rend());
  // Check there is no index in the current version that references |old_name|.
  DCHECK(std::none_of(indices_.begin(), indices_.end(),
                      [&old_name](const Index& index) {
                        return index.max_version == kInvalidVersion &&
                               base::ContainsValue(index.columns, old_name);
                      }));

  if (sealed_version_ != kInvalidVersion &&
      old_column->min_version <= sealed_version_) {
    // This column exists in the last sealed version. Therefore it cannot be
    // just replaced, it needs to be kept for generating the migration code.
    Column new_column = {new_name,
                         old_column->type,
                         old_column->part_of_primary_key,
                         old_column->part_of_unique_key,
                         sealed_version_ + 1,
                         kInvalidVersion,
                         true};
    old_column->max_version = sealed_version_;
    auto past_old =
        old_column.base();  // Points one element after |old_column|.
    columns_.insert(past_old, std::move(new_column));
  } else {
    // This column was just introduced in the currently unsealed version. To
    // rename it, it is enough just to modify the entry in columns_.
    old_column->name = new_name;
  }
}

// Removes column |name|. |name| must have been added in the past.
void SQLTableBuilder::DropColumn(const std::string& name) {
  auto column = FindLastColumnByName(name);
  DCHECK(column != columns_.rend());
  // Check there is no index in the current version that references |old_name|.
  DCHECK(std::none_of(indices_.begin(), indices_.end(),
                      [&name](const Index& index) {
                        return index.max_version == kInvalidVersion &&
                               base::ContainsValue(index.columns, name);
                      }));
  if (sealed_version_ != kInvalidVersion &&
      column->min_version <= sealed_version_) {
    // This column exists in the last sealed version. Therefore it cannot be
    // just deleted, it needs to be kept for generating the migration code.
    column->max_version = sealed_version_;
  } else {
    // This column was just introduced in the currently unsealed version. It
    // can be just erased from |columns_|.
    columns_.erase(
        --(column.base()));  // base() points one element after |column|.
  }
}

void SQLTableBuilder::AddIndex(std::string name,
                               std::vector<std::string> columns) {
  DCHECK(!columns.empty());
  // Check if all entries of |columns| are unique.
  DCHECK_EQ(std::set<std::string>(columns.begin(), columns.end()).size(),
            columns.size());
  // |name| must not have been added before.
  DCHECK(FindLastIndexByName(name) == indices_.rend());
  // Check that all referenced columns are present in the last version by making
  // sure that the inner predicate applies to all columns names in |columns|.
  DCHECK(std::all_of(
      columns.begin(), columns.end(), [this](const std::string& column_name) {
        // Check if there is any column with the required name which is also
        // present in the latest version. Note that we don't require the last
        // version to be sealed.
        return std::any_of(columns_.begin(), columns_.end(),
                           [&column_name](const Column& column) {
                             return column.name == column_name &&
                                    column.max_version == kInvalidVersion;
                           });
      }));
  indices_.push_back({std::move(name), std::move(columns), sealed_version_ + 1,
                      kInvalidVersion});
}

void SQLTableBuilder::RenameIndex(const std::string& old_name,
                                  const std::string& new_name) {
  auto old_index = FindLastIndexByName(old_name);
  // Check that there is an index with the old name.
  DCHECK(old_index != indices_.rend());
  if (old_name == new_name)  // The easy case.
    return;

  // Check that there is no index with the new name.
  DCHECK(FindLastIndexByName(new_name) == indices_.rend());
  // Check that there is at least one sealed version.
  DCHECK_NE(sealed_version_, kInvalidVersion);
  // Check that the old index has been added before the last version was sealed.
  DCHECK_LE(old_index->min_version, sealed_version_);
  // Check that the old index has not been renamed or deleted yet.
  DCHECK_EQ(old_index->max_version, kInvalidVersion);
  // This index exists in the last sealed version. Therefore it cannot be
  // just replaced, it needs to be kept for generating the migration code.
  old_index->max_version = sealed_version_;
  // Add the new index.
  indices_.push_back(
      {new_name, old_index->columns, sealed_version_ + 1, kInvalidVersion});
}

void SQLTableBuilder::DropIndex(const std::string& name) {
  auto index = FindLastIndexByName(name);
  // Check that an index with the name exists.
  DCHECK(index != indices_.rend());
  // Check that this index exists in the last sealed version and hasn't been
  // renamed or deleted yet.
  // Check that there is at least one sealed version.
  DCHECK_NE(sealed_version_, kInvalidVersion);
  // Check that the index has been added before the last version was sealed.
  DCHECK_LE(index->min_version, sealed_version_);
  // Check that the index has not been renamed or deleted yet.
  DCHECK_EQ(index->max_version, kInvalidVersion);
  // This index exists in the last sealed version. Therefore it cannot be
  // just deleted, it needs to be kept for generating the migration code.
  index->max_version = sealed_version_;
}

std::string SQLTableBuilder::ComputeConstraints(unsigned version) const {
  std::string primary_key;
  std::string unique_key;
  for (const Column& column : columns_) {
    // Ignore dropped columns.
    if (column.max_version < version)
      continue;
    // Ignore columns columns from future versions.
    if (column.min_version > version)
      continue;
    if (column.part_of_primary_key)
      Append(column.name, &primary_key);
    if (column.part_of_unique_key)
      Append(column.name, &unique_key);
  }
  std::string constraints;
  if (!primary_key.empty())
    Append("PRIMARY KEY (" + primary_key + ")", &constraints);
  if (!unique_key.empty())
    Append("UNIQUE (" + unique_key + ")", &constraints);
  return constraints;
}

unsigned SQLTableBuilder::SealVersion() {
  return ++sealed_version_;
}

bool SQLTableBuilder::MigrateFrom(unsigned old_version,
                                  sql::Database* db) const {
  for (; old_version < sealed_version_; ++old_version) {
    if (!MigrateToNextFrom(old_version, db))
      return false;
  }

  return true;
}

bool SQLTableBuilder::CreateTable(sql::Database* db) const {
  DCHECK(IsVersionLastAndSealed(sealed_version_));
  if (db->DoesTableExist(table_name_.c_str()))
    return true;
  std::string constraints = ComputeConstraints(sealed_version_);
  DCHECK(!constraints.empty());

  std::string names;  // Names and types of the current columns.
  for (const Column& column : columns_) {
    if (IsColumnInLastVersion(column))
      Append(column.name + " " + column.type, &names);
  }

  std::vector<std::string>
      create_index_sqls;  // CREATE INDEX statements for the current indices.
  for (const Index& index : indices_) {
    if (IsIndexInLastVersion(index)) {
      create_index_sqls.push_back(base::StringPrintf(
          "CREATE INDEX %s ON %s (%s)", index.name.c_str(), table_name_.c_str(),
          base::JoinString(index.columns, ", ").c_str()));
    }
  }
  sql::Transaction transaction(db);
  return transaction.Begin() &&
         db->Execute(base::StringPrintf("CREATE TABLE %s (%s, %s)",
                                        table_name_.c_str(), names.c_str(),
                                        constraints.c_str())
                         .c_str()) &&
         std::all_of(create_index_sqls.begin(), create_index_sqls.end(),
                     [&db](const std::string& sql) {
                       return db->Execute(sql.c_str());
                     }) &&
         transaction.Commit();
}

std::string SQLTableBuilder::ListAllColumnNames() const {
  DCHECK(IsVersionLastAndSealed(sealed_version_));
  std::string result;
  for (const Column& column : columns_) {
    if (IsColumnInLastVersion(column))
      Append(column.name, &result);
  }
  return result;
}

std::string SQLTableBuilder::ListAllNonuniqueKeyNames() const {
  DCHECK(IsVersionLastAndSealed(sealed_version_));
  std::string result;
  for (const Column& column : columns_) {
    if (IsColumnInLastVersion(column) &&
        !(column.part_of_primary_key || column.part_of_unique_key))
      Append(column.name + "=?", &result);
  }
  return result;
}

std::string SQLTableBuilder::ListAllUniqueKeyNames() const {
  DCHECK(IsVersionLastAndSealed(sealed_version_));
  std::string result;
  for (const Column& column : columns_) {
    if (IsColumnInLastVersion(column) && column.part_of_unique_key) {
      if (!result.empty())
        result += " AND ";
      result += column.name + "=?";
    }
  }
  return result;
}

std::vector<base::StringPiece> SQLTableBuilder::AllPrimaryKeyNames() const {
  DCHECK(IsVersionLastAndSealed(sealed_version_));
  std::vector<base::StringPiece> result;
  result.reserve(columns_.size());
  for (const Column& column : columns_) {
    if (IsColumnInLastVersion(column) && column.part_of_primary_key) {
      result.emplace_back(column.name);
    }
  }
  return result;
}

std::vector<base::StringPiece> SQLTableBuilder::AllIndexNames() const {
  DCHECK(IsVersionLastAndSealed(sealed_version_));
  std::vector<base::StringPiece> result;
  result.reserve(indices_.size());
  for (const Index& index : indices_) {
    if (IsIndexInLastVersion(index)) {
      result.emplace_back(index.name);
    }
  }
  return result;
}

size_t SQLTableBuilder::NumberOfColumns() const {
  DCHECK(IsVersionLastAndSealed(sealed_version_));
  return base::checked_cast<size_t>(std::count_if(
      columns_.begin(), columns_.end(),
      [this](const Column& column) { return IsColumnInLastVersion(column); }));
}

size_t SQLTableBuilder::NumberOfIndices() const {
  DCHECK(IsVersionLastAndSealed(sealed_version_));
  return base::checked_cast<size_t>(std::count_if(
      indices_.begin(), indices_.end(),
      [this](const Index& index) { return IsIndexInLastVersion(index); }));
}

bool SQLTableBuilder::MigrateToNextFrom(unsigned old_version,
                                        sql::Database* db) const {
  DCHECK_LT(old_version, sealed_version_);
  DCHECK_GE(old_version, 0u);
  DCHECK(IsVersionLastAndSealed(sealed_version_));

  // Names of columns from old version, values of which are copied. This
  // contains only the names without their types.
  std::string old_names_of_existing_columns_without_types;
  // Names of columns in new version, except for added ones.
  std::string new_names_of_existing_columns;
  // Names of columns in new version, except for added ones. This contains only
  // the names without their types.
  std::string new_names_of_existing_columns_without_types;
  std::vector<std::string>
      names_of_new_columns_list;  // Names of added columns.

  // A temporary table will be needed if some columns are dropped or renamed,
  // because that is not supported by a single SQLite command.
  bool needs_temp_table = false;

  for (auto column = columns_.begin(); column != columns_.end(); ++column) {
    if (column->max_version == old_version) {
      // This column was deleted after |old_version|. It can have two reasons:
      needs_temp_table = true;
      auto next_column = std::next(column);
      if (next_column != columns_.end() && next_column->gets_previous_data) {
        // (1) The column is being renamed.
        DCHECK_EQ(column->type, next_column->type);
        DCHECK_NE(column->name, next_column->name);
        Append(column->name, &old_names_of_existing_columns_without_types);
        Append(next_column->name + " " + next_column->type,
               &new_names_of_existing_columns);
        Append(next_column->name, &new_names_of_existing_columns_without_types);
        ++column;  // Avoid processing next_column in the next loop.
      } else {
        // (2) The column is being dropped.
      }
    } else if (column->min_version == old_version + 1) {
      // This column was added after old_version.
      if (column->part_of_primary_key || column->part_of_unique_key)
        needs_temp_table = true;
      names_of_new_columns_list.push_back(column->name + " " + column->type);
    } else if (column->min_version <= old_version &&
               (column->max_version == kInvalidVersion ||
                column->max_version > old_version)) {
      // This column stays.
      Append(column->name, &old_names_of_existing_columns_without_types);
      Append(column->name + " " + column->type, &new_names_of_existing_columns);
      Append(column->name, &new_names_of_existing_columns_without_types);
    }
  }

  if (old_names_of_existing_columns_without_types.empty()) {
    // Table didn't exist in this version, and nothing to migrate.
    return true;
  }

  if (needs_temp_table) {
    // Following the instructions from
    // https://www.sqlite.org/lang_altertable.html#otheralter, this code works
    // around the fact that SQLite does not allow dropping or renaming
    // columns. Instead, a new table is constructed, with the new column
    // names, and data from all but dropped columns from the current table are
    // copied into it. After that, the new table is renamed to the current
    // one.

    std::string constraints = ComputeConstraints(old_version + 1);
    DCHECK(!constraints.empty());

    // Foreign key constraints are not enabled for the login database, so no
    // PRAGMA foreign_keys=off needed.
    const std::string temp_table_name = "temp_" + table_name_;

    std::string names_of_all_columns = new_names_of_existing_columns;
    for (const std::string& new_column : names_of_new_columns_list) {
      Append(new_column, &names_of_all_columns);
    }

    sql::Transaction transaction(db);
    if (!(transaction.Begin() &&
          db->Execute(base::StringPrintf(
                          "CREATE TABLE %s (%s, %s)", temp_table_name.c_str(),
                          names_of_all_columns.c_str(), constraints.c_str())
                          .c_str()) &&
          db->Execute(base::StringPrintf(
                          "INSERT OR REPLACE INTO %s (%s) SELECT %s FROM %s",
                          temp_table_name.c_str(),
                          new_names_of_existing_columns_without_types.c_str(),
                          old_names_of_existing_columns_without_types.c_str(),
                          table_name_.c_str())
                          .c_str()) &&
          db->Execute(base::StringPrintf("DROP TABLE %s", table_name_.c_str())
                          .c_str()) &&
          db->Execute(base::StringPrintf("ALTER TABLE %s RENAME TO %s",
                                         temp_table_name.c_str(),
                                         table_name_.c_str())
                          .c_str()) &&
          transaction.Commit())) {
      return false;
    }
  } else if (!names_of_new_columns_list.empty()) {
    // If no new table has been created, we need to add the new columns here if
    // any.
    sql::Transaction transaction(db);
    if (!(transaction.Begin() &&
          std::all_of(names_of_new_columns_list.begin(),
                      names_of_new_columns_list.end(),
                      [this, &db](const std::string& name) {
                        return db->Execute(
                            base::StringPrintf("ALTER TABLE %s ADD COLUMN %s",
                                               table_name_.c_str(),
                                               name.c_str())
                                .c_str());
                      }) &&
          transaction.Commit())) {
      return false;
    }
  }

  return MigrateIndicesToNextFrom(old_version, db);
}

bool SQLTableBuilder::MigrateIndicesToNextFrom(unsigned old_version,
                                               sql::Database* db) const {
  DCHECK_LT(old_version, sealed_version_);
  DCHECK(IsVersionLastAndSealed(sealed_version_));
  sql::Transaction transaction(db);
  if (!transaction.Begin())
    return false;

  for (const auto& index : indices_) {
    std::string sql;
    if (index.max_version <= old_version) {
      // Index is not supposed to exist in the new version.
      sql = base::StringPrintf("DROP INDEX IF EXISTS %s", index.name.c_str());
    } else if (index.min_version <= old_version + 1) {
      // Index is supposed to exist in the new version.
      sql = base::StringPrintf("CREATE INDEX IF NOT EXISTS %s ON %s (%s)",
                               index.name.c_str(), table_name_.c_str(),
                               base::JoinString(index.columns, ", ").c_str());
    } else {
      continue;
    }

    if (!db->Execute(sql.c_str()))
      return false;
  }

  return transaction.Commit();
}

std::vector<SQLTableBuilder::Column>::reverse_iterator
SQLTableBuilder::FindLastColumnByName(const std::string& name) {
  return std::find_if(
      columns_.rbegin(), columns_.rend(),
      [&name](const Column& column) { return name == column.name; });
}

std::vector<SQLTableBuilder::Index>::reverse_iterator
SQLTableBuilder::FindLastIndexByName(const std::string& name) {
  return std::find_if(
      indices_.rbegin(), indices_.rend(),
      [&name](const Index& index) { return name == index.name; });
}

bool SQLTableBuilder::IsVersionLastAndSealed(unsigned version) const {
  // Is |version| the last sealed one?
  if (sealed_version_ != version)
    return false;
  // Is the current version the last sealed one? In other words, is there
  // neither a column or index added past the sealed version (min_version >
  // sealed) nor deleted one version after the sealed (max_version == sealed)?
  return std::none_of(columns_.begin(), columns_.end(),
                      [this](const Column& column) {
                        return column.min_version > sealed_version_ ||
                               column.max_version == sealed_version_;
                      }) &&
         std::none_of(indices_.begin(), indices_.end(),
                      [this](const Index& index) {
                        return index.min_version > sealed_version_ ||
                               index.max_version == sealed_version_;
                      });
}

bool SQLTableBuilder::IsColumnInLastVersion(const Column& column) const {
  DCHECK(IsVersionLastAndSealed(sealed_version_));
  return (column.min_version <= sealed_version_ &&
          (column.max_version == kInvalidVersion ||
           column.max_version >= sealed_version_));
}

bool SQLTableBuilder::IsIndexInLastVersion(const Index& index) const {
  DCHECK(IsVersionLastAndSealed(sealed_version_));
  return (index.min_version <= sealed_version_ &&
          (index.max_version == kInvalidVersion ||
           index.max_version >= sealed_version_));
}

}  // namespace password_manager
