77 *
88 *
99 * IDENTIFICATION
10- * $Header: /cvsroot/pgsql/src/backend/parser/parse_expr.c,v 1.52 1999/07/1604:59:32 momjian Exp $
10+ * $Header: /cvsroot/pgsql/src/backend/parser/parse_expr.c,v 1.53 1999/07/1622:32:25 tgl Exp $
1111 *
1212 *-------------------------------------------------------------------------
1313 */
3030#include "utils/builtins.h"
3131
3232static Node * parser_typecast (Value * expr ,TypeName * typename ,int32 atttypmod );
33- static Node * transformIdent (ParseState * pstate ,Node * expr ,int precedence );
33+ static Node * transformAttr (ParseState * pstate ,Attr * att ,int precedence );
34+ static Node * transformIdent (ParseState * pstate ,Ident * ident ,int precedence );
35+ static Node * transformIndirection (ParseState * pstate ,Node * basenode ,
36+ List * indirection ,int precedence );
3437
3538/*
3639 * transformExpr -
@@ -51,45 +54,7 @@ transformExpr(ParseState *pstate, Node *expr, int precedence)
5154{
5255case T_Attr :
5356{
54- Attr * att = (Attr * )expr ;
55- Node * temp ;
56-
57- /* what if att.attrs == "*"? */
58- temp = ParseNestedFuncOrColumn (pstate ,att ,& pstate -> p_last_resno ,
59- precedence );
60- if (att -> indirection != NIL )
61- {
62- List * idx = att -> indirection ;
63-
64- while (idx != NIL )
65- {
66- A_Indices * ai = (A_Indices * )lfirst (idx );
67- Node * lexpr = NULL ,
68- * uexpr ;
69-
70- uexpr = transformExpr (pstate ,ai -> uidx ,precedence );/* must exists */
71- if (exprType (uexpr )!= INT4OID )
72- elog (ERROR ,"array index expressions must be int4's" );
73- if (ai -> lidx != NULL )
74- {
75- lexpr = transformExpr (pstate ,ai -> lidx ,precedence );
76- if (exprType (lexpr )!= INT4OID )
77- elog (ERROR ,"array index expressions must be int4's" );
78- }
79- ai -> lidx = lexpr ;
80- ai -> uidx = uexpr ;
81-
82- /*
83- * note we reuse the list of indices, make sure we
84- * don't free them! Otherwise, make a new list
85- * here
86- */
87- idx = lnext (idx );
88- }
89- result = (Node * )make_array_ref (temp ,att -> indirection );
90- }
91- else
92- result = temp ;
57+ result = transformAttr (pstate , (Attr * )expr ,precedence );
9358break ;
9459}
9560case T_A_Const :
@@ -106,12 +71,10 @@ transformExpr(ParseState *pstate, Node *expr, int precedence)
10671case T_ParamNo :
10772{
10873ParamNo * pno = (ParamNo * )expr ;
109- Oid toid ;
110- int paramno ;
74+ int paramno = pno -> number ;
75+ Oid toid = param_type ( paramno ) ;
11176Param * param ;
11277
113- paramno = pno -> number ;
114- toid = param_type (paramno );
11578if (!OidIsValid (toid ))
11679elog (ERROR ,"Parameter '$%d' is out of range" ,paramno );
11780param = makeNode (Param );
@@ -120,40 +83,8 @@ transformExpr(ParseState *pstate, Node *expr, int precedence)
12083param -> paramname = "<unnamed>" ;
12184param -> paramtype = (Oid )toid ;
12285param -> param_tlist = (List * )NULL ;
123-
124- if (pno -> indirection != NIL )
125- {
126- List * idx = pno -> indirection ;
127-
128- while (idx != NIL )
129- {
130- A_Indices * ai = (A_Indices * )lfirst (idx );
131- Node * lexpr = NULL ,
132- * uexpr ;
133-
134- uexpr = transformExpr (pstate ,ai -> uidx ,precedence );/* must exists */
135- if (exprType (uexpr )!= INT4OID )
136- elog (ERROR ,"array index expressions must be int4's" );
137- if (ai -> lidx != NULL )
138- {
139- lexpr = transformExpr (pstate ,ai -> lidx ,precedence );
140- if (exprType (lexpr )!= INT4OID )
141- elog (ERROR ,"array index expressions must be int4's" );
142- }
143- ai -> lidx = lexpr ;
144- ai -> uidx = uexpr ;
145-
146- /*
147- * note we reuse the list of indices, make sure we
148- * don't free them! Otherwise, make a new list
149- * here
150- */
151- idx = lnext (idx );
152- }
153- result = (Node * )make_array_ref ((Node * )param ,pno -> indirection );
154- }
155- else
156- result = (Node * )param ;
86+ result = transformIndirection (pstate , (Node * )param ,
87+ pno -> indirection ,precedence );
15788break ;
15889}
15990case T_A_Expr :
@@ -247,12 +178,7 @@ transformExpr(ParseState *pstate, Node *expr, int precedence)
247178}
248179case T_Ident :
249180{
250-
251- /*
252- * look for a column name or a relation name (the default
253- * behavior)
254- */
255- result = transformIdent (pstate ,expr ,precedence );
181+ result = transformIdent (pstate , (Ident * )expr ,precedence );
256182break ;
257183}
258184case T_FuncCall :
@@ -544,48 +470,79 @@ transformExpr(ParseState *pstate, Node *expr, int precedence)
544470}
545471
546472static Node *
547- transformIdent (ParseState * pstate ,Node * expr ,int precedence )
473+ transformIndirection (ParseState * pstate ,Node * basenode ,
474+ List * indirection ,int precedence )
548475{
549- Ident * ident = (Ident * )expr ;
550- RangeTblEntry * rte ;
551- Node * column_result ,
552- * relation_result ,
553- * result ;
476+ List * idx ;
554477
555- column_result = relation_result = result = 0 ;
556- /* try to find the ident as a column */
557- if (( rte = colnameRangeTableEntry ( pstate , ident -> name )) != NULL )
478+ if ( indirection == NIL )
479+ return basenode ;
480+ foreach ( idx , indirection )
558481{
559- Attr * att = makeNode (Attr );
482+ A_Indices * ai = (A_Indices * )lfirst (idx );
483+ Node * lexpr = NULL ,
484+ * uexpr ;
560485
561- /* we add the relation name for them */
562- att -> relname = rte -> refname ;
563- att -> attrs = lcons (makeString (ident -> name ),NIL );
564- column_result = (Node * )ParseNestedFuncOrColumn (pstate ,att ,
565- & pstate -> p_last_resno ,precedence );
486+ /* uidx is always present, but lidx might be null */
487+ if (ai -> lidx != NULL )
488+ {
489+ lexpr = transformExpr (pstate ,ai -> lidx ,precedence );
490+ if (exprType (lexpr )!= INT4OID )
491+ elog (ERROR ,"array index expressions must be int4's" );
492+ }
493+ uexpr = transformExpr (pstate ,ai -> uidx ,precedence );
494+ if (exprType (uexpr )!= INT4OID )
495+ elog (ERROR ,"array index expressions must be int4's" );
496+ ai -> lidx = lexpr ;
497+ ai -> uidx = uexpr ;
498+ /*
499+ * note we reuse the list of A_Indices nodes, make sure
500+ * we don't free them! Otherwise, make a new list here
501+ */
566502}
503+ return (Node * )make_array_ref (basenode ,indirection );
504+ }
505+
506+ static Node *
507+ transformAttr (ParseState * pstate ,Attr * att ,int precedence )
508+ {
509+ Node * basenode ;
567510
568- /* try to find the ident as a relation */
569- if (refnameRangeTableEntry (pstate ,ident -> name )!= NULL )
511+ /* what if att->attrs == "*"? */
512+ basenode = ParseNestedFuncOrColumn (pstate ,att ,& pstate -> p_last_resno ,
513+ precedence );
514+ return transformIndirection (pstate ,basenode ,
515+ att -> indirection ,precedence );
516+ }
517+
518+ static Node *
519+ transformIdent (ParseState * pstate ,Ident * ident ,int precedence )
520+ {
521+ Node * result = NULL ;
522+ RangeTblEntry * rte ;
523+
524+ /* try to find the ident as a relation ... but not if subscripts appear */
525+ if (ident -> indirection == NIL &&
526+ refnameRangeTableEntry (pstate ,ident -> name )!= NULL )
570527{
571528ident -> isRel = TRUE;
572- relation_result = (Node * )ident ;
529+ result = (Node * )ident ;
573530}
574531
575- /* choose the right result based on the precedence */
576- if (precedence == EXPR_COLUMN_FIRST )
532+ if (result == NULL || precedence == EXPR_COLUMN_FIRST )
577533{
578- if (column_result )
579- result = column_result ;
580- else
581- result = relation_result ;
582- }
583- else
584- {
585- if (relation_result )
586- result = relation_result ;
587- else
588- result = column_result ;
534+ /* try to find the ident as a column */
535+ if ((rte = colnameRangeTableEntry (pstate ,ident -> name ))!= NULL )
536+ {
537+ /* Convert it to a fully qualified Attr, and transform that */
538+ Attr * att = makeNode (Attr );
539+
540+ att -> relname = rte -> refname ;
541+ att -> paramNo = NULL ;
542+ att -> attrs = lcons (makeString (ident -> name ),NIL );
543+ att -> indirection = ident -> indirection ;
544+ return transformAttr (pstate ,att ,precedence );
545+ }
589546}
590547
591548if (result == NULL )