## 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 -->
## 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>
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>
Fixes a batch of production Studio crashes from Sentry (all caught by
the global error boundary). Most are missing array/null guards where an
endpoint typed as an array — or with a nested array field — returned a
non-array body in production; a few are one-off render crashes.
Resolves FE-3748.
## Issues fixed
| Sentry | Error | Fix |
| --- | --- | --- |
| [J7R](https://supabase.sentry.io/issues/7492997940/) | Maximum update
depth exceeded | Disable RadialBar animation in disk-cooldown countdown
|
| [JR5](https://supabase.sentry.io/issues/7548484681/) |
resourceWarnings.find is not a function | Guard in
ResourceExhaustionWarningBanner |
| [JCJ](https://supabase.sentry.io/issues/7506024989/) |
resourceWarnings.find is not a function | Guard in ProjectLayout +
normalize query |
| [K1Y](https://supabase.sentry.io/issues/7584792331/) | snippet.name on
undefined | Optional-chain SQL editor download filename |
| [B3K](https://supabase.sentry.io/issues/7141649636/) |
pagination.count on undefined | Guard pagination in projects infinite
query |
| [JVP](https://supabase.sentry.io/issues/7560437621/) | schemas.some /
extensions.find | Coerce pg-meta lists to arrays in
useInstalledIntegrations |
| [JR2](https://supabase.sentry.io/issues/7548339272/) | extensions.find
is not a function | (same fix as JVP) |
| [JQR](https://supabase.sentry.io/issues/7547163939/) | lints.filter is
not a function | Normalize project lints query |
| [JR3](https://supabase.sentry.io/issues/7548433501/) |
entitlements.find is not a function | Guard call sites + normalize
entitlements query |
| [JQS](https://supabase.sentry.io/issues/7547557098/) |
selected_addons.find is not a function | Normalize addons query arrays |
<!-- This is an auto-generated comment: release notes by coderabbit.ai
-->
## Summary by CodeRabbit
* **Bug Fixes**
* Improved stability across several Studio screens by handling missing
or unexpected data more safely.
* Downloads now use a fallback name when a snippet name isn’t available.
* Project, entitlement, schema, addon, warning, and extension views are
less likely to break when data is missing or not in the expected format.
* Pagination and countdown visuals now behave more consistently, with
reduced chance of runtime errors or animation-related glitches.
<!-- end of auto-generated comment: release notes by coderabbit.ai -->
---------
Co-authored-by: Ivan Vasilov <vasilov.ivan@gmail.com>
## Problem
There's still more unused code in the repository which slows down
everything:
- checkouts
- tooling
- probably builds (not sure how good turbopack is at handling this)
## Solution
- remove old unused code
- remove more recent code after checking git history to ensure it's not
unfinished/ongoing work
<!-- This is an auto-generated comment: release notes by coderabbit.ai
-->
## Summary by CodeRabbit
* **Chores**
* Removed several outdated UI components and helper utilities to
streamline the app.
* Cleaned up unused analytics, database, and observability hooks and
queries.
* **Refactor**
* Simplified data table, unified logs, and assistant panel internals by
removing legacy display and navigation pieces.
* **Bug Fixes**
* Reduced the chance of showing stale or inconsistent status, chart, and
metric views by eliminating obsolete display paths.
<!-- end of auto-generated comment: release notes by coderabbit.ai -->
## 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 -->
## Context
Just some clean up as I was going through stuff
- `useExecuteSqlQuery` is deprecated and not used at all
- As such `execute-sql-query` is technically irrelevant, the more
relevant file is `execute-sql-mutation`
- Hence opting to consolidate `execute-sql-query` into
`execute-sql-mutation`
- Also removing `ExecuteSqlError` since its just re-exporting the
`ResponseError` type
There's a lot of file changes but its essentially just updating the
importing statements across the files
## Summary
Part 4 of the SafeSql migration stack
([#45897](https://github.com/supabase/supabase/pull/45897),
[#45903](https://github.com/supabase/supabase/pull/45903),
[#45990](https://github.com/supabase/supabase/pull/45990), this PR, …).
Converts the remaining reports, query performance, observability, index
advisor, and privileges call sites of `executeSql` to produce
`SafeSqlFragment` values. The `ReportQuery.sql` field flips from
`string` to `SafeSqlFragment`, which cascades into every consumer —
landed here atomically so each branch typechecks cleanly.
Touched areas:
- `interfaces/Reports/*` — `ReportQuery.sql: SafeSqlFragment`, plus all
report definitions/utilities updated
- `interfaces/QueryPerformance/useQueryPerformanceQuery.ts`
- `interfaces/Database/IndexAdvisor/*` and
`data/database/{table-index-advisor,retrieve-index-advisor-result}-query.ts`
-
`data/privileges/{table-api-access,update-exposed-entities}-mutation.ts`
- `interfaces/Storage/StoragePolicies/StoragePolicies.tsx`
- `hooks/analytics/useDbQuery.tsx`
- `Observability/useSlowQueriesCount.ts` +
`useQueryInsightsIssues.utils.test.ts`
## Test plan
- [x] `pnpm typecheck` passes
- [x] `useQueryInsightsIssues.utils.test.ts` passes
- [x] Dev-server smoke test: reports pages, query performance, index
advisor, storage policies
<!-- This is an auto-generated comment: release notes by coderabbit.ai
-->
## Summary by CodeRabbit
* **Refactor**
* Reworked SQL construction and typings across reporting, query
performance, index advisor, and privilege features to use safer SQL
fragments, improving reliability and preventing query composition
issues.
* **Types**
* Reporting query types were split to distinguish database vs. logs
queries, enabling correct handling and validation.
* **Docs/Utils**
* Added a helper to consistently generate logs SQL for report hooks.
* **Tests**
* Updated tests to exercise the new SQL-building API.
<!-- review_stack_entry_start -->
[](https://app.coderabbit.ai/change-stack/supabase/supabase/pull/45998)
<!-- review_stack_entry_end -->
<!-- end of auto-generated comment: release notes by coderabbit.ai -->
## 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 -->
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 -->
## 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 -->
## 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 -->
Fixes#44586
The `enabled` field in `useGetIndexAdvisorResult` had an OR branch that
bypassed the `enabled` prop for queries starting with `with
pgrst_source`. This meant the query could fire even when `enabled:
false` was passed (e.g. when the index_advisor extension isn't installed
or the result is already prefetched).
Restructures the logic to match the sibling hook in
`retrieve-index-from-select-query.ts`, which correctly ANDs `enabled`
with all conditions using an extracted `isValidQueryForIndexing`
variable.
<!-- This is an auto-generated comment: release notes by coderabbit.ai
-->
## Summary by CodeRabbit
* **Bug Fixes**
* Improved query validation in index advisor to more reliably handle SQL
query normalization and ensure consistent query processing.
<!-- end of auto-generated comment: release notes by coderabbit.ai -->
## Context
Shifting more dashboard queries into pg-meta so that we centralize all
manually written queries in one place
Having them in packages/pg-meta also allows us to write tests for them
## To test
Just needs a smoke test on
- Table Editor
- Fetching entities
- Viewing definition
- SQL Editor
- View ongoing queries
- Abort queries
- Integrations
- Queues
- Database
- Migrations
-Triggers (Updating)
## Context
Related to FE-2557
Part of shifting manually written dashboard queries into
packages/pg-meta where
- pg-meta can be code owners of
- we can write tests for the queries
This PR just shifts all the `.sql.ts` files that we previously created
into packages/pg-meta
There's still other areas where we need to shift over as well which I'll
address in subsequent PRs
## Notable changes
- `getTableRowsCountSql` -> Opted to shift `formatFilterValue` logic out
before calling this method (ref `table-rows-count-query`)
- `getDeleteOldCronJobRunDetailsByCtidSql` -> Opted to shift
`validatePageNumber` logic out before calling this method (ref
`CronJobsTab.useCleanupActions`)
## 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 introduces Query Insights. It's the first edition of possible
future updates. This takes our old prototype and builds upon it for a
more action driven insights view.
---------
Co-authored-by: Claude Sonnet 4.6 <noreply@anthropic.com>
Co-authored-by: Ali Waseem <waseema393@gmail.com>
## 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?
Spotted by @kostasb, index advisor was recommending slightly different
column names. Index advisor was running on mismatched queries thus
recommending for the wrong table.
## Context
Part of dashboard scalability project
Opting to use the connection string of the project's read replica (if
available) for read queries on the database.
Trialing with the Table Editor as a first pass - changes involved will
opt to use replica connection string for `useTableRowsQuery`,
`useTableRowsCountQuery`, and `useForeignKeyConstraintsQuery`
There's definitely optimizations to be done for deciding which replica
to use - but am starting off with a rather naive logic to prioritize
replicas in the same region as the project.
## Changes involved
- We're no longer passing `connectionString` as a param into the
affected hooks, the `connectionString` is derived from within those
hooks instead
- Change is feature flagged, so things should be status quo if flag is
off (use primary database's connection string)
- Added `useConnectionStringForReadOps` hook which returns the replica's
connection string if (Otherwise defaults to primary database connection
string)
- Feature flag is on
- Project has a replica available
## To test
- [ ] Verify that the table editor works as expected for a project that
has read replicas (There shouldn't be any change really)
- [ ] Also just double check that updating cells in the table editor
works as well (There's no change there, we're using the primary DB's
connection string for mutation ops)
- [ ] ^ Same thing for a project that doesn't have read replicas
- [ ] ^ Same thing for local / self-host
Add a Query Performance page implementation powered by
[supamonitor](https://github.com/supabase/supamonitor).
[Context](https://linear.app/supabase/project/build-extension-for-supabase-query-insights-df4fb145352c/overview)
This looks largely the same as the pg_stat_monitor implementation:
<img width="2556" height="960" alt="Screenshot 2026-02-12 at 7 35 47 PM"
src="https://github.com/user-attachments/assets/bf37466e-f7af-41f2-b4f2-cf8eb6a8c76f"
/>
Only available on projects on custom AMI - existing users are unaffected
<!-- This is an auto-generated comment: release notes by coderabbit.ai
-->
## Summary by CodeRabbit
* **New Features**
* Supamonitor-based query performance view: charts, aggregated metrics,
date-range controls, and export/download.
* Added "Application" column for per-application tracking.
* Interactive Supamonitor grid: sorting, filtering, keyboard navigation,
selection, retry/error handling.
* Automatic per-project Supamonitor detection with toggleable UI
integration.
* **Bug Fixes**
* Chart latency calculation prefers histogram data for more accurate
p95.
* **Documentation**
* Minor blog formatting fix.
<!-- end of auto-generated comment: release notes by coderabbit.ai -->
---------
Co-authored-by: kemal <hello@kemal.earth>
Co-authored-by: Ali Waseem <waseema393@gmail.com>
## Context
Related to Dashboard Scalability, specifically having Postgres team as
CODEOWNERS for dashboard queries
This is just a clean up as we're currently piling manual queries into
one folder under `data/sql/queries`, whereas I reckon it'll be better
for each query to sit within their RQ folder for better context.
Am opting the naming format for files housing queries to be `*.sql.ts`,
and also updating CODEOWNERS to reflect as such
Next step will also be to shift all the dashboard queries within pg-meta
into studio itself as requested by the pg-meta team
<!-- This is an auto-generated comment: release notes by coderabbit.ai
-->
## Summary by CodeRabbit
* **Refactor**
* Consolidated and reorganized internal module structure for the data
layer to improve maintainability and reduce redundancy.
* Streamlined import paths across components to align with new
consolidated module organization.
* **Chores**
* Updated code ownership patterns to reflect reorganized file structure.
<!-- end of auto-generated comment: release notes by coderabbit.ai -->
---------
Co-authored-by: Ali Waseem <waseema393@gmail.com>
## 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?
Set missing search path to support extension calling for older postgres
version (PG15)
<!-- This is an auto-generated comment: release notes by coderabbit.ai
-->
## Summary by CodeRabbit
* **Bug Fixes**
* Fixed index advisor query execution to ensure proper schema context
during analysis operations.
<!-- end of auto-generated comment: release notes by coderabbit.ai -->
* added table advisor query
* updated to include table editor performance
* updated JSON B
* added side panel
* updated query indexes to show highlights context
* show index advisor in table editor
* updated invalidation logic
* added color updates
* added query indexes
* updated query performance type
* updated overflow and title
* put behind flag
* remove gap
* added on close
* Update apps/studio/data/database/table-index-advisor-query.ts
Co-authored-by: Charis <26616127+charislam@users.noreply.github.com>
* updated styling
---------
Co-authored-by: Charis <26616127+charislam@users.noreply.github.com>
* Add custom types for queries, mutations and infinite queries.
* Migrate all queries to use the new type.
* Migrate all infinite queries to useCustomInfiniteQueryOptions.
* Migrate all mutations to use useCustomMutationOptions.
* Add type to all imports in `types` folder.
* Migrate all uses of invalidateQueries to use object syntax.
* Migrate the remainder of useInfiniteQuery.
* Migrate all setQueriesData.
* Migrate all fetchQuery uses.
* Migrate some leftover functions from RQ.
* Fix issues found by Charis.
* init
* hovercard
* adds button to install index advisor
* hover card now now insert indexes
* update
* moved hook
* align alert dialog to design syste,
* Update index-advisor.utils.ts
* shows all index statements now
* Update query-performance.tsx
* Some refactors
* Clean up
* Fix
* One last nit refactor
---------
Co-authored-by: Joshen Lim <joshenlimek@gmail.com>
* Init
* Initial set up for hooking up supavisor and pgbouncer
* Hook up pgbouncer status check after swapping pooler type
* Add check for nano compute for switching to pg bouncer
* Add check for ipv4 addon
* Remove expect error tag
* Update copy in IPv4SidePanel
* Add badge to select options for pooler types
* Hook up pgbouncer config for connect UI
* Refactor pooling-configuration react queries to supavisor-configuration
* Update Ipv4 compatability UI indicators in Connect UI when on pgbouncer
* Remove statement mode
* Resolve undefined problem with react hook form
* Fix
* Update UI texts from PgBouncer to Dedicated Pooler
* Feature flag changes
* Add pooler settings link in Connect UI
* Smol update
* Update session pooler description for pgbouncer