OSDN Git Service

OK, folks, here is the pgindent output.
[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  *
9  * IDENTIFICATION
10  *        $Header: /cvsroot/pgsql/src/backend/parser/analyze.c,v 1.85 1998/09/01 04:30:15 momjian Exp $
11  *
12  *-------------------------------------------------------------------------
13  */
14
15 #include <stdio.h>
16 #include <stdlib.h>
17 #include <stdarg.h>
18 #include <string.h>
19
20 #include "postgres.h"
21 #include "access/heapam.h"
22 #include "nodes/makefuncs.h"
23 #include "nodes/memnodes.h"
24 #include "nodes/pg_list.h"
25 #include "parser/analyze.h"
26 #include "parser/parse_agg.h"
27 #include "parser/parse_clause.h"
28 #include "parser/parse_node.h"
29 #include "parser/parse_relation.h"
30 #include "parser/parse_target.h"
31 #include "utils/builtins.h"
32 #include "utils/mcxt.h"
33 #ifdef PARSEDEBUG
34 #include "nodes/print.h"
35 #endif
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 List       *extras = NIL;
49
50 /*
51  * parse_analyze -
52  *        analyze a list of parse trees and transform them if necessary.
53  *
54  * Returns a list of transformed parse trees. Optimizable statements are
55  * all transformed to Query while the rest stays the same.
56  *
57  */
58 QueryTreeList *
59 parse_analyze(List *pl, ParseState *parentParseState)
60 {
61         QueryTreeList *result;
62         ParseState *pstate;
63         int                     i = 0;
64
65         result = malloc(sizeof(QueryTreeList));
66         result->len = length(pl);
67         result->qtrees = (Query **) malloc(result->len * sizeof(Query *));
68
69         while (pl != NIL)
70         {
71 #ifdef PARSEDEBUG
72                 elog(DEBUG, "parse tree from yacc:\n---\n%s\n---\n", nodeToString(lfirst(pl)));
73 #endif
74
75                 pstate = make_parsestate(parentParseState);
76                 result->qtrees[i++] = transformStmt(pstate, lfirst(pl));
77                 if (pstate->p_target_relation != NULL)
78                         heap_close(pstate->p_target_relation);
79
80                 if (extras != NIL)
81                 {
82                         result->len += length(extras);
83                         result->qtrees = (Query **) realloc(result->qtrees, result->len * sizeof(Query *));
84                         while (extras != NIL)
85                         {
86                                 result->qtrees[i++] = transformStmt(pstate, lfirst(extras));
87                                 if (pstate->p_target_relation != NULL)
88                                         heap_close(pstate->p_target_relation);
89                                 extras = lnext(extras);
90                         }
91                 }
92                 extras = NIL;
93                 pl = lnext(pl);
94                 pfree(pstate);
95         }
96
97         return result;
98 }
99
100 /*
101  * transformStmt -
102  *        transform a Parse tree. If it is an optimizable statement, turn it
103  *        into a Query tree.
104  */
105 static Query *
106 transformStmt(ParseState *pstate, Node *parseTree)
107 {
108         Query      *result = NULL;
109
110         switch (nodeTag(parseTree))
111         {
112                         /*------------------------
113                          *      Non-optimizable statements
114                          *------------------------
115                          */
116                 case T_CreateStmt:
117                         result = transformCreateStmt(pstate, (CreateStmt *) parseTree);
118                         break;
119
120                 case T_IndexStmt:
121                         result = transformIndexStmt(pstate, (IndexStmt *) parseTree);
122                         break;
123
124                 case T_ExtendStmt:
125                         result = transformExtendStmt(pstate, (ExtendStmt *) parseTree);
126                         break;
127
128                 case T_RuleStmt:
129                         result = transformRuleStmt(pstate, (RuleStmt *) parseTree);
130                         break;
131
132                 case T_ViewStmt:
133                         {
134                                 ViewStmt   *n = (ViewStmt *) parseTree;
135
136                                 n->query = (Query *) transformStmt(pstate, (Node *) n->query);
137                                 result = makeNode(Query);
138                                 result->commandType = CMD_UTILITY;
139                                 result->utilityStmt = (Node *) n;
140                         }
141                         break;
142
143                 case T_VacuumStmt:
144                         {
145                                 MemoryContext oldcontext;
146
147                                 /*
148                                  * make sure that this Query is allocated in TopMemory
149                                  * context because vacuum spans transactions and we don't
150                                  * want to lose the vacuum Query due to end-of-transaction
151                                  * free'ing
152                                  */
153                                 oldcontext = MemoryContextSwitchTo(TopMemoryContext);
154                                 result = makeNode(Query);
155                                 result->commandType = CMD_UTILITY;
156                                 result->utilityStmt = (Node *) parseTree;
157                                 MemoryContextSwitchTo(oldcontext);
158                                 break;
159
160                         }
161                 case T_ExplainStmt:
162                         {
163                                 ExplainStmt *n = (ExplainStmt *) parseTree;
164
165                                 result = makeNode(Query);
166                                 result->commandType = CMD_UTILITY;
167                                 n->query = transformStmt(pstate, (Node *) n->query);
168                                 result->utilityStmt = (Node *) parseTree;
169                         }
170                         break;
171
172                         /*------------------------
173                          *      Optimizable statements
174                          *------------------------
175                          */
176                 case T_InsertStmt:
177                         result = transformInsertStmt(pstate, (InsertStmt *) parseTree);
178                         break;
179
180                 case T_DeleteStmt:
181                         result = transformDeleteStmt(pstate, (DeleteStmt *) parseTree);
182                         break;
183
184                 case T_UpdateStmt:
185                         result = transformUpdateStmt(pstate, (UpdateStmt *) parseTree);
186                         break;
187
188                 case T_SelectStmt:
189                         if (!((SelectStmt *) parseTree)->portalname)
190                                 result = transformSelectStmt(pstate, (SelectStmt *) parseTree);
191                         else
192                                 result = transformCursorStmt(pstate, (SelectStmt *) parseTree);
193                         break;
194
195                 default:
196
197                         /*
198                          * other statments don't require any transformation-- just
199                          * return the original parsetree, yea!
200                          */
201                         result = makeNode(Query);
202                         result->commandType = CMD_UTILITY;
203                         result->utilityStmt = (Node *) parseTree;
204                         break;
205         }
206         return result;
207 }
208
209 /*
210  * transformDeleteStmt -
211  *        transforms a Delete Statement
212  */
213 static Query *
214 transformDeleteStmt(ParseState *pstate, DeleteStmt *stmt)
215 {
216         Query      *qry = makeNode(Query);
217
218         qry->commandType = CMD_DELETE;
219
220         /* set up a range table */
221         makeRangeTable(pstate, stmt->relname, NULL);
222
223         qry->uniqueFlag = NULL;
224
225         /* fix where clause */
226         qry->qual = transformWhereClause(pstate, stmt->whereClause);
227         qry->hasSubLinks = pstate->p_hasSubLinks;
228
229         qry->rtable = pstate->p_rtable;
230         qry->resultRelation = refnameRangeTablePosn(pstate, stmt->relname, NULL);
231
232         qry->hasAggs = pstate->p_hasAggs;
233         if (pstate->p_hasAggs)
234                 parseCheckAggregates(pstate, qry);
235
236         return (Query *) qry;
237 }
238
239 /*
240  * transformInsertStmt -
241  *        transform an Insert Statement
242  */
243 static Query *
244 transformInsertStmt(ParseState *pstate, InsertStmt *stmt)
245 {
246         Query      *qry = makeNode(Query);      /* make a new query tree */
247         List       *icolumns;
248
249         qry->commandType = CMD_INSERT;
250         pstate->p_is_insert = true;
251
252         /* set up a range table */
253         makeRangeTable(pstate, stmt->relname, stmt->fromClause);
254
255         qry->uniqueFlag = stmt->unique;
256
257         /* fix the target list */
258         icolumns = pstate->p_insert_columns = makeTargetNames(pstate, stmt->cols);
259
260         qry->targetList = transformTargetList(pstate, stmt->targetList);
261
262         /* DEFAULT handling */
263         if (length(qry->targetList) < pstate->p_target_relation->rd_att->natts &&
264                 pstate->p_target_relation->rd_att->constr &&
265                 pstate->p_target_relation->rd_att->constr->num_defval > 0)
266         {
267                 Form_pg_attribute *att = pstate->p_target_relation->rd_att->attrs;
268                 AttrDefault *defval = pstate->p_target_relation->rd_att->constr->defval;
269                 int                     ndef = pstate->p_target_relation->rd_att->constr->num_defval;
270
271                 /*
272                  * if stmt->cols == NIL then makeTargetNames returns list of all
273                  * attrs: have to shorter icolumns list...
274                  */
275                 if (stmt->cols == NIL)
276                 {
277                         List       *extrl;
278                         int                     i = length(qry->targetList);
279
280                         foreach(extrl, icolumns)
281                         {
282                                 if (--i <= 0)
283                                         break;
284                         }
285                         freeList(lnext(extrl));
286                         lnext(extrl) = NIL;
287                 }
288
289                 while (ndef-- > 0)
290                 {
291                         List       *tl;
292                         Ident      *id;
293                         TargetEntry *te;
294
295                         foreach(tl, icolumns)
296                         {
297                                 id = (Ident *) lfirst(tl);
298                                 if (!namestrcmp(&(att[defval[ndef].adnum - 1]->attname), id->name))
299                                         break;
300                         }
301                         if (tl != NIL)          /* something given for this attr */
302                                 continue;
303
304                         /*
305                          * Nothing given for this attr with DEFAULT expr, so add new
306                          * TargetEntry to qry->targetList. Note, that we set resno to
307                          * defval[ndef].adnum: it's what
308                          * transformTargetList()->make_targetlist_expr() does for
309                          * INSERT ... SELECT. But for INSERT ... VALUES
310                          * pstate->p_last_resno is used. It doesn't matter for
311                          * "normal" using (planner creates proper target list in
312                          * preptlist.c), but may break RULEs in some way. It seems
313                          * better to create proper target list here...
314                          */
315                         te = makeTargetEntry(makeResdom(defval[ndef].adnum,
316                                                                    att[defval[ndef].adnum - 1]->atttypid,
317                                                                   att[defval[ndef].adnum - 1]->atttypmod,
318                            pstrdup(nameout(&(att[defval[ndef].adnum - 1]->attname))),
319                                                                                         0, 0, 0),
320                                                           (Node *) stringToNode(defval[ndef].adbin));
321                         qry->targetList = lappend(qry->targetList, te);
322                 }
323         }
324
325         /* fix where clause */
326         qry->qual = transformWhereClause(pstate, stmt->whereClause);
327
328         /*
329          * The havingQual has a similar meaning as "qual" in the where
330          * statement. So we can easily use the code from the "where clause"
331          * with some additional traversals done in
332          * .../optimizer/plan/planner.c
333          */
334         qry->havingQual = transformWhereClause(pstate, stmt->havingClause);
335
336         qry->hasSubLinks = pstate->p_hasSubLinks;
337
338         /* now the range table will not change */
339         qry->rtable = pstate->p_rtable;
340         qry->resultRelation = refnameRangeTablePosn(pstate, stmt->relname, NULL);
341
342         qry->groupClause = transformGroupClause(pstate,
343                                                                                         stmt->groupClause,
344                                                                                         qry->targetList);
345
346         /* fix order clause */
347         qry->sortClause = transformSortClause(pstate,
348                                                                                   NIL,
349                                                                                   NIL,
350                                                                                   qry->targetList,
351                                                                                   qry->uniqueFlag);
352
353         qry->hasAggs = pstate->p_hasAggs;
354         if (pstate->p_hasAggs)
355                 parseCheckAggregates(pstate, qry);
356
357         /*
358          * The INSERT INTO ... SELECT ... could have a UNION in child, so
359          * unionClause may be false
360          */
361         qry->unionall = stmt->unionall;
362         qry->unionClause = transformUnionClause(stmt->unionClause, qry->targetList);
363
364         /*
365          * If there is a havingQual but there are no aggregates, then there is
366          * something wrong with the query because having must contain
367          * aggregates in its expressions! Otherwise the query could have been
368          * formulated using the where clause.
369          */
370         if ((qry->hasAggs == false) && (qry->havingQual != NULL))
371         {
372                 elog(ERROR, "This is not a valid having query!");
373                 return (Query *) NIL;
374         }
375
376         return (Query *) qry;
377 }
378
379 /*
380  *      makeTableName()
381  *      Create a table name from a list of fields.
382  */
383 static char *
384 makeTableName(void *elem,...)
385 {
386         va_list         args;
387
388         char       *name;
389         char            buf[NAMEDATALEN + 1];
390
391         buf[0] = '\0';
392
393         va_start(args, elem);
394
395         name = elem;
396         while (name != NULL)
397         {
398                 /* not enough room for next part? then return nothing */
399                 if ((strlen(buf) + strlen(name)) >= (sizeof(buf) - 1))
400                         return NULL;
401
402                 if (strlen(buf) > 0)
403                         strcat(buf, "_");
404                 strcat(buf, name);
405
406                 name = va_arg(args, void *);
407         }
408
409         va_end(args);
410
411         name = palloc(strlen(buf) + 1);
412         strcpy(name, buf);
413
414         return name;
415 }
416
417 static char *
418 CreateIndexName(char *table_name, char *column_name, char *label, List *indices)
419 {
420         int                     pass = 0;
421         char       *iname = NULL;
422         List       *ilist;
423         IndexStmt  *index;
424         char            name2[NAMEDATALEN + 1];
425
426         /* use working storage, since we might be trying several possibilities */
427         strcpy(name2, column_name);
428         while (iname == NULL)
429         {
430                 iname = makeTableName(table_name, name2, label, NULL);
431                 /* unable to make a name at all? then quit */
432                 if (iname == NULL)
433                         break;
434
435                 ilist = indices;
436                 while (ilist != NIL)
437                 {
438                         index = lfirst(ilist);
439                         if (strcasecmp(iname, index->idxname) == 0)
440                                 break;
441
442                         ilist = lnext(ilist);
443                 }
444                 /* ran through entire list? then no name conflict found so done */
445                 if (ilist == NIL)
446                         break;
447
448                 /* the last one conflicted, so try a new name component */
449                 pfree(iname);
450                 iname = NULL;
451                 pass++;
452                 sprintf(name2, "%s_%d", column_name, (pass + 1));
453         }
454
455         return iname;
456 }
457
458 /*
459  * transformCreateStmt -
460  *        transforms the "create table" statement
461  *        SQL92 allows constraints to be scattered all over, so thumb through
462  *         the columns and collect all constraints into one place.
463  *        If there are any implied indices (e.g. UNIQUE or PRIMARY KEY)
464  *         then expand those into multiple IndexStmt blocks.
465  *        - thomas 1997-12-02
466  */
467 static Query *
468 transformCreateStmt(ParseState *pstate, CreateStmt *stmt)
469 {
470         Query      *q;
471         int                     have_pkey = FALSE;
472         List       *elements;
473         Node       *element;
474         List       *columns;
475         List       *dlist;
476         ColumnDef  *column;
477         List       *constraints,
478                            *clist;
479         Constraint *constraint;
480         List       *keys;
481         Ident      *key;
482         List       *ilist = NIL;
483         IndexStmt  *index;
484         IndexElem  *iparam;
485
486         q = makeNode(Query);
487         q->commandType = CMD_UTILITY;
488
489         elements = stmt->tableElts;
490         constraints = stmt->constraints;
491         columns = NIL;
492         dlist = NIL;
493
494         while (elements != NIL)
495         {
496                 element = lfirst(elements);
497                 switch (nodeTag(element))
498                 {
499                         case T_ColumnDef:
500                                 column = (ColumnDef *) element;
501                                 columns = lappend(columns, column);
502
503                                 if (column->is_sequence)
504                                 {
505                                         char       *cstring;
506                                         CreateSeqStmt *sequence;
507
508                                         constraint = makeNode(Constraint);
509                                         constraint->contype = CONSTR_DEFAULT;
510                                         constraint->name = makeTableName(stmt->relname, column->colname, "seq", NULL);
511                                         cstring = palloc(9 + strlen(constraint->name) + 2 + 1);
512                                         strcpy(cstring, "nextval('");
513                                         strcat(cstring, constraint->name);
514                                         strcat(cstring, "')");
515                                         constraint->def = cstring;
516                                         constraint->keys = NULL;
517
518                                         if (column->constraints != NIL)
519                                                 column->constraints = lappend(column->constraints, constraint);
520                                         else
521                                                 column->constraints = lcons(constraint, NIL);
522
523                                         sequence = makeNode(CreateSeqStmt);
524                                         sequence->seqname = pstrdup(constraint->name);
525                                         sequence->options = NIL;
526
527                                         elog(NOTICE, "CREATE TABLE will create implicit sequence %s for SERIAL column %s.%s",
528                                           sequence->seqname, stmt->relname, column->colname);
529
530                                         ilist = lcons(sequence, NIL);
531
532                                         constraint = makeNode(Constraint);
533                                         constraint->contype = CONSTR_UNIQUE;
534                                         constraint->name = makeTableName(stmt->relname, column->colname, "key", NULL);
535
536                                         column->constraints = lappend(column->constraints, constraint);
537                                 }
538
539                                 if (column->constraints != NIL)
540                                 {
541                                         clist = column->constraints;
542                                         while (clist != NIL)
543                                         {
544                                                 constraint = lfirst(clist);
545                                                 switch (constraint->contype)
546                                                 {
547                                                         case CONSTR_NOTNULL:
548                                                                 if (column->is_not_null)
549                                                                         elog(ERROR, "CREATE TABLE/NOT NULL already specified"
550                                                                                  " for %s.%s", stmt->relname, column->colname);
551                                                                 column->is_not_null = TRUE;
552                                                                 break;
553
554                                                         case CONSTR_DEFAULT:
555                                                                 if (column->defval != NULL)
556                                                                         elog(ERROR, "CREATE TABLE/DEFAULT multiple values specified"
557                                                                                  " for %s.%s", stmt->relname, column->colname);
558                                                                 column->defval = constraint->def;
559                                                                 break;
560
561                                                         case CONSTR_PRIMARY:
562                                                                 if (constraint->name == NULL)
563                                                                         constraint->name = makeTableName(stmt->relname, "pkey", NULL);
564                                                                 if (constraint->keys == NIL)
565                                                                         constraint->keys = lappend(constraint->keys, column);
566                                                                 dlist = lappend(dlist, constraint);
567                                                                 break;
568
569                                                         case CONSTR_UNIQUE:
570                                                                 if (constraint->name == NULL)
571                                                                         constraint->name = makeTableName(stmt->relname, column->colname, "key", NULL);
572                                                                 if (constraint->keys == NIL)
573                                                                         constraint->keys = lappend(constraint->keys, column);
574                                                                 dlist = lappend(dlist, constraint);
575                                                                 break;
576
577                                                         case CONSTR_CHECK:
578                                                                 constraints = lappend(constraints, constraint);
579                                                                 if (constraint->name == NULL)
580                                                                         constraint->name = makeTableName(stmt->relname, column->colname, NULL);
581                                                                 break;
582
583                                                         default:
584                                                                 elog(ERROR, "parser: internal error; unrecognized constraint", NULL);
585                                                                 break;
586                                                 }
587                                                 clist = lnext(clist);
588                                         }
589                                 }
590                                 break;
591
592                         case T_Constraint:
593                                 constraint = (Constraint *) element;
594                                 switch (constraint->contype)
595                                 {
596                                         case CONSTR_PRIMARY:
597                                                 if (constraint->name == NULL)
598                                                         constraint->name = makeTableName(stmt->relname, "pkey", NULL);
599                                                 dlist = lappend(dlist, constraint);
600                                                 break;
601
602                                         case CONSTR_UNIQUE:
603 #if FALSE
604                                                 if (constraint->name == NULL)
605                                                         constraint->name = makeTableName(stmt->relname, "key", NULL);
606 #endif
607                                                 dlist = lappend(dlist, constraint);
608                                                 break;
609
610                                         case CONSTR_CHECK:
611                                                 constraints = lappend(constraints, constraint);
612                                                 break;
613
614                                         case CONSTR_NOTNULL:
615                                         case CONSTR_DEFAULT:
616                                                 elog(ERROR, "parser: internal error; illegal context for constraint", NULL);
617                                                 break;
618                                         default:
619                                                 elog(ERROR, "parser: internal error; unrecognized constraint", NULL);
620                                                 break;
621                                 }
622                                 break;
623
624                         default:
625                                 elog(ERROR, "parser: internal error; unrecognized node", NULL);
626                 }
627
628                 elements = lnext(elements);
629         }
630
631         stmt->tableElts = columns;
632         stmt->constraints = constraints;
633
634 /* Now run through the "deferred list" to complete the query transformation.
635  * For PRIMARY KEYs, mark each column as NOT NULL and create an index.
636  * For UNIQUE, create an index as for PRIMARY KEYS, but do not insist on NOT NULL.
637  *
638  * Note that this code does not currently look for all possible redundant cases
639  *      and either ignore or stop with warning. The create might fail later when
640  *      names for indices turn out to be redundant, or a user might have specified
641  *      extra useless indices which might hurt performance. - thomas 1997-12-08
642  */
643         while (dlist != NIL)
644         {
645                 constraint = lfirst(dlist);
646                 if (nodeTag(constraint) != T_Constraint)
647                         elog(ERROR, "parser: internal error; unrecognized deferred node", NULL);
648
649                 if (constraint->contype == CONSTR_PRIMARY)
650                 {
651                         if (have_pkey)
652                                 elog(ERROR, "CREATE TABLE/PRIMARY KEY multiple primary keys"
653                                          " for table %s are not legal", stmt->relname);
654                         else
655                                 have_pkey = TRUE;
656                 }
657                 else if (constraint->contype != CONSTR_UNIQUE)
658                         elog(ERROR, "parser: internal error; unrecognized deferred constraint", NULL);
659
660                 index = makeNode(IndexStmt);
661
662                 index->unique = TRUE;
663                 if (constraint->name != NULL)
664                         index->idxname = constraint->name;
665                 else if (constraint->contype == CONSTR_PRIMARY)
666                 {
667                         if (have_pkey)
668                                 elog(ERROR, "CREATE TABLE/PRIMARY KEY multiple keys for table %s are not legal", stmt->relname);
669
670                         have_pkey = TRUE;
671                         index->idxname = makeTableName(stmt->relname, "pkey", NULL);
672                 }
673                 else
674                         index->idxname = NULL;
675
676                 index->relname = stmt->relname;
677                 index->accessMethod = "btree";
678                 index->indexParams = NIL;
679                 index->withClause = NIL;
680                 index->whereClause = NULL;
681
682                 keys = constraint->keys;
683                 while (keys != NIL)
684                 {
685                         key = lfirst(keys);
686                         columns = stmt->tableElts;
687                         column = NULL;
688                         while (columns != NIL)
689                         {
690                                 column = lfirst(columns);
691                                 if (strcasecmp(column->colname, key->name) == 0)
692                                         break;
693                                 else
694                                         column = NULL;
695                                 columns = lnext(columns);
696                         }
697                         if (column == NULL)
698                                 elog(ERROR, "parser: column '%s' in key does not exist", key->name);
699
700                         if (constraint->contype == CONSTR_PRIMARY)
701                                 column->is_not_null = TRUE;
702                         iparam = makeNode(IndexElem);
703                         iparam->name = strcpy(palloc(strlen(column->colname) + 1), column->colname);
704                         iparam->args = NIL;
705                         iparam->class = NULL;
706                         iparam->typename = NULL;
707                         index->indexParams = lappend(index->indexParams, iparam);
708
709                         if (index->idxname == NULL)
710                                 index->idxname = CreateIndexName(stmt->relname, iparam->name, "key", ilist);
711
712                         keys = lnext(keys);
713                 }
714
715                 if (index->idxname == NULL)
716                         elog(ERROR, "parser: unable to construct implicit index for table %s"
717                                  "; name too long", stmt->relname);
718                 else
719                         elog(NOTICE, "CREATE TABLE/%s will create implicit index %s for table %s",
720                                  ((constraint->contype == CONSTR_PRIMARY) ? "PRIMARY KEY" : "UNIQUE"),
721                                  index->idxname, stmt->relname);
722
723                 ilist = lappend(ilist, index);
724                 dlist = lnext(dlist);
725         }
726
727         q->utilityStmt = (Node *) stmt;
728         extras = ilist;
729
730         return q;
731 }
732
733 /*
734  * transformIndexStmt -
735  *        transforms the qualification of the index statement
736  */
737 static Query *
738 transformIndexStmt(ParseState *pstate, IndexStmt *stmt)
739 {
740         Query      *qry;
741
742         qry = makeNode(Query);
743         qry->commandType = CMD_UTILITY;
744
745         /* take care of the where clause */
746         stmt->whereClause = transformWhereClause(pstate, stmt->whereClause);
747         qry->hasSubLinks = pstate->p_hasSubLinks;
748
749         stmt->rangetable = pstate->p_rtable;
750
751         qry->utilityStmt = (Node *) stmt;
752
753         return qry;
754 }
755
756 /*
757  * transformExtendStmt -
758  *        transform the qualifications of the Extend Index Statement
759  *
760  */
761 static Query *
762 transformExtendStmt(ParseState *pstate, ExtendStmt *stmt)
763 {
764         Query      *qry;
765
766         qry = makeNode(Query);
767         qry->commandType = CMD_UTILITY;
768
769         /* take care of the where clause */
770         stmt->whereClause = transformWhereClause(pstate, stmt->whereClause);
771         qry->hasSubLinks = pstate->p_hasSubLinks;
772
773         stmt->rangetable = pstate->p_rtable;
774
775         qry->utilityStmt = (Node *) stmt;
776         return qry;
777 }
778
779 /*
780  * transformRuleStmt -
781  *        transform a Create Rule Statement. The actions is a list of parse
782  *        trees which is transformed into a list of query trees.
783  */
784 static Query *
785 transformRuleStmt(ParseState *pstate, RuleStmt *stmt)
786 {
787         Query      *qry;
788         Query      *action;
789         List       *actions;
790
791         qry = makeNode(Query);
792         qry->commandType = CMD_UTILITY;
793
794         /*
795          * 'instead nothing' rules with a qualification need a query a
796          * rangetable so the rewrite handler can add the negated rule
797          * qualification to the original query. We create a query with the new
798          * command type CMD_NOTHING here that is treated special by the
799          * rewrite system.
800          */
801         if (stmt->actions == NIL)
802         {
803                 Query      *nothing_qry = makeNode(Query);
804
805                 nothing_qry->commandType = CMD_NOTHING;
806
807                 addRangeTableEntry(pstate, stmt->object->relname, "*CURRENT*",
808                                                    FALSE, FALSE);
809                 addRangeTableEntry(pstate, stmt->object->relname, "*NEW*",
810                                                    FALSE, FALSE);
811
812                 nothing_qry->rtable = pstate->p_rtable;
813
814                 stmt->actions = lappend(NIL, nothing_qry);
815         }
816
817         actions = stmt->actions;
818
819         /*
820          * transform each statment, like parse_analyze()
821          */
822         while (actions != NIL)
823         {
824
825                 /*
826                  * NOTE: 'CURRENT' must always have a varno equal to 1 and 'NEW'
827                  * equal to 2.
828                  */
829                 addRangeTableEntry(pstate, stmt->object->relname, "*CURRENT*",
830                                                    FALSE, FALSE);
831                 addRangeTableEntry(pstate, stmt->object->relname, "*NEW*",
832                                                    FALSE, FALSE);
833
834                 pstate->p_last_resno = 1;
835                 pstate->p_is_rule = true;               /* for expand all */
836                 pstate->p_hasAggs = false;
837
838                 action = (Query *) lfirst(actions);
839                 if (action->commandType != CMD_NOTHING)
840                         lfirst(actions) = transformStmt(pstate, lfirst(actions));
841                 actions = lnext(actions);
842         }
843
844         /* take care of the where clause */
845         stmt->whereClause = transformWhereClause(pstate, stmt->whereClause);
846         qry->hasSubLinks = pstate->p_hasSubLinks;
847
848         qry->utilityStmt = (Node *) stmt;
849         return qry;
850 }
851
852
853 /*
854  * transformSelectStmt -
855  *        transforms a Select Statement
856  *
857  */
858 static Query *
859 transformSelectStmt(ParseState *pstate, SelectStmt *stmt)
860 {
861         Query      *qry = makeNode(Query);
862
863         qry->commandType = CMD_SELECT;
864
865         /* set up a range table */
866         makeRangeTable(pstate, NULL, stmt->fromClause);
867
868         qry->uniqueFlag = stmt->unique;
869
870         qry->into = stmt->into;
871         qry->isPortal = FALSE;
872
873         qry->targetList = transformTargetList(pstate, stmt->targetList);
874
875         qry->qual = transformWhereClause(pstate, stmt->whereClause);
876
877         /*
878          * The havingQual has a similar meaning as "qual" in the where
879          * statement. So we can easily use the code from the "where clause"
880          * with some additional traversals done in
881          * .../optimizer/plan/planner.c
882          */
883         qry->havingQual = transformWhereClause(pstate, stmt->havingClause);
884
885         qry->hasSubLinks = pstate->p_hasSubLinks;
886
887         qry->sortClause = transformSortClause(pstate,
888                                                                                   stmt->sortClause,
889                                                                                   NIL,
890                                                                                   qry->targetList,
891                                                                                   qry->uniqueFlag);
892
893         qry->groupClause = transformGroupClause(pstate,
894                                                                                         stmt->groupClause,
895                                                                                         qry->targetList);
896         qry->rtable = pstate->p_rtable;
897
898         qry->hasAggs = pstate->p_hasAggs;
899         if (pstate->p_hasAggs)
900                 parseCheckAggregates(pstate, qry);
901
902         /*
903          * The INSERT INTO ... SELECT ... could have a UNION in child, so
904          * unionClause may be false
905          */
906         qry->unionall = stmt->unionall;
907         qry->unionClause = transformUnionClause(stmt->unionClause, qry->targetList);
908
909         /*
910          * If there is a havingQual but there are no aggregates, then there is
911          * something wrong with the query because having must contain
912          * aggregates in its expressions! Otherwise the query could have been
913          * formulated using the where clause.
914          */
915         if ((qry->hasAggs == false) && (qry->havingQual != NULL))
916         {
917                 elog(ERROR, "This is not a valid having query!");
918                 return (Query *) NIL;
919         }
920
921         return (Query *) qry;
922 }
923
924 /*
925  * transformUpdateStmt -
926  *        transforms an update statement
927  *
928  */
929 static Query *
930 transformUpdateStmt(ParseState *pstate, UpdateStmt *stmt)
931 {
932         Query      *qry = makeNode(Query);
933
934         qry->commandType = CMD_UPDATE;
935         pstate->p_is_update = true;
936
937         /*
938          * the FROM clause is non-standard SQL syntax. We used to be able to
939          * do this with REPLACE in POSTQUEL so we keep the feature.
940          */
941         makeRangeTable(pstate, stmt->relname, stmt->fromClause);
942
943         qry->targetList = transformTargetList(pstate, stmt->targetList);
944
945         qry->qual = transformWhereClause(pstate, stmt->whereClause);
946         qry->hasSubLinks = pstate->p_hasSubLinks;
947
948         qry->rtable = pstate->p_rtable;
949
950         qry->resultRelation = refnameRangeTablePosn(pstate, stmt->relname, NULL);
951
952         qry->hasAggs = pstate->p_hasAggs;
953         if (pstate->p_hasAggs)
954                 parseCheckAggregates(pstate, qry);
955
956         return (Query *) qry;
957 }
958
959 /*
960  * transformCursorStmt -
961  *        transform a Create Cursor Statement
962  *
963  */
964 static Query *
965 transformCursorStmt(ParseState *pstate, SelectStmt *stmt)
966 {
967         Query      *qry;
968
969         qry = transformSelectStmt(pstate, stmt);
970
971         qry->into = stmt->portalname;
972         qry->isPortal = TRUE;
973         qry->isBinary = stmt->binary;           /* internal portal */
974
975         return qry;
976 }