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.
This commit is contained in:
Tom Lane 2012-10-04 17:14:59 -04:00
parent 7e389f73d1
commit 707263542e
2 changed files with 31 additions and 7 deletions

View File

@ -67,15 +67,33 @@
#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) \
do { \
if (N) \
if ((N) > 0) \
(Current) = (Rhs)[1]; \
else \
(Current) = (Rhs)[0]; \
(Current) = (-1); \
} 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,
* so we can easily have it use palloc instead of malloc. This prevents
@ -1223,8 +1241,14 @@ OptSchemaName:
;
OptSchemaEltList:
OptSchemaEltList schema_stmt { $$ = lappend($1, $2); }
| /* EMPTY */ { $$ = NIL; }
OptSchemaEltList schema_stmt
{
if (@$ < 0) /* see comments for YYLLOC_DEFAULT */
@$ = @2;
$$ = lappend($1, $2);
}
| /* EMPTY */
{ $$ = NIL; }
;
/*

View File

@ -47,8 +47,8 @@ CREATE SCHEMA IF NOT EXISTS test_schema_1 -- fail, disallowed
b int UNIQUE
);
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;
NOTICE: drop cascades to 2 other objects
DETAIL: drop cascades to table test_schema_1.abc