130 lines
2.5 KiB
Go
130 lines
2.5 KiB
Go
package schema
|
|
|
|
import (
|
|
"errors"
|
|
"reflect"
|
|
"strings"
|
|
"time"
|
|
)
|
|
|
|
type Column struct {
|
|
Name string
|
|
FieldName string
|
|
Type string
|
|
Modifiers map[string]string
|
|
}
|
|
|
|
func NewColumn(name string, typ string, fieldName string, tag reflect.StructTag) Column {
|
|
return Column{name, typ, fieldName, determineModifiers(tag)}
|
|
}
|
|
|
|
func determineModifiers(tag reflect.StructTag) map[string]string {
|
|
modifiers := make(map[string]string)
|
|
sqlTag := tag.Get("sql")
|
|
if sqlTag == "" {
|
|
return modifiers
|
|
}
|
|
|
|
rawModifiers := strings.SplitSeq(sqlTag, ";")
|
|
for rawModifier := range rawModifiers {
|
|
if strings.Contains(rawModifier, "=") {
|
|
keyValue := strings.Split(rawModifier, "=")
|
|
modifiers[keyValue[0]] = keyValue[1]
|
|
} else {
|
|
modifiers[rawModifier] = ""
|
|
}
|
|
}
|
|
return modifiers
|
|
}
|
|
|
|
func (c *Column) GetDDL() (string, error) {
|
|
var ddlBuilder strings.Builder
|
|
|
|
ddlBuilder.WriteString(c.Name)
|
|
ddlBuilder.WriteString(" ")
|
|
ddlBuilder.WriteString(c.Type)
|
|
|
|
inlineMods := c.inlineModifiers()
|
|
for _, mod := range inlineMods {
|
|
ddlBuilder.WriteString(" ")
|
|
ddlBuilder.WriteString(mod)
|
|
}
|
|
|
|
return ddlBuilder.String(), nil
|
|
}
|
|
|
|
func (c *Column) inlineModifiers() []string {
|
|
var mods []string
|
|
for k := range c.Modifiers {
|
|
switch k {
|
|
case "nn":
|
|
mods = append(mods, "NOT NULL")
|
|
}
|
|
}
|
|
return mods
|
|
}
|
|
|
|
func (c Column) GetSelectDML() (string, error) {
|
|
return c.Name, nil
|
|
}
|
|
|
|
func (c Column) GetInsertDML() (string, error) {
|
|
return c.Name, nil
|
|
}
|
|
|
|
func (c Column) GetUpdateDML() (string, error) {
|
|
return c.Name + " = ?", nil
|
|
}
|
|
|
|
func (Column) GetDeleteDML() (string, error) {
|
|
return "", errors.New("No delete DML for columns")
|
|
}
|
|
|
|
func (c *Column) IsPK() bool {
|
|
_, ok := c.Modifiers["pk"]
|
|
return ok
|
|
}
|
|
|
|
// Encodes the value to be DB compatible
|
|
func (c Column) Encode(value reflect.Value) any {
|
|
typ := value.Type().String()
|
|
|
|
var encoded any
|
|
switch typ {
|
|
case "time.Time":
|
|
timeVal := value.Interface().(time.Time)
|
|
encoded = timeVal.UnixMilli()
|
|
case "bool":
|
|
boolVal := value.Interface().(bool)
|
|
if boolVal {
|
|
encoded = 1
|
|
} else {
|
|
encoded = false
|
|
}
|
|
default:
|
|
encoded = value.Interface()
|
|
}
|
|
|
|
return encoded
|
|
}
|
|
|
|
// Decodes the raw value from the DBs
|
|
func (c Column) Decode(expected string, rawValue reflect.Value) any {
|
|
var decoded any
|
|
switch expected {
|
|
case "time.Time":
|
|
decoded = time.UnixMilli(rawValue.Interface().(int64))
|
|
case "bool":
|
|
rawValue := rawValue.Interface().(int)
|
|
if rawValue > 0 {
|
|
decoded = true
|
|
} else {
|
|
decoded = false
|
|
}
|
|
default:
|
|
decoded = rawValue.Interface()
|
|
}
|
|
|
|
return decoded
|
|
}
|