OSDN Git Service

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