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