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.98 1999/02/08 14:14:11 wieck 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)
65 QueryTreeList *result;
70 result = malloc(sizeof(QueryTreeList));
71 result->len = length(pl);
72 result->qtrees = (Query **) malloc(result->len * sizeof(Query *));
76 pstate = make_parsestate(parentParseState);
77 parsetree = transformStmt(pstate, lfirst(pl));
78 if (pstate->p_target_relation != NULL)
79 heap_close(pstate->p_target_relation);
81 if (extras_before != NIL)
83 result->len += length(extras_before);
84 result->qtrees = (Query **) realloc(result->qtrees, result->len * sizeof(Query *));
85 while (extras_before != NIL)
87 result->qtrees[i++] = transformStmt(pstate, lfirst(extras_before));
88 if (pstate->p_target_relation != NULL)
89 heap_close(pstate->p_target_relation);
90 extras_before = lnext(extras_before);
95 result->qtrees[i++] = parsetree;
97 if (extras_after != NIL)
99 result->len += length(extras_after);
100 result->qtrees = (Query **) realloc(result->qtrees, result->len * sizeof(Query *));
101 while (extras_after != NIL)
103 result->qtrees[i++] = transformStmt(pstate, lfirst(extras_after));
104 if (pstate->p_target_relation != NULL)
105 heap_close(pstate->p_target_relation);
106 extras_after = lnext(extras_after);
120 * transform a Parse tree. If it is an optimizable statement, turn it
124 transformStmt(ParseState *pstate, Node *parseTree)
126 Query *result = NULL;
128 switch (nodeTag(parseTree))
130 /*------------------------
131 * Non-optimizable statements
132 *------------------------
135 result = transformCreateStmt(pstate, (CreateStmt *) parseTree);
139 result = transformIndexStmt(pstate, (IndexStmt *) parseTree);
143 result = transformExtendStmt(pstate, (ExtendStmt *) parseTree);
147 result = transformRuleStmt(pstate, (RuleStmt *) parseTree);
152 ViewStmt *n = (ViewStmt *) parseTree;
154 n->query = (Query *) transformStmt(pstate, (Node *) n->query);
155 result = makeNode(Query);
156 result->commandType = CMD_UTILITY;
157 result->utilityStmt = (Node *) n;
163 MemoryContext oldcontext;
166 * make sure that this Query is allocated in TopMemory
167 * context because vacuum spans transactions and we don't
168 * want to lose the vacuum Query due to end-of-transaction
171 oldcontext = MemoryContextSwitchTo(TopMemoryContext);
172 result = makeNode(Query);
173 result->commandType = CMD_UTILITY;
174 result->utilityStmt = (Node *) parseTree;
175 MemoryContextSwitchTo(oldcontext);
181 ExplainStmt *n = (ExplainStmt *) parseTree;
183 result = makeNode(Query);
184 result->commandType = CMD_UTILITY;
185 n->query = transformStmt(pstate, (Node *) n->query);
186 result->utilityStmt = (Node *) parseTree;
190 /*------------------------
191 * Optimizable statements
192 *------------------------
195 result = transformInsertStmt(pstate, (InsertStmt *) parseTree);
199 result = transformDeleteStmt(pstate, (DeleteStmt *) parseTree);
203 result = transformUpdateStmt(pstate, (UpdateStmt *) parseTree);
207 if (!((SelectStmt *) parseTree)->portalname)
209 result = transformSelectStmt(pstate, (SelectStmt *) parseTree);
210 result->limitOffset = ((SelectStmt *)parseTree)->limitOffset;
211 result->limitCount = ((SelectStmt *)parseTree)->limitCount;
214 result = transformCursorStmt(pstate, (SelectStmt *) parseTree);
220 * other statments don't require any transformation-- just
221 * return the original parsetree, yea!
223 result = makeNode(Query);
224 result->commandType = CMD_UTILITY;
225 result->utilityStmt = (Node *) parseTree;
232 * transformDeleteStmt -
233 * transforms a Delete Statement
236 transformDeleteStmt(ParseState *pstate, DeleteStmt *stmt)
238 Query *qry = makeNode(Query);
240 qry->commandType = CMD_DELETE;
242 /* set up a range table */
243 makeRangeTable(pstate, stmt->relname, NULL);
245 qry->uniqueFlag = NULL;
247 /* fix where clause */
248 qry->qual = transformWhereClause(pstate, stmt->whereClause);
249 qry->hasSubLinks = pstate->p_hasSubLinks;
251 qry->rtable = pstate->p_rtable;
252 qry->resultRelation = refnameRangeTablePosn(pstate, stmt->relname, NULL);
254 qry->hasAggs = pstate->p_hasAggs;
255 if (pstate->p_hasAggs)
256 parseCheckAggregates(pstate, qry);
258 return (Query *) qry;
262 * transformInsertStmt -
263 * transform an Insert Statement
266 transformInsertStmt(ParseState *pstate, InsertStmt *stmt)
268 Query *qry = makeNode(Query); /* make a new query tree */
271 qry->commandType = CMD_INSERT;
272 pstate->p_is_insert = true;
274 /* set up a range table */
275 makeRangeTable(pstate, stmt->relname, stmt->fromClause);
277 qry->uniqueFlag = stmt->unique;
279 /* fix the target list */
280 icolumns = pstate->p_insert_columns = makeTargetNames(pstate, stmt->cols);
282 qry->targetList = transformTargetList(pstate, stmt->targetList);
284 /* DEFAULT handling */
285 if (length(qry->targetList) < pstate->p_target_relation->rd_att->natts &&
286 pstate->p_target_relation->rd_att->constr &&
287 pstate->p_target_relation->rd_att->constr->num_defval > 0)
289 Form_pg_attribute *att = pstate->p_target_relation->rd_att->attrs;
290 AttrDefault *defval = pstate->p_target_relation->rd_att->constr->defval;
291 int ndef = pstate->p_target_relation->rd_att->constr->num_defval;
294 * if stmt->cols == NIL then makeTargetNames returns list of all attrs.
295 * May have to shorten icolumns list...
297 if (stmt->cols == NIL)
300 int i = length(qry->targetList);
302 foreach(extrl, icolumns)
305 * decrements first, so if we started with zero items
306 * it will now be negative
312 * this an index into the targetList,
313 * so make sure we had one to start...
317 freeList(lnext(extrl));
332 foreach(tl, icolumns)
334 id = (Ident *) lfirst(tl);
335 if (namestrcmp(&(att[defval[ndef].adnum - 1]->attname), id->name) == 0)
338 if (tl != NIL) /* something given for this attr */
342 * Nothing given for this attr with DEFAULT expr, so add new
343 * TargetEntry to qry->targetList. Note, that we set resno to
344 * defval[ndef].adnum: it's what
345 * transformTargetList()->make_targetlist_expr() does for
346 * INSERT ... SELECT. But for INSERT ... VALUES
347 * pstate->p_last_resno is used. It doesn't matter for
348 * "normal" using (planner creates proper target list in
349 * preptlist.c), but may break RULEs in some way. It seems
350 * better to create proper target list here...
352 te = makeTargetEntry(makeResdom(defval[ndef].adnum,
353 att[defval[ndef].adnum - 1]->atttypid,
354 att[defval[ndef].adnum - 1]->atttypmod,
355 pstrdup(nameout(&(att[defval[ndef].adnum - 1]->attname))),
357 (Node *) stringToNode(defval[ndef].adbin));
358 qry->targetList = lappend(qry->targetList, te);
362 /* fix where clause */
363 qry->qual = transformWhereClause(pstate, stmt->whereClause);
366 * The havingQual has a similar meaning as "qual" in the where
367 * statement. So we can easily use the code from the "where clause"
368 * with some additional traversals done in
369 * .../optimizer/plan/planner.c
371 qry->havingQual = transformWhereClause(pstate, stmt->havingClause);
373 qry->hasSubLinks = pstate->p_hasSubLinks;
375 /* now the range table will not change */
376 qry->rtable = pstate->p_rtable;
377 qry->resultRelation = refnameRangeTablePosn(pstate, stmt->relname, NULL);
379 qry->groupClause = transformGroupClause(pstate,
383 /* fix order clause */
384 qry->sortClause = transformSortClause(pstate,
390 qry->hasAggs = pstate->p_hasAggs;
391 if (pstate->p_hasAggs)
392 parseCheckAggregates(pstate, qry);
395 * The INSERT INTO ... SELECT ... could have a UNION in child, so
396 * unionClause may be false
398 qry->unionall = stmt->unionall;
401 /* Just hand through the unionClause and intersectClause.
402 * We will handle it in the function Except_Intersect_Rewrite() */
403 qry->unionClause = stmt->unionClause;
404 qry->intersectClause = stmt->intersectClause;
407 * If there is a havingQual but there are no aggregates, then there is
408 * something wrong with the query because having must contain
409 * aggregates in its expressions! Otherwise the query could have been
410 * formulated using the where clause.
412 if ((qry->hasAggs == false) && (qry->havingQual != NULL))
414 elog(ERROR, "SELECT/HAVING requires aggregates to be valid");
415 return (Query *) NIL;
418 if (stmt->forUpdate != NULL)
419 transformForUpdate(qry, stmt->forUpdate);
421 return (Query *) qry;
426 * Create a table name from a list of fields.
429 makeTableName(void *elem,...)
434 char buf[NAMEDATALEN + 1];
438 va_start(args, elem);
443 /* not enough room for next part? then return nothing */
444 if ((strlen(buf) + strlen(name)) >= (sizeof(buf) - 1))
451 name = va_arg(args, void *);
456 name = palloc(strlen(buf) + 1);
463 CreateIndexName(char *table_name, char *column_name, char *label, List *indices)
469 char name2[NAMEDATALEN + 1];
471 /* use working storage, since we might be trying several possibilities */
472 strcpy(name2, column_name);
473 while (iname == NULL)
475 iname = makeTableName(table_name, name2, label, NULL);
476 /* unable to make a name at all? then quit */
483 index = lfirst(ilist);
484 if (strcasecmp(iname, index->idxname) == 0)
487 ilist = lnext(ilist);
489 /* ran through entire list? then no name conflict found so done */
493 /* the last one conflicted, so try a new name component */
497 sprintf(name2, "%s_%d", column_name, (pass + 1));
504 * transformCreateStmt -
505 * transforms the "create table" statement
506 * SQL92 allows constraints to be scattered all over, so thumb through
507 * the columns and collect all constraints into one place.
508 * If there are any implied indices (e.g. UNIQUE or PRIMARY KEY)
509 * then expand those into multiple IndexStmt blocks.
510 * - thomas 1997-12-02
513 transformCreateStmt(ParseState *pstate, CreateStmt *stmt)
516 int have_pkey = FALSE;
524 Constraint *constraint;
533 q->commandType = CMD_UTILITY;
535 elements = stmt->tableElts;
536 constraints = stmt->constraints;
540 while (elements != NIL)
542 element = lfirst(elements);
543 switch (nodeTag(element))
546 column = (ColumnDef *) element;
547 columns = lappend(columns, column);
549 if (column->is_sequence)
553 CreateSeqStmt *sequence;
555 sname = makeTableName(stmt->relname, column->colname, "seq", NULL);
557 constraint = makeNode(Constraint);
558 constraint->contype = CONSTR_DEFAULT;
559 constraint->name = sname;
560 cstring = palloc(9 + strlen(constraint->name) + 2 + 1);
561 strcpy(cstring, "nextval('");
562 strcat(cstring, constraint->name);
563 strcat(cstring, "')");
564 constraint->def = cstring;
565 constraint->keys = NULL;
567 /* The parser only allows PRIMARY KEY as a constraint for the SERIAL type.
568 * So, if there is a constraint of any kind, assume it is that.
569 * If PRIMARY KEY is specified, then don't need to gin up a UNIQUE constraint
570 * since that will be covered already.
571 * - thomas 1998-09-15
573 if (column->constraints != NIL)
575 column->constraints = lappend(column->constraints, constraint);
579 column->constraints = lcons(constraint, NIL);
581 constraint = makeNode(Constraint);
582 constraint->contype = CONSTR_UNIQUE;
583 constraint->name = makeTableName(stmt->relname, column->colname, "key", NULL);
584 column->constraints = lappend(column->constraints, constraint);
587 sequence = makeNode(CreateSeqStmt);
588 sequence->seqname = pstrdup(sname);
589 sequence->options = NIL;
591 elog(NOTICE, "CREATE TABLE will create implicit sequence %s for SERIAL column %s.%s",
592 sequence->seqname, stmt->relname, column->colname);
594 blist = lcons(sequence, NIL);
597 if (column->constraints != NIL)
599 clist = column->constraints;
602 constraint = lfirst(clist);
603 switch (constraint->contype)
606 if (column->is_not_null)
607 elog(ERROR, "CREATE TABLE/NOT NULL already specified"
608 " for %s.%s", stmt->relname, column->colname);
609 column->is_not_null = TRUE;
613 if (column->defval != NULL)
614 elog(ERROR, "CREATE TABLE/DEFAULT multiple values specified"
615 " for %s.%s", stmt->relname, column->colname);
616 column->defval = constraint->def;
620 if (constraint->name == NULL)
621 constraint->name = makeTableName(stmt->relname, "pkey", NULL);
622 if (constraint->keys == NIL)
623 constraint->keys = lappend(constraint->keys, column);
624 dlist = lappend(dlist, constraint);
628 if (constraint->name == NULL)
629 constraint->name = makeTableName(stmt->relname, column->colname, "key", NULL);
630 if (constraint->keys == NIL)
631 constraint->keys = lappend(constraint->keys, column);
632 dlist = lappend(dlist, constraint);
636 constraints = lappend(constraints, constraint);
637 if (constraint->name == NULL)
638 constraint->name = makeTableName(stmt->relname, column->colname, NULL);
642 elog(ERROR, "parser: unrecognized constraint (internal error)", NULL);
645 clist = lnext(clist);
651 constraint = (Constraint *) element;
652 switch (constraint->contype)
655 if (constraint->name == NULL)
656 constraint->name = makeTableName(stmt->relname, "pkey", NULL);
657 dlist = lappend(dlist, constraint);
662 if (constraint->name == NULL)
663 constraint->name = makeTableName(stmt->relname, "key", NULL);
665 dlist = lappend(dlist, constraint);
669 constraints = lappend(constraints, constraint);
674 elog(ERROR, "parser: illegal context for constraint (internal error)", NULL);
677 elog(ERROR, "parser: unrecognized constraint (internal error)", NULL);
683 elog(ERROR, "parser: unrecognized node (internal error)", NULL);
686 elements = lnext(elements);
689 stmt->tableElts = columns;
690 stmt->constraints = constraints;
692 /* Now run through the "deferred list" to complete the query transformation.
693 * For PRIMARY KEYs, mark each column as NOT NULL and create an index.
694 * For UNIQUE, create an index as for PRIMARY KEYS, but do not insist on NOT NULL.
696 * Note that this code does not currently look for all possible redundant cases
697 * and either ignore or stop with warning. The create might fail later when
698 * names for indices turn out to be redundant, or a user might have specified
699 * extra useless indices which might hurt performance. - thomas 1997-12-08
703 constraint = lfirst(dlist);
704 if (nodeTag(constraint) != T_Constraint)
705 elog(ERROR, "parser: unrecognized deferred node (internal error)", NULL);
707 if (constraint->contype == CONSTR_PRIMARY)
710 elog(ERROR, "CREATE TABLE/PRIMARY KEY multiple primary keys"
711 " for table %s are not legal", stmt->relname);
715 else if (constraint->contype != CONSTR_UNIQUE)
716 elog(ERROR, "parser: unrecognized deferred constraint (internal error)", NULL);
718 index = makeNode(IndexStmt);
720 index->unique = TRUE;
721 index->primary = (constraint->contype == CONSTR_PRIMARY ? TRUE:FALSE);
722 if (constraint->name != NULL)
723 index->idxname = constraint->name;
724 else if (constraint->contype == CONSTR_PRIMARY)
727 elog(ERROR, "CREATE TABLE/PRIMARY KEY multiple keys for table %s are not legal", stmt->relname);
730 index->idxname = makeTableName(stmt->relname, "pkey", NULL);
733 index->idxname = NULL;
735 index->relname = stmt->relname;
736 index->accessMethod = "btree";
737 index->indexParams = NIL;
738 index->withClause = NIL;
739 index->whereClause = NULL;
741 keys = constraint->keys;
745 columns = stmt->tableElts;
747 while (columns != NIL)
749 column = lfirst(columns);
750 if (strcasecmp(column->colname, key->name) == 0)
754 columns = lnext(columns);
757 elog(ERROR, "CREATE TABLE column '%s' in key does not exist", key->name);
759 if (constraint->contype == CONSTR_PRIMARY)
760 column->is_not_null = TRUE;
761 iparam = makeNode(IndexElem);
762 iparam->name = strcpy(palloc(strlen(column->colname) + 1), column->colname);
764 iparam->class = NULL;
765 iparam->typename = NULL;
766 index->indexParams = lappend(index->indexParams, iparam);
768 if (index->idxname == NULL)
769 index->idxname = CreateIndexName(stmt->relname, iparam->name, "key", ilist);
774 if (index->idxname == NULL)
775 elog(ERROR, "CREATE TABLE unable to construct implicit index for table %s"
776 "; name too long", stmt->relname);
778 elog(NOTICE, "CREATE TABLE/%s will create implicit index %s for table %s",
779 ((constraint->contype == CONSTR_PRIMARY) ? "PRIMARY KEY" : "UNIQUE"),
780 index->idxname, stmt->relname);
782 ilist = lappend(ilist, index);
783 dlist = lnext(dlist);
786 q->utilityStmt = (Node *) stmt;
787 extras_before = blist;
788 extras_after = ilist;
794 * transformIndexStmt -
795 * transforms the qualification of the index statement
798 transformIndexStmt(ParseState *pstate, IndexStmt *stmt)
802 qry = makeNode(Query);
803 qry->commandType = CMD_UTILITY;
805 /* take care of the where clause */
806 stmt->whereClause = transformWhereClause(pstate, stmt->whereClause);
807 qry->hasSubLinks = pstate->p_hasSubLinks;
809 stmt->rangetable = pstate->p_rtable;
811 qry->utilityStmt = (Node *) stmt;
817 * transformExtendStmt -
818 * transform the qualifications of the Extend Index Statement
822 transformExtendStmt(ParseState *pstate, ExtendStmt *stmt)
826 qry = makeNode(Query);
827 qry->commandType = CMD_UTILITY;
829 /* take care of the where clause */
830 stmt->whereClause = transformWhereClause(pstate, stmt->whereClause);
831 qry->hasSubLinks = pstate->p_hasSubLinks;
833 stmt->rangetable = pstate->p_rtable;
835 qry->utilityStmt = (Node *) stmt;
840 * transformRuleStmt -
841 * transform a Create Rule Statement. The actions is a list of parse
842 * trees which is transformed into a list of query trees.
845 transformRuleStmt(ParseState *pstate, RuleStmt *stmt)
851 qry = makeNode(Query);
852 qry->commandType = CMD_UTILITY;
855 * 'instead nothing' rules with a qualification need a query a
856 * rangetable so the rewrite handler can add the negated rule
857 * qualification to the original query. We create a query with the new
858 * command type CMD_NOTHING here that is treated special by the
861 if (stmt->actions == NIL)
863 Query *nothing_qry = makeNode(Query);
865 nothing_qry->commandType = CMD_NOTHING;
867 addRangeTableEntry(pstate, stmt->object->relname, "*CURRENT*",
869 addRangeTableEntry(pstate, stmt->object->relname, "*NEW*",
872 nothing_qry->rtable = pstate->p_rtable;
874 stmt->actions = lappend(NIL, nothing_qry);
877 actions = stmt->actions;
880 * transform each statment, like parse_analyze()
882 while (actions != NIL)
886 * NOTE: 'CURRENT' must always have a varno equal to 1 and 'NEW'
889 addRangeTableEntry(pstate, stmt->object->relname, "*CURRENT*",
891 addRangeTableEntry(pstate, stmt->object->relname, "*NEW*",
894 pstate->p_last_resno = 1;
895 pstate->p_is_rule = true; /* for expand all */
896 pstate->p_hasAggs = false;
898 action = (Query *) lfirst(actions);
899 if (action->commandType != CMD_NOTHING)
900 lfirst(actions) = transformStmt(pstate, lfirst(actions));
901 actions = lnext(actions);
904 /* take care of the where clause */
905 stmt->whereClause = transformWhereClause(pstate, stmt->whereClause);
906 qry->hasSubLinks = pstate->p_hasSubLinks;
908 qry->utilityStmt = (Node *) stmt;
914 * transformSelectStmt -
915 * transforms a Select Statement
919 transformSelectStmt(ParseState *pstate, SelectStmt *stmt)
921 Query *qry = makeNode(Query);
923 qry->commandType = CMD_SELECT;
925 /* set up a range table */
926 makeRangeTable(pstate, NULL, stmt->fromClause);
928 qry->uniqueFlag = stmt->unique;
930 qry->into = stmt->into;
931 qry->isTemp = stmt->istemp;
932 qry->isPortal = FALSE;
934 qry->targetList = transformTargetList(pstate, stmt->targetList);
936 qry->qual = transformWhereClause(pstate, stmt->whereClause);
939 * The havingQual has a similar meaning as "qual" in the where
940 * statement. So we can easily use the code from the "where clause"
941 * with some additional traversals done in optimizer/plan/planner.c
943 qry->havingQual = transformWhereClause(pstate, stmt->havingClause);
945 qry->hasSubLinks = pstate->p_hasSubLinks;
947 qry->sortClause = transformSortClause(pstate,
953 qry->groupClause = transformGroupClause(pstate,
956 qry->rtable = pstate->p_rtable;
958 qry->hasAggs = pstate->p_hasAggs;
959 if (pstate->p_hasAggs)
960 parseCheckAggregates(pstate, qry);
963 * The INSERT INTO ... SELECT ... could have a UNION in child, so
964 * unionClause may be false
966 qry->unionall = stmt->unionall;
969 /* Just hand through the unionClause and intersectClause.
970 * We will handle it in the function Except_Intersect_Rewrite() */
971 qry->unionClause = stmt->unionClause;
972 qry->intersectClause = stmt->intersectClause;
975 * If there is a havingQual but there are no aggregates, then there is
976 * something wrong with the query because having must contain
977 * aggregates in its expressions! Otherwise the query could have been
978 * formulated using the where clause.
980 if ((qry->hasAggs == false) && (qry->havingQual != NULL))
982 elog(ERROR, "SELECT/HAVING requires aggregates to be valid");
983 return (Query *) NIL;
986 if (stmt->forUpdate != NULL)
987 transformForUpdate(qry, stmt->forUpdate);
989 return (Query *) qry;
993 * transformUpdateStmt -
994 * transforms an update statement
998 transformUpdateStmt(ParseState *pstate, UpdateStmt *stmt)
1000 Query *qry = makeNode(Query);
1002 qry->commandType = CMD_UPDATE;
1003 pstate->p_is_update = true;
1006 * the FROM clause is non-standard SQL syntax. We used to be able to
1007 * do this with REPLACE in POSTQUEL so we keep the feature.
1009 makeRangeTable(pstate, stmt->relname, stmt->fromClause);
1011 qry->targetList = transformTargetList(pstate, stmt->targetList);
1013 qry->qual = transformWhereClause(pstate, stmt->whereClause);
1014 qry->hasSubLinks = pstate->p_hasSubLinks;
1016 qry->rtable = pstate->p_rtable;
1018 qry->resultRelation = refnameRangeTablePosn(pstate, stmt->relname, NULL);
1020 qry->hasAggs = pstate->p_hasAggs;
1021 if (pstate->p_hasAggs)
1022 parseCheckAggregates(pstate, qry);
1024 return (Query *) qry;
1028 * transformCursorStmt -
1029 * transform a Create Cursor Statement
1033 transformCursorStmt(ParseState *pstate, SelectStmt *stmt)
1037 qry = transformSelectStmt(pstate, stmt);
1039 qry->into = stmt->portalname;
1040 qry->isTemp = stmt->istemp;
1041 qry->isPortal = TRUE;
1042 qry->isBinary = stmt->binary; /* internal portal */
1048 /* This function steps through the tree
1049 * built up by the select_w_o_sort rule
1050 * and builds a list of all SelectStmt Nodes found
1051 * The built up list is handed back in **select_list.
1052 * If one of the SelectStmt Nodes has the 'unionall' flag
1053 * set to true *unionall_present hands back 'true' */
1055 create_select_list(Node *ptr, List **select_list, bool *unionall_present)
1057 if(IsA(ptr, SelectStmt)) {
1058 *select_list = lappend(*select_list, ptr);
1059 if(((SelectStmt *)ptr)->unionall == TRUE) *unionall_present = TRUE;
1063 /* Recursively call for all arguments. A NOT expr has no lexpr! */
1064 if (((A_Expr *)ptr)->lexpr != NULL)
1065 create_select_list(((A_Expr *)ptr)->lexpr, select_list, unionall_present);
1066 create_select_list(((A_Expr *)ptr)->rexpr, select_list, unionall_present);
1069 /* Changes the A_Expr Nodes to Expr Nodes and exchanges ANDs and ORs.
1070 * The reason for the exchange is easy: We implement INTERSECTs and EXCEPTs
1071 * by rewriting these queries to semantically equivalent queries that use
1072 * IN and NOT IN subselects. To be able to use all three operations
1073 * (UNIONs INTERSECTs and EXCEPTs) in one complex query we have to
1074 * translate the queries into Disjunctive Normal Form (DNF). Unfortunately
1075 * there is no function 'dnfify' but there is a function 'cnfify'
1076 * which produces DNF when we exchange ANDs and ORs before calling
1077 * 'cnfify' and exchange them back in the result.
1079 * If an EXCEPT or INTERSECT is present *intersect_present
1080 * hands back 'true' */
1081 Node *A_Expr_to_Expr(Node *ptr, bool *intersect_present)
1083 Node *result = NULL;
1085 switch(nodeTag(ptr))
1089 A_Expr *a = (A_Expr *)ptr;
1095 Expr *expr = makeNode(Expr);
1096 Node *lexpr = A_Expr_to_Expr(((A_Expr *)ptr)->lexpr, intersect_present);
1097 Node *rexpr = A_Expr_to_Expr(((A_Expr *)ptr)->rexpr, intersect_present);
1099 *intersect_present = TRUE;
1101 expr->typeOid = BOOLOID;
1102 expr->opType = OR_EXPR;
1103 expr->args = makeList(lexpr, rexpr, -1);
1104 result = (Node *) expr;
1109 Expr *expr = makeNode(Expr);
1110 Node *lexpr = A_Expr_to_Expr(((A_Expr *)ptr)->lexpr, intersect_present);
1111 Node *rexpr = A_Expr_to_Expr(((A_Expr *)ptr)->rexpr, intersect_present);
1113 expr->typeOid = BOOLOID;
1114 expr->opType = AND_EXPR;
1115 expr->args = makeList(lexpr, rexpr, -1);
1116 result = (Node *) expr;
1121 Expr *expr = makeNode(Expr);
1122 Node *rexpr = A_Expr_to_Expr(((A_Expr *)ptr)->rexpr, intersect_present);
1124 expr->typeOid = BOOLOID;
1125 expr->opType = NOT_EXPR;
1126 expr->args = makeList(rexpr, -1);
1127 result = (Node *) expr;
1142 CheckSelectForUpdate(Query *qry)
1144 if (qry->unionClause != NULL)
1145 elog(ERROR, "SELECT FOR UPDATE is not allowed with UNION/INTERSECT/EXCEPT clause");
1146 if (qry->uniqueFlag != NULL)
1147 elog(ERROR, "SELECT FOR UPDATE is not allowed with DISTINCT clause");
1148 if (qry->groupClause != NULL)
1149 elog(ERROR, "SELECT FOR UPDATE is not allowed with GROUP BY clause");
1151 elog(ERROR, "SELECT FOR UPDATE is not allowed with AGGREGATE");
1155 transformForUpdate(Query *qry, List *forUpdate)
1157 List *rowMark = NULL;
1162 CheckSelectForUpdate(qry);
1164 if (lfirst(forUpdate) == NULL) /* all tables */
1167 foreach (l, qry->rtable)
1169 newrm = makeNode(RowMark);
1171 newrm->info = ROW_MARK_FOR_UPDATE|ROW_ACL_FOR_UPDATE;
1172 rowMark = lappend(rowMark, newrm);
1174 qry->rowMark = nconc(qry->rowMark, rowMark);
1178 foreach (l, forUpdate)
1184 foreach (l2, qry->rtable)
1186 if (strcmp(((RangeTblEntry*)lfirst(l2))->refname, lfirst(l)) == 0)
1188 foreach (l3, rowMark)
1190 if (((RowMark*)lfirst(l3))->rti == i) /* duplicate */
1195 newrm = makeNode(RowMark);
1197 newrm->info = ROW_MARK_FOR_UPDATE|ROW_ACL_FOR_UPDATE;
1198 rowMark = lappend(rowMark, newrm);
1205 elog(ERROR, "FOR UPDATE: relation %s not found in FROM clause", lfirst(l));
1208 qry->rowMark = rowMark;