1 /*-------------------------------------------------------------------------
4 * transform the parse tree into a query tree
6 * Copyright (c) 1994, Regents of the University of California
8 * $Id: analyze.c,v 1.107 1999/05/23 21:41:14 tgl Exp $
10 *-------------------------------------------------------------------------
19 #include "access/heapam.h"
20 #include "nodes/makefuncs.h"
21 #include "nodes/memnodes.h"
22 #include "nodes/pg_list.h"
23 #include "parser/analyze.h"
24 #include "parser/parse_agg.h"
25 #include "parser/parse_clause.h"
26 #include "parser/parse_node.h"
27 #include "parser/parse_relation.h"
28 #include "parser/parse_target.h"
30 #include "parser/parse_expr.h"
31 #include "catalog/pg_type.h"
34 #include "utils/builtins.h"
35 #include "utils/mcxt.h"
37 static Query *transformStmt(ParseState *pstate, Node *stmt);
38 static Query *transformDeleteStmt(ParseState *pstate, DeleteStmt *stmt);
39 static Query *transformInsertStmt(ParseState *pstate, InsertStmt *stmt);
40 static Query *transformIndexStmt(ParseState *pstate, IndexStmt *stmt);
41 static Query *transformExtendStmt(ParseState *pstate, ExtendStmt *stmt);
42 static Query *transformRuleStmt(ParseState *query, RuleStmt *stmt);
43 static Query *transformSelectStmt(ParseState *pstate, SelectStmt *stmt);
44 static Query *transformUpdateStmt(ParseState *pstate, UpdateStmt *stmt);
45 static Query *transformCursorStmt(ParseState *pstate, SelectStmt *stmt);
46 static Query *transformCreateStmt(ParseState *pstate, CreateStmt *stmt);
48 static void transformForUpdate(Query *qry, List *forUpdate);
49 void CheckSelectForUpdate(Query *qry);
51 List *extras_before = NIL;
52 List *extras_after = NIL;
56 * analyze a list of parse trees and transform them if necessary.
58 * Returns a list of transformed parse trees. Optimizable statements are
59 * all transformed to Query while the rest stays the same.
63 parse_analyze(List *pl, ParseState *parentParseState)
71 pstate = make_parsestate(parentParseState);
72 parsetree = transformStmt(pstate, lfirst(pl));
73 if (pstate->p_target_relation != NULL)
74 heap_close(pstate->p_target_relation);
76 while (extras_before != NIL)
78 result = lappend(result,
79 transformStmt(pstate, lfirst(extras_before)));
80 if (pstate->p_target_relation != NULL)
81 heap_close(pstate->p_target_relation);
82 extras_before = lnext(extras_before);
85 result = lappend(result, parsetree);
87 while (extras_after != NIL)
89 result = lappend(result,
90 transformStmt(pstate, lfirst(extras_after)));
91 if (pstate->p_target_relation != NULL)
92 heap_close(pstate->p_target_relation);
93 extras_after = lnext(extras_after);
105 * transform a Parse tree. If it is an optimizable statement, turn it
109 transformStmt(ParseState *pstate, Node *parseTree)
111 Query *result = NULL;
113 switch (nodeTag(parseTree))
115 /*------------------------
116 * Non-optimizable statements
117 *------------------------
120 result = transformCreateStmt(pstate, (CreateStmt *) parseTree);
124 result = transformIndexStmt(pstate, (IndexStmt *) parseTree);
128 result = transformExtendStmt(pstate, (ExtendStmt *) parseTree);
132 result = transformRuleStmt(pstate, (RuleStmt *) parseTree);
137 ViewStmt *n = (ViewStmt *) parseTree;
139 n->query = (Query *) transformStmt(pstate, (Node *) n->query);
140 result = makeNode(Query);
141 result->commandType = CMD_UTILITY;
142 result->utilityStmt = (Node *) n;
148 MemoryContext oldcontext;
151 * make sure that this Query is allocated in TopMemory
152 * context because vacuum spans transactions and we don't
153 * want to lose the vacuum Query due to end-of-transaction
156 oldcontext = MemoryContextSwitchTo(TopMemoryContext);
157 result = makeNode(Query);
158 result->commandType = CMD_UTILITY;
159 result->utilityStmt = (Node *) parseTree;
160 MemoryContextSwitchTo(oldcontext);
166 ExplainStmt *n = (ExplainStmt *) parseTree;
168 result = makeNode(Query);
169 result->commandType = CMD_UTILITY;
170 n->query = transformStmt(pstate, (Node *) n->query);
171 result->utilityStmt = (Node *) parseTree;
175 /*------------------------
176 * Optimizable statements
177 *------------------------
180 result = transformInsertStmt(pstate, (InsertStmt *) parseTree);
184 result = transformDeleteStmt(pstate, (DeleteStmt *) parseTree);
188 result = transformUpdateStmt(pstate, (UpdateStmt *) parseTree);
192 if (!((SelectStmt *) parseTree)->portalname)
194 result = transformSelectStmt(pstate, (SelectStmt *) parseTree);
195 result->limitOffset = ((SelectStmt *)parseTree)->limitOffset;
196 result->limitCount = ((SelectStmt *)parseTree)->limitCount;
199 result = transformCursorStmt(pstate, (SelectStmt *) parseTree);
205 * other statments don't require any transformation-- just
206 * return the original parsetree, yea!
208 result = makeNode(Query);
209 result->commandType = CMD_UTILITY;
210 result->utilityStmt = (Node *) parseTree;
217 * transformDeleteStmt -
218 * transforms a Delete Statement
221 transformDeleteStmt(ParseState *pstate, DeleteStmt *stmt)
223 Query *qry = makeNode(Query);
225 qry->commandType = CMD_DELETE;
227 /* set up a range table */
228 makeRangeTable(pstate, stmt->relname, NULL, NULL);
230 qry->uniqueFlag = NULL;
232 /* fix where clause */
233 qry->qual = transformWhereClause(pstate, stmt->whereClause, NULL);
234 qry->hasSubLinks = pstate->p_hasSubLinks;
236 qry->rtable = pstate->p_rtable;
237 qry->resultRelation = refnameRangeTablePosn(pstate, stmt->relname, NULL);
239 qry->hasAggs = pstate->p_hasAggs;
240 if (pstate->p_hasAggs)
241 parseCheckAggregates(pstate, qry);
243 return (Query *) qry;
247 * transformInsertStmt -
248 * transform an Insert Statement
251 transformInsertStmt(ParseState *pstate, InsertStmt *stmt)
253 Query *qry = makeNode(Query); /* make a new query tree */
256 qry->commandType = CMD_INSERT;
257 pstate->p_is_insert = true;
259 /* set up a range table */
260 makeRangeTable(pstate, stmt->relname, stmt->fromClause, NULL);
262 qry->uniqueFlag = stmt->unique;
264 /* fix the target list */
265 icolumns = pstate->p_insert_columns = makeTargetNames(pstate, stmt->cols);
267 qry->targetList = transformTargetList(pstate, stmt->targetList);
269 /* DEFAULT handling */
270 if (length(qry->targetList) < pstate->p_target_relation->rd_att->natts &&
271 pstate->p_target_relation->rd_att->constr &&
272 pstate->p_target_relation->rd_att->constr->num_defval > 0)
274 Form_pg_attribute *att = pstate->p_target_relation->rd_att->attrs;
275 AttrDefault *defval = pstate->p_target_relation->rd_att->constr->defval;
276 int ndef = pstate->p_target_relation->rd_att->constr->num_defval;
279 * if stmt->cols == NIL then makeTargetNames returns list of all attrs.
280 * May have to shorten icolumns list...
282 if (stmt->cols == NIL)
285 int i = length(qry->targetList);
287 foreach(extrl, icolumns)
290 * decrements first, so if we started with zero items
291 * it will now be negative
297 * this an index into the targetList,
298 * so make sure we had one to start...
302 freeList(lnext(extrl));
317 foreach(tl, icolumns)
319 id = (Ident *) lfirst(tl);
320 if (namestrcmp(&(att[defval[ndef].adnum - 1]->attname), id->name) == 0)
323 if (tl != NIL) /* something given for this attr */
327 * Nothing given for this attr with DEFAULT expr, so add new
328 * TargetEntry to qry->targetList. Note, that we set resno to
329 * defval[ndef].adnum: it's what
330 * transformTargetList()->make_targetlist_expr() does for
331 * INSERT ... SELECT. But for INSERT ... VALUES
332 * pstate->p_last_resno is used. It doesn't matter for
333 * "normal" using (planner creates proper target list in
334 * preptlist.c), but may break RULEs in some way. It seems
335 * better to create proper target list here...
337 te = makeTargetEntry(makeResdom(defval[ndef].adnum,
338 att[defval[ndef].adnum - 1]->atttypid,
339 att[defval[ndef].adnum - 1]->atttypmod,
340 pstrdup(nameout(&(att[defval[ndef].adnum - 1]->attname))),
342 (Node *) stringToNode(defval[ndef].adbin));
343 qry->targetList = lappend(qry->targetList, te);
347 /* fix where clause */
348 qry->qual = transformWhereClause(pstate, stmt->whereClause, NULL);
351 * The havingQual has a similar meaning as "qual" in the where
352 * statement. So we can easily use the code from the "where clause"
353 * with some additional traversals done in
354 * .../optimizer/plan/planner.c
356 qry->havingQual = transformWhereClause(pstate, stmt->havingClause, NULL);
358 qry->hasSubLinks = pstate->p_hasSubLinks;
360 /* now the range table will not change */
361 qry->rtable = pstate->p_rtable;
362 qry->resultRelation = refnameRangeTablePosn(pstate, stmt->relname, NULL);
364 qry->groupClause = transformGroupClause(pstate,
368 /* fix order clause */
369 qry->sortClause = transformSortClause(pstate,
375 qry->hasAggs = pstate->p_hasAggs;
376 if (pstate->p_hasAggs || qry->groupClause)
377 parseCheckAggregates(pstate, qry);
380 * The INSERT INTO ... SELECT ... could have a UNION in child, so
381 * unionClause may be false
383 qry->unionall = stmt->unionall;
386 /* Just hand through the unionClause and intersectClause.
387 * We will handle it in the function Except_Intersect_Rewrite() */
388 qry->unionClause = stmt->unionClause;
389 qry->intersectClause = stmt->intersectClause;
392 * If there is a havingQual but there are no aggregates, then there is
393 * something wrong with the query because having must contain
394 * aggregates in its expressions! Otherwise the query could have been
395 * formulated using the where clause.
397 if ((qry->hasAggs == false) && (qry->havingQual != NULL))
399 elog(ERROR, "SELECT/HAVING requires aggregates to be valid");
400 return (Query *) NIL;
403 if (stmt->forUpdate != NULL)
404 transformForUpdate(qry, stmt->forUpdate);
406 return (Query *) qry;
411 * Create a table name from a list of fields.
414 makeTableName(void *elem,...)
419 char buf[NAMEDATALEN + 1];
423 va_start(args, elem);
428 /* not enough room for next part? then return nothing */
429 if ((strlen(buf) + strlen(name)) >= (sizeof(buf) - 1))
436 name = va_arg(args, void *);
441 name = palloc(strlen(buf) + 1);
448 CreateIndexName(char *table_name, char *column_name, char *label, List *indices)
454 char name2[NAMEDATALEN + 1];
456 /* use working storage, since we might be trying several possibilities */
457 strcpy(name2, column_name);
458 while (iname == NULL)
460 iname = makeTableName(table_name, name2, label, NULL);
461 /* unable to make a name at all? then quit */
468 index = lfirst(ilist);
469 if (strcasecmp(iname, index->idxname) == 0)
472 ilist = lnext(ilist);
474 /* ran through entire list? then no name conflict found so done */
478 /* the last one conflicted, so try a new name component */
482 sprintf(name2, "%s_%d", column_name, (pass + 1));
489 * transformCreateStmt -
490 * transforms the "create table" statement
491 * SQL92 allows constraints to be scattered all over, so thumb through
492 * the columns and collect all constraints into one place.
493 * If there are any implied indices (e.g. UNIQUE or PRIMARY KEY)
494 * then expand those into multiple IndexStmt blocks.
495 * - thomas 1997-12-02
498 transformCreateStmt(ParseState *pstate, CreateStmt *stmt)
508 Constraint *constraint;
511 List *blist = NIL; /* "before list" of things to do before creating the table */
512 List *ilist = NIL; /* "index list" of things to do after creating the table */
513 IndexStmt *index, *pkey = NULL;
517 q->commandType = CMD_UTILITY;
519 elements = stmt->tableElts;
520 constraints = stmt->constraints;
524 while (elements != NIL)
526 element = lfirst(elements);
527 switch (nodeTag(element))
530 column = (ColumnDef *) element;
531 columns = lappend(columns, column);
533 if (column->is_sequence)
537 CreateSeqStmt *sequence;
539 sname = makeTableName(stmt->relname, column->colname, "seq", NULL);
541 elog(ERROR, "CREATE TABLE/SERIAL implicit sequence name must be less than %d characters"
542 "\n\tSum of lengths of '%s' and '%s' must be less than %d",
543 NAMEDATALEN, stmt->relname, column->colname, (NAMEDATALEN-5));
545 constraint = makeNode(Constraint);
546 constraint->contype = CONSTR_DEFAULT;
547 constraint->name = sname;
548 cstring = palloc(10 + strlen(constraint->name) + 3 + 1);
549 strcpy(cstring, "nextval('\"");
550 strcat(cstring, constraint->name);
551 strcat(cstring, "\"')");
552 constraint->def = cstring;
553 constraint->keys = NULL;
555 column->constraints = lappend(column->constraints, constraint);
557 constraint = makeNode(Constraint);
558 constraint->contype = CONSTR_UNIQUE;
559 constraint->name = makeTableName(stmt->relname, column->colname, "key", NULL);
560 if (constraint->name == NULL)
561 elog(ERROR, "CREATE TABLE/SERIAL implicit index name must be less than %d characters"
562 "\n\tSum of lengths of '%s' and '%s' must be less than %d",
563 NAMEDATALEN, stmt->relname, column->colname, (NAMEDATALEN-5));
564 column->constraints = lappend(column->constraints, constraint);
566 sequence = makeNode(CreateSeqStmt);
567 sequence->seqname = pstrdup(sname);
568 sequence->options = NIL;
570 elog(NOTICE, "CREATE TABLE will create implicit sequence '%s' for SERIAL column '%s.%s'",
571 sequence->seqname, stmt->relname, column->colname);
573 blist = lcons(sequence, NIL);
576 if (column->constraints != NIL)
578 clist = column->constraints;
581 constraint = lfirst(clist);
582 switch (constraint->contype)
585 /* We should mark this explicitly,
586 * so we can tell if NULL and NOT NULL are both specified
588 if (column->is_not_null)
589 elog(ERROR, "CREATE TABLE/(NOT) NULL conflicting declaration"
590 " for '%s.%s'", stmt->relname, column->colname);
591 column->is_not_null = FALSE;
595 if (column->is_not_null)
596 elog(ERROR, "CREATE TABLE/NOT NULL already specified"
597 " for '%s.%s'", stmt->relname, column->colname);
598 column->is_not_null = TRUE;
602 if (column->defval != NULL)
603 elog(ERROR, "CREATE TABLE/DEFAULT multiple values specified"
604 " for '%s.%s'", stmt->relname, column->colname);
605 column->defval = constraint->def;
609 if (constraint->name == NULL)
610 constraint->name = makeTableName(stmt->relname, "pkey", NULL);
611 if (constraint->name == NULL)
612 elog(ERROR, "CREATE TABLE/PRIMARY KEY implicit index name must be less than %d characters"
613 "\n\tLength of '%s' must be less than %d",
614 NAMEDATALEN, stmt->relname, (NAMEDATALEN-6));
615 if (constraint->keys == NIL)
616 constraint->keys = lappend(constraint->keys, column);
617 dlist = lappend(dlist, constraint);
621 if (constraint->name == NULL)
622 constraint->name = makeTableName(stmt->relname, column->colname, "key", NULL);
623 if (constraint->name == NULL)
624 elog(ERROR, "CREATE TABLE/UNIQUE implicit index name must be less than %d characters"
625 "\n\tLength of '%s' must be less than %d",
626 NAMEDATALEN, stmt->relname, (NAMEDATALEN-5));
627 if (constraint->keys == NIL)
628 constraint->keys = lappend(constraint->keys, column);
629 dlist = lappend(dlist, constraint);
633 constraints = lappend(constraints, constraint);
634 if (constraint->name == NULL)
635 constraint->name = makeTableName(stmt->relname, column->colname, NULL);
636 if (constraint->name == NULL)
637 elog(ERROR, "CREATE TABLE/CHECK implicit constraint name must be less than %d characters"
638 "\n\tSum of lengths of '%s' and '%s' must be less than %d",
639 NAMEDATALEN, stmt->relname, column->colname, (NAMEDATALEN-1));
643 elog(ERROR, "parser: unrecognized constraint (internal error)", NULL);
646 clist = lnext(clist);
652 constraint = (Constraint *) element;
653 switch (constraint->contype)
656 if (constraint->name == NULL)
657 constraint->name = makeTableName(stmt->relname, "pkey", NULL);
658 if (constraint->name == NULL)
659 elog(ERROR, "CREATE TABLE/PRIMARY KEY implicit index name must be less than %d characters"
660 "\n\tLength of '%s' must be less than %d",
661 NAMEDATALEN, stmt->relname, (NAMEDATALEN-5));
662 dlist = lappend(dlist, constraint);
666 dlist = lappend(dlist, constraint);
670 constraints = lappend(constraints, constraint);
675 elog(ERROR, "parser: illegal context for constraint (internal error)", NULL);
678 elog(ERROR, "parser: unrecognized constraint (internal error)", NULL);
684 elog(ERROR, "parser: unrecognized node (internal error)", NULL);
687 elements = lnext(elements);
690 stmt->tableElts = columns;
691 stmt->constraints = constraints;
693 /* Now run through the "deferred list" to complete the query transformation.
694 * For PRIMARY KEYs, mark each column as NOT NULL and create an index.
695 * For UNIQUE, create an index as for PRIMARY KEYS, but do not insist on NOT NULL.
697 * Note that this code does not currently look for all possible redundant cases
698 * and either ignore or stop with warning. The create might fail later when
699 * names for indices turn out to be duplicated, or a user might have specified
700 * extra useless indices which might hurt performance. - thomas 1997-12-08
704 constraint = lfirst(dlist);
705 Assert(nodeTag(constraint) == T_Constraint);
706 Assert((constraint->contype == CONSTR_PRIMARY)
707 || (constraint->contype == CONSTR_UNIQUE));
709 index = makeNode(IndexStmt);
711 index->unique = TRUE;
712 index->primary = (constraint->contype == CONSTR_PRIMARY ? TRUE:FALSE);
716 elog(ERROR, "CREATE TABLE/PRIMARY KEY multiple primary keys"
717 " for table '%s' are not allowed", stmt->relname);
718 pkey = (IndexStmt *) index;
721 if (constraint->name != NULL)
723 index->idxname = constraint->name;
725 else if (constraint->contype == CONSTR_PRIMARY)
727 index->idxname = makeTableName(stmt->relname, "pkey", NULL);
728 if (index->idxname == NULL)
729 elog(ERROR, "CREATE TABLE/PRIMARY KEY implicit index name must be less than %d characters"
730 "\n\tLength of '%s' must be less than %d",
731 NAMEDATALEN, stmt->relname, (NAMEDATALEN-5));
735 index->idxname = NULL;
738 index->relname = stmt->relname;
739 index->accessMethod = "btree";
740 index->indexParams = NIL;
741 index->withClause = NIL;
742 index->whereClause = NULL;
744 keys = constraint->keys;
748 columns = stmt->tableElts;
750 while (columns != NIL)
752 column = lfirst(columns);
753 if (strcasecmp(column->colname, key->name) == 0)
757 columns = lnext(columns);
760 elog(ERROR, "CREATE TABLE column '%s' in key does not exist", key->name);
762 if (constraint->contype == CONSTR_PRIMARY)
763 column->is_not_null = TRUE;
764 iparam = makeNode(IndexElem);
765 iparam->name = strcpy(palloc(strlen(column->colname) + 1), column->colname);
767 iparam->class = NULL;
768 iparam->typename = NULL;
769 index->indexParams = lappend(index->indexParams, iparam);
771 if (index->idxname == NULL)
772 index->idxname = CreateIndexName(stmt->relname, iparam->name, "key", ilist);
777 if (index->idxname == NULL)
778 elog(ERROR, "CREATE TABLE unable to construct implicit index for table '%s'"
779 "; name too long", stmt->relname);
781 ilist = lappend(ilist, index);
782 dlist = lnext(dlist);
785 /* OK, now finally, if there is a primary key, then make sure that there aren't any redundant
786 * unique indices defined on columns. This can arise if someone specifies UNIQUE explicitly
787 * or if a SERIAL column was defined along with a table PRIMARY KEY constraint.
788 * - thomas 1999-05-11
790 if ((pkey != NULL) && (length(lfirst(pkey->indexParams)) == 1))
798 index = lfirst(dlist);
800 /* has a single column argument, so might be a conflicting index... */
802 && (length(index->indexParams) == 1))
804 char *pname = ((IndexElem *) lfirst(index->indexParams))->name;
805 char *iname = ((IndexElem *) lfirst(index->indexParams))->name;
806 /* same names? then don't keep... */
807 keep = (strcmp(iname, pname) != 0);
811 ilist = lappend(ilist, index);
812 dlist = lnext(dlist);
819 index = lfirst(dlist);
820 elog(NOTICE, "CREATE TABLE/%s will create implicit index '%s' for table '%s'",
821 (index->primary? "PRIMARY KEY": "UNIQUE"),
822 index->idxname, stmt->relname);
823 dlist = lnext(dlist);
826 q->utilityStmt = (Node *) stmt;
827 extras_before = blist;
828 extras_after = ilist;
831 } /* transformCreateStmt() */
834 * transformIndexStmt -
835 * transforms the qualification of the index statement
838 transformIndexStmt(ParseState *pstate, IndexStmt *stmt)
842 qry = makeNode(Query);
843 qry->commandType = CMD_UTILITY;
845 /* take care of the where clause */
846 stmt->whereClause = transformWhereClause(pstate, stmt->whereClause, NULL);
847 qry->hasSubLinks = pstate->p_hasSubLinks;
849 stmt->rangetable = pstate->p_rtable;
851 qry->utilityStmt = (Node *) stmt;
857 * transformExtendStmt -
858 * transform the qualifications of the Extend Index Statement
862 transformExtendStmt(ParseState *pstate, ExtendStmt *stmt)
866 qry = makeNode(Query);
867 qry->commandType = CMD_UTILITY;
869 /* take care of the where clause */
870 stmt->whereClause = transformWhereClause(pstate, stmt->whereClause, NULL);
871 qry->hasSubLinks = pstate->p_hasSubLinks;
873 stmt->rangetable = pstate->p_rtable;
875 qry->utilityStmt = (Node *) stmt;
880 * transformRuleStmt -
881 * transform a Create Rule Statement. The actions is a list of parse
882 * trees which is transformed into a list of query trees.
885 transformRuleStmt(ParseState *pstate, RuleStmt *stmt)
891 qry = makeNode(Query);
892 qry->commandType = CMD_UTILITY;
895 * 'instead nothing' rules with a qualification need a query a
896 * rangetable so the rewrite handler can add the negated rule
897 * qualification to the original query. We create a query with the new
898 * command type CMD_NOTHING here that is treated special by the
901 if (stmt->actions == NIL)
903 Query *nothing_qry = makeNode(Query);
905 nothing_qry->commandType = CMD_NOTHING;
907 addRangeTableEntry(pstate, stmt->object->relname, "*CURRENT*",
909 addRangeTableEntry(pstate, stmt->object->relname, "*NEW*",
912 nothing_qry->rtable = pstate->p_rtable;
914 stmt->actions = lappend(NIL, nothing_qry);
917 actions = stmt->actions;
920 * transform each statment, like parse_analyze()
922 while (actions != NIL)
926 * NOTE: 'CURRENT' must always have a varno equal to 1 and 'NEW'
929 addRangeTableEntry(pstate, stmt->object->relname, "*CURRENT*",
931 addRangeTableEntry(pstate, stmt->object->relname, "*NEW*",
934 pstate->p_last_resno = 1;
935 pstate->p_is_rule = true; /* for expand all */
936 pstate->p_hasAggs = false;
938 action = (Query *) lfirst(actions);
939 if (action->commandType != CMD_NOTHING)
940 lfirst(actions) = transformStmt(pstate, lfirst(actions));
941 actions = lnext(actions);
944 /* take care of the where clause */
945 stmt->whereClause = transformWhereClause(pstate, stmt->whereClause, NULL);
946 qry->hasSubLinks = pstate->p_hasSubLinks;
948 qry->utilityStmt = (Node *) stmt;
954 * transformSelectStmt -
955 * transforms a Select Statement
959 transformSelectStmt(ParseState *pstate, SelectStmt *stmt)
961 Query *qry = makeNode(Query);
964 qry->commandType = CMD_SELECT;
966 /* set up a range table */
967 makeRangeTable(pstate, NULL, stmt->fromClause, &qual);
969 qry->uniqueFlag = stmt->unique;
971 qry->into = stmt->into;
972 qry->isTemp = stmt->istemp;
973 qry->isPortal = FALSE;
975 qry->targetList = transformTargetList(pstate, stmt->targetList);
977 qry->qual = transformWhereClause(pstate, stmt->whereClause, qual);
980 * The havingQual has a similar meaning as "qual" in the where
981 * statement. So we can easily use the code from the "where clause"
982 * with some additional traversals done in optimizer/plan/planner.c
984 qry->havingQual = transformWhereClause(pstate, stmt->havingClause, NULL);
986 qry->hasSubLinks = pstate->p_hasSubLinks;
988 qry->sortClause = transformSortClause(pstate,
994 qry->groupClause = transformGroupClause(pstate,
997 qry->rtable = pstate->p_rtable;
999 qry->hasAggs = pstate->p_hasAggs;
1000 if (pstate->p_hasAggs || qry->groupClause)
1001 parseCheckAggregates(pstate, qry);
1004 * The INSERT INTO ... SELECT ... could have a UNION in child, so
1005 * unionClause may be false
1007 qry->unionall = stmt->unionall;
1010 /* Just hand through the unionClause and intersectClause.
1011 * We will handle it in the function Except_Intersect_Rewrite() */
1012 qry->unionClause = stmt->unionClause;
1013 qry->intersectClause = stmt->intersectClause;
1016 * If there is a havingQual but there are no aggregates, then there is
1017 * something wrong with the query because having must contain
1018 * aggregates in its expressions! Otherwise the query could have been
1019 * formulated using the where clause.
1021 if ((qry->hasAggs == false) && (qry->havingQual != NULL))
1023 elog(ERROR, "SELECT/HAVING requires aggregates to be valid");
1024 return (Query *) NIL;
1027 if (stmt->forUpdate != NULL)
1028 transformForUpdate(qry, stmt->forUpdate);
1030 return (Query *) qry;
1034 * transformUpdateStmt -
1035 * transforms an update statement
1039 transformUpdateStmt(ParseState *pstate, UpdateStmt *stmt)
1041 Query *qry = makeNode(Query);
1043 qry->commandType = CMD_UPDATE;
1044 pstate->p_is_update = true;
1047 * the FROM clause is non-standard SQL syntax. We used to be able to
1048 * do this with REPLACE in POSTQUEL so we keep the feature.
1050 makeRangeTable(pstate, stmt->relname, stmt->fromClause, NULL);
1052 qry->targetList = transformTargetList(pstate, stmt->targetList);
1054 qry->qual = transformWhereClause(pstate, stmt->whereClause, NULL);
1055 qry->hasSubLinks = pstate->p_hasSubLinks;
1057 qry->rtable = pstate->p_rtable;
1059 qry->resultRelation = refnameRangeTablePosn(pstate, stmt->relname, NULL);
1061 qry->hasAggs = pstate->p_hasAggs;
1062 if (pstate->p_hasAggs)
1063 parseCheckAggregates(pstate, qry);
1065 return (Query *) qry;
1069 * transformCursorStmt -
1070 * transform a Create Cursor Statement
1074 transformCursorStmt(ParseState *pstate, SelectStmt *stmt)
1078 qry = transformSelectStmt(pstate, stmt);
1080 qry->into = stmt->portalname;
1081 qry->isTemp = stmt->istemp;
1082 qry->isPortal = TRUE;
1083 qry->isBinary = stmt->binary; /* internal portal */
1089 /* This function steps through the tree
1090 * built up by the select_w_o_sort rule
1091 * and builds a list of all SelectStmt Nodes found
1092 * The built up list is handed back in **select_list.
1093 * If one of the SelectStmt Nodes has the 'unionall' flag
1094 * set to true *unionall_present hands back 'true' */
1096 create_select_list(Node *ptr, List **select_list, bool *unionall_present)
1098 if(IsA(ptr, SelectStmt)) {
1099 *select_list = lappend(*select_list, ptr);
1100 if(((SelectStmt *)ptr)->unionall == TRUE) *unionall_present = TRUE;
1104 /* Recursively call for all arguments. A NOT expr has no lexpr! */
1105 if (((A_Expr *)ptr)->lexpr != NULL)
1106 create_select_list(((A_Expr *)ptr)->lexpr, select_list, unionall_present);
1107 create_select_list(((A_Expr *)ptr)->rexpr, select_list, unionall_present);
1110 /* Changes the A_Expr Nodes to Expr Nodes and exchanges ANDs and ORs.
1111 * The reason for the exchange is easy: We implement INTERSECTs and EXCEPTs
1112 * by rewriting these queries to semantically equivalent queries that use
1113 * IN and NOT IN subselects. To be able to use all three operations
1114 * (UNIONs INTERSECTs and EXCEPTs) in one complex query we have to
1115 * translate the queries into Disjunctive Normal Form (DNF). Unfortunately
1116 * there is no function 'dnfify' but there is a function 'cnfify'
1117 * which produces DNF when we exchange ANDs and ORs before calling
1118 * 'cnfify' and exchange them back in the result.
1120 * If an EXCEPT or INTERSECT is present *intersect_present
1121 * hands back 'true' */
1122 Node *A_Expr_to_Expr(Node *ptr, bool *intersect_present)
1124 Node *result = NULL;
1126 switch(nodeTag(ptr))
1130 A_Expr *a = (A_Expr *)ptr;
1136 Expr *expr = makeNode(Expr);
1137 Node *lexpr = A_Expr_to_Expr(((A_Expr *)ptr)->lexpr, intersect_present);
1138 Node *rexpr = A_Expr_to_Expr(((A_Expr *)ptr)->rexpr, intersect_present);
1140 *intersect_present = TRUE;
1142 expr->typeOid = BOOLOID;
1143 expr->opType = OR_EXPR;
1144 expr->args = makeList(lexpr, rexpr, -1);
1145 result = (Node *) expr;
1150 Expr *expr = makeNode(Expr);
1151 Node *lexpr = A_Expr_to_Expr(((A_Expr *)ptr)->lexpr, intersect_present);
1152 Node *rexpr = A_Expr_to_Expr(((A_Expr *)ptr)->rexpr, intersect_present);
1154 expr->typeOid = BOOLOID;
1155 expr->opType = AND_EXPR;
1156 expr->args = makeList(lexpr, rexpr, -1);
1157 result = (Node *) expr;
1162 Expr *expr = makeNode(Expr);
1163 Node *rexpr = A_Expr_to_Expr(((A_Expr *)ptr)->rexpr, intersect_present);
1165 expr->typeOid = BOOLOID;
1166 expr->opType = NOT_EXPR;
1167 expr->args = makeList(rexpr, -1);
1168 result = (Node *) expr;
1183 CheckSelectForUpdate(Query *qry)
1185 if (qry->unionClause != NULL)
1186 elog(ERROR, "SELECT FOR UPDATE is not allowed with UNION/INTERSECT/EXCEPT clause");
1187 if (qry->uniqueFlag != NULL)
1188 elog(ERROR, "SELECT FOR UPDATE is not allowed with DISTINCT clause");
1189 if (qry->groupClause != NULL)
1190 elog(ERROR, "SELECT FOR UPDATE is not allowed with GROUP BY clause");
1192 elog(ERROR, "SELECT FOR UPDATE is not allowed with AGGREGATE");
1196 transformForUpdate(Query *qry, List *forUpdate)
1198 List *rowMark = NULL;
1203 CheckSelectForUpdate(qry);
1205 if (lfirst(forUpdate) == NULL) /* all tables */
1208 foreach (l, qry->rtable)
1210 newrm = makeNode(RowMark);
1212 newrm->info = ROW_MARK_FOR_UPDATE|ROW_ACL_FOR_UPDATE;
1213 rowMark = lappend(rowMark, newrm);
1215 qry->rowMark = nconc(qry->rowMark, rowMark);
1219 foreach (l, forUpdate)
1225 foreach (l2, qry->rtable)
1227 if (strcmp(((RangeTblEntry*)lfirst(l2))->refname, lfirst(l)) == 0)
1229 foreach (l3, rowMark)
1231 if (((RowMark*)lfirst(l3))->rti == i) /* duplicate */
1236 newrm = makeNode(RowMark);
1238 newrm->info = ROW_MARK_FOR_UPDATE|ROW_ACL_FOR_UPDATE;
1239 rowMark = lappend(rowMark, newrm);
1246 elog(ERROR, "FOR UPDATE: relation %s not found in FROM clause", lfirst(l));
1249 qry->rowMark = rowMark;