]> granicus.if.org Git - postgresql/blob - src/backend/parser/analyze.c
Inheritance overhaul by Chris Bitmead <chris@bitmead.com>
[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-2000, PostgreSQL, Inc
7  * Portions Copyright (c) 1994, Regents of the University of California
8  *
9  *      $Id: analyze.c,v 1.146 2000/06/09 01:44:18 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/parse_agg.h"
24 #include "parser/parse_clause.h"
25 #include "parser/parse_relation.h"
26 #include "parser/parse_target.h"
27 #include "parser/parse_type.h"
28 #include "utils/builtins.h"
29 #include "utils/fmgroids.h"
30
31 void            CheckSelectForUpdate(Query *qry);       /* no points for style... */
32
33 static Query *transformStmt(ParseState *pstate, Node *stmt);
34 static Query *transformDeleteStmt(ParseState *pstate, DeleteStmt *stmt);
35 static Query *transformInsertStmt(ParseState *pstate, InsertStmt *stmt);
36 static Query *transformIndexStmt(ParseState *pstate, IndexStmt *stmt);
37 static Query *transformExtendStmt(ParseState *pstate, ExtendStmt *stmt);
38 static Query *transformRuleStmt(ParseState *query, RuleStmt *stmt);
39 static Query *transformSelectStmt(ParseState *pstate, SelectStmt *stmt);
40 static Query *transformUpdateStmt(ParseState *pstate, UpdateStmt *stmt);
41 static Query *transformCursorStmt(ParseState *pstate, SelectStmt *stmt);
42 static Query *transformCreateStmt(ParseState *pstate, CreateStmt *stmt);
43 static Query *transformAlterTableStmt(ParseState *pstate, AlterTableStmt *stmt);
44
45 static void transformForUpdate(Query *qry, List *forUpdate);
46 static void transformFkeyGetPrimaryKey(FkConstraint *fkconstraint);
47 static void transformConstraintAttrs(List *constraintList);
48 static void transformColumnType(ParseState *pstate, ColumnDef *column);
49
50 /* kluge to return extra info from transformCreateStmt() */
51 static List *extras_before;
52 static List *extras_after;
53
54
55 /*
56  * parse_analyze -
57  *        analyze a list of parse trees and transform them if necessary.
58  *
59  * Returns a list of transformed parse trees. Optimizable statements are
60  * all transformed to Query while the rest stays the same.
61  *
62  */
63 List *
64 parse_analyze(List *pl, ParseState *parentParseState)
65 {
66         List       *result = NIL;
67         ParseState *pstate;
68         Query      *parsetree;
69
70         while (pl != NIL)
71         {
72                 extras_before = extras_after = NIL;
73                 pstate = make_parsestate(parentParseState);
74
75                 parsetree = transformStmt(pstate, lfirst(pl));
76                 if (pstate->p_target_relation != NULL)
77                         heap_close(pstate->p_target_relation, AccessShareLock);
78                 pstate->p_target_relation = NULL;
79                 pstate->p_target_rangetblentry = NULL;
80
81                 while (extras_before != NIL)
82                 {
83                         result = lappend(result,
84                                                    transformStmt(pstate, lfirst(extras_before)));
85                         if (pstate->p_target_relation != NULL)
86                                 heap_close(pstate->p_target_relation, AccessShareLock);
87                         pstate->p_target_relation = NULL;
88                         pstate->p_target_rangetblentry = NULL;
89                         extras_before = lnext(extras_before);
90                 }
91
92                 result = lappend(result, parsetree);
93
94                 while (extras_after != NIL)
95                 {
96                         result = lappend(result,
97                                                          transformStmt(pstate, lfirst(extras_after)));
98                         if (pstate->p_target_relation != NULL)
99                                 heap_close(pstate->p_target_relation, AccessShareLock);
100                         pstate->p_target_relation = NULL;
101                         pstate->p_target_rangetblentry = NULL;
102                         extras_after = lnext(extras_after);
103                 }
104
105                 pfree(pstate);
106                 pl = lnext(pl);
107         }
108
109         return result;
110 }
111
112 /*
113  * transformStmt -
114  *        transform a Parse tree. If it is an optimizable statement, turn it
115  *        into a Query tree.
116  */
117 static Query *
118 transformStmt(ParseState *pstate, Node *parseTree)
119 {
120         Query      *result = NULL;
121
122         switch (nodeTag(parseTree))
123         {
124                         /*------------------------
125                          *      Non-optimizable statements
126                          *------------------------
127                          */
128                 case T_CreateStmt:
129                         result = transformCreateStmt(pstate, (CreateStmt *) parseTree);
130                         break;
131
132                 case T_IndexStmt:
133                         result = transformIndexStmt(pstate, (IndexStmt *) parseTree);
134                         break;
135
136                 case T_ExtendStmt:
137                         result = transformExtendStmt(pstate, (ExtendStmt *) parseTree);
138                         break;
139
140                 case T_RuleStmt:
141                         result = transformRuleStmt(pstate, (RuleStmt *) parseTree);
142                         break;
143
144                 case T_ViewStmt:
145                         {
146                                 ViewStmt   *n = (ViewStmt *) parseTree;
147
148                                 n->query = (Query *) transformStmt(pstate, (Node *) n->query);
149
150                                 /*
151                                  * If a list of column names was given, run through and
152                                  * insert these into the actual query tree. - thomas
153                                  * 2000-03-08
154                                  */
155                                 if (n->aliases != NIL)
156                                 {
157                                         int                     i;
158                                         List       *targetList = n->query->targetList;
159
160                                         if (length(targetList) < length(n->aliases))
161                                                 elog(ERROR, "CREATE VIEW specifies %d columns"
162                                                          " but only %d columns are present",
163                                                          length(targetList), length(n->aliases));
164
165                                         for (i = 0; i < length(n->aliases); i++)
166                                         {
167                                                 Ident      *id;
168                                                 TargetEntry *te;
169                                                 Resdom     *rd;
170
171                                                 id = nth(i, n->aliases);
172                                                 Assert(nodeTag(id) == T_Ident);
173                                                 te = nth(i, targetList);
174                                                 Assert(nodeTag(te) == T_TargetEntry);
175                                                 rd = te->resdom;
176                                                 Assert(nodeTag(rd) == T_Resdom);
177                                                 rd->resname = pstrdup(id->name);
178                                         }
179                                 }
180                                 result = makeNode(Query);
181                                 result->commandType = CMD_UTILITY;
182                                 result->utilityStmt = (Node *) n;
183                         }
184                         break;
185
186                 case T_VacuumStmt:
187                         {
188                                 MemoryContext oldcontext;
189
190                                 /*
191                                  * make sure that this Query is allocated in TopMemory
192                                  * context because vacuum spans transactions and we don't
193                                  * want to lose the vacuum Query due to end-of-transaction
194                                  * free'ing
195                                  */
196                                 oldcontext = MemoryContextSwitchTo(TopMemoryContext);
197                                 result = makeNode(Query);
198                                 result->commandType = CMD_UTILITY;
199                                 result->utilityStmt = (Node *) parseTree;
200                                 MemoryContextSwitchTo(oldcontext);
201                         }
202                         break;
203
204                 case T_ExplainStmt:
205                         {
206                                 ExplainStmt *n = (ExplainStmt *) parseTree;
207
208                                 result = makeNode(Query);
209                                 result->commandType = CMD_UTILITY;
210                                 n->query = transformStmt(pstate, (Node *) n->query);
211                                 result->utilityStmt = (Node *) parseTree;
212                         }
213                         break;
214
215                 case T_AlterTableStmt:
216                         result = transformAlterTableStmt(pstate, (AlterTableStmt *) parseTree);
217                         break;
218
219                         /*------------------------
220                          *      Optimizable statements
221                          *------------------------
222                          */
223                 case T_InsertStmt:
224                         result = transformInsertStmt(pstate, (InsertStmt *) parseTree);
225                         break;
226
227                 case T_DeleteStmt:
228                         result = transformDeleteStmt(pstate, (DeleteStmt *) parseTree);
229                         break;
230
231                 case T_UpdateStmt:
232                         result = transformUpdateStmt(pstate, (UpdateStmt *) parseTree);
233                         break;
234
235                 case T_SelectStmt:
236                         if (!((SelectStmt *) parseTree)->portalname)
237                         {
238                                 result = transformSelectStmt(pstate, (SelectStmt *) parseTree);
239                                 result->limitOffset = ((SelectStmt *) parseTree)->limitOffset;
240                                 result->limitCount = ((SelectStmt *) parseTree)->limitCount;
241                         }
242                         else
243                                 result = transformCursorStmt(pstate, (SelectStmt *) parseTree);
244                         break;
245
246                 default:
247
248                         /*
249                          * other statments don't require any transformation-- just
250                          * return the original parsetree, yea!
251                          */
252                         result = makeNode(Query);
253                         result->commandType = CMD_UTILITY;
254                         result->utilityStmt = (Node *) parseTree;
255                         break;
256         }
257         return result;
258 }
259
260 /*
261  * transformDeleteStmt -
262  *        transforms a Delete Statement
263  */
264 static Query *
265 transformDeleteStmt(ParseState *pstate, DeleteStmt *stmt)
266 {
267         Query      *qry = makeNode(Query);
268
269         qry->commandType = CMD_DELETE;
270
271         /* set up a range table */
272         makeRangeTable(pstate, NULL);
273         setTargetTable(pstate, stmt->relname, stmt->inh);
274
275         qry->distinctClause = NIL;
276
277         /* fix where clause */
278         qry->qual = transformWhereClause(pstate, stmt->whereClause);
279
280         qry->rtable = pstate->p_rtable;
281         qry->resultRelation = refnameRangeTablePosn(pstate, stmt->relname, NULL);
282
283         qry->hasSubLinks = pstate->p_hasSubLinks;
284         qry->hasAggs = pstate->p_hasAggs;
285         if (pstate->p_hasAggs)
286                 parseCheckAggregates(pstate, qry);
287
288         return (Query *) qry;
289 }
290
291 /*
292  * transformInsertStmt -
293  *        transform an Insert Statement
294  */
295 static Query *
296 transformInsertStmt(ParseState *pstate, InsertStmt *stmt)
297 {
298         Query      *qry = makeNode(Query);
299         List       *icolumns;
300         List       *attrnos;
301         List       *attnos;
302         int                     numuseratts;
303         List       *tl;
304         TupleDesc       rd_att;
305
306         qry->commandType = CMD_INSERT;
307         pstate->p_is_insert = true;
308
309         /*----------
310          * Initial processing steps are just like SELECT, which should not
311          * be surprising, since we may be handling an INSERT ... SELECT.
312          * It is important that we finish processing all the SELECT subclauses
313          * before we start doing any INSERT-specific processing; otherwise
314          * the behavior of SELECT within INSERT might be different from a
315          * stand-alone SELECT.  (Indeed, Postgres up through 6.5 had bugs of
316          * just that nature...)
317          *----------
318          */
319
320         /* set up a range table --- note INSERT target is not in it yet */
321         makeRangeTable(pstate, stmt->fromClause);
322
323         qry->targetList = transformTargetList(pstate, stmt->targetList);
324
325         qry->qual = transformWhereClause(pstate, stmt->whereClause);
326
327         /*
328          * Initial processing of HAVING clause is just like WHERE clause.
329          * Additional work will be done in optimizer/plan/planner.c.
330          */
331         qry->havingQual = transformWhereClause(pstate, stmt->havingClause);
332
333         qry->groupClause = transformGroupClause(pstate,
334                                                                                         stmt->groupClause,
335                                                                                         qry->targetList);
336
337         /* An InsertStmt has no sortClause */
338         qry->sortClause = NIL;
339
340         qry->distinctClause = transformDistinctClause(pstate,
341                                                                                                   stmt->distinctClause,
342                                                                                                   qry->targetList,
343                                                                                                   &qry->sortClause);
344
345         qry->hasSubLinks = pstate->p_hasSubLinks;
346         qry->hasAggs = pstate->p_hasAggs;
347         if (pstate->p_hasAggs || qry->groupClause || qry->havingQual)
348                 parseCheckAggregates(pstate, qry);
349
350         /*
351          * The INSERT INTO ... SELECT ... could have a UNION in child, so
352          * unionClause may be false
353          */
354         qry->unionall = stmt->unionall;
355
356         /*
357          * Just hand through the unionClause and intersectClause. We will
358          * handle it in the function Except_Intersect_Rewrite()
359          */
360         qry->unionClause = stmt->unionClause;
361         qry->intersectClause = stmt->intersectClause;
362
363         /*
364          * Now we are done with SELECT-like processing, and can get on with
365          * transforming the target list to match the INSERT target columns.
366          *
367          * In particular, it's time to add the INSERT target to the rangetable.
368          * (We didn't want it there until now since it shouldn't be visible in
369          * the SELECT part.)
370          */
371         setTargetTable(pstate, stmt->relname, FALSE);
372
373         /* now the range table will not change */
374         qry->rtable = pstate->p_rtable;
375         qry->resultRelation = refnameRangeTablePosn(pstate, stmt->relname, NULL);
376
377         /* Prepare to assign non-conflicting resnos to resjunk attributes */
378         if (pstate->p_last_resno <= pstate->p_target_relation->rd_rel->relnatts)
379                 pstate->p_last_resno = pstate->p_target_relation->rd_rel->relnatts + 1;
380
381         /* Validate stmt->cols list, or build default list if no list given */
382         icolumns = checkInsertTargets(pstate, stmt->cols, &attrnos);
383
384         /* Prepare non-junk columns for assignment to target table */
385         numuseratts = 0;
386         attnos = attrnos;
387         foreach(tl, qry->targetList)
388         {
389                 TargetEntry *tle = (TargetEntry *) lfirst(tl);
390                 Resdom     *resnode = tle->resdom;
391                 Ident      *id;
392
393                 if (resnode->resjunk)
394                 {
395
396                         /*
397                          * Resjunk nodes need no additional processing, but be sure
398                          * they have names and resnos that do not match any target
399                          * columns; else rewriter or planner might get confused.
400                          */
401                         resnode->resname = "?resjunk?";
402                         resnode->resno = (AttrNumber) pstate->p_last_resno++;
403                         continue;
404                 }
405                 if (icolumns == NIL || attnos == NIL)
406                         elog(ERROR, "INSERT has more expressions than target columns");
407                 id = (Ident *) lfirst(icolumns);
408                 updateTargetListEntry(pstate, tle, id->name, lfirsti(attnos),
409                                                           id->indirection);
410                 numuseratts++;
411                 icolumns = lnext(icolumns);
412                 attnos = lnext(attnos);
413         }
414
415         /*
416          * It is possible that the targetlist has fewer entries than were in
417          * the columns list.  We do not consider this an error (perhaps we
418          * should, if the columns list was explictly given?).  We must
419          * truncate the attrnos list to only include the attrs actually
420          * provided, else we will fail to apply defaults for them below.
421          */
422         if (icolumns != NIL)
423                 attrnos = ltruncate(numuseratts, attrnos);
424
425         /*
426          * Add targetlist items to assign DEFAULT values to any columns that
427          * have defaults and were not assigned to by the user.
428          *
429          * XXX wouldn't it make more sense to do this further downstream, after
430          * the rule rewriter?
431          */
432         rd_att = pstate->p_target_relation->rd_att;
433         if (rd_att->constr && rd_att->constr->num_defval > 0)
434         {
435                 Form_pg_attribute *att = rd_att->attrs;
436                 AttrDefault *defval = rd_att->constr->defval;
437                 int                     ndef = rd_att->constr->num_defval;
438
439                 while (--ndef >= 0)
440                 {
441                         AttrNumber      attrno = defval[ndef].adnum;
442                         Form_pg_attribute thisatt = att[attrno - 1];
443                         TargetEntry *te;
444
445                         if (intMember((int) attrno, attrnos))
446                                 continue;               /* there was a user-specified value */
447
448                         /*
449                          * No user-supplied value, so add a targetentry with DEFAULT
450                          * expr and correct data for the target column.
451                          */
452                         te = makeTargetEntry(
453                                                                  makeResdom(attrno,
454                                                                                         thisatt->atttypid,
455                                                                                         thisatt->atttypmod,
456                                                                           pstrdup(NameStr(thisatt->attname)),
457                                                                                         0, 0, false),
458                                                                  stringToNode(defval[ndef].adbin));
459                         qry->targetList = lappend(qry->targetList, te);
460
461                         /*
462                          * Make sure the value is coerced to the target column type
463                          * (might not be right type if it's not a constant!)
464                          */
465                         updateTargetListEntry(pstate, te, te->resdom->resname, attrno,
466                                                                   NIL);
467                 }
468         }
469
470         if (stmt->forUpdate != NULL)
471                 transformForUpdate(qry, stmt->forUpdate);
472
473         /* in case of subselects in default clauses... */
474         qry->hasSubLinks = pstate->p_hasSubLinks;
475
476         return (Query *) qry;
477 }
478
479 /*
480  *      makeObjectName()
481  *
482  *      Create a name for an implicitly created index, sequence, constraint, etc.
483  *
484  *      The parameters are: the original table name, the original field name, and
485  *      a "type" string (such as "seq" or "pkey").      The field name and/or type
486  *      can be NULL if not relevant.
487  *
488  *      The result is a palloc'd string.
489  *
490  *      The basic result we want is "name1_name2_type", omitting "_name2" or
491  *      "_type" when those parameters are NULL.  However, we must generate
492  *      a name with less than NAMEDATALEN characters!  So, we truncate one or
493  *      both names if necessary to make a short-enough string.  The type part
494  *      is never truncated (so it had better be reasonably short).
495  *
496  *      To reduce the probability of collisions, we might someday add more
497  *      smarts to this routine, like including some "hash" characters computed
498  *      from the truncated characters.  Currently it seems best to keep it simple,
499  *      so that the generated names are easily predictable by a person.
500  */
501 static char *
502 makeObjectName(char *name1, char *name2, char *typename)
503 {
504         char       *name;
505         int                     overhead = 0;   /* chars needed for type and underscores */
506         int                     availchars;             /* chars available for name(s) */
507         int                     name1chars;             /* chars allocated to name1 */
508         int                     name2chars;             /* chars allocated to name2 */
509         int                     ndx;
510
511         name1chars = strlen(name1);
512         if (name2)
513         {
514                 name2chars = strlen(name2);
515                 overhead++;                             /* allow for separating underscore */
516         }
517         else
518                 name2chars = 0;
519         if (typename)
520                 overhead += strlen(typename) + 1;
521
522         availchars = NAMEDATALEN - 1 - overhead;
523
524         /*
525          * If we must truncate,  preferentially truncate the longer name. This
526          * logic could be expressed without a loop, but it's simple and
527          * obvious as a loop.
528          */
529         while (name1chars + name2chars > availchars)
530         {
531                 if (name1chars > name2chars)
532                         name1chars--;
533                 else
534                         name2chars--;
535         }
536
537         /* Now construct the string using the chosen lengths */
538         name = palloc(name1chars + name2chars + overhead + 1);
539         strncpy(name, name1, name1chars);
540         ndx = name1chars;
541         if (name2)
542         {
543                 name[ndx++] = '_';
544                 strncpy(name + ndx, name2, name2chars);
545                 ndx += name2chars;
546         }
547         if (typename)
548         {
549                 name[ndx++] = '_';
550                 strcpy(name + ndx, typename);
551         }
552         else
553                 name[ndx] = '\0';
554
555         return name;
556 }
557
558 static char *
559 CreateIndexName(char *table_name, char *column_name, char *label, List *indices)
560 {
561         int                     pass = 0;
562         char       *iname = NULL;
563         List       *ilist;
564         char            typename[NAMEDATALEN];
565
566         /*
567          * The type name for makeObjectName is label, or labelN if that's
568          * necessary to prevent collisions among multiple indexes for the same
569          * table.  Note there is no check for collisions with already-existing
570          * indexes; this ought to be rethought someday.
571          */
572         strcpy(typename, label);
573
574         for (;;)
575         {
576                 iname = makeObjectName(table_name, column_name, typename);
577
578                 foreach(ilist, indices)
579                 {
580                         IndexStmt  *index = lfirst(ilist);
581
582                         if (strcmp(iname, index->idxname) == 0)
583                                 break;
584                 }
585                 /* ran through entire list? then no name conflict found so done */
586                 if (ilist == NIL)
587                         break;
588
589                 /* the last one conflicted, so try a new name component */
590                 pfree(iname);
591                 sprintf(typename, "%s%d", label, ++pass);
592         }
593
594         return iname;
595 }
596
597 /*
598  * transformCreateStmt -
599  *        transforms the "create table" statement
600  *        SQL92 allows constraints to be scattered all over, so thumb through
601  *         the columns and collect all constraints into one place.
602  *        If there are any implied indices (e.g. UNIQUE or PRIMARY KEY)
603  *         then expand those into multiple IndexStmt blocks.
604  *        - thomas 1997-12-02
605  */
606 static Query *
607 transformCreateStmt(ParseState *pstate, CreateStmt *stmt)
608 {
609         Query      *q;
610         List       *elements;
611         Node       *element;
612         List       *columns;
613         List       *dlist;
614         ColumnDef  *column;
615         List       *constraints,
616                            *clist;
617         Constraint *constraint;
618         List       *fkconstraints,      /* List of FOREIGN KEY constraints to */
619                            *fkclist;            /* add finally */
620         FkConstraint *fkconstraint;
621         List       *keys;
622         Ident      *key;
623         List       *blist = NIL;        /* "before list" of things to do before
624                                                                  * creating the table */
625         List       *ilist = NIL;        /* "index list" of things to do after
626                                                                  * creating the table */
627         IndexStmt  *index,
628                            *pkey = NULL;
629         IndexElem  *iparam;
630         bool            saw_nullable;
631
632         q = makeNode(Query);
633         q->commandType = CMD_UTILITY;
634
635         fkconstraints = NIL;
636         constraints = stmt->constraints;
637         columns = NIL;
638         dlist = NIL;
639
640         /*
641          * Run through each primary element in the table creation clause
642          */
643         foreach(elements, stmt->tableElts)
644         {
645                 element = lfirst(elements);
646                 switch (nodeTag(element))
647                 {
648                         case T_ColumnDef:
649                                 column = (ColumnDef *) element;
650                                 columns = lappend(columns, column);
651
652                                 transformColumnType(pstate, column);
653
654                                 /* Special case SERIAL type? */
655                                 if (column->is_sequence)
656                                 {
657                                         char       *sname;
658                                         char       *qstring;
659                                         A_Const    *snamenode;
660                                         FuncCall   *funccallnode;
661                                         CreateSeqStmt *sequence;
662
663                                         /*
664                                          * Create appropriate constraints for SERIAL.  We do
665                                          * this in full, rather than shortcutting, so that we
666                                          * will detect any conflicting constraints the user
667                                          * wrote (like a different DEFAULT).
668                                          */
669                                         sname = makeObjectName(stmt->relname, column->colname,
670                                                                                    "seq");
671
672                                         /*
673                                          * Create an expression tree representing the function
674                                          * call  nextval('"sequencename"')
675                                          */
676                                         qstring = palloc(strlen(sname) + 2 + 1);
677                                         sprintf(qstring, "\"%s\"", sname);
678                                         snamenode = makeNode(A_Const);
679                                         snamenode->val.type = T_String;
680                                         snamenode->val.val.str = qstring;
681                                         funccallnode = makeNode(FuncCall);
682                                         funccallnode->funcname = "nextval";
683                                         funccallnode->args = lcons(snamenode, NIL);
684                                         funccallnode->agg_star = false;
685                                         funccallnode->agg_distinct = false;
686
687                                         constraint = makeNode(Constraint);
688                                         constraint->contype = CONSTR_DEFAULT;
689                                         constraint->name = sname;
690                                         constraint->raw_expr = (Node *) funccallnode;
691                                         constraint->cooked_expr = NULL;
692                                         constraint->keys = NIL;
693                                         column->constraints = lappend(column->constraints,
694                                                                                                   constraint);
695
696                                         constraint = makeNode(Constraint);
697                                         constraint->contype = CONSTR_UNIQUE;
698                                         constraint->name = makeObjectName(stmt->relname,
699                                                                                                           column->colname,
700                                                                                                           "key");
701                                         column->constraints = lappend(column->constraints,
702                                                                                                   constraint);
703
704                                         constraint = makeNode(Constraint);
705                                         constraint->contype = CONSTR_NOTNULL;
706                                         column->constraints = lappend(column->constraints,
707                                                                                                   constraint);
708
709                                         sequence = makeNode(CreateSeqStmt);
710                                         sequence->seqname = pstrdup(sname);
711                                         sequence->options = NIL;
712
713                                         elog(NOTICE, "CREATE TABLE will create implicit sequence '%s' for SERIAL column '%s.%s'",
714                                           sequence->seqname, stmt->relname, column->colname);
715
716                                         blist = lcons(sequence, NIL);
717                                 }
718
719                                 /* Process column constraints, if any... */
720                                 transformConstraintAttrs(column->constraints);
721
722                                 saw_nullable = false;
723
724                                 foreach(clist, column->constraints)
725                                 {
726                                         constraint = lfirst(clist);
727
728                                         /* ----------
729                                          * If this column constraint is a FOREIGN KEY
730                                          * constraint, then we fill in the current attributes
731                                          * name and throw it into the list of FK constraints
732                                          * to be processed later.
733                                          * ----------
734                                          */
735                                         if (IsA(constraint, FkConstraint))
736                                         {
737                                                 Ident      *id = makeNode(Ident);
738
739                                                 id->name = column->colname;
740                                                 id->indirection = NIL;
741                                                 id->isRel = false;
742
743                                                 fkconstraint = (FkConstraint *) constraint;
744                                                 fkconstraint->fk_attrs = lappend(NIL, id);
745
746                                                 fkconstraints = lappend(fkconstraints, constraint);
747                                                 continue;
748                                         }
749
750                                         switch (constraint->contype)
751                                         {
752                                                 case CONSTR_NULL:
753                                                         if (saw_nullable && column->is_not_null)
754                                                                 elog(ERROR, "CREATE TABLE/(NOT) NULL conflicting declaration"
755                                                                          " for '%s.%s'", stmt->relname, column->colname);
756                                                         column->is_not_null = FALSE;
757                                                         saw_nullable = true;
758                                                         break;
759
760                                                 case CONSTR_NOTNULL:
761                                                         if (saw_nullable && !column->is_not_null)
762                                                                 elog(ERROR, "CREATE TABLE/(NOT) NULL conflicting declaration"
763                                                                          " for '%s.%s'", stmt->relname, column->colname);
764                                                         column->is_not_null = TRUE;
765                                                         saw_nullable = true;
766                                                         break;
767
768                                                 case CONSTR_DEFAULT:
769                                                         if (column->raw_default != NULL)
770                                                                 elog(ERROR, "CREATE TABLE/DEFAULT multiple values specified"
771                                                                          " for '%s.%s'", stmt->relname, column->colname);
772                                                         column->raw_default = constraint->raw_expr;
773                                                         Assert(constraint->cooked_expr == NULL);
774                                                         break;
775
776                                                 case CONSTR_PRIMARY:
777                                                         if (constraint->name == NULL)
778                                                                 constraint->name = makeObjectName(stmt->relname, NULL, "pkey");
779                                                         if (constraint->keys == NIL)
780                                                         {
781                                                                 key = makeNode(Ident);
782                                                                 key->name = pstrdup(column->colname);
783                                                                 constraint->keys = lcons(key, NIL);
784                                                         }
785                                                         dlist = lappend(dlist, constraint);
786                                                         break;
787
788                                                 case CONSTR_UNIQUE:
789                                                         if (constraint->name == NULL)
790                                                                 constraint->name = makeObjectName(stmt->relname, column->colname, "key");
791                                                         if (constraint->keys == NIL)
792                                                         {
793                                                                 key = makeNode(Ident);
794                                                                 key->name = pstrdup(column->colname);
795                                                                 constraint->keys = lcons(key, NIL);
796                                                         }
797                                                         dlist = lappend(dlist, constraint);
798                                                         break;
799
800                                                 case CONSTR_CHECK:
801                                                         if (constraint->name == NULL)
802                                                                 constraint->name = makeObjectName(stmt->relname, column->colname, NULL);
803                                                         constraints = lappend(constraints, constraint);
804                                                         break;
805
806                                                 case CONSTR_ATTR_DEFERRABLE:
807                                                 case CONSTR_ATTR_NOT_DEFERRABLE:
808                                                 case CONSTR_ATTR_DEFERRED:
809                                                 case CONSTR_ATTR_IMMEDIATE:
810                                                         /* transformConstraintAttrs took care of these */
811                                                         break;
812
813                                                 default:
814                                                         elog(ERROR, "parser: unrecognized constraint (internal error)");
815                                                         break;
816                                         }
817                                 }
818                                 break;
819
820                         case T_Constraint:
821                                 constraint = (Constraint *) element;
822                                 switch (constraint->contype)
823                                 {
824                                         case CONSTR_PRIMARY:
825                                                 if (constraint->name == NULL)
826                                                         constraint->name = makeObjectName(stmt->relname, NULL, "pkey");
827                                                 dlist = lappend(dlist, constraint);
828                                                 break;
829
830                                         case CONSTR_UNIQUE:
831                                                 dlist = lappend(dlist, constraint);
832                                                 break;
833
834                                         case CONSTR_CHECK:
835                                                 constraints = lappend(constraints, constraint);
836                                                 break;
837
838                                         case CONSTR_NULL:
839                                         case CONSTR_NOTNULL:
840                                         case CONSTR_DEFAULT:
841                                         case CONSTR_ATTR_DEFERRABLE:
842                                         case CONSTR_ATTR_NOT_DEFERRABLE:
843                                         case CONSTR_ATTR_DEFERRED:
844                                         case CONSTR_ATTR_IMMEDIATE:
845                                                 elog(ERROR, "parser: illegal context for constraint (internal error)");
846                                                 break;
847
848                                         default:
849                                                 elog(ERROR, "parser: unrecognized constraint (internal error)");
850                                                 break;
851                                 }
852                                 break;
853
854                         case T_FkConstraint:
855                                 /* ----------
856                                  * Table level FOREIGN KEY constraints are already complete.
857                                  * Just remember for later.
858                                  * ----------
859                                  */
860                                 fkconstraints = lappend(fkconstraints, element);
861                                 break;
862
863                         default:
864                                 elog(ERROR, "parser: unrecognized node (internal error)");
865                 }
866         }
867
868         stmt->tableElts = columns;
869         stmt->constraints = constraints;
870
871 /* Now run through the "deferred list" to complete the query transformation.
872  * For PRIMARY KEYs, mark each column as NOT NULL and create an index.
873  * For UNIQUE, create an index as for PRIMARY KEYS, but do not insist on NOT NULL.
874  *
875  * Note that this code does not currently look for all possible redundant cases
876  *      and either ignore or stop with warning. The create might fail later when
877  *      names for indices turn out to be duplicated, or a user might have specified
878  *      extra useless indices which might hurt performance. - thomas 1997-12-08
879  */
880         while (dlist != NIL)
881         {
882                 constraint = lfirst(dlist);
883                 Assert(nodeTag(constraint) == T_Constraint);
884                 Assert((constraint->contype == CONSTR_PRIMARY)
885                            || (constraint->contype == CONSTR_UNIQUE));
886
887                 index = makeNode(IndexStmt);
888
889                 index->unique = TRUE;
890                 index->primary = (constraint->contype == CONSTR_PRIMARY ? TRUE : FALSE);
891                 if (index->primary)
892                 {
893                         if (pkey != NULL)
894                                 elog(ERROR, "CREATE TABLE/PRIMARY KEY multiple primary keys"
895                                          " for table '%s' are not allowed", stmt->relname);
896                         pkey = (IndexStmt *) index;
897                 }
898
899                 if (constraint->name != NULL)
900                         index->idxname = pstrdup(constraint->name);
901                 else if (constraint->contype == CONSTR_PRIMARY)
902                         index->idxname = makeObjectName(stmt->relname, NULL, "pkey");
903                 else
904                         index->idxname = NULL;
905
906                 index->relname = stmt->relname;
907                 index->accessMethod = "btree";
908                 index->indexParams = NIL;
909                 index->withClause = NIL;
910                 index->whereClause = NULL;
911
912                 foreach(keys, constraint->keys)
913                 {
914                         key = (Ident *) lfirst(keys);
915                         Assert(IsA(key, Ident));
916                         column = NULL;
917                         foreach(columns, stmt->tableElts)
918                         {
919                                 column = lfirst(columns);
920                                 Assert(IsA(column, ColumnDef));
921                                 if (strcmp(column->colname, key->name) == 0)
922                                         break;
923                         }
924                         if (columns == NIL) /* fell off end of list? */
925                                 elog(ERROR, "CREATE TABLE: column '%s' named in key does not exist",
926                                          key->name);
927
928                         if (constraint->contype == CONSTR_PRIMARY)
929                                 column->is_not_null = TRUE;
930                         iparam = makeNode(IndexElem);
931                         iparam->name = pstrdup(column->colname);
932                         iparam->args = NIL;
933                         iparam->class = NULL;
934                         iparam->typename = NULL;
935                         index->indexParams = lappend(index->indexParams, iparam);
936
937                         if (index->idxname == NULL)
938                                 index->idxname = CreateIndexName(stmt->relname, iparam->name, "key", ilist);
939                 }
940
941                 if (index->idxname == NULL)             /* should not happen */
942                         elog(ERROR, "CREATE TABLE: failed to make implicit index name");
943
944                 ilist = lappend(ilist, index);
945                 dlist = lnext(dlist);
946         }
947
948 /* OK, now finally, if there is a primary key, then make sure that there aren't any redundant
949  * unique indices defined on columns. This can arise if someone specifies UNIQUE explicitly
950  * or if a SERIAL column was defined along with a table PRIMARY KEY constraint.
951  * - thomas 1999-05-11
952  */
953         if (pkey != NULL)
954         {
955                 dlist = ilist;
956                 ilist = NIL;
957                 while (dlist != NIL)
958                 {
959                         List       *pcols,
960                                            *icols;
961                         int                     plen,
962                                                 ilen;
963                         int                     keep = TRUE;
964
965                         index = lfirst(dlist);
966                         pcols = pkey->indexParams;
967                         icols = index->indexParams;
968
969                         plen = length(pcols);
970                         ilen = length(icols);
971
972                         /* Not the same as the primary key? Then we should look... */
973                         if ((index != pkey) && (ilen == plen))
974                         {
975                                 keep = FALSE;
976                                 while ((pcols != NIL) && (icols != NIL))
977                                 {
978                                         IndexElem  *pcol = lfirst(pcols);
979                                         IndexElem  *icol = lfirst(icols);
980                                         char       *pname = pcol->name;
981                                         char       *iname = icol->name;
982
983                                         /* different names? then no match... */
984                                         if (strcmp(iname, pname) != 0)
985                                         {
986                                                 keep = TRUE;
987                                                 break;
988                                         }
989                                         pcols = lnext(pcols);
990                                         icols = lnext(icols);
991                                 }
992                         }
993
994                         if (keep)
995                                 ilist = lappend(ilist, index);
996                         dlist = lnext(dlist);
997                 }
998         }
999
1000         dlist = ilist;
1001         while (dlist != NIL)
1002         {
1003                 index = lfirst(dlist);
1004                 elog(NOTICE, "CREATE TABLE/%s will create implicit index '%s' for table '%s'",
1005                          (index->primary ? "PRIMARY KEY" : "UNIQUE"),
1006                          index->idxname, stmt->relname);
1007                 dlist = lnext(dlist);
1008         }
1009
1010         q->utilityStmt = (Node *) stmt;
1011         extras_before = blist;
1012         extras_after = ilist;
1013
1014         /*
1015          * Now process the FOREIGN KEY constraints and add appropriate queries
1016          * to the extras_after statements list.
1017          *
1018          */
1019         if (fkconstraints != NIL)
1020         {
1021                 CreateTrigStmt *fk_trigger;
1022                 List       *fk_attr;
1023                 List       *pk_attr;
1024                 Ident      *id;
1025
1026                 elog(NOTICE, "CREATE TABLE will create implicit trigger(s) for FOREIGN KEY check(s)");
1027
1028                 foreach(fkclist, fkconstraints)
1029                 {
1030                         fkconstraint = (FkConstraint *) lfirst(fkclist);
1031
1032                         /*
1033                          * If the constraint has no name, set it to <unnamed>
1034                          *
1035                          */
1036                         if (fkconstraint->constr_name == NULL)
1037                                 fkconstraint->constr_name = "<unnamed>";
1038
1039                         /*
1040                          * If the attribute list for the referenced table was omitted,
1041                          * lookup for the definition of the primary key. If the
1042                          * referenced table is this table, use the definition we found
1043                          * above, rather than looking to the system tables.
1044                          *
1045                          */
1046                         if (fkconstraint->fk_attrs != NIL && fkconstraint->pk_attrs == NIL)
1047                         {
1048                                 if (strcmp(fkconstraint->pktable_name, stmt->relname) != 0)
1049                                         transformFkeyGetPrimaryKey(fkconstraint);
1050                                 else if (pkey != NULL)
1051                                 {
1052                                         List       *pkey_attr = pkey->indexParams;
1053                                         List       *attr;
1054                                         IndexElem  *ielem;
1055                                         Ident      *pkattr;
1056
1057                                         foreach(attr, pkey_attr)
1058                                         {
1059                                                 ielem = lfirst(attr);
1060                                                 pkattr = (Ident *) makeNode(Ident);
1061                                                 pkattr->name = pstrdup(ielem->name);
1062                                                 pkattr->indirection = NIL;
1063                                                 pkattr->isRel = false;
1064                                                 fkconstraint->pk_attrs = lappend(fkconstraint->pk_attrs, pkattr);
1065                                         }
1066                                 }
1067                                 else
1068                                 {
1069                                         elog(ERROR, "PRIMARY KEY for referenced table \"%s\" not found",
1070                                                  fkconstraint->pktable_name);
1071                                 }
1072                         }
1073
1074                         /*
1075                          * Build a CREATE CONSTRAINT TRIGGER statement for the CHECK
1076                          * action.
1077                          *
1078                          */
1079                         fk_trigger = (CreateTrigStmt *) makeNode(CreateTrigStmt);
1080                         fk_trigger->trigname = fkconstraint->constr_name;
1081                         fk_trigger->relname = stmt->relname;
1082                         fk_trigger->funcname = "RI_FKey_check_ins";
1083                         fk_trigger->before = false;
1084                         fk_trigger->row = true;
1085                         fk_trigger->actions[0] = 'i';
1086                         fk_trigger->actions[1] = 'u';
1087                         fk_trigger->actions[2] = '\0';
1088                         fk_trigger->lang = NULL;
1089                         fk_trigger->text = NULL;
1090
1091                         fk_trigger->attr = NIL;
1092                         fk_trigger->when = NULL;
1093                         fk_trigger->isconstraint = true;
1094                         fk_trigger->deferrable = fkconstraint->deferrable;
1095                         fk_trigger->initdeferred = fkconstraint->initdeferred;
1096                         fk_trigger->constrrelname = fkconstraint->pktable_name;
1097
1098                         fk_trigger->args = NIL;
1099                         fk_trigger->args = lappend(fk_trigger->args,
1100                                                                            fkconstraint->constr_name);
1101                         fk_trigger->args = lappend(fk_trigger->args,
1102                                                                            stmt->relname);
1103                         fk_trigger->args = lappend(fk_trigger->args,
1104                                                                            fkconstraint->pktable_name);
1105                         fk_trigger->args = lappend(fk_trigger->args,
1106                                                                            fkconstraint->match_type);
1107                         fk_attr = fkconstraint->fk_attrs;
1108                         pk_attr = fkconstraint->pk_attrs;
1109                         if (length(fk_attr) != length(pk_attr))
1110                         {
1111                                 elog(NOTICE, "Illegal FOREIGN KEY definition REFERENCES \"%s\"",
1112                                          fkconstraint->pktable_name);
1113                                 elog(ERROR, "number of key attributes in referenced table must be equal to foreign key");
1114                         }
1115                         while (fk_attr != NIL)
1116                         {
1117                                 id = (Ident *) lfirst(fk_attr);
1118                                 fk_trigger->args = lappend(fk_trigger->args, id->name);
1119
1120                                 id = (Ident *) lfirst(pk_attr);
1121                                 fk_trigger->args = lappend(fk_trigger->args, id->name);
1122
1123                                 fk_attr = lnext(fk_attr);
1124                                 pk_attr = lnext(pk_attr);
1125                         }
1126
1127                         extras_after = lappend(extras_after, (Node *) fk_trigger);
1128
1129                         /*
1130                          * Build a CREATE CONSTRAINT TRIGGER statement for the ON
1131                          * DELETE action fired on the PK table !!!
1132                          *
1133                          */
1134                         fk_trigger = (CreateTrigStmt *) makeNode(CreateTrigStmt);
1135                         fk_trigger->trigname = fkconstraint->constr_name;
1136                         fk_trigger->relname = fkconstraint->pktable_name;
1137                         fk_trigger->before = false;
1138                         fk_trigger->row = true;
1139                         fk_trigger->actions[0] = 'd';
1140                         fk_trigger->actions[1] = '\0';
1141                         fk_trigger->lang = NULL;
1142                         fk_trigger->text = NULL;
1143
1144                         fk_trigger->attr = NIL;
1145                         fk_trigger->when = NULL;
1146                         fk_trigger->isconstraint = true;
1147                         fk_trigger->deferrable = fkconstraint->deferrable;
1148                         fk_trigger->initdeferred = fkconstraint->initdeferred;
1149                         fk_trigger->constrrelname = stmt->relname;
1150                         switch ((fkconstraint->actions & FKCONSTR_ON_DELETE_MASK)
1151                                         >> FKCONSTR_ON_DELETE_SHIFT)
1152                         {
1153                                 case FKCONSTR_ON_KEY_NOACTION:
1154                                         fk_trigger->funcname = "RI_FKey_noaction_del";
1155                                         break;
1156                                 case FKCONSTR_ON_KEY_RESTRICT:
1157                                         fk_trigger->deferrable = false;
1158                                         fk_trigger->initdeferred = false;
1159                                         fk_trigger->funcname = "RI_FKey_restrict_del";
1160                                         break;
1161                                 case FKCONSTR_ON_KEY_CASCADE:
1162                                         fk_trigger->funcname = "RI_FKey_cascade_del";
1163                                         break;
1164                                 case FKCONSTR_ON_KEY_SETNULL:
1165                                         fk_trigger->funcname = "RI_FKey_setnull_del";
1166                                         break;
1167                                 case FKCONSTR_ON_KEY_SETDEFAULT:
1168                                         fk_trigger->funcname = "RI_FKey_setdefault_del";
1169                                         break;
1170                                 default:
1171                                         elog(ERROR, "Only one ON DELETE action can be specified for FOREIGN KEY constraint");
1172                                         break;
1173                         }
1174
1175                         fk_trigger->args = NIL;
1176                         fk_trigger->args = lappend(fk_trigger->args,
1177                                                                            fkconstraint->constr_name);
1178                         fk_trigger->args = lappend(fk_trigger->args,
1179                                                                            stmt->relname);
1180                         fk_trigger->args = lappend(fk_trigger->args,
1181                                                                            fkconstraint->pktable_name);
1182                         fk_trigger->args = lappend(fk_trigger->args,
1183                                                                            fkconstraint->match_type);
1184                         fk_attr = fkconstraint->fk_attrs;
1185                         pk_attr = fkconstraint->pk_attrs;
1186                         while (fk_attr != NIL)
1187                         {
1188                                 id = (Ident *) lfirst(fk_attr);
1189                                 fk_trigger->args = lappend(fk_trigger->args, id->name);
1190
1191                                 id = (Ident *) lfirst(pk_attr);
1192                                 fk_trigger->args = lappend(fk_trigger->args, id->name);
1193
1194                                 fk_attr = lnext(fk_attr);
1195                                 pk_attr = lnext(pk_attr);
1196                         }
1197
1198                         extras_after = lappend(extras_after, (Node *) fk_trigger);
1199
1200                         /*
1201                          * Build a CREATE CONSTRAINT TRIGGER statement for the ON
1202                          * UPDATE action fired on the PK table !!!
1203                          *
1204                          */
1205                         fk_trigger = (CreateTrigStmt *) makeNode(CreateTrigStmt);
1206                         fk_trigger->trigname = fkconstraint->constr_name;
1207                         fk_trigger->relname = fkconstraint->pktable_name;
1208                         fk_trigger->before = false;
1209                         fk_trigger->row = true;
1210                         fk_trigger->actions[0] = 'u';
1211                         fk_trigger->actions[1] = '\0';
1212                         fk_trigger->lang = NULL;
1213                         fk_trigger->text = NULL;
1214
1215                         fk_trigger->attr = NIL;
1216                         fk_trigger->when = NULL;
1217                         fk_trigger->isconstraint = true;
1218                         fk_trigger->deferrable = fkconstraint->deferrable;
1219                         fk_trigger->initdeferred = fkconstraint->initdeferred;
1220                         fk_trigger->constrrelname = stmt->relname;
1221                         switch ((fkconstraint->actions & FKCONSTR_ON_UPDATE_MASK)
1222                                         >> FKCONSTR_ON_UPDATE_SHIFT)
1223                         {
1224                                 case FKCONSTR_ON_KEY_NOACTION:
1225                                         fk_trigger->funcname = "RI_FKey_noaction_upd";
1226                                         break;
1227                                 case FKCONSTR_ON_KEY_RESTRICT:
1228                                         fk_trigger->deferrable = false;
1229                                         fk_trigger->initdeferred = false;
1230                                         fk_trigger->funcname = "RI_FKey_restrict_upd";
1231                                         break;
1232                                 case FKCONSTR_ON_KEY_CASCADE:
1233                                         fk_trigger->funcname = "RI_FKey_cascade_upd";
1234                                         break;
1235                                 case FKCONSTR_ON_KEY_SETNULL:
1236                                         fk_trigger->funcname = "RI_FKey_setnull_upd";
1237                                         break;
1238                                 case FKCONSTR_ON_KEY_SETDEFAULT:
1239                                         fk_trigger->funcname = "RI_FKey_setdefault_upd";
1240                                         break;
1241                                 default:
1242                                         elog(ERROR, "Only one ON UPDATE action can be specified for FOREIGN KEY constraint");
1243                                         break;
1244                         }
1245
1246                         fk_trigger->args = NIL;
1247                         fk_trigger->args = lappend(fk_trigger->args,
1248                                                                            fkconstraint->constr_name);
1249                         fk_trigger->args = lappend(fk_trigger->args,
1250                                                                            stmt->relname);
1251                         fk_trigger->args = lappend(fk_trigger->args,
1252                                                                            fkconstraint->pktable_name);
1253                         fk_trigger->args = lappend(fk_trigger->args,
1254                                                                            fkconstraint->match_type);
1255                         fk_attr = fkconstraint->fk_attrs;
1256                         pk_attr = fkconstraint->pk_attrs;
1257                         while (fk_attr != NIL)
1258                         {
1259                                 id = (Ident *) lfirst(fk_attr);
1260                                 fk_trigger->args = lappend(fk_trigger->args, id->name);
1261
1262                                 id = (Ident *) lfirst(pk_attr);
1263                                 fk_trigger->args = lappend(fk_trigger->args, id->name);
1264
1265                                 fk_attr = lnext(fk_attr);
1266                                 pk_attr = lnext(pk_attr);
1267                         }
1268
1269                         extras_after = lappend(extras_after, (Node *) fk_trigger);
1270                 }
1271         }
1272
1273         return q;
1274 }       /* transformCreateStmt() */
1275
1276
1277 /*
1278  * transformIndexStmt -
1279  *        transforms the qualification of the index statement
1280  */
1281 static Query *
1282 transformIndexStmt(ParseState *pstate, IndexStmt *stmt)
1283 {
1284         Query      *qry;
1285
1286         qry = makeNode(Query);
1287         qry->commandType = CMD_UTILITY;
1288
1289         /* take care of the where clause */
1290         stmt->whereClause = transformWhereClause(pstate, stmt->whereClause);
1291
1292         qry->hasSubLinks = pstate->p_hasSubLinks;
1293
1294         stmt->rangetable = pstate->p_rtable;
1295
1296         qry->utilityStmt = (Node *) stmt;
1297
1298         return qry;
1299 }
1300
1301 /*
1302  * transformExtendStmt -
1303  *        transform the qualifications of the Extend Index Statement
1304  *
1305  */
1306 static Query *
1307 transformExtendStmt(ParseState *pstate, ExtendStmt *stmt)
1308 {
1309         Query      *qry;
1310
1311         qry = makeNode(Query);
1312         qry->commandType = CMD_UTILITY;
1313
1314         /* take care of the where clause */
1315         stmt->whereClause = transformWhereClause(pstate, stmt->whereClause);
1316
1317         qry->hasSubLinks = pstate->p_hasSubLinks;
1318
1319         stmt->rangetable = pstate->p_rtable;
1320
1321         qry->utilityStmt = (Node *) stmt;
1322         return qry;
1323 }
1324
1325 /*
1326  * transformRuleStmt -
1327  *        transform a Create Rule Statement. The actions is a list of parse
1328  *        trees which is transformed into a list of query trees.
1329  */
1330 static Query *
1331 transformRuleStmt(ParseState *pstate, RuleStmt *stmt)
1332 {
1333         Query      *qry;
1334         Query      *action;
1335         List       *actions;
1336
1337         qry = makeNode(Query);
1338         qry->commandType = CMD_UTILITY;
1339
1340         /*
1341          * 'instead nothing' rules with a qualification need a query a
1342          * rangetable so the rewrite handler can add the negated rule
1343          * qualification to the original query. We create a query with the new
1344          * command type CMD_NOTHING here that is treated special by the
1345          * rewrite system.
1346          */
1347         if (stmt->actions == NIL)
1348         {
1349                 Query      *nothing_qry = makeNode(Query);
1350
1351                 nothing_qry->commandType = CMD_NOTHING;
1352
1353                 addRangeTableEntry(pstate, stmt->object->relname,
1354                                                    makeAttr("*CURRENT*", NULL),
1355                                                    FALSE, FALSE, FALSE);
1356                 addRangeTableEntry(pstate, stmt->object->relname,
1357                                                    makeAttr("*NEW*", NULL),
1358                                                    FALSE, FALSE, FALSE);
1359
1360                 nothing_qry->rtable = pstate->p_rtable;
1361
1362                 stmt->actions = lappend(NIL, nothing_qry);
1363         }
1364
1365         actions = stmt->actions;
1366
1367         /*
1368          * transform each statment, like parse_analyze()
1369          */
1370         while (actions != NIL)
1371         {
1372
1373                 /*
1374                  * NOTE: 'CURRENT' must always have a varno equal to 1 and 'NEW'
1375                  * equal to 2.
1376                  */
1377                 addRangeTableEntry(pstate, stmt->object->relname,
1378                                                    makeAttr("*CURRENT*", NULL),
1379                                                    FALSE, FALSE, FALSE);
1380                 addRangeTableEntry(pstate, stmt->object->relname,
1381                                                    makeAttr("*NEW*", NULL),
1382                                                    FALSE, FALSE, FALSE);
1383
1384                 pstate->p_last_resno = 1;
1385                 pstate->p_is_rule = true;               /* for expand all */
1386                 pstate->p_hasAggs = false;
1387
1388                 action = (Query *) lfirst(actions);
1389                 if (action->commandType != CMD_NOTHING)
1390                         lfirst(actions) = transformStmt(pstate, lfirst(actions));
1391                 actions = lnext(actions);
1392         }
1393
1394         /* take care of the where clause */
1395         stmt->whereClause = transformWhereClause(pstate, stmt->whereClause);
1396
1397         qry->hasSubLinks = pstate->p_hasSubLinks;
1398
1399         qry->utilityStmt = (Node *) stmt;
1400         return qry;
1401 }
1402
1403
1404 /*
1405  * transformSelectStmt -
1406  *        transforms a Select Statement
1407  *
1408  */
1409 static Query *
1410 transformSelectStmt(ParseState *pstate, SelectStmt *stmt)
1411 {
1412         Query      *qry = makeNode(Query);
1413
1414         qry->commandType = CMD_SELECT;
1415
1416         /* set up a range table */
1417         makeRangeTable(pstate, stmt->fromClause);
1418
1419         qry->into = stmt->into;
1420         qry->isTemp = stmt->istemp;
1421         qry->isPortal = FALSE;
1422
1423         qry->targetList = transformTargetList(pstate, stmt->targetList);
1424
1425         qry->qual = transformWhereClause(pstate, stmt->whereClause);
1426
1427         /*
1428          * Initial processing of HAVING clause is just like WHERE clause.
1429          * Additional work will be done in optimizer/plan/planner.c.
1430          */
1431         qry->havingQual = transformWhereClause(pstate, stmt->havingClause);
1432
1433         qry->groupClause = transformGroupClause(pstate,
1434                                                                                         stmt->groupClause,
1435                                                                                         qry->targetList);
1436
1437         qry->sortClause = transformSortClause(pstate,
1438                                                                                   stmt->sortClause,
1439                                                                                   qry->targetList);
1440
1441         qry->distinctClause = transformDistinctClause(pstate,
1442                                                                                                   stmt->distinctClause,
1443                                                                                                   qry->targetList,
1444                                                                                                   &qry->sortClause);
1445
1446         qry->hasSubLinks = pstate->p_hasSubLinks;
1447         qry->hasAggs = pstate->p_hasAggs;
1448         if (pstate->p_hasAggs || qry->groupClause || qry->havingQual)
1449                 parseCheckAggregates(pstate, qry);
1450
1451         /*
1452          * The INSERT INTO ... SELECT ... could have a UNION in child, so
1453          * unionClause may be false
1454          */
1455         qry->unionall = stmt->unionall;
1456
1457         /*
1458          * Just hand through the unionClause and intersectClause. We will
1459          * handle it in the function Except_Intersect_Rewrite()
1460          */
1461         qry->unionClause = stmt->unionClause;
1462         qry->intersectClause = stmt->intersectClause;
1463
1464         qry->rtable = pstate->p_rtable;
1465
1466         if (stmt->forUpdate != NULL)
1467                 transformForUpdate(qry, stmt->forUpdate);
1468
1469         return (Query *) qry;
1470 }
1471
1472 /*
1473  * transformUpdateStmt -
1474  *        transforms an update statement
1475  *
1476  */
1477 static Query *
1478 transformUpdateStmt(ParseState *pstate, UpdateStmt *stmt)
1479 {
1480         Query      *qry = makeNode(Query);
1481         List       *origTargetList;
1482         List       *tl;
1483
1484         qry->commandType = CMD_UPDATE;
1485         pstate->p_is_update = true;
1486
1487         /*
1488          * the FROM clause is non-standard SQL syntax. We used to be able to
1489          * do this with REPLACE in POSTQUEL so we keep the feature.
1490          */
1491         makeRangeTable(pstate, stmt->fromClause);
1492         setTargetTable(pstate, stmt->relname, stmt->inh);
1493
1494         qry->targetList = transformTargetList(pstate, stmt->targetList);
1495
1496         qry->qual = transformWhereClause(pstate, stmt->whereClause);
1497
1498         qry->hasSubLinks = pstate->p_hasSubLinks;
1499
1500         qry->rtable = pstate->p_rtable;
1501         qry->resultRelation = refnameRangeTablePosn(pstate, stmt->relname, NULL);
1502
1503         qry->hasAggs = pstate->p_hasAggs;
1504         if (pstate->p_hasAggs)
1505                 parseCheckAggregates(pstate, qry);
1506
1507         /*
1508          * Now we are done with SELECT-like processing, and can get on with
1509          * transforming the target list to match the UPDATE target columns.
1510          */
1511
1512         /* Prepare to assign non-conflicting resnos to resjunk attributes */
1513         if (pstate->p_last_resno <= pstate->p_target_relation->rd_rel->relnatts)
1514                 pstate->p_last_resno = pstate->p_target_relation->rd_rel->relnatts + 1;
1515
1516         /* Prepare non-junk columns for assignment to target table */
1517         origTargetList = stmt->targetList;
1518         foreach(tl, qry->targetList)
1519         {
1520                 TargetEntry *tle = (TargetEntry *) lfirst(tl);
1521                 Resdom     *resnode = tle->resdom;
1522                 ResTarget  *origTarget;
1523
1524                 if (resnode->resjunk)
1525                 {
1526
1527                         /*
1528                          * Resjunk nodes need no additional processing, but be sure
1529                          * they have names and resnos that do not match any target
1530                          * columns; else rewriter or planner might get confused.
1531                          */
1532                         resnode->resname = "?resjunk?";
1533                         resnode->resno = (AttrNumber) pstate->p_last_resno++;
1534                         continue;
1535                 }
1536                 if (origTargetList == NIL)
1537                         elog(ERROR, "UPDATE target count mismatch --- internal error");
1538                 origTarget = (ResTarget *) lfirst(origTargetList);
1539                 updateTargetListEntry(pstate, tle, origTarget->name,
1540                                                           attnameAttNum(pstate->p_target_relation,
1541                                                                                         origTarget->name),
1542                                                           origTarget->indirection);
1543                 origTargetList = lnext(origTargetList);
1544         }
1545         if (origTargetList != NIL)
1546                 elog(ERROR, "UPDATE target count mismatch --- internal error");
1547
1548         return (Query *) qry;
1549 }
1550
1551 /*
1552  * transformCursorStmt -
1553  *        transform a Create Cursor Statement
1554  *
1555  */
1556 static Query *
1557 transformCursorStmt(ParseState *pstate, SelectStmt *stmt)
1558 {
1559         Query      *qry;
1560
1561         qry = transformSelectStmt(pstate, stmt);
1562
1563         qry->into = stmt->portalname;
1564         qry->isTemp = stmt->istemp;
1565         qry->isPortal = TRUE;
1566         qry->isBinary = stmt->binary;           /* internal portal */
1567
1568         return qry;
1569 }
1570
1571 /*
1572  * tranformAlterTableStmt -
1573  *      transform an Alter Table Statement
1574  *
1575  */
1576 static Query *
1577 transformAlterTableStmt(ParseState *pstate, AlterTableStmt *stmt)
1578 {
1579         Query      *qry;
1580
1581         qry = makeNode(Query);
1582         qry->commandType = CMD_UTILITY;
1583
1584         /*
1585          * The only subtypes that currently have special handling are 'A'dd
1586          * column and Add 'C'onstraint.  In addition, right now only Foreign
1587          * Key 'C'onstraints have a special transformation.
1588          *
1589          */
1590         switch (stmt->subtype)
1591         {
1592                 case 'A':
1593                         transformColumnType(pstate, (ColumnDef *) stmt->def);
1594                         break;
1595                 case 'C':
1596                         if (stmt->def && nodeTag(stmt->def) == T_FkConstraint)
1597                         {
1598                                 CreateTrigStmt *fk_trigger;
1599                                 List       *fk_attr;
1600                                 List       *pk_attr;
1601                                 Ident      *id;
1602                                 FkConstraint *fkconstraint;
1603
1604                                 extras_after = NIL;
1605                                 elog(NOTICE, "ALTER TABLE ... ADD CONSTRAINT will create implicit trigger(s) for FOREIGN KEY check(s)");
1606
1607                                 fkconstraint = (FkConstraint *) stmt->def;
1608
1609                                 /*
1610                                  * If the constraint has no name, set it to <unnamed>
1611                                  *
1612                                  */
1613                                 if (fkconstraint->constr_name == NULL)
1614                                         fkconstraint->constr_name = "<unnamed>";
1615
1616                                 /*
1617                                  * If the attribute list for the referenced table was
1618                                  * omitted, lookup for the definition of the primary key
1619                                  *
1620                                  */
1621                                 if (fkconstraint->fk_attrs != NIL && fkconstraint->pk_attrs == NIL)
1622                                         transformFkeyGetPrimaryKey(fkconstraint);
1623
1624                                 /*
1625                                  * Build a CREATE CONSTRAINT TRIGGER statement for the
1626                                  * CHECK action.
1627                                  *
1628                                  */
1629                                 fk_trigger = (CreateTrigStmt *) makeNode(CreateTrigStmt);
1630                                 fk_trigger->trigname = fkconstraint->constr_name;
1631                                 fk_trigger->relname = stmt->relname;
1632                                 fk_trigger->funcname = "RI_FKey_check_ins";
1633                                 fk_trigger->before = false;
1634                                 fk_trigger->row = true;
1635                                 fk_trigger->actions[0] = 'i';
1636                                 fk_trigger->actions[1] = 'u';
1637                                 fk_trigger->actions[2] = '\0';
1638                                 fk_trigger->lang = NULL;
1639                                 fk_trigger->text = NULL;
1640
1641                                 fk_trigger->attr = NIL;
1642                                 fk_trigger->when = NULL;
1643                                 fk_trigger->isconstraint = true;
1644                                 fk_trigger->deferrable = fkconstraint->deferrable;
1645                                 fk_trigger->initdeferred = fkconstraint->initdeferred;
1646                                 fk_trigger->constrrelname = fkconstraint->pktable_name;
1647
1648                                 fk_trigger->args = NIL;
1649                                 fk_trigger->args = lappend(fk_trigger->args,
1650                                                                                    fkconstraint->constr_name);
1651                                 fk_trigger->args = lappend(fk_trigger->args,
1652                                                                                    stmt->relname);
1653                                 fk_trigger->args = lappend(fk_trigger->args,
1654                                                                                    fkconstraint->pktable_name);
1655                                 fk_trigger->args = lappend(fk_trigger->args,
1656                                                                                    fkconstraint->match_type);
1657                                 fk_attr = fkconstraint->fk_attrs;
1658                                 pk_attr = fkconstraint->pk_attrs;
1659                                 if (length(fk_attr) != length(pk_attr))
1660                                 {
1661                                         elog(NOTICE, "Illegal FOREIGN KEY definition REFERENCES \"%s\"",
1662                                                  fkconstraint->pktable_name);
1663                                         elog(ERROR, "number of key attributes in referenced table must be equal to foreign key");
1664                                 }
1665                                 while (fk_attr != NIL)
1666                                 {
1667                                         id = (Ident *) lfirst(fk_attr);
1668                                         fk_trigger->args = lappend(fk_trigger->args, id->name);
1669
1670                                         id = (Ident *) lfirst(pk_attr);
1671                                         fk_trigger->args = lappend(fk_trigger->args, id->name);
1672
1673                                         fk_attr = lnext(fk_attr);
1674                                         pk_attr = lnext(pk_attr);
1675                                 }
1676
1677                                 extras_after = lappend(extras_after, (Node *) fk_trigger);
1678
1679                                 /*
1680                                  * Build a CREATE CONSTRAINT TRIGGER statement for the ON
1681                                  * DELETE action fired on the PK table !!!
1682                                  *
1683                                  */
1684                                 fk_trigger = (CreateTrigStmt *) makeNode(CreateTrigStmt);
1685                                 fk_trigger->trigname = fkconstraint->constr_name;
1686                                 fk_trigger->relname = fkconstraint->pktable_name;
1687                                 switch ((fkconstraint->actions & FKCONSTR_ON_DELETE_MASK)
1688                                                 >> FKCONSTR_ON_DELETE_SHIFT)
1689                                 {
1690                                         case FKCONSTR_ON_KEY_NOACTION:
1691                                                 fk_trigger->funcname = "RI_FKey_noaction_del";
1692                                                 break;
1693                                         case FKCONSTR_ON_KEY_RESTRICT:
1694                                                 fk_trigger->funcname = "RI_FKey_restrict_del";
1695                                                 break;
1696                                         case FKCONSTR_ON_KEY_CASCADE:
1697                                                 fk_trigger->funcname = "RI_FKey_cascade_del";
1698                                                 break;
1699                                         case FKCONSTR_ON_KEY_SETNULL:
1700                                                 fk_trigger->funcname = "RI_FKey_setnull_del";
1701                                                 break;
1702                                         case FKCONSTR_ON_KEY_SETDEFAULT:
1703                                                 fk_trigger->funcname = "RI_FKey_setdefault_del";
1704                                                 break;
1705                                         default:
1706                                                 elog(ERROR, "Only one ON DELETE action can be specified for FOREIGN KEY constraint");
1707                                                 break;
1708                                 }
1709                                 fk_trigger->before = false;
1710                                 fk_trigger->row = true;
1711                                 fk_trigger->actions[0] = 'd';
1712                                 fk_trigger->actions[1] = '\0';
1713                                 fk_trigger->lang = NULL;
1714                                 fk_trigger->text = NULL;
1715
1716                                 fk_trigger->attr = NIL;
1717                                 fk_trigger->when = NULL;
1718                                 fk_trigger->isconstraint = true;
1719                                 fk_trigger->deferrable = fkconstraint->deferrable;
1720                                 fk_trigger->initdeferred = fkconstraint->initdeferred;
1721                                 fk_trigger->constrrelname = stmt->relname;
1722
1723                                 fk_trigger->args = NIL;
1724                                 fk_trigger->args = lappend(fk_trigger->args,
1725                                                                                    fkconstraint->constr_name);
1726                                 fk_trigger->args = lappend(fk_trigger->args,
1727                                                                                    stmt->relname);
1728                                 fk_trigger->args = lappend(fk_trigger->args,
1729                                                                                    fkconstraint->pktable_name);
1730                                 fk_trigger->args = lappend(fk_trigger->args,
1731                                                                                    fkconstraint->match_type);
1732                                 fk_attr = fkconstraint->fk_attrs;
1733                                 pk_attr = fkconstraint->pk_attrs;
1734                                 while (fk_attr != NIL)
1735                                 {
1736                                         id = (Ident *) lfirst(fk_attr);
1737                                         fk_trigger->args = lappend(fk_trigger->args, id->name);
1738
1739                                         id = (Ident *) lfirst(pk_attr);
1740                                         fk_trigger->args = lappend(fk_trigger->args, id->name);
1741
1742                                         fk_attr = lnext(fk_attr);
1743                                         pk_attr = lnext(pk_attr);
1744                                 }
1745
1746                                 extras_after = lappend(extras_after, (Node *) fk_trigger);
1747
1748                                 /*
1749                                  * Build a CREATE CONSTRAINT TRIGGER statement for the ON
1750                                  * UPDATE action fired on the PK table !!!
1751                                  *
1752                                  */
1753                                 fk_trigger = (CreateTrigStmt *) makeNode(CreateTrigStmt);
1754                                 fk_trigger->trigname = fkconstraint->constr_name;
1755                                 fk_trigger->relname = fkconstraint->pktable_name;
1756                                 switch ((fkconstraint->actions & FKCONSTR_ON_UPDATE_MASK)
1757                                                 >> FKCONSTR_ON_UPDATE_SHIFT)
1758                                 {
1759                                         case FKCONSTR_ON_KEY_NOACTION:
1760                                                 fk_trigger->funcname = "RI_FKey_noaction_upd";
1761                                                 break;
1762                                         case FKCONSTR_ON_KEY_RESTRICT:
1763                                                 fk_trigger->funcname = "RI_FKey_restrict_upd";
1764                                                 break;
1765                                         case FKCONSTR_ON_KEY_CASCADE:
1766                                                 fk_trigger->funcname = "RI_FKey_cascade_upd";
1767                                                 break;
1768                                         case FKCONSTR_ON_KEY_SETNULL:
1769                                                 fk_trigger->funcname = "RI_FKey_setnull_upd";
1770                                                 break;
1771                                         case FKCONSTR_ON_KEY_SETDEFAULT:
1772                                                 fk_trigger->funcname = "RI_FKey_setdefault_upd";
1773                                                 break;
1774                                         default:
1775                                                 elog(ERROR, "Only one ON UPDATE action can be specified for FOREIGN KEY constraint");
1776                                                 break;
1777                                 }
1778                                 fk_trigger->before = false;
1779                                 fk_trigger->row = true;
1780                                 fk_trigger->actions[0] = 'u';
1781                                 fk_trigger->actions[1] = '\0';
1782                                 fk_trigger->lang = NULL;
1783                                 fk_trigger->text = NULL;
1784
1785                                 fk_trigger->attr = NIL;
1786                                 fk_trigger->when = NULL;
1787                                 fk_trigger->isconstraint = true;
1788                                 fk_trigger->deferrable = fkconstraint->deferrable;
1789                                 fk_trigger->initdeferred = fkconstraint->initdeferred;
1790                                 fk_trigger->constrrelname = stmt->relname;
1791
1792                                 fk_trigger->args = NIL;
1793                                 fk_trigger->args = lappend(fk_trigger->args,
1794                                                                                    fkconstraint->constr_name);
1795                                 fk_trigger->args = lappend(fk_trigger->args,
1796                                                                                    stmt->relname);
1797                                 fk_trigger->args = lappend(fk_trigger->args,
1798                                                                                    fkconstraint->pktable_name);
1799                                 fk_trigger->args = lappend(fk_trigger->args,
1800                                                                                    fkconstraint->match_type);
1801                                 fk_attr = fkconstraint->fk_attrs;
1802                                 pk_attr = fkconstraint->pk_attrs;
1803                                 while (fk_attr != NIL)
1804                                 {
1805                                         id = (Ident *) lfirst(fk_attr);
1806                                         fk_trigger->args = lappend(fk_trigger->args, id->name);
1807
1808                                         id = (Ident *) lfirst(pk_attr);
1809                                         fk_trigger->args = lappend(fk_trigger->args, id->name);
1810
1811                                         fk_attr = lnext(fk_attr);
1812                                         pk_attr = lnext(pk_attr);
1813                                 }
1814
1815                                 extras_after = lappend(extras_after, (Node *) fk_trigger);
1816                         }
1817                         break;
1818                 default:
1819                         break;
1820         }
1821         qry->utilityStmt = (Node *) stmt;
1822         return qry;
1823 }
1824
1825
1826 /* This function steps through the tree
1827  * built up by the select_w_o_sort rule
1828  * and builds a list of all SelectStmt Nodes found
1829  * The built up list is handed back in **select_list.
1830  * If one of the SelectStmt Nodes has the 'unionall' flag
1831  * set to true *unionall_present hands back 'true' */
1832 void
1833 create_select_list(Node *ptr, List **select_list, bool *unionall_present)
1834 {
1835         if (IsA(ptr, SelectStmt))
1836         {
1837                 *select_list = lappend(*select_list, ptr);
1838                 if (((SelectStmt *) ptr)->unionall == TRUE)
1839                         *unionall_present = TRUE;
1840                 return;
1841         }
1842
1843         /* Recursively call for all arguments. A NOT expr has no lexpr! */
1844         if (((A_Expr *) ptr)->lexpr != NULL)
1845                 create_select_list(((A_Expr *) ptr)->lexpr, select_list, unionall_present);
1846         create_select_list(((A_Expr *) ptr)->rexpr, select_list, unionall_present);
1847 }
1848
1849 /* Changes the A_Expr Nodes to Expr Nodes and exchanges ANDs and ORs.
1850  * The reason for the exchange is easy: We implement INTERSECTs and EXCEPTs
1851  * by rewriting these queries to semantically equivalent queries that use
1852  * IN and NOT IN subselects. To be able to use all three operations
1853  * (UNIONs INTERSECTs and EXCEPTs) in one complex query we have to
1854  * translate the queries into Disjunctive Normal Form (DNF). Unfortunately
1855  * there is no function 'dnfify' but there is a function 'cnfify'
1856  * which produces DNF when we exchange ANDs and ORs before calling
1857  * 'cnfify' and exchange them back in the result.
1858  *
1859  * If an EXCEPT or INTERSECT is present *intersect_present
1860  * hands back 'true' */
1861 Node *
1862 A_Expr_to_Expr(Node *ptr, bool *intersect_present)
1863 {
1864         Node       *result = NULL;
1865
1866         switch (nodeTag(ptr))
1867         {
1868                 case T_A_Expr:
1869                         {
1870                                 A_Expr     *a = (A_Expr *) ptr;
1871
1872                                 switch (a->oper)
1873                                 {
1874                                         case AND:
1875                                                 {
1876                                                         Expr       *expr = makeNode(Expr);
1877                                                         Node       *lexpr = A_Expr_to_Expr(((A_Expr *) ptr)->lexpr, intersect_present);
1878                                                         Node       *rexpr = A_Expr_to_Expr(((A_Expr *) ptr)->rexpr, intersect_present);
1879
1880                                                         *intersect_present = TRUE;
1881
1882                                                         expr->typeOid = BOOLOID;
1883                                                         expr->opType = OR_EXPR;
1884                                                         expr->args = makeList(lexpr, rexpr, -1);
1885                                                         result = (Node *) expr;
1886                                                         break;
1887                                                 }
1888                                         case OR:
1889                                                 {
1890                                                         Expr       *expr = makeNode(Expr);
1891                                                         Node       *lexpr = A_Expr_to_Expr(((A_Expr *) ptr)->lexpr, intersect_present);
1892                                                         Node       *rexpr = A_Expr_to_Expr(((A_Expr *) ptr)->rexpr, intersect_present);
1893
1894                                                         expr->typeOid = BOOLOID;
1895                                                         expr->opType = AND_EXPR;
1896                                                         expr->args = makeList(lexpr, rexpr, -1);
1897                                                         result = (Node *) expr;
1898                                                         break;
1899                                                 }
1900                                         case NOT:
1901                                                 {
1902                                                         Expr       *expr = makeNode(Expr);
1903                                                         Node       *rexpr = A_Expr_to_Expr(((A_Expr *) ptr)->rexpr, intersect_present);
1904
1905                                                         expr->typeOid = BOOLOID;
1906                                                         expr->opType = NOT_EXPR;
1907                                                         expr->args = makeList(rexpr, -1);
1908                                                         result = (Node *) expr;
1909                                                         break;
1910                                                 }
1911                                 }
1912                                 break;
1913                         }
1914                 default:
1915                         result = ptr;
1916         }
1917         return result;
1918 }
1919
1920 void
1921 CheckSelectForUpdate(Query *qry)
1922 {
1923         if (qry->unionClause != NULL)
1924                 elog(ERROR, "SELECT FOR UPDATE is not allowed with UNION/INTERSECT/EXCEPT clause");
1925         if (qry->distinctClause != NIL)
1926                 elog(ERROR, "SELECT FOR UPDATE is not allowed with DISTINCT clause");
1927         if (qry->groupClause != NIL)
1928                 elog(ERROR, "SELECT FOR UPDATE is not allowed with GROUP BY clause");
1929         if (qry->hasAggs)
1930                 elog(ERROR, "SELECT FOR UPDATE is not allowed with AGGREGATE");
1931 }
1932
1933 static void
1934 transformForUpdate(Query *qry, List *forUpdate)
1935 {
1936         List       *rowMark = NULL;
1937         RowMark    *newrm;
1938         List       *l;
1939         Index           i;
1940
1941         CheckSelectForUpdate(qry);
1942
1943         if (lfirst(forUpdate) == NULL)          /* all tables */
1944         {
1945                 i = 1;
1946                 foreach(l, qry->rtable)
1947                 {
1948                         newrm = makeNode(RowMark);
1949                         newrm->rti = i++;
1950                         newrm->info = ROW_MARK_FOR_UPDATE | ROW_ACL_FOR_UPDATE;
1951                         rowMark = lappend(rowMark, newrm);
1952                 }
1953                 qry->rowMark = nconc(qry->rowMark, rowMark);
1954                 return;
1955         }
1956
1957         foreach(l, forUpdate)
1958         {
1959                 char       *relname = lfirst(l);
1960                 List       *l2;
1961
1962                 i = 1;
1963                 foreach(l2, qry->rtable)
1964                 {
1965                         if (strcmp(((RangeTblEntry *) lfirst(l2))->eref->relname, relname) == 0)
1966                         {
1967                                 List       *l3;
1968
1969                                 foreach(l3, rowMark)
1970                                 {
1971                                         if (((RowMark *) lfirst(l3))->rti == i)         /* duplicate */
1972                                                 break;
1973                                 }
1974                                 if (l3 == NULL)
1975                                 {
1976                                         newrm = makeNode(RowMark);
1977                                         newrm->rti = i;
1978                                         newrm->info = ROW_MARK_FOR_UPDATE | ROW_ACL_FOR_UPDATE;
1979                                         rowMark = lappend(rowMark, newrm);
1980                                 }
1981                                 break;
1982                         }
1983                         i++;
1984                 }
1985                 if (l2 == NULL)
1986                         elog(ERROR, "FOR UPDATE: relation '%s' not found in FROM clause",
1987                                  relname);
1988         }
1989
1990         qry->rowMark = rowMark;
1991 }
1992
1993
1994 /*
1995  * transformFkeyGetPrimaryKey -
1996  *
1997  *      Try to find the primary key attributes of a referenced table if
1998  *      the column list in the REFERENCES specification was omitted.
1999  *
2000  */
2001 static void
2002 transformFkeyGetPrimaryKey(FkConstraint *fkconstraint)
2003 {
2004         Relation        pkrel;
2005         Form_pg_attribute *pkrel_attrs;
2006         Relation        indexRd;
2007         HeapScanDesc indexSd;
2008         ScanKeyData key;
2009         HeapTuple       indexTup;
2010         Form_pg_index indexStruct = NULL;
2011         Ident      *pkattr;
2012         int                     pkattno;
2013         int                     i;
2014
2015         /* ----------
2016          * Open the referenced table and get the attributes list
2017          * ----------
2018          */
2019         pkrel = heap_openr(fkconstraint->pktable_name, AccessShareLock);
2020         if (pkrel == NULL)
2021                 elog(ERROR, "referenced table \"%s\" not found",
2022                          fkconstraint->pktable_name);
2023         pkrel_attrs = pkrel->rd_att->attrs;
2024
2025         /* ----------
2026          * Open pg_index and begin a scan for all indices defined on
2027          * the referenced table
2028          * ----------
2029          */
2030         indexRd = heap_openr(IndexRelationName, AccessShareLock);
2031         ScanKeyEntryInitialize(&key, 0, Anum_pg_index_indrelid,
2032                                                    F_OIDEQ,
2033                                                    ObjectIdGetDatum(pkrel->rd_id));
2034         indexSd = heap_beginscan(indexRd,       /* scan desc */
2035                                                          false,         /* scan backward flag */
2036                                                          SnapshotNow,           /* NOW snapshot */
2037                                                          1, /* number scan keys */
2038                                                          &key);         /* scan keys */
2039
2040         /* ----------
2041          * Fetch the index with indisprimary == true
2042          * ----------
2043          */
2044         while (HeapTupleIsValid(indexTup = heap_getnext(indexSd, 0)))
2045         {
2046                 indexStruct = (Form_pg_index) GETSTRUCT(indexTup);
2047
2048                 if (indexStruct->indisprimary)
2049                         break;
2050         }
2051
2052         /* ----------
2053          * Check that we found it
2054          * ----------
2055          */
2056         if (!HeapTupleIsValid(indexTup))
2057                 elog(ERROR, "PRIMARY KEY for referenced table \"%s\" not found",
2058                          fkconstraint->pktable_name);
2059
2060         /* ----------
2061          * Now build the list of PK attributes from the indkey definition
2062          * using the attribute names of the PK relation descriptor
2063          * ----------
2064          */
2065         for (i = 0; i < INDEX_MAX_KEYS && indexStruct->indkey[i] != 0; i++)
2066         {
2067                 pkattno = indexStruct->indkey[i];
2068                 pkattr = (Ident *) makeNode(Ident);
2069                 pkattr->name = nameout(&(pkrel_attrs[pkattno - 1]->attname));
2070                 pkattr->indirection = NIL;
2071                 pkattr->isRel = false;
2072
2073                 fkconstraint->pk_attrs = lappend(fkconstraint->pk_attrs, pkattr);
2074         }
2075
2076         /* ----------
2077          * End index scan and close relations
2078          * ----------
2079          */
2080         heap_endscan(indexSd);
2081         heap_close(indexRd, AccessShareLock);
2082         heap_close(pkrel, AccessShareLock);
2083 }
2084
2085 /*
2086  * Preprocess a list of column constraint clauses
2087  * to attach constraint attributes to their primary constraint nodes
2088  * and detect inconsistent/misplaced constraint attributes.
2089  *
2090  * NOTE: currently, attributes are only supported for FOREIGN KEY primary
2091  * constraints, but someday they ought to be supported for other constraints.
2092  */
2093 static void
2094 transformConstraintAttrs(List *constraintList)
2095 {
2096         Node       *lastprimarynode = NULL;
2097         bool            saw_deferrability = false;
2098         bool            saw_initially = false;
2099         List       *clist;
2100
2101         foreach(clist, constraintList)
2102         {
2103                 Node       *node = lfirst(clist);
2104
2105                 if (!IsA(node, Constraint))
2106                 {
2107                         lastprimarynode = node;
2108                         /* reset flags for new primary node */
2109                         saw_deferrability = false;
2110                         saw_initially = false;
2111                 }
2112                 else
2113                 {
2114                         Constraint *con = (Constraint *) node;
2115
2116                         switch (con->contype)
2117                         {
2118                                 case CONSTR_ATTR_DEFERRABLE:
2119                                         if (lastprimarynode == NULL ||
2120                                                 !IsA(lastprimarynode, FkConstraint))
2121                                                 elog(ERROR, "Misplaced DEFERRABLE clause");
2122                                         if (saw_deferrability)
2123                                                 elog(ERROR, "Multiple DEFERRABLE/NOT DEFERRABLE clauses not allowed");
2124                                         saw_deferrability = true;
2125                                         ((FkConstraint *) lastprimarynode)->deferrable = true;
2126                                         break;
2127                                 case CONSTR_ATTR_NOT_DEFERRABLE:
2128                                         if (lastprimarynode == NULL ||
2129                                                 !IsA(lastprimarynode, FkConstraint))
2130                                                 elog(ERROR, "Misplaced NOT DEFERRABLE clause");
2131                                         if (saw_deferrability)
2132                                                 elog(ERROR, "Multiple DEFERRABLE/NOT DEFERRABLE clauses not allowed");
2133                                         saw_deferrability = true;
2134                                         ((FkConstraint *) lastprimarynode)->deferrable = false;
2135                                         if (saw_initially &&
2136                                                 ((FkConstraint *) lastprimarynode)->initdeferred)
2137                                                 elog(ERROR, "INITIALLY DEFERRED constraint must be DEFERRABLE");
2138                                         break;
2139                                 case CONSTR_ATTR_DEFERRED:
2140                                         if (lastprimarynode == NULL ||
2141                                                 !IsA(lastprimarynode, FkConstraint))
2142                                                 elog(ERROR, "Misplaced INITIALLY DEFERRED clause");
2143                                         if (saw_initially)
2144                                                 elog(ERROR, "Multiple INITIALLY IMMEDIATE/DEFERRED clauses not allowed");
2145                                         saw_initially = true;
2146                                         ((FkConstraint *) lastprimarynode)->initdeferred = true;
2147
2148                                         /*
2149                                          * If only INITIALLY DEFERRED appears, assume
2150                                          * DEFERRABLE
2151                                          */
2152                                         if (!saw_deferrability)
2153                                                 ((FkConstraint *) lastprimarynode)->deferrable = true;
2154                                         else if (!((FkConstraint *) lastprimarynode)->deferrable)
2155                                                 elog(ERROR, "INITIALLY DEFERRED constraint must be DEFERRABLE");
2156                                         break;
2157                                 case CONSTR_ATTR_IMMEDIATE:
2158                                         if (lastprimarynode == NULL ||
2159                                                 !IsA(lastprimarynode, FkConstraint))
2160                                                 elog(ERROR, "Misplaced INITIALLY IMMEDIATE clause");
2161                                         if (saw_initially)
2162                                                 elog(ERROR, "Multiple INITIALLY IMMEDIATE/DEFERRED clauses not allowed");
2163                                         saw_initially = true;
2164                                         ((FkConstraint *) lastprimarynode)->initdeferred = false;
2165                                         break;
2166                                 default:
2167                                         /* Otherwise it's not an attribute */
2168                                         lastprimarynode = node;
2169                                         /* reset flags for new primary node */
2170                                         saw_deferrability = false;
2171                                         saw_initially = false;
2172                                         break;
2173                         }
2174                 }
2175         }
2176 }
2177
2178 /*
2179  * Special handling of type definition for a column
2180  */
2181 static void
2182 transformColumnType(ParseState *pstate, ColumnDef *column)
2183 {
2184
2185         /*
2186          * If the column doesn't have an explicitly specified typmod, check to
2187          * see if we want to insert a default length.
2188          *
2189          * Note that we deliberately do NOT look at array or set information
2190          * here; "numeric[]" needs the same default typmod as "numeric".
2191          */
2192         if (column->typename->typmod == -1)
2193         {
2194                 switch (typeTypeId(typenameType(column->typename->name)))
2195                 {
2196                                 case BPCHAROID:
2197                                 /* "char" -> "char(1)" */
2198                                 column->typename->typmod = VARHDRSZ + 1;
2199                                 break;
2200                         case NUMERICOID:
2201                                 column->typename->typmod = VARHDRSZ +
2202                                         ((NUMERIC_DEFAULT_PRECISION << 16) | NUMERIC_DEFAULT_SCALE);
2203                                 break;
2204                 }
2205         }
2206 }