winget-cli

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

SetInfoTable.cpp (11380B)


      1 // Copyright (c) Microsoft Corporation.
      2 // Licensed under the MIT License.
      3 #include "pch.h"
      4 #include "SetInfoTable.h"
      5 #include "UnitInfoTable.h"
      6 #include "ConfigurationSetSerializer.h"
      7 #include "ConfigurationSetParser.h"
      8 #include <AppInstallerDateTime.h>
      9 #include <AppInstallerStrings.h>
     10 #include <winget/SQLiteStatementBuilder.h>
     11 
     12 using namespace AppInstaller::SQLite;
     13 using namespace AppInstaller::SQLite::Builder;
     14 using namespace AppInstaller::Utility;
     15 
     16 namespace winrt::Microsoft::Management::Configuration::implementation::Database::Schema::V0_1
     17 {
     18     namespace
     19     {
     20         constexpr std::string_view s_SetInfoTable_Table = "set_info"sv;
     21 
     22         constexpr std::string_view s_SetInfoTable_Column_InstanceIdentifier = "instance_identifier"sv;
     23         constexpr std::string_view s_SetInfoTable_Column_Name = "name"sv;
     24         constexpr std::string_view s_SetInfoTable_Column_Origin = "origin"sv;
     25         constexpr std::string_view s_SetInfoTable_Column_Path = "path"sv;
     26         constexpr std::string_view s_SetInfoTable_Column_FirstApply = "first_apply"sv;
     27         constexpr std::string_view s_SetInfoTable_Column_SchemaVersion = "schema_version"sv;
     28         constexpr std::string_view s_SetInfoTable_Column_Metadata = "metadata"sv;
     29         constexpr std::string_view s_SetInfoTable_Column_Parameters = "parameters"sv;
     30         constexpr std::string_view s_SetInfoTable_Column_Variables = "variables"sv;
     31 
     32         void BuildBaseSetSelectStatement(StatementBuilder& builder)
     33         {
     34             builder.Select({
     35                 RowIDName,                                  // 0
     36                 s_SetInfoTable_Column_InstanceIdentifier,   // 1
     37                 s_SetInfoTable_Column_Name,                 // 2
     38                 s_SetInfoTable_Column_Origin,               // 3
     39                 s_SetInfoTable_Column_Path,                 // 4
     40                 s_SetInfoTable_Column_SchemaVersion,        // 5
     41                 s_SetInfoTable_Column_Metadata,             // 6
     42                 s_SetInfoTable_Column_Parameters,           // 7
     43                 s_SetInfoTable_Column_Variables,            // 8
     44             }).From(s_SetInfoTable_Table);
     45         }
     46 
     47         IConfigurationDatabase::ConfigurationSetPtr GetSetFromStatement(Statement& statement, UnitInfoTable& unitInfoTable)
     48         {
     49             auto configurationSet = make_self<implementation::ConfigurationSet>(statement.GetColumn<GUID>(1));
     50 
     51             configurationSet->Name(hstring{ ConvertToUTF16(statement.GetColumn<std::string>(2)) });
     52             configurationSet->Origin(hstring{ ConvertToUTF16(statement.GetColumn<std::string>(3)) });
     53             configurationSet->Path(hstring{ ConvertToUTF16(statement.GetColumn<std::string>(4)) });
     54 
     55             std::string schemaVersion = statement.GetColumn<std::string>(5);
     56             configurationSet->SchemaVersion(hstring{ ConvertToUTF16(schemaVersion) });
     57 
     58             auto parser = ConfigurationSetParser::CreateForSchemaVersion(schemaVersion);
     59             configurationSet->Metadata(parser->ParseValueSet(statement.GetColumn<std::string>(6)));
     60             parser->ExtractEnvironmentFromMetadata(configurationSet->Metadata(), configurationSet->EnvironmentInternal());
     61 
     62             THROW_HR_IF(E_NOTIMPL, !statement.GetColumn<std::string>(7).empty());
     63             configurationSet->Variables(parser->ParseValueSet(statement.GetColumn<std::string>(8)));
     64 
     65             std::vector<Configuration::ConfigurationUnit> winrtUnits;
     66             for (const auto& unit : unitInfoTable.GetAllUnitsForSet(statement.GetColumn<rowid_t>(0), schemaVersion))
     67             {
     68                 winrtUnits.emplace_back(*unit);
     69             }
     70             configurationSet->Units(std::move(winrtUnits));
     71 
     72             return configurationSet;
     73         }
     74     }
     75 
     76     SetInfoTable::SetInfoTable(Connection& connection) : m_connection(connection) {}
     77 
     78     std::string_view SetInfoTable::TableName()
     79     {
     80         return s_SetInfoTable_Table;
     81     }
     82 
     83     std::string_view SetInfoTable::InstanceIdentifierColumn()
     84     {
     85         return s_SetInfoTable_Column_InstanceIdentifier;
     86     }
     87 
     88     void SetInfoTable::Create()
     89     {
     90         Savepoint savepoint = Savepoint::Create(m_connection, "SetInfoTable_Create_0_1");
     91 
     92         StatementBuilder tableBuilder;
     93         tableBuilder.CreateTable(s_SetInfoTable_Table).Columns({
     94             IntegerPrimaryKey(),
     95             ColumnBuilder(s_SetInfoTable_Column_InstanceIdentifier, Type::Blob).Unique().NotNull(),
     96             ColumnBuilder(s_SetInfoTable_Column_Name, Type::Text).NotNull(),
     97             ColumnBuilder(s_SetInfoTable_Column_Origin, Type::Text).NotNull(),
     98             ColumnBuilder(s_SetInfoTable_Column_Path, Type::Text).NotNull(),
     99             ColumnBuilder(s_SetInfoTable_Column_FirstApply, Type::Int64).NotNull(),
    100             ColumnBuilder(s_SetInfoTable_Column_SchemaVersion, Type::Text).NotNull(),
    101             ColumnBuilder(s_SetInfoTable_Column_Metadata, Type::Text).NotNull(),
    102             ColumnBuilder(s_SetInfoTable_Column_Parameters, Type::Text).NotNull(),
    103             ColumnBuilder(s_SetInfoTable_Column_Variables, Type::Text).NotNull(),
    104         });
    105 
    106         tableBuilder.Execute(m_connection);
    107 
    108         savepoint.Commit();
    109     }
    110 
    111     rowid_t SetInfoTable::Add(const Configuration::ConfigurationSet& configurationSet)
    112     {
    113         THROW_HR_IF(E_NOTIMPL, configurationSet.Parameters().Size() > 0);
    114 
    115         Savepoint savepoint = Savepoint::Create(m_connection, "SetInfoTable_Add_0_1");
    116 
    117         hstring schemaVersion = configurationSet.SchemaVersion();
    118         auto serializer = ConfigurationSetSerializer::CreateSerializer(schemaVersion);
    119 
    120         StatementBuilder builder;
    121         builder.InsertInto(s_SetInfoTable_Table).Columns({
    122             s_SetInfoTable_Column_InstanceIdentifier,
    123             s_SetInfoTable_Column_Name,
    124             s_SetInfoTable_Column_Origin,
    125             s_SetInfoTable_Column_Path,
    126             s_SetInfoTable_Column_FirstApply,
    127             s_SetInfoTable_Column_SchemaVersion,
    128             s_SetInfoTable_Column_Metadata,
    129             s_SetInfoTable_Column_Parameters,
    130             s_SetInfoTable_Column_Variables,
    131         }).Values(
    132             static_cast<GUID>(configurationSet.InstanceIdentifier()),
    133             ConvertToUTF8(configurationSet.Name()),
    134             ConvertToUTF8(configurationSet.Origin()),
    135             ConvertToUTF8(configurationSet.Path()),
    136             GetCurrentUnixEpoch(),
    137             ConvertToUTF8(schemaVersion),
    138             serializer->SerializeMetadataWithEnvironment(configurationSet.Metadata(), configurationSet.Environment()),
    139             std::string{}, // Parameters
    140             serializer->SerializeValueSet(configurationSet.Variables())
    141         );
    142 
    143         builder.Execute(m_connection);
    144         rowid_t result = m_connection.GetLastInsertRowID();
    145 
    146         UnitInfoTable unitInfoTable(m_connection);
    147 
    148         auto winrtUnits = configurationSet.Units();
    149         std::vector<Configuration::ConfigurationUnit> units{ winrtUnits.Size() };
    150         winrtUnits.GetMany(0, units);
    151 
    152         for (const auto& unit : units)
    153         {
    154             unitInfoTable.Add(unit, result, schemaVersion);
    155         }
    156 
    157         savepoint.Commit();
    158         return result;
    159     }
    160 
    161     void SetInfoTable::Update(rowid_t target, const Configuration::ConfigurationSet& configurationSet)
    162     {
    163         THROW_HR_IF(E_NOTIMPL, configurationSet.Parameters().Size() > 0);
    164 
    165         Savepoint savepoint = Savepoint::Create(m_connection, "SetInfoTable_Update_0_1");
    166 
    167         hstring schemaVersion = configurationSet.SchemaVersion();
    168         auto serializer = ConfigurationSetSerializer::CreateSerializer(schemaVersion);
    169 
    170         StatementBuilder builder;
    171         builder.Update(s_SetInfoTable_Table).Set().
    172             Column(s_SetInfoTable_Column_Name).Equals(ConvertToUTF8(configurationSet.Name())).
    173             Column(s_SetInfoTable_Column_Origin).Equals(ConvertToUTF8(configurationSet.Origin())).
    174             Column(s_SetInfoTable_Column_Path).Equals(ConvertToUTF8(configurationSet.Path())).
    175             Column(s_SetInfoTable_Column_SchemaVersion).Equals(ConvertToUTF8(schemaVersion)).
    176             Column(s_SetInfoTable_Column_Metadata).Equals(serializer->SerializeMetadataWithEnvironment(configurationSet.Metadata(), configurationSet.Environment())).
    177             Column(s_SetInfoTable_Column_Variables).Equals(serializer->SerializeValueSet(configurationSet.Variables())).
    178         Where(RowIDName).Equals(target);
    179 
    180         builder.Execute(m_connection);
    181 
    182         UnitInfoTable unitInfoTable(m_connection);
    183         unitInfoTable.UpdateForSet(target, configurationSet.Units(), schemaVersion);
    184 
    185         savepoint.Commit();
    186     }
    187 
    188     void SetInfoTable::Remove(rowid_t target)
    189     {
    190         Savepoint savepoint = Savepoint::Create(m_connection, "SetInfoTable_Remove_0_1");
    191 
    192         StatementBuilder builder;
    193         builder.DeleteFrom(s_SetInfoTable_Table).Where(RowIDName).Equals(target);
    194         builder.Execute(m_connection);
    195 
    196         UnitInfoTable unitInfoTable(m_connection);
    197         unitInfoTable.RemoveForSet(target);
    198 
    199         savepoint.Commit();
    200     }
    201 
    202     std::vector<IConfigurationDatabase::ConfigurationSetPtr> SetInfoTable::GetAllSets()
    203     {
    204         std::vector<IConfigurationDatabase::ConfigurationSetPtr> result;
    205 
    206         StatementBuilder builder;
    207         BuildBaseSetSelectStatement(builder);
    208 
    209         Statement getAllSets = builder.Prepare(m_connection);
    210 
    211         UnitInfoTable unitInfoTable(m_connection);
    212 
    213         while (getAllSets.Step())
    214         {
    215             result.emplace_back(GetSetFromStatement(getAllSets, unitInfoTable));
    216         }
    217 
    218         return result;
    219     }
    220 
    221     std::optional<rowid_t> SetInfoTable::GetSetRowId(const GUID& instanceIdentifier)
    222     {
    223         StatementBuilder builder;
    224         builder.Select(RowIDName).From(s_SetInfoTable_Table).Where(s_SetInfoTable_Column_InstanceIdentifier).Equals(instanceIdentifier);
    225 
    226         Statement select = builder.Prepare(m_connection);
    227 
    228         if (select.Step())
    229         {
    230             return select.GetColumn<rowid_t>(0);
    231         }
    232 
    233         return std::nullopt;
    234     }
    235 
    236     IConfigurationDatabase::ConfigurationSetPtr SetInfoTable::GetSet(const GUID& instanceIdentifier)
    237     {
    238         IConfigurationDatabase::ConfigurationSetPtr result;
    239 
    240         StatementBuilder builder;
    241         BuildBaseSetSelectStatement(builder);
    242         builder.Where(s_SetInfoTable_Column_InstanceIdentifier).Equals(instanceIdentifier);
    243 
    244         Statement getSet = builder.Prepare(m_connection);
    245 
    246         if (getSet.Step())
    247         {
    248             UnitInfoTable unitInfoTable(m_connection);
    249             result = GetSetFromStatement(getSet, unitInfoTable);
    250         }
    251 
    252         return result;
    253     }
    254 
    255     std::chrono::system_clock::time_point SetInfoTable::GetSetFirstApply(const GUID& instanceIdentifier)
    256     {
    257         StatementBuilder builder;
    258         builder.Select(s_SetInfoTable_Column_FirstApply).From(s_SetInfoTable_Table).Where(s_SetInfoTable_Column_InstanceIdentifier).Equals(instanceIdentifier);
    259 
    260         Statement statement = builder.Prepare(m_connection);
    261 
    262         return (statement.Step() ? ConvertUnixEpochToSystemClock(statement.GetColumn<int64_t>(0)) : std::chrono::system_clock::time_point{});
    263     }
    264 }