OSDN Git Service

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