Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
67 changes: 67 additions & 0 deletions go/vt/sqlparser/ast.go
Original file line number Diff line number Diff line change
Expand Up @@ -404,6 +404,9 @@ func (*Declare) iStatement() {}
func (*OpenCursor) iStatement() {}
func (*CloseCursor) iStatement() {}
func (*FetchCursor) iStatement() {}
func (*Loop) iStatement() {}
func (*Leave) iStatement() {}
func (*Iterate) iStatement() {}
func (*Call) iStatement() {}
func (*Load) iStatement() {}
func (*Savepoint) iStatement() {}
Expand Down Expand Up @@ -1203,6 +1206,70 @@ func (oc *FetchCursor) walkSubtree(visit Visit) error {
return nil
}

// Loop represents the LOOP statement
type Loop struct {
Label string
Statements Statements
}

// Format implements the interface SQLNode.
func (l *Loop) Format(buf *TrackedBuffer) {
beginLabel := ""
endLabel := ""
if len(l.Label) > 0 {
beginLabel = fmt.Sprintf("%s: ", l.Label)
endLabel = fmt.Sprintf(" %s", l.Label)
}
buf.Myprintf("%sloop\n", beginLabel)
for _, s := range l.Statements {
buf.Myprintf("%v;\n", s)
}
buf.Myprintf("end loop%s", endLabel)
}

// walkSubtree implements the interface WalkableSQLNode.
func (l *Loop) walkSubtree(visit Visit) error {
if l == nil {
return nil
}
for _, s := range l.Statements {
if err := Walk(visit, s); err != nil {
return err
}
}
return nil
}

// Leave represents the LEAVE statement
type Leave struct {
Label string
}

// Format implements the interface SQLNode.
func (l *Leave) Format(buf *TrackedBuffer) {
buf.Myprintf("leave %s", l.Label)
}

// walkSubtree implements the interface WalkableSQLNode.
func (l *Leave) walkSubtree(visit Visit) error {
return nil
}

// Iterate represents the ITERATE statement
type Iterate struct {
Label string
}

// Format implements the interface SQLNode.
func (i *Iterate) Format(buf *TrackedBuffer) {
buf.Myprintf("iterate %s", i.Label)
}

// walkSubtree implements the interface WalkableSQLNode.
func (i *Iterate) walkSubtree(visit Visit) error {
return nil
}

// Signal represents the SIGNAL statement
type Signal struct {
ConditionName string // Previously declared condition name
Expand Down
63 changes: 63 additions & 0 deletions go/vt/sqlparser/parse_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -2904,6 +2904,69 @@ else insert into test.t3 values (a, c);
end if;
close cur1;
close cur2;
end`,
},
{
input: `CREATE PROCEDURE testproc() BEGIN
DECLARE done INT DEFAULT FALSE;
DECLARE a CHAR(16);
DECLARE b INT;
DECLARE cur1 CURSOR FOR SELECT id, data FROM test.t1;
DECLARE CONTINUE HANDLER FOR NOT FOUND SET done = TRUE;

OPEN cur1;

read_loop : LOOP
FETCH cur1 INTO a, b;
IF done THEN
LEAVE read_loop;
END IF;
IF a < b THEN
INSERT INTO test.t3 VALUES (a,b);
ELSE
ITERATE read_loop;
END IF;
END LOOP;

BEGIN
DECLARE EXIT HANDLER FOR NOT FOUND BEGIN END;
LOOP
FETCH cur1 INTO a, b;
END LOOP;
END;

empty_loop: LOOP
LEAVE empty_loop;
END LOOP empty_loop;

CLOSE cur1;
END`,
output: `create procedure testproc () begin
declare done INT default false;
declare a CHAR(16);
declare b INT;
declare cur1 cursor for select id, `+"`data`"+` from test.t1;
declare continue handler for not found set done = true;
open cur1;
read_loop: loop
fetch cur1 into a, b;
if done then leave read_loop;
end if;
if a < b then insert into test.t3 values (a, b);
else iterate read_loop;
end if;
end loop read_loop;
begin
declare exit handler for not found begin
end;
loop
fetch cur1 into a, b;
end loop;
end;
empty_loop: loop
leave empty_loop;
end loop empty_loop;
close cur1;
end`,
},
}
Expand Down
Loading