From 84a160f3a41c46002a64e2af8c11be2be4847d89 Mon Sep 17 00:00:00 2001 From: Aaron L Date: Wed, 22 Jun 2016 22:03:05 -0700 Subject: [PATCH] Start of the to_many relationships. --- dbdrivers/relationships.go | 52 ++++++++++++++++++ dbdrivers/relationships_test.go | 36 +++++++++++++ sqlboiler.go | 1 + templates/05_relationship_to_many.tpl | 56 ++++++++++++++++++++ templates/{05_all.tpl => 06_all.tpl} | 0 templates/{06_find.tpl => 07_find.tpl} | 0 templates/{07_insert.tpl => 08_insert.tpl} | 0 templates/{08_update.tpl => 09_update.tpl} | 0 templates/{09_delete.tpl => 10_delete.tpl} | 0 templates/{10_helpers.tpl => 11_helpers.tpl} | 0 10 files changed, 145 insertions(+) create mode 100644 dbdrivers/relationships.go create mode 100644 dbdrivers/relationships_test.go create mode 100644 templates/05_relationship_to_many.tpl rename templates/{05_all.tpl => 06_all.tpl} (100%) rename templates/{06_find.tpl => 07_find.tpl} (100%) rename templates/{07_insert.tpl => 08_insert.tpl} (100%) rename templates/{08_update.tpl => 09_update.tpl} (100%) rename templates/{09_delete.tpl => 10_delete.tpl} (100%) rename templates/{10_helpers.tpl => 11_helpers.tpl} (100%) diff --git a/dbdrivers/relationships.go b/dbdrivers/relationships.go new file mode 100644 index 0000000..ea96808 --- /dev/null +++ b/dbdrivers/relationships.go @@ -0,0 +1,52 @@ +package dbdrivers + +import ( + "fmt" + + "github.com/nullbio/sqlboiler/strmangle" +) + +// ToManyRelationship describes a relationship between two tables where the +// local table has no id, and the foreign table has an id that matches a column +// in the local table. +type ToManyRelationship struct { + Name string + ForeignTable string + ForeignColumn string +} + +// ToManyRelationships relationship lookups +// Input should be the sql name of a table like: videos +func ToManyRelationships(table string, tables []Table) []ToManyRelationship { + var relationships []ToManyRelationship + + for _, t := range tables { + if t.Name == table { + continue + } + + for _, f := range t.FKeys { + if f.ForeignTable != table { + continue + } + + singularName := strmangle.Singular(table) + standardColName := fmt.Sprintf("%s_id", singularName) + + relationship := ToManyRelationship{ + ForeignTable: t.Name, + ForeignColumn: f.Column, + } + + if standardColName == f.ForeignColumn { + relationship.Name = strmangle.TitleCase(strmangle.Plural(name)) + } else { + relationship.Name = strmangle.TitleCase(strmangle.Plural(name)) + } + + relationships = append(relationships, relationship) + } + } + + return relationships +} diff --git a/dbdrivers/relationships_test.go b/dbdrivers/relationships_test.go new file mode 100644 index 0000000..741c156 --- /dev/null +++ b/dbdrivers/relationships_test.go @@ -0,0 +1,36 @@ +package dbdrivers + +import "testing" + +func TestToManyRelationships(t *testing.T) { + t.Parallel() + + tables := []Table{ + Table{ + Name: "videos", + FKeys: []ForeignKey{ + {Name: "videos_user_id_fk", Column: "user_id", ForeignTable: "users", ForeignKey: "id"}, + {Name: "videos_contest_id_fk", Column: "contest_id", ForeignTable: "contests", ForeignKey: "id"}, + }, + }, + Table{ + Name: "notifications", + FKeys: []ForeignKey{ + {Name: "notifications_user_id_fk", Column: "user_id", ForeignTable: "users", ForeignKey: "id"}, + {Name: "notifications_source_id_fk", Column: "source_id", ForeignTable: "users", ForeignKey: "id"}, + }, + }, + } + + relationships := ToManyRelationships("users", tables) + r := relationships[0] + if r.Name != "Videos" { + t.Error("wrong name:", r.Name) + } + if r.ForeignTable != "videos" { + t.Error("wrong foreign table:", r.ForeignTable) + } + if r.ForeignColumn != "user_id" { + t.Error("wrong foreign column:", r.ForeignColumn) + } +} diff --git a/sqlboiler.go b/sqlboiler.go index 43e0454..67a1625 100644 --- a/sqlboiler.go +++ b/sqlboiler.go @@ -102,6 +102,7 @@ func (s *State) Run(includeTests bool) error { } data := &templateData{ + Tables: s.Tables, Table: table, DriverName: s.Config.DriverName, PkgName: s.Config.PkgName, diff --git a/templates/05_relationship_to_many.tpl b/templates/05_relationship_to_many.tpl new file mode 100644 index 0000000..781f14c --- /dev/null +++ b/templates/05_relationship_to_many.tpl @@ -0,0 +1,56 @@ +{{- if .Table.IsJoinTable -}} +{{- else -}} + {{- $pkg := .PkgName -}} + {{- $localTable := .Table.Name -}} + {{- $ltable := .Table.Name | singular | titleCase -}} + {{- range $table := .Tables -}} + {{- if eq $table.Name $localTable -}} + {{- else -}} + {{ range $fkey := .FKeys -}} + {{- if eq $localTable $fkey.ForeignTable -}} + {{- $ftable := $table.Name | plural | titleCase -}} + {{- $recv := $localTable | substring 0 1 | toLower -}} + {{- $fn := $ftable -}} + {{- $col := $localTable | singular | printf "%s_id" -}} + {{- if eq $col $fkey.Column -}} + {{- $col := $localTable -}} + {{- end -}} +func ({{$recv}} *{{$ltable}}) {{$fn}} +{{ end -}} + {{- end -}} + {{- end -}} + {{- end -}} +{{- end -}} +{{/* +// Challengee fetches the Video pointed to by the foreign key. +func (b *Battle) Challengee(exec boil.Executor, selectCols ...string) (*Video, error) { + video := &Video{} + + query := fmt.Sprintf(`select %s from videos where id = $1`, strings.Join(selectCols, `,`)) + err := exec.QueryRow(query, b.ChallengeeID).Scan(boil.GetStructPointers(video, selectCols...)...) + if err != nil { + return nil, fmt.Errorf(`models: unable to select from videos: %v`, err) + } + + return video, nil +} + + {{- range .Table.FKeys -}} + {{- $localColumn := .Column | remove "_id" | singular | titleCase -}} + {{- $foreignColumn := .Column | remove "_id" | singular | titleCase -}} + {{- $foreignTable := .ForeignTable | singular | titleCase -}} + {{- $varname := .ForeignTable | singular | camelCase -}} + {{- $receiver := $localTable | toLower | substring 0 1 -}} +// {{$foreignColumn}} fetches the {{$foreignTable}} pointed to by the foreign key. +func ({{$receiver}} *{{$localTable}}) {{$foreignColumn}}(exec boil.Executor, selectCols ...string) (*{{$foreignTable}}, error) { + {{$varname}} := &{{$foreignTable}}{} + + query := fmt.Sprintf(`select %s from {{.ForeignTable}} where id = $1`, strings.Join(selectCols, `,`)) + err := exec.QueryRow(query, {{$receiver}}.{{titleCase .Column}}).Scan(boil.GetStructPointers({{$varname}}, selectCols...)...) + if err != nil { + return nil, fmt.Errorf(`{{$pkg}}: unable to select from {{.ForeignTable}}: %v`, err) + } + + return {{$varname}}, nil +} +*/}} diff --git a/templates/05_all.tpl b/templates/06_all.tpl similarity index 100% rename from templates/05_all.tpl rename to templates/06_all.tpl diff --git a/templates/06_find.tpl b/templates/07_find.tpl similarity index 100% rename from templates/06_find.tpl rename to templates/07_find.tpl diff --git a/templates/07_insert.tpl b/templates/08_insert.tpl similarity index 100% rename from templates/07_insert.tpl rename to templates/08_insert.tpl diff --git a/templates/08_update.tpl b/templates/09_update.tpl similarity index 100% rename from templates/08_update.tpl rename to templates/09_update.tpl diff --git a/templates/09_delete.tpl b/templates/10_delete.tpl similarity index 100% rename from templates/09_delete.tpl rename to templates/10_delete.tpl diff --git a/templates/10_helpers.tpl b/templates/11_helpers.tpl similarity index 100% rename from templates/10_helpers.tpl rename to templates/11_helpers.tpl