From fda30539b68556034854c1594d5915531dbb422d Mon Sep 17 00:00:00 2001 From: Syngnat Date: Sat, 14 Feb 2026 15:45:02 +0800 Subject: [PATCH] =?UTF-8?q?=20=F0=9F=90=9B=20fix(highgo):=20=E4=BF=AE?= =?UTF-8?q?=E5=A4=8D=E6=B5=B7=E9=87=8F=E6=95=B0=E6=8D=AE=E6=BA=90=E5=A4=8D?= =?UTF-8?q?=E5=88=B6=E8=A1=A8=E7=BB=93=E6=9E=84=E4=BB=85=E8=BF=94=E5=9B=9E?= =?UTF-8?q?=E6=B3=A8=E9=87=8A?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - 识别 HighGo 占位建表语句 - 通过 GetColumns 生成包含字段与主键的建表SQL - 避免右键复制表结构出现空字段 - refs #99 --- internal/app/methods_db.go | 111 +++++++++++++++++++++++++++++++++++++ 1 file changed, 111 insertions(+) diff --git a/internal/app/methods_db.go b/internal/app/methods_db.go index 5d8b382..47587f6 100644 --- a/internal/app/methods_db.go +++ b/internal/app/methods_db.go @@ -465,6 +465,7 @@ func (a *App) DBGetTables(config connection.ConnectionConfig, dbName string) con func (a *App) DBShowCreateTable(config connection.ConnectionConfig, dbName string, tableName string) connection.QueryResult { runConfig := normalizeRunConfig(config, dbName) + dbType := resolveDDLDBType(config) dbInst, err := a.getDatabase(runConfig) if err != nil { @@ -478,10 +479,120 @@ func (a *App) DBShowCreateTable(config connection.ConnectionConfig, dbName strin logger.Error(err, "DBShowCreateTable 获取建表语句失败:%s 表=%s", formatConnSummary(runConfig), tableName) return connection.QueryResult{Success: false, Message: err.Error()} } + if shouldFallbackCreateStatement(dbType, sqlStr) { + columns, colErr := dbInst.GetColumns(schemaName, pureTableName) + if colErr != nil { + logger.Error(colErr, "DBShowCreateTable 兜底加载字段失败:%s 表=%s", formatConnSummary(runConfig), tableName) + return connection.QueryResult{Success: false, Message: colErr.Error()} + } + fallbackDDL, buildErr := buildFallbackCreateStatement(dbType, schemaName, pureTableName, columns) + if buildErr != nil { + logger.Error(buildErr, "DBShowCreateTable 兜底生成 DDL 失败:%s 表=%s", formatConnSummary(runConfig), tableName) + return connection.QueryResult{Success: false, Message: buildErr.Error()} + } + sqlStr = fallbackDDL + } return connection.QueryResult{Success: true, Data: sqlStr} } +func shouldFallbackCreateStatement(dbType string, ddl string) bool { + switch dbType { + case "postgres", "kingbase", "highgo", "vastbase": + default: + return false + } + + trimmed := strings.TrimSpace(ddl) + if trimmed == "" { + return true + } + if hasCreateTableHead(trimmed) { + return false + } + + lower := strings.ToLower(trimmed) + if strings.Contains(lower, "not fully supported") || + strings.Contains(lower, "not directly supported") || + strings.Contains(lower, "not supported") { + return true + } + return true +} + +func hasCreateTableHead(sqlText string) bool { + lines := strings.Split(sqlText, "\n") + for _, line := range lines { + line = strings.TrimSpace(line) + if line == "" { + continue + } + if strings.HasPrefix(line, "--") || strings.HasPrefix(line, "/*") || strings.HasPrefix(line, "*") { + continue + } + return strings.HasPrefix(strings.ToLower(line), "create table") + } + return false +} + +func buildFallbackCreateStatement(dbType string, schemaName string, tableName string, columns []connection.ColumnDefinition) (string, error) { + table := strings.TrimSpace(tableName) + if table == "" { + return "", fmt.Errorf("表名不能为空") + } + if len(columns) == 0 { + return "", fmt.Errorf("未获取到字段定义,无法生成建表语句") + } + + qualifiedTable := quoteTableIdentByType(dbType, schemaName, table) + columnLines := make([]string, 0, len(columns)+1) + primaryKeys := make([]string, 0, 2) + + for _, col := range columns { + colNameRaw := strings.TrimSpace(col.Name) + if colNameRaw == "" { + continue + } + colType := strings.TrimSpace(col.Type) + if colType == "" { + colType = "text" + } + + colName := quoteIdentByType(dbType, colNameRaw) + defParts := []string{fmt.Sprintf("%s %s", colName, colType)} + + if strings.EqualFold(strings.TrimSpace(col.Nullable), "NO") { + defParts = append(defParts, "NOT NULL") + } + if col.Default != nil { + defVal := strings.TrimSpace(*col.Default) + if defVal != "" { + defParts = append(defParts, "DEFAULT "+defVal) + } + } + + columnLines = append(columnLines, " "+strings.Join(defParts, " ")) + if strings.EqualFold(strings.TrimSpace(col.Key), "PRI") { + primaryKeys = append(primaryKeys, colName) + } + } + + if len(columnLines) == 0 { + return "", fmt.Errorf("字段定义为空,无法生成建表语句") + } + if len(primaryKeys) > 0 { + columnLines = append(columnLines, " PRIMARY KEY ("+strings.Join(primaryKeys, ", ")+")") + } + + ddl := strings.Builder{} + ddl.WriteString("CREATE TABLE ") + ddl.WriteString(qualifiedTable) + ddl.WriteString(" (\n") + ddl.WriteString(strings.Join(columnLines, ",\n")) + ddl.WriteString("\n);") + return ddl.String(), nil +} + func (a *App) DBGetColumns(config connection.ConnectionConfig, dbName string, tableName string) connection.QueryResult { runConfig := normalizeRunConfig(config, dbName)