winget-cli

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

PackagesTable.h (8998B)


      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 <initializer_list>
      7 #include <optional>
      8 #include <string_view>
      9 #include <utility>
     10 #include <vector>
     11 
     12 
     13 namespace AppInstaller::Repository::Microsoft::Schema::V2_0
     14 {
     15     namespace details
     16     {
     17         // Info on the columns.
     18         struct ColumnInfo
     19         {
     20             template<typename Column>
     21             static constexpr ColumnInfo Create()
     22             {
     23                 ColumnInfo result;
     24                 result.Name = Column::Name;
     25                 result.Type = Column::Type;
     26                 result.PrimaryKey = Column::PrimaryKey;
     27                 result.AllowNull = Column::AllowNull;
     28                 return result;
     29             }
     30 
     31             std::string_view Name;
     32             SQLite::Builder::Type Type = {};
     33             bool PrimaryKey = false;
     34             bool AllowNull = false;
     35         };
     36 
     37         // Creates the table.
     38         void PackagesTableCreate(SQLite::Connection& connection, std::initializer_list<ColumnInfo> values);
     39 
     40         // Gets the requested values for the manifest with the given rowid.
     41         SQLite::Statement PackagesTableGetValuesById_Statement(
     42             const SQLite::Connection& connection,
     43             SQLite::rowid_t id,
     44             std::initializer_list<std::string_view> columns,
     45             bool stepAndVerify = true);
     46 
     47         // Prepares a statement to update the value of a single column for the manifest with the given rowid.
     48         // The first bind value will be the value to set.
     49         // The second bind value will be the manifest rowid to modify.
     50         SQLite::Statement PackagesTableUpdateValueIdById_Statement(SQLite::Connection& connection, std::string_view valueName);
     51 
     52         // Removes data that is no longer needed for an index that is to be published.
     53         void PackagesTablePrepareForPackaging(SQLite::Connection& connection, std::initializer_list<ColumnInfo> values);
     54 
     55         // Checks for embedded nulls in the database.
     56         bool PackagesTableCheckConsistency(const SQLite::Connection& connection, std::initializer_list<std::string_view> values, bool log);
     57     }
     58 
     59     // A table in which each row represents a single package.
     60     struct PackagesTable
     61     {
     62         // Get the table name.
     63         static std::string_view TableName();
     64 
     65         struct IdColumn
     66         {
     67             static constexpr std::string_view Name = "id"sv;
     68             static constexpr SQLite::Builder::Type Type = SQLite::Builder::Type::Text;
     69             static constexpr bool PrimaryKey = true;
     70             static constexpr bool AllowNull = false;
     71         };
     72 
     73         struct NameColumn
     74         {
     75             static constexpr std::string_view Name = "name"sv;
     76             static constexpr SQLite::Builder::Type Type = SQLite::Builder::Type::Text;
     77             static constexpr bool PrimaryKey = false;
     78             static constexpr bool AllowNull = false;
     79         };
     80 
     81         struct MonikerColumn
     82         {
     83             static constexpr std::string_view Name = "moniker"sv;
     84             static constexpr SQLite::Builder::Type Type = SQLite::Builder::Type::Text;
     85             static constexpr bool PrimaryKey = false;
     86             static constexpr bool AllowNull = true;
     87         };
     88 
     89         struct LatestVersionColumn
     90         {
     91             static constexpr std::string_view Name = "latest_version"sv;
     92             static constexpr SQLite::Builder::Type Type = SQLite::Builder::Type::Text;
     93             static constexpr bool PrimaryKey = false;
     94             static constexpr bool AllowNull = false;
     95         };
     96 
     97         struct ARPMinVersionColumn
     98         {
     99             static constexpr std::string_view Name = "arp_min_version"sv;
    100             static constexpr SQLite::Builder::Type Type = SQLite::Builder::Type::Text;
    101             static constexpr bool PrimaryKey = false;
    102             static constexpr bool AllowNull = true;
    103         };
    104 
    105         struct ARPMaxVersionColumn
    106         {
    107             static constexpr std::string_view Name = "arp_max_version"sv;
    108             static constexpr SQLite::Builder::Type Type = SQLite::Builder::Type::Text;
    109             static constexpr bool PrimaryKey = false;
    110             static constexpr bool AllowNull = true;
    111         };
    112 
    113         struct HashColumn
    114         {
    115             static constexpr std::string_view Name = "hash"sv;
    116             static constexpr SQLite::Builder::Type Type = SQLite::Builder::Type::Blob;
    117             static constexpr bool PrimaryKey = false;
    118             static constexpr bool AllowNull = true;
    119         };
    120 
    121         using ColumnInfo = details::ColumnInfo;
    122 
    123         // Creates the table.
    124         template <typename... Columns>
    125         static void Create(SQLite::Connection& connection)
    126         {
    127             details::PackagesTableCreate(connection, { ColumnInfo::Create<Columns>()... });
    128         }
    129 
    130         // Drops the table.
    131         static void Drop(SQLite::Connection& connection);
    132 
    133         // Determine if the table currently exists in the database.
    134         static bool Exists(const SQLite::Connection& connection);
    135 
    136         // Alters the table, adding the column provided.
    137         static void AddColumn(SQLite::Connection& connection, const ColumnInfo& value);
    138 
    139         // A string value for the package.
    140         struct NameValuePair
    141         {
    142             std::string_view Name;
    143             std::string Value;
    144         };
    145 
    146         // Insert the given values into the table.
    147         static SQLite::rowid_t Insert(SQLite::Connection& connection, const std::vector<NameValuePair>& values);
    148 
    149         // Gets a value indicating whether the package with rowid exists.
    150         static bool ExistsById(const SQLite::Connection& connection, SQLite::rowid_t rowid);
    151 
    152         // Gets all row ids from the table.
    153         static std::vector<SQLite::rowid_t> GetAllRowIds(const SQLite::Connection& connection, std::string_view orderByColumn, size_t limit = 0);
    154 
    155         // Gets the total number of rows in the table.
    156         static uint64_t GetCount(const SQLite::Connection& connection);
    157 
    158         // Gets the values requested for the package with the given rowid.
    159         template <typename... Columns>
    160         static auto GetValuesById(const SQLite::Connection& connection, SQLite::rowid_t rowid)
    161         {
    162             return details::PackagesTableGetValuesById_Statement(connection, rowid, { Columns::Name... }).GetRow<typename SQLite::Builder::TypeInfo<Columns::Type, Columns::AllowNull>::value_t...>();
    163         }
    164 
    165         // Gets the value requested for the package with the given rowid, if it exists.
    166         template <typename Column>
    167         static std::optional<typename SQLite::Builder::TypeInfo<Column::Type, false>::value_t> GetValueById(const SQLite::Connection& connection, SQLite::rowid_t rowid)
    168         {
    169             auto statement = details::PackagesTableGetValuesById_Statement(connection, rowid, { Column::Name }, false);
    170             if (statement.Step()) { return statement.GetColumn<typename SQLite::Builder::TypeInfo<Column::Type, Column::AllowNull>::value_t>(0); }
    171             else { return std::nullopt; }
    172         }
    173 
    174         // Builds the search select statement base on the given value.
    175         // The return value is the bind index of the value to match against.
    176         static int BuildSearchStatement(SQLite::Builder::StatementBuilder& builder, std::string_view valueName, std::string_view primaryAlias, std::string_view valueAlias, bool useLike);
    177 
    178         // Update the value of a single column for the package with the given rowid.
    179         template <typename Column>
    180         static void UpdateValueIdById(SQLite::Connection& connection, SQLite::rowid_t id, const typename SQLite::Builder::TypeInfo<Column::Type, Column::AllowNull>::value_t& value)
    181         {
    182             auto stmt = details::PackagesTableUpdateValueIdById_Statement(connection, Column::Name);
    183             stmt.Bind(1, value);
    184             stmt.Bind(2, id);
    185             stmt.Execute();
    186         }
    187 
    188         // Removes data that is no longer needed for an index that is to be published.
    189         template <typename... Columns>
    190         static void PrepareForPackaging(SQLite::Connection& connection)
    191         {
    192             details::PackagesTablePrepareForPackaging(connection, { ColumnInfo::Create<Columns>()... });
    193         }
    194 
    195         // Checks the consistency of the index to ensure that every referenced row exists.
    196         // Returns true if index is consistent; false if it is not.
    197         template <typename... Columns>
    198         static bool CheckConsistency(const SQLite::Connection& connection, bool log)
    199         {
    200             return details::PackagesTableCheckConsistency(connection, { Columns::Name... }, log);
    201         }
    202 
    203         // Determines if the table is empty.
    204         static bool IsEmpty(SQLite::Connection& connection);
    205     };
    206 }