OSDN Git Service

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