analyze.c 34.2 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.103 1999/05/13 07:28:34 tgl 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 33
/***S*I***/
#include "parser/parse_expr.h"
#include "catalog/pg_type.h"
#include "parse.h"

34 35
#include "utils/builtins.h"
#include "utils/mcxt.h"
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 49
static void		transformForUpdate(Query *qry, List *forUpdate);
void			CheckSelectForUpdate(Query *qry);
50

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

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

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

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

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

87
		while (extras_after != NIL)
B
Bruce Momjian 已提交
88
		{
89 90 91 92 93
			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 已提交
94 95
		}

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

	return result;
101 102 103 104
}

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

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

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

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

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

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

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

146 147 148
		case T_VacuumStmt:
			{
				MemoryContext oldcontext;
149

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

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

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

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

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

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

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

202
		default:
203

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

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

225
	qry->commandType = CMD_DELETE;
226

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

230
	qry->uniqueFlag = NULL;
231

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

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

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

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

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

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

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

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

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

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

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

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

			foreach(extrl, icolumns)
288
			{
289 290 291 292
				/*
				 * decrements first, so if we started with zero items
				 * it will now be negative
				 */
293 294 295
				if (--i <= 0)
					break;
			}
296 297 298 299 300 301 302 303 304 305 306 307 308
			/*
			 * this an index into the targetList,
			 * so make sure we had one to start...
			 */
			if (i >= 0)
			{
				freeList(lnext(extrl));
				lnext(extrl) = NIL;
			}
			else
			{
				icolumns = NIL;
			}
309
		}
310

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

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

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

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

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

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

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

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

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

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

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

 	/***S*I***/
 	/* 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
/*
 *	makeTableName()
 *	Create a table name from a list of fields.
412 413 414 415
 */
static char *
makeTableName(void *elem,...)
{
416
	va_list		args;
417

418 419
	char	   *name;
	char		buf[NAMEDATALEN + 1];
420

B
Bruce Momjian 已提交
421
	buf[0] = '\0';
422

423
	va_start(args, elem);
424 425 426 427 428

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

B
Bruce Momjian 已提交
432
		if (strlen(buf) > 0)
433 434
			strcat(buf, "_");
		strcat(buf, name);
435

436
		name = va_arg(args, void *);
437 438 439 440
	}

	va_end(args);

441 442
	name = palloc(strlen(buf) + 1);
	strcpy(name, buf);
443

444
	return name;
B
Bruce Momjian 已提交
445
}
446

B
Bruce Momjian 已提交
447
static char *
448
CreateIndexName(char *table_name, char *column_name, char *label, List *indices)
449 450 451 452 453
{
	int			pass = 0;
	char	   *iname = NULL;
	List	   *ilist;
	IndexStmt  *index;
454
	char		name2[NAMEDATALEN + 1];
455 456

	/* use working storage, since we might be trying several possibilities */
457
	strcpy(name2, column_name);
458 459
	while (iname == NULL)
	{
460
		iname = makeTableName(table_name, name2, label, NULL);
461 462 463 464 465 466 467 468
		/* unable to make a name at all? then quit */
		if (iname == NULL)
			break;

		ilist = indices;
		while (ilist != NIL)
		{
			index = lfirst(ilist);
469
			if (strcasecmp(iname, index->idxname) == 0)
470 471 472 473 474 475 476 477 478 479 480 481
				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++;
482
		sprintf(name2, "%s_%d", column_name, (pass + 1));
483 484
	}

485
	return iname;
B
Bruce Momjian 已提交
486
}
487

488 489 490 491 492 493 494 495 496 497 498 499 500 501 502 503 504 505
/*
 * 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;
506 507
	List	   *constraints,
			   *clist;
508 509 510
	Constraint *constraint;
	List	   *keys;
	Ident	   *key;
511 512 513
	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;
514 515 516 517 518 519 520 521 522 523 524 525 526 527 528 529 530
	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;
531
				columns = lappend(columns, column);
532 533 534

				if (column->is_sequence)
				{
535 536
					char		  *sname;
					char		  *cstring;
537 538
					CreateSeqStmt *sequence;

539
					sname = makeTableName(stmt->relname, column->colname, "seq", NULL);
540 541 542 543
					if (sname == NULL)
						elog(ERROR, "CREATE TABLE/SERIAL implicit sequence name must be less than %d characters"
							 "\n\tSum of lengths of '%s' and '%s' must be less than %d",
							 NAMEDATALEN, stmt->relname, column->colname, (NAMEDATALEN-5));
544

545 546
					constraint = makeNode(Constraint);
					constraint->contype = CONSTR_DEFAULT;
547
					constraint->name = sname;
548
					cstring = palloc(9 + strlen(constraint->name) + 2 + 1);
549 550 551 552 553 554
					strcpy(cstring, "nextval('");
					strcat(cstring, constraint->name);
					strcat(cstring, "')");
					constraint->def = cstring;
					constraint->keys = NULL;

555
#if 0
556 557 558 559 560 561
					/* The parser only allows PRIMARY KEY as a constraint for the SERIAL type.
					 * So, if there is a constraint of any kind, assume it is that.
					 * If PRIMARY KEY is specified, then don't need to gin up a UNIQUE constraint
					 * since that will be covered already.
					 * - thomas 1998-09-15
					 */
562
					if (column->constraints != NIL)
563
					{
564
						column->constraints = lappend(column->constraints, constraint);
565
					}
566
					else
567
					{
568 569
#endif
						column->constraints = lappend(column->constraints, constraint);
570

571 572 573
						constraint = makeNode(Constraint);
						constraint->contype = CONSTR_UNIQUE;
						constraint->name = makeTableName(stmt->relname, column->colname, "key", NULL);
574 575 576 577
						if (constraint->name == NULL)
							elog(ERROR, "CREATE TABLE/SERIAL implicit index name must be less than %d characters"
								 "\n\tSum of lengths of '%s' and '%s' must be less than %d",
								 NAMEDATALEN, stmt->relname, column->colname, (NAMEDATALEN-5));
578
						column->constraints = lappend(column->constraints, constraint);
579
#if 0
580
					}
581
#endif
582

583
					sequence = makeNode(CreateSeqStmt);
584
					sequence->seqname = pstrdup(sname);
585 586
					sequence->options = NIL;

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

B
Bruce Momjian 已提交
590
					blist = lcons(sequence, NIL);
591 592
				}

593 594 595 596 597 598 599 600
				if (column->constraints != NIL)
				{
					clist = column->constraints;
					while (clist != NIL)
					{
						constraint = lfirst(clist);
						switch (constraint->contype)
						{
601 602 603 604 605 606 607 608 609 610
							case CONSTR_NULL:
								/* We should mark this explicitly,
								 * so we can tell if NULL and NOT NULL are both specified
								 */
								if (column->is_not_null)
									elog(ERROR, "CREATE TABLE/(NOT) NULL conflicting declaration"
										 " for %s.%s", stmt->relname, column->colname);
								column->is_not_null = FALSE;
								break;

611 612
							case CONSTR_NOTNULL:
								if (column->is_not_null)
613 614
									elog(ERROR, "CREATE TABLE/NOT NULL already specified"
										 " for %s.%s", stmt->relname, column->colname);
615 616 617 618 619
								column->is_not_null = TRUE;
								break;

							case CONSTR_DEFAULT:
								if (column->defval != NULL)
620 621
									elog(ERROR, "CREATE TABLE/DEFAULT multiple values specified"
										 " for %s.%s", stmt->relname, column->colname);
622 623 624 625 626 627
								column->defval = constraint->def;
								break;

							case CONSTR_PRIMARY:
								if (constraint->name == NULL)
									constraint->name = makeTableName(stmt->relname, "pkey", NULL);
628 629 630 631
								if (constraint->name == NULL)
									elog(ERROR, "CREATE TABLE/PRIMARY KEY implicit index name must be less than %d characters"
										 "\n\tLength of '%s' must be less than %d",
										 NAMEDATALEN, stmt->relname, (NAMEDATALEN-6));
632 633 634 635 636 637 638 639
								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);
640 641 642 643
								if (constraint->name == NULL)
									elog(ERROR, "CREATE TABLE/UNIQUE implicit index name must be less than %d characters"
										 "\n\tLength of '%s' must be less than %d",
										 NAMEDATALEN, stmt->relname, (NAMEDATALEN-5));
644 645 646 647 648 649 650 651
								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)
652
									constraint->name = makeTableName(stmt->relname, column->colname, NULL);
653 654 655 656
								if (constraint->name == NULL)
									elog(ERROR, "CREATE TABLE/CHECK implicit constraint name must be less than %d characters"
										 "\n\tSum of lengths of '%s' and '%s' must be less than %d",
										 NAMEDATALEN, stmt->relname, column->colname, (NAMEDATALEN-1));
657 658 659
								break;

							default:
T
Thomas G. Lockhart 已提交
660
								elog(ERROR, "parser: unrecognized constraint (internal error)", NULL);
661 662 663 664 665 666 667 668 669 670 671 672 673 674
								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);
675 676 677 678
						if (constraint->name == NULL)
							elog(ERROR, "CREATE TABLE/PRIMARY KEY implicit index name must be less than %d characters"
								 "\n\tLength of '%s' must be less than %d",
								 NAMEDATALEN, stmt->relname, (NAMEDATALEN-5));
679 680 681 682
						dlist = lappend(dlist, constraint);
						break;

					case CONSTR_UNIQUE:
M
 
Marc G. Fournier 已提交
683
#ifdef NOT_USED
684 685 686 687 688 689 690 691 692 693 694 695
						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:
T
Thomas G. Lockhart 已提交
696
						elog(ERROR, "parser: illegal context for constraint (internal error)", NULL);
697 698
						break;
					default:
T
Thomas G. Lockhart 已提交
699
						elog(ERROR, "parser: unrecognized constraint (internal error)", NULL);
700 701 702 703 704
						break;
				}
				break;

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

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

730 731 732 733 734
		index = makeNode(IndexStmt);

		index->unique = TRUE;
		index->primary = (constraint->contype == CONSTR_PRIMARY ? TRUE:FALSE);
		if (index->primary)
735
		{
736
			if (pkey != NULL)
737 738
				elog(ERROR, "CREATE TABLE/PRIMARY KEY multiple primary keys"
					 " for table %s are not legal", stmt->relname);
739
			pkey = (IndexStmt *) index;
740
		}
741

742
		if (constraint->name != NULL)
743
		{
744
			index->idxname = constraint->name;
745
		}
746
		else if (constraint->contype == CONSTR_PRIMARY)
747
		{
748
			index->idxname = makeTableName(stmt->relname, "pkey", NULL);
749 750 751 752
			if (index->idxname == NULL)
				elog(ERROR, "CREATE TABLE/PRIMARY KEY implicit index name must be less than %d characters"
					 "\n\tLength of '%s' must be less than %d",
					 NAMEDATALEN, stmt->relname, (NAMEDATALEN-5));
753
		}
754
		else
755
		{
756
			index->idxname = NULL;
757
		}
758 759 760 761 762 763

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

765 766 767 768 769 770 771 772 773
		keys = constraint->keys;
		while (keys != NIL)
		{
			key = lfirst(keys);
			columns = stmt->tableElts;
			column = NULL;
			while (columns != NIL)
			{
				column = lfirst(columns);
774 775 776 777
				if (strcasecmp(column->colname, key->name) == 0)
					break;
				else
					column = NULL;
778 779 780
				columns = lnext(columns);
			}
			if (column == NULL)
T
Thomas G. Lockhart 已提交
781
				elog(ERROR, "CREATE TABLE column '%s' in key does not exist", key->name);
782 783 784 785

			if (constraint->contype == CONSTR_PRIMARY)
				column->is_not_null = TRUE;
			iparam = makeNode(IndexElem);
786
			iparam->name = strcpy(palloc(strlen(column->colname) + 1), column->colname);
787 788
			iparam->args = NIL;
			iparam->class = NULL;
789
			iparam->typename = NULL;
790 791 792
			index->indexParams = lappend(index->indexParams, iparam);

			if (index->idxname == NULL)
793
				index->idxname = CreateIndexName(stmt->relname, iparam->name, "key", ilist);
794 795 796 797 798

			keys = lnext(keys);
		}

		if (index->idxname == NULL)
T
Thomas G. Lockhart 已提交
799
			elog(ERROR, "CREATE TABLE unable to construct implicit index for table %s"
800
				 "; name too long", stmt->relname);
801
#if 0
802
		else
803
			elog(NOTICE, "CREATE TABLE/%s will create implicit index '%s' for table '%s'",
804 805
				 ((constraint->contype == CONSTR_PRIMARY) ? "PRIMARY KEY" : "UNIQUE"),
				 index->idxname, stmt->relname);
806
#endif
807

808
		ilist = lappend(ilist, index);
809 810 811
		dlist = lnext(dlist);
	}

812 813 814 815 816 817 818 819 820 821 822 823 824 825 826 827 828 829 830 831 832 833 834 835 836 837 838 839 840 841 842 843 844 845 846 847 848 849 850 851 852
/* 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)
		{
			int keep = TRUE;

			index = lfirst(dlist);

			/* has a single column argument, so might be a conflicting index... */
			if ((index != pkey)
			 && (length(index->indexParams) == 1))
			{
				char *pname = ((IndexElem *) lfirst(index->indexParams))->name;
				char *iname = ((IndexElem *) lfirst(index->indexParams))->name;
				/* 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'",
			 (index->primary? "PRIMARY KEY": "UNIQUE"),
			 index->idxname, stmt->relname);
		dlist = lnext(dlist);
	}

853
	q->utilityStmt = (Node *) stmt;
B
Bruce Momjian 已提交
854 855
	extras_before = blist;
	extras_after = ilist;
856 857

	return q;
B
Bruce Momjian 已提交
858
}
859

860 861
/*
 * transformIndexStmt -
862
 *	  transforms the qualification of the index statement
863
 */
864
static Query *
865
transformIndexStmt(ParseState *pstate, IndexStmt *stmt)
866
{
B
Bruce Momjian 已提交
867
	Query	   *qry;
868

B
Bruce Momjian 已提交
869 870
	qry = makeNode(Query);
	qry->commandType = CMD_UTILITY;
871

872
	/* take care of the where clause */
873
	stmt->whereClause = transformWhereClause(pstate, stmt->whereClause, NULL);
B
Bruce Momjian 已提交
874
	qry->hasSubLinks = pstate->p_hasSubLinks;
875

876
	stmt->rangetable = pstate->p_rtable;
877

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

B
Bruce Momjian 已提交
880
	return qry;
881 882 883 884
}

/*
 * transformExtendStmt -
885
 *	  transform the qualifications of the Extend Index Statement
886 887
 *
 */
888
static Query *
889
transformExtendStmt(ParseState *pstate, ExtendStmt *stmt)
890
{
B
Bruce Momjian 已提交
891
	Query	   *qry;
892

B
Bruce Momjian 已提交
893 894
	qry = makeNode(Query);
	qry->commandType = CMD_UTILITY;
895

896
	/* take care of the where clause */
897
	stmt->whereClause = transformWhereClause(pstate, stmt->whereClause, NULL);
B
Bruce Momjian 已提交
898 899
	qry->hasSubLinks = pstate->p_hasSubLinks;

900
	stmt->rangetable = pstate->p_rtable;
901

B
Bruce Momjian 已提交
902 903
	qry->utilityStmt = (Node *) stmt;
	return qry;
904 905 906 907
}

/*
 * transformRuleStmt -
908 909
 *	  transform a Create Rule Statement. The actions is a list of parse
 *	  trees which is transformed into a list of query trees.
910
 */
911
static Query *
912
transformRuleStmt(ParseState *pstate, RuleStmt *stmt)
913
{
B
Bruce Momjian 已提交
914
	Query	   *qry;
M
 
Marc G. Fournier 已提交
915
	Query	   *action;
916
	List	   *actions;
917

B
Bruce Momjian 已提交
918 919
	qry = makeNode(Query);
	qry->commandType = CMD_UTILITY;
920

M
 
Marc G. Fournier 已提交
921
	/*
922 923 924 925 926
	 * '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 已提交
927
	 */
928 929 930 931
	if (stmt->actions == NIL)
	{
		Query	   *nothing_qry = makeNode(Query);

M
 
Marc G. Fournier 已提交
932 933 934 935 936 937 938 939 940 941 942 943
		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);
	}

944 945
	actions = stmt->actions;

946
	/*
947
	 * transform each statment, like parse_analyze()
948
	 */
949 950
	while (actions != NIL)
	{
951

952 953 954 955 956
		/*
		 * NOTE: 'CURRENT' must always have a varno equal to 1 and 'NEW'
		 * equal to 2.
		 */
		addRangeTableEntry(pstate, stmt->object->relname, "*CURRENT*",
957
						   FALSE, FALSE);
958
		addRangeTableEntry(pstate, stmt->object->relname, "*NEW*",
959
						   FALSE, FALSE);
960 961 962

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

965
		action = (Query *) lfirst(actions);
M
 
Marc G. Fournier 已提交
966 967
		if (action->commandType != CMD_NOTHING)
			lfirst(actions) = transformStmt(pstate, lfirst(actions));
968 969
		actions = lnext(actions);
	}
970

971
	/* take care of the where clause */
972
	stmt->whereClause = transformWhereClause(pstate, stmt->whereClause, NULL);
B
Bruce Momjian 已提交
973
	qry->hasSubLinks = pstate->p_hasSubLinks;
974

B
Bruce Momjian 已提交
975 976
	qry->utilityStmt = (Node *) stmt;
	return qry;
977 978 979 980 981
}


/*
 * transformSelectStmt -
982
 *	  transforms a Select Statement
983 984
 *
 */
985
static Query *
B
Bruce Momjian 已提交
986
transformSelectStmt(ParseState *pstate, SelectStmt *stmt)
987
{
988
	Query	   *qry = makeNode(Query);
989
	Node	   *qual;
990 991

	qry->commandType = CMD_SELECT;
992

993
	/* set up a range table */
994
	makeRangeTable(pstate, NULL, stmt->fromClause, &qual);
995

996
	qry->uniqueFlag = stmt->unique;
997

998
	qry->into = stmt->into;
999
	qry->isTemp = stmt->istemp;
1000
	qry->isPortal = FALSE;
1001

1002
	qry->targetList = transformTargetList(pstate, stmt->targetList);
1003

1004
	qry->qual = transformWhereClause(pstate, stmt->whereClause, qual);
1005

1006 1007 1008
	/*
	 * 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 已提交
1009
	 * with some additional traversals done in optimizer/plan/planner.c
1010
	 */
1011
	qry->havingQual = transformWhereClause(pstate, stmt->havingClause, NULL);
1012

B
Bruce Momjian 已提交
1013
	qry->hasSubLinks = pstate->p_hasSubLinks;
1014

1015 1016
	qry->sortClause = transformSortClause(pstate,
										  stmt->sortClause,
B
Bruce Momjian 已提交
1017
										  NIL,
1018 1019
										  qry->targetList,
										  qry->uniqueFlag);
1020

1021 1022 1023 1024
	qry->groupClause = transformGroupClause(pstate,
											stmt->groupClause,
											qry->targetList);
	qry->rtable = pstate->p_rtable;
1025

B
Bruce Momjian 已提交
1026
	qry->hasAggs = pstate->p_hasAggs;
1027
	if (pstate->p_hasAggs)
B
Bruce Momjian 已提交
1028
		parseCheckAggregates(pstate, qry);
1029

1030 1031 1032
	/*
	 * The INSERT INTO ... SELECT ... could have a UNION in child, so
	 * unionClause may be false
1033 1034
	 */
	qry->unionall = stmt->unionall;
B
Hi!  
Bruce Momjian 已提交
1035 1036 1037 1038 1039 1040

 	/***S*I***/
 	/* 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;
1041

1042 1043 1044 1045 1046 1047 1048 1049
	/*
	 * 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 已提交
1050
		elog(ERROR, "SELECT/HAVING requires aggregates to be valid");
1051 1052
		return (Query *) NIL;
	}
1053

1054 1055 1056
	if (stmt->forUpdate != NULL)
		transformForUpdate(qry, stmt->forUpdate);

1057
	return (Query *) qry;
1058 1059 1060 1061
}

/*
 * transformUpdateStmt -
1062
 *	  transforms an update statement
1063 1064
 *
 */
1065
static Query *
B
Bruce Momjian 已提交
1066
transformUpdateStmt(ParseState *pstate, UpdateStmt *stmt)
1067
{
1068
	Query	   *qry = makeNode(Query);
1069 1070 1071

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

1073 1074 1075 1076
	/*
	 * 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.
	 */
1077
	makeRangeTable(pstate, stmt->relname, stmt->fromClause, NULL);
1078

1079
	qry->targetList = transformTargetList(pstate, stmt->targetList);
1080

1081
	qry->qual = transformWhereClause(pstate, stmt->whereClause, NULL);
B
Bruce Momjian 已提交
1082
	qry->hasSubLinks = pstate->p_hasSubLinks;
1083

1084
	qry->rtable = pstate->p_rtable;
1085

1086
	qry->resultRelation = refnameRangeTablePosn(pstate, stmt->relname, NULL);
1087

B
Bruce Momjian 已提交
1088
	qry->hasAggs = pstate->p_hasAggs;
1089
	if (pstate->p_hasAggs)
1090
		parseCheckAggregates(pstate, qry);
1091

1092
	return (Query *) qry;
1093 1094 1095 1096
}

/*
 * transformCursorStmt -
1097
 *	  transform a Create Cursor Statement
1098 1099
 *
 */
1100
static Query *
1101
transformCursorStmt(ParseState *pstate, SelectStmt *stmt)
1102
{
1103
	Query	   *qry;
1104

1105
	qry = transformSelectStmt(pstate, stmt);
1106

1107
	qry->into = stmt->portalname;
1108
	qry->isTemp = stmt->istemp;
1109 1110
	qry->isPortal = TRUE;
	qry->isBinary = stmt->binary;		/* internal portal */
1111

1112
	return qry;
1113
}
B
Hi!  
Bruce Momjian 已提交
1114 1115 1116 1117 1118 1119 1120 1121 1122 1123 1124 1125 1126 1127 1128 1129 1130 1131 1132 1133 1134 1135 1136 1137 1138 1139 1140 1141 1142 1143 1144 1145 1146 1147 1148 1149 1150

/***S*I***/
/* 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' */
void 
create_select_list(Node *ptr, List **select_list, bool *unionall_present)
{
  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);
}

/* Changes the A_Expr Nodes to Expr Nodes and exchanges ANDs and ORs.
 * The reason for the exchange is easy: We implement INTERSECTs and EXCEPTs 
 * by rewriting these queries to semantically equivalent queries that use
 * IN and NOT IN subselects. To be able to use all three operations 
 * (UNIONs INTERSECTs and EXCEPTs) in one complex query we have to 
 * 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
 * hands back 'true' */ 
Node *A_Expr_to_Expr(Node *ptr, bool *intersect_present)
{
1151
  Node *result = NULL;
B
Hi!  
Bruce Momjian 已提交
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 1191 1192 1193 1194 1195 1196 1197 1198 1199 1200 1201 1202 1203 1204 1205 1206 1207
  
  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:
      {
	result = ptr;
      }      
    }
  return result;  
}
1208

1209 1210 1211 1212 1213 1214 1215 1216 1217 1218 1219 1220 1221
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");
}

1222 1223 1224 1225 1226 1227 1228 1229
static void
transformForUpdate(Query *qry, List *forUpdate)
{
	List	   *rowMark = NULL;
	RowMark	   *newrm;
	List	   *l;
	Index		i;

1230 1231
	CheckSelectForUpdate(qry);

1232 1233 1234 1235 1236 1237 1238 1239 1240 1241 1242 1243 1244 1245 1246 1247 1248 1249 1250 1251 1252 1253 1254 1255 1256 1257 1258 1259 1260 1261 1262 1263 1264 1265 1266 1267 1268 1269 1270 1271 1272 1273 1274 1275 1276 1277 1278
	if (lfirst(forUpdate) == NULL)		/* all tables */
	{
		i = 1;
		foreach (l, qry->rtable)
		{
			newrm = makeNode(RowMark);
			newrm->rti = i++;
			newrm->info = ROW_MARK_FOR_UPDATE|ROW_ACL_FOR_UPDATE;
			rowMark = lappend(rowMark, newrm);
		}
		qry->rowMark = nconc(qry->rowMark, rowMark);
		return;
	}

	foreach (l, forUpdate)
	{
		List   *l2;
		List   *l3;

		i = 1;
		foreach (l2, qry->rtable)
		{
			if (strcmp(((RangeTblEntry*)lfirst(l2))->refname, lfirst(l)) == 0)
			{
				foreach (l3, rowMark)
				{
					if (((RowMark*)lfirst(l3))->rti == i)	/* duplicate */
						break;
				}
				if (l3 == NULL)
				{
					newrm = makeNode(RowMark);
					newrm->rti = i;
					newrm->info = ROW_MARK_FOR_UPDATE|ROW_ACL_FOR_UPDATE;
					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;
}