-
Notifications
You must be signed in to change notification settings - Fork 6
/
manyManyNode.go
228 lines (196 loc) · 6.09 KB
/
manyManyNode.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
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
package query
import (
"bytes"
"encoding/gob"
"log"
"strings"
)
// A ManyManyNode is an association node that links one table to another table with a many-to-many relationship.
// Some of the columns have overloaded meanings depending on SQL or NoSQL mode.
type ManyManyNode struct {
nodeAlias
nodeCondition
nodeLink
// Which database in the global list of databases does the node belong to
dbKey string
// NoSQL: The originating table. SQL: The association table
dbTable string
// NoSQL: The table storing the array of ids on the other end. SQL: the table in the association table pointing towards us.
dbColumn string
// Property in the original object used to ref to this object or node.
goPropName string
// NoSQL & SQL: The table we are joining to
refTable string
// NoSQL: table point backwards to us. SQL: Column in association table pointing forwards to refTable
refColumn string
// Are we expanding as an array, or one item at a time.
isArray bool
// Is this pointing to a type table item?
isTypeTable bool
}
// NewManyManyNode is used internally by the framework to return a new ManyMany node.
func NewManyManyNode(
dbKey string,
// NoSQL: The originating table. SQL: The association table
dbTable string,
// NoSQL: The table storing the array of ids on the other end. SQL: the table in the association table pointing towards us.
dbColumn string,
// Property in the original object used to ref to this object or node.
goName string,
// NoSQL & SQL: The table we are joining to
refTableName string,
// NoSQL: table point backwards to us. SQL: Column in association table pointing forwards to refTable
refColumn string,
// Are we pointing to a type table
isType bool,
) *ManyManyNode {
n := &ManyManyNode{
dbKey: dbKey,
dbTable: dbTable,
dbColumn: dbColumn,
goPropName: goName,
refTable: refTableName,
refColumn: refColumn,
isArray: true,
isTypeTable: isType,
}
return n
}
func (n *ManyManyNode) copy() NodeI {
ret := &ManyManyNode{
dbKey: n.dbKey,
dbTable: n.dbTable,
dbColumn: n.dbColumn,
goPropName: n.goPropName,
refTable: n.refTable,
refColumn: n.refColumn,
isArray: n.isArray,
isTypeTable: n.isTypeTable,
nodeAlias: nodeAlias{n.alias},
nodeCondition: nodeCondition{n.condition}, // shouldn't need to duplicate condition
}
return ret
}
func (n *ManyManyNode) nodeType() NodeType {
return ManyManyNodeType
}
// Expand tells this node to create multiple original objects with a single link for each joined item, rather than to create one original with an array of joined items
func (n *ManyManyNode) Expand() {
n.isArray = false
}
// isExpanded reports whether this node is creating a new object for each joined item (true), or creating an array of
// joined items (false).
func (n *ManyManyNode) isExpanded() bool {
return !n.isArray
}
func (n *ManyManyNode) isExpander() bool {
return true
}
// Equals is used internally by the framework to test if the node is the same as another node.
func (n *ManyManyNode) Equals(n2 NodeI) bool {
if tn, ok := n2.(TableNodeI); !ok {
return false
} else if cn, ok2 := tn.EmbeddedNode_().(*ManyManyNode); !ok2 {
return false
} else {
return cn.dbTable == n.dbTable &&
cn.goPropName == n.goPropName &&
(cn.alias == "" || n.alias == "" || cn.alias == n.alias)
}
}
func (n *ManyManyNode) tableName() string {
return n.refTable
}
func (n *ManyManyNode) databaseKey() string {
return n.dbKey
}
func (n *ManyManyNode) log(level int) {
tabs := strings.Repeat("\t", level)
log.Print(tabs + "MM: " + n.dbTable + "." + n.dbColumn + "." + n.refTable + "." + n.refColumn + " AS " + n.GetAlias())
}
// Return the name as a captialized object name
func (n *ManyManyNode) goName() string {
return n.goPropName
}
type manyManyNodeEncoded struct {
Alias string
Condition NodeI
Parent NodeI
DbKey string
DbTable string
DbColumn string
GoPropName string
RefTable string
RefColumn string
IsArray bool
IsTypeTable bool
}
func (n *ManyManyNode) GobEncode() (data []byte, err error) {
var buf bytes.Buffer
e := gob.NewEncoder(&buf)
s := manyManyNodeEncoded{
Alias: n.alias,
Condition: n.condition,
Parent: n.parentNode,
DbKey: n.dbKey,
DbTable: n.dbTable,
DbColumn: n.dbColumn,
GoPropName: n.goPropName,
RefTable: n.refTable,
RefColumn: n.refColumn,
IsArray: n.isArray,
IsTypeTable: n.isTypeTable,
}
if err = e.Encode(s); err != nil {
panic(err)
}
data = buf.Bytes()
return
}
func (n *ManyManyNode) GobDecode(data []byte) (err error) {
buf := bytes.NewBuffer(data)
dec := gob.NewDecoder(buf)
var s manyManyNodeEncoded
if err = dec.Decode(&s); err != nil {
panic(err)
}
n.alias = s.Alias
n.condition = s.Condition
n.dbKey = s.DbKey
n.dbTable = s.DbTable
n.dbColumn = s.DbColumn
n.goPropName = s.GoPropName
n.refTable = s.RefTable
n.refColumn = s.RefColumn
n.isArray = s.IsArray
n.isTypeTable = s.IsTypeTable
SetParentNode(n, s.Parent)
return
}
func init() {
gob.Register(&ManyManyNode{})
}
// ManyManyNodeIsArray is used internally by the framework to return whether the node creates an array, or just a link to a single item.
func ManyManyNodeIsArray(n *ManyManyNode) bool {
return n.isArray
}
// ManyManyNodeIsTypeTable is used internally by the framework to return whether the node points to a type table
func ManyManyNodeIsTypeTable(n *ManyManyNode) bool {
return n.isTypeTable
}
// ManyManyNodeRefTable is used internally by the framework to return the table name on the other end of the link
func ManyManyNodeRefTable(n *ManyManyNode) string {
return n.refTable
}
// ManyManyNodeRefColumn is used internally by the framework to return the column name on the other end of the link
func ManyManyNodeRefColumn(n *ManyManyNode) string {
return n.refColumn
}
// ManyManyNodeDbTable is used internally by the framework to return the table name of the table the node belongs to
func ManyManyNodeDbTable(n *ManyManyNode) string {
return n.dbTable
}
// ManyManyNodeDbColumn is used internally by the framework to return the column name in the table the node belongs to
func ManyManyNodeDbColumn(n *ManyManyNode) string {
return n.dbColumn
}