Skip to content

Commit 00df4f6

Browse files
authored
ast: Add support for CREATE / DROP SCHEMA (#389)
1 parent 96be689 commit 00df4f6

File tree

5 files changed

+91
-8
lines changed

5 files changed

+91
-8
lines changed

Makefile

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
build:
2-
go build ./...
2+
go build --tags=exp ./...
33

44
test:
55
go test --tags=exp ./...

internal/endtoend/testdata/experimental_elephant/query.sql

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -14,10 +14,13 @@ DROP TABLE bar;
1414
DROP TABLE IF EXISTS bar;
1515
DROP TABLE IF EXISTS baz;
1616

17-
1817
CREATE TABLE baz (name text);
1918
ALTER TABLE baz ADD COLUMN email text;
2019
ALTER TABLE baz ADD COLUMN bar text;
2120
ALTER TABLE baz DROP COLUMN IF EXISTS foo;
2221
ALTER TABLE baz DROP COLUMN bar;
2322
ALTER TABLE baz DROP COLUMN IF EXISTS bar;
23+
24+
CREATE SCHEMA baz;
25+
CREATE TABLE baz.foo ();
26+
DROP SCHEMA baz;

internal/postgresql/parse.go

Lines changed: 29 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -223,20 +223,43 @@ func translate(node nodes.Node) (ast.Node, error) {
223223
}
224224
return stmt, nil
225225

226+
case nodes.CreateSchemaStmt:
227+
return &ast.CreateSchemaStmt{
228+
Name: n.Schemaname,
229+
IfNotExists: n.IfNotExists,
230+
}, nil
231+
226232
case nodes.DropStmt:
227-
drop := &ast.DropTableStmt{
228-
IfExists: n.MissingOk,
229-
}
230-
for _, obj := range n.Objects.Items {
231-
if n.RemoveType == nodes.OBJECT_TABLE {
233+
switch n.RemoveType {
234+
235+
case nodes.OBJECT_SCHEMA:
236+
drop := &ast.DropSchemaStmt{
237+
MissingOk: n.MissingOk,
238+
}
239+
for _, obj := range n.Objects.Items {
240+
val, ok := obj.(nodes.String)
241+
if !ok {
242+
return nil, fmt.Errorf("nodes.DropStmt: unknown type in objects list: %T", obj)
243+
}
244+
drop.Schemas = append(drop.Schemas, &ast.String{Str: val.Str})
245+
}
246+
return drop, nil
247+
248+
case nodes.OBJECT_TABLE:
249+
drop := &ast.DropTableStmt{
250+
IfExists: n.MissingOk,
251+
}
252+
for _, obj := range n.Objects.Items {
232253
name, err := parseTableName(obj)
233254
if err != nil {
234255
return nil, err
235256
}
236257
drop.Tables = append(drop.Tables, name)
237258
}
259+
return drop, nil
260+
238261
}
239-
return drop, nil
262+
return nil, nil
240263

241264
default:
242265
return nil, nil

internal/sql/ast/ast.go

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -66,6 +66,15 @@ func (n *CreateEnumStmt) Pos() int {
6666
return 0
6767
}
6868

69+
type CreateSchemaStmt struct {
70+
Name *string
71+
IfNotExists bool
72+
}
73+
74+
func (n *CreateSchemaStmt) Pos() int {
75+
return 0
76+
}
77+
6978
type CreateTableStmt struct {
7079
IfNotExists bool
7180
Name *TableName
@@ -76,6 +85,15 @@ func (n *CreateTableStmt) Pos() int {
7685
return 0
7786
}
7887

88+
type DropSchemaStmt struct {
89+
Schemas []*String
90+
MissingOk bool
91+
}
92+
93+
func (n *DropSchemaStmt) Pos() int {
94+
return 0
95+
}
96+
7997
type DropTableStmt struct {
8098
IfExists bool
8199
Tables []*TableName

internal/sql/catalog/catalog.go

Lines changed: 39 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@ package catalog
22

33
import (
44
"errors"
5+
"fmt"
56

67
"github.com/kyleconroy/sqlc/internal/sql/ast"
78
)
@@ -23,8 +24,12 @@ func Build(stmts []ast.Statement) (*Catalog, error) {
2324
err = c.alterTable(n)
2425
case *ast.CreateEnumStmt:
2526
err = c.createEnum(n)
27+
case *ast.CreateSchemaStmt:
28+
err = c.createSchema(n)
2629
case *ast.CreateTableStmt:
2730
err = c.createTable(n)
31+
case *ast.DropSchemaStmt:
32+
err = c.dropSchema(n)
2833
case *ast.DropTableStmt:
2934
err = c.dropTable(n)
3035
}
@@ -203,6 +208,20 @@ func (c *Catalog) createEnum(stmt *ast.CreateEnumStmt) error {
203208
return nil
204209
}
205210

211+
func (c *Catalog) createSchema(stmt *ast.CreateSchemaStmt) error {
212+
if stmt.Name == nil {
213+
return fmt.Errorf("create schema: empty name")
214+
}
215+
if _, err := c.getSchema(*stmt.Name); err == nil {
216+
if !stmt.IfNotExists {
217+
// return wrap(pg.ErrorSchemaAlreadyExists(name), raw.StmtLocation)
218+
return ErrRelationAlreadyExists
219+
}
220+
}
221+
c.Schemas = append(c.Schemas, &Schema{Name: *stmt.Name})
222+
return nil
223+
}
224+
206225
func (c *Catalog) createTable(stmt *ast.CreateTableStmt) error {
207226
ns := stmt.Name.Schema
208227
if ns == "" {
@@ -231,6 +250,26 @@ func (c *Catalog) createTable(stmt *ast.CreateTableStmt) error {
231250
return nil
232251
}
233252

253+
func (c *Catalog) dropSchema(stmt *ast.DropSchemaStmt) error {
254+
// TODO: n^2 in the worst-case
255+
for _, name := range stmt.Schemas {
256+
idx := -1
257+
for i := range c.Schemas {
258+
if c.Schemas[i].Name == name.Str {
259+
idx = i
260+
}
261+
}
262+
if idx == -1 {
263+
if stmt.MissingOk {
264+
continue
265+
}
266+
return ErrSchemaNotFound
267+
}
268+
c.Schemas = append(c.Schemas[:idx], c.Schemas[idx+1:]...)
269+
}
270+
return nil
271+
}
272+
234273
func (c *Catalog) dropTable(stmt *ast.DropTableStmt) error {
235274
for _, name := range stmt.Tables {
236275
ns := name.Schema

0 commit comments

Comments
 (0)