]> granicus.if.org Git - postgresql/blob - src/backend/parser/analyze.c
c6f21e77b03be983c556726fa3c271b407c4b9e4
[postgresql] / src / backend / parser / analyze.c
1 /*-------------------------------------------------------------------------
2  *
3  * analyze.c
4  *        transform the parse tree into a query tree
5  *
6  * Portions Copyright (c) 1996-2001, PostgreSQL Global Development Group
7  * Portions Copyright (c) 1994, Regents of the University of California
8  *
9  *      $Header: /cvsroot/pgsql/src/backend/parser/analyze.c,v 1.189 2001/06/04 23:27:23 momjian Exp $
10  *
11  *-------------------------------------------------------------------------
12  */
13
14 #include "postgres.h"
15
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/parsetree.h"
24 #include "parser/parse_agg.h"
25 #include "parser/parse_clause.h"
26 #include "parser/parse_coerce.h"
27 #include "parser/parse_expr.h"
28 #include "parser/parse_oper.h"
29 #include "parser/parse_relation.h"
30 #include "parser/parse_target.h"
31 #include "parser/parse_type.h"
32 #include "parser/parse_expr.h"
33 #include "rewrite/rewriteManip.h"
34 #include "utils/builtins.h"
35 #include "utils/fmgroids.h"
36 #include "utils/relcache.h"
37 #include "utils/syscache.h"
38
39 #ifdef MULTIBYTE
40 #include "mb/pg_wchar.h"
41 #endif
42
43 static Query *transformStmt(ParseState *pstate, Node *stmt);
44 static Query *transformDeleteStmt(ParseState *pstate, DeleteStmt *stmt);
45 static Query *transformInsertStmt(ParseState *pstate, InsertStmt *stmt);
46 static Query *transformIndexStmt(ParseState *pstate, IndexStmt *stmt);
47 static Query *transformExtendStmt(ParseState *pstate, ExtendStmt *stmt);
48 static Query *transformRuleStmt(ParseState *query, RuleStmt *stmt);
49 static Query *transformSelectStmt(ParseState *pstate, SelectStmt *stmt);
50 static Query *transformSetOperationStmt(ParseState *pstate, SelectStmt *stmt);
51 static Node *transformSetOperationTree(ParseState *pstate, SelectStmt *stmt);
52 static Query *transformUpdateStmt(ParseState *pstate, UpdateStmt *stmt);
53 static Query *transformCreateStmt(ParseState *pstate, CreateStmt *stmt);
54 static Query *transformAlterTableStmt(ParseState *pstate, AlterTableStmt *stmt);
55 static Node *transformTypeRefs(ParseState *pstate, Node *stmt);
56
57 static void transformTypeRefsList(ParseState *pstate, List *l);
58 static void transformTypeRef(ParseState *pstate, TypeName *tn);
59 static List *getSetColTypes(ParseState *pstate, Node *node);
60 static void transformForUpdate(Query *qry, List *forUpdate);
61 static void transformFkeyGetPrimaryKey(FkConstraint *fkconstraint, Oid *pktypoid);
62 static void transformConstraintAttrs(List *constraintList);
63 static void transformColumnType(ParseState *pstate, ColumnDef *column);
64 static void transformFkeyCheckAttrs(FkConstraint *fkconstraint, Oid *pktypoid);
65
66 static void release_pstate_resources(ParseState *pstate);
67 static FromExpr *makeFromExpr(List *fromlist, Node *quals);
68
69 /* kluge to return extra info from transformCreateStmt() */
70 static List *extras_before;
71 static List *extras_after;
72
73
74 /*
75  * parse_analyze -
76  *        analyze a raw parse tree and transform it to Query form.
77  *
78  * The result is a List of Query nodes (we need a list since some commands
79  * produce multiple Queries).  Optimizable statements require considerable
80  * transformation, while many utility-type statements are simply hung off
81  * a dummy CMD_UTILITY Query node.
82  */
83 List *
84 parse_analyze(Node *parseTree, ParseState *parentParseState)
85 {
86         List       *result = NIL;
87         ParseState *pstate = make_parsestate(parentParseState);
88         Query      *query;
89
90         extras_before = extras_after = NIL;
91
92         query = transformStmt(pstate, parseTree);
93         release_pstate_resources(pstate);
94
95         while (extras_before != NIL)
96         {
97                 result = lappend(result,
98                                                  transformStmt(pstate, lfirst(extras_before)));
99                 release_pstate_resources(pstate);
100                 extras_before = lnext(extras_before);
101         }
102
103         result = lappend(result, query);
104
105         while (extras_after != NIL)
106         {
107                 result = lappend(result,
108                                                  transformStmt(pstate, lfirst(extras_after)));
109                 release_pstate_resources(pstate);
110                 extras_after = lnext(extras_after);
111         }
112
113         pfree(pstate);
114
115         return result;
116 }
117
118 static void
119 release_pstate_resources(ParseState *pstate)
120 {
121         if (pstate->p_target_relation != NULL)
122                 heap_close(pstate->p_target_relation, NoLock);
123         pstate->p_target_relation = NULL;
124         pstate->p_target_rangetblentry = NULL;
125 }
126
127 /*
128  * transformStmt -
129  *        transform a Parse tree into a Query tree.
130  */
131 static Query *
132 transformStmt(ParseState *pstate, Node *parseTree)
133 {
134         Query      *result = NULL;
135
136         switch (nodeTag(parseTree))
137         {
138
139                         /*
140                          * Non-optimizable statements
141                          */
142                 case T_CreateStmt:
143                         result = transformCreateStmt(pstate, (CreateStmt *) parseTree);
144                         break;
145
146                 case T_IndexStmt:
147                         result = transformIndexStmt(pstate, (IndexStmt *) parseTree);
148                         break;
149
150                 case T_ExtendStmt:
151                         result = transformExtendStmt(pstate, (ExtendStmt *) parseTree);
152                         break;
153
154                 case T_RuleStmt:
155                         result = transformRuleStmt(pstate, (RuleStmt *) parseTree);
156                         break;
157
158                 case T_ViewStmt:
159                         {
160                                 ViewStmt   *n = (ViewStmt *) parseTree;
161
162                                 n->query = transformStmt(pstate, (Node *) n->query);
163
164                                 /*
165                                  * If a list of column names was given, run through and
166                                  * insert these into the actual query tree. - thomas
167                                  * 2000-03-08
168                                  */
169                                 if (n->aliases != NIL)
170                                 {
171                                         int                     i;
172                                         List       *targetList = n->query->targetList;
173
174                                         if (length(targetList) < length(n->aliases))
175                                                 elog(ERROR, "CREATE VIEW specifies %d columns"
176                                                          " but only %d columns are present",
177                                                          length(targetList), length(n->aliases));
178
179                                         for (i = 0; i < length(n->aliases); i++)
180                                         {
181                                                 Ident      *id;
182                                                 TargetEntry *te;
183                                                 Resdom     *rd;
184
185                                                 id = nth(i, n->aliases);
186                                                 Assert(IsA(id, Ident));
187                                                 te = nth(i, targetList);
188                                                 Assert(IsA(te, TargetEntry));
189                                                 rd = te->resdom;
190                                                 Assert(IsA(rd, Resdom));
191                                                 rd->resname = pstrdup(id->name);
192                                         }
193                                 }
194                                 result = makeNode(Query);
195                                 result->commandType = CMD_UTILITY;
196                                 result->utilityStmt = (Node *) n;
197                         }
198                         break;
199
200                 case T_ExplainStmt:
201                         {
202                                 ExplainStmt *n = (ExplainStmt *) parseTree;
203
204                                 result = makeNode(Query);
205                                 result->commandType = CMD_UTILITY;
206                                 n->query = transformStmt(pstate, (Node *) n->query);
207                                 result->utilityStmt = (Node *) parseTree;
208                         }
209                         break;
210
211                 case T_AlterTableStmt:
212                         result = transformAlterTableStmt(pstate, (AlterTableStmt *) parseTree);
213                         break;
214
215                         /*
216                          * Optimizable statements
217                          */
218                 case T_InsertStmt:
219                         result = transformInsertStmt(pstate, (InsertStmt *) parseTree);
220                         break;
221
222                 case T_DeleteStmt:
223                         result = transformDeleteStmt(pstate, (DeleteStmt *) parseTree);
224                         break;
225
226                 case T_UpdateStmt:
227                         result = transformUpdateStmt(pstate, (UpdateStmt *) parseTree);
228                         break;
229
230                 case T_SelectStmt:
231                         if (((SelectStmt *) parseTree)->op == SETOP_NONE)
232                                 result = transformSelectStmt(pstate,
233                                                                                          (SelectStmt *) parseTree);
234                         else
235                                 result = transformSetOperationStmt(pstate,
236                                                                                            (SelectStmt *) parseTree);
237                         break;
238
239                         /*
240                          * Convert use of %TYPE in statements where it is permitted.
241                          */
242                 case T_ProcedureStmt:
243                 case T_CommentStmt:
244                 case T_RemoveFuncStmt:
245                 case T_DefineStmt:
246                         result = makeNode(Query);
247                         result->commandType = CMD_UTILITY;
248                         result->utilityStmt = transformTypeRefs(pstate, parseTree);
249                         break;
250
251                 default:
252
253                         /*
254                          * other statements don't require any transformation-- just
255                          * return the original parsetree, yea!
256                          */
257                         result = makeNode(Query);
258                         result->commandType = CMD_UTILITY;
259                         result->utilityStmt = (Node *) parseTree;
260                         break;
261         }
262         return result;
263 }
264
265 /*
266  * transformDeleteStmt -
267  *        transforms a Delete Statement
268  */
269 static Query *
270 transformDeleteStmt(ParseState *pstate, DeleteStmt *stmt)
271 {
272         Query      *qry = makeNode(Query);
273         Node       *qual;
274
275         qry->commandType = CMD_DELETE;
276
277         /* set up range table with just the result rel */
278         qry->resultRelation = setTargetTable(pstate, stmt->relname,
279                                                                                  interpretInhOption(stmt->inhOpt),
280                                                                                  true);
281
282         qry->distinctClause = NIL;
283
284         /* fix where clause */
285         qual = transformWhereClause(pstate, stmt->whereClause);
286
287         /* done building the range table and jointree */
288         qry->rtable = pstate->p_rtable;
289         qry->jointree = makeFromExpr(pstate->p_joinlist, qual);
290
291         qry->hasSubLinks = pstate->p_hasSubLinks;
292         qry->hasAggs = pstate->p_hasAggs;
293         if (pstate->p_hasAggs)
294                 parseCheckAggregates(pstate, qry, qual);
295
296         return qry;
297 }
298
299 /*
300  * transformInsertStmt -
301  *        transform an Insert Statement
302  */
303 static Query *
304 transformInsertStmt(ParseState *pstate, InsertStmt *stmt)
305 {
306         Query      *qry = makeNode(Query);
307         List       *sub_rtable;
308         List       *sub_namespace;
309         List       *icolumns;
310         List       *attrnos;
311         List       *attnos;
312         int                     numuseratts;
313         List       *tl;
314         TupleDesc       rd_att;
315
316         qry->commandType = CMD_INSERT;
317         pstate->p_is_insert = true;
318
319         /*
320          * If a non-nil rangetable/namespace was passed in, and we are doing
321          * INSERT/SELECT, arrange to pass the rangetable/namespace down to the
322          * SELECT.      This can only happen if we are inside a CREATE RULE, and
323          * in that case we want the rule's OLD and NEW rtable entries to
324          * appear as part of the SELECT's rtable, not as outer references for
325          * it.  (Kluge!)  The SELECT's joinlist is not affected however. We
326          * must do this before adding the target table to the INSERT's rtable.
327          */
328         if (stmt->selectStmt)
329         {
330                 sub_rtable = pstate->p_rtable;
331                 pstate->p_rtable = NIL;
332                 sub_namespace = pstate->p_namespace;
333                 pstate->p_namespace = NIL;
334         }
335         else
336         {
337                 sub_rtable = NIL;               /* not used, but keep compiler quiet */
338                 sub_namespace = NIL;
339         }
340
341         /*
342          * Must get write lock on INSERT target table before scanning SELECT,
343          * else we will grab the wrong kind of initial lock if the target
344          * table is also mentioned in the SELECT part.  Note that the target
345          * table is not added to the joinlist or namespace.
346          */
347         qry->resultRelation = setTargetTable(pstate, stmt->relname,
348                                                                                  false, false);
349
350         /*
351          * Is it INSERT ... SELECT or INSERT ... VALUES?
352          */
353         if (stmt->selectStmt)
354         {
355                 ParseState *sub_pstate = make_parsestate(pstate->parentParseState);
356                 Query      *selectQuery;
357                 RangeTblEntry *rte;
358                 RangeTblRef *rtr;
359
360                 /*
361                  * Process the source SELECT.
362                  *
363                  * It is important that this be handled just like a standalone
364                  * SELECT; otherwise the behavior of SELECT within INSERT might be
365                  * different from a stand-alone SELECT. (Indeed, Postgres up
366                  * through 6.5 had bugs of just that nature...)
367                  */
368                 sub_pstate->p_rtable = sub_rtable;
369                 sub_pstate->p_namespace = sub_namespace;
370
371                 selectQuery = transformStmt(sub_pstate, stmt->selectStmt);
372
373                 release_pstate_resources(sub_pstate);
374                 pfree(sub_pstate);
375
376                 Assert(IsA(selectQuery, Query));
377                 Assert(selectQuery->commandType == CMD_SELECT);
378                 if (selectQuery->into || selectQuery->isPortal)
379                         elog(ERROR, "INSERT ... SELECT may not specify INTO");
380
381                 /*
382                  * Make the source be a subquery in the INSERT's rangetable, and
383                  * add it to the INSERT's joinlist.
384                  */
385                 rte = addRangeTableEntryForSubquery(pstate,
386                                                                                         selectQuery,
387                                                                                         makeAttr("*SELECT*", NULL),
388                                                                                         true);
389                 rtr = makeNode(RangeTblRef);
390                 /* assume new rte is at end */
391                 rtr->rtindex = length(pstate->p_rtable);
392                 Assert(rte == rt_fetch(rtr->rtindex, pstate->p_rtable));
393                 pstate->p_joinlist = lappend(pstate->p_joinlist, rtr);
394
395                 /*
396                  * Generate a targetlist for the INSERT that selects all the
397                  * non-resjunk columns from the subquery.  (We need this to be
398                  * separate from the subquery's tlist because we may add columns,
399                  * insert datatype coercions, etc.)
400                  *
401                  * HACK: constants in the INSERT's targetlist are copied up as-is
402                  * rather than being referenced as subquery outputs.  This is
403                  * mainly to ensure that when we try to coerce them to the target
404                  * column's datatype, the right things happen for UNKNOWN
405                  * constants. Otherwise this fails: INSERT INTO foo SELECT 'bar',
406                  * ... FROM baz
407                  */
408                 qry->targetList = NIL;
409                 foreach(tl, selectQuery->targetList)
410                 {
411                         TargetEntry *tle = (TargetEntry *) lfirst(tl);
412                         Resdom     *resnode = tle->resdom;
413                         Node       *expr;
414
415                         if (resnode->resjunk)
416                                 continue;
417                         if (tle->expr && IsA(tle->expr, Const))
418                                 expr = tle->expr;
419                         else
420                                 expr = (Node *) makeVar(rtr->rtindex,
421                                                                                 resnode->resno,
422                                                                                 resnode->restype,
423                                                                                 resnode->restypmod,
424                                                                                 0);
425                         resnode = copyObject(resnode);
426                         resnode->resno = (AttrNumber) pstate->p_last_resno++;
427                         qry->targetList = lappend(qry->targetList,
428                                                                           makeTargetEntry(resnode, expr));
429                 }
430         }
431         else
432         {
433
434                 /*
435                  * For INSERT ... VALUES, transform the given list of values to
436                  * form a targetlist for the INSERT.
437                  */
438                 qry->targetList = transformTargetList(pstate, stmt->targetList);
439         }
440
441         /*
442          * Now we are done with SELECT-like processing, and can get on with
443          * transforming the target list to match the INSERT target columns.
444          */
445
446         /* Prepare to assign non-conflicting resnos to resjunk attributes */
447         if (pstate->p_last_resno <= pstate->p_target_relation->rd_rel->relnatts)
448                 pstate->p_last_resno = pstate->p_target_relation->rd_rel->relnatts + 1;
449
450         /* Validate stmt->cols list, or build default list if no list given */
451         icolumns = checkInsertTargets(pstate, stmt->cols, &attrnos);
452
453         /*
454          * Prepare columns for assignment to target table.
455          */
456         numuseratts = 0;
457         attnos = attrnos;
458         foreach(tl, qry->targetList)
459         {
460                 TargetEntry *tle = (TargetEntry *) lfirst(tl);
461                 Ident      *id;
462
463                 Assert(!tle->resdom->resjunk);
464                 if (icolumns == NIL || attnos == NIL)
465                         elog(ERROR, "INSERT has more expressions than target columns");
466                 id = (Ident *) lfirst(icolumns);
467                 updateTargetListEntry(pstate, tle, id->name, lfirsti(attnos),
468                                                           id->indirection);
469                 numuseratts++;
470                 icolumns = lnext(icolumns);
471                 attnos = lnext(attnos);
472         }
473
474         /*
475          * It is possible that the targetlist has fewer entries than were in
476          * the columns list.  We do not consider this an error (perhaps we
477          * should, if the columns list was explictly given?).  We must
478          * truncate the attrnos list to only include the attrs actually
479          * provided, else we will fail to apply defaults for them below.
480          */
481         if (icolumns != NIL)
482                 attrnos = ltruncate(numuseratts, attrnos);
483
484         /*
485          * Add targetlist items to assign DEFAULT values to any columns that
486          * have defaults and were not assigned to by the user.
487          *
488          * XXX wouldn't it make more sense to do this further downstream, after
489          * the rule rewriter?  As is, altering a column default will not
490          * change the behavior of INSERTs in already-defined rules.
491          */
492         rd_att = pstate->p_target_relation->rd_att;
493         if (rd_att->constr && rd_att->constr->num_defval > 0)
494         {
495                 Form_pg_attribute *att = rd_att->attrs;
496                 AttrDefault *defval = rd_att->constr->defval;
497                 int                     ndef = rd_att->constr->num_defval;
498
499                 while (--ndef >= 0)
500                 {
501                         AttrNumber      attrno = defval[ndef].adnum;
502                         Form_pg_attribute thisatt = att[attrno - 1];
503                         TargetEntry *te;
504
505                         if (intMember((int) attrno, attrnos))
506                                 continue;               /* there was a user-specified value */
507
508                         /*
509                          * No user-supplied value, so add a targetentry with DEFAULT
510                          * expr and correct data for the target column.
511                          */
512                         te = makeTargetEntry(
513                                                                  makeResdom(attrno,
514                                                                                         thisatt->atttypid,
515                                                                                         thisatt->atttypmod,
516                                                                           pstrdup(NameStr(thisatt->attname)),
517                                                                                         false),
518                                                                  stringToNode(defval[ndef].adbin));
519                         qry->targetList = lappend(qry->targetList, te);
520
521                         /*
522                          * Make sure the value is coerced to the target column type
523                          * (might not be right type if it's not a constant!)
524                          */
525                         updateTargetListEntry(pstate, te, te->resdom->resname, attrno,
526                                                                   NIL);
527                 }
528         }
529
530         /* done building the range table and jointree */
531         qry->rtable = pstate->p_rtable;
532         qry->jointree = makeFromExpr(pstate->p_joinlist, NULL);
533
534         qry->hasSubLinks = pstate->p_hasSubLinks;
535         qry->hasAggs = pstate->p_hasAggs;
536         if (pstate->p_hasAggs)
537                 parseCheckAggregates(pstate, qry, NULL);
538
539         return qry;
540 }
541
542 /*
543  *      makeObjectName()
544  *
545  *      Create a name for an implicitly created index, sequence, constraint, etc.
546  *
547  *      The parameters are: the original table name, the original field name, and
548  *      a "type" string (such as "seq" or "pkey").      The field name and/or type
549  *      can be NULL if not relevant.
550  *
551  *      The result is a palloc'd string.
552  *
553  *      The basic result we want is "name1_name2_type", omitting "_name2" or
554  *      "_type" when those parameters are NULL.  However, we must generate
555  *      a name with less than NAMEDATALEN characters!  So, we truncate one or
556  *      both names if necessary to make a short-enough string.  The type part
557  *      is never truncated (so it had better be reasonably short).
558  *
559  *      To reduce the probability of collisions, we might someday add more
560  *      smarts to this routine, like including some "hash" characters computed
561  *      from the truncated characters.  Currently it seems best to keep it simple,
562  *      so that the generated names are easily predictable by a person.
563  */
564 static char *
565 makeObjectName(char *name1, char *name2, char *typename)
566 {
567         char       *name;
568         int                     overhead = 0;   /* chars needed for type and underscores */
569         int                     availchars;             /* chars available for name(s) */
570         int                     name1chars;             /* chars allocated to name1 */
571         int                     name2chars;             /* chars allocated to name2 */
572         int                     ndx;
573
574         name1chars = strlen(name1);
575         if (name2)
576         {
577                 name2chars = strlen(name2);
578                 overhead++;                             /* allow for separating underscore */
579         }
580         else
581                 name2chars = 0;
582         if (typename)
583                 overhead += strlen(typename) + 1;
584
585         availchars = NAMEDATALEN - 1 - overhead;
586
587         /*
588          * If we must truncate,  preferentially truncate the longer name. This
589          * logic could be expressed without a loop, but it's simple and
590          * obvious as a loop.
591          */
592         while (name1chars + name2chars > availchars)
593         {
594                 if (name1chars > name2chars)
595                         name1chars--;
596                 else
597                         name2chars--;
598         }
599
600 #ifdef MULTIBYTE
601         if (name1)
602                 name1chars = pg_mbcliplen(name1, name1chars, name1chars);
603         if (name2)
604                 name2chars = pg_mbcliplen(name2, name2chars, name2chars);
605 #endif
606
607         /* Now construct the string using the chosen lengths */
608         name = palloc(name1chars + name2chars + overhead + 1);
609         strncpy(name, name1, name1chars);
610         ndx = name1chars;
611         if (name2)
612         {
613                 name[ndx++] = '_';
614                 strncpy(name + ndx, name2, name2chars);
615                 ndx += name2chars;
616         }
617         if (typename)
618         {
619                 name[ndx++] = '_';
620                 strcpy(name + ndx, typename);
621         }
622         else
623                 name[ndx] = '\0';
624
625         return name;
626 }
627
628 static char *
629 CreateIndexName(char *table_name, char *column_name,
630                                 char *label, List *indices)
631 {
632         int                     pass = 0;
633         char       *iname = NULL;
634         List       *ilist;
635         char            typename[NAMEDATALEN];
636
637         /*
638          * The type name for makeObjectName is label, or labelN if that's
639          * necessary to prevent collisions among multiple indexes for the same
640          * table.  Note there is no check for collisions with already-existing
641          * indexes, only among the indexes we're about to create now; this
642          * ought to be improved someday.
643          */
644         strcpy(typename, label);
645
646         for (;;)
647         {
648                 iname = makeObjectName(table_name, column_name, typename);
649
650                 foreach(ilist, indices)
651                 {
652                         IndexStmt  *index = lfirst(ilist);
653
654                         if (index->idxname != NULL &&
655                                 strcmp(iname, index->idxname) == 0)
656                                 break;
657                 }
658                 /* ran through entire list? then no name conflict found so done */
659                 if (ilist == NIL)
660                         break;
661
662                 /* found a conflict, so try a new name component */
663                 pfree(iname);
664                 sprintf(typename, "%s%d", label, ++pass);
665         }
666
667         return iname;
668 }
669
670 /*
671  * transformCreateStmt -
672  *        transforms the "create table" statement
673  *        SQL92 allows constraints to be scattered all over, so thumb through
674  *         the columns and collect all constraints into one place.
675  *        If there are any implied indices (e.g. UNIQUE or PRIMARY KEY)
676  *         then expand those into multiple IndexStmt blocks.
677  *        - thomas 1997-12-02
678  */
679 static Query *
680 transformCreateStmt(ParseState *pstate, CreateStmt *stmt)
681 {
682         Query      *q;
683         List       *elements;
684         Node       *element;
685         List       *columns;
686         List       *dlist;
687         ColumnDef  *column;
688         List       *constraints,
689                            *clist;
690         Constraint *constraint;
691         List       *fkconstraints,      /* List of FOREIGN KEY constraints to */
692                            *fkclist;            /* add finally */
693         FkConstraint *fkconstraint;
694         List       *keys;
695         Ident      *key;
696         List       *blist = NIL;        /* "before list" of things to do before
697                                                                  * creating the table */
698         List       *ilist = NIL;        /* "index list" of things to do after
699                                                                  * creating the table */
700         IndexStmt  *index,
701                            *pkey = NULL;
702         IndexElem  *iparam;
703         bool            saw_nullable;
704
705         q = makeNode(Query);
706         q->commandType = CMD_UTILITY;
707
708         fkconstraints = NIL;
709         constraints = stmt->constraints;
710         columns = NIL;
711         dlist = NIL;
712
713         /*
714          * Run through each primary element in the table creation clause
715          */
716         foreach(elements, stmt->tableElts)
717         {
718                 element = lfirst(elements);
719                 switch (nodeTag(element))
720                 {
721                         case T_ColumnDef:
722                                 column = (ColumnDef *) element;
723                                 columns = lappend(columns, column);
724
725                                 transformColumnType(pstate, column);
726
727                                 /* Special case SERIAL type? */
728                                 if (column->is_sequence)
729                                 {
730                                         char       *sname;
731                                         char       *qstring;
732                                         A_Const    *snamenode;
733                                         FuncCall   *funccallnode;
734                                         CreateSeqStmt *sequence;
735
736                                         /*
737                                          * Create appropriate constraints for SERIAL.  We do
738                                          * this in full, rather than shortcutting, so that we
739                                          * will detect any conflicting constraints the user
740                                          * wrote (like a different DEFAULT).
741                                          */
742                                         sname = makeObjectName(stmt->relname, column->colname,
743                                                                                    "seq");
744
745                                         /*
746                                          * Create an expression tree representing the function
747                                          * call  nextval('"sequencename"')
748                                          */
749                                         qstring = palloc(strlen(sname) + 2 + 1);
750                                         sprintf(qstring, "\"%s\"", sname);
751                                         snamenode = makeNode(A_Const);
752                                         snamenode->val.type = T_String;
753                                         snamenode->val.val.str = qstring;
754                                         funccallnode = makeNode(FuncCall);
755                                         funccallnode->funcname = "nextval";
756                                         funccallnode->args = makeList1(snamenode);
757                                         funccallnode->agg_star = false;
758                                         funccallnode->agg_distinct = false;
759
760                                         constraint = makeNode(Constraint);
761                                         constraint->contype = CONSTR_DEFAULT;
762                                         constraint->name = sname;
763                                         constraint->raw_expr = (Node *) funccallnode;
764                                         constraint->cooked_expr = NULL;
765                                         constraint->keys = NIL;
766                                         column->constraints = lappend(column->constraints,
767                                                                                                   constraint);
768
769                                         constraint = makeNode(Constraint);
770                                         constraint->contype = CONSTR_UNIQUE;
771                                         constraint->name = NULL;        /* assign later */
772                                         column->constraints = lappend(column->constraints,
773                                                                                                   constraint);
774
775                                         constraint = makeNode(Constraint);
776                                         constraint->contype = CONSTR_NOTNULL;
777                                         column->constraints = lappend(column->constraints,
778                                                                                                   constraint);
779
780                                         sequence = makeNode(CreateSeqStmt);
781                                         sequence->seqname = pstrdup(sname);
782                                         sequence->options = NIL;
783
784                                         elog(NOTICE, "CREATE TABLE will create implicit sequence '%s' for SERIAL column '%s.%s'",
785                                           sequence->seqname, stmt->relname, column->colname);
786
787                                         blist = lappend(blist, sequence);
788                                 }
789
790                                 /* Process column constraints, if any... */
791                                 transformConstraintAttrs(column->constraints);
792
793                                 saw_nullable = false;
794
795                                 foreach(clist, column->constraints)
796                                 {
797                                         constraint = lfirst(clist);
798
799                                         /*
800                                          * If this column constraint is a FOREIGN KEY
801                                          * constraint, then we fill in the current attributes
802                                          * name and throw it into the list of FK constraints
803                                          * to be processed later.
804                                          */
805                                         if (IsA(constraint, FkConstraint))
806                                         {
807                                                 Ident      *id = makeNode(Ident);
808
809                                                 id->name = column->colname;
810                                                 id->indirection = NIL;
811                                                 id->isRel = false;
812
813                                                 fkconstraint = (FkConstraint *) constraint;
814                                                 fkconstraint->fk_attrs = makeList1(id);
815
816                                                 fkconstraints = lappend(fkconstraints, constraint);
817                                                 continue;
818                                         }
819
820                                         switch (constraint->contype)
821                                         {
822                                                 case CONSTR_NULL:
823                                                         if (saw_nullable && column->is_not_null)
824                                                                 elog(ERROR, "CREATE TABLE/(NOT) NULL conflicting declaration"
825                                                                          " for '%s.%s'", stmt->relname, column->colname);
826                                                         column->is_not_null = FALSE;
827                                                         saw_nullable = true;
828                                                         break;
829
830                                                 case CONSTR_NOTNULL:
831                                                         if (saw_nullable && !column->is_not_null)
832                                                                 elog(ERROR, "CREATE TABLE/(NOT) NULL conflicting declaration"
833                                                                          " for '%s.%s'", stmt->relname, column->colname);
834                                                         column->is_not_null = TRUE;
835                                                         saw_nullable = true;
836                                                         break;
837
838                                                 case CONSTR_DEFAULT:
839                                                         if (column->raw_default != NULL)
840                                                                 elog(ERROR, "CREATE TABLE/DEFAULT multiple values specified"
841                                                                          " for '%s.%s'", stmt->relname, column->colname);
842                                                         column->raw_default = constraint->raw_expr;
843                                                         Assert(constraint->cooked_expr == NULL);
844                                                         break;
845
846                                                 case CONSTR_PRIMARY:
847                                                         if (constraint->name == NULL)
848                                                                 constraint->name = makeObjectName(stmt->relname, NULL, "pkey");
849                                                         if (constraint->keys == NIL)
850                                                         {
851                                                                 key = makeNode(Ident);
852                                                                 key->name = pstrdup(column->colname);
853                                                                 constraint->keys = makeList1(key);
854                                                         }
855                                                         dlist = lappend(dlist, constraint);
856                                                         break;
857
858                                                 case CONSTR_UNIQUE:
859                                                         if (constraint->name == NULL)
860                                                                 constraint->name = makeObjectName(stmt->relname, column->colname, "key");
861                                                         if (constraint->keys == NIL)
862                                                         {
863                                                                 key = makeNode(Ident);
864                                                                 key->name = pstrdup(column->colname);
865                                                                 constraint->keys = makeList1(key);
866                                                         }
867                                                         dlist = lappend(dlist, constraint);
868                                                         break;
869
870                                                 case CONSTR_CHECK:
871                                                         if (constraint->name == NULL)
872                                                                 constraint->name = makeObjectName(stmt->relname, column->colname, NULL);
873                                                         constraints = lappend(constraints, constraint);
874                                                         break;
875
876                                                 case CONSTR_ATTR_DEFERRABLE:
877                                                 case CONSTR_ATTR_NOT_DEFERRABLE:
878                                                 case CONSTR_ATTR_DEFERRED:
879                                                 case CONSTR_ATTR_IMMEDIATE:
880                                                         /* transformConstraintAttrs took care of these */
881                                                         break;
882
883                                                 default:
884                                                         elog(ERROR, "parser: unrecognized constraint (internal error)");
885                                                         break;
886                                         }
887                                 }
888                                 break;
889
890                         case T_Constraint:
891                                 constraint = (Constraint *) element;
892                                 switch (constraint->contype)
893                                 {
894                                         case CONSTR_PRIMARY:
895                                                 if (constraint->name == NULL)
896                                                         constraint->name = makeObjectName(stmt->relname, NULL, "pkey");
897                                                 dlist = lappend(dlist, constraint);
898                                                 break;
899
900                                         case CONSTR_UNIQUE:
901                                                 dlist = lappend(dlist, constraint);
902                                                 break;
903
904                                         case CONSTR_CHECK:
905                                                 constraints = lappend(constraints, constraint);
906                                                 break;
907
908                                         case CONSTR_NULL:
909                                         case CONSTR_NOTNULL:
910                                         case CONSTR_DEFAULT:
911                                         case CONSTR_ATTR_DEFERRABLE:
912                                         case CONSTR_ATTR_NOT_DEFERRABLE:
913                                         case CONSTR_ATTR_DEFERRED:
914                                         case CONSTR_ATTR_IMMEDIATE:
915                                                 elog(ERROR, "parser: illegal context for constraint (internal error)");
916                                                 break;
917
918                                         default:
919                                                 elog(ERROR, "parser: unrecognized constraint (internal error)");
920                                                 break;
921                                 }
922                                 break;
923
924                         case T_FkConstraint:
925
926                                 /*
927                                  * Table level FOREIGN KEY constraints are already
928                                  * complete. Just remember for later.
929                                  */
930                                 fkconstraints = lappend(fkconstraints, element);
931                                 break;
932
933                         default:
934                                 elog(ERROR, "parser: unrecognized node (internal error)");
935                 }
936         }
937
938         stmt->tableElts = columns;
939         stmt->constraints = constraints;
940
941 /* Now run through the "deferred list" to complete the query transformation.
942  * For PRIMARY KEY, mark each column as NOT NULL and create an index.
943  * For UNIQUE, create an index as for PRIMARY KEY, but do not insist on
944  * NOT NULL.
945  */
946         while (dlist != NIL)
947         {
948                 constraint = lfirst(dlist);
949                 Assert(IsA(constraint, Constraint));
950                 Assert((constraint->contype == CONSTR_PRIMARY)
951                            || (constraint->contype == CONSTR_UNIQUE));
952
953                 index = makeNode(IndexStmt);
954
955                 index->unique = TRUE;
956                 index->primary = (constraint->contype == CONSTR_PRIMARY ? TRUE : FALSE);
957                 if (index->primary)
958                 {
959                         if (pkey != NULL)
960                                 elog(ERROR, "CREATE TABLE/PRIMARY KEY multiple primary keys"
961                                          " for table '%s' are not allowed", stmt->relname);
962                         pkey = index;
963                 }
964
965                 if (constraint->name != NULL)
966                         index->idxname = pstrdup(constraint->name);
967                 else if (constraint->contype == CONSTR_PRIMARY)
968                         index->idxname = makeObjectName(stmt->relname, NULL, "pkey");
969                 else
970                         index->idxname = NULL;          /* will set it later */
971
972                 index->relname = stmt->relname;
973                 index->accessMethod = "btree";
974                 index->indexParams = NIL;
975                 index->withClause = NIL;
976                 index->whereClause = NULL;
977
978                 foreach(keys, constraint->keys)
979                 {
980                         bool            found = false;
981
982                         key = (Ident *) lfirst(keys);
983                         Assert(IsA(key, Ident));
984                         column = NULL;
985                         foreach(columns, stmt->tableElts)
986                         {
987                                 column = lfirst(columns);
988                                 Assert(IsA(column, ColumnDef));
989                                 if (strcmp(column->colname, key->name) == 0)
990                                 {
991                                         found = true;
992                                         break;
993                                 }
994                         }
995                         if (found)
996                         {
997                                 /* found column in the new table; force it to be NOT NULL */
998                                 if (constraint->contype == CONSTR_PRIMARY)
999                                         column->is_not_null = TRUE;
1000                         }
1001                         else
1002                         {
1003                                 /* try inherited tables */
1004                                 List       *inhRelnames = stmt->inhRelnames;
1005                                 List       *inher;
1006
1007                                 foreach(inher, inhRelnames)
1008                                 {
1009                                         Value      *inh = lfirst(inher);
1010                                         Relation        rel;
1011                                         int                     count;
1012
1013                                         Assert(IsA(inh, String));
1014                                         rel = heap_openr(strVal(inh), AccessShareLock);
1015                                         if (rel->rd_rel->relkind != RELKIND_RELATION)
1016                                                 elog(ERROR, "inherited table \"%s\" is not a relation",
1017                                                          strVal(inh));
1018                                         for (count = 0; count < rel->rd_att->natts; count++)
1019                                         {
1020                                                 Form_pg_attribute inhattr = rel->rd_att->attrs[count];
1021                                                 char       *inhname = NameStr(inhattr->attname);
1022
1023                                                 if (strcmp(key->name, inhname) == 0)
1024                                                 {
1025                                                         found = true;
1026
1027                                                         /*
1028                                                          * If the column is inherited, we currently
1029                                                          * have no easy way to force it to be NOT
1030                                                          * NULL. Only way I can see to fix this would
1031                                                          * be to convert the inherited-column info to
1032                                                          * ColumnDef nodes before we reach this point,
1033                                                          * and then create the table from those nodes
1034                                                          * rather than referencing the parent tables
1035                                                          * later.  That would likely be cleaner, but
1036                                                          * too much work to contemplate right now.
1037                                                          * Instead, raise an error if the inherited
1038                                                          * column won't be NOT NULL. (Would a NOTICE
1039                                                          * be more reasonable?)
1040                                                          */
1041                                                         if (constraint->contype == CONSTR_PRIMARY &&
1042                                                                 !inhattr->attnotnull)
1043                                                                 elog(ERROR, "inherited attribute \"%s\" cannot be a PRIMARY KEY because it is not marked NOT NULL",
1044                                                                          inhname);
1045                                                         break;
1046                                                 }
1047                                         }
1048                                         heap_close(rel, NoLock);
1049                                         if (found)
1050                                                 break;
1051                                 }
1052                         }
1053
1054                         if (!found)
1055                                 elog(ERROR, "CREATE TABLE: column \"%s\" named in key does not exist",
1056                                          key->name);
1057
1058                         iparam = makeNode(IndexElem);
1059                         iparam->name = pstrdup(key->name);
1060                         iparam->args = NIL;
1061                         iparam->class = NULL;
1062                         index->indexParams = lappend(index->indexParams, iparam);
1063                 }
1064
1065                 ilist = lappend(ilist, index);
1066                 dlist = lnext(dlist);
1067         }
1068
1069         /*
1070          * Scan the index list and remove any redundant index specifications.
1071          * This can happen if, for instance, the user writes SERIAL PRIMARY
1072          * KEY or SERIAL UNIQUE.  A strict reading of SQL92 would suggest
1073          * raising an error instead, but that strikes me as too
1074          * anal-retentive. - tgl 2001-02-14
1075          */
1076         dlist = ilist;
1077         ilist = NIL;
1078         if (pkey != NULL)
1079         {
1080                 /* Make sure we keep the PKEY index in preference to others... */
1081                 ilist = makeList1(pkey);
1082         }
1083         while (dlist != NIL)
1084         {
1085                 index = lfirst(dlist);
1086
1087                 /* if it's pkey, it's already in ilist */
1088                 if (index != pkey)
1089                 {
1090                         bool            keep = true;
1091                         List       *priorlist;
1092
1093                         foreach(priorlist, ilist)
1094                         {
1095                                 IndexStmt  *priorindex = lfirst(priorlist);
1096
1097                                 if (equal(index->indexParams, priorindex->indexParams))
1098                                 {
1099
1100                                         /*
1101                                          * If the prior index is as yet unnamed, and this one
1102                                          * is named, then transfer the name to the prior
1103                                          * index. This ensures that if we have named and
1104                                          * unnamed constraints, we'll use (at least one of)
1105                                          * the names for the index.
1106                                          */
1107                                         if (priorindex->idxname == NULL)
1108                                                 priorindex->idxname = index->idxname;
1109                                         keep = false;
1110                                         break;
1111                                 }
1112                         }
1113
1114                         if (keep)
1115                                 ilist = lappend(ilist, index);
1116                 }
1117
1118                 dlist = lnext(dlist);
1119         }
1120
1121         /*
1122          * Finally, select unique names for all not-previously-named indices,
1123          * and display notice messages.
1124          */
1125         dlist = ilist;
1126         while (dlist != NIL)
1127         {
1128                 index = lfirst(dlist);
1129
1130                 if (index->idxname == NULL && index->indexParams != NIL)
1131                 {
1132                         iparam = lfirst(index->indexParams);
1133                         index->idxname = CreateIndexName(stmt->relname, iparam->name,
1134                                                                                          "key", ilist);
1135                 }
1136                 if (index->idxname == NULL)             /* should not happen */
1137                         elog(ERROR, "CREATE TABLE: failed to make implicit index name");
1138
1139                 elog(NOTICE, "CREATE TABLE/%s will create implicit index '%s' for table '%s'",
1140                          (index->primary ? "PRIMARY KEY" : "UNIQUE"),
1141                          index->idxname, stmt->relname);
1142
1143                 dlist = lnext(dlist);
1144         }
1145
1146         q->utilityStmt = (Node *) stmt;
1147         extras_before = blist;
1148         extras_after = ilist;
1149
1150         /*
1151          * Now process the FOREIGN KEY constraints and add appropriate queries
1152          * to the extras_after statements list.
1153          */
1154         if (fkconstraints != NIL)
1155         {
1156                 CreateTrigStmt *fk_trigger;
1157                 List       *fk_attr;
1158                 List       *pk_attr;
1159                 Ident      *id;
1160                 Oid        pktypoid[INDEX_MAX_KEYS];
1161                 Oid        fktypoid[INDEX_MAX_KEYS];
1162                 int        i;
1163
1164                 for (i=0; i<INDEX_MAX_KEYS; i++) {
1165                         pktypoid[i]=fktypoid[i]=0;
1166                 }
1167                 elog(NOTICE, "CREATE TABLE will create implicit trigger(s) for FOREIGN KEY check(s)");
1168
1169                 foreach(fkclist, fkconstraints)
1170                 {
1171                         fkconstraint = (FkConstraint *) lfirst(fkclist);
1172
1173                         /*
1174                          * If the constraint has no name, set it to <unnamed>
1175                          *
1176                          */
1177                         if (fkconstraint->constr_name == NULL)
1178                                 fkconstraint->constr_name = "<unnamed>";
1179
1180                         /*
1181                          * Check to see if the attributes mentioned by the constraint
1182                          * actually exist on this table.
1183                          */
1184                         if (fkconstraint->fk_attrs != NIL)
1185                         {
1186                                 int                     found = 0;
1187                                 int        attnum=0;
1188                                 List       *cols;
1189                                 List       *fkattrs;
1190                                 Ident      *fkattr = NULL;
1191                                 ColumnDef  *col;
1192
1193                                 foreach(fkattrs, fkconstraint->fk_attrs)
1194                                 {
1195                                         found = 0;
1196                                         fkattr = lfirst(fkattrs);
1197                                         foreach(cols, stmt->tableElts)
1198                                         {
1199                                                 col = lfirst(cols);
1200                                                 if (strcmp(col->colname, fkattr->name) == 0)
1201                                                 {
1202                                                         char *buff=TypeNameToInternalName(col->typename);
1203                                                         Oid type=typenameTypeId(buff);
1204                                                         if (!OidIsValid(type)) {
1205                                                                 elog(ERROR, "Unable to lookup type %s", col->typename->name);
1206                                                         }
1207                                                         fktypoid[attnum++]=type;
1208                                                         found = 1;
1209                                                         break;
1210                                                 }
1211                                         }
1212                                         if (!found) {
1213                                                 List       *inher;
1214                                                 List       *inhRelnames = stmt->inhRelnames;
1215                                                 Relation        rel;
1216
1217                                                 foreach(inher, inhRelnames)
1218                                                 {
1219                                                         Value      *inh = lfirst(inher);
1220                                                         int                     count;
1221
1222                                                         Assert(IsA(inh, String));
1223                                                         rel = heap_openr(strVal(inh), AccessShareLock);
1224                                                         if (rel->rd_rel->relkind != RELKIND_RELATION)
1225                                                                 elog(ERROR, "inherited table \"%s\" is not a relation",
1226                                                                          strVal(inh));
1227                                                         for (count = 0; count < rel->rd_att->natts; count++)
1228                                                         {
1229                                                                 char       *name = NameStr(rel->rd_att->attrs[count]->attname);
1230
1231                                                                 if (strcmp(fkattr->name, name) == 0)
1232                                                                 {
1233                                                                         fktypoid[attnum++]=rel->rd_att->attrs[count]->atttypid;
1234                                                                         found = 1;
1235                                                                         break;
1236                                                                 }
1237                                                         }
1238                                                         heap_close(rel, NoLock);
1239                                                         if (found)
1240                                                                 break;
1241                                                 }
1242                                         }
1243                                         if (!found)
1244                                                 break;
1245                                 }
1246                                 if (!found)
1247                                         elog(ERROR, "columns referenced in foreign key constraint not found.");
1248                         }
1249
1250                         /*
1251                          * If the attribute list for the referenced table was omitted,
1252                          * lookup for the definition of the primary key. If the
1253                          * referenced table is this table, use the definition we found
1254                          * above, rather than looking to the system tables.
1255                          *
1256                          */
1257                         if (fkconstraint->fk_attrs != NIL && fkconstraint->pk_attrs == NIL)
1258                         {
1259                                 if (strcmp(fkconstraint->pktable_name, stmt->relname) != 0)
1260                                         transformFkeyGetPrimaryKey(fkconstraint, pktypoid);
1261                                 else if (pkey != NULL)
1262                                 {
1263                                         List       *pkey_attr = pkey->indexParams;
1264                                         List       *attr;
1265                                         List       *findattr;
1266                                         IndexElem  *ielem;
1267                                         Ident      *pkattr;
1268                                         int        attnum=0;
1269                                         ColumnDef  *col;
1270
1271                                         foreach(attr, pkey_attr)
1272                                         {
1273                                                 ielem = lfirst(attr);
1274                                                 pkattr = (Ident *) makeNode(Ident);
1275                                                 pkattr->name = pstrdup(ielem->name);
1276                                                 pkattr->indirection = NIL;
1277                                                 pkattr->isRel = false;
1278                                                 fkconstraint->pk_attrs = lappend(fkconstraint->pk_attrs, pkattr);
1279                                                 foreach (findattr, stmt->tableElts) {
1280                                                                                                         col=lfirst(findattr);
1281                                                                                                         if (strcmp(col->colname, ielem->name)==0) {
1282                                                                 char *buff=TypeNameToInternalName(col->typename);
1283                                                                 Oid type=typenameTypeId(buff);
1284                                                                                                                         if (!OidIsValid(type)) {
1285                                                                                                                                         elog(ERROR, "Unable to lookup type %s", col->typename->name);
1286                                                                                                                         }
1287                                                                                                                         pktypoid[attnum++]=type; /* need to convert typename */
1288                                                                                                                         break;
1289                                                                                                         }
1290                                                 }
1291                                         }
1292                                 }
1293                                 else
1294                                 {
1295                                         elog(ERROR, "PRIMARY KEY for referenced table \"%s\" not found",
1296                                                  fkconstraint->pktable_name);
1297                                 }
1298                         }
1299                         else
1300                         {
1301                                 if (strcmp(fkconstraint->pktable_name, stmt->relname) != 0)
1302                                         transformFkeyCheckAttrs(fkconstraint, pktypoid);
1303                                 else
1304                                 {
1305                                         /* Get a unique/pk constraint from above */
1306                                         List       *index;
1307                                         int                     found = 0;
1308
1309                                         foreach(index, ilist)
1310                                         {
1311                                                 IndexStmt  *ind = lfirst(index);
1312                                                 IndexElem  *indparm;
1313                                                 List       *indparms;
1314                                                 List       *pkattrs;
1315                                                 List       *findattr;
1316                                                 ColumnDef  *col;
1317                                                 Ident      *pkattr;
1318
1319                                                 if (ind->unique)
1320                                                 {
1321                                                         int                     count = 0;
1322                                                         int attnum=0;
1323
1324                                                         foreach(indparms, ind->indexParams)
1325                                                                 count++;
1326                                                         if (count != length(fkconstraint->pk_attrs))
1327                                                                 found = 0;
1328                                                         else
1329                                                         {
1330                                                                 foreach(pkattrs, fkconstraint->pk_attrs)
1331                                                                 {
1332                                                                         found = 0;
1333                                                                         pkattr = lfirst(pkattrs);
1334                                                                         foreach(indparms, ind->indexParams)
1335                                                                         {
1336                                                                                 indparm = lfirst(indparms);
1337                                                                                 if (strcmp(indparm->name, pkattr->name) == 0)
1338                                                                                 {
1339                                                                                         foreach (findattr, stmt->tableElts) {
1340                                                                                                 col=lfirst(findattr);
1341                                                                                                 if (strcmp(col->colname, indparm->name)==0) {
1342                                                                                                         char *buff=TypeNameToInternalName(col->typename);
1343                                                                                                         Oid type=typenameTypeId(buff);
1344                                                                                                         if (!OidIsValid(type)) {
1345                                                                                                                 elog(ERROR, "Unable to lookup type %s", col->typename->name);
1346                                                                                                         }
1347                                                                                                         pktypoid[attnum++]=type;
1348                                                                                                         found=1;
1349                                                                                                         break;
1350                                                                                                 }
1351                                                                                         }
1352                                                                                         if (!found) {
1353                                                                                                 List *inher;
1354                                                                                                 List *inhRelnames=stmt->inhRelnames;
1355                                                                                                 Relation rel;
1356                                                                                                 foreach (inher, inhRelnames) {
1357                                                                                                         Value *inh=lfirst(inher);
1358                                                                                                         int count;
1359                                                                                                         Assert(IsA(inh, String));
1360                                                                                                         rel=heap_openr(strVal(inh), AccessShareLock);
1361                                                                                                         if (rel->rd_rel->relkind!=RELKIND_RELATION)
1362                                                                                                                 elog(ERROR, "inherited table \"%s\" is not a relation", strVal(inh));
1363                                                                                                         for (count=0; count<rel->rd_att->natts; count++) {
1364                                                                                                                 char *name=NameStr(rel->rd_att->attrs[count]->attname);
1365                                                                                                                 if (strcmp(pkattr->name, name)==0) {
1366                                                                                                                         pktypoid[attnum++]=rel->rd_att->attrs[count]->atttypid;
1367                                                                                                                         found=1;
1368                                                                                                                         break;
1369                                                                                                                 }
1370                                                                                                         }
1371                                                                                                         heap_close(rel, NoLock);
1372                                                                                                         if (found)
1373                                                                                                                 break;
1374                                                                                                 }
1375                                                                                         }
1376                                                                                         break;
1377                                                                                 }
1378                                                                         }
1379                                                                         if (!found)
1380                                                                                 break;
1381                                                                 }
1382                                                         }
1383                                                 }
1384                                                 if (found)
1385                                                         break;
1386                                         }
1387                                         if (!found)
1388                                                 elog(ERROR, "UNIQUE constraint matching given keys for referenced table \"%s\" not found",
1389                                                          fkconstraint->pktable_name);
1390                                 }
1391                         }
1392
1393                         for (i = 0; i < INDEX_MAX_KEYS && fktypoid[i] != 0; i++) {
1394                                 /*
1395                                  * fktypoid[i] is the foreign key table's i'th element's type oid
1396                                  * pktypoid[i] is the primary key table's i'th element's type oid
1397                                  * We let oper() do our work for us, including elog(ERROR) if the
1398                                  * types don't compare with =
1399                                  */
1400                                 Operator o=oper("=", fktypoid[i], pktypoid[i], false);
1401                                 ReleaseSysCache(o);
1402                         }
1403                         /*
1404                          * Build a CREATE CONSTRAINT TRIGGER statement for the CHECK
1405                          * action.
1406                          *
1407                          */
1408                         fk_trigger = (CreateTrigStmt *) makeNode(CreateTrigStmt);
1409                         fk_trigger->trigname = fkconstraint->constr_name;
1410                         fk_trigger->relname = stmt->relname;
1411                         fk_trigger->funcname = "RI_FKey_check_ins";
1412                         fk_trigger->before = false;
1413                         fk_trigger->row = true;
1414                         fk_trigger->actions[0] = 'i';
1415                         fk_trigger->actions[1] = 'u';
1416                         fk_trigger->actions[2] = '\0';
1417                         fk_trigger->lang = NULL;
1418                         fk_trigger->text = NULL;
1419
1420                         fk_trigger->attr = NIL;
1421                         fk_trigger->when = NULL;
1422                         fk_trigger->isconstraint = true;
1423                         fk_trigger->deferrable = fkconstraint->deferrable;
1424                         fk_trigger->initdeferred = fkconstraint->initdeferred;
1425                         fk_trigger->constrrelname = fkconstraint->pktable_name;
1426
1427                         fk_trigger->args = NIL;
1428                         fk_trigger->args = lappend(fk_trigger->args,
1429                                                                   makeString(fkconstraint->constr_name));
1430                         fk_trigger->args = lappend(fk_trigger->args,
1431                                                                            makeString(stmt->relname));
1432                         fk_trigger->args = lappend(fk_trigger->args,
1433                                                                  makeString(fkconstraint->pktable_name));
1434                         fk_trigger->args = lappend(fk_trigger->args,
1435                                                                    makeString(fkconstraint->match_type));
1436                         fk_attr = fkconstraint->fk_attrs;
1437                         pk_attr = fkconstraint->pk_attrs;
1438                         if (length(fk_attr) != length(pk_attr))
1439                         {
1440                                 elog(NOTICE, "Illegal FOREIGN KEY definition REFERENCES \"%s\"",
1441                                          fkconstraint->pktable_name);
1442                                 elog(ERROR, "number of key attributes in referenced table must be equal to foreign key");
1443                         }
1444                         while (fk_attr != NIL)
1445                         {
1446                                 id = (Ident *) lfirst(fk_attr);
1447                                 fk_trigger->args = lappend(fk_trigger->args,
1448                                                                                    makeString(id->name));
1449
1450                                 id = (Ident *) lfirst(pk_attr);
1451                                 fk_trigger->args = lappend(fk_trigger->args,
1452                                                                                    makeString(id->name));
1453
1454                                 fk_attr = lnext(fk_attr);
1455                                 pk_attr = lnext(pk_attr);
1456                         }
1457
1458                         extras_after = lappend(extras_after, (Node *) fk_trigger);
1459
1460                         /*
1461                          * Build a CREATE CONSTRAINT TRIGGER statement for the ON
1462                          * DELETE action fired on the PK table !!!
1463                          *
1464                          */
1465                         fk_trigger = (CreateTrigStmt *) makeNode(CreateTrigStmt);
1466                         fk_trigger->trigname = fkconstraint->constr_name;
1467                         fk_trigger->relname = fkconstraint->pktable_name;
1468                         fk_trigger->before = false;
1469                         fk_trigger->row = true;
1470                         fk_trigger->actions[0] = 'd';
1471                         fk_trigger->actions[1] = '\0';
1472                         fk_trigger->lang = NULL;
1473                         fk_trigger->text = NULL;
1474
1475                         fk_trigger->attr = NIL;
1476                         fk_trigger->when = NULL;
1477                         fk_trigger->isconstraint = true;
1478                         fk_trigger->deferrable = fkconstraint->deferrable;
1479                         fk_trigger->initdeferred = fkconstraint->initdeferred;
1480                         fk_trigger->constrrelname = stmt->relname;
1481                         switch ((fkconstraint->actions & FKCONSTR_ON_DELETE_MASK)
1482                                         >> FKCONSTR_ON_DELETE_SHIFT)
1483                         {
1484                                 case FKCONSTR_ON_KEY_NOACTION:
1485                                         fk_trigger->funcname = "RI_FKey_noaction_del";
1486                                         break;
1487                                 case FKCONSTR_ON_KEY_RESTRICT:
1488                                         fk_trigger->deferrable = false;
1489                                         fk_trigger->initdeferred = false;
1490                                         fk_trigger->funcname = "RI_FKey_restrict_del";
1491                                         break;
1492                                 case FKCONSTR_ON_KEY_CASCADE:
1493                                         fk_trigger->funcname = "RI_FKey_cascade_del";
1494                                         break;
1495                                 case FKCONSTR_ON_KEY_SETNULL:
1496                                         fk_trigger->funcname = "RI_FKey_setnull_del";
1497                                         break;
1498                                 case FKCONSTR_ON_KEY_SETDEFAULT:
1499                                         fk_trigger->funcname = "RI_FKey_setdefault_del";
1500                                         break;
1501                                 default:
1502                                         elog(ERROR, "Only one ON DELETE action can be specified for FOREIGN KEY constraint");
1503                                         break;
1504                         }
1505
1506                         fk_trigger->args = NIL;
1507                         fk_trigger->args = lappend(fk_trigger->args,
1508                                                                   makeString(fkconstraint->constr_name));
1509                         fk_trigger->args = lappend(fk_trigger->args,
1510                                                                            makeString(stmt->relname));
1511                         fk_trigger->args = lappend(fk_trigger->args,
1512                                                                  makeString(fkconstraint->pktable_name));
1513                         fk_trigger->args = lappend(fk_trigger->args,
1514                                                                    makeString(fkconstraint->match_type));
1515                         fk_attr = fkconstraint->fk_attrs;
1516                         pk_attr = fkconstraint->pk_attrs;
1517                         while (fk_attr != NIL)
1518                         {
1519                                 id = (Ident *) lfirst(fk_attr);
1520                                 fk_trigger->args = lappend(fk_trigger->args,
1521                                                                                    makeString(id->name));
1522
1523                                 id = (Ident *) lfirst(pk_attr);
1524                                 fk_trigger->args = lappend(fk_trigger->args,
1525                                                                                    makeString(id->name));
1526
1527                                 fk_attr = lnext(fk_attr);
1528                                 pk_attr = lnext(pk_attr);
1529                         }
1530
1531                         extras_after = lappend(extras_after, (Node *) fk_trigger);
1532
1533                         /*
1534                          * Build a CREATE CONSTRAINT TRIGGER statement for the ON
1535                          * UPDATE action fired on the PK table !!!
1536                          *
1537                          */
1538                         fk_trigger = (CreateTrigStmt *) makeNode(CreateTrigStmt);
1539                         fk_trigger->trigname = fkconstraint->constr_name;
1540                         fk_trigger->relname = fkconstraint->pktable_name;
1541                         fk_trigger->before = false;
1542                         fk_trigger->row = true;
1543                         fk_trigger->actions[0] = 'u';
1544                         fk_trigger->actions[1] = '\0';
1545                         fk_trigger->lang = NULL;
1546                         fk_trigger->text = NULL;
1547
1548                         fk_trigger->attr = NIL;
1549                         fk_trigger->when = NULL;
1550                         fk_trigger->isconstraint = true;
1551                         fk_trigger->deferrable = fkconstraint->deferrable;
1552                         fk_trigger->initdeferred = fkconstraint->initdeferred;
1553                         fk_trigger->constrrelname = stmt->relname;
1554                         switch ((fkconstraint->actions & FKCONSTR_ON_UPDATE_MASK)
1555                                         >> FKCONSTR_ON_UPDATE_SHIFT)
1556                         {
1557                                 case FKCONSTR_ON_KEY_NOACTION:
1558                                         fk_trigger->funcname = "RI_FKey_noaction_upd";
1559                                         break;
1560                                 case FKCONSTR_ON_KEY_RESTRICT:
1561                                         fk_trigger->deferrable = false;
1562                                         fk_trigger->initdeferred = false;
1563                                         fk_trigger->funcname = "RI_FKey_restrict_upd";
1564                                         break;
1565                                 case FKCONSTR_ON_KEY_CASCADE:
1566                                         fk_trigger->funcname = "RI_FKey_cascade_upd";
1567                                         break;
1568                                 case FKCONSTR_ON_KEY_SETNULL:
1569                                         fk_trigger->funcname = "RI_FKey_setnull_upd";
1570                                         break;
1571                                 case FKCONSTR_ON_KEY_SETDEFAULT:
1572                                         fk_trigger->funcname = "RI_FKey_setdefault_upd";
1573                                         break;
1574                                 default:
1575                                         elog(ERROR, "Only one ON UPDATE action can be specified for FOREIGN KEY constraint");
1576                                         break;
1577                         }
1578
1579                         fk_trigger->args = NIL;
1580                         fk_trigger->args = lappend(fk_trigger->args,
1581                                                                   makeString(fkconstraint->constr_name));
1582                         fk_trigger->args = lappend(fk_trigger->args,
1583                                                                            makeString(stmt->relname));
1584                         fk_trigger->args = lappend(fk_trigger->args,
1585                                                                  makeString(fkconstraint->pktable_name));
1586                         fk_trigger->args = lappend(fk_trigger->args,
1587                                                                    makeString(fkconstraint->match_type));
1588                         fk_attr = fkconstraint->fk_attrs;
1589                         pk_attr = fkconstraint->pk_attrs;
1590                         while (fk_attr != NIL)
1591                         {
1592                                 id = (Ident *) lfirst(fk_attr);
1593                                 fk_trigger->args = lappend(fk_trigger->args,
1594                                                                                    makeString(id->name));
1595
1596                                 id = (Ident *) lfirst(pk_attr);
1597                                 fk_trigger->args = lappend(fk_trigger->args,
1598                                                                                    makeString(id->name));
1599
1600                                 fk_attr = lnext(fk_attr);
1601                                 pk_attr = lnext(pk_attr);
1602                         }
1603
1604                         extras_after = lappend(extras_after, (Node *) fk_trigger);
1605                 }
1606         }
1607
1608         return q;
1609 }       /* transformCreateStmt() */
1610
1611
1612 /*
1613  * transformIndexStmt -
1614  *        transforms the qualification of the index statement
1615  */
1616 static Query *
1617 transformIndexStmt(ParseState *pstate, IndexStmt *stmt)
1618 {
1619         Query      *qry;
1620
1621         qry = makeNode(Query);
1622         qry->commandType = CMD_UTILITY;
1623
1624         /* take care of the where clause */
1625         stmt->whereClause = transformWhereClause(pstate, stmt->whereClause);
1626
1627         qry->hasSubLinks = pstate->p_hasSubLinks;
1628
1629         stmt->rangetable = pstate->p_rtable;
1630
1631         qry->utilityStmt = (Node *) stmt;
1632
1633         return qry;
1634 }
1635
1636 /*
1637  * transformExtendStmt -
1638  *        transform the qualifications of the Extend Index Statement
1639  *
1640  */
1641 static Query *
1642 transformExtendStmt(ParseState *pstate, ExtendStmt *stmt)
1643 {
1644         Query      *qry;
1645
1646         qry = makeNode(Query);
1647         qry->commandType = CMD_UTILITY;
1648
1649         /* take care of the where clause */
1650         stmt->whereClause = transformWhereClause(pstate, stmt->whereClause);
1651
1652         qry->hasSubLinks = pstate->p_hasSubLinks;
1653
1654         stmt->rangetable = pstate->p_rtable;
1655
1656         qry->utilityStmt = (Node *) stmt;
1657         return qry;
1658 }
1659
1660 /*
1661  * transformRuleStmt -
1662  *        transform a Create Rule Statement. The actions is a list of parse
1663  *        trees which is transformed into a list of query trees.
1664  */
1665 static Query *
1666 transformRuleStmt(ParseState *pstate, RuleStmt *stmt)
1667 {
1668         Query      *qry;
1669         RangeTblEntry *oldrte;
1670         RangeTblEntry *newrte;
1671
1672         qry = makeNode(Query);
1673         qry->commandType = CMD_UTILITY;
1674         qry->utilityStmt = (Node *) stmt;
1675
1676         /*
1677          * To avoid deadlock, make sure the first thing we do is grab
1678          * AccessExclusiveLock on the target relation.  This will be needed by
1679          * DefineQueryRewrite(), and we don't want to grab a lesser lock
1680          * beforehand.  We don't need to hold a refcount on the relcache
1681          * entry, however.
1682          */
1683         heap_close(heap_openr(stmt->object->relname, AccessExclusiveLock),
1684                            NoLock);
1685
1686         /*
1687          * NOTE: 'OLD' must always have a varno equal to 1 and 'NEW' equal to
1688          * 2.  Set up their RTEs in the main pstate for use in parsing the
1689          * rule qualification.
1690          */
1691         Assert(pstate->p_rtable == NIL);
1692         oldrte = addRangeTableEntry(pstate, stmt->object->relname,
1693                                                                 makeAttr("*OLD*", NULL),
1694                                                                 false, true);
1695         newrte = addRangeTableEntry(pstate, stmt->object->relname,
1696                                                                 makeAttr("*NEW*", NULL),
1697                                                                 false, true);
1698         /* Must override addRangeTableEntry's default access-check flags */
1699         oldrte->checkForRead = false;
1700         newrte->checkForRead = false;
1701
1702         /*
1703          * They must be in the namespace too for lookup purposes, but only add
1704          * the one(s) that are relevant for the current kind of rule.  In an
1705          * UPDATE rule, quals must refer to OLD.field or NEW.field to be
1706          * unambiguous, but there's no need to be so picky for INSERT &
1707          * DELETE. (Note we marked the RTEs "inFromCl = true" above to allow
1708          * unqualified references to their fields.)  We do not add them to the
1709          * joinlist.
1710          */
1711         switch (stmt->event)
1712         {
1713                 case CMD_SELECT:
1714                         addRTEtoQuery(pstate, oldrte, false, true);
1715                         break;
1716                 case CMD_UPDATE:
1717                         addRTEtoQuery(pstate, oldrte, false, true);
1718                         addRTEtoQuery(pstate, newrte, false, true);
1719                         break;
1720                 case CMD_INSERT:
1721                         addRTEtoQuery(pstate, newrte, false, true);
1722                         break;
1723                 case CMD_DELETE:
1724                         addRTEtoQuery(pstate, oldrte, false, true);
1725                         break;
1726                 default:
1727                         elog(ERROR, "transformRuleStmt: unexpected event type %d",
1728                                  (int) stmt->event);
1729                         break;
1730         }
1731
1732         /* take care of the where clause */
1733         stmt->whereClause = transformWhereClause(pstate, stmt->whereClause);
1734
1735         if (length(pstate->p_rtable) != 2)      /* naughty, naughty... */
1736                 elog(ERROR, "Rule WHERE condition may not contain references to other relations");
1737
1738         /* save info about sublinks in where clause */
1739         qry->hasSubLinks = pstate->p_hasSubLinks;
1740
1741         /*
1742          * 'instead nothing' rules with a qualification need a query
1743          * rangetable so the rewrite handler can add the negated rule
1744          * qualification to the original query. We create a query with the new
1745          * command type CMD_NOTHING here that is treated specially by the
1746          * rewrite system.
1747          */
1748         if (stmt->actions == NIL)
1749         {
1750                 Query      *nothing_qry = makeNode(Query);
1751
1752                 nothing_qry->commandType = CMD_NOTHING;
1753                 nothing_qry->rtable = pstate->p_rtable;
1754                 nothing_qry->jointree = makeFromExpr(NIL, NULL);                /* no join wanted */
1755
1756                 stmt->actions = makeList1(nothing_qry);
1757         }
1758         else
1759         {
1760                 List       *oldactions;
1761                 List       *newactions = NIL;
1762
1763                 /*
1764                  * transform each statement, like parse_analyze()
1765                  */
1766                 foreach(oldactions, stmt->actions)
1767                 {
1768                         Node       *action = (Node *) lfirst(oldactions);
1769                         ParseState *sub_pstate = make_parsestate(pstate->parentParseState);
1770                         Query      *sub_qry,
1771                                            *top_subqry;
1772                         bool            has_old,
1773                                                 has_new;
1774
1775                         /*
1776                          * Set up OLD/NEW in the rtable for this statement.  The
1777                          * entries are marked not inFromCl because we don't want them
1778                          * to be referred to by unqualified field names nor "*" in the
1779                          * rule actions.  We must add them to the namespace, however,
1780                          * or they won't be accessible at all.  We decide later
1781                          * whether to put them in the joinlist.
1782                          */
1783                         oldrte = addRangeTableEntry(sub_pstate, stmt->object->relname,
1784                                                                                 makeAttr("*OLD*", NULL),
1785                                                                                 false, false);
1786                         newrte = addRangeTableEntry(sub_pstate, stmt->object->relname,
1787                                                                                 makeAttr("*NEW*", NULL),
1788                                                                                 false, false);
1789                         oldrte->checkForRead = false;
1790                         newrte->checkForRead = false;
1791                         addRTEtoQuery(sub_pstate, oldrte, false, true);
1792                         addRTEtoQuery(sub_pstate, newrte, false, true);
1793
1794                         /* Transform the rule action statement */
1795                         top_subqry = transformStmt(sub_pstate, action);
1796
1797                         /*
1798                          * We cannot support utility-statement actions (eg NOTIFY)
1799                          * with nonempty rule WHERE conditions, because there's no
1800                          * way to make the utility action execute conditionally.
1801                          */
1802                         if (top_subqry->commandType == CMD_UTILITY &&
1803                                 stmt->whereClause != NULL)
1804                                 elog(ERROR, "Rules with WHERE conditions may only have SELECT, INSERT, UPDATE, or DELETE actions");
1805
1806                         /*
1807                          * If the action is INSERT...SELECT, OLD/NEW have been pushed
1808                          * down into the SELECT, and that's what we need to look at.
1809                          * (Ugly kluge ... try to fix this when we redesign
1810                          * querytrees.)
1811                          */
1812                         sub_qry = getInsertSelectQuery(top_subqry, NULL);
1813
1814                         /*
1815                          * Validate action's use of OLD/NEW, qual too
1816                          */
1817                         has_old =
1818                                 rangeTableEntry_used((Node *) sub_qry, PRS2_OLD_VARNO, 0) ||
1819                                 rangeTableEntry_used(stmt->whereClause, PRS2_OLD_VARNO, 0);
1820                         has_new =
1821                                 rangeTableEntry_used((Node *) sub_qry, PRS2_NEW_VARNO, 0) ||
1822                                 rangeTableEntry_used(stmt->whereClause, PRS2_NEW_VARNO, 0);
1823
1824                         switch (stmt->event)
1825                         {
1826                                 case CMD_SELECT:
1827                                         if (has_old)
1828                                                 elog(ERROR, "ON SELECT rule may not use OLD");
1829                                         if (has_new)
1830                                                 elog(ERROR, "ON SELECT rule may not use NEW");
1831                                         break;
1832                                 case CMD_UPDATE:
1833                                         /* both are OK */
1834                                         break;
1835                                 case CMD_INSERT:
1836                                         if (has_old)
1837                                                 elog(ERROR, "ON INSERT rule may not use OLD");
1838                                         break;
1839                                 case CMD_DELETE:
1840                                         if (has_new)
1841                                                 elog(ERROR, "ON DELETE rule may not use NEW");
1842                                         break;
1843                                 default:
1844                                         elog(ERROR, "transformRuleStmt: unexpected event type %d",
1845                                                  (int) stmt->event);
1846                                         break;
1847                         }
1848
1849                         /*
1850                          * For efficiency's sake, add OLD to the rule action's
1851                          * jointree only if it was actually referenced in the
1852                          * statement or qual.
1853                          *
1854                          * For INSERT, NEW is not really a relation (only a reference to
1855                          * the to-be-inserted tuple) and should never be added to the
1856                          * jointree.
1857                          *
1858                          * For UPDATE, we treat NEW as being another kind of reference to
1859                          * OLD, because it represents references to *transformed*
1860                          * tuples of the existing relation.  It would be wrong to
1861                          * enter NEW separately in the jointree, since that would
1862                          * cause a double join of the updated relation.  It's also
1863                          * wrong to fail to make a jointree entry if only NEW and not
1864                          * OLD is mentioned.
1865                          */
1866                         if (has_old || (has_new && stmt->event == CMD_UPDATE))
1867                         {
1868                                 /* hack so we can use addRTEtoQuery() */
1869                                 sub_pstate->p_rtable = sub_qry->rtable;
1870                                 sub_pstate->p_joinlist = sub_qry->jointree->fromlist;
1871                                 addRTEtoQuery(sub_pstate, oldrte, true, false);
1872                                 sub_qry->jointree->fromlist = sub_pstate->p_joinlist;
1873                         }
1874
1875                         newactions = lappend(newactions, top_subqry);
1876
1877                         release_pstate_resources(sub_pstate);
1878                         pfree(sub_pstate);
1879                 }
1880
1881                 stmt->actions = newactions;
1882         }
1883
1884         return qry;
1885 }
1886
1887
1888 /*
1889  * transformSelectStmt -
1890  *        transforms a Select Statement
1891  *
1892  * Note: this is also used for DECLARE CURSOR statements.
1893  */
1894 static Query *
1895 transformSelectStmt(ParseState *pstate, SelectStmt *stmt)
1896 {
1897         Query      *qry = makeNode(Query);
1898         Node       *qual;
1899
1900         qry->commandType = CMD_SELECT;
1901
1902         if (stmt->portalname)
1903         {
1904                 /* DECLARE CURSOR */
1905                 if (stmt->into)
1906                         elog(ERROR, "DECLARE CURSOR must not specify INTO");
1907                 if (stmt->forUpdate)
1908                         elog(ERROR, "DECLARE/UPDATE is not supported"
1909                                  "\n\tCursors must be READ ONLY");
1910
1911                 /*
1912                  * 15 august 1991 -- since 3.0 postgres does locking right, we
1913                  * discovered that portals were violating locking protocol. portal
1914                  * locks cannot span xacts. as a short-term fix, we installed the
1915                  * check here. -- mao
1916                  */
1917                 if (!IsTransactionBlock())
1918                         elog(ERROR, "DECLARE CURSOR may only be used in begin/end transaction blocks");
1919
1920                 qry->into = stmt->portalname;
1921                 qry->isTemp = stmt->istemp;
1922                 qry->isPortal = TRUE;
1923                 qry->isBinary = stmt->binary;   /* internal portal */
1924         }
1925         else
1926         {
1927                 /* SELECT */
1928                 qry->into = stmt->into;
1929                 qry->isTemp = stmt->istemp;
1930                 qry->isPortal = FALSE;
1931                 qry->isBinary = FALSE;
1932         }
1933
1934         /* make FOR UPDATE clause available to addRangeTableEntry */
1935         pstate->p_forUpdate = stmt->forUpdate;
1936
1937         /* process the FROM clause */
1938         transformFromClause(pstate, stmt->fromClause);
1939
1940         /* transform targetlist and WHERE */
1941         qry->targetList = transformTargetList(pstate, stmt->targetList);
1942
1943         qual = transformWhereClause(pstate, stmt->whereClause);
1944
1945         /*
1946          * Initial processing of HAVING clause is just like WHERE clause.
1947          * Additional work will be done in optimizer/plan/planner.c.
1948          */
1949         qry->havingQual = transformWhereClause(pstate, stmt->havingClause);
1950
1951         qry->groupClause = transformGroupClause(pstate,
1952                                                                                         stmt->groupClause,
1953                                                                                         qry->targetList);
1954
1955         qry->sortClause = transformSortClause(pstate,
1956                                                                                   stmt->sortClause,
1957                                                                                   qry->targetList);
1958
1959         qry->distinctClause = transformDistinctClause(pstate,
1960                                                                                                   stmt->distinctClause,
1961                                                                                                   qry->targetList,
1962                                                                                                   &qry->sortClause);
1963
1964         qry->limitOffset = stmt->limitOffset;
1965         qry->limitCount = stmt->limitCount;
1966
1967         qry->hasSubLinks = pstate->p_hasSubLinks;
1968         qry->hasAggs = pstate->p_hasAggs;
1969         if (pstate->p_hasAggs || qry->groupClause || qry->havingQual)
1970                 parseCheckAggregates(pstate, qry, qual);
1971
1972         qry->rtable = pstate->p_rtable;
1973         qry->jointree = makeFromExpr(pstate->p_joinlist, qual);
1974
1975         if (stmt->forUpdate != NIL)
1976                 transformForUpdate(qry, stmt->forUpdate);
1977
1978         return qry;
1979 }
1980
1981 /*
1982  * transformSetOperationsStmt -
1983  *        transforms a set-operations tree
1984  *
1985  * A set-operation tree is just a SELECT, but with UNION/INTERSECT/EXCEPT
1986  * structure to it.  We must transform each leaf SELECT and build up a top-
1987  * level Query that contains the leaf SELECTs as subqueries in its rangetable.
1988  * The tree of set operations is converted into the setOperations field of
1989  * the top-level Query.
1990  */
1991 static Query *transformSetOperationStmt(ParseState *pstate, SelectStmt *stmt)
1992 {
1993         Query      *qry = makeNode(Query);
1994         SelectStmt *leftmostSelect;
1995         int                     leftmostRTI;
1996         Query      *leftmostQuery;
1997         SetOperationStmt *sostmt;
1998         char       *into;
1999         bool            istemp;
2000         char       *portalname;
2001         bool            binary;
2002         List       *sortClause;
2003         Node       *limitOffset;
2004         Node       *limitCount;
2005         List       *forUpdate;
2006         Node       *node;
2007         List       *lefttl,
2008                            *dtlist,
2009                            *targetvars,
2010                            *targetnames,
2011                            *sv_namespace;
2012         JoinExpr   *jnode;
2013         int                     tllen;
2014
2015         qry->commandType = CMD_SELECT;
2016
2017         /*
2018          * Find leftmost leaf SelectStmt; extract the one-time-only items from
2019          * it and from the top-level node.
2020          */
2021         leftmostSelect = stmt->larg;
2022         while (leftmostSelect && leftmostSelect->op != SETOP_NONE)
2023                 leftmostSelect = leftmostSelect->larg;
2024         Assert(leftmostSelect && IsA(leftmostSelect, SelectStmt) &&
2025                    leftmostSelect->larg == NULL);
2026         into = leftmostSelect->into;
2027         istemp = leftmostSelect->istemp;
2028         portalname = stmt->portalname;
2029         binary = stmt->binary;
2030
2031         /* clear them to prevent complaints in transformSetOperationTree() */
2032         leftmostSelect->into = NULL;
2033         leftmostSelect->istemp = false;
2034         stmt->portalname = NULL;
2035         stmt->binary = false;
2036
2037         /*
2038          * These are not one-time, exactly, but we want to process them here
2039          * and not let transformSetOperationTree() see them --- else it'll
2040          * just recurse right back here!
2041          */
2042         sortClause = stmt->sortClause;
2043         limitOffset = stmt->limitOffset;
2044         limitCount = stmt->limitCount;
2045         forUpdate = stmt->forUpdate;
2046
2047         stmt->sortClause = NIL;
2048         stmt->limitOffset = NULL;
2049         stmt->limitCount = NULL;
2050         stmt->forUpdate = NIL;
2051
2052         /* We don't support forUpdate with set ops at the moment. */
2053         if (forUpdate)
2054                 elog(ERROR, "SELECT FOR UPDATE is not allowed with UNION/INTERSECT/EXCEPT");
2055
2056         /*
2057          * Recursively transform the components of the tree.
2058          */
2059         sostmt = (SetOperationStmt *) transformSetOperationTree(pstate, stmt);
2060         Assert(sostmt && IsA(sostmt, SetOperationStmt));
2061         qry->setOperations = (Node *) sostmt;
2062
2063         /*
2064          * Re-find leftmost SELECT (now it's a sub-query in rangetable)
2065          */
2066         node = sostmt->larg;
2067         while (node && IsA(node, SetOperationStmt))
2068                 node = ((SetOperationStmt *) node)->larg;
2069         Assert(node && IsA(node, RangeTblRef));
2070         leftmostRTI = ((RangeTblRef *) node)->rtindex;
2071         leftmostQuery = rt_fetch(leftmostRTI, pstate->p_rtable)->subquery;
2072         Assert(leftmostQuery != NULL);
2073
2074         /*
2075          * Generate dummy targetlist for outer query using column names of
2076          * leftmost select and common datatypes of topmost set operation. Also
2077          * make lists of the dummy vars and their names for use in parsing
2078          * ORDER BY.
2079          */
2080         qry->targetList = NIL;
2081         targetvars = NIL;
2082         targetnames = NIL;
2083         lefttl = leftmostQuery->targetList;
2084         foreach(dtlist, sostmt->colTypes)
2085         {
2086                 Oid                     colType = (Oid) lfirsti(dtlist);
2087                 Resdom     *leftResdom = ((TargetEntry *) lfirst(lefttl))->resdom;
2088                 char       *colName = pstrdup(leftResdom->resname);
2089                 Resdom     *resdom;
2090                 Node       *expr;
2091
2092                 resdom = makeResdom((AttrNumber) pstate->p_last_resno++,
2093                                                         colType,
2094                                                         -1,
2095                                                         colName,
2096                                                         false);
2097                 expr = (Node *) makeVar(leftmostRTI,
2098                                                                 leftResdom->resno,
2099                                                                 colType,
2100                                                                 -1,
2101                                                                 0);
2102                 qry->targetList = lappend(qry->targetList,
2103                                                                   makeTargetEntry(resdom, expr));
2104                 targetvars = lappend(targetvars, expr);
2105                 targetnames = lappend(targetnames, makeString(colName));
2106                 lefttl = lnext(lefttl);
2107         }
2108
2109         /*
2110          * Insert one-time items into top-level query
2111          *
2112          * This needs to agree with transformSelectStmt!
2113          */
2114         if (portalname)
2115         {
2116                 /* DECLARE CURSOR */
2117                 if (into)
2118                         elog(ERROR, "DECLARE CURSOR must not specify INTO");
2119                 if (forUpdate)
2120                         elog(ERROR, "DECLARE/UPDATE is not supported"
2121                                  "\n\tCursors must be READ ONLY");
2122
2123                 /*
2124                  * 15 august 1991 -- since 3.0 postgres does locking right, we
2125                  * discovered that portals were violating locking protocol. portal
2126                  * locks cannot span xacts. as a short-term fix, we installed the
2127                  * check here. -- mao
2128                  */
2129                 if (!IsTransactionBlock())
2130                         elog(ERROR, "DECLARE CURSOR may only be used in begin/end transaction blocks");
2131
2132                 qry->into = portalname;
2133                 qry->isTemp = istemp;
2134                 qry->isPortal = TRUE;
2135                 qry->isBinary = binary; /* internal portal */
2136         }
2137         else
2138         {
2139                 /* SELECT */
2140                 qry->into = into;
2141                 qry->isTemp = istemp;
2142                 qry->isPortal = FALSE;
2143                 qry->isBinary = FALSE;
2144         }
2145
2146         /*
2147          * As a first step towards supporting sort clauses that are
2148          * expressions using the output columns, generate a namespace entry
2149          * that makes the output columns visible.  A JoinExpr node is handy
2150          * for this, since we can easily control the Vars generated upon
2151          * matches.
2152          *
2153          * Note: we don't yet do anything useful with such cases, but at least
2154          * "ORDER BY upper(foo)" will draw the right error message rather than
2155          * "foo not found".
2156          */
2157         jnode = makeNode(JoinExpr);
2158         jnode->colnames = targetnames;
2159         jnode->colvars = targetvars;
2160
2161         sv_namespace = pstate->p_namespace;
2162         pstate->p_namespace = makeList1(jnode);
2163
2164         /*
2165          * For now, we don't support resjunk sort clauses on the output of a
2166          * setOperation tree --- you can only use the SQL92-spec options of
2167          * selecting an output column by name or number.  Enforce by checking
2168          * that transformSortClause doesn't add any items to tlist.
2169          */
2170         tllen = length(qry->targetList);
2171
2172         qry->sortClause = transformSortClause(pstate,
2173                                                                                   sortClause,
2174                                                                                   qry->targetList);
2175
2176         pstate->p_namespace = sv_namespace;
2177
2178         if (tllen != length(qry->targetList))
2179                 elog(ERROR, "ORDER BY on a UNION/INTERSECT/EXCEPT result must be on one of the result columns");
2180
2181         qry->limitOffset = limitOffset;
2182         qry->limitCount = limitCount;
2183
2184         qry->hasSubLinks = pstate->p_hasSubLinks;
2185         qry->hasAggs = pstate->p_hasAggs;
2186         if (pstate->p_hasAggs || qry->groupClause || qry->havingQual)
2187                 parseCheckAggregates(pstate, qry, NULL);
2188
2189         qry->rtable = pstate->p_rtable;
2190         qry->jointree = makeFromExpr(pstate->p_joinlist, NULL);
2191
2192         if (forUpdate != NIL)
2193                 transformForUpdate(qry, forUpdate);
2194
2195         return qry;
2196 }
2197
2198 /*
2199  * transformSetOperationTree
2200  *              Recursively transform leaves and internal nodes of a set-op tree
2201  */
2202 static Node *
2203 transformSetOperationTree(ParseState *pstate, SelectStmt *stmt)
2204 {
2205         bool            isLeaf;
2206
2207         Assert(stmt && IsA(stmt, SelectStmt));
2208
2209         /*
2210          * Validity-check both leaf and internal SELECTs for disallowed ops.
2211          */
2212         if (stmt->into)
2213                 elog(ERROR, "INTO is only allowed on first SELECT of UNION/INTERSECT/EXCEPT");
2214         if (stmt->portalname)           /* should not happen */
2215                 elog(ERROR, "Portal may not appear in UNION/INTERSECT/EXCEPT");
2216         /* We don't support forUpdate with set ops at the moment. */
2217         if (stmt->forUpdate)
2218                 elog(ERROR, "SELECT FOR UPDATE is not allowed with UNION/INTERSECT/EXCEPT");
2219
2220         /*
2221          * If an internal node of a set-op tree has ORDER BY, UPDATE, or LIMIT
2222          * clauses attached, we need to treat it like a leaf node to generate
2223          * an independent sub-Query tree.  Otherwise, it can be represented by
2224          * a SetOperationStmt node underneath the parent Query.
2225          */
2226         if (stmt->op == SETOP_NONE)
2227         {
2228                 Assert(stmt->larg == NULL && stmt->rarg == NULL);
2229                 isLeaf = true;
2230         }
2231         else
2232         {
2233                 Assert(stmt->larg != NULL && stmt->rarg != NULL);
2234                 if (stmt->sortClause || stmt->limitOffset || stmt->limitCount ||
2235                         stmt->forUpdate)
2236                         isLeaf = true;
2237                 else
2238                         isLeaf = false;
2239         }
2240
2241         if (isLeaf)
2242         {
2243                 /* Process leaf SELECT */
2244                 List       *selectList;
2245                 Query      *selectQuery;
2246                 char            selectName[32];
2247                 RangeTblEntry *rte;
2248                 RangeTblRef *rtr;
2249
2250                 /*
2251                  * Transform SelectStmt into a Query.
2252                  *
2253                  * Note: previously transformed sub-queries don't affect the parsing
2254                  * of this sub-query, because they are not in the toplevel
2255                  * pstate's namespace list.
2256                  */
2257                 selectList = parse_analyze((Node *) stmt, pstate);
2258
2259                 Assert(length(selectList) == 1);
2260                 selectQuery = (Query *) lfirst(selectList);
2261
2262                 /*
2263                  * Make the leaf query be a subquery in the top-level rangetable.
2264                  */
2265                 sprintf(selectName, "*SELECT* %d", length(pstate->p_rtable) + 1);
2266                 rte = addRangeTableEntryForSubquery(pstate,
2267                                                                                         selectQuery,
2268                                                                                         makeAttr(pstrdup(selectName),
2269                                                                                                          NULL),
2270                                                                                         false);
2271
2272                 /*
2273                  * Return a RangeTblRef to replace the SelectStmt in the set-op
2274                  * tree.
2275                  */
2276                 rtr = makeNode(RangeTblRef);
2277                 /* assume new rte is at end */
2278                 rtr->rtindex = length(pstate->p_rtable);
2279                 Assert(rte == rt_fetch(rtr->rtindex, pstate->p_rtable));
2280                 return (Node *) rtr;
2281         }
2282         else
2283         {
2284                 /* Process an internal node (set operation node) */
2285                 SetOperationStmt *op = makeNode(SetOperationStmt);
2286                 List       *lcoltypes;
2287                 List       *rcoltypes;
2288                 const char *context;
2289
2290                 context = (stmt->op == SETOP_UNION ? "UNION" :
2291                                    (stmt->op == SETOP_INTERSECT ? "INTERSECT" :
2292                                         "EXCEPT"));
2293
2294                 op->op = stmt->op;
2295                 op->all = stmt->all;
2296
2297                 /*
2298                  * Recursively transform the child nodes.
2299                  */
2300                 op->larg = transformSetOperationTree(pstate, stmt->larg);
2301                 op->rarg = transformSetOperationTree(pstate, stmt->rarg);
2302
2303                 /*
2304                  * Verify that the two children have the same number of non-junk
2305                  * columns, and determine the types of the merged output columns.
2306                  */
2307                 lcoltypes = getSetColTypes(pstate, op->larg);
2308                 rcoltypes = getSetColTypes(pstate, op->rarg);
2309                 if (length(lcoltypes) != length(rcoltypes))
2310                         elog(ERROR, "Each %s query must have the same number of columns",
2311                                  context);
2312                 op->colTypes = NIL;
2313                 while (lcoltypes != NIL)
2314                 {
2315                         Oid                     lcoltype = (Oid) lfirsti(lcoltypes);
2316                         Oid                     rcoltype = (Oid) lfirsti(rcoltypes);
2317                         Oid                     rescoltype;
2318
2319                         rescoltype = select_common_type(makeListi2(lcoltype, rcoltype),
2320                                                                                         context);
2321                         op->colTypes = lappendi(op->colTypes, rescoltype);
2322                         lcoltypes = lnext(lcoltypes);
2323                         rcoltypes = lnext(rcoltypes);
2324                 }
2325
2326                 return (Node *) op;
2327         }
2328 }
2329
2330 /*
2331  * getSetColTypes
2332  *              Get output column types of an (already transformed) set-op node
2333  */
2334 static List *
2335 getSetColTypes(ParseState *pstate, Node *node)
2336 {
2337         if (IsA(node, RangeTblRef))
2338         {
2339                 RangeTblRef *rtr = (RangeTblRef *) node;
2340                 RangeTblEntry *rte = rt_fetch(rtr->rtindex, pstate->p_rtable);
2341                 Query      *selectQuery = rte->subquery;
2342                 List       *result = NIL;
2343                 List       *tl;
2344
2345                 Assert(selectQuery != NULL);
2346                 /* Get types of non-junk columns */
2347                 foreach(tl, selectQuery->targetList)
2348                 {
2349                         TargetEntry *tle = (TargetEntry *) lfirst(tl);
2350                         Resdom     *resnode = tle->resdom;
2351
2352                         if (resnode->resjunk)
2353                                 continue;
2354                         result = lappendi(result, resnode->restype);
2355                 }
2356                 return result;
2357         }
2358         else if (IsA(node, SetOperationStmt))
2359         {
2360                 SetOperationStmt *op = (SetOperationStmt *) node;
2361
2362                 /* Result already computed during transformation of node */
2363                 Assert(op->colTypes != NIL);
2364                 return op->colTypes;
2365         }
2366         else
2367         {
2368                 elog(ERROR, "getSetColTypes: unexpected node %d",
2369                          (int) nodeTag(node));
2370                 return NIL;                             /* keep compiler quiet */
2371         }
2372 }
2373
2374
2375 /*
2376  * transformUpdateStmt -
2377  *        transforms an update statement
2378  *
2379  */
2380 static Query *
2381 transformUpdateStmt(ParseState *pstate, UpdateStmt *stmt)
2382 {
2383         Query      *qry = makeNode(Query);
2384         Node       *qual;
2385         List       *origTargetList;
2386         List       *tl;
2387
2388         qry->commandType = CMD_UPDATE;
2389         pstate->p_is_update = true;
2390
2391         qry->resultRelation = setTargetTable(pstate, stmt->relname,
2392                                                                                  interpretInhOption(stmt->inhOpt),
2393                                                                                  true);
2394
2395         /*
2396          * the FROM clause is non-standard SQL syntax. We used to be able to
2397          * do this with REPLACE in POSTQUEL so we keep the feature.
2398          */
2399         transformFromClause(pstate, stmt->fromClause);
2400
2401         qry->targetList = transformTargetList(pstate, stmt->targetList);
2402
2403         qual = transformWhereClause(pstate, stmt->whereClause);
2404
2405         qry->rtable = pstate->p_rtable;
2406         qry->jointree = makeFromExpr(pstate->p_joinlist, qual);
2407
2408         qry->hasSubLinks = pstate->p_hasSubLinks;
2409         qry->hasAggs = pstate->p_hasAggs;
2410         if (pstate->p_hasAggs)
2411                 parseCheckAggregates(pstate, qry, qual);
2412
2413         /*
2414          * Now we are done with SELECT-like processing, and can get on with
2415          * transforming the target list to match the UPDATE target columns.
2416          */
2417
2418         /* Prepare to assign non-conflicting resnos to resjunk attributes */
2419         if (pstate->p_last_resno <= pstate->p_target_relation->rd_rel->relnatts)
2420                 pstate->p_last_resno = pstate->p_target_relation->rd_rel->relnatts + 1;
2421
2422         /* Prepare non-junk columns for assignment to target table */
2423         origTargetList = stmt->targetList;
2424         foreach(tl, qry->targetList)
2425         {
2426                 TargetEntry *tle = (TargetEntry *) lfirst(tl);
2427                 Resdom     *resnode = tle->resdom;
2428                 ResTarget  *origTarget;
2429
2430                 if (resnode->resjunk)
2431                 {
2432
2433                         /*
2434                          * Resjunk nodes need no additional processing, but be sure
2435                          * they have names and resnos that do not match any target
2436                          * columns; else rewriter or planner might get confused.
2437                          */
2438                         resnode->resname = "?resjunk?";
2439                         resnode->resno = (AttrNumber) pstate->p_last_resno++;
2440                         continue;
2441                 }
2442                 if (origTargetList == NIL)
2443                         elog(ERROR, "UPDATE target count mismatch --- internal error");
2444                 origTarget = (ResTarget *) lfirst(origTargetList);
2445                 updateTargetListEntry(pstate, tle, origTarget->name,
2446                                                           attnameAttNum(pstate->p_target_relation,
2447                                                                                         origTarget->name),
2448                                                           origTarget->indirection);
2449                 origTargetList = lnext(origTargetList);
2450         }
2451         if (origTargetList != NIL)
2452                 elog(ERROR, "UPDATE target count mismatch --- internal error");
2453
2454         return qry;
2455 }
2456
2457 /*
2458  * tranformAlterTableStmt -
2459  *      transform an Alter Table Statement
2460  *
2461  */
2462 static Query *
2463 transformAlterTableStmt(ParseState *pstate, AlterTableStmt *stmt)
2464 {
2465         Query      *qry;
2466
2467         qry = makeNode(Query);
2468         qry->commandType = CMD_UTILITY;
2469
2470         /*
2471          * The only subtypes that currently have special handling are 'A'dd
2472          * column and Add 'C'onstraint.  In addition, right now only Foreign
2473          * Key 'C'onstraints have a special transformation.
2474          *
2475          */
2476         switch (stmt->subtype)
2477         {
2478                 case 'A':
2479                         transformColumnType(pstate, (ColumnDef *) stmt->def);
2480                         break;
2481                 case 'C':
2482                         if (stmt->def && IsA(stmt->def, FkConstraint))
2483                         {
2484                                 CreateTrigStmt *fk_trigger;
2485                                 List       *fk_attr;
2486                                 List       *pk_attr;
2487                                 Ident      *id;
2488                                 FkConstraint *fkconstraint;
2489
2490                                 extras_after = NIL;
2491                                 elog(NOTICE, "ALTER TABLE ... ADD CONSTRAINT will create implicit trigger(s) for FOREIGN KEY check(s)");
2492
2493                                 fkconstraint = (FkConstraint *) stmt->def;
2494
2495                                 /*
2496                                  * If the constraint has no name, set it to <unnamed>
2497                                  *
2498                                  */
2499                                 if (fkconstraint->constr_name == NULL)
2500                                         fkconstraint->constr_name = "<unnamed>";
2501
2502                                 /*
2503                                  * If the attribute list for the referenced table was
2504                                  * omitted, lookup for the definition of the primary key
2505                                  *
2506                                  */
2507                                 if (fkconstraint->fk_attrs != NIL && fkconstraint->pk_attrs == NIL) {
2508                                         Oid pktypoid[INDEX_MAX_KEYS];
2509                                         transformFkeyGetPrimaryKey(fkconstraint, pktypoid);
2510                                 }
2511
2512                                 /*
2513                                  * Build a CREATE CONSTRAINT TRIGGER statement for the
2514                                  * CHECK action.
2515                                  *
2516                                  */
2517                                 fk_trigger = (CreateTrigStmt *) makeNode(CreateTrigStmt);
2518                                 fk_trigger->trigname = fkconstraint->constr_name;
2519                                 fk_trigger->relname = stmt->relname;
2520                                 fk_trigger->funcname = "RI_FKey_check_ins";
2521                                 fk_trigger->before = false;
2522                                 fk_trigger->row = true;
2523                                 fk_trigger->actions[0] = 'i';
2524                                 fk_trigger->actions[1] = 'u';
2525                                 fk_trigger->actions[2] = '\0';
2526                                 fk_trigger->lang = NULL;
2527                                 fk_trigger->text = NULL;
2528
2529                                 fk_trigger->attr = NIL;
2530                                 fk_trigger->when = NULL;
2531                                 fk_trigger->isconstraint = true;
2532                                 fk_trigger->deferrable = fkconstraint->deferrable;
2533                                 fk_trigger->initdeferred = fkconstraint->initdeferred;
2534                                 fk_trigger->constrrelname = fkconstraint->pktable_name;
2535
2536                                 fk_trigger->args = NIL;
2537                                 fk_trigger->args = lappend(fk_trigger->args,
2538                                                                   makeString(fkconstraint->constr_name));
2539                                 fk_trigger->args = lappend(fk_trigger->args,
2540                                                                                    makeString(stmt->relname));
2541                                 fk_trigger->args = lappend(fk_trigger->args,
2542                                                                  makeString(fkconstraint->pktable_name));
2543                                 fk_trigger->args = lappend(fk_trigger->args,
2544                                                                    makeString(fkconstraint->match_type));
2545                                 fk_attr = fkconstraint->fk_attrs;
2546                                 pk_attr = fkconstraint->pk_attrs;
2547                                 if (length(fk_attr) != length(pk_attr))
2548                                 {
2549                                         elog(NOTICE, "Illegal FOREIGN KEY definition REFERENCES \"%s\"",
2550                                                  fkconstraint->pktable_name);
2551                                         elog(ERROR, "number of key attributes in referenced table must be equal to foreign key");
2552                                 }
2553                                 while (fk_attr != NIL)
2554                                 {
2555                                         id = (Ident *) lfirst(fk_attr);
2556                                         fk_trigger->args = lappend(fk_trigger->args,
2557                                                                                            makeString(id->name));
2558
2559                                         id = (Ident *) lfirst(pk_attr);
2560                                         fk_trigger->args = lappend(fk_trigger->args,
2561                                                                                            makeString(id->name));
2562
2563                                         fk_attr = lnext(fk_attr);
2564                                         pk_attr = lnext(pk_attr);
2565                                 }
2566
2567                                 extras_after = lappend(extras_after, (Node *) fk_trigger);
2568
2569                                 /*
2570                                  * Build a CREATE CONSTRAINT TRIGGER statement for the ON
2571                                  * DELETE action fired on the PK table !!!
2572                                  *
2573                                  */
2574                                 fk_trigger = (CreateTrigStmt *) makeNode(CreateTrigStmt);
2575                                 fk_trigger->trigname = fkconstraint->constr_name;
2576                                 fk_trigger->relname = fkconstraint->pktable_name;
2577                                 switch ((fkconstraint->actions & FKCONSTR_ON_DELETE_MASK)
2578                                                 >> FKCONSTR_ON_DELETE_SHIFT)
2579                                 {
2580                                         case FKCONSTR_ON_KEY_NOACTION:
2581                                                 fk_trigger->funcname = "RI_FKey_noaction_del";
2582                                                 break;
2583                                         case FKCONSTR_ON_KEY_RESTRICT:
2584                                                 fk_trigger->funcname = "RI_FKey_restrict_del";
2585                                                 break;
2586                                         case FKCONSTR_ON_KEY_CASCADE:
2587                                                 fk_trigger->funcname = "RI_FKey_cascade_del";
2588                                                 break;
2589                                         case FKCONSTR_ON_KEY_SETNULL:
2590                                                 fk_trigger->funcname = "RI_FKey_setnull_del";
2591                                                 break;
2592                                         case FKCONSTR_ON_KEY_SETDEFAULT:
2593                                                 fk_trigger->funcname = "RI_FKey_setdefault_del";
2594                                                 break;
2595                                         default:
2596                                                 elog(ERROR, "Only one ON DELETE action can be specified for FOREIGN KEY constraint");
2597                                                 break;
2598                                 }
2599                                 fk_trigger->before = false;
2600                                 fk_trigger->row = true;
2601                                 fk_trigger->actions[0] = 'd';
2602                                 fk_trigger->actions[1] = '\0';
2603                                 fk_trigger->lang = NULL;
2604                                 fk_trigger->text = NULL;
2605
2606                                 fk_trigger->attr = NIL;
2607                                 fk_trigger->when = NULL;
2608                                 fk_trigger->isconstraint = true;
2609                                 fk_trigger->deferrable = fkconstraint->deferrable;
2610                                 fk_trigger->initdeferred = fkconstraint->initdeferred;
2611                                 fk_trigger->constrrelname = stmt->relname;
2612
2613                                 fk_trigger->args = NIL;
2614                                 fk_trigger->args = lappend(fk_trigger->args,
2615                                                                   makeString(fkconstraint->constr_name));
2616                                 fk_trigger->args = lappend(fk_trigger->args,
2617                                                                                    makeString(stmt->relname));
2618                                 fk_trigger->args = lappend(fk_trigger->args,
2619                                                                  makeString(fkconstraint->pktable_name));
2620                                 fk_trigger->args = lappend(fk_trigger->args,
2621                                                                    makeString(fkconstraint->match_type));
2622                                 fk_attr = fkconstraint->fk_attrs;
2623                                 pk_attr = fkconstraint->pk_attrs;
2624                                 while (fk_attr != NIL)
2625                                 {
2626                                         id = (Ident *) lfirst(fk_attr);
2627                                         fk_trigger->args = lappend(fk_trigger->args,
2628                                                                                            makeString(id->name));
2629
2630                                         id = (Ident *) lfirst(pk_attr);
2631                                         fk_trigger->args = lappend(fk_trigger->args,
2632                                                                                            makeString(id->name));
2633
2634                                         fk_attr = lnext(fk_attr);
2635                                         pk_attr = lnext(pk_attr);
2636                                 }
2637
2638                                 extras_after = lappend(extras_after, (Node *) fk_trigger);
2639
2640                                 /*
2641                                  * Build a CREATE CONSTRAINT TRIGGER statement for the ON
2642                                  * UPDATE action fired on the PK table !!!
2643                                  *
2644                                  */
2645                                 fk_trigger = (CreateTrigStmt *) makeNode(CreateTrigStmt);
2646                                 fk_trigger->trigname = fkconstraint->constr_name;
2647                                 fk_trigger->relname = fkconstraint->pktable_name;
2648                                 switch ((fkconstraint->actions & FKCONSTR_ON_UPDATE_MASK)
2649                                                 >> FKCONSTR_ON_UPDATE_SHIFT)
2650                                 {
2651                                         case FKCONSTR_ON_KEY_NOACTION:
2652                                                 fk_trigger->funcname = "RI_FKey_noaction_upd";
2653                                                 break;
2654                                         case FKCONSTR_ON_KEY_RESTRICT:
2655                                                 fk_trigger->funcname = "RI_FKey_restrict_upd";
2656                                                 break;
2657                                         case FKCONSTR_ON_KEY_CASCADE:
2658                                                 fk_trigger->funcname = "RI_FKey_cascade_upd";
2659                                                 break;
2660                                         case FKCONSTR_ON_KEY_SETNULL:
2661                                                 fk_trigger->funcname = "RI_FKey_setnull_upd";
2662                                                 break;
2663                                         case FKCONSTR_ON_KEY_SETDEFAULT:
2664                                                 fk_trigger->funcname = "RI_FKey_setdefault_upd";
2665                                                 break;
2666                                         default:
2667                                                 elog(ERROR, "Only one ON UPDATE action can be specified for FOREIGN KEY constraint");
2668                                                 break;
2669                                 }
2670                                 fk_trigger->before = false;
2671                                 fk_trigger->row = true;
2672                                 fk_trigger->actions[0] = 'u';
2673                                 fk_trigger->actions[1] = '\0';
2674                                 fk_trigger->lang = NULL;
2675                                 fk_trigger->text = NULL;
2676
2677                                 fk_trigger->attr = NIL;
2678                                 fk_trigger->when = NULL;
2679                                 fk_trigger->isconstraint = true;
2680                                 fk_trigger->deferrable = fkconstraint->deferrable;
2681                                 fk_trigger->initdeferred = fkconstraint->initdeferred;
2682                                 fk_trigger->constrrelname = stmt->relname;
2683
2684                                 fk_trigger->args = NIL;
2685                                 fk_trigger->args = lappend(fk_trigger->args,
2686                                                                   makeString(fkconstraint->constr_name));
2687                                 fk_trigger->args = lappend(fk_trigger->args,
2688                                                                                    makeString(stmt->relname));
2689                                 fk_trigger->args = lappend(fk_trigger->args,
2690                                                                  makeString(fkconstraint->pktable_name));
2691                                 fk_trigger->args = lappend(fk_trigger->args,
2692                                                                    makeString(fkconstraint->match_type));
2693                                 fk_attr = fkconstraint->fk_attrs;
2694                                 pk_attr = fkconstraint->pk_attrs;
2695                                 while (fk_attr != NIL)
2696                                 {
2697                                         id = (Ident *) lfirst(fk_attr);
2698                                         fk_trigger->args = lappend(fk_trigger->args,
2699                                                                                            makeString(id->name));
2700
2701                                         id = (Ident *) lfirst(pk_attr);
2702                                         fk_trigger->args = lappend(fk_trigger->args,
2703                                                                                            makeString(id->name));
2704
2705                                         fk_attr = lnext(fk_attr);
2706                                         pk_attr = lnext(pk_attr);
2707                                 }
2708
2709                                 extras_after = lappend(extras_after, (Node *) fk_trigger);
2710                         }
2711                         break;
2712                 default:
2713                         break;
2714         }
2715         qry->utilityStmt = (Node *) stmt;
2716         return qry;
2717 }
2718
2719 /* 
2720  * Transform uses of %TYPE in a statement.
2721  */
2722 static Node *
2723 transformTypeRefs(ParseState *pstate, Node *stmt)
2724 {
2725         switch (nodeTag(stmt))
2726         {
2727                 case T_ProcedureStmt:
2728                 {
2729                         ProcedureStmt  *ps = (ProcedureStmt *) stmt;
2730
2731                         transformTypeRefsList(pstate, ps->argTypes);
2732                         transformTypeRef(pstate, (TypeName *) ps->returnType);
2733                         transformTypeRefsList(pstate, ps->withClause);
2734                 }
2735                 break;
2736
2737                 case T_CommentStmt:
2738                 {
2739                         CommentStmt        *cs = (CommentStmt *) stmt;
2740
2741                         transformTypeRefsList(pstate, cs->objlist);
2742                 }
2743                 break;
2744
2745                 case T_RemoveFuncStmt:
2746                 {
2747                         RemoveFuncStmt *rs = (RemoveFuncStmt *) stmt;
2748
2749                         transformTypeRefsList(pstate, rs->args);
2750                 }
2751                 break;
2752
2753                 case T_DefineStmt:
2754                 {
2755                         DefineStmt *ds = (DefineStmt *) stmt;
2756                         List       *ele;
2757
2758                         foreach(ele, ds->definition)
2759                         {
2760                                 DefElem    *de = (DefElem *) lfirst(ele);
2761
2762                                 if (de->arg != NULL
2763                                         && IsA(de->arg, TypeName))
2764                                 {
2765                                         transformTypeRef(pstate, (TypeName *) de->arg);
2766                                 }
2767                         }
2768                 }
2769                 break;
2770
2771                 default:
2772                         elog(ERROR, "Unsupported type %d in transformTypeRefs",
2773                                  nodeTag(stmt));
2774                         break;
2775         }
2776
2777         return stmt;
2778 }
2779
2780 /*
2781  * Transform uses of %TYPE in a list.
2782  */
2783 static void
2784 transformTypeRefsList(ParseState *pstate, List *l)
2785 {
2786         List       *ele;
2787
2788         foreach(ele, l)
2789         {
2790                 if (IsA(lfirst(ele), TypeName))
2791                         transformTypeRef(pstate, (TypeName *) lfirst(ele));
2792         }
2793 }
2794
2795 /*
2796  * Transform a TypeName to not use %TYPE.
2797  */
2798 static void
2799 transformTypeRef(ParseState *pstate, TypeName *tn)
2800 {
2801         Attr   *att;
2802         Node   *n;
2803         Var        *v;
2804         char   *tyn;
2805
2806         if (tn->attrname == NULL)
2807                 return;
2808         att = makeAttr(tn->name, tn->attrname);
2809         n = transformExpr(pstate, (Node *) att, EXPR_COLUMN_FIRST);
2810         if (! IsA(n, Var))
2811                 elog(ERROR, "unsupported expression in %%TYPE");
2812         v = (Var *) n;
2813         tyn = typeidTypeName(v->vartype);
2814         elog(NOTICE, "%s.%s%%TYPE converted to %s", tn->name, tn->attrname, tyn);
2815         tn->name = tyn;
2816         tn->typmod = v->vartypmod;
2817         tn->attrname = NULL;
2818 }
2819
2820 /* exported so planner can check again after rewriting, query pullup, etc */
2821 void
2822 CheckSelectForUpdate(Query *qry)
2823 {
2824         if (qry->setOperations)
2825                 elog(ERROR, "SELECT FOR UPDATE is not allowed with UNION/INTERSECT/EXCEPT");
2826         if (qry->distinctClause != NIL)
2827                 elog(ERROR, "SELECT FOR UPDATE is not allowed with DISTINCT clause");
2828         if (qry->groupClause != NIL)
2829                 elog(ERROR, "SELECT FOR UPDATE is not allowed with GROUP BY clause");
2830         if (qry->hasAggs)
2831                 elog(ERROR, "SELECT FOR UPDATE is not allowed with AGGREGATE");
2832 }
2833
2834 static void
2835 transformForUpdate(Query *qry, List *forUpdate)
2836 {
2837         List       *rowMarks = qry->rowMarks;
2838         List       *l;
2839         List       *rt;
2840         Index           i;
2841
2842         CheckSelectForUpdate(qry);
2843
2844         if (lfirst(forUpdate) == NULL)
2845         {
2846                 /* all tables used in query */
2847                 i = 0;
2848                 foreach(rt, qry->rtable)
2849                 {
2850                         RangeTblEntry *rte = (RangeTblEntry *) lfirst(rt);
2851
2852                         ++i;
2853                         if (rte->subquery)
2854                         {
2855                                 /* FOR UPDATE of subquery is propagated to subquery's rels */
2856                                 transformForUpdate(rte->subquery, makeList1(NULL));
2857                         }
2858                         else
2859                         {
2860                                 if (!intMember(i, rowMarks))    /* avoid duplicates */
2861                                         rowMarks = lappendi(rowMarks, i);
2862                                 rte->checkForWrite = true;
2863                         }
2864                 }
2865         }
2866         else
2867         {
2868                 /* just the named tables */
2869                 foreach(l, forUpdate)
2870                 {
2871                         char       *relname = strVal(lfirst(l));
2872
2873                         i = 0;
2874                         foreach(rt, qry->rtable)
2875                         {
2876                                 RangeTblEntry *rte = (RangeTblEntry *) lfirst(rt);
2877
2878                                 ++i;
2879                                 if (strcmp(rte->eref->relname, relname) == 0)
2880                                 {
2881                                         if (rte->subquery)
2882                                         {
2883                                                 /* propagate to subquery */
2884                                                 transformForUpdate(rte->subquery, makeList1(NULL));
2885                                         }
2886                                         else
2887                                         {
2888                                                 if (!intMember(i, rowMarks))    /* avoid duplicates */
2889                                                         rowMarks = lappendi(rowMarks, i);
2890                                                 rte->checkForWrite = true;
2891                                         }
2892                                         break;
2893                                 }
2894                         }
2895                         if (rt == NIL)
2896                                 elog(ERROR, "FOR UPDATE: relation \"%s\" not found in FROM clause",
2897                                          relname);
2898                 }
2899         }
2900
2901         qry->rowMarks = rowMarks;
2902 }
2903
2904
2905 /*
2906  * transformFkeyCheckAttrs -
2907  *
2908  *      Try to make sure that the attributes of a referenced table
2909  *              belong to a unique (or primary key) constraint.
2910  *
2911  */
2912 static void
2913 transformFkeyCheckAttrs(FkConstraint *fkconstraint, Oid *pktypoid)
2914 {
2915         Relation        pkrel;
2916         Form_pg_attribute *pkrel_attrs;
2917         List       *indexoidlist,
2918                            *indexoidscan;
2919         int                     i;
2920         bool            found = false;
2921
2922         /*
2923          * Open the referenced table and get the attributes list
2924          */
2925         pkrel = heap_openr(fkconstraint->pktable_name, AccessShareLock);
2926         if (pkrel == NULL)
2927                 elog(ERROR, "referenced table \"%s\" not found",
2928                          fkconstraint->pktable_name);
2929         pkrel_attrs = pkrel->rd_att->attrs;
2930
2931         /*
2932          * Get the list of index OIDs for the table from the relcache, and
2933          * look up each one in the pg_index syscache for each unique one, and
2934          * then compare the attributes we were given to those defined.
2935          */
2936         indexoidlist = RelationGetIndexList(pkrel);
2937
2938         foreach(indexoidscan, indexoidlist)
2939         {
2940                 Oid                     indexoid = lfirsti(indexoidscan);
2941                 HeapTuple       indexTuple;
2942                 Form_pg_index indexStruct;
2943
2944                 indexTuple = SearchSysCache(INDEXRELID,
2945                                                                         ObjectIdGetDatum(indexoid),
2946                                                                         0, 0, 0);
2947                 if (!HeapTupleIsValid(indexTuple))
2948                         elog(ERROR, "transformFkeyGetPrimaryKey: index %u not found",
2949                                  indexoid);
2950                 indexStruct = (Form_pg_index) GETSTRUCT(indexTuple);
2951
2952                 if (indexStruct->indisunique)
2953                 {
2954                         List       *attrl;
2955                         int        attnum=0;
2956
2957                         for (i = 0; i < INDEX_MAX_KEYS && indexStruct->indkey[i] != 0; i++);
2958                         if (i != length(fkconstraint->pk_attrs))
2959                                 found = false;
2960                         else
2961                         {
2962                                 /* go through the fkconstraint->pk_attrs list */
2963                                 foreach(attrl, fkconstraint->pk_attrs)
2964                                 {
2965                                         Ident      *attr = lfirst(attrl);
2966
2967                                         found = false;
2968                                         for (i = 0; i < INDEX_MAX_KEYS && indexStruct->indkey[i] != 0; i++)
2969                                         {
2970                                                 int                     pkattno = indexStruct->indkey[i];
2971
2972                                                 if (pkattno > 0)
2973                                                 {
2974                                                         char       *name = NameStr(pkrel_attrs[pkattno - 1]->attname);
2975
2976                                                         if (strcmp(name, attr->name) == 0)
2977                                                         {
2978                                                                 pktypoid[attnum++]=pkrel_attrs[pkattno-1]->atttypid;
2979                                                                 found = true;
2980                                                                 break;
2981                                                         }
2982                                                 }
2983                                         }
2984                                         if (!found)
2985                                                 break;
2986                                 }
2987                         }
2988                 }
2989                 ReleaseSysCache(indexTuple);
2990                 if (found)
2991                         break;
2992         }
2993         if (!found)
2994                 elog(ERROR, "UNIQUE constraint matching given keys for referenced table \"%s\" not found",
2995                          fkconstraint->pktable_name);
2996
2997         freeList(indexoidlist);
2998         heap_close(pkrel, AccessShareLock);
2999 }
3000
3001
3002 /*
3003  * transformFkeyGetPrimaryKey -
3004  *
3005  *      Try to find the primary key attributes of a referenced table if
3006  *      the column list in the REFERENCES specification was omitted.
3007  *
3008  */
3009 static void
3010 transformFkeyGetPrimaryKey(FkConstraint *fkconstraint, Oid *pktypoid)
3011 {
3012         Relation        pkrel;
3013         Form_pg_attribute *pkrel_attrs;
3014         List       *indexoidlist,
3015                            *indexoidscan;
3016         HeapTuple       indexTuple = NULL;
3017         Form_pg_index indexStruct = NULL;
3018         int                     i;
3019         int             attnum=0;
3020
3021         /*
3022          * Open the referenced table and get the attributes list
3023          */
3024         pkrel = heap_openr(fkconstraint->pktable_name, AccessShareLock);
3025         if (pkrel == NULL)
3026                 elog(ERROR, "referenced table \"%s\" not found",
3027                          fkconstraint->pktable_name);
3028         pkrel_attrs = pkrel->rd_att->attrs;
3029
3030         /*
3031          * Get the list of index OIDs for the table from the relcache, and
3032          * look up each one in the pg_index syscache until we find one marked
3033          * primary key (hopefully there isn't more than one such).
3034          */
3035         indexoidlist = RelationGetIndexList(pkrel);
3036
3037         foreach(indexoidscan, indexoidlist)
3038         {
3039                 Oid                     indexoid = lfirsti(indexoidscan);
3040
3041                 indexTuple = SearchSysCache(INDEXRELID,
3042                                                                         ObjectIdGetDatum(indexoid),
3043                                                                         0, 0, 0);
3044                 if (!HeapTupleIsValid(indexTuple))
3045                         elog(ERROR, "transformFkeyGetPrimaryKey: index %u not found",
3046                                  indexoid);
3047                 indexStruct = (Form_pg_index) GETSTRUCT(indexTuple);
3048                 if (indexStruct->indisprimary)
3049                         break;
3050                 ReleaseSysCache(indexTuple);
3051                 indexStruct = NULL;
3052         }
3053
3054         freeList(indexoidlist);
3055
3056         /*
3057          * Check that we found it
3058          */
3059         if (indexStruct == NULL)
3060                 elog(ERROR, "PRIMARY KEY for referenced table \"%s\" not found",
3061                          fkconstraint->pktable_name);
3062
3063         /*
3064          * Now build the list of PK attributes from the indkey definition
3065          * using the attribute names of the PK relation descriptor
3066          */
3067         for (i = 0; i < INDEX_MAX_KEYS && indexStruct->indkey[i] != 0; i++)
3068         {
3069                 int                     pkattno = indexStruct->indkey[i];
3070                 Ident      *pkattr = makeNode(Ident);
3071
3072                 pkattr->name = DatumGetCString(DirectFunctionCall1(nameout,
3073                                         NameGetDatum(&(pkrel_attrs[pkattno - 1]->attname))));
3074                 pkattr->indirection = NIL;
3075                 pkattr->isRel = false;
3076                 pktypoid[attnum++]=pkrel_attrs[pkattno-1]->atttypid;
3077
3078                 fkconstraint->pk_attrs = lappend(fkconstraint->pk_attrs, pkattr);
3079         }
3080
3081         ReleaseSysCache(indexTuple);
3082
3083         heap_close(pkrel, AccessShareLock);
3084 }
3085
3086 /*
3087  * Preprocess a list of column constraint clauses
3088  * to attach constraint attributes to their primary constraint nodes
3089  * and detect inconsistent/misplaced constraint attributes.
3090  *
3091  * NOTE: currently, attributes are only supported for FOREIGN KEY primary
3092  * constraints, but someday they ought to be supported for other constraints.
3093  */
3094 static void
3095 transformConstraintAttrs(List *constraintList)
3096 {
3097         Node       *lastprimarynode = NULL;
3098         bool            saw_deferrability = false;
3099         bool            saw_initially = false;
3100         List       *clist;
3101
3102         foreach(clist, constraintList)
3103         {
3104                 Node       *node = lfirst(clist);
3105
3106                 if (!IsA(node, Constraint))
3107                 {
3108                         lastprimarynode = node;
3109                         /* reset flags for new primary node */
3110                         saw_deferrability = false;
3111                         saw_initially = false;
3112                 }
3113                 else
3114                 {
3115                         Constraint *con = (Constraint *) node;
3116
3117                         switch (con->contype)
3118                         {
3119                                 case CONSTR_ATTR_DEFERRABLE:
3120                                         if (lastprimarynode == NULL ||
3121                                                 !IsA(lastprimarynode, FkConstraint))
3122                                                 elog(ERROR, "Misplaced DEFERRABLE clause");
3123                                         if (saw_deferrability)
3124                                                 elog(ERROR, "Multiple DEFERRABLE/NOT DEFERRABLE clauses not allowed");
3125                                         saw_deferrability = true;
3126                                         ((FkConstraint *) lastprimarynode)->deferrable = true;
3127                                         break;
3128                                 case CONSTR_ATTR_NOT_DEFERRABLE:
3129                                         if (lastprimarynode == NULL ||
3130                                                 !IsA(lastprimarynode, FkConstraint))
3131                                                 elog(ERROR, "Misplaced NOT DEFERRABLE clause");
3132                                         if (saw_deferrability)
3133                                                 elog(ERROR, "Multiple DEFERRABLE/NOT DEFERRABLE clauses not allowed");
3134                                         saw_deferrability = true;
3135                                         ((FkConstraint *) lastprimarynode)->deferrable = false;
3136                                         if (saw_initially &&
3137                                                 ((FkConstraint *) lastprimarynode)->initdeferred)
3138                                                 elog(ERROR, "INITIALLY DEFERRED constraint must be DEFERRABLE");
3139                                         break;
3140                                 case CONSTR_ATTR_DEFERRED:
3141                                         if (lastprimarynode == NULL ||
3142                                                 !IsA(lastprimarynode, FkConstraint))
3143                                                 elog(ERROR, "Misplaced INITIALLY DEFERRED clause");
3144                                         if (saw_initially)
3145                                                 elog(ERROR, "Multiple INITIALLY IMMEDIATE/DEFERRED clauses not allowed");
3146                                         saw_initially = true;
3147                                         ((FkConstraint *) lastprimarynode)->initdeferred = true;
3148
3149                                         /*
3150                                          * If only INITIALLY DEFERRED appears, assume
3151                                          * DEFERRABLE
3152                                          */
3153                                         if (!saw_deferrability)
3154                                                 ((FkConstraint *) lastprimarynode)->deferrable = true;
3155                                         else if (!((FkConstraint *) lastprimarynode)->deferrable)
3156                                                 elog(ERROR, "INITIALLY DEFERRED constraint must be DEFERRABLE");
3157                                         break;
3158                                 case CONSTR_ATTR_IMMEDIATE:
3159                                         if (lastprimarynode == NULL ||
3160                                                 !IsA(lastprimarynode, FkConstraint))
3161                                                 elog(ERROR, "Misplaced INITIALLY IMMEDIATE clause");
3162                                         if (saw_initially)
3163                                                 elog(ERROR, "Multiple INITIALLY IMMEDIATE/DEFERRED clauses not allowed");
3164                                         saw_initially = true;
3165                                         ((FkConstraint *) lastprimarynode)->initdeferred = false;
3166                                         break;
3167                                 default:
3168                                         /* Otherwise it's not an attribute */
3169                                         lastprimarynode = node;
3170                                         /* reset flags for new primary node */
3171                                         saw_deferrability = false;
3172                                         saw_initially = false;
3173                                         break;
3174                         }
3175                 }
3176         }
3177 }
3178
3179 /* Build a FromExpr node */
3180 static FromExpr *
3181 makeFromExpr(List *fromlist, Node *quals)
3182 {
3183         FromExpr   *f = makeNode(FromExpr);
3184
3185         f->fromlist = fromlist;
3186         f->quals = quals;
3187         return f;
3188 }
3189
3190 /*
3191  * Special handling of type definition for a column
3192  */
3193 static void
3194 transformColumnType(ParseState *pstate, ColumnDef *column)
3195 {
3196         TypeName   *typename = column->typename;
3197         Type            ctype = typenameType(typename->name);
3198
3199         /*
3200          * If the column doesn't have an explicitly specified typmod, check to
3201          * see if we want to insert a default length.
3202          *
3203          * Note that we deliberately do NOT look at array or set information
3204          * here; "numeric[]" needs the same default typmod as "numeric".
3205          */
3206         if (typename->typmod == -1)
3207         {
3208                 switch (typeTypeId(ctype))
3209                 {
3210                         case BPCHAROID:
3211                                 /* "char" -> "char(1)" */
3212                                 typename->typmod = VARHDRSZ + 1;
3213                                 break;
3214                         case NUMERICOID:
3215                                 typename->typmod = VARHDRSZ +
3216                                         ((NUMERIC_DEFAULT_PRECISION << 16) | NUMERIC_DEFAULT_SCALE);
3217                                 break;
3218                         case BITOID:
3219                                 /* 'bit' -> 'bit(1)' */
3220                                 typename->typmod = 1;
3221                                 break;
3222                 }
3223         }
3224
3225         /*
3226          * Is this the name of a complex type? If so, implement it as a set.
3227          *
3228          * XXX this is a hangover from ancient Berkeley code that probably
3229          * doesn't work anymore anyway.
3230          */
3231         if (typeTypeRelid(ctype) != InvalidOid)
3232         {
3233
3234                 /*
3235                  * (Eventually add in here that the set can only contain one
3236                  * element.)
3237                  */
3238                 typename->setof = true;
3239         }
3240
3241         ReleaseSysCache(ctype);
3242 }