11package builder_test
22
33import (
4- "strings"
54 "testing"
65
76 "github.com/stretchr/testify/assert"
@@ -11,43 +10,104 @@ import (
1110)
1211
1312func TestN (t * testing.T ) {
14- validIdentifiers := []string {
15- "column_name1" ,
16- `"MyTable".name` ,
17- "public.\" MyTable\" .*" ,
18- `"My"."Table".name` ,
19- `"My""Quoted""Table".*` ,
20- "space_trimmed " ,
21- "táblá_ñámé" ,
22- "öäüß_column" ,
23- `U&"d\0061t\+000061"` ,
24- `U&"\0441\043B\043E\043D"` ,
25- `U&"d!0061t!+000061" UESCAPE '!'` ,
26- }
13+ tests := []struct {
14+ input string
15+ expectInvalid bool
16+ expected string
17+ }{
18+ // Regular identifiers (unchanged)
19+ {"column_name1" , false , "column_name1" },
20+ {"users" , false , "users" },
21+ {"táblá_ñámé" , false , "táblá_ñámé" },
22+ {"öäüß_column" , false , "öäüß_column" },
23+ {"space_trimmed " , false , "space_trimmed" },
2724
28- invalidIdentifiers := []string {
29- "1column_name" ,
30- `"MyTable.name` ,
31- `My"Table.name` ,
32- }
25+ // Dotted paths without keywords (unchanged)
26+ {"public.users" , false , "public.users" },
27+ {"schema.mytable.mycolumn" , false , "schema.mytable.mycolumn" },
3328
34- for _ , id := range validIdentifiers {
35- t .Run (id , func (t * testing.T ) {
36- q := qrb .N (id )
29+ // Asterisks (unchanged)
30+ {"*" , false , "*" },
31+ {"mytable.*" , false , "mytable.*" },
32+ {"public.mytable.*" , false , "public.mytable.*" },
3733
38- sql , _ , err := qrb .Build (q ).ToSQL ()
39- require .NoError (t , err )
40- assert .Equal (t , strings .TrimSpace (id ), sql )
41- assert .Equal (t , strings .TrimSpace (id ), q .Ident ())
42- })
34+ // Dotted paths with "table" and "column" keywords
35+ {"schema.table.column" , false , `schema."table"."column"` },
36+ {"table.*" , false , `"table".*` },
37+ {"public.table.*" , false , `public."table".*` },
38+
39+ // Already quoted identifiers (unchanged)
40+ {`"MyTable".name` , false , `"MyTable".name` },
41+ {`public."MyTable".*` , false , `public."MyTable".*` },
42+ {`"My"."Table".name` , false , `"My"."Table".name` },
43+ {`"My""Quoted""Table".*` , false , `"My""Quoted""Table".*` },
44+
45+ // Unicode identifiers (unchanged)
46+ {`U&"d\0061t\+000061"` , false , `U&"d\0061t\+000061"` },
47+ {`U&"\0441\043B\043E\043D"` , false , `U&"\0441\043B\043E\043D"` },
48+ {`U&"d!0061t!+000061" UESCAPE '!'` , false , `U&"d!0061t!+000061" UESCAPE '!'` },
49+
50+ // Keywords - should be auto-quoted
51+ {"from" , false , `"from"` },
52+ {"select" , false , `"select"` },
53+ {"where" , false , `"where"` },
54+ {"order" , false , `"order"` },
55+ {"group" , false , `"group"` },
56+ {"user" , false , `"user"` },
57+ {"table" , false , `"table"` },
58+ {"to" , false , `"to"` },
59+ {"all" , false , `"all"` },
60+ {"and" , false , `"and"` },
61+ {"or" , false , `"or"` },
62+ {"not" , false , `"not"` },
63+ {"null" , false , `"null"` },
64+ {"true" , false , `"true"` },
65+ {"false" , false , `"false"` },
66+ {"in" , false , "in" }, // "in" is not a reserved keyword
67+
68+ // Keywords with different cases - should be auto-quoted
69+ {"FROM" , false , `"FROM"` },
70+ {"Select" , false , `"Select"` },
71+ {"WHERE" , false , `"WHERE"` },
72+ {"User" , false , `"User"` },
73+
74+ // Keywords in dotted paths - only keyword parts should be quoted
75+ {"mytable.from.id" , false , `mytable."from".id` },
76+ {"schema.select.mycolumn" , false , `schema."select".mycolumn` },
77+ {"public.user.name" , false , `public."user".name` },
78+ {"from.to.where" , false , `"from"."to"."where"` },
79+ {"table.from.id" , false , `"table"."from".id` },
80+ {"schema.select.column" , false , `schema."select"."column"` },
81+
82+ // Already quoted keywords (unchanged)
83+ {`"from"` , false , `"from"` },
84+ {`"select"` , false , `"select"` },
85+ {`mytable."from".id` , false , `mytable."from".id` },
86+ {`"table"."from"."id"` , false , `"table"."from"."id"` },
87+
88+ // Quoted identifier with dot inside (unchanged)
89+ {`schema."my.table".mycolumn` , false , `schema."my.table".mycolumn` },
90+ // Keywords in quoted identifier context
91+ {`table."from".id` , false , `"table"."from".id` },
92+ {`schema."my.table".column` , false , `schema."my.table"."column"` },
93+
94+ // Invalid identifiers
95+ {"1column_name" , true , "" },
96+ {`"MyTable.name` , true , "" },
97+ {`My"Table.name` , true , "" },
4398 }
4499
45- for _ , id := range invalidIdentifiers {
46- t .Run (id , func (t * testing.T ) {
47- q := qrb .N (id )
100+ for _ , tt := range tests {
101+ t .Run (tt . input , func (t * testing.T ) {
102+ q := qrb .N (tt . input )
48103
49- _ , _ , err := qrb .Build (q ).ToSQL ()
50- require .Error (t , err )
104+ sql , _ , err := qrb .Build (q ).ToSQL ()
105+ if tt .expectInvalid {
106+ require .Error (t , err )
107+ } else {
108+ require .NoError (t , err )
109+ assert .Equal (t , tt .expected , sql )
110+ }
51111 })
52112 }
53113}
0 commit comments