PinTable.cpp (7499B)
1 // Copyright (c) Microsoft Corporation. 2 // Licensed under the MIT License. 3 #include "pch.h" 4 #include "PinTable.h" 5 #include <winget/SQLiteStatementBuilder.h> 6 #include "Microsoft/Schema/IPinningIndex.h" 7 8 namespace AppInstaller::Repository::Microsoft::Schema::Pinning_V1_0 9 { 10 namespace 11 { 12 std::optional<Pinning::Pin> GetPinFromRow( 13 std::string_view packageId, 14 std::string_view sourceId, 15 Pinning::PinType type, 16 std::string_view version) 17 18 { 19 switch (type) 20 { 21 case Pinning::PinType::Blocking: 22 return Pinning::Pin::CreateBlockingPin({ packageId, sourceId }); 23 case Pinning::PinType::Pinning: 24 return Pinning::Pin::CreatePinningPin({ packageId, sourceId }); 25 case Pinning::PinType::Gating: 26 return Pinning::Pin::CreateGatingPin({ packageId, sourceId }, Utility::GatedVersion{ version }); 27 default: 28 return {}; 29 } 30 } 31 } 32 33 using namespace std::string_view_literals; 34 static constexpr std::string_view s_PinTable_Table_Name = "pin"sv; 35 static constexpr std::string_view s_PinTable_PackageId_Column = "package_id"sv; 36 static constexpr std::string_view s_PinTable_SourceId_Column = "source_id"sv; 37 static constexpr std::string_view s_PinTable_Type_Column = "type"sv; 38 static constexpr std::string_view s_PinTable_Version_Column = "version"sv; 39 static constexpr std::string_view s_PinTable_Index = "pin_index"sv; 40 41 std::string_view PinTable::TableName() 42 { 43 return s_PinTable_Table_Name; 44 } 45 46 void PinTable::Create(SQLite::Connection& connection) 47 { 48 using namespace SQLite::Builder; 49 50 SQLite::Savepoint savepoint = SQLite::Savepoint::Create(connection, "createpintable_v1_0"); 51 52 StatementBuilder createTableBuilder; 53 createTableBuilder.CreateTable(s_PinTable_Table_Name).BeginColumns(); 54 55 createTableBuilder.Column(ColumnBuilder(s_PinTable_PackageId_Column, Type::Text).NotNull()); 56 createTableBuilder.Column(ColumnBuilder(s_PinTable_SourceId_Column, Type::Text).NotNull()); 57 createTableBuilder.Column(ColumnBuilder(s_PinTable_Type_Column, Type::Int64).NotNull()); 58 createTableBuilder.Column(ColumnBuilder(s_PinTable_Version_Column, Type::Text).NotNull()); 59 60 createTableBuilder.EndColumns(); 61 createTableBuilder.Execute(connection); 62 63 // Create an index over the pairs package,source 64 StatementBuilder createIndexBuilder; 65 createIndexBuilder.CreateUniqueIndex(s_PinTable_Index).On(s_PinTable_Table_Name) 66 .Columns({ s_PinTable_PackageId_Column, s_PinTable_SourceId_Column }); 67 createIndexBuilder.Execute(connection); 68 69 savepoint.Commit(); 70 } 71 72 std::optional<SQLite::rowid_t> PinTable::GetIdByPinKey(SQLite::Connection& connection, const Pinning::PinKey& pinKey) 73 { 74 SQLite::Builder::StatementBuilder builder; 75 builder.Select(SQLite::RowIDName).From(s_PinTable_Table_Name) 76 .Where(s_PinTable_PackageId_Column).Equals((std::string_view)pinKey.PackageId) 77 .And(s_PinTable_SourceId_Column).Equals((std::string_view)pinKey.SourceId); 78 79 SQLite::Statement select = builder.Prepare(connection); 80 81 if (select.Step()) 82 { 83 return select.GetColumn<SQLite::rowid_t>(0); 84 } 85 else 86 { 87 return {}; 88 } 89 } 90 91 SQLite::rowid_t PinTable::AddPin(SQLite::Connection& connection, const Pinning::Pin& pin) 92 { 93 SQLite::Builder::StatementBuilder builder; 94 const auto& pinKey = pin.GetKey(); 95 builder.InsertInto(s_PinTable_Table_Name) 96 .Columns({ 97 s_PinTable_PackageId_Column, 98 s_PinTable_SourceId_Column, 99 s_PinTable_Type_Column, 100 s_PinTable_Version_Column }) 101 .Values( 102 (std::string_view)pinKey.PackageId, 103 pinKey.SourceId, 104 pin.GetType(), 105 pin.GetGatedVersion().ToString()); 106 107 builder.Execute(connection); 108 return connection.GetLastInsertRowID(); 109 } 110 111 bool PinTable::UpdatePinById(SQLite::Connection& connection, SQLite::rowid_t pinId, const Pinning::Pin& pin) 112 { 113 SQLite::Builder::StatementBuilder builder; 114 const auto& pinKey = pin.GetKey(); 115 builder.Update(s_PinTable_Table_Name).Set() 116 .Column(s_PinTable_PackageId_Column).Equals((std::string_view)pinKey.PackageId) 117 .Column(s_PinTable_SourceId_Column).Equals(pinKey.SourceId) 118 .Column(s_PinTable_Type_Column).Equals(pin.GetType()) 119 .Column(s_PinTable_Version_Column).Equals(pin.GetGatedVersion().ToString()) 120 .Where(SQLite::RowIDName).Equals(pinId); 121 122 builder.Execute(connection); 123 return connection.GetChanges() != 0; 124 } 125 126 void PinTable::RemovePinById(SQLite::Connection& connection, SQLite::rowid_t pinId) 127 { 128 SQLite::Builder::StatementBuilder builder; 129 builder.DeleteFrom(s_PinTable_Table_Name).Where(SQLite::RowIDName).Equals(pinId); 130 builder.Execute(connection); 131 } 132 133 std::optional<Pinning::Pin> PinTable::GetPinById(SQLite::Connection& connection, const SQLite::rowid_t pinId) 134 { 135 SQLite::Builder::StatementBuilder builder; 136 builder.Select({ 137 s_PinTable_PackageId_Column, 138 s_PinTable_SourceId_Column, 139 s_PinTable_Type_Column, 140 s_PinTable_Version_Column }) 141 .From(s_PinTable_Table_Name).Where(SQLite::RowIDName).Equals(pinId); 142 143 SQLite::Statement select = builder.Prepare(connection); 144 145 if (!select.Step()) 146 { 147 return {}; 148 } 149 150 auto [packageId, sourceId, pinType, gatedVersion] = 151 select.GetRow<std::string, std::string, Pinning::PinType, std::string>(); 152 return GetPinFromRow(packageId, sourceId, pinType, gatedVersion); 153 } 154 155 std::vector<Pinning::Pin> PinTable::GetAllPins(SQLite::Connection& connection) 156 { 157 SQLite::Builder::StatementBuilder builder; 158 builder.Select({ 159 s_PinTable_PackageId_Column, 160 s_PinTable_SourceId_Column, 161 s_PinTable_Type_Column, 162 s_PinTable_Version_Column }) 163 .From(s_PinTable_Table_Name); 164 165 SQLite::Statement select = builder.Prepare(connection); 166 167 std::vector<Pinning::Pin> pins; 168 while (select.Step()) 169 { 170 auto [packageId, sourceId, pinType, gatedVersion] = 171 select.GetRow<std::string, std::string, Pinning::PinType, std::string>(); 172 auto pin = GetPinFromRow(packageId, sourceId, pinType, gatedVersion); 173 if (pin) 174 { 175 pins.push_back(std::move(pin.value())); 176 } 177 } 178 179 return pins; 180 } 181 182 bool PinTable::ResetAllPins(SQLite::Connection& connection, std::string_view sourceId) 183 { 184 SQLite::Builder::StatementBuilder builder; 185 builder.DeleteFrom(s_PinTable_Table_Name); 186 187 if (!sourceId.empty()) 188 { 189 builder.Where(s_PinTable_SourceId_Column).Equals(sourceId); 190 } 191 192 builder.Execute(connection); 193 194 return connection.GetChanges() != 0; 195 } 196 }