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 }