winget-cli

Unnamed repository; edit this file 'description' to name the repository.
Log | Files | Refs | README | LICENSE

ManifestTable.h (12515B)


      1 // Copyright (c) Microsoft Corporation.
      2 // Licensed under the MIT License.
      3 #pragma once
      4 #include <winget/SQLiteWrapper.h>
      5 #include <winget/SQLiteStatementBuilder.h>
      6 #include "Microsoft/Schema/1_0/VirtualTableBase.h"
      7 #include <initializer_list>
      8 #include <optional>
      9 #include <string_view>
     10 #include <utility>
     11 #include <vector>
     12 
     13 
     14 namespace AppInstaller::Repository::Microsoft::Schema::V1_0
     15 {
     16     namespace details
     17     {
     18         template<typename Table>
     19         std::string_view GetManifestTableColumnName()
     20         {
     21             if constexpr (std::is_base_of<VirtualTableBase, Table>())
     22             {
     23                 return Table::ManifestColumnName();
     24             }
     25             else
     26             {
     27                 return Table::ValueName();
     28             }
     29         }
     30 
     31         // Selects a manifest by the given value id.
     32         std::optional<SQLite::rowid_t> ManifestTableSelectByValueIds(
     33             const SQLite::Connection& connection,
     34             std::initializer_list<std::string_view> values,
     35             std::initializer_list<SQLite::rowid_t> ids);
     36 
     37         // Gets the requested ids for the manifest with the given rowid.
     38         SQLite::Statement ManifestTableGetIdsById_Statement(
     39             const SQLite::Connection& connection,
     40             SQLite::rowid_t id,
     41             std::initializer_list<std::string_view> values,
     42             bool stepAndVerify = true);
     43 
     44         // Gets the requested values for the manifest with the given rowid.
     45         SQLite::Statement ManifestTableGetValuesById_Statement(
     46             const SQLite::Connection& connection,
     47             SQLite::rowid_t id,
     48             std::initializer_list<SQLite::Builder::QualifiedColumn> columns,
     49             std::initializer_list<std::string_view> manifestColumnNames,
     50             bool stepAndVerify = true);
     51 
     52         // Gets all values for rows that match the given ids.
     53         SQLite::Statement ManifestTableGetAllValuesByIds_Statement(
     54             const SQLite::Connection& connection,
     55             std::initializer_list<SQLite::Builder::QualifiedColumn> valueColumns,
     56             std::initializer_list<SQLite::Builder::QualifiedColumn> joinColumns,
     57             std::initializer_list<std::string_view> idColumns,
     58             std::initializer_list<SQLite::rowid_t> ids);
     59 
     60         // Gets all values for rows that match the given ids.
     61         std::vector<std::pair<SQLite::rowid_t, std::string>> ManifestTableGetAllValuesByIds(
     62             const SQLite::Connection& connection,
     63             std::initializer_list<SQLite::Builder::QualifiedColumn> valueColumns,
     64             std::initializer_list<SQLite::Builder::QualifiedColumn> joinColumns,
     65             std::initializer_list<std::string_view> idColumns,
     66             std::initializer_list<SQLite::rowid_t> ids);
     67 
     68         // Builds the search select statement base on the given values.
     69         std::vector<int> ManifestTableBuildSearchStatement(
     70             SQLite::Builder::StatementBuilder& builder,
     71             std::initializer_list<SQLite::Builder::QualifiedColumn> columns,
     72             std::initializer_list<bool> isOneToOnes,
     73             std::string_view manifestAlias,
     74             std::string_view valueAlias,
     75             bool useLike);
     76 
     77         // Prepares a statement to update the value of a single column for the manifest with the given rowid.
     78         // The first bind value will be the value to set.
     79         // The second bind value will be the manifest rowid to modify.
     80         SQLite::Statement ManifestTableUpdateValueIdById_Statement(SQLite::Connection& connection, std::string_view valueName);
     81 
     82         // Checks the consistency of the index to ensure that every referenced row exists.
     83         // Returns true if index is consistent; false if it is not.
     84         bool ManifestTableCheckConsistency(const SQLite::Connection& connection, const SQLite::Builder::QualifiedColumn& target, std::string_view manifestColumnName, bool log);
     85     }
     86 
     87     // Info on the manifest columns.
     88     struct ManifestColumnInfo
     89     {
     90         std::string_view Name;
     91         bool PrimaryKey;
     92         bool Unique;
     93     };
     94 
     95     // Information on a column being added via ALTER TABLE
     96     struct AddedColumnInfo
     97     {
     98         std::string_view Name;
     99         SQLite::Builder::Type Type;
    100     };
    101 
    102     // A value that is 1:1 with the manifest.
    103     struct ManifestOneToOneValue
    104     {
    105         std::string_view Name;
    106         SQLite::rowid_t Value;
    107     };
    108 
    109     // A table that represents a single manifest
    110     struct ManifestTable
    111     {
    112         // Get the table name.
    113         static std::string_view TableName();
    114 
    115         // Creates the table with named indices.
    116         static void Create(SQLite::Connection& connection, std::initializer_list<ManifestColumnInfo> values);
    117 
    118         // Alters the table, adding the columns provided.
    119         static void AddColumn(SQLite::Connection& connection, AddedColumnInfo value);
    120 
    121         // Creates the table with standard primary keys.
    122         static void Create_deprecated(SQLite::Connection& connection, std::initializer_list<ManifestColumnInfo> values);
    123 
    124         // Drops the table.
    125         static void Drop(SQLite::Connection& connection);
    126 
    127         // Insert the given values into the table.
    128         static SQLite::rowid_t Insert(SQLite::Connection& connection, std::initializer_list<ManifestOneToOneValue> values);
    129 
    130         // Gets a value indicating whether the manifest with rowid id exists.
    131         static bool ExistsById(const SQLite::Connection& connection, SQLite::rowid_t id);
    132 
    133         // Select the first rowid of the manifest with the given value.
    134         template <typename... Tables>
    135         static std::optional<SQLite::rowid_t> SelectByValueIds(const SQLite::Connection& connection, std::initializer_list<SQLite::rowid_t> ids)
    136         {
    137             static_assert(sizeof...(Tables) >= 1);
    138             return details::ManifestTableSelectByValueIds(connection, { Tables::ValueName()... }, ids);
    139         }
    140 
    141         // Gets the ids requested for the manifest with the given rowid.
    142         template <typename... Tables>
    143         static auto GetIdsById(const SQLite::Connection& connection, SQLite::rowid_t id)
    144         {
    145             return details::ManifestTableGetIdsById_Statement(connection, id, { details::GetManifestTableColumnName<Tables>()...}).GetRow<typename Tables::id_t...>();
    146         }
    147 
    148         // Gets the id requested for the manifest with the given rowid, if it exists.
    149         template <typename Table>
    150         static std::optional<typename Table::id_t> GetIdById(const SQLite::Connection& connection, SQLite::rowid_t id)
    151         {
    152             auto statement = details::ManifestTableGetIdsById_Statement(connection, id, { details::GetManifestTableColumnName<Table>() }, false);
    153             if (statement.Step()) { return statement.GetColumn<typename Table::id_t>(0); }
    154             else { return std::nullopt; }
    155         }
    156 
    157         // Gets the values requested for the manifest with the given rowid.
    158         template <typename... Tables>
    159         static auto GetValuesById(const SQLite::Connection& connection, SQLite::rowid_t id)
    160         {
    161             return details::ManifestTableGetValuesById_Statement(connection, id, { SQLite::Builder::QualifiedColumn{ Tables::TableName(), Tables::ValueName() }... }, { details::GetManifestTableColumnName<Tables>()... }).GetRow<typename Tables::value_t...>();
    162         }
    163 
    164         // Gets the value requested for the manifest with the given rowid, if it exists.
    165         template <typename Table>
    166         static std::optional<typename Table::value_t> GetValueById(const SQLite::Connection& connection, SQLite::rowid_t id)
    167         {
    168             auto statement = details::ManifestTableGetValuesById_Statement(connection, id, { SQLite::Builder::QualifiedColumn{ Table::TableName(), Table::ValueName() } }, { details::GetManifestTableColumnName<Table>() }, false);
    169             if (statement.Step()) { return statement.GetColumn<typename Table::value_t>(0); }
    170             else { return std::nullopt; }
    171         }
    172 
    173         // Gets the row ids and values for rows that match the given ids.
    174         template <typename ValueTable, typename... IdTables>
    175         static std::vector<std::pair<SQLite::rowid_t, typename ValueTable::value_t>> GetAllValuesByIds(const SQLite::Connection& connection, std::initializer_list<SQLite::rowid_t> ids)
    176         {
    177             return details::ManifestTableGetAllValuesByIds(connection,
    178                 { SQLite::Builder::QualifiedColumn{ ValueTable::TableName(), SQLite::RowIDName }, SQLite::Builder::QualifiedColumn{ ValueTable::TableName(), ValueTable::ValueName() } },
    179                 { SQLite::Builder::QualifiedColumn{ ValueTable::TableName(), ValueTable::ValueName() } },
    180                 { IdTables::ValueName()... }, ids);
    181         }
    182 
    183         // Gets all values for rows that match the given id.
    184         template <typename IdTable, typename... ValueTables>
    185         static std::vector<std::tuple<SQLite::rowid_t, typename ValueTables::value_t...>> GetAllValuesById(const SQLite::Connection& connection, SQLite::rowid_t id)
    186         {
    187             auto stmt = details::ManifestTableGetAllValuesByIds_Statement(connection,
    188                 { SQLite::Builder::QualifiedColumn{ TableName(), SQLite::RowIDName }, SQLite::Builder::QualifiedColumn{ ValueTables::TableName(), ValueTables::ValueName() }... },
    189                 { SQLite::Builder::QualifiedColumn{ ValueTables::TableName(), ValueTables::ValueName() }... },
    190                 { IdTable::ValueName() }, { id });
    191             std::vector<std::tuple<SQLite::rowid_t, typename ValueTables::value_t...>> result;
    192             while (stmt.Step())
    193             {
    194                 result.emplace_back(stmt.GetRow<SQLite::rowid_t, typename ValueTables::value_t...>());
    195             }
    196             return result;
    197         }
    198 
    199         // Builds the search select statement base on the given values.
    200         // If more than one table is provided, no value will be captured.
    201         // The return value is the bind indices of the values to match against.
    202         template <typename... Table>
    203         static std::vector<int> BuildSearchStatement(SQLite::Builder::StatementBuilder& builder, std::string_view manifestAlias, std::string_view valueAlias, bool useLike)
    204         {
    205             return details::ManifestTableBuildSearchStatement(builder, { SQLite::Builder::QualifiedColumn{ Table::TableName(), Table::ValueName() }... }, { Table::IsOneToOne()... }, manifestAlias, valueAlias, useLike);
    206         }
    207 
    208         // Update the value of a single column for the manifest with the given rowid.
    209         template <typename Table>
    210         static void UpdateValueIdById(SQLite::Connection& connection, SQLite::rowid_t id, const typename Table::id_t& value)
    211         {
    212             auto stmt = details::ManifestTableUpdateValueIdById_Statement(connection, details::GetManifestTableColumnName<Table>());
    213             stmt.Bind(1, value);
    214             stmt.Bind(2, id);
    215             stmt.Execute();
    216         }
    217 
    218         // Deletes the manifest row with the given rowid.
    219         static void DeleteById(SQLite::Connection& connection, SQLite::rowid_t id);
    220 
    221         // Removes data that is no longer needed for an index that is to be published.
    222         static void PrepareForPackaging(SQLite::Connection& connection, std::initializer_list<std::string_view> values);
    223 
    224         // Removes data that is no longer needed for an index that is to be published.
    225         static void PrepareForPackaging_deprecated(SQLite::Connection& connection, std::initializer_list<std::string_view> values);
    226 
    227         // Checks if the row id is present in the column denoted by the value supplied.
    228         static bool IsValueReferenced(const SQLite::Connection& connection, std::string_view valueName, SQLite::rowid_t valueRowId);
    229 
    230         // Checks the consistency of the index to ensure that every referenced row exists.
    231         // Returns true if index is consistent; false if it is not.
    232         template <typename Table>
    233         static bool CheckConsistency(const SQLite::Connection& connection, bool log)
    234         {
    235             return details::ManifestTableCheckConsistency(
    236                 connection, SQLite::Builder::QualifiedColumn{ Table::TableName(), Table::ValueName() }, details::GetManifestTableColumnName<Table>(), log);
    237         }
    238 
    239         // Determines if the table is empty.
    240         static bool IsEmpty(SQLite::Connection& connection);
    241     };
    242 }