@@ -219,6 +219,8 @@ struct Tuplesortstate
219
219
* tuples to return? */
220
220
bool boundUsed ;/* true if we made use of a bounded heap */
221
221
int bound ;/* if bounded, the maximum number of tuples */
222
+ int prefix ;/* number of prefix keys by which input data is already sorted */
223
+ int matchedKeys ;/* number of matched keys */
222
224
int64 availMem ;/* remaining memory available, in bytes */
223
225
int64 allowedMem ;/* total memory allowed, in bytes */
224
226
int maxTapes ;/* number of tapes (Knuth's T) */
@@ -458,7 +460,7 @@ struct Tuplesortstate
458
460
459
461
460
462
static Tuplesortstate * tuplesort_begin_common (int workMem ,bool randomAccess );
461
- static void puttuple_common (Tuplesortstate * state ,SortTuple * tuple );
463
+ static bool puttuple_common (Tuplesortstate * state ,SortTuple * tuple );
462
464
static bool consider_abort_common (Tuplesortstate * state );
463
465
static void inittapes (Tuplesortstate * state );
464
466
static void selectnewtape (Tuplesortstate * state );
@@ -575,7 +577,7 @@ tuplesort_begin_common(int workMem, bool randomAccess)
575
577
state -> availMem = state -> allowedMem ;
576
578
state -> sortcontext = sortcontext ;
577
579
state -> tapeset = NULL ;
578
-
580
+ state -> prefix = 0 ;
579
581
state -> memtupcount = 0 ;
580
582
581
583
/*
@@ -613,7 +615,7 @@ tuplesort_begin_heap(TupleDesc tupDesc,
613
615
int nkeys ,AttrNumber * attNums ,
614
616
Oid * sortOperators ,Oid * sortCollations ,
615
617
bool * nullsFirstFlags ,
616
- int workMem ,bool randomAccess )
618
+ int workMem ,bool randomAccess , int prefix )
617
619
{
618
620
Tuplesortstate * state = tuplesort_begin_common (workMem ,randomAccess );
619
621
MemoryContext oldcontext ;
@@ -648,6 +650,7 @@ tuplesort_begin_heap(TupleDesc tupDesc,
648
650
649
651
/* Prepare SortSupport data for each column */
650
652
state -> sortKeys = (SortSupport )palloc0 (nkeys * sizeof (SortSupportData ));
653
+ state -> prefix = prefix ;
651
654
652
655
for (i = 0 ;i < nkeys ;i ++ )
653
656
{
@@ -1202,21 +1205,22 @@ grow_memtuples(Tuplesortstate *state)
1202
1205
*
1203
1206
* Note that the input data is always copied; the caller need not save it.
1204
1207
*/
1205
- void
1208
+ bool
1206
1209
tuplesort_puttupleslot (Tuplesortstate * state ,TupleTableSlot * slot )
1207
1210
{
1208
1211
MemoryContext oldcontext = MemoryContextSwitchTo (state -> sortcontext );
1209
1212
SortTuple stup ;
1210
-
1213
+ bool needmore ;
1211
1214
/*
1212
1215
* Copy the given tuple into memory we control, and decrease availMem.
1213
1216
* Then call the common code.
1214
1217
*/
1215
1218
COPYTUP (state ,& stup , (void * )slot );
1216
1219
1217
- puttuple_common (state ,& stup );
1220
+ needmore = puttuple_common (state ,& stup );
1218
1221
1219
1222
MemoryContextSwitchTo (oldcontext );
1223
+ return needmore ;
1220
1224
}
1221
1225
1222
1226
/*
@@ -1397,7 +1401,7 @@ tuplesort_putdatum(Tuplesortstate *state, Datum val, bool isNull)
1397
1401
/*
1398
1402
* Shared code for tuple and datum cases.
1399
1403
*/
1400
- static void
1404
+ static bool
1401
1405
puttuple_common (Tuplesortstate * state ,SortTuple * tuple )
1402
1406
{
1403
1407
switch (state -> status )
@@ -1441,14 +1445,14 @@ puttuple_common(Tuplesortstate *state, SortTuple *tuple)
1441
1445
pg_rusage_show (& state -> ru_start ));
1442
1446
#endif
1443
1447
make_bounded_heap (state );
1444
- return ;
1448
+ break ;
1445
1449
}
1446
1450
1447
1451
/*
1448
1452
* Done if we still fit in available memory and have array slots.
1449
1453
*/
1450
1454
if (state -> memtupcount < state -> memtupsize && !LACKMEM (state ))
1451
- return ;
1455
+ break ;
1452
1456
1453
1457
/*
1454
1458
* Nope; time to switch to tape-based operation.
@@ -1475,6 +1479,9 @@ puttuple_common(Tuplesortstate *state, SortTuple *tuple)
1475
1479
{
1476
1480
/* new tuple <= top of the heap, so we can discard it */
1477
1481
free_sort_tuple (state ,tuple );
1482
+ if (state -> prefix > state -> matchedKeys && state -> memtupcount >=state -> bound ) {
1483
+ return false;
1484
+ }
1478
1485
CHECK_FOR_INTERRUPTS ();
1479
1486
}
1480
1487
else
@@ -1517,6 +1524,7 @@ puttuple_common(Tuplesortstate *state, SortTuple *tuple)
1517
1524
elog (ERROR ,"invalid tuplesort state" );
1518
1525
break ;
1519
1526
}
1527
+ return true;
1520
1528
}
1521
1529
1522
1530
static bool
@@ -3071,19 +3079,20 @@ comparetup_heap(const SortTuple *a, const SortTuple *b, Tuplesortstate *state)
3071
3079
HeapTupleData rtup ;
3072
3080
TupleDesc tupDesc ;
3073
3081
int nkey ;
3074
- int32 compare ;
3082
+ int32 compare = 0 ;
3075
3083
AttrNumber attno ;
3076
3084
Datum datum1 ,
3077
3085
datum2 ;
3078
3086
bool isnull1 ,
3079
3087
isnull2 ;
3080
3088
3089
+ state -> matchedKeys = 0 ;
3081
3090
3082
3091
/* Compare the leading sort key */
3083
3092
compare = ApplySortComparator (a -> datum1 ,a -> isnull1 ,
3084
3093
b -> datum1 ,b -> isnull1 ,
3085
3094
sortKey );
3086
- if (compare != 0 )
3095
+ if (compare != 0 )
3087
3096
return compare ;
3088
3097
3089
3098
/* Compare additional sort keys */
@@ -3119,10 +3128,11 @@ comparetup_heap(const SortTuple *a, const SortTuple *b, Tuplesortstate *state)
3119
3128
datum2 ,isnull2 ,
3120
3129
sortKey );
3121
3130
if (compare != 0 )
3122
- return compare ;
3131
+ break ;
3123
3132
}
3133
+ state -> matchedKeys = nkey ;
3124
3134
3125
- return 0 ;
3135
+ return compare ;
3126
3136
}
3127
3137
3128
3138
static void