1 /*-------------------------------------------------------------------------
4 * transform the parse tree into a query tree
6 * Copyright (c) 1994, Regents of the University of California
10 * $Header: /cvsroot/pgsql/src/backend/parser/analyze.c,v 1.17 1996/11/29 15:56:16 momjian Exp $
12 *-------------------------------------------------------------------------
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 "parser/parse_query.h"
33 #include "parser/parse_state.h"
34 #include "nodes/makefuncs.h" /* for makeResdom(), etc. */
35 #include "nodes/nodeFuncs.h"
37 #include "optimizer/clauses.h"
38 #include "access/heapam.h"
40 #include "port-protos.h" /* strdup() */
42 /* convert the parse tree into a query tree */
43 static Query *transformStmt(ParseState *pstate, Node *stmt);
45 static Query *transformDeleteStmt(ParseState *pstate, DeleteStmt *stmt);
46 static Query *transformInsertStmt(ParseState *pstate, AppendStmt *stmt);
47 static Query *transformIndexStmt(ParseState *pstate, IndexStmt *stmt);
48 static Query *transformExtendStmt(ParseState *pstate, ExtendStmt *stmt);
49 static Query *transformRuleStmt(ParseState *query, RuleStmt *stmt);
50 static Query *transformSelectStmt(ParseState *pstate, RetrieveStmt *stmt);
51 static Query *transformUpdateStmt(ParseState *pstate, ReplaceStmt *stmt);
52 static Query *transformCursorStmt(ParseState *pstate, CursorStmt *stmt);
53 static Node *handleNestedDots(ParseState *pstate, Attr *attr, int *curr_resno);
55 static Node *transformExpr(ParseState *pstate, Node *expr);
57 static void makeRangeTable(ParseState *pstate, char *relname, List *frmList);
58 static List *expandAllTables(ParseState *pstate);
59 static char *figureColname(Node *expr, Node *resval);
60 static List *makeTargetNames(ParseState *pstate, List *cols);
61 static List *transformTargetList(ParseState *pstate, List *targetlist);
62 static TargetEntry *make_targetlist_expr(ParseState *pstate,
63 char *colname, Node *expr,
65 static Node *transformWhereClause(ParseState *pstate, Node *a_expr);
66 static List *transformGroupClause(ParseState *pstate, List *grouplist);
67 static List *transformSortClause(ParseState *pstate,
68 List *orderlist, List *targetlist,
71 static void parseFromClause(ParseState *pstate, List *frmList);
72 static Node *ParseFunc(ParseState *pstate, char *funcname,
73 List *fargs, int *curr_resno);
74 static List *setup_tlist(char *attname, Oid relid);
75 static List *setup_base_tlist(Oid typeid);
76 static void make_arguments(int nargs, List *fargs, Oid *input_typeids,
77 Oid *function_typeids);
78 static void AddAggToParseState(ParseState *pstate, Aggreg *aggreg);
79 static void finalizeAggregates(ParseState *pstate, Query *qry);
80 static void parseCheckAggregates(ParseState *pstate, Query *qry);
82 static bool is_lowercase(char *string);
83 static void make_lowercase(char *string);
85 /*****************************************************************************
87 *****************************************************************************/
91 * allocate and initialize a new ParseState.
92 * the CALLERS is responsible for freeing the ParseState* returned
101 pstate = malloc(sizeof(ParseState));
102 pstate->p_last_resno = 1;
103 pstate->p_rtable = NIL;
104 pstate->p_numAgg = 0;
105 pstate->p_aggs = NIL;
106 pstate->p_is_insert = false;
107 pstate->p_insert_columns = NIL;
108 pstate->p_is_update = false;
109 pstate->p_is_rule = false;
110 pstate->p_target_relation = NULL;
111 pstate->p_target_rangetblentry = NULL;
118 * analyze a list of parse trees and transform them if necessary.
120 * Returns a list of transformed parse trees. Optimizable statements are
121 * all transformed to Query while the rest stays the same.
123 * CALLER is responsible for freeing the QueryTreeList* returned
126 parse_analyze(List *pl)
128 QueryTreeList *result;
132 result = malloc(sizeof(QueryTreeList));
133 result->len = length(pl);
134 result->qtrees = (Query**)malloc(result->len * sizeof(Query*));
137 pstate = makeParseState();
138 result->qtrees[i++] = transformStmt(pstate, lfirst(pl));
140 if (pstate->p_target_relation != NULL)
141 heap_close(pstate->p_target_relation);
150 * transform a Parse tree. If it is an optimizable statement, turn it
154 transformStmt(ParseState* pstate, Node *parseTree)
156 Query* result = NULL;
158 switch(nodeTag(parseTree)) {
159 /*------------------------
160 * Non-optimizable statements
161 *------------------------
164 result = transformIndexStmt(pstate, (IndexStmt *)parseTree);
168 result = transformExtendStmt(pstate, (ExtendStmt *)parseTree);
172 result = transformRuleStmt(pstate, (RuleStmt *)parseTree);
177 ViewStmt *n = (ViewStmt *)parseTree;
178 n->query = (Query *)transformStmt(pstate, (Node*)n->query);
179 result = makeNode(Query);
180 result->commandType = CMD_UTILITY;
181 result->utilityStmt = (Node*)n;
187 MemoryContext oldcontext;
188 /* make sure that this Query is allocated in TopMemory context
189 because vacuum spans transactions and we don't want to lose
190 the vacuum Query due to end-of-transaction free'ing*/
191 oldcontext = MemoryContextSwitchTo(TopMemoryContext);
192 result = makeNode(Query);
193 result->commandType = CMD_UTILITY;
194 result->utilityStmt = (Node*)parseTree;
195 MemoryContextSwitchTo(oldcontext);
201 ExplainStmt *n = (ExplainStmt *)parseTree;
202 result = makeNode(Query);
203 result->commandType = CMD_UTILITY;
204 n->query = transformStmt(pstate, (Node*)n->query);
205 result->utilityStmt = (Node*)parseTree;
209 /*------------------------
210 * Optimizable statements
211 *------------------------
214 result = transformInsertStmt(pstate, (AppendStmt *)parseTree);
218 result = transformDeleteStmt(pstate, (DeleteStmt *)parseTree);
222 result = transformUpdateStmt(pstate, (ReplaceStmt *)parseTree);
226 result = transformCursorStmt(pstate, (CursorStmt *)parseTree);
230 result = transformSelectStmt(pstate, (RetrieveStmt *)parseTree);
235 * other statments don't require any transformation-- just
236 * return the original parsetree
238 result = makeNode(Query);
239 result->commandType = CMD_UTILITY;
240 result->utilityStmt = (Node*)parseTree;
247 * transformDeleteStmt -
248 * transforms a Delete Statement
251 transformDeleteStmt(ParseState *pstate, DeleteStmt *stmt)
253 Query *qry = makeNode(Query);
255 qry->commandType = CMD_DELETE;
257 /* set up a range table */
258 makeRangeTable(pstate, stmt->relname, NULL);
260 qry->uniqueFlag = NULL;
262 /* fix where clause */
263 qry->qual = transformWhereClause(pstate, stmt->whereClause);
265 qry->rtable = pstate->p_rtable;
266 qry->resultRelation = refnameRangeTablePosn(pstate->p_rtable, stmt->relname);
268 /* make sure we don't have aggregates in the where clause */
269 if (pstate->p_numAgg > 0)
270 parseCheckAggregates(pstate, qry);
276 * transformInsertStmt -
277 * transform an Insert Statement
280 transformInsertStmt(ParseState *pstate, AppendStmt *stmt)
282 Query *qry = makeNode(Query); /* make a new query tree */
284 qry->commandType = CMD_INSERT;
285 pstate->p_is_insert = true;
287 /* set up a range table */
288 makeRangeTable(pstate, stmt->relname, stmt->fromClause);
290 qry->uniqueFlag = NULL;
292 /* fix the target list */
293 pstate->p_insert_columns = makeTargetNames(pstate, stmt->cols);
295 qry->targetList = transformTargetList(pstate, stmt->targetList);
297 /* fix where clause */
298 qry->qual = transformWhereClause(pstate, stmt->whereClause);
300 /* now the range table will not change */
301 qry->rtable = pstate->p_rtable;
302 qry->resultRelation = refnameRangeTablePosn(pstate->p_rtable, stmt->relname);
304 if (pstate->p_numAgg > 0)
305 finalizeAggregates(pstate, qry);
311 * transformIndexStmt -
312 * transforms the qualification of the index statement
315 transformIndexStmt(ParseState *pstate, IndexStmt *stmt)
320 q->commandType = CMD_UTILITY;
322 /* take care of the where clause */
323 stmt->whereClause = transformWhereClause(pstate,stmt->whereClause);
324 stmt->rangetable = pstate->p_rtable;
326 q->utilityStmt = (Node*)stmt;
332 * transformExtendStmt -
333 * transform the qualifications of the Extend Index Statement
337 transformExtendStmt(ParseState *pstate, ExtendStmt *stmt)
342 q->commandType = CMD_UTILITY;
344 /* take care of the where clause */
345 stmt->whereClause = transformWhereClause(pstate,stmt->whereClause);
346 stmt->rangetable = pstate->p_rtable;
348 q->utilityStmt = (Node*)stmt;
353 * transformRuleStmt -
354 * transform a Create Rule Statement. The actions is a list of parse
355 * trees which is transformed into a list of query trees.
358 transformRuleStmt(ParseState *pstate, RuleStmt *stmt)
364 q->commandType = CMD_UTILITY;
366 actions = stmt->actions;
368 * transform each statment, like parse_analyze()
370 while (actions != NIL) {
372 * NOTE: 'CURRENT' must always have a varno equal to 1 and 'NEW'
375 addRangeTableEntry(pstate, stmt->object->relname, "*CURRENT*",
377 addRangeTableEntry(pstate, stmt->object->relname, "*NEW*",
380 pstate->p_last_resno = 1;
381 pstate->p_is_rule = true; /* for expand all */
382 pstate->p_numAgg = 0;
383 pstate->p_aggs = NULL;
385 lfirst(actions) = transformStmt(pstate, lfirst(actions));
386 actions = lnext(actions);
389 /* take care of the where clause */
390 stmt->whereClause = transformWhereClause(pstate,stmt->whereClause);
392 q->utilityStmt = (Node*)stmt;
398 * transformSelectStmt -
399 * transforms a Select Statement
403 transformSelectStmt(ParseState *pstate, RetrieveStmt *stmt)
405 Query *qry = makeNode(Query);
407 qry->commandType = CMD_SELECT;
409 /* set up a range table */
410 makeRangeTable(pstate, NULL, stmt->fromClause);
412 qry->uniqueFlag = stmt->unique;
414 qry->into = stmt->into;
415 qry->isPortal = FALSE;
417 /* fix the target list */
418 qry->targetList = transformTargetList(pstate, stmt->targetList);
420 /* fix where clause */
421 qry->qual = transformWhereClause(pstate,stmt->whereClause);
423 /* fix order clause */
424 qry->sortClause = transformSortClause(pstate,
429 /* fix group by clause */
430 qry->groupClause = transformGroupClause(pstate,
432 qry->rtable = pstate->p_rtable;
434 if (pstate->p_numAgg > 0)
435 finalizeAggregates(pstate, qry);
441 * transformUpdateStmt -
442 * transforms an update statement
446 transformUpdateStmt(ParseState *pstate, ReplaceStmt *stmt)
448 Query *qry = makeNode(Query);
450 qry->commandType = CMD_UPDATE;
451 pstate->p_is_update = true;
453 * the FROM clause is non-standard SQL syntax. We used to be able to
454 * do this with REPLACE in POSTQUEL so we keep the feature.
456 makeRangeTable(pstate, stmt->relname, stmt->fromClause);
458 /* fix the target list */
459 qry->targetList = transformTargetList(pstate, stmt->targetList);
461 /* fix where clause */
462 qry->qual = transformWhereClause(pstate,stmt->whereClause);
464 qry->rtable = pstate->p_rtable;
465 qry->resultRelation = refnameRangeTablePosn(pstate->p_rtable, stmt->relname);
467 /* make sure we don't have aggregates in the where clause */
468 if (pstate->p_numAgg > 0)
469 parseCheckAggregates(pstate, qry);
475 * transformCursorStmt -
476 * transform a Create Cursor Statement
480 transformCursorStmt(ParseState *pstate, CursorStmt *stmt)
482 Query *qry = makeNode(Query);
485 * in the old days, a cursor statement is a 'retrieve into portal';
486 * If you change the following, make sure you also go through the code
487 * in various places that tests the kind of operation.
489 qry->commandType = CMD_SELECT;
491 /* set up a range table */
492 makeRangeTable(pstate, NULL, stmt->fromClause);
494 qry->uniqueFlag = stmt->unique;
496 qry->into = stmt->portalname;
497 qry->isPortal = TRUE;
498 qry->isBinary = stmt->binary; /* internal portal */
500 /* fix the target list */
501 qry->targetList = transformTargetList(pstate, stmt->targetList);
503 /* fix where clause */
504 qry->qual = transformWhereClause(pstate,stmt->whereClause);
506 /* fix order clause */
507 qry->sortClause = transformSortClause(pstate,
511 /* fix group by clause */
512 qry->groupClause = transformGroupClause(pstate,
515 qry->rtable = pstate->p_rtable;
517 if (pstate->p_numAgg > 0)
518 finalizeAggregates(pstate, qry);
523 /*****************************************************************************
525 * Transform Exprs, Aggs, etc.
527 *****************************************************************************/
531 * analyze and transform expressions. Type checking and type casting is
532 * done here. The optimizer and the executor cannot handle the original
533 * (raw) expressions collected by the parse tree. Hence the transformation
537 transformExpr(ParseState *pstate, Node *expr)
544 switch(nodeTag(expr)) {
546 Attr *att = (Attr *)expr;
549 /* what if att.attrs == "*"?? */
550 temp = handleNestedDots(pstate, att, &pstate->p_last_resno);
551 if (att->indirection != NIL) {
552 List *idx = att->indirection;
554 A_Indices *ai = (A_Indices *)lfirst(idx);
555 Node *lexpr=NULL, *uexpr;
556 uexpr = transformExpr(pstate, ai->uidx); /* must exists */
557 if (exprType(uexpr) != INT4OID)
558 elog(WARN, "array index expressions must be int4's");
559 if (ai->lidx != NULL) {
560 lexpr = transformExpr(pstate, ai->lidx);
561 if (exprType(lexpr) != INT4OID)
562 elog(WARN, "array index expressions must be int4's");
566 if (ai->lidx!=NULL) pfree(ai->lidx);
570 /* note we reuse the list of indices, make sure we don't free
571 them! Otherwise, make a new list here */
574 result = (Node*)make_array_ref(temp, att->indirection);
581 A_Const *con= (A_Const *)expr;
582 Value *val = &con->val;
583 if (con->typename != NULL) {
584 result = parser_typecast(val, con->typename, -1);
586 result = (Node *)make_const(val);
591 ParamNo *pno = (ParamNo *)expr;
596 paramno = pno->number;
597 toid = param_type(paramno);
598 if (!OidIsValid(toid)) {
599 elog(WARN, "Parameter '$%d' is out of range",
602 param = makeNode(Param);
603 param->paramkind = PARAM_NUM;
604 param->paramid = (AttrNumber) paramno;
605 param->paramname = "<unnamed>";
606 param->paramtype = (Oid)toid;
607 param->param_tlist = (List*) NULL;
609 result = (Node *)param;
613 A_Expr *a = (A_Expr *)expr;
618 Node *lexpr = transformExpr(pstate, a->lexpr);
619 Node *rexpr = transformExpr(pstate, a->rexpr);
620 result = (Node *)make_op(a->opname, lexpr, rexpr);
625 Node *lexpr = transformExpr(pstate, a->lexpr);
626 result = ParseFunc(pstate,
627 "NullValue", lcons(lexpr, NIL),
628 &pstate->p_last_resno);
633 Node *lexpr = transformExpr(pstate, a->lexpr);
634 result = ParseFunc(pstate,
635 "NonNullValue", lcons(lexpr, NIL),
636 &pstate->p_last_resno);
641 Expr *expr = makeNode(Expr);
642 Node *lexpr = transformExpr(pstate, a->lexpr);
643 Node *rexpr = transformExpr(pstate, a->rexpr);
644 if (exprType(lexpr) != BOOLOID)
646 "left-hand side of AND is type '%s', not bool",
647 tname(get_id_type(exprType(lexpr))));
648 if (exprType(rexpr) != BOOLOID)
650 "right-hand side of AND is type '%s', not bool",
651 tname(get_id_type(exprType(rexpr))));
652 expr->typeOid = BOOLOID;
653 expr->opType = AND_EXPR;
654 expr->args = makeList(lexpr, rexpr, -1);
655 result = (Node *)expr;
660 Expr *expr = makeNode(Expr);
661 Node *lexpr = transformExpr(pstate, a->lexpr);
662 Node *rexpr = transformExpr(pstate, a->rexpr);
663 if (exprType(lexpr) != BOOLOID)
665 "left-hand side of OR is type '%s', not bool",
666 tname(get_id_type(exprType(lexpr))));
667 if (exprType(rexpr) != BOOLOID)
669 "right-hand side of OR is type '%s', not bool",
670 tname(get_id_type(exprType(rexpr))));
671 expr->typeOid = BOOLOID;
672 expr->opType = OR_EXPR;
673 expr->args = makeList(lexpr, rexpr, -1);
674 result = (Node *)expr;
679 Expr *expr = makeNode(Expr);
680 Node *rexpr = transformExpr(pstate, a->rexpr);
681 if (exprType(rexpr) != BOOLOID)
683 "argument to NOT is type '%s', not bool",
684 tname(get_id_type(exprType(rexpr))));
685 expr->typeOid = BOOLOID;
686 expr->opType = NOT_EXPR;
687 expr->args = makeList(rexpr, -1);
688 result = (Node *)expr;
695 Ident *ident = (Ident*)expr;
698 /* could be a column name or a relation_name */
699 if (refnameRangeTableEntry(pstate->p_rtable, ident->name) != NULL) {
701 result = (Node*)ident;
703 else if ((rte = colnameRangeTableEntry(pstate, ident->name)) != NULL)
705 Attr *att = makeNode(Attr);
707 att->relname = rte->refname;
708 att->attrs = lcons(makeString(ident->name), NIL);
710 (Node*)handleNestedDots(pstate, att, &pstate->p_last_resno);
712 elog(WARN, "attribute \"%s\" not found", ident->name);
716 FuncCall *fn = (FuncCall *)expr;
719 /* transform the list of arguments */
720 foreach(args, fn->args)
721 lfirst(args) = transformExpr(pstate, (Node*)lfirst(args));
722 result = ParseFunc(pstate,
723 fn->funcname, fn->args, &pstate->p_last_resno);
727 /* should not reach here */
728 elog(WARN, "transformExpr: does not know how to transform %d\n",
736 /*****************************************************************************
740 *****************************************************************************/
744 * turns the table references specified in the from-clause into a
745 * range table. The range table may grow as we transform the expressions
746 * in the target list. (Note that this happens because in POSTQUEL, we
747 * allow references to relations not specified in the from-clause. We
748 * also allow that in our POST-SQL)
752 parseFromClause(ParseState *pstate, List *frmList)
758 RangeVar *r = lfirst(fl);
759 RelExpr *baserel = r->relExpr;
760 char *relname = baserel->relname;
761 char *refname = r->name;
768 * marks this entry to indicate it comes from the FROM clause. In
769 * SQL, the target list can only refer to range variables specified
770 * in the from clause but we follow the more powerful POSTQUEL
771 * semantics and automatically generate the range variable if not
772 * specified. However there are times we need to know whether the
773 * entries are legitimate.
775 * eg. select * from foo f where f.x = 1; will generate wrong answer
776 * if we expand * to foo.x.
778 rte = addRangeTableEntry(pstate, relname, refname, baserel->inh, TRUE,
785 * make a range table with the specified relation (optional) and the
789 makeRangeTable(ParseState *pstate, char *relname, List *frmList)
793 parseFromClause(pstate, frmList);
798 if (refnameRangeTablePosn(pstate->p_rtable, relname) < 1)
799 rte = addRangeTableEntry(pstate, relname, relname, FALSE, FALSE, NULL);
801 rte = refnameRangeTableEntry(pstate->p_rtable, relname);
803 pstate->p_target_rangetblentry = rte;
804 Assert(pstate->p_target_relation == NULL);
805 pstate->p_target_relation = heap_open(rte->relid);
806 Assert(pstate->p_target_relation != NULL);
807 /* will close relation later */
812 * returns the Oid of the type of the expression. (Used for typechecking.)
819 switch(nodeTag(expr)) {
821 type = ((Func*)expr)->functype;
824 type = ((Iter*)expr)->itertype;
827 type = ((Var*)expr)->vartype;
830 type = ((Expr*)expr)->typeOid;
833 type = ((Const*)expr)->consttype;
836 type = ((ArrayRef*)expr)->refelemtype;
839 type = ((Aggreg*)expr)->aggtype;
842 type = ((Param*)expr)->paramtype;
849 elog(WARN, "exprType: don't know how to get type for %d node",
858 * turns '*' (in the target list) into a list of attributes (of all
859 * relations in the range table)
862 expandAllTables(ParseState *pstate)
865 List *legit_rtable=NIL;
868 rtable = pstate->p_rtable;
869 if (pstate->p_is_rule) {
871 * skip first two entries, "*new*" and "*current*"
873 rtable = lnext(lnext(pstate->p_rtable));
876 /* this should not happen */
878 elog(WARN, "cannot expand: null p_rtable");
881 * go through the range table and make a list of range table entries
882 * which we will expand.
884 foreach(rt, rtable) {
885 RangeTblEntry *rte = lfirst(rt);
888 * we only expand those specify in the from clause. (This will
889 * also prevent us from using the wrong table in inserts: eg. tenk2
890 * in "insert into tenk2 select * from tenk1;")
894 legit_rtable = lappend(legit_rtable, rte);
897 foreach(rt, legit_rtable) {
898 RangeTblEntry *rte = lfirst(rt);
902 target = expandAll(pstate, rte->relname, rte->refname,
903 &pstate->p_last_resno);
905 while (temp != NIL && lnext(temp) != NIL)
907 lnext(temp) = expandAll(pstate, rte->relname, rte->refname,
908 &pstate->p_last_resno);
917 * if the name of the resulting column is not specified in the target
918 * list, we have to guess.
922 figureColname(Node *expr, Node *resval)
924 switch (nodeTag(expr)) {
926 return (char*) /* XXX */
927 ((Aggreg *)expr)->aggname;
929 if (((Expr*)expr)->opType == FUNC_EXPR) {
930 if (nodeTag(resval)==T_FuncCall)
931 return ((FuncCall*)resval)->funcname;
941 /*****************************************************************************
945 *****************************************************************************/
949 * generate a list of column names if not supplied or
950 * test supplied column names to make sure they are in target table
951 * (used exclusively for inserts)
954 makeTargetNames(ParseState *pstate, List *cols)
958 /* Generate ResTarget if not supplied */
963 AttributeTupleForm *attr = pstate->p_target_relation->rd_att->attrs;
965 numcol = pstate->p_target_relation->rd_rel->relnatts;
966 for(i=0; i < numcol; i++) {
967 Ident *id = makeNode(Ident);
969 id->name = palloc(NAMEDATALEN+1);
970 strncpy(id->name, attr[i]->attname.data, NAMEDATALEN);
971 id->name[NAMEDATALEN]='\0';
972 id->indirection = NIL;
975 cols = tl = lcons(id, NIL);
977 lnext(tl) = lcons(id,NIL);
984 /* elog on failure */
985 (void)varattno(pstate->p_target_relation,((Ident *)lfirst(tl))->name);
991 * transformTargetList -
992 * turns a list of ResTarget's into a list of TargetEntry's
995 transformTargetList(ParseState *pstate, List *targetlist)
998 List *tail_p_target = NIL;
1000 while(targetlist != NIL) {
1001 ResTarget *res= (ResTarget *)lfirst(targetlist);
1002 TargetEntry *tent = makeNode(TargetEntry);
1004 switch(nodeTag(res->val)) {
1012 identname = ((Ident*)res->val)->name;
1013 handleTargetColname(pstate, &res->name, NULL, res->name);
1014 expr = transformExpr(pstate, (Node*)res->val);
1015 type_id = exprType(expr);
1016 type_len = tlen(get_id_type(type_id));
1017 resname = (res->name) ? res->name : identname;
1018 tent->resdom = makeResdom((AttrNumber)pstate->p_last_resno++,
1033 Node *expr = transformExpr(pstate, (Node *)res->val);
1035 handleTargetColname(pstate, &res->name, NULL, NULL);
1036 /* note indirection has not been transformed */
1037 if (pstate->p_is_insert && res->indirection!=NIL) {
1038 /* this is an array assignment */
1040 char *str, *save_str;
1043 int lindx[MAXDIM], uindx[MAXDIM];
1048 if (exprType(expr) != UNKNOWNOID ||
1050 elog(WARN, "yyparse: string constant expected");
1052 val = (char *) textout((struct varlena *)
1053 ((Const *)expr)->constvalue);
1054 str = save_str = (char*)palloc(strlen(val) + MAXDIM * 25 + 2);
1055 foreach(elt, res->indirection) {
1056 A_Indices *aind = (A_Indices *)lfirst(elt);
1057 aind->uidx = transformExpr(pstate, aind->uidx);
1058 if (!IsA(aind->uidx,Const))
1060 "Array Index for Append should be a constant");
1061 uindx[i] = ((Const *)aind->uidx)->constvalue;
1062 if (aind->lidx!=NULL) {
1063 aind->lidx = transformExpr(pstate, aind->lidx);
1064 if (!IsA(aind->lidx,Const))
1066 "Array Index for Append should be a constant");
1067 lindx[i] = ((Const*)aind->lidx)->constvalue;
1071 if (lindx[i] > uindx[i])
1072 elog(WARN, "yyparse: lower index cannot be greater than upper index");
1073 sprintf(str, "[%d:%d]", lindx[i], uindx[i]);
1077 sprintf(str, "=%s", val);
1078 rd = pstate->p_target_relation;
1080 resdomno = varattno(rd, res->name);
1081 ndims = att_attnelems(rd, resdomno);
1083 elog(WARN, "yyparse: array dimensions do not match");
1084 constval = makeNode(Value);
1085 constval->type = T_String;
1086 constval->val.str = save_str;
1087 tent = make_targetlist_expr(pstate, res->name,
1088 (Node*)make_const(constval),
1092 char *colname= res->name;
1093 /* this is not an array assignment */
1094 if (colname==NULL) {
1095 /* if you're wondering why this is here, look at
1096 * the yacc grammar for why a name can be missing. -ay
1098 colname = figureColname(expr, res->val);
1100 if (res->indirection) {
1101 List *ilist = res->indirection;
1102 while (ilist!=NIL) {
1103 A_Indices *ind = lfirst(ilist);
1104 ind->lidx = transformExpr(pstate, ind->lidx);
1105 ind->uidx = transformExpr(pstate, ind->uidx);
1106 ilist = lnext(ilist);
1109 res->name = colname;
1110 tent = make_targetlist_expr(pstate, res->name, expr,
1118 Attr *att = (Attr *)res->val;
1123 List *attrs = att->attrs;
1126 * Target item is a single '*', expand all tables
1127 * (eg. SELECT * FROM emp)
1129 if (att->relname!=NULL && !strcmp(att->relname, "*")) {
1130 if (tail_p_target == NIL)
1131 p_target = tail_p_target = expandAllTables(pstate);
1133 lnext(tail_p_target) = expandAllTables(pstate);
1135 while(lnext(tail_p_target)!=NIL)
1136 /* make sure we point to the last target entry */
1137 tail_p_target = lnext(tail_p_target);
1139 * skip rest of while loop
1141 targetlist = lnext(targetlist);
1146 * Target item is relation.*, expand the table
1147 * (eg. SELECT emp.*, dname FROM emp, dept)
1149 attrname = strVal(lfirst(att->attrs));
1150 if (att->attrs!=NIL && !strcmp(attrname,"*")) {
1151 /* tail_p_target is the target list we're building in the while
1152 * loop. Make sure we fix it after appending more nodes.
1154 if (tail_p_target == NIL)
1155 p_target = tail_p_target = expandAll(pstate, att->relname,
1156 att->relname, &pstate->p_last_resno);
1158 lnext(tail_p_target) =
1159 expandAll(pstate, att->relname, att->relname,
1160 &pstate->p_last_resno);
1161 while(lnext(tail_p_target)!=NIL)
1162 /* make sure we point to the last target entry */
1163 tail_p_target = lnext(tail_p_target);
1165 * skip the rest of the while loop
1167 targetlist = lnext(targetlist);
1173 * Target item is fully specified: ie. relation.attribute
1175 result = handleNestedDots(pstate, att, &pstate->p_last_resno);
1176 handleTargetColname(pstate, &res->name, att->relname, attrname);
1177 if (att->indirection != NIL) {
1178 List *ilist = att->indirection;
1179 while (ilist!=NIL) {
1180 A_Indices *ind = lfirst(ilist);
1181 ind->lidx = transformExpr(pstate, ind->lidx);
1182 ind->uidx = transformExpr(pstate, ind->uidx);
1183 ilist = lnext(ilist);
1185 result = (Node*)make_array_ref(result, att->indirection);
1187 type_id = exprType(result);
1188 type_len = tlen(get_id_type(type_id));
1189 /* move to last entry */
1190 while(lnext(attrs)!=NIL)
1192 resname = (res->name) ? res->name : strVal(lfirst(attrs));
1193 resnode = makeResdom((AttrNumber)pstate->p_last_resno++,
1200 tent->resdom = resnode;
1201 tent->expr = result;
1205 /* internal error */
1207 "internal error: do not know how to transform targetlist");
1211 if (p_target == NIL) {
1212 p_target = tail_p_target = lcons(tent, NIL);
1214 lnext(tail_p_target) = lcons(tent, NIL);
1215 tail_p_target = lnext(tail_p_target);
1217 targetlist = lnext(targetlist);
1225 * make_targetlist_expr -
1226 * make a TargetEntry from an expression
1228 * arrayRef is a list of transformed A_Indices
1230 static TargetEntry *
1231 make_targetlist_expr(ParseState *pstate,
1236 int type_id, type_len, attrtype, attrlen;
1244 elog(WARN, "make_targetlist_expr: invalid use of NULL expression");
1246 type_id = exprType(expr);
1250 type_len = tlen(get_id_type(type_id));
1252 /* I have no idea what the following does! */
1253 /* It appears to process target columns that will be receiving results */
1254 if (pstate->p_is_insert||pstate->p_is_update) {
1256 * append or replace query --
1257 * append, replace work only on one relation,
1258 * so multiple occurence of same resdomno is bogus
1260 rd = pstate->p_target_relation;
1262 resdomno = varattno(rd,colname);
1263 attrisset = varisset(rd,colname);
1264 attrtype = att_typeid(rd,resdomno);
1265 if ((arrayRef != NIL) && (lfirst(arrayRef) == NIL))
1266 attrtype = GetArrayElementType(attrtype);
1267 if (attrtype==BPCHAROID || attrtype==VARCHAROID) {
1268 attrlen = rd->rd_att->attrs[resdomno-1]->attlen;
1270 attrlen = tlen(get_id_type(attrtype));
1273 if(Input_is_string && Typecast_ok){
1275 if (type_id == typeid(type("unknown"))){
1276 val = (Datum)textout((struct varlena *)
1277 ((Const)lnext(expr))->constvalue);
1279 val = ((Const)lnext(expr))->constvalue;
1282 lnext(expr) = makeConst(attrtype,
1292 (Datum)fmgr(typeid_get_retinfunc(attrtype),
1293 val,get_typelem(attrtype),-1),
1295 true /* Maybe correct-- 80% chance */,
1296 false /* is not a set */);
1298 } else if((Typecast_ok) && (attrtype != type_id)){
1300 parser_typecast2(expr, get_id_type((long)attrtype));
1302 if (attrtype != type_id) {
1303 if ((attrtype == INT2OID) && (type_id == INT4OID))
1304 lfirst(expr) = lispInteger (INT2OID);
1305 else if ((attrtype == FLOAT4OID) && (type_id == FLOAT8OID))
1306 lfirst(expr) = lispInteger (FLOAT4OID);
1308 elog(WARN, "unequal type in tlist : %s \n",
1312 Input_is_string = false;
1313 Input_is_integer = false;
1317 if (attrtype != type_id) {
1318 if (IsA(expr,Const)) {
1319 /* try to cast the constant */
1320 if (arrayRef && !(((A_Indices *)lfirst(arrayRef))->lidx)) {
1321 /* updating a single item */
1322 Oid typelem = get_typelem(attrtype);
1323 expr = (Node*)parser_typecast2(expr,
1325 get_id_type((long)typelem),
1328 expr = (Node*)parser_typecast2(expr,
1330 get_id_type((long)attrtype),
1333 /* currently, we can't handle casting of expressions */
1334 elog(WARN, "parser: attribute '%s' is of type '%.*s' but expression is of type '%.*s'",
1336 NAMEDATALEN, get_id_typname(attrtype),
1337 NAMEDATALEN, get_id_typname(type_id));
1341 if (arrayRef != NIL) {
1343 Attr *att = makeNode(Attr);
1344 List *ar = arrayRef;
1345 List *upperIndexpr = NIL;
1346 List *lowerIndexpr = NIL;
1348 att->relname = pstrdup(RelationGetRelationName(rd)->data);
1349 att->attrs = lcons(makeString(colname), NIL);
1350 target_expr = (Expr*)handleNestedDots(pstate, att,
1351 &pstate->p_last_resno);
1353 A_Indices *ind = lfirst(ar);
1354 if (lowerIndexpr || (!upperIndexpr && ind->lidx)) {
1355 /* XXX assume all lowerIndexpr is non-null in
1358 lowerIndexpr = lappend(lowerIndexpr, ind->lidx);
1360 upperIndexpr = lappend(upperIndexpr, ind->uidx);
1364 expr = (Node*)make_array_set(target_expr,
1368 attrtype = att_typeid(rd,resdomno);
1369 attrlen = tlen(get_id_type(attrtype));
1372 resdomno = pstate->p_last_resno++;
1376 tent = makeNode(TargetEntry);
1378 resnode = makeResdom((AttrNumber)resdomno,
1386 tent->resdom = resnode;
1393 /*****************************************************************************
1397 *****************************************************************************/
1400 * transformWhereClause -
1401 * transforms the qualification and make sure it is of type Boolean
1405 transformWhereClause(ParseState *pstate, Node *a_expr)
1410 return (Node *)NULL; /* no qualifiers */
1412 qual = transformExpr(pstate, a_expr);
1413 if (exprType(qual) != BOOLOID) {
1415 "where clause must return type bool, not %s",
1416 tname(get_id_type(exprType(qual))));
1421 /*****************************************************************************
1425 *****************************************************************************/
1429 * returns the Resdom in the target list matching the specified varname
1434 find_tl_elt(ParseState *pstate, char *refname, char *colname, List *tlist)
1437 int real_rtable_pos = 0;
1440 real_rtable_pos = refnameRangeTablePosn(pstate->p_rtable, refname);
1443 TargetEntry *target = (TargetEntry *)lfirst(i);
1444 Resdom *resnode = target->resdom;
1445 Var *var = (Var *)target->expr;
1446 char *resname = resnode->resname;
1447 int test_rtable_pos = var->varno;
1449 if (!strcmp(resname, colname)) {
1451 if(real_rtable_pos == test_rtable_pos) {
1459 return ((Resdom *)NULL);
1463 any_ordering_op(int restype)
1468 order_op = oper("<",restype,restype);
1469 order_opid = (Oid)oprid(order_op);
1475 * transformGroupClause -
1476 * transform an Group By clause
1480 transformGroupClause(ParseState *pstate, List *grouplist)
1482 List *glist = NIL, *gl = NIL;
1484 while (grouplist != NIL) {
1485 GroupClause *grpcl = makeNode(GroupClause);
1486 Var *groupAttr = (Var*)transformExpr(pstate, (Node*)lfirst(grouplist));
1488 if (nodeTag(groupAttr) != T_Var) {
1489 elog(WARN, "parser: can only specify attribute in group by");
1491 grpcl->grpAttr = groupAttr;
1492 grpcl->grpOpoid = any_ordering_op(groupAttr->vartype);
1494 gl = glist = lcons(grpcl, NIL);
1496 lnext(gl) = lcons(grpcl, NIL);
1499 grouplist = lnext(grouplist);
1506 * transformSortClause -
1507 * transform an Order By clause
1511 transformSortClause(ParseState *pstate,
1512 List *orderlist, List *targetlist,
1515 List *sortlist = NIL;
1518 while(orderlist != NIL) {
1519 SortBy *sortby = lfirst(orderlist);
1520 SortClause *sortcl = makeNode(SortClause);
1523 resdom = find_tl_elt(pstate, sortby->range, sortby->name, targetlist);
1525 elog(WARN,"The field being sorted by must appear in the target list");
1527 sortcl->resdom = resdom;
1528 sortcl->opoid = oprid(oper(sortby->useOp,
1531 if (sortlist == NIL) {
1532 s = sortlist = lcons(sortcl, NIL);
1534 lnext(s) = lcons(sortcl, NIL);
1537 orderlist = lnext(orderlist);
1541 if (uniqueFlag[0] == '*') {
1542 /* concatenate all elements from target list
1543 that are not already in the sortby list */
1544 foreach (i,targetlist) {
1545 TargetEntry *tlelt = (TargetEntry *)lfirst(i);
1549 SortClause *sortcl = lfirst(s);
1550 if (sortcl->resdom==tlelt->resdom)
1555 /* not a member of the sortclauses yet */
1556 SortClause *sortcl = makeNode(SortClause);
1558 sortcl->resdom = tlelt->resdom;
1559 sortcl->opoid = any_ordering_op(tlelt->resdom->restype);
1561 sortlist = lappend(sortlist, sortcl);
1566 TargetEntry *tlelt = NULL;
1567 char* uniqueAttrName = uniqueFlag;
1569 /* only create sort clause with the specified unique attribute */
1570 foreach (i, targetlist) {
1571 tlelt = (TargetEntry*)lfirst(i);
1572 if (strcmp(tlelt->resdom->resname, uniqueAttrName) == 0)
1576 elog(WARN, "The field specified in the UNIQUE ON clause is not in the targetlist");
1579 foreach (s, sortlist) {
1580 SortClause *sortcl = lfirst(s);
1581 if (sortcl->resdom == tlelt->resdom)
1585 /* not a member of the sortclauses yet */
1586 SortClause *sortcl = makeNode(SortClause);
1588 sortcl->resdom = tlelt->resdom;
1589 sortcl->opoid = any_ordering_op(tlelt->resdom->restype);
1591 sortlist = lappend(sortlist, sortcl);
1601 ** HandleNestedDots --
1602 ** Given a nested dot expression (i.e. (relation func ... attr), build up
1603 ** a tree with of Iter and Func nodes.
1606 handleNestedDots(ParseState *pstate, Attr *attr, int *curr_resno)
1609 Node *retval = NULL;
1611 if (attr->paramNo != NULL) {
1612 Param *param = (Param *)transformExpr(pstate, (Node*)attr->paramNo);
1615 ParseFunc(pstate, strVal(lfirst(attr->attrs)),
1619 Ident *ident = makeNode(Ident);
1621 ident->name = attr->relname;
1622 ident->isRel = TRUE;
1624 ParseFunc(pstate, strVal(lfirst(attr->attrs)),
1629 foreach (mutator_iter, lnext(attr->attrs)) {
1630 retval = ParseFunc(pstate,strVal(lfirst(mutator_iter)),
1639 ** make_arguments --
1640 ** Given the number and types of arguments to a function, and the
1641 ** actual arguments and argument types, do the necessary typecasting.
1644 make_arguments(int nargs,
1647 Oid *function_typeids)
1650 * there are two ways an input typeid can differ from a function typeid :
1651 * either the input type inherits the function type, so no typecasting is
1652 * necessary, or the input type can be typecast into the function type.
1653 * right now, we only typecast unknowns, and that is all we check for.
1656 List *current_fargs;
1659 for (i=0, current_fargs = fargs;
1661 i++, current_fargs = lnext(current_fargs)) {
1663 if (input_typeids[i] == UNKNOWNOID && function_typeids[i] != 0) {
1664 lfirst(current_fargs) =
1665 parser_typecast2(lfirst(current_fargs),
1667 get_id_type(function_typeids[i]),
1675 ** Build a tlist that says which attribute to project to.
1676 ** This routine is called by ParseFunc() to set up a target list
1677 ** on a tuple parameter or return value. Due to a bug in 4.0,
1678 ** it's not possible to refer to system attributes in this case.
1681 setup_tlist(char *attname, Oid relid)
1689 attno = get_attnum(relid, attname);
1691 elog(WARN, "cannot reference attribute %s of tuple params/return values for functions", attname);
1693 typeid = find_atttype(relid, attname);
1694 resnode = makeResdom(1,
1696 tlen(get_id_type(typeid)),
1697 get_attname(relid, attno),
1701 varnode = makeVar(-1, attno, typeid, -1, attno);
1703 tle = makeNode(TargetEntry);
1704 tle->resdom = resnode;
1705 tle->expr = (Node*)varnode;
1706 return (lcons(tle, NIL));
1710 ** setup_base_tlist --
1711 ** Build a tlist that extracts a base type from the tuple
1712 ** returned by the executor.
1715 setup_base_tlist(Oid typeid)
1721 resnode = makeResdom(1,
1723 tlen(get_id_type(typeid)),
1728 varnode = makeVar(-1, 1, typeid, -1, 1);
1729 tle = makeNode(TargetEntry);
1730 tle->resdom = resnode;
1731 tle->expr = (Node*)varnode;
1733 return (lcons(tle, NIL));
1737 * ParseComplexProjection -
1738 * handles function calls with a single argument that is of complex type.
1739 * This routine returns NULL if it can't handle the projection (eg. sets).
1742 ParseComplexProjection(ParseState *pstate,
1754 switch (nodeTag(first_arg)) {
1760 iter = (Iter*)first_arg;
1761 func = (Func *)((Expr*)iter->iterexpr)->oper;
1762 argtype = funcid_get_rettype(func->funcid);
1763 argrelid = typeid_get_relid(argtype);
1765 ((attnum = get_attnum(argrelid, funcname))
1766 != InvalidAttrNumber)) {
1768 /* the argument is a function returning a tuple, so funcname
1769 may be a projection */
1771 /* add a tlist to the func node and return the Iter */
1772 rd = heap_openr(tname(get_id_type(argtype)));
1773 if (RelationIsValid(rd)) {
1774 relid = RelationGetRelationId(rd);
1775 relname = RelationGetRelationName(rd);
1778 if (RelationIsValid(rd)) {
1780 setup_tlist(funcname, argrelid);
1781 iter->itertype = att_typeid(rd,attnum);
1782 return ((Node*)iter);
1785 "Function %s has bad returntype %d",
1797 * The argument is a set, so this is either a projection
1798 * or a function call on this set.
1805 Expr *expr = (Expr*)first_arg;
1808 if (expr->opType != FUNC_EXPR)
1811 funcnode= (Func *) expr->oper;
1812 argtype = funcid_get_rettype(funcnode->funcid);
1813 argrelid = typeid_get_relid(argtype);
1815 * the argument is a function returning a tuple, so funcname
1816 * may be a projection
1819 (attnum = get_attnum(argrelid, funcname))
1820 != InvalidAttrNumber) {
1822 /* add a tlist to the func node */
1823 rd = heap_openr(tname(get_id_type(argtype)));
1824 if (RelationIsValid(rd)) {
1825 relid = RelationGetRelationId(rd);
1826 relname = RelationGetRelationName(rd);
1829 if (RelationIsValid(rd)) {
1832 funcnode->func_tlist =
1833 setup_tlist(funcname, argrelid);
1834 funcnode->functype = att_typeid(rd,attnum);
1836 newexpr = makeNode(Expr);
1837 newexpr->typeOid = funcnode->functype;
1838 newexpr->opType = FUNC_EXPR;
1839 newexpr->oper = (Node *)funcnode;
1840 newexpr->args = lcons(first_arg, NIL);
1842 return ((Node*)newexpr);
1847 elog(WARN, "Function %s has bad returntype %d",
1853 Param *param = (Param*)first_arg;
1855 * If the Param is a complex type, this could be a projection
1857 rd = heap_openr(tname(get_id_type(param->paramtype)));
1858 if (RelationIsValid(rd)) {
1859 relid = RelationGetRelationId(rd);
1860 relname = RelationGetRelationName(rd);
1863 if (RelationIsValid(rd) &&
1864 (attnum = get_attnum(relid, funcname))
1865 != InvalidAttrNumber) {
1867 param->paramtype = att_typeid(rd, attnum);
1868 param->param_tlist = setup_tlist(funcname, relid);
1869 return ((Node*)param);
1880 static bool is_lowercase(char *string)
1884 for(i = 0; i < strlen(string); i++) {
1885 if(string[i] >= 'A' && string[i] <= 'Z') {
1893 static void make_lowercase(char *string)
1897 for(i = 0; i < strlen(string); i++) {
1898 if(string[i] >= 'A' && string[i] <= 'Z') {
1899 string[i] = (string[i] - 'A') + 'a';
1905 ParseFunc(ParseState *pstate, char *funcname, List *fargs, int *curr_resno)
1907 Oid rettype = (Oid)0;
1908 Oid argrelid = (Oid)0;
1909 Oid funcid = (Oid)0;
1911 Node *first_arg= NULL;
1912 char *relname = NULL;
1913 char *refname = NULL;
1919 Oid *true_oid_array;
1923 bool attisset = false;
1928 first_arg = lfirst(fargs);
1929 if (first_arg == NULL)
1930 elog (WARN,"function %s does not allow NULL input",funcname);
1934 ** check for projection methods: if function takes one argument, and
1935 ** that argument is a relation, param, or PQ function returning a complex
1936 ** type, then the function could be a projection.
1938 if (length(fargs) == 1) {
1940 if (nodeTag(first_arg)==T_Ident && ((Ident*)first_arg)->isRel) {
1942 Ident *ident = (Ident*)first_arg;
1945 * first arg is a relation. This could be a projection.
1947 refname = ident->name;
1949 rte = refnameRangeTableEntry(pstate->p_rtable, refname);
1951 rte = addRangeTableEntry(pstate, refname, refname, FALSE, FALSE,NULL);
1953 relname = rte->relname;
1956 /* If the attr isn't a set, just make a var for it. If
1957 * it is a set, treat it like a function and drop through.
1959 if (get_attnum(relid, funcname) != InvalidAttrNumber) {
1963 ((Node*)make_var(pstate,
1968 /* drop through - attr is a set */
1971 } else if (ISCOMPLEX(exprType(first_arg))) {
1973 * Attempt to handle projection of a complex argument. If
1974 * ParseComplexProjection can't handle the projection, we
1975 * have to keep going.
1977 retval = ParseComplexProjection(pstate,
1982 toid = exprType(first_arg);
1983 rd = heap_openr(tname(get_id_type(toid)));
1984 if (RelationIsValid(rd)) {
1985 relname = RelationGetRelationName(rd)->data;
1989 "Type %s is not a relation type",
1990 tname(get_id_type(toid)));
1991 argrelid = typeid_get_relid(toid);
1992 /* A projection contains either an attribute name or the
1995 if ((get_attnum(argrelid, funcname) == InvalidAttrNumber)
1996 && strcmp(funcname, "*")) {
1997 elog(WARN, "Functions on sets are not yet supported");
2005 * Parsing aggregates.
2008 /* the aggregate count is a special case,
2009 ignore its base type. Treat it as zero */
2010 if (strcmp(funcname, "count") == 0)
2013 basetype = exprType(lfirst(fargs));
2014 if (SearchSysCacheTuple(AGGNAME,
2015 PointerGetDatum(funcname),
2016 ObjectIdGetDatum(basetype),
2018 Aggreg *aggreg = ParseAgg(funcname, basetype, lfirst(fargs));
2020 AddAggToParseState(pstate, aggreg);
2021 return (Node*)aggreg;
2023 /* try one more time with lowercase --djm 8/17/96 */
2024 if(!is_lowercase(funcname)) {
2025 char *lowercase_funcname = strdup(funcname);
2027 make_lowercase(lowercase_funcname);
2028 if (strcmp(lowercase_funcname, "count") == 0)
2031 basetype = exprType(lfirst(fargs));
2032 if (SearchSysCacheTuple(AGGNAME,
2033 PointerGetDatum(lowercase_funcname),
2034 ObjectIdGetDatum(basetype),
2036 Aggreg *aggreg = ParseAgg(lowercase_funcname,
2037 basetype, lfirst(fargs));
2039 AddAggToParseState(pstate, aggreg);
2040 return (Node*)aggreg;
2049 ** If we dropped through to here it's really a function (or a set, which
2050 ** is implemented as a function.)
2051 ** extract arg type info and transform relation name arguments into
2052 ** varnodes of the appropriate form.
2054 memset(&oid_array[0], 0, 8 * sizeof(Oid));
2057 foreach ( i , fargs ) {
2060 Node *pair = lfirst(i);
2062 if (nodeTag(pair)==T_Ident && ((Ident*)pair)->isRel) {
2066 refname = ((Ident*)pair)->name;
2068 rte = refnameRangeTableEntry(pstate->p_rtable, refname);
2070 rte = addRangeTableEntry(pstate, refname, refname,
2071 FALSE, FALSE, NULL);
2072 relname = rte->relname;
2074 vnum = refnameRangeTablePosn (pstate->p_rtable, rte->refname);
2077 * for func(relname), the param to the function
2078 * is the tuple under consideration. we build a special
2079 * VarNode to reflect this -- it has varno set to the
2080 * correct range table entry, but has varattno == 0 to
2081 * signal that the whole tuple is the argument.
2083 toid = typeid(type(relname));
2084 /* replace it in the arg list */
2086 makeVar(vnum, 0, toid, vnum, 0);
2087 }else if (!attisset) { /* set functions don't have parameters */
2089 /* any functiona args which are typed "unknown", but aren't
2090 constants, we don't know what to do with, because we
2091 can't cast them - jolly*/
2092 if (exprType(pair) == UNKNOWNOID &&
2095 elog(WARN, "ParseFunc: no function named %s that takes in an unknown type as argument #%d", funcname, nargs);
2098 toid = exprType(pair);
2101 oid_array[nargs++] = toid;
2105 * func_get_detail looks up the function in the catalogs, does
2106 * disambiguation for polymorphic functions, handles inheritance,
2107 * and returns the funcid and type and set or singleton status of
2108 * the function's return value. it also returns the true argument
2109 * types to the function. if func_get_detail returns true,
2110 * the function exists. otherwise, there was an error.
2112 if (attisset) { /* we know all of these fields already */
2113 /* We create a funcnode with a placeholder function SetEval.
2114 * SetEval() never actually gets executed. When the function
2115 * evaluation routines see it, they use the funcid projected
2116 * out from the relation as the actual function to call.
2117 * Example: retrieve (emp.mgr.name)
2118 * The plan for this will scan the emp relation, projecting
2119 * out the mgr attribute, which is a funcid. This function
2120 * is then called (instead of SetEval) and "name" is projected
2123 funcid = SetEvalRegProcedure;
2126 true_oid_array = oid_array;
2129 exists = func_get_detail(funcname, nargs, oid_array, &funcid,
2130 &rettype, &retset, &true_oid_array);
2134 elog(WARN, "no such attribute or function %s", funcname);
2137 funcnode = makeNode(Func);
2138 funcnode->funcid = funcid;
2139 funcnode->functype = rettype;
2140 funcnode->funcisindex = false;
2141 funcnode->funcsize = 0;
2142 funcnode->func_fcache = NULL;
2143 funcnode->func_tlist = NIL;
2144 funcnode->func_planlist = NIL;
2146 /* perform the necessary typecasting */
2147 make_arguments(nargs, fargs, oid_array, true_oid_array);
2150 * for functions returning base types, we want to project out the
2151 * return value. set up a target list to do that. the executor
2152 * will ignore these for c functions, and do the right thing for
2153 * postquel functions.
2156 if (typeid_get_relid(rettype) == InvalidOid)
2157 funcnode->func_tlist = setup_base_tlist(rettype);
2159 /* For sets, we want to make a targetlist to project out this
2160 * attribute of the set tuples.
2163 if (!strcmp(funcname, "*")) {
2164 funcnode->func_tlist =
2165 expandAll(pstate, relname, refname, curr_resno);
2167 funcnode->func_tlist = setup_tlist(funcname,argrelid);
2168 rettype = find_atttype(argrelid, funcname);
2172 expr = makeNode(Expr);
2173 expr->typeOid = rettype;
2174 expr->opType = FUNC_EXPR;
2175 expr->oper = (Node *)funcnode;
2177 retval = (Node*)expr;
2180 * if the function returns a set of values, then we need to iterate
2181 * over all the returned values in the executor, so we stick an
2182 * iter node here. if it returns a singleton, then we don't need
2187 Iter *iter = makeNode(Iter);
2188 iter->itertype = rettype;
2189 iter->iterexpr = retval;
2190 retval = (Node*)iter;
2196 /*****************************************************************************
2198 *****************************************************************************/
2201 * AddAggToParseState -
2202 * add the aggregate to the list of unique aggregates in pstate.
2204 * SIDE EFFECT: aggno in target list entry will be modified
2207 AddAggToParseState(ParseState *pstate, Aggreg *aggreg)
2213 * see if we have the aggregate already (we only need to record
2214 * the aggregate once)
2217 foreach(ag, pstate->p_aggs) {
2218 Aggreg *a = lfirst(ag);
2220 if (!strcmp(a->aggname, aggreg->aggname) &&
2221 equal(a->target, aggreg->target)) {
2223 /* fill in the aggno and we're done */
2230 /* not found, new aggregate */
2233 pstate->p_aggs = lappend(pstate->p_aggs, aggreg);
2238 * finalizeAggregates -
2239 * fill in qry_aggs from pstate. Also checks to make sure that aggregates
2240 * are used in the proper place.
2243 finalizeAggregates(ParseState *pstate, Query *qry)
2248 parseCheckAggregates(pstate, qry);
2250 qry->qry_numAgg = pstate->p_numAgg;
2252 (Aggreg **)palloc(sizeof(Aggreg *) * qry->qry_numAgg);
2254 foreach(l, pstate->p_aggs)
2255 qry->qry_aggs[i++] = (Aggreg*)lfirst(l);
2259 * contain_agg_clause--
2260 * Recursively find aggreg nodes from a clause.
2262 * Returns true if any aggregate found.
2265 contain_agg_clause(Node *clause)
2269 else if (IsA(clause,Aggreg))
2271 else if (IsA(clause,Iter))
2272 return contain_agg_clause(((Iter*)clause)->iterexpr);
2273 else if (single_node(clause))
2275 else if (or_clause(clause)) {
2278 foreach (temp, ((Expr*)clause)->args)
2279 if (contain_agg_clause(lfirst(temp)))
2282 } else if (is_funcclause (clause)) {
2285 foreach(temp, ((Expr *)clause)->args)
2286 if (contain_agg_clause(lfirst(temp)))
2289 } else if (IsA(clause,ArrayRef)) {
2292 foreach(temp, ((ArrayRef*)clause)->refupperindexpr)
2293 if (contain_agg_clause(lfirst(temp)))
2295 foreach(temp, ((ArrayRef*)clause)->reflowerindexpr)
2296 if (contain_agg_clause(lfirst(temp)))
2298 if (contain_agg_clause(((ArrayRef*)clause)->refexpr))
2300 if (contain_agg_clause(((ArrayRef*)clause)->refassgnexpr))
2303 } else if (not_clause(clause))
2304 return contain_agg_clause((Node*)get_notclausearg((Expr*)clause));
2305 else if (is_opclause(clause))
2306 return (contain_agg_clause((Node*)get_leftop((Expr*)clause)) ||
2307 contain_agg_clause((Node*)get_rightop((Expr*)clause)));
2313 * exprIsAggOrGroupCol -
2314 * returns true if the expression does not contain non-group columns.
2317 exprIsAggOrGroupCol(Node *expr, List *groupClause)
2321 else if (IsA(expr,Const))
2323 else if (IsA(expr,Var)) {
2325 Var *var = (Var*)expr;
2327 * only group columns are legal
2329 foreach (gl, groupClause) {
2330 GroupClause *grpcl = lfirst(gl);
2331 if ((grpcl->grpAttr->varno == var->varno) &&
2332 (grpcl->grpAttr->varattno == var->varattno))
2336 } else if (IsA(expr,Aggreg))
2337 /* aggregates can take group column or non-group column as argument,
2338 no further check necessary. */
2340 else if (IsA(expr,Expr)) {
2343 foreach (temp, ((Expr*)expr)->args)
2344 if (!exprIsAggOrGroupCol(lfirst(temp),groupClause))
2353 * parseCheckAggregates -
2354 * this should really be done earlier but the current grammar
2355 * cannot differentiate functions from aggregates. So we have do check
2356 * here when the target list and the qualifications are finalized.
2359 parseCheckAggregates(ParseState *pstate, Query *qry)
2362 Assert(pstate->p_numAgg > 0);
2365 * aggregates never appear in WHERE clauses. (we have to check where
2366 * clause first because if there is an aggregate, the check for
2367 * non-group column in target list may fail.)
2369 if (contain_agg_clause(qry->qual))
2370 elog(WARN, "parser: aggregates not allowed in WHERE clause");
2373 * the target list can only contain aggregates, group columns and
2374 * functions thereof.
2376 foreach (tl, qry->targetList) {
2377 TargetEntry *tle = lfirst(tl);
2378 if (!exprIsAggOrGroupCol(tle->expr, qry->groupClause))
2380 "parser: illegal use of aggregates or non-group column in target list");
2384 * the expression specified in the HAVING clause has the same restriction
2385 * as those in the target list.
2387 if (!exprIsAggOrGroupCol(qry->havingQual, qry->groupClause))
2389 "parser: illegal use of aggregates or non-group column in HAVING clause");