diff --git a/templates/relationship_to_many_eager.tpl b/templates/relationship_to_many_eager.tpl index ae6817a..2dfb3f3 100644 --- a/templates/relationship_to_many_eager.tpl +++ b/templates/relationship_to_many_eager.tpl @@ -1,16 +1,13 @@ -{{- define "relationship_to_one_eager_helper" -}} -{{- end -}} {{- if .Table.IsJoinTable -}} {{- else}} {{- $dot := . -}} {{- range .Table.ToManyRelationships -}} -{{- if .ForeignColumnUnique -}} +{{- if (and .ForeignColumnUnique (not .ToJoinTable)) -}} {{- template "relationship_to_one_eager_helper" (textsFromOneToOneRelationship $dot.PkgName $dot.Tables $dot.Table .) -}} {{- else -}} {{- $rel := textsFromRelationship $dot.Tables $dot.Table . -}} {{- $arg := printf "maybe%s" $rel.LocalTable.NameGo -}} {{- $slice := printf "%sSlice" $rel.LocalTable.NameGo}} - {{- $pkeySlice := printf "%sPrimaryKeyColumns" ($dot.Table.Name | singular | camelCase)}} // Load{{$rel.Function.Name}} allows an eager lookup of values, cached into the // relationships structs of the objects. func (r *{{$rel.LocalTable.NameGo}}Relationships) Load{{$rel.Function.Name}}(e boil.Executor, singular bool, {{$arg}} interface{}) error { @@ -25,17 +22,26 @@ func (r *{{$rel.LocalTable.NameGo}}Relationships) Load{{$rel.Function.Name}}(e b count = len(slice) } - var args []interface{} + args := make([]interface{}, count) if singular { - args = boil.GetStructValues(object, "{{.Column}}") + args[0] = object.{{.Column | titleCase}} } else { - args = boil.GetSliceValues(slice, "{{.Column}}") + for i, obj := range slice { + args[i] = obj.{{.Column | titleCase}} + } } + {{if .ToJoinTable -}} + query := fmt.Sprintf( + `select "{{id 0}}".* from "{{.ForeignTable}}" as {{id 0}} inner join "{{.JoinTable}}" as "{{id 1}}" on "{{id 1}}"."{{.JoinForeignColumn}}" = "{{id 0}}"."{{.ForeignColumn}}" where "{{.ForeignColumn}}" in (%s)`, + strmangle.Placeholders(count, 1, 1), + ) + {{else -}} query := fmt.Sprintf( `select * from "{{.ForeignTable}}" where "{{.ForeignColumn}}" in (%s)`, strmangle.Placeholders(count, 1, 1), ) + {{end -}} results, err := e.Query(query, args...) if err != nil { diff --git a/templates/relationship_to_one_eager.tpl b/templates/relationship_to_one_eager.tpl new file mode 100644 index 0000000..ca431f9 --- /dev/null +++ b/templates/relationship_to_one_eager.tpl @@ -0,0 +1,72 @@ +{{- define "relationship_to_one_eager_helper" -}} + {{- $arg := printf "maybe%s" .LocalTable.NameGo -}} + {{- $slice := printf "%sSlice" .LocalTable.NameGo}} +// Load{{.Function.Name}} allows an eager lookup of values, cached into the +// relationships structs of the objects. +func (r *{{.LocalTable.NameGo}}Relationships) Load{{.Function.Name}}(e boil.Executor, singular bool, {{$arg}} interface{}) error { + var slice []*{{.LocalTable.NameGo}} + var object *{{.LocalTable.NameGo}} + + count := 1 + if singular { + object = {{$arg}}.(*{{.LocalTable.NameGo}}) + } else { + slice = {{$arg}}.({{$slice}}) + count = len(slice) + } + + args := make([]interface{}, count) + if singular { + args[0] = object.{{.LocalTable.ColumnNameGo}} + } else { + for i, obj := range slice { + args[i] = obj.{{.LocalTable.ColumnNameGo}} + } + } + + query := fmt.Sprintf( + `select * from "{{.ForeignKey.ForeignTable}}" where "{{.ForeignKey.ForeignColumn}}" in (%s)`, + strmangle.Placeholders(count, 1, 1), + ) + + results, err := e.Query(query, args...) + if err != nil { + return errors.Wrap(err, "failed to eager load {{.ForeignTable.NameGo}}") + } + defer results.Close() + + var resultSlice []*{{.ForeignTable.NameGo}} + if err = boil.Bind(results, &resultSlice); err != nil { + return errors.Wrap(err, "failed to bind eager loaded slice {{.ForeignTable}}") + } + + if singular && len(resultSlice) != 0 { + object.Relationships = &{{.LocalTable.NameGo}}Relationships{ + {{.Function.Name}}: resultSlice[0], + } + return nil + } + + for _, foreign := range resultSlice { + for _, local := range slice { + if local.{{.Function.LocalAssignment}} == foreign.{{.Function.ForeignAssignment}} { + if local.Relationships == nil { + local.Relationships = &{{.LocalTable.NameGo}}Relationships{} + } + local.Relationships.{{.Function.Name}} = foreign + break + } + } + } + + return nil +} +{{- end -}} +{{- if .Table.IsJoinTable -}} +{{- else -}} + {{- $dot := . -}} + {{- range .Table.FKeys -}} + {{- $rel := textsFromForeignKey $dot.PkgName $dot.Tables $dot.Table . -}} +{{- template "relationship_to_one_eager_helper" $rel -}} +{{end -}} +{{- end -}} diff --git a/templates_test/relationship_to_many.tpl b/templates_test/relationship_to_many.tpl index 138f703..52e2bc0 100644 --- a/templates_test/relationship_to_many.tpl +++ b/templates_test/relationship_to_many.tpl @@ -74,6 +74,21 @@ func test{{$rel.LocalTable.NameGo}}ToMany{{$rel.Function.Name}}(t *testing.T) { t.Error("expected to find c") } + if err = a.Relationships.Load{{$rel.Function.Name}}(tx, false, {{$rel.LocalTable.NameGo}}Slice{&a}); err != nil { + t.Error(err) + } + if len(a.Relationships.{{$rel.Function.Name}}) != 2 { + t.Error("expected to be able to eager load 2 relationships") + } + + a.Relationships.{{$rel.Function.Name}} = nil + if err = a.Relationships.Load{{$rel.Function.Name}}(tx, true, &a); err != nil { + t.Error(err) + } + if len(a.Relationships.{{$rel.Function.Name}}) != 2 { + t.Error("expected to be able to eager load 2 relationships") + } + if t.Failed() { t.Logf("%#v", {{$varname}}) }