]> granicus.if.org Git - postgresql/commitdiff
Kris Jurka pointed out that the qualified_name production wasn't
authorTom Lane <tgl@sss.pgh.pa.us>
Mon, 8 Nov 2004 04:02:20 +0000 (04:02 +0000)
committerTom Lane <tgl@sss.pgh.pa.us>
Mon, 8 Nov 2004 04:02:20 +0000 (04:02 +0000)
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.

src/backend/parser/gram.y

index 12c1acac4d8d7c583f43030a33b7df358206de52..f4d99486d3d7dab14a7791a5e29bc5fcddadcf25 100644 (file)
@@ -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