Re: SELECT results in "ERROR: index key does not match expected index column" - Mailing list pgsql-bugs

From Tom Lane
Subject Re: SELECT results in "ERROR: index key does not match expected index column"
Date
Msg-id 27544.1562111153@sss.pgh.pa.us
Whole thread Raw
In response to Re: SELECT results in "ERROR: index key does not match expected indexcolumn"  (Gavin Flower <GavinFlower@archidevsys.co.nz>)
Responses Re: SELECT results in "ERROR: index key does not match expected index column"  (Peter Geoghegan <pg@bowt.ie>)
List pgsql-bugs
Gavin Flower <GavinFlower@archidevsys.co.nz> writes:
> On 03/07/2019 10:50, Tom Lane wrote:
>> Manuel Rigger <rigger.manuel@gmail.com> writes:
>>> Consider the following test case:
>>> CREATE TABLE t0(c0 boolean UNIQUE);
>>> CREATE INDEX i0 ON t0((nullif(FALSE, TRUE)));
>>> INSERT INTO t0(c0) VALUES(TRUE);
>>> SELECT * FROM t0 WHERE nullif(FALSE, TRUE) OR t0.c0;
>>> ERROR:  index key does not match expected index column

>> Huh.  I don't see that in HEAD/v12, but it does reproduce in v11
>> and quite a large number of branches before that.  Looking ...

So the problem here is that fix_indexqual_references hasn't got
enough information to guess whether the derived indexable clause
"nullif(FALSE, TRUE) = TRUE" needs to be commuted or not, and it
guesses wrong:

            /*
             * Check to see if the indexkey is on the right; if so, commute
             * the clause.  The indexkey should be the side that refers to
             * (only) the base relation.
             */
            if (!bms_equal(rinfo->left_relids, index->rel->relids))
                CommuteOpExpr(op);

In this example both left_relids and right_relids are empty (since
both sides of the comparison are constants), so there's no way for it
to do the right thing.  We could invert the way the test is done, but
that would just move the failure to other cases where commutation
*is* needed.

This is fixed somewhat accidentally in HEAD/v12 because I got rid of
the need for fix_indexqual_references to guess anything, by dint of
requiring the index clause to have been generated with indexkey on
the left to begin with:

    Author: Tom Lane <tgl@sss.pgh.pa.us>
    Branch: master [1a8d5afb0] 2019-02-09 17:30:43 -0500

    Refactor the representation of indexable clauses in IndexPaths.
    ...
    We also change the ground rules a bit by mandating that clause commutation,
    if needed, be done up-front so that what is stored in the indexquals list
    is always directly usable as an index condition.  This gets rid of repeated
    re-determination of which side of the clause is the indexkey during costing
    and plan generation, as well as repeated lookups of the commutator
    operator.

There's exactly no chance that we'd back-patch a change as invasive
as that was, of course.

This problem has been there a *long* time --- the given test case
fails back to 8.1, and I can make variants of it fail in 7.4, and
probably further back but I'm disinclined to spin up a machine with
an older server just to check.  Probably the reason it's not been
complained of more is that it's pretty hard to get to --- usually,
an all-constant qual condition wouldn't be a candidate to be matched to
an index in the first place.  The "OR" with another, more obviously
indexable, qual is probably essential to expose the problem.

Given the history and the lack of any easy fix, I'm inclined to write
this off as "won't fix in back branches".

>> (You realize of course that an index on a constant is pretty
>> useless.  I wonder if we should disallow that.)

> I think it should cause an error, most likely an unintentional
> implementation mistake -- so the sooner it is flagged the better to
> remedy it!

On reflection that might be overkill.  I've heard of people using
unique indexes on constants to constrain tables to one row, and
you can make interesting refinements by making the index partial.

(If you want to do something like that in released branches, the
workaround for this problem would be to use a constant value that
doesn't match anything that'd appear in your queries...)

            regards, tom lane



pgsql-bugs by date:

Previous
From: Thomas Munro
Date:
Subject: Re: SELECT results in "ERROR: index key does not match expected index column"
Next
From: Peter Geoghegan
Date:
Subject: Re: SELECT results in "ERROR: index key does not match expected index column"