mirror of
https://gitee.com/johng/gf
synced 2026-06-06 16:21:40 +08:00
90 lines
2.8 KiB
Go
90 lines
2.8 KiB
Go
// Copyright GoFrame Author(https://goframe.org). All Rights Reserved.
|
|
//
|
|
// This Source Code Form is subject to the terms of the MIT License.
|
|
// If a copy of the MIT was not distributed with this file,
|
|
// You can obtain one at https://github.com/gogf/gf.
|
|
|
|
package pgsql
|
|
|
|
import (
|
|
"context"
|
|
"fmt"
|
|
|
|
"github.com/gogf/gf/v2/database/gdb"
|
|
"github.com/gogf/gf/v2/util/gutil"
|
|
)
|
|
|
|
var (
|
|
tableFieldsSqlTmp = `
|
|
SELECT a.attname AS field, t.typname AS type,a.attnotnull as null,
|
|
(case when d.contype = 'p' then 'pri' when d.contype = 'u' then 'uni' else '' end) as key
|
|
,ic.column_default as default_value,b.description as comment
|
|
,coalesce(character_maximum_length, numeric_precision, -1) as length
|
|
,numeric_scale as scale
|
|
FROM pg_attribute a
|
|
left join pg_class c on a.attrelid = c.oid
|
|
left join pg_constraint d on d.conrelid = c.oid and a.attnum = d.conkey[1]
|
|
left join pg_description b ON a.attrelid=b.objoid AND a.attnum = b.objsubid
|
|
left join pg_type t ON a.atttypid = t.oid
|
|
left join information_schema.columns ic on ic.column_name = a.attname and ic.table_name = c.relname
|
|
WHERE c.relname = '%s' and a.attisdropped is false and a.attnum > 0
|
|
ORDER BY a.attnum`
|
|
)
|
|
|
|
func init() {
|
|
var err error
|
|
tableFieldsSqlTmp, err = gdb.FormatMultiLineSqlToSingle(tableFieldsSqlTmp)
|
|
if err != nil {
|
|
panic(err)
|
|
}
|
|
}
|
|
|
|
// TableFields retrieves and returns the fields' information of specified table of current schema.
|
|
func (d *Driver) TableFields(ctx context.Context, table string, schema ...string) (fields map[string]*gdb.TableField, err error) {
|
|
var (
|
|
result gdb.Result
|
|
link gdb.Link
|
|
usedSchema = gutil.GetOrDefaultStr(d.GetSchema(), schema...)
|
|
// TODO duplicated `id` result?
|
|
structureSql = fmt.Sprintf(tableFieldsSqlTmp, table)
|
|
)
|
|
if link, err = d.SlaveLink(usedSchema); err != nil {
|
|
return nil, err
|
|
}
|
|
result, err = d.DoSelect(ctx, link, structureSql)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
fields = make(map[string]*gdb.TableField)
|
|
var (
|
|
index = 0
|
|
name string
|
|
ok bool
|
|
existingField *gdb.TableField
|
|
)
|
|
for _, m := range result {
|
|
name = m["field"].String()
|
|
// Merge duplicated fields, especially for key constraints.
|
|
// Priority: pri > uni > others
|
|
if existingField, ok = fields[name]; ok {
|
|
currentKey := m["key"].String()
|
|
// Merge key information with priority: pri > uni
|
|
if currentKey == "pri" || (currentKey == "uni" && existingField.Key != "pri") {
|
|
existingField.Key = currentKey
|
|
}
|
|
continue
|
|
}
|
|
fields[name] = &gdb.TableField{
|
|
Index: index,
|
|
Name: name,
|
|
Type: m["type"].String(),
|
|
Null: !m["null"].Bool(),
|
|
Key: m["key"].String(),
|
|
Default: m["default_value"].Val(),
|
|
Comment: m["comment"].String(),
|
|
}
|
|
index++
|
|
}
|
|
return fields, nil
|
|
}
|