-
Notifications
You must be signed in to change notification settings - Fork 4
/
stmt_document_parsing_test.go
146 lines (136 loc) · 6.88 KB
/
stmt_document_parsing_test.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
package godynamo
import (
"fmt"
"reflect"
"testing"
"github.com/aws/aws-sdk-go-v2/aws"
)
func Test_Stmt_Select_parse(t *testing.T) {
testName := "Test_Stmt_Select_parse"
testData := []struct {
name string
sql string
afterSql string
numInput int
limit *int32
mustError bool
}{
{name: "basic", sql: `SELECT * FROM "table"`, numInput: 0, afterSql: `SELECT * FROM "table"`},
{name: "limit", sql: `SELECT * FROM "table" LIMIT 10`, numInput: 0, limit: aws.Int32(10), afterSql: `SELECT * FROM "table"`},
{name: "limit with space", sql: `SELECT * FROM "table" LIMIT 10`, numInput: 0, limit: aws.Int32(10), afterSql: `SELECT * FROM "table"`},
{name: "limit with space and new line", sql: `SELECT * FROM "table" LIMIT 10
`, numInput: 0, limit: aws.Int32(10), afterSql: `SELECT * FROM "table"`},
{name: "parameterized", sql: `SELECT * FROM "table" WHERE id=?`, numInput: 1, afterSql: `SELECT * FROM "table" WHERE id=?`},
{name: "parameterized with space", sql: `SELECT * FROM "table" WHERE id = ?`, numInput: 1, afterSql: `SELECT * FROM "table" WHERE id = ?`},
{name: "parameterized with space and new line", sql: `SELECT * FROM "table" WHERE id = ?
`, numInput: 1, afterSql: `SELECT * FROM "table" WHERE id = ?`},
{name: "invalid limit", sql: `SELECT * FROM "table" LIMIT a`, mustError: true},
{name: "invalid limit value", sql: `SELECT * FROM "table" LIMIT -2`, mustError: true},
{name: "limit value with opt", sql: `SELECT * FROM "table" LIMIT 1 WITH CONSTENCY=strong`, mustError: false, limit: aws.Int32(1), afterSql: `SELECT * FROM "table"`},
}
for _, testCase := range testData {
t.Run(testCase.name, func(t *testing.T) {
s, err := parseQuery(nil, testCase.sql)
if testCase.mustError && err == nil {
t.Fatalf("%s failed: parsing must fail", testName+"/"+testCase.name)
}
if testCase.mustError {
return
}
if err != nil {
t.Fatalf("%s failed: %s", testName+"/"+testCase.name, err)
}
stmt, ok := s.(*StmtSelect)
if !ok {
t.Fatalf("%s failed: expected StmtSelect but received %T", testName+"/"+testCase.name, stmt)
}
if stmt.numInput != testCase.numInput {
t.Fatalf("%s failed: expected %#v input parameters but received %#v", testName+"/"+testCase.name, testCase.numInput, stmt.numInput)
}
if (testCase.limit == nil && stmt.limit != nil) || (testCase.limit != nil && (stmt.limit == nil || *testCase.limit != *stmt.limit)) {
t.Fatalf("%s failed: expected %#v limit but received %#v", testName+"/"+testCase.name, testCase.limit, stmt.limit)
}
if stmt.query != testCase.afterSql {
t.Fatalf("%s failed: expected %#v afterSql but received %#v", testName+"/"+testCase.name, testCase.afterSql, stmt.query)
}
})
}
}
func Test_Stmt_Select_parse_placeholders(t *testing.T) {
testName := "Test_Stmt_Select_parse_placeholders"
testData := []struct {
name string
sql string
numPlaceholders int
}{
{name: "basic", sql: `SELECT * FROM "table"`, numPlaceholders: 0},
{name: "parameterized", sql: `SELECT * FROM "table" WHERE id=?`, numPlaceholders: 1},
{name: "parameterized with space", sql: `SELECT * FROM "table" WHERE id = ?`, numPlaceholders: 1},
{name: "parameterized with space and new line", sql: `SELECT * FROM "table" WHERE id = ?
`, numPlaceholders: 1},
{name: "multiple placeholders", sql: `SELECT "Category", "Name" FROM "Forum" WHERE ("Category" IS NULL OR "Category" = ? OR trim("Category") = ?)`, numPlaceholders: 2},
{name: "not in string", sql: `SELECT * FROM "table" WHERE id = 'ab'+?+'cd'`, numPlaceholders: 1},
{name: "not in string with prefix", sql: `SELECT * FROM "table" WHERE id = prefix+'ab'+?+"cd"`, numPlaceholders: 1},
{name: "not in string with suffix", sql: `SELECT * FROM "table" WHERE id = "ab"+?+"cd"+suffix`, numPlaceholders: 1},
{name: "in string - single quote", sql: `SELECT * FROM "table" WHERE id = 'ab?cd'`, numPlaceholders: 0},
{name: "in string - double quote", sql: `SELECT * FROM "table" WHERE id = "ab?cd"`, numPlaceholders: 0},
{name: "in string - double quote inside single quote", sql: `SELECT * FROM "table" WHERE id = 'ab"?"cd'`, numPlaceholders: 0},
{name: "in string - single quote inside double quote", sql: `SELECT * FROM "table" WHERE id = "ab'?'cd"`, numPlaceholders: 0},
{name: "in string with space - single quote", sql: `SELECT * FROM "table" WHERE id = 'ab? cd'`, numPlaceholders: 0},
{name: "in string with space - double quote", sql: `SELECT * FROM "table" WHERE id = "ab? cd"`, numPlaceholders: 0},
{name: "in string with space - double quote inside single quote", sql: `SELECT * FROM "table" WHERE id = 'ab"? "cd'`, numPlaceholders: 0},
{name: "in string with space - single quote inside double quote", sql: `SELECT * FROM "table" WHERE id = "ab'? 'cd"`, numPlaceholders: 0},
{name: "large number of placeholders", sql: `SELECT * FROM "table" WHERE id = ? AND name = ? AND age = ? AND active = ? AND grade = ? AND list = ? AND map = ?`, numPlaceholders: 7},
{name: "placeholder inside sql functions", sql: `SELECT * FROM "table" WHERE id = trim(?)`, numPlaceholders: 1},
{name: "placeholder inside sql functions with space", sql: `SELECT * FROM "table" WHERE id = trim( ? )`, numPlaceholders: 1},
}
for _, testCase := range testData {
t.Run(testCase.name, func(t *testing.T) {
stmt, err := parseQuery(nil, testCase.sql)
if err != nil {
t.Fatalf("%s failed: %s", testCase.name, err)
}
if stmt.NumInput() != testCase.numPlaceholders {
fmt.Printf("[DEBUG] %s\n", testCase.sql)
t.Fatalf("%s failed: expected %#v placeholders but received %#v", testName+"/"+testCase.name, testCase.numPlaceholders, stmt.NumInput())
}
})
}
}
func Test_Stmt_Select_parse_withopts(t *testing.T) {
testName := "Test_Stmt_Select_parse_withopts"
testCases := []struct {
name string
sql string
expected map[string]OptStrings
}{{
name: "basic",
sql: `SELECT * FROM "table"`,
expected: map[string]OptStrings{},
}, {
name: "with read consistency",
sql: `SELECT * FROM "table" WITH CONSISTENTREAD=strong`,
expected: map[string]OptStrings{"CONSISTENTREAD": {"strong"}},
}, {
name: "with read consistency and projection",
sql: `SELECT * FROM "table" WITH CONSISTENTREAD=strong WITH PROJECTION=ALL`,
expected: map[string]OptStrings{"CONSISTENTREAD": {"strong"}, "PROJECTION": {"ALL"}},
},
}
for _, testCase := range testCases {
t.Run(testCase.name, func(t *testing.T) {
stmt, err := parseQuery(nil, testCase.sql)
if err != nil {
fmt.Printf("[DEBUG] %s\n", testCase.sql)
t.Fatalf("%s failed: %s", testName+"/"+testCase.name, err)
}
stmtSelect, ok := stmt.(*StmtSelect)
if !ok {
t.Fatalf("%s failed: expected StmtSelect but received %T", testName+"/"+testCase.name, stmt)
}
if !reflect.DeepEqual(stmtSelect.withOpts, testCase.expected) {
t.Fatalf("%s failed: expected %#v but received %#v", testName+"/"+testCase.name, testCase.expected, stmtSelect.withOpts)
}
})
}
}