OSDN Git Service

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