fix(clickhouse): load table index metadata
This commit is contained in:
1 parent
293df56274
commit
521a3021c4
6 files changed
+267
-42
No files matched your search
@@ -133,6 +133,7 @@ import { useCellDetailEditor, type UseCellDetailEditorReturn } from "@/composabl
|
||||
import { useTheme } from "@/composables/useTheme";
|
||||
import { useSettingsStore } from "@/stores/settingsStore";
|
||||
import { nextDataGridSortState, type DataGridSortDirection } from "@/lib/dataGridSort";
|
||||
import { getTableMetadataCapabilities } from "@/lib/tableMetadataCapabilities";
|
||||
|
||||
const SqlPreviewPanel = defineAsyncComponent(() => import("@/components/editor/SqlPreviewPanel.vue"));
|
||||
|
||||
@@ -5175,6 +5176,7 @@ async function prefetchCopyStatements() {
|
||||
const sqlOneLiner = computed(() => props.sql?.replace(/\s+/g, " ").trim() || "");
|
||||
|
||||
type TableInfoTab = "columns" | "indexes" | "foreignKeys" | "triggers" | "ddl";
|
||||
type TableInfoTabItem = { id: TableInfoTab; label: string; icon: Component; count?: number };
|
||||
|
||||
const TABLE_INFO_DRAWER_MIN_WIDTH = 240;
|
||||
const CELL_DETAIL_PANEL_MIN_HEIGHT = 180;
|
||||
@@ -5268,26 +5270,34 @@ function toggleCellDetailPanelLayout() {
|
||||
});
|
||||
}
|
||||
|
||||
const tableInfoTabs = computed(
|
||||
() =>
|
||||
[
|
||||
{
|
||||
id: "columns" as const,
|
||||
label: t("grid.tableInfoColumns"),
|
||||
icon: ListTree,
|
||||
count: props.tableMeta?.columns.length,
|
||||
},
|
||||
{ id: "indexes" as const, label: t("grid.tableInfoIndexes"), icon: KeyRound, count: indexes.value.length },
|
||||
{
|
||||
id: "foreignKeys" as const,
|
||||
label: t("grid.tableInfoForeignKeys"),
|
||||
icon: Link2,
|
||||
count: foreignKeys.value.length,
|
||||
},
|
||||
{ id: "triggers" as const, label: t("grid.tableInfoTriggers"), icon: RotateCcw, count: triggers.value.length },
|
||||
{ id: "ddl" as const, label: "DDL", icon: Code2 },
|
||||
] satisfies Array<{ id: TableInfoTab; label: string; icon: Component; count?: number }>,
|
||||
);
|
||||
const tableMetadataCapabilities = computed(() => getTableMetadataCapabilities(props.databaseType));
|
||||
const tableInfoTabs = computed(() => {
|
||||
const tabs: TableInfoTabItem[] = [
|
||||
{
|
||||
id: "columns",
|
||||
label: t("grid.tableInfoColumns"),
|
||||
icon: ListTree,
|
||||
count: props.tableMeta?.columns.length,
|
||||
},
|
||||
{ id: "indexes", label: t("grid.tableInfoIndexes"), icon: KeyRound, count: indexes.value.length },
|
||||
];
|
||||
if (tableMetadataCapabilities.value.foreignKeys) {
|
||||
tabs.push({
|
||||
id: "foreignKeys",
|
||||
label: t("grid.tableInfoForeignKeys"),
|
||||
icon: Link2,
|
||||
count: foreignKeys.value.length,
|
||||
});
|
||||
}
|
||||
if (tableMetadataCapabilities.value.triggers) {
|
||||
tabs.push({ id: "triggers", label: t("grid.tableInfoTriggers"), icon: RotateCcw, count: triggers.value.length });
|
||||
}
|
||||
tabs.push({ id: "ddl", label: "DDL", icon: Code2 });
|
||||
return tabs;
|
||||
});
|
||||
const tableInfoTabListStyle = computed(() => ({
|
||||
gridTemplateColumns: `repeat(${tableInfoTabs.value.length}, minmax(0, 1fr))`,
|
||||
}));
|
||||
|
||||
async function toggleTableInfo(tab: TableInfoTab = activeTableInfoTab.value) {
|
||||
if (showTableInfo.value && activeTableInfoTab.value === tab) {
|
||||
@@ -5299,11 +5309,12 @@ async function toggleTableInfo(tab: TableInfoTab = activeTableInfoTab.value) {
|
||||
}
|
||||
|
||||
async function selectTableInfoTab(tab: TableInfoTab) {
|
||||
activeTableInfoTab.value = tab;
|
||||
if (tab === "ddl") await fetchDdl();
|
||||
else if (tab === "indexes") await fetchIndexes();
|
||||
else if (tab === "foreignKeys") await fetchForeignKeys();
|
||||
else if (tab === "triggers") await fetchTriggers();
|
||||
const nextTab = tableInfoTabs.value.some((item) => item.id === tab) ? tab : "columns";
|
||||
activeTableInfoTab.value = nextTab;
|
||||
if (nextTab === "ddl") await fetchDdl();
|
||||
else if (nextTab === "indexes") await fetchIndexes();
|
||||
else if (nextTab === "foreignKeys") await fetchForeignKeys();
|
||||
else if (nextTab === "triggers") await fetchTriggers();
|
||||
}
|
||||
|
||||
async function fetchDdl() {
|
||||
@@ -6882,7 +6893,7 @@ const gridContextMenuItems = computed<ContextMenuItem[]>(() => {
|
||||
<X class="w-3 h-3" />
|
||||
</Button>
|
||||
</div>
|
||||
<div class="grid grid-cols-5 border-b bg-background shrink-0">
|
||||
<div class="grid border-b bg-background shrink-0" :style="tableInfoTabListStyle">
|
||||
<button
|
||||
v-for="tab in tableInfoTabs"
|
||||
:key="tab.id"
|
||||
|
||||
@@ -22,6 +22,7 @@ import { type SqlHighlighter, createShikiSqlHighlighter } from "@/lib/sqlHighlig
|
||||
import { copyToClipboard } from "@/lib/clipboard";
|
||||
import { queryTimeoutSecsForConnection } from "@/lib/queryTimeout";
|
||||
import { type EditableStructureColumn, type EditableStructureIndex } from "@/lib/tableStructureEditorSql";
|
||||
import { getTableMetadataCapabilities } from "@/lib/tableMetadataCapabilities";
|
||||
import { getTableStructureCapabilities } from "@/lib/tableStructureCapabilities";
|
||||
import { connectionObjectTreeQuerySchema, effectiveDatabaseTypeForConnection } from "@/lib/jdbcDialect";
|
||||
import { buildStructureTargetLabel, combineDataTypeForDatabase, createColumnDrafts, createIndexDrafts, getDataTypeOptions, getDefaultLengthForType, splitDataType, toColumnNames } from "@/lib/tableStructureEditorState";
|
||||
@@ -268,6 +269,7 @@ function onIndexColResize(e: MouseEvent, col: number) {
|
||||
const connection = computed(() => (props.connectionId ? store.getConfig(props.connectionId) : undefined));
|
||||
const databaseType = computed(() => effectiveDatabaseTypeForConnection(connection.value));
|
||||
const structureCapabilities = computed(() => getTableStructureCapabilities(databaseType.value));
|
||||
const tableMetadataCapabilities = computed(() => getTableMetadataCapabilities(databaseType.value));
|
||||
const structureDialect = computed(() => structureCapabilities.value.dialect);
|
||||
const isTableCommentDisabled = computed(() => !structureCapabilities.value.comment);
|
||||
const dataTypeOptions = computed(() => getDataTypeOptions(databaseType.value));
|
||||
@@ -372,8 +374,8 @@ async function loadStructure(silent = false) {
|
||||
const nextColumns = await api.getColumns(props.connectionId, props.database, metadataSchema.value, props.tableName);
|
||||
const [nextIndexes, nextForeignKeys, nextTriggers] = await Promise.all([
|
||||
api.listIndexes(props.connectionId, props.database, metadataSchema.value, props.tableName).catch(() => []),
|
||||
api.listForeignKeys(props.connectionId, props.database, metadataSchema.value, props.tableName).catch(() => []),
|
||||
api.listTriggers(props.connectionId, props.database, metadataSchema.value, props.tableName).catch(() => []),
|
||||
tableMetadataCapabilities.value.foreignKeys ? api.listForeignKeys(props.connectionId, props.database, metadataSchema.value, props.tableName).catch(() => []) : Promise.resolve([]),
|
||||
tableMetadataCapabilities.value.triggers ? api.listTriggers(props.connectionId, props.database, metadataSchema.value, props.tableName).catch(() => []) : Promise.resolve([]),
|
||||
]);
|
||||
columns.value = createColumnDrafts(nextColumns, databaseType.value);
|
||||
indexes.value = createIndexDrafts(nextIndexes);
|
||||
@@ -670,6 +672,11 @@ onBeforeUnmount(() => {
|
||||
unregisterStructureEditorShortcuts();
|
||||
});
|
||||
|
||||
watch(tableMetadataCapabilities, (capabilities) => {
|
||||
if (activeTab.value === "foreignKeys" && !capabilities.foreignKeys) activeTab.value = "columns";
|
||||
if (activeTab.value === "triggers" && !capabilities.triggers) activeTab.value = "columns";
|
||||
});
|
||||
|
||||
watch(
|
||||
[isCreateMode, databaseType, () => props.schema, () => props.tableName, newTableName, tableComment, columns, indexes],
|
||||
() => {
|
||||
@@ -730,8 +737,8 @@ watch(activeTab, (tab) => {
|
||||
<TabsList>
|
||||
<TabsTrigger value="columns">{{ t("structureEditor.columns") }}</TabsTrigger>
|
||||
<TabsTrigger value="indexes">{{ t("structureEditor.indexes") }}</TabsTrigger>
|
||||
<TabsTrigger value="foreignKeys">{{ t("structureEditor.foreignKeys") }}</TabsTrigger>
|
||||
<TabsTrigger value="triggers">{{ t("structureEditor.triggers") }}</TabsTrigger>
|
||||
<TabsTrigger v-if="tableMetadataCapabilities.foreignKeys" value="foreignKeys">{{ t("structureEditor.foreignKeys") }}</TabsTrigger>
|
||||
<TabsTrigger v-if="tableMetadataCapabilities.triggers" value="triggers">{{ t("structureEditor.triggers") }}</TabsTrigger>
|
||||
<TabsTrigger value="ddl" v-if="!isCreateMode">DDL</TabsTrigger>
|
||||
</TabsList>
|
||||
<div class="flex shrink-0 items-center gap-1.5">
|
||||
@@ -1077,7 +1084,7 @@ watch(activeTab, (tab) => {
|
||||
</table>
|
||||
</TabsContent>
|
||||
|
||||
<TabsContent value="foreignKeys" class="m-0 min-h-0 flex-1 overflow-auto p-[var(--structure-cell-px)]">
|
||||
<TabsContent v-if="tableMetadataCapabilities.foreignKeys" value="foreignKeys" class="m-0 min-h-0 flex-1 overflow-auto p-[var(--structure-cell-px)]">
|
||||
<div v-if="foreignKeys.length === 0" class="py-10 text-center text-muted-foreground">
|
||||
{{ t("structureEditor.emptyReadonly") }}
|
||||
</div>
|
||||
@@ -1089,7 +1096,7 @@ watch(activeTab, (tab) => {
|
||||
</div>
|
||||
</TabsContent>
|
||||
|
||||
<TabsContent value="triggers" class="m-0 min-h-0 flex-1 overflow-auto p-[var(--structure-cell-px)]">
|
||||
<TabsContent v-if="tableMetadataCapabilities.triggers" value="triggers" class="m-0 min-h-0 flex-1 overflow-auto p-[var(--structure-cell-px)]">
|
||||
<div v-if="triggers.length === 0" class="py-10 text-center text-muted-foreground">
|
||||
{{ t("structureEditor.emptyReadonly") }}
|
||||
</div>
|
||||
|
||||
Reference in new issue
Block a user