aboutsummaryrefslogtreecommitdiff
path: root/src/backend/utils
diff options
context:
space:
mode:
Diffstat (limited to 'src/backend/utils')
-rw-r--r--src/backend/utils/adt/ruleutils.c31
-rw-r--r--src/backend/utils/adt/selfuncs.c4
-rw-r--r--src/backend/utils/cache/relcache.c87
-rw-r--r--src/backend/utils/sort/tuplesort.c5
4 files changed, 85 insertions, 42 deletions
diff --git a/src/backend/utils/adt/ruleutils.c b/src/backend/utils/adt/ruleutils.c
index f8fc7f83f9b..b75a224ee8c 100644
--- a/src/backend/utils/adt/ruleutils.c
+++ b/src/backend/utils/adt/ruleutils.c
@@ -1296,6 +1296,21 @@ pg_get_indexdef_worker(Oid indexrelid, int colno,
Oid keycoltype;
Oid keycolcollation;
+ /*
+ * attrsOnly flag is used for building unique-constraint and
+ * exclusion-constraint error messages. Included attrs are meaningless
+ * there, so do not include them in the message.
+ */
+ if (attrsOnly && keyno >= idxrec->indnkeyatts)
+ break;
+
+ /* Report the INCLUDED attributes, if any. */
+ if ((!attrsOnly) && keyno == idxrec->indnkeyatts)
+ {
+ appendStringInfoString(&buf, ") INCLUDE (");
+ sep = "";
+ }
+
if (!colno)
appendStringInfoString(&buf, sep);
sep = ", ";
@@ -1347,6 +1362,9 @@ pg_get_indexdef_worker(Oid indexrelid, int colno,
appendStringInfo(&buf, " COLLATE %s",
generate_collation_name((indcoll)));
+ if (keyno >= idxrec->indnkeyatts)
+ continue;
+
/* Add the operator class name, if not default */
get_opclass_name(indclass->values[keyno], keycoltype, &buf);
@@ -2047,6 +2065,19 @@ pg_get_constraintdef_worker(Oid constraintId, bool fullCommand,
appendStringInfoChar(&buf, ')');
+ /* Fetch and build including column list */
+ isnull = true;
+ val = SysCacheGetAttr(CONSTROID, tup,
+ Anum_pg_constraint_conincluding, &isnull);
+ if (!isnull)
+ {
+ appendStringInfoString(&buf, " INCLUDE (");
+
+ decompile_column_index_array(val, conForm->conrelid, &buf);
+
+ appendStringInfoChar(&buf, ')');
+ }
+
indexId = get_constraint_index(constraintId);
/* XXX why do we only print these bits if fullCommand? */
diff --git a/src/backend/utils/adt/selfuncs.c b/src/backend/utils/adt/selfuncs.c
index f998d859c1c..fe606d72798 100644
--- a/src/backend/utils/adt/selfuncs.c
+++ b/src/backend/utils/adt/selfuncs.c
@@ -4902,7 +4902,7 @@ examine_variable(PlannerInfo *root, Node *node, int varRelid,
* should match has_unique_index().
*/
if (index->unique &&
- index->ncolumns == 1 &&
+ index->nkeycolumns == 1 &&
(index->indpred == NIL || index->predOK))
vardata->isunique = true;
@@ -7053,7 +7053,7 @@ btcostestimate(PlannerInfo *root, IndexPath *path, double loop_count,
* NullTest invalidates that theory, even though it sets eqQualHere.
*/
if (index->unique &&
- indexcol == index->ncolumns - 1 &&
+ indexcol == index->nkeycolumns - 1 &&
eqQualHere &&
!found_saop &&
!found_is_null_op)
diff --git a/src/backend/utils/cache/relcache.c b/src/backend/utils/cache/relcache.c
index 40a2c1df049..e81c4691ec2 100644
--- a/src/backend/utils/cache/relcache.c
+++ b/src/backend/utils/cache/relcache.c
@@ -538,7 +538,7 @@ RelationBuildTupleDesc(Relation relation)
/*
* add attribute data to relation->rd_att
*/
- need = relation->rd_rel->relnatts;
+ need = RelationGetNumberOfAttributes(relation);
while (HeapTupleIsValid(pg_attribute_tuple = systable_getnext(pg_attribute_scan)))
{
@@ -548,7 +548,7 @@ RelationBuildTupleDesc(Relation relation)
attp = (Form_pg_attribute) GETSTRUCT(pg_attribute_tuple);
attnum = attp->attnum;
- if (attnum <= 0 || attnum > relation->rd_rel->relnatts)
+ if (attnum <= 0 || attnum > RelationGetNumberOfAttributes(relation))
elog(ERROR, "invalid attribute number %d for %s",
attp->attnum, RelationGetRelationName(relation));
@@ -567,7 +567,7 @@ RelationBuildTupleDesc(Relation relation)
if (attrdef == NULL)
attrdef = (AttrDefault *)
MemoryContextAllocZero(CacheMemoryContext,
- relation->rd_rel->relnatts *
+ RelationGetNumberOfAttributes(relation) *
sizeof(AttrDefault));
attrdef[ndef].adnum = attnum;
attrdef[ndef].adbin = NULL;
@@ -650,7 +650,7 @@ RelationBuildTupleDesc(Relation relation)
{
int i;
- for (i = 0; i < relation->rd_rel->relnatts; i++)
+ for (i = 0; i < RelationGetNumberOfAttributes(relation); i++)
Assert(TupleDescAttr(relation->rd_att, i)->attcacheoff == -1);
}
#endif
@@ -660,7 +660,7 @@ RelationBuildTupleDesc(Relation relation)
* attribute: it must be zero. This eliminates the need for special cases
* for attnum=1 that used to exist in fastgetattr() and index_getattr().
*/
- if (relation->rd_rel->relnatts > 0)
+ if (RelationGetNumberOfAttributes(relation) > 0)
TupleDescAttr(relation->rd_att, 0)->attcacheoff = 0;
/*
@@ -673,7 +673,7 @@ RelationBuildTupleDesc(Relation relation)
if (ndef > 0) /* DEFAULTs */
{
- if (ndef < relation->rd_rel->relnatts)
+ if (ndef < RelationGetNumberOfAttributes(relation))
constr->defval = (AttrDefault *)
repalloc(attrdef, ndef * sizeof(AttrDefault));
else
@@ -1557,7 +1557,8 @@ RelationInitIndexAccessInfo(Relation relation)
int2vector *indoption;
MemoryContext indexcxt;
MemoryContext oldcontext;
- int natts;
+ int indnatts;
+ int indnkeyatts;
uint16 amsupport;
/*
@@ -1587,10 +1588,11 @@ RelationInitIndexAccessInfo(Relation relation)
relation->rd_amhandler = aform->amhandler;
ReleaseSysCache(tuple);
- natts = relation->rd_rel->relnatts;
- if (natts != relation->rd_index->indnatts)
+ indnatts = RelationGetNumberOfAttributes(relation);
+ if (indnatts != IndexRelationGetNumberOfAttributes(relation))
elog(ERROR, "relnatts disagrees with indnatts for index %u",
RelationGetRelid(relation));
+ indnkeyatts = IndexRelationGetNumberOfKeyAttributes(relation);
/*
* Make the private context to hold index access info. The reason we need
@@ -1610,17 +1612,18 @@ RelationInitIndexAccessInfo(Relation relation)
InitIndexAmRoutine(relation);
/*
- * Allocate arrays to hold data
+ * Allocate arrays to hold data. Opclasses are not used for included
+ * columns, so allocate them for indnkeyatts only.
*/
relation->rd_opfamily = (Oid *)
- MemoryContextAllocZero(indexcxt, natts * sizeof(Oid));
+ MemoryContextAllocZero(indexcxt, indnkeyatts * sizeof(Oid));
relation->rd_opcintype = (Oid *)
- MemoryContextAllocZero(indexcxt, natts * sizeof(Oid));
+ MemoryContextAllocZero(indexcxt, indnkeyatts * sizeof(Oid));
amsupport = relation->rd_amroutine->amsupport;
if (amsupport > 0)
{
- int nsupport = natts * amsupport;
+ int nsupport = indnatts * amsupport;
relation->rd_support = (RegProcedure *)
MemoryContextAllocZero(indexcxt, nsupport * sizeof(RegProcedure));
@@ -1634,10 +1637,10 @@ RelationInitIndexAccessInfo(Relation relation)
}
relation->rd_indcollation = (Oid *)
- MemoryContextAllocZero(indexcxt, natts * sizeof(Oid));
+ MemoryContextAllocZero(indexcxt, indnatts * sizeof(Oid));
relation->rd_indoption = (int16 *)
- MemoryContextAllocZero(indexcxt, natts * sizeof(int16));
+ MemoryContextAllocZero(indexcxt, indnatts * sizeof(int16));
/*
* indcollation cannot be referenced directly through the C struct,
@@ -1650,7 +1653,7 @@ RelationInitIndexAccessInfo(Relation relation)
&isnull);
Assert(!isnull);
indcoll = (oidvector *) DatumGetPointer(indcollDatum);
- memcpy(relation->rd_indcollation, indcoll->values, natts * sizeof(Oid));
+ memcpy(relation->rd_indcollation, indcoll->values, indnatts * sizeof(Oid));
/*
* indclass cannot be referenced directly through the C struct, because it
@@ -1671,7 +1674,7 @@ RelationInitIndexAccessInfo(Relation relation)
*/
IndexSupportInitialize(indclass, relation->rd_support,
relation->rd_opfamily, relation->rd_opcintype,
- amsupport, natts);
+ amsupport, indnkeyatts);
/*
* Similarly extract indoption and copy it to the cache entry
@@ -1682,7 +1685,7 @@ RelationInitIndexAccessInfo(Relation relation)
&isnull);
Assert(!isnull);
indoption = (int2vector *) DatumGetPointer(indoptionDatum);
- memcpy(relation->rd_indoption, indoption->values, natts * sizeof(int16));
+ memcpy(relation->rd_indoption, indoption->values, indnatts * sizeof(int16));
/*
* expressions, predicate, exclusion caches will be filled later
@@ -5064,20 +5067,28 @@ restart:
{
int attrnum = indexInfo->ii_KeyAttrNumbers[i];
+ /*
+ * Since we have covering indexes with non-key columns, we must
+ * handle them accurately here. non-key columns must be added into
+ * indexattrs, since they are in index, and HOT-update shouldn't
+ * miss them. Obviously, non-key columns couldn't be referenced by
+ * foreign key or identity key. Hence we do not include them into
+ * uindexattrs, pkindexattrs and idindexattrs bitmaps.
+ */
if (attrnum != 0)
{
indexattrs = bms_add_member(indexattrs,
attrnum - FirstLowInvalidHeapAttributeNumber);
- if (isKey)
+ if (isKey && i < indexInfo->ii_NumIndexKeyAttrs)
uindexattrs = bms_add_member(uindexattrs,
attrnum - FirstLowInvalidHeapAttributeNumber);
- if (isPK)
+ if (isPK && i < indexInfo->ii_NumIndexKeyAttrs)
pkindexattrs = bms_add_member(pkindexattrs,
attrnum - FirstLowInvalidHeapAttributeNumber);
- if (isIDKey)
+ if (isIDKey && i < indexInfo->ii_NumIndexKeyAttrs)
idindexattrs = bms_add_member(idindexattrs,
attrnum - FirstLowInvalidHeapAttributeNumber);
}
@@ -5195,7 +5206,7 @@ RelationGetExclusionInfo(Relation indexRelation,
Oid **procs,
uint16 **strategies)
{
- int ncols = indexRelation->rd_rel->relnatts;
+ int indnkeyatts;
Oid *ops;
Oid *funcs;
uint16 *strats;
@@ -5207,17 +5218,19 @@ RelationGetExclusionInfo(Relation indexRelation,
MemoryContext oldcxt;
int i;
+ indnkeyatts = 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) * indnkeyatts);
+ *procs = funcs = (Oid *) palloc(sizeof(Oid) * indnkeyatts);
+ *strategies = strats = (uint16 *) palloc(sizeof(uint16) * indnkeyatts);
/* 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) * indnkeyatts);
+ memcpy(funcs, indexRelation->rd_exclprocs, sizeof(Oid) * indnkeyatts);
+ memcpy(strats, indexRelation->rd_exclstrats, sizeof(uint16) * indnkeyatts);
return;
}
@@ -5266,12 +5279,12 @@ RelationGetExclusionInfo(Relation indexRelation,
arr = DatumGetArrayTypeP(val); /* ensure not toasted */
nelem = ARR_DIMS(arr)[0];
if (ARR_NDIM(arr) != 1 ||
- nelem != ncols ||
+ nelem != indnkeyatts ||
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) * indnkeyatts);
}
systable_endscan(conscan);
@@ -5282,7 +5295,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 < indnkeyatts; i++)
{
funcs[i] = get_opcode(ops[i]);
strats[i] = get_op_opfamily_strategy(ops[i],
@@ -5295,12 +5308,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) * indnkeyatts);
+ indexRelation->rd_exclprocs = (Oid *) palloc(sizeof(Oid) * indnkeyatts);
+ indexRelation->rd_exclstrats = (uint16 *) palloc(sizeof(uint16) * indnkeyatts);
+ memcpy(indexRelation->rd_exclops, ops, sizeof(Oid) * indnkeyatts);
+ memcpy(indexRelation->rd_exclprocs, funcs, sizeof(Oid) * indnkeyatts);
+ memcpy(indexRelation->rd_exclstrats, strats, sizeof(uint16) * indnkeyatts);
MemoryContextSwitchTo(oldcxt);
}
diff --git a/src/backend/utils/sort/tuplesort.c b/src/backend/utils/sort/tuplesort.c
index e433faad86a..a0c0d6f701a 100644
--- a/src/backend/utils/sort/tuplesort.c
+++ b/src/backend/utils/sort/tuplesort.c
@@ -900,7 +900,7 @@ tuplesort_begin_cluster(TupleDesc tupDesc,
workMem, randomAccess ? 't' : 'f');
#endif
- state->nKeys = RelationGetNumberOfAttributes(indexRel);
+ state->nKeys = IndexRelationGetNumberOfKeyAttributes(indexRel);
TRACE_POSTGRESQL_SORT_START(CLUSTER_SORT,
false, /* no unique check */
@@ -995,7 +995,7 @@ tuplesort_begin_index_btree(Relation heapRel,
workMem, randomAccess ? 't' : 'f');
#endif
- state->nKeys = RelationGetNumberOfAttributes(indexRel);
+ state->nKeys = IndexRelationGetNumberOfKeyAttributes(indexRel);
TRACE_POSTGRESQL_SORT_START(INDEX_SORT,
enforceUnique,
@@ -1015,7 +1015,6 @@ tuplesort_begin_index_btree(Relation heapRel,
state->enforceUnique = enforceUnique;
indexScanKey = _bt_mkscankey_nodata(indexRel);
- state->nKeys = RelationGetNumberOfAttributes(indexRel);
/* Prepare SortSupport data for each column */
state->sortKeys = (SortSupport) palloc0(state->nKeys *