Skip to content

fix: ensure teams primary key exists before adding foreign key#196

Merged
ManukMinasyan merged 1 commit intomainfrom
hotfix/teams-primary-key-constraint
Mar 29, 2026
Merged

fix: ensure teams primary key exists before adding foreign key#196
ManukMinasyan merged 1 commit intomainfrom
hotfix/teams-primary-key-constraint

Conversation

@ManukMinasyan
Copy link
Copy Markdown
Contributor

The ULID migration can leave teams.id without a primary key on PostgreSQL. Add a pre-check that restores the constraint before creating the foreign key on personal_access_tokens.

The ULID migration can leave teams.id without a primary key on
PostgreSQL. Add a pre-check that restores the constraint before
creating the foreign key on personal_access_tokens.
Copilot AI review requested due to automatic review settings March 29, 2026 09:40
@ManukMinasyan ManukMinasyan merged commit 08be628 into main Mar 29, 2026
10 checks passed
Copy link
Copy Markdown

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Adds a PostgreSQL-specific pre-check in the personal_access_tokens.team_id migration to repair a missing teams.id primary key before creating the foreign key constraint, preventing failures after the ULID migration sequence.

Changes:

  • Adds a ensureTeamsPrimaryKey() pre-check executed before adding the team_id foreign key.
  • Uses a pg_constraint lookup to detect whether teams has a primary key, and re-adds one on id if missing.

Comment on lines +31 to +35
$hasPrimary = DB::selectOne(
"SELECT 1 FROM pg_constraint WHERE conrelid = 'teams'::regclass AND contype = 'p'"
);

if (! $hasPrimary) {
Copy link

Copilot AI Mar 29, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The pre-check only verifies that the teams table has some primary key (contype = 'p'), but the foreign key requires that the referenced column (teams.id) is unique/primary. As written, this can still fail if teams has a primary key on a different column, and it can also add a redundant primary key/index when teams.id is already covered by a unique constraint. Consider checking specifically for a primary/unique constraint that includes the id column (e.g., via pg_index/pg_attribute), and only adding a constraint when teams.id is not already unique.

Suggested change
$hasPrimary = DB::selectOne(
"SELECT 1 FROM pg_constraint WHERE conrelid = 'teams'::regclass AND contype = 'p'"
);
if (! $hasPrimary) {
$idIsUnique = DB::selectOne("
SELECT 1
FROM pg_index i
JOIN pg_class c ON c.oid = i.indrelid
JOIN pg_attribute a ON a.attrelid = c.oid AND a.attnum = ANY(i.indkey)
WHERE c.relname = 'teams'
AND i.indisunique
AND i.indnatts = 1
AND a.attname = 'id'
LIMIT 1
");
if (! $idIsUnique) {

Copilot uses AI. Check for mistakes.
Comment on lines +31 to +35
$hasPrimary = DB::selectOne(
"SELECT 1 FROM pg_constraint WHERE conrelid = 'teams'::regclass AND contype = 'p'"
);

if (! $hasPrimary) {
Copy link

Copilot AI Mar 29, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

DB::selectOne() returns an object or null, but $hasPrimary is treated as a boolean. For clarity (and to avoid surprising truthiness), consider renaming to something like $primaryConstraintExists and using an explicit null check (e.g., === null) rather than if (! $hasPrimary).

Suggested change
$hasPrimary = DB::selectOne(
"SELECT 1 FROM pg_constraint WHERE conrelid = 'teams'::regclass AND contype = 'p'"
);
if (! $hasPrimary) {
$primaryConstraintExists = DB::selectOne(
"SELECT 1 FROM pg_constraint WHERE conrelid = 'teams'::regclass AND contype = 'p'"
);
if ($primaryConstraintExists === null) {

Copilot uses AI. Check for mistakes.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants