1
+ package querysql
2
+
3
+ import (
4
+ "fmt"
5
+ "strconv"
6
+ "strings"
7
+ "testing"
8
+ )
9
+
10
+ var aAndB = `{ "glue":"and", "data":[{ "field": "a", "condition":{ "rule":"less", "value":1}}, { "field": "b", "condition":{ "rule":"greater", "value":"abc" }}]}`
11
+ var aOrB = `{ "glue":"or", "data":[{ "field": "a", "condition":{ "rule":"less", "value":1}}, { "field": "b", "condition":{ "rule":"greater", "value":"abc" }}]}`
12
+ var cOrC = `{ "glue":"or", "data":[{ "field": "a", "condition":{ "rule":"is null" }}, { "field": "b", "condition":{ "rule":"range100", "value":500 }}]}`
13
+
14
+ var cases = [][]string {
15
+ []string {`{}` , "" , "" },
16
+ []string {
17
+ `{ "glue":"and", "data":[{ "field": "a", "condition":{ "rule":"equal", "value":1 }}]}` ,
18
+ "a = ?" ,
19
+ "1" ,
20
+ },
21
+ []string {
22
+ aAndB ,
23
+ "( a < ? AND b > ? )" ,
24
+ "1,abc" ,
25
+ },
26
+ []string {
27
+ aOrB ,
28
+ "( a < ? OR b > ? )" ,
29
+ "1,abc" ,
30
+ },
31
+ []string {
32
+ `{ "glue":"AND", "data":[` + aAndB + `,` + aOrB + `,{ "field":"c", "condition": { "rule":"equal", "value":3 } }]}` ,
33
+ "( ( a < ? AND b > ? ) AND ( a < ? OR b > ? ) AND c = ? )" ,
34
+ "1,abc,1,abc,3" ,
35
+ },
36
+ []string {
37
+ `{ "glue":"and", "data":[{ "field": "a", "includes":[1,2,3]}]}` ,
38
+ "a IN(?,?,?)" ,
39
+ "1,2,3" ,
40
+ },
41
+ []string {
42
+ `{ "glue":"and", "data":[{ "field": "a", "includes":["a","b","c"]}]}` ,
43
+ "a IN(?,?,?)" ,
44
+ "a,b,c" ,
45
+ },
46
+ }
47
+
48
+ func anyToStringArray (some []interface {}) (string , error ) {
49
+ out := make ([]string , 0 , len (some ))
50
+ for _ , x := range some {
51
+ str , strOk := x .(string )
52
+ if strOk {
53
+ out = append (out , str )
54
+ continue
55
+ }
56
+
57
+ num , numOk := x .(float64 )
58
+ if numOk {
59
+ out = append (out , strconv .Itoa (int (num )))
60
+ continue
61
+ }
62
+
63
+ return "" , fmt .Errorf ("can't convert %+v to a string" , x )
64
+ }
65
+
66
+ return strings .Join (out , "," ), nil
67
+ }
68
+
69
+ func TestSQL (t * testing.T ) {
70
+ for _ , line := range cases {
71
+ format , err := FromJSON ([]byte (line [0 ]))
72
+ if err != nil {
73
+ t .Errorf ("can't parse json\n j: %s\n %f" , line [0 ], err )
74
+ continue
75
+ }
76
+
77
+ sql , vals , err := GetSQL (format , nil )
78
+ if err != nil {
79
+ t .Errorf ("can't generate sql\n j: %s\n %f" , line [0 ], err )
80
+ continue
81
+ }
82
+ if sql != line [1 ] {
83
+ t .Errorf ("wrong sql generated\n j: %s\n s: %s\n r: %s" , line [0 ], line [1 ], sql )
84
+ continue
85
+ }
86
+
87
+ valsStr , err := anyToStringArray (vals )
88
+ if err != nil {
89
+ t .Errorf ("can't convert parameters\n j: %s\n %f" , line [0 ], err )
90
+ continue
91
+ }
92
+
93
+ if valsStr != line [2 ] {
94
+ t .Errorf ("wrong sql generated\n j: %s\n s: %s\n r: %s" , line [0 ], line [2 ], valsStr )
95
+ continue
96
+ }
97
+ }
98
+ }
99
+
100
+ func TestWhitelist (t * testing.T ) {
101
+ format , err := FromJSON ([]byte (aAndB ))
102
+ if err != nil {
103
+ t .Errorf ("can't parse json\n j: %s\n %f" , aAndB , err )
104
+ return
105
+ }
106
+
107
+ _ , _ , err = GetSQL (format , nil )
108
+ if err != nil {
109
+ t .Errorf ("doesn't work without config" )
110
+ return
111
+ }
112
+ _ , _ , err = GetSQL (format , & SQLConfig {})
113
+ if err != nil {
114
+ t .Errorf ("doesn't work without whitelist" )
115
+ return
116
+ }
117
+
118
+ _ , _ , err = GetSQL (format , & SQLConfig {Whitelist : map [string ]bool {"a" : true , "b" : true }})
119
+ if err != nil {
120
+ t .Errorf ("doesn't work with fields allowed" )
121
+ return
122
+ }
123
+
124
+ _ , _ , err = GetSQL (format , & SQLConfig {Whitelist : map [string ]bool {"a" : true }})
125
+ if err == nil {
126
+ t .Errorf ("doesn't return error when field is not allowed" )
127
+ return
128
+ }
129
+
130
+ _ , _ , err = GetSQL (format , & SQLConfig {Whitelist : map [string ]bool {"b" : true }})
131
+ if err == nil {
132
+ t .Errorf ("doesn't return error when field is not allowed" )
133
+ return
134
+ }
135
+ }
136
+
137
+ func TestCustomOperation (t * testing.T ) {
138
+ format , err := FromJSON ([]byte (cOrC ))
139
+ if err != nil {
140
+ t .Errorf ("can't parse json\n j: %s\n %f" , aAndB , err )
141
+ return
142
+ }
143
+
144
+ sql , vals , err := GetSQL (format , & SQLConfig {
145
+ Operations : map [string ]CustomOperation {
146
+ "is null" : func (n string , c Condition ) (string , []interface {}, error ) {
147
+ return fmt .Sprintf ("%s IS NULL" , n ), NoValues , nil
148
+ },
149
+ "range100" : func (n string , c Condition ) (string , []interface {}, error ) {
150
+ return fmt .Sprintf ("( %s > ? AND %s < ? + 100 )" , n , n ), []interface {}{c .Value , c .Value }, nil
151
+ },
152
+ },
153
+ })
154
+
155
+ if err != nil {
156
+ t .Errorf ("can't generate sql: %s\n %f" , cOrC , err )
157
+ return
158
+ }
159
+
160
+ check := "( a IS NULL OR ( b > ? AND b < ? + 100 ) )"
161
+ if sql != check {
162
+ t .Errorf ("wrong sql generated\n j: %s\n s: %s\n r: %s" , cOrC , check , sql )
163
+ return
164
+ }
165
+
166
+ valsStr , err := anyToStringArray (vals )
167
+ if err != nil {
168
+ t .Errorf ("can't convert parameters\n j: %s\n %f" , cOrC , err )
169
+ return
170
+ }
171
+
172
+ check = "500,500"
173
+ if valsStr != check {
174
+ t .Errorf ("wrong sql generated\n j: %s\n s: %s\n r: %s" , cOrC , check , valsStr )
175
+ return
176
+ }
177
+ }
0 commit comments