winget-cli

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

UnitInfoTable.cpp (10139B)


      1 // Copyright (c) Microsoft Corporation.
      2 // Licensed under the MIT License.
      3 #include "pch.h"
      4 #include "UnitInfoTable.h"
      5 #include "ConfigurationUnit.h"
      6 #include "ConfigurationSetParser.h"
      7 #include "ConfigurationSetSerializer.h"
      8 #include <AppInstallerLanguageUtilities.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_UnitInfoTable_Table = "unit_info"sv;
     21         constexpr std::string_view s_UnitInfoTable_SetRowIdIndex = "unit_info_set_idx"sv;
     22 
     23         constexpr std::string_view s_UnitInfoTable_Column_SetRowId = "set_rowid"sv;
     24         constexpr std::string_view s_UnitInfoTable_Column_ParentRowId = "parent_rowid"sv;
     25         constexpr std::string_view s_UnitInfoTable_Column_InstanceIdentifier = "instance_identifier"sv;
     26         constexpr std::string_view s_UnitInfoTable_Column_Type = "type"sv;
     27         constexpr std::string_view s_UnitInfoTable_Column_Identifier = "identifier"sv;
     28         constexpr std::string_view s_UnitInfoTable_Column_Intent = "intent"sv;
     29         constexpr std::string_view s_UnitInfoTable_Column_Dependencies = "dependencies"sv;
     30         constexpr std::string_view s_UnitInfoTable_Column_Metadata = "metadata"sv;
     31         constexpr std::string_view s_UnitInfoTable_Column_Settings = "settings"sv;
     32         constexpr std::string_view s_UnitInfoTable_Column_IsActive = "is_active"sv;
     33         constexpr std::string_view s_UnitInfoTable_Column_IsGroup = "is_group"sv;
     34     }
     35 
     36     UnitInfoTable::UnitInfoTable(Connection& connection) : m_connection(connection) {}
     37 
     38     void UnitInfoTable::Create()
     39     {
     40         Savepoint savepoint = Savepoint::Create(m_connection, "UnitInfoTable_Create_0_1");
     41 
     42         StatementBuilder tableBuilder;
     43         tableBuilder.CreateTable(s_UnitInfoTable_Table).Columns({
     44             IntegerPrimaryKey(),
     45             ColumnBuilder(s_UnitInfoTable_Column_SetRowId, Type::RowId).NotNull(),
     46             ColumnBuilder(s_UnitInfoTable_Column_ParentRowId, Type::RowId),
     47             ColumnBuilder(s_UnitInfoTable_Column_InstanceIdentifier, Type::Blob).NotNull(),
     48             ColumnBuilder(s_UnitInfoTable_Column_Type, Type::Text).NotNull(),
     49             ColumnBuilder(s_UnitInfoTable_Column_Identifier, Type::Text).NotNull(),
     50             ColumnBuilder(s_UnitInfoTable_Column_Intent, Type::Int).NotNull(),
     51             ColumnBuilder(s_UnitInfoTable_Column_Dependencies, Type::Text).NotNull(),
     52             ColumnBuilder(s_UnitInfoTable_Column_Metadata, Type::Text).NotNull(),
     53             ColumnBuilder(s_UnitInfoTable_Column_Settings, Type::Text).NotNull(),
     54             ColumnBuilder(s_UnitInfoTable_Column_IsActive, Type::Bool).NotNull(),
     55             ColumnBuilder(s_UnitInfoTable_Column_IsGroup, Type::Bool).NotNull(),
     56             });
     57 
     58         tableBuilder.Execute(m_connection);
     59 
     60         StatementBuilder indexBuilder;
     61         indexBuilder.CreateIndex(s_UnitInfoTable_SetRowIdIndex).On(s_UnitInfoTable_Table).Columns(s_UnitInfoTable_Column_SetRowId);
     62 
     63         indexBuilder.Execute(m_connection);
     64 
     65         savepoint.Commit();
     66     }
     67 
     68     void UnitInfoTable::Add(const Configuration::ConfigurationUnit& configurationUnit, AppInstaller::SQLite::rowid_t setRowId, hstring schemaVersion)
     69     {
     70         Savepoint savepoint = Savepoint::Create(m_connection, "UnitInfoTable_Add_0_1");
     71 
     72         StatementBuilder builder;
     73         builder.InsertInto(s_UnitInfoTable_Table).Columns({
     74             s_UnitInfoTable_Column_SetRowId,
     75             s_UnitInfoTable_Column_ParentRowId,
     76             s_UnitInfoTable_Column_InstanceIdentifier,
     77             s_UnitInfoTable_Column_Type,
     78             s_UnitInfoTable_Column_Identifier,
     79             s_UnitInfoTable_Column_Intent,
     80             s_UnitInfoTable_Column_Dependencies,
     81             s_UnitInfoTable_Column_Metadata,
     82             s_UnitInfoTable_Column_Settings,
     83             s_UnitInfoTable_Column_IsActive,
     84             s_UnitInfoTable_Column_IsGroup,
     85         }).Values(
     86             Unbound,
     87             Unbound,
     88             Unbound,
     89             Unbound,
     90             Unbound,
     91             Unbound,
     92             Unbound,
     93             Unbound,
     94             Unbound,
     95             Unbound,
     96             Unbound
     97         );
     98 
     99         Statement insertStatement = builder.Prepare(m_connection);
    100 
    101         struct UnitsToInsert
    102         {
    103             std::optional<rowid_t> Parent;
    104             Configuration::ConfigurationUnit Unit;
    105         };
    106 
    107         std::queue<UnitsToInsert> unitsToInsert;
    108         unitsToInsert.emplace(UnitsToInsert{ std::nullopt, configurationUnit });
    109         auto serializer = ConfigurationSetSerializer::CreateSerializer(schemaVersion);
    110 
    111         while (!unitsToInsert.empty())
    112         {
    113             const auto& current = unitsToInsert.front();
    114 
    115             insertStatement.Reset();
    116 
    117             bool isGroup = current.Unit.IsGroup();
    118 
    119             insertStatement.Bind(1, setRowId);
    120             insertStatement.Bind(2, current.Parent);
    121             insertStatement.Bind(3, static_cast<GUID>(current.Unit.InstanceIdentifier()));
    122             insertStatement.Bind(4, ConvertToUTF8(current.Unit.Type()));
    123             insertStatement.Bind(5, ConvertToUTF8(current.Unit.Identifier()));
    124             insertStatement.Bind(6, AppInstaller::ToIntegral(current.Unit.Intent()));
    125             insertStatement.Bind(7, serializer->SerializeStringArray(current.Unit.Dependencies()));
    126             insertStatement.Bind(8, serializer->SerializeMetadataWithEnvironment(current.Unit.Metadata(), current.Unit.Environment()));
    127             insertStatement.Bind(9, serializer->SerializeValueSet(current.Unit.Settings()));
    128             insertStatement.Bind(10, current.Unit.IsActive());
    129             insertStatement.Bind(11, isGroup);
    130 
    131             insertStatement.Execute();
    132 
    133             if (isGroup)
    134             {
    135                 rowid_t currentRowId = m_connection.GetLastInsertRowID();
    136 
    137                 auto winrtUnits = current.Unit.Units();
    138                 std::vector<Configuration::ConfigurationUnit> units{ winrtUnits.Size() };
    139                 winrtUnits.GetMany(0, units);
    140 
    141                 for (const auto& unit : units)
    142                 {
    143                     unitsToInsert.emplace(UnitsToInsert{ currentRowId, unit });
    144                 }
    145             }
    146 
    147             unitsToInsert.pop();
    148         }
    149 
    150         savepoint.Commit();
    151     }
    152 
    153     void UnitInfoTable::UpdateForSet(AppInstaller::SQLite::rowid_t target, const Windows::Foundation::Collections::IVector<Configuration::ConfigurationUnit>& winrtUnits, hstring schemaVersion)
    154     {
    155         Savepoint savepoint = Savepoint::Create(m_connection, "UnitInfoTable_UpdateForSet_0_1");
    156 
    157         RemoveForSet(target);
    158 
    159         std::vector<Configuration::ConfigurationUnit> units{ winrtUnits.Size() };
    160         winrtUnits.GetMany(0, units);
    161 
    162         for (const auto& unit : units)
    163         {
    164             Add(unit, target, schemaVersion);
    165         }
    166 
    167         savepoint.Commit();
    168     }
    169 
    170     void UnitInfoTable::RemoveForSet(AppInstaller::SQLite::rowid_t target)
    171     {
    172         StatementBuilder builder;
    173         builder.DeleteFrom(s_UnitInfoTable_Table).Where(s_UnitInfoTable_Column_SetRowId).Equals(target);
    174         builder.Execute(m_connection);
    175     }
    176 
    177     std::vector<IConfigurationDatabase::ConfigurationUnitPtr> UnitInfoTable::GetAllUnitsForSet(AppInstaller::SQLite::rowid_t setRowId, std::string_view schemaVersion)
    178     {
    179         StatementBuilder builder;
    180         builder.Select({
    181             RowIDName,                                 // 0
    182             s_UnitInfoTable_Column_ParentRowId,        // 1
    183             s_UnitInfoTable_Column_InstanceIdentifier, // 2
    184             s_UnitInfoTable_Column_Type,               // 3
    185             s_UnitInfoTable_Column_Identifier,         // 4
    186             s_UnitInfoTable_Column_Intent,             // 5
    187             s_UnitInfoTable_Column_Dependencies,       // 6
    188             s_UnitInfoTable_Column_Metadata,           // 7
    189             s_UnitInfoTable_Column_Settings,           // 8
    190             s_UnitInfoTable_Column_IsActive,           // 9
    191             s_UnitInfoTable_Column_IsGroup,            // 10
    192         }).From(s_UnitInfoTable_Table).Where(s_UnitInfoTable_Column_SetRowId).Equals(setRowId);
    193 
    194         Statement statement = builder.Prepare(m_connection);
    195 
    196         std::vector<IConfigurationDatabase::ConfigurationUnitPtr> result;
    197         std::map<rowid_t, IConfigurationDatabase::ConfigurationUnitPtr> rowToUnitMap;
    198         auto parser = ConfigurationSetParser::CreateForSchemaVersion(std::string{ schemaVersion });
    199 
    200         while (statement.Step())
    201         {
    202             auto unit = make_self<implementation::ConfigurationUnit>(statement.GetColumn<GUID>(2));
    203 
    204             unit->Type(hstring{ ConvertToUTF16(statement.GetColumn<std::string>(3)) });
    205             unit->Identifier(hstring{ ConvertToUTF16(statement.GetColumn<std::string>(4)) });
    206             unit->Intent(statement.GetColumn<ConfigurationUnitIntent>(5));
    207             unit->Dependencies(parser->ParseStringArray(statement.GetColumn<std::string>(6)));
    208             unit->Metadata(parser->ParseValueSet(statement.GetColumn<std::string>(7)));
    209             unit->Settings(parser->ParseValueSet(statement.GetColumn<std::string>(8)));
    210             unit->IsActive(statement.GetColumn<bool>(9));
    211             unit->IsGroup(statement.GetColumn<bool>(10));
    212 
    213             parser->ExtractEnvironmentFromMetadata(unit->Metadata(), unit->EnvironmentInternal());
    214 
    215             if (statement.GetColumnIsNull(1))
    216             {
    217                 result.emplace_back(unit);
    218             }
    219             else
    220             {
    221                 rowToUnitMap.at(statement.GetColumn<rowid_t>(1))->Units().Append(*unit);
    222             }
    223 
    224             rowToUnitMap.emplace(statement.GetColumn<rowid_t>(0), unit);
    225         }
    226 
    227         return result;
    228     }
    229 }