winget-cli

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

SQLiteIndex.h (10327B)


      1 // Copyright (c) Microsoft Corporation.
      2 // Licensed under the MIT License.
      3 #pragma once
      4 #include <winget/SQLiteWrapper.h>
      5 #include "Microsoft/Schema/ISQLiteIndex.h"
      6 #include <winget/SQLiteVersion.h>
      7 #include <winget/SQLiteStorageBase.h>
      8 #include "ISource.h"
      9 #include <AppInstallerLanguageUtilities.h>
     10 #include <AppInstallerVersions.h>
     11 #include <winget/Manifest.h>
     12 #include <winget/NameNormalization.h>
     13 #include <winget/ManagedFile.h>
     14 
     15 #include <filesystem>
     16 #include <limits>
     17 #include <memory>
     18 #include <optional>
     19 #include <string>
     20 #include <utility>
     21 #include <vector>
     22 
     23 namespace AppInstaller::Repository::Microsoft
     24 {
     25     // Holds the connection to the database, as well as the appropriate functionality to interface with it.
     26     struct SQLiteIndex : SQLite::SQLiteStorageBase
     27     {
     28         // An id that refers to a specific application.
     29         using IdType = SQLite::rowid_t;
     30 
     31         // The return type of Search
     32         using SearchResult = Schema::ISQLiteIndex::SearchResult;
     33 
     34         // The return type of GetMetadataByManifestId
     35         using MetadataResult = Schema::ISQLiteIndex::MetadataResult;
     36 
     37         // Options for creating a new index.
     38         using CreateOptions = Schema::ISQLiteIndex::CreateOptions;
     39 
     40         // The type of version keys.
     41         using VersionKey = Schema::ISQLiteIndex::VersionKey;
     42 
     43         SQLiteIndex(const SQLiteIndex&) = delete;
     44         SQLiteIndex& operator=(const SQLiteIndex&) = delete;
     45 
     46         SQLiteIndex(SQLiteIndex&&) = default;
     47         SQLiteIndex& operator=(SQLiteIndex&&) = default;
     48 
     49         // Creates a new index database of the given version.
     50         static SQLiteIndex CreateNew(const std::string& filePath, SQLite::Version version = SQLite::Version::Latest(), CreateOptions options = CreateOptions::None);
     51 
     52         // Opens an existing SQLiteIndex database.
     53         static SQLiteIndex Open(const std::string& filePath, OpenDisposition disposition, Utility::ManagedFile&& indexFile = {});
     54 
     55         // Creates a copy of the given index.
     56         static SQLiteIndex CopyFrom(const std::string& filePath, SQLiteIndex& source);
     57 
     58 #ifndef AICLI_DISABLE_TEST_HOOKS
     59         // Changes the version of the interface being used to operate on the database.
     60         // Should only be used for testing.
     61         void ForceVersion(const SQLite::Version& version);
     62 
     63         // Gets the latest version of the index schema (the actual numbers, not just the latest sentinel values).
     64         static SQLite::Version GetLatestVersion();
     65 
     66         // Gets the context data for testing.
     67         const Schema::SQLiteIndexContextData& GetContextData() const;
     68 #endif
     69 
     70         // Adds the manifest at the repository relative path to the index.
     71         // If the function succeeds, the manifest has been added.
     72         // Returns the manifest id.
     73         IdType AddManifest(const std::filesystem::path& manifestPath, const std::filesystem::path& relativePath);
     74 
     75         // Adds the manifest at the repository relative path to the index.
     76         // If the function succeeds, the manifest has been added.
     77         // Returns the manifest id.
     78         IdType AddManifest(const Manifest::Manifest& manifest, const std::filesystem::path& relativePath);
     79 
     80         // Adds the manifest to the index.
     81         // If the function succeeds, the manifest has been added.
     82         // Returns the manifest id.
     83         IdType AddManifest(const Manifest::Manifest& manifest);
     84 
     85         // Updates the manifest with matching { Id, Version, Channel } in the index.
     86         // The return value indicates whether the index was modified by the function.
     87         bool UpdateManifest(const std::filesystem::path& manifestPath, const std::filesystem::path& relativePath);
     88 
     89         // Updates the manifest with matching { Id, Version, Channel } in the index.
     90         // The return value indicates whether the index was modified by the function.
     91         bool UpdateManifest(const Manifest::Manifest& manifest, const std::filesystem::path& relativePath);
     92 
     93         // Updates the manifest with matching { Id, Version, Channel } in the index.
     94         // The return value indicates whether the index was modified by the function.
     95         bool UpdateManifest(const Manifest::Manifest& manifest);
     96 
     97         // Adds or updates the manifest with matching { Id, Version, Channel } in the index.
     98         // The return value indicates whether the manifest was added (true) or updated (false).
     99         bool AddOrUpdateManifest(const std::filesystem::path& manifestPath, const std::filesystem::path& relativePath);
    100 
    101         // Updates the manifest with matching { Id, Version, Channel } in the index.
    102         // The return value indicates whether the manifest was added (true) or updated (false).
    103         bool AddOrUpdateManifest(const Manifest::Manifest& manifest, const std::filesystem::path& relativePath);
    104 
    105         // Updates the manifest with matching { Id, Version, Channel } in the index.
    106         // The return value indicates whether the manifest was added (true) or updated (false).
    107         bool AddOrUpdateManifest(const Manifest::Manifest& manifest);
    108 
    109         // Removes the manifest with matching { Id, Version, Channel } from the index.
    110         void RemoveManifest(const std::filesystem::path& manifestPath, const std::filesystem::path& relativePath);
    111 
    112         // Removes the manifest with matching { Id, Version, Channel } from the index.
    113         void RemoveManifest(const Manifest::Manifest& manifest, const std::filesystem::path& relativePath);
    114         
    115         // Removes the manifest with matching { Id, Version, Channel } from the index.
    116         void RemoveManifest(const Manifest::Manifest& manifest);
    117 
    118         // Removes the manifest with the given id.
    119         void RemoveManifestById(IdType manifestId);
    120 
    121         // Removes data that is no longer needed for an index that is to be published.
    122         void PrepareForPackaging();
    123 
    124         // Checks the consistency of the index to ensure that every referenced row exists.
    125         // Returns true if index is consistent; false if it is not.
    126         bool CheckConsistency(bool log = false) const;
    127 
    128         // Performs a search based on the given criteria.
    129         SearchResult Search(const SearchRequest& request) const;
    130 
    131         // Gets the string for the given property and primary id, if present.
    132         std::optional<std::string> GetPropertyByPrimaryId(IdType primaryId, PackageVersionProperty property) const;
    133 
    134         // Gets the string values for the given property and primary id, if present.
    135         std::vector<std::string> GetMultiPropertyByPrimaryId(IdType primaryId, PackageVersionMultiProperty property) const;
    136 
    137         // Gets the manifest id for the given { id, version, channel }, if present.
    138         // If version is empty, gets the value for the 'latest' version.
    139         std::optional<IdType> GetManifestIdByKey(IdType id, std::string_view version, std::string_view channel) const;
    140 
    141         // Gets the manifest id for the given manifest, if present.
    142         std::optional<IdType> GetManifestIdByManifest(const Manifest::Manifest& manifest) const;
    143 
    144         // Gets all versions and channels for the given id.
    145         std::vector<VersionKey> GetVersionKeysById(IdType id) const;
    146 
    147         // Gets the string for the given metadata and manifest id, if present.
    148         MetadataResult GetMetadataByManifestId(SQLite::rowid_t manifestId) const;
    149 
    150         // Sets the string for the given metadata and manifest id.
    151         void SetMetadataByManifestId(IdType manifestId, PackageVersionMetadata metadata, std::string_view value);
    152 
    153         // Normalizes a name using the internal rules used by the index.
    154         // Largely a utility function; should not be used to do work on behalf of the index by the caller.
    155         Utility::NormalizedName NormalizeName(std::string_view name, std::string_view publisher) const;
    156 
    157         // Get all the dependencies for a specific manifest.
    158         std::set<std::pair<SQLite::rowid_t, Utility::NormalizedString>> GetDependenciesByManifestRowId(SQLite::rowid_t manifestRowId) const;
    159         std::vector<std::pair<SQLite::rowid_t, Utility::NormalizedString>> GetDependentsById(AppInstaller::Manifest::string_t packageId) const;
    160 
    161         // Migrates the index to the target version.
    162         // Returns false to indicate that the requested migration is not supported.
    163         bool MigrateTo(SQLite::Version version);
    164 
    165         // The property values that can be set.
    166         enum class Property
    167         {
    168             PackageUpdateTrackingBaseTime,
    169             IntermediateFileOutputPath,
    170         };
    171 
    172         // Sets the given property.
    173         // Some properties will persist into the database.
    174         void SetProperty(Property property, const std::string& value);
    175 
    176     private:
    177         // Constructor used to create a new index.
    178         SQLiteIndex(const std::string& target, const SQLite::Version& version);
    179 
    180         // Constructor used to open an existing index.
    181         SQLiteIndex(const std::string& target, SQLiteStorageBase::OpenDisposition disposition, Utility::ManagedFile&& indexFile);
    182 
    183         // Constructor used to copy the given index.
    184         SQLiteIndex(const std::string& target, SQLiteIndex& source);
    185 
    186         // Sets the database file path in the context data if appropriate.
    187         void SetDatabaseFilePath(const std::string& target);
    188 
    189         // Internal functions to normalize on the relativePath being present.
    190         IdType AddManifestInternal(const Manifest::Manifest& manifest, const std::optional<std::filesystem::path>& relativePath);
    191         IdType AddManifestInternalHoldingLock(const Manifest::Manifest& manifest, const std::optional<std::filesystem::path>& relativePath);
    192         bool UpdateManifestInternal(const Manifest::Manifest& manifest, const std::optional<std::filesystem::path>& relativePath);
    193         bool UpdateManifestInternalHoldingLock(const Manifest::Manifest& manifest, const std::optional<std::filesystem::path>& relativePath);
    194         bool AddOrUpdateManifestInternal(const Manifest::Manifest& manifest, const std::optional<std::filesystem::path>& relativePath);
    195 
    196         std::unique_ptr<Schema::ISQLiteIndex> m_interface;
    197         Schema::SQLiteIndexContextData m_contextData;
    198     };
    199 }