mirror of
https://github.com/postgres/postgres.git
synced 2025-07-05 07:21:24 +03:00
Kris Jurka pointed out that the qualified_name production wasn't
working as intended --- for some reason, FROM a.b.c was getting parsed as if it were a function name and not a qualified name. I think there must be a bug in bison, because it should have complained that the grammar was ambiguous. Anyway, fix it along the same lines previously used for func_name vs columnref, and get rid of the right-recursion in attrs that seems to have confused bison.
This commit is contained in:
@ -11,7 +11,7 @@
|
|||||||
*
|
*
|
||||||
*
|
*
|
||||||
* IDENTIFICATION
|
* IDENTIFICATION
|
||||||
* $PostgreSQL: pgsql/src/backend/parser/gram.y,v 2.479 2004/11/05 19:16:02 tgl Exp $
|
* $PostgreSQL: pgsql/src/backend/parser/gram.y,v 2.480 2004/11/08 04:02:20 tgl Exp $
|
||||||
*
|
*
|
||||||
* HISTORY
|
* HISTORY
|
||||||
* AUTHOR DATE MAJOR EVENT
|
* AUTHOR DATE MAJOR EVENT
|
||||||
@ -82,6 +82,7 @@ static Node *makeRowNullTest(NullTestType test, RowExpr *row);
|
|||||||
static DefElem *makeDefElem(char *name, Node *arg);
|
static DefElem *makeDefElem(char *name, Node *arg);
|
||||||
static A_Const *makeBoolAConst(bool state);
|
static A_Const *makeBoolAConst(bool state);
|
||||||
static FuncCall *makeOverlaps(List *largs, List *rargs);
|
static FuncCall *makeOverlaps(List *largs, List *rargs);
|
||||||
|
static void check_qualified_name(List *names);
|
||||||
static List *check_func_name(List *names);
|
static List *check_func_name(List *names);
|
||||||
static List *extractArgTypes(List *parameters);
|
static List *extractArgTypes(List *parameters);
|
||||||
static SelectStmt *findLeftmostSelect(SelectStmt *node);
|
static SelectStmt *findLeftmostSelect(SelectStmt *node);
|
||||||
@ -2670,14 +2671,10 @@ any_name: ColId { $$ = list_make1(makeString($1)); }
|
|||||||
| ColId attrs { $$ = lcons(makeString($1), $2); }
|
| ColId attrs { $$ = lcons(makeString($1), $2); }
|
||||||
;
|
;
|
||||||
|
|
||||||
/*
|
|
||||||
* The slightly convoluted way of writing this production avoids reduce/reduce
|
|
||||||
* errors against indirection_el.
|
|
||||||
*/
|
|
||||||
attrs: '.' attr_name
|
attrs: '.' attr_name
|
||||||
{ $$ = list_make1(makeString($2)); }
|
{ $$ = list_make1(makeString($2)); }
|
||||||
| '.' attr_name attrs
|
| attrs '.' attr_name
|
||||||
{ $$ = lcons(makeString($2), $3); }
|
{ $$ = lappend($1, makeString($3)); }
|
||||||
;
|
;
|
||||||
|
|
||||||
|
|
||||||
@ -7391,6 +7388,13 @@ qualified_name_list:
|
|||||||
| qualified_name_list ',' qualified_name { $$ = lappend($1, $3); }
|
| qualified_name_list ',' qualified_name { $$ = lappend($1, $3); }
|
||||||
;
|
;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* The production for a qualified relation name has to exactly match the
|
||||||
|
* production for a qualified func_name, because in a FROM clause we cannot
|
||||||
|
* tell which we are parsing until we see what comes after it ('(' for a
|
||||||
|
* func_name, something else for a relation). Therefore we allow 'indirection'
|
||||||
|
* which may contain subscripts, and reject that case in the C code.
|
||||||
|
*/
|
||||||
qualified_name:
|
qualified_name:
|
||||||
relation_name
|
relation_name
|
||||||
{
|
{
|
||||||
@ -7399,8 +7403,9 @@ qualified_name:
|
|||||||
$$->schemaname = NULL;
|
$$->schemaname = NULL;
|
||||||
$$->relname = $1;
|
$$->relname = $1;
|
||||||
}
|
}
|
||||||
| relation_name attrs
|
| relation_name indirection
|
||||||
{
|
{
|
||||||
|
check_qualified_name($2);
|
||||||
$$ = makeNode(RangeVar);
|
$$ = makeNode(RangeVar);
|
||||||
switch (list_length($2))
|
switch (list_length($2))
|
||||||
{
|
{
|
||||||
@ -8200,6 +8205,25 @@ makeOverlaps(List *largs, List *rargs)
|
|||||||
return n;
|
return n;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* check_qualified_name --- check the result of qualified_name production
|
||||||
|
*
|
||||||
|
* It's easiest to let the grammar production for qualified_name allow
|
||||||
|
* subscripts and '*', which we then must reject here.
|
||||||
|
*/
|
||||||
|
static void
|
||||||
|
check_qualified_name(List *names)
|
||||||
|
{
|
||||||
|
ListCell *i;
|
||||||
|
|
||||||
|
foreach(i, names)
|
||||||
|
{
|
||||||
|
if (!IsA(lfirst(i), String))
|
||||||
|
yyerror("syntax error");
|
||||||
|
else if (strcmp(strVal(lfirst(i)), "*") == 0)
|
||||||
|
yyerror("syntax error");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/* check_func_name --- check the result of func_name production
|
/* check_func_name --- check the result of func_name production
|
||||||
*
|
*
|
||||||
* It's easiest to let the grammar production for func_name allow subscripts
|
* It's easiest to let the grammar production for func_name allow subscripts
|
||||||
|
Reference in New Issue
Block a user