00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027 #include "postgres.h"
00028
00029 #include "access/htup_details.h"
00030 #include "access/reloptions.h"
00031 #include "catalog/dependency.h"
00032 #include "catalog/heap.h"
00033 #include "catalog/index.h"
00034 #include "catalog/namespace.h"
00035 #include "catalog/pg_collation.h"
00036 #include "catalog/pg_constraint.h"
00037 #include "catalog/pg_opclass.h"
00038 #include "catalog/pg_operator.h"
00039 #include "catalog/pg_type.h"
00040 #include "commands/comment.h"
00041 #include "commands/defrem.h"
00042 #include "commands/tablecmds.h"
00043 #include "commands/tablespace.h"
00044 #include "miscadmin.h"
00045 #include "nodes/makefuncs.h"
00046 #include "nodes/nodeFuncs.h"
00047 #include "parser/analyze.h"
00048 #include "parser/parse_clause.h"
00049 #include "parser/parse_collate.h"
00050 #include "parser/parse_expr.h"
00051 #include "parser/parse_relation.h"
00052 #include "parser/parse_target.h"
00053 #include "parser/parse_type.h"
00054 #include "parser/parse_utilcmd.h"
00055 #include "parser/parser.h"
00056 #include "rewrite/rewriteManip.h"
00057 #include "utils/acl.h"
00058 #include "utils/builtins.h"
00059 #include "utils/lsyscache.h"
00060 #include "utils/rel.h"
00061 #include "utils/syscache.h"
00062 #include "utils/typcache.h"
00063
00064
00065
00066 typedef struct
00067 {
00068 ParseState *pstate;
00069 const char *stmtType;
00070 RangeVar *relation;
00071 Relation rel;
00072 List *inhRelations;
00073 bool isforeign;
00074 bool isalter;
00075 bool hasoids;
00076 List *columns;
00077 List *ckconstraints;
00078 List *fkconstraints;
00079 List *ixconstraints;
00080 List *inh_indexes;
00081 List *blist;
00082
00083 List *alist;
00084
00085 IndexStmt *pkey;
00086 } CreateStmtContext;
00087
00088
00089 typedef struct
00090 {
00091 const char *stmtType;
00092 char *schemaname;
00093 char *authid;
00094 List *sequences;
00095 List *tables;
00096 List *views;
00097 List *indexes;
00098 List *triggers;
00099 List *grants;
00100 } CreateSchemaStmtContext;
00101
00102
00103 static void transformColumnDefinition(CreateStmtContext *cxt,
00104 ColumnDef *column);
00105 static void transformTableConstraint(CreateStmtContext *cxt,
00106 Constraint *constraint);
00107 static void transformTableLikeClause(CreateStmtContext *cxt,
00108 TableLikeClause *table_like_clause);
00109 static void transformOfType(CreateStmtContext *cxt,
00110 TypeName *ofTypename);
00111 static IndexStmt *generateClonedIndexStmt(CreateStmtContext *cxt,
00112 Relation source_idx,
00113 const AttrNumber *attmap, int attmap_length);
00114 static List *get_collation(Oid collation, Oid actual_datatype);
00115 static List *get_opclass(Oid opclass, Oid actual_datatype);
00116 static void transformIndexConstraints(CreateStmtContext *cxt);
00117 static IndexStmt *transformIndexConstraint(Constraint *constraint,
00118 CreateStmtContext *cxt);
00119 static void transformFKConstraints(CreateStmtContext *cxt,
00120 bool skipValidation,
00121 bool isAddConstraint);
00122 static void transformConstraintAttrs(CreateStmtContext *cxt,
00123 List *constraintList);
00124 static void transformColumnType(CreateStmtContext *cxt, ColumnDef *column);
00125 static void setSchemaName(char *context_schema, char **stmt_schema_name);
00126
00127
00128
00129
00130
00131
00132
00133
00134
00135
00136
00137
00138
00139
00140
00141
00142 List *
00143 transformCreateStmt(CreateStmt *stmt, const char *queryString)
00144 {
00145 ParseState *pstate;
00146 CreateStmtContext cxt;
00147 List *result;
00148 List *save_alist;
00149 ListCell *elements;
00150 Oid namespaceid;
00151 Oid existing_relid;
00152
00153
00154
00155
00156
00157 stmt = (CreateStmt *) copyObject(stmt);
00158
00159
00160
00161
00162
00163
00164
00165 namespaceid =
00166 RangeVarGetAndCheckCreationNamespace(stmt->relation, NoLock,
00167 &existing_relid);
00168
00169
00170
00171
00172
00173 if (stmt->if_not_exists && OidIsValid(existing_relid))
00174 {
00175 ereport(NOTICE,
00176 (errcode(ERRCODE_DUPLICATE_TABLE),
00177 errmsg("relation \"%s\" already exists, skipping",
00178 stmt->relation->relname)));
00179 return NIL;
00180 }
00181
00182
00183
00184
00185
00186
00187
00188
00189 if (stmt->relation->schemaname == NULL
00190 && stmt->relation->relpersistence != RELPERSISTENCE_TEMP)
00191 stmt->relation->schemaname = get_namespace_name(namespaceid);
00192
00193
00194 pstate = make_parsestate(NULL);
00195 pstate->p_sourcetext = queryString;
00196
00197 cxt.pstate = pstate;
00198 if (IsA(stmt, CreateForeignTableStmt))
00199 {
00200 cxt.stmtType = "CREATE FOREIGN TABLE";
00201 cxt.isforeign = true;
00202 }
00203 else
00204 {
00205 cxt.stmtType = "CREATE TABLE";
00206 cxt.isforeign = false;
00207 }
00208 cxt.relation = stmt->relation;
00209 cxt.rel = NULL;
00210 cxt.inhRelations = stmt->inhRelations;
00211 cxt.isalter = false;
00212 cxt.columns = NIL;
00213 cxt.ckconstraints = NIL;
00214 cxt.fkconstraints = NIL;
00215 cxt.ixconstraints = NIL;
00216 cxt.inh_indexes = NIL;
00217 cxt.blist = NIL;
00218 cxt.alist = NIL;
00219 cxt.pkey = NULL;
00220 cxt.hasoids = interpretOidsOption(stmt->options, true);
00221
00222 Assert(!stmt->ofTypename || !stmt->inhRelations);
00223
00224 if (stmt->ofTypename)
00225 transformOfType(&cxt, stmt->ofTypename);
00226
00227
00228
00229
00230
00231 foreach(elements, stmt->tableElts)
00232 {
00233 Node *element = lfirst(elements);
00234
00235 switch (nodeTag(element))
00236 {
00237 case T_ColumnDef:
00238 transformColumnDefinition(&cxt, (ColumnDef *) element);
00239 break;
00240
00241 case T_Constraint:
00242 transformTableConstraint(&cxt, (Constraint *) element);
00243 break;
00244
00245 case T_TableLikeClause:
00246 transformTableLikeClause(&cxt, (TableLikeClause *) element);
00247 break;
00248
00249 default:
00250 elog(ERROR, "unrecognized node type: %d",
00251 (int) nodeTag(element));
00252 break;
00253 }
00254 }
00255
00256
00257
00258
00259
00260 save_alist = cxt.alist;
00261 cxt.alist = NIL;
00262
00263 Assert(stmt->constraints == NIL);
00264
00265
00266
00267
00268 transformIndexConstraints(&cxt);
00269
00270
00271
00272
00273 transformFKConstraints(&cxt, true, false);
00274
00275
00276
00277
00278 stmt->tableElts = cxt.columns;
00279 stmt->constraints = cxt.ckconstraints;
00280
00281 result = lappend(cxt.blist, stmt);
00282 result = list_concat(result, cxt.alist);
00283 result = list_concat(result, save_alist);
00284
00285 return result;
00286 }
00287
00288
00289
00290
00291
00292
00293 static void
00294 transformColumnDefinition(CreateStmtContext *cxt, ColumnDef *column)
00295 {
00296 bool is_serial;
00297 bool saw_nullable;
00298 bool saw_default;
00299 Constraint *constraint;
00300 ListCell *clist;
00301
00302 cxt->columns = lappend(cxt->columns, column);
00303
00304
00305 is_serial = false;
00306 if (column->typeName
00307 && list_length(column->typeName->names) == 1
00308 && !column->typeName->pct_type)
00309 {
00310 char *typname = strVal(linitial(column->typeName->names));
00311
00312 if (strcmp(typname, "smallserial") == 0 ||
00313 strcmp(typname, "serial2") == 0)
00314 {
00315 is_serial = true;
00316 column->typeName->names = NIL;
00317 column->typeName->typeOid = INT2OID;
00318 }
00319 else if (strcmp(typname, "serial") == 0 ||
00320 strcmp(typname, "serial4") == 0)
00321 {
00322 is_serial = true;
00323 column->typeName->names = NIL;
00324 column->typeName->typeOid = INT4OID;
00325 }
00326 else if (strcmp(typname, "bigserial") == 0 ||
00327 strcmp(typname, "serial8") == 0)
00328 {
00329 is_serial = true;
00330 column->typeName->names = NIL;
00331 column->typeName->typeOid = INT8OID;
00332 }
00333
00334
00335
00336
00337
00338
00339 if (is_serial && column->typeName->arrayBounds != NIL)
00340 ereport(ERROR,
00341 (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
00342 errmsg("array of serial is not implemented"),
00343 parser_errposition(cxt->pstate,
00344 column->typeName->location)));
00345 }
00346
00347
00348 if (column->typeName)
00349 transformColumnType(cxt, column);
00350
00351
00352 if (is_serial)
00353 {
00354 Oid snamespaceid;
00355 char *snamespace;
00356 char *sname;
00357 char *qstring;
00358 A_Const *snamenode;
00359 TypeCast *castnode;
00360 FuncCall *funccallnode;
00361 CreateSeqStmt *seqstmt;
00362 AlterSeqStmt *altseqstmt;
00363 List *attnamelist;
00364
00365
00366
00367
00368
00369
00370
00371
00372
00373
00374
00375
00376 if (cxt->rel)
00377 snamespaceid = RelationGetNamespace(cxt->rel);
00378 else
00379 {
00380 snamespaceid = RangeVarGetCreationNamespace(cxt->relation);
00381 RangeVarAdjustRelationPersistence(cxt->relation, snamespaceid);
00382 }
00383 snamespace = get_namespace_name(snamespaceid);
00384 sname = ChooseRelationName(cxt->relation->relname,
00385 column->colname,
00386 "seq",
00387 snamespaceid);
00388
00389 ereport(DEBUG1,
00390 (errmsg("%s will create implicit sequence \"%s\" for serial column \"%s.%s\"",
00391 cxt->stmtType, sname,
00392 cxt->relation->relname, column->colname)));
00393
00394
00395
00396
00397
00398
00399 seqstmt = makeNode(CreateSeqStmt);
00400 seqstmt->sequence = makeRangeVar(snamespace, sname, -1);
00401 seqstmt->options = NIL;
00402
00403
00404
00405
00406
00407
00408
00409
00410 if (cxt->rel)
00411 seqstmt->ownerId = cxt->rel->rd_rel->relowner;
00412 else
00413 seqstmt->ownerId = InvalidOid;
00414
00415 cxt->blist = lappend(cxt->blist, seqstmt);
00416
00417
00418
00419
00420
00421
00422 altseqstmt = makeNode(AlterSeqStmt);
00423 altseqstmt->sequence = makeRangeVar(snamespace, sname, -1);
00424 attnamelist = list_make3(makeString(snamespace),
00425 makeString(cxt->relation->relname),
00426 makeString(column->colname));
00427 altseqstmt->options = list_make1(makeDefElem("owned_by",
00428 (Node *) attnamelist));
00429
00430 cxt->alist = lappend(cxt->alist, altseqstmt);
00431
00432
00433
00434
00435
00436
00437
00438
00439
00440
00441
00442 qstring = quote_qualified_identifier(snamespace, sname);
00443 snamenode = makeNode(A_Const);
00444 snamenode->val.type = T_String;
00445 snamenode->val.val.str = qstring;
00446 snamenode->location = -1;
00447 castnode = makeNode(TypeCast);
00448 castnode->typeName = SystemTypeName("regclass");
00449 castnode->arg = (Node *) snamenode;
00450 castnode->location = -1;
00451 funccallnode = makeNode(FuncCall);
00452 funccallnode->funcname = SystemFuncName("nextval");
00453 funccallnode->args = list_make1(castnode);
00454 funccallnode->agg_order = NIL;
00455 funccallnode->agg_star = false;
00456 funccallnode->agg_distinct = false;
00457 funccallnode->func_variadic = false;
00458 funccallnode->over = NULL;
00459 funccallnode->location = -1;
00460
00461 constraint = makeNode(Constraint);
00462 constraint->contype = CONSTR_DEFAULT;
00463 constraint->location = -1;
00464 constraint->raw_expr = (Node *) funccallnode;
00465 constraint->cooked_expr = NULL;
00466 column->constraints = lappend(column->constraints, constraint);
00467
00468 constraint = makeNode(Constraint);
00469 constraint->contype = CONSTR_NOTNULL;
00470 constraint->location = -1;
00471 column->constraints = lappend(column->constraints, constraint);
00472 }
00473
00474
00475 transformConstraintAttrs(cxt, column->constraints);
00476
00477 saw_nullable = false;
00478 saw_default = false;
00479
00480 foreach(clist, column->constraints)
00481 {
00482 constraint = lfirst(clist);
00483 Assert(IsA(constraint, Constraint));
00484
00485 switch (constraint->contype)
00486 {
00487 case CONSTR_NULL:
00488 if (saw_nullable && column->is_not_null)
00489 ereport(ERROR,
00490 (errcode(ERRCODE_SYNTAX_ERROR),
00491 errmsg("conflicting NULL/NOT NULL declarations for column \"%s\" of table \"%s\"",
00492 column->colname, cxt->relation->relname),
00493 parser_errposition(cxt->pstate,
00494 constraint->location)));
00495 column->is_not_null = FALSE;
00496 saw_nullable = true;
00497 break;
00498
00499 case CONSTR_NOTNULL:
00500 if (saw_nullable && !column->is_not_null)
00501 ereport(ERROR,
00502 (errcode(ERRCODE_SYNTAX_ERROR),
00503 errmsg("conflicting NULL/NOT NULL declarations for column \"%s\" of table \"%s\"",
00504 column->colname, cxt->relation->relname),
00505 parser_errposition(cxt->pstate,
00506 constraint->location)));
00507 column->is_not_null = TRUE;
00508 saw_nullable = true;
00509 break;
00510
00511 case CONSTR_DEFAULT:
00512 if (saw_default)
00513 ereport(ERROR,
00514 (errcode(ERRCODE_SYNTAX_ERROR),
00515 errmsg("multiple default values specified for column \"%s\" of table \"%s\"",
00516 column->colname, cxt->relation->relname),
00517 parser_errposition(cxt->pstate,
00518 constraint->location)));
00519 column->raw_default = constraint->raw_expr;
00520 Assert(constraint->cooked_expr == NULL);
00521 saw_default = true;
00522 break;
00523
00524 case CONSTR_CHECK:
00525 if (cxt->isforeign)
00526 ereport(ERROR,
00527 (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
00528 errmsg("constraints are not supported on foreign tables"),
00529 parser_errposition(cxt->pstate,
00530 constraint->location)));
00531 cxt->ckconstraints = lappend(cxt->ckconstraints, constraint);
00532 break;
00533
00534 case CONSTR_PRIMARY:
00535 case CONSTR_UNIQUE:
00536 if (cxt->isforeign)
00537 ereport(ERROR,
00538 (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
00539 errmsg("constraints are not supported on foreign tables"),
00540 parser_errposition(cxt->pstate,
00541 constraint->location)));
00542 if (constraint->keys == NIL)
00543 constraint->keys = list_make1(makeString(column->colname));
00544 cxt->ixconstraints = lappend(cxt->ixconstraints, constraint);
00545 break;
00546
00547 case CONSTR_EXCLUSION:
00548
00549 elog(ERROR, "column exclusion constraints are not supported");
00550 break;
00551
00552 case CONSTR_FOREIGN:
00553 if (cxt->isforeign)
00554 ereport(ERROR,
00555 (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
00556 errmsg("constraints are not supported on foreign tables"),
00557 parser_errposition(cxt->pstate,
00558 constraint->location)));
00559
00560
00561
00562
00563 constraint->fk_attrs = list_make1(makeString(column->colname));
00564 cxt->fkconstraints = lappend(cxt->fkconstraints, constraint);
00565 break;
00566
00567 case CONSTR_ATTR_DEFERRABLE:
00568 case CONSTR_ATTR_NOT_DEFERRABLE:
00569 case CONSTR_ATTR_DEFERRED:
00570 case CONSTR_ATTR_IMMEDIATE:
00571
00572 break;
00573
00574 default:
00575 elog(ERROR, "unrecognized constraint type: %d",
00576 constraint->contype);
00577 break;
00578 }
00579 }
00580
00581
00582
00583
00584
00585 if (column->fdwoptions != NIL)
00586 {
00587 AlterTableStmt *stmt;
00588 AlterTableCmd *cmd;
00589
00590 cmd = makeNode(AlterTableCmd);
00591 cmd->subtype = AT_AlterColumnGenericOptions;
00592 cmd->name = column->colname;
00593 cmd->def = (Node *) column->fdwoptions;
00594 cmd->behavior = DROP_RESTRICT;
00595 cmd->missing_ok = false;
00596
00597 stmt = makeNode(AlterTableStmt);
00598 stmt->relation = cxt->relation;
00599 stmt->cmds = NIL;
00600 stmt->relkind = OBJECT_FOREIGN_TABLE;
00601 stmt->cmds = lappend(stmt->cmds, cmd);
00602
00603 cxt->alist = lappend(cxt->alist, stmt);
00604 }
00605 }
00606
00607
00608
00609
00610
00611 static void
00612 transformTableConstraint(CreateStmtContext *cxt, Constraint *constraint)
00613 {
00614 if (cxt->isforeign)
00615 ereport(ERROR,
00616 (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
00617 errmsg("constraints are not supported on foreign tables"),
00618 parser_errposition(cxt->pstate,
00619 constraint->location)));
00620
00621 switch (constraint->contype)
00622 {
00623 case CONSTR_PRIMARY:
00624 case CONSTR_UNIQUE:
00625 case CONSTR_EXCLUSION:
00626 cxt->ixconstraints = lappend(cxt->ixconstraints, constraint);
00627 break;
00628
00629 case CONSTR_CHECK:
00630 cxt->ckconstraints = lappend(cxt->ckconstraints, constraint);
00631 break;
00632
00633 case CONSTR_FOREIGN:
00634 cxt->fkconstraints = lappend(cxt->fkconstraints, constraint);
00635 break;
00636
00637 case CONSTR_NULL:
00638 case CONSTR_NOTNULL:
00639 case CONSTR_DEFAULT:
00640 case CONSTR_ATTR_DEFERRABLE:
00641 case CONSTR_ATTR_NOT_DEFERRABLE:
00642 case CONSTR_ATTR_DEFERRED:
00643 case CONSTR_ATTR_IMMEDIATE:
00644 elog(ERROR, "invalid context for constraint type %d",
00645 constraint->contype);
00646 break;
00647
00648 default:
00649 elog(ERROR, "unrecognized constraint type: %d",
00650 constraint->contype);
00651 break;
00652 }
00653 }
00654
00655
00656
00657
00658
00659
00660
00661
00662 static void
00663 transformTableLikeClause(CreateStmtContext *cxt, TableLikeClause *table_like_clause)
00664 {
00665 AttrNumber parent_attno;
00666 Relation relation;
00667 TupleDesc tupleDesc;
00668 TupleConstr *constr;
00669 AttrNumber *attmap;
00670 AclResult aclresult;
00671 char *comment;
00672 ParseCallbackState pcbstate;
00673
00674 setup_parser_errposition_callback(&pcbstate, cxt->pstate,
00675 table_like_clause->relation->location);
00676
00677
00678 if (cxt->isforeign)
00679 ereport(ERROR,
00680 (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
00681 errmsg("LIKE is not supported for foreign tables")));
00682
00683 relation = relation_openrv(table_like_clause->relation, AccessShareLock);
00684
00685 if (relation->rd_rel->relkind != RELKIND_RELATION &&
00686 relation->rd_rel->relkind != RELKIND_VIEW &&
00687 relation->rd_rel->relkind != RELKIND_MATVIEW &&
00688 relation->rd_rel->relkind != RELKIND_COMPOSITE_TYPE &&
00689 relation->rd_rel->relkind != RELKIND_FOREIGN_TABLE)
00690 ereport(ERROR,
00691 (errcode(ERRCODE_WRONG_OBJECT_TYPE),
00692 errmsg("\"%s\" is not a table, view, composite type, or foreign table",
00693 RelationGetRelationName(relation))));
00694
00695 cancel_parser_errposition_callback(&pcbstate);
00696
00697
00698
00699
00700 if (relation->rd_rel->relkind == RELKIND_COMPOSITE_TYPE)
00701 {
00702 aclresult = pg_type_aclcheck(relation->rd_rel->reltype, GetUserId(),
00703 ACL_USAGE);
00704 if (aclresult != ACLCHECK_OK)
00705 aclcheck_error(aclresult, ACL_KIND_TYPE,
00706 RelationGetRelationName(relation));
00707 }
00708 else
00709 {
00710 aclresult = pg_class_aclcheck(RelationGetRelid(relation), GetUserId(),
00711 ACL_SELECT);
00712 if (aclresult != ACLCHECK_OK)
00713 aclcheck_error(aclresult, ACL_KIND_CLASS,
00714 RelationGetRelationName(relation));
00715 }
00716
00717 tupleDesc = RelationGetDescr(relation);
00718 constr = tupleDesc->constr;
00719
00720
00721
00722
00723
00724
00725 attmap = (AttrNumber *) palloc0(sizeof(AttrNumber) * tupleDesc->natts);
00726
00727
00728
00729
00730 for (parent_attno = 1; parent_attno <= tupleDesc->natts;
00731 parent_attno++)
00732 {
00733 Form_pg_attribute attribute = tupleDesc->attrs[parent_attno - 1];
00734 char *attributeName = NameStr(attribute->attname);
00735 ColumnDef *def;
00736
00737
00738
00739
00740 if (attribute->attisdropped)
00741 continue;
00742
00743
00744
00745
00746
00747
00748
00749 def = makeNode(ColumnDef);
00750 def->colname = pstrdup(attributeName);
00751 def->typeName = makeTypeNameFromOid(attribute->atttypid,
00752 attribute->atttypmod);
00753 def->inhcount = 0;
00754 def->is_local = true;
00755 def->is_not_null = attribute->attnotnull;
00756 def->is_from_type = false;
00757 def->storage = 0;
00758 def->raw_default = NULL;
00759 def->cooked_default = NULL;
00760 def->collClause = NULL;
00761 def->collOid = attribute->attcollation;
00762 def->constraints = NIL;
00763
00764
00765
00766
00767 cxt->columns = lappend(cxt->columns, def);
00768
00769 attmap[parent_attno - 1] = list_length(cxt->columns);
00770
00771
00772
00773
00774 if (attribute->atthasdef &&
00775 (table_like_clause->options & CREATE_TABLE_LIKE_DEFAULTS))
00776 {
00777 Node *this_default = NULL;
00778 AttrDefault *attrdef;
00779 int i;
00780
00781
00782 Assert(constr != NULL);
00783 attrdef = constr->defval;
00784 for (i = 0; i < constr->num_defval; i++)
00785 {
00786 if (attrdef[i].adnum == parent_attno)
00787 {
00788 this_default = stringToNode(attrdef[i].adbin);
00789 break;
00790 }
00791 }
00792 Assert(this_default != NULL);
00793
00794
00795
00796
00797
00798
00799 def->cooked_default = this_default;
00800 }
00801
00802
00803 if (table_like_clause->options & CREATE_TABLE_LIKE_STORAGE)
00804 def->storage = attribute->attstorage;
00805 else
00806 def->storage = 0;
00807
00808
00809 if ((table_like_clause->options & CREATE_TABLE_LIKE_COMMENTS) &&
00810 (comment = GetComment(attribute->attrelid,
00811 RelationRelationId,
00812 attribute->attnum)) != NULL)
00813 {
00814 CommentStmt *stmt = makeNode(CommentStmt);
00815
00816 stmt->objtype = OBJECT_COLUMN;
00817 stmt->objname = list_make3(makeString(cxt->relation->schemaname),
00818 makeString(cxt->relation->relname),
00819 makeString(def->colname));
00820 stmt->objargs = NIL;
00821 stmt->comment = comment;
00822
00823 cxt->alist = lappend(cxt->alist, stmt);
00824 }
00825 }
00826
00827
00828
00829
00830
00831 if ((table_like_clause->options & CREATE_TABLE_LIKE_CONSTRAINTS) &&
00832 tupleDesc->constr)
00833 {
00834 int ccnum;
00835
00836 for (ccnum = 0; ccnum < tupleDesc->constr->num_check; ccnum++)
00837 {
00838 char *ccname = tupleDesc->constr->check[ccnum].ccname;
00839 char *ccbin = tupleDesc->constr->check[ccnum].ccbin;
00840 Constraint *n = makeNode(Constraint);
00841 Node *ccbin_node;
00842 bool found_whole_row;
00843
00844 ccbin_node = map_variable_attnos(stringToNode(ccbin),
00845 1, 0,
00846 attmap, tupleDesc->natts,
00847 &found_whole_row);
00848
00849
00850
00851
00852
00853
00854
00855 if (found_whole_row)
00856 ereport(ERROR,
00857 (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
00858 errmsg("cannot convert whole-row table reference"),
00859 errdetail("Constraint \"%s\" contains a whole-row reference to table \"%s\".",
00860 ccname,
00861 RelationGetRelationName(relation))));
00862
00863 n->contype = CONSTR_CHECK;
00864 n->location = -1;
00865 n->conname = pstrdup(ccname);
00866 n->raw_expr = NULL;
00867 n->cooked_expr = nodeToString(ccbin_node);
00868 cxt->ckconstraints = lappend(cxt->ckconstraints, n);
00869
00870
00871 if ((table_like_clause->options & CREATE_TABLE_LIKE_COMMENTS) &&
00872 (comment = GetComment(get_relation_constraint_oid(RelationGetRelid(relation),
00873 n->conname, false),
00874 ConstraintRelationId,
00875 0)) != NULL)
00876 {
00877 CommentStmt *stmt = makeNode(CommentStmt);
00878
00879 stmt->objtype = OBJECT_CONSTRAINT;
00880 stmt->objname = list_make3(makeString(cxt->relation->schemaname),
00881 makeString(cxt->relation->relname),
00882 makeString(n->conname));
00883 stmt->objargs = NIL;
00884 stmt->comment = comment;
00885
00886 cxt->alist = lappend(cxt->alist, stmt);
00887 }
00888 }
00889 }
00890
00891
00892
00893
00894 if ((table_like_clause->options & CREATE_TABLE_LIKE_INDEXES) &&
00895 relation->rd_rel->relhasindex)
00896 {
00897 List *parent_indexes;
00898 ListCell *l;
00899
00900 parent_indexes = RelationGetIndexList(relation);
00901
00902 foreach(l, parent_indexes)
00903 {
00904 Oid parent_index_oid = lfirst_oid(l);
00905 Relation parent_index;
00906 IndexStmt *index_stmt;
00907
00908 parent_index = index_open(parent_index_oid, AccessShareLock);
00909
00910
00911 index_stmt = generateClonedIndexStmt(cxt, parent_index,
00912 attmap, tupleDesc->natts);
00913
00914
00915 if (table_like_clause->options & CREATE_TABLE_LIKE_COMMENTS)
00916 {
00917 comment = GetComment(parent_index_oid, RelationRelationId, 0);
00918
00919
00920
00921
00922
00923 index_stmt->idxcomment = comment;
00924 }
00925
00926
00927 cxt->inh_indexes = lappend(cxt->inh_indexes, index_stmt);
00928
00929 index_close(parent_index, AccessShareLock);
00930 }
00931 }
00932
00933
00934
00935
00936
00937
00938 heap_close(relation, NoLock);
00939 }
00940
00941 static void
00942 transformOfType(CreateStmtContext *cxt, TypeName *ofTypename)
00943 {
00944 HeapTuple tuple;
00945 TupleDesc tupdesc;
00946 int i;
00947 Oid ofTypeId;
00948
00949 AssertArg(ofTypename);
00950
00951 tuple = typenameType(NULL, ofTypename, NULL);
00952 check_of_type(tuple);
00953 ofTypeId = HeapTupleGetOid(tuple);
00954 ofTypename->typeOid = ofTypeId;
00955
00956 tupdesc = lookup_rowtype_tupdesc(ofTypeId, -1);
00957 for (i = 0; i < tupdesc->natts; i++)
00958 {
00959 Form_pg_attribute attr = tupdesc->attrs[i];
00960 ColumnDef *n;
00961
00962 if (attr->attisdropped)
00963 continue;
00964
00965 n = makeNode(ColumnDef);
00966 n->colname = pstrdup(NameStr(attr->attname));
00967 n->typeName = makeTypeNameFromOid(attr->atttypid, attr->atttypmod);
00968 n->inhcount = 0;
00969 n->is_local = true;
00970 n->is_not_null = false;
00971 n->is_from_type = true;
00972 n->storage = 0;
00973 n->raw_default = NULL;
00974 n->cooked_default = NULL;
00975 n->collClause = NULL;
00976 n->collOid = attr->attcollation;
00977 n->constraints = NIL;
00978 cxt->columns = lappend(cxt->columns, n);
00979 }
00980 DecrTupleDescRefCount(tupdesc);
00981
00982 ReleaseSysCache(tuple);
00983 }
00984
00985
00986
00987
00988
00989 static IndexStmt *
00990 generateClonedIndexStmt(CreateStmtContext *cxt, Relation source_idx,
00991 const AttrNumber *attmap, int attmap_length)
00992 {
00993 Oid source_relid = RelationGetRelid(source_idx);
00994 Form_pg_attribute *attrs = RelationGetDescr(source_idx)->attrs;
00995 HeapTuple ht_idxrel;
00996 HeapTuple ht_idx;
00997 Form_pg_class idxrelrec;
00998 Form_pg_index idxrec;
00999 Form_pg_am amrec;
01000 oidvector *indcollation;
01001 oidvector *indclass;
01002 IndexStmt *index;
01003 List *indexprs;
01004 ListCell *indexpr_item;
01005 Oid indrelid;
01006 int keyno;
01007 Oid keycoltype;
01008 Datum datum;
01009 bool isnull;
01010
01011
01012
01013
01014
01015 ht_idxrel = SearchSysCache1(RELOID, ObjectIdGetDatum(source_relid));
01016 if (!HeapTupleIsValid(ht_idxrel))
01017 elog(ERROR, "cache lookup failed for relation %u", source_relid);
01018 idxrelrec = (Form_pg_class) GETSTRUCT(ht_idxrel);
01019
01020
01021 ht_idx = source_idx->rd_indextuple;
01022 idxrec = (Form_pg_index) GETSTRUCT(ht_idx);
01023 indrelid = idxrec->indrelid;
01024
01025
01026 amrec = source_idx->rd_am;
01027
01028
01029 datum = SysCacheGetAttr(INDEXRELID, ht_idx,
01030 Anum_pg_index_indcollation, &isnull);
01031 Assert(!isnull);
01032 indcollation = (oidvector *) DatumGetPointer(datum);
01033
01034
01035 datum = SysCacheGetAttr(INDEXRELID, ht_idx,
01036 Anum_pg_index_indclass, &isnull);
01037 Assert(!isnull);
01038 indclass = (oidvector *) DatumGetPointer(datum);
01039
01040
01041 index = makeNode(IndexStmt);
01042 index->relation = cxt->relation;
01043 index->accessMethod = pstrdup(NameStr(amrec->amname));
01044 if (OidIsValid(idxrelrec->reltablespace))
01045 index->tableSpace = get_tablespace_name(idxrelrec->reltablespace);
01046 else
01047 index->tableSpace = NULL;
01048 index->excludeOpNames = NIL;
01049 index->idxcomment = NULL;
01050 index->indexOid = InvalidOid;
01051 index->oldNode = InvalidOid;
01052 index->unique = idxrec->indisunique;
01053 index->primary = idxrec->indisprimary;
01054 index->concurrent = false;
01055
01056
01057
01058
01059
01060 index->idxname = NULL;
01061
01062
01063
01064
01065
01066
01067
01068 if (index->primary || index->unique || idxrec->indisexclusion)
01069 {
01070 Oid constraintId = get_index_constraint(source_relid);
01071
01072 if (OidIsValid(constraintId))
01073 {
01074 HeapTuple ht_constr;
01075 Form_pg_constraint conrec;
01076
01077 ht_constr = SearchSysCache1(CONSTROID,
01078 ObjectIdGetDatum(constraintId));
01079 if (!HeapTupleIsValid(ht_constr))
01080 elog(ERROR, "cache lookup failed for constraint %u",
01081 constraintId);
01082 conrec = (Form_pg_constraint) GETSTRUCT(ht_constr);
01083
01084 index->isconstraint = true;
01085 index->deferrable = conrec->condeferrable;
01086 index->initdeferred = conrec->condeferred;
01087
01088
01089 if (idxrec->indisexclusion)
01090 {
01091 Datum *elems;
01092 int nElems;
01093 int i;
01094
01095 Assert(conrec->contype == CONSTRAINT_EXCLUSION);
01096
01097 datum = SysCacheGetAttr(CONSTROID, ht_constr,
01098 Anum_pg_constraint_conexclop,
01099 &isnull);
01100 if (isnull)
01101 elog(ERROR, "null conexclop for constraint %u",
01102 constraintId);
01103
01104 deconstruct_array(DatumGetArrayTypeP(datum),
01105 OIDOID, sizeof(Oid), true, 'i',
01106 &elems, NULL, &nElems);
01107
01108 for (i = 0; i < nElems; i++)
01109 {
01110 Oid operid = DatumGetObjectId(elems[i]);
01111 HeapTuple opertup;
01112 Form_pg_operator operform;
01113 char *oprname;
01114 char *nspname;
01115 List *namelist;
01116
01117 opertup = SearchSysCache1(OPEROID,
01118 ObjectIdGetDatum(operid));
01119 if (!HeapTupleIsValid(opertup))
01120 elog(ERROR, "cache lookup failed for operator %u",
01121 operid);
01122 operform = (Form_pg_operator) GETSTRUCT(opertup);
01123 oprname = pstrdup(NameStr(operform->oprname));
01124
01125 nspname = get_namespace_name(operform->oprnamespace);
01126 namelist = list_make2(makeString(nspname),
01127 makeString(oprname));
01128 index->excludeOpNames = lappend(index->excludeOpNames,
01129 namelist);
01130 ReleaseSysCache(opertup);
01131 }
01132 }
01133
01134 ReleaseSysCache(ht_constr);
01135 }
01136 else
01137 index->isconstraint = false;
01138 }
01139 else
01140 index->isconstraint = false;
01141
01142
01143 datum = SysCacheGetAttr(INDEXRELID, ht_idx,
01144 Anum_pg_index_indexprs, &isnull);
01145 if (!isnull)
01146 {
01147 char *exprsString;
01148
01149 exprsString = TextDatumGetCString(datum);
01150 indexprs = (List *) stringToNode(exprsString);
01151 }
01152 else
01153 indexprs = NIL;
01154
01155
01156 index->indexParams = NIL;
01157
01158 indexpr_item = list_head(indexprs);
01159 for (keyno = 0; keyno < idxrec->indnatts; keyno++)
01160 {
01161 IndexElem *iparam;
01162 AttrNumber attnum = idxrec->indkey.values[keyno];
01163 int16 opt = source_idx->rd_indoption[keyno];
01164
01165 iparam = makeNode(IndexElem);
01166
01167 if (AttributeNumberIsValid(attnum))
01168 {
01169
01170 char *attname;
01171
01172 attname = get_relid_attribute_name(indrelid, attnum);
01173 keycoltype = get_atttype(indrelid, attnum);
01174
01175 iparam->name = attname;
01176 iparam->expr = NULL;
01177 }
01178 else
01179 {
01180
01181 Node *indexkey;
01182 bool found_whole_row;
01183
01184 if (indexpr_item == NULL)
01185 elog(ERROR, "too few entries in indexprs list");
01186 indexkey = (Node *) lfirst(indexpr_item);
01187 indexpr_item = lnext(indexpr_item);
01188
01189
01190 indexkey = map_variable_attnos(indexkey,
01191 1, 0,
01192 attmap, attmap_length,
01193 &found_whole_row);
01194
01195
01196 if (found_whole_row)
01197 ereport(ERROR,
01198 (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
01199 errmsg("cannot convert whole-row table reference"),
01200 errdetail("Index \"%s\" contains a whole-row table reference.",
01201 RelationGetRelationName(source_idx))));
01202
01203 iparam->name = NULL;
01204 iparam->expr = indexkey;
01205
01206 keycoltype = exprType(indexkey);
01207 }
01208
01209
01210 iparam->indexcolname = pstrdup(NameStr(attrs[keyno]->attname));
01211
01212
01213 iparam->collation = get_collation(indcollation->values[keyno], keycoltype);
01214
01215
01216 iparam->opclass = get_opclass(indclass->values[keyno], keycoltype);
01217
01218 iparam->ordering = SORTBY_DEFAULT;
01219 iparam->nulls_ordering = SORTBY_NULLS_DEFAULT;
01220
01221
01222 if (amrec->amcanorder)
01223 {
01224
01225
01226
01227
01228
01229
01230 if (opt & INDOPTION_DESC)
01231 {
01232 iparam->ordering = SORTBY_DESC;
01233 if ((opt & INDOPTION_NULLS_FIRST) == 0)
01234 iparam->nulls_ordering = SORTBY_NULLS_LAST;
01235 }
01236 else
01237 {
01238 if (opt & INDOPTION_NULLS_FIRST)
01239 iparam->nulls_ordering = SORTBY_NULLS_FIRST;
01240 }
01241 }
01242
01243 index->indexParams = lappend(index->indexParams, iparam);
01244 }
01245
01246
01247 datum = SysCacheGetAttr(RELOID, ht_idxrel,
01248 Anum_pg_class_reloptions, &isnull);
01249 if (!isnull)
01250 index->options = untransformRelOptions(datum);
01251
01252
01253 datum = SysCacheGetAttr(INDEXRELID, ht_idx,
01254 Anum_pg_index_indpred, &isnull);
01255 if (!isnull)
01256 {
01257 char *pred_str;
01258 Node *pred_tree;
01259 bool found_whole_row;
01260
01261
01262 pred_str = TextDatumGetCString(datum);
01263 pred_tree = (Node *) stringToNode(pred_str);
01264
01265
01266 pred_tree = map_variable_attnos(pred_tree,
01267 1, 0,
01268 attmap, attmap_length,
01269 &found_whole_row);
01270
01271
01272 if (found_whole_row)
01273 ereport(ERROR,
01274 (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
01275 errmsg("cannot convert whole-row table reference"),
01276 errdetail("Index \"%s\" contains a whole-row table reference.",
01277 RelationGetRelationName(source_idx))));
01278
01279 index->whereClause = pred_tree;
01280 }
01281
01282
01283 ReleaseSysCache(ht_idxrel);
01284
01285 return index;
01286 }
01287
01288
01289
01290
01291
01292
01293
01294 static List *
01295 get_collation(Oid collation, Oid actual_datatype)
01296 {
01297 List *result;
01298 HeapTuple ht_coll;
01299 Form_pg_collation coll_rec;
01300 char *nsp_name;
01301 char *coll_name;
01302
01303 if (!OidIsValid(collation))
01304 return NIL;
01305 if (collation == get_typcollation(actual_datatype))
01306 return NIL;
01307
01308 ht_coll = SearchSysCache1(COLLOID, ObjectIdGetDatum(collation));
01309 if (!HeapTupleIsValid(ht_coll))
01310 elog(ERROR, "cache lookup failed for collation %u", collation);
01311 coll_rec = (Form_pg_collation) GETSTRUCT(ht_coll);
01312
01313
01314 nsp_name = get_namespace_name(coll_rec->collnamespace);
01315 coll_name = pstrdup(NameStr(coll_rec->collname));
01316 result = list_make2(makeString(nsp_name), makeString(coll_name));
01317
01318 ReleaseSysCache(ht_coll);
01319 return result;
01320 }
01321
01322
01323
01324
01325
01326
01327
01328 static List *
01329 get_opclass(Oid opclass, Oid actual_datatype)
01330 {
01331 List *result = NIL;
01332 HeapTuple ht_opc;
01333 Form_pg_opclass opc_rec;
01334
01335 ht_opc = SearchSysCache1(CLAOID, ObjectIdGetDatum(opclass));
01336 if (!HeapTupleIsValid(ht_opc))
01337 elog(ERROR, "cache lookup failed for opclass %u", opclass);
01338 opc_rec = (Form_pg_opclass) GETSTRUCT(ht_opc);
01339
01340 if (GetDefaultOpClass(actual_datatype, opc_rec->opcmethod) != opclass)
01341 {
01342
01343 char *nsp_name = get_namespace_name(opc_rec->opcnamespace);
01344 char *opc_name = pstrdup(NameStr(opc_rec->opcname));
01345
01346 result = list_make2(makeString(nsp_name), makeString(opc_name));
01347 }
01348
01349 ReleaseSysCache(ht_opc);
01350 return result;
01351 }
01352
01353
01354
01355
01356
01357
01358
01359
01360 static void
01361 transformIndexConstraints(CreateStmtContext *cxt)
01362 {
01363 IndexStmt *index;
01364 List *indexlist = NIL;
01365 ListCell *lc;
01366
01367
01368
01369
01370
01371
01372
01373 foreach(lc, cxt->ixconstraints)
01374 {
01375 Constraint *constraint = (Constraint *) lfirst(lc);
01376
01377 Assert(IsA(constraint, Constraint));
01378 Assert(constraint->contype == CONSTR_PRIMARY ||
01379 constraint->contype == CONSTR_UNIQUE ||
01380 constraint->contype == CONSTR_EXCLUSION);
01381
01382 index = transformIndexConstraint(constraint, cxt);
01383
01384 indexlist = lappend(indexlist, index);
01385 }
01386
01387
01388 foreach(lc, cxt->inh_indexes)
01389 {
01390 index = (IndexStmt *) lfirst(lc);
01391
01392 if (index->primary)
01393 {
01394 if (cxt->pkey != NULL)
01395 ereport(ERROR,
01396 (errcode(ERRCODE_INVALID_TABLE_DEFINITION),
01397 errmsg("multiple primary keys for table \"%s\" are not allowed",
01398 cxt->relation->relname)));
01399 cxt->pkey = index;
01400 }
01401
01402 indexlist = lappend(indexlist, index);
01403 }
01404
01405
01406
01407
01408
01409
01410
01411
01412
01413
01414 Assert(cxt->alist == NIL);
01415 if (cxt->pkey != NULL)
01416 {
01417
01418 cxt->alist = list_make1(cxt->pkey);
01419 }
01420
01421 foreach(lc, indexlist)
01422 {
01423 bool keep = true;
01424 ListCell *k;
01425
01426 index = lfirst(lc);
01427
01428
01429 if (index == cxt->pkey)
01430 continue;
01431
01432 foreach(k, cxt->alist)
01433 {
01434 IndexStmt *priorindex = lfirst(k);
01435
01436 if (equal(index->indexParams, priorindex->indexParams) &&
01437 equal(index->whereClause, priorindex->whereClause) &&
01438 equal(index->excludeOpNames, priorindex->excludeOpNames) &&
01439 strcmp(index->accessMethod, priorindex->accessMethod) == 0 &&
01440 index->deferrable == priorindex->deferrable &&
01441 index->initdeferred == priorindex->initdeferred)
01442 {
01443 priorindex->unique |= index->unique;
01444
01445
01446
01447
01448
01449
01450
01451 if (priorindex->idxname == NULL)
01452 priorindex->idxname = index->idxname;
01453 keep = false;
01454 break;
01455 }
01456 }
01457
01458 if (keep)
01459 cxt->alist = lappend(cxt->alist, index);
01460 }
01461 }
01462
01463
01464
01465
01466
01467
01468 static IndexStmt *
01469 transformIndexConstraint(Constraint *constraint, CreateStmtContext *cxt)
01470 {
01471 IndexStmt *index;
01472 ListCell *lc;
01473
01474 index = makeNode(IndexStmt);
01475
01476 index->unique = (constraint->contype != CONSTR_EXCLUSION);
01477 index->primary = (constraint->contype == CONSTR_PRIMARY);
01478 if (index->primary)
01479 {
01480 if (cxt->pkey != NULL)
01481 ereport(ERROR,
01482 (errcode(ERRCODE_INVALID_TABLE_DEFINITION),
01483 errmsg("multiple primary keys for table \"%s\" are not allowed",
01484 cxt->relation->relname),
01485 parser_errposition(cxt->pstate, constraint->location)));
01486 cxt->pkey = index;
01487
01488
01489
01490
01491
01492 }
01493 index->isconstraint = true;
01494 index->deferrable = constraint->deferrable;
01495 index->initdeferred = constraint->initdeferred;
01496
01497 if (constraint->conname != NULL)
01498 index->idxname = pstrdup(constraint->conname);
01499 else
01500 index->idxname = NULL;
01501
01502 index->relation = cxt->relation;
01503 index->accessMethod = constraint->access_method ? constraint->access_method : DEFAULT_INDEX_TYPE;
01504 index->options = constraint->options;
01505 index->tableSpace = constraint->indexspace;
01506 index->whereClause = constraint->where_clause;
01507 index->indexParams = NIL;
01508 index->excludeOpNames = NIL;
01509 index->idxcomment = NULL;
01510 index->indexOid = InvalidOid;
01511 index->oldNode = InvalidOid;
01512 index->concurrent = false;
01513
01514
01515
01516
01517
01518
01519
01520 if (constraint->indexname != NULL)
01521 {
01522 char *index_name = constraint->indexname;
01523 Relation heap_rel = cxt->rel;
01524 Oid index_oid;
01525 Relation index_rel;
01526 Form_pg_index index_form;
01527 oidvector *indclass;
01528 Datum indclassDatum;
01529 bool isnull;
01530 int i;
01531
01532
01533 Assert(constraint->keys == NIL);
01534
01535
01536 Assert(constraint->contype == CONSTR_PRIMARY ||
01537 constraint->contype == CONSTR_UNIQUE);
01538
01539
01540 if (!cxt->isalter)
01541 ereport(ERROR,
01542 (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
01543 errmsg("cannot use an existing index in CREATE TABLE"),
01544 parser_errposition(cxt->pstate, constraint->location)));
01545
01546
01547 index_oid = get_relname_relid(index_name, RelationGetNamespace(heap_rel));
01548
01549 if (!OidIsValid(index_oid))
01550 ereport(ERROR,
01551 (errcode(ERRCODE_UNDEFINED_OBJECT),
01552 errmsg("index \"%s\" does not exist", index_name),
01553 parser_errposition(cxt->pstate, constraint->location)));
01554
01555
01556 index_rel = index_open(index_oid, AccessShareLock);
01557 index_form = index_rel->rd_index;
01558
01559
01560 if (OidIsValid(get_index_constraint(index_oid)))
01561 ereport(ERROR,
01562 (errcode(ERRCODE_OBJECT_NOT_IN_PREREQUISITE_STATE),
01563 errmsg("index \"%s\" is already associated with a constraint",
01564 index_name),
01565 parser_errposition(cxt->pstate, constraint->location)));
01566
01567
01568 if (index_form->indrelid != RelationGetRelid(heap_rel))
01569 ereport(ERROR,
01570 (errcode(ERRCODE_OBJECT_NOT_IN_PREREQUISITE_STATE),
01571 errmsg("index \"%s\" does not belong to table \"%s\"",
01572 index_name, RelationGetRelationName(heap_rel)),
01573 parser_errposition(cxt->pstate, constraint->location)));
01574
01575 if (!IndexIsValid(index_form))
01576 ereport(ERROR,
01577 (errcode(ERRCODE_OBJECT_NOT_IN_PREREQUISITE_STATE),
01578 errmsg("index \"%s\" is not valid", index_name),
01579 parser_errposition(cxt->pstate, constraint->location)));
01580
01581 if (!index_form->indisunique)
01582 ereport(ERROR,
01583 (errcode(ERRCODE_WRONG_OBJECT_TYPE),
01584 errmsg("\"%s\" is not a unique index", index_name),
01585 errdetail("Cannot create a primary key or unique constraint using such an index."),
01586 parser_errposition(cxt->pstate, constraint->location)));
01587
01588 if (RelationGetIndexExpressions(index_rel) != NIL)
01589 ereport(ERROR,
01590 (errcode(ERRCODE_WRONG_OBJECT_TYPE),
01591 errmsg("index \"%s\" contains expressions", index_name),
01592 errdetail("Cannot create a primary key or unique constraint using such an index."),
01593 parser_errposition(cxt->pstate, constraint->location)));
01594
01595 if (RelationGetIndexPredicate(index_rel) != NIL)
01596 ereport(ERROR,
01597 (errcode(ERRCODE_WRONG_OBJECT_TYPE),
01598 errmsg("\"%s\" is a partial index", index_name),
01599 errdetail("Cannot create a primary key or unique constraint using such an index."),
01600 parser_errposition(cxt->pstate, constraint->location)));
01601
01602
01603
01604
01605
01606
01607 if (!index_form->indimmediate && !constraint->deferrable)
01608 ereport(ERROR,
01609 (errcode(ERRCODE_WRONG_OBJECT_TYPE),
01610 errmsg("\"%s\" is a deferrable index", index_name),
01611 errdetail("Cannot create a non-deferrable constraint using a deferrable index."),
01612 parser_errposition(cxt->pstate, constraint->location)));
01613
01614
01615
01616
01617
01618
01619
01620
01621 if (index_rel->rd_rel->relam != get_am_oid(DEFAULT_INDEX_TYPE, false))
01622 ereport(ERROR,
01623 (errcode(ERRCODE_WRONG_OBJECT_TYPE),
01624 errmsg("index \"%s\" is not a btree", index_name),
01625 parser_errposition(cxt->pstate, constraint->location)));
01626
01627
01628 indclassDatum = SysCacheGetAttr(INDEXRELID, index_rel->rd_indextuple,
01629 Anum_pg_index_indclass, &isnull);
01630 Assert(!isnull);
01631 indclass = (oidvector *) DatumGetPointer(indclassDatum);
01632
01633 for (i = 0; i < index_form->indnatts; i++)
01634 {
01635 int16 attnum = index_form->indkey.values[i];
01636 Form_pg_attribute attform;
01637 char *attname;
01638 Oid defopclass;
01639
01640
01641
01642
01643
01644
01645 if (attnum > 0)
01646 {
01647 Assert(attnum <= heap_rel->rd_att->natts);
01648 attform = heap_rel->rd_att->attrs[attnum - 1];
01649 }
01650 else
01651 attform = SystemAttributeDefinition(attnum,
01652 heap_rel->rd_rel->relhasoids);
01653 attname = pstrdup(NameStr(attform->attname));
01654
01655
01656
01657
01658
01659
01660
01661
01662 defopclass = GetDefaultOpClass(attform->atttypid,
01663 index_rel->rd_rel->relam);
01664 if (indclass->values[i] != defopclass ||
01665 index_rel->rd_indoption[i] != 0)
01666 ereport(ERROR,
01667 (errcode(ERRCODE_WRONG_OBJECT_TYPE),
01668 errmsg("index \"%s\" does not have default sorting behavior", index_name),
01669 errdetail("Cannot create a primary key or unique constraint using such an index."),
01670 parser_errposition(cxt->pstate, constraint->location)));
01671
01672 constraint->keys = lappend(constraint->keys, makeString(attname));
01673 }
01674
01675
01676 relation_close(index_rel, NoLock);
01677
01678 index->indexOid = index_oid;
01679 }
01680
01681
01682
01683
01684
01685
01686 if (constraint->contype == CONSTR_EXCLUSION)
01687 {
01688 foreach(lc, constraint->exclusions)
01689 {
01690 List *pair = (List *) lfirst(lc);
01691 IndexElem *elem;
01692 List *opname;
01693
01694 Assert(list_length(pair) == 2);
01695 elem = (IndexElem *) linitial(pair);
01696 Assert(IsA(elem, IndexElem));
01697 opname = (List *) lsecond(pair);
01698 Assert(IsA(opname, List));
01699
01700 index->indexParams = lappend(index->indexParams, elem);
01701 index->excludeOpNames = lappend(index->excludeOpNames, opname);
01702 }
01703
01704 return index;
01705 }
01706
01707
01708
01709
01710
01711
01712
01713
01714
01715 foreach(lc, constraint->keys)
01716 {
01717 char *key = strVal(lfirst(lc));
01718 bool found = false;
01719 ColumnDef *column = NULL;
01720 ListCell *columns;
01721 IndexElem *iparam;
01722
01723 foreach(columns, cxt->columns)
01724 {
01725 column = (ColumnDef *) lfirst(columns);
01726 Assert(IsA(column, ColumnDef));
01727 if (strcmp(column->colname, key) == 0)
01728 {
01729 found = true;
01730 break;
01731 }
01732 }
01733 if (found)
01734 {
01735
01736 if (constraint->contype == CONSTR_PRIMARY)
01737 column->is_not_null = TRUE;
01738 }
01739 else if (SystemAttributeByName(key, cxt->hasoids) != NULL)
01740 {
01741
01742
01743
01744
01745
01746 found = true;
01747 }
01748 else if (cxt->inhRelations)
01749 {
01750
01751 ListCell *inher;
01752
01753 foreach(inher, cxt->inhRelations)
01754 {
01755 RangeVar *inh = (RangeVar *) lfirst(inher);
01756 Relation rel;
01757 int count;
01758
01759 Assert(IsA(inh, RangeVar));
01760 rel = heap_openrv(inh, AccessShareLock);
01761 if (rel->rd_rel->relkind != RELKIND_RELATION)
01762 ereport(ERROR,
01763 (errcode(ERRCODE_WRONG_OBJECT_TYPE),
01764 errmsg("inherited relation \"%s\" is not a table",
01765 inh->relname)));
01766 for (count = 0; count < rel->rd_att->natts; count++)
01767 {
01768 Form_pg_attribute inhattr = rel->rd_att->attrs[count];
01769 char *inhname = NameStr(inhattr->attname);
01770
01771 if (inhattr->attisdropped)
01772 continue;
01773 if (strcmp(key, inhname) == 0)
01774 {
01775 found = true;
01776
01777
01778
01779
01780
01781
01782
01783 break;
01784 }
01785 }
01786 heap_close(rel, NoLock);
01787 if (found)
01788 break;
01789 }
01790 }
01791
01792
01793
01794
01795
01796
01797
01798 if (!found && !cxt->isalter)
01799 ereport(ERROR,
01800 (errcode(ERRCODE_UNDEFINED_COLUMN),
01801 errmsg("column \"%s\" named in key does not exist", key),
01802 parser_errposition(cxt->pstate, constraint->location)));
01803
01804
01805 foreach(columns, index->indexParams)
01806 {
01807 iparam = (IndexElem *) lfirst(columns);
01808 if (iparam->name && strcmp(key, iparam->name) == 0)
01809 {
01810 if (index->primary)
01811 ereport(ERROR,
01812 (errcode(ERRCODE_DUPLICATE_COLUMN),
01813 errmsg("column \"%s\" appears twice in primary key constraint",
01814 key),
01815 parser_errposition(cxt->pstate, constraint->location)));
01816 else
01817 ereport(ERROR,
01818 (errcode(ERRCODE_DUPLICATE_COLUMN),
01819 errmsg("column \"%s\" appears twice in unique constraint",
01820 key),
01821 parser_errposition(cxt->pstate, constraint->location)));
01822 }
01823 }
01824
01825
01826 iparam = makeNode(IndexElem);
01827 iparam->name = pstrdup(key);
01828 iparam->expr = NULL;
01829 iparam->indexcolname = NULL;
01830 iparam->collation = NIL;
01831 iparam->opclass = NIL;
01832 iparam->ordering = SORTBY_DEFAULT;
01833 iparam->nulls_ordering = SORTBY_NULLS_DEFAULT;
01834 index->indexParams = lappend(index->indexParams, iparam);
01835 }
01836
01837 return index;
01838 }
01839
01840
01841
01842
01843
01844 static void
01845 transformFKConstraints(CreateStmtContext *cxt,
01846 bool skipValidation, bool isAddConstraint)
01847 {
01848 ListCell *fkclist;
01849
01850 if (cxt->fkconstraints == NIL)
01851 return;
01852
01853
01854
01855
01856
01857
01858 if (skipValidation)
01859 {
01860 foreach(fkclist, cxt->fkconstraints)
01861 {
01862 Constraint *constraint = (Constraint *) lfirst(fkclist);
01863
01864 constraint->skip_validation = true;
01865 constraint->initially_valid = true;
01866 }
01867 }
01868
01869
01870
01871
01872
01873
01874
01875
01876
01877
01878
01879
01880 if (!isAddConstraint)
01881 {
01882 AlterTableStmt *alterstmt = makeNode(AlterTableStmt);
01883
01884 alterstmt->relation = cxt->relation;
01885 alterstmt->cmds = NIL;
01886 alterstmt->relkind = OBJECT_TABLE;
01887
01888 foreach(fkclist, cxt->fkconstraints)
01889 {
01890 Constraint *constraint = (Constraint *) lfirst(fkclist);
01891 AlterTableCmd *altercmd = makeNode(AlterTableCmd);
01892
01893 altercmd->subtype = AT_ProcessedConstraint;
01894 altercmd->name = NULL;
01895 altercmd->def = (Node *) constraint;
01896 alterstmt->cmds = lappend(alterstmt->cmds, altercmd);
01897 }
01898
01899 cxt->alist = lappend(cxt->alist, alterstmt);
01900 }
01901 }
01902
01903
01904
01905
01906
01907
01908
01909
01910
01911 IndexStmt *
01912 transformIndexStmt(IndexStmt *stmt, const char *queryString)
01913 {
01914 Relation rel;
01915 ParseState *pstate;
01916 RangeTblEntry *rte;
01917 ListCell *l;
01918
01919
01920
01921
01922
01923 stmt = (IndexStmt *) copyObject(stmt);
01924
01925
01926
01927
01928
01929
01930
01931
01932
01933 rel = heap_openrv(stmt->relation,
01934 (stmt->concurrent ? ShareUpdateExclusiveLock : ShareLock));
01935
01936
01937 pstate = make_parsestate(NULL);
01938 pstate->p_sourcetext = queryString;
01939
01940
01941
01942
01943
01944 rte = addRangeTableEntry(pstate, stmt->relation, NULL, false, true);
01945
01946
01947 addRTEtoQuery(pstate, rte, false, true, true);
01948
01949
01950 if (stmt->whereClause)
01951 {
01952 stmt->whereClause = transformWhereClause(pstate,
01953 stmt->whereClause,
01954 EXPR_KIND_INDEX_PREDICATE,
01955 "WHERE");
01956
01957 assign_expr_collations(pstate, stmt->whereClause);
01958 }
01959
01960
01961 foreach(l, stmt->indexParams)
01962 {
01963 IndexElem *ielem = (IndexElem *) lfirst(l);
01964
01965 if (ielem->expr)
01966 {
01967
01968 if (ielem->indexcolname == NULL)
01969 ielem->indexcolname = FigureIndexColname(ielem->expr);
01970
01971
01972 ielem->expr = transformExpr(pstate, ielem->expr,
01973 EXPR_KIND_INDEX_EXPRESSION);
01974
01975
01976 assign_expr_collations(pstate, ielem->expr);
01977
01978
01979
01980
01981
01982
01983
01984
01985
01986
01987 if (expression_returns_set(ielem->expr))
01988 ereport(ERROR,
01989 (errcode(ERRCODE_DATATYPE_MISMATCH),
01990 errmsg("index expression cannot return a set")));
01991 }
01992 }
01993
01994
01995
01996
01997
01998 if (list_length(pstate->p_rtable) != 1)
01999 ereport(ERROR,
02000 (errcode(ERRCODE_INVALID_COLUMN_REFERENCE),
02001 errmsg("index expressions and predicates can refer only to the table being indexed")));
02002
02003 free_parsestate(pstate);
02004
02005
02006 heap_close(rel, NoLock);
02007
02008 return stmt;
02009 }
02010
02011
02012
02013
02014
02015
02016
02017
02018
02019
02020
02021
02022
02023
02024 void
02025 transformRuleStmt(RuleStmt *stmt, const char *queryString,
02026 List **actions, Node **whereClause)
02027 {
02028 Relation rel;
02029 ParseState *pstate;
02030 RangeTblEntry *oldrte;
02031 RangeTblEntry *newrte;
02032
02033
02034
02035
02036
02037
02038
02039 rel = heap_openrv(stmt->relation, AccessExclusiveLock);
02040
02041 if (rel->rd_rel->relkind == RELKIND_MATVIEW)
02042 ereport(ERROR,
02043 (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
02044 errmsg("rules on materialized views are not supported")));
02045
02046
02047 pstate = make_parsestate(NULL);
02048 pstate->p_sourcetext = queryString;
02049
02050
02051
02052
02053
02054
02055 oldrte = addRangeTableEntryForRelation(pstate, rel,
02056 makeAlias("old", NIL),
02057 false, false);
02058 newrte = addRangeTableEntryForRelation(pstate, rel,
02059 makeAlias("new", NIL),
02060 false, false);
02061
02062 oldrte->requiredPerms = 0;
02063 newrte->requiredPerms = 0;
02064
02065
02066
02067
02068
02069
02070
02071
02072 switch (stmt->event)
02073 {
02074 case CMD_SELECT:
02075 addRTEtoQuery(pstate, oldrte, false, true, true);
02076 break;
02077 case CMD_UPDATE:
02078 addRTEtoQuery(pstate, oldrte, false, true, true);
02079 addRTEtoQuery(pstate, newrte, false, true, true);
02080 break;
02081 case CMD_INSERT:
02082 addRTEtoQuery(pstate, newrte, false, true, true);
02083 break;
02084 case CMD_DELETE:
02085 addRTEtoQuery(pstate, oldrte, false, true, true);
02086 break;
02087 default:
02088 elog(ERROR, "unrecognized event type: %d",
02089 (int) stmt->event);
02090 break;
02091 }
02092
02093
02094 *whereClause = transformWhereClause(pstate,
02095 (Node *) copyObject(stmt->whereClause),
02096 EXPR_KIND_WHERE,
02097 "WHERE");
02098
02099 assign_expr_collations(pstate, *whereClause);
02100
02101
02102 if (list_length(pstate->p_rtable) != 2)
02103 ereport(ERROR,
02104 (errcode(ERRCODE_INVALID_OBJECT_DEFINITION),
02105 errmsg("rule WHERE condition cannot contain references to other relations")));
02106
02107
02108
02109
02110
02111
02112
02113 if (stmt->actions == NIL)
02114 {
02115 Query *nothing_qry = makeNode(Query);
02116
02117 nothing_qry->commandType = CMD_NOTHING;
02118 nothing_qry->rtable = pstate->p_rtable;
02119 nothing_qry->jointree = makeFromExpr(NIL, NULL);
02120
02121 *actions = list_make1(nothing_qry);
02122 }
02123 else
02124 {
02125 ListCell *l;
02126 List *newactions = NIL;
02127
02128
02129
02130
02131 foreach(l, stmt->actions)
02132 {
02133 Node *action = (Node *) lfirst(l);
02134 ParseState *sub_pstate = make_parsestate(NULL);
02135 Query *sub_qry,
02136 *top_subqry;
02137 bool has_old,
02138 has_new;
02139
02140
02141
02142
02143
02144 sub_pstate->p_sourcetext = queryString;
02145
02146
02147
02148
02149
02150
02151
02152
02153 oldrte = addRangeTableEntryForRelation(sub_pstate, rel,
02154 makeAlias("old", NIL),
02155 false, false);
02156 newrte = addRangeTableEntryForRelation(sub_pstate, rel,
02157 makeAlias("new", NIL),
02158 false, false);
02159 oldrte->requiredPerms = 0;
02160 newrte->requiredPerms = 0;
02161 addRTEtoQuery(sub_pstate, oldrte, false, true, false);
02162 addRTEtoQuery(sub_pstate, newrte, false, true, false);
02163
02164
02165 top_subqry = transformStmt(sub_pstate,
02166 (Node *) copyObject(action));
02167
02168
02169
02170
02171
02172
02173 if (top_subqry->commandType == CMD_UTILITY &&
02174 *whereClause != NULL)
02175 ereport(ERROR,
02176 (errcode(ERRCODE_INVALID_OBJECT_DEFINITION),
02177 errmsg("rules with WHERE conditions can only have SELECT, INSERT, UPDATE, or DELETE actions")));
02178
02179
02180
02181
02182
02183
02184 sub_qry = getInsertSelectQuery(top_subqry, NULL);
02185
02186
02187
02188
02189
02190
02191
02192 if (sub_qry->setOperations != NULL && *whereClause != NULL)
02193 ereport(ERROR,
02194 (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
02195 errmsg("conditional UNION/INTERSECT/EXCEPT statements are not implemented")));
02196
02197
02198
02199
02200 has_old =
02201 rangeTableEntry_used((Node *) sub_qry, PRS2_OLD_VARNO, 0) ||
02202 rangeTableEntry_used(*whereClause, PRS2_OLD_VARNO, 0);
02203 has_new =
02204 rangeTableEntry_used((Node *) sub_qry, PRS2_NEW_VARNO, 0) ||
02205 rangeTableEntry_used(*whereClause, PRS2_NEW_VARNO, 0);
02206
02207 switch (stmt->event)
02208 {
02209 case CMD_SELECT:
02210 if (has_old)
02211 ereport(ERROR,
02212 (errcode(ERRCODE_INVALID_OBJECT_DEFINITION),
02213 errmsg("ON SELECT rule cannot use OLD")));
02214 if (has_new)
02215 ereport(ERROR,
02216 (errcode(ERRCODE_INVALID_OBJECT_DEFINITION),
02217 errmsg("ON SELECT rule cannot use NEW")));
02218 break;
02219 case CMD_UPDATE:
02220
02221 break;
02222 case CMD_INSERT:
02223 if (has_old)
02224 ereport(ERROR,
02225 (errcode(ERRCODE_INVALID_OBJECT_DEFINITION),
02226 errmsg("ON INSERT rule cannot use OLD")));
02227 break;
02228 case CMD_DELETE:
02229 if (has_new)
02230 ereport(ERROR,
02231 (errcode(ERRCODE_INVALID_OBJECT_DEFINITION),
02232 errmsg("ON DELETE rule cannot use NEW")));
02233 break;
02234 default:
02235 elog(ERROR, "unrecognized event type: %d",
02236 (int) stmt->event);
02237 break;
02238 }
02239
02240
02241
02242
02243
02244
02245
02246
02247
02248
02249
02250
02251
02252
02253
02254 if (rangeTableEntry_used((Node *) top_subqry->cteList,
02255 PRS2_OLD_VARNO, 0) ||
02256 rangeTableEntry_used((Node *) sub_qry->cteList,
02257 PRS2_OLD_VARNO, 0))
02258 ereport(ERROR,
02259 (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
02260 errmsg("cannot refer to OLD within WITH query")));
02261 if (rangeTableEntry_used((Node *) top_subqry->cteList,
02262 PRS2_NEW_VARNO, 0) ||
02263 rangeTableEntry_used((Node *) sub_qry->cteList,
02264 PRS2_NEW_VARNO, 0))
02265 ereport(ERROR,
02266 (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
02267 errmsg("cannot refer to NEW within WITH query")));
02268
02269
02270
02271
02272
02273
02274
02275
02276
02277
02278
02279
02280
02281
02282
02283
02284 if (has_old || (has_new && stmt->event == CMD_UPDATE))
02285 {
02286
02287
02288
02289
02290
02291 if (sub_qry->setOperations != NULL)
02292 ereport(ERROR,
02293 (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
02294 errmsg("conditional UNION/INTERSECT/EXCEPT statements are not implemented")));
02295
02296 sub_pstate->p_rtable = sub_qry->rtable;
02297 sub_pstate->p_joinlist = sub_qry->jointree->fromlist;
02298 addRTEtoQuery(sub_pstate, oldrte, true, false, false);
02299 sub_qry->jointree->fromlist = sub_pstate->p_joinlist;
02300 }
02301
02302 newactions = lappend(newactions, top_subqry);
02303
02304 free_parsestate(sub_pstate);
02305 }
02306
02307 *actions = newactions;
02308 }
02309
02310 free_parsestate(pstate);
02311
02312
02313 heap_close(rel, NoLock);
02314 }
02315
02316
02317
02318
02319
02320
02321
02322
02323
02324
02325 List *
02326 transformAlterTableStmt(AlterTableStmt *stmt, const char *queryString)
02327 {
02328 Relation rel;
02329 ParseState *pstate;
02330 CreateStmtContext cxt;
02331 List *result;
02332 List *save_alist;
02333 ListCell *lcmd,
02334 *l;
02335 List *newcmds = NIL;
02336 bool skipValidation = true;
02337 AlterTableCmd *newcmd;
02338 LOCKMODE lockmode;
02339
02340
02341
02342
02343
02344 stmt = (AlterTableStmt *) copyObject(stmt);
02345
02346
02347
02348
02349 lockmode = AlterTableGetLockLevel(stmt->cmds);
02350
02351
02352
02353
02354
02355
02356
02357
02358
02359
02360 rel = relation_openrv_extended(stmt->relation, lockmode, stmt->missing_ok);
02361 if (rel == NULL)
02362 {
02363
02364 ereport(NOTICE,
02365 (errmsg("relation \"%s\" does not exist, skipping",
02366 stmt->relation->relname)));
02367 return NIL;
02368 }
02369
02370
02371 pstate = make_parsestate(NULL);
02372 pstate->p_sourcetext = queryString;
02373
02374 cxt.pstate = pstate;
02375 if (stmt->relkind == OBJECT_FOREIGN_TABLE)
02376 {
02377 cxt.stmtType = "ALTER FOREIGN TABLE";
02378 cxt.isforeign = true;
02379 }
02380 else
02381 {
02382 cxt.stmtType = "ALTER TABLE";
02383 cxt.isforeign = false;
02384 }
02385 cxt.relation = stmt->relation;
02386 cxt.rel = rel;
02387 cxt.inhRelations = NIL;
02388 cxt.isalter = true;
02389 cxt.hasoids = false;
02390 cxt.columns = NIL;
02391 cxt.ckconstraints = NIL;
02392 cxt.fkconstraints = NIL;
02393 cxt.ixconstraints = NIL;
02394 cxt.inh_indexes = NIL;
02395 cxt.blist = NIL;
02396 cxt.alist = NIL;
02397 cxt.pkey = NULL;
02398
02399
02400
02401
02402
02403
02404 foreach(lcmd, stmt->cmds)
02405 {
02406 AlterTableCmd *cmd = (AlterTableCmd *) lfirst(lcmd);
02407
02408 switch (cmd->subtype)
02409 {
02410 case AT_AddColumn:
02411 case AT_AddColumnToView:
02412 {
02413 ColumnDef *def = (ColumnDef *) cmd->def;
02414
02415 Assert(IsA(def, ColumnDef));
02416 transformColumnDefinition(&cxt, def);
02417
02418
02419
02420
02421
02422 if (def->raw_default != NULL)
02423 skipValidation = false;
02424
02425
02426
02427
02428
02429 def->constraints = NIL;
02430
02431 newcmds = lappend(newcmds, cmd);
02432 break;
02433 }
02434 case AT_AddConstraint:
02435
02436
02437
02438
02439 if (IsA(cmd->def, Constraint))
02440 {
02441 transformTableConstraint(&cxt, (Constraint *) cmd->def);
02442 if (((Constraint *) cmd->def)->contype == CONSTR_FOREIGN)
02443 skipValidation = false;
02444 }
02445 else
02446 elog(ERROR, "unrecognized node type: %d",
02447 (int) nodeTag(cmd->def));
02448 break;
02449
02450 case AT_ProcessedConstraint:
02451
02452
02453
02454
02455
02456 cmd->subtype = AT_AddConstraint;
02457 newcmds = lappend(newcmds, cmd);
02458 break;
02459
02460 default:
02461 newcmds = lappend(newcmds, cmd);
02462 break;
02463 }
02464 }
02465
02466
02467
02468
02469
02470
02471 save_alist = cxt.alist;
02472 cxt.alist = NIL;
02473
02474
02475 transformIndexConstraints(&cxt);
02476
02477 transformFKConstraints(&cxt, skipValidation, true);
02478
02479
02480
02481
02482
02483
02484
02485 foreach(l, cxt.alist)
02486 {
02487 IndexStmt *idxstmt = (IndexStmt *) lfirst(l);
02488
02489 Assert(IsA(idxstmt, IndexStmt));
02490 idxstmt = transformIndexStmt(idxstmt, queryString);
02491 newcmd = makeNode(AlterTableCmd);
02492 newcmd->subtype = OidIsValid(idxstmt->indexOid) ? AT_AddIndexConstraint : AT_AddIndex;
02493 newcmd->def = (Node *) idxstmt;
02494 newcmds = lappend(newcmds, newcmd);
02495 }
02496 cxt.alist = NIL;
02497
02498
02499 foreach(l, cxt.ckconstraints)
02500 {
02501 newcmd = makeNode(AlterTableCmd);
02502 newcmd->subtype = AT_AddConstraint;
02503 newcmd->def = (Node *) lfirst(l);
02504 newcmds = lappend(newcmds, newcmd);
02505 }
02506 foreach(l, cxt.fkconstraints)
02507 {
02508 newcmd = makeNode(AlterTableCmd);
02509 newcmd->subtype = AT_AddConstraint;
02510 newcmd->def = (Node *) lfirst(l);
02511 newcmds = lappend(newcmds, newcmd);
02512 }
02513
02514
02515 relation_close(rel, NoLock);
02516
02517
02518
02519
02520 stmt->cmds = newcmds;
02521
02522 result = lappend(cxt.blist, stmt);
02523 result = list_concat(result, cxt.alist);
02524 result = list_concat(result, save_alist);
02525
02526 return result;
02527 }
02528
02529
02530
02531
02532
02533
02534
02535
02536
02537
02538
02539 static void
02540 transformConstraintAttrs(CreateStmtContext *cxt, List *constraintList)
02541 {
02542 Constraint *lastprimarycon = NULL;
02543 bool saw_deferrability = false;
02544 bool saw_initially = false;
02545 ListCell *clist;
02546
02547 #define SUPPORTS_ATTRS(node) \
02548 ((node) != NULL && \
02549 ((node)->contype == CONSTR_PRIMARY || \
02550 (node)->contype == CONSTR_UNIQUE || \
02551 (node)->contype == CONSTR_EXCLUSION || \
02552 (node)->contype == CONSTR_FOREIGN))
02553
02554 foreach(clist, constraintList)
02555 {
02556 Constraint *con = (Constraint *) lfirst(clist);
02557
02558 if (!IsA(con, Constraint))
02559 elog(ERROR, "unrecognized node type: %d",
02560 (int) nodeTag(con));
02561 switch (con->contype)
02562 {
02563 case CONSTR_ATTR_DEFERRABLE:
02564 if (!SUPPORTS_ATTRS(lastprimarycon))
02565 ereport(ERROR,
02566 (errcode(ERRCODE_SYNTAX_ERROR),
02567 errmsg("misplaced DEFERRABLE clause"),
02568 parser_errposition(cxt->pstate, con->location)));
02569 if (saw_deferrability)
02570 ereport(ERROR,
02571 (errcode(ERRCODE_SYNTAX_ERROR),
02572 errmsg("multiple DEFERRABLE/NOT DEFERRABLE clauses not allowed"),
02573 parser_errposition(cxt->pstate, con->location)));
02574 saw_deferrability = true;
02575 lastprimarycon->deferrable = true;
02576 break;
02577
02578 case CONSTR_ATTR_NOT_DEFERRABLE:
02579 if (!SUPPORTS_ATTRS(lastprimarycon))
02580 ereport(ERROR,
02581 (errcode(ERRCODE_SYNTAX_ERROR),
02582 errmsg("misplaced NOT DEFERRABLE clause"),
02583 parser_errposition(cxt->pstate, con->location)));
02584 if (saw_deferrability)
02585 ereport(ERROR,
02586 (errcode(ERRCODE_SYNTAX_ERROR),
02587 errmsg("multiple DEFERRABLE/NOT DEFERRABLE clauses not allowed"),
02588 parser_errposition(cxt->pstate, con->location)));
02589 saw_deferrability = true;
02590 lastprimarycon->deferrable = false;
02591 if (saw_initially &&
02592 lastprimarycon->initdeferred)
02593 ereport(ERROR,
02594 (errcode(ERRCODE_SYNTAX_ERROR),
02595 errmsg("constraint declared INITIALLY DEFERRED must be DEFERRABLE"),
02596 parser_errposition(cxt->pstate, con->location)));
02597 break;
02598
02599 case CONSTR_ATTR_DEFERRED:
02600 if (!SUPPORTS_ATTRS(lastprimarycon))
02601 ereport(ERROR,
02602 (errcode(ERRCODE_SYNTAX_ERROR),
02603 errmsg("misplaced INITIALLY DEFERRED clause"),
02604 parser_errposition(cxt->pstate, con->location)));
02605 if (saw_initially)
02606 ereport(ERROR,
02607 (errcode(ERRCODE_SYNTAX_ERROR),
02608 errmsg("multiple INITIALLY IMMEDIATE/DEFERRED clauses not allowed"),
02609 parser_errposition(cxt->pstate, con->location)));
02610 saw_initially = true;
02611 lastprimarycon->initdeferred = true;
02612
02613
02614
02615
02616 if (!saw_deferrability)
02617 lastprimarycon->deferrable = true;
02618 else if (!lastprimarycon->deferrable)
02619 ereport(ERROR,
02620 (errcode(ERRCODE_SYNTAX_ERROR),
02621 errmsg("constraint declared INITIALLY DEFERRED must be DEFERRABLE"),
02622 parser_errposition(cxt->pstate, con->location)));
02623 break;
02624
02625 case CONSTR_ATTR_IMMEDIATE:
02626 if (!SUPPORTS_ATTRS(lastprimarycon))
02627 ereport(ERROR,
02628 (errcode(ERRCODE_SYNTAX_ERROR),
02629 errmsg("misplaced INITIALLY IMMEDIATE clause"),
02630 parser_errposition(cxt->pstate, con->location)));
02631 if (saw_initially)
02632 ereport(ERROR,
02633 (errcode(ERRCODE_SYNTAX_ERROR),
02634 errmsg("multiple INITIALLY IMMEDIATE/DEFERRED clauses not allowed"),
02635 parser_errposition(cxt->pstate, con->location)));
02636 saw_initially = true;
02637 lastprimarycon->initdeferred = false;
02638 break;
02639
02640 default:
02641
02642 lastprimarycon = con;
02643
02644 saw_deferrability = false;
02645 saw_initially = false;
02646 break;
02647 }
02648 }
02649 }
02650
02651
02652
02653
02654 static void
02655 transformColumnType(CreateStmtContext *cxt, ColumnDef *column)
02656 {
02657
02658
02659
02660
02661 Type ctype = typenameType(cxt->pstate, column->typeName, NULL);
02662
02663 if (column->collClause)
02664 {
02665 Form_pg_type typtup = (Form_pg_type) GETSTRUCT(ctype);
02666
02667 LookupCollation(cxt->pstate,
02668 column->collClause->collname,
02669 column->collClause->location);
02670
02671 if (!OidIsValid(typtup->typcollation))
02672 ereport(ERROR,
02673 (errcode(ERRCODE_DATATYPE_MISMATCH),
02674 errmsg("collations are not supported by type %s",
02675 format_type_be(HeapTupleGetOid(ctype))),
02676 parser_errposition(cxt->pstate,
02677 column->collClause->location)));
02678 }
02679
02680 ReleaseSysCache(ctype);
02681 }
02682
02683
02684
02685
02686
02687
02688
02689
02690
02691
02692
02693
02694
02695
02696
02697
02698
02699
02700
02701
02702
02703
02704
02705
02706
02707 List *
02708 transformCreateSchemaStmt(CreateSchemaStmt *stmt)
02709 {
02710 CreateSchemaStmtContext cxt;
02711 List *result;
02712 ListCell *elements;
02713
02714 cxt.stmtType = "CREATE SCHEMA";
02715 cxt.schemaname = stmt->schemaname;
02716 cxt.authid = stmt->authid;
02717 cxt.sequences = NIL;
02718 cxt.tables = NIL;
02719 cxt.views = NIL;
02720 cxt.indexes = NIL;
02721 cxt.triggers = NIL;
02722 cxt.grants = NIL;
02723
02724
02725
02726
02727
02728 foreach(elements, stmt->schemaElts)
02729 {
02730 Node *element = lfirst(elements);
02731
02732 switch (nodeTag(element))
02733 {
02734 case T_CreateSeqStmt:
02735 {
02736 CreateSeqStmt *elp = (CreateSeqStmt *) element;
02737
02738 setSchemaName(cxt.schemaname, &elp->sequence->schemaname);
02739 cxt.sequences = lappend(cxt.sequences, element);
02740 }
02741 break;
02742
02743 case T_CreateStmt:
02744 {
02745 CreateStmt *elp = (CreateStmt *) element;
02746
02747 setSchemaName(cxt.schemaname, &elp->relation->schemaname);
02748
02749
02750
02751
02752 cxt.tables = lappend(cxt.tables, element);
02753 }
02754 break;
02755
02756 case T_ViewStmt:
02757 {
02758 ViewStmt *elp = (ViewStmt *) element;
02759
02760 setSchemaName(cxt.schemaname, &elp->view->schemaname);
02761
02762
02763
02764
02765 cxt.views = lappend(cxt.views, element);
02766 }
02767 break;
02768
02769 case T_IndexStmt:
02770 {
02771 IndexStmt *elp = (IndexStmt *) element;
02772
02773 setSchemaName(cxt.schemaname, &elp->relation->schemaname);
02774 cxt.indexes = lappend(cxt.indexes, element);
02775 }
02776 break;
02777
02778 case T_CreateTrigStmt:
02779 {
02780 CreateTrigStmt *elp = (CreateTrigStmt *) element;
02781
02782 setSchemaName(cxt.schemaname, &elp->relation->schemaname);
02783 cxt.triggers = lappend(cxt.triggers, element);
02784 }
02785 break;
02786
02787 case T_GrantStmt:
02788 cxt.grants = lappend(cxt.grants, element);
02789 break;
02790
02791 default:
02792 elog(ERROR, "unrecognized node type: %d",
02793 (int) nodeTag(element));
02794 }
02795 }
02796
02797 result = NIL;
02798 result = list_concat(result, cxt.sequences);
02799 result = list_concat(result, cxt.tables);
02800 result = list_concat(result, cxt.views);
02801 result = list_concat(result, cxt.indexes);
02802 result = list_concat(result, cxt.triggers);
02803 result = list_concat(result, cxt.grants);
02804
02805 return result;
02806 }
02807
02808
02809
02810
02811
02812 static void
02813 setSchemaName(char *context_schema, char **stmt_schema_name)
02814 {
02815 if (*stmt_schema_name == NULL)
02816 *stmt_schema_name = context_schema;
02817 else if (strcmp(context_schema, *stmt_schema_name) != 0)
02818 ereport(ERROR,
02819 (errcode(ERRCODE_INVALID_SCHEMA_DEFINITION),
02820 errmsg("CREATE specifies a schema (%s) "
02821 "different from the one being created (%s)",
02822 *stmt_schema_name, context_schema)));
02823 }