Support subscripts on bare column names.
authorTom Lane
Fri, 16 Jul 1999 22:32:25 +0000 (22:32 +0000)
committerTom Lane
Fri, 16 Jul 1999 22:32:25 +0000 (22:32 +0000)
src/backend/parser/parse_expr.c

index b3ec1f7935f207b15a505c0330bd8f5af807855b..049605348c4ec286488feafa18928b829a391328 100644 (file)
@@ -7,7 +7,7 @@
  *
  *
  * IDENTIFICATION
- *   $Header: /cvsroot/pgsql/src/backend/parser/parse_expr.c,v 1.52 1999/07/16 04:59:32 momjian Exp $
+ *   $Header: /cvsroot/pgsql/src/backend/parser/parse_expr.c,v 1.53 1999/07/16 22:32:25 tgl Exp $
  *
  *-------------------------------------------------------------------------
  */
 #include "utils/builtins.h"
 
 static Node *parser_typecast(Value *expr, TypeName *typename, int32 atttypmod);
-static Node *transformIdent(ParseState *pstate, Node *expr, int precedence);
+static Node *transformAttr(ParseState *pstate, Attr *att, int precedence);
+static Node *transformIdent(ParseState *pstate, Ident *ident, int precedence);
+static Node *transformIndirection(ParseState *pstate, Node *basenode,
+                                 List *indirection, int precedence);
 
 /*
  * transformExpr -
@@ -51,45 +54,7 @@ transformExpr(ParseState *pstate, Node *expr, int precedence)
    {
        case T_Attr:
            {
-               Attr       *att = (Attr *) expr;
-               Node       *temp;
-
-               /* what if att.attrs == "*"? */
-               temp = ParseNestedFuncOrColumn(pstate, att, &pstate->p_last_resno,
-                                              precedence);
-               if (att->indirection != NIL)
-               {
-                   List       *idx = att->indirection;
-
-                   while (idx != NIL)
-                   {
-                       A_Indices  *ai = (A_Indices *) lfirst(idx);
-                       Node       *lexpr = NULL,
-                                  *uexpr;
-
-                       uexpr = transformExpr(pstate, ai->uidx, precedence);    /* must exists */
-                       if (exprType(uexpr) != INT4OID)
-                           elog(ERROR, "array index expressions must be int4's");
-                       if (ai->lidx != NULL)
-                       {
-                           lexpr = transformExpr(pstate, ai->lidx, precedence);
-                           if (exprType(lexpr) != INT4OID)
-                               elog(ERROR, "array index expressions must be int4's");
-                       }
-                       ai->lidx = lexpr;
-                       ai->uidx = uexpr;
-
-                       /*
-                        * note we reuse the list of indices, make sure we
-                        * don't free them! Otherwise, make a new list
-                        * here
-                        */
-                       idx = lnext(idx);
-                   }
-                   result = (Node *) make_array_ref(temp, att->indirection);
-               }
-               else
-                   result = temp;
+               result = transformAttr(pstate, (Attr *) expr, precedence);
                break;
            }
        case T_A_Const:
@@ -106,12 +71,10 @@ transformExpr(ParseState *pstate, Node *expr, int precedence)
        case T_ParamNo:
            {
                ParamNo    *pno = (ParamNo *) expr;
-               Oid         toid;
-               int         paramno;
+               int         paramno = pno->number;
+               Oid         toid = param_type(paramno);
                Param      *param;
 
-               paramno = pno->number;
-               toid = param_type(paramno);
                if (!OidIsValid(toid))
                    elog(ERROR, "Parameter '$%d' is out of range", paramno);
                param = makeNode(Param);
@@ -120,40 +83,8 @@ transformExpr(ParseState *pstate, Node *expr, int precedence)
                param->paramname = "";
                param->paramtype = (Oid) toid;
                param->param_tlist = (List *) NULL;
-
-               if (pno->indirection != NIL)
-               {
-                   List       *idx = pno->indirection;
-
-                   while (idx != NIL)
-                   {
-                       A_Indices  *ai = (A_Indices *) lfirst(idx);
-                       Node       *lexpr = NULL,
-                                  *uexpr;
-
-                       uexpr = transformExpr(pstate, ai->uidx, precedence);    /* must exists */
-                       if (exprType(uexpr) != INT4OID)
-                           elog(ERROR, "array index expressions must be int4's");
-                       if (ai->lidx != NULL)
-                       {
-                           lexpr = transformExpr(pstate, ai->lidx, precedence);
-                           if (exprType(lexpr) != INT4OID)
-                               elog(ERROR, "array index expressions must be int4's");
-                       }
-                       ai->lidx = lexpr;
-                       ai->uidx = uexpr;
-
-                       /*
-                        * note we reuse the list of indices, make sure we
-                        * don't free them! Otherwise, make a new list
-                        * here
-                        */
-                       idx = lnext(idx);
-                   }
-                   result = (Node *) make_array_ref((Node *) param, pno->indirection);
-               }
-               else
-                   result = (Node *) param;
+               result = transformIndirection(pstate, (Node *) param,
+                                             pno->indirection, precedence);
                break;
            }
        case T_A_Expr:
@@ -247,12 +178,7 @@ transformExpr(ParseState *pstate, Node *expr, int precedence)
            }
        case T_Ident:
            {
-
-               /*
-                * look for a column name or a relation name (the default
-                * behavior)
-                */
-               result = transformIdent(pstate, expr, precedence);
+               result = transformIdent(pstate, (Ident *) expr, precedence);
                break;
            }
        case T_FuncCall:
@@ -544,48 +470,79 @@ transformExpr(ParseState *pstate, Node *expr, int precedence)
 }
 
 static Node *
-transformIdent(ParseState *pstate, Node *expr, int precedence)
+transformIndirection(ParseState *pstate, Node *basenode,
+                    List *indirection, int precedence)
 {
-   Ident      *ident = (Ident *) expr;
-   RangeTblEntry *rte;
-   Node       *column_result,
-              *relation_result,
-              *result;
+   List       *idx;
 
-   column_result = relation_result = result = 0;
-   /* try to find the ident as a column */
-   if ((rte = colnameRangeTableEntry(pstate, ident->name)) != NULL)
+   if (indirection == NIL)
+       return basenode;
+   foreach (idx, indirection)
    {
-       Attr       *att = makeNode(Attr);
+       A_Indices  *ai = (A_Indices *) lfirst(idx);
+       Node       *lexpr = NULL,
+                  *uexpr;
 
-       /* we add the relation name for them */
-       att->relname = rte->refname;
-       att->attrs = lcons(makeString(ident->name), NIL);
-       column_result = (Node *) ParseNestedFuncOrColumn(pstate, att,
-                                     &pstate->p_last_resno, precedence);
+       /* uidx is always present, but lidx might be null */
+       if (ai->lidx != NULL)
+       {
+           lexpr = transformExpr(pstate, ai->lidx, precedence);
+           if (exprType(lexpr) != INT4OID)
+               elog(ERROR, "array index expressions must be int4's");
+       }
+       uexpr = transformExpr(pstate, ai->uidx, precedence);
+       if (exprType(uexpr) != INT4OID)
+           elog(ERROR, "array index expressions must be int4's");
+       ai->lidx = lexpr;
+       ai->uidx = uexpr;
+       /*
+        * note we reuse the list of A_Indices nodes, make sure
+        * we don't free them! Otherwise, make a new list here
+        */
    }
+   return (Node *) make_array_ref(basenode, indirection);
+}
+
+static Node *
+transformAttr(ParseState *pstate, Attr *att, int precedence)
+{
+   Node       *basenode;
 
-   /* try to find the ident as a relation */
-   if (refnameRangeTableEntry(pstate, ident->name) != NULL)
+   /* what if att->attrs == "*"? */
+   basenode = ParseNestedFuncOrColumn(pstate, att, &pstate->p_last_resno,
+                                      precedence);
+   return transformIndirection(pstate, basenode,
+                               att->indirection, precedence);
+}
+
+static Node *
+transformIdent(ParseState *pstate, Ident *ident, int precedence)
+{
+   Node       *result = NULL;
+   RangeTblEntry *rte;
+
+   /* try to find the ident as a relation ... but not if subscripts appear */
+   if (ident->indirection == NIL &&
+       refnameRangeTableEntry(pstate, ident->name) != NULL)
    {
        ident->isRel = TRUE;
-       relation_result = (Node *) ident;
+       result = (Node *) ident;
    }
 
-   /* choose the right result based on the precedence */
-   if (precedence == EXPR_COLUMN_FIRST)
+   if (result == NULL || precedence == EXPR_COLUMN_FIRST)
    {
-       if (column_result)
-           result = column_result;
-       else
-           result = relation_result;
-   }
-   else
-   {
-       if (relation_result)
-           result = relation_result;
-       else
-           result = column_result;
+       /* try to find the ident as a column */
+       if ((rte = colnameRangeTableEntry(pstate, ident->name)) != NULL)
+       {
+           /* Convert it to a fully qualified Attr, and transform that */
+           Attr       *att = makeNode(Attr);
+
+           att->relname = rte->refname;
+           att->paramNo = NULL;
+           att->attrs = lcons(makeString(ident->name), NIL);
+           att->indirection = ident->indirection;
+           return transformAttr(pstate, att, precedence);
+       }
    }
 
    if (result == NULL)