summaryrefslogtreecommitdiff
path: root/src/test
diff options
context:
space:
mode:
authorTom Lane2015-08-22 00:17:19 +0000
committerTom Lane2015-08-22 00:17:19 +0000
commitfcdfce6820373422bcdb5630f9eb63df14fd0764 (patch)
treebd95391239fe0156fde6886309486ee44cf7c649 /src/test
parent072710dff3eef4540f1c64d07890eb128535e212 (diff)
Detect mismatched CONTINUE and EXIT statements at plpgsql compile time.
With a bit of tweaking of the compile namestack data structure, we can verify at compile time whether a CONTINUE or EXIT is legal. This is surely better than leaving it to runtime, both because earlier is better and because we can issue a proper error pointer. Also, we can get rid of the ad-hoc old way of detecting the problem, which only took care of CONTINUE not EXIT. Jim Nasby, adjusted a bit by me
Diffstat (limited to 'src/test')
-rw-r--r--src/test/regress/expected/plpgsql.out85
-rw-r--r--src/test/regress/sql/plpgsql.sql64
2 files changed, 119 insertions, 30 deletions
diff --git a/src/test/regress/expected/plpgsql.out b/src/test/regress/expected/plpgsql.out
index 452ef9d836d..b10157bb170 100644
--- a/src/test/regress/expected/plpgsql.out
+++ b/src/test/regress/expected/plpgsql.out
@@ -2830,21 +2830,58 @@ NOTICE: 10
(1 row)
--- CONTINUE is only legal inside a loop
-create function continue_test2() returns void as $$
+drop function continue_test1();
+drop table conttesttbl;
+-- should fail: CONTINUE is only legal inside a loop
+create function continue_error1() returns void as $$
begin
begin
continue;
end;
- return;
end;
$$ language plpgsql;
--- should fail
-select continue_test2();
ERROR: CONTINUE cannot be used outside a loop
-CONTEXT: PL/pgSQL function continue_test2()
--- CONTINUE can't reference the label of a named block
-create function continue_test3() returns void as $$
+LINE 4: continue;
+ ^
+-- should fail: EXIT is only legal inside a loop
+create function exit_error1() returns void as $$
+begin
+ begin
+ exit;
+ end;
+end;
+$$ language plpgsql;
+ERROR: EXIT cannot be used outside a loop
+LINE 4: exit;
+ ^
+-- should fail: no such label
+create function continue_error2() returns void as $$
+begin
+ begin
+ loop
+ continue no_such_label;
+ end loop;
+ end;
+end;
+$$ language plpgsql;
+ERROR: label "no_such_label" does not exist
+LINE 5: continue no_such_label;
+ ^
+-- should fail: no such label
+create function exit_error2() returns void as $$
+begin
+ begin
+ loop
+ exit no_such_label;
+ end loop;
+ end;
+end;
+$$ language plpgsql;
+ERROR: label "no_such_label" does not exist
+LINE 5: exit no_such_label;
+ ^
+-- should fail: CONTINUE can't reference the label of a named block
+create function continue_error3() returns void as $$
begin
<<begin_block1>>
begin
@@ -2854,14 +2891,28 @@ begin
end;
end;
$$ language plpgsql;
--- should fail
-select continue_test3();
-ERROR: CONTINUE cannot be used outside a loop
-CONTEXT: PL/pgSQL function continue_test3()
-drop function continue_test1();
-drop function continue_test2();
-drop function continue_test3();
-drop table conttesttbl;
+ERROR: block label "begin_block1" cannot be used in CONTINUE
+LINE 6: continue begin_block1;
+ ^
+-- On the other hand, EXIT *can* reference the label of a named block
+create function exit_block1() returns void as $$
+begin
+ <<begin_block1>>
+ begin
+ loop
+ exit begin_block1;
+ raise exception 'should not get here';
+ end loop;
+ end;
+end;
+$$ language plpgsql;
+select exit_block1();
+ exit_block1
+-------------
+
+(1 row)
+
+drop function exit_block1();
-- verbose end block and end loop
create function end_label1() returns void as $$
<<blbl>>
@@ -2891,7 +2942,7 @@ begin
end loop flbl1;
end;
$$ language plpgsql;
-ERROR: label does not exist at or near "flbl1"
+ERROR: end label "flbl1" specified for unlabelled block
LINE 5: end loop flbl1;
^
-- should fail: end label does not match start label
diff --git a/src/test/regress/sql/plpgsql.sql b/src/test/regress/sql/plpgsql.sql
index b46439ee709..7b4191ecf97 100644
--- a/src/test/regress/sql/plpgsql.sql
+++ b/src/test/regress/sql/plpgsql.sql
@@ -2361,21 +2361,51 @@ end; $$ language plpgsql;
select continue_test1();
--- CONTINUE is only legal inside a loop
-create function continue_test2() returns void as $$
+drop function continue_test1();
+drop table conttesttbl;
+
+-- should fail: CONTINUE is only legal inside a loop
+create function continue_error1() returns void as $$
begin
begin
continue;
end;
- return;
end;
$$ language plpgsql;
--- should fail
-select continue_test2();
+-- should fail: EXIT is only legal inside a loop
+create function exit_error1() returns void as $$
+begin
+ begin
+ exit;
+ end;
+end;
+$$ language plpgsql;
+
+-- should fail: no such label
+create function continue_error2() returns void as $$
+begin
+ begin
+ loop
+ continue no_such_label;
+ end loop;
+ end;
+end;
+$$ language plpgsql;
+
+-- should fail: no such label
+create function exit_error2() returns void as $$
+begin
+ begin
+ loop
+ exit no_such_label;
+ end loop;
+ end;
+end;
+$$ language plpgsql;
--- CONTINUE can't reference the label of a named block
-create function continue_test3() returns void as $$
+-- should fail: CONTINUE can't reference the label of a named block
+create function continue_error3() returns void as $$
begin
<<begin_block1>>
begin
@@ -2386,13 +2416,21 @@ begin
end;
$$ language plpgsql;
--- should fail
-select continue_test3();
+-- On the other hand, EXIT *can* reference the label of a named block
+create function exit_block1() returns void as $$
+begin
+ <<begin_block1>>
+ begin
+ loop
+ exit begin_block1;
+ raise exception 'should not get here';
+ end loop;
+ end;
+end;
+$$ language plpgsql;
-drop function continue_test1();
-drop function continue_test2();
-drop function continue_test3();
-drop table conttesttbl;
+select exit_block1();
+drop function exit_block1();
-- verbose end block and end loop
create function end_label1() returns void as $$