OneToManyTable.h (8189B)
1 // Copyright (c) Microsoft Corporation. 2 // Licensed under the MIT License. 3 #pragma once 4 #include <winget/SQLiteWrapper.h> 5 #include <string> 6 #include <string_view> 7 #include <vector> 8 9 10 namespace AppInstaller::Repository::Microsoft::Schema::V1_0 11 { 12 // Allow the different schema version to indicate which they are. 13 enum class OneToManyTableSchema 14 { 15 // Does not used a named unique index for either table. 16 // Map table has primary key and rowid. 17 Version_1_0, 18 // Uses a named unique index for both tables. 19 // Map table has rowid. 20 Version_1_1, 21 // Uses a named unique index for data table. (No change from 1.1) 22 // Map table has primary key and no rowid. 23 Version_1_7, 24 }; 25 26 namespace details 27 { 28 // Returns the map table name for a given table. 29 std::string OneToManyTableGetMapTableName(std::string_view tableName); 30 31 // Returns the manifest column name. 32 std::string_view OneToManyTableGetManifestColumnName(); 33 34 // Create the tables. 35 void CreateOneToManyTable(SQLite::Connection& connection, OneToManyTableSchema schemaVersion, std::string_view tableName, std::string_view valueName); 36 37 // Drop the tables. 38 void DropOneToManyTable(SQLite::Connection& connection, std::string_view tableName); 39 40 // Gets all values associated with the given manifest id. 41 std::vector<std::string> OneToManyTableGetValuesByManifestId( 42 const SQLite::Connection& connection, 43 std::string_view tableName, 44 std::string_view valueName, 45 SQLite::rowid_t manifestId); 46 47 // Ensures that the value exists and inserts mapping entries. 48 void OneToManyTableEnsureExistsAndInsert(SQLite::Connection& connection, 49 std::string_view tableName, std::string_view valueName, 50 const std::vector<Utility::NormalizedString>& values, SQLite::rowid_t manifestId); 51 52 // Updates the mapping table to represent the given values for the manifest. 53 bool OneToManyTableUpdateIfNeededByManifestId(SQLite::Connection& connection, 54 std::string_view tableName, std::string_view valueName, 55 const std::vector<Utility::NormalizedString>& values, SQLite::rowid_t manifestId); 56 57 // Deletes the mapping rows for the given manifest, then removes any unused data rows. 58 void OneToManyTableDeleteIfNotNeededByManifestId(SQLite::Connection& connection, std::string_view tableName, std::string_view valueName, SQLite::rowid_t manifestId); 59 60 // Removes data that is no longer needed for an index that is to be published. 61 void OneToManyTablePrepareForPackaging(SQLite::Connection& connection, std::string_view tableName, OneToManyTableSchema schemaVersion, bool preserveManifestIndex, bool preserveValuesIndex); 62 63 // Checks the consistency of the index to ensure that every referenced row exists. 64 // Returns true if index is consistent; false if it is not. 65 bool OneToManyTableCheckConsistency(const SQLite::Connection& connection, std::string_view tableName, std::string_view valueName, bool log); 66 67 // Determines if the table is empty. 68 bool OneToManyTableIsEmpty(SQLite::Connection& connection, std::string_view tableName); 69 70 // Prepares a statement for replacing all of the map data to point to a single manifest for a given id. 71 SQLite::Statement OneToManyTablePrepareMapDataFoldingStatement(const SQLite::Connection& connection, std::string_view tableName); 72 } 73 74 // Gets the manifest id that the PrepareMapDataFoldingStatement will fold to for the given manifest id. 75 std::optional<SQLite::rowid_t> OneToManyTableGetMapDataFoldingManifestTargetId(const SQLite::Connection& connection, SQLite::rowid_t manifestId); 76 77 // A table that represents a value that is 1:N with a primary entry. 78 template <typename TableInfo> 79 struct OneToManyTable 80 { 81 // The name of the table. 82 static constexpr std::string_view TableName() 83 { 84 return TableInfo::TableName(); 85 } 86 87 // The value name of the table. 88 static constexpr std::string_view ValueName() 89 { 90 return TableInfo::ValueName(); 91 } 92 93 // Value indicating type. 94 static constexpr bool IsOneToOne() 95 { 96 return false; 97 } 98 99 // Creates the table with named indices. 100 static void Create(SQLite::Connection& connection, OneToManyTableSchema schemaVersion) 101 { 102 details::CreateOneToManyTable(connection, schemaVersion, TableInfo::TableName(), TableInfo::ValueName()); 103 } 104 105 // Drops the table. 106 static void Drop(SQLite::Connection& connection) 107 { 108 details::DropOneToManyTable(connection, TableInfo::TableName()); 109 } 110 111 // Gets all values associated with the given manifest id. 112 static std::vector<std::string> GetValuesByManifestId(const SQLite::Connection& connection, SQLite::rowid_t manifestId) 113 { 114 return details::OneToManyTableGetValuesByManifestId(connection, TableInfo::TableName(), TableInfo::ValueName(), manifestId); 115 } 116 117 // Ensures that all values exist in the data table, and inserts into the mapping table for the given manifest id. 118 static void EnsureExistsAndInsert(SQLite::Connection& connection, const std::vector<Utility::NormalizedString>& values, SQLite::rowid_t manifestId) 119 { 120 details::OneToManyTableEnsureExistsAndInsert(connection, TableInfo::TableName(), TableInfo::ValueName(), values, manifestId); 121 } 122 123 // Updates the mapping table to represent the given values for the manifest. 124 static bool UpdateIfNeededByManifestId(SQLite::Connection& connection, const std::vector<Utility::NormalizedString>& values, SQLite::rowid_t manifestId) 125 { 126 return details::OneToManyTableUpdateIfNeededByManifestId(connection, TableInfo::TableName(), TableInfo::ValueName(), values, manifestId); 127 } 128 129 // Deletes the mapping rows for the given manifest, then removes any unused data rows. 130 static void DeleteIfNotNeededByManifestId(SQLite::Connection& connection, SQLite::rowid_t manifestId) 131 { 132 details::OneToManyTableDeleteIfNotNeededByManifestId(connection, TableInfo::TableName(), TableInfo::ValueName(), manifestId); 133 } 134 135 // Removes data that is no longer needed for an index that is to be published. 136 // Preserving the manifest index will improve the efficiency of finding the values associated with a manifest. 137 // Preserving the values index will improve searching when it is primarily done by equality. 138 static void PrepareForPackaging(SQLite::Connection& connection, OneToManyTableSchema schemaVersion, bool preserveManifestIndex, bool preserveValuesIndex) 139 { 140 details::OneToManyTablePrepareForPackaging(connection, TableInfo::TableName(), schemaVersion, preserveManifestIndex, preserveValuesIndex); 141 } 142 143 // Checks the consistency of the index to ensure that every referenced row exists. 144 // Returns true if index is consistent; false if it is not. 145 static bool CheckConsistency(const SQLite::Connection& connection, bool log) 146 { 147 return details::OneToManyTableCheckConsistency(connection, TableInfo::TableName(), TableInfo::ValueName(), log); 148 } 149 150 // Determines if the table is empty. 151 static bool IsEmpty(SQLite::Connection& connection) 152 { 153 return details::OneToManyTableIsEmpty(connection, TableInfo::TableName()); 154 } 155 156 // Prepares a statement for replacing all of the map data to point to a single manifest for a given id. 157 static SQLite::Statement PrepareMapDataFoldingStatement(const SQLite::Connection& connection) 158 { 159 return details::OneToManyTablePrepareMapDataFoldingStatement(connection, TableInfo::TableName()); 160 } 161 }; 162 }