OSDN Git Service

Support subscripts on bare column names.
authorTom Lane <tgl@sss.pgh.pa.us>
Fri, 16 Jul 1999 22:32:25 +0000 (22:32 +0000)
committerTom Lane <tgl@sss.pgh.pa.us>
Fri, 16 Jul 1999 22:32:25 +0000 (22:32 +0000)
src/backend/parser/parse_expr.c

index b3ec1f7..0496053 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 = "<unnamed>";
                                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)