Skip to content

Commit c9d608b

Browse files
authored
Merge pull request #785 from FgForrest/master-hotfix
Master hotfix
2 parents cb1f80a + 39c05c1 commit c9d608b

File tree

4 files changed

+50
-21
lines changed

4 files changed

+50
-21
lines changed

evita_engine/src/main/java/io/evitadb/core/query/sort/CacheableSorter.java

+3-3
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@
66
* | __/\ V /| | || (_| | |_| | |_) |
77
* \___| \_/ |_|\__\__,_|____/|____/
88
*
9-
* Copyright (c) 2023-2024
9+
* Copyright (c) 2023-2025
1010
*
1111
* Licensed under the Business Source License, Version 1.1 (the "License");
1212
* you may not use this file except in compliance with the License.
@@ -25,7 +25,7 @@
2525

2626
import io.evitadb.api.requestResponse.EvitaResponseExtraResult;
2727
import io.evitadb.core.cache.payload.CachePayloadHeader;
28-
import io.evitadb.core.query.QueryPlanningContext;
28+
import io.evitadb.core.query.QueryExecutionContext;
2929
import io.evitadb.core.query.algebra.Formula;
3030
import io.evitadb.core.query.response.TransactionalDataRelatedStructure;
3131
import io.evitadb.core.query.sort.SortedRecordsSupplierFactory.SortedRecordsProvider;
@@ -60,7 +60,7 @@ public interface CacheableSorter extends TransactionalDataRelatedStructure, Sort
6060

6161
/**
6262
* Returns copy of this computer with same configuration but new method handle that references callback that
63-
* will be called when {@link #sortAndSlice(QueryPlanningContext, Formula, int, int, int[], int)} method is first executed
63+
* will be called when {@link #sortAndSlice(QueryExecutionContext, Formula, int, int, int[], int)} method is first executed
6464
* and memoized result is available.
6565
*/
6666
@Nonnull

evita_engine/src/main/java/io/evitadb/core/query/sort/DeferredSorter.java

+11-5
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@
66
* | __/\ V /| | || (_| | |_| | |_) |
77
* \___| \_/ |_|\__\__,_|____/|____/
88
*
9-
* Copyright (c) 2023-2024
9+
* Copyright (c) 2023-2025
1010
*
1111
* Licensed under the Business Source License, Version 1.1 (the "License");
1212
* you may not use this file except in compliance with the License.
@@ -72,9 +72,15 @@ public int sortAndSlice(
7272
int peak,
7373
@Nullable IntConsumer skippedRecordsConsumer
7474
) {
75-
return executionWrapper.applyAsInt(
76-
() -> ConditionalSorter.getFirstApplicableSorter(queryContext, sorter)
77-
.sortAndSlice(queryContext, input, startIndex, endIndex, result, peak, skippedRecordsConsumer)
78-
);
75+
final Sorter firstApplicableSorter = ConditionalSorter.getFirstApplicableSorter(queryContext, sorter);
76+
if (firstApplicableSorter == null) {
77+
return 0;
78+
} else {
79+
return executionWrapper.applyAsInt(
80+
() -> firstApplicableSorter.sortAndSlice(
81+
queryContext, input, startIndex, endIndex, result, peak, skippedRecordsConsumer
82+
)
83+
);
84+
}
7985
}
8086
}

evita_engine/src/main/java/io/evitadb/core/query/sort/attribute/MergedSortedRecordsSupplier.java

+31-8
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@
66
* | __/\ V /| | || (_| | |_| | |_) |
77
* \___| \_/ |_|\__\__,_|____/|____/
88
*
9-
* Copyright (c) 2023-2024
9+
* Copyright (c) 2023-2025
1010
*
1111
* Licensed under the Business Source License, Version 1.1 (the "License");
1212
* you may not use this file except in compliance with the License.
@@ -34,6 +34,7 @@
3434
import io.evitadb.index.bitmap.Bitmap;
3535
import io.evitadb.index.bitmap.RoaringBitmapBackedBitmap;
3636
import lombok.Getter;
37+
import lombok.RequiredArgsConstructor;
3738
import org.roaringbitmap.BatchIterator;
3839
import org.roaringbitmap.RoaringBatchIterator;
3940
import org.roaringbitmap.RoaringBitmap;
@@ -91,12 +92,14 @@ private static PartialSortResult fetchSlice(
9192

9293
// skip previous pages quickly
9394
if (toSkip > 0) {
94-
toSkip -= bufferPeak;
95-
}
96-
if (skippedRecordsConsumer != null && skip > 0) {
97-
for (int i = 0; i < bufferPeak + toSkip; i++) {
98-
skippedRecordsConsumer.accept(preSortedRecordIds[buffer[i]]);
95+
if (skippedRecordsConsumer != null) {
96+
// skip records in buffer, cap really read records in the buffer
97+
final int skippedInBuffer = Math.max(0, Math.min(toSkip, bufferPeak));
98+
for (int i = 0; i < skippedInBuffer; i++) {
99+
skippedRecordsConsumer.accept(preSortedRecordIds[buffer[i]]);
100+
}
99101
}
102+
toSkip -= bufferPeak;
100103
}
101104

102105
// now we are on the page
@@ -235,13 +238,15 @@ public int sortAndSlice(
235238
} else {
236239
final int[] buffer = queryContext.borrowBuffer();
237240
try {
241+
final SkippingRecordConsumer delegateConsumer = new SkippingRecordConsumer(skippedRecordsConsumer);
238242
final SortResult sortResult = collectPartialResults(
239-
queryContext, selectedRecordIds, startIndex, endIndex, result, peak, buffer, skippedRecordsConsumer
243+
queryContext, selectedRecordIds, startIndex, endIndex, result, peak, buffer, delegateConsumer
240244
);
241245
return returnResultAppendingUnknown(
242246
queryContext, sortResult.notSortedRecords(),
243247
unknownRecordIdsSorter,
244-
startIndex, endIndex,
248+
Math.max(0, startIndex - delegateConsumer.getCounter()),
249+
Math.max(0, endIndex - delegateConsumer.getCounter()),
245250
result, sortResult.peak(), buffer
246251
);
247252
} finally {
@@ -336,4 +341,22 @@ private record SortResult(
336341
) {
337342
}
338343

344+
/**
345+
* The SkippingRecordConsumer is an implementation of the {@link IntConsumer} interface that wraps an optional delegate
346+
* {@code IntConsumer} and tracks the count of records processed. This class is intended to be used for scenarios
347+
* where certain records need to be tracked, possibly skipped, or processed with optional side effects.
348+
*/
349+
@RequiredArgsConstructor
350+
private static class SkippingRecordConsumer implements IntConsumer {
351+
@Nullable private final IntConsumer delegate;
352+
@Getter private int counter = 0;
353+
354+
@Override
355+
public void accept(int value) {
356+
if (this.delegate != null) {
357+
this.delegate.accept(value);
358+
}
359+
this.counter++;
360+
}
361+
}
339362
}

evita_engine/src/main/java/io/evitadb/core/query/sort/attribute/translator/PredecessorAttributeComparator.java

+5-5
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@
66
* | __/\ V /| | || (_| | |_| | |_) |
77
* \___| \_/ |_|\__\__,_|____/|____/
88
*
9-
* Copyright (c) 2023-2024
9+
* Copyright (c) 2023-2025
1010
*
1111
* Licensed under the Business Source License, Version 1.1 (the "License");
1212
* you may not use this file except in compliance with the License.
@@ -108,16 +108,16 @@ public int compare(EntityContract o1, EntityContract o2) {
108108
break;
109109
}
110110
}
111-
if (!(o1Found || o2Found) && nonSortedEntities == null) {
111+
if (!(o1Found && o2Found) && this.nonSortedEntities == null) {
112112
// if any of the entities is not found, and we don't have the container to store them, create it
113-
nonSortedEntities = new CompositeObjectArray<>(EntityContract.class);
113+
this.nonSortedEntities = new CompositeObjectArray<>(EntityContract.class);
114114
}
115115
// if any of the entities is not found, store it in the container
116116
if (!o1Found) {
117-
nonSortedEntities.add(o1);
117+
this.nonSortedEntities.add(o1);
118118
}
119119
if (!o2Found) {
120-
nonSortedEntities.add(o2);
120+
this.nonSortedEntities.add(o2);
121121
}
122122
// return the result
123123
return result;

0 commit comments

Comments
 (0)