OSDN Git Service

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