-
Notifications
You must be signed in to change notification settings - Fork 0
/
relationship.go
118 lines (100 loc) · 2.78 KB
/
relationship.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
package base
import (
"reflect"
"github.com/pkg/errors"
"github.com/daihasso/machgo/refl"
)
type typeTableColumn struct {
typ reflect.Type
column,
table string
}
// Relationship is a representation of how two objects join together.
type Relationship struct {
selfInfo,
targetInfo typeTableColumn
}
// Invert takes the relationship and swaps the self with the target.
// This essentially has the effect of changing:
// foo.bar=baz.fizz
// Into:
// baz.fizz=foo.bar
func (self Relationship) Invert() *Relationship {
return &Relationship {
selfInfo: self.targetInfo,
targetInfo: self.selfInfo,
}
}
func (self Relationship) Tables() (string, string) {
return self.selfInfo.table, self.targetInfo.table
}
func (self Relationship) Columns() (string, string) {
return self.selfInfo.column, self.targetInfo.column
}
func (self Relationship) Types() (reflect.Type, reflect.Type) {
return self.selfInfo.typ, self.targetInfo.typ
}
// Relationshipable is a type that has at least on relationship.
type Relationshipable interface {
Relationships() []Relationship
}
func NewRelationship(
self Base, selfColumn string, target Base, targetColumn string,
) (*Relationship, error) {
selfTable, err := BaseTable(self)
if err != nil {
return nil, errors.Wrap(
err, "Error determining table for self in relationship",
)
}
targetTable, err := BaseTable(target)
if err != nil {
return nil, errors.Wrap(
err, "Error determining table for target in relationship",
)
}
targetInfo := typeTableColumn{
typ: refl.Deref(reflect.TypeOf(target)),
column: targetColumn,
table: targetTable,
}
selfInfo := typeTableColumn{
typ: refl.Deref(reflect.TypeOf(self)),
column: selfColumn,
table: selfTable,
}
return &Relationship{
selfInfo: selfInfo,
targetInfo: targetInfo,
}, nil
}
func MustRelationship(
self Base, selfColumn string, target Base, targetColumn string,
) Relationship {
selfTable, err := BaseTable(self)
if err != nil {
panic(errors.Wrap(
err, "Error determining table for self in relationship",
))
}
targetTable, err := BaseTable(target)
if err != nil {
panic(errors.Wrap(
err, "Error determining table for target in relationship",
))
}
targetInfo := typeTableColumn{
typ: refl.Deref(reflect.TypeOf(target)),
column: targetColumn,
table: targetTable,
}
selfInfo := typeTableColumn{
typ: refl.Deref(reflect.TypeOf(self)),
column: selfColumn,
table: selfTable,
}
return Relationship{
selfInfo: selfInfo,
targetInfo: targetInfo,
}
}