analyze.c 23.9 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
M
 
Marc G. Fournier 已提交
10
 *	  $Header: /cvsroot/pgsql/src/backend/parser/analyze.c,v 1.80 1998/08/18 00:48:54 scrappy 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
			te = makeTargetEntry(makeResdom(defval[ndef].adnum,
316
									att[defval[ndef].adnum - 1]->atttypid,
317 318
									att[defval[ndef].adnum - 1]->atttypmod,
									pstrdup(nameout(&(att[defval[ndef].adnum - 1]->attname))),
319
									0, 0, 0),
B
Bruce Momjian 已提交
320
						(Node *) stringToNode(defval[ndef].adbin));
321
			qry->targetList = lappend(qry->targetList, te);
322 323
		}
	}
324

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

328 329 330
	/* The havingQual has a similar meaning as "qual" in the where statement. 
	 * So we can easily use the code from the "where clause" with some additional
         * traversals done in .../optimizer/plan/planner.c */
B
Bruce Momjian 已提交
331 332
	qry->havingQual = transformWhereClause(pstate, stmt->havingClause);

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

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

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

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

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

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

360 361 362 363 364 365 366 367 368
	/* If there is a havingQual but there are no aggregates, then there is something wrong
	 * with the query because having must contain aggregates in its expressions! 
	 * Otherwise the query could have been formulated using the where clause. */
	if((qry->hasAggs == false) && (qry->havingQual != NULL))
	  {
	    elog(ERROR,"This is not a valid having query!");
	    return (Query *)NIL;
	  }

369
	return (Query *) qry;
370 371
}

B
Bruce Momjian 已提交
372 373 374
/*
 *	makeTableName()
 *	Create a table name from a list of fields.
375 376 377 378
 */
static char *
makeTableName(void *elem,...)
{
379
	va_list		args;
380

381 382
	char	   *name;
	char		buf[NAMEDATALEN + 1];
383

B
Bruce Momjian 已提交
384
	buf[0] = '\0';
385

386
	va_start(args, elem);
387 388 389 390 391

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

B
Bruce Momjian 已提交
395
		if (strlen(buf) > 0)
396 397
			strcat(buf, "_");
		strcat(buf, name);
398

399
		name = va_arg(args, void *);
400 401 402 403
	}

	va_end(args);

404 405
	name = palloc(strlen(buf) + 1);
	strcpy(name, buf);
406 407

	return (name);
B
Bruce Momjian 已提交
408
}
409

B
Bruce Momjian 已提交
410
static char *
411 412 413 414 415 416
CreateIndexName(char *tname, char *cname, char *label, List *indices)
{
	int			pass = 0;
	char	   *iname = NULL;
	List	   *ilist;
	IndexStmt  *index;
417
	char		name2[NAMEDATALEN + 1];
418 419

	/* use working storage, since we might be trying several possibilities */
420
	strcpy(name2, cname);
421 422 423 424 425 426 427 428 429 430 431
	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);
432
			if (strcasecmp(iname, index->idxname) == 0)
433 434 435 436 437 438 439 440 441 442 443 444
				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++;
445
		sprintf(name2, "%s_%d", cname, (pass + 1));
446 447 448
	}

	return (iname);
B
Bruce Momjian 已提交
449
}
450

451 452 453 454 455 456 457 458 459 460 461 462 463
/*
 * 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;
464
	int			have_pkey = FALSE;
465 466 467 468 469
	List	   *elements;
	Node	   *element;
	List	   *columns;
	List	   *dlist;
	ColumnDef  *column;
470 471
	List	   *constraints,
			   *clist;
472 473 474 475 476 477 478 479 480 481 482 483 484 485 486 487 488 489 490 491 492 493
	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;
494
				columns = lappend(columns, column);
495 496 497 498 499 500 501 502 503 504
				if (column->constraints != NIL)
				{
					clist = column->constraints;
					while (clist != NIL)
					{
						constraint = lfirst(clist);
						switch (constraint->contype)
						{
							case CONSTR_NOTNULL:
								if (column->is_not_null)
505 506
									elog(ERROR, "CREATE TABLE/NOT NULL already specified"
										 " for %s.%s", stmt->relname, column->colname);
507 508 509 510 511
								column->is_not_null = TRUE;
								break;

							case CONSTR_DEFAULT:
								if (column->defval != NULL)
512 513
									elog(ERROR, "CREATE TABLE/DEFAULT multiple values specified"
										 " for %s.%s", stmt->relname, column->colname);
514 515 516 517 518 519 520 521 522 523 524 525 526 527 528 529 530 531 532 533 534 535
								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)
536
									constraint->name = makeTableName(stmt->relname, column->colname, NULL);
537 538 539
								break;

							default:
540
								elog(ERROR, "parser: internal error; unrecognized constraint", NULL);
541 542 543 544 545 546 547 548 549 550 551 552 553 554 555 556 557 558 559 560 561 562 563 564 565 566 567 568 569 570 571
								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:
572
						elog(ERROR, "parser: internal error; illegal context for constraint", NULL);
573 574
						break;
					default:
575
						elog(ERROR, "parser: internal error; unrecognized constraint", NULL);
576 577 578 579 580
						break;
				}
				break;

			default:
581
				elog(ERROR, "parser: internal error; unrecognized node", NULL);
582 583 584 585 586 587 588 589 590 591 592 593 594
		}

		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
595 596 597
 *	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
598 599 600 601 602 603
 */
	ilist = NIL;
	while (dlist != NIL)
	{
		constraint = lfirst(dlist);
		if (nodeTag(constraint) != T_Constraint)
604
			elog(ERROR, "parser: internal error; unrecognized deferred node", NULL);
605

606
		if (constraint->contype == CONSTR_PRIMARY)
607
		{
608
			if (have_pkey)
609 610 611
				elog(ERROR, "CREATE TABLE/PRIMARY KEY multiple primary keys"
					 " for table %s are not legal", stmt->relname);
			else
612
				have_pkey = TRUE;
613
		}
614
		else if (constraint->contype != CONSTR_UNIQUE)
615
			elog(ERROR, "parser: internal error; unrecognized deferred constraint", NULL);
616

617 618 619 620 621 622
		index = makeNode(IndexStmt);

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

			have_pkey = TRUE;
628
			index->idxname = makeTableName(stmt->relname, "pkey", NULL);
629
		}
630 631 632 633 634 635 636 637
		else
			index->idxname = NULL;

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

639 640 641 642 643 644 645 646 647
		keys = constraint->keys;
		while (keys != NIL)
		{
			key = lfirst(keys);
			columns = stmt->tableElts;
			column = NULL;
			while (columns != NIL)
			{
				column = lfirst(columns);
648 649 650 651
				if (strcasecmp(column->colname, key->name) == 0)
					break;
				else
					column = NULL;
652 653 654
				columns = lnext(columns);
			}
			if (column == NULL)
655
				elog(ERROR, "parser: column '%s' in key does not exist", key->name);
656 657 658 659

			if (constraint->contype == CONSTR_PRIMARY)
				column->is_not_null = TRUE;
			iparam = makeNode(IndexElem);
660
			iparam->name = strcpy(palloc(strlen(column->colname) + 1), column->colname);
661 662 663 664 665 666
			iparam->args = NIL;
			iparam->class = NULL;
			iparam->tname = NULL;
			index->indexParams = lappend(index->indexParams, iparam);

			if (index->idxname == NULL)
667
				index->idxname = CreateIndexName(stmt->relname, iparam->name, "key", ilist);
668 669 670 671 672

			keys = lnext(keys);
		}

		if (index->idxname == NULL)
673 674
			elog(ERROR, "parser: unable to construct implicit index for table %s"
				 "; name too long", stmt->relname);
675
		else
676 677 678
			elog(NOTICE, "CREATE TABLE/%s will create implicit index %s for table %s",
				 ((constraint->contype == CONSTR_PRIMARY) ? "PRIMARY KEY" : "UNIQUE"),
				 index->idxname, stmt->relname);
679

680
		ilist = lappend(ilist, index);
681 682 683 684 685 686 687
		dlist = lnext(dlist);
	}

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

	return q;
B
Bruce Momjian 已提交
688
}
689

690 691
/*
 * transformIndexStmt -
692
 *	  transforms the qualification of the index statement
693
 */
694
static Query *
695
transformIndexStmt(ParseState *pstate, IndexStmt *stmt)
696
{
B
Bruce Momjian 已提交
697
	Query	   *qry;
698

B
Bruce Momjian 已提交
699 700
	qry = makeNode(Query);
	qry->commandType = CMD_UTILITY;
701

702 703
	/* take care of the where clause */
	stmt->whereClause = transformWhereClause(pstate, stmt->whereClause);
B
Bruce Momjian 已提交
704
	qry->hasSubLinks = pstate->p_hasSubLinks;
705

706
	stmt->rangetable = pstate->p_rtable;
707

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

B
Bruce Momjian 已提交
710
	return qry;
711 712 713 714
}

/*
 * transformExtendStmt -
715
 *	  transform the qualifications of the Extend Index Statement
716 717
 *
 */
718
static Query *
719
transformExtendStmt(ParseState *pstate, ExtendStmt *stmt)
720
{
B
Bruce Momjian 已提交
721
	Query	   *qry;
722

B
Bruce Momjian 已提交
723 724
	qry = makeNode(Query);
	qry->commandType = CMD_UTILITY;
725

726 727
	/* take care of the where clause */
	stmt->whereClause = transformWhereClause(pstate, stmt->whereClause);
B
Bruce Momjian 已提交
728 729
	qry->hasSubLinks = pstate->p_hasSubLinks;

730
	stmt->rangetable = pstate->p_rtable;
731

B
Bruce Momjian 已提交
732 733
	qry->utilityStmt = (Node *) stmt;
	return qry;
734 735 736 737
}

/*
 * transformRuleStmt -
738 739
 *	  transform a Create Rule Statement. The actions is a list of parse
 *	  trees which is transformed into a list of query trees.
740
 */
741
static Query *
742
transformRuleStmt(ParseState *pstate, RuleStmt *stmt)
743
{
B
Bruce Momjian 已提交
744
	Query	   *qry;
M
 
Marc G. Fournier 已提交
745
	Query	   *action;
746
	List	   *actions;
747

B
Bruce Momjian 已提交
748 749
	qry = makeNode(Query);
	qry->commandType = CMD_UTILITY;
750

M
 
Marc G. Fournier 已提交
751 752 753 754 755 756 757 758 759 760 761 762 763 764 765 766 767 768 769 770 771
	/*
	 * 'instead nothing' rules with a qualification need a
	 * query a rangetable so the rewrite handler can add the
	 * negated rule qualification to the original query. We
	 * create a query with the new command type CMD_NOTHING
	 * here that is treated special by the rewrite system.
	 */
	if (stmt->actions == NIL) {
		Query		*nothing_qry = makeNode(Query);
		nothing_qry->commandType = CMD_NOTHING;

		addRangeTableEntry(pstate, stmt->object->relname, "*CURRENT*",
						   FALSE, FALSE);
		addRangeTableEntry(pstate, stmt->object->relname, "*NEW*",
						   FALSE, FALSE);

		nothing_qry->rtable = pstate->p_rtable;

		stmt->actions = lappend(NIL, nothing_qry);
	}

772 773
	actions = stmt->actions;

774
	/*
775
	 * transform each statment, like parse_analyze()
776
	 */
777 778
	while (actions != NIL)
	{
779

780 781 782 783 784
		/*
		 * NOTE: 'CURRENT' must always have a varno equal to 1 and 'NEW'
		 * equal to 2.
		 */
		addRangeTableEntry(pstate, stmt->object->relname, "*CURRENT*",
785
						   FALSE, FALSE);
786
		addRangeTableEntry(pstate, stmt->object->relname, "*NEW*",
787
						   FALSE, FALSE);
788 789 790

		pstate->p_last_resno = 1;
		pstate->p_is_rule = true;		/* for expand all */
791
		pstate->p_hasAggs = false;
792

M
 
Marc G. Fournier 已提交
793 794 795
		action = (Query *)lfirst(actions);
		if (action->commandType != CMD_NOTHING)
			lfirst(actions) = transformStmt(pstate, lfirst(actions));
796 797
		actions = lnext(actions);
	}
798

799 800
	/* take care of the where clause */
	stmt->whereClause = transformWhereClause(pstate, stmt->whereClause);
B
Bruce Momjian 已提交
801
	qry->hasSubLinks = pstate->p_hasSubLinks;
802

B
Bruce Momjian 已提交
803 804
	qry->utilityStmt = (Node *) stmt;
	return qry;
805 806 807 808 809
}


/*
 * transformSelectStmt -
810
 *	  transforms a Select Statement
811 812
 *
 */
813
static Query *
B
Bruce Momjian 已提交
814
transformSelectStmt(ParseState *pstate, SelectStmt *stmt)
815
{
816
	Query	   *qry = makeNode(Query);
817 818

	qry->commandType = CMD_SELECT;
819

820 821
	/* set up a range table */
	makeRangeTable(pstate, NULL, stmt->fromClause);
822

823
	qry->uniqueFlag = stmt->unique;
824

825 826
	qry->into = stmt->into;
	qry->isPortal = FALSE;
827

828
	qry->targetList = transformTargetList(pstate, stmt->targetList);
829

830
	qry->qual = transformWhereClause(pstate, stmt->whereClause);
831

832 833 834
	/* The havingQual has a similar meaning as "qual" in the where statement. 
	 * So we can easily use the code from the "where clause" with some additional
         * traversals done in .../optimizer/plan/planner.c */
835 836
	qry->havingQual = transformWhereClause(pstate, stmt->havingClause);

B
Bruce Momjian 已提交
837
	qry->hasSubLinks = pstate->p_hasSubLinks;
838

839 840
	qry->sortClause = transformSortClause(pstate,
										  stmt->sortClause,
B
Bruce Momjian 已提交
841
										  NIL,
842 843
										  qry->targetList,
										  qry->uniqueFlag);
844

845 846 847 848
	qry->groupClause = transformGroupClause(pstate,
											stmt->groupClause,
											qry->targetList);
	qry->rtable = pstate->p_rtable;
849

B
Bruce Momjian 已提交
850
	qry->hasAggs = pstate->p_hasAggs;
851
	if (pstate->p_hasAggs)
B
Bruce Momjian 已提交
852
		parseCheckAggregates(pstate, qry);
853

854 855 856 857
	/* The INSERT INTO ... SELECT ... could have a UNION
	 * in child, so unionClause may be false
	 */
	qry->unionall = stmt->unionall;
858
	qry->unionClause = transformUnionClause(stmt->unionClause, qry->targetList);
859

860 861 862 863 864 865 866 867 868
	/* If there is a havingQual but there are no aggregates, then there is something wrong
	 * with the query because having must contain aggregates in its expressions! 
	 * Otherwise the query could have been formulated using the where clause. */
	if((qry->hasAggs == false) && (qry->havingQual != NULL))
	  {
	    elog(ERROR,"This is not a valid having query!");
	    return (Query *)NIL;
	  }

869
	return (Query *) qry;
870 871 872 873
}

/*
 * transformUpdateStmt -
874
 *	  transforms an update statement
875 876
 *
 */
877
static Query *
B
Bruce Momjian 已提交
878
transformUpdateStmt(ParseState *pstate, UpdateStmt *stmt)
879
{
880
	Query	   *qry = makeNode(Query);
881 882 883

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

885 886 887 888 889
	/*
	 * 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);
890

891
	qry->targetList = transformTargetList(pstate, stmt->targetList);
892

893
	qry->qual = transformWhereClause(pstate, stmt->whereClause);
B
Bruce Momjian 已提交
894
	qry->hasSubLinks = pstate->p_hasSubLinks;
895

896
	qry->rtable = pstate->p_rtable;
897

898
	qry->resultRelation = refnameRangeTablePosn(pstate, stmt->relname, NULL);
899

B
Bruce Momjian 已提交
900
	qry->hasAggs = pstate->p_hasAggs;
901
	if (pstate->p_hasAggs)
902
		parseCheckAggregates(pstate, qry);
903

904
	return (Query *) qry;
905 906 907 908
}

/*
 * transformCursorStmt -
909
 *	  transform a Create Cursor Statement
910 911
 *
 */
912
static Query *
913
transformCursorStmt(ParseState *pstate, SelectStmt *stmt)
914
{
915
	Query	   *qry;
916

917
	qry = transformSelectStmt(pstate, stmt);
918

919 920 921
	qry->into = stmt->portalname;
	qry->isPortal = TRUE;
	qry->isBinary = stmt->binary;		/* internal portal */
922

923
	return qry;
924
}