Commit 70726354 authored by Tom Lane's avatar Tom Lane

Fix parse location tracking for lists that can be empty.

The previous coding of the YYLLOC_DEFAULT macro behaved strangely for empty
productions, assigning the previous nonterminal's location as the parse
location of the result.  The usefulness of that was (at best) debatable
already, but the real problem is that in list-generating nonterminals like
	OptFooList: /* EMPTY */ { ... } | OptFooList Foo { ... } ;
the initially-identified location would get copied up, so that even a
nonempty list would be given a bogus parse location.  Document how to work
around that, and do so for OptSchemaEltList, so that the error condition
just added for CREATE SCHEMA IF NOT EXISTS produces a sane error cursor.
So far as I can tell, there are currently no other cases where the
situation arises, so we don't need other instances of this coding yet.
parent 7e389f73
...@@ -67,15 +67,33 @@ ...@@ -67,15 +67,33 @@
#include "utils/xml.h" #include "utils/xml.h"
/* Location tracking support --- simpler than bison's default */ /*
* Location tracking support --- simpler than bison's default, since we only
* want to track the start position not the end position of each nonterminal.
*/
#define YYLLOC_DEFAULT(Current, Rhs, N) \ #define YYLLOC_DEFAULT(Current, Rhs, N) \
do { \ do { \
if (N) \ if ((N) > 0) \
(Current) = (Rhs)[1]; \ (Current) = (Rhs)[1]; \
else \ else \
(Current) = (Rhs)[0]; \ (Current) = (-1); \
} while (0) } while (0)
/*
* The above macro assigns -1 (unknown) as the parse location of any
* nonterminal that was reduced from an empty rule. This is problematic
* for nonterminals defined like
* OptFooList: / * EMPTY * / { ... } | OptFooList Foo { ... } ;
* because we'll set -1 as the location during the first reduction and then
* copy it during each subsequent reduction, leaving us with -1 for the
* location even when the list is not empty. To fix that, do this in the
* action for the nonempty rule(s):
* if (@$ < 0) @$ = @2;
* (Although we have many nonterminals that follow this pattern, we only
* bother with fixing @$ like this when the nonterminal's parse location
* is actually referenced in some rule.)
*/
/* /*
* Bison doesn't allocate anything that needs to live across parser calls, * Bison doesn't allocate anything that needs to live across parser calls,
* so we can easily have it use palloc instead of malloc. This prevents * so we can easily have it use palloc instead of malloc. This prevents
...@@ -1223,8 +1241,14 @@ OptSchemaName: ...@@ -1223,8 +1241,14 @@ OptSchemaName:
; ;
OptSchemaEltList: OptSchemaEltList:
OptSchemaEltList schema_stmt { $$ = lappend($1, $2); } OptSchemaEltList schema_stmt
| /* EMPTY */ { $$ = NIL; } {
if (@$ < 0) /* see comments for YYLLOC_DEFAULT */
@$ = @2;
$$ = lappend($1, $2);
}
| /* EMPTY */
{ $$ = NIL; }
; ;
/* /*
......
...@@ -47,8 +47,8 @@ CREATE SCHEMA IF NOT EXISTS test_schema_1 -- fail, disallowed ...@@ -47,8 +47,8 @@ CREATE SCHEMA IF NOT EXISTS test_schema_1 -- fail, disallowed
b int UNIQUE b int UNIQUE
); );
ERROR: CREATE SCHEMA IF NOT EXISTS cannot include schema elements ERROR: CREATE SCHEMA IF NOT EXISTS cannot include schema elements
LINE 1: CREATE SCHEMA IF NOT EXISTS test_schema_1 LINE 2: CREATE TABLE abc (
^ ^
DROP SCHEMA test_schema_1 CASCADE; DROP SCHEMA test_schema_1 CASCADE;
NOTICE: drop cascades to 2 other objects NOTICE: drop cascades to 2 other objects
DETAIL: drop cascades to table test_schema_1.abc DETAIL: drop cascades to table test_schema_1.abc
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment