1 /*-------------------------------------------------------------------------
4 * transform the parse tree into a query tree
6 * Portions Copyright (c) 1996-2000, PostgreSQL, Inc
7 * Portions Copyright (c) 1994, Regents of the University of California
9 * $Id: analyze.c,v 1.146 2000/06/09 01:44:18 momjian Exp $
11 *-------------------------------------------------------------------------
16 #include "access/heapam.h"
17 #include "catalog/catname.h"
18 #include "catalog/pg_index.h"
19 #include "catalog/pg_type.h"
20 #include "nodes/makefuncs.h"
21 #include "parser/analyze.h"
22 #include "parser/parse.h"
23 #include "parser/parse_agg.h"
24 #include "parser/parse_clause.h"
25 #include "parser/parse_relation.h"
26 #include "parser/parse_target.h"
27 #include "parser/parse_type.h"
28 #include "utils/builtins.h"
29 #include "utils/fmgroids.h"
31 void CheckSelectForUpdate(Query *qry); /* no points for style... */
33 static Query *transformStmt(ParseState *pstate, Node *stmt);
34 static Query *transformDeleteStmt(ParseState *pstate, DeleteStmt *stmt);
35 static Query *transformInsertStmt(ParseState *pstate, InsertStmt *stmt);
36 static Query *transformIndexStmt(ParseState *pstate, IndexStmt *stmt);
37 static Query *transformExtendStmt(ParseState *pstate, ExtendStmt *stmt);
38 static Query *transformRuleStmt(ParseState *query, RuleStmt *stmt);
39 static Query *transformSelectStmt(ParseState *pstate, SelectStmt *stmt);
40 static Query *transformUpdateStmt(ParseState *pstate, UpdateStmt *stmt);
41 static Query *transformCursorStmt(ParseState *pstate, SelectStmt *stmt);
42 static Query *transformCreateStmt(ParseState *pstate, CreateStmt *stmt);
43 static Query *transformAlterTableStmt(ParseState *pstate, AlterTableStmt *stmt);
45 static void transformForUpdate(Query *qry, List *forUpdate);
46 static void transformFkeyGetPrimaryKey(FkConstraint *fkconstraint);
47 static void transformConstraintAttrs(List *constraintList);
48 static void transformColumnType(ParseState *pstate, ColumnDef *column);
50 /* kluge to return extra info from transformCreateStmt() */
51 static List *extras_before;
52 static List *extras_after;
57 * analyze a list of parse trees and transform them if necessary.
59 * Returns a list of transformed parse trees. Optimizable statements are
60 * all transformed to Query while the rest stays the same.
64 parse_analyze(List *pl, ParseState *parentParseState)
72 extras_before = extras_after = NIL;
73 pstate = make_parsestate(parentParseState);
75 parsetree = transformStmt(pstate, lfirst(pl));
76 if (pstate->p_target_relation != NULL)
77 heap_close(pstate->p_target_relation, AccessShareLock);
78 pstate->p_target_relation = NULL;
79 pstate->p_target_rangetblentry = NULL;
81 while (extras_before != NIL)
83 result = lappend(result,
84 transformStmt(pstate, lfirst(extras_before)));
85 if (pstate->p_target_relation != NULL)
86 heap_close(pstate->p_target_relation, AccessShareLock);
87 pstate->p_target_relation = NULL;
88 pstate->p_target_rangetblentry = NULL;
89 extras_before = lnext(extras_before);
92 result = lappend(result, parsetree);
94 while (extras_after != NIL)
96 result = lappend(result,
97 transformStmt(pstate, lfirst(extras_after)));
98 if (pstate->p_target_relation != NULL)
99 heap_close(pstate->p_target_relation, AccessShareLock);
100 pstate->p_target_relation = NULL;
101 pstate->p_target_rangetblentry = NULL;
102 extras_after = lnext(extras_after);
114 * transform a Parse tree. If it is an optimizable statement, turn it
118 transformStmt(ParseState *pstate, Node *parseTree)
120 Query *result = NULL;
122 switch (nodeTag(parseTree))
124 /*------------------------
125 * Non-optimizable statements
126 *------------------------
129 result = transformCreateStmt(pstate, (CreateStmt *) parseTree);
133 result = transformIndexStmt(pstate, (IndexStmt *) parseTree);
137 result = transformExtendStmt(pstate, (ExtendStmt *) parseTree);
141 result = transformRuleStmt(pstate, (RuleStmt *) parseTree);
146 ViewStmt *n = (ViewStmt *) parseTree;
148 n->query = (Query *) transformStmt(pstate, (Node *) n->query);
151 * If a list of column names was given, run through and
152 * insert these into the actual query tree. - thomas
155 if (n->aliases != NIL)
158 List *targetList = n->query->targetList;
160 if (length(targetList) < length(n->aliases))
161 elog(ERROR, "CREATE VIEW specifies %d columns"
162 " but only %d columns are present",
163 length(targetList), length(n->aliases));
165 for (i = 0; i < length(n->aliases); i++)
171 id = nth(i, n->aliases);
172 Assert(nodeTag(id) == T_Ident);
173 te = nth(i, targetList);
174 Assert(nodeTag(te) == T_TargetEntry);
176 Assert(nodeTag(rd) == T_Resdom);
177 rd->resname = pstrdup(id->name);
180 result = makeNode(Query);
181 result->commandType = CMD_UTILITY;
182 result->utilityStmt = (Node *) n;
188 MemoryContext oldcontext;
191 * make sure that this Query is allocated in TopMemory
192 * context because vacuum spans transactions and we don't
193 * want to lose the vacuum Query due to end-of-transaction
196 oldcontext = MemoryContextSwitchTo(TopMemoryContext);
197 result = makeNode(Query);
198 result->commandType = CMD_UTILITY;
199 result->utilityStmt = (Node *) parseTree;
200 MemoryContextSwitchTo(oldcontext);
206 ExplainStmt *n = (ExplainStmt *) parseTree;
208 result = makeNode(Query);
209 result->commandType = CMD_UTILITY;
210 n->query = transformStmt(pstate, (Node *) n->query);
211 result->utilityStmt = (Node *) parseTree;
215 case T_AlterTableStmt:
216 result = transformAlterTableStmt(pstate, (AlterTableStmt *) parseTree);
219 /*------------------------
220 * Optimizable statements
221 *------------------------
224 result = transformInsertStmt(pstate, (InsertStmt *) parseTree);
228 result = transformDeleteStmt(pstate, (DeleteStmt *) parseTree);
232 result = transformUpdateStmt(pstate, (UpdateStmt *) parseTree);
236 if (!((SelectStmt *) parseTree)->portalname)
238 result = transformSelectStmt(pstate, (SelectStmt *) parseTree);
239 result->limitOffset = ((SelectStmt *) parseTree)->limitOffset;
240 result->limitCount = ((SelectStmt *) parseTree)->limitCount;
243 result = transformCursorStmt(pstate, (SelectStmt *) parseTree);
249 * other statments don't require any transformation-- just
250 * return the original parsetree, yea!
252 result = makeNode(Query);
253 result->commandType = CMD_UTILITY;
254 result->utilityStmt = (Node *) parseTree;
261 * transformDeleteStmt -
262 * transforms a Delete Statement
265 transformDeleteStmt(ParseState *pstate, DeleteStmt *stmt)
267 Query *qry = makeNode(Query);
269 qry->commandType = CMD_DELETE;
271 /* set up a range table */
272 makeRangeTable(pstate, NULL);
273 setTargetTable(pstate, stmt->relname, stmt->inh);
275 qry->distinctClause = NIL;
277 /* fix where clause */
278 qry->qual = transformWhereClause(pstate, stmt->whereClause);
280 qry->rtable = pstate->p_rtable;
281 qry->resultRelation = refnameRangeTablePosn(pstate, stmt->relname, NULL);
283 qry->hasSubLinks = pstate->p_hasSubLinks;
284 qry->hasAggs = pstate->p_hasAggs;
285 if (pstate->p_hasAggs)
286 parseCheckAggregates(pstate, qry);
288 return (Query *) qry;
292 * transformInsertStmt -
293 * transform an Insert Statement
296 transformInsertStmt(ParseState *pstate, InsertStmt *stmt)
298 Query *qry = makeNode(Query);
306 qry->commandType = CMD_INSERT;
307 pstate->p_is_insert = true;
310 * Initial processing steps are just like SELECT, which should not
311 * be surprising, since we may be handling an INSERT ... SELECT.
312 * It is important that we finish processing all the SELECT subclauses
313 * before we start doing any INSERT-specific processing; otherwise
314 * the behavior of SELECT within INSERT might be different from a
315 * stand-alone SELECT. (Indeed, Postgres up through 6.5 had bugs of
316 * just that nature...)
320 /* set up a range table --- note INSERT target is not in it yet */
321 makeRangeTable(pstate, stmt->fromClause);
323 qry->targetList = transformTargetList(pstate, stmt->targetList);
325 qry->qual = transformWhereClause(pstate, stmt->whereClause);
328 * Initial processing of HAVING clause is just like WHERE clause.
329 * Additional work will be done in optimizer/plan/planner.c.
331 qry->havingQual = transformWhereClause(pstate, stmt->havingClause);
333 qry->groupClause = transformGroupClause(pstate,
337 /* An InsertStmt has no sortClause */
338 qry->sortClause = NIL;
340 qry->distinctClause = transformDistinctClause(pstate,
341 stmt->distinctClause,
345 qry->hasSubLinks = pstate->p_hasSubLinks;
346 qry->hasAggs = pstate->p_hasAggs;
347 if (pstate->p_hasAggs || qry->groupClause || qry->havingQual)
348 parseCheckAggregates(pstate, qry);
351 * The INSERT INTO ... SELECT ... could have a UNION in child, so
352 * unionClause may be false
354 qry->unionall = stmt->unionall;
357 * Just hand through the unionClause and intersectClause. We will
358 * handle it in the function Except_Intersect_Rewrite()
360 qry->unionClause = stmt->unionClause;
361 qry->intersectClause = stmt->intersectClause;
364 * Now we are done with SELECT-like processing, and can get on with
365 * transforming the target list to match the INSERT target columns.
367 * In particular, it's time to add the INSERT target to the rangetable.
368 * (We didn't want it there until now since it shouldn't be visible in
371 setTargetTable(pstate, stmt->relname, FALSE);
373 /* now the range table will not change */
374 qry->rtable = pstate->p_rtable;
375 qry->resultRelation = refnameRangeTablePosn(pstate, stmt->relname, NULL);
377 /* Prepare to assign non-conflicting resnos to resjunk attributes */
378 if (pstate->p_last_resno <= pstate->p_target_relation->rd_rel->relnatts)
379 pstate->p_last_resno = pstate->p_target_relation->rd_rel->relnatts + 1;
381 /* Validate stmt->cols list, or build default list if no list given */
382 icolumns = checkInsertTargets(pstate, stmt->cols, &attrnos);
384 /* Prepare non-junk columns for assignment to target table */
387 foreach(tl, qry->targetList)
389 TargetEntry *tle = (TargetEntry *) lfirst(tl);
390 Resdom *resnode = tle->resdom;
393 if (resnode->resjunk)
397 * Resjunk nodes need no additional processing, but be sure
398 * they have names and resnos that do not match any target
399 * columns; else rewriter or planner might get confused.
401 resnode->resname = "?resjunk?";
402 resnode->resno = (AttrNumber) pstate->p_last_resno++;
405 if (icolumns == NIL || attnos == NIL)
406 elog(ERROR, "INSERT has more expressions than target columns");
407 id = (Ident *) lfirst(icolumns);
408 updateTargetListEntry(pstate, tle, id->name, lfirsti(attnos),
411 icolumns = lnext(icolumns);
412 attnos = lnext(attnos);
416 * It is possible that the targetlist has fewer entries than were in
417 * the columns list. We do not consider this an error (perhaps we
418 * should, if the columns list was explictly given?). We must
419 * truncate the attrnos list to only include the attrs actually
420 * provided, else we will fail to apply defaults for them below.
423 attrnos = ltruncate(numuseratts, attrnos);
426 * Add targetlist items to assign DEFAULT values to any columns that
427 * have defaults and were not assigned to by the user.
429 * XXX wouldn't it make more sense to do this further downstream, after
432 rd_att = pstate->p_target_relation->rd_att;
433 if (rd_att->constr && rd_att->constr->num_defval > 0)
435 Form_pg_attribute *att = rd_att->attrs;
436 AttrDefault *defval = rd_att->constr->defval;
437 int ndef = rd_att->constr->num_defval;
441 AttrNumber attrno = defval[ndef].adnum;
442 Form_pg_attribute thisatt = att[attrno - 1];
445 if (intMember((int) attrno, attrnos))
446 continue; /* there was a user-specified value */
449 * No user-supplied value, so add a targetentry with DEFAULT
450 * expr and correct data for the target column.
452 te = makeTargetEntry(
456 pstrdup(NameStr(thisatt->attname)),
458 stringToNode(defval[ndef].adbin));
459 qry->targetList = lappend(qry->targetList, te);
462 * Make sure the value is coerced to the target column type
463 * (might not be right type if it's not a constant!)
465 updateTargetListEntry(pstate, te, te->resdom->resname, attrno,
470 if (stmt->forUpdate != NULL)
471 transformForUpdate(qry, stmt->forUpdate);
473 /* in case of subselects in default clauses... */
474 qry->hasSubLinks = pstate->p_hasSubLinks;
476 return (Query *) qry;
482 * Create a name for an implicitly created index, sequence, constraint, etc.
484 * The parameters are: the original table name, the original field name, and
485 * a "type" string (such as "seq" or "pkey"). The field name and/or type
486 * can be NULL if not relevant.
488 * The result is a palloc'd string.
490 * The basic result we want is "name1_name2_type", omitting "_name2" or
491 * "_type" when those parameters are NULL. However, we must generate
492 * a name with less than NAMEDATALEN characters! So, we truncate one or
493 * both names if necessary to make a short-enough string. The type part
494 * is never truncated (so it had better be reasonably short).
496 * To reduce the probability of collisions, we might someday add more
497 * smarts to this routine, like including some "hash" characters computed
498 * from the truncated characters. Currently it seems best to keep it simple,
499 * so that the generated names are easily predictable by a person.
502 makeObjectName(char *name1, char *name2, char *typename)
505 int overhead = 0; /* chars needed for type and underscores */
506 int availchars; /* chars available for name(s) */
507 int name1chars; /* chars allocated to name1 */
508 int name2chars; /* chars allocated to name2 */
511 name1chars = strlen(name1);
514 name2chars = strlen(name2);
515 overhead++; /* allow for separating underscore */
520 overhead += strlen(typename) + 1;
522 availchars = NAMEDATALEN - 1 - overhead;
525 * If we must truncate, preferentially truncate the longer name. This
526 * logic could be expressed without a loop, but it's simple and
529 while (name1chars + name2chars > availchars)
531 if (name1chars > name2chars)
537 /* Now construct the string using the chosen lengths */
538 name = palloc(name1chars + name2chars + overhead + 1);
539 strncpy(name, name1, name1chars);
544 strncpy(name + ndx, name2, name2chars);
550 strcpy(name + ndx, typename);
559 CreateIndexName(char *table_name, char *column_name, char *label, List *indices)
564 char typename[NAMEDATALEN];
567 * The type name for makeObjectName is label, or labelN if that's
568 * necessary to prevent collisions among multiple indexes for the same
569 * table. Note there is no check for collisions with already-existing
570 * indexes; this ought to be rethought someday.
572 strcpy(typename, label);
576 iname = makeObjectName(table_name, column_name, typename);
578 foreach(ilist, indices)
580 IndexStmt *index = lfirst(ilist);
582 if (strcmp(iname, index->idxname) == 0)
585 /* ran through entire list? then no name conflict found so done */
589 /* the last one conflicted, so try a new name component */
591 sprintf(typename, "%s%d", label, ++pass);
598 * transformCreateStmt -
599 * transforms the "create table" statement
600 * SQL92 allows constraints to be scattered all over, so thumb through
601 * the columns and collect all constraints into one place.
602 * If there are any implied indices (e.g. UNIQUE or PRIMARY KEY)
603 * then expand those into multiple IndexStmt blocks.
604 * - thomas 1997-12-02
607 transformCreateStmt(ParseState *pstate, CreateStmt *stmt)
617 Constraint *constraint;
618 List *fkconstraints, /* List of FOREIGN KEY constraints to */
619 *fkclist; /* add finally */
620 FkConstraint *fkconstraint;
623 List *blist = NIL; /* "before list" of things to do before
624 * creating the table */
625 List *ilist = NIL; /* "index list" of things to do after
626 * creating the table */
633 q->commandType = CMD_UTILITY;
636 constraints = stmt->constraints;
641 * Run through each primary element in the table creation clause
643 foreach(elements, stmt->tableElts)
645 element = lfirst(elements);
646 switch (nodeTag(element))
649 column = (ColumnDef *) element;
650 columns = lappend(columns, column);
652 transformColumnType(pstate, column);
654 /* Special case SERIAL type? */
655 if (column->is_sequence)
660 FuncCall *funccallnode;
661 CreateSeqStmt *sequence;
664 * Create appropriate constraints for SERIAL. We do
665 * this in full, rather than shortcutting, so that we
666 * will detect any conflicting constraints the user
667 * wrote (like a different DEFAULT).
669 sname = makeObjectName(stmt->relname, column->colname,
673 * Create an expression tree representing the function
674 * call nextval('"sequencename"')
676 qstring = palloc(strlen(sname) + 2 + 1);
677 sprintf(qstring, "\"%s\"", sname);
678 snamenode = makeNode(A_Const);
679 snamenode->val.type = T_String;
680 snamenode->val.val.str = qstring;
681 funccallnode = makeNode(FuncCall);
682 funccallnode->funcname = "nextval";
683 funccallnode->args = lcons(snamenode, NIL);
684 funccallnode->agg_star = false;
685 funccallnode->agg_distinct = false;
687 constraint = makeNode(Constraint);
688 constraint->contype = CONSTR_DEFAULT;
689 constraint->name = sname;
690 constraint->raw_expr = (Node *) funccallnode;
691 constraint->cooked_expr = NULL;
692 constraint->keys = NIL;
693 column->constraints = lappend(column->constraints,
696 constraint = makeNode(Constraint);
697 constraint->contype = CONSTR_UNIQUE;
698 constraint->name = makeObjectName(stmt->relname,
701 column->constraints = lappend(column->constraints,
704 constraint = makeNode(Constraint);
705 constraint->contype = CONSTR_NOTNULL;
706 column->constraints = lappend(column->constraints,
709 sequence = makeNode(CreateSeqStmt);
710 sequence->seqname = pstrdup(sname);
711 sequence->options = NIL;
713 elog(NOTICE, "CREATE TABLE will create implicit sequence '%s' for SERIAL column '%s.%s'",
714 sequence->seqname, stmt->relname, column->colname);
716 blist = lcons(sequence, NIL);
719 /* Process column constraints, if any... */
720 transformConstraintAttrs(column->constraints);
722 saw_nullable = false;
724 foreach(clist, column->constraints)
726 constraint = lfirst(clist);
729 * If this column constraint is a FOREIGN KEY
730 * constraint, then we fill in the current attributes
731 * name and throw it into the list of FK constraints
732 * to be processed later.
735 if (IsA(constraint, FkConstraint))
737 Ident *id = makeNode(Ident);
739 id->name = column->colname;
740 id->indirection = NIL;
743 fkconstraint = (FkConstraint *) constraint;
744 fkconstraint->fk_attrs = lappend(NIL, id);
746 fkconstraints = lappend(fkconstraints, constraint);
750 switch (constraint->contype)
753 if (saw_nullable && column->is_not_null)
754 elog(ERROR, "CREATE TABLE/(NOT) NULL conflicting declaration"
755 " for '%s.%s'", stmt->relname, column->colname);
756 column->is_not_null = FALSE;
761 if (saw_nullable && !column->is_not_null)
762 elog(ERROR, "CREATE TABLE/(NOT) NULL conflicting declaration"
763 " for '%s.%s'", stmt->relname, column->colname);
764 column->is_not_null = TRUE;
769 if (column->raw_default != NULL)
770 elog(ERROR, "CREATE TABLE/DEFAULT multiple values specified"
771 " for '%s.%s'", stmt->relname, column->colname);
772 column->raw_default = constraint->raw_expr;
773 Assert(constraint->cooked_expr == NULL);
777 if (constraint->name == NULL)
778 constraint->name = makeObjectName(stmt->relname, NULL, "pkey");
779 if (constraint->keys == NIL)
781 key = makeNode(Ident);
782 key->name = pstrdup(column->colname);
783 constraint->keys = lcons(key, NIL);
785 dlist = lappend(dlist, constraint);
789 if (constraint->name == NULL)
790 constraint->name = makeObjectName(stmt->relname, column->colname, "key");
791 if (constraint->keys == NIL)
793 key = makeNode(Ident);
794 key->name = pstrdup(column->colname);
795 constraint->keys = lcons(key, NIL);
797 dlist = lappend(dlist, constraint);
801 if (constraint->name == NULL)
802 constraint->name = makeObjectName(stmt->relname, column->colname, NULL);
803 constraints = lappend(constraints, constraint);
806 case CONSTR_ATTR_DEFERRABLE:
807 case CONSTR_ATTR_NOT_DEFERRABLE:
808 case CONSTR_ATTR_DEFERRED:
809 case CONSTR_ATTR_IMMEDIATE:
810 /* transformConstraintAttrs took care of these */
814 elog(ERROR, "parser: unrecognized constraint (internal error)");
821 constraint = (Constraint *) element;
822 switch (constraint->contype)
825 if (constraint->name == NULL)
826 constraint->name = makeObjectName(stmt->relname, NULL, "pkey");
827 dlist = lappend(dlist, constraint);
831 dlist = lappend(dlist, constraint);
835 constraints = lappend(constraints, constraint);
841 case CONSTR_ATTR_DEFERRABLE:
842 case CONSTR_ATTR_NOT_DEFERRABLE:
843 case CONSTR_ATTR_DEFERRED:
844 case CONSTR_ATTR_IMMEDIATE:
845 elog(ERROR, "parser: illegal context for constraint (internal error)");
849 elog(ERROR, "parser: unrecognized constraint (internal error)");
856 * Table level FOREIGN KEY constraints are already complete.
857 * Just remember for later.
860 fkconstraints = lappend(fkconstraints, element);
864 elog(ERROR, "parser: unrecognized node (internal error)");
868 stmt->tableElts = columns;
869 stmt->constraints = constraints;
871 /* Now run through the "deferred list" to complete the query transformation.
872 * For PRIMARY KEYs, mark each column as NOT NULL and create an index.
873 * For UNIQUE, create an index as for PRIMARY KEYS, but do not insist on NOT NULL.
875 * Note that this code does not currently look for all possible redundant cases
876 * and either ignore or stop with warning. The create might fail later when
877 * names for indices turn out to be duplicated, or a user might have specified
878 * extra useless indices which might hurt performance. - thomas 1997-12-08
882 constraint = lfirst(dlist);
883 Assert(nodeTag(constraint) == T_Constraint);
884 Assert((constraint->contype == CONSTR_PRIMARY)
885 || (constraint->contype == CONSTR_UNIQUE));
887 index = makeNode(IndexStmt);
889 index->unique = TRUE;
890 index->primary = (constraint->contype == CONSTR_PRIMARY ? TRUE : FALSE);
894 elog(ERROR, "CREATE TABLE/PRIMARY KEY multiple primary keys"
895 " for table '%s' are not allowed", stmt->relname);
896 pkey = (IndexStmt *) index;
899 if (constraint->name != NULL)
900 index->idxname = pstrdup(constraint->name);
901 else if (constraint->contype == CONSTR_PRIMARY)
902 index->idxname = makeObjectName(stmt->relname, NULL, "pkey");
904 index->idxname = NULL;
906 index->relname = stmt->relname;
907 index->accessMethod = "btree";
908 index->indexParams = NIL;
909 index->withClause = NIL;
910 index->whereClause = NULL;
912 foreach(keys, constraint->keys)
914 key = (Ident *) lfirst(keys);
915 Assert(IsA(key, Ident));
917 foreach(columns, stmt->tableElts)
919 column = lfirst(columns);
920 Assert(IsA(column, ColumnDef));
921 if (strcmp(column->colname, key->name) == 0)
924 if (columns == NIL) /* fell off end of list? */
925 elog(ERROR, "CREATE TABLE: column '%s' named in key does not exist",
928 if (constraint->contype == CONSTR_PRIMARY)
929 column->is_not_null = TRUE;
930 iparam = makeNode(IndexElem);
931 iparam->name = pstrdup(column->colname);
933 iparam->class = NULL;
934 iparam->typename = NULL;
935 index->indexParams = lappend(index->indexParams, iparam);
937 if (index->idxname == NULL)
938 index->idxname = CreateIndexName(stmt->relname, iparam->name, "key", ilist);
941 if (index->idxname == NULL) /* should not happen */
942 elog(ERROR, "CREATE TABLE: failed to make implicit index name");
944 ilist = lappend(ilist, index);
945 dlist = lnext(dlist);
948 /* OK, now finally, if there is a primary key, then make sure that there aren't any redundant
949 * unique indices defined on columns. This can arise if someone specifies UNIQUE explicitly
950 * or if a SERIAL column was defined along with a table PRIMARY KEY constraint.
951 * - thomas 1999-05-11
965 index = lfirst(dlist);
966 pcols = pkey->indexParams;
967 icols = index->indexParams;
969 plen = length(pcols);
970 ilen = length(icols);
972 /* Not the same as the primary key? Then we should look... */
973 if ((index != pkey) && (ilen == plen))
976 while ((pcols != NIL) && (icols != NIL))
978 IndexElem *pcol = lfirst(pcols);
979 IndexElem *icol = lfirst(icols);
980 char *pname = pcol->name;
981 char *iname = icol->name;
983 /* different names? then no match... */
984 if (strcmp(iname, pname) != 0)
989 pcols = lnext(pcols);
990 icols = lnext(icols);
995 ilist = lappend(ilist, index);
996 dlist = lnext(dlist);
1001 while (dlist != NIL)
1003 index = lfirst(dlist);
1004 elog(NOTICE, "CREATE TABLE/%s will create implicit index '%s' for table '%s'",
1005 (index->primary ? "PRIMARY KEY" : "UNIQUE"),
1006 index->idxname, stmt->relname);
1007 dlist = lnext(dlist);
1010 q->utilityStmt = (Node *) stmt;
1011 extras_before = blist;
1012 extras_after = ilist;
1015 * Now process the FOREIGN KEY constraints and add appropriate queries
1016 * to the extras_after statements list.
1019 if (fkconstraints != NIL)
1021 CreateTrigStmt *fk_trigger;
1026 elog(NOTICE, "CREATE TABLE will create implicit trigger(s) for FOREIGN KEY check(s)");
1028 foreach(fkclist, fkconstraints)
1030 fkconstraint = (FkConstraint *) lfirst(fkclist);
1033 * If the constraint has no name, set it to <unnamed>
1036 if (fkconstraint->constr_name == NULL)
1037 fkconstraint->constr_name = "<unnamed>";
1040 * If the attribute list for the referenced table was omitted,
1041 * lookup for the definition of the primary key. If the
1042 * referenced table is this table, use the definition we found
1043 * above, rather than looking to the system tables.
1046 if (fkconstraint->fk_attrs != NIL && fkconstraint->pk_attrs == NIL)
1048 if (strcmp(fkconstraint->pktable_name, stmt->relname) != 0)
1049 transformFkeyGetPrimaryKey(fkconstraint);
1050 else if (pkey != NULL)
1052 List *pkey_attr = pkey->indexParams;
1057 foreach(attr, pkey_attr)
1059 ielem = lfirst(attr);
1060 pkattr = (Ident *) makeNode(Ident);
1061 pkattr->name = pstrdup(ielem->name);
1062 pkattr->indirection = NIL;
1063 pkattr->isRel = false;
1064 fkconstraint->pk_attrs = lappend(fkconstraint->pk_attrs, pkattr);
1069 elog(ERROR, "PRIMARY KEY for referenced table \"%s\" not found",
1070 fkconstraint->pktable_name);
1075 * Build a CREATE CONSTRAINT TRIGGER statement for the CHECK
1079 fk_trigger = (CreateTrigStmt *) makeNode(CreateTrigStmt);
1080 fk_trigger->trigname = fkconstraint->constr_name;
1081 fk_trigger->relname = stmt->relname;
1082 fk_trigger->funcname = "RI_FKey_check_ins";
1083 fk_trigger->before = false;
1084 fk_trigger->row = true;
1085 fk_trigger->actions[0] = 'i';
1086 fk_trigger->actions[1] = 'u';
1087 fk_trigger->actions[2] = '\0';
1088 fk_trigger->lang = NULL;
1089 fk_trigger->text = NULL;
1091 fk_trigger->attr = NIL;
1092 fk_trigger->when = NULL;
1093 fk_trigger->isconstraint = true;
1094 fk_trigger->deferrable = fkconstraint->deferrable;
1095 fk_trigger->initdeferred = fkconstraint->initdeferred;
1096 fk_trigger->constrrelname = fkconstraint->pktable_name;
1098 fk_trigger->args = NIL;
1099 fk_trigger->args = lappend(fk_trigger->args,
1100 fkconstraint->constr_name);
1101 fk_trigger->args = lappend(fk_trigger->args,
1103 fk_trigger->args = lappend(fk_trigger->args,
1104 fkconstraint->pktable_name);
1105 fk_trigger->args = lappend(fk_trigger->args,
1106 fkconstraint->match_type);
1107 fk_attr = fkconstraint->fk_attrs;
1108 pk_attr = fkconstraint->pk_attrs;
1109 if (length(fk_attr) != length(pk_attr))
1111 elog(NOTICE, "Illegal FOREIGN KEY definition REFERENCES \"%s\"",
1112 fkconstraint->pktable_name);
1113 elog(ERROR, "number of key attributes in referenced table must be equal to foreign key");
1115 while (fk_attr != NIL)
1117 id = (Ident *) lfirst(fk_attr);
1118 fk_trigger->args = lappend(fk_trigger->args, id->name);
1120 id = (Ident *) lfirst(pk_attr);
1121 fk_trigger->args = lappend(fk_trigger->args, id->name);
1123 fk_attr = lnext(fk_attr);
1124 pk_attr = lnext(pk_attr);
1127 extras_after = lappend(extras_after, (Node *) fk_trigger);
1130 * Build a CREATE CONSTRAINT TRIGGER statement for the ON
1131 * DELETE action fired on the PK table !!!
1134 fk_trigger = (CreateTrigStmt *) makeNode(CreateTrigStmt);
1135 fk_trigger->trigname = fkconstraint->constr_name;
1136 fk_trigger->relname = fkconstraint->pktable_name;
1137 fk_trigger->before = false;
1138 fk_trigger->row = true;
1139 fk_trigger->actions[0] = 'd';
1140 fk_trigger->actions[1] = '\0';
1141 fk_trigger->lang = NULL;
1142 fk_trigger->text = NULL;
1144 fk_trigger->attr = NIL;
1145 fk_trigger->when = NULL;
1146 fk_trigger->isconstraint = true;
1147 fk_trigger->deferrable = fkconstraint->deferrable;
1148 fk_trigger->initdeferred = fkconstraint->initdeferred;
1149 fk_trigger->constrrelname = stmt->relname;
1150 switch ((fkconstraint->actions & FKCONSTR_ON_DELETE_MASK)
1151 >> FKCONSTR_ON_DELETE_SHIFT)
1153 case FKCONSTR_ON_KEY_NOACTION:
1154 fk_trigger->funcname = "RI_FKey_noaction_del";
1156 case FKCONSTR_ON_KEY_RESTRICT:
1157 fk_trigger->deferrable = false;
1158 fk_trigger->initdeferred = false;
1159 fk_trigger->funcname = "RI_FKey_restrict_del";
1161 case FKCONSTR_ON_KEY_CASCADE:
1162 fk_trigger->funcname = "RI_FKey_cascade_del";
1164 case FKCONSTR_ON_KEY_SETNULL:
1165 fk_trigger->funcname = "RI_FKey_setnull_del";
1167 case FKCONSTR_ON_KEY_SETDEFAULT:
1168 fk_trigger->funcname = "RI_FKey_setdefault_del";
1171 elog(ERROR, "Only one ON DELETE action can be specified for FOREIGN KEY constraint");
1175 fk_trigger->args = NIL;
1176 fk_trigger->args = lappend(fk_trigger->args,
1177 fkconstraint->constr_name);
1178 fk_trigger->args = lappend(fk_trigger->args,
1180 fk_trigger->args = lappend(fk_trigger->args,
1181 fkconstraint->pktable_name);
1182 fk_trigger->args = lappend(fk_trigger->args,
1183 fkconstraint->match_type);
1184 fk_attr = fkconstraint->fk_attrs;
1185 pk_attr = fkconstraint->pk_attrs;
1186 while (fk_attr != NIL)
1188 id = (Ident *) lfirst(fk_attr);
1189 fk_trigger->args = lappend(fk_trigger->args, id->name);
1191 id = (Ident *) lfirst(pk_attr);
1192 fk_trigger->args = lappend(fk_trigger->args, id->name);
1194 fk_attr = lnext(fk_attr);
1195 pk_attr = lnext(pk_attr);
1198 extras_after = lappend(extras_after, (Node *) fk_trigger);
1201 * Build a CREATE CONSTRAINT TRIGGER statement for the ON
1202 * UPDATE action fired on the PK table !!!
1205 fk_trigger = (CreateTrigStmt *) makeNode(CreateTrigStmt);
1206 fk_trigger->trigname = fkconstraint->constr_name;
1207 fk_trigger->relname = fkconstraint->pktable_name;
1208 fk_trigger->before = false;
1209 fk_trigger->row = true;
1210 fk_trigger->actions[0] = 'u';
1211 fk_trigger->actions[1] = '\0';
1212 fk_trigger->lang = NULL;
1213 fk_trigger->text = NULL;
1215 fk_trigger->attr = NIL;
1216 fk_trigger->when = NULL;
1217 fk_trigger->isconstraint = true;
1218 fk_trigger->deferrable = fkconstraint->deferrable;
1219 fk_trigger->initdeferred = fkconstraint->initdeferred;
1220 fk_trigger->constrrelname = stmt->relname;
1221 switch ((fkconstraint->actions & FKCONSTR_ON_UPDATE_MASK)
1222 >> FKCONSTR_ON_UPDATE_SHIFT)
1224 case FKCONSTR_ON_KEY_NOACTION:
1225 fk_trigger->funcname = "RI_FKey_noaction_upd";
1227 case FKCONSTR_ON_KEY_RESTRICT:
1228 fk_trigger->deferrable = false;
1229 fk_trigger->initdeferred = false;
1230 fk_trigger->funcname = "RI_FKey_restrict_upd";
1232 case FKCONSTR_ON_KEY_CASCADE:
1233 fk_trigger->funcname = "RI_FKey_cascade_upd";
1235 case FKCONSTR_ON_KEY_SETNULL:
1236 fk_trigger->funcname = "RI_FKey_setnull_upd";
1238 case FKCONSTR_ON_KEY_SETDEFAULT:
1239 fk_trigger->funcname = "RI_FKey_setdefault_upd";
1242 elog(ERROR, "Only one ON UPDATE action can be specified for FOREIGN KEY constraint");
1246 fk_trigger->args = NIL;
1247 fk_trigger->args = lappend(fk_trigger->args,
1248 fkconstraint->constr_name);
1249 fk_trigger->args = lappend(fk_trigger->args,
1251 fk_trigger->args = lappend(fk_trigger->args,
1252 fkconstraint->pktable_name);
1253 fk_trigger->args = lappend(fk_trigger->args,
1254 fkconstraint->match_type);
1255 fk_attr = fkconstraint->fk_attrs;
1256 pk_attr = fkconstraint->pk_attrs;
1257 while (fk_attr != NIL)
1259 id = (Ident *) lfirst(fk_attr);
1260 fk_trigger->args = lappend(fk_trigger->args, id->name);
1262 id = (Ident *) lfirst(pk_attr);
1263 fk_trigger->args = lappend(fk_trigger->args, id->name);
1265 fk_attr = lnext(fk_attr);
1266 pk_attr = lnext(pk_attr);
1269 extras_after = lappend(extras_after, (Node *) fk_trigger);
1274 } /* transformCreateStmt() */
1278 * transformIndexStmt -
1279 * transforms the qualification of the index statement
1282 transformIndexStmt(ParseState *pstate, IndexStmt *stmt)
1286 qry = makeNode(Query);
1287 qry->commandType = CMD_UTILITY;
1289 /* take care of the where clause */
1290 stmt->whereClause = transformWhereClause(pstate, stmt->whereClause);
1292 qry->hasSubLinks = pstate->p_hasSubLinks;
1294 stmt->rangetable = pstate->p_rtable;
1296 qry->utilityStmt = (Node *) stmt;
1302 * transformExtendStmt -
1303 * transform the qualifications of the Extend Index Statement
1307 transformExtendStmt(ParseState *pstate, ExtendStmt *stmt)
1311 qry = makeNode(Query);
1312 qry->commandType = CMD_UTILITY;
1314 /* take care of the where clause */
1315 stmt->whereClause = transformWhereClause(pstate, stmt->whereClause);
1317 qry->hasSubLinks = pstate->p_hasSubLinks;
1319 stmt->rangetable = pstate->p_rtable;
1321 qry->utilityStmt = (Node *) stmt;
1326 * transformRuleStmt -
1327 * transform a Create Rule Statement. The actions is a list of parse
1328 * trees which is transformed into a list of query trees.
1331 transformRuleStmt(ParseState *pstate, RuleStmt *stmt)
1337 qry = makeNode(Query);
1338 qry->commandType = CMD_UTILITY;
1341 * 'instead nothing' rules with a qualification need a query a
1342 * rangetable so the rewrite handler can add the negated rule
1343 * qualification to the original query. We create a query with the new
1344 * command type CMD_NOTHING here that is treated special by the
1347 if (stmt->actions == NIL)
1349 Query *nothing_qry = makeNode(Query);
1351 nothing_qry->commandType = CMD_NOTHING;
1353 addRangeTableEntry(pstate, stmt->object->relname,
1354 makeAttr("*CURRENT*", NULL),
1355 FALSE, FALSE, FALSE);
1356 addRangeTableEntry(pstate, stmt->object->relname,
1357 makeAttr("*NEW*", NULL),
1358 FALSE, FALSE, FALSE);
1360 nothing_qry->rtable = pstate->p_rtable;
1362 stmt->actions = lappend(NIL, nothing_qry);
1365 actions = stmt->actions;
1368 * transform each statment, like parse_analyze()
1370 while (actions != NIL)
1374 * NOTE: 'CURRENT' must always have a varno equal to 1 and 'NEW'
1377 addRangeTableEntry(pstate, stmt->object->relname,
1378 makeAttr("*CURRENT*", NULL),
1379 FALSE, FALSE, FALSE);
1380 addRangeTableEntry(pstate, stmt->object->relname,
1381 makeAttr("*NEW*", NULL),
1382 FALSE, FALSE, FALSE);
1384 pstate->p_last_resno = 1;
1385 pstate->p_is_rule = true; /* for expand all */
1386 pstate->p_hasAggs = false;
1388 action = (Query *) lfirst(actions);
1389 if (action->commandType != CMD_NOTHING)
1390 lfirst(actions) = transformStmt(pstate, lfirst(actions));
1391 actions = lnext(actions);
1394 /* take care of the where clause */
1395 stmt->whereClause = transformWhereClause(pstate, stmt->whereClause);
1397 qry->hasSubLinks = pstate->p_hasSubLinks;
1399 qry->utilityStmt = (Node *) stmt;
1405 * transformSelectStmt -
1406 * transforms a Select Statement
1410 transformSelectStmt(ParseState *pstate, SelectStmt *stmt)
1412 Query *qry = makeNode(Query);
1414 qry->commandType = CMD_SELECT;
1416 /* set up a range table */
1417 makeRangeTable(pstate, stmt->fromClause);
1419 qry->into = stmt->into;
1420 qry->isTemp = stmt->istemp;
1421 qry->isPortal = FALSE;
1423 qry->targetList = transformTargetList(pstate, stmt->targetList);
1425 qry->qual = transformWhereClause(pstate, stmt->whereClause);
1428 * Initial processing of HAVING clause is just like WHERE clause.
1429 * Additional work will be done in optimizer/plan/planner.c.
1431 qry->havingQual = transformWhereClause(pstate, stmt->havingClause);
1433 qry->groupClause = transformGroupClause(pstate,
1437 qry->sortClause = transformSortClause(pstate,
1441 qry->distinctClause = transformDistinctClause(pstate,
1442 stmt->distinctClause,
1446 qry->hasSubLinks = pstate->p_hasSubLinks;
1447 qry->hasAggs = pstate->p_hasAggs;
1448 if (pstate->p_hasAggs || qry->groupClause || qry->havingQual)
1449 parseCheckAggregates(pstate, qry);
1452 * The INSERT INTO ... SELECT ... could have a UNION in child, so
1453 * unionClause may be false
1455 qry->unionall = stmt->unionall;
1458 * Just hand through the unionClause and intersectClause. We will
1459 * handle it in the function Except_Intersect_Rewrite()
1461 qry->unionClause = stmt->unionClause;
1462 qry->intersectClause = stmt->intersectClause;
1464 qry->rtable = pstate->p_rtable;
1466 if (stmt->forUpdate != NULL)
1467 transformForUpdate(qry, stmt->forUpdate);
1469 return (Query *) qry;
1473 * transformUpdateStmt -
1474 * transforms an update statement
1478 transformUpdateStmt(ParseState *pstate, UpdateStmt *stmt)
1480 Query *qry = makeNode(Query);
1481 List *origTargetList;
1484 qry->commandType = CMD_UPDATE;
1485 pstate->p_is_update = true;
1488 * the FROM clause is non-standard SQL syntax. We used to be able to
1489 * do this with REPLACE in POSTQUEL so we keep the feature.
1491 makeRangeTable(pstate, stmt->fromClause);
1492 setTargetTable(pstate, stmt->relname, stmt->inh);
1494 qry->targetList = transformTargetList(pstate, stmt->targetList);
1496 qry->qual = transformWhereClause(pstate, stmt->whereClause);
1498 qry->hasSubLinks = pstate->p_hasSubLinks;
1500 qry->rtable = pstate->p_rtable;
1501 qry->resultRelation = refnameRangeTablePosn(pstate, stmt->relname, NULL);
1503 qry->hasAggs = pstate->p_hasAggs;
1504 if (pstate->p_hasAggs)
1505 parseCheckAggregates(pstate, qry);
1508 * Now we are done with SELECT-like processing, and can get on with
1509 * transforming the target list to match the UPDATE target columns.
1512 /* Prepare to assign non-conflicting resnos to resjunk attributes */
1513 if (pstate->p_last_resno <= pstate->p_target_relation->rd_rel->relnatts)
1514 pstate->p_last_resno = pstate->p_target_relation->rd_rel->relnatts + 1;
1516 /* Prepare non-junk columns for assignment to target table */
1517 origTargetList = stmt->targetList;
1518 foreach(tl, qry->targetList)
1520 TargetEntry *tle = (TargetEntry *) lfirst(tl);
1521 Resdom *resnode = tle->resdom;
1522 ResTarget *origTarget;
1524 if (resnode->resjunk)
1528 * Resjunk nodes need no additional processing, but be sure
1529 * they have names and resnos that do not match any target
1530 * columns; else rewriter or planner might get confused.
1532 resnode->resname = "?resjunk?";
1533 resnode->resno = (AttrNumber) pstate->p_last_resno++;
1536 if (origTargetList == NIL)
1537 elog(ERROR, "UPDATE target count mismatch --- internal error");
1538 origTarget = (ResTarget *) lfirst(origTargetList);
1539 updateTargetListEntry(pstate, tle, origTarget->name,
1540 attnameAttNum(pstate->p_target_relation,
1542 origTarget->indirection);
1543 origTargetList = lnext(origTargetList);
1545 if (origTargetList != NIL)
1546 elog(ERROR, "UPDATE target count mismatch --- internal error");
1548 return (Query *) qry;
1552 * transformCursorStmt -
1553 * transform a Create Cursor Statement
1557 transformCursorStmt(ParseState *pstate, SelectStmt *stmt)
1561 qry = transformSelectStmt(pstate, stmt);
1563 qry->into = stmt->portalname;
1564 qry->isTemp = stmt->istemp;
1565 qry->isPortal = TRUE;
1566 qry->isBinary = stmt->binary; /* internal portal */
1572 * tranformAlterTableStmt -
1573 * transform an Alter Table Statement
1577 transformAlterTableStmt(ParseState *pstate, AlterTableStmt *stmt)
1581 qry = makeNode(Query);
1582 qry->commandType = CMD_UTILITY;
1585 * The only subtypes that currently have special handling are 'A'dd
1586 * column and Add 'C'onstraint. In addition, right now only Foreign
1587 * Key 'C'onstraints have a special transformation.
1590 switch (stmt->subtype)
1593 transformColumnType(pstate, (ColumnDef *) stmt->def);
1596 if (stmt->def && nodeTag(stmt->def) == T_FkConstraint)
1598 CreateTrigStmt *fk_trigger;
1602 FkConstraint *fkconstraint;
1605 elog(NOTICE, "ALTER TABLE ... ADD CONSTRAINT will create implicit trigger(s) for FOREIGN KEY check(s)");
1607 fkconstraint = (FkConstraint *) stmt->def;
1610 * If the constraint has no name, set it to <unnamed>
1613 if (fkconstraint->constr_name == NULL)
1614 fkconstraint->constr_name = "<unnamed>";
1617 * If the attribute list for the referenced table was
1618 * omitted, lookup for the definition of the primary key
1621 if (fkconstraint->fk_attrs != NIL && fkconstraint->pk_attrs == NIL)
1622 transformFkeyGetPrimaryKey(fkconstraint);
1625 * Build a CREATE CONSTRAINT TRIGGER statement for the
1629 fk_trigger = (CreateTrigStmt *) makeNode(CreateTrigStmt);
1630 fk_trigger->trigname = fkconstraint->constr_name;
1631 fk_trigger->relname = stmt->relname;
1632 fk_trigger->funcname = "RI_FKey_check_ins";
1633 fk_trigger->before = false;
1634 fk_trigger->row = true;
1635 fk_trigger->actions[0] = 'i';
1636 fk_trigger->actions[1] = 'u';
1637 fk_trigger->actions[2] = '\0';
1638 fk_trigger->lang = NULL;
1639 fk_trigger->text = NULL;
1641 fk_trigger->attr = NIL;
1642 fk_trigger->when = NULL;
1643 fk_trigger->isconstraint = true;
1644 fk_trigger->deferrable = fkconstraint->deferrable;
1645 fk_trigger->initdeferred = fkconstraint->initdeferred;
1646 fk_trigger->constrrelname = fkconstraint->pktable_name;
1648 fk_trigger->args = NIL;
1649 fk_trigger->args = lappend(fk_trigger->args,
1650 fkconstraint->constr_name);
1651 fk_trigger->args = lappend(fk_trigger->args,
1653 fk_trigger->args = lappend(fk_trigger->args,
1654 fkconstraint->pktable_name);
1655 fk_trigger->args = lappend(fk_trigger->args,
1656 fkconstraint->match_type);
1657 fk_attr = fkconstraint->fk_attrs;
1658 pk_attr = fkconstraint->pk_attrs;
1659 if (length(fk_attr) != length(pk_attr))
1661 elog(NOTICE, "Illegal FOREIGN KEY definition REFERENCES \"%s\"",
1662 fkconstraint->pktable_name);
1663 elog(ERROR, "number of key attributes in referenced table must be equal to foreign key");
1665 while (fk_attr != NIL)
1667 id = (Ident *) lfirst(fk_attr);
1668 fk_trigger->args = lappend(fk_trigger->args, id->name);
1670 id = (Ident *) lfirst(pk_attr);
1671 fk_trigger->args = lappend(fk_trigger->args, id->name);
1673 fk_attr = lnext(fk_attr);
1674 pk_attr = lnext(pk_attr);
1677 extras_after = lappend(extras_after, (Node *) fk_trigger);
1680 * Build a CREATE CONSTRAINT TRIGGER statement for the ON
1681 * DELETE action fired on the PK table !!!
1684 fk_trigger = (CreateTrigStmt *) makeNode(CreateTrigStmt);
1685 fk_trigger->trigname = fkconstraint->constr_name;
1686 fk_trigger->relname = fkconstraint->pktable_name;
1687 switch ((fkconstraint->actions & FKCONSTR_ON_DELETE_MASK)
1688 >> FKCONSTR_ON_DELETE_SHIFT)
1690 case FKCONSTR_ON_KEY_NOACTION:
1691 fk_trigger->funcname = "RI_FKey_noaction_del";
1693 case FKCONSTR_ON_KEY_RESTRICT:
1694 fk_trigger->funcname = "RI_FKey_restrict_del";
1696 case FKCONSTR_ON_KEY_CASCADE:
1697 fk_trigger->funcname = "RI_FKey_cascade_del";
1699 case FKCONSTR_ON_KEY_SETNULL:
1700 fk_trigger->funcname = "RI_FKey_setnull_del";
1702 case FKCONSTR_ON_KEY_SETDEFAULT:
1703 fk_trigger->funcname = "RI_FKey_setdefault_del";
1706 elog(ERROR, "Only one ON DELETE action can be specified for FOREIGN KEY constraint");
1709 fk_trigger->before = false;
1710 fk_trigger->row = true;
1711 fk_trigger->actions[0] = 'd';
1712 fk_trigger->actions[1] = '\0';
1713 fk_trigger->lang = NULL;
1714 fk_trigger->text = NULL;
1716 fk_trigger->attr = NIL;
1717 fk_trigger->when = NULL;
1718 fk_trigger->isconstraint = true;
1719 fk_trigger->deferrable = fkconstraint->deferrable;
1720 fk_trigger->initdeferred = fkconstraint->initdeferred;
1721 fk_trigger->constrrelname = stmt->relname;
1723 fk_trigger->args = NIL;
1724 fk_trigger->args = lappend(fk_trigger->args,
1725 fkconstraint->constr_name);
1726 fk_trigger->args = lappend(fk_trigger->args,
1728 fk_trigger->args = lappend(fk_trigger->args,
1729 fkconstraint->pktable_name);
1730 fk_trigger->args = lappend(fk_trigger->args,
1731 fkconstraint->match_type);
1732 fk_attr = fkconstraint->fk_attrs;
1733 pk_attr = fkconstraint->pk_attrs;
1734 while (fk_attr != NIL)
1736 id = (Ident *) lfirst(fk_attr);
1737 fk_trigger->args = lappend(fk_trigger->args, id->name);
1739 id = (Ident *) lfirst(pk_attr);
1740 fk_trigger->args = lappend(fk_trigger->args, id->name);
1742 fk_attr = lnext(fk_attr);
1743 pk_attr = lnext(pk_attr);
1746 extras_after = lappend(extras_after, (Node *) fk_trigger);
1749 * Build a CREATE CONSTRAINT TRIGGER statement for the ON
1750 * UPDATE action fired on the PK table !!!
1753 fk_trigger = (CreateTrigStmt *) makeNode(CreateTrigStmt);
1754 fk_trigger->trigname = fkconstraint->constr_name;
1755 fk_trigger->relname = fkconstraint->pktable_name;
1756 switch ((fkconstraint->actions & FKCONSTR_ON_UPDATE_MASK)
1757 >> FKCONSTR_ON_UPDATE_SHIFT)
1759 case FKCONSTR_ON_KEY_NOACTION:
1760 fk_trigger->funcname = "RI_FKey_noaction_upd";
1762 case FKCONSTR_ON_KEY_RESTRICT:
1763 fk_trigger->funcname = "RI_FKey_restrict_upd";
1765 case FKCONSTR_ON_KEY_CASCADE:
1766 fk_trigger->funcname = "RI_FKey_cascade_upd";
1768 case FKCONSTR_ON_KEY_SETNULL:
1769 fk_trigger->funcname = "RI_FKey_setnull_upd";
1771 case FKCONSTR_ON_KEY_SETDEFAULT:
1772 fk_trigger->funcname = "RI_FKey_setdefault_upd";
1775 elog(ERROR, "Only one ON UPDATE action can be specified for FOREIGN KEY constraint");
1778 fk_trigger->before = false;
1779 fk_trigger->row = true;
1780 fk_trigger->actions[0] = 'u';
1781 fk_trigger->actions[1] = '\0';
1782 fk_trigger->lang = NULL;
1783 fk_trigger->text = NULL;
1785 fk_trigger->attr = NIL;
1786 fk_trigger->when = NULL;
1787 fk_trigger->isconstraint = true;
1788 fk_trigger->deferrable = fkconstraint->deferrable;
1789 fk_trigger->initdeferred = fkconstraint->initdeferred;
1790 fk_trigger->constrrelname = stmt->relname;
1792 fk_trigger->args = NIL;
1793 fk_trigger->args = lappend(fk_trigger->args,
1794 fkconstraint->constr_name);
1795 fk_trigger->args = lappend(fk_trigger->args,
1797 fk_trigger->args = lappend(fk_trigger->args,
1798 fkconstraint->pktable_name);
1799 fk_trigger->args = lappend(fk_trigger->args,
1800 fkconstraint->match_type);
1801 fk_attr = fkconstraint->fk_attrs;
1802 pk_attr = fkconstraint->pk_attrs;
1803 while (fk_attr != NIL)
1805 id = (Ident *) lfirst(fk_attr);
1806 fk_trigger->args = lappend(fk_trigger->args, id->name);
1808 id = (Ident *) lfirst(pk_attr);
1809 fk_trigger->args = lappend(fk_trigger->args, id->name);
1811 fk_attr = lnext(fk_attr);
1812 pk_attr = lnext(pk_attr);
1815 extras_after = lappend(extras_after, (Node *) fk_trigger);
1821 qry->utilityStmt = (Node *) stmt;
1826 /* This function steps through the tree
1827 * built up by the select_w_o_sort rule
1828 * and builds a list of all SelectStmt Nodes found
1829 * The built up list is handed back in **select_list.
1830 * If one of the SelectStmt Nodes has the 'unionall' flag
1831 * set to true *unionall_present hands back 'true' */
1833 create_select_list(Node *ptr, List **select_list, bool *unionall_present)
1835 if (IsA(ptr, SelectStmt))
1837 *select_list = lappend(*select_list, ptr);
1838 if (((SelectStmt *) ptr)->unionall == TRUE)
1839 *unionall_present = TRUE;
1843 /* Recursively call for all arguments. A NOT expr has no lexpr! */
1844 if (((A_Expr *) ptr)->lexpr != NULL)
1845 create_select_list(((A_Expr *) ptr)->lexpr, select_list, unionall_present);
1846 create_select_list(((A_Expr *) ptr)->rexpr, select_list, unionall_present);
1849 /* Changes the A_Expr Nodes to Expr Nodes and exchanges ANDs and ORs.
1850 * The reason for the exchange is easy: We implement INTERSECTs and EXCEPTs
1851 * by rewriting these queries to semantically equivalent queries that use
1852 * IN and NOT IN subselects. To be able to use all three operations
1853 * (UNIONs INTERSECTs and EXCEPTs) in one complex query we have to
1854 * translate the queries into Disjunctive Normal Form (DNF). Unfortunately
1855 * there is no function 'dnfify' but there is a function 'cnfify'
1856 * which produces DNF when we exchange ANDs and ORs before calling
1857 * 'cnfify' and exchange them back in the result.
1859 * If an EXCEPT or INTERSECT is present *intersect_present
1860 * hands back 'true' */
1862 A_Expr_to_Expr(Node *ptr, bool *intersect_present)
1864 Node *result = NULL;
1866 switch (nodeTag(ptr))
1870 A_Expr *a = (A_Expr *) ptr;
1876 Expr *expr = makeNode(Expr);
1877 Node *lexpr = A_Expr_to_Expr(((A_Expr *) ptr)->lexpr, intersect_present);
1878 Node *rexpr = A_Expr_to_Expr(((A_Expr *) ptr)->rexpr, intersect_present);
1880 *intersect_present = TRUE;
1882 expr->typeOid = BOOLOID;
1883 expr->opType = OR_EXPR;
1884 expr->args = makeList(lexpr, rexpr, -1);
1885 result = (Node *) expr;
1890 Expr *expr = makeNode(Expr);
1891 Node *lexpr = A_Expr_to_Expr(((A_Expr *) ptr)->lexpr, intersect_present);
1892 Node *rexpr = A_Expr_to_Expr(((A_Expr *) ptr)->rexpr, intersect_present);
1894 expr->typeOid = BOOLOID;
1895 expr->opType = AND_EXPR;
1896 expr->args = makeList(lexpr, rexpr, -1);
1897 result = (Node *) expr;
1902 Expr *expr = makeNode(Expr);
1903 Node *rexpr = A_Expr_to_Expr(((A_Expr *) ptr)->rexpr, intersect_present);
1905 expr->typeOid = BOOLOID;
1906 expr->opType = NOT_EXPR;
1907 expr->args = makeList(rexpr, -1);
1908 result = (Node *) expr;
1921 CheckSelectForUpdate(Query *qry)
1923 if (qry->unionClause != NULL)
1924 elog(ERROR, "SELECT FOR UPDATE is not allowed with UNION/INTERSECT/EXCEPT clause");
1925 if (qry->distinctClause != NIL)
1926 elog(ERROR, "SELECT FOR UPDATE is not allowed with DISTINCT clause");
1927 if (qry->groupClause != NIL)
1928 elog(ERROR, "SELECT FOR UPDATE is not allowed with GROUP BY clause");
1930 elog(ERROR, "SELECT FOR UPDATE is not allowed with AGGREGATE");
1934 transformForUpdate(Query *qry, List *forUpdate)
1936 List *rowMark = NULL;
1941 CheckSelectForUpdate(qry);
1943 if (lfirst(forUpdate) == NULL) /* all tables */
1946 foreach(l, qry->rtable)
1948 newrm = makeNode(RowMark);
1950 newrm->info = ROW_MARK_FOR_UPDATE | ROW_ACL_FOR_UPDATE;
1951 rowMark = lappend(rowMark, newrm);
1953 qry->rowMark = nconc(qry->rowMark, rowMark);
1957 foreach(l, forUpdate)
1959 char *relname = lfirst(l);
1963 foreach(l2, qry->rtable)
1965 if (strcmp(((RangeTblEntry *) lfirst(l2))->eref->relname, relname) == 0)
1969 foreach(l3, rowMark)
1971 if (((RowMark *) lfirst(l3))->rti == i) /* duplicate */
1976 newrm = makeNode(RowMark);
1978 newrm->info = ROW_MARK_FOR_UPDATE | ROW_ACL_FOR_UPDATE;
1979 rowMark = lappend(rowMark, newrm);
1986 elog(ERROR, "FOR UPDATE: relation '%s' not found in FROM clause",
1990 qry->rowMark = rowMark;
1995 * transformFkeyGetPrimaryKey -
1997 * Try to find the primary key attributes of a referenced table if
1998 * the column list in the REFERENCES specification was omitted.
2002 transformFkeyGetPrimaryKey(FkConstraint *fkconstraint)
2005 Form_pg_attribute *pkrel_attrs;
2007 HeapScanDesc indexSd;
2010 Form_pg_index indexStruct = NULL;
2016 * Open the referenced table and get the attributes list
2019 pkrel = heap_openr(fkconstraint->pktable_name, AccessShareLock);
2021 elog(ERROR, "referenced table \"%s\" not found",
2022 fkconstraint->pktable_name);
2023 pkrel_attrs = pkrel->rd_att->attrs;
2026 * Open pg_index and begin a scan for all indices defined on
2027 * the referenced table
2030 indexRd = heap_openr(IndexRelationName, AccessShareLock);
2031 ScanKeyEntryInitialize(&key, 0, Anum_pg_index_indrelid,
2033 ObjectIdGetDatum(pkrel->rd_id));
2034 indexSd = heap_beginscan(indexRd, /* scan desc */
2035 false, /* scan backward flag */
2036 SnapshotNow, /* NOW snapshot */
2037 1, /* number scan keys */
2038 &key); /* scan keys */
2041 * Fetch the index with indisprimary == true
2044 while (HeapTupleIsValid(indexTup = heap_getnext(indexSd, 0)))
2046 indexStruct = (Form_pg_index) GETSTRUCT(indexTup);
2048 if (indexStruct->indisprimary)
2053 * Check that we found it
2056 if (!HeapTupleIsValid(indexTup))
2057 elog(ERROR, "PRIMARY KEY for referenced table \"%s\" not found",
2058 fkconstraint->pktable_name);
2061 * Now build the list of PK attributes from the indkey definition
2062 * using the attribute names of the PK relation descriptor
2065 for (i = 0; i < INDEX_MAX_KEYS && indexStruct->indkey[i] != 0; i++)
2067 pkattno = indexStruct->indkey[i];
2068 pkattr = (Ident *) makeNode(Ident);
2069 pkattr->name = nameout(&(pkrel_attrs[pkattno - 1]->attname));
2070 pkattr->indirection = NIL;
2071 pkattr->isRel = false;
2073 fkconstraint->pk_attrs = lappend(fkconstraint->pk_attrs, pkattr);
2077 * End index scan and close relations
2080 heap_endscan(indexSd);
2081 heap_close(indexRd, AccessShareLock);
2082 heap_close(pkrel, AccessShareLock);
2086 * Preprocess a list of column constraint clauses
2087 * to attach constraint attributes to their primary constraint nodes
2088 * and detect inconsistent/misplaced constraint attributes.
2090 * NOTE: currently, attributes are only supported for FOREIGN KEY primary
2091 * constraints, but someday they ought to be supported for other constraints.
2094 transformConstraintAttrs(List *constraintList)
2096 Node *lastprimarynode = NULL;
2097 bool saw_deferrability = false;
2098 bool saw_initially = false;
2101 foreach(clist, constraintList)
2103 Node *node = lfirst(clist);
2105 if (!IsA(node, Constraint))
2107 lastprimarynode = node;
2108 /* reset flags for new primary node */
2109 saw_deferrability = false;
2110 saw_initially = false;
2114 Constraint *con = (Constraint *) node;
2116 switch (con->contype)
2118 case CONSTR_ATTR_DEFERRABLE:
2119 if (lastprimarynode == NULL ||
2120 !IsA(lastprimarynode, FkConstraint))
2121 elog(ERROR, "Misplaced DEFERRABLE clause");
2122 if (saw_deferrability)
2123 elog(ERROR, "Multiple DEFERRABLE/NOT DEFERRABLE clauses not allowed");
2124 saw_deferrability = true;
2125 ((FkConstraint *) lastprimarynode)->deferrable = true;
2127 case CONSTR_ATTR_NOT_DEFERRABLE:
2128 if (lastprimarynode == NULL ||
2129 !IsA(lastprimarynode, FkConstraint))
2130 elog(ERROR, "Misplaced NOT DEFERRABLE clause");
2131 if (saw_deferrability)
2132 elog(ERROR, "Multiple DEFERRABLE/NOT DEFERRABLE clauses not allowed");
2133 saw_deferrability = true;
2134 ((FkConstraint *) lastprimarynode)->deferrable = false;
2135 if (saw_initially &&
2136 ((FkConstraint *) lastprimarynode)->initdeferred)
2137 elog(ERROR, "INITIALLY DEFERRED constraint must be DEFERRABLE");
2139 case CONSTR_ATTR_DEFERRED:
2140 if (lastprimarynode == NULL ||
2141 !IsA(lastprimarynode, FkConstraint))
2142 elog(ERROR, "Misplaced INITIALLY DEFERRED clause");
2144 elog(ERROR, "Multiple INITIALLY IMMEDIATE/DEFERRED clauses not allowed");
2145 saw_initially = true;
2146 ((FkConstraint *) lastprimarynode)->initdeferred = true;
2149 * If only INITIALLY DEFERRED appears, assume
2152 if (!saw_deferrability)
2153 ((FkConstraint *) lastprimarynode)->deferrable = true;
2154 else if (!((FkConstraint *) lastprimarynode)->deferrable)
2155 elog(ERROR, "INITIALLY DEFERRED constraint must be DEFERRABLE");
2157 case CONSTR_ATTR_IMMEDIATE:
2158 if (lastprimarynode == NULL ||
2159 !IsA(lastprimarynode, FkConstraint))
2160 elog(ERROR, "Misplaced INITIALLY IMMEDIATE clause");
2162 elog(ERROR, "Multiple INITIALLY IMMEDIATE/DEFERRED clauses not allowed");
2163 saw_initially = true;
2164 ((FkConstraint *) lastprimarynode)->initdeferred = false;
2167 /* Otherwise it's not an attribute */
2168 lastprimarynode = node;
2169 /* reset flags for new primary node */
2170 saw_deferrability = false;
2171 saw_initially = false;
2179 * Special handling of type definition for a column
2182 transformColumnType(ParseState *pstate, ColumnDef *column)
2186 * If the column doesn't have an explicitly specified typmod, check to
2187 * see if we want to insert a default length.
2189 * Note that we deliberately do NOT look at array or set information
2190 * here; "numeric[]" needs the same default typmod as "numeric".
2192 if (column->typename->typmod == -1)
2194 switch (typeTypeId(typenameType(column->typename->name)))
2197 /* "char" -> "char(1)" */
2198 column->typename->typmod = VARHDRSZ + 1;
2201 column->typename->typmod = VARHDRSZ +
2202 ((NUMERIC_DEFAULT_PRECISION << 16) | NUMERIC_DEFAULT_SCALE);