-
Notifications
You must be signed in to change notification settings - Fork 15
/
Copy pathselection.go
180 lines (143 loc) · 4.08 KB
/
selection.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
package dqlx
import (
"bytes"
"fmt"
"strings"
)
type node struct {
Attributes DQLizer
ParentName string
Edges map[string][]QueryBuilder
HasParentAttributes bool
}
// ToDQL returns the DQL statements for representing a selection set
func (node node) ToDQL() (query string, args []interface{}, err error) {
writer := bytes.Buffer{}
if node.Attributes != nil {
if err := addPart(node.Attributes, &writer, &args); err != nil {
return "", nil, err
}
}
// nested childrenEdges
nestedEdges, ok := node.Edges[node.ParentName]
if !ok {
return writer.String(), args, nil
}
statements := make([]string, 0, len(nestedEdges))
for _, queryBuilder := range nestedEdges {
nestedEdge, edgesArgs, err := queryBuilder.rootEdge.ToDQL()
args = append(args, edgesArgs...)
if err != nil {
return "", nil, err
}
statements = append(statements, nestedEdge)
}
// add a space if parent nodeAttributes are present
if node.HasParentAttributes {
writer.WriteString(" ")
}
writer.WriteString(strings.Join(statements, " "))
return writer.String(), args, nil
}
type nodeAttributes struct {
predicates []interface{}
}
// Select adds nodeAttributes to selection set
func Select(predicates ...interface{}) DQLizer {
return nodeAttributes{predicates}
}
// Fields alias of Select
// @Deprecated use Select() instead
func Fields(predicates ...interface{}) DQLizer {
return Select(predicates...)
}
// ToDQL returns the dql statement for selected nodeAttributes
func (fields nodeAttributes) ToDQL() (query string, args []interface{}, err error) {
var selectedFields []string
for _, field := range fields.predicates {
switch requestField := field.(type) {
case DQLizer:
computedDql, computedArgs, err := requestField.ToDQL()
if err != nil {
return "", nil, err
}
args = append(args, computedArgs...)
selectedFields = append(selectedFields, computedDql)
case string:
fieldString := parsePredicates(requestField)
selectedFields = append(selectedFields, fieldString...)
default:
return "", nil, fmt.Errorf("nodeAttributes can only accept strings or Dqlizer, given %v", requestField)
}
}
return strings.Join(selectedFields, " "), args, nil
}
type aliasField struct {
alias string
value interface{}
}
// Alias allows to alias a field
func Alias(alias string, predicate interface{}) DQLizer {
return aliasField{
alias: alias,
value: predicate,
}
}
// ToDQL returns the alias dql statement of a field
func (aliasField aliasField) ToDQL() (query string, args []interface{}, err error) {
var value string
switch cast := aliasField.value.(type) {
case DQLizer:
value, args, err = cast.ToDQL()
if err != nil {
return "", nil, err
}
case string:
value = EscapePredicate(cast)
default:
return "", nil, fmt.Errorf("alias only accepts string or DQlizers, given %v", value)
}
aliasName := EscapePredicate(aliasField.alias)
return fmt.Sprintf("%s:%s", aliasName, value), args, nil
}
type as struct {
variable string
predicate interface{}
}
// As makes a field a variable
// Example: dqlx.Query(...).Select(dqlx.As("C", "a"))
func As(varName string, predicate interface{}) DQLizer {
return as{
variable: varName,
predicate: predicate,
}
}
// ToDQL returns the dql statement for a field variable
func (as as) ToDQL() (query string, args []interface{}, err error) {
var predicate string
switch cast := as.predicate.(type) {
case DQLizer:
predicate, args, err = cast.ToDQL()
if err != nil {
return "", nil, err
}
case string:
predicate = EscapePredicate(cast)
default:
return "", nil, fmt.Errorf("alias only accepts string or DQlizers, given %v", predicate)
}
varName := escapeSpecialChars(as.variable)
return fmt.Sprintf("%s as %s", varName, predicate), args, nil
}
func parsePredicates(predicates string) []string {
var parsedFields []string
fieldsParts := strings.Split(predicates, "\n")
for _, fieldPart := range fieldsParts {
if strings.TrimSpace(fieldPart) == "" {
continue
}
escapedField := EscapePredicate(fieldPart)
parsedFields = append(parsedFields, escapedField)
}
return parsedFields
}