Add to_many relationships as a first class citizen
- to_many relationships are now cached on the table data structure - to_many relationships now know if any columns involved are nullable
This commit is contained in:
parent
bac9bb30ce
commit
fb802ad687
5 changed files with 319 additions and 62 deletions
|
@ -57,6 +57,11 @@ func Tables(db Interface, names ...string) ([]Table, error) {
|
||||||
tables = append(tables, t)
|
tables = append(tables, t)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
for i := range tables {
|
||||||
|
tbl := &tables[i]
|
||||||
|
setRelationships(tbl, tables)
|
||||||
|
}
|
||||||
|
|
||||||
return tables, nil
|
return tables, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -102,3 +107,7 @@ func setForeignKeyNullability(t *Table) {
|
||||||
t.FKeys[i].Nullable = t.Columns[found].Nullable
|
t.FKeys[i].Nullable = t.Columns[found].Nullable
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func setRelationships(t *Table, tables []Table) {
|
||||||
|
t.ToManyRelationships = toManyRelationships(*t, tables)
|
||||||
|
}
|
||||||
|
|
|
@ -11,32 +11,38 @@ func (t testInterface) TableNames() ([]string, error) {
|
||||||
return []string{"table1", "table2"}, nil
|
return []string{"table1", "table2"}, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (t testInterface) Columns(tableName string) ([]Column, error) {
|
var testCols = []Column{
|
||||||
return []Column{
|
|
||||||
Column{Name: "col1", Type: "character varying"},
|
Column{Name: "col1", Type: "character varying"},
|
||||||
Column{Name: "col2", Type: "character varying", Nullable: true},
|
Column{Name: "col2", Type: "character varying", Nullable: true},
|
||||||
}, nil
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (t testInterface) Columns(tableName string) ([]Column, error) {
|
||||||
|
return testCols, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
var testPkey = &PrimaryKey{Name: "pkey1", Columns: []string{"col1", "col2"}}
|
||||||
|
|
||||||
func (t testInterface) PrimaryKeyInfo(tableName string) (*PrimaryKey, error) {
|
func (t testInterface) PrimaryKeyInfo(tableName string) (*PrimaryKey, error) {
|
||||||
return &PrimaryKey{Name: "pkey1", Columns: []string{"col1", "col2"}}, nil
|
return testPkey, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (t testInterface) ForeignKeyInfo(tableName string) ([]ForeignKey, error) {
|
var testFkeys = []ForeignKey{
|
||||||
return []ForeignKey{
|
|
||||||
{
|
{
|
||||||
Name: "fkey1",
|
Name: "fkey1",
|
||||||
Column: "col1",
|
Column: "col1",
|
||||||
ForeignTable: "table3",
|
ForeignTable: "table2",
|
||||||
ForeignColumn: "col3",
|
ForeignColumn: "col2",
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
Name: "fkey2",
|
Name: "fkey2",
|
||||||
Column: "col2",
|
Column: "col2",
|
||||||
ForeignTable: "table3",
|
ForeignTable: "table1",
|
||||||
ForeignColumn: "col3",
|
ForeignColumn: "col1",
|
||||||
},
|
},
|
||||||
}, nil
|
}
|
||||||
|
|
||||||
|
func (t testInterface) ForeignKeyInfo(tableName string) ([]ForeignKey, error) {
|
||||||
|
return testFkeys, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (t testInterface) TranslateColumnType(column Column) Column {
|
func (t testInterface) TranslateColumnType(column Column) Column {
|
||||||
|
@ -62,42 +68,27 @@ func TestTables(t *testing.T) {
|
||||||
t.Errorf("Expected len 2, got: %d\n", len(tables))
|
t.Errorf("Expected len 2, got: %d\n", len(tables))
|
||||||
}
|
}
|
||||||
|
|
||||||
expectCols := []Column{
|
if !reflect.DeepEqual(tables[0].Columns, testCols) {
|
||||||
Column{Name: "col1", Type: "string"},
|
t.Errorf("Did not get expected columns, got:\n%#v\n%#v", tables[0].Columns, testCols)
|
||||||
Column{Name: "col2", Type: "string", Nullable: true},
|
|
||||||
}
|
|
||||||
|
|
||||||
if !reflect.DeepEqual(tables[0].Columns, expectCols) {
|
|
||||||
t.Errorf("Did not get expected columns, got:\n%#v\n%#v", tables[0].Columns, expectCols)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if !tables[0].IsJoinTable || !tables[1].IsJoinTable {
|
if !tables[0].IsJoinTable || !tables[1].IsJoinTable {
|
||||||
t.Errorf("Expected IsJoinTable to be true")
|
t.Errorf("Expected IsJoinTable to be true")
|
||||||
}
|
}
|
||||||
|
|
||||||
expectPkey := &PrimaryKey{Name: "pkey1", Columns: []string{"col1", "col2"}}
|
if !reflect.DeepEqual(tables[0].PKey, testPkey) {
|
||||||
expectFkey := []ForeignKey{
|
t.Errorf("Did not get expected PKey, got:\n#%v\n%#v", tables[0].PKey, testPkey)
|
||||||
{
|
|
||||||
Name: "fkey1",
|
|
||||||
Column: "col1",
|
|
||||||
ForeignTable: "table3",
|
|
||||||
ForeignColumn: "col3",
|
|
||||||
},
|
|
||||||
{
|
|
||||||
Name: "fkey2",
|
|
||||||
Column: "col2",
|
|
||||||
ForeignTable: "table3",
|
|
||||||
ForeignColumn: "col3",
|
|
||||||
Nullable: true,
|
|
||||||
},
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if !reflect.DeepEqual(tables[0].FKeys, expectFkey) {
|
if !reflect.DeepEqual(tables[0].FKeys, testFkeys) {
|
||||||
t.Errorf("Did not get expected Fkey, got:\n%#v\n%#v", tables[0].FKeys, expectFkey)
|
t.Errorf("Did not get expected Fkey, got:\n%#v\n%#v", tables[0].FKeys, testFkeys)
|
||||||
}
|
}
|
||||||
|
|
||||||
if !reflect.DeepEqual(tables[0].PKey, expectPkey) {
|
if len(tables[0].ToManyRelationships) != 1 {
|
||||||
t.Errorf("Did not get expected PKey, got:\n#%v\n%#v", tables[0].PKey, expectPkey)
|
t.Error("wanted a to many relationship")
|
||||||
|
}
|
||||||
|
if len(tables[1].ToManyRelationships) != 1 {
|
||||||
|
t.Error("wanted a to many relationship")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -161,3 +152,47 @@ func TestSetForeignKeyNullability(t *testing.T) {
|
||||||
t.Error("should be nullable")
|
t.Error("should be nullable")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func TestSetRelationships(t *testing.T) {
|
||||||
|
t.Parallel()
|
||||||
|
|
||||||
|
tables := []Table{
|
||||||
|
Table{
|
||||||
|
Name: "one",
|
||||||
|
Columns: []Column{
|
||||||
|
Column{Name: "id", Type: "string"},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
Table{
|
||||||
|
Name: "other",
|
||||||
|
Columns: []Column{
|
||||||
|
Column{Name: "other_id", Type: "string"},
|
||||||
|
},
|
||||||
|
FKeys: []ForeignKey{{Column: "other_id", ForeignTable: "one", ForeignColumn: "id", Nullable: true}},
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
|
setRelationships(&tables[0], tables)
|
||||||
|
setRelationships(&tables[1], tables)
|
||||||
|
|
||||||
|
if got := len(tables[0].ToManyRelationships); got != 1 {
|
||||||
|
t.Error("should have a relationship:", got)
|
||||||
|
}
|
||||||
|
if got := len(tables[1].ToManyRelationships); got != 0 {
|
||||||
|
t.Error("should have no to many relationships:", got)
|
||||||
|
}
|
||||||
|
|
||||||
|
rel := tables[0].ToManyRelationships[0]
|
||||||
|
if rel.Column != "id" {
|
||||||
|
t.Error("wrong column:", rel.Column)
|
||||||
|
}
|
||||||
|
if rel.ForeignTable != "other" {
|
||||||
|
t.Error("wrong table:", rel.ForeignTable)
|
||||||
|
}
|
||||||
|
if rel.ForeignColumn != "other_id" {
|
||||||
|
t.Error("wrong column:", rel.ForeignColumn)
|
||||||
|
}
|
||||||
|
if rel.ToJoinTable {
|
||||||
|
t.Error("should not be a join table")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
|
@ -5,60 +5,82 @@ package bdb
|
||||||
// in the local table.
|
// in the local table.
|
||||||
type ToManyRelationship struct {
|
type ToManyRelationship struct {
|
||||||
Column string
|
Column string
|
||||||
|
Nullable bool
|
||||||
|
|
||||||
ForeignTable string
|
ForeignTable string
|
||||||
ForeignColumn string
|
ForeignColumn string
|
||||||
|
ForeignColumnNullable bool
|
||||||
|
|
||||||
ToJoinTable bool
|
ToJoinTable bool
|
||||||
JoinTable string
|
JoinTable string
|
||||||
JoinLocalColumn string
|
JoinLocalColumn string
|
||||||
|
JoinLocalColumnNullable bool
|
||||||
JoinForeignColumn string
|
JoinForeignColumn string
|
||||||
|
JoinForeignColumnNullable bool
|
||||||
}
|
}
|
||||||
|
|
||||||
// ToManyRelationships relationship lookups
|
// ToManyRelationships relationship lookups
|
||||||
// Input should be the sql name of a table like: videos
|
// Input should be the sql name of a table like: videos
|
||||||
func ToManyRelationships(table string, tables []Table) []ToManyRelationship {
|
func ToManyRelationships(table string, tables []Table) []ToManyRelationship {
|
||||||
|
localTable := GetTable(tables, table)
|
||||||
|
|
||||||
|
return toManyRelationships(localTable, tables)
|
||||||
|
}
|
||||||
|
|
||||||
|
func toManyRelationships(table Table, tables []Table) []ToManyRelationship {
|
||||||
var relationships []ToManyRelationship
|
var relationships []ToManyRelationship
|
||||||
|
|
||||||
for _, t := range tables {
|
for _, t := range tables {
|
||||||
if t.Name == table {
|
if t.Name == table.Name {
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
|
|
||||||
for _, f := range t.FKeys {
|
for _, f := range t.FKeys {
|
||||||
if f.ForeignTable != table {
|
if f.ForeignTable != table.Name {
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
|
|
||||||
relationships = append(relationships, buildRelationship(table, f, t))
|
relationships = append(relationships, buildRelationship(table, f, t, tables))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return relationships
|
return relationships
|
||||||
}
|
}
|
||||||
|
|
||||||
func buildRelationship(localTable string, foreignKey ForeignKey, foreignTable Table) ToManyRelationship {
|
func buildRelationship(localTable Table, foreignKey ForeignKey, foreignTable Table, tables []Table) ToManyRelationship {
|
||||||
if !foreignTable.IsJoinTable {
|
if !foreignTable.IsJoinTable {
|
||||||
|
col := localTable.GetColumn(foreignKey.ForeignColumn)
|
||||||
return ToManyRelationship{
|
return ToManyRelationship{
|
||||||
Column: foreignKey.ForeignColumn,
|
Column: foreignKey.ForeignColumn,
|
||||||
|
Nullable: col.Nullable,
|
||||||
ForeignTable: foreignTable.Name,
|
ForeignTable: foreignTable.Name,
|
||||||
ForeignColumn: foreignKey.Column,
|
ForeignColumn: foreignKey.Column,
|
||||||
ToJoinTable: foreignTable.IsJoinTable,
|
ForeignColumnNullable: foreignKey.Nullable,
|
||||||
|
ToJoinTable: false,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
col := foreignTable.GetColumn(foreignKey.Column)
|
||||||
relationship := ToManyRelationship{
|
relationship := ToManyRelationship{
|
||||||
Column: foreignKey.ForeignColumn,
|
Column: foreignKey.ForeignColumn,
|
||||||
|
Nullable: col.Nullable,
|
||||||
ToJoinTable: true,
|
ToJoinTable: true,
|
||||||
JoinTable: foreignTable.Name,
|
JoinTable: foreignTable.Name,
|
||||||
}
|
}
|
||||||
|
|
||||||
for _, fk := range foreignTable.FKeys {
|
for _, fk := range foreignTable.FKeys {
|
||||||
if fk.ForeignTable != localTable {
|
if fk.ForeignTable != localTable.Name {
|
||||||
relationship.JoinForeignColumn = fk.Column
|
relationship.JoinForeignColumn = fk.Column
|
||||||
|
relationship.JoinForeignColumnNullable = fk.Nullable
|
||||||
|
|
||||||
|
foreignTable := GetTable(tables, fk.ForeignTable)
|
||||||
|
foreignCol := foreignTable.GetColumn(fk.ForeignColumn)
|
||||||
relationship.ForeignTable = fk.ForeignTable
|
relationship.ForeignTable = fk.ForeignTable
|
||||||
relationship.ForeignColumn = fk.ForeignColumn
|
relationship.ForeignColumn = fk.ForeignColumn
|
||||||
|
relationship.ForeignColumnNullable = foreignCol.Nullable
|
||||||
} else {
|
} else {
|
||||||
relationship.JoinLocalColumn = fk.Column
|
relationship.JoinLocalColumn = fk.Column
|
||||||
|
relationship.JoinLocalColumnNullable = fk.Nullable
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -6,8 +6,15 @@ func TestToManyRelationships(t *testing.T) {
|
||||||
t.Parallel()
|
t.Parallel()
|
||||||
|
|
||||||
tables := []Table{
|
tables := []Table{
|
||||||
|
Table{Name: "users", Columns: []Column{{Name: "id"}}},
|
||||||
|
Table{Name: "contests", Columns: []Column{{Name: "id"}}},
|
||||||
Table{
|
Table{
|
||||||
Name: "videos",
|
Name: "videos",
|
||||||
|
Columns: []Column{
|
||||||
|
{Name: "id"},
|
||||||
|
{Name: "user_id"},
|
||||||
|
{Name: "contest_id"},
|
||||||
|
},
|
||||||
FKeys: []ForeignKey{
|
FKeys: []ForeignKey{
|
||||||
{Name: "videos_user_id_fk", Column: "user_id", ForeignTable: "users", ForeignColumn: "id"},
|
{Name: "videos_user_id_fk", Column: "user_id", ForeignTable: "users", ForeignColumn: "id"},
|
||||||
{Name: "videos_contest_id_fk", Column: "contest_id", ForeignTable: "contests", ForeignColumn: "id"},
|
{Name: "videos_contest_id_fk", Column: "contest_id", ForeignTable: "contests", ForeignColumn: "id"},
|
||||||
|
@ -15,6 +22,10 @@ func TestToManyRelationships(t *testing.T) {
|
||||||
},
|
},
|
||||||
Table{
|
Table{
|
||||||
Name: "notifications",
|
Name: "notifications",
|
||||||
|
Columns: []Column{
|
||||||
|
{Name: "user_id"},
|
||||||
|
{Name: "source_id"},
|
||||||
|
},
|
||||||
FKeys: []ForeignKey{
|
FKeys: []ForeignKey{
|
||||||
{Name: "notifications_user_id_fk", Column: "user_id", ForeignTable: "users", ForeignColumn: "id"},
|
{Name: "notifications_user_id_fk", Column: "user_id", ForeignTable: "users", ForeignColumn: "id"},
|
||||||
{Name: "notifications_source_id_fk", Column: "source_id", ForeignTable: "users", ForeignColumn: "id"},
|
{Name: "notifications_source_id_fk", Column: "source_id", ForeignTable: "users", ForeignColumn: "id"},
|
||||||
|
@ -23,6 +34,10 @@ func TestToManyRelationships(t *testing.T) {
|
||||||
Table{
|
Table{
|
||||||
Name: "users_video_tags",
|
Name: "users_video_tags",
|
||||||
IsJoinTable: true,
|
IsJoinTable: true,
|
||||||
|
Columns: []Column{
|
||||||
|
{Name: "user_id"},
|
||||||
|
{Name: "video_id"},
|
||||||
|
},
|
||||||
FKeys: []ForeignKey{
|
FKeys: []ForeignKey{
|
||||||
{Name: "user_id_fk", Column: "user_id", ForeignTable: "users", ForeignColumn: "id"},
|
{Name: "user_id_fk", Column: "user_id", ForeignTable: "users", ForeignColumn: "id"},
|
||||||
{Name: "video_id_fk", Column: "video_id", ForeignTable: "videos", ForeignColumn: "id"},
|
{Name: "video_id_fk", Column: "video_id", ForeignTable: "videos", ForeignColumn: "id"},
|
||||||
|
@ -39,12 +54,18 @@ func TestToManyRelationships(t *testing.T) {
|
||||||
if r.Column != "id" {
|
if r.Column != "id" {
|
||||||
t.Error("wrong local column:", r.Column)
|
t.Error("wrong local column:", r.Column)
|
||||||
}
|
}
|
||||||
|
if r.Nullable {
|
||||||
|
t.Error("should not be nullable")
|
||||||
|
}
|
||||||
if r.ForeignTable != "videos" {
|
if r.ForeignTable != "videos" {
|
||||||
t.Error("wrong foreign table:", r.ForeignTable)
|
t.Error("wrong foreign table:", r.ForeignTable)
|
||||||
}
|
}
|
||||||
if r.ForeignColumn != "user_id" {
|
if r.ForeignColumn != "user_id" {
|
||||||
t.Error("wrong foreign column:", r.ForeignColumn)
|
t.Error("wrong foreign column:", r.ForeignColumn)
|
||||||
}
|
}
|
||||||
|
if r.ForeignColumnNullable {
|
||||||
|
t.Error("should not be nullable")
|
||||||
|
}
|
||||||
if r.ToJoinTable {
|
if r.ToJoinTable {
|
||||||
t.Error("not a join table")
|
t.Error("not a join table")
|
||||||
}
|
}
|
||||||
|
@ -53,12 +74,18 @@ func TestToManyRelationships(t *testing.T) {
|
||||||
if r.Column != "id" {
|
if r.Column != "id" {
|
||||||
t.Error("wrong local column:", r.Column)
|
t.Error("wrong local column:", r.Column)
|
||||||
}
|
}
|
||||||
|
if r.Nullable {
|
||||||
|
t.Error("should not be nullable")
|
||||||
|
}
|
||||||
if r.ForeignTable != "notifications" {
|
if r.ForeignTable != "notifications" {
|
||||||
t.Error("wrong foreign table:", r.ForeignTable)
|
t.Error("wrong foreign table:", r.ForeignTable)
|
||||||
}
|
}
|
||||||
if r.ForeignColumn != "user_id" {
|
if r.ForeignColumn != "user_id" {
|
||||||
t.Error("wrong foreign column:", r.ForeignColumn)
|
t.Error("wrong foreign column:", r.ForeignColumn)
|
||||||
}
|
}
|
||||||
|
if r.ForeignColumnNullable {
|
||||||
|
t.Error("should not be nullable")
|
||||||
|
}
|
||||||
if r.ToJoinTable {
|
if r.ToJoinTable {
|
||||||
t.Error("not a join table")
|
t.Error("not a join table")
|
||||||
}
|
}
|
||||||
|
@ -67,12 +94,18 @@ func TestToManyRelationships(t *testing.T) {
|
||||||
if r.Column != "id" {
|
if r.Column != "id" {
|
||||||
t.Error("wrong local column:", r.Column)
|
t.Error("wrong local column:", r.Column)
|
||||||
}
|
}
|
||||||
|
if r.Nullable {
|
||||||
|
t.Error("should not be nullable")
|
||||||
|
}
|
||||||
if r.ForeignTable != "notifications" {
|
if r.ForeignTable != "notifications" {
|
||||||
t.Error("wrong foreign table:", r.ForeignTable)
|
t.Error("wrong foreign table:", r.ForeignTable)
|
||||||
}
|
}
|
||||||
if r.ForeignColumn != "source_id" {
|
if r.ForeignColumn != "source_id" {
|
||||||
t.Error("wrong foreign column:", r.ForeignColumn)
|
t.Error("wrong foreign column:", r.ForeignColumn)
|
||||||
}
|
}
|
||||||
|
if r.ForeignColumnNullable {
|
||||||
|
t.Error("should not be nullable")
|
||||||
|
}
|
||||||
if r.ToJoinTable {
|
if r.ToJoinTable {
|
||||||
t.Error("not a join table")
|
t.Error("not a join table")
|
||||||
}
|
}
|
||||||
|
@ -81,9 +114,15 @@ func TestToManyRelationships(t *testing.T) {
|
||||||
if r.Column != "id" {
|
if r.Column != "id" {
|
||||||
t.Error("wrong local column:", r.Column)
|
t.Error("wrong local column:", r.Column)
|
||||||
}
|
}
|
||||||
|
if r.Nullable {
|
||||||
|
t.Error("should not be nullable")
|
||||||
|
}
|
||||||
if r.ForeignColumn != "id" {
|
if r.ForeignColumn != "id" {
|
||||||
t.Error("wrong foreign column:", r.Column)
|
t.Error("wrong foreign column:", r.Column)
|
||||||
}
|
}
|
||||||
|
if r.ForeignColumnNullable {
|
||||||
|
t.Error("should not be nullable")
|
||||||
|
}
|
||||||
if r.ForeignTable != "videos" {
|
if r.ForeignTable != "videos" {
|
||||||
t.Error("wrong foreign table:", r.ForeignTable)
|
t.Error("wrong foreign table:", r.ForeignTable)
|
||||||
}
|
}
|
||||||
|
@ -93,9 +132,159 @@ func TestToManyRelationships(t *testing.T) {
|
||||||
if r.JoinLocalColumn != "user_id" {
|
if r.JoinLocalColumn != "user_id" {
|
||||||
t.Error("wrong local join column:", r.JoinLocalColumn)
|
t.Error("wrong local join column:", r.JoinLocalColumn)
|
||||||
}
|
}
|
||||||
|
if r.JoinLocalColumnNullable {
|
||||||
|
t.Error("should not be nullable")
|
||||||
|
}
|
||||||
if r.JoinForeignColumn != "video_id" {
|
if r.JoinForeignColumn != "video_id" {
|
||||||
t.Error("wrong foreign join column:", r.JoinForeignColumn)
|
t.Error("wrong foreign join column:", r.JoinForeignColumn)
|
||||||
}
|
}
|
||||||
|
if r.JoinForeignColumnNullable {
|
||||||
|
t.Error("should not be nullable")
|
||||||
|
}
|
||||||
|
if !r.ToJoinTable {
|
||||||
|
t.Error("expected a join table")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestToManyRelationshipsNull(t *testing.T) {
|
||||||
|
t.Parallel()
|
||||||
|
|
||||||
|
tables := []Table{
|
||||||
|
Table{Name: "users", Columns: []Column{{Name: "id", Nullable: true}}},
|
||||||
|
Table{Name: "contests", Columns: []Column{{Name: "id", Nullable: true}}},
|
||||||
|
Table{
|
||||||
|
Name: "videos",
|
||||||
|
Columns: []Column{
|
||||||
|
{Name: "id", Nullable: true},
|
||||||
|
{Name: "user_id", Nullable: true},
|
||||||
|
{Name: "contest_id", Nullable: true},
|
||||||
|
},
|
||||||
|
FKeys: []ForeignKey{
|
||||||
|
{Name: "videos_user_id_fk", Column: "user_id", ForeignTable: "users", ForeignColumn: "id", Nullable: true},
|
||||||
|
{Name: "videos_contest_id_fk", Column: "contest_id", ForeignTable: "contests", ForeignColumn: "id", Nullable: true},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
Table{
|
||||||
|
Name: "notifications",
|
||||||
|
Columns: []Column{
|
||||||
|
{Name: "user_id", Nullable: true},
|
||||||
|
{Name: "source_id", Nullable: true},
|
||||||
|
},
|
||||||
|
FKeys: []ForeignKey{
|
||||||
|
{Name: "notifications_user_id_fk", Column: "user_id", ForeignTable: "users", ForeignColumn: "id", Nullable: true},
|
||||||
|
{Name: "notifications_source_id_fk", Column: "source_id", ForeignTable: "users", ForeignColumn: "id", Nullable: true},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
Table{
|
||||||
|
Name: "users_video_tags",
|
||||||
|
IsJoinTable: true,
|
||||||
|
Columns: []Column{
|
||||||
|
{Name: "user_id", Nullable: true},
|
||||||
|
{Name: "video_id", Nullable: true},
|
||||||
|
},
|
||||||
|
FKeys: []ForeignKey{
|
||||||
|
{Name: "user_id_fk", Column: "user_id", ForeignTable: "users", ForeignColumn: "id", Nullable: true},
|
||||||
|
{Name: "video_id_fk", Column: "video_id", ForeignTable: "videos", ForeignColumn: "id", Nullable: true},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
|
relationships := ToManyRelationships("users", tables)
|
||||||
|
if len(relationships) != 4 {
|
||||||
|
t.Error("wrong # of relationships:", len(relationships))
|
||||||
|
}
|
||||||
|
|
||||||
|
r := relationships[0]
|
||||||
|
if r.Column != "id" {
|
||||||
|
t.Error("wrong local column:", r.Column)
|
||||||
|
}
|
||||||
|
if !r.Nullable {
|
||||||
|
t.Error("should be nullable")
|
||||||
|
}
|
||||||
|
if r.ForeignTable != "videos" {
|
||||||
|
t.Error("wrong foreign table:", r.ForeignTable)
|
||||||
|
}
|
||||||
|
if r.ForeignColumn != "user_id" {
|
||||||
|
t.Error("wrong foreign column:", r.ForeignColumn)
|
||||||
|
}
|
||||||
|
if !r.ForeignColumnNullable {
|
||||||
|
t.Error("should be nullable")
|
||||||
|
}
|
||||||
|
if r.ToJoinTable {
|
||||||
|
t.Error("not a join table")
|
||||||
|
}
|
||||||
|
|
||||||
|
r = relationships[1]
|
||||||
|
if r.Column != "id" {
|
||||||
|
t.Error("wrong local column:", r.Column)
|
||||||
|
}
|
||||||
|
if !r.Nullable {
|
||||||
|
t.Error("should be nullable")
|
||||||
|
}
|
||||||
|
if r.ForeignTable != "notifications" {
|
||||||
|
t.Error("wrong foreign table:", r.ForeignTable)
|
||||||
|
}
|
||||||
|
if r.ForeignColumn != "user_id" {
|
||||||
|
t.Error("wrong foreign column:", r.ForeignColumn)
|
||||||
|
}
|
||||||
|
if !r.ForeignColumnNullable {
|
||||||
|
t.Error("should be nullable")
|
||||||
|
}
|
||||||
|
if r.ToJoinTable {
|
||||||
|
t.Error("not a join table")
|
||||||
|
}
|
||||||
|
|
||||||
|
r = relationships[2]
|
||||||
|
if r.Column != "id" {
|
||||||
|
t.Error("wrong local column:", r.Column)
|
||||||
|
}
|
||||||
|
if !r.Nullable {
|
||||||
|
t.Error("should be nullable")
|
||||||
|
}
|
||||||
|
if r.ForeignTable != "notifications" {
|
||||||
|
t.Error("wrong foreign table:", r.ForeignTable)
|
||||||
|
}
|
||||||
|
if r.ForeignColumn != "source_id" {
|
||||||
|
t.Error("wrong foreign column:", r.ForeignColumn)
|
||||||
|
}
|
||||||
|
if !r.ForeignColumnNullable {
|
||||||
|
t.Error("should be nullable")
|
||||||
|
}
|
||||||
|
if r.ToJoinTable {
|
||||||
|
t.Error("not a join table")
|
||||||
|
}
|
||||||
|
|
||||||
|
r = relationships[3]
|
||||||
|
if r.Column != "id" {
|
||||||
|
t.Error("wrong local column:", r.Column)
|
||||||
|
}
|
||||||
|
if !r.Nullable {
|
||||||
|
t.Error("should be nullable")
|
||||||
|
}
|
||||||
|
if r.ForeignColumn != "id" {
|
||||||
|
t.Error("wrong foreign column:", r.Column)
|
||||||
|
}
|
||||||
|
if !r.ForeignColumnNullable {
|
||||||
|
t.Error("should be nullable")
|
||||||
|
}
|
||||||
|
if r.ForeignTable != "videos" {
|
||||||
|
t.Error("wrong foreign table:", r.ForeignTable)
|
||||||
|
}
|
||||||
|
if r.JoinTable != "users_video_tags" {
|
||||||
|
t.Error("wrong join table:", r.ForeignTable)
|
||||||
|
}
|
||||||
|
if r.JoinLocalColumn != "user_id" {
|
||||||
|
t.Error("wrong local join column:", r.JoinLocalColumn)
|
||||||
|
}
|
||||||
|
if !r.JoinLocalColumnNullable {
|
||||||
|
t.Error("should be nullable")
|
||||||
|
}
|
||||||
|
if r.JoinForeignColumn != "video_id" {
|
||||||
|
t.Error("wrong foreign join column:", r.JoinForeignColumn)
|
||||||
|
}
|
||||||
|
if !r.JoinForeignColumnNullable {
|
||||||
|
t.Error("should be nullable")
|
||||||
|
}
|
||||||
if !r.ToJoinTable {
|
if !r.ToJoinTable {
|
||||||
t.Error("expected a join table")
|
t.Error("expected a join table")
|
||||||
}
|
}
|
||||||
|
|
|
@ -11,6 +11,8 @@ type Table struct {
|
||||||
FKeys []ForeignKey
|
FKeys []ForeignKey
|
||||||
|
|
||||||
IsJoinTable bool
|
IsJoinTable bool
|
||||||
|
|
||||||
|
ToManyRelationships []ToManyRelationship
|
||||||
}
|
}
|
||||||
|
|
||||||
// GetTable by name. Panics if not found (for use in templates mostly).
|
// GetTable by name. Panics if not found (for use in templates mostly).
|
||||||
|
|
Loading…
Reference in a new issue