mirror of
https://github.com/postgres/postgres.git
synced 2025-06-25 01:02:05 +03:00
Cleanup covering infrastructure
- Explicitly forbids opclass, collation and indoptions (like DESC/ASC etc) for including columns. Throw an error if user points that. - Truncated storage arrays for such attributes to store only key atrributes, added assertion checks. - Do not check opfamily and collation for including columns in CompareIndexInfo() Discussion: https://www.postgresql.org/message-id/5ee72852-3c4e-ee35-e2ed-c1d053d45c08@sigaev.ru
This commit is contained in:
@ -297,6 +297,7 @@ ConstructTupleDescriptor(Relation heapRelation,
|
|||||||
Oid *classObjectId)
|
Oid *classObjectId)
|
||||||
{
|
{
|
||||||
int numatts = indexInfo->ii_NumIndexAttrs;
|
int numatts = indexInfo->ii_NumIndexAttrs;
|
||||||
|
int numkeyatts = indexInfo->ii_NumIndexKeyAttrs;
|
||||||
ListCell *colnames_item = list_head(indexColNames);
|
ListCell *colnames_item = list_head(indexColNames);
|
||||||
ListCell *indexpr_item = list_head(indexInfo->ii_Expressions);
|
ListCell *indexpr_item = list_head(indexInfo->ii_Expressions);
|
||||||
IndexAmRoutine *amroutine;
|
IndexAmRoutine *amroutine;
|
||||||
@ -375,7 +376,8 @@ ConstructTupleDescriptor(Relation heapRelation,
|
|||||||
to->attidentity = '\0';
|
to->attidentity = '\0';
|
||||||
to->attislocal = true;
|
to->attislocal = true;
|
||||||
to->attinhcount = 0;
|
to->attinhcount = 0;
|
||||||
to->attcollation = collationObjectId[i];
|
to->attcollation = (i < numkeyatts) ?
|
||||||
|
collationObjectId[i] : InvalidOid;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
@ -411,7 +413,8 @@ ConstructTupleDescriptor(Relation heapRelation,
|
|||||||
to->attcacheoff = -1;
|
to->attcacheoff = -1;
|
||||||
to->atttypmod = exprTypmod(indexkey);
|
to->atttypmod = exprTypmod(indexkey);
|
||||||
to->attislocal = true;
|
to->attislocal = true;
|
||||||
to->attcollation = collationObjectId[i];
|
to->attcollation = (i < numkeyatts) ?
|
||||||
|
collationObjectId[i] : InvalidOid;
|
||||||
|
|
||||||
ReleaseSysCache(tuple);
|
ReleaseSysCache(tuple);
|
||||||
|
|
||||||
@ -608,9 +611,9 @@ UpdateIndexRelation(Oid indexoid,
|
|||||||
indkey = buildint2vector(NULL, indexInfo->ii_NumIndexAttrs);
|
indkey = buildint2vector(NULL, indexInfo->ii_NumIndexAttrs);
|
||||||
for (i = 0; i < indexInfo->ii_NumIndexAttrs; i++)
|
for (i = 0; i < indexInfo->ii_NumIndexAttrs; i++)
|
||||||
indkey->values[i] = indexInfo->ii_IndexAttrNumbers[i];
|
indkey->values[i] = indexInfo->ii_IndexAttrNumbers[i];
|
||||||
indcollation = buildoidvector(collationOids, indexInfo->ii_NumIndexAttrs);
|
indcollation = buildoidvector(collationOids, indexInfo->ii_NumIndexKeyAttrs);
|
||||||
indclass = buildoidvector(classOids, indexInfo->ii_NumIndexKeyAttrs);
|
indclass = buildoidvector(classOids, indexInfo->ii_NumIndexKeyAttrs);
|
||||||
indoption = buildint2vector(coloptions, indexInfo->ii_NumIndexAttrs);
|
indoption = buildint2vector(coloptions, indexInfo->ii_NumIndexKeyAttrs);
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Convert the index expressions (if any) to a text datum
|
* Convert the index expressions (if any) to a text datum
|
||||||
@ -1081,7 +1084,7 @@ index_create(Relation heapRelation,
|
|||||||
|
|
||||||
/* Store dependency on collations */
|
/* Store dependency on collations */
|
||||||
/* The default collation is pinned, so don't bother recording it */
|
/* 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]) &&
|
if (OidIsValid(collationObjectId[i]) &&
|
||||||
collationObjectId[i] != DEFAULT_COLLATION_OID)
|
collationObjectId[i] != DEFAULT_COLLATION_OID)
|
||||||
@ -1832,6 +1835,11 @@ CompareIndexInfo(IndexInfo *info1, IndexInfo *info2,
|
|||||||
if (info1->ii_NumIndexAttrs != info2->ii_NumIndexAttrs)
|
if (info1->ii_NumIndexAttrs != info2->ii_NumIndexAttrs)
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
|
/* and same number of key attributes */
|
||||||
|
if (info1->ii_NumIndexKeyAttrs != info2->ii_NumIndexKeyAttrs)
|
||||||
|
return false;
|
||||||
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* and columns match through the attribute map (actual attribute numbers
|
* and columns match through the attribute map (actual attribute numbers
|
||||||
* might differ!) Note that this implies that index columns that are
|
* might differ!) Note that this implies that index columns that are
|
||||||
@ -1849,6 +1857,10 @@ CompareIndexInfo(IndexInfo *info1, IndexInfo *info2,
|
|||||||
info1->ii_IndexAttrNumbers[i]))
|
info1->ii_IndexAttrNumbers[i]))
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
|
/* collation and opfamily is not valid for including columns */
|
||||||
|
if (i >= info1->ii_NumIndexKeyAttrs)
|
||||||
|
continue;
|
||||||
|
|
||||||
if (collations1[i] != collations2[i])
|
if (collations1[i] != collations2[i])
|
||||||
return false;
|
return false;
|
||||||
if (opfamilies1[i] != opfamilies2[i])
|
if (opfamilies1[i] != opfamilies2[i])
|
||||||
|
@ -1359,7 +1359,8 @@ CheckPredicate(Expr *predicate)
|
|||||||
|
|
||||||
/*
|
/*
|
||||||
* Compute per-index-column information, including indexed column numbers
|
* Compute per-index-column information, including indexed column numbers
|
||||||
* or index expressions, opclasses, and indoptions.
|
* or index expressions, opclasses, and indoptions. Note, all output vectors
|
||||||
|
* should be allocated for all columns, including "including" ones.
|
||||||
*/
|
*/
|
||||||
static void
|
static void
|
||||||
ComputeIndexAttrs(IndexInfo *indexInfo,
|
ComputeIndexAttrs(IndexInfo *indexInfo,
|
||||||
@ -1490,6 +1491,36 @@ ComputeIndexAttrs(IndexInfo *indexInfo,
|
|||||||
|
|
||||||
typeOidP[attn] = atttype;
|
typeOidP[attn] = atttype;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Included columns have no collation, no opclass and no ordering options.
|
||||||
|
*/
|
||||||
|
if (attn >= nkeycols)
|
||||||
|
{
|
||||||
|
if (attribute->collation)
|
||||||
|
ereport(ERROR,
|
||||||
|
(errcode(ERRCODE_INVALID_OBJECT_DEFINITION),
|
||||||
|
errmsg("including column does not support a collation")));
|
||||||
|
if (attribute->opclass)
|
||||||
|
ereport(ERROR,
|
||||||
|
(errcode(ERRCODE_INVALID_OBJECT_DEFINITION),
|
||||||
|
errmsg("including column does not support an operator class")));
|
||||||
|
if (attribute->ordering != SORTBY_DEFAULT)
|
||||||
|
ereport(ERROR,
|
||||||
|
(errcode(ERRCODE_INVALID_OBJECT_DEFINITION),
|
||||||
|
errmsg("including column does not support ASC/DESC options")));
|
||||||
|
if (attribute->nulls_ordering != SORTBY_NULLS_DEFAULT)
|
||||||
|
ereport(ERROR,
|
||||||
|
(errcode(ERRCODE_INVALID_OBJECT_DEFINITION),
|
||||||
|
errmsg("including column does not support NULLS FIRST/LAST options")));
|
||||||
|
|
||||||
|
classOidP[attn] = InvalidOid;
|
||||||
|
colOptionP[attn] = 0;
|
||||||
|
collationOidP[attn] = InvalidOid;
|
||||||
|
attn++;
|
||||||
|
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Apply collation override if any
|
* Apply collation override if any
|
||||||
*/
|
*/
|
||||||
@ -1521,17 +1552,6 @@ ComputeIndexAttrs(IndexInfo *indexInfo,
|
|||||||
|
|
||||||
collationOidP[attn] = attcollation;
|
collationOidP[attn] = attcollation;
|
||||||
|
|
||||||
/*
|
|
||||||
* Included columns have no opclass and no ordering options.
|
|
||||||
*/
|
|
||||||
if (attn >= nkeycols)
|
|
||||||
{
|
|
||||||
classOidP[attn] = InvalidOid;
|
|
||||||
colOptionP[attn] = 0;
|
|
||||||
attn++;
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Identify the opclass to use.
|
* Identify the opclass to use.
|
||||||
*/
|
*/
|
||||||
|
@ -2329,8 +2329,8 @@ match_clause_to_indexcol(IndexOptInfo *index,
|
|||||||
{
|
{
|
||||||
Expr *clause = rinfo->clause;
|
Expr *clause = rinfo->clause;
|
||||||
Index index_relid = index->rel->relid;
|
Index index_relid = index->rel->relid;
|
||||||
Oid opfamily = index->opfamily[indexcol];
|
Oid opfamily;
|
||||||
Oid idxcollation = index->indexcollations[indexcol];
|
Oid idxcollation;
|
||||||
Node *leftop,
|
Node *leftop,
|
||||||
*rightop;
|
*rightop;
|
||||||
Relids left_relids;
|
Relids left_relids;
|
||||||
@ -2339,6 +2339,11 @@ match_clause_to_indexcol(IndexOptInfo *index,
|
|||||||
Oid expr_coll;
|
Oid expr_coll;
|
||||||
bool plain_op;
|
bool plain_op;
|
||||||
|
|
||||||
|
Assert(indexcol < index->nkeycolumns);
|
||||||
|
|
||||||
|
opfamily = index->opfamily[indexcol];
|
||||||
|
idxcollation = index->indexcollations[indexcol];
|
||||||
|
|
||||||
/* First check for boolean-index cases. */
|
/* First check for boolean-index cases. */
|
||||||
if (IsBooleanOpfamily(opfamily))
|
if (IsBooleanOpfamily(opfamily))
|
||||||
{
|
{
|
||||||
@ -2678,8 +2683,8 @@ match_clause_to_ordering_op(IndexOptInfo *index,
|
|||||||
Expr *clause,
|
Expr *clause,
|
||||||
Oid pk_opfamily)
|
Oid pk_opfamily)
|
||||||
{
|
{
|
||||||
Oid opfamily = index->opfamily[indexcol];
|
Oid opfamily;
|
||||||
Oid idxcollation = index->indexcollations[indexcol];
|
Oid idxcollation;
|
||||||
Node *leftop,
|
Node *leftop,
|
||||||
*rightop;
|
*rightop;
|
||||||
Oid expr_op;
|
Oid expr_op;
|
||||||
@ -2687,6 +2692,10 @@ match_clause_to_ordering_op(IndexOptInfo *index,
|
|||||||
Oid sortfamily;
|
Oid sortfamily;
|
||||||
bool commuted;
|
bool commuted;
|
||||||
|
|
||||||
|
Assert(indexcol < index->nkeycolumns);
|
||||||
|
|
||||||
|
opfamily = index->opfamily[indexcol];
|
||||||
|
idxcollation = index->indexcollations[indexcol];
|
||||||
/*
|
/*
|
||||||
* Clause must be a binary opclause.
|
* Clause must be a binary opclause.
|
||||||
*/
|
*/
|
||||||
@ -2921,8 +2930,13 @@ ec_member_matches_indexcol(PlannerInfo *root, RelOptInfo *rel,
|
|||||||
{
|
{
|
||||||
IndexOptInfo *index = ((ec_member_matches_arg *) arg)->index;
|
IndexOptInfo *index = ((ec_member_matches_arg *) arg)->index;
|
||||||
int indexcol = ((ec_member_matches_arg *) arg)->indexcol;
|
int indexcol = ((ec_member_matches_arg *) arg)->indexcol;
|
||||||
Oid curFamily = index->opfamily[indexcol];
|
Oid curFamily;
|
||||||
Oid curCollation = index->indexcollations[indexcol];
|
Oid curCollation;
|
||||||
|
|
||||||
|
Assert(indexcol < index->nkeycolumns);
|
||||||
|
|
||||||
|
curFamily = index->opfamily[indexcol];
|
||||||
|
curCollation = index->indexcollations[indexcol];
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* If it's a btree index, we can reject it if its opfamily isn't
|
* If it's a btree index, we can reject it if its opfamily isn't
|
||||||
@ -3548,8 +3562,13 @@ expand_indexqual_conditions(IndexOptInfo *index,
|
|||||||
RestrictInfo *rinfo = (RestrictInfo *) lfirst(lcc);
|
RestrictInfo *rinfo = (RestrictInfo *) lfirst(lcc);
|
||||||
int indexcol = lfirst_int(lci);
|
int indexcol = lfirst_int(lci);
|
||||||
Expr *clause = rinfo->clause;
|
Expr *clause = rinfo->clause;
|
||||||
Oid curFamily = index->opfamily[indexcol];
|
Oid curFamily;
|
||||||
Oid curCollation = index->indexcollations[indexcol];
|
Oid curCollation;
|
||||||
|
|
||||||
|
Assert(indexcol < index->nkeycolumns);
|
||||||
|
|
||||||
|
curFamily = index->opfamily[indexcol];
|
||||||
|
curCollation = index->indexcollations[indexcol];
|
||||||
|
|
||||||
/* First check for boolean cases */
|
/* First check for boolean cases */
|
||||||
if (IsBooleanOpfamily(curFamily))
|
if (IsBooleanOpfamily(curFamily))
|
||||||
@ -3918,14 +3937,15 @@ adjust_rowcompare_for_index(RowCompareExpr *clause,
|
|||||||
/*
|
/*
|
||||||
* The Var side can match any column of the index.
|
* The Var side can match any column of the index.
|
||||||
*/
|
*/
|
||||||
for (i = 0; i < index->ncolumns; i++)
|
for (i = 0; i < index->nkeycolumns; i++)
|
||||||
{
|
{
|
||||||
if (match_index_to_operand(varop, i, index) &&
|
if (match_index_to_operand(varop, i, index) &&
|
||||||
get_op_opfamily_strategy(expr_op,
|
get_op_opfamily_strategy(expr_op,
|
||||||
index->opfamily[i]) == op_strategy &&
|
index->opfamily[i]) == op_strategy &&
|
||||||
IndexCollMatchesExprColl(index->indexcollations[i],
|
IndexCollMatchesExprColl(index->indexcollations[i],
|
||||||
lfirst_oid(collids_cell)))
|
lfirst_oid(collids_cell)))
|
||||||
break;
|
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
if (i >= index->ncolumns)
|
if (i >= index->ncolumns)
|
||||||
break; /* no match found */
|
break; /* no match found */
|
||||||
|
@ -242,7 +242,7 @@ get_relation_info(PlannerInfo *root, Oid relationObjectId, bool inhparent,
|
|||||||
info->nkeycolumns = nkeycolumns = index->indnkeyatts;
|
info->nkeycolumns = nkeycolumns = index->indnkeyatts;
|
||||||
|
|
||||||
info->indexkeys = (int *) palloc(sizeof(int) * ncolumns);
|
info->indexkeys = (int *) palloc(sizeof(int) * ncolumns);
|
||||||
info->indexcollations = (Oid *) palloc(sizeof(Oid) * ncolumns);
|
info->indexcollations = (Oid *) palloc(sizeof(Oid) * nkeycolumns);
|
||||||
info->opfamily = (Oid *) palloc(sizeof(Oid) * nkeycolumns);
|
info->opfamily = (Oid *) palloc(sizeof(Oid) * nkeycolumns);
|
||||||
info->opcintype = (Oid *) palloc(sizeof(Oid) * nkeycolumns);
|
info->opcintype = (Oid *) palloc(sizeof(Oid) * nkeycolumns);
|
||||||
info->canreturn = (bool *) palloc(sizeof(bool) * ncolumns);
|
info->canreturn = (bool *) palloc(sizeof(bool) * ncolumns);
|
||||||
@ -250,7 +250,6 @@ get_relation_info(PlannerInfo *root, Oid relationObjectId, bool inhparent,
|
|||||||
for (i = 0; i < ncolumns; i++)
|
for (i = 0; i < ncolumns; i++)
|
||||||
{
|
{
|
||||||
info->indexkeys[i] = index->indkey.values[i];
|
info->indexkeys[i] = index->indkey.values[i];
|
||||||
info->indexcollations[i] = indexRelation->rd_indcollation[i];
|
|
||||||
info->canreturn[i] = index_can_return(indexRelation, i + 1);
|
info->canreturn[i] = index_can_return(indexRelation, i + 1);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -258,6 +257,7 @@ get_relation_info(PlannerInfo *root, Oid relationObjectId, bool inhparent,
|
|||||||
{
|
{
|
||||||
info->opfamily[i] = indexRelation->rd_opfamily[i];
|
info->opfamily[i] = indexRelation->rd_opfamily[i];
|
||||||
info->opcintype[i] = indexRelation->rd_opcintype[i];
|
info->opcintype[i] = indexRelation->rd_opcintype[i];
|
||||||
|
info->indexcollations[i] = indexRelation->rd_indcollation[i];
|
||||||
}
|
}
|
||||||
|
|
||||||
info->relam = indexRelation->rd_rel->relam;
|
info->relam = indexRelation->rd_rel->relam;
|
||||||
|
@ -1588,9 +1588,6 @@ generateClonedIndexStmt(RangeVar *heapRel, Oid heapRelid, Relation source_idx,
|
|||||||
/* Copy the original index column name */
|
/* Copy the original index column name */
|
||||||
iparam->indexcolname = pstrdup(NameStr(attr->attname));
|
iparam->indexcolname = pstrdup(NameStr(attr->attname));
|
||||||
|
|
||||||
/* Add the collation name, if non-default */
|
|
||||||
iparam->collation = get_collation(indcollation->values[keyno], keycoltype);
|
|
||||||
|
|
||||||
index->indexIncludingParams = lappend(index->indexIncludingParams, iparam);
|
index->indexIncludingParams = lappend(index->indexIncludingParams, iparam);
|
||||||
}
|
}
|
||||||
/* Copy reloptions if any */
|
/* Copy reloptions if any */
|
||||||
|
@ -1356,15 +1356,15 @@ pg_get_indexdef_worker(Oid indexrelid, int colno,
|
|||||||
{
|
{
|
||||||
Oid indcoll;
|
Oid indcoll;
|
||||||
|
|
||||||
|
if (keyno >= idxrec->indnkeyatts)
|
||||||
|
continue;
|
||||||
|
|
||||||
/* Add collation, if not default for column */
|
/* Add collation, if not default for column */
|
||||||
indcoll = indcollation->values[keyno];
|
indcoll = indcollation->values[keyno];
|
||||||
if (OidIsValid(indcoll) && indcoll != keycolcollation)
|
if (OidIsValid(indcoll) && indcoll != keycolcollation)
|
||||||
appendStringInfo(&buf, " COLLATE %s",
|
appendStringInfo(&buf, " COLLATE %s",
|
||||||
generate_collation_name((indcoll)));
|
generate_collation_name((indcoll)));
|
||||||
|
|
||||||
if (keyno >= idxrec->indnkeyatts)
|
|
||||||
continue;
|
|
||||||
|
|
||||||
/* Add the operator class name, if not default */
|
/* Add the operator class name, if not default */
|
||||||
get_opclass_name(indclass->values[keyno], keycoltype, &buf);
|
get_opclass_name(indclass->values[keyno], keycoltype, &buf);
|
||||||
|
|
||||||
|
@ -7437,6 +7437,8 @@ gincost_pattern(IndexOptInfo *index, int indexcol,
|
|||||||
int32 searchMode = GIN_SEARCH_MODE_DEFAULT;
|
int32 searchMode = GIN_SEARCH_MODE_DEFAULT;
|
||||||
int32 i;
|
int32 i;
|
||||||
|
|
||||||
|
Assert(indexcol < index->nkeycolumns);
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Get the operator's strategy number and declared input data types within
|
* Get the operator's strategy number and declared input data types within
|
||||||
* the index opfamily. (We don't need the latter, but we use
|
* the index opfamily. (We don't need the latter, but we use
|
||||||
|
8
src/backend/utils/cache/relcache.c
vendored
8
src/backend/utils/cache/relcache.c
vendored
@ -1637,10 +1637,10 @@ RelationInitIndexAccessInfo(Relation relation)
|
|||||||
}
|
}
|
||||||
|
|
||||||
relation->rd_indcollation = (Oid *)
|
relation->rd_indcollation = (Oid *)
|
||||||
MemoryContextAllocZero(indexcxt, indnatts * sizeof(Oid));
|
MemoryContextAllocZero(indexcxt, indnkeyatts * sizeof(Oid));
|
||||||
|
|
||||||
relation->rd_indoption = (int16 *)
|
relation->rd_indoption = (int16 *)
|
||||||
MemoryContextAllocZero(indexcxt, indnatts * sizeof(int16));
|
MemoryContextAllocZero(indexcxt, indnkeyatts * sizeof(int16));
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* indcollation cannot be referenced directly through the C struct,
|
* indcollation cannot be referenced directly through the C struct,
|
||||||
@ -1653,7 +1653,7 @@ RelationInitIndexAccessInfo(Relation relation)
|
|||||||
&isnull);
|
&isnull);
|
||||||
Assert(!isnull);
|
Assert(!isnull);
|
||||||
indcoll = (oidvector *) DatumGetPointer(indcollDatum);
|
indcoll = (oidvector *) DatumGetPointer(indcollDatum);
|
||||||
memcpy(relation->rd_indcollation, indcoll->values, indnatts * sizeof(Oid));
|
memcpy(relation->rd_indcollation, indcoll->values, indnkeyatts * sizeof(Oid));
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* indclass cannot be referenced directly through the C struct, because it
|
* indclass cannot be referenced directly through the C struct, because it
|
||||||
@ -1685,7 +1685,7 @@ RelationInitIndexAccessInfo(Relation relation)
|
|||||||
&isnull);
|
&isnull);
|
||||||
Assert(!isnull);
|
Assert(!isnull);
|
||||||
indoption = (int2vector *) DatumGetPointer(indoptionDatum);
|
indoption = (int2vector *) DatumGetPointer(indoptionDatum);
|
||||||
memcpy(relation->rd_indoption, indoption->values, indnatts * sizeof(int16));
|
memcpy(relation->rd_indoption, indoption->values, indnkeyatts * sizeof(int16));
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* expressions, predicate, exclusion caches will be filled later
|
* expressions, predicate, exclusion caches will be filled later
|
||||||
|
Reference in New Issue
Block a user