Index: components/password_manager/core/browser/sql_table_builder.h |
diff --git a/components/password_manager/core/browser/sql_table_builder.h b/components/password_manager/core/browser/sql_table_builder.h |
new file mode 100644 |
index 0000000000000000000000000000000000000000..bac1394f123937eae7095bd4b838606dcbd41af1 |
--- /dev/null |
+++ b/components/password_manager/core/browser/sql_table_builder.h |
@@ -0,0 +1,149 @@ |
+// 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. |
+ |
+#ifndef COMPONENTS_PASSWORD_MANAGER_CORE_BROWSER_SQL_TABLE_BUILDER_H_ |
+#define COMPONENTS_PASSWORD_MANAGER_CORE_BROWSER_SQL_TABLE_BUILDER_H_ |
+ |
+#include <limits> |
+#include <list> |
+#include <string> |
+ |
+#include "base/macros.h" |
+ |
+namespace sql { |
+class Connection; |
+} |
+ |
+namespace password_manager { |
+ |
+// Use this class to represent the versioned evolution of a SQLite table |
+// structure and generate creating and migrating statements for it. |
+// |
+// Two values are currently hard-coded, because they are the same in the |
+// current use-cases: |
+// * The table name is hard-coded as "logins". |
+// * The index is built for column "signon_realm" which is expected to exist. |
+// |
+// Usage example: |
+// |
+// SQLTableBuilder builder; |
+// |
+// // First describe a couple of versions: |
+// builder.AddColumn("name", "VARCHAR"); |
+// builder.AddColumn("icon", "VARCHAR"); |
+// builder.AddColumn("password", "VARCHAR NOT NULL"); |
+// unsigned version = builder.SealVersion(); // Version 0 is sealed. |
+// DCHECK_EQ(0u, version); |
+// builder.RenameColumn("icon", "avatar"); |
+// version = builder.SealVersion(); // Version 1 is sealed. |
+// DCHECK_EQ(1u, version); |
+// |
+// // Now, assuming that |db| has a table "logins" in a state corresponding |
+// // version 0, this will migrate it to version 1: |
+// sql::Connection* db = ...; |
+// builder.MigrateToNextFrom(0, db); |
+// |
+// // And assuming |db| has no table called "logins", this will create one |
+// // in a state corresponding the latest sealed version: |
+// builder.CreateTable(db); |
+class SQLTableBuilder { |
+ public: |
+ // Create the builder for "logins". |
+ SQLTableBuilder(); |
+ |
+ ~SQLTableBuilder(); |
+ |
+ // Adds a column in the table description, with |name| and |type|. |name| |
+ // must not have been added to the table in this version before. |
+ void AddColumn(const std::string& name, const std::string& type); |
+ |
+ // As AddColumn but also adds column |name| to the unique key of the table. |
+ // SealVersion must not have been called yet (the builder does not currently |
+ // support migration code for changing the unique key between versions). |
+ void AddColumnToUniqueKey(const std::string& name, const std::string& type); |
+ |
+ // Renames column |old_name| to |new_name|. |old_name| must have been added in |
+ // the past. The column "signon_realm" must not be renamed. |
+ void RenameColumn(const std::string& old_name, const std::string& new_name); |
+ |
+ // Removes column |name|. |name| must have been added in the past. The column |
+ // "signon_realm" must not be renamed. |
+ void DropColumn(const std::string& name); |
+ |
+ // Increments the internal version counter and marks the current state of the |
+ // table as that version. Returns the sealed version. Calling any of the |
+ // *Column* methods above will result in starting a new version which is not |
+ // considered sealed. The first version is 0. The column "signon_realm" must |
+ // be present in |columns_| every time this is called, and at least one call |
+ // to AddColumnToUniqueKey must have been done before this is called the first |
+ // time. |
+ unsigned SealVersion(); |
+ |
+ // Assuming that the database connected through |db| contains a table called |
+ // "logins" in a state described by version |old_version|, migrates it to |
+ // the current version, which must be sealed. Returns true on success. |
+ bool MigrateFrom(unsigned old_version, sql::Connection* db); |
+ |
+ // If |db| connects to a database where table "logins" already exists, |
+ // this is a no-op and returns true. Otherwise, "logins" is created in a |
+ // state described by the current version known to the builder. The current |
+ // version must be sealed. Returns true on success. |
+ bool CreateTable(sql::Connection* db); |
+ |
+ // Returns the comma-separated list of all column names present in the last |
+ // version. The last version must be sealed. |
+ std::string ListAllColumnNames() const; |
+ |
+ // Same as ListAllColumnNames, but for non-unique key names only, and with |
+ // names followed by " = ?". |
+ std::string ListAllNonuniqueKeyNames() const; |
+ |
+ // Same as ListAllNonuniqueKeyNames, but for unique key names and separated by |
+ // " AND ". |
+ std::string ListAllUniqueKeyNames() const; |
+ |
+ // Returns the number of all columns present in the last version. The last |
+ // version must be sealed. |
+ size_t NumberOfColumns() const; |
+ |
+ private: |
+ // Stores the information about one column (name, type, etc.). |
+ struct Column; |
+ |
+ static unsigned constexpr kInvalidVersion = |
+ std::numeric_limits<unsigned>::max(); |
+ |
+ // Assuming that the database connected through |db| contains a table called |
+ // "logins" in a state described by version |old_version|, migrates it to |
+ // version |old_version + 1|. The current version known to the builder must be |
+ // at least |old_version + 1| and sealed. Returns true on success. |
+ bool MigrateToNextFrom(unsigned old_version, sql::Connection* db); |
+ |
+ // Looks up column named |name| in |columns_|. If present, returns the last |
+ // one. |
+ std::list<Column>::reverse_iterator FindLastByName(const std::string& name); |
+ |
+ // Returns whether the last version is |version| and whether it was sealed |
+ // (by calling SealVersion with no table modifications afterwards). |
+ bool IsVersionLastAndSealed(unsigned version) const; |
+ |
+ // Whether |column| is present in the last version. The last version must be |
+ // sealed. |
+ bool IsInLastVersion(const Column& column) const; |
+ |
+ // Last sealed version, kInvalidVersion means "none". |
+ unsigned sealed_version_ = kInvalidVersion; |
+ |
+ std::list<Column> columns_; // Columns of the table, across all versions. |
+ |
+ // The "UNIQUE" part of an SQL CREATE TABLE constraint. This value is |
+ // computed dring sealing the first version (0). |
+ std::string unique_constraint_; |
+ |
+ DISALLOW_COPY_AND_ASSIGN(SQLTableBuilder); |
+}; |
+ |
+} // namespace password_manager |
+ |
+#endif // COMPONENTS_PASSWORD_MANAGER_CORE_BROWSER_SQL_TABLE_BUILDER_H_ |