1 /*-------------------------------------------------------------------------
4 * transform the parse tree into a query tree
6 * Copyright (c) 1994, Regents of the University of California
10 * $Header: /cvsroot/pgsql/src/backend/parser/analyze.c,v 1.68 1998/01/20 22:11:51 momjian Exp $
12 *-------------------------------------------------------------------------
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"
34 static Query *transformStmt(ParseState *pstate, Node *stmt);
35 static Query *transformDeleteStmt(ParseState *pstate, DeleteStmt *stmt);
36 static Query *transformInsertStmt(ParseState *pstate, InsertStmt *stmt);
37 static Query *transformIndexStmt(ParseState *pstate, IndexStmt *stmt);
38 static Query *transformExtendStmt(ParseState *pstate, ExtendStmt *stmt);
39 static Query *transformRuleStmt(ParseState *query, RuleStmt *stmt);
40 static Query *transformSelectStmt(ParseState *pstate, SelectStmt *stmt);
41 static Query *transformUpdateStmt(ParseState *pstate, UpdateStmt *stmt);
42 static Query *transformCursorStmt(ParseState *pstate, SelectStmt *stmt);
43 static Query *transformCreateStmt(ParseState *pstate, CreateStmt *stmt);
49 * analyze a list of parse trees and transform them if necessary.
51 * Returns a list of transformed parse trees. Optimizable statements are
52 * all transformed to Query while the rest stays the same.
56 parse_analyze(List *pl, ParseState *parentParseState)
58 QueryTreeList *result;
62 result = malloc(sizeof(QueryTreeList));
63 result->len = length(pl);
64 result->qtrees = (Query **) malloc(result->len * sizeof(Query *));
68 pstate = make_parsestate(parentParseState);
69 result->qtrees[i++] = transformStmt(pstate, lfirst(pl));
70 if (pstate->p_target_relation != NULL)
71 heap_close(pstate->p_target_relation);
75 result->len += length(extras);
76 result->qtrees = (Query **) realloc(result->qtrees, result->len * sizeof(Query *));
79 result->qtrees[i++] = transformStmt(pstate, lfirst(extras));
80 if (pstate->p_target_relation != NULL)
81 heap_close(pstate->p_target_relation);
82 extras = lnext(extras);
95 * transform a Parse tree. If it is an optimizable statement, turn it
99 transformStmt(ParseState *pstate, Node *parseTree)
101 Query *result = NULL;
103 switch (nodeTag(parseTree))
105 /*------------------------
106 * Non-optimizable statements
107 *------------------------
110 result = transformCreateStmt(pstate, (CreateStmt *) parseTree);
114 result = transformIndexStmt(pstate, (IndexStmt *) parseTree);
118 result = transformExtendStmt(pstate, (ExtendStmt *) parseTree);
122 result = transformRuleStmt(pstate, (RuleStmt *) parseTree);
127 ViewStmt *n = (ViewStmt *) parseTree;
129 n->query = (Query *) transformStmt(pstate, (Node *) n->query);
130 result = makeNode(Query);
131 result->commandType = CMD_UTILITY;
132 result->utilityStmt = (Node *) n;
138 MemoryContext oldcontext;
141 * make sure that this Query is allocated in TopMemory
142 * context because vacuum spans transactions and we don't
143 * want to lose the vacuum Query due to end-of-transaction
146 oldcontext = MemoryContextSwitchTo(TopMemoryContext);
147 result = makeNode(Query);
148 result->commandType = CMD_UTILITY;
149 result->utilityStmt = (Node *) parseTree;
150 MemoryContextSwitchTo(oldcontext);
156 ExplainStmt *n = (ExplainStmt *) parseTree;
158 result = makeNode(Query);
159 result->commandType = CMD_UTILITY;
160 n->query = transformStmt(pstate, (Node *) n->query);
161 result->utilityStmt = (Node *) parseTree;
165 /*------------------------
166 * Optimizable statements
167 *------------------------
170 result = transformInsertStmt(pstate, (InsertStmt *) parseTree);
174 result = transformDeleteStmt(pstate, (DeleteStmt *) parseTree);
178 result = transformUpdateStmt(pstate, (UpdateStmt *) parseTree);
182 if (!((SelectStmt *)parseTree)->portalname)
183 result = transformSelectStmt(pstate, (SelectStmt *) parseTree);
185 result = transformCursorStmt(pstate, (SelectStmt *) parseTree);
191 * other statments don't require any transformation-- just
192 * return the original parsetree, yea!
194 result = makeNode(Query);
195 result->commandType = CMD_UTILITY;
196 result->utilityStmt = (Node *) parseTree;
203 * transformDeleteStmt -
204 * transforms a Delete Statement
207 transformDeleteStmt(ParseState *pstate, DeleteStmt *stmt)
209 Query *qry = makeNode(Query);
211 qry->commandType = CMD_DELETE;
213 /* set up a range table */
214 makeRangeTable(pstate, stmt->relname, NULL);
216 qry->uniqueFlag = NULL;
218 /* fix where clause */
219 qry->qual = transformWhereClause(pstate, stmt->whereClause);
221 qry->rtable = pstate->p_rtable;
222 qry->resultRelation = refnameRangeTablePosn(pstate, stmt->relname, NULL);
224 qry->hasAggs = pstate->p_hasAggs;
225 if (pstate->p_hasAggs)
226 parseCheckAggregates(pstate, qry);
228 return (Query *) qry;
232 * transformInsertStmt -
233 * transform an Insert Statement
236 transformInsertStmt(ParseState *pstate, InsertStmt *stmt)
238 Query *qry = makeNode(Query); /* make a new query tree */
241 qry->commandType = CMD_INSERT;
242 pstate->p_is_insert = true;
244 /* set up a range table */
245 makeRangeTable(pstate, stmt->relname, stmt->fromClause);
247 qry->uniqueFlag = stmt->unique;
249 /* fix the target list */
250 icolumns = pstate->p_insert_columns = makeTargetNames(pstate, stmt->cols);
252 qry->targetList = transformTargetList(pstate, stmt->targetList);
254 /* DEFAULT handling */
255 if (length(qry->targetList) < pstate->p_target_relation->rd_att->natts &&
256 pstate->p_target_relation->rd_att->constr &&
257 pstate->p_target_relation->rd_att->constr->num_defval > 0)
259 AttributeTupleForm *att = pstate->p_target_relation->rd_att->attrs;
260 AttrDefault *defval = pstate->p_target_relation->rd_att->constr->defval;
261 int ndef = pstate->p_target_relation->rd_att->constr->num_defval;
264 * if stmt->cols == NIL then makeTargetNames returns list of all
265 * attrs: have to shorter icolumns list...
267 if (stmt->cols == NIL)
270 int i = length(qry->targetList);
272 foreach (extrl, icolumns)
277 freeList (lnext(extrl));
287 foreach (tl, icolumns)
289 id = (Ident *) lfirst(tl);
290 if (!namestrcmp(&(att[defval[ndef].adnum - 1]->attname), id->name))
293 if (tl != NIL) /* something given for this attr */
296 * Nothing given for this attr with DEFAULT expr, so
297 * add new TargetEntry to qry->targetList.
298 * Note, that we set resno to defval[ndef].adnum:
299 * it's what transformTargetList()->make_targetlist_expr()
300 * does for INSERT ... SELECT. But for INSERT ... VALUES
301 * pstate->p_last_resno is used. It doesn't matter for
302 * "normal" using (planner creates proper target list
303 * in preptlist.c), but may break RULEs in some way.
304 * It seems better to create proper target list here...
306 te = makeNode(TargetEntry);
307 te->resdom = makeResdom(defval[ndef].adnum,
308 att[defval[ndef].adnum - 1]->atttypid,
309 att[defval[ndef].adnum - 1]->attlen,
310 pstrdup(nameout(&(att[defval[ndef].adnum - 1]->attname))),
313 te->expr = (Node *) stringToNode(defval[ndef].adbin);
314 qry->targetList = lappend (qry->targetList, te);
318 /* fix where clause */
319 qry->qual = transformWhereClause(pstate, stmt->whereClause);
321 /* now the range table will not change */
322 qry->rtable = pstate->p_rtable;
323 qry->resultRelation = refnameRangeTablePosn(pstate, stmt->relname, NULL);
325 qry->groupClause = transformGroupClause(pstate,
329 /* fix order clause */
330 qry->sortClause = transformSortClause(pstate,
336 qry->hasAggs = pstate->p_hasAggs;
337 if (pstate->p_hasAggs)
338 parseCheckAggregates(pstate, qry);
340 /* The INSERT INTO ... SELECT ... could have a UNION */
341 qry->unionall = stmt->unionall; /* in child, so unionClause may be false */
342 qry->unionClause = transformUnionClause(stmt->unionClause, qry->targetList);
344 return (Query *) qry;
349 * Create a table name from a list of fields.
352 makeTableName(void *elem,...)
357 char buf[NAMEDATALEN+1];
366 /* not enough room for next part? then return nothing */
367 if ((strlen(buf)+strlen(name)) >= (sizeof(buf)-1))
374 name = va_arg(args,void *);
379 name = palloc(strlen(buf)+1);
386 CreateIndexName(char *tname, char *cname, char *label, List *indices)
392 char name2[NAMEDATALEN+1];
394 /* use working storage, since we might be trying several possibilities */
396 while (iname == NULL)
398 iname = makeTableName(tname, name2, label, NULL);
399 /* unable to make a name at all? then quit */
406 index = lfirst(ilist);
407 if (strcasecmp(iname,index->idxname) == 0)
410 ilist = lnext(ilist);
412 /* ran through entire list? then no name conflict found so done */
416 /* the last one conflicted, so try a new name component */
420 sprintf(name2, "%s_%d", cname, (pass+1));
427 * transformCreateStmt -
428 * transforms the "create table" statement
429 * SQL92 allows constraints to be scattered all over, so thumb through
430 * the columns and collect all constraints into one place.
431 * If there are any implied indices (e.g. UNIQUE or PRIMARY KEY)
432 * then expand those into multiple IndexStmt blocks.
433 * - thomas 1997-12-02
436 transformCreateStmt(ParseState *pstate, CreateStmt *stmt)
439 int have_pkey = FALSE;
445 List *constraints, *clist;
446 Constraint *constraint;
454 q->commandType = CMD_UTILITY;
456 elements = stmt->tableElts;
457 constraints = stmt->constraints;
461 while (elements != NIL)
463 element = lfirst(elements);
464 switch (nodeTag(element))
467 column = (ColumnDef *) element;
468 columns = lappend(columns,column);
469 if (column->constraints != NIL)
471 clist = column->constraints;
474 constraint = lfirst(clist);
475 switch (constraint->contype)
478 if (column->is_not_null)
479 elog(ERROR,"CREATE TABLE/NOT NULL already specified"
480 " for %s.%s", stmt->relname, column->colname);
481 column->is_not_null = TRUE;
485 if (column->defval != NULL)
486 elog(ERROR,"CREATE TABLE/DEFAULT multiple values specified"
487 " for %s.%s", stmt->relname, column->colname);
488 column->defval = constraint->def;
492 if (constraint->name == NULL)
493 constraint->name = makeTableName(stmt->relname, "pkey", NULL);
494 if (constraint->keys == NIL)
495 constraint->keys = lappend(constraint->keys, column);
496 dlist = lappend(dlist, constraint);
500 if (constraint->name == NULL)
501 constraint->name = makeTableName(stmt->relname, column->colname, "key", NULL);
502 if (constraint->keys == NIL)
503 constraint->keys = lappend(constraint->keys, column);
504 dlist = lappend(dlist, constraint);
508 constraints = lappend(constraints, constraint);
509 if (constraint->name == NULL)
510 constraint->name = makeTableName(stmt->relname, column->colname, NULL);
514 elog(ERROR,"parser: internal error; unrecognized constraint",NULL);
517 clist = lnext(clist);
523 constraint = (Constraint *) element;
524 switch (constraint->contype)
527 if (constraint->name == NULL)
528 constraint->name = makeTableName(stmt->relname, "pkey", NULL);
529 dlist = lappend(dlist, constraint);
534 if (constraint->name == NULL)
535 constraint->name = makeTableName(stmt->relname, "key", NULL);
537 dlist = lappend(dlist, constraint);
541 constraints = lappend(constraints, constraint);
546 elog(ERROR,"parser: internal error; illegal context for constraint",NULL);
549 elog(ERROR,"parser: internal error; unrecognized constraint",NULL);
555 elog(ERROR,"parser: internal error; unrecognized node",NULL);
558 elements = lnext(elements);
561 stmt->tableElts = columns;
562 stmt->constraints = constraints;
564 /* Now run through the "deferred list" to complete the query transformation.
565 * For PRIMARY KEYs, mark each column as NOT NULL and create an index.
566 * For UNIQUE, create an index as for PRIMARY KEYS, but do not insist on NOT NULL.
568 * Note that this code does not currently look for all possible redundant cases
569 * and either ignore or stop with warning. The create might fail later when
570 * names for indices turn out to be redundant, or a user might have specified
571 * extra useless indices which might hurt performance. - thomas 1997-12-08
576 constraint = lfirst(dlist);
577 if (nodeTag(constraint) != T_Constraint)
578 elog(ERROR,"parser: internal error; unrecognized deferred node",NULL);
580 if (constraint->contype == CONSTR_PRIMARY)
582 elog(ERROR,"CREATE TABLE/PRIMARY KEY multiple primary keys"
583 " for table %s are not legal", stmt->relname);
586 else if (constraint->contype != CONSTR_UNIQUE)
587 elog(ERROR,"parser: internal error; unrecognized deferred constraint",NULL);
589 index = makeNode(IndexStmt);
591 index->unique = TRUE;
592 if (constraint->name != NULL)
593 index->idxname = constraint->name;
594 else if (constraint->contype == CONSTR_PRIMARY)
597 elog(ERROR,"CREATE TABLE/PRIMARY KEY multiple keys for table %s are not legal", stmt->relname);
600 index->idxname = makeTableName(stmt->relname, "pkey", NULL);
603 index->idxname = NULL;
605 index->relname = stmt->relname;
606 index->accessMethod = "btree";
607 index->indexParams = NIL;
608 index->withClause = NIL;
609 index->whereClause = NULL;
611 keys = constraint->keys;
615 columns = stmt->tableElts;
617 while (columns != NIL)
619 column = lfirst(columns);
620 if (strcasecmp(column->colname,key->name) == 0) break;
622 columns = lnext(columns);
625 elog(ERROR,"parser: column '%s' in key does not exist",key->name);
627 if (constraint->contype == CONSTR_PRIMARY)
628 column->is_not_null = TRUE;
629 iparam = makeNode(IndexElem);
630 iparam->name = strcpy(palloc(strlen(column->colname)+1), column->colname);
632 iparam->class = NULL;
633 iparam->tname = NULL;
634 index->indexParams = lappend(index->indexParams, iparam);
636 if (index->idxname == NULL)
637 index->idxname = CreateIndexName(stmt->relname, iparam->name, "key", ilist);
642 if (index->idxname == NULL)
643 elog(ERROR,"parser: unable to construct implicit index for table %s"
644 "; name too long", stmt->relname);
646 elog(NOTICE,"CREATE TABLE/%s will create implicit index %s for table %s",
647 ((constraint->contype == CONSTR_PRIMARY)? "PRIMARY KEY": "UNIQUE"),
648 index->idxname, stmt->relname);
650 ilist = lappend(ilist, index);
651 dlist = lnext(dlist);
654 q->utilityStmt = (Node *) stmt;
661 * transformIndexStmt -
662 * transforms the qualification of the index statement
665 transformIndexStmt(ParseState *pstate, IndexStmt *stmt)
670 q->commandType = CMD_UTILITY;
672 /* take care of the where clause */
673 stmt->whereClause = transformWhereClause(pstate, stmt->whereClause);
674 stmt->rangetable = pstate->p_rtable;
676 q->utilityStmt = (Node *) stmt;
682 * transformExtendStmt -
683 * transform the qualifications of the Extend Index Statement
687 transformExtendStmt(ParseState *pstate, ExtendStmt *stmt)
692 q->commandType = CMD_UTILITY;
694 /* take care of the where clause */
695 stmt->whereClause = transformWhereClause(pstate, stmt->whereClause);
696 stmt->rangetable = pstate->p_rtable;
698 q->utilityStmt = (Node *) stmt;
703 * transformRuleStmt -
704 * transform a Create Rule Statement. The actions is a list of parse
705 * trees which is transformed into a list of query trees.
708 transformRuleStmt(ParseState *pstate, RuleStmt *stmt)
714 q->commandType = CMD_UTILITY;
716 actions = stmt->actions;
719 * transform each statment, like parse_analyze()
721 while (actions != NIL)
725 * NOTE: 'CURRENT' must always have a varno equal to 1 and 'NEW'
728 addRangeTableEntry(pstate, stmt->object->relname, "*CURRENT*",
730 addRangeTableEntry(pstate, stmt->object->relname, "*NEW*",
733 pstate->p_last_resno = 1;
734 pstate->p_is_rule = true; /* for expand all */
735 pstate->p_hasAggs = false;
737 lfirst(actions) = transformStmt(pstate, lfirst(actions));
738 actions = lnext(actions);
741 /* take care of the where clause */
742 stmt->whereClause = transformWhereClause(pstate, stmt->whereClause);
744 q->utilityStmt = (Node *) stmt;
750 * transformSelectStmt -
751 * transforms a Select Statement
755 transformSelectStmt(ParseState *pstate, SelectStmt *stmt)
757 Query *qry = makeNode(Query);
759 qry->commandType = CMD_SELECT;
761 /* set up a range table */
762 makeRangeTable(pstate, NULL, stmt->fromClause);
764 qry->uniqueFlag = stmt->unique;
766 qry->into = stmt->into;
767 qry->isPortal = FALSE;
769 qry->targetList = transformTargetList(pstate, stmt->targetList);
771 qry->qual = transformWhereClause(pstate, stmt->whereClause);
773 qry->sortClause = transformSortClause(pstate,
779 qry->groupClause = transformGroupClause(pstate,
782 qry->rtable = pstate->p_rtable;
784 qry->hasAggs = pstate->p_hasAggs;
785 if (pstate->p_hasAggs)
786 parseCheckAggregates(pstate, qry);
788 qry->unionall = stmt->unionall; /* in child, so unionClause may be false */
789 qry->unionClause = transformUnionClause(stmt->unionClause, qry->targetList);
791 return (Query *) qry;
795 * transformUpdateStmt -
796 * transforms an update statement
800 transformUpdateStmt(ParseState *pstate, UpdateStmt *stmt)
802 Query *qry = makeNode(Query);
804 qry->commandType = CMD_UPDATE;
805 pstate->p_is_update = true;
808 * the FROM clause is non-standard SQL syntax. We used to be able to
809 * do this with REPLACE in POSTQUEL so we keep the feature.
811 makeRangeTable(pstate, stmt->relname, stmt->fromClause);
813 qry->targetList = transformTargetList(pstate, stmt->targetList);
815 qry->qual = transformWhereClause(pstate, stmt->whereClause);
817 qry->rtable = pstate->p_rtable;
819 qry->resultRelation = refnameRangeTablePosn(pstate, stmt->relname, NULL);
821 qry->hasAggs = pstate->p_hasAggs;
822 if (pstate->p_hasAggs)
823 parseCheckAggregates(pstate, qry);
825 return (Query *) qry;
829 * transformCursorStmt -
830 * transform a Create Cursor Statement
834 transformCursorStmt(ParseState *pstate, SelectStmt *stmt)
838 qry = transformSelectStmt(pstate, stmt);
840 qry->into = stmt->portalname;
841 qry->isPortal = TRUE;
842 qry->isBinary = stmt->binary; /* internal portal */