3dec5d3b71
* LYN-2537 Moved the Engine and Editor folder to be within the EngineAssets folder * Fixed Documentation in bootstrap.cfg to correct the path to the user project specific registry file * Adding a newline to the output of AssetCatalog 'Registering asset..., but type is not set' message * Updating the AssetProcessorPlatformConfig.setreg Scan Folder to detect the @ENGINEROOT@/EngineAssets/Engine path for engine runtime assets and @ENGINEROOT@/EngineAssets/Editor path for engine tool assets * Updating references to Icons and other assets to account for moving the Engine and Editor folder under a single EngineAssets folder * Moving the Engine Settings Registry folder from Engine/Registry -> Registry * Removed the LY_PROJECT_CMAKE_PATH define as it is not portable to other locations. It is hard coded to the project location that was used for the CMake configuration. Furthermore it paths with backslashes within it are treated as escape characters and not a path separator * Updated the LyTestTools asset_processor.py script to copy the exclude.filetag from the EngineAssets/Engine directory now * Fixed Atom Shader Preprocessing when running using an External Project * Updated the TSGenerateAction.cpp to fix the build error with using a renamed variable * Updated the Install_Common.cmake ly_setup_others function to install the EngineAssets directory and the each of the Gem's Assets directory while maintaining the relative directory structure to the Engine Root Also updated the install step to install the Registry folder at the engine root * Fixed the copying of the Registry folder to be in the install root, instead of under a second 'Registry' folder * Moving the AssetProcessorPlatformConfig.setreg file over to the Registry folder * Updated the LyTestTools and C++ code to point that the new location of the AssetProcessorPlatformConfig.setreg file inside of the Registry folder * Renamed Test AssetProcessor*Config.ini files to have the .setreg extension * Converted the AssetProcessor test setreg files from ini format to json format using the SerializeContextTools convert-ini command * Updated the AssetProcessor CMakeLists.txt to copy over the test setreg files to the build folder * Updated the assetprocessor test file list to point at the renamed AsssetProcessor*Config setreg filenames * Removed the Output Prefix code from the AssetProcessor. The complexity that it brought to the AP code is not needed, as users can replicate the behavior by just moving there assets underneath a another folder, underneath the scan folder * Adding back support to read the AssetProcessorPlatformConfig.setreg file from the asset root. This is only needed for C++ UnitTests as they run in an environment where the accessing the Engine Settings Registry is not available * Updating the Install_common.cmake logic to copy any "Assets" folder to the install layout. The Script has also been updated to copy over the "Assets" folder in the Engine Root to the install layout instead of an "EngineAssets" folder * Updating References to EngineAssets source asset folder in code to be the Assets source folder * Moved the Engine Source Asset folder of 'EngineAssets' to a new folder name of 'Assets'. This is inline with the naming scheme we use for Gem asset folders * Adding the EngineFinder.cmake to the AutomatedTesting project to allow it to work in a project centric manner * Updating the LyTestTools copy_assets_to_project function to be able to copy assets with folders to the temporary project root Fixed an issue in LyTestTools where the temporary log directory could have shutil.rmtree being called twice on it leading to an exception which fails an automated test Updated the asset_procesor_gui_tests_2 AddScanFolder test to not use the output prefix, but instead place the source asset root into a subdirectory * Correct the AssetProcessorPlatformConfig Scan Folders for the EngineAssets directory to point at the Assets directory * Updated the asset procesor batch dependency test scan folder to point at the 'Assets' folder instead of 'EngineAssets'
3204 lines
143 KiB
C++
3204 lines
143 KiB
C++
/*
|
|
* All or portions of this file Copyright (c) Amazon.com, Inc. or its affiliates or
|
|
* its licensors.
|
|
*
|
|
* For complete copyright and license terms please see the LICENSE at the root of this
|
|
* distribution (the "License"). All use of this software is governed by the License,
|
|
* or, if provided, by the license below or the license accompanying this file. Do not
|
|
* remove or modify any license notices. This file is distributed on an "AS IS" BASIS,
|
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
*
|
|
*/
|
|
|
|
|
|
#include "AssetDatabase.h"
|
|
#include <AzCore/IO/SystemFile.h>
|
|
#include <AzToolsFramework/API/AssetDatabaseBus.h>
|
|
#include <AzToolsFramework/SQLite/SQLiteQuery.h>
|
|
#include <native/utilities/assetUtils.h>
|
|
#include <sqlite3.h>
|
|
|
|
namespace AssetProcessor
|
|
{
|
|
using namespace AzToolsFramework;
|
|
using namespace AzToolsFramework::AssetSystem;
|
|
using namespace AzToolsFramework::AssetDatabase;
|
|
using namespace AzToolsFramework::SQLite;
|
|
|
|
//tack on the namespace to avoid statement name collisions
|
|
namespace
|
|
{
|
|
static const char* LOG_NAME = "AssetProcessor";
|
|
|
|
//////////////////////////////////////////////////////////////////////////
|
|
//tables
|
|
static const char* CREATE_DATABASE_INFOTABLE = "AssetProcessor::CreateDatabaseInfoTable";
|
|
static const char* CREATE_DATABASE_INFOTABLE_STATEMENT =
|
|
"CREATE TABLE IF NOT EXISTS dbinfo( "
|
|
" rowID INTEGER PRIMARY KEY, "
|
|
" version INTEGER NOT NULL);";
|
|
|
|
static const char* CREATE_SCANFOLDERS_TABLE = "AssetProcessor::CreateScanFoldersTable";
|
|
static const char* CREATE_SCANFOLDERS_TABLE_STATEMENT =
|
|
"CREATE TABLE IF NOT EXISTS ScanFolders( "
|
|
" ScanFolderID INTEGER PRIMARY KEY AUTOINCREMENT, "
|
|
" ScanFolder TEXT NOT NULL collate nocase, "
|
|
" DisplayName TEXT NOT NULL collate nocase, "
|
|
" PortableKey TEXT NOT NULL collate nocase, "
|
|
" IsRoot INTEGER NOT NULL);";
|
|
|
|
static const char* CREATE_SOURCES_TABLE = "AssetProcessor::CreateSourceTable";
|
|
static const char* CREATE_SOURCES_TABLE_STATEMENT =
|
|
"CREATE TABLE IF NOT EXISTS Sources("
|
|
" SourceID INTEGER PRIMARY KEY AUTOINCREMENT, "
|
|
" ScanFolderPK INTEGER NOT NULL, "
|
|
" SourceName TEXT NOT NULL collate nocase, "
|
|
" SourceGuid BLOB NOT NULL, "
|
|
" AnalysisFingerprint TEXT default('') collate nocase, "
|
|
" FOREIGN KEY (ScanFolderPK) REFERENCES "
|
|
" ScanFolders(ScanFolderID) ON DELETE CASCADE);";
|
|
|
|
static const char* CREATE_JOBS_TABLE = "AssetProcessor::CreateJobsTable";
|
|
static const char* CREATE_JOBS_TABLE_STATEMENT =
|
|
"CREATE TABLE IF NOT EXISTS Jobs("
|
|
" JobID INTEGER PRIMARY KEY AUTOINCREMENT, "
|
|
" SourcePK INTEGER NOT NULL, "
|
|
" JobKey TEXT NOT NULL collate nocase, "
|
|
" Fingerprint INTEGER NOT NULL, "
|
|
" Platform TEXT NOT NULL collate nocase, "
|
|
" BuilderGuid BLOB NOT NULL, "
|
|
" Status INTEGER NOT NULL, "
|
|
" JobRunKey INTEGER NOT NULL, "
|
|
" FirstFailLogTime INTEGER NOT NULL, "
|
|
" FirstFailLogFile TEXT collate nocase, "
|
|
" LastFailLogTime INTEGER NOT NULL, "
|
|
" LastFailLogFile TEXT collate nocase, "
|
|
" LastLogTime INTEGER NOT NULL, "
|
|
" LastLogFile TEXT collate nocase, "
|
|
" ErrorCount INTEGER NOT NULL, "
|
|
" WarningCount INTEGER NOT NULL, "
|
|
" FOREIGN KEY (SourcePK) REFERENCES "
|
|
" Sources(SourceID) ON DELETE CASCADE);";
|
|
|
|
static const char* CREATEINDEX_JOBS_JOBRUNKEY = "AssetProcesser::CreateIndexJobsJobRunKey";
|
|
static const char* CREATEINDEX_JOBS_JOBRUNKEY_STATEMENT =
|
|
"CREATE INDEX IF NOT EXISTS Jobs_JobRunKey ON Jobs (JobRunKey);";
|
|
|
|
static const char* CREATEINDEX_JOBS_JOBKEY = "AssetProcesser::CreateIndexJobsJobKey";
|
|
static const char* CREATEINDEX_JOBS_JOBKEY_STATEMENT =
|
|
"CREATE INDEX IF NOT EXISTS Jobs_JobKey ON Jobs (JobKey);";
|
|
|
|
static const char* CREATE_PRODUCT_TABLE = "AssetProcessor::CreateProductTable";
|
|
static const char* CREATE_PRODUCT_TABLE_STATEMENT =
|
|
"CREATE TABLE IF NOT EXISTS Products( "
|
|
" ProductID INTEGER PRIMARY KEY AUTOINCREMENT, "
|
|
" JobPK INTEGER NOT NULL, "
|
|
" ProductName TEXT NOT NULL collate nocase, "
|
|
" SubID INTEGER NOT NULL, "
|
|
" AssetType BLOB NOT NULL, "
|
|
" LegacyGuid BLOB NOT NULL, "
|
|
" FOREIGN KEY (JobPK) REFERENCES "
|
|
" Jobs(JobID) ON DELETE CASCADE);";
|
|
|
|
static const char* CREATE_LEGACYSUBIDS_TABLE = "AssetProcessor::CreateLegacySubIDsTable";
|
|
static const char* CREATE_LEGACYSUBIDS_TABLE_STATEMENT =
|
|
"CREATE TABLE IF NOT EXISTS LegacySubIDs( "
|
|
" LegacySubID INTEGER PRIMARY KEY, "
|
|
" ProductPK INTEGER NOT NULL, "
|
|
" SubID INTEGER NOT NULL, "
|
|
" FOREIGN KEY(ProductPK) REFERENCES "
|
|
" Products(ProductID) ON DELETE CASCADE);";
|
|
|
|
static const char* CREATEINDEX_LEGACYSUBIDS_PRODUCTPK = "AssetProcesser::CreateIndexLegacySubIDs_ProductPK";
|
|
static const char* CREATEINDEX_LEGACYSUBIDS_PRODUCTPK_STATEMENT =
|
|
"CREATE INDEX IF NOT EXISTS LegacySubIDs_ProductPK ON LegacySubIDs (ProductPK);";
|
|
|
|
static const char* CREATE_SOURCE_DEPENDENCY_TABLE = "AssetProcessor::CreateSourceDependencyTable";
|
|
static const char* CREATE_SOURCE_DEPENDENCY_TABLE_STATEMENT =
|
|
"CREATE TABLE IF NOT EXISTS SourceDependency("
|
|
" SourceDependencyID INTEGER PRIMARY KEY AUTOINCREMENT, "
|
|
" BuilderGuid BLOB NOT NULL, "
|
|
" Source TEXT NOT NULL collate nocase, "
|
|
" DependsOnSource TEXT NOT NULL collate nocase, "
|
|
" TypeOfDependency INTEGER NOT NULL DEFAULT 0,"
|
|
" FromAssetId INTEGER NOT NULL DEFAULT 0 "
|
|
"); ";
|
|
|
|
static const char* CREATE_PRODUCT_DEPENDENCY_TABLE = "AssetProcessor::CreateProductDependencyTable";
|
|
static const char* CREATE_PRODUCT_DEPENDENCY_TABLE_STATEMENT =
|
|
"CREATE TABLE IF NOT EXISTS ProductDependencies("
|
|
" ProductDependencyID INTEGER PRIMARY KEY AUTOINCREMENT, "
|
|
" ProductPK INTEGER NOT NULL, "
|
|
" DependencySourceGuid BLOB NOT NULL, "
|
|
" DependencySubID INTEGER NOT NULL, "
|
|
" Platform TEXT NOT NULL collate nocase, "
|
|
" DependencyFlags INTEGER NOT NULL, "
|
|
" UnresolvedPath TEXT NOT NULL collate nocase, "
|
|
" UnresolvedDependencyType INTEGER NOT NULL DEFAULT 0, "
|
|
" FromAssetId INTEGER NOT NULL DEFAULT 0, "
|
|
" FOREIGN KEY (ProductPK) REFERENCES "
|
|
" Products(ProductID) ON DELETE CASCADE);";
|
|
|
|
static const char* CREATE_MISSING_PRODUCT_DEPENDENCY_TABLE = "AssetProcessor::CreateMissingProductDependencyTable";
|
|
static const char* CREATE_MISSING_PRODUCT_DEPENDENCY_TABLE_STATEMENT =
|
|
"CREATE TABLE IF NOT EXISTS MissingProductDependencies("
|
|
" MissingProductDependencyId INTEGER PRIMARY KEY AUTOINCREMENT, "
|
|
" ProductPK INTEGER NOT NULL, "
|
|
" ScannerId TEXT NOT NULL, "
|
|
" ScannerVersion TEXT NOT NULL, "
|
|
" SourceFileFingerprint TEXT NOT NULL, "
|
|
" DependencySourceGuid BLOB NOT NULL, "
|
|
" DependencySubId INTEGER, "
|
|
" MissingDependencyString TEXT NOT NULL, "
|
|
" LastScanTime TEXT, "
|
|
" ScanTimeSecondsSinceEpoch INTEGER, "
|
|
" FOREIGN KEY (ProductPK) REFERENCES "
|
|
" Products(ProductID) ON DELETE CASCADE);";
|
|
|
|
static const char* CREATE_FILES_TABLE = "AssetProcessor::CreateFilesTable";
|
|
static const char* CREATE_FILES_TABLE_STATEMENT =
|
|
"CREATE TABLE IF NOT EXISTS Files( "
|
|
" FileID INTEGER PRIMARY KEY AUTOINCREMENT, "
|
|
" ScanFolderPK INTEGER NOT NULL, "
|
|
" FileName TEXT NOT NULL collate nocase, "
|
|
" IsFolder INTEGER NOT NULL, "
|
|
" ModTime INTEGER NOT NULL, "
|
|
" Hash INTEGER NOT NULL, "
|
|
" FOREIGN KEY (ScanFolderPK) REFERENCES "
|
|
" ScanFolders(ScanFolderID) ON DELETE CASCADE);";
|
|
|
|
//////////////////////////////////////////////////////////////////////////
|
|
//indices
|
|
static const char* CREATEINDEX_DEPENDSONSOURCE_SOURCEDEPENDENCY = "AssetProcesser::CreateIndexDependsOnSource_SourceDependency";
|
|
static const char* CREATEINDEX_DEPENDSONSOURCE_SOURCEDEPENDENCY_STATEMENT =
|
|
"CREATE INDEX IF NOT EXISTS DependsOnSource_SourceDependency ON SourceDependency (DependsOnSource);";
|
|
static const char* CREATEINDEX_BUILDERGUID_SOURCE_SOURCEDEPENDENCY = "AssetProcesser::CreateIndexBuilderGuid_Source_SourceDependency";
|
|
static const char* CREATEINDEX_BUILDERGUID_SOURCE_SOURCEDEPENDENCY_STATEMENT =
|
|
"CREATE INDEX IF NOT EXISTS BuilderGuid_Source_SourceDependency ON SourceDependency (BuilderGuid, Source);";
|
|
static const char* CREATEINDEX_TYPEOFDEPENDENCY_SOURCEDEPENDENCY = "AssetProcessor::CreateIndexTypeOfDependency_SourceDependency";
|
|
static const char* CREATEINDEX_TYPEOFDEPENDENCY_SOURCEDEPENDENCY_STATEMENT =
|
|
"CREATE INDEX IF NOT EXISTS TypeOfDependency_SourceDependency ON SourceDependency (TypeOfDependency);";
|
|
|
|
static const char* CREATEINDEX_SCANFOLDERS_SOURCES = "AssetProcesser::CreateIndexScanFoldersSources";
|
|
static const char* CREATEINDEX_SCANFOLDERS_SOURCES_STATEMENT =
|
|
"CREATE INDEX IF NOT EXISTS ScanFolders_Sources ON Sources (ScanFolderPK);";
|
|
static const char* DROPINDEX_SCANFOLDERS_SOURCES_STATEMENT =
|
|
"DROP INDEX IF EXISTS ScanFolders_Sources_idx;";
|
|
|
|
static const char* CREATEINDEX_SCANFOLDERS_SOURCES_SCANFOLDER = "AssetProcesser::CreateIndexScanFoldersSourcesScanFolder";
|
|
static const char* CREATEINDEX_SCANFOLDERS_SOURCES_SCANFOLDER_STATEMENT =
|
|
"CREATE INDEX IF NOT EXISTS IdxSources_SourceAndScanFolder ON Sources (ScanFolderPK, SourceName);";
|
|
|
|
static const char* CREATEINDEX_SOURCES_JOBS = "AssetProcesser::CreateIndexSourcesJobs";
|
|
static const char* CREATEINDEX_SOURCES_JOBS_STATEMENT =
|
|
"CREATE INDEX IF NOT EXISTS Sources_Jobs ON Jobs (SourcePK);";
|
|
static const char* DROPINDEX_SOURCES_JOBS_STATEMENT =
|
|
"DROP INDEX IF EXISTS Sources_Jobs_idx;";
|
|
|
|
static const char* CREATEINDEX_JOBS_PRODUCTS = "AssetProcesser::CreateIndexJobsProducts";
|
|
static const char* CREATEINDEX_JOBS_PRODUCTS_STATEMENT =
|
|
"CREATE INDEX IF NOT EXISTS Jobs_Products ON Products (JobPK);";
|
|
static const char* DROPINDEX_JOBS_PRODUCTS_STATEMENT =
|
|
"DROP INDEX IF EXISTS Jobs_Products_idx;";
|
|
|
|
static const char* CREATEINDEX_SOURCE_NAME = "AssetProcessor::CreateIndexSourceName";
|
|
static const char* CREATEINDEX_SOURCE_NAME_STATEMENT =
|
|
"CREATE INDEX IF NOT EXISTS Sources_SourceName ON Sources (SourceName);";
|
|
static const char* DROPINDEX_SOURCE_NAME_STATEMENT =
|
|
"DROP INDEX IF EXISTS Sources_SourceName_idx;";
|
|
|
|
static const char* CREATEINDEX_SOURCE_GUID = "AssetProcessor::CreateIndexSourceGuid";
|
|
static const char* CREATEINDEX_SOURCE_GUID_STATEMENT =
|
|
"CREATE INDEX IF NOT EXISTS Sources_SourceGuid ON Sources (SourceGuid);";
|
|
|
|
static const char* CREATEINDEX_PRODUCT_NAME = "AssetProcessor::CreateIndexProductName";
|
|
static const char* CREATEINDEX_PRODUCT_NAME_STATEMENT =
|
|
"CREATE INDEX IF NOT EXISTS Products_ProductName ON Products (ProductName);";
|
|
static const char* DROPINDEX_PRODUCT_NAME_STATEMENT =
|
|
"DROP INDEX IF EXISTS Products_ProductName_idx;";
|
|
|
|
static const char* CREATEINDEX_PRODUCT_SUBID = "AssetProcessor::CreateIndexProductSubID";
|
|
static const char* CREATEINDEX_PRODUCT_SUBID_STATEMENT =
|
|
"CREATE INDEX IF NOT EXISTS Products_SubID ON Products (SubID);";
|
|
|
|
static const char* CREATEINDEX_PRODUCTDEPENDENCIES_PRODUCTPK = "AssetProcessor::CreateIndexProductDependenciesProductPK";
|
|
static const char* CREATEINDEX_PRODUCTDEPENDENCIES_PRODUCTPK_STATEMENT =
|
|
"CREATE INDEX IF NOT EXISTS ProductDependencies_ProductPK ON ProductDependencies (ProductPK);";
|
|
|
|
static const char* CREATEINDEX_PRODUCTDEPENDENCIES_UNRESOLVEDPATH = "AssetProccessor::CreateIndexProductDependenciesUnresolvedPath";
|
|
static const char* CREATEINDEX_PRODUCTDEPENDENCIES_UNRESOLVEDPATH_STATEMENT =
|
|
"CREATE INDEX IF NOT EXISTS ProductDependencies_UnresolvedPath ON ProductDependencies (UnresolvedPath);";
|
|
|
|
static const char* CREATEINDEX_PRODUCTDEPENDENCIES_UNRESOLVEDPATH_WILDCARD = "AssetProccessor::CreateIndexProductDependenciesUnresolvedPathWildcard";
|
|
static const char* CREATEINDEX_PRODUCTDEPENDENCIES_UNRESOLVEDPATH_WILDCARD_STATEMENT =
|
|
"CREATE INDEX IF NOT EXISTS ProductDependencies_UnresolvedPathWildcard ON ProductDependencies (UnresolvedPath) WHERE UnresolvedPath LIKE \"%*%\"";
|
|
|
|
static const char* CREATEINDEX_FILE_NAME = "AssetProcessor::CreateIndexFilesName";
|
|
static const char* CREATEINDEX_FILE_NAME_STATEMENT =
|
|
"CREATE INDEX IF NOT EXISTS Files_FileName ON Files (FileName);";
|
|
|
|
static const char* CREATEINDEX_SCANFOLDERS_FILES = "AssetProcesser::CreateIndexScanFoldersFiles";
|
|
static const char* CREATEINDEX_SCANFOLDERS_FILES_STATEMENT =
|
|
"CREATE INDEX IF NOT EXISTS ScanFolders_Files ON Files (ScanFolderPK);";
|
|
|
|
//////////////////////////////////////////////////////////////////////////
|
|
//insert/set/update/delete
|
|
static const char* SET_DATABASE_VERSION = "AssetProcessor::SetDatabaseVersion";
|
|
static const char* SET_DATABASE_VERSION_STATEMENT =
|
|
"INSERT OR REPLACE INTO dbinfo(rowID, version) "
|
|
"VALUES (1, :ver);";
|
|
|
|
static const auto s_SetDatabaseVersionQuery = MakeSqlQuery(SET_DATABASE_VERSION, SET_DATABASE_VERSION_STATEMENT, LOG_NAME,
|
|
SqlParam<AZ::s32>(":ver"));
|
|
|
|
static const char* INSERT_SCANFOLDER = "AssetProcessor::InsertScanFolder";
|
|
static const char* INSERT_SCANFOLDER_STATEMENT =
|
|
"INSERT INTO ScanFolders (ScanFolder, DisplayName, PortableKey, IsRoot) "
|
|
"VALUES (:scanfolder, :displayname, :portablekey, :isroot);";
|
|
|
|
static const auto s_InsertScanfolderQuery = MakeSqlQuery(INSERT_SCANFOLDER, INSERT_SCANFOLDER_STATEMENT, LOG_NAME,
|
|
SqlParam<const char*>(":scanfolder"),
|
|
SqlParam<const char*>(":displayname"),
|
|
SqlParam<const char*>(":portablekey"),
|
|
SqlParam<AZ::s32>(":isroot"));
|
|
|
|
static const char* UPDATE_SCANFOLDER = "AssetProcessor::UpdateScanFolder";
|
|
static const char* UPDATE_SCANFOLDER_STATEMENT =
|
|
"UPDATE ScanFolders SET "
|
|
"ScanFolder = :scanfolder, "
|
|
"DisplayName = :displayname, "
|
|
"PortableKey = :portablekey, "
|
|
"IsRoot = :isroot "
|
|
"WHERE "
|
|
"ScanFolderID = :scanfolderid;";
|
|
|
|
static const auto s_UpdateScanfolderQuery = MakeSqlQuery(UPDATE_SCANFOLDER, UPDATE_SCANFOLDER_STATEMENT, LOG_NAME,
|
|
SqlParam<const char*>(":scanfolder"),
|
|
SqlParam<const char*>(":displayname"),
|
|
SqlParam<const char*>(":portablekey"),
|
|
SqlParam<AZ::s32>(":isroot"),
|
|
SqlParam<AZ::s64>(":scanfolderid"));
|
|
|
|
static const char* DELETE_SCANFOLDER = "AssetProcessor::RemoveScanFolder";
|
|
static const char* DELETE_SCANFOLDER_STATEMENT =
|
|
"DELETE FROM ScanFolders WHERE "
|
|
"(ScanFolderID = :scanfolderid);";
|
|
|
|
static const auto s_DeleteScanfolderQuery = MakeSqlQuery(DELETE_SCANFOLDER, DELETE_SCANFOLDER_STATEMENT, LOG_NAME,
|
|
SqlParam<AZ::s64>(":scanfolderid"));
|
|
|
|
static const char* INSERT_SOURCE = "AssetProcessor::InsertSource";
|
|
static const char* INSERT_SOURCE_STATEMENT =
|
|
"INSERT INTO Sources (ScanFolderPK, SourceName, SourceGuid, AnalysisFingerprint) "
|
|
"VALUES (:scanfolderid, :sourcename, :sourceguid, :analysisFingerprint);";
|
|
|
|
static const auto s_InsertSourceQuery = MakeSqlQuery(INSERT_SOURCE, INSERT_SOURCE_STATEMENT, LOG_NAME,
|
|
SqlParam<AZ::s64>(":scanfolderid"),
|
|
SqlParam<const char*>(":sourcename"),
|
|
SqlParam<AZ::Uuid>(":sourceguid"),
|
|
SqlParam<const char*>(":analysisFingerprint"));
|
|
|
|
static const char* UPDATE_SOURCE = "AssetProcessor::UpdateSource";
|
|
static const char* UPDATE_SOURCE_STATEMENT =
|
|
"UPDATE Sources SET "
|
|
"ScanFolderPK = :scanfolderpk, "
|
|
"SourceName = :sourcename, "
|
|
"SourceGuid = :sourceguid, "
|
|
"AnalysisFingerprint = :analysisFingerprint "
|
|
"WHERE SourceID = :sourceid;";
|
|
|
|
static const auto s_UpdateSourceQuery = MakeSqlQuery(UPDATE_SOURCE, UPDATE_SOURCE_STATEMENT, LOG_NAME,
|
|
SqlParam<AZ::s64>(":scanfolderpk"),
|
|
SqlParam<const char*>(":sourcename"),
|
|
SqlParam<AZ::Uuid>(":sourceguid"),
|
|
SqlParam<AZ::s64>(":sourceid"),
|
|
SqlParam<const char*>(":analysisFingerprint"));
|
|
|
|
static const char* DELETE_SOURCE = "AssetProcessor::DeleteSource";
|
|
static const char* DELETE_SOURCE_STATEMENT =
|
|
"DELETE FROM Sources WHERE "
|
|
"SourceID = :sourceid;";
|
|
|
|
static const auto s_DeleteSourceQuery = MakeSqlQuery(DELETE_SOURCE, DELETE_SOURCE_STATEMENT, LOG_NAME,
|
|
SqlParam<AZ::s64>(":sourceid"));
|
|
|
|
static const char* DELETE_SOURCE_BY_SCANFOLDERID = "AssetProcessor::DeleteSourceByScanFolderID";
|
|
static const char* DELETE_SOURCE_BY_SCANFOLDERID_STATEMENT =
|
|
"DELETE FROM Sources WHERE "
|
|
"ScanFolderPK = :scanfolderid;";
|
|
|
|
static const auto s_DeleteSourceByScanfolderidQuery = MakeSqlQuery(DELETE_SOURCE_BY_SCANFOLDERID, DELETE_SOURCE_BY_SCANFOLDERID_STATEMENT, LOG_NAME,
|
|
SqlParam<AZ::s64>(":scanfolderid"));
|
|
|
|
static const char* INVALIDATE_SOURCE_ANALYSISFINGEPRINTS = "AssetProcessor::InvalidateSourceAnalysisFingerprints";
|
|
static const char* INVALIDATE_SOURCE_ANALYSISFINGEPRINTS_STATEMENT =
|
|
"UPDATE Sources SET AnalysisFingerprint = ''";
|
|
|
|
static const char* GET_HIGHEST_JOBRUNKEY = "AssetProcessor::GetHighestJobRunKey";
|
|
static const char* GET_HIGHEST_JOBRUNKEY_STATEMENT =
|
|
"SELECT JobRunKey FROM Jobs ORDER BY JobRunKey DESC LIMIT 1;";
|
|
|
|
static const auto s_GetHighestJobrunkeyQuery = MakeSqlQuery(GET_HIGHEST_JOBRUNKEY, GET_HIGHEST_JOBRUNKEY_STATEMENT, LOG_NAME);
|
|
|
|
static const char* INSERT_JOB = "AssetProcessor::InsertJob";
|
|
static const char* INSERT_JOB_STATEMENT =
|
|
"INSERT INTO Jobs (SourcePK, JobKey, Fingerprint, Platform, BuilderGuid, Status, JobRunKey, FirstFailLogTime, FirstFailLogFile, LastFailLogTime, LastFailLogFile, LastLogTime, LastLogFile, WarningCount, ErrorCount) "
|
|
"VALUES (:sourceid, :jobkey, :fingerprint, :platform, :builderguid, :status, :jobrunkey, :firstfaillogtime, :firstfaillogfile, :lastfaillogtime, :lastfaillogfile, :lastlogtime, :lastlogfile, :warningcount, :errorcount);";
|
|
|
|
static const auto s_InsertJobQuery = MakeSqlQuery(INSERT_JOB, INSERT_JOB_STATEMENT, LOG_NAME,
|
|
SqlParam<AZ::s64>(":sourceid"),
|
|
SqlParam<const char*>(":jobkey"),
|
|
SqlParam<AZ::u32>(":fingerprint"),
|
|
SqlParam<const char*>(":platform"),
|
|
SqlParam<AZ::Uuid>(":builderguid"),
|
|
SqlParam<AZ::s32>(":status"),
|
|
SqlParam<AZ::u64>(":jobrunkey"),
|
|
SqlParam<AZ::s64>(":firstfaillogtime"),
|
|
SqlParam<const char*>(":firstfaillogfile"),
|
|
SqlParam<AZ::s64>(":lastfaillogtime"),
|
|
SqlParam<const char*>(":lastfaillogfile"),
|
|
SqlParam<AZ::s64>(":lastlogtime"),
|
|
SqlParam<const char*>(":lastlogfile"),
|
|
SqlParam<AZ::u32>(":warningcount"),
|
|
SqlParam<AZ::u32>(":errorcount")
|
|
);
|
|
|
|
static const char* UPDATE_JOB = "AssetProcessor::UpdateJob";
|
|
static const char* UPDATE_JOB_STATEMENT =
|
|
"UPDATE Jobs SET "
|
|
"SourcePK = :sourceid, "
|
|
"JobKey = :jobkey, "
|
|
"Fingerprint = :fingerprint, "
|
|
"Platform = :platform, "
|
|
"BuilderGuid = :builderguid, "
|
|
"Status = :status, "
|
|
"JobRunKey = :jobrunkey, "
|
|
"FirstFailLogTime = :firstfaillogtime, "
|
|
"FirstFailLogFile = :firstfaillogfile, "
|
|
"LastFailLogTime = :lastfaillogtime, "
|
|
"LastFailLogFile = :lastfaillogfile, "
|
|
"LastLogTime = :lastlogtime, "
|
|
"LastLogFile = :lastlogfile, "
|
|
"WarningCount = :warningcount, "
|
|
"ErrorCount = :errorcount "
|
|
"WHERE JobID = :jobid;";
|
|
|
|
static const auto s_UpdateJobQuery = MakeSqlQuery(UPDATE_JOB, UPDATE_JOB_STATEMENT, LOG_NAME,
|
|
SqlParam<AZ::s64>(":sourceid"),
|
|
SqlParam<const char*>(":jobkey"),
|
|
SqlParam<AZ::u32>(":fingerprint"),
|
|
SqlParam<const char*>(":platform"),
|
|
SqlParam<AZ::Uuid>(":builderguid"),
|
|
SqlParam<AZ::s32>(":status"),
|
|
SqlParam<AZ::u64>(":jobrunkey"),
|
|
SqlParam<AZ::s64>(":firstfaillogtime"),
|
|
SqlParam<const char*>(":firstfaillogfile"),
|
|
SqlParam<AZ::s64>(":lastfaillogtime"),
|
|
SqlParam<const char*>(":lastfaillogfile"),
|
|
SqlParam<AZ::s64>(":lastlogtime"),
|
|
SqlParam<const char*>(":lastlogfile"),
|
|
SqlParam<AZ::u32>(":warningcount"),
|
|
SqlParam<AZ::u32>(":errorcount"),
|
|
SqlParam<AZ::s64>(":jobid")
|
|
);
|
|
|
|
static const char* DELETE_JOB = "AssetProcessor::DeleteJob";
|
|
static const char* DELETE_JOB_STATEMENT =
|
|
"DELETE FROM Jobs WHERE "
|
|
"JobID = :jobid;";
|
|
|
|
static const auto s_DeleteJobQuery = MakeSqlQuery(DELETE_JOB, DELETE_JOB_STATEMENT, LOG_NAME,
|
|
SqlParam<AZ::s64>(":jobid"));
|
|
|
|
static const char* INSERT_PRODUCT = "AssetProcessor::InsertProduct";
|
|
static const char* INSERT_PRODUCT_STATEMENT =
|
|
"INSERT INTO Products (JobPK, SubID, ProductName, AssetType, LegacyGuid) "
|
|
"VALUES (:jobid, :subid, :productname, :assettype, :legacyguid);";
|
|
|
|
static const auto s_InsertProductQuery = MakeSqlQuery(INSERT_PRODUCT, INSERT_PRODUCT_STATEMENT, LOG_NAME,
|
|
SqlParam<AZ::s64>(":jobid"),
|
|
SqlParam<AZ::u32>(":subid"),
|
|
SqlParam<const char*>(":productname"),
|
|
SqlParam<AZ::Uuid>(":assettype"),
|
|
SqlParam<AZ::Uuid>(":legacyguid"));
|
|
|
|
static const char* UPDATE_PRODUCT = "AssetProcessor::UpdateProduct";
|
|
static const char* UPDATE_PRODUCT_STATEMENT =
|
|
"UPDATE Products SET "
|
|
"JobPK = :jobid, "
|
|
"SubID = :subid, "
|
|
"ProductName = :productname, "
|
|
"AssetType = :assettype, "
|
|
"LegacyGuid = :legacyguid WHERE "
|
|
"ProductID = :productid;";
|
|
|
|
static const auto s_UpdateProductQuery = MakeSqlQuery(UPDATE_PRODUCT, UPDATE_PRODUCT_STATEMENT, LOG_NAME,
|
|
SqlParam<AZ::s64>(":jobid"),
|
|
SqlParam<AZ::u32>(":subid"),
|
|
SqlParam<const char*>(":productname"),
|
|
SqlParam<AZ::Uuid>(":assettype"),
|
|
SqlParam<AZ::Uuid>(":legacyguid"),
|
|
SqlParam<AZ::s64>(":productid"));
|
|
|
|
static const char* DELETE_PRODUCT = "AssetProcessor::DeleteProduct";
|
|
static const char* DELETE_PRODUCT_STATEMENT =
|
|
"DELETE FROM Products WHERE "
|
|
"ProductID = :productid;";
|
|
|
|
static const auto s_DeleteProductQuery = MakeSqlQuery(DELETE_PRODUCT, DELETE_PRODUCT_STATEMENT, LOG_NAME,
|
|
SqlParam<AZ::s64>(":productid"));
|
|
|
|
static const char* DELETE_PRODUCTS_BY_JOBID = "AssetProcessor::DeleteAllProductsByJobID";
|
|
static const char* DELETE_PRODUCTS_BY_JOBID_STATEMENT =
|
|
"DELETE FROM Products WHERE "
|
|
"JobPK = :jobid;";
|
|
|
|
static const auto s_DeleteProductsByJobidQuery = MakeSqlQuery(DELETE_PRODUCTS_BY_JOBID, DELETE_PRODUCTS_BY_JOBID_STATEMENT, LOG_NAME,
|
|
SqlParam<AZ::s64>(":jobid"));
|
|
|
|
static const char* DELETE_PRODUCTS_BY_SOURCEID = "AssetProcessor::DeleteAllProductsBySourceID";
|
|
static const char* DELETE_PRODUCTS_BY_SOURCEID_STATEMENT =
|
|
"DELETE FROM Products "
|
|
"WHERE EXISTS "
|
|
"(SELECT * FROM Jobs WHERE "
|
|
"Products.JobPK = Jobs.JobID AND "
|
|
"Jobs.SourcePK = :sourceid);";
|
|
|
|
static const auto s_DeleteProductsBySourceidQuery = MakeSqlQuery(DELETE_PRODUCTS_BY_SOURCEID, DELETE_PRODUCTS_BY_SOURCEID_STATEMENT, LOG_NAME,
|
|
SqlParam<AZ::s64>(":sourceid"));
|
|
|
|
static const char* DELETE_PRODUCTS_BY_SOURCEID_PLATFORM = "AssetProcessor::DeleteProductsBySourceIDPlatform";
|
|
static const char* DELETE_PRODUCTS_BY_SOURCEID_PLATFORM_STATEMENT =
|
|
"DELETE FROM Products "
|
|
"WHERE EXISTS "
|
|
"(SELECT * FROM Jobs WHERE "
|
|
"Products.JobPK = Jobs.JobID AND "
|
|
"Jobs.SourcePK = :sourceid AND "
|
|
"Jobs.Platform = :platform);";
|
|
|
|
static const auto s_DeleteProductsBySourceidPlatformQuery = MakeSqlQuery(DELETE_PRODUCTS_BY_SOURCEID_PLATFORM, DELETE_PRODUCTS_BY_SOURCEID_PLATFORM_STATEMENT, LOG_NAME,
|
|
SqlParam<AZ::s64>(":sourceid"),
|
|
SqlParam<const char*>(":platform"));
|
|
|
|
static const char* INSERT_SOURCE_DEPENDENCY = "AssetProcessor::InsertSourceDependency";
|
|
static const char* INSERT_SOURCE_DEPENDENCY_STATEMENT =
|
|
"INSERT INTO SourceDependency (BuilderGuid, Source, DependsOnSource, TypeOfDependency, FromAssetId) "
|
|
"VALUES (:builderGuid, :source, :dependsOnSource, :typeofdependency, :fromAssetId);";
|
|
static const auto s_InsertSourceDependencyQuery = MakeSqlQuery(INSERT_SOURCE_DEPENDENCY, INSERT_SOURCE_DEPENDENCY_STATEMENT, LOG_NAME,
|
|
SqlParam<AZ::Uuid>(":builderGuid"),
|
|
SqlParam<const char*>(":source"),
|
|
SqlParam<const char*>(":dependsOnSource"),
|
|
SqlParam<AZ::s32>(":typeofdependency"),
|
|
SqlParam<AZ::s32>(":fromAssetId"));
|
|
|
|
static const char* DELETE_SOURCE_DEPENDENCY_SOURCEDEPENDENCYID = "AssetProcessor::DeleteSourceDependencBySourceDependencyId";
|
|
static const char* DELETE_SOURCE_DEPENDENCY_SOURCEDEPENDENCYID_STATEMENT =
|
|
"DELETE FROM SourceDependency WHERE "
|
|
"SourceDependencyID = :sourceDependencyId;";
|
|
static const auto s_DeleteSourceDependencySourcedependencyidQuery = MakeSqlQuery(DELETE_SOURCE_DEPENDENCY_SOURCEDEPENDENCYID, DELETE_SOURCE_DEPENDENCY_SOURCEDEPENDENCYID_STATEMENT, LOG_NAME,
|
|
SqlParam<AZ::s64>(":sourceDependencyId"));
|
|
|
|
static const char* INSERT_NEW_LEGACYSUBID = "AssetProcessor::InsertLegacySubID";
|
|
static const char* INSERT_NEW_LEGACYSUBID_STATEMENT =
|
|
"INSERT INTO LegacySubIDs (ProductPK, SubID) "
|
|
"VALUES (:productPK, :subID);";
|
|
|
|
static const auto s_InsertNewLegacysubidQuery = MakeSqlQuery(INSERT_NEW_LEGACYSUBID, INSERT_NEW_LEGACYSUBID_STATEMENT, LOG_NAME,
|
|
SqlParam<AZ::s64>(":productPK"),
|
|
SqlParam<AZ::u32>(":subID"));
|
|
|
|
static const char* OVERWRITE_EXISTING_LEGACYSUBID = "AssetProcessor::OverwriteLegacySubID";
|
|
static const char* OVERWRITE_EXISTING_LEGACYSUBID_STATEMENT =
|
|
"UPDATE LegacySubIDs "
|
|
" SET "
|
|
" ProductPK = :productPK, "
|
|
" SubID = :subID "
|
|
" WHERE "
|
|
" LegacySubID = :legacySubID;";
|
|
|
|
static const auto s_OverwriteExistingLegacysubidQuery = MakeSqlQuery(OVERWRITE_EXISTING_LEGACYSUBID, OVERWRITE_EXISTING_LEGACYSUBID_STATEMENT, LOG_NAME,
|
|
SqlParam<AZ::s64>(":productPK"),
|
|
SqlParam<AZ::u32>(":subID"),
|
|
SqlParam<AZ::s64>(":legacySubID"));
|
|
|
|
static const char* DELETE_LEGACYSUBIDS_BY_PRIMARY_KEY = "AssetProcessor::DeleteLegacySubIDsByPrimaryKey";
|
|
static const char* DELETE_LEGACYSUBIDS_BY_PRIMARY_KEY_STATEMENT =
|
|
"DELETE FROM LegacySubIDs WHERE "
|
|
"LegacySubID = :legacySubID;";
|
|
|
|
static const auto s_DeleteLegacysubidsByPrimaryKeyQuery = MakeSqlQuery(DELETE_LEGACYSUBIDS_BY_PRIMARY_KEY, DELETE_LEGACYSUBIDS_BY_PRIMARY_KEY_STATEMENT, LOG_NAME,
|
|
SqlParam<AZ::s64>(":legacySubID"));
|
|
|
|
static const char* DELETE_LEGACYSUBIDS_BY_PRODUCTID = "AssetProcessor::DeleteLegacySubIDsByProductID";
|
|
static const char* DELETE_LEGACYSUBIDS_BY_PRODUCTID_STATEMENT =
|
|
"DELETE FROM LegacySubIDs WHERE "
|
|
"ProductPK = :productPK;";
|
|
|
|
static const auto s_DeleteLegacysubidsByProductidQuery = MakeSqlQuery(DELETE_LEGACYSUBIDS_BY_PRODUCTID, DELETE_LEGACYSUBIDS_BY_PRODUCTID_STATEMENT, LOG_NAME,
|
|
SqlParam<AZ::s64>(":productPK"));
|
|
|
|
static const char* INSERT_PRODUCT_DEPENDENCY = "AssetProcessor::InsertProductDependency";
|
|
static const char* INSERT_PRODUCT_DEPENDENCY_STATEMENT =
|
|
"INSERT INTO ProductDependencies (ProductPK, DependencySourceGuid, DependencySubID, DependencyFlags, Platform, UnresolvedPath, UnresolvedDependencyType, FromAssetId) "
|
|
"VALUES (:productPK, :dependencySourceGuid, :dependencySubID, :dependencyFlags, :platform, :unresolvedPath, :typeofdependency, :fromAssetId);";
|
|
|
|
static const auto s_InsertProductDependencyQuery = MakeSqlQuery(INSERT_PRODUCT_DEPENDENCY, INSERT_PRODUCT_DEPENDENCY_STATEMENT, LOG_NAME,
|
|
SqlParam<AZ::s64>(":productPK"),
|
|
SqlParam<AZ::Uuid>(":dependencySourceGuid"),
|
|
SqlParam<AZ::u32>(":dependencySubID"),
|
|
SqlParam<AZ::s64>(":dependencyFlags"),
|
|
SqlParam<const char*>(":platform"),
|
|
SqlParam<const char*>(":unresolvedPath"),
|
|
SqlParam<AZ::u32>(":typeofdependency"),
|
|
SqlParam<AZ::u32>(":fromAssetId"));
|
|
|
|
static const char* UPDATE_PRODUCT_DEPENDENCY = "AssetProcessor::UpdateProductDependency";
|
|
static const char* UPDATE_PRODUCT_DEPENDENCY_STATEMENT =
|
|
"UPDATE ProductDependencies SET "
|
|
"ProductPK = :productPK, "
|
|
"DependencySourceGuid = :dependencySourceGuid, "
|
|
"DependencySubID = :dependencySubID, "
|
|
"DependencyFlags = :dependencyFlags, "
|
|
"Platform = :platform, "
|
|
"UnresolvedPath = :unresolvedPath, "
|
|
"UnresolvedDependencyType = :typeofdependency, "
|
|
"FromAssetId = :fromAssetId WHERE "
|
|
"ProductDependencyID = :productDependencyID;";
|
|
|
|
static const auto s_UpdateProductDependencyQuery = MakeSqlQuery(UPDATE_PRODUCT_DEPENDENCY, UPDATE_PRODUCT_DEPENDENCY_STATEMENT, LOG_NAME,
|
|
SqlParam<AZ::s64>(":productPK"),
|
|
SqlParam<AZ::Uuid>(":dependencySourceGuid"),
|
|
SqlParam<AZ::u32>(":dependencySubID"),
|
|
SqlParam<AZ::u64>(":dependencyFlags"),
|
|
SqlParam<const char*>(":platform"),
|
|
SqlParam<const char *>(":unresolvedPath"),
|
|
SqlParam<AZ::s64>(":productDependencyID"),
|
|
SqlParam<AZ::u32>(":typeofdependency"),
|
|
SqlParam<AZ::u32>(":fromAssetId"));
|
|
|
|
static const char* DELETE_PRODUCT_DEPENDENCY_BY_PRODUCTID = "AssetProcessor::DeleteProductDependencyByProductId";
|
|
static const char* DELETE_PRODUCT_DEPENDENCY_BY_PRODUCTID_STATEMENT =
|
|
"DELETE FROM ProductDependencies WHERE "
|
|
"ProductPK = :productpk;";
|
|
static const auto s_DeleteProductDependencyByProductIdQuery = MakeSqlQuery(DELETE_PRODUCT_DEPENDENCY_BY_PRODUCTID, DELETE_PRODUCT_DEPENDENCY_BY_PRODUCTID_STATEMENT, LOG_NAME,
|
|
SqlParam<AZ::s64>(":productpk"));
|
|
|
|
static const char* INSERT_MISSING_PRODUCT_DEPENDENCY = "AssetProcessor::InsertMissingProductDependency";
|
|
static const char* INSERT_MISSING_PRODUCT_DEPENDENCY_STATEMENT =
|
|
"INSERT INTO MissingProductDependencies (ProductPK, ScannerId, ScannerVersion, SourceFileFingerprint, DependencySourceGuid, DependencySubId, MissingDependencyString, LastScanTime, ScanTimeSecondsSinceEpoch) "
|
|
"VALUES (:productPK, :scannerId, :scannerVersion, :sourceFileFingerprint, :dependencySourceGuid, :dependencySubId, :missingDependencyString, :lastScanTime, :scanTimeSecondsSinceEpoch);";
|
|
|
|
static const char* DELETE_MISSING_PRODUCT_DEPENDENCY_BY_PRODUCTID = "AssetProcessor::DeleteMissingProductDependencyByProductId";
|
|
static const char* DELETE_MISSING_PRODUCT_DEPENDENCY_BY_PRODUCTID_STATEMENT =
|
|
"DELETE FROM MissingProductDependencies WHERE "
|
|
"ProductPK = :productpk;";
|
|
|
|
static const char* UPDATE_MISSING_PRODUCT_DEPENDENCY = "AssetProcessor::UpdateMissingProductDependency";
|
|
static const char* UPDATE_MISSING_PRODUCT_DEPENDENCY_STATEMENT =
|
|
"UPDATE MissingProductDependencies SET "
|
|
"ProductPK = :productPK, "
|
|
"ScannerId = :scannerId, "
|
|
"ScannerVersion = :scannerVersion, "
|
|
"SourceFileFingerprint = :sourceFileFingerprint, "
|
|
"DependencySourceGuid = :dependencySourceGuid, "
|
|
"DependencySubId = :dependencySubId, "
|
|
"MissingDependencyString = :missingDependencyString, "
|
|
"LastScanTime = :lastScanTime, "
|
|
"ScanTimeSecondsSinceEpoch = :scanTimeSecondsSinceEpoch WHERE "
|
|
"MissingProductDependencyId = :missingProductDependencyId;";
|
|
|
|
static const auto s_InsertMissingProductDependencyQuery = MakeSqlQuery(INSERT_MISSING_PRODUCT_DEPENDENCY, INSERT_MISSING_PRODUCT_DEPENDENCY_STATEMENT, LOG_NAME,
|
|
SqlParam<AZ::s64>(":productPK"),
|
|
SqlParam<const char*>(":scannerId"),
|
|
SqlParam<const char*>(":scannerVersion"),
|
|
SqlParam<const char*>(":sourceFileFingerprint"),
|
|
SqlParam<AZ::Uuid>(":dependencySourceGuid"),
|
|
SqlParam<AZ::u32>(":dependencySubId"),
|
|
SqlParam<const char*>(":missingDependencyString"),
|
|
SqlParam<const char*>(":lastScanTime"),
|
|
SqlParam<AZ::u64>(":scanTimeSecondsSinceEpoch"));
|
|
|
|
static const auto s_UpdateMissingProductDependencyQuery = MakeSqlQuery(UPDATE_MISSING_PRODUCT_DEPENDENCY, UPDATE_MISSING_PRODUCT_DEPENDENCY_STATEMENT, LOG_NAME,
|
|
SqlParam<AZ::s64>(":missingProductDependencyId"),
|
|
SqlParam<AZ::s64>(":productPK"),
|
|
SqlParam<const char*>(":scannerId"),
|
|
SqlParam<const char*>(":scannerVersion"),
|
|
SqlParam<const char*>(":sourceFileFingerprint"),
|
|
SqlParam<AZ::Uuid>(":dependencySourceGuid"),
|
|
SqlParam<AZ::u32>(":dependencySubId"),
|
|
SqlParam<const char*>(":missingDependencyString"),
|
|
SqlParam<const char*>(":lastScanTime"),
|
|
SqlParam<AZ::u64>(":scanTimeSecondsSinceEpoch"));
|
|
|
|
|
|
static const auto s_DeleteMissingProductDependencyByProductIdQuery = MakeSqlQuery(
|
|
DELETE_MISSING_PRODUCT_DEPENDENCY_BY_PRODUCTID,
|
|
DELETE_MISSING_PRODUCT_DEPENDENCY_BY_PRODUCTID_STATEMENT,
|
|
LOG_NAME,
|
|
SqlParam<AZ::s64>(":productpk"));
|
|
|
|
|
|
static const char* DELETE_AUTO_SUCCEED_JOBS = "AssetProcessor::DeleteAutoSucceedJobs";
|
|
static const char* DELETE_AUTO_SUCCEED_JOBS_STATEMENT =
|
|
"DELETE FROM Jobs WHERE JobKey LIKE 'CreateJobs_success_'";
|
|
|
|
static const char* CREATE_BUILDERINFO_TABLE = "AssetProcessor::CreateBuilderInfoTable";
|
|
static const char* CREATE_BUILDERINFO_TABLE_STATEMENT =
|
|
"CREATE TABLE IF NOT EXISTS BuilderInfo( "
|
|
" BuilderID INTEGER PRIMARY KEY AUTOINCREMENT, "
|
|
" Guid BLOB NOT NULL, "
|
|
" AnalysisFingerprint TEXT default('') collate nocase);";
|
|
|
|
static const char* CLEAR_BUILDERINFO_TABLE = "AssetProcessor::ClearBuilderInfoTable";
|
|
static const char* CLEAR_BUILDERINFO_TABLE_STATEMENT = "DELETE FROM BuilderInfo;";
|
|
|
|
static const char* INSERT_BUILDERINFO = "AssetProcessor::InsertBuilderInfo";
|
|
static const char* INSERT_BUILDERINFO_STATEMENT =
|
|
"INSERT INTO BuilderInfo (Guid, AnalysisFingerprint) "
|
|
"VALUES (:guid, :analysisFingerprint);";
|
|
static const auto s_InsertBuilderInfoQuery = MakeSqlQuery(INSERT_BUILDERINFO, INSERT_BUILDERINFO_STATEMENT, LOG_NAME,
|
|
SqlParam<AZ::Uuid>(":guid"),
|
|
SqlParam<const char*>(":analysisFingerprint"));
|
|
|
|
static const char* INSERT_COLUMN_ANALYSISFINGERPRINT = "AssetProcessor::AddColumnAnalysisFingerprint";
|
|
static const char* INSERT_COLUMN_ANALYSISFINGERPRINT_STATEMENT =
|
|
"ALTER TABLE Sources "
|
|
"ADD AnalysisFingerprint TEXT NOT NULL collate nocase default('');";
|
|
|
|
static const char* INSERT_COLUMN_SOURCEDEPENDENCY_TYPEOFDEPENDENCY = "AssetProcessor::AddSourceDependency_TypeOfDependency";
|
|
static const char* INSERT_COLUMN_SOURCEDEPENDENCY_TYPEOFDEPENDENCY_STATEMENT =
|
|
"ALTER TABLE SourceDependency "
|
|
"ADD TypeOfDependency INTEGER NOT NULL DEFAULT 0;";
|
|
|
|
static const char* INSERT_COLUMN_FILE_MODTIME = "AssetProcessor::AddFiles_ModTime";
|
|
static const char* INSERT_COLUMN_FILE_MODTIME_STATEMENT =
|
|
"ALTER TABLE Files "
|
|
"ADD ModTime INTEGER NOT NULL DEFAULT 0;";
|
|
|
|
static const char* INSERT_COLUMN_FILE_HASH = "AssetProcessor::AddFiles_Hash";
|
|
static const char* INSERT_COLUMN_FILE_HASH_STATEMENT =
|
|
"ALTER TABLE Files "
|
|
"ADD Hash INTEGER NOT NULL DEFAULT 0;";
|
|
|
|
static const char* INSERT_COLUMN_PRODUCTDEPENDENCY_UNRESOLVEDPATH = "AssetProcessor::AddProductDependency_UnresolvedPath";
|
|
static const char* INSERT_COLUMN_PRODUCTDEPENDENCY_UNRESOLVEDPATH_STATEMENT =
|
|
"ALTER TABLE ProductDependencies "
|
|
"ADD UnresolvedPath TEXT NOT NULL collate nocase default('');";
|
|
|
|
static const char* INSERT_COLUMN_PRODUCTDEPENDENCY_TYPEOFDEPENDENCY = "AssetProcessor::AddProductDependency_TypeOfDependency";
|
|
static const char* INSERT_COLUMN_PRODUCTDEPENDENCY_TYPEOFDEPENDENCY_STATEMENT =
|
|
"ALTER TABLE ProductDependencies "
|
|
"ADD UnresolvedDependencyType INTEGER NOT NULL DEFAULT 0;";
|
|
|
|
static const char* INSERT_COLUMN_PRODUCTDEPENDENCY_PLATFORM = "AssetProcessor::AddProductDependency_Platform";
|
|
static const char* INSERT_COLUMN_PRODUCTDEPENDENCY_PLATFORM_STATEMENT =
|
|
"ALTER TABLE ProductDependencies "
|
|
"ADD Platform TEXT NOT NULL collate nocase default('');";
|
|
|
|
static const char* INSERT_COLUMNS_JOB_WARNING_COUNT = "AssetProcessor::AddJobs_WarningCount";
|
|
static const char* INSERT_COLUMNS_JOB_WARNING_COUNT_STATEMENT =
|
|
"ALTER TABLE Jobs "
|
|
"ADD WarningCount INTEGER NOT NULL DEFAULT 0; "
|
|
;
|
|
|
|
static const char* INSERT_COLUMNS_JOB_ERROR_COUNT = "AssetProcessor::AddJobs_ErrorCount";
|
|
static const char* INSERT_COLUMNS_JOB_ERROR_COUNT_STATEMENT =
|
|
"ALTER TABLE Jobs "
|
|
"ADD ErrorCount INTEGER NOT NULL DEFAULT 0;"
|
|
;
|
|
|
|
static const char* INSERT_COLUMNS_SOURCEDEPENDENCY_FROM_ASSETID = "AssetProcessor::AddSourceDependencies_FromAssetId";
|
|
static const char* INSERT_COLUMNS_SOURCEDEPENDENCY_FROM_ASSETID_STATEMENT =
|
|
"ALTER TABLE SourceDependency "
|
|
"ADD FromAssetId INTEGER NOT NULL DEFAULT 0; "
|
|
;
|
|
|
|
static const char* INSERT_COLUMNS_PRODUCTDEPENDENCY_FROM_ASSETID = "AssetProcessor::AddProductDependencies_FromAssetId";
|
|
static const char* INSERT_COLUMNS_PRODUCTDEPENDENCY_FROM_ASSETID_STATEMENT =
|
|
"ALTER TABLE ProductDependencies "
|
|
"ADD FromAssetId INTEGER NOT NULL DEFAULT 0; "
|
|
;
|
|
|
|
static const char* INSERT_COLUMN_LAST_SCAN = "AssetProcessor::AddMissingProductDependencies_LastScanTime";
|
|
static const char* INSERT_COLUMN_LAST_SCAN_STATEMENT =
|
|
"ALTER TABLE MissingProductDependencies "
|
|
"ADD LastScanTime TEXT;";
|
|
|
|
static const char* INSERT_COLUMN_SCAN_TIME_SECONDS_SINCE_EPOCH = "AssetProcessor::AddMissingProductDependencies_ScanTimeSecondsSinceEpoch";
|
|
static const char* INSERT_COLUMN_SCAN_TIME_SECONDS_SINCE_EPOCH_STATEMENT =
|
|
"ALTER TABLE MissingProductDependencies "
|
|
"ADD ScanTimeSecondsSinceEpoch INTEGER;";
|
|
|
|
static const char* INSERT_FILE = "AssetProcessor::InsertFile";
|
|
static const char* INSERT_FILE_STATEMENT =
|
|
"INSERT INTO Files (ScanFolderPK, FileName, IsFolder, ModTime, Hash) "
|
|
"VALUES (:scanfolderpk, :filename, :isfolder, :modtime, :hash);";
|
|
static const auto s_InsertFileQuery = MakeSqlQuery(INSERT_FILE, INSERT_FILE_STATEMENT, LOG_NAME,
|
|
SqlParam<AZ::s64>(":scanfolderpk"),
|
|
SqlParam<const char*>(":filename"),
|
|
SqlParam<AZ::s64>(":isfolder"),
|
|
SqlParam<AZ::u64>(":modtime"),
|
|
SqlParam<AZ::u64>(":hash"));
|
|
|
|
static const char* UPDATE_FILE = "AssetProcessor::UpdateFile";
|
|
static const char* UPDATE_FILE_STATEMENT =
|
|
"UPDATE Files SET "
|
|
"ScanFolderPK = :scanfolderpk, "
|
|
"FileName = :filename, "
|
|
"IsFolder = :isfolder, "
|
|
"ModTime = :modtime, "
|
|
"Hash = :hash "
|
|
"WHERE FileID = :fileid;";
|
|
static const auto s_UpdateFileQuery = MakeSqlQuery(UPDATE_FILE, UPDATE_FILE_STATEMENT, LOG_NAME,
|
|
SqlParam<AZ::s64>(":scanfolderpk"),
|
|
SqlParam<const char*>(":filename"),
|
|
SqlParam<AZ::s64>(":isfolder"),
|
|
SqlParam<AZ::u64>(":modtime"),
|
|
SqlParam<AZ::u64>(":hash"),
|
|
SqlParam<AZ::s64>(":fileid"));
|
|
|
|
static const char* UPDATE_FILE_MODTIME_AND_HASH_BY_FILENAME_SCANFOLDER_ID = "AssetProcessor::UpdateFileModtimeAndHashByFileNameScanFolderId";
|
|
static const char* UPDATE_FILE_MODTIME_AND_HASH_BY_FILENAME_SCANFOLDER_ID_STATEMENT =
|
|
"UPDATE Files SET "
|
|
"ModTime = :modtime, "
|
|
"Hash = :hash "
|
|
"WHERE FileName = :filename "
|
|
"AND ScanFolderPK = :scanfolderpk;";
|
|
static const auto s_UpdateFileModtimeByFileNameScanFolderIdQuery = MakeSqlQuery(UPDATE_FILE_MODTIME_AND_HASH_BY_FILENAME_SCANFOLDER_ID, UPDATE_FILE_MODTIME_AND_HASH_BY_FILENAME_SCANFOLDER_ID_STATEMENT, LOG_NAME,
|
|
SqlParam<AZ::u64>(":modtime"),
|
|
SqlParam<AZ::u64>(":hash"),
|
|
SqlParam<const char*>(":filename"),
|
|
SqlParam<AZ::s64>(":scanfolderpk"));
|
|
|
|
static const char* DELETE_FILE = "AssetProcessor::DeleteFile";
|
|
static const char* DELETE_FILE_STATEMENT =
|
|
"DELETE FROM Files WHERE "
|
|
"FileID = :fileid;";
|
|
static const auto s_DeleteFileQuery = MakeSqlQuery(DELETE_FILE, DELETE_FILE_STATEMENT, LOG_NAME,
|
|
SqlParam<AZ::s64>(":fileid"));
|
|
}
|
|
|
|
AssetDatabaseConnection::AssetDatabaseConnection()
|
|
{
|
|
qRegisterMetaType<ScanFolderDatabaseEntry>("ScanFolderEntry");
|
|
qRegisterMetaType<SourceDatabaseEntry>("SourceEntry");
|
|
qRegisterMetaType<JobDatabaseEntry>("JobDatabaseEntry");
|
|
qRegisterMetaType<ProductDatabaseEntry>("ProductEntry");
|
|
qRegisterMetaType<CombinedDatabaseEntry>("CombinedEntry");
|
|
qRegisterMetaType<SourceDatabaseEntryContainer>("SourceEntryContainer");
|
|
qRegisterMetaType<JobDatabaseEntryContainer>("JobDatabaseEntryContainer");
|
|
qRegisterMetaType<ProductDatabaseEntryContainer>("ProductEntryContainer");
|
|
qRegisterMetaType<CombinedDatabaseEntryContainer>("CombinedEntryContainer");
|
|
}
|
|
|
|
AssetDatabaseConnection::~AssetDatabaseConnection()
|
|
{
|
|
CloseDatabase();
|
|
}
|
|
|
|
bool AssetDatabaseConnection::DataExists()
|
|
{
|
|
AZStd::string dbFilePath = GetAssetDatabaseFilePath();
|
|
return AZ::IO::SystemFile::Exists(dbFilePath.c_str());
|
|
}
|
|
|
|
void AssetDatabaseConnection::LoadData()
|
|
{
|
|
if ((!m_databaseConnection) || (!m_databaseConnection->IsOpen()))
|
|
{
|
|
OpenDatabase();
|
|
}
|
|
}
|
|
|
|
void AssetDatabaseConnection::ClearData()
|
|
{
|
|
if ((m_databaseConnection) && (m_databaseConnection->IsOpen()))
|
|
{
|
|
CloseDatabase();
|
|
}
|
|
AZStd::string dbFilePath = GetAssetDatabaseFilePath();
|
|
AZ::IO::SystemFile::Delete(dbFilePath.c_str());
|
|
OpenDatabase();
|
|
}
|
|
|
|
|
|
bool AssetDatabaseConnection::PostOpenDatabase()
|
|
{
|
|
DatabaseVersion foundVersion = DatabaseVersion::DatabaseDoesNotExist;
|
|
|
|
if (m_databaseConnection->DoesTableExist("dbinfo"))
|
|
{
|
|
foundVersion = QueryDatabaseVersion();
|
|
}
|
|
bool dropAllTables = true;
|
|
|
|
// if its a future version, we don't want to drop tables and blow up, we'd rather just inform the user, and move on:
|
|
if (foundVersion > CurrentDatabaseVersion())
|
|
{
|
|
AZ_Error(AssetProcessor::ConsoleChannel, false,
|
|
"The database in the Cache folder appears to be from a NEWER version of Asset Processor than this one.\n"
|
|
"To prevent loss of data in the cache for the newer version, this Asset Processor will close.\n");
|
|
return false;
|
|
}
|
|
|
|
if (foundVersion == DatabaseVersion::AddedOutputPrefixToScanFolders)
|
|
{
|
|
// execute statements to upgrade the database
|
|
if (m_databaseConnection->ExecuteOneOffStatement(CREATEINDEX_JOBS_JOBKEY))
|
|
{
|
|
foundVersion = DatabaseVersion::AddedJobKeyIndex;
|
|
AZ_TracePrintf(AssetProcessor::ConsoleChannel, "Upgraded Asset Database to version %i (AddedJobKeyIndex)\n", foundVersion)
|
|
}
|
|
}
|
|
|
|
// over here, check the version number, and perform upgrading if you need to
|
|
if (foundVersion == DatabaseVersion::AddedJobKeyIndex)
|
|
{
|
|
if (
|
|
(m_databaseConnection->ExecuteOneOffStatement(CREATEINDEX_SOURCE_GUID)) &&
|
|
(m_databaseConnection->ExecuteOneOffStatement(CREATEINDEX_SCANFOLDERS_SOURCES_SCANFOLDER))
|
|
)
|
|
{
|
|
foundVersion = DatabaseVersion::AddedSourceGuidIndex;
|
|
AZ_TracePrintf(AssetProcessor::ConsoleChannel, "Upgraded Asset Database to version %i (AddedSourceGuidIndex)\n", foundVersion)
|
|
}
|
|
}
|
|
|
|
if (foundVersion == DatabaseVersion::AddedSourceGuidIndex)
|
|
{
|
|
if (
|
|
(m_databaseConnection->ExecuteOneOffStatement(CREATE_SOURCE_DEPENDENCY_TABLE)) &&
|
|
(m_databaseConnection->ExecuteOneOffStatement(CREATEINDEX_DEPENDSONSOURCE_SOURCEDEPENDENCY)) &&
|
|
(m_databaseConnection->ExecuteOneOffStatement(CREATEINDEX_BUILDERGUID_SOURCE_SOURCEDEPENDENCY))
|
|
)
|
|
{
|
|
foundVersion = DatabaseVersion::AddedSourceDependencyTable;
|
|
AZ_TracePrintf(AssetProcessor::ConsoleChannel, "Upgraded Asset Database to version %i (AddedSourceDependencyTable)\n", foundVersion)
|
|
}
|
|
}
|
|
|
|
if (foundVersion == DatabaseVersion::AddedSourceDependencyTable)
|
|
{
|
|
// add the missing tables - nothing will have generated data for this before this point, so its okay to just make empty ones.
|
|
if (
|
|
(m_databaseConnection->ExecuteOneOffStatement(CREATE_LEGACYSUBIDS_TABLE)) &&
|
|
(m_databaseConnection->ExecuteOneOffStatement(CREATEINDEX_LEGACYSUBIDS_PRODUCTPK))
|
|
)
|
|
{
|
|
foundVersion = DatabaseVersion::AddedLegacySubIDsTable;
|
|
AZ_TracePrintf(AssetProcessor::ConsoleChannel, "Upgraded Asset Database to version %i (AddedLegacySubIDsTable)\n", foundVersion)
|
|
}
|
|
}
|
|
|
|
if (foundVersion == DatabaseVersion::AddedLegacySubIDsTable)
|
|
{
|
|
if (m_databaseConnection->ExecuteOneOffStatement(CREATE_PRODUCT_DEPENDENCY_TABLE))
|
|
{
|
|
foundVersion = DatabaseVersion::AddedProductDependencyTable;
|
|
AZ_TracePrintf(AssetProcessor::ConsoleChannel, "Upgraded Asset Database to version %i (AddedProductDependencyTable)\n", foundVersion)
|
|
}
|
|
}
|
|
|
|
if (foundVersion == DatabaseVersion::AddedProductDependencyTable)
|
|
{
|
|
if (m_databaseConnection->ExecuteOneOffStatement(DELETE_AUTO_SUCCEED_JOBS))
|
|
{
|
|
foundVersion = DatabaseVersion::ClearAutoSucceedJobs;
|
|
AZ_TracePrintf(AssetProcessor::ConsoleChannel, "Upgraded Asset Database to version %i (ClearAutoSucceedJobs)\n", foundVersion)
|
|
}
|
|
}
|
|
|
|
if (foundVersion == DatabaseVersion::ClearAutoSucceedJobs)
|
|
{
|
|
if (m_databaseConnection->ExecuteOneOffStatement(CREATE_FILES_TABLE))
|
|
{
|
|
foundVersion = DatabaseVersion::AddedFilesTable;
|
|
AZ_TracePrintf(AssetProcessor::ConsoleChannel, "Upgraded Asset Database to version %i (AddedFilesTable)\n", foundVersion)
|
|
}
|
|
}
|
|
|
|
if (foundVersion == DatabaseVersion::AddedFilesTable)
|
|
{
|
|
if ((m_databaseConnection->ExecuteOneOffStatement(INSERT_COLUMN_ANALYSISFINGERPRINT))&&
|
|
(m_databaseConnection->ExecuteOneOffStatement(CREATE_BUILDERINFO_TABLE)))
|
|
{
|
|
foundVersion = DatabaseVersion::AddedAnalysisFingerprint;
|
|
AZ_TracePrintf(AssetProcessor::ConsoleChannel, "Upgraded Asset Database to version %i (AddedAnalysisFingerprint)\n", foundVersion)
|
|
}
|
|
}
|
|
|
|
if (foundVersion == DatabaseVersion::AddedAnalysisFingerprint)
|
|
{
|
|
if (m_databaseConnection->ExecuteOneOffStatement(INSERT_COLUMN_SOURCEDEPENDENCY_TYPEOFDEPENDENCY))
|
|
{
|
|
foundVersion = DatabaseVersion::AddedSourceDependencyType;
|
|
AZ_TracePrintf(AssetProcessor::ConsoleChannel, "Upgraded Asset Database to version %i (AddedSourceDependencyType)\n", foundVersion)
|
|
}
|
|
}
|
|
|
|
if (foundVersion == AssetDatabase::DatabaseVersion::AddedSourceDependencyType)
|
|
{
|
|
if (m_databaseConnection->ExecuteOneOffStatement(INSERT_COLUMN_FILE_MODTIME))
|
|
{
|
|
foundVersion = DatabaseVersion::AddedFileModTimes;
|
|
AZ_TracePrintf(AssetProcessor::ConsoleChannel, "Upgraded Asset Database to version %i (AddedFileModTimes)\n", foundVersion)
|
|
}
|
|
}
|
|
|
|
if (foundVersion == AssetDatabase::DatabaseVersion::AddedFileModTimes)
|
|
{
|
|
if (m_databaseConnection->ExecuteOneOffStatement(INSERT_COLUMN_PRODUCTDEPENDENCY_UNRESOLVEDPATH))
|
|
{
|
|
foundVersion = DatabaseVersion::AddedUnresolvedDependencyField;
|
|
AZ_TracePrintf(AssetProcessor::ConsoleChannel, "Upgraded Asset Database to version %i (AddedUnresolvedDependencyField)\n", foundVersion)
|
|
}
|
|
}
|
|
|
|
if (foundVersion == AssetDatabase::DatabaseVersion::AddedUnresolvedDependencyField)
|
|
{
|
|
if (m_databaseConnection->ExecuteOneOffStatement(INSERT_COLUMN_PRODUCTDEPENDENCY_TYPEOFDEPENDENCY))
|
|
{
|
|
foundVersion = DatabaseVersion::AddedUnresolvedDependencyTypeField;
|
|
AZ_TracePrintf(AssetProcessor::ConsoleChannel, "Upgraded Asset Database to version %i (AddedUnresolvedDependencyTypeField)\n", foundVersion)
|
|
}
|
|
}
|
|
|
|
if (foundVersion == AssetDatabase::DatabaseVersion::AddedUnresolvedDependencyTypeField)
|
|
{
|
|
if (m_databaseConnection->ExecuteOneOffStatement(CREATEINDEX_TYPEOFDEPENDENCY_SOURCEDEPENDENCY))
|
|
{
|
|
foundVersion = DatabaseVersion::AddedTypeOfDependencyIndex;
|
|
AZ_TracePrintf(AssetProcessor::ConsoleChannel, "Upgraded Asset Database to version %i (AddedTypeOfDependencyIndex)\n", foundVersion)
|
|
}
|
|
}
|
|
|
|
if (foundVersion == AssetDatabase::DatabaseVersion::AddedTypeOfDependencyIndex)
|
|
{
|
|
if (m_databaseConnection->ExecuteOneOffStatement(INSERT_COLUMN_PRODUCTDEPENDENCY_PLATFORM))
|
|
{
|
|
foundVersion = DatabaseVersion::AddedProductDependencyPlatform;
|
|
AZ_TracePrintf(AssetProcessor::ConsoleChannel, "Upgraded Asset Database to version %i (AddedProductDependencyPlatform)\n", foundVersion)
|
|
}
|
|
}
|
|
|
|
if (foundVersion == DatabaseVersion::AddedProductDependencyPlatform)
|
|
{
|
|
if (m_databaseConnection->ExecuteOneOffStatement(CREATE_MISSING_PRODUCT_DEPENDENCY_TABLE))
|
|
{
|
|
foundVersion = DatabaseVersion::AddedMissingProductDependencyTable;
|
|
AZ_TracePrintf(AssetProcessor::ConsoleChannel, "Upgraded Asset Database to version %i (AddedMissingProductDependencyTable)\n", foundVersion)
|
|
}
|
|
}
|
|
|
|
if (foundVersion == DatabaseVersion::AddedMissingProductDependencyTable)
|
|
{
|
|
if (m_databaseConnection->ExecuteOneOffStatement(INSERT_COLUMNS_JOB_WARNING_COUNT) &&
|
|
m_databaseConnection->ExecuteOneOffStatement(INSERT_COLUMNS_JOB_ERROR_COUNT))
|
|
{
|
|
foundVersion = DatabaseVersion::AddedWarningAndErrorCountToJobs;
|
|
AZ_TracePrintf(AssetProcessor::ConsoleChannel, "Upgraded Asset Database to version %i (AddedWarningAndErrorCountToJobs)\n", foundVersion)
|
|
}
|
|
}
|
|
|
|
if (foundVersion == DatabaseVersion::AddedWarningAndErrorCountToJobs)
|
|
{
|
|
if (m_databaseConnection->ExecuteOneOffStatement(INSERT_COLUMNS_SOURCEDEPENDENCY_FROM_ASSETID) &&
|
|
m_databaseConnection->ExecuteOneOffStatement(INSERT_COLUMNS_PRODUCTDEPENDENCY_FROM_ASSETID))
|
|
{
|
|
foundVersion = DatabaseVersion::AddedFromAssetIdField;
|
|
AZ_TracePrintf(AssetProcessor::ConsoleChannel, "Upgraded Asset Database to version %i (AddedFromAssetIdField)\n", foundVersion)
|
|
}
|
|
}
|
|
|
|
if (foundVersion == DatabaseVersion::AddedFromAssetIdField)
|
|
{
|
|
if (m_databaseConnection->ExecuteOneOffStatement(CREATEINDEX_PRODUCTDEPENDENCIES_UNRESOLVEDPATH) &&
|
|
m_databaseConnection->ExecuteOneOffStatement(CREATEINDEX_PRODUCTDEPENDENCIES_UNRESOLVEDPATH_WILDCARD))
|
|
{
|
|
foundVersion = DatabaseVersion::AddedProductDependencyIndexes;
|
|
AZ_TracePrintf(AssetProcessor::ConsoleChannel, "Upgraded Asset Database to version %i (AddedProductDependencyIndexes)\n", foundVersion)
|
|
}
|
|
}
|
|
|
|
if (foundVersion == AssetDatabase::DatabaseVersion::AddedProductDependencyIndexes)
|
|
{
|
|
if (m_databaseConnection->ExecuteOneOffStatement(INSERT_COLUMN_FILE_HASH))
|
|
{
|
|
foundVersion = DatabaseVersion::AddedFileHashField;
|
|
AZ_TracePrintf(AssetProcessor::ConsoleChannel, "Upgraded Asset Database to version %i (AddedFileHashField)\n", foundVersion)
|
|
}
|
|
}
|
|
|
|
if (foundVersion == AssetDatabase::DatabaseVersion::AddedFileHashField)
|
|
{
|
|
if (m_databaseConnection->ExecuteOneOffStatement(INSERT_COLUMN_LAST_SCAN))
|
|
{
|
|
foundVersion = DatabaseVersion::AddedLastScanTimeField;
|
|
AZ_TracePrintf(AssetProcessor::ConsoleChannel, "Upgraded Asset Database to version %i (AddedLastScanTimeField)\n", foundVersion)
|
|
}
|
|
}
|
|
|
|
if (foundVersion == AssetDatabase::DatabaseVersion::AddedLastScanTimeField)
|
|
{
|
|
if (m_databaseConnection->ExecuteOneOffStatement(INSERT_COLUMN_SCAN_TIME_SECONDS_SINCE_EPOCH))
|
|
{
|
|
foundVersion = DatabaseVersion::AddedScanTimeSecondsSinceEpochField;
|
|
AZ_TracePrintf(AssetProcessor::ConsoleChannel, "Upgraded Asset Database to version %i (AddedScanTimeSecondsSinceEpochField)\n", foundVersion)
|
|
}
|
|
}
|
|
|
|
// Nothing to do for version `AssetDatabase::DatabaseVersion::RemoveOutputPrefixFromScanFolders`
|
|
// sqlite doesn't not support altering a table to remove a column
|
|
// This is fine as the extra OutputPrefix column will not be queried
|
|
|
|
if (foundVersion == CurrentDatabaseVersion())
|
|
{
|
|
dropAllTables = false;
|
|
}
|
|
else
|
|
{
|
|
AZ_TracePrintf(AssetProcessor::ConsoleChannel, "Asset Database must be cleared (hasVersion: %i currentVersion: %i)\n", foundVersion, CurrentDatabaseVersion())
|
|
dropAllTables = true;
|
|
}
|
|
|
|
// example, if you know how to get from version 1 to version 2, and we're on version 1 and should be on version 2,
|
|
// we can either drop all tables and recreate them, or we can write statements which upgrade the database.
|
|
// if you know how to upgrade, write your modify statements here, then set dropAllTables to false.
|
|
// otherwise it will re-create from scratch.
|
|
|
|
if (dropAllTables)
|
|
{
|
|
// drop all tables by destroying the entire database.
|
|
m_databaseConnection->Close();
|
|
|
|
AZStd::string dbFilePath = GetAssetDatabaseFilePath();
|
|
if (dbFilePath != ":memory:")
|
|
{
|
|
// you cannot delete a memory database, but it drops all data when you close it anyway.
|
|
if (!AZ::IO::SystemFile::Delete(dbFilePath.c_str()))
|
|
{
|
|
delete m_databaseConnection;
|
|
m_databaseConnection = nullptr;
|
|
AZ_Error(LOG_NAME, false, "Unable to clear the asset database at %s\n", dbFilePath.c_str());
|
|
return false;
|
|
}
|
|
}
|
|
|
|
if (!m_databaseConnection->Open(dbFilePath, IsReadOnly()))
|
|
{
|
|
delete m_databaseConnection;
|
|
m_databaseConnection = nullptr;
|
|
AZ_Error(LOG_NAME, false, "Unable to open the asset database at %s\n", dbFilePath.c_str());
|
|
return false;
|
|
}
|
|
|
|
AZ_TracePrintf(AssetProcessor::ConsoleChannel, "Asset Database has been cleared.\n")
|
|
CreateStatements();
|
|
ExecuteCreateStatements();
|
|
}
|
|
|
|
// now that the database matches the schema, update it:
|
|
SetDatabaseVersion(CurrentDatabaseVersion());
|
|
|
|
return AzToolsFramework::AssetDatabase::AssetDatabaseConnection::PostOpenDatabase();
|
|
}
|
|
|
|
|
|
void AssetDatabaseConnection::ExecuteCreateStatements()
|
|
{
|
|
AZ_Assert(m_databaseConnection, "No connection!");
|
|
for (const auto& element : m_createStatements)
|
|
{
|
|
m_databaseConnection->ExecuteOneOffStatement(element.c_str());
|
|
}
|
|
}
|
|
|
|
void AssetDatabaseConnection::SetDatabaseVersion(DatabaseVersion ver)
|
|
{
|
|
AZ_Error(LOG_NAME, m_databaseConnection, "Fatal: attempt to work on a database connection that doesn't exist");
|
|
AZ_Error(LOG_NAME, m_databaseConnection->IsOpen(), "Fatal: attempt to work on a database connection that isn't open");
|
|
AZ_Error(LOG_NAME, m_databaseConnection->DoesTableExist("dbinfo"), "Fatal: dbinfo table does not exist");
|
|
|
|
StatementAutoFinalizer autoFinal;
|
|
// note that BindAndStep outputs errors if it fails, no need to ouput them here.
|
|
s_SetDatabaseVersionQuery.BindAndStep(*m_databaseConnection, static_cast<int>(ver));
|
|
}
|
|
|
|
void AssetDatabaseConnection::CreateStatements()
|
|
{
|
|
AZ_Assert(m_databaseConnection, "No connection!");
|
|
AZ_Assert(m_databaseConnection->IsOpen(), "Connection is not open");
|
|
|
|
AzToolsFramework::AssetDatabase::AssetDatabaseConnection::CreateStatements();
|
|
|
|
// ---------------------------------------------------------------------------------------------
|
|
// Housekeeping
|
|
// ---------------------------------------------------------------------------------------------
|
|
m_databaseConnection->AddStatement("VACUUM", "VACUUM");
|
|
m_databaseConnection->AddStatement("ANALYZE", "ANALYZE");
|
|
|
|
// ---------------------------------------------------------------------------------------------
|
|
// Database Info table
|
|
// ----------------------------------------------------------------------------------------------
|
|
m_databaseConnection->AddStatement(CREATE_DATABASE_INFOTABLE, CREATE_DATABASE_INFOTABLE_STATEMENT);
|
|
m_createStatements.push_back(CREATE_DATABASE_INFOTABLE);
|
|
|
|
AddStatement(m_databaseConnection, s_SetDatabaseVersionQuery);
|
|
|
|
// ----------------------------------------------------------------------------------------------
|
|
// ScanFolders table
|
|
// ----------------------------------------------------------------------------------------------
|
|
m_databaseConnection->AddStatement(CREATE_SCANFOLDERS_TABLE, CREATE_SCANFOLDERS_TABLE_STATEMENT);
|
|
m_createStatements.push_back(CREATE_SCANFOLDERS_TABLE);
|
|
|
|
AddStatement(m_databaseConnection, s_InsertScanfolderQuery);
|
|
AddStatement(m_databaseConnection, s_UpdateScanfolderQuery);
|
|
AddStatement(m_databaseConnection, s_DeleteScanfolderQuery);
|
|
AddStatement(m_databaseConnection, s_DeleteSourceByScanfolderidQuery);
|
|
|
|
// ---------------------------------------------------------------------------------------------
|
|
// Source table
|
|
// ---------------------------------------------------------------------------------------------
|
|
m_databaseConnection->AddStatement(CREATE_SOURCES_TABLE, CREATE_SOURCES_TABLE_STATEMENT);
|
|
m_createStatements.push_back(CREATE_SOURCES_TABLE);
|
|
|
|
AddStatement(m_databaseConnection, s_InsertSourceQuery);
|
|
AddStatement(m_databaseConnection, s_UpdateSourceQuery);
|
|
AddStatement(m_databaseConnection, s_DeleteSourceQuery);
|
|
m_databaseConnection->AddStatement(INVALIDATE_SOURCE_ANALYSISFINGEPRINTS, INVALIDATE_SOURCE_ANALYSISFINGEPRINTS_STATEMENT);
|
|
|
|
// ---------------------------------------------------------------------------------------------
|
|
// Jobs table
|
|
// ---------------------------------------------------------------------------------------------
|
|
m_databaseConnection->AddStatement(CREATE_JOBS_TABLE, CREATE_JOBS_TABLE_STATEMENT);
|
|
m_databaseConnection->AddStatement(INSERT_COLUMNS_JOB_WARNING_COUNT, INSERT_COLUMNS_JOB_WARNING_COUNT_STATEMENT);
|
|
m_databaseConnection->AddStatement(INSERT_COLUMNS_JOB_ERROR_COUNT, INSERT_COLUMNS_JOB_ERROR_COUNT_STATEMENT);
|
|
m_createStatements.push_back(CREATE_JOBS_TABLE);
|
|
|
|
AddStatement(m_databaseConnection, s_GetHighestJobrunkeyQuery);
|
|
AddStatement(m_databaseConnection, s_InsertJobQuery);
|
|
AddStatement(m_databaseConnection, s_UpdateJobQuery);
|
|
AddStatement(m_databaseConnection, s_DeleteJobQuery);
|
|
|
|
// ---------------------------------------------------------------------------------------------
|
|
// Builder Info Table
|
|
// ---------------------------------------------------------------------------------------------
|
|
m_databaseConnection->AddStatement(INSERT_COLUMN_ANALYSISFINGERPRINT, INSERT_COLUMN_ANALYSISFINGERPRINT_STATEMENT);
|
|
m_databaseConnection->AddStatement(CREATE_BUILDERINFO_TABLE, CREATE_BUILDERINFO_TABLE_STATEMENT);
|
|
m_databaseConnection->AddStatement(CLEAR_BUILDERINFO_TABLE, CLEAR_BUILDERINFO_TABLE_STATEMENT);
|
|
m_databaseConnection->AddStatement(INSERT_BUILDERINFO, INSERT_BUILDERINFO_STATEMENT);
|
|
m_createStatements.push_back(CREATE_BUILDERINFO_TABLE);
|
|
|
|
// ---------------------------------------------------------------------------------------------
|
|
// Products table
|
|
// ---------------------------------------------------------------------------------------------
|
|
m_databaseConnection->AddStatement(CREATE_PRODUCT_TABLE, CREATE_PRODUCT_TABLE_STATEMENT);
|
|
m_createStatements.push_back(CREATE_PRODUCT_TABLE);
|
|
|
|
AddStatement(m_databaseConnection, s_InsertProductQuery);
|
|
AddStatement(m_databaseConnection, s_UpdateProductQuery);
|
|
AddStatement(m_databaseConnection, s_DeleteProductQuery);
|
|
AddStatement(m_databaseConnection, s_DeleteProductsByJobidQuery);
|
|
AddStatement(m_databaseConnection, s_DeleteProductsBySourceidQuery);
|
|
AddStatement(m_databaseConnection, s_DeleteProductsBySourceidPlatformQuery);
|
|
|
|
// ---------------------------------------------------------------------------------------------
|
|
// Source Dependency table
|
|
// ---------------------------------------------------------------------------------------------
|
|
m_databaseConnection->AddStatement(CREATE_SOURCE_DEPENDENCY_TABLE, CREATE_SOURCE_DEPENDENCY_TABLE_STATEMENT);
|
|
m_databaseConnection->AddStatement(INSERT_COLUMN_SOURCEDEPENDENCY_TYPEOFDEPENDENCY, INSERT_COLUMN_SOURCEDEPENDENCY_TYPEOFDEPENDENCY_STATEMENT);
|
|
m_databaseConnection->AddStatement(INSERT_COLUMNS_SOURCEDEPENDENCY_FROM_ASSETID, INSERT_COLUMNS_SOURCEDEPENDENCY_FROM_ASSETID_STATEMENT);
|
|
|
|
m_createStatements.push_back(CREATE_SOURCE_DEPENDENCY_TABLE);
|
|
|
|
AddStatement(m_databaseConnection, s_InsertSourceDependencyQuery);
|
|
AddStatement(m_databaseConnection, s_DeleteSourceDependencySourcedependencyidQuery);
|
|
|
|
|
|
// ---------------------------------------------------------------------------------------------
|
|
// Legacy SubIDs table
|
|
// ---------------------------------------------------------------------------------------------
|
|
m_databaseConnection->AddStatement(CREATE_LEGACYSUBIDS_TABLE, CREATE_LEGACYSUBIDS_TABLE_STATEMENT);
|
|
m_databaseConnection->AddStatement(CREATEINDEX_LEGACYSUBIDS_PRODUCTPK, CREATEINDEX_LEGACYSUBIDS_PRODUCTPK_STATEMENT);
|
|
|
|
m_createStatements.push_back(CREATE_LEGACYSUBIDS_TABLE);
|
|
m_createStatements.push_back(CREATEINDEX_LEGACYSUBIDS_PRODUCTPK);
|
|
|
|
AddStatement(m_databaseConnection, s_InsertNewLegacysubidQuery);
|
|
AddStatement(m_databaseConnection, s_OverwriteExistingLegacysubidQuery);
|
|
AddStatement(m_databaseConnection, s_DeleteLegacysubidsByPrimaryKeyQuery);
|
|
AddStatement(m_databaseConnection, s_DeleteLegacysubidsByProductidQuery);
|
|
|
|
// ---------------------------------------------------------------------------------------------
|
|
// Product Dependency table
|
|
// ---------------------------------------------------------------------------------------------
|
|
m_databaseConnection->AddStatement(CREATE_PRODUCT_DEPENDENCY_TABLE, CREATE_PRODUCT_DEPENDENCY_TABLE_STATEMENT);
|
|
m_databaseConnection->AddStatement(INSERT_COLUMN_PRODUCTDEPENDENCY_UNRESOLVEDPATH, INSERT_COLUMN_PRODUCTDEPENDENCY_UNRESOLVEDPATH_STATEMENT);
|
|
m_databaseConnection->AddStatement(INSERT_COLUMN_PRODUCTDEPENDENCY_TYPEOFDEPENDENCY, INSERT_COLUMN_PRODUCTDEPENDENCY_TYPEOFDEPENDENCY_STATEMENT);
|
|
m_databaseConnection->AddStatement(INSERT_COLUMN_PRODUCTDEPENDENCY_PLATFORM, INSERT_COLUMN_PRODUCTDEPENDENCY_PLATFORM_STATEMENT);
|
|
m_databaseConnection->AddStatement(INSERT_COLUMNS_PRODUCTDEPENDENCY_FROM_ASSETID, INSERT_COLUMNS_PRODUCTDEPENDENCY_FROM_ASSETID_STATEMENT);
|
|
|
|
m_createStatements.push_back(CREATE_PRODUCT_DEPENDENCY_TABLE);
|
|
|
|
AddStatement(m_databaseConnection, s_InsertProductDependencyQuery);
|
|
AddStatement(m_databaseConnection, s_UpdateProductDependencyQuery);
|
|
AddStatement(m_databaseConnection, s_DeleteProductDependencyByProductIdQuery);
|
|
|
|
// ---------------------------------------------------------------------------------------------
|
|
// Missing Product Dependency table
|
|
// ---------------------------------------------------------------------------------------------
|
|
m_databaseConnection->AddStatement(CREATE_MISSING_PRODUCT_DEPENDENCY_TABLE, CREATE_MISSING_PRODUCT_DEPENDENCY_TABLE_STATEMENT);
|
|
|
|
m_createStatements.push_back(CREATE_MISSING_PRODUCT_DEPENDENCY_TABLE);
|
|
|
|
AddStatement(m_databaseConnection, s_InsertMissingProductDependencyQuery);
|
|
AddStatement(m_databaseConnection, s_UpdateMissingProductDependencyQuery);
|
|
AddStatement(m_databaseConnection, s_DeleteMissingProductDependencyByProductIdQuery);
|
|
|
|
// ---------------------------------------------------------------------------------------------
|
|
// Files table
|
|
// ---------------------------------------------------------------------------------------------
|
|
m_databaseConnection->AddStatement(CREATE_FILES_TABLE, CREATE_FILES_TABLE_STATEMENT);
|
|
m_createStatements.push_back(CREATE_FILES_TABLE);
|
|
|
|
m_databaseConnection->AddStatement(INSERT_FILE, INSERT_FILE_STATEMENT);
|
|
m_databaseConnection->AddStatement(UPDATE_FILE, UPDATE_FILE_STATEMENT);
|
|
m_databaseConnection->AddStatement(UPDATE_FILE_MODTIME_AND_HASH_BY_FILENAME_SCANFOLDER_ID, UPDATE_FILE_MODTIME_AND_HASH_BY_FILENAME_SCANFOLDER_ID_STATEMENT);
|
|
m_databaseConnection->AddStatement(DELETE_FILE, DELETE_FILE_STATEMENT);
|
|
m_databaseConnection->AddStatement(INSERT_COLUMN_FILE_MODTIME, INSERT_COLUMN_FILE_MODTIME_STATEMENT);
|
|
m_databaseConnection->AddStatement(INSERT_COLUMN_FILE_HASH, INSERT_COLUMN_FILE_HASH_STATEMENT);
|
|
m_databaseConnection->AddStatement(INSERT_COLUMN_LAST_SCAN, INSERT_COLUMN_LAST_SCAN_STATEMENT);
|
|
m_databaseConnection->AddStatement(INSERT_COLUMN_SCAN_TIME_SECONDS_SINCE_EPOCH, INSERT_COLUMN_SCAN_TIME_SECONDS_SINCE_EPOCH_STATEMENT);
|
|
// ---------------------------------------------------------------------------------------------
|
|
// Indices
|
|
// ---------------------------------------------------------------------------------------------
|
|
m_databaseConnection->AddStatement(CREATEINDEX_DEPENDSONSOURCE_SOURCEDEPENDENCY, CREATEINDEX_DEPENDSONSOURCE_SOURCEDEPENDENCY_STATEMENT);
|
|
m_createStatements.push_back(CREATEINDEX_DEPENDSONSOURCE_SOURCEDEPENDENCY);
|
|
|
|
m_databaseConnection->AddStatement(CREATEINDEX_BUILDERGUID_SOURCE_SOURCEDEPENDENCY, CREATEINDEX_BUILDERGUID_SOURCE_SOURCEDEPENDENCY_STATEMENT);
|
|
m_createStatements.push_back(CREATEINDEX_BUILDERGUID_SOURCE_SOURCEDEPENDENCY);
|
|
|
|
m_databaseConnection->AddStatement(CREATEINDEX_TYPEOFDEPENDENCY_SOURCEDEPENDENCY, CREATEINDEX_TYPEOFDEPENDENCY_SOURCEDEPENDENCY_STATEMENT);
|
|
m_createStatements.push_back(CREATEINDEX_TYPEOFDEPENDENCY_SOURCEDEPENDENCY);
|
|
|
|
m_databaseConnection->AddStatement(CREATEINDEX_SCANFOLDERS_SOURCES_SCANFOLDER, CREATEINDEX_SCANFOLDERS_SOURCES_SCANFOLDER_STATEMENT);
|
|
m_createStatements.push_back(CREATEINDEX_SCANFOLDERS_SOURCES_SCANFOLDER);
|
|
|
|
m_databaseConnection->AddStatement(CREATEINDEX_SOURCES_JOBS, CREATEINDEX_SOURCES_JOBS_STATEMENT);
|
|
m_createStatements.push_back(CREATEINDEX_SOURCES_JOBS);
|
|
|
|
m_databaseConnection->AddStatement(CREATEINDEX_JOBS_PRODUCTS, CREATEINDEX_JOBS_PRODUCTS_STATEMENT);
|
|
|
|
m_createStatements.push_back(CREATEINDEX_JOBS_PRODUCTS);
|
|
|
|
m_databaseConnection->AddStatement(CREATEINDEX_JOBS_JOBRUNKEY, CREATEINDEX_JOBS_JOBRUNKEY_STATEMENT);
|
|
m_createStatements.push_back(CREATEINDEX_JOBS_JOBRUNKEY);
|
|
|
|
m_databaseConnection->AddStatement(CREATEINDEX_JOBS_JOBKEY, CREATEINDEX_JOBS_JOBKEY_STATEMENT);
|
|
m_createStatements.push_back(CREATEINDEX_JOBS_JOBKEY);
|
|
|
|
m_databaseConnection->AddStatement(CREATEINDEX_SOURCE_NAME, CREATEINDEX_SOURCE_NAME_STATEMENT);
|
|
m_createStatements.push_back(CREATEINDEX_SOURCE_NAME);
|
|
|
|
m_databaseConnection->AddStatement(CREATEINDEX_SOURCE_GUID, CREATEINDEX_SOURCE_GUID_STATEMENT);
|
|
m_createStatements.push_back(CREATEINDEX_SOURCE_GUID);
|
|
|
|
m_databaseConnection->AddStatement(CREATEINDEX_PRODUCT_NAME, CREATEINDEX_PRODUCT_NAME_STATEMENT);
|
|
m_createStatements.push_back(CREATEINDEX_PRODUCT_NAME);
|
|
|
|
m_databaseConnection->AddStatement(CREATEINDEX_PRODUCT_SUBID, CREATEINDEX_PRODUCT_SUBID_STATEMENT);
|
|
m_createStatements.push_back(CREATEINDEX_PRODUCT_SUBID);
|
|
|
|
m_databaseConnection->AddStatement(CREATEINDEX_PRODUCTDEPENDENCIES_PRODUCTPK, CREATEINDEX_PRODUCTDEPENDENCIES_PRODUCTPK_STATEMENT);
|
|
m_createStatements.push_back(CREATEINDEX_PRODUCTDEPENDENCIES_PRODUCTPK);
|
|
|
|
m_databaseConnection->AddStatement(CREATEINDEX_PRODUCTDEPENDENCIES_UNRESOLVEDPATH, CREATEINDEX_PRODUCTDEPENDENCIES_UNRESOLVEDPATH_STATEMENT);
|
|
m_createStatements.push_back(CREATEINDEX_PRODUCTDEPENDENCIES_UNRESOLVEDPATH);
|
|
|
|
m_databaseConnection->AddStatement(CREATEINDEX_PRODUCTDEPENDENCIES_UNRESOLVEDPATH_WILDCARD, CREATEINDEX_PRODUCTDEPENDENCIES_UNRESOLVEDPATH_WILDCARD_STATEMENT);
|
|
m_createStatements.push_back(CREATEINDEX_PRODUCTDEPENDENCIES_UNRESOLVEDPATH_WILDCARD);
|
|
|
|
m_databaseConnection->AddStatement(CREATEINDEX_FILE_NAME, CREATEINDEX_FILE_NAME_STATEMENT);
|
|
m_createStatements.push_back(CREATEINDEX_FILE_NAME);
|
|
|
|
m_databaseConnection->AddStatement(CREATEINDEX_SCANFOLDERS_FILES, CREATEINDEX_SCANFOLDERS_FILES_STATEMENT);
|
|
m_createStatements.push_back(CREATEINDEX_SCANFOLDERS_FILES);
|
|
|
|
m_databaseConnection->AddStatement(DELETE_AUTO_SUCCEED_JOBS, DELETE_AUTO_SUCCEED_JOBS_STATEMENT);
|
|
}
|
|
|
|
void AssetDatabaseConnection::VacuumAndAnalyze()
|
|
{
|
|
if (m_databaseConnection)
|
|
{
|
|
m_databaseConnection->ExecuteOneOffStatement("VACUUM");
|
|
m_databaseConnection->ExecuteOneOffStatement("ANALYZE");
|
|
}
|
|
}
|
|
|
|
bool AssetDatabaseConnection::GetScanFolderByScanFolderID(AZ::s64 scanfolderID, ScanFolderDatabaseEntry& entry)
|
|
{
|
|
bool found = false;
|
|
QueryScanFolderByScanFolderID( scanfolderID,
|
|
[&](ScanFolderDatabaseEntry& scanFolderEntry)
|
|
{
|
|
entry = scanFolderEntry;
|
|
found = true;
|
|
return false;//only one
|
|
});
|
|
return found;
|
|
}
|
|
|
|
bool AssetDatabaseConnection::GetScanFolderBySourceID(AZ::s64 sourceID, ScanFolderDatabaseEntry& entry)
|
|
{
|
|
bool found = false;
|
|
QueryScanFolderBySourceID( sourceID,
|
|
[&](ScanFolderDatabaseEntry& scanFolderEntry)
|
|
{
|
|
entry = scanFolderEntry;
|
|
found = true;
|
|
return false;//only one
|
|
});
|
|
return found;
|
|
}
|
|
|
|
bool AssetDatabaseConnection::GetScanFolderByJobID(AZ::s64 jobID, ScanFolderDatabaseEntry& entry)
|
|
{
|
|
bool found = false;
|
|
QueryScanFolderByJobID( jobID,
|
|
[&](ScanFolderDatabaseEntry& scanFolderEntry)
|
|
{
|
|
entry = scanFolderEntry;
|
|
found = true;
|
|
return false; // return false because we only want one entry, no need to continue scanning rows
|
|
});
|
|
return found ;
|
|
}
|
|
|
|
bool AssetDatabaseConnection::GetScanFolderByProductID(AZ::s64 productID, ScanFolderDatabaseEntry& entry)
|
|
{
|
|
bool found = false;
|
|
QueryScanFolderByProductID( productID,
|
|
[&](ScanFolderDatabaseEntry& scanFolderEntry)
|
|
{
|
|
entry = scanFolderEntry;
|
|
found = true;
|
|
return false; // stop after the first result
|
|
});
|
|
return found;
|
|
}
|
|
|
|
bool AssetDatabaseConnection::GetScanFolderByPortableKey(QString portableKey, ScanFolderDatabaseEntry& entry)
|
|
{
|
|
bool found = false;
|
|
QueryScanFolderByPortableKey(portableKey.toUtf8().constData(),
|
|
[&](ScanFolderDatabaseEntry& scanFolder)
|
|
{
|
|
entry = AZStd::move(scanFolder);
|
|
found = true;
|
|
return false; // stop after the first result
|
|
});
|
|
return found;
|
|
}
|
|
|
|
bool AssetDatabaseConnection::GetScanFolders(ScanFolderDatabaseEntryContainer& container)
|
|
{
|
|
bool found = false;
|
|
bool succeeded = QueryScanFoldersTable(
|
|
[&](ScanFolderDatabaseEntry& scanFolder)
|
|
{
|
|
found = true;
|
|
container.push_back();
|
|
container.back() = AZStd::move(scanFolder);
|
|
return true; // return true to collect more rows since we are filling a container
|
|
});
|
|
return found && succeeded;
|
|
}
|
|
|
|
bool AssetDatabaseConnection::SetScanFolder(ScanFolderDatabaseEntry& entry)
|
|
{
|
|
ScanFolderDatabaseEntry existingEntry;
|
|
|
|
if (entry.m_scanFolderID == InvalidEntryId)
|
|
{
|
|
//they didn't supply an id, add to database!
|
|
|
|
//make sure the scan path is not already in the database
|
|
if (GetScanFolderByPortableKey(entry.m_portableKey.c_str(), existingEntry))
|
|
{
|
|
//its in the database already, update the input entry id and try again:
|
|
entry.m_scanFolderID = existingEntry.m_scanFolderID;
|
|
return SetScanFolder(entry);
|
|
}
|
|
|
|
//its not in the database, add it
|
|
// it is a single statement, do not wrap it in a transaction, this wastes a lot of time.
|
|
if (!s_InsertScanfolderQuery.BindAndStep(*m_databaseConnection, entry.m_scanFolder.c_str(), entry.m_displayName.c_str(), entry.m_portableKey.c_str(), entry.m_isRoot))
|
|
{
|
|
return false;
|
|
}
|
|
|
|
if (GetScanFolderByPortableKey(entry.m_portableKey.c_str(), existingEntry))
|
|
{
|
|
//its in the database already, update the input entry
|
|
entry.m_scanFolderID = existingEntry.m_scanFolderID;
|
|
return true;
|
|
}
|
|
|
|
AZ_Error(LOG_NAME, false, "Failed to read the new scan folder into the database.");
|
|
return false;
|
|
}
|
|
else
|
|
{
|
|
//they supplied an id, see if it exists in the database
|
|
if (!GetScanFolderByScanFolderID(entry.m_scanFolderID, existingEntry))
|
|
{
|
|
AZ_WarningOnce(LOG_NAME, false, "Failed to write the new scan folder into the database.");
|
|
return false;
|
|
}
|
|
|
|
return s_UpdateScanfolderQuery.BindAndStep(*m_databaseConnection, entry.m_scanFolder.c_str(), entry.m_displayName.c_str(), entry.m_portableKey.c_str(), entry.m_isRoot, entry.m_scanFolderID);
|
|
}
|
|
}
|
|
|
|
bool AssetDatabaseConnection::RemoveScanFolder(AZ::s64 scanFolderID)
|
|
{
|
|
ScopedTransaction transaction(m_databaseConnection);
|
|
|
|
if (!s_DeleteScanfolderQuery.BindAndStep(*m_databaseConnection, scanFolderID))
|
|
{
|
|
return false;
|
|
}
|
|
|
|
transaction.Commit();
|
|
|
|
return true;
|
|
}
|
|
|
|
bool AssetDatabaseConnection::RemoveScanFolders(ScanFolderDatabaseEntryContainer& container)
|
|
{
|
|
bool succeeded = true;
|
|
for (auto& entry : container)
|
|
{
|
|
succeeded &= RemoveScanFolder(entry.m_scanFolderID);
|
|
if (succeeded)
|
|
{
|
|
entry.m_scanFolderID = InvalidEntryId;//set it to default InvalidEntryId as this is no longer exists
|
|
}
|
|
}
|
|
return succeeded;
|
|
}
|
|
|
|
bool AssetDatabaseConnection::GetSourceBySourceID(AZ::s64 sourceID, SourceDatabaseEntry& entry)
|
|
{
|
|
bool found = false;
|
|
QuerySourceBySourceID( sourceID,
|
|
[&](SourceDatabaseEntry& source)
|
|
{
|
|
found = true;
|
|
entry = AZStd::move(source);
|
|
return false; // return false in order to stop iterating any further - we are only populating one entry.
|
|
});
|
|
return found;
|
|
}
|
|
|
|
bool AssetDatabaseConnection::GetSourceBySourceGuid(AZ::Uuid sourceGuid, SourceDatabaseEntry& entry)
|
|
{
|
|
bool found = false;
|
|
QuerySourceBySourceGuid(sourceGuid,
|
|
[&](SourceDatabaseEntry& source)
|
|
{
|
|
found = true;
|
|
entry = AZStd::move(source);
|
|
return false; // return false in order to stop iterating any further - we are only populating one entry.
|
|
});
|
|
return found;
|
|
}
|
|
|
|
bool AssetDatabaseConnection::GetSources(SourceDatabaseEntryContainer& container)
|
|
{
|
|
bool found = false;
|
|
bool succeeded = QuerySourcesTable(
|
|
[&](SourceDatabaseEntry& source)
|
|
{
|
|
found = true;
|
|
container.push_back();
|
|
container.back() = AZStd::move(source);
|
|
return true; // return true to continue iterating over additional results, we are populating a container
|
|
});
|
|
return found && succeeded;
|
|
}
|
|
|
|
bool AssetDatabaseConnection::GetSourceBySourceName(QString exactSourceName, SourceDatabaseEntry& entry)
|
|
{
|
|
bool found = false;
|
|
QuerySourceBySourceName(AssetUtilities::NormalizeFilePath(exactSourceName).toUtf8().constData(),
|
|
[&](SourceDatabaseEntry& source)
|
|
{
|
|
found = true;
|
|
entry = AZStd::move(source);
|
|
return false; // stop after the first result
|
|
});
|
|
return found;
|
|
}
|
|
|
|
bool AssetDatabaseConnection::GetSourcesBySourceName(QString exactSourceName, SourceDatabaseEntryContainer& container)
|
|
{
|
|
bool found = false;
|
|
bool succeeded = QuerySourceBySourceName(AssetUtilities::NormalizeFilePath(exactSourceName).toUtf8().constData(),
|
|
[&](SourceDatabaseEntry& source)
|
|
{
|
|
found = true;
|
|
container.push_back();
|
|
container.back() = AZStd::move(source);
|
|
return true; // return true to continue iterating over additional results, we are populating a container
|
|
});
|
|
return found && succeeded;
|
|
}
|
|
|
|
bool AssetDatabaseConnection::GetSourcesBySourceNameScanFolderId(QString exactSourceName, AZ::s64 scanFolderID, SourceDatabaseEntryContainer& container)
|
|
{
|
|
bool found = false;
|
|
bool succeeded = QuerySourceBySourceNameScanFolderID(exactSourceName.toUtf8().constData(),
|
|
scanFolderID,
|
|
[&](SourceDatabaseEntry& source)
|
|
{
|
|
found = true;
|
|
container.push_back();
|
|
container.back() = AZStd::move(source);
|
|
return true; // return true to continue iterating over additional results, we are populating a container
|
|
});
|
|
return found && succeeded;
|
|
}
|
|
|
|
bool AssetDatabaseConnection::GetSourcesLikeSourceName(QString likeSourceName, LikeType likeType, SourceDatabaseEntryContainer& container)
|
|
{
|
|
if (likeSourceName.isEmpty())
|
|
{
|
|
return false;
|
|
}
|
|
|
|
bool found = false;
|
|
bool succeeded = QuerySourceLikeSourceName(likeSourceName.toUtf8().constData(), likeType,
|
|
[&](SourceDatabaseEntry& source)
|
|
{
|
|
found = true;
|
|
container.push_back();
|
|
container.back() = AZStd::move(source);
|
|
return true; // return true to continue iterating over additional results, we are populating a container
|
|
});
|
|
return found && succeeded;
|
|
}
|
|
|
|
bool AssetDatabaseConnection::GetSourceByJobID(AZ::s64 jobID, SourceDatabaseEntry& entry)
|
|
{
|
|
bool found = false;
|
|
QuerySourceByJobID( jobID,
|
|
[&](SourceDatabaseEntry& source)
|
|
{
|
|
found = true;
|
|
entry = AZStd::move(source);
|
|
return false; // stop after the first result
|
|
});
|
|
return found;
|
|
}
|
|
|
|
bool AssetDatabaseConnection::GetSourceByProductID(AZ::s64 productID, SourceDatabaseEntry& entry)
|
|
{
|
|
bool found = false;
|
|
QuerySourceByProductID( productID,
|
|
[&](SourceDatabaseEntry& source)
|
|
{
|
|
found = true;
|
|
entry = AZStd::move(source);
|
|
return false; // stop after the first result
|
|
});
|
|
return found;
|
|
}
|
|
|
|
bool AssetDatabaseConnection::GetSourcesByProductName(QString exactProductName, SourceDatabaseEntryContainer& container)
|
|
{
|
|
bool found = false;
|
|
bool succeeded = QueryCombinedByProductName(exactProductName.toUtf8().constData(),
|
|
[&](CombinedDatabaseEntry& combined)
|
|
{
|
|
found = true;
|
|
container.push_back();
|
|
container.back() = AZStd::move(combined);
|
|
return true; // return true to continue collecting all
|
|
});
|
|
return found && succeeded;
|
|
}
|
|
|
|
bool AssetDatabaseConnection::GetSourcesLikeProductName(QString likeProductName, LikeType likeType, SourceDatabaseEntryContainer& container)
|
|
{
|
|
bool found = false;
|
|
bool succeeded = QueryCombinedLikeProductName(likeProductName.toUtf8().constData(), likeType,
|
|
[&](CombinedDatabaseEntry& combined)
|
|
{
|
|
found = true;
|
|
container.push_back();
|
|
container.back() = AZStd::move(combined);
|
|
return true;//all
|
|
});
|
|
return found && succeeded;
|
|
}
|
|
|
|
bool AssetDatabaseConnection::SetSource(SourceDatabaseEntry& entry)
|
|
{
|
|
if (entry.m_sourceID == InvalidEntryId)
|
|
{
|
|
//they didn't supply an id, add to database
|
|
|
|
//first make sure its not already in the database
|
|
SourceDatabaseEntry existingEntry;
|
|
if (GetSourceBySourceGuid(entry.m_sourceGuid, existingEntry))
|
|
{
|
|
// this source guid already exists. note that the UUID is final, there is only ever one UUID for a source
|
|
// if folders override each other, the UUID stays the same but the scanfolder field changes but its still considered the same source file.
|
|
entry.m_sourceID = existingEntry.m_sourceID;
|
|
return SetSource(entry); // now update the existing field
|
|
}
|
|
|
|
if (!s_InsertSourceQuery.BindAndStep(*m_databaseConnection, entry.m_scanFolderPK, entry.m_sourceName.c_str(), entry.m_sourceGuid, entry.m_analysisFingerprint.c_str()))
|
|
{
|
|
AZ_Warning(LOG_NAME, false, "Failed to write the new source into the database. %s", entry.m_sourceName.c_str());
|
|
return false;
|
|
}
|
|
//now that its in the database get the id:
|
|
entry.m_sourceID = m_databaseConnection->GetLastRowID();
|
|
|
|
AzToolsFramework::AssetDatabase::AssetDatabaseNotificationBus::Broadcast(
|
|
&AzToolsFramework::AssetDatabase::AssetDatabaseNotificationBus::Events::OnSourceFileChanged, entry);
|
|
return true;
|
|
}
|
|
else
|
|
{
|
|
//they supplied an id, see if it exists in the database
|
|
SourceDatabaseEntry existingEntry;
|
|
if (!GetSourceBySourceID(entry.m_sourceID, existingEntry))
|
|
{
|
|
//they supplied an id but is not in the database!
|
|
AZ_Error(LOG_NAME, false, "Failed to write the source into the database.");
|
|
return false;
|
|
}
|
|
|
|
// don't bother updating the database if all fields are equal.
|
|
// note that we already looked it up by source ID
|
|
if ((existingEntry.m_scanFolderPK == entry.m_scanFolderPK) &&
|
|
(existingEntry.m_sourceGuid == entry.m_sourceGuid) &&
|
|
(existingEntry.m_sourceName == entry.m_sourceName) &&
|
|
(existingEntry.m_analysisFingerprint == entry.m_analysisFingerprint)
|
|
)
|
|
{
|
|
return true;
|
|
}
|
|
|
|
|
|
bool bindResult = s_UpdateSourceQuery.BindAndStep(*m_databaseConnection, entry.m_scanFolderPK, entry.m_sourceName.c_str(), entry.m_sourceGuid, entry.m_sourceID, entry.m_analysisFingerprint.c_str());
|
|
if (bindResult)
|
|
{
|
|
AzToolsFramework::AssetDatabase::AssetDatabaseNotificationBus::Broadcast(
|
|
&AzToolsFramework::AssetDatabase::AssetDatabaseNotificationBus::Events::OnSourceFileChanged, entry);
|
|
}
|
|
return bindResult;
|
|
}
|
|
}
|
|
|
|
bool AssetDatabaseConnection::InvalidateSourceAnalysisFingerprints()
|
|
{
|
|
return m_databaseConnection->ExecuteOneOffStatement(INVALIDATE_SOURCE_ANALYSISFINGEPRINTS);
|
|
}
|
|
|
|
// this must actually delete the source
|
|
bool AssetDatabaseConnection::RemoveSource(AZ::s64 sourceID)
|
|
{
|
|
ScopedTransaction transaction(m_databaseConnection);
|
|
|
|
if (!s_DeleteSourceQuery.BindAndStep(*m_databaseConnection, sourceID))
|
|
{
|
|
return false;
|
|
}
|
|
|
|
transaction.Commit();
|
|
|
|
AzToolsFramework::AssetDatabase::AssetDatabaseNotificationBus::Broadcast(
|
|
&AzToolsFramework::AssetDatabase::AssetDatabaseNotificationBus::Events::OnSourceFileRemoved, sourceID);
|
|
|
|
return true;
|
|
}
|
|
|
|
bool AssetDatabaseConnection::RemoveSources(SourceDatabaseEntryContainer& container)
|
|
{
|
|
bool succeeded = true;
|
|
for (auto& entry : container)
|
|
{
|
|
succeeded &= RemoveSource(entry.m_sourceID);
|
|
if (succeeded)
|
|
{
|
|
entry.m_sourceID = InvalidEntryId;//set it to InvalidEntryId as it no longer exists
|
|
}
|
|
}
|
|
return succeeded;
|
|
}
|
|
|
|
bool AssetDatabaseConnection::RemoveSourcesByScanFolderID(AZ::s64 scanFolderID)
|
|
{
|
|
bool found = false;
|
|
bool succeeded = QuerySourceByScanFolderID(scanFolderID,
|
|
[&](SourceDatabaseEntry& source)
|
|
{
|
|
found = true;
|
|
succeeded &= RemoveSource(source.m_sourceID);
|
|
return true;//all
|
|
});
|
|
return found && succeeded;
|
|
}
|
|
|
|
AZ::s64 AssetDatabaseConnection::GetHighestJobRunKey()
|
|
{
|
|
if (!m_databaseConnection)
|
|
{
|
|
return 0;
|
|
}
|
|
|
|
StatementAutoFinalizer autoFinal;
|
|
|
|
if (!s_GetHighestJobrunkeyQuery.Bind(*m_databaseConnection, autoFinal))
|
|
{
|
|
return 0;
|
|
}
|
|
|
|
Statement* statement = autoFinal.Get();
|
|
|
|
if (statement->Step() == Statement::SqlError)
|
|
{
|
|
// this is okay, since the table may be empty.
|
|
return 0;
|
|
}
|
|
|
|
return statement->GetColumnInt64(0);
|
|
}
|
|
|
|
bool AssetDatabaseConnection::GetJobs(JobDatabaseEntryContainer& container, AZ::Uuid builderGuid, QString jobKey, QString platform, JobStatus status)
|
|
{
|
|
bool found = false;
|
|
bool succeeded = QueryJobsTable(
|
|
[&](JobDatabaseEntry& job)
|
|
{
|
|
found = true;
|
|
container.push_back();
|
|
container.back() = AZStd::move(job);
|
|
return true;//all
|
|
}, builderGuid,
|
|
jobKey.isEmpty() ? nullptr : jobKey.toUtf8().constData(),
|
|
platform.isEmpty() ? nullptr : platform.toUtf8().constData(),
|
|
status);
|
|
return found && succeeded;
|
|
}
|
|
|
|
bool AssetDatabaseConnection::GetJobByJobID(AZ::s64 jobID, JobDatabaseEntry& entry)
|
|
{
|
|
bool found = false;
|
|
QueryJobByJobID( jobID,
|
|
[&](JobDatabaseEntry& job)
|
|
{
|
|
found = true;
|
|
entry = AZStd::move(job);
|
|
return false; // stop after the first result
|
|
});
|
|
return found;
|
|
}
|
|
|
|
bool AssetDatabaseConnection::GetJobByProductID(AZ::s64 productID, JobDatabaseEntry& entry)
|
|
{
|
|
bool found = false;
|
|
QueryJobByProductID(productID,
|
|
[&](JobDatabaseEntry& job)
|
|
{
|
|
found = true;
|
|
entry = AZStd::move(job);
|
|
return false; // stop after the first result
|
|
});
|
|
return found;
|
|
}
|
|
|
|
bool AssetDatabaseConnection::GetJobsBySourceID(AZ::s64 sourceID, JobDatabaseEntryContainer& container, AZ::Uuid builderGuid, QString jobKey, QString platform, JobStatus status)
|
|
{
|
|
bool found = false;
|
|
bool succeeded = QueryJobBySourceID(sourceID,
|
|
[&](JobDatabaseEntry& job)
|
|
{
|
|
found = true;
|
|
container.push_back();
|
|
container.back() = AZStd::move(job);
|
|
return true; // continue to fetch more rows.
|
|
}, builderGuid,
|
|
jobKey.isEmpty() ? nullptr : jobKey.toUtf8().constData(),
|
|
platform.isEmpty() ? nullptr : platform.toUtf8().constData(),
|
|
status);
|
|
return found && succeeded;
|
|
}
|
|
|
|
bool AssetDatabaseConnection::GetJobsBySourceName(QString exactSourceName, JobDatabaseEntryContainer& container, AZ::Uuid builderGuid, QString jobKey, QString platform, JobStatus status)
|
|
{
|
|
bool found = false;
|
|
bool succeeded = QuerySourceBySourceName(exactSourceName.toUtf8().constData(),
|
|
[&](SourceDatabaseEntry& source)
|
|
{
|
|
succeeded = QueryJobBySourceID(source.m_sourceID,
|
|
[&](JobDatabaseEntry& job)
|
|
{
|
|
found = true;
|
|
container.push_back();
|
|
container.back() = AZStd::move(job);
|
|
return true;//all
|
|
}, builderGuid,
|
|
jobKey.isEmpty() ? nullptr : jobKey.toUtf8().constData(),
|
|
platform.isEmpty() ? nullptr : platform.toUtf8().constData(),
|
|
status);
|
|
return true; // continue to fetch more rows.
|
|
});
|
|
return found && succeeded;
|
|
}
|
|
|
|
bool AssetDatabaseConnection::GetJobsLikeSourceName(QString likeSourceName, LikeType likeType, JobDatabaseEntryContainer& container, AZ::Uuid builderGuid, QString jobKey, QString platform, JobStatus status)
|
|
{
|
|
if (likeSourceName.isEmpty())
|
|
{
|
|
return false;
|
|
}
|
|
|
|
bool found = false;
|
|
bool succeeded = QuerySourceLikeSourceName(likeSourceName.toUtf8().constData(), likeType,
|
|
[&](SourceDatabaseEntry& source)
|
|
{
|
|
succeeded = QueryJobBySourceID(source.m_sourceID,
|
|
[&](JobDatabaseEntry& job)
|
|
{
|
|
found = true;
|
|
container.push_back();
|
|
container.back() = AZStd::move(job);
|
|
return true;//all
|
|
}, builderGuid,
|
|
jobKey.isEmpty() ? nullptr : jobKey.toUtf8().constData(),
|
|
platform.isEmpty() ? nullptr : platform.toUtf8().constData(),
|
|
status);
|
|
return true; // continue to fetch more rows.
|
|
});
|
|
return found && succeeded;
|
|
}
|
|
|
|
bool AssetDatabaseConnection::GetJobsByProductName(QString exactProductName, JobDatabaseEntryContainer& container, AZ::Uuid builderGuid, QString jobKey, QString platform, JobStatus status)
|
|
{
|
|
bool found = false;
|
|
bool succeeded = QueryProductByProductName(exactProductName.toUtf8().constData(),
|
|
[&](ProductDatabaseEntry& product)
|
|
{
|
|
succeeded = QueryJobByProductID(product.m_productID,
|
|
[&](JobDatabaseEntry& job)
|
|
{
|
|
found = true;
|
|
container.push_back();
|
|
container.back() = AZStd::move(job);
|
|
return true;//all
|
|
});
|
|
return true; // continue to fetch more rows.
|
|
}, builderGuid,
|
|
jobKey.isEmpty() ? nullptr : jobKey.toUtf8().constData(),
|
|
platform.isEmpty() ? nullptr : platform.toUtf8().constData(),
|
|
status);
|
|
return found && succeeded;
|
|
}
|
|
|
|
bool AssetDatabaseConnection::GetJobsLikeProductName(QString likeProductName, LikeType likeType, JobDatabaseEntryContainer& container, AZ::Uuid builderGuid, QString jobKey, QString platform, JobStatus status)
|
|
{
|
|
bool found = false;
|
|
bool succeeded = QueryProductLikeProductName(likeProductName.toUtf8().constData(), likeType,
|
|
[&](ProductDatabaseEntry& product)
|
|
{
|
|
succeeded = QueryJobByProductID(product.m_productID,
|
|
[&](JobDatabaseEntry& job)
|
|
{
|
|
found = true;
|
|
container.push_back();
|
|
container.back() = AZStd::move(job);
|
|
return true; // continue to fetch more rows for the QueryJobByProductId call
|
|
});
|
|
return true; // continue to fetch more rows for the QueryProductLikeProductName call
|
|
}, builderGuid,
|
|
jobKey.isEmpty() ? nullptr : jobKey.toUtf8().constData(),
|
|
platform.isEmpty() ? nullptr : platform.toUtf8().constData(),
|
|
status);
|
|
return found && succeeded;
|
|
}
|
|
|
|
bool AssetDatabaseConnection::SetJob(JobDatabaseEntry& entry)
|
|
{
|
|
if (entry.m_jobRunKey <= 0)
|
|
{
|
|
AZ_Error(LOG_NAME, false, "You must specify a valid Job Run Key for a job to make it into the database.\n");
|
|
return false;
|
|
}
|
|
|
|
if (entry.m_jobID == InvalidEntryId)
|
|
{
|
|
//they didn't supply an id, add to database
|
|
|
|
//make sure its not already in the database
|
|
JobDatabaseEntryContainer existingJobs;
|
|
if (GetJobsBySourceID(entry.m_sourcePK, existingJobs, entry.m_builderGuid, entry.m_jobKey.c_str(), entry.m_platform.c_str()))
|
|
{
|
|
//see if this job is already here
|
|
for (const auto& existingjob : existingJobs)
|
|
{
|
|
if (existingjob == entry)
|
|
{
|
|
//this job already exists
|
|
entry.m_jobID = existingjob.m_jobID;
|
|
return true;
|
|
}
|
|
}
|
|
}
|
|
|
|
if (!s_InsertJobQuery.BindAndStep(*m_databaseConnection, entry.m_sourcePK, entry.m_jobKey.c_str(), entry.m_fingerprint, entry.m_platform.c_str(),
|
|
entry.m_builderGuid, static_cast<int>(entry.m_status), entry.m_jobRunKey, entry.m_firstFailLogTime, entry.m_firstFailLogFile.c_str(),
|
|
entry.m_lastFailLogTime, entry.m_lastFailLogFile.c_str(), entry.m_lastLogTime, entry.m_lastLogFile.c_str(), entry.m_warningCount, entry.m_errorCount))
|
|
{
|
|
return false;
|
|
}
|
|
|
|
//make sure its now in the database
|
|
existingJobs.clear();
|
|
if (GetJobsBySourceID(entry.m_sourcePK, existingJobs, entry.m_builderGuid, entry.m_jobKey.c_str(), entry.m_platform.c_str()))
|
|
{
|
|
//see if this job is already here
|
|
for (const auto& existingjob : existingJobs)
|
|
{
|
|
if (existingjob == entry)
|
|
{
|
|
//this job already exists
|
|
entry.m_jobID = existingjob.m_jobID;
|
|
return true;
|
|
}
|
|
}
|
|
}
|
|
|
|
AZ_Warning(LOG_NAME, false, "Failed to read the new job from the database.");
|
|
return false;
|
|
}
|
|
else
|
|
{
|
|
//they supplied an id, see if it exists in the database
|
|
JobDatabaseEntry existingEntry;
|
|
if (!GetJobByJobID(entry.m_jobID, existingEntry))
|
|
{
|
|
AZ_Error(LOG_NAME, false, "Failed to find the job in the database.");
|
|
return false;
|
|
}
|
|
|
|
//its in the database already, if its not the same update the database
|
|
if (existingEntry == entry)
|
|
{
|
|
return true;
|
|
}
|
|
|
|
return s_UpdateJobQuery.BindAndStep(*m_databaseConnection, entry.m_sourcePK, entry.m_jobKey.c_str(), entry.m_fingerprint, entry.m_platform.c_str(),
|
|
entry.m_builderGuid, static_cast<int>(entry.m_status), entry.m_jobRunKey, entry.m_firstFailLogTime, entry.m_firstFailLogFile.c_str(),
|
|
entry.m_lastFailLogTime, entry.m_lastFailLogFile.c_str(), entry.m_lastLogTime, entry.m_lastLogFile.c_str(), entry.m_warningCount, entry.m_errorCount, entry.m_jobID);
|
|
}
|
|
}
|
|
|
|
// this must actually delete the job
|
|
bool AssetDatabaseConnection::RemoveJob(AZ::s64 jobID)
|
|
{
|
|
ScopedTransaction transaction(m_databaseConnection);
|
|
|
|
if(!s_DeleteJobQuery.BindAndStep(*m_databaseConnection, jobID))
|
|
{
|
|
return false;
|
|
}
|
|
|
|
transaction.Commit();
|
|
|
|
return true;
|
|
}
|
|
|
|
bool AssetDatabaseConnection::RemoveJobs(JobDatabaseEntryContainer& container)
|
|
{
|
|
bool succeeded = true;
|
|
for (auto& entry : container)
|
|
{
|
|
succeeded &= RemoveJob(entry.m_jobID);
|
|
if (succeeded)
|
|
{
|
|
entry.m_jobID = InvalidEntryId; //set it to InvalidEntryId as the id is no longer valid
|
|
}
|
|
}
|
|
|
|
return succeeded;
|
|
}
|
|
|
|
bool AssetDatabaseConnection::RemoveJobByProductID(AZ::s64 productID)
|
|
{
|
|
JobDatabaseEntry job;
|
|
bool succeeded = GetJobByProductID(productID, job);
|
|
if (succeeded)
|
|
{
|
|
succeeded &= RemoveJob(job.m_jobID);
|
|
}
|
|
return succeeded;
|
|
}
|
|
|
|
bool AssetDatabaseConnection::GetProductByProductID(AZ::s64 productID, ProductDatabaseEntry& entry)
|
|
{
|
|
bool found = false;
|
|
QueryProductByProductID(productID,
|
|
[&](ProductDatabaseEntry& product)
|
|
{
|
|
found = true;
|
|
entry = AZStd::move(product);
|
|
return false; // stop after the first one is found.
|
|
});
|
|
return found;
|
|
}
|
|
|
|
bool AssetDatabaseConnection::GetProducts(ProductDatabaseEntryContainer& container, AZ::Uuid builderGuid, QString jobKey, QString platform, JobStatus status)
|
|
{
|
|
bool found = false;
|
|
bool succeeded = QueryProductsTable(
|
|
[&](ProductDatabaseEntry& product)
|
|
{
|
|
found = true;
|
|
container.push_back();
|
|
container.back() = AZStd::move(product);
|
|
return true; // continue fetching more results.
|
|
}, builderGuid,
|
|
jobKey.isEmpty() ? nullptr : jobKey.toUtf8().constData(),
|
|
platform.isEmpty() ? nullptr : platform.toUtf8().constData(),
|
|
status);
|
|
return found && succeeded;
|
|
}
|
|
|
|
bool AssetDatabaseConnection::GetProductsByProductName(QString exactProductName, ProductDatabaseEntryContainer& container, AZ::Uuid builderGuid, QString jobKey, QString platform, JobStatus status)
|
|
{
|
|
bool found = false;
|
|
bool succeeded = QueryProductByProductName(exactProductName.toUtf8().constData(),
|
|
[&](ProductDatabaseEntry& product)
|
|
{
|
|
found = true;
|
|
container.push_back();
|
|
container.back() = AZStd::move(product);
|
|
return true; // continue fetching more results.
|
|
}, builderGuid,
|
|
jobKey.isEmpty() ? nullptr : jobKey.toUtf8().constData(),
|
|
platform.isEmpty() ? nullptr : platform.toUtf8().constData(),
|
|
status);
|
|
return found && succeeded;
|
|
}
|
|
|
|
bool AssetDatabaseConnection::GetProductsLikeProductName(QString likeProductName, LikeType likeType, ProductDatabaseEntryContainer& container, AZ::Uuid builderGuid, QString jobKey, QString platform, JobStatus status)
|
|
{
|
|
bool found = false;
|
|
|
|
if (likeProductName.isEmpty())
|
|
{
|
|
return false;
|
|
}
|
|
|
|
bool succeeded = QueryProductLikeProductName(likeProductName.toUtf8().constData(), likeType,
|
|
[&](ProductDatabaseEntry& product)
|
|
{
|
|
found = true;
|
|
container.push_back();
|
|
container.back() = AZStd::move(product);
|
|
return true; // continue fetching more results.
|
|
}, builderGuid,
|
|
jobKey.isEmpty() ? nullptr : jobKey.toUtf8().constData(),
|
|
platform.isEmpty() ? nullptr : platform.toUtf8().constData(),
|
|
status);
|
|
return found && succeeded;
|
|
}
|
|
|
|
bool AssetDatabaseConnection::GetProductsBySourceName(QString exactSourceName, ProductDatabaseEntryContainer& container, AZ::Uuid builderGuid, QString jobKey, QString platform, JobStatus status)
|
|
{
|
|
bool found = false;
|
|
bool succeeded = QueryProductBySourceName(exactSourceName.toUtf8().constData(),
|
|
[&](ProductDatabaseEntry& product)
|
|
{
|
|
found = true;
|
|
container.push_back();
|
|
container.back() = AZStd::move(product);
|
|
return true; // continue fetching more results.
|
|
}, builderGuid,
|
|
jobKey.isEmpty() ? nullptr : jobKey.toUtf8().constData(),
|
|
platform.isEmpty() ? nullptr : platform.toUtf8().constData(),
|
|
status);
|
|
return found && succeeded;
|
|
}
|
|
|
|
bool AssetDatabaseConnection::GetProductsLikeSourceName(QString likeSourceName, LikeType likeType, ProductDatabaseEntryContainer& container, AZ::Uuid builderGuid, QString jobKey, QString platform, JobStatus status)
|
|
{
|
|
if (likeSourceName.isEmpty())
|
|
{
|
|
return false;
|
|
}
|
|
|
|
bool found = false;
|
|
bool succeeded = QueryProductLikeSourceName(likeSourceName.toUtf8().constData(), likeType,
|
|
[&](ProductDatabaseEntry& product)
|
|
{
|
|
found = true;
|
|
container.push_back();
|
|
container.back() = AZStd::move(product);
|
|
return true; // continue fetching more results.
|
|
}, builderGuid,
|
|
jobKey.isEmpty() ? nullptr : jobKey.toUtf8().constData(),
|
|
platform.isEmpty() ? nullptr : platform.toUtf8().constData(),
|
|
status);
|
|
return found && succeeded;
|
|
}
|
|
|
|
bool AssetDatabaseConnection::GetProductsBySourceID(AZ::s64 sourceID, ProductDatabaseEntryContainer& container, AZ::Uuid builderGuid, QString jobKey, QString platform, JobStatus status)
|
|
{
|
|
bool found = false;
|
|
bool succeeded = QueryCombinedBySourceID(sourceID,
|
|
[&](CombinedDatabaseEntry& combined)
|
|
{
|
|
found = true;
|
|
container.push_back();
|
|
container.back() = AZStd::move(combined);
|
|
return true; // continue fetching more results.
|
|
}, builderGuid,
|
|
jobKey.isEmpty() ? nullptr : jobKey.toUtf8().constData(),
|
|
platform.isEmpty() ? nullptr : platform.toUtf8().constData(),
|
|
status);
|
|
return found && succeeded;
|
|
}
|
|
|
|
bool AssetDatabaseConnection::GetProductsByJobID(AZ::s64 jobID, ProductDatabaseEntryContainer& container)
|
|
{
|
|
bool found = false;
|
|
bool succeeded = QueryCombinedByJobID(jobID,
|
|
[&](CombinedDatabaseEntry& combined)
|
|
{
|
|
found = true;
|
|
container.push_back();
|
|
container.back() = AZStd::move(combined);
|
|
return true; // continue fetching more results.
|
|
});
|
|
return found && succeeded;
|
|
}
|
|
|
|
bool AssetDatabaseConnection::GetProductByJobIDSubId(AZ::s64 jobID, AZ::u32 subID, AzToolsFramework::AssetDatabase::ProductDatabaseEntry& result)
|
|
{
|
|
bool found = false;
|
|
QueryProductByJobIDSubID(jobID, subID,
|
|
[&](ProductDatabaseEntry& resultFromDB)
|
|
{
|
|
found = true;
|
|
result = AZStd::move(resultFromDB);
|
|
return false; // stop after the first result
|
|
});
|
|
return found;
|
|
}
|
|
|
|
bool AssetDatabaseConnection::GetProductBySourceGuidSubId(AZ::Uuid sourceGuid, AZ::u32 subId, AzToolsFramework::AssetDatabase::ProductDatabaseEntry& result)
|
|
{
|
|
bool found = false;
|
|
QueryProductBySourceGuidSubID(sourceGuid, subId,
|
|
[&](ProductDatabaseEntry& resultFromDB)
|
|
{
|
|
found = true;
|
|
result = AZStd::move(resultFromDB);
|
|
return false; // stop after the first result
|
|
});
|
|
return found;
|
|
}
|
|
|
|
//! For a given source, set the list of products for that source.
|
|
//! Removes any data that's present and overwrites it with the new list
|
|
//! Note that an empty list is in fact acceptable data, it means the source emitted no products
|
|
bool AssetDatabaseConnection::SetProduct(ProductDatabaseEntry& entry)
|
|
{
|
|
bool wasAlreadyInDatabase = false;
|
|
ProductDatabaseEntry existingProductInDatabase;
|
|
|
|
if (entry.m_productID == InvalidEntryId)
|
|
{
|
|
// they didn't set an id, add to database
|
|
// but make sure its not already in the database before doing so:
|
|
if (GetProductByJobIDSubId(entry.m_jobPK, entry.m_subID, existingProductInDatabase))
|
|
{
|
|
wasAlreadyInDatabase = true;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
if (GetProductByProductID(entry.m_productID, existingProductInDatabase))
|
|
{
|
|
wasAlreadyInDatabase = true;
|
|
}
|
|
else
|
|
{
|
|
// its not OK to be pushing specific IDs into the database that don't exist.
|
|
AZ_Error(LOG_NAME, false, "Attempt to call SetProduct(...) with a database productID (%lli) that is not -1 but also doesn't exist.", entry.m_productID);
|
|
return false;
|
|
}
|
|
}
|
|
|
|
// we can early out if it was in the database and the database entry is identical to the new one:
|
|
if (wasAlreadyInDatabase)
|
|
{
|
|
entry.m_productID = existingProductInDatabase.m_productID;
|
|
if (entry == existingProductInDatabase)
|
|
{
|
|
return true;
|
|
}
|
|
}
|
|
|
|
// if we get here, we need to either insert or update in the database.
|
|
|
|
{
|
|
// note, intentional scope created for the statement finalizer
|
|
StatementAutoFinalizer autoFinalizer;
|
|
if (wasAlreadyInDatabase)
|
|
{
|
|
// it was already in the database, so use the "UPDATE" version
|
|
if (!s_UpdateProductQuery.Bind(*m_databaseConnection, autoFinalizer, entry.m_jobPK, entry.m_subID, entry.m_productName.c_str(), entry.m_assetType, entry.m_legacyGuid, entry.m_productID))
|
|
{
|
|
return false;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
// it wasn't in the database, so use the "INSERT" version
|
|
if (!s_InsertProductQuery.Bind(*m_databaseConnection, autoFinalizer, entry.m_jobPK, entry.m_subID, entry.m_productName.c_str(), entry.m_assetType, entry.m_legacyGuid))
|
|
{
|
|
return false;
|
|
}
|
|
}
|
|
|
|
Statement* statement = autoFinalizer.Get();
|
|
|
|
if(statement->Step() == Statement::SqlError)
|
|
{
|
|
AZ_Error(LOG_NAME, false, "Failed to execute the %s statement", wasAlreadyInDatabase ? UPDATE_PRODUCT : INSERT_PRODUCT);
|
|
return false;
|
|
}
|
|
|
|
if (!wasAlreadyInDatabase)
|
|
{
|
|
// just read what the last inserted row ID is.
|
|
// (this is why database access must only be one thread per connection, as this could otherwise
|
|
// be mutated by the other thread. its stored on the connection object, not a TLS variable)
|
|
entry.m_productID = m_databaseConnection->GetLastRowID();
|
|
}
|
|
|
|
AzToolsFramework::AssetDatabase::AssetDatabaseNotificationBus::Broadcast(
|
|
&AzToolsFramework::AssetDatabase::AssetDatabaseNotificationBus::Events::OnProductFileChanged, entry);
|
|
}
|
|
return true;
|
|
}
|
|
|
|
bool AssetDatabaseConnection::SetProducts(ProductDatabaseEntryContainer& container)
|
|
{
|
|
if (container.empty())
|
|
{
|
|
return false;
|
|
}
|
|
|
|
bool succeeded = true;
|
|
for (auto& entry : container)
|
|
{
|
|
succeeded &= SetProduct(entry);
|
|
}
|
|
return succeeded;
|
|
}
|
|
|
|
//! Clear the products for a given source. This removes the entry entirely, not just sets it to empty.
|
|
bool AssetDatabaseConnection::RemoveProduct(AZ::s64 productID)
|
|
{
|
|
ScopedTransaction transaction(m_databaseConnection);
|
|
|
|
if (!s_DeleteProductQuery.BindAndStep(*m_databaseConnection, productID))
|
|
{
|
|
return false;
|
|
}
|
|
|
|
bool wasEffective = (m_databaseConnection->GetNumAffectedRows() != 0);
|
|
|
|
transaction.Commit();
|
|
|
|
if (wasEffective)
|
|
{
|
|
AzToolsFramework::AssetDatabase::AssetDatabaseNotificationBus::Broadcast(
|
|
&AzToolsFramework::AssetDatabase::AssetDatabaseNotificationBus::Events::OnProductFileRemoved, productID);
|
|
}
|
|
return wasEffective;
|
|
}
|
|
|
|
bool AssetDatabaseConnection::RemoveProducts(ProductDatabaseEntryContainer& container)
|
|
{
|
|
if (container.empty())
|
|
{
|
|
return false;
|
|
}
|
|
|
|
bool succeeded = true;
|
|
for (auto& entry : container)
|
|
{
|
|
succeeded &= RemoveProduct(entry.m_productID);
|
|
if (succeeded)
|
|
{
|
|
entry.m_productID = InvalidEntryId;
|
|
}
|
|
}
|
|
return succeeded;
|
|
}
|
|
|
|
bool AssetDatabaseConnection::RemoveProductsByJobID(AZ::s64 jobID)
|
|
{
|
|
ScopedTransaction transaction(m_databaseConnection);
|
|
|
|
ProductDatabaseEntryContainer productsToRemove;
|
|
GetProductsByJobID(jobID, productsToRemove);
|
|
|
|
if (!s_DeleteProductsByJobidQuery.BindAndStep(*m_databaseConnection, jobID))
|
|
{
|
|
return false;
|
|
}
|
|
|
|
|
|
bool wasEffective = (m_databaseConnection->GetNumAffectedRows() != 0);
|
|
|
|
transaction.Commit();
|
|
|
|
if (wasEffective)
|
|
{
|
|
AzToolsFramework::AssetDatabase::AssetDatabaseNotificationBus::Broadcast(
|
|
&AzToolsFramework::AssetDatabase::AssetDatabaseNotificationBus::Events::OnProductFilesRemoved, productsToRemove);
|
|
}
|
|
|
|
return wasEffective;
|
|
}
|
|
|
|
bool AssetDatabaseConnection::RemoveProductsBySourceID(AZ::s64 sourceID, AZ::Uuid builderGuid, QString jobKey, QString platform, JobStatus status)
|
|
{
|
|
ProductDatabaseEntryContainer products;
|
|
bool getProductsSucceeded = GetProductsBySourceID(sourceID, products, builderGuid, jobKey, platform, status);
|
|
if ( (!builderGuid.IsNull()) || (jobKey != nullptr) || (status != AssetSystem::JobStatus::Any) )
|
|
{
|
|
//we have to do custom query the delete
|
|
if (getProductsSucceeded)
|
|
{
|
|
getProductsSucceeded &= RemoveProducts(products);
|
|
}
|
|
return getProductsSucceeded;
|
|
}
|
|
|
|
ScopedTransaction transaction(m_databaseConnection);
|
|
|
|
if(!platform.isEmpty())
|
|
{
|
|
AZStd::string platformStr = platform.toUtf8().constData();
|
|
|
|
if (!s_DeleteProductsBySourceidPlatformQuery.BindAndStep(*m_databaseConnection, sourceID, platformStr.c_str()))
|
|
{
|
|
return false;
|
|
}
|
|
}
|
|
else if(!s_DeleteProductsBySourceidQuery.BindAndStep(*m_databaseConnection, sourceID))
|
|
{
|
|
return false;
|
|
}
|
|
|
|
|
|
bool wasEffective = (m_databaseConnection->GetNumAffectedRows() != 0);
|
|
|
|
transaction.Commit();
|
|
|
|
if (wasEffective && getProductsSucceeded)
|
|
{
|
|
AzToolsFramework::AssetDatabase::AssetDatabaseNotificationBus::Broadcast(
|
|
&AzToolsFramework::AssetDatabase::AssetDatabaseNotificationBus::Events::OnProductFilesRemoved, products);
|
|
}
|
|
|
|
return wasEffective;
|
|
}
|
|
|
|
bool AssetDatabaseConnection::GetJobInfoByJobID(AZ::s64 jobID, JobInfo& entry)
|
|
{
|
|
bool found = false;
|
|
QueryJobInfoByJobID(jobID,
|
|
[&](JobInfo& jobInfo)
|
|
{
|
|
found = true;
|
|
entry = AZStd::move(jobInfo);
|
|
return false; // stop after the first result
|
|
});
|
|
return found;
|
|
}
|
|
|
|
bool AssetDatabaseConnection::GetJobInfoByJobKey(AZStd::string jobKey, JobInfoContainer& container)
|
|
{
|
|
bool found = false;
|
|
bool succeeded = QueryJobInfoByJobKey(jobKey,
|
|
[&](JobInfo& jobInfo)
|
|
{
|
|
found = true;
|
|
container.push_back();
|
|
container.back() = AZStd::move(jobInfo);
|
|
return true; // return true to keep iterating over further rows.
|
|
});
|
|
return found && succeeded;
|
|
|
|
}
|
|
|
|
bool AssetDatabaseConnection::GetJobInfoByJobRunKey(AZ::u64 jobRunKey, JobInfoContainer& container)
|
|
{
|
|
bool found = false;
|
|
bool succeeded = QueryJobInfoByJobRunKey(jobRunKey,
|
|
[&](JobInfo& jobInfo)
|
|
{
|
|
found = true;
|
|
container.push_back();
|
|
container.back() = AZStd::move(jobInfo);
|
|
return true; // return true to keep iterating over further rows.
|
|
});
|
|
return found && succeeded;
|
|
}
|
|
|
|
bool AssetDatabaseConnection::GetJobInfoBySourceName(QString exactSourceName, JobInfoContainer& container, AZ::Uuid builderGuid, QString jobKey, QString platform, JobStatus status)
|
|
{
|
|
bool found = false;
|
|
bool succeeded = QueryJobInfoBySourceName(exactSourceName.toUtf8().constData(),
|
|
[&](JobInfo& jobInfo)
|
|
{
|
|
found = true;
|
|
container.push_back();
|
|
container.back() = AZStd::move(jobInfo);
|
|
return true; // return true to keep iterating over further rows.
|
|
}, builderGuid,
|
|
jobKey.isEmpty() ? nullptr : jobKey.toUtf8().constData(),
|
|
platform.isEmpty() ? nullptr : platform.toUtf8().constData(),
|
|
status);
|
|
return found && succeeded;
|
|
}
|
|
|
|
bool AssetDatabaseConnection::SetSourceFileDependencies(SourceFileDependencyEntryContainer& container)
|
|
{
|
|
bool succeeded = true;
|
|
for (auto& entry : container)
|
|
{
|
|
succeeded = succeeded && SetSourceFileDependency(entry);
|
|
}
|
|
return succeeded;
|
|
}
|
|
|
|
bool AssetDatabaseConnection::SetSourceFileDependency(SourceFileDependencyEntry& entry)
|
|
{
|
|
//first make sure its not already in the database
|
|
if (!s_InsertSourceDependencyQuery.BindAndStep(*m_databaseConnection, entry.m_builderGuid, entry.m_source.c_str(), entry.m_dependsOnSource.c_str(), entry.m_typeOfDependency, entry.m_fromAssetId))
|
|
{
|
|
return false;
|
|
}
|
|
|
|
entry.m_sourceDependencyID = m_databaseConnection->GetLastRowID();
|
|
return true;
|
|
}
|
|
|
|
bool AssetDatabaseConnection::RemoveSourceFileDependencies(const AZStd::unordered_set<AZ::s64>& container)
|
|
{
|
|
ScopedTransaction transaction(m_databaseConnection);
|
|
bool succeeded = true;
|
|
for (AZ::s64 entry : container)
|
|
{
|
|
succeeded = succeeded && RemoveSourceFileDependency(entry);
|
|
}
|
|
|
|
if (succeeded)
|
|
{
|
|
transaction.Commit();
|
|
return true;
|
|
}
|
|
return false;
|
|
}
|
|
|
|
bool AssetDatabaseConnection::RemoveSourceFileDependencies(const SourceFileDependencyEntryContainer& container)
|
|
{
|
|
AZStd::unordered_set<AZ::s64> uniqueRowIds;
|
|
for (const SourceFileDependencyEntry& item : container)
|
|
{
|
|
uniqueRowIds.insert(item.m_sourceDependencyID);
|
|
}
|
|
return RemoveSourceFileDependencies(uniqueRowIds);
|
|
}
|
|
|
|
bool AssetDatabaseConnection::RemoveSourceFileDependency(AZ::s64 sourceFileDependencyId)
|
|
{
|
|
return s_DeleteSourceDependencySourcedependencyidQuery.BindAndStep(*m_databaseConnection, sourceFileDependencyId);
|
|
}
|
|
|
|
bool AssetDatabaseConnection::GetSourceFileDependenciesByBuilderGUIDAndSource(const AZ::Uuid& builderGuid, const char* source, AzToolsFramework::AssetDatabase::SourceFileDependencyEntry::TypeOfDependency typeOfDependency, SourceFileDependencyEntryContainer& container)
|
|
{
|
|
bool found = false;
|
|
bool succeeded = QueryDependsOnSourceBySourceDependency(source, nullptr, typeOfDependency,
|
|
[&](SourceFileDependencyEntry& entry)
|
|
{
|
|
if (builderGuid == entry.m_builderGuid)
|
|
{
|
|
found = true;
|
|
container.push_back();
|
|
container.back() = AZStd::move(entry);
|
|
}
|
|
return true; // return true to keep iterating over further rows.
|
|
});
|
|
return found && succeeded;
|
|
}
|
|
|
|
bool AssetDatabaseConnection::GetSourceFileDependenciesByDependsOnSource(const QString& dependsOnSource, AzToolsFramework::AssetDatabase::SourceFileDependencyEntry::TypeOfDependency typeOfDependency, SourceFileDependencyEntryContainer& container)
|
|
{
|
|
bool found = false;
|
|
bool succeeded = QuerySourceDependencyByDependsOnSource(dependsOnSource.toUtf8().constData(), nullptr, typeOfDependency,
|
|
[&](SourceFileDependencyEntry& entry)
|
|
{
|
|
found = true;
|
|
container.push_back();
|
|
container.back() = AZStd::move(entry);
|
|
return true; // return true to keep iterating over further rows.
|
|
});
|
|
return found && succeeded;
|
|
}
|
|
|
|
bool AssetDatabaseConnection::GetDependsOnSourceBySource(
|
|
const char* source,
|
|
AzToolsFramework::AssetDatabase::SourceFileDependencyEntry::TypeOfDependency typeOfDependency,
|
|
AzToolsFramework::AssetDatabase::SourceFileDependencyEntryContainer& container)
|
|
{
|
|
bool found = false;
|
|
bool succeeded = QueryDependsOnSourceBySourceDependency(source, nullptr, typeOfDependency,
|
|
[&](SourceFileDependencyEntry& entry)
|
|
{
|
|
found = true;
|
|
container.push_back();
|
|
container.back() = AZStd::move(entry);
|
|
return true; // return true to keep iterating over further rows.
|
|
});
|
|
return found && succeeded;
|
|
}
|
|
|
|
bool AssetDatabaseConnection::GetSourceFileDependencyBySourceDependencyId(AZ::s64 sourceDependencyId, SourceFileDependencyEntry& sourceDependencyEntry)
|
|
{
|
|
bool found = false;
|
|
QuerySourceDependencyBySourceDependencyId(sourceDependencyId,
|
|
[&](SourceFileDependencyEntry& entry)
|
|
{
|
|
found = true;
|
|
sourceDependencyEntry = AZStd::move(entry);
|
|
return false; // stop after the first result
|
|
});
|
|
return found;
|
|
}
|
|
|
|
bool AssetDatabaseConnection::CreateOrUpdateLegacySubID(AzToolsFramework::AssetDatabase::LegacySubIDsEntry& entry)
|
|
{
|
|
ScopedTransaction transaction(m_databaseConnection);
|
|
|
|
const char* statementName = INSERT_NEW_LEGACYSUBID;
|
|
|
|
bool creatingNew = entry.m_subIDsEntryID == InvalidEntryId;
|
|
|
|
if (!creatingNew)
|
|
{
|
|
statementName = OVERWRITE_EXISTING_LEGACYSUBID;
|
|
}
|
|
|
|
if (creatingNew)
|
|
{
|
|
if (!s_InsertNewLegacysubidQuery.BindAndStep(*m_databaseConnection, entry.m_productPK, entry.m_subID))
|
|
{
|
|
return false;
|
|
}
|
|
}
|
|
else if (!s_OverwriteExistingLegacysubidQuery.BindAndStep(*m_databaseConnection, entry.m_productPK, entry.m_subID, entry.m_subIDsEntryID))
|
|
{
|
|
return false;
|
|
}
|
|
|
|
|
|
if (creatingNew)
|
|
{
|
|
AZ::s64 rowID = m_databaseConnection->GetLastRowID();
|
|
entry.m_subIDsEntryID = rowID;
|
|
}
|
|
else
|
|
{
|
|
if (m_databaseConnection->GetNumAffectedRows() == 0)
|
|
{
|
|
// you specified an invalid key.
|
|
AZ_Warning(LOG_NAME, false, "Failed to CreateOrUpdateLegacySubID in the database - invalid key specified.");
|
|
return false;
|
|
}
|
|
}
|
|
|
|
transaction.Commit();
|
|
return true;
|
|
}
|
|
|
|
bool AssetDatabaseConnection::RemoveLegacySubID(AZ::s64 legacySubIDsEntryID)
|
|
{
|
|
ScopedTransaction transaction(m_databaseConnection);
|
|
|
|
if (!s_DeleteLegacysubidsByPrimaryKeyQuery.BindAndStep(*m_databaseConnection, legacySubIDsEntryID))
|
|
{
|
|
return false;
|
|
}
|
|
|
|
transaction.Commit();
|
|
|
|
return true;
|
|
}
|
|
|
|
bool AssetDatabaseConnection::RemoveLegacySubIDsByProductID(AZ::s64 productID)
|
|
{
|
|
ScopedTransaction transaction(m_databaseConnection);
|
|
|
|
if (!s_DeleteLegacysubidsByProductidQuery.BindAndStep(*m_databaseConnection, productID))
|
|
{
|
|
return false;
|
|
}
|
|
|
|
transaction.Commit();
|
|
|
|
return true;
|
|
}
|
|
|
|
// ProductDependencies
|
|
bool AssetDatabaseConnection::GetProductDependencies(ProductDependencyDatabaseEntryContainer& container)
|
|
{
|
|
bool found = false;
|
|
bool succeeded = QueryProductDependenciesTable([&](AZ::Data::AssetId& /*assetId*/, ProductDependencyDatabaseEntry& entry)
|
|
{
|
|
found = true;
|
|
container.push_back();
|
|
container.back() = AZStd::move(entry);
|
|
return true; // return true to keep iterating over further rows.
|
|
});
|
|
return found && succeeded;
|
|
}
|
|
|
|
bool AssetDatabaseConnection::GetProductDependencyByProductDependencyID(AZ::s64 productDependencyID, ProductDependencyDatabaseEntry& productDependencyEntry)
|
|
{
|
|
bool found = false;
|
|
QueryProductDependencyByProductDependencyId(productDependencyID,
|
|
[&](ProductDependencyDatabaseEntry& entry)
|
|
{
|
|
found = true;
|
|
productDependencyEntry = AZStd::move(entry);
|
|
return false; // stop after the first result
|
|
});
|
|
return found;
|
|
}
|
|
|
|
bool AssetDatabaseConnection::GetProductDependenciesByProductID(AZ::s64 productID, ProductDependencyDatabaseEntryContainer& container)
|
|
{
|
|
bool found = false;
|
|
bool succeeded = QueryProductDependencyByProductId(productID,
|
|
[&](ProductDependencyDatabaseEntry& entry)
|
|
{
|
|
found = true;
|
|
container.push_back();
|
|
container.back() = AZStd::move(entry);
|
|
return true; // return true to keep iterating over further rows.
|
|
});
|
|
return found && succeeded;
|
|
}
|
|
|
|
bool AssetDatabaseConnection::GetDirectProductDependencies(AZ::s64 productID, AzToolsFramework::AssetDatabase::ProductDatabaseEntryContainer& container)
|
|
{
|
|
bool found = false;
|
|
bool succeeded = QueryDirectProductDependencies(productID,
|
|
[&](ProductDatabaseEntry& entry)
|
|
{
|
|
found = true;
|
|
container.push_back();
|
|
container.back() = AZStd::move(entry);
|
|
return true; // return true to keep iterating over further rows.
|
|
});
|
|
return found && succeeded;
|
|
}
|
|
|
|
bool AssetDatabaseConnection::GetDirectReverseProductDependenciesBySourceGuidSubId(AZ::Uuid dependencySourceGuid, AZ::u32 dependencySubId, AzToolsFramework::AssetDatabase::ProductDatabaseEntryContainer& container)
|
|
{
|
|
bool found = false;
|
|
bool succeeded = QueryDirectReverseProductDependenciesBySourceGuidSubId(dependencySourceGuid, dependencySubId,
|
|
[&](ProductDatabaseEntry& entry)
|
|
{
|
|
found = true;
|
|
container.push_back();
|
|
container.back() = AZStd::move(entry);
|
|
return true;
|
|
});
|
|
return found && succeeded;
|
|
}
|
|
|
|
bool AssetDatabaseConnection::GetAllProductDependencies(AZ::s64 productID, AzToolsFramework::AssetDatabase::ProductDatabaseEntryContainer& container)
|
|
{
|
|
bool found = false;
|
|
bool succeeded = QueryAllProductDependencies(productID,
|
|
[&](ProductDatabaseEntry& entry)
|
|
{
|
|
found = true;
|
|
container.push_back();
|
|
container.back() = AZStd::move(entry);
|
|
return true; // return true to keep iterating over further rows.
|
|
});
|
|
return found && succeeded;
|
|
}
|
|
|
|
|
|
bool AssetDatabaseConnection::GetUnresolvedProductDependencies(AzToolsFramework::AssetDatabase::ProductDependencyDatabaseEntryContainer& container)
|
|
{
|
|
bool found = false;
|
|
bool succeeded = QueryUnresolvedProductDependencies(
|
|
[&](ProductDependencyDatabaseEntry& entry)
|
|
{
|
|
found = true;
|
|
container.push_back();
|
|
container.back() = AZStd::move(entry);
|
|
return true; // return true to keep iterating over further rows.
|
|
});
|
|
return found && succeeded;
|
|
}
|
|
|
|
bool AssetDatabaseConnection::SetProductDependency(ProductDependencyDatabaseEntry& entry)
|
|
{
|
|
if (entry.m_productDependencyID == InvalidEntryId)
|
|
{
|
|
//they didn't set an id, add to database
|
|
|
|
//make sure its not already in the database
|
|
ProductDependencyDatabaseEntryContainer existingProductDependencies;
|
|
if (GetProductDependenciesByProductID(entry.m_productPK, existingProductDependencies))
|
|
{
|
|
for (const auto& existingProductDependency : existingProductDependencies)
|
|
{
|
|
if (existingProductDependency == entry)
|
|
{
|
|
//this product already exists
|
|
entry.m_productDependencyID = existingProductDependency.m_productDependencyID;
|
|
return true;
|
|
}
|
|
}
|
|
}
|
|
|
|
if (!s_InsertProductDependencyQuery.BindAndStep(*m_databaseConnection, entry.m_productPK, entry.m_dependencySourceGuid, entry.m_dependencySubID, entry.m_dependencyFlags.to_ullong(), entry.m_platform.c_str(), entry.m_unresolvedPath.c_str(), entry.m_dependencyType, entry.m_fromAssetId))
|
|
{
|
|
return false;
|
|
}
|
|
|
|
//now read it from the database
|
|
existingProductDependencies.clear();
|
|
if (GetProductDependenciesByProductID(entry.m_productPK, existingProductDependencies))
|
|
{
|
|
for (const auto& existingProductDependency : existingProductDependencies)
|
|
{
|
|
if (existingProductDependency == entry)
|
|
{
|
|
entry.m_productDependencyID = existingProductDependency.m_productDependencyID;
|
|
return true;
|
|
}
|
|
}
|
|
}
|
|
|
|
return false;
|
|
}
|
|
else
|
|
{
|
|
//they supplied an id, see if it exists in the database
|
|
ProductDependencyDatabaseEntry existingEntry;
|
|
if (!GetProductDependencyByProductDependencyID(entry.m_productDependencyID, existingEntry))
|
|
{
|
|
AZ_Error(
|
|
LOG_NAME,
|
|
false,
|
|
"Failed to read and update the product dependency with ID %d for product key %d from the database.",
|
|
entry.m_productDependencyID,
|
|
entry.m_productPK);
|
|
return false;
|
|
}
|
|
|
|
//if the product is now different update it
|
|
if (existingEntry == entry)
|
|
{
|
|
return true;
|
|
}
|
|
|
|
return s_UpdateProductDependencyQuery.BindAndStep(*m_databaseConnection, entry.m_productPK, entry.m_dependencySourceGuid, entry.m_dependencySubID, entry.m_dependencyFlags.to_ullong(), entry.m_platform.c_str(), entry.m_unresolvedPath.c_str(), entry.m_productDependencyID, entry.m_dependencyType, entry.m_fromAssetId);
|
|
}
|
|
}
|
|
|
|
bool AssetDatabaseConnection::SetMissingProductDependency(AzToolsFramework::AssetDatabase::MissingProductDependencyDatabaseEntry& entry)
|
|
{
|
|
if (entry.m_missingProductDependencyId == InvalidEntryId)
|
|
{
|
|
// make sure its not already in the database
|
|
MissingProductDependencyDatabaseEntryContainer existingMissingProductDependencies;
|
|
if (GetMissingProductDependenciesByProductId(entry.m_productPK, existingMissingProductDependencies))
|
|
{
|
|
for (const auto& existingMissingProductDependency : existingMissingProductDependencies)
|
|
{
|
|
if (existingMissingProductDependency == entry)
|
|
{
|
|
// this missing dependency is already in the database
|
|
entry.m_missingProductDependencyId = existingMissingProductDependency.m_missingProductDependencyId;
|
|
return true;
|
|
}
|
|
}
|
|
}
|
|
|
|
// Add the new missing dependency to the database
|
|
if (!s_InsertMissingProductDependencyQuery.BindAndStep(
|
|
*m_databaseConnection,
|
|
entry.m_productPK,
|
|
entry.m_scannerId.c_str(),
|
|
entry.m_scannerVersion.c_str(),
|
|
entry.m_sourceFileFingerprint.c_str(),
|
|
entry.m_dependencySourceGuid,
|
|
entry.m_dependencySubId,
|
|
entry.m_missingDependencyString.c_str(),
|
|
entry.m_lastScanTime.c_str(),
|
|
entry.m_scanTimeSecondsSinceEpoch))
|
|
{
|
|
return false;
|
|
}
|
|
|
|
// Read it from the database to get the ID, and to verify it was written correctly.
|
|
existingMissingProductDependencies.clear();
|
|
if (GetMissingProductDependenciesByProductId(entry.m_productPK, existingMissingProductDependencies))
|
|
{
|
|
for (const auto& existingMissingProductDependency : existingMissingProductDependencies)
|
|
{
|
|
if (existingMissingProductDependency == entry)
|
|
{
|
|
entry.m_missingProductDependencyId = existingMissingProductDependency.m_missingProductDependencyId;
|
|
return true;
|
|
}
|
|
}
|
|
}
|
|
return false;
|
|
}
|
|
else
|
|
{
|
|
// An ID was supplied, see if it's already in the database
|
|
MissingProductDependencyDatabaseEntry existingEntry;
|
|
if (!GetMissingProductDependencyByMissingProductDependencyId(entry.m_missingProductDependencyId, existingEntry))
|
|
{
|
|
AZ_Error(
|
|
LOG_NAME,
|
|
false,
|
|
"Failed to read and update the missing product dependency with ID %d for product key %d from the database.",
|
|
entry.m_missingProductDependencyId,
|
|
entry.m_productPK);
|
|
return false;
|
|
}
|
|
|
|
// if the entry in the database matches what was passed in, there's nothing else that needs to be done
|
|
if (existingEntry == entry)
|
|
{
|
|
return true;
|
|
}
|
|
|
|
// Update the entry in the database
|
|
return s_UpdateMissingProductDependencyQuery.BindAndStep(
|
|
*m_databaseConnection,
|
|
entry.m_missingProductDependencyId,
|
|
entry.m_productPK,
|
|
entry.m_scannerId.c_str(),
|
|
entry.m_scannerVersion.c_str(),
|
|
entry.m_sourceFileFingerprint.c_str(),
|
|
entry.m_dependencySourceGuid,
|
|
entry.m_dependencySubId,
|
|
entry.m_missingDependencyString.c_str(),
|
|
entry.m_lastScanTime.c_str(),
|
|
entry.m_scanTimeSecondsSinceEpoch);
|
|
}
|
|
|
|
}
|
|
|
|
bool AssetDatabaseConnection::GetMissingProductDependenciesByProductId(AZ::s64 productId, AzToolsFramework::AssetDatabase::MissingProductDependencyDatabaseEntryContainer& container)
|
|
{
|
|
bool found = false;
|
|
bool succeeded = QueryMissingProductDependencyByProductId(productId,
|
|
[&](MissingProductDependencyDatabaseEntry& entry)
|
|
{
|
|
found = true;
|
|
container.push_back();
|
|
container.back() = AZStd::move(entry);
|
|
return true; // return true to keep iterating over further rows.
|
|
});
|
|
return found && succeeded;
|
|
}
|
|
|
|
bool AssetDatabaseConnection::GetMissingProductDependencyByMissingProductDependencyId(AZ::s64 missingProductDependencyId, AzToolsFramework::AssetDatabase::MissingProductDependencyDatabaseEntry& missingProductDependencyEntry)
|
|
{
|
|
bool found = false;
|
|
QueryMissingProductDependencyByMissingProductDependencyId(missingProductDependencyId,
|
|
[&](MissingProductDependencyDatabaseEntry& entry)
|
|
{
|
|
found = true;
|
|
missingProductDependencyEntry = AZStd::move(entry);
|
|
return false; // stop after the first result
|
|
});
|
|
return found;
|
|
}
|
|
|
|
bool AssetDatabaseConnection::UpdateProductDependencies(AzToolsFramework::AssetDatabase::ProductDependencyDatabaseEntryContainer& container)
|
|
{
|
|
ScopedTransaction transaction(m_databaseConnection);
|
|
|
|
for(auto& entry : container)
|
|
{
|
|
if(!SetProductDependency(entry))
|
|
{
|
|
return false;
|
|
}
|
|
}
|
|
|
|
transaction.Commit();
|
|
return true;
|
|
}
|
|
|
|
bool AssetDatabaseConnection::SetProductDependencies(const ProductDependencyDatabaseEntryContainer& container)
|
|
{
|
|
// first, collect all unique ProductPKs:
|
|
ScopedTransaction transaction(m_databaseConnection);
|
|
|
|
AZStd::unordered_set<AZ::s64> uniqueProductIds;
|
|
for (const ProductDependencyDatabaseEntry& item : container)
|
|
{
|
|
uniqueProductIds.insert(item.m_productPK);
|
|
}
|
|
|
|
// unordered set eliminates dupes
|
|
for (AZ::s64 productId : uniqueProductIds)
|
|
{
|
|
if (!RemoveProductDependencyByProductId(productId))
|
|
{
|
|
return false; // auto rollback will occur
|
|
}
|
|
}
|
|
|
|
// now insert the new ones since we know there's no collisions:
|
|
|
|
for (auto& entry : container)
|
|
{
|
|
|
|
if (!s_InsertProductDependencyQuery.BindAndStep(*m_databaseConnection, entry.m_productPK, entry.m_dependencySourceGuid, entry.m_dependencySubID, entry.m_dependencyFlags.to_ullong(), entry.m_platform.c_str(), entry.m_unresolvedPath.c_str(), entry.m_dependencyType, entry.m_fromAssetId))
|
|
{
|
|
return false;
|
|
}
|
|
}
|
|
|
|
transaction.Commit();
|
|
return true;
|
|
}
|
|
|
|
bool AssetDatabaseConnection::RemoveProductDependencyByProductId(AZ::s64 productID)
|
|
{
|
|
ScopedTransaction transaction(m_databaseConnection);
|
|
|
|
if (!s_DeleteProductDependencyByProductIdQuery.BindAndStep(*m_databaseConnection, productID))
|
|
{
|
|
return false;
|
|
}
|
|
|
|
transaction.Commit();
|
|
|
|
return true;
|
|
}
|
|
|
|
bool AssetDatabaseConnection::GetFileByFileID(AZ::s64 fileID, FileDatabaseEntry& entry)
|
|
{
|
|
bool found = false;
|
|
bool succeeded = QueryFileByFileID(fileID,
|
|
[&](FileDatabaseEntry& file)
|
|
{
|
|
found = true;
|
|
entry = AZStd::move(file);
|
|
return false;//one
|
|
});
|
|
return found && succeeded;
|
|
}
|
|
|
|
bool AssetDatabaseConnection::GetFileByFileNameAndScanFolderId(QString fileName, AZ::s64 scanFolderId, FileDatabaseEntry& entry)
|
|
{
|
|
bool found = false;
|
|
bool succeeded = QueryFilesByFileNameAndScanFolderID(AssetUtilities::NormalizeFilePath(fileName).toUtf8().constData(), scanFolderId,
|
|
[&](FileDatabaseEntry& file)
|
|
{
|
|
found = true;
|
|
entry = AZStd::move(file);
|
|
return false;//one
|
|
});
|
|
return found && succeeded;
|
|
}
|
|
|
|
bool AssetDatabaseConnection::GetFilesLikeFileName(QString likeFileName, LikeType likeType, FileDatabaseEntryContainer& container)
|
|
{
|
|
bool found = false;
|
|
bool succeeded = QueryFilesLikeFileName(likeFileName.toUtf8().constData(), likeType,
|
|
[&](FileDatabaseEntry& file)
|
|
{
|
|
found = true;
|
|
container.push_back(file);
|
|
return true;//all
|
|
});
|
|
return found && succeeded;
|
|
}
|
|
|
|
bool AssetDatabaseConnection::InsertFiles(FileDatabaseEntryContainer& entries)
|
|
{
|
|
ScopedTransaction transaction(m_databaseConnection);
|
|
|
|
for (auto& entry : entries)
|
|
{
|
|
StatementAutoFinalizer autoFinal;
|
|
|
|
if (!s_InsertFileQuery.Bind(*m_databaseConnection, autoFinal, entry.m_scanFolderPK, entry.m_fileName.c_str(), static_cast<AZ::s64>(entry.m_isFolder), entry.m_modTime, entry.m_hash))
|
|
{
|
|
return false;
|
|
}
|
|
|
|
Statement* statement = autoFinal.Get();
|
|
|
|
if (statement->Step() == Statement::SqlError)
|
|
{
|
|
AZ_Warning(LOG_NAME, false, "Failed to write the new source into the database. %s", entry.m_fileName.c_str());
|
|
return false;
|
|
}
|
|
|
|
//now that its in the database get the id
|
|
AZ::s64 rowID = m_databaseConnection->GetLastRowID();
|
|
entry.m_fileID = rowID;
|
|
}
|
|
|
|
transaction.Commit();
|
|
|
|
return true;
|
|
}
|
|
|
|
bool AssetDatabaseConnection::InsertFile(FileDatabaseEntry& entry, bool& entryAlreadyExists)
|
|
{
|
|
entryAlreadyExists = false;
|
|
|
|
//they didn't supply an id, add to database
|
|
if (entry.m_fileID == InvalidEntryId)
|
|
{
|
|
//first make sure its not already in the database
|
|
FileDatabaseEntry existingEntry;
|
|
if (GetFileByFileNameAndScanFolderId(entry.m_fileName.c_str(), entry.m_scanFolderPK, existingEntry))
|
|
{
|
|
entry.m_fileID = existingEntry.m_fileID;
|
|
return UpdateFile(entry, entryAlreadyExists); // now update the existing field
|
|
}
|
|
StatementAutoFinalizer autoFinal;
|
|
|
|
if (!s_InsertFileQuery.Bind(*m_databaseConnection, autoFinal, entry.m_scanFolderPK, entry.m_fileName.c_str(), static_cast<AZ::s64>(entry.m_isFolder), entry.m_modTime, entry.m_hash))
|
|
{
|
|
return false;
|
|
}
|
|
|
|
Statement* statement = autoFinal.Get();
|
|
|
|
if (statement->Step() == Statement::SqlError)
|
|
{
|
|
AZ_Warning(LOG_NAME, false, "Failed to write the new source into the database. %s", entry.m_fileName.c_str());
|
|
return false;
|
|
}
|
|
|
|
//now that its in the database get the id
|
|
AZ::s64 rowID = m_databaseConnection->GetLastRowID();
|
|
entry.m_fileID = rowID;
|
|
|
|
return true;
|
|
}
|
|
|
|
return UpdateFile(entry, entryAlreadyExists);
|
|
}
|
|
|
|
bool AssetDatabaseConnection::UpdateFile(FileDatabaseEntry& entry, bool& entryAlreadyExists)
|
|
{
|
|
entryAlreadyExists = false;
|
|
|
|
//they supplied an id, see if it exists in the database
|
|
FileDatabaseEntry existingEntry;
|
|
if (!GetFileByFileID(entry.m_fileID, existingEntry))
|
|
{
|
|
//they supplied an id but is not in the database!
|
|
AZ_Error(LOG_NAME, false, "Failed to write the file into the database.");
|
|
return false;
|
|
}
|
|
|
|
// don't bother updating the database if all fields are equal.
|
|
// note that we already looked it up by source ID
|
|
if ((existingEntry.m_scanFolderPK == entry.m_scanFolderPK) &&
|
|
(existingEntry.m_fileName == entry.m_fileName) &&
|
|
(existingEntry.m_isFolder == entry.m_isFolder) &&
|
|
(existingEntry.m_modTime == entry.m_modTime))
|
|
{
|
|
entryAlreadyExists = true;
|
|
|
|
return true;
|
|
}
|
|
|
|
StatementAutoFinalizer autoFinal;
|
|
if (!s_UpdateFileQuery.BindAndStep(*m_databaseConnection, entry.m_scanFolderPK, entry.m_fileName.c_str(), entry.m_isFolder, entry.m_modTime, entry.m_hash, entry.m_fileID))
|
|
{
|
|
return false;
|
|
}
|
|
|
|
return true;
|
|
}
|
|
|
|
bool AssetDatabaseConnection::UpdateFileModTimeAndHashByFileNameAndScanFolderId(QString fileName, AZ::s64 scanFolderId, AZ::u64 modTime, AZ::u64 hash)
|
|
{
|
|
if(!s_UpdateFileModtimeByFileNameScanFolderIdQuery.BindAndStep(*m_databaseConnection, modTime, hash, fileName.toUtf8().constData(), scanFolderId))
|
|
{
|
|
return false;
|
|
}
|
|
|
|
return m_databaseConnection->GetNumAffectedRows() > 0;
|
|
}
|
|
|
|
bool AssetDatabaseConnection::RemoveFile(AZ::s64 fileID)
|
|
{
|
|
return s_DeleteFileQuery.BindAndStep(*m_databaseConnection, fileID);
|
|
}
|
|
|
|
bool AssetDatabaseConnection::SetBuilderInfoTable(AzToolsFramework::AssetDatabase::BuilderInfoEntryContainer& newEntries)
|
|
{
|
|
ScopedTransaction transaction(m_databaseConnection);
|
|
if (!m_databaseConnection->ExecuteOneOffStatement(CLEAR_BUILDERINFO_TABLE))
|
|
{
|
|
return false;
|
|
}
|
|
|
|
for (AzToolsFramework::AssetDatabase::BuilderInfoEntry &entry : newEntries)
|
|
{
|
|
if (!s_InsertBuilderInfoQuery.BindAndStep(*m_databaseConnection, entry.m_builderUuid, entry.m_analysisFingerprint.c_str()))
|
|
{
|
|
return false;
|
|
}
|
|
// update the entry to have the applied ID.
|
|
entry.m_builderInfoID = m_databaseConnection->GetLastRowID();
|
|
}
|
|
|
|
transaction.Commit();
|
|
return true;
|
|
}
|
|
|
|
}//namespace AssetProcessor
|
|
|