OSDN Git Service

Add detection and warnings for UNION and HAVING clauses.
[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.36 1997/09/01 05:56:34 thomas 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); do 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",
1361                               colname));
1362                }
1363           
1364           Input_is_string = false;
1365           Input_is_integer = false;
1366           Typecast_ok = true;
1367 #endif
1368
1369           if (attrtype != type_id) {
1370               if (IsA(expr,Const)) {
1371                   /* try to cast the constant */
1372                   if (arrayRef && !(((A_Indices *)lfirst(arrayRef))->lidx)) {
1373                       /* updating a single item */
1374                       Oid typelem = get_typelem(attrtype);
1375                       expr = (Node*)parser_typecast2(expr,
1376                                                    type_id,
1377                                                    get_id_type(typelem),
1378                                                    attrlen);
1379                   } else
1380                   expr = (Node*)parser_typecast2(expr,
1381                                                  type_id,
1382                                                  get_id_type(attrtype),
1383                                                  attrlen);
1384               } else {
1385                   /* currently, we can't handle casting of expressions */
1386                   elog(WARN, "parser: attribute '%s' is of type '%s' but expression is of type '%s'",
1387                        colname,
1388                        get_id_typname(attrtype),
1389                        get_id_typname(type_id));
1390               }
1391           }
1392
1393           if (arrayRef != NIL) {
1394                Expr *target_expr;
1395                Attr *att = makeNode(Attr);
1396                List *ar = arrayRef;
1397                List *upperIndexpr = NIL;
1398                List *lowerIndexpr = NIL;
1399
1400                att->relname = pstrdup(RelationGetRelationName(rd)->data);
1401                att->attrs = lcons(makeString(colname), NIL);
1402                target_expr = (Expr*)handleNestedDots(pstate, att,
1403                                                      &pstate->p_last_resno);
1404                while(ar!=NIL) {
1405                    A_Indices *ind = lfirst(ar);
1406                    if (lowerIndexpr || (!upperIndexpr && ind->lidx)) {
1407                        /* XXX assume all lowerIndexpr is non-null in
1408                         * this case
1409                         */
1410                        lowerIndexpr = lappend(lowerIndexpr, ind->lidx);
1411                    }
1412                    upperIndexpr = lappend(upperIndexpr, ind->uidx);
1413                    ar = lnext(ar);
1414                }
1415                
1416                expr = (Node*)make_array_set(target_expr,
1417                                             upperIndexpr,
1418                                             lowerIndexpr,
1419                                             (Expr*)expr);       
1420                attrtype = att_typeid(rd,resdomno);
1421                attrlen = tlen(get_id_type(attrtype)); 
1422           }
1423      } else {
1424           resdomno = pstate->p_last_resno++;
1425           attrtype = type_id;
1426           attrlen = type_len;
1427      }
1428      tent = makeNode(TargetEntry);
1429
1430      resnode = makeResdom((AttrNumber)resdomno,
1431                           (Oid) attrtype,
1432                           (Size) attrlen,
1433                           colname, 
1434                           (Index)0,
1435                           (Oid)0,
1436                           0);
1437
1438      tent->resdom = resnode;
1439      tent->expr = expr;
1440          
1441      return  tent;
1442 }
1443
1444
1445 /*****************************************************************************
1446  *
1447  * Where Clause
1448  *
1449  *****************************************************************************/
1450
1451 /*
1452  * transformWhereClause -
1453  *    transforms the qualification and make sure it is of type Boolean
1454  *
1455  */
1456 static Node *
1457 transformWhereClause(ParseState *pstate, Node *a_expr)
1458 {
1459     Node *qual;
1460
1461     if (a_expr == NULL)
1462         return (Node *)NULL;            /* no qualifiers */
1463
1464     inWhereClause = true;
1465     qual = transformExpr(pstate, a_expr, EXPR_COLUMN_FIRST);
1466     inWhereClause = false;
1467     if (exprType(qual) != BOOLOID) {
1468         elog(WARN,
1469              "where clause must return type bool, not %s",
1470              tname(get_id_type(exprType(qual))));
1471     }
1472     return qual;
1473 }
1474
1475 /*****************************************************************************
1476  *
1477  * Sort Clause
1478  *
1479  *****************************************************************************/
1480
1481 /*
1482  *  find_targetlist_entry -
1483  *    returns the Resdom in the target list matching the specified varname
1484  *    and range
1485  *
1486  */
1487 static TargetEntry *
1488 find_targetlist_entry(ParseState *pstate, SortGroupBy *sortgroupby, List *tlist)
1489 {
1490     List *i;
1491     int real_rtable_pos = 0, target_pos = 0;
1492     TargetEntry *target_result = NULL;
1493     
1494     if(sortgroupby->range)
1495         real_rtable_pos = refnameRangeTablePosn(pstate->p_rtable,
1496                                                         sortgroupby->range);
1497
1498     foreach(i, tlist) {
1499         TargetEntry *target = (TargetEntry *)lfirst(i);
1500         Resdom *resnode = target->resdom;
1501         Var *var = (Var *)target->expr;
1502         char *resname = resnode->resname;
1503         int test_rtable_pos = var->varno;
1504
1505 #ifdef PARSEDEBUG
1506 printf("find_targetlist_entry- target name is %s, position %d, resno %d\n",
1507  (sortgroupby->name? sortgroupby->name: "(null)"), target_pos+1, sortgroupby->resno);
1508 #endif
1509
1510         if (!sortgroupby->name) {
1511             if (sortgroupby->resno == ++target_pos) {
1512                 target_result = target;
1513                 break;
1514             }
1515         }
1516         else {
1517             if (!strcmp(resname, sortgroupby->name)) {
1518                 if(sortgroupby->range) {
1519                     if(real_rtable_pos == test_rtable_pos) {
1520                         if (target_result != NULL)
1521                             elog(WARN, "Order/Group By %s is ambiguous", sortgroupby->name);
1522                         else    target_result = target;
1523                     }
1524                 }                       
1525                 else {
1526                     if (target_result != NULL)
1527                         elog(WARN, "Order/Group By %s is ambiguous", sortgroupby->name);
1528                     else        target_result = target;
1529                 }
1530             }
1531         }
1532     }
1533     return target_result;
1534 }
1535
1536 static Oid
1537 any_ordering_op(int restype)
1538 {
1539     Operator order_op;
1540     Oid order_opid;
1541     
1542     order_op = oper("<",restype,restype,false);
1543     order_opid = oprid(order_op);
1544     
1545     return order_opid;
1546 }
1547
1548 /*
1549  * transformGroupClause -
1550  *    transform a Group By clause
1551  *
1552  */
1553 static List *
1554 transformGroupClause(ParseState *pstate, List *grouplist, List *targetlist)
1555 {
1556     List *glist = NIL, *gl = NIL;
1557
1558     while (grouplist != NIL) {
1559         GroupClause *grpcl = makeNode(GroupClause);
1560         TargetEntry *restarget;
1561         Resdom *resdom;
1562
1563         restarget = find_targetlist_entry(pstate, lfirst(grouplist), targetlist);
1564
1565         if (restarget == NULL)
1566             elog(WARN,"The field being grouped by must appear in the target list");
1567
1568         grpcl->entry = restarget;
1569         resdom = restarget->resdom;
1570         grpcl->grpOpoid = oprid(oper("<",
1571                                    resdom->restype,
1572                                    resdom->restype,false));
1573         if (glist == NIL)
1574             gl = glist = lcons(grpcl, NIL);
1575         else {
1576             lnext(gl) = lcons(grpcl, NIL);
1577             gl = lnext(gl);
1578         }
1579         grouplist = lnext(grouplist);
1580     }
1581
1582     return glist;
1583 }
1584
1585 /*
1586  * transformSortClause -
1587  *    transform an Order By clause
1588  *
1589  */
1590 static List *
1591 transformSortClause(ParseState *pstate,
1592                     List *orderlist, List *targetlist,
1593                     char* uniqueFlag)
1594 {
1595     List *sortlist = NIL;
1596     List *s = NIL, *i;
1597
1598     while(orderlist != NIL) {
1599         SortGroupBy *sortby = lfirst(orderlist);
1600         SortClause *sortcl = makeNode(SortClause);
1601         TargetEntry *restarget;
1602         Resdom *resdom;
1603
1604         restarget = find_targetlist_entry(pstate, sortby, targetlist);
1605         if (restarget == NULL)
1606             elog(WARN,"The field being ordered by must appear in the target list");
1607
1608         sortcl->resdom = resdom = restarget->resdom;
1609         sortcl->opoid = oprid(oper(sortby->useOp,
1610                                    resdom->restype,
1611                                    resdom->restype,false));
1612         if (sortlist == NIL) {
1613             s = sortlist = lcons(sortcl, NIL);
1614         }else {
1615             lnext(s) = lcons(sortcl, NIL);
1616             s = lnext(s);
1617         }
1618         orderlist = lnext(orderlist);
1619     }
1620     
1621     if (uniqueFlag) {
1622       if (uniqueFlag[0] == '*') {
1623         /* concatenate all elements from target list
1624            that are not already in the sortby list */
1625         foreach (i,targetlist) {
1626             TargetEntry *tlelt = (TargetEntry *)lfirst(i);
1627
1628             s = sortlist;
1629             while(s != NIL) {
1630                 SortClause *sortcl = lfirst(s);
1631                 if (sortcl->resdom==tlelt->resdom)
1632                     break;
1633                 s = lnext(s);
1634             }
1635             if (s == NIL) {
1636                 /* not a member of the sortclauses yet */
1637                 SortClause *sortcl = makeNode(SortClause);
1638                 
1639                 sortcl->resdom = tlelt->resdom;
1640                 sortcl->opoid = any_ordering_op(tlelt->resdom->restype);
1641
1642                 sortlist = lappend(sortlist, sortcl);
1643               }
1644           }
1645       }
1646       else {
1647         TargetEntry *tlelt = NULL;
1648         char* uniqueAttrName = uniqueFlag;
1649
1650           /* only create sort clause with the specified unique attribute */
1651           foreach (i, targetlist) {
1652             tlelt = (TargetEntry*)lfirst(i);
1653             if (strcmp(tlelt->resdom->resname, uniqueAttrName) == 0)
1654               break;
1655           }
1656           if (i == NIL) {
1657             elog(WARN, "The field specified in the UNIQUE ON clause is not in the targetlist");
1658           }
1659           s = sortlist;
1660           foreach (s, sortlist) {
1661             SortClause *sortcl = lfirst(s);
1662             if (sortcl->resdom == tlelt->resdom)
1663               break;
1664           }
1665           if (s == NIL) { 
1666                 /* not a member of the sortclauses yet */
1667                 SortClause *sortcl = makeNode(SortClause);
1668                 
1669                 sortcl->resdom = tlelt->resdom;
1670                 sortcl->opoid = any_ordering_op(tlelt->resdom->restype);
1671
1672                 sortlist = lappend(sortlist, sortcl);
1673               }
1674         }
1675
1676     }
1677     
1678     return sortlist;
1679 }
1680
1681 /*
1682  ** HandleNestedDots --
1683  **    Given a nested dot expression (i.e. (relation func ... attr), build up
1684  ** a tree with of Iter and Func nodes.
1685  */
1686 static Node*
1687 handleNestedDots(ParseState *pstate, Attr *attr, int *curr_resno)
1688 {
1689     List *mutator_iter;
1690     Node *retval = NULL;
1691     
1692     if (attr->paramNo != NULL) {
1693         Param *param = (Param *)transformExpr(pstate, (Node*)attr->paramNo, EXPR_RELATION_FIRST);
1694
1695         retval = 
1696             ParseFunc(pstate, strVal(lfirst(attr->attrs)),
1697                       lcons(param, NIL),
1698                       curr_resno);
1699     } else {
1700         Ident *ident = makeNode(Ident);
1701
1702         ident->name = attr->relname;
1703         ident->isRel = TRUE;
1704         retval =
1705             ParseFunc(pstate, strVal(lfirst(attr->attrs)),
1706                       lcons(ident, NIL),
1707                       curr_resno);
1708     }
1709     
1710     foreach (mutator_iter, lnext(attr->attrs)) {
1711         retval = ParseFunc(pstate,strVal(lfirst(mutator_iter)), 
1712                            lcons(retval, NIL),
1713                            curr_resno);
1714     }
1715     
1716     return(retval);
1717 }
1718
1719 /*
1720  ** make_arguments --
1721  **   Given the number and types of arguments to a function, and the 
1722  **   actual arguments and argument types, do the necessary typecasting.
1723  */
1724 static void
1725 make_arguments(int nargs,
1726                List *fargs,
1727                Oid *input_typeids,
1728                Oid *function_typeids)
1729 {
1730     /*
1731      * there are two ways an input typeid can differ from a function typeid :
1732      * either the input type inherits the function type, so no typecasting is
1733      * necessary, or the input type can be typecast into the function type.
1734      * right now, we only typecast unknowns, and that is all we check for.
1735      */
1736     
1737     List *current_fargs;
1738     int i;
1739     
1740     for (i=0, current_fargs = fargs;
1741          i<nargs;
1742          i++, current_fargs = lnext(current_fargs)) {
1743
1744         if (input_typeids[i] == UNKNOWNOID && function_typeids[i] != InvalidOid) {
1745             lfirst(current_fargs) =
1746                 parser_typecast2(lfirst(current_fargs),
1747                                  input_typeids[i],
1748                                  get_id_type(function_typeids[i]),
1749                                  -1);
1750         }
1751     }
1752 }
1753
1754 /*
1755  ** setup_tlist --
1756  **     Build a tlist that says which attribute to project to.
1757  **     This routine is called by ParseFunc() to set up a target list
1758  **     on a tuple parameter or return value.  Due to a bug in 4.0,
1759  **     it's not possible to refer to system attributes in this case.
1760  */
1761 static List *
1762 setup_tlist(char *attname, Oid relid)
1763 {
1764     TargetEntry *tle;
1765     Resdom *resnode;
1766     Var *varnode;
1767     Oid typeid;
1768     int attno;
1769     
1770     attno = get_attnum(relid, attname);
1771     if (attno < 0)
1772         elog(WARN, "cannot reference attribute %s of tuple params/return values for functions", attname);
1773     
1774     typeid = find_atttype(relid, attname);
1775     resnode = makeResdom(1,
1776                          typeid,
1777                          tlen(get_id_type(typeid)),
1778                          get_attname(relid, attno),
1779                          0,
1780                          (Oid)0,
1781                          0);
1782     varnode = makeVar(-1, attno, typeid, -1, attno);
1783
1784     tle = makeNode(TargetEntry);
1785     tle->resdom = resnode;
1786     tle->expr = (Node*)varnode;
1787     return (lcons(tle, NIL));
1788 }
1789
1790 /*
1791  ** setup_base_tlist --
1792  **     Build a tlist that extracts a base type from the tuple
1793  **     returned by the executor.
1794  */
1795 static List *
1796 setup_base_tlist(Oid typeid)
1797 {
1798     TargetEntry *tle;
1799     Resdom *resnode;
1800     Var *varnode;
1801     
1802     resnode = makeResdom(1,
1803                          typeid,
1804                          tlen(get_id_type(typeid)),
1805                          "<noname>",
1806                          0,
1807                          (Oid)0,
1808                          0);
1809     varnode = makeVar(-1, 1, typeid, -1, 1);
1810     tle = makeNode(TargetEntry);
1811     tle->resdom = resnode;
1812     tle->expr = (Node*)varnode;
1813
1814     return (lcons(tle, NIL));
1815 }
1816
1817 /*
1818  * ParseComplexProjection -
1819  *    handles function calls with a single argument that is of complex type.
1820  *    This routine returns NULL if it can't handle the projection (eg. sets).
1821  */
1822 static Node *
1823 ParseComplexProjection(ParseState *pstate,
1824                        char *funcname,
1825                        Node *first_arg,
1826                        bool *attisset)
1827 {
1828     Oid argtype;
1829     Oid argrelid;
1830     Name relname;
1831     Relation rd;
1832     Oid relid;
1833     int attnum;
1834
1835     switch (nodeTag(first_arg)) {
1836     case T_Iter:
1837         {
1838             Func *func;
1839             Iter *iter;
1840
1841             iter = (Iter*)first_arg;        
1842             func = (Func *)((Expr*)iter->iterexpr)->oper;
1843             argtype = funcid_get_rettype(func->funcid);
1844             argrelid = typeid_get_relid(argtype);
1845             if (argrelid &&
1846                 ((attnum = get_attnum(argrelid, funcname))
1847                 != InvalidAttrNumber)) {
1848                 
1849                 /* the argument is a function returning a tuple, so funcname
1850                    may be a projection */
1851
1852                 /* add a tlist to the func node and return the Iter */
1853                 rd = heap_openr(tname(get_id_type(argtype)));
1854                 if (RelationIsValid(rd)) {
1855                     relid = RelationGetRelationId(rd);
1856                     relname = RelationGetRelationName(rd);
1857                     heap_close(rd);
1858                 }
1859                 if (RelationIsValid(rd)) {
1860                     func->func_tlist =
1861                         setup_tlist(funcname, argrelid);
1862                     iter->itertype = att_typeid(rd,attnum);
1863                     return ((Node*)iter);
1864                 }else {
1865                     elog(WARN, 
1866                          "Function %s has bad returntype %d", 
1867                          funcname, argtype);
1868                 }
1869             }else { 
1870                 /* drop through */
1871                 ;
1872             }
1873             break;
1874         }
1875     case T_Var:
1876         {
1877             /*
1878              * The argument is a set, so this is either a projection
1879              * or a function call on this set.
1880              */
1881             *attisset = true;
1882             break;
1883         }
1884     case T_Expr:
1885         {
1886             Expr *expr = (Expr*)first_arg;
1887             Func *funcnode;
1888
1889             if (expr->opType != FUNC_EXPR)
1890                 break;
1891
1892             funcnode= (Func *) expr->oper;
1893             argtype = funcid_get_rettype(funcnode->funcid);
1894             argrelid = typeid_get_relid(argtype);
1895             /*
1896              * the argument is a function returning a tuple, so funcname
1897              * may be a projection
1898              */
1899             if (argrelid &&
1900                 (attnum = get_attnum(argrelid, funcname)) 
1901                 != InvalidAttrNumber) {
1902
1903                 /* add a tlist to the func node */
1904                 rd = heap_openr(tname(get_id_type(argtype)));
1905                 if (RelationIsValid(rd)) {
1906                     relid = RelationGetRelationId(rd);
1907                     relname = RelationGetRelationName(rd);
1908                     heap_close(rd);
1909                 }
1910                 if (RelationIsValid(rd)) {
1911                     Expr *newexpr;
1912                     
1913                     funcnode->func_tlist =
1914                         setup_tlist(funcname, argrelid);
1915                     funcnode->functype = att_typeid(rd,attnum);
1916
1917                     newexpr = makeNode(Expr);
1918                     newexpr->typeOid = funcnode->functype;
1919                     newexpr->opType = FUNC_EXPR;
1920                     newexpr->oper = (Node *)funcnode;
1921                     newexpr->args = lcons(first_arg, NIL);
1922
1923                     return ((Node*)newexpr);
1924                 }
1925             
1926             }
1927
1928             elog(WARN, "Function %s has bad returntype %d", 
1929                 funcname, argtype);
1930             break;
1931         }
1932     case T_Param:
1933         {
1934             Param *param = (Param*)first_arg;
1935             /*
1936              * If the Param is a complex type, this could be a projection
1937              */
1938             rd = heap_openr(tname(get_id_type(param->paramtype)));
1939             if (RelationIsValid(rd)) {
1940                 relid = RelationGetRelationId(rd);
1941                 relname = RelationGetRelationName(rd);
1942                 heap_close(rd);
1943             }
1944             if (RelationIsValid(rd) && 
1945                 (attnum = get_attnum(relid, funcname))
1946                 != InvalidAttrNumber) {
1947
1948                 param->paramtype = att_typeid(rd, attnum);
1949                 param->param_tlist = setup_tlist(funcname, relid);
1950                 return ((Node*)param);
1951             }
1952             break;
1953         }
1954     default:
1955         break;
1956     }
1957
1958     return NULL;
1959 }
1960                        
1961 static Node *
1962 ParseFunc(ParseState *pstate, char *funcname, List *fargs, int *curr_resno)
1963 {
1964     Oid rettype = (Oid)0;
1965     Oid argrelid = (Oid)0;
1966     Oid funcid = (Oid)0;
1967     List *i = NIL;
1968     Node *first_arg= NULL;
1969     char *relname = NULL;
1970     char *refname = NULL;
1971     Relation rd;
1972     Oid relid;
1973     int nargs;
1974     Func *funcnode;
1975     Oid oid_array[8];
1976     Oid *true_oid_array;
1977     Node *retval;
1978     bool retset;
1979     bool exists;
1980     bool attisset = false;
1981     Oid toid = (Oid)0;
1982     Expr *expr;
1983
1984     if (fargs) {
1985         first_arg = lfirst(fargs);
1986         if (first_arg == NULL)
1987             elog (WARN,"function %s does not allow NULL input",funcname);
1988     }
1989     
1990     /*
1991      ** check for projection methods: if function takes one argument, and 
1992      ** that argument is a relation, param, or PQ function returning a complex 
1993      ** type, then the function could be a projection.
1994      */
1995     if (length(fargs) == 1) {
1996         
1997         if (nodeTag(first_arg)==T_Ident && ((Ident*)first_arg)->isRel) {
1998             RangeTblEntry *rte;
1999             Ident *ident = (Ident*)first_arg;
2000
2001             /*
2002              * first arg is a relation. This could be a projection.
2003              */
2004             refname = ident->name;
2005
2006             rte = refnameRangeTableEntry(pstate->p_rtable, refname);
2007             if (rte == NULL)
2008                 rte = addRangeTableEntry(pstate, refname, refname, FALSE, FALSE,NULL);
2009
2010             relname = rte->relname;
2011             relid = rte->relid;
2012
2013             /* If the attr isn't a set, just make a var for it.  If
2014              * it is a set, treat it like a function and drop through.
2015              */
2016             if (get_attnum(relid, funcname) != InvalidAttrNumber) {
2017                 Oid dummyTypeId;
2018
2019                 return
2020                     ((Node*)make_var(pstate,
2021                                      refname,
2022                                      funcname,
2023                                      &dummyTypeId));
2024             } else {
2025                 /* drop through - attr is a set */
2026                 ;
2027             }
2028         } else if (ISCOMPLEX(exprType(first_arg))) {
2029             /*
2030              * Attempt to handle projection of a complex argument. If
2031              * ParseComplexProjection can't handle the projection, we
2032              * have to keep going.
2033              */
2034             retval = ParseComplexProjection(pstate,
2035                                             funcname,
2036                                             first_arg,
2037                                             &attisset);
2038             if (attisset) {
2039                 toid = exprType(first_arg);
2040                 rd = heap_openr(tname(get_id_type(toid)));
2041                 if (RelationIsValid(rd)) {
2042                     relname = RelationGetRelationName(rd)->data;
2043                     heap_close(rd);
2044                 } else
2045                     elog(WARN,
2046                          "Type %s is not a relation type",
2047                          tname(get_id_type(toid)));
2048                 argrelid = typeid_get_relid(toid);
2049                 /* A projection contains either an attribute name or the
2050                  * "*".
2051                  */
2052                 if ((get_attnum(argrelid, funcname) == InvalidAttrNumber) 
2053                     && strcmp(funcname, "*")) {
2054                     elog(WARN, "Functions on sets are not yet supported");
2055                 }
2056             }
2057                 
2058             if (retval)
2059                 return retval;
2060         } else {
2061             /*
2062              * Parsing aggregates.
2063              */
2064             Oid basetype;
2065             /* the aggregate count is a special case,
2066                ignore its base type.  Treat it as zero */
2067             if (strcmp(funcname, "count") == 0)
2068                 basetype = 0;
2069             else
2070                 basetype = exprType(lfirst(fargs));
2071             if (SearchSysCacheTuple(AGGNAME, 
2072                                     PointerGetDatum(funcname), 
2073                                     ObjectIdGetDatum(basetype),
2074                                     0, 0)) {
2075                 Aggreg *aggreg = ParseAgg(funcname, basetype, lfirst(fargs));
2076
2077                 AddAggToParseState(pstate, aggreg);
2078                 return (Node*)aggreg;
2079             }
2080         }
2081     }
2082     
2083     
2084     /*
2085      ** If we dropped through to here it's really a function (or a set, which
2086      ** is implemented as a function.)
2087      ** extract arg type info and transform relation name arguments into
2088      ** varnodes of the appropriate form.
2089      */
2090     memset(&oid_array[0], 0, 8 * sizeof(Oid)); 
2091
2092     nargs=0;
2093     foreach ( i , fargs ) {
2094         int vnum;
2095         RangeTblEntry *rte;
2096         Node *pair = lfirst(i);
2097
2098         if (nodeTag(pair)==T_Ident && ((Ident*)pair)->isRel) {
2099             /*
2100              * a relation
2101              */
2102             refname = ((Ident*)pair)->name;
2103                     
2104             rte = refnameRangeTableEntry(pstate->p_rtable, refname);
2105             if (rte == NULL)
2106                 rte = addRangeTableEntry(pstate, refname, refname,
2107                                                 FALSE, FALSE, NULL);
2108             relname = rte->relname;
2109
2110             vnum = refnameRangeTablePosn (pstate->p_rtable, rte->refname);
2111            
2112             /*
2113              *  for func(relname), the param to the function
2114              *  is the tuple under consideration.  we build a special
2115              *  VarNode to reflect this -- it has varno set to the 
2116              *  correct range table entry, but has varattno == 0 to 
2117              *  signal that the whole tuple is the argument.
2118              */
2119             toid = typeid(type(relname));                  
2120             /* replace it in the arg list */
2121             lfirst(fargs) =
2122                 makeVar(vnum, 0, toid, vnum, 0);
2123         }else if (!attisset) { /* set functions don't have parameters */
2124  
2125           /* any functiona args which are typed "unknown", but aren't
2126              constants, we don't know what to do with, because we
2127              can't cast them    - jolly*/
2128           if (exprType(pair) == UNKNOWNOID &&
2129                !IsA(pair, Const))
2130               {
2131                   elog(WARN, "ParseFunc: no function named %s that takes in an unknown type as argument #%d", funcname, nargs);
2132               }
2133           else
2134               toid = exprType(pair);
2135         }
2136             
2137         oid_array[nargs++] = toid;
2138     }
2139     
2140     /*
2141      *  func_get_detail looks up the function in the catalogs, does
2142      *  disambiguation for polymorphic functions, handles inheritance,
2143      *  and returns the funcid and type and set or singleton status of
2144      *  the function's return value.  it also returns the true argument
2145      *  types to the function.  if func_get_detail returns true,
2146      *  the function exists.  otherwise, there was an error.
2147      */
2148     if (attisset) { /* we know all of these fields already */
2149         /* We create a funcnode with a placeholder function SetEval.
2150          * SetEval() never actually gets executed.  When the function
2151          * evaluation routines see it, they use the funcid projected
2152          * out from the relation as the actual function to call.
2153          * Example:  retrieve (emp.mgr.name)
2154          * The plan for this will scan the emp relation, projecting
2155          * out the mgr attribute, which is a funcid.  This function
2156          * is then called (instead of SetEval) and "name" is projected
2157          * from its result.
2158          */
2159         funcid = SetEvalRegProcedure;
2160         rettype = toid;
2161         retset = true;
2162         true_oid_array = oid_array;
2163         exists = true;
2164     } else {
2165         exists = func_get_detail(funcname, nargs, oid_array, &funcid,
2166                                  &rettype, &retset, &true_oid_array);
2167     }
2168     
2169     if (!exists)
2170         elog(WARN, "no such attribute or function %s", funcname);
2171     
2172     /* got it */
2173     funcnode = makeNode(Func);
2174     funcnode->funcid = funcid;
2175     funcnode->functype = rettype;
2176     funcnode->funcisindex = false;
2177     funcnode->funcsize = 0;
2178     funcnode->func_fcache = NULL;
2179     funcnode->func_tlist = NIL;
2180     funcnode->func_planlist = NIL;
2181     
2182     /* perform the necessary typecasting */
2183     make_arguments(nargs, fargs, oid_array, true_oid_array);
2184     
2185     /*
2186      *  for functions returning base types, we want to project out the
2187      *  return value.  set up a target list to do that.  the executor
2188      *  will ignore these for c functions, and do the right thing for
2189      *  postquel functions.
2190      */
2191     
2192     if (typeid_get_relid(rettype) == InvalidOid)
2193         funcnode->func_tlist = setup_base_tlist(rettype);
2194     
2195     /* For sets, we want to make a targetlist to project out this
2196      * attribute of the set tuples.
2197      */
2198     if (attisset) {
2199         if (!strcmp(funcname, "*")) {
2200             funcnode->func_tlist =
2201                 expandAll(pstate, relname, refname, curr_resno);
2202         } else {
2203             funcnode->func_tlist = setup_tlist(funcname,argrelid);
2204             rettype = find_atttype(argrelid, funcname);
2205         }
2206     }
2207
2208     /*
2209      * Sequence handling.
2210      */
2211     if ( funcid == SeqNextValueRegProcedure || 
2212                 funcid == SeqCurrValueRegProcedure )
2213     {
2214         Const *seq;
2215         char *seqrel;
2216         int32 aclcheck_result = -1;
2217         
2218         Assert ( length(fargs) == 1 );
2219         seq = (Const*)lfirst(fargs);
2220         if ( ! IsA ((Node*)seq, Const) )
2221             elog (WARN, "%s: only constant sequence names are acceptable", funcname);
2222         seqrel = textout ((struct varlena *) (seq->constvalue));
2223         
2224         if ( ( aclcheck_result = pg_aclcheck (seqrel, GetPgUserName(), 
2225                 ((funcid == SeqNextValueRegProcedure) ? ACL_WR : ACL_RD)) )
2226                                                 != ACLCHECK_OK )
2227             elog (WARN, "%s.%s: %s", 
2228                 seqrel, funcname, aclcheck_error_strings[aclcheck_result]);
2229         
2230         pfree (seqrel);
2231
2232         if ( funcid == SeqNextValueRegProcedure && inWhereClause )
2233             elog (WARN, "nextval of a sequence in WHERE disallowed"); 
2234     }
2235
2236     expr = makeNode(Expr);
2237     expr->typeOid = rettype;
2238     expr->opType = FUNC_EXPR;
2239     expr->oper = (Node *)funcnode;
2240     expr->args = fargs;
2241     retval = (Node*)expr;
2242     
2243     /*
2244      *  if the function returns a set of values, then we need to iterate
2245      *  over all the returned values in the executor, so we stick an
2246      *  iter node here.  if it returns a singleton, then we don't need
2247      *  the iter node.
2248      */
2249     
2250     if (retset) {
2251         Iter *iter = makeNode(Iter);
2252         iter->itertype = rettype;
2253         iter->iterexpr = retval;
2254         retval = (Node*)iter;
2255     }
2256     
2257     return(retval);
2258 }
2259
2260 /*****************************************************************************
2261  *
2262  *****************************************************************************/
2263
2264 /*
2265  * AddAggToParseState -
2266  *    add the aggregate to the list of unique aggregates in pstate. 
2267  *
2268  * SIDE EFFECT: aggno in target list entry will be modified
2269  */
2270 static void
2271 AddAggToParseState(ParseState *pstate, Aggreg *aggreg)
2272 {
2273     List *ag;
2274     int i;
2275
2276     /*
2277      * see if we have the aggregate already (we only need to record
2278      * the aggregate once)
2279      */
2280     i = 0;
2281     foreach(ag, pstate->p_aggs) {
2282         Aggreg *a = lfirst(ag);
2283         
2284         if (!strcmp(a->aggname, aggreg->aggname) &&
2285             equal(a->target, aggreg->target)) {
2286
2287             /* fill in the aggno and we're done */
2288             aggreg->aggno = i;
2289             return;
2290         }
2291         i++;
2292     }
2293
2294     /* not found, new aggregate */
2295     aggreg->aggno = i;
2296     pstate->p_numAgg++;
2297     pstate->p_aggs = lappend(pstate->p_aggs, aggreg);
2298     return;
2299 }
2300
2301 /*
2302  * finalizeAggregates -
2303  *    fill in qry_aggs from pstate. Also checks to make sure that aggregates
2304  *    are used in the proper place.
2305  */
2306 static void
2307 finalizeAggregates(ParseState *pstate, Query *qry)
2308 {    
2309     List *l;
2310     int i;
2311
2312     parseCheckAggregates(pstate, qry);
2313         
2314     qry->qry_numAgg = pstate->p_numAgg;
2315     qry->qry_aggs =
2316         (Aggreg **)palloc(sizeof(Aggreg *) * qry->qry_numAgg);
2317     i = 0;
2318     foreach(l, pstate->p_aggs)
2319         qry->qry_aggs[i++] = (Aggreg*)lfirst(l);
2320 }
2321
2322 /*    
2323  * contain_agg_clause--
2324  *    Recursively find aggreg nodes from a clause.
2325  *    
2326  *    Returns true if any aggregate found.
2327  */
2328 static bool
2329 contain_agg_clause(Node *clause)
2330 {
2331     if (clause==NULL) 
2332         return FALSE;
2333     else if (IsA(clause,Aggreg))
2334         return TRUE;
2335     else if (IsA(clause,Iter))
2336         return contain_agg_clause(((Iter*)clause)->iterexpr);
2337     else if (single_node(clause)) 
2338         return FALSE;
2339     else if (or_clause(clause)) {
2340         List *temp;
2341
2342         foreach (temp, ((Expr*)clause)->args)
2343             if (contain_agg_clause(lfirst(temp)))
2344                 return TRUE;
2345         return FALSE;
2346     } else if (is_funcclause (clause)) {
2347         List *temp;
2348
2349         foreach(temp, ((Expr *)clause)->args)
2350             if (contain_agg_clause(lfirst(temp)))
2351                 return TRUE;
2352         return FALSE;
2353     } else if (IsA(clause,ArrayRef)) {
2354         List *temp;
2355
2356         foreach(temp, ((ArrayRef*)clause)->refupperindexpr)
2357             if (contain_agg_clause(lfirst(temp)))
2358                 return TRUE;
2359         foreach(temp, ((ArrayRef*)clause)->reflowerindexpr)
2360             if (contain_agg_clause(lfirst(temp)))
2361                 return TRUE;
2362         if (contain_agg_clause(((ArrayRef*)clause)->refexpr))
2363             return TRUE;
2364         if (contain_agg_clause(((ArrayRef*)clause)->refassgnexpr))
2365             return TRUE;
2366         return FALSE;
2367     } else if (not_clause(clause))
2368         return contain_agg_clause((Node*)get_notclausearg((Expr*)clause));
2369     else if (is_opclause(clause))
2370         return (contain_agg_clause((Node*)get_leftop((Expr*)clause)) ||
2371                 contain_agg_clause((Node*)get_rightop((Expr*)clause)));
2372
2373     return FALSE;
2374 }
2375
2376 /*
2377  * exprIsAggOrGroupCol -
2378  *    returns true if the expression does not contain non-group columns.
2379  */
2380 static bool
2381 exprIsAggOrGroupCol(Node *expr, List *groupClause)
2382 {
2383     List *gl;
2384     
2385     if ( expr == NULL || IsA (expr, Const) || 
2386                 IsA (expr, Param) || IsA (expr, Aggreg) )
2387         return TRUE;
2388
2389     foreach (gl, groupClause)
2390     {
2391         GroupClause *grpcl = lfirst(gl);
2392         
2393         if ( equal (expr, grpcl->entry->expr) )
2394                 return TRUE;
2395     }
2396
2397     if ( IsA (expr, Expr) )
2398     {
2399         List *temp;
2400
2401         foreach (temp, ((Expr*)expr)->args)
2402             if (!exprIsAggOrGroupCol(lfirst(temp),groupClause))
2403                 return FALSE;
2404         return TRUE;
2405     }
2406
2407     return FALSE;
2408 }
2409
2410 /*
2411  * tleIsAggOrGroupCol -
2412  *    returns true if the TargetEntry is Agg or GroupCol.
2413  */
2414 static bool
2415 tleIsAggOrGroupCol(TargetEntry *tle, List *groupClause)
2416 {
2417     Node *expr = tle->expr;
2418     List *gl;
2419     
2420     if ( expr == NULL || IsA (expr, Const) || IsA (expr, Param) )
2421         return TRUE;
2422         
2423     foreach (gl, groupClause)
2424     {
2425         GroupClause *grpcl = lfirst(gl);
2426         
2427         if ( tle->resdom->resno == grpcl->entry->resdom->resno )
2428         {
2429             if ( contain_agg_clause ((Node*) expr) )
2430                 elog (WARN, "parser: aggregates not allowed in GROUP BY clause");
2431             return TRUE;
2432         }
2433     }
2434
2435     if ( IsA (expr, Aggreg) )
2436         return TRUE;
2437
2438     if ( IsA (expr, Expr) )
2439     {
2440         List *temp;
2441
2442         foreach (temp, ((Expr*)expr)->args)
2443             if (!exprIsAggOrGroupCol(lfirst(temp),groupClause))
2444                 return FALSE;
2445         return TRUE;
2446     }
2447
2448     return FALSE;
2449 }
2450
2451 /*
2452  * parseCheckAggregates -
2453  *    this should really be done earlier but the current grammar
2454  *    cannot differentiate functions from aggregates. So we have do check
2455  *    here when the target list and the qualifications are finalized.
2456  */
2457 static void
2458 parseCheckAggregates(ParseState *pstate, Query *qry)
2459 {
2460     List *tl;
2461     Assert(pstate->p_numAgg > 0);
2462
2463     /*
2464      * aggregates never appear in WHERE clauses. (we have to check where
2465      * clause first because if there is an aggregate, the check for
2466      * non-group column in target list may fail.)
2467      */
2468     if (contain_agg_clause(qry->qual))
2469         elog(WARN, "parser: aggregates not allowed in WHERE clause");
2470
2471     /*
2472      * the target list can only contain aggregates, group columns and
2473      * functions thereof.
2474      */
2475     foreach (tl, qry->targetList) {
2476         TargetEntry *tle = lfirst(tl);
2477         if (!tleIsAggOrGroupCol(tle, qry->groupClause))
2478             elog(WARN,
2479                  "parser: illegal use of aggregates or non-group column in target list");
2480     }
2481         
2482     /*
2483      * the expression specified in the HAVING clause has the same restriction
2484      * as those in the target list.
2485      */
2486 /*
2487  * Need to change here when we get HAVING works. Currently 
2488  * qry->havingQual is NULL.     - vadim 04/05/97
2489     if (!exprIsAggOrGroupCol(qry->havingQual, qry->groupClause))
2490         elog(WARN,
2491              "parser: illegal use of aggregates or non-group column in HAVING clause");
2492  */    
2493     return;
2494 }