tsdb.pp 37 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225
  1. {$mode objfpc}
  2. {$H+}
  3. unit tsdb;
  4. Interface
  5. Uses
  6. sqldb, types, tstypes, tsstring, tsutils, pqconnection;
  7. const
  8. // Ini file constants
  9. DefaultDBConfigFileName = '/etc/dbdigest.ini';
  10. SSection = 'Database';
  11. KeyName = 'Name';
  12. KeyHost = 'Host';
  13. KeyUser = 'UserName';
  14. KeyPassword = 'Password';
  15. KeyPort = 'Port';
  16. // Query to run to get all test run test results.
  17. // For test results that did not change, the last test result ID is returned.
  18. // Needs formatting with 2 IDS : Run ID, Platform ID
  19. SQLTestResultIDS =
  20. 'with testrunresultids as ( ' +
  21. ' select ' +
  22. ' tr_id as theid ' +
  23. ' from ' +
  24. ' testresults ' +
  25. ' where ' +
  26. ' (tr_testrun_fk=%d) ' +
  27. ' union ' +
  28. ' select ' +
  29. ' tl_testresults_fk as theid ' +
  30. ' from ' +
  31. ' tests ' +
  32. ' inner join testlastresults on (tl_test_fk=t_id) and (tl_platform_fk=%d) ' +
  33. ')';
  34. // Get all test results for a testrun (but not compile/run log)
  35. SQLSelectTestResults =
  36. SQLTestResultIDS +
  37. 'select ' +
  38. ' T_ID as Id,T_NAME as Filename,TR_SKIP as Skipped, TR_OK as OK,TR_RESULT as Result ' +
  39. 'from ' +
  40. ' testrunresultids ' +
  41. ' left join testresults on (tr_id=theid) ' +
  42. ' inner join tests on (tr_test_fk=t_id)';
  43. Type
  44. TMapType = (mtCPU, mtOS, mtVersion);
  45. { TTestSQL }
  46. TTestSQL = class(TObject)
  47. Const
  48. Bools : Array[Boolean] of String = ('f','t');
  49. private
  50. FRelSrcDir: String;
  51. FTestSrcDir: string;
  52. FConnection : TPQConnection;
  53. FDatabaseName : String;
  54. FHost : String;
  55. FUser : String;
  56. FPassword : String;
  57. FPort : Word;
  58. Flogprefix : String;
  59. Class Procedure FreeQueryResult (Var aQry : TSQLQuery);
  60. Class Function GetIntResultField (aQry : TSQLQuery; aFieldIndex : Integer) : Integer;
  61. Class Function GetInt64ResultField (aQry : TSQLQuery; aFieldIndex : Integer) : Int64;
  62. Class Function GetStrResultField (aQry : TSQLQuery; aFieldIndex : Integer) : String;
  63. function InsertTestHistory(TestRunID, TestPreviousID: Integer): boolean;
  64. // Overload adds prefix to actual call
  65. procedure Verbose(aLevel : TVerboseLevel; const aMsg : string);
  66. { ---------------------------------------------------------------------
  67. Low-level DB access.
  68. ---------------------------------------------------------------------}
  69. // create and open a query, return in Res.
  70. Function OpenQuery (Qry : String; Out Res : TSQLQuery; Silent : Boolean) : Boolean ;
  71. Public
  72. { ---------------------------------------------------------------------
  73. High-level access
  74. ---------------------------------------------------------------------}
  75. // Constructor.
  76. Constructor create(aDatabaseName,aHost,aUser,aPassword : String; aPort : Word);
  77. // Destructor
  78. Destructor destroy; override;
  79. // Try to connect to database with params given in constructor.
  80. Function ConnectToDatabase : Boolean;
  81. // Disconnect from database
  82. Procedure DisconnectDatabase;
  83. // Create query object.
  84. function CreateQuery(const ASQL: String): TSQLQuery;
  85. // Execute a query, return true if it executed without error.
  86. Function ExecuteQuery (Qry : String; Silent : Boolean) : Boolean ;
  87. // Run query, return first field as integer. -1 on error or no data.
  88. function GetIDQueryResult(Qry: TSQLQuery): Int64;
  89. // Run SQL, return first field as integer. -1 on error or no data.
  90. Function IDQuery(Qry : String) : Integer;
  91. // Run query, return first field as int64. -1 on error or no data.
  92. Function ID64Query(Qry : String) : Int64;
  93. // Run query, return first field as string. Empty string on error or no data.
  94. Function StringQuery(Qry : String) : String;
  95. Function CreateMap(aType : TMapType) : TIntegerDynArray;
  96. // Adding things
  97. // Add a category.
  98. Function AddCategory(const aName : String) : Integer;
  99. // Add a CPU.
  100. Function AddCPU(const aName : String) : Integer;
  101. // Add an OS.
  102. Function AddOS(const aName : String) : Integer;
  103. // Add a compiler version.
  104. function AddVersion(const aName: String; aReleaseDate: TDateTime): Integer;
  105. // Add a platform.
  106. Function AddPlatform(const aData : TTestRunData) : Integer;
  107. // Add a test and return the ID. If the test already exists, return it's ID
  108. Function AddTest(Name : String; AddSource : Boolean) : Integer;
  109. // Add a test run. Return the test run ID.
  110. function AddRun(const aData: TTestRunData): Int64;
  111. // Ad test result and return ID. If a result exists already for the given run/test, update and return ID.
  112. Function AddTestResult(aData : TTestResultData) : Int64;
  113. // Add LastTestResult. If it exists already with given platform/test, update result ID.
  114. function AddLastResult(TestID, PlatformID: Integer; ResultID: Int64): Boolean;
  115. // Add previousTestResult. If it exists already with given platform/test, update result ID.
  116. function AddPreviousResult(TestID, PlatformID: Integer; ResultID: Int64): Boolean;
  117. // Add Check-All-RTL results. Adds logs for failed tests, if available.
  118. Function AddCheckAllRtl(aData : TCheckAllRTL) : Int64;
  119. // Add Check-All-RTL failed run log
  120. function AddCheckAllRtlLog(aCheckAllRTLID: int64; aStep: Byte; const aLog: String): Int64;
  121. //
  122. // Get ID based on key. All keys are case sensitive. If a key does not exist, -1 is returned.
  123. //
  124. // Get test ID based on test name.
  125. Function GetTestID(aName : string) : Integer;
  126. Function GetTestName(aID : Integer) : string;
  127. Function GetTestFileName(aID : Integer) : String;
  128. Function GetTestSource(aID : Integer) : String;
  129. // Get OS ID based on OS name.
  130. Function GetOSID(aName : String) : Integer;
  131. Function GetOSName(aID : Integer) : String;
  132. // Get CPU ID based on CPU name.
  133. Function GetCPUID(Name : String) : Integer;
  134. Function GetCPUName(aID : Integer) : String;
  135. // Get category ID based on Category name.
  136. Function GetCategoryID(aName : String) : Integer;
  137. Function GetCategoryName(aID : Integer) : String;
  138. // Get version ID based on version name.
  139. Function GetVersionID(aName : String) : Integer;
  140. Function GetVersionName(aID : Integer) : string;
  141. // Get platform ID based on OS, cpu, category, config.
  142. function GetPlatformID(aData: TTestRunData; aAllowCreate: Boolean): Integer;
  143. function GetPlatformID(aVersionID, aOSID, aCPUID, aCategoryID : Integer; const aMachine, aConfig : String): Integer;
  144. function GetPlatformID(aRunID : Int64): Integer;
  145. // Get run ID based on platform/date.
  146. Function GetRunID(aData : TTestRunData) : Int64;
  147. function GetNextRunID(RunID: Int64): Int64;
  148. function GetPreviousRunID(RunID: Int64): Int64;
  149. Function GetRunData(aID : Int64; out aData : TTestRunData) : Boolean;
  150. Function GetLastRunByPlatformAndDate(aPLatformID : Integer; aDate : TDateTime) : Integer;
  151. // Get testinfo based on test ID
  152. function GetTestInfo(aID: Int64; out aInfo: TTestInfo): Boolean;
  153. // Get last test result ID based on platform/test.
  154. function GetLastTestResult(aTestID, aPlatFormID: Integer): TTestResultData;
  155. function GetFailCount(aRunID : Int64) : Int64;
  156. // Update tests
  157. Function UpdateTest(ID : Integer; Info : TConfig; Const Source : String) : Boolean;
  158. function UpdateTestResult(aData: TTestResultData): Int64;
  159. function UpdateTestRun(aData : TTestRunData): Boolean;
  160. Function GetFailCount(aRunID : Integer) : Int64;
  161. // Create test if it does not exist yet.
  162. Function RequireTestID(const aName : String): Integer;
  163. // Delete all results from a test run.
  164. Function CleanTestRun(ID : Integer) : Boolean;
  165. // Escape SQL (quotes etc.
  166. Class Function EscapeSQL(Const S : String) : String;
  167. // return SQL date
  168. Class Function SQLDate(D : TDateTime) : String;
  169. // Rel src dir
  170. Property RelSrcDir : String Read FRelSrcDir Write FRelSrcDir;
  171. // test src dir.
  172. Property TestSrcDir : string read FTestSrcDir Write FTestSrcDir;
  173. // Prefix to use when logging (in case of multi-thread)
  174. Property LogPrefix : String Read FLogPrefix Write FLogPrefix;
  175. end;
  176. Implementation
  177. Uses
  178. SysUtils;
  179. { ---------------------------------------------------------------------
  180. Low-level DB access.
  181. ---------------------------------------------------------------------}
  182. function TTestSQL.ConnectToDatabase: Boolean;
  183. begin
  184. Result:=False;
  185. Verbose(V_SQL,'Connection params : '+FDatabaseName+' '+FHost+' '+FUser+' '+IntToStr(FPort));
  186. FConnection:=TPQConnection.Create(Nil);
  187. try
  188. FConnection.Hostname:=FHost;
  189. FConnection.DatabaseName:=FDatabaseName;
  190. FConnection.Username:=FUser;
  191. FConnection.Password:=FPassword;
  192. FConnection.Connected:=true;
  193. FConnection.Transaction:=TSQLTransaction.Create(FConnection);
  194. if (FPort<>0) then
  195. FConnection.Params.Values['Port']:=IntToStr(FPort);
  196. FConnection.Connected:=True;
  197. Result:=True
  198. except
  199. On E : Exception do
  200. begin
  201. Verbose(V_ERROR,'Failed to connect to database : '+E.Message);
  202. FreeAndNil(FConnection);
  203. end;
  204. end;
  205. end;
  206. procedure TTestSQL.DisconnectDatabase;
  207. begin
  208. FreeAndNil(FConnection);
  209. end;
  210. function TTestSQL.AddCategory(const aName: String): Integer;
  211. Const
  212. SQLInsert = 'INSERT INTO TESTCATEGORY (TA_NAME) VALUES (''%s'') RETURNING TA_ID';
  213. begin
  214. Result:=IDQuery(Format(SQLInsert,[EscapeSQL(aName)]));
  215. end;
  216. function TTestSQL.AddCPU(const aName: String): Integer;
  217. Const
  218. SQLInsert = 'INSERT INTO TESTCPU (TC_NAME) VALUES (''%s'') RETURNING TC_ID';
  219. begin
  220. Result:=IDQuery(Format(SQLInsert,[EscapeSQL(aName)]));
  221. end;
  222. function TTestSQL.AddOS(const aName: String): Integer;
  223. Const
  224. SQLInsert = 'INSERT INTO TESTOS (TO_NAME) VALUES (''%s'') RETURNING TO_ID';
  225. begin
  226. Result:=IDQuery(Format(SQLInsert,[EscapeSQL(aName)]));
  227. end;
  228. function TTestSQL.AddVersion(const aName: String; aReleaseDate : TDateTime): Integer;
  229. Const
  230. SQLInsert = 'INSERT INTO TESTVERSION (TV_VERSION,TV_RELEASEDATE) VALUES (''%s'',''%s'') RETURNING TV_ID';
  231. begin
  232. Result:=IDQuery(Format(SQLInsert,[EscapeSQL(aName),SQLDate(aReleaseDate)]));
  233. end;
  234. function TTestSQL.CreateQuery(const ASQL: String): TSQLQuery;
  235. begin
  236. Result:=TSQLQuery.Create(FConnection);
  237. Result.Database:=FConnection;
  238. Result.Transaction:=FConnection.Transaction;
  239. Result.SQL.Text:=ASQL;
  240. end;
  241. function TTestSQL.ExecuteQuery(Qry: String; Silent: Boolean): Boolean;
  242. begin
  243. Verbose(V_SQL,'Executing query:'+Qry);
  244. Result:=False;
  245. try
  246. With CreateQuery(Qry) do
  247. try
  248. ExecSQL;
  249. Result:=True;
  250. (Transaction as TSQLTransaction).Commit;
  251. finally
  252. Free;
  253. end;
  254. except
  255. On E : exception do
  256. begin
  257. FConnection.Transaction.RollBack;
  258. if not Silent then
  259. Verbose(V_WARNING,'Query : '+Qry+'Failed : '+E.Message);
  260. end;
  261. end;
  262. end;
  263. function TTestSQL.OpenQuery(Qry: String; out Res: TSQLQuery; Silent: Boolean): Boolean;
  264. begin
  265. Result:=False;
  266. Verbose(V_SQL,'Running query:'+Qry);
  267. Res:=CreateQuery(Qry);
  268. try
  269. Res.Open;
  270. Result:=True;
  271. except
  272. On E : exception do
  273. begin
  274. FreeAndNil(Res);
  275. Try
  276. FConnection.Transaction.RollBack;
  277. except
  278. end;
  279. if not Silent then
  280. Verbose(V_WARNING,'Query : '+Qry+'Failed : '+E.Message);
  281. end;
  282. end;
  283. end;
  284. class function TTestSQL.GetIntResultField(aQry: TSQLQuery; aFieldIndex: Integer): Integer;
  285. begin
  286. If (aQry=Nil) or (aQry.IsEmpty) or (aFieldIndex>=aQry.Fields.Count) then
  287. Result:=-1
  288. else
  289. Result:=aQry.Fields[aFieldIndex].AsInteger;
  290. tsutils.Verbose(V_SQL,'Field value '+IntToStr(Result));
  291. end;
  292. class function TTestSQL.GetInt64ResultField(aQry: TSQLQuery; aFieldIndex: Integer): Int64;
  293. begin
  294. If (aQry=Nil) or (aQry.IsEmpty) or (aFieldIndex>=aQry.Fields.Count) then
  295. Result:=-1
  296. else
  297. Result:=aQry.Fields[aFieldIndex].AsLargeInt;
  298. tsutils.Verbose(V_SQL,'Field value '+IntToStr(Result));
  299. end;
  300. class function TTestSQL.GetStrResultField(aQry: TSQLQuery; aFieldIndex: Integer): String;
  301. begin
  302. If (aQry=Nil) or (aQry.IsEmpty) or (aFieldIndex>=aQry.Fields.Count) then
  303. Result:=''
  304. else
  305. Result:=aQry.Fields[aFieldIndex].AsString;
  306. tsutils.Verbose(V_SQL,'Field value '+Result);
  307. end;
  308. procedure TTestSQL.Verbose(aLevel: TVerboseLevel; const aMsg: string);
  309. begin
  310. tsutils.Verbose(aLevel,logPrefix+aMsg);
  311. end;
  312. function TTestSQL.AddPlatform(const aData : TTestRunData) : Integer;
  313. const
  314. SQLInsert = 'INSERT INTO TESTPLATFORM (TP_CPU_FK, TP_OS_FK, TP_VERSION_FK, TP_CATEGORY_FK, TP_CONFIG, TP_MACHINE) '+
  315. ' VALUES (%d, %d, %d, %d, ''%s'', ''%s'') '+
  316. ' RETURNING TP_ID';
  317. begin
  318. With aData do
  319. Result:=IDQuery(Format(SQLInsert,[CPUID,OSID,VersionID,CategoryID,EscapeSQL(config),EscapeSQL(machine)]));
  320. end;
  321. class procedure TTestSQL.FreeQueryResult(var aQry: TSQLQuery);
  322. begin
  323. if Assigned(aQry) and Assigned(aQry.Transaction) then
  324. aQry.SQLTransaction.Commit;
  325. FreeAndNil(aQry);
  326. end;
  327. function TTestSQL.GetIDQueryResult(Qry: TSQLQuery): Int64;
  328. begin
  329. Result:=-1;
  330. Qry.Open;
  331. if Not Qry.IsEmpty then
  332. Result:=Qry.Fields[0].AsLargeInt;
  333. Qry.SQLTransaction.Commit;
  334. end;
  335. function TTestSQL.IDQuery(Qry: String): Integer;
  336. Var
  337. Res : TSQLQuery;
  338. begin
  339. Result:=-1;
  340. If OpenQuery(Qry,Res,False) then
  341. try
  342. Result:=GetIntResultField(Res,0);
  343. finally
  344. FreeQueryResult(Res);
  345. end;
  346. end;
  347. function TTestSQL.ID64Query(Qry: String): Int64;
  348. Var
  349. Res : TSQLQuery;
  350. begin
  351. Result:=-1;
  352. If OpenQuery(Qry,Res,False) then
  353. try
  354. Result:=GetInt64ResultField(Res,0);
  355. finally
  356. FreeQueryResult(Res);
  357. end;
  358. end;
  359. function TTestSQL.StringQuery(Qry: String): String;
  360. Var
  361. Res : TSQLQuery;
  362. begin
  363. Result:='';
  364. If OpenQuery(Qry,Res,False) then
  365. try
  366. Result:=GetStrResultField(Res,0);
  367. Verbose(V_SQL,'StringQuery: '+Result);
  368. finally
  369. FreeQueryResult(Res);
  370. end;
  371. end;
  372. function TTestSQL.CreateMap(aType: TMapType): TIntegerDynArray;
  373. var
  374. Qry : TSQLQuery;
  375. lSQL : string;
  376. lIdx : Integer;
  377. begin
  378. Result:=[];
  379. Case aType of
  380. mtCPU : lSQL:='SELECT TC_ID FROM TESTCPU order by TC_ID';
  381. mtOS : lSQL:='SELECT TO_ID FROM TESTOS order by TO_ID';
  382. mtVersion : lSQL:='SELECT TV_ID FROM TESTVERSION order by TV_ID';
  383. end;
  384. Qry:=CreateQuery(lSQL);
  385. Verbose(V_SQL,'CreateMap: '+lSQL);
  386. try
  387. Qry.PacketRecords:=-1;
  388. Qry.Open;
  389. SetLength(Result,Qry.RecordCount);
  390. lIDx:=0;
  391. While not Qry.EOF do
  392. begin
  393. Result[lIdx]:=Qry.Fields[0].AsInteger;
  394. inc(lIdx);
  395. Qry.Next;
  396. end;
  397. finally
  398. Qry.Free;
  399. end;
  400. end;
  401. constructor TTestSQL.create(aDatabaseName, aHost, aUser, aPassword: String; aPort: Word);
  402. begin
  403. FDatabaseName:=aDatabaseName;
  404. FHost:=aHost;
  405. FUser:=aUser;
  406. FPassword:=aPassword;
  407. FPort:=aPort;
  408. end;
  409. destructor TTestSQL.destroy;
  410. begin
  411. DisconnectDatabase;
  412. inherited destroy;
  413. end;
  414. class function TTestSQL.EscapeSQL(const S: String): String;
  415. begin
  416. // Result:=StringReplace(S,'\','\\',[rfReplaceAll]);
  417. Result:=StringReplace(S,'''','''''',[rfReplaceAll]);
  418. if (Result<>S) then
  419. tsutils.Verbose(V_SQL,'EscapeSQL : "'+S+'" -> "'+Result+'"');
  420. end;
  421. class function TTestSQL.SQLDate(D: TDateTime): String;
  422. begin
  423. Result:=FormatDateTime('YYYY/MM/DD hh:nn:ss',D);
  424. end;
  425. { ---------------------------------------------------------------------
  426. High-level access
  427. ---------------------------------------------------------------------}
  428. function TTestSQL.GetTestID(aName: string): Integer;
  429. Const
  430. SFromName = 'SELECT T_ID FROM TESTS WHERE (T_NAME=''%s'')';
  431. begin
  432. Result:=IDQuery(Format(SFromName,[aName]));
  433. end;
  434. function TTestSQL.GetTestName(aID: Integer): string;
  435. begin
  436. Result:=StringQuery(Format('SELECT T_NAME FROM TESTCPU WHERE (T_ID=%d)',[aID]));
  437. end;
  438. function TTestSQL.GetTestFileName(aID: Integer): String;
  439. begin
  440. Result:=StringQuery(Format('SELECT T_NAME FROM TESTS WHERE (T_ID=%d)',[aID]));
  441. end;
  442. function TTestSQL.GetTestSource(aID: Integer): String;
  443. begin
  444. Result:=StringQuery(Format('select T_SOURCE from TESTS where (T_ID=%d)',[aid]));
  445. end;
  446. function TTestSQL.GetOSID(aName: String): Integer;
  447. Const
  448. SFromName = 'SELECT TO_ID FROM TESTOS WHERE (TO_NAME=''%s'')';
  449. begin
  450. Result:=IDQuery(Format(SFromName,[aName]));
  451. end;
  452. function TTestSQL.GetOSName(aID: Integer): String;
  453. begin
  454. Result:=StringQuery(Format('SELECT TO_NAME FROM TESTOS WHERE (TO_ID=%d)',[aID]));
  455. end;
  456. function TTestSQL.GetVersionID(aName: String): Integer;
  457. Const
  458. SFromName = 'SELECT TV_ID FROM TESTVERSION WHERE (TV_VERSION=''%s'')';
  459. begin
  460. Result:=IDQuery(Format(SFromName,[aName]));
  461. end;
  462. function TTestSQL.GetVersionName(aID: Integer): string;
  463. const
  464. SQLSelectVersion = 'SELECT TV_VERSION FROM TESTVERSION WHERE (TV_ID=%d)';
  465. begin
  466. Result:=StringQuery(Format(SQLSelectVersion,[aID]));
  467. end;
  468. function TTestSQL.GetPlatformID(aData: TTestRunData; aAllowCreate: Boolean): Integer;
  469. Const
  470. SQLSelect = 'SELECT TP_ID FROM TESTPLATFORM ' +
  471. ' WHERE ' +
  472. ' (TP_VERSION_FK=%d)' +
  473. ' AND (TP_OS_FK=%d)' +
  474. ' AND (TP_CPU_FK=%d)' +
  475. ' AND (TP_CATEGORY_FK=%d)' +
  476. ' AND (TP_CONFIG=''%s'')' +
  477. ' AND (TP_MACHINE=''%s'')';
  478. begin
  479. With aData do
  480. Result:=IDQuery(Format(SQLSelect,[VersionID,OSID,CPUID,CategoryID,Config,Machine]));
  481. if (Result=-1) and aAllowCreate then
  482. Result:=AddPlatform(aData)
  483. end;
  484. function TTestSQL.GetPlatformID(aVersionID, aOSID, aCPUID, aCategoryID: Integer; const aMachine, aConfig: String): Integer;
  485. var
  486. TR : TTestRunData;
  487. begin
  488. TR:=Default(TTestRunData);
  489. TR.VersionID:=aVersionID;
  490. TR.OSID:=aOSID;
  491. TR.CPUID:=aCPUID;
  492. TR.CategoryID:=aCategoryID;
  493. TR.config:=aConfig;
  494. TR.Machine:=aMachine;
  495. Result:=GetPlatformID(TR,False);
  496. end;
  497. function TTestSQL.GetPlatformID(aRunID: Int64): Integer;
  498. Const
  499. SFromID = 'SELECT TU_PLATFORM_FK FROM TESTRUN WHERE (TU_ID=%d)';
  500. begin
  501. Result:=IDQuery(Format(SFromID,[aRunID]));
  502. end;
  503. function TTestSQL.GetCPUID(Name: String): Integer;
  504. Const
  505. SFromName = 'SELECT TC_ID FROM TESTCPU WHERE (TC_NAME=''%s'')';
  506. begin
  507. Result:=IDQuery(Format(SFromName,[Name]));
  508. end;
  509. function TTestSQL.GetCPUName(aID: Integer): String;
  510. begin
  511. Result:=StringQuery(Format('SELECT TC_NAME FROM TESTCPU WHERE (TC_ID=%d)',[aID]));
  512. end;
  513. function TTestSQL.GetCategoryID(aName: String): Integer;
  514. Const
  515. SFromName = 'SELECT TA_ID FROM TESTCATEGORY WHERE (TA_NAME=''%s'')';
  516. begin
  517. Result:=IDQuery(Format(SFromName,[aName]));
  518. end;
  519. function TTestSQL.GetCategoryName(aID: Integer): String;
  520. begin
  521. Result:=StringQuery(Format('SELECT TA_NAME FROM TESTCATEGORY WHERE (TA_ID=%d)',[aID]));
  522. end;
  523. function TTestSQL.GetRunID(aData: TTestRunData): Int64;
  524. Const
  525. SFromIDS = 'SELECT TU_ID FROM TESTRUN WHERE '+
  526. ' (TU_PLATFORM_FK=%d) '+
  527. ' AND (TU_DATE=''%s'')';
  528. begin
  529. With aData do
  530. Result:=ID64Query(Format(SFromIDS,[PlatFormID,SQLDate(Date)]));
  531. end;
  532. function TTestSQL.GetRunData(aID: Int64; out aData: TTestRunData): Boolean;
  533. const
  534. SQLSelectRUNData =
  535. 'select ' +
  536. ' TA_NAME, TV_VERSION, TV_RELEASEDATE, TV_ID, TC_NAME, TO_NAME, TestPlatform.* , TESTRUN.* ' +
  537. 'from ' +
  538. ' TESTRUN ' +
  539. ' INNER JOIN TESTPLATFORM ON (TP_ID=TU_PLATFORM_FK) ' +
  540. ' INNER JOIN TESTOS ON (TO_ID=TP_OS_FK) ' +
  541. ' INNER JOIN TESTCPU ON (TC_ID=TP_CPU_FK) ' +
  542. ' INNER JOIN TESTCATEGORY ON (TA_ID=TP_CATEGORY_FK) ' +
  543. ' INNER JOIN TESTVERSION ON (TV_ID=TP_VERSION_FK) ' +
  544. 'WHERE (TU_ID=%d)';
  545. var
  546. Qry : TSQLQuery;
  547. ST : TTestStatus;
  548. S : string;
  549. begin
  550. S:=Format(SQLSelectRunData,[aID]);
  551. Qry:=CreateQuery(S);
  552. Verbose(V_SQL,'GetRunData: '+s);
  553. try
  554. Qry.Open;
  555. Result:=Not Qry.IsEmpty;
  556. if Result then
  557. With Qry do
  558. begin
  559. aData.RunID:=aID;
  560. aData.os:=FieldByName('TO_NAME').AsString;
  561. aData.OSID:=FieldByName('TP_OS_FK').AsInteger;
  562. aData.cpu:=FieldByName('TC_NAME').AsString;
  563. aData.CPUID:=FieldByName('TP_CPU_FK').AsInteger;
  564. aData.version:=FieldByName('TV_VERSION').AsString;
  565. aData.versionID:=FieldByName('TV_ID').asInteger;
  566. aData.category:=FieldByName('TA_NAME').AsString;
  567. aData.PlatformID:=FieldByName('TP_ID').AsInteger;
  568. aData.Config:=FieldByName('TP_CONFIG').AsString;
  569. aData.Machine:=FieldByName('TP_MACHINE').AsString;
  570. aData.submitter:=FieldByName('TU_SUBMITTER').AsString;
  571. // aData.:=FieldByName('TV_RELEASEDATE').AsString;
  572. aData.Date:=FieldByName('TU_DATE').AsDateTime;
  573. aData.CompilerDate:=FieldByName('TU_COMPILERDATE').AsString;
  574. aData.CompilerFullversion:=FieldByName('TU_COMPILERFULLVERSION').AsString;
  575. aData.CompilerRevision:=FieldByName('TU_COMPILERREVISION').AsString;
  576. aData.TestsRevision:=FieldByName('TU_TESTSREVISION').AsString;
  577. aData.RTLRevision:=FieldByName('TU_RTLREVISION').AsString;
  578. aData.PackagesRevision:=FieldByName('TU_PACKAGESREVISION').AsString;
  579. for ST in TValidTestStatus do
  580. aData.StatusCount[ST]:=FieldByName(SQLField[ST]).AsInteger;
  581. end;
  582. finally
  583. Qry.Free;
  584. end;
  585. end;
  586. function TTestSQL.GetLastRunByPlatformAndDate(aPLatformID: Integer; aDate: TDateTime): Integer;
  587. const
  588. SQLSelect =
  589. 'select '+
  590. ' TU_ID '+
  591. 'from '+
  592. ' testrun '+
  593. 'where '+
  594. ' (tu_platform_fk=%d) '+
  595. ' and (tu_date<''%s'') '+
  596. 'order by '+
  597. ' tu_date desc '+
  598. 'limit 1';
  599. begin
  600. Result:=ID64Query(Format(SQLSelect,[aPlatformID,SQLDate(aDate)]));
  601. end;
  602. function TTestSQL.GetTestInfo(aID: Int64; out aInfo: TTestInfo): Boolean;
  603. function splitID(aString : String) : TIntegerDynArray;
  604. var
  605. lArray : TStringDynArray;
  606. i,count : integer;
  607. S : string;
  608. begin
  609. Result:=[];
  610. lArray:=aString.Split(',');
  611. SetLength(Result,Length(lArray));
  612. count:=0;
  613. for S in lArray do
  614. if TryStrToInt(Trim(S),i) then
  615. begin
  616. Result[Count]:=I;
  617. inc(count);
  618. end;
  619. SetLength(Result,Count);
  620. end;
  621. const
  622. SQLSelect = 'SELECT * FROM TESTS WHERE (T_ID=%d)';
  623. var
  624. Qry : TSQLQuery;
  625. begin
  626. aInfo:=Default(TTestInfo);
  627. Qry:=CreateQuery(Format(SQLSelect,[aID]));
  628. try
  629. Qry.Open;
  630. Result:=Not Qry.IsEmpty;
  631. if Not Result then
  632. exit;
  633. aInfo.Name:=Qry.FieldByname('T_Name').AsString;
  634. aInfo.CPU:=Qry.FieldByname('T_CPU').AsString;
  635. aInfo.OS:=Qry.FieldByname('T_OS').Asstring;
  636. aInfo.Version:=Qry.FieldByname('T_VERSION').Asstring;
  637. aInfo.AddDate:=Qry.FieldByname('T_ADDDATE').AsDateTime;
  638. aInfo.Graph:=Qry.FieldByname('T_GRAPH').Asboolean;
  639. aInfo.Interactive:=Qry.FieldByname('T_INTERACTIVE').Asboolean;
  640. aInfo.Result:=Qry.FieldByname('T_RESULT').AsInteger;
  641. aInfo.Fail:=Qry.FieldByname('T_FAIL').Asboolean;
  642. aInfo.ReCompile:=Qry.FieldByname('T_RECOMPILE').Asboolean;
  643. aInfo.NoRun:=Qry.FieldByname('T_NORUN').Asboolean;
  644. aInfo.NeedLibrary:=Qry.FieldByname('T_NEEDLIBRARY').Asboolean;
  645. aInfo.KnownRunError:=Qry.FieldByname('T_KNOWNRUNERROR').AsInteger;
  646. aInfo.Known:=Qry.FieldByname('T_Known').Asboolean;
  647. aInfo.Note:=Qry.FieldByname('T_NOTE').AsString;
  648. aInfo.Description:=Qry.FieldByname('T_DESCRIPTION').AsString;
  649. aInfo.Source:=Qry.FieldByname('T_SOURCE').AsString;
  650. aInfo.Opts:=Qry.FieldByname('T_OPTS').AsString;
  651. aInfo.DelOptions:=Qry.FieldByname('T_DELOPTS').AsString;
  652. aInfo.SkipCPU:=Qry.FieldByname('T_SKIPCPU').AsString;
  653. aInfo.SkipEmu:=Qry.FieldByname('T_SKIPEMU').AsString;
  654. aInfo.NeedTarget:=Qry.FieldByname('T_NEEDTARGET').AsString;
  655. aInfo.SkipTarget:=Qry.FieldByname('T_SKIPTARGET').AsString;
  656. aInfo.MaxVersion:=Qry.FieldByname('T_MAXVERSION').AsString;
  657. aInfo.KnownRunNote:=Qry.FieldByname('T_KNOWNRUNNOTE').AsString;
  658. aInfo.KnownCompileNote:=Qry.FieldByname('T_KNOWNCOMPILENOTE').AsString;
  659. aInfo.RecompileOpt:=Qry.FieldByname('T_RECOMPILEOPT').AsString;
  660. aInfo.KnownCompileError:=Qry.FieldByname('T_KNOWNCOMPILEERROR').AsInteger;
  661. aInfo.NeededAfter:=Qry.FieldByname('T_NEEDEDAFTER').AsBoolean;
  662. aInfo.IsKnownRunError:=Qry.FieldByname('T_ISKNOWNRUNERROR').AsBoolean;
  663. aInfo.Timeout:=Qry.FieldByname('T_TIMEOUT').AsInteger;
  664. aInfo.Category:=Qry.FieldByname('T_CATEGORY').AsString;
  665. aInfo.Files:=Qry.FieldByname('T_FILES').AsString;
  666. aInfo.ConfigFileSrc:=Qry.FieldByname('T_CONFIGFILESRC').AsString;
  667. aInfo.ConfigFileDst:=Qry.FieldByname('T_CONFIGFILEDST').AsString;
  668. aInfo.WpoParas:=Qry.FieldByname('T_WPOPARAS').AsString;
  669. aInfo.WpoPasses:=Qry.FieldByname('T_WPOPASSES').AsInteger;
  670. aInfo.DelFiles:=Qry.FieldByname('T_DELFILES').AsString;
  671. aInfo.ExpectMsgs:=SplitID(Qry.FieldByname('T_EXPECTMSGS').AsString);
  672. finally
  673. Qry.Free;
  674. end;
  675. end;
  676. function TTestSQL.AddRun(const aData : TTestRunData): Int64;
  677. Const
  678. SInsertRun = 'INSERT INTO TESTRUN '+
  679. '(TU_PLATFORM_FK, TU_SUBMITTER, TU_DATE, '+
  680. ' TU_COMPILERDATE, TU_COMPILERFULLVERSION, TU_COMPILERREVISION, '+
  681. ' TU_TESTSREVISION, TU_RTLREVISION, TU_PACKAGESREVISION )'+
  682. ' VALUES '+
  683. '(%d,''%s'',''%s'', '+
  684. ' ''%s'',''%s'',''%s'', '+
  685. ' ''%s'',''%s'',''%s'' '+
  686. ') RETURNING TU_ID';
  687. var
  688. Qry : string;
  689. PreviousID : Int64;
  690. begin
  691. With aData do
  692. qry:=Format(SInsertRun,[PlatformID,
  693. EscapeSQL(Submitter),
  694. SQLDate(Date),
  695. EscapeSQL(CompilerDate),
  696. EscapeSQL(CompilerFullVersion),
  697. EscapeSQL(CompilerRevision),
  698. EscapeSQL(TestsRevision),
  699. EscapeSQL(RTLRevision),
  700. EscapeSQL(PackagesRevision)]);
  701. Result:=IDQuery(Qry);
  702. PreviousID:=GetLastRunByPlatformAndDate(aData.PlatformID,aData.Date);
  703. if PreviousID<>-1 then
  704. InsertTestHistory(Result,PreviousID);
  705. end;
  706. function TTestSQL.InsertTestHistory(TestRunID,TestPreviousID : Integer) : boolean;
  707. const
  708. SQLInsert = 'INSERT INTO TESTRUNHISTORY '+
  709. ' (TH_ID_FK,TH_PREVIOUS_FK) '+
  710. 'VALUES '+
  711. ' (%d,%d) '+
  712. 'ON CONFLICT (TH_ID_FK) '+
  713. 'DO UPDATE SET '+
  714. ' TH_PREVIOUS_FK=EXCLUDED.TH_PREVIOUS_FK';
  715. var
  716. qry : string;
  717. begin
  718. Qry:=format(SQLInsert,[TestRunID,TestPreviousID]);
  719. Result:=ExecuteQuery(Qry,False);
  720. end;
  721. function TTestSQL.AddTest(Name: String; AddSource: Boolean): Integer;
  722. Const
  723. SInsertTest = 'INSERT INTO TESTS (T_NAME,T_ADDDATE)'+
  724. ' VALUES (''%s'',NOW()) ON CONFLICT (T_NAME) DO UPDATE SET T_ADDDATE=NOW() RETURNING T_ID';
  725. Var
  726. Info : TConfig;
  727. lSrcDir : String;
  728. lFileName : string;
  729. begin
  730. Info:=Default(TConfig);
  731. Result:=-1;
  732. lSrcDir:=IncludeTrailingPathDelimiter(TestSrcDir+RelSrcDir);
  733. lFileName:=ExpandFileName(lSrcDir+Name);
  734. Verbose(V_Debug,'Checking test filename: '+lFileName);
  735. Result:=IDQuery(Format(SInsertTest,[Name]));
  736. If Result=-1 then
  737. begin
  738. Verbose(V_WARNING,'Could not add test!');
  739. exit;
  740. end;
  741. If (FileExists(lFileName) and GetConfig(logprefix,lFileName,Info))
  742. or GetUnitTestConfig(logprefix,Name,lSrcDir,Info) then
  743. begin
  744. If AddSource then
  745. UpdateTest(Result,Info,tsutils.GetFileContents(Name))
  746. else
  747. UpdateTest(Result,Info,'');
  748. end
  749. else
  750. Verbose(V_WARNING,'Could not find test "'+Name+'" or info about this test.');
  751. end;
  752. function TTestSQL.UpdateTest(ID: Integer; Info: TConfig; const Source: String): Boolean;
  753. Const
  754. SQLUpdateTest = 'Update TESTS SET '+
  755. ' %s '+
  756. 'WHERE'+
  757. ' (T_ID=%d)';
  758. function JoinIDS(IDS: Array of Integer) : string;
  759. var
  760. S : String;
  761. I : Integer;
  762. begin
  763. S:='';
  764. For I:=0 to Length(IDS)-1 do
  765. begin
  766. if I>0 then
  767. S:=S+',';
  768. S:=S+IntToStr(IDS[i]);
  769. end;
  770. Result:=S;
  771. end;
  772. procedure AddField(var S : String; const aName,aValue : String);
  773. begin
  774. if S<>'' then
  775. S:=S+', ';
  776. S:=S+Format('%s = ''%s''',[aName,EscapeSQl(aValue)])
  777. end;
  778. procedure AddField(var S : String; const aName : String; aValue : Integer);
  779. begin
  780. if S<>'' then
  781. S:=S+', ';
  782. S:=S+Format('%s = %d',[aName,aValue])
  783. end;
  784. Var
  785. Qry : String;
  786. begin
  787. Qry:='';
  788. With Info do
  789. begin
  790. AddField(Qry,'T_CPU',NeedCPU);
  791. AddField(Qry,'T_OS',OS);
  792. AddField(Qry,'T_VERSION',MinVersion);
  793. AddField(Qry,'T_GRAPH',Bools[usesGraph]);
  794. AddField(Qry,'T_INTERACTIVE',Bools[IsInteractive]);
  795. AddField(Qry,'T_RESULT',ResultCode);
  796. AddField(Qry,'T_FAIL',Bools[ShouldFail]);
  797. AddField(Qry,'T_RECOMPILE',Bools[NeedRecompile]);
  798. AddField(Qry,'T_NORUN',Bools[NoRun]);
  799. AddField(Qry,'T_DESCRIPTION',Description);
  800. AddField(Qry,'T_NEEDLIBRARY',Bools[NeedLibrary]);
  801. AddField(Qry,'T_KNOWNRUNERROR',KnownRunError);
  802. AddField(Qry,'T_KNOWN',Bools[IsKnownCompileError]);
  803. AddField(Qry,'T_Note',Note);
  804. AddField(Qry,'T_OPTS',NeedOptions);
  805. AddField(Qry,'T_DELOPTS',DelOptions);
  806. AddField(Qry,'T_SKIPCPU',SkipCPU);
  807. AddField(Qry,'T_SKIPEMU',SkipEmu);
  808. AddField(Qry,'T_NEEDTARGET',NeedTarget);
  809. AddField(Qry,'T_SKIPTARGET',SkipTarget);
  810. AddField(Qry,'T_MAXVERSION',MaxVersion);
  811. AddField(Qry,'T_KNOWNRUNNOTE',KnownRunNote);
  812. AddField(Qry,'T_KNOWNCOMPILENOTE',KnownCompileNote);
  813. AddField(Qry,'T_RECOMPILEOPT',RecompileOpt);
  814. AddField(Qry,'T_KNOWNCOMPILEERROR',KnownCompileError);
  815. AddField(Qry,'T_NEEDEDAFTER',Bools[NeededAfter]);
  816. AddField(Qry,'T_ISKNOWNRUNERROR',Bools[IsKnownRunError]);
  817. AddField(Qry,'T_TIMEOUT', Timeout);
  818. AddField(Qry,'T_CATEGORY',Category);
  819. AddField(Qry,'T_FILES',Files);
  820. AddField(Qry,'T_CONFIGFILESRC',ConfigFileSrc);
  821. AddField(Qry,'T_CONFIGFILEDST',ConfigFileDst);
  822. AddField(Qry,'T_WPOPARAS',WpoParas);
  823. AddField(Qry,'T_WPOPASSES',WpoPasses);
  824. AddField(Qry,'T_DELFILES',DelFiles);
  825. AddField(Qry,'T_EXPECTMSGS',JoinIDS(ExpectMsgs));
  826. If (Source<>'') then
  827. AddField(Qry,'T_SOURCE',Source);
  828. end;
  829. Qry:=Format(SQLUpdateTest,[Qry,ID]);
  830. Result:=ExecuteQuery(Qry,False);
  831. end;
  832. function TTestSQL.UpdateTestResult(aData: TTestResultData): Int64;
  833. const
  834. SQLUpdate = 'UPDATE TESTRESULTS SET '+
  835. ' TR_RESULT = %d, '+
  836. ' TR_TESTRUN_FK = %d, '+
  837. ' TR_OK = ''%s'', '+
  838. ' TR_SKIP = ''%s'', '+
  839. ' TR_LOG = ''%s'' '+
  840. 'WHERE (TR_ID=%d)';
  841. var
  842. Qry : String;
  843. OK, Skipped : Boolean;
  844. begin
  845. with aData do
  846. begin
  847. OK:=TestOK[TestResult];
  848. Skipped:=TestSkipped[TestResult];
  849. Qry:=Format(SQLUpdate, [Ord(TestResult),RunID,Bools[OK],Bools[Skipped],EscapeSQL(Log),aData.ID]);
  850. Result:=aData.ID;
  851. end;
  852. ExecuteQuery(Qry,False);
  853. end;
  854. function TTestSQL.AddTestResult(aData: TTestResultData): Int64;
  855. Const
  856. SQLInsert = 'Insert into TESTRESULTS '+
  857. ' (TR_TEST_FK,TR_TESTRUN_FK,TR_OK,TR_SKIP,TR_RESULT,TR_LOG) '+
  858. 'VALUES '+
  859. ' (%d,%d,''%s'',''%s'',%d, ''%s'') '+
  860. 'ON CONFLICT (TR_TEST_FK,TR_TESTRUN_FK) '+
  861. 'DO UPDATE SET '+
  862. ' TR_OK = EXCLUDED.TR_OK, '+
  863. ' TR_SKIP = EXCLUDED.TR_SKIP, '+
  864. ' TR_RESULT = EXCLUDED.TR_RESULT, '+
  865. ' TR_LOG = EXCLUDED.TR_LOG '+
  866. 'RETURNING TR_ID ';
  867. Var
  868. Qry : String;
  869. OK, Skipped : Boolean;
  870. begin
  871. Result:=-1;
  872. With aData do
  873. begin
  874. OK:=TestOK[TestResult];
  875. Skipped:=TestSkipped[TestResult];
  876. Qry:=Format(SQLInsert, [TestID,RunID,Bools[OK],Bools[Skipped],Ord(TestResult),EscapeSQL(Log)]);
  877. end;
  878. Result:=ID64Query(Qry);
  879. end;
  880. function TTestSQL.GetLastTestResult(aTestID, aPlatFormID: Integer): TTestResultData;
  881. Const
  882. SQLSelect = 'SELECT TESTRESULTS.*, TU_DATE FROM '+
  883. ' TESTLASTRESULTS '+
  884. ' INNER JOIN TESTRESULTS ON (TL_TESTRESULTS_FK=TR_ID) '+
  885. ' INNER JOIN TESTRUN ON (TR_TESTRUN_FK=TU_ID) '+
  886. 'WHERE '+
  887. ' (TL_TEST_FK=%d) '+
  888. ' AND (TL_PLATFORM_FK=%d)';
  889. var
  890. Qry : TSQLQuery;
  891. S : String;
  892. begin
  893. Result:=Default(TTestResultData);
  894. Result.TestID:=aTestID;
  895. Result.PlatformID:=aPlatformID;
  896. S:=Format(SQLSelect,[aTestID,aPlatformID]);
  897. Qry:=CreateQuery(S);
  898. Verbose(V_SQL,'GetLastTestResult: '+s);
  899. try
  900. Qry.Open;
  901. If not Qry.IsEmpty then
  902. begin
  903. Result.ID:=Qry.FieldByName('TR_ID').AsLargeInt;
  904. Result.TestResult:=TTestStatus(Qry.FieldByName('TR_RESULT').AsInteger);
  905. Result.RunID:=Qry.FieldByName('TR_TESTRUN_FK').AsLargeInt;
  906. Result.Log:=Qry.FieldByName('TR_LOG').AsString;
  907. Result.Date:=Qry.FieldByName('TU_DATE').AsDateTime;
  908. end
  909. else
  910. Result.ID:=-1;
  911. finally
  912. if Qry.SQLTransaction.Active then
  913. Qry.SQLTransaction.Commit;
  914. Qry.Free;
  915. end;
  916. end;
  917. function TTestSQL.GetFailCount(aRunID: Int64): Int64;
  918. const
  919. SQLSelectFailCount =
  920. 'SELECT (TU_FAILEDTOCOMPILE + TU_FAILEDTOFAIL + TU_FAILEDTORUN) as thecount '+
  921. ' FROM TESTRUN WHERE (TU_ID=%d)';
  922. begin
  923. Result:=ID64Query(Format(SQLSelectFailCount,[aRunID]));
  924. end;
  925. function TTestSQL.AddLastResult(TestID, PlatformID: Integer; ResultID: Int64) : Boolean;
  926. const
  927. SQLInsert = 'Insert into TESTLASTRESULTS '+
  928. ' (TL_TEST_FK,TL_PLATFORM_FK,TL_TESTRESULTS_FK) '+
  929. 'VALUES '+
  930. ' (%d,%d,%d) '+
  931. 'ON CONFLICT (TL_TEST_FK,TL_PLATFORM_FK) '+
  932. 'DO UPDATE SET TL_TESTRESULTS_FK = EXCLUDED.TL_TESTRESULTS_FK ';
  933. begin
  934. Result:=ExecuteQuery(Format(SQLInsert,[TestId,PlatFormID,ResultID]),False);
  935. end;
  936. function TTestSQL.AddPreviousResult(TestID, PlatformID: Integer; ResultID: Int64): Boolean;
  937. const
  938. SQLInsert = 'Insert into TESTPREVIOUSRESULTS '+
  939. ' (TPR_TEST_FK,TPR_PLATFORM_FK,TPR_TESTRESULTS_FK) '+
  940. 'VALUES '+
  941. ' (%d,%d,%d) '+
  942. 'ON CONFLICT (TPR_TEST_FK,TPR_PLATFORM_FK) '+
  943. 'DO UPDATE SET TPR_TESTRESULTS_FK = EXCLUDED.TPR_TESTRESULTS_FK ';
  944. begin
  945. Result:=ExecuteQuery(Format(SQLInsert,[TestId,PlatFormID,ResultID]),False);
  946. end;
  947. function TTestSQL.AddCheckAllRtlLog(aCheckAllRTLID : int64; aStep : Byte; const aLog : String): Int64;
  948. const
  949. SQLInsertLog = 'INSERT INTO public.checkallrtllog '+
  950. ' (cal_checkallrtl_fk, cal_step, cal_log) '+
  951. 'VALUES '+
  952. ' (:cal_checkallrtl_fk, :cal_step, :cal_log) '+
  953. 'returning cal_id';
  954. var
  955. Qry : TSQLQuery;
  956. begin
  957. Qry:=CreateQuery(SQLInsertLog);
  958. try
  959. Qry.ParamByName('cal_checkallrtl_fk').AsLargeInt:=aCheckAllRTLID;
  960. Qry.ParamByName('cal_step').AsInteger:=aStep;
  961. Qry.ParamByName('cal_log').AsString:=aLog;
  962. Result:=GetIDQueryResult(Qry);
  963. finally
  964. Qry.Free;
  965. end;
  966. end;
  967. function TTestSQL.AddCheckAllRtl(aData: TCheckAllRTL): Int64;
  968. const
  969. SQLInsertCAR =
  970. 'INSERT INTO public.checkallrtl( '+
  971. ' ca_platform_fk, ca_date, ca_step1, ca_step2, ca_step3, ca_step4, ca_step5, ca_step6)'+
  972. 'VALUES (:ca_platform_fk, :ca_date, :ca_step1, :ca_step2, :ca_step3, :ca_step4, :ca_step5, :ca_step6) '+
  973. ' returning ca_id';
  974. var
  975. Qry : TSQLQuery;
  976. i : TCheckStage;
  977. begin
  978. Qry:=CreateQuery(SQLInsertCar);
  979. try
  980. Qry.ParamByName('ca_platform_fk').AsInteger:=aData.Platform;
  981. Qry.ParamByName('ca_date').AsDateTime:=aData.Date;
  982. Qry.ParamByName('ca_step1').AsBoolean:=aData.Steps[1];
  983. Qry.ParamByName('ca_step2').AsBoolean:=aData.Steps[2];
  984. Qry.ParamByName('ca_step3').AsBoolean:=aData.Steps[3];
  985. Qry.ParamByName('ca_step4').AsBoolean:=aData.Steps[4];
  986. Qry.ParamByName('ca_step5').AsBoolean:=aData.Steps[5];
  987. Qry.ParamByName('ca_step6').AsBoolean:=aData.Steps[6];
  988. Qry.Open;
  989. Result:=GetIDQueryResult(Qry);
  990. if Result<>-1 then
  991. begin
  992. For I in TCheckStage do
  993. if (not aData.Steps[i]) and (aData.Logs[i]<>'') then
  994. AddCheckAllRtlLog(Result,i,aData.Logs[i]);
  995. end;
  996. finally
  997. Qry.Free;
  998. end;
  999. end;
  1000. function TTestSQL.UpdateTestRun(aData: TTestRunData): Boolean;
  1001. var
  1002. Qry : string;
  1003. I : TValidTestStatus;
  1004. Procedure AddTo(S : String);
  1005. begin
  1006. if Qry<>'' then
  1007. Qry:=Qry+' , ';
  1008. Qry:=Qry+S;
  1009. end;
  1010. begin
  1011. Qry:='';
  1012. for I in TValidTestStatus do
  1013. AddTo(format('%s=%d',[SQLField[i],aData.StatusCount[i]]));
  1014. qry:='UPDATE TESTRUN SET '+Qry+' WHERE TU_ID='+format('%d',[aData.RunID]);
  1015. ExecuteQuery(Qry,False);
  1016. Result:=True;
  1017. end;
  1018. function TTestSQL.GetFailCount(aRunID: Integer): Int64;
  1019. begin
  1020. Result:=ID64Query(Format('SELECT (TU_FAILEDTOCOMPILE + TU_FAILEDTOFAIL + TU_FAILEDTORUN) FROM TESTRUN WHERE (TU_ID=%d)',[aRunID]));
  1021. end;
  1022. function TTestSQL.RequireTestID(const aName: String): Integer;
  1023. begin
  1024. Result:=GetTestID(aName);
  1025. If Result=-1 then
  1026. Result:=AddTest(aName,True);
  1027. If Result=-1 then
  1028. Verbose(V_WARNING,'Could not find or create entry for test '+aName);
  1029. end;
  1030. function TTestSQL.CleanTestRun(ID: Integer): Boolean;
  1031. Const
  1032. SDeleteRun = 'DELETE FROM TESTRESULTS WHERE TR_TESTRUN_FK=%d';
  1033. begin
  1034. Result:=ExecuteQuery(Format(SDeleteRun,[ID]),False);
  1035. end;
  1036. function TTestSQL.GetPreviousRunID(RunID: Int64): Int64;
  1037. begin
  1038. Result:=ID64Query(Format('SELECT TH_PREVIOUS_FK FROM TESTRUNHISTORY WHERE (TH_ID_FK=%d)',[RunID]));
  1039. end;
  1040. function TTestSQL.GetNextRunID(RunID: Int64): Int64;
  1041. begin
  1042. Result:=ID64Query(Format('SELECT TH_ID_FK FROM TESTRUNHISTORY WHERE (TH_PREVIOUS_FK=%d)',[RunID]));
  1043. end;
  1044. end.