diamond-orm/model_migration.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
}