111 lines
3.1 KiB
Go
111 lines
3.1 KiB
Go
package orm
|
|
|
|
import (
|
|
"fmt"
|
|
"reflect"
|
|
"strings"
|
|
)
|
|
|
|
func (m *Model) createTableSql() string {
|
|
var fields []string
|
|
var fks []string
|
|
for _, field := range m.Fields {
|
|
isStructOrSliceOfStructs := field.Type.Kind() == reflect.Struct ||
|
|
((field.Type.Kind() == reflect.Slice || field.Type.Kind() == reflect.Array) &&
|
|
field.Type.Elem().Kind() == reflect.Struct)
|
|
if field.PrimaryKey {
|
|
fields = append(fields, fmt.Sprintf("%s %s PRIMARY KEY", field.ColumnName, field.ColumnType))
|
|
} else if (field.fk != nil && field.fk.Type != HasMany && field.fk.Type != ManyToMany) && field.isForeignKey {
|
|
colType := serialToRegular(field.ColumnType)
|
|
if !field.Nullable {
|
|
colType += " NOT NULL "
|
|
}
|
|
ffk := field.fk.RelatedModel.Fields[field.fk.RelatedModel.IDField]
|
|
if ffk != nil {
|
|
fks = append(fks, fmt.Sprintf("%s %s REFERENCES %s(%s)",
|
|
field.ColumnName, colType,
|
|
field.fk.RelatedModel.TableName,
|
|
field.fk.RelatedModel.Fields[field.fk.RelatedModel.IDField].ColumnName))
|
|
}
|
|
} else if !isStructOrSliceOfStructs || field.ColumnType != "" {
|
|
lalala := fmt.Sprintf("%s %s", field.ColumnName, field.ColumnType)
|
|
if !field.Nullable {
|
|
lalala += " NOT NULL"
|
|
}
|
|
fields = append(fields, lalala)
|
|
}
|
|
}
|
|
inter := strings.Join(fields, ", ")
|
|
if len(fks) > 0 {
|
|
inter += ", "
|
|
inter += strings.Join(fks, ", ")
|
|
}
|
|
return fmt.Sprintf("CREATE TABLE IF NOT EXISTS %s (%s);",
|
|
m.TableName, inter)
|
|
}
|
|
|
|
func (m *Model) createJoinTableSql(relName string) string {
|
|
ref, ok := m.Relationships[relName]
|
|
if !ok {
|
|
return ""
|
|
}
|
|
aTable := m.TableName
|
|
joinTableName := ref.JoinTable()
|
|
fct := serialToRegular(ref.Model.Fields[ref.Model.IDField].ColumnType)
|
|
rct := serialToRegular(ref.RelatedModel.Fields[ref.RelatedModel.IDField].ColumnType)
|
|
pkSection := fmt.Sprintf(",\nPRIMARY KEY (%s, %s_id)",
|
|
fmt.Sprintf("%s_%s",
|
|
aTable, pascalToSnakeCase(ref.FieldName),
|
|
),
|
|
ref.RelatedModel.TableName,
|
|
)
|
|
if ref.Type == HasMany || ref.Type == ManyToMany {
|
|
pkSection = ""
|
|
}
|
|
return fmt.Sprintf(`CREATE TABLE IF NOT EXISTS %s (
|
|
%s %s REFERENCES %s(%s),
|
|
%s_id %s REFERENCES %s(%s)%s
|
|
);`,
|
|
joinTableName,
|
|
fmt.Sprintf("%s_%s",
|
|
aTable, pascalToSnakeCase(ref.FieldName),
|
|
),
|
|
fct,
|
|
ref.Model.TableName, ref.Model.Fields[ref.Model.IDField].ColumnName,
|
|
ref.RelatedModel.TableName,
|
|
rct,
|
|
ref.RelatedModel.TableName, ref.RelatedModel.Fields[ref.RelatedModel.IDField].ColumnName,
|
|
pkSection,
|
|
)
|
|
}
|
|
|
|
func (m *Model) migrate(engine *Engine) error {
|
|
sql := m.createTableSql()
|
|
fmt.Println(sql)
|
|
if !engine.dryRun {
|
|
_, err := engine.conn.Exec(engine.ctx, sql)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
}
|
|
for relName, rel := range m.Relationships {
|
|
relkey := rel.Model.Name
|
|
if (rel.Type == ManyToMany && !engine.m2mSeen[relkey]) ||
|
|
(rel.Model.embeddedIsh && !rel.RelatedModel.embeddedIsh && rel.Type == HasMany) {
|
|
if rel.Type == ManyToMany {
|
|
engine.m2mSeen[relkey] = true
|
|
engine.m2mSeen[rel.RelatedModel.Name] = true
|
|
}
|
|
jtsql := m.createJoinTableSql(relName)
|
|
fmt.Println(jtsql)
|
|
if !engine.dryRun {
|
|
_, err := engine.conn.Exec(engine.ctx, jtsql)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
}
|
|
}
|
|
}
|
|
return nil
|
|
}
|