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