Skip to content

Commit 5487585

Browse files
Fix CLUSTER tuplesorts on abbreviated expressions.
CLUSTER sort won't use the datum1 SortTuple field when clustering against an index whose leading key is an expression. This makes it unsafe to use the abbreviated keys optimization, which was missed by the logic that sets up SortSupport state. Affected tuplesorts output tuples in a completely bogus order as a result (the wrong SortSupport based comparator was used for the leading attribute). This issue is similar to the bug fixed on the master branch by recent commit cc58eec. But it's a far older issue, that dates back to the introduction of the abbreviated keys optimization by commit 4ea51cd. Backpatch to all supported versions. Author: Peter Geoghegan <pg@bowt.ie> Author: Thomas Munro <thomas.munro@gmail.com> Discussion: https://postgr.es/m/CA+hUKG+bA+bmwD36_oDxAoLrCwZjVtST2fqe=b4=qZcmU7u89A@mail.gmail.com Backpatch: 10-
1 parent 33fe55c commit 5487585

File tree

3 files changed

+23
-1
lines changed

3 files changed

+23
-1
lines changed

src/backend/utils/sort/tuplesort.c

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -884,6 +884,7 @@ tuplesort_begin_cluster(TupleDesc tupDesc,
884884
{
885885
Tuplesortstate *state = tuplesort_begin_common(workMem, coordinate,
886886
randomAccess);
887+
AttrNumber leading;
887888
BTScanInsert indexScanKey;
888889
MemoryContext oldcontext;
889890
int i;
@@ -916,6 +917,7 @@ tuplesort_begin_cluster(TupleDesc tupDesc,
916917
state->abbrevNext = 10;
917918

918919
state->indexInfo = BuildIndexInfo(indexRel);
920+
leading = state->indexInfo->ii_IndexAttrNumbers[0];
919921

920922
state->tupDesc = tupDesc; /* assume we need not copy tupDesc */
921923

@@ -954,7 +956,7 @@ tuplesort_begin_cluster(TupleDesc tupDesc,
954956
(scanKey->sk_flags & SK_BT_NULLS_FIRST) != 0;
955957
sortKey->ssup_attno = scanKey->sk_attno;
956958
/* Convey if abbreviation optimization is applicable in principle */
957-
sortKey->abbreviate = (i == 0);
959+
sortKey->abbreviate = (i == 0 && leading != 0);
958960

959961
AssertState(sortKey->ssup_attno != 0);
960962

src/test/regress/expected/cluster.out

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -506,6 +506,13 @@ SELECT * FROM clstr_expression WHERE -a = -3 ORDER BY -a, b;
506506
COMMIT;
507507
-- and after clustering on clstr_expression_minus_a
508508
CLUSTER clstr_expression USING clstr_expression_minus_a;
509+
WITH rows AS
510+
(SELECT ctid, lag(a) OVER (ORDER BY ctid) AS la, a FROM clstr_expression)
511+
SELECT * FROM rows WHERE la < a;
512+
ctid | la | a
513+
------+----+---
514+
(0 rows)
515+
509516
BEGIN;
510517
SET LOCAL enable_seqscan = false;
511518
EXPLAIN (COSTS OFF) SELECT * FROM clstr_expression WHERE upper(b) = 'PREFIX3';
@@ -540,6 +547,13 @@ SELECT * FROM clstr_expression WHERE -a = -3 ORDER BY -a, b;
540547
COMMIT;
541548
-- and after clustering on clstr_expression_upper_b
542549
CLUSTER clstr_expression USING clstr_expression_upper_b;
550+
WITH rows AS
551+
(SELECT ctid, lag(b) OVER (ORDER BY ctid) AS lb, b FROM clstr_expression)
552+
SELECT * FROM rows WHERE upper(lb) > upper(b);
553+
ctid | lb | b
554+
------+----+---
555+
(0 rows)
556+
543557
BEGIN;
544558
SET LOCAL enable_seqscan = false;
545559
EXPLAIN (COSTS OFF) SELECT * FROM clstr_expression WHERE upper(b) = 'PREFIX3';

src/test/regress/sql/cluster.sql

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -239,6 +239,9 @@ COMMIT;
239239

240240
-- and after clustering on clstr_expression_minus_a
241241
CLUSTER clstr_expression USING clstr_expression_minus_a;
242+
WITH rows AS
243+
(SELECT ctid, lag(a) OVER (ORDER BY ctid) AS la, a FROM clstr_expression)
244+
SELECT * FROM rows WHERE la < a;
242245
BEGIN;
243246
SET LOCAL enable_seqscan = false;
244247
EXPLAIN (COSTS OFF) SELECT * FROM clstr_expression WHERE upper(b) = 'PREFIX3';
@@ -249,6 +252,9 @@ COMMIT;
249252

250253
-- and after clustering on clstr_expression_upper_b
251254
CLUSTER clstr_expression USING clstr_expression_upper_b;
255+
WITH rows AS
256+
(SELECT ctid, lag(b) OVER (ORDER BY ctid) AS lb, b FROM clstr_expression)
257+
SELECT * FROM rows WHERE upper(lb) > upper(b);
252258
BEGIN;
253259
SET LOCAL enable_seqscan = false;
254260
EXPLAIN (COSTS OFF) SELECT * FROM clstr_expression WHERE upper(b) = 'PREFIX3';

0 commit comments

Comments
 (0)
pFad - Phonifier reborn

Pfad - The Proxy pFad of © 2024 Garber Painting. All rights reserved.

Note: This service is not intended for secure transactions such as banking, social media, email, or purchasing. Use at your own risk. We assume no liability whatsoever for broken pages.


Alternative Proxies:

Alternative Proxy

pFad Proxy

pFad v3 Proxy

pFad v4 Proxy