OSDN Git Service

Add capabilities for automatic type conversion.
[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.75 1998/05/09 23:29:52 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                 AttributeTupleForm *att = pstate->p_target_relation->rd_att->attrs;
268                 AttrDefault *defval = pstate->p_target_relation->rd_att->constr->defval;
269                 int                     ndef = pstate->p_target_relation->rd_att->constr->num_defval;
270
271                 /*
272                  * if stmt->cols == NIL then makeTargetNames returns list of all
273                  * attrs: have to shorter icolumns list...
274                  */
275                 if (stmt->cols == NIL)
276                 {
277                         List       *extrl;
278                         int                     i = length(qry->targetList);
279
280                         foreach(extrl, icolumns)
281                         {
282                                 if (--i <= 0)
283                                         break;
284                         }
285                         freeList(lnext(extrl));
286                         lnext(extrl) = NIL;
287                 }
288
289                 while (ndef-- > 0)
290                 {
291                         List       *tl;
292                         Ident      *id;
293                         TargetEntry *te;
294
295                         foreach(tl, icolumns)
296                         {
297                                 id = (Ident *) lfirst(tl);
298                                 if (!namestrcmp(&(att[defval[ndef].adnum - 1]->attname), id->name))
299                                         break;
300                         }
301                         if (tl != NIL)          /* something given for this attr */
302                                 continue;
303
304                         /*
305                          * Nothing given for this attr with DEFAULT expr, so add new
306                          * TargetEntry to qry->targetList. Note, that we set resno to
307                          * defval[ndef].adnum: it's what
308                          * transformTargetList()->make_targetlist_expr() does for
309                          * INSERT ... SELECT. But for INSERT ... VALUES
310                          * pstate->p_last_resno is used. It doesn't matter for
311                          * "normal" using (planner creates proper target list in
312                          * preptlist.c), but may break RULEs in some way. It seems
313                          * better to create proper target list here...
314                          */
315                         te = makeNode(TargetEntry);
316                         te->resdom = makeResdom(defval[ndef].adnum,
317                                                                         att[defval[ndef].adnum - 1]->atttypid,
318                                                                   att[defval[ndef].adnum - 1]->atttypmod,
319                            pstrdup(nameout(&(att[defval[ndef].adnum - 1]->attname))),
320                                                                         0, 0, 0);
321                         te->fjoin = NULL;
322                         te->expr = (Node *) stringToNode(defval[ndef].adbin);
323                         qry->targetList = lappend(qry->targetList, te);
324                 }
325         }
326
327         /* fix where clause */
328         qry->qual = transformWhereClause(pstate, stmt->whereClause);
329
330         qry->havingQual = transformWhereClause(pstate, stmt->havingClause);
331
332         qry->hasSubLinks = pstate->p_hasSubLinks;
333
334         /* now the range table will not change */
335         qry->rtable = pstate->p_rtable;
336         qry->resultRelation = refnameRangeTablePosn(pstate, stmt->relname, NULL);
337
338         qry->groupClause = transformGroupClause(pstate,
339                                                                                         stmt->groupClause,
340                                                                                         qry->targetList);
341
342         /* fix order clause */
343         qry->sortClause = transformSortClause(pstate,
344                                                                                   NIL,
345                                                                                   NIL,
346                                                                                   qry->targetList,
347                                                                                   qry->uniqueFlag);
348
349         qry->hasAggs = pstate->p_hasAggs;
350         if (pstate->p_hasAggs)
351                 parseCheckAggregates(pstate, qry);
352
353         /* The INSERT INTO ... SELECT ... could have a UNION */
354         qry->unionall = stmt->unionall;         /* in child, so unionClause may be
355                                                                                  * false */
356         qry->unionClause = transformUnionClause(stmt->unionClause, qry->targetList);
357
358         return (Query *) qry;
359 }
360
361 /*
362  *      makeTableName()
363  *      Create a table name from a list of fields.
364  */
365 static char *
366 makeTableName(void *elem,...)
367 {
368         va_list         args;
369
370         char       *name;
371         char            buf[NAMEDATALEN + 1];
372
373         buf[0] = '\0';
374
375         va_start(args, elem);
376
377         name = elem;
378         while (name != NULL)
379         {
380                 /* not enough room for next part? then return nothing */
381                 if ((strlen(buf) + strlen(name)) >= (sizeof(buf) - 1))
382                         return (NULL);
383
384                 if (strlen(buf) > 0)
385                         strcat(buf, "_");
386                 strcat(buf, name);
387
388                 name = va_arg(args, void *);
389         }
390
391         va_end(args);
392
393         name = palloc(strlen(buf) + 1);
394         strcpy(name, buf);
395
396         return (name);
397 }
398
399 static char *
400 CreateIndexName(char *tname, char *cname, char *label, List *indices)
401 {
402         int                     pass = 0;
403         char       *iname = NULL;
404         List       *ilist;
405         IndexStmt  *index;
406         char            name2[NAMEDATALEN + 1];
407
408         /* use working storage, since we might be trying several possibilities */
409         strcpy(name2, cname);
410         while (iname == NULL)
411         {
412                 iname = makeTableName(tname, name2, label, NULL);
413                 /* unable to make a name at all? then quit */
414                 if (iname == NULL)
415                         break;
416
417                 ilist = indices;
418                 while (ilist != NIL)
419                 {
420                         index = lfirst(ilist);
421                         if (strcasecmp(iname, index->idxname) == 0)
422                                 break;
423
424                         ilist = lnext(ilist);
425                 }
426                 /* ran through entire list? then no name conflict found so done */
427                 if (ilist == NIL)
428                         break;
429
430                 /* the last one conflicted, so try a new name component */
431                 pfree(iname);
432                 iname = NULL;
433                 pass++;
434                 sprintf(name2, "%s_%d", cname, (pass + 1));
435         }
436
437         return (iname);
438 }
439
440 /*
441  * transformCreateStmt -
442  *        transforms the "create table" statement
443  *        SQL92 allows constraints to be scattered all over, so thumb through
444  *         the columns and collect all constraints into one place.
445  *        If there are any implied indices (e.g. UNIQUE or PRIMARY KEY)
446  *         then expand those into multiple IndexStmt blocks.
447  *        - thomas 1997-12-02
448  */
449 static Query *
450 transformCreateStmt(ParseState *pstate, CreateStmt *stmt)
451 {
452         Query      *q;
453         int                     have_pkey = FALSE;
454         List       *elements;
455         Node       *element;
456         List       *columns;
457         List       *dlist;
458         ColumnDef  *column;
459         List       *constraints,
460                            *clist;
461         Constraint *constraint;
462         List       *keys;
463         Ident      *key;
464         List       *ilist;
465         IndexStmt  *index;
466         IndexElem  *iparam;
467
468         q = makeNode(Query);
469         q->commandType = CMD_UTILITY;
470
471         elements = stmt->tableElts;
472         constraints = stmt->constraints;
473         columns = NIL;
474         dlist = NIL;
475
476         while (elements != NIL)
477         {
478                 element = lfirst(elements);
479                 switch (nodeTag(element))
480                 {
481                         case T_ColumnDef:
482                                 column = (ColumnDef *) element;
483                                 columns = lappend(columns, column);
484                                 if (column->constraints != NIL)
485                                 {
486                                         clist = column->constraints;
487                                         while (clist != NIL)
488                                         {
489                                                 constraint = lfirst(clist);
490                                                 switch (constraint->contype)
491                                                 {
492                                                         case CONSTR_NOTNULL:
493                                                                 if (column->is_not_null)
494                                                                         elog(ERROR, "CREATE TABLE/NOT NULL already specified"
495                                                                                  " for %s.%s", stmt->relname, column->colname);
496                                                                 column->is_not_null = TRUE;
497                                                                 break;
498
499                                                         case CONSTR_DEFAULT:
500                                                                 if (column->defval != NULL)
501                                                                         elog(ERROR, "CREATE TABLE/DEFAULT multiple values specified"
502                                                                                  " for %s.%s", stmt->relname, column->colname);
503                                                                 column->defval = constraint->def;
504                                                                 break;
505
506                                                         case CONSTR_PRIMARY:
507                                                                 if (constraint->name == NULL)
508                                                                         constraint->name = makeTableName(stmt->relname, "pkey", NULL);
509                                                                 if (constraint->keys == NIL)
510                                                                         constraint->keys = lappend(constraint->keys, column);
511                                                                 dlist = lappend(dlist, constraint);
512                                                                 break;
513
514                                                         case CONSTR_UNIQUE:
515                                                                 if (constraint->name == NULL)
516                                                                         constraint->name = makeTableName(stmt->relname, column->colname, "key", NULL);
517                                                                 if (constraint->keys == NIL)
518                                                                         constraint->keys = lappend(constraint->keys, column);
519                                                                 dlist = lappend(dlist, constraint);
520                                                                 break;
521
522                                                         case CONSTR_CHECK:
523                                                                 constraints = lappend(constraints, constraint);
524                                                                 if (constraint->name == NULL)
525                                                                         constraint->name = makeTableName(stmt->relname, column->colname, NULL);
526                                                                 break;
527
528                                                         default:
529                                                                 elog(ERROR, "parser: internal error; unrecognized constraint", NULL);
530                                                                 break;
531                                                 }
532                                                 clist = lnext(clist);
533                                         }
534                                 }
535                                 break;
536
537                         case T_Constraint:
538                                 constraint = (Constraint *) element;
539                                 switch (constraint->contype)
540                                 {
541                                         case CONSTR_PRIMARY:
542                                                 if (constraint->name == NULL)
543                                                         constraint->name = makeTableName(stmt->relname, "pkey", NULL);
544                                                 dlist = lappend(dlist, constraint);
545                                                 break;
546
547                                         case CONSTR_UNIQUE:
548 #if FALSE
549                                                 if (constraint->name == NULL)
550                                                         constraint->name = makeTableName(stmt->relname, "key", NULL);
551 #endif
552                                                 dlist = lappend(dlist, constraint);
553                                                 break;
554
555                                         case CONSTR_CHECK:
556                                                 constraints = lappend(constraints, constraint);
557                                                 break;
558
559                                         case CONSTR_NOTNULL:
560                                         case CONSTR_DEFAULT:
561                                                 elog(ERROR, "parser: internal error; illegal context for constraint", NULL);
562                                                 break;
563                                         default:
564                                                 elog(ERROR, "parser: internal error; unrecognized constraint", NULL);
565                                                 break;
566                                 }
567                                 break;
568
569                         default:
570                                 elog(ERROR, "parser: internal error; unrecognized node", NULL);
571                 }
572
573                 elements = lnext(elements);
574         }
575
576         stmt->tableElts = columns;
577         stmt->constraints = constraints;
578
579 /* Now run through the "deferred list" to complete the query transformation.
580  * For PRIMARY KEYs, mark each column as NOT NULL and create an index.
581  * For UNIQUE, create an index as for PRIMARY KEYS, but do not insist on NOT NULL.
582  *
583  * Note that this code does not currently look for all possible redundant cases
584  *      and either ignore or stop with warning. The create might fail later when
585  *      names for indices turn out to be redundant, or a user might have specified
586  *      extra useless indices which might hurt performance. - thomas 1997-12-08
587  */
588         ilist = NIL;
589         while (dlist != NIL)
590         {
591                 constraint = lfirst(dlist);
592                 if (nodeTag(constraint) != T_Constraint)
593                         elog(ERROR, "parser: internal error; unrecognized deferred node", NULL);
594
595                 if (constraint->contype == CONSTR_PRIMARY)
596                 {
597                         if (have_pkey)
598                                 elog(ERROR, "CREATE TABLE/PRIMARY KEY multiple primary keys"
599                                          " for table %s are not legal", stmt->relname);
600                         else
601                                 have_pkey = TRUE;
602                 }
603                 else if (constraint->contype != CONSTR_UNIQUE)
604                         elog(ERROR, "parser: internal error; unrecognized deferred constraint", NULL);
605
606                 index = makeNode(IndexStmt);
607
608                 index->unique = TRUE;
609                 if (constraint->name != NULL)
610                         index->idxname = constraint->name;
611                 else if (constraint->contype == CONSTR_PRIMARY)
612                 {
613                         if (have_pkey)
614                                 elog(ERROR, "CREATE TABLE/PRIMARY KEY multiple keys for table %s are not legal", stmt->relname);
615
616                         have_pkey = TRUE;
617                         index->idxname = makeTableName(stmt->relname, "pkey", NULL);
618                 }
619                 else
620                         index->idxname = NULL;
621
622                 index->relname = stmt->relname;
623                 index->accessMethod = "btree";
624                 index->indexParams = NIL;
625                 index->withClause = NIL;
626                 index->whereClause = NULL;
627
628                 keys = constraint->keys;
629                 while (keys != NIL)
630                 {
631                         key = lfirst(keys);
632                         columns = stmt->tableElts;
633                         column = NULL;
634                         while (columns != NIL)
635                         {
636                                 column = lfirst(columns);
637                                 if (strcasecmp(column->colname, key->name) == 0)
638                                         break;
639                                 else
640                                         column = NULL;
641                                 columns = lnext(columns);
642                         }
643                         if (column == NULL)
644                                 elog(ERROR, "parser: column '%s' in key does not exist", key->name);
645
646                         if (constraint->contype == CONSTR_PRIMARY)
647                                 column->is_not_null = TRUE;
648                         iparam = makeNode(IndexElem);
649                         iparam->name = strcpy(palloc(strlen(column->colname) + 1), column->colname);
650                         iparam->args = NIL;
651                         iparam->class = NULL;
652                         iparam->tname = NULL;
653                         index->indexParams = lappend(index->indexParams, iparam);
654
655                         if (index->idxname == NULL)
656                                 index->idxname = CreateIndexName(stmt->relname, iparam->name, "key", ilist);
657
658                         keys = lnext(keys);
659                 }
660
661                 if (index->idxname == NULL)
662                         elog(ERROR, "parser: unable to construct implicit index for table %s"
663                                  "; name too long", stmt->relname);
664                 else
665                         elog(NOTICE, "CREATE TABLE/%s will create implicit index %s for table %s",
666                                  ((constraint->contype == CONSTR_PRIMARY) ? "PRIMARY KEY" : "UNIQUE"),
667                                  index->idxname, stmt->relname);
668
669                 ilist = lappend(ilist, index);
670                 dlist = lnext(dlist);
671         }
672
673         q->utilityStmt = (Node *) stmt;
674         extras = ilist;
675
676         return q;
677 }
678
679 /*
680  * transformIndexStmt -
681  *        transforms the qualification of the index statement
682  */
683 static Query *
684 transformIndexStmt(ParseState *pstate, IndexStmt *stmt)
685 {
686         Query      *qry;
687
688         qry = makeNode(Query);
689         qry->commandType = CMD_UTILITY;
690
691         /* take care of the where clause */
692         stmt->whereClause = transformWhereClause(pstate, stmt->whereClause);
693         qry->hasSubLinks = pstate->p_hasSubLinks;
694
695         stmt->rangetable = pstate->p_rtable;
696
697         qry->utilityStmt = (Node *) stmt;
698
699         return qry;
700 }
701
702 /*
703  * transformExtendStmt -
704  *        transform the qualifications of the Extend Index Statement
705  *
706  */
707 static Query *
708 transformExtendStmt(ParseState *pstate, ExtendStmt *stmt)
709 {
710         Query      *qry;
711
712         qry = makeNode(Query);
713         qry->commandType = CMD_UTILITY;
714
715         /* take care of the where clause */
716         stmt->whereClause = transformWhereClause(pstate, stmt->whereClause);
717         qry->hasSubLinks = pstate->p_hasSubLinks;
718
719         stmt->rangetable = pstate->p_rtable;
720
721         qry->utilityStmt = (Node *) stmt;
722         return qry;
723 }
724
725 /*
726  * transformRuleStmt -
727  *        transform a Create Rule Statement. The actions is a list of parse
728  *        trees which is transformed into a list of query trees.
729  */
730 static Query *
731 transformRuleStmt(ParseState *pstate, RuleStmt *stmt)
732 {
733         Query      *qry;
734         List       *actions;
735
736         qry = makeNode(Query);
737         qry->commandType = CMD_UTILITY;
738
739         actions = stmt->actions;
740
741         /*
742          * transform each statment, like parse_analyze()
743          */
744         while (actions != NIL)
745         {
746
747                 /*
748                  * NOTE: 'CURRENT' must always have a varno equal to 1 and 'NEW'
749                  * equal to 2.
750                  */
751                 addRangeTableEntry(pstate, stmt->object->relname, "*CURRENT*",
752                                                    FALSE, FALSE);
753                 addRangeTableEntry(pstate, stmt->object->relname, "*NEW*",
754                                                    FALSE, FALSE);
755
756                 pstate->p_last_resno = 1;
757                 pstate->p_is_rule = true;               /* for expand all */
758                 pstate->p_hasAggs = false;
759
760                 lfirst(actions) = transformStmt(pstate, lfirst(actions));
761                 actions = lnext(actions);
762         }
763
764         /* take care of the where clause */
765         stmt->whereClause = transformWhereClause(pstate, stmt->whereClause);
766         qry->hasSubLinks = pstate->p_hasSubLinks;
767
768         qry->utilityStmt = (Node *) stmt;
769         return qry;
770 }
771
772
773 /*
774  * transformSelectStmt -
775  *        transforms a Select Statement
776  *
777  */
778 static Query *
779 transformSelectStmt(ParseState *pstate, SelectStmt *stmt)
780 {
781         Query      *qry = makeNode(Query);
782
783         qry->commandType = CMD_SELECT;
784
785         /* set up a range table */
786         makeRangeTable(pstate, NULL, stmt->fromClause);
787
788         qry->uniqueFlag = stmt->unique;
789
790         qry->into = stmt->into;
791         qry->isPortal = FALSE;
792
793         qry->targetList = transformTargetList(pstate, stmt->targetList);
794
795         qry->qual = transformWhereClause(pstate, stmt->whereClause);
796
797         qry->havingQual = transformWhereClause(pstate, stmt->havingClause);
798
799         qry->hasSubLinks = pstate->p_hasSubLinks;
800
801         qry->sortClause = transformSortClause(pstate,
802                                                                                   stmt->sortClause,
803                                                                                   NIL,
804                                                                                   qry->targetList,
805                                                                                   qry->uniqueFlag);
806
807         qry->groupClause = transformGroupClause(pstate,
808                                                                                         stmt->groupClause,
809                                                                                         qry->targetList);
810         qry->rtable = pstate->p_rtable;
811
812         qry->hasAggs = pstate->p_hasAggs;
813         if (pstate->p_hasAggs)
814                 parseCheckAggregates(pstate, qry);
815
816         qry->unionall = stmt->unionall;         /* in child, so unionClause may be
817                                                                                  * false */
818         qry->unionClause = transformUnionClause(stmt->unionClause, qry->targetList);
819
820         return (Query *) qry;
821 }
822
823 /*
824  * transformUpdateStmt -
825  *        transforms an update statement
826  *
827  */
828 static Query *
829 transformUpdateStmt(ParseState *pstate, UpdateStmt *stmt)
830 {
831         Query      *qry = makeNode(Query);
832
833         qry->commandType = CMD_UPDATE;
834         pstate->p_is_update = true;
835
836         /*
837          * the FROM clause is non-standard SQL syntax. We used to be able to
838          * do this with REPLACE in POSTQUEL so we keep the feature.
839          */
840         makeRangeTable(pstate, stmt->relname, stmt->fromClause);
841
842         qry->targetList = transformTargetList(pstate, stmt->targetList);
843
844         qry->qual = transformWhereClause(pstate, stmt->whereClause);
845         qry->hasSubLinks = pstate->p_hasSubLinks;
846
847         qry->rtable = pstate->p_rtable;
848
849         qry->resultRelation = refnameRangeTablePosn(pstate, stmt->relname, NULL);
850
851         qry->hasAggs = pstate->p_hasAggs;
852         if (pstate->p_hasAggs)
853                 parseCheckAggregates(pstate, qry);
854
855         return (Query *) qry;
856 }
857
858 /*
859  * transformCursorStmt -
860  *        transform a Create Cursor Statement
861  *
862  */
863 static Query *
864 transformCursorStmt(ParseState *pstate, SelectStmt *stmt)
865 {
866         Query      *qry;
867
868         qry = transformSelectStmt(pstate, stmt);
869
870         qry->into = stmt->portalname;
871         qry->isPortal = TRUE;
872         qry->isBinary = stmt->binary;           /* internal portal */
873
874         return qry;
875 }