Bugfix Issue 834 Schema Finalize Blocked - sebiboga/testlink-upgraded GitHub Wiki
Issue #834 — Finalize builds schema: drop testplan_id + swap unique key (blocked)
Child tracking sub-task of enhancement #503 ("builds scoped to the Test Project").
Status: OPEN — destructive drop blocked by un-migrated readers
Issue #834 asks to finalize the builds schema:
- Replace
UNIQUE KEY (testplan_id, name)withUNIQUE KEY (testproject_id, name). - Drop
builds.testplan_id.
The issue's own precondition is "After all readers are migrated (sub-tasks #826-#832)".
That precondition is not yet met, so the drop must not be forced. Attempting it would
break several live builds.testplan_id readers at runtime.
Approach (the HOW)
- Investigate before touching code — reproduce the state on a freshly imported DB,
enumerate every reader of
builds.testplan_id, and check whether the #826-#832 reader migration actually completed. - Quantify the blast radius rather than assume "ready to drop".
- Refrain from a partial, risky migration — the rework spans many SQL sites whose correct project-scoped form is non-trivial (builds are now shared across a project's plans), and doing it half-way would leave a broken build surface. Documented findings instead; the issue stays open for the modernize flow / a larger follow-up.
Measured evidence
Live schema (MariaDB 127.0.0.1 testlink) — testplan_id still present, unique key
still (testplan_id, name):
id, testproject_id (NOT NULL DEFAULT 0), testplan_id (NOT NULL DEFAULT 0), name, …
UNIQUE KEY `name` (testplan_id, name)
KEY testplan_id (testplan_id); KEY testproject_id (testproject_id)
builds is currently empty (count(*) = 0), so the #827 duplicate-merge has nothing to
conflict on today.
Un-migrated builds.testplan_id readers (would break on drop)
| Location | Query / use |
|---|---|
lib/functions/testplan.class.php:4154 (+ 4427, 4473, 4514, 4567, 4630, 4743, 4828, 4916, 5015, 5061, 5361, 5435, 5583, 5678) |
JOIN builds B ON B.testplan_id = TPTCV.testplan_id — per-build execution assignment / reporting (15 sites) |
lib/functions/tlTestPlanMetrics.class.php:2432, 2478, 2567, 2616 |
Not-Run / metrics joins builds to testplan_tcversions by plan id |
lib/functions/testplan.class.php:2024 |
DELETE FROM builds WHERE testplan_id={$id} |
lib/functions/testplan.class.php:7298 |
SELECT … FROM builds WHERE testplan_id={$id} (build max-id lookup) |
lib/api/rest/v2/tlRestApi.class.php:1308 |
$build['testplan_id'] → permission context in updateBuild |
lib/api/rest/v3/RestApi.class.php:710 |
same |
lib/plan/buildCopyExecTaskAssignment.php:95 |
defensive isset($bi['testplan_id']) (only already-defensive site) |
Sub-task #832 (execution page build selection → project builds) is also still OPEN
(gh issue view 832). The execution-page selector already routes through the
project-scoped get_builds_for_html_options() (execSetResults.php:1566 / execDashboard.php:208),
but the per-build reporting/metrics joins and the plan-scoped delete/read above remain.
Root cause chain
- #503 scoped builds to the Test Project;
builds.testproject_idadded in #826. builds.testplan_idretained as dual-write during migration (seedocs/Bugfix-Issue-831-Build-UI-Project-Scope-Verification.md: "dual-write until #834 drops it").- The reporting/metrics/delete readers that JOIN
builds.testplan_idwere never converted — so the "all readers migrated" precondition is unmet.
Recommended fix path (future run)
- Convert metric/assignment joins to project scope: join
testplans TP ON TP.id = TPTCV.testplan_idthenB ON B.testproject_id = TP.testproject_id(plusB.id IN (project-builds)predicate), orB ON B.id = UA.build_idwhereuser_assignmentsalready carriesbuild_id. - Rework
testplan.class.php:2024/7298delete/read to project scope viagetProjectIdOfPlan($id). - Rework REST v2/v3
updateBuildpermission context off$build['testplan_id']. - Run
tmp/fixtures_827.phpduplicate-merge, thenALTER TABLE builds DROP COLUMN testplan_idand recreateUNIQUE KEY (testproject_id, name), re-run full regression.
Conclusion
This is an architecture-grade migration, not a single-line defect, and its prerequisite in the issue body is not satisfied. Per the fix rulebook the destructive drop is not forced; findings are documented and the issue remains OPEN for the modernize flow.
Files
| File | Purpose |
|---|---|
docs/Bugfix-Issue-834-Schema-Finalize-Blocked.md |
This analysis |