mirror of
https://github.com/supabase/supabase.git
synced 2026-10-05 09:25:06 +03:00
master
145
Commits
| Author | SHA1 | Message | Date | |
|---|---|---|---|---|
|
|
9aae037dff |
Joshenlim/fe 4475 fdw update sql to run proper alter statements instead of (#50988)
## Context Currently for FDWs under integrations, editing an FDW involves tearing it down then re-creating it - which while conveniently works has a lot of problems like: - Blast radius is way bigger than the edit - Everything is recreated, including vault secrets - Silent drops grants/comments/ownership - Cascades on dependent objects - Views or functions built on top of foreign tables would get dropped along with it Changes in this PR hence updates `getUpdateFDWSql` to diff the current wrapper state against the form state and generate targeted `ALTER` statements for only what actually changed ## To test - [ ] Verify that updating an existing wrapper still works as expected <!-- This is an auto-generated comment: release notes by coderabbit.ai --> ## Summary by CodeRabbit * **New Features** * Wrapper changes can be saved in place, including server options, encrypted values, foreign tables, and column definitions. * Input fields can display placeholder text, and missing server-option values display their defaults. * **Improvements** * Saving is unavailable until encrypted values are ready; a waiting message appears while they load. * The edit panel closes after a successful save. Confirmation text explains that table or column changes may affect dependent functionality. <!-- end of auto-generated comment: release notes by coderabbit.ai --> |
||
|
|
f0952fdef8 |
fix(studio): delete only the selected foreign server FE-4462 (#50785)
## Problem The dashboard lists one row per foreign server, but deleting a row dropped its foreign data wrapper with CASCADE. When multiple servers shared a wrapper, deleting one removed all of them. ## Fix Drop the selected server and its foreign tables. Remove the underlying wrapper and Vault secret only when no servers still use it. Edits to a shared wrapper now stop before making changes because the existing edit flow recreates the underlying wrapper. ## How to test 1. Configure two BigQuery foreign servers that use the same foreign data wrapper. Delete one from the dashboard. 2. Confirm the other server and its foreign tables still exist and work. 3. Delete the remaining server. Confirm the foreign data wrapper and its Vault secret are removed. 4. Attempt to edit one of two servers sharing a wrapper. Confirm the edit fails without removing either server. Focused pg-meta tests and typecheck pass. <!-- This is an auto-generated comment: release notes by coderabbit.ai --> ## Summary by CodeRabbit * **New Features** * Shared connections are identified in the integrations list, with guidance for editing them in the SQL Editor. Editing is disabled when a wrapper is shared, with an explanation shown. * Deleting a connection removes its foreign tables and removes the wrapper and Vault secret only when no other connection uses them. * **Bug Fixes** * Connection deletion verifies that the selected server still belongs to the wrapper and reports failures using connection-focused wording. * Attempts to edit a wrapper used by another connection are blocked with a clear explanation. * Connection deletion and confirmation messages now consistently refer to deleting a connection. <!-- end of auto-generated comment: release notes by coderabbit.ai --> |
||
|
|
b1a9e072ec |
Update table editor ilike related comparators to implicitly wrap filter string with % if not provided (#50394)
### Context For table editor - the `ilike` related comparators expect users to input a `%` in the filter string, which for non-developers might not be intuitive. Hence opting to implicitly wrap the filter string with `%` in the query when filtering if non provided <img width="1182" height="755" alt="image" src="https://github.com/user-attachments/assets/819c39f5-fcbf-4213-95b3-3ad1ee901f47" /> <!-- This is an auto-generated comment: release notes by coderabbit.ai --> ## Summary by CodeRabbit * **Bug Fixes** * Improved pattern-match filters so bare text values perform contains matching by automatically wrapping them with wildcards. * Preserved explicit wildcard patterns using `%` or `_` without adding additional wildcards. * Improved handling of empty values for non-text filters while retaining existing numeric filter validation. <!-- end of auto-generated comment: release notes by coderabbit.ai --> |
||
|
|
c427615234 |
fix(pg-meta): pair composite foreign key columns correctly (#41080)
## TL;DR Correctly pairs composite foreign key columns when loading table metadata. ## What's hurting? The tables introspection query matched every source column in a composite foreign key with every target column. For `(user_id, tenant_id) → (id, tenant_id)`, it returned four relationships instead of the correct two, causing incorrect relationship metadata in the Table Editor... ## Now fixed Source and target columns are paired by ordinal position using a lateral multi-array `unnest`. Regression coverage now verifies adversarial column ordering, and the existing performance guard exercises thousands of composite foreign keys... PS: local stress test found no performance regression or unexpected sequential scans. ## Ref - Closes #41068 <!-- This is an auto-generated comment: release notes by coderabbit.ai --> ## Summary by CodeRabbit * **Bug Fixes** * Corrected foreign-key relationship detection for composite keys, ensuring source and target columns are paired accurately. * Improved catalog relationship queries to remain within performance limits for composite-key tables. <!-- end of auto-generated comment: release notes by coderabbit.ai --> --------- Co-authored-by: Andrew Valleteau <avallete@users.noreply.github.com> |
||
|
|
db0e6b761b |
Joshenlim/fe 4304 bring database connections out of feature preview (#50107)
## Context
As per PR title - we're bringing Database Connections out of feature
preview and it'll live on the dashboard by default 🙂
Also deprecating the existing Ongoing queries panel which Database
Connections now supercedes.
<!-- This is an auto-generated comment: release notes by coderabbit.ai
-->
## Summary by CodeRabbit
* **New Features**
* Database Connections is now available without feature-preview
activation.
* The SQL editor’s “View running queries” option now links directly to
Database Connections.
* **Bug Fixes**
* Query cancellation and session termination now refresh database
activity data.
* **Removed**
* Removed the in-editor ongoing queries panel and its termination
controls.
* Removed the Database Connections promotional banner, preview
messaging, settings, and related telemetry.
<!-- end of auto-generated comment: release notes by coderabbit.ai -->
|
||
|
|
2ac052752a |
fix(pg-meta): fix invalid SQL when setting column default to NULL (#50097)
## Summary
- Fixes invalid SQL generation when setting a column's default value to
NULL through Studio's Table Editor
- The bug occurred because raw `null` values bypassed literal
serialization in the SQL builder
- Added special case handling in both `create()` and `update()`
functions to use `literal(null)` regardless of format
## Details
Setting a column's default to NULL via the "Set as NULL" suggestion in
Studio generated invalid SQL: `ALTER TABLE ... ALTER COLUMN ... SET
DEFAULT ;` (missing the NULL keyword). This was caused by
`default_value` being JS `null` and bypassing the literal()
serialization function when `default_value_format === 'expression'`.
The fix ensures that when `default_value === null`, we always use
`literal(null)` to produce the correct `SET DEFAULT NULL` clause.
## Test plan
- New regression test in `packages/pg-meta/test/columns.test.ts`
("update column default value to NULL via expression format") verifies
the fix by:
- Creating a text column with a literal default
- Updating it using `default_value_format: 'expression', default_value:
null` (exact payload from Studio)
- Asserting the column's default value is null
- All 58 tests in `packages/pg-meta/test/columns.test.ts` pass
- TypeScript check (`tsc --noEmit`) passes
Fixes FE-4343
<!-- This is an auto-generated comment: release notes by coderabbit.ai
-->
## Summary by CodeRabbit
- **Bug Fixes**
- Fixed column creation and updates so explicitly setting a default
value to `NULL` correctly preserves the `DEFAULT NULL` clause.
- Ensured setting a column default to `NULL` through expression-based
editing is reflected accurately when column details are retrieved.
- **Style**
- Improved the column editor’s suggestion menu layout and spacing for
clearer readability.
- **Tests**
- Added coverage for updating a column default to `NULL`.
<!-- end of auto-generated comment: release notes by coderabbit.ai -->
---------
Co-authored-by: Joshen Lim <joshenlimek@gmail.com>
|
||
|
|
75b90c5de1 |
Check the session's backend_start for cancelling or terminating sessions (#48929)
## Context Related to database connections - specifically for cancelling queries or terminating sessions PIDs can be re-used, so a more accurate check is to use both PID and `backend_start` to uniquely identify the session to cancel or terminate <!-- This is an auto-generated comment: release notes by coderabbit.ai --> ## Summary by CodeRabbit * **Bug Fixes** * Improved query cancellation and session termination reliability by verifying the active database session before taking action. * Prevented actions from affecting a different session that reused the same process ID. * Added clearer guidance to refresh when a session has changed or is no longer available. <!-- end of auto-generated comment: release notes by coderabbit.ai --> |
||
|
|
cdfb5b310f |
Add cancel query action for database connections (#48922)
## Context Related to Database Connections - Adds a "cancel query" action for "active" sessions using `pg_cancel_backend` - Gentler alternative as the connection stays alive, unlike terminating the session - Not applicable for queries idle in transaction as there's no query running (Disabled in this case) - Rename "Terminate" to "Terminate session" - Rename "Abort query" to "Terminate session" For active queries: <img width="220" height="135" alt="image" src="https://github.com/user-attachments/assets/d6ca790d-bb6a-4582-8554-24431388483a" /> For idle in txn queries: <img width="433" height="135" alt="image" src="https://github.com/user-attachments/assets/615d0651-9f5b-4efc-a5cf-72f93727aa91" /> Also updating confirmation modal for terminating session CTA: For active queries: <img width="407" height="301" alt="image" src="https://github.com/user-attachments/assets/e5f56764-11b9-4c10-ba01-d7547aaec872" /> All other queries: <img width="410" height="212" alt="image" src="https://github.com/user-attachments/assets/8631633f-5d4a-40a7-b089-6980a5180219" /> <!-- This is an auto-generated comment: release notes by coderabbit.ai --> ## Summary by CodeRabbit ## New Features - Added a separate **Cancel query** action for active database queries. - Added **Terminate session** to close connections and roll back active transactions. - Added safeguards based on query activity and permissions. - Added confirmation guidance for active queries, including cancellation options. - Added loading, success, and error feedback for query cancellation and session termination. - Added telemetry for query-cancellation actions. <!-- end of auto-generated comment: release notes by coderabbit.ai --> |
||
|
|
ec64135f9d |
perf(pg-meta): scope column privileges query to a single table (#48553)
## I have read the [CONTRIBUTING.md](https://github.com/supabase/supabase/blob/master/CONTRIBUTING.md) file. YES ## What kind of change does this PR introduce? Performance improvement ## What is the current behavior? The column privileges page in Studio only ever renders one table, but the underlying query still `aclexplode`s every column in the whole schema and filters the result client-side. ## What is the new behavior? Adds a scoped SQL path that prunes `pg_class`/`pg_namespace` to the requested schema+table before exploding ACLs, gated behind the `pgMetaScopedIntrospection` flag, with a plan-guard test asserting `pg_class`/`pg_attribute` stay index-driven. Studio's query hook and cache keys now thread the selected table through so column-privilege invalidation and cold-load races are scoped correctly, and the page fetches per-table instead of per-schema. ## Additional context <!-- This is an auto-generated comment: release notes by coderabbit.ai --> ## Summary by CodeRabbit * **Improvements** * Column privileges are now scoped to the selected schema and table for more accurate results. * Changing schemas automatically updates the table selection and refreshes the displayed privileges. * Privilege updates now refresh only the relevant schema, table, and column data. * Loading states are handled more accurately when no table is selected. * **Bug Fixes** * Improved consistency between scoped and unscoped column privilege results, including table-, column-, and grant-option privileges. <!-- end of auto-generated comment: release notes by coderabbit.ai --> |
||
|
|
a06eb5f26f |
[FE-3724] feat(studio): add enable cleanup button to cron jobs page (#48200)
Adds a standalone **Enable cleanup** button to the Cron Jobs page header so users can schedule the daily `delete-job-run-details` cleanup job proactively — previously this was only reachable inside the conditional "table too big" overflow dialog. Addresses [FE-3724](https://linear.app/supabase/issue/FE-3724/enable-pg-cron-cleanup-job-from-ui-and-api) (the UI half; the Management API half needs platform-side work). **Added:** - `Enable cleanup` button in the cron jobs header (left of Refresh), hidden while the existence check loads and whenever a `delete-job-run-details` job already exists - Confirmation dialog with a retention-period select (defaults to 7 days), live SQL preview, and telemetry (`cron_job_cleanup_enable_button_clicked` with `origin` + `retentionInterval`) - Component tests (MSW) for visibility gating and the schedule/cancel flows - E2E regression test for the full schedule → delete → button-reappears cycle **Fixed:** - Name-based `useCronJobQuery` lookup: the `queryFn` dropped the `name` param, and a not-found job returned `undefined` (rejected by react-query v5) — now passes `name` through and returns `CronJob | null` - Cache invalidation gaps: create/delete now invalidate the whole cron-jobs prefix (list, count, job details), so the footer count updates after create/delete and the button reappears after the cleanup job is deleted. The schedule mutation deliberately invalidates only the existence check + count (see inline comment) - Pre-existing e2e leak: the cleanup-workflow test left `delete-job-run-details` scheduled; it now cleans up after itself ## Screenshots | Header button | Dialog | | --- | --- | | <img width="890" height="325" alt="Screenshot 2026-07-22 at 9 44 40 PM" src="https://github.com/user-attachments/assets/966cd640-d8a6-4c8f-92e7-73151bf4de9c" /> | <img width="512" height="461" alt="fe3724-dialog" src="https://github.com/user-attachments/assets/6be1785f-cc7e-4048-a648-9ef260b0949f" /> | ## To test - Go to a project's Integrations → Cron → Jobs with pg_cron enabled and no `delete-job-run-details` job → the `Enable cleanup` button shows next to Refresh - Open the dialog, switch retention intervals → the SQL preview updates; confirm → success toast, the job appears in the grid (`0 12 * * *`), and the button disappears without a reload - Delete the `delete-job-run-details` job from the grid → the button reappears without a reload - Create then delete any other job → the footer `Total: N jobs` count updates both ways without a reload - Regression: with the high-query-cost banner forced (or via the e2e), the overflow dialog's "Schedule cleanup job" step still shows its success state — the dialog must not close mid-flow <!-- This is an auto-generated comment: release notes by coderabbit.ai --> ## Summary by CodeRabbit ## Summary by CodeRabbit * **New Features** * Added an **Enable cleanup** action to the Cron Jobs tab header, including a retention selector and SQL preview. * Enabling schedules the daily cleanup, shows a success toast, updates the grid, and hides the enable button; **Cancel** closes the dialog without scheduling. * **Bug Fixes** * Improved cron job lookup to work by name when needed. * Refreshed related cron job data more reliably after scheduling and deletion. * **Telemetry** * Added an event for cleanup enable button clicks. * **Tests** * Added component and Playwright coverage for enable/cancel/schedule/delete and cleanup banner flows. <!-- end of auto-generated comment: release notes by coderabbit.ai --> --------- Co-authored-by: Alaister Young <10985857+alaister@users.noreply.github.com> |
||
|
|
6c6a721cb7 |
fix(pg-meta): scope remaining O(catalog) introspection queries behind pgMetaScopedIntrospection (#48148)
## I have read the [CONTRIBUTING.md](https://github.com/supabase/supabase/blob/master/CONTRIBUTING.md) file. YES ## What kind of change does this PR introduce? Bug fix (performance), follow-up to #47894, plus regression-guard tests. ## What is the current behavior? #47894 scoped the Table Editor and entity-definition introspection queries, but four more `@supabase/pg-meta` query families still do O(catalog) work per request. On a production project with a very large catalog (hundreds of schemas, ~465K `pg_constraint` rows) they run 5 to 55 seconds each, trip the 58s `statement_timeout`, and spill sorts to temp files. During a recent "DB CPU > 85%" incident on such a project, 24 of 27 active backends were running these queries concurrently. 1. **`tables.retrieve()` (single-table lookup by name+schema or id)**: the `tables`/`columns` CTEs scan the whole catalog (`pg_class`, `pg_constraint`, `pg_index`, all of `pg_attribute`, per-table sizes) and the one-table predicate is applied only on the outer select. Same bug class #47894 fixed for the OID-based table editor query; this sibling path never got the treatment. It accounted for 94 of the 96 statement-timeout cancellations in the incident. 2. **Types listing**: the `t_enums` and `t_attributes` subqueries aggregate the entire `pg_enum` and every composite relation before the wrapper's schema filter applies. 3. **Table privileges**: `aclexplode` + double `pg_roles` join + GROUP BY over every relation in the database; schema/OID filters applied only after aggregation, in both `list()` and `retrieve()`. 4. **Row counts**: `getTableRowsCountSql` treats `reltuples = -1` (never-analyzed table) as "small table, run exact count(*)". A freshly bulk-loaded multi-million-row table times out on every Table Editor pagination render. Two Studio-side amplifiers turned one slow query into a sustained load storm: - `useTableQuery` (behind `tables.retrieve()`) mounts once per visible foreign-key grid cell via `ForeignKeyFormatter`, so a single Table Editor view fires ~20 concurrent copies against the FK target table. A timed-out query caches nothing, and TanStack retries errored no-data queries on every observer mount by default, so scrolling kept re-issuing the 58s scan. - `useTableApiAccessQuery` fetched table privileges for the entire database and filtered down to one schema client-side. ## What is the new behavior? **pg-meta (all behind the existing `pgMetaScopedIntrospection` flag, same rollout mechanism as #47894; `scoped: false` keeps serving the current SQL):** - `tables.retrieve()`: the identifier is resolved to a scalar `targetOid` init-plan and pushed into the base scan, primary-key, relationships (both FK directions kept: `conrelid` or `confrelid`) and columns CTEs. A materialized `target` CTE was deliberately avoided: it acts as an optimization barrier and forces the very seq scans being removed. - Types: filter `pg_type`/`pg_namespace` first, then compute enums/attributes per surviving row via correlated index-scan subqueries (`pg_enum(enumtypid, enumsortorder)`, `pg_attribute(attrelid, attnum)`). - Table privileges: schema/OID predicates injected into the base WHERE before `aclexplode`/GROUP BY for `list()` and `retrieve()`. - Row counts: `reltuples = -1` is treated as "unknown" and gated on physical size via `pg_relation_size` (a cheap stat call; `relpages` is equally stale pre-vacuum). At or below `THRESHOLD_ESTIMATE_BYTES` (~10MB, derived from `THRESHOLD_COUNT` at a conservative ~200 bytes/row) the exact count runs as before: fast by construction, and it avoids bogus estimates since Postgres floors never-vacuumed heaps at 10 pages, so an empty table would otherwise report ~2K estimated rows. Above the gate the count routes through the EXPLAIN-based `pg_temp.count_estimate`, or returns `-1`/`is_estimate = true` in read-only contexts where the temp function cannot be created. The scoped branch embeds the estimated select via `literal()` instead of legacy's apostrophe-only escaping, so it stays correct under `standard_conforming_strings = off`. `enforceExactCount` unchanged. **Studio:** - The flag decision is contained in the data layer instead of prop-drilled: a small imperative accessor (`apps/studio/data/scoped-introspection.ts`) is hydrated from `useFlag` via a one-line `useSyncScopedIntrospection()` call in `DefaultLayout`, and the query functions read it internally when building the pg-meta SQL. `DefaultLayout` is shared by both the Next and TanStack router trees; hydrating from `_app.tsx` alone would leave TanStack-served pages permanently unscoped since `routes/__root.tsx` mounts its own flag provider. Cold loads cannot race the flag: the query functions await a readiness promise that resolves only after the sync hook has hydrated the accessor with a loaded flag store (immediately on self-hosted where flags are disabled; a 5s safety net armed lazily on the first `ready()` call - not at module import, which would let the timer expire before a project page ever mounts - bounds genuine ConfigCat outages). No component threading, no query-key changes (remaining tradeoff, documented in the module: a mid-session flag flip can serve stale-keyed caches until refetch, fine for a session-stable rollout flag). #47894's existing threading is left as-is and gets deleted together with the flag in the cleanup PR. Also fixes the previously-missing `scoped` pass-through in `getTableRowsCount`. - Flag-independent hardening: `useTableQuery` now sets `retryOnMount: false`, `refetchOnWindowFocus: false` and `staleTime: 5min`. Errored (timed-out) queries no longer refire on every grid cell remount, while stale successful metadata still revalidates on mount after `staleTime`. - `useTableApiAccessQuery` now passes `includedSchemas: [schemaName]`; the client-side filter stays as a safety net. - The rows-count query is `enabled`-gated on the permission check settling, so a transiently-false `canSQLAdminWrite` can no longer cache a read-only `-1` count for a writable user (read replicas short-circuit synchronously as before). **Regression guards (extending the #47894 infrastructure):** - Execution-based scoped-vs-legacy equivalence tests for all four queries: both variants run against the test database and are compared with raw `toEqual` - no normalization, ids included (types across 6 option combos, privileges incl. multi-grantee + PUBLIC, `tables.retrieve` for both identifier branches, row counts for every case where the two paths must agree). Two documented exceptions where only the LEGACY side is sorted, because a de-normalized diagnostic run proved legacy emits genuinely plan-dependent order there (an adversarial-FK fixture shows it is neither oid, name, nor creation order): the `types.list` outer row order (scoped adds `order by t.oid`; legacy has no ORDER BY) and the `tables.retrieve` relationships array (scoped orders by `constraint_name` + column-name tie-breakers - a composite two-column FK expands to 4 entries sharing one constraint_name). Everything else (privileges via `aclexplode` over the same relacl, columns by `ordinal_position`, primary keys by `indkey` order, enums by `enumsortorder`) is byte-identical between the two paths with no test-side help. The one intentional value divergence, never-analyzed tables above the size gate where legacy's exact count is the timeout bug itself, is asserted explicitly as a divergence. - Plan-guard budgets for every scoped query against the stress catalog (extended with 200 enums + 200 composite types). Residual seq scans are justified in-budget: `pg_constraint` max 2 (no index on `confrelid`), `pg_attrdef` max 1, `pg_authid` max 2 (scales with role count, not schema count). - Legacy templates carry a FROZEN do-not-edit marker (they must keep matching production behavior until the flag cleanup deletes them); the ordinary test suite runs against the legacy default, so behavioral drift there fails regular tests. ### Validation - pg-meta: typecheck clean; the affected suites (types, table-privileges, tables, rows-count, catalog-plan-guard) pass in full. - Cross-version: the scoped-vs-legacy equivalence and rows-count behavioral suites were validated on PostgreSQL 14, 15, and 17 (identical results on all three). Two version-marginal planner choices surfaced on 17 (`pg_type` / `pg_class` seq scan vs full-index bitmap for per-schema listings, both structurally unavoidable without an index leading on the namespace column) and are carried as justified plan-guard budget entries. A full 468-test suite run sequentially: 452 passed, 16 failures verified environmental (13 timeouts in an untouched file that passes 27/27 in isolation on the marathon-run cluster, 3 cluster-global role collisions from container reuse). - Studio: `pnpm --filter studio typecheck` clean; 39/39 tests across the touched data hooks; eslint clean on touched files. ### Rollout Same staged ConfigCat rollout as #47894 via `pgMetaScopedIntrospection` (user-email targeting first, then percentage, then 100%). The `useTableQuery` hardening and the API-access schema scoping ship unflagged (behavior-safe). Gate before percentage rollout: functionally verify the FK popover/selector UX under the new `staleTime`/`retryOnMount` settings (a just-edited FK target must not look stale anywhere Studio does not already refetch on save). Once fully rolled out, the legacy templates and flag get deleted together with #47894's in one cleanup PR. 🤖 Generated with [Claude Code](https://claude.com/claude-code) --------- Co-authored-by: Claude Fable 5 <noreply@anthropic.com> |
||
|
|
2e12cdc2e1 |
fix: empty search_path (#48151)
## TL;DR Restores handling for functions with `search_path` set to `''` editing them in the UI was failing with a Postgres `zero-length delimited identifier` error since the SafeSql refactor dropped the empty-string sentinel conversion ## ref - closes #48149 <!-- This is an auto-generated comment: release notes by coderabbit.ai --> ## Summary by CodeRabbit * **Bug Fixes** * Preserved empty `search_path` configuration values when updating database functions. * Prevented empty configuration values from being altered or lost during function updates. * **Tests** * Added coverage verifying that function definitions can be updated without changing an existing empty `search_path` setting. <!-- end of auto-generated comment: release notes by coderabbit.ai --> |
||
|
|
c7803b8b9b |
Chore/add sessions database connections (#48094)
## Context Initial work for Top for Postgres - adds a "Sessions" section under a new Observability segment "Database Connections" NOTE: All the copywriting and naming might change - not sure what's an ideal title for this We'll also be iteratively building on top of this UI, adding more actionable signals instead of just information Changes are featured flagged, off for public - This would essentially replace the "View ongoing queries" in the SQL Editor by providing a dedicated UI - It checks against `pg_stat_activity` as per the ongoing queries UI - We'll also subsequently deprecate the "Ongoing queries" UI in the SQL editor - Defaults into a "live mode" where the data is refreshed every 3 seconds via long-polling <img width="983" height="474" alt="image" src="https://github.com/user-attachments/assets/16402fe4-0b53-4f9e-9342-cdda26e3778a" /> - Supports filtering by state <img width="374" height="282" alt="image" src="https://github.com/user-attachments/assets/562f8fbe-2dc6-48e7-8ec0-de7ffb8348d1" /> - Users can also terminate queries through here <img width="247" height="164" alt="image" src="https://github.com/user-attachments/assets/23a639dc-8f96-473a-a823-605b0bab02ee" /> <!-- This is an auto-generated comment: release notes by coderabbit.ai --> ## Summary by CodeRabbit # Release Notes * **New Features** * Added an Observability **Database Connections** page with a live **Sessions** activity table (state/roles filtering, blocked-by details, session duration, and per-session termination with confirmation). * Included a **Live/Pause** toggle to control automatic refresh (~3 seconds). * **Enhancements** * Improved Reports selection filtering: supports optional option quantities, better popover styling, sorted apply behavior, and shows quantity inline. * Query performance duration formatting now supports configurable decimal precision. * Tooltips can now render richer content (string or React node). <!-- end of auto-generated comment: release notes by coderabbit.ai --> |
||
|
|
24ce0ba5f8 |
chore: migrate repo to pnpm v11 (#48033)
## I have read the [CONTRIBUTING.md](https://github.com/supabase/supabase/blob/master/CONTRIBUTING.md) file. YES ## What kind of change does this PR introduce? Chore / dependency tooling update. ## What is the current behavior? The repo is pinned to pnpm 10.24.0. Closes https://linear.app/supabase/issue/FE-3673/migrate-the-repo-to-use-pnpm-v11. ## What is the new behavior? The repo is pinned to pnpm 11.13.1, pnpm v11 workspace settings are migrated to `allowBuilds`, and the Studio Dockerfile installs pnpm 11.13.1. ## Additional context Validated with `CI=true mise exec node@22 -- pnpm install --frozen-lockfile`, `mise exec node@22 -- pnpm run typecheck`, and `mise exec node@22 -- pnpm run lint`; full Prettier check still fails on existing generated docs/router files outside this migration. <!-- This is an auto-generated comment: release notes by coderabbit.ai --> ## Summary by CodeRabbit * **Chores** * Updated tooling requirements (pnpm **11.13.1**, Node **>=22.13**) and aligned container build tooling accordingly. * Adjusted package manager behavior (scoped registry override, update notifications disabled) and workspace build/engine validation settings. * **Maintenance** * Updated `clean` scripts across apps/packages to remove only build/cache artifacts (no longer delete installed dependencies). * Reduced Turbo `clean` task output to **errors-only** for cleaner logs. <!-- end of auto-generated comment: release notes by coderabbit.ai --> |
||
|
|
768ea1001b |
fix(studio): scope table editor introspection CTEs to target table OID (#47894)
## I have read the [CONTRIBUTING.md](https://github.com/supabase/supabase/blob/master/CONTRIBUTING.md) file. YES ## What kind of change does this PR introduce? Bug fix (performance), plus a regression-guard test suite and docs. ## What is the current behavior? Studio's introspection queries in `@supabase/pg-meta` do `O(catalog)` work for per-table requests. On databases with very large catalogs (hundreds of thousands of relations/constraints — real deployments reach this) they take tens of seconds per dashboard interaction, trip `statement_timeout`, and create heavy CPU/memory pressure when several tabs open concurrently. Two instances of the same bug class: **1. Table Editor query (`getTableEditorSql`)** — fetches metadata for ONE table by OID, but five catalog scans are unscoped and only filtered at the top-level join: - `primary_keys` CTE — scans all of `pg_index` (`where i.indisprimary`) - `index_cols` CTE — scans all unique indexes - `relationships` CTE — scans every FK in `pg_constraint` (and is scanned twice by the two subplans) - `uniques` subquery (inside `columns`) — scans all single-column unique constraints - `check_constraints` subquery (inside `columns`) — scans all single-column check constraints The planner cannot push the outer join qual into grouped / `distinct on` subqueries, so each is computed over the full catalog and thrown away. `tables-paginated.ts` was previously rewritten to avoid exactly this pattern; the single-table query never got the same treatment. **2. Entity definitions (`getTableDefinitionSql` / `getEntityDefinitionsSql`)** — the vendored `pg_get_tabledef` plpgsql function scans the entire `information_schema.columns` view once **per column** (plus `information_schema.tables` once per call) just to decide whether a name needs double-quoting — a pure string property of a name it already holds — and its per-index partial-index lookup casts `relnamespace::regnamespace::text` across every `pg_class` row. On a 12K-table catalog this makes a single entity's DDL cost ~3.7s and a default 100-entity definitions page ~6 minutes. ## What is the new behavior? **Fix 1 — scope the Table Editor CTEs to the requested OID** (`id` is validated non-null and interpolated via `literal()`, same as the existing `base_table_info` filter): - `primary_keys` / `index_cols`: `and i.indrelid = <id>` - `relationships`: `and (c.conrelid = <id> or c.confrelid = <id>)` - `uniques` / `check_constraints`: `and conrelid = <id>` Semantics are unchanged: the top-level select already filtered every CTE to the target table, so rows for other tables were computed and discarded. The `pg_index`/`pg_constraint` lookups become index scans returning a handful of rows. One residual scan is structural: PostgreSQL has no index on `pg_constraint.confrelid`, so the incoming-FK half of `relationships` is a single filtered seq scan of `pg_constraint` — still one cheap pass instead of materializing every FK row twice. **Fix 2 — remove the O(catalog) scans inside `pg_get_tabledef`**: the information_schema uppercase checks are replaced with direct regex tests on the name in hand (preserving the original's `quote_ident` behavior for schemas that need quoting), and the partial-index lookup is scoped by the already-resolved table OID. Original statements are kept as comments, matching the vendored file's convention. **Regression guard** — so this bug class stays out: - `test/db/stress-catalog.ts` builds a synthetic catalog (default 2,000 tables with PKs, unique + check constraints, FK chains and an FK hub; `PG_META_STRESS_TABLES` scales it to incident size). - `test/db/plan-guard.ts` provides `EXPLAIN (ANALYZE, FORMAT JSON)`-based budget assertions: a query's plan may only seq-scan a scaling catalog if its budget entry carries a written structural justification (e.g. no index on `pg_constraint.confrelid`; no index on `pg_class.relnamespace` for per-schema listings), plus a per-query time bound (the only guard available for opaque plpgsql internals like `pg_get_tabledef`). - `test/sql/studio/catalog-plan-guard.test.ts` applies budgets to the hot-path studio queries: table editor, constraints, FK listing, entity types, tables-paginated, columns, indexes, table/entity definitions, views. Reverting either fix makes the suite fail immediately with the offending scans listed. - `test/sql/studio/table-editor.test.ts` (new — none existed) asserts the Table Editor query's semantics: primary keys, unique indexes, both FK directions, `is_unique`, check definitions, column comments. - A new package `README.md` documents the plan-guard budget entry as a requirement for any new introspection query. ### Validation (synthetic 12,000-table catalog, PostgreSQL 17.6) - **Output equivalence, fix 1:** for 12 relation types (regular, composite PK, partitioned parent + partition, view, materialized view, constraint-free table, FK hub/chain/tail, and a fixture with enums/domains/generated/identity columns and duplicate check constraints), the `entity` jsonb from the old and new query is byte-identical. - **Output equivalence, fix 2:** byte-identical DDL across 13 fixture combinations (serial/identity/generated/array columns, case-sensitive and keyword names, mixed-case schemas, partitions, unlogged + reloptions, partial/expression indexes, external PK/FK/comments/trigger variants). - **Performance, fix 1:** Table Editor query `EXPLAIN ANALYZE` ~1,630ms → ~30ms (~50×); the gap grows with catalog size since the old query is O(catalog) per call. - **Performance, fix 2:** single entity definition 3,672ms → 63ms; a 100-entity definitions page ~6min → 0.87s. The plan-guard bound for `getEntityDefinitionsSql` tightens accordingly from 15s/25 entities to 3s/100 entities (330ms measured at default test scale). Verified locally: `catalog-plan-guard` (12 tests), `table-editor`, `tables-paginated` (16 tests) pass; `typecheck` clean. ### Rollout Per review, the new behavior ships **dark** behind the `pgMetaScopedIntrospection` ConfigCat flag (default off = legacy SQL, kept as full duplicated templates in pg-meta and verified byte-identical to the pre-PR queries). Studio reads the flag in the query hooks and threads it through (flag state is part of the React Query keys). The rollout is staged in the ConfigCat dashboard via user-email targeting (like every other ConfigCat flag): target the reporting user's email first, then a percentage rollout, then 100%. Server-side AI callers of `getEntityDefinitionsSql` stay on the legacy path. Once fully rolled out, delete the legacy templates + flag in a cleanup PR. 🤖 Generated with [Claude Code](https://claude.com/claude-code) Closes: PGMETA-122 <!-- This is an auto-generated comment: release notes by coderabbit.ai --> ## Summary by CodeRabbit - **Bug Fixes** - Improved table editor SQL to correctly scope primary keys, indexes, uniques, checks, and relationships to the selected table. - Optimized table definition SQL to reduce unnecessary catalog scanning for uppercase-name detection and partial-index detection. - **Tests** - Added SQL generator tests for table editor metadata (keys, indexes, relationships, comments, and constraints). - Added catalog query plan guard coverage with a stress catalog and EXPLAIN-based scoping/performance budgets. - **Documentation** - Expanded documentation on catalog query plan safeguards and how to keep new introspection queries properly scoped. <!-- end of auto-generated comment: release notes by coderabbit.ai --> --------- Co-authored-by: Claude Fable 5 <noreply@anthropic.com> |
||
|
|
a3f2c4ffc1 |
chore(deps): upgrade to TypeScript 7 (native compiler) (#47757)
Upgrades the monorepo to TypeScript 7.0.2, released 2026-07-08. `tsc` is now the native Go compiler ([announcement](https://devblogs.microsoft.com/typescript/announcing-typescript-7-0/)) — full turbo typecheck drops from ~56s to ~19s locally. TS 7.0 ships **without a programmatic API** (it lands in 7.1), so this uses Microsoft's recommended side-by-side setup: the `typescript` name resolves to `@typescript/typescript6` (the 6.0 API republished) for API consumers — typescript-eslint and Next.js build typechecking — while `@typescript/native` (the real `typescript@7.0.2`) owns the `tsc` bin that typecheck scripts run. Exactly one version of each is in the lockfile; nothing imports the native package as a library. When 7.1 + tool support lands we can collapse back to a single `typescript` dep in the catalog. **Changed:** - `pnpm-workspace.yaml`: catalog aliases for `typescript` / `@typescript/native` - 17 package.json files: `@typescript/native` added beside each `typescript` dep so every package's `tsc` is the native binary - `apps/studio/tsconfig.json`: exclude `dist/` (gitignored build output) from typechecking **Fixed** (real type errors TS 6 under-reported): - `packages/ui-patterns` CodeBlock: `borderLeft: null` → `undefined` (`CSSProperties` doesn't accept null) - `apps/www` CodeBlock: removed a JSX `@ts-ignore` comment that tsgo doesn't honor and fixed what it masked (untyped `.js` theme objects, possibly-undefined highlighter children) ⚠️ **Merge timing:** the new packages are inside pnpm's 3-day `minimumReleaseAge` window until ~July 11. Installs from the committed lockfile are unaffected (resolution is skipped), but anything that forces a re-resolution before then will fail — hold off merging until the window passes. Note for editors: the compat package has no `lib/tsserver.js`, so VS Code's "Use Workspace Version" won't work — use the bundled TS or the TypeScript Native Preview extension. ## To test - `pnpm install && pnpm typecheck` — all 15 tasks green, and `./node_modules/.bin/tsc --version` prints 7.0.2 - `pnpm lint --filter=studio` — typescript-eslint still parses (resolves the 6.0 API) - `pnpm build --filter=design-system` (or any Next app) — Next's tsconfig validation and build typecheck still work - CodeBlock rendering on www (syntax highlighting, line highlights with/without border) — the two fixes are behavior-neutral but worth an eyeball <!-- This is an auto-generated comment: release notes by coderabbit.ai --> ## Summary by CodeRabbit * **Improvements / New Features** * Enhanced TypeScript tooling support across the workspace for smoother development builds and checks. * **Bug Fixes** * Code blocks render more reliably when content is empty or missing. * Highlighted code line styling applies more consistently. * **Maintenance** * Studio TypeScript builds now avoid including generated output (such as `dist`) during compilation. <!-- end of auto-generated comment: release notes by coderabbit.ai --> --------- Co-authored-by: Alaister Young <10985857+alaister@users.noreply.github.com> Co-authored-by: Ivan Vasilov <vasilov.ivan@gmail.com> |
||
|
|
f34fdd6c8f |
Skip using count estimate function for retrieving row counts if in read only context (#47761)
## Context Currently when retrieving row counts of a table in the Table Editor, we're using a `COUNT_ESTIMATE` pg function ([ref](https://github.com/supabase/supabase/blob/master/packages/pg-meta/src/sql/studio/database/get-count-estimate.ts#L5)) to retrieve an estimate (instead of checking `pg_class` -> `reltuples`) as that would theoretically provide a more accurate representation. However, in a read only context, that function can't be used - users will run into `cannot execute CREATE FUNCTION in a read-only transaction`, so we need to fallback to just checking `pg_class` in this scenario. The logic's already set up as we were previously looking into allowing users to use a read replica to power the dashboard, but we also need to consider members with read-only roles within the organization, so this PR updates the logic a little to factor that in. ## To test - [ ] With a read-only role, open the table editor and verify that we're not using the count estimate function to retrieve the table row counts <!-- This is an auto-generated comment: release notes by coderabbit.ai --> ## Summary by CodeRabbit * **New Features** * Updated the invite member dialog to open in a larger size for better usability. * **Bug Fixes** * Improved table row count behavior so it now respects read-only access and permission limits more reliably. * Count estimates should now be shown more consistently across different database contexts. <!-- end of auto-generated comment: release notes by coderabbit.ai --> |
||
|
|
4901f081e5 |
Migrate remaining requests to pg-meta API to use query endpoint (#47758)
## Context Migrates the remaining API requests to the pg-meta endpoint to use the query endpoint directly with the SQL from the pg-meta package. This touches the following: - policies - publications - triggers - views - materialized views - types ## To test Just need to verify that we're still fetching the data correctly on these pages - Database policies - Database publications - Database triggers - Database tables (views + materialized views) - Database types <!-- This is an auto-generated comment: release notes by coderabbit.ai --> ## Summary by CodeRabbit * **Bug Fixes** * Improved and stabilized loading of database metadata (views, triggers, RLS policies, publications, materialized views, and enum types), including more reliable schema-scoped filtering. * Updated policy loading behavior and related UI queries to consistently use schema arrays, improving cache correctness and consistency. * **Tests** * Updated end-to-end test synchronization to wait for the correct metadata responses using more specific request identifiers. <!-- end of auto-generated comment: release notes by coderabbit.ai --> |
||
|
|
9af6e65df4 |
fix(studio): DOM-nesting hydration errors, ghost deleted-snippet nav, and migrations query 400s (#47667)
App-level fixes that reproduce on BOTH the Next and TanStack builds — split out of #47657 (which stays TanStack-only) for reviewability. All were found by a full-site click-through of the dashboard. ## Invalid HTML nesting (React 19 "will cause a hydration error" console errors) - **FormLayout description rendered in a `<p>`** (`packages/ui-patterns`): consumers pass arbitrary JSX (the RowEditor's `created_at` timezone note passes a `<div>` with `<p>`s) → `<p>`-in-`<p>` / `<div>`-in-`<p>`. Container is now a `<div>` with identical classes (Tailwind preflight makes them render the same). - **Switch toggles nested inside Tooltip trigger buttons** (button-in-button) in ColumnEditor ("Allow Nullable" + "Is Unique"), ExtensionRow, and PublicationsTableItem → repo-standard `TooltipTrigger asChild` + `<div>` wrapper. - **Saved log queries rendered a `<div>` directly inside `<tbody>`** (`/logs/explorer/saved`) → rows are now proper `<tr><td colSpan>` wrappers; the component itself is untouched (it's valid in its sidebar usage). - **Nested anchors in observability metric cards**: a card-level `<Link>` wrapped MetricCard's "More information" `<Link>` (identical URLs) → the chevron affordance renders as a `<span>` when no `href` is passed; clicks bubble to the card link, tooltips preserved. Design-system standalone usage unaffected. - **`objectFit="cover"` passed to modern `next/image`** on the featured integration card (unknown-prop warning) — the className already had `object-cover`; prop dropped. ## Ghost dead-snippet after deletion Deleting the active SQL snippet left its id in `useDashboardHistory` (`history.sql`), so the "SQL Editor" nav item navigated to `/sql/<deleted-id>` — content fetch 404s, no editor pane renders, and a phantom tab reappears. Fixed both ends: delete flows now purge dashboard history (and the tabs store clears a stale `previewTabId`), and `/sql/[id]` treats a snippet 404 as "clean up + `router.replace` to `/sql/new` + toast" instead of rendering the dead state. Unit tests for the store/history cleanup. ## `pg-meta` migrations query 400s on every project load `ActivityStats` on project home runs the migrations list query, whose SQL was a bare `select * from supabase_migrations.schema_migrations` — that table only exists once a migration has run, so every other project logged a failed `?key=migrations` request on every load (visible in production consoles too). The SQL is now guarded with `to_regclass` + `query_to_xml` (same pattern as the advisor lints' `storage.buckets` guard), returning zero rows instead of erroring; legacy version-only tables still work. Tested against real dockerized Postgres (absent table, populated ordering, special chars, legacy schema) + MSW hook tests. Found and verified via /test-supabase-local (browser click-through + console audit on both builds). ## To test Console must stay free of React DOM-nesting errors ("cannot be a descendant of" / "cannot contain a nested") on each surface: 1. Table editor → Insert row panel (`created_at` field renders its timezone note) and Edit column panel ("Allow Nullable"/"Is Unique" tooltips still hover). 2. `/database/extensions` and `/database/publications` → toggle switches render, tooltips hover. 3. `/logs/explorer/saved` (with ≥1 saved query) → rows render full-width inside the table, hover shows Actions. 4. `/observability` → no nested-anchor error on load; card body click and the chevron both navigate; label help-icons still show tooltips. 5. `/integrations` → no `objectFit` unknown-prop warning; featured card images still cover. 6. **Ghost snippet**: open a SQL snippet → delete it via the sidebar → click the "SQL Editor" nav item → lands on `/sql/new` (no phantom tab, no 404 content fetch). Direct-load `/sql/<random-uuid>` → toast + redirect to `/sql/new`. 7. **Migrations 400**: load project home with a project that has never run a migration → the `pg-meta/<ref>/query?key=migrations` request returns **200** with `[]` (previously a 400 on every load). Database → Migrations still lists real migrations when they exist. <!-- This is an auto-generated comment: release notes by coderabbit.ai --> ## Summary by CodeRabbit ## Summary by CodeRabbit * **Bug Fixes** * Deleted SQL snippets are fully removed from dashboard history and stale editor/tab state; users are redirected with a toast. * Closing preview tabs no longer leaves stale references. * Improved toggle/tooltip/dialog interactions to avoid broken UI, including metric headers showing tooltips even without direct links. * Migrations display safely when migration tables/relations are missing. * **UI Improvements** * Refreshed layout for saved queries, form descriptions, and integration imagery. * **Tests** * Added coverage for snippet history cleanup, tab removal, migrations SQL behavior, and query edge cases. <!-- end of auto-generated comment: release notes by coderabbit.ai --> --- ### Review feedback: `query_to_xml` breaks on Multigres (Ivan) The defensive migrations query (added here to stop the `?key=migrations` 400 when the table doesn't exist yet) originally guarded with `query_to_xml`, which is forbidden through Multigres's pooler (MUL-736 / PSQL-1318). Rewritten without `query_to_xml`/`xmltable` using the splinter#170 pattern: a PL/pgSQL `do` block guarded by `to_regclass` (PL/pgSQL defers planning, so a missing table never errors) stashes the rows into a transaction-local GUC via `set_config`, and a trailing `select` reads them back with `jsonb_array_elements`. Verified that postgres-meta sends the whole SQL as one simple-query string → single implicit transaction → the local GUC survives to the `select` and doesn't leak into the pooled connection. 6/6 dockerized-Postgres tests (absent table → `[]`, populated/ordered/special-chars, legacy version-only table, full pg-meta-shaped multi-statement string, GUC non-leakage). Note (out of scope, pre-existing): `packages/pg-meta/src/sql/studio/advisor/lints.ts` still uses `query_to_xml` — a separate pre-existing Multigres risk that should get its own splinter-pattern sync. --------- Co-authored-by: Alaister Young <10985857+alaister@users.noreply.github.com> Co-authored-by: Joshen Lim <joshenlimek@gmail.com> Co-authored-by: Saxon Fletcher <saxonafletcher@gmail.com> |
||
|
|
99db104cf5 |
fix(pg-meta): escape unencrypted FDW server options via format() %L (#47014)
Closes #47012 ## What kind of change does this PR introduce? Bug fix. ## What is the current behavior? Unencrypted FDW server option values are pre-escaped with `literal(value).replace(/'/g, "''")` and embedded inside the outer `create server` `E'...'` string built by `format()`. That nests the value inside two `E'...'` literals, so backslashes are decoded twice. A value like `domain\user` aborts wrapper creation with `invalid Unicode escape`, and `p@ss\w0rd` is silently stored as `p@ssw0rd`. ## What is the new behavior? Unencrypted option values are passed as `format()` `%L` arguments, the same way the encrypted options already supply their secret id, so Postgres escapes each value exactly once. Before and after, on postgres:16: | Value | Before | After | | --- | --- | --- | | `domain\user` | aborts (invalid Unicode escape) | stored `domain\user` | | `p@ss\w0rd` | stored `p@ssw0rd` | stored `p@ss\w0rd` | | `a\b` | stored `a`+backspace | stored `a\b` | ## Additional context Added a unit test in `packages/pg-meta/test/sql/studio/fdw.test.ts` asserting unencrypted options use a `%L` placeholder with the value as a `format()` argument, and that the old double-escaped form is gone. The encrypted-option path is unchanged. <!-- This is an auto-generated comment: release notes by coderabbit.ai --> ## Summary by CodeRabbit * **Bug Fixes** * Improved handling of special characters in foreign data wrapper server option values. * **Tests** * Added test coverage for foreign data wrapper configuration, including edge cases with special characters. <!-- end of auto-generated comment: release notes by coderabbit.ai --> |
||
|
|
c9b8768940 |
fix: cmdk search (#47035)
- closes https://github.com/supabase/supabase/issues/47033 <!-- This is an auto-generated comment: release notes by coderabbit.ai --> ## Summary by CodeRabbit * **New Features** * Table search now matches fully-qualified table names (e.g., `schema.table`) when no specific schema is selected, enabling searches to work seamlessly across all schemas. * **Tests** * Added comprehensive test coverage validating schema-qualified table name matching in search filters. <!-- end of auto-generated comment: release notes by coderabbit.ai --> |
||
|
|
097f220c5c |
Add support for managing stored procedures under database functions (#46977)
## Context Dashboard currently doesn't have any support for managing stored procedures. In the event that the security advisor surfaces a warning about a stored procedure, users hence run into a dead-end as there's currently no way to self-remediate via the dashboard ## Changes involved We're hence adding support for managing stored procedures within Database Functions <img width="1082" height="546" alt="image" src="https://github.com/user-attachments/assets/2598a5fe-e58f-4e8a-ad2f-9cb6d0eb2f53" /> Creating a function now shows a dropdown to select the type <img width="500" alt="image" src="https://github.com/user-attachments/assets/acc9249d-7b25-4416-aae8-89c630e1c62b" /> In which if stored procedure is selected, the following fields will be hidden since they're irrelevant for stored procedures - Return type - Behaviour (Under advanced settings) Some other minor UI changes as well: - Field inputs are re-ordered a little, opting to group "Schema" and "Name" into one section, followed by "Type" and "Return type" - Opting to show "Return type" when editing a function but disabled - Add schema filter for fetching database functions to reduce unnecessary load on the database ## To test - [ ] Can create, update, delete, read stored procedures via database functions page <!-- This is an auto-generated comment: release notes by coderabbit.ai --> ## Summary by CodeRabbit ## Summary - **New Features** - Added PostgreSQL **procedure** support alongside functions, including a **Type** selector in the create/edit flow. - Updated Functions UI with a new **Type** column and procedure-aware return/argument details. - **Improvements** - Refreshed create/edit headers and language help text for clearer context. - Improved argument parsing/display, including better handling of procedure argument modes. - **Bug Fixes** - Corrected routine-type handling during function/procedure delete and update SQL operations. - **Tests** - Updated unit snapshots and end-to-end UI flows/labels for the new “New function” control. <!-- end of auto-generated comment: release notes by coderabbit.ai --> |
||
|
|
aba4e147eb |
Joshen/fe 3613 database tables query should have schema filter wherever appropriate (#46935)
## Context There's certain areas in the dashboard where we're calling `useTablesQuery` without a schema filter, in which case the dashboard then fires a query against the project's database to fetch _all_ tables across _all_ schemas - this could easily be a heavy query if there's a large number of relations in the project's database. Am hence opting to either add a schema filter if appropriate, or otherwise opt to use the infinite loading behaviour ## Changes involved - Add schema filter to `useTablesQuery` in database triggers and publications - Use infinite loading for tables in Cmd K for "Run query on table" and "Search database tables" ## To test - [x] Verify that database triggers + publications still function as expected - [x] Verify that CMD K "Run query on table" and "Search database tables" still function as expected (including search) <!-- This is an auto-generated comment: release notes by coderabbit.ai --> ## Summary by CodeRabbit * **New Features** * Implemented debounced infinite-scrolling table search in the command menu and SQL editor command flow. * Added a schema selector dropdown to publications management for easier navigation. * **Improvements** * Removed the “Schema” column from the publications tables UI. * Updated search guidance and table-picker status (counts/loading) during infinite browsing. * Trigger table listings now follow the selected schema context. * Refined command menu list height and improved the database-tables placeholder text. <!-- end of auto-generated comment: release notes by coderabbit.ai --> |
||
|
|
a4334a2cc7 |
feat(studio): paginate Schema Designer via useInfiniteTablesQuery (#46402)
## I have read the [CONTRIBUTING.md](https://github.com/supabase/supabase/blob/master/CONTRIBUTING.md) file. YES ## What kind of change does this PR introduce? Performance improvement / feature ## What is the current behavior? The Schema Designer fetches all tables in a single request via `useTablesQuery`. For schemas with 400+ tables this blocks first paint on a large payload. ## What is the new behavior? `SchemaGraph` uses `useInfiniteTablesQuery` (pageSize: 100) so the first 100 tables paint immediately. A "Load more tables" button appears above the legend whenever more pages remain, letting users load the rest on demand. ## Additional context <!-- This is an auto-generated comment: release notes by coderabbit.ai --> ## Summary by CodeRabbit * **New Features** * Added a "Find table…" selector and keyboard shortcut to quickly locate and focus tables; supports incremental loading and debounced name search (with literal wildcard handling). * Schema Graph shows a bottom "Load more tables" control with loading state and preserves view after loading more. * **Refactor** * Table listing switched to infinite/paginated retrieval and improved "no tables" logic; server-side name filtering supported. * **Tests** * E2E tests add a schema-visualizer wait helper and update flows to support the paginated visualizer. <!-- review_stack_entry_start --> [](https://app.coderabbit.ai/change-stack/supabase/supabase/pull/46402?utm_source=github_walkthrough&utm_medium=github&utm_campaign=change_stack) <!-- review_stack_entry_end --> <!-- end of auto-generated comment: release notes by coderabbit.ai --> |
||
|
|
426b0183af |
feat(studio): add useInfiniteTablesQuery hook for paginated tables (#46285)
## I have read the [CONTRIBUTING.md](https://github.com/supabase/supabase/blob/master/CONTRIBUTING.md) file. YES ## What kind of change does this PR introduce? Feature — adds a new data-layer hook. No callers are switched over in this PR. ## What is the current behavior? The Schema Designer and Database > Tables list both call `useTablesQuery({ includeColumns: true })`, which fetches the full schema (every table, with every column, every relationship) in one round-trip. For customers with many tables this never loads. Towards FE-3428. ## What is the new behavior? Introduces `useInfiniteTablesQuery` — a cursor-paginated tables hook ready to be consumed by the two pages above in follow-up PRs. - `pg-meta`: new `getTablesPaginatedSql` SQL builder that picks a page of table OIDs first (cheap `pg_class` index scan) and constrains every enrichment CTE (primary keys, relationships, columns) to that set. Pagination is by `c.oid > $afterOid` rather than `OFFSET`, so deep pages stay O(limit). Relationships use a `UNION ALL` keyed by `table_id` so the downstream join is a plain equi-join. - `pg-meta`: `COLUMNS_SQL` is now produced by `getColumnsSql({ filter })`, letting a paginating caller push a table-OID predicate into the WHERE clause directly. The bare `COLUMNS_SQL` export is preserved for the 5 existing callers (`pg-meta-columns`, `pg-meta-tables`, `pg-meta-views`, `pg-meta-materialized-views`, `pg-meta-foreign-tables`). - `studio`: `useInfiniteTablesQuery` wires the new SQL into `useInfiniteQuery` via `executeSql`. `initialPageParam: 0`, `getNextPageParam` returns the last row's `id` or `undefined` on a short last page. - Tests: 12 new tests in `pg-meta` covering cursor invariants (no overlap / no gap), schema filtering, primary-key / relationship / column shape, and output parity against the existing `pgTableZod` schema. ## Additional context <!-- This is an auto-generated comment: release notes by coderabbit.ai --> ## Summary by CodeRabbit * **New Features** * Enabled infinite scrolling for table listings with cursor-based pagination and optional page sizing. * Added an option to include per-table column data in paginated results. * Made column queries filterable for more targeted metadata retrieval. * **Tests** * Added comprehensive tests validating pagination, schema scoping, column inclusion, and relationship/PK shaping. <!-- review_stack_entry_start --> [](https://app.coderabbit.ai/change-stack/supabase/supabase/pull/46285?utm_source=github_walkthrough&utm_medium=github&utm_campaign=change_stack) <!-- review_stack_entry_end --> <!-- end of auto-generated comment: release notes by coderabbit.ai --> |
||
|
|
64143a5d90 |
fix(pg-meta): tighten pg-format keyword() against control-phrase injection (#46076)
## I have read the [CONTRIBUTING.md](https://github.com/supabase/supabase/blob/master/CONTRIBUTING.md) file. YES ## What kind of change does this PR introduce? Bug fix (sanitization hardening). ## What is the current behavior? `pg-format`'s `keyword()` helper validates with `/^[A-Za-z][A-Za-z0-9_ ]*$/`, which allows any space-separated word sequence. Phrases like `'DROP TABLE'` or `'DELETE FROM users'` pass validation and can be interpolated into queries. ## What is the new behavior? `keyword()` accepts either a single word matching `[A-Za-z][A-Za-z0-9_]*` (no spaces) or a phrase from a small case-insensitive allow-list (`'INSTEAD OF'`, `'BY DEFAULT'`) — which covers every multi-word value real callers actually produce (trigger activation, identity generation). Arbitrary multi-word phrases now throw. Tests updated accordingly. ## Additional context <!-- This is an auto-generated comment: release notes by coderabbit.ai --> ## Summary by CodeRabbit * **Bug Fixes** * Reinforced SQL keyword validation with stricter security controls to prevent unsafe keyword usage. The system now only permits single-word identifiers or specific pre-approved multi-word keyword phrases. Previously accepted multi-word inputs that don't match the curated allowlist are now properly rejected with improved error messaging. <!-- review_stack_entry_start --> [](https://app.coderabbit.ai/change-stack/supabase/supabase/pull/46076?utm_source=github_walkthrough&utm_medium=github&utm_campaign=change_stack) <!-- review_stack_entry_end --> <!-- end of auto-generated comment: release notes by coderabbit.ai --> |
||
|
|
e925385415 |
studio,pg-meta: SafeSql for functions/policies/triggers (3/7) (#45990)
## Summary
Third PR in the SafeSql migration stack. Flips the input/output types on
`pgMeta.functions/policies/triggers`'s `.create/.update/.remove` to use
`SafeSqlFragment`, and updates every Studio consumer atomically.
### pg-meta
- `pgMeta.functions/policies/triggers` `.create/.update/.remove` now
return `{ sql: SafeSqlFragment }` and accept branded input parameters
(`PGFunctionCreate`, `PGSavedFunction`, `PolicyCreate/UpdateParams`,
`PGTriggerCreate` with branded condition).
- `QueryModifier.toSql()` returns `SafeSqlFragment`.
### Studio consumers updated to the new branded API
- `data/database-functions/*` (query, create/update/delete mutations)
- `data/database-policies/*` (create, update mutations)
- `data/database-triggers/database-trigger-update-transaction-mutation`
- `components/Database/Triggers/TriggerSheet`
- `components/Database/Functions/CreateFunction`
- `components/Auth/Policies/PolicyEditorPanel`
These consumers land atomically with the pg-meta API change because the
input-type strictness flip (string → `SafeSqlFragment` for SQL fields)
forces every call site to update together.
## Stack
- 1/7: #45897 (merged)
- 2/7: #45903 (merged)
- 3/7: this PR
- 4/7–7/7: upcoming
## Test plan
- [x] `pnpm typecheck` passes
- [x] `pnpm --filter @supabase/pg-meta test` passes
- [x] Dev-server smoke test: function editor, policy editor, trigger
sheet
<!-- This is an auto-generated comment: release notes by coderabbit.ai
-->
## Summary by CodeRabbit
* **Refactor**
* Strengthened SQL safety across policy, function, and trigger workflows
by converting raw SQL strings to typed SQL fragments and safer
composition
* Updated editor behavior to handle policy conditions/checks as typed
SQL fragments with improved initialization and template handling
* Aligned query and modifier interfaces to return typed SQL fragments
for safer composition
* **Tests**
* Updated tests to use typed SQL fragments and synchronous builders
where applicable
<!-- review_stack_entry_start -->
[](https://app.coderabbit.ai/change-stack/supabase/supabase/pull/45990)
<!-- review_stack_entry_end -->
<!-- end of auto-generated comment: release notes by coderabbit.ai -->
|
||
|
|
d79a276824 |
studio: ColumnTypeRef cascade + FK type comparison fixes (2/7) (#45903)
## I have read the [CONTRIBUTING.md](https://github.com/supabase/supabase/blob/master/CONTRIBUTING.md) file. YES ## What kind of change does this PR introduce? Refactor + bug fixes (part of the SafeSql migration stack — PR 2 of 7, stacks on top of #45897). ## What is the current behavior? - `pgMeta.columns.create` and the table-editor SQL builder take column type as a string with array suffix and schema baked in (e.g. `'private.test_enum'`, `'int4[]'`). - The studio table-editor SQL emits the legacy schema-embedded `format` string for enums in non-public schemas, while the pg-meta columns SQL already returns the new shape (bare `format` + separate `format_schema`). The two queries disagree on how to represent the same column, surfacing as a false-positive type mismatch in the FK selector when both ends are an enum from a non-public schema. - The FK selector compares column types by `format` alone — same-named enums in different schemas appear equal, and arrays vs. scalars of the same base type pass the family check. - `displayColumnType` renders arrays as the raw `_typname` pg-meta emits (e.g. `_int4` instead of `int4[]`). ## What is the new behavior? **pg-meta** - Introduce `ColumnTypeRef` (`{ schema?, name, isArray? }`) for column type input, replacing the legacy string-with-array-suffix format. `pgMeta.columns.create` and the table-editor SQL builder consume the new shape. - Add `format_schema` to the column zod schema; pg-meta SQL emits the type's schema for the table editor's ColumnType dropdown. - `pgMeta.columns.create` returns a `SafeSqlFragment`. - Studio table-editor SQL now emits bare `format` + `format_schema`, matching pg-meta's columns SQL. **Studio** - `SafePostgresColumn`/`SafePostgresTable` extend the new `PG*` types (master dropped postgres-meta). - Pipe `ColumnTypeRef` through `SidePanelEditor` → `ColumnEditor` → `TableEditor`, along with the column-create mutation, table retrieve/list queries, and the `TableList`/`ColumnList` surfaces. - `displayColumnType` helper renders arrays as `type[]` (or `schema.type[]`) and handles non-implicit schemas. - FK selector now carries `sourceIsArray`/`targetIsArray` and compares the full `(format, format_schema, isArray)` triple. Family checks for numeric/text/uuid skip when either side is an array (FKs across array boundaries are never compatible). - Type-mismatch and type-notice alerts pass `isArray` to the display helper. - Bundle `Policies.utils` + `Policies.types` + `sql-policy-mutation`, `PolicyEditorModal`, and `SchemaGraph` here because `SidePanelEditor` consumes `acceptGeneratedPolicy`/`AcceptedGeneratedPolicy` — splitting requires temporary overloads with no architectural payoff. ## Additional context Part of the SafeSql migration stack. Stacks on top of #45897. ### Manual test checklist Surfaces touched by this PR — please exercise each: **Table editor** - [x] Create a new table with a mix of column types (scalar, array, enum, foreign key) - [x] Add a column to an existing table; verify the type dropdown lists scalars + arrays separately and shows schema-qualified names for non-public enums - [x] Edit an existing column's type (scalar ↔ array, switch between enums in different schemas) and save - [x] Verify enum types from a non-public schema (e.g. `private.my_enum`) display as `private.my_enum` in the column list **Foreign key selector** - [x] Open the FK selector for a column and pick a target column with a matching type — no mismatch warning - [x] Pick a target column whose type differs only by schema (two same-named enums in different schemas) — should show a type-mismatch alert - [x] Pick a target column where one side is an array and the other is a scalar of the same base type — should show a type-mismatch alert (no auto-cast across array boundary) - [x] When FK target sets the column type, verify `format_schema` and `isArray` are preserved on the source column - [x] Type-mismatch and type-notice alert messages render array types as `type[]` (not `_type`) **Column list / table list** - [x] Schema-qualified type names display correctly for columns whose type lives in a non-public schema - [x] Array columns display as `type[]` (or `schema.type[]`) **Policies (bundled due to import dependency)** - [x] Open the Policies page; create/edit/delete a row-level policy via the modal - [x] Generate a policy via the AI assistant and accept it through `SidePanelEditor` — verify the accepted policy lands in the editor correctly **Schema visualizer** - [x] Open the Schemas → Schema Visualizer page; verify it renders without type errors and shows tables/relationships <!-- This is an auto-generated comment: release notes by coderabbit.ai --> ## Summary by CodeRabbit * **Improvements** * Support for column types in non-public schemas and richer column type presentation (includes schema and array info). * Stronger SQL safety around policies and constraints; draft policy SQL is now promoted explicitly on save. * Improved foreign-key type validation and compatibility checks using enhanced type metadata. * **Tests** * Updated snapshots and tests to reflect new column metadata and SQL fragment handling. <!-- review_stack_entry_start --> [](https://app.coderabbit.ai/change-stack/supabase/supabase/pull/45903) <!-- review_stack_entry_end --> <!-- end of auto-generated comment: release notes by coderabbit.ai --> |
||
|
|
d4079083fc |
chore(studio): drop @supabase/postgres-meta in favor of @supabase/pg-meta (#45844)
## I have read the [CONTRIBUTING.md](https://github.com/supabase/supabase/blob/master/CONTRIBUTING.md) file. YES ## What kind of change does this PR introduce? Refactor / dependency cleanup. ## What is the current behavior? `apps/studio` lists both `@supabase/pg-meta` (workspace package) as a runtime dep and `@supabase/postgres-meta` (external npm package, `^0.64.4`) as a devDependency. The external package is used only for type imports across 44 files — there is no runtime usage and no codegen pipeline that needs it. ## What is the new behavior? Every `Postgres*` type import (`PostgresTable`, `PostgresColumn`, `PostgresPolicy`, `PostgresTrigger`, `PostgresView`, `PostgresMaterializedView`, `PostgresForeignTable`, `PostgresSchema`, `PostgresPublication`, `PostgresRelationship`, `PostgresPrimaryKey`) is replaced with its `PG*` counterpart from `@supabase/pg-meta`, and the external dep is removed from \`apps/studio/package.json\`. Top-level type re-exports were added to \`packages/pg-meta/src/index.ts\` so consumers can import directly from the package root. Two latent issues surfaced by the stricter pg-meta types are also fixed: - \`data/foreign-tables/foreign-tables-query.ts\` was casting foreign-table results as \`PostgresView[]\`; corrected to \`PGForeignTable[]\`. - \`pg-meta\`'s \`PGTrigger\` Zod schema declared \`orientation\`/\`activation\` as \`z.string()\`, inconsistent with pg-meta's own \`getDatabaseTriggerUpdateSQL\` helper that requires the narrow literal unions; tightened to \`z.enum\`. ## Additional context <!-- This is an auto-generated comment: release notes by coderabbit.ai --> ## Summary by CodeRabbit * **Chores** * Updated internal TypeScript type definitions across the codebase to use the latest type system from `@supabase/pg-meta`. * Removed `@supabase/postgres-meta` dependency. * Enhanced type validation for database triggers and schemas to enforce stricter constraints. [](https://app.coderabbit.ai/change-stack/supabase/supabase/pull/45844) <!-- end of auto-generated comment: release notes by coderabbit.ai --> |
||
|
|
116faefcda |
studio: convert more executeSql callers to SafeSqlFragment (#45645)
## Summary - Converts ~27 `executeSql` call sites in `apps/studio/data/**` to build SQL through `safeSql` / `ident` / `literal` / `keyword` / `joinSqlFragments` instead of raw template-string interpolation. - Tightens the `useDatabaseCronJobCreateMutation` and `useDatabaseEventTriggerCreateMutation` `sql`/`query` parameter types from `string` to `SafeSqlFragment` (callers already produce one). - Updates `getDeleteEnumeratedTypeSQL` in `packages/pg-meta` to return `SafeSqlFragment`. - Fixes a bug noticed while testing where Queues integration does not correctly handle queues with uppercase names. ## Pages to manually test - Integrations > Cron Jobs - Integrations > Queues - Database > Triggers > Event Triggers - Database > Indexes - Reports > Query Performance - Storage <!-- This is an auto-generated comment: release notes by coderabbit.ai --> ## Summary by CodeRabbit ## Release Notes * **Bug Fixes** * Queue lookups now correctly handle case-insensitive queue names. * Queue table references are now properly managed and consistently applied throughout the queue management interface. * Improved queue name display normalization in the user interface. * **Chores** * Enhanced SQL query safety across the database layer through parameterized query construction and safer templating approaches. <!-- end of auto-generated comment: release notes by coderabbit.ai --> |
||
|
|
6119e35f78 |
pg-meta: convert last files to use SafeSqlFragment (#45552)
<!-- This is an auto-generated comment: release notes by coderabbit.ai --> ## Summary by CodeRabbit * **Refactor** * Enhanced safety of database query generation for publication and table definition operations. <!-- end of auto-generated comment: release notes by coderabbit.ai --> |
||
|
|
0433eeb5f5 |
feat(studio): mark sql provenance for safety (#45336)
Mark provenance of SQL via the branded types SafeSqlFragment and UntrustedSqlFragment. Only SafeSqlFragment should be executed; UntrustedSqlFragments require some kind of implicit user approval (show on screen + user has to click something) before they are promoted to SafeSqlFragment. <!-- This is an auto-generated comment: release notes by coderabbit.ai --> ## Summary by CodeRabbit * **New Features** * Editor and RLS tester show loading states for inferred/generated SQL and include a dedicated user SQL editor for safer edits. * **Refactor** * Platform-wide SQL handling tightened: snippets and AI-generated SQL are treated as untrusted/display-only until promoted, improving safety and consistency. <!-- end of auto-generated comment: release notes by coderabbit.ai --> |
||
|
|
73cdf2ddd1 |
fix(pg-meta): include schema in pg_indexes join to avoid cross-schema index collisions (#45374)
## I have read the CONTRIBUTING.md file. YES ## What kind of change does this PR introduce? Bug fix ## What is the current behavior? The query in `sql/indexes.ts` joins `pg_class` with `pg_indexes` using only the index name: ```sql JOIN pg_indexes ix ON c.relname = ix.indexname ``` This can lead to incorrect results when multiple schemas contain indexes with the same name. PostgreSQL allows identical index names across different schemas, so this join may return the wrong index_definition. ## What is the new behavior? The join condition now includes the schema name: ```sql JOIN pg_indexes ix ON c.relname = ix.indexname AND n.nspname = ix.schemaname ``` This ensures the correct index_definition is retrieved for each index, even when duplicate index names exist across schemas. ## Additional context - Added a test case to verify behavior when the same index name exists in multiple schemas. - This change prevents cross-schema collisions and ensures accurate index metadata retrieval. <!-- This is an auto-generated comment: release notes by coderabbit.ai --> ## Summary by CodeRabbit * **Bug Fixes** * Improved index listing so indexes that share the same name in different schemas are correctly distinguished and reported. * **Tests** * Added a regression test ensuring indexes with identical names in separate schemas are both detected and contain expected schema-qualified references. <!-- end of auto-generated comment: release notes by coderabbit.ai --> --------- Co-authored-by: Charis Lam <26616127+charislam@users.noreply.github.com> |
||
|
|
f051c6a1c1 |
refactor(pg-meta): consolidate test scripts and support parallel test runs across worktrees (#45340)
## I have read the [CONTRIBUTING.md](https://github.com/supabase/supabase/blob/master/CONTRIBUTING.md) file. YES ## What kind of change does this PR introduce? Refactor of the pg-meta test setup scripts. ## What is the current behavior? The test command runs multiple sequential npm-run-s scripts (`db:clean`, `db:run`, `test:run`, `db:clean`) with a hardcoded port 5432, causing container name and port collisions when running tests across multiple git worktrees in parallel. ## What is the new behavior? A single `test/run-tests.sh` wrapper script handles the full test lifecycle: it finds an available port dynamically (scanning 5432–5531), sets a unique Docker Compose project name based on a hash of the package directory path, starts the DB, runs the test command, and tears down on exit. This allows pg-meta tests to run in parallel across multiple worktrees without conflicts. ## Additional context <!-- This is an auto-generated comment: release notes by coderabbit.ai --> ## Summary by CodeRabbit * **Chores** * Streamlined test execution to centralize setup and teardown for reliable runs. * Made the test database port configurable with automatic local port discovery and fail-fast behavior. * Created isolated test environments per workspace to avoid container/name collisions and improve cleanup. <!-- end of auto-generated comment: release notes by coderabbit.ai --> |
||
|
|
a8de56aec2 |
fix(pg-meta): require replica_identity_index when replica_identity is INDEX (#45019)
## I have read the CONTRIBUTING.md file. YES ## What kind of change does this PR introduce? Bug fix ## What is the current behavior? When updating a table with `replica_identity = 'INDEX'`, it is possible to omit the `replica_identity_index`. This results in invalid SQL being generated: `REPLICA IDENTITY USING INDEX` PostgreSQL requires an index name for this operation. No existing issue found. This PR fixes a validation gap discovered during development. ## What is the new behavior? - Throws an error if `replica_identity` is set to `INDEX` without providing `replica_identity_index` - Ensures generated SQL is always valid ## Additional context - Added validation in `pg-meta-tables.ts` - Added test case to verify an error is thrown when the index name is missing This aligns pg-meta behavior with PostgreSQL requirements for `REPLICA IDENTITY USING INDEX`. <!-- This is an auto-generated comment: release notes by coderabbit.ai --> ## Summary by CodeRabbit ## Release Notes * **Bug Fixes** * Enhanced validation for database replica identity configuration to prevent incomplete or invalid configurations. * **Tests** * Added test coverage for replica identity validation scenarios. <!-- end of auto-generated comment: release notes by coderabbit.ai --> |
||
|
|
5f867e5f6c |
Feature Preview: RLS Tester (#45121)
## Context Resolves FE-3077 Related discussion: https://github.com/orgs/supabase/discussions/45233 Verifying the correctness of your RLS policies set up has always been a gap, as highlighted by a number of GitHub discussions like [here](https://github.com/orgs/supabase/discussions/12269) and [here](https://github.com/orgs/supabase/discussions/14401). As such, we're piloting a dedicated UI for RLS testing (using role impersonation as the base), in which you'll be able to - Run a SQL query as a user (not logged in / logged in - this is the role impersonation part) - See which RLS policies are being evaluated as part of the query - And hopefully be able to debug which policies are not set up correctly Changes are currently set as a feature preview - and we'll iterate as we get feedback from everyone 🙂 🙏 <img width="613" height="957" alt="image" src="https://github.com/user-attachments/assets/83c37f8a-28fc-43b3-b0ff-e28571d8710c" /> <!-- This is an auto-generated comment: release notes by coderabbit.ai --> ## Summary by CodeRabbit * **New Features** * RLS Tester: run queries as anon or authenticated users, view inferred SQL, per-table policy summaries, and data previews of accessible rows. * UI preview: new RLS Tester preview card and modal with opt-in toggle; RLS Tester sheet with role/user selector and query editor. * SQLEditor: “Explain” tab is always visible. * **Chores** * Added supporting API endpoints, background checks for table RLS status, and a local-storage flag to persist the preview opt-in. <!-- end of auto-generated comment: release notes by coderabbit.ai --> |
||
|
|
67deabf67e |
fix: create etl publication as postgres (#45043)
## What kind of change does this PR introduce? Bug fix ## What is the current behavior? Creating a schema only branch fails because ETL publication is owned by `supabase_etl_admin` which users have no access. ## What is the new behavior? Since ETL supports user managed publications, create them through pgmeta so it's owned by `postgres` role instead. ## Additional context mirrors [upstream etl](https://github.com/supabase/etl/blob/main/etl-api/src/db/publications.rs#L22-L51) implementation <!-- This is an auto-generated comment: release notes by coderabbit.ai --> ## Summary by CodeRabbit * **Bug Fixes** * Added guards to prevent creating publications when project or connection info is missing, with clearer error logging. * Ensure the project connection string is explicitly passed so publications target the correct database. * **Refactor** * Publication creation now executes generated SQL directly against the database, with correct handling of empty or selected table lists and proper identifier quoting for reliability. <!-- end of auto-generated comment: release notes by coderabbit.ai --> --------- Co-authored-by: Joshen Lim <joshenlimek@gmail.com> Co-authored-by: coderabbitai[bot] <136622811+coderabbitai[bot]@users.noreply.github.com> Co-authored-by: CodeRabbit <noreply@coderabbit.ai> |
||
|
|
4afbe9c2b2 |
feat: lint integration for pg_graphql introspection + SECURITY DEFINER functions (#45260)
## I have read the [CONTRIBUTING.md](https://github.com/supabase/supabase/blob/master/CONTRIBUTING.md) file. YES ## What kind of change does this PR introduce? Feature — wires up three new advisor lints landed in splinter, and updates the self-hosted SQL bundle for the existing `pg_graphql_anon_table_exposed` lint to track splinter's correctness fixes. Companion to `supabase/splinter` #160 (already merged) and #162 (test fix in flight). ## What is the current behavior? Splinter's `main` now exposes four lints in the pg_graphql / SECURITY DEFINER family: - `pg_graphql_anon_table_exposed` (0026, existing) — wired into Studio in #45253; SQL in `packages/pg-meta` is the original version that uses `has_table_privilege` and the relkind set `('r','p','v','m')`. - `pg_graphql_authenticated_table_exposed` (0027, new) — paired check against the `authenticated` role. Studio renders any new finding without a `lintInfoMap` entry as a row with no icon, no title mapping, and no "Fix" CTA. Self-hosted users do not see the lint at all because `packages/pg-meta` does not include it. - `anon_security_definer_function_executable` (0028, new) — `SECURITY DEFINER` function executable by `anon`. Same Studio + self-hosted gaps as 0027. - `authenticated_security_definer_function_executable` (0029, new) — same against `authenticated`. Splinter has also updated 0026 itself (PR #160) in two ways that need to flow into the self-hosted SQL bundle: 1. **`relkind` filter:** `('r','p','v','m')` → `('r','v','m','f')`. Drops partitioned table roots (pg_graphql does not expose them; their leaf partitions are still covered as `'r'`) and adds foreign tables, which pg_graphql does expose. 2. **Privilege predicate:** `has_table_privilege(role, oid, 'SELECT')` → `EXISTS` over `pg_attribute` calling `has_column_privilege`. Catches column-level grants such as `GRANT SELECT (col) ON t TO anon`, which pg_graphql's introspection exposes but `has_table_privilege` missed. Cloud projects auto-fetch `splinter.sql` via the platform mgmt-api's `getLintSql` (1-hour cache TTL), so they pick up #160's lint and SQL changes independently of this PR. This PR is about the Studio display mapping and the self-hosted SQL bundle. ## What is the new behavior? Two minimal additions, mirroring the integration shape of #45253. ### `apps/studio/components/interfaces/Linter/Linter.utils.tsx` Three new entries appended to `lintInfoMap`: - `pg_graphql_authenticated_table_exposed` — `Eye` icon (paired with the existing `pg_graphql_anon_table_exposed` entry); link points to the Table Editor scoped to `metadata.schema` + `metadata.name`; `linkText: 'View object'`; `category: 'security'`. - `anon_security_definer_function_executable` — `Unlock` icon (signals "this thing is callable when it shouldn't be"); link points to the Database Functions browser scoped to `metadata.schema` + `metadata.name`; `linkText: 'View function'`; `category: 'security'`. - `authenticated_security_definer_function_executable` — same as 0028 against `authenticated`. Each entry's `docsLink` points at the splinter-hosted lint doc. ### `packages/pg-meta/src/sql/studio/advisor/lints.ts` The existing `pg_graphql_anon_table_exposed` SQL block is updated in place to match the new splinter version: new `relkind` set, `case` statement for `'f'`, and the `EXISTS` over `pg_attribute` privilege check. Three new `union all` blocks are appended for 0027/0028/0029. The function lints (0028/0029) include the `pgrst.db_schemas` filter (mirroring lint `0023_sensitive_columns_exposed`) so findings are scoped to schemas PostgREST actually exposes; the self-hosted query wrapper already sets the GUC when `exposedSchemas` is passed (`enrichLintsQuery`). ## Coverage of the four exposure paths | Role | Tables/views/MVs/foreign tables | SECURITY DEFINER functions | |------|---------|----------| | `anon` | 0026 (existing, updated) | 0028 (new) | | `authenticated` | 0027 (new) | 0029 (new) | The 0026/0027 pair covers `pg_graphql` introspection visibility; the 0028/0029 pair covers RLS bypass via privileged function execution through `/rest/v1/rpc` (and `/graphql/v1` for compatible return types). Each lint's doc cross-references its sibling so an operator hitting one is steered toward the others. ## Verification - `cd packages/pg-meta && npx tsc --noEmit` — clean. - `cd apps/studio && npx tsc --noEmit` — clean for the changed file. (Other unrelated TS errors exist in the working tree but are pre-existing and not introduced by this PR.) - `cd apps/studio && npx eslint components/interfaces/Linter/Linter.utils.tsx` — clean. ## Files - `apps/studio/components/interfaces/Linter/Linter.utils.tsx` — adds three `lintInfoMap` entries (0027, 0028, 0029). - `packages/pg-meta/src/sql/studio/advisor/lints.ts` — updates the 0026 SQL block to match splinter's correctness fixes, appends 0027/0028/0029 SQL blocks. ## Related - supabase/splinter#160 — adds 0027/0028/0029 and rewrites 0026 (merged). - supabase/splinter#162 — fixes test setup for 0028/0029 (in flight; does not affect the SQL shipped here). - supabase/supabase#45253 — original 0026 Studio integration. <!-- This is an auto-generated comment: release notes by coderabbit.ai --> ## Summary by CodeRabbit * **New Features** * Added security linting to detect authenticated-table exposure and executable SECURITY DEFINER functions. * Added signed-in visibility checks alongside anonymous checks. * **Bug Fixes / Improvements** * Improved relation type handling for accurate table/foreign/partition classification. * Switched to column-level privilege analysis for visibility. * Improved entity naming shown in lints (includes function argument display). <!-- end of auto-generated comment: release notes by coderabbit.ai --> --------- Co-authored-by: Danny White <3104761+dnywh@users.noreply.github.com> |
||
|
|
801b912fc8 |
feat: lint for pg_graphql introspection fix (#45253)
## I have read the [CONTRIBUTING.md](https://github.com/supabase/supabase/blob/master/CONTRIBUTING.md) file. YES ## What kind of change does this PR introduce? Feature — wires up the new advisor lint `pg_graphql_anon_table_exposed` so it renders properly in Studio and ships with self-hosted Supabase. The lint itself was added to splinter in supabase/splinter#158 (already merged). ## What is the current behavior? Splinter's `main` exposes lint `0026_pg_graphql_anon_table_exposed`, which detects tables, views, and materialized views whose schema is visible through the public `/graphql/v1` introspection endpoint when the `anon` role has `SELECT` on them. The hosted advisor (mgmt-api) auto-fetches `splinter.sql` from raw.githubusercontent.com, so the lint will start firing on cloud projects, but: - Studio has no `lintInfoMap` entry for it, so the row renders without an icon, title mapping, "Fix" CTA, or category classification. - Self-hosted Supabase ships with a vendored copy of the lint SQL in `packages/pg-meta`; without an update there, self-hosted users never see the lint at all. ## What is the new behavior? Two minimal additions: - **`apps/studio/components/interfaces/Linter/Linter.utils.tsx`** — adds a `lintInfoMap` entry for `pg_graphql_anon_table_exposed`: title `"pg_graphql Anon Role Exposes Objects in Introspection"`, `Eye` icon, `security` category, `"View object"` CTA pointing at the table editor scoped by `metadata.schema` and `metadata.name`, docs link to the splinter docs page. - **`packages/pg-meta/src/sql/studio/advisor/lints.ts`** — vendors the lint's SQL block into `getLintsSQL()` so self-hosted deployments include it. Follows the file's documented copy-paste convention from splinter: every backtick inside SQL string literals is escaped (`` ` `` → `` \` ``), and the hardcoded docs URL is replaced with `${literal(\`${docsUrl}/...\`)}`. No changes to the OpenAPI surface, no changes to the `LINT_TYPES` literal union (auto-generated; matches the precedent of how lints 0023–0025 were added — Studio's `LintInfo.name` is typed as `string`, not the strict enum). ## Additional context - Splinter PR (merged): https://github.com/supabase/splinter/pull/158 - Splinter lint source: https://github.com/supabase/splinter/blob/main/lints/0026_pg_graphql_anon_table_exposed.sql - Splinter docs page: https://github.com/supabase/splinter/blob/main/docs/0026_pg_graphql_anon_table_exposed.md - The hosted advisor flow that fetches splinter.sql automatically lives in the platform mgmt-api (`getLintSql` in `advisors-utils.ts`), with a 1-hour cache TTL — cloud projects will pick up the new lint independently of this PR; this PR is about the Studio display mapping and the self-hosted SQL bundle. <!-- This is an auto-generated comment: release notes by coderabbit.ai --> ## Summary by CodeRabbit * **New Features** * Added a new security linter check that identifies tables and views exposed to anonymous GraphQL access, with warnings and remediation guidance to help resolve the issue. <!-- end of auto-generated comment: release notes by coderabbit.ai --> |
||
|
|
2e3ddc3a52 |
fix: csv seq sync (#45076)
## TL;DR fixes csv imports with explicit id values leaving auto generated primary keys out of sync by resolving the primary key sequence correctly after import ## ex: | Before | After | | --- | --- | | <img width="378" height="201" alt="Before: stale sequence after CSV import" src="https://github.com/user-attachments/assets/34c827f5-c69b-4c05-aa67-9fb6fd65a040" /> | <img width="435" height="196" alt="After: sequence synced after CSV import" src="https://github.com/user-attachments/assets/bb84f286-1b3e-44a5-965b-5f2faa3f7622" /> | ## ref: - closes https://github.com/supabase/supabase/issues/45073 <!-- This is an auto-generated comment: release notes by coderabbit.ai --> ## Summary by CodeRabbit ## Release Notes * **Bug Fixes** * Fixed identity sequence synchronization during CSV imports. After spreadsheet data is inserted, the system now properly updates sequence values, ensuring subsequent rows receive correct identifiers. <!-- end of auto-generated comment: release notes by coderabbit.ai --> |
||
|
|
e1bd0c791f |
convert migrations and privileges sql utils to use safesql (#45070)
<!-- This is an auto-generated comment: release notes by coderabbit.ai --> ## Summary by CodeRabbit * **Refactor** * Enhanced SQL query generation for database migrations and privilege management with improved parameterization and type safety. * Strengthened security and robustness of database operations through modernized SQL building patterns. <!-- end of auto-generated comment: release notes by coderabbit.ai --> |
||
|
|
bff92df845 |
convert fdw sql utilities to safesql (#45069)
<!-- This is an auto-generated comment: release notes by coderabbit.ai --> ## Summary by CodeRabbit * **Bug Fixes** * Improved SQL query handling for vector bucket creation and Foreign Data Wrapper operations <!-- end of auto-generated comment: release notes by coderabbit.ai --> |
||
|
|
62d59d596b |
convert advisor and auth queries in pgmeta to safesql (#44998)
<!-- This is an auto-generated comment: release notes by coderabbit.ai --> ## Summary by CodeRabbit * **Refactor** * Improved SQL construction across the studio to make queries safer and more consistent. * Safer parameter handling for optional schema and remediation links to prevent injection risks. * Deterministic query header formatting and stable date/comments in generated SQL. * More robust user-count and paginated-user queries for accurate counts, sorting and pagination. * Updated tests to align with the new safe query handling. <!-- end of auto-generated comment: release notes by coderabbit.ai --> |
||
|
|
8c4ae77ece |
fix: enum quotes (#45023)
## TL;DR
fixes enum create/update failures when names contain quotes
(also added a smol e2e)
## Ex:
<table>
<tr>
<td><strong>Before</strong></td>
<td><strong>After</strong></td>
</tr>
<tr>
<td>
<img width="424" height="178" alt="Before"
src="https://github.com/user-attachments/assets/d1815f4e-3879-4f8d-8d24-40d2c1f5563d"
/>
</td>
<td>
<img width="233" height="75" alt="After fix"
src="https://github.com/user-attachments/assets/f3f9b53c-b234-4e18-9b2d-db97ca4713d5"
/>
</td>
</tr>
</table>
## ref:
- closes https://github.com/supabase/supabase/issues/45022
<!-- This is an auto-generated comment: release notes by coderabbit.ai
-->
## Summary by CodeRabbit
* **Bug Fixes**
* Fixed enumerated type description handling to preserve special
characters (quotes and apostrophes) without unintended escaping.
* **Tests**
* Extended enumerated types test coverage to include creation, updates,
and deletion of types with special characters in names and descriptions.
<!-- end of auto-generated comment: release notes by coderabbit.ai -->
|
||
|
|
8f69a10cc9 |
fix(studio): reliable schema-aware SQL editor AI completions (#44730)
A variety of fixes and improvements to the Cmd+K AI completions endpoint in the [SQL Editor](https://supabase.com/dashboard/project/_/sql/new): - Pre-load table definitions for the public schema and any other schemas referenced in the editor, so the model has real column names without needing to fetch them dynamically - Replace the generic tool suite with a single streamlined `getSchemaDefinitions` tool the model can still call to look up additional schemas on demand without behavior differences across platform & self-hosted - Swap generic chat system prompt for a purpose-built `COMPLETION_PROMPT`; fix role (`assistant` → `user`) for consistency with other endpoints - Validate and type the request body with `zod`, which was previously untyped (`any`) - Improve Cmd+K behavior when nothing is selected — use the full editor content as context, return the complete query rather than just the changed fragment, and switch to a generation mode when the editor is blank - Escape single quotes in schema names when fetching entity definitions in `pg-meta` to prevent schema names from breaking out of the SQL string and injecting arbitrary content into the prompt ## Before Before, the SQL Editor would often hallucinate tables / columns that don't exist in the user's database making it less helpful if you don't know the exact table/column names. Even with maximum Assistant opt-in level on the org, it would often fail to call the necessary tools to gather database context. <img width="5062" height="1522" alt="image" src="https://github.com/user-attachments/assets/fbe1130f-6b5a-41a8-99d7-7268880af188" /> <img width="2540" height="658" alt="image" src="https://github.com/user-attachments/assets/a31c2967-7751-4fce-a9b7-60bd77660b1a" /> Sometimes it also silently fails and generates empty queries: <img width="1352" height="398" alt="CleanShot 2026-04-09 at 17 46 06@2x" src="https://github.com/user-attachments/assets/e17c103a-d47d-47e6-8c2e-101f0fae5651" /> Or echos back the user's prompt: <img width="1368" height="282" alt="CleanShot 2026-04-09 at 23 04 56@2x" src="https://github.com/user-attachments/assets/7dff6e64-f54e-45b5-8e86-5399e5a2fe41" /> ## After In this example, the completion correctly interpreted my request for "completed" todos as a query on the `completed_foo` column in my `public` schema, instead of assuming existence of a `completed` column. <img width="1452" height="838" alt="CleanShot 2026-04-09 at 17 43 13@2x" src="https://github.com/user-attachments/assets/7a575589-78b4-448d-810a-0330ff08ef8b" /> In this example, the completion was correctly aware of an `other` schema because it was detected in my existing query. I didn't have to select the text, it included the full query in context when unselected. Notice how it correctly used the `is_done` column when I asked for "completed" cakes: <img width="1372" height="534" alt="CleanShot 2026-04-09 at 17 39 07@2x" src="https://github.com/user-attachments/assets/e6b7eb6f-f3e8-4fa1-90a3-b5e34ddc14e4" /> Supersedes #44151 Closes AI-544 |
||
|
|
b1531545fb |
security: migrate more files to safeSql (#44727)
<!-- This is an auto-generated comment: release notes by coderabbit.ai --> ## Summary by CodeRabbit * **Refactor** * Overhauled SQL generation across the Studio: queries and helpers now use safer, parameterized SQL construction for more robust and consistent behavior. * **Bug Fixes** * Improved trigger update flow so event values are normalized before saving, reducing errors when modifying webhooks/triggers. <!-- end of auto-generated comment: release notes by coderabbit.ai --> |
||
|
|
fdf8732727 |
fix: Include security_invoker in definition (#44936)
## TL;DR the table editor definition panel was showing incomplete SQL for views with `WITH (security_invoker = true)` ignoring the reloption and making it easy to accidentally strip it when recreating the view ## prob When viewing a security invoker view in the Table Editor, the Definition panel only showed `CREATE VIEW ... AS ...` without the `WITH (security_invoker = true)` clause which caused two issues: 1. the displayed SQL was incomplete and didn't match the actual view definition 2. users copying the SQL to recreate the view would unintentionally lose the security_invoker setting ## ex: | Before | After | |--------|-------| | `create view public.exposed_api as`<br>`select id, secret from public.rls_protected_table;` | `create view public.exposed_api with (security_invoker = true) as`<br>`select id, secret from public.rls_protected_table;` | ## ref: - closes https://github.com/supabase/supabase/issues/44934 <!-- This is an auto-generated comment: release notes by coderabbit.ai --> ## Summary by CodeRabbit * **New Features** * View definitions now show the full CREATE statement (including materialized views and WITH (...) options) and preserve security options like security_invoker when viewed or opened in the SQL editor. * **Tests** * Added end-to-end test verifying security option preservation in view definitions and when opening them in the SQL editor. <!-- end of auto-generated comment: release notes by coderabbit.ai --> |
||
|
|
1b1d05ff96 |
chore: upgrade vite to v8 and vitest to v4 (#44833)
Upgrade vite and vitest to their latest major versions across the
monorepo, along with related packages.
**Changed:**
- `vite` catalog: `^7.3.2` → `^8.0.8` (Rolldown replaces esbuild/Rollup)
- `vitest` catalog: `^3.2.0` → `^4.1.4`
- `@vitejs/plugin-react`: `^4.3.4` → `^6.0.1`
- `@vitest/coverage-v8`: `^3.2.0` → `^4.1.4`
- `@vitest/ui`: `^3.2.0` → `^4.1.4`
- `vite-tsconfig-paths`: `^4.3.2` / `^5.1.4` → `^6.1.1`
**Pinned to vite 7:**
- `apps/lite-studio` — `@react-router/dev` hasn't declared vite 8
support yet
- `blocks/vue` — Nuxt plugins (`vite-plugin-inspect`, `vite-dev-rpc`,
`vite-hot-client`, `vite-plugin-vue-tracer`) haven't declared vite 8
support yet
**Test fixes for vitest 4 breaking changes:**
- **`apps/studio/lib/api/snippets.utils.test.ts`** — Replaced
`vi.mock('fs/promises')` automock with an explicit factory. Vitest 4's
automocking doesn't create mock functions for getter-based exports on
Node built-ins, so `mockedFS.access.mockResolvedValue` etc. were
`undefined`.
- **`apps/studio/lib/api/self-hosted/functions/index.test.ts`** —
Changed `mockReturnValue` to `mockImplementation(function() { ... })`
for a constructor mock. Vitest 4 no longer allows `mockReturnValue` when
the mock is called with `new`.
- **`apps/studio/tests/pages/api/mcp/index.test.ts`** — Changed arrow
function to regular `function` in `mockImplementation` for
`StreamableHTTPServerTransport`. Arrow functions can't be constructors,
and vitest 4 now enforces this.
- **`packages/ui-patterns/vitest.setup.ts`** — Changed `ResizeObserver`
mock from arrow function to regular `function` for the same constructor
enforcement reason. This was crashing Radix popover rendering in jsdom.
## To test
- `pnpm test:studio` — all 226 test files should pass
- `pnpm --filter ui-patterns vitest run` — all 183 tests should pass
- `pnpm --filter www test -- --run` — all 19 tests should pass
- `pnpm --filter ui vitest run` — all tests should pass
- `pnpm --filter dev-tools vitest run` — all tests should pass
- `pnpm --filter ai-commands vitest run` — all tests should pass
<!-- This is an auto-generated comment: release notes by coderabbit.ai
-->
## Summary by CodeRabbit
* **Chores**
* Standardized and updated development tooling versions and version
sources for consistent installs across the repo (Vite, Vitest,
vite-tsconfig-paths and related plugins/catalog entries).
* **Tests**
* Improved test mocks and typings (updated mock
factories/implementations and tightened spy/type assertions) to increase
test reliability and compatibility with updated tooling.
<!-- end of auto-generated comment: release notes by coderabbit.ai -->
---------
Co-authored-by: Alaister Young <10985857+alaister@users.noreply.github.com>
|
||
|
|
83e5ee8c5c |
feat(studio): add advisor for public bucket rls (#44438)
## I have read the [CONTRIBUTING.md](https://github.com/supabase/supabase/blob/master/CONTRIBUTING.md) file. YES ## What kind of change does this PR introduce? This connects the Advisor from the splinter repo. Below are the list of changes: - Register advisor which should appear in both the legacy Advisors and Advisors sidebar. - Adds a "Dismiss" button to the admonition inside the bucket view. - Makes the check for select policy on public buckets tiny bit stricter/truer. This is awaiting the [PR](https://github.com/supabase/splinter/pull/152) in splinter going in! <!-- This is an auto-generated comment: release notes by coderabbit.ai --> ## Summary by CodeRabbit * **New Features** * Added a security lint that flags public storage buckets allowing listing, with a direct "View bucket" link. * Users can dismiss public-bucket warnings per project+bucket for 14 days via a Dismiss button. * **Improvements** * Tightened policy detection to better target bucket-scoped select policies and avoid unrelated matches. * **Telemetry** * Added events for policy removal and dismiss-button clicks. <!-- end of auto-generated comment: release notes by coderabbit.ai --> --------- Co-authored-by: Danny White <3104761+dnywh@users.noreply.github.com> Co-authored-by: Claude Sonnet 4.6 <noreply@anthropic.com> |
||
|
|
5d013cb2f6 |
refactor(pg-meta): expand safeSql usage (#44674)
<!-- This is an auto-generated comment: release notes by coderabbit.ai --> ## Summary by CodeRabbit * **Refactor** * Standardized SQL construction across the pg-meta package to use parameter-safe SQL fragments instead of raw string assembly, improving safety for dynamic values (filters, limits, offsets, identifiers) and unifying how exported SQL constants and query helpers are produced. No functional query behavior changes expected. <!-- end of auto-generated comment: release notes by coderabbit.ai --> |