OSDN Git Service

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