Commit c266ed31 authored by Teodor Sigaev's avatar Teodor Sigaev

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
parent 08ea7a22
...@@ -297,6 +297,7 @@ ConstructTupleDescriptor(Relation heapRelation, ...@@ -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, ...@@ -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, ...@@ -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, ...@@ -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, ...@@ -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, ...@@ -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, ...@@ -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) ...@@ -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, ...@@ -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, ...@@ -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, ...@@ -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, ...@@ -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, ...@@ -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, ...@@ -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, ...@@ -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, ...@@ -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, ...@@ -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, ...@@ -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, ...@@ -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, ...@@ -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, ...@@ -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, ...@@ -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, ...@@ -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
......
...@@ -1637,10 +1637,10 @@ RelationInitIndexAccessInfo(Relation relation) ...@@ -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) ...@@ -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) ...@@ -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
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment