231 lines
3.9 KiB
Go
231 lines
3.9 KiB
Go
package schema
|
|
|
|
import (
|
|
"reflect"
|
|
"strings"
|
|
|
|
"git.gdulai.com/gdulai/simpleorm/util"
|
|
)
|
|
|
|
type OrderBy struct {
|
|
Field string
|
|
Direction string
|
|
}
|
|
|
|
type Table struct {
|
|
name string
|
|
typ reflect.Type
|
|
columns []Column
|
|
constraints []Constraint
|
|
}
|
|
|
|
func (t Table) Name() string {
|
|
return t.name
|
|
}
|
|
|
|
func (t Table) Type() reflect.Type {
|
|
return t.typ
|
|
}
|
|
|
|
func (t Table) Columns() []Column {
|
|
return t.columns
|
|
}
|
|
|
|
func (t Table) Constraints() []Constraint {
|
|
return t.constraints
|
|
}
|
|
|
|
func (t Table) GetDDL() (string, error) {
|
|
var ddl strings.Builder
|
|
ddl.WriteString("CREATE TABLE IF NOT EXISTS ")
|
|
ddl.WriteString(t.name)
|
|
ddl.WriteString(" (")
|
|
for i, col := range t.columns {
|
|
if i != 0 {
|
|
ddl.WriteString(", ")
|
|
}
|
|
colDdl, err := col.GetDDL()
|
|
if err != nil {
|
|
return "", err
|
|
}
|
|
ddl.WriteString(colDdl)
|
|
}
|
|
for _, constr := range t.constraints {
|
|
constrDdl, err := constr.GetDDL()
|
|
if err != nil {
|
|
return "", err
|
|
}
|
|
ddl.WriteString(", ")
|
|
ddl.WriteString(constrDdl)
|
|
}
|
|
|
|
ddl.WriteString(");")
|
|
return ddl.String(), nil
|
|
}
|
|
|
|
func (t Table) GetSelectDML() (string, error) {
|
|
var dml strings.Builder
|
|
dml.WriteString("SELECT ")
|
|
|
|
for i, col := range t.columns {
|
|
if i != 0 {
|
|
dml.WriteString(", ")
|
|
}
|
|
colDml, err := col.GetSelectDML()
|
|
if err != nil {
|
|
return "", err
|
|
}
|
|
dml.WriteString(colDml)
|
|
}
|
|
|
|
dml.WriteString(" FROM ")
|
|
dml.WriteString(t.name)
|
|
return dml.String(), nil
|
|
}
|
|
|
|
func (t Table) GetCountDML() string {
|
|
return "SELECT COUNT(*) FROM " + t.name
|
|
}
|
|
|
|
func (t Table) GetInsertDML(count int) (string, error) {
|
|
var dml strings.Builder
|
|
dml.WriteString("INSERT INTO ")
|
|
dml.WriteString(util.CamelToSnake(t.typ.Name()))
|
|
dml.WriteString(" (")
|
|
|
|
columnsLen := len(t.columns)
|
|
effectiveColumnsLen := 0
|
|
for i, col := range t.columns {
|
|
_, ok := col.Modifiers["pk"]
|
|
if ok && t.IsPkAuto() {
|
|
continue
|
|
}
|
|
|
|
colDml, err := col.GetInsertDML()
|
|
if err != nil {
|
|
return "", err
|
|
}
|
|
|
|
dml.WriteString(colDml)
|
|
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("?)")
|
|
}
|
|
}
|
|
}
|
|
|
|
dml.WriteString(" RETURNING *")
|
|
|
|
return dml.String(), nil
|
|
}
|
|
|
|
func (t Table) GetUpdateDML() (string, error) {
|
|
var dml strings.Builder
|
|
dml.WriteString("UPDATE ")
|
|
dml.WriteString(util.CamelToSnake(t.typ.Name()))
|
|
dml.WriteString(" SET ")
|
|
|
|
colLen := len(t.columns)
|
|
var pkColumns []string
|
|
// Colum names
|
|
for i, col := range t.columns {
|
|
modifiers := col.Modifiers
|
|
|
|
_, ok := modifiers["pk"]
|
|
if ok {
|
|
pkColumns = append(pkColumns, col.Name)
|
|
if t.IsPkAuto() {
|
|
continue
|
|
}
|
|
}
|
|
|
|
colDml, err := col.GetUpdateDML()
|
|
if err != nil {
|
|
return "", err
|
|
}
|
|
|
|
if i != colLen-1 {
|
|
dml.WriteString(colDml)
|
|
dml.WriteString(", ")
|
|
} else {
|
|
dml.WriteString(colDml)
|
|
dml.WriteString(" ")
|
|
}
|
|
}
|
|
|
|
dml.WriteString("WHERE ")
|
|
|
|
for i, pkCol := range pkColumns {
|
|
if i != 0 {
|
|
dml.WriteString(" AND ")
|
|
}
|
|
dml.WriteString(pkCol)
|
|
dml.WriteString(" = ?")
|
|
}
|
|
|
|
return dml.String(), nil
|
|
}
|
|
|
|
func (t Table) GetDeleteDML(count int) (string, error) {
|
|
var dml strings.Builder
|
|
dml.WriteString("DELETE FROM ")
|
|
dml.WriteString(t.name)
|
|
dml.WriteString(" WHERE ")
|
|
|
|
for _, col := range t.columns {
|
|
modifiers := col.Modifiers
|
|
|
|
_, ok := modifiers["pk"]
|
|
if ok {
|
|
if count > 1 {
|
|
dml.WriteString(col.Name)
|
|
dml.WriteString(" IN (")
|
|
} else {
|
|
dml.WriteString(col.Name)
|
|
dml.WriteString(" = ")
|
|
}
|
|
}
|
|
}
|
|
|
|
for i := range count {
|
|
if i != 0 {
|
|
dml.WriteString(", ")
|
|
}
|
|
dml.WriteString("?")
|
|
}
|
|
|
|
if count > 1 {
|
|
dml.WriteString(")")
|
|
}
|
|
|
|
return dml.String(), nil
|
|
}
|
|
|
|
func (t Table) IsPkAuto() bool {
|
|
for _, constr := range t.constraints {
|
|
if constr.Type != "pk" {
|
|
continue
|
|
}
|
|
|
|
return len(constr.Columns) == 1
|
|
}
|
|
return true
|
|
}
|