Visitar URL original
fix: silence plpgsql_check false positives in list/search functions by TylerHillery · Pull Request #1485 · supabase/storage · GitHub
Skip to content

fix: silence plpgsql_check false positives in list/search functions - #1485

Open
TylerHillery wants to merge 1 commit into
masterfrom
tyler/fix/storage-db-lint
Open

TylerHillery wants to merge 1 commit into
masterfrom
tyler/fix/storage-db-lint

Conversation

@TylerHillery

Copy link
Copy Markdown
Contributor

What kind of change does this PR introduce?

fixes #1468

What is the current behavior?

supabase db lint which uses plpgsql_check was reporting the following errors

warning storage.list_objects_with_delimiter(text,text,text,integer,text,text,text,text,text,timestamp with time zone,text) line 552: cannot determinate a result of dynamic SQL (00000)
  There is a risk of related false alarms.
error storage.list_objects_with_delimiter(text,text,text,integer,text,text,text,text,text,timestamp with time zone,text) line 557: record "v_current" is not assigned yet (55000)
  The tuple structure of a not-yet-assigned record is indeterminate.
warning storage.search(text,text,integer,integer,integer,text,text,text,text,text) line 473: cannot determinate a result of dynamic SQL (00000)
  There is a risk of related false alarms.
error storage.search(text,text,integer,integer,integer,text,text,text,text,text) line 478: record "v_current" is not assigned yet (55000)
  The tuple structure of a not-yet-assigned record is indeterminate.

4 plpgsql_check finding(s) at level error/warning. These surface to users via `supabase db lint`. For records populated by dynamic SQL, declare their shape with PERFORM 'PRAGMA:TYPE:<var> (<col> <type>, ...)'.

This was due to the fact that v_current record shape was determined at runtime.

What is the new behavior?

Added a pragma as a type hint for plpgsql_check.

Additional context

I also added step in CI and a script to run these lints to ensure we don't add migrations in the future the violate plpgsql_check so they don't show up in supabase db lint

@TylerHillery
TylerHillery requested a review from a team as a code owner October 7, 2026 14:30
Copilot AI balanced review requested due to automatic review settings October 7, 2026 14:30

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Copilot review overview

🟡 Changes recommended

The lint script unconditionally removes a potentially pre-existing plpgsql_check extension.

Review effort: Balanced
Findings: 1 Medium severity

Open (1)
What changed in this PR

Adds plpgsql_check type pragmas to suppress false positives and introduces migration linting in CI.

Changes:

  • Adds type hints for dynamic v_current records.
  • Registers migration 0074.
  • Adds a migration lint script and CI job.
File Description
migrations/​tenant/​0074-pragma-dynamic-record-types.sql Recreates affected functions with type pragmas.
src/​internal/​database/​migrations/​types.ts Registers migration 0074.
src/​scripts/​lint-migrations.ts Runs plpgsql_check against migrated functions.
package.json Adds the migration lint command.
.github/​workflows/​ci.yml Runs migration linting in CI.

💡 Add a code-review agent skill or configure MCP servers for context-aware, tailored reviews. Learn more in the docs.

Comment thread src/scripts/lint-migrations.ts
@coveralls

coveralls commented Oct 7, 2026 •

Copy link
Copy Markdown

Coverage Report for CI Build 37639103658

Coverage remained the same at 84.939%

Details

  • Coverage remained the same as the base build.
  • Patch coverage: No coverable lines changed in this PR.
  • No coverage regressions found.

Uncovered Changes

No uncovered changes found.

Coverage Regressions

No coverage regressions found.


Coverage Stats

Coverage Status
Relevant Lines: 14525
Covered Lines: 12789
Line Coverage: 88.05%
Relevant Branches: 8973
Covered Branches: 7170
Branch Coverage: 79.91%
Branches in Coverage %: Yes
Coverage Strength: 782.89 hits per line

💛 - Coveralls

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

@claude claude Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

I reviewed this PR and didn't find any bugs. Because it recreates the two core storage listing/search functions (~600 lines each) and adds a new CI job that provisions a Postgres container and installs an extension, a human look would still be worthwhile.

What was reviewed: compared the new migration 0074 line-by-line against the prior definitions in 0070 — confirmed the storage.list_objects_with_delimiter and storage.search bodies are byte-identical except for the added PERFORM 'PRAGMA:TYPE:v_current (...)' hint lines; verified the PRAGMA column list/order matches each function's dynamic-SQL SELECT list exactly (so the hint is accurate, not just silencing); checked the new lint-migrations.ts script and ci.yml job wiring (migration registration in types.ts, migration:lint npm script, CI job sequencing) — all consistent and non-interactive with no untrusted input.

Extended reasoning...

The diff touches CI config (.github/workflows/ci.yml, a new lint-migrations.ts script) and a tenant SQL migration that re-creates storage.list_objects_with_delimiter and storage.search, adding a static PRAGMA type-hint comment for plpgsql_check; no auth/crypto/permissions or injection surface is touched (the lint script runs only static, parameterless SQL against an ephemeral CI database). I manually diffed the new migration against the prior function definitions to confirm the bodies are unchanged and the PRAGMA column order matches the dynamic-SQL SELECT lists, which gives reasonable confidence, but the size and production blast radius of these listing functions (used for all tenant object listings) still warrants a human glance.

This review covers commit a669cd3, which is no longer the latest commit on this pull request; later commits are not covered by it.

await client.end()
}

const failures = rows.filter((row) => FAILING_LEVELS.includes(row.level))

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

it seems cli is using prefix match and fails on extra rules as well

Comment on lines +14 to +26
const CHECK_SQL = `
SELECT p.oid::regprocedure::text AS function, r.lineno, r.level, r.sqlstate, r.message, r.detail
FROM pg_catalog.pg_proc p
JOIN pg_catalog.pg_namespace n ON n.oid = p.pronamespace
JOIN pg_catalog.pg_language l ON l.oid = p.prolang
CROSS JOIN LATERAL plpgsql_check_function_tb(
p.oid,
COALESCE((SELECT t.tgrelid FROM pg_catalog.pg_trigger t WHERE t.tgfoid = p.oid LIMIT 1), 0)
) r
WHERE l.lanname = 'plpgsql'
AND n.nspname = 'storage'
AND (p.prorettype <> 'trigger'::regtype OR EXISTS (SELECT 1 FROM pg_catalog.pg_trigger t WHERE t.tgfoid = p.oid))
ORDER BY 1, 2

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

seems like cli is ignoring functions return trigger

is it better to update cli or align with it?

Comment thread .github/workflows/ci.yml
Comment on lines +47 to +52
- name: Start Postgres with plpgsql_check
run: |
docker run -d --name plpgsql_check_db -p 5432:5432 -e POSTGRES_PASSWORD=postgres postgres:17
docker exec plpgsql_check_db bash -c \
'apt-get update -qq && apt-get install -y -qq postgresql-17-plpgsql-check'
until docker exec plpgsql_check_db pg_isready -h 127.0.0.1 -U postgres; do sleep 1; done

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

is it better to test supabase/postgres image?

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

another related question is that I think different version of major pg version doesn't matter but extension version might matter so do we need to test multiple versions of the skipped extension?

Comment thread .github/workflows/ci.yml

lint_migrations:
name: Lint / Migrations (plpgsql_check)
needs: lint_build

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

nit: this isn't on the critical path and lint_build is cheap but not necessarily need to wait for

This branch has not been deployed

No deployments
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.

Confirm managed Storage lint false positives for dynamic v_current records (migration 0070)

4 participants