winget-cli

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

commit 841496f9cd710ec09eb9a046a7565545652af759
parent 1ac30f8509d01671aa4f69f559d3fbcd1da2f142
Author: JohnMcPMS <johnmcp@microsoft.com>
Date:   Wed, 11 Mar 2020 12:45:45 -0700

Implement running all given filters (#50)


Diffstat:
Msrc/AppInstallerCLITests/SQLiteIndex.cpp | 54+++++++++++++++++++++++++++++++++++++++++++++++++++++-
Msrc/AppInstallerRepositoryCore/Microsoft/Schema/1_0/Interface.cpp | 6+++---
Msrc/AppInstallerRepositoryCore/Microsoft/Schema/1_0/SearchResultsTable.cpp | 138++++++++++++++++++++++++++++++++++++++++++++++++++++++++++---------------------
Msrc/AppInstallerRepositoryCore/SQLiteStatementBuilder.cpp | 87++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++-
Msrc/AppInstallerRepositoryCore/SQLiteStatementBuilder.h | 22++++++++++++++++++++++
Msrc/AppInstallerRepositoryCore/SQLiteTempTable.cpp | 11++++++++---
Msrc/AppInstallerRepositoryCore/SQLiteTempTable.h | 3++-
7 files changed, 275 insertions(+), 46 deletions(-)

diff --git a/src/AppInstallerCLITests/SQLiteIndex.cpp b/src/AppInstallerCLITests/SQLiteIndex.cpp @@ -755,7 +755,7 @@ TEST_CASE("SQLiteIndex_Search_ExactBeforeSubstring", "[sqliteindex]") REQUIRE(index.GetIdStringById(results[1].first) == "Id2"); } -TEST_CASE("SQLiteIndex_Search_Filter", "[sqliteindex]") +TEST_CASE("SQLiteIndex_Search_SingleFilter", "[sqliteindex]") { TempFile tempFile{ "repolibtest_tempdb"s, ".db"s }; INFO("Using temporary file named: " << tempFile.GetPath()); @@ -800,3 +800,55 @@ TEST_CASE("SQLiteIndex_Search_Multimatch", "[sqliteindex]") auto results = index.Search(request); REQUIRE(results.size() == 3); } + +TEST_CASE("SQLiteIndex_Search_QueryAndFilter", "[sqliteindex]") +{ + TempFile tempFile{ "repolibtest_tempdb"s, ".db"s }; + INFO("Using temporary file named: " << tempFile.GetPath()); + + SQLiteIndex index = SearchTestSetup(tempFile, { + { "Nope", "Name", "Moniker", "Version", "Channel", { "Tag" }, { "Command" }, "Path1" }, + { "Id2", "Na", "Moniker", "Version", "Channel", { "Tag" }, { "Command" }, "Path2" }, + { "Id3", "No", "Moniker", "Version", "Channel", { "Tag" }, { "Command" }, "Path3" }, + }); + + SearchRequest request; + request.Query = RequestMatch(MatchType::Substring, "Id"); + request.Filters.emplace_back(ApplicationMatchField::Name, MatchType::Substring, "Na"); + + auto results = index.Search(request); + REQUIRE(results.size() == 1); + + auto result = index.GetIdStringById(results[0].first); + REQUIRE(result.has_value()); + REQUIRE(result.value() == "Id2"); +} + +TEST_CASE("SQLiteIndex_Search_QueryAndMultipleFilters", "[sqliteindex]") +{ + TempFile tempFile{ "repolibtest_tempdb"s, ".db"s }; + INFO("Using temporary file named: " << tempFile.GetPath()); + + SQLiteIndex index = SearchTestSetup(tempFile, { + { "Id1", "Name", "Moniker", "Version", "Channel", { "foot" }, { "com34" }, "Path1" }, + { "Id1", "Name1", "Moniker", "Version1", "Channel", { "floor" }, { "com3" }, "Path2" }, + { "Id2", "Name", "Moniker", "Version", "", {}, { "Command" }, "Path3" }, + { "Id2", "Name", "Moniker", "Version", "Channel", {}, { "Command" }, "Path4" }, + { "Id3", "Tagit", "Moniker", "Version1", "", { "foo" }, { "com3" }, "Path5" }, + { "Id3", "Tagit", "Moniker", "Version2", "", { "foo" }, { "com3" }, "Path6" }, + { "Id3", "Tagit", "new", "Version3", "", { "foo" }, { "com3" }, "Path7" }, + }); + + SearchRequest request; + request.Query = RequestMatch(MatchType::Substring, "tag"); + request.Filters.emplace_back(ApplicationMatchField::Command, MatchType::Exact, "com3"); + request.Filters.emplace_back(ApplicationMatchField::Tag, MatchType::Substring, "foo"); + request.Filters.emplace_back(ApplicationMatchField::Moniker, MatchType::Substring, "new"); + + auto results = index.Search(request); + REQUIRE(results.size() == 1); + + auto result = index.GetIdStringById(results[0].first); + REQUIRE(result.has_value()); + REQUIRE(result.value() == "Id3"); +} diff --git a/src/AppInstallerRepositoryCore/Microsoft/Schema/1_0/Interface.cpp b/src/AppInstallerRepositoryCore/Microsoft/Schema/1_0/Interface.cpp @@ -141,9 +141,9 @@ namespace AppInstaller::Repository::Microsoft::Schema::V1_0 case MatchType::Wildcard: return { MatchType::Wildcard }; case MatchType::Fuzzy: - return { MatchType::Exact, MatchType::Substring, MatchType::Fuzzy }; + return { MatchType::Exact, MatchType::Fuzzy }; case MatchType::FuzzySubstring: - return { MatchType::Exact, MatchType::Substring, MatchType::Fuzzy, MatchType::FuzzySubstring }; + return { MatchType::Exact, MatchType::Fuzzy, MatchType::Substring, MatchType::FuzzySubstring }; default: THROW_HR(E_UNEXPECTED); } @@ -379,7 +379,7 @@ namespace AppInstaller::Repository::Microsoft::Schema::V1_0 { THROW_HR_IF(E_UNEXPECTED, request.Filters.empty()); - // Perform search for just the field matching this filter + // Perform search for just the field matching the first filter const ApplicationMatchFilter& filter = request.Filters[0]; for (MatchType match : GetMatchTypeOrder(filter.Type)) diff --git a/src/AppInstallerRepositoryCore/Microsoft/Schema/1_0/SearchResultsTable.cpp b/src/AppInstallerRepositoryCore/Microsoft/Schema/1_0/SearchResultsTable.cpp @@ -27,10 +27,38 @@ namespace AppInstaller::Repository::Microsoft::Schema::V1_0 constexpr std::string_view s_SearchResultsTable_SortValue = "sort"sv; constexpr std::string_view s_SearchResultsTable_Filter = "filter"sv; + constexpr std::string_view s_SearchResultsTable_Index_Suffix = "_i_m"sv; + constexpr std::string_view s_SearchResultsTable_SubSelect_TableAlias = "valueTable"sv; constexpr std::string_view s_SearchResultsTable_SubSelect_ManifestAlias = "m"sv; constexpr std::string_view s_SearchResultsTable_SubSelect_ValueAlias = "v"sv; + bool MatchUsesLike(MatchType match) + { + return (match != MatchType::Exact); + } + + int BuildSearchStatement(SQLite::Builder::StatementBuilder& builder, ApplicationMatchField field, MatchType match) + { + bool useLike = MatchUsesLike(match); + + switch (field) + { + case ApplicationMatchField::Id: + return ManifestTable::BuildSearchStatement<IdTable>(builder, s_SearchResultsTable_SubSelect_ManifestAlias, s_SearchResultsTable_SubSelect_ValueAlias, useLike); + case ApplicationMatchField::Name: + return ManifestTable::BuildSearchStatement<NameTable>(builder, s_SearchResultsTable_SubSelect_ManifestAlias, s_SearchResultsTable_SubSelect_ValueAlias, useLike); + case ApplicationMatchField::Moniker: + return ManifestTable::BuildSearchStatement<MonikerTable>(builder, s_SearchResultsTable_SubSelect_ManifestAlias, s_SearchResultsTable_SubSelect_ValueAlias, useLike); + case ApplicationMatchField::Tag: + return ManifestTable::BuildSearchStatement<TagsTable>(builder, s_SearchResultsTable_SubSelect_ManifestAlias, s_SearchResultsTable_SubSelect_ValueAlias, useLike); + case ApplicationMatchField::Command: + return ManifestTable::BuildSearchStatement<CommandsTable>(builder, s_SearchResultsTable_SubSelect_ManifestAlias, s_SearchResultsTable_SubSelect_ValueAlias, useLike); + default: + THROW_HR(E_UNEXPECTED); + } + } + void ExecuteStatementForMatchType(SQLite::Statement& statement, MatchType match, int bindIndex, bool escapeValueForLike, std::string_view value) { // TODO: Implement these more complex match types @@ -65,21 +93,35 @@ namespace AppInstaller::Repository::Microsoft::Schema::V1_0 { using namespace SQLite::Builder; - StatementBuilder builder; - builder.CreateTable(GetQualifiedName()).BeginColumns(); + { + StatementBuilder builder; + builder.CreateTable(GetQualifiedName()).BeginColumns(); - builder.Column(ColumnBuilder(s_SearchResultsTable_Manifest, Type::RowId).NotNull()); - builder.Column(ColumnBuilder(s_SearchResultsTable_MatchField, Type::Int).NotNull()); - builder.Column(ColumnBuilder(s_SearchResultsTable_MatchType, Type::Int).NotNull()); - builder.Column(ColumnBuilder(s_SearchResultsTable_MatchValue, Type::Text).NotNull()); - builder.Column(ColumnBuilder(s_SearchResultsTable_SortValue, Type::Int).NotNull()); - builder.Column(ColumnBuilder(s_SearchResultsTable_Filter, Type::Bool).NotNull()); + builder.Column(ColumnBuilder(s_SearchResultsTable_Manifest, Type::RowId).NotNull()); + builder.Column(ColumnBuilder(s_SearchResultsTable_MatchField, Type::Int).NotNull()); + builder.Column(ColumnBuilder(s_SearchResultsTable_MatchType, Type::Int).NotNull()); + builder.Column(ColumnBuilder(s_SearchResultsTable_MatchValue, Type::Text).NotNull()); + builder.Column(ColumnBuilder(s_SearchResultsTable_SortValue, Type::Int).NotNull()); + builder.Column(ColumnBuilder(s_SearchResultsTable_Filter, Type::Bool).NotNull()); - builder.EndColumns(); + builder.EndColumns(); - builder.Execute(m_connection); + builder.Execute(m_connection); + } InitDropStatement(m_connection); + + { + SQLite::Builder::QualifiedTable index = GetQualifiedName(); + std::string indexName(index.Table); + indexName += s_SearchResultsTable_Index_Suffix; + index.Table = indexName; + + StatementBuilder builder; + builder.CreateIndex(indexName).On(GetQualifiedName().Table).Columns(s_SearchResultsTable_Manifest); + + builder.Execute(m_connection); + } } void SearchResultsTable::SearchOnField(ApplicationMatchField field, MatchType match, std::string_view value) @@ -104,56 +146,78 @@ namespace AppInstaller::Repository::Microsoft::Schema::V1_0 Value(false). From().BeginParenthetical(); - bool useLike = (match != MatchType::Exact); - int bindIndex = 0; - - switch (field) - { - case ApplicationMatchField::Id: - bindIndex = ManifestTable::BuildSearchStatement<IdTable>(builder, s_SearchResultsTable_SubSelect_ManifestAlias, s_SearchResultsTable_SubSelect_ValueAlias, useLike); - break; - case ApplicationMatchField::Name: - bindIndex = ManifestTable::BuildSearchStatement<NameTable>(builder, s_SearchResultsTable_SubSelect_ManifestAlias, s_SearchResultsTable_SubSelect_ValueAlias, useLike); - break; - case ApplicationMatchField::Moniker: - bindIndex = ManifestTable::BuildSearchStatement<MonikerTable>(builder, s_SearchResultsTable_SubSelect_ManifestAlias, s_SearchResultsTable_SubSelect_ValueAlias, useLike); - break; - case ApplicationMatchField::Tag: - bindIndex = ManifestTable::BuildSearchStatement<TagsTable>(builder, s_SearchResultsTable_SubSelect_ManifestAlias, s_SearchResultsTable_SubSelect_ValueAlias, useLike); - break; - case ApplicationMatchField::Command: - bindIndex = ManifestTable::BuildSearchStatement<CommandsTable>(builder, s_SearchResultsTable_SubSelect_ManifestAlias, s_SearchResultsTable_SubSelect_ValueAlias, useLike); - break; - default: - THROW_HR(E_UNEXPECTED); - } + // Add the field specific portion + int bindIndex = BuildSearchStatement(builder, field, match); builder.EndParenthetical().As(s_SearchResultsTable_SubSelect_TableAlias); SQLite::Statement statement = builder.Prepare(m_connection); - ExecuteStatementForMatchType(statement, match, bindIndex, useLike, value); + ExecuteStatementForMatchType(statement, match, bindIndex, MatchUsesLike(match), value); } void SearchResultsTable::RemoveDuplicateManifestRows() { + using namespace SQLite::Builder; + // Create a delete statement to leave only one row with a given manifest. + // This will arbitrarily choose one of the rows if multiple have the same lowest sort order. + // The goal is a statement like this: + // DELETE from <temp> where rowid not in ( + // SELECT rowid from ( + // SELECT rowid, min(sort) from <temp> group by manifest + // ) + // ) + StatementBuilder builder; + builder.DeleteFrom(GetQualifiedName()).Where(SQLite::RowIDName).Not().In().BeginParenthetical(). + Select(SQLite::RowIDName).From().BeginParenthetical(). + Select().Column(SQLite::RowIDName).Column(Aggregate::Min, s_SearchResultsTable_SortValue).From(GetQualifiedName()).GroupBy(s_SearchResultsTable_Manifest). + EndParenthetical(). + EndParenthetical(); + + builder.Execute(m_connection); } void SearchResultsTable::PrepareToFilter() { + // Reset all filter values to unselected + SQLite::Builder::StatementBuilder builder; + builder.Update(GetQualifiedName()).Set().Column(s_SearchResultsTable_Filter).Equals(false); + builder.Execute(m_connection); } void SearchResultsTable::FilterOnField(ApplicationMatchField field, MatchType match, std::string_view value) { - UNREFERENCED_PARAMETER(field); - UNREFERENCED_PARAMETER(match); - UNREFERENCED_PARAMETER(value); + using namespace SQLite::Builder; + + // Create an update statement to mark rows that are found by the search. + // This will arbitrarily choose one of the rows if multiple have the same lowest sort order. + // The goal is a statement like this: + // UPDATE <temp> set filter = 1 where manifest in ( + // SELECT m from ( + // SELECT manifest.rowid as m, manifest.id as v from manifest join ids on manifest.id = ids.rowid where ids.id = <value> + // ) + // ) + StatementBuilder builder; + builder.Update(GetQualifiedName()).Set().Column(s_SearchResultsTable_Filter).Equals(true).Where(s_SearchResultsTable_Manifest).In().BeginParenthetical(). + Select(s_SearchResultsTable_SubSelect_ManifestAlias).From().BeginParenthetical(); + + // Add the field specific portion + int bindIndex = BuildSearchStatement(builder, field, match); + + builder.EndParenthetical().EndParenthetical(); + + SQLite::Statement statement = builder.Prepare(m_connection); + ExecuteStatementForMatchType(statement, match, bindIndex, MatchUsesLike(match), value); } void SearchResultsTable::CompleteFilter() { + // Delete all unselected values + SQLite::Builder::StatementBuilder builder; + builder.DeleteFrom(GetQualifiedName()).Where(s_SearchResultsTable_Filter).Equals(false); + builder.Execute(m_connection); } std::vector<std::pair<SQLite::rowid_t, ApplicationMatchFilter>> SearchResultsTable::GetSearchResults(size_t limit) diff --git a/src/AppInstallerRepositoryCore/SQLiteStatementBuilder.cpp b/src/AppInstallerRepositoryCore/SQLiteStatementBuilder.cpp @@ -8,7 +8,21 @@ namespace AppInstaller::Repository::SQLite::Builder { std::ostream& operator<<(std::ostream& out, const QualifiedColumn& column) { - out << '[' << column.Table << "].[" << column.Column << ']'; + if (!column.Table.empty()) + { + out << '[' << column.Table << "]."; + } + out << '[' << column.Column << ']'; + return out; + } + + std::ostream& operator<<(std::ostream& out, const QualifiedTable& table) + { + if (!table.Schema.empty()) + { + out << '[' << table.Schema << "]."; + } + out << '[' << table.Table << ']'; return out; } @@ -94,6 +108,11 @@ namespace AppInstaller::Repository::SQLite::Builder out << op << " [" << table << ']'; } + void OutputOperationAndTable(std::ostream& out, std::string_view op, QualifiedTable table) + { + out << op << table; + } + void OutputOperationAndTable(std::ostream& out, std::string_view op, std::initializer_list<std::string_view> table) { out << op << " ["; @@ -248,6 +267,12 @@ namespace AppInstaller::Repository::SQLite::Builder return *this; } + StatementBuilder& StatementBuilder::From(QualifiedTable table) + { + OutputOperationAndTable(m_stream, " FROM", table); + return *this; + } + StatementBuilder& StatementBuilder::From(std::initializer_list<std::string_view> table) { OutputOperationAndTable(m_stream, " FROM", table); @@ -293,6 +318,18 @@ namespace AppInstaller::Repository::SQLite::Builder THROW_HR(E_NOTIMPL); } + StatementBuilder& StatementBuilder::Not() + { + m_stream << " NOT"; + return *this; + } + + StatementBuilder& StatementBuilder::In() + { + m_stream << " IN"; + return *this; + } + StatementBuilder& StatementBuilder::IsNull() { m_stream << " IS NULL"; @@ -317,6 +354,12 @@ namespace AppInstaller::Repository::SQLite::Builder return *this; } + StatementBuilder& StatementBuilder::Join(QualifiedTable table) + { + OutputOperationAndTable(m_stream, " JOIN", table); + return *this; + } + StatementBuilder& StatementBuilder::Join(std::initializer_list<std::string_view> table) { OutputOperationAndTable(m_stream, " JOIN", table); @@ -365,6 +408,12 @@ namespace AppInstaller::Repository::SQLite::Builder return *this; } + StatementBuilder& StatementBuilder::InsertInto(QualifiedTable table) + { + OutputOperationAndTable(m_stream, "INSERT INTO", table); + return *this; + } + StatementBuilder& StatementBuilder::InsertInto(std::initializer_list<std::string_view> table) { OutputOperationAndTable(m_stream, "INSERT INTO", table); @@ -495,6 +544,12 @@ namespace AppInstaller::Repository::SQLite::Builder return *this; } + StatementBuilder& StatementBuilder::CreateTable(QualifiedTable table) + { + OutputOperationAndTable(m_stream, "CREATE TABLE", table); + return *this; + } + StatementBuilder& StatementBuilder::CreateTable(std::initializer_list<std::string_view> table) { OutputOperationAndTable(m_stream, "CREATE TABLE", table); @@ -507,6 +562,12 @@ namespace AppInstaller::Repository::SQLite::Builder return *this; } + StatementBuilder& StatementBuilder::DropTable(QualifiedTable table) + { + OutputOperationAndTable(m_stream, "DROP TABLE", table); + return *this; + } + StatementBuilder& StatementBuilder::DropTable(std::initializer_list<std::string_view> table) { OutputOperationAndTable(m_stream, "DROP TABLE", table); @@ -519,6 +580,12 @@ namespace AppInstaller::Repository::SQLite::Builder return *this; } + StatementBuilder& StatementBuilder::CreateIndex(QualifiedTable table) + { + OutputOperationAndTable(m_stream, "CREATE INDEX", table); + return *this; + } + StatementBuilder& StatementBuilder::CreateIndex(std::initializer_list<std::string_view> table) { OutputOperationAndTable(m_stream, "CREATE INDEX", table); @@ -531,6 +598,12 @@ namespace AppInstaller::Repository::SQLite::Builder return *this; } + StatementBuilder& StatementBuilder::DropIndex(QualifiedTable 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); @@ -555,6 +628,12 @@ namespace AppInstaller::Repository::SQLite::Builder return *this; } + StatementBuilder& StatementBuilder::DeleteFrom(QualifiedTable table) + { + OutputOperationAndTable(m_stream, "DELETE FROM", table); + return *this; + } + StatementBuilder& StatementBuilder::DeleteFrom(std::initializer_list<std::string_view> table) { OutputOperationAndTable(m_stream, "DELETE FROM", table); @@ -567,6 +646,12 @@ namespace AppInstaller::Repository::SQLite::Builder return *this; } + StatementBuilder& StatementBuilder::Update(QualifiedTable table) + { + OutputOperationAndTable(m_stream, "UPDATE", table); + return *this; + } + StatementBuilder& StatementBuilder::Update(std::initializer_list<std::string_view> table) { OutputOperationAndTable(m_stream, "UPDATE", table); diff --git a/src/AppInstallerRepositoryCore/SQLiteStatementBuilder.h b/src/AppInstallerRepositoryCore/SQLiteStatementBuilder.h @@ -61,6 +61,16 @@ namespace AppInstaller::Repository::SQLite::Builder // Pass this value to indicate that the number of rows is to be selected. __declspec_selectany_ details::rowcount_t RowCount; + // A qualified table reference. + struct QualifiedTable + { + std::string_view Schema; + std::string_view Table; + + explicit QualifiedTable(std::string_view table) : Table(table) {} + explicit QualifiedTable(std::string_view schema, std::string_view table) : Schema(schema), Table(table) {} + }; + // A qualified column reference. struct QualifiedColumn { @@ -162,6 +172,7 @@ namespace AppInstaller::Repository::SQLite::Builder // The initializer_list form enables the table name to be constructed from multiple parts. StatementBuilder& From(); StatementBuilder& From(std::string_view table); + StatementBuilder& From(QualifiedTable table); StatementBuilder& From(std::initializer_list<std::string_view> table); // Begin a filter clause on the given column. @@ -194,6 +205,9 @@ namespace AppInstaller::Repository::SQLite::Builder StatementBuilder& Like(details::unbound_t); StatementBuilder& Escape(std::string_view escapeChar); + StatementBuilder& Not(); + StatementBuilder& In(); + StatementBuilder& IsNull(); // Operators for combining filter clauses. @@ -203,6 +217,7 @@ namespace AppInstaller::Repository::SQLite::Builder // Begin a join clause. // The initializer_list form enables the table name to be constructed from multiple parts. StatementBuilder& Join(std::string_view table); + StatementBuilder& Join(QualifiedTable table); StatementBuilder& Join(std::initializer_list<std::string_view> table); // Set the join constraint. @@ -222,6 +237,7 @@ namespace AppInstaller::Repository::SQLite::Builder // Begin an insert statement for the given table. // The initializer_list form enables the table name to be constructed from multiple parts. StatementBuilder& InsertInto(std::string_view table); + StatementBuilder& InsertInto(QualifiedTable table); StatementBuilder& InsertInto(std::initializer_list<std::string_view> table); // Set the columns for a statement (typically insert). @@ -263,21 +279,25 @@ namespace AppInstaller::Repository::SQLite::Builder // Begin a table creation statement. // The initializer_list form enables the table name to be constructed from multiple parts. StatementBuilder& CreateTable(std::string_view table); + StatementBuilder& CreateTable(QualifiedTable table); StatementBuilder& CreateTable(std::initializer_list<std::string_view> table); // Begin an table deletion statement. // The initializer_list form enables the table name to be constructed from multiple parts. StatementBuilder& DropTable(std::string_view table); + StatementBuilder& DropTable(QualifiedTable table); StatementBuilder& DropTable(std::initializer_list<std::string_view> table); // Begin an index creation statement. // The initializer_list form enables the table name to be constructed from multiple parts. StatementBuilder& CreateIndex(std::string_view table); + StatementBuilder& CreateIndex(QualifiedTable 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(QualifiedTable table); StatementBuilder& DropIndex(std::initializer_list<std::string_view> table); // Set index target table. @@ -287,11 +307,13 @@ namespace AppInstaller::Repository::SQLite::Builder // Begin a delete statement. // The initializer_list form enables the table name to be constructed from multiple parts. StatementBuilder& DeleteFrom(std::string_view table); + StatementBuilder& DeleteFrom(QualifiedTable table); StatementBuilder& DeleteFrom(std::initializer_list<std::string_view> table); // Begin an update statement. // The initializer_list form enables the table name to be constructed from multiple parts. StatementBuilder& Update(std::string_view table); + StatementBuilder& Update(QualifiedTable table); StatementBuilder& Update(std::initializer_list<std::string_view> table); // Output the set portion of an update statement. diff --git a/src/AppInstallerRepositoryCore/SQLiteTempTable.cpp b/src/AppInstallerRepositoryCore/SQLiteTempTable.cpp @@ -3,11 +3,12 @@ #pragma once #include "pch.h" #include "SQLiteTempTable.h" -#include "SQLiteStatementBuilder.h" namespace AppInstaller::Repository::SQLite { + using namespace std::string_view_literals; + TempTable::TempTable() { GUID tempName; @@ -16,8 +17,7 @@ namespace AppInstaller::Repository::SQLite wchar_t guidAsString[MAX_PATH]; THROW_HR_IF(E_UNEXPECTED, StringFromGUID2(tempName, guidAsString, MAX_PATH) == 0); - m_name = "temp].["; - m_name += Utility::ConvertToUTF8(guidAsString); + m_name = Utility::ConvertToUTF8(guidAsString); } TempTable::~TempTable() @@ -28,6 +28,11 @@ namespace AppInstaller::Repository::SQLite } } + Builder::QualifiedTable TempTable::GetQualifiedName() const + { + return Builder::QualifiedTable("temp"sv, m_name); + } + void TempTable::InitDropStatement(Connection& connection) { Builder::StatementBuilder builder; diff --git a/src/AppInstallerRepositoryCore/SQLiteTempTable.h b/src/AppInstallerRepositoryCore/SQLiteTempTable.h @@ -2,6 +2,7 @@ // Licensed under the MIT License. #pragma once #include "SQLiteWrapper.h" +#include "SQLiteStatementBuilder.h" namespace AppInstaller::Repository::SQLite @@ -21,7 +22,7 @@ namespace AppInstaller::Repository::SQLite protected: // Gets the qualified name of the temp table. - const std::string& GetQualifiedName() const { return m_name; } + Builder::QualifiedTable GetQualifiedName() const; // Prepares the drop table statement for use in destructor. // It needs to be run by the derived class after the table is actually created.