From 89eb9a2df90630432c92eae2582b9ae8df0863c9 Mon Sep 17 00:00:00 2001 From: Zack Galbreath Date: Wed, 20 Nov 2024 07:43:04 -0500 Subject: [PATCH] Move remove_builds (and related functions) to DatabaseUtils (#2575) Continue to reduce the amount of legacy code that lives in common.php. Functionally, this should be more-or-less a no-op. --- app/Http/Controllers/AdminController.php | 5 +- app/Http/Controllers/BuildController.php | 3 +- app/Utils/DatabaseCleanupUtils.php | 312 +++++++++++++++++- app/Utils/SubmissionUtils.php | 2 +- app/cdash/app/Model/Build.php | 3 +- app/cdash/include/common.php | 306 +---------------- app/cdash/tests/test_bazeljson.php | 23 +- app/cdash/tests/test_branchcoverage.php | 5 +- app/cdash/tests/test_buildconfigure.php | 6 +- app/cdash/tests/test_builddetails.php | 7 +- app/cdash/tests/test_buildfailuredetails.php | 5 +- app/cdash/tests/test_buildgrouprule.php | 3 +- app/cdash/tests/test_buildmodel.php | 6 +- app/cdash/tests/test_buildrelationship.php | 3 +- app/cdash/tests/test_deferredsubmissions.php | 3 +- app/cdash/tests/test_disabledtests.php | 3 +- app/cdash/tests/test_donehandler.php | 5 +- .../tests/test_dynamicanalysissummary.php | 3 +- .../tests/test_externallinksfromtests.php | 3 +- app/cdash/tests/test_filterbuilderrors.php | 3 +- app/cdash/tests/test_filtertestlabels.php | 6 +- app/cdash/tests/test_hidecolumns.php | 3 +- app/cdash/tests/test_imagecomparison.php | 3 +- app/cdash/tests/test_managemeasurements.php | 5 +- app/cdash/tests/test_multicoverage.php | 6 +- app/cdash/tests/test_multiplesubprojects.php | 5 +- app/cdash/tests/test_nobackup.php | 3 +- app/cdash/tests/test_opencovercoverage.php | 4 +- app/cdash/tests/test_parallelsubmissions.php | 4 +- app/cdash/tests/test_removebuilds.php | 3 +- app/cdash/tests/test_replacebuild.php | 5 +- .../tests/test_submission_assign_buildid.php | 3 +- .../tests/test_subprojectnextprevious.php | 5 +- app/cdash/tests/test_truncateoutput.php | 3 +- .../test_unparsedsubmissionshonorbuildid.php | 4 +- app/cdash/tests/test_updateappend.php | 6 +- app/cdash/tests/test_updateonlyuserstats.php | 3 +- .../tests/test_viewdynamicanalysisfile.php | 3 +- phpstan-baseline.neon | 93 ++++-- 39 files changed, 471 insertions(+), 405 deletions(-) diff --git a/app/Http/Controllers/AdminController.php b/app/Http/Controllers/AdminController.php index 1eb47e8c60..337e816dd1 100644 --- a/app/Http/Controllers/AdminController.php +++ b/app/Http/Controllers/AdminController.php @@ -2,6 +2,7 @@ namespace App\Http\Controllers; use App\Models\User; +use App\Utils\DatabaseCleanupUtils; use CDash\Model\Project; use Illuminate\Http\RedirectResponse; use Illuminate\Support\Facades\DB; @@ -96,7 +97,7 @@ public function removeBuilds(): View|RedirectResponse $builds[] = (int) $build_array->id; } - remove_build_chunked($builds); + DatabaseCleanupUtils::removeBuildChunked($builds); $alert = 'Removed ' . count($builds) . ' builds.'; } @@ -446,7 +447,7 @@ public function upgrade() starttime<'1975-12-31 23:59:59' OR starttime>'$forwarddate'"); while ($builds_array = pdo_fetch_array($builds)) { $buildid = $builds_array['id']; - remove_build($buildid); + DatabaseCleanupUtils::removeBuild($buildid); } } diff --git a/app/Http/Controllers/BuildController.php b/app/Http/Controllers/BuildController.php index 2b64f88c10..0a6a3260eb 100644 --- a/app/Http/Controllers/BuildController.php +++ b/app/Http/Controllers/BuildController.php @@ -4,6 +4,7 @@ use App\Models\Comment; use App\Models\User; use App\Models\Build as EloquentBuild; +use App\Utils\DatabaseCleanupUtils; use App\Utils\PageTimer; use App\Utils\RepositoryUtils; use App\Utils\TestingDay; @@ -1470,7 +1471,7 @@ private function restApiPost(): JsonResponse private function restApiDelete(): JsonResponse { Log::info("Build #{$this->build->Id} removed manually."); - remove_build($this->build->Id); + DatabaseCleanupUtils::removeBuild($this->build->Id); return response()->json(); } } diff --git a/app/Utils/DatabaseCleanupUtils.php b/app/Utils/DatabaseCleanupUtils.php index 9066e51dff..1b57001323 100644 --- a/app/Utils/DatabaseCleanupUtils.php +++ b/app/Utils/DatabaseCleanupUtils.php @@ -6,8 +6,10 @@ use App\Models\Build; use App\Models\BuildGroup; +use CDash\Database; use Illuminate\Support\Facades\DB; use Illuminate\Support\Facades\Log; +use InvalidArgumentException; class DatabaseCleanupUtils { @@ -54,7 +56,7 @@ public static function removeBuildsGroupwise(int $projectid, int $maxbuilds, boo $s = 'removing old buildids for projectid: ' . $projectid; Log::info($s); echo ' -- ' . $s . "\n"; - remove_build_chunked($buildids); + self::removeBuildChunked($buildids); } /** Remove the first builds that are at the beginning of the queue */ @@ -89,6 +91,312 @@ public static function removeFirstBuilds(int $projectid, int $days, int $maxbuil if ($echo) { echo ' -- ' . $s . "\n"; // for "interactive" command line feedback } - remove_build_chunked($buildids); + self::removeBuildChunked($buildids); + } + + /** + * Remove all related inserts for a given build or any build in an array of builds + * @param array|int $buildid + * @throws \InvalidArgumentException + */ + public static function removeBuild($buildid) : void + { + // TODO: (williamjallen) much of this work could be done on the DB side automatically by setting up + // proper foreign-key relationships between between entities, and using the DB's cascade functionality. + // For complex cascades, custom SQL functions can be written. + + if (!is_array($buildid)) { + $buildid = [$buildid]; + } + + $buildids = []; + foreach ($buildid as $b) { + if (!is_numeric($b)) { + throw new InvalidArgumentException('Invalid Build ID'); + } + $buildids[] = intval($b); + } + + $db = Database::getInstance(); + $buildid_prepare_array = $db->createPreparedArray(count($buildids)); + + // Remove the buildfailureargument + $buildfailureids = []; + $buildfailure = DB::select("SELECT id FROM buildfailure WHERE buildid IN $buildid_prepare_array", $buildids); + foreach ($buildfailure as $buildfailure_array) { + $buildfailureids[] = intval($buildfailure_array->id); + } + if (count($buildfailureids) > 0) { + $buildfailure_prepare_array = $db->createPreparedArray(count($buildfailureids)); + DB::delete("DELETE FROM buildfailure2argument WHERE buildfailureid IN $buildfailure_prepare_array", $buildfailureids); + DB::delete("DELETE FROM label2buildfailure WHERE buildfailureid IN $buildfailure_prepare_array", $buildfailureids); + } + + // Delete buildfailuredetails that are only used by builds that are being + // deleted. + DB::delete(" + DELETE FROM buildfailuredetails WHERE id IN ( + SELECT a.detailsid + FROM buildfailure AS a + LEFT JOIN buildfailure AS b ON ( + a.detailsid=b.detailsid + AND b.buildid NOT IN $buildid_prepare_array + ) + WHERE a.buildid IN $buildid_prepare_array + GROUP BY a.detailsid + HAVING count(b.detailsid)=0 + ) + ", array_merge($buildids, $buildids)); + + // Delete the configure if not shared. + $build2configure = DB::select(" + SELECT a.configureid + FROM build2configure AS a + LEFT JOIN build2configure AS b ON ( + a.configureid=b.configureid + AND b.buildid NOT IN $buildid_prepare_array + ) + WHERE a.buildid IN $buildid_prepare_array + GROUP BY a.configureid + HAVING count(b.configureid)=0 + ", array_merge($buildids, $buildids)); + + $configureids = []; + foreach ($build2configure as $build2configure_array) { + // It is safe to delete this configure because it is only used + // by builds that are being deleted. + $configureids[] = intval($build2configure_array->configureid); + } + if (count($configureids) > 0) { + $configureids_prepare_array = $db->createPreparedArray(count($configureids)); + DB::delete("DELETE FROM configure WHERE id IN $configureids_prepare_array", $configureids); + } + + // coverage files are kept unless they are shared + DB::delete(" + DELETE FROM coveragefile + WHERE id IN ( + SELECT f1.id + FROM ( + SELECT a.fileid AS id, COUNT(DISTINCT a.buildid) AS c + FROM coverage a + WHERE a.buildid IN $buildid_prepare_array + GROUP BY a.fileid + ) AS f1 + INNER JOIN ( + SELECT b.fileid AS id, COUNT(DISTINCT b.buildid) AS c + FROM coverage b + INNER JOIN ( + SELECT fileid + FROM coverage + WHERE buildid IN $buildid_prepare_array + ) AS d ON b.fileid = d.fileid + GROUP BY b.fileid + ) AS f2 ON (f1.id = f2.id) + WHERE f1.c = f2.c + ) + ", array_merge($buildids, $buildids)); + + // dynamicanalysisdefect + $dynamicanalysis = DB::select(" + SELECT id + FROM dynamicanalysis + WHERE buildid IN $buildid_prepare_array + ", $buildids); + + $dynids = []; + foreach ($dynamicanalysis as $dynamicanalysis_array) { + $dynids[] = intval($dynamicanalysis_array->id); + } + + if (count($dynids) > 0) { + $dynids_prepare_array = $db->createPreparedArray(count($dynids)); + DB::delete("DELETE FROM dynamicanalysisdefect WHERE dynamicanalysisid IN $dynids_prepare_array", $dynids); + DB::delete("DELETE FROM label2dynamicanalysis WHERE dynamicanalysisid IN $dynids_prepare_array", $dynids); + } + + // Delete the note if not shared + DB::delete(" + DELETE FROM note WHERE id IN ( + SELECT f1.id + FROM ( + SELECT a.noteid AS id, COUNT(DISTINCT a.buildid) AS c + FROM build2note a + WHERE a.buildid IN $buildid_prepare_array + GROUP BY a.noteid + ) AS f1 + INNER JOIN ( + SELECT b.noteid AS id, COUNT(DISTINCT b.buildid) AS c + FROM build2note b + INNER JOIN ( + SELECT noteid + FROM build2note + WHERE buildid IN $buildid_prepare_array + ) AS d ON b.noteid = d.noteid + GROUP BY b.noteid + ) AS f2 ON (f1.id = f2.id) + WHERE f1.c = f2.c + ) + ", array_merge($buildids, $buildids)); + + // Delete the update if not shared + $build2update = DB::select(" + SELECT a.updateid + FROM build2update AS a + LEFT JOIN build2update AS b ON ( + a.updateid=b.updateid + AND b.buildid NOT IN $buildid_prepare_array + ) + WHERE a.buildid IN $buildid_prepare_array + GROUP BY a.updateid + HAVING count(b.updateid)=0 + ", array_merge($buildids, $buildids)); + + $updateids = []; + foreach ($build2update as $build2update_array) { + // Update is not shared we delete + $updateids[] = intval($build2update_array->updateid); + } + + if (count($updateids) > 0) { + $updateids_prepare_array = $db->createPreparedArray(count($updateids)); + DB::delete("DELETE FROM buildupdate WHERE id IN $updateids_prepare_array", $updateids); + DB::delete("DELETE FROM updatefile WHERE updateid IN $updateids_prepare_array", $updateids); + } + + // Delete tests and testoutputs that are not shared. + // First find all the tests and testoutputs from builds that are about to be deleted. + $b2t_result = DB::select(" + SELECT DISTINCT outputid + FROM build2test + WHERE buildid IN $buildid_prepare_array + ", $buildids); + + $all_outputids = []; + foreach ($b2t_result as $b2t_row) { + $all_outputids[] = intval($b2t_row->outputid); + } + + // Delete un-shared testoutput rows. + if (!empty($all_outputids)) { + // Next identify tests from this list that should be preserved + // because they are shared with builds that are not about to be deleted. + $all_outputids_prepare_array = $db->createPreparedArray(count($all_outputids)); + $save_test_result = DB::select(" + SELECT DISTINCT outputid + FROM build2test + WHERE + outputid IN $all_outputids_prepare_array + AND buildid NOT IN $buildid_prepare_array + ", array_merge($all_outputids, $buildids)); + $testoutputs_to_save = []; + foreach ($save_test_result as $save_test_row) { + $testoutputs_to_save[] = intval($save_test_row->outputid); + } + + // Use array_diff to get the list of tests that should be deleted. + $testoutputs_to_delete = array_diff($all_outputids, $testoutputs_to_save); + if (!empty($testoutputs_to_delete)) { + self::deleteRowsChunked('DELETE FROM testoutput WHERE id IN ', $testoutputs_to_delete); + + $testoutputs_to_delete_prepare_array = $db->createPreparedArray(count($testoutputs_to_delete)); + // Check if the images for the test are not shared + $test2image = DB::select(" + SELECT a.imgid + FROM test2image AS a + LEFT JOIN test2image AS b ON ( + a.imgid=b.imgid + AND b.outputid NOT IN $testoutputs_to_delete_prepare_array + ) + WHERE a.outputid IN $testoutputs_to_delete_prepare_array + GROUP BY a.imgid + HAVING count(b.imgid)=0 + ", array_merge($testoutputs_to_delete, $testoutputs_to_delete)); + + $imgids = []; + foreach ($test2image as $test2image_array) { + $imgids[] = intval($test2image_array->imgid); + } + + if (count($imgids) > 0) { + $imgids_prepare_array = $db->createPreparedArray(count($imgids)); + DB::delete("DELETE FROM image WHERE id IN $imgids_prepare_array", $imgids); + } + self::deleteRowsChunked('DELETE FROM test2image WHERE outputid IN ', $testoutputs_to_delete); + } + } + + // Delete the uploaded files if not shared + $build2uploadfiles = DB::select(" + SELECT a.fileid + FROM build2uploadfile AS a + LEFT JOIN build2uploadfile AS b ON ( + a.fileid=b.fileid + AND b.buildid NOT IN $buildid_prepare_array + ) + WHERE a.buildid IN $buildid_prepare_array + GROUP BY a.fileid + HAVING count(b.fileid)=0 + ", array_merge($buildids, $buildids)); + + $fileids = []; + foreach ($build2uploadfiles as $build2uploadfile_array) { + $fileid = intval($build2uploadfile_array->fileid); + $fileids[] = $fileid; + unlink_uploaded_file($fileid); + } + + if (count($fileids) > 0) { + $fileids_prepare_array = $db->createPreparedArray(count($fileids)); + DB::delete("DELETE FROM uploadfile WHERE id IN $fileids_prepare_array", $fileids); + DB::delete("DELETE FROM build2uploadfile WHERE fileid IN $fileids_prepare_array", $fileids); + } + + // Remove any children of these builds. + // In order to avoid making the list of builds to delete too large + // we delete them in batches (one batch per parent). + foreach ($buildids as $parentid) { + $child_result = DB::select('SELECT id FROM build WHERE parentid=?', [intval($parentid)]); + + $childids = []; + foreach ($child_result as $child_array) { + $childids[] = intval($child_array->id); + } + if (!empty($childids)) { + self::removeBuild($childids); + } + } + + // Only delete the buildid at the end so that no other build can get it in the meantime + DB::delete("DELETE FROM build WHERE id IN $buildid_prepare_array", $buildids); + + add_last_sql_error('remove_build'); + } + + /** + * Call removeBuild() in batches of 100. + * @param array|int $buildids + */ + public static function removeBuildChunked($buildids): void + { + if (!is_array($buildids)) { + self::removeBuild($buildid); + } + foreach (array_chunk($buildids, 100) as $chunk) { + self::removeBuild($chunk); + } + } + + /** + * Chunk up DELETE queries into batches of 100. + */ + private static function deleteRowsChunked(string $query, array $ids): void + { + foreach (array_chunk($ids, 100) as $chunk) { + $chunk_prepared_array = Database::getInstance()->createPreparedArray(count($chunk)); + DB::delete("$query $chunk_prepared_array", $chunk); + // Sleep for a microsecond to give other processes a chance. + usleep(1); + } } } diff --git a/app/Utils/SubmissionUtils.php b/app/Utils/SubmissionUtils.php index d69a103e99..412f786617 100644 --- a/app/Utils/SubmissionUtils.php +++ b/app/Utils/SubmissionUtils.php @@ -91,7 +91,7 @@ public static function add_build(Build $build) if ($buildid > 0 && !$build->Append) { $build->Id = $buildid; if ($build->GetDone()) { - remove_build($buildid); + DatabaseCleanupUtils::removeBuild($buildid); $build->Id = null; } } diff --git a/app/cdash/app/Model/Build.php b/app/cdash/app/Model/Build.php index b5ceadc92d..9060eba9dd 100644 --- a/app/cdash/app/Model/Build.php +++ b/app/cdash/app/Model/Build.php @@ -18,6 +18,7 @@ use App\Models\Test; use App\Models\Site; +use App\Utils\DatabaseCleanupUtils; use App\Utils\RepositoryUtils; use App\Utils\SubmissionUtils; use App\Utils\TestingDay; @@ -2199,7 +2200,7 @@ public function RemoveIfDone(): bool return false; } - remove_build($this->Id); + DatabaseCleanupUtils::removeBuild($this->Id); $this->Id = 0; return true; } diff --git a/app/cdash/include/common.php b/app/cdash/include/common.php index c692855d7e..79cc2e6552 100644 --- a/app/cdash/include/common.php +++ b/app/cdash/include/common.php @@ -17,6 +17,7 @@ use App\Utils\SubmissionUtils; use Illuminate\Support\Facades\Auth; +use App\Utils\DatabaseCleanupUtils; use App\Utils\TestingDay; use CDash\Database; @@ -407,310 +408,7 @@ function remove_project_builds($projectid): void foreach ($build as $build_array) { $buildids[] = (int) $build_array->id; } - remove_build_chunked($buildids); -} - -/** - * Remove all related inserts for a given build or any build in an array of builds - */ -function remove_build($buildid) -{ - // TODO: (williamjallen) much of this work could be done on the DB side automatically by setting up - // proper foreign-key relationships between between entities, and using the DB's cascade functionality. - // For complex cascades, custom SQL functions can be written. - - if (!is_array($buildid)) { - $buildid = [$buildid]; - } - - $buildids = []; - foreach ($buildid as $b) { - if (!is_numeric($b)) { - throw new InvalidArgumentException('Invalid Build ID'); - } - $buildids[] = intval($b); - } - - $db = Database::getInstance(); - $buildid_prepare_array = $db->createPreparedArray(count($buildids)); - - // Remove the buildfailureargument - $buildfailureids = []; - $buildfailure = DB::select("SELECT id FROM buildfailure WHERE buildid IN $buildid_prepare_array", $buildids); - foreach ($buildfailure as $buildfailure_array) { - $buildfailureids[] = intval($buildfailure_array->id); - } - if (count($buildfailureids) > 0) { - $buildfailure_prepare_array = $db->createPreparedArray(count($buildfailureids)); - DB::delete("DELETE FROM buildfailure2argument WHERE buildfailureid IN $buildfailure_prepare_array", $buildfailureids); - DB::delete("DELETE FROM label2buildfailure WHERE buildfailureid IN $buildfailure_prepare_array", $buildfailureids); - } - - // Delete buildfailuredetails that are only used by builds that are being - // deleted. - DB::delete(" - DELETE FROM buildfailuredetails WHERE id IN ( - SELECT a.detailsid - FROM buildfailure AS a - LEFT JOIN buildfailure AS b ON ( - a.detailsid=b.detailsid - AND b.buildid NOT IN $buildid_prepare_array - ) - WHERE a.buildid IN $buildid_prepare_array - GROUP BY a.detailsid - HAVING count(b.detailsid)=0 - ) - ", array_merge($buildids, $buildids)); - - // Delete the configure if not shared. - $build2configure = DB::select(" - SELECT a.configureid - FROM build2configure AS a - LEFT JOIN build2configure AS b ON ( - a.configureid=b.configureid - AND b.buildid NOT IN $buildid_prepare_array - ) - WHERE a.buildid IN $buildid_prepare_array - GROUP BY a.configureid - HAVING count(b.configureid)=0 - ", array_merge($buildids, $buildids)); - - $configureids = []; - foreach ($build2configure as $build2configure_array) { - // It is safe to delete this configure because it is only used - // by builds that are being deleted. - $configureids[] = intval($build2configure_array->configureid); - } - if (count($configureids) > 0) { - $configureids_prepare_array = $db->createPreparedArray(count($configureids)); - DB::delete("DELETE FROM configure WHERE id IN $configureids_prepare_array", $configureids); - } - - // coverage files are kept unless they are shared - DB::delete(" - DELETE FROM coveragefile - WHERE id IN ( - SELECT f1.id - FROM ( - SELECT a.fileid AS id, COUNT(DISTINCT a.buildid) AS c - FROM coverage a - WHERE a.buildid IN $buildid_prepare_array - GROUP BY a.fileid - ) AS f1 - INNER JOIN ( - SELECT b.fileid AS id, COUNT(DISTINCT b.buildid) AS c - FROM coverage b - INNER JOIN ( - SELECT fileid - FROM coverage - WHERE buildid IN $buildid_prepare_array - ) AS d ON b.fileid = d.fileid - GROUP BY b.fileid - ) AS f2 ON (f1.id = f2.id) - WHERE f1.c = f2.c - ) - ", array_merge($buildids, $buildids)); - - // dynamicanalysisdefect - $dynamicanalysis = DB::select(" - SELECT id - FROM dynamicanalysis - WHERE buildid IN $buildid_prepare_array - ", $buildids); - - $dynids = []; - foreach ($dynamicanalysis as $dynamicanalysis_array) { - $dynids[] = intval($dynamicanalysis_array->id); - } - - if (count($dynids) > 0) { - $dynids_prepare_array = $db->createPreparedArray(count($dynids)); - DB::delete("DELETE FROM dynamicanalysisdefect WHERE dynamicanalysisid IN $dynids_prepare_array", $dynids); - DB::delete("DELETE FROM label2dynamicanalysis WHERE dynamicanalysisid IN $dynids_prepare_array", $dynids); - } - - // Delete the note if not shared - DB::delete(" - DELETE FROM note WHERE id IN ( - SELECT f1.id - FROM ( - SELECT a.noteid AS id, COUNT(DISTINCT a.buildid) AS c - FROM build2note a - WHERE a.buildid IN $buildid_prepare_array - GROUP BY a.noteid - ) AS f1 - INNER JOIN ( - SELECT b.noteid AS id, COUNT(DISTINCT b.buildid) AS c - FROM build2note b - INNER JOIN ( - SELECT noteid - FROM build2note - WHERE buildid IN $buildid_prepare_array - ) AS d ON b.noteid = d.noteid - GROUP BY b.noteid - ) AS f2 ON (f1.id = f2.id) - WHERE f1.c = f2.c - ) - ", array_merge($buildids, $buildids)); - - // Delete the update if not shared - $build2update = DB::select(" - SELECT a.updateid - FROM build2update AS a - LEFT JOIN build2update AS b ON ( - a.updateid=b.updateid - AND b.buildid NOT IN $buildid_prepare_array - ) - WHERE a.buildid IN $buildid_prepare_array - GROUP BY a.updateid - HAVING count(b.updateid)=0 - ", array_merge($buildids, $buildids)); - - $updateids = []; - foreach ($build2update as $build2update_array) { - // Update is not shared we delete - $updateids[] = intval($build2update_array->updateid); - } - - if (count($updateids) > 0) { - $updateids_prepare_array = $db->createPreparedArray(count($updateids)); - DB::delete("DELETE FROM buildupdate WHERE id IN $updateids_prepare_array", $updateids); - DB::delete("DELETE FROM updatefile WHERE updateid IN $updateids_prepare_array", $updateids); - } - - // Delete tests and testoutputs that are not shared. - // First find all the tests and testoutputs from builds that are about to be deleted. - $b2t_result = DB::select(" - SELECT DISTINCT outputid - FROM build2test - WHERE buildid IN $buildid_prepare_array - ", $buildids); - - $all_outputids = []; - foreach ($b2t_result as $b2t_row) { - $all_outputids[] = intval($b2t_row->outputid); - } - - // Delete un-shared testoutput rows. - if (!empty($all_outputids)) { - // Next identify tests from this list that should be preserved - // because they are shared with builds that are not about to be deleted. - $all_outputids_prepare_array = $db->createPreparedArray(count($all_outputids)); - $save_test_result = DB::select(" - SELECT DISTINCT outputid - FROM build2test - WHERE - outputid IN $all_outputids_prepare_array - AND buildid NOT IN $buildid_prepare_array - ", array_merge($all_outputids, $buildids)); - $testoutputs_to_save = []; - foreach ($save_test_result as $save_test_row) { - $testoutputs_to_save[] = intval($save_test_row->outputid); - } - - // Use array_diff to get the list of tests that should be deleted. - $testoutputs_to_delete = array_diff($all_outputids, $testoutputs_to_save); - if (!empty($testoutputs_to_delete)) { - delete_rows_chunked('DELETE FROM testoutput WHERE id IN ', $testoutputs_to_delete); - - $testoutputs_to_delete_prepare_array = $db->createPreparedArray(count($testoutputs_to_delete)); - // Check if the images for the test are not shared - $test2image = DB::select(" - SELECT a.imgid - FROM test2image AS a - LEFT JOIN test2image AS b ON ( - a.imgid=b.imgid - AND b.outputid NOT IN $testoutputs_to_delete_prepare_array - ) - WHERE a.outputid IN $testoutputs_to_delete_prepare_array - GROUP BY a.imgid - HAVING count(b.imgid)=0 - ", array_merge($testoutputs_to_delete, $testoutputs_to_delete)); - - $imgids = []; - foreach ($test2image as $test2image_array) { - $imgids[] = intval($test2image_array->imgid); - } - - if (count($imgids) > 0) { - $imgids_prepare_array = $db->createPreparedArray(count($imgids)); - DB::delete("DELETE FROM image WHERE id IN $imgids_prepare_array", $imgids); - } - delete_rows_chunked('DELETE FROM test2image WHERE outputid IN ', $testoutputs_to_delete); - } - } - - // Delete the uploaded files if not shared - $build2uploadfiles = DB::select(" - SELECT a.fileid - FROM build2uploadfile AS a - LEFT JOIN build2uploadfile AS b ON ( - a.fileid=b.fileid - AND b.buildid NOT IN $buildid_prepare_array - ) - WHERE a.buildid IN $buildid_prepare_array - GROUP BY a.fileid - HAVING count(b.fileid)=0 - ", array_merge($buildids, $buildids)); - - $fileids = []; - foreach ($build2uploadfiles as $build2uploadfile_array) { - $fileid = intval($build2uploadfile_array->fileid); - $fileids[] = $fileid; - unlink_uploaded_file($fileid); - } - - if (count($fileids) > 0) { - $fileids_prepare_array = $db->createPreparedArray(count($fileids)); - DB::delete("DELETE FROM uploadfile WHERE id IN $fileids_prepare_array", $fileids); - DB::delete("DELETE FROM build2uploadfile WHERE fileid IN $fileids_prepare_array", $fileids); - } - - // Remove any children of these builds. - // In order to avoid making the list of builds to delete too large - // we delete them in batches (one batch per parent). - foreach ($buildids as $parentid) { - $child_result = DB::select('SELECT id FROM build WHERE parentid=?', [intval($parentid)]); - - $childids = []; - foreach ($child_result as $child_array) { - $childids[] = intval($child_array->id); - } - if (!empty($childids)) { - remove_build($childids); - } - } - - // Only delete the buildid at the end so that no other build can get it in the meantime - DB::delete("DELETE FROM build WHERE id IN $buildid_prepare_array", $buildids); - - add_last_sql_error('remove_build'); -} - -/** - * Call remove_build() in batches of 100. - */ -function remove_build_chunked($buildid): void -{ - if (!is_array($buildid)) { - remove_build($buildid); - } - foreach (array_chunk($buildid, 100) as $chunk) { - remove_build($chunk); - } -} - -/** - * Chunk up DELETE queries into batches of 100. - */ -function delete_rows_chunked(string $query, array $ids): void -{ - foreach (array_chunk($ids, 100) as $chunk) { - $chunk_prepared_array = Database::getInstance()->createPreparedArray(count($chunk)); - DB::delete("$query $chunk_prepared_array", $chunk); - // Sleep for a microsecond to give other processes a chance. - usleep(1); - } + DatabaseCleanupUtils::removeBuildChunked($buildids); } /** diff --git a/app/cdash/tests/test_bazeljson.php b/app/cdash/tests/test_bazeljson.php index 30b6de050c..1b3936d634 100644 --- a/app/cdash/tests/test_bazeljson.php +++ b/app/cdash/tests/test_bazeljson.php @@ -1,6 +1,7 @@ assertTrue($testdiff_stmt->fetchColumn() === false); // Cleanup. - remove_build($buildid); - remove_build($buildid2); + DatabaseCleanupUtils::removeBuild($buildid); + DatabaseCleanupUtils::removeBuild($buildid2); } public function testFilterBazelJSON() @@ -130,7 +131,7 @@ public function testFilterBazelJSON() } // Cleanup. - remove_build($buildid); + DatabaseCleanupUtils::removeBuild($buildid); $project->Delete(); } @@ -297,7 +298,7 @@ public function testBazelTestFailed() } // Cleanup. - remove_build($buildid); + DatabaseCleanupUtils::removeBuild($buildid); } public function testBazelTimeout() @@ -353,7 +354,7 @@ public function testBazelTimeout() } // Cleanup. - remove_build($buildid); + DatabaseCleanupUtils::removeBuild($buildid); } public function testBazelConfigure() @@ -389,7 +390,7 @@ public function testBazelConfigure() } // Cleanup. - remove_build($buildid); + DatabaseCleanupUtils::removeBuild($buildid); } public function testBazelDuplicateTests() @@ -425,7 +426,7 @@ public function testBazelDuplicateTests() } // Cleanup. - remove_build($buildid); + DatabaseCleanupUtils::removeBuild($buildid); } public function testMultipleLineError() @@ -470,7 +471,7 @@ public function testMultipleLineError() } // Cleanup. - remove_build($buildid); + DatabaseCleanupUtils::removeBuild($buildid); } public function testShardTest() @@ -526,7 +527,7 @@ public function testShardTest() } // Cleanup. - remove_build($buildid); + DatabaseCleanupUtils::removeBuild($buildid); } public function testShardTestFailures() @@ -622,7 +623,7 @@ public function testShardTestFailures() } // Cleanup. - remove_build($buildid); + DatabaseCleanupUtils::removeBuild($buildid); } public function testShardTestTimeout() @@ -709,7 +710,7 @@ public function testShardTestTimeout() } // Cleanup. - remove_build($buildid); + DatabaseCleanupUtils::removeBuild($buildid); } private function submit_data($project_name, $upload_type, $md5, $file_path, diff --git a/app/cdash/tests/test_branchcoverage.php b/app/cdash/tests/test_branchcoverage.php index 7e62ba47f0..7df6b563bb 100644 --- a/app/cdash/tests/test_branchcoverage.php +++ b/app/cdash/tests/test_branchcoverage.php @@ -5,8 +5,7 @@ // require_once dirname(__FILE__) . '/cdash_test_case.php'; - - +use App\Utils\DatabaseCleanupUtils; use CDash\Model\Build; use CDash\Model\PendingSubmissions; use Illuminate\Support\Facades\DB; @@ -35,7 +34,7 @@ protected function clearPriorBranchCoverageResults() SELECT id FROM build WHERE name = 'branch_coverage'"); $existing_buildid = $stmt->fetchColumn(); if ($existing_buildid !== false) { - remove_build($existing_buildid); + DatabaseCleanupUtils::removeBuild((int) $existing_buildid); } $files = Storage::allFiles('inbox'); diff --git a/app/cdash/tests/test_buildconfigure.php b/app/cdash/tests/test_buildconfigure.php index 50e3842d72..f472a4d775 100644 --- a/app/cdash/tests/test_buildconfigure.php +++ b/app/cdash/tests/test_buildconfigure.php @@ -5,9 +5,7 @@ // require_once dirname(__FILE__) . '/cdash_test_case.php'; - - - +use App\Utils\DatabaseCleanupUtils; use CDash\Database; use CDash\Model\Build; use CDash\Model\BuildConfigure; @@ -90,7 +88,7 @@ public function testBuildConfigureDiff() "SELECT id FROM build WHERE name = 'configure_warning_diff'"); $this->PDO->execute($stmt); while ($row = $stmt->fetch()) { - remove_build($row['id']); + DatabaseCleanupUtils::removeBuild($row['id']); } // Make two consecutive builds. diff --git a/app/cdash/tests/test_builddetails.php b/app/cdash/tests/test_builddetails.php index 3fafd1cb91..d6a2a41226 100644 --- a/app/cdash/tests/test_builddetails.php +++ b/app/cdash/tests/test_builddetails.php @@ -3,6 +3,7 @@ // After including cdash_test_case.php, subsequent require_once calls are // relative to the top of the CDash source tree // +use App\Utils\DatabaseCleanupUtils; use Illuminate\Support\Facades\DB; require_once dirname(__FILE__) . '/cdash_test_case.php'; @@ -41,7 +42,7 @@ public function __construct() public function __destruct() { foreach ($this->builds as $build) { - remove_build($build['id']); + DatabaseCleanupUtils::removeBuild($build['id']); } } @@ -125,7 +126,7 @@ public function testViewTestReturnsProperFormat() $this->assertEqual($actualResponse->numNotRun, $expectedResponse->numNotRun); $this->assertEqual($actualResponse->numTimeFailed, $expectedResponse->numTimeFailed); - remove_build($buildId->id); + DatabaseCleanupUtils::removeBuild($buildId->id); } public function testViewTestReturnsProperFormatForParentBuilds() @@ -147,6 +148,6 @@ public function testViewTestReturnsProperFormatForParentBuilds() $this->assertTrue($test->subprojectname == 'some-subproject'); } - remove_build($buildId->id); + DatabaseCleanupUtils::removeBuild($buildId->id); } } diff --git a/app/cdash/tests/test_buildfailuredetails.php b/app/cdash/tests/test_buildfailuredetails.php index 5a994fce9a..323dd42d54 100644 --- a/app/cdash/tests/test_buildfailuredetails.php +++ b/app/cdash/tests/test_buildfailuredetails.php @@ -3,6 +3,7 @@ // After including cdash_test_case.php, subsequent require_once calls are // relative to the top of the CDash source tree // +use App\Utils\DatabaseCleanupUtils; use Illuminate\Support\Facades\DB; require_once dirname(__FILE__) . '/cdash_test_case.php'; @@ -68,7 +69,7 @@ public function testBuildFailureDetails() } // Delete one of the builds. - remove_build($buildids[0]); + DatabaseCleanupUtils::removeBuild($buildids[0]); // Verify 2 buildfailures, 1 build, and 2 details. $count_results = DB::select($count_query)[0]; @@ -89,7 +90,7 @@ public function testBuildFailureDetails() } // Delete the other build. - remove_build($buildids[1]); + DatabaseCleanupUtils::removeBuild($buildids[1]); // Verify that the rest of our data is now gone. $count_results = DB::select($count_query)[0]; diff --git a/app/cdash/tests/test_buildgrouprule.php b/app/cdash/tests/test_buildgrouprule.php index 0af2c03a21..b46a20da42 100644 --- a/app/cdash/tests/test_buildgrouprule.php +++ b/app/cdash/tests/test_buildgrouprule.php @@ -6,6 +6,7 @@ require_once dirname(__FILE__) . '/cdash_test_case.php'; +use App\Utils\DatabaseCleanupUtils; use App\Utils\SubmissionUtils; use CDash\Database; use CDash\Model\Build; @@ -108,7 +109,7 @@ public function testOnlyExpireRulesFromSameProject() "SELECT id FROM build WHERE name = 'no-project-leakage'"); pdo_execute($stmt); while ($row = $stmt->fetch()) { - remove_build($row['id']); + DatabaseCleanupUtils::removeBuild($row['id']); } DB::delete("DELETE FROM build2grouprule WHERE buildname = 'no-project-leakage'"); diff --git a/app/cdash/tests/test_buildmodel.php b/app/cdash/tests/test_buildmodel.php index 59143817f9..2814786212 100644 --- a/app/cdash/tests/test_buildmodel.php +++ b/app/cdash/tests/test_buildmodel.php @@ -7,7 +7,7 @@ - +use App\Utils\DatabaseCleanupUtils; use CDash\Model\Build; use CDash\Model\BuildError; use Illuminate\Support\Facades\DB; @@ -63,7 +63,7 @@ public function __construct() public function __destruct() { foreach ($this->builds as $build) { - remove_build($build['id']); + DatabaseCleanupUtils::removeBuild($build['id']); } } @@ -322,6 +322,6 @@ public function testBuildModelAddBuild() $build2 = new Build(); $this->assertFalse($build2->AddBuild()); - remove_build($build->Id); + DatabaseCleanupUtils::removeBuild($build->Id); } } diff --git a/app/cdash/tests/test_buildrelationship.php b/app/cdash/tests/test_buildrelationship.php index 56d94ea822..aad402c142 100644 --- a/app/cdash/tests/test_buildrelationship.php +++ b/app/cdash/tests/test_buildrelationship.php @@ -6,6 +6,7 @@ require_once dirname(__FILE__) . '/cdash_test_case.php'; +use App\Utils\DatabaseCleanupUtils; use App\Utils\SubmissionUtils; use CDash\Database; use CDash\Model\Build; @@ -27,7 +28,7 @@ public function testBuildRelationships() "SELECT id FROM build WHERE name = 'test-build-relationships'"); pdo_execute($stmt); while ($row = $stmt->fetch()) { - remove_build($row['id']); + DatabaseCleanupUtils::removeBuild($row['id']); } // Login as admin. diff --git a/app/cdash/tests/test_deferredsubmissions.php b/app/cdash/tests/test_deferredsubmissions.php index 64c4359077..4a42b6c5ba 100644 --- a/app/cdash/tests/test_deferredsubmissions.php +++ b/app/cdash/tests/test_deferredsubmissions.php @@ -9,6 +9,7 @@ use App\Models\AuthToken; +use App\Utils\DatabaseCleanupUtils; use CDash\Model\Project; class DeferredSubmissionsTestCase extends BranchCoverageTestCase @@ -86,7 +87,7 @@ private function prepareForNormalSubmission() ->where('name', '=', 'deferred_submission') ->first(); if ($existing_build_row) { - remove_build($existing_build_row->id); + DatabaseCleanupUtils::removeBuild($existing_build_row->id); } // Make sure inbox is empty. diff --git a/app/cdash/tests/test_disabledtests.php b/app/cdash/tests/test_disabledtests.php index 4aba1a22c1..fa1decdc01 100644 --- a/app/cdash/tests/test_disabledtests.php +++ b/app/cdash/tests/test_disabledtests.php @@ -5,6 +5,7 @@ // require_once dirname(__FILE__) . '/cdash_test_case.php'; +use App\Utils\DatabaseCleanupUtils; use CDash\Database; class DisabledTestsTestCase extends KWWebTestCase @@ -71,6 +72,6 @@ public function testDisabledTests() $this->fail("Erroneous email sent for test 'ThisTestIsDisabled'"); } - remove_build($buildid); + DatabaseCleanupUtils::removeBuild($buildid); } } diff --git a/app/cdash/tests/test_donehandler.php b/app/cdash/tests/test_donehandler.php index d1c11b1c01..ac3387b0fa 100644 --- a/app/cdash/tests/test_donehandler.php +++ b/app/cdash/tests/test_donehandler.php @@ -4,9 +4,10 @@ require_once 'include/ctestparser.php'; +use App\Models\Site; +use App\Utils\DatabaseCleanupUtils; use CDash\Model\Build; use CDash\Model\PendingSubmissions; -use App\Models\Site; use Illuminate\Support\Facades\Artisan; use Illuminate\Support\Facades\Storage; @@ -106,6 +107,6 @@ private function performTest($remote = false) $this->assertTrue(strpos($contents, "Done retries=\"5\"") !== false); unlink($tmpfname); - remove_build($build->Id); + DatabaseCleanupUtils::removeBuild($build->Id); } } diff --git a/app/cdash/tests/test_dynamicanalysissummary.php b/app/cdash/tests/test_dynamicanalysissummary.php index 020bec6c14..b71c9ed7b7 100644 --- a/app/cdash/tests/test_dynamicanalysissummary.php +++ b/app/cdash/tests/test_dynamicanalysissummary.php @@ -15,6 +15,7 @@ =========================================================================*/ +use App\Utils\DatabaseCleanupUtils; use Illuminate\Support\Facades\DB; require_once dirname(__FILE__) . '/cdash_test_case.php'; @@ -68,7 +69,7 @@ public function testSubProjectDynamicAnalysisSummary() public function testDynamicAnalysisSummaryGetsDeleted() { // Remove the builds we just created. - remove_build($this->ParentId); + DatabaseCleanupUtils::removeBuild($this->ParentId); // Verify that the dynamicanalysisssummary rows got deleted. $result = DB::select(" diff --git a/app/cdash/tests/test_externallinksfromtests.php b/app/cdash/tests/test_externallinksfromtests.php index 300dccff62..03197ec0aa 100644 --- a/app/cdash/tests/test_externallinksfromtests.php +++ b/app/cdash/tests/test_externallinksfromtests.php @@ -3,6 +3,7 @@ // After including cdash_test_case.php, subsequent require_once calls are // relative to the top of the CDash source tree // +use App\Utils\DatabaseCleanupUtils; use Illuminate\Support\Facades\DB; require_once dirname(__FILE__) . '/cdash_test_case.php'; @@ -60,7 +61,7 @@ public function testExternalLinksFromTests() } // Delete the build that we created during this test. - remove_build($buildid); + DatabaseCleanupUtils::removeBuild($buildid); if (!$success) { $this->fail($error_msg); diff --git a/app/cdash/tests/test_filterbuilderrors.php b/app/cdash/tests/test_filterbuilderrors.php index 1f8e9164d8..721790649b 100644 --- a/app/cdash/tests/test_filterbuilderrors.php +++ b/app/cdash/tests/test_filterbuilderrors.php @@ -5,6 +5,7 @@ // require_once dirname(__FILE__) . '/cdash_test_case.php'; +use App\Utils\DatabaseCleanupUtils; use CDash\Database; use CDash\Model\Project; @@ -71,7 +72,7 @@ public function testFilterBuildErrors() } // Cleanup. - remove_build($buildid); + DatabaseCleanupUtils::removeBuild($buildid); $project->Delete(); } } diff --git a/app/cdash/tests/test_filtertestlabels.php b/app/cdash/tests/test_filtertestlabels.php index cc3aedd67d..9e4570905a 100644 --- a/app/cdash/tests/test_filtertestlabels.php +++ b/app/cdash/tests/test_filtertestlabels.php @@ -5,7 +5,7 @@ // require_once dirname(__FILE__) . '/cdash_test_case.php'; - +use App\Utils\DatabaseCleanupUtils; class FilterTestLabelsTestCase extends KWWebTestCase { @@ -41,7 +41,7 @@ public function testFilterLabels() if (count($buildids) != 1) { foreach ($buildids as $id) { - remove_build($id); + DatabaseCleanupUtils::removeBuild($id); } $this->fail('Expected 1 build, found ' . count($buildids)); return 1; @@ -88,7 +88,7 @@ public function testFilterLabels() } // Delete the build - remove_build($buildid); + DatabaseCleanupUtils::removeBuild($buildid); // Turn the option back off. pdo_query("UPDATE project SET sharelabelfilters=0 diff --git a/app/cdash/tests/test_hidecolumns.php b/app/cdash/tests/test_hidecolumns.php index abf594db52..3b5a64a5db 100644 --- a/app/cdash/tests/test_hidecolumns.php +++ b/app/cdash/tests/test_hidecolumns.php @@ -3,6 +3,7 @@ // After including cdash_test_case.php, subsequent require_once calls are // relative to the top of the CDash source tree // +use App\Utils\DatabaseCleanupUtils; use Illuminate\Support\Facades\DB; require_once dirname(__FILE__) . '/cdash_test_case.php'; @@ -95,7 +96,7 @@ public function onlyColumn($method) $buildid_results = DB::select( "SELECT id FROM build WHERE name='HideColumns'")[0]; $buildid = $buildid_results->id; - remove_build($buildid); + DatabaseCleanupUtils::removeBuild($buildid); return $retval; } } diff --git a/app/cdash/tests/test_imagecomparison.php b/app/cdash/tests/test_imagecomparison.php index 71602c3aed..3a81d1e325 100644 --- a/app/cdash/tests/test_imagecomparison.php +++ b/app/cdash/tests/test_imagecomparison.php @@ -5,6 +5,7 @@ // require_once dirname(__FILE__) . '/cdash_test_case.php'; +use App\Utils\DatabaseCleanupUtils; use CDash\Database; use CDash\Model\Image; @@ -54,6 +55,6 @@ public function testImageComparison() } } - remove_build($buildid); + DatabaseCleanupUtils::removeBuild($buildid); } } diff --git a/app/cdash/tests/test_managemeasurements.php b/app/cdash/tests/test_managemeasurements.php index 247c57bebc..95b256ebcb 100644 --- a/app/cdash/tests/test_managemeasurements.php +++ b/app/cdash/tests/test_managemeasurements.php @@ -7,6 +7,7 @@ require_once dirname(__FILE__) . '/cdash_test_case.php'; use App\Models\Measurement; +use App\Utils\DatabaseCleanupUtils; class ManageMeasurementsTestCase extends KWWebTestCase { @@ -31,10 +32,10 @@ public function __construct() public function __destruct() { if (!is_null($this->BuildId)) { - remove_build($this->BuildId); + DatabaseCleanupUtils::removeBuild($this->BuildId); } if (!is_null($this->SubProjectBuildId)) { - remove_build($this->SubProjectBuildId); + DatabaseCleanupUtils::removeBuild($this->SubProjectBuildId); } Measurement::destroy($this->MeasurementIds); diff --git a/app/cdash/tests/test_multicoverage.php b/app/cdash/tests/test_multicoverage.php index ecc3266145..a9296dc0f3 100644 --- a/app/cdash/tests/test_multicoverage.php +++ b/app/cdash/tests/test_multicoverage.php @@ -5,7 +5,7 @@ // require_once dirname(__FILE__) . '/cdash_test_case.php'; - +use App\Utils\DatabaseCleanupUtils; class MultiCoverageTestCase extends KWWebTestCase { @@ -30,7 +30,7 @@ public function testXMLFirst() $this->pass("Passed"); } - remove_build($this->BuildId); + DatabaseCleanupUtils::removeBuild($this->BuildId); return $success; } @@ -47,7 +47,7 @@ public function testTarFirst() $this->pass("Passed"); } - remove_build($this->BuildId); + DatabaseCleanupUtils::removeBuild($this->BuildId); return $success; } diff --git a/app/cdash/tests/test_multiplesubprojects.php b/app/cdash/tests/test_multiplesubprojects.php index f229eeb7df..9cb752f2eb 100644 --- a/app/cdash/tests/test_multiplesubprojects.php +++ b/app/cdash/tests/test_multiplesubprojects.php @@ -5,6 +5,7 @@ // require_once dirname(__FILE__) . '/cdash_test_case.php'; +use App\Utils\DatabaseCleanupUtils; use CDash\Database; class MultipleSubprojectsTestCase extends KWWebTestCase @@ -122,7 +123,7 @@ private function submitBuild() if ($total_builds != 5) { // parent + 4 subprojects foreach ($this->buildIds as $id) { - remove_build($id); + DatabaseCleanupUtils::removeBuild($id); } $this->fail("Expected 5 Builds found {$total_builds}"); return 1; @@ -131,7 +132,7 @@ private function submitBuild() private function restoreState() { - remove_build($this->buildIds); + DatabaseCleanupUtils::removeBuild($this->buildIds); $this->restoreEmailPreference(); diff --git a/app/cdash/tests/test_nobackup.php b/app/cdash/tests/test_nobackup.php index 9c73419dd2..b288ea4da0 100644 --- a/app/cdash/tests/test_nobackup.php +++ b/app/cdash/tests/test_nobackup.php @@ -5,6 +5,7 @@ // require_once dirname(__FILE__) . '/cdash_test_case.php'; +use App\Utils\DatabaseCleanupUtils; use CDash\Database; class NoBackupTestCase extends KWWebTestCase @@ -86,6 +87,6 @@ public function testNoBackup() $this->checkLog($this->logfilename); - remove_build($buildid); + DatabaseCleanupUtils::removeBuild((int) $buildid); } } diff --git a/app/cdash/tests/test_opencovercoverage.php b/app/cdash/tests/test_opencovercoverage.php index 123c25e06a..d14d1a5e26 100644 --- a/app/cdash/tests/test_opencovercoverage.php +++ b/app/cdash/tests/test_opencovercoverage.php @@ -5,7 +5,7 @@ // require_once(dirname(__FILE__).'/cdash_test_case.php'); - +use App\Utils\DatabaseCleanupUtils; class OpenCoverCoverageTestCase extends KWWebTestCase { @@ -17,7 +17,7 @@ public function __construct() } public function tearDown() { - remove_build($this->buildId); + DatabaseCleanupUtils::removeBuild($this->buildId); } public function testOpenCoverCoverage() { diff --git a/app/cdash/tests/test_parallelsubmissions.php b/app/cdash/tests/test_parallelsubmissions.php index f273bfebf0..e87639ebdb 100644 --- a/app/cdash/tests/test_parallelsubmissions.php +++ b/app/cdash/tests/test_parallelsubmissions.php @@ -8,7 +8,7 @@ require_once 'tests/trilinos_submission_test.php'; - +use App\Utils\DatabaseCleanupUtils; use CDash\Model\Project; class ParallelSubmissionsTestCase extends TrilinosSubmissionTestCase @@ -47,7 +47,7 @@ public function testParallelSubmissions() ->whereBetween('starttime', ['2011-07-22 00:00:00', '2011-07-22 23:59:59']) ->first(); if ($trilinos_build_row) { - remove_build($trilinos_build_row->id); + DatabaseCleanupUtils::removeBuild($trilinos_build_row->id); } // Change CDash config to queue submissions in the database. diff --git a/app/cdash/tests/test_removebuilds.php b/app/cdash/tests/test_removebuilds.php index 83a5f74d59..314b022932 100644 --- a/app/cdash/tests/test_removebuilds.php +++ b/app/cdash/tests/test_removebuilds.php @@ -6,6 +6,7 @@ require_once dirname(__FILE__) . '/cdash_test_case.php'; use App\Models\TestMeasurement; +use App\Utils\DatabaseCleanupUtils; use App\Utils\TestCreator; use App\Utils\NoteCreator; @@ -429,7 +430,7 @@ public function testBuildRemovalWorksAsExpected() return; // Remove the build. - remove_build($build->Id); + DatabaseCleanupUtils::removeBuild($build->Id); // Check that everything was deleted properly. $this->verify('build', 'id', '=', $build->Id, 0, true); diff --git a/app/cdash/tests/test_replacebuild.php b/app/cdash/tests/test_replacebuild.php index b79810916e..798e0afabd 100644 --- a/app/cdash/tests/test_replacebuild.php +++ b/app/cdash/tests/test_replacebuild.php @@ -3,6 +3,7 @@ // After including cdash_test_case.php, subsequent require_once calls are // relative to the top of the CDash source tree // +use App\Utils\DatabaseCleanupUtils; use Illuminate\Support\Facades\DB; require_once dirname(__FILE__) . '/cdash_test_case.php'; @@ -62,7 +63,7 @@ public function testReplaceBuild() $error_msg = "Expected 0 rows, found $num_rows"; echo "$error_msg\n"; $success = false; - remove_build($first_buildid); + DatabaseCleanupUtils::removeBuild($first_buildid); } // Verify the replacement build. @@ -76,7 +77,7 @@ public function testReplaceBuild() } // Delete the build that we created during this test. - remove_build($second_buildid); + DatabaseCleanupUtils::removeBuild($second_buildid); if ($success) { $this->pass('Test passed'); diff --git a/app/cdash/tests/test_submission_assign_buildid.php b/app/cdash/tests/test_submission_assign_buildid.php index d92e9e000a..32de80684c 100644 --- a/app/cdash/tests/test_submission_assign_buildid.php +++ b/app/cdash/tests/test_submission_assign_buildid.php @@ -2,6 +2,7 @@ require_once dirname(__FILE__) . '/cdash_test_case.php'; +use App\Utils\DatabaseCleanupUtils; use CDash\Model\Build; class SubmissionAssignBuildIdTestCase extends KWWebTestCase @@ -37,6 +38,6 @@ public function testSubmissionAssignBuildId() $this->assertEqual('gcc', $build->CompilerName); $this->assertEqual('5.5.0', $build->CompilerVersion); - remove_build($buildid); + DatabaseCleanupUtils::removeBuild($buildid); } } diff --git a/app/cdash/tests/test_subprojectnextprevious.php b/app/cdash/tests/test_subprojectnextprevious.php index 528cb29066..b1ba02b68a 100644 --- a/app/cdash/tests/test_subprojectnextprevious.php +++ b/app/cdash/tests/test_subprojectnextprevious.php @@ -3,6 +3,7 @@ // After including cdash_test_case.php, subsequent require_once calls are // relative to the top of the CDash source tree // +use App\Utils\DatabaseCleanupUtils; use Illuminate\Support\Facades\DB; require_once dirname(__FILE__) . '/cdash_test_case.php'; @@ -323,8 +324,8 @@ public function testSubProjectNextPrevious() } // Delete the builds that we created during this test. - remove_build($second_parentid); - remove_build($third_parentid); + DatabaseCleanupUtils::removeBuild($second_parentid); + DatabaseCleanupUtils::removeBuild($third_parentid); if (!$success) { $this->fail($error_msg); diff --git a/app/cdash/tests/test_truncateoutput.php b/app/cdash/tests/test_truncateoutput.php index a1306f6ec8..bedaa5c8e5 100644 --- a/app/cdash/tests/test_truncateoutput.php +++ b/app/cdash/tests/test_truncateoutput.php @@ -3,6 +3,7 @@ // After including cdash_test_case.php, subsequent require_once calls are // relative to the top of the CDash source tree // +use App\Utils\DatabaseCleanupUtils; use Illuminate\Support\Facades\DB; require_once dirname(__FILE__).'/cdash_test_case.php'; @@ -102,7 +103,7 @@ public function testTruncateOutput() private function removeBuild() { if ($this->BuildId > 0) { - remove_build($this->BuildId); + DatabaseCleanupUtils::removeBuild($this->BuildId); $this->BuildId = 0; } } diff --git a/app/cdash/tests/test_unparsedsubmissionshonorbuildid.php b/app/cdash/tests/test_unparsedsubmissionshonorbuildid.php index b0b2f412d7..bfaa848b35 100644 --- a/app/cdash/tests/test_unparsedsubmissionshonorbuildid.php +++ b/app/cdash/tests/test_unparsedsubmissionshonorbuildid.php @@ -6,6 +6,8 @@ require_once dirname(__FILE__) . '/cdash_test_case.php'; require_once 'tests/test_branchcoverage.php'; +use App\Utils\DatabaseCleanupUtils; + class UnparsedSubmissionsHonorBuildIdTestCase extends BranchCoverageTestCase { protected $projectname; @@ -38,6 +40,6 @@ public function testBranchCoverage(): void $this->verifyResults(); DB::delete("DELETE FROM buildfile WHERE buildid='{$old_buildid}'"); - remove_build($old_buildid); + DatabaseCleanupUtils::removeBuild($old_buildid); } } diff --git a/app/cdash/tests/test_updateappend.php b/app/cdash/tests/test_updateappend.php index 0942d503d3..f4cf07a97e 100644 --- a/app/cdash/tests/test_updateappend.php +++ b/app/cdash/tests/test_updateappend.php @@ -5,7 +5,7 @@ // require_once dirname(__FILE__) . '/cdash_test_case.php'; - +use App\Utils\DatabaseCleanupUtils; class UppdateAppendTestCase extends KWWebTestCase { @@ -46,7 +46,7 @@ public function testUpdateAppend() if (count($buildids) != 1) { foreach ($buildids as $id) { - remove_build($id); + DatabaseCleanupUtils::removeBuild($id); } $this->fail('Expected 1 build, found ' . count($buildids)); return 1; @@ -114,7 +114,7 @@ public function testUpdateAppend() } // Delete the build - remove_build($buildid); + DatabaseCleanupUtils::removeBuild($buildid); if ($success) { $this->pass('Test passed'); diff --git a/app/cdash/tests/test_updateonlyuserstats.php b/app/cdash/tests/test_updateonlyuserstats.php index ef6b6f21c8..6c53b9b535 100644 --- a/app/cdash/tests/test_updateonlyuserstats.php +++ b/app/cdash/tests/test_updateonlyuserstats.php @@ -17,6 +17,7 @@ use CDash\Database; use App\Models\User; +use App\Utils\DatabaseCleanupUtils; use CDash\Model\UserProject; class UpdateOnlyUserStatsTestCase extends KWWebTestCase @@ -162,7 +163,7 @@ public function testCleanup() "SELECT id FROM build WHERE name='GithubUserStats'"); $stmt->execute(); while ($row = $stmt->fetch()) { - remove_build($row['id']); + DatabaseCleanupUtils::removeBuild($row['id']); } // Delete project. diff --git a/app/cdash/tests/test_viewdynamicanalysisfile.php b/app/cdash/tests/test_viewdynamicanalysisfile.php index 1834a7f525..3a84e90157 100644 --- a/app/cdash/tests/test_viewdynamicanalysisfile.php +++ b/app/cdash/tests/test_viewdynamicanalysisfile.php @@ -5,6 +5,7 @@ // require_once dirname(__FILE__) . '/cdash_test_case.php'; +use App\Utils\DatabaseCleanupUtils; use CDash\Model\Build; use CDash\Model\DynamicAnalysis; use CDash\Database; @@ -86,7 +87,7 @@ public function testNextPrevious() pdo_execute($stmt, [$id_to_delete]); $row = $stmt->fetch(); $buildid = $row['buildid']; - remove_build($buildid); + DatabaseCleanupUtils::removeBuild($buildid); } } } diff --git a/phpstan-baseline.neon b/phpstan-baseline.neon index 1f9b2963bf..c284cda5bc 100644 --- a/phpstan-baseline.neon +++ b/phpstan-baseline.neon @@ -3943,6 +3943,19 @@ parameters: count: 1 path: app/Utils/AuthTokenUtil.php + - + message: """ + #^Call to deprecated function add_last_sql_error\\(\\)\\: + 04/22/2023$# + """ + count: 1 + path: app/Utils/DatabaseCleanupUtils.php + + - + message: "#^Construct empty\\(\\) is not allowed\\. Use more strict comparison\\.$#" + count: 3 + path: app/Utils/DatabaseCleanupUtils.php + - message: "#^Dynamic call to static method Illuminate\\\\Database\\\\Eloquent\\\\Builder\\\\:\\:limit\\(\\)\\.$#" count: 1 @@ -3953,6 +3966,26 @@ parameters: count: 1 path: app/Utils/DatabaseCleanupUtils.php + - + message: "#^Method App\\\\Utils\\\\DatabaseCleanupUtils\\:\\:deleteRowsChunked\\(\\) has parameter \\$ids with no value type specified in iterable type array\\.$#" + count: 1 + path: app/Utils/DatabaseCleanupUtils.php + + - + message: "#^Parameter \\#1 \\$array of function array_chunk expects array, array\\\\|int given\\.$#" + count: 1 + path: app/Utils/DatabaseCleanupUtils.php + + - + message: "#^Parameter \\#1 \\$buildids of static method App\\\\Utils\\\\DatabaseCleanupUtils\\:\\:removeBuildChunked\\(\\) expects array\\\\|int, array given\\.$#" + count: 1 + path: app/Utils/DatabaseCleanupUtils.php + + - + message: "#^Undefined variable\\: \\$buildid$#" + count: 1 + path: app/Utils/DatabaseCleanupUtils.php + - message: """ #^Call to deprecated function pdo_real_escape_string\\(\\)\\: @@ -13885,14 +13918,6 @@ parameters: count: 1 path: app/cdash/include/common.php - - - message: """ - #^Call to deprecated function add_last_sql_error\\(\\)\\: - 04/22/2023$# - """ - count: 1 - path: app/cdash/include/common.php - - message: """ #^Call to deprecated function add_log\\(\\)\\: @@ -14030,7 +14055,7 @@ parameters: - message: "#^Construct empty\\(\\) is not allowed\\. Use more strict comparison\\.$#" - count: 5 + count: 2 path: app/cdash/include/common.php - @@ -14118,11 +14143,6 @@ parameters: count: 1 path: app/cdash/include/common.php - - - message: "#^Function delete_rows_chunked\\(\\) has parameter \\$ids with no value type specified in iterable type array\\.$#" - count: 1 - path: app/cdash/include/common.php - - message: "#^Function generate_XSLT\\(\\) has parameter \\$xml with no type specified\\.$#" count: 1 @@ -14263,21 +14283,6 @@ parameters: count: 1 path: app/cdash/include/common.php - - - message: "#^Function remove_build\\(\\) has no return type specified\\.$#" - count: 1 - path: app/cdash/include/common.php - - - - message: "#^Function remove_build\\(\\) has parameter \\$buildid with no type specified\\.$#" - count: 1 - path: app/cdash/include/common.php - - - - message: "#^Function remove_build_chunked\\(\\) has parameter \\$buildid with no type specified\\.$#" - count: 1 - path: app/cdash/include/common.php - - message: "#^Function remove_project_builds\\(\\) has parameter \\$projectid with no type specified\\.$#" count: 1 @@ -21816,6 +21821,11 @@ parameters: count: 1 path: app/cdash/tests/test_buildconfigure.php + - + message: "#^Parameter \\#1 \\$buildid of static method App\\\\Utils\\\\DatabaseCleanupUtils\\:\\:removeBuild\\(\\) expects array\\\\|int, mixed given\\.$#" + count: 1 + path: app/cdash/tests/test_buildconfigure.php + - message: "#^Parameter \\#1 \\$haystack of function strpos expects string, string\\|false given\\.$#" count: 2 @@ -23326,6 +23336,11 @@ parameters: count: 1 path: app/cdash/tests/test_disabledtests.php + - + message: "#^Parameter \\#1 \\$buildid of static method App\\\\Utils\\\\DatabaseCleanupUtils\\:\\:removeBuild\\(\\) expects array\\\\|int, mixed given\\.$#" + count: 1 + path: app/cdash/tests/test_disabledtests.php + - message: "#^Parameter \\#1 \\$haystack of function strpos expects string, string\\|false given\\.$#" count: 2 @@ -24402,6 +24417,11 @@ parameters: count: 1 path: app/cdash/tests/test_imagecomparison.php + - + message: "#^Parameter \\#1 \\$buildid of static method App\\\\Utils\\\\DatabaseCleanupUtils\\:\\:removeBuild\\(\\) expects array\\\\|int, mixed given\\.$#" + count: 1 + path: app/cdash/tests/test_imagecomparison.php + - message: "#^Part \\$imgid \\(mixed\\) of encapsed string cannot be cast to string\\.$#" count: 1 @@ -25661,6 +25681,11 @@ parameters: count: 7 path: app/cdash/tests/test_multiplesubprojects.php + - + message: "#^Parameter \\#1 \\$buildid of static method App\\\\Utils\\\\DatabaseCleanupUtils\\:\\:removeBuild\\(\\) expects array\\\\|int, mixed given\\.$#" + count: 1 + path: app/cdash/tests/test_multiplesubprojects.php + - message: "#^Parameter \\#1 \\$haystack of function strpos expects string, int\\|string\\|false\\|null given\\.$#" count: 1 @@ -28562,6 +28587,11 @@ parameters: count: 1 path: app/cdash/tests/test_updateonlyuserstats.php + - + message: "#^Parameter \\#1 \\$buildid of static method App\\\\Utils\\\\DatabaseCleanupUtils\\:\\:removeBuild\\(\\) expects array\\\\|int, mixed given\\.$#" + count: 1 + path: app/cdash/tests/test_updateonlyuserstats.php + - message: "#^Parameter \\#1 \\$key of function array_key_exists expects int\\|string, mixed given\\.$#" count: 1 @@ -28783,6 +28813,11 @@ parameters: count: 1 path: app/cdash/tests/test_viewdynamicanalysisfile.php + - + message: "#^Parameter \\#1 \\$buildid of static method App\\\\Utils\\\\DatabaseCleanupUtils\\:\\:removeBuild\\(\\) expects array\\\\|int, mixed given\\.$#" + count: 1 + path: app/cdash/tests/test_viewdynamicanalysisfile.php + - message: "#^Parameter \\#1 \\$object_or_class of function property_exists expects object\\|string, mixed given\\.$#" count: 1