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