ManifestMetadataTable.cpp (5940B)
1 // Copyright (c) Microsoft Corporation. 2 // Licensed under the MIT License. 3 #include "pch.h" 4 #include "ManifestMetadataTable.h" 5 #include <winget/SQLiteStatementBuilder.h> 6 7 8 namespace AppInstaller::Repository::Microsoft::Schema::V1_1 9 { 10 using namespace SQLite; 11 12 static constexpr std::string_view s_ManifestMetadataTable_Table_Name = "manifest_metadata"sv; 13 static constexpr std::string_view s_ManifestMetadataTable_PrimaryKeyIndex_Name = "manifest_metadata_pk"sv; 14 static constexpr std::string_view s_ManifestMetadataTable_Manifest_Column = "manifest"sv; 15 static constexpr std::string_view s_ManifestMetadataTable_Metadata_Column = "metadata"sv; 16 static constexpr std::string_view s_ManifestMetadataTable_Value_Column = "value"sv; 17 18 bool ManifestMetadataTable::Exists(const SQLite::Connection& connection) 19 { 20 Builder::StatementBuilder builder; 21 builder.Select(Builder::RowCount).From(Builder::Schema::MainTable). 22 Where(Builder::Schema::TypeColumn).Equals(Builder::Schema::Type_Table).And(Builder::Schema::NameColumn).Equals(s_ManifestMetadataTable_Table_Name); 23 24 Statement statement = builder.Prepare(connection); 25 THROW_HR_IF(E_UNEXPECTED, !statement.Step()); 26 return statement.GetColumn<int64_t>(0) != 0; 27 } 28 29 void ManifestMetadataTable::Create(SQLite::Connection& connection) 30 { 31 using namespace Builder; 32 33 SQLite::Savepoint savepoint = SQLite::Savepoint::Create(connection, "createmanifestmetadata_v1_1"); 34 35 StatementBuilder createTableBuilder; 36 createTableBuilder.CreateTable(s_ManifestMetadataTable_Table_Name).Columns({ 37 ColumnBuilder(s_ManifestMetadataTable_Manifest_Column, Type::Int64).NotNull(), 38 ColumnBuilder(s_ManifestMetadataTable_Metadata_Column, Type::Int64).NotNull(), 39 ColumnBuilder(s_ManifestMetadataTable_Value_Column, Type::Text) 40 }); 41 42 createTableBuilder.Execute(connection); 43 44 StatementBuilder createPKIndexBuilder; 45 createPKIndexBuilder.CreateUniqueIndex(s_ManifestMetadataTable_PrimaryKeyIndex_Name).On(s_ManifestMetadataTable_Table_Name). 46 Columns({ s_ManifestMetadataTable_Manifest_Column, s_ManifestMetadataTable_Metadata_Column }); 47 createPKIndexBuilder.Execute(connection); 48 49 savepoint.Commit(); 50 } 51 52 void ManifestMetadataTable::Drop(SQLite::Connection& connection) 53 { 54 SQLite::Builder::StatementBuilder dropTableBuilder; 55 dropTableBuilder.DropTableIfExists(s_ManifestMetadataTable_Table_Name); 56 57 dropTableBuilder.Execute(connection); 58 } 59 60 ISQLiteIndex::MetadataResult ManifestMetadataTable::GetMetadataByManifestId(const SQLite::Connection& connection, SQLite::rowid_t manifestId) 61 { 62 using namespace Builder; 63 64 StatementBuilder builder; 65 builder.Select({ s_ManifestMetadataTable_Metadata_Column, s_ManifestMetadataTable_Value_Column }).From(s_ManifestMetadataTable_Table_Name). 66 Where(s_ManifestMetadataTable_Manifest_Column).Equals(manifestId); 67 68 Statement statement = builder.Prepare(connection); 69 70 ISQLiteIndex::MetadataResult result; 71 while (statement.Step()) 72 { 73 result.emplace_back(std::make_pair(statement.GetColumn<PackageVersionMetadata>(0), statement.GetColumn<std::string>(1))); 74 } 75 76 return result; 77 } 78 79 std::optional<std::string> ManifestMetadataTable::GetMetadataByManifestIdAndMetadata(const SQLite::Connection& connection, SQLite::rowid_t manifestId, PackageVersionMetadata metadata) 80 { 81 using namespace Builder; 82 83 StatementBuilder builder; 84 builder.Select(s_ManifestMetadataTable_Value_Column).From(s_ManifestMetadataTable_Table_Name). 85 Where(s_ManifestMetadataTable_Manifest_Column).Equals(manifestId). 86 And(s_ManifestMetadataTable_Metadata_Column).Equals(metadata); 87 88 Statement statement = builder.Prepare(connection); 89 90 if (statement.Step()) 91 { 92 return statement.GetColumn<std::string>(0); 93 } 94 95 return {}; 96 } 97 98 void ManifestMetadataTable::SetMetadataByManifestId(SQLite::Connection& connection, SQLite::rowid_t manifestId, PackageVersionMetadata metadata, std::string_view value) 99 { 100 using namespace Builder; 101 102 // First, we attempt to update an existing row. If not changes occurred, we then insert the new value. 103 // UPSERT (aka ON CONFLICT) is not available to us, as it was only introduced in 3.24.0 (2018-06-04), 104 // and we need to support Windows 10 (17763) which was released in 2017. 105 StatementBuilder updateBuilder; 106 updateBuilder.Update(s_ManifestMetadataTable_Table_Name).Set().Column(s_ManifestMetadataTable_Value_Column).Equals(value). 107 Where(s_ManifestMetadataTable_Manifest_Column).Equals(manifestId).And(s_ManifestMetadataTable_Metadata_Column).Equals(metadata); 108 109 updateBuilder.Execute(connection); 110 111 // No changes means we need to insert the row 112 if (connection.GetChanges() == 0) 113 { 114 StatementBuilder insertBuilder; 115 insertBuilder.InsertInto(s_ManifestMetadataTable_Table_Name). 116 Columns({ s_ManifestMetadataTable_Manifest_Column, s_ManifestMetadataTable_Metadata_Column, s_ManifestMetadataTable_Value_Column }) 117 .Values(manifestId, metadata, value); 118 119 insertBuilder.Execute(connection); 120 } 121 } 122 123 void ManifestMetadataTable::DeleteByManifestId(SQLite::Connection & connection, SQLite::rowid_t manifestId) 124 { 125 using namespace Builder; 126 127 StatementBuilder builder; 128 builder.DeleteFrom(s_ManifestMetadataTable_Table_Name).Where(s_ManifestMetadataTable_Manifest_Column).Equals(manifestId); 129 builder.Execute(connection); 130 } 131 }