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

Commit 8ab0ebb

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 eafdf9d commit 8ab0ebb

File tree

3 files changed

+24
-4
lines changed

3 files changed

+24
-4
lines changed

src/backend/utils/sort/tuplesort.c

+4-4
Original file line numberDiff line numberDiff line change
@@ -1051,7 +1051,7 @@ tuplesort_begin_heap(TupleDesc tupDesc,
10511051
sortKey->ssup_nulls_first = nullsFirstFlags[i];
10521052
sortKey->ssup_attno = attNums[i];
10531053
/* Convey if abbreviation optimization is applicable in principle */
1054-
sortKey->abbreviate = (i == 0);
1054+
sortKey->abbreviate = (i == 0 && state->haveDatum1);
10551055

10561056
PrepareSortSupportFromOrderingOp(sortOperators[i], sortKey);
10571057
}
@@ -1157,7 +1157,7 @@ tuplesort_begin_cluster(TupleDesc tupDesc,
11571157
(scanKey->sk_flags & SK_BT_NULLS_FIRST) != 0;
11581158
sortKey->ssup_attno = scanKey->sk_attno;
11591159
/* Convey if abbreviation optimization is applicable in principle */
1160-
sortKey->abbreviate = (i == 0);
1160+
sortKey->abbreviate = (i == 0 && state->haveDatum1);
11611161

11621162
AssertState(sortKey->ssup_attno != 0);
11631163

@@ -1238,7 +1238,7 @@ tuplesort_begin_index_btree(Relation heapRel,
12381238
(scanKey->sk_flags & SK_BT_NULLS_FIRST) != 0;
12391239
sortKey->ssup_attno = scanKey->sk_attno;
12401240
/* Convey if abbreviation optimization is applicable in principle */
1241-
sortKey->abbreviate = (i == 0);
1241+
sortKey->abbreviate = (i == 0 && state->haveDatum1);
12421242

12431243
AssertState(sortKey->ssup_attno != 0);
12441244

@@ -1348,7 +1348,7 @@ tuplesort_begin_index_gist(Relation heapRel,
13481348
sortKey->ssup_nulls_first = false;
13491349
sortKey->ssup_attno = i + 1;
13501350
/* Convey if abbreviation optimization is applicable in principle */
1351-
sortKey->abbreviate = (i == 0);
1351+
sortKey->abbreviate = (i == 0 && state->haveDatum1);
13521352

13531353
AssertState(sortKey->ssup_attno != 0);
13541354

src/test/regress/expected/cluster.out

+14
Original file line numberDiff line numberDiff line change
@@ -577,6 +577,13 @@ SELECT * FROM clstr_expression WHERE -a = -3 ORDER BY -a, b;
577577
COMMIT;
578578
-- and after clustering on clstr_expression_minus_a
579579
CLUSTER clstr_expression USING clstr_expression_minus_a;
580+
WITH rows AS
581+
(SELECT ctid, lag(a) OVER (ORDER BY ctid) AS la, a FROM clstr_expression)
582+
SELECT * FROM rows WHERE la < a;
583+
ctid | la | a
584+
------+----+---
585+
(0 rows)
586+
580587
BEGIN;
581588
SET LOCAL enable_seqscan = false;
582589
EXPLAIN (COSTS OFF) SELECT * FROM clstr_expression WHERE upper(b) = 'PREFIX3';
@@ -611,6 +618,13 @@ SELECT * FROM clstr_expression WHERE -a = -3 ORDER BY -a, b;
611618
COMMIT;
612619
-- and after clustering on clstr_expression_upper_b
613620
CLUSTER clstr_expression USING clstr_expression_upper_b;
621+
WITH rows AS
622+
(SELECT ctid, lag(b) OVER (ORDER BY ctid) AS lb, b FROM clstr_expression)
623+
SELECT * FROM rows WHERE upper(lb) > upper(b);
624+
ctid | lb | b
625+
------+----+---
626+
(0 rows)
627+
614628
BEGIN;
615629
SET LOCAL enable_seqscan = false;
616630
EXPLAIN (COSTS OFF) SELECT * FROM clstr_expression WHERE upper(b) = 'PREFIX3';

src/test/regress/sql/cluster.sql

+6
Original file line numberDiff line numberDiff line change
@@ -284,6 +284,9 @@ COMMIT;
284284

285285
-- and after clustering on clstr_expression_minus_a
286286
CLUSTER clstr_expression USING clstr_expression_minus_a;
287+
WITH rows AS
288+
(SELECT ctid, lag(a) OVER (ORDER BY ctid) AS la, a FROM clstr_expression)
289+
SELECT * FROM rows WHERE la < a;
287290
BEGIN;
288291
SET LOCAL enable_seqscan = false;
289292
EXPLAIN (COSTS OFF) SELECT * FROM clstr_expression WHERE upper(b) = 'PREFIX3';
@@ -294,6 +297,9 @@ COMMIT;
294297

295298
-- and after clustering on clstr_expression_upper_b
296299
CLUSTER clstr_expression USING clstr_expression_upper_b;
300+
WITH rows AS
301+
(SELECT ctid, lag(b) OVER (ORDER BY ctid) AS lb, b FROM clstr_expression)
302+
SELECT * FROM rows WHERE upper(lb) > upper(b);
297303
BEGIN;
298304
SET LOCAL enable_seqscan = false;
299305
EXPLAIN (COSTS OFF) SELECT * FROM clstr_expression WHERE upper(b) = 'PREFIX3';

0 commit comments

Comments
 (0)