Files
supabase/apps/studio/components/interfaces/SQLEditor/usePrettifyQuery.ts
Charis c16c7e94cc feat(studio): SQL editor logs source — toolbar UI + creation flow (#48452)
## What

PR 6 of the SQL-editor "query source (Database vs Logs)" stack (builds
on the merged PR 5, #48414). Adds the user-facing toolbar surface for
the logs query source and consolidates the SQL-editor toolbar into a
single **source menu**.

Everything stays behind `sqlEditorLogsSource` + `otelLegacyLogs`
(dual-flag gated); with the flags off the toolbar is unchanged.

## Changes

- **Consolidated source menu** (`QuerySourceMenu`) — one `Database ▾` /
`Logs ▾` dropdown that both labels the snippet's source and hosts the
source-specific controls as flyout submenus:
- Database: database selector (`Primary` / read replicas), `Run as`
(role impersonation), and `Row limit`.
- Logs: `Time range` — the same relative presets as the Logs Explorer
plus a `Custom range…` calendar dialog.
- **Source is immutable** — the Database/Logs rows aren't a toggle. An
existing (materialized) snippet opens a *fresh* tab of the target source
(never reinterpreting a query against the wrong backend); a blank new
tab re-flavors in place. Extracted as the pure, unit-tested
`resolveSourceSwitch`.
- **New-snippet-with-source** threaded through `/sql/new?source=`, the
nav "Create a new logs query" entry, and the duplicate flow. Logs
snippets hide the (db-dialect) Export action.
- **Run-affordance guard** — the Run button is disabled + annotated for
a logs snippet on a non-ClickHouse org (sits above PR 5's execution
short-circuit).
- **Retention entitlement gating** — both preset and custom logs ranges
past `log.retention_days` surface the upgrade prompt instead of applying
silently. Prettify is disabled for logs (sql-formatter mangles
ClickHouse).

## Tests

- `querySource.test.ts` — `logDateRangesEqual` (structural
relative/absolute matching, incl. the "Last hour" vs "Last 1 hour" label
case).
- `QuerySourceMenu.utils.test.ts` — `resolveSourceSwitch`
push-vs-replace / no-op behavior.

`pnpm --filter studio typecheck` · `lint:ratchet` · Prettier · SQL
editor suite (307 tests) all green.

## For reviewers

To test manually, enable the `sqlEditorLogsSource` feature flag for
yourself on local/staging. There is no nav for Log SQL snippets
currently (that is by design, this PR is big enough as-is), so to check
an existing logs snippet, you can create one using the existing Logs
Explorer, copy its UUID, and force navigate to that snippet in the SQL
editor via URL.

<!-- This is an auto-generated comment: release notes by coderabbit.ai
-->

## Summary by CodeRabbit

* **New Features**
* Added support for creating and switching between database and logs
queries.
  * Added log time-range presets and custom date-range selection.
  * Added database, run-as role, and row-limit controls.
* Added read-replica selection, including options to create a new
replica when available.
* **Improvements**
  * Added clearer explanations when query execution is unavailable.
* Disabled SQL formatting and query export where unsupported for logs
queries.

<!-- end of auto-generated comment: release notes by coderabbit.ai -->

---------

Co-authored-by: Joshen Lim <joshenlimek@gmail.com>
2026-07-30 08:38:11 -04:00

42 lines
1.5 KiB
TypeScript

import { useCallback } from 'react'
import { useSQLEditorContext } from './SQLEditorContext'
import { useSelectedProjectQuery } from '@/hooks/misc/useSelectedProject'
import { formatSql } from '@/lib/formatSql'
import {
getSqlEditorV2StateSnapshot,
useSqlEditorV2StateSnapshot,
} from '@/state/sql-editor/sql-editor-state'
/**
* Formats the current editor SQL in place (respecting a selection) and writes
* the formatted SQL back to the snippet store. No-op while a diff is open.
*/
export function usePrettifyQuery({ id, isDiffOpen }: { id: string; isDiffOpen: boolean }) {
const { editor } = useSQLEditorContext()
const { data: project } = useSelectedProjectQuery()
const snapV2 = useSqlEditorV2StateSnapshot()
return useCallback(async () => {
if (isDiffOpen) return
// use the latest state
const state = getSqlEditorV2StateSnapshot()
const snippet = state.snippets[id]
// pg formatting can mangle ClickHouse syntax (backtick identifiers), so
// Prettify is a no-op for logs snippets — the UI also hides the affordance.
if (snippet?.snippet.type === 'log_sql') return
if (editor.isReady() && project) {
const fallback = snippet?.snippet.content?.unchecked_sql
const sql = editor.getSql(fallback)
if (sql === undefined) return
const formattedSql = formatSql(sql)
editor.replaceAll(formattedSql, 'apply-prettify-edit')
snapV2.setSql({ id, sql: formattedSql })
}
}, [editor, id, isDiffOpen, project, snapV2])
}