Skip to content

Commit a35ed29

Browse files
committed
Supported some more YQL constructions:
USE ... PRAGMA CREATE USER CREATE GROUP COMMIT RESTORE also added some new tests and debugged old code for mistakes
1 parent 4269e8c commit a35ed29

18 files changed

+1266
-28
lines changed

internal/codegen/golang/ydb_type.go

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -49,7 +49,7 @@ func YDBType(req *plugin.GenerateRequest, options *opts.Options, col *plugin.Col
4949
}
5050
// return "sql.NullInt16"
5151
return "*int16"
52-
case "int32":
52+
case "int", "int32": //ydb doesn't have int type, but we need it to support untyped constants
5353
if notNull {
5454
return "int32"
5555
}
@@ -155,9 +155,12 @@ func YDBType(req *plugin.GenerateRequest, options *opts.Options, col *plugin.Col
155155
// return "sql.Null"
156156
return "interface{}"
157157

158+
case "any":
159+
return "interface{}"
160+
158161
default:
159162
if debug.Active {
160-
log.Printf("unknown SQLite type: %s\n", columnType)
163+
log.Printf("unknown YDB type: %s\n", columnType)
161164
}
162165

163166
return "interface{}"
Lines changed: 110 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,110 @@
1+
package ydb_test
2+
3+
import (
4+
"strings"
5+
"testing"
6+
7+
"github.com/google/go-cmp/cmp"
8+
"github.com/google/go-cmp/cmp/cmpopts"
9+
"github.com/sqlc-dev/sqlc/internal/engine/ydb"
10+
"github.com/sqlc-dev/sqlc/internal/sql/ast"
11+
)
12+
13+
func TestCreateGroup(t *testing.T) {
14+
tests := []struct {
15+
stmt string
16+
expected ast.Node
17+
}{
18+
{
19+
stmt: `CREATE GROUP group1`,
20+
expected: &ast.Statement{
21+
Raw: &ast.RawStmt{
22+
Stmt: &ast.CreateRoleStmt{
23+
StmtType: ast.RoleStmtType(3), // CREATE GROUP
24+
Role: strPtr("group1"),
25+
Options: &ast.List{},
26+
},
27+
},
28+
},
29+
},
30+
{
31+
stmt: `CREATE GROUP group1 WITH USER alice`,
32+
expected: &ast.Statement{
33+
Raw: &ast.RawStmt{
34+
Stmt: &ast.CreateRoleStmt{
35+
StmtType: ast.RoleStmtType(3),
36+
Role: strPtr("group1"),
37+
Options: &ast.List{
38+
Items: []ast.Node{
39+
&ast.DefElem{
40+
Defname: strPtr("rolemembers"),
41+
Arg: &ast.List{
42+
Items: []ast.Node{
43+
&ast.RoleSpec{
44+
Roletype: ast.RoleSpecType(1),
45+
Rolename: strPtr("alice"),
46+
},
47+
},
48+
},
49+
},
50+
},
51+
},
52+
},
53+
},
54+
},
55+
},
56+
{
57+
stmt: `CREATE GROUP group1 WITH USER alice, bebik`,
58+
expected: &ast.Statement{
59+
Raw: &ast.RawStmt{
60+
Stmt: &ast.CreateRoleStmt{
61+
StmtType: ast.RoleStmtType(3),
62+
Role: strPtr("group1"),
63+
Options: &ast.List{
64+
Items: []ast.Node{
65+
&ast.DefElem{
66+
Defname: strPtr("rolemembers"),
67+
Arg: &ast.List{
68+
Items: []ast.Node{
69+
&ast.RoleSpec{
70+
Roletype: ast.RoleSpecType(1),
71+
Rolename: strPtr("alice"),
72+
},
73+
&ast.RoleSpec{
74+
Roletype: ast.RoleSpecType(1),
75+
Rolename: strPtr("bebik"),
76+
},
77+
},
78+
},
79+
},
80+
},
81+
},
82+
},
83+
},
84+
},
85+
},
86+
}
87+
88+
p := ydb.NewParser()
89+
for _, tc := range tests {
90+
t.Run(tc.stmt, func(t *testing.T) {
91+
stmts, err := p.Parse(strings.NewReader(tc.stmt))
92+
if err != nil {
93+
t.Fatalf("Ошибка парсинга запроса %q: %v", tc.stmt, err)
94+
}
95+
if len(stmts) == 0 {
96+
t.Fatalf("Запрос %q не распарсен", tc.stmt)
97+
}
98+
99+
diff := cmp.Diff(tc.expected, &stmts[0],
100+
cmpopts.IgnoreFields(ast.RawStmt{}, "StmtLocation", "StmtLen"),
101+
cmpopts.IgnoreFields(ast.DefElem{}, "Location"),
102+
cmpopts.IgnoreFields(ast.RoleSpec{}, "Location"),
103+
cmpopts.IgnoreFields(ast.A_Const{}, "Location"),
104+
)
105+
if diff != "" {
106+
t.Errorf("Несовпадение AST (-ожидалось +получено):\n%s", diff)
107+
}
108+
})
109+
}
110+
}
Lines changed: 129 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,129 @@
1+
package ydb_test
2+
3+
import (
4+
"strings"
5+
"testing"
6+
7+
"github.com/google/go-cmp/cmp"
8+
"github.com/google/go-cmp/cmp/cmpopts"
9+
"github.com/sqlc-dev/sqlc/internal/engine/ydb"
10+
"github.com/sqlc-dev/sqlc/internal/sql/ast"
11+
)
12+
13+
func TestCreateUser(t *testing.T) {
14+
tests := []struct {
15+
stmt string
16+
expected ast.Node
17+
}{
18+
{
19+
stmt: `CREATE USER alice`,
20+
expected: &ast.Statement{
21+
Raw: &ast.RawStmt{
22+
Stmt: &ast.CreateRoleStmt{
23+
StmtType: ast.RoleStmtType(2), // CREATE USER
24+
Role: strPtr("alice"),
25+
Options: &ast.List{},
26+
},
27+
},
28+
},
29+
},
30+
{
31+
stmt: `CREATE USER bob PASSWORD 'secret'`,
32+
expected: &ast.Statement{
33+
Raw: &ast.RawStmt{
34+
Stmt: &ast.CreateRoleStmt{
35+
StmtType: ast.RoleStmtType(2),
36+
Role: strPtr("bob"),
37+
Options: &ast.List{
38+
Items: []ast.Node{
39+
&ast.DefElem{
40+
Defname: strPtr("password"),
41+
Arg: &ast.String{Str: "secret"},
42+
},
43+
},
44+
},
45+
},
46+
},
47+
},
48+
},
49+
{
50+
stmt: `CREATE USER charlie LOGIN`,
51+
expected: &ast.Statement{
52+
Raw: &ast.RawStmt{
53+
Stmt: &ast.CreateRoleStmt{
54+
StmtType: ast.RoleStmtType(2),
55+
Role: strPtr("charlie"),
56+
Options: &ast.List{
57+
Items: []ast.Node{
58+
&ast.DefElem{
59+
Defname: strPtr("login"),
60+
Arg: &ast.Boolean{Boolval: true},
61+
},
62+
},
63+
},
64+
},
65+
},
66+
},
67+
},
68+
{
69+
stmt: `CREATE USER dave NOLOGIN`,
70+
expected: &ast.Statement{
71+
Raw: &ast.RawStmt{
72+
Stmt: &ast.CreateRoleStmt{
73+
StmtType: ast.RoleStmtType(2),
74+
Role: strPtr("dave"),
75+
Options: &ast.List{
76+
Items: []ast.Node{
77+
&ast.DefElem{
78+
Defname: strPtr("nologin"),
79+
Arg: &ast.Boolean{Boolval: false},
80+
},
81+
},
82+
},
83+
},
84+
},
85+
},
86+
},
87+
{
88+
stmt: `CREATE USER bjorn HASH 'abc123'`,
89+
expected: &ast.Statement{
90+
Raw: &ast.RawStmt{
91+
Stmt: &ast.CreateRoleStmt{
92+
StmtType: ast.RoleStmtType(2),
93+
Role: strPtr("bjorn"),
94+
Options: &ast.List{
95+
Items: []ast.Node{
96+
&ast.DefElem{
97+
Defname: strPtr("hash"),
98+
Arg: &ast.String{Str: "abc123"},
99+
},
100+
},
101+
},
102+
},
103+
},
104+
},
105+
},
106+
}
107+
108+
p := ydb.NewParser()
109+
for _, tc := range tests {
110+
t.Run(tc.stmt, func(t *testing.T) {
111+
stmts, err := p.Parse(strings.NewReader(tc.stmt))
112+
if err != nil {
113+
t.Fatalf("Ошибка парсинга запроса %q: %v", tc.stmt, err)
114+
}
115+
if len(stmts) == 0 {
116+
t.Fatalf("Запрос %q не распарсен", tc.stmt)
117+
}
118+
119+
diff := cmp.Diff(tc.expected, &stmts[0],
120+
cmpopts.IgnoreFields(ast.RawStmt{}, "StmtLocation", "StmtLen"),
121+
cmpopts.IgnoreFields(ast.A_Const{}, "Location"),
122+
cmpopts.IgnoreFields(ast.DefElem{}, "Location"),
123+
)
124+
if diff != "" {
125+
t.Errorf("Несовпадение AST (-ожидалось +получено):\n%s", diff)
126+
}
127+
})
128+
}
129+
}

0 commit comments

Comments
 (0)