AssetDatabase.cpp 160 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281128212831284128512861287128812891290129112921293129412951296129712981299130013011302130313041305130613071308130913101311131213131314131513161317131813191320132113221323132413251326132713281329133013311332133313341335133613371338133913401341134213431344134513461347134813491350135113521353135413551356135713581359136013611362136313641365136613671368136913701371137213731374137513761377137813791380138113821383138413851386138713881389139013911392139313941395139613971398139914001401140214031404140514061407140814091410141114121413141414151416141714181419142014211422142314241425142614271428142914301431143214331434143514361437143814391440144114421443144414451446144714481449145014511452145314541455145614571458145914601461146214631464146514661467146814691470147114721473147414751476147714781479148014811482148314841485148614871488148914901491149214931494149514961497149814991500150115021503150415051506150715081509151015111512151315141515151615171518151915201521152215231524152515261527152815291530153115321533153415351536153715381539154015411542154315441545154615471548154915501551155215531554155515561557155815591560156115621563156415651566156715681569157015711572157315741575157615771578157915801581158215831584158515861587158815891590159115921593159415951596159715981599160016011602160316041605160616071608160916101611161216131614161516161617161816191620162116221623162416251626162716281629163016311632163316341635163616371638163916401641164216431644164516461647164816491650165116521653165416551656165716581659166016611662166316641665166616671668166916701671167216731674167516761677167816791680168116821683168416851686168716881689169016911692169316941695169616971698169917001701170217031704170517061707170817091710171117121713171417151716171717181719172017211722172317241725172617271728172917301731173217331734173517361737173817391740174117421743174417451746174717481749175017511752175317541755175617571758175917601761176217631764176517661767176817691770177117721773177417751776177717781779178017811782178317841785178617871788178917901791179217931794179517961797179817991800180118021803180418051806180718081809181018111812181318141815181618171818181918201821182218231824182518261827182818291830183118321833183418351836183718381839184018411842184318441845184618471848184918501851185218531854185518561857185818591860186118621863186418651866186718681869187018711872187318741875187618771878187918801881188218831884188518861887188818891890189118921893189418951896189718981899190019011902190319041905190619071908190919101911191219131914191519161917191819191920192119221923192419251926192719281929193019311932193319341935193619371938193919401941194219431944194519461947194819491950195119521953195419551956195719581959196019611962196319641965196619671968196919701971197219731974197519761977197819791980198119821983198419851986198719881989199019911992199319941995199619971998199920002001200220032004200520062007200820092010201120122013201420152016201720182019202020212022202320242025202620272028202920302031203220332034203520362037203820392040204120422043204420452046204720482049205020512052205320542055205620572058205920602061206220632064206520662067206820692070207120722073207420752076207720782079208020812082208320842085208620872088208920902091209220932094209520962097209820992100210121022103210421052106210721082109211021112112211321142115211621172118211921202121212221232124212521262127212821292130213121322133213421352136213721382139214021412142214321442145214621472148214921502151215221532154215521562157215821592160216121622163216421652166216721682169217021712172217321742175217621772178217921802181218221832184218521862187218821892190219121922193219421952196219721982199220022012202220322042205220622072208220922102211221222132214221522162217221822192220222122222223222422252226222722282229223022312232223322342235223622372238223922402241224222432244224522462247224822492250225122522253225422552256225722582259226022612262226322642265226622672268226922702271227222732274227522762277227822792280228122822283228422852286228722882289229022912292229322942295229622972298229923002301230223032304230523062307230823092310231123122313231423152316231723182319232023212322232323242325232623272328232923302331233223332334233523362337233823392340234123422343234423452346234723482349235023512352235323542355235623572358235923602361236223632364236523662367236823692370237123722373237423752376237723782379238023812382238323842385238623872388238923902391239223932394239523962397239823992400240124022403240424052406240724082409241024112412241324142415241624172418241924202421242224232424242524262427242824292430243124322433243424352436243724382439244024412442244324442445244624472448244924502451245224532454245524562457245824592460246124622463246424652466246724682469247024712472247324742475247624772478247924802481248224832484248524862487248824892490249124922493249424952496249724982499250025012502250325042505250625072508250925102511251225132514251525162517251825192520252125222523252425252526252725282529253025312532253325342535253625372538253925402541254225432544254525462547254825492550255125522553255425552556255725582559256025612562256325642565256625672568256925702571257225732574257525762577257825792580258125822583258425852586258725882589259025912592259325942595259625972598259926002601260226032604260526062607260826092610261126122613261426152616261726182619262026212622262326242625262626272628262926302631263226332634263526362637263826392640264126422643264426452646264726482649265026512652265326542655265626572658265926602661266226632664266526662667266826692670267126722673267426752676267726782679268026812682268326842685268626872688268926902691269226932694269526962697269826992700270127022703270427052706270727082709271027112712271327142715271627172718271927202721272227232724272527262727272827292730273127322733273427352736273727382739274027412742274327442745274627472748274927502751275227532754275527562757275827592760276127622763276427652766276727682769277027712772277327742775277627772778277927802781278227832784278527862787278827892790279127922793279427952796279727982799280028012802280328042805280628072808280928102811281228132814281528162817281828192820282128222823282428252826282728282829283028312832283328342835283628372838283928402841284228432844284528462847284828492850285128522853285428552856285728582859286028612862286328642865286628672868286928702871287228732874287528762877287828792880288128822883288428852886288728882889289028912892289328942895289628972898289929002901290229032904290529062907290829092910291129122913291429152916291729182919292029212922292329242925292629272928292929302931293229332934293529362937293829392940294129422943294429452946294729482949295029512952295329542955295629572958295929602961296229632964296529662967296829692970297129722973297429752976297729782979298029812982298329842985298629872988298929902991299229932994299529962997299829993000300130023003300430053006300730083009301030113012301330143015301630173018301930203021302230233024302530263027302830293030303130323033303430353036303730383039304030413042304330443045304630473048304930503051305230533054305530563057305830593060306130623063306430653066306730683069307030713072307330743075307630773078307930803081308230833084308530863087308830893090309130923093309430953096309730983099310031013102310331043105310631073108310931103111311231133114311531163117311831193120312131223123312431253126312731283129313031313132313331343135313631373138313931403141314231433144314531463147314831493150315131523153315431553156315731583159316031613162316331643165316631673168316931703171317231733174317531763177317831793180318131823183318431853186318731883189319031913192319331943195319631973198319932003201320232033204320532063207320832093210321132123213321432153216321732183219322032213222322332243225322632273228322932303231323232333234323532363237323832393240324132423243324432453246324732483249325032513252325332543255325632573258325932603261326232633264326532663267326832693270327132723273327432753276327732783279328032813282328332843285328632873288328932903291329232933294329532963297329832993300330133023303330433053306330733083309331033113312331333143315331633173318331933203321332233233324332533263327332833293330333133323333333433353336333733383339334033413342334333443345334633473348334933503351335233533354335533563357335833593360336133623363336433653366336733683369337033713372337333743375337633773378337933803381338233833384338533863387338833893390339133923393339433953396339733983399340034013402340334043405340634073408340934103411341234133414341534163417341834193420342134223423342434253426342734283429343034313432343334343435343634373438343934403441344234433444344534463447344834493450345134523453345434553456345734583459346034613462346334643465346634673468346934703471347234733474347534763477347834793480348134823483348434853486348734883489349034913492349334943495349634973498349935003501
  1. /*
  2. * Copyright (c) Contributors to the Open 3D Engine Project.
  3. * For complete copyright and license terms please see the LICENSE at the root of this distribution.
  4. *
  5. * SPDX-License-Identifier: Apache-2.0 OR MIT
  6. *
  7. */
  8. #include "AssetDatabase.h"
  9. #include <AzCore/IO/SystemFile.h>
  10. #include <AzToolsFramework/API/AssetDatabaseBus.h>
  11. #include <AzToolsFramework/SQLite/SQLiteQuery.h>
  12. #include <native/utilities/assetUtils.h>
  13. #include <sqlite3.h>
  14. namespace AssetProcessor
  15. {
  16. using namespace AzToolsFramework;
  17. using namespace AzToolsFramework::AssetSystem;
  18. using namespace AzToolsFramework::AssetDatabase;
  19. using namespace AzToolsFramework::SQLite;
  20. //tack on the namespace to avoid statement name collisions
  21. namespace
  22. {
  23. static const char* LOG_NAME = "AssetProcessor";
  24. //////////////////////////////////////////////////////////////////////////
  25. //tables
  26. static const char* CREATE_DATABASE_INFOTABLE = "AssetProcessor::CreateDatabaseInfoTable";
  27. static const char* CREATE_DATABASE_INFOTABLE_STATEMENT =
  28. "CREATE TABLE IF NOT EXISTS dbinfo( "
  29. " rowID INTEGER PRIMARY KEY, "
  30. " version INTEGER NOT NULL);";
  31. static const char* CREATE_SCANFOLDERS_TABLE = "AssetProcessor::CreateScanFoldersTable";
  32. static const char* CREATE_SCANFOLDERS_TABLE_STATEMENT =
  33. "CREATE TABLE IF NOT EXISTS ScanFolders( "
  34. " ScanFolderID INTEGER PRIMARY KEY AUTOINCREMENT, "
  35. " ScanFolder TEXT NOT NULL collate nocase, "
  36. " DisplayName TEXT NOT NULL collate nocase, "
  37. " PortableKey TEXT NOT NULL collate nocase, "
  38. " IsRoot INTEGER NOT NULL);";
  39. static const char* CREATE_SOURCES_TABLE = "AssetProcessor::CreateSourceTable";
  40. static const char* CREATE_SOURCES_TABLE_STATEMENT =
  41. "CREATE TABLE IF NOT EXISTS Sources("
  42. " SourceID INTEGER PRIMARY KEY AUTOINCREMENT, "
  43. " ScanFolderPK INTEGER NOT NULL, "
  44. " SourceName TEXT NOT NULL collate nocase, "
  45. " SourceGuid BLOB NOT NULL, "
  46. " AnalysisFingerprint TEXT default('') collate nocase, "
  47. " FOREIGN KEY (ScanFolderPK) REFERENCES "
  48. " ScanFolders(ScanFolderID) ON DELETE CASCADE);";
  49. static const char* CREATE_JOBS_TABLE = "AssetProcessor::CreateJobsTable";
  50. static const char* CREATE_JOBS_TABLE_STATEMENT =
  51. "CREATE TABLE IF NOT EXISTS Jobs("
  52. " JobID INTEGER PRIMARY KEY AUTOINCREMENT, "
  53. " SourcePK INTEGER NOT NULL, "
  54. " JobKey TEXT NOT NULL collate nocase, "
  55. " Fingerprint INTEGER NOT NULL, "
  56. " Platform TEXT NOT NULL collate nocase, "
  57. " BuilderGuid BLOB NOT NULL, "
  58. " Status INTEGER NOT NULL, "
  59. " JobRunKey INTEGER NOT NULL, "
  60. " FailureCauseSourcePK INTEGER, "
  61. " FailureCauseFingerprint INTEGER, "
  62. " FirstFailLogTime INTEGER NOT NULL, "
  63. " FirstFailLogFile TEXT collate nocase, "
  64. " LastFailLogTime INTEGER NOT NULL, "
  65. " LastFailLogFile TEXT collate nocase, "
  66. " LastLogTime INTEGER NOT NULL, "
  67. " LastLogFile TEXT collate nocase, "
  68. " ErrorCount INTEGER NOT NULL, "
  69. " WarningCount INTEGER NOT NULL, "
  70. " FOREIGN KEY (SourcePK) REFERENCES "
  71. " Sources(SourceID) ON DELETE CASCADE);";
  72. static const char* CREATEINDEX_JOBS_JOBRUNKEY = "AssetProcesser::CreateIndexJobsJobRunKey";
  73. static const char* CREATEINDEX_JOBS_JOBRUNKEY_STATEMENT =
  74. "CREATE INDEX IF NOT EXISTS Jobs_JobRunKey ON Jobs (JobRunKey);";
  75. static const char* CREATEINDEX_JOBS_JOBKEY = "AssetProcesser::CreateIndexJobsJobKey";
  76. static const char* CREATEINDEX_JOBS_JOBKEY_STATEMENT =
  77. "CREATE INDEX IF NOT EXISTS Jobs_JobKey ON Jobs (JobKey);";
  78. static const char* CREATE_PRODUCT_TABLE = "AssetProcessor::CreateProductTable";
  79. static const char* CREATE_PRODUCT_TABLE_STATEMENT =
  80. "CREATE TABLE IF NOT EXISTS Products( "
  81. " ProductID INTEGER PRIMARY KEY AUTOINCREMENT, "
  82. " JobPK INTEGER NOT NULL, "
  83. " ProductName TEXT NOT NULL collate nocase, "
  84. " SubID INTEGER NOT NULL, "
  85. " AssetType BLOB NOT NULL, "
  86. " LegacyGuid BLOB NOT NULL, "
  87. " Hash INTEGER NOT NULL, "
  88. " Flags INTEGER NOT NULL DEFAULT 1, "
  89. " FOREIGN KEY (JobPK) REFERENCES "
  90. " Jobs(JobID) ON DELETE CASCADE);";
  91. static const char* CREATE_LEGACYSUBIDS_TABLE = "AssetProcessor::CreateLegacySubIDsTable";
  92. static const char* CREATE_LEGACYSUBIDS_TABLE_STATEMENT =
  93. "CREATE TABLE IF NOT EXISTS LegacySubIDs( "
  94. " LegacySubID INTEGER PRIMARY KEY, "
  95. " ProductPK INTEGER NOT NULL, "
  96. " SubID INTEGER NOT NULL, "
  97. " FOREIGN KEY(ProductPK) REFERENCES "
  98. " Products(ProductID) ON DELETE CASCADE);";
  99. static const char* CREATEINDEX_LEGACYSUBIDS_PRODUCTPK = "AssetProcesser::CreateIndexLegacySubIDs_ProductPK";
  100. static const char* CREATEINDEX_LEGACYSUBIDS_PRODUCTPK_STATEMENT =
  101. "CREATE INDEX IF NOT EXISTS LegacySubIDs_ProductPK ON LegacySubIDs (ProductPK);";
  102. static const char* CREATE_SOURCE_DEPENDENCY_TABLE = "AssetProcessor::CreateSourceDependencyTable";
  103. static const char* CREATE_SOURCE_DEPENDENCY_TABLE_STATEMENT =
  104. "CREATE TABLE IF NOT EXISTS SourceDependency("
  105. " SourceDependencyID INTEGER PRIMARY KEY AUTOINCREMENT, "
  106. " BuilderGuid BLOB NOT NULL, "
  107. " SourceGuid BLOB NOT NULL, "
  108. " DependsOnSource TEXT NOT NULL collate nocase, "
  109. " SubIds TEXT NOT NULL collate nocase, "
  110. " TypeOfDependency INTEGER NOT NULL DEFAULT 0,"
  111. " FromAssetId INTEGER NOT NULL DEFAULT 0 "
  112. "); ";
  113. static const char* CREATE_PRODUCT_DEPENDENCY_TABLE = "AssetProcessor::CreateProductDependencyTable";
  114. static const char* CREATE_PRODUCT_DEPENDENCY_TABLE_STATEMENT =
  115. "CREATE TABLE IF NOT EXISTS ProductDependencies("
  116. " ProductDependencyID INTEGER PRIMARY KEY AUTOINCREMENT, "
  117. " ProductPK INTEGER NOT NULL, "
  118. " DependencySourceGuid BLOB NOT NULL, "
  119. " DependencySubID INTEGER NOT NULL, "
  120. " Platform TEXT NOT NULL collate nocase, "
  121. " DependencyFlags INTEGER NOT NULL, "
  122. " UnresolvedPath TEXT NOT NULL collate nocase, "
  123. " UnresolvedDependencyType INTEGER NOT NULL DEFAULT 0, "
  124. " FromAssetId INTEGER NOT NULL DEFAULT 0, "
  125. " FOREIGN KEY (ProductPK) REFERENCES "
  126. " Products(ProductID) ON DELETE CASCADE);";
  127. static const char* CREATE_MISSING_PRODUCT_DEPENDENCY_TABLE = "AssetProcessor::CreateMissingProductDependencyTable";
  128. static const char* CREATE_MISSING_PRODUCT_DEPENDENCY_TABLE_STATEMENT =
  129. "CREATE TABLE IF NOT EXISTS MissingProductDependencies("
  130. " MissingProductDependencyId INTEGER PRIMARY KEY AUTOINCREMENT, "
  131. " ProductPK INTEGER NOT NULL, "
  132. " ScannerId TEXT NOT NULL, "
  133. " ScannerVersion TEXT NOT NULL, "
  134. " SourceFileFingerprint TEXT NOT NULL, "
  135. " DependencySourceGuid BLOB NOT NULL, "
  136. " DependencySubId INTEGER, "
  137. " MissingDependencyString TEXT NOT NULL, "
  138. " LastScanTime TEXT, "
  139. " ScanTimeSecondsSinceEpoch INTEGER, "
  140. " FOREIGN KEY (ProductPK) REFERENCES "
  141. " Products(ProductID) ON DELETE CASCADE);";
  142. static const char* CREATEINDEX_MISSINGPRODUCTDEPENDENCY_PRODUCTPK =
  143. "AssetProcessor::CreateIndexMissingProductDependencies_ProductPK";
  144. static const char* CREATEINDEX_MISSINGPRODUCTDEPENDENCY_PRODUCTPK_STATEMENT =
  145. "CREATE INDEX IF NOT EXISTS MissingProductDependencies_ProductPK ON MissingProductDependencies (ProductPK);";
  146. static const char* CREATE_FILES_TABLE = "AssetProcessor::CreateFilesTable";
  147. static const char* CREATE_FILES_TABLE_STATEMENT =
  148. "CREATE TABLE IF NOT EXISTS Files( "
  149. " FileID INTEGER PRIMARY KEY AUTOINCREMENT, "
  150. " ScanFolderPK INTEGER NOT NULL, "
  151. " FileName TEXT NOT NULL collate nocase, "
  152. " IsFolder INTEGER NOT NULL, "
  153. " ModTime INTEGER NOT NULL, "
  154. " Hash INTEGER NOT NULL, "
  155. " FOREIGN KEY (ScanFolderPK) REFERENCES "
  156. " ScanFolders(ScanFolderID) ON DELETE CASCADE);";
  157. static const char* CREATE_STATS_TABLE = "AssetProcessor::CreateStatsTable";
  158. static const char* CREATE_STATS_TABLE_STATEMENT =
  159. "CREATE TABLE IF NOT EXISTS Stats( "
  160. " StatName TEXT PRIMARY KEY collate nocase, "
  161. " StatValue INTEGER NOT NULL, "
  162. " LastLogTime INTEGER NOT NULL "
  163. ");";
  164. //////////////////////////////////////////////////////////////////////////
  165. //indices
  166. static const char* CREATEINDEX_DEPENDSONSOURCE_SOURCEDEPENDENCY = "AssetProcesser::CreateIndexDependsOnSource_SourceDependency";
  167. static const char* CREATEINDEX_DEPENDSONSOURCE_SOURCEDEPENDENCY_STATEMENT =
  168. "CREATE INDEX IF NOT EXISTS DependsOnSource_SourceDependency ON SourceDependency (DependsOnSource);";
  169. static const char* CREATEINDEX_BUILDERGUID_SOURCE_SOURCEDEPENDENCY = "AssetProcesser::CreateIndexBuilderGuid_Source_SourceDependency";
  170. static const char* CREATEINDEX_BUILDERGUID_SOURCE_SOURCEDEPENDENCY_STATEMENT =
  171. "CREATE INDEX IF NOT EXISTS BuilderGuid_Source_SourceDependency ON SourceDependency (BuilderGuid, SourceGuid);";
  172. static const char* CREATEINDEX_TYPEOFDEPENDENCY_SOURCEDEPENDENCY = "AssetProcessor::CreateIndexTypeOfDependency_SourceDependency";
  173. static const char* CREATEINDEX_TYPEOFDEPENDENCY_SOURCEDEPENDENCY_STATEMENT =
  174. "CREATE INDEX IF NOT EXISTS TypeOfDependency_SourceDependency ON SourceDependency (TypeOfDependency);";
  175. static const char* CREATEINDEX_SCANFOLDERS_SOURCES_SCANFOLDER = "AssetProcesser::CreateIndexScanFoldersSourcesScanFolder";
  176. static const char* CREATEINDEX_SCANFOLDERS_SOURCES_SCANFOLDER_STATEMENT =
  177. "CREATE INDEX IF NOT EXISTS IdxSources_SourceAndScanFolder ON Sources (ScanFolderPK, SourceName);";
  178. static const char* CREATEINDEX_SOURCES_JOBS = "AssetProcesser::CreateIndexSourcesJobs";
  179. static const char* CREATEINDEX_SOURCES_JOBS_STATEMENT =
  180. "CREATE INDEX IF NOT EXISTS Sources_Jobs ON Jobs (SourcePK);";
  181. static const char* CREATEINDEX_JOBS_PRODUCTS = "AssetProcesser::CreateIndexJobsProducts";
  182. static const char* CREATEINDEX_JOBS_PRODUCTS_STATEMENT =
  183. "CREATE INDEX IF NOT EXISTS Jobs_Products ON Products (JobPK);";
  184. static const char* CREATEINDEX_SOURCE_NAME = "AssetProcessor::CreateIndexSourceName";
  185. static const char* CREATEINDEX_SOURCE_NAME_STATEMENT =
  186. "CREATE INDEX IF NOT EXISTS Sources_SourceName ON Sources (SourceName);";
  187. static const char* CREATEINDEX_SOURCE_GUID = "AssetProcessor::CreateIndexSourceGuid";
  188. static const char* CREATEINDEX_SOURCE_GUID_STATEMENT =
  189. "CREATE INDEX IF NOT EXISTS Sources_SourceGuid ON Sources (SourceGuid);";
  190. static const char* CREATEINDEX_PRODUCT_NAME = "AssetProcessor::CreateIndexProductName";
  191. static const char* CREATEINDEX_PRODUCT_NAME_STATEMENT =
  192. "CREATE INDEX IF NOT EXISTS Products_ProductName ON Products (ProductName);";
  193. static const char* CREATEINDEX_PRODUCT_SUBID = "AssetProcessor::CreateIndexProductSubID";
  194. static const char* CREATEINDEX_PRODUCT_SUBID_STATEMENT =
  195. "CREATE INDEX IF NOT EXISTS Products_SubID ON Products (SubID);";
  196. static const char* CREATEINDEX_PRODUCTDEPENDENCIES_PRODUCTPK = "AssetProcessor::CreateIndexProductDependenciesProductPK";
  197. static const char* CREATEINDEX_PRODUCTDEPENDENCIES_PRODUCTPK_STATEMENT =
  198. "CREATE INDEX IF NOT EXISTS ProductDependencies_ProductPK ON ProductDependencies (ProductPK);";
  199. static const char* CREATEINDEX_PRODUCTDEPENDENCIES_UNRESOLVEDPATH = "AssetProccessor::CreateIndexProductDependenciesUnresolvedPath";
  200. static const char* CREATEINDEX_PRODUCTDEPENDENCIES_UNRESOLVEDPATH_STATEMENT =
  201. "CREATE INDEX IF NOT EXISTS ProductDependencies_UnresolvedPath ON ProductDependencies (UnresolvedPath);";
  202. static const char* CREATEINDEX_PRODUCTDEPENDENCIES_UNRESOLVEDPATH_WILDCARD = "AssetProccessor::CreateIndexProductDependenciesUnresolvedPathWildcard";
  203. static const char* CREATEINDEX_PRODUCTDEPENDENCIES_UNRESOLVEDPATH_WILDCARD_STATEMENT =
  204. "CREATE INDEX IF NOT EXISTS ProductDependencies_UnresolvedPathWildcard ON ProductDependencies (UnresolvedPath) WHERE UnresolvedPath LIKE \"%*%\"";
  205. static const char* CREATEINDEX_FILE_NAME = "AssetProcessor::CreateIndexFilesName";
  206. static const char* CREATEINDEX_FILE_NAME_STATEMENT =
  207. "CREATE INDEX IF NOT EXISTS Files_FileName ON Files (FileName);";
  208. static const char* CREATEINDEX_SCANFOLDERS_FILES = "AssetProcesser::CreateIndexScanFoldersFiles";
  209. static const char* CREATEINDEX_SCANFOLDERS_FILES_STATEMENT =
  210. "CREATE INDEX IF NOT EXISTS ScanFolders_Files ON Files (ScanFolderPK);";
  211. //////////////////////////////////////////////////////////////////////////
  212. //insert/set/update/delete
  213. static const char* SET_DATABASE_VERSION = "AssetProcessor::SetDatabaseVersion";
  214. static const char* SET_DATABASE_VERSION_STATEMENT =
  215. "INSERT OR REPLACE INTO dbinfo(rowID, version) "
  216. "VALUES (1, :ver);";
  217. static const auto s_SetDatabaseVersionQuery = MakeSqlQuery(SET_DATABASE_VERSION, SET_DATABASE_VERSION_STATEMENT, LOG_NAME,
  218. SqlParam<AZ::s32>(":ver"));
  219. static const char* INSERT_SCANFOLDER = "AssetProcessor::InsertScanFolder";
  220. static const char* INSERT_SCANFOLDER_STATEMENT =
  221. "INSERT INTO ScanFolders (ScanFolder, DisplayName, PortableKey, IsRoot) "
  222. "VALUES (:scanfolder, :displayname, :portablekey, :isroot);";
  223. static const auto s_InsertScanfolderQuery = MakeSqlQuery(INSERT_SCANFOLDER, INSERT_SCANFOLDER_STATEMENT, LOG_NAME,
  224. SqlParam<const char*>(":scanfolder"),
  225. SqlParam<const char*>(":displayname"),
  226. SqlParam<const char*>(":portablekey"),
  227. SqlParam<AZ::s32>(":isroot"));
  228. static const char* UPDATE_SCANFOLDER = "AssetProcessor::UpdateScanFolder";
  229. static const char* UPDATE_SCANFOLDER_STATEMENT =
  230. "UPDATE ScanFolders SET "
  231. "ScanFolder = :scanfolder, "
  232. "DisplayName = :displayname, "
  233. "PortableKey = :portablekey, "
  234. "IsRoot = :isroot "
  235. "WHERE "
  236. "ScanFolderID = :scanfolderid;";
  237. static const auto s_UpdateScanfolderQuery = MakeSqlQuery(UPDATE_SCANFOLDER, UPDATE_SCANFOLDER_STATEMENT, LOG_NAME,
  238. SqlParam<const char*>(":scanfolder"),
  239. SqlParam<const char*>(":displayname"),
  240. SqlParam<const char*>(":portablekey"),
  241. SqlParam<AZ::s32>(":isroot"),
  242. SqlParam<AZ::s64>(":scanfolderid"));
  243. static const char* DELETE_SCANFOLDER = "AssetProcessor::RemoveScanFolder";
  244. static const char* DELETE_SCANFOLDER_STATEMENT =
  245. "DELETE FROM ScanFolders WHERE "
  246. "(ScanFolderID = :scanfolderid);";
  247. static const auto s_DeleteScanfolderQuery = MakeSqlQuery(DELETE_SCANFOLDER, DELETE_SCANFOLDER_STATEMENT, LOG_NAME,
  248. SqlParam<AZ::s64>(":scanfolderid"));
  249. static const char* INSERT_SOURCE = "AssetProcessor::InsertSource";
  250. static const char* INSERT_SOURCE_STATEMENT =
  251. "INSERT INTO Sources (ScanFolderPK, SourceName, SourceGuid, AnalysisFingerprint) "
  252. "VALUES (:scanfolderid, :sourcename, :sourceguid, :analysisFingerprint);";
  253. static const auto s_InsertSourceQuery = MakeSqlQuery(INSERT_SOURCE, INSERT_SOURCE_STATEMENT, LOG_NAME,
  254. SqlParam<AZ::s64>(":scanfolderid"),
  255. SqlParam<const char*>(":sourcename"),
  256. SqlParam<AZ::Uuid>(":sourceguid"),
  257. SqlParam<const char*>(":analysisFingerprint"));
  258. static const char* UPDATE_SOURCE = "AssetProcessor::UpdateSource";
  259. static const char* UPDATE_SOURCE_STATEMENT =
  260. "UPDATE Sources SET "
  261. "ScanFolderPK = :scanfolderpk, "
  262. "SourceName = :sourcename, "
  263. "SourceGuid = :sourceguid, "
  264. "AnalysisFingerprint = :analysisFingerprint "
  265. "WHERE SourceID = :sourceid;";
  266. static const auto s_UpdateSourceQuery = MakeSqlQuery(UPDATE_SOURCE, UPDATE_SOURCE_STATEMENT, LOG_NAME,
  267. SqlParam<AZ::s64>(":scanfolderpk"),
  268. SqlParam<const char*>(":sourcename"),
  269. SqlParam<AZ::Uuid>(":sourceguid"),
  270. SqlParam<AZ::s64>(":sourceid"),
  271. SqlParam<const char*>(":analysisFingerprint"));
  272. static const char* DELETE_SOURCE = "AssetProcessor::DeleteSource";
  273. static const char* DELETE_SOURCE_STATEMENT =
  274. "DELETE FROM Sources WHERE "
  275. "SourceID = :sourceid;";
  276. static const auto s_DeleteSourceQuery = MakeSqlQuery(DELETE_SOURCE, DELETE_SOURCE_STATEMENT, LOG_NAME,
  277. SqlParam<AZ::s64>(":sourceid"));
  278. static const char* DELETE_SOURCE_BY_SCANFOLDERID = "AssetProcessor::DeleteSourceByScanFolderID";
  279. static const char* DELETE_SOURCE_BY_SCANFOLDERID_STATEMENT =
  280. "DELETE FROM Sources WHERE "
  281. "ScanFolderPK = :scanfolderid;";
  282. static const auto s_DeleteSourceByScanfolderidQuery = MakeSqlQuery(DELETE_SOURCE_BY_SCANFOLDERID, DELETE_SOURCE_BY_SCANFOLDERID_STATEMENT, LOG_NAME,
  283. SqlParam<AZ::s64>(":scanfolderid"));
  284. static const char* INVALIDATE_SOURCE_ANALYSISFINGEPRINTS = "AssetProcessor::InvalidateSourceAnalysisFingerprints";
  285. static const char* INVALIDATE_SOURCE_ANALYSISFINGEPRINTS_STATEMENT =
  286. "UPDATE Sources SET AnalysisFingerprint = ''";
  287. static const char* GET_HIGHEST_JOBRUNKEY = "AssetProcessor::GetHighestJobRunKey";
  288. static const char* GET_HIGHEST_JOBRUNKEY_STATEMENT =
  289. "SELECT JobRunKey FROM Jobs ORDER BY JobRunKey DESC LIMIT 1;";
  290. static const auto s_GetHighestJobrunkeyQuery = MakeSqlQuery(GET_HIGHEST_JOBRUNKEY, GET_HIGHEST_JOBRUNKEY_STATEMENT, LOG_NAME);
  291. static const char* INSERT_JOB = "AssetProcessor::InsertJob";
  292. static const char* INSERT_JOB_STATEMENT =
  293. "INSERT INTO Jobs (SourcePK, JobKey, Fingerprint, Platform, BuilderGuid, Status, JobRunKey, FailureCauseSourcePK, FailureCauseFingerprint, FirstFailLogTime, FirstFailLogFile, LastFailLogTime, LastFailLogFile, LastLogTime, LastLogFile, WarningCount, ErrorCount) "
  294. "VALUES (:sourceid, :jobkey, :fingerprint, :platform, :builderguid, :status, :jobrunkey, :failurecausesourcepk, :failurecausefingerprint, :firstfaillogtime, :firstfaillogfile, :lastfaillogtime, :lastfaillogfile, :lastlogtime, :lastlogfile, :warningcount, :errorcount);";
  295. static const auto s_InsertJobQuery = MakeSqlQuery(INSERT_JOB, INSERT_JOB_STATEMENT, LOG_NAME,
  296. SqlParam<AZ::s64>(":sourceid"),
  297. SqlParam<const char*>(":jobkey"),
  298. SqlParam<AZ::u32>(":fingerprint"),
  299. SqlParam<const char*>(":platform"),
  300. SqlParam<AZ::Uuid>(":builderguid"),
  301. SqlParam<AZ::s32>(":status"),
  302. SqlParam<AZ::u64>(":jobrunkey"),
  303. SqlParam<AZ::s64>(":failurecausesourcepk"),
  304. SqlParam<AZ::u32>(":failurecausefingerprint"),
  305. SqlParam<AZ::s64>(":firstfaillogtime"),
  306. SqlParam<const char*>(":firstfaillogfile"),
  307. SqlParam<AZ::s64>(":lastfaillogtime"),
  308. SqlParam<const char*>(":lastfaillogfile"),
  309. SqlParam<AZ::s64>(":lastlogtime"),
  310. SqlParam<const char*>(":lastlogfile"),
  311. SqlParam<AZ::u32>(":warningcount"),
  312. SqlParam<AZ::u32>(":errorcount")
  313. );
  314. static const char* UPDATE_JOB = "AssetProcessor::UpdateJob";
  315. static const char* UPDATE_JOB_STATEMENT =
  316. "UPDATE Jobs SET "
  317. "SourcePK = :sourceid, "
  318. "JobKey = :jobkey, "
  319. "Fingerprint = :fingerprint, "
  320. "Platform = :platform, "
  321. "BuilderGuid = :builderguid, "
  322. "Status = :status, "
  323. "JobRunKey = :jobrunkey, "
  324. "FailureCauseSourcePK = :failurecausesourcepk, "
  325. "FailureCauseFingerprint = :failurecausefingerprint, "
  326. "FirstFailLogTime = :firstfaillogtime, "
  327. "FirstFailLogFile = :firstfaillogfile, "
  328. "LastFailLogTime = :lastfaillogtime, "
  329. "LastFailLogFile = :lastfaillogfile, "
  330. "LastLogTime = :lastlogtime, "
  331. "LastLogFile = :lastlogfile, "
  332. "WarningCount = :warningcount, "
  333. "ErrorCount = :errorcount "
  334. "WHERE JobID = :jobid;";
  335. static const auto s_UpdateJobQuery = MakeSqlQuery(UPDATE_JOB, UPDATE_JOB_STATEMENT, LOG_NAME,
  336. SqlParam<AZ::s64>(":sourceid"),
  337. SqlParam<const char*>(":jobkey"),
  338. SqlParam<AZ::u32>(":fingerprint"),
  339. SqlParam<const char*>(":platform"),
  340. SqlParam<AZ::Uuid>(":builderguid"),
  341. SqlParam<AZ::s32>(":status"),
  342. SqlParam<AZ::u64>(":jobrunkey"),
  343. SqlParam<AZ::s64>(":failurecausesourcepk"),
  344. SqlParam<AZ::u32>(":failurecausefingerprint"),
  345. SqlParam<AZ::s64>(":firstfaillogtime"),
  346. SqlParam<const char*>(":firstfaillogfile"),
  347. SqlParam<AZ::s64>(":lastfaillogtime"),
  348. SqlParam<const char*>(":lastfaillogfile"),
  349. SqlParam<AZ::s64>(":lastlogtime"),
  350. SqlParam<const char*>(":lastlogfile"),
  351. SqlParam<AZ::u32>(":warningcount"),
  352. SqlParam<AZ::u32>(":errorcount"),
  353. SqlParam<AZ::s64>(":jobid")
  354. );
  355. static const char* UPDATE_JOB_FINGERPRINT_BY_SOURCE_ID = "AssetProcessor::SetJobFingerprintsBySourceID";
  356. static const char* UPDATE_JOB_FINGERPRINT_BY_SOURCE_ID_STATEMENT =
  357. "UPDATE Jobs SET "
  358. "Fingerprint = :fingerprint "
  359. "WHERE SourcePK = :sourceid;";
  360. static const auto s_SetJobFingerprintsBySourceIDQuery = MakeSqlQuery(
  361. UPDATE_JOB_FINGERPRINT_BY_SOURCE_ID,
  362. UPDATE_JOB_FINGERPRINT_BY_SOURCE_ID_STATEMENT,
  363. LOG_NAME,
  364. SqlParam<AZ::u64>(":fingerprint"),
  365. SqlParam<AZ::s64>(":sourceid"));
  366. static const char* DELETE_JOB = "AssetProcessor::DeleteJob";
  367. static const char* DELETE_JOB_STATEMENT =
  368. "DELETE FROM Jobs WHERE "
  369. "JobID = :jobid;";
  370. static const auto s_DeleteJobQuery = MakeSqlQuery(DELETE_JOB, DELETE_JOB_STATEMENT, LOG_NAME,
  371. SqlParam<AZ::s64>(":jobid"));
  372. static const char* INSERT_PRODUCT = "AssetProcessor::InsertProduct";
  373. static const char* INSERT_PRODUCT_STATEMENT =
  374. "INSERT INTO Products (JobPK, SubID, ProductName, AssetType, LegacyGuid, Hash, Flags) "
  375. "VALUES (:jobid, :subid, :productname, :assettype, :legacyguid, :hash, :flags);";
  376. static const auto s_InsertProductQuery = MakeSqlQuery(INSERT_PRODUCT, INSERT_PRODUCT_STATEMENT, LOG_NAME,
  377. SqlParam<AZ::s64>(":jobid"),
  378. SqlParam<AZ::u32>(":subid"),
  379. SqlParam<const char*>(":productname"),
  380. SqlParam<AZ::Uuid>(":assettype"),
  381. SqlParam<AZ::Uuid>(":legacyguid"),
  382. SqlParam<AZ::u64>(":hash"),
  383. SqlParam<AZ::u64>(":flags"));
  384. static const char* UPDATE_PRODUCT = "AssetProcessor::UpdateProduct";
  385. static const char* UPDATE_PRODUCT_STATEMENT =
  386. "UPDATE Products SET "
  387. "JobPK = :jobid, "
  388. "SubID = :subid, "
  389. "ProductName = :productname, "
  390. "AssetType = :assettype, "
  391. "LegacyGuid = :legacyguid, "
  392. "Hash = :hash, "
  393. "Flags = :flags "
  394. "WHERE ProductID = :productid;";
  395. static const auto s_UpdateProductQuery = MakeSqlQuery(UPDATE_PRODUCT, UPDATE_PRODUCT_STATEMENT, LOG_NAME,
  396. SqlParam<AZ::s64>(":jobid"),
  397. SqlParam<AZ::u32>(":subid"),
  398. SqlParam<const char*>(":productname"),
  399. SqlParam<AZ::Uuid>(":assettype"),
  400. SqlParam<AZ::Uuid>(":legacyguid"),
  401. SqlParam<AZ::u64>(":flags"),
  402. SqlParam<AZ::s64>(":productid"),
  403. SqlParam<AZ::u64>(":hash"));
  404. static const char* DELETE_PRODUCT = "AssetProcessor::DeleteProduct";
  405. static const char* DELETE_PRODUCT_STATEMENT =
  406. "DELETE FROM Products WHERE "
  407. "ProductID = :productid;";
  408. static const auto s_DeleteProductQuery = MakeSqlQuery(DELETE_PRODUCT, DELETE_PRODUCT_STATEMENT, LOG_NAME,
  409. SqlParam<AZ::s64>(":productid"));
  410. static const char* DELETE_PRODUCTS_BY_JOBID = "AssetProcessor::DeleteAllProductsByJobID";
  411. static const char* DELETE_PRODUCTS_BY_JOBID_STATEMENT =
  412. "DELETE FROM Products WHERE "
  413. "JobPK = :jobid;";
  414. static const auto s_DeleteProductsByJobidQuery = MakeSqlQuery(DELETE_PRODUCTS_BY_JOBID, DELETE_PRODUCTS_BY_JOBID_STATEMENT, LOG_NAME,
  415. SqlParam<AZ::s64>(":jobid"));
  416. static const char* DELETE_PRODUCTS_BY_SOURCEID = "AssetProcessor::DeleteAllProductsBySourceID";
  417. static const char* DELETE_PRODUCTS_BY_SOURCEID_STATEMENT =
  418. "DELETE FROM Products "
  419. "WHERE EXISTS "
  420. "(SELECT * FROM Jobs WHERE "
  421. "Products.JobPK = Jobs.JobID AND "
  422. "Jobs.SourcePK = :sourceid);";
  423. static const auto s_DeleteProductsBySourceidQuery = MakeSqlQuery(DELETE_PRODUCTS_BY_SOURCEID, DELETE_PRODUCTS_BY_SOURCEID_STATEMENT, LOG_NAME,
  424. SqlParam<AZ::s64>(":sourceid"));
  425. static const char* DELETE_PRODUCTS_BY_SOURCEID_PLATFORM = "AssetProcessor::DeleteProductsBySourceIDPlatform";
  426. static const char* DELETE_PRODUCTS_BY_SOURCEID_PLATFORM_STATEMENT =
  427. "DELETE FROM Products "
  428. "WHERE EXISTS "
  429. "(SELECT * FROM Jobs WHERE "
  430. "Products.JobPK = Jobs.JobID AND "
  431. "Jobs.SourcePK = :sourceid AND "
  432. "Jobs.Platform = :platform);";
  433. static const auto s_DeleteProductsBySourceidPlatformQuery = MakeSqlQuery(DELETE_PRODUCTS_BY_SOURCEID_PLATFORM, DELETE_PRODUCTS_BY_SOURCEID_PLATFORM_STATEMENT, LOG_NAME,
  434. SqlParam<AZ::s64>(":sourceid"),
  435. SqlParam<const char*>(":platform"));
  436. static const char* INSERT_SOURCE_DEPENDENCY = "AssetProcessor::InsertSourceDependency";
  437. static const char* INSERT_SOURCE_DEPENDENCY_STATEMENT =
  438. "INSERT INTO SourceDependency (BuilderGuid, SourceGuid, DependsOnSource, TypeOfDependency, FromAssetId, SubIds) "
  439. "VALUES (:builderGuid, :source, :dependsOnSource, :typeofdependency, :fromAssetId, :subIds);";
  440. static const auto s_InsertSourceDependencyQuery = MakeSqlQuery(INSERT_SOURCE_DEPENDENCY, INSERT_SOURCE_DEPENDENCY_STATEMENT, LOG_NAME,
  441. SqlParam<AZ::Uuid>(":builderGuid"),
  442. SqlParam<AZ::Uuid>(":source"),
  443. SqlParam<PathOrUuid>(":dependsOnSource"),
  444. SqlParam<AZ::s32>(":typeofdependency"),
  445. SqlParam<AZ::s32>(":fromAssetId"),
  446. SqlParam<const char*>(":subIds"));
  447. static const char* DELETE_SOURCE_DEPENDENCY_SOURCEDEPENDENCYID = "AssetProcessor::DeleteSourceDependencBySourceDependencyId";
  448. static const char* DELETE_SOURCE_DEPENDENCY_SOURCEDEPENDENCYID_STATEMENT =
  449. "DELETE FROM SourceDependency WHERE "
  450. "SourceDependencyID = :sourceDependencyId;";
  451. static const auto s_DeleteSourceDependencySourcedependencyidQuery = MakeSqlQuery(DELETE_SOURCE_DEPENDENCY_SOURCEDEPENDENCYID, DELETE_SOURCE_DEPENDENCY_SOURCEDEPENDENCYID_STATEMENT, LOG_NAME,
  452. SqlParam<AZ::s64>(":sourceDependencyId"));
  453. static const char* INSERT_NEW_LEGACYSUBID = "AssetProcessor::InsertLegacySubID";
  454. static const char* INSERT_NEW_LEGACYSUBID_STATEMENT =
  455. "INSERT INTO LegacySubIDs (ProductPK, SubID) "
  456. "VALUES (:productPK, :subID);";
  457. static const auto s_InsertNewLegacysubidQuery = MakeSqlQuery(INSERT_NEW_LEGACYSUBID, INSERT_NEW_LEGACYSUBID_STATEMENT, LOG_NAME,
  458. SqlParam<AZ::s64>(":productPK"),
  459. SqlParam<AZ::u32>(":subID"));
  460. static const char* OVERWRITE_EXISTING_LEGACYSUBID = "AssetProcessor::OverwriteLegacySubID";
  461. static const char* OVERWRITE_EXISTING_LEGACYSUBID_STATEMENT =
  462. "UPDATE LegacySubIDs "
  463. " SET "
  464. " ProductPK = :productPK, "
  465. " SubID = :subID "
  466. " WHERE "
  467. " LegacySubID = :legacySubID;";
  468. static const auto s_OverwriteExistingLegacysubidQuery = MakeSqlQuery(OVERWRITE_EXISTING_LEGACYSUBID, OVERWRITE_EXISTING_LEGACYSUBID_STATEMENT, LOG_NAME,
  469. SqlParam<AZ::s64>(":productPK"),
  470. SqlParam<AZ::u32>(":subID"),
  471. SqlParam<AZ::s64>(":legacySubID"));
  472. static const char* DELETE_LEGACYSUBIDS_BY_PRIMARY_KEY = "AssetProcessor::DeleteLegacySubIDsByPrimaryKey";
  473. static const char* DELETE_LEGACYSUBIDS_BY_PRIMARY_KEY_STATEMENT =
  474. "DELETE FROM LegacySubIDs WHERE "
  475. "LegacySubID = :legacySubID;";
  476. static const auto s_DeleteLegacysubidsByPrimaryKeyQuery = MakeSqlQuery(DELETE_LEGACYSUBIDS_BY_PRIMARY_KEY, DELETE_LEGACYSUBIDS_BY_PRIMARY_KEY_STATEMENT, LOG_NAME,
  477. SqlParam<AZ::s64>(":legacySubID"));
  478. static const char* DELETE_LEGACYSUBIDS_BY_PRODUCTID = "AssetProcessor::DeleteLegacySubIDsByProductID";
  479. static const char* DELETE_LEGACYSUBIDS_BY_PRODUCTID_STATEMENT =
  480. "DELETE FROM LegacySubIDs WHERE "
  481. "ProductPK = :productPK;";
  482. static const auto s_DeleteLegacysubidsByProductidQuery = MakeSqlQuery(DELETE_LEGACYSUBIDS_BY_PRODUCTID, DELETE_LEGACYSUBIDS_BY_PRODUCTID_STATEMENT, LOG_NAME,
  483. SqlParam<AZ::s64>(":productPK"));
  484. static const char* INSERT_PRODUCT_DEPENDENCY = "AssetProcessor::InsertProductDependency";
  485. static const char* INSERT_PRODUCT_DEPENDENCY_STATEMENT =
  486. "INSERT INTO ProductDependencies (ProductPK, DependencySourceGuid, DependencySubID, DependencyFlags, Platform, UnresolvedPath, UnresolvedDependencyType, FromAssetId) "
  487. "VALUES (:productPK, :dependencySourceGuid, :dependencySubID, :dependencyFlags, :platform, :unresolvedPath, :typeofdependency, :fromAssetId);";
  488. static const auto s_InsertProductDependencyQuery = MakeSqlQuery(INSERT_PRODUCT_DEPENDENCY, INSERT_PRODUCT_DEPENDENCY_STATEMENT, LOG_NAME,
  489. SqlParam<AZ::s64>(":productPK"),
  490. SqlParam<AZ::Uuid>(":dependencySourceGuid"),
  491. SqlParam<AZ::u32>(":dependencySubID"),
  492. SqlParam<AZ::s64>(":dependencyFlags"),
  493. SqlParam<const char*>(":platform"),
  494. SqlParam<const char*>(":unresolvedPath"),
  495. SqlParam<AZ::u32>(":typeofdependency"),
  496. SqlParam<AZ::u32>(":fromAssetId"));
  497. static const char* UPDATE_PRODUCT_DEPENDENCY = "AssetProcessor::UpdateProductDependency";
  498. static const char* UPDATE_PRODUCT_DEPENDENCY_STATEMENT =
  499. "UPDATE ProductDependencies SET "
  500. "ProductPK = :productPK, "
  501. "DependencySourceGuid = :dependencySourceGuid, "
  502. "DependencySubID = :dependencySubID, "
  503. "DependencyFlags = :dependencyFlags, "
  504. "Platform = :platform, "
  505. "UnresolvedPath = :unresolvedPath, "
  506. "UnresolvedDependencyType = :typeofdependency, "
  507. "FromAssetId = :fromAssetId WHERE "
  508. "ProductDependencyID = :productDependencyID;";
  509. static const auto s_UpdateProductDependencyQuery = MakeSqlQuery(UPDATE_PRODUCT_DEPENDENCY, UPDATE_PRODUCT_DEPENDENCY_STATEMENT, LOG_NAME,
  510. SqlParam<AZ::s64>(":productPK"),
  511. SqlParam<AZ::Uuid>(":dependencySourceGuid"),
  512. SqlParam<AZ::u32>(":dependencySubID"),
  513. SqlParam<AZ::u64>(":dependencyFlags"),
  514. SqlParam<const char*>(":platform"),
  515. SqlParam<const char *>(":unresolvedPath"),
  516. SqlParam<AZ::s64>(":productDependencyID"),
  517. SqlParam<AZ::u32>(":typeofdependency"),
  518. SqlParam<AZ::u32>(":fromAssetId"));
  519. static const char* DELETE_PRODUCT_DEPENDENCY_BY_PRODUCTID = "AssetProcessor::DeleteProductDependencyByProductId";
  520. static const char* DELETE_PRODUCT_DEPENDENCY_BY_PRODUCTID_STATEMENT =
  521. "DELETE FROM ProductDependencies WHERE "
  522. "ProductPK = :productpk;";
  523. static const auto s_DeleteProductDependencyByProductIdQuery = MakeSqlQuery(DELETE_PRODUCT_DEPENDENCY_BY_PRODUCTID, DELETE_PRODUCT_DEPENDENCY_BY_PRODUCTID_STATEMENT, LOG_NAME,
  524. SqlParam<AZ::s64>(":productpk"));
  525. static const char* INSERT_MISSING_PRODUCT_DEPENDENCY = "AssetProcessor::InsertMissingProductDependency";
  526. static const char* INSERT_MISSING_PRODUCT_DEPENDENCY_STATEMENT =
  527. "INSERT INTO MissingProductDependencies (ProductPK, ScannerId, ScannerVersion, SourceFileFingerprint, DependencySourceGuid, DependencySubId, MissingDependencyString, LastScanTime, ScanTimeSecondsSinceEpoch) "
  528. "VALUES (:productPK, :scannerId, :scannerVersion, :sourceFileFingerprint, :dependencySourceGuid, :dependencySubId, :missingDependencyString, :lastScanTime, :scanTimeSecondsSinceEpoch);";
  529. static const char* DELETE_MISSING_PRODUCT_DEPENDENCY_BY_PRODUCTID = "AssetProcessor::DeleteMissingProductDependencyByProductId";
  530. static const char* DELETE_MISSING_PRODUCT_DEPENDENCY_BY_PRODUCTID_STATEMENT =
  531. "DELETE FROM MissingProductDependencies WHERE "
  532. "ProductPK = :productpk;";
  533. static const char* UPDATE_MISSING_PRODUCT_DEPENDENCY = "AssetProcessor::UpdateMissingProductDependency";
  534. static const char* UPDATE_MISSING_PRODUCT_DEPENDENCY_STATEMENT =
  535. "UPDATE MissingProductDependencies SET "
  536. "ProductPK = :productPK, "
  537. "ScannerId = :scannerId, "
  538. "ScannerVersion = :scannerVersion, "
  539. "SourceFileFingerprint = :sourceFileFingerprint, "
  540. "DependencySourceGuid = :dependencySourceGuid, "
  541. "DependencySubId = :dependencySubId, "
  542. "MissingDependencyString = :missingDependencyString, "
  543. "LastScanTime = :lastScanTime, "
  544. "ScanTimeSecondsSinceEpoch = :scanTimeSecondsSinceEpoch WHERE "
  545. "MissingProductDependencyId = :missingProductDependencyId;";
  546. static const auto s_InsertMissingProductDependencyQuery = MakeSqlQuery(INSERT_MISSING_PRODUCT_DEPENDENCY, INSERT_MISSING_PRODUCT_DEPENDENCY_STATEMENT, LOG_NAME,
  547. SqlParam<AZ::s64>(":productPK"),
  548. SqlParam<const char*>(":scannerId"),
  549. SqlParam<const char*>(":scannerVersion"),
  550. SqlParam<const char*>(":sourceFileFingerprint"),
  551. SqlParam<AZ::Uuid>(":dependencySourceGuid"),
  552. SqlParam<AZ::u32>(":dependencySubId"),
  553. SqlParam<const char*>(":missingDependencyString"),
  554. SqlParam<const char*>(":lastScanTime"),
  555. SqlParam<AZ::u64>(":scanTimeSecondsSinceEpoch"));
  556. static const auto s_UpdateMissingProductDependencyQuery = MakeSqlQuery(UPDATE_MISSING_PRODUCT_DEPENDENCY, UPDATE_MISSING_PRODUCT_DEPENDENCY_STATEMENT, LOG_NAME,
  557. SqlParam<AZ::s64>(":missingProductDependencyId"),
  558. SqlParam<AZ::s64>(":productPK"),
  559. SqlParam<const char*>(":scannerId"),
  560. SqlParam<const char*>(":scannerVersion"),
  561. SqlParam<const char*>(":sourceFileFingerprint"),
  562. SqlParam<AZ::Uuid>(":dependencySourceGuid"),
  563. SqlParam<AZ::u32>(":dependencySubId"),
  564. SqlParam<const char*>(":missingDependencyString"),
  565. SqlParam<const char*>(":lastScanTime"),
  566. SqlParam<AZ::u64>(":scanTimeSecondsSinceEpoch"));
  567. static const auto s_DeleteMissingProductDependencyByProductIdQuery = MakeSqlQuery(
  568. DELETE_MISSING_PRODUCT_DEPENDENCY_BY_PRODUCTID,
  569. DELETE_MISSING_PRODUCT_DEPENDENCY_BY_PRODUCTID_STATEMENT,
  570. LOG_NAME,
  571. SqlParam<AZ::s64>(":productpk"));
  572. static const char* DELETE_AUTO_SUCCEED_JOBS = "AssetProcessor::DeleteAutoSucceedJobs";
  573. static const char* DELETE_AUTO_SUCCEED_JOBS_STATEMENT =
  574. "DELETE FROM Jobs WHERE JobKey LIKE 'CreateJobs_success_'";
  575. static const char* CREATE_BUILDERINFO_TABLE = "AssetProcessor::CreateBuilderInfoTable";
  576. static const char* CREATE_BUILDERINFO_TABLE_STATEMENT =
  577. "CREATE TABLE IF NOT EXISTS BuilderInfo( "
  578. " BuilderID INTEGER PRIMARY KEY AUTOINCREMENT, "
  579. " Guid BLOB NOT NULL, "
  580. " AnalysisFingerprint TEXT default('') collate nocase);";
  581. static const char* CLEAR_BUILDERINFO_TABLE = "AssetProcessor::ClearBuilderInfoTable";
  582. static const char* CLEAR_BUILDERINFO_TABLE_STATEMENT = "DELETE FROM BuilderInfo;";
  583. static const char* INSERT_BUILDERINFO = "AssetProcessor::InsertBuilderInfo";
  584. static const char* INSERT_BUILDERINFO_STATEMENT =
  585. "INSERT INTO BuilderInfo (Guid, AnalysisFingerprint) "
  586. "VALUES (:guid, :analysisFingerprint);";
  587. static const auto s_InsertBuilderInfoQuery = MakeSqlQuery(INSERT_BUILDERINFO, INSERT_BUILDERINFO_STATEMENT, LOG_NAME,
  588. SqlParam<AZ::Uuid>(":guid"),
  589. SqlParam<const char*>(":analysisFingerprint"));
  590. static const char* INSERT_COLUMN_ANALYSISFINGERPRINT = "AssetProcessor::AddColumnAnalysisFingerprint";
  591. static const char* INSERT_COLUMN_ANALYSISFINGERPRINT_STATEMENT =
  592. "ALTER TABLE Sources "
  593. "ADD AnalysisFingerprint TEXT NOT NULL collate nocase default('');";
  594. static const char* INSERT_COLUMN_SOURCEDEPENDENCY_TYPEOFDEPENDENCY = "AssetProcessor::AddSourceDependency_TypeOfDependency";
  595. static const char* INSERT_COLUMN_SOURCEDEPENDENCY_TYPEOFDEPENDENCY_STATEMENT =
  596. "ALTER TABLE SourceDependency "
  597. "ADD TypeOfDependency INTEGER NOT NULL DEFAULT 0;";
  598. static const char* INSERT_COLUMN_FILE_MODTIME = "AssetProcessor::AddFiles_ModTime";
  599. static const char* INSERT_COLUMN_FILE_MODTIME_STATEMENT =
  600. "ALTER TABLE Files "
  601. "ADD ModTime INTEGER NOT NULL DEFAULT 0;";
  602. static const char* INSERT_COLUMN_FILE_HASH = "AssetProcessor::AddFiles_Hash";
  603. static const char* INSERT_COLUMN_FILE_HASH_STATEMENT =
  604. "ALTER TABLE Files "
  605. "ADD Hash INTEGER NOT NULL DEFAULT 0;";
  606. static const char* INSERT_COLUMN_PRODUCTDEPENDENCY_UNRESOLVEDPATH = "AssetProcessor::AddProductDependency_UnresolvedPath";
  607. static const char* INSERT_COLUMN_PRODUCTDEPENDENCY_UNRESOLVEDPATH_STATEMENT =
  608. "ALTER TABLE ProductDependencies "
  609. "ADD UnresolvedPath TEXT NOT NULL collate nocase default('');";
  610. static const char* INSERT_COLUMN_PRODUCTDEPENDENCY_TYPEOFDEPENDENCY = "AssetProcessor::AddProductDependency_TypeOfDependency";
  611. static const char* INSERT_COLUMN_PRODUCTDEPENDENCY_TYPEOFDEPENDENCY_STATEMENT =
  612. "ALTER TABLE ProductDependencies "
  613. "ADD UnresolvedDependencyType INTEGER NOT NULL DEFAULT 0;";
  614. static const char* INSERT_COLUMN_PRODUCTDEPENDENCY_PLATFORM = "AssetProcessor::AddProductDependency_Platform";
  615. static const char* INSERT_COLUMN_PRODUCTDEPENDENCY_PLATFORM_STATEMENT =
  616. "ALTER TABLE ProductDependencies "
  617. "ADD Platform TEXT NOT NULL collate nocase default('');";
  618. static const char* INSERT_COLUMNS_JOB_WARNING_COUNT = "AssetProcessor::AddJobs_WarningCount";
  619. static const char* INSERT_COLUMNS_JOB_WARNING_COUNT_STATEMENT =
  620. "ALTER TABLE Jobs "
  621. "ADD WarningCount INTEGER NOT NULL DEFAULT 0; "
  622. ;
  623. static const char* INSERT_COLUMNS_JOB_ERROR_COUNT = "AssetProcessor::AddJobs_ErrorCount";
  624. static const char* INSERT_COLUMNS_JOB_ERROR_COUNT_STATEMENT =
  625. "ALTER TABLE Jobs "
  626. "ADD ErrorCount INTEGER NOT NULL DEFAULT 0;"
  627. ;
  628. static const char* INSERT_COLUMNS_SOURCEDEPENDENCY_FROM_ASSETID = "AssetProcessor::AddSourceDependencies_FromAssetId";
  629. static const char* INSERT_COLUMNS_SOURCEDEPENDENCY_FROM_ASSETID_STATEMENT =
  630. "ALTER TABLE SourceDependency "
  631. "ADD FromAssetId INTEGER NOT NULL DEFAULT 0; "
  632. ;
  633. static const char* INSERT_COLUMNS_PRODUCTDEPENDENCY_FROM_ASSETID = "AssetProcessor::AddProductDependencies_FromAssetId";
  634. static const char* INSERT_COLUMNS_PRODUCTDEPENDENCY_FROM_ASSETID_STATEMENT =
  635. "ALTER TABLE ProductDependencies "
  636. "ADD FromAssetId INTEGER NOT NULL DEFAULT 0; "
  637. ;
  638. static const char* INSERT_COLUMN_LAST_SCAN = "AssetProcessor::AddMissingProductDependencies_LastScanTime";
  639. static const char* INSERT_COLUMN_LAST_SCAN_STATEMENT =
  640. "ALTER TABLE MissingProductDependencies "
  641. "ADD LastScanTime TEXT;";
  642. static const char* INSERT_COLUMN_SCAN_TIME_SECONDS_SINCE_EPOCH = "AssetProcessor::AddMissingProductDependencies_ScanTimeSecondsSinceEpoch";
  643. static const char* INSERT_COLUMN_SCAN_TIME_SECONDS_SINCE_EPOCH_STATEMENT =
  644. "ALTER TABLE MissingProductDependencies "
  645. "ADD ScanTimeSecondsSinceEpoch INTEGER;";
  646. static const char* INSERT_FILE = "AssetProcessor::InsertFile";
  647. static const char* INSERT_FILE_STATEMENT =
  648. "INSERT INTO Files (ScanFolderPK, FileName, IsFolder, ModTime, Hash) "
  649. "VALUES (:scanfolderpk, :filename, :isfolder, :modtime, :hash);";
  650. static const auto s_InsertFileQuery = MakeSqlQuery(INSERT_FILE, INSERT_FILE_STATEMENT, LOG_NAME,
  651. SqlParam<AZ::s64>(":scanfolderpk"),
  652. SqlParam<const char*>(":filename"),
  653. SqlParam<AZ::s64>(":isfolder"),
  654. SqlParam<AZ::u64>(":modtime"),
  655. SqlParam<AZ::u64>(":hash"));
  656. static const char* UPDATE_FILE = "AssetProcessor::UpdateFile";
  657. static const char* UPDATE_FILE_STATEMENT =
  658. "UPDATE Files SET "
  659. "ScanFolderPK = :scanfolderpk, "
  660. "FileName = :filename, "
  661. "IsFolder = :isfolder, "
  662. "ModTime = :modtime, "
  663. "Hash = :hash "
  664. "WHERE FileID = :fileid;";
  665. static const auto s_UpdateFileQuery = MakeSqlQuery(UPDATE_FILE, UPDATE_FILE_STATEMENT, LOG_NAME,
  666. SqlParam<AZ::s64>(":scanfolderpk"),
  667. SqlParam<const char*>(":filename"),
  668. SqlParam<AZ::s64>(":isfolder"),
  669. SqlParam<AZ::u64>(":modtime"),
  670. SqlParam<AZ::u64>(":hash"),
  671. SqlParam<AZ::s64>(":fileid"));
  672. static const char* UPDATE_FILE_MODTIME_AND_HASH_BY_FILENAME_SCANFOLDER_ID = "AssetProcessor::UpdateFileModtimeAndHashByFileNameScanFolderId";
  673. static const char* UPDATE_FILE_MODTIME_AND_HASH_BY_FILENAME_SCANFOLDER_ID_STATEMENT =
  674. "UPDATE Files SET "
  675. "ModTime = :modtime, "
  676. "Hash = :hash "
  677. "WHERE FileName = :filename "
  678. "AND ScanFolderPK = :scanfolderpk;";
  679. 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,
  680. SqlParam<AZ::u64>(":modtime"),
  681. SqlParam<AZ::u64>(":hash"),
  682. SqlParam<const char*>(":filename"),
  683. SqlParam<AZ::s64>(":scanfolderpk"));
  684. static const char* UPDATE_FILE_HASH_BY_FILENAME_SCANFOLDER_ID = "AssetProcessor::UpdateFileHashByFileNameScanFolderId";
  685. static const char* UPDATE_FILE_HASH_BY_FILENAME_SCANFOLDER_ID_STATEMENT =
  686. "UPDATE Files SET "
  687. "Hash = :hash "
  688. "WHERE FileName = :filename "
  689. "AND ScanFolderPK = :scanfolderpk;";
  690. static const auto s_UpdateFileHashByFileNameScanFolderIdQuery = MakeSqlQuery(
  691. UPDATE_FILE_HASH_BY_FILENAME_SCANFOLDER_ID,
  692. UPDATE_FILE_HASH_BY_FILENAME_SCANFOLDER_ID_STATEMENT,
  693. LOG_NAME,
  694. SqlParam<AZ::u64>(":hash"),
  695. SqlParam<const char*>(":filename"),
  696. SqlParam<AZ::s64>(":scanfolderpk"));
  697. static const char* DELETE_FILE = "AssetProcessor::DeleteFile";
  698. static const char* DELETE_FILE_STATEMENT =
  699. "DELETE FROM Files WHERE "
  700. "FileID = :fileid;";
  701. static const auto s_DeleteFileQuery = MakeSqlQuery(DELETE_FILE, DELETE_FILE_STATEMENT, LOG_NAME,
  702. SqlParam<AZ::s64>(":fileid"));
  703. static const char* REPLACE_STAT = "AssetProcessor::ReplaceStat";
  704. static const char* REPLACE_STAT_STATEMENT = "REPLACE INTO Stats VALUES (:statname, :statvalue, :lastlogtime);";
  705. static const auto s_ReplaceStatQuery = MakeSqlQuery(
  706. REPLACE_STAT,
  707. REPLACE_STAT_STATEMENT,
  708. LOG_NAME,
  709. SqlParam<const char*>(":statname"),
  710. SqlParam<AZ::s64>(":statvalue"),
  711. SqlParam<AZ::s64>(":lastlogtime"));
  712. static const char* CREATEINDEX_SOURCEDEPENDENCY_SOURCE = "AssetProcesser::CreateIndexSourceSourceDependency";
  713. static const char* CREATEINDEX_SOURCEDEPENDENCY_SOURCE_STATEMENT =
  714. "CREATE INDEX IF NOT EXISTS Source_SourceDependency ON SourceDependency (Source);";
  715. static const char* DROPINDEX_BUILDERGUID_SOURCE_SOURCEDEPENDENCY = "AssetProcesser::DropIndexBuilderGuid_Source_SourceDependency";
  716. static const char* DROPINDEX_BUILDERGUID_SOURCE_SOURCEDEPENDENCY_STATEMENT =
  717. "DROP INDEX IF EXISTS BuilderGuid_Source_SourceDependency;";
  718. static const char* INSERT_COLUMN_PRODUCT_HASH = "AssetProcessor::InsertColumnsProductsHash";
  719. static const char* INSERT_COLUMN_PRODUCT_HASH_STATEMENT =
  720. "ALTER TABLE PRODUCTS "
  721. "ADD Hash INTEGER NOT NULL DEFAULT 0;";
  722. static const char* INSERT_COLUMN_SOURCEDEPENDENCY_SUBIDS = "AssetProcessor::InsertColumnsSourceDependenciesSubIds";
  723. static const char* INSERT_COLUMN_SOURCEDEPENDENCY_SUBIDS_STATEMENT =
  724. "ALTER TABLE SourceDependency "
  725. "ADD SubIds TEXT NOT NULL collate nocase default('');";
  726. static const char* INSERT_COLUMN_PRODUCTS_FLAGS = "AssetProcessor::InsertColumnProductsFlags";
  727. static const char* INSERT_COLUMN_PRODUCTS_FLAGS_STATEMENT =
  728. "ALTER TABLE Products "
  729. "ADD Flags INTEGER NOT NULL DEFAULT 1;";
  730. static const char* CREATEINDEX_SOURCEDEPENDENCY_SOURCEGUID = "AssetProcessor::CreateIndexSourceGuidSourceDependency";
  731. static const char* CREATEINDEX_SOURCEDEPENDENCY_SOURCEGUID_STATEMENT =
  732. "CREATE INDEX IF NOT EXISTS SourceGuid_SourceDependency ON SourceDependency (SourceGuid);";
  733. static const char* INSERT_COLUMN_JOBS_FAILURECAUSESOURCEID = "AssetProcessor::InsertColumnJobsFailureCauseSourceId";
  734. static const char* INSERT_COLUMN_JOBS_FAILURECAUSESOURCEID_STATEMENT =
  735. "ALTER TABLE Jobs "
  736. "ADD FailureCauseSourcePK INTEGER;";
  737. static const char* INSERT_COLUMN_JOBS_FAILURECAUSEFINGERPRINT = "AssetProcessor::InsertColumnJobsFailureCauseFingerprint";
  738. static const char* INSERT_COLUMN_JOBS_FAILURECAUSEFINGERPRINT_STATEMENT =
  739. "ALTER TABLE Jobs "
  740. "Add FailureCauseFingerprint INTEGER;";
  741. }
  742. AssetDatabaseConnection::AssetDatabaseConnection()
  743. {
  744. qRegisterMetaType<ScanFolderDatabaseEntry>("ScanFolderEntry");
  745. qRegisterMetaType<SourceDatabaseEntry>("SourceEntry");
  746. qRegisterMetaType<JobDatabaseEntry>("JobDatabaseEntry");
  747. qRegisterMetaType<ProductDatabaseEntry>("ProductEntry");
  748. qRegisterMetaType<CombinedDatabaseEntry>("CombinedEntry");
  749. qRegisterMetaType<SourceDatabaseEntryContainer>("SourceEntryContainer");
  750. qRegisterMetaType<JobDatabaseEntryContainer>("JobDatabaseEntryContainer");
  751. qRegisterMetaType<ProductDatabaseEntryContainer>("ProductEntryContainer");
  752. qRegisterMetaType<CombinedDatabaseEntryContainer>("CombinedEntryContainer");
  753. }
  754. AssetDatabaseConnection::~AssetDatabaseConnection()
  755. {
  756. CloseDatabase();
  757. }
  758. bool AssetDatabaseConnection::DataExists()
  759. {
  760. AZStd::string dbFilePath = GetAssetDatabaseFilePath();
  761. return AZ::IO::SystemFile::Exists(dbFilePath.c_str());
  762. }
  763. void AssetDatabaseConnection::LoadData()
  764. {
  765. if ((!m_databaseConnection) || (!m_databaseConnection->IsOpen()))
  766. {
  767. OpenDatabase();
  768. }
  769. }
  770. void AssetDatabaseConnection::ClearData()
  771. {
  772. if ((m_databaseConnection) && (m_databaseConnection->IsOpen()))
  773. {
  774. CloseDatabase();
  775. }
  776. AZStd::string dbFilePath = GetAssetDatabaseFilePath();
  777. AZ::IO::SystemFile::Delete(dbFilePath.c_str());
  778. OpenDatabase();
  779. }
  780. bool AssetDatabaseConnection::PostOpenDatabase(bool ignoreFutureAssetDBVersionError)
  781. {
  782. DatabaseVersion foundVersion = DatabaseVersion::DatabaseDoesNotExist;
  783. if (m_databaseConnection->DoesTableExist("dbinfo"))
  784. {
  785. foundVersion = QueryDatabaseVersion();
  786. }
  787. bool dropAllTables = true;
  788. // 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:
  789. if (foundVersion > CurrentDatabaseVersion())
  790. {
  791. if (!ignoreFutureAssetDBVersionError)
  792. {
  793. AZ_Error(
  794. AssetProcessor::ConsoleChannel,
  795. false,
  796. "The database in the Cache folder appears to be from a NEWER version of Asset Processor than this one.\n"
  797. "To prevent loss of data in the cache for the newer version, this Asset Processor will close.\n");
  798. return false;
  799. }
  800. else
  801. {
  802. // This will erase the Asset Database. A future version can't be fully resolved,
  803. // so if the flag is set to ignore the error, this will erase the Asset Database and create a new one at the current version.
  804. // This flag should only be used with automated builds that use the same asset cache across builds of different branches.
  805. // This should not be used for individual builds. If an individual finds themselves running into this issue often, the team should
  806. // examine their workflows to determine why that individual frequently encounters future Asset Database versions.
  807. AZ_TracePrintf(
  808. AssetProcessor::ConsoleChannel,
  809. "The Asset Database in the Cache folder is from a newer version of the Asset Processor (%i) than this one (expected: %i).\n"
  810. "The existing Asset Database will be deleted and a new Asset Database will be constructed.\n",
  811. foundVersion,
  812. CurrentDatabaseVersion()
  813. );
  814. dropAllTables = true;
  815. }
  816. }
  817. if (foundVersion == DatabaseVersion::AddedOutputPrefixToScanFolders)
  818. {
  819. // execute statements to upgrade the database
  820. if (m_databaseConnection->ExecuteOneOffStatement(CREATEINDEX_JOBS_JOBKEY))
  821. {
  822. foundVersion = DatabaseVersion::AddedJobKeyIndex;
  823. AZ_TracePrintf(AssetProcessor::ConsoleChannel, "Upgraded Asset Database to version %i (AddedJobKeyIndex)\n", foundVersion)
  824. }
  825. }
  826. // over here, check the version number, and perform upgrading if you need to
  827. if (foundVersion == DatabaseVersion::AddedJobKeyIndex)
  828. {
  829. if (
  830. (m_databaseConnection->ExecuteOneOffStatement(CREATEINDEX_SOURCE_GUID)) &&
  831. (m_databaseConnection->ExecuteOneOffStatement(CREATEINDEX_SCANFOLDERS_SOURCES_SCANFOLDER))
  832. )
  833. {
  834. foundVersion = DatabaseVersion::AddedSourceGuidIndex;
  835. AZ_TracePrintf(AssetProcessor::ConsoleChannel, "Upgraded Asset Database to version %i (AddedSourceGuidIndex)\n", foundVersion)
  836. }
  837. }
  838. if (foundVersion == DatabaseVersion::AddedSourceGuidIndex)
  839. {
  840. if (
  841. (m_databaseConnection->ExecuteOneOffStatement(CREATE_SOURCE_DEPENDENCY_TABLE)) &&
  842. (m_databaseConnection->ExecuteOneOffStatement(CREATEINDEX_DEPENDSONSOURCE_SOURCEDEPENDENCY)) &&
  843. (m_databaseConnection->ExecuteOneOffStatement(CREATEINDEX_BUILDERGUID_SOURCE_SOURCEDEPENDENCY))
  844. )
  845. {
  846. foundVersion = DatabaseVersion::AddedSourceDependencyTable;
  847. AZ_TracePrintf(AssetProcessor::ConsoleChannel, "Upgraded Asset Database to version %i (AddedSourceDependencyTable)\n", foundVersion)
  848. }
  849. }
  850. if (foundVersion == DatabaseVersion::AddedSourceDependencyTable)
  851. {
  852. // add the missing tables - nothing will have generated data for this before this point, so its okay to just make empty ones.
  853. if (
  854. (m_databaseConnection->ExecuteOneOffStatement(CREATE_LEGACYSUBIDS_TABLE)) &&
  855. (m_databaseConnection->ExecuteOneOffStatement(CREATEINDEX_LEGACYSUBIDS_PRODUCTPK))
  856. )
  857. {
  858. foundVersion = DatabaseVersion::AddedLegacySubIDsTable;
  859. AZ_TracePrintf(AssetProcessor::ConsoleChannel, "Upgraded Asset Database to version %i (AddedLegacySubIDsTable)\n", foundVersion)
  860. }
  861. }
  862. if (foundVersion == DatabaseVersion::AddedLegacySubIDsTable)
  863. {
  864. if (m_databaseConnection->ExecuteOneOffStatement(CREATE_PRODUCT_DEPENDENCY_TABLE))
  865. {
  866. foundVersion = DatabaseVersion::AddedProductDependencyTable;
  867. AZ_TracePrintf(AssetProcessor::ConsoleChannel, "Upgraded Asset Database to version %i (AddedProductDependencyTable)\n", foundVersion)
  868. }
  869. }
  870. if (foundVersion == DatabaseVersion::AddedProductDependencyTable)
  871. {
  872. if (m_databaseConnection->ExecuteOneOffStatement(DELETE_AUTO_SUCCEED_JOBS))
  873. {
  874. foundVersion = DatabaseVersion::ClearAutoSucceedJobs;
  875. AZ_TracePrintf(AssetProcessor::ConsoleChannel, "Upgraded Asset Database to version %i (ClearAutoSucceedJobs)\n", foundVersion)
  876. }
  877. }
  878. if (foundVersion == DatabaseVersion::ClearAutoSucceedJobs)
  879. {
  880. if (m_databaseConnection->ExecuteOneOffStatement(CREATE_FILES_TABLE))
  881. {
  882. foundVersion = DatabaseVersion::AddedFilesTable;
  883. AZ_TracePrintf(AssetProcessor::ConsoleChannel, "Upgraded Asset Database to version %i (AddedFilesTable)\n", foundVersion)
  884. }
  885. }
  886. if (foundVersion == DatabaseVersion::AddedFilesTable)
  887. {
  888. if ((m_databaseConnection->ExecuteOneOffStatement(INSERT_COLUMN_ANALYSISFINGERPRINT))&&
  889. (m_databaseConnection->ExecuteOneOffStatement(CREATE_BUILDERINFO_TABLE)))
  890. {
  891. foundVersion = DatabaseVersion::AddedAnalysisFingerprint;
  892. AZ_TracePrintf(AssetProcessor::ConsoleChannel, "Upgraded Asset Database to version %i (AddedAnalysisFingerprint)\n", foundVersion)
  893. }
  894. }
  895. if (foundVersion == DatabaseVersion::AddedAnalysisFingerprint)
  896. {
  897. if (m_databaseConnection->ExecuteOneOffStatement(INSERT_COLUMN_SOURCEDEPENDENCY_TYPEOFDEPENDENCY))
  898. {
  899. foundVersion = DatabaseVersion::AddedSourceDependencyType;
  900. AZ_TracePrintf(AssetProcessor::ConsoleChannel, "Upgraded Asset Database to version %i (AddedSourceDependencyType)\n", foundVersion)
  901. }
  902. }
  903. if (foundVersion == AssetDatabase::DatabaseVersion::AddedSourceDependencyType)
  904. {
  905. if (m_databaseConnection->ExecuteOneOffStatement(INSERT_COLUMN_FILE_MODTIME))
  906. {
  907. foundVersion = DatabaseVersion::AddedFileModTimes;
  908. AZ_TracePrintf(AssetProcessor::ConsoleChannel, "Upgraded Asset Database to version %i (AddedFileModTimes)\n", foundVersion)
  909. }
  910. }
  911. if (foundVersion == AssetDatabase::DatabaseVersion::AddedFileModTimes)
  912. {
  913. if (m_databaseConnection->ExecuteOneOffStatement(INSERT_COLUMN_PRODUCTDEPENDENCY_UNRESOLVEDPATH))
  914. {
  915. foundVersion = DatabaseVersion::AddedUnresolvedDependencyField;
  916. AZ_TracePrintf(AssetProcessor::ConsoleChannel, "Upgraded Asset Database to version %i (AddedUnresolvedDependencyField)\n", foundVersion)
  917. }
  918. }
  919. if (foundVersion == AssetDatabase::DatabaseVersion::AddedUnresolvedDependencyField)
  920. {
  921. if (m_databaseConnection->ExecuteOneOffStatement(INSERT_COLUMN_PRODUCTDEPENDENCY_TYPEOFDEPENDENCY))
  922. {
  923. foundVersion = DatabaseVersion::AddedUnresolvedDependencyTypeField;
  924. AZ_TracePrintf(AssetProcessor::ConsoleChannel, "Upgraded Asset Database to version %i (AddedUnresolvedDependencyTypeField)\n", foundVersion)
  925. }
  926. }
  927. if (foundVersion == AssetDatabase::DatabaseVersion::AddedUnresolvedDependencyTypeField)
  928. {
  929. if (m_databaseConnection->ExecuteOneOffStatement(CREATEINDEX_TYPEOFDEPENDENCY_SOURCEDEPENDENCY))
  930. {
  931. foundVersion = DatabaseVersion::AddedTypeOfDependencyIndex;
  932. AZ_TracePrintf(AssetProcessor::ConsoleChannel, "Upgraded Asset Database to version %i (AddedTypeOfDependencyIndex)\n", foundVersion)
  933. }
  934. }
  935. if (foundVersion == AssetDatabase::DatabaseVersion::AddedTypeOfDependencyIndex)
  936. {
  937. if (m_databaseConnection->ExecuteOneOffStatement(INSERT_COLUMN_PRODUCTDEPENDENCY_PLATFORM))
  938. {
  939. foundVersion = DatabaseVersion::AddedProductDependencyPlatform;
  940. AZ_TracePrintf(AssetProcessor::ConsoleChannel, "Upgraded Asset Database to version %i (AddedProductDependencyPlatform)\n", foundVersion)
  941. }
  942. }
  943. if (foundVersion == DatabaseVersion::AddedProductDependencyPlatform)
  944. {
  945. if (m_databaseConnection->ExecuteOneOffStatement(CREATE_MISSING_PRODUCT_DEPENDENCY_TABLE))
  946. {
  947. foundVersion = DatabaseVersion::AddedMissingProductDependencyTable;
  948. AZ_TracePrintf(AssetProcessor::ConsoleChannel, "Upgraded Asset Database to version %i (AddedMissingProductDependencyTable)\n", foundVersion)
  949. }
  950. }
  951. if (foundVersion == DatabaseVersion::AddedMissingProductDependencyTable)
  952. {
  953. if (m_databaseConnection->ExecuteOneOffStatement(INSERT_COLUMNS_JOB_WARNING_COUNT) &&
  954. m_databaseConnection->ExecuteOneOffStatement(INSERT_COLUMNS_JOB_ERROR_COUNT))
  955. {
  956. foundVersion = DatabaseVersion::AddedWarningAndErrorCountToJobs;
  957. AZ_TracePrintf(AssetProcessor::ConsoleChannel, "Upgraded Asset Database to version %i (AddedWarningAndErrorCountToJobs)\n", foundVersion)
  958. }
  959. }
  960. if (foundVersion == DatabaseVersion::AddedWarningAndErrorCountToJobs)
  961. {
  962. if (m_databaseConnection->ExecuteOneOffStatement(INSERT_COLUMNS_SOURCEDEPENDENCY_FROM_ASSETID) &&
  963. m_databaseConnection->ExecuteOneOffStatement(INSERT_COLUMNS_PRODUCTDEPENDENCY_FROM_ASSETID))
  964. {
  965. foundVersion = DatabaseVersion::AddedFromAssetIdField;
  966. AZ_TracePrintf(AssetProcessor::ConsoleChannel, "Upgraded Asset Database to version %i (AddedFromAssetIdField)\n", foundVersion)
  967. }
  968. }
  969. if (foundVersion == DatabaseVersion::AddedFromAssetIdField)
  970. {
  971. if (m_databaseConnection->ExecuteOneOffStatement(CREATEINDEX_PRODUCTDEPENDENCIES_UNRESOLVEDPATH) &&
  972. m_databaseConnection->ExecuteOneOffStatement(CREATEINDEX_PRODUCTDEPENDENCIES_UNRESOLVEDPATH_WILDCARD))
  973. {
  974. foundVersion = DatabaseVersion::AddedProductDependencyIndexes;
  975. AZ_TracePrintf(AssetProcessor::ConsoleChannel, "Upgraded Asset Database to version %i (AddedProductDependencyIndexes)\n", foundVersion)
  976. }
  977. }
  978. if (foundVersion == AssetDatabase::DatabaseVersion::AddedProductDependencyIndexes)
  979. {
  980. if (m_databaseConnection->ExecuteOneOffStatement(INSERT_COLUMN_FILE_HASH))
  981. {
  982. foundVersion = DatabaseVersion::AddedFileHashField;
  983. AZ_TracePrintf(AssetProcessor::ConsoleChannel, "Upgraded Asset Database to version %i (AddedFileHashField)\n", foundVersion)
  984. }
  985. }
  986. if (foundVersion == AssetDatabase::DatabaseVersion::AddedFileHashField)
  987. {
  988. if (m_databaseConnection->ExecuteOneOffStatement(INSERT_COLUMN_LAST_SCAN))
  989. {
  990. foundVersion = DatabaseVersion::AddedLastScanTimeField;
  991. AZ_TracePrintf(AssetProcessor::ConsoleChannel, "Upgraded Asset Database to version %i (AddedLastScanTimeField)\n", foundVersion)
  992. }
  993. }
  994. if (foundVersion == AssetDatabase::DatabaseVersion::AddedLastScanTimeField)
  995. {
  996. if (m_databaseConnection->ExecuteOneOffStatement(INSERT_COLUMN_SCAN_TIME_SECONDS_SINCE_EPOCH))
  997. {
  998. foundVersion = DatabaseVersion::AddedScanTimeSecondsSinceEpochField;
  999. AZ_TracePrintf(AssetProcessor::ConsoleChannel, "Upgraded Asset Database to version %i (AddedScanTimeSecondsSinceEpochField)\n", foundVersion)
  1000. }
  1001. }
  1002. // Nothing to do for version `AssetDatabase::DatabaseVersion::RemoveOutputPrefixFromScanFolders`
  1003. // sqlite doesn't not support altering a table to remove a column
  1004. // This is fine as the extra OutputPrefix column will not be queried
  1005. if (foundVersion == AssetDatabase::DatabaseVersion::RemoveOutputPrefixFromScanFolders)
  1006. {
  1007. if (m_databaseConnection->ExecuteOneOffStatement(DROPINDEX_BUILDERGUID_SOURCE_SOURCEDEPENDENCY) && m_databaseConnection->ExecuteOneOffStatement(CREATEINDEX_SOURCEDEPENDENCY_SOURCE))
  1008. {
  1009. foundVersion = AssetDatabase::DatabaseVersion::AddedSourceIndexForSourceDependencyTable;
  1010. AZ_TracePrintf(AssetProcessor::ConsoleChannel, "Upgraded Asset Database to version %i (AddedSourceIndexForSourceDependencyTable)\n", foundVersion)
  1011. }
  1012. }
  1013. if (foundVersion == AssetDatabase::DatabaseVersion::AddedSourceIndexForSourceDependencyTable)
  1014. {
  1015. if (m_databaseConnection->ExecuteOneOffStatement(INSERT_COLUMN_PRODUCT_HASH) && m_databaseConnection->ExecuteOneOffStatement(INSERT_COLUMN_SOURCEDEPENDENCY_SUBIDS))
  1016. {
  1017. foundVersion = AssetDatabase::DatabaseVersion::AddedSourceDependencySubIdsAndProductHashes;
  1018. AZ_TracePrintf(AssetProcessor::ConsoleChannel, "Upgraded Asset Database to version %i (AddedSourceDependencySubIdsAndProductHashes)\n", foundVersion);
  1019. }
  1020. }
  1021. if(foundVersion == AssetDatabase::DatabaseVersion::AddedSourceDependencySubIdsAndProductHashes)
  1022. {
  1023. if(m_databaseConnection->ExecuteOneOffStatement(INSERT_COLUMN_PRODUCTS_FLAGS))
  1024. {
  1025. foundVersion = AssetDatabase::DatabaseVersion::AddedFlagsColumnToProductTable;
  1026. AZ_TracePrintf(AssetProcessor::ConsoleChannel, "Upgraded Asset Database to version %i (AddedFlagsColumnToProductTable)\n", foundVersion);
  1027. }
  1028. }
  1029. if (foundVersion == DatabaseVersion::AddedFlagsColumnToProductTable)
  1030. {
  1031. if (m_databaseConnection->ExecuteOneOffStatement(CREATE_STATS_TABLE))
  1032. {
  1033. foundVersion = DatabaseVersion::AddedStatsTable;
  1034. AZ_TracePrintf(AssetProcessor::ConsoleChannel, "Upgraded Asset Database to version %i (AddedStatsTable)\n", foundVersion);
  1035. }
  1036. }
  1037. if (foundVersion == DatabaseVersion::AddedStatsTable)
  1038. {
  1039. // Version update - change SourceDependency Source to SourceGuid column
  1040. // Do nothing so the whole database is dropped.
  1041. // Unfortunately we have to reprocess all assets because of the way the fingerprinting algorithm works,
  1042. // changing from storing the path to the UUID changes the fingerprint, resulting in all assets reprocessing anyway
  1043. AZ_TracePrintf(
  1044. AssetProcessor::ConsoleChannel,
  1045. "Asset database version updated to ChangedSourceDependencySourceColumn, database will be cleared as migration is not "
  1046. "possible for this update\n",
  1047. foundVersion);
  1048. }
  1049. if (foundVersion == DatabaseVersion::NewMaterialTypeBuildPipeline)
  1050. {
  1051. if (m_databaseConnection->ExecuteOneOffStatement(INSERT_COLUMN_JOBS_FAILURECAUSESOURCEID)
  1052. && m_databaseConnection->ExecuteOneOffStatement(INSERT_COLUMN_JOBS_FAILURECAUSEFINGERPRINT))
  1053. {
  1054. foundVersion = DatabaseVersion::AddedJobFailureSourceColumn;
  1055. AZ_TracePrintf(AssetProcessor::ConsoleChannel, "Upgraded Asset Database to version %i (AddedJobFailureSourceColumn)\n", foundVersion);
  1056. }
  1057. }
  1058. if (foundVersion == DatabaseVersion::AddedJobFailureSourceColumn)
  1059. {
  1060. if (m_databaseConnection->ExecuteOneOffStatement(CREATEINDEX_MISSINGPRODUCTDEPENDENCY_PRODUCTPK))
  1061. {
  1062. foundVersion = DatabaseVersion::AddedMissingDependenciesIndex;
  1063. AZ_TracePrintf(
  1064. AssetProcessor::ConsoleChannel, "Upgraded Asset Database to version %i (AddedMissingDependenciesIndex)\n", foundVersion);
  1065. }
  1066. }
  1067. if (foundVersion == CurrentDatabaseVersion())
  1068. {
  1069. dropAllTables = false;
  1070. }
  1071. else
  1072. {
  1073. AZ_TracePrintf(AssetProcessor::ConsoleChannel, "Asset Database must be cleared (hasVersion: %i currentVersion: %i)\n", foundVersion, CurrentDatabaseVersion())
  1074. dropAllTables = true;
  1075. }
  1076. // 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,
  1077. // we can either drop all tables and recreate them, or we can write statements which upgrade the database.
  1078. // if you know how to upgrade, write your modify statements here, then set dropAllTables to false.
  1079. // otherwise it will re-create from scratch.
  1080. if (dropAllTables)
  1081. {
  1082. // drop all tables by destroying the entire database.
  1083. m_databaseConnection->Close();
  1084. AZStd::string dbFilePath = GetAssetDatabaseFilePath();
  1085. if (dbFilePath != ":memory:")
  1086. {
  1087. // you cannot delete a memory database, but it drops all data when you close it anyway.
  1088. if (!AZ::IO::SystemFile::Delete(dbFilePath.c_str()))
  1089. {
  1090. delete m_databaseConnection;
  1091. m_databaseConnection = nullptr;
  1092. AZ_Error(LOG_NAME, false, "Unable to clear the asset database at %s\n", dbFilePath.c_str());
  1093. return false;
  1094. }
  1095. }
  1096. if (!m_databaseConnection->Open(dbFilePath, IsReadOnly()))
  1097. {
  1098. delete m_databaseConnection;
  1099. m_databaseConnection = nullptr;
  1100. AZ_Error(LOG_NAME, false, "Unable to open the asset database at %s\n", dbFilePath.c_str());
  1101. return false;
  1102. }
  1103. AZ_TracePrintf(AssetProcessor::ConsoleChannel, "Asset Database has been cleared.\n")
  1104. CreateStatements();
  1105. ExecuteCreateStatements();
  1106. }
  1107. // now that the database matches the schema, update it:
  1108. SetDatabaseVersion(CurrentDatabaseVersion());
  1109. return AzToolsFramework::AssetDatabase::AssetDatabaseConnection::PostOpenDatabase(ignoreFutureAssetDBVersionError);
  1110. }
  1111. void AssetDatabaseConnection::ExecuteCreateStatements()
  1112. {
  1113. AZ_Assert(m_databaseConnection, "No connection!");
  1114. for (const auto& element : m_createStatements)
  1115. {
  1116. m_databaseConnection->ExecuteOneOffStatement(element.c_str());
  1117. }
  1118. }
  1119. void AssetDatabaseConnection::SetDatabaseVersion(DatabaseVersion ver)
  1120. {
  1121. AZ_Error(LOG_NAME, m_databaseConnection, "Fatal: attempt to work on a database connection that doesn't exist");
  1122. AZ_Error(LOG_NAME, m_databaseConnection->IsOpen(), "Fatal: attempt to work on a database connection that isn't open");
  1123. AZ_Error(LOG_NAME, m_databaseConnection->DoesTableExist("dbinfo"), "Fatal: dbinfo table does not exist");
  1124. StatementAutoFinalizer autoFinal;
  1125. // note that BindAndStep outputs errors if it fails, no need to ouput them here.
  1126. s_SetDatabaseVersionQuery.BindAndStep(*m_databaseConnection, static_cast<int>(ver));
  1127. }
  1128. void AssetDatabaseConnection::CreateStatements()
  1129. {
  1130. AZ_Assert(m_databaseConnection, "No connection!");
  1131. AZ_Assert(m_databaseConnection->IsOpen(), "Connection is not open");
  1132. AzToolsFramework::AssetDatabase::AssetDatabaseConnection::CreateStatements();
  1133. // ---------------------------------------------------------------------------------------------
  1134. // Housekeeping
  1135. // ---------------------------------------------------------------------------------------------
  1136. m_databaseConnection->AddStatement("VACUUM", "VACUUM");
  1137. m_databaseConnection->AddStatement("ANALYZE", "ANALYZE");
  1138. // ---------------------------------------------------------------------------------------------
  1139. // Database Info table
  1140. // ----------------------------------------------------------------------------------------------
  1141. m_databaseConnection->AddStatement(CREATE_DATABASE_INFOTABLE, CREATE_DATABASE_INFOTABLE_STATEMENT);
  1142. m_createStatements.push_back(CREATE_DATABASE_INFOTABLE);
  1143. AddStatement(m_databaseConnection, s_SetDatabaseVersionQuery);
  1144. // ----------------------------------------------------------------------------------------------
  1145. // ScanFolders table
  1146. // ----------------------------------------------------------------------------------------------
  1147. m_databaseConnection->AddStatement(CREATE_SCANFOLDERS_TABLE, CREATE_SCANFOLDERS_TABLE_STATEMENT);
  1148. m_createStatements.push_back(CREATE_SCANFOLDERS_TABLE);
  1149. AddStatement(m_databaseConnection, s_InsertScanfolderQuery);
  1150. AddStatement(m_databaseConnection, s_UpdateScanfolderQuery);
  1151. AddStatement(m_databaseConnection, s_DeleteScanfolderQuery);
  1152. AddStatement(m_databaseConnection, s_DeleteSourceByScanfolderidQuery);
  1153. // ---------------------------------------------------------------------------------------------
  1154. // Source table
  1155. // ---------------------------------------------------------------------------------------------
  1156. m_databaseConnection->AddStatement(CREATE_SOURCES_TABLE, CREATE_SOURCES_TABLE_STATEMENT);
  1157. m_createStatements.push_back(CREATE_SOURCES_TABLE);
  1158. AddStatement(m_databaseConnection, s_InsertSourceQuery);
  1159. AddStatement(m_databaseConnection, s_UpdateSourceQuery);
  1160. AddStatement(m_databaseConnection, s_DeleteSourceQuery);
  1161. m_databaseConnection->AddStatement(INVALIDATE_SOURCE_ANALYSISFINGEPRINTS, INVALIDATE_SOURCE_ANALYSISFINGEPRINTS_STATEMENT);
  1162. // ---------------------------------------------------------------------------------------------
  1163. // Jobs table
  1164. // ---------------------------------------------------------------------------------------------
  1165. m_databaseConnection->AddStatement(CREATE_JOBS_TABLE, CREATE_JOBS_TABLE_STATEMENT);
  1166. m_databaseConnection->AddStatement(INSERT_COLUMNS_JOB_WARNING_COUNT, INSERT_COLUMNS_JOB_WARNING_COUNT_STATEMENT);
  1167. m_databaseConnection->AddStatement(INSERT_COLUMNS_JOB_ERROR_COUNT, INSERT_COLUMNS_JOB_ERROR_COUNT_STATEMENT);
  1168. m_databaseConnection->AddStatement(UPDATE_JOB_FINGERPRINT_BY_SOURCE_ID, UPDATE_JOB_FINGERPRINT_BY_SOURCE_ID_STATEMENT);
  1169. m_databaseConnection->AddStatement(INSERT_COLUMN_JOBS_FAILURECAUSESOURCEID, INSERT_COLUMN_JOBS_FAILURECAUSESOURCEID_STATEMENT);
  1170. m_databaseConnection->AddStatement(INSERT_COLUMN_JOBS_FAILURECAUSEFINGERPRINT, INSERT_COLUMN_JOBS_FAILURECAUSEFINGERPRINT_STATEMENT);
  1171. m_createStatements.push_back(CREATE_JOBS_TABLE);
  1172. AddStatement(m_databaseConnection, s_GetHighestJobrunkeyQuery);
  1173. AddStatement(m_databaseConnection, s_InsertJobQuery);
  1174. AddStatement(m_databaseConnection, s_UpdateJobQuery);
  1175. AddStatement(m_databaseConnection, s_DeleteJobQuery);
  1176. // ---------------------------------------------------------------------------------------------
  1177. // Builder Info Table
  1178. // ---------------------------------------------------------------------------------------------
  1179. m_databaseConnection->AddStatement(INSERT_COLUMN_ANALYSISFINGERPRINT, INSERT_COLUMN_ANALYSISFINGERPRINT_STATEMENT);
  1180. m_databaseConnection->AddStatement(CREATE_BUILDERINFO_TABLE, CREATE_BUILDERINFO_TABLE_STATEMENT);
  1181. m_databaseConnection->AddStatement(CLEAR_BUILDERINFO_TABLE, CLEAR_BUILDERINFO_TABLE_STATEMENT);
  1182. m_databaseConnection->AddStatement(INSERT_BUILDERINFO, INSERT_BUILDERINFO_STATEMENT);
  1183. m_createStatements.push_back(CREATE_BUILDERINFO_TABLE);
  1184. // ---------------------------------------------------------------------------------------------
  1185. // Products table
  1186. // ---------------------------------------------------------------------------------------------
  1187. m_databaseConnection->AddStatement(CREATE_PRODUCT_TABLE, CREATE_PRODUCT_TABLE_STATEMENT);
  1188. m_databaseConnection->AddStatement(INSERT_COLUMN_PRODUCT_HASH, INSERT_COLUMN_PRODUCT_HASH_STATEMENT);
  1189. m_databaseConnection->AddStatement(INSERT_COLUMN_PRODUCTS_FLAGS, INSERT_COLUMN_PRODUCTS_FLAGS_STATEMENT);
  1190. m_createStatements.push_back(CREATE_PRODUCT_TABLE);
  1191. AddStatement(m_databaseConnection, s_InsertProductQuery);
  1192. AddStatement(m_databaseConnection, s_UpdateProductQuery);
  1193. AddStatement(m_databaseConnection, s_DeleteProductQuery);
  1194. AddStatement(m_databaseConnection, s_DeleteProductsByJobidQuery);
  1195. AddStatement(m_databaseConnection, s_DeleteProductsBySourceidQuery);
  1196. AddStatement(m_databaseConnection, s_DeleteProductsBySourceidPlatformQuery);
  1197. // ---------------------------------------------------------------------------------------------
  1198. // Source Dependency table
  1199. // ---------------------------------------------------------------------------------------------
  1200. m_databaseConnection->AddStatement(CREATE_SOURCE_DEPENDENCY_TABLE, CREATE_SOURCE_DEPENDENCY_TABLE_STATEMENT);
  1201. m_databaseConnection->AddStatement(INSERT_COLUMN_SOURCEDEPENDENCY_TYPEOFDEPENDENCY, INSERT_COLUMN_SOURCEDEPENDENCY_TYPEOFDEPENDENCY_STATEMENT);
  1202. m_databaseConnection->AddStatement(INSERT_COLUMNS_SOURCEDEPENDENCY_FROM_ASSETID, INSERT_COLUMNS_SOURCEDEPENDENCY_FROM_ASSETID_STATEMENT);
  1203. m_databaseConnection->AddStatement(INSERT_COLUMN_SOURCEDEPENDENCY_SUBIDS, INSERT_COLUMN_SOURCEDEPENDENCY_SUBIDS_STATEMENT);
  1204. m_createStatements.push_back(CREATE_SOURCE_DEPENDENCY_TABLE);
  1205. AddStatement(m_databaseConnection, s_InsertSourceDependencyQuery);
  1206. AddStatement(m_databaseConnection, s_DeleteSourceDependencySourcedependencyidQuery);
  1207. // ---------------------------------------------------------------------------------------------
  1208. // Legacy SubIDs table
  1209. // ---------------------------------------------------------------------------------------------
  1210. m_databaseConnection->AddStatement(CREATE_LEGACYSUBIDS_TABLE, CREATE_LEGACYSUBIDS_TABLE_STATEMENT);
  1211. m_databaseConnection->AddStatement(CREATEINDEX_LEGACYSUBIDS_PRODUCTPK, CREATEINDEX_LEGACYSUBIDS_PRODUCTPK_STATEMENT);
  1212. m_createStatements.push_back(CREATE_LEGACYSUBIDS_TABLE);
  1213. m_createStatements.push_back(CREATEINDEX_LEGACYSUBIDS_PRODUCTPK);
  1214. AddStatement(m_databaseConnection, s_InsertNewLegacysubidQuery);
  1215. AddStatement(m_databaseConnection, s_OverwriteExistingLegacysubidQuery);
  1216. AddStatement(m_databaseConnection, s_DeleteLegacysubidsByPrimaryKeyQuery);
  1217. AddStatement(m_databaseConnection, s_DeleteLegacysubidsByProductidQuery);
  1218. // ---------------------------------------------------------------------------------------------
  1219. // Product Dependency table
  1220. // ---------------------------------------------------------------------------------------------
  1221. m_databaseConnection->AddStatement(CREATE_PRODUCT_DEPENDENCY_TABLE, CREATE_PRODUCT_DEPENDENCY_TABLE_STATEMENT);
  1222. m_databaseConnection->AddStatement(INSERT_COLUMN_PRODUCTDEPENDENCY_UNRESOLVEDPATH, INSERT_COLUMN_PRODUCTDEPENDENCY_UNRESOLVEDPATH_STATEMENT);
  1223. m_databaseConnection->AddStatement(INSERT_COLUMN_PRODUCTDEPENDENCY_TYPEOFDEPENDENCY, INSERT_COLUMN_PRODUCTDEPENDENCY_TYPEOFDEPENDENCY_STATEMENT);
  1224. m_databaseConnection->AddStatement(INSERT_COLUMN_PRODUCTDEPENDENCY_PLATFORM, INSERT_COLUMN_PRODUCTDEPENDENCY_PLATFORM_STATEMENT);
  1225. m_databaseConnection->AddStatement(INSERT_COLUMNS_PRODUCTDEPENDENCY_FROM_ASSETID, INSERT_COLUMNS_PRODUCTDEPENDENCY_FROM_ASSETID_STATEMENT);
  1226. m_createStatements.push_back(CREATE_PRODUCT_DEPENDENCY_TABLE);
  1227. AddStatement(m_databaseConnection, s_InsertProductDependencyQuery);
  1228. AddStatement(m_databaseConnection, s_UpdateProductDependencyQuery);
  1229. AddStatement(m_databaseConnection, s_DeleteProductDependencyByProductIdQuery);
  1230. // ---------------------------------------------------------------------------------------------
  1231. // Missing Product Dependency table
  1232. // ---------------------------------------------------------------------------------------------
  1233. m_databaseConnection->AddStatement(CREATE_MISSING_PRODUCT_DEPENDENCY_TABLE, CREATE_MISSING_PRODUCT_DEPENDENCY_TABLE_STATEMENT);
  1234. m_createStatements.push_back(CREATE_MISSING_PRODUCT_DEPENDENCY_TABLE);
  1235. AddStatement(m_databaseConnection, s_InsertMissingProductDependencyQuery);
  1236. AddStatement(m_databaseConnection, s_UpdateMissingProductDependencyQuery);
  1237. AddStatement(m_databaseConnection, s_DeleteMissingProductDependencyByProductIdQuery);
  1238. // ---------------------------------------------------------------------------------------------
  1239. // Files table
  1240. // ---------------------------------------------------------------------------------------------
  1241. m_databaseConnection->AddStatement(CREATE_FILES_TABLE, CREATE_FILES_TABLE_STATEMENT);
  1242. m_createStatements.push_back(CREATE_FILES_TABLE);
  1243. m_databaseConnection->AddStatement(INSERT_FILE, INSERT_FILE_STATEMENT);
  1244. m_databaseConnection->AddStatement(UPDATE_FILE, UPDATE_FILE_STATEMENT);
  1245. m_databaseConnection->AddStatement(UPDATE_FILE_MODTIME_AND_HASH_BY_FILENAME_SCANFOLDER_ID, UPDATE_FILE_MODTIME_AND_HASH_BY_FILENAME_SCANFOLDER_ID_STATEMENT);
  1246. m_databaseConnection->AddStatement(UPDATE_FILE_HASH_BY_FILENAME_SCANFOLDER_ID, UPDATE_FILE_HASH_BY_FILENAME_SCANFOLDER_ID_STATEMENT);
  1247. m_databaseConnection->AddStatement(DELETE_FILE, DELETE_FILE_STATEMENT);
  1248. m_databaseConnection->AddStatement(INSERT_COLUMN_FILE_MODTIME, INSERT_COLUMN_FILE_MODTIME_STATEMENT);
  1249. m_databaseConnection->AddStatement(INSERT_COLUMN_FILE_HASH, INSERT_COLUMN_FILE_HASH_STATEMENT);
  1250. m_databaseConnection->AddStatement(INSERT_COLUMN_LAST_SCAN, INSERT_COLUMN_LAST_SCAN_STATEMENT);
  1251. m_databaseConnection->AddStatement(INSERT_COLUMN_SCAN_TIME_SECONDS_SINCE_EPOCH, INSERT_COLUMN_SCAN_TIME_SECONDS_SINCE_EPOCH_STATEMENT);
  1252. // ---------------------------------------------------------------------------------------------
  1253. // Stats table
  1254. // ---------------------------------------------------------------------------------------------
  1255. m_databaseConnection->AddStatement(CREATE_STATS_TABLE, CREATE_STATS_TABLE_STATEMENT);
  1256. m_createStatements.push_back(CREATE_STATS_TABLE);
  1257. m_databaseConnection->AddStatement(REPLACE_STAT, REPLACE_STAT_STATEMENT);
  1258. // ---------------------------------------------------------------------------------------------
  1259. // Indices
  1260. // ---------------------------------------------------------------------------------------------
  1261. m_databaseConnection->AddStatement(CREATEINDEX_DEPENDSONSOURCE_SOURCEDEPENDENCY, CREATEINDEX_DEPENDSONSOURCE_SOURCEDEPENDENCY_STATEMENT);
  1262. m_createStatements.push_back(CREATEINDEX_DEPENDSONSOURCE_SOURCEDEPENDENCY);
  1263. m_databaseConnection->AddStatement(CREATEINDEX_BUILDERGUID_SOURCE_SOURCEDEPENDENCY, CREATEINDEX_BUILDERGUID_SOURCE_SOURCEDEPENDENCY_STATEMENT);
  1264. m_createStatements.push_back(CREATEINDEX_BUILDERGUID_SOURCE_SOURCEDEPENDENCY);
  1265. m_databaseConnection->AddStatement(CREATEINDEX_TYPEOFDEPENDENCY_SOURCEDEPENDENCY, CREATEINDEX_TYPEOFDEPENDENCY_SOURCEDEPENDENCY_STATEMENT);
  1266. m_createStatements.push_back(CREATEINDEX_TYPEOFDEPENDENCY_SOURCEDEPENDENCY);
  1267. m_databaseConnection->AddStatement(CREATEINDEX_SCANFOLDERS_SOURCES_SCANFOLDER, CREATEINDEX_SCANFOLDERS_SOURCES_SCANFOLDER_STATEMENT);
  1268. m_createStatements.push_back(CREATEINDEX_SCANFOLDERS_SOURCES_SCANFOLDER);
  1269. m_databaseConnection->AddStatement(CREATEINDEX_SOURCES_JOBS, CREATEINDEX_SOURCES_JOBS_STATEMENT);
  1270. m_createStatements.push_back(CREATEINDEX_SOURCES_JOBS);
  1271. m_databaseConnection->AddStatement(CREATEINDEX_JOBS_PRODUCTS, CREATEINDEX_JOBS_PRODUCTS_STATEMENT);
  1272. m_createStatements.push_back(CREATEINDEX_JOBS_PRODUCTS);
  1273. m_databaseConnection->AddStatement(CREATEINDEX_JOBS_JOBRUNKEY, CREATEINDEX_JOBS_JOBRUNKEY_STATEMENT);
  1274. m_createStatements.push_back(CREATEINDEX_JOBS_JOBRUNKEY);
  1275. m_databaseConnection->AddStatement(CREATEINDEX_JOBS_JOBKEY, CREATEINDEX_JOBS_JOBKEY_STATEMENT);
  1276. m_createStatements.push_back(CREATEINDEX_JOBS_JOBKEY);
  1277. m_databaseConnection->AddStatement(CREATEINDEX_SOURCE_NAME, CREATEINDEX_SOURCE_NAME_STATEMENT);
  1278. m_createStatements.push_back(CREATEINDEX_SOURCE_NAME);
  1279. m_databaseConnection->AddStatement(CREATEINDEX_SOURCE_GUID, CREATEINDEX_SOURCE_GUID_STATEMENT);
  1280. m_createStatements.push_back(CREATEINDEX_SOURCE_GUID);
  1281. m_databaseConnection->AddStatement(CREATEINDEX_PRODUCT_NAME, CREATEINDEX_PRODUCT_NAME_STATEMENT);
  1282. m_createStatements.push_back(CREATEINDEX_PRODUCT_NAME);
  1283. m_databaseConnection->AddStatement(CREATEINDEX_PRODUCT_SUBID, CREATEINDEX_PRODUCT_SUBID_STATEMENT);
  1284. m_createStatements.push_back(CREATEINDEX_PRODUCT_SUBID);
  1285. m_databaseConnection->AddStatement(CREATEINDEX_PRODUCTDEPENDENCIES_PRODUCTPK, CREATEINDEX_PRODUCTDEPENDENCIES_PRODUCTPK_STATEMENT);
  1286. m_createStatements.push_back(CREATEINDEX_PRODUCTDEPENDENCIES_PRODUCTPK);
  1287. m_databaseConnection->AddStatement(CREATEINDEX_PRODUCTDEPENDENCIES_UNRESOLVEDPATH, CREATEINDEX_PRODUCTDEPENDENCIES_UNRESOLVEDPATH_STATEMENT);
  1288. m_createStatements.push_back(CREATEINDEX_PRODUCTDEPENDENCIES_UNRESOLVEDPATH);
  1289. m_databaseConnection->AddStatement(CREATEINDEX_PRODUCTDEPENDENCIES_UNRESOLVEDPATH_WILDCARD, CREATEINDEX_PRODUCTDEPENDENCIES_UNRESOLVEDPATH_WILDCARD_STATEMENT);
  1290. m_createStatements.push_back(CREATEINDEX_PRODUCTDEPENDENCIES_UNRESOLVEDPATH_WILDCARD);
  1291. m_databaseConnection->AddStatement(CREATEINDEX_FILE_NAME, CREATEINDEX_FILE_NAME_STATEMENT);
  1292. m_createStatements.push_back(CREATEINDEX_FILE_NAME);
  1293. m_databaseConnection->AddStatement(CREATEINDEX_SCANFOLDERS_FILES, CREATEINDEX_SCANFOLDERS_FILES_STATEMENT);
  1294. m_createStatements.push_back(CREATEINDEX_SCANFOLDERS_FILES);
  1295. m_databaseConnection->AddStatement(CREATEINDEX_SOURCEDEPENDENCY_SOURCE, CREATEINDEX_SOURCEDEPENDENCY_SOURCE_STATEMENT);
  1296. m_databaseConnection->AddStatement(DROPINDEX_BUILDERGUID_SOURCE_SOURCEDEPENDENCY, DROPINDEX_BUILDERGUID_SOURCE_SOURCEDEPENDENCY_STATEMENT);
  1297. m_createStatements.push_back(DROPINDEX_BUILDERGUID_SOURCE_SOURCEDEPENDENCY);
  1298. m_databaseConnection->AddStatement(CREATEINDEX_SOURCEDEPENDENCY_SOURCEGUID, CREATEINDEX_SOURCEDEPENDENCY_SOURCEGUID_STATEMENT);
  1299. m_createStatements.push_back(CREATEINDEX_SOURCEDEPENDENCY_SOURCEGUID);
  1300. m_databaseConnection->AddStatement(DELETE_AUTO_SUCCEED_JOBS, DELETE_AUTO_SUCCEED_JOBS_STATEMENT);
  1301. m_databaseConnection->AddStatement(
  1302. CREATEINDEX_MISSINGPRODUCTDEPENDENCY_PRODUCTPK, CREATEINDEX_MISSINGPRODUCTDEPENDENCY_PRODUCTPK_STATEMENT);
  1303. m_createStatements.push_back(CREATEINDEX_MISSINGPRODUCTDEPENDENCY_PRODUCTPK);
  1304. }
  1305. void AssetDatabaseConnection::VacuumAndAnalyze()
  1306. {
  1307. if (m_databaseConnection)
  1308. {
  1309. m_databaseConnection->ExecuteOneOffStatement("VACUUM");
  1310. m_databaseConnection->ExecuteOneOffStatement("ANALYZE");
  1311. }
  1312. }
  1313. bool AssetDatabaseConnection::GetScanFolderByScanFolderID(AZ::s64 scanfolderID, ScanFolderDatabaseEntry& entry)
  1314. {
  1315. bool found = false;
  1316. QueryScanFolderByScanFolderID( scanfolderID,
  1317. [&](ScanFolderDatabaseEntry& scanFolderEntry)
  1318. {
  1319. entry = scanFolderEntry;
  1320. found = true;
  1321. return false;//only one
  1322. });
  1323. return found;
  1324. }
  1325. bool AssetDatabaseConnection::GetScanFolderBySourceID(AZ::s64 sourceID, ScanFolderDatabaseEntry& entry)
  1326. {
  1327. bool found = false;
  1328. QueryScanFolderBySourceID( sourceID,
  1329. [&](ScanFolderDatabaseEntry& scanFolderEntry)
  1330. {
  1331. entry = scanFolderEntry;
  1332. found = true;
  1333. return false;//only one
  1334. });
  1335. return found;
  1336. }
  1337. bool AssetDatabaseConnection::GetScanFolderByJobID(AZ::s64 jobID, ScanFolderDatabaseEntry& entry)
  1338. {
  1339. bool found = false;
  1340. QueryScanFolderByJobID( jobID,
  1341. [&](ScanFolderDatabaseEntry& scanFolderEntry)
  1342. {
  1343. entry = scanFolderEntry;
  1344. found = true;
  1345. return false; // return false because we only want one entry, no need to continue scanning rows
  1346. });
  1347. return found ;
  1348. }
  1349. bool AssetDatabaseConnection::GetScanFolderByProductID(AZ::s64 productID, ScanFolderDatabaseEntry& entry)
  1350. {
  1351. bool found = false;
  1352. QueryScanFolderByProductID( productID,
  1353. [&](ScanFolderDatabaseEntry& scanFolderEntry)
  1354. {
  1355. entry = scanFolderEntry;
  1356. found = true;
  1357. return false; // stop after the first result
  1358. });
  1359. return found;
  1360. }
  1361. bool AssetDatabaseConnection::GetScanFolderByPortableKey(QString portableKey, ScanFolderDatabaseEntry& entry)
  1362. {
  1363. bool found = false;
  1364. QueryScanFolderByPortableKey(portableKey.toUtf8().constData(),
  1365. [&](ScanFolderDatabaseEntry& scanFolder)
  1366. {
  1367. entry = AZStd::move(scanFolder);
  1368. found = true;
  1369. return false; // stop after the first result
  1370. });
  1371. return found;
  1372. }
  1373. bool AssetDatabaseConnection::GetScanFolders(ScanFolderDatabaseEntryContainer& container)
  1374. {
  1375. bool found = false;
  1376. bool succeeded = QueryScanFoldersTable(
  1377. [&](ScanFolderDatabaseEntry& scanFolder)
  1378. {
  1379. found = true;
  1380. container.emplace_back() = AZStd::move(scanFolder);
  1381. return true; // return true to collect more rows since we are filling a container
  1382. });
  1383. return found && succeeded;
  1384. }
  1385. bool AssetDatabaseConnection::SetScanFolder(ScanFolderDatabaseEntry& entry)
  1386. {
  1387. ScanFolderDatabaseEntry existingEntry;
  1388. if (entry.m_scanFolderID == InvalidEntryId)
  1389. {
  1390. //they didn't supply an id, add to database!
  1391. //make sure the scan path is not already in the database
  1392. if (GetScanFolderByPortableKey(entry.m_portableKey.c_str(), existingEntry))
  1393. {
  1394. //its in the database already, update the input entry id and try again:
  1395. entry.m_scanFolderID = existingEntry.m_scanFolderID;
  1396. return SetScanFolder(entry);
  1397. }
  1398. //its not in the database, add it
  1399. // it is a single statement, do not wrap it in a transaction, this wastes a lot of time.
  1400. if (!s_InsertScanfolderQuery.BindAndStep(*m_databaseConnection, entry.m_scanFolder.c_str(), entry.m_displayName.c_str(), entry.m_portableKey.c_str(), entry.m_isRoot))
  1401. {
  1402. return false;
  1403. }
  1404. if (GetScanFolderByPortableKey(entry.m_portableKey.c_str(), existingEntry))
  1405. {
  1406. //its in the database already, update the input entry
  1407. entry.m_scanFolderID = existingEntry.m_scanFolderID;
  1408. return true;
  1409. }
  1410. AZ_Error(LOG_NAME, false, "Failed to read the new scan folder into the database.");
  1411. return false;
  1412. }
  1413. else
  1414. {
  1415. //they supplied an id, see if it exists in the database
  1416. if (!GetScanFolderByScanFolderID(entry.m_scanFolderID, existingEntry))
  1417. {
  1418. AZ_WarningOnce(LOG_NAME, false, "Failed to write the new scan folder into the database.");
  1419. return false;
  1420. }
  1421. 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);
  1422. }
  1423. }
  1424. bool AssetDatabaseConnection::RemoveScanFolder(AZ::s64 scanFolderID)
  1425. {
  1426. ScopedTransaction transaction(m_databaseConnection);
  1427. if (!s_DeleteScanfolderQuery.BindAndStep(*m_databaseConnection, scanFolderID))
  1428. {
  1429. return false;
  1430. }
  1431. transaction.Commit();
  1432. return true;
  1433. }
  1434. bool AssetDatabaseConnection::RemoveScanFolders(ScanFolderDatabaseEntryContainer& container)
  1435. {
  1436. bool succeeded = true;
  1437. for (auto& entry : container)
  1438. {
  1439. succeeded &= RemoveScanFolder(entry.m_scanFolderID);
  1440. if (succeeded)
  1441. {
  1442. entry.m_scanFolderID = InvalidEntryId;//set it to default InvalidEntryId as this is no longer exists
  1443. }
  1444. }
  1445. return succeeded;
  1446. }
  1447. bool AssetDatabaseConnection::GetSourceBySourceID(AZ::s64 sourceID, SourceDatabaseEntry& entry)
  1448. {
  1449. bool found = false;
  1450. QuerySourceBySourceID( sourceID,
  1451. [&](SourceDatabaseEntry& source)
  1452. {
  1453. found = true;
  1454. entry = AZStd::move(source);
  1455. return false; // return false in order to stop iterating any further - we are only populating one entry.
  1456. });
  1457. return found;
  1458. }
  1459. bool AssetDatabaseConnection::GetSourceBySourceGuid(AZ::Uuid sourceGuid, SourceDatabaseEntry& entry)
  1460. {
  1461. bool found = false;
  1462. QuerySourceBySourceGuid(sourceGuid,
  1463. [&](SourceDatabaseEntry& source)
  1464. {
  1465. found = true;
  1466. entry = AZStd::move(source);
  1467. return false; // return false in order to stop iterating any further - we are only populating one entry.
  1468. });
  1469. return found;
  1470. }
  1471. bool AssetDatabaseConnection::GetSources(SourceDatabaseEntryContainer& container)
  1472. {
  1473. bool found = false;
  1474. bool succeeded = QuerySourcesTable(
  1475. [&](SourceDatabaseEntry& source)
  1476. {
  1477. found = true;
  1478. container.emplace_back() = AZStd::move(source);
  1479. return true; // return true to continue iterating over additional results, we are populating a container
  1480. });
  1481. return found && succeeded;
  1482. }
  1483. bool AssetDatabaseConnection::GetSourceBySourceNameScanFolderId(QString exactSourceName, AZ::s64 scanFolderID, AzToolsFramework::AssetDatabase::SourceDatabaseEntry& entry)
  1484. {
  1485. bool found = false;
  1486. bool succeeded = QuerySourceBySourceNameScanFolderID(exactSourceName.toUtf8().constData(),
  1487. scanFolderID,
  1488. [&](SourceDatabaseEntry& source)
  1489. {
  1490. found = true;
  1491. entry = AZStd::move(source);
  1492. return false; // return false in order to stop iterating any further - we are only populating one entry.
  1493. });
  1494. return found && succeeded;
  1495. }
  1496. bool AssetDatabaseConnection::GetSourcesBySourceName(QString exactSourceName, SourceDatabaseEntryContainer& container)
  1497. {
  1498. bool found = false;
  1499. bool succeeded = QuerySourceBySourceName(
  1500. exactSourceName.toUtf8().constData(),
  1501. [&](SourceDatabaseEntry& source)
  1502. {
  1503. found = true;
  1504. container.emplace_back() = AZStd::move(source);
  1505. return true; // return true to continue iterating over additional results, we are populating a container
  1506. });
  1507. return found && succeeded;
  1508. }
  1509. bool AssetDatabaseConnection::GetSourcesLikeSourceName(QString likeSourceName, LikeType likeType, SourceDatabaseEntryContainer& container)
  1510. {
  1511. if (likeSourceName.isEmpty())
  1512. {
  1513. return false;
  1514. }
  1515. bool found = false;
  1516. bool succeeded = QuerySourceLikeSourceName(likeSourceName.toUtf8().constData(), likeType,
  1517. [&](SourceDatabaseEntry& source)
  1518. {
  1519. found = true;
  1520. container.emplace_back() = AZStd::move(source);
  1521. return true; // return true to continue iterating over additional results, we are populating a container
  1522. });
  1523. return found && succeeded;
  1524. }
  1525. bool AssetDatabaseConnection::GetSourcesLikeSourceNameScanFolderId(
  1526. QString likeSourceName,
  1527. AZ::s64 scanFolderID,
  1528. LikeType likeType,
  1529. AzToolsFramework::AssetDatabase::SourceDatabaseEntryContainer& container)
  1530. {
  1531. if (likeSourceName.isEmpty())
  1532. {
  1533. return false;
  1534. }
  1535. bool found = false;
  1536. bool succeeded = QuerySourceLikeSourceNameScanFolderID(
  1537. likeSourceName.toUtf8().constData(), scanFolderID, likeType,
  1538. [&](SourceDatabaseEntry& source)
  1539. {
  1540. found = true;
  1541. container.emplace_back() = AZStd::move(source);
  1542. return true; // return true to continue iterating over additional results, we are populating a container
  1543. });
  1544. return found && succeeded;
  1545. }
  1546. bool AssetDatabaseConnection::GetSourceByJobID(AZ::s64 jobID, SourceDatabaseEntry& entry)
  1547. {
  1548. bool found = false;
  1549. QuerySourceByJobID( jobID,
  1550. [&](SourceDatabaseEntry& source)
  1551. {
  1552. found = true;
  1553. entry = AZStd::move(source);
  1554. return false; // stop after the first result
  1555. });
  1556. return found;
  1557. }
  1558. bool AssetDatabaseConnection::GetSourceByProductID(AZ::s64 productID, SourceDatabaseEntry& entry)
  1559. {
  1560. bool found = false;
  1561. QuerySourceByProductID( productID,
  1562. [&](SourceDatabaseEntry& source)
  1563. {
  1564. found = true;
  1565. entry = AZStd::move(source);
  1566. return false; // stop after the first result
  1567. });
  1568. return found;
  1569. }
  1570. bool AssetDatabaseConnection::GetSourcesByProductName(QString exactProductName, SourceDatabaseEntryContainer& container)
  1571. {
  1572. bool found = false;
  1573. bool succeeded = QueryCombinedByProductName(exactProductName.toUtf8().constData(),
  1574. [&](CombinedDatabaseEntry& combined)
  1575. {
  1576. found = true;
  1577. container.emplace_back() = AZStd::move(combined);
  1578. return true; // return true to continue collecting all
  1579. });
  1580. return found && succeeded;
  1581. }
  1582. bool AssetDatabaseConnection::GetSourcesLikeProductName(QString likeProductName, LikeType likeType, SourceDatabaseEntryContainer& container)
  1583. {
  1584. bool found = false;
  1585. bool succeeded = QueryCombinedLikeProductName(likeProductName.toUtf8().constData(), likeType,
  1586. [&](CombinedDatabaseEntry& combined)
  1587. {
  1588. found = true;
  1589. container.emplace_back() = AZStd::move(combined);
  1590. return true;//all
  1591. });
  1592. return found && succeeded;
  1593. }
  1594. bool AssetDatabaseConnection::SetSource(SourceDatabaseEntry& entry)
  1595. {
  1596. if (entry.m_sourceID == InvalidEntryId)
  1597. {
  1598. //they didn't supply an id, add to database
  1599. //first make sure its not already in the database
  1600. SourceDatabaseEntry existingEntry;
  1601. if (GetSourceBySourceGuid(entry.m_sourceGuid, existingEntry))
  1602. {
  1603. // this source guid already exists. note that the UUID is final, there is only ever one UUID for a source
  1604. // if folders override each other, the UUID stays the same but the scanfolder field changes but its still considered the same source file.
  1605. entry.m_sourceID = existingEntry.m_sourceID;
  1606. return SetSource(entry); // now update the existing field
  1607. }
  1608. if (!s_InsertSourceQuery.BindAndStep(*m_databaseConnection, entry.m_scanFolderPK, entry.m_sourceName.c_str(), entry.m_sourceGuid, entry.m_analysisFingerprint.c_str()))
  1609. {
  1610. AZ_Warning(LOG_NAME, false, "Failed to write the new source into the database. %s", entry.m_sourceName.c_str());
  1611. return false;
  1612. }
  1613. //now that its in the database get the id:
  1614. entry.m_sourceID = m_databaseConnection->GetLastRowID();
  1615. AzToolsFramework::AssetDatabase::AssetDatabaseNotificationBus::Broadcast(
  1616. &AzToolsFramework::AssetDatabase::AssetDatabaseNotificationBus::Events::OnSourceFileChanged, entry);
  1617. return true;
  1618. }
  1619. else
  1620. {
  1621. //they supplied an id, see if it exists in the database
  1622. SourceDatabaseEntry existingEntry;
  1623. if (!GetSourceBySourceID(entry.m_sourceID, existingEntry))
  1624. {
  1625. //they supplied an id but is not in the database!
  1626. AZ_Error(LOG_NAME, false, "Failed to write the source into the database.");
  1627. return false;
  1628. }
  1629. // don't bother updating the database if all fields are equal.
  1630. // note that we already looked it up by source ID
  1631. if ((existingEntry.m_scanFolderPK == entry.m_scanFolderPK) &&
  1632. (existingEntry.m_sourceGuid == entry.m_sourceGuid) &&
  1633. (existingEntry.m_sourceName == entry.m_sourceName) &&
  1634. (existingEntry.m_analysisFingerprint == entry.m_analysisFingerprint)
  1635. )
  1636. {
  1637. return true;
  1638. }
  1639. 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());
  1640. if (bindResult)
  1641. {
  1642. AzToolsFramework::AssetDatabase::AssetDatabaseNotificationBus::Broadcast(
  1643. &AzToolsFramework::AssetDatabase::AssetDatabaseNotificationBus::Events::OnSourceFileChanged, entry);
  1644. }
  1645. return bindResult;
  1646. }
  1647. }
  1648. bool AssetDatabaseConnection::InvalidateSourceAnalysisFingerprints()
  1649. {
  1650. return m_databaseConnection->ExecuteOneOffStatement(INVALIDATE_SOURCE_ANALYSISFINGEPRINTS);
  1651. }
  1652. // this must actually delete the source
  1653. bool AssetDatabaseConnection::RemoveSource(AZ::s64 sourceID)
  1654. {
  1655. ScopedTransaction transaction(m_databaseConnection);
  1656. if (!s_DeleteSourceQuery.BindAndStep(*m_databaseConnection, sourceID))
  1657. {
  1658. return false;
  1659. }
  1660. transaction.Commit();
  1661. AzToolsFramework::AssetDatabase::AssetDatabaseNotificationBus::Broadcast(
  1662. &AzToolsFramework::AssetDatabase::AssetDatabaseNotificationBus::Events::OnSourceFileRemoved, sourceID);
  1663. return true;
  1664. }
  1665. bool AssetDatabaseConnection::RemoveSources(SourceDatabaseEntryContainer& container)
  1666. {
  1667. bool succeeded = true;
  1668. for (auto& entry : container)
  1669. {
  1670. succeeded &= RemoveSource(entry.m_sourceID);
  1671. if (succeeded)
  1672. {
  1673. entry.m_sourceID = InvalidEntryId;//set it to InvalidEntryId as it no longer exists
  1674. }
  1675. }
  1676. return succeeded;
  1677. }
  1678. bool AssetDatabaseConnection::RemoveSourcesByScanFolderID(AZ::s64 scanFolderID)
  1679. {
  1680. bool found = false;
  1681. bool succeeded = QuerySourceByScanFolderID(scanFolderID,
  1682. [&](SourceDatabaseEntry& source)
  1683. {
  1684. found = true;
  1685. succeeded &= RemoveSource(source.m_sourceID);
  1686. return true;//all
  1687. });
  1688. return found && succeeded;
  1689. }
  1690. AZ::s64 AssetDatabaseConnection::GetHighestJobRunKey()
  1691. {
  1692. if (!m_databaseConnection)
  1693. {
  1694. return 0;
  1695. }
  1696. StatementAutoFinalizer autoFinal;
  1697. if (!s_GetHighestJobrunkeyQuery.Bind(*m_databaseConnection, autoFinal))
  1698. {
  1699. return 0;
  1700. }
  1701. Statement* statement = autoFinal.Get();
  1702. if (statement->Step() == Statement::SqlError)
  1703. {
  1704. // this is okay, since the table may be empty.
  1705. return 0;
  1706. }
  1707. return statement->GetColumnInt64(0);
  1708. }
  1709. bool AssetDatabaseConnection::GetJobs(JobDatabaseEntryContainer& container, AZ::Uuid builderGuid, QString jobKey, QString platform, JobStatus status)
  1710. {
  1711. bool found = false;
  1712. bool succeeded = QueryJobsTable(
  1713. [&](JobDatabaseEntry& job)
  1714. {
  1715. found = true;
  1716. container.emplace_back() = AZStd::move(job);
  1717. return true;//all
  1718. }, builderGuid,
  1719. jobKey.isEmpty() ? nullptr : jobKey.toUtf8().constData(),
  1720. platform.isEmpty() ? nullptr : platform.toUtf8().constData(),
  1721. status);
  1722. return found && succeeded;
  1723. }
  1724. bool AssetDatabaseConnection::GetJobByJobID(AZ::s64 jobID, JobDatabaseEntry& entry)
  1725. {
  1726. bool found = false;
  1727. QueryJobByJobID( jobID,
  1728. [&](JobDatabaseEntry& job)
  1729. {
  1730. found = true;
  1731. entry = AZStd::move(job);
  1732. return false; // stop after the first result
  1733. });
  1734. return found;
  1735. }
  1736. bool AssetDatabaseConnection::GetJobByProductID(AZ::s64 productID, JobDatabaseEntry& entry)
  1737. {
  1738. bool found = false;
  1739. QueryJobByProductID(productID,
  1740. [&](JobDatabaseEntry& job)
  1741. {
  1742. found = true;
  1743. entry = AZStd::move(job);
  1744. return false; // stop after the first result
  1745. });
  1746. return found;
  1747. }
  1748. bool AssetDatabaseConnection::GetJobsBySourceID(AZ::s64 sourceID, JobDatabaseEntryContainer& container, AZ::Uuid builderGuid, QString jobKey, QString platform, JobStatus status)
  1749. {
  1750. bool found = false;
  1751. bool succeeded = QueryJobBySourceID(sourceID,
  1752. [&](JobDatabaseEntry& job)
  1753. {
  1754. found = true;
  1755. container.emplace_back() = AZStd::move(job);
  1756. return true; // continue to fetch more rows.
  1757. }, builderGuid,
  1758. jobKey.isEmpty() ? nullptr : jobKey.toUtf8().constData(),
  1759. platform.isEmpty() ? nullptr : platform.toUtf8().constData(),
  1760. status);
  1761. return found && succeeded;
  1762. }
  1763. bool AssetDatabaseConnection::GetJobsBySourceName(const SourceAssetReference& sourceAsset, JobDatabaseEntryContainer& container, AZ::Uuid builderGuid, QString jobKey, QString platform, JobStatus status)
  1764. {
  1765. bool found = false;
  1766. bool succeeded = QuerySourceBySourceNameScanFolderID(sourceAsset.RelativePath().c_str(), sourceAsset.ScanFolderId(),
  1767. [&](SourceDatabaseEntry& source)
  1768. {
  1769. succeeded = QueryJobBySourceID(source.m_sourceID,
  1770. [&](JobDatabaseEntry& job)
  1771. {
  1772. found = true;
  1773. container.emplace_back() = AZStd::move(job);
  1774. return true;//all
  1775. }, builderGuid,
  1776. jobKey.isEmpty() ? nullptr : jobKey.toUtf8().constData(),
  1777. platform.isEmpty() ? nullptr : platform.toUtf8().constData(),
  1778. status);
  1779. return true; // continue to fetch more rows.
  1780. });
  1781. return found && succeeded;
  1782. }
  1783. bool AssetDatabaseConnection::GetJobsLikeSourceName(QString likeSourceName, LikeType likeType, JobDatabaseEntryContainer& container, AZ::Uuid builderGuid, QString jobKey, QString platform, JobStatus status)
  1784. {
  1785. if (likeSourceName.isEmpty())
  1786. {
  1787. return false;
  1788. }
  1789. bool found = false;
  1790. bool succeeded = QuerySourceLikeSourceName(likeSourceName.toUtf8().constData(), likeType,
  1791. [&](SourceDatabaseEntry& source)
  1792. {
  1793. succeeded = QueryJobBySourceID(source.m_sourceID,
  1794. [&](JobDatabaseEntry& job)
  1795. {
  1796. found = true;
  1797. container.emplace_back() = AZStd::move(job);
  1798. return true;//all
  1799. }, builderGuid,
  1800. jobKey.isEmpty() ? nullptr : jobKey.toUtf8().constData(),
  1801. platform.isEmpty() ? nullptr : platform.toUtf8().constData(),
  1802. status);
  1803. return true; // continue to fetch more rows.
  1804. });
  1805. return found && succeeded;
  1806. }
  1807. bool AssetDatabaseConnection::GetJobsByFailureCauseSourceId(AZ::s64 sourceID, AzToolsFramework::AssetDatabase::JobDatabaseEntryContainer& container)
  1808. {
  1809. bool found = false;
  1810. bool succeeded = QueryJobsByFailureCauseSourceID(
  1811. sourceID,
  1812. [&found, &container](JobDatabaseEntry& job)
  1813. {
  1814. found = true;
  1815. container.emplace_back() = AZStd::move(job);
  1816. return true;
  1817. });
  1818. return found && succeeded;
  1819. }
  1820. bool AssetDatabaseConnection::GetJobsByProductName(QString exactProductName, JobDatabaseEntryContainer& container, AZ::Uuid builderGuid, QString jobKey, QString platform, JobStatus status)
  1821. {
  1822. bool found = false;
  1823. bool succeeded = QueryProductByProductName(exactProductName.toUtf8().constData(),
  1824. [&](ProductDatabaseEntry& product)
  1825. {
  1826. succeeded = QueryJobByProductID(product.m_productID,
  1827. [&](JobDatabaseEntry& job)
  1828. {
  1829. found = true;
  1830. container.emplace_back() = AZStd::move(job);
  1831. return true;//all
  1832. });
  1833. return true; // continue to fetch more rows.
  1834. }, builderGuid,
  1835. jobKey.isEmpty() ? nullptr : jobKey.toUtf8().constData(),
  1836. platform.isEmpty() ? nullptr : platform.toUtf8().constData(),
  1837. status);
  1838. return found && succeeded;
  1839. }
  1840. bool AssetDatabaseConnection::GetJobsLikeProductName(QString likeProductName, LikeType likeType, JobDatabaseEntryContainer& container, AZ::Uuid builderGuid, QString jobKey, QString platform, JobStatus status)
  1841. {
  1842. bool found = false;
  1843. bool succeeded = QueryProductLikeProductName(likeProductName.toUtf8().constData(), likeType,
  1844. [&](ProductDatabaseEntry& product)
  1845. {
  1846. succeeded = QueryJobByProductID(product.m_productID,
  1847. [&](JobDatabaseEntry& job)
  1848. {
  1849. found = true;
  1850. container.emplace_back() = AZStd::move(job);
  1851. return true; // continue to fetch more rows for the QueryJobByProductId call
  1852. });
  1853. return true; // continue to fetch more rows for the QueryProductLikeProductName call
  1854. }, builderGuid,
  1855. jobKey.isEmpty() ? nullptr : jobKey.toUtf8().constData(),
  1856. platform.isEmpty() ? nullptr : platform.toUtf8().constData(),
  1857. status);
  1858. return found && succeeded;
  1859. }
  1860. bool AssetDatabaseConnection::SetJob(JobDatabaseEntry& entry)
  1861. {
  1862. if (entry.m_jobRunKey <= 0)
  1863. {
  1864. AZ_Error(LOG_NAME, false, "You must specify a valid Job Run Key for a job to make it into the database.\n");
  1865. return false;
  1866. }
  1867. if (entry.m_jobID == InvalidEntryId)
  1868. {
  1869. //they didn't supply an id, add to database
  1870. //make sure its not already in the database
  1871. JobDatabaseEntryContainer existingJobs;
  1872. if (GetJobsBySourceID(entry.m_sourcePK, existingJobs, entry.m_builderGuid, entry.m_jobKey.c_str(), entry.m_platform.c_str()))
  1873. {
  1874. //see if this job is already here
  1875. for (const auto& existingjob : existingJobs)
  1876. {
  1877. if (existingjob == entry)
  1878. {
  1879. //this job already exists
  1880. entry.m_jobID = existingjob.m_jobID;
  1881. return true;
  1882. }
  1883. }
  1884. }
  1885. if (!s_InsertJobQuery.BindAndStep(*m_databaseConnection, entry.m_sourcePK, entry.m_jobKey.c_str(), entry.m_fingerprint, entry.m_platform.c_str(),
  1886. entry.m_builderGuid, static_cast<int>(entry.m_status), entry.m_jobRunKey, entry.m_failureCauseSourcePK, entry.m_failureCauseFingerprint, entry.m_firstFailLogTime, entry.m_firstFailLogFile.c_str(),
  1887. entry.m_lastFailLogTime, entry.m_lastFailLogFile.c_str(), entry.m_lastLogTime, entry.m_lastLogFile.c_str(), entry.m_warningCount, entry.m_errorCount))
  1888. {
  1889. return false;
  1890. }
  1891. //make sure its now in the database
  1892. existingJobs.clear();
  1893. if (GetJobsBySourceID(entry.m_sourcePK, existingJobs, entry.m_builderGuid, entry.m_jobKey.c_str(), entry.m_platform.c_str()))
  1894. {
  1895. //see if this job is already here
  1896. for (const auto& existingjob : existingJobs)
  1897. {
  1898. if (existingjob == entry)
  1899. {
  1900. //this job already exists
  1901. entry.m_jobID = existingjob.m_jobID;
  1902. return true;
  1903. }
  1904. }
  1905. }
  1906. AZ_Warning(LOG_NAME, false, "Failed to read the new job from the database.");
  1907. return false;
  1908. }
  1909. else
  1910. {
  1911. //they supplied an id, see if it exists in the database
  1912. JobDatabaseEntry existingEntry;
  1913. if (!GetJobByJobID(entry.m_jobID, existingEntry))
  1914. {
  1915. AZ_Error(LOG_NAME, false, "Failed to find the job in the database.");
  1916. return false;
  1917. }
  1918. //its in the database already, if its not the same update the database
  1919. if (existingEntry == entry)
  1920. {
  1921. return true;
  1922. }
  1923. return s_UpdateJobQuery.BindAndStep(*m_databaseConnection, entry.m_sourcePK, entry.m_jobKey.c_str(), entry.m_fingerprint, entry.m_platform.c_str(),
  1924. entry.m_builderGuid, static_cast<int>(entry.m_status), entry.m_jobRunKey, entry.m_failureCauseSourcePK, entry.m_failureCauseFingerprint, entry.m_firstFailLogTime, entry.m_firstFailLogFile.c_str(),
  1925. 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);
  1926. }
  1927. }
  1928. bool AssetDatabaseConnection::SetJobFingerprintsBySourceID(AZ::s64 sourceID, AZ::u64 hash)
  1929. {
  1930. if (!s_SetJobFingerprintsBySourceIDQuery.BindAndStep(*m_databaseConnection, hash, sourceID))
  1931. {
  1932. return false;
  1933. }
  1934. return m_databaseConnection->GetNumAffectedRows() > 0;
  1935. }
  1936. // this must actually delete the job
  1937. bool AssetDatabaseConnection::RemoveJob(AZ::s64 jobID)
  1938. {
  1939. ScopedTransaction transaction(m_databaseConnection);
  1940. if(!s_DeleteJobQuery.BindAndStep(*m_databaseConnection, jobID))
  1941. {
  1942. return false;
  1943. }
  1944. transaction.Commit();
  1945. return true;
  1946. }
  1947. bool AssetDatabaseConnection::RemoveJobs(JobDatabaseEntryContainer& container)
  1948. {
  1949. bool succeeded = true;
  1950. for (auto& entry : container)
  1951. {
  1952. succeeded &= RemoveJob(entry.m_jobID);
  1953. if (succeeded)
  1954. {
  1955. entry.m_jobID = InvalidEntryId; //set it to InvalidEntryId as the id is no longer valid
  1956. }
  1957. }
  1958. return succeeded;
  1959. }
  1960. bool AssetDatabaseConnection::RemoveJobByProductID(AZ::s64 productID)
  1961. {
  1962. JobDatabaseEntry job;
  1963. bool succeeded = GetJobByProductID(productID, job);
  1964. if (succeeded)
  1965. {
  1966. succeeded &= RemoveJob(job.m_jobID);
  1967. }
  1968. return succeeded;
  1969. }
  1970. bool AssetDatabaseConnection::GetProductByProductID(AZ::s64 productID, ProductDatabaseEntry& entry)
  1971. {
  1972. bool found = false;
  1973. QueryProductByProductID(productID,
  1974. [&](ProductDatabaseEntry& product)
  1975. {
  1976. found = true;
  1977. entry = AZStd::move(product);
  1978. return false; // stop after the first one is found.
  1979. });
  1980. return found;
  1981. }
  1982. bool AssetDatabaseConnection::GetProducts(ProductDatabaseEntryContainer& container, AZ::Uuid builderGuid, QString jobKey, QString platform, JobStatus status)
  1983. {
  1984. bool found = false;
  1985. bool succeeded = QueryProductsTable(
  1986. [&](ProductDatabaseEntry& product)
  1987. {
  1988. found = true;
  1989. container.emplace_back() = AZStd::move(product);
  1990. return true; // continue fetching more results.
  1991. }, builderGuid,
  1992. jobKey.isEmpty() ? nullptr : jobKey.toUtf8().constData(),
  1993. platform.isEmpty() ? nullptr : platform.toUtf8().constData(),
  1994. status);
  1995. return found && succeeded;
  1996. }
  1997. bool AssetDatabaseConnection::GetProductsByProductName(QString exactProductName, ProductDatabaseEntryContainer& container, AZ::Uuid builderGuid, QString jobKey, QString platform, JobStatus status)
  1998. {
  1999. bool found = false;
  2000. bool succeeded = QueryProductByProductName(exactProductName.toUtf8().constData(),
  2001. [&](ProductDatabaseEntry& product)
  2002. {
  2003. found = true;
  2004. container.emplace_back() = AZStd::move(product);
  2005. return true; // continue fetching more results.
  2006. }, builderGuid,
  2007. jobKey.isEmpty() ? nullptr : jobKey.toUtf8().constData(),
  2008. platform.isEmpty() ? nullptr : platform.toUtf8().constData(),
  2009. status);
  2010. return found && succeeded;
  2011. }
  2012. bool AssetDatabaseConnection::GetProductsLikeProductName(QString likeProductName, LikeType likeType, ProductDatabaseEntryContainer& container, AZ::Uuid builderGuid, QString jobKey, QString platform, JobStatus status)
  2013. {
  2014. bool found = false;
  2015. if (likeProductName.isEmpty())
  2016. {
  2017. return false;
  2018. }
  2019. bool succeeded = QueryProductLikeProductName(likeProductName.toUtf8().constData(), likeType,
  2020. [&](ProductDatabaseEntry& product)
  2021. {
  2022. found = true;
  2023. container.emplace_back() = AZStd::move(product);
  2024. return true; // continue fetching more results.
  2025. }, builderGuid,
  2026. jobKey.isEmpty() ? nullptr : jobKey.toUtf8().constData(),
  2027. platform.isEmpty() ? nullptr : platform.toUtf8().constData(),
  2028. status);
  2029. return found && succeeded;
  2030. }
  2031. bool AssetDatabaseConnection::GetProductsBySourceName(QString exactSourceName, ProductDatabaseEntryContainer& container, AZ::Uuid builderGuid, QString jobKey, QString platform, JobStatus status)
  2032. {
  2033. bool found = false;
  2034. bool succeeded = QueryProductBySourceName(exactSourceName.toUtf8().constData(),
  2035. [&](ProductDatabaseEntry& product)
  2036. {
  2037. found = true;
  2038. container.emplace_back() = AZStd::move(product);
  2039. return true; // continue fetching more results.
  2040. }, builderGuid,
  2041. jobKey.isEmpty() ? nullptr : jobKey.toUtf8().constData(),
  2042. platform.isEmpty() ? nullptr : platform.toUtf8().constData(),
  2043. status);
  2044. return found && succeeded;
  2045. }
  2046. bool AssetDatabaseConnection::GetProductsBySourceNameScanFolderID(QString exactSourceName, AZ::s64 scanFolderId, ProductDatabaseEntryContainer& container, AZ::Uuid builderGuid, QString jobKey, QString platform, JobStatus status)
  2047. {
  2048. bool found = false;
  2049. bool succeeded = QueryProductBySourceNameScanFolderID(exactSourceName.toUtf8().constData(), scanFolderId,
  2050. [&](ProductDatabaseEntry& product)
  2051. {
  2052. found = true;
  2053. container.emplace_back() = AZStd::move(product);
  2054. return true; // continue fetching more results.
  2055. }, builderGuid,
  2056. jobKey.isEmpty() ? nullptr : jobKey.toUtf8().constData(),
  2057. platform.isEmpty() ? nullptr : platform.toUtf8().constData(),
  2058. status);
  2059. return found && succeeded;
  2060. }
  2061. bool AssetDatabaseConnection::GetProductsLikeSourceName(QString likeSourceName, LikeType likeType, ProductDatabaseEntryContainer& container, AZ::Uuid builderGuid, QString jobKey, QString platform, JobStatus status)
  2062. {
  2063. if (likeSourceName.isEmpty())
  2064. {
  2065. return false;
  2066. }
  2067. bool found = false;
  2068. bool succeeded = QueryProductLikeSourceName(likeSourceName.toUtf8().constData(), likeType,
  2069. [&](ProductDatabaseEntry& product)
  2070. {
  2071. found = true;
  2072. container.emplace_back() = AZStd::move(product);
  2073. return true; // continue fetching more results.
  2074. }, builderGuid,
  2075. jobKey.isEmpty() ? nullptr : jobKey.toUtf8().constData(),
  2076. platform.isEmpty() ? nullptr : platform.toUtf8().constData(),
  2077. status);
  2078. return found && succeeded;
  2079. }
  2080. bool AssetDatabaseConnection::GetProductsBySourceID(AZ::s64 sourceID, ProductDatabaseEntryContainer& container, AZ::Uuid builderGuid, QString jobKey, QString platform, JobStatus status)
  2081. {
  2082. bool found = false;
  2083. bool succeeded = QueryCombinedBySourceID(sourceID,
  2084. [&](CombinedDatabaseEntry& combined)
  2085. {
  2086. found = true;
  2087. container.emplace_back() = AZStd::move(combined);
  2088. return true; // continue fetching more results.
  2089. }, builderGuid,
  2090. jobKey.isEmpty() ? nullptr : jobKey.toUtf8().constData(),
  2091. platform.isEmpty() ? nullptr : platform.toUtf8().constData(),
  2092. status);
  2093. return found && succeeded;
  2094. }
  2095. bool AssetDatabaseConnection::GetProductsByJobID(AZ::s64 jobID, ProductDatabaseEntryContainer& container)
  2096. {
  2097. bool found = false;
  2098. bool succeeded = QueryCombinedByJobID(jobID,
  2099. [&](CombinedDatabaseEntry& combined)
  2100. {
  2101. found = true;
  2102. container.emplace_back() = AZStd::move(combined);
  2103. return true; // continue fetching more results.
  2104. });
  2105. return found && succeeded;
  2106. }
  2107. bool AssetDatabaseConnection::GetProductByJobIDSubId(AZ::s64 jobID, AZ::u32 subID, AzToolsFramework::AssetDatabase::ProductDatabaseEntry& result)
  2108. {
  2109. bool found = false;
  2110. QueryProductByJobIDSubID(jobID, subID,
  2111. [&](ProductDatabaseEntry& resultFromDB)
  2112. {
  2113. found = true;
  2114. result = AZStd::move(resultFromDB);
  2115. return false; // stop after the first result
  2116. });
  2117. return found;
  2118. }
  2119. bool AssetDatabaseConnection::GetProductBySourceGuidSubId(AZ::Uuid sourceGuid, AZ::u32 subId, AzToolsFramework::AssetDatabase::ProductDatabaseEntry& result)
  2120. {
  2121. bool found = false;
  2122. QueryProductBySourceGuidSubID(sourceGuid, subId,
  2123. [&](ProductDatabaseEntry& resultFromDB)
  2124. {
  2125. found = true;
  2126. result = AZStd::move(resultFromDB);
  2127. return false; // stop after the first result
  2128. });
  2129. return found;
  2130. }
  2131. //! For a given source, set the list of products for that source.
  2132. //! Removes any data that's present and overwrites it with the new list
  2133. //! Note that an empty list is in fact acceptable data, it means the source emitted no products
  2134. bool AssetDatabaseConnection::SetProduct(ProductDatabaseEntry& entry)
  2135. {
  2136. bool wasAlreadyInDatabase = false;
  2137. ProductDatabaseEntry existingProductInDatabase;
  2138. if (entry.m_productID == InvalidEntryId)
  2139. {
  2140. // they didn't set an id, add to database
  2141. // but make sure its not already in the database before doing so:
  2142. if (GetProductByJobIDSubId(entry.m_jobPK, entry.m_subID, existingProductInDatabase))
  2143. {
  2144. wasAlreadyInDatabase = true;
  2145. }
  2146. }
  2147. else
  2148. {
  2149. if (GetProductByProductID(entry.m_productID, existingProductInDatabase))
  2150. {
  2151. wasAlreadyInDatabase = true;
  2152. }
  2153. else
  2154. {
  2155. // its not OK to be pushing specific IDs into the database that don't exist.
  2156. 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);
  2157. return false;
  2158. }
  2159. }
  2160. // we can early out if it was in the database and the database entry is identical to the new one:
  2161. if (wasAlreadyInDatabase)
  2162. {
  2163. entry.m_productID = existingProductInDatabase.m_productID;
  2164. if (entry == existingProductInDatabase)
  2165. {
  2166. return true;
  2167. }
  2168. }
  2169. // if we get here, we need to either insert or update in the database.
  2170. {
  2171. // note, intentional scope created for the statement finalizer
  2172. StatementAutoFinalizer autoFinalizer;
  2173. if (wasAlreadyInDatabase)
  2174. {
  2175. // it was already in the database, so use the "UPDATE" version
  2176. 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_flags.to_ullong(), entry.m_productID, entry.m_hash))
  2177. {
  2178. return false;
  2179. }
  2180. }
  2181. else
  2182. {
  2183. // it wasn't in the database, so use the "INSERT" version
  2184. if (!s_InsertProductQuery.Bind(*m_databaseConnection, autoFinalizer, entry.m_jobPK, entry.m_subID, entry.m_productName.c_str(), entry.m_assetType, entry.m_legacyGuid, entry.m_hash, entry.m_flags.to_ullong()))
  2185. {
  2186. return false;
  2187. }
  2188. }
  2189. Statement* statement = autoFinalizer.Get();
  2190. if(statement->Step() == Statement::SqlError)
  2191. {
  2192. AZ_Error(LOG_NAME, false, "Failed to execute the %s statement", wasAlreadyInDatabase ? UPDATE_PRODUCT : INSERT_PRODUCT);
  2193. return false;
  2194. }
  2195. if (!wasAlreadyInDatabase)
  2196. {
  2197. // just read what the last inserted row ID is.
  2198. // (this is why database access must only be one thread per connection, as this could otherwise
  2199. // be mutated by the other thread. its stored on the connection object, not a TLS variable)
  2200. entry.m_productID = m_databaseConnection->GetLastRowID();
  2201. }
  2202. AzToolsFramework::AssetDatabase::AssetDatabaseNotificationBus::Broadcast(
  2203. &AzToolsFramework::AssetDatabase::AssetDatabaseNotificationBus::Events::OnProductFileChanged, entry);
  2204. }
  2205. return true;
  2206. }
  2207. bool AssetDatabaseConnection::SetProducts(ProductDatabaseEntryContainer& container)
  2208. {
  2209. if (container.empty())
  2210. {
  2211. return false;
  2212. }
  2213. ScopedTransaction transaction(m_databaseConnection);
  2214. for (auto& entry : container)
  2215. {
  2216. if(!SetProduct(entry))
  2217. {
  2218. return false;
  2219. }
  2220. }
  2221. transaction.Commit();
  2222. return true;
  2223. }
  2224. //! Clear the products for a given source. This removes the entry entirely, not just sets it to empty.
  2225. bool AssetDatabaseConnection::RemoveProduct(AZ::s64 productID)
  2226. {
  2227. ScopedTransaction transaction(m_databaseConnection);
  2228. if (!s_DeleteProductQuery.BindAndStep(*m_databaseConnection, productID))
  2229. {
  2230. return false;
  2231. }
  2232. bool wasEffective = (m_databaseConnection->GetNumAffectedRows() != 0);
  2233. transaction.Commit();
  2234. if (wasEffective)
  2235. {
  2236. AzToolsFramework::AssetDatabase::AssetDatabaseNotificationBus::Broadcast(
  2237. &AzToolsFramework::AssetDatabase::AssetDatabaseNotificationBus::Events::OnProductFileRemoved, productID);
  2238. }
  2239. return wasEffective;
  2240. }
  2241. bool AssetDatabaseConnection::RemoveProducts(ProductDatabaseEntryContainer& container)
  2242. {
  2243. if (container.empty())
  2244. {
  2245. return false;
  2246. }
  2247. bool succeeded = true;
  2248. for (auto& entry : container)
  2249. {
  2250. succeeded &= RemoveProduct(entry.m_productID);
  2251. if (succeeded)
  2252. {
  2253. entry.m_productID = InvalidEntryId;
  2254. }
  2255. }
  2256. return succeeded;
  2257. }
  2258. bool AssetDatabaseConnection::RemoveProductsByJobID(AZ::s64 jobID)
  2259. {
  2260. ScopedTransaction transaction(m_databaseConnection);
  2261. ProductDatabaseEntryContainer productsToRemove;
  2262. GetProductsByJobID(jobID, productsToRemove);
  2263. if (!s_DeleteProductsByJobidQuery.BindAndStep(*m_databaseConnection, jobID))
  2264. {
  2265. return false;
  2266. }
  2267. bool wasEffective = (m_databaseConnection->GetNumAffectedRows() != 0);
  2268. transaction.Commit();
  2269. if (wasEffective)
  2270. {
  2271. AzToolsFramework::AssetDatabase::AssetDatabaseNotificationBus::Broadcast(
  2272. &AzToolsFramework::AssetDatabase::AssetDatabaseNotificationBus::Events::OnProductFilesRemoved, productsToRemove);
  2273. }
  2274. return wasEffective;
  2275. }
  2276. bool AssetDatabaseConnection::RemoveProductsBySourceID(AZ::s64 sourceID, AZ::Uuid builderGuid, QString jobKey, QString platform, JobStatus status)
  2277. {
  2278. ProductDatabaseEntryContainer products;
  2279. bool getProductsSucceeded = GetProductsBySourceID(sourceID, products, builderGuid, jobKey, platform, status);
  2280. if ( (!builderGuid.IsNull()) || (jobKey != nullptr) || (status != AssetSystem::JobStatus::Any) )
  2281. {
  2282. //we have to do custom query the delete
  2283. if (getProductsSucceeded)
  2284. {
  2285. getProductsSucceeded &= RemoveProducts(products);
  2286. }
  2287. return getProductsSucceeded;
  2288. }
  2289. ScopedTransaction transaction(m_databaseConnection);
  2290. if(!platform.isEmpty())
  2291. {
  2292. AZStd::string platformStr = platform.toUtf8().constData();
  2293. if (!s_DeleteProductsBySourceidPlatformQuery.BindAndStep(*m_databaseConnection, sourceID, platformStr.c_str()))
  2294. {
  2295. return false;
  2296. }
  2297. }
  2298. else if(!s_DeleteProductsBySourceidQuery.BindAndStep(*m_databaseConnection, sourceID))
  2299. {
  2300. return false;
  2301. }
  2302. bool wasEffective = (m_databaseConnection->GetNumAffectedRows() != 0);
  2303. transaction.Commit();
  2304. if (wasEffective && getProductsSucceeded)
  2305. {
  2306. AzToolsFramework::AssetDatabase::AssetDatabaseNotificationBus::Broadcast(
  2307. &AzToolsFramework::AssetDatabase::AssetDatabaseNotificationBus::Events::OnProductFilesRemoved, products);
  2308. }
  2309. return wasEffective;
  2310. }
  2311. bool AssetDatabaseConnection::GetJobInfoByJobID(AZ::s64 jobID, JobInfo& entry)
  2312. {
  2313. bool found = false;
  2314. QueryJobInfoByJobID(jobID,
  2315. [&](JobInfo& jobInfo)
  2316. {
  2317. found = true;
  2318. entry = AZStd::move(jobInfo);
  2319. return false; // stop after the first result
  2320. });
  2321. return found;
  2322. }
  2323. bool AssetDatabaseConnection::GetJobInfoByJobKey(AZStd::string jobKey, JobInfoContainer& container)
  2324. {
  2325. bool found = false;
  2326. bool succeeded = QueryJobInfoByJobKey(jobKey,
  2327. [&](JobInfo& jobInfo)
  2328. {
  2329. found = true;
  2330. container.emplace_back() = AZStd::move(jobInfo);
  2331. return true; // return true to keep iterating over further rows.
  2332. });
  2333. return found && succeeded;
  2334. }
  2335. bool AssetDatabaseConnection::GetJobInfoByJobRunKey(AZ::u64 jobRunKey, JobInfoContainer& container)
  2336. {
  2337. bool found = false;
  2338. bool succeeded = QueryJobInfoByJobRunKey(jobRunKey,
  2339. [&](JobInfo& jobInfo)
  2340. {
  2341. found = true;
  2342. container.emplace_back() = AZStd::move(jobInfo);
  2343. return true; // return true to keep iterating over further rows.
  2344. });
  2345. return found && succeeded;
  2346. }
  2347. bool AssetDatabaseConnection::GetJobInfoBySourceNameScanFolderId(QString exactSourceName, AZ::s64 scanfolderId, JobInfoContainer& container, AZ::Uuid builderGuid, QString jobKey, QString platform, JobStatus status)
  2348. {
  2349. bool found = false;
  2350. bool succeeded = QueryJobInfoBySourceNameScanFolderId(exactSourceName.toUtf8().constData(), scanfolderId,
  2351. [&](JobInfo& jobInfo)
  2352. {
  2353. found = true;
  2354. container.emplace_back() = AZStd::move(jobInfo);
  2355. return true; // return true to keep iterating over further rows.
  2356. }, builderGuid,
  2357. jobKey.isEmpty() ? nullptr : jobKey.toUtf8().constData(),
  2358. platform.isEmpty() ? nullptr : platform.toUtf8().constData(),
  2359. status);
  2360. return found && succeeded;
  2361. }
  2362. bool AssetDatabaseConnection::SetSourceFileDependencies(SourceFileDependencyEntryContainer& container)
  2363. {
  2364. bool succeeded = true;
  2365. for (auto& entry : container)
  2366. {
  2367. succeeded = succeeded && SetSourceFileDependency(entry);
  2368. }
  2369. return succeeded;
  2370. }
  2371. bool AssetDatabaseConnection::SetSourceFileDependency(SourceFileDependencyEntry& entry)
  2372. {
  2373. //first make sure its not already in the database
  2374. if (!s_InsertSourceDependencyQuery.BindAndStep(*m_databaseConnection, entry.m_builderGuid, entry.m_sourceGuid, entry.m_dependsOnSource, entry.m_typeOfDependency, entry.m_fromAssetId, entry.m_subIds.c_str()))
  2375. {
  2376. return false;
  2377. }
  2378. entry.m_sourceDependencyID = m_databaseConnection->GetLastRowID();
  2379. return true;
  2380. }
  2381. bool AssetDatabaseConnection::RemoveSourceFileDependencies(const AZStd::unordered_set<AZ::s64>& container)
  2382. {
  2383. ScopedTransaction transaction(m_databaseConnection);
  2384. bool succeeded = true;
  2385. for (AZ::s64 entry : container)
  2386. {
  2387. succeeded = succeeded && RemoveSourceFileDependency(entry);
  2388. }
  2389. if (succeeded)
  2390. {
  2391. transaction.Commit();
  2392. return true;
  2393. }
  2394. return false;
  2395. }
  2396. bool AssetDatabaseConnection::RemoveSourceFileDependencies(const SourceFileDependencyEntryContainer& container)
  2397. {
  2398. AZStd::unordered_set<AZ::s64> uniqueRowIds;
  2399. for (const SourceFileDependencyEntry& item : container)
  2400. {
  2401. uniqueRowIds.insert(item.m_sourceDependencyID);
  2402. }
  2403. return RemoveSourceFileDependencies(uniqueRowIds);
  2404. }
  2405. bool AssetDatabaseConnection::RemoveSourceFileDependency(AZ::s64 sourceFileDependencyId)
  2406. {
  2407. return s_DeleteSourceDependencySourcedependencyidQuery.BindAndStep(*m_databaseConnection, sourceFileDependencyId);
  2408. }
  2409. bool AssetDatabaseConnection::GetSourceFileDependenciesByBuilderGUIDAndSource(const AZ::Uuid& builderGuid, AZ::Uuid sourceGuid, AzToolsFramework::AssetDatabase::SourceFileDependencyEntry::TypeOfDependency typeOfDependency, SourceFileDependencyEntryContainer& container)
  2410. {
  2411. bool found = false;
  2412. bool succeeded = QueryDependsOnSourceBySourceDependency(sourceGuid, typeOfDependency,
  2413. [&](SourceFileDependencyEntry& entry)
  2414. {
  2415. if (builderGuid == entry.m_builderGuid)
  2416. {
  2417. found = true;
  2418. container.emplace_back() = AZStd::move(entry);
  2419. }
  2420. return true; // return true to keep iterating over further rows.
  2421. });
  2422. return found && succeeded;
  2423. }
  2424. bool AssetDatabaseConnection::GetSourceFileDependenciesByDependsOnSource(AZ::Uuid sourceGuid, const char* sourceName, const char* absolutePath, AzToolsFramework::AssetDatabase::SourceFileDependencyEntry::TypeOfDependency typeOfDependency, SourceFileDependencyEntryContainer& container)
  2425. {
  2426. bool found = false;
  2427. bool succeeded = QuerySourceDependencyByDependsOnSource(sourceGuid, sourceName, absolutePath,typeOfDependency,
  2428. [&](SourceFileDependencyEntry& entry)
  2429. {
  2430. found = true;
  2431. container.emplace_back() = AZStd::move(entry);
  2432. return true; // return true to keep iterating over further rows.
  2433. });
  2434. return found && succeeded;
  2435. }
  2436. bool AssetDatabaseConnection::GetDependsOnSourceBySource(
  2437. AZ::Uuid sourceUuid,
  2438. AzToolsFramework::AssetDatabase::SourceFileDependencyEntry::TypeOfDependency typeOfDependency,
  2439. AzToolsFramework::AssetDatabase::SourceFileDependencyEntryContainer& container)
  2440. {
  2441. bool found = false;
  2442. bool succeeded = QueryDependsOnSourceBySourceDependency(sourceUuid, typeOfDependency,
  2443. [&](SourceFileDependencyEntry& entry)
  2444. {
  2445. found = true;
  2446. container.emplace_back() = AZStd::move(entry);
  2447. return true; // return true to keep iterating over further rows.
  2448. });
  2449. return found && succeeded;
  2450. }
  2451. bool AssetDatabaseConnection::GetSourceFileDependencyBySourceDependencyId(AZ::s64 sourceDependencyId, SourceFileDependencyEntry& sourceDependencyEntry)
  2452. {
  2453. bool found = false;
  2454. QuerySourceDependencyBySourceDependencyId(sourceDependencyId,
  2455. [&](SourceFileDependencyEntry& entry)
  2456. {
  2457. found = true;
  2458. sourceDependencyEntry = AZStd::move(entry);
  2459. return false; // stop after the first result
  2460. });
  2461. return found;
  2462. }
  2463. bool AssetDatabaseConnection::CreateOrUpdateLegacySubID(AzToolsFramework::AssetDatabase::LegacySubIDsEntry& entry)
  2464. {
  2465. ScopedTransaction transaction(m_databaseConnection);
  2466. bool creatingNew = entry.m_subIDsEntryID == InvalidEntryId;
  2467. if (creatingNew)
  2468. {
  2469. if (!s_InsertNewLegacysubidQuery.BindAndStep(*m_databaseConnection, entry.m_productPK, entry.m_subID))
  2470. {
  2471. return false;
  2472. }
  2473. }
  2474. else if (!s_OverwriteExistingLegacysubidQuery.BindAndStep(*m_databaseConnection, entry.m_productPK, entry.m_subID, entry.m_subIDsEntryID))
  2475. {
  2476. return false;
  2477. }
  2478. if (creatingNew)
  2479. {
  2480. AZ::s64 rowID = m_databaseConnection->GetLastRowID();
  2481. entry.m_subIDsEntryID = rowID;
  2482. }
  2483. else
  2484. {
  2485. if (m_databaseConnection->GetNumAffectedRows() == 0)
  2486. {
  2487. // you specified an invalid key.
  2488. AZ_Warning(LOG_NAME, false, "Failed to CreateOrUpdateLegacySubID in the database - invalid key specified.");
  2489. return false;
  2490. }
  2491. }
  2492. transaction.Commit();
  2493. return true;
  2494. }
  2495. bool AssetDatabaseConnection::RemoveLegacySubID(AZ::s64 legacySubIDsEntryID)
  2496. {
  2497. ScopedTransaction transaction(m_databaseConnection);
  2498. if (!s_DeleteLegacysubidsByPrimaryKeyQuery.BindAndStep(*m_databaseConnection, legacySubIDsEntryID))
  2499. {
  2500. return false;
  2501. }
  2502. transaction.Commit();
  2503. return true;
  2504. }
  2505. bool AssetDatabaseConnection::RemoveLegacySubIDsByProductID(AZ::s64 productID)
  2506. {
  2507. ScopedTransaction transaction(m_databaseConnection);
  2508. if (!s_DeleteLegacysubidsByProductidQuery.BindAndStep(*m_databaseConnection, productID))
  2509. {
  2510. return false;
  2511. }
  2512. transaction.Commit();
  2513. return true;
  2514. }
  2515. // ProductDependencies
  2516. bool AssetDatabaseConnection::GetProductDependencies(ProductDependencyDatabaseEntryContainer& container)
  2517. {
  2518. bool found = false;
  2519. bool succeeded = QueryProductDependenciesTable([&](AZ::Data::AssetId& /*assetId*/, ProductDependencyDatabaseEntry& entry)
  2520. {
  2521. found = true;
  2522. container.emplace_back() = AZStd::move(entry);
  2523. return true; // return true to keep iterating over further rows.
  2524. });
  2525. return found && succeeded;
  2526. }
  2527. bool AssetDatabaseConnection::GetProductDependencyByProductDependencyID(AZ::s64 productDependencyID, ProductDependencyDatabaseEntry& productDependencyEntry)
  2528. {
  2529. bool found = false;
  2530. QueryProductDependencyByProductDependencyId(productDependencyID,
  2531. [&](ProductDependencyDatabaseEntry& entry)
  2532. {
  2533. found = true;
  2534. productDependencyEntry = AZStd::move(entry);
  2535. return false; // stop after the first result
  2536. });
  2537. return found;
  2538. }
  2539. bool AssetDatabaseConnection::GetProductDependenciesByProductID(AZ::s64 productID, ProductDependencyDatabaseEntryContainer& container)
  2540. {
  2541. bool found = false;
  2542. bool succeeded = QueryProductDependencyByProductId(productID,
  2543. [&](ProductDependencyDatabaseEntry& entry)
  2544. {
  2545. found = true;
  2546. container.emplace_back() = AZStd::move(entry);
  2547. return true; // return true to keep iterating over further rows.
  2548. });
  2549. return found && succeeded;
  2550. }
  2551. bool AssetDatabaseConnection::GetDirectProductDependencies(AZ::s64 productID, AzToolsFramework::AssetDatabase::ProductDatabaseEntryContainer& container)
  2552. {
  2553. bool found = false;
  2554. bool succeeded = QueryDirectProductDependencies(productID,
  2555. [&](ProductDatabaseEntry& entry)
  2556. {
  2557. found = true;
  2558. container.emplace_back() = AZStd::move(entry);
  2559. return true; // return true to keep iterating over further rows.
  2560. });
  2561. return found && succeeded;
  2562. }
  2563. bool AssetDatabaseConnection::GetDirectReverseProductDependenciesBySourceGuidSubId(AZ::Uuid dependencySourceGuid, AZ::u32 dependencySubId, AzToolsFramework::AssetDatabase::ProductDatabaseEntryContainer& container)
  2564. {
  2565. bool found = false;
  2566. bool succeeded = QueryDirectReverseProductDependenciesBySourceGuidSubId(dependencySourceGuid, dependencySubId,
  2567. [&](ProductDatabaseEntry& entry)
  2568. {
  2569. found = true;
  2570. container.emplace_back() = AZStd::move(entry);
  2571. return true;
  2572. });
  2573. return found && succeeded;
  2574. }
  2575. bool AssetDatabaseConnection::GetDirectReverseProductDependenciesBySourceGuidAllPlatforms(AZ::Uuid dependencySourceGuid, AzToolsFramework::AssetDatabase::ProductDependencyDatabaseEntryContainer& container)
  2576. {
  2577. bool succeeded = QueryDirectReverseProductDependenciesBySourceGuidAllPlatforms(dependencySourceGuid, [&container](ProductDependencyDatabaseEntry entry)
  2578. {
  2579. container.emplace_back(AZStd::move(entry));
  2580. return true;
  2581. });
  2582. return succeeded;
  2583. }
  2584. bool AssetDatabaseConnection::GetAllProductDependencies(AZ::s64 productID, AzToolsFramework::AssetDatabase::ProductDatabaseEntryContainer& container)
  2585. {
  2586. bool found = false;
  2587. bool succeeded = QueryAllProductDependencies(productID,
  2588. [&](ProductDatabaseEntry& entry)
  2589. {
  2590. found = true;
  2591. container.emplace_back() = AZStd::move(entry);
  2592. return true; // return true to keep iterating over further rows.
  2593. });
  2594. return found && succeeded;
  2595. }
  2596. bool AssetDatabaseConnection::GetUnresolvedProductDependencies(AzToolsFramework::AssetDatabase::ProductDependencyDatabaseEntryContainer& container)
  2597. {
  2598. bool found = false;
  2599. bool succeeded = QueryUnresolvedProductDependencies(
  2600. [&](ProductDependencyDatabaseEntry& entry)
  2601. {
  2602. found = true;
  2603. container.emplace_back() = AZStd::move(entry);
  2604. return true; // return true to keep iterating over further rows.
  2605. });
  2606. return found && succeeded;
  2607. }
  2608. bool AssetDatabaseConnection::SetProductDependency(ProductDependencyDatabaseEntry& entry)
  2609. {
  2610. if (entry.m_productDependencyID == InvalidEntryId)
  2611. {
  2612. //they didn't set an id, add to database
  2613. //make sure its not already in the database
  2614. ProductDependencyDatabaseEntryContainer existingProductDependencies;
  2615. if (GetProductDependenciesByProductID(entry.m_productPK, existingProductDependencies))
  2616. {
  2617. for (const auto& existingProductDependency : existingProductDependencies)
  2618. {
  2619. if (existingProductDependency == entry)
  2620. {
  2621. //this product already exists
  2622. entry.m_productDependencyID = existingProductDependency.m_productDependencyID;
  2623. return true;
  2624. }
  2625. }
  2626. }
  2627. 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))
  2628. {
  2629. return false;
  2630. }
  2631. //now read it from the database
  2632. existingProductDependencies.clear();
  2633. if (GetProductDependenciesByProductID(entry.m_productPK, existingProductDependencies))
  2634. {
  2635. for (const auto& existingProductDependency : existingProductDependencies)
  2636. {
  2637. if (existingProductDependency == entry)
  2638. {
  2639. entry.m_productDependencyID = existingProductDependency.m_productDependencyID;
  2640. return true;
  2641. }
  2642. }
  2643. }
  2644. return false;
  2645. }
  2646. else
  2647. {
  2648. //they supplied an id, see if it exists in the database
  2649. ProductDependencyDatabaseEntry existingEntry;
  2650. if (!GetProductDependencyByProductDependencyID(entry.m_productDependencyID, existingEntry))
  2651. {
  2652. AZ_Error(
  2653. LOG_NAME,
  2654. false,
  2655. "Failed to read and update the product dependency with ID %d for product key %d from the database.",
  2656. entry.m_productDependencyID,
  2657. entry.m_productPK);
  2658. return false;
  2659. }
  2660. //if the product is now different update it
  2661. if (existingEntry == entry)
  2662. {
  2663. return true;
  2664. }
  2665. 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);
  2666. }
  2667. }
  2668. bool AssetDatabaseConnection::SetMissingProductDependency(AzToolsFramework::AssetDatabase::MissingProductDependencyDatabaseEntry& entry)
  2669. {
  2670. if (entry.m_missingProductDependencyId == InvalidEntryId)
  2671. {
  2672. // make sure its not already in the database
  2673. MissingProductDependencyDatabaseEntryContainer existingMissingProductDependencies;
  2674. if (GetMissingProductDependenciesByProductId(entry.m_productPK, existingMissingProductDependencies))
  2675. {
  2676. for (const auto& existingMissingProductDependency : existingMissingProductDependencies)
  2677. {
  2678. if (existingMissingProductDependency == entry)
  2679. {
  2680. // this missing dependency is already in the database
  2681. entry.m_missingProductDependencyId = existingMissingProductDependency.m_missingProductDependencyId;
  2682. return true;
  2683. }
  2684. }
  2685. }
  2686. // Add the new missing dependency to the database
  2687. if (!s_InsertMissingProductDependencyQuery.BindAndStep(
  2688. *m_databaseConnection,
  2689. entry.m_productPK,
  2690. entry.m_scannerId.c_str(),
  2691. entry.m_scannerVersion.c_str(),
  2692. entry.m_sourceFileFingerprint.c_str(),
  2693. entry.m_dependencySourceGuid,
  2694. entry.m_dependencySubId,
  2695. entry.m_missingDependencyString.c_str(),
  2696. entry.m_lastScanTime.c_str(),
  2697. entry.m_scanTimeSecondsSinceEpoch))
  2698. {
  2699. return false;
  2700. }
  2701. // Read it from the database to get the ID, and to verify it was written correctly.
  2702. existingMissingProductDependencies.clear();
  2703. if (GetMissingProductDependenciesByProductId(entry.m_productPK, existingMissingProductDependencies))
  2704. {
  2705. for (const auto& existingMissingProductDependency : existingMissingProductDependencies)
  2706. {
  2707. if (existingMissingProductDependency == entry)
  2708. {
  2709. entry.m_missingProductDependencyId = existingMissingProductDependency.m_missingProductDependencyId;
  2710. return true;
  2711. }
  2712. }
  2713. }
  2714. return false;
  2715. }
  2716. else
  2717. {
  2718. // An ID was supplied, see if it's already in the database
  2719. MissingProductDependencyDatabaseEntry existingEntry;
  2720. if (!GetMissingProductDependencyByMissingProductDependencyId(entry.m_missingProductDependencyId, existingEntry))
  2721. {
  2722. AZ_Error(
  2723. LOG_NAME,
  2724. false,
  2725. "Failed to read and update the missing product dependency with ID %d for product key %d from the database.",
  2726. entry.m_missingProductDependencyId,
  2727. entry.m_productPK);
  2728. return false;
  2729. }
  2730. // if the entry in the database matches what was passed in, there's nothing else that needs to be done
  2731. if (existingEntry == entry)
  2732. {
  2733. return true;
  2734. }
  2735. // Update the entry in the database
  2736. return s_UpdateMissingProductDependencyQuery.BindAndStep(
  2737. *m_databaseConnection,
  2738. entry.m_missingProductDependencyId,
  2739. entry.m_productPK,
  2740. entry.m_scannerId.c_str(),
  2741. entry.m_scannerVersion.c_str(),
  2742. entry.m_sourceFileFingerprint.c_str(),
  2743. entry.m_dependencySourceGuid,
  2744. entry.m_dependencySubId,
  2745. entry.m_missingDependencyString.c_str(),
  2746. entry.m_lastScanTime.c_str(),
  2747. entry.m_scanTimeSecondsSinceEpoch);
  2748. }
  2749. }
  2750. bool AssetDatabaseConnection::GetMissingProductDependenciesByProductId(AZ::s64 productId, AzToolsFramework::AssetDatabase::MissingProductDependencyDatabaseEntryContainer& container)
  2751. {
  2752. bool found = false;
  2753. bool succeeded = QueryMissingProductDependencyByProductId(productId,
  2754. [&](MissingProductDependencyDatabaseEntry& entry)
  2755. {
  2756. found = true;
  2757. container.emplace_back() = AZStd::move(entry);
  2758. return true; // return true to keep iterating over further rows.
  2759. });
  2760. return found && succeeded;
  2761. }
  2762. bool AssetDatabaseConnection::GetMissingProductDependencyByMissingProductDependencyId(AZ::s64 missingProductDependencyId, AzToolsFramework::AssetDatabase::MissingProductDependencyDatabaseEntry& missingProductDependencyEntry)
  2763. {
  2764. bool found = false;
  2765. QueryMissingProductDependencyByMissingProductDependencyId(missingProductDependencyId,
  2766. [&](MissingProductDependencyDatabaseEntry& entry)
  2767. {
  2768. found = true;
  2769. missingProductDependencyEntry = AZStd::move(entry);
  2770. return false; // stop after the first result
  2771. });
  2772. return found;
  2773. }
  2774. bool AssetDatabaseConnection::UpdateProductDependencies(AzToolsFramework::AssetDatabase::ProductDependencyDatabaseEntryContainer& container)
  2775. {
  2776. ScopedTransaction transaction(m_databaseConnection);
  2777. for(auto& entry : container)
  2778. {
  2779. if(entry.m_productDependencyID == InvalidEntryId)
  2780. {
  2781. if (!s_InsertProductDependencyQuery.BindAndStep(
  2782. *m_databaseConnection, entry.m_productPK, entry.m_dependencySourceGuid, entry.m_dependencySubID,
  2783. entry.m_dependencyFlags.to_ullong(), entry.m_platform.c_str(), entry.m_unresolvedPath.c_str(),
  2784. entry.m_dependencyType, entry.m_fromAssetId))
  2785. {
  2786. return false;
  2787. }
  2788. }
  2789. else
  2790. {
  2791. if(!s_UpdateProductDependencyQuery.BindAndStep(
  2792. *m_databaseConnection, entry.m_productPK, entry.m_dependencySourceGuid, entry.m_dependencySubID,
  2793. entry.m_dependencyFlags.to_ullong(), entry.m_platform.c_str(), entry.m_unresolvedPath.c_str(),
  2794. entry.m_productDependencyID, entry.m_dependencyType, entry.m_fromAssetId))
  2795. {
  2796. return false;
  2797. }
  2798. }
  2799. }
  2800. transaction.Commit();
  2801. return true;
  2802. }
  2803. bool AssetDatabaseConnection::SetProductDependencies(const ProductDependencyDatabaseEntryContainer& container)
  2804. {
  2805. // first, collect all unique ProductPKs:
  2806. ScopedTransaction transaction(m_databaseConnection);
  2807. AZStd::unordered_set<AZ::s64> uniqueProductIds;
  2808. for (const ProductDependencyDatabaseEntry& item : container)
  2809. {
  2810. uniqueProductIds.insert(item.m_productPK);
  2811. }
  2812. // unordered set eliminates dupes
  2813. for (AZ::s64 productId : uniqueProductIds)
  2814. {
  2815. if (!RemoveProductDependencyByProductId(productId))
  2816. {
  2817. return false; // auto rollback will occur
  2818. }
  2819. }
  2820. // now insert the new ones since we know there's no collisions:
  2821. for (auto& entry : container)
  2822. {
  2823. 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))
  2824. {
  2825. return false;
  2826. }
  2827. }
  2828. transaction.Commit();
  2829. return true;
  2830. }
  2831. bool AssetDatabaseConnection::RemoveProductDependencyByProductId(AZ::s64 productID)
  2832. {
  2833. ScopedTransaction transaction(m_databaseConnection);
  2834. if (!s_DeleteProductDependencyByProductIdQuery.BindAndStep(*m_databaseConnection, productID))
  2835. {
  2836. return false;
  2837. }
  2838. transaction.Commit();
  2839. return true;
  2840. }
  2841. bool AssetDatabaseConnection::GetFileByFileID(AZ::s64 fileID, FileDatabaseEntry& entry)
  2842. {
  2843. bool found = false;
  2844. bool succeeded = QueryFileByFileID(fileID,
  2845. [&](FileDatabaseEntry& file)
  2846. {
  2847. found = true;
  2848. entry = AZStd::move(file);
  2849. return false;//one
  2850. });
  2851. return found && succeeded;
  2852. }
  2853. bool AssetDatabaseConnection::GetFileByFileNameAndScanFolderId(QString fileName, AZ::s64 scanFolderId, FileDatabaseEntry& entry)
  2854. {
  2855. bool found = false;
  2856. bool succeeded = QueryFilesByFileNameAndScanFolderID(AssetUtilities::NormalizeFilePath(fileName).toUtf8().constData(), scanFolderId,
  2857. [&](FileDatabaseEntry& file)
  2858. {
  2859. found = true;
  2860. entry = AZStd::move(file);
  2861. return false;//one
  2862. });
  2863. return found && succeeded;
  2864. }
  2865. bool AssetDatabaseConnection::GetFilesLikeFileNameScanFolderId(QString likeFileName, LikeType likeType, AZ::s64 scanFolderId, FileDatabaseEntryContainer& container)
  2866. {
  2867. bool found = false;
  2868. bool succeeded = QueryFilesLikeFileNameAndScanFolderID(likeFileName.toUtf8().constData(), likeType, scanFolderId,
  2869. [&](FileDatabaseEntry& file)
  2870. {
  2871. found = true;
  2872. container.push_back(file);
  2873. return true;//all
  2874. });
  2875. return found && succeeded;
  2876. }
  2877. bool AssetDatabaseConnection::InsertFiles(FileDatabaseEntryContainer& entries)
  2878. {
  2879. // Skip creating and committing a scoped transaction, if the entry list is empty.
  2880. if (entries.empty())
  2881. {
  2882. return true;
  2883. }
  2884. ScopedTransaction transaction(m_databaseConnection);
  2885. for (auto& entry : entries)
  2886. {
  2887. StatementAutoFinalizer autoFinal;
  2888. 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))
  2889. {
  2890. return false;
  2891. }
  2892. Statement* statement = autoFinal.Get();
  2893. if (statement->Step() == Statement::SqlError)
  2894. {
  2895. AZ_Warning(LOG_NAME, false, "Failed to write the new source into the database. %s", entry.m_fileName.c_str());
  2896. return false;
  2897. }
  2898. //now that its in the database get the id
  2899. AZ::s64 rowID = m_databaseConnection->GetLastRowID();
  2900. entry.m_fileID = rowID;
  2901. }
  2902. transaction.Commit();
  2903. return true;
  2904. }
  2905. bool AssetDatabaseConnection::InsertFile(FileDatabaseEntry& entry, bool& entryAlreadyExists)
  2906. {
  2907. entryAlreadyExists = false;
  2908. //they didn't supply an id, add to database
  2909. if (entry.m_fileID == InvalidEntryId)
  2910. {
  2911. //first make sure its not already in the database
  2912. FileDatabaseEntry existingEntry;
  2913. if (GetFileByFileNameAndScanFolderId(entry.m_fileName.c_str(), entry.m_scanFolderPK, existingEntry))
  2914. {
  2915. entry.m_fileID = existingEntry.m_fileID;
  2916. return UpdateFile(entry, entryAlreadyExists); // now update the existing field
  2917. }
  2918. StatementAutoFinalizer autoFinal;
  2919. 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))
  2920. {
  2921. return false;
  2922. }
  2923. Statement* statement = autoFinal.Get();
  2924. if (statement->Step() == Statement::SqlError)
  2925. {
  2926. AZ_Warning(LOG_NAME, false, "Failed to write the new source into the database. %s", entry.m_fileName.c_str());
  2927. return false;
  2928. }
  2929. //now that its in the database get the id
  2930. AZ::s64 rowID = m_databaseConnection->GetLastRowID();
  2931. entry.m_fileID = rowID;
  2932. return true;
  2933. }
  2934. return UpdateFile(entry, entryAlreadyExists);
  2935. }
  2936. bool AssetDatabaseConnection::UpdateFile(FileDatabaseEntry& entry, bool& entryAlreadyExists)
  2937. {
  2938. entryAlreadyExists = false;
  2939. //they supplied an id, see if it exists in the database
  2940. FileDatabaseEntry existingEntry;
  2941. if (!GetFileByFileID(entry.m_fileID, existingEntry))
  2942. {
  2943. //they supplied an id but is not in the database!
  2944. AZ_Error(LOG_NAME, false, "Failed to write the file into the database.");
  2945. return false;
  2946. }
  2947. // don't bother updating the database if all fields are equal.
  2948. // note that we already looked it up by source ID
  2949. if ((existingEntry.m_scanFolderPK == entry.m_scanFolderPK) &&
  2950. (existingEntry.m_fileName == entry.m_fileName) &&
  2951. (existingEntry.m_isFolder == entry.m_isFolder) &&
  2952. (existingEntry.m_modTime == entry.m_modTime))
  2953. {
  2954. entryAlreadyExists = true;
  2955. return true;
  2956. }
  2957. StatementAutoFinalizer autoFinal;
  2958. 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))
  2959. {
  2960. return false;
  2961. }
  2962. return true;
  2963. }
  2964. bool AssetDatabaseConnection::UpdateFileModTimeAndHashByFileNameAndScanFolderId(QString fileName, AZ::s64 scanFolderId, AZ::u64 modTime, AZ::u64 hash)
  2965. {
  2966. if(!s_UpdateFileModtimeByFileNameScanFolderIdQuery.BindAndStep(*m_databaseConnection, modTime, hash, fileName.toUtf8().constData(), scanFolderId))
  2967. {
  2968. return false;
  2969. }
  2970. return m_databaseConnection->GetNumAffectedRows() > 0;
  2971. }
  2972. bool AssetDatabaseConnection::UpdateFileHashByFileNameAndScanFolderId(QString fileName, AZ::s64 scanFolderId, AZ::u64 hash)
  2973. {
  2974. if (!s_UpdateFileHashByFileNameScanFolderIdQuery.BindAndStep(
  2975. *m_databaseConnection, hash, fileName.toUtf8().constData(), scanFolderId))
  2976. {
  2977. return false;
  2978. }
  2979. return m_databaseConnection->GetNumAffectedRows() > 0;
  2980. }
  2981. bool AssetDatabaseConnection::RemoveFile(AZ::s64 fileID)
  2982. {
  2983. return s_DeleteFileQuery.BindAndStep(*m_databaseConnection, fileID);
  2984. }
  2985. bool AssetDatabaseConnection::GetStatByStatName(QString statName, StatDatabaseEntryContainer& container)
  2986. {
  2987. bool found = false;
  2988. bool succeeded = QueryStatByStatName(
  2989. statName.toUtf8().constData(),
  2990. [&](StatDatabaseEntry& stat)
  2991. {
  2992. found = true;
  2993. container.emplace_back() = AZStd::move(stat);
  2994. return true; // return true to continue iterating over additional results, we are populating a container
  2995. });
  2996. return found && succeeded;
  2997. }
  2998. bool AssetDatabaseConnection::GetStatLikeStatName(QString statName, StatDatabaseEntryContainer& container)
  2999. {
  3000. bool found = false;
  3001. bool succeeded = QueryStatLikeStatName(
  3002. statName.toUtf8().constData(),
  3003. [&](StatDatabaseEntry& stat)
  3004. {
  3005. found = true;
  3006. container.emplace_back() = AZStd::move(stat);
  3007. return true; // return true to continue iterating over additional results, we are populating a container
  3008. });
  3009. return found && succeeded;
  3010. }
  3011. bool AssetDatabaseConnection::ReplaceStat(AzToolsFramework::AssetDatabase::StatDatabaseEntry& stat)
  3012. {
  3013. return s_ReplaceStatQuery.BindAndStep(*m_databaseConnection, stat.m_statName.c_str(), stat.m_statValue, stat.m_lastLogTime);
  3014. }
  3015. bool AssetDatabaseConnection::SetBuilderInfoTable(AzToolsFramework::AssetDatabase::BuilderInfoEntryContainer& newEntries)
  3016. {
  3017. ScopedTransaction transaction(m_databaseConnection);
  3018. if (!m_databaseConnection->ExecuteOneOffStatement(CLEAR_BUILDERINFO_TABLE))
  3019. {
  3020. return false;
  3021. }
  3022. for (AzToolsFramework::AssetDatabase::BuilderInfoEntry &entry : newEntries)
  3023. {
  3024. if (!s_InsertBuilderInfoQuery.BindAndStep(*m_databaseConnection, entry.m_builderUuid, entry.m_analysisFingerprint.c_str()))
  3025. {
  3026. return false;
  3027. }
  3028. // update the entry to have the applied ID.
  3029. entry.m_builderInfoID = m_databaseConnection->GetLastRowID();
  3030. }
  3031. transaction.Commit();
  3032. return true;
  3033. }
  3034. }//namespace AssetProcessor