OSDN Git Service

Now we can GROUP BY func_results.
[pg-rex/syncrep.git] / src / backend / parser / analyze.c
1 /*-------------------------------------------------------------------------
2  *
3  * analyze.c--
4  *    transform the parse tree into a query tree
5  *
6  * Copyright (c) 1994, Regents of the University of California
7  *
8  *
9  * IDENTIFICATION
10  *    $Header: /cvsroot/pgsql/src/backend/parser/analyze.c,v 1.25 1997/04/05 06:29:03 vadim Exp $
11  *
12  *-------------------------------------------------------------------------
13  */
14 #include <stdio.h>
15 #include <stdlib.h>
16 #include <string.h>
17 #include "postgres.h"
18 #include "nodes/nodes.h"
19 #include "nodes/params.h"
20 #include "nodes/primnodes.h"
21 #include "nodes/parsenodes.h"
22 #include "nodes/relation.h"
23 #include "parse.h"              /* for AND, OR, etc. */
24 #include "catalog/pg_type.h"    /* for INT4OID, etc. */
25 #include "catalog/pg_proc.h"
26 #include "utils/elog.h"
27 #include "utils/builtins.h"     /* namecmp(), textout() */
28 #include "utils/lsyscache.h"
29 #include "utils/palloc.h"
30 #include "utils/mcxt.h"
31 #include "utils/syscache.h"
32 #include "utils/acl.h"
33 #include "parser/parse_query.h"
34 #include "parser/parse_state.h"
35 #include "nodes/makefuncs.h"    /* for makeResdom(), etc. */
36 #include "nodes/nodeFuncs.h"
37 #include "commands/sequence.h"
38
39 #include "optimizer/clauses.h"
40 #include "access/heapam.h"
41
42 #include "miscadmin.h"
43
44 #include "port-protos.h"        /* strdup() */
45
46 /* convert the parse tree into a query tree */
47 static Query *transformStmt(ParseState *pstate, Node *stmt);
48
49 static Query *transformDeleteStmt(ParseState *pstate, DeleteStmt *stmt);
50 static Query *transformInsertStmt(ParseState *pstate, AppendStmt *stmt);
51 static Query *transformIndexStmt(ParseState *pstate, IndexStmt *stmt);
52 static Query *transformExtendStmt(ParseState *pstate, ExtendStmt *stmt);
53 static Query *transformRuleStmt(ParseState *query, RuleStmt *stmt);
54 static Query *transformSelectStmt(ParseState *pstate, RetrieveStmt *stmt);
55 static Query *transformUpdateStmt(ParseState *pstate, ReplaceStmt *stmt);
56 static Query *transformCursorStmt(ParseState *pstate, CursorStmt *stmt);
57 static Node *handleNestedDots(ParseState *pstate, Attr *attr, int *curr_resno);
58
59 #define EXPR_COLUMN_FIRST    1
60 #define EXPR_RELATION_FIRST  2
61 static Node *transformExpr(ParseState *pstate, Node *expr, int precedence);
62 static Node *transformIdent(ParseState *pstate, Node *expr, int precedence);
63
64 static void makeRangeTable(ParseState *pstate, char *relname, List *frmList);
65 static List *expandAllTables(ParseState *pstate);
66 static char *figureColname(Node *expr, Node *resval);
67 static List *makeTargetNames(ParseState *pstate, List *cols);
68 static List *transformTargetList(ParseState *pstate, List *targetlist);
69 static TargetEntry *make_targetlist_expr(ParseState *pstate,
70                                          char *colname, Node *expr,
71                                          List *arrayRef);
72 static bool inWhereClause = false;
73 static Node *transformWhereClause(ParseState *pstate, Node *a_expr);
74 static List *transformGroupClause(ParseState *pstate, List *grouplist,
75                                                         List *targetlist);
76 static List *transformSortClause(ParseState *pstate,
77                                  List *orderlist, List *targetlist,
78                                  char* uniqueFlag);
79
80 static void parseFromClause(ParseState *pstate, List *frmList);
81 static Node *ParseFunc(ParseState *pstate, char *funcname, 
82                        List *fargs, int *curr_resno);
83 static List *setup_tlist(char *attname, Oid relid);
84 static List *setup_base_tlist(Oid typeid);
85 static void make_arguments(int nargs, List *fargs, Oid *input_typeids,
86                                                         Oid *function_typeids);
87 static void AddAggToParseState(ParseState *pstate, Aggreg *aggreg);
88 static void finalizeAggregates(ParseState *pstate, Query *qry);
89 static void parseCheckAggregates(ParseState *pstate, Query *qry);
90
91 /*****************************************************************************
92  *
93  *****************************************************************************/
94
95 /*
96  * makeParseState() -- 
97  *    allocate and initialize a new ParseState.
98  *  the CALLERS is responsible for freeing the ParseState* returned
99  *
100  */
101
102 ParseState* 
103 makeParseState(void)
104 {
105     ParseState *pstate;
106
107     pstate = malloc(sizeof(ParseState));
108     pstate->p_last_resno = 1;
109     pstate->p_rtable = NIL;
110     pstate->p_numAgg = 0;
111     pstate->p_aggs = NIL;
112     pstate->p_is_insert = false;
113     pstate->p_insert_columns = NIL;
114     pstate->p_is_update = false;
115     pstate->p_is_rule = false;
116     pstate->p_target_relation = NULL;
117     pstate->p_target_rangetblentry = NULL;
118
119     return (pstate);
120 }
121
122 /*
123  * parse_analyze -
124  *    analyze a list of parse trees and transform them if necessary.
125  *
126  * Returns a list of transformed parse trees. Optimizable statements are
127  * all transformed to Query while the rest stays the same.
128  *
129  * CALLER is responsible for freeing the QueryTreeList* returned
130  */
131 QueryTreeList *
132 parse_analyze(List *pl)
133 {
134     QueryTreeList *result;
135     ParseState *pstate;
136     int i = 0;
137
138     result = malloc(sizeof(QueryTreeList));
139     result->len = length(pl);
140     result->qtrees = (Query**)malloc(result->len * sizeof(Query*));
141     
142     inWhereClause = false;      /* to avoid nextval(sequence) in WHERE */
143
144     while(pl!=NIL) {
145         pstate = makeParseState();
146         result->qtrees[i++] = transformStmt(pstate, lfirst(pl));
147         pl = lnext(pl);
148         if (pstate->p_target_relation != NULL)
149             heap_close(pstate->p_target_relation);
150         free(pstate);
151     }
152
153     return result;
154 }
155
156 /*
157  * transformStmt -
158  *    transform a Parse tree. If it is an optimizable statement, turn it
159  *    into a Query tree.
160  */
161 static Query *
162 transformStmt(ParseState* pstate, Node *parseTree)
163 {
164     Query* result = NULL;
165
166     switch(nodeTag(parseTree)) {
167       /*------------------------
168        *  Non-optimizable statements
169        *------------------------
170        */
171     case T_IndexStmt:
172       result = transformIndexStmt(pstate, (IndexStmt *)parseTree);
173       break;
174
175     case T_ExtendStmt:
176       result = transformExtendStmt(pstate, (ExtendStmt *)parseTree);
177       break;
178
179     case T_RuleStmt:
180       result = transformRuleStmt(pstate, (RuleStmt *)parseTree);
181       break;
182
183     case T_ViewStmt:
184       {
185         ViewStmt *n = (ViewStmt *)parseTree;
186         n->query = (Query *)transformStmt(pstate, (Node*)n->query);
187         result = makeNode(Query);
188         result->commandType = CMD_UTILITY;
189         result->utilityStmt = (Node*)n;
190       }
191       break;
192
193     case T_VacuumStmt:
194       {
195         MemoryContext oldcontext;
196         /* make sure that this Query is allocated in TopMemory context
197            because vacuum spans transactions and we don't want to lose
198            the vacuum Query due to end-of-transaction free'ing*/
199         oldcontext = MemoryContextSwitchTo(TopMemoryContext);
200         result = makeNode(Query);
201         result->commandType = CMD_UTILITY;
202         result->utilityStmt = (Node*)parseTree;
203         MemoryContextSwitchTo(oldcontext);
204         break;
205             
206       }
207   case T_ExplainStmt:
208       {
209           ExplainStmt *n = (ExplainStmt *)parseTree;
210           result = makeNode(Query);
211           result->commandType = CMD_UTILITY;
212           n->query = transformStmt(pstate, (Node*)n->query);
213           result->utilityStmt = (Node*)parseTree;
214       }
215       break;
216       
217       /*------------------------
218        *  Optimizable statements
219        *------------------------
220        */
221     case T_AppendStmt:
222       result = transformInsertStmt(pstate, (AppendStmt *)parseTree);
223       break;
224
225     case T_DeleteStmt:
226       result = transformDeleteStmt(pstate, (DeleteStmt *)parseTree);
227       break;
228
229     case T_ReplaceStmt:
230       result = transformUpdateStmt(pstate, (ReplaceStmt *)parseTree);
231       break;
232
233     case T_CursorStmt:
234       result = transformCursorStmt(pstate, (CursorStmt *)parseTree);
235       break;
236
237     case T_RetrieveStmt:
238       result = transformSelectStmt(pstate, (RetrieveStmt *)parseTree);
239       break;
240
241     default:
242       /*
243        * other statments don't require any transformation-- just
244        * return the original parsetree 
245        */
246       result = makeNode(Query);
247       result->commandType = CMD_UTILITY;
248       result->utilityStmt = (Node*)parseTree;
249       break;
250     }
251     return result;
252 }
253
254 /*
255  * transformDeleteStmt -
256  *    transforms a Delete Statement
257  */
258 static Query *
259 transformDeleteStmt(ParseState *pstate, DeleteStmt *stmt)
260 {
261     Query *qry = makeNode(Query);
262
263     qry->commandType = CMD_DELETE;
264
265     /* set up a range table */
266     makeRangeTable(pstate, stmt->relname, NULL);
267     
268     qry->uniqueFlag = NULL; 
269
270     /* fix where clause */
271     qry->qual = transformWhereClause(pstate, stmt->whereClause);
272
273     qry->rtable = pstate->p_rtable;
274     qry->resultRelation = refnameRangeTablePosn(pstate->p_rtable, stmt->relname);
275
276     /* make sure we don't have aggregates in the where clause */
277     if (pstate->p_numAgg > 0)
278         parseCheckAggregates(pstate, qry);
279
280     return (Query *)qry;
281 }
282
283 /*
284  * transformInsertStmt -
285  *    transform an Insert Statement
286  */
287 static Query *
288 transformInsertStmt(ParseState *pstate, AppendStmt *stmt)
289 {
290     Query *qry = makeNode(Query);       /* make a new query tree */
291
292     qry->commandType = CMD_INSERT;
293     pstate->p_is_insert = true;
294
295     /* set up a range table */
296     makeRangeTable(pstate, stmt->relname, stmt->fromClause);
297
298     qry->uniqueFlag = NULL; 
299
300     /* fix the target list */
301     pstate->p_insert_columns = makeTargetNames(pstate, stmt->cols);
302
303     qry->targetList = transformTargetList(pstate, stmt->targetList);
304
305     /* fix where clause */
306     qry->qual = transformWhereClause(pstate, stmt->whereClause);
307
308     /* now the range table will not change */
309     qry->rtable = pstate->p_rtable;
310     qry->resultRelation = refnameRangeTablePosn(pstate->p_rtable, stmt->relname);
311
312     if (pstate->p_numAgg > 0)
313         finalizeAggregates(pstate, qry);
314
315     return (Query *)qry;
316 }
317
318 /*
319  * transformIndexStmt -
320  *    transforms the qualification of the index statement
321  */
322 static Query *
323 transformIndexStmt(ParseState *pstate, IndexStmt *stmt)
324 {
325     Query* q;
326
327     q = makeNode(Query);
328     q->commandType = CMD_UTILITY;
329     
330     /* take care of the where clause */
331     stmt->whereClause = transformWhereClause(pstate,stmt->whereClause);
332     stmt->rangetable = pstate->p_rtable;
333
334     q->utilityStmt = (Node*)stmt;
335
336     return q;
337 }
338
339 /*
340  * transformExtendStmt -
341  *    transform the qualifications of the Extend Index Statement
342  *
343  */
344 static Query *
345 transformExtendStmt(ParseState *pstate, ExtendStmt *stmt)
346 {
347     Query  *q;
348
349     q = makeNode(Query);
350     q->commandType = CMD_UTILITY;
351
352     /* take care of the where clause */
353     stmt->whereClause = transformWhereClause(pstate,stmt->whereClause);
354     stmt->rangetable = pstate->p_rtable;
355
356     q->utilityStmt = (Node*)stmt;
357     return q;
358 }
359
360 /*
361  * transformRuleStmt -
362  *    transform a Create Rule Statement. The actions is a list of parse
363  *    trees which is transformed into a list of query trees.
364  */
365 static Query *
366 transformRuleStmt(ParseState *pstate, RuleStmt *stmt)
367 {
368     Query *q;
369     List *actions;
370     
371     q = makeNode(Query);
372     q->commandType = CMD_UTILITY;
373
374     actions = stmt->actions;
375     /*
376      * transform each statment, like parse_analyze()
377      */
378     while (actions != NIL) {
379         /*
380          * NOTE: 'CURRENT' must always have a varno equal to 1 and 'NEW' 
381          * equal to 2.
382          */
383         addRangeTableEntry(pstate, stmt->object->relname, "*CURRENT*",
384                                         FALSE, FALSE, NULL);
385         addRangeTableEntry(pstate, stmt->object->relname, "*NEW*",
386                                         FALSE, FALSE, NULL);
387
388         pstate->p_last_resno = 1;
389         pstate->p_is_rule = true;       /* for expand all */
390         pstate->p_numAgg = 0;
391         pstate->p_aggs = NULL;
392         
393         lfirst(actions) =  transformStmt(pstate, lfirst(actions));
394         actions = lnext(actions);
395     }
396
397     /* take care of the where clause */
398     stmt->whereClause = transformWhereClause(pstate,stmt->whereClause);
399
400     q->utilityStmt = (Node*)stmt;
401     return q;
402 }
403
404
405 /*
406  * transformSelectStmt -
407  *    transforms a Select Statement
408  *
409  */
410 static Query *
411 transformSelectStmt(ParseState *pstate, RetrieveStmt *stmt)
412 {
413     Query *qry = makeNode(Query);
414
415     qry->commandType = CMD_SELECT;
416
417     /* set up a range table */
418     makeRangeTable(pstate, NULL, stmt->fromClause);
419
420     qry->uniqueFlag = stmt->unique;
421
422     qry->into     = stmt->into;
423     qry->isPortal = FALSE;
424
425     /* fix the target list */
426     qry->targetList = transformTargetList(pstate, stmt->targetList);
427
428     /* fix where clause */
429     qry->qual = transformWhereClause(pstate,stmt->whereClause);
430
431     /* fix order clause */
432     qry->sortClause = transformSortClause(pstate,
433                                           stmt->sortClause,
434                                           qry->targetList,
435                                           qry->uniqueFlag);
436
437     /* fix group by clause */
438     qry->groupClause = transformGroupClause(pstate,
439                                           stmt->groupClause,
440                                           qry->targetList);
441     qry->rtable = pstate->p_rtable;
442
443     if (pstate->p_numAgg > 0)
444         finalizeAggregates(pstate, qry);
445         
446     return (Query *)qry;
447 }
448
449 /*
450  * transformUpdateStmt -
451  *    transforms an update statement
452  *
453  */
454 static Query *
455 transformUpdateStmt(ParseState *pstate, ReplaceStmt *stmt)
456 {
457     Query *qry = makeNode(Query);
458
459     qry->commandType = CMD_UPDATE;
460     pstate->p_is_update = true;
461     /*
462      * the FROM clause is non-standard SQL syntax. We used to be able to
463      * do this with REPLACE in POSTQUEL so we keep the feature.
464      */
465     makeRangeTable(pstate, stmt->relname, stmt->fromClause); 
466
467     /* fix the target list */
468     qry->targetList = transformTargetList(pstate, stmt->targetList);
469
470     /* fix where clause */
471     qry->qual = transformWhereClause(pstate,stmt->whereClause);
472
473     qry->rtable = pstate->p_rtable;
474     qry->resultRelation = refnameRangeTablePosn(pstate->p_rtable, stmt->relname);
475
476     /* make sure we don't have aggregates in the where clause */
477     if (pstate->p_numAgg > 0)
478         parseCheckAggregates(pstate, qry);
479
480     return (Query *)qry;
481 }
482
483 /*
484  * transformCursorStmt -
485  *    transform a Create Cursor Statement
486  *
487  */
488 static Query *
489 transformCursorStmt(ParseState *pstate, CursorStmt *stmt)
490 {
491     Query *qry = makeNode(Query);
492
493     /*
494      * in the old days, a cursor statement is a 'retrieve into portal';
495      * If you change the following, make sure you also go through the code
496      * in various places that tests the kind of operation.
497      */
498     qry->commandType = CMD_SELECT;
499
500     /* set up a range table */
501     makeRangeTable(pstate, NULL, stmt->fromClause);
502
503     qry->uniqueFlag = stmt->unique;
504
505     qry->into     = stmt->portalname;
506     qry->isPortal = TRUE;
507     qry->isBinary = stmt->binary;       /* internal portal */
508
509     /* fix the target list */
510     qry->targetList = transformTargetList(pstate, stmt->targetList);
511
512     /* fix where clause */
513     qry->qual = transformWhereClause(pstate,stmt->whereClause);
514
515     /* fix order clause */
516     qry->sortClause = transformSortClause(pstate,
517                                           stmt->sortClause,
518                                           qry->targetList,
519                                           qry->uniqueFlag);
520     /* fix group by clause */
521     qry->groupClause = transformGroupClause(pstate,
522                                           stmt->groupClause,
523                                           qry->targetList);
524
525     qry->rtable = pstate->p_rtable;
526
527     if (pstate->p_numAgg > 0)
528         finalizeAggregates(pstate, qry);
529
530     return (Query *)qry;
531 }
532
533 /*****************************************************************************
534  *
535  * Transform Exprs, Aggs, etc.
536  *
537  *****************************************************************************/
538
539 /*
540  * transformExpr -
541  *    analyze and transform expressions. Type checking and type casting is
542  *    done here. The optimizer and the executor cannot handle the original
543  *    (raw) expressions collected by the parse tree. Hence the transformation
544  *    here.
545  */
546 static Node *
547 transformExpr(ParseState *pstate, Node *expr, int precedence)
548 {
549     Node *result = NULL;
550
551     if (expr==NULL)
552         return NULL;
553     
554     switch(nodeTag(expr)) {
555     case T_Attr: {
556         Attr *att = (Attr *)expr;
557         Node *temp;
558
559         /* what if att.attrs == "*"?? */
560         temp = handleNestedDots(pstate, att, &pstate->p_last_resno);
561         if (att->indirection != NIL) {
562             List *idx = att->indirection;
563             while(idx!=NIL) {
564                 A_Indices *ai = (A_Indices *)lfirst(idx);
565                 Node *lexpr=NULL, *uexpr;
566                 uexpr = transformExpr(pstate, ai->uidx, precedence);  /* must exists */
567                 if (exprType(uexpr) != INT4OID)
568                     elog(WARN, "array index expressions must be int4's");
569                 if (ai->lidx != NULL) {
570                     lexpr = transformExpr(pstate, ai->lidx, precedence);
571                     if (exprType(lexpr) != INT4OID)
572                         elog(WARN, "array index expressions must be int4's");
573                 }
574 #if 0
575                 pfree(ai->uidx);
576                 if (ai->lidx!=NULL) pfree(ai->lidx);
577 #endif
578                 ai->lidx = lexpr;
579                 ai->uidx = uexpr;
580                 /* note we reuse the list of indices, make sure we don't free
581                    them! Otherwise, make a new list here */
582                 idx = lnext(idx);
583             }
584             result = (Node*)make_array_ref(temp, att->indirection);
585         }else {
586             result = temp;
587         }
588         break;
589     }
590     case T_A_Const: {
591         A_Const *con= (A_Const *)expr;
592         Value *val = &con->val;
593         if (con->typename != NULL) {
594             result = parser_typecast(val, con->typename, -1);
595         }else {
596             result = (Node *)make_const(val);
597         }
598         break;
599     }
600     case T_ParamNo: {
601         ParamNo *pno = (ParamNo *)expr;
602         Oid toid;
603         int paramno;
604         Param *param;
605
606         paramno = pno->number;
607         toid = param_type(paramno);
608         if (!OidIsValid(toid)) {
609             elog(WARN, "Parameter '$%d' is out of range",
610                  paramno);
611         }
612         param = makeNode(Param);
613         param->paramkind = PARAM_NUM;
614         param->paramid = (AttrNumber) paramno;
615         param->paramname = "<unnamed>";
616         param->paramtype = (Oid)toid;
617         param->param_tlist = (List*) NULL;
618
619         result = (Node *)param;
620         break;
621     }
622     case T_A_Expr: {
623         A_Expr *a = (A_Expr *)expr;
624
625         switch(a->oper) {
626         case OP:
627             {
628                 Node *lexpr = transformExpr(pstate, a->lexpr, precedence);
629                 Node *rexpr = transformExpr(pstate, a->rexpr, precedence);
630                 result = (Node *)make_op(a->opname, lexpr, rexpr);
631             }
632             break;
633         case ISNULL:
634             {
635                 Node *lexpr = transformExpr(pstate, a->lexpr, precedence);
636                 result = ParseFunc(pstate, 
637                                    "NullValue", lcons(lexpr, NIL),
638                                    &pstate->p_last_resno);
639             }
640             break;
641         case NOTNULL:
642             {
643                 Node *lexpr = transformExpr(pstate, a->lexpr, precedence);
644                 result = ParseFunc(pstate,
645                                    "NonNullValue", lcons(lexpr, NIL),
646                                    &pstate->p_last_resno);
647             }
648             break;
649         case AND:
650             {
651                 Expr *expr = makeNode(Expr);
652                 Node *lexpr = transformExpr(pstate, a->lexpr, precedence);
653                 Node *rexpr = transformExpr(pstate, a->rexpr, precedence);
654                 if (exprType(lexpr) != BOOLOID)
655                     elog(WARN,
656                          "left-hand side of AND is type '%s', not bool",
657                          tname(get_id_type(exprType(lexpr))));
658                 if (exprType(rexpr) != BOOLOID)
659                     elog(WARN,
660                          "right-hand side of AND is type '%s', not bool",
661                          tname(get_id_type(exprType(rexpr))));
662                 expr->typeOid = BOOLOID;
663                 expr->opType = AND_EXPR;
664                 expr->args = makeList(lexpr, rexpr, -1);
665                 result = (Node *)expr;
666             }
667             break;
668         case OR:
669             {
670                 Expr *expr = makeNode(Expr);
671                 Node *lexpr = transformExpr(pstate, a->lexpr, precedence);
672                 Node *rexpr = transformExpr(pstate, a->rexpr, precedence);
673                 if (exprType(lexpr) != BOOLOID)
674                     elog(WARN,
675                          "left-hand side of OR is type '%s', not bool",
676                          tname(get_id_type(exprType(lexpr))));
677                 if (exprType(rexpr) != BOOLOID)
678                     elog(WARN,
679                          "right-hand side of OR is type '%s', not bool",
680                          tname(get_id_type(exprType(rexpr))));
681                 expr->typeOid = BOOLOID;
682                 expr->opType = OR_EXPR;
683                 expr->args = makeList(lexpr, rexpr, -1);
684                 result = (Node *)expr;
685             }
686             break;
687         case NOT:
688             {
689                 Expr *expr = makeNode(Expr);
690                 Node *rexpr = transformExpr(pstate, a->rexpr, precedence);
691                 if (exprType(rexpr) != BOOLOID)
692                     elog(WARN,
693                          "argument to NOT is type '%s', not bool",
694                          tname(get_id_type(exprType(rexpr))));
695                 expr->typeOid = BOOLOID;
696                 expr->opType = NOT_EXPR;
697                 expr->args = makeList(rexpr, -1);
698                 result = (Node *)expr;
699             }
700             break;
701         }
702         break;
703     }
704     case T_Ident: {
705         /* look for a column name or a relation name (the default behavior) */
706         result = transformIdent(pstate, expr, precedence);
707         break;
708     }
709     case T_FuncCall: {
710         FuncCall *fn = (FuncCall *)expr;
711         List *args;
712
713         /* transform the list of arguments */
714         foreach(args, fn->args)
715             lfirst(args) = transformExpr(pstate, (Node*)lfirst(args), precedence);
716         result = ParseFunc(pstate,
717                            fn->funcname, fn->args, &pstate->p_last_resno);
718         break;
719     }
720     default:
721         /* should not reach here */
722         elog(WARN, "transformExpr: does not know how to transform %d\n",
723              nodeTag(expr));
724         break;
725     }
726
727     return result;
728 }
729
730 static Node *
731 transformIdent(ParseState *pstate, Node *expr, int precedence)
732 {
733     Ident *ident = (Ident*)expr;
734     RangeTblEntry *rte;
735     Node *column_result, *relation_result, *result;
736
737     column_result = relation_result = result = 0;
738     /* try to find the ident as a column */
739     if ((rte = colnameRangeTableEntry(pstate, ident->name)) != NULL) {
740         Attr *att = makeNode(Attr);
741         
742         att->relname = rte->refname;
743         att->attrs = lcons(makeString(ident->name), NIL);
744         column_result =
745             (Node*)handleNestedDots(pstate, att, &pstate->p_last_resno);
746     }
747
748     /* try to find the ident as a relation */
749     if (refnameRangeTableEntry(pstate->p_rtable, ident->name) != NULL) {
750         ident->isRel = TRUE;
751         relation_result = (Node*)ident;
752     }
753
754     /* choose the right result based on the precedence */
755     if(precedence == EXPR_COLUMN_FIRST) {
756         if(column_result)
757             result = column_result;
758         else
759             result = relation_result;
760     } else {
761         if(relation_result)
762             result = relation_result;
763         else
764             result = column_result;
765     }
766
767     if(result == NULL) 
768         elog(WARN, "attribute \"%s\" not found", ident->name);
769    
770     return result;
771 }
772
773 /*****************************************************************************
774  *
775  * From Clause
776  *
777  *****************************************************************************/
778
779 /*
780  * parseFromClause -
781  *    turns the table references specified in the from-clause into a
782  *    range table. The range table may grow as we transform the expressions
783  *    in the target list. (Note that this happens because in POSTQUEL, we
784  *    allow references to relations not specified in the from-clause. We
785  *    also allow that in our POST-SQL)
786  *
787  */
788 static void
789 parseFromClause(ParseState *pstate, List *frmList)
790 {
791     List *fl;
792
793     foreach(fl, frmList)
794     {
795         RangeVar *r = lfirst(fl);
796         RelExpr *baserel = r->relExpr;
797         char *relname = baserel->relname;
798         char *refname = r->name;
799         RangeTblEntry *rte;
800         
801         if (refname==NULL)
802             refname = relname;
803
804         /*
805          * marks this entry to indicate it comes from the FROM clause. In
806          * SQL, the target list can only refer to range variables specified
807          * in the from clause but we follow the more powerful POSTQUEL
808          * semantics and automatically generate the range variable if not
809          * specified. However there are times we need to know whether the
810          * entries are legitimate.
811          *
812          * eg. select * from foo f where f.x = 1; will generate wrong answer
813          *     if we expand * to foo.x.
814          */
815         rte = addRangeTableEntry(pstate, relname, refname, baserel->inh, TRUE,
816                                   baserel->timeRange);
817     }
818 }
819
820 /*
821  * makeRangeTable -
822  *    make a range table with the specified relation (optional) and the
823  *    from-clause.
824  */
825 static void
826 makeRangeTable(ParseState *pstate, char *relname, List *frmList)
827 {
828     RangeTblEntry *rte;
829
830     parseFromClause(pstate, frmList);
831
832     if (relname == NULL)
833         return;
834     
835     if (refnameRangeTablePosn(pstate->p_rtable, relname) < 1)
836         rte = addRangeTableEntry(pstate, relname, relname, FALSE, FALSE, NULL);
837     else
838         rte = refnameRangeTableEntry(pstate->p_rtable, relname);
839
840     pstate->p_target_rangetblentry = rte;
841     Assert(pstate->p_target_relation == NULL);
842     pstate->p_target_relation = heap_open(rte->relid);
843     Assert(pstate->p_target_relation != NULL);
844         /* will close relation later */
845 }
846
847 /*
848  *  exprType -
849  *    returns the Oid of the type of the expression. (Used for typechecking.)
850  */
851 Oid
852 exprType(Node *expr)
853 {
854     Oid type = (Oid)0;
855     
856     switch(nodeTag(expr)) {
857     case T_Func:
858         type = ((Func*)expr)->functype;
859         break;
860     case T_Iter:
861         type = ((Iter*)expr)->itertype;
862         break;
863     case T_Var:
864         type = ((Var*)expr)->vartype;
865         break;
866     case T_Expr:
867         type = ((Expr*)expr)->typeOid;
868         break;
869     case T_Const:
870         type = ((Const*)expr)->consttype;
871         break;
872     case T_ArrayRef:
873         type = ((ArrayRef*)expr)->refelemtype;
874         break;
875     case T_Aggreg:
876         type = ((Aggreg*)expr)->aggtype;
877         break;
878     case T_Param:
879         type = ((Param*)expr)->paramtype;
880         break;
881     case T_Ident:
882         /* is this right? */
883         type = UNKNOWNOID;
884         break;
885     default:
886         elog(WARN, "exprType: don't know how to get type for %d node",
887              nodeTag(expr));
888         break;
889     }
890     return type;
891 }
892
893 /*
894  * expandAllTables -
895  *    turns '*' (in the target list) into a list of attributes (of all
896  *    relations in the range table)
897  */
898 static List *
899 expandAllTables(ParseState *pstate)
900 {
901     List *target= NIL;
902     List *legit_rtable=NIL;
903     List *rt, *rtable;
904
905     rtable = pstate->p_rtable;
906     if (pstate->p_is_rule) {
907         /*
908          * skip first two entries, "*new*" and "*current*"
909          */
910         rtable = lnext(lnext(pstate->p_rtable));
911     }
912     
913     /* this should not happen */
914     if (rtable==NULL) 
915         elog(WARN, "cannot expand: null p_rtable");
916
917     /* 
918      * go through the range table and make a list of range table entries
919      * which we will expand.
920      */
921     foreach(rt, rtable) {
922         RangeTblEntry *rte = lfirst(rt);
923
924         /*
925          * we only expand those specify in the from clause. (This will
926          * also prevent us from using the wrong table in inserts: eg. tenk2
927          * in "insert into tenk2 select * from tenk1;")
928          */
929         if (!rte->inFromCl)
930             continue;
931         legit_rtable = lappend(legit_rtable, rte);
932     }
933
934     foreach(rt, legit_rtable) {
935         RangeTblEntry *rte = lfirst(rt);
936         List *temp = target;
937         
938         if(temp == NIL )
939             target = expandAll(pstate, rte->relname, rte->refname,
940                                                         &pstate->p_last_resno);
941         else {
942             while (temp != NIL && lnext(temp) != NIL)
943                 temp = lnext(temp);
944             lnext(temp) = expandAll(pstate, rte->relname, rte->refname,
945                                                         &pstate->p_last_resno);
946         }
947     }
948     return target;
949 }
950
951
952 /*
953  * figureColname -
954  *    if the name of the resulting column is not specified in the target
955  *    list, we have to guess.
956  *
957  */
958 static char *
959 figureColname(Node *expr, Node *resval)
960 {
961     switch (nodeTag(expr)) {
962     case T_Aggreg:
963         return (char*) /* XXX */
964             ((Aggreg *)expr)->aggname;
965     case T_Expr:
966         if (((Expr*)expr)->opType == FUNC_EXPR) {
967             if (nodeTag(resval)==T_FuncCall)
968                 return ((FuncCall*)resval)->funcname;
969         }
970         break;
971     default:
972         break;
973     }
974         
975     return "?column?";
976 }
977
978 /*****************************************************************************
979  *
980  * Target list
981  *
982  *****************************************************************************/
983
984 /*
985  * makeTargetNames -
986  *    generate a list of column names if not supplied or
987  *    test supplied column names to make sure they are in target table
988  *    (used exclusively for inserts)
989  */
990 static List *
991 makeTargetNames(ParseState *pstate, List *cols)
992 {
993     List *tl=NULL;
994
995         /* Generate ResTarget if not supplied */
996         
997     if (cols == NIL) {
998         int numcol;
999         int i;
1000         AttributeTupleForm *attr = pstate->p_target_relation->rd_att->attrs;
1001         
1002         numcol = pstate->p_target_relation->rd_rel->relnatts;
1003         for(i=0; i < numcol; i++) {
1004             Ident *id = makeNode(Ident);
1005
1006             id->name = palloc(NAMEDATALEN+1);
1007             strncpy(id->name, attr[i]->attname.data, NAMEDATALEN);
1008             id->name[NAMEDATALEN]='\0';
1009             id->indirection = NIL;
1010             id->isRel = false;
1011             if (tl == NIL)
1012                 cols = tl = lcons(id, NIL);
1013             else {
1014                 lnext(tl) = lcons(id,NIL);
1015                 tl = lnext(tl);
1016             }
1017         }
1018     }
1019     else
1020         foreach(tl, cols)
1021                         /* elog on failure */
1022          (void)varattno(pstate->p_target_relation,((Ident *)lfirst(tl))->name);
1023
1024     return cols;
1025 }
1026
1027 /*
1028  * transformTargetList -
1029  *    turns a list of ResTarget's into a list of TargetEntry's
1030  */
1031 static List *
1032 transformTargetList(ParseState *pstate, List *targetlist)
1033 {
1034     List *p_target= NIL;
1035     List *tail_p_target = NIL;
1036
1037     while(targetlist != NIL) {
1038         ResTarget *res= (ResTarget *)lfirst(targetlist);
1039         TargetEntry *tent = makeNode(TargetEntry);
1040
1041         switch(nodeTag(res->val)) {
1042         case T_Ident: {
1043             Node *expr;
1044             Oid type_id;
1045             int type_len;
1046             char *identname;
1047             char *resname;
1048             
1049             identname = ((Ident*)res->val)->name;
1050             handleTargetColname(pstate, &res->name, NULL, res->name);
1051
1052             /* here we want to look for column names only, not relation */
1053             /* names (even though they can be stored in Ident nodes,    */
1054             /* too)                                                     */
1055             expr = transformIdent(pstate, (Node*)res->val, EXPR_COLUMN_FIRST);
1056             type_id = exprType(expr);
1057             type_len = tlen(get_id_type(type_id));
1058             resname = (res->name) ? res->name : identname;
1059             tent->resdom = makeResdom((AttrNumber)pstate->p_last_resno++,
1060                                       (Oid)type_id,
1061                                       (Size)type_len,
1062                                       resname,
1063                                       (Index)0,
1064                                       (Oid)0,
1065                                       0);
1066                                       
1067             tent->expr = expr;
1068             break;
1069         }
1070         case T_ParamNo:
1071         case T_FuncCall:
1072         case T_A_Const:    
1073         case T_A_Expr: {
1074             Node *expr = transformExpr(pstate, (Node *)res->val, EXPR_COLUMN_FIRST);
1075
1076             handleTargetColname(pstate, &res->name, NULL, NULL);
1077             /* note indirection has not been transformed */
1078             if (pstate->p_is_insert && res->indirection!=NIL) {
1079                 /* this is an array assignment */
1080                 char *val;
1081                 char *str, *save_str;
1082                 List *elt;
1083                 int i = 0, ndims;
1084                 int lindx[MAXDIM], uindx[MAXDIM];
1085                 int resdomno;
1086                 Relation rd;
1087                 Value *constval;
1088                 
1089                 if (exprType(expr) != UNKNOWNOID ||
1090                     !IsA(expr,Const))
1091                     elog(WARN, "yyparse: string constant expected");
1092
1093                 val = (char *) textout((struct varlena *)
1094                                        ((Const *)expr)->constvalue);
1095                 str = save_str = (char*)palloc(strlen(val) + MAXDIM * 25 + 2);
1096                 foreach(elt, res->indirection) {
1097                     A_Indices *aind = (A_Indices *)lfirst(elt);
1098                     aind->uidx = transformExpr(pstate, aind->uidx, EXPR_COLUMN_FIRST);
1099                     if (!IsA(aind->uidx,Const)) 
1100                         elog(WARN,
1101                              "Array Index for Append should be a constant");
1102                     uindx[i] = ((Const *)aind->uidx)->constvalue;
1103                     if (aind->lidx!=NULL) {
1104                         aind->lidx = transformExpr(pstate, aind->lidx, EXPR_COLUMN_FIRST);
1105                         if (!IsA(aind->lidx,Const))
1106                             elog(WARN,
1107                                 "Array Index for Append should be a constant");
1108                         lindx[i] = ((Const*)aind->lidx)->constvalue;
1109                     }else {
1110                         lindx[i] = 1;
1111                     }
1112                     if (lindx[i] > uindx[i]) 
1113                         elog(WARN, "yyparse: lower index cannot be greater than upper index");
1114                     sprintf(str, "[%d:%d]", lindx[i], uindx[i]);
1115                     str += strlen(str);
1116                     i++;
1117                 }
1118                 sprintf(str, "=%s", val);
1119                 rd = pstate->p_target_relation;
1120                 Assert(rd != NULL);
1121                 resdomno = varattno(rd, res->name);
1122                 ndims = att_attnelems(rd, resdomno);
1123                 if (i != ndims)
1124                     elog(WARN, "yyparse: array dimensions do not match");
1125                 constval = makeNode(Value);
1126                 constval->type = T_String;
1127                 constval->val.str = save_str;
1128                 tent = make_targetlist_expr(pstate, res->name,
1129                                             (Node*)make_const(constval),
1130                                             NULL);
1131                 pfree(save_str);
1132             } else {
1133                 char *colname= res->name;
1134                 /* this is not an array assignment */
1135                 if (colname==NULL) {
1136                     /* if you're wondering why this is here, look at
1137                      * the yacc grammar for why a name can be missing. -ay
1138                      */
1139                     colname = figureColname(expr, res->val);
1140                 }
1141                 if (res->indirection) {
1142                     List *ilist = res->indirection;
1143                     while (ilist!=NIL) {
1144                         A_Indices *ind = lfirst(ilist);
1145                         ind->lidx = transformExpr(pstate, ind->lidx, EXPR_COLUMN_FIRST);
1146                         ind->uidx = transformExpr(pstate, ind->uidx, EXPR_COLUMN_FIRST);
1147                         ilist = lnext(ilist);
1148                     }
1149                 }
1150                 res->name = colname;
1151                 tent = make_targetlist_expr(pstate, res->name, expr, 
1152                                             res->indirection);
1153             }
1154             break;
1155         }
1156         case T_Attr: {
1157             Oid type_id;
1158             int type_len;
1159             Attr *att = (Attr *)res->val;
1160             Node *result;
1161             char *attrname;
1162             char *resname;
1163             Resdom *resnode;
1164             List *attrs = att->attrs;
1165
1166             /*
1167              * Target item is a single '*', expand all tables
1168              * (eg. SELECT * FROM emp)
1169              */
1170             if (att->relname!=NULL && !strcmp(att->relname, "*")) {
1171                 if (tail_p_target == NIL)
1172                     p_target = tail_p_target = expandAllTables(pstate);
1173                 else
1174                     lnext(tail_p_target) = expandAllTables(pstate);
1175
1176                 while(lnext(tail_p_target)!=NIL)
1177                         /* make sure we point to the last target entry */
1178                     tail_p_target = lnext(tail_p_target);
1179                 /*
1180                  * skip rest of while loop
1181                  */
1182                 targetlist = lnext(targetlist);
1183                 continue;
1184             }
1185
1186             /*
1187              * Target item is relation.*, expand the table
1188              * (eg. SELECT emp.*, dname FROM emp, dept)
1189              */
1190             attrname = strVal(lfirst(att->attrs));
1191             if (att->attrs!=NIL && !strcmp(attrname,"*")) {
1192                 /* tail_p_target is the target list we're building in the while
1193                  * loop. Make sure we fix it after appending more nodes.
1194                  */
1195                 if (tail_p_target == NIL)
1196                     p_target = tail_p_target = expandAll(pstate, att->relname,
1197                                         att->relname, &pstate->p_last_resno);
1198                 else
1199                     lnext(tail_p_target) =
1200                         expandAll(pstate, att->relname, att->relname,
1201                                                         &pstate->p_last_resno);
1202                 while(lnext(tail_p_target)!=NIL)
1203                         /* make sure we point to the last target entry */
1204                     tail_p_target = lnext(tail_p_target);
1205                 /*
1206                  * skip the rest of the while loop
1207                  */
1208                 targetlist = lnext(targetlist);
1209                 continue; 
1210             }
1211
1212
1213             /*
1214              * Target item is fully specified: ie. relation.attribute
1215              */
1216             result = handleNestedDots(pstate, att, &pstate->p_last_resno);
1217             handleTargetColname(pstate, &res->name, att->relname, attrname);
1218             if (att->indirection != NIL) {
1219                 List *ilist = att->indirection;
1220                 while (ilist!=NIL) {
1221                     A_Indices *ind = lfirst(ilist);
1222                     ind->lidx = transformExpr(pstate, ind->lidx, EXPR_COLUMN_FIRST);
1223                     ind->uidx = transformExpr(pstate, ind->uidx, EXPR_COLUMN_FIRST);
1224                     ilist = lnext(ilist);
1225                 }
1226                 result = (Node*)make_array_ref(result, att->indirection);
1227             }
1228             type_id = exprType(result);
1229             type_len = tlen(get_id_type(type_id));
1230                 /* move to last entry */
1231             while(lnext(attrs)!=NIL)
1232                 attrs=lnext(attrs);
1233             resname = (res->name) ? res->name : strVal(lfirst(attrs));
1234             resnode = makeResdom((AttrNumber)pstate->p_last_resno++,
1235                                  (Oid)type_id,
1236                                  (Size)type_len,
1237                                  resname,
1238                                  (Index)0,
1239                                  (Oid)0,
1240                                  0);
1241             tent->resdom = resnode;
1242             tent->expr = result;
1243             break;
1244         }
1245         default:
1246             /* internal error */
1247             elog(WARN,
1248                  "internal error: do not know how to transform targetlist");
1249             break;
1250         }
1251
1252         if (p_target == NIL) {
1253             p_target = tail_p_target = lcons(tent, NIL);
1254         }else {
1255             lnext(tail_p_target) = lcons(tent, NIL);
1256             tail_p_target = lnext(tail_p_target);
1257         }
1258         targetlist = lnext(targetlist);
1259     }
1260
1261     return p_target;
1262 }
1263
1264
1265 /*
1266  * make_targetlist_expr -
1267  *    make a TargetEntry from an expression
1268  *
1269  * arrayRef is a list of transformed A_Indices
1270  */
1271 static TargetEntry *
1272 make_targetlist_expr(ParseState *pstate,
1273                      char *colname,
1274                      Node *expr,
1275                      List *arrayRef)
1276 {
1277      Oid type_id, attrtype;
1278      int type_len, attrlen;
1279      int resdomno;
1280      Relation rd;
1281      bool attrisset;
1282      TargetEntry *tent;
1283      Resdom *resnode;
1284      
1285      if (expr == NULL)
1286          elog(WARN, "make_targetlist_expr: invalid use of NULL expression");
1287
1288      type_id = exprType(expr);
1289      if (type_id == InvalidOid) {
1290          type_len = 0;
1291      } else
1292      type_len = tlen(get_id_type(type_id));
1293
1294      /* I have no idea what the following does! */
1295      /* It appears to process target columns that will be receiving results */
1296      if (pstate->p_is_insert||pstate->p_is_update) {
1297           /*
1298            * append or replace query -- 
1299            * append, replace work only on one relation,
1300            * so multiple occurence of same resdomno is bogus
1301            */
1302           rd = pstate->p_target_relation;
1303           Assert(rd != NULL);
1304           resdomno = varattno(rd,colname);
1305           attrisset = varisset(rd,colname);
1306           attrtype = att_typeid(rd,resdomno);
1307           if ((arrayRef != NIL) && (lfirst(arrayRef) == NIL))
1308                attrtype = GetArrayElementType(attrtype);
1309           if (attrtype==BPCHAROID || attrtype==VARCHAROID) {
1310               attrlen = rd->rd_att->attrs[resdomno-1]->attlen;
1311           } else {
1312               attrlen = tlen(get_id_type(attrtype));
1313           }
1314 #if 0
1315           if(Input_is_string && Typecast_ok){
1316                Datum val;
1317                if (type_id == typeid(type("unknown"))){
1318                     val = (Datum)textout((struct varlena *)
1319                                          ((Const)lnext(expr))->constvalue);
1320                }else{
1321                     val = ((Const)lnext(expr))->constvalue;
1322                }
1323                if (attrisset) {
1324                     lnext(expr) =  makeConst(attrtype,
1325                                            attrlen,
1326                                            val,
1327                                            false,
1328                                            true,
1329                                            true, /* is set */
1330                                            false);
1331                } else {
1332                     lnext(expr) = 
1333                          makeConst(attrtype, 
1334                                    attrlen,
1335                                    (Datum)fmgr(typeid_get_retinfunc(attrtype),
1336                                                val,get_typelem(attrtype),-1),
1337                                    false, 
1338                                    true /* Maybe correct-- 80% chance */,
1339                                    false, /* is not a set */
1340                                    false);
1341                }
1342           } else if((Typecast_ok) && (attrtype != type_id)){
1343                lnext(expr) = 
1344                     parser_typecast2(expr, get_id_type(attrtype));
1345           } else
1346                if (attrtype != type_id) {
1347                     if ((attrtype == INT2OID) && (type_id == INT4OID))
1348                          lfirst(expr) = lispInteger (INT2OID);
1349                     else if ((attrtype == FLOAT4OID) && (type_id == FLOAT8OID))
1350                          lfirst(expr) = lispInteger (FLOAT4OID);
1351                     else
1352                          elog(WARN, "unequal type in tlist : %s \n",
1353                               colname));
1354                }
1355           
1356           Input_is_string = false;
1357           Input_is_integer = false;
1358           Typecast_ok = true;
1359 #endif
1360
1361           if (attrtype != type_id) {
1362               if (IsA(expr,Const)) {
1363                   /* try to cast the constant */
1364                   if (arrayRef && !(((A_Indices *)lfirst(arrayRef))->lidx)) {
1365                       /* updating a single item */
1366                       Oid typelem = get_typelem(attrtype);
1367                       expr = (Node*)parser_typecast2(expr,
1368                                                    type_id,
1369                                                    get_id_type(typelem),
1370                                                    attrlen);
1371                   } else
1372                   expr = (Node*)parser_typecast2(expr,
1373                                                  type_id,
1374                                                  get_id_type(attrtype),
1375                                                  attrlen);
1376               } else {
1377                   /* currently, we can't handle casting of expressions */
1378                   elog(WARN, "parser: attribute '%s' is of type '%.*s' but expression is of type '%.*s'",
1379                        colname,
1380                        NAMEDATALEN, get_id_typname(attrtype),
1381                        NAMEDATALEN, get_id_typname(type_id));
1382               }
1383           }
1384
1385           if (arrayRef != NIL) {
1386                Expr *target_expr;
1387                Attr *att = makeNode(Attr);
1388                List *ar = arrayRef;
1389                List *upperIndexpr = NIL;
1390                List *lowerIndexpr = NIL;
1391
1392                att->relname = pstrdup(RelationGetRelationName(rd)->data);
1393                att->attrs = lcons(makeString(colname), NIL);
1394                target_expr = (Expr*)handleNestedDots(pstate, att,
1395                                                      &pstate->p_last_resno);
1396                while(ar!=NIL) {
1397                    A_Indices *ind = lfirst(ar);
1398                    if (lowerIndexpr || (!upperIndexpr && ind->lidx)) {
1399                        /* XXX assume all lowerIndexpr is non-null in
1400                         * this case
1401                         */
1402                        lowerIndexpr = lappend(lowerIndexpr, ind->lidx);
1403                    }
1404                    upperIndexpr = lappend(upperIndexpr, ind->uidx);
1405                    ar = lnext(ar);
1406                }
1407                
1408                expr = (Node*)make_array_set(target_expr,
1409                                             upperIndexpr,
1410                                             lowerIndexpr,
1411                                             (Expr*)expr);       
1412                attrtype = att_typeid(rd,resdomno);
1413                attrlen = tlen(get_id_type(attrtype)); 
1414           }
1415      } else {
1416           resdomno = pstate->p_last_resno++;
1417           attrtype = type_id;
1418           attrlen = type_len;
1419      }
1420      tent = makeNode(TargetEntry);
1421
1422      resnode = makeResdom((AttrNumber)resdomno,
1423                           (Oid) attrtype,
1424                           (Size) attrlen,
1425                           colname, 
1426                           (Index)0,
1427                           (Oid)0,
1428                           0);
1429
1430      tent->resdom = resnode;
1431      tent->expr = expr;
1432          
1433      return  tent;
1434 }
1435
1436
1437 /*****************************************************************************
1438  *
1439  * Where Clause
1440  *
1441  *****************************************************************************/
1442
1443 /*
1444  * transformWhereClause -
1445  *    transforms the qualification and make sure it is of type Boolean
1446  *
1447  */
1448 static Node *
1449 transformWhereClause(ParseState *pstate, Node *a_expr)
1450 {
1451     Node *qual;
1452
1453     if (a_expr == NULL)
1454         return (Node *)NULL;            /* no qualifiers */
1455
1456     inWhereClause = true;
1457     qual = transformExpr(pstate, a_expr, EXPR_COLUMN_FIRST);
1458     inWhereClause = false;
1459     if (exprType(qual) != BOOLOID) {
1460         elog(WARN,
1461              "where clause must return type bool, not %s",
1462              tname(get_id_type(exprType(qual))));
1463     }
1464     return qual;
1465 }
1466
1467 /*****************************************************************************
1468  *
1469  * Sort Clause
1470  *
1471  *****************************************************************************/
1472
1473 /*
1474  *  find_targetlist_entry -
1475  *    returns the Resdom in the target list matching the specified varname
1476  *    and range
1477  *
1478  */
1479 static TargetEntry *
1480 find_targetlist_entry(ParseState *pstate, SortGroupBy *sortgroupby, List *tlist)
1481 {
1482     List *i;
1483     int real_rtable_pos = 0, target_pos = 0;
1484     TargetEntry *target_result = NULL;
1485     
1486     if(sortgroupby->range)
1487         real_rtable_pos = refnameRangeTablePosn(pstate->p_rtable,
1488                                                         sortgroupby->range);
1489
1490     foreach(i, tlist) {
1491         TargetEntry *target = (TargetEntry *)lfirst(i);
1492         Resdom *resnode = target->resdom;
1493         Var *var = (Var *)target->expr;
1494         char *resname = resnode->resname;
1495         int test_rtable_pos = var->varno;
1496
1497         if (!sortgroupby->name) {
1498             if (sortgroupby->resno == ++target_pos) {
1499                 target_result = target;
1500                 break;
1501             }
1502         }
1503         else {
1504             if (!strcmp(resname, sortgroupby->name)) {
1505                 if(sortgroupby->range) {
1506                     if(real_rtable_pos == test_rtable_pos) {
1507                         if (target_result != NULL)
1508                             elog(WARN, "Order/Group By %s is ambiguous", sortgroupby->name);
1509                         else    target_result = target;
1510                     }
1511                 }                       
1512                 else {
1513                     if (target_result != NULL)
1514                         elog(WARN, "Order/Group By %s is ambiguous", sortgroupby->name);
1515                     else        target_result = target;
1516                 }
1517             }
1518         }
1519     }
1520     return target_result;
1521 }
1522
1523 static Oid
1524 any_ordering_op(int restype)
1525 {
1526     Operator order_op;
1527     Oid order_opid;
1528     
1529     order_op = oper("<",restype,restype,false);
1530     order_opid = oprid(order_op);
1531     
1532     return order_opid;
1533 }
1534
1535 /*
1536  * transformGroupClause -
1537  *    transform an Group By clause
1538  *
1539  */
1540 static List *
1541 transformGroupClause(ParseState *pstate, List *grouplist, List *targetlist)
1542 {
1543     List *glist = NIL, *gl = NIL;
1544
1545     while (grouplist != NIL) {
1546         GroupClause *grpcl = makeNode(GroupClause);
1547         TargetEntry *restarget;
1548         Resdom *resdom;
1549
1550         restarget = find_targetlist_entry(pstate, lfirst(grouplist), targetlist);
1551
1552         if (restarget == NULL)
1553             elog(WARN,"The field being grouped by must appear in the target list");
1554
1555         grpcl->resdom = resdom = restarget->resdom;
1556         grpcl->grpOpoid = oprid(oper("<",
1557                                    resdom->restype,
1558                                    resdom->restype,false));
1559         if (glist == NIL)
1560             gl = glist = lcons(grpcl, NIL);
1561         else {
1562             lnext(gl) = lcons(grpcl, NIL);
1563             gl = lnext(gl);
1564         }
1565         grouplist = lnext(grouplist);
1566     }
1567
1568     return glist;
1569 }
1570
1571 /*
1572  * transformSortClause -
1573  *    transform an Order By clause
1574  *
1575  */
1576 static List *
1577 transformSortClause(ParseState *pstate,
1578                     List *orderlist, List *targetlist,
1579                     char* uniqueFlag)
1580 {
1581     List *sortlist = NIL;
1582     List *s = NIL, *i;
1583
1584     while(orderlist != NIL) {
1585         SortGroupBy *sortby = lfirst(orderlist);
1586         SortClause *sortcl = makeNode(SortClause);
1587         TargetEntry *restarget;
1588         Resdom *resdom;
1589
1590         restarget = find_targetlist_entry(pstate, sortby, targetlist);
1591         if (restarget == NULL)
1592             elog(WARN,"The field being ordered by must appear in the target list");
1593
1594         sortcl->resdom = resdom = restarget->resdom;
1595         sortcl->opoid = oprid(oper(sortby->useOp,
1596                                    resdom->restype,
1597                                    resdom->restype,false));
1598         if (sortlist == NIL) {
1599             s = sortlist = lcons(sortcl, NIL);
1600         }else {
1601             lnext(s) = lcons(sortcl, NIL);
1602             s = lnext(s);
1603         }
1604         orderlist = lnext(orderlist);
1605     }
1606     
1607     if (uniqueFlag) {
1608       if (uniqueFlag[0] == '*') {
1609         /* concatenate all elements from target list
1610            that are not already in the sortby list */
1611         foreach (i,targetlist) {
1612             TargetEntry *tlelt = (TargetEntry *)lfirst(i);
1613
1614             s = sortlist;
1615             while(s != NIL) {
1616                 SortClause *sortcl = lfirst(s);
1617                 if (sortcl->resdom==tlelt->resdom)
1618                     break;
1619                 s = lnext(s);
1620             }
1621             if (s == NIL) {
1622                 /* not a member of the sortclauses yet */
1623                 SortClause *sortcl = makeNode(SortClause);
1624                 
1625                 sortcl->resdom = tlelt->resdom;
1626                 sortcl->opoid = any_ordering_op(tlelt->resdom->restype);
1627
1628                 sortlist = lappend(sortlist, sortcl);
1629               }
1630           }
1631       }
1632       else {
1633         TargetEntry *tlelt = NULL;
1634         char* uniqueAttrName = uniqueFlag;
1635
1636           /* only create sort clause with the specified unique attribute */
1637           foreach (i, targetlist) {
1638             tlelt = (TargetEntry*)lfirst(i);
1639             if (strcmp(tlelt->resdom->resname, uniqueAttrName) == 0)
1640               break;
1641           }
1642           if (i == NIL) {
1643             elog(WARN, "The field specified in the UNIQUE ON clause is not in the targetlist");
1644           }
1645           s = sortlist;
1646           foreach (s, sortlist) {
1647             SortClause *sortcl = lfirst(s);
1648             if (sortcl->resdom == tlelt->resdom)
1649               break;
1650           }
1651           if (s == NIL) { 
1652                 /* not a member of the sortclauses yet */
1653                 SortClause *sortcl = makeNode(SortClause);
1654                 
1655                 sortcl->resdom = tlelt->resdom;
1656                 sortcl->opoid = any_ordering_op(tlelt->resdom->restype);
1657
1658                 sortlist = lappend(sortlist, sortcl);
1659               }
1660         }
1661
1662     }
1663     
1664     return sortlist;
1665 }
1666
1667 /*
1668  ** HandleNestedDots --
1669  **    Given a nested dot expression (i.e. (relation func ... attr), build up
1670  ** a tree with of Iter and Func nodes.
1671  */
1672 static Node*
1673 handleNestedDots(ParseState *pstate, Attr *attr, int *curr_resno)
1674 {
1675     List *mutator_iter;
1676     Node *retval = NULL;
1677     
1678     if (attr->paramNo != NULL) {
1679         Param *param = (Param *)transformExpr(pstate, (Node*)attr->paramNo, EXPR_RELATION_FIRST);
1680
1681         retval = 
1682             ParseFunc(pstate, strVal(lfirst(attr->attrs)),
1683                       lcons(param, NIL),
1684                       curr_resno);
1685     } else {
1686         Ident *ident = makeNode(Ident);
1687
1688         ident->name = attr->relname;
1689         ident->isRel = TRUE;
1690         retval =
1691             ParseFunc(pstate, strVal(lfirst(attr->attrs)),
1692                       lcons(ident, NIL),
1693                       curr_resno);
1694     }
1695     
1696     foreach (mutator_iter, lnext(attr->attrs)) {
1697         retval = ParseFunc(pstate,strVal(lfirst(mutator_iter)), 
1698                            lcons(retval, NIL),
1699                            curr_resno);
1700     }
1701     
1702     return(retval);
1703 }
1704
1705 /*
1706  ** make_arguments --
1707  **   Given the number and types of arguments to a function, and the 
1708  **   actual arguments and argument types, do the necessary typecasting.
1709  */
1710 static void
1711 make_arguments(int nargs,
1712                List *fargs,
1713                Oid *input_typeids,
1714                Oid *function_typeids)
1715 {
1716     /*
1717      * there are two ways an input typeid can differ from a function typeid :
1718      * either the input type inherits the function type, so no typecasting is
1719      * necessary, or the input type can be typecast into the function type.
1720      * right now, we only typecast unknowns, and that is all we check for.
1721      */
1722     
1723     List *current_fargs;
1724     int i;
1725     
1726     for (i=0, current_fargs = fargs;
1727          i<nargs;
1728          i++, current_fargs = lnext(current_fargs)) {
1729
1730         if (input_typeids[i] == UNKNOWNOID && function_typeids[i] != InvalidOid) {
1731             lfirst(current_fargs) =
1732                 parser_typecast2(lfirst(current_fargs),
1733                                  input_typeids[i],
1734                                  get_id_type(function_typeids[i]),
1735                                  -1);
1736         }
1737     }
1738 }
1739
1740 /*
1741  ** setup_tlist --
1742  **     Build a tlist that says which attribute to project to.
1743  **     This routine is called by ParseFunc() to set up a target list
1744  **     on a tuple parameter or return value.  Due to a bug in 4.0,
1745  **     it's not possible to refer to system attributes in this case.
1746  */
1747 static List *
1748 setup_tlist(char *attname, Oid relid)
1749 {
1750     TargetEntry *tle;
1751     Resdom *resnode;
1752     Var *varnode;
1753     Oid typeid;
1754     int attno;
1755     
1756     attno = get_attnum(relid, attname);
1757     if (attno < 0)
1758         elog(WARN, "cannot reference attribute %s of tuple params/return values for functions", attname);
1759     
1760     typeid = find_atttype(relid, attname);
1761     resnode = makeResdom(1,
1762                          typeid,
1763                          tlen(get_id_type(typeid)),
1764                          get_attname(relid, attno),
1765                          0,
1766                          (Oid)0,
1767                          0);
1768     varnode = makeVar(-1, attno, typeid, -1, attno);
1769
1770     tle = makeNode(TargetEntry);
1771     tle->resdom = resnode;
1772     tle->expr = (Node*)varnode;
1773     return (lcons(tle, NIL));
1774 }
1775
1776 /*
1777  ** setup_base_tlist --
1778  **     Build a tlist that extracts a base type from the tuple
1779  **     returned by the executor.
1780  */
1781 static List *
1782 setup_base_tlist(Oid typeid)
1783 {
1784     TargetEntry *tle;
1785     Resdom *resnode;
1786     Var *varnode;
1787     
1788     resnode = makeResdom(1,
1789                          typeid,
1790                          tlen(get_id_type(typeid)),
1791                          "<noname>",
1792                          0,
1793                          (Oid)0,
1794                          0);
1795     varnode = makeVar(-1, 1, typeid, -1, 1);
1796     tle = makeNode(TargetEntry);
1797     tle->resdom = resnode;
1798     tle->expr = (Node*)varnode;
1799
1800     return (lcons(tle, NIL));
1801 }
1802
1803 /*
1804  * ParseComplexProjection -
1805  *    handles function calls with a single argument that is of complex type.
1806  *    This routine returns NULL if it can't handle the projection (eg. sets).
1807  */
1808 static Node *
1809 ParseComplexProjection(ParseState *pstate,
1810                        char *funcname,
1811                        Node *first_arg,
1812                        bool *attisset)
1813 {
1814     Oid argtype;
1815     Oid argrelid;
1816     Name relname;
1817     Relation rd;
1818     Oid relid;
1819     int attnum;
1820
1821     switch (nodeTag(first_arg)) {
1822     case T_Iter:
1823         {
1824             Func *func;
1825             Iter *iter;
1826
1827             iter = (Iter*)first_arg;        
1828             func = (Func *)((Expr*)iter->iterexpr)->oper;
1829             argtype = funcid_get_rettype(func->funcid);
1830             argrelid = typeid_get_relid(argtype);
1831             if (argrelid &&
1832                 ((attnum = get_attnum(argrelid, funcname))
1833                 != InvalidAttrNumber)) {
1834                 
1835                 /* the argument is a function returning a tuple, so funcname
1836                    may be a projection */
1837
1838                 /* add a tlist to the func node and return the Iter */
1839                 rd = heap_openr(tname(get_id_type(argtype)));
1840                 if (RelationIsValid(rd)) {
1841                     relid = RelationGetRelationId(rd);
1842                     relname = RelationGetRelationName(rd);
1843                     heap_close(rd);
1844                 }
1845                 if (RelationIsValid(rd)) {
1846                     func->func_tlist =
1847                         setup_tlist(funcname, argrelid);
1848                     iter->itertype = att_typeid(rd,attnum);
1849                     return ((Node*)iter);
1850                 }else {
1851                     elog(WARN, 
1852                          "Function %s has bad returntype %d", 
1853                          funcname, argtype);
1854                 }
1855             }else { 
1856                 /* drop through */
1857                 ;
1858             }
1859             break;
1860         }
1861     case T_Var:
1862         {
1863             /*
1864              * The argument is a set, so this is either a projection
1865              * or a function call on this set.
1866              */
1867             *attisset = true;
1868             break;
1869         }
1870     case T_Expr:
1871         {
1872             Expr *expr = (Expr*)first_arg;
1873             Func *funcnode;
1874
1875             if (expr->opType != FUNC_EXPR)
1876                 break;
1877
1878             funcnode= (Func *) expr->oper;
1879             argtype = funcid_get_rettype(funcnode->funcid);
1880             argrelid = typeid_get_relid(argtype);
1881             /*
1882              * the argument is a function returning a tuple, so funcname
1883              * may be a projection
1884              */
1885             if (argrelid &&
1886                 (attnum = get_attnum(argrelid, funcname)) 
1887                 != InvalidAttrNumber) {
1888
1889                 /* add a tlist to the func node */
1890                 rd = heap_openr(tname(get_id_type(argtype)));
1891                 if (RelationIsValid(rd)) {
1892                     relid = RelationGetRelationId(rd);
1893                     relname = RelationGetRelationName(rd);
1894                     heap_close(rd);
1895                 }
1896                 if (RelationIsValid(rd)) {
1897                     Expr *newexpr;
1898                     
1899                     funcnode->func_tlist =
1900                         setup_tlist(funcname, argrelid);
1901                     funcnode->functype = att_typeid(rd,attnum);
1902
1903                     newexpr = makeNode(Expr);
1904                     newexpr->typeOid = funcnode->functype;
1905                     newexpr->opType = FUNC_EXPR;
1906                     newexpr->oper = (Node *)funcnode;
1907                     newexpr->args = lcons(first_arg, NIL);
1908
1909                     return ((Node*)newexpr);
1910                 }
1911             
1912             }
1913
1914             elog(WARN, "Function %s has bad returntype %d", 
1915                 funcname, argtype);
1916             break;
1917         }
1918     case T_Param:
1919         {
1920             Param *param = (Param*)first_arg;
1921             /*
1922              * If the Param is a complex type, this could be a projection
1923              */
1924             rd = heap_openr(tname(get_id_type(param->paramtype)));
1925             if (RelationIsValid(rd)) {
1926                 relid = RelationGetRelationId(rd);
1927                 relname = RelationGetRelationName(rd);
1928                 heap_close(rd);
1929             }
1930             if (RelationIsValid(rd) && 
1931                 (attnum = get_attnum(relid, funcname))
1932                 != InvalidAttrNumber) {
1933
1934                 param->paramtype = att_typeid(rd, attnum);
1935                 param->param_tlist = setup_tlist(funcname, relid);
1936                 return ((Node*)param);
1937             }
1938             break;
1939         }
1940     default:
1941         break;
1942     }
1943
1944     return NULL;
1945 }
1946                        
1947 static Node *
1948 ParseFunc(ParseState *pstate, char *funcname, List *fargs, int *curr_resno)
1949 {
1950     Oid rettype = (Oid)0;
1951     Oid argrelid = (Oid)0;
1952     Oid funcid = (Oid)0;
1953     List *i = NIL;
1954     Node *first_arg= NULL;
1955     char *relname = NULL;
1956     char *refname = NULL;
1957     Relation rd;
1958     Oid relid;
1959     int nargs;
1960     Func *funcnode;
1961     Oid oid_array[8];
1962     Oid *true_oid_array;
1963     Node *retval;
1964     bool retset;
1965     bool exists;
1966     bool attisset = false;
1967     Oid toid = (Oid)0;
1968     Expr *expr;
1969
1970     if (fargs) {
1971         first_arg = lfirst(fargs);
1972         if (first_arg == NULL)
1973             elog (WARN,"function %s does not allow NULL input",funcname);
1974     }
1975     
1976     /*
1977      ** check for projection methods: if function takes one argument, and 
1978      ** that argument is a relation, param, or PQ function returning a complex 
1979      ** type, then the function could be a projection.
1980      */
1981     if (length(fargs) == 1) {
1982         
1983         if (nodeTag(first_arg)==T_Ident && ((Ident*)first_arg)->isRel) {
1984             RangeTblEntry *rte;
1985             Ident *ident = (Ident*)first_arg;
1986
1987             /*
1988              * first arg is a relation. This could be a projection.
1989              */
1990             refname = ident->name;
1991
1992             rte = refnameRangeTableEntry(pstate->p_rtable, refname);
1993             if (rte == NULL)
1994                 rte = addRangeTableEntry(pstate, refname, refname, FALSE, FALSE,NULL);
1995
1996             relname = rte->relname;
1997             relid = rte->relid;
1998
1999             /* If the attr isn't a set, just make a var for it.  If
2000              * it is a set, treat it like a function and drop through.
2001              */
2002             if (get_attnum(relid, funcname) != InvalidAttrNumber) {
2003                 Oid dummyTypeId;
2004
2005                 return
2006                     ((Node*)make_var(pstate,
2007                                      refname,
2008                                      funcname,
2009                                      &dummyTypeId));
2010             } else {
2011                 /* drop through - attr is a set */
2012                 ;
2013             }
2014         } else if (ISCOMPLEX(exprType(first_arg))) {
2015             /*
2016              * Attempt to handle projection of a complex argument. If
2017              * ParseComplexProjection can't handle the projection, we
2018              * have to keep going.
2019              */
2020             retval = ParseComplexProjection(pstate,
2021                                             funcname,
2022                                             first_arg,
2023                                             &attisset);
2024             if (attisset) {
2025                 toid = exprType(first_arg);
2026                 rd = heap_openr(tname(get_id_type(toid)));
2027                 if (RelationIsValid(rd)) {
2028                     relname = RelationGetRelationName(rd)->data;
2029                     heap_close(rd);
2030                 } else
2031                     elog(WARN,
2032                          "Type %s is not a relation type",
2033                          tname(get_id_type(toid)));
2034                 argrelid = typeid_get_relid(toid);
2035                 /* A projection contains either an attribute name or the
2036                  * "*".
2037                  */
2038                 if ((get_attnum(argrelid, funcname) == InvalidAttrNumber) 
2039                     && strcmp(funcname, "*")) {
2040                     elog(WARN, "Functions on sets are not yet supported");
2041                 }
2042             }
2043                 
2044             if (retval)
2045                 return retval;
2046         } else {
2047             /*
2048              * Parsing aggregates.
2049              */
2050             Oid basetype;
2051             /* the aggregate count is a special case,
2052                ignore its base type.  Treat it as zero */
2053             if (strcmp(funcname, "count") == 0)
2054                 basetype = 0;
2055             else
2056                 basetype = exprType(lfirst(fargs));
2057             if (SearchSysCacheTuple(AGGNAME, 
2058                                     PointerGetDatum(funcname), 
2059                                     ObjectIdGetDatum(basetype),
2060                                     0, 0)) {
2061                 Aggreg *aggreg = ParseAgg(funcname, basetype, lfirst(fargs));
2062
2063                 AddAggToParseState(pstate, aggreg);
2064                 return (Node*)aggreg;
2065             }
2066         }
2067     }
2068     
2069     
2070     /*
2071      ** If we dropped through to here it's really a function (or a set, which
2072      ** is implemented as a function.)
2073      ** extract arg type info and transform relation name arguments into
2074      ** varnodes of the appropriate form.
2075      */
2076     memset(&oid_array[0], 0, 8 * sizeof(Oid)); 
2077
2078     nargs=0;
2079     foreach ( i , fargs ) {
2080         int vnum;
2081         RangeTblEntry *rte;
2082         Node *pair = lfirst(i);
2083
2084         if (nodeTag(pair)==T_Ident && ((Ident*)pair)->isRel) {
2085             /*
2086              * a relation
2087              */
2088             refname = ((Ident*)pair)->name;
2089                     
2090             rte = refnameRangeTableEntry(pstate->p_rtable, refname);
2091             if (rte == NULL)
2092                 rte = addRangeTableEntry(pstate, refname, refname,
2093                                                 FALSE, FALSE, NULL);
2094             relname = rte->relname;
2095
2096             vnum = refnameRangeTablePosn (pstate->p_rtable, rte->refname);
2097            
2098             /*
2099              *  for func(relname), the param to the function
2100              *  is the tuple under consideration.  we build a special
2101              *  VarNode to reflect this -- it has varno set to the 
2102              *  correct range table entry, but has varattno == 0 to 
2103              *  signal that the whole tuple is the argument.
2104              */
2105             toid = typeid(type(relname));                  
2106             /* replace it in the arg list */
2107             lfirst(fargs) =
2108                 makeVar(vnum, 0, toid, vnum, 0);
2109         }else if (!attisset) { /* set functions don't have parameters */
2110  
2111           /* any functiona args which are typed "unknown", but aren't
2112              constants, we don't know what to do with, because we
2113              can't cast them    - jolly*/
2114           if (exprType(pair) == UNKNOWNOID &&
2115                !IsA(pair, Const))
2116               {
2117                   elog(WARN, "ParseFunc: no function named %s that takes in an unknown type as argument #%d", funcname, nargs);
2118               }
2119           else
2120               toid = exprType(pair);
2121         }
2122             
2123         oid_array[nargs++] = toid;
2124     }
2125     
2126     /*
2127      *  func_get_detail looks up the function in the catalogs, does
2128      *  disambiguation for polymorphic functions, handles inheritance,
2129      *  and returns the funcid and type and set or singleton status of
2130      *  the function's return value.  it also returns the true argument
2131      *  types to the function.  if func_get_detail returns true,
2132      *  the function exists.  otherwise, there was an error.
2133      */
2134     if (attisset) { /* we know all of these fields already */
2135         /* We create a funcnode with a placeholder function SetEval.
2136          * SetEval() never actually gets executed.  When the function
2137          * evaluation routines see it, they use the funcid projected
2138          * out from the relation as the actual function to call.
2139          * Example:  retrieve (emp.mgr.name)
2140          * The plan for this will scan the emp relation, projecting
2141          * out the mgr attribute, which is a funcid.  This function
2142          * is then called (instead of SetEval) and "name" is projected
2143          * from its result.
2144          */
2145         funcid = SetEvalRegProcedure;
2146         rettype = toid;
2147         retset = true;
2148         true_oid_array = oid_array;
2149         exists = true;
2150     } else {
2151         exists = func_get_detail(funcname, nargs, oid_array, &funcid,
2152                                  &rettype, &retset, &true_oid_array);
2153     }
2154     
2155     if (!exists)
2156         elog(WARN, "no such attribute or function %s", funcname);
2157     
2158     /* got it */
2159     funcnode = makeNode(Func);
2160     funcnode->funcid = funcid;
2161     funcnode->functype = rettype;
2162     funcnode->funcisindex = false;
2163     funcnode->funcsize = 0;
2164     funcnode->func_fcache = NULL;
2165     funcnode->func_tlist = NIL;
2166     funcnode->func_planlist = NIL;
2167     
2168     /* perform the necessary typecasting */
2169     make_arguments(nargs, fargs, oid_array, true_oid_array);
2170     
2171     /*
2172      *  for functions returning base types, we want to project out the
2173      *  return value.  set up a target list to do that.  the executor
2174      *  will ignore these for c functions, and do the right thing for
2175      *  postquel functions.
2176      */
2177     
2178     if (typeid_get_relid(rettype) == InvalidOid)
2179         funcnode->func_tlist = setup_base_tlist(rettype);
2180     
2181     /* For sets, we want to make a targetlist to project out this
2182      * attribute of the set tuples.
2183      */
2184     if (attisset) {
2185         if (!strcmp(funcname, "*")) {
2186             funcnode->func_tlist =
2187                 expandAll(pstate, relname, refname, curr_resno);
2188         } else {
2189             funcnode->func_tlist = setup_tlist(funcname,argrelid);
2190             rettype = find_atttype(argrelid, funcname);
2191         }
2192     }
2193
2194     /*
2195      * Sequence handling.
2196      */
2197     if ( funcid == SeqNextValueRegProcedure || 
2198                 funcid == SeqCurrValueRegProcedure )
2199     {
2200         Const *seq;
2201         char *seqrel;
2202         int32 aclcheck_result = -1;
2203         
2204         Assert ( length(fargs) == 1 );
2205         seq = (Const*)lfirst(fargs);
2206         if ( ! IsA ((Node*)seq, Const) )
2207             elog (WARN, "%s: only constant sequence names are acceptable", funcname);
2208         seqrel = textout ((struct varlena *) (seq->constvalue));
2209         
2210         if ( ( aclcheck_result = pg_aclcheck (seqrel, GetPgUserName(), 
2211                 ((funcid == SeqNextValueRegProcedure) ? ACL_WR : ACL_RD)) )
2212                                                 != ACLCHECK_OK )
2213             elog (WARN, "%s.%s: %s", 
2214                 seqrel, funcname, aclcheck_error_strings[aclcheck_result]);
2215         
2216         pfree (seqrel);
2217
2218         if ( funcid == SeqNextValueRegProcedure && inWhereClause )
2219             elog (WARN, "nextval of a sequence in WHERE disallowed"); 
2220     }
2221
2222     expr = makeNode(Expr);
2223     expr->typeOid = rettype;
2224     expr->opType = FUNC_EXPR;
2225     expr->oper = (Node *)funcnode;
2226     expr->args = fargs;
2227     retval = (Node*)expr;
2228     
2229     /*
2230      *  if the function returns a set of values, then we need to iterate
2231      *  over all the returned values in the executor, so we stick an
2232      *  iter node here.  if it returns a singleton, then we don't need
2233      *  the iter node.
2234      */
2235     
2236     if (retset) {
2237         Iter *iter = makeNode(Iter);
2238         iter->itertype = rettype;
2239         iter->iterexpr = retval;
2240         retval = (Node*)iter;
2241     }
2242     
2243     return(retval);
2244 }
2245
2246 /*****************************************************************************
2247  *
2248  *****************************************************************************/
2249
2250 /*
2251  * AddAggToParseState -
2252  *    add the aggregate to the list of unique aggregates in pstate. 
2253  *
2254  * SIDE EFFECT: aggno in target list entry will be modified
2255  */
2256 static void
2257 AddAggToParseState(ParseState *pstate, Aggreg *aggreg)
2258 {
2259     List *ag;
2260     int i;
2261
2262     /*
2263      * see if we have the aggregate already (we only need to record
2264      * the aggregate once)
2265      */
2266     i = 0;
2267     foreach(ag, pstate->p_aggs) {
2268         Aggreg *a = lfirst(ag);
2269         
2270         if (!strcmp(a->aggname, aggreg->aggname) &&
2271             equal(a->target, aggreg->target)) {
2272
2273             /* fill in the aggno and we're done */
2274             aggreg->aggno = i;
2275             return;
2276         }
2277         i++;
2278     }
2279
2280     /* not found, new aggregate */
2281     aggreg->aggno = i;
2282     pstate->p_numAgg++;
2283     pstate->p_aggs = lappend(pstate->p_aggs, aggreg);
2284     return;
2285 }
2286
2287 /*
2288  * finalizeAggregates -
2289  *    fill in qry_aggs from pstate. Also checks to make sure that aggregates
2290  *    are used in the proper place.
2291  */
2292 static void
2293 finalizeAggregates(ParseState *pstate, Query *qry)
2294 {    
2295     List *l;
2296     int i;
2297
2298     parseCheckAggregates(pstate, qry);
2299         
2300     qry->qry_numAgg = pstate->p_numAgg;
2301     qry->qry_aggs =
2302         (Aggreg **)palloc(sizeof(Aggreg *) * qry->qry_numAgg);
2303     i = 0;
2304     foreach(l, pstate->p_aggs)
2305         qry->qry_aggs[i++] = (Aggreg*)lfirst(l);
2306 }
2307
2308 /*    
2309  * contain_agg_clause--
2310  *    Recursively find aggreg nodes from a clause.
2311  *    
2312  *    Returns true if any aggregate found.
2313  */
2314 static bool
2315 contain_agg_clause(Node *clause)
2316 {
2317     if (clause==NULL) 
2318         return FALSE;
2319     else if (IsA(clause,Aggreg))
2320         return TRUE;
2321     else if (IsA(clause,Iter))
2322         return contain_agg_clause(((Iter*)clause)->iterexpr);
2323     else if (single_node(clause)) 
2324         return FALSE;
2325     else if (or_clause(clause)) {
2326         List *temp;
2327
2328         foreach (temp, ((Expr*)clause)->args)
2329             if (contain_agg_clause(lfirst(temp)))
2330                 return TRUE;
2331         return FALSE;
2332     } else if (is_funcclause (clause)) {
2333         List *temp;
2334
2335         foreach(temp, ((Expr *)clause)->args)
2336             if (contain_agg_clause(lfirst(temp)))
2337                 return TRUE;
2338         return FALSE;
2339     } else if (IsA(clause,ArrayRef)) {
2340         List *temp;
2341
2342         foreach(temp, ((ArrayRef*)clause)->refupperindexpr)
2343             if (contain_agg_clause(lfirst(temp)))
2344                 return TRUE;
2345         foreach(temp, ((ArrayRef*)clause)->reflowerindexpr)
2346             if (contain_agg_clause(lfirst(temp)))
2347                 return TRUE;
2348         if (contain_agg_clause(((ArrayRef*)clause)->refexpr))
2349             return TRUE;
2350         if (contain_agg_clause(((ArrayRef*)clause)->refassgnexpr))
2351             return TRUE;
2352         return FALSE;
2353     } else if (not_clause(clause))
2354         return contain_agg_clause((Node*)get_notclausearg((Expr*)clause));
2355     else if (is_opclause(clause))
2356         return (contain_agg_clause((Node*)get_leftop((Expr*)clause)) ||
2357                 contain_agg_clause((Node*)get_rightop((Expr*)clause)));
2358
2359     return FALSE;
2360 }
2361
2362 /*
2363  * tleIsAggOrGroupCol -
2364  *    returns true if the TargetEntry is Agg or GroupCol.
2365  */
2366 static bool
2367 tleIsAggOrGroupCol(TargetEntry *tle, List *groupClause)
2368 {
2369     Node *expr = tle->expr;
2370     List *gl;
2371     
2372     if ( expr == NULL || IsA (expr, Const) )
2373         return TRUE;
2374         
2375     foreach (gl, groupClause)
2376     {
2377         GroupClause *grpcl = lfirst(gl);
2378         
2379         if ( tle->resdom->resno == grpcl->resdom->resno )
2380         {
2381             if ( IsA (expr, Aggreg) )
2382                 elog (WARN, "parser: aggregates not allowed in GROUP BY clause");
2383             return TRUE;
2384         }
2385     }
2386
2387     if ( IsA (expr, Aggreg) )
2388         return TRUE;
2389
2390     return FALSE;
2391 }
2392
2393 #if 0   /* Now GroupBy contains resdom to enable Group By func_results */
2394 /*
2395  * exprIsAggOrGroupCol -
2396  *    returns true if the expression does not contain non-group columns.
2397  */
2398 static bool
2399 exprIsAggOrGroupCol(Node *expr, List *groupClause)
2400 {
2401     if (expr==NULL)
2402         return TRUE;
2403     else if (IsA(expr,Const))
2404         return TRUE;
2405     else if (IsA(expr,Var)) {
2406         List *gl;
2407         Var *var = (Var*)expr;
2408         /*
2409          * only group columns are legal
2410          */
2411         foreach (gl, groupClause) {
2412             GroupClause *grpcl = lfirst(gl);
2413             if ((grpcl->grpAttr->varno == var->varno) &&
2414                 (grpcl->grpAttr->varattno == var->varattno))
2415                 return TRUE;
2416         }
2417         return FALSE;
2418     } else if (IsA(expr,Aggreg))
2419         /* aggregates can take group column or non-group column as argument,
2420            no further check necessary. */
2421         return TRUE;
2422     else if (IsA(expr,Expr)) {
2423         List *temp;
2424
2425         foreach (temp, ((Expr*)expr)->args)
2426             if (!exprIsAggOrGroupCol(lfirst(temp),groupClause))
2427                 return FALSE;
2428         return TRUE;
2429     }
2430
2431     return FALSE;
2432 }
2433 #endif
2434
2435 /*
2436  * parseCheckAggregates -
2437  *    this should really be done earlier but the current grammar
2438  *    cannot differentiate functions from aggregates. So we have do check
2439  *    here when the target list and the qualifications are finalized.
2440  */
2441 static void
2442 parseCheckAggregates(ParseState *pstate, Query *qry)
2443 {
2444     List *tl;
2445     Assert(pstate->p_numAgg > 0);
2446
2447     /*
2448      * aggregates never appear in WHERE clauses. (we have to check where
2449      * clause first because if there is an aggregate, the check for
2450      * non-group column in target list may fail.)
2451      */
2452     if (contain_agg_clause(qry->qual))
2453         elog(WARN, "parser: aggregates not allowed in WHERE clause");
2454
2455     /*
2456      * the target list can only contain aggregates, group columns and
2457      * functions thereof.
2458      */
2459     foreach (tl, qry->targetList) {
2460         TargetEntry *tle = lfirst(tl);
2461         if (!tleIsAggOrGroupCol(tle, qry->groupClause))
2462             elog(WARN,
2463                  "parser: illegal use of aggregates or non-group column in target list");
2464     }
2465         
2466     /*
2467      * the expression specified in the HAVING clause has the same restriction
2468      * as those in the target list.
2469      */
2470 /*
2471  * Need to change here when we get HAVING works. Currently 
2472  * qry->havingQual is NULL.     - vadim 04/05/97
2473     if (!exprIsAggOrGroupCol(qry->havingQual, qry->groupClause))
2474         elog(WARN,
2475              "parser: illegal use of aggregates or non-group column in HAVING clause");
2476  */    
2477     return;
2478 }