fix(redis): disable SQL formatting for Redis queries

This commit is contained in:
jearhe
2026-09-09 14:44:40 +08:00
committed by GitHub
parent 894ecdec42
commit a535cf8f51
5 changed files with 58 additions and 4 deletions
+3
View File
@@ -1410,6 +1410,9 @@ function resolveToolbarTab(tabId?: string) {
function formatActiveSql(tabId?: string) {
const tab = resolveToolbarTab(tabId);
if (!tab || tab.mode !== "query" || !tab.sql.trim()) return;
const connection = connectionStore.getConfig(tab.connectionId);
const databaseType = effectiveDatabaseTypeForConnection(connection) ?? connection?.db_type;
if (!canFormatSqlForDatabaseType(databaseType)) return;
formatSqlRequest.value = {
id: (formatSqlRequest.value?.id ?? 0) + 1,
tabId: tab.id,
@@ -25,6 +25,7 @@ import { productionContextForDatabase } from "@/lib/database/productionSafety";
import { formatShortcutDisplay } from "@/lib/editor/shortcutDisplay";
import { resolveNextEditorToolbarTier, type EditorToolbarTier } from "@/lib/tabs/editorToolbarLayout";
import { looksLikeDmlStatement } from "@/lib/sql/dmlChangePreview";
import { canFormatSqlForDatabaseType } from "@/lib/sql/sqlFormatter";
import type { QueryTab, ConnectionConfig } from "@/types/database";
const props = defineProps<{
@@ -326,7 +327,8 @@ const isActiveDatabaseDefault = computed(() => isDefaultDatabase(props.activeCon
// tier contract.
const showOverflowMenu = computed(() => toolbarTier.value >= 1);
const showFormatButton = computed(() => toolbarTier.value < 2);
const canFormatSql = computed(() => canFormatSqlForDatabaseType(props.activeConnection?.db_type));
const showFormatButton = computed(() => canFormatSql.value && toolbarTier.value < 2);
const showExplainAnalyzeToggle = computed(() => toolbarTier.value < 3);
const showCompressButton = computed(() => toolbarTier.value < 1);
const showKeywordCaseButton = computed(() => toolbarTier.value < 1);
@@ -608,7 +610,7 @@ async function changeCatalog(selectedCatalog: string) {
{{ insertValueHintsToggleTooltip }}
</DropdownMenuCheckboxItem>
<template v-if="toolbarTier >= 2">
<DropdownMenuItem :disabled="activeTab.isExecuting || activeTab.isExplaining || !activeTab.sql.trim()" @select="emit('formatSql')">
<DropdownMenuItem v-if="canFormatSql" :disabled="activeTab.isExecuting || activeTab.isExplaining || !activeTab.sql.trim()" @select="emit('formatSql')">
<AlignLeft class="h-3.5 w-3.5" />
{{ t("toolbar.formatSql") }}
</DropdownMenuItem>
@@ -141,6 +141,54 @@ describe("EditorToolbar mount contract", () => {
host.remove();
});
it("does not expose SQL formatting for Redis connections", async () => {
const connectionStore = useConnectionStore();
connectionStore.connections = [
{
id: "conn-redis",
name: "redis",
db_type: "redis",
host: "localhost",
port: 6379,
} as never,
];
const host = createHost();
const app = createApp(EditorToolbar, {
activeTab: {
id: "tab-redis",
title: "Redis",
connectionId: "conn-redis",
database: "0",
sql: 'SET user:1 "hello world"',
mode: "query",
isExecuting: false,
isCancelling: false,
isExplaining: false,
},
activeConnection: connectionStore.getConfig("conn-redis"),
executableSql: 'SET user:1 "hello world"',
explainMode: "explain",
blockDangerousRedisCommands: true,
sqlKeywordCase: "preserve",
databaseRequiredSignal: 0,
autoCommit: true,
txnSessionId: undefined,
txnAutoRolledBack: false,
oracleTxnPossiblyDirty: false,
isOracleManualTransaction: false,
});
app.use(pinia);
app.use(i18n);
app.mount(host);
await nextTick();
expect(host.textContent).not.toContain("toolbar.formatSql");
app.unmount();
host.remove();
});
it("mounts for a schema-aware connection whose watchEffect reads tier-gated selectors", async () => {
// Regression: the tier-gated showSchemaSelector is read eagerly by the
// schema-loading watchEffect, so the tier refs must be declared before any
+2 -1
View File
@@ -11,7 +11,8 @@ describe("sqlFormatter", () => {
expect(sqlFormatterSource).not.toContain("(?<=");
});
it("disables SQL formatting for VictoriaMetrics queries", () => {
it("disables SQL formatting for Redis and VictoriaMetrics queries", () => {
expect(canFormatSqlForDatabaseType("redis")).toBe(false);
expect(canFormatSqlForDatabaseType("victoriametrics")).toBe(false);
expect(canFormatSqlForDatabaseType("mysql")).toBe(true);
});
+1 -1
View File
@@ -27,7 +27,7 @@ function resolveClickHouseIdentifierSafeDialect(sqlFormatter: SqlFormatterModule
}
export function canFormatSqlForDatabaseType(dbType: string | null | undefined): boolean {
return dbType !== "victoriametrics";
return dbType !== "redis" && dbType !== "victoriametrics";
}
/**