diff --git a/src/backend/parser/parse_expr.c b/src/backend/parser/parse_expr.c index b3ec1f7935..049605348c 100644 --- a/src/backend/parser/parse_expr.c +++ b/src/backend/parser/parse_expr.c @@ -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 $ * *------------------------------------------------------------------------- */ @@ -30,7 +30,10 @@ #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); +} - /* try to find the ident as a relation */ - if (refnameRangeTableEntry(pstate, ident->name) != NULL) +static Node * +transformAttr(ParseState *pstate, Attr *att, int precedence) +{ + Node *basenode; + + /* 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)