🐛 fix(table-designer): 优化结构设计器元数据加载性能

- 字段元数据优先加载并拆分各页签 loading 状态

- 收窄 Oracle 与达梦约束字典查询范围

- 补充结构设计器与字典查询回归测试
This commit is contained in:
Syngnat
2026-07-02 21:15:40 +08:00
parent 0fe3060cf1
commit b0f077ffbb
7 changed files with 277 additions and 82 deletions

View File

@@ -23,6 +23,16 @@ func TestBuildDamengColumnsQuery_IncludesPrimaryKeyMetadata(t *testing.T) {
if !strings.Contains(ownerQuery, "WHERE c.owner = 'BIZ' AND c.table_name = 'ORDERS'") {
t.Fatalf("owner query 应按 owner/table 过滤, got=%s", ownerQuery)
}
for _, want := range []string{
"AND cons.owner = 'BIZ'",
"AND cons.table_name = 'ORDERS'",
"AND cols.owner = 'BIZ'",
"AND cols.table_name = 'ORDERS'",
} {
if !strings.Contains(ownerQuery, want) {
t.Fatalf("owner query 主键子查询应按 owner/table 预过滤 %q, got=%s", want, ownerQuery)
}
}
userQuery := buildDamengColumnsQuery("", "orders")
if !strings.Contains(userQuery, "FROM user_tab_columns c") {
@@ -31,6 +41,41 @@ func TestBuildDamengColumnsQuery_IncludesPrimaryKeyMetadata(t *testing.T) {
if !strings.Contains(userQuery, "JOIN user_cons_columns cols") {
t.Fatalf("user query 应关联 user_cons_columns, got=%s", userQuery)
}
for _, want := range []string{
"AND cons.table_name = 'ORDERS'",
"AND cols.table_name = 'ORDERS'",
} {
if !strings.Contains(userQuery, want) {
t.Fatalf("user query 主键子查询应按 table 预过滤 %q, got=%s", want, userQuery)
}
}
}
func TestBuildDamengForeignKeysQuery_PreFiltersLocalColumnsByTargetTable(t *testing.T) {
t.Parallel()
ownerQuery := buildDamengForeignKeysQuery("biz", "orders")
for _, want := range []string{
"FROM (",
"FROM all_cons_columns",
"WHERE owner = 'BIZ' AND table_name = 'ORDERS'",
"WHERE c.constraint_type = 'R' AND c.owner = 'BIZ' AND c.table_name = 'ORDERS'",
} {
if !strings.Contains(ownerQuery, want) {
t.Fatalf("owner foreign-key query 应按 owner/table 预过滤 %q, got=%s", want, ownerQuery)
}
}
userQuery := buildDamengForeignKeysQuery("", "orders")
for _, want := range []string{
"FROM user_cons_columns",
"WHERE table_name = 'ORDERS'",
"WHERE c.constraint_type = 'R' AND c.table_name = 'ORDERS'",
} {
if !strings.Contains(userQuery, want) {
t.Fatalf("user foreign-key query 应按 table 预过滤 %q, got=%s", want, userQuery)
}
}
}
func TestBuildDamengColumnDefinitions_MarksPrimaryKeyColumns(t *testing.T) {

View File

@@ -333,15 +333,7 @@ func (d *DamengDB) GetIndexes(dbName, tableName string) ([]connection.IndexDefin
func (d *DamengDB) GetForeignKeys(dbName, tableName string) ([]connection.ForeignKeyDefinition, error) {
// Reusing Oracle style query as DM is highly compatible
query := fmt.Sprintf(`SELECT a.constraint_name, a.column_name, c_pk.table_name r_table_name, b.column_name r_column_name
FROM all_cons_columns a
JOIN all_constraints c ON a.owner = c.owner AND a.constraint_name = c.constraint_name
JOIN all_constraints c_pk ON c.r_owner = c_pk.owner AND c.r_constraint_name = c_pk.constraint_name
JOIN all_cons_columns b ON c_pk.owner = b.owner AND c_pk.constraint_name = b.constraint_name AND a.position = b.position
WHERE c.constraint_type = 'R' AND a.owner = '%s' AND a.table_name = '%s'`,
strings.ToUpper(dbName), strings.ToUpper(tableName))
data, _, err := d.Query(query)
data, _, err := d.Query(buildDamengForeignKeysQuery(dbName, tableName))
if err != nil {
return nil, err
}

View File

@@ -118,9 +118,11 @@ func buildDamengColumnsQuery(dbName, tableName string) string {
FROM user_constraints cons
JOIN user_cons_columns cols USING (constraint_name)
WHERE cons.constraint_type = 'P'
AND cons.table_name = '%s'
AND cols.table_name = '%s'
) pk ON c.table_name = pk.table_name AND c.column_name = pk.column_name
WHERE c.table_name = '%s'
ORDER BY c.column_id`, upperTableName)
ORDER BY c.column_id`, upperTableName, upperTableName, upperTableName)
}
return fmt.Sprintf(`SELECT c.column_name, c.data_type, c.data_length, c.char_length, c.data_precision, c.data_scale, c.nullable, c.data_default,
@@ -132,9 +134,41 @@ func buildDamengColumnsQuery(dbName, tableName string) string {
JOIN all_cons_columns cols
ON cons.owner = cols.owner AND cons.constraint_name = cols.constraint_name
WHERE cons.constraint_type = 'P'
AND cons.owner = '%s'
AND cons.table_name = '%s'
AND cols.owner = '%s'
AND cols.table_name = '%s'
) pk ON c.owner = pk.owner AND c.table_name = pk.table_name AND c.column_name = pk.column_name
WHERE c.owner = '%s' AND c.table_name = '%s'
ORDER BY c.column_id`, upperDBName, upperTableName)
ORDER BY c.column_id`, upperDBName, upperTableName, upperDBName, upperTableName, upperDBName, upperTableName)
}
func buildDamengForeignKeysQuery(dbName, tableName string) string {
upperDBName := strings.ToUpper(strings.TrimSpace(dbName))
upperTableName := strings.ToUpper(strings.TrimSpace(tableName))
if upperDBName == "" {
return fmt.Sprintf(`SELECT a.constraint_name, a.column_name, c_pk.table_name r_table_name, b.column_name r_column_name
FROM (
SELECT constraint_name, table_name, column_name, position
FROM user_cons_columns
WHERE table_name = '%s'
) a
JOIN user_constraints c ON a.constraint_name = c.constraint_name
JOIN user_constraints c_pk ON c.r_constraint_name = c_pk.constraint_name
JOIN user_cons_columns b ON c_pk.constraint_name = b.constraint_name AND a.position = b.position
WHERE c.constraint_type = 'R' AND c.table_name = '%s'`, upperTableName, upperTableName)
}
return fmt.Sprintf(`SELECT a.constraint_name, a.column_name, c_pk.table_name r_table_name, b.column_name r_column_name
FROM (
SELECT owner, constraint_name, table_name, column_name, position
FROM all_cons_columns
WHERE owner = '%s' AND table_name = '%s'
) a
JOIN all_constraints c ON a.owner = c.owner AND a.constraint_name = c.constraint_name
JOIN all_constraints c_pk ON c.r_owner = c_pk.owner AND c.r_constraint_name = c_pk.constraint_name
JOIN all_cons_columns b ON c_pk.owner = b.owner AND c_pk.constraint_name = b.constraint_name AND a.position = b.position
WHERE c.constraint_type = 'R' AND c.owner = '%s' AND c.table_name = '%s'`,
upperDBName, upperTableName, upperDBName, upperTableName)
}
func getDamengRowInt(row map[string]interface{}, keys ...string) (int, bool) {

View File

@@ -112,6 +112,39 @@ func TestOracleGetColumnsIncludesColumnComments(t *testing.T) {
}
}
func TestOracleColumnsQueryFiltersPrimaryKeyLookupByTargetTable(t *testing.T) {
t.Parallel()
query := buildOracleColumnsQuery("MYCIMLED", "EDC_LOG")
for _, want := range []string{
`AND cons.owner = 'MYCIMLED'`,
`AND cons.table_name = 'EDC_LOG'`,
`AND cols.owner = 'MYCIMLED'`,
`AND cols.table_name = 'EDC_LOG'`,
`WHERE c.owner = 'MYCIMLED' AND c.table_name = 'EDC_LOG'`,
} {
if !strings.Contains(query, want) {
t.Fatalf("expected Oracle columns query to contain %q, got: %s", want, query)
}
}
}
func TestOracleForeignKeysQueryPreFiltersLocalColumnsByTargetTable(t *testing.T) {
t.Parallel()
query := buildOracleForeignKeysQuery("MYCIMLED", "EDC_LOG")
for _, want := range []string{
`FROM (`,
`FROM all_cons_columns`,
`WHERE owner = 'MYCIMLED' AND table_name = 'EDC_LOG'`,
`WHERE c.constraint_type = 'R' AND c.owner = 'MYCIMLED' AND c.table_name = 'EDC_LOG'`,
} {
if !strings.Contains(query, want) {
t.Fatalf("expected Oracle foreign-key query to contain %q, got: %s", want, query)
}
}
}
func TestOracleGetColumnsPreservesMetadataNameCaseBeforeUppercaseFallback(t *testing.T) {
t.Parallel()

View File

@@ -733,9 +733,11 @@ func buildOracleColumnsQuery(schema string, table string) string {
FROM user_constraints cons
JOIN user_cons_columns cols USING (constraint_name)
WHERE cons.constraint_type = 'P'
AND cons.table_name = '%s'
AND cols.table_name = '%s'
) pk ON c.table_name = pk.table_name AND c.column_name = pk.column_name
WHERE c.table_name = '%s'
ORDER BY c.column_id`, metadataTableName)
ORDER BY c.column_id`, metadataTableName, metadataTableName, metadataTableName)
}
return fmt.Sprintf(`SELECT c.column_name AS "COLUMN_NAME", c.data_type AS "DATA_TYPE", c.data_length AS "DATA_LENGTH", c.char_length AS "CHAR_LENGTH", c.data_precision AS "DATA_PRECISION", c.data_scale AS "DATA_SCALE", c.nullable AS "NULLABLE", c.data_default AS "DATA_DEFAULT",
@@ -750,9 +752,13 @@ func buildOracleColumnsQuery(schema string, table string) string {
JOIN all_cons_columns cols
ON cons.owner = cols.owner AND cons.constraint_name = cols.constraint_name
WHERE cons.constraint_type = 'P'
AND cons.owner = '%s'
AND cons.table_name = '%s'
AND cols.owner = '%s'
AND cols.table_name = '%s'
) pk ON c.owner = pk.owner AND c.table_name = pk.table_name AND c.column_name = pk.column_name
WHERE c.owner = '%s' AND c.table_name = '%s'
ORDER BY c.column_id`, metadataSchemaName, metadataTableName)
ORDER BY c.column_id`, metadataSchemaName, metadataTableName, metadataSchemaName, metadataTableName, metadataSchemaName, metadataTableName)
}
func parseOracleColumns(data []map[string]interface{}) []connection.ColumnDefinition {
@@ -884,19 +890,27 @@ func buildOracleForeignKeysQuery(schema string, table string) string {
metadataSchemaName := escapeOracleMetadataLiteralExact(schema)
if strings.TrimSpace(schema) == "" {
return fmt.Sprintf(`SELECT a.constraint_name, a.column_name, c_pk.table_name r_table_name, b.column_name r_column_name
FROM user_cons_columns a
FROM (
SELECT constraint_name, table_name, column_name, position
FROM user_cons_columns
WHERE table_name = '%s'
) a
JOIN user_constraints c ON a.constraint_name = c.constraint_name
JOIN user_constraints c_pk ON c.r_constraint_name = c_pk.constraint_name
JOIN user_cons_columns b ON c_pk.constraint_name = b.constraint_name AND a.position = b.position
WHERE c.constraint_type = 'R' AND a.table_name = '%s'`, metadataTableName)
WHERE c.constraint_type = 'R' AND c.table_name = '%s'`, metadataTableName, metadataTableName)
}
return fmt.Sprintf(`SELECT a.constraint_name, a.column_name, c_pk.table_name r_table_name, b.column_name r_column_name
FROM all_cons_columns a
FROM (
SELECT owner, constraint_name, table_name, column_name, position
FROM all_cons_columns
WHERE owner = '%s' AND table_name = '%s'
) a
JOIN all_constraints c ON a.owner = c.owner AND a.constraint_name = c.constraint_name
JOIN all_constraints c_pk ON c.r_owner = c_pk.owner AND c.r_constraint_name = c_pk.constraint_name
JOIN all_cons_columns b ON c_pk.owner = b.owner AND c_pk.constraint_name = b.constraint_name AND a.position = b.position
WHERE c.constraint_type = 'R' AND a.owner = '%s' AND a.table_name = '%s'`,
metadataSchemaName, metadataTableName)
WHERE c.constraint_type = 'R' AND c.owner = '%s' AND c.table_name = '%s'`,
metadataSchemaName, metadataTableName, metadataSchemaName, metadataTableName)
}
func parseOracleForeignKeys(data []map[string]interface{}) []connection.ForeignKeyDefinition {