186 lines
3.7 KiB
Go
186 lines
3.7 KiB
Go
package simpleorm
|
|
|
|
import (
|
|
"errors"
|
|
"reflect"
|
|
"strings"
|
|
"time"
|
|
)
|
|
|
|
type Table struct {
|
|
Name string
|
|
Type reflect.Type
|
|
Columns []Column
|
|
Constraints []Constraint
|
|
}
|
|
|
|
func (t Table) ToDDL() string {
|
|
var ddl strings.Builder
|
|
ddl.WriteString("CREATE TABLE IF NOT EXISTS " + t.Name + " (")
|
|
for i, col := range t.Columns {
|
|
if i != 0 {
|
|
ddl.WriteString(", ")
|
|
}
|
|
ddl.WriteString(col.ToDDL())
|
|
}
|
|
for _, constr := range t.Constraints {
|
|
ddl.WriteString(", " + constr.ToDDL())
|
|
}
|
|
|
|
ddl.WriteString(");")
|
|
return ddl.String()
|
|
}
|
|
|
|
func (t Table) ToSelectDML() string {
|
|
var dml strings.Builder
|
|
dml.WriteString("SELECT ")
|
|
|
|
for i, col := range t.Columns {
|
|
if i != 0 {
|
|
dml.WriteString(", ")
|
|
}
|
|
dml.WriteString(col.Name)
|
|
}
|
|
|
|
dml.WriteString(" FROM " + t.Name)
|
|
return dml.String()
|
|
}
|
|
|
|
func (t Table) ToInsertDML(count int) string {
|
|
var dml strings.Builder
|
|
dml.WriteString("INSERT INTO " + camelToSnake(t.Type.Name()) + " (")
|
|
|
|
columnsLen := len(t.Columns)
|
|
effectiveColumnsLen := 0
|
|
for i, col := range t.Columns {
|
|
_, ok := col.Modifiers["pk"]
|
|
if ok {
|
|
continue
|
|
}
|
|
|
|
dml.WriteString(col.Name)
|
|
if i != columnsLen-1 {
|
|
dml.WriteString(", ")
|
|
}
|
|
effectiveColumnsLen++
|
|
}
|
|
|
|
dml.WriteString(") VALUES")
|
|
|
|
for i := range count {
|
|
if i != 0 {
|
|
dml.WriteString(", ")
|
|
}
|
|
for j := range effectiveColumnsLen {
|
|
if j == 0 {
|
|
dml.WriteString("(")
|
|
}
|
|
if j != effectiveColumnsLen-1 {
|
|
dml.WriteString("?, ")
|
|
} else {
|
|
dml.WriteString("?)")
|
|
}
|
|
}
|
|
}
|
|
|
|
return dml.String()
|
|
}
|
|
|
|
func (t Table) ToUpdateDML(src any) string {
|
|
var dml strings.Builder
|
|
dml.WriteString("UPDATE " + camelToSnake(t.Type.Name()) + " SET ")
|
|
|
|
var pkCol string
|
|
// Colum names
|
|
for i := 0; i < t.Type.NumField(); i++ {
|
|
field := t.Type.Field(i)
|
|
modifiers := determineModifiers(field.Tag)
|
|
|
|
_, ok := modifiers["pk"]
|
|
if ok {
|
|
pkCol = camelToSnake(field.Name)
|
|
continue
|
|
}
|
|
|
|
if i != t.Type.NumField()-1 {
|
|
dml.WriteString(camelToSnake(field.Name) + " = ?, ")
|
|
} else {
|
|
dml.WriteString(camelToSnake(field.Name) + " = ? ")
|
|
}
|
|
|
|
}
|
|
|
|
dml.WriteString("WHERE " + pkCol + " = ?")
|
|
|
|
return dml.String()
|
|
}
|
|
|
|
func (t Table) ToDeleteDML(src any) string {
|
|
var dml strings.Builder
|
|
dml.WriteString("DELETE FROM " + camelToSnake(t.Type.Name()) + " WHERE ")
|
|
|
|
for i := 0; i < t.Type.NumField(); i++ {
|
|
field := t.Type.Field(i)
|
|
modifiers := determineModifiers(field.Tag)
|
|
_, ok := modifiers["pk"]
|
|
if ok {
|
|
dml.WriteString(camelToSnake(field.Name) + " = ?")
|
|
return dml.String()
|
|
}
|
|
}
|
|
|
|
return ""
|
|
}
|
|
|
|
func (t Table) createSelectResultContainer() []any {
|
|
vals := make([]any, t.Type.NumField())
|
|
for i := range vals {
|
|
switch t.Type.Field(i).Type.Kind().String() {
|
|
case "string":
|
|
var fieldContainer string
|
|
vals[i] = &fieldContainer
|
|
case "int":
|
|
var fieldContainer int
|
|
vals[i] = &fieldContainer
|
|
case "int64", "time.Time":
|
|
var fieldContainer int64
|
|
vals[i] = &fieldContainer
|
|
}
|
|
}
|
|
return vals
|
|
}
|
|
|
|
func (t Table) prepareParams(src any) []any {
|
|
var params []any
|
|
for i := 0; i < t.Type.NumField(); i++ {
|
|
field := t.Type.Field(i)
|
|
modifiers := determineModifiers(field.Tag)
|
|
_, ok := modifiers["pk"]
|
|
if ok {
|
|
continue
|
|
}
|
|
typStr := field.Type.String()
|
|
switch typStr {
|
|
case "time.Time":
|
|
time := reflect.ValueOf(src).Field(i).Interface().(time.Time)
|
|
params = append(params, time.UnixMilli())
|
|
default:
|
|
params = append(params, reflect.ValueOf(src).Field(i).Interface())
|
|
}
|
|
}
|
|
|
|
return params
|
|
}
|
|
|
|
func (t Table) getPk(src any) (any, error) {
|
|
for i := 0; i < t.Type.NumField(); i++ {
|
|
field := t.Type.Field(i)
|
|
modifiers := determineModifiers(field.Tag)
|
|
_, ok := modifiers["pk"]
|
|
if ok {
|
|
return reflect.ValueOf(src).Field(i).Interface(), nil
|
|
}
|
|
}
|
|
return nil, errors.New("Could not determine pk column!")
|
|
}
|