mirror of
https://github.com/t8y2/dbx.git
synced 2026-10-20 00:17:44 +00:00
fix(gaussdb): support M-mode type metadata
This commit is contained in:
@@ -115,7 +115,7 @@ public abstract class ConfiguredJdbcAgent extends AbstractJdbcAgent {
|
||||
|
||||
@Override
|
||||
public List<IndexInfo> listIndexes(String schema, String table) {
|
||||
return StandardJdbcMetadata.INSTANCE.listIndexes(requireConnection(), schema, table);
|
||||
return StandardJdbcMetadata.INSTANCE.listIndexes(requireConnection(), profile, configuredDatabase, schema, table);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
||||
@@ -207,12 +207,28 @@ public final class StandardJdbcMetadata {
|
||||
});
|
||||
}
|
||||
|
||||
public List<IndexInfo> listIndexes(Connection conn, String schema, String table) {
|
||||
public List<IndexInfo> listIndexes(
|
||||
Connection conn,
|
||||
JdbcAgentProfile profile,
|
||||
String configuredDatabase,
|
||||
String schema,
|
||||
String table
|
||||
) {
|
||||
return unchecked(() -> {
|
||||
List<IndexInfo> result = listIndexesInternal(conn, null, schema, table);
|
||||
if (result.isEmpty() && profile.getCatalogFallbackEnabled() && hasConfiguredDatabase(configuredDatabase)) {
|
||||
result = listIndexesInternal(conn, configuredDatabase, schema, table);
|
||||
}
|
||||
return result;
|
||||
});
|
||||
}
|
||||
|
||||
private List<IndexInfo> listIndexesInternal(Connection conn, String catalog, String schema, String table) {
|
||||
return unchecked(() -> {
|
||||
DatabaseMetaData meta = conn.getMetaData();
|
||||
Map<String, List<IndexColumn>> indexes = new LinkedHashMap<>();
|
||||
Map<String, Boolean> unique = new LinkedHashMap<>();
|
||||
try (ResultSet rs = meta.getIndexInfo(null, blankToNull(schema), table, false, false)) {
|
||||
try (ResultSet rs = meta.getIndexInfo(blankToNull(catalog), blankToNull(schema), table, false, false)) {
|
||||
while (rs.next()) {
|
||||
String name = rs.getString("INDEX_NAME");
|
||||
String column = rs.getString("COLUMN_NAME");
|
||||
|
||||
@@ -419,13 +419,62 @@ class StandardJdbcMetadataTest {
|
||||
rows()
|
||||
);
|
||||
|
||||
List<IndexInfo> indexes = StandardJdbcMetadata.INSTANCE.listIndexes(conn, "APP", "ORDERS");
|
||||
List<IndexInfo> indexes = StandardJdbcMetadata.INSTANCE.listIndexes(conn, profile, null, "APP", "ORDERS");
|
||||
|
||||
assertEquals(1, indexes.size());
|
||||
assertEquals(Arrays.asList("A", "B"), indexes.get(0).getColumns());
|
||||
assertFalse(indexes.get(0).getIs_unique());
|
||||
}
|
||||
|
||||
@Test
|
||||
void listIndexesUsesConfiguredCatalogOnlyWhenProfileAllowsFallback() {
|
||||
Connection enabledConn = catalogIndexFallbackConnection(
|
||||
"TENANTDB",
|
||||
rows(),
|
||||
rows(row("INDEX_NAME", "IDX_ORDERS", "COLUMN_NAME", "ID", "ORDINAL_POSITION", (short) 1, "NON_UNIQUE", false))
|
||||
);
|
||||
|
||||
List<IndexInfo> enabledIndexes = StandardJdbcMetadata.INSTANCE.listIndexes(
|
||||
enabledConn,
|
||||
profile,
|
||||
"TENANTDB",
|
||||
"APP",
|
||||
"ORDERS"
|
||||
);
|
||||
|
||||
assertEquals(1, enabledIndexes.size());
|
||||
|
||||
JdbcAgentProfile fallbackDisabledProfile = new JdbcAgentProfile(
|
||||
"example.Driver",
|
||||
"jdbc:example://{host}:{port}/{database}",
|
||||
0,
|
||||
false,
|
||||
Collections.emptySet(),
|
||||
Collections.singletonList("TABLE"),
|
||||
"\"",
|
||||
"SET SCHEMA",
|
||||
false,
|
||||
false,
|
||||
false,
|
||||
false
|
||||
);
|
||||
Connection disabledConn = catalogIndexFallbackConnection(
|
||||
"TENANTDB",
|
||||
rows(),
|
||||
rows(row("INDEX_NAME", "IDX_ORDERS", "COLUMN_NAME", "ID", "ORDINAL_POSITION", (short) 1, "NON_UNIQUE", false))
|
||||
);
|
||||
|
||||
List<IndexInfo> disabledIndexes = StandardJdbcMetadata.INSTANCE.listIndexes(
|
||||
disabledConn,
|
||||
fallbackDisabledProfile,
|
||||
"TENANTDB",
|
||||
"APP",
|
||||
"ORDERS"
|
||||
);
|
||||
|
||||
assertTrue(disabledIndexes.isEmpty());
|
||||
}
|
||||
|
||||
@Test
|
||||
void mapsForeignKeysAndEmptyTriggers() {
|
||||
Connection conn = connection(
|
||||
@@ -667,6 +716,31 @@ class StandardJdbcMetadataTest {
|
||||
});
|
||||
}
|
||||
|
||||
private static Connection catalogIndexFallbackConnection(
|
||||
String fallbackCatalog,
|
||||
ResultSet defaultIndexes,
|
||||
ResultSet fallbackIndexes
|
||||
) {
|
||||
DatabaseMetaData meta = proxy(DatabaseMetaData.class, new MethodHandler() {
|
||||
@Override
|
||||
public Object handle(Method method, Object[] args) {
|
||||
if ("getIndexInfo".equals(method.getName())) {
|
||||
return fallbackCatalog.equals(args[0]) ? fallbackIndexes : defaultIndexes;
|
||||
}
|
||||
return defaultValue(method.getReturnType());
|
||||
}
|
||||
});
|
||||
return proxy(Connection.class, new MethodHandler() {
|
||||
@Override
|
||||
public Object handle(Method method, Object[] args) {
|
||||
if ("getMetaData".equals(method.getName())) {
|
||||
return meta;
|
||||
}
|
||||
return defaultValue(method.getReturnType());
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
private static Connection catalogPrimaryKeyFallbackConnection(
|
||||
String fallbackCatalog,
|
||||
ResultSet defaultPrimaryKeys,
|
||||
|
||||
@@ -90,7 +90,7 @@ fn tdengine_websocket_live_compatibility() {
|
||||
format!("CREATE DATABASE IF NOT EXISTS {database}"),
|
||||
format!("CREATE STABLE IF NOT EXISTS {database}.meters (ts TIMESTAMP, current FLOAT, voltage INT, active BOOL, note NCHAR(32)) TAGS (location NCHAR(64), group_id INT)"),
|
||||
format!("CREATE TABLE IF NOT EXISTS {database}.d1001 USING {database}.meters TAGS ('California.SanFrancisco', 2)"),
|
||||
format!("INSERT INTO {database}.d1001 VALUES ('2026-08-04 10:00:00.001', 10.1, 220, true, 'first') ('2026-08-04 10:00:00.002', 10.2, 221, false, 'second') ('2026-08-04 10:00:00.003', 10.3, 222, true, 'third')")
|
||||
format!("INSERT INTO {database}.d1001 VALUES (1785808800001, 10.1, 220, true, 'first') (1785808800002, 10.2, 221, false, 'second') (1785808800003, 10.3, 222, true, 'third')")
|
||||
]
|
||||
}),
|
||||
);
|
||||
|
||||
@@ -10,6 +10,7 @@ gbase8s native-pushdown java-sql Uses systables with type, filter, stable order,
|
||||
goldendb native-pushdown java-sql Uses information_schema with type, filter, stable order, and LIMIT/OFFSET.
|
||||
h2 native-pushdown java-sql Uses INFORMATION_SCHEMA with type, filter, stable order, and LIMIT/OFFSET.
|
||||
hive intentional-fallback java-sql Uses Hive metadata paths where stable server-side fuzzy paging is not portable, common constraints filter locally.
|
||||
hive-go shared-fallback native-go Uses HiveServer2 metadata APIs, then applies stable filtering and paging in the native agent with a SHOW TABLES fallback.
|
||||
informix native-pushdown java-sql Uses systables/sysprocedures with type, filter, stable order, and SKIP/FIRST.
|
||||
iotdb shared-fallback native-go Uses SHOW DEVICES or SHOW TABLES DETAILS for Tree/Table metadata, then applies stable filtering and paging in the native agent.
|
||||
kingbase-go shared-fallback native-go Uses sys_catalog/information_schema for compatibility-aware metadata, then applies stable filtering and paging in the native agent.
|
||||
|
||||
|
@@ -5,6 +5,8 @@ import { Button } from "@/components/ui/button";
|
||||
import { Badge } from "@/components/ui/badge";
|
||||
import { useToast } from "@/composables/useToast";
|
||||
import { copyToClipboard } from "@/lib/common/clipboard";
|
||||
import { gaussdbMTypeDisplayName } from "@/lib/table/postgresDataTypeHelp";
|
||||
import type { DatabaseType } from "@/types/database";
|
||||
|
||||
export interface ColumnInfo {
|
||||
name: string;
|
||||
@@ -17,10 +19,12 @@ export interface ColumnInfo {
|
||||
extra?: string | null;
|
||||
}
|
||||
|
||||
defineProps<{
|
||||
const props = defineProps<{
|
||||
columns: ColumnInfo[];
|
||||
loading: boolean;
|
||||
error?: string;
|
||||
databaseType?: DatabaseType;
|
||||
isGaussdbM?: boolean;
|
||||
}>();
|
||||
|
||||
const emit = defineEmits<{
|
||||
@@ -30,6 +34,14 @@ const emit = defineEmits<{
|
||||
const { t } = useI18n();
|
||||
const { toast } = useToast();
|
||||
|
||||
function displayDataType(dataType: string | undefined): string {
|
||||
if (!dataType) return "—";
|
||||
if (props.databaseType === "gaussdb" && props.isGaussdbM) {
|
||||
return gaussdbMTypeDisplayName(dataType);
|
||||
}
|
||||
return dataType;
|
||||
}
|
||||
|
||||
async function copyText(text: string) {
|
||||
try {
|
||||
await copyToClipboard(text);
|
||||
@@ -81,8 +93,8 @@ async function copyText(text: string) {
|
||||
<div class="rounded-md border border-border divide-y divide-border text-xs">
|
||||
<div class="flex items-center justify-between px-2 py-1">
|
||||
<span class="text-muted-foreground">{{ t("grid.columnType") }}</span>
|
||||
<span class="font-medium max-w-[180px] truncate" :title="col.dataType">
|
||||
{{ col.dataType || "—" }}
|
||||
<span class="font-medium max-w-[180px] truncate" :title="displayDataType(col.dataType)">
|
||||
{{ displayDataType(col.dataType) }}
|
||||
</span>
|
||||
</div>
|
||||
<div class="flex items-center justify-between px-2 py-1">
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -1040,7 +1040,15 @@ defineExpose({ focusSearch, refreshData, refreshQueryEditorCompletionCache, hand
|
||||
@click-column="onHandleClickColumn"
|
||||
@close-column-panel="onHandleCloseColumnPanel"
|
||||
/>
|
||||
<ColumnInfoPanel v-if="showColumnInfo" :columns="columnInfoColumns" :loading="columnInfoLoading" :error="columnInfoError" @close="closeColumnInfo" />
|
||||
<ColumnInfoPanel
|
||||
v-if="showColumnInfo"
|
||||
:columns="columnInfoColumns"
|
||||
:loading="columnInfoLoading"
|
||||
:error="columnInfoError"
|
||||
:database-type="activeEffectiveDatabaseType"
|
||||
:is-gaussdb-m="activeEffectiveDatabaseType === 'gaussdb' && activeResultConnection?.driver_profile?.toLowerCase() === 'gaussdb-m'"
|
||||
@close="closeColumnInfo"
|
||||
/>
|
||||
<Button v-if="hasQueryOutput && !resultsPaneOpen" variant="secondary" size="sm" class="absolute bottom-3 right-3 z-20 h-7 gap-1.5 rounded-full border bg-background/95 px-3 text-xs shadow-lg hover:bg-accent" @click="resultsPaneOpen = true">
|
||||
<ChevronUp class="h-3.5 w-3.5" />
|
||||
{{ t("editor.showResultsPane") }}
|
||||
|
||||
@@ -125,6 +125,7 @@ import { filterObjectBrowserTableColumns } from "@/lib/table/objectBrowserTableI
|
||||
import { createSidePanelRequestGuard } from "@/lib/table/sidePanelRequestGuard";
|
||||
import { runBatchTableTruncate } from "@/lib/table/batchTableTruncate";
|
||||
import { tableColumnDefaultDisplayValue } from "@/lib/table/tableColumnDefaultPresentation";
|
||||
import { gaussdbMTypeDisplayName } from "@/lib/table/postgresDataTypeHelp";
|
||||
import { cacheObjectBrowserRows, createObjectBrowserRowsCacheWriteToken, getCachedObjectBrowserRows, type ObjectBrowserRowsCacheScope, type ObjectBrowserRowsCacheWriteToken } from "@/lib/table/objectBrowserRowsCache";
|
||||
import { createObjectBrowserRowsLoadGuard, type ObjectBrowserRowsLoadHandle } from "@/lib/table/objectBrowserRowsLoadGuard";
|
||||
|
||||
@@ -202,8 +203,16 @@ const sidePanelGuard = createSidePanelRequestGuard();
|
||||
const sidePanelRef = ref<InstanceType<typeof CustomTypeInfoPanel> | null>(null);
|
||||
const tableMetadataCapabilities = computed<TableMetadataCapabilities>(() => getTableMetadataCapabilities(effectiveDatabaseType.value));
|
||||
const effectiveDatabaseType = computed(() => effectiveDatabaseTypeForConnection(props.connection) ?? props.connection.db_type);
|
||||
const isGaussdbM = computed(() => effectiveDatabaseType.value === "gaussdb" && props.connection.driver_profile?.toLowerCase() === "gaussdb-m");
|
||||
const isVictoriaMetrics = computed(() => effectiveDatabaseType.value === "victoriametrics");
|
||||
const objectRowsLabel = computed(() => t(isVictoriaMetrics.value ? "objects.series" : "objects.rows"));
|
||||
|
||||
function gaussdbMColumnType(dataType: string): string {
|
||||
if (isGaussdbM.value) {
|
||||
return gaussdbMTypeDisplayName(dataType);
|
||||
}
|
||||
return dataType;
|
||||
}
|
||||
const tableStructureDatabaseType = computed(() => tableStructureDatabaseTypeForConnection(props.connection) ?? props.connection.db_type);
|
||||
const sourceEditableText = ref("");
|
||||
const sourceDraft = ref("");
|
||||
@@ -3200,7 +3209,7 @@ function getObjectBrowserMenuItems(item: ObjectBrowserRow): ContextMenuItem[] {
|
||||
{{ column.comment }}
|
||||
</div>
|
||||
</td>
|
||||
<td class="px-3 py-2 font-mono text-[11px] text-muted-foreground">{{ column.data_type }}</td>
|
||||
<td class="px-3 py-2 font-mono text-[11px] text-muted-foreground">{{ gaussdbMColumnType(column.data_type) }}</td>
|
||||
<td class="px-3 py-2">{{ column.is_nullable ? "YES" : "NO" }}</td>
|
||||
<td data-table-info-column-default class="max-w-56 px-3 py-2 font-mono text-[11px]" :class="{ 'text-muted-foreground/70': column.column_default == null }" :title="column.column_default ?? undefined">
|
||||
<span class="block max-w-56 truncate">{{ tableColumnDefaultDisplayValue(column.column_default) }}</span>
|
||||
|
||||
@@ -32,7 +32,7 @@ import { invalidateTableMetadataCache } from "@/lib/metadata/tableMetadataCache"
|
||||
import { type BuildTableStructureChangeSqlOptions, type EditableStructureColumn, type EditableStructureForeignKey, type EditableStructureIndex, type EditableStructureTrigger } from "@/lib/table/tableStructureEditorSql";
|
||||
import { PRESET_FIELDS_TEMPLATE_ID, createTableColumnTemplateDrafts } from "@/lib/table/tableColumnTemplates";
|
||||
import { getMysqlDataTypeHelp } from "@/lib/table/mysqlDataTypeHelp";
|
||||
import { getPostgresDataTypeHelp } from "@/lib/table/postgresDataTypeHelp";
|
||||
import { getPostgresDataTypeHelp, gaussdbMTypeDisplayName } from "@/lib/table/postgresDataTypeHelp";
|
||||
import { getSqliteDataTypeHelp } from "@/lib/table/sqliteDataTypeHelp";
|
||||
import { getTableMetadataCapabilities, firstStructureMetadataTab, isStructureMetadataTabSupported } from "@/lib/table/tableMetadataCapabilities";
|
||||
import { hasTableStructureRefreshWork, unloadedTableStructureRefreshScope, visibleTableStructureRefreshScope, type TableStructureRefreshScope } from "@/lib/table/tableStructureMetadataLoading";
|
||||
@@ -1079,6 +1079,16 @@ function dataTypeTooltip(option: string): string | undefined {
|
||||
return undefined;
|
||||
}
|
||||
|
||||
function gaussdbMDataTypeDisplayName(option: string): string {
|
||||
if (databaseType.value === "gaussdb") {
|
||||
const conn = connection.value;
|
||||
if (conn?.driver_profile?.toLowerCase() === "gaussdb-m") {
|
||||
return gaussdbMTypeDisplayName(option);
|
||||
}
|
||||
}
|
||||
return option;
|
||||
}
|
||||
|
||||
async function loadDynamicDataTypeOptions() {
|
||||
const requestId = ++dataTypeOptionsRequestId;
|
||||
const connectionId = props.connectionId;
|
||||
@@ -2801,10 +2811,11 @@ watch([activeTab, ddlLoading], ([tab, loading]) => {
|
||||
:loading-text="t('common.loading')"
|
||||
:allow-custom="true"
|
||||
:option-tooltip="dataTypeTooltip"
|
||||
:display-name="gaussdbMDataTypeDisplayName"
|
||||
:trigger-class="[structureMonoControlClass, 'w-full']"
|
||||
@update:model-value="(v: string) => updateColumnDataType(column, v)"
|
||||
/>
|
||||
<Input v-else :model-value="splitDataType(column.dataType).baseType" :class="[structureMonoControlClass, 'w-full']" disabled />
|
||||
<Input v-else :model-value="gaussdbMDataTypeDisplayName(splitDataType(column.dataType).baseType)" :class="[structureMonoControlClass, 'w-full']" disabled />
|
||||
</td>
|
||||
<td v-if="columnEditorControls.length" :class="structureCellClass">
|
||||
<Popover v-if="isMysqlEnumDataType(databaseType, column.dataType)">
|
||||
|
||||
@@ -9,6 +9,7 @@ import * as api from "@/lib/backend/api";
|
||||
import { isTauriRuntime } from "@/lib/backend/tauriRuntime";
|
||||
import { copyToClipboard } from "@/lib/common/clipboard";
|
||||
import { effectiveDatabaseTypeForConnection } from "@/lib/database/jdbcDialect";
|
||||
import { gaussdbMTypeDisplayName } from "@/lib/table/postgresDataTypeHelp";
|
||||
import { joinExportedDdls } from "@/lib/export/ddlExport";
|
||||
import { translateBackendError } from "@/i18n/backend-errors";
|
||||
import { sidebarStructureExportTargets } from "@/lib/sidebar/sidebarExportRuntime";
|
||||
@@ -107,8 +108,12 @@ export function useSidebarTreeExportRuntime(options: SidebarTreeExportRuntimeOpt
|
||||
return includeTable ? [t("contextMenu.structureDocTable"), ...headers] : headers;
|
||||
}
|
||||
|
||||
function columnDocCells(target: TreeNode, column: ColumnInfo, includeTable: boolean): unknown[] {
|
||||
const cells = [column.name, column.data_type, column.is_primary_key ? t("contextMenu.structureDocYes") : t("contextMenu.structureDocNo"), column.is_nullable ? t("contextMenu.structureDocYes") : t("contextMenu.structureDocNo"), column.column_default, column.comment];
|
||||
function columnDocCells(target: TreeNode & { connectionId: string }, column: ColumnInfo, includeTable: boolean): unknown[] {
|
||||
const config = connectionStore.getConfig(target.connectionId);
|
||||
const isGaussdbM = effectiveDatabaseTypeForConnection(config) === "gaussdb" && config?.driver_profile?.toLowerCase() === "gaussdb-m";
|
||||
const sourceDataType = column.data_type;
|
||||
const dataType = isGaussdbM && sourceDataType ? gaussdbMTypeDisplayName(sourceDataType) : sourceDataType;
|
||||
const cells = [column.name, dataType, column.is_primary_key ? t("contextMenu.structureDocYes") : t("contextMenu.structureDocNo"), column.is_nullable ? t("contextMenu.structureDocYes") : t("contextMenu.structureDocNo"), column.column_default, column.comment];
|
||||
return includeTable ? [structureTargetName(target), ...cells] : cells;
|
||||
}
|
||||
|
||||
|
||||
@@ -153,3 +153,26 @@ function floatHelpKey(normalizedType: string): "real" | "double" | undefined {
|
||||
if (value >= 1 && value <= 24) return "real";
|
||||
return value >= 25 && value <= 53 ? "double" : undefined;
|
||||
}
|
||||
|
||||
/**
|
||||
* Converts a GaussDB M-mode PostgreSQL internal type name to its MySQL-style
|
||||
* display name. Returns the original name if no conversion applies.
|
||||
*
|
||||
* GaussDB M mode returns PostgreSQL internal type names (e.g. bpchar, int4,
|
||||
* numeric, int1) but should display MySQL-compatible names.
|
||||
*/
|
||||
export function gaussdbMTypeDisplayName(typeName: string): string {
|
||||
const s = typeName.trim().toLowerCase();
|
||||
if (s === "bpchar") return "char";
|
||||
if (s === "int4" || s === "integer") return "int";
|
||||
if (s === "int2" || s === "smallint") return "smallint";
|
||||
if (s === "int8" || s === "bigint") return "bigint";
|
||||
if (s === "int1") return "tinyint";
|
||||
if (s === "numeric") return "decimal";
|
||||
if (s === "float4" || s === "real") return "float";
|
||||
if (s === "float8" || s === "double precision") return "double";
|
||||
if (s === "bool" || s === "boolean") return "boolean";
|
||||
if (s === "character varying") return "varchar";
|
||||
if (s === "character") return "char";
|
||||
return typeName;
|
||||
}
|
||||
|
||||
@@ -73,6 +73,7 @@ import { shouldMarkDisconnected } from "@/lib/connection/connectionHealth";
|
||||
import { connectionAttemptOriginalErrorMessage, connectionAttemptTimeoutMessage, connectionAttemptTimeoutMs } from "@/lib/connection/connectionAttemptTimeout";
|
||||
import { loadTimeoutInheritanceBackup, saveTimeoutInheritanceBackup } from "@/lib/connection/timeoutInheritanceBackup";
|
||||
import { migrateSqlServerLegacyCompatibilityConfig, requiresSqlServerLegacyCompatibilityComponent, SQLSERVER_LEGACY_COMPATIBILITY_DRIVER_KEY } from "@/lib/connection/sqlServerLegacyCompatibility";
|
||||
import { gaussdbMTypeDisplayName } from "@/lib/table/postgresDataTypeHelp";
|
||||
import { deleteTabResultSnapshotsForOwner } from "@/lib/tabs/tabResultCache";
|
||||
import { connectionUsesVisibleSchemaFilter, filterDatabaseNamesForConnection, filterSchemaNamesForConnection, filterVisibleDatabaseNames, normalizeVisibleDatabaseSelection } from "@/lib/database/visibleDatabases";
|
||||
import {
|
||||
@@ -5066,11 +5067,13 @@ export const useConnectionStore = defineStore("connection", () => {
|
||||
const columns = await api.getColumns(connectionId, database, querySchema, table, catalog);
|
||||
const targetNode = treeNodeLoadTarget(load);
|
||||
if (!targetNode) return;
|
||||
const connConfig = getConfig(connectionId);
|
||||
const isGaussdbM = effectiveDatabaseTypeForConnection(connConfig) === "gaussdb" && connConfig?.driver_profile?.toLowerCase() === "gaussdb-m";
|
||||
setChildren(
|
||||
targetNode,
|
||||
columns.map((col) => ({
|
||||
id: `${parentId}:${col.name}`,
|
||||
label: `${col.name} (${col.data_type})`,
|
||||
label: `${col.name} (${isGaussdbM ? gaussdbMTypeDisplayName(col.data_type) : col.data_type})`,
|
||||
type: "column" as const,
|
||||
connectionId,
|
||||
database,
|
||||
|
||||
Reference in New Issue
Block a user