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 */