OSDN Git Service

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