1111 *
1212 *
1313 * IDENTIFICATION
14- * $PostgreSQL: pgsql/src/backend/parser/gram.y,v 2.479 2004/11/05 19:16:02 tgl Exp $
14+ * $PostgreSQL: pgsql/src/backend/parser/gram.y,v 2.480 2004/11/08 04:02:20 tgl Exp $
1515 *
1616 * HISTORY
1717 * AUTHORDATEMAJOR EVENT
@@ -82,6 +82,7 @@ static Node *makeRowNullTest(NullTestType test, RowExpr *row);
8282static DefElem *makeDefElem (char *name, Node *arg);
8383static A_Const *makeBoolAConst (bool state);
8484static FuncCall *makeOverlaps (List *largs, List *rargs);
85+ static void check_qualified_name (List *names);
8586static List *check_func_name (List *names);
8687static List *extractArgTypes (List *parameters);
8788static SelectStmt *findLeftmostSelect (SelectStmt *node);
@@ -2670,14 +2671,10 @@ any_name:ColId{ $$ = list_make1(makeString($1)); }
26702671| ColId attrs{$$ = lcons(makeString($1 ),$2 ); }
26712672;
26722673
2673- /*
2674- * The slightly convoluted way of writing this production avoids reduce/reduce
2675- * errors against indirection_el.
2676- */
26772674attrs:' .' attr_name
26782675{$$ = list_make1(makeString($2 )); }
2679- |' .' attr_name attrs
2680- {$$ =lcons(makeString( $2 ), $3 ); }
2676+ |attrs ' .' attr_name
2677+ {$$ =lappend( $1 , makeString( $3 ) ); }
26812678;
26822679
26832680
@@ -7391,6 +7388,13 @@ qualified_name_list:
73917388| qualified_name_list' ,' qualified_name {$$ = lappend($1 ,$3 ); }
73927389;
73937390
7391+ /*
7392+ * The production for a qualified relation name has to exactly match the
7393+ * production for a qualified func_name, because in a FROM clause we cannot
7394+ * tell which we are parsing until we see what comes after it ('(' for a
7395+ * func_name, something else for a relation). Therefore we allow 'indirection'
7396+ * which may contain subscripts, and reject that case in the C code.
7397+ */
73947398qualified_name:
73957399relation_name
73967400{
@@ -7399,8 +7403,9 @@ qualified_name:
73997403$$ ->schemaname =NULL ;
74007404$$ ->relname =$1 ;
74017405}
7402- | relation_nameattrs
7406+ | relation_nameindirection
74037407{
7408+ check_qualified_name ($2 );
74047409$$ = makeNode(RangeVar);
74057410switch (list_length($2 ))
74067411{
@@ -8200,6 +8205,25 @@ makeOverlaps(List *largs, List *rargs)
82008205return n;
82018206}
82028207
8208+ /* check_qualified_name --- check the result of qualified_name production
8209+ *
8210+ * It's easiest to let the grammar production for qualified_name allow
8211+ * subscripts and '*', which we then must reject here.
8212+ */
8213+ static void
8214+ check_qualified_name(List *names)
8215+ {
8216+ ListCell *i;
8217+
8218+ foreach(i, names)
8219+ {
8220+ if (!IsA(lfirst(i), String))
8221+ yyerror("syntax error");
8222+ else if (strcmp(strVal(lfirst(i)), "*") == 0)
8223+ yyerror("syntax error");
8224+ }
8225+ }
8226+
82038227/* check_func_name --- check the result of func_name production
82048228 *
82058229 * It's easiest to let the grammar production for func_name allow subscripts