analyze.c 88.6 KB
Newer Older
1 2
/*-------------------------------------------------------------------------
 *
3
 * analyze.c
4
 *	  transform the parse tree into a query tree
5
 *
6
 * Portions Copyright (c) 1996-2001, PostgreSQL Global Development Group
Bruce Momjian's avatar
Add:  
Bruce Momjian committed
7
 * Portions Copyright (c) 1994, Regents of the University of California
8
 *
9
 *	$Header: /cvsroot/pgsql/src/backend/parser/analyze.c,v 1.203 2001/10/23 17:39:02 tgl Exp $
10 11 12
 *
 *-------------------------------------------------------------------------
 */
13

Bruce Momjian's avatar
Bruce Momjian committed
14
#include "postgres.h"
Bruce Momjian's avatar
Bruce Momjian committed
15

16
#include "access/heapam.h"
Jan Wieck's avatar
Jan Wieck committed
17
#include "catalog/catname.h"
18
#include "catalog/heap.h"
Jan Wieck's avatar
Jan Wieck committed
19
#include "catalog/pg_index.h"
Bruce Momjian's avatar
Bruce Momjian committed
20
#include "catalog/pg_type.h"
21 22
#include "nodes/makefuncs.h"
#include "parser/analyze.h"
23
#include "parser/parse.h"
24
#include "parser/parsetree.h"
25
#include "parser/parse_agg.h"
Bruce Momjian's avatar
Bruce Momjian committed
26
#include "parser/parse_clause.h"
27
#include "parser/parse_coerce.h"
28 29
#include "parser/parse_expr.h"
#include "parser/parse_oper.h"
30 31
#include "parser/parse_relation.h"
#include "parser/parse_target.h"
32
#include "parser/parse_type.h"
33
#include "parser/parse_expr.h"
34
#include "rewrite/rewriteManip.h"
35
#include "utils/builtins.h"
36
#include "utils/fmgroids.h"
37
#include "utils/numeric.h"
38 39
#include "utils/relcache.h"
#include "utils/syscache.h"
40
#include "utils/temprel.h"
41

42 43 44 45
#ifdef MULTIBYTE
#include "mb/pg_wchar.h"
#endif

46 47 48 49 50 51 52 53

/* State shared by transformCreateStmt and its subroutines */
typedef struct
{
	const char *stmtType;		/* "CREATE TABLE" or "ALTER TABLE" */
	char	   *relname;		/* name of relation */
	List	   *inhRelnames;	/* names of relations to inherit from */
	bool		istemp;			/* is it to be a temp relation? */
54
	bool		hasoids;		/* does relation have an OID column? */
55 56 57 58 59 60 61 62 63 64 65 66 67
	Oid			relOid;			/* OID of table, if ALTER TABLE case */
	List	   *columns;		/* ColumnDef items */
	List	   *ckconstraints;	/* CHECK constraints */
	List	   *fkconstraints;	/* FOREIGN KEY constraints */
	List	   *ixconstraints;	/* index-creating constraints */
	List	   *blist;			/* "before list" of things to do before
								 * creating the table */
	List	   *alist;			/* "after list" of things to do after
								 * creating the table */
	IndexStmt  *pkey;			/* PRIMARY KEY index, if any */
} CreateStmtContext;


68 69
static Query *transformStmt(ParseState *pstate, Node *stmt);
static Query *transformDeleteStmt(ParseState *pstate, DeleteStmt *stmt);
Bruce Momjian's avatar
Bruce Momjian committed
70
static Query *transformInsertStmt(ParseState *pstate, InsertStmt *stmt);
71 72
static Query *transformIndexStmt(ParseState *pstate, IndexStmt *stmt);
static Query *transformRuleStmt(ParseState *query, RuleStmt *stmt);
Bruce Momjian's avatar
Bruce Momjian committed
73
static Query *transformSelectStmt(ParseState *pstate, SelectStmt *stmt);
74 75
static Query *transformSetOperationStmt(ParseState *pstate, SelectStmt *stmt);
static Node *transformSetOperationTree(ParseState *pstate, SelectStmt *stmt);
Bruce Momjian's avatar
Bruce Momjian committed
76
static Query *transformUpdateStmt(ParseState *pstate, UpdateStmt *stmt);
77
static Query *transformCreateStmt(ParseState *pstate, CreateStmt *stmt);
78
static Query *transformAlterTableStmt(ParseState *pstate, AlterTableStmt *stmt);
79 80 81 82 83 84 85 86 87 88
static void transformColumnDefinition(ParseState *pstate,
									  CreateStmtContext *cxt,
									  ColumnDef *column);
static void transformTableConstraint(ParseState *pstate,
									 CreateStmtContext *cxt,
									 Constraint *constraint);
static void transformIndexConstraints(ParseState *pstate,
									  CreateStmtContext *cxt);
static void transformFKConstraints(ParseState *pstate,
								   CreateStmtContext *cxt);
89
static Node *transformTypeRefs(ParseState *pstate, Node *stmt);
90

91 92
static void transformTypeRefsList(ParseState *pstate, List *l);
static void transformTypeRef(ParseState *pstate, TypeName *tn);
93
static List *getSetColTypes(ParseState *pstate, Node *node);
Bruce Momjian's avatar
Bruce Momjian committed
94
static void transformForUpdate(Query *qry, List *forUpdate);
95
static void transformConstraintAttrs(List *constraintList);
96
static void transformColumnType(ParseState *pstate, ColumnDef *column);
97
static void transformFkeyCheckAttrs(FkConstraint *fkconstraint, Oid *pktypoid);
98 99 100
static void transformFkeyGetPrimaryKey(FkConstraint *fkconstraint, Oid *pktypoid);
static bool relationHasPrimaryKey(char *relname);
static Oid transformFkeyGetColType(CreateStmtContext *cxt, char *colname);
101
static void release_pstate_resources(ParseState *pstate);
102
static FromExpr *makeFromExpr(List *fromlist, Node *quals);
103

104
/* kluge to return extra info from transformCreateStmt() */
105 106
static List *extras_before;
static List *extras_after;
107

Bruce Momjian's avatar
Bruce Momjian committed
108

109 110
/*
 * parse_analyze -
111
 *	  analyze a raw parse tree and transform it to Query form.
112
 *
113 114 115 116
 * The result is a List of Query nodes (we need a list since some commands
 * produce multiple Queries).  Optimizable statements require considerable
 * transformation, while many utility-type statements are simply hung off
 * a dummy CMD_UTILITY Query node.
117
 */
118
List *
119
parse_analyze(Node *parseTree, ParseState *parentParseState)
120
{
Bruce Momjian's avatar
Bruce Momjian committed
121
	List	   *result = NIL;
122 123
	ParseState *pstate = make_parsestate(parentParseState);
	Query	   *query;
124

125
	extras_before = extras_after = NIL;
126

127 128
	query = transformStmt(pstate, parseTree);
	release_pstate_resources(pstate);
129

130 131 132 133
	while (extras_before != NIL)
	{
		result = lappend(result,
						 transformStmt(pstate, lfirst(extras_before)));
134
		release_pstate_resources(pstate);
135 136
		extras_before = lnext(extras_before);
	}
Bruce Momjian's avatar
Bruce Momjian committed
137

138
	result = lappend(result, query);
Bruce Momjian's avatar
Bruce Momjian committed
139

140 141 142 143 144 145
	while (extras_after != NIL)
	{
		result = lappend(result,
						 transformStmt(pstate, lfirst(extras_after)));
		release_pstate_resources(pstate);
		extras_after = lnext(extras_after);
146 147
	}

148 149
	pfree(pstate);

150
	return result;
151 152
}

153 154 155 156
static void
release_pstate_resources(ParseState *pstate)
{
	if (pstate->p_target_relation != NULL)
157
		heap_close(pstate->p_target_relation, NoLock);
158 159 160 161
	pstate->p_target_relation = NULL;
	pstate->p_target_rangetblentry = NULL;
}

162 163
/*
 * transformStmt -
164
 *	  transform a Parse tree into a Query tree.
165
 */
166
static Query *
167
transformStmt(ParseState *pstate, Node *parseTree)
168
{
169
	Query	   *result = NULL;
170 171 172

	switch (nodeTag(parseTree))
	{
173 174 175

			/*
			 * Non-optimizable statements
176
			 */
177 178 179 180
		case T_CreateStmt:
			result = transformCreateStmt(pstate, (CreateStmt *) parseTree);
			break;

181 182 183
		case T_IndexStmt:
			result = transformIndexStmt(pstate, (IndexStmt *) parseTree);
			break;
184

185 186 187
		case T_RuleStmt:
			result = transformRuleStmt(pstate, (RuleStmt *) parseTree);
			break;
188

189 190 191
		case T_ViewStmt:
			{
				ViewStmt   *n = (ViewStmt *) parseTree;
192

193
				n->query = transformStmt(pstate, (Node *) n->query);
194

195 196 197 198
				/*
				 * If a list of column names was given, run through and
				 * insert these into the actual query tree. - thomas
				 * 2000-03-08
199 200 201
				 *
				 * Outer loop is over targetlist to make it easier to
				 * skip junk targetlist entries.
202 203 204
				 */
				if (n->aliases != NIL)
				{
205 206
					List	   *aliaslist = n->aliases;
					List	   *targetList;
207

208
					foreach(targetList, n->query->targetList)
209
					{
210
						TargetEntry *te = (TargetEntry *) lfirst(targetList);
211
						Resdom	   *rd;
212
						Ident	   *id;
213

214
						Assert(IsA(te, TargetEntry));
215
						rd = te->resdom;
216
						Assert(IsA(rd, Resdom));
217 218 219 220
						if (rd->resjunk) /* junk columns don't get aliases */
							continue;
						id = (Ident *) lfirst(aliaslist);
						Assert(IsA(id, Ident));
221
						rd->resname = pstrdup(id->name);
222 223 224
						aliaslist = lnext(aliaslist);
						if (aliaslist == NIL)
							break; /* done assigning aliases */
225
					}
226 227 228

					if (aliaslist != NIL)
						elog(ERROR, "CREATE VIEW specifies more column names than columns");
229
				}
230 231 232 233 234
				result = makeNode(Query);
				result->commandType = CMD_UTILITY;
				result->utilityStmt = (Node *) n;
			}
			break;
235

236 237 238
		case T_ExplainStmt:
			{
				ExplainStmt *n = (ExplainStmt *) parseTree;
239

240 241 242 243 244 245
				result = makeNode(Query);
				result->commandType = CMD_UTILITY;
				n->query = transformStmt(pstate, (Node *) n->query);
				result->utilityStmt = (Node *) parseTree;
			}
			break;
246

247
		case T_AlterTableStmt:
248
			result = transformAlterTableStmt(pstate, (AlterTableStmt *) parseTree);
249 250
			break;

251 252
			/*
			 * Optimizable statements
253
			 */
Bruce Momjian's avatar
Bruce Momjian committed
254 255
		case T_InsertStmt:
			result = transformInsertStmt(pstate, (InsertStmt *) parseTree);
256
			break;
257

258 259 260
		case T_DeleteStmt:
			result = transformDeleteStmt(pstate, (DeleteStmt *) parseTree);
			break;
261

Bruce Momjian's avatar
Bruce Momjian committed
262 263
		case T_UpdateStmt:
			result = transformUpdateStmt(pstate, (UpdateStmt *) parseTree);
264
			break;
265

Bruce Momjian's avatar
Bruce Momjian committed
266
		case T_SelectStmt:
267 268 269 270 271
			if (((SelectStmt *) parseTree)->op == SETOP_NONE)
				result = transformSelectStmt(pstate,
											 (SelectStmt *) parseTree);
			else
				result = transformSetOperationStmt(pstate,
272
											   (SelectStmt *) parseTree);
273
			break;
274

275 276 277 278 279 280 281 282 283 284 285
			/*
			 * Convert use of %TYPE in statements where it is permitted.
			 */
		case T_ProcedureStmt:
		case T_CommentStmt:
		case T_RemoveFuncStmt:
		case T_DefineStmt:
			result = makeNode(Query);
			result->commandType = CMD_UTILITY;
			result->utilityStmt = transformTypeRefs(pstate, parseTree);
			break;
286

287
		default:
288

289
			/*
290
			 * other statements don't require any transformation-- just
Bruce Momjian's avatar
Bruce Momjian committed
291
			 * return the original parsetree, yea!
292 293 294 295 296
			 */
			result = makeNode(Query);
			result->commandType = CMD_UTILITY;
			result->utilityStmt = (Node *) parseTree;
			break;
297 298
	}
	return result;
299 300 301 302
}

/*
 * transformDeleteStmt -
303
 *	  transforms a Delete Statement
304
 */
305
static Query *
306
transformDeleteStmt(ParseState *pstate, DeleteStmt *stmt)
307
{
308
	Query	   *qry = makeNode(Query);
309
	Node	   *qual;
310

311
	qry->commandType = CMD_DELETE;
312

313 314 315 316
	/* set up range table with just the result rel */
	qry->resultRelation = setTargetTable(pstate, stmt->relname,
										 interpretInhOption(stmt->inhOpt),
										 true);
317

318
	qry->distinctClause = NIL;
319

320
	/* fix where clause */
321
	qual = transformWhereClause(pstate, stmt->whereClause);
322

323
	/* done building the range table and jointree */
324
	qry->rtable = pstate->p_rtable;
325
	qry->jointree = makeFromExpr(pstate->p_joinlist, qual);
326

327
	qry->hasSubLinks = pstate->p_hasSubLinks;
Bruce Momjian's avatar
Bruce Momjian committed
328
	qry->hasAggs = pstate->p_hasAggs;
329
	if (pstate->p_hasAggs)
330
		parseCheckAggregates(pstate, qry, qual);
331

332
	return qry;
333 334 335 336
}

/*
 * transformInsertStmt -
337
 *	  transform an Insert Statement
338
 */
339
static Query *
Bruce Momjian's avatar
Bruce Momjian committed
340
transformInsertStmt(ParseState *pstate, InsertStmt *stmt)
341
{
342
	Query	   *qry = makeNode(Query);
343 344
	List	   *sub_rtable;
	List	   *sub_namespace;
345
	List	   *icolumns;
346 347 348
	List	   *attrnos;
	List	   *attnos;
	int			numuseratts;
349 350
	List	   *tl;
	TupleDesc	rd_att;
351

352 353
	qry->commandType = CMD_INSERT;
	pstate->p_is_insert = true;
354

355
	/*
356 357
	 * If a non-nil rangetable/namespace was passed in, and we are doing
	 * INSERT/SELECT, arrange to pass the rangetable/namespace down to the
358 359
	 * SELECT.	This can only happen if we are inside a CREATE RULE, and
	 * in that case we want the rule's OLD and NEW rtable entries to
360
	 * appear as part of the SELECT's rtable, not as outer references for
361 362
	 * it.	(Kluge!)  The SELECT's joinlist is not affected however. We
	 * must do this before adding the target table to the INSERT's rtable.
363 364 365 366 367 368 369 370 371 372 373 374 375 376 377 378
	 */
	if (stmt->selectStmt)
	{
		sub_rtable = pstate->p_rtable;
		pstate->p_rtable = NIL;
		sub_namespace = pstate->p_namespace;
		pstate->p_namespace = NIL;
	}
	else
	{
		sub_rtable = NIL;		/* not used, but keep compiler quiet */
		sub_namespace = NIL;
	}

	/*
	 * Must get write lock on INSERT target table before scanning SELECT,
379
	 * else we will grab the wrong kind of initial lock if the target
380
	 * table is also mentioned in the SELECT part.	Note that the target
381
	 * table is not added to the joinlist or namespace.
382
	 */
383 384
	qry->resultRelation = setTargetTable(pstate, stmt->relname,
										 false, false);
385

386
	/*
387
	 * Is it INSERT ... SELECT or INSERT ... VALUES?
Bruce Momjian's avatar
Bruce Momjian committed
388
	 */
389 390
	if (stmt->selectStmt)
	{
391
		ParseState *sub_pstate = make_parsestate(pstate->parentParseState);
392
		Query	   *selectQuery;
393 394
		RangeTblEntry *rte;
		RangeTblRef *rtr;
Bruce Momjian's avatar
Bruce Momjian committed
395

396 397 398
		/*
		 * Process the source SELECT.
		 *
399 400 401 402
		 * It is important that this be handled just like a standalone
		 * SELECT; otherwise the behavior of SELECT within INSERT might be
		 * different from a stand-alone SELECT. (Indeed, Postgres up
		 * through 6.5 had bugs of just that nature...)
403
		 */
404 405 406
		sub_pstate->p_rtable = sub_rtable;
		sub_pstate->p_namespace = sub_namespace;

407
		selectQuery = transformStmt(sub_pstate, stmt->selectStmt);
408

409 410
		release_pstate_resources(sub_pstate);
		pfree(sub_pstate);
411 412 413 414 415

		Assert(IsA(selectQuery, Query));
		Assert(selectQuery->commandType == CMD_SELECT);
		if (selectQuery->into || selectQuery->isPortal)
			elog(ERROR, "INSERT ... SELECT may not specify INTO");
416

417
		/*
418 419
		 * Make the source be a subquery in the INSERT's rangetable, and
		 * add it to the INSERT's joinlist.
420 421 422 423 424 425 426 427 428 429
		 */
		rte = addRangeTableEntryForSubquery(pstate,
											selectQuery,
											makeAttr("*SELECT*", NULL),
											true);
		rtr = makeNode(RangeTblRef);
		/* assume new rte is at end */
		rtr->rtindex = length(pstate->p_rtable);
		Assert(rte == rt_fetch(rtr->rtindex, pstate->p_rtable));
		pstate->p_joinlist = lappend(pstate->p_joinlist, rtr);
430

431
		/*
432 433 434 435
		 * Generate a targetlist for the INSERT that selects all the
		 * non-resjunk columns from the subquery.  (We need this to be
		 * separate from the subquery's tlist because we may add columns,
		 * insert datatype coercions, etc.)
436 437
		 *
		 * HACK: constants in the INSERT's targetlist are copied up as-is
438 439 440 441 442
		 * rather than being referenced as subquery outputs.  This is
		 * mainly to ensure that when we try to coerce them to the target
		 * column's datatype, the right things happen for UNKNOWN
		 * constants. Otherwise this fails: INSERT INTO foo SELECT 'bar',
		 * ... FROM baz
443 444 445 446 447 448 449 450 451 452 453 454 455 456 457 458 459 460 461 462 463 464 465 466 467 468
		 */
		qry->targetList = NIL;
		foreach(tl, selectQuery->targetList)
		{
			TargetEntry *tle = (TargetEntry *) lfirst(tl);
			Resdom	   *resnode = tle->resdom;
			Node	   *expr;

			if (resnode->resjunk)
				continue;
			if (tle->expr && IsA(tle->expr, Const))
				expr = tle->expr;
			else
				expr = (Node *) makeVar(rtr->rtindex,
										resnode->resno,
										resnode->restype,
										resnode->restypmod,
										0);
			resnode = copyObject(resnode);
			resnode->resno = (AttrNumber) pstate->p_last_resno++;
			qry->targetList = lappend(qry->targetList,
									  makeTargetEntry(resnode, expr));
		}
	}
	else
	{
469

470
		/*
471 472
		 * For INSERT ... VALUES, transform the given list of values to
		 * form a targetlist for the INSERT.
473 474 475
		 */
		qry->targetList = transformTargetList(pstate, stmt->targetList);
	}
476

477
	/*
478 479 480 481 482 483 484 485 486
	 * Now we are done with SELECT-like processing, and can get on with
	 * transforming the target list to match the INSERT target columns.
	 */

	/* Prepare to assign non-conflicting resnos to resjunk attributes */
	if (pstate->p_last_resno <= pstate->p_target_relation->rd_rel->relnatts)
		pstate->p_last_resno = pstate->p_target_relation->rd_rel->relnatts + 1;

	/* Validate stmt->cols list, or build default list if no list given */
487
	icolumns = checkInsertTargets(pstate, stmt->cols, &attrnos);
488

489 490 491
	/*
	 * Prepare columns for assignment to target table.
	 */
492 493
	numuseratts = 0;
	attnos = attrnos;
494 495 496 497 498
	foreach(tl, qry->targetList)
	{
		TargetEntry *tle = (TargetEntry *) lfirst(tl);
		Ident	   *id;

499
		Assert(!tle->resdom->resjunk);
500
		if (icolumns == NIL || attnos == NIL)
501 502
			elog(ERROR, "INSERT has more expressions than target columns");
		id = (Ident *) lfirst(icolumns);
503 504 505
		updateTargetListEntry(pstate, tle, id->name, lfirsti(attnos),
							  id->indirection);
		numuseratts++;
506
		icolumns = lnext(icolumns);
507
		attnos = lnext(attnos);
508 509
	}

510 511 512
	/*
	 * It is possible that the targetlist has fewer entries than were in
	 * the columns list.  We do not consider this an error (perhaps we
513 514 515
	 * should, if the columns list was explictly given?).  We must
	 * truncate the attrnos list to only include the attrs actually
	 * provided, else we will fail to apply defaults for them below.
516 517 518 519
	 */
	if (icolumns != NIL)
		attrnos = ltruncate(numuseratts, attrnos);

520 521 522
	/*
	 * Add targetlist items to assign DEFAULT values to any columns that
	 * have defaults and were not assigned to by the user.
523
	 *
524
	 * XXX wouldn't it make more sense to do this further downstream, after
525 526
	 * the rule rewriter?  As is, altering a column default will not
	 * change the behavior of INSERTs in already-defined rules.
527
	 */
528 529
	rd_att = pstate->p_target_relation->rd_att;
	if (rd_att->constr && rd_att->constr->num_defval > 0)
530
	{
531 532 533 534
		Form_pg_attribute *att = rd_att->attrs;
		AttrDefault *defval = rd_att->constr->defval;
		int			ndef = rd_att->constr->num_defval;

535
		while (--ndef >= 0)
536
		{
537
			AttrNumber	attrno = defval[ndef].adnum;
538
			Form_pg_attribute thisatt = att[attrno - 1];
539
			TargetEntry *te;
540

541 542
			if (intMember((int) attrno, attrnos))
				continue;		/* there was a user-specified value */
543

544
			/*
545 546
			 * No user-supplied value, so add a targetentry with DEFAULT
			 * expr and correct data for the target column.
547
			 */
548
			te = makeTargetEntry(makeResdom(attrno,
549 550
											thisatt->atttypid,
											thisatt->atttypmod,
551
											pstrdup(NameStr(thisatt->attname)),
552
											false),
553
								 stringToNode(defval[ndef].adbin));
554
			qry->targetList = lappend(qry->targetList, te);
555

556 557 558 559
			/*
			 * Make sure the value is coerced to the target column type
			 * (might not be right type if it's not a constant!)
			 */
560 561
			updateTargetListEntry(pstate, te, te->resdom->resname, attrno,
								  NIL);
562
		}
563
	}
564

565 566 567
	/* done building the range table and jointree */
	qry->rtable = pstate->p_rtable;
	qry->jointree = makeFromExpr(pstate->p_joinlist, NULL);
568

569
	qry->hasSubLinks = pstate->p_hasSubLinks;
570 571 572
	qry->hasAggs = pstate->p_hasAggs;
	if (pstate->p_hasAggs)
		parseCheckAggregates(pstate, qry, NULL);
573

574
	return qry;
575 576
}

Bruce Momjian's avatar
Bruce Momjian committed
577
/*
578 579 580 581 582
 *	makeObjectName()
 *
 *	Create a name for an implicitly created index, sequence, constraint, etc.
 *
 *	The parameters are: the original table name, the original field name, and
583
 *	a "type" string (such as "seq" or "pkey").	The field name and/or type
584 585 586 587 588 589 590
 *	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
591
 *	both names if necessary to make a short-enough string.	The type part
592 593 594 595
 *	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
596
 *	from the truncated characters.	Currently it seems best to keep it simple,
597
 *	so that the generated names are easily predictable by a person.
598
 */
599
char *
600
makeObjectName(char *name1, char *name2, char *typename)
601
{
602
	char	   *name;
603 604 605 606 607 608 609 610
	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)
611
	{
612 613 614 615 616 617 618
		name2chars = strlen(name2);
		overhead++;				/* allow for separating underscore */
	}
	else
		name2chars = 0;
	if (typename)
		overhead += strlen(typename) + 1;
619

620
	availchars = NAMEDATALEN - 1 - overhead;
621

622 623 624
	/*
	 * If we must truncate,  preferentially truncate the longer name. This
	 * logic could be expressed without a loop, but it's simple and
625 626 627 628 629 630 631 632
	 * obvious as a loop.
	 */
	while (name1chars + name2chars > availchars)
	{
		if (name1chars > name2chars)
			name1chars--;
		else
			name2chars--;
633 634
	}

635 636 637 638 639 640 641
#ifdef MULTIBYTE
	if (name1)
		name1chars = pg_mbcliplen(name1, name1chars, name1chars);
	if (name2)
		name2chars = pg_mbcliplen(name2, name2chars, name2chars);
#endif

642 643 644 645 646 647 648
	/* Now construct the string using the chosen lengths */
	name = palloc(name1chars + name2chars + overhead + 1);
	strncpy(name, name1, name1chars);
	ndx = name1chars;
	if (name2)
	{
		name[ndx++] = '_';
649
		strncpy(name + ndx, name2, name2chars);
650 651 652 653 654
		ndx += name2chars;
	}
	if (typename)
	{
		name[ndx++] = '_';
655
		strcpy(name + ndx, typename);
656 657 658
	}
	else
		name[ndx] = '\0';
659

660
	return name;
Bruce Momjian's avatar
Bruce Momjian committed
661
}
662

Bruce Momjian's avatar
Bruce Momjian committed
663
static char *
664 665
CreateIndexName(char *table_name, char *column_name,
				char *label, List *indices)
666 667 668 669
{
	int			pass = 0;
	char	   *iname = NULL;
	List	   *ilist;
670 671
	char		typename[NAMEDATALEN];

672 673
	/*
	 * The type name for makeObjectName is label, or labelN if that's
674 675
	 * necessary to prevent collisions among multiple indexes for the same
	 * table.  Note there is no check for collisions with already-existing
676 677
	 * indexes, only among the indexes we're about to create now; this
	 * ought to be improved someday.
678 679
	 */
	strcpy(typename, label);
680

681
	for (;;)
682
	{
683
		iname = makeObjectName(table_name, column_name, typename);
684

685
		foreach(ilist, indices)
686
		{
687
			IndexStmt  *index = lfirst(ilist);
688

689 690
			if (index->idxname != NULL &&
				strcmp(iname, index->idxname) == 0)
691 692 693 694 695 696
				break;
		}
		/* ran through entire list? then no name conflict found so done */
		if (ilist == NIL)
			break;

697
		/* found a conflict, so try a new name component */
698
		pfree(iname);
699
		sprintf(typename, "%s%d", label, ++pass);
700 701
	}

702
	return iname;
Bruce Momjian's avatar
Bruce Momjian committed
703
}
704

705 706 707 708 709 710 711 712 713 714 715 716
/*
 * 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)
{
717
	CreateStmtContext cxt;
718 719
	Query	   *q;
	List	   *elements;
720

721 722 723 724
	cxt.stmtType = "CREATE TABLE";
	cxt.relname = stmt->relname;
	cxt.inhRelnames = stmt->inhRelnames;
	cxt.istemp = stmt->istemp;
725
	cxt.hasoids = stmt->hasoids;
726 727 728 729 730 731 732 733
	cxt.relOid = InvalidOid;
	cxt.columns = NIL;
	cxt.ckconstraints = NIL;
	cxt.fkconstraints = NIL;
	cxt.ixconstraints = NIL;
	cxt.blist = NIL;
	cxt.alist = NIL;
	cxt.pkey = NULL;
734

735
	/*
736 737
	 * Run through each primary element in the table creation clause.
	 * Separate column defs from constraints, and do preliminary analysis.
738
	 */
739
	foreach(elements, stmt->tableElts)
740
	{
741 742
		Node	   *element = lfirst(elements);

743 744 745
		switch (nodeTag(element))
		{
			case T_ColumnDef:
746 747 748
				transformColumnDefinition(pstate, &cxt,
										  (ColumnDef *) element);
				break;
749

750 751 752 753
			case T_Constraint:
				transformTableConstraint(pstate, &cxt,
										 (Constraint *) element);
				break;
754

755 756 757 758
			case T_FkConstraint:
				/* No pre-transformation needed */
				cxt.fkconstraints = lappend(cxt.fkconstraints, element);
				break;
759

760 761 762 763
			default:
				elog(ERROR, "parser: unrecognized node (internal error)");
		}
	}
764

765
	Assert(stmt->constraints == NIL);
766

767 768 769 770
	/*
	 * Postprocess constraints that give rise to index definitions.
	 */
	transformIndexConstraints(pstate, &cxt);
771

772 773 774 775 776 777 778 779 780 781 782 783 784 785 786
	/*
	 * Postprocess foreign-key constraints.
	 */
	transformFKConstraints(pstate, &cxt);

	/*
	 * Output results.
	 */
	q = makeNode(Query);
	q->commandType = CMD_UTILITY;
	q->utilityStmt = (Node *) stmt;
	stmt->tableElts = cxt.columns;
	stmt->constraints = cxt.ckconstraints;
	extras_before = cxt.blist;
	extras_after = cxt.alist;
787

788 789
	return q;
}
790

791 792 793 794 795 796 797 798 799
static void
transformColumnDefinition(ParseState *pstate, CreateStmtContext *cxt,
						  ColumnDef *column)
{
	bool		is_serial;
	bool		saw_nullable;
	Constraint *constraint;
	List	   *clist;
	Ident	   *key;
800

801
	cxt->columns = lappend(cxt->columns, column);
802

803 804 805 806 807 808 809 810 811 812 813 814 815 816
	/* Check for SERIAL pseudo-types */
	is_serial = false;
	if (strcmp(column->typename->name, "serial") == 0 ||
		strcmp(column->typename->name, "serial4") == 0)
	{
		is_serial = true;
		column->typename->name = pstrdup("int4");
	}
	else if (strcmp(column->typename->name, "bigserial") == 0 ||
			 strcmp(column->typename->name, "serial8") == 0)
	{
		is_serial = true;
		column->typename->name = pstrdup("int8");
	}
817

818 819
	/* Do necessary work on the column type declaration */
	transformColumnType(pstate, column);
Jan Wieck's avatar
Jan Wieck committed
820

821 822 823 824 825 826 827 828
	/* Special actions for SERIAL pseudo-types */
	if (is_serial)
	{
		char	   *sname;
		char	   *qstring;
		A_Const    *snamenode;
		FuncCall   *funccallnode;
		CreateSeqStmt *sequence;
829

830 831 832 833 834 835 836
		/*
		 * Create appropriate constraints for SERIAL.  We do
		 * this in full, rather than shortcutting, so that we
		 * will detect any conflicting constraints the user
		 * wrote (like a different DEFAULT).
		 */
		sname = makeObjectName(cxt->relname, column->colname, "seq");
Jan Wieck's avatar
Jan Wieck committed
837

838 839 840 841 842 843 844 845 846 847 848 849 850 851 852 853 854 855 856 857 858 859 860 861 862 863 864 865 866 867 868
		/*
		 * Create an expression tree representing the function
		 * call  nextval('"sequencename"')
		 */
		qstring = palloc(strlen(sname) + 2 + 1);
		sprintf(qstring, "\"%s\"", sname);
		snamenode = makeNode(A_Const);
		snamenode->val.type = T_String;
		snamenode->val.val.str = qstring;
		funccallnode = makeNode(FuncCall);
		funccallnode->funcname = "nextval";
		funccallnode->args = makeList1(snamenode);
		funccallnode->agg_star = false;
		funccallnode->agg_distinct = false;

		constraint = makeNode(Constraint);
		constraint->contype = CONSTR_DEFAULT;
		constraint->name = sname;
		constraint->raw_expr = (Node *) funccallnode;
		constraint->cooked_expr = NULL;
		constraint->keys = NIL;
		column->constraints = lappend(column->constraints, constraint);

		constraint = makeNode(Constraint);
		constraint->contype = CONSTR_UNIQUE;
		constraint->name = NULL;	/* assign later */
		column->constraints = lappend(column->constraints, constraint);

		constraint = makeNode(Constraint);
		constraint->contype = CONSTR_NOTNULL;
		column->constraints = lappend(column->constraints, constraint);
869

870 871 872 873 874 875 876 877 878
		/*
		 * Build a CREATE SEQUENCE command to create the
		 * sequence object, and add it to the list of things
		 * to be done before this CREATE/ALTER TABLE.
		 */
		sequence = makeNode(CreateSeqStmt);
		sequence->seqname = pstrdup(sname);
		sequence->istemp = cxt->istemp;
		sequence->options = NIL;
Jan Wieck's avatar
Jan Wieck committed
879

880 881
		elog(NOTICE, "%s will create implicit sequence '%s' for SERIAL column '%s.%s'",
			 cxt->stmtType, sequence->seqname, cxt->relname, column->colname);
882

883 884
		cxt->blist = lappend(cxt->blist, sequence);
	}
885

886 887
	/* Process column constraints, if any... */
	transformConstraintAttrs(column->constraints);
888

889
	saw_nullable = false;
890

891 892 893
	foreach(clist, column->constraints)
	{
		constraint = lfirst(clist);
894

895 896 897 898 899 900 901 902 903 904
		/*
		 * If this column constraint is a FOREIGN KEY
		 * constraint, then we fill in the current attributes
		 * name and throw it into the list of FK constraints
		 * to be processed later.
		 */
		if (IsA(constraint, FkConstraint))
		{
			FkConstraint *fkconstraint = (FkConstraint *) constraint;
			Ident	   *id = makeNode(Ident);
905

906 907 908
			id->name = column->colname;
			id->indirection = NIL;
			id->isRel = false;
909

910
			fkconstraint->fk_attrs = makeList1(id);
911

912 913 914
			cxt->fkconstraints = lappend(cxt->fkconstraints, fkconstraint);
			continue;
		}
915

916
		Assert(IsA(constraint, Constraint));
917

918 919 920 921 922 923 924 925 926
		switch (constraint->contype)
		{
			case CONSTR_NULL:
				if (saw_nullable && column->is_not_null)
					elog(ERROR, "%s/(NOT) NULL conflicting declaration for '%s.%s'",
						 cxt->stmtType, cxt->relname, column->colname);
				column->is_not_null = FALSE;
				saw_nullable = true;
				break;
927

928 929 930 931 932 933 934
			case CONSTR_NOTNULL:
				if (saw_nullable && !column->is_not_null)
					elog(ERROR, "%s/(NOT) NULL conflicting declaration for '%s.%s'",
						 cxt->stmtType, cxt->relname, column->colname);
				column->is_not_null = TRUE;
				saw_nullable = true;
				break;
935

936 937 938 939 940 941 942 943 944 945 946 947 948 949 950 951 952 953
			case CONSTR_DEFAULT:
				if (column->raw_default != NULL)
					elog(ERROR, "%s/DEFAULT multiple values specified for '%s.%s'",
						 cxt->stmtType, cxt->relname, column->colname);
				column->raw_default = constraint->raw_expr;
				Assert(constraint->cooked_expr == NULL);
				break;

			case CONSTR_PRIMARY:
				if (constraint->name == NULL)
					constraint->name = makeObjectName(cxt->relname,
													  NULL,
													  "pkey");
				if (constraint->keys == NIL)
				{
					key = makeNode(Ident);
					key->name = pstrdup(column->colname);
					constraint->keys = makeList1(key);
954
				}
955
				cxt->ixconstraints = lappend(cxt->ixconstraints, constraint);
956 957
				break;

958 959 960 961 962 963 964 965 966 967 968 969 970
			case CONSTR_UNIQUE:
				if (constraint->name == NULL)
					constraint->name = makeObjectName(cxt->relname,
													  column->colname,
													  "key");
				if (constraint->keys == NIL)
				{
					key = makeNode(Ident);
					key->name = pstrdup(column->colname);
					constraint->keys = makeList1(key);
				}
				cxt->ixconstraints = lappend(cxt->ixconstraints, constraint);
				break;
971

972 973 974 975 976 977 978 979 980 981 982 983 984
			case CONSTR_CHECK:
				if (constraint->name == NULL)
					constraint->name = makeObjectName(cxt->relname,
													  column->colname,
													  NULL);
				cxt->ckconstraints = lappend(cxt->ckconstraints, constraint);
				break;

			case CONSTR_ATTR_DEFERRABLE:
			case CONSTR_ATTR_NOT_DEFERRABLE:
			case CONSTR_ATTR_DEFERRED:
			case CONSTR_ATTR_IMMEDIATE:
				/* transformConstraintAttrs took care of these */
Jan Wieck's avatar
Jan Wieck committed
985 986
				break;

987
			default:
988 989
				elog(ERROR, "parser: unrecognized constraint (internal error)");
				break;
990 991
		}
	}
992
}
993

994 995 996 997 998 999 1000 1001 1002 1003 1004 1005 1006
static void
transformTableConstraint(ParseState *pstate, CreateStmtContext *cxt,
						 Constraint *constraint)
{
	switch (constraint->contype)
	{
		case CONSTR_PRIMARY:
			if (constraint->name == NULL)
				constraint->name = makeObjectName(cxt->relname,
												  NULL,
												  "pkey");
			cxt->ixconstraints = lappend(cxt->ixconstraints, constraint);
			break;
1007

1008 1009 1010 1011 1012 1013 1014 1015 1016 1017 1018 1019 1020 1021 1022 1023 1024 1025 1026 1027 1028 1029 1030 1031 1032 1033 1034 1035 1036 1037 1038 1039 1040 1041 1042 1043 1044 1045 1046 1047 1048 1049
		case CONSTR_UNIQUE:
			cxt->ixconstraints = lappend(cxt->ixconstraints, constraint);
			break;

		case CONSTR_CHECK:
			cxt->ckconstraints = lappend(cxt->ckconstraints, constraint);
			break;

		case CONSTR_NULL:
		case CONSTR_NOTNULL:
		case CONSTR_DEFAULT:
		case CONSTR_ATTR_DEFERRABLE:
		case CONSTR_ATTR_NOT_DEFERRABLE:
		case CONSTR_ATTR_DEFERRED:
		case CONSTR_ATTR_IMMEDIATE:
			elog(ERROR, "parser: illegal context for constraint (internal error)");
			break;

		default:
			elog(ERROR, "parser: unrecognized constraint (internal error)");
			break;
	}
}

static void
transformIndexConstraints(ParseState *pstate, CreateStmtContext *cxt)
{
	List	   *listptr;
	List	   *keys;
	IndexStmt  *index;
	IndexElem  *iparam;
	ColumnDef  *column;
	List	   *columns;
	List	   *indexlist = NIL;

	/*
	 * Run through the constraints that need to generate an index.
	 * For PRIMARY KEY, mark each column as NOT NULL and create an index.
	 * For UNIQUE, create an index as for PRIMARY KEY, but do not insist on
	 * NOT NULL.
	 */
	foreach(listptr, cxt->ixconstraints)
1050
	{
1051 1052
		Constraint *constraint = lfirst(listptr);

1053
		Assert(IsA(constraint, Constraint));
1054
		Assert((constraint->contype == CONSTR_PRIMARY)
Bruce Momjian's avatar
Bruce Momjian committed
1055
			   || (constraint->contype == CONSTR_UNIQUE));
1056

1057 1058
		index = makeNode(IndexStmt);

1059 1060
		index->unique = true;
		index->primary = (constraint->contype == CONSTR_PRIMARY);
1061
		if (index->primary)
1062
		{
1063 1064 1065 1066 1067 1068 1069 1070
			/* In ALTER TABLE case, a primary index might already exist */
			if (cxt->pkey != NULL ||
				(OidIsValid(cxt->relOid) &&
				 relationHasPrimaryKey(cxt->relname)))
				elog(ERROR, "%s/PRIMARY KEY multiple primary keys"
					 " for table '%s' are not allowed",
					 cxt->stmtType, cxt->relname);
			cxt->pkey = index;
1071
		}
1072

1073
		if (constraint->name != NULL)
1074
			index->idxname = pstrdup(constraint->name);
1075
		else if (constraint->contype == CONSTR_PRIMARY)
1076
			index->idxname = makeObjectName(cxt->relname, NULL, "pkey");
1077
		else
1078
			index->idxname = NULL;		/* will set it later */
1079

1080
		index->relname = cxt->relname;
1081 1082 1083
		index->accessMethod = "btree";
		index->indexParams = NIL;
		index->whereClause = NULL;
1084

1085 1086 1087 1088
		/*
		 * Make sure referenced keys exist.  If we are making a
		 * PRIMARY KEY index, also make sure they are NOT NULL.
		 */
1089
		foreach(keys, constraint->keys)
1090
		{
1091
			Ident	   *key = (Ident *) lfirst(keys);
1092
			bool		found = false;
1093

1094
			Assert(IsA(key, Ident));
1095
			column = NULL;
1096
			foreach(columns, cxt->columns)
1097 1098
			{
				column = lfirst(columns);
1099 1100
				Assert(IsA(column, ColumnDef));
				if (strcmp(column->colname, key->name) == 0)
1101 1102
				{
					found = true;
1103
					break;
1104
				}
1105
			}
1106 1107 1108 1109 1110 1111
			if (found)
			{
				/* found column in the new table; force it to be NOT NULL */
				if (constraint->contype == CONSTR_PRIMARY)
					column->is_not_null = TRUE;
			}
1112 1113 1114 1115 1116 1117 1118 1119 1120
			else if (SystemAttributeByName(key->name, cxt->hasoids) != NULL)
			{
				/*
				 * column will be a system column in the new table,
				 * so accept it.  System columns can't ever be null,
				 * so no need to worry about PRIMARY/NOT NULL constraint.
				 */
				found = true;
			}
1121
			else if (cxt->inhRelnames)
1122 1123
			{
				/* try inherited tables */
1124
				List	   *inher;
1125

1126
				foreach(inher, cxt->inhRelnames)
1127
				{
1128 1129 1130
					Value	   *inh = lfirst(inher);
					Relation	rel;
					int			count;
1131 1132

					Assert(IsA(inh, String));
1133
					rel = heap_openr(strVal(inh), AccessShareLock);
1134 1135
					if (rel->rd_rel->relkind != RELKIND_RELATION)
						elog(ERROR, "inherited table \"%s\" is not a relation",
1136
							 strVal(inh));
1137 1138 1139
					for (count = 0; count < rel->rd_att->natts; count++)
					{
						Form_pg_attribute inhattr = rel->rd_att->attrs[count];
1140
						char	   *inhname = NameStr(inhattr->attname);
1141 1142 1143 1144

						if (strcmp(key->name, inhname) == 0)
						{
							found = true;
1145

1146
							/*
1147 1148 1149 1150 1151 1152 1153 1154 1155 1156 1157 1158
							 * If the column is inherited, we currently
							 * have no easy way to force it to be NOT
							 * NULL. Only way I can see to fix this would
							 * be to convert the inherited-column info to
							 * ColumnDef nodes before we reach this point,
							 * and then create the table from those nodes
							 * rather than referencing the parent tables
							 * later.  That would likely be cleaner, but
							 * too much work to contemplate right now.
							 * Instead, raise an error if the inherited
							 * column won't be NOT NULL. (Would a NOTICE
							 * be more reasonable?)
1159
							 */
1160
							if (constraint->contype == CONSTR_PRIMARY &&
1161
								!inhattr->attnotnull)
1162 1163
								elog(ERROR, "inherited attribute \"%s\" cannot be a PRIMARY KEY because it is not marked NOT NULL",
									 inhname);
1164 1165 1166 1167 1168 1169 1170 1171
							break;
						}
					}
					heap_close(rel, NoLock);
					if (found)
						break;
				}
			}
1172 1173 1174 1175 1176 1177 1178 1179 1180 1181 1182 1183 1184 1185 1186 1187 1188 1189 1190 1191 1192 1193 1194
			else if (OidIsValid(cxt->relOid))
			{
				/* ALTER TABLE case: does column already exist? */
				HeapTuple	atttuple;

				atttuple = SearchSysCache(ATTNAME,
										  ObjectIdGetDatum(cxt->relOid),
										  PointerGetDatum(key->name),
										  0, 0);
				if (HeapTupleIsValid(atttuple))
				{
					found = true;
					/*
					 * We require pre-existing column to be already marked
					 * NOT NULL.
					 */
					if (constraint->contype == CONSTR_PRIMARY &&
						!((Form_pg_attribute) GETSTRUCT(atttuple))->attnotnull)
						elog(ERROR, "Existing attribute \"%s\" cannot be a PRIMARY KEY because it is not marked NOT NULL",
							 key->name);
					ReleaseSysCache(atttuple);
				}
			}
1195 1196

			if (!found)
1197 1198
				elog(ERROR, "%s: column \"%s\" named in key does not exist",
					 cxt->stmtType, key->name);
1199

1200 1201 1202 1203 1204
			/* Check for PRIMARY KEY(foo, foo) */
			foreach(columns, index->indexParams)
			{
				iparam = (IndexElem *) lfirst(columns);
				if (strcmp(key->name, iparam->name) == 0)
1205 1206
					elog(ERROR, "%s: column \"%s\" appears twice in %s constraint",
						 cxt->stmtType, key->name,
1207 1208 1209 1210
						 index->primary ? "PRIMARY KEY" : "UNIQUE");
			}

			/* OK, add it to the index definition */
1211
			iparam = makeNode(IndexElem);
1212
			iparam->name = pstrdup(key->name);
1213 1214 1215 1216 1217
			iparam->args = NIL;
			iparam->class = NULL;
			index->indexParams = lappend(index->indexParams, iparam);
		}

1218
		indexlist = lappend(indexlist, index);
1219 1220
	}

1221 1222
	/*
	 * Scan the index list and remove any redundant index specifications.
1223 1224 1225 1226
	 * This can happen if, for instance, the user writes SERIAL PRIMARY
	 * KEY or SERIAL UNIQUE.  A strict reading of SQL92 would suggest
	 * raising an error instead, but that strikes me as too
	 * anal-retentive. - tgl 2001-02-14
1227 1228 1229
	 *
	 * XXX in ALTER TABLE case, it'd be nice to look for duplicate
	 * pre-existing indexes, too.
1230
	 */
1231 1232
	cxt->alist = NIL;
	if (cxt->pkey != NULL)
1233
	{
1234
		/* Make sure we keep the PKEY index in preference to others... */
1235
		cxt->alist = makeList1(cxt->pkey);
1236
	}
1237
	while (indexlist != NIL)
1238
	{
1239
		index = lfirst(indexlist);
1240

1241 1242
		/* if it's pkey, it's already in cxt->alist */
		if (index != cxt->pkey)
1243 1244 1245
		{
			bool		keep = true;
			List	   *priorlist;
1246

1247
			foreach(priorlist, cxt->alist)
1248
			{
1249
				IndexStmt  *priorindex = lfirst(priorlist);
Bruce Momjian's avatar
Bruce Momjian committed
1250

1251 1252 1253 1254
				if (equal(index->indexParams, priorindex->indexParams))
				{
					/*
					 * If the prior index is as yet unnamed, and this one
1255 1256 1257 1258
					 * is named, then transfer the name to the prior
					 * index. This ensures that if we have named and
					 * unnamed constraints, we'll use (at least one of)
					 * the names for the index.
1259 1260 1261 1262 1263
					 */
					if (priorindex->idxname == NULL)
						priorindex->idxname = index->idxname;
					keep = false;
					break;
1264
				}
1265 1266 1267
			}

			if (keep)
1268
				cxt->alist = lappend(cxt->alist, index);
1269
		}
1270

1271
		indexlist = lnext(indexlist);
1272 1273
	}

1274 1275 1276
	/*
	 * Finally, select unique names for all not-previously-named indices,
	 * and display notice messages.
1277 1278 1279
	 *
	 * XXX in ALTER TABLE case, we fail to consider name collisions
	 * against pre-existing indexes.
1280
	 */
1281
	foreach(indexlist, cxt->alist)
1282
	{
1283
		index = lfirst(indexlist);
1284 1285 1286 1287

		if (index->idxname == NULL && index->indexParams != NIL)
		{
			iparam = lfirst(index->indexParams);
1288 1289
			index->idxname = CreateIndexName(cxt->relname, iparam->name,
											 "key", cxt->alist);
1290 1291
		}
		if (index->idxname == NULL)		/* should not happen */
1292 1293
			elog(ERROR, "%s: failed to make implicit index name",
				 cxt->stmtType);
1294

1295 1296 1297
		elog(NOTICE, "%s/%s will create implicit index '%s' for table '%s'",
			 cxt->stmtType, (index->primary ? "PRIMARY KEY" : "UNIQUE"),
			 index->idxname, cxt->relname);
1298
	}
1299
}
1300

1301 1302 1303 1304 1305 1306 1307 1308 1309 1310 1311 1312 1313 1314 1315
static void
transformFKConstraints(ParseState *pstate, CreateStmtContext *cxt)
{
	CreateTrigStmt *fk_trigger;
	List	   *fkactions = NIL;
	List	   *fkclist;
	List	   *fk_attr;
	List	   *pk_attr;
	Ident	   *id;
	Oid	   pktypoid[INDEX_MAX_KEYS];
	Oid	   fktypoid[INDEX_MAX_KEYS];
	int	   i;

	if (cxt->fkconstraints == NIL)
		return;
1316

1317 1318 1319 1320
	elog(NOTICE, "%s will create implicit trigger(s) for FOREIGN KEY check(s)",
		 cxt->stmtType);

	foreach(fkclist, cxt->fkconstraints)
Jan Wieck's avatar
Jan Wieck committed
1321
	{
1322 1323 1324
		FkConstraint *fkconstraint = (FkConstraint *) lfirst(fkclist);
		int	   attnum;
		List	   *fkattrs;
Jan Wieck's avatar
Jan Wieck committed
1325

1326 1327 1328 1329 1330
		/*
		 * If the constraint has no name, set it to <unnamed>
		 */
		if (fkconstraint->constr_name == NULL)
			fkconstraint->constr_name = "<unnamed>";
Jan Wieck's avatar
Jan Wieck committed
1331

1332 1333 1334 1335 1336 1337 1338 1339 1340
		for (attnum=0; attnum<INDEX_MAX_KEYS; attnum++)
			pktypoid[attnum] = fktypoid[attnum] = InvalidOid;

		/*
		 * Look up the referencing attributes to make sure they exist
		 * (or will exist) in this table, and remember their type OIDs.
		 */
		attnum = 0;
		foreach(fkattrs, fkconstraint->fk_attrs)
Jan Wieck's avatar
Jan Wieck committed
1341
		{
1342
			Ident	   *fkattr = lfirst(fkattrs);
Jan Wieck's avatar
Jan Wieck committed
1343

1344 1345 1346 1347 1348 1349
			if (attnum >= INDEX_MAX_KEYS)
				elog(ERROR, "Can only have %d keys in a foreign key",
					 INDEX_MAX_KEYS);
			fktypoid[attnum++] = transformFkeyGetColType(cxt,
														 fkattr->name);
		}
Jan Wieck's avatar
Jan Wieck committed
1350

1351 1352 1353 1354 1355 1356 1357 1358 1359
		/*
		 * If the attribute list for the referenced table was omitted,
		 * lookup the definition of the primary key.
		 */
		if (fkconstraint->pk_attrs == NIL)
		{
			if (strcmp(fkconstraint->pktable_name, cxt->relname) != 0)
				transformFkeyGetPrimaryKey(fkconstraint, pktypoid);
			else if (cxt->pkey != NULL)
1360
			{
1361 1362
				/* Use the to-be-created primary key */
				List	   *attr;
1363

1364 1365 1366 1367 1368 1369 1370 1371 1372 1373 1374 1375 1376 1377 1378 1379
				attnum=0;
				foreach(attr, cxt->pkey->indexParams)
				{
					IndexElem  *ielem = lfirst(attr);
					Ident	   *pkattr = (Ident *) makeNode(Ident);

					pkattr->name = pstrdup(ielem->name);
					pkattr->indirection = NIL;
					pkattr->isRel = false;
					fkconstraint->pk_attrs = lappend(fkconstraint->pk_attrs,
													 pkattr);
					if (attnum >= INDEX_MAX_KEYS)
						elog(ERROR, "Can only have %d keys in a foreign key",
							 INDEX_MAX_KEYS);
					pktypoid[attnum++] = transformFkeyGetColType(cxt,
																 ielem->name);
1380
				}
1381
			}
1382
			else
1383
			{
1384 1385
				/* In ALTER TABLE case, primary key may already exist */
				if (OidIsValid(cxt->relOid))
1386
					transformFkeyGetPrimaryKey(fkconstraint, pktypoid);
1387
				else
1388
					elog(ERROR, "PRIMARY KEY for referenced table \"%s\" not found",
1389
						 fkconstraint->pktable_name);
1390
			}
1391 1392 1393 1394 1395 1396
		}
		else
		{
			/* Validate the specified referenced key list */
			if (strcmp(fkconstraint->pktable_name, cxt->relname) != 0)
				transformFkeyCheckAttrs(fkconstraint, pktypoid);
1397 1398
			else
			{
1399 1400 1401 1402 1403
				/* Look for a matching new unique/primary constraint */
				List	   *index;
				bool		found = false;

				foreach(index, cxt->alist)
1404
				{
1405 1406
					IndexStmt  *ind = lfirst(index);
					List	   *pkattrs;
1407

1408 1409 1410 1411 1412 1413 1414
					if (!ind->unique)
						continue;
					if (length(ind->indexParams) !=
						length(fkconstraint->pk_attrs))
						continue;
					attnum=0;
					foreach(pkattrs, fkconstraint->pk_attrs)
1415
					{
1416
						Ident	   *pkattr = lfirst(pkattrs);
1417 1418
						List	   *indparms;

1419 1420
						found = false;
						foreach(indparms, ind->indexParams)
1421
						{
1422 1423 1424
							IndexElem  *indparm = lfirst(indparms);

							if (strcmp(indparm->name, pkattr->name) == 0)
1425
							{
1426 1427
								found = true;
								break;
1428 1429
							}
						}
1430
						if (!found)
1431
							break;
1432 1433 1434 1435 1436
						if (attnum >= INDEX_MAX_KEYS)
							elog(ERROR, "Can only have %d keys in a foreign key",
								 INDEX_MAX_KEYS);
						pktypoid[attnum++] = transformFkeyGetColType(cxt,
																	 pkattr->name);
1437
					}
1438 1439 1440 1441 1442 1443 1444 1445 1446
					if (found)
						break;
				}
				if (!found)
				{
					/* In ALTER TABLE case, such an index may already exist */
					if (OidIsValid(cxt->relOid))
						transformFkeyCheckAttrs(fkconstraint, pktypoid);
					else
1447 1448 1449 1450
						elog(ERROR, "UNIQUE constraint matching given keys for referenced table \"%s\" not found",
							 fkconstraint->pktable_name);
				}
			}
1451
		}
1452

1453 1454 1455
		/* Be sure referencing and referenced column types are comparable */
		for (i = 0; i < INDEX_MAX_KEYS && fktypoid[i] != 0; i++)
		{
Jan Wieck's avatar
Jan Wieck committed
1456
			/*
1457 1458 1459 1460
			 * fktypoid[i] is the foreign key table's i'th element's type oid
			 * pktypoid[i] is the primary key table's i'th element's type oid
			 * We let oper() do our work for us, including elog(ERROR) if the
			 * types don't compare with =
Jan Wieck's avatar
Jan Wieck committed
1461
			 */
1462 1463 1464 1465 1466 1467 1468 1469 1470 1471 1472 1473 1474 1475 1476 1477 1478 1479 1480 1481 1482 1483 1484 1485 1486 1487 1488 1489 1490 1491 1492 1493 1494 1495 1496
			Operator o=oper("=", fktypoid[i], pktypoid[i], false);
			ReleaseSysCache(o);
		}

		/*
		 * Build a CREATE CONSTRAINT TRIGGER statement for the CHECK
		 * action.
		 */
		fk_trigger = (CreateTrigStmt *) makeNode(CreateTrigStmt);
		fk_trigger->trigname = fkconstraint->constr_name;
		fk_trigger->relname = cxt->relname;
		fk_trigger->funcname = "RI_FKey_check_ins";
		fk_trigger->before = false;
		fk_trigger->row = true;
		fk_trigger->actions[0] = 'i';
		fk_trigger->actions[1] = 'u';
		fk_trigger->actions[2] = '\0';
		fk_trigger->lang = NULL;
		fk_trigger->text = NULL;

		fk_trigger->attr = NIL;
		fk_trigger->when = NULL;
		fk_trigger->isconstraint = true;
		fk_trigger->deferrable = fkconstraint->deferrable;
		fk_trigger->initdeferred = fkconstraint->initdeferred;
		fk_trigger->constrrelname = fkconstraint->pktable_name;

		fk_trigger->args = NIL;
		fk_trigger->args = lappend(fk_trigger->args,
								   makeString(fkconstraint->constr_name));
		fk_trigger->args = lappend(fk_trigger->args,
								   makeString(cxt->relname));
		fk_trigger->args = lappend(fk_trigger->args,
								   makeString(fkconstraint->pktable_name));
		fk_trigger->args = lappend(fk_trigger->args,
1497
								   makeString(fkconstraint->match_type));
1498 1499 1500 1501 1502 1503 1504 1505 1506 1507 1508 1509
		fk_attr = fkconstraint->fk_attrs;
		pk_attr = fkconstraint->pk_attrs;
		if (length(fk_attr) != length(pk_attr))
			elog(ERROR, "number of key attributes in referenced table must be equal to foreign key"
				 "\n\tIllegal FOREIGN KEY definition references \"%s\"",
				 fkconstraint->pktable_name);

		while (fk_attr != NIL)
		{
			id = (Ident *) lfirst(fk_attr);
			fk_trigger->args = lappend(fk_trigger->args,
									   makeString(id->name));
Jan Wieck's avatar
Jan Wieck committed
1510

1511 1512 1513
			id = (Ident *) lfirst(pk_attr);
			fk_trigger->args = lappend(fk_trigger->args,
									   makeString(id->name));
Jan Wieck's avatar
Jan Wieck committed
1514

1515 1516 1517
			fk_attr = lnext(fk_attr);
			pk_attr = lnext(pk_attr);
		}
Jan Wieck's avatar
Jan Wieck committed
1518

1519
		fkactions = lappend(fkactions, (Node *) fk_trigger);
Jan Wieck's avatar
Jan Wieck committed
1520

1521 1522 1523 1524 1525 1526 1527 1528 1529 1530 1531 1532 1533 1534 1535 1536 1537 1538 1539 1540 1541 1542 1543 1544 1545 1546 1547 1548 1549 1550 1551 1552 1553 1554 1555 1556 1557 1558 1559 1560 1561 1562 1563 1564
		/*
		 * Build a CREATE CONSTRAINT TRIGGER statement for the ON
		 * DELETE action fired on the PK table !!!
		 */
		fk_trigger = (CreateTrigStmt *) makeNode(CreateTrigStmt);
		fk_trigger->trigname = fkconstraint->constr_name;
		fk_trigger->relname = fkconstraint->pktable_name;
		fk_trigger->before = false;
		fk_trigger->row = true;
		fk_trigger->actions[0] = 'd';
		fk_trigger->actions[1] = '\0';
		fk_trigger->lang = NULL;
		fk_trigger->text = NULL;

		fk_trigger->attr = NIL;
		fk_trigger->when = NULL;
		fk_trigger->isconstraint = true;
		fk_trigger->deferrable = fkconstraint->deferrable;
		fk_trigger->initdeferred = fkconstraint->initdeferred;
		fk_trigger->constrrelname = cxt->relname;
		switch ((fkconstraint->actions & FKCONSTR_ON_DELETE_MASK)
				>> FKCONSTR_ON_DELETE_SHIFT)
		{
			case FKCONSTR_ON_KEY_NOACTION:
				fk_trigger->funcname = "RI_FKey_noaction_del";
				break;
			case FKCONSTR_ON_KEY_RESTRICT:
				fk_trigger->deferrable = false;
				fk_trigger->initdeferred = false;
				fk_trigger->funcname = "RI_FKey_restrict_del";
				break;
			case FKCONSTR_ON_KEY_CASCADE:
				fk_trigger->funcname = "RI_FKey_cascade_del";
				break;
			case FKCONSTR_ON_KEY_SETNULL:
				fk_trigger->funcname = "RI_FKey_setnull_del";
				break;
			case FKCONSTR_ON_KEY_SETDEFAULT:
				fk_trigger->funcname = "RI_FKey_setdefault_del";
				break;
			default:
				elog(ERROR, "Only one ON DELETE action can be specified for FOREIGN KEY constraint");
				break;
		}
Jan Wieck's avatar
Jan Wieck committed
1565

1566 1567 1568 1569 1570 1571 1572 1573
		fk_trigger->args = NIL;
		fk_trigger->args = lappend(fk_trigger->args,
								   makeString(fkconstraint->constr_name));
		fk_trigger->args = lappend(fk_trigger->args,
								   makeString(cxt->relname));
		fk_trigger->args = lappend(fk_trigger->args,
								   makeString(fkconstraint->pktable_name));
		fk_trigger->args = lappend(fk_trigger->args,
1574
								   makeString(fkconstraint->match_type));
1575 1576 1577 1578 1579 1580 1581
		fk_attr = fkconstraint->fk_attrs;
		pk_attr = fkconstraint->pk_attrs;
		while (fk_attr != NIL)
		{
			id = (Ident *) lfirst(fk_attr);
			fk_trigger->args = lappend(fk_trigger->args,
									   makeString(id->name));
Jan Wieck's avatar
Jan Wieck committed
1582

1583 1584 1585
			id = (Ident *) lfirst(pk_attr);
			fk_trigger->args = lappend(fk_trigger->args,
									   makeString(id->name));
Jan Wieck's avatar
Jan Wieck committed
1586

1587 1588 1589
			fk_attr = lnext(fk_attr);
			pk_attr = lnext(pk_attr);
		}
Jan Wieck's avatar
Jan Wieck committed
1590

1591
		fkactions = lappend(fkactions, (Node *) fk_trigger);
1592

1593 1594 1595 1596 1597 1598 1599 1600 1601 1602 1603 1604 1605 1606 1607 1608 1609 1610 1611 1612 1613 1614 1615 1616 1617 1618 1619 1620 1621 1622 1623 1624 1625 1626 1627 1628 1629 1630 1631 1632 1633 1634 1635 1636
		/*
		 * Build a CREATE CONSTRAINT TRIGGER statement for the ON
		 * UPDATE action fired on the PK table !!!
		 */
		fk_trigger = (CreateTrigStmt *) makeNode(CreateTrigStmt);
		fk_trigger->trigname = fkconstraint->constr_name;
		fk_trigger->relname = fkconstraint->pktable_name;
		fk_trigger->before = false;
		fk_trigger->row = true;
		fk_trigger->actions[0] = 'u';
		fk_trigger->actions[1] = '\0';
		fk_trigger->lang = NULL;
		fk_trigger->text = NULL;

		fk_trigger->attr = NIL;
		fk_trigger->when = NULL;
		fk_trigger->isconstraint = true;
		fk_trigger->deferrable = fkconstraint->deferrable;
		fk_trigger->initdeferred = fkconstraint->initdeferred;
		fk_trigger->constrrelname = cxt->relname;
		switch ((fkconstraint->actions & FKCONSTR_ON_UPDATE_MASK)
				>> FKCONSTR_ON_UPDATE_SHIFT)
		{
			case FKCONSTR_ON_KEY_NOACTION:
				fk_trigger->funcname = "RI_FKey_noaction_upd";
				break;
			case FKCONSTR_ON_KEY_RESTRICT:
				fk_trigger->deferrable = false;
				fk_trigger->initdeferred = false;
				fk_trigger->funcname = "RI_FKey_restrict_upd";
				break;
			case FKCONSTR_ON_KEY_CASCADE:
				fk_trigger->funcname = "RI_FKey_cascade_upd";
				break;
			case FKCONSTR_ON_KEY_SETNULL:
				fk_trigger->funcname = "RI_FKey_setnull_upd";
				break;
			case FKCONSTR_ON_KEY_SETDEFAULT:
				fk_trigger->funcname = "RI_FKey_setdefault_upd";
				break;
			default:
				elog(ERROR, "Only one ON UPDATE action can be specified for FOREIGN KEY constraint");
				break;
		}
Jan Wieck's avatar
Jan Wieck committed
1637

1638 1639 1640 1641 1642 1643 1644 1645
		fk_trigger->args = NIL;
		fk_trigger->args = lappend(fk_trigger->args,
								   makeString(fkconstraint->constr_name));
		fk_trigger->args = lappend(fk_trigger->args,
								   makeString(cxt->relname));
		fk_trigger->args = lappend(fk_trigger->args,
								   makeString(fkconstraint->pktable_name));
		fk_trigger->args = lappend(fk_trigger->args,
1646
								   makeString(fkconstraint->match_type));
1647 1648 1649 1650 1651 1652 1653
		fk_attr = fkconstraint->fk_attrs;
		pk_attr = fkconstraint->pk_attrs;
		while (fk_attr != NIL)
		{
			id = (Ident *) lfirst(fk_attr);
			fk_trigger->args = lappend(fk_trigger->args,
									   makeString(id->name));
Jan Wieck's avatar
Jan Wieck committed
1654

1655 1656 1657
			id = (Ident *) lfirst(pk_attr);
			fk_trigger->args = lappend(fk_trigger->args,
									   makeString(id->name));
1658

1659 1660
			fk_attr = lnext(fk_attr);
			pk_attr = lnext(pk_attr);
Jan Wieck's avatar
Jan Wieck committed
1661 1662
		}

1663 1664
		fkactions = lappend(fkactions, (Node *) fk_trigger);
	}
1665

1666 1667 1668 1669 1670 1671 1672
	/*
	 * Attach completed list of extra actions to cxt->alist.  We cannot
	 * do this earlier, because we assume above that cxt->alist still
	 * holds only IndexStmts.
	 */
	cxt->alist = nconc(cxt->alist, fkactions);
}
Jan Wieck's avatar
Jan Wieck committed
1673

1674 1675
/*
 * transformIndexStmt -
1676
 *	  transforms the qualification of the index statement
1677
 */
1678
static Query *
1679
transformIndexStmt(ParseState *pstate, IndexStmt *stmt)
1680
{
Bruce Momjian's avatar
Bruce Momjian committed
1681
	Query	   *qry;
1682
	RangeTblEntry *rte;
1683

Bruce Momjian's avatar
Bruce Momjian committed
1684 1685
	qry = makeNode(Query);
	qry->commandType = CMD_UTILITY;
1686

1687
	/* take care of the where clause */
1688 1689 1690 1691 1692 1693 1694 1695 1696 1697
	if (stmt->whereClause)
	{
		/*
		 * Put the parent table into the rtable so that the WHERE clause can
		 * refer to its fields without qualification.  Note that this only
		 * works if the parent table already exists --- so we can't easily
		 * support predicates on indexes created implicitly by CREATE TABLE.
		 * Fortunately, that's not necessary.
		 */
		rte = addRangeTableEntry(pstate, stmt->relname, NULL, false, true);
1698

1699 1700
		/* no to join list, yes to namespace */
		addRTEtoQuery(pstate, rte, false, true);
1701

1702 1703
		stmt->whereClause = transformWhereClause(pstate, stmt->whereClause);
	}
1704

Bruce Momjian's avatar
Bruce Momjian committed
1705
	qry->hasSubLinks = pstate->p_hasSubLinks;
1706
	stmt->rangetable = pstate->p_rtable;
1707

Bruce Momjian's avatar
Bruce Momjian committed
1708
	qry->utilityStmt = (Node *) stmt;
1709

Bruce Momjian's avatar
Bruce Momjian committed
1710
	return qry;
1711 1712 1713 1714
}

/*
 * transformRuleStmt -
1715 1716
 *	  transform a Create Rule Statement. The actions is a list of parse
 *	  trees which is transformed into a list of query trees.
1717
 */
1718
static Query *
1719
transformRuleStmt(ParseState *pstate, RuleStmt *stmt)
1720
{
Bruce Momjian's avatar
Bruce Momjian committed
1721
	Query	   *qry;
1722 1723
	RangeTblEntry *oldrte;
	RangeTblEntry *newrte;
1724

Bruce Momjian's avatar
Bruce Momjian committed
1725 1726
	qry = makeNode(Query);
	qry->commandType = CMD_UTILITY;
1727 1728
	qry->utilityStmt = (Node *) stmt;

1729 1730
	/*
	 * To avoid deadlock, make sure the first thing we do is grab
1731 1732 1733
	 * AccessExclusiveLock on the target relation.	This will be needed by
	 * DefineQueryRewrite(), and we don't want to grab a lesser lock
	 * beforehand.	We don't need to hold a refcount on the relcache
1734 1735 1736 1737 1738
	 * entry, however.
	 */
	heap_close(heap_openr(stmt->object->relname, AccessExclusiveLock),
			   NoLock);

1739
	/*
1740 1741 1742
	 * NOTE: 'OLD' must always have a varno equal to 1 and 'NEW' equal to
	 * 2.  Set up their RTEs in the main pstate for use in parsing the
	 * rule qualification.
1743 1744 1745 1746 1747 1748 1749 1750
	 */
	Assert(pstate->p_rtable == NIL);
	oldrte = addRangeTableEntry(pstate, stmt->object->relname,
								makeAttr("*OLD*", NULL),
								false, true);
	newrte = addRangeTableEntry(pstate, stmt->object->relname,
								makeAttr("*NEW*", NULL),
								false, true);
1751 1752 1753
	/* Must override addRangeTableEntry's default access-check flags */
	oldrte->checkForRead = false;
	newrte->checkForRead = false;
1754

1755
	/*
1756
	 * They must be in the namespace too for lookup purposes, but only add
1757 1758
	 * the one(s) that are relevant for the current kind of rule.  In an
	 * UPDATE rule, quals must refer to OLD.field or NEW.field to be
1759 1760 1761 1762
	 * unambiguous, but there's no need to be so picky for INSERT &
	 * DELETE. (Note we marked the RTEs "inFromCl = true" above to allow
	 * unqualified references to their fields.)  We do not add them to the
	 * joinlist.
1763 1764 1765 1766
	 */
	switch (stmt->event)
	{
		case CMD_SELECT:
1767
			addRTEtoQuery(pstate, oldrte, false, true);
1768 1769
			break;
		case CMD_UPDATE:
1770 1771
			addRTEtoQuery(pstate, oldrte, false, true);
			addRTEtoQuery(pstate, newrte, false, true);
1772 1773
			break;
		case CMD_INSERT:
1774
			addRTEtoQuery(pstate, newrte, false, true);
1775 1776
			break;
		case CMD_DELETE:
1777
			addRTEtoQuery(pstate, oldrte, false, true);
1778 1779 1780 1781 1782 1783 1784 1785 1786 1787
			break;
		default:
			elog(ERROR, "transformRuleStmt: unexpected event type %d",
				 (int) stmt->event);
			break;
	}

	/* take care of the where clause */
	stmt->whereClause = transformWhereClause(pstate, stmt->whereClause);

1788
	if (length(pstate->p_rtable) != 2)	/* naughty, naughty... */
1789 1790 1791 1792
		elog(ERROR, "Rule WHERE condition may not contain references to other relations");

	/* save info about sublinks in where clause */
	qry->hasSubLinks = pstate->p_hasSubLinks;
1793

1794
	/*
1795
	 * 'instead nothing' rules with a qualification need a query
1796 1797
	 * rangetable so the rewrite handler can add the negated rule
	 * qualification to the original query. We create a query with the new
1798
	 * command type CMD_NOTHING here that is treated specially by the
1799
	 * rewrite system.
1800
	 */
1801 1802 1803 1804
	if (stmt->actions == NIL)
	{
		Query	   *nothing_qry = makeNode(Query);

1805 1806
		nothing_qry->commandType = CMD_NOTHING;
		nothing_qry->rtable = pstate->p_rtable;
1807
		nothing_qry->jointree = makeFromExpr(NIL, NULL);		/* no join wanted */
1808

1809
		stmt->actions = makeList1(nothing_qry);
1810
	}
1811
	else
1812
	{
1813 1814
		List	   *oldactions;
		List	   *newactions = NIL;
1815

1816
		/*
1817
		 * transform each statement, like parse_analyze()
1818
		 */
1819
		foreach(oldactions, stmt->actions)
1820
		{
1821
			Node	   *action = (Node *) lfirst(oldactions);
1822
			ParseState *sub_pstate = make_parsestate(pstate->parentParseState);
1823 1824
			Query	   *sub_qry,
					   *top_subqry;
1825 1826
			bool		has_old,
						has_new;
1827

1828
			/*
1829 1830 1831 1832 1833 1834
			 * Set up OLD/NEW in the rtable for this statement.  The
			 * entries are marked not inFromCl because we don't want them
			 * to be referred to by unqualified field names nor "*" in the
			 * rule actions.  We must add them to the namespace, however,
			 * or they won't be accessible at all.  We decide later
			 * whether to put them in the joinlist.
1835 1836 1837 1838 1839 1840 1841
			 */
			oldrte = addRangeTableEntry(sub_pstate, stmt->object->relname,
										makeAttr("*OLD*", NULL),
										false, false);
			newrte = addRangeTableEntry(sub_pstate, stmt->object->relname,
										makeAttr("*NEW*", NULL),
										false, false);
1842 1843
			oldrte->checkForRead = false;
			newrte->checkForRead = false;
1844 1845
			addRTEtoQuery(sub_pstate, oldrte, false, true);
			addRTEtoQuery(sub_pstate, newrte, false, true);
1846

1847
			/* Transform the rule action statement */
1848 1849 1850 1851 1852 1853 1854 1855 1856 1857
			top_subqry = transformStmt(sub_pstate, action);

			/*
			 * We cannot support utility-statement actions (eg NOTIFY)
			 * with nonempty rule WHERE conditions, because there's no
			 * way to make the utility action execute conditionally.
			 */
			if (top_subqry->commandType == CMD_UTILITY &&
				stmt->whereClause != NULL)
				elog(ERROR, "Rules with WHERE conditions may only have SELECT, INSERT, UPDATE, or DELETE actions");
1858 1859 1860 1861

			/*
			 * If the action is INSERT...SELECT, OLD/NEW have been pushed
			 * down into the SELECT, and that's what we need to look at.
1862 1863
			 * (Ugly kluge ... try to fix this when we redesign
			 * querytrees.)
1864 1865
			 */
			sub_qry = getInsertSelectQuery(top_subqry, NULL);
1866 1867 1868 1869 1870 1871 1872 1873 1874 1875 1876 1877 1878 1879 1880 1881 1882 1883 1884 1885 1886 1887 1888 1889 1890 1891 1892 1893 1894 1895 1896 1897 1898 1899 1900 1901 1902

			/*
			 * Validate action's use of OLD/NEW, qual too
			 */
			has_old =
				rangeTableEntry_used((Node *) sub_qry, PRS2_OLD_VARNO, 0) ||
				rangeTableEntry_used(stmt->whereClause, PRS2_OLD_VARNO, 0);
			has_new =
				rangeTableEntry_used((Node *) sub_qry, PRS2_NEW_VARNO, 0) ||
				rangeTableEntry_used(stmt->whereClause, PRS2_NEW_VARNO, 0);

			switch (stmt->event)
			{
				case CMD_SELECT:
					if (has_old)
						elog(ERROR, "ON SELECT rule may not use OLD");
					if (has_new)
						elog(ERROR, "ON SELECT rule may not use NEW");
					break;
				case CMD_UPDATE:
					/* both are OK */
					break;
				case CMD_INSERT:
					if (has_old)
						elog(ERROR, "ON INSERT rule may not use OLD");
					break;
				case CMD_DELETE:
					if (has_new)
						elog(ERROR, "ON DELETE rule may not use NEW");
					break;
				default:
					elog(ERROR, "transformRuleStmt: unexpected event type %d",
						 (int) stmt->event);
					break;
			}

			/*
1903 1904 1905
			 * For efficiency's sake, add OLD to the rule action's
			 * jointree only if it was actually referenced in the
			 * statement or qual.
1906 1907 1908 1909 1910 1911
			 *
			 * For INSERT, NEW is not really a relation (only a reference to
			 * the to-be-inserted tuple) and should never be added to the
			 * jointree.
			 *
			 * For UPDATE, we treat NEW as being another kind of reference to
1912 1913 1914 1915 1916 1917
			 * OLD, because it represents references to *transformed*
			 * tuples of the existing relation.  It would be wrong to
			 * enter NEW separately in the jointree, since that would
			 * cause a double join of the updated relation.  It's also
			 * wrong to fail to make a jointree entry if only NEW and not
			 * OLD is mentioned.
1918
			 */
1919
			if (has_old || (has_new && stmt->event == CMD_UPDATE))
1920
			{
1921
				/* hack so we can use addRTEtoQuery() */
1922 1923
				sub_pstate->p_rtable = sub_qry->rtable;
				sub_pstate->p_joinlist = sub_qry->jointree->fromlist;
1924
				addRTEtoQuery(sub_pstate, oldrte, true, false);
1925
				sub_qry->jointree->fromlist = sub_pstate->p_joinlist;
1926 1927
			}

1928
			newactions = lappend(newactions, top_subqry);
1929 1930 1931 1932

			release_pstate_resources(sub_pstate);
			pfree(sub_pstate);
		}
1933 1934

		stmt->actions = newactions;
1935
	}
1936

Bruce Momjian's avatar
Bruce Momjian committed
1937
	return qry;
1938 1939 1940 1941 1942
}


/*
 * transformSelectStmt -
1943
 *	  transforms a Select Statement
1944
 *
1945
 * Note: this is also used for DECLARE CURSOR statements.
1946
 */
1947
static Query *
Bruce Momjian's avatar
Bruce Momjian committed
1948
transformSelectStmt(ParseState *pstate, SelectStmt *stmt)
1949
{
1950
	Query	   *qry = makeNode(Query);
1951
	Node	   *qual;
1952 1953

	qry->commandType = CMD_SELECT;
1954

1955 1956 1957 1958 1959 1960 1961 1962
	if (stmt->portalname)
	{
		/* DECLARE CURSOR */
		if (stmt->into)
			elog(ERROR, "DECLARE CURSOR must not specify INTO");
		if (stmt->forUpdate)
			elog(ERROR, "DECLARE/UPDATE is not supported"
				 "\n\tCursors must be READ ONLY");
1963

1964
		/*
1965
		 * 15 august 1991 -- since 3.0 postgres does locking right, we
1966 1967 1968
		 * discovered that portals were violating locking protocol. portal
		 * locks cannot span xacts. as a short-term fix, we installed the
		 * check here. -- mao
1969 1970 1971 1972 1973 1974 1975
		 */
		if (!IsTransactionBlock())
			elog(ERROR, "DECLARE CURSOR may only be used in begin/end transaction blocks");

		qry->into = stmt->portalname;
		qry->isTemp = stmt->istemp;
		qry->isPortal = TRUE;
1976
		qry->isBinary = stmt->binary;	/* internal portal */
1977 1978 1979 1980 1981 1982 1983 1984 1985 1986
	}
	else
	{
		/* SELECT */
		qry->into = stmt->into;
		qry->isTemp = stmt->istemp;
		qry->isPortal = FALSE;
		qry->isBinary = FALSE;
	}

1987 1988 1989
	/* make FOR UPDATE clause available to addRangeTableEntry */
	pstate->p_forUpdate = stmt->forUpdate;

1990 1991
	/* process the FROM clause */
	transformFromClause(pstate, stmt->fromClause);
1992

1993
	/* transform targetlist and WHERE */
1994
	qry->targetList = transformTargetList(pstate, stmt->targetList);
1995

1996
	qual = transformWhereClause(pstate, stmt->whereClause);
1997

1998 1999
	/*
	 * Initial processing of HAVING clause is just like WHERE clause.
2000
	 * Additional work will be done in optimizer/plan/planner.c.
2001
	 */
2002
	qry->havingQual = transformWhereClause(pstate, stmt->havingClause);
2003

2004 2005 2006
	qry->groupClause = transformGroupClause(pstate,
											stmt->groupClause,
											qry->targetList);
2007

2008 2009
	qry->sortClause = transformSortClause(pstate,
										  stmt->sortClause,
2010 2011 2012 2013 2014
										  qry->targetList);

	qry->distinctClause = transformDistinctClause(pstate,
												  stmt->distinctClause,
												  qry->targetList,
2015
												  &qry->sortClause);
2016

2017 2018 2019
	qry->limitOffset = stmt->limitOffset;
	qry->limitCount = stmt->limitCount;

2020
	qry->hasSubLinks = pstate->p_hasSubLinks;
Bruce Momjian's avatar
Bruce Momjian committed
2021
	qry->hasAggs = pstate->p_hasAggs;
2022
	if (pstate->p_hasAggs || qry->groupClause || qry->havingQual)
2023
		parseCheckAggregates(pstate, qry, qual);
2024

2025 2026 2027
	qry->rtable = pstate->p_rtable;
	qry->jointree = makeFromExpr(pstate->p_joinlist, qual);

2028
	if (stmt->forUpdate != NIL)
2029 2030 2031 2032 2033 2034 2035
		transformForUpdate(qry, stmt->forUpdate);

	return qry;
}

/*
 * transformSetOperationsStmt -
2036
 *	  transforms a set-operations tree
2037
 *
2038
 * A set-operation tree is just a SELECT, but with UNION/INTERSECT/EXCEPT
2039 2040
 * structure to it.  We must transform each leaf SELECT and build up a top-
 * level Query that contains the leaf SELECTs as subqueries in its rangetable.
2041 2042
 * The tree of set operations is converted into the setOperations field of
 * the top-level Query.
2043
 */
2044
static Query *transformSetOperationStmt(ParseState *pstate, SelectStmt *stmt)
2045 2046 2047
{
	Query	   *qry = makeNode(Query);
	SelectStmt *leftmostSelect;
2048
	int			leftmostRTI;
2049
	Query	   *leftmostQuery;
2050
	SetOperationStmt *sostmt;
2051
	char	   *into;
2052
	bool		istemp;
2053 2054 2055 2056 2057 2058
	char	   *portalname;
	bool		binary;
	List	   *sortClause;
	Node	   *limitOffset;
	Node	   *limitCount;
	List	   *forUpdate;
2059
	Node	   *node;
2060
	List	   *lefttl,
2061 2062 2063 2064 2065
			   *dtlist,
			   *targetvars,
			   *targetnames,
			   *sv_namespace;
	JoinExpr   *jnode;
2066 2067 2068 2069
	int			tllen;

	qry->commandType = CMD_SELECT;

2070
	/*
2071 2072
	 * Find leftmost leaf SelectStmt; extract the one-time-only items from
	 * it and from the top-level node.
2073
	 */
2074 2075 2076 2077 2078
	leftmostSelect = stmt->larg;
	while (leftmostSelect && leftmostSelect->op != SETOP_NONE)
		leftmostSelect = leftmostSelect->larg;
	Assert(leftmostSelect && IsA(leftmostSelect, SelectStmt) &&
		   leftmostSelect->larg == NULL);
2079 2080
	into = leftmostSelect->into;
	istemp = leftmostSelect->istemp;
2081 2082
	portalname = stmt->portalname;
	binary = stmt->binary;
2083 2084 2085 2086

	/* clear them to prevent complaints in transformSetOperationTree() */
	leftmostSelect->into = NULL;
	leftmostSelect->istemp = false;
2087 2088
	stmt->portalname = NULL;
	stmt->binary = false;
2089

2090 2091
	/*
	 * These are not one-time, exactly, but we want to process them here
2092 2093
	 * and not let transformSetOperationTree() see them --- else it'll
	 * just recurse right back here!
2094 2095 2096 2097 2098 2099 2100 2101 2102 2103 2104 2105
	 */
	sortClause = stmt->sortClause;
	limitOffset = stmt->limitOffset;
	limitCount = stmt->limitCount;
	forUpdate = stmt->forUpdate;

	stmt->sortClause = NIL;
	stmt->limitOffset = NULL;
	stmt->limitCount = NULL;
	stmt->forUpdate = NIL;

	/* We don't support forUpdate with set ops at the moment. */
2106 2107
	if (forUpdate)
		elog(ERROR, "SELECT FOR UPDATE is not allowed with UNION/INTERSECT/EXCEPT");
Bruce Momjian's avatar
Hi!  
Bruce Momjian committed
2108

Bruce Momjian's avatar
Bruce Momjian committed
2109
	/*
2110
	 * Recursively transform the components of the tree.
Bruce Momjian's avatar
Bruce Momjian committed
2111
	 */
2112 2113 2114
	sostmt = (SetOperationStmt *) transformSetOperationTree(pstate, stmt);
	Assert(sostmt && IsA(sostmt, SetOperationStmt));
	qry->setOperations = (Node *) sostmt;
2115 2116 2117 2118

	/*
	 * Re-find leftmost SELECT (now it's a sub-query in rangetable)
	 */
2119
	node = sostmt->larg;
2120 2121 2122
	while (node && IsA(node, SetOperationStmt))
		node = ((SetOperationStmt *) node)->larg;
	Assert(node && IsA(node, RangeTblRef));
2123 2124
	leftmostRTI = ((RangeTblRef *) node)->rtindex;
	leftmostQuery = rt_fetch(leftmostRTI, pstate->p_rtable)->subquery;
2125
	Assert(leftmostQuery != NULL);
2126

2127 2128
	/*
	 * Generate dummy targetlist for outer query using column names of
2129 2130 2131
	 * leftmost select and common datatypes of topmost set operation. Also
	 * make lists of the dummy vars and their names for use in parsing
	 * ORDER BY.
2132 2133
	 */
	qry->targetList = NIL;
2134 2135
	targetvars = NIL;
	targetnames = NIL;
2136
	lefttl = leftmostQuery->targetList;
2137
	foreach(dtlist, sostmt->colTypes)
2138
	{
2139 2140 2141 2142 2143
		Oid			colType = (Oid) lfirsti(dtlist);
		Resdom	   *leftResdom = ((TargetEntry *) lfirst(lefttl))->resdom;
		char	   *colName = pstrdup(leftResdom->resname);
		Resdom	   *resdom;
		Node	   *expr;
2144 2145 2146 2147

		resdom = makeResdom((AttrNumber) pstate->p_last_resno++,
							colType,
							-1,
2148
							colName,
2149
							false);
2150 2151
		expr = (Node *) makeVar(leftmostRTI,
								leftResdom->resno,
2152 2153 2154 2155 2156
								colType,
								-1,
								0);
		qry->targetList = lappend(qry->targetList,
								  makeTargetEntry(resdom, expr));
2157 2158
		targetvars = lappend(targetvars, expr);
		targetnames = lappend(targetnames, makeString(colName));
2159 2160
		lefttl = lnext(lefttl);
	}
2161

2162 2163 2164 2165 2166 2167 2168 2169 2170 2171 2172 2173 2174
	/*
	 * Insert one-time items into top-level query
	 *
	 * This needs to agree with transformSelectStmt!
	 */
	if (portalname)
	{
		/* DECLARE CURSOR */
		if (into)
			elog(ERROR, "DECLARE CURSOR must not specify INTO");
		if (forUpdate)
			elog(ERROR, "DECLARE/UPDATE is not supported"
				 "\n\tCursors must be READ ONLY");
2175

2176
		/*
2177
		 * 15 august 1991 -- since 3.0 postgres does locking right, we
2178 2179 2180
		 * discovered that portals were violating locking protocol. portal
		 * locks cannot span xacts. as a short-term fix, we installed the
		 * check here. -- mao
2181 2182 2183 2184 2185 2186 2187 2188 2189 2190 2191 2192 2193 2194 2195 2196 2197 2198
		 */
		if (!IsTransactionBlock())
			elog(ERROR, "DECLARE CURSOR may only be used in begin/end transaction blocks");

		qry->into = portalname;
		qry->isTemp = istemp;
		qry->isPortal = TRUE;
		qry->isBinary = binary; /* internal portal */
	}
	else
	{
		/* SELECT */
		qry->into = into;
		qry->isTemp = istemp;
		qry->isPortal = FALSE;
		qry->isBinary = FALSE;
	}

2199
	/*
2200 2201 2202 2203 2204
	 * As a first step towards supporting sort clauses that are
	 * expressions using the output columns, generate a namespace entry
	 * that makes the output columns visible.  A JoinExpr node is handy
	 * for this, since we can easily control the Vars generated upon
	 * matches.
2205 2206 2207 2208 2209 2210 2211 2212 2213 2214 2215 2216
	 *
	 * Note: we don't yet do anything useful with such cases, but at least
	 * "ORDER BY upper(foo)" will draw the right error message rather than
	 * "foo not found".
	 */
	jnode = makeNode(JoinExpr);
	jnode->colnames = targetnames;
	jnode->colvars = targetvars;

	sv_namespace = pstate->p_namespace;
	pstate->p_namespace = makeList1(jnode);

2217 2218 2219 2220 2221 2222 2223 2224 2225 2226 2227 2228
	/*
	 * For now, we don't support resjunk sort clauses on the output of a
	 * setOperation tree --- you can only use the SQL92-spec options of
	 * selecting an output column by name or number.  Enforce by checking
	 * that transformSortClause doesn't add any items to tlist.
	 */
	tllen = length(qry->targetList);

	qry->sortClause = transformSortClause(pstate,
										  sortClause,
										  qry->targetList);

2229 2230
	pstate->p_namespace = sv_namespace;

2231 2232 2233 2234 2235 2236 2237 2238 2239 2240
	if (tllen != length(qry->targetList))
		elog(ERROR, "ORDER BY on a UNION/INTERSECT/EXCEPT result must be on one of the result columns");

	qry->limitOffset = limitOffset;
	qry->limitCount = limitCount;

	qry->hasSubLinks = pstate->p_hasSubLinks;
	qry->hasAggs = pstate->p_hasAggs;
	if (pstate->p_hasAggs || qry->groupClause || qry->havingQual)
		parseCheckAggregates(pstate, qry, NULL);
2241

2242
	qry->rtable = pstate->p_rtable;
2243
	qry->jointree = makeFromExpr(pstate->p_joinlist, NULL);
2244

2245
	if (forUpdate != NIL)
2246
		transformForUpdate(qry, forUpdate);
2247

2248 2249 2250 2251 2252 2253 2254 2255
	return qry;
}

/*
 * transformSetOperationTree
 *		Recursively transform leaves and internal nodes of a set-op tree
 */
static Node *
2256
transformSetOperationTree(ParseState *pstate, SelectStmt *stmt)
2257
{
2258
	bool		isLeaf;
2259 2260 2261 2262 2263 2264 2265 2266 2267 2268 2269 2270 2271 2272 2273 2274 2275 2276 2277 2278 2279 2280 2281 2282 2283 2284

	Assert(stmt && IsA(stmt, SelectStmt));

	/*
	 * Validity-check both leaf and internal SELECTs for disallowed ops.
	 */
	if (stmt->into)
		elog(ERROR, "INTO is only allowed on first SELECT of UNION/INTERSECT/EXCEPT");
	if (stmt->portalname)		/* should not happen */
		elog(ERROR, "Portal may not appear in UNION/INTERSECT/EXCEPT");
	/* We don't support forUpdate with set ops at the moment. */
	if (stmt->forUpdate)
		elog(ERROR, "SELECT FOR UPDATE is not allowed with UNION/INTERSECT/EXCEPT");

	/*
	 * If an internal node of a set-op tree has ORDER BY, UPDATE, or LIMIT
	 * clauses attached, we need to treat it like a leaf node to generate
	 * an independent sub-Query tree.  Otherwise, it can be represented by
	 * a SetOperationStmt node underneath the parent Query.
	 */
	if (stmt->op == SETOP_NONE)
	{
		Assert(stmt->larg == NULL && stmt->rarg == NULL);
		isLeaf = true;
	}
	else
2285
	{
2286 2287 2288 2289 2290 2291 2292 2293 2294 2295 2296
		Assert(stmt->larg != NULL && stmt->rarg != NULL);
		if (stmt->sortClause || stmt->limitOffset || stmt->limitCount ||
			stmt->forUpdate)
			isLeaf = true;
		else
			isLeaf = false;
	}

	if (isLeaf)
	{
		/* Process leaf SELECT */
2297 2298 2299
		List	   *selectList;
		Query	   *selectQuery;
		char		selectName[32];
2300 2301 2302 2303
		RangeTblEntry *rte;
		RangeTblRef *rtr;

		/*
2304 2305 2306
		 * Transform SelectStmt into a Query.
		 *
		 * Note: previously transformed sub-queries don't affect the parsing
2307 2308
		 * of this sub-query, because they are not in the toplevel
		 * pstate's namespace list.
2309
		 */
2310
		selectList = parse_analyze((Node *) stmt, pstate);
2311 2312 2313

		Assert(length(selectList) == 1);
		selectQuery = (Query *) lfirst(selectList);
2314

2315 2316 2317 2318 2319 2320 2321 2322 2323
		/*
		 * Make the leaf query be a subquery in the top-level rangetable.
		 */
		sprintf(selectName, "*SELECT* %d", length(pstate->p_rtable) + 1);
		rte = addRangeTableEntryForSubquery(pstate,
											selectQuery,
											makeAttr(pstrdup(selectName),
													 NULL),
											false);
2324

2325
		/*
2326 2327
		 * Return a RangeTblRef to replace the SelectStmt in the set-op
		 * tree.
2328 2329 2330 2331 2332 2333 2334
		 */
		rtr = makeNode(RangeTblRef);
		/* assume new rte is at end */
		rtr->rtindex = length(pstate->p_rtable);
		Assert(rte == rt_fetch(rtr->rtindex, pstate->p_rtable));
		return (Node *) rtr;
	}
2335
	else
2336
	{
2337 2338
		/* Process an internal node (set operation node) */
		SetOperationStmt *op = makeNode(SetOperationStmt);
2339 2340
		List	   *lcoltypes;
		List	   *rcoltypes;
2341 2342
		const char *context;

2343 2344
		context = (stmt->op == SETOP_UNION ? "UNION" :
				   (stmt->op == SETOP_INTERSECT ? "INTERSECT" :
2345
					"EXCEPT"));
2346 2347 2348 2349

		op->op = stmt->op;
		op->all = stmt->all;

2350 2351 2352
		/*
		 * Recursively transform the child nodes.
		 */
2353 2354
		op->larg = transformSetOperationTree(pstate, stmt->larg);
		op->rarg = transformSetOperationTree(pstate, stmt->rarg);
2355

2356 2357 2358 2359 2360 2361 2362 2363 2364 2365 2366 2367
		/*
		 * Verify that the two children have the same number of non-junk
		 * columns, and determine the types of the merged output columns.
		 */
		lcoltypes = getSetColTypes(pstate, op->larg);
		rcoltypes = getSetColTypes(pstate, op->rarg);
		if (length(lcoltypes) != length(rcoltypes))
			elog(ERROR, "Each %s query must have the same number of columns",
				 context);
		op->colTypes = NIL;
		while (lcoltypes != NIL)
		{
2368 2369 2370
			Oid			lcoltype = (Oid) lfirsti(lcoltypes);
			Oid			rcoltype = (Oid) lfirsti(rcoltypes);
			Oid			rescoltype;
2371 2372 2373 2374 2375 2376 2377

			rescoltype = select_common_type(makeListi2(lcoltype, rcoltype),
											context);
			op->colTypes = lappendi(op->colTypes, rescoltype);
			lcoltypes = lnext(lcoltypes);
			rcoltypes = lnext(rcoltypes);
		}
2378

2379 2380
		return (Node *) op;
	}
2381 2382
}

2383 2384 2385 2386 2387 2388 2389 2390 2391 2392 2393
/*
 * getSetColTypes
 *		Get output column types of an (already transformed) set-op node
 */
static List *
getSetColTypes(ParseState *pstate, Node *node)
{
	if (IsA(node, RangeTblRef))
	{
		RangeTblRef *rtr = (RangeTblRef *) node;
		RangeTblEntry *rte = rt_fetch(rtr->rtindex, pstate->p_rtable);
2394 2395 2396
		Query	   *selectQuery = rte->subquery;
		List	   *result = NIL;
		List	   *tl;
2397 2398 2399 2400 2401 2402 2403 2404 2405 2406 2407 2408 2409 2410 2411 2412 2413 2414 2415 2416 2417 2418 2419 2420 2421 2422 2423 2424 2425 2426 2427

		Assert(selectQuery != NULL);
		/* Get types of non-junk columns */
		foreach(tl, selectQuery->targetList)
		{
			TargetEntry *tle = (TargetEntry *) lfirst(tl);
			Resdom	   *resnode = tle->resdom;

			if (resnode->resjunk)
				continue;
			result = lappendi(result, resnode->restype);
		}
		return result;
	}
	else if (IsA(node, SetOperationStmt))
	{
		SetOperationStmt *op = (SetOperationStmt *) node;

		/* Result already computed during transformation of node */
		Assert(op->colTypes != NIL);
		return op->colTypes;
	}
	else
	{
		elog(ERROR, "getSetColTypes: unexpected node %d",
			 (int) nodeTag(node));
		return NIL;				/* keep compiler quiet */
	}
}


2428 2429
/*
 * transformUpdateStmt -
2430
 *	  transforms an update statement
2431
 */
2432
static Query *
Bruce Momjian's avatar
Bruce Momjian committed
2433
transformUpdateStmt(ParseState *pstate, UpdateStmt *stmt)
2434
{
2435
	Query	   *qry = makeNode(Query);
2436
	Node	   *qual;
2437 2438
	List	   *origTargetList;
	List	   *tl;
2439 2440 2441

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

2443 2444 2445 2446
	qry->resultRelation = setTargetTable(pstate, stmt->relname,
										 interpretInhOption(stmt->inhOpt),
										 true);

2447 2448 2449 2450
	/*
	 * 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.
	 */
2451
	transformFromClause(pstate, stmt->fromClause);
2452

2453
	qry->targetList = transformTargetList(pstate, stmt->targetList);
2454

2455
	qual = transformWhereClause(pstate, stmt->whereClause);
2456

2457
	qry->rtable = pstate->p_rtable;
2458
	qry->jointree = makeFromExpr(pstate->p_joinlist, qual);
2459

2460
	qry->hasSubLinks = pstate->p_hasSubLinks;
Bruce Momjian's avatar
Bruce Momjian committed
2461
	qry->hasAggs = pstate->p_hasAggs;
2462
	if (pstate->p_hasAggs)
2463
		parseCheckAggregates(pstate, qry, qual);
2464

2465 2466 2467 2468 2469 2470 2471 2472 2473 2474 2475 2476 2477 2478 2479 2480 2481 2482 2483
	/*
	 * Now we are done with SELECT-like processing, and can get on with
	 * transforming the target list to match the UPDATE target columns.
	 */

	/* Prepare to assign non-conflicting resnos to resjunk attributes */
	if (pstate->p_last_resno <= pstate->p_target_relation->rd_rel->relnatts)
		pstate->p_last_resno = pstate->p_target_relation->rd_rel->relnatts + 1;

	/* Prepare non-junk columns for assignment to target table */
	origTargetList = stmt->targetList;
	foreach(tl, qry->targetList)
	{
		TargetEntry *tle = (TargetEntry *) lfirst(tl);
		Resdom	   *resnode = tle->resdom;
		ResTarget  *origTarget;

		if (resnode->resjunk)
		{
2484 2485 2486 2487 2488

			/*
			 * Resjunk nodes need no additional processing, but be sure
			 * they have names and resnos that do not match any target
			 * columns; else rewriter or planner might get confused.
2489 2490 2491 2492 2493 2494 2495 2496
			 */
			resnode->resname = "?resjunk?";
			resnode->resno = (AttrNumber) pstate->p_last_resno++;
			continue;
		}
		if (origTargetList == NIL)
			elog(ERROR, "UPDATE target count mismatch --- internal error");
		origTarget = (ResTarget *) lfirst(origTargetList);
2497 2498 2499 2500
		updateTargetListEntry(pstate, tle, origTarget->name,
							  attnameAttNum(pstate->p_target_relation,
											origTarget->name),
							  origTarget->indirection);
2501 2502 2503 2504 2505
		origTargetList = lnext(origTargetList);
	}
	if (origTargetList != NIL)
		elog(ERROR, "UPDATE target count mismatch --- internal error");

2506
	return qry;
2507
}
Bruce Momjian's avatar
Hi!  
Bruce Momjian committed
2508

2509 2510
/*
 * tranformAlterTableStmt -
2511
 *	transform an Alter Table Statement
2512 2513
 */
static Query *
2514
transformAlterTableStmt(ParseState *pstate, AlterTableStmt *stmt)
2515
{
2516
	CreateStmtContext cxt;
2517 2518 2519
	Query	   *qry;

	/*
2520 2521 2522
	 * The only subtypes that currently require parse transformation
	 * handling are 'A'dd column and Add 'C'onstraint.  These largely
	 * re-use code from CREATE TABLE.
2523
	 */
2524 2525
	switch (stmt->subtype)
	{
2526
		case 'A':
2527 2528 2529 2530 2531 2532 2533
			cxt.stmtType = "ALTER TABLE";
			cxt.relname = stmt->relname;
			cxt.inhRelnames = NIL;
			cxt.istemp = is_temp_rel_name(stmt->relname);
			cxt.relOid = GetSysCacheOid(RELNAME,
										PointerGetDatum(stmt->relname),
										0, 0, 0);
2534 2535 2536 2537
			cxt.hasoids = SearchSysCacheExists(ATTNUM,
											   ObjectIdGetDatum(cxt.relOid),
											   Int16GetDatum(ObjectIdAttributeNumber),
											   0, 0);
2538 2539 2540 2541 2542 2543 2544 2545 2546 2547 2548 2549 2550 2551 2552 2553 2554 2555
			cxt.columns = NIL;
			cxt.ckconstraints = NIL;
			cxt.fkconstraints = NIL;
			cxt.ixconstraints = NIL;
			cxt.blist = NIL;
			cxt.alist = NIL;
			cxt.pkey = NULL;

			Assert(IsA(stmt->def, ColumnDef));
			transformColumnDefinition(pstate, &cxt,
									  (ColumnDef *) stmt->def);

			transformIndexConstraints(pstate, &cxt);
			transformFKConstraints(pstate, &cxt);

			((ColumnDef *) stmt->def)->constraints = cxt.ckconstraints;
			extras_before = cxt.blist;
			extras_after = cxt.alist;
2556
			break;
2557

2558 2559 2560 2561 2562 2563 2564 2565
		case 'C':
			cxt.stmtType = "ALTER TABLE";
			cxt.relname = stmt->relname;
			cxt.inhRelnames = NIL;
			cxt.istemp = is_temp_rel_name(stmt->relname);
			cxt.relOid = GetSysCacheOid(RELNAME,
										PointerGetDatum(stmt->relname),
										0, 0, 0);
2566 2567 2568 2569
			cxt.hasoids = SearchSysCacheExists(ATTNUM,
											   ObjectIdGetDatum(cxt.relOid),
											   Int16GetDatum(ObjectIdAttributeNumber),
											   0, 0);
2570 2571 2572 2573 2574 2575 2576 2577 2578 2579 2580 2581 2582 2583 2584
			cxt.columns = NIL;
			cxt.ckconstraints = NIL;
			cxt.fkconstraints = NIL;
			cxt.ixconstraints = NIL;
			cxt.blist = NIL;
			cxt.alist = NIL;
			cxt.pkey = NULL;

			if (IsA(stmt->def, Constraint))
				transformTableConstraint(pstate, &cxt,
										 (Constraint *) stmt->def);
			else if (IsA(stmt->def, FkConstraint))
				cxt.fkconstraints = lappend(cxt.fkconstraints, stmt->def);
			else
				elog(ERROR, "Unexpected node type in ALTER TABLE ADD CONSTRAINT");
2585

2586 2587
			transformIndexConstraints(pstate, &cxt);
			transformFKConstraints(pstate, &cxt);
2588

2589 2590 2591 2592
			Assert(cxt.columns == NIL);
			stmt->def = (Node *) nconc(cxt.ckconstraints, cxt.fkconstraints);
			extras_before = cxt.blist;
			extras_after = cxt.alist;
2593
			break;
2594

2595 2596 2597
		default:
			break;
	}
2598 2599 2600

	qry = makeNode(Query);
	qry->commandType = CMD_UTILITY;
2601
	qry->utilityStmt = (Node *) stmt;
2602

2603 2604 2605
	return qry;
}

2606
/*
2607 2608 2609 2610 2611 2612 2613 2614 2615 2616 2617 2618 2619 2620 2621 2622 2623 2624 2625 2626 2627 2628 2629 2630 2631 2632 2633 2634 2635 2636 2637 2638 2639 2640 2641 2642 2643 2644 2645 2646 2647 2648 2649 2650 2651 2652 2653 2654 2655 2656 2657 2658 2659 2660 2661 2662 2663 2664 2665 2666 2667 2668 2669 2670 2671 2672 2673 2674 2675 2676
 * Transform uses of %TYPE in a statement.
 */
static Node *
transformTypeRefs(ParseState *pstate, Node *stmt)
{
	switch (nodeTag(stmt))
	{
		case T_ProcedureStmt:
		{
			ProcedureStmt  *ps = (ProcedureStmt *) stmt;

			transformTypeRefsList(pstate, ps->argTypes);
			transformTypeRef(pstate, (TypeName *) ps->returnType);
			transformTypeRefsList(pstate, ps->withClause);
		}
		break;

		case T_CommentStmt:
		{
			CommentStmt	   *cs = (CommentStmt *) stmt;

			transformTypeRefsList(pstate, cs->objlist);
		}
		break;

		case T_RemoveFuncStmt:
		{
			RemoveFuncStmt *rs = (RemoveFuncStmt *) stmt;

			transformTypeRefsList(pstate, rs->args);
		}
		break;

		case T_DefineStmt:
		{
			DefineStmt *ds = (DefineStmt *) stmt;
			List	   *ele;

			foreach(ele, ds->definition)
			{
				DefElem	   *de = (DefElem *) lfirst(ele);

				if (de->arg != NULL
					&& IsA(de->arg, TypeName))
				{
					transformTypeRef(pstate, (TypeName *) de->arg);
				}
			}
		}
		break;

		default:
			elog(ERROR, "Unsupported type %d in transformTypeRefs",
				 nodeTag(stmt));
			break;
	}

	return stmt;
}

/*
 * Transform uses of %TYPE in a list.
 */
static void
transformTypeRefsList(ParseState *pstate, List *l)
{
	List	   *ele;

	foreach(ele, l)
	{
2677 2678 2679 2680
		Node   *elem = lfirst(ele);

		if (elem && IsA(elem, TypeName))
			transformTypeRef(pstate, (TypeName *) elem);
2681 2682 2683 2684 2685 2686 2687 2688 2689 2690 2691 2692 2693 2694 2695 2696 2697 2698 2699 2700 2701 2702 2703 2704 2705 2706 2707 2708
	}
}

/*
 * Transform a TypeName to not use %TYPE.
 */
static void
transformTypeRef(ParseState *pstate, TypeName *tn)
{
	Attr   *att;
	Node   *n;
	Var	   *v;
	char   *tyn;

	if (tn->attrname == NULL)
		return;
	att = makeAttr(tn->name, tn->attrname);
	n = transformExpr(pstate, (Node *) att, EXPR_COLUMN_FIRST);
	if (! IsA(n, Var))
		elog(ERROR, "unsupported expression in %%TYPE");
	v = (Var *) n;
	tyn = typeidTypeName(v->vartype);
	elog(NOTICE, "%s.%s%%TYPE converted to %s", tn->name, tn->attrname, tyn);
	tn->name = tyn;
	tn->typmod = v->vartypmod;
	tn->attrname = NULL;
}

2709
/* exported so planner can check again after rewriting, query pullup, etc */
2710 2711 2712
void
CheckSelectForUpdate(Query *qry)
{
2713 2714
	if (qry->setOperations)
		elog(ERROR, "SELECT FOR UPDATE is not allowed with UNION/INTERSECT/EXCEPT");
2715
	if (qry->distinctClause != NIL)
2716
		elog(ERROR, "SELECT FOR UPDATE is not allowed with DISTINCT clause");
2717
	if (qry->groupClause != NIL)
2718 2719 2720 2721 2722
		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");
}

2723 2724 2725
static void
transformForUpdate(Query *qry, List *forUpdate)
{
2726
	List	   *rowMarks = qry->rowMarks;
2727
	List	   *l;
2728
	List	   *rt;
2729 2730
	Index		i;

2731 2732
	CheckSelectForUpdate(qry);

2733
	if (lfirst(forUpdate) == NULL)
2734
	{
2735 2736 2737
		/* all tables used in query */
		i = 0;
		foreach(rt, qry->rtable)
2738
		{
2739 2740 2741 2742 2743 2744 2745 2746 2747 2748
			RangeTblEntry *rte = (RangeTblEntry *) lfirst(rt);

			++i;
			if (rte->subquery)
			{
				/* FOR UPDATE of subquery is propagated to subquery's rels */
				transformForUpdate(rte->subquery, makeList1(NULL));
			}
			else
			{
2749
				if (!intMember(i, rowMarks))	/* avoid duplicates */
2750
					rowMarks = lappendi(rowMarks, i);
2751 2752
				rte->checkForWrite = true;
			}
2753 2754
		}
	}
2755
	else
2756
	{
2757 2758
		/* just the named tables */
		foreach(l, forUpdate)
2759
		{
2760
			char	   *relname = strVal(lfirst(l));
2761 2762 2763

			i = 0;
			foreach(rt, qry->rtable)
2764
			{
2765
				RangeTblEntry *rte = (RangeTblEntry *) lfirst(rt);
2766

2767 2768
				++i;
				if (strcmp(rte->eref->relname, relname) == 0)
2769
				{
2770 2771 2772 2773 2774 2775 2776
					if (rte->subquery)
					{
						/* propagate to subquery */
						transformForUpdate(rte->subquery, makeList1(NULL));
					}
					else
					{
2777
						if (!intMember(i, rowMarks))	/* avoid duplicates */
2778 2779 2780 2781
							rowMarks = lappendi(rowMarks, i);
						rte->checkForWrite = true;
					}
					break;
2782 2783
				}
			}
2784 2785 2786
			if (rt == NIL)
				elog(ERROR, "FOR UPDATE: relation \"%s\" not found in FROM clause",
					 relname);
2787 2788 2789
		}
	}

2790
	qry->rowMarks = rowMarks;
2791
}
Jan Wieck's avatar
Jan Wieck committed
2792 2793


2794 2795 2796
/*
 * transformFkeyCheckAttrs -
 *
2797
 *	Make sure that the attributes of a referenced table
2798
 *		belong to a unique (or primary key) constraint.
2799
 */
2800
static void
2801
transformFkeyCheckAttrs(FkConstraint *fkconstraint, Oid *pktypoid)
2802 2803 2804 2805 2806
{
	Relation	pkrel;
	List	   *indexoidlist,
			   *indexoidscan;
	int			i;
2807
	bool		found = false;
2808

2809
	/*
2810
	 * Open the referenced table
2811 2812 2813
	 */
	pkrel = heap_openr(fkconstraint->pktable_name, AccessShareLock);

2814 2815 2816 2817
	/*
	 * Get the list of index OIDs for the table from the relcache, and
	 * look up each one in the pg_index syscache for each unique one, and
	 * then compare the attributes we were given to those defined.
2818 2819 2820 2821 2822
	 */
	indexoidlist = RelationGetIndexList(pkrel);

	foreach(indexoidscan, indexoidlist)
	{
2823
		Oid			indexoid = lfirsti(indexoidscan);
2824
		HeapTuple	indexTuple;
2825 2826
		Form_pg_index indexStruct;

2827
		found = false;
2828 2829 2830
		indexTuple = SearchSysCache(INDEXRELID,
									ObjectIdGetDatum(indexoid),
									0, 0, 0);
2831
		if (!HeapTupleIsValid(indexTuple))
2832
			elog(ERROR, "transformFkeyCheckAttrs: index %u not found",
2833 2834 2835
				 indexoid);
		indexStruct = (Form_pg_index) GETSTRUCT(indexTuple);

2836 2837
		if (indexStruct->indisunique)
		{
2838 2839
			for (i = 0; i < INDEX_MAX_KEYS && indexStruct->indkey[i] != 0; i++)
				;
2840
			if (i == length(fkconstraint->pk_attrs))
2841
			{
Tom Lane's avatar
Tom Lane committed
2842
				/* go through the fkconstraint->pk_attrs list */
2843 2844 2845
				List	   *attrl;
				int	   attnum = 0;

Tom Lane's avatar
Tom Lane committed
2846
				foreach(attrl, fkconstraint->pk_attrs)
2847
				{
2848 2849
					Ident	   *attr = lfirst(attrl);

Tom Lane's avatar
Tom Lane committed
2850 2851
					found = false;
					for (i = 0; i < INDEX_MAX_KEYS && indexStruct->indkey[i] != 0; i++)
2852
					{
2853 2854
						int			pkattno = indexStruct->indkey[i];

2855 2856
						if (namestrcmp(attnumAttName(pkrel, pkattno),
									   attr->name) == 0)
2857
						{
2858 2859 2860
							pktypoid[attnum++] = attnumTypeId(pkrel, pkattno);
							found = true;
							break;
2861 2862
						}
					}
Tom Lane's avatar
Tom Lane committed
2863 2864
					if (!found)
						break;
2865 2866 2867
				}
			}
		}
2868
		ReleaseSysCache(indexTuple);
2869
		if (found)
2870
			break;
2871 2872 2873 2874 2875 2876 2877 2878 2879 2880
	}
	if (!found)
		elog(ERROR, "UNIQUE constraint matching given keys for referenced table \"%s\" not found",
			 fkconstraint->pktable_name);

	freeList(indexoidlist);
	heap_close(pkrel, AccessShareLock);
}


Jan Wieck's avatar
Jan Wieck committed
2881 2882 2883 2884 2885 2886 2887
/*
 * transformFkeyGetPrimaryKey -
 *
 *	Try to find the primary key attributes of a referenced table if
 *	the column list in the REFERENCES specification was omitted.
 */
static void
2888
transformFkeyGetPrimaryKey(FkConstraint *fkconstraint, Oid *pktypoid)
Jan Wieck's avatar
Jan Wieck committed
2889
{
2890
	Relation	pkrel;
2891 2892
	List	   *indexoidlist,
			   *indexoidscan;
2893
	HeapTuple	indexTuple = NULL;
2894 2895
	Form_pg_index indexStruct = NULL;
	int			i;
2896
	int		attnum=0;
Jan Wieck's avatar
Jan Wieck committed
2897

2898
	/*
2899
	 * Open the referenced table
Jan Wieck's avatar
Jan Wieck committed
2900 2901 2902
	 */
	pkrel = heap_openr(fkconstraint->pktable_name, AccessShareLock);

2903 2904 2905 2906
	/*
	 * Get the list of index OIDs for the table from the relcache, and
	 * look up each one in the pg_index syscache until we find one marked
	 * primary key (hopefully there isn't more than one such).
Jan Wieck's avatar
Jan Wieck committed
2907
	 */
2908
	indexoidlist = RelationGetIndexList(pkrel);
Jan Wieck's avatar
Jan Wieck committed
2909

2910
	foreach(indexoidscan, indexoidlist)
Jan Wieck's avatar
Jan Wieck committed
2911
	{
2912
		Oid			indexoid = lfirsti(indexoidscan);
2913

2914 2915 2916
		indexTuple = SearchSysCache(INDEXRELID,
									ObjectIdGetDatum(indexoid),
									0, 0, 0);
2917 2918 2919 2920
		if (!HeapTupleIsValid(indexTuple))
			elog(ERROR, "transformFkeyGetPrimaryKey: index %u not found",
				 indexoid);
		indexStruct = (Form_pg_index) GETSTRUCT(indexTuple);
Jan Wieck's avatar
Jan Wieck committed
2921 2922
		if (indexStruct->indisprimary)
			break;
2923
		ReleaseSysCache(indexTuple);
2924
		indexStruct = NULL;
Jan Wieck's avatar
Jan Wieck committed
2925 2926
	}

2927 2928
	freeList(indexoidlist);

2929
	/*
Jan Wieck's avatar
Jan Wieck committed
2930 2931
	 * Check that we found it
	 */
2932
	if (indexStruct == NULL)
Jan Wieck's avatar
Jan Wieck committed
2933
		elog(ERROR, "PRIMARY KEY for referenced table \"%s\" not found",
2934
			 fkconstraint->pktable_name);
Jan Wieck's avatar
Jan Wieck committed
2935

2936
	/*
Jan Wieck's avatar
Jan Wieck committed
2937 2938 2939
	 * Now build the list of PK attributes from the indkey definition
	 * using the attribute names of the PK relation descriptor
	 */
2940
	for (i = 0; i < INDEX_MAX_KEYS && indexStruct->indkey[i] != 0; i++)
Jan Wieck's avatar
Jan Wieck committed
2941
	{
2942 2943 2944
		int			pkattno = indexStruct->indkey[i];
		Ident	   *pkattr = makeNode(Ident);

2945
		pkattr->name = pstrdup(NameStr(*attnumAttName(pkrel, pkattno)));
Jan Wieck's avatar
Jan Wieck committed
2946 2947
		pkattr->indirection = NIL;
		pkattr->isRel = false;
2948
		pktypoid[attnum++] = attnumTypeId(pkrel, pkattno);
Jan Wieck's avatar
Jan Wieck committed
2949 2950 2951 2952

		fkconstraint->pk_attrs = lappend(fkconstraint->pk_attrs, pkattr);
	}

2953 2954
	ReleaseSysCache(indexTuple);

Jan Wieck's avatar
Jan Wieck committed
2955 2956 2957
	heap_close(pkrel, AccessShareLock);
}

2958 2959 2960 2961 2962 2963 2964 2965 2966 2967 2968 2969 2970 2971 2972 2973 2974 2975 2976 2977 2978 2979 2980 2981 2982 2983 2984 2985 2986 2987 2988 2989 2990 2991 2992 2993 2994 2995 2996 2997 2998 2999 3000 3001 3002 3003 3004 3005 3006 3007 3008 3009 3010 3011 3012 3013 3014 3015
/*
 * relationHasPrimaryKey -
 *
 *	See whether an existing relation has a primary key.
 */
static bool
relationHasPrimaryKey(char *relname)
{
	bool		result = false;
	Relation	rel;
	List	   *indexoidlist,
			   *indexoidscan;

	rel = heap_openr(relname, AccessShareLock);

	/*
	 * Get the list of index OIDs for the table from the relcache, and
	 * look up each one in the pg_index syscache until we find one marked
	 * primary key (hopefully there isn't more than one such).
	 */
	indexoidlist = RelationGetIndexList(rel);

	foreach(indexoidscan, indexoidlist)
	{
		Oid			indexoid = lfirsti(indexoidscan);
		HeapTuple	indexTuple;

		indexTuple = SearchSysCache(INDEXRELID,
									ObjectIdGetDatum(indexoid),
									0, 0, 0);
		if (!HeapTupleIsValid(indexTuple))
			elog(ERROR, "relationHasPrimaryKey: index %u not found",
				 indexoid);
		result = ((Form_pg_index) GETSTRUCT(indexTuple))->indisprimary;
		ReleaseSysCache(indexTuple);
		if (result)
			break;
	}

	freeList(indexoidlist);

	heap_close(rel, AccessShareLock);

	return result;
}

/*
 * transformFkeyGetColType -
 *
 *	Find a referencing column by name, and return its type OID.
 *	Error if it can't be found.
 */
static Oid
transformFkeyGetColType(CreateStmtContext *cxt, char *colname)
{
	List	   *cols;
	List	   *inher;
	Oid			result;
3016
	Form_pg_attribute sysatt;
3017 3018 3019 3020 3021 3022 3023 3024 3025 3026 3027 3028 3029 3030 3031 3032 3033

	/* First look for column among the newly-created columns */
	foreach(cols, cxt->columns)
	{
		ColumnDef  *col = lfirst(cols);

		if (strcmp(col->colname, colname) == 0)
		{
			char *buff = TypeNameToInternalName(col->typename);

			result = typenameTypeId(buff);
			if (!OidIsValid(result))
				elog(ERROR, "Unable to lookup type %s",
					 col->typename->name);
			return result;
		}
	}
3034 3035 3036 3037
	/* Perhaps it's a system column name */
	sysatt = SystemAttributeByName(colname, cxt->hasoids);
	if (sysatt)
		return sysatt->atttypid;
3038 3039 3040 3041 3042 3043 3044 3045 3046 3047 3048 3049 3050 3051 3052 3053 3054 3055 3056 3057 3058 3059 3060 3061 3062 3063 3064 3065 3066 3067 3068 3069 3070 3071 3072 3073 3074 3075 3076 3077 3078 3079 3080 3081 3082 3083 3084 3085 3086
	/* Look for column among inherited columns (if CREATE TABLE case) */
	foreach(inher, cxt->inhRelnames)
	{
		Value	   *inh = lfirst(inher);
		Relation	rel;
		int			count;

		Assert(IsA(inh, String));
		rel = heap_openr(strVal(inh), AccessShareLock);
		if (rel->rd_rel->relkind != RELKIND_RELATION)
			elog(ERROR, "inherited table \"%s\" is not a relation",
				 strVal(inh));
		for (count = 0; count < rel->rd_att->natts; count++)
		{
			char	   *name = NameStr(rel->rd_att->attrs[count]->attname);

			if (strcmp(name, colname) == 0)
			{
				result = rel->rd_att->attrs[count]->atttypid;

				heap_close(rel, NoLock);
				return result;
			}
		}
		heap_close(rel, NoLock);
	}
	/* Look for column among existing columns (if ALTER TABLE case) */
	if (OidIsValid(cxt->relOid))
	{
		HeapTuple	atttuple;

		atttuple = SearchSysCache(ATTNAME,
								  ObjectIdGetDatum(cxt->relOid),
								  PointerGetDatum(colname),
								  0, 0);
		if (HeapTupleIsValid(atttuple))
		{
			result = ((Form_pg_attribute) GETSTRUCT(atttuple))->atttypid;

			ReleaseSysCache(atttuple);
			return result;
		}
	}

	elog(ERROR, "%s: column \"%s\" referenced in foreign key constraint does not exist",
		 cxt->stmtType, colname);
	return InvalidOid;			/* keep compiler quiet */
}

3087 3088 3089 3090 3091 3092 3093 3094 3095 3096 3097 3098 3099 3100 3101 3102 3103 3104
/*
 * Preprocess a list of column constraint clauses
 * to attach constraint attributes to their primary constraint nodes
 * and detect inconsistent/misplaced constraint attributes.
 *
 * NOTE: currently, attributes are only supported for FOREIGN KEY primary
 * constraints, but someday they ought to be supported for other constraints.
 */
static void
transformConstraintAttrs(List *constraintList)
{
	Node	   *lastprimarynode = NULL;
	bool		saw_deferrability = false;
	bool		saw_initially = false;
	List	   *clist;

	foreach(clist, constraintList)
	{
3105
		Node	   *node = lfirst(clist);
3106

3107
		if (!IsA(node, Constraint))
3108 3109 3110 3111 3112 3113 3114 3115
		{
			lastprimarynode = node;
			/* reset flags for new primary node */
			saw_deferrability = false;
			saw_initially = false;
		}
		else
		{
3116
			Constraint *con = (Constraint *) node;
3117 3118 3119 3120 3121

			switch (con->contype)
			{
				case CONSTR_ATTR_DEFERRABLE:
					if (lastprimarynode == NULL ||
3122
						!IsA(lastprimarynode, FkConstraint))
3123 3124 3125 3126 3127 3128 3129 3130
						elog(ERROR, "Misplaced DEFERRABLE clause");
					if (saw_deferrability)
						elog(ERROR, "Multiple DEFERRABLE/NOT DEFERRABLE clauses not allowed");
					saw_deferrability = true;
					((FkConstraint *) lastprimarynode)->deferrable = true;
					break;
				case CONSTR_ATTR_NOT_DEFERRABLE:
					if (lastprimarynode == NULL ||
3131
						!IsA(lastprimarynode, FkConstraint))
3132 3133 3134 3135 3136 3137 3138 3139 3140 3141 3142
						elog(ERROR, "Misplaced NOT DEFERRABLE clause");
					if (saw_deferrability)
						elog(ERROR, "Multiple DEFERRABLE/NOT DEFERRABLE clauses not allowed");
					saw_deferrability = true;
					((FkConstraint *) lastprimarynode)->deferrable = false;
					if (saw_initially &&
						((FkConstraint *) lastprimarynode)->initdeferred)
						elog(ERROR, "INITIALLY DEFERRED constraint must be DEFERRABLE");
					break;
				case CONSTR_ATTR_DEFERRED:
					if (lastprimarynode == NULL ||
3143
						!IsA(lastprimarynode, FkConstraint))
3144 3145 3146 3147 3148
						elog(ERROR, "Misplaced INITIALLY DEFERRED clause");
					if (saw_initially)
						elog(ERROR, "Multiple INITIALLY IMMEDIATE/DEFERRED clauses not allowed");
					saw_initially = true;
					((FkConstraint *) lastprimarynode)->initdeferred = true;
3149 3150 3151 3152 3153 3154

					/*
					 * If only INITIALLY DEFERRED appears, assume
					 * DEFERRABLE
					 */
					if (!saw_deferrability)
3155
						((FkConstraint *) lastprimarynode)->deferrable = true;
3156
					else if (!((FkConstraint *) lastprimarynode)->deferrable)
3157 3158 3159 3160
						elog(ERROR, "INITIALLY DEFERRED constraint must be DEFERRABLE");
					break;
				case CONSTR_ATTR_IMMEDIATE:
					if (lastprimarynode == NULL ||
3161
						!IsA(lastprimarynode, FkConstraint))
3162 3163 3164 3165 3166 3167 3168 3169 3170 3171 3172 3173 3174 3175 3176 3177 3178 3179
						elog(ERROR, "Misplaced INITIALLY IMMEDIATE clause");
					if (saw_initially)
						elog(ERROR, "Multiple INITIALLY IMMEDIATE/DEFERRED clauses not allowed");
					saw_initially = true;
					((FkConstraint *) lastprimarynode)->initdeferred = false;
					break;
				default:
					/* Otherwise it's not an attribute */
					lastprimarynode = node;
					/* reset flags for new primary node */
					saw_deferrability = false;
					saw_initially = false;
					break;
			}
		}
	}
}

3180 3181 3182 3183
/* Build a FromExpr node */
static FromExpr *
makeFromExpr(List *fromlist, Node *quals)
{
3184
	FromExpr   *f = makeNode(FromExpr);
3185 3186 3187 3188 3189 3190

	f->fromlist = fromlist;
	f->quals = quals;
	return f;
}

3191 3192 3193 3194 3195 3196
/*
 * Special handling of type definition for a column
 */
static void
transformColumnType(ParseState *pstate, ColumnDef *column)
{
3197
	TypeName   *typename = column->typename;
3198
	Type		ctype = typenameType(typename->name);
3199

3200
	/*
3201 3202
	 * If the column doesn't have an explicitly specified typmod, check to
	 * see if we want to insert a default length.
3203 3204 3205 3206
	 *
	 * Note that we deliberately do NOT look at array or set information
	 * here; "numeric[]" needs the same default typmod as "numeric".
	 */
3207
	if (typename->typmod == -1)
3208
	{
3209
		switch (typeTypeId(ctype))
3210
		{
3211
			case BPCHAROID:
3212
				/* "char" -> "char(1)" */
3213
				typename->typmod = VARHDRSZ + 1;
3214 3215
				break;
			case NUMERICOID:
3216
				typename->typmod = VARHDRSZ +
3217
					((NUMERIC_DEFAULT_PRECISION << 16) | NUMERIC_DEFAULT_SCALE);
3218
				break;
3219
			case BITOID:
3220 3221 3222
				/* 'bit' -> 'bit(1)' */
				typename->typmod = 1;
				break;
3223 3224
		}
	}
3225 3226

	/*
3227
	 * Is this the name of a complex type? If so, implement it as a set.
3228 3229 3230 3231
	 *
	 * XXX this is a hangover from ancient Berkeley code that probably
	 * doesn't work anymore anyway.
	 */
3232 3233 3234 3235 3236 3237 3238 3239 3240 3241 3242
	if (typeTypeRelid(ctype) != InvalidOid)
	{

		/*
		 * (Eventually add in here that the set can only contain one
		 * element.)
		 */
		typename->setof = true;
	}

	ReleaseSysCache(ctype);
3243
}