Allow a_expr not just AexprConst in the right-hand list of
authorTom Lane
Wed, 28 Jul 1999 17:39:38 +0000 (17:39 +0000)
committerTom Lane
Wed, 28 Jul 1999 17:39:38 +0000 (17:39 +0000)
IN and NOT IN operators.  Rewrite grotty implementation of IN-list
parsing ... look Ma, no global variable ...

src/backend/parser/gram.y

index 60ff7a6ef259f266e7e10db93f41e244f3c04a55..cf2139a9cc4aa41ac3a5bfc6f1f1229c86771991 100644 (file)
@@ -10,7 +10,7 @@
  *
  *
  * IDENTIFICATION
- *   $Header: /cvsroot/pgsql/src/backend/parser/gram.y,v 2.95 1999/07/27 03:51:06 tgl Exp $
+ *   $Header: /cvsroot/pgsql/src/backend/parser/gram.y,v 2.96 1999/07/28 17:39:38 tgl Exp $
  *
  * HISTORY
  *   AUTHOR            DATE            MAJOR EVENT
@@ -55,7 +55,6 @@
 
 static char saved_relname[NAMEDATALEN];  /* need this for complex attributes */
 static bool QueryIsRule = FALSE;
-static List *saved_In_Expr = NIL;
 static Oid *param_type_info;
 static int pfunc_num_args;
 extern List *parsetree;
@@ -213,9 +212,8 @@ Oid param_type(int t); /* used in parse_expr.c */
 %type  def_elem
 %type    def_arg, columnElem, where_clause,
                a_expr, a_expr_or_null, b_expr, AexprConst,
-               in_expr, in_expr_nodes, not_in_expr, not_in_expr_nodes,
-               having_clause
-%type    row_descriptor, row_list, c_list, c_expr
+               in_expr, having_clause
+%type    row_descriptor, row_list, c_list, c_expr, in_expr_nodes
 %type    row_expr
 %type         row_op
 %type    case_expr, case_arg, when_clause, case_default
@@ -3986,33 +3984,59 @@ a_expr:  attr
                        makeA_Expr(OP, "<", $1, $4),
                        makeA_Expr(OP, ">", $1, $6));
                }
-       | a_expr IN { saved_In_Expr = lcons($1,saved_In_Expr); } '(' in_expr ')'
+       | a_expr IN '(' in_expr ')'
                {
-                   saved_In_Expr = lnext(saved_In_Expr);
-                   if (nodeTag($5) == T_SubLink)
+                   /* in_expr returns a SubLink or a list of a_exprs */
+                   if (IsA($4, SubLink))
                    {
-                           SubLink *n = (SubLink *)$5;
+                           SubLink *n = (SubLink *)$4;
                            n->lefthand = lcons($1, NIL);
                            n->oper = lcons("=",NIL);
                            n->useor = false;
                            n->subLinkType = ANY_SUBLINK;
                            $$ = (Node *)n;
                    }
-                   else    $$ = $5;
+                   else
+                   {
+                       Node *n = NULL;
+                       List *l;
+                       foreach(l, (List *) $4)
+                       {
+                           Node *cmp = makeA_Expr(OP, "=", $1, lfirst(l));
+                           if (n == NULL)
+                               n = cmp;
+                           else
+                               n = makeA_Expr(OR, NULL, n, cmp);
+                       }
+                       $$ = n;
+                   }
                }
-       | a_expr NOT IN { saved_In_Expr = lcons($1,saved_In_Expr); } '(' not_in_expr ')'
+       | a_expr NOT IN '(' in_expr ')'
                {
-                   saved_In_Expr = lnext(saved_In_Expr);
-                   if (nodeTag($6) == T_SubLink)
+                   /* in_expr returns a SubLink or a list of a_exprs */
+                   if (IsA($5, SubLink))
                    {
-                           SubLink *n = (SubLink *)$6;
-                           n->lefthand = lcons($1, NIL);
-                           n->oper = lcons("<>",NIL);
-                           n->useor = false;
-                           n->subLinkType = ALL_SUBLINK;
-                           $$ = (Node *)n;
+                       SubLink *n = (SubLink *)$5;
+                       n->lefthand = lcons($1, NIL);
+                       n->oper = lcons("<>",NIL);
+                       n->useor = false;
+                       n->subLinkType = ALL_SUBLINK;
+                       $$ = (Node *)n;
+                   }
+                   else
+                   {
+                       Node *n = NULL;
+                       List *l;
+                       foreach(l, (List *) $5)
+                       {
+                           Node *cmp = makeA_Expr(OP, "<>", $1, lfirst(l));
+                           if (n == NULL)
+                               n = cmp;
+                           else
+                               n = makeA_Expr(AND, NULL, n, cmp);
+                       }
+                       $$ = n;
                    }
-                   else    $$ = $6;
                }
        | a_expr Op '(' SubSelect ')'
                {
@@ -4632,33 +4656,13 @@ in_expr:  SubSelect
                    $$ = (Node *)n;
                }
        | in_expr_nodes
-               {   $$ = $1; }
-       ;
-
-in_expr_nodes:  AexprConst
-               {   $$ = makeA_Expr(OP, "=", lfirst(saved_In_Expr), $1); }
-       | in_expr_nodes ',' AexprConst
-               {   $$ = makeA_Expr(OR, NULL, $1,
-                       makeA_Expr(OP, "=", lfirst(saved_In_Expr), $3));
-               }
+               {   $$ = (Node *)$1; }
        ;
 
-not_in_expr:  SubSelect
-               {
-                   SubLink *n = makeNode(SubLink);
-                   n->subselect = $1;
-                   $$ = (Node *)n;
-               }
-       | not_in_expr_nodes
-               {   $$ = $1; }
-       ;
-
-not_in_expr_nodes:  AexprConst
-               {   $$ = makeA_Expr(OP, "<>", lfirst(saved_In_Expr), $1); }
-       | not_in_expr_nodes ',' AexprConst
-               {   $$ = makeA_Expr(AND, NULL, $1,
-                       makeA_Expr(OP, "<>", lfirst(saved_In_Expr), $3));
-               }
+in_expr_nodes:  a_expr
+               {   $$ = lcons($1, NIL); }
+       | in_expr_nodes ',' a_expr
+               {   $$ = lappend($1, $3); }
        ;
 
 /* Case clause
@@ -5239,7 +5243,6 @@ void parser_init(Oid *typev, int nargs)
 {
    QueryIsRule = FALSE;
    saved_relname[0]= '\0';
-   saved_In_Expr = NULL;
 
    param_type_init(typev, nargs);
 }