commit 8ae9f00e3e03553784942cd04a3dba0b47e6e318 parent 45e2dcf91302f6eb7bfb071a6df5171852cc7d36 Author: JohnMcPMS <johnmcp@microsoft.com> Date: Fri, 14 Feb 2020 15:07:39 -0800 Update index for current plans (#36) Diffstat:
23 files changed, 171 insertions(+), 98 deletions(-)
diff --git a/src/AppInstallerCLITests/SQLiteIndex.cpp b/src/AppInstallerCLITests/SQLiteIndex.cpp @@ -15,8 +15,6 @@ #include <Microsoft/Schema/1_0/ManifestTable.h> #include <Microsoft/Schema/1_0/TagsTable.h> #include <Microsoft/Schema/1_0/CommandsTable.h> -#include <Microsoft/Schema/1_0/ProtocolsTable.h> -#include <Microsoft/Schema/1_0/ExtensionsTable.h> using namespace std::string_literals; using namespace TestCommon; @@ -77,8 +75,6 @@ TEST_CASE("SQLiteIndexCreateAndAddManifest", "[sqliteindex]") manifest.Channel = "test"; manifest.Tags = { "t1", "t2" }; manifest.Commands = { "test1", "test2" }; - manifest.Protocols = { "htttest" }; - manifest.FileExtensions = { "tst", "test", "testy" }; index.AddManifest(manifest, "test/id/test.id-1.0.0.yml"); } @@ -109,7 +105,7 @@ TEST_CASE("SQLiteIndex_RemoveManifestFile_NotPresent", "[sqliteindex]") REQUIRE_THROWS_HR(index.RemoveManifest(manifestFile, manifestPath), E_NOT_SET); } -TEST_CASE("SQLiteIndex_RemoveManifest", "[sqliteindex]") +TEST_CASE("SQLiteIndex_RemoveManifest", "[sqliteindex][V1_0]") { TempFile tempFile{ "repolibtest_tempdb"s, ".db"s }; INFO("Using temporary file named: " << tempFile.GetPath()); @@ -123,8 +119,6 @@ TEST_CASE("SQLiteIndex_RemoveManifest", "[sqliteindex]") manifest1.Channel = "test"; manifest1.Tags = { "t1", "t2" }; manifest1.Commands = { "test1", "test2" }; - manifest1.Protocols = { "htttest" }; - manifest1.FileExtensions = { "tst", "test", "testy" }; std::string manifest2Path = "test/woah/test.id-1.0.0.yml"; Manifest manifest2; @@ -133,10 +127,8 @@ TEST_CASE("SQLiteIndex_RemoveManifest", "[sqliteindex]") manifest2.AppMoniker = "testmoniker"; manifest2.Version = "1.0.0"; manifest2.Channel = "test"; - manifest2.Tags = { "t1" }; + manifest2.Tags = {}; manifest2.Commands = { "test1", "test2", "test3" }; - manifest2.Protocols = {}; - manifest2.FileExtensions = { "tst", "test", "testy" }; { SQLiteIndex index = SQLiteIndex::CreateNew(tempFile, { 1, 0 }); @@ -159,11 +151,9 @@ TEST_CASE("SQLiteIndex_RemoveManifest", "[sqliteindex]") REQUIRE(!Schema::V1_0::VersionTable::IsEmpty(connection)); REQUIRE(!Schema::V1_0::ChannelTable::IsEmpty(connection)); REQUIRE(!Schema::V1_0::PathPartTable::IsEmpty(connection)); - REQUIRE(!Schema::V1_0::TagsTable::IsEmpty(connection)); + // Because manifest2 had no tags + REQUIRE(Schema::V1_0::TagsTable::IsEmpty(connection)); REQUIRE(!Schema::V1_0::CommandsTable::IsEmpty(connection)); - // Because manifest2 had no protocols - REQUIRE(Schema::V1_0::ProtocolsTable::IsEmpty(connection)); - REQUIRE(!Schema::V1_0::ExtensionsTable::IsEmpty(connection)); } { @@ -185,11 +175,9 @@ TEST_CASE("SQLiteIndex_RemoveManifest", "[sqliteindex]") REQUIRE(Schema::V1_0::PathPartTable::IsEmpty(connection)); REQUIRE(Schema::V1_0::TagsTable::IsEmpty(connection)); REQUIRE(Schema::V1_0::CommandsTable::IsEmpty(connection)); - REQUIRE(Schema::V1_0::ProtocolsTable::IsEmpty(connection)); - REQUIRE(Schema::V1_0::ExtensionsTable::IsEmpty(connection)); } -TEST_CASE("SQLiteIndex_RemoveManifestFile", "[sqliteindex]") +TEST_CASE("SQLiteIndex_RemoveManifestFile", "[sqliteindex][V1_0]") { TempFile tempFile{ "repolibtest_tempdb"s, ".db"s }; INFO("Using temporary file named: " << tempFile.GetPath()); @@ -218,11 +206,9 @@ TEST_CASE("SQLiteIndex_RemoveManifestFile", "[sqliteindex]") REQUIRE(Schema::V1_0::PathPartTable::IsEmpty(connection)); REQUIRE(Schema::V1_0::TagsTable::IsEmpty(connection)); REQUIRE(Schema::V1_0::CommandsTable::IsEmpty(connection)); - REQUIRE(Schema::V1_0::ProtocolsTable::IsEmpty(connection)); - REQUIRE(Schema::V1_0::ExtensionsTable::IsEmpty(connection)); } -TEST_CASE("SQLiteIndex_UpdateManifest", "[sqliteindex]") +TEST_CASE("SQLiteIndex_UpdateManifest", "[sqliteindex][V1_0]") { TempFile tempFile{ "repolibtest_tempdb"s, ".db"s }; INFO("Using temporary file named: " << tempFile.GetPath()); @@ -236,8 +222,6 @@ TEST_CASE("SQLiteIndex_UpdateManifest", "[sqliteindex]") manifest.Channel = "test"; manifest.Tags = { "t1", "t2" }; manifest.Commands = { "test1", "test2" }; - manifest.Protocols = { "htttest" }; - manifest.FileExtensions = { "tst", "test", "testy" }; { SQLiteIndex index = SQLiteIndex::CreateNew(tempFile, { 1, 0 }); @@ -258,8 +242,6 @@ TEST_CASE("SQLiteIndex_UpdateManifest", "[sqliteindex]") REQUIRE(!Schema::V1_0::PathPartTable::IsEmpty(connection)); REQUIRE(!Schema::V1_0::TagsTable::IsEmpty(connection)); REQUIRE(!Schema::V1_0::CommandsTable::IsEmpty(connection)); - REQUIRE(!Schema::V1_0::ProtocolsTable::IsEmpty(connection)); - REQUIRE(!Schema::V1_0::ExtensionsTable::IsEmpty(connection)); } { @@ -277,9 +259,7 @@ TEST_CASE("SQLiteIndex_UpdateManifest", "[sqliteindex]") manifest.Name = "Test Name2"; manifest.AppMoniker = "testmoniker2"; manifest.Tags = { "t1", "t2", "t3" }; - manifest.Commands = { "test1", "test3" }; - manifest.Protocols = {}; - manifest.FileExtensions = { "tst", "test", "testy" }; + manifest.Commands = {}; REQUIRE(index.UpdateManifest(manifest, manifestPath)); } @@ -296,10 +276,8 @@ TEST_CASE("SQLiteIndex_UpdateManifest", "[sqliteindex]") REQUIRE(!Schema::V1_0::ChannelTable::IsEmpty(connection)); REQUIRE(!Schema::V1_0::PathPartTable::IsEmpty(connection)); REQUIRE(!Schema::V1_0::TagsTable::IsEmpty(connection)); - REQUIRE(!Schema::V1_0::CommandsTable::IsEmpty(connection)); - // The update removed all protocols - REQUIRE(Schema::V1_0::ProtocolsTable::IsEmpty(connection)); - REQUIRE(!Schema::V1_0::ExtensionsTable::IsEmpty(connection)); + // The update removed all commands + REQUIRE(Schema::V1_0::CommandsTable::IsEmpty(connection)); } { @@ -321,8 +299,6 @@ TEST_CASE("SQLiteIndex_UpdateManifest", "[sqliteindex]") REQUIRE(Schema::V1_0::PathPartTable::IsEmpty(connection)); REQUIRE(Schema::V1_0::TagsTable::IsEmpty(connection)); REQUIRE(Schema::V1_0::CommandsTable::IsEmpty(connection)); - REQUIRE(Schema::V1_0::ProtocolsTable::IsEmpty(connection)); - REQUIRE(Schema::V1_0::ExtensionsTable::IsEmpty(connection)); } TEST_CASE("PathPartTable_EnsurePathExists_Negative_Paths", "[sqliteindex][V1_0]") @@ -391,3 +367,18 @@ TEST_CASE("PathPartTable_EnsurePathExists", "[sqliteindex][V1_0]") REQUIRE(!std::get<0>(result7)); REQUIRE(std::get<1>(result6) == std::get<1>(result7)); } + +TEST_CASE("SQLiteIndex_PrepareForPackaging", "[sqliteindex]") +{ + TempFile tempFile{ "repolibtest_tempdb"s, ".db"s }; + INFO("Using temporary file named: " << tempFile.GetPath()); + + SQLiteIndex index = SQLiteIndex::CreateNew(tempFile, Schema::Version::Latest()); + + TestDataFile manifestFile{ "GoodManifest.yml" }; + std::filesystem::path manifestPath{ "microsoft/msixsdk/microsoft.msixsdk-1.7.32.yml" }; + + index.AddManifest(manifestFile, manifestPath); + + index.PrepareForPackaging(); +} diff --git a/src/AppInstallerRepositoryCore/AppInstallerRepositoryCore.vcxproj b/src/AppInstallerRepositoryCore/AppInstallerRepositoryCore.vcxproj @@ -173,7 +173,6 @@ <ClInclude Include="Manifest\ManifestLocalization.h" /> <ClInclude Include="Microsoft\Schema\1_0\ChannelTable.h" /> <ClInclude Include="Microsoft\Schema\1_0\CommandsTable.h" /> - <ClInclude Include="Microsoft\Schema\1_0\ExtensionsTable.h" /> <ClInclude Include="Microsoft\Schema\1_0\IdTable.h" /> <ClInclude Include="Microsoft\Schema\1_0\Interface.h" /> <ClInclude Include="Microsoft\Schema\1_0\ManifestTable.h" /> @@ -182,7 +181,6 @@ <ClInclude Include="Microsoft\Schema\1_0\OneToManyTable.h" /> <ClInclude Include="Microsoft\Schema\1_0\OneToOneTable.h" /> <ClInclude Include="Microsoft\Schema\1_0\PathPartTable.h" /> - <ClInclude Include="Microsoft\Schema\1_0\ProtocolsTable.h" /> <ClInclude Include="Microsoft\Schema\1_0\TagsTable.h" /> <ClInclude Include="Microsoft\Schema\1_0\VersionTable.h" /> <ClInclude Include="Microsoft\Schema\ISQLiteIndex.h" /> diff --git a/src/AppInstallerRepositoryCore/AppInstallerRepositoryCore.vcxproj.filters b/src/AppInstallerRepositoryCore/AppInstallerRepositoryCore.vcxproj.filters @@ -87,12 +87,6 @@ <ClInclude Include="Microsoft\Schema\1_0\CommandsTable.h"> <Filter>Microsoft\Schema\1_0</Filter> </ClInclude> - <ClInclude Include="Microsoft\Schema\1_0\ExtensionsTable.h"> - <Filter>Microsoft\Schema\1_0</Filter> - </ClInclude> - <ClInclude Include="Microsoft\Schema\1_0\ProtocolsTable.h"> - <Filter>Microsoft\Schema\1_0</Filter> - </ClInclude> <ClInclude Include="Microsoft\Schema\1_0\ManifestTable.h"> <Filter>Microsoft\Schema\1_0</Filter> </ClInclude> diff --git a/src/AppInstallerRepositoryCore/Microsoft/SQLiteIndex.cpp b/src/AppInstallerRepositoryCore/Microsoft/SQLiteIndex.cpp @@ -190,6 +190,13 @@ namespace AppInstaller::Repository::Microsoft savepoint.Commit(); } + void SQLiteIndex::PrepareForPackaging() + { + AICLI_LOG(Repo, Info, << "Preparing index for packaging"); + + m_interface->PrepareForPackaging(m_dbconn); + } + // Recording last write time based on MSDN documentation stating that time returns a POSIX epoch time and thus // should be consistent across systems. void SQLiteIndex::SetLastWriteTime() diff --git a/src/AppInstallerRepositoryCore/Microsoft/SQLiteIndex.h b/src/AppInstallerRepositoryCore/Microsoft/SQLiteIndex.h @@ -67,6 +67,9 @@ namespace AppInstaller::Repository::Microsoft // Removes the manifest at the repository relative path from the index. void RemoveManifest(const Manifest::Manifest& manifest, const std::filesystem::path& relativePath); + // Removes data that is no longer needed for an index that is to be published. + void PrepareForPackaging(); + private: // Constructor used to open an existing index. SQLiteIndex(const std::string& target, SQLite::Connection::OpenDisposition disposition, SQLite::Connection::OpenFlags flags); diff --git a/src/AppInstallerRepositoryCore/Microsoft/Schema/1_0/ExtensionsTable.h b/src/AppInstallerRepositoryCore/Microsoft/Schema/1_0/ExtensionsTable.h @@ -1,22 +0,0 @@ -// Copyright (c) Microsoft Corporation. -// Licensed under the MIT License. -#pragma once -#include "Microsoft/Schema/1_0/OneToManyTable.h" - - -namespace AppInstaller::Repository::Microsoft::Schema::V1_0 -{ - namespace details - { - using namespace std::string_view_literals; - - struct ExtensionsTableInfo - { - inline static constexpr std::string_view TableName() { return "extensions"sv; } - inline static constexpr std::string_view ValueName() { return "extension"sv; } - }; - } - - // The table for Extensions. - using ExtensionsTable = OneToManyTable<details::ExtensionsTableInfo>; -} diff --git a/src/AppInstallerRepositoryCore/Microsoft/Schema/1_0/Interface.cpp b/src/AppInstallerRepositoryCore/Microsoft/Schema/1_0/Interface.cpp @@ -15,8 +15,6 @@ #include "Microsoft/Schema/1_0/TagsTable.h" #include "Microsoft/Schema/1_0/CommandsTable.h" -#include "Microsoft/Schema/1_0/ProtocolsTable.h" -#include "Microsoft/Schema/1_0/ExtensionsTable.h" namespace AppInstaller::Repository::Microsoft::Schema::V1_0 { @@ -120,8 +118,6 @@ namespace AppInstaller::Repository::Microsoft::Schema::V1_0 TagsTable::Create(connection); CommandsTable::Create(connection); - ProtocolsTable::Create(connection); - ExtensionsTable::Create(connection); savepoint.Commit(); } @@ -155,8 +151,6 @@ namespace AppInstaller::Repository::Microsoft::Schema::V1_0 // Add all of the 1:N data. TagsTable::EnsureExistsAndInsert(connection, manifest.Tags, manifestId); CommandsTable::EnsureExistsAndInsert(connection, manifest.Commands, manifestId); - ProtocolsTable::EnsureExistsAndInsert(connection, manifest.Protocols, manifestId); - ExtensionsTable::EnsureExistsAndInsert(connection, manifest.FileExtensions, manifestId); savepoint.Commit(); } @@ -198,8 +192,6 @@ namespace AppInstaller::Repository::Microsoft::Schema::V1_0 // Update all 1:N tables as necessary indexModified = TagsTable::UpdateIfNeededByManifestId(connection, manifest.Tags, manifestId) || indexModified; indexModified = CommandsTable::UpdateIfNeededByManifestId(connection, manifest.Commands, manifestId) || indexModified; - indexModified = ProtocolsTable::UpdateIfNeededByManifestId(connection, manifest.Protocols, manifestId) || indexModified; - indexModified = ExtensionsTable::UpdateIfNeededByManifestId(connection, manifest.FileExtensions, manifestId) || indexModified; savepoint.Commit(); @@ -237,9 +229,37 @@ namespace AppInstaller::Repository::Microsoft::Schema::V1_0 // Remove all of the 1:N data that is no longer referenced. TagsTable::DeleteIfNotNeededByManifestId(connection, manifestId); CommandsTable::DeleteIfNotNeededByManifestId(connection, manifestId); - ProtocolsTable::DeleteIfNotNeededByManifestId(connection, manifestId); - ExtensionsTable::DeleteIfNotNeededByManifestId(connection, manifestId); savepoint.Commit(); } + + void Interface::PrepareForPackaging(SQLite::Connection& connection) + { + SQLite::Savepoint savepoint = SQLite::Savepoint::Create(connection, "prepareforpackaging_v1_0"); + + IdTable::PrepareForPackaging(connection); + NameTable::PrepareForPackaging(connection); + MonikerTable::PrepareForPackaging(connection); + VersionTable::PrepareForPackaging(connection); + ChannelTable::PrepareForPackaging(connection); + + PathPartTable::PrepareForPackaging(connection); + + ManifestTable::PrepareForPackaging(connection, { + VersionTable::ValueName(), + ChannelTable::ValueName(), + PathPartTable::ValueName(), + }); + + TagsTable::PrepareForPackaging(connection); + CommandsTable::PrepareForPackaging(connection); + + savepoint.Commit(); + + // Force the database to actually shrink the file size. + // This *must* be done outside of an active transaction. + SQLite::Builder::StatementBuilder builder; + builder.Vacuum(); + builder.Execute(connection); + } } diff --git a/src/AppInstallerRepositoryCore/Microsoft/Schema/1_0/Interface.h b/src/AppInstallerRepositoryCore/Microsoft/Schema/1_0/Interface.h @@ -15,5 +15,6 @@ namespace AppInstaller::Repository::Microsoft::Schema::V1_0 void AddManifest(SQLite::Connection& connection, const Manifest::Manifest& manifest, const std::filesystem::path& relativePath) override; bool UpdateManifest(SQLite::Connection& connection, const Manifest::Manifest& manifest, const std::filesystem::path& relativePath) override; void RemoveManifest(SQLite::Connection& connection, const Manifest::Manifest& manifest, const std::filesystem::path& relativePath) override; + void PrepareForPackaging(SQLite::Connection& connection) override; }; } diff --git a/src/AppInstallerRepositoryCore/Microsoft/Schema/1_0/ManifestTable.cpp b/src/AppInstallerRepositoryCore/Microsoft/Schema/1_0/ManifestTable.cpp @@ -157,6 +157,22 @@ namespace AppInstaller::Repository::Microsoft::Schema::V1_0 builder.Execute(connection); } + void ManifestTable::PrepareForPackaging(SQLite::Connection& connection, std::initializer_list<std::string_view> values) + { + SQLite::Savepoint savepoint = SQLite::Savepoint::Create(connection, "pfpManifestTable_v1_0"); + + // Drop the index on the requested values + for (std::string_view value : values) + { + SQLite::Builder::StatementBuilder dropIndexBuilder; + dropIndexBuilder.DropIndex({ s_ManifestTable_Table_Name, s_ManifestTable_Index_Separator, value, s_ManifestTable_Index_Suffix }); + + dropIndexBuilder.Execute(connection); + } + + savepoint.Commit(); + } + bool ManifestTable::IsEmpty(SQLite::Connection& connection) { SQLite::Builder::StatementBuilder builder; diff --git a/src/AppInstallerRepositoryCore/Microsoft/Schema/1_0/ManifestTable.h b/src/AppInstallerRepositoryCore/Microsoft/Schema/1_0/ManifestTable.h @@ -86,6 +86,9 @@ namespace AppInstaller::Repository::Microsoft::Schema::V1_0 // Deletes the manifest row with the given rowid. static void DeleteById(SQLite::Connection& connection, SQLite::rowid_t id); + // Removes data that is no longer needed for an index that is to be published. + static void PrepareForPackaging(SQLite::Connection& connection, std::initializer_list<std::string_view> values); + // Determines if the table is empty. static bool IsEmpty(SQLite::Connection& connection); }; diff --git a/src/AppInstallerRepositoryCore/Microsoft/Schema/1_0/OneToManyTable.cpp b/src/AppInstallerRepositoryCore/Microsoft/Schema/1_0/OneToManyTable.cpp @@ -13,6 +13,7 @@ namespace AppInstaller::Repository::Microsoft::Schema::V1_0 using namespace std::string_view_literals; static constexpr std::string_view s_OneToManyTable_MapTable_ManifestName = "manifest"sv; static constexpr std::string_view s_OneToManyTable_MapTable_Suffix = "_map"sv; + static constexpr std::string_view s_OneToManyTable_MapTable_IndexSuffix = "_index"sv; namespace { @@ -97,11 +98,17 @@ namespace AppInstaller::Repository::Microsoft::Schema::V1_0 createMapTableBuilder.CreateTable({ tableName, s_OneToManyTable_MapTable_Suffix }).Columns({ ColumnBuilder(s_OneToManyTable_MapTable_ManifestName, Type::Int64).NotNull(), ColumnBuilder(valueName, Type::Int64).NotNull(), - PrimaryKeyBuilder({ s_OneToManyTable_MapTable_ManifestName, valueName }) + PrimaryKeyBuilder({ valueName, s_OneToManyTable_MapTable_ManifestName }) }); createMapTableBuilder.Execute(connection); + StatementBuilder createMapTableIndexBuilder; + createMapTableIndexBuilder.CreateIndex({ tableName, s_OneToManyTable_MapTable_Suffix, s_OneToManyTable_MapTable_IndexSuffix }). + On({ tableName, s_OneToManyTable_MapTable_Suffix }).Columns(s_OneToManyTable_MapTable_ManifestName); + + createMapTableIndexBuilder.Execute(connection); + savepoint.Commit(); } @@ -207,6 +214,14 @@ namespace AppInstaller::Repository::Microsoft::Schema::V1_0 savepoint.Commit(); } + void OneToManyTablePrepareForPackaging(SQLite::Connection& connection, std::string_view tableName) + { + SQLite::Builder::StatementBuilder dropMapTableIndexBuilder; + dropMapTableIndexBuilder.DropIndex({ tableName, s_OneToManyTable_MapTable_Suffix, s_OneToManyTable_MapTable_IndexSuffix }); + + dropMapTableIndexBuilder.Execute(connection); + } + bool OneToManyTableIsEmpty(SQLite::Connection& connection, std::string_view tableName) { SQLite::Builder::StatementBuilder countBuilder; diff --git a/src/AppInstallerRepositoryCore/Microsoft/Schema/1_0/OneToManyTable.h b/src/AppInstallerRepositoryCore/Microsoft/Schema/1_0/OneToManyTable.h @@ -27,6 +27,9 @@ namespace AppInstaller::Repository::Microsoft::Schema::V1_0 // Deletes the mapping rows for the given manifest, then removes any unused data rows. void OneToManyTableDeleteIfNotNeededByManifestId(SQLite::Connection& connection, std::string_view tableName, std::string_view valueName, SQLite::rowid_t manifestId); + // Removes data that is no longer needed for an index that is to be published. + void OneToManyTablePrepareForPackaging(SQLite::Connection& connection, std::string_view tableName); + // Determines if the table is empty. bool OneToManyTableIsEmpty(SQLite::Connection& connection, std::string_view tableName); } @@ -59,6 +62,12 @@ namespace AppInstaller::Repository::Microsoft::Schema::V1_0 details::OneToManyTableDeleteIfNotNeededByManifestId(connection, TableInfo::TableName(), TableInfo::ValueName(), manifestId); } + // Removes data that is no longer needed for an index that is to be published. + static void PrepareForPackaging(SQLite::Connection& connection) + { + details::OneToManyTablePrepareForPackaging(connection, TableInfo::TableName()); + } + // Determines if the table is empty. static bool IsEmpty(SQLite::Connection& connection) { diff --git a/src/AppInstallerRepositoryCore/Microsoft/Schema/1_0/OneToOneTable.h b/src/AppInstallerRepositoryCore/Microsoft/Schema/1_0/OneToOneTable.h @@ -63,6 +63,12 @@ namespace AppInstaller::Repository::Microsoft::Schema::V1_0 return details::OneToOneTableDeleteIfNotNeededById(connection, TableInfo::TableName(), TableInfo::ValueName(), id); } + // Removes data that is no longer needed for an index that is to be published. + static void PrepareForPackaging(SQLite::Connection&) + { + // There is currently nothing to do for these tables. + } + // Determines if the table is empty. static bool IsEmpty(SQLite::Connection& connection) { diff --git a/src/AppInstallerRepositoryCore/Microsoft/Schema/1_0/PathPartTable.cpp b/src/AppInstallerRepositoryCore/Microsoft/Schema/1_0/PathPartTable.cpp @@ -189,6 +189,14 @@ namespace AppInstaller::Repository::Microsoft::Schema::V1_0 } } + void PathPartTable::PrepareForPackaging(SQLite::Connection& connection) + { + SQLite::Builder::StatementBuilder dropIndexBuilder; + dropIndexBuilder.DropIndex(s_PathPartTable_ParentIndex_Name); + + dropIndexBuilder.Execute(connection); + } + bool PathPartTable::IsEmpty(SQLite::Connection& connection) { SQLite::Builder::StatementBuilder builder; diff --git a/src/AppInstallerRepositoryCore/Microsoft/Schema/1_0/PathPartTable.h b/src/AppInstallerRepositoryCore/Microsoft/Schema/1_0/PathPartTable.h @@ -32,6 +32,9 @@ namespace AppInstaller::Repository::Microsoft::Schema::V1_0 // Will not remove a path part if it is referenced. static void RemovePathById(SQLite::Connection& connection, SQLite::rowid_t id); + // Removes data that is no longer needed for an index that is to be published. + static void PrepareForPackaging(SQLite::Connection& connection); + // Determines if the table is empty. static bool IsEmpty(SQLite::Connection& connection); }; diff --git a/src/AppInstallerRepositoryCore/Microsoft/Schema/1_0/ProtocolsTable.h b/src/AppInstallerRepositoryCore/Microsoft/Schema/1_0/ProtocolsTable.h @@ -1,22 +0,0 @@ -// Copyright (c) Microsoft Corporation. -// Licensed under the MIT License. -#pragma once -#include "Microsoft/Schema/1_0/OneToManyTable.h" - - -namespace AppInstaller::Repository::Microsoft::Schema::V1_0 -{ - namespace details - { - using namespace std::string_view_literals; - - struct ProtocolsTableInfo - { - inline static constexpr std::string_view TableName() { return "protocols"sv; } - inline static constexpr std::string_view ValueName() { return "protocol"sv; } - }; - } - - // The table for Protocols. - using ProtocolsTable = OneToManyTable<details::ProtocolsTableInfo>; -} diff --git a/src/AppInstallerRepositoryCore/Microsoft/Schema/ISQLiteIndex.h b/src/AppInstallerRepositoryCore/Microsoft/Schema/ISQLiteIndex.h @@ -34,6 +34,9 @@ namespace AppInstaller::Repository::Microsoft::Schema // Removes the manifest at the repository relative path from the index. virtual void RemoveManifest(SQLite::Connection& connection, const Manifest::Manifest& manifest, const std::filesystem::path& relativePath) = 0; + + // Removes data that is no longer needed for an index that is to be published. + virtual void PrepareForPackaging(SQLite::Connection& connection) = 0; }; diff --git a/src/AppInstallerRepositoryCore/Public/AppInstallerRepositorySearch.h b/src/AppInstallerRepositoryCore/Public/AppInstallerRepositorySearch.h @@ -29,8 +29,6 @@ namespace AppInstaller::Repository Moniker, Tag, Command, - Protocol, - Extension, }; // A single match to be performed during a search. diff --git a/src/AppInstallerRepositoryCore/SQLiteStatementBuilder.cpp b/src/AppInstallerRepositoryCore/SQLiteStatementBuilder.cpp @@ -416,6 +416,18 @@ namespace AppInstaller::Repository::SQLite::Builder return *this; } + StatementBuilder& StatementBuilder::DropIndex(std::string_view table) + { + OutputOperationAndTable(m_stream, "DROP INDEX", table); + return *this; + } + + StatementBuilder& StatementBuilder::DropIndex(std::initializer_list<std::string_view> table) + { + OutputOperationAndTable(m_stream, "DROP INDEX", table); + return *this; + } + StatementBuilder& StatementBuilder::On(std::string_view table) { OutputOperationAndTable(m_stream, " ON", table); @@ -459,6 +471,12 @@ namespace AppInstaller::Repository::SQLite::Builder return *this; } + StatementBuilder& StatementBuilder::Vacuum() + { + m_stream << "VACUUM"; + return *this; + } + Statement StatementBuilder::Prepare(Connection& connection, bool persistent) { Statement result = Statement::Create(connection, m_stream.str(), persistent); diff --git a/src/AppInstallerRepositoryCore/SQLiteStatementBuilder.h b/src/AppInstallerRepositoryCore/SQLiteStatementBuilder.h @@ -243,6 +243,11 @@ namespace AppInstaller::Repository::SQLite::Builder StatementBuilder& CreateIndex(std::string_view table); StatementBuilder& CreateIndex(std::initializer_list<std::string_view> table); + // Begin an index deletion statement. + // The initializer_list form enables the table name to be constructed from multiple parts. + StatementBuilder& DropIndex(std::string_view table); + StatementBuilder& DropIndex(std::initializer_list<std::string_view> table); + // Set index target table. StatementBuilder& On(std::string_view table); StatementBuilder& On(std::initializer_list<std::string_view> table); @@ -260,6 +265,9 @@ namespace AppInstaller::Repository::SQLite::Builder // Output the set portion of an update statement. StatementBuilder& Set(); + // Output the set portion of an update statement. + StatementBuilder& Vacuum(); + // Prepares and returns the statement, applying any bindings that were requested. Statement Prepare(Connection& connection, bool persistent = false); diff --git a/src/AppInstallerSQLiteIndexUtil/AppInstallerSQLiteIndexUtil.h b/src/AppInstallerSQLiteIndexUtil/AppInstallerSQLiteIndexUtil.h @@ -59,4 +59,8 @@ extern "C" APPINSTALLER_SQLITE_INDEX_HANDLE index, APPINSTALLER_SQLITE_INDEX_STRING manifestPath, APPINSTALLER_SQLITE_INDEX_STRING relativePath); + + // Removes data that is no longer needed for an index that is to be published. + APPINSTALLER_SQLITE_INDEX_API AppInstallerSQLiteIndexPrepareForPackaging( + APPINSTALLER_SQLITE_INDEX_HANDLE index); } diff --git a/src/AppInstallerSQLiteIndexUtil/Exports.cpp b/src/AppInstallerSQLiteIndexUtil/Exports.cpp @@ -136,4 +136,15 @@ extern "C" return S_OK; } CATCH_RETURN() + + APPINSTALLER_SQLITE_INDEX_API AppInstallerSQLiteIndexPrepareForPackaging( + APPINSTALLER_SQLITE_INDEX_HANDLE index) try + { + THROW_HR_IF(E_INVALIDARG, !index); + + reinterpret_cast<SQLiteIndex*>(index)->PrepareForPackaging(); + + return S_OK; + } + CATCH_RETURN() } diff --git a/src/AppInstallerSQLiteIndexUtil/Source.def b/src/AppInstallerSQLiteIndexUtil/Source.def @@ -8,3 +8,4 @@ EXPORTS AppInstallerSQLiteIndexAddManifest AppInstallerSQLiteIndexUpdateManifest AppInstallerSQLiteIndexRemoveManifest + AppInstallerSQLiteIndexPrepareForPackaging