diff --git a/templates/08_relationship_to_one_setops.tpl b/templates/08_relationship_to_one_setops.tpl index eb157bc..e03803d 100644 --- a/templates/08_relationship_to_one_setops.tpl +++ b/templates/08_relationship_to_one_setops.tpl @@ -14,12 +14,25 @@ func ({{.Function.Receiver}} *{{.LocalTable.NameGo}}) Set{{.Function.Name}}(exec } } - oldVal := {{.Function.Receiver}}.{{.LocalTable.ColumnNameGo}} - {{.Function.Receiver}}.{{.Function.LocalAssignment}} = related.{{.Function.ForeignAssignment}} - if err = {{.Function.Receiver}}.Update(exec, "{{.ForeignKey.Column}}"); err != nil { - {{.Function.Receiver}}.{{.LocalTable.ColumnNameGo}} = oldVal + {{if .Function.OneToOne -}} + oldVal := related.{{.Function.ForeignAssignment}} + related.{{.Function.ForeignAssignment}} = {{.Function.Receiver}}.{{.Function.LocalAssignment}} + {{if .ForeignKey.ForeignColumnNullable -}} + related.{{.ForeignTable.ColumnNameGo}}.Valid = true + {{end -}} + if err = related.Update(exec, "{{.ForeignKey.ForeignColumn}}"); err != nil { + related.{{.Function.ForeignAssignment}} = oldVal return errors.Wrap(err, "failed to update local table") } + {{else -}} + oldVal := {{.Function.Receiver}}.{{.Function.LocalAssignment}} + related.{{.Function.ForeignAssignment}} = {{.Function.Receiver}}.{{.Function.LocalAssignment}} + {{.Function.Receiver}}.{{.Function.LocalAssignment}} = related.{{.Function.ForeignAssignment}} + if err = {{.Function.Receiver}}.Update(exec, "{{.ForeignKey.Column}}"); err != nil { + {{.Function.Receiver}}.{{.Function.LocalAssignment}} = oldVal + return errors.Wrap(err, "failed to update local table") + } + {{end -}} if {{.Function.Receiver}}.R == nil { {{.Function.Receiver}}.R = &{{$localNameSingular}}R{ @@ -53,18 +66,26 @@ func ({{.Function.Receiver}} *{{.LocalTable.NameGo}}) Set{{.Function.Name}}(exec return nil } - {{- if .ForeignKey.Nullable}} + {{- if or (.ForeignKey.Nullable) (and .Function.OneToOne .ForeignKey.ForeignColumnNullable)}} // Remove{{.Function.Name}} relationship. // Sets {{.Function.Receiver}}.R.{{.Function.Name}} to nil. // Removes {{.Function.Receiver}} from all passed in related items' relationships struct (Optional). func ({{.Function.Receiver}} *{{.LocalTable.NameGo}}) Remove{{.Function.Name}}(exec boil.Executor, related *{{.ForeignTable.NameGo}}) error { var err error + {{if .Function.OneToOne -}} + related.{{.ForeignTable.ColumnNameGo}}.Valid = false + if err = related.Update(exec, "{{.ForeignKey.ForeignColumn}}"); err != nil { + related.{{.ForeignTable.ColumnNameGo}}.Valid = true + return errors.Wrap(err, "failed to update local table") + } + {{else -}} {{.Function.Receiver}}.{{.LocalTable.ColumnNameGo}}.Valid = false if err = {{.Function.Receiver}}.Update(exec, "{{.ForeignKey.Column}}"); err != nil { {{.Function.Receiver}}.{{.LocalTable.ColumnNameGo}}.Valid = true return errors.Wrap(err, "failed to update local table") } + {{end -}} {{.Function.Receiver}}.R.{{.Function.Name}} = nil if related == nil || related.R == nil { diff --git a/templates_test/relationship_to_one_setops.tpl b/templates_test/relationship_to_one_setops.tpl index dd78025..f78c261 100644 --- a/templates_test/relationship_to_one_setops.tpl +++ b/templates_test/relationship_to_one_setops.tpl @@ -10,7 +10,10 @@ func test{{.LocalTable.NameGo}}ToOneSetOp{{.ForeignTable.NameGo}}_{{.Function.Na defer tx.Rollback() var a {{.LocalTable.NameGo}} - var b, c {{.ForeignTable.NameGo}} + var b {{.ForeignTable.NameGo}} + {{if not .Function.OneToOne -}} + var c {{.ForeignTable.NameGo}} + {{- end}} seed := randomize.NewSeed() if err = randomize.Struct(seed, &a, {{$varNameSingular}}DBTypes, false, strmangle.SetComplement({{$varNameSingular}}PrimaryKeyColumns, {{$varNameSingular}}ColumnsWithoutDefault)...); err != nil { @@ -19,9 +22,11 @@ func test{{.LocalTable.NameGo}}ToOneSetOp{{.ForeignTable.NameGo}}_{{.Function.Na if err = randomize.Struct(seed, &b, {{$foreignVarNameSingular}}DBTypes, false, strmangle.SetComplement({{$foreignVarNameSingular}}PrimaryKeyColumns, {{$foreignVarNameSingular}}ColumnsWithoutDefault)...); err != nil { t.Fatal(err) } + {{if not .Function.OneToOne -}} if err = randomize.Struct(seed, &c, {{$foreignVarNameSingular}}DBTypes, false, strmangle.SetComplement({{$foreignVarNameSingular}}PrimaryKeyColumns, {{$foreignVarNameSingular}}ColumnsWithoutDefault)...); err != nil { t.Fatal(err) } + {{- end}} if err := a.Insert(tx); err != nil { t.Fatal(err) @@ -30,7 +35,7 @@ func test{{.LocalTable.NameGo}}ToOneSetOp{{.ForeignTable.NameGo}}_{{.Function.Na t.Fatal(err) } - for i, x := range []*{{.ForeignTable.NameGo}}{&b, &c} { + for i, x := range []*{{.ForeignTable.NameGo}}{&b{{if not .Function.OneToOne}}, &c{{end}}} { err = a.Set{{.Function.Name}}(tx, i != 0, x) if err != nil { t.Fatal(err) @@ -47,12 +52,23 @@ func test{{.LocalTable.NameGo}}ToOneSetOp{{.ForeignTable.NameGo}}_{{.Function.Na t.Error("relationship struct not set to correct value") } + {{if .Function.OneToOne -}} + zero := reflect.Zero(reflect.TypeOf(x.{{.Function.ForeignAssignment}})) + reflect.Indirect(reflect.ValueOf(&x.{{.Function.ForeignAssignment}})).Set(zero) + + xrel := x.R + if err = x.Reload(tx); err != nil { + t.Fatal("failed to reload", err) + } + x.R = xrel + {{else -}} zero := reflect.Zero(reflect.TypeOf(a.{{.Function.LocalAssignment}})) reflect.Indirect(reflect.ValueOf(&a.{{.Function.LocalAssignment}})).Set(zero) if err = a.Reload(tx); err != nil { t.Fatal("failed to reload", err) } + {{- end}} {{if .Function.UsesBytes -}} if 0 != bytes.Compare(a.{{.Function.LocalAssignment}}, x.{{.Function.ForeignAssignment}}) { @@ -73,7 +89,7 @@ func test{{.LocalTable.NameGo}}ToOneSetOp{{.ForeignTable.NameGo}}_{{.Function.Na {{end -}} } } -{{- if .ForeignKey.Nullable}} +{{- if or (.ForeignKey.Nullable) (and .Function.OneToOne .ForeignKey.ForeignColumnNullable)}} func test{{.LocalTable.NameGo}}ToOneRemoveOp{{.ForeignTable.NameGo}}_{{.Function.Name}}(t *testing.T) { var err error @@ -116,9 +132,15 @@ func test{{.LocalTable.NameGo}}ToOneRemoveOp{{.ForeignTable.NameGo}}_{{.Function t.Error("R struct entry should be nil") } + {{if .Function.OneToOne -}} + if b.{{.ForeignTable.ColumnNameGo}}.Valid { + t.Error("R struct entry should be nil") + } + {{else -}} if a.{{.LocalTable.ColumnNameGo}}.Valid { t.Error("R struct entry should be nil") } + {{- end}} {{if .ForeignKey.Unique -}} if b.R.{{.Function.ForeignName}} != nil { @@ -128,7 +150,7 @@ func test{{.LocalTable.NameGo}}ToOneRemoveOp{{.ForeignTable.NameGo}}_{{.Function if len(b.R.{{.Function.ForeignName}}) != 0 { t.Error("failed to remove a from b's relationships") } - {{end -}} + {{- end}} } {{end -}}{{/* end if foreign key nullable */}} {{- end -}}{{/* with rel */}} diff --git a/templates_test/singleton/boil_suites_test.tpl b/templates_test/singleton/boil_suites_test.tpl index 3749a07..9147b46 100644 --- a/templates_test/singleton/boil_suites_test.tpl +++ b/templates_test/singleton/boil_suites_test.tpl @@ -252,7 +252,7 @@ func TestToManyRemove(t *testing.T) { {{- $rel := textsFromRelationship $dot.Tables $table . -}} {{- if (and .ForeignColumnUnique (not .ToJoinTable)) -}} {{- $oneToOne := textsFromOneToOneRelationship $dot.PkgName $dot.Tables $table . -}} - {{- if $oneToOne.ForeignKey.Nullable -}} + {{- if or ($oneToOne.ForeignKey.Nullable) (and $oneToOne.Function.OneToOne $oneToOne.ForeignKey.ForeignColumnNullable)}} t.Run("{{$oneToOne.LocalTable.NameGo}}OneToOne{{$oneToOne.ForeignTable.NameGo}}_{{$oneToOne.Function.Name}}", test{{$oneToOne.LocalTable.NameGo}}ToOneRemoveOp{{$oneToOne.ForeignTable.NameGo}}_{{$oneToOne.Function.Name}}) {{end -}} {{- else -}}