Обсуждение: BUG #19049: Assert failure when using skip arrays on an index key with DESC order

Поиск
Список
Период
Сортировка

BUG #19049: Assert failure when using skip arrays on an index key with DESC order

От
PG Bug reporting form
Дата:
The following bug has been logged on the website:

Bug reference:      19049
Logged by:          Natalya Aksman
Email address:      natalya@timescale.com
PostgreSQL version: 18rc1
Operating system:   Ubuntu 24.04
Description:

Reproducer:

-- Set up a table with >=2 DESC index keys
create table mv (t1 int, t2 int, s0 int, s1 int);
create index on mv(s0, s1, t1 desc, t2 desc);
insert into mv select f.t,  f.t, 1 s0, 1 s1 from generate_series(1, 2 *
pow(10, 4)::int) f(t);
analyze mv;

-- Make sure index is used
set enable_seqscan=0;
explain (costs off) select distinct on(s0, s1) * from mv where t2 >= -1 and
t1 < 10 order by s0, s1, t1 desc, t2 desc;
                        QUERY PLAN
-----------------------------------------------------------
 Unique
   ->  Index Only Scan using mv_s0_s1_t1_t2_idx on mv
         Index Cond: ((t1 < 10) AND (t2 >= '-1'::integer))
(3 rows)

-- This query crashes with an Assert
 select distinct on(s0, s1) * from mv where t2 >= -1 and t1 < 10 order by
s0, s1, t1 desc, t2 desc;

Assert is:
                if (ScanDirectionIsForward(dir) && array->low_compare)
Assert(DatumGetBool(FunctionCall2Coll(&array->low_compare->sk_func,
array->low_compare->sk_collation,
tupdatum,
array->low_compare->sk_argument)));

The problem is "array->low_compare" changing "t1<10" to "t1>10" because t1
order is DESC.


PG Bug reporting form <noreply@postgresql.org> writes:
> -- This query crashes with an Assert
>  select distinct on(s0, s1) * from mv where t2 >= -1 and t1 < 10 order by
> s0, s1, t1 desc, t2 desc;

> Assert is:
>                 if (ScanDirectionIsForward(dir) && array->low_compare)
> Assert(DatumGetBool(FunctionCall2Coll(&array->low_compare->sk_func,
> array->low_compare->sk_collation, tupdatum, array->low_compare->sk_argument)));

Indeed.  "git bisect" says this started at

b3f1a13f22f9e28842ee5fbd08b7ec805e27aaac is the first bad commit
commit b3f1a13f22f9e28842ee5fbd08b7ec805e27aaac
Author: Peter Geoghegan <pg@bowt.ie>
Date:   Fri Apr 4 14:14:08 2025 -0400

    Avoid extra index searches through preprocessing.

Peter, you want to take a look?

            regards, tom lane



Re: BUG #19049: Assert failure when using skip arrays on an index key with DESC order

От
Peter Geoghegan
Дата:
On Thu, Sep 11, 2025 at 11:49 AM Tom Lane <tgl@sss.pgh.pa.us> wrote:
> Peter, you want to take a look?

Looking at it now...

--
Peter Geoghegan



Re: BUG #19049: Assert failure when using skip arrays on an index key with DESC order

От
Peter Geoghegan
Дата:
On Thu, Sep 11, 2025 at 10:35 AM PG Bug reporting form
<noreply@postgresql.org> wrote:
> Assert is:
>                 if (ScanDirectionIsForward(dir) && array->low_compare)
> Assert(DatumGetBool(FunctionCall2Coll(&array->low_compare->sk_func,
> array->low_compare->sk_collation,
> tupdatum,
> array->low_compare->sk_argument)));
>
> The problem is "array->low_compare" changing "t1<10" to "t1>10" because t1
> order is DESC.

This explanation is correct: I simply neglected to account for the way
that DESC column scalar keys (used as a skip array's
low_compare/high_compare) will have already had their operator
strategy inverted, at the point where preprocessing converts a
low_compare > into an equivalent >= (and/or a high_compare < into an
equivalent <=) as an optimization. As Tom pointed out, this is a bug
in the mechanism added by commit b3f1a13f (not the main skip scan
commit)

A draft fix is attached. This fixes the crash that your test case
exhibits, and passes all of my existing tests. I'll commit something
along these lines within the next few days, barring any objections.

I'm going to revisit my test coverage for DESC columns in light of
this issue. I didn't add support for DESC columns in my fuzz testing
scripts, which now seems like an oversight -- I'd definitely have
caught this problem myself, had I done that from the start.

--
Peter Geoghegan

Вложения

Re: BUG #19049: Assert failure when using skip arrays on an index key with DESC order

От
Natalya Aksman
Дата:
The patch looks good and fixes our failing tests.

Thank you,
Natalya Aksman.

On Thu, Sep 11, 2025 at 12:48 PM Peter Geoghegan <pg@bowt.ie> wrote:
On Thu, Sep 11, 2025 at 10:35 AM PG Bug reporting form
<noreply@postgresql.org> wrote:
> Assert is:
>                 if (ScanDirectionIsForward(dir) && array->low_compare)
> Assert(DatumGetBool(FunctionCall2Coll(&array->low_compare->sk_func,
> array->low_compare->sk_collation,
> tupdatum,
> array->low_compare->sk_argument)));
>
> The problem is "array->low_compare" changing "t1<10" to "t1>10" because t1
> order is DESC.

This explanation is correct: I simply neglected to account for the way
that DESC column scalar keys (used as a skip array's
low_compare/high_compare) will have already had their operator
strategy inverted, at the point where preprocessing converts a
low_compare > into an equivalent >= (and/or a high_compare < into an
equivalent <=) as an optimization. As Tom pointed out, this is a bug
in the mechanism added by commit b3f1a13f (not the main skip scan
commit)

A draft fix is attached. This fixes the crash that your test case
exhibits, and passes all of my existing tests. I'll commit something
along these lines within the next few days, barring any objections.

I'm going to revisit my test coverage for DESC columns in light of
this issue. I didn't add support for DESC columns in my fuzz testing
scripts, which now seems like an oversight -- I'd definitely have
caught this problem myself, had I done that from the start.

--
Peter Geoghegan

Re: BUG #19049: Assert failure when using skip arrays on an index key with DESC order

От
Peter Geoghegan
Дата:
On Thu, Sep 11, 2025 at 1:09 PM Natalya Aksman <natalya@tigerdata.com> wrote:
> The patch looks good and fixes our failing tests.

Thanks for the high quality bug report!

--
Peter Geoghegan



Re: BUG #19049: Assert failure when using skip arrays on an index key with DESC order

От
Peter Geoghegan
Дата:
On Thu, Sep 11, 2025 at 12:48 PM Peter Geoghegan <pg@bowt.ie> wrote:
> I'm going to revisit my test coverage for DESC columns in light of
> this issue. I didn't add support for DESC columns in my fuzz testing
> scripts, which now seems like an oversight -- I'd definitely have
> caught this problem myself, had I done that from the start.

Just for the record, I tried this out. Here's what happened:

I found that when I introduced alternating ASC/DESC column orders to
my existing fuzz testing script, it found the same bug in literally a
fraction of a second. I didn't see the same assertion failure that
Natalya's test case ran into, though; the script just detected
discrepancies between results from an index scan, and an equivalent
sequential scan (both for the same randomly generated query).

I also found that with my patch was applied, the same fuzz testing
script correctly executed several million randomly generated test
queries without incident. This includes randomly generated
combinations of equality/inequality operators, IS NULL/IS NOT NULL
conditions, IN() constructs, and skip arrays. All against either one
of a pair of indexes, each with 4 index columns (now with alternating
ASC and DESC column orders) -- there are two indexes to cover
different permutations of NULLS FIRST and NULLS LAST. The fuzz testing
script generates both backwards and forwards scans, for both of these
multicolumn indexes.

Obviously, this doesn't prove the absence of more DESC column related
bugs in the skip scan patchset. But it does make me confident that any
remaining DESC column related bugs are bound to be far more
subtle/hard to hit than this one was.

--
Peter Geoghegan