initial
This commit is contained in:
+182
@@ -0,0 +1,182 @@
|
||||
package gormcol
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"reflect"
|
||||
"strings"
|
||||
|
||||
"gorm.io/gorm/schema"
|
||||
)
|
||||
|
||||
// NamingStrategy is the GORM naming strategy used for column/table name resolution.
|
||||
// Defaults to gorm.io/gorm/schema.NamingStrategy.
|
||||
// Set this to NamingStrategy when using within a project that has a database connection.
|
||||
var NamingStrategy schema.Namer = schema.NamingStrategy{}
|
||||
|
||||
type Tabler interface {
|
||||
TableName() string
|
||||
}
|
||||
|
||||
// Field represents a GORM column descriptor with table context.
|
||||
// Define package-level variables to get type-safe column references:
|
||||
//
|
||||
// var PsAccess = struct {
|
||||
// IDProfile gormcol.Field
|
||||
// IDAuthorizationRole gormcol.Field
|
||||
// }{
|
||||
// IDProfile: gormcol.Field{Table: "ps_access", Column: "id_profile"},
|
||||
// IDAuthorizationRole: gormcol.Field{Table: "ps_access", Column: "id_authorization_role"},
|
||||
// }
|
||||
type Field struct {
|
||||
Table string
|
||||
Column string
|
||||
}
|
||||
|
||||
// Column returns the column name from a Field descriptor.
|
||||
//
|
||||
// gormcol.Column(prestadb.PsAccess.IDAuthorizationRole) // "id_authorization_role"
|
||||
func Column(f Field) string {
|
||||
return f.Column
|
||||
}
|
||||
|
||||
// ColumnOnTable returns "table.column" from a Field descriptor.
|
||||
//
|
||||
// gormcol.ColumnOnTable(prestadb.PsAccess.IDAuthorizationRole) // "ps_access.id_authorization_role"
|
||||
func ColumnOnTable(f Field) string {
|
||||
return f.Table + "." + f.Column
|
||||
}
|
||||
|
||||
// TableField returns the table name from a Field descriptor.
|
||||
func TableField(f Field) string {
|
||||
return f.Table
|
||||
}
|
||||
|
||||
// -- Reflection-based utilities (for structs without Field descriptors) --
|
||||
|
||||
// Col extracts the GORM column name from the `gorm:"column:..."` struct tag.
|
||||
//
|
||||
// gormcol.Col[prestadb.PsAccess]("IDAuthorizationRole") // "id_authorization_role"
|
||||
func Col[T any](fieldName string) string {
|
||||
var zero T
|
||||
typ := reflect.TypeOf(zero)
|
||||
return columnFromType(typ, fieldName)
|
||||
}
|
||||
|
||||
// ColOf extracts a GORM column name from a field on a nested struct referenced
|
||||
// by structFieldName.
|
||||
func ColOf[T, S any](structFieldName, fieldName string) string {
|
||||
var zero T
|
||||
typ := reflect.TypeOf(zero)
|
||||
|
||||
field, ok := typ.FieldByName(structFieldName)
|
||||
if !ok {
|
||||
panic(fmt.Sprintf("gormcol: struct %q has no field %q", typ.Name(), structFieldName))
|
||||
}
|
||||
|
||||
return columnFromType(field.Type, fieldName)
|
||||
}
|
||||
|
||||
// Tbl returns the table name for a GORM model.
|
||||
// Uses TableName() method if the struct implements Tabler,
|
||||
// otherwise falls back to the GORM naming strategy.
|
||||
//
|
||||
// gormcol.Tbl[prestadb.PsAccess]() // "ps_access"
|
||||
func Tbl[T any]() string {
|
||||
var zero T
|
||||
if t, ok := any(zero).(Tabler); ok {
|
||||
return t.TableName()
|
||||
}
|
||||
typ := reflect.TypeOf(zero)
|
||||
return NamingStrategy.TableName(typ.Name())
|
||||
}
|
||||
|
||||
// ColOnTbl returns the column prefixed with the table name (reflection-based).
|
||||
//
|
||||
// gormcol.ColOnTbl[prestadb.PsAccess]("IDAuthorizationRole") // "ps_access.id_authorization_role"
|
||||
func ColOnTbl[T any](fieldName string) string {
|
||||
return Tbl[T]() + "." + Col[T](fieldName)
|
||||
}
|
||||
|
||||
// PK returns the primary key column name for a GORM model.
|
||||
//
|
||||
// gormcol.PK[prestadb.PsAccess]() // "id_authorization_role"
|
||||
func PK[T any]() string {
|
||||
var zero T
|
||||
typ := reflect.TypeOf(zero)
|
||||
|
||||
for i := 0; i < typ.NumField(); i++ {
|
||||
field := typ.Field(i)
|
||||
gormTag := field.Tag.Get("gorm")
|
||||
if gormTag == "" || gormTag == "-" {
|
||||
continue
|
||||
}
|
||||
for _, part := range strings.Split(gormTag, ";") {
|
||||
if strings.TrimSpace(part) == "primaryKey" {
|
||||
return parseGormColumn(gormTag)
|
||||
}
|
||||
}
|
||||
}
|
||||
return ""
|
||||
}
|
||||
|
||||
// Columns returns all GORM column names for a struct type.
|
||||
//
|
||||
// gormcol.Columns[prestadb.PsAccess]() // []string{"id_profile", "id_authorization_role"}
|
||||
func Columns[T any]() []string {
|
||||
var zero T
|
||||
typ := reflect.TypeOf(zero)
|
||||
|
||||
var cols []string
|
||||
for i := 0; i < typ.NumField(); i++ {
|
||||
field := typ.Field(i)
|
||||
if field.PkgPath != "" {
|
||||
continue
|
||||
}
|
||||
col := parseGormColumn(field.Tag.Get("gorm"))
|
||||
if col == "" {
|
||||
col = NamingStrategy.ColumnName(typ.Name(), field.Name)
|
||||
}
|
||||
cols = append(cols, col)
|
||||
}
|
||||
return cols
|
||||
}
|
||||
|
||||
// ColByJSON finds the GORM column name by matching the struct field's json tag.
|
||||
//
|
||||
// gormcol.ColByJSON[prestadb.PsAccess]("id_authorization_role") // "id_authorization_role"
|
||||
func ColByJSON[T any](jsonName string) string {
|
||||
var zero T
|
||||
typ := reflect.TypeOf(zero)
|
||||
|
||||
for i := 0; i < typ.NumField(); i++ {
|
||||
field := typ.Field(i)
|
||||
jsonTag := field.Tag.Get("json")
|
||||
if jsonTag == "" {
|
||||
continue
|
||||
}
|
||||
tagName := strings.Split(jsonTag, ",")[0]
|
||||
if tagName == jsonName {
|
||||
return columnFromType(typ, field.Name)
|
||||
}
|
||||
}
|
||||
panic(fmt.Sprintf("gormcol: struct %q has no field with json tag %q", typ.Name(), jsonName))
|
||||
}
|
||||
|
||||
func columnFromType(typ reflect.Type, fieldName string) string {
|
||||
field, ok := typ.FieldByName(fieldName)
|
||||
if !ok {
|
||||
panic(fmt.Sprintf("gormcol: struct %q has no field %q", typ.Name(), fieldName))
|
||||
}
|
||||
|
||||
gormTag := field.Tag.Get("gorm")
|
||||
if gormTag == "" || gormTag == "-" {
|
||||
return NamingStrategy.ColumnName(typ.Name(), fieldName)
|
||||
}
|
||||
|
||||
col := parseGormColumn(gormTag)
|
||||
if col != "" {
|
||||
return col
|
||||
}
|
||||
|
||||
return NamingStrategy.ColumnName(typ.Name(), fieldName)
|
||||
}
|
||||
Reference in New Issue
Block a user