diff --git a/doc/src/sgml/catalogs.sgml b/doc/src/sgml/catalogs.sgml index 192891bc4f..71e20f2740 100644 --- a/doc/src/sgml/catalogs.sgml +++ b/doc/src/sgml/catalogs.sgml @@ -3005,14 +3005,15 @@ SCRAM-SHA-256$<iteration count>:&l will be disallowed outright (we'll tell the user to issue a DROP against the referenced object, instead). While a regular internal dependency will prevent - the dependent object from being dropped while any such dependencies remain, - DEPENDENCY_INTERNAL_AUTO will allow such a drop as long - as the object can be found by following any of such dependencies. - Example: an index - on a partition is made internal-auto-dependent on both the partition - itself as well as on the index on the parent partitioned table; - so the partition index is dropped together with either partition it indexes, - or with the parent index it is attached to. + the dependent object from being dropped while any such dependencies + remain, DEPENDENCY_INTERNAL_AUTO will allow such + a drop as long as the object can be found by following any of such + dependencies. + Example: an index on a partition is made internal-auto-dependent on + both the partition itself as well as on the index on the parent + partitioned table; so the partition index is dropped together with + either the partition it indexes, or with the parent index it is + attached to. diff --git a/src/backend/catalog/dependency.c b/src/backend/catalog/dependency.c index a46e859488..be60270ea5 100644 --- a/src/backend/catalog/dependency.c +++ b/src/backend/catalog/dependency.c @@ -637,14 +637,16 @@ findDependentObjects(const ObjectAddress *object, * For INTERNAL_AUTO dependencies, we don't enforce this; * in other words, we don't follow the links back to the * owning object. - * + */ + if (foundDep->deptype == DEPENDENCY_INTERNAL_AUTO) + break; + + /* * First, release caller's lock on this object and get * deletion lock on the owning object. (We must release * caller's lock to avoid deadlock against a concurrent * deletion of the owning object.) */ - if (foundDep->deptype == DEPENDENCY_INTERNAL_AUTO) - break; ReleaseDeletionLock(object); AcquireDeletionLock(&otherObject, 0); diff --git a/src/backend/catalog/index.c b/src/backend/catalog/index.c index 6c4649c594..4e10026297 100644 --- a/src/backend/catalog/index.c +++ b/src/backend/catalog/index.c @@ -42,6 +42,7 @@ #include "catalog/pg_constraint.h" #include "catalog/pg_constraint_fn.h" #include "catalog/pg_depend.h" +#include "catalog/pg_inherits_fn.h" #include "catalog/pg_operator.h" #include "catalog/pg_opclass.h" #include "catalog/pg_tablespace.h" @@ -56,6 +57,7 @@ #include "nodes/nodeFuncs.h" #include "optimizer/clauses.h" #include "parser/parser.h" +#include "rewrite/rewriteManip.h" #include "storage/bufmgr.h" #include "storage/lmgr.h" #include "storage/predicate.h" @@ -869,9 +871,9 @@ index_create(Relation heapRelation, } /* - * create the index relation's relcache entry and physical disk file. (If - * we fail further down, it's the smgr's responsibility to remove the disk - * file again.) + * create the index relation's relcache entry and, if necessary, the + * physical disk file. (If we fail further down, it's the smgr's + * responsibility to remove the disk file again, if any.) */ indexRelation = heap_create(indexRelationName, namespaceId, @@ -1044,7 +1046,6 @@ index_create(Relation heapRelation, recordDependencyOn(&myself, &referenced, DEPENDENCY_INTERNAL_AUTO); } - /* Store dependency on collations */ /* The default collation is pinned, so don't bother recording it */ for (i = 0; i < indexInfo->ii_NumIndexAttrs; i++) @@ -1745,7 +1746,7 @@ BuildIndexInfo(Relation index) * attmap is an attribute map where info2 is input and info1 is output. */ bool -CompareIndexInfo(IndexInfo *info1, IndexInfo *info2, AttrNumber *attmap) +CompareIndexInfo(IndexInfo *info1, IndexInfo *info2, AttrNumber *attmap, int maplen) { int i; @@ -1759,7 +1760,9 @@ CompareIndexInfo(IndexInfo *info1, IndexInfo *info2, AttrNumber *attmap) /* * and columns match through the attribute map (actual attribute numbers - * might differ!) + * might differ!) Note that this implies that index columns that are + * expressions appear in the same positions. We will next compare the + * expressions themselves. */ for (i = 0; i < info1->ii_NumIndexAttrs; i++) { @@ -1769,11 +1772,24 @@ CompareIndexInfo(IndexInfo *info1, IndexInfo *info2, AttrNumber *attmap) } /* - * Expression indexes are currently not considered equal. Not needed for - * current callers. + * For expression indexes: either both are expression indexes, or neither + * is; if they are, make sure the expressions match. */ - if (info1->ii_Expressions != NIL || info2->ii_Expressions != NIL) + if ((info1->ii_Expressions != NIL) != (info2->ii_Expressions != NIL)) return false; + else + { + bool found_whole_row; + Node *mapped; + + mapped = map_variable_attnos((Node *) info2->ii_Expressions, + 1, 0, attmap, maplen, + InvalidOid, &found_whole_row); + if (found_whole_row) + elog(ERROR, "having fun with whole-row expressions, are we?"); + + return equal(info1->ii_Expressions, mapped); + } /* Index predicates must be identical */ if (!equal(info1->ii_Predicate, info2->ii_Predicate)) diff --git a/src/backend/catalog/pg_inherits.c b/src/backend/catalog/pg_inherits.c index bde5176cab..973e8d5835 100644 --- a/src/backend/catalog/pg_inherits.c +++ b/src/backend/catalog/pg_inherits.c @@ -410,7 +410,7 @@ typeInheritsFrom(Oid subclassTypeId, Oid superclassTypeId) * Create a single pg_inherits row with the given data */ void -StoreSingleInheritance(Oid relationId, Oid parentOid, int16 seqNumber) +StoreSingleInheritance(Oid relationId, Oid parentOid, int32 seqNumber) { Datum values[Natts_pg_inherits]; bool nulls[Natts_pg_inherits]; @@ -424,7 +424,7 @@ StoreSingleInheritance(Oid relationId, Oid parentOid, int16 seqNumber) */ values[Anum_pg_inherits_inhrelid - 1] = ObjectIdGetDatum(relationId); values[Anum_pg_inherits_inhparent - 1] = ObjectIdGetDatum(parentOid); - values[Anum_pg_inherits_inhseqno - 1] = Int16GetDatum(seqNumber); + values[Anum_pg_inherits_inhseqno - 1] = Int32GetDatum(seqNumber); memset(nulls, 0, sizeof(nulls)); diff --git a/src/backend/commands/indexcmds.c b/src/backend/commands/indexcmds.c index 9b7f29c7fc..1a921f70a2 100644 --- a/src/backend/commands/indexcmds.c +++ b/src/backend/commands/indexcmds.c @@ -816,7 +816,7 @@ DefineIndex(Oid relationId, parentDesc, gettext_noop("could not convert row type")); - if (CompareIndexInfo(cldIdxInfo, indexInfo, attmap)) + if (CompareIndexInfo(cldIdxInfo, indexInfo, attmap, parentDesc->natts)) { /* * Found a match. Attach index to parent and we're diff --git a/src/backend/commands/tablecmds.c b/src/backend/commands/tablecmds.c index a9a1d7fdd7..649a644158 100644 --- a/src/backend/commands/tablecmds.c +++ b/src/backend/commands/tablecmds.c @@ -4206,9 +4206,13 @@ ATRewriteTables(AlterTableStmt *parsetree, List **wqueue, LOCKMODE lockmode) { AlteredTableInfo *tab = (AlteredTableInfo *) lfirst(ltab); - /* Foreign tables have no storage, nor do partitioned tables. */ + /* + * Foreign tables have no storage, nor do partitioned tables and + * indexes. + */ if (tab->relkind == RELKIND_FOREIGN_TABLE || - tab->relkind == RELKIND_PARTITIONED_TABLE) + tab->relkind == RELKIND_PARTITIONED_TABLE || + tab->relkind == RELKIND_PARTITIONED_INDEX) continue; /* @@ -14084,7 +14088,8 @@ ATExecAttachPartition(List **wqueue, Relation rel, PartitionCmd *cmd) if (has_superclass(RelationGetRelid(attachrelIdxRels[i]))) continue; - if (CompareIndexInfo(info, attachInfos[i], attmap)) + if (CompareIndexInfo(info, attachInfos[i], attmap, + RelationGetDescr(rel)->natts)) { /* bingo. */ IndexSetParentIndex(attachrelIdxRels[i], idx); @@ -14121,6 +14126,8 @@ ATExecAttachPartition(List **wqueue, Relation rel, PartitionCmd *cmd) pfree(idxes); if (attachRelIdxs) pfree(attachRelIdxs); + if (attachInfos) + pfree(attachInfos); } /* @@ -14283,8 +14290,7 @@ ATExecDetachPartition(Relation rel, RangeVar *name) if (!has_superclass(idxid)) continue; - Assert(!has_superclass(idxid) || - (IndexGetRelation(get_partition_parent(idxid), false) == + Assert((IndexGetRelation(get_partition_parent(idxid), false) == RelationGetRelid(rel))); idx = index_open(idxid, AccessExclusiveLock); @@ -14402,16 +14408,16 @@ ATExecAttachPartitionIdx(List **wqueue, Relation parentIdx, RangeVar *name) (errcode(ERRCODE_UNDEFINED_OBJECT), errmsg("index \"%s\" does not exist", name->relname))); - /* no deadlock risk: our callback above already acquired the lock */ + /* no deadlock risk: RangeVarGetRelidExtended already acquired the lock */ partIdx = relation_open(partIdxId, AccessExclusiveLock); - /* we already hold lock on both tables, so this is safe: */ + /* we already hold locks on both tables, so this is safe: */ parentTbl = relation_open(parentIdx->rd_index->indrelid, AccessShareLock); partTbl = relation_open(partIdx->rd_index->indrelid, NoLock); ObjectAddressSet(address, RelationRelationId, RelationGetRelid(partIdx)); - /* Silently do nothing if already the right state */ + /* Silently do nothing if already in the right state */ currParent = !has_superclass(partIdxId) ? InvalidOid : get_partition_parent(partIdxId); if (currParent != RelationGetRelid(parentIdx)) @@ -14463,7 +14469,8 @@ ATExecAttachPartitionIdx(List **wqueue, Relation parentIdx, RangeVar *name) attmap = convert_tuples_by_name_map(RelationGetDescr(parentTbl), RelationGetDescr(partTbl), gettext_noop("could not convert row type")); - if (!CompareIndexInfo(parentInfo, childInfo, attmap)) + if (!CompareIndexInfo(parentInfo, childInfo, attmap, + RelationGetDescr(partTbl)->natts)) ereport(ERROR, (errcode(ERRCODE_INVALID_OBJECT_DEFINITION), errmsg("cannot attach index \"%s\" as a partition of index \"%s\"", diff --git a/src/backend/parser/gram.y b/src/backend/parser/gram.y index 04ef741a4c..5bf8dc2e56 100644 --- a/src/backend/parser/gram.y +++ b/src/backend/parser/gram.y @@ -7390,6 +7390,7 @@ IndexStmt: CREATE opt_unique INDEX opt_concurrently opt_index_name n->concurrent = $4; n->idxname = $8; n->relation = $10; + n->relationId = InvalidOid; n->accessMethod = $11; n->indexParams = $13; n->options = $15; diff --git a/src/backend/tcop/utility.c b/src/backend/tcop/utility.c index 16c4f8fad4..1a29dda783 100644 --- a/src/backend/tcop/utility.c +++ b/src/backend/tcop/utility.c @@ -1353,8 +1353,7 @@ ProcessUtilitySlow(ParseState *pstate, commandCollected = true; EventTriggerAlterTableEnd(); - if (inheritors) - list_free(inheritors); + list_free(inheritors); } break; diff --git a/src/backend/utils/cache/relcache.c b/src/backend/utils/cache/relcache.c index a28046f857..2e4e968a90 100644 --- a/src/backend/utils/cache/relcache.c +++ b/src/backend/utils/cache/relcache.c @@ -430,20 +430,26 @@ static void RelationParseRelOptions(Relation relation, HeapTuple tuple) { bytea *options; - bool isindex; + amoptions_function amoptsfn; relation->rd_options = NULL; - /* Fall out if relkind should not have options */ + /* + * Look up any AM-specific parse function; fall out if relkind should not + * have options. + */ switch (relation->rd_rel->relkind) { case RELKIND_RELATION: case RELKIND_TOASTVALUE: - case RELKIND_INDEX: - case RELKIND_PARTITIONED_INDEX: case RELKIND_VIEW: case RELKIND_MATVIEW: case RELKIND_PARTITIONED_TABLE: + amoptsfn = NULL; + break; + case RELKIND_INDEX: + case RELKIND_PARTITIONED_INDEX: + amoptsfn = relation->rd_amroutine->amoptions; break; default: return; @@ -454,12 +460,7 @@ RelationParseRelOptions(Relation relation, HeapTuple tuple) * we might not have any other for pg_class yet (consider executing this * code for pg_class itself) */ - isindex = relation->rd_rel->relkind == RELKIND_INDEX || - relation->rd_rel->relkind == RELKIND_PARTITIONED_INDEX; - options = extractRelOptions(tuple, - GetPgClassDescriptor(), - isindex ? relation->rd_amroutine->amoptions : - NULL); + options = extractRelOptions(tuple, GetPgClassDescriptor(), amoptions); /* * Copy parsed data into CacheMemoryContext. To guard against the diff --git a/src/include/catalog/catversion.h b/src/include/catalog/catversion.h index 2b2c166266..f1765af4ba 100644 --- a/src/include/catalog/catversion.h +++ b/src/include/catalog/catversion.h @@ -53,6 +53,6 @@ */ /* yyyymmddN */ -#define CATALOG_VERSION_NO 201712291 +#define CATALOG_VERSION_NO 201712251 #endif diff --git a/src/include/catalog/dependency.h b/src/include/catalog/dependency.h index 67d8a20be3..46c271a46c 100644 --- a/src/include/catalog/dependency.h +++ b/src/include/catalog/dependency.h @@ -60,7 +60,7 @@ * Example: an index on a partition is made internal-auto-dependent on * both the partition itself as well as on the index on the parent * partitioned table; so the partition index is dropped together with - * either partition it indexes, or with the parent index it is attached + * either the partition it indexes, or with the parent index it is attached * to. * DEPENDENCY_EXTENSION ('e'): the dependent object is a member of the diff --git a/src/include/catalog/index.h b/src/include/catalog/index.h index 139365c3b3..8ff3a0732e 100644 --- a/src/include/catalog/index.h +++ b/src/include/catalog/index.h @@ -87,7 +87,8 @@ extern void index_drop(Oid indexId, bool concurrent); extern IndexInfo *BuildIndexInfo(Relation index); -extern bool CompareIndexInfo(IndexInfo *info1, IndexInfo *info2, AttrNumber *attmap); +extern bool CompareIndexInfo(IndexInfo *info1, IndexInfo *info2, + AttrNumber *attmap, int maplen); extern void BuildSpeculativeIndexInfo(Relation index, IndexInfo *ii); diff --git a/src/include/catalog/pg_inherits_fn.h b/src/include/catalog/pg_inherits_fn.h index b587f2d042..d0abde4168 100644 --- a/src/include/catalog/pg_inherits_fn.h +++ b/src/include/catalog/pg_inherits_fn.h @@ -24,6 +24,6 @@ extern bool has_subclass(Oid relationId); extern bool has_superclass(Oid relationId); extern bool typeInheritsFrom(Oid subclassTypeId, Oid superclassTypeId); extern void StoreSingleInheritance(Oid relationId, Oid parentOid, - int16 seqNumber); + int32 seqNumber); #endif /* PG_INHERITS_FN_H */