analyze.c 33.3 KB
Newer Older
1 2
/*-------------------------------------------------------------------------
 *
3
 * analyze.c
4
 *	  transform the parse tree into a query tree
5 6 7
 *
 * Copyright (c) 1994, Regents of the University of California
 *
8
 *	$Id: analyze.c,v 1.111 1999/07/13 21:17:32 momjian Exp $
9 10 11
 *
 *-------------------------------------------------------------------------
 */
12

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

B
Bruce Momjian 已提交
18
#include "postgres.h"
19 20 21 22 23 24
#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 已提交
25
#include "parser/parse_clause.h"
26 27 28
#include "parser/parse_node.h"
#include "parser/parse_relation.h"
#include "parser/parse_target.h"
B
Hi!  
Bruce Momjian 已提交
29 30 31 32
#include "parser/parse_expr.h"
#include "catalog/pg_type.h"
#include "parse.h"

33 34
#include "utils/builtins.h"
#include "utils/mcxt.h"
35

36 37
static Query *transformStmt(ParseState *pstate, Node *stmt);
static Query *transformDeleteStmt(ParseState *pstate, DeleteStmt *stmt);
B
Bruce Momjian 已提交
38
static Query *transformInsertStmt(ParseState *pstate, InsertStmt *stmt);
39 40 41
static Query *transformIndexStmt(ParseState *pstate, IndexStmt *stmt);
static Query *transformExtendStmt(ParseState *pstate, ExtendStmt *stmt);
static Query *transformRuleStmt(ParseState *query, RuleStmt *stmt);
B
Bruce Momjian 已提交
42 43
static Query *transformSelectStmt(ParseState *pstate, SelectStmt *stmt);
static Query *transformUpdateStmt(ParseState *pstate, UpdateStmt *stmt);
44
static Query *transformCursorStmt(ParseState *pstate, SelectStmt *stmt);
45
static Query *transformCreateStmt(ParseState *pstate, CreateStmt *stmt);
46

B
Bruce Momjian 已提交
47 48
static void transformForUpdate(Query *qry, List *forUpdate);
void		CheckSelectForUpdate(Query *qry);
49

B
Bruce Momjian 已提交
50 51
List	   *extras_before = NIL;
List	   *extras_after = NIL;
B
Bruce Momjian 已提交
52

53 54
/*
 * parse_analyze -
55
 *	  analyze a list of parse trees and transform them if necessary.
56 57 58 59 60
 *
 * Returns a list of transformed parse trees. Optimizable statements are
 * all transformed to Query while the rest stays the same.
 *
 */
61
List *
62
parse_analyze(List *pl, ParseState *parentParseState)
63
{
B
Bruce Momjian 已提交
64
	List	   *result = NIL;
65
	ParseState *pstate;
B
Bruce Momjian 已提交
66
	Query	   *parsetree;
67 68 69

	while (pl != NIL)
	{
70
		pstate = make_parsestate(parentParseState);
B
Bruce Momjian 已提交
71
		parsetree = transformStmt(pstate, lfirst(pl));
B
Bruce Momjian 已提交
72 73 74
		if (pstate->p_target_relation != NULL)
			heap_close(pstate->p_target_relation);

75
		while (extras_before != NIL)
76
		{
77
			result = lappend(result,
B
Bruce Momjian 已提交
78
						   transformStmt(pstate, lfirst(extras_before)));
79 80 81
			if (pstate->p_target_relation != NULL)
				heap_close(pstate->p_target_relation);
			extras_before = lnext(extras_before);
82
		}
B
Bruce Momjian 已提交
83

84
		result = lappend(result, parsetree);
B
Bruce Momjian 已提交
85

86
		while (extras_after != NIL)
B
Bruce Momjian 已提交
87
		{
88 89 90 91 92
			result = lappend(result,
							 transformStmt(pstate, lfirst(extras_after)));
			if (pstate->p_target_relation != NULL)
				heap_close(pstate->p_target_relation);
			extras_after = lnext(extras_after);
B
Bruce Momjian 已提交
93 94
		}

95
		pl = lnext(pl);
B
Bruce Momjian 已提交
96
		pfree(pstate);
97 98 99
	}

	return result;
100 101 102 103
}

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

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

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

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

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

134 135 136
		case T_ViewStmt:
			{
				ViewStmt   *n = (ViewStmt *) parseTree;
137

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

145 146 147
		case T_VacuumStmt:
			{
				MemoryContext oldcontext;
148

149 150 151 152 153 154 155 156 157 158 159 160
				/*
				 * 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;
161

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

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

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

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

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

B
Bruce Momjian 已提交
190
		case T_SelectStmt:
191
			if (!((SelectStmt *) parseTree)->portalname)
192
			{
193
				result = transformSelectStmt(pstate, (SelectStmt *) parseTree);
B
Bruce Momjian 已提交
194 195
				result->limitOffset = ((SelectStmt *) parseTree)->limitOffset;
				result->limitCount = ((SelectStmt *) parseTree)->limitCount;
196
			}
197 198
			else
				result = transformCursorStmt(pstate, (SelectStmt *) parseTree);
199
			break;
200

201
		default:
202

203 204
			/*
			 * other statments don't require any transformation-- just
B
Bruce Momjian 已提交
205
			 * return the original parsetree, yea!
206 207 208 209 210
			 */
			result = makeNode(Query);
			result->commandType = CMD_UTILITY;
			result->utilityStmt = (Node *) parseTree;
			break;
211 212
	}
	return result;
213 214 215 216
}

/*
 * transformDeleteStmt -
217
 *	  transforms a Delete Statement
218
 */
219
static Query *
220
transformDeleteStmt(ParseState *pstate, DeleteStmt *stmt)
221
{
222
	Query	   *qry = makeNode(Query);
223

224
	qry->commandType = CMD_DELETE;
225

226
	/* set up a range table */
227
	makeRangeTable(pstate, stmt->relname, NULL, NULL);
228

229
	qry->uniqueFlag = NULL;
230

231
	/* fix where clause */
232
	qry->qual = transformWhereClause(pstate, stmt->whereClause, NULL);
B
Bruce Momjian 已提交
233
	qry->hasSubLinks = pstate->p_hasSubLinks;
234

235
	qry->rtable = pstate->p_rtable;
236
	qry->resultRelation = refnameRangeTablePosn(pstate, stmt->relname, NULL);
237

B
Bruce Momjian 已提交
238
	qry->hasAggs = pstate->p_hasAggs;
239
	if (pstate->p_hasAggs)
240
		parseCheckAggregates(pstate, qry);
241

242
	return (Query *) qry;
243 244 245 246
}

/*
 * transformInsertStmt -
247
 *	  transform an Insert Statement
248
 */
249
static Query *
B
Bruce Momjian 已提交
250
transformInsertStmt(ParseState *pstate, InsertStmt *stmt)
251
{
252
	Query	   *qry = makeNode(Query);	/* make a new query tree */
253
	List	   *icolumns;
254

255 256
	qry->commandType = CMD_INSERT;
	pstate->p_is_insert = true;
257

258
	/* set up a range table */
259
	makeRangeTable(pstate, stmt->relname, stmt->fromClause, NULL);
260

261
	qry->uniqueFlag = stmt->unique;
262

263
	/* fix the target list */
264
	icolumns = pstate->p_insert_columns = makeTargetNames(pstate, stmt->cols);
265

266
	qry->targetList = transformTargetList(pstate, stmt->targetList);
267

268 269 270 271 272
	/* 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)
	{
273
		Form_pg_attribute *att = pstate->p_target_relation->rd_att->attrs;
274 275 276 277
		AttrDefault *defval = pstate->p_target_relation->rd_att->constr->defval;
		int			ndef = pstate->p_target_relation->rd_att->constr->num_defval;

		/*
B
Bruce Momjian 已提交
278 279
		 * if stmt->cols == NIL then makeTargetNames returns list of all
		 * attrs. May have to shorten icolumns list...
280 281 282
		 */
		if (stmt->cols == NIL)
		{
283 284 285 286
			List	   *extrl;
			int			i = length(qry->targetList);

			foreach(extrl, icolumns)
287
			{
B
Bruce Momjian 已提交
288

289
				/*
B
Bruce Momjian 已提交
290 291
				 * decrements first, so if we started with zero items it
				 * will now be negative
292
				 */
293 294 295
				if (--i <= 0)
					break;
			}
B
Bruce Momjian 已提交
296

297
			/*
B
Bruce Momjian 已提交
298 299
			 * this an index into the targetList, so make sure we had one
			 * to start...
300 301 302 303 304 305 306 307
			 */
			if (i >= 0)
			{
				freeList(lnext(extrl));
				lnext(extrl) = NIL;
			}
			else
				icolumns = NIL;
308
		}
309

310 311
		while (ndef-- > 0)
		{
312 313 314 315 316
			List	   *tl;
			Ident	   *id;
			TargetEntry *te;

			foreach(tl, icolumns)
317 318
			{
				id = (Ident *) lfirst(tl);
319
				if (namestrcmp(&(att[defval[ndef].adnum - 1]->attname), id->name) == 0)
320 321 322 323
					break;
			}
			if (tl != NIL)		/* something given for this attr */
				continue;
324 325 326 327 328 329 330 331 332 333 334

			/*
			 * 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...
335
			 */
336
			te = makeTargetEntry(makeResdom(defval[ndef].adnum,
337 338 339
								   att[defval[ndef].adnum - 1]->atttypid,
								  att[defval[ndef].adnum - 1]->atttypmod,
			   pstrdup(nameout(&(att[defval[ndef].adnum - 1]->attname))),
B
Bruce Momjian 已提交
340
											0, 0, false),
341
							  (Node *) stringToNode(defval[ndef].adbin));
342
			qry->targetList = lappend(qry->targetList, te);
343 344
		}
	}
345

346
	/* fix where clause */
347
	qry->qual = transformWhereClause(pstate, stmt->whereClause, NULL);
B
Bruce Momjian 已提交
348

349 350 351 352 353 354
	/*
	 * 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
	 */
355
	qry->havingQual = transformWhereClause(pstate, stmt->havingClause, NULL);
B
Bruce Momjian 已提交
356

B
Bruce Momjian 已提交
357
	qry->hasSubLinks = pstate->p_hasSubLinks;
358

359 360
	/* now the range table will not change */
	qry->rtable = pstate->p_rtable;
361
	qry->resultRelation = refnameRangeTablePosn(pstate, stmt->relname, NULL);
362

363 364 365 366 367 368 369 370 371 372 373
	qry->groupClause = transformGroupClause(pstate,
											stmt->groupClause,
											qry->targetList);

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

B
Bruce Momjian 已提交
374
	qry->hasAggs = pstate->p_hasAggs;
375
	if (pstate->p_hasAggs || qry->groupClause)
B
Bruce Momjian 已提交
376
		parseCheckAggregates(pstate, qry);
377

378 379
	/*
	 * The INSERT INTO ... SELECT ... could have a UNION in child, so
B
Bruce Momjian 已提交
380 381 382 383 384 385 386 387 388 389
	 * unionClause may be false ,
	 */
	qry->unionall = stmt->unionall;

	/*
	 * Just hand through the unionClause and intersectClause. We will
	 * handle it in the function Except_Intersect_Rewrite()
	 */
	qry->unionClause = stmt->unionClause;
	qry->intersectClause = stmt->intersectClause;
390

391 392 393 394 395 396 397 398
	/*
	 * 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))
	{
T
Thomas G. Lockhart 已提交
399
		elog(ERROR, "SELECT/HAVING requires aggregates to be valid");
400 401
		return (Query *) NIL;
	}
402

403 404 405
	if (stmt->forUpdate != NULL)
		transformForUpdate(qry, stmt->forUpdate);

406
	return (Query *) qry;
407 408
}

B
Bruce Momjian 已提交
409
/*
410 411 412 413 414 415 416 417 418 419 420 421 422 423 424 425 426 427 428 429
 *	makeObjectName()
 *
 *	Create a name for an implicitly created index, sequence, constraint, etc.
 *
 *	The parameters are: the original table name, the original field name, and
 *	a "type" string (such as "seq" or "pkey").  The field name and/or type
 *	can be NULL if not relevant.
 *
 *	The result is a palloc'd string.
 *
 *	The basic result we want is "name1_name2_type", omitting "_name2" or
 *	"_type" when those parameters are NULL.  However, we must generate
 *	a name with less than NAMEDATALEN characters!  So, we truncate one or
 *	both names if necessary to make a short-enough string.  The type part
 *	is never truncated (so it had better be reasonably short).
 *
 *	To reduce the probability of collisions, we might someday add more
 *	smarts to this routine, like including some "hash" characters computed
 *	from the truncated characters.  Currently it seems best to keep it simple,
 *	so that the generated names are easily predictable by a person.
430 431
 */
static char *
432
makeObjectName(char *name1, char *name2, char *typename)
433
{
434
	char	   *name;
435 436 437 438 439 440 441 442
	int			overhead = 0;	/* chars needed for type and underscores */
	int			availchars;		/* chars available for name(s) */
	int			name1chars;		/* chars allocated to name1 */
	int			name2chars;		/* chars allocated to name2 */
	int			ndx;

	name1chars = strlen(name1);
	if (name2)
443
	{
444 445 446 447 448 449 450
		name2chars = strlen(name2);
		overhead++;				/* allow for separating underscore */
	}
	else
		name2chars = 0;
	if (typename)
		overhead += strlen(typename) + 1;
451

452
	availchars = NAMEDATALEN-1 - overhead;
453

454 455 456 457 458 459 460 461 462 463
	/* If we must truncate,  preferentially truncate the longer name.
	 * This logic could be expressed without a loop, but it's simple and
	 * obvious as a loop.
	 */
	while (name1chars + name2chars > availchars)
	{
		if (name1chars > name2chars)
			name1chars--;
		else
			name2chars--;
464 465
	}

466 467 468 469 470 471 472 473 474 475 476 477 478 479 480 481 482
	/* Now construct the string using the chosen lengths */
	name = palloc(name1chars + name2chars + overhead + 1);
	strncpy(name, name1, name1chars);
	ndx = name1chars;
	if (name2)
	{
		name[ndx++] = '_';
		strncpy(name+ndx, name2, name2chars);
		ndx += name2chars;
	}
	if (typename)
	{
		name[ndx++] = '_';
		strcpy(name+ndx, typename);
	}
	else
		name[ndx] = '\0';
483

484
	return name;
B
Bruce Momjian 已提交
485
}
486

B
Bruce Momjian 已提交
487
static char *
488
CreateIndexName(char *table_name, char *column_name, char *label, List *indices)
489 490 491 492
{
	int			pass = 0;
	char	   *iname = NULL;
	List	   *ilist;
493 494 495 496 497 498 499 500
	char		typename[NAMEDATALEN];

	/* The type name for makeObjectName is label, or labelN if that's
	 * necessary to prevent collisions among multiple indexes for the same
	 * table.  Note there is no check for collisions with already-existing
	 * indexes; this ought to be rethought someday.
	 */
	strcpy(typename, label);
501

502
	for (;;)
503
	{
504
		iname = makeObjectName(table_name, column_name, typename);
505

506
		foreach(ilist, indices)
507
		{
508
			IndexStmt  *index = lfirst(ilist);
509
			if (strcasecmp(iname, index->idxname) == 0)
510 511 512 513 514 515 516 517
				break;
		}
		/* 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);
518
		sprintf(typename, "%s%d", label, ++pass);
519 520
	}

521
	return iname;
B
Bruce Momjian 已提交
522
}
523

524 525 526 527 528 529 530 531 532 533 534 535 536 537 538 539 540 541
/*
 * 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;
	List	   *elements;
	Node	   *element;
	List	   *columns;
	List	   *dlist;
	ColumnDef  *column;
542 543
	List	   *constraints,
			   *clist;
544 545 546
	Constraint *constraint;
	List	   *keys;
	Ident	   *key;
B
Bruce Momjian 已提交
547 548 549 550 551 552
	List	   *blist = NIL;	/* "before list" of things to do before
								 * creating the table */
	List	   *ilist = NIL;	/* "index list" of things to do after
								 * creating the table */
	IndexStmt  *index,
			   *pkey = NULL;
553 554 555 556 557 558 559 560 561 562 563 564 565 566 567 568 569
	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;
570
				columns = lappend(columns, column);
571 572 573

				if (column->is_sequence)
				{
B
Bruce Momjian 已提交
574 575
					char	   *sname;
					char	   *cstring;
576 577
					CreateSeqStmt *sequence;

578 579
					sname = makeObjectName(stmt->relname, column->colname,
										   "seq");
580 581
					constraint = makeNode(Constraint);
					constraint->contype = CONSTR_DEFAULT;
582
					constraint->name = sname;
583
					cstring = palloc(10 + strlen(constraint->name) + 3 + 1);
584
					strcpy(cstring, "nextval('\"");
585
					strcat(cstring, constraint->name);
586
					strcat(cstring, "\"')");
587 588 589
					constraint->def = cstring;
					constraint->keys = NULL;

590
					column->constraints = lappend(column->constraints, constraint);
591

592 593
					constraint = makeNode(Constraint);
					constraint->contype = CONSTR_UNIQUE;
594 595 596
					constraint->name = makeObjectName(stmt->relname,
													  column->colname,
													  "key");
597
					column->constraints = lappend(column->constraints, constraint);
598

599
					sequence = makeNode(CreateSeqStmt);
600
					sequence->seqname = pstrdup(sname);
601 602
					sequence->options = NIL;

603
					elog(NOTICE, "CREATE TABLE will create implicit sequence '%s' for SERIAL column '%s.%s'",
604
					  sequence->seqname, stmt->relname, column->colname);
605

B
Bruce Momjian 已提交
606
					blist = lcons(sequence, NIL);
607 608
				}

609 610 611 612 613 614 615 616
				if (column->constraints != NIL)
				{
					clist = column->constraints;
					while (clist != NIL)
					{
						constraint = lfirst(clist);
						switch (constraint->contype)
						{
617
							case CONSTR_NULL:
B
Bruce Momjian 已提交
618 619 620 621 622

								/*
								 * We should mark this explicitly, so we
								 * can tell if NULL and NOT NULL are both
								 * specified
623 624 625
								 */
								if (column->is_not_null)
									elog(ERROR, "CREATE TABLE/(NOT) NULL conflicting declaration"
626
										 " for '%s.%s'", stmt->relname, column->colname);
627 628 629
								column->is_not_null = FALSE;
								break;

630 631
							case CONSTR_NOTNULL:
								if (column->is_not_null)
632
									elog(ERROR, "CREATE TABLE/NOT NULL already specified"
633
										 " for '%s.%s'", stmt->relname, column->colname);
634 635 636 637 638
								column->is_not_null = TRUE;
								break;

							case CONSTR_DEFAULT:
								if (column->defval != NULL)
639
									elog(ERROR, "CREATE TABLE/DEFAULT multiple values specified"
640
										 " for '%s.%s'", stmt->relname, column->colname);
641 642 643 644 645
								column->defval = constraint->def;
								break;

							case CONSTR_PRIMARY:
								if (constraint->name == NULL)
646
									constraint->name = makeObjectName(stmt->relname, NULL, "pkey");
647 648 649 650 651 652 653
								if (constraint->keys == NIL)
									constraint->keys = lappend(constraint->keys, column);
								dlist = lappend(dlist, constraint);
								break;

							case CONSTR_UNIQUE:
								if (constraint->name == NULL)
654
									constraint->name = makeObjectName(stmt->relname, column->colname, "key");
655 656 657 658 659 660 661 662
								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)
663
									constraint->name = makeObjectName(stmt->relname, column->colname, NULL);
664 665 666
								break;

							default:
T
Thomas G. Lockhart 已提交
667
								elog(ERROR, "parser: unrecognized constraint (internal error)", NULL);
668 669 670 671 672 673 674 675 676 677 678 679 680
								break;
						}
						clist = lnext(clist);
					}
				}
				break;

			case T_Constraint:
				constraint = (Constraint *) element;
				switch (constraint->contype)
				{
					case CONSTR_PRIMARY:
						if (constraint->name == NULL)
681
							constraint->name = makeObjectName(stmt->relname, NULL, "pkey");
682 683 684 685 686 687 688 689 690 691 692 693 694
						dlist = lappend(dlist, constraint);
						break;

					case CONSTR_UNIQUE:
						dlist = lappend(dlist, constraint);
						break;

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

					case CONSTR_NOTNULL:
					case CONSTR_DEFAULT:
T
Thomas G. Lockhart 已提交
695
						elog(ERROR, "parser: illegal context for constraint (internal error)", NULL);
696 697
						break;
					default:
T
Thomas G. Lockhart 已提交
698
						elog(ERROR, "parser: unrecognized constraint (internal error)", NULL);
699 700 701 702 703
						break;
				}
				break;

			default:
T
Thomas G. Lockhart 已提交
704
				elog(ERROR, "parser: unrecognized node (internal error)", NULL);
705 706 707 708 709 710 711 712 713 714 715 716 717
		}

		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
718
 *	and either ignore or stop with warning. The create might fail later when
719
 *	names for indices turn out to be duplicated, or a user might have specified
720
 *	extra useless indices which might hurt performance. - thomas 1997-12-08
721 722 723 724
 */
	while (dlist != NIL)
	{
		constraint = lfirst(dlist);
725 726
		Assert(nodeTag(constraint) == T_Constraint);
		Assert((constraint->contype == CONSTR_PRIMARY)
B
Bruce Momjian 已提交
727
			   || (constraint->contype == CONSTR_UNIQUE));
728

729 730 731
		index = makeNode(IndexStmt);

		index->unique = TRUE;
B
Bruce Momjian 已提交
732
		index->primary = (constraint->contype == CONSTR_PRIMARY ? TRUE : FALSE);
733
		if (index->primary)
734
		{
735
			if (pkey != NULL)
736
				elog(ERROR, "CREATE TABLE/PRIMARY KEY multiple primary keys"
737
					 " for table '%s' are not allowed", stmt->relname);
738
			pkey = (IndexStmt *) index;
739
		}
740

741
		if (constraint->name != NULL)
742
			index->idxname = pstrdup(constraint->name);
743
		else if (constraint->contype == CONSTR_PRIMARY)
744
			index->idxname = makeObjectName(stmt->relname, NULL, "pkey");
745 746 747 748 749 750 751 752
		else
			index->idxname = NULL;

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

754 755 756 757 758 759 760 761 762
		keys = constraint->keys;
		while (keys != NIL)
		{
			key = lfirst(keys);
			columns = stmt->tableElts;
			column = NULL;
			while (columns != NIL)
			{
				column = lfirst(columns);
763 764 765 766
				if (strcasecmp(column->colname, key->name) == 0)
					break;
				else
					column = NULL;
767 768 769
				columns = lnext(columns);
			}
			if (column == NULL)
T
Thomas G. Lockhart 已提交
770
				elog(ERROR, "CREATE TABLE column '%s' in key does not exist", key->name);
771 772 773 774

			if (constraint->contype == CONSTR_PRIMARY)
				column->is_not_null = TRUE;
			iparam = makeNode(IndexElem);
775
			iparam->name = pstrdup(column->colname);
776 777
			iparam->args = NIL;
			iparam->class = NULL;
778
			iparam->typename = NULL;
779 780 781
			index->indexParams = lappend(index->indexParams, iparam);

			if (index->idxname == NULL)
782
				index->idxname = CreateIndexName(stmt->relname, iparam->name, "key", ilist);
783 784 785 786

			keys = lnext(keys);
		}

787 788
		if (index->idxname == NULL)	/* should not happen */
			elog(ERROR, "CREATE TABLE: failed to make implicit index name");
789

790
		ilist = lappend(ilist, index);
791 792 793
		dlist = lnext(dlist);
	}

794 795 796 797 798 799 800 801 802 803 804
/* OK, now finally, if there is a primary key, then make sure that there aren't any redundant
 * unique indices defined on columns. This can arise if someone specifies UNIQUE explicitly
 * or if a SERIAL column was defined along with a table PRIMARY KEY constraint.
 * - thomas 1999-05-11
 */
	if ((pkey != NULL) && (length(lfirst(pkey->indexParams)) == 1))
	{
		dlist = ilist;
		ilist = NIL;
		while (dlist != NIL)
		{
B
Bruce Momjian 已提交
805
			int			keep = TRUE;
806 807 808

			index = lfirst(dlist);

B
Bruce Momjian 已提交
809 810 811 812
			/*
			 * has a single column argument, so might be a conflicting
			 * index...
			 */
813
			if ((index != pkey)
B
Bruce Momjian 已提交
814
				&& (length(index->indexParams) == 1))
815
			{
B
Bruce Momjian 已提交
816 817 818
				char	   *pname = ((IndexElem *) lfirst(index->indexParams))->name;
				char	   *iname = ((IndexElem *) lfirst(index->indexParams))->name;

819 820 821 822 823 824 825 826 827 828 829 830 831 832 833
				/* same names? then don't keep... */
				keep = (strcmp(iname, pname) != 0);
			}

			if (keep)
				ilist = lappend(ilist, index);
			dlist = lnext(dlist);
		}
	}

	dlist = ilist;
	while (dlist != NIL)
	{
		index = lfirst(dlist);
		elog(NOTICE, "CREATE TABLE/%s will create implicit index '%s' for table '%s'",
B
Bruce Momjian 已提交
834
			 (index->primary ? "PRIMARY KEY" : "UNIQUE"),
835 836 837 838
			 index->idxname, stmt->relname);
		dlist = lnext(dlist);
	}

839
	q->utilityStmt = (Node *) stmt;
B
Bruce Momjian 已提交
840 841
	extras_before = blist;
	extras_after = ilist;
842 843

	return q;
B
Bruce Momjian 已提交
844
}	/* transformCreateStmt() */
845

846 847
/*
 * transformIndexStmt -
848
 *	  transforms the qualification of the index statement
849
 */
850
static Query *
851
transformIndexStmt(ParseState *pstate, IndexStmt *stmt)
852
{
B
Bruce Momjian 已提交
853
	Query	   *qry;
854

B
Bruce Momjian 已提交
855 856
	qry = makeNode(Query);
	qry->commandType = CMD_UTILITY;
857

858
	/* take care of the where clause */
859
	stmt->whereClause = transformWhereClause(pstate, stmt->whereClause, NULL);
B
Bruce Momjian 已提交
860
	qry->hasSubLinks = pstate->p_hasSubLinks;
861

862
	stmt->rangetable = pstate->p_rtable;
863

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

B
Bruce Momjian 已提交
866
	return qry;
867 868 869 870
}

/*
 * transformExtendStmt -
871
 *	  transform the qualifications of the Extend Index Statement
872 873
 *
 */
874
static Query *
875
transformExtendStmt(ParseState *pstate, ExtendStmt *stmt)
876
{
B
Bruce Momjian 已提交
877
	Query	   *qry;
878

B
Bruce Momjian 已提交
879 880
	qry = makeNode(Query);
	qry->commandType = CMD_UTILITY;
881

882
	/* take care of the where clause */
883
	stmt->whereClause = transformWhereClause(pstate, stmt->whereClause, NULL);
B
Bruce Momjian 已提交
884 885
	qry->hasSubLinks = pstate->p_hasSubLinks;

886
	stmt->rangetable = pstate->p_rtable;
887

B
Bruce Momjian 已提交
888 889
	qry->utilityStmt = (Node *) stmt;
	return qry;
890 891 892 893
}

/*
 * transformRuleStmt -
894 895
 *	  transform a Create Rule Statement. The actions is a list of parse
 *	  trees which is transformed into a list of query trees.
896
 */
897
static Query *
898
transformRuleStmt(ParseState *pstate, RuleStmt *stmt)
899
{
B
Bruce Momjian 已提交
900
	Query	   *qry;
M
 
Marc G. Fournier 已提交
901
	Query	   *action;
902
	List	   *actions;
903

B
Bruce Momjian 已提交
904 905
	qry = makeNode(Query);
	qry->commandType = CMD_UTILITY;
906

M
 
Marc G. Fournier 已提交
907
	/*
908 909 910 911 912
	 * '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.
M
 
Marc G. Fournier 已提交
913
	 */
914 915 916 917
	if (stmt->actions == NIL)
	{
		Query	   *nothing_qry = makeNode(Query);

M
 
Marc G. Fournier 已提交
918 919 920 921 922 923 924 925 926 927 928 929
		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);
	}

930 931
	actions = stmt->actions;

932
	/*
933
	 * transform each statment, like parse_analyze()
934
	 */
935 936
	while (actions != NIL)
	{
937

938 939 940 941 942
		/*
		 * NOTE: 'CURRENT' must always have a varno equal to 1 and 'NEW'
		 * equal to 2.
		 */
		addRangeTableEntry(pstate, stmt->object->relname, "*CURRENT*",
943
						   FALSE, FALSE);
944
		addRangeTableEntry(pstate, stmt->object->relname, "*NEW*",
945
						   FALSE, FALSE);
946 947 948

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

951
		action = (Query *) lfirst(actions);
M
 
Marc G. Fournier 已提交
952 953
		if (action->commandType != CMD_NOTHING)
			lfirst(actions) = transformStmt(pstate, lfirst(actions));
954 955
		actions = lnext(actions);
	}
956

957
	/* take care of the where clause */
958
	stmt->whereClause = transformWhereClause(pstate, stmt->whereClause, NULL);
B
Bruce Momjian 已提交
959
	qry->hasSubLinks = pstate->p_hasSubLinks;
960

B
Bruce Momjian 已提交
961 962
	qry->utilityStmt = (Node *) stmt;
	return qry;
963 964 965 966 967
}


/*
 * transformSelectStmt -
968
 *	  transforms a Select Statement
969 970
 *
 */
971
static Query *
B
Bruce Momjian 已提交
972
transformSelectStmt(ParseState *pstate, SelectStmt *stmt)
973
{
974
	Query	   *qry = makeNode(Query);
975
	Node	   *qual;
976 977

	qry->commandType = CMD_SELECT;
978

979
	/* set up a range table */
980
	makeRangeTable(pstate, NULL, stmt->fromClause, &qual);
981

982
	qry->uniqueFlag = stmt->unique;
983

984
	qry->into = stmt->into;
985
	qry->isTemp = stmt->istemp;
986
	qry->isPortal = FALSE;
987

988
	qry->targetList = transformTargetList(pstate, stmt->targetList);
989

990
	qry->qual = transformWhereClause(pstate, stmt->whereClause, qual);
991

992 993 994
	/*
	 * The havingQual has a similar meaning as "qual" in the where
	 * statement. So we can easily use the code from the "where clause"
T
Thomas G. Lockhart 已提交
995
	 * with some additional traversals done in optimizer/plan/planner.c
996
	 */
997
	qry->havingQual = transformWhereClause(pstate, stmt->havingClause, NULL);
998

B
Bruce Momjian 已提交
999
	qry->hasSubLinks = pstate->p_hasSubLinks;
1000

1001 1002
	qry->sortClause = transformSortClause(pstate,
										  stmt->sortClause,
B
Bruce Momjian 已提交
1003
										  NIL,
1004 1005
										  qry->targetList,
										  qry->uniqueFlag);
1006

1007 1008 1009 1010
	qry->groupClause = transformGroupClause(pstate,
											stmt->groupClause,
											qry->targetList);
	qry->rtable = pstate->p_rtable;
1011

B
Bruce Momjian 已提交
1012
	qry->hasAggs = pstate->p_hasAggs;
1013
	if (pstate->p_hasAggs || qry->groupClause)
B
Bruce Momjian 已提交
1014
		parseCheckAggregates(pstate, qry);
1015

1016 1017 1018
	/*
	 * The INSERT INTO ... SELECT ... could have a UNION in child, so
	 * unionClause may be false
1019 1020
	 */
	qry->unionall = stmt->unionall;
B
Hi!  
Bruce Momjian 已提交
1021

B
Bruce Momjian 已提交
1022 1023 1024 1025 1026 1027
	/*
	 * Just hand through the unionClause and intersectClause. We will
	 * handle it in the function Except_Intersect_Rewrite()
	 */
	qry->unionClause = stmt->unionClause;
	qry->intersectClause = stmt->intersectClause;
1028

1029 1030 1031 1032 1033 1034 1035 1036
	/*
	 * 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))
	{
T
Thomas G. Lockhart 已提交
1037
		elog(ERROR, "SELECT/HAVING requires aggregates to be valid");
1038 1039
		return (Query *) NIL;
	}
1040

1041 1042 1043
	if (stmt->forUpdate != NULL)
		transformForUpdate(qry, stmt->forUpdate);

1044
	return (Query *) qry;
1045 1046 1047 1048
}

/*
 * transformUpdateStmt -
1049
 *	  transforms an update statement
1050 1051
 *
 */
1052
static Query *
B
Bruce Momjian 已提交
1053
transformUpdateStmt(ParseState *pstate, UpdateStmt *stmt)
1054
{
1055
	Query	   *qry = makeNode(Query);
1056 1057 1058

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

1060 1061 1062 1063
	/*
	 * 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.
	 */
1064
	makeRangeTable(pstate, stmt->relname, stmt->fromClause, NULL);
1065

1066
	qry->targetList = transformTargetList(pstate, stmt->targetList);
1067

1068
	qry->qual = transformWhereClause(pstate, stmt->whereClause, NULL);
B
Bruce Momjian 已提交
1069
	qry->hasSubLinks = pstate->p_hasSubLinks;
1070

1071
	qry->rtable = pstate->p_rtable;
1072

1073
	qry->resultRelation = refnameRangeTablePosn(pstate, stmt->relname, NULL);
1074

B
Bruce Momjian 已提交
1075
	qry->hasAggs = pstate->p_hasAggs;
1076
	if (pstate->p_hasAggs)
1077
		parseCheckAggregates(pstate, qry);
1078

1079
	return (Query *) qry;
1080 1081 1082 1083
}

/*
 * transformCursorStmt -
1084
 *	  transform a Create Cursor Statement
1085 1086
 *
 */
1087
static Query *
1088
transformCursorStmt(ParseState *pstate, SelectStmt *stmt)
1089
{
1090
	Query	   *qry;
1091

1092
	qry = transformSelectStmt(pstate, stmt);
1093

1094
	qry->into = stmt->portalname;
1095
	qry->isTemp = stmt->istemp;
1096 1097
	qry->isPortal = TRUE;
	qry->isBinary = stmt->binary;		/* internal portal */
1098

1099
	return qry;
1100
}
B
Hi!  
Bruce Momjian 已提交
1101 1102 1103 1104 1105 1106 1107

/* This function steps through the tree
 * built up by the select_w_o_sort rule
 * and builds a list of all SelectStmt Nodes found
 * The built up list is handed back in **select_list.
 * If one of the SelectStmt Nodes has the 'unionall' flag
 * set to true *unionall_present hands back 'true' */
B
Bruce Momjian 已提交
1108
void
B
Hi!  
Bruce Momjian 已提交
1109 1110
create_select_list(Node *ptr, List **select_list, bool *unionall_present)
{
B
Bruce Momjian 已提交
1111 1112 1113 1114 1115 1116 1117 1118 1119 1120 1121 1122
	if (IsA(ptr, SelectStmt))
	{
		*select_list = lappend(*select_list, ptr);
		if (((SelectStmt *) ptr)->unionall == TRUE)
			*unionall_present = TRUE;
		return;
	}

	/* Recursively call for all arguments. A NOT expr has no lexpr! */
	if (((A_Expr *) ptr)->lexpr != NULL)
		create_select_list(((A_Expr *) ptr)->lexpr, select_list, unionall_present);
	create_select_list(((A_Expr *) ptr)->rexpr, select_list, unionall_present);
B
Hi!  
Bruce Momjian 已提交
1123 1124 1125
}

/* Changes the A_Expr Nodes to Expr Nodes and exchanges ANDs and ORs.
B
Bruce Momjian 已提交
1126
 * The reason for the exchange is easy: We implement INTERSECTs and EXCEPTs
B
Hi!  
Bruce Momjian 已提交
1127
 * by rewriting these queries to semantically equivalent queries that use
B
Bruce Momjian 已提交
1128 1129
 * IN and NOT IN subselects. To be able to use all three operations
 * (UNIONs INTERSECTs and EXCEPTs) in one complex query we have to
B
Hi!  
Bruce Momjian 已提交
1130 1131 1132 1133 1134 1135
 * translate the queries into Disjunctive Normal Form (DNF). Unfortunately
 * there is no function 'dnfify' but there is a function 'cnfify'
 * which produces DNF when we exchange ANDs and ORs before calling
 * 'cnfify' and exchange them back in the result.
 *
 * If an EXCEPT or INTERSECT is present *intersect_present
B
Bruce Momjian 已提交
1136 1137 1138
 * hands back 'true' */
Node *
A_Expr_to_Expr(Node *ptr, bool *intersect_present)
B
Hi!  
Bruce Momjian 已提交
1139
{
B
Bruce Momjian 已提交
1140 1141 1142 1143 1144 1145 1146 1147 1148 1149 1150 1151 1152 1153 1154 1155 1156 1157 1158 1159 1160 1161 1162 1163 1164 1165 1166 1167 1168 1169 1170 1171 1172 1173 1174 1175 1176 1177 1178 1179 1180 1181 1182 1183 1184 1185 1186 1187 1188 1189 1190
	Node	   *result = NULL;

	switch (nodeTag(ptr))
	{
		case T_A_Expr:
			{
				A_Expr	   *a = (A_Expr *) ptr;

				switch (a->oper)
				{
					case AND:
						{
							Expr	   *expr = makeNode(Expr);
							Node	   *lexpr = A_Expr_to_Expr(((A_Expr *) ptr)->lexpr, intersect_present);
							Node	   *rexpr = A_Expr_to_Expr(((A_Expr *) ptr)->rexpr, intersect_present);

							*intersect_present = TRUE;

							expr->typeOid = BOOLOID;
							expr->opType = OR_EXPR;
							expr->args = makeList(lexpr, rexpr, -1);
							result = (Node *) expr;
							break;
						}
					case OR:
						{
							Expr	   *expr = makeNode(Expr);
							Node	   *lexpr = A_Expr_to_Expr(((A_Expr *) ptr)->lexpr, intersect_present);
							Node	   *rexpr = A_Expr_to_Expr(((A_Expr *) ptr)->rexpr, intersect_present);

							expr->typeOid = BOOLOID;
							expr->opType = AND_EXPR;
							expr->args = makeList(lexpr, rexpr, -1);
							result = (Node *) expr;
							break;
						}
					case NOT:
						{
							Expr	   *expr = makeNode(Expr);
							Node	   *rexpr = A_Expr_to_Expr(((A_Expr *) ptr)->rexpr, intersect_present);

							expr->typeOid = BOOLOID;
							expr->opType = NOT_EXPR;
							expr->args = makeList(rexpr, -1);
							result = (Node *) expr;
							break;
						}
				}
				break;
			}
		default:
1191
			result = ptr;
B
Bruce Momjian 已提交
1192 1193
	}
	return result;
B
Hi!  
Bruce Momjian 已提交
1194
}
1195

1196 1197 1198 1199 1200 1201 1202 1203 1204 1205 1206 1207 1208
void
CheckSelectForUpdate(Query *qry)
{
	if (qry->unionClause != NULL)
		elog(ERROR, "SELECT FOR UPDATE is not allowed with UNION/INTERSECT/EXCEPT clause");
	if (qry->uniqueFlag != NULL)
		elog(ERROR, "SELECT FOR UPDATE is not allowed with DISTINCT clause");
	if (qry->groupClause != NULL)
		elog(ERROR, "SELECT FOR UPDATE is not allowed with GROUP BY clause");
	if (qry->hasAggs)
		elog(ERROR, "SELECT FOR UPDATE is not allowed with AGGREGATE");
}

1209 1210 1211 1212
static void
transformForUpdate(Query *qry, List *forUpdate)
{
	List	   *rowMark = NULL;
B
Bruce Momjian 已提交
1213
	RowMark    *newrm;
1214 1215 1216
	List	   *l;
	Index		i;

1217 1218
	CheckSelectForUpdate(qry);

1219 1220 1221
	if (lfirst(forUpdate) == NULL)		/* all tables */
	{
		i = 1;
B
Bruce Momjian 已提交
1222
		foreach(l, qry->rtable)
1223 1224 1225
		{
			newrm = makeNode(RowMark);
			newrm->rti = i++;
B
Bruce Momjian 已提交
1226
			newrm->info = ROW_MARK_FOR_UPDATE | ROW_ACL_FOR_UPDATE;
1227 1228 1229 1230 1231 1232
			rowMark = lappend(rowMark, newrm);
		}
		qry->rowMark = nconc(qry->rowMark, rowMark);
		return;
	}

B
Bruce Momjian 已提交
1233
	foreach(l, forUpdate)
1234
	{
B
Bruce Momjian 已提交
1235 1236
		List	   *l2;
		List	   *l3;
1237 1238

		i = 1;
B
Bruce Momjian 已提交
1239
		foreach(l2, qry->rtable)
1240
		{
B
Bruce Momjian 已提交
1241
			if (strcmp(((RangeTblEntry *) lfirst(l2))->refname, lfirst(l)) == 0)
1242
			{
B
Bruce Momjian 已提交
1243
				foreach(l3, rowMark)
1244
				{
B
Bruce Momjian 已提交
1245
					if (((RowMark *) lfirst(l3))->rti == i)		/* duplicate */
1246 1247 1248 1249 1250 1251
						break;
				}
				if (l3 == NULL)
				{
					newrm = makeNode(RowMark);
					newrm->rti = i;
B
Bruce Momjian 已提交
1252
					newrm->info = ROW_MARK_FOR_UPDATE | ROW_ACL_FOR_UPDATE;
1253 1254 1255 1256 1257 1258 1259 1260 1261 1262 1263 1264 1265
					rowMark = lappend(rowMark, newrm);
				}
				break;
			}
			i++;
		}
		if (l2 == NULL)
			elog(ERROR, "FOR UPDATE: relation %s not found in FROM clause", lfirst(l));
	}

	qry->rowMark = rowMark;
	return;
}