diff --git a/src/backend/parser/gram.y b/src/backend/parser/gram.y index 12c1acac4d..f4d99486d3 100644 --- a/src/backend/parser/gram.y +++ b/src/backend/parser/gram.y @@ -11,7 +11,7 @@ * * * 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 * AUTHOR DATE MAJOR EVENT @@ -82,6 +82,7 @@ static Node *makeRowNullTest(NullTestType test, RowExpr *row); static DefElem *makeDefElem(char *name, Node *arg); static A_Const *makeBoolAConst(bool state); static FuncCall *makeOverlaps(List *largs, List *rargs); +static void check_qualified_name(List *names); static List *check_func_name(List *names); static List *extractArgTypes(List *parameters); static SelectStmt *findLeftmostSelect(SelectStmt *node); @@ -2670,14 +2671,10 @@ any_name: ColId { $$ = list_make1(makeString($1)); } | ColId attrs { $$ = lcons(makeString($1), $2); } ; -/* - * The slightly convoluted way of writing this production avoids reduce/reduce - * errors against indirection_el. - */ attrs: '.' attr_name { $$ = list_make1(makeString($2)); } - | '.' attr_name attrs - { $$ = lcons(makeString($2), $3); } + | attrs '.' attr_name + { $$ = lappend($1, makeString($3)); } ; @@ -7391,6 +7388,13 @@ qualified_name_list: | 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: relation_name { @@ -7399,8 +7403,9 @@ qualified_name: $$->schemaname = NULL; $$->relname = $1; } - | relation_name attrs + | relation_name indirection { + check_qualified_name($2); $$ = makeNode(RangeVar); switch (list_length($2)) { @@ -8200,6 +8205,25 @@ makeOverlaps(List *largs, List *rargs) 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 * * It's easiest to let the grammar production for func_name allow subscripts