Location via proxy:   [ UP ]  
[Report a bug]   [Manage cookies]                
Skip to content

Commit 9f71e10

Browse files
committed
Fix checking of index expressions in CompareIndexInfo().
This code was sloppy about comparison of index columns that are expressions. It didn't reliably reject cases where one index has an expression where the other has a plain column, and it could index off the start of the attmap array, leading to a Valgrind complaint (though an actual crash seems unlikely). I'm not sure that the expression-vs-column sloppiness leads to any visible problem in practice, because the subsequent comparison of the two expression lists would reject cases where the indexes have different numbers of expressions overall. Maybe we could falsely match indexes having the same expressions in different column positions, but it'd require unlucky contents of the word before the attmap array. It's not too surprising that no problem has been reported from the field. Nonetheless, this code is clearly wrong. Per bug #18135 from Alexander Lakhin. Back-patch to all supported branches. Discussion: https://postgr.es/m/18135-532f4a755e71e4d2@postgresql.org
1 parent 4e9fc3a commit 9f71e10

File tree

1 file changed

+16
-7
lines changed

1 file changed

+16
-7
lines changed

src/backend/catalog/index.c

Lines changed: 16 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -2559,7 +2559,7 @@ CompareIndexInfo(const IndexInfo *info1, const IndexInfo *info2,
25592559

25602560
/*
25612561
* and columns match through the attribute map (actual attribute numbers
2562-
* might differ!) Note that this implies that index columns that are
2562+
* might differ!) Note that this checks that index columns that are
25632563
* expressions appear in the same positions. We will next compare the
25642564
* expressions themselves.
25652565
*/
@@ -2568,13 +2568,22 @@ CompareIndexInfo(const IndexInfo *info1, const IndexInfo *info2,
25682568
if (attmap->maplen < info2->ii_IndexAttrNumbers[i])
25692569
elog(ERROR, "incorrect attribute map");
25702570

2571-
/* ignore expressions at this stage */
2572-
if ((info1->ii_IndexAttrNumbers[i] != InvalidAttrNumber) &&
2573-
(attmap->attnums[info2->ii_IndexAttrNumbers[i] - 1] !=
2574-
info1->ii_IndexAttrNumbers[i]))
2575-
return false;
2571+
/* ignore expressions for now (but check their collation/opfamily) */
2572+
if (!(info1->ii_IndexAttrNumbers[i] == InvalidAttrNumber &&
2573+
info2->ii_IndexAttrNumbers[i] == InvalidAttrNumber))
2574+
{
2575+
/* fail if just one index has an expression in this column */
2576+
if (info1->ii_IndexAttrNumbers[i] == InvalidAttrNumber ||
2577+
info2->ii_IndexAttrNumbers[i] == InvalidAttrNumber)
2578+
return false;
2579+
2580+
/* both are columns, so check for match after mapping */
2581+
if (attmap->attnums[info2->ii_IndexAttrNumbers[i] - 1] !=
2582+
info1->ii_IndexAttrNumbers[i])
2583+
return false;
2584+
}
25762585

2577-
/* collation and opfamily is not valid for including columns */
2586+
/* collation and opfamily are not valid for included columns */
25782587
if (i >= info1->ii_NumIndexKeyAttrs)
25792588
continue;
25802589

0 commit comments

Comments
 (0)