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