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-2019, 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/relation.h"
32 #include "access/reloptions.h"
33 #include "access/table.h"
34 #include "catalog/dependency.h"
35 #include "catalog/heap.h"
36 #include "catalog/index.h"
37 #include "catalog/namespace.h"
38 #include "catalog/pg_am.h"
39 #include "catalog/pg_collation.h"
40 #include "catalog/pg_constraint.h"
41 #include "catalog/pg_opclass.h"
42 #include "catalog/pg_operator.h"
43 #include "catalog/pg_statistic_ext.h"
44 #include "catalog/pg_type.h"
45 #include "commands/comment.h"
46 #include "commands/defrem.h"
47 #include "commands/sequence.h"
48 #include "commands/tablecmds.h"
49 #include "commands/tablespace.h"
50 #include "miscadmin.h"
51 #include "nodes/makefuncs.h"
52 #include "nodes/nodeFuncs.h"
53 #include "optimizer/optimizer.h"
54 #include "parser/analyze.h"
55 #include "parser/parse_clause.h"
56 #include "parser/parse_coerce.h"
57 #include "parser/parse_collate.h"
58 #include "parser/parse_expr.h"
59 #include "parser/parse_relation.h"
60 #include "parser/parse_target.h"
61 #include "parser/parse_type.h"
62 #include "parser/parse_utilcmd.h"
63 #include "parser/parser.h"
64 #include "rewrite/rewriteManip.h"
65 #include "utils/acl.h"
66 #include "utils/builtins.h"
67 #include "utils/lsyscache.h"
68 #include "utils/partcache.h"
69 #include "utils/rel.h"
70 #include "utils/ruleutils.h"
71 #include "utils/syscache.h"
72 #include "utils/typcache.h"
73 
74 
75 /* State shared by transformCreateStmt and its subroutines */
76 typedef struct
77 {
78 	ParseState *pstate;			/* overall parser state */
79 	const char *stmtType;		/* "CREATE [FOREIGN] TABLE" or "ALTER TABLE" */
80 	RangeVar   *relation;		/* relation to create */
81 	Relation	rel;			/* opened/locked rel, if ALTER */
82 	List	   *inhRelations;	/* relations to inherit from */
83 	bool		isforeign;		/* true if CREATE/ALTER FOREIGN TABLE */
84 	bool		isalter;		/* true if altering existing table */
85 	List	   *columns;		/* ColumnDef items */
86 	List	   *ckconstraints;	/* CHECK constraints */
87 	List	   *fkconstraints;	/* FOREIGN KEY constraints */
88 	List	   *ixconstraints;	/* index-creating constraints */
89 	List	   *likeclauses;	/* LIKE clauses that need post-processing */
90 	List	   *extstats;		/* cloned extended statistics */
91 	List	   *blist;			/* "before list" of things to do before
92 								 * creating the table */
93 	List	   *alist;			/* "after list" of things to do after creating
94 								 * the table */
95 	IndexStmt  *pkey;			/* PRIMARY KEY index, if any */
96 	bool		ispartitioned;	/* true if table is partitioned */
97 	PartitionBoundSpec *partbound;	/* transformed FOR VALUES */
98 	bool		ofType;			/* true if statement contains OF typename */
99 } CreateStmtContext;
100 
101 /* State shared by transformCreateSchemaStmt and its subroutines */
102 typedef struct
103 {
104 	const char *stmtType;		/* "CREATE SCHEMA" or "ALTER SCHEMA" */
105 	char	   *schemaname;		/* name of schema */
106 	RoleSpec   *authrole;		/* owner of schema */
107 	List	   *sequences;		/* CREATE SEQUENCE items */
108 	List	   *tables;			/* CREATE TABLE items */
109 	List	   *views;			/* CREATE VIEW items */
110 	List	   *indexes;		/* CREATE INDEX items */
111 	List	   *triggers;		/* CREATE TRIGGER items */
112 	List	   *grants;			/* GRANT items */
113 } CreateSchemaStmtContext;
114 
115 
116 static void transformColumnDefinition(CreateStmtContext *cxt,
117 									  ColumnDef *column);
118 static void transformTableConstraint(CreateStmtContext *cxt,
119 									 Constraint *constraint);
120 static void transformTableLikeClause(CreateStmtContext *cxt,
121 									 TableLikeClause *table_like_clause);
122 static void transformOfType(CreateStmtContext *cxt,
123 							TypeName *ofTypename);
124 static CreateStatsStmt *generateClonedExtStatsStmt(RangeVar *heapRel,
125 												   Oid heapRelid, Oid source_statsid);
126 static List *get_collation(Oid collation, Oid actual_datatype);
127 static List *get_opclass(Oid opclass, Oid actual_datatype);
128 static void transformIndexConstraints(CreateStmtContext *cxt);
129 static IndexStmt *transformIndexConstraint(Constraint *constraint,
130 										   CreateStmtContext *cxt);
131 static void transformExtendedStatistics(CreateStmtContext *cxt);
132 static void transformFKConstraints(CreateStmtContext *cxt,
133 								   bool skipValidation,
134 								   bool isAddConstraint);
135 static void transformCheckConstraints(CreateStmtContext *cxt,
136 									  bool skipValidation);
137 static void transformConstraintAttrs(CreateStmtContext *cxt,
138 									 List *constraintList);
139 static void transformColumnType(CreateStmtContext *cxt, ColumnDef *column);
140 static void setSchemaName(char *context_schema, char **stmt_schema_name);
141 static void transformPartitionCmd(CreateStmtContext *cxt, PartitionCmd *cmd);
142 static List *transformPartitionRangeBounds(ParseState *pstate, List *blist,
143 										   Relation parent);
144 static void validateInfiniteBounds(ParseState *pstate, List *blist);
145 static Const *transformPartitionBoundValue(ParseState *pstate, Node *con,
146 										   const char *colName, Oid colType, int32 colTypmod,
147 										   Oid partCollation);
148 
149 
150 /*
151  * transformCreateStmt -
152  *	  parse analysis for CREATE TABLE
153  *
154  * Returns a List of utility commands to be done in sequence.  One of these
155  * will be the transformed CreateStmt, but there may be additional actions
156  * to be done before and after the actual DefineRelation() call.
157  * In addition to normal utility commands such as AlterTableStmt and
158  * IndexStmt, the result list may contain TableLikeClause(s), representing
159  * the need to perform additional parse analysis after DefineRelation().
160  *
161  * SQL allows constraints to be scattered all over, so thumb through
162  * the columns and collect all constraints into one place.
163  * If there are any implied indices (e.g. UNIQUE or PRIMARY KEY)
164  * then expand those into multiple IndexStmt blocks.
165  *	  - thomas 1997-12-02
166  */
167 List *
transformCreateStmt(CreateStmt * stmt,const char * queryString)168 transformCreateStmt(CreateStmt *stmt, const char *queryString)
169 {
170 	ParseState *pstate;
171 	CreateStmtContext cxt;
172 	List	   *result;
173 	List	   *save_alist;
174 	ListCell   *elements;
175 	Oid			namespaceid;
176 	Oid			existing_relid;
177 	ParseCallbackState pcbstate;
178 	bool		is_foreign_table = IsA(stmt, CreateForeignTableStmt);
179 
180 	/*
181 	 * We must not scribble on the passed-in CreateStmt, so copy it.  (This is
182 	 * overkill, but easy.)
183 	 */
184 	stmt = copyObject(stmt);
185 
186 	/* Set up pstate */
187 	pstate = make_parsestate(NULL);
188 	pstate->p_sourcetext = queryString;
189 
190 	/*
191 	 * Look up the creation namespace.  This also checks permissions on the
192 	 * target namespace, locks it against concurrent drops, checks for a
193 	 * preexisting relation in that namespace with the same name, and updates
194 	 * stmt->relation->relpersistence if the selected namespace is temporary.
195 	 */
196 	setup_parser_errposition_callback(&pcbstate, pstate,
197 									  stmt->relation->location);
198 	namespaceid =
199 		RangeVarGetAndCheckCreationNamespace(stmt->relation, NoLock,
200 											 &existing_relid);
201 	cancel_parser_errposition_callback(&pcbstate);
202 
203 	/*
204 	 * If the relation already exists and the user specified "IF NOT EXISTS",
205 	 * bail out with a NOTICE.
206 	 */
207 	if (stmt->if_not_exists && OidIsValid(existing_relid))
208 	{
209 		ereport(NOTICE,
210 				(errcode(ERRCODE_DUPLICATE_TABLE),
211 				 errmsg("relation \"%s\" already exists, skipping",
212 						stmt->relation->relname)));
213 		return NIL;
214 	}
215 
216 	/*
217 	 * If the target relation name isn't schema-qualified, make it so.  This
218 	 * prevents some corner cases in which added-on rewritten commands might
219 	 * think they should apply to other relations that have the same name and
220 	 * are earlier in the search path.  But a local temp table is effectively
221 	 * specified to be in pg_temp, so no need for anything extra in that case.
222 	 */
223 	if (stmt->relation->schemaname == NULL
224 		&& stmt->relation->relpersistence != RELPERSISTENCE_TEMP)
225 		stmt->relation->schemaname = get_namespace_name(namespaceid);
226 
227 	/* Set up CreateStmtContext */
228 	cxt.pstate = pstate;
229 	if (IsA(stmt, CreateForeignTableStmt))
230 	{
231 		cxt.stmtType = "CREATE FOREIGN TABLE";
232 		cxt.isforeign = true;
233 	}
234 	else
235 	{
236 		cxt.stmtType = "CREATE TABLE";
237 		cxt.isforeign = false;
238 	}
239 	cxt.relation = stmt->relation;
240 	cxt.rel = NULL;
241 	cxt.inhRelations = stmt->inhRelations;
242 	cxt.isalter = false;
243 	cxt.columns = NIL;
244 	cxt.ckconstraints = NIL;
245 	cxt.fkconstraints = NIL;
246 	cxt.ixconstraints = NIL;
247 	cxt.likeclauses = NIL;
248 	cxt.extstats = NIL;
249 	cxt.blist = NIL;
250 	cxt.alist = NIL;
251 	cxt.pkey = NULL;
252 	cxt.ispartitioned = stmt->partspec != NULL;
253 	cxt.partbound = stmt->partbound;
254 	cxt.ofType = (stmt->ofTypename != NULL);
255 
256 	Assert(!stmt->ofTypename || !stmt->inhRelations);	/* grammar enforces */
257 
258 	if (stmt->ofTypename)
259 		transformOfType(&cxt, stmt->ofTypename);
260 
261 	if (stmt->partspec)
262 	{
263 		if (stmt->inhRelations && !stmt->partbound)
264 			ereport(ERROR,
265 					(errcode(ERRCODE_INVALID_OBJECT_DEFINITION),
266 					 errmsg("cannot create partitioned table as inheritance child")));
267 	}
268 
269 	/*
270 	 * Run through each primary element in the table creation clause. Separate
271 	 * column defs from constraints, and do preliminary analysis.
272 	 */
273 	foreach(elements, stmt->tableElts)
274 	{
275 		Node	   *element = lfirst(elements);
276 
277 		switch (nodeTag(element))
278 		{
279 			case T_ColumnDef:
280 				transformColumnDefinition(&cxt, (ColumnDef *) element);
281 				break;
282 
283 			case T_Constraint:
284 				transformTableConstraint(&cxt, (Constraint *) element);
285 				break;
286 
287 			case T_TableLikeClause:
288 				transformTableLikeClause(&cxt, (TableLikeClause *) element);
289 				break;
290 
291 			default:
292 				elog(ERROR, "unrecognized node type: %d",
293 					 (int) nodeTag(element));
294 				break;
295 		}
296 	}
297 
298 	/*
299 	 * Transfer anything we already have in cxt.alist into save_alist, to keep
300 	 * it separate from the output of transformIndexConstraints.  (This may
301 	 * not be necessary anymore, but we'll keep doing it to preserve the
302 	 * historical order of execution of the alist commands.)
303 	 */
304 	save_alist = cxt.alist;
305 	cxt.alist = NIL;
306 
307 	Assert(stmt->constraints == NIL);
308 
309 	/*
310 	 * Postprocess constraints that give rise to index definitions.
311 	 */
312 	transformIndexConstraints(&cxt);
313 
314 	/*
315 	 * Re-consideration of LIKE clauses should happen after creation of
316 	 * indexes, but before creation of foreign keys.  This order is critical
317 	 * because a LIKE clause may attempt to create a primary key.  If there's
318 	 * also a pkey in the main CREATE TABLE list, creation of that will not
319 	 * check for a duplicate at runtime (since index_check_primary_key()
320 	 * expects that we rejected dups here).  Creation of the LIKE-generated
321 	 * pkey behaves like ALTER TABLE ADD, so it will check, but obviously that
322 	 * only works if it happens second.  On the other hand, we want to make
323 	 * pkeys before foreign key constraints, in case the user tries to make a
324 	 * self-referential FK.
325 	 */
326 	cxt.alist = list_concat(cxt.alist, cxt.likeclauses);
327 
328 	/*
329 	 * Postprocess foreign-key constraints.
330 	 */
331 	transformFKConstraints(&cxt, true, false);
332 
333 	/*
334 	 * Postprocess check constraints.
335 	 */
336 	transformCheckConstraints(&cxt, !is_foreign_table ? true : false);
337 
338 	/*
339 	 * Postprocess extended statistics.
340 	 */
341 	transformExtendedStatistics(&cxt);
342 
343 	/*
344 	 * Output results.
345 	 */
346 	stmt->tableElts = cxt.columns;
347 	stmt->constraints = cxt.ckconstraints;
348 
349 	result = lappend(cxt.blist, stmt);
350 	result = list_concat(result, cxt.alist);
351 	result = list_concat(result, save_alist);
352 
353 	return result;
354 }
355 
356 /*
357  * generateSerialExtraStmts
358  *		Generate CREATE SEQUENCE and ALTER SEQUENCE ... OWNED BY statements
359  *		to create the sequence for a serial or identity column.
360  *
361  * This includes determining the name the sequence will have.  The caller
362  * can ask to get back the name components by passing non-null pointers
363  * for snamespace_p and sname_p.
364  */
365 static void
generateSerialExtraStmts(CreateStmtContext * cxt,ColumnDef * column,Oid seqtypid,List * seqoptions,bool for_identity,char ** snamespace_p,char ** sname_p)366 generateSerialExtraStmts(CreateStmtContext *cxt, ColumnDef *column,
367 						 Oid seqtypid, List *seqoptions, bool for_identity,
368 						 char **snamespace_p, char **sname_p)
369 {
370 	ListCell   *option;
371 	DefElem    *nameEl = NULL;
372 	Oid			snamespaceid;
373 	char	   *snamespace;
374 	char	   *sname;
375 	CreateSeqStmt *seqstmt;
376 	AlterSeqStmt *altseqstmt;
377 	List	   *attnamelist;
378 
379 	/*
380 	 * Determine namespace and name to use for the sequence.
381 	 *
382 	 * First, check if a sequence name was passed in as an option.  This is
383 	 * used by pg_dump.  Else, generate a name.
384 	 *
385 	 * Although we use ChooseRelationName, it's not guaranteed that the
386 	 * selected sequence name won't conflict; given sufficiently long field
387 	 * names, two different serial columns in the same table could be assigned
388 	 * the same sequence name, and we'd not notice since we aren't creating
389 	 * the sequence quite yet.  In practice this seems quite unlikely to be a
390 	 * problem, especially since few people would need two serial columns in
391 	 * one table.
392 	 */
393 	foreach(option, seqoptions)
394 	{
395 		DefElem    *defel = lfirst_node(DefElem, option);
396 
397 		if (strcmp(defel->defname, "sequence_name") == 0)
398 		{
399 			if (nameEl)
400 				ereport(ERROR,
401 						(errcode(ERRCODE_SYNTAX_ERROR),
402 						 errmsg("conflicting or redundant options")));
403 			nameEl = defel;
404 		}
405 	}
406 
407 	if (nameEl)
408 	{
409 		RangeVar   *rv = makeRangeVarFromNameList(castNode(List, nameEl->arg));
410 
411 		snamespace = rv->schemaname;
412 		if (!snamespace)
413 		{
414 			/* Given unqualified SEQUENCE NAME, select namespace */
415 			if (cxt->rel)
416 				snamespaceid = RelationGetNamespace(cxt->rel);
417 			else
418 				snamespaceid = RangeVarGetCreationNamespace(cxt->relation);
419 			snamespace = get_namespace_name(snamespaceid);
420 		}
421 		sname = rv->relname;
422 		/* Remove the SEQUENCE NAME item from seqoptions */
423 		seqoptions = list_delete_ptr(seqoptions, nameEl);
424 	}
425 	else
426 	{
427 		if (cxt->rel)
428 			snamespaceid = RelationGetNamespace(cxt->rel);
429 		else
430 		{
431 			snamespaceid = RangeVarGetCreationNamespace(cxt->relation);
432 			RangeVarAdjustRelationPersistence(cxt->relation, snamespaceid);
433 		}
434 		snamespace = get_namespace_name(snamespaceid);
435 		sname = ChooseRelationName(cxt->relation->relname,
436 								   column->colname,
437 								   "seq",
438 								   snamespaceid,
439 								   false);
440 	}
441 
442 	ereport(DEBUG1,
443 			(errmsg("%s will create implicit sequence \"%s\" for serial column \"%s.%s\"",
444 					cxt->stmtType, sname,
445 					cxt->relation->relname, column->colname)));
446 
447 	/*
448 	 * Build a CREATE SEQUENCE command to create the sequence object, and add
449 	 * it to the list of things to be done before this CREATE/ALTER TABLE.
450 	 */
451 	seqstmt = makeNode(CreateSeqStmt);
452 	seqstmt->for_identity = for_identity;
453 	seqstmt->sequence = makeRangeVar(snamespace, sname, -1);
454 	seqstmt->options = seqoptions;
455 
456 	/*
457 	 * If a sequence data type was specified, add it to the options.  Prepend
458 	 * to the list rather than append; in case a user supplied their own AS
459 	 * clause, the "redundant options" error will point to their occurrence,
460 	 * not our synthetic one.
461 	 */
462 	if (seqtypid)
463 		seqstmt->options = lcons(makeDefElem("as",
464 											 (Node *) makeTypeNameFromOid(seqtypid, -1),
465 											 -1),
466 								 seqstmt->options);
467 
468 	/*
469 	 * If this is ALTER ADD COLUMN, make sure the sequence will be owned by
470 	 * the table's owner.  The current user might be someone else (perhaps a
471 	 * superuser, or someone who's only a member of the owning role), but the
472 	 * SEQUENCE OWNED BY mechanisms will bleat unless table and sequence have
473 	 * exactly the same owning role.
474 	 */
475 	if (cxt->rel)
476 		seqstmt->ownerId = cxt->rel->rd_rel->relowner;
477 	else
478 		seqstmt->ownerId = InvalidOid;
479 
480 	cxt->blist = lappend(cxt->blist, seqstmt);
481 
482 	/*
483 	 * Store the identity sequence name that we decided on.  ALTER TABLE ...
484 	 * ADD COLUMN ... IDENTITY needs this so that it can fill the new column
485 	 * with values from the sequence, while the association of the sequence
486 	 * with the table is not set until after the ALTER TABLE.
487 	 */
488 	column->identitySequence = seqstmt->sequence;
489 
490 	/*
491 	 * Build an ALTER SEQUENCE ... OWNED BY command to mark the sequence as
492 	 * owned by this column, and add it to the list of things to be done after
493 	 * this CREATE/ALTER TABLE.
494 	 */
495 	altseqstmt = makeNode(AlterSeqStmt);
496 	altseqstmt->sequence = makeRangeVar(snamespace, sname, -1);
497 	attnamelist = list_make3(makeString(snamespace),
498 							 makeString(cxt->relation->relname),
499 							 makeString(column->colname));
500 	altseqstmt->options = list_make1(makeDefElem("owned_by",
501 												 (Node *) attnamelist, -1));
502 	altseqstmt->for_identity = for_identity;
503 
504 	cxt->alist = lappend(cxt->alist, altseqstmt);
505 
506 	if (snamespace_p)
507 		*snamespace_p = snamespace;
508 	if (sname_p)
509 		*sname_p = sname;
510 }
511 
512 /*
513  * transformColumnDefinition -
514  *		transform a single ColumnDef within CREATE TABLE
515  *		Also used in ALTER TABLE ADD COLUMN
516  */
517 static void
transformColumnDefinition(CreateStmtContext * cxt,ColumnDef * column)518 transformColumnDefinition(CreateStmtContext *cxt, ColumnDef *column)
519 {
520 	bool		is_serial;
521 	bool		saw_nullable;
522 	bool		saw_default;
523 	bool		saw_identity;
524 	bool		saw_generated;
525 	ListCell   *clist;
526 
527 	cxt->columns = lappend(cxt->columns, column);
528 
529 	/* Check for SERIAL pseudo-types */
530 	is_serial = false;
531 	if (column->typeName
532 		&& list_length(column->typeName->names) == 1
533 		&& !column->typeName->pct_type)
534 	{
535 		char	   *typname = strVal(linitial(column->typeName->names));
536 
537 		if (strcmp(typname, "smallserial") == 0 ||
538 			strcmp(typname, "serial2") == 0)
539 		{
540 			is_serial = true;
541 			column->typeName->names = NIL;
542 			column->typeName->typeOid = INT2OID;
543 		}
544 		else if (strcmp(typname, "serial") == 0 ||
545 				 strcmp(typname, "serial4") == 0)
546 		{
547 			is_serial = true;
548 			column->typeName->names = NIL;
549 			column->typeName->typeOid = INT4OID;
550 		}
551 		else if (strcmp(typname, "bigserial") == 0 ||
552 				 strcmp(typname, "serial8") == 0)
553 		{
554 			is_serial = true;
555 			column->typeName->names = NIL;
556 			column->typeName->typeOid = INT8OID;
557 		}
558 
559 		/*
560 		 * We have to reject "serial[]" explicitly, because once we've set
561 		 * typeid, LookupTypeName won't notice arrayBounds.  We don't need any
562 		 * special coding for serial(typmod) though.
563 		 */
564 		if (is_serial && column->typeName->arrayBounds != NIL)
565 			ereport(ERROR,
566 					(errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
567 					 errmsg("array of serial is not implemented"),
568 					 parser_errposition(cxt->pstate,
569 										column->typeName->location)));
570 	}
571 
572 	/* Do necessary work on the column type declaration */
573 	if (column->typeName)
574 		transformColumnType(cxt, column);
575 
576 	/* Special actions for SERIAL pseudo-types */
577 	if (is_serial)
578 	{
579 		char	   *snamespace;
580 		char	   *sname;
581 		char	   *qstring;
582 		A_Const    *snamenode;
583 		TypeCast   *castnode;
584 		FuncCall   *funccallnode;
585 		Constraint *constraint;
586 
587 		generateSerialExtraStmts(cxt, column,
588 								 column->typeName->typeOid, NIL, false,
589 								 &snamespace, &sname);
590 
591 		/*
592 		 * Create appropriate constraints for SERIAL.  We do this in full,
593 		 * rather than shortcutting, so that we will detect any conflicting
594 		 * constraints the user wrote (like a different DEFAULT).
595 		 *
596 		 * Create an expression tree representing the function call
597 		 * nextval('sequencename').  We cannot reduce the raw tree to cooked
598 		 * form until after the sequence is created, but there's no need to do
599 		 * so.
600 		 */
601 		qstring = quote_qualified_identifier(snamespace, sname);
602 		snamenode = makeNode(A_Const);
603 		snamenode->val.type = T_String;
604 		snamenode->val.val.str = qstring;
605 		snamenode->location = -1;
606 		castnode = makeNode(TypeCast);
607 		castnode->typeName = SystemTypeName("regclass");
608 		castnode->arg = (Node *) snamenode;
609 		castnode->location = -1;
610 		funccallnode = makeFuncCall(SystemFuncName("nextval"),
611 									list_make1(castnode),
612 									-1);
613 		constraint = makeNode(Constraint);
614 		constraint->contype = CONSTR_DEFAULT;
615 		constraint->location = -1;
616 		constraint->raw_expr = (Node *) funccallnode;
617 		constraint->cooked_expr = NULL;
618 		column->constraints = lappend(column->constraints, constraint);
619 
620 		constraint = makeNode(Constraint);
621 		constraint->contype = CONSTR_NOTNULL;
622 		constraint->location = -1;
623 		column->constraints = lappend(column->constraints, constraint);
624 	}
625 
626 	/* Process column constraints, if any... */
627 	transformConstraintAttrs(cxt, column->constraints);
628 
629 	saw_nullable = false;
630 	saw_default = false;
631 	saw_identity = false;
632 	saw_generated = false;
633 
634 	foreach(clist, column->constraints)
635 	{
636 		Constraint *constraint = lfirst_node(Constraint, clist);
637 
638 		switch (constraint->contype)
639 		{
640 			case CONSTR_NULL:
641 				if (saw_nullable && column->is_not_null)
642 					ereport(ERROR,
643 							(errcode(ERRCODE_SYNTAX_ERROR),
644 							 errmsg("conflicting NULL/NOT NULL declarations for column \"%s\" of table \"%s\"",
645 									column->colname, cxt->relation->relname),
646 							 parser_errposition(cxt->pstate,
647 												constraint->location)));
648 				column->is_not_null = false;
649 				saw_nullable = true;
650 				break;
651 
652 			case CONSTR_NOTNULL:
653 				if (saw_nullable && !column->is_not_null)
654 					ereport(ERROR,
655 							(errcode(ERRCODE_SYNTAX_ERROR),
656 							 errmsg("conflicting NULL/NOT NULL declarations for column \"%s\" of table \"%s\"",
657 									column->colname, cxt->relation->relname),
658 							 parser_errposition(cxt->pstate,
659 												constraint->location)));
660 				column->is_not_null = true;
661 				saw_nullable = true;
662 				break;
663 
664 			case CONSTR_DEFAULT:
665 				if (saw_default)
666 					ereport(ERROR,
667 							(errcode(ERRCODE_SYNTAX_ERROR),
668 							 errmsg("multiple default values specified for column \"%s\" of table \"%s\"",
669 									column->colname, cxt->relation->relname),
670 							 parser_errposition(cxt->pstate,
671 												constraint->location)));
672 				column->raw_default = constraint->raw_expr;
673 				Assert(constraint->cooked_expr == NULL);
674 				saw_default = true;
675 				break;
676 
677 			case CONSTR_IDENTITY:
678 				{
679 					Type		ctype;
680 					Oid			typeOid;
681 
682 					if (cxt->ofType)
683 						ereport(ERROR,
684 								(errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
685 								 errmsg("identity columns are not supported on typed tables")));
686 					if (cxt->partbound)
687 						ereport(ERROR,
688 								(errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
689 								 errmsg("identity columns are not supported on partitions")));
690 
691 					ctype = typenameType(cxt->pstate, column->typeName, NULL);
692 					typeOid = ((Form_pg_type) GETSTRUCT(ctype))->oid;
693 					ReleaseSysCache(ctype);
694 
695 					if (saw_identity)
696 						ereport(ERROR,
697 								(errcode(ERRCODE_SYNTAX_ERROR),
698 								 errmsg("multiple identity specifications for column \"%s\" of table \"%s\"",
699 										column->colname, cxt->relation->relname),
700 								 parser_errposition(cxt->pstate,
701 													constraint->location)));
702 
703 					generateSerialExtraStmts(cxt, column,
704 											 typeOid, constraint->options, true,
705 											 NULL, NULL);
706 
707 					column->identity = constraint->generated_when;
708 					saw_identity = true;
709 
710 					/* An identity column is implicitly NOT NULL */
711 					if (saw_nullable && !column->is_not_null)
712 						ereport(ERROR,
713 								(errcode(ERRCODE_SYNTAX_ERROR),
714 								 errmsg("conflicting NULL/NOT NULL declarations for column \"%s\" of table \"%s\"",
715 										column->colname, cxt->relation->relname),
716 								 parser_errposition(cxt->pstate,
717 													constraint->location)));
718 					column->is_not_null = true;
719 					saw_nullable = true;
720 					break;
721 				}
722 
723 			case CONSTR_GENERATED:
724 				if (cxt->ofType)
725 					ereport(ERROR,
726 							(errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
727 							 errmsg("generated columns are not supported on typed tables")));
728 				if (cxt->partbound)
729 					ereport(ERROR,
730 							(errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
731 							 errmsg("generated columns are not supported on partitions")));
732 
733 				if (saw_generated)
734 					ereport(ERROR,
735 							(errcode(ERRCODE_SYNTAX_ERROR),
736 							 errmsg("multiple generation clauses specified for column \"%s\" of table \"%s\"",
737 									column->colname, cxt->relation->relname),
738 							 parser_errposition(cxt->pstate,
739 												constraint->location)));
740 				column->generated = ATTRIBUTE_GENERATED_STORED;
741 				column->raw_default = constraint->raw_expr;
742 				Assert(constraint->cooked_expr == NULL);
743 				saw_generated = true;
744 				break;
745 
746 			case CONSTR_CHECK:
747 				cxt->ckconstraints = lappend(cxt->ckconstraints, constraint);
748 				break;
749 
750 			case CONSTR_PRIMARY:
751 				if (cxt->isforeign)
752 					ereport(ERROR,
753 							(errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
754 							 errmsg("primary key constraints are not supported on foreign tables"),
755 							 parser_errposition(cxt->pstate,
756 												constraint->location)));
757 				/* FALL THRU */
758 
759 			case CONSTR_UNIQUE:
760 				if (cxt->isforeign)
761 					ereport(ERROR,
762 							(errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
763 							 errmsg("unique constraints are not supported on foreign tables"),
764 							 parser_errposition(cxt->pstate,
765 												constraint->location)));
766 				if (constraint->keys == NIL)
767 					constraint->keys = list_make1(makeString(column->colname));
768 				cxt->ixconstraints = lappend(cxt->ixconstraints, constraint);
769 				break;
770 
771 			case CONSTR_EXCLUSION:
772 				/* grammar does not allow EXCLUDE as a column constraint */
773 				elog(ERROR, "column exclusion constraints are not supported");
774 				break;
775 
776 			case CONSTR_FOREIGN:
777 				if (cxt->isforeign)
778 					ereport(ERROR,
779 							(errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
780 							 errmsg("foreign key constraints are not supported on foreign tables"),
781 							 parser_errposition(cxt->pstate,
782 												constraint->location)));
783 
784 				/*
785 				 * Fill in the current attribute's name and throw it into the
786 				 * list of FK constraints to be processed later.
787 				 */
788 				constraint->fk_attrs = list_make1(makeString(column->colname));
789 				cxt->fkconstraints = lappend(cxt->fkconstraints, constraint);
790 				break;
791 
792 			case CONSTR_ATTR_DEFERRABLE:
793 			case CONSTR_ATTR_NOT_DEFERRABLE:
794 			case CONSTR_ATTR_DEFERRED:
795 			case CONSTR_ATTR_IMMEDIATE:
796 				/* transformConstraintAttrs took care of these */
797 				break;
798 
799 			default:
800 				elog(ERROR, "unrecognized constraint type: %d",
801 					 constraint->contype);
802 				break;
803 		}
804 
805 		if (saw_default && saw_identity)
806 			ereport(ERROR,
807 					(errcode(ERRCODE_SYNTAX_ERROR),
808 					 errmsg("both default and identity specified for column \"%s\" of table \"%s\"",
809 							column->colname, cxt->relation->relname),
810 					 parser_errposition(cxt->pstate,
811 										constraint->location)));
812 
813 		if (saw_default && saw_generated)
814 			ereport(ERROR,
815 					(errcode(ERRCODE_SYNTAX_ERROR),
816 					 errmsg("both default and generation expression specified for column \"%s\" of table \"%s\"",
817 							column->colname, cxt->relation->relname),
818 					 parser_errposition(cxt->pstate,
819 										constraint->location)));
820 
821 		if (saw_identity && saw_generated)
822 			ereport(ERROR,
823 					(errcode(ERRCODE_SYNTAX_ERROR),
824 					 errmsg("both identity and generation expression specified for column \"%s\" of table \"%s\"",
825 							column->colname, cxt->relation->relname),
826 					 parser_errposition(cxt->pstate,
827 										constraint->location)));
828 	}
829 
830 	/*
831 	 * If needed, generate ALTER FOREIGN TABLE ALTER COLUMN statement to add
832 	 * per-column foreign data wrapper options to this column after creation.
833 	 */
834 	if (column->fdwoptions != NIL)
835 	{
836 		AlterTableStmt *stmt;
837 		AlterTableCmd *cmd;
838 
839 		cmd = makeNode(AlterTableCmd);
840 		cmd->subtype = AT_AlterColumnGenericOptions;
841 		cmd->name = column->colname;
842 		cmd->def = (Node *) column->fdwoptions;
843 		cmd->behavior = DROP_RESTRICT;
844 		cmd->missing_ok = false;
845 
846 		stmt = makeNode(AlterTableStmt);
847 		stmt->relation = cxt->relation;
848 		stmt->cmds = NIL;
849 		stmt->relkind = OBJECT_FOREIGN_TABLE;
850 		stmt->cmds = lappend(stmt->cmds, cmd);
851 
852 		cxt->alist = lappend(cxt->alist, stmt);
853 	}
854 }
855 
856 /*
857  * transformTableConstraint
858  *		transform a Constraint node within CREATE TABLE or ALTER TABLE
859  */
860 static void
transformTableConstraint(CreateStmtContext * cxt,Constraint * constraint)861 transformTableConstraint(CreateStmtContext *cxt, Constraint *constraint)
862 {
863 	switch (constraint->contype)
864 	{
865 		case CONSTR_PRIMARY:
866 			if (cxt->isforeign)
867 				ereport(ERROR,
868 						(errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
869 						 errmsg("primary key constraints are not supported on foreign tables"),
870 						 parser_errposition(cxt->pstate,
871 											constraint->location)));
872 			cxt->ixconstraints = lappend(cxt->ixconstraints, constraint);
873 			break;
874 
875 		case CONSTR_UNIQUE:
876 			if (cxt->isforeign)
877 				ereport(ERROR,
878 						(errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
879 						 errmsg("unique constraints are not supported on foreign tables"),
880 						 parser_errposition(cxt->pstate,
881 											constraint->location)));
882 			cxt->ixconstraints = lappend(cxt->ixconstraints, constraint);
883 			break;
884 
885 		case CONSTR_EXCLUSION:
886 			if (cxt->isforeign)
887 				ereport(ERROR,
888 						(errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
889 						 errmsg("exclusion constraints are not supported on foreign tables"),
890 						 parser_errposition(cxt->pstate,
891 											constraint->location)));
892 			if (cxt->ispartitioned)
893 				ereport(ERROR,
894 						(errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
895 						 errmsg("exclusion constraints are not supported on partitioned tables"),
896 						 parser_errposition(cxt->pstate,
897 											constraint->location)));
898 			cxt->ixconstraints = lappend(cxt->ixconstraints, constraint);
899 			break;
900 
901 		case CONSTR_CHECK:
902 			cxt->ckconstraints = lappend(cxt->ckconstraints, constraint);
903 			break;
904 
905 		case CONSTR_FOREIGN:
906 			if (cxt->isforeign)
907 				ereport(ERROR,
908 						(errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
909 						 errmsg("foreign key constraints are not supported on foreign tables"),
910 						 parser_errposition(cxt->pstate,
911 											constraint->location)));
912 			cxt->fkconstraints = lappend(cxt->fkconstraints, constraint);
913 			break;
914 
915 		case CONSTR_NULL:
916 		case CONSTR_NOTNULL:
917 		case CONSTR_DEFAULT:
918 		case CONSTR_ATTR_DEFERRABLE:
919 		case CONSTR_ATTR_NOT_DEFERRABLE:
920 		case CONSTR_ATTR_DEFERRED:
921 		case CONSTR_ATTR_IMMEDIATE:
922 			elog(ERROR, "invalid context for constraint type %d",
923 				 constraint->contype);
924 			break;
925 
926 		default:
927 			elog(ERROR, "unrecognized constraint type: %d",
928 				 constraint->contype);
929 			break;
930 	}
931 }
932 
933 /*
934  * transformTableLikeClause
935  *
936  * Change the LIKE <srctable> portion of a CREATE TABLE statement into
937  * column definitions that recreate the user defined column portions of
938  * <srctable>.  Also, if there are any LIKE options that we can't fully
939  * process at this point, add the TableLikeClause to cxt->likeclauses, which
940  * will cause utility.c to call expandTableLikeClause() after the new
941  * table has been created.
942  */
943 static void
transformTableLikeClause(CreateStmtContext * cxt,TableLikeClause * table_like_clause)944 transformTableLikeClause(CreateStmtContext *cxt, TableLikeClause *table_like_clause)
945 {
946 	AttrNumber	parent_attno;
947 	Relation	relation;
948 	TupleDesc	tupleDesc;
949 	AclResult	aclresult;
950 	char	   *comment;
951 	ParseCallbackState pcbstate;
952 
953 	setup_parser_errposition_callback(&pcbstate, cxt->pstate,
954 									  table_like_clause->relation->location);
955 
956 	/* we could support LIKE in many cases, but worry about it another day */
957 	if (cxt->isforeign)
958 		ereport(ERROR,
959 				(errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
960 				 errmsg("LIKE is not supported for creating foreign tables")));
961 
962 	/* Open the relation referenced by the LIKE clause */
963 	relation = relation_openrv(table_like_clause->relation, AccessShareLock);
964 
965 	if (relation->rd_rel->relkind != RELKIND_RELATION &&
966 		relation->rd_rel->relkind != RELKIND_VIEW &&
967 		relation->rd_rel->relkind != RELKIND_MATVIEW &&
968 		relation->rd_rel->relkind != RELKIND_COMPOSITE_TYPE &&
969 		relation->rd_rel->relkind != RELKIND_FOREIGN_TABLE &&
970 		relation->rd_rel->relkind != RELKIND_PARTITIONED_TABLE)
971 		ereport(ERROR,
972 				(errcode(ERRCODE_WRONG_OBJECT_TYPE),
973 				 errmsg("\"%s\" is not a table, view, materialized view, composite type, or foreign table",
974 						RelationGetRelationName(relation))));
975 
976 	cancel_parser_errposition_callback(&pcbstate);
977 
978 	/*
979 	 * Check for privileges
980 	 */
981 	if (relation->rd_rel->relkind == RELKIND_COMPOSITE_TYPE)
982 	{
983 		aclresult = pg_type_aclcheck(relation->rd_rel->reltype, GetUserId(),
984 									 ACL_USAGE);
985 		if (aclresult != ACLCHECK_OK)
986 			aclcheck_error(aclresult, OBJECT_TYPE,
987 						   RelationGetRelationName(relation));
988 	}
989 	else
990 	{
991 		aclresult = pg_class_aclcheck(RelationGetRelid(relation), GetUserId(),
992 									  ACL_SELECT);
993 		if (aclresult != ACLCHECK_OK)
994 			aclcheck_error(aclresult, get_relkind_objtype(relation->rd_rel->relkind),
995 						   RelationGetRelationName(relation));
996 	}
997 
998 	tupleDesc = RelationGetDescr(relation);
999 
1000 	/*
1001 	 * Insert the copied attributes into the cxt for the new table definition.
1002 	 * We must do this now so that they appear in the table in the relative
1003 	 * position where the LIKE clause is, as required by SQL99.
1004 	 */
1005 	for (parent_attno = 1; parent_attno <= tupleDesc->natts;
1006 		 parent_attno++)
1007 	{
1008 		Form_pg_attribute attribute = TupleDescAttr(tupleDesc,
1009 													parent_attno - 1);
1010 		char	   *attributeName = NameStr(attribute->attname);
1011 		ColumnDef  *def;
1012 
1013 		/*
1014 		 * Ignore dropped columns in the parent.
1015 		 */
1016 		if (attribute->attisdropped)
1017 			continue;
1018 
1019 		/*
1020 		 * Create a new column, which is marked as NOT inherited.
1021 		 *
1022 		 * For constraints, ONLY the NOT NULL constraint is inherited by the
1023 		 * new column definition per SQL99.
1024 		 */
1025 		def = makeNode(ColumnDef);
1026 		def->colname = pstrdup(attributeName);
1027 		def->typeName = makeTypeNameFromOid(attribute->atttypid,
1028 											attribute->atttypmod);
1029 		def->inhcount = 0;
1030 		def->is_local = true;
1031 		def->is_not_null = attribute->attnotnull;
1032 		def->is_from_type = false;
1033 		def->storage = 0;
1034 		def->raw_default = NULL;
1035 		def->cooked_default = NULL;
1036 		def->collClause = NULL;
1037 		def->collOid = attribute->attcollation;
1038 		def->constraints = NIL;
1039 		def->location = -1;
1040 
1041 		/*
1042 		 * Add to column list
1043 		 */
1044 		cxt->columns = lappend(cxt->columns, def);
1045 
1046 		/*
1047 		 * Although we don't transfer the column's default/generation
1048 		 * expression now, we need to mark it GENERATED if appropriate.
1049 		 */
1050 		if (attribute->atthasdef && attribute->attgenerated &&
1051 			(table_like_clause->options & CREATE_TABLE_LIKE_GENERATED))
1052 			def->generated = attribute->attgenerated;
1053 
1054 		/*
1055 		 * Copy identity if requested
1056 		 */
1057 		if (attribute->attidentity &&
1058 			(table_like_clause->options & CREATE_TABLE_LIKE_IDENTITY))
1059 		{
1060 			Oid			seq_relid;
1061 			List	   *seq_options;
1062 
1063 			/*
1064 			 * find sequence owned by old column; extract sequence parameters;
1065 			 * build new create sequence command
1066 			 */
1067 			seq_relid = getOwnedSequence(RelationGetRelid(relation), attribute->attnum);
1068 			seq_options = sequence_options(seq_relid);
1069 			generateSerialExtraStmts(cxt, def,
1070 									 InvalidOid, seq_options, true,
1071 									 NULL, NULL);
1072 			def->identity = attribute->attidentity;
1073 		}
1074 
1075 		/* Likewise, copy storage if requested */
1076 		if (table_like_clause->options & CREATE_TABLE_LIKE_STORAGE)
1077 			def->storage = attribute->attstorage;
1078 		else
1079 			def->storage = 0;
1080 
1081 		/* Likewise, copy comment if requested */
1082 		if ((table_like_clause->options & CREATE_TABLE_LIKE_COMMENTS) &&
1083 			(comment = GetComment(attribute->attrelid,
1084 								  RelationRelationId,
1085 								  attribute->attnum)) != NULL)
1086 		{
1087 			CommentStmt *stmt = makeNode(CommentStmt);
1088 
1089 			stmt->objtype = OBJECT_COLUMN;
1090 			stmt->object = (Node *) list_make3(makeString(cxt->relation->schemaname),
1091 											   makeString(cxt->relation->relname),
1092 											   makeString(def->colname));
1093 			stmt->comment = comment;
1094 
1095 			cxt->alist = lappend(cxt->alist, stmt);
1096 		}
1097 	}
1098 
1099 	/*
1100 	 * We cannot yet deal with defaults, CHECK constraints, or indexes, since
1101 	 * we don't yet know what column numbers the copied columns will have in
1102 	 * the finished table.  If any of those options are specified, add the
1103 	 * LIKE clause to cxt->likeclauses so that expandTableLikeClause will be
1104 	 * called after we do know that.  Also, remember the relation OID so that
1105 	 * expandTableLikeClause is certain to open the same table.
1106 	 */
1107 	if (table_like_clause->options &
1108 		(CREATE_TABLE_LIKE_DEFAULTS |
1109 		 CREATE_TABLE_LIKE_GENERATED |
1110 		 CREATE_TABLE_LIKE_CONSTRAINTS |
1111 		 CREATE_TABLE_LIKE_INDEXES))
1112 	{
1113 		table_like_clause->relationOid = RelationGetRelid(relation);
1114 		cxt->likeclauses = lappend(cxt->likeclauses, table_like_clause);
1115 	}
1116 
1117 	/*
1118 	 * We may copy extended statistics if requested, since the representation
1119 	 * of CreateStatsStmt doesn't depend on column numbers.
1120 	 */
1121 	if (table_like_clause->options & CREATE_TABLE_LIKE_STATISTICS)
1122 	{
1123 		List	   *parent_extstats;
1124 		ListCell   *l;
1125 
1126 		parent_extstats = RelationGetStatExtList(relation);
1127 
1128 		foreach(l, parent_extstats)
1129 		{
1130 			Oid			parent_stat_oid = lfirst_oid(l);
1131 			CreateStatsStmt *stats_stmt;
1132 
1133 			stats_stmt = generateClonedExtStatsStmt(cxt->relation,
1134 													RelationGetRelid(relation),
1135 													parent_stat_oid);
1136 
1137 			/* Copy comment on statistics object, if requested */
1138 			if (table_like_clause->options & CREATE_TABLE_LIKE_COMMENTS)
1139 			{
1140 				comment = GetComment(parent_stat_oid, StatisticExtRelationId, 0);
1141 
1142 				/*
1143 				 * We make use of CreateStatsStmt's stxcomment option, so as
1144 				 * not to need to know now what name the statistics will have.
1145 				 */
1146 				stats_stmt->stxcomment = comment;
1147 			}
1148 
1149 			cxt->extstats = lappend(cxt->extstats, stats_stmt);
1150 		}
1151 
1152 		list_free(parent_extstats);
1153 	}
1154 
1155 	/*
1156 	 * Close the parent rel, but keep our AccessShareLock on it until xact
1157 	 * commit.  That will prevent someone else from deleting or ALTERing the
1158 	 * parent before we can run expandTableLikeClause.
1159 	 */
1160 	table_close(relation, NoLock);
1161 }
1162 
1163 /*
1164  * expandTableLikeClause
1165  *
1166  * Process LIKE options that require knowing the final column numbers
1167  * assigned to the new table's columns.  This executes after we have
1168  * run DefineRelation for the new table.  It returns a list of utility
1169  * commands that should be run to generate indexes etc.
1170  */
1171 List *
expandTableLikeClause(RangeVar * heapRel,TableLikeClause * table_like_clause)1172 expandTableLikeClause(RangeVar *heapRel, TableLikeClause *table_like_clause)
1173 {
1174 	List	   *result = NIL;
1175 	List	   *atsubcmds = NIL;
1176 	AttrNumber	parent_attno;
1177 	Relation	relation;
1178 	Relation	childrel;
1179 	TupleDesc	tupleDesc;
1180 	TupleConstr *constr;
1181 	AttrNumber *attmap;
1182 	char	   *comment;
1183 
1184 	/*
1185 	 * Open the relation referenced by the LIKE clause.  We should still have
1186 	 * the table lock obtained by transformTableLikeClause (and this'll throw
1187 	 * an assertion failure if not).  Hence, no need to recheck privileges
1188 	 * etc.  We must open the rel by OID not name, to be sure we get the same
1189 	 * table.
1190 	 */
1191 	if (!OidIsValid(table_like_clause->relationOid))
1192 		elog(ERROR, "expandTableLikeClause called on untransformed LIKE clause");
1193 
1194 	relation = relation_open(table_like_clause->relationOid, NoLock);
1195 
1196 	tupleDesc = RelationGetDescr(relation);
1197 	constr = tupleDesc->constr;
1198 
1199 	/*
1200 	 * Open the newly-created child relation; we have lock on that too.
1201 	 */
1202 	childrel = relation_openrv(heapRel, NoLock);
1203 
1204 	/*
1205 	 * Construct a map from the LIKE relation's attnos to the child rel's.
1206 	 * This re-checks type match etc, although it shouldn't be possible to
1207 	 * have a failure since both tables are locked.
1208 	 */
1209 	attmap = convert_tuples_by_name_map(RelationGetDescr(childrel),
1210 										tupleDesc,
1211 										gettext_noop("could not convert row type"));
1212 
1213 	/*
1214 	 * Process defaults, if required.
1215 	 */
1216 	if ((table_like_clause->options &
1217 		 (CREATE_TABLE_LIKE_DEFAULTS | CREATE_TABLE_LIKE_GENERATED)) &&
1218 		constr != NULL)
1219 	{
1220 		AttrDefault *attrdef = constr->defval;
1221 
1222 		for (parent_attno = 1; parent_attno <= tupleDesc->natts;
1223 			 parent_attno++)
1224 		{
1225 			Form_pg_attribute attribute = TupleDescAttr(tupleDesc,
1226 														parent_attno - 1);
1227 
1228 			/*
1229 			 * Ignore dropped columns in the parent.
1230 			 */
1231 			if (attribute->attisdropped)
1232 				continue;
1233 
1234 			/*
1235 			 * Copy default, if present and it should be copied.  We have
1236 			 * separate options for plain default expressions and GENERATED
1237 			 * defaults.
1238 			 */
1239 			if (attribute->atthasdef &&
1240 				(attribute->attgenerated ?
1241 				 (table_like_clause->options & CREATE_TABLE_LIKE_GENERATED) :
1242 				 (table_like_clause->options & CREATE_TABLE_LIKE_DEFAULTS)))
1243 			{
1244 				Node	   *this_default = NULL;
1245 				AlterTableCmd *atsubcmd;
1246 				bool		found_whole_row;
1247 
1248 				/* Find default in constraint structure */
1249 				for (int i = 0; i < constr->num_defval; i++)
1250 				{
1251 					if (attrdef[i].adnum == parent_attno)
1252 					{
1253 						this_default = stringToNode(attrdef[i].adbin);
1254 						break;
1255 					}
1256 				}
1257 				Assert(this_default != NULL);
1258 
1259 				atsubcmd = makeNode(AlterTableCmd);
1260 				atsubcmd->subtype = AT_CookedColumnDefault;
1261 				atsubcmd->num = attmap[parent_attno - 1];
1262 				atsubcmd->def = map_variable_attnos(this_default,
1263 													1, 0,
1264 													attmap, tupleDesc->natts,
1265 													InvalidOid,
1266 													&found_whole_row);
1267 
1268 				/*
1269 				 * Prevent this for the same reason as for constraints below.
1270 				 * Note that defaults cannot contain any vars, so it's OK that
1271 				 * the error message refers to generated columns.
1272 				 */
1273 				if (found_whole_row)
1274 					ereport(ERROR,
1275 							(errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
1276 							 errmsg("cannot convert whole-row table reference"),
1277 							 errdetail("Generation expression for column \"%s\" contains a whole-row reference to table \"%s\".",
1278 									   NameStr(attribute->attname),
1279 									   RelationGetRelationName(relation))));
1280 
1281 				atsubcmds = lappend(atsubcmds, atsubcmd);
1282 			}
1283 		}
1284 	}
1285 
1286 	/*
1287 	 * Copy CHECK constraints if requested, being careful to adjust attribute
1288 	 * numbers so they match the child.
1289 	 */
1290 	if ((table_like_clause->options & CREATE_TABLE_LIKE_CONSTRAINTS) &&
1291 		constr != NULL)
1292 	{
1293 		int			ccnum;
1294 
1295 		for (ccnum = 0; ccnum < constr->num_check; ccnum++)
1296 		{
1297 			char	   *ccname = constr->check[ccnum].ccname;
1298 			char	   *ccbin = constr->check[ccnum].ccbin;
1299 			Node	   *ccbin_node;
1300 			bool		found_whole_row;
1301 			Constraint *n;
1302 			AlterTableCmd *atsubcmd;
1303 
1304 			ccbin_node = map_variable_attnos(stringToNode(ccbin),
1305 											 1, 0,
1306 											 attmap, tupleDesc->natts,
1307 											 InvalidOid, &found_whole_row);
1308 
1309 			/*
1310 			 * We reject whole-row variables because the whole point of LIKE
1311 			 * is that the new table's rowtype might later diverge from the
1312 			 * parent's.  So, while translation might be possible right now,
1313 			 * it wouldn't be possible to guarantee it would work in future.
1314 			 */
1315 			if (found_whole_row)
1316 				ereport(ERROR,
1317 						(errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
1318 						 errmsg("cannot convert whole-row table reference"),
1319 						 errdetail("Constraint \"%s\" contains a whole-row reference to table \"%s\".",
1320 								   ccname,
1321 								   RelationGetRelationName(relation))));
1322 
1323 			n = makeNode(Constraint);
1324 			n->contype = CONSTR_CHECK;
1325 			n->location = -1;
1326 			n->conname = pstrdup(ccname);
1327 			n->raw_expr = NULL;
1328 			n->cooked_expr = nodeToString(ccbin_node);
1329 
1330 			/* We can skip validation, since the new table should be empty. */
1331 			n->skip_validation = true;
1332 			n->initially_valid = true;
1333 
1334 			atsubcmd = makeNode(AlterTableCmd);
1335 			atsubcmd->subtype = AT_AddConstraint;
1336 			atsubcmd->def = (Node *) n;
1337 			atsubcmds = lappend(atsubcmds, atsubcmd);
1338 
1339 			/* Copy comment on constraint */
1340 			if ((table_like_clause->options & CREATE_TABLE_LIKE_COMMENTS) &&
1341 				(comment = GetComment(get_relation_constraint_oid(RelationGetRelid(relation),
1342 																  n->conname, false),
1343 									  ConstraintRelationId,
1344 									  0)) != NULL)
1345 			{
1346 				CommentStmt *stmt = makeNode(CommentStmt);
1347 
1348 				stmt->objtype = OBJECT_TABCONSTRAINT;
1349 				stmt->object = (Node *) list_make3(makeString(heapRel->schemaname),
1350 												   makeString(heapRel->relname),
1351 												   makeString(n->conname));
1352 				stmt->comment = comment;
1353 
1354 				result = lappend(result, stmt);
1355 			}
1356 		}
1357 	}
1358 
1359 	/*
1360 	 * If we generated any ALTER TABLE actions above, wrap them into a single
1361 	 * ALTER TABLE command.  Stick it at the front of the result, so it runs
1362 	 * before any CommentStmts we made above.
1363 	 */
1364 	if (atsubcmds)
1365 	{
1366 		AlterTableStmt *atcmd = makeNode(AlterTableStmt);
1367 
1368 		atcmd->relation = copyObject(heapRel);
1369 		atcmd->cmds = atsubcmds;
1370 		atcmd->relkind = OBJECT_TABLE;
1371 		atcmd->missing_ok = false;
1372 		result = lcons(atcmd, result);
1373 	}
1374 
1375 	/*
1376 	 * Process indexes if required.
1377 	 */
1378 	if ((table_like_clause->options & CREATE_TABLE_LIKE_INDEXES) &&
1379 		relation->rd_rel->relhasindex)
1380 	{
1381 		List	   *parent_indexes;
1382 		ListCell   *l;
1383 
1384 		parent_indexes = RelationGetIndexList(relation);
1385 
1386 		foreach(l, parent_indexes)
1387 		{
1388 			Oid			parent_index_oid = lfirst_oid(l);
1389 			Relation	parent_index;
1390 			IndexStmt  *index_stmt;
1391 
1392 			parent_index = index_open(parent_index_oid, AccessShareLock);
1393 
1394 			/* Build CREATE INDEX statement to recreate the parent_index */
1395 			index_stmt = generateClonedIndexStmt(heapRel,
1396 												 parent_index,
1397 												 attmap, tupleDesc->natts,
1398 												 NULL);
1399 
1400 			/* Copy comment on index, if requested */
1401 			if (table_like_clause->options & CREATE_TABLE_LIKE_COMMENTS)
1402 			{
1403 				comment = GetComment(parent_index_oid, RelationRelationId, 0);
1404 
1405 				/*
1406 				 * We make use of IndexStmt's idxcomment option, so as not to
1407 				 * need to know now what name the index will have.
1408 				 */
1409 				index_stmt->idxcomment = comment;
1410 			}
1411 
1412 			result = lappend(result, index_stmt);
1413 
1414 			index_close(parent_index, AccessShareLock);
1415 		}
1416 	}
1417 
1418 	/* Done with child rel */
1419 	table_close(childrel, NoLock);
1420 
1421 	/*
1422 	 * Close the parent rel, but keep our AccessShareLock on it until xact
1423 	 * commit.  That will prevent someone else from deleting or ALTERing the
1424 	 * parent before the child is committed.
1425 	 */
1426 	table_close(relation, NoLock);
1427 
1428 	return result;
1429 }
1430 
1431 static void
transformOfType(CreateStmtContext * cxt,TypeName * ofTypename)1432 transformOfType(CreateStmtContext *cxt, TypeName *ofTypename)
1433 {
1434 	HeapTuple	tuple;
1435 	TupleDesc	tupdesc;
1436 	int			i;
1437 	Oid			ofTypeId;
1438 
1439 	AssertArg(ofTypename);
1440 
1441 	tuple = typenameType(NULL, ofTypename, NULL);
1442 	check_of_type(tuple);
1443 	ofTypeId = ((Form_pg_type) GETSTRUCT(tuple))->oid;
1444 	ofTypename->typeOid = ofTypeId; /* cached for later */
1445 
1446 	tupdesc = lookup_rowtype_tupdesc(ofTypeId, -1);
1447 	for (i = 0; i < tupdesc->natts; i++)
1448 	{
1449 		Form_pg_attribute attr = TupleDescAttr(tupdesc, i);
1450 		ColumnDef  *n;
1451 
1452 		if (attr->attisdropped)
1453 			continue;
1454 
1455 		n = makeNode(ColumnDef);
1456 		n->colname = pstrdup(NameStr(attr->attname));
1457 		n->typeName = makeTypeNameFromOid(attr->atttypid, attr->atttypmod);
1458 		n->inhcount = 0;
1459 		n->is_local = true;
1460 		n->is_not_null = false;
1461 		n->is_from_type = true;
1462 		n->storage = 0;
1463 		n->raw_default = NULL;
1464 		n->cooked_default = NULL;
1465 		n->collClause = NULL;
1466 		n->collOid = attr->attcollation;
1467 		n->constraints = NIL;
1468 		n->location = -1;
1469 		cxt->columns = lappend(cxt->columns, n);
1470 	}
1471 	DecrTupleDescRefCount(tupdesc);
1472 
1473 	ReleaseSysCache(tuple);
1474 }
1475 
1476 /*
1477  * Generate an IndexStmt node using information from an already existing index
1478  * "source_idx".
1479  *
1480  * heapRel is stored into the IndexStmt's relation field, but we don't use it
1481  * otherwise; some callers pass NULL, if they don't need it to be valid.
1482  * (The target relation might not exist yet, so we mustn't try to access it.)
1483  *
1484  * Attribute numbers in expression Vars are adjusted according to attmap.
1485  *
1486  * If constraintOid isn't NULL, we store the OID of any constraint associated
1487  * with the index there.
1488  *
1489  * Unlike transformIndexConstraint, we don't make any effort to force primary
1490  * key columns to be NOT NULL.  The larger cloning process this is part of
1491  * should have cloned their NOT NULL status separately (and DefineIndex will
1492  * complain if that fails to happen).
1493  */
1494 IndexStmt *
generateClonedIndexStmt(RangeVar * heapRel,Relation source_idx,const AttrNumber * attmap,int attmap_length,Oid * constraintOid)1495 generateClonedIndexStmt(RangeVar *heapRel, Relation source_idx,
1496 						const AttrNumber *attmap, int attmap_length,
1497 						Oid *constraintOid)
1498 {
1499 	Oid			source_relid = RelationGetRelid(source_idx);
1500 	HeapTuple	ht_idxrel;
1501 	HeapTuple	ht_idx;
1502 	HeapTuple	ht_am;
1503 	Form_pg_class idxrelrec;
1504 	Form_pg_index idxrec;
1505 	Form_pg_am	amrec;
1506 	oidvector  *indcollation;
1507 	oidvector  *indclass;
1508 	IndexStmt  *index;
1509 	List	   *indexprs;
1510 	ListCell   *indexpr_item;
1511 	Oid			indrelid;
1512 	int			keyno;
1513 	Oid			keycoltype;
1514 	Datum		datum;
1515 	bool		isnull;
1516 
1517 	if (constraintOid)
1518 		*constraintOid = InvalidOid;
1519 
1520 	/*
1521 	 * Fetch pg_class tuple of source index.  We can't use the copy in the
1522 	 * relcache entry because it doesn't include optional fields.
1523 	 */
1524 	ht_idxrel = SearchSysCache1(RELOID, ObjectIdGetDatum(source_relid));
1525 	if (!HeapTupleIsValid(ht_idxrel))
1526 		elog(ERROR, "cache lookup failed for relation %u", source_relid);
1527 	idxrelrec = (Form_pg_class) GETSTRUCT(ht_idxrel);
1528 
1529 	/* Fetch pg_index tuple for source index from relcache entry */
1530 	ht_idx = source_idx->rd_indextuple;
1531 	idxrec = (Form_pg_index) GETSTRUCT(ht_idx);
1532 	indrelid = idxrec->indrelid;
1533 
1534 	/* Fetch the pg_am tuple of the index' access method */
1535 	ht_am = SearchSysCache1(AMOID, ObjectIdGetDatum(idxrelrec->relam));
1536 	if (!HeapTupleIsValid(ht_am))
1537 		elog(ERROR, "cache lookup failed for access method %u",
1538 			 idxrelrec->relam);
1539 	amrec = (Form_pg_am) GETSTRUCT(ht_am);
1540 
1541 	/* Extract indcollation from the pg_index tuple */
1542 	datum = SysCacheGetAttr(INDEXRELID, ht_idx,
1543 							Anum_pg_index_indcollation, &isnull);
1544 	Assert(!isnull);
1545 	indcollation = (oidvector *) DatumGetPointer(datum);
1546 
1547 	/* Extract indclass from the pg_index tuple */
1548 	datum = SysCacheGetAttr(INDEXRELID, ht_idx,
1549 							Anum_pg_index_indclass, &isnull);
1550 	Assert(!isnull);
1551 	indclass = (oidvector *) DatumGetPointer(datum);
1552 
1553 	/* Begin building the IndexStmt */
1554 	index = makeNode(IndexStmt);
1555 	index->relation = heapRel;
1556 	index->accessMethod = pstrdup(NameStr(amrec->amname));
1557 	if (OidIsValid(idxrelrec->reltablespace))
1558 		index->tableSpace = get_tablespace_name(idxrelrec->reltablespace);
1559 	else
1560 		index->tableSpace = NULL;
1561 	index->excludeOpNames = NIL;
1562 	index->idxcomment = NULL;
1563 	index->indexOid = InvalidOid;
1564 	index->oldNode = InvalidOid;
1565 	index->unique = idxrec->indisunique;
1566 	index->primary = idxrec->indisprimary;
1567 	index->transformed = true;	/* don't need transformIndexStmt */
1568 	index->concurrent = false;
1569 	index->if_not_exists = false;
1570 	index->reset_default_tblspc = false;
1571 
1572 	/*
1573 	 * We don't try to preserve the name of the source index; instead, just
1574 	 * let DefineIndex() choose a reasonable name.  (If we tried to preserve
1575 	 * the name, we'd get duplicate-relation-name failures unless the source
1576 	 * table was in a different schema.)
1577 	 */
1578 	index->idxname = NULL;
1579 
1580 	/*
1581 	 * If the index is marked PRIMARY or has an exclusion condition, it's
1582 	 * certainly from a constraint; else, if it's not marked UNIQUE, it
1583 	 * certainly isn't.  If it is or might be from a constraint, we have to
1584 	 * fetch the pg_constraint record.
1585 	 */
1586 	if (index->primary || index->unique || idxrec->indisexclusion)
1587 	{
1588 		Oid			constraintId = get_index_constraint(source_relid);
1589 
1590 		if (OidIsValid(constraintId))
1591 		{
1592 			HeapTuple	ht_constr;
1593 			Form_pg_constraint conrec;
1594 
1595 			if (constraintOid)
1596 				*constraintOid = constraintId;
1597 
1598 			ht_constr = SearchSysCache1(CONSTROID,
1599 										ObjectIdGetDatum(constraintId));
1600 			if (!HeapTupleIsValid(ht_constr))
1601 				elog(ERROR, "cache lookup failed for constraint %u",
1602 					 constraintId);
1603 			conrec = (Form_pg_constraint) GETSTRUCT(ht_constr);
1604 
1605 			index->isconstraint = true;
1606 			index->deferrable = conrec->condeferrable;
1607 			index->initdeferred = conrec->condeferred;
1608 
1609 			/* If it's an exclusion constraint, we need the operator names */
1610 			if (idxrec->indisexclusion)
1611 			{
1612 				Datum	   *elems;
1613 				int			nElems;
1614 				int			i;
1615 
1616 				Assert(conrec->contype == CONSTRAINT_EXCLUSION);
1617 				/* Extract operator OIDs from the pg_constraint tuple */
1618 				datum = SysCacheGetAttr(CONSTROID, ht_constr,
1619 										Anum_pg_constraint_conexclop,
1620 										&isnull);
1621 				if (isnull)
1622 					elog(ERROR, "null conexclop for constraint %u",
1623 						 constraintId);
1624 
1625 				deconstruct_array(DatumGetArrayTypeP(datum),
1626 								  OIDOID, sizeof(Oid), true, 'i',
1627 								  &elems, NULL, &nElems);
1628 
1629 				for (i = 0; i < nElems; i++)
1630 				{
1631 					Oid			operid = DatumGetObjectId(elems[i]);
1632 					HeapTuple	opertup;
1633 					Form_pg_operator operform;
1634 					char	   *oprname;
1635 					char	   *nspname;
1636 					List	   *namelist;
1637 
1638 					opertup = SearchSysCache1(OPEROID,
1639 											  ObjectIdGetDatum(operid));
1640 					if (!HeapTupleIsValid(opertup))
1641 						elog(ERROR, "cache lookup failed for operator %u",
1642 							 operid);
1643 					operform = (Form_pg_operator) GETSTRUCT(opertup);
1644 					oprname = pstrdup(NameStr(operform->oprname));
1645 					/* For simplicity we always schema-qualify the op name */
1646 					nspname = get_namespace_name(operform->oprnamespace);
1647 					namelist = list_make2(makeString(nspname),
1648 										  makeString(oprname));
1649 					index->excludeOpNames = lappend(index->excludeOpNames,
1650 													namelist);
1651 					ReleaseSysCache(opertup);
1652 				}
1653 			}
1654 
1655 			ReleaseSysCache(ht_constr);
1656 		}
1657 		else
1658 			index->isconstraint = false;
1659 	}
1660 	else
1661 		index->isconstraint = false;
1662 
1663 	/* Get the index expressions, if any */
1664 	datum = SysCacheGetAttr(INDEXRELID, ht_idx,
1665 							Anum_pg_index_indexprs, &isnull);
1666 	if (!isnull)
1667 	{
1668 		char	   *exprsString;
1669 
1670 		exprsString = TextDatumGetCString(datum);
1671 		indexprs = (List *) stringToNode(exprsString);
1672 	}
1673 	else
1674 		indexprs = NIL;
1675 
1676 	/* Build the list of IndexElem */
1677 	index->indexParams = NIL;
1678 	index->indexIncludingParams = NIL;
1679 
1680 	indexpr_item = list_head(indexprs);
1681 	for (keyno = 0; keyno < idxrec->indnkeyatts; keyno++)
1682 	{
1683 		IndexElem  *iparam;
1684 		AttrNumber	attnum = idxrec->indkey.values[keyno];
1685 		Form_pg_attribute attr = TupleDescAttr(RelationGetDescr(source_idx),
1686 											   keyno);
1687 		int16		opt = source_idx->rd_indoption[keyno];
1688 
1689 		iparam = makeNode(IndexElem);
1690 
1691 		if (AttributeNumberIsValid(attnum))
1692 		{
1693 			/* Simple index column */
1694 			char	   *attname;
1695 
1696 			attname = get_attname(indrelid, attnum, false);
1697 			keycoltype = get_atttype(indrelid, attnum);
1698 
1699 			iparam->name = attname;
1700 			iparam->expr = NULL;
1701 		}
1702 		else
1703 		{
1704 			/* Expressional index */
1705 			Node	   *indexkey;
1706 			bool		found_whole_row;
1707 
1708 			if (indexpr_item == NULL)
1709 				elog(ERROR, "too few entries in indexprs list");
1710 			indexkey = (Node *) lfirst(indexpr_item);
1711 			indexpr_item = lnext(indexpr_item);
1712 
1713 			/* Adjust Vars to match new table's column numbering */
1714 			indexkey = map_variable_attnos(indexkey,
1715 										   1, 0,
1716 										   attmap, attmap_length,
1717 										   InvalidOid, &found_whole_row);
1718 
1719 			/* As in expandTableLikeClause, reject whole-row variables */
1720 			if (found_whole_row)
1721 				ereport(ERROR,
1722 						(errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
1723 						 errmsg("cannot convert whole-row table reference"),
1724 						 errdetail("Index \"%s\" contains a whole-row table reference.",
1725 								   RelationGetRelationName(source_idx))));
1726 
1727 			iparam->name = NULL;
1728 			iparam->expr = indexkey;
1729 
1730 			keycoltype = exprType(indexkey);
1731 		}
1732 
1733 		/* Copy the original index column name */
1734 		iparam->indexcolname = pstrdup(NameStr(attr->attname));
1735 
1736 		/* Add the collation name, if non-default */
1737 		iparam->collation = get_collation(indcollation->values[keyno], keycoltype);
1738 
1739 		/* Add the operator class name, if non-default */
1740 		iparam->opclass = get_opclass(indclass->values[keyno], keycoltype);
1741 
1742 		iparam->ordering = SORTBY_DEFAULT;
1743 		iparam->nulls_ordering = SORTBY_NULLS_DEFAULT;
1744 
1745 		/* Adjust options if necessary */
1746 		if (source_idx->rd_indam->amcanorder)
1747 		{
1748 			/*
1749 			 * If it supports sort ordering, copy DESC and NULLS opts. Don't
1750 			 * set non-default settings unnecessarily, though, so as to
1751 			 * improve the chance of recognizing equivalence to constraint
1752 			 * indexes.
1753 			 */
1754 			if (opt & INDOPTION_DESC)
1755 			{
1756 				iparam->ordering = SORTBY_DESC;
1757 				if ((opt & INDOPTION_NULLS_FIRST) == 0)
1758 					iparam->nulls_ordering = SORTBY_NULLS_LAST;
1759 			}
1760 			else
1761 			{
1762 				if (opt & INDOPTION_NULLS_FIRST)
1763 					iparam->nulls_ordering = SORTBY_NULLS_FIRST;
1764 			}
1765 		}
1766 
1767 		index->indexParams = lappend(index->indexParams, iparam);
1768 	}
1769 
1770 	/* Handle included columns separately */
1771 	for (keyno = idxrec->indnkeyatts; keyno < idxrec->indnatts; keyno++)
1772 	{
1773 		IndexElem  *iparam;
1774 		AttrNumber	attnum = idxrec->indkey.values[keyno];
1775 		Form_pg_attribute attr = TupleDescAttr(RelationGetDescr(source_idx),
1776 											   keyno);
1777 
1778 		iparam = makeNode(IndexElem);
1779 
1780 		if (AttributeNumberIsValid(attnum))
1781 		{
1782 			/* Simple index column */
1783 			char	   *attname;
1784 
1785 			attname = get_attname(indrelid, attnum, false);
1786 			keycoltype = get_atttype(indrelid, attnum);
1787 
1788 			iparam->name = attname;
1789 			iparam->expr = NULL;
1790 		}
1791 		else
1792 			ereport(ERROR,
1793 					(errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
1794 					 errmsg("expressions are not supported in included columns")));
1795 
1796 		/* Copy the original index column name */
1797 		iparam->indexcolname = pstrdup(NameStr(attr->attname));
1798 
1799 		index->indexIncludingParams = lappend(index->indexIncludingParams, iparam);
1800 	}
1801 	/* Copy reloptions if any */
1802 	datum = SysCacheGetAttr(RELOID, ht_idxrel,
1803 							Anum_pg_class_reloptions, &isnull);
1804 	if (!isnull)
1805 		index->options = untransformRelOptions(datum);
1806 
1807 	/* If it's a partial index, decompile and append the predicate */
1808 	datum = SysCacheGetAttr(INDEXRELID, ht_idx,
1809 							Anum_pg_index_indpred, &isnull);
1810 	if (!isnull)
1811 	{
1812 		char	   *pred_str;
1813 		Node	   *pred_tree;
1814 		bool		found_whole_row;
1815 
1816 		/* Convert text string to node tree */
1817 		pred_str = TextDatumGetCString(datum);
1818 		pred_tree = (Node *) stringToNode(pred_str);
1819 
1820 		/* Adjust Vars to match new table's column numbering */
1821 		pred_tree = map_variable_attnos(pred_tree,
1822 										1, 0,
1823 										attmap, attmap_length,
1824 										InvalidOid, &found_whole_row);
1825 
1826 		/* As in expandTableLikeClause, reject whole-row variables */
1827 		if (found_whole_row)
1828 			ereport(ERROR,
1829 					(errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
1830 					 errmsg("cannot convert whole-row table reference"),
1831 					 errdetail("Index \"%s\" contains a whole-row table reference.",
1832 							   RelationGetRelationName(source_idx))));
1833 
1834 		index->whereClause = pred_tree;
1835 	}
1836 
1837 	/* Clean up */
1838 	ReleaseSysCache(ht_idxrel);
1839 	ReleaseSysCache(ht_am);
1840 
1841 	return index;
1842 }
1843 
1844 /*
1845  * Generate a CreateStatsStmt node using information from an already existing
1846  * extended statistic "source_statsid", for the rel identified by heapRel and
1847  * heapRelid.
1848  */
1849 static CreateStatsStmt *
generateClonedExtStatsStmt(RangeVar * heapRel,Oid heapRelid,Oid source_statsid)1850 generateClonedExtStatsStmt(RangeVar *heapRel, Oid heapRelid,
1851 						   Oid source_statsid)
1852 {
1853 	HeapTuple	ht_stats;
1854 	Form_pg_statistic_ext statsrec;
1855 	CreateStatsStmt *stats;
1856 	List	   *stat_types = NIL;
1857 	List	   *def_names = NIL;
1858 	bool		isnull;
1859 	Datum		datum;
1860 	ArrayType  *arr;
1861 	char	   *enabled;
1862 	int			i;
1863 
1864 	Assert(OidIsValid(heapRelid));
1865 	Assert(heapRel != NULL);
1866 
1867 	/*
1868 	 * Fetch pg_statistic_ext tuple of source statistics object.
1869 	 */
1870 	ht_stats = SearchSysCache1(STATEXTOID, ObjectIdGetDatum(source_statsid));
1871 	if (!HeapTupleIsValid(ht_stats))
1872 		elog(ERROR, "cache lookup failed for statistics object %u", source_statsid);
1873 	statsrec = (Form_pg_statistic_ext) GETSTRUCT(ht_stats);
1874 
1875 	/* Determine which statistics types exist */
1876 	datum = SysCacheGetAttr(STATEXTOID, ht_stats,
1877 							Anum_pg_statistic_ext_stxkind, &isnull);
1878 	Assert(!isnull);
1879 	arr = DatumGetArrayTypeP(datum);
1880 	if (ARR_NDIM(arr) != 1 ||
1881 		ARR_HASNULL(arr) ||
1882 		ARR_ELEMTYPE(arr) != CHAROID)
1883 		elog(ERROR, "stxkind is not a 1-D char array");
1884 	enabled = (char *) ARR_DATA_PTR(arr);
1885 	for (i = 0; i < ARR_DIMS(arr)[0]; i++)
1886 	{
1887 		if (enabled[i] == STATS_EXT_NDISTINCT)
1888 			stat_types = lappend(stat_types, makeString("ndistinct"));
1889 		else if (enabled[i] == STATS_EXT_DEPENDENCIES)
1890 			stat_types = lappend(stat_types, makeString("dependencies"));
1891 		else if (enabled[i] == STATS_EXT_MCV)
1892 			stat_types = lappend(stat_types, makeString("mcv"));
1893 		else
1894 			elog(ERROR, "unrecognized statistics kind %c", enabled[i]);
1895 	}
1896 
1897 	/* Determine which columns the statistics are on */
1898 	for (i = 0; i < statsrec->stxkeys.dim1; i++)
1899 	{
1900 		ColumnRef  *cref = makeNode(ColumnRef);
1901 		AttrNumber	attnum = statsrec->stxkeys.values[i];
1902 
1903 		cref->fields = list_make1(makeString(get_attname(heapRelid,
1904 														 attnum, false)));
1905 		cref->location = -1;
1906 
1907 		def_names = lappend(def_names, cref);
1908 	}
1909 
1910 	/* finally, build the output node */
1911 	stats = makeNode(CreateStatsStmt);
1912 	stats->defnames = NULL;
1913 	stats->stat_types = stat_types;
1914 	stats->exprs = def_names;
1915 	stats->relations = list_make1(heapRel);
1916 	stats->stxcomment = NULL;
1917 	stats->if_not_exists = false;
1918 
1919 	/* Clean up */
1920 	ReleaseSysCache(ht_stats);
1921 
1922 	return stats;
1923 }
1924 
1925 /*
1926  * get_collation		- fetch qualified name of a collation
1927  *
1928  * If collation is InvalidOid or is the default for the given actual_datatype,
1929  * then the return value is NIL.
1930  */
1931 static List *
get_collation(Oid collation,Oid actual_datatype)1932 get_collation(Oid collation, Oid actual_datatype)
1933 {
1934 	List	   *result;
1935 	HeapTuple	ht_coll;
1936 	Form_pg_collation coll_rec;
1937 	char	   *nsp_name;
1938 	char	   *coll_name;
1939 
1940 	if (!OidIsValid(collation))
1941 		return NIL;				/* easy case */
1942 	if (collation == get_typcollation(actual_datatype))
1943 		return NIL;				/* just let it default */
1944 
1945 	ht_coll = SearchSysCache1(COLLOID, ObjectIdGetDatum(collation));
1946 	if (!HeapTupleIsValid(ht_coll))
1947 		elog(ERROR, "cache lookup failed for collation %u", collation);
1948 	coll_rec = (Form_pg_collation) GETSTRUCT(ht_coll);
1949 
1950 	/* For simplicity, we always schema-qualify the name */
1951 	nsp_name = get_namespace_name(coll_rec->collnamespace);
1952 	coll_name = pstrdup(NameStr(coll_rec->collname));
1953 	result = list_make2(makeString(nsp_name), makeString(coll_name));
1954 
1955 	ReleaseSysCache(ht_coll);
1956 	return result;
1957 }
1958 
1959 /*
1960  * get_opclass			- fetch qualified name of an index operator class
1961  *
1962  * If the opclass is the default for the given actual_datatype, then
1963  * the return value is NIL.
1964  */
1965 static List *
get_opclass(Oid opclass,Oid actual_datatype)1966 get_opclass(Oid opclass, Oid actual_datatype)
1967 {
1968 	List	   *result = NIL;
1969 	HeapTuple	ht_opc;
1970 	Form_pg_opclass opc_rec;
1971 
1972 	ht_opc = SearchSysCache1(CLAOID, ObjectIdGetDatum(opclass));
1973 	if (!HeapTupleIsValid(ht_opc))
1974 		elog(ERROR, "cache lookup failed for opclass %u", opclass);
1975 	opc_rec = (Form_pg_opclass) GETSTRUCT(ht_opc);
1976 
1977 	if (GetDefaultOpClass(actual_datatype, opc_rec->opcmethod) != opclass)
1978 	{
1979 		/* For simplicity, we always schema-qualify the name */
1980 		char	   *nsp_name = get_namespace_name(opc_rec->opcnamespace);
1981 		char	   *opc_name = pstrdup(NameStr(opc_rec->opcname));
1982 
1983 		result = list_make2(makeString(nsp_name), makeString(opc_name));
1984 	}
1985 
1986 	ReleaseSysCache(ht_opc);
1987 	return result;
1988 }
1989 
1990 
1991 /*
1992  * transformIndexConstraints
1993  *		Handle UNIQUE, PRIMARY KEY, EXCLUDE constraints, which create indexes.
1994  *		We also merge in any index definitions arising from
1995  *		LIKE ... INCLUDING INDEXES.
1996  */
1997 static void
transformIndexConstraints(CreateStmtContext * cxt)1998 transformIndexConstraints(CreateStmtContext *cxt)
1999 {
2000 	IndexStmt  *index;
2001 	List	   *indexlist = NIL;
2002 	List	   *finalindexlist = NIL;
2003 	ListCell   *lc;
2004 
2005 	/*
2006 	 * Run through the constraints that need to generate an index. For PRIMARY
2007 	 * KEY, mark each column as NOT NULL and create an index. For UNIQUE or
2008 	 * EXCLUDE, create an index as for PRIMARY KEY, but do not insist on NOT
2009 	 * NULL.
2010 	 */
2011 	foreach(lc, cxt->ixconstraints)
2012 	{
2013 		Constraint *constraint = lfirst_node(Constraint, lc);
2014 
2015 		Assert(constraint->contype == CONSTR_PRIMARY ||
2016 			   constraint->contype == CONSTR_UNIQUE ||
2017 			   constraint->contype == CONSTR_EXCLUSION);
2018 
2019 		index = transformIndexConstraint(constraint, cxt);
2020 
2021 		indexlist = lappend(indexlist, index);
2022 	}
2023 
2024 	/*
2025 	 * Scan the index list and remove any redundant index specifications. This
2026 	 * can happen if, for instance, the user writes UNIQUE PRIMARY KEY. A
2027 	 * strict reading of SQL would suggest raising an error instead, but that
2028 	 * strikes me as too anal-retentive. - tgl 2001-02-14
2029 	 *
2030 	 * XXX in ALTER TABLE case, it'd be nice to look for duplicate
2031 	 * pre-existing indexes, too.
2032 	 */
2033 	if (cxt->pkey != NULL)
2034 	{
2035 		/* Make sure we keep the PKEY index in preference to others... */
2036 		finalindexlist = list_make1(cxt->pkey);
2037 	}
2038 
2039 	foreach(lc, indexlist)
2040 	{
2041 		bool		keep = true;
2042 		ListCell   *k;
2043 
2044 		index = lfirst(lc);
2045 
2046 		/* if it's pkey, it's already in finalindexlist */
2047 		if (index == cxt->pkey)
2048 			continue;
2049 
2050 		foreach(k, finalindexlist)
2051 		{
2052 			IndexStmt  *priorindex = lfirst(k);
2053 
2054 			if (equal(index->indexParams, priorindex->indexParams) &&
2055 				equal(index->indexIncludingParams, priorindex->indexIncludingParams) &&
2056 				equal(index->whereClause, priorindex->whereClause) &&
2057 				equal(index->excludeOpNames, priorindex->excludeOpNames) &&
2058 				strcmp(index->accessMethod, priorindex->accessMethod) == 0 &&
2059 				index->deferrable == priorindex->deferrable &&
2060 				index->initdeferred == priorindex->initdeferred)
2061 			{
2062 				priorindex->unique |= index->unique;
2063 
2064 				/*
2065 				 * If the prior index is as yet unnamed, and this one is
2066 				 * named, then transfer the name to the prior index. This
2067 				 * ensures that if we have named and unnamed constraints,
2068 				 * we'll use (at least one of) the names for the index.
2069 				 */
2070 				if (priorindex->idxname == NULL)
2071 					priorindex->idxname = index->idxname;
2072 				keep = false;
2073 				break;
2074 			}
2075 		}
2076 
2077 		if (keep)
2078 			finalindexlist = lappend(finalindexlist, index);
2079 	}
2080 
2081 	/*
2082 	 * Now append all the IndexStmts to cxt->alist.  If we generated an ALTER
2083 	 * TABLE SET NOT NULL statement to support a primary key, it's already in
2084 	 * cxt->alist.
2085 	 */
2086 	cxt->alist = list_concat(cxt->alist, finalindexlist);
2087 }
2088 
2089 /*
2090  * transformIndexConstraint
2091  *		Transform one UNIQUE, PRIMARY KEY, or EXCLUDE constraint for
2092  *		transformIndexConstraints.
2093  *
2094  * We return an IndexStmt.  For a PRIMARY KEY constraint, we additionally
2095  * produce NOT NULL constraints, either by marking ColumnDefs in cxt->columns
2096  * as is_not_null or by adding an ALTER TABLE SET NOT NULL command to
2097  * cxt->alist.
2098  */
2099 static IndexStmt *
transformIndexConstraint(Constraint * constraint,CreateStmtContext * cxt)2100 transformIndexConstraint(Constraint *constraint, CreateStmtContext *cxt)
2101 {
2102 	IndexStmt  *index;
2103 	List	   *notnullcmds = NIL;
2104 	ListCell   *lc;
2105 
2106 	index = makeNode(IndexStmt);
2107 
2108 	index->unique = (constraint->contype != CONSTR_EXCLUSION);
2109 	index->primary = (constraint->contype == CONSTR_PRIMARY);
2110 	if (index->primary)
2111 	{
2112 		if (cxt->pkey != NULL)
2113 			ereport(ERROR,
2114 					(errcode(ERRCODE_INVALID_TABLE_DEFINITION),
2115 					 errmsg("multiple primary keys for table \"%s\" are not allowed",
2116 							cxt->relation->relname),
2117 					 parser_errposition(cxt->pstate, constraint->location)));
2118 		cxt->pkey = index;
2119 
2120 		/*
2121 		 * In ALTER TABLE case, a primary index might already exist, but
2122 		 * DefineIndex will check for it.
2123 		 */
2124 	}
2125 	index->isconstraint = true;
2126 	index->deferrable = constraint->deferrable;
2127 	index->initdeferred = constraint->initdeferred;
2128 
2129 	if (constraint->conname != NULL)
2130 		index->idxname = pstrdup(constraint->conname);
2131 	else
2132 		index->idxname = NULL;	/* DefineIndex will choose name */
2133 
2134 	index->relation = cxt->relation;
2135 	index->accessMethod = constraint->access_method ? constraint->access_method : DEFAULT_INDEX_TYPE;
2136 	index->options = constraint->options;
2137 	index->tableSpace = constraint->indexspace;
2138 	index->whereClause = constraint->where_clause;
2139 	index->indexParams = NIL;
2140 	index->indexIncludingParams = NIL;
2141 	index->excludeOpNames = NIL;
2142 	index->idxcomment = NULL;
2143 	index->indexOid = InvalidOid;
2144 	index->oldNode = InvalidOid;
2145 	index->transformed = false;
2146 	index->concurrent = false;
2147 	index->if_not_exists = false;
2148 	index->reset_default_tblspc = constraint->reset_default_tblspc;
2149 
2150 	/*
2151 	 * If it's ALTER TABLE ADD CONSTRAINT USING INDEX, look up the index and
2152 	 * verify it's usable, then extract the implied column name list.  (We
2153 	 * will not actually need the column name list at runtime, but we need it
2154 	 * now to check for duplicate column entries below.)
2155 	 */
2156 	if (constraint->indexname != NULL)
2157 	{
2158 		char	   *index_name = constraint->indexname;
2159 		Relation	heap_rel = cxt->rel;
2160 		Oid			index_oid;
2161 		Relation	index_rel;
2162 		Form_pg_index index_form;
2163 		oidvector  *indclass;
2164 		Datum		indclassDatum;
2165 		bool		isnull;
2166 		int			i;
2167 
2168 		/* Grammar should not allow this with explicit column list */
2169 		Assert(constraint->keys == NIL);
2170 
2171 		/* Grammar should only allow PRIMARY and UNIQUE constraints */
2172 		Assert(constraint->contype == CONSTR_PRIMARY ||
2173 			   constraint->contype == CONSTR_UNIQUE);
2174 
2175 		/* Must be ALTER, not CREATE, but grammar doesn't enforce that */
2176 		if (!cxt->isalter)
2177 			ereport(ERROR,
2178 					(errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
2179 					 errmsg("cannot use an existing index in CREATE TABLE"),
2180 					 parser_errposition(cxt->pstate, constraint->location)));
2181 
2182 		/* Look for the index in the same schema as the table */
2183 		index_oid = get_relname_relid(index_name, RelationGetNamespace(heap_rel));
2184 
2185 		if (!OidIsValid(index_oid))
2186 			ereport(ERROR,
2187 					(errcode(ERRCODE_UNDEFINED_OBJECT),
2188 					 errmsg("index \"%s\" does not exist", index_name),
2189 					 parser_errposition(cxt->pstate, constraint->location)));
2190 
2191 		/* Open the index (this will throw an error if it is not an index) */
2192 		index_rel = index_open(index_oid, AccessShareLock);
2193 		index_form = index_rel->rd_index;
2194 
2195 		/* Check that it does not have an associated constraint already */
2196 		if (OidIsValid(get_index_constraint(index_oid)))
2197 			ereport(ERROR,
2198 					(errcode(ERRCODE_OBJECT_NOT_IN_PREREQUISITE_STATE),
2199 					 errmsg("index \"%s\" is already associated with a constraint",
2200 							index_name),
2201 					 parser_errposition(cxt->pstate, constraint->location)));
2202 
2203 		/* Perform validity checks on the index */
2204 		if (index_form->indrelid != RelationGetRelid(heap_rel))
2205 			ereport(ERROR,
2206 					(errcode(ERRCODE_OBJECT_NOT_IN_PREREQUISITE_STATE),
2207 					 errmsg("index \"%s\" does not belong to table \"%s\"",
2208 							index_name, RelationGetRelationName(heap_rel)),
2209 					 parser_errposition(cxt->pstate, constraint->location)));
2210 
2211 		if (!index_form->indisvalid)
2212 			ereport(ERROR,
2213 					(errcode(ERRCODE_OBJECT_NOT_IN_PREREQUISITE_STATE),
2214 					 errmsg("index \"%s\" is not valid", index_name),
2215 					 parser_errposition(cxt->pstate, constraint->location)));
2216 
2217 		if (!index_form->indisunique)
2218 			ereport(ERROR,
2219 					(errcode(ERRCODE_WRONG_OBJECT_TYPE),
2220 					 errmsg("\"%s\" is not a unique index", index_name),
2221 					 errdetail("Cannot create a primary key or unique constraint using such an index."),
2222 					 parser_errposition(cxt->pstate, constraint->location)));
2223 
2224 		if (RelationGetIndexExpressions(index_rel) != NIL)
2225 			ereport(ERROR,
2226 					(errcode(ERRCODE_WRONG_OBJECT_TYPE),
2227 					 errmsg("index \"%s\" contains expressions", index_name),
2228 					 errdetail("Cannot create a primary key or unique constraint using such an index."),
2229 					 parser_errposition(cxt->pstate, constraint->location)));
2230 
2231 		if (RelationGetIndexPredicate(index_rel) != NIL)
2232 			ereport(ERROR,
2233 					(errcode(ERRCODE_WRONG_OBJECT_TYPE),
2234 					 errmsg("\"%s\" is a partial index", index_name),
2235 					 errdetail("Cannot create a primary key or unique constraint using such an index."),
2236 					 parser_errposition(cxt->pstate, constraint->location)));
2237 
2238 		/*
2239 		 * It's probably unsafe to change a deferred index to non-deferred. (A
2240 		 * non-constraint index couldn't be deferred anyway, so this case
2241 		 * should never occur; no need to sweat, but let's check it.)
2242 		 */
2243 		if (!index_form->indimmediate && !constraint->deferrable)
2244 			ereport(ERROR,
2245 					(errcode(ERRCODE_WRONG_OBJECT_TYPE),
2246 					 errmsg("\"%s\" is a deferrable index", index_name),
2247 					 errdetail("Cannot create a non-deferrable constraint using a deferrable index."),
2248 					 parser_errposition(cxt->pstate, constraint->location)));
2249 
2250 		/*
2251 		 * Insist on it being a btree.  That's the only kind that supports
2252 		 * uniqueness at the moment anyway; but we must have an index that
2253 		 * exactly matches what you'd get from plain ADD CONSTRAINT syntax,
2254 		 * else dump and reload will produce a different index (breaking
2255 		 * pg_upgrade in particular).
2256 		 */
2257 		if (index_rel->rd_rel->relam != get_index_am_oid(DEFAULT_INDEX_TYPE, false))
2258 			ereport(ERROR,
2259 					(errcode(ERRCODE_WRONG_OBJECT_TYPE),
2260 					 errmsg("index \"%s\" is not a btree", index_name),
2261 					 parser_errposition(cxt->pstate, constraint->location)));
2262 
2263 		/* Must get indclass the hard way */
2264 		indclassDatum = SysCacheGetAttr(INDEXRELID, index_rel->rd_indextuple,
2265 										Anum_pg_index_indclass, &isnull);
2266 		Assert(!isnull);
2267 		indclass = (oidvector *) DatumGetPointer(indclassDatum);
2268 
2269 		for (i = 0; i < index_form->indnatts; i++)
2270 		{
2271 			int16		attnum = index_form->indkey.values[i];
2272 			const FormData_pg_attribute *attform;
2273 			char	   *attname;
2274 			Oid			defopclass;
2275 
2276 			/*
2277 			 * We shouldn't see attnum == 0 here, since we already rejected
2278 			 * expression indexes.  If we do, SystemAttributeDefinition will
2279 			 * throw an error.
2280 			 */
2281 			if (attnum > 0)
2282 			{
2283 				Assert(attnum <= heap_rel->rd_att->natts);
2284 				attform = TupleDescAttr(heap_rel->rd_att, attnum - 1);
2285 			}
2286 			else
2287 				attform = SystemAttributeDefinition(attnum);
2288 			attname = pstrdup(NameStr(attform->attname));
2289 
2290 			if (i < index_form->indnkeyatts)
2291 			{
2292 				/*
2293 				 * Insist on default opclass and sort options.  While the
2294 				 * index would still work as a constraint with non-default
2295 				 * settings, it might not provide exactly the same uniqueness
2296 				 * semantics as you'd get from a normally-created constraint;
2297 				 * and there's also the dump/reload problem mentioned above.
2298 				 */
2299 				defopclass = GetDefaultOpClass(attform->atttypid,
2300 											   index_rel->rd_rel->relam);
2301 				if (indclass->values[i] != defopclass ||
2302 					index_rel->rd_indoption[i] != 0)
2303 					ereport(ERROR,
2304 							(errcode(ERRCODE_WRONG_OBJECT_TYPE),
2305 							 errmsg("index \"%s\" column number %d does not have default sorting behavior", index_name, i + 1),
2306 							 errdetail("Cannot create a primary key or unique constraint using such an index."),
2307 							 parser_errposition(cxt->pstate, constraint->location)));
2308 
2309 				constraint->keys = lappend(constraint->keys, makeString(attname));
2310 			}
2311 			else
2312 				constraint->including = lappend(constraint->including, makeString(attname));
2313 		}
2314 
2315 		/* Close the index relation but keep the lock */
2316 		relation_close(index_rel, NoLock);
2317 
2318 		index->indexOid = index_oid;
2319 	}
2320 
2321 	/*
2322 	 * If it's an EXCLUDE constraint, the grammar returns a list of pairs of
2323 	 * IndexElems and operator names.  We have to break that apart into
2324 	 * separate lists.
2325 	 */
2326 	if (constraint->contype == CONSTR_EXCLUSION)
2327 	{
2328 		foreach(lc, constraint->exclusions)
2329 		{
2330 			List	   *pair = (List *) lfirst(lc);
2331 			IndexElem  *elem;
2332 			List	   *opname;
2333 
2334 			Assert(list_length(pair) == 2);
2335 			elem = linitial_node(IndexElem, pair);
2336 			opname = lsecond_node(List, pair);
2337 
2338 			index->indexParams = lappend(index->indexParams, elem);
2339 			index->excludeOpNames = lappend(index->excludeOpNames, opname);
2340 		}
2341 	}
2342 
2343 	/*
2344 	 * For UNIQUE and PRIMARY KEY, we just have a list of column names.
2345 	 *
2346 	 * Make sure referenced keys exist.  If we are making a PRIMARY KEY index,
2347 	 * also make sure they are NOT NULL.
2348 	 */
2349 	else
2350 	{
2351 		foreach(lc, constraint->keys)
2352 		{
2353 			char	   *key = strVal(lfirst(lc));
2354 			bool		found = false;
2355 			bool		forced_not_null = false;
2356 			ColumnDef  *column = NULL;
2357 			ListCell   *columns;
2358 			IndexElem  *iparam;
2359 
2360 			/* Make sure referenced column exists. */
2361 			foreach(columns, cxt->columns)
2362 			{
2363 				column = castNode(ColumnDef, lfirst(columns));
2364 				if (strcmp(column->colname, key) == 0)
2365 				{
2366 					found = true;
2367 					break;
2368 				}
2369 			}
2370 			if (found)
2371 			{
2372 				/*
2373 				 * column is defined in the new table.  For PRIMARY KEY, we
2374 				 * can apply the NOT NULL constraint cheaply here ... unless
2375 				 * the column is marked is_from_type, in which case marking it
2376 				 * here would be ineffective (see MergeAttributes).
2377 				 */
2378 				if (constraint->contype == CONSTR_PRIMARY &&
2379 					!column->is_from_type)
2380 				{
2381 					column->is_not_null = true;
2382 					forced_not_null = true;
2383 				}
2384 			}
2385 			else if (SystemAttributeByName(key) != NULL)
2386 			{
2387 				/*
2388 				 * column will be a system column in the new table, so accept
2389 				 * it. System columns can't ever be null, so no need to worry
2390 				 * about PRIMARY/NOT NULL constraint.
2391 				 */
2392 				found = true;
2393 			}
2394 			else if (cxt->inhRelations)
2395 			{
2396 				/* try inherited tables */
2397 				ListCell   *inher;
2398 
2399 				foreach(inher, cxt->inhRelations)
2400 				{
2401 					RangeVar   *inh = castNode(RangeVar, lfirst(inher));
2402 					Relation	rel;
2403 					int			count;
2404 
2405 					rel = table_openrv(inh, AccessShareLock);
2406 					/* check user requested inheritance from valid relkind */
2407 					if (rel->rd_rel->relkind != RELKIND_RELATION &&
2408 						rel->rd_rel->relkind != RELKIND_FOREIGN_TABLE &&
2409 						rel->rd_rel->relkind != RELKIND_PARTITIONED_TABLE)
2410 						ereport(ERROR,
2411 								(errcode(ERRCODE_WRONG_OBJECT_TYPE),
2412 								 errmsg("inherited relation \"%s\" is not a table or foreign table",
2413 										inh->relname)));
2414 					for (count = 0; count < rel->rd_att->natts; count++)
2415 					{
2416 						Form_pg_attribute inhattr = TupleDescAttr(rel->rd_att,
2417 																  count);
2418 						char	   *inhname = NameStr(inhattr->attname);
2419 
2420 						if (inhattr->attisdropped)
2421 							continue;
2422 						if (strcmp(key, inhname) == 0)
2423 						{
2424 							found = true;
2425 
2426 							/*
2427 							 * It's tempting to set forced_not_null if the
2428 							 * parent column is already NOT NULL, but that
2429 							 * seems unsafe because the column's NOT NULL
2430 							 * marking might disappear between now and
2431 							 * execution.  Do the runtime check to be safe.
2432 							 */
2433 							break;
2434 						}
2435 					}
2436 					table_close(rel, NoLock);
2437 					if (found)
2438 						break;
2439 				}
2440 			}
2441 
2442 			/*
2443 			 * In the ALTER TABLE case, don't complain about index keys not
2444 			 * created in the command; they may well exist already.
2445 			 * DefineIndex will complain about them if not.
2446 			 */
2447 			if (!found && !cxt->isalter)
2448 				ereport(ERROR,
2449 						(errcode(ERRCODE_UNDEFINED_COLUMN),
2450 						 errmsg("column \"%s\" named in key does not exist", key),
2451 						 parser_errposition(cxt->pstate, constraint->location)));
2452 
2453 			/* Check for PRIMARY KEY(foo, foo) */
2454 			foreach(columns, index->indexParams)
2455 			{
2456 				iparam = (IndexElem *) lfirst(columns);
2457 				if (iparam->name && strcmp(key, iparam->name) == 0)
2458 				{
2459 					if (index->primary)
2460 						ereport(ERROR,
2461 								(errcode(ERRCODE_DUPLICATE_COLUMN),
2462 								 errmsg("column \"%s\" appears twice in primary key constraint",
2463 										key),
2464 								 parser_errposition(cxt->pstate, constraint->location)));
2465 					else
2466 						ereport(ERROR,
2467 								(errcode(ERRCODE_DUPLICATE_COLUMN),
2468 								 errmsg("column \"%s\" appears twice in unique constraint",
2469 										key),
2470 								 parser_errposition(cxt->pstate, constraint->location)));
2471 				}
2472 			}
2473 
2474 			/* OK, add it to the index definition */
2475 			iparam = makeNode(IndexElem);
2476 			iparam->name = pstrdup(key);
2477 			iparam->expr = NULL;
2478 			iparam->indexcolname = NULL;
2479 			iparam->collation = NIL;
2480 			iparam->opclass = NIL;
2481 			iparam->ordering = SORTBY_DEFAULT;
2482 			iparam->nulls_ordering = SORTBY_NULLS_DEFAULT;
2483 			index->indexParams = lappend(index->indexParams, iparam);
2484 
2485 			/*
2486 			 * For a primary-key column, also create an item for ALTER TABLE
2487 			 * SET NOT NULL if we couldn't ensure it via is_not_null above.
2488 			 */
2489 			if (constraint->contype == CONSTR_PRIMARY && !forced_not_null)
2490 			{
2491 				AlterTableCmd *notnullcmd = makeNode(AlterTableCmd);
2492 
2493 				notnullcmd->subtype = AT_SetNotNull;
2494 				notnullcmd->name = pstrdup(key);
2495 				notnullcmds = lappend(notnullcmds, notnullcmd);
2496 			}
2497 		}
2498 	}
2499 
2500 	/*
2501 	 * Add included columns to index definition.  This is much like the
2502 	 * simple-column-name-list code above, except that we don't worry about
2503 	 * NOT NULL marking; included columns in a primary key should not be
2504 	 * forced NOT NULL.  We don't complain about duplicate columns, either,
2505 	 * though maybe we should?
2506 	 */
2507 	foreach(lc, constraint->including)
2508 	{
2509 		char	   *key = strVal(lfirst(lc));
2510 		bool		found = false;
2511 		ColumnDef  *column = NULL;
2512 		ListCell   *columns;
2513 		IndexElem  *iparam;
2514 
2515 		foreach(columns, cxt->columns)
2516 		{
2517 			column = lfirst_node(ColumnDef, columns);
2518 			if (strcmp(column->colname, key) == 0)
2519 			{
2520 				found = true;
2521 				break;
2522 			}
2523 		}
2524 
2525 		if (!found)
2526 		{
2527 			if (SystemAttributeByName(key) != NULL)
2528 			{
2529 				/*
2530 				 * column will be a system column in the new table, so accept
2531 				 * it.
2532 				 */
2533 				found = true;
2534 			}
2535 			else if (cxt->inhRelations)
2536 			{
2537 				/* try inherited tables */
2538 				ListCell   *inher;
2539 
2540 				foreach(inher, cxt->inhRelations)
2541 				{
2542 					RangeVar   *inh = lfirst_node(RangeVar, inher);
2543 					Relation	rel;
2544 					int			count;
2545 
2546 					rel = table_openrv(inh, AccessShareLock);
2547 					/* check user requested inheritance from valid relkind */
2548 					if (rel->rd_rel->relkind != RELKIND_RELATION &&
2549 						rel->rd_rel->relkind != RELKIND_FOREIGN_TABLE &&
2550 						rel->rd_rel->relkind != RELKIND_PARTITIONED_TABLE)
2551 						ereport(ERROR,
2552 								(errcode(ERRCODE_WRONG_OBJECT_TYPE),
2553 								 errmsg("inherited relation \"%s\" is not a table or foreign table",
2554 										inh->relname)));
2555 					for (count = 0; count < rel->rd_att->natts; count++)
2556 					{
2557 						Form_pg_attribute inhattr = TupleDescAttr(rel->rd_att,
2558 																  count);
2559 						char	   *inhname = NameStr(inhattr->attname);
2560 
2561 						if (inhattr->attisdropped)
2562 							continue;
2563 						if (strcmp(key, inhname) == 0)
2564 						{
2565 							found = true;
2566 							break;
2567 						}
2568 					}
2569 					table_close(rel, NoLock);
2570 					if (found)
2571 						break;
2572 				}
2573 			}
2574 		}
2575 
2576 		/*
2577 		 * In the ALTER TABLE case, don't complain about index keys not
2578 		 * created in the command; they may well exist already. DefineIndex
2579 		 * will complain about them if not.
2580 		 */
2581 		if (!found && !cxt->isalter)
2582 			ereport(ERROR,
2583 					(errcode(ERRCODE_UNDEFINED_COLUMN),
2584 					 errmsg("column \"%s\" named in key does not exist", key),
2585 					 parser_errposition(cxt->pstate, constraint->location)));
2586 
2587 		/* OK, add it to the index definition */
2588 		iparam = makeNode(IndexElem);
2589 		iparam->name = pstrdup(key);
2590 		iparam->expr = NULL;
2591 		iparam->indexcolname = NULL;
2592 		iparam->collation = NIL;
2593 		iparam->opclass = NIL;
2594 		index->indexIncludingParams = lappend(index->indexIncludingParams, iparam);
2595 	}
2596 
2597 	/*
2598 	 * If we found anything that requires run-time SET NOT NULL, build a full
2599 	 * ALTER TABLE command for that and add it to cxt->alist.
2600 	 */
2601 	if (notnullcmds)
2602 	{
2603 		AlterTableStmt *alterstmt = makeNode(AlterTableStmt);
2604 
2605 		alterstmt->relation = copyObject(cxt->relation);
2606 		alterstmt->cmds = notnullcmds;
2607 		alterstmt->relkind = OBJECT_TABLE;
2608 		alterstmt->missing_ok = false;
2609 
2610 		cxt->alist = lappend(cxt->alist, alterstmt);
2611 	}
2612 
2613 	return index;
2614 }
2615 
2616 /*
2617  * transformExtendedStatistics
2618  *     Handle extended statistic objects
2619  *
2620  * Right now, there's nothing to do here, so we just append the list to
2621  * the existing "after" list.
2622  */
2623 static void
transformExtendedStatistics(CreateStmtContext * cxt)2624 transformExtendedStatistics(CreateStmtContext *cxt)
2625 {
2626 	cxt->alist = list_concat(cxt->alist, cxt->extstats);
2627 }
2628 
2629 /*
2630  * transformCheckConstraints
2631  *		handle CHECK constraints
2632  *
2633  * Right now, there's nothing to do here when called from ALTER TABLE,
2634  * but the other constraint-transformation functions are called in both
2635  * the CREATE TABLE and ALTER TABLE paths, so do the same here, and just
2636  * don't do anything if we're not authorized to skip validation.
2637  */
2638 static void
transformCheckConstraints(CreateStmtContext * cxt,bool skipValidation)2639 transformCheckConstraints(CreateStmtContext *cxt, bool skipValidation)
2640 {
2641 	ListCell   *ckclist;
2642 
2643 	if (cxt->ckconstraints == NIL)
2644 		return;
2645 
2646 	/*
2647 	 * If creating a new table (but not a foreign table), we can safely skip
2648 	 * validation of check constraints, and nonetheless mark them valid. (This
2649 	 * will override any user-supplied NOT VALID flag.)
2650 	 */
2651 	if (skipValidation)
2652 	{
2653 		foreach(ckclist, cxt->ckconstraints)
2654 		{
2655 			Constraint *constraint = (Constraint *) lfirst(ckclist);
2656 
2657 			constraint->skip_validation = true;
2658 			constraint->initially_valid = true;
2659 		}
2660 	}
2661 }
2662 
2663 /*
2664  * transformFKConstraints
2665  *		handle FOREIGN KEY constraints
2666  */
2667 static void
transformFKConstraints(CreateStmtContext * cxt,bool skipValidation,bool isAddConstraint)2668 transformFKConstraints(CreateStmtContext *cxt,
2669 					   bool skipValidation, bool isAddConstraint)
2670 {
2671 	ListCell   *fkclist;
2672 
2673 	if (cxt->fkconstraints == NIL)
2674 		return;
2675 
2676 	/*
2677 	 * If CREATE TABLE or adding a column with NULL default, we can safely
2678 	 * skip validation of FK constraints, and nonetheless mark them valid.
2679 	 * (This will override any user-supplied NOT VALID flag.)
2680 	 */
2681 	if (skipValidation)
2682 	{
2683 		foreach(fkclist, cxt->fkconstraints)
2684 		{
2685 			Constraint *constraint = (Constraint *) lfirst(fkclist);
2686 
2687 			constraint->skip_validation = true;
2688 			constraint->initially_valid = true;
2689 		}
2690 	}
2691 
2692 	/*
2693 	 * For CREATE TABLE or ALTER TABLE ADD COLUMN, gin up an ALTER TABLE ADD
2694 	 * CONSTRAINT command to execute after the basic command is complete. (If
2695 	 * called from ADD CONSTRAINT, that routine will add the FK constraints to
2696 	 * its own subcommand list.)
2697 	 *
2698 	 * Note: the ADD CONSTRAINT command must also execute after any index
2699 	 * creation commands.  Thus, this should run after
2700 	 * transformIndexConstraints, so that the CREATE INDEX commands are
2701 	 * already in cxt->alist.  See also the handling of cxt->likeclauses.
2702 	 */
2703 	if (!isAddConstraint)
2704 	{
2705 		AlterTableStmt *alterstmt = makeNode(AlterTableStmt);
2706 
2707 		alterstmt->relation = cxt->relation;
2708 		alterstmt->cmds = NIL;
2709 		alterstmt->relkind = OBJECT_TABLE;
2710 
2711 		foreach(fkclist, cxt->fkconstraints)
2712 		{
2713 			Constraint *constraint = (Constraint *) lfirst(fkclist);
2714 			AlterTableCmd *altercmd = makeNode(AlterTableCmd);
2715 
2716 			altercmd->subtype = AT_ProcessedConstraint;
2717 			altercmd->name = NULL;
2718 			altercmd->def = (Node *) constraint;
2719 			alterstmt->cmds = lappend(alterstmt->cmds, altercmd);
2720 		}
2721 
2722 		cxt->alist = lappend(cxt->alist, alterstmt);
2723 	}
2724 }
2725 
2726 /*
2727  * transformIndexStmt - parse analysis for CREATE INDEX and ALTER TABLE
2728  *
2729  * Note: this is a no-op for an index not using either index expressions or
2730  * a predicate expression.  There are several code paths that create indexes
2731  * without bothering to call this, because they know they don't have any
2732  * such expressions to deal with.
2733  *
2734  * To avoid race conditions, it's important that this function rely only on
2735  * the passed-in relid (and not on stmt->relation) to determine the target
2736  * relation.
2737  */
2738 IndexStmt *
transformIndexStmt(Oid relid,IndexStmt * stmt,const char * queryString)2739 transformIndexStmt(Oid relid, IndexStmt *stmt, const char *queryString)
2740 {
2741 	ParseState *pstate;
2742 	RangeTblEntry *rte;
2743 	ListCell   *l;
2744 	Relation	rel;
2745 
2746 	/* Nothing to do if statement already transformed. */
2747 	if (stmt->transformed)
2748 		return stmt;
2749 
2750 	/*
2751 	 * We must not scribble on the passed-in IndexStmt, so copy it.  (This is
2752 	 * overkill, but easy.)
2753 	 */
2754 	stmt = copyObject(stmt);
2755 
2756 	/* Set up pstate */
2757 	pstate = make_parsestate(NULL);
2758 	pstate->p_sourcetext = queryString;
2759 
2760 	/*
2761 	 * Put the parent table into the rtable so that the expressions can refer
2762 	 * to its fields without qualification.  Caller is responsible for locking
2763 	 * relation, but we still need to open it.
2764 	 */
2765 	rel = relation_open(relid, NoLock);
2766 	rte = addRangeTableEntryForRelation(pstate, rel,
2767 										AccessShareLock,
2768 										NULL, false, true);
2769 
2770 	/* no to join list, yes to namespaces */
2771 	addRTEtoQuery(pstate, rte, false, true, true);
2772 
2773 	/* take care of the where clause */
2774 	if (stmt->whereClause)
2775 	{
2776 		stmt->whereClause = transformWhereClause(pstate,
2777 												 stmt->whereClause,
2778 												 EXPR_KIND_INDEX_PREDICATE,
2779 												 "WHERE");
2780 		/* we have to fix its collations too */
2781 		assign_expr_collations(pstate, stmt->whereClause);
2782 	}
2783 
2784 	/* take care of any index expressions */
2785 	foreach(l, stmt->indexParams)
2786 	{
2787 		IndexElem  *ielem = (IndexElem *) lfirst(l);
2788 
2789 		if (ielem->expr)
2790 		{
2791 			/* Extract preliminary index col name before transforming expr */
2792 			if (ielem->indexcolname == NULL)
2793 				ielem->indexcolname = FigureIndexColname(ielem->expr);
2794 
2795 			/* Now do parse transformation of the expression */
2796 			ielem->expr = transformExpr(pstate, ielem->expr,
2797 										EXPR_KIND_INDEX_EXPRESSION);
2798 
2799 			/* We have to fix its collations too */
2800 			assign_expr_collations(pstate, ielem->expr);
2801 
2802 			/*
2803 			 * transformExpr() should have already rejected subqueries,
2804 			 * aggregates, window functions, and SRFs, based on the EXPR_KIND_
2805 			 * for an index expression.
2806 			 *
2807 			 * DefineIndex() will make more checks.
2808 			 */
2809 		}
2810 	}
2811 
2812 	/*
2813 	 * Check that only the base rel is mentioned.  (This should be dead code
2814 	 * now that add_missing_from is history.)
2815 	 */
2816 	if (list_length(pstate->p_rtable) != 1)
2817 		ereport(ERROR,
2818 				(errcode(ERRCODE_INVALID_COLUMN_REFERENCE),
2819 				 errmsg("index expressions and predicates can refer only to the table being indexed")));
2820 
2821 	free_parsestate(pstate);
2822 
2823 	/* Close relation */
2824 	table_close(rel, NoLock);
2825 
2826 	/* Mark statement as successfully transformed */
2827 	stmt->transformed = true;
2828 
2829 	return stmt;
2830 }
2831 
2832 
2833 /*
2834  * transformRuleStmt -
2835  *	  transform a CREATE RULE Statement. The action is a list of parse
2836  *	  trees which is transformed into a list of query trees, and we also
2837  *	  transform the WHERE clause if any.
2838  *
2839  * actions and whereClause are output parameters that receive the
2840  * transformed results.
2841  *
2842  * Note that we must not scribble on the passed-in RuleStmt, so we do
2843  * copyObject() on the actions and WHERE clause.
2844  */
2845 void
transformRuleStmt(RuleStmt * stmt,const char * queryString,List ** actions,Node ** whereClause)2846 transformRuleStmt(RuleStmt *stmt, const char *queryString,
2847 				  List **actions, Node **whereClause)
2848 {
2849 	Relation	rel;
2850 	ParseState *pstate;
2851 	RangeTblEntry *oldrte;
2852 	RangeTblEntry *newrte;
2853 
2854 	/*
2855 	 * To avoid deadlock, make sure the first thing we do is grab
2856 	 * AccessExclusiveLock on the target relation.  This will be needed by
2857 	 * DefineQueryRewrite(), and we don't want to grab a lesser lock
2858 	 * beforehand.
2859 	 */
2860 	rel = table_openrv(stmt->relation, AccessExclusiveLock);
2861 
2862 	if (rel->rd_rel->relkind == RELKIND_MATVIEW)
2863 		ereport(ERROR,
2864 				(errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
2865 				 errmsg("rules on materialized views are not supported")));
2866 
2867 	/* Set up pstate */
2868 	pstate = make_parsestate(NULL);
2869 	pstate->p_sourcetext = queryString;
2870 
2871 	/*
2872 	 * NOTE: 'OLD' must always have a varno equal to 1 and 'NEW' equal to 2.
2873 	 * Set up their RTEs in the main pstate for use in parsing the rule
2874 	 * qualification.
2875 	 */
2876 	oldrte = addRangeTableEntryForRelation(pstate, rel,
2877 										   AccessShareLock,
2878 										   makeAlias("old", NIL),
2879 										   false, false);
2880 	newrte = addRangeTableEntryForRelation(pstate, rel,
2881 										   AccessShareLock,
2882 										   makeAlias("new", NIL),
2883 										   false, false);
2884 	/* Must override addRangeTableEntry's default access-check flags */
2885 	oldrte->requiredPerms = 0;
2886 	newrte->requiredPerms = 0;
2887 
2888 	/*
2889 	 * They must be in the namespace too for lookup purposes, but only add the
2890 	 * one(s) that are relevant for the current kind of rule.  In an UPDATE
2891 	 * rule, quals must refer to OLD.field or NEW.field to be unambiguous, but
2892 	 * there's no need to be so picky for INSERT & DELETE.  We do not add them
2893 	 * to the joinlist.
2894 	 */
2895 	switch (stmt->event)
2896 	{
2897 		case CMD_SELECT:
2898 			addRTEtoQuery(pstate, oldrte, false, true, true);
2899 			break;
2900 		case CMD_UPDATE:
2901 			addRTEtoQuery(pstate, oldrte, false, true, true);
2902 			addRTEtoQuery(pstate, newrte, false, true, true);
2903 			break;
2904 		case CMD_INSERT:
2905 			addRTEtoQuery(pstate, newrte, false, true, true);
2906 			break;
2907 		case CMD_DELETE:
2908 			addRTEtoQuery(pstate, oldrte, false, true, true);
2909 			break;
2910 		default:
2911 			elog(ERROR, "unrecognized event type: %d",
2912 				 (int) stmt->event);
2913 			break;
2914 	}
2915 
2916 	/* take care of the where clause */
2917 	*whereClause = transformWhereClause(pstate,
2918 										(Node *) copyObject(stmt->whereClause),
2919 										EXPR_KIND_WHERE,
2920 										"WHERE");
2921 	/* we have to fix its collations too */
2922 	assign_expr_collations(pstate, *whereClause);
2923 
2924 	/* this is probably dead code without add_missing_from: */
2925 	if (list_length(pstate->p_rtable) != 2) /* naughty, naughty... */
2926 		ereport(ERROR,
2927 				(errcode(ERRCODE_INVALID_OBJECT_DEFINITION),
2928 				 errmsg("rule WHERE condition cannot contain references to other relations")));
2929 
2930 	/*
2931 	 * 'instead nothing' rules with a qualification need a query rangetable so
2932 	 * the rewrite handler can add the negated rule qualification to the
2933 	 * original query. We create a query with the new command type CMD_NOTHING
2934 	 * here that is treated specially by the rewrite system.
2935 	 */
2936 	if (stmt->actions == NIL)
2937 	{
2938 		Query	   *nothing_qry = makeNode(Query);
2939 
2940 		nothing_qry->commandType = CMD_NOTHING;
2941 		nothing_qry->rtable = pstate->p_rtable;
2942 		nothing_qry->jointree = makeFromExpr(NIL, NULL);	/* no join wanted */
2943 
2944 		*actions = list_make1(nothing_qry);
2945 	}
2946 	else
2947 	{
2948 		ListCell   *l;
2949 		List	   *newactions = NIL;
2950 
2951 		/*
2952 		 * transform each statement, like parse_sub_analyze()
2953 		 */
2954 		foreach(l, stmt->actions)
2955 		{
2956 			Node	   *action = (Node *) lfirst(l);
2957 			ParseState *sub_pstate = make_parsestate(NULL);
2958 			Query	   *sub_qry,
2959 					   *top_subqry;
2960 			bool		has_old,
2961 						has_new;
2962 
2963 			/*
2964 			 * Since outer ParseState isn't parent of inner, have to pass down
2965 			 * the query text by hand.
2966 			 */
2967 			sub_pstate->p_sourcetext = queryString;
2968 
2969 			/*
2970 			 * Set up OLD/NEW in the rtable for this statement.  The entries
2971 			 * are added only to relnamespace, not varnamespace, because we
2972 			 * don't want them to be referred to by unqualified field names
2973 			 * nor "*" in the rule actions.  We decide later whether to put
2974 			 * them in the joinlist.
2975 			 */
2976 			oldrte = addRangeTableEntryForRelation(sub_pstate, rel,
2977 												   AccessShareLock,
2978 												   makeAlias("old", NIL),
2979 												   false, false);
2980 			newrte = addRangeTableEntryForRelation(sub_pstate, rel,
2981 												   AccessShareLock,
2982 												   makeAlias("new", NIL),
2983 												   false, false);
2984 			oldrte->requiredPerms = 0;
2985 			newrte->requiredPerms = 0;
2986 			addRTEtoQuery(sub_pstate, oldrte, false, true, false);
2987 			addRTEtoQuery(sub_pstate, newrte, false, true, false);
2988 
2989 			/* Transform the rule action statement */
2990 			top_subqry = transformStmt(sub_pstate,
2991 									   (Node *) copyObject(action));
2992 
2993 			/*
2994 			 * We cannot support utility-statement actions (eg NOTIFY) with
2995 			 * nonempty rule WHERE conditions, because there's no way to make
2996 			 * the utility action execute conditionally.
2997 			 */
2998 			if (top_subqry->commandType == CMD_UTILITY &&
2999 				*whereClause != NULL)
3000 				ereport(ERROR,
3001 						(errcode(ERRCODE_INVALID_OBJECT_DEFINITION),
3002 						 errmsg("rules with WHERE conditions can only have SELECT, INSERT, UPDATE, or DELETE actions")));
3003 
3004 			/*
3005 			 * If the action is INSERT...SELECT, OLD/NEW have been pushed down
3006 			 * into the SELECT, and that's what we need to look at. (Ugly
3007 			 * kluge ... try to fix this when we redesign querytrees.)
3008 			 */
3009 			sub_qry = getInsertSelectQuery(top_subqry, NULL);
3010 
3011 			/*
3012 			 * If the sub_qry is a setop, we cannot attach any qualifications
3013 			 * to it, because the planner won't notice them.  This could
3014 			 * perhaps be relaxed someday, but for now, we may as well reject
3015 			 * such a rule immediately.
3016 			 */
3017 			if (sub_qry->setOperations != NULL && *whereClause != NULL)
3018 				ereport(ERROR,
3019 						(errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
3020 						 errmsg("conditional UNION/INTERSECT/EXCEPT statements are not implemented")));
3021 
3022 			/*
3023 			 * Validate action's use of OLD/NEW, qual too
3024 			 */
3025 			has_old =
3026 				rangeTableEntry_used((Node *) sub_qry, PRS2_OLD_VARNO, 0) ||
3027 				rangeTableEntry_used(*whereClause, PRS2_OLD_VARNO, 0);
3028 			has_new =
3029 				rangeTableEntry_used((Node *) sub_qry, PRS2_NEW_VARNO, 0) ||
3030 				rangeTableEntry_used(*whereClause, PRS2_NEW_VARNO, 0);
3031 
3032 			switch (stmt->event)
3033 			{
3034 				case CMD_SELECT:
3035 					if (has_old)
3036 						ereport(ERROR,
3037 								(errcode(ERRCODE_INVALID_OBJECT_DEFINITION),
3038 								 errmsg("ON SELECT rule cannot use OLD")));
3039 					if (has_new)
3040 						ereport(ERROR,
3041 								(errcode(ERRCODE_INVALID_OBJECT_DEFINITION),
3042 								 errmsg("ON SELECT rule cannot use NEW")));
3043 					break;
3044 				case CMD_UPDATE:
3045 					/* both are OK */
3046 					break;
3047 				case CMD_INSERT:
3048 					if (has_old)
3049 						ereport(ERROR,
3050 								(errcode(ERRCODE_INVALID_OBJECT_DEFINITION),
3051 								 errmsg("ON INSERT rule cannot use OLD")));
3052 					break;
3053 				case CMD_DELETE:
3054 					if (has_new)
3055 						ereport(ERROR,
3056 								(errcode(ERRCODE_INVALID_OBJECT_DEFINITION),
3057 								 errmsg("ON DELETE rule cannot use NEW")));
3058 					break;
3059 				default:
3060 					elog(ERROR, "unrecognized event type: %d",
3061 						 (int) stmt->event);
3062 					break;
3063 			}
3064 
3065 			/*
3066 			 * OLD/NEW are not allowed in WITH queries, because they would
3067 			 * amount to outer references for the WITH, which we disallow.
3068 			 * However, they were already in the outer rangetable when we
3069 			 * analyzed the query, so we have to check.
3070 			 *
3071 			 * Note that in the INSERT...SELECT case, we need to examine the
3072 			 * CTE lists of both top_subqry and sub_qry.
3073 			 *
3074 			 * Note that we aren't digging into the body of the query looking
3075 			 * for WITHs in nested sub-SELECTs.  A WITH down there can
3076 			 * legitimately refer to OLD/NEW, because it'd be an
3077 			 * indirect-correlated outer reference.
3078 			 */
3079 			if (rangeTableEntry_used((Node *) top_subqry->cteList,
3080 									 PRS2_OLD_VARNO, 0) ||
3081 				rangeTableEntry_used((Node *) sub_qry->cteList,
3082 									 PRS2_OLD_VARNO, 0))
3083 				ereport(ERROR,
3084 						(errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
3085 						 errmsg("cannot refer to OLD within WITH query")));
3086 			if (rangeTableEntry_used((Node *) top_subqry->cteList,
3087 									 PRS2_NEW_VARNO, 0) ||
3088 				rangeTableEntry_used((Node *) sub_qry->cteList,
3089 									 PRS2_NEW_VARNO, 0))
3090 				ereport(ERROR,
3091 						(errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
3092 						 errmsg("cannot refer to NEW within WITH query")));
3093 
3094 			/*
3095 			 * For efficiency's sake, add OLD to the rule action's jointree
3096 			 * only if it was actually referenced in the statement or qual.
3097 			 *
3098 			 * For INSERT, NEW is not really a relation (only a reference to
3099 			 * the to-be-inserted tuple) and should never be added to the
3100 			 * jointree.
3101 			 *
3102 			 * For UPDATE, we treat NEW as being another kind of reference to
3103 			 * OLD, because it represents references to *transformed* tuples
3104 			 * of the existing relation.  It would be wrong to enter NEW
3105 			 * separately in the jointree, since that would cause a double
3106 			 * join of the updated relation.  It's also wrong to fail to make
3107 			 * a jointree entry if only NEW and not OLD is mentioned.
3108 			 */
3109 			if (has_old || (has_new && stmt->event == CMD_UPDATE))
3110 			{
3111 				/*
3112 				 * If sub_qry is a setop, manipulating its jointree will do no
3113 				 * good at all, because the jointree is dummy. (This should be
3114 				 * a can't-happen case because of prior tests.)
3115 				 */
3116 				if (sub_qry->setOperations != NULL)
3117 					ereport(ERROR,
3118 							(errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
3119 							 errmsg("conditional UNION/INTERSECT/EXCEPT statements are not implemented")));
3120 				/* hack so we can use addRTEtoQuery() */
3121 				sub_pstate->p_rtable = sub_qry->rtable;
3122 				sub_pstate->p_joinlist = sub_qry->jointree->fromlist;
3123 				addRTEtoQuery(sub_pstate, oldrte, true, false, false);
3124 				sub_qry->jointree->fromlist = sub_pstate->p_joinlist;
3125 			}
3126 
3127 			newactions = lappend(newactions, top_subqry);
3128 
3129 			free_parsestate(sub_pstate);
3130 		}
3131 
3132 		*actions = newactions;
3133 	}
3134 
3135 	free_parsestate(pstate);
3136 
3137 	/* Close relation, but keep the exclusive lock */
3138 	table_close(rel, NoLock);
3139 }
3140 
3141 
3142 /*
3143  * transformAlterTableStmt -
3144  *		parse analysis for ALTER TABLE
3145  *
3146  * Returns a List of utility commands to be done in sequence.  One of these
3147  * will be the transformed AlterTableStmt, but there may be additional actions
3148  * to be done before and after the actual AlterTable() call.
3149  *
3150  * To avoid race conditions, it's important that this function rely only on
3151  * the passed-in relid (and not on stmt->relation) to determine the target
3152  * relation.
3153  */
3154 List *
transformAlterTableStmt(Oid relid,AlterTableStmt * stmt,const char * queryString)3155 transformAlterTableStmt(Oid relid, AlterTableStmt *stmt,
3156 						const char *queryString)
3157 {
3158 	Relation	rel;
3159 	TupleDesc	tupdesc;
3160 	ParseState *pstate;
3161 	CreateStmtContext cxt;
3162 	List	   *result;
3163 	List	   *save_alist;
3164 	ListCell   *lcmd,
3165 			   *l;
3166 	List	   *newcmds = NIL;
3167 	bool		skipValidation = true;
3168 	AlterTableCmd *newcmd;
3169 	RangeTblEntry *rte;
3170 
3171 	/*
3172 	 * We must not scribble on the passed-in AlterTableStmt, so copy it. (This
3173 	 * is overkill, but easy.)
3174 	 */
3175 	stmt = copyObject(stmt);
3176 
3177 	/* Caller is responsible for locking the relation */
3178 	rel = relation_open(relid, NoLock);
3179 	tupdesc = RelationGetDescr(rel);
3180 
3181 	/* Set up pstate */
3182 	pstate = make_parsestate(NULL);
3183 	pstate->p_sourcetext = queryString;
3184 	rte = addRangeTableEntryForRelation(pstate,
3185 										rel,
3186 										AccessShareLock,
3187 										NULL,
3188 										false,
3189 										true);
3190 	addRTEtoQuery(pstate, rte, false, true, true);
3191 
3192 	/* Set up CreateStmtContext */
3193 	cxt.pstate = pstate;
3194 	if (stmt->relkind == OBJECT_FOREIGN_TABLE)
3195 	{
3196 		cxt.stmtType = "ALTER FOREIGN TABLE";
3197 		cxt.isforeign = true;
3198 	}
3199 	else
3200 	{
3201 		cxt.stmtType = "ALTER TABLE";
3202 		cxt.isforeign = false;
3203 	}
3204 	cxt.relation = stmt->relation;
3205 	cxt.rel = rel;
3206 	cxt.inhRelations = NIL;
3207 	cxt.isalter = true;
3208 	cxt.columns = NIL;
3209 	cxt.ckconstraints = NIL;
3210 	cxt.fkconstraints = NIL;
3211 	cxt.ixconstraints = NIL;
3212 	cxt.likeclauses = NIL;
3213 	cxt.extstats = NIL;
3214 	cxt.blist = NIL;
3215 	cxt.alist = NIL;
3216 	cxt.pkey = NULL;
3217 	cxt.ispartitioned = (rel->rd_rel->relkind == RELKIND_PARTITIONED_TABLE);
3218 	cxt.partbound = NULL;
3219 	cxt.ofType = false;
3220 
3221 	/*
3222 	 * The only subtypes that currently require parse transformation handling
3223 	 * are ADD COLUMN, ADD CONSTRAINT and SET DATA TYPE.  These largely re-use
3224 	 * code from CREATE TABLE.
3225 	 */
3226 	foreach(lcmd, stmt->cmds)
3227 	{
3228 		AlterTableCmd *cmd = (AlterTableCmd *) lfirst(lcmd);
3229 
3230 		switch (cmd->subtype)
3231 		{
3232 			case AT_AddColumn:
3233 			case AT_AddColumnToView:
3234 				{
3235 					ColumnDef  *def = castNode(ColumnDef, cmd->def);
3236 
3237 					transformColumnDefinition(&cxt, def);
3238 
3239 					/*
3240 					 * If the column has a non-null default, we can't skip
3241 					 * validation of foreign keys.
3242 					 */
3243 					if (def->raw_default != NULL)
3244 						skipValidation = false;
3245 
3246 					/*
3247 					 * All constraints are processed in other ways. Remove the
3248 					 * original list
3249 					 */
3250 					def->constraints = NIL;
3251 
3252 					newcmds = lappend(newcmds, cmd);
3253 					break;
3254 				}
3255 
3256 			case AT_AddConstraint:
3257 
3258 				/*
3259 				 * The original AddConstraint cmd node doesn't go to newcmds
3260 				 */
3261 				if (IsA(cmd->def, Constraint))
3262 				{
3263 					transformTableConstraint(&cxt, (Constraint *) cmd->def);
3264 					if (((Constraint *) cmd->def)->contype == CONSTR_FOREIGN)
3265 						skipValidation = false;
3266 				}
3267 				else
3268 					elog(ERROR, "unrecognized node type: %d",
3269 						 (int) nodeTag(cmd->def));
3270 				break;
3271 
3272 			case AT_ProcessedConstraint:
3273 
3274 				/*
3275 				 * Already-transformed ADD CONSTRAINT, so just make it look
3276 				 * like the standard case.
3277 				 */
3278 				cmd->subtype = AT_AddConstraint;
3279 				newcmds = lappend(newcmds, cmd);
3280 				break;
3281 
3282 			case AT_AlterColumnType:
3283 				{
3284 					ColumnDef  *def = (ColumnDef *) cmd->def;
3285 					AttrNumber	attnum;
3286 
3287 					/*
3288 					 * For ALTER COLUMN TYPE, transform the USING clause if
3289 					 * one was specified.
3290 					 */
3291 					if (def->raw_default)
3292 					{
3293 						def->cooked_default =
3294 							transformExpr(pstate, def->raw_default,
3295 										  EXPR_KIND_ALTER_COL_TRANSFORM);
3296 					}
3297 
3298 					/*
3299 					 * For identity column, create ALTER SEQUENCE command to
3300 					 * change the data type of the sequence.
3301 					 */
3302 					attnum = get_attnum(relid, cmd->name);
3303 
3304 					/*
3305 					 * if attribute not found, something will error about it
3306 					 * later
3307 					 */
3308 					if (attnum != InvalidAttrNumber &&
3309 						TupleDescAttr(tupdesc, attnum - 1)->attidentity)
3310 					{
3311 						Oid			seq_relid = getOwnedSequence(relid, attnum);
3312 						Oid			typeOid = typenameTypeId(pstate, def->typeName);
3313 						AlterSeqStmt *altseqstmt = makeNode(AlterSeqStmt);
3314 
3315 						altseqstmt->sequence = makeRangeVar(get_namespace_name(get_rel_namespace(seq_relid)),
3316 															get_rel_name(seq_relid),
3317 															-1);
3318 						altseqstmt->options = list_make1(makeDefElem("as", (Node *) makeTypeNameFromOid(typeOid, -1), -1));
3319 						altseqstmt->for_identity = true;
3320 						cxt.blist = lappend(cxt.blist, altseqstmt);
3321 					}
3322 
3323 					newcmds = lappend(newcmds, cmd);
3324 					break;
3325 				}
3326 
3327 			case AT_AddIdentity:
3328 				{
3329 					Constraint *def = castNode(Constraint, cmd->def);
3330 					ColumnDef  *newdef = makeNode(ColumnDef);
3331 					AttrNumber	attnum;
3332 
3333 					newdef->colname = cmd->name;
3334 					newdef->identity = def->generated_when;
3335 					cmd->def = (Node *) newdef;
3336 
3337 					attnum = get_attnum(relid, cmd->name);
3338 
3339 					/*
3340 					 * if attribute not found, something will error about it
3341 					 * later
3342 					 */
3343 					if (attnum != InvalidAttrNumber)
3344 						generateSerialExtraStmts(&cxt, newdef,
3345 												 get_atttype(relid, attnum),
3346 												 def->options, true,
3347 												 NULL, NULL);
3348 
3349 					newcmds = lappend(newcmds, cmd);
3350 					break;
3351 				}
3352 
3353 			case AT_SetIdentity:
3354 				{
3355 					/*
3356 					 * Create an ALTER SEQUENCE statement for the internal
3357 					 * sequence of the identity column.
3358 					 */
3359 					ListCell   *lc;
3360 					List	   *newseqopts = NIL;
3361 					List	   *newdef = NIL;
3362 					List	   *seqlist;
3363 					AttrNumber	attnum;
3364 
3365 					/*
3366 					 * Split options into those handled by ALTER SEQUENCE and
3367 					 * those for ALTER TABLE proper.
3368 					 */
3369 					foreach(lc, castNode(List, cmd->def))
3370 					{
3371 						DefElem    *def = lfirst_node(DefElem, lc);
3372 
3373 						if (strcmp(def->defname, "generated") == 0)
3374 							newdef = lappend(newdef, def);
3375 						else
3376 							newseqopts = lappend(newseqopts, def);
3377 					}
3378 
3379 					attnum = get_attnum(relid, cmd->name);
3380 
3381 					if (attnum)
3382 					{
3383 						seqlist = getOwnedSequences(relid, attnum);
3384 						if (seqlist)
3385 						{
3386 							AlterSeqStmt *seqstmt;
3387 							Oid			seq_relid;
3388 
3389 							seqstmt = makeNode(AlterSeqStmt);
3390 							seq_relid = linitial_oid(seqlist);
3391 							seqstmt->sequence = makeRangeVar(get_namespace_name(get_rel_namespace(seq_relid)),
3392 															 get_rel_name(seq_relid), -1);
3393 							seqstmt->options = newseqopts;
3394 							seqstmt->for_identity = true;
3395 							seqstmt->missing_ok = false;
3396 
3397 							cxt.alist = lappend(cxt.alist, seqstmt);
3398 						}
3399 					}
3400 
3401 					/*
3402 					 * If column was not found or was not an identity column,
3403 					 * we just let the ALTER TABLE command error out later.
3404 					 */
3405 
3406 					cmd->def = (Node *) newdef;
3407 					newcmds = lappend(newcmds, cmd);
3408 					break;
3409 				}
3410 
3411 			case AT_AttachPartition:
3412 			case AT_DetachPartition:
3413 				{
3414 					PartitionCmd *partcmd = (PartitionCmd *) cmd->def;
3415 
3416 					transformPartitionCmd(&cxt, partcmd);
3417 					/* assign transformed value of the partition bound */
3418 					partcmd->bound = cxt.partbound;
3419 				}
3420 
3421 				newcmds = lappend(newcmds, cmd);
3422 				break;
3423 
3424 			default:
3425 				newcmds = lappend(newcmds, cmd);
3426 				break;
3427 		}
3428 	}
3429 
3430 	/*
3431 	 * Transfer anything we already have in cxt.alist into save_alist, to keep
3432 	 * it separate from the output of transformIndexConstraints.
3433 	 */
3434 	save_alist = cxt.alist;
3435 	cxt.alist = NIL;
3436 
3437 	/* Postprocess constraints */
3438 	transformIndexConstraints(&cxt);
3439 	transformFKConstraints(&cxt, skipValidation, true);
3440 	transformCheckConstraints(&cxt, false);
3441 
3442 	/*
3443 	 * Push any index-creation commands into the ALTER, so that they can be
3444 	 * scheduled nicely by tablecmds.c.  Note that tablecmds.c assumes that
3445 	 * the IndexStmt attached to an AT_AddIndex or AT_AddIndexConstraint
3446 	 * subcommand has already been through transformIndexStmt.
3447 	 */
3448 	foreach(l, cxt.alist)
3449 	{
3450 		Node	   *istmt = (Node *) lfirst(l);
3451 
3452 		/*
3453 		 * We assume here that cxt.alist contains only IndexStmts and possibly
3454 		 * ALTER TABLE SET NOT NULL statements generated from primary key
3455 		 * constraints.  We absorb the subcommands of the latter directly.
3456 		 */
3457 		if (IsA(istmt, IndexStmt))
3458 		{
3459 			IndexStmt  *idxstmt = (IndexStmt *) istmt;
3460 
3461 			idxstmt = transformIndexStmt(relid, idxstmt, queryString);
3462 			newcmd = makeNode(AlterTableCmd);
3463 			newcmd->subtype = OidIsValid(idxstmt->indexOid) ? AT_AddIndexConstraint : AT_AddIndex;
3464 			newcmd->def = (Node *) idxstmt;
3465 			newcmds = lappend(newcmds, newcmd);
3466 		}
3467 		else if (IsA(istmt, AlterTableStmt))
3468 		{
3469 			AlterTableStmt *alterstmt = (AlterTableStmt *) istmt;
3470 
3471 			newcmds = list_concat(newcmds, alterstmt->cmds);
3472 		}
3473 		else
3474 			elog(ERROR, "unexpected stmt type %d", (int) nodeTag(istmt));
3475 	}
3476 	cxt.alist = NIL;
3477 
3478 	/* Append any CHECK or FK constraints to the commands list */
3479 	foreach(l, cxt.ckconstraints)
3480 	{
3481 		newcmd = makeNode(AlterTableCmd);
3482 		newcmd->subtype = AT_AddConstraint;
3483 		newcmd->def = (Node *) lfirst(l);
3484 		newcmds = lappend(newcmds, newcmd);
3485 	}
3486 	foreach(l, cxt.fkconstraints)
3487 	{
3488 		newcmd = makeNode(AlterTableCmd);
3489 		newcmd->subtype = AT_AddConstraint;
3490 		newcmd->def = (Node *) lfirst(l);
3491 		newcmds = lappend(newcmds, newcmd);
3492 	}
3493 
3494 	/* Append extended statistic objects */
3495 	transformExtendedStatistics(&cxt);
3496 
3497 	/* Close rel */
3498 	relation_close(rel, NoLock);
3499 
3500 	/*
3501 	 * Output results.
3502 	 */
3503 	stmt->cmds = newcmds;
3504 
3505 	result = lappend(cxt.blist, stmt);
3506 	result = list_concat(result, cxt.alist);
3507 	result = list_concat(result, save_alist);
3508 
3509 	return result;
3510 }
3511 
3512 
3513 /*
3514  * Preprocess a list of column constraint clauses
3515  * to attach constraint attributes to their primary constraint nodes
3516  * and detect inconsistent/misplaced constraint attributes.
3517  *
3518  * NOTE: currently, attributes are only supported for FOREIGN KEY, UNIQUE,
3519  * EXCLUSION, and PRIMARY KEY constraints, but someday they ought to be
3520  * supported for other constraint types.
3521  */
3522 static void
transformConstraintAttrs(CreateStmtContext * cxt,List * constraintList)3523 transformConstraintAttrs(CreateStmtContext *cxt, List *constraintList)
3524 {
3525 	Constraint *lastprimarycon = NULL;
3526 	bool		saw_deferrability = false;
3527 	bool		saw_initially = false;
3528 	ListCell   *clist;
3529 
3530 #define SUPPORTS_ATTRS(node)				\
3531 	((node) != NULL &&						\
3532 	 ((node)->contype == CONSTR_PRIMARY ||	\
3533 	  (node)->contype == CONSTR_UNIQUE ||	\
3534 	  (node)->contype == CONSTR_EXCLUSION || \
3535 	  (node)->contype == CONSTR_FOREIGN))
3536 
3537 	foreach(clist, constraintList)
3538 	{
3539 		Constraint *con = (Constraint *) lfirst(clist);
3540 
3541 		if (!IsA(con, Constraint))
3542 			elog(ERROR, "unrecognized node type: %d",
3543 				 (int) nodeTag(con));
3544 		switch (con->contype)
3545 		{
3546 			case CONSTR_ATTR_DEFERRABLE:
3547 				if (!SUPPORTS_ATTRS(lastprimarycon))
3548 					ereport(ERROR,
3549 							(errcode(ERRCODE_SYNTAX_ERROR),
3550 							 errmsg("misplaced DEFERRABLE clause"),
3551 							 parser_errposition(cxt->pstate, con->location)));
3552 				if (saw_deferrability)
3553 					ereport(ERROR,
3554 							(errcode(ERRCODE_SYNTAX_ERROR),
3555 							 errmsg("multiple DEFERRABLE/NOT DEFERRABLE clauses not allowed"),
3556 							 parser_errposition(cxt->pstate, con->location)));
3557 				saw_deferrability = true;
3558 				lastprimarycon->deferrable = true;
3559 				break;
3560 
3561 			case CONSTR_ATTR_NOT_DEFERRABLE:
3562 				if (!SUPPORTS_ATTRS(lastprimarycon))
3563 					ereport(ERROR,
3564 							(errcode(ERRCODE_SYNTAX_ERROR),
3565 							 errmsg("misplaced NOT DEFERRABLE clause"),
3566 							 parser_errposition(cxt->pstate, con->location)));
3567 				if (saw_deferrability)
3568 					ereport(ERROR,
3569 							(errcode(ERRCODE_SYNTAX_ERROR),
3570 							 errmsg("multiple DEFERRABLE/NOT DEFERRABLE clauses not allowed"),
3571 							 parser_errposition(cxt->pstate, con->location)));
3572 				saw_deferrability = true;
3573 				lastprimarycon->deferrable = false;
3574 				if (saw_initially &&
3575 					lastprimarycon->initdeferred)
3576 					ereport(ERROR,
3577 							(errcode(ERRCODE_SYNTAX_ERROR),
3578 							 errmsg("constraint declared INITIALLY DEFERRED must be DEFERRABLE"),
3579 							 parser_errposition(cxt->pstate, con->location)));
3580 				break;
3581 
3582 			case CONSTR_ATTR_DEFERRED:
3583 				if (!SUPPORTS_ATTRS(lastprimarycon))
3584 					ereport(ERROR,
3585 							(errcode(ERRCODE_SYNTAX_ERROR),
3586 							 errmsg("misplaced INITIALLY DEFERRED clause"),
3587 							 parser_errposition(cxt->pstate, con->location)));
3588 				if (saw_initially)
3589 					ereport(ERROR,
3590 							(errcode(ERRCODE_SYNTAX_ERROR),
3591 							 errmsg("multiple INITIALLY IMMEDIATE/DEFERRED clauses not allowed"),
3592 							 parser_errposition(cxt->pstate, con->location)));
3593 				saw_initially = true;
3594 				lastprimarycon->initdeferred = true;
3595 
3596 				/*
3597 				 * If only INITIALLY DEFERRED appears, assume DEFERRABLE
3598 				 */
3599 				if (!saw_deferrability)
3600 					lastprimarycon->deferrable = true;
3601 				else if (!lastprimarycon->deferrable)
3602 					ereport(ERROR,
3603 							(errcode(ERRCODE_SYNTAX_ERROR),
3604 							 errmsg("constraint declared INITIALLY DEFERRED must be DEFERRABLE"),
3605 							 parser_errposition(cxt->pstate, con->location)));
3606 				break;
3607 
3608 			case CONSTR_ATTR_IMMEDIATE:
3609 				if (!SUPPORTS_ATTRS(lastprimarycon))
3610 					ereport(ERROR,
3611 							(errcode(ERRCODE_SYNTAX_ERROR),
3612 							 errmsg("misplaced INITIALLY IMMEDIATE clause"),
3613 							 parser_errposition(cxt->pstate, con->location)));
3614 				if (saw_initially)
3615 					ereport(ERROR,
3616 							(errcode(ERRCODE_SYNTAX_ERROR),
3617 							 errmsg("multiple INITIALLY IMMEDIATE/DEFERRED clauses not allowed"),
3618 							 parser_errposition(cxt->pstate, con->location)));
3619 				saw_initially = true;
3620 				lastprimarycon->initdeferred = false;
3621 				break;
3622 
3623 			default:
3624 				/* Otherwise it's not an attribute */
3625 				lastprimarycon = con;
3626 				/* reset flags for new primary node */
3627 				saw_deferrability = false;
3628 				saw_initially = false;
3629 				break;
3630 		}
3631 	}
3632 }
3633 
3634 /*
3635  * Special handling of type definition for a column
3636  */
3637 static void
transformColumnType(CreateStmtContext * cxt,ColumnDef * column)3638 transformColumnType(CreateStmtContext *cxt, ColumnDef *column)
3639 {
3640 	/*
3641 	 * All we really need to do here is verify that the type is valid,
3642 	 * including any collation spec that might be present.
3643 	 */
3644 	Type		ctype = typenameType(cxt->pstate, column->typeName, NULL);
3645 
3646 	if (column->collClause)
3647 	{
3648 		Form_pg_type typtup = (Form_pg_type) GETSTRUCT(ctype);
3649 
3650 		LookupCollation(cxt->pstate,
3651 						column->collClause->collname,
3652 						column->collClause->location);
3653 		/* Complain if COLLATE is applied to an uncollatable type */
3654 		if (!OidIsValid(typtup->typcollation))
3655 			ereport(ERROR,
3656 					(errcode(ERRCODE_DATATYPE_MISMATCH),
3657 					 errmsg("collations are not supported by type %s",
3658 							format_type_be(typtup->oid)),
3659 					 parser_errposition(cxt->pstate,
3660 										column->collClause->location)));
3661 	}
3662 
3663 	ReleaseSysCache(ctype);
3664 }
3665 
3666 
3667 /*
3668  * transformCreateSchemaStmt -
3669  *	  analyzes the CREATE SCHEMA statement
3670  *
3671  * Split the schema element list into individual commands and place
3672  * them in the result list in an order such that there are no forward
3673  * references (e.g. GRANT to a table created later in the list). Note
3674  * that the logic we use for determining forward references is
3675  * presently quite incomplete.
3676  *
3677  * SQL also allows constraints to make forward references, so thumb through
3678  * the table columns and move forward references to a posterior alter-table
3679  * command.
3680  *
3681  * The result is a list of parse nodes that still need to be analyzed ---
3682  * but we can't analyze the later commands until we've executed the earlier
3683  * ones, because of possible inter-object references.
3684  *
3685  * Note: this breaks the rules a little bit by modifying schema-name fields
3686  * within passed-in structs.  However, the transformation would be the same
3687  * if done over, so it should be all right to scribble on the input to this
3688  * extent.
3689  */
3690 List *
transformCreateSchemaStmt(CreateSchemaStmt * stmt)3691 transformCreateSchemaStmt(CreateSchemaStmt *stmt)
3692 {
3693 	CreateSchemaStmtContext cxt;
3694 	List	   *result;
3695 	ListCell   *elements;
3696 
3697 	cxt.stmtType = "CREATE SCHEMA";
3698 	cxt.schemaname = stmt->schemaname;
3699 	cxt.authrole = (RoleSpec *) stmt->authrole;
3700 	cxt.sequences = NIL;
3701 	cxt.tables = NIL;
3702 	cxt.views = NIL;
3703 	cxt.indexes = NIL;
3704 	cxt.triggers = NIL;
3705 	cxt.grants = NIL;
3706 
3707 	/*
3708 	 * Run through each schema element in the schema element list. Separate
3709 	 * statements by type, and do preliminary analysis.
3710 	 */
3711 	foreach(elements, stmt->schemaElts)
3712 	{
3713 		Node	   *element = lfirst(elements);
3714 
3715 		switch (nodeTag(element))
3716 		{
3717 			case T_CreateSeqStmt:
3718 				{
3719 					CreateSeqStmt *elp = (CreateSeqStmt *) element;
3720 
3721 					setSchemaName(cxt.schemaname, &elp->sequence->schemaname);
3722 					cxt.sequences = lappend(cxt.sequences, element);
3723 				}
3724 				break;
3725 
3726 			case T_CreateStmt:
3727 				{
3728 					CreateStmt *elp = (CreateStmt *) element;
3729 
3730 					setSchemaName(cxt.schemaname, &elp->relation->schemaname);
3731 
3732 					/*
3733 					 * XXX todo: deal with constraints
3734 					 */
3735 					cxt.tables = lappend(cxt.tables, element);
3736 				}
3737 				break;
3738 
3739 			case T_ViewStmt:
3740 				{
3741 					ViewStmt   *elp = (ViewStmt *) element;
3742 
3743 					setSchemaName(cxt.schemaname, &elp->view->schemaname);
3744 
3745 					/*
3746 					 * XXX todo: deal with references between views
3747 					 */
3748 					cxt.views = lappend(cxt.views, element);
3749 				}
3750 				break;
3751 
3752 			case T_IndexStmt:
3753 				{
3754 					IndexStmt  *elp = (IndexStmt *) element;
3755 
3756 					setSchemaName(cxt.schemaname, &elp->relation->schemaname);
3757 					cxt.indexes = lappend(cxt.indexes, element);
3758 				}
3759 				break;
3760 
3761 			case T_CreateTrigStmt:
3762 				{
3763 					CreateTrigStmt *elp = (CreateTrigStmt *) element;
3764 
3765 					setSchemaName(cxt.schemaname, &elp->relation->schemaname);
3766 					cxt.triggers = lappend(cxt.triggers, element);
3767 				}
3768 				break;
3769 
3770 			case T_GrantStmt:
3771 				cxt.grants = lappend(cxt.grants, element);
3772 				break;
3773 
3774 			default:
3775 				elog(ERROR, "unrecognized node type: %d",
3776 					 (int) nodeTag(element));
3777 		}
3778 	}
3779 
3780 	result = NIL;
3781 	result = list_concat(result, cxt.sequences);
3782 	result = list_concat(result, cxt.tables);
3783 	result = list_concat(result, cxt.views);
3784 	result = list_concat(result, cxt.indexes);
3785 	result = list_concat(result, cxt.triggers);
3786 	result = list_concat(result, cxt.grants);
3787 
3788 	return result;
3789 }
3790 
3791 /*
3792  * setSchemaName
3793  *		Set or check schema name in an element of a CREATE SCHEMA command
3794  */
3795 static void
setSchemaName(char * context_schema,char ** stmt_schema_name)3796 setSchemaName(char *context_schema, char **stmt_schema_name)
3797 {
3798 	if (*stmt_schema_name == NULL)
3799 		*stmt_schema_name = context_schema;
3800 	else if (strcmp(context_schema, *stmt_schema_name) != 0)
3801 		ereport(ERROR,
3802 				(errcode(ERRCODE_INVALID_SCHEMA_DEFINITION),
3803 				 errmsg("CREATE specifies a schema (%s) "
3804 						"different from the one being created (%s)",
3805 						*stmt_schema_name, context_schema)));
3806 }
3807 
3808 /*
3809  * transformPartitionCmd
3810  *		Analyze the ATTACH/DETACH PARTITION command
3811  *
3812  * In case of the ATTACH PARTITION command, cxt->partbound is set to the
3813  * transformed value of cmd->bound.
3814  */
3815 static void
transformPartitionCmd(CreateStmtContext * cxt,PartitionCmd * cmd)3816 transformPartitionCmd(CreateStmtContext *cxt, PartitionCmd *cmd)
3817 {
3818 	Relation	parentRel = cxt->rel;
3819 
3820 	switch (parentRel->rd_rel->relkind)
3821 	{
3822 		case RELKIND_PARTITIONED_TABLE:
3823 			/* transform the partition bound, if any */
3824 			Assert(RelationGetPartitionKey(parentRel) != NULL);
3825 			if (cmd->bound != NULL)
3826 				cxt->partbound = transformPartitionBound(cxt->pstate, parentRel,
3827 														 cmd->bound);
3828 			break;
3829 		case RELKIND_PARTITIONED_INDEX:
3830 			/* nothing to check */
3831 			break;
3832 		case RELKIND_RELATION:
3833 			/* the table must be partitioned */
3834 			ereport(ERROR,
3835 					(errcode(ERRCODE_INVALID_OBJECT_DEFINITION),
3836 					 errmsg("table \"%s\" is not partitioned",
3837 							RelationGetRelationName(parentRel))));
3838 			break;
3839 		case RELKIND_INDEX:
3840 			/* the index must be partitioned */
3841 			ereport(ERROR,
3842 					(errcode(ERRCODE_INVALID_OBJECT_DEFINITION),
3843 					 errmsg("index \"%s\" is not partitioned",
3844 							RelationGetRelationName(parentRel))));
3845 			break;
3846 		default:
3847 			/* parser shouldn't let this case through */
3848 			elog(ERROR, "\"%s\" is not a partitioned table or index",
3849 				 RelationGetRelationName(parentRel));
3850 			break;
3851 	}
3852 }
3853 
3854 /*
3855  * transformPartitionBound
3856  *
3857  * Transform a partition bound specification
3858  */
3859 PartitionBoundSpec *
transformPartitionBound(ParseState * pstate,Relation parent,PartitionBoundSpec * spec)3860 transformPartitionBound(ParseState *pstate, Relation parent,
3861 						PartitionBoundSpec *spec)
3862 {
3863 	PartitionBoundSpec *result_spec;
3864 	PartitionKey key = RelationGetPartitionKey(parent);
3865 	char		strategy = get_partition_strategy(key);
3866 	int			partnatts = get_partition_natts(key);
3867 	List	   *partexprs = get_partition_exprs(key);
3868 
3869 	/* Avoid scribbling on input */
3870 	result_spec = copyObject(spec);
3871 
3872 	if (spec->is_default)
3873 	{
3874 		if (strategy == PARTITION_STRATEGY_HASH)
3875 			ereport(ERROR,
3876 					(errcode(ERRCODE_INVALID_TABLE_DEFINITION),
3877 					 errmsg("a hash-partitioned table may not have a default partition")));
3878 
3879 		/*
3880 		 * In case of the default partition, parser had no way to identify the
3881 		 * partition strategy. Assign the parent's strategy to the default
3882 		 * partition bound spec.
3883 		 */
3884 		result_spec->strategy = strategy;
3885 
3886 		return result_spec;
3887 	}
3888 
3889 	if (strategy == PARTITION_STRATEGY_HASH)
3890 	{
3891 		if (spec->strategy != PARTITION_STRATEGY_HASH)
3892 			ereport(ERROR,
3893 					(errcode(ERRCODE_INVALID_TABLE_DEFINITION),
3894 					 errmsg("invalid bound specification for a hash partition"),
3895 					 parser_errposition(pstate, exprLocation((Node *) spec))));
3896 
3897 		if (spec->modulus <= 0)
3898 			ereport(ERROR,
3899 					(errcode(ERRCODE_INVALID_TABLE_DEFINITION),
3900 					 errmsg("modulus for hash partition must be an integer value greater than zero")));
3901 
3902 		Assert(spec->remainder >= 0);
3903 
3904 		if (spec->remainder >= spec->modulus)
3905 			ereport(ERROR,
3906 					(errcode(ERRCODE_INVALID_TABLE_DEFINITION),
3907 					 errmsg("remainder for hash partition must be less than modulus")));
3908 	}
3909 	else if (strategy == PARTITION_STRATEGY_LIST)
3910 	{
3911 		ListCell   *cell;
3912 		char	   *colname;
3913 		Oid			coltype;
3914 		int32		coltypmod;
3915 		Oid			partcollation;
3916 
3917 		if (spec->strategy != PARTITION_STRATEGY_LIST)
3918 			ereport(ERROR,
3919 					(errcode(ERRCODE_INVALID_TABLE_DEFINITION),
3920 					 errmsg("invalid bound specification for a list partition"),
3921 					 parser_errposition(pstate, exprLocation((Node *) spec))));
3922 
3923 		/* Get the only column's name in case we need to output an error */
3924 		if (key->partattrs[0] != 0)
3925 			colname = get_attname(RelationGetRelid(parent),
3926 								  key->partattrs[0], false);
3927 		else
3928 			colname = deparse_expression((Node *) linitial(partexprs),
3929 										 deparse_context_for(RelationGetRelationName(parent),
3930 															 RelationGetRelid(parent)),
3931 										 false, false);
3932 		/* Need its type data too */
3933 		coltype = get_partition_col_typid(key, 0);
3934 		coltypmod = get_partition_col_typmod(key, 0);
3935 		partcollation = get_partition_col_collation(key, 0);
3936 
3937 		result_spec->listdatums = NIL;
3938 		foreach(cell, spec->listdatums)
3939 		{
3940 			Node	   *expr = lfirst(cell);
3941 			Const	   *value;
3942 			ListCell   *cell2;
3943 			bool		duplicate;
3944 
3945 			value = transformPartitionBoundValue(pstate, expr,
3946 												 colname, coltype, coltypmod,
3947 												 partcollation);
3948 
3949 			/* Don't add to the result if the value is a duplicate */
3950 			duplicate = false;
3951 			foreach(cell2, result_spec->listdatums)
3952 			{
3953 				Const	   *value2 = castNode(Const, lfirst(cell2));
3954 
3955 				if (equal(value, value2))
3956 				{
3957 					duplicate = true;
3958 					break;
3959 				}
3960 			}
3961 			if (duplicate)
3962 				continue;
3963 
3964 			result_spec->listdatums = lappend(result_spec->listdatums,
3965 											  value);
3966 		}
3967 	}
3968 	else if (strategy == PARTITION_STRATEGY_RANGE)
3969 	{
3970 		if (spec->strategy != PARTITION_STRATEGY_RANGE)
3971 			ereport(ERROR,
3972 					(errcode(ERRCODE_INVALID_TABLE_DEFINITION),
3973 					 errmsg("invalid bound specification for a range partition"),
3974 					 parser_errposition(pstate, exprLocation((Node *) spec))));
3975 
3976 		if (list_length(spec->lowerdatums) != partnatts)
3977 			ereport(ERROR,
3978 					(errcode(ERRCODE_INVALID_TABLE_DEFINITION),
3979 					 errmsg("FROM must specify exactly one value per partitioning column")));
3980 		if (list_length(spec->upperdatums) != partnatts)
3981 			ereport(ERROR,
3982 					(errcode(ERRCODE_INVALID_TABLE_DEFINITION),
3983 					 errmsg("TO must specify exactly one value per partitioning column")));
3984 
3985 		/*
3986 		 * Convert raw parse nodes into PartitionRangeDatum nodes and perform
3987 		 * any necessary validation.
3988 		 */
3989 		result_spec->lowerdatums =
3990 			transformPartitionRangeBounds(pstate, spec->lowerdatums,
3991 										  parent);
3992 		result_spec->upperdatums =
3993 			transformPartitionRangeBounds(pstate, spec->upperdatums,
3994 										  parent);
3995 	}
3996 	else
3997 		elog(ERROR, "unexpected partition strategy: %d", (int) strategy);
3998 
3999 	return result_spec;
4000 }
4001 
4002 /*
4003  * transformPartitionRangeBounds
4004  *		This converts the expressions for range partition bounds from the raw
4005  *		grammar representation to PartitionRangeDatum structs
4006  */
4007 static List *
transformPartitionRangeBounds(ParseState * pstate,List * blist,Relation parent)4008 transformPartitionRangeBounds(ParseState *pstate, List *blist,
4009 							  Relation parent)
4010 {
4011 	List	   *result = NIL;
4012 	PartitionKey key = RelationGetPartitionKey(parent);
4013 	List	   *partexprs = get_partition_exprs(key);
4014 	ListCell   *lc;
4015 	int			i,
4016 				j;
4017 
4018 	i = j = 0;
4019 	foreach(lc, blist)
4020 	{
4021 		Node	   *expr = lfirst(lc);
4022 		PartitionRangeDatum *prd = NULL;
4023 
4024 		/*
4025 		 * Infinite range bounds -- "minvalue" and "maxvalue" -- get passed in
4026 		 * as ColumnRefs.
4027 		 */
4028 		if (IsA(expr, ColumnRef))
4029 		{
4030 			ColumnRef  *cref = (ColumnRef *) expr;
4031 			char	   *cname = NULL;
4032 
4033 			/*
4034 			 * There should be a single field named either "minvalue" or
4035 			 * "maxvalue".
4036 			 */
4037 			if (list_length(cref->fields) == 1 &&
4038 				IsA(linitial(cref->fields), String))
4039 				cname = strVal(linitial(cref->fields));
4040 
4041 			if (cname == NULL)
4042 			{
4043 				/*
4044 				 * ColumnRef is not in the desired single-field-name form. For
4045 				 * consistency between all partition strategies, let the
4046 				 * expression transformation report any errors rather than
4047 				 * doing it ourselves.
4048 				 */
4049 			}
4050 			else if (strcmp("minvalue", cname) == 0)
4051 			{
4052 				prd = makeNode(PartitionRangeDatum);
4053 				prd->kind = PARTITION_RANGE_DATUM_MINVALUE;
4054 				prd->value = NULL;
4055 			}
4056 			else if (strcmp("maxvalue", cname) == 0)
4057 			{
4058 				prd = makeNode(PartitionRangeDatum);
4059 				prd->kind = PARTITION_RANGE_DATUM_MAXVALUE;
4060 				prd->value = NULL;
4061 			}
4062 		}
4063 
4064 		if (prd == NULL)
4065 		{
4066 			char	   *colname;
4067 			Oid			coltype;
4068 			int32		coltypmod;
4069 			Oid			partcollation;
4070 			Const	   *value;
4071 
4072 			/* Get the column's name in case we need to output an error */
4073 			if (key->partattrs[i] != 0)
4074 				colname = get_attname(RelationGetRelid(parent),
4075 									  key->partattrs[i], false);
4076 			else
4077 			{
4078 				colname = deparse_expression((Node *) list_nth(partexprs, j),
4079 											 deparse_context_for(RelationGetRelationName(parent),
4080 																 RelationGetRelid(parent)),
4081 											 false, false);
4082 				++j;
4083 			}
4084 
4085 			/* Need its type data too */
4086 			coltype = get_partition_col_typid(key, i);
4087 			coltypmod = get_partition_col_typmod(key, i);
4088 			partcollation = get_partition_col_collation(key, i);
4089 
4090 			value = transformPartitionBoundValue(pstate, expr,
4091 												 colname,
4092 												 coltype, coltypmod,
4093 												 partcollation);
4094 			if (value->constisnull)
4095 				ereport(ERROR,
4096 						(errcode(ERRCODE_INVALID_OBJECT_DEFINITION),
4097 						 errmsg("cannot specify NULL in range bound")));
4098 			prd = makeNode(PartitionRangeDatum);
4099 			prd->kind = PARTITION_RANGE_DATUM_VALUE;
4100 			prd->value = (Node *) value;
4101 			++i;
4102 		}
4103 
4104 		prd->location = exprLocation(expr);
4105 
4106 		result = lappend(result, prd);
4107 	}
4108 
4109 	/*
4110 	 * Once we see MINVALUE or MAXVALUE for one column, the remaining columns
4111 	 * must be the same.
4112 	 */
4113 	validateInfiniteBounds(pstate, result);
4114 
4115 	return result;
4116 }
4117 
4118 /*
4119  * validateInfiniteBounds
4120  *
4121  * Check that a MAXVALUE or MINVALUE specification in a partition bound is
4122  * followed only by more of the same.
4123  */
4124 static void
validateInfiniteBounds(ParseState * pstate,List * blist)4125 validateInfiniteBounds(ParseState *pstate, List *blist)
4126 {
4127 	ListCell   *lc;
4128 	PartitionRangeDatumKind kind = PARTITION_RANGE_DATUM_VALUE;
4129 
4130 	foreach(lc, blist)
4131 	{
4132 		PartitionRangeDatum *prd = castNode(PartitionRangeDatum, lfirst(lc));
4133 
4134 		if (kind == prd->kind)
4135 			continue;
4136 
4137 		switch (kind)
4138 		{
4139 			case PARTITION_RANGE_DATUM_VALUE:
4140 				kind = prd->kind;
4141 				break;
4142 
4143 			case PARTITION_RANGE_DATUM_MAXVALUE:
4144 				ereport(ERROR,
4145 						(errcode(ERRCODE_DATATYPE_MISMATCH),
4146 						 errmsg("every bound following MAXVALUE must also be MAXVALUE"),
4147 						 parser_errposition(pstate, exprLocation((Node *) prd))));
4148 				break;
4149 
4150 			case PARTITION_RANGE_DATUM_MINVALUE:
4151 				ereport(ERROR,
4152 						(errcode(ERRCODE_DATATYPE_MISMATCH),
4153 						 errmsg("every bound following MINVALUE must also be MINVALUE"),
4154 						 parser_errposition(pstate, exprLocation((Node *) prd))));
4155 				break;
4156 		}
4157 	}
4158 }
4159 
4160 /*
4161  * Transform one constant in a partition bound spec
4162  */
4163 static Const *
transformPartitionBoundValue(ParseState * pstate,Node * val,const char * colName,Oid colType,int32 colTypmod,Oid partCollation)4164 transformPartitionBoundValue(ParseState *pstate, Node *val,
4165 							 const char *colName, Oid colType, int32 colTypmod,
4166 							 Oid partCollation)
4167 {
4168 	Node	   *value;
4169 
4170 	/* Transform raw parsetree */
4171 	value = transformExpr(pstate, val, EXPR_KIND_PARTITION_BOUND);
4172 
4173 	/*
4174 	 * Check that the input expression's collation is compatible with one
4175 	 * specified for the parent's partition key (partcollation).  Don't throw
4176 	 * an error if it's the default collation which we'll replace with the
4177 	 * parent's collation anyway.
4178 	 */
4179 	if (IsA(value, CollateExpr))
4180 	{
4181 		Oid			exprCollOid = exprCollation(value);
4182 
4183 		/*
4184 		 * Check we have a collation iff it is a collatable type.  The only
4185 		 * expected failures here are (1) COLLATE applied to a noncollatable
4186 		 * type, or (2) partition bound expression had an unresolved
4187 		 * collation.  But we might as well code this to be a complete
4188 		 * consistency check.
4189 		 */
4190 		if (type_is_collatable(colType))
4191 		{
4192 			if (!OidIsValid(exprCollOid))
4193 				ereport(ERROR,
4194 						(errcode(ERRCODE_INDETERMINATE_COLLATION),
4195 						 errmsg("could not determine which collation to use for partition bound expression"),
4196 						 errhint("Use the COLLATE clause to set the collation explicitly.")));
4197 		}
4198 		else
4199 		{
4200 			if (OidIsValid(exprCollOid))
4201 				ereport(ERROR,
4202 						(errcode(ERRCODE_DATATYPE_MISMATCH),
4203 						 errmsg("collations are not supported by type %s",
4204 								format_type_be(colType))));
4205 		}
4206 
4207 		if (OidIsValid(exprCollOid) &&
4208 			exprCollOid != DEFAULT_COLLATION_OID &&
4209 			exprCollOid != partCollation)
4210 			ereport(ERROR,
4211 					(errcode(ERRCODE_DATATYPE_MISMATCH),
4212 					 errmsg("collation of partition bound value for column \"%s\" does not match partition key collation \"%s\"",
4213 							colName, get_collation_name(partCollation)),
4214 					 parser_errposition(pstate, exprLocation(value))));
4215 	}
4216 
4217 	/* Coerce to correct type */
4218 	value = coerce_to_target_type(pstate,
4219 								  value, exprType(value),
4220 								  colType,
4221 								  colTypmod,
4222 								  COERCION_ASSIGNMENT,
4223 								  COERCE_IMPLICIT_CAST,
4224 								  -1);
4225 
4226 	if (value == NULL)
4227 		ereport(ERROR,
4228 				(errcode(ERRCODE_DATATYPE_MISMATCH),
4229 				 errmsg("specified value cannot be cast to type %s for column \"%s\"",
4230 						format_type_be(colType), colName),
4231 				 parser_errposition(pstate, exprLocation(val))));
4232 
4233 	/* Simplify the expression, in case we had a coercion */
4234 	if (!IsA(value, Const))
4235 	{
4236 		assign_expr_collations(pstate, value);
4237 		value = (Node *) expression_planner((Expr *) value);
4238 	}
4239 
4240 	/*
4241 	 * transformExpr() should have already rejected column references,
4242 	 * subqueries, aggregates, window functions, and SRFs, based on the
4243 	 * EXPR_KIND_ for a default expression.
4244 	 */
4245 	Assert(!contain_var_clause(value));
4246 
4247 	/*
4248 	 * Evaluate the expression, assigning the partition key's collation to the
4249 	 * resulting Const expression.
4250 	 */
4251 	value = (Node *) evaluate_expr((Expr *) value, colType, colTypmod,
4252 								   partCollation);
4253 	if (!IsA(value, Const))
4254 		elog(ERROR, "could not evaluate partition bound expression");
4255 
4256 	return (Const *) value;
4257 }
4258