jet/generator/template/sql_builder_template.go

272 lines
8 KiB
Go
Raw Normal View History

package template
import (
"fmt"
2024-11-26 15:40:34 +06:00
"path/filepath"
"slices"
2021-10-21 13:21:01 +02:00
"strings"
"unicode"
"github.com/go-jet/jet/v2/generator/metadata"
"github.com/go-jet/jet/v2/internal/utils/dbidentifier"
)
// SQLBuilder is template for generating sql builder files
type SQLBuilder struct {
Skip bool
Path string
Table func(table metadata.Table) TableSQLBuilder
View func(view metadata.Table) TableSQLBuilder
Enum func(enum metadata.Enum) EnumSQLBuilder
}
// DefaultSQLBuilder returns default SQLBuilder implementation
func DefaultSQLBuilder() SQLBuilder {
return SQLBuilder{
Path: "",
Table: DefaultTableSQLBuilder,
View: DefaultViewSQLBuilder,
Enum: DefaultEnumSQLBuilder,
}
}
// UsePath returns new SQLBuilder with new relative path set
func (sb SQLBuilder) UsePath(path string) SQLBuilder {
sb.Path = path
return sb
}
// UseTable returns new SQLBuilder with new TableSQLBuilder template function set
func (sb SQLBuilder) UseTable(tableFunc func(table metadata.Table) TableSQLBuilder) SQLBuilder {
sb.Table = tableFunc
return sb
}
// UseView returns new SQLBuilder with new ViewSQLBuilder template function set
func (sb SQLBuilder) UseView(viewFunc func(table metadata.Table) ViewSQLBuilder) SQLBuilder {
sb.View = viewFunc
return sb
}
// UseEnum returns new SQLBuilder with new EnumSQLBuilder template function set
func (sb SQLBuilder) UseEnum(enumFunc func(enum metadata.Enum) EnumSQLBuilder) SQLBuilder {
sb.Enum = enumFunc
return sb
}
// ShouldSkip returns new SQLBuilder with new skip flag set
func (sb SQLBuilder) ShouldSkip(skip bool) SQLBuilder {
sb.Skip = skip
return sb
}
// TableSQLBuilder is template for generating table SQLBuilder files
type TableSQLBuilder struct {
Skip bool
Path string
FileName string
InstanceName string
TypeName string
DefaultAlias string
Column func(columnMetaData metadata.Column) TableSQLBuilderColumn
}
// ViewSQLBuilder is template for generating view SQLBuilder files
type ViewSQLBuilder = TableSQLBuilder
// DefaultTableSQLBuilder returns default implementation for TableSQLBuilder
func DefaultTableSQLBuilder(tableMetaData metadata.Table) TableSQLBuilder {
tableNameGoIdentifier := dbidentifier.ToGoIdentifier(tableMetaData.Name)
return TableSQLBuilder{
Path: "/table",
2023-07-21 14:11:31 +02:00
FileName: dbidentifier.ToGoFileName(tableMetaData.Name),
InstanceName: tableNameGoIdentifier,
TypeName: tableNameGoIdentifier + "Table",
DefaultAlias: "",
Column: DefaultTableSQLBuilderColumn,
}
}
// DefaultViewSQLBuilder returns default implementation for ViewSQLBuilder
func DefaultViewSQLBuilder(viewMetaData metadata.Table) ViewSQLBuilder {
tableSQLBuilder := DefaultTableSQLBuilder(viewMetaData)
tableSQLBuilder.Path = "/view"
return tableSQLBuilder
}
// PackageName returns package name of table sql builder types
func (tb TableSQLBuilder) PackageName() string {
2024-11-26 15:40:34 +06:00
return filepath.Base(tb.Path)
}
// UsePath returns new TableSQLBuilder with new relative path set
func (tb TableSQLBuilder) UsePath(path string) TableSQLBuilder {
tb.Path = path
return tb
}
// UseFileName returns new TableSQLBuilder with new file name set
func (tb TableSQLBuilder) UseFileName(name string) TableSQLBuilder {
tb.FileName = name
return tb
}
// UseInstanceName returns new TableSQLBuilder with new instance name set
func (tb TableSQLBuilder) UseInstanceName(name string) TableSQLBuilder {
tb.InstanceName = name
return tb
}
// UseTypeName returns new TableSQLBuilder with new type name set
func (tb TableSQLBuilder) UseTypeName(name string) TableSQLBuilder {
tb.TypeName = name
return tb
}
// UseDefaultAlias returns new TableSQLBuilder with new default alias set
func (tb TableSQLBuilder) UseDefaultAlias(defaultAlias string) TableSQLBuilder {
tb.DefaultAlias = defaultAlias
return tb
}
// UseColumn returns new TableSQLBuilder with new column template function set
func (tb TableSQLBuilder) UseColumn(columnsFunc func(column metadata.Column) TableSQLBuilderColumn) TableSQLBuilder {
tb.Column = columnsFunc
return tb
}
// TableSQLBuilderColumn is template for table sql builder column
type TableSQLBuilderColumn struct {
Skip bool
Name string
Type string
}
2025-02-06 09:34:22 +01:00
var reservedKeywords = []string{"TableName", "Table", "SchemaName", "Alias", "AllColumns", "MutableColumns", "DefaultColumns"}
func renameIfReserved(name string) string {
if slices.Contains(reservedKeywords, name) {
return name + "_"
}
return name
}
// DefaultTableSQLBuilderColumn returns default implementation of TableSQLBuilderColumn
func DefaultTableSQLBuilderColumn(columnMetaData metadata.Column) TableSQLBuilderColumn {
return TableSQLBuilderColumn{
Name: renameIfReserved(dbidentifier.ToGoIdentifier(columnMetaData.Name)),
Type: getSqlBuilderColumnType(columnMetaData),
}
}
// getSqlBuilderColumnType returns type of jet sql builder column
func getSqlBuilderColumnType(columnMetaData metadata.Column) string {
2024-02-01 15:20:49 +01:00
if columnMetaData.DataType.Kind != metadata.BaseType &&
columnMetaData.DataType.Kind != metadata.RangeType {
return "String"
}
2021-10-21 13:21:01 +02:00
switch strings.ToLower(columnMetaData.DataType.Name) {
2024-02-01 15:20:49 +01:00
case "boolean", "bool":
return "Bool"
2024-02-01 15:20:49 +01:00
case "smallint", "integer", "bigint", "int2", "int4", "int8",
"tinyint", "mediumint", "int", "year": //MySQL
return "Integer"
case "date":
return "Date"
case "timestamp without time zone",
"timestamp", "datetime": //MySQL:
return "Timestamp"
2024-02-01 15:20:49 +01:00
case "timestamp with time zone", "timestamptz":
return "Timestampz"
case "time without time zone",
"time": //MySQL
return "Time"
2024-02-01 15:20:49 +01:00
case "time with time zone", "timetz":
return "Timez"
case "interval":
return "Interval"
2025-02-28 18:23:15 +01:00
case "user-defined", "enum", "text", "character", "character varying", "uuid",
"tsvector", "bit", "bit varying", "money", "json", "jsonb", "xml", "point", "line", "ARRAY",
2025-02-28 18:23:15 +01:00
"char", "varchar", "nvarchar", "bpchar", "varbit",
"tinytext", "mediumtext", "longtext": // MySQL
return "String"
2025-02-28 18:23:15 +01:00
case "bytea": // postgres
return "Bytea"
case "binary", "varbinary", "tinyblob", "mediumblob", "longblob", "blob": // mysql and sqlite
return "Blob"
2024-02-01 15:20:49 +01:00
case "real", "numeric", "decimal", "double precision", "float", "float4", "float8",
"double": // MySQL
return "Float"
case "daterange":
return "DateRange"
case "tsrange":
return "TimestampRange"
case "tstzrange":
return "TimestampzRange"
case "int4range":
return "Int4Range"
case "int8range":
return "Int8Range"
case "numrange":
return "NumericRange"
default:
fmt.Println("- [SQL Builder] Unsupported sql column '" + columnMetaData.Name + " " + columnMetaData.DataType.Name + "', using StringColumn instead.")
return "String"
}
}
// EnumSQLBuilder is template for generating enum SQLBuilder files
type EnumSQLBuilder struct {
Skip bool
Path string
FileName string
InstanceName string
ValueName func(enumValue string) string
}
// DefaultEnumSQLBuilder returns default implementation of EnumSQLBuilder
func DefaultEnumSQLBuilder(enumMetaData metadata.Enum) EnumSQLBuilder {
return EnumSQLBuilder{
Path: "/enum",
2023-07-21 14:11:31 +02:00
FileName: dbidentifier.ToGoFileName(enumMetaData.Name),
InstanceName: dbidentifier.ToGoIdentifier(enumMetaData.Name),
ValueName: func(enumValue string) string {
return defaultEnumValueName(enumMetaData.Name, enumValue)
},
}
}
// PackageName returns enum sql builder package name
func (e EnumSQLBuilder) PackageName() string {
2024-11-26 15:40:34 +06:00
return filepath.Base(e.Path)
}
// UsePath returns new EnumSQLBuilder with new path set
func (e EnumSQLBuilder) UsePath(path string) EnumSQLBuilder {
e.Path = path
return e
}
// UseFileName returns new EnumSQLBuilder with new file name set
func (e EnumSQLBuilder) UseFileName(name string) EnumSQLBuilder {
e.FileName = name
return e
}
// UseInstanceName returns new EnumSQLBuilder with instance name set
func (e EnumSQLBuilder) UseInstanceName(name string) EnumSQLBuilder {
e.InstanceName = name
return e
}
func defaultEnumValueName(enumName, enumValue string) string {
2023-07-21 14:11:31 +02:00
enumValueName := dbidentifier.ToGoIdentifier(enumValue)
if !unicode.IsLetter([]rune(enumValueName)[0]) {
2023-07-21 14:11:31 +02:00
return dbidentifier.ToGoIdentifier(enumName) + enumValueName
}
return enumValueName
}