-
Notifications
You must be signed in to change notification settings - Fork 15
/
statement.go
130 lines (104 loc) · 2.65 KB
/
statement.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
package dqlx
import (
"bytes"
"fmt"
"reflect"
"strings"
"time"
)
func toVariables(rawVariables map[int]interface{}) (variables map[string]string, placeholders []string) {
variables = map[string]string{}
placeholders = make([]string, len(rawVariables))
queryPlaceholderNames := getSortedVariables(rawVariables)
// Format Variables
for index, placeholderName := range queryPlaceholderNames {
variableName := fmt.Sprintf("$%d", placeholderName)
variables[variableName] = toVariableValue(rawVariables[index])
placeholders[index] = fmt.Sprintf("$%d:%s", placeholderName, goTypeToDQLType(rawVariables[placeholderName]))
}
return variables, placeholders
}
func toVariableValue(value interface{}) string {
switch val := value.(type) {
case time.Time:
return val.Format(time.RFC3339)
case *time.Time:
return val.Format(time.RFC3339)
default:
return fmt.Sprintf("%v", val)
}
}
func goTypeToDQLType(value interface{}) string {
switch value.(type) {
case string:
return "string"
case int, int8, int32, int64:
return "int"
case float32, float64:
return "float"
case bool:
return "bool"
case time.Time, *time.Time:
return "datetime"
}
return "string"
}
func dqlTypeToGoType(value DGraphScalar) string {
switch value {
case ScalarPassword, ScalarString, ScalarUID:
return "string"
case ScalarInt:
return "int64"
case ScalarDateTime:
return "time.Time"
case ScalarBool:
return "bool"
case ScalarFloat:
return "float64"
}
return string(value)
}
func replacePlaceholders(query string, args []interface{}, transform func(index int, value interface{}) string) (string, map[int]interface{}) {
variables := map[int]interface{}{}
buf := &bytes.Buffer{}
i := 0
for {
p := strings.Index(query, "??")
if p == -1 {
break
}
buf.WriteString(query[:p])
key := transform(i, args[i])
buf.WriteString(key)
query = query[p+2:]
// Assign the variables
variables[i] = args[i]
i++
}
buf.WriteString(query)
return buf.String(), variables
}
func isListType(val interface{}) bool {
valVal := reflect.ValueOf(val)
return valVal.Kind() == reflect.Array || valVal.Kind() == reflect.Slice
}
func addStatement(parts []DQLizer, statements *[]string, args *[]interface{}) error {
for _, block := range parts {
statement, queryArg, err := block.ToDQL()
if err != nil {
return err
}
*statements = append(*statements, statement)
*args = append(*args, queryArg...)
}
return nil
}
func addPart(part DQLizer, writer *bytes.Buffer, args *[]interface{}) error {
statement, statementArgs, err := part.ToDQL()
*args = append(*args, statementArgs...)
if err != nil {
return err
}
writer.WriteString(statement)
return nil
}