chore: 恢复旧布局基线(迁移改动丢失后重建,apps/packages 布局暂存)
This commit is contained in:
1 parent
a9510235bb
commit
456fa6954b
203 files changed
+18787
-48
No files matched your search
@@ -0,0 +1,121 @@
|
||||
package db
|
||||
|
||||
import (
|
||||
"context"
|
||||
"database/sql"
|
||||
"fmt"
|
||||
"strings"
|
||||
)
|
||||
|
||||
// GetDDL 返回表/视图的建表语句。mysql 族走 SHOW CREATE TABLE,sqlite 读 sqlite_master,
|
||||
// pg/mssql/oracle 用 ListColumns 元数据在 Go 侧拼装 CREATE TABLE。
|
||||
func GetDDL(ctx context.Context, c ConnReq) (string, error) {
|
||||
ctx = reqCtx(ctx)
|
||||
if c.Table == "" {
|
||||
return "", fmt.Errorf("缺少表名")
|
||||
}
|
||||
if isRedis(c.Driver) {
|
||||
return "", fmt.Errorf("该驱动不支持 DDL 查看")
|
||||
}
|
||||
// pg/mssql/oracle:复用列元数据拼装,避免再查一次库
|
||||
switch {
|
||||
case isPostgresFamily(c.Driver), isMSSQL(c.Driver), driverKey(c.Driver) == "oracle":
|
||||
cols, err := ListColumns(ctx, c)
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
return buildDDLFromColumns(c.Driver, c.Table, cols)
|
||||
}
|
||||
var out string
|
||||
err := withDB(c, func(db *sql.DB) error {
|
||||
var err error
|
||||
switch {
|
||||
case isMySQLFamily(c.Driver):
|
||||
out, err = getDDLMySQL(ctx, db, c)
|
||||
case driverKey(c.Driver) == "sqlite":
|
||||
out, err = getDDLSQLite(ctx, db, c.Table)
|
||||
default:
|
||||
err = unsupportedDriverErr(c)
|
||||
}
|
||||
return err
|
||||
})
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
return out, nil
|
||||
}
|
||||
|
||||
// getDDLMySQL SHOW CREATE TABLE 第二列即 DDL(列名随对象类型变化:Create Table/Create View)。
|
||||
func getDDLMySQL(ctx context.Context, dbh *sql.DB, c ConnReq) (string, error) {
|
||||
ident := quoteMySQLIdent(c.Table)
|
||||
if c.Database != "" {
|
||||
ident = quoteMySQLIdent(c.Database) + "." + ident
|
||||
}
|
||||
rows, err := dbh.QueryContext(ctx, "SHOW CREATE TABLE "+ident)
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
defer rows.Close()
|
||||
if rows.Next() {
|
||||
var name string
|
||||
var ddl sql.NullString
|
||||
if err := rows.Scan(&name, &ddl); err != nil {
|
||||
return "", err
|
||||
}
|
||||
if !ddl.Valid {
|
||||
return "", fmt.Errorf("无法读取 %s 的 DDL", c.Table)
|
||||
}
|
||||
return ddl.String, nil
|
||||
}
|
||||
if err := rows.Err(); err != nil {
|
||||
return "", err
|
||||
}
|
||||
return "", fmt.Errorf("表 %s 不存在", c.Table)
|
||||
}
|
||||
|
||||
// getDDLSQLite sqlite_master 的 sql 列即建表语句。
|
||||
func getDDLSQLite(ctx context.Context, dbh *sql.DB, table string) (string, error) {
|
||||
var ddl sql.NullString
|
||||
err := dbh.QueryRowContext(ctx, `SELECT sql FROM sqlite_master WHERE name = ?`, table).Scan(&ddl)
|
||||
if err == sql.ErrNoRows {
|
||||
return "", fmt.Errorf("表 %s 不存在", table)
|
||||
}
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
if !ddl.Valid {
|
||||
return "", fmt.Errorf("表 %s 无 DDL 记录", table)
|
||||
}
|
||||
return ddl.String, nil
|
||||
}
|
||||
|
||||
// buildDDLFromColumns 用列元数据拼装 CREATE TABLE(类型直接用 ColumnInfo.Type)。
|
||||
func buildDDLFromColumns(driver, table string, cols []ColumnInfo) (string, error) {
|
||||
if len(cols) == 0 {
|
||||
return "", fmt.Errorf("表 %s 不存在或无列", table)
|
||||
}
|
||||
var pks []string
|
||||
for _, col := range cols {
|
||||
if col.Key == "PRI" {
|
||||
pks = append(pks, quoteIdentFor(driver, col.Name))
|
||||
}
|
||||
}
|
||||
var b strings.Builder
|
||||
fmt.Fprintf(&b, "CREATE TABLE %s (\n", quoteTableNameFor(driver, table))
|
||||
for i, col := range cols {
|
||||
line := " " + quoteIdentFor(driver, col.Name) + " " + col.Type
|
||||
if !col.Nullable {
|
||||
line += " NOT NULL"
|
||||
}
|
||||
// 非最后一列、或后面还有 PRIMARY KEY 子句时需要逗号
|
||||
if i < len(cols)-1 || len(pks) > 0 {
|
||||
line += ","
|
||||
}
|
||||
b.WriteString(line + "\n")
|
||||
}
|
||||
if len(pks) > 0 {
|
||||
b.WriteString(" PRIMARY KEY (" + strings.Join(pks, ", ") + ")\n")
|
||||
}
|
||||
b.WriteString(");\n")
|
||||
return b.String(), nil
|
||||
}
|
||||
Reference in new issue
Block a user