OSDN Git Service

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