fix(oceanbase-oracle): format view DDL preview
This commit is contained in:
1 parent
0a239bddb2
commit
8da9905ed5
3 files changed
+66
-4
No files matched your search
@@ -20,7 +20,7 @@ import { executableStatementRangeAtCursor, executableStatementRangeCacheForDoc,
|
|||||||
import { currentStatementFrameRangeTo } from "@/lib/sql/currentStatementFrame";
|
import { currentStatementFrameRangeTo } from "@/lib/sql/currentStatementFrame";
|
||||||
import { expandToSqlStatementWindow } from "@/lib/sql/insertValueHints";
|
import { expandToSqlStatementWindow } from "@/lib/sql/insertValueHints";
|
||||||
import { insertValueHintColumnNames } from "@/lib/sql/insertValueHintColumns";
|
import { insertValueHintColumnNames } from "@/lib/sql/insertValueHintColumns";
|
||||||
import { canFormatSqlForDatabaseType, formatSqlForEditing, compressSqlText, type SqlFormatDialect } from "@/lib/sql/sqlFormatter";
|
import { canFormatSqlForDatabaseType, formatSqlForDisplay, formatSqlForEditing, compressSqlText, sqlFormatDialectForDbType, type SqlFormatDialect } from "@/lib/sql/sqlFormatter";
|
||||||
import { detectAndFormatStructured } from "@/lib/sql/autoFormat";
|
import { detectAndFormatStructured } from "@/lib/sql/autoFormat";
|
||||||
import { enabledSqlParameterSyntaxes, resolveSqlVariableSyntaxToggles } from "@/lib/sql/sqlVariableSyntax";
|
import { enabledSqlParameterSyntaxes, resolveSqlVariableSyntaxToggles } from "@/lib/sql/sqlVariableSyntax";
|
||||||
import { blankLineDeletionChanges, replaceSelectedEditorText } from "@/lib/editor/queryEditorTextEdits";
|
import { blankLineDeletionChanges, replaceSelectedEditorText } from "@/lib/editor/queryEditorTextEdits";
|
||||||
@@ -2825,7 +2825,13 @@ async function resolveSqlHoverTooltip(currentView: EditorViewType, pos: number)
|
|||||||
const { ddl } = await loadObjectDdl(objectMetadataRequest);
|
const { ddl } = await loadObjectDdl(objectMetadataRequest);
|
||||||
const rawDdl = ddlForHoverPreview(ddl);
|
const rawDdl = ddlForHoverPreview(ddl);
|
||||||
if (rawDdl && rawDdl.trim()) {
|
if (rawDdl && rawDdl.trim()) {
|
||||||
sqlContent = reformatHoverDdl(rawDdl, quoteQualifiedName(hoverQualifiedName));
|
// A view's display DDL wraps the raw (often single-line) view source
|
||||||
|
// in `CREATE ... VIEW ... AS`; the table-oriented reformatter cannot
|
||||||
|
// lay out a SELECT body, so views reuse the shared display formatter
|
||||||
|
// (the same one the sidebar/object-source viewers use). Tables keep
|
||||||
|
// the aligned column layout from reformatHoverDdl.
|
||||||
|
const isViewObject = objectMetadataRequest.objectType === "VIEW" || objectMetadataRequest.objectType === "MATERIALIZED_VIEW";
|
||||||
|
sqlContent = isViewObject ? await formatSqlForDisplay(rawDdl, props.formatDialect ?? sqlFormatDialectForDbType(props.databaseType), settingsStore.editorSettings.sqlFormatter) : reformatHoverDdl(rawDdl, quoteQualifiedName(hoverQualifiedName));
|
||||||
}
|
}
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
console.warn(`[DBX] Failed to load table DDL for ${hoverDatabase}.${hoverSchema}.${table.name}:`, error);
|
console.warn(`[DBX] Failed to load table DDL for ${hoverDatabase}.${hoverSchema}.${table.name}:`, error);
|
||||||
|
|||||||
+56
-2
@@ -60,9 +60,63 @@ describe("sqlFormatter", () => {
|
|||||||
expect(sqlFormatDialectForDbType("duckdb")).toBe("duckdb");
|
expect(sqlFormatDialectForDbType("duckdb")).toBe("duckdb");
|
||||||
});
|
});
|
||||||
|
|
||||||
it("maps only Oracle to the PL/SQL formatter dialect", () => {
|
it("maps Oracle and OceanBase Oracle mode to the PL/SQL formatter dialect", () => {
|
||||||
expect(sqlFormatDialectForDbType("oracle")).toBe("oracle");
|
expect(sqlFormatDialectForDbType("oracle")).toBe("oracle");
|
||||||
expect(sqlFormatDialectForDbType("oceanbase-oracle")).toBe("generic");
|
// OceanBase Oracle mode speaks Oracle SQL — issue #7540: it must reuse the
|
||||||
|
// Oracle dialect so view DDL previews are formatted instead of one line.
|
||||||
|
expect(sqlFormatDialectForDbType("oceanbase-oracle")).toBe("oracle");
|
||||||
|
});
|
||||||
|
|
||||||
|
it("formats an OceanBase Oracle single-line view DDL into readable multi-line SQL (issue #7540)", async () => {
|
||||||
|
const singleLine = `CREATE OR REPLACE VIEW "APP"."ACTIVE_USERS" AS SELECT ID, NAME FROM USERS WHERE STATUS = 'ACTIVE'`;
|
||||||
|
const formatted = await formatSqlForDisplay(singleLine, sqlFormatDialectForDbType("oceanbase-oracle"));
|
||||||
|
|
||||||
|
expect(formatted).not.toBe(singleLine);
|
||||||
|
expect(formatted.split("\n").length).toBeGreaterThan(1);
|
||||||
|
expect(formatted).toContain("CREATE OR REPLACE VIEW");
|
||||||
|
expect(formatted).toMatch(/\bSELECT\b/);
|
||||||
|
expect(formatted).toMatch(/\bFROM\b/);
|
||||||
|
expect(formatted).toMatch(/\bWHERE\b/);
|
||||||
|
// String literals and quoted identifiers must survive formatting untouched.
|
||||||
|
expect(formatted).toContain("'ACTIVE'");
|
||||||
|
expect(formatted).toContain('"ACTIVE_USERS"');
|
||||||
|
});
|
||||||
|
|
||||||
|
it("formats a bare OceanBase Oracle view source wrapped as CREATE VIEW (issue #7540)", async () => {
|
||||||
|
// Mirrors the backend build_view_ddl_sql output for a fallback ALL_VIEWS.TEXT
|
||||||
|
// body: `CREATE VIEW <name> AS <single-line SELECT>`.
|
||||||
|
const wrapped = `CREATE VIEW "APP"."ACTIVE_USERS" AS
|
||||||
|
SELECT ID, NAME FROM USERS WHERE STATUS = 'ACTIVE';`;
|
||||||
|
const formatted = await formatSqlForDisplay(wrapped, sqlFormatDialectForDbType("oceanbase-oracle"));
|
||||||
|
|
||||||
|
expect(formatted.split("\n").length).toBeGreaterThan(2);
|
||||||
|
expect(formatted).toMatch(/\bSELECT\b/);
|
||||||
|
expect(formatted).toMatch(/\bFROM\b/);
|
||||||
|
expect(formatted).toMatch(/\bWHERE\b/);
|
||||||
|
expect(formatted).toContain("'ACTIVE'");
|
||||||
|
});
|
||||||
|
|
||||||
|
it("does not split string literals when formatting an OceanBase Oracle view (issue #7540)", async () => {
|
||||||
|
const singleLine = `CREATE OR REPLACE VIEW "APP"."V" AS SELECT 'SELECT X FROM Y' AS TXT FROM DUAL`;
|
||||||
|
const formatted = await formatSqlForDisplay(singleLine, sqlFormatDialectForDbType("oceanbase-oracle"));
|
||||||
|
|
||||||
|
expect(formatted).toContain("'SELECT X FROM Y'");
|
||||||
|
});
|
||||||
|
|
||||||
|
it("leaves an already multi-line OceanBase Oracle view DDL semantically intact (issue #7540)", async () => {
|
||||||
|
const multiLine = `CREATE OR REPLACE VIEW "APP"."ACTIVE_USERS" AS
|
||||||
|
SELECT
|
||||||
|
ID,
|
||||||
|
NAME
|
||||||
|
FROM USERS
|
||||||
|
WHERE STATUS = 'ACTIVE';`;
|
||||||
|
const formatted = await formatSqlForDisplay(multiLine, sqlFormatDialectForDbType("oceanbase-oracle"));
|
||||||
|
|
||||||
|
expect(formatted).toContain('"ACTIVE_USERS"');
|
||||||
|
expect(formatted).toContain("'ACTIVE'");
|
||||||
|
expect(formatted).toMatch(/\bID\b/);
|
||||||
|
expect(formatted).toMatch(/\bNAME\b/);
|
||||||
|
expect(formatted).toMatch(/\bWHERE\b/);
|
||||||
});
|
});
|
||||||
|
|
||||||
it("keeps issue #7138 Oracle hierarchy clauses intact", async () => {
|
it("keeps issue #7138 Oracle hierarchy clauses intact", async () => {
|
||||||
|
|||||||
@@ -77,6 +77,8 @@ export function sqlFormatDialectForDbType(dbType: string | null | undefined): Sq
|
|||||||
case "sqlserver":
|
case "sqlserver":
|
||||||
return "sqlserver";
|
return "sqlserver";
|
||||||
case "oracle":
|
case "oracle":
|
||||||
|
// OceanBase Oracle mode speaks Oracle SQL, so it reuses the PL/SQL grammar.
|
||||||
|
case "oceanbase-oracle":
|
||||||
return "oracle";
|
return "oracle";
|
||||||
case "clickhouse":
|
case "clickhouse":
|
||||||
return "clickhouse";
|
return "clickhouse";
|
||||||
|
|||||||
Reference in new issue
Block a user