1 /*-------------------------------------------------------------------------
2  *
3  * parse_utilcmd.c
4  *	  Perform parse analysis work for various utility commands
5  *
6  * Formerly we did this work during parse_analyze() in analyze.c.  However
7  * that is fairly unsafe in the presence of querytree caching, since any
8  * database state that we depend on in making the transformations might be
9  * obsolete by the time the utility command is executed; and utility commands
10  * have no infrastructure for holding locks or rechecking plan validity.
11  * Hence these functions are now called at the start of execution of their
12  * respective utility commands.
13  *
14  * NOTE: in general we must avoid scribbling on the passed-in raw parse
15  * tree, since it might be in a plan cache.  The simplest solution is
16  * a quick copyObject() call before manipulating the query tree.
17  *
18  *
19  * Portions Copyright (c) 1996-2016, PostgreSQL Global Development Group
20  * Portions Copyright (c) 1994, Regents of the University of California
21  *
22  *	src/backend/parser/parse_utilcmd.c
23  *
24  *-------------------------------------------------------------------------
25  */
26 
27 #include "postgres.h"
28 
29 #include "access/amapi.h"
30 #include "access/htup_details.h"
31 #include "access/reloptions.h"
32 #include "access/tupconvert.h"
33 #include "catalog/dependency.h"
34 #include "catalog/heap.h"
35 #include "catalog/index.h"
36 #include "catalog/namespace.h"
37 #include "catalog/pg_am.h"
38 #include "catalog/pg_collation.h"
39 #include "catalog/pg_constraint.h"
40 #include "catalog/pg_constraint_fn.h"
41 #include "catalog/pg_opclass.h"
42 #include "catalog/pg_operator.h"
43 #include "catalog/pg_type.h"
44 #include "commands/comment.h"
45 #include "commands/defrem.h"
46 #include "commands/tablecmds.h"
47 #include "commands/tablespace.h"
48 #include "miscadmin.h"
49 #include "nodes/makefuncs.h"
50 #include "nodes/nodeFuncs.h"
51 #include "parser/analyze.h"
52 #include "parser/parse_clause.h"
53 #include "parser/parse_collate.h"
54 #include "parser/parse_expr.h"
55 #include "parser/parse_relation.h"
56 #include "parser/parse_target.h"
57 #include "parser/parse_type.h"
58 #include "parser/parse_utilcmd.h"
59 #include "parser/parser.h"
60 #include "rewrite/rewriteManip.h"
61 #include "utils/acl.h"
62 #include "utils/builtins.h"
63 #include "utils/lsyscache.h"
64 #include "utils/rel.h"
65 #include "utils/syscache.h"
66 #include "utils/typcache.h"
67 
68 
69 /* State shared by transformCreateStmt and its subroutines */
70 typedef struct
71 {
72 	ParseState *pstate;			/* overall parser state */
73 	const char *stmtType;		/* "CREATE [FOREIGN] TABLE" or "ALTER TABLE" */
74 	RangeVar   *relation;		/* relation to create */
75 	Relation	rel;			/* opened/locked rel, if ALTER */
76 	List	   *inhRelations;	/* relations to inherit from */
77 	bool		isforeign;		/* true if CREATE/ALTER FOREIGN TABLE */
78 	bool		isalter;		/* true if altering existing table */
79 	bool		hasoids;		/* does relation have an OID column? */
80 	List	   *columns;		/* ColumnDef items */
81 	List	   *ckconstraints;	/* CHECK constraints */
82 	List	   *fkconstraints;	/* FOREIGN KEY constraints */
83 	List	   *ixconstraints;	/* index-creating constraints */
84 	List	   *likeclauses;	/* LIKE clauses that need post-processing */
85 	List	   *blist;			/* "before list" of things to do before
86 								 * creating the table */
87 	List	   *alist;			/* "after list" of things to do after creating
88 								 * the table */
89 	IndexStmt  *pkey;			/* PRIMARY KEY index, if any */
90 } CreateStmtContext;
91 
92 /* State shared by transformCreateSchemaStmt and its subroutines */
93 typedef struct
94 {
95 	const char *stmtType;		/* "CREATE SCHEMA" or "ALTER SCHEMA" */
96 	char	   *schemaname;		/* name of schema */
97 	RoleSpec   *authrole;		/* owner of schema */
98 	List	   *sequences;		/* CREATE SEQUENCE items */
99 	List	   *tables;			/* CREATE TABLE items */
100 	List	   *views;			/* CREATE VIEW items */
101 	List	   *indexes;		/* CREATE INDEX items */
102 	List	   *triggers;		/* CREATE TRIGGER items */
103 	List	   *grants;			/* GRANT items */
104 } CreateSchemaStmtContext;
105 
106 
107 static void transformColumnDefinition(CreateStmtContext *cxt,
108 						  ColumnDef *column);
109 static void transformTableConstraint(CreateStmtContext *cxt,
110 						 Constraint *constraint);
111 static void transformTableLikeClause(CreateStmtContext *cxt,
112 						 TableLikeClause *table_like_clause);
113 static void transformOfType(CreateStmtContext *cxt,
114 				TypeName *ofTypename);
115 static IndexStmt *generateClonedIndexStmt(RangeVar *heapRel,
116 						Relation source_idx,
117 						const AttrNumber *attmap, int attmap_length);
118 static List *get_collation(Oid collation, Oid actual_datatype);
119 static List *get_opclass(Oid opclass, Oid actual_datatype);
120 static void transformIndexConstraints(CreateStmtContext *cxt);
121 static IndexStmt *transformIndexConstraint(Constraint *constraint,
122 						 CreateStmtContext *cxt);
123 static void transformFKConstraints(CreateStmtContext *cxt,
124 					   bool skipValidation,
125 					   bool isAddConstraint);
126 static void transformCheckConstraints(CreateStmtContext *cxt,
127 						  bool skipValidation);
128 static void transformConstraintAttrs(CreateStmtContext *cxt,
129 						 List *constraintList);
130 static void transformColumnType(CreateStmtContext *cxt, ColumnDef *column);
131 static void setSchemaName(char *context_schema, char **stmt_schema_name);
132 
133 
134 /*
135  * transformCreateStmt -
136  *	  parse analysis for CREATE TABLE
137  *
138  * Returns a List of utility commands to be done in sequence.  One of these
139  * will be the transformed CreateStmt, but there may be additional actions
140  * to be done before and after the actual DefineRelation() call.
141  * In addition to normal utility commands such as AlterTableStmt and
142  * IndexStmt, the result list may contain TableLikeClause(s), representing
143  * the need to perform additional parse analysis after DefineRelation().
144  *
145  * SQL allows constraints to be scattered all over, so thumb through
146  * the columns and collect all constraints into one place.
147  * If there are any implied indices (e.g. UNIQUE or PRIMARY KEY)
148  * then expand those into multiple IndexStmt blocks.
149  *	  - thomas 1997-12-02
150  */
151 List *
transformCreateStmt(CreateStmt * stmt,const char * queryString)152 transformCreateStmt(CreateStmt *stmt, const char *queryString)
153 {
154 	ParseState *pstate;
155 	CreateStmtContext cxt;
156 	List	   *result;
157 	List	   *save_alist;
158 	ListCell   *elements;
159 	Oid			namespaceid;
160 	Oid			existing_relid;
161 	ParseCallbackState pcbstate;
162 	bool		like_found = false;
163 	bool		is_foreign_table = IsA(stmt, CreateForeignTableStmt);
164 
165 	/*
166 	 * We must not scribble on the passed-in CreateStmt, so copy it.  (This is
167 	 * overkill, but easy.)
168 	 */
169 	stmt = (CreateStmt *) copyObject(stmt);
170 
171 	/* Set up pstate */
172 	pstate = make_parsestate(NULL);
173 	pstate->p_sourcetext = queryString;
174 
175 	/*
176 	 * Look up the creation namespace.  This also checks permissions on the
177 	 * target namespace, locks it against concurrent drops, checks for a
178 	 * preexisting relation in that namespace with the same name, and updates
179 	 * stmt->relation->relpersistence if the selected namespace is temporary.
180 	 */
181 	setup_parser_errposition_callback(&pcbstate, pstate,
182 									  stmt->relation->location);
183 	namespaceid =
184 		RangeVarGetAndCheckCreationNamespace(stmt->relation, NoLock,
185 											 &existing_relid);
186 	cancel_parser_errposition_callback(&pcbstate);
187 
188 	/*
189 	 * If the relation already exists and the user specified "IF NOT EXISTS",
190 	 * bail out with a NOTICE.
191 	 */
192 	if (stmt->if_not_exists && OidIsValid(existing_relid))
193 	{
194 		ereport(NOTICE,
195 				(errcode(ERRCODE_DUPLICATE_TABLE),
196 				 errmsg("relation \"%s\" already exists, skipping",
197 						stmt->relation->relname)));
198 		return NIL;
199 	}
200 
201 	/*
202 	 * If the target relation name isn't schema-qualified, make it so.  This
203 	 * prevents some corner cases in which added-on rewritten commands might
204 	 * think they should apply to other relations that have the same name and
205 	 * are earlier in the search path.  But a local temp table is effectively
206 	 * specified to be in pg_temp, so no need for anything extra in that case.
207 	 */
208 	if (stmt->relation->schemaname == NULL
209 		&& stmt->relation->relpersistence != RELPERSISTENCE_TEMP)
210 		stmt->relation->schemaname = get_namespace_name(namespaceid);
211 
212 	/* Set up CreateStmtContext */
213 	cxt.pstate = pstate;
214 	if (IsA(stmt, CreateForeignTableStmt))
215 	{
216 		cxt.stmtType = "CREATE FOREIGN TABLE";
217 		cxt.isforeign = true;
218 	}
219 	else
220 	{
221 		cxt.stmtType = "CREATE TABLE";
222 		cxt.isforeign = false;
223 	}
224 	cxt.relation = stmt->relation;
225 	cxt.rel = NULL;
226 	cxt.inhRelations = stmt->inhRelations;
227 	cxt.isalter = false;
228 	cxt.columns = NIL;
229 	cxt.ckconstraints = NIL;
230 	cxt.fkconstraints = NIL;
231 	cxt.ixconstraints = NIL;
232 	cxt.likeclauses = NIL;
233 	cxt.blist = NIL;
234 	cxt.alist = NIL;
235 	cxt.pkey = NULL;
236 
237 	/*
238 	 * Notice that we allow OIDs here only for plain tables, even though
239 	 * foreign tables also support them.  This is necessary because the
240 	 * default_with_oids GUC must apply only to plain tables and not any other
241 	 * relkind; doing otherwise would break existing pg_dump files.  We could
242 	 * allow explicit "WITH OIDS" while not allowing default_with_oids to
243 	 * affect other relkinds, but it would complicate interpretOidsOption(),
244 	 * and right now there's no WITH OIDS option in CREATE FOREIGN TABLE
245 	 * anyway.
246 	 */
247 	cxt.hasoids = interpretOidsOption(stmt->options, !cxt.isforeign);
248 
249 	Assert(!stmt->ofTypename || !stmt->inhRelations);	/* grammar enforces */
250 
251 	if (stmt->ofTypename)
252 		transformOfType(&cxt, stmt->ofTypename);
253 
254 	/*
255 	 * Run through each primary element in the table creation clause. Separate
256 	 * column defs from constraints, and do preliminary analysis.
257 	 */
258 	foreach(elements, stmt->tableElts)
259 	{
260 		Node	   *element = lfirst(elements);
261 
262 		switch (nodeTag(element))
263 		{
264 			case T_ColumnDef:
265 				transformColumnDefinition(&cxt, (ColumnDef *) element);
266 				break;
267 
268 			case T_Constraint:
269 				transformTableConstraint(&cxt, (Constraint *) element);
270 				break;
271 
272 			case T_TableLikeClause:
273 				like_found = true;
274 				transformTableLikeClause(&cxt, (TableLikeClause *) element);
275 				break;
276 
277 			default:
278 				elog(ERROR, "unrecognized node type: %d",
279 					 (int) nodeTag(element));
280 				break;
281 		}
282 	}
283 
284 	/*
285 	 * If we had any LIKE tables, they may require creation of an OID column
286 	 * even though the command's own WITH clause didn't ask for one (or,
287 	 * perhaps, even specifically rejected having one).  Insert a WITH option
288 	 * to ensure that happens.  We prepend to the list because the first oid
289 	 * option will be honored, and we want to override anything already there.
290 	 * (But note that DefineRelation will override this again to add an OID
291 	 * column if one appears in an inheritance parent table.)
292 	 */
293 	if (like_found && cxt.hasoids)
294 		stmt->options = lcons(makeDefElem("oids",
295 										  (Node *) makeInteger(true)),
296 							  stmt->options);
297 
298 	/*
299 	 * transformIndexConstraints wants cxt.alist to contain only index
300 	 * statements, so transfer anything we already have into save_alist.
301 	 */
302 	save_alist = cxt.alist;
303 	cxt.alist = NIL;
304 
305 	Assert(stmt->constraints == NIL);
306 
307 	/*
308 	 * Postprocess constraints that give rise to index definitions.
309 	 */
310 	transformIndexConstraints(&cxt);
311 
312 	/*
313 	 * Re-consideration of LIKE clauses should happen after creation of
314 	 * indexes, but before creation of foreign keys.  This order is critical
315 	 * because a LIKE clause may attempt to create a primary key.  If there's
316 	 * also a pkey in the main CREATE TABLE list, creation of that will not
317 	 * check for a duplicate at runtime (since index_check_primary_key()
318 	 * expects that we rejected dups here).  Creation of the LIKE-generated
319 	 * pkey behaves like ALTER TABLE ADD, so it will check, but obviously that
320 	 * only works if it happens second.  On the other hand, we want to make
321 	 * pkeys before foreign key constraints, in case the user tries to make a
322 	 * self-referential FK.
323 	 */
324 	cxt.alist = list_concat(cxt.alist, cxt.likeclauses);
325 
326 	/*
327 	 * Postprocess foreign-key constraints.
328 	 */
329 	transformFKConstraints(&cxt, true, false);
330 
331 	/*
332 	 * Postprocess check constraints.
333 	 */
334 	transformCheckConstraints(&cxt, !is_foreign_table ? true : false);
335 
336 	/*
337 	 * Output results.
338 	 */
339 	stmt->tableElts = cxt.columns;
340 	stmt->constraints = cxt.ckconstraints;
341 
342 	result = lappend(cxt.blist, stmt);
343 	result = list_concat(result, cxt.alist);
344 	result = list_concat(result, save_alist);
345 
346 	return result;
347 }
348 
349 /*
350  * transformColumnDefinition -
351  *		transform a single ColumnDef within CREATE TABLE
352  *		Also used in ALTER TABLE ADD COLUMN
353  */
354 static void
transformColumnDefinition(CreateStmtContext * cxt,ColumnDef * column)355 transformColumnDefinition(CreateStmtContext *cxt, ColumnDef *column)
356 {
357 	bool		is_serial;
358 	bool		saw_nullable;
359 	bool		saw_default;
360 	Constraint *constraint;
361 	ListCell   *clist;
362 
363 	cxt->columns = lappend(cxt->columns, column);
364 
365 	/* Check for SERIAL pseudo-types */
366 	is_serial = false;
367 	if (column->typeName
368 		&& list_length(column->typeName->names) == 1
369 		&& !column->typeName->pct_type)
370 	{
371 		char	   *typname = strVal(linitial(column->typeName->names));
372 
373 		if (strcmp(typname, "smallserial") == 0 ||
374 			strcmp(typname, "serial2") == 0)
375 		{
376 			is_serial = true;
377 			column->typeName->names = NIL;
378 			column->typeName->typeOid = INT2OID;
379 		}
380 		else if (strcmp(typname, "serial") == 0 ||
381 				 strcmp(typname, "serial4") == 0)
382 		{
383 			is_serial = true;
384 			column->typeName->names = NIL;
385 			column->typeName->typeOid = INT4OID;
386 		}
387 		else if (strcmp(typname, "bigserial") == 0 ||
388 				 strcmp(typname, "serial8") == 0)
389 		{
390 			is_serial = true;
391 			column->typeName->names = NIL;
392 			column->typeName->typeOid = INT8OID;
393 		}
394 
395 		/*
396 		 * We have to reject "serial[]" explicitly, because once we've set
397 		 * typeid, LookupTypeName won't notice arrayBounds.  We don't need any
398 		 * special coding for serial(typmod) though.
399 		 */
400 		if (is_serial && column->typeName->arrayBounds != NIL)
401 			ereport(ERROR,
402 					(errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
403 					 errmsg("array of serial is not implemented"),
404 					 parser_errposition(cxt->pstate,
405 										column->typeName->location)));
406 	}
407 
408 	/* Do necessary work on the column type declaration */
409 	if (column->typeName)
410 		transformColumnType(cxt, column);
411 
412 	/* Special actions for SERIAL pseudo-types */
413 	if (is_serial)
414 	{
415 		Oid			snamespaceid;
416 		char	   *snamespace;
417 		char	   *sname;
418 		char	   *qstring;
419 		A_Const    *snamenode;
420 		TypeCast   *castnode;
421 		FuncCall   *funccallnode;
422 		CreateSeqStmt *seqstmt;
423 		AlterSeqStmt *altseqstmt;
424 		List	   *attnamelist;
425 
426 		/*
427 		 * Determine namespace and name to use for the sequence.
428 		 *
429 		 * Although we use ChooseRelationName, it's not guaranteed that the
430 		 * selected sequence name won't conflict; given sufficiently long
431 		 * field names, two different serial columns in the same table could
432 		 * be assigned the same sequence name, and we'd not notice since we
433 		 * aren't creating the sequence quite yet.  In practice this seems
434 		 * quite unlikely to be a problem, especially since few people would
435 		 * need two serial columns in one table.
436 		 */
437 		if (cxt->rel)
438 			snamespaceid = RelationGetNamespace(cxt->rel);
439 		else
440 		{
441 			snamespaceid = RangeVarGetCreationNamespace(cxt->relation);
442 			RangeVarAdjustRelationPersistence(cxt->relation, snamespaceid);
443 		}
444 		snamespace = get_namespace_name(snamespaceid);
445 		sname = ChooseRelationName(cxt->relation->relname,
446 								   column->colname,
447 								   "seq",
448 								   snamespaceid);
449 
450 		ereport(DEBUG1,
451 				(errmsg("%s will create implicit sequence \"%s\" for serial column \"%s.%s\"",
452 						cxt->stmtType, sname,
453 						cxt->relation->relname, column->colname)));
454 
455 		/*
456 		 * Build a CREATE SEQUENCE command to create the sequence object, and
457 		 * add it to the list of things to be done before this CREATE/ALTER
458 		 * TABLE.
459 		 */
460 		seqstmt = makeNode(CreateSeqStmt);
461 		seqstmt->sequence = makeRangeVar(snamespace, sname, -1);
462 		seqstmt->options = NIL;
463 
464 		/*
465 		 * If this is ALTER ADD COLUMN, make sure the sequence will be owned
466 		 * by the table's owner.  The current user might be someone else
467 		 * (perhaps a superuser, or someone who's only a member of the owning
468 		 * role), but the SEQUENCE OWNED BY mechanisms will bleat unless table
469 		 * and sequence have exactly the same owning role.
470 		 */
471 		if (cxt->rel)
472 			seqstmt->ownerId = cxt->rel->rd_rel->relowner;
473 		else
474 			seqstmt->ownerId = InvalidOid;
475 
476 		cxt->blist = lappend(cxt->blist, seqstmt);
477 
478 		/*
479 		 * Build an ALTER SEQUENCE ... OWNED BY command to mark the sequence
480 		 * as owned by this column, and add it to the list of things to be
481 		 * done after this CREATE/ALTER TABLE.
482 		 */
483 		altseqstmt = makeNode(AlterSeqStmt);
484 		altseqstmt->sequence = makeRangeVar(snamespace, sname, -1);
485 		attnamelist = list_make3(makeString(snamespace),
486 								 makeString(cxt->relation->relname),
487 								 makeString(column->colname));
488 		altseqstmt->options = list_make1(makeDefElem("owned_by",
489 													 (Node *) attnamelist));
490 
491 		cxt->alist = lappend(cxt->alist, altseqstmt);
492 
493 		/*
494 		 * Create appropriate constraints for SERIAL.  We do this in full,
495 		 * rather than shortcutting, so that we will detect any conflicting
496 		 * constraints the user wrote (like a different DEFAULT).
497 		 *
498 		 * Create an expression tree representing the function call
499 		 * nextval('sequencename').  We cannot reduce the raw tree to cooked
500 		 * form until after the sequence is created, but there's no need to do
501 		 * so.
502 		 */
503 		qstring = quote_qualified_identifier(snamespace, sname);
504 		snamenode = makeNode(A_Const);
505 		snamenode->val.type = T_String;
506 		snamenode->val.val.str = qstring;
507 		snamenode->location = -1;
508 		castnode = makeNode(TypeCast);
509 		castnode->typeName = SystemTypeName("regclass");
510 		castnode->arg = (Node *) snamenode;
511 		castnode->location = -1;
512 		funccallnode = makeFuncCall(SystemFuncName("nextval"),
513 									list_make1(castnode),
514 									-1);
515 		constraint = makeNode(Constraint);
516 		constraint->contype = CONSTR_DEFAULT;
517 		constraint->location = -1;
518 		constraint->raw_expr = (Node *) funccallnode;
519 		constraint->cooked_expr = NULL;
520 		column->constraints = lappend(column->constraints, constraint);
521 
522 		constraint = makeNode(Constraint);
523 		constraint->contype = CONSTR_NOTNULL;
524 		constraint->location = -1;
525 		column->constraints = lappend(column->constraints, constraint);
526 	}
527 
528 	/* Process column constraints, if any... */
529 	transformConstraintAttrs(cxt, column->constraints);
530 
531 	saw_nullable = false;
532 	saw_default = false;
533 
534 	foreach(clist, column->constraints)
535 	{
536 		constraint = lfirst(clist);
537 		Assert(IsA(constraint, Constraint));
538 
539 		switch (constraint->contype)
540 		{
541 			case CONSTR_NULL:
542 				if (saw_nullable && column->is_not_null)
543 					ereport(ERROR,
544 							(errcode(ERRCODE_SYNTAX_ERROR),
545 							 errmsg("conflicting NULL/NOT NULL declarations for column \"%s\" of table \"%s\"",
546 									column->colname, cxt->relation->relname),
547 							 parser_errposition(cxt->pstate,
548 												constraint->location)));
549 				column->is_not_null = FALSE;
550 				saw_nullable = true;
551 				break;
552 
553 			case CONSTR_NOTNULL:
554 				if (saw_nullable && !column->is_not_null)
555 					ereport(ERROR,
556 							(errcode(ERRCODE_SYNTAX_ERROR),
557 							 errmsg("conflicting NULL/NOT NULL declarations for column \"%s\" of table \"%s\"",
558 									column->colname, cxt->relation->relname),
559 							 parser_errposition(cxt->pstate,
560 												constraint->location)));
561 				column->is_not_null = TRUE;
562 				saw_nullable = true;
563 				break;
564 
565 			case CONSTR_DEFAULT:
566 				if (saw_default)
567 					ereport(ERROR,
568 							(errcode(ERRCODE_SYNTAX_ERROR),
569 							 errmsg("multiple default values specified for column \"%s\" of table \"%s\"",
570 									column->colname, cxt->relation->relname),
571 							 parser_errposition(cxt->pstate,
572 												constraint->location)));
573 				column->raw_default = constraint->raw_expr;
574 				Assert(constraint->cooked_expr == NULL);
575 				saw_default = true;
576 				break;
577 
578 			case CONSTR_CHECK:
579 				cxt->ckconstraints = lappend(cxt->ckconstraints, constraint);
580 				break;
581 
582 			case CONSTR_PRIMARY:
583 				if (cxt->isforeign)
584 					ereport(ERROR,
585 							(errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
586 							 errmsg("primary key constraints are not supported on foreign tables"),
587 							 parser_errposition(cxt->pstate,
588 												constraint->location)));
589 				/* FALL THRU */
590 
591 			case CONSTR_UNIQUE:
592 				if (cxt->isforeign)
593 					ereport(ERROR,
594 							(errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
595 							 errmsg("unique constraints are not supported on foreign tables"),
596 							 parser_errposition(cxt->pstate,
597 												constraint->location)));
598 				if (constraint->keys == NIL)
599 					constraint->keys = list_make1(makeString(column->colname));
600 				cxt->ixconstraints = lappend(cxt->ixconstraints, constraint);
601 				break;
602 
603 			case CONSTR_EXCLUSION:
604 				/* grammar does not allow EXCLUDE as a column constraint */
605 				elog(ERROR, "column exclusion constraints are not supported");
606 				break;
607 
608 			case CONSTR_FOREIGN:
609 				if (cxt->isforeign)
610 					ereport(ERROR,
611 							(errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
612 							 errmsg("foreign key constraints are not supported on foreign tables"),
613 							 parser_errposition(cxt->pstate,
614 												constraint->location)));
615 
616 				/*
617 				 * Fill in the current attribute's name and throw it into the
618 				 * list of FK constraints to be processed later.
619 				 */
620 				constraint->fk_attrs = list_make1(makeString(column->colname));
621 				cxt->fkconstraints = lappend(cxt->fkconstraints, constraint);
622 				break;
623 
624 			case CONSTR_ATTR_DEFERRABLE:
625 			case CONSTR_ATTR_NOT_DEFERRABLE:
626 			case CONSTR_ATTR_DEFERRED:
627 			case CONSTR_ATTR_IMMEDIATE:
628 				/* transformConstraintAttrs took care of these */
629 				break;
630 
631 			default:
632 				elog(ERROR, "unrecognized constraint type: %d",
633 					 constraint->contype);
634 				break;
635 		}
636 	}
637 
638 	/*
639 	 * If needed, generate ALTER FOREIGN TABLE ALTER COLUMN statement to add
640 	 * per-column foreign data wrapper options to this column after creation.
641 	 */
642 	if (column->fdwoptions != NIL)
643 	{
644 		AlterTableStmt *stmt;
645 		AlterTableCmd *cmd;
646 
647 		cmd = makeNode(AlterTableCmd);
648 		cmd->subtype = AT_AlterColumnGenericOptions;
649 		cmd->name = column->colname;
650 		cmd->def = (Node *) column->fdwoptions;
651 		cmd->behavior = DROP_RESTRICT;
652 		cmd->missing_ok = false;
653 
654 		stmt = makeNode(AlterTableStmt);
655 		stmt->relation = cxt->relation;
656 		stmt->cmds = NIL;
657 		stmt->relkind = OBJECT_FOREIGN_TABLE;
658 		stmt->cmds = lappend(stmt->cmds, cmd);
659 
660 		cxt->alist = lappend(cxt->alist, stmt);
661 	}
662 }
663 
664 /*
665  * transformTableConstraint
666  *		transform a Constraint node within CREATE TABLE or ALTER TABLE
667  */
668 static void
transformTableConstraint(CreateStmtContext * cxt,Constraint * constraint)669 transformTableConstraint(CreateStmtContext *cxt, Constraint *constraint)
670 {
671 	switch (constraint->contype)
672 	{
673 		case CONSTR_PRIMARY:
674 			if (cxt->isforeign)
675 				ereport(ERROR,
676 						(errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
677 						 errmsg("primary key constraints are not supported on foreign tables"),
678 						 parser_errposition(cxt->pstate,
679 											constraint->location)));
680 			cxt->ixconstraints = lappend(cxt->ixconstraints, constraint);
681 			break;
682 
683 		case CONSTR_UNIQUE:
684 			if (cxt->isforeign)
685 				ereport(ERROR,
686 						(errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
687 						 errmsg("unique constraints are not supported on foreign tables"),
688 						 parser_errposition(cxt->pstate,
689 											constraint->location)));
690 			cxt->ixconstraints = lappend(cxt->ixconstraints, constraint);
691 			break;
692 
693 		case CONSTR_EXCLUSION:
694 			if (cxt->isforeign)
695 				ereport(ERROR,
696 						(errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
697 						 errmsg("exclusion constraints are not supported on foreign tables"),
698 						 parser_errposition(cxt->pstate,
699 											constraint->location)));
700 			cxt->ixconstraints = lappend(cxt->ixconstraints, constraint);
701 			break;
702 
703 		case CONSTR_CHECK:
704 			cxt->ckconstraints = lappend(cxt->ckconstraints, constraint);
705 			break;
706 
707 		case CONSTR_FOREIGN:
708 			if (cxt->isforeign)
709 				ereport(ERROR,
710 						(errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
711 						 errmsg("foreign key constraints are not supported on foreign tables"),
712 						 parser_errposition(cxt->pstate,
713 											constraint->location)));
714 			cxt->fkconstraints = lappend(cxt->fkconstraints, constraint);
715 			break;
716 
717 		case CONSTR_NULL:
718 		case CONSTR_NOTNULL:
719 		case CONSTR_DEFAULT:
720 		case CONSTR_ATTR_DEFERRABLE:
721 		case CONSTR_ATTR_NOT_DEFERRABLE:
722 		case CONSTR_ATTR_DEFERRED:
723 		case CONSTR_ATTR_IMMEDIATE:
724 			elog(ERROR, "invalid context for constraint type %d",
725 				 constraint->contype);
726 			break;
727 
728 		default:
729 			elog(ERROR, "unrecognized constraint type: %d",
730 				 constraint->contype);
731 			break;
732 	}
733 }
734 
735 /*
736  * transformTableLikeClause
737  *
738  * Change the LIKE <srctable> portion of a CREATE TABLE statement into
739  * column definitions that recreate the user defined column portions of
740  * <srctable>.  Also, if there are any LIKE options that we can't fully
741  * process at this point, add the TableLikeClause to cxt->likeclauses, which
742  * will cause utility.c to call expandTableLikeClause() after the new
743  * table has been created.
744  */
745 static void
transformTableLikeClause(CreateStmtContext * cxt,TableLikeClause * table_like_clause)746 transformTableLikeClause(CreateStmtContext *cxt, TableLikeClause *table_like_clause)
747 {
748 	AttrNumber	parent_attno;
749 	Relation	relation;
750 	TupleDesc	tupleDesc;
751 	TupleConstr *constr;
752 	AclResult	aclresult;
753 	char	   *comment;
754 	ParseCallbackState pcbstate;
755 
756 	setup_parser_errposition_callback(&pcbstate, cxt->pstate,
757 									  table_like_clause->relation->location);
758 
759 	/* we could support LIKE in many cases, but worry about it another day */
760 	if (cxt->isforeign)
761 		ereport(ERROR,
762 				(errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
763 			   errmsg("LIKE is not supported for creating foreign tables")));
764 
765 	/* Open the relation referenced by the LIKE clause */
766 	relation = relation_openrv(table_like_clause->relation, AccessShareLock);
767 
768 	if (relation->rd_rel->relkind != RELKIND_RELATION &&
769 		relation->rd_rel->relkind != RELKIND_VIEW &&
770 		relation->rd_rel->relkind != RELKIND_MATVIEW &&
771 		relation->rd_rel->relkind != RELKIND_COMPOSITE_TYPE &&
772 		relation->rd_rel->relkind != RELKIND_FOREIGN_TABLE)
773 		ereport(ERROR,
774 				(errcode(ERRCODE_WRONG_OBJECT_TYPE),
775 				 errmsg("\"%s\" is not a table, view, materialized view, composite type, or foreign table",
776 						RelationGetRelationName(relation))));
777 
778 	cancel_parser_errposition_callback(&pcbstate);
779 
780 	/*
781 	 * Check for privileges
782 	 */
783 	if (relation->rd_rel->relkind == RELKIND_COMPOSITE_TYPE)
784 	{
785 		aclresult = pg_type_aclcheck(relation->rd_rel->reltype, GetUserId(),
786 									 ACL_USAGE);
787 		if (aclresult != ACLCHECK_OK)
788 			aclcheck_error(aclresult, ACL_KIND_TYPE,
789 						   RelationGetRelationName(relation));
790 	}
791 	else
792 	{
793 		aclresult = pg_class_aclcheck(RelationGetRelid(relation), GetUserId(),
794 									  ACL_SELECT);
795 		if (aclresult != ACLCHECK_OK)
796 			aclcheck_error(aclresult, ACL_KIND_CLASS,
797 						   RelationGetRelationName(relation));
798 	}
799 
800 	tupleDesc = RelationGetDescr(relation);
801 	constr = tupleDesc->constr;
802 
803 	/*
804 	 * Insert the copied attributes into the cxt for the new table definition.
805 	 * We must do this now so that they appear in the table in the relative
806 	 * position where the LIKE clause is, as required by SQL99.
807 	 */
808 	for (parent_attno = 1; parent_attno <= tupleDesc->natts;
809 		 parent_attno++)
810 	{
811 		Form_pg_attribute attribute = tupleDesc->attrs[parent_attno - 1];
812 		char	   *attributeName = NameStr(attribute->attname);
813 		ColumnDef  *def;
814 
815 		/*
816 		 * Ignore dropped columns in the parent.
817 		 */
818 		if (attribute->attisdropped)
819 			continue;
820 
821 		/*
822 		 * Create a new column, which is marked as NOT inherited.
823 		 *
824 		 * For constraints, ONLY the NOT NULL constraint is inherited by the
825 		 * new column definition per SQL99.
826 		 */
827 		def = makeNode(ColumnDef);
828 		def->colname = pstrdup(attributeName);
829 		def->typeName = makeTypeNameFromOid(attribute->atttypid,
830 											attribute->atttypmod);
831 		def->inhcount = 0;
832 		def->is_local = true;
833 		def->is_not_null = attribute->attnotnull;
834 		def->is_from_type = false;
835 		def->storage = 0;
836 		def->raw_default = NULL;
837 		def->cooked_default = NULL;
838 		def->collClause = NULL;
839 		def->collOid = attribute->attcollation;
840 		def->constraints = NIL;
841 		def->location = -1;
842 
843 		/*
844 		 * Add to column list
845 		 */
846 		cxt->columns = lappend(cxt->columns, def);
847 
848 		/*
849 		 * Copy default, if present and the default has been requested
850 		 */
851 		if (attribute->atthasdef &&
852 			(table_like_clause->options & CREATE_TABLE_LIKE_DEFAULTS))
853 		{
854 			Node	   *this_default = NULL;
855 			AttrDefault *attrdef;
856 			int			i;
857 
858 			/* Find default in constraint structure */
859 			Assert(constr != NULL);
860 			attrdef = constr->defval;
861 			for (i = 0; i < constr->num_defval; i++)
862 			{
863 				if (attrdef[i].adnum == parent_attno)
864 				{
865 					this_default = stringToNode(attrdef[i].adbin);
866 					break;
867 				}
868 			}
869 			Assert(this_default != NULL);
870 
871 			/*
872 			 * If default expr could contain any vars, we'd need to fix 'em,
873 			 * but it can't; so default is ready to apply to child.
874 			 */
875 
876 			def->cooked_default = this_default;
877 		}
878 
879 		/* Likewise, copy storage if requested */
880 		if (table_like_clause->options & CREATE_TABLE_LIKE_STORAGE)
881 			def->storage = attribute->attstorage;
882 		else
883 			def->storage = 0;
884 
885 		/* Likewise, copy comment if requested */
886 		if ((table_like_clause->options & CREATE_TABLE_LIKE_COMMENTS) &&
887 			(comment = GetComment(attribute->attrelid,
888 								  RelationRelationId,
889 								  attribute->attnum)) != NULL)
890 		{
891 			CommentStmt *stmt = makeNode(CommentStmt);
892 
893 			stmt->objtype = OBJECT_COLUMN;
894 			stmt->objname = list_make3(makeString(cxt->relation->schemaname),
895 									   makeString(cxt->relation->relname),
896 									   makeString(def->colname));
897 			stmt->objargs = NIL;
898 			stmt->comment = comment;
899 
900 			cxt->alist = lappend(cxt->alist, stmt);
901 		}
902 	}
903 
904 	/* We use oids if at least one LIKE'ed table has oids. */
905 	cxt->hasoids |= relation->rd_rel->relhasoids;
906 
907 	/*
908 	 * We cannot yet deal with CHECK constraints or indexes, since we don't
909 	 * yet know what column numbers the copied columns will have in the
910 	 * finished table.  If any of those options are specified, add the LIKE
911 	 * clause to cxt->likeclauses so that expandTableLikeClause will be called
912 	 * after we do know that.  Also, remember the relation OID so that
913 	 * expandTableLikeClause is certain to open the same table.
914 	 */
915 	if (table_like_clause->options &
916 		(CREATE_TABLE_LIKE_CONSTRAINTS |
917 		 CREATE_TABLE_LIKE_INDEXES))
918 	{
919 		table_like_clause->relationOid = RelationGetRelid(relation);
920 		cxt->likeclauses = lappend(cxt->likeclauses, table_like_clause);
921 	}
922 
923 	/*
924 	 * Close the parent rel, but keep our AccessShareLock on it until xact
925 	 * commit.  That will prevent someone else from deleting or ALTERing the
926 	 * parent before we can run expandTableLikeClause.
927 	 */
928 	heap_close(relation, NoLock);
929 }
930 
931 /*
932  * expandTableLikeClause
933  *
934  * Process LIKE options that require knowing the final column numbers
935  * assigned to the new table's columns.  This executes after we have
936  * run DefineRelation for the new table.  It returns a list of utility
937  * commands that should be run to generate indexes etc.
938  */
939 List *
expandTableLikeClause(RangeVar * heapRel,TableLikeClause * table_like_clause)940 expandTableLikeClause(RangeVar *heapRel, TableLikeClause *table_like_clause)
941 {
942 	List	   *result = NIL;
943 	List	   *atsubcmds = NIL;
944 	Relation	relation;
945 	Relation	childrel;
946 	TupleDesc	tupleDesc;
947 	TupleConstr *constr;
948 	AttrNumber *attmap;
949 	char	   *comment;
950 
951 	/*
952 	 * Open the relation referenced by the LIKE clause.  We should still have
953 	 * the table lock obtained by transformTableLikeClause (and this'll throw
954 	 * an assertion failure if not).  Hence, no need to recheck privileges
955 	 * etc.  We must open the rel by OID not name, to be sure we get the same
956 	 * table.
957 	 */
958 	if (!OidIsValid(table_like_clause->relationOid))
959 		elog(ERROR, "expandTableLikeClause called on untransformed LIKE clause");
960 
961 	relation = relation_open(table_like_clause->relationOid, NoLock);
962 
963 	tupleDesc = RelationGetDescr(relation);
964 	constr = tupleDesc->constr;
965 
966 	/*
967 	 * Open the newly-created child relation; we have lock on that too.
968 	 */
969 	childrel = relation_openrv(heapRel, NoLock);
970 
971 	/*
972 	 * Construct a map from the LIKE relation's attnos to the child rel's.
973 	 * This re-checks type match etc, although it shouldn't be possible to
974 	 * have a failure since both tables are locked.
975 	 */
976 	attmap = convert_tuples_by_name_map(RelationGetDescr(childrel),
977 										tupleDesc,
978 										gettext_noop("could not convert row type"));
979 
980 	/*
981 	 * Copy CHECK constraints if requested, being careful to adjust attribute
982 	 * numbers so they match the child.
983 	 */
984 	if ((table_like_clause->options & CREATE_TABLE_LIKE_CONSTRAINTS) &&
985 		constr != NULL)
986 	{
987 		int			ccnum;
988 
989 		for (ccnum = 0; ccnum < constr->num_check; ccnum++)
990 		{
991 			char	   *ccname = constr->check[ccnum].ccname;
992 			char	   *ccbin = constr->check[ccnum].ccbin;
993 			Node	   *ccbin_node;
994 			bool		found_whole_row;
995 			Constraint *n;
996 			AlterTableCmd *atsubcmd;
997 
998 			ccbin_node = map_variable_attnos(stringToNode(ccbin),
999 											 1, 0,
1000 											 attmap, tupleDesc->natts,
1001 											 &found_whole_row);
1002 
1003 			/*
1004 			 * We reject whole-row variables because the whole point of LIKE
1005 			 * is that the new table's rowtype might later diverge from the
1006 			 * parent's.  So, while translation might be possible right now,
1007 			 * it wouldn't be possible to guarantee it would work in future.
1008 			 */
1009 			if (found_whole_row)
1010 				ereport(ERROR,
1011 						(errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
1012 						 errmsg("cannot convert whole-row table reference"),
1013 						 errdetail("Constraint \"%s\" contains a whole-row reference to table \"%s\".",
1014 								   ccname,
1015 								   RelationGetRelationName(relation))));
1016 
1017 			n = makeNode(Constraint);
1018 			n->contype = CONSTR_CHECK;
1019 			n->location = -1;
1020 			n->conname = pstrdup(ccname);
1021 			n->raw_expr = NULL;
1022 			n->cooked_expr = nodeToString(ccbin_node);
1023 
1024 			/* We can skip validation, since the new table should be empty. */
1025 			n->skip_validation = true;
1026 			n->initially_valid = true;
1027 
1028 			atsubcmd = makeNode(AlterTableCmd);
1029 			atsubcmd->subtype = AT_AddConstraint;
1030 			atsubcmd->def = (Node *) n;
1031 			atsubcmds = lappend(atsubcmds, atsubcmd);
1032 
1033 			/* Copy comment on constraint */
1034 			if ((table_like_clause->options & CREATE_TABLE_LIKE_COMMENTS) &&
1035 				(comment = GetComment(get_relation_constraint_oid(RelationGetRelid(relation),
1036 														  n->conname, false),
1037 									  ConstraintRelationId,
1038 									  0)) != NULL)
1039 			{
1040 				CommentStmt *stmt = makeNode(CommentStmt);
1041 
1042 				stmt->objtype = OBJECT_TABCONSTRAINT;
1043 				stmt->objname = list_make3(makeString(heapRel->schemaname),
1044 										   makeString(heapRel->relname),
1045 										   makeString(n->conname));
1046 				stmt->objargs = NIL;
1047 				stmt->comment = comment;
1048 
1049 				result = lappend(result, stmt);
1050 			}
1051 		}
1052 	}
1053 
1054 	/*
1055 	 * If we generated any ALTER TABLE actions above, wrap them into a single
1056 	 * ALTER TABLE command.  Stick it at the front of the result, so it runs
1057 	 * before any CommentStmts we made above.
1058 	 */
1059 	if (atsubcmds)
1060 	{
1061 		AlterTableStmt *atcmd = makeNode(AlterTableStmt);
1062 
1063 		atcmd->relation = copyObject(heapRel);
1064 		atcmd->cmds = atsubcmds;
1065 		atcmd->relkind = OBJECT_TABLE;
1066 		atcmd->missing_ok = false;
1067 		result = lcons(atcmd, result);
1068 	}
1069 
1070 	/*
1071 	 * Process indexes if required.
1072 	 */
1073 	if ((table_like_clause->options & CREATE_TABLE_LIKE_INDEXES) &&
1074 		relation->rd_rel->relhasindex)
1075 	{
1076 		List	   *parent_indexes;
1077 		ListCell   *l;
1078 
1079 		parent_indexes = RelationGetIndexList(relation);
1080 
1081 		foreach(l, parent_indexes)
1082 		{
1083 			Oid			parent_index_oid = lfirst_oid(l);
1084 			Relation	parent_index;
1085 			IndexStmt  *index_stmt;
1086 
1087 			parent_index = index_open(parent_index_oid, AccessShareLock);
1088 
1089 			/* Build CREATE INDEX statement to recreate the parent_index */
1090 			index_stmt = generateClonedIndexStmt(heapRel, parent_index,
1091 												 attmap, tupleDesc->natts);
1092 
1093 			/* Copy comment on index, if requested */
1094 			if (table_like_clause->options & CREATE_TABLE_LIKE_COMMENTS)
1095 			{
1096 				comment = GetComment(parent_index_oid, RelationRelationId, 0);
1097 
1098 				/*
1099 				 * We make use of IndexStmt's idxcomment option, so as not to
1100 				 * need to know now what name the index will have.
1101 				 */
1102 				index_stmt->idxcomment = comment;
1103 			}
1104 
1105 			result = lappend(result, index_stmt);
1106 
1107 			index_close(parent_index, AccessShareLock);
1108 		}
1109 	}
1110 
1111 	/* Done with child rel */
1112 	heap_close(childrel, NoLock);
1113 
1114 	/*
1115 	 * Close the parent rel, but keep our AccessShareLock on it until xact
1116 	 * commit.  That will prevent someone else from deleting or ALTERing the
1117 	 * parent before the child is committed.
1118 	 */
1119 	heap_close(relation, NoLock);
1120 
1121 	return result;
1122 }
1123 
1124 static void
transformOfType(CreateStmtContext * cxt,TypeName * ofTypename)1125 transformOfType(CreateStmtContext *cxt, TypeName *ofTypename)
1126 {
1127 	HeapTuple	tuple;
1128 	TupleDesc	tupdesc;
1129 	int			i;
1130 	Oid			ofTypeId;
1131 
1132 	AssertArg(ofTypename);
1133 
1134 	tuple = typenameType(NULL, ofTypename, NULL);
1135 	check_of_type(tuple);
1136 	ofTypeId = HeapTupleGetOid(tuple);
1137 	ofTypename->typeOid = ofTypeId;		/* cached for later */
1138 
1139 	tupdesc = lookup_rowtype_tupdesc(ofTypeId, -1);
1140 	for (i = 0; i < tupdesc->natts; i++)
1141 	{
1142 		Form_pg_attribute attr = tupdesc->attrs[i];
1143 		ColumnDef  *n;
1144 
1145 		if (attr->attisdropped)
1146 			continue;
1147 
1148 		n = makeNode(ColumnDef);
1149 		n->colname = pstrdup(NameStr(attr->attname));
1150 		n->typeName = makeTypeNameFromOid(attr->atttypid, attr->atttypmod);
1151 		n->inhcount = 0;
1152 		n->is_local = true;
1153 		n->is_not_null = false;
1154 		n->is_from_type = true;
1155 		n->storage = 0;
1156 		n->raw_default = NULL;
1157 		n->cooked_default = NULL;
1158 		n->collClause = NULL;
1159 		n->collOid = attr->attcollation;
1160 		n->constraints = NIL;
1161 		n->location = -1;
1162 		cxt->columns = lappend(cxt->columns, n);
1163 	}
1164 	DecrTupleDescRefCount(tupdesc);
1165 
1166 	ReleaseSysCache(tuple);
1167 }
1168 
1169 /*
1170  * Generate an IndexStmt node using information from an already existing index
1171  * "source_idx".  Attribute numbers should be adjusted according to attmap.
1172  */
1173 static IndexStmt *
generateClonedIndexStmt(RangeVar * heapRel,Relation source_idx,const AttrNumber * attmap,int attmap_length)1174 generateClonedIndexStmt(RangeVar *heapRel, Relation source_idx,
1175 						const AttrNumber *attmap, int attmap_length)
1176 {
1177 	Oid			source_relid = RelationGetRelid(source_idx);
1178 	Form_pg_attribute *attrs = RelationGetDescr(source_idx)->attrs;
1179 	HeapTuple	ht_idxrel;
1180 	HeapTuple	ht_idx;
1181 	HeapTuple	ht_am;
1182 	Form_pg_class idxrelrec;
1183 	Form_pg_index idxrec;
1184 	Form_pg_am	amrec;
1185 	oidvector  *indcollation;
1186 	oidvector  *indclass;
1187 	IndexStmt  *index;
1188 	List	   *indexprs;
1189 	ListCell   *indexpr_item;
1190 	Oid			indrelid;
1191 	int			keyno;
1192 	Oid			keycoltype;
1193 	Datum		datum;
1194 	bool		isnull;
1195 
1196 	/*
1197 	 * Fetch pg_class tuple of source index.  We can't use the copy in the
1198 	 * relcache entry because it doesn't include optional fields.
1199 	 */
1200 	ht_idxrel = SearchSysCache1(RELOID, ObjectIdGetDatum(source_relid));
1201 	if (!HeapTupleIsValid(ht_idxrel))
1202 		elog(ERROR, "cache lookup failed for relation %u", source_relid);
1203 	idxrelrec = (Form_pg_class) GETSTRUCT(ht_idxrel);
1204 
1205 	/* Fetch pg_index tuple for source index from relcache entry */
1206 	ht_idx = source_idx->rd_indextuple;
1207 	idxrec = (Form_pg_index) GETSTRUCT(ht_idx);
1208 	indrelid = idxrec->indrelid;
1209 
1210 	/* Fetch the pg_am tuple of the index' access method */
1211 	ht_am = SearchSysCache1(AMOID, ObjectIdGetDatum(idxrelrec->relam));
1212 	if (!HeapTupleIsValid(ht_am))
1213 		elog(ERROR, "cache lookup failed for access method %u",
1214 			 idxrelrec->relam);
1215 	amrec = (Form_pg_am) GETSTRUCT(ht_am);
1216 
1217 	/* Extract indcollation from the pg_index tuple */
1218 	datum = SysCacheGetAttr(INDEXRELID, ht_idx,
1219 							Anum_pg_index_indcollation, &isnull);
1220 	Assert(!isnull);
1221 	indcollation = (oidvector *) DatumGetPointer(datum);
1222 
1223 	/* Extract indclass from the pg_index tuple */
1224 	datum = SysCacheGetAttr(INDEXRELID, ht_idx,
1225 							Anum_pg_index_indclass, &isnull);
1226 	Assert(!isnull);
1227 	indclass = (oidvector *) DatumGetPointer(datum);
1228 
1229 	/* Begin building the IndexStmt */
1230 	index = makeNode(IndexStmt);
1231 	index->relation = heapRel;
1232 	index->accessMethod = pstrdup(NameStr(amrec->amname));
1233 	if (OidIsValid(idxrelrec->reltablespace))
1234 		index->tableSpace = get_tablespace_name(idxrelrec->reltablespace);
1235 	else
1236 		index->tableSpace = NULL;
1237 	index->excludeOpNames = NIL;
1238 	index->idxcomment = NULL;
1239 	index->indexOid = InvalidOid;
1240 	index->oldNode = InvalidOid;
1241 	index->unique = idxrec->indisunique;
1242 	index->primary = idxrec->indisprimary;
1243 	index->transformed = true;	/* don't need transformIndexStmt */
1244 	index->concurrent = false;
1245 	index->if_not_exists = false;
1246 
1247 	/*
1248 	 * We don't try to preserve the name of the source index; instead, just
1249 	 * let DefineIndex() choose a reasonable name.  (If we tried to preserve
1250 	 * the name, we'd get duplicate-relation-name failures unless the source
1251 	 * table was in a different schema.)
1252 	 */
1253 	index->idxname = NULL;
1254 
1255 	/*
1256 	 * If the index is marked PRIMARY or has an exclusion condition, it's
1257 	 * certainly from a constraint; else, if it's not marked UNIQUE, it
1258 	 * certainly isn't.  If it is or might be from a constraint, we have to
1259 	 * fetch the pg_constraint record.
1260 	 */
1261 	if (index->primary || index->unique || idxrec->indisexclusion)
1262 	{
1263 		Oid			constraintId = get_index_constraint(source_relid);
1264 
1265 		if (OidIsValid(constraintId))
1266 		{
1267 			HeapTuple	ht_constr;
1268 			Form_pg_constraint conrec;
1269 
1270 			ht_constr = SearchSysCache1(CONSTROID,
1271 										ObjectIdGetDatum(constraintId));
1272 			if (!HeapTupleIsValid(ht_constr))
1273 				elog(ERROR, "cache lookup failed for constraint %u",
1274 					 constraintId);
1275 			conrec = (Form_pg_constraint) GETSTRUCT(ht_constr);
1276 
1277 			index->isconstraint = true;
1278 			index->deferrable = conrec->condeferrable;
1279 			index->initdeferred = conrec->condeferred;
1280 
1281 			/* If it's an exclusion constraint, we need the operator names */
1282 			if (idxrec->indisexclusion)
1283 			{
1284 				Datum	   *elems;
1285 				int			nElems;
1286 				int			i;
1287 
1288 				Assert(conrec->contype == CONSTRAINT_EXCLUSION);
1289 				/* Extract operator OIDs from the pg_constraint tuple */
1290 				datum = SysCacheGetAttr(CONSTROID, ht_constr,
1291 										Anum_pg_constraint_conexclop,
1292 										&isnull);
1293 				if (isnull)
1294 					elog(ERROR, "null conexclop for constraint %u",
1295 						 constraintId);
1296 
1297 				deconstruct_array(DatumGetArrayTypeP(datum),
1298 								  OIDOID, sizeof(Oid), true, 'i',
1299 								  &elems, NULL, &nElems);
1300 
1301 				for (i = 0; i < nElems; i++)
1302 				{
1303 					Oid			operid = DatumGetObjectId(elems[i]);
1304 					HeapTuple	opertup;
1305 					Form_pg_operator operform;
1306 					char	   *oprname;
1307 					char	   *nspname;
1308 					List	   *namelist;
1309 
1310 					opertup = SearchSysCache1(OPEROID,
1311 											  ObjectIdGetDatum(operid));
1312 					if (!HeapTupleIsValid(opertup))
1313 						elog(ERROR, "cache lookup failed for operator %u",
1314 							 operid);
1315 					operform = (Form_pg_operator) GETSTRUCT(opertup);
1316 					oprname = pstrdup(NameStr(operform->oprname));
1317 					/* For simplicity we always schema-qualify the op name */
1318 					nspname = get_namespace_name(operform->oprnamespace);
1319 					namelist = list_make2(makeString(nspname),
1320 										  makeString(oprname));
1321 					index->excludeOpNames = lappend(index->excludeOpNames,
1322 													namelist);
1323 					ReleaseSysCache(opertup);
1324 				}
1325 			}
1326 
1327 			ReleaseSysCache(ht_constr);
1328 		}
1329 		else
1330 			index->isconstraint = false;
1331 	}
1332 	else
1333 		index->isconstraint = false;
1334 
1335 	/* Get the index expressions, if any */
1336 	datum = SysCacheGetAttr(INDEXRELID, ht_idx,
1337 							Anum_pg_index_indexprs, &isnull);
1338 	if (!isnull)
1339 	{
1340 		char	   *exprsString;
1341 
1342 		exprsString = TextDatumGetCString(datum);
1343 		indexprs = (List *) stringToNode(exprsString);
1344 	}
1345 	else
1346 		indexprs = NIL;
1347 
1348 	/* Build the list of IndexElem */
1349 	index->indexParams = NIL;
1350 
1351 	indexpr_item = list_head(indexprs);
1352 	for (keyno = 0; keyno < idxrec->indnatts; keyno++)
1353 	{
1354 		IndexElem  *iparam;
1355 		AttrNumber	attnum = idxrec->indkey.values[keyno];
1356 		int16		opt = source_idx->rd_indoption[keyno];
1357 
1358 		iparam = makeNode(IndexElem);
1359 
1360 		if (AttributeNumberIsValid(attnum))
1361 		{
1362 			/* Simple index column */
1363 			char	   *attname;
1364 
1365 			attname = get_relid_attribute_name(indrelid, attnum);
1366 			keycoltype = get_atttype(indrelid, attnum);
1367 
1368 			iparam->name = attname;
1369 			iparam->expr = NULL;
1370 		}
1371 		else
1372 		{
1373 			/* Expressional index */
1374 			Node	   *indexkey;
1375 			bool		found_whole_row;
1376 
1377 			if (indexpr_item == NULL)
1378 				elog(ERROR, "too few entries in indexprs list");
1379 			indexkey = (Node *) lfirst(indexpr_item);
1380 			indexpr_item = lnext(indexpr_item);
1381 
1382 			/* Adjust Vars to match new table's column numbering */
1383 			indexkey = map_variable_attnos(indexkey,
1384 										   1, 0,
1385 										   attmap, attmap_length,
1386 										   &found_whole_row);
1387 
1388 			/* As in transformTableLikeClause, reject whole-row variables */
1389 			if (found_whole_row)
1390 				ereport(ERROR,
1391 						(errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
1392 						 errmsg("cannot convert whole-row table reference"),
1393 						 errdetail("Index \"%s\" contains a whole-row table reference.",
1394 								   RelationGetRelationName(source_idx))));
1395 
1396 			iparam->name = NULL;
1397 			iparam->expr = indexkey;
1398 
1399 			keycoltype = exprType(indexkey);
1400 		}
1401 
1402 		/* Copy the original index column name */
1403 		iparam->indexcolname = pstrdup(NameStr(attrs[keyno]->attname));
1404 
1405 		/* Add the collation name, if non-default */
1406 		iparam->collation = get_collation(indcollation->values[keyno], keycoltype);
1407 
1408 		/* Add the operator class name, if non-default */
1409 		iparam->opclass = get_opclass(indclass->values[keyno], keycoltype);
1410 
1411 		iparam->ordering = SORTBY_DEFAULT;
1412 		iparam->nulls_ordering = SORTBY_NULLS_DEFAULT;
1413 
1414 		/* Adjust options if necessary */
1415 		if (source_idx->rd_amroutine->amcanorder)
1416 		{
1417 			/*
1418 			 * If it supports sort ordering, copy DESC and NULLS opts. Don't
1419 			 * set non-default settings unnecessarily, though, so as to
1420 			 * improve the chance of recognizing equivalence to constraint
1421 			 * indexes.
1422 			 */
1423 			if (opt & INDOPTION_DESC)
1424 			{
1425 				iparam->ordering = SORTBY_DESC;
1426 				if ((opt & INDOPTION_NULLS_FIRST) == 0)
1427 					iparam->nulls_ordering = SORTBY_NULLS_LAST;
1428 			}
1429 			else
1430 			{
1431 				if (opt & INDOPTION_NULLS_FIRST)
1432 					iparam->nulls_ordering = SORTBY_NULLS_FIRST;
1433 			}
1434 		}
1435 
1436 		index->indexParams = lappend(index->indexParams, iparam);
1437 	}
1438 
1439 	/* Copy reloptions if any */
1440 	datum = SysCacheGetAttr(RELOID, ht_idxrel,
1441 							Anum_pg_class_reloptions, &isnull);
1442 	if (!isnull)
1443 		index->options = untransformRelOptions(datum);
1444 
1445 	/* If it's a partial index, decompile and append the predicate */
1446 	datum = SysCacheGetAttr(INDEXRELID, ht_idx,
1447 							Anum_pg_index_indpred, &isnull);
1448 	if (!isnull)
1449 	{
1450 		char	   *pred_str;
1451 		Node	   *pred_tree;
1452 		bool		found_whole_row;
1453 
1454 		/* Convert text string to node tree */
1455 		pred_str = TextDatumGetCString(datum);
1456 		pred_tree = (Node *) stringToNode(pred_str);
1457 
1458 		/* Adjust Vars to match new table's column numbering */
1459 		pred_tree = map_variable_attnos(pred_tree,
1460 										1, 0,
1461 										attmap, attmap_length,
1462 										&found_whole_row);
1463 
1464 		/* As in transformTableLikeClause, reject whole-row variables */
1465 		if (found_whole_row)
1466 			ereport(ERROR,
1467 					(errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
1468 					 errmsg("cannot convert whole-row table reference"),
1469 			  errdetail("Index \"%s\" contains a whole-row table reference.",
1470 						RelationGetRelationName(source_idx))));
1471 
1472 		index->whereClause = pred_tree;
1473 	}
1474 
1475 	/* Clean up */
1476 	ReleaseSysCache(ht_idxrel);
1477 	ReleaseSysCache(ht_am);
1478 
1479 	return index;
1480 }
1481 
1482 /*
1483  * get_collation		- fetch qualified name of a collation
1484  *
1485  * If collation is InvalidOid or is the default for the given actual_datatype,
1486  * then the return value is NIL.
1487  */
1488 static List *
get_collation(Oid collation,Oid actual_datatype)1489 get_collation(Oid collation, Oid actual_datatype)
1490 {
1491 	List	   *result;
1492 	HeapTuple	ht_coll;
1493 	Form_pg_collation coll_rec;
1494 	char	   *nsp_name;
1495 	char	   *coll_name;
1496 
1497 	if (!OidIsValid(collation))
1498 		return NIL;				/* easy case */
1499 	if (collation == get_typcollation(actual_datatype))
1500 		return NIL;				/* just let it default */
1501 
1502 	ht_coll = SearchSysCache1(COLLOID, ObjectIdGetDatum(collation));
1503 	if (!HeapTupleIsValid(ht_coll))
1504 		elog(ERROR, "cache lookup failed for collation %u", collation);
1505 	coll_rec = (Form_pg_collation) GETSTRUCT(ht_coll);
1506 
1507 	/* For simplicity, we always schema-qualify the name */
1508 	nsp_name = get_namespace_name(coll_rec->collnamespace);
1509 	coll_name = pstrdup(NameStr(coll_rec->collname));
1510 	result = list_make2(makeString(nsp_name), makeString(coll_name));
1511 
1512 	ReleaseSysCache(ht_coll);
1513 	return result;
1514 }
1515 
1516 /*
1517  * get_opclass			- fetch qualified name of an index operator class
1518  *
1519  * If the opclass is the default for the given actual_datatype, then
1520  * the return value is NIL.
1521  */
1522 static List *
get_opclass(Oid opclass,Oid actual_datatype)1523 get_opclass(Oid opclass, Oid actual_datatype)
1524 {
1525 	List	   *result = NIL;
1526 	HeapTuple	ht_opc;
1527 	Form_pg_opclass opc_rec;
1528 
1529 	ht_opc = SearchSysCache1(CLAOID, ObjectIdGetDatum(opclass));
1530 	if (!HeapTupleIsValid(ht_opc))
1531 		elog(ERROR, "cache lookup failed for opclass %u", opclass);
1532 	opc_rec = (Form_pg_opclass) GETSTRUCT(ht_opc);
1533 
1534 	if (GetDefaultOpClass(actual_datatype, opc_rec->opcmethod) != opclass)
1535 	{
1536 		/* For simplicity, we always schema-qualify the name */
1537 		char	   *nsp_name = get_namespace_name(opc_rec->opcnamespace);
1538 		char	   *opc_name = pstrdup(NameStr(opc_rec->opcname));
1539 
1540 		result = list_make2(makeString(nsp_name), makeString(opc_name));
1541 	}
1542 
1543 	ReleaseSysCache(ht_opc);
1544 	return result;
1545 }
1546 
1547 
1548 /*
1549  * transformIndexConstraints
1550  *		Handle UNIQUE, PRIMARY KEY, EXCLUDE constraints, which create indexes.
1551  *		We also merge in any index definitions arising from
1552  *		LIKE ... INCLUDING INDEXES.
1553  */
1554 static void
transformIndexConstraints(CreateStmtContext * cxt)1555 transformIndexConstraints(CreateStmtContext *cxt)
1556 {
1557 	IndexStmt  *index;
1558 	List	   *indexlist = NIL;
1559 	ListCell   *lc;
1560 
1561 	/*
1562 	 * Run through the constraints that need to generate an index. For PRIMARY
1563 	 * KEY, mark each column as NOT NULL and create an index. For UNIQUE or
1564 	 * EXCLUDE, create an index as for PRIMARY KEY, but do not insist on NOT
1565 	 * NULL.
1566 	 */
1567 	foreach(lc, cxt->ixconstraints)
1568 	{
1569 		Constraint *constraint = (Constraint *) lfirst(lc);
1570 
1571 		Assert(IsA(constraint, Constraint));
1572 		Assert(constraint->contype == CONSTR_PRIMARY ||
1573 			   constraint->contype == CONSTR_UNIQUE ||
1574 			   constraint->contype == CONSTR_EXCLUSION);
1575 
1576 		index = transformIndexConstraint(constraint, cxt);
1577 
1578 		indexlist = lappend(indexlist, index);
1579 	}
1580 
1581 	/*
1582 	 * Scan the index list and remove any redundant index specifications. This
1583 	 * can happen if, for instance, the user writes UNIQUE PRIMARY KEY. A
1584 	 * strict reading of SQL would suggest raising an error instead, but that
1585 	 * strikes me as too anal-retentive. - tgl 2001-02-14
1586 	 *
1587 	 * XXX in ALTER TABLE case, it'd be nice to look for duplicate
1588 	 * pre-existing indexes, too.
1589 	 */
1590 	Assert(cxt->alist == NIL);
1591 	if (cxt->pkey != NULL)
1592 	{
1593 		/* Make sure we keep the PKEY index in preference to others... */
1594 		cxt->alist = list_make1(cxt->pkey);
1595 	}
1596 
1597 	foreach(lc, indexlist)
1598 	{
1599 		bool		keep = true;
1600 		ListCell   *k;
1601 
1602 		index = lfirst(lc);
1603 
1604 		/* if it's pkey, it's already in cxt->alist */
1605 		if (index == cxt->pkey)
1606 			continue;
1607 
1608 		foreach(k, cxt->alist)
1609 		{
1610 			IndexStmt  *priorindex = lfirst(k);
1611 
1612 			if (equal(index->indexParams, priorindex->indexParams) &&
1613 				equal(index->whereClause, priorindex->whereClause) &&
1614 				equal(index->excludeOpNames, priorindex->excludeOpNames) &&
1615 				strcmp(index->accessMethod, priorindex->accessMethod) == 0 &&
1616 				index->deferrable == priorindex->deferrable &&
1617 				index->initdeferred == priorindex->initdeferred)
1618 			{
1619 				priorindex->unique |= index->unique;
1620 
1621 				/*
1622 				 * If the prior index is as yet unnamed, and this one is
1623 				 * named, then transfer the name to the prior index. This
1624 				 * ensures that if we have named and unnamed constraints,
1625 				 * we'll use (at least one of) the names for the index.
1626 				 */
1627 				if (priorindex->idxname == NULL)
1628 					priorindex->idxname = index->idxname;
1629 				keep = false;
1630 				break;
1631 			}
1632 		}
1633 
1634 		if (keep)
1635 			cxt->alist = lappend(cxt->alist, index);
1636 	}
1637 }
1638 
1639 /*
1640  * transformIndexConstraint
1641  *		Transform one UNIQUE, PRIMARY KEY, or EXCLUDE constraint for
1642  *		transformIndexConstraints.
1643  */
1644 static IndexStmt *
transformIndexConstraint(Constraint * constraint,CreateStmtContext * cxt)1645 transformIndexConstraint(Constraint *constraint, CreateStmtContext *cxt)
1646 {
1647 	IndexStmt  *index;
1648 	ListCell   *lc;
1649 
1650 	index = makeNode(IndexStmt);
1651 
1652 	index->unique = (constraint->contype != CONSTR_EXCLUSION);
1653 	index->primary = (constraint->contype == CONSTR_PRIMARY);
1654 	if (index->primary)
1655 	{
1656 		if (cxt->pkey != NULL)
1657 			ereport(ERROR,
1658 					(errcode(ERRCODE_INVALID_TABLE_DEFINITION),
1659 			 errmsg("multiple primary keys for table \"%s\" are not allowed",
1660 					cxt->relation->relname),
1661 					 parser_errposition(cxt->pstate, constraint->location)));
1662 		cxt->pkey = index;
1663 
1664 		/*
1665 		 * In ALTER TABLE case, a primary index might already exist, but
1666 		 * DefineIndex will check for it.
1667 		 */
1668 	}
1669 	index->isconstraint = true;
1670 	index->deferrable = constraint->deferrable;
1671 	index->initdeferred = constraint->initdeferred;
1672 
1673 	if (constraint->conname != NULL)
1674 		index->idxname = pstrdup(constraint->conname);
1675 	else
1676 		index->idxname = NULL;	/* DefineIndex will choose name */
1677 
1678 	index->relation = cxt->relation;
1679 	index->accessMethod = constraint->access_method ? constraint->access_method : DEFAULT_INDEX_TYPE;
1680 	index->options = constraint->options;
1681 	index->tableSpace = constraint->indexspace;
1682 	index->whereClause = constraint->where_clause;
1683 	index->indexParams = NIL;
1684 	index->excludeOpNames = NIL;
1685 	index->idxcomment = NULL;
1686 	index->indexOid = InvalidOid;
1687 	index->oldNode = InvalidOid;
1688 	index->transformed = false;
1689 	index->concurrent = false;
1690 	index->if_not_exists = false;
1691 
1692 	/*
1693 	 * If it's ALTER TABLE ADD CONSTRAINT USING INDEX, look up the index and
1694 	 * verify it's usable, then extract the implied column name list.  (We
1695 	 * will not actually need the column name list at runtime, but we need it
1696 	 * now to check for duplicate column entries below.)
1697 	 */
1698 	if (constraint->indexname != NULL)
1699 	{
1700 		char	   *index_name = constraint->indexname;
1701 		Relation	heap_rel = cxt->rel;
1702 		Oid			index_oid;
1703 		Relation	index_rel;
1704 		Form_pg_index index_form;
1705 		oidvector  *indclass;
1706 		Datum		indclassDatum;
1707 		bool		isnull;
1708 		int			i;
1709 
1710 		/* Grammar should not allow this with explicit column list */
1711 		Assert(constraint->keys == NIL);
1712 
1713 		/* Grammar should only allow PRIMARY and UNIQUE constraints */
1714 		Assert(constraint->contype == CONSTR_PRIMARY ||
1715 			   constraint->contype == CONSTR_UNIQUE);
1716 
1717 		/* Must be ALTER, not CREATE, but grammar doesn't enforce that */
1718 		if (!cxt->isalter)
1719 			ereport(ERROR,
1720 					(errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
1721 					 errmsg("cannot use an existing index in CREATE TABLE"),
1722 					 parser_errposition(cxt->pstate, constraint->location)));
1723 
1724 		/* Look for the index in the same schema as the table */
1725 		index_oid = get_relname_relid(index_name, RelationGetNamespace(heap_rel));
1726 
1727 		if (!OidIsValid(index_oid))
1728 			ereport(ERROR,
1729 					(errcode(ERRCODE_UNDEFINED_OBJECT),
1730 					 errmsg("index \"%s\" does not exist", index_name),
1731 					 parser_errposition(cxt->pstate, constraint->location)));
1732 
1733 		/* Open the index (this will throw an error if it is not an index) */
1734 		index_rel = index_open(index_oid, AccessShareLock);
1735 		index_form = index_rel->rd_index;
1736 
1737 		/* Check that it does not have an associated constraint already */
1738 		if (OidIsValid(get_index_constraint(index_oid)))
1739 			ereport(ERROR,
1740 					(errcode(ERRCODE_OBJECT_NOT_IN_PREREQUISITE_STATE),
1741 			   errmsg("index \"%s\" is already associated with a constraint",
1742 					  index_name),
1743 					 parser_errposition(cxt->pstate, constraint->location)));
1744 
1745 		/* Perform validity checks on the index */
1746 		if (index_form->indrelid != RelationGetRelid(heap_rel))
1747 			ereport(ERROR,
1748 					(errcode(ERRCODE_OBJECT_NOT_IN_PREREQUISITE_STATE),
1749 					 errmsg("index \"%s\" does not belong to table \"%s\"",
1750 							index_name, RelationGetRelationName(heap_rel)),
1751 					 parser_errposition(cxt->pstate, constraint->location)));
1752 
1753 		if (!IndexIsValid(index_form))
1754 			ereport(ERROR,
1755 					(errcode(ERRCODE_OBJECT_NOT_IN_PREREQUISITE_STATE),
1756 					 errmsg("index \"%s\" is not valid", index_name),
1757 					 parser_errposition(cxt->pstate, constraint->location)));
1758 
1759 		if (!index_form->indisunique)
1760 			ereport(ERROR,
1761 					(errcode(ERRCODE_WRONG_OBJECT_TYPE),
1762 					 errmsg("\"%s\" is not a unique index", index_name),
1763 					 errdetail("Cannot create a primary key or unique constraint using such an index."),
1764 					 parser_errposition(cxt->pstate, constraint->location)));
1765 
1766 		if (RelationGetIndexExpressions(index_rel) != NIL)
1767 			ereport(ERROR,
1768 					(errcode(ERRCODE_WRONG_OBJECT_TYPE),
1769 					 errmsg("index \"%s\" contains expressions", index_name),
1770 					 errdetail("Cannot create a primary key or unique constraint using such an index."),
1771 					 parser_errposition(cxt->pstate, constraint->location)));
1772 
1773 		if (RelationGetIndexPredicate(index_rel) != NIL)
1774 			ereport(ERROR,
1775 					(errcode(ERRCODE_WRONG_OBJECT_TYPE),
1776 					 errmsg("\"%s\" is a partial index", index_name),
1777 					 errdetail("Cannot create a primary key or unique constraint using such an index."),
1778 					 parser_errposition(cxt->pstate, constraint->location)));
1779 
1780 		/*
1781 		 * It's probably unsafe to change a deferred index to non-deferred. (A
1782 		 * non-constraint index couldn't be deferred anyway, so this case
1783 		 * should never occur; no need to sweat, but let's check it.)
1784 		 */
1785 		if (!index_form->indimmediate && !constraint->deferrable)
1786 			ereport(ERROR,
1787 					(errcode(ERRCODE_WRONG_OBJECT_TYPE),
1788 					 errmsg("\"%s\" is a deferrable index", index_name),
1789 					 errdetail("Cannot create a non-deferrable constraint using a deferrable index."),
1790 					 parser_errposition(cxt->pstate, constraint->location)));
1791 
1792 		/*
1793 		 * Insist on it being a btree.  That's the only kind that supports
1794 		 * uniqueness at the moment anyway; but we must have an index that
1795 		 * exactly matches what you'd get from plain ADD CONSTRAINT syntax,
1796 		 * else dump and reload will produce a different index (breaking
1797 		 * pg_upgrade in particular).
1798 		 */
1799 		if (index_rel->rd_rel->relam != get_index_am_oid(DEFAULT_INDEX_TYPE, false))
1800 			ereport(ERROR,
1801 					(errcode(ERRCODE_WRONG_OBJECT_TYPE),
1802 					 errmsg("index \"%s\" is not a btree", index_name),
1803 					 parser_errposition(cxt->pstate, constraint->location)));
1804 
1805 		/* Must get indclass the hard way */
1806 		indclassDatum = SysCacheGetAttr(INDEXRELID, index_rel->rd_indextuple,
1807 										Anum_pg_index_indclass, &isnull);
1808 		Assert(!isnull);
1809 		indclass = (oidvector *) DatumGetPointer(indclassDatum);
1810 
1811 		for (i = 0; i < index_form->indnatts; i++)
1812 		{
1813 			int16		attnum = index_form->indkey.values[i];
1814 			Form_pg_attribute attform;
1815 			char	   *attname;
1816 			Oid			defopclass;
1817 
1818 			/*
1819 			 * We shouldn't see attnum == 0 here, since we already rejected
1820 			 * expression indexes.  If we do, SystemAttributeDefinition will
1821 			 * throw an error.
1822 			 */
1823 			if (attnum > 0)
1824 			{
1825 				Assert(attnum <= heap_rel->rd_att->natts);
1826 				attform = heap_rel->rd_att->attrs[attnum - 1];
1827 			}
1828 			else
1829 				attform = SystemAttributeDefinition(attnum,
1830 											   heap_rel->rd_rel->relhasoids);
1831 			attname = pstrdup(NameStr(attform->attname));
1832 
1833 			/*
1834 			 * Insist on default opclass and sort options.  While the index
1835 			 * would still work as a constraint with non-default settings, it
1836 			 * might not provide exactly the same uniqueness semantics as
1837 			 * you'd get from a normally-created constraint; and there's also
1838 			 * the dump/reload problem mentioned above.
1839 			 */
1840 			defopclass = GetDefaultOpClass(attform->atttypid,
1841 										   index_rel->rd_rel->relam);
1842 			if (indclass->values[i] != defopclass ||
1843 				index_rel->rd_indoption[i] != 0)
1844 				ereport(ERROR,
1845 						(errcode(ERRCODE_WRONG_OBJECT_TYPE),
1846 						 errmsg("index \"%s\" does not have default sorting behavior", index_name),
1847 						 errdetail("Cannot create a primary key or unique constraint using such an index."),
1848 					 parser_errposition(cxt->pstate, constraint->location)));
1849 
1850 			constraint->keys = lappend(constraint->keys, makeString(attname));
1851 		}
1852 
1853 		/* Close the index relation but keep the lock */
1854 		relation_close(index_rel, NoLock);
1855 
1856 		index->indexOid = index_oid;
1857 	}
1858 
1859 	/*
1860 	 * If it's an EXCLUDE constraint, the grammar returns a list of pairs of
1861 	 * IndexElems and operator names.  We have to break that apart into
1862 	 * separate lists.
1863 	 */
1864 	if (constraint->contype == CONSTR_EXCLUSION)
1865 	{
1866 		foreach(lc, constraint->exclusions)
1867 		{
1868 			List	   *pair = (List *) lfirst(lc);
1869 			IndexElem  *elem;
1870 			List	   *opname;
1871 
1872 			Assert(list_length(pair) == 2);
1873 			elem = (IndexElem *) linitial(pair);
1874 			Assert(IsA(elem, IndexElem));
1875 			opname = (List *) lsecond(pair);
1876 			Assert(IsA(opname, List));
1877 
1878 			index->indexParams = lappend(index->indexParams, elem);
1879 			index->excludeOpNames = lappend(index->excludeOpNames, opname);
1880 		}
1881 
1882 		return index;
1883 	}
1884 
1885 	/*
1886 	 * For UNIQUE and PRIMARY KEY, we just have a list of column names.
1887 	 *
1888 	 * Make sure referenced keys exist.  If we are making a PRIMARY KEY index,
1889 	 * also make sure they are NOT NULL, if possible. (Although we could leave
1890 	 * it to DefineIndex to mark the columns NOT NULL, it's more efficient to
1891 	 * get it right the first time.)
1892 	 */
1893 	foreach(lc, constraint->keys)
1894 	{
1895 		char	   *key = strVal(lfirst(lc));
1896 		bool		found = false;
1897 		ColumnDef  *column = NULL;
1898 		ListCell   *columns;
1899 		IndexElem  *iparam;
1900 
1901 		foreach(columns, cxt->columns)
1902 		{
1903 			column = (ColumnDef *) lfirst(columns);
1904 			Assert(IsA(column, ColumnDef));
1905 			if (strcmp(column->colname, key) == 0)
1906 			{
1907 				found = true;
1908 				break;
1909 			}
1910 		}
1911 		if (found)
1912 		{
1913 			/* found column in the new table; force it to be NOT NULL */
1914 			if (constraint->contype == CONSTR_PRIMARY)
1915 				column->is_not_null = TRUE;
1916 		}
1917 		else if (SystemAttributeByName(key, cxt->hasoids) != NULL)
1918 		{
1919 			/*
1920 			 * column will be a system column in the new table, so accept it.
1921 			 * System columns can't ever be null, so no need to worry about
1922 			 * PRIMARY/NOT NULL constraint.
1923 			 */
1924 			found = true;
1925 		}
1926 		else if (cxt->inhRelations)
1927 		{
1928 			/* try inherited tables */
1929 			ListCell   *inher;
1930 
1931 			foreach(inher, cxt->inhRelations)
1932 			{
1933 				RangeVar   *inh = (RangeVar *) lfirst(inher);
1934 				Relation	rel;
1935 				int			count;
1936 
1937 				Assert(IsA(inh, RangeVar));
1938 				rel = heap_openrv(inh, AccessShareLock);
1939 				/* check user requested inheritance from valid relkind */
1940 				if (rel->rd_rel->relkind != RELKIND_RELATION &&
1941 					rel->rd_rel->relkind != RELKIND_FOREIGN_TABLE)
1942 					ereport(ERROR,
1943 							(errcode(ERRCODE_WRONG_OBJECT_TYPE),
1944 							 errmsg("inherited relation \"%s\" is not a table or foreign table",
1945 									inh->relname)));
1946 				for (count = 0; count < rel->rd_att->natts; count++)
1947 				{
1948 					Form_pg_attribute inhattr = rel->rd_att->attrs[count];
1949 					char	   *inhname = NameStr(inhattr->attname);
1950 
1951 					if (inhattr->attisdropped)
1952 						continue;
1953 					if (strcmp(key, inhname) == 0)
1954 					{
1955 						found = true;
1956 
1957 						/*
1958 						 * We currently have no easy way to force an inherited
1959 						 * column to be NOT NULL at creation, if its parent
1960 						 * wasn't so already. We leave it to DefineIndex to
1961 						 * fix things up in this case.
1962 						 */
1963 						break;
1964 					}
1965 				}
1966 				heap_close(rel, NoLock);
1967 				if (found)
1968 					break;
1969 			}
1970 		}
1971 
1972 		/*
1973 		 * In the ALTER TABLE case, don't complain about index keys not
1974 		 * created in the command; they may well exist already. DefineIndex
1975 		 * will complain about them if not, and will also take care of marking
1976 		 * them NOT NULL.
1977 		 */
1978 		if (!found && !cxt->isalter)
1979 			ereport(ERROR,
1980 					(errcode(ERRCODE_UNDEFINED_COLUMN),
1981 					 errmsg("column \"%s\" named in key does not exist", key),
1982 					 parser_errposition(cxt->pstate, constraint->location)));
1983 
1984 		/* Check for PRIMARY KEY(foo, foo) */
1985 		foreach(columns, index->indexParams)
1986 		{
1987 			iparam = (IndexElem *) lfirst(columns);
1988 			if (iparam->name && strcmp(key, iparam->name) == 0)
1989 			{
1990 				if (index->primary)
1991 					ereport(ERROR,
1992 							(errcode(ERRCODE_DUPLICATE_COLUMN),
1993 							 errmsg("column \"%s\" appears twice in primary key constraint",
1994 									key),
1995 					 parser_errposition(cxt->pstate, constraint->location)));
1996 				else
1997 					ereport(ERROR,
1998 							(errcode(ERRCODE_DUPLICATE_COLUMN),
1999 					errmsg("column \"%s\" appears twice in unique constraint",
2000 						   key),
2001 					 parser_errposition(cxt->pstate, constraint->location)));
2002 			}
2003 		}
2004 
2005 		/* OK, add it to the index definition */
2006 		iparam = makeNode(IndexElem);
2007 		iparam->name = pstrdup(key);
2008 		iparam->expr = NULL;
2009 		iparam->indexcolname = NULL;
2010 		iparam->collation = NIL;
2011 		iparam->opclass = NIL;
2012 		iparam->ordering = SORTBY_DEFAULT;
2013 		iparam->nulls_ordering = SORTBY_NULLS_DEFAULT;
2014 		index->indexParams = lappend(index->indexParams, iparam);
2015 	}
2016 
2017 	return index;
2018 }
2019 
2020 /*
2021  * transformCheckConstraints
2022  *		handle CHECK constraints
2023  *
2024  * Right now, there's nothing to do here when called from ALTER TABLE,
2025  * but the other constraint-transformation functions are called in both
2026  * the CREATE TABLE and ALTER TABLE paths, so do the same here, and just
2027  * don't do anything if we're not authorized to skip validation.
2028  */
2029 static void
transformCheckConstraints(CreateStmtContext * cxt,bool skipValidation)2030 transformCheckConstraints(CreateStmtContext *cxt, bool skipValidation)
2031 {
2032 	ListCell   *ckclist;
2033 
2034 	if (cxt->ckconstraints == NIL)
2035 		return;
2036 
2037 	/*
2038 	 * If creating a new table (but not a foreign table), we can safely skip
2039 	 * validation of check constraints, and nonetheless mark them valid.
2040 	 * (This will override any user-supplied NOT VALID flag.)
2041 	 */
2042 	if (skipValidation)
2043 	{
2044 		foreach(ckclist, cxt->ckconstraints)
2045 		{
2046 			Constraint *constraint = (Constraint *) lfirst(ckclist);
2047 
2048 			constraint->skip_validation = true;
2049 			constraint->initially_valid = true;
2050 		}
2051 	}
2052 }
2053 
2054 /*
2055  * transformFKConstraints
2056  *		handle FOREIGN KEY constraints
2057  */
2058 static void
transformFKConstraints(CreateStmtContext * cxt,bool skipValidation,bool isAddConstraint)2059 transformFKConstraints(CreateStmtContext *cxt,
2060 					   bool skipValidation, bool isAddConstraint)
2061 {
2062 	ListCell   *fkclist;
2063 
2064 	if (cxt->fkconstraints == NIL)
2065 		return;
2066 
2067 	/*
2068 	 * If CREATE TABLE or adding a column with NULL default, we can safely
2069 	 * skip validation of FK constraints, and nonetheless mark them valid.
2070 	 * (This will override any user-supplied NOT VALID flag.)
2071 	 */
2072 	if (skipValidation)
2073 	{
2074 		foreach(fkclist, cxt->fkconstraints)
2075 		{
2076 			Constraint *constraint = (Constraint *) lfirst(fkclist);
2077 
2078 			constraint->skip_validation = true;
2079 			constraint->initially_valid = true;
2080 		}
2081 	}
2082 
2083 	/*
2084 	 * For CREATE TABLE or ALTER TABLE ADD COLUMN, gin up an ALTER TABLE ADD
2085 	 * CONSTRAINT command to execute after the basic command is complete. (If
2086 	 * called from ADD CONSTRAINT, that routine will add the FK constraints to
2087 	 * its own subcommand list.)
2088 	 *
2089 	 * Note: the ADD CONSTRAINT command must also execute after any index
2090 	 * creation commands.  Thus, this should run after
2091 	 * transformIndexConstraints, so that the CREATE INDEX commands are
2092 	 * already in cxt->alist.  See also the handling of cxt->likeclauses.
2093 	 */
2094 	if (!isAddConstraint)
2095 	{
2096 		AlterTableStmt *alterstmt = makeNode(AlterTableStmt);
2097 
2098 		alterstmt->relation = cxt->relation;
2099 		alterstmt->cmds = NIL;
2100 		alterstmt->relkind = OBJECT_TABLE;
2101 
2102 		foreach(fkclist, cxt->fkconstraints)
2103 		{
2104 			Constraint *constraint = (Constraint *) lfirst(fkclist);
2105 			AlterTableCmd *altercmd = makeNode(AlterTableCmd);
2106 
2107 			altercmd->subtype = AT_ProcessedConstraint;
2108 			altercmd->name = NULL;
2109 			altercmd->def = (Node *) constraint;
2110 			alterstmt->cmds = lappend(alterstmt->cmds, altercmd);
2111 		}
2112 
2113 		cxt->alist = lappend(cxt->alist, alterstmt);
2114 	}
2115 }
2116 
2117 /*
2118  * transformIndexStmt - parse analysis for CREATE INDEX and ALTER TABLE
2119  *
2120  * Note: this is a no-op for an index not using either index expressions or
2121  * a predicate expression.  There are several code paths that create indexes
2122  * without bothering to call this, because they know they don't have any
2123  * such expressions to deal with.
2124  *
2125  * To avoid race conditions, it's important that this function rely only on
2126  * the passed-in relid (and not on stmt->relation) to determine the target
2127  * relation.
2128  */
2129 IndexStmt *
transformIndexStmt(Oid relid,IndexStmt * stmt,const char * queryString)2130 transformIndexStmt(Oid relid, IndexStmt *stmt, const char *queryString)
2131 {
2132 	ParseState *pstate;
2133 	RangeTblEntry *rte;
2134 	ListCell   *l;
2135 	Relation	rel;
2136 
2137 	/* Nothing to do if statement already transformed. */
2138 	if (stmt->transformed)
2139 		return stmt;
2140 
2141 	/*
2142 	 * We must not scribble on the passed-in IndexStmt, so copy it.  (This is
2143 	 * overkill, but easy.)
2144 	 */
2145 	stmt = (IndexStmt *) copyObject(stmt);
2146 
2147 	/* Set up pstate */
2148 	pstate = make_parsestate(NULL);
2149 	pstate->p_sourcetext = queryString;
2150 
2151 	/*
2152 	 * Put the parent table into the rtable so that the expressions can refer
2153 	 * to its fields without qualification.  Caller is responsible for locking
2154 	 * relation, but we still need to open it.
2155 	 */
2156 	rel = relation_open(relid, NoLock);
2157 	rte = addRangeTableEntryForRelation(pstate, rel, NULL, false, true);
2158 
2159 	/* no to join list, yes to namespaces */
2160 	addRTEtoQuery(pstate, rte, false, true, true);
2161 
2162 	/* take care of the where clause */
2163 	if (stmt->whereClause)
2164 	{
2165 		stmt->whereClause = transformWhereClause(pstate,
2166 												 stmt->whereClause,
2167 												 EXPR_KIND_INDEX_PREDICATE,
2168 												 "WHERE");
2169 		/* we have to fix its collations too */
2170 		assign_expr_collations(pstate, stmt->whereClause);
2171 	}
2172 
2173 	/* take care of any index expressions */
2174 	foreach(l, stmt->indexParams)
2175 	{
2176 		IndexElem  *ielem = (IndexElem *) lfirst(l);
2177 
2178 		if (ielem->expr)
2179 		{
2180 			/* Extract preliminary index col name before transforming expr */
2181 			if (ielem->indexcolname == NULL)
2182 				ielem->indexcolname = FigureIndexColname(ielem->expr);
2183 
2184 			/* Now do parse transformation of the expression */
2185 			ielem->expr = transformExpr(pstate, ielem->expr,
2186 										EXPR_KIND_INDEX_EXPRESSION);
2187 
2188 			/* We have to fix its collations too */
2189 			assign_expr_collations(pstate, ielem->expr);
2190 
2191 			/*
2192 			 * transformExpr() should have already rejected subqueries,
2193 			 * aggregates, and window functions, based on the EXPR_KIND_ for
2194 			 * an index expression.
2195 			 *
2196 			 * Also reject expressions returning sets; this is for consistency
2197 			 * with what transformWhereClause() checks for the predicate.
2198 			 * DefineIndex() will make more checks.
2199 			 */
2200 			if (expression_returns_set(ielem->expr))
2201 				ereport(ERROR,
2202 						(errcode(ERRCODE_DATATYPE_MISMATCH),
2203 						 errmsg("index expression cannot return a set")));
2204 		}
2205 	}
2206 
2207 	/*
2208 	 * Check that only the base rel is mentioned.  (This should be dead code
2209 	 * now that add_missing_from is history.)
2210 	 */
2211 	if (list_length(pstate->p_rtable) != 1)
2212 		ereport(ERROR,
2213 				(errcode(ERRCODE_INVALID_COLUMN_REFERENCE),
2214 				 errmsg("index expressions and predicates can refer only to the table being indexed")));
2215 
2216 	free_parsestate(pstate);
2217 
2218 	/* Close relation */
2219 	heap_close(rel, NoLock);
2220 
2221 	/* Mark statement as successfully transformed */
2222 	stmt->transformed = true;
2223 
2224 	return stmt;
2225 }
2226 
2227 
2228 /*
2229  * transformRuleStmt -
2230  *	  transform a CREATE RULE Statement. The action is a list of parse
2231  *	  trees which is transformed into a list of query trees, and we also
2232  *	  transform the WHERE clause if any.
2233  *
2234  * actions and whereClause are output parameters that receive the
2235  * transformed results.
2236  *
2237  * Note that we must not scribble on the passed-in RuleStmt, so we do
2238  * copyObject() on the actions and WHERE clause.
2239  */
2240 void
transformRuleStmt(RuleStmt * stmt,const char * queryString,List ** actions,Node ** whereClause)2241 transformRuleStmt(RuleStmt *stmt, const char *queryString,
2242 				  List **actions, Node **whereClause)
2243 {
2244 	Relation	rel;
2245 	ParseState *pstate;
2246 	RangeTblEntry *oldrte;
2247 	RangeTblEntry *newrte;
2248 
2249 	/*
2250 	 * To avoid deadlock, make sure the first thing we do is grab
2251 	 * AccessExclusiveLock on the target relation.  This will be needed by
2252 	 * DefineQueryRewrite(), and we don't want to grab a lesser lock
2253 	 * beforehand.
2254 	 */
2255 	rel = heap_openrv(stmt->relation, AccessExclusiveLock);
2256 
2257 	if (rel->rd_rel->relkind == RELKIND_MATVIEW)
2258 		ereport(ERROR,
2259 				(errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
2260 				 errmsg("rules on materialized views are not supported")));
2261 
2262 	/* Set up pstate */
2263 	pstate = make_parsestate(NULL);
2264 	pstate->p_sourcetext = queryString;
2265 
2266 	/*
2267 	 * NOTE: 'OLD' must always have a varno equal to 1 and 'NEW' equal to 2.
2268 	 * Set up their RTEs in the main pstate for use in parsing the rule
2269 	 * qualification.
2270 	 */
2271 	oldrte = addRangeTableEntryForRelation(pstate, rel,
2272 										   makeAlias("old", NIL),
2273 										   false, false);
2274 	newrte = addRangeTableEntryForRelation(pstate, rel,
2275 										   makeAlias("new", NIL),
2276 										   false, false);
2277 	/* Must override addRangeTableEntry's default access-check flags */
2278 	oldrte->requiredPerms = 0;
2279 	newrte->requiredPerms = 0;
2280 
2281 	/*
2282 	 * They must be in the namespace too for lookup purposes, but only add the
2283 	 * one(s) that are relevant for the current kind of rule.  In an UPDATE
2284 	 * rule, quals must refer to OLD.field or NEW.field to be unambiguous, but
2285 	 * there's no need to be so picky for INSERT & DELETE.  We do not add them
2286 	 * to the joinlist.
2287 	 */
2288 	switch (stmt->event)
2289 	{
2290 		case CMD_SELECT:
2291 			addRTEtoQuery(pstate, oldrte, false, true, true);
2292 			break;
2293 		case CMD_UPDATE:
2294 			addRTEtoQuery(pstate, oldrte, false, true, true);
2295 			addRTEtoQuery(pstate, newrte, false, true, true);
2296 			break;
2297 		case CMD_INSERT:
2298 			addRTEtoQuery(pstate, newrte, false, true, true);
2299 			break;
2300 		case CMD_DELETE:
2301 			addRTEtoQuery(pstate, oldrte, false, true, true);
2302 			break;
2303 		default:
2304 			elog(ERROR, "unrecognized event type: %d",
2305 				 (int) stmt->event);
2306 			break;
2307 	}
2308 
2309 	/* take care of the where clause */
2310 	*whereClause = transformWhereClause(pstate,
2311 									  (Node *) copyObject(stmt->whereClause),
2312 										EXPR_KIND_WHERE,
2313 										"WHERE");
2314 	/* we have to fix its collations too */
2315 	assign_expr_collations(pstate, *whereClause);
2316 
2317 	/* this is probably dead code without add_missing_from: */
2318 	if (list_length(pstate->p_rtable) != 2)		/* naughty, naughty... */
2319 		ereport(ERROR,
2320 				(errcode(ERRCODE_INVALID_OBJECT_DEFINITION),
2321 				 errmsg("rule WHERE condition cannot contain references to other relations")));
2322 
2323 	/*
2324 	 * 'instead nothing' rules with a qualification need a query rangetable so
2325 	 * the rewrite handler can add the negated rule qualification to the
2326 	 * original query. We create a query with the new command type CMD_NOTHING
2327 	 * here that is treated specially by the rewrite system.
2328 	 */
2329 	if (stmt->actions == NIL)
2330 	{
2331 		Query	   *nothing_qry = makeNode(Query);
2332 
2333 		nothing_qry->commandType = CMD_NOTHING;
2334 		nothing_qry->rtable = pstate->p_rtable;
2335 		nothing_qry->jointree = makeFromExpr(NIL, NULL);		/* no join wanted */
2336 
2337 		*actions = list_make1(nothing_qry);
2338 	}
2339 	else
2340 	{
2341 		ListCell   *l;
2342 		List	   *newactions = NIL;
2343 
2344 		/*
2345 		 * transform each statement, like parse_sub_analyze()
2346 		 */
2347 		foreach(l, stmt->actions)
2348 		{
2349 			Node	   *action = (Node *) lfirst(l);
2350 			ParseState *sub_pstate = make_parsestate(NULL);
2351 			Query	   *sub_qry,
2352 					   *top_subqry;
2353 			bool		has_old,
2354 						has_new;
2355 
2356 			/*
2357 			 * Since outer ParseState isn't parent of inner, have to pass down
2358 			 * the query text by hand.
2359 			 */
2360 			sub_pstate->p_sourcetext = queryString;
2361 
2362 			/*
2363 			 * Set up OLD/NEW in the rtable for this statement.  The entries
2364 			 * are added only to relnamespace, not varnamespace, because we
2365 			 * don't want them to be referred to by unqualified field names
2366 			 * nor "*" in the rule actions.  We decide later whether to put
2367 			 * them in the joinlist.
2368 			 */
2369 			oldrte = addRangeTableEntryForRelation(sub_pstate, rel,
2370 												   makeAlias("old", NIL),
2371 												   false, false);
2372 			newrte = addRangeTableEntryForRelation(sub_pstate, rel,
2373 												   makeAlias("new", NIL),
2374 												   false, false);
2375 			oldrte->requiredPerms = 0;
2376 			newrte->requiredPerms = 0;
2377 			addRTEtoQuery(sub_pstate, oldrte, false, true, false);
2378 			addRTEtoQuery(sub_pstate, newrte, false, true, false);
2379 
2380 			/* Transform the rule action statement */
2381 			top_subqry = transformStmt(sub_pstate,
2382 									   (Node *) copyObject(action));
2383 
2384 			/*
2385 			 * We cannot support utility-statement actions (eg NOTIFY) with
2386 			 * nonempty rule WHERE conditions, because there's no way to make
2387 			 * the utility action execute conditionally.
2388 			 */
2389 			if (top_subqry->commandType == CMD_UTILITY &&
2390 				*whereClause != NULL)
2391 				ereport(ERROR,
2392 						(errcode(ERRCODE_INVALID_OBJECT_DEFINITION),
2393 						 errmsg("rules with WHERE conditions can only have SELECT, INSERT, UPDATE, or DELETE actions")));
2394 
2395 			/*
2396 			 * If the action is INSERT...SELECT, OLD/NEW have been pushed down
2397 			 * into the SELECT, and that's what we need to look at. (Ugly
2398 			 * kluge ... try to fix this when we redesign querytrees.)
2399 			 */
2400 			sub_qry = getInsertSelectQuery(top_subqry, NULL);
2401 
2402 			/*
2403 			 * If the sub_qry is a setop, we cannot attach any qualifications
2404 			 * to it, because the planner won't notice them.  This could
2405 			 * perhaps be relaxed someday, but for now, we may as well reject
2406 			 * such a rule immediately.
2407 			 */
2408 			if (sub_qry->setOperations != NULL && *whereClause != NULL)
2409 				ereport(ERROR,
2410 						(errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
2411 						 errmsg("conditional UNION/INTERSECT/EXCEPT statements are not implemented")));
2412 
2413 			/*
2414 			 * Validate action's use of OLD/NEW, qual too
2415 			 */
2416 			has_old =
2417 				rangeTableEntry_used((Node *) sub_qry, PRS2_OLD_VARNO, 0) ||
2418 				rangeTableEntry_used(*whereClause, PRS2_OLD_VARNO, 0);
2419 			has_new =
2420 				rangeTableEntry_used((Node *) sub_qry, PRS2_NEW_VARNO, 0) ||
2421 				rangeTableEntry_used(*whereClause, PRS2_NEW_VARNO, 0);
2422 
2423 			switch (stmt->event)
2424 			{
2425 				case CMD_SELECT:
2426 					if (has_old)
2427 						ereport(ERROR,
2428 								(errcode(ERRCODE_INVALID_OBJECT_DEFINITION),
2429 								 errmsg("ON SELECT rule cannot use OLD")));
2430 					if (has_new)
2431 						ereport(ERROR,
2432 								(errcode(ERRCODE_INVALID_OBJECT_DEFINITION),
2433 								 errmsg("ON SELECT rule cannot use NEW")));
2434 					break;
2435 				case CMD_UPDATE:
2436 					/* both are OK */
2437 					break;
2438 				case CMD_INSERT:
2439 					if (has_old)
2440 						ereport(ERROR,
2441 								(errcode(ERRCODE_INVALID_OBJECT_DEFINITION),
2442 								 errmsg("ON INSERT rule cannot use OLD")));
2443 					break;
2444 				case CMD_DELETE:
2445 					if (has_new)
2446 						ereport(ERROR,
2447 								(errcode(ERRCODE_INVALID_OBJECT_DEFINITION),
2448 								 errmsg("ON DELETE rule cannot use NEW")));
2449 					break;
2450 				default:
2451 					elog(ERROR, "unrecognized event type: %d",
2452 						 (int) stmt->event);
2453 					break;
2454 			}
2455 
2456 			/*
2457 			 * OLD/NEW are not allowed in WITH queries, because they would
2458 			 * amount to outer references for the WITH, which we disallow.
2459 			 * However, they were already in the outer rangetable when we
2460 			 * analyzed the query, so we have to check.
2461 			 *
2462 			 * Note that in the INSERT...SELECT case, we need to examine the
2463 			 * CTE lists of both top_subqry and sub_qry.
2464 			 *
2465 			 * Note that we aren't digging into the body of the query looking
2466 			 * for WITHs in nested sub-SELECTs.  A WITH down there can
2467 			 * legitimately refer to OLD/NEW, because it'd be an
2468 			 * indirect-correlated outer reference.
2469 			 */
2470 			if (rangeTableEntry_used((Node *) top_subqry->cteList,
2471 									 PRS2_OLD_VARNO, 0) ||
2472 				rangeTableEntry_used((Node *) sub_qry->cteList,
2473 									 PRS2_OLD_VARNO, 0))
2474 				ereport(ERROR,
2475 						(errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
2476 						 errmsg("cannot refer to OLD within WITH query")));
2477 			if (rangeTableEntry_used((Node *) top_subqry->cteList,
2478 									 PRS2_NEW_VARNO, 0) ||
2479 				rangeTableEntry_used((Node *) sub_qry->cteList,
2480 									 PRS2_NEW_VARNO, 0))
2481 				ereport(ERROR,
2482 						(errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
2483 						 errmsg("cannot refer to NEW within WITH query")));
2484 
2485 			/*
2486 			 * For efficiency's sake, add OLD to the rule action's jointree
2487 			 * only if it was actually referenced in the statement or qual.
2488 			 *
2489 			 * For INSERT, NEW is not really a relation (only a reference to
2490 			 * the to-be-inserted tuple) and should never be added to the
2491 			 * jointree.
2492 			 *
2493 			 * For UPDATE, we treat NEW as being another kind of reference to
2494 			 * OLD, because it represents references to *transformed* tuples
2495 			 * of the existing relation.  It would be wrong to enter NEW
2496 			 * separately in the jointree, since that would cause a double
2497 			 * join of the updated relation.  It's also wrong to fail to make
2498 			 * a jointree entry if only NEW and not OLD is mentioned.
2499 			 */
2500 			if (has_old || (has_new && stmt->event == CMD_UPDATE))
2501 			{
2502 				/*
2503 				 * If sub_qry is a setop, manipulating its jointree will do no
2504 				 * good at all, because the jointree is dummy. (This should be
2505 				 * a can't-happen case because of prior tests.)
2506 				 */
2507 				if (sub_qry->setOperations != NULL)
2508 					ereport(ERROR,
2509 							(errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
2510 							 errmsg("conditional UNION/INTERSECT/EXCEPT statements are not implemented")));
2511 				/* hack so we can use addRTEtoQuery() */
2512 				sub_pstate->p_rtable = sub_qry->rtable;
2513 				sub_pstate->p_joinlist = sub_qry->jointree->fromlist;
2514 				addRTEtoQuery(sub_pstate, oldrte, true, false, false);
2515 				sub_qry->jointree->fromlist = sub_pstate->p_joinlist;
2516 			}
2517 
2518 			newactions = lappend(newactions, top_subqry);
2519 
2520 			free_parsestate(sub_pstate);
2521 		}
2522 
2523 		*actions = newactions;
2524 	}
2525 
2526 	free_parsestate(pstate);
2527 
2528 	/* Close relation, but keep the exclusive lock */
2529 	heap_close(rel, NoLock);
2530 }
2531 
2532 
2533 /*
2534  * transformAlterTableStmt -
2535  *		parse analysis for ALTER TABLE
2536  *
2537  * Returns a List of utility commands to be done in sequence.  One of these
2538  * will be the transformed AlterTableStmt, but there may be additional actions
2539  * to be done before and after the actual AlterTable() call.
2540  *
2541  * To avoid race conditions, it's important that this function rely only on
2542  * the passed-in relid (and not on stmt->relation) to determine the target
2543  * relation.
2544  */
2545 List *
transformAlterTableStmt(Oid relid,AlterTableStmt * stmt,const char * queryString)2546 transformAlterTableStmt(Oid relid, AlterTableStmt *stmt,
2547 						const char *queryString)
2548 {
2549 	Relation	rel;
2550 	ParseState *pstate;
2551 	CreateStmtContext cxt;
2552 	List	   *result;
2553 	List	   *save_alist;
2554 	ListCell   *lcmd,
2555 			   *l;
2556 	List	   *newcmds = NIL;
2557 	bool		skipValidation = true;
2558 	AlterTableCmd *newcmd;
2559 	RangeTblEntry *rte;
2560 
2561 	/*
2562 	 * We must not scribble on the passed-in AlterTableStmt, so copy it. (This
2563 	 * is overkill, but easy.)
2564 	 */
2565 	stmt = (AlterTableStmt *) copyObject(stmt);
2566 
2567 	/* Caller is responsible for locking the relation */
2568 	rel = relation_open(relid, NoLock);
2569 
2570 	/* Set up pstate */
2571 	pstate = make_parsestate(NULL);
2572 	pstate->p_sourcetext = queryString;
2573 	rte = addRangeTableEntryForRelation(pstate,
2574 										rel,
2575 										NULL,
2576 										false,
2577 										true);
2578 	addRTEtoQuery(pstate, rte, false, true, true);
2579 
2580 	/* Set up CreateStmtContext */
2581 	cxt.pstate = pstate;
2582 	if (stmt->relkind == OBJECT_FOREIGN_TABLE)
2583 	{
2584 		cxt.stmtType = "ALTER FOREIGN TABLE";
2585 		cxt.isforeign = true;
2586 	}
2587 	else
2588 	{
2589 		cxt.stmtType = "ALTER TABLE";
2590 		cxt.isforeign = false;
2591 	}
2592 	cxt.relation = stmt->relation;
2593 	cxt.rel = rel;
2594 	cxt.inhRelations = NIL;
2595 	cxt.isalter = true;
2596 	cxt.hasoids = false;		/* need not be right */
2597 	cxt.columns = NIL;
2598 	cxt.ckconstraints = NIL;
2599 	cxt.fkconstraints = NIL;
2600 	cxt.ixconstraints = NIL;
2601 	cxt.likeclauses = NIL;
2602 	cxt.blist = NIL;
2603 	cxt.alist = NIL;
2604 	cxt.pkey = NULL;
2605 
2606 	/*
2607 	 * The only subtypes that currently require parse transformation handling
2608 	 * are ADD COLUMN, ADD CONSTRAINT and SET DATA TYPE.  These largely re-use
2609 	 * code from CREATE TABLE.
2610 	 */
2611 	foreach(lcmd, stmt->cmds)
2612 	{
2613 		AlterTableCmd *cmd = (AlterTableCmd *) lfirst(lcmd);
2614 
2615 		switch (cmd->subtype)
2616 		{
2617 			case AT_AddColumn:
2618 			case AT_AddColumnToView:
2619 				{
2620 					ColumnDef  *def = (ColumnDef *) cmd->def;
2621 
2622 					Assert(IsA(def, ColumnDef));
2623 					transformColumnDefinition(&cxt, def);
2624 
2625 					/*
2626 					 * If the column has a non-null default, we can't skip
2627 					 * validation of foreign keys.
2628 					 */
2629 					if (def->raw_default != NULL)
2630 						skipValidation = false;
2631 
2632 					/*
2633 					 * All constraints are processed in other ways. Remove the
2634 					 * original list
2635 					 */
2636 					def->constraints = NIL;
2637 
2638 					newcmds = lappend(newcmds, cmd);
2639 					break;
2640 				}
2641 
2642 			case AT_AddConstraint:
2643 
2644 				/*
2645 				 * The original AddConstraint cmd node doesn't go to newcmds
2646 				 */
2647 				if (IsA(cmd->def, Constraint))
2648 				{
2649 					transformTableConstraint(&cxt, (Constraint *) cmd->def);
2650 					if (((Constraint *) cmd->def)->contype == CONSTR_FOREIGN)
2651 						skipValidation = false;
2652 				}
2653 				else
2654 					elog(ERROR, "unrecognized node type: %d",
2655 						 (int) nodeTag(cmd->def));
2656 				break;
2657 
2658 			case AT_ProcessedConstraint:
2659 
2660 				/*
2661 				 * Already-transformed ADD CONSTRAINT, so just make it look
2662 				 * like the standard case.
2663 				 */
2664 				cmd->subtype = AT_AddConstraint;
2665 				newcmds = lappend(newcmds, cmd);
2666 				break;
2667 
2668 			case AT_AlterColumnType:
2669 				{
2670 					ColumnDef  *def = (ColumnDef *) cmd->def;
2671 
2672 					/*
2673 					 * For ALTER COLUMN TYPE, transform the USING clause if
2674 					 * one was specified.
2675 					 */
2676 					if (def->raw_default)
2677 					{
2678 						def->cooked_default =
2679 							transformExpr(pstate, def->raw_default,
2680 										  EXPR_KIND_ALTER_COL_TRANSFORM);
2681 
2682 						/* it can't return a set */
2683 						if (expression_returns_set(def->cooked_default))
2684 							ereport(ERROR,
2685 									(errcode(ERRCODE_DATATYPE_MISMATCH),
2686 									 errmsg("transform expression must not return a set")));
2687 					}
2688 
2689 					newcmds = lappend(newcmds, cmd);
2690 					break;
2691 				}
2692 
2693 			default:
2694 				newcmds = lappend(newcmds, cmd);
2695 				break;
2696 		}
2697 	}
2698 
2699 	/*
2700 	 * transformIndexConstraints wants cxt.alist to contain only index
2701 	 * statements, so transfer anything we already have into save_alist
2702 	 * immediately.
2703 	 */
2704 	save_alist = cxt.alist;
2705 	cxt.alist = NIL;
2706 
2707 	/* Postprocess constraints */
2708 	transformIndexConstraints(&cxt);
2709 	transformFKConstraints(&cxt, skipValidation, true);
2710 	transformCheckConstraints(&cxt, false);
2711 
2712 	/*
2713 	 * Push any index-creation commands into the ALTER, so that they can be
2714 	 * scheduled nicely by tablecmds.c.  Note that tablecmds.c assumes that
2715 	 * the IndexStmt attached to an AT_AddIndex or AT_AddIndexConstraint
2716 	 * subcommand has already been through transformIndexStmt.
2717 	 */
2718 	foreach(l, cxt.alist)
2719 	{
2720 		IndexStmt  *idxstmt = (IndexStmt *) lfirst(l);
2721 
2722 		Assert(IsA(idxstmt, IndexStmt));
2723 		idxstmt = transformIndexStmt(relid, idxstmt, queryString);
2724 		newcmd = makeNode(AlterTableCmd);
2725 		newcmd->subtype = OidIsValid(idxstmt->indexOid) ? AT_AddIndexConstraint : AT_AddIndex;
2726 		newcmd->def = (Node *) idxstmt;
2727 		newcmds = lappend(newcmds, newcmd);
2728 	}
2729 	cxt.alist = NIL;
2730 
2731 	/* Append any CHECK or FK constraints to the commands list */
2732 	foreach(l, cxt.ckconstraints)
2733 	{
2734 		newcmd = makeNode(AlterTableCmd);
2735 		newcmd->subtype = AT_AddConstraint;
2736 		newcmd->def = (Node *) lfirst(l);
2737 		newcmds = lappend(newcmds, newcmd);
2738 	}
2739 	foreach(l, cxt.fkconstraints)
2740 	{
2741 		newcmd = makeNode(AlterTableCmd);
2742 		newcmd->subtype = AT_AddConstraint;
2743 		newcmd->def = (Node *) lfirst(l);
2744 		newcmds = lappend(newcmds, newcmd);
2745 	}
2746 
2747 	/* Close rel */
2748 	relation_close(rel, NoLock);
2749 
2750 	/*
2751 	 * Output results.
2752 	 */
2753 	stmt->cmds = newcmds;
2754 
2755 	result = lappend(cxt.blist, stmt);
2756 	result = list_concat(result, cxt.alist);
2757 	result = list_concat(result, save_alist);
2758 
2759 	return result;
2760 }
2761 
2762 
2763 /*
2764  * Preprocess a list of column constraint clauses
2765  * to attach constraint attributes to their primary constraint nodes
2766  * and detect inconsistent/misplaced constraint attributes.
2767  *
2768  * NOTE: currently, attributes are only supported for FOREIGN KEY, UNIQUE,
2769  * EXCLUSION, and PRIMARY KEY constraints, but someday they ought to be
2770  * supported for other constraint types.
2771  */
2772 static void
transformConstraintAttrs(CreateStmtContext * cxt,List * constraintList)2773 transformConstraintAttrs(CreateStmtContext *cxt, List *constraintList)
2774 {
2775 	Constraint *lastprimarycon = NULL;
2776 	bool		saw_deferrability = false;
2777 	bool		saw_initially = false;
2778 	ListCell   *clist;
2779 
2780 #define SUPPORTS_ATTRS(node)				\
2781 	((node) != NULL &&						\
2782 	 ((node)->contype == CONSTR_PRIMARY ||	\
2783 	  (node)->contype == CONSTR_UNIQUE ||	\
2784 	  (node)->contype == CONSTR_EXCLUSION || \
2785 	  (node)->contype == CONSTR_FOREIGN))
2786 
2787 	foreach(clist, constraintList)
2788 	{
2789 		Constraint *con = (Constraint *) lfirst(clist);
2790 
2791 		if (!IsA(con, Constraint))
2792 			elog(ERROR, "unrecognized node type: %d",
2793 				 (int) nodeTag(con));
2794 		switch (con->contype)
2795 		{
2796 			case CONSTR_ATTR_DEFERRABLE:
2797 				if (!SUPPORTS_ATTRS(lastprimarycon))
2798 					ereport(ERROR,
2799 							(errcode(ERRCODE_SYNTAX_ERROR),
2800 							 errmsg("misplaced DEFERRABLE clause"),
2801 							 parser_errposition(cxt->pstate, con->location)));
2802 				if (saw_deferrability)
2803 					ereport(ERROR,
2804 							(errcode(ERRCODE_SYNTAX_ERROR),
2805 							 errmsg("multiple DEFERRABLE/NOT DEFERRABLE clauses not allowed"),
2806 							 parser_errposition(cxt->pstate, con->location)));
2807 				saw_deferrability = true;
2808 				lastprimarycon->deferrable = true;
2809 				break;
2810 
2811 			case CONSTR_ATTR_NOT_DEFERRABLE:
2812 				if (!SUPPORTS_ATTRS(lastprimarycon))
2813 					ereport(ERROR,
2814 							(errcode(ERRCODE_SYNTAX_ERROR),
2815 							 errmsg("misplaced NOT DEFERRABLE clause"),
2816 							 parser_errposition(cxt->pstate, con->location)));
2817 				if (saw_deferrability)
2818 					ereport(ERROR,
2819 							(errcode(ERRCODE_SYNTAX_ERROR),
2820 							 errmsg("multiple DEFERRABLE/NOT DEFERRABLE clauses not allowed"),
2821 							 parser_errposition(cxt->pstate, con->location)));
2822 				saw_deferrability = true;
2823 				lastprimarycon->deferrable = false;
2824 				if (saw_initially &&
2825 					lastprimarycon->initdeferred)
2826 					ereport(ERROR,
2827 							(errcode(ERRCODE_SYNTAX_ERROR),
2828 							 errmsg("constraint declared INITIALLY DEFERRED must be DEFERRABLE"),
2829 							 parser_errposition(cxt->pstate, con->location)));
2830 				break;
2831 
2832 			case CONSTR_ATTR_DEFERRED:
2833 				if (!SUPPORTS_ATTRS(lastprimarycon))
2834 					ereport(ERROR,
2835 							(errcode(ERRCODE_SYNTAX_ERROR),
2836 							 errmsg("misplaced INITIALLY DEFERRED clause"),
2837 							 parser_errposition(cxt->pstate, con->location)));
2838 				if (saw_initially)
2839 					ereport(ERROR,
2840 							(errcode(ERRCODE_SYNTAX_ERROR),
2841 							 errmsg("multiple INITIALLY IMMEDIATE/DEFERRED clauses not allowed"),
2842 							 parser_errposition(cxt->pstate, con->location)));
2843 				saw_initially = true;
2844 				lastprimarycon->initdeferred = true;
2845 
2846 				/*
2847 				 * If only INITIALLY DEFERRED appears, assume DEFERRABLE
2848 				 */
2849 				if (!saw_deferrability)
2850 					lastprimarycon->deferrable = true;
2851 				else if (!lastprimarycon->deferrable)
2852 					ereport(ERROR,
2853 							(errcode(ERRCODE_SYNTAX_ERROR),
2854 							 errmsg("constraint declared INITIALLY DEFERRED must be DEFERRABLE"),
2855 							 parser_errposition(cxt->pstate, con->location)));
2856 				break;
2857 
2858 			case CONSTR_ATTR_IMMEDIATE:
2859 				if (!SUPPORTS_ATTRS(lastprimarycon))
2860 					ereport(ERROR,
2861 							(errcode(ERRCODE_SYNTAX_ERROR),
2862 							 errmsg("misplaced INITIALLY IMMEDIATE clause"),
2863 							 parser_errposition(cxt->pstate, con->location)));
2864 				if (saw_initially)
2865 					ereport(ERROR,
2866 							(errcode(ERRCODE_SYNTAX_ERROR),
2867 							 errmsg("multiple INITIALLY IMMEDIATE/DEFERRED clauses not allowed"),
2868 							 parser_errposition(cxt->pstate, con->location)));
2869 				saw_initially = true;
2870 				lastprimarycon->initdeferred = false;
2871 				break;
2872 
2873 			default:
2874 				/* Otherwise it's not an attribute */
2875 				lastprimarycon = con;
2876 				/* reset flags for new primary node */
2877 				saw_deferrability = false;
2878 				saw_initially = false;
2879 				break;
2880 		}
2881 	}
2882 }
2883 
2884 /*
2885  * Special handling of type definition for a column
2886  */
2887 static void
transformColumnType(CreateStmtContext * cxt,ColumnDef * column)2888 transformColumnType(CreateStmtContext *cxt, ColumnDef *column)
2889 {
2890 	/*
2891 	 * All we really need to do here is verify that the type is valid,
2892 	 * including any collation spec that might be present.
2893 	 */
2894 	Type		ctype = typenameType(cxt->pstate, column->typeName, NULL);
2895 
2896 	if (column->collClause)
2897 	{
2898 		Form_pg_type typtup = (Form_pg_type) GETSTRUCT(ctype);
2899 
2900 		LookupCollation(cxt->pstate,
2901 						column->collClause->collname,
2902 						column->collClause->location);
2903 		/* Complain if COLLATE is applied to an uncollatable type */
2904 		if (!OidIsValid(typtup->typcollation))
2905 			ereport(ERROR,
2906 					(errcode(ERRCODE_DATATYPE_MISMATCH),
2907 					 errmsg("collations are not supported by type %s",
2908 							format_type_be(HeapTupleGetOid(ctype))),
2909 					 parser_errposition(cxt->pstate,
2910 										column->collClause->location)));
2911 	}
2912 
2913 	ReleaseSysCache(ctype);
2914 }
2915 
2916 
2917 /*
2918  * transformCreateSchemaStmt -
2919  *	  analyzes the CREATE SCHEMA statement
2920  *
2921  * Split the schema element list into individual commands and place
2922  * them in the result list in an order such that there are no forward
2923  * references (e.g. GRANT to a table created later in the list). Note
2924  * that the logic we use for determining forward references is
2925  * presently quite incomplete.
2926  *
2927  * SQL also allows constraints to make forward references, so thumb through
2928  * the table columns and move forward references to a posterior alter-table
2929  * command.
2930  *
2931  * The result is a list of parse nodes that still need to be analyzed ---
2932  * but we can't analyze the later commands until we've executed the earlier
2933  * ones, because of possible inter-object references.
2934  *
2935  * Note: this breaks the rules a little bit by modifying schema-name fields
2936  * within passed-in structs.  However, the transformation would be the same
2937  * if done over, so it should be all right to scribble on the input to this
2938  * extent.
2939  */
2940 List *
transformCreateSchemaStmt(CreateSchemaStmt * stmt)2941 transformCreateSchemaStmt(CreateSchemaStmt *stmt)
2942 {
2943 	CreateSchemaStmtContext cxt;
2944 	List	   *result;
2945 	ListCell   *elements;
2946 
2947 	cxt.stmtType = "CREATE SCHEMA";
2948 	cxt.schemaname = stmt->schemaname;
2949 	cxt.authrole = (RoleSpec *) stmt->authrole;
2950 	cxt.sequences = NIL;
2951 	cxt.tables = NIL;
2952 	cxt.views = NIL;
2953 	cxt.indexes = NIL;
2954 	cxt.triggers = NIL;
2955 	cxt.grants = NIL;
2956 
2957 	/*
2958 	 * Run through each schema element in the schema element list. Separate
2959 	 * statements by type, and do preliminary analysis.
2960 	 */
2961 	foreach(elements, stmt->schemaElts)
2962 	{
2963 		Node	   *element = lfirst(elements);
2964 
2965 		switch (nodeTag(element))
2966 		{
2967 			case T_CreateSeqStmt:
2968 				{
2969 					CreateSeqStmt *elp = (CreateSeqStmt *) element;
2970 
2971 					setSchemaName(cxt.schemaname, &elp->sequence->schemaname);
2972 					cxt.sequences = lappend(cxt.sequences, element);
2973 				}
2974 				break;
2975 
2976 			case T_CreateStmt:
2977 				{
2978 					CreateStmt *elp = (CreateStmt *) element;
2979 
2980 					setSchemaName(cxt.schemaname, &elp->relation->schemaname);
2981 
2982 					/*
2983 					 * XXX todo: deal with constraints
2984 					 */
2985 					cxt.tables = lappend(cxt.tables, element);
2986 				}
2987 				break;
2988 
2989 			case T_ViewStmt:
2990 				{
2991 					ViewStmt   *elp = (ViewStmt *) element;
2992 
2993 					setSchemaName(cxt.schemaname, &elp->view->schemaname);
2994 
2995 					/*
2996 					 * XXX todo: deal with references between views
2997 					 */
2998 					cxt.views = lappend(cxt.views, element);
2999 				}
3000 				break;
3001 
3002 			case T_IndexStmt:
3003 				{
3004 					IndexStmt  *elp = (IndexStmt *) element;
3005 
3006 					setSchemaName(cxt.schemaname, &elp->relation->schemaname);
3007 					cxt.indexes = lappend(cxt.indexes, element);
3008 				}
3009 				break;
3010 
3011 			case T_CreateTrigStmt:
3012 				{
3013 					CreateTrigStmt *elp = (CreateTrigStmt *) element;
3014 
3015 					setSchemaName(cxt.schemaname, &elp->relation->schemaname);
3016 					cxt.triggers = lappend(cxt.triggers, element);
3017 				}
3018 				break;
3019 
3020 			case T_GrantStmt:
3021 				cxt.grants = lappend(cxt.grants, element);
3022 				break;
3023 
3024 			default:
3025 				elog(ERROR, "unrecognized node type: %d",
3026 					 (int) nodeTag(element));
3027 		}
3028 	}
3029 
3030 	result = NIL;
3031 	result = list_concat(result, cxt.sequences);
3032 	result = list_concat(result, cxt.tables);
3033 	result = list_concat(result, cxt.views);
3034 	result = list_concat(result, cxt.indexes);
3035 	result = list_concat(result, cxt.triggers);
3036 	result = list_concat(result, cxt.grants);
3037 
3038 	return result;
3039 }
3040 
3041 /*
3042  * setSchemaName
3043  *		Set or check schema name in an element of a CREATE SCHEMA command
3044  */
3045 static void
setSchemaName(char * context_schema,char ** stmt_schema_name)3046 setSchemaName(char *context_schema, char **stmt_schema_name)
3047 {
3048 	if (*stmt_schema_name == NULL)
3049 		*stmt_schema_name = context_schema;
3050 	else if (strcmp(context_schema, *stmt_schema_name) != 0)
3051 		ereport(ERROR,
3052 				(errcode(ERRCODE_INVALID_SCHEMA_DEFINITION),
3053 				 errmsg("CREATE specifies a schema (%s) "
3054 						"different from the one being created (%s)",
3055 						*stmt_schema_name, context_schema)));
3056 }
3057