OSDN Git Service

Remove unused #includes in *.c files.
[pg-rex/syncrep.git] / src / backend / parser / analyze.c
1 /*-------------------------------------------------------------------------
2  *
3  * analyze.c
4  *        transform the parse tree into a query tree
5  *
6  * Copyright (c) 1994, Regents of the University of California
7  *
8  *      $Id: analyze.c,v 1.113 1999/07/15 22:39:33 momjian Exp $
9  *
10  *-------------------------------------------------------------------------
11  */
12
13 #include <stdio.h>
14 #include <stdlib.h>
15 #include <stdarg.h>
16 #include <string.h>
17
18 #include "postgres.h"
19 #include "access/heapam.h"
20 #include "nodes/makefuncs.h"
21 #include "parser/analyze.h"
22 #include "parser/parse_agg.h"
23 #include "parser/parse_clause.h"
24 #include "parser/parse_relation.h"
25 #include "parser/parse_target.h"
26 #include "catalog/pg_type.h"
27 #include "parse.h"
28
29 #include "utils/builtins.h"
30
31 static Query *transformStmt(ParseState *pstate, Node *stmt);
32 static Query *transformDeleteStmt(ParseState *pstate, DeleteStmt *stmt);
33 static Query *transformInsertStmt(ParseState *pstate, InsertStmt *stmt);
34 static Query *transformIndexStmt(ParseState *pstate, IndexStmt *stmt);
35 static Query *transformExtendStmt(ParseState *pstate, ExtendStmt *stmt);
36 static Query *transformRuleStmt(ParseState *query, RuleStmt *stmt);
37 static Query *transformSelectStmt(ParseState *pstate, SelectStmt *stmt);
38 static Query *transformUpdateStmt(ParseState *pstate, UpdateStmt *stmt);
39 static Query *transformCursorStmt(ParseState *pstate, SelectStmt *stmt);
40 static Query *transformCreateStmt(ParseState *pstate, CreateStmt *stmt);
41
42 static void transformForUpdate(Query *qry, List *forUpdate);
43 void            CheckSelectForUpdate(Query *qry);
44
45 List       *extras_before = NIL;
46 List       *extras_after = NIL;
47
48 /*
49  * parse_analyze -
50  *        analyze a list of parse trees and transform them if necessary.
51  *
52  * Returns a list of transformed parse trees. Optimizable statements are
53  * all transformed to Query while the rest stays the same.
54  *
55  */
56 List *
57 parse_analyze(List *pl, ParseState *parentParseState)
58 {
59         List       *result = NIL;
60         ParseState *pstate;
61         Query      *parsetree;
62
63         while (pl != NIL)
64         {
65                 pstate = make_parsestate(parentParseState);
66                 parsetree = transformStmt(pstate, lfirst(pl));
67                 if (pstate->p_target_relation != NULL)
68                         heap_close(pstate->p_target_relation);
69
70                 while (extras_before != NIL)
71                 {
72                         result = lappend(result,
73                                                    transformStmt(pstate, lfirst(extras_before)));
74                         if (pstate->p_target_relation != NULL)
75                                 heap_close(pstate->p_target_relation);
76                         extras_before = lnext(extras_before);
77                 }
78
79                 result = lappend(result, parsetree);
80
81                 while (extras_after != NIL)
82                 {
83                         result = lappend(result,
84                                                          transformStmt(pstate, lfirst(extras_after)));
85                         if (pstate->p_target_relation != NULL)
86                                 heap_close(pstate->p_target_relation);
87                         extras_after = lnext(extras_after);
88                 }
89
90                 pl = lnext(pl);
91                 pfree(pstate);
92         }
93
94         return result;
95 }
96
97 /*
98  * transformStmt -
99  *        transform a Parse tree. If it is an optimizable statement, turn it
100  *        into a Query tree.
101  */
102 static Query *
103 transformStmt(ParseState *pstate, Node *parseTree)
104 {
105         Query      *result = NULL;
106
107         switch (nodeTag(parseTree))
108         {
109                         /*------------------------
110                          *      Non-optimizable statements
111                          *------------------------
112                          */
113                 case T_CreateStmt:
114                         result = transformCreateStmt(pstate, (CreateStmt *) parseTree);
115                         break;
116
117                 case T_IndexStmt:
118                         result = transformIndexStmt(pstate, (IndexStmt *) parseTree);
119                         break;
120
121                 case T_ExtendStmt:
122                         result = transformExtendStmt(pstate, (ExtendStmt *) parseTree);
123                         break;
124
125                 case T_RuleStmt:
126                         result = transformRuleStmt(pstate, (RuleStmt *) parseTree);
127                         break;
128
129                 case T_ViewStmt:
130                         {
131                                 ViewStmt   *n = (ViewStmt *) parseTree;
132
133                                 n->query = (Query *) transformStmt(pstate, (Node *) n->query);
134                                 result = makeNode(Query);
135                                 result->commandType = CMD_UTILITY;
136                                 result->utilityStmt = (Node *) n;
137                         }
138                         break;
139
140                 case T_VacuumStmt:
141                         {
142                                 MemoryContext oldcontext;
143
144                                 /*
145                                  * make sure that this Query is allocated in TopMemory
146                                  * context because vacuum spans transactions and we don't
147                                  * want to lose the vacuum Query due to end-of-transaction
148                                  * free'ing
149                                  */
150                                 oldcontext = MemoryContextSwitchTo(TopMemoryContext);
151                                 result = makeNode(Query);
152                                 result->commandType = CMD_UTILITY;
153                                 result->utilityStmt = (Node *) parseTree;
154                                 MemoryContextSwitchTo(oldcontext);
155                                 break;
156
157                         }
158                 case T_ExplainStmt:
159                         {
160                                 ExplainStmt *n = (ExplainStmt *) parseTree;
161
162                                 result = makeNode(Query);
163                                 result->commandType = CMD_UTILITY;
164                                 n->query = transformStmt(pstate, (Node *) n->query);
165                                 result->utilityStmt = (Node *) parseTree;
166                         }
167                         break;
168
169                         /*------------------------
170                          *      Optimizable statements
171                          *------------------------
172                          */
173                 case T_InsertStmt:
174                         result = transformInsertStmt(pstate, (InsertStmt *) parseTree);
175                         break;
176
177                 case T_DeleteStmt:
178                         result = transformDeleteStmt(pstate, (DeleteStmt *) parseTree);
179                         break;
180
181                 case T_UpdateStmt:
182                         result = transformUpdateStmt(pstate, (UpdateStmt *) parseTree);
183                         break;
184
185                 case T_SelectStmt:
186                         if (!((SelectStmt *) parseTree)->portalname)
187                         {
188                                 result = transformSelectStmt(pstate, (SelectStmt *) parseTree);
189                                 result->limitOffset = ((SelectStmt *) parseTree)->limitOffset;
190                                 result->limitCount = ((SelectStmt *) parseTree)->limitCount;
191                         }
192                         else
193                                 result = transformCursorStmt(pstate, (SelectStmt *) parseTree);
194                         break;
195
196                 default:
197
198                         /*
199                          * other statments don't require any transformation-- just
200                          * return the original parsetree, yea!
201                          */
202                         result = makeNode(Query);
203                         result->commandType = CMD_UTILITY;
204                         result->utilityStmt = (Node *) parseTree;
205                         break;
206         }
207         return result;
208 }
209
210 /*
211  * transformDeleteStmt -
212  *        transforms a Delete Statement
213  */
214 static Query *
215 transformDeleteStmt(ParseState *pstate, DeleteStmt *stmt)
216 {
217         Query      *qry = makeNode(Query);
218
219         qry->commandType = CMD_DELETE;
220
221         /* set up a range table */
222         makeRangeTable(pstate, stmt->relname, NULL, NULL);
223
224         qry->uniqueFlag = NULL;
225
226         /* fix where clause */
227         qry->qual = transformWhereClause(pstate, stmt->whereClause, NULL);
228         qry->hasSubLinks = pstate->p_hasSubLinks;
229
230         qry->rtable = pstate->p_rtable;
231         qry->resultRelation = refnameRangeTablePosn(pstate, stmt->relname, NULL);
232
233         qry->hasAggs = pstate->p_hasAggs;
234         if (pstate->p_hasAggs)
235                 parseCheckAggregates(pstate, qry);
236
237         return (Query *) qry;
238 }
239
240 /*
241  * transformInsertStmt -
242  *        transform an Insert Statement
243  */
244 static Query *
245 transformInsertStmt(ParseState *pstate, InsertStmt *stmt)
246 {
247         Query      *qry = makeNode(Query);      /* make a new query tree */
248         List       *icolumns;
249
250         qry->commandType = CMD_INSERT;
251         pstate->p_is_insert = true;
252
253         /* set up a range table */
254         makeRangeTable(pstate, stmt->relname, stmt->fromClause, NULL);
255
256         qry->uniqueFlag = stmt->unique;
257
258         /* fix the target list */
259         icolumns = pstate->p_insert_columns = makeTargetNames(pstate, stmt->cols);
260
261         qry->targetList = transformTargetList(pstate, stmt->targetList);
262
263         /* DEFAULT handling */
264         if (length(qry->targetList) < pstate->p_target_relation->rd_att->natts &&
265                 pstate->p_target_relation->rd_att->constr &&
266                 pstate->p_target_relation->rd_att->constr->num_defval > 0)
267         {
268                 Form_pg_attribute *att = pstate->p_target_relation->rd_att->attrs;
269                 AttrDefault *defval = pstate->p_target_relation->rd_att->constr->defval;
270                 int                     ndef = pstate->p_target_relation->rd_att->constr->num_defval;
271
272                 /*
273                  * if stmt->cols == NIL then makeTargetNames returns list of all
274                  * attrs. May have to shorten icolumns list...
275                  */
276                 if (stmt->cols == NIL)
277                 {
278                         List       *extrl;
279                         int                     i = length(qry->targetList);
280
281                         foreach(extrl, icolumns)
282                         {
283
284                                 /*
285                                  * decrements first, so if we started with zero items it
286                                  * will now be negative
287                                  */
288                                 if (--i <= 0)
289                                         break;
290                         }
291
292                         /*
293                          * this an index into the targetList, so make sure we had one
294                          * to start...
295                          */
296                         if (i >= 0)
297                         {
298                                 freeList(lnext(extrl));
299                                 lnext(extrl) = NIL;
300                         }
301                         else
302                                 icolumns = NIL;
303                 }
304
305                 while (ndef-- > 0)
306                 {
307                         List       *tl;
308                         Ident      *id;
309                         TargetEntry *te;
310
311                         foreach(tl, icolumns)
312                         {
313                                 id = (Ident *) lfirst(tl);
314                                 if (namestrcmp(&(att[defval[ndef].adnum - 1]->attname), id->name) == 0)
315                                         break;
316                         }
317                         if (tl != NIL)          /* something given for this attr */
318                                 continue;
319
320                         /*
321                          * Nothing given for this attr with DEFAULT expr, so add new
322                          * TargetEntry to qry->targetList. Note, that we set resno to
323                          * defval[ndef].adnum: it's what
324                          * transformTargetList()->make_targetlist_expr() does for
325                          * INSERT ... SELECT. But for INSERT ... VALUES
326                          * pstate->p_last_resno is used. It doesn't matter for
327                          * "normal" using (planner creates proper target list in
328                          * preptlist.c), but may break RULEs in some way. It seems
329                          * better to create proper target list here...
330                          */
331                         te = makeTargetEntry(makeResdom(defval[ndef].adnum,
332                                                                    att[defval[ndef].adnum - 1]->atttypid,
333                                                                   att[defval[ndef].adnum - 1]->atttypmod,
334                            pstrdup(nameout(&(att[defval[ndef].adnum - 1]->attname))),
335                                                                                         0, 0, false),
336                                                           (Node *) stringToNode(defval[ndef].adbin));
337                         qry->targetList = lappend(qry->targetList, te);
338                 }
339         }
340
341         /* fix where clause */
342         qry->qual = transformWhereClause(pstate, stmt->whereClause, NULL);
343
344         /*
345          * The havingQual has a similar meaning as "qual" in the where
346          * statement. So we can easily use the code from the "where clause"
347          * with some additional traversals done in
348          * .../optimizer/plan/planner.c
349          */
350         qry->havingQual = transformWhereClause(pstate, stmt->havingClause, NULL);
351
352         qry->hasSubLinks = pstate->p_hasSubLinks;
353
354         /* now the range table will not change */
355         qry->rtable = pstate->p_rtable;
356         qry->resultRelation = refnameRangeTablePosn(pstate, stmt->relname, NULL);
357
358         qry->groupClause = transformGroupClause(pstate,
359                                                                                         stmt->groupClause,
360                                                                                         qry->targetList);
361
362         /* fix order clause */
363         qry->sortClause = transformSortClause(pstate,
364                                                                                   NIL,
365                                                                                   NIL,
366                                                                                   qry->targetList,
367                                                                                   qry->uniqueFlag);
368
369         qry->hasAggs = pstate->p_hasAggs;
370         if (pstate->p_hasAggs || qry->groupClause)
371                 parseCheckAggregates(pstate, qry);
372
373         /*
374          * The INSERT INTO ... SELECT ... could have a UNION in child, so
375          * unionClause may be false ,
376          */
377         qry->unionall = stmt->unionall;
378
379         /*
380          * Just hand through the unionClause and intersectClause. We will
381          * handle it in the function Except_Intersect_Rewrite()
382          */
383         qry->unionClause = stmt->unionClause;
384         qry->intersectClause = stmt->intersectClause;
385
386         /*
387          * If there is a havingQual but there are no aggregates, then there is
388          * something wrong with the query because having must contain
389          * aggregates in its expressions! Otherwise the query could have been
390          * formulated using the where clause.
391          */
392         if ((qry->hasAggs == false) && (qry->havingQual != NULL))
393         {
394                 elog(ERROR, "SELECT/HAVING requires aggregates to be valid");
395                 return (Query *) NIL;
396         }
397
398         if (stmt->forUpdate != NULL)
399                 transformForUpdate(qry, stmt->forUpdate);
400
401         return (Query *) qry;
402 }
403
404 /*
405  *      makeObjectName()
406  *
407  *      Create a name for an implicitly created index, sequence, constraint, etc.
408  *
409  *      The parameters are: the original table name, the original field name, and
410  *      a "type" string (such as "seq" or "pkey").  The field name and/or type
411  *      can be NULL if not relevant.
412  *
413  *      The result is a palloc'd string.
414  *
415  *      The basic result we want is "name1_name2_type", omitting "_name2" or
416  *      "_type" when those parameters are NULL.  However, we must generate
417  *      a name with less than NAMEDATALEN characters!  So, we truncate one or
418  *      both names if necessary to make a short-enough string.  The type part
419  *      is never truncated (so it had better be reasonably short).
420  *
421  *      To reduce the probability of collisions, we might someday add more
422  *      smarts to this routine, like including some "hash" characters computed
423  *      from the truncated characters.  Currently it seems best to keep it simple,
424  *      so that the generated names are easily predictable by a person.
425  */
426 static char *
427 makeObjectName(char *name1, char *name2, char *typename)
428 {
429         char       *name;
430         int                     overhead = 0;   /* chars needed for type and underscores */
431         int                     availchars;             /* chars available for name(s) */
432         int                     name1chars;             /* chars allocated to name1 */
433         int                     name2chars;             /* chars allocated to name2 */
434         int                     ndx;
435
436         name1chars = strlen(name1);
437         if (name2)
438         {
439                 name2chars = strlen(name2);
440                 overhead++;                             /* allow for separating underscore */
441         }
442         else
443                 name2chars = 0;
444         if (typename)
445                 overhead += strlen(typename) + 1;
446
447         availchars = NAMEDATALEN-1 - overhead;
448
449         /* If we must truncate,  preferentially truncate the longer name.
450          * This logic could be expressed without a loop, but it's simple and
451          * obvious as a loop.
452          */
453         while (name1chars + name2chars > availchars)
454         {
455                 if (name1chars > name2chars)
456                         name1chars--;
457                 else
458                         name2chars--;
459         }
460
461         /* Now construct the string using the chosen lengths */
462         name = palloc(name1chars + name2chars + overhead + 1);
463         strncpy(name, name1, name1chars);
464         ndx = name1chars;
465         if (name2)
466         {
467                 name[ndx++] = '_';
468                 strncpy(name+ndx, name2, name2chars);
469                 ndx += name2chars;
470         }
471         if (typename)
472         {
473                 name[ndx++] = '_';
474                 strcpy(name+ndx, typename);
475         }
476         else
477                 name[ndx] = '\0';
478
479         return name;
480 }
481
482 static char *
483 CreateIndexName(char *table_name, char *column_name, char *label, List *indices)
484 {
485         int                     pass = 0;
486         char       *iname = NULL;
487         List       *ilist;
488         char            typename[NAMEDATALEN];
489
490         /* The type name for makeObjectName is label, or labelN if that's
491          * necessary to prevent collisions among multiple indexes for the same
492          * table.  Note there is no check for collisions with already-existing
493          * indexes; this ought to be rethought someday.
494          */
495         strcpy(typename, label);
496
497         for (;;)
498         {
499                 iname = makeObjectName(table_name, column_name, typename);
500
501                 foreach(ilist, indices)
502                 {
503                         IndexStmt  *index = lfirst(ilist);
504                         if (strcasecmp(iname, index->idxname) == 0)
505                                 break;
506                 }
507                 /* ran through entire list? then no name conflict found so done */
508                 if (ilist == NIL)
509                         break;
510
511                 /* the last one conflicted, so try a new name component */
512                 pfree(iname);
513                 sprintf(typename, "%s%d", label, ++pass);
514         }
515
516         return iname;
517 }
518
519 /*
520  * transformCreateStmt -
521  *        transforms the "create table" statement
522  *        SQL92 allows constraints to be scattered all over, so thumb through
523  *         the columns and collect all constraints into one place.
524  *        If there are any implied indices (e.g. UNIQUE or PRIMARY KEY)
525  *         then expand those into multiple IndexStmt blocks.
526  *        - thomas 1997-12-02
527  */
528 static Query *
529 transformCreateStmt(ParseState *pstate, CreateStmt *stmt)
530 {
531         Query      *q;
532         List       *elements;
533         Node       *element;
534         List       *columns;
535         List       *dlist;
536         ColumnDef  *column;
537         List       *constraints,
538                            *clist;
539         Constraint *constraint;
540         List       *keys;
541         Ident      *key;
542         List       *blist = NIL;        /* "before list" of things to do before
543                                                                  * creating the table */
544         List       *ilist = NIL;        /* "index list" of things to do after
545                                                                  * creating the table */
546         IndexStmt  *index,
547                            *pkey = NULL;
548         IndexElem  *iparam;
549
550         q = makeNode(Query);
551         q->commandType = CMD_UTILITY;
552
553         elements = stmt->tableElts;
554         constraints = stmt->constraints;
555         columns = NIL;
556         dlist = NIL;
557
558         while (elements != NIL)
559         {
560                 element = lfirst(elements);
561                 switch (nodeTag(element))
562                 {
563                         case T_ColumnDef:
564                                 column = (ColumnDef *) element;
565                                 columns = lappend(columns, column);
566
567                                 if (column->is_sequence)
568                                 {
569                                         char       *sname;
570                                         char       *cstring;
571                                         CreateSeqStmt *sequence;
572
573                                         sname = makeObjectName(stmt->relname, column->colname,
574                                                                                    "seq");
575                                         constraint = makeNode(Constraint);
576                                         constraint->contype = CONSTR_DEFAULT;
577                                         constraint->name = sname;
578                                         cstring = palloc(10 + strlen(constraint->name) + 3 + 1);
579                                         strcpy(cstring, "nextval('\"");
580                                         strcat(cstring, constraint->name);
581                                         strcat(cstring, "\"')");
582                                         constraint->def = cstring;
583                                         constraint->keys = NULL;
584
585                                         column->constraints = lappend(column->constraints, constraint);
586
587                                         constraint = makeNode(Constraint);
588                                         constraint->contype = CONSTR_UNIQUE;
589                                         constraint->name = makeObjectName(stmt->relname,
590                                                                                                           column->colname,
591                                                                                                           "key");
592                                         column->constraints = lappend(column->constraints, constraint);
593
594                                         sequence = makeNode(CreateSeqStmt);
595                                         sequence->seqname = pstrdup(sname);
596                                         sequence->options = NIL;
597
598                                         elog(NOTICE, "CREATE TABLE will create implicit sequence '%s' for SERIAL column '%s.%s'",
599                                           sequence->seqname, stmt->relname, column->colname);
600
601                                         blist = lcons(sequence, NIL);
602                                 }
603
604                                 if (column->constraints != NIL)
605                                 {
606                                         clist = column->constraints;
607                                         while (clist != NIL)
608                                         {
609                                                 constraint = lfirst(clist);
610                                                 switch (constraint->contype)
611                                                 {
612                                                         case CONSTR_NULL:
613
614                                                                 /*
615                                                                  * We should mark this explicitly, so we
616                                                                  * can tell if NULL and NOT NULL are both
617                                                                  * specified
618                                                                  */
619                                                                 if (column->is_not_null)
620                                                                         elog(ERROR, "CREATE TABLE/(NOT) NULL conflicting declaration"
621                                                                                  " for '%s.%s'", stmt->relname, column->colname);
622                                                                 column->is_not_null = FALSE;
623                                                                 break;
624
625                                                         case CONSTR_NOTNULL:
626                                                                 if (column->is_not_null)
627                                                                         elog(ERROR, "CREATE TABLE/NOT NULL already specified"
628                                                                                  " for '%s.%s'", stmt->relname, column->colname);
629                                                                 column->is_not_null = TRUE;
630                                                                 break;
631
632                                                         case CONSTR_DEFAULT:
633                                                                 if (column->defval != NULL)
634                                                                         elog(ERROR, "CREATE TABLE/DEFAULT multiple values specified"
635                                                                                  " for '%s.%s'", stmt->relname, column->colname);
636                                                                 column->defval = constraint->def;
637                                                                 break;
638
639                                                         case CONSTR_PRIMARY:
640                                                                 if (constraint->name == NULL)
641                                                                         constraint->name = makeObjectName(stmt->relname, NULL, "pkey");
642                                                                 if (constraint->keys == NIL)
643                                                                         constraint->keys = lappend(constraint->keys, column);
644                                                                 dlist = lappend(dlist, constraint);
645                                                                 break;
646
647                                                         case CONSTR_UNIQUE:
648                                                                 if (constraint->name == NULL)
649                                                                         constraint->name = makeObjectName(stmt->relname, column->colname, "key");
650                                                                 if (constraint->keys == NIL)
651                                                                         constraint->keys = lappend(constraint->keys, column);
652                                                                 dlist = lappend(dlist, constraint);
653                                                                 break;
654
655                                                         case CONSTR_CHECK:
656                                                                 constraints = lappend(constraints, constraint);
657                                                                 if (constraint->name == NULL)
658                                                                         constraint->name = makeObjectName(stmt->relname, column->colname, NULL);
659                                                                 break;
660
661                                                         default:
662                                                                 elog(ERROR, "parser: unrecognized constraint (internal error)", NULL);
663                                                                 break;
664                                                 }
665                                                 clist = lnext(clist);
666                                         }
667                                 }
668                                 break;
669
670                         case T_Constraint:
671                                 constraint = (Constraint *) element;
672                                 switch (constraint->contype)
673                                 {
674                                         case CONSTR_PRIMARY:
675                                                 if (constraint->name == NULL)
676                                                         constraint->name = makeObjectName(stmt->relname, NULL, "pkey");
677                                                 dlist = lappend(dlist, constraint);
678                                                 break;
679
680                                         case CONSTR_UNIQUE:
681                                                 dlist = lappend(dlist, constraint);
682                                                 break;
683
684                                         case CONSTR_CHECK:
685                                                 constraints = lappend(constraints, constraint);
686                                                 break;
687
688                                         case CONSTR_NOTNULL:
689                                         case CONSTR_DEFAULT:
690                                                 elog(ERROR, "parser: illegal context for constraint (internal error)", NULL);
691                                                 break;
692                                         default:
693                                                 elog(ERROR, "parser: unrecognized constraint (internal error)", NULL);
694                                                 break;
695                                 }
696                                 break;
697
698                         default:
699                                 elog(ERROR, "parser: unrecognized node (internal error)", NULL);
700                 }
701
702                 elements = lnext(elements);
703         }
704
705         stmt->tableElts = columns;
706         stmt->constraints = constraints;
707
708 /* Now run through the "deferred list" to complete the query transformation.
709  * For PRIMARY KEYs, mark each column as NOT NULL and create an index.
710  * For UNIQUE, create an index as for PRIMARY KEYS, but do not insist on NOT NULL.
711  *
712  * Note that this code does not currently look for all possible redundant cases
713  *      and either ignore or stop with warning. The create might fail later when
714  *      names for indices turn out to be duplicated, or a user might have specified
715  *      extra useless indices which might hurt performance. - thomas 1997-12-08
716  */
717         while (dlist != NIL)
718         {
719                 constraint = lfirst(dlist);
720                 Assert(nodeTag(constraint) == T_Constraint);
721                 Assert((constraint->contype == CONSTR_PRIMARY)
722                            || (constraint->contype == CONSTR_UNIQUE));
723
724                 index = makeNode(IndexStmt);
725
726                 index->unique = TRUE;
727                 index->primary = (constraint->contype == CONSTR_PRIMARY ? TRUE : FALSE);
728                 if (index->primary)
729                 {
730                         if (pkey != NULL)
731                                 elog(ERROR, "CREATE TABLE/PRIMARY KEY multiple primary keys"
732                                          " for table '%s' are not allowed", stmt->relname);
733                         pkey = (IndexStmt *) index;
734                 }
735
736                 if (constraint->name != NULL)
737                         index->idxname = pstrdup(constraint->name);
738                 else if (constraint->contype == CONSTR_PRIMARY)
739                         index->idxname = makeObjectName(stmt->relname, NULL, "pkey");
740                 else
741                         index->idxname = NULL;
742
743                 index->relname = stmt->relname;
744                 index->accessMethod = "btree";
745                 index->indexParams = NIL;
746                 index->withClause = NIL;
747                 index->whereClause = NULL;
748
749                 keys = constraint->keys;
750                 while (keys != NIL)
751                 {
752                         key = lfirst(keys);
753                         columns = stmt->tableElts;
754                         column = NULL;
755                         while (columns != NIL)
756                         {
757                                 column = lfirst(columns);
758                                 if (strcasecmp(column->colname, key->name) == 0)
759                                         break;
760                                 else
761                                         column = NULL;
762                                 columns = lnext(columns);
763                         }
764                         if (column == NULL)
765                                 elog(ERROR, "CREATE TABLE column '%s' in key does not exist", key->name);
766
767                         if (constraint->contype == CONSTR_PRIMARY)
768                                 column->is_not_null = TRUE;
769                         iparam = makeNode(IndexElem);
770                         iparam->name = pstrdup(column->colname);
771                         iparam->args = NIL;
772                         iparam->class = NULL;
773                         iparam->typename = NULL;
774                         index->indexParams = lappend(index->indexParams, iparam);
775
776                         if (index->idxname == NULL)
777                                 index->idxname = CreateIndexName(stmt->relname, iparam->name, "key", ilist);
778
779                         keys = lnext(keys);
780                 }
781
782                 if (index->idxname == NULL)     /* should not happen */
783                         elog(ERROR, "CREATE TABLE: failed to make implicit index name");
784
785                 ilist = lappend(ilist, index);
786                 dlist = lnext(dlist);
787         }
788
789 /* OK, now finally, if there is a primary key, then make sure that there aren't any redundant
790  * unique indices defined on columns. This can arise if someone specifies UNIQUE explicitly
791  * or if a SERIAL column was defined along with a table PRIMARY KEY constraint.
792  * - thomas 1999-05-11
793  */
794         if ((pkey != NULL) && (length(lfirst(pkey->indexParams)) == 1))
795         {
796                 dlist = ilist;
797                 ilist = NIL;
798                 while (dlist != NIL)
799                 {
800                         int                     keep = TRUE;
801
802                         index = lfirst(dlist);
803
804                         /*
805                          * has a single column argument, so might be a conflicting
806                          * index...
807                          */
808                         if ((index != pkey)
809                                 && (length(index->indexParams) == 1))
810                         {
811                                 char       *pname = ((IndexElem *) lfirst(index->indexParams))->name;
812                                 char       *iname = ((IndexElem *) lfirst(index->indexParams))->name;
813
814                                 /* same names? then don't keep... */
815                                 keep = (strcmp(iname, pname) != 0);
816                         }
817
818                         if (keep)
819                                 ilist = lappend(ilist, index);
820                         dlist = lnext(dlist);
821                 }
822         }
823
824         dlist = ilist;
825         while (dlist != NIL)
826         {
827                 index = lfirst(dlist);
828                 elog(NOTICE, "CREATE TABLE/%s will create implicit index '%s' for table '%s'",
829                          (index->primary ? "PRIMARY KEY" : "UNIQUE"),
830                          index->idxname, stmt->relname);
831                 dlist = lnext(dlist);
832         }
833
834         q->utilityStmt = (Node *) stmt;
835         extras_before = blist;
836         extras_after = ilist;
837
838         return q;
839 }       /* transformCreateStmt() */
840
841 /*
842  * transformIndexStmt -
843  *        transforms the qualification of the index statement
844  */
845 static Query *
846 transformIndexStmt(ParseState *pstate, IndexStmt *stmt)
847 {
848         Query      *qry;
849
850         qry = makeNode(Query);
851         qry->commandType = CMD_UTILITY;
852
853         /* take care of the where clause */
854         stmt->whereClause = transformWhereClause(pstate, stmt->whereClause, NULL);
855         qry->hasSubLinks = pstate->p_hasSubLinks;
856
857         stmt->rangetable = pstate->p_rtable;
858
859         qry->utilityStmt = (Node *) stmt;
860
861         return qry;
862 }
863
864 /*
865  * transformExtendStmt -
866  *        transform the qualifications of the Extend Index Statement
867  *
868  */
869 static Query *
870 transformExtendStmt(ParseState *pstate, ExtendStmt *stmt)
871 {
872         Query      *qry;
873
874         qry = makeNode(Query);
875         qry->commandType = CMD_UTILITY;
876
877         /* take care of the where clause */
878         stmt->whereClause = transformWhereClause(pstate, stmt->whereClause, NULL);
879         qry->hasSubLinks = pstate->p_hasSubLinks;
880
881         stmt->rangetable = pstate->p_rtable;
882
883         qry->utilityStmt = (Node *) stmt;
884         return qry;
885 }
886
887 /*
888  * transformRuleStmt -
889  *        transform a Create Rule Statement. The actions is a list of parse
890  *        trees which is transformed into a list of query trees.
891  */
892 static Query *
893 transformRuleStmt(ParseState *pstate, RuleStmt *stmt)
894 {
895         Query      *qry;
896         Query      *action;
897         List       *actions;
898
899         qry = makeNode(Query);
900         qry->commandType = CMD_UTILITY;
901
902         /*
903          * 'instead nothing' rules with a qualification need a query a
904          * rangetable so the rewrite handler can add the negated rule
905          * qualification to the original query. We create a query with the new
906          * command type CMD_NOTHING here that is treated special by the
907          * rewrite system.
908          */
909         if (stmt->actions == NIL)
910         {
911                 Query      *nothing_qry = makeNode(Query);
912
913                 nothing_qry->commandType = CMD_NOTHING;
914
915                 addRangeTableEntry(pstate, stmt->object->relname, "*CURRENT*",
916                                                    FALSE, FALSE);
917                 addRangeTableEntry(pstate, stmt->object->relname, "*NEW*",
918                                                    FALSE, FALSE);
919
920                 nothing_qry->rtable = pstate->p_rtable;
921
922                 stmt->actions = lappend(NIL, nothing_qry);
923         }
924
925         actions = stmt->actions;
926
927         /*
928          * transform each statment, like parse_analyze()
929          */
930         while (actions != NIL)
931         {
932
933                 /*
934                  * NOTE: 'CURRENT' must always have a varno equal to 1 and 'NEW'
935                  * equal to 2.
936                  */
937                 addRangeTableEntry(pstate, stmt->object->relname, "*CURRENT*",
938                                                    FALSE, FALSE);
939                 addRangeTableEntry(pstate, stmt->object->relname, "*NEW*",
940                                                    FALSE, FALSE);
941
942                 pstate->p_last_resno = 1;
943                 pstate->p_is_rule = true;               /* for expand all */
944                 pstate->p_hasAggs = false;
945
946                 action = (Query *) lfirst(actions);
947                 if (action->commandType != CMD_NOTHING)
948                         lfirst(actions) = transformStmt(pstate, lfirst(actions));
949                 actions = lnext(actions);
950         }
951
952         /* take care of the where clause */
953         stmt->whereClause = transformWhereClause(pstate, stmt->whereClause, NULL);
954         qry->hasSubLinks = pstate->p_hasSubLinks;
955
956         qry->utilityStmt = (Node *) stmt;
957         return qry;
958 }
959
960
961 /*
962  * transformSelectStmt -
963  *        transforms a Select Statement
964  *
965  */
966 static Query *
967 transformSelectStmt(ParseState *pstate, SelectStmt *stmt)
968 {
969         Query      *qry = makeNode(Query);
970         Node       *qual;
971
972         qry->commandType = CMD_SELECT;
973
974         /* set up a range table */
975         makeRangeTable(pstate, NULL, stmt->fromClause, &qual);
976
977         qry->uniqueFlag = stmt->unique;
978
979         qry->into = stmt->into;
980         qry->isTemp = stmt->istemp;
981         qry->isPortal = FALSE;
982
983         qry->targetList = transformTargetList(pstate, stmt->targetList);
984
985         qry->qual = transformWhereClause(pstate, stmt->whereClause, qual);
986
987         /*
988          * The havingQual has a similar meaning as "qual" in the where
989          * statement. So we can easily use the code from the "where clause"
990          * with some additional traversals done in optimizer/plan/planner.c
991          */
992         qry->havingQual = transformWhereClause(pstate, stmt->havingClause, NULL);
993
994         qry->hasSubLinks = pstate->p_hasSubLinks;
995
996         qry->sortClause = transformSortClause(pstate,
997                                                                                   stmt->sortClause,
998                                                                                   NIL,
999                                                                                   qry->targetList,
1000                                                                                   qry->uniqueFlag);
1001
1002         qry->groupClause = transformGroupClause(pstate,
1003                                                                                         stmt->groupClause,
1004                                                                                         qry->targetList);
1005         qry->rtable = pstate->p_rtable;
1006
1007         qry->hasAggs = pstate->p_hasAggs;
1008         if (pstate->p_hasAggs || qry->groupClause)
1009                 parseCheckAggregates(pstate, qry);
1010
1011         /*
1012          * The INSERT INTO ... SELECT ... could have a UNION in child, so
1013          * unionClause may be false
1014          */
1015         qry->unionall = stmt->unionall;
1016
1017         /*
1018          * Just hand through the unionClause and intersectClause. We will
1019          * handle it in the function Except_Intersect_Rewrite()
1020          */
1021         qry->unionClause = stmt->unionClause;
1022         qry->intersectClause = stmt->intersectClause;
1023
1024         /*
1025          * If there is a havingQual but there are no aggregates, then there is
1026          * something wrong with the query because having must contain
1027          * aggregates in its expressions! Otherwise the query could have been
1028          * formulated using the where clause.
1029          */
1030         if ((qry->hasAggs == false) && (qry->havingQual != NULL))
1031         {
1032                 elog(ERROR, "SELECT/HAVING requires aggregates to be valid");
1033                 return (Query *) NIL;
1034         }
1035
1036         if (stmt->forUpdate != NULL)
1037                 transformForUpdate(qry, stmt->forUpdate);
1038
1039         return (Query *) qry;
1040 }
1041
1042 /*
1043  * transformUpdateStmt -
1044  *        transforms an update statement
1045  *
1046  */
1047 static Query *
1048 transformUpdateStmt(ParseState *pstate, UpdateStmt *stmt)
1049 {
1050         Query      *qry = makeNode(Query);
1051
1052         qry->commandType = CMD_UPDATE;
1053         pstate->p_is_update = true;
1054
1055         /*
1056          * the FROM clause is non-standard SQL syntax. We used to be able to
1057          * do this with REPLACE in POSTQUEL so we keep the feature.
1058          */
1059         makeRangeTable(pstate, stmt->relname, stmt->fromClause, NULL);
1060
1061         qry->targetList = transformTargetList(pstate, stmt->targetList);
1062
1063         qry->qual = transformWhereClause(pstate, stmt->whereClause, NULL);
1064         qry->hasSubLinks = pstate->p_hasSubLinks;
1065
1066         qry->rtable = pstate->p_rtable;
1067
1068         qry->resultRelation = refnameRangeTablePosn(pstate, stmt->relname, NULL);
1069
1070         qry->hasAggs = pstate->p_hasAggs;
1071         if (pstate->p_hasAggs)
1072                 parseCheckAggregates(pstate, qry);
1073
1074         return (Query *) qry;
1075 }
1076
1077 /*
1078  * transformCursorStmt -
1079  *        transform a Create Cursor Statement
1080  *
1081  */
1082 static Query *
1083 transformCursorStmt(ParseState *pstate, SelectStmt *stmt)
1084 {
1085         Query      *qry;
1086
1087         qry = transformSelectStmt(pstate, stmt);
1088
1089         qry->into = stmt->portalname;
1090         qry->isTemp = stmt->istemp;
1091         qry->isPortal = TRUE;
1092         qry->isBinary = stmt->binary;           /* internal portal */
1093
1094         return qry;
1095 }
1096
1097 /* This function steps through the tree
1098  * built up by the select_w_o_sort rule
1099  * and builds a list of all SelectStmt Nodes found
1100  * The built up list is handed back in **select_list.
1101  * If one of the SelectStmt Nodes has the 'unionall' flag
1102  * set to true *unionall_present hands back 'true' */
1103 void
1104 create_select_list(Node *ptr, List **select_list, bool *unionall_present)
1105 {
1106         if (IsA(ptr, SelectStmt))
1107         {
1108                 *select_list = lappend(*select_list, ptr);
1109                 if (((SelectStmt *) ptr)->unionall == TRUE)
1110                         *unionall_present = TRUE;
1111                 return;
1112         }
1113
1114         /* Recursively call for all arguments. A NOT expr has no lexpr! */
1115         if (((A_Expr *) ptr)->lexpr != NULL)
1116                 create_select_list(((A_Expr *) ptr)->lexpr, select_list, unionall_present);
1117         create_select_list(((A_Expr *) ptr)->rexpr, select_list, unionall_present);
1118 }
1119
1120 /* Changes the A_Expr Nodes to Expr Nodes and exchanges ANDs and ORs.
1121  * The reason for the exchange is easy: We implement INTERSECTs and EXCEPTs
1122  * by rewriting these queries to semantically equivalent queries that use
1123  * IN and NOT IN subselects. To be able to use all three operations
1124  * (UNIONs INTERSECTs and EXCEPTs) in one complex query we have to
1125  * translate the queries into Disjunctive Normal Form (DNF). Unfortunately
1126  * there is no function 'dnfify' but there is a function 'cnfify'
1127  * which produces DNF when we exchange ANDs and ORs before calling
1128  * 'cnfify' and exchange them back in the result.
1129  *
1130  * If an EXCEPT or INTERSECT is present *intersect_present
1131  * hands back 'true' */
1132 Node *
1133 A_Expr_to_Expr(Node *ptr, bool *intersect_present)
1134 {
1135         Node       *result = NULL;
1136
1137         switch (nodeTag(ptr))
1138         {
1139                 case T_A_Expr:
1140                         {
1141                                 A_Expr     *a = (A_Expr *) ptr;
1142
1143                                 switch (a->oper)
1144                                 {
1145                                         case AND:
1146                                                 {
1147                                                         Expr       *expr = makeNode(Expr);
1148                                                         Node       *lexpr = A_Expr_to_Expr(((A_Expr *) ptr)->lexpr, intersect_present);
1149                                                         Node       *rexpr = A_Expr_to_Expr(((A_Expr *) ptr)->rexpr, intersect_present);
1150
1151                                                         *intersect_present = TRUE;
1152
1153                                                         expr->typeOid = BOOLOID;
1154                                                         expr->opType = OR_EXPR;
1155                                                         expr->args = makeList(lexpr, rexpr, -1);
1156                                                         result = (Node *) expr;
1157                                                         break;
1158                                                 }
1159                                         case OR:
1160                                                 {
1161                                                         Expr       *expr = makeNode(Expr);
1162                                                         Node       *lexpr = A_Expr_to_Expr(((A_Expr *) ptr)->lexpr, intersect_present);
1163                                                         Node       *rexpr = A_Expr_to_Expr(((A_Expr *) ptr)->rexpr, intersect_present);
1164
1165                                                         expr->typeOid = BOOLOID;
1166                                                         expr->opType = AND_EXPR;
1167                                                         expr->args = makeList(lexpr, rexpr, -1);
1168                                                         result = (Node *) expr;
1169                                                         break;
1170                                                 }
1171                                         case NOT:
1172                                                 {
1173                                                         Expr       *expr = makeNode(Expr);
1174                                                         Node       *rexpr = A_Expr_to_Expr(((A_Expr *) ptr)->rexpr, intersect_present);
1175
1176                                                         expr->typeOid = BOOLOID;
1177                                                         expr->opType = NOT_EXPR;
1178                                                         expr->args = makeList(rexpr, -1);
1179                                                         result = (Node *) expr;
1180                                                         break;
1181                                                 }
1182                                 }
1183                                 break;
1184                         }
1185                 default:
1186                         result = ptr;
1187         }
1188         return result;
1189 }
1190
1191 void
1192 CheckSelectForUpdate(Query *qry)
1193 {
1194         if (qry->unionClause != NULL)
1195                 elog(ERROR, "SELECT FOR UPDATE is not allowed with UNION/INTERSECT/EXCEPT clause");
1196         if (qry->uniqueFlag != NULL)
1197                 elog(ERROR, "SELECT FOR UPDATE is not allowed with DISTINCT clause");
1198         if (qry->groupClause != NULL)
1199                 elog(ERROR, "SELECT FOR UPDATE is not allowed with GROUP BY clause");
1200         if (qry->hasAggs)
1201                 elog(ERROR, "SELECT FOR UPDATE is not allowed with AGGREGATE");
1202 }
1203
1204 static void
1205 transformForUpdate(Query *qry, List *forUpdate)
1206 {
1207         List       *rowMark = NULL;
1208         RowMark    *newrm;
1209         List       *l;
1210         Index           i;
1211
1212         CheckSelectForUpdate(qry);
1213
1214         if (lfirst(forUpdate) == NULL)          /* all tables */
1215         {
1216                 i = 1;
1217                 foreach(l, qry->rtable)
1218                 {
1219                         newrm = makeNode(RowMark);
1220                         newrm->rti = i++;
1221                         newrm->info = ROW_MARK_FOR_UPDATE | ROW_ACL_FOR_UPDATE;
1222                         rowMark = lappend(rowMark, newrm);
1223                 }
1224                 qry->rowMark = nconc(qry->rowMark, rowMark);
1225                 return;
1226         }
1227
1228         foreach(l, forUpdate)
1229         {
1230                 List       *l2;
1231                 List       *l3;
1232
1233                 i = 1;
1234                 foreach(l2, qry->rtable)
1235                 {
1236                         if (strcmp(((RangeTblEntry *) lfirst(l2))->refname, lfirst(l)) == 0)
1237                         {
1238                                 foreach(l3, rowMark)
1239                                 {
1240                                         if (((RowMark *) lfirst(l3))->rti == i)         /* duplicate */
1241                                                 break;
1242                                 }
1243                                 if (l3 == NULL)
1244                                 {
1245                                         newrm = makeNode(RowMark);
1246                                         newrm->rti = i;
1247                                         newrm->info = ROW_MARK_FOR_UPDATE | ROW_ACL_FOR_UPDATE;
1248                                         rowMark = lappend(rowMark, newrm);
1249                                 }
1250                                 break;
1251                         }
1252                         i++;
1253                 }
1254                 if (l2 == NULL)
1255                         elog(ERROR, "FOR UPDATE: relation %s not found in FROM clause", lfirst(l));
1256         }
1257
1258         qry->rowMark = rowMark;
1259         return;
1260 }