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

Commit 1272630

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 8275ba7 commit 1272630

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
@@ -956,6 +956,7 @@ tuplesort_begin_cluster(TupleDesc tupDesc,
956956
{
957957
Tuplesortstate *state = tuplesort_begin_common(workMem, coordinate,
958958
randomAccess);
959+
AttrNumber leading;
959960
BTScanInsert indexScanKey;
960961
MemoryContext oldcontext;
961962
int i;
@@ -988,6 +989,7 @@ tuplesort_begin_cluster(TupleDesc tupDesc,
988989
state->abbrevNext = 10;
989990

990991
state->indexInfo = BuildIndexInfo(indexRel);
992+
leading = state->indexInfo->ii_IndexAttrNumbers[0];
991993

992994
state->tupDesc = tupDesc; /* assume we need not copy tupDesc */
993995

@@ -1026,7 +1028,7 @@ tuplesort_begin_cluster(TupleDesc tupDesc,
10261028
(scanKey->sk_flags & SK_BT_NULLS_FIRST) != 0;
10271029
sortKey->ssup_attno = scanKey->sk_attno;
10281030
/* Convey if abbreviation optimization is applicable in principle */
1029-
sortKey->abbreviate = (i == 0);
1031+
sortKey->abbreviate = (i == 0 && leading != 0);
10301032

10311033
AssertState(sortKey->ssup_attno != 0);
10321034

src/test/regress/expected/cluster.out

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -511,6 +511,13 @@ SELECT * FROM clstr_expression WHERE -a = -3 ORDER BY -a, b;
511511
COMMIT;
512512
-- and after clustering on clstr_expression_minus_a
513513
CLUSTER clstr_expression USING clstr_expression_minus_a;
514+
WITH rows AS
515+
(SELECT ctid, lag(a) OVER (ORDER BY ctid) AS la, a FROM clstr_expression)
516+
SELECT * FROM rows WHERE la < a;
517+
ctid | la | a
518+
------+----+---
519+
(0 rows)
520+
514521
BEGIN;
515522
SET LOCAL enable_seqscan = false;
516523
EXPLAIN (COSTS OFF) SELECT * FROM clstr_expression WHERE upper(b) = 'PREFIX3';
@@ -545,6 +552,13 @@ SELECT * FROM clstr_expression WHERE -a = -3 ORDER BY -a, b;
545552
COMMIT;
546553
-- and after clustering on clstr_expression_upper_b
547554
CLUSTER clstr_expression USING clstr_expression_upper_b;
555+
WITH rows AS
556+
(SELECT ctid, lag(b) OVER (ORDER BY ctid) AS lb, b FROM clstr_expression)
557+
SELECT * FROM rows WHERE upper(lb) > upper(b);
558+
ctid | lb | b
559+
------+----+---
560+
(0 rows)
561+
548562
BEGIN;
549563
SET LOCAL enable_seqscan = false;
550564
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
@@ -245,6 +245,9 @@ COMMIT;
245245

246246
-- and after clustering on clstr_expression_minus_a
247247
CLUSTER clstr_expression USING clstr_expression_minus_a;
248+
WITH rows AS
249+
(SELECT ctid, lag(a) OVER (ORDER BY ctid) AS la, a FROM clstr_expression)
250+
SELECT * FROM rows WHERE la < a;
248251
BEGIN;
249252
SET LOCAL enable_seqscan = false;
250253
EXPLAIN (COSTS OFF) SELECT * FROM clstr_expression WHERE upper(b) = 'PREFIX3';
@@ -255,6 +258,9 @@ COMMIT;
255258

256259
-- and after clustering on clstr_expression_upper_b
257260
CLUSTER clstr_expression USING clstr_expression_upper_b;
261+
WITH rows AS
262+
(SELECT ctid, lag(b) OVER (ORDER BY ctid) AS lb, b FROM clstr_expression)
263+
SELECT * FROM rows WHERE upper(lb) > upper(b);
258264
BEGIN;
259265
SET LOCAL enable_seqscan = false;
260266
EXPLAIN (COSTS OFF) SELECT * FROM clstr_expression WHERE upper(b) = 'PREFIX3';

0 commit comments

Comments
 (0)