fix(postgres): include owner and grants in displayed DDL

This commit is contained in:
zipg authored and GitHub committed 2026-07-27 21:45:35 +08:00
1 parent a5eb6fd1fa
commit 1d671ca698
13 files changed
+479 -12

No files matched your search

@@ -7130,7 +7130,7 @@ async function fetchDdl() {
ddlLoading.value = true;
try {
// Preserve view identity so the backend loads the stored view source instead of synthesizing table DDL.
ddlContent.value = await api.getTableDdl(props.connectionId, props.database || "", props.tableMeta.schema || props.database || "", props.tableMeta.tableName, tableObjectSourceKind(props.tableMeta.tableType), props.tableMeta.catalog);
ddlContent.value = await api.getTableDisplayDdl(props.connectionId, props.database || "", props.tableMeta.schema || props.database || "", props.tableMeta.tableName, tableObjectSourceKind(props.tableMeta.tableType), props.tableMeta.catalog);
} catch (e: any) {
ddlContent.value = `-- Error: ${e}`;
} finally {
@@ -61,7 +61,7 @@ watch(
ddlLoading.value = true;
try {
const schema = props.schema || props.database;
const ddl = await api.getTableDdl(props.connectionId, props.database, schema, props.tableName, props.objectType, props.catalog);
const ddl = await api.getTableDisplayDdl(props.connectionId, props.database, schema, props.tableName, props.objectType, props.catalog);
ddlContent.value = await formatSqlForDisplay(ddl, props.formatDialect ?? props.dialect, settingsStore.editorSettings.sqlFormatter);
} catch (e: any) {
ddlError.value = e?.message || String(e);
@@ -176,7 +176,7 @@ function retry() {
ddlContent.value = "";
const schema = props.schema || props.database;
api
.getTableDdl(props.connectionId, props.database, schema, props.tableName, props.objectType)
.getTableDisplayDdl(props.connectionId, props.database, schema, props.tableName, props.objectType)
.then(async (ddl) => {
ddlContent.value = await formatSqlForDisplay(ddl, props.formatDialect ?? props.dialect, settingsStore.editorSettings.sqlFormatter);
})
@@ -934,7 +934,7 @@ async function fetchTableDdl() {
tableDdlLoading.value = true;
try {
const schema = row.schema || selectedSchema.value || props.database;
const ddl = await api.getTableDdl(props.connection.id, props.database || "", schema, row.name, tableDdlObjectType(row.type), props.catalog);
const ddl = await api.getTableDisplayDdl(props.connection.id, props.database || "", schema, row.name, tableDdlObjectType(row.type), props.catalog);
if (sidePanelGuard.isStale(epoch)) return;
tableDdlContent.value = ddl;
} catch (e: any) {
@@ -1248,9 +1248,9 @@ async function generateDdlTemplate() {
const schema = node.schema || node.database;
let ddl: string;
if (node.type === "table") {
ddl = await api.getTableDdl(node.connectionId, node.database, schema, node.label, undefined, node.catalog);
ddl = await api.getTableDisplayDdl(node.connectionId, node.database, schema, node.label, undefined, node.catalog);
} else if (node.type === "materialized_view") {
ddl = await api.getTableDdl(node.connectionId, node.database, schema, node.label, "MATERIALIZED_VIEW", node.catalog);
ddl = await api.getTableDisplayDdl(node.connectionId, node.database, schema, node.label, "MATERIALIZED_VIEW", node.catalog);
} else {
const result = await api.getObjectSource(node.connectionId, node.database, schema, node.label, "VIEW");
ddl = await buildViewDdl({
@@ -155,7 +155,7 @@ async function fetchDdl() {
if (!props.connectionId || !props.database || !props.tableName || ddlFetched.value || !tableMetadataCapabilities.value.ddl) return;
ddlLoading.value = true;
try {
const ddl = await api.getTableDdl(props.connectionId, props.database, metadataSchema.value, props.tableName, undefined, props.catalog);
const ddl = await api.getTableDisplayDdl(props.connectionId, props.database, metadataSchema.value, props.tableName, undefined, props.catalog);
ddlContent.value = await formatSqlForDisplay(ddl, sqlFormatDialectForDbType(databaseType.value), settingsStore.editorSettings.sqlFormatter);
ddlFetched.value = true;
} catch (e: any) {
@@ -960,7 +960,7 @@ async function hydrateRestoredDraftFromDatabase() {
let nextColumns = await api.getColumns(connectionId, database, schema, tableName, catalog);
if (databaseType.value === "manticoresearch" && tableMetadataCapabilities.value.ddl) {
try {
const ddl = await api.getTableDdl(connectionId, database, schema, tableName, undefined, catalog);
const ddl = await api.getTableDisplayDdl(connectionId, database, schema, tableName, undefined, catalog);
ddlContent.value = await formatSqlForDisplay(ddl, sqlFormatDialectForDbType(databaseType.value), settingsStore.editorSettings.sqlFormatter);
ddlFetched.value = true;
nextColumns = applyManticoreDdlColumnExtras(nextColumns, ddl);
@@ -1256,7 +1256,7 @@ async function loadStructure(silent = false, scope: TableStructureRefreshScope =
if (nextColumns) {
if (databaseType.value === "manticoresearch" && tableMetadataCapabilities.value.ddl) {
try {
const ddl = await api.getTableDdl(connectionId, database, schema, tableName, undefined, catalog);
const ddl = await api.getTableDisplayDdl(connectionId, database, schema, tableName, undefined, catalog);
ddlContent.value = await formatSqlForDisplay(ddl, sqlFormatDialectForDbType(databaseType.value), settingsStore.editorSettings.sqlFormatter);
ddlFetched.value = true;
nextColumns = applyManticoreDdlColumnExtras(nextColumns, ddl);
@@ -5,6 +5,8 @@ const contentAreaSource = readFileSync(new URL("../../../components/layout/Conte
const connectionTreeSource = readFileSync(new URL("../../../components/sidebar/ConnectionTree.vue", import.meta.url), "utf8");
const ddlViewDialogSource = readFileSync(new URL("../../../components/objects/DdlViewDialog.vue", import.meta.url), "utf8");
const objectBrowserSource = readFileSync(new URL("../../../components/objects/ObjectBrowser.vue", import.meta.url), "utf8");
const fetchTableDdlSource = objectBrowserSource.match(/async function fetchTableDdl\(\)[\s\S]*?(?=\nasync function fetchTableColumns\()/)?.[0] ?? "";
const exportStructureSource = objectBrowserSource.match(/async function exportStructure\([\s\S]*?(?=\nasync function exportDataLegacy\()/)?.[0] ?? "";
function openingTag(source: string, componentName: string): string {
return source.match(new RegExp(`<${componentName}\\b[\\s\\S]*?>`))?.[0] ?? "";
@@ -24,7 +26,7 @@ describe("ContentArea external catalog wiring", () => {
});
it("forwards the DDL dialog catalog to the metadata API", () => {
expect(ddlViewDialogSource).toMatch(/api\.getTableDdl\([\s\S]*?props\.objectType, props\.catalog\)/);
expect(ddlViewDialogSource).toMatch(/api\.getTableDisplayDdl\([\s\S]*?props\.objectType, props\.catalog\)/);
});
});
@@ -43,3 +45,14 @@ describe("ContentArea object browser refresh wiring", () => {
expect(objectBrowserSource).toMatch(/<Button[^>]*:title="refreshTooltip"[^>]*@click="reload">/);
});
});
describe("ObjectBrowser DDL API boundaries", () => {
it("uses display DDL for the table information panel", () => {
expect(fetchTableDdlSource).toMatch(/api\.getTableDisplayDdl\([\s\S]*?props\.catalog\);/);
});
it("keeps structure exports on the portable base DDL", () => {
expect(exportStructureSource).toMatch(/api\.getTableDdl\([\s\S]*?props\.catalog\);/);
expect(exportStructureSource).not.toContain("api.getTableDisplayDdl(");
});
});
+1
View File
@@ -165,6 +165,7 @@ export const listConstraints = forward("listConstraints");
export const listPartitions = forward("listPartitions");
export const listSubpartitions = forward("listSubpartitions");
export const getTableDdl = forward("getTableDdl");
export const getTableDisplayDdl = forward("getTableDisplayDdl");
export const listFunctions = forward("listFunctions");
export const listSequences = forward("listSequences");
export const listRules = forward("listRules");
+4
View File
@@ -722,6 +722,10 @@ export async function getTableDdl(connectionId: string, database: string, schema
return get(`/api/schema/ddl?${qs({ connection_id: connectionId, database, schema, table, object_type: objectType, catalog })}`);
}
export async function getTableDisplayDdl(connectionId: string, database: string, schema: string, table: string, objectType?: ObjectSourceKind, catalog?: string): Promise<string> {
return get(`/api/schema/ddl?${qs({ connection_id: connectionId, database, schema, table, object_type: objectType, catalog, include_postgres_access: true })}`);
}
export async function prepareSchemaDiff(options: SchemaDiffPreparationOptions): Promise<SchemaDiffPreparation> {
return post("/api/schema-diff/prepare", options);
}
+4
View File
@@ -1202,6 +1202,10 @@ export async function getTableDdl(connectionId: string, database: string, schema
return invoke("get_table_ddl", { connectionId, database, schema, table, objectType, catalog });
}
export async function getTableDisplayDdl(connectionId: string, database: string, schema: string, table: string, objectType?: ObjectSourceKind, catalog?: string): Promise<string> {
return invoke("get_table_ddl", { connectionId, database, schema, table, objectType, catalog, includePostgresAccess: true });
}
export async function prepareSchemaDiff(options: SchemaDiffPreparationOptions): Promise<SchemaDiffPreparation> {
return invoke("prepare_schema_diff", { options });
}