Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(456)

Unified Diff: components/password_manager/core/browser/sql_table_builder.h

Issue 2126713006: Refactor LoginDatabase migration (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: Comments addressed Created 4 years, 5 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View side-by-side diff with in-line comments
Download patch
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_

Powered by Google App Engine
This is Rietveld 408576698