You cannot select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
680 lines
40 KiB
C++
680 lines
40 KiB
C++
/*
|
|
* Copyright (c) Contributors to the Open 3D Engine Project.
|
|
* For complete copyright and license terms please see the LICENSE at the root of this distribution.
|
|
*
|
|
* SPDX-License-Identifier: Apache-2.0 OR MIT
|
|
*
|
|
*/
|
|
#ifndef AZTOOLSFRAMEWORK_Connection_H
|
|
#define AZTOOLSFRAMEWORK_Connection_H
|
|
#pragma once
|
|
|
|
#include <AzCore/Memory/SystemAllocator.h>
|
|
#include <AzCore/Asset/AssetCommon.h>
|
|
#include <AzCore/std/string/string.h>
|
|
#include <AzCore/std/containers/bitset.h>
|
|
#include <AzToolsFramework/API/EditorAssetSystemAPI.h>
|
|
#include <AzToolsFramework/SQLite/SQLiteQueryLogBus.h>
|
|
|
|
// At the time of writing, AZStd::function does not support RVALUE-Refs. We use std::function instead.
|
|
#include <functional>
|
|
|
|
namespace AzToolsFramework
|
|
{
|
|
namespace SQLite
|
|
{
|
|
class Connection;
|
|
class Statement;
|
|
} // namespace SQLite
|
|
|
|
namespace AssetDatabase
|
|
{
|
|
constexpr AZ::s64 InvalidEntryId = -1;
|
|
|
|
//! List all database version changes here with descriptive naming to explain what was changed in
|
|
//! the database
|
|
enum class DatabaseVersion : int
|
|
{
|
|
DatabaseDoesNotExist = -1,
|
|
StartingVersion = 2,
|
|
AddedIndices = 3, // the version where we added the indexes
|
|
AddedJobLogTable = 4, // added job log table to the database
|
|
// skipping up to 7 internally so that old tables are cleared.
|
|
NewTables = 7, // the version where we tables refactored to scanfolder/source/job/product
|
|
AddedOutputPrefixToScanFolders = 8,
|
|
AddedJobKeyIndex = 9, // the version where we add jobKey index on job table
|
|
AddedSourceGuidIndex = 10,
|
|
AddedSourceDependencyTable = 11,
|
|
AddedLegacySubIDsTable = 12, // the version where we added the table that contains a map of product -> previously known aliases
|
|
AddedProductDependencyTable = 13,
|
|
ClearAutoSucceedJobs = 14, // version bump to clear out AutoSucceed jobs from the database (they were never intended to be there in the first place)
|
|
AddedFilesTable = 15,
|
|
AddedAnalysisFingerprint = 16,
|
|
AddedSourceDependencyType = 17,
|
|
AddedFileModTimes = 18,
|
|
AddedUnresolvedDependencyField = 19, // Add unresolved path field to dependency table
|
|
AddedUnresolvedDependencyTypeField = 20,
|
|
AddedTypeOfDependencyIndex = 21,
|
|
AddedProductDependencyPlatform = 22,
|
|
AddedMissingProductDependencyTable = 23,
|
|
AddedWarningAndErrorCountToJobs = 24,
|
|
AddedFromAssetIdField = 25,
|
|
AddedProductDependencyIndexes = 26,
|
|
AddedFileHashField = 27,
|
|
AddedLastScanTimeField = 28,
|
|
AddedScanTimeSecondsSinceEpochField = 29,
|
|
ChangedSortFunctionFromQSortToStdStableSort = 30,
|
|
RemoveOutputPrefixFromScanFolders,
|
|
AddedSourceIndexForSourceDependencyTable,
|
|
//Add all new versions before this
|
|
DatabaseVersionCount,
|
|
LatestVersion = DatabaseVersionCount - 1
|
|
};
|
|
|
|
//////////////////////////////////////////////////////////////////////////
|
|
//DatabaseInfoEntry
|
|
class DatabaseInfoEntry
|
|
{
|
|
public:
|
|
DatabaseInfoEntry() = default;
|
|
DatabaseInfoEntry(AZ::s64 rowID, DatabaseVersion version);
|
|
|
|
auto GetColumns();
|
|
|
|
AZ::s64 m_rowID = -1;
|
|
DatabaseVersion m_version = DatabaseVersion::DatabaseDoesNotExist;
|
|
};
|
|
|
|
typedef AZStd::vector<DatabaseInfoEntry> DatabaseInfoEntryContainer;
|
|
|
|
//////////////////////////////////////////////////////////////////////////
|
|
//ScanFolderDatabaseEntry
|
|
class ScanFolderDatabaseEntry
|
|
{
|
|
public:
|
|
ScanFolderDatabaseEntry() = default;
|
|
ScanFolderDatabaseEntry(AZ::s64 scanFolderID,
|
|
const char* scanFolder,
|
|
const char* displayName,
|
|
const char* portableKey,
|
|
int isRoot = 0);
|
|
ScanFolderDatabaseEntry(const char* scanFolder,
|
|
const char* displayName,
|
|
const char* portableKey,
|
|
int isRoot = 0);
|
|
ScanFolderDatabaseEntry(const ScanFolderDatabaseEntry& other);
|
|
ScanFolderDatabaseEntry(ScanFolderDatabaseEntry&& other);
|
|
|
|
ScanFolderDatabaseEntry& operator=(ScanFolderDatabaseEntry&& other);
|
|
ScanFolderDatabaseEntry& operator=(const ScanFolderDatabaseEntry& other);
|
|
bool operator==(const ScanFolderDatabaseEntry& other) const;
|
|
|
|
AZStd::string ToString() const;
|
|
auto GetColumns();
|
|
|
|
AZ::s64 m_scanFolderID = InvalidEntryId; // the database Primary Key row index, not to be used for any logic purpose
|
|
AZStd::string m_scanFolder; // the actual local computer path to that scan folder.
|
|
AZStd::string m_displayName; // a display name, blank means it should not show up in UIs
|
|
AZStd::string m_portableKey; // a key that uniquely identifies a scan folder so that we can recognize the same one in other databases/computer
|
|
int m_isRoot = 0;
|
|
};
|
|
|
|
typedef AZStd::vector<ScanFolderDatabaseEntry> ScanFolderDatabaseEntryContainer;
|
|
|
|
//////////////////////////////////////////////////////////////////////////
|
|
//SourceDatabaseEntry
|
|
class SourceDatabaseEntry
|
|
{
|
|
public:
|
|
SourceDatabaseEntry() = default;
|
|
SourceDatabaseEntry(AZ::s64 sourceID, AZ::s64 scanFolderPK, const char* sourceName, AZ::Uuid sourceGuid, const char* analysisFingerprint);
|
|
SourceDatabaseEntry(AZ::s64 scanFolderPK, const char* sourceName, AZ::Uuid sourceGuid, const char* analysisFingerprint);
|
|
|
|
AZStd::string ToString() const;
|
|
auto GetColumns();
|
|
|
|
AZ::s64 m_sourceID = InvalidEntryId;
|
|
AZ::s64 m_scanFolderPK = InvalidEntryId;
|
|
AZStd::string m_sourceName;
|
|
AZ::Uuid m_sourceGuid = AZ::Uuid::CreateNull();
|
|
AZStd::string m_analysisFingerprint;
|
|
};
|
|
|
|
typedef AZStd::vector<SourceDatabaseEntry> SourceDatabaseEntryContainer;
|
|
|
|
//////////////////////////////////////////////////////////////////////////
|
|
class BuilderInfoEntry
|
|
{
|
|
public:
|
|
BuilderInfoEntry() = default;
|
|
BuilderInfoEntry(AZ::s64 builderInfoID, const AZ::Uuid& builderUuid, const char* analysisFingerprint);
|
|
AZ::s64 m_builderInfoID = InvalidEntryId;
|
|
AZ::Uuid m_builderUuid = AZ::Uuid::CreateNull();
|
|
AZStd::string m_analysisFingerprint;
|
|
|
|
AZStd::string ToString() const;
|
|
auto GetColumns();
|
|
};
|
|
|
|
using BuilderInfoEntryContainer = AZStd::vector<BuilderInfoEntry>;
|
|
|
|
//////////////////////////////////////////////////////////////////////////
|
|
//JobDatabaseEntry
|
|
class JobDatabaseEntry
|
|
{
|
|
public:
|
|
JobDatabaseEntry() = default;
|
|
JobDatabaseEntry(AZ::s64 jobID, AZ::s64 sourcePK, const char* jobKey, AZ::u32 fingerprint, const char* platform, AZ::Uuid builderGuid, AssetSystem::JobStatus status, AZ::u64 jobRunKey, AZ::s64 firstFailLogTime = 0, const char* firstFailLogFile = nullptr, AZ::s64 lastFailLogTime = 0, const char* lastFailLogFile = nullptr, AZ::s64 lastLogTime = 0, const char* lastLogFile = nullptr, AZ::u32 warningCount = 0, AZ::u32 errorCount = 0);
|
|
JobDatabaseEntry(AZ::s64 sourcePK, const char* jobKey, AZ::u32 fingerprint, const char* platform, AZ::Uuid builderGuid, AssetSystem::JobStatus status, AZ::u64 jobRunKey, AZ::s64 firstFailLogTime = 0, const char* firstFailLogFile = nullptr, AZ::s64 lastFailLogTime = 0, const char* lastFailLogFile = nullptr, AZ::s64 lastLogTime = 0, const char* lastLogFile = nullptr, AZ::u32 warningCount = 0, AZ::u32 errorCount = 0);
|
|
|
|
bool operator==(const JobDatabaseEntry& other) const;
|
|
|
|
AZStd::string ToString() const;
|
|
auto GetColumns();
|
|
|
|
AZ::s64 m_jobID = InvalidEntryId;
|
|
AZ::s64 m_sourcePK = InvalidEntryId;
|
|
AZStd::string m_jobKey;
|
|
AZ::u32 m_fingerprint = 0;
|
|
AZStd::string m_platform;
|
|
AZ::Uuid m_builderGuid;
|
|
AssetSystem::JobStatus m_status = AssetSystem::JobStatus::Queued;
|
|
AZ::u64 m_jobRunKey = 0;
|
|
AZ::s64 m_firstFailLogTime = 0;
|
|
AZStd::string m_firstFailLogFile;
|
|
AZ::s64 m_lastFailLogTime = 0;
|
|
AZStd::string m_lastFailLogFile;
|
|
AZ::s64 m_lastLogTime = 0;
|
|
AZStd::string m_lastLogFile;
|
|
AZ::u32 m_errorCount = 0;
|
|
AZ::u32 m_warningCount = 0;
|
|
};
|
|
|
|
typedef AZStd::vector<JobDatabaseEntry> JobDatabaseEntryContainer;
|
|
|
|
//////////////////////////////////////////////////////////////////////////
|
|
//SourceFileDependencyEntry
|
|
class SourceFileDependencyEntry
|
|
{
|
|
public:
|
|
/// This is also used as a bitset when making queries.
|
|
enum TypeOfDependency : AZ::u32
|
|
{
|
|
DEP_SourceToSource = 1 << 0, ///< source file depends on other source file
|
|
DEP_JobToJob = 1 << 1, ///< job depends on other job
|
|
DEP_SourceOrJob = (DEP_SourceToSource | DEP_JobToJob),
|
|
DEP_SourceLikeMatch = 1 << 2, ///< Allow wildcard matches using LIKE
|
|
DEP_Any = 0xFFFFFFFF ///< convenience value - not allowed to write this to the actual DB.
|
|
};
|
|
|
|
SourceFileDependencyEntry() = default;
|
|
SourceFileDependencyEntry(AZ::Uuid builderGuid, const char* source, const char* dependsOnSource, TypeOfDependency dependencyType, AZ::u32 fromAssetId);
|
|
|
|
AZStd::string ToString() const;
|
|
auto GetColumns();
|
|
|
|
AZ::s64 m_sourceDependencyID = InvalidEntryId;
|
|
AZ::Uuid m_builderGuid = AZ::Uuid::CreateNull();
|
|
TypeOfDependency m_typeOfDependency = DEP_SourceToSource;
|
|
AZStd::string m_source;
|
|
AZStd::string m_dependsOnSource;
|
|
AZ::u32 m_fromAssetId = false; // Indicates if the dependency was converted from an AssetId into a path before being stored in the DB
|
|
};
|
|
|
|
typedef AZStd::vector<SourceFileDependencyEntry> SourceFileDependencyEntryContainer;
|
|
|
|
//////////////////////////////////////////////////////////////////////////
|
|
//ProductDatabaseEntry
|
|
class ProductDatabaseEntry
|
|
{
|
|
public:
|
|
ProductDatabaseEntry() = default;
|
|
ProductDatabaseEntry(AZ::s64 productID, AZ::s64 jobPK, AZ::u32 subID, const char* productName,
|
|
AZ::Data::AssetType assetType, AZ::Uuid legacyGuid = AZ::Uuid::CreateNull());
|
|
ProductDatabaseEntry(AZ::s64 jobPK, AZ::u32 subID, const char* productName,
|
|
AZ::Data::AssetType assetType, AZ::Uuid legacyGuid = AZ::Uuid::CreateNull());
|
|
ProductDatabaseEntry(const ProductDatabaseEntry& entry);
|
|
ProductDatabaseEntry(ProductDatabaseEntry&& other);
|
|
|
|
ProductDatabaseEntry& operator=(ProductDatabaseEntry&& other);
|
|
ProductDatabaseEntry& operator=(const ProductDatabaseEntry& other);
|
|
bool operator==(const ProductDatabaseEntry& other) const;
|
|
|
|
AZStd::string ToString() const;
|
|
auto GetColumns();
|
|
|
|
AZ::s64 m_productID = InvalidEntryId;
|
|
AZ::s64 m_jobPK = InvalidEntryId;
|
|
AZ::u32 m_subID = 0;
|
|
AZStd::string m_productName;
|
|
AZ::Data::AssetType m_assetType = AZ::Data::AssetType::CreateNull();
|
|
AZ::Uuid m_legacyGuid = AZ::Uuid::CreateNull();//used only for backward compatibility with old product guid, is generated based on product name
|
|
};
|
|
typedef AZStd::vector<ProductDatabaseEntry> ProductDatabaseEntryContainer;
|
|
|
|
class LegacySubIDsEntry
|
|
{
|
|
public:
|
|
LegacySubIDsEntry() = default;
|
|
LegacySubIDsEntry(AZ::s64 subIDsEntryID, AZ::s64 productPK, AZ::u32 subId); // loaded from db, and thus includes the PK
|
|
LegacySubIDsEntry(AZ::s64 productPK, AZ::u32 subId); // being synthesized does not include the PK.
|
|
|
|
bool operator==(const LegacySubIDsEntry& other) const;
|
|
|
|
auto GetColumns();
|
|
|
|
AZ::s64 m_subIDsEntryID = InvalidEntryId; // the main ID of this table.
|
|
AZ::s64 m_productPK = InvalidEntryId; // the foreign key to the Products table.
|
|
AZ::u32 m_subID = 0; // the legacy subID.
|
|
};
|
|
|
|
typedef AZStd::vector<LegacySubIDsEntry> LegacySubIDsEntryContainer;
|
|
|
|
//////////////////////////////////////////////////////////////////////////
|
|
//ProductDependencyDatabaseEntry
|
|
class ProductDependencyDatabaseEntry
|
|
{
|
|
public:
|
|
enum DependencyType : AZ::u32
|
|
{
|
|
ProductDep_ProductFile = 0,
|
|
ProductDep_SourceFile
|
|
};
|
|
|
|
ProductDependencyDatabaseEntry() = default;
|
|
ProductDependencyDatabaseEntry(AZ::s64 productDependencyID, AZ::s64 productPK, AZ::Uuid dependencySourceGuid, AZ::u32 dependencySubID, AZStd::bitset<64> dependencyFlags, const AZStd::string& platform, const AZStd::string& unresolvedPath, DependencyType dependencyType, AZ::u32 fromAssetId);
|
|
ProductDependencyDatabaseEntry(AZ::s64 productPK, AZ::Uuid dependencySourceGuid, AZ::u32 dependencySubID, AZStd::bitset<64> dependencyFlags, const AZStd::string& platform, AZ::u32 fromAssetId, const AZStd::string& unresolvedPath="", DependencyType dependencyType = DependencyType::ProductDep_ProductFile);
|
|
|
|
bool operator == (const ProductDependencyDatabaseEntry& other) const;
|
|
|
|
AZStd::string ToString() const;
|
|
auto GetColumns();
|
|
|
|
AZ::s64 m_productDependencyID = InvalidEntryId;
|
|
AZ::s64 m_productPK = InvalidEntryId;
|
|
AZ::Uuid m_dependencySourceGuid = AZ::Uuid::CreateNull();
|
|
AZ::u32 m_dependencySubID = 0;
|
|
AZStd::bitset<64> m_dependencyFlags = 0;
|
|
AZStd::string m_unresolvedPath;
|
|
AZStd::string m_platform;
|
|
DependencyType m_dependencyType = DependencyType::ProductDep_ProductFile;
|
|
AZ::u32 m_fromAssetId = false; // Indicates if the dependency was originally from an AssetId (true) or if it was originally a path dependency (false)
|
|
};
|
|
|
|
typedef AZStd::vector<ProductDependencyDatabaseEntry> ProductDependencyDatabaseEntryContainer;
|
|
|
|
//////////////////////////////////////////////////////////////////////////
|
|
//MissingProductDependencyDatabaseEntry
|
|
class MissingProductDependencyDatabaseEntry
|
|
{
|
|
public:
|
|
MissingProductDependencyDatabaseEntry() = default;
|
|
MissingProductDependencyDatabaseEntry(
|
|
AZ::s64 missingProductDependencyId,
|
|
AZ::s64 productPK,
|
|
const AZStd::string& scannerId,
|
|
const AZStd::string& scannerVersion,
|
|
const AZStd::string& sourceFileFingerprint,
|
|
AZ::Uuid dependencySourceGuid,
|
|
AZ::u32 dependencySubId,
|
|
const AZStd::string& missingDependencyString,
|
|
const AZStd::string& lastScanTime,
|
|
AZ::u64 scanTimeSecondsSinceEpoch);
|
|
MissingProductDependencyDatabaseEntry(
|
|
AZ::s64 productPK,
|
|
const AZStd::string& scannerId,
|
|
const AZStd::string& scannerVersion,
|
|
const AZStd::string& sourceFileFingerprint,
|
|
AZ::Uuid dependencySourceGuid,
|
|
AZ::u32 dependencySubId,
|
|
const AZStd::string& missingDependencyString,
|
|
const AZStd::string& lastScanTime,
|
|
AZ::u64 scanTimeSecondsSinceEpoch);
|
|
|
|
bool operator == (const MissingProductDependencyDatabaseEntry& other) const;
|
|
|
|
AZStd::string ToString() const;
|
|
auto GetColumns();
|
|
|
|
AZ::s64 m_missingProductDependencyId = InvalidEntryId;
|
|
AZ::s64 m_productPK = InvalidEntryId;
|
|
AZStd::string m_scannerId;
|
|
AZStd::string m_scannerVersion;
|
|
AZStd::string m_sourceFileFingerprint;
|
|
AZ::Uuid m_dependencySourceGuid = AZ::Uuid::CreateNull();
|
|
AZ::u32 m_dependencySubId = 0;
|
|
AZStd::string m_missingDependencyString;
|
|
AZStd::string m_lastScanTime; // It's useful to see in the UI if / when a scan was last performed.
|
|
AZ::u64 m_scanTimeSecondsSinceEpoch = 0; // Makes it easy to sort by scan time.
|
|
};
|
|
|
|
typedef AZStd::vector<MissingProductDependencyDatabaseEntry> MissingProductDependencyDatabaseEntryContainer;
|
|
|
|
//////////////////////////////////////////////////////////////////////////
|
|
//CombinedDatabaseEntry
|
|
class CombinedDatabaseEntry
|
|
: public ScanFolderDatabaseEntry
|
|
, public SourceDatabaseEntry
|
|
, public JobDatabaseEntry
|
|
, public ProductDatabaseEntry
|
|
{
|
|
public:
|
|
// allow it to default move operators and etc.
|
|
bool operator==(const CombinedDatabaseEntry& other) = delete; // its meaningless to compare these
|
|
LegacySubIDsEntryContainer m_legacySubIDs;
|
|
|
|
auto GetColumns();
|
|
};
|
|
|
|
typedef AZStd::vector<CombinedDatabaseEntry> CombinedDatabaseEntryContainer;
|
|
|
|
//////////////////////////////////////////////////////////////////////////
|
|
//FileDatabaseEntry
|
|
class FileDatabaseEntry
|
|
{
|
|
public:
|
|
FileDatabaseEntry() = default;
|
|
|
|
FileDatabaseEntry(const FileDatabaseEntry& other) = default;
|
|
FileDatabaseEntry(FileDatabaseEntry&& other) = default;
|
|
|
|
FileDatabaseEntry& operator=(FileDatabaseEntry&& other) = default;
|
|
FileDatabaseEntry& operator=(const FileDatabaseEntry& other) = default;
|
|
bool operator==(const FileDatabaseEntry& other) const;
|
|
|
|
AZStd::string ToString() const;
|
|
auto GetColumns();
|
|
|
|
AZ::s64 m_fileID = InvalidEntryId;
|
|
AZ::s64 m_scanFolderPK = InvalidEntryId;
|
|
AZStd::string m_fileName;
|
|
int m_isFolder = 0;
|
|
AZ::u64 m_modTime{};
|
|
AZ::u64 m_hash{};
|
|
};
|
|
|
|
typedef AZStd::vector<FileDatabaseEntry> FileDatabaseEntryContainer;
|
|
|
|
//////////////////////////////////////////////////////////////////////////
|
|
//SourceAndScanFolderDatabaseEntry
|
|
class SourceAndScanFolderDatabaseEntry
|
|
: public ScanFolderDatabaseEntry
|
|
, public SourceDatabaseEntry
|
|
{
|
|
public:
|
|
auto GetColumns();
|
|
};
|
|
|
|
typedef AZStd::vector<SourceAndScanFolderDatabaseEntry> SourceAndScanFolderDatabaseEntryContainer;
|
|
|
|
//////////////////////////////////////////////////////////////////////////
|
|
//AssetDatabaseConnection
|
|
//! The Connection class represents a read-only connection to the asset database specifically
|
|
//! (as opposed to a sql connection). Things like the Asset Processor derive from this in order
|
|
//! to provide read-write access and curate the database. You may have as many of these
|
|
//! connections as you wish, each represents a single connection to the asset database for use by
|
|
//! a specific thread.
|
|
//! All general read only queries are added here. Since this is meant for tools, we only care
|
|
//! about queries which return data here, no modifications allowed here. Currently the Asset
|
|
//! Processor is the only program allowed to modify the database. As such it derives from this
|
|
//! class and overrides ReadOnly to return false which allows it to write / curate the database.
|
|
//! However most systems only need to read and be notified of changes, so when they derive
|
|
//! they don't override anything but CreateStatements to add specific queries that only make
|
|
//! sense for their specific purpose, otherwise that statement should be added to this class so
|
|
//! it can be reused by any system that needs it. Note that if a system needs read only access
|
|
//! and has no special query needs, then this class can be used directly.
|
|
class AssetDatabaseConnection : public SQLite::SQLiteQueryLogBus::Handler
|
|
{
|
|
public:
|
|
AZ_CLASS_ALLOCATOR(AssetDatabaseConnection, AZ::SystemAllocator, 0);
|
|
|
|
AssetDatabaseConnection();
|
|
virtual ~AssetDatabaseConnection();
|
|
|
|
//Open / Close the database
|
|
bool OpenDatabase();
|
|
void CloseDatabase();
|
|
|
|
//These only need to be overridden by derived class if write access is needed, such as by the
|
|
//asset processor.
|
|
virtual bool IsReadOnly() const
|
|
{
|
|
return true;
|
|
}
|
|
virtual bool PostOpenDatabase(); // used by Asset Processor to upgrade the database
|
|
|
|
//returns the current version of the code used for reading the database
|
|
//this is how we know we have to upgrade old databases to the new ones
|
|
virtual DatabaseVersion CurrentDatabaseVersion() const
|
|
{
|
|
return DatabaseVersion::LatestVersion; // DO NOT alter this value, add to the enumeration instead
|
|
}
|
|
|
|
//////////////////////////////////////////////////////////////////////////
|
|
//handlers
|
|
using databaseInfoHandler = AZStd::function<bool(DatabaseInfoEntry& entry)>;
|
|
using scanFolderHandler = AZStd::function<bool(ScanFolderDatabaseEntry& entry)>;
|
|
using sourceHandler = AZStd::function<bool(SourceDatabaseEntry& entry)>;
|
|
using combinedSourceScanFolderHandler = AZStd::function<bool(SourceAndScanFolderDatabaseEntry& entry)>;
|
|
using jobHandler = AZStd::function<bool(JobDatabaseEntry& entry)>;
|
|
using productHandler = AZStd::function<bool(ProductDatabaseEntry& entry)>;
|
|
using combinedHandler = AZStd::function<bool(CombinedDatabaseEntry& entry)>;
|
|
using jobInfoHandler = AZStd::function<bool(AzToolsFramework::AssetSystem::JobInfo& job)>;
|
|
using sourceFileDependencyHandler = AZStd::function<bool(SourceFileDependencyEntry& entry)>;
|
|
using legacySubIDsHandler = AZStd::function<bool(LegacySubIDsEntry& entry)>;
|
|
using productDependencyHandler = AZStd::function<bool(ProductDependencyDatabaseEntry& entry)>;
|
|
using productDependencyAndPathHandler = AZStd::function<bool(ProductDependencyDatabaseEntry& entry, const AZStd::string& path)>;
|
|
using missingProductDependencyHandler = AZStd::function<bool(MissingProductDependencyDatabaseEntry& entry)>;
|
|
using combinedProductDependencyHandler = AZStd::function<bool(AZ::Data::AssetId& asset, ProductDependencyDatabaseEntry& entry)>;
|
|
// note that AZStd::function cannot handle rvalue-refs at the time of writing this.
|
|
using BuilderInfoHandler = std::function<bool(BuilderInfoEntry&&)>;
|
|
using fileHandler = AZStd::function<bool(FileDatabaseEntry& entry)>;
|
|
|
|
//////////////////////////////////////////////////////////////////
|
|
//Query entire table
|
|
bool QueryDatabaseInfoTable(databaseInfoHandler handler);
|
|
DatabaseVersion QueryDatabaseVersion();//convenience function to return the version field in the database
|
|
bool QueryScanFoldersTable(scanFolderHandler handler);
|
|
bool QuerySourcesTable(sourceHandler handler);
|
|
bool QueryJobsTable(jobHandler handler, AZ::Uuid builderGuid = AZ::Uuid::CreateNull(), const char* jobKey = nullptr, const char* platform = nullptr, AssetSystem::JobStatus status = AssetSystem::JobStatus::Any);
|
|
bool QueryProductsTable(productHandler handler, AZ::Uuid builderGuid = AZ::Uuid::CreateNull(), const char* jobKey = nullptr, const char* platform = nullptr, AssetSystem::JobStatus status = AssetSystem::JobStatus::Any);
|
|
bool QueryProductDependenciesTable(combinedProductDependencyHandler handler);
|
|
bool QueryBuilderInfoTable(const BuilderInfoHandler& handler);
|
|
bool QueryFilesTable(fileHandler handler);
|
|
|
|
//////////////////////////////////////////////////////////////////////////
|
|
//Queries
|
|
//NOTE: There are 2 variations of string equivalence in the database:
|
|
//"By": Means the strings are exactly the same.
|
|
//"Like": Raw LIKE sql query that takes SQL % wild card and _ wild space.
|
|
enum LikeType
|
|
{
|
|
Raw,
|
|
StartsWith,
|
|
EndsWith,
|
|
Matches,
|
|
};
|
|
AZStd::string GetLikeActualSearchTerm(const char* likeString, LikeType likeType);
|
|
//NOTE: The return bool is always whether the database query succeeded. If you
|
|
//succeeded in querying the database but it does not exist in the database it will return true.
|
|
//NOTE: If a query returns true you are guaranteed to have at least one output. However, if it fails
|
|
//you MAY still have some output as it could be the result of multiple internal queries.
|
|
//NOTE: Also these functions are all ADDITIVE, meaning if you pass a container in
|
|
//and the query results in outputs, they are added to whats already there, they never delete
|
|
//before adding outputs.
|
|
//NOTE: A connection is NON MUTATING. This class CAN NOT modify the database in any way whatsoever.
|
|
//This class is to provide a flexible read only interface for people to use. If you need to
|
|
//Write then you should derive from this class and and write your writing code there. The
|
|
//derived class may wrap or even hide this classes interface, but should follow the same rules.
|
|
//NOTE: Any query to do with a non specific job or product has a optional platform filter.
|
|
//NOTE: All combined query also has an optional jobKey filter, except the specific product queries
|
|
//NOTE: Any additional filtering is probably best done in code as permutations of the SQL will
|
|
//most likely not result in any significant speed boost and could easily become unmanageable.
|
|
|
|
//scan folder
|
|
bool QueryScanFolderByScanFolderID(AZ::s64 scanfolderID, scanFolderHandler handler);
|
|
bool QueryScanFolderBySourceID(AZ::s64 sourceID, scanFolderHandler handler);
|
|
bool QueryScanFolderByJobID(AZ::s64 jobID, scanFolderHandler handler);
|
|
bool QueryScanFolderByProductID(AZ::s64 productID, scanFolderHandler handler);
|
|
|
|
bool QueryScanFolderByDisplayName(const char* displayname, scanFolderHandler handler);
|
|
bool QueryScanFolderByPortableKey(const char* portableKey, scanFolderHandler handler);
|
|
|
|
//source
|
|
bool QuerySourceBySourceID(AZ::s64 sourceID, sourceHandler handler);
|
|
bool QuerySourceByScanFolderID(AZ::s64 scanFolderID, sourceHandler handler);
|
|
bool QuerySourceByJobID(AZ::s64 jobID, sourceHandler handler);
|
|
bool QuerySourceByProductID(AZ::s64 productID, sourceHandler handler);
|
|
bool QuerySourceBySourceGuid(AZ::Uuid sourceGuid, sourceHandler handler);
|
|
|
|
bool QuerySourceBySourceName(const char* exactSourceName, sourceHandler handler);
|
|
bool QuerySourceBySourceNameScanFolderID(const char* exactSourceName, AZ::s64 scanFolderID, sourceHandler handler);
|
|
bool QuerySourceLikeSourceName(const char* likeSourceName, LikeType likeType, sourceHandler handler);
|
|
bool QuerySourceAnalysisFingerprint(const char* exactSourceName, AZ::s64 scanFolderID, AZStd::string& result);
|
|
bool QuerySourceAndScanfolder(combinedSourceScanFolderHandler handler);
|
|
|
|
//job
|
|
bool QueryJobByJobID(AZ::s64 jobID, jobHandler handler);
|
|
bool QueryJobByJobKey(AZStd::string jobKey, jobHandler handler);
|
|
bool QueryJobByJobRunKey(AZ::u64 jobRunKey, jobHandler handler);
|
|
bool QueryJobByProductID(AZ::s64 productID, jobHandler handler);
|
|
bool QueryJobBySourceID(AZ::s64 sourceID, jobHandler handler, AZ::Uuid builderGuid = AZ::Uuid::CreateNull(), const char* jobKey = nullptr, const char* platform = nullptr, AssetSystem::JobStatus status = AssetSystem::JobStatus::Any);
|
|
|
|
//product
|
|
bool QueryProductByProductID(AZ::s64 productID, productHandler handler);
|
|
bool QueryProductByJobID(AZ::s64 jobID, productHandler handler, AZ::Uuid builderGuid = AZ::Uuid::CreateNull(), const char* jobKey = nullptr, const char* platform = nullptr, AssetSystem::JobStatus status = AssetSystem::JobStatus::Any);
|
|
bool QueryProductBySourceID(AZ::s64 sourceID, productHandler handler, AZ::Uuid builderGuid = AZ::Uuid::CreateNull(), const char* jobKey = nullptr, const char* platform = nullptr, AssetSystem::JobStatus status = AssetSystem::JobStatus::Any);
|
|
bool QueryProductBySourceGuidSubID(AZ::Uuid sourceGuid, AZ::u32 productSubID, productHandler handler);
|
|
|
|
bool QueryProductByProductName(const char* exactProductName, productHandler handler, AZ::Uuid builderGuid = AZ::Uuid::CreateNull(), const char* jobKey = nullptr, const char* platform = nullptr, AssetSystem::JobStatus status = AssetSystem::JobStatus::Any);
|
|
bool QueryProductLikeProductName(const char* likeProductName, LikeType likeType, productHandler handler, AZ::Uuid builderGuid = AZ::Uuid::CreateNull(), const char* jobKey = nullptr, const char* platform = nullptr, AssetSystem::JobStatus status = AssetSystem::JobStatus::Any);
|
|
|
|
bool QueryProductBySourceName(const char* exactSourceName, productHandler handler, AZ::Uuid builderGuid = AZ::Uuid::CreateNull(), const char* jobKey = nullptr, const char* platform = nullptr, AssetSystem::JobStatus status = AssetSystem::JobStatus::Any);
|
|
bool QueryProductLikeSourceName(const char* likeSourceName, LikeType likeType, productHandler handler, AZ::Uuid builderGuid = AZ::Uuid::CreateNull(), const char* jobKey = nullptr, const char* platform = nullptr, AssetSystem::JobStatus status = AssetSystem::JobStatus::Any);
|
|
bool QueryProductByJobIDSubID(AZ::s64 jobID, AZ::u32 subId, productHandler handler);
|
|
|
|
// legacy SubIDs
|
|
bool QueryLegacySubIdsByProductID(AZ::s64 productId, legacySubIDsHandler handler);
|
|
|
|
//combined scan folder/source/job/product
|
|
bool QueryCombined(combinedHandler handler, AZ::Uuid builderGuid = AZ::Uuid::CreateNull(), const char* jobKey = nullptr, const char* platform = nullptr, AssetSystem::JobStatus status = AssetSystem::JobStatus::Any, bool includeLegacySubIDs = false);
|
|
bool QueryCombinedBySourceID(AZ::s64 sourceID, combinedHandler handler, AZ::Uuid builderGuid = AZ::Uuid::CreateNull(), const char* jobKey = nullptr, const char* platform = nullptr, AssetSystem::JobStatus status = AssetSystem::JobStatus::Any);
|
|
bool QueryCombinedByJobID(AZ::s64 jobID, combinedHandler handler, AZ::Uuid builderGuid = AZ::Uuid::CreateNull(), const char* jobKey = nullptr, const char* platform = nullptr, AssetSystem::JobStatus status = AssetSystem::JobStatus::Any);
|
|
bool QueryCombinedByProductID(AZ::s64 productID, combinedHandler handler, AZ::Uuid builderGuid = AZ::Uuid::CreateNull(), const char* jobKey = nullptr, const char* platform = nullptr, AssetSystem::JobStatus status = AssetSystem::JobStatus::Any);
|
|
bool QueryCombinedBySourceGuidProductSubId(AZ::Uuid sourceGuid, AZ::u32 productSubID, combinedHandler handler, AZ::Uuid builderGuid = AZ::Uuid::CreateNull(), const char* jobKey = nullptr, const char* platform = nullptr, AssetSystem::JobStatus status = AssetSystem::JobStatus::Any);
|
|
|
|
bool QueryCombinedBySourceName(const char* exactSourceName, combinedHandler handler, AZ::Uuid builderGuid = AZ::Uuid::CreateNull(), const char* jobKey = nullptr, const char* platform = nullptr, AssetSystem::JobStatus status = AssetSystem::JobStatus::Any);
|
|
bool QueryCombinedLikeSourceName(const char* likeSourceName, LikeType likeType, combinedHandler handler, AZ::Uuid builderGuid = AZ::Uuid::CreateNull(), const char* jobKey = nullptr, const char* platform = nullptr, AssetSystem::JobStatus status = AssetSystem::JobStatus::Any);
|
|
|
|
bool QueryCombinedByProductName(const char* productName, combinedHandler handler, AZ::Uuid builderGuid = AZ::Uuid::CreateNull(), const char* jobKey = nullptr, const char* platform = nullptr, AssetSystem::JobStatus status = AssetSystem::JobStatus::Any);
|
|
bool QueryCombinedLikeProductName(const char* productName, LikeType likeType, combinedHandler handler, AZ::Uuid builderGuid = AZ::Uuid::CreateNull(), const char* jobKey = nullptr, const char* platform = nullptr, AssetSystem::JobStatus status = AssetSystem::JobStatus::Any);
|
|
|
|
//jobinfo
|
|
bool QueryJobInfoByJobID(AZ::s64 jobID, jobInfoHandler handler);
|
|
bool QueryJobInfoByJobRunKey(AZ::u64 jobRunKey, jobInfoHandler handler);
|
|
bool QueryJobInfoByJobKey(AZStd::string jobKey, jobInfoHandler handler);
|
|
bool QueryJobInfoBySourceName(const char* sourceName, jobInfoHandler handler, AZ::Uuid builderGuid = AZ::Uuid::CreateNull(), const char* jobKey = nullptr, const char* platform = nullptr, AssetSystem::JobStatus status = AssetSystem::JobStatus::Any);
|
|
|
|
//SourceDependency
|
|
/// direct query - look up table row by row ID
|
|
bool QuerySourceDependencyBySourceDependencyId(AZ::s64 sourceDependencyID, sourceFileDependencyHandler handler);
|
|
|
|
//! Query sources which depend on 'dependsOnSource'.
|
|
//! Reverse dependencies are incoming dependencies: what assets depend on me?
|
|
//! Optional nullable 'dependentFilter' filters it to only resulting sources which are LIKE the filter.
|
|
bool QuerySourceDependencyByDependsOnSource(const char* dependsOnSource, const char* dependentFilter, AzToolsFramework::AssetDatabase::SourceFileDependencyEntry::TypeOfDependency dependencyType, sourceFileDependencyHandler handler);
|
|
|
|
//! Attempt to match either DEP_SourcetoSource or DEP_JobToJob
|
|
//! Then allow DEP_SourceLikeMatch with Wildcard characters
|
|
//! Optional nullable 'dependentFilter' filters it to only resulting sources which are LIKE the filter.
|
|
bool QuerySourceDependencyByDependsOnSourceWildcard(const char* dependsOnSource, const char* dependentFilter, sourceFileDependencyHandler handler);
|
|
|
|
//! Query everything 'sourceDependency' depends on.
|
|
//! Optional nullable 'dependentFilter' filters it to only resulting dependencies which are LIKE the filter.
|
|
bool QueryDependsOnSourceBySourceDependency(const char* sourceDependency, const char* dependencyFilter, AzToolsFramework::AssetDatabase::SourceFileDependencyEntry::TypeOfDependency dependencyType, sourceFileDependencyHandler handler);
|
|
|
|
// Recursive reverse dependency query (returns all the source dependencies which depend on 'dependsOnSource' and all the entries that depend on them, etc)
|
|
bool QueryAllSourceDependencyByDependsOnSource(const char* dependsOnSource, SourceFileDependencyEntry::TypeOfDependency dependencyType, sourceFileDependencyHandler handler);
|
|
|
|
// Returns all sources who's products depend on any of the products of the specified source
|
|
bool QueryProductDependenciesThatDependOnProductBySourceId(AZ::s64 sourceId, productDependencyHandler handler);
|
|
|
|
//ProductDependencies
|
|
bool QueryProductDependencyByProductDependencyId(AZ::s64 productDependencyID, productDependencyHandler handler);
|
|
bool QueryProductDependencyByProductId(AZ::s64 productID, productDependencyHandler handler);
|
|
bool QueryProductDependencyBySourceGuidSubId(AZ::Uuid guid, AZ::u32 subId, const AZStd::string& platform, productDependencyHandler handler);
|
|
bool QueryDirectProductDependencies(AZ::s64 productID, productHandler handler);
|
|
|
|
//! Query products which depend on the product with "dependencySubId" and whose source file has "dependencySourceGuid")
|
|
//! These finds all incoming dependencies: everything that depends on the given asset.
|
|
//! Similar to QueryDirectProductDependencies, this query deals with product dependencies but retrieves rows from Products, not ProductDependencies.
|
|
bool QueryDirectReverseProductDependenciesBySourceGuidSubId(AZ::Uuid dependencySourceGuid, AZ::u32 dependencySubId, productHandler handler);
|
|
bool QueryAllProductDependencies(AZ::s64 productID, productHandler handler);
|
|
|
|
bool QueryUnresolvedProductDependencies(productDependencyHandler handler);
|
|
bool QueryProductDependencyExclusions(productDependencyHandler handler);
|
|
|
|
//! Returns any unresolved dependencies which match (by exact or wildcard match) the input searchPaths
|
|
//! The extra path returned for each row is the searchPath entry that was matched with the returned dependency entry
|
|
//! @param searchPaths vector of relative paths to search for matches
|
|
bool QueryProductDependenciesUnresolvedAdvanced(const AZStd::vector<AZStd::string>& searchPaths, productDependencyAndPathHandler handler);
|
|
|
|
bool QueryMissingProductDependencyByProductId(AZ::s64 productId, missingProductDependencyHandler handler);
|
|
bool DeleteMissingProductDependencyByProductId(AZ::s64 productId);
|
|
bool QueryMissingProductDependencyByMissingProductDependencyId(AZ::s64 productDependencyId, missingProductDependencyHandler handler);
|
|
|
|
//FileInfo
|
|
bool QueryFileByFileID(AZ::s64 fileID, fileHandler handler);
|
|
bool QueryFilesByFileNameAndScanFolderID(const char* fileName, AZ::s64 scanfolderID, fileHandler handler);
|
|
bool QueryFilesLikeFileName(const char* likeFileName, LikeType likeType, fileHandler handler);
|
|
bool QueryFilesByScanFolderID(AZ::s64 scanFolderID, fileHandler handler);
|
|
bool QueryFileByFileNameScanFolderID(const char* fileName, AZ::s64 scanFolderID, fileHandler handler);
|
|
//////////////////////////////////////////////////////////////////////////
|
|
|
|
void SetQueryLogging(bool enableLogging);
|
|
void LogQuery(const char* statement, const AZStd::string& params) override;
|
|
void LogResultId(AZ::s64 rowId) override;
|
|
protected:
|
|
|
|
SQLite::Connection* m_databaseConnection;
|
|
|
|
//override in your derived class when you need to add specific queries
|
|
virtual void CreateStatements(); // when overriding call the base first then add additional statements
|
|
|
|
//return the path to the database
|
|
virtual AZStd::string GetAssetDatabaseFilePath();
|
|
|
|
//validation
|
|
bool ValidateDatabaseTable(const char* callName, const char* tableName);
|
|
|
|
//boiler plate
|
|
auto GetCombinedResultAsLambda(); // helper to wrap up GetCombinedResult in a lambda, since GetCombinedResult is a member function
|
|
bool GetCombinedResult(const char* callName, SQLite::Statement* statement, AssetDatabaseConnection::combinedHandler handler, AZ::Uuid builderGuid = AZ::Uuid::CreateNull(), const char* jobKey = nullptr, AssetSystem::JobStatus status = AssetSystem::JobStatus::Any, bool includeLegacyAssetIDs = false);
|
|
|
|
// cache what tables have been validated. it is assumed that AP is the only app with read-write access to the table, and only
|
|
// one AP can be running on a branch at any given time. Therefore once the table is validated, there is no reason to continue validating it
|
|
// before every query, since validating it essentially must makes sure it exists.
|
|
AZStd::unordered_set<AZStd::string> m_validatedTables;
|
|
};
|
|
} // namespace AssetDatabase
|
|
}// namespace AzToolsFramework
|
|
|
|
namespace AZStd
|
|
{
|
|
template<>
|
|
struct hash<AzToolsFramework::AssetDatabase::ProductDependencyDatabaseEntry>
|
|
{
|
|
using argument_type = AzToolsFramework::AssetDatabase::ProductDependencyDatabaseEntry;
|
|
using result_type = size_t;
|
|
|
|
result_type operator() (const argument_type& obj) const
|
|
{
|
|
size_t h = 0;
|
|
hash_combine(h, obj.ToString());
|
|
return h;
|
|
}
|
|
};
|
|
}
|
|
|
|
#endif // AZTOOLSFRAMEWORK_Connection_H
|