omit_opclass_4.0.patch
text/x-patch
Filename: omit_opclass_4.0.patch
Type: text/x-patch
Part: 1
Message:
Re: WIP: Covering + unique indexes.
Patch
Format: unified
| File | + | − |
|---|---|---|
| src/backend/access/index/genam.c | 24 | 14 |
| src/backend/access/nbtree/nbtutils.c | 4 | 4 |
| src/backend/catalog/index.c | 44 | 35 |
| src/backend/commands/indexcmds.c | 99 | 94 |
| src/backend/optimizer/util/plancat.c | 15 | 11 |
| src/backend/utils/adt/ruleutils.c | 2 | 1 |
| src/backend/utils/cache/relcache.c | 23 | 20 |
| src/backend/utils/sort/tuplesort.c | 1 | 1 |
diff --git a/src/backend/access/index/genam.c b/src/backend/access/index/genam.c
index aa5b28c..270ab00 100644
--- a/src/backend/access/index/genam.c
+++ b/src/backend/access/index/genam.c
@@ -175,6 +175,7 @@ BuildIndexValueDescription(Relation indexRelation,
Form_pg_index idxrec;
HeapTuple ht_idx;
int natts = indexRelation->rd_rel->relnatts;
+ int nkeyatts;
int i;
int keyno;
Oid indexrelid = RelationGetRelid(indexRelation);
@@ -244,6 +245,7 @@ BuildIndexValueDescription(Relation indexRelation,
appendStringInfo(&buf, "(%s)=(",
pg_get_indexdef_columns(indexrelid, true));
+ nkeyatts = IndexRelationGetNumberOfKeyAttributes(indexRelation);
for (i = 0; i < natts; i++)
{
char *val;
@@ -254,20 +256,28 @@ BuildIndexValueDescription(Relation indexRelation,
{
Oid foutoid;
bool typisvarlena;
-
- /*
- * The provided data is not necessarily of the type stored in the
- * index; rather it is of the index opclass's input type. So look
- * at rd_opcintype not the index tupdesc.
- *
- * Note: this is a bit shaky for opclasses that have pseudotype
- * input types such as ANYARRAY or RECORD. Currently, the
- * typoutput functions associated with the pseudotypes will work
- * okay, but we might have to try harder in future.
- */
- getTypeOutputInfo(indexRelation->rd_opcintype[i],
- &foutoid, &typisvarlena);
- val = OidOutputFunctionCall(foutoid, values[i]);
+ TupleDesc tupdesc = RelationGetDescr(indexRelation);
+ if (i < nkeyatts)
+ {
+ /*
+ * The provided data is not necessarily of the type stored in the
+ * index; rather it is of the index opclass's input type. So look
+ * at rd_opcintype not the index tupdesc.
+ *
+ * Note: this is a bit shaky for opclasses that have pseudotype
+ * input types such as ANYARRAY or RECORD. Currently, the
+ * typoutput functions associated with the pseudotypes will work
+ * okay, but we might have to try harder in future.
+ */
+ getTypeOutputInfo(indexRelation->rd_opcintype[i],
+ &foutoid, &typisvarlena);
+ val = OidOutputFunctionCall(foutoid, values[i]);
+ }
+ else
+ {
+ getTypeOutputInfo(tupdesc->attrs[i]->atttypid, &foutoid, &typisvarlena);
+ val = OidOutputFunctionCall(foutoid, values[i]);
+ }
}
if (i > 0)
diff --git a/src/backend/access/nbtree/nbtutils.c b/src/backend/access/nbtree/nbtutils.c
index 2192da4..e9997aa 100644
--- a/src/backend/access/nbtree/nbtutils.c
+++ b/src/backend/access/nbtree/nbtutils.c
@@ -121,16 +121,16 @@ ScanKey
_bt_mkscankey_nodata(Relation rel)
{
ScanKey skey;
- int natts;
+ int nkeyatts;
int16 *indoption;
int i;
- natts = RelationGetNumberOfAttributes(rel);
+ nkeyatts = IndexRelationGetNumberOfKeyAttributes(rel);
indoption = rel->rd_indoption;
- skey = (ScanKey) palloc(natts * sizeof(ScanKeyData));
+ skey = (ScanKey) palloc(nkeyatts * sizeof(ScanKeyData));
- for (i = 0; i < natts; i++)
+ for (i = 0; i < nkeyatts; i++)
{
FmgrInfo *procinfo;
int flags;
diff --git a/src/backend/catalog/index.c b/src/backend/catalog/index.c
index d3e980e..eaefe3b 100644
--- a/src/backend/catalog/index.c
+++ b/src/backend/catalog/index.c
@@ -427,38 +427,45 @@ ConstructTupleDescriptor(Relation heapRelation,
namestrcpy(&to->attname, (const char *) lfirst(colnames_item));
colnames_item = lnext(colnames_item);
- /*
- * Check the opclass and index AM to see if either provides a keytype
- * (overriding the attribute type). Opclass takes precedence.
- */
- tuple = SearchSysCache1(CLAOID, ObjectIdGetDatum(classObjectId[i]));
- if (!HeapTupleIsValid(tuple))
- elog(ERROR, "cache lookup failed for opclass %u",
- classObjectId[i]);
- opclassTup = (Form_pg_opclass) GETSTRUCT(tuple);
- if (OidIsValid(opclassTup->opckeytype))
- keyType = opclassTup->opckeytype;
- else
- keyType = amform->amkeytype;
- ReleaseSysCache(tuple);
-
- if (OidIsValid(keyType) && keyType != to->atttypid)
+ if (i < indexInfo->ii_NumIndexKeyAttrs)
{
- /* index value and heap value have different types */
- tuple = SearchSysCache1(TYPEOID, ObjectIdGetDatum(keyType));
+ /*
+ * Check the opclass and index AM to see if either provides a keytype
+ * (overriding the attribute type). Opclass takes precedence.
+ */
+ tuple = SearchSysCache1(CLAOID, ObjectIdGetDatum(classObjectId[i]));
if (!HeapTupleIsValid(tuple))
- elog(ERROR, "cache lookup failed for type %u", keyType);
- typeTup = (Form_pg_type) GETSTRUCT(tuple);
-
- to->atttypid = keyType;
- to->atttypmod = -1;
- to->attlen = typeTup->typlen;
- to->attbyval = typeTup->typbyval;
- to->attalign = typeTup->typalign;
- to->attstorage = typeTup->typstorage;
-
+ elog(ERROR, "cache lookup failed for opclass %u",
+ classObjectId[i]);
+ opclassTup = (Form_pg_opclass) GETSTRUCT(tuple);
+ if (OidIsValid(opclassTup->opckeytype))
+ keyType = opclassTup->opckeytype;
+ else
+ keyType = amform->amkeytype;
ReleaseSysCache(tuple);
+
+ if (OidIsValid(keyType) && keyType != to->atttypid)
+ {
+ /* index value and heap value have different types */
+ tuple = SearchSysCache1(TYPEOID, ObjectIdGetDatum(keyType));
+ if (!HeapTupleIsValid(tuple))
+ elog(ERROR, "cache lookup failed for type %u", keyType);
+ typeTup = (Form_pg_type) GETSTRUCT(tuple);
+
+ to->atttypid = keyType;
+ to->atttypmod = -1;
+ to->attlen = typeTup->typlen;
+ to->attbyval = typeTup->typbyval;
+ to->attalign = typeTup->typalign;
+ to->attstorage = typeTup->typstorage;
+
+ ReleaseSysCache(tuple);
+ }
}
+// else
+// {
+// elog(NOTICE, "ConstructTupleDescriptor. Included opclass attr num %d. Don't check opclass", i);
+// }
}
ReleaseSysCache(amtuple);
@@ -1000,7 +1007,7 @@ index_create(Relation heapRelation,
/* Store dependency on collations */
/* The default collation is pinned, so don't bother recording it */
- for (i = 0; i < indexInfo->ii_NumIndexAttrs; i++)
+ for (i = 0; i < indexInfo->ii_NumIndexKeyAttrs; i++)
{
if (OidIsValid(collationObjectId[i]) &&
collationObjectId[i] != DEFAULT_COLLATION_OID)
@@ -1014,7 +1021,7 @@ index_create(Relation heapRelation,
}
/* Store dependency on operator classes */
- for (i = 0; i < indexInfo->ii_NumIndexAttrs; i++)
+ for (i = 0; i < indexInfo->ii_NumIndexKeyAttrs; i++)
{
referenced.classId = OperatorClassRelationId;
referenced.objectId = classObjectId[i];
@@ -1702,9 +1709,11 @@ BuildIndexInfo(Relation index)
void
BuildSpeculativeIndexInfo(Relation index, IndexInfo *ii)
{
- int ncols = index->rd_rel->relnatts;
+ int nkeycols;
int i;
+ nkeycols = IndexRelationGetNumberOfKeyAttributes(index);
+
/*
* fetch info for checking unique indexes
*/
@@ -1713,16 +1722,16 @@ BuildSpeculativeIndexInfo(Relation index, IndexInfo *ii)
if (index->rd_rel->relam != BTREE_AM_OID)
elog(ERROR, "unexpected non-btree speculative unique index");
- ii->ii_UniqueOps = (Oid *) palloc(sizeof(Oid) * ncols);
- ii->ii_UniqueProcs = (Oid *) palloc(sizeof(Oid) * ncols);
- ii->ii_UniqueStrats = (uint16 *) palloc(sizeof(uint16) * ncols);
+ ii->ii_UniqueOps = (Oid *) palloc(sizeof(Oid) * nkeycols);
+ ii->ii_UniqueProcs = (Oid *) palloc(sizeof(Oid) * nkeycols);
+ ii->ii_UniqueStrats = (uint16 *) palloc(sizeof(uint16) * nkeycols);
/*
* We have to look up the operator's strategy number. This provides a
* cross-check that the operator does match the index.
*/
/* We need the func OIDs and strategy numbers too */
- for (i = 0; i < ncols; i++)
+ for (i = 0; i < nkeycols; i++)
{
ii->ii_UniqueStrats[i] = BTEqualStrategyNumber;
ii->ii_UniqueOps[i] =
diff --git a/src/backend/commands/indexcmds.c b/src/backend/commands/indexcmds.c
index f5ca83a..7ecca3f 100644
--- a/src/backend/commands/indexcmds.c
+++ b/src/backend/commands/indexcmds.c
@@ -988,16 +988,15 @@ ComputeIndexAttrs(IndexInfo *indexInfo,
ListCell *nextExclOp;
ListCell *lc;
int attn;
+ int nkeycols = indexInfo->ii_NumIndexKeyAttrs;
/* Allocate space for exclusion operator info, if needed */
if (exclusionOpNames)
{
- int ncols = list_length(attList);
-
- Assert(list_length(exclusionOpNames) == ncols);
- indexInfo->ii_ExclusionOps = (Oid *) palloc(sizeof(Oid) * ncols);
- indexInfo->ii_ExclusionProcs = (Oid *) palloc(sizeof(Oid) * ncols);
- indexInfo->ii_ExclusionStrats = (uint16 *) palloc(sizeof(uint16) * ncols);
+ Assert(list_length(exclusionOpNames) == nkeycols);
+ indexInfo->ii_ExclusionOps = (Oid *) palloc(sizeof(Oid) * nkeycols);
+ indexInfo->ii_ExclusionProcs = (Oid *) palloc(sizeof(Oid) * nkeycols);
+ indexInfo->ii_ExclusionStrats = (uint16 *) palloc(sizeof(uint16) * nkeycols);
nextExclOp = list_head(exclusionOpNames);
}
else
@@ -1130,110 +1129,116 @@ ComputeIndexAttrs(IndexInfo *indexInfo,
/*
* Identify the opclass to use.
*/
- classOidP[attn] = GetIndexOpClass(attribute->opclass,
- atttype,
- accessMethodName,
- accessMethodId);
-
- /*
- * Identify the exclusion operator, if any.
- */
- if (nextExclOp)
+ if (attn < nkeycols)
{
- List *opname = (List *) lfirst(nextExclOp);
- Oid opid;
- Oid opfamily;
- int strat;
+ classOidP[attn] = GetIndexOpClass(attribute->opclass,
+ atttype,
+ accessMethodName,
+ accessMethodId);
/*
- * Find the operator --- it must accept the column datatype
- * without runtime coercion (but binary compatibility is OK)
+ * Identify the exclusion operator, if any.
*/
- opid = compatible_oper_opid(opname, atttype, atttype, false);
+ if (nextExclOp)
+ {
+ List *opname = (List *) lfirst(nextExclOp);
+ Oid opid;
+ Oid opfamily;
+ int strat;
- /*
- * Only allow commutative operators to be used in exclusion
- * constraints. If X conflicts with Y, but Y does not conflict
- * with X, bad things will happen.
- */
- if (get_commutator(opid) != opid)
- ereport(ERROR,
- (errcode(ERRCODE_WRONG_OBJECT_TYPE),
- errmsg("operator %s is not commutative",
- format_operator(opid)),
- errdetail("Only commutative operators can be used in exclusion constraints.")));
+ /*
+ * Find the operator --- it must accept the column datatype
+ * without runtime coercion (but binary compatibility is OK)
+ */
+ opid = compatible_oper_opid(opname, atttype, atttype, false);
- /*
- * Operator must be a member of the right opfamily, too
- */
- opfamily = get_opclass_family(classOidP[attn]);
- strat = get_op_opfamily_strategy(opid, opfamily);
- if (strat == 0)
- {
- HeapTuple opftuple;
- Form_pg_opfamily opfform;
+ /*
+ * Only allow commutative operators to be used in exclusion
+ * constraints. If X conflicts with Y, but Y does not conflict
+ * with X, bad things will happen.
+ */
+ if (get_commutator(opid) != opid)
+ ereport(ERROR,
+ (errcode(ERRCODE_WRONG_OBJECT_TYPE),
+ errmsg("operator %s is not commutative",
+ format_operator(opid)),
+ errdetail("Only commutative operators can be used in exclusion constraints.")));
/*
- * attribute->opclass might not explicitly name the opfamily,
- * so fetch the name of the selected opfamily for use in the
- * error message.
- */
- opftuple = SearchSysCache1(OPFAMILYOID,
- ObjectIdGetDatum(opfamily));
- if (!HeapTupleIsValid(opftuple))
- elog(ERROR, "cache lookup failed for opfamily %u",
- opfamily);
- opfform = (Form_pg_opfamily) GETSTRUCT(opftuple);
+ * Operator must be a member of the right opfamily, too
+ */
+ opfamily = get_opclass_family(classOidP[attn]);
+ strat = get_op_opfamily_strategy(opid, opfamily);
+ if (strat == 0)
+ {
+ HeapTuple opftuple;
+ Form_pg_opfamily opfform;
+
+ /*
+ * attribute->opclass might not explicitly name the opfamily,
+ * so fetch the name of the selected opfamily for use in the
+ * error message.
+ */
+ opftuple = SearchSysCache1(OPFAMILYOID,
+ ObjectIdGetDatum(opfamily));
+ if (!HeapTupleIsValid(opftuple))
+ elog(ERROR, "cache lookup failed for opfamily %u",
+ opfamily);
+ opfform = (Form_pg_opfamily) GETSTRUCT(opftuple);
- ereport(ERROR,
- (errcode(ERRCODE_WRONG_OBJECT_TYPE),
- errmsg("operator %s is not a member of operator family \"%s\"",
- format_operator(opid),
- NameStr(opfform->opfname)),
- errdetail("The exclusion operator must be related to the index operator class for the constraint.")));
- }
+ ereport(ERROR,
+ (errcode(ERRCODE_WRONG_OBJECT_TYPE),
+ errmsg("operator %s is not a member of operator family \"%s\"",
+ format_operator(opid),
+ NameStr(opfform->opfname)),
+ errdetail("The exclusion operator must be related to the index operator class for the constraint.")));
+ }
- indexInfo->ii_ExclusionOps[attn] = opid;
- indexInfo->ii_ExclusionProcs[attn] = get_opcode(opid);
- indexInfo->ii_ExclusionStrats[attn] = strat;
- nextExclOp = lnext(nextExclOp);
- }
+ indexInfo->ii_ExclusionOps[attn] = opid;
+ indexInfo->ii_ExclusionProcs[attn] = get_opcode(opid);
+ indexInfo->ii_ExclusionStrats[attn] = strat;
+ nextExclOp = lnext(nextExclOp);
+ }
- /*
- * Set up the per-column options (indoption field). For now, this is
- * zero for any un-ordered index, while ordered indexes have DESC and
- * NULLS FIRST/LAST options.
- */
- colOptionP[attn] = 0;
- if (amcanorder)
- {
- /* default ordering is ASC */
- if (attribute->ordering == SORTBY_DESC)
- colOptionP[attn] |= INDOPTION_DESC;
- /* default null ordering is LAST for ASC, FIRST for DESC */
- if (attribute->nulls_ordering == SORTBY_NULLS_DEFAULT)
+ /*
+ * Set up the per-column options (indoption field). For now, this is
+ * zero for any un-ordered index, while ordered indexes have DESC and
+ * NULLS FIRST/LAST options.
+ */
+ colOptionP[attn] = 0;
+ if (amcanorder)
{
+ /* default ordering is ASC */
if (attribute->ordering == SORTBY_DESC)
+ colOptionP[attn] |= INDOPTION_DESC;
+ /* default null ordering is LAST for ASC, FIRST for DESC */
+ if (attribute->nulls_ordering == SORTBY_NULLS_DEFAULT)
+ {
+ if (attribute->ordering == SORTBY_DESC)
+ colOptionP[attn] |= INDOPTION_NULLS_FIRST;
+ }
+ else if (attribute->nulls_ordering == SORTBY_NULLS_FIRST)
colOptionP[attn] |= INDOPTION_NULLS_FIRST;
}
- else if (attribute->nulls_ordering == SORTBY_NULLS_FIRST)
- colOptionP[attn] |= INDOPTION_NULLS_FIRST;
- }
- else
- {
- /* index AM does not support ordering */
- if (attribute->ordering != SORTBY_DEFAULT)
- ereport(ERROR,
- (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
- errmsg("access method \"%s\" does not support ASC/DESC options",
- accessMethodName)));
- if (attribute->nulls_ordering != SORTBY_NULLS_DEFAULT)
- ereport(ERROR,
- (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
- errmsg("access method \"%s\" does not support NULLS FIRST/LAST options",
- accessMethodName)));
+ else
+ {
+ /* index AM does not support ordering */
+ if (attribute->ordering != SORTBY_DEFAULT)
+ ereport(ERROR,
+ (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
+ errmsg("access method \"%s\" does not support ASC/DESC options",
+ accessMethodName)));
+ if (attribute->nulls_ordering != SORTBY_NULLS_DEFAULT)
+ ereport(ERROR,
+ (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
+ errmsg("access method \"%s\" does not support NULLS FIRST/LAST options",
+ accessMethodName)));
+ }
}
-
+// else
+// {
+// elog(NOTICE, "ComputeIndexAttrs. Included attn %d, nkeycols %d ncols %d Don't look for opclass", attn, nkeycols, indexInfo->ii_NumIndexAttrs);
+// }
attn++;
}
}
diff --git a/src/backend/optimizer/util/plancat.c b/src/backend/optimizer/util/plancat.c
index 603d11d..b7c2429 100644
--- a/src/backend/optimizer/util/plancat.c
+++ b/src/backend/optimizer/util/plancat.c
@@ -225,18 +225,22 @@ get_relation_info(PlannerInfo *root, Oid relationObjectId, bool inhparent,
* each indexed column must have an opclass.
*/
info->indexkeys = (int *) palloc(sizeof(int) * ncolumns);
- info->indexcollations = (Oid *) palloc(sizeof(Oid) * ncolumns);
- info->opfamily = (Oid *) palloc(sizeof(Oid) * ncolumns);
- info->opcintype = (Oid *) palloc(sizeof(Oid) * ncolumns);
+ info->indexcollations = (Oid *) palloc(sizeof(Oid) * nkeycolumns);
+ info->opfamily = (Oid *) palloc(sizeof(Oid) * nkeycolumns);
+ info->opcintype = (Oid *) palloc(sizeof(Oid) * nkeycolumns);
info->canreturn = (bool *) palloc(sizeof(bool) * ncolumns);
for (i = 0; i < ncolumns; i++)
{
info->indexkeys[i] = index->indkey.values[i];
+ info->canreturn[i] = index_can_return(indexRelation, i + 1);
+ }
+
+ for (i = 0; i < nkeycolumns; i++)
+ {
info->indexcollations[i] = indexRelation->rd_indcollation[i];
info->opfamily[i] = indexRelation->rd_opfamily[i];
info->opcintype[i] = indexRelation->rd_opcintype[i];
- info->canreturn[i] = index_can_return(indexRelation, i + 1);
}
info->relam = indexRelation->rd_rel->relam;
@@ -260,10 +264,10 @@ get_relation_info(PlannerInfo *root, Oid relationObjectId, bool inhparent,
Assert(indexRelation->rd_am->amcanorder);
info->sortopfamily = info->opfamily;
- info->reverse_sort = (bool *) palloc(sizeof(bool) * ncolumns);
- info->nulls_first = (bool *) palloc(sizeof(bool) * ncolumns);
+ info->reverse_sort = (bool *) palloc(sizeof(bool) * nkeycolumns);
+ info->nulls_first = (bool *) palloc(sizeof(bool) * nkeycolumns);
- for (i = 0; i < ncolumns; i++)
+ for (i = 0; i < nkeycolumns; i++)
{
int16 opt = indexRelation->rd_indoption[i];
@@ -287,11 +291,11 @@ get_relation_info(PlannerInfo *root, Oid relationObjectId, bool inhparent,
* of current or foreseeable amcanorder index types, it's not
* worth expending more effort on now.
*/
- info->sortopfamily = (Oid *) palloc(sizeof(Oid) * ncolumns);
- info->reverse_sort = (bool *) palloc(sizeof(bool) * ncolumns);
- info->nulls_first = (bool *) palloc(sizeof(bool) * ncolumns);
+ info->sortopfamily = (Oid *) palloc(sizeof(Oid) * nkeycolumns);
+ info->reverse_sort = (bool *) palloc(sizeof(bool) * nkeycolumns);
+ info->nulls_first = (bool *) palloc(sizeof(bool) * nkeycolumns);
- for (i = 0; i < ncolumns; i++)
+ for (i = 0; i < nkeycolumns; i++)
{
int16 opt = indexRelation->rd_indoption[i];
Oid ltopr;
diff --git a/src/backend/utils/adt/ruleutils.c b/src/backend/utils/adt/ruleutils.c
index 8a7b0f1..05221d9 100644
--- a/src/backend/utils/adt/ruleutils.c
+++ b/src/backend/utils/adt/ruleutils.c
@@ -1194,7 +1194,8 @@ pg_get_indexdef_worker(Oid indexrelid, int colno,
keycolcollation = exprCollation(indexkey);
}
- if (!attrsOnly && (!colno || colno == keyno + 1))
+ if (!attrsOnly && (!colno || colno == keyno + 1)
+ && keyno < idxrec->indnkeyatts)
{
Oid indcoll;
diff --git a/src/backend/utils/cache/relcache.c b/src/backend/utils/cache/relcache.c
index 8851f40..003fa0c 100644
--- a/src/backend/utils/cache/relcache.c
+++ b/src/backend/utils/cache/relcache.c
@@ -1176,7 +1176,7 @@ RelationInitIndexAccessInfo(Relation relation)
int2vector *indoption;
MemoryContext indexcxt;
MemoryContext oldcontext;
- int natts;
+ int natts, nkeyatts;
uint16 amsupport;
/*
@@ -1212,6 +1212,7 @@ RelationInitIndexAccessInfo(Relation relation)
elog(ERROR, "relnatts disagrees with indnatts for index %u",
RelationGetRelid(relation));
amsupport = aform->amsupport;
+ nkeyatts = IndexRelationGetNumberOfKeyAttributes(relation);
/*
* Make the private context to hold index access info. The reason we need
@@ -1235,9 +1236,9 @@ RelationInitIndexAccessInfo(Relation relation)
MemoryContextAllocZero(indexcxt, sizeof(RelationAmInfo));
relation->rd_opfamily = (Oid *)
- MemoryContextAllocZero(indexcxt, natts * sizeof(Oid));
+ MemoryContextAllocZero(indexcxt, nkeyatts * sizeof(Oid));
relation->rd_opcintype = (Oid *)
- MemoryContextAllocZero(indexcxt, natts * sizeof(Oid));
+ MemoryContextAllocZero(indexcxt, nkeyatts * sizeof(Oid));
if (amsupport > 0)
{
@@ -1292,7 +1293,7 @@ RelationInitIndexAccessInfo(Relation relation)
*/
IndexSupportInitialize(indclass, relation->rd_support,
relation->rd_opfamily, relation->rd_opcintype,
- amsupport, natts);
+ amsupport, nkeyatts);
/*
* Similarly extract indoption and copy it to the cache entry
@@ -4364,7 +4365,7 @@ RelationGetExclusionInfo(Relation indexRelation,
Oid **procs,
uint16 **strategies)
{
- int ncols = indexRelation->rd_rel->relnatts;
+ int nkeycols;
Oid *ops;
Oid *funcs;
uint16 *strats;
@@ -4376,17 +4377,19 @@ RelationGetExclusionInfo(Relation indexRelation,
MemoryContext oldcxt;
int i;
+ nkeycols = IndexRelationGetNumberOfKeyAttributes(indexRelation);
+
/* Allocate result space in caller context */
- *operators = ops = (Oid *) palloc(sizeof(Oid) * ncols);
- *procs = funcs = (Oid *) palloc(sizeof(Oid) * ncols);
- *strategies = strats = (uint16 *) palloc(sizeof(uint16) * ncols);
+ *operators = ops = (Oid *) palloc(sizeof(Oid) * nkeycols);
+ *procs = funcs = (Oid *) palloc(sizeof(Oid) * nkeycols);
+ *strategies = strats = (uint16 *) palloc(sizeof(uint16) * nkeycols);
/* Quick exit if we have the data cached already */
if (indexRelation->rd_exclstrats != NULL)
{
- memcpy(ops, indexRelation->rd_exclops, sizeof(Oid) * ncols);
- memcpy(funcs, indexRelation->rd_exclprocs, sizeof(Oid) * ncols);
- memcpy(strats, indexRelation->rd_exclstrats, sizeof(uint16) * ncols);
+ memcpy(ops, indexRelation->rd_exclops, sizeof(Oid) * nkeycols);
+ memcpy(funcs, indexRelation->rd_exclprocs, sizeof(Oid) * nkeycols);
+ memcpy(strats, indexRelation->rd_exclstrats, sizeof(uint16) * nkeycols);
return;
}
@@ -4435,12 +4438,12 @@ RelationGetExclusionInfo(Relation indexRelation,
arr = DatumGetArrayTypeP(val); /* ensure not toasted */
nelem = ARR_DIMS(arr)[0];
if (ARR_NDIM(arr) != 1 ||
- nelem != ncols ||
+ nelem != nkeycols ||
ARR_HASNULL(arr) ||
ARR_ELEMTYPE(arr) != OIDOID)
elog(ERROR, "conexclop is not a 1-D Oid array");
- memcpy(ops, ARR_DATA_PTR(arr), sizeof(Oid) * ncols);
+ memcpy(ops, ARR_DATA_PTR(arr), sizeof(Oid) * nkeycols);
}
systable_endscan(conscan);
@@ -4451,7 +4454,7 @@ RelationGetExclusionInfo(Relation indexRelation,
RelationGetRelationName(indexRelation));
/* We need the func OIDs and strategy numbers too */
- for (i = 0; i < ncols; i++)
+ for (i = 0; i < nkeycols; i++)
{
funcs[i] = get_opcode(ops[i]);
strats[i] = get_op_opfamily_strategy(ops[i],
@@ -4464,12 +4467,12 @@ RelationGetExclusionInfo(Relation indexRelation,
/* Save a copy of the results in the relcache entry. */
oldcxt = MemoryContextSwitchTo(indexRelation->rd_indexcxt);
- indexRelation->rd_exclops = (Oid *) palloc(sizeof(Oid) * ncols);
- indexRelation->rd_exclprocs = (Oid *) palloc(sizeof(Oid) * ncols);
- indexRelation->rd_exclstrats = (uint16 *) palloc(sizeof(uint16) * ncols);
- memcpy(indexRelation->rd_exclops, ops, sizeof(Oid) * ncols);
- memcpy(indexRelation->rd_exclprocs, funcs, sizeof(Oid) * ncols);
- memcpy(indexRelation->rd_exclstrats, strats, sizeof(uint16) * ncols);
+ indexRelation->rd_exclops = (Oid *) palloc(sizeof(Oid) * nkeycols);
+ indexRelation->rd_exclprocs = (Oid *) palloc(sizeof(Oid) * nkeycols);
+ indexRelation->rd_exclstrats = (uint16 *) palloc(sizeof(uint16) * nkeycols);
+ memcpy(indexRelation->rd_exclops, ops, sizeof(Oid) * nkeycols);
+ memcpy(indexRelation->rd_exclprocs, funcs, sizeof(Oid) * nkeycols);
+ memcpy(indexRelation->rd_exclstrats, strats, sizeof(uint16) * nkeycols);
MemoryContextSwitchTo(oldcxt);
}
diff --git a/src/backend/utils/sort/tuplesort.c b/src/backend/utils/sort/tuplesort.c
index cf1cdcb..78ab531 100644
--- a/src/backend/utils/sort/tuplesort.c
+++ b/src/backend/utils/sort/tuplesort.c
@@ -812,7 +812,7 @@ tuplesort_begin_index_btree(Relation heapRel,
state->enforceUnique = enforceUnique;
indexScanKey = _bt_mkscankey_nodata(indexRel);
- state->nKeys = RelationGetNumberOfAttributes(indexRel);
+ state->nKeys = IndexRelationGetNumberOfKeyAttributes(indexRel);
/* Prepare SortSupport data for each column */
state->sortKeys = (SortSupport) palloc0(state->nKeys *