modify unique to constraint
This commit is contained in:
parent
567f44f14e
commit
fb2ec8caea
@ -82,10 +82,6 @@ func (m Migrator) FullDataTypeOf(field *schema.Field) (expr clause.Expr) {
|
|||||||
expr.SQL += " NOT NULL"
|
expr.SQL += " NOT NULL"
|
||||||
}
|
}
|
||||||
|
|
||||||
if field.Unique {
|
|
||||||
expr.SQL += " UNIQUE"
|
|
||||||
}
|
|
||||||
|
|
||||||
if field.HasDefaultValue && (field.DefaultValueInterface != nil || field.DefaultValue != "") {
|
if field.HasDefaultValue && (field.DefaultValueInterface != nil || field.DefaultValue != "") {
|
||||||
if field.DefaultValueInterface != nil {
|
if field.DefaultValueInterface != nil {
|
||||||
defaultStmt := &gorm.Statement{Vars: []interface{}{field.DefaultValueInterface}}
|
defaultStmt := &gorm.Statement{Vars: []interface{}{field.DefaultValueInterface}}
|
||||||
@ -119,8 +115,9 @@ func (m Migrator) AutoMigrate(values ...interface{}) error {
|
|||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
var (
|
var (
|
||||||
parseIndexes = stmt.Schema.ParseIndexes()
|
parseIndexes = stmt.Schema.ParseIndexes()
|
||||||
parseCheckConstraints = stmt.Schema.ParseCheckConstraints()
|
parseCheckConstraints = stmt.Schema.ParseCheckConstraints()
|
||||||
|
parseUniqueConstraints = stmt.Schema.ParseUniqueConstraints()
|
||||||
)
|
)
|
||||||
for _, dbName := range stmt.Schema.DBNames {
|
for _, dbName := range stmt.Schema.DBNames {
|
||||||
var foundColumn gorm.ColumnType
|
var foundColumn gorm.ColumnType
|
||||||
@ -160,6 +157,14 @@ func (m Migrator) AutoMigrate(values ...interface{}) error {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
for _, uni := range parseUniqueConstraints {
|
||||||
|
if !queryTx.Migrator().HasConstraint(value, uni.Name) {
|
||||||
|
if err := execTx.Migrator().CreateConstraint(value, uni.Name); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
for _, chk := range parseCheckConstraints {
|
for _, chk := range parseCheckConstraints {
|
||||||
if !queryTx.Migrator().HasConstraint(value, chk.Name) {
|
if !queryTx.Migrator().HasConstraint(value, chk.Name) {
|
||||||
if err := execTx.Migrator().CreateConstraint(value, chk.Name); err != nil {
|
if err := execTx.Migrator().CreateConstraint(value, chk.Name); err != nil {
|
||||||
@ -257,7 +262,7 @@ func (m Migrator) CreateTable(values ...interface{}) error {
|
|||||||
}
|
}
|
||||||
if constraint := rel.ParseConstraint(); constraint != nil {
|
if constraint := rel.ParseConstraint(); constraint != nil {
|
||||||
if constraint.Schema == stmt.Schema {
|
if constraint.Schema == stmt.Schema {
|
||||||
sql, vars := buildConstraint(constraint)
|
sql, vars := constraint.Build()
|
||||||
createTableSQL += sql + ","
|
createTableSQL += sql + ","
|
||||||
values = append(values, vars...)
|
values = append(values, vars...)
|
||||||
}
|
}
|
||||||
@ -265,6 +270,11 @@ func (m Migrator) CreateTable(values ...interface{}) error {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
for _, uni := range stmt.Schema.ParseUniqueConstraints() {
|
||||||
|
createTableSQL += "CONSTRAINT ? UNIQUE (?),"
|
||||||
|
values = append(values, clause.Column{Name: uni.Name}, clause.Expr{SQL: stmt.Quote(uni.Field.DBName)})
|
||||||
|
}
|
||||||
|
|
||||||
for _, chk := range stmt.Schema.ParseCheckConstraints() {
|
for _, chk := range stmt.Schema.ParseCheckConstraints() {
|
||||||
createTableSQL += "CONSTRAINT ? CHECK (?),"
|
createTableSQL += "CONSTRAINT ? CHECK (?),"
|
||||||
values = append(values, clause.Column{Name: chk.Name}, clause.Expr{SQL: chk.Constraint})
|
values = append(values, clause.Column{Name: chk.Name}, clause.Expr{SQL: chk.Constraint})
|
||||||
@ -599,37 +609,20 @@ func (m Migrator) DropView(name string) error {
|
|||||||
return m.DB.Exec("DROP VIEW IF EXISTS ?", clause.Table{Name: name}).Error
|
return m.DB.Exec("DROP VIEW IF EXISTS ?", clause.Table{Name: name}).Error
|
||||||
}
|
}
|
||||||
|
|
||||||
func buildConstraint(constraint *schema.Constraint) (sql string, results []interface{}) {
|
|
||||||
sql = "CONSTRAINT ? FOREIGN KEY ? REFERENCES ??"
|
|
||||||
if constraint.OnDelete != "" {
|
|
||||||
sql += " ON DELETE " + constraint.OnDelete
|
|
||||||
}
|
|
||||||
|
|
||||||
if constraint.OnUpdate != "" {
|
|
||||||
sql += " ON UPDATE " + constraint.OnUpdate
|
|
||||||
}
|
|
||||||
|
|
||||||
var foreignKeys, references []interface{}
|
|
||||||
for _, field := range constraint.ForeignKeys {
|
|
||||||
foreignKeys = append(foreignKeys, clause.Column{Name: field.DBName})
|
|
||||||
}
|
|
||||||
|
|
||||||
for _, field := range constraint.References {
|
|
||||||
references = append(references, clause.Column{Name: field.DBName})
|
|
||||||
}
|
|
||||||
results = append(results, clause.Table{Name: constraint.Name}, foreignKeys, clause.Table{Name: constraint.ReferenceSchema.Table}, references)
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
// GuessConstraintAndTable guess statement's constraint and it's table based on name
|
// GuessConstraintAndTable guess statement's constraint and it's table based on name
|
||||||
func (m Migrator) GuessConstraintAndTable(stmt *gorm.Statement, name string) (_ *schema.Constraint, _ *schema.Check, table string) {
|
func (m Migrator) GuessConstraintAndTable(stmt *gorm.Statement, name string) (_ schema.ConstraintInterface, table string) {
|
||||||
if stmt.Schema == nil {
|
if stmt.Schema == nil {
|
||||||
return nil, nil, stmt.Table
|
return nil, stmt.Table
|
||||||
}
|
}
|
||||||
|
|
||||||
checkConstraints := stmt.Schema.ParseCheckConstraints()
|
checkConstraints := stmt.Schema.ParseCheckConstraints()
|
||||||
if chk, ok := checkConstraints[name]; ok {
|
if chk, ok := checkConstraints[name]; ok {
|
||||||
return nil, &chk, stmt.Table
|
return &chk, stmt.Table
|
||||||
|
}
|
||||||
|
|
||||||
|
uniqueConstraints := stmt.Schema.ParseUniqueConstraints()
|
||||||
|
if uni, ok := uniqueConstraints[name]; ok {
|
||||||
|
return &uni, stmt.Table
|
||||||
}
|
}
|
||||||
|
|
||||||
getTable := func(rel *schema.Relationship) string {
|
getTable := func(rel *schema.Relationship) string {
|
||||||
@ -644,7 +637,7 @@ func (m Migrator) GuessConstraintAndTable(stmt *gorm.Statement, name string) (_
|
|||||||
|
|
||||||
for _, rel := range stmt.Schema.Relationships.Relations {
|
for _, rel := range stmt.Schema.Relationships.Relations {
|
||||||
if constraint := rel.ParseConstraint(); constraint != nil && constraint.Name == name {
|
if constraint := rel.ParseConstraint(); constraint != nil && constraint.Name == name {
|
||||||
return constraint, nil, getTable(rel)
|
return constraint, getTable(rel)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -652,40 +645,39 @@ func (m Migrator) GuessConstraintAndTable(stmt *gorm.Statement, name string) (_
|
|||||||
for k := range checkConstraints {
|
for k := range checkConstraints {
|
||||||
if checkConstraints[k].Field == field {
|
if checkConstraints[k].Field == field {
|
||||||
v := checkConstraints[k]
|
v := checkConstraints[k]
|
||||||
return nil, &v, stmt.Table
|
return &v, stmt.Table
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
for k := range uniqueConstraints {
|
||||||
|
if uniqueConstraints[k].Field == field {
|
||||||
|
v := uniqueConstraints[k]
|
||||||
|
return &v, stmt.Table
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
for _, rel := range stmt.Schema.Relationships.Relations {
|
for _, rel := range stmt.Schema.Relationships.Relations {
|
||||||
if constraint := rel.ParseConstraint(); constraint != nil && rel.Field == field {
|
if constraint := rel.ParseConstraint(); constraint != nil && rel.Field == field {
|
||||||
return constraint, nil, getTable(rel)
|
return constraint, getTable(rel)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return nil, nil, stmt.Schema.Table
|
return nil, stmt.Schema.Table
|
||||||
}
|
}
|
||||||
|
|
||||||
// CreateConstraint create constraint
|
// CreateConstraint create constraint
|
||||||
func (m Migrator) CreateConstraint(value interface{}, name string) error {
|
func (m Migrator) CreateConstraint(value interface{}, name string) error {
|
||||||
return m.RunWithValue(value, func(stmt *gorm.Statement) error {
|
return m.RunWithValue(value, func(stmt *gorm.Statement) error {
|
||||||
constraint, chk, table := m.GuessConstraintAndTable(stmt, name)
|
constraint, table := m.GuessConstraintAndTable(stmt, name)
|
||||||
if chk != nil {
|
|
||||||
return m.DB.Exec(
|
|
||||||
"ALTER TABLE ? ADD CONSTRAINT ? CHECK (?)",
|
|
||||||
m.CurrentTable(stmt), clause.Column{Name: chk.Name}, clause.Expr{SQL: chk.Constraint},
|
|
||||||
).Error
|
|
||||||
}
|
|
||||||
|
|
||||||
if constraint != nil {
|
if constraint != nil {
|
||||||
vars := []interface{}{clause.Table{Name: table}}
|
vars := []interface{}{clause.Table{Name: table}}
|
||||||
if stmt.TableExpr != nil {
|
if stmt.TableExpr != nil {
|
||||||
vars[0] = stmt.TableExpr
|
vars[0] = stmt.TableExpr
|
||||||
}
|
}
|
||||||
sql, values := buildConstraint(constraint)
|
sql, values := constraint.Build()
|
||||||
return m.DB.Exec("ALTER TABLE ? ADD "+sql, append(vars, values...)...).Error
|
return m.DB.Exec("ALTER TABLE ? ADD "+sql, append(vars, values...)...).Error
|
||||||
}
|
}
|
||||||
|
|
||||||
return nil
|
return nil
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
@ -693,11 +685,9 @@ func (m Migrator) CreateConstraint(value interface{}, name string) error {
|
|||||||
// DropConstraint drop constraint
|
// DropConstraint drop constraint
|
||||||
func (m Migrator) DropConstraint(value interface{}, name string) error {
|
func (m Migrator) DropConstraint(value interface{}, name string) error {
|
||||||
return m.RunWithValue(value, func(stmt *gorm.Statement) error {
|
return m.RunWithValue(value, func(stmt *gorm.Statement) error {
|
||||||
constraint, chk, table := m.GuessConstraintAndTable(stmt, name)
|
constraint, table := m.GuessConstraintAndTable(stmt, name)
|
||||||
if constraint != nil {
|
if constraint != nil {
|
||||||
name = constraint.Name
|
name = constraint.GetName()
|
||||||
} else if chk != nil {
|
|
||||||
name = chk.Name
|
|
||||||
}
|
}
|
||||||
return m.DB.Exec("ALTER TABLE ? DROP CONSTRAINT ?", clause.Table{Name: table}, clause.Column{Name: name}).Error
|
return m.DB.Exec("ALTER TABLE ? DROP CONSTRAINT ?", clause.Table{Name: table}, clause.Column{Name: name}).Error
|
||||||
})
|
})
|
||||||
@ -708,11 +698,9 @@ func (m Migrator) HasConstraint(value interface{}, name string) bool {
|
|||||||
var count int64
|
var count int64
|
||||||
m.RunWithValue(value, func(stmt *gorm.Statement) error {
|
m.RunWithValue(value, func(stmt *gorm.Statement) error {
|
||||||
currentDatabase := m.DB.Migrator().CurrentDatabase()
|
currentDatabase := m.DB.Migrator().CurrentDatabase()
|
||||||
constraint, chk, table := m.GuessConstraintAndTable(stmt, name)
|
constraint, table := m.GuessConstraintAndTable(stmt, name)
|
||||||
if constraint != nil {
|
if constraint != nil {
|
||||||
name = constraint.Name
|
name = constraint.GetName()
|
||||||
} else if chk != nil {
|
|
||||||
name = chk.Name
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return m.DB.Raw(
|
return m.DB.Raw(
|
||||||
|
@ -1,35 +0,0 @@
|
|||||||
package schema
|
|
||||||
|
|
||||||
import (
|
|
||||||
"regexp"
|
|
||||||
"strings"
|
|
||||||
)
|
|
||||||
|
|
||||||
// reg match english letters and midline
|
|
||||||
var regEnLetterAndMidline = regexp.MustCompile("^[A-Za-z-_]+$")
|
|
||||||
|
|
||||||
type Check struct {
|
|
||||||
Name string
|
|
||||||
Constraint string // length(phone) >= 10
|
|
||||||
*Field
|
|
||||||
}
|
|
||||||
|
|
||||||
// ParseCheckConstraints parse schema check constraints
|
|
||||||
func (schema *Schema) ParseCheckConstraints() map[string]Check {
|
|
||||||
checks := map[string]Check{}
|
|
||||||
for _, field := range schema.FieldsByDBName {
|
|
||||||
if chk := field.TagSettings["CHECK"]; chk != "" {
|
|
||||||
names := strings.Split(chk, ",")
|
|
||||||
if len(names) > 1 && regEnLetterAndMidline.MatchString(names[0]) {
|
|
||||||
checks[names[0]] = Check{Name: names[0], Constraint: strings.Join(names[1:], ","), Field: field}
|
|
||||||
} else {
|
|
||||||
if names[0] == "" {
|
|
||||||
chk = strings.Join(names[1:], ",")
|
|
||||||
}
|
|
||||||
name := schema.namer.CheckerName(schema.Table, field.DBName)
|
|
||||||
checks[name] = Check{Name: name, Constraint: chk, Field: field}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return checks
|
|
||||||
}
|
|
66
schema/constraint.go
Normal file
66
schema/constraint.go
Normal file
@ -0,0 +1,66 @@
|
|||||||
|
package schema
|
||||||
|
|
||||||
|
import (
|
||||||
|
"regexp"
|
||||||
|
"strings"
|
||||||
|
|
||||||
|
"gorm.io/gorm/clause"
|
||||||
|
)
|
||||||
|
|
||||||
|
// reg match english letters and midline
|
||||||
|
var regEnLetterAndMidline = regexp.MustCompile("^[A-Za-z-_]+$")
|
||||||
|
|
||||||
|
type CheckConstraint struct {
|
||||||
|
Name string
|
||||||
|
Constraint string // length(phone) >= 10
|
||||||
|
*Field
|
||||||
|
}
|
||||||
|
|
||||||
|
func (chk *CheckConstraint) GetName() string { return chk.Name }
|
||||||
|
|
||||||
|
func (chk *CheckConstraint) Build() (sql string, vars []interface{}) {
|
||||||
|
return "CONSTRAINT ? CHECK (?)", []interface{}{clause.Column{Name: chk.Name}, clause.Expr{SQL: chk.Constraint}}
|
||||||
|
}
|
||||||
|
|
||||||
|
// ParseCheckConstraints parse schema check constraints
|
||||||
|
func (schema *Schema) ParseCheckConstraints() map[string]CheckConstraint {
|
||||||
|
checks := map[string]CheckConstraint{}
|
||||||
|
for _, field := range schema.FieldsByDBName {
|
||||||
|
if chk := field.TagSettings["CHECK"]; chk != "" {
|
||||||
|
names := strings.Split(chk, ",")
|
||||||
|
if len(names) > 1 && regEnLetterAndMidline.MatchString(names[0]) {
|
||||||
|
checks[names[0]] = CheckConstraint{Name: names[0], Constraint: strings.Join(names[1:], ","), Field: field}
|
||||||
|
} else {
|
||||||
|
if names[0] == "" {
|
||||||
|
chk = strings.Join(names[1:], ",")
|
||||||
|
}
|
||||||
|
name := schema.namer.CheckerName(schema.Table, field.DBName)
|
||||||
|
checks[name] = CheckConstraint{Name: name, Constraint: chk, Field: field}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return checks
|
||||||
|
}
|
||||||
|
|
||||||
|
type UniqueConstraint struct {
|
||||||
|
Name string
|
||||||
|
Field *Field
|
||||||
|
}
|
||||||
|
|
||||||
|
func (uni *UniqueConstraint) GetName() string { return uni.Name }
|
||||||
|
|
||||||
|
func (uni *UniqueConstraint) Build() (sql string, vars []interface{}) {
|
||||||
|
return "CONSTRAINT ? UNIQUE (?)", []interface{}{clause.Column{Name: uni.Name}, clause.Column{Name: uni.Field.DBName}}
|
||||||
|
}
|
||||||
|
|
||||||
|
// ParseUniqueConstraints parse schema unique constraints
|
||||||
|
func (schema *Schema) ParseUniqueConstraints() map[string]UniqueConstraint {
|
||||||
|
uniques := make(map[string]UniqueConstraint)
|
||||||
|
for _, field := range schema.Fields {
|
||||||
|
if field.Unique {
|
||||||
|
name := schema.namer.UniqueName(schema.Table, field.DBName)
|
||||||
|
uniques[name] = UniqueConstraint{Name: name, Field: field}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return uniques
|
||||||
|
}
|
@ -6,6 +6,7 @@ import (
|
|||||||
"testing"
|
"testing"
|
||||||
|
|
||||||
"gorm.io/gorm/schema"
|
"gorm.io/gorm/schema"
|
||||||
|
"gorm.io/gorm/utils/tests"
|
||||||
)
|
)
|
||||||
|
|
||||||
type UserCheck struct {
|
type UserCheck struct {
|
||||||
@ -20,7 +21,7 @@ func TestParseCheck(t *testing.T) {
|
|||||||
t.Fatalf("failed to parse user check, got error %v", err)
|
t.Fatalf("failed to parse user check, got error %v", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
results := map[string]schema.Check{
|
results := map[string]schema.CheckConstraint{
|
||||||
"name_checker": {
|
"name_checker": {
|
||||||
Name: "name_checker",
|
Name: "name_checker",
|
||||||
Constraint: "name <> 'jinzhu'",
|
Constraint: "name <> 'jinzhu'",
|
||||||
@ -53,3 +54,31 @@ func TestParseCheck(t *testing.T) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func TestParseUniqueConstraints(t *testing.T) {
|
||||||
|
type UserUnique struct {
|
||||||
|
Name1 string `gorm:"unique"`
|
||||||
|
Name2 string `gorm:"uniqueIndex"`
|
||||||
|
}
|
||||||
|
|
||||||
|
user, err := schema.Parse(&UserUnique{}, &sync.Map{}, schema.NamingStrategy{})
|
||||||
|
if err != nil {
|
||||||
|
t.Fatalf("failed to parse user unique, got error %v", err)
|
||||||
|
}
|
||||||
|
constraints := user.ParseUniqueConstraints()
|
||||||
|
|
||||||
|
results := map[string]schema.UniqueConstraint{
|
||||||
|
"uni_user_uniques_name1": {
|
||||||
|
Name: "uni_user_uniques_name1",
|
||||||
|
Field: &schema.Field{Name: "Name1", Unique: true},
|
||||||
|
},
|
||||||
|
}
|
||||||
|
for k, result := range results {
|
||||||
|
v, ok := constraints[k]
|
||||||
|
if !ok {
|
||||||
|
t.Errorf("Failed to found unique constraint %v from parsed constraints %+v", k, constraints)
|
||||||
|
}
|
||||||
|
tests.AssertObjEqual(t, result, v, "Name")
|
||||||
|
tests.AssertObjEqual(t, result.Field, v.Field, "Name", "Unique", "UniqueIndex")
|
||||||
|
}
|
||||||
|
}
|
@ -4,6 +4,12 @@ import (
|
|||||||
"gorm.io/gorm/clause"
|
"gorm.io/gorm/clause"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
// ConstraintInterface database constraint interface
|
||||||
|
type ConstraintInterface interface {
|
||||||
|
GetName() string
|
||||||
|
Build() (sql string, vars []interface{})
|
||||||
|
}
|
||||||
|
|
||||||
// GormDataTypeInterface gorm data type interface
|
// GormDataTypeInterface gorm data type interface
|
||||||
type GormDataTypeInterface interface {
|
type GormDataTypeInterface interface {
|
||||||
GormDataType() string
|
GormDataType() string
|
||||||
|
@ -19,6 +19,7 @@ type Namer interface {
|
|||||||
RelationshipFKName(Relationship) string
|
RelationshipFKName(Relationship) string
|
||||||
CheckerName(table, column string) string
|
CheckerName(table, column string) string
|
||||||
IndexName(table, column string) string
|
IndexName(table, column string) string
|
||||||
|
UniqueName(table, column string) string
|
||||||
}
|
}
|
||||||
|
|
||||||
// Replacer replacer interface like strings.Replacer
|
// Replacer replacer interface like strings.Replacer
|
||||||
@ -85,6 +86,11 @@ func (ns NamingStrategy) IndexName(table, column string) string {
|
|||||||
return ns.formatName("idx", table, ns.toDBName(column))
|
return ns.formatName("idx", table, ns.toDBName(column))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// UniqueName generate unique constraint name
|
||||||
|
func (ns NamingStrategy) UniqueName(table, column string) string {
|
||||||
|
return ns.formatName("uni", table, ns.toDBName(column))
|
||||||
|
}
|
||||||
|
|
||||||
func (ns NamingStrategy) formatName(prefix, table, name string) string {
|
func (ns NamingStrategy) formatName(prefix, table, name string) string {
|
||||||
formattedName := strings.ReplaceAll(strings.Join([]string{
|
formattedName := strings.ReplaceAll(strings.Join([]string{
|
||||||
prefix, table, name,
|
prefix, table, name,
|
||||||
|
@ -566,7 +566,7 @@ func (schema *Schema) guessRelation(relation *Relationship, field *Field, cgl gu
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
type Constraint struct {
|
type FKConstraint struct {
|
||||||
Name string
|
Name string
|
||||||
Field *Field
|
Field *Field
|
||||||
Schema *Schema
|
Schema *Schema
|
||||||
@ -577,7 +577,31 @@ type Constraint struct {
|
|||||||
OnUpdate string
|
OnUpdate string
|
||||||
}
|
}
|
||||||
|
|
||||||
func (rel *Relationship) ParseConstraint() *Constraint {
|
func (constraint *FKConstraint) GetName() string { return constraint.Name }
|
||||||
|
|
||||||
|
func (constraint *FKConstraint) Build() (sql string, vars []interface{}) {
|
||||||
|
sql = "CONSTRAINT ? FOREIGN KEY ? REFERENCES ??"
|
||||||
|
if constraint.OnDelete != "" {
|
||||||
|
sql += " ON DELETE " + constraint.OnDelete
|
||||||
|
}
|
||||||
|
|
||||||
|
if constraint.OnUpdate != "" {
|
||||||
|
sql += " ON UPDATE " + constraint.OnUpdate
|
||||||
|
}
|
||||||
|
|
||||||
|
var foreignKeys, references []interface{}
|
||||||
|
for _, field := range constraint.ForeignKeys {
|
||||||
|
foreignKeys = append(foreignKeys, clause.Column{Name: field.DBName})
|
||||||
|
}
|
||||||
|
|
||||||
|
for _, field := range constraint.References {
|
||||||
|
references = append(references, clause.Column{Name: field.DBName})
|
||||||
|
}
|
||||||
|
vars = append(vars, clause.Table{Name: constraint.Name}, foreignKeys, clause.Table{Name: constraint.ReferenceSchema.Table}, references)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
func (rel *Relationship) ParseConstraint() *FKConstraint {
|
||||||
str := rel.Field.TagSettings["CONSTRAINT"]
|
str := rel.Field.TagSettings["CONSTRAINT"]
|
||||||
if str == "-" {
|
if str == "-" {
|
||||||
return nil
|
return nil
|
||||||
@ -617,7 +641,7 @@ func (rel *Relationship) ParseConstraint() *Constraint {
|
|||||||
name = rel.Schema.namer.RelationshipFKName(*rel)
|
name = rel.Schema.namer.RelationshipFKName(*rel)
|
||||||
}
|
}
|
||||||
|
|
||||||
constraint := Constraint{
|
constraint := FKConstraint{
|
||||||
Name: name,
|
Name: name,
|
||||||
Field: rel.Field,
|
Field: rel.Field,
|
||||||
OnUpdate: settings["ONUPDATE"],
|
OnUpdate: settings["ONUPDATE"],
|
||||||
|
Loading…
x
Reference in New Issue
Block a user