Skip to content

Commit

Permalink
support declare cursor
Browse files Browse the repository at this point in the history
  • Loading branch information
Takaya Yamazoe committed Aug 3, 2021
1 parent c88e36d commit 757c233
Show file tree
Hide file tree
Showing 5 changed files with 3,666 additions and 3,475 deletions.
47 changes: 38 additions & 9 deletions cmd/mssqldef/mssqldef_test.go
Expand Up @@ -194,8 +194,6 @@ func TestMssqldefTrigger(t *testing.T) {

createTrigger := stripHeredoc(`
CREATE TRIGGER [insert_log] ON [dbo].[users] after insert AS
declare
@event varchar(20)
insert into logs(log, dt) values ('insert', getdate());
`,
)
Expand All @@ -204,23 +202,54 @@ func TestMssqldefTrigger(t *testing.T) {

createTrigger = stripHeredoc(`
CREATE TRIGGER [insert_log] ON [dbo].[users] after insert AS
declare
@event varchar(20),
@log varchar(20)
insert into logs(log, dt) values ('insert', getdate())
delete from logs
insert into logs(log, dt) values ('insert', getdate());
`,
)

assertApplyOutput(t, createTable+createTrigger, applyPrefix+
"CREATE OR ALTER TRIGGER [insert_log] ON [dbo].[users] after insert AS\n"+
"declare\n"+
"@event varchar(20),\n"+
"@log varchar(20)\n"+
"delete from logs\n"+
"insert into logs(log, dt) values ('insert', getdate());\n",
)
assertApplyOutput(t, createTable+createTrigger, nothingModified)
}

func TestMssqldefTriggerWithRichSyntax(t *testing.T) {
resetTestDatabase()

createTable := stripHeredoc(`
CREATE TABLE users (
id bigint NOT NULL,
name text
);
CREATE TABLE logs (
id bigint NOT NULL,
log varchar(20),
dt datetime
);
`,
)
assertApplyOutput(t, createTable, applyPrefix+createTable)
assertApplyOutput(t, createTable, nothingModified)

createTrigger := stripHeredoc(`
CREATE TRIGGER [insert_log] ON [dbo].[users] after insert AS
declare
@event varchar(20),
@date datetime
set @event = 'insert_user'
set @date = getdate()
declare
users_cursor scroll cursor for
select name from users order by id asc
insert into logs(log, dt) values (@event, @date);
`,
)
assertApplyOutput(t, createTable+createTrigger, applyPrefix+createTrigger)
assertApplyOutput(t, createTable+createTrigger, nothingModified)
}

func TestMssqldefAddColumn(t *testing.T) {
resetTestDatabase()

Expand Down
64 changes: 55 additions & 9 deletions sqlparser/ast.go
Expand Up @@ -3456,38 +3456,59 @@ func (node ColIdent) walkSubtree(visit Visit) error {
return nil
}

type DeclareType int

const (
declareVariable DeclareType = iota
declareCursor
)

type Declare struct {
Definitions []*DeclareDefinition
Type DeclareType
Variables []*LocalVariable
Cursor *Cursor
}

func (node *Declare) Format(buf *TrackedBuffer) {
var prefix string
buf.Myprintf("declare\n")
for _, n := range node.Definitions {
buf.Myprintf("%s%v", prefix, n)
prefix = ",\n"
switch node.Type {
case declareVariable:
for _, n := range node.Variables {
buf.Myprintf("%s%v", prefix, n)
prefix = ",\n"
}
case declareCursor:
buf.Myprintf("%v", node.Cursor)
}
}

func (node *Declare) walkSubtree(visit Visit) error {
for _, n := range node.Definitions {
if err := Walk(visit, n); err != nil {
switch node.Type {
case declareVariable:
for _, n := range node.Variables {
if err := Walk(visit, n); err != nil {
return err
}
}
case declareCursor:
if err := Walk(visit, node.Cursor); err != nil {
return err
}
}
return nil
}

type DeclareDefinition struct {
type LocalVariable struct {
Name ColIdent
DataType ColumnType
}

func (node *DeclareDefinition) Format(buf *TrackedBuffer) {
func (node *LocalVariable) Format(buf *TrackedBuffer) {
buf.Myprintf("%v %v", node.Name, &node.DataType)
}

func (node *DeclareDefinition) walkSubtree(visit Visit) error {
func (node *LocalVariable) walkSubtree(visit Visit) error {
if node == nil {
return nil
}
Expand All @@ -3498,6 +3519,31 @@ func (node *DeclareDefinition) walkSubtree(visit Visit) error {
)
}

type Cursor struct {
Name ColIdent
Scroll bool
Select SelectStatement
}

func (node *Cursor) Format(buf *TrackedBuffer) {
var scrollStr string
if node.Scroll {
scrollStr = " scroll"
}
buf.Myprintf("%v%s cursor for\n%v", node.Name, scrollStr, node.Select)
}

func (node *Cursor) walkSubtree(visit Visit) error {
if node == nil {
return nil
}
return Walk(
visit,
node.Name,
node.Select.(*Select),
)
}

// IsEmpty returns true if the name is empty.
func (node ColIdent) IsEmpty() bool {
return node.val == ""
Expand Down

0 comments on commit 757c233

Please sign in to comment.