analyze.c 22.0 KB
Newer Older
1 2 3
/*-------------------------------------------------------------------------
 *
 * analyze.c--
4
 *	  transform the parse tree into a query tree
5 6 7 8 9
 *
 * Copyright (c) 1994, Regents of the University of California
 *
 *
 * IDENTIFICATION
10
 *	  $Header: /cvsroot/pgsql/src/backend/parser/analyze.c,v 1.76 1998/05/29 13:39:30 thomas Exp $
11 12 13
 *
 *-------------------------------------------------------------------------
 */
14

15 16
#include <stdio.h>
#include <stdlib.h>
17
#include <stdarg.h>
18
#include <string.h>
V
Vadim B. Mikheev 已提交
19

B
Bruce Momjian 已提交
20
#include "postgres.h"
21 22 23 24 25 26
#include "access/heapam.h"
#include "nodes/makefuncs.h"
#include "nodes/memnodes.h"
#include "nodes/pg_list.h"
#include "parser/analyze.h"
#include "parser/parse_agg.h"
B
Bruce Momjian 已提交
27
#include "parser/parse_clause.h"
28 29 30 31 32
#include "parser/parse_node.h"
#include "parser/parse_relation.h"
#include "parser/parse_target.h"
#include "utils/builtins.h"
#include "utils/mcxt.h"
33 34 35
#ifdef PARSEDEBUG
#include "nodes/print.h"
#endif
36

37 38
static Query *transformStmt(ParseState *pstate, Node *stmt);
static Query *transformDeleteStmt(ParseState *pstate, DeleteStmt *stmt);
B
Bruce Momjian 已提交
39
static Query *transformInsertStmt(ParseState *pstate, InsertStmt *stmt);
40 41 42
static Query *transformIndexStmt(ParseState *pstate, IndexStmt *stmt);
static Query *transformExtendStmt(ParseState *pstate, ExtendStmt *stmt);
static Query *transformRuleStmt(ParseState *query, RuleStmt *stmt);
B
Bruce Momjian 已提交
43 44
static Query *transformSelectStmt(ParseState *pstate, SelectStmt *stmt);
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;
B
Bruce Momjian 已提交
49

50 51
/*
 * parse_analyze -
52
 *	  analyze a list of parse trees and transform them if necessary.
53 54 55 56 57
 *
 * Returns a list of transformed parse trees. Optimizable statements are
 * all transformed to Query while the rest stays the same.
 *
 */
58
QueryTreeList *
59
parse_analyze(List *pl, ParseState *parentParseState)
60
{
61 62 63
	QueryTreeList *result;
	ParseState *pstate;
	int			i = 0;
64 65 66 67 68 69 70

	result = malloc(sizeof(QueryTreeList));
	result->len = length(pl);
	result->qtrees = (Query **) malloc(result->len * sizeof(Query *));

	while (pl != NIL)
	{
71 72 73 74
#ifdef PARSEDEBUG
		elog(DEBUG,"parse tree from yacc:\n---\n%s\n---\n", nodeToString(lfirst(pl)));
#endif

75
		pstate = make_parsestate(parentParseState);
76
		result->qtrees[i++] = transformStmt(pstate, lfirst(pl));
B
Bruce Momjian 已提交
77 78 79
		if (pstate->p_target_relation != NULL)
			heap_close(pstate->p_target_relation);

80 81 82 83 84 85 86
		if (extras != NIL)
		{
			result->len += length(extras);
			result->qtrees = (Query **) realloc(result->qtrees, result->len * sizeof(Query *));
			while (extras != NIL)
			{
				result->qtrees[i++] = transformStmt(pstate, lfirst(extras));
B
Bruce Momjian 已提交
87 88
				if (pstate->p_target_relation != NULL)
					heap_close(pstate->p_target_relation);
89 90 91 92
				extras = lnext(extras);
			}
		}
		extras = NIL;
93
		pl = lnext(pl);
B
Bruce Momjian 已提交
94
		pfree(pstate);
95 96 97
	}

	return result;
98 99 100 101
}

/*
 * transformStmt -
102 103
 *	  transform a Parse tree. If it is an optimizable statement, turn it
 *	  into a Query tree.
104
 */
105
static Query *
106
transformStmt(ParseState *pstate, Node *parseTree)
107
{
108
	Query	   *result = NULL;
109 110 111

	switch (nodeTag(parseTree))
	{
112 113 114 115
			/*------------------------
			 *	Non-optimizable statements
			 *------------------------
			 */
116 117 118 119
		case T_CreateStmt:
			result = transformCreateStmt(pstate, (CreateStmt *) parseTree);
			break;

120 121 122
		case T_IndexStmt:
			result = transformIndexStmt(pstate, (IndexStmt *) parseTree);
			break;
123

124 125 126
		case T_ExtendStmt:
			result = transformExtendStmt(pstate, (ExtendStmt *) parseTree);
			break;
127

128 129 130
		case T_RuleStmt:
			result = transformRuleStmt(pstate, (RuleStmt *) parseTree);
			break;
131

132 133 134
		case T_ViewStmt:
			{
				ViewStmt   *n = (ViewStmt *) parseTree;
135

136 137 138 139 140 141
				n->query = (Query *) transformStmt(pstate, (Node *) n->query);
				result = makeNode(Query);
				result->commandType = CMD_UTILITY;
				result->utilityStmt = (Node *) n;
			}
			break;
142

143 144 145
		case T_VacuumStmt:
			{
				MemoryContext oldcontext;
146

147 148 149 150 151 152 153 154 155 156 157 158
				/*
				 * make sure that this Query is allocated in TopMemory
				 * context because vacuum spans transactions and we don't
				 * want to lose the vacuum Query due to end-of-transaction
				 * free'ing
				 */
				oldcontext = MemoryContextSwitchTo(TopMemoryContext);
				result = makeNode(Query);
				result->commandType = CMD_UTILITY;
				result->utilityStmt = (Node *) parseTree;
				MemoryContextSwitchTo(oldcontext);
				break;
159

160 161 162 163
			}
		case T_ExplainStmt:
			{
				ExplainStmt *n = (ExplainStmt *) parseTree;
164

165 166 167 168 169 170
				result = makeNode(Query);
				result->commandType = CMD_UTILITY;
				n->query = transformStmt(pstate, (Node *) n->query);
				result->utilityStmt = (Node *) parseTree;
			}
			break;
171

172 173 174 175
			/*------------------------
			 *	Optimizable statements
			 *------------------------
			 */
B
Bruce Momjian 已提交
176 177
		case T_InsertStmt:
			result = transformInsertStmt(pstate, (InsertStmt *) parseTree);
178
			break;
179

180 181 182
		case T_DeleteStmt:
			result = transformDeleteStmt(pstate, (DeleteStmt *) parseTree);
			break;
183

B
Bruce Momjian 已提交
184 185
		case T_UpdateStmt:
			result = transformUpdateStmt(pstate, (UpdateStmt *) parseTree);
186
			break;
187

B
Bruce Momjian 已提交
188
		case T_SelectStmt:
189
			if (!((SelectStmt *) parseTree)->portalname)
190 191 192
				result = transformSelectStmt(pstate, (SelectStmt *) parseTree);
			else
				result = transformCursorStmt(pstate, (SelectStmt *) parseTree);
193
			break;
194

195
		default:
196

197 198
			/*
			 * other statments don't require any transformation-- just
B
Bruce Momjian 已提交
199
			 * return the original parsetree, yea!
200 201 202 203 204
			 */
			result = makeNode(Query);
			result->commandType = CMD_UTILITY;
			result->utilityStmt = (Node *) parseTree;
			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 221
	/* set up a range table */
	makeRangeTable(pstate, stmt->relname, NULL);
222

223
	qry->uniqueFlag = NULL;
224

225 226
	/* fix where clause */
	qry->qual = transformWhereClause(pstate, stmt->whereClause);
B
Bruce Momjian 已提交
227
	qry->hasSubLinks = pstate->p_hasSubLinks;
228

229
	qry->rtable = pstate->p_rtable;
230
	qry->resultRelation = refnameRangeTablePosn(pstate, stmt->relname, NULL);
231

B
Bruce Momjian 已提交
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 *
B
Bruce Momjian 已提交
244
transformInsertStmt(ParseState *pstate, InsertStmt *stmt)
245
{
246
	Query	   *qry = makeNode(Query);	/* make a new query tree */
247
	List	   *icolumns;
248

249 250
	qry->commandType = CMD_INSERT;
	pstate->p_is_insert = true;
251

252 253
	/* set up a range table */
	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 263 264 265 266
	/* DEFAULT handling */
	if (length(qry->targetList) < pstate->p_target_relation->rd_att->natts &&
		pstate->p_target_relation->rd_att->constr &&
		pstate->p_target_relation->rd_att->constr->num_defval > 0)
	{
267 268 269 270 271
		AttributeTupleForm *att = pstate->p_target_relation->rd_att->attrs;
		AttrDefault *defval = pstate->p_target_relation->rd_att->constr->defval;
		int			ndef = pstate->p_target_relation->rd_att->constr->num_defval;

		/*
B
Bruce Momjian 已提交
272
		 * if stmt->cols == NIL then makeTargetNames returns list of all
273 274 275 276
		 * attrs: have to shorter icolumns list...
		 */
		if (stmt->cols == NIL)
		{
277 278 279 280
			List	   *extrl;
			int			i = length(qry->targetList);

			foreach(extrl, icolumns)
281 282 283 284
			{
				if (--i <= 0)
					break;
			}
285
			freeList(lnext(extrl));
286 287
			lnext(extrl) = NIL;
		}
288

289 290
		while (ndef-- > 0)
		{
291 292 293 294 295
			List	   *tl;
			Ident	   *id;
			TargetEntry *te;

			foreach(tl, icolumns)
296 297 298 299 300 301 302
			{
				id = (Ident *) lfirst(tl);
				if (!namestrcmp(&(att[defval[ndef].adnum - 1]->attname), id->name))
					break;
			}
			if (tl != NIL)		/* something given for this attr */
				continue;
303 304 305 306 307 308 309 310 311 312 313

			/*
			 * Nothing given for this attr with DEFAULT expr, so add new
			 * TargetEntry to qry->targetList. Note, that we set resno to
			 * defval[ndef].adnum: it's what
			 * transformTargetList()->make_targetlist_expr() does for
			 * INSERT ... SELECT. But for INSERT ... VALUES
			 * pstate->p_last_resno is used. It doesn't matter for
			 * "normal" using (planner creates proper target list in
			 * preptlist.c), but may break RULEs in some way. It seems
			 * better to create proper target list here...
314 315 316 317
			 */
			te = makeNode(TargetEntry);
			te->resdom = makeResdom(defval[ndef].adnum,
									att[defval[ndef].adnum - 1]->atttypid,
318 319
									att[defval[ndef].adnum - 1]->atttypmod,
									pstrdup(nameout(&(att[defval[ndef].adnum - 1]->attname))),
320 321 322
									0, 0, 0);
			te->fjoin = NULL;
			te->expr = (Node *) stringToNode(defval[ndef].adbin);
323
			qry->targetList = lappend(qry->targetList, te);
324 325
		}
	}
326

327 328
	/* fix where clause */
	qry->qual = transformWhereClause(pstate, stmt->whereClause);
B
Bruce Momjian 已提交
329 330 331

	qry->havingQual = transformWhereClause(pstate, stmt->havingClause);

B
Bruce Momjian 已提交
332
	qry->hasSubLinks = pstate->p_hasSubLinks;
333

334 335
	/* now the range table will not change */
	qry->rtable = pstate->p_rtable;
336
	qry->resultRelation = refnameRangeTablePosn(pstate, stmt->relname, NULL);
337

338 339 340 341 342 343 344 345 346 347 348
	qry->groupClause = transformGroupClause(pstate,
											stmt->groupClause,
											qry->targetList);

	/* fix order clause */
	qry->sortClause = transformSortClause(pstate,
										  NIL,
										  NIL,
										  qry->targetList,
										  qry->uniqueFlag);

B
Bruce Momjian 已提交
349
	qry->hasAggs = pstate->p_hasAggs;
350
	if (pstate->p_hasAggs)
B
Bruce Momjian 已提交
351
		parseCheckAggregates(pstate, qry);
352

353 354 355 356
	/* The INSERT INTO ... SELECT ... could have a UNION
	 * in child, so unionClause may be false
	 */
	qry->unionall = stmt->unionall;
357 358
	qry->unionClause = transformUnionClause(stmt->unionClause, qry->targetList);

359
	return (Query *) qry;
360 361
}

B
Bruce Momjian 已提交
362 363 364
/*
 *	makeTableName()
 *	Create a table name from a list of fields.
365 366 367 368
 */
static char *
makeTableName(void *elem,...)
{
369
	va_list		args;
370

371 372
	char	   *name;
	char		buf[NAMEDATALEN + 1];
373

B
Bruce Momjian 已提交
374
	buf[0] = '\0';
375

376
	va_start(args, elem);
377 378 379 380 381

	name = elem;
	while (name != NULL)
	{
		/* not enough room for next part? then return nothing */
382
		if ((strlen(buf) + strlen(name)) >= (sizeof(buf) - 1))
383 384
			return (NULL);

B
Bruce Momjian 已提交
385
		if (strlen(buf) > 0)
386 387
			strcat(buf, "_");
		strcat(buf, name);
388

389
		name = va_arg(args, void *);
390 391 392 393
	}

	va_end(args);

394 395
	name = palloc(strlen(buf) + 1);
	strcpy(name, buf);
396 397

	return (name);
B
Bruce Momjian 已提交
398
}
399

B
Bruce Momjian 已提交
400
static char *
401 402 403 404 405 406
CreateIndexName(char *tname, char *cname, char *label, List *indices)
{
	int			pass = 0;
	char	   *iname = NULL;
	List	   *ilist;
	IndexStmt  *index;
407
	char		name2[NAMEDATALEN + 1];
408 409

	/* use working storage, since we might be trying several possibilities */
410
	strcpy(name2, cname);
411 412 413 414 415 416 417 418 419 420 421
	while (iname == NULL)
	{
		iname = makeTableName(tname, name2, label, NULL);
		/* unable to make a name at all? then quit */
		if (iname == NULL)
			break;

		ilist = indices;
		while (ilist != NIL)
		{
			index = lfirst(ilist);
422
			if (strcasecmp(iname, index->idxname) == 0)
423 424 425 426 427 428 429 430 431 432 433 434
				break;

			ilist = lnext(ilist);
		}
		/* ran through entire list? then no name conflict found so done */
		if (ilist == NIL)
			break;

		/* the last one conflicted, so try a new name component */
		pfree(iname);
		iname = NULL;
		pass++;
435
		sprintf(name2, "%s_%d", cname, (pass + 1));
436 437 438
	}

	return (iname);
B
Bruce Momjian 已提交
439
}
440

441 442 443 444 445 446 447 448 449 450 451 452 453
/*
 * transformCreateStmt -
 *	  transforms the "create table" statement
 *	  SQL92 allows constraints to be scattered all over, so thumb through
 *	   the columns and collect all constraints into one place.
 *	  If there are any implied indices (e.g. UNIQUE or PRIMARY KEY)
 *	   then expand those into multiple IndexStmt blocks.
 *	  - thomas 1997-12-02
 */
static Query *
transformCreateStmt(ParseState *pstate, CreateStmt *stmt)
{
	Query	   *q;
454
	int			have_pkey = FALSE;
455 456 457 458 459
	List	   *elements;
	Node	   *element;
	List	   *columns;
	List	   *dlist;
	ColumnDef  *column;
460 461
	List	   *constraints,
			   *clist;
462 463 464 465 466 467 468 469 470 471 472 473 474 475 476 477 478 479 480 481 482 483
	Constraint *constraint;
	List	   *keys;
	Ident	   *key;
	List	   *ilist;
	IndexStmt  *index;
	IndexElem  *iparam;

	q = makeNode(Query);
	q->commandType = CMD_UTILITY;

	elements = stmt->tableElts;
	constraints = stmt->constraints;
	columns = NIL;
	dlist = NIL;

	while (elements != NIL)
	{
		element = lfirst(elements);
		switch (nodeTag(element))
		{
			case T_ColumnDef:
				column = (ColumnDef *) element;
484
				columns = lappend(columns, column);
485 486 487 488 489 490 491 492 493 494
				if (column->constraints != NIL)
				{
					clist = column->constraints;
					while (clist != NIL)
					{
						constraint = lfirst(clist);
						switch (constraint->contype)
						{
							case CONSTR_NOTNULL:
								if (column->is_not_null)
495 496
									elog(ERROR, "CREATE TABLE/NOT NULL already specified"
										 " for %s.%s", stmt->relname, column->colname);
497 498 499 500 501
								column->is_not_null = TRUE;
								break;

							case CONSTR_DEFAULT:
								if (column->defval != NULL)
502 503
									elog(ERROR, "CREATE TABLE/DEFAULT multiple values specified"
										 " for %s.%s", stmt->relname, column->colname);
504 505 506 507 508 509 510 511 512 513 514 515 516 517 518 519 520 521 522 523 524 525
								column->defval = constraint->def;
								break;

							case CONSTR_PRIMARY:
								if (constraint->name == NULL)
									constraint->name = makeTableName(stmt->relname, "pkey", NULL);
								if (constraint->keys == NIL)
									constraint->keys = lappend(constraint->keys, column);
								dlist = lappend(dlist, constraint);
								break;

							case CONSTR_UNIQUE:
								if (constraint->name == NULL)
									constraint->name = makeTableName(stmt->relname, column->colname, "key", NULL);
								if (constraint->keys == NIL)
									constraint->keys = lappend(constraint->keys, column);
								dlist = lappend(dlist, constraint);
								break;

							case CONSTR_CHECK:
								constraints = lappend(constraints, constraint);
								if (constraint->name == NULL)
526
									constraint->name = makeTableName(stmt->relname, column->colname, NULL);
527 528 529
								break;

							default:
530
								elog(ERROR, "parser: internal error; unrecognized constraint", NULL);
531 532 533 534 535 536 537 538 539 540 541 542 543 544 545 546 547 548 549 550 551 552 553 554 555 556 557 558 559 560 561
								break;
						}
						clist = lnext(clist);
					}
				}
				break;

			case T_Constraint:
				constraint = (Constraint *) element;
				switch (constraint->contype)
				{
					case CONSTR_PRIMARY:
						if (constraint->name == NULL)
							constraint->name = makeTableName(stmt->relname, "pkey", NULL);
						dlist = lappend(dlist, constraint);
						break;

					case CONSTR_UNIQUE:
#if FALSE
						if (constraint->name == NULL)
							constraint->name = makeTableName(stmt->relname, "key", NULL);
#endif
						dlist = lappend(dlist, constraint);
						break;

					case CONSTR_CHECK:
						constraints = lappend(constraints, constraint);
						break;

					case CONSTR_NOTNULL:
					case CONSTR_DEFAULT:
562
						elog(ERROR, "parser: internal error; illegal context for constraint", NULL);
563 564
						break;
					default:
565
						elog(ERROR, "parser: internal error; unrecognized constraint", NULL);
566 567 568 569 570
						break;
				}
				break;

			default:
571
				elog(ERROR, "parser: internal error; unrecognized node", NULL);
572 573 574 575 576 577 578 579 580 581 582 583 584
		}

		elements = lnext(elements);
	}

	stmt->tableElts = columns;
	stmt->constraints = constraints;

/* Now run through the "deferred list" to complete the query transformation.
 * For PRIMARY KEYs, mark each column as NOT NULL and create an index.
 * For UNIQUE, create an index as for PRIMARY KEYS, but do not insist on NOT NULL.
 *
 * Note that this code does not currently look for all possible redundant cases
585 586 587
 *	and either ignore or stop with warning. The create might fail later when
 *	names for indices turn out to be redundant, or a user might have specified
 *	extra useless indices which might hurt performance. - thomas 1997-12-08
588 589 590 591 592 593
 */
	ilist = NIL;
	while (dlist != NIL)
	{
		constraint = lfirst(dlist);
		if (nodeTag(constraint) != T_Constraint)
594
			elog(ERROR, "parser: internal error; unrecognized deferred node", NULL);
595

596
		if (constraint->contype == CONSTR_PRIMARY)
597
		{
598
			if (have_pkey)
599 600 601
				elog(ERROR, "CREATE TABLE/PRIMARY KEY multiple primary keys"
					 " for table %s are not legal", stmt->relname);
			else
602
				have_pkey = TRUE;
603
		}
604
		else if (constraint->contype != CONSTR_UNIQUE)
605
			elog(ERROR, "parser: internal error; unrecognized deferred constraint", NULL);
606

607 608 609 610 611 612
		index = makeNode(IndexStmt);

		index->unique = TRUE;
		if (constraint->name != NULL)
			index->idxname = constraint->name;
		else if (constraint->contype == CONSTR_PRIMARY)
613 614
		{
			if (have_pkey)
615
				elog(ERROR, "CREATE TABLE/PRIMARY KEY multiple keys for table %s are not legal", stmt->relname);
616 617

			have_pkey = TRUE;
618
			index->idxname = makeTableName(stmt->relname, "pkey", NULL);
619
		}
620 621 622 623 624 625 626 627
		else
			index->idxname = NULL;

		index->relname = stmt->relname;
		index->accessMethod = "btree";
		index->indexParams = NIL;
		index->withClause = NIL;
		index->whereClause = NULL;
628

629 630 631 632 633 634 635 636 637
		keys = constraint->keys;
		while (keys != NIL)
		{
			key = lfirst(keys);
			columns = stmt->tableElts;
			column = NULL;
			while (columns != NIL)
			{
				column = lfirst(columns);
638 639 640 641
				if (strcasecmp(column->colname, key->name) == 0)
					break;
				else
					column = NULL;
642 643 644
				columns = lnext(columns);
			}
			if (column == NULL)
645
				elog(ERROR, "parser: column '%s' in key does not exist", key->name);
646 647 648 649

			if (constraint->contype == CONSTR_PRIMARY)
				column->is_not_null = TRUE;
			iparam = makeNode(IndexElem);
650
			iparam->name = strcpy(palloc(strlen(column->colname) + 1), column->colname);
651 652 653 654 655 656
			iparam->args = NIL;
			iparam->class = NULL;
			iparam->tname = NULL;
			index->indexParams = lappend(index->indexParams, iparam);

			if (index->idxname == NULL)
657
				index->idxname = CreateIndexName(stmt->relname, iparam->name, "key", ilist);
658 659 660 661 662

			keys = lnext(keys);
		}

		if (index->idxname == NULL)
663 664
			elog(ERROR, "parser: unable to construct implicit index for table %s"
				 "; name too long", stmt->relname);
665
		else
666 667 668
			elog(NOTICE, "CREATE TABLE/%s will create implicit index %s for table %s",
				 ((constraint->contype == CONSTR_PRIMARY) ? "PRIMARY KEY" : "UNIQUE"),
				 index->idxname, stmt->relname);
669

670
		ilist = lappend(ilist, index);
671 672 673 674 675 676 677
		dlist = lnext(dlist);
	}

	q->utilityStmt = (Node *) stmt;
	extras = ilist;

	return q;
B
Bruce Momjian 已提交
678
}
679

680 681
/*
 * transformIndexStmt -
682
 *	  transforms the qualification of the index statement
683
 */
684
static Query *
685
transformIndexStmt(ParseState *pstate, IndexStmt *stmt)
686
{
B
Bruce Momjian 已提交
687
	Query	   *qry;
688

B
Bruce Momjian 已提交
689 690
	qry = makeNode(Query);
	qry->commandType = CMD_UTILITY;
691

692 693
	/* take care of the where clause */
	stmt->whereClause = transformWhereClause(pstate, stmt->whereClause);
B
Bruce Momjian 已提交
694
	qry->hasSubLinks = pstate->p_hasSubLinks;
695

696
	stmt->rangetable = pstate->p_rtable;
697

B
Bruce Momjian 已提交
698
	qry->utilityStmt = (Node *) stmt;
699

B
Bruce Momjian 已提交
700
	return qry;
701 702 703 704
}

/*
 * transformExtendStmt -
705
 *	  transform the qualifications of the Extend Index Statement
706 707
 *
 */
708
static Query *
709
transformExtendStmt(ParseState *pstate, ExtendStmt *stmt)
710
{
B
Bruce Momjian 已提交
711
	Query	   *qry;
712

B
Bruce Momjian 已提交
713 714
	qry = makeNode(Query);
	qry->commandType = CMD_UTILITY;
715

716 717
	/* take care of the where clause */
	stmt->whereClause = transformWhereClause(pstate, stmt->whereClause);
B
Bruce Momjian 已提交
718 719
	qry->hasSubLinks = pstate->p_hasSubLinks;

720
	stmt->rangetable = pstate->p_rtable;
721

B
Bruce Momjian 已提交
722 723
	qry->utilityStmt = (Node *) stmt;
	return qry;
724 725 726 727
}

/*
 * transformRuleStmt -
728 729
 *	  transform a Create Rule Statement. The actions is a list of parse
 *	  trees which is transformed into a list of query trees.
730
 */
731
static Query *
732
transformRuleStmt(ParseState *pstate, RuleStmt *stmt)
733
{
B
Bruce Momjian 已提交
734
	Query	   *qry;
735
	List	   *actions;
736

B
Bruce Momjian 已提交
737 738
	qry = makeNode(Query);
	qry->commandType = CMD_UTILITY;
739 740 741

	actions = stmt->actions;

742
	/*
743
	 * transform each statment, like parse_analyze()
744
	 */
745 746
	while (actions != NIL)
	{
747

748 749 750 751 752
		/*
		 * NOTE: 'CURRENT' must always have a varno equal to 1 and 'NEW'
		 * equal to 2.
		 */
		addRangeTableEntry(pstate, stmt->object->relname, "*CURRENT*",
753
						   FALSE, FALSE);
754
		addRangeTableEntry(pstate, stmt->object->relname, "*NEW*",
755
						   FALSE, FALSE);
756 757 758

		pstate->p_last_resno = 1;
		pstate->p_is_rule = true;		/* for expand all */
759
		pstate->p_hasAggs = false;
760 761 762 763

		lfirst(actions) = transformStmt(pstate, lfirst(actions));
		actions = lnext(actions);
	}
764

765 766
	/* take care of the where clause */
	stmt->whereClause = transformWhereClause(pstate, stmt->whereClause);
B
Bruce Momjian 已提交
767
	qry->hasSubLinks = pstate->p_hasSubLinks;
768

B
Bruce Momjian 已提交
769 770
	qry->utilityStmt = (Node *) stmt;
	return qry;
771 772 773 774 775
}


/*
 * transformSelectStmt -
776
 *	  transforms a Select Statement
777 778
 *
 */
779
static Query *
B
Bruce Momjian 已提交
780
transformSelectStmt(ParseState *pstate, SelectStmt *stmt)
781
{
782
	Query	   *qry = makeNode(Query);
783 784

	qry->commandType = CMD_SELECT;
785

786 787
	/* set up a range table */
	makeRangeTable(pstate, NULL, stmt->fromClause);
788

789
	qry->uniqueFlag = stmt->unique;
790

791 792
	qry->into = stmt->into;
	qry->isPortal = FALSE;
793

794
	qry->targetList = transformTargetList(pstate, stmt->targetList);
795

796
	qry->qual = transformWhereClause(pstate, stmt->whereClause);
797 798 799

	qry->havingQual = transformWhereClause(pstate, stmt->havingClause);

B
Bruce Momjian 已提交
800
	qry->hasSubLinks = pstate->p_hasSubLinks;
801

802 803
	qry->sortClause = transformSortClause(pstate,
										  stmt->sortClause,
B
Bruce Momjian 已提交
804
										  NIL,
805 806
										  qry->targetList,
										  qry->uniqueFlag);
807

808 809 810 811
	qry->groupClause = transformGroupClause(pstate,
											stmt->groupClause,
											qry->targetList);
	qry->rtable = pstate->p_rtable;
812

B
Bruce Momjian 已提交
813
	qry->hasAggs = pstate->p_hasAggs;
814
	if (pstate->p_hasAggs)
B
Bruce Momjian 已提交
815
		parseCheckAggregates(pstate, qry);
816

817 818 819 820
	/* The INSERT INTO ... SELECT ... could have a UNION
	 * in child, so unionClause may be false
	 */
	qry->unionall = stmt->unionall;
821
	qry->unionClause = transformUnionClause(stmt->unionClause, qry->targetList);
822

823
	return (Query *) qry;
824 825 826 827
}

/*
 * transformUpdateStmt -
828
 *	  transforms an update statement
829 830
 *
 */
831
static Query *
B
Bruce Momjian 已提交
832
transformUpdateStmt(ParseState *pstate, UpdateStmt *stmt)
833
{
834
	Query	   *qry = makeNode(Query);
835 836 837

	qry->commandType = CMD_UPDATE;
	pstate->p_is_update = true;
838

839 840 841 842 843
	/*
	 * the FROM clause is non-standard SQL syntax. We used to be able to
	 * do this with REPLACE in POSTQUEL so we keep the feature.
	 */
	makeRangeTable(pstate, stmt->relname, stmt->fromClause);
844

845
	qry->targetList = transformTargetList(pstate, stmt->targetList);
846

847
	qry->qual = transformWhereClause(pstate, stmt->whereClause);
B
Bruce Momjian 已提交
848
	qry->hasSubLinks = pstate->p_hasSubLinks;
849

850
	qry->rtable = pstate->p_rtable;
851

852
	qry->resultRelation = refnameRangeTablePosn(pstate, stmt->relname, NULL);
853

B
Bruce Momjian 已提交
854
	qry->hasAggs = pstate->p_hasAggs;
855
	if (pstate->p_hasAggs)
856
		parseCheckAggregates(pstate, qry);
857

858
	return (Query *) qry;
859 860 861 862
}

/*
 * transformCursorStmt -
863
 *	  transform a Create Cursor Statement
864 865
 *
 */
866
static Query *
867
transformCursorStmt(ParseState *pstate, SelectStmt *stmt)
868
{
869
	Query	   *qry;
870

871
	qry = transformSelectStmt(pstate, stmt);
872

873 874 875
	qry->into = stmt->portalname;
	qry->isPortal = TRUE;
	qry->isBinary = stmt->binary;		/* internal portal */
876

877
	return qry;
878
}