2024-01-30 20:03:58 +08:00
// 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 dm
import (
"context"
"fmt"
"strings"
2025-12-03 17:52:05 +08:00
"github.com/gogf/gf/v2/container/gmap"
2024-01-30 20:03:58 +08:00
"github.com/gogf/gf/v2/database/gdb"
"github.com/gogf/gf/v2/util/gutil"
)
2025-12-03 17:52:05 +08:00
// escapeSingleQuote escapes single quotes in the string to prevent SQL injection.
// In SQL, single quotes are escaped by doubling them (two single quotes).
func escapeSingleQuote ( s string ) string {
return strings . ReplaceAll ( s , "'" , "''" )
}
2024-01-30 20:03:58 +08:00
const (
2025-12-03 17:52:05 +08:00
tableFieldsSqlTmp = ` SELECT c.COLUMN_NAME, c.DATA_TYPE, c.DATA_DEFAULT, c.NULLABLE, cc.COMMENTS FROM ALL_TAB_COLUMNS c LEFT JOIN ALL_COL_COMMENTS cc ON c.COLUMN_NAME = cc.COLUMN_NAME AND c.TABLE_NAME = cc.TABLE_NAME AND c.OWNER = cc.OWNER WHERE c.TABLE_NAME = '%s' AND c.OWNER = '%s' `
tableFieldsPkSqlSchemaTmp = ` SELECT COLS.COLUMN_NAME AS PRIMARY_KEY_COLUMN FROM USER_CONSTRAINTS CONS JOIN USER_CONS_COLUMNS COLS ON CONS.CONSTRAINT_NAME = COLS.CONSTRAINT_NAME WHERE CONS.TABLE_NAME = '%s' AND CONS.CONSTRAINT_TYPE = 'P' `
tableFieldsPkSqlDBATmp = ` SELECT COLS.COLUMN_NAME AS PRIMARY_KEY_COLUMN FROM DBA_CONSTRAINTS CONS JOIN DBA_CONS_COLUMNS COLS ON CONS.CONSTRAINT_NAME = COLS.CONSTRAINT_NAME WHERE CONS.TABLE_NAME = '%s' AND CONS.OWNER = '%s' AND CONS.CONSTRAINT_TYPE = 'P' `
2024-01-30 20:03:58 +08:00
)
// 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 (
2025-12-03 17:52:05 +08:00
result gdb . Result
pkResult gdb . Result
link gdb . Link
2024-01-30 20:03:58 +08:00
// When no schema is specified, the configuration item is returned by default
usedSchema = gutil . GetOrDefaultStr ( d . GetSchema ( ) , schema ... )
)
// When usedSchema is empty, return the default link
if link , err = d . SlaveLink ( usedSchema ) ; err != nil {
return nil , err
}
// The link has been distinguished and no longer needs to judge the owner
result , err = d . DoSelect (
ctx , link ,
fmt . Sprintf (
tableFieldsSqlTmp ,
2025-12-03 17:52:05 +08:00
escapeSingleQuote ( strings . ToUpper ( table ) ) ,
escapeSingleQuote ( strings . ToUpper ( d . GetSchema ( ) ) ) ,
2024-01-30 20:03:58 +08:00
) ,
)
if err != nil {
return nil , err
}
2025-12-03 17:52:05 +08:00
// Query the primary key field
pkResult , err = d . DoSelect (
ctx , link ,
fmt . Sprintf ( tableFieldsPkSqlSchemaTmp , escapeSingleQuote ( strings . ToUpper ( table ) ) ) ,
)
if err != nil {
return nil , err
}
if pkResult . IsEmpty ( ) {
pkResult , err = d . DoSelect (
ctx , link ,
fmt . Sprintf ( tableFieldsPkSqlDBATmp , escapeSingleQuote ( strings . ToUpper ( table ) ) , escapeSingleQuote ( strings . ToUpper ( d . GetSchema ( ) ) ) ) ,
)
if err != nil {
return nil , err
}
}
2024-01-30 20:03:58 +08:00
fields = make ( map [ string ] * gdb . TableField )
2025-12-03 17:52:05 +08:00
pkFields := gmap . NewStrStrMap ( )
for _ , pk := range pkResult {
pkFields . Set ( pk [ "PRIMARY_KEY_COLUMN" ] . String ( ) , "PRI" )
}
2024-01-30 20:03:58 +08:00
for i , m := range result {
// m[NULLABLE] returns "N" "Y"
// "N" means not null
// "Y" means could be null
var nullable bool
if m [ "NULLABLE" ] . String ( ) != "N" {
nullable = true
}
fields [ m [ "COLUMN_NAME" ] . String ( ) ] = & gdb . TableField {
Index : i ,
Name : m [ "COLUMN_NAME" ] . String ( ) ,
Type : m [ "DATA_TYPE" ] . String ( ) ,
Null : nullable ,
Default : m [ "DATA_DEFAULT" ] . Val ( ) ,
2025-12-03 17:52:05 +08:00
Key : pkFields . Get ( m [ "COLUMN_NAME" ] . String ( ) ) ,
2024-01-30 20:03:58 +08:00
// Extra: m["Extra"].String(),
2025-12-03 17:52:05 +08:00
Comment : m [ "COMMENTS" ] . String ( ) ,
2024-01-30 20:03:58 +08:00
}
}
return fields , nil
}