Skip to content

Commit c28394d

Browse files
authored
Merge pull request #791 from FgForrest/master-789
fix: Ordering referenced entities by reference attribute inside `inScope` container doesn't work
2 parents 228aa11 + 6ae1b63 commit c28394d

File tree

3 files changed

+47
-10
lines changed

3 files changed

+47
-10
lines changed

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

+2-6
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.
@@ -130,10 +130,6 @@ public class OrderByVisitor implements ConstraintVisitor, LocaleProvider {
130130
* Contemporary stack for auxiliary data resolved for each level of the query.
131131
*/
132132
private final Deque<ProcessingScope> scope = new ArrayDeque<>(16);
133-
/**
134-
* Contains the created sorter from the ordering query source tree.
135-
*/
136-
private final Deque<Sorter> sorters = new ArrayDeque<>(16);
137133

138134
public OrderByVisitor(
139135
@Nonnull QueryPlanningContext queryContext,
@@ -175,7 +171,7 @@ public OrderByVisitor(
175171
null,
176172
attributeSchemaAccessor,
177173
EntityAttributeExtractor.INSTANCE,
178-
this.sorters
174+
new ArrayDeque<>(16)
179175
)
180176
);
181177
}

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

+28-2
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.
@@ -60,6 +60,7 @@
6060
import io.evitadb.core.query.sort.translator.OrderByTranslator;
6161
import io.evitadb.core.query.sort.translator.OrderInScopeTranslator;
6262
import io.evitadb.core.query.sort.translator.ReferenceOrderingConstraintTranslator;
63+
import io.evitadb.dataType.Scope;
6364
import io.evitadb.exception.GenericEvitaInternalError;
6465
import io.evitadb.index.EntityIndex;
6566
import io.evitadb.index.EntityIndexKey;
@@ -73,9 +74,12 @@
7374

7475
import javax.annotation.Nonnull;
7576
import javax.annotation.Nullable;
77+
import java.util.ArrayDeque;
78+
import java.util.Deque;
7679
import java.util.Map;
7780
import java.util.Objects;
7881
import java.util.Optional;
82+
import java.util.Set;
7983

8084
import static io.evitadb.utils.Assert.isPremiseValid;
8185
import static java.util.Optional.ofNullable;
@@ -137,6 +141,10 @@ public class ReferenceOrderByVisitor implements ConstraintVisitor, FetchRequirem
137141
* This variable is internally updated during the traversal and comparison of constraints.
138142
*/
139143
@Nullable private ChainIndex lastRetrievedChainIndex;
144+
/**
145+
* Contemporary stack for scopes used on each level of the ordering query tree.
146+
*/
147+
private final Deque<Set<Scope>> scope = new ArrayDeque<>(16);
140148

141149
/**
142150
* Extracts {@link OrderingDescriptor} from the passed `orderBy` constraint using passed `queryContext` for
@@ -274,7 +282,7 @@ public NamedSchemaContract getAttributeSchemaOrSortableAttributeCompound(
274282
@Nonnull String attributeName
275283
) {
276284
return attributeSchemaAccessor.getAttributeSchemaOrSortableAttributeCompound(
277-
attributeName, this.getScopes()
285+
attributeName, this.scope.isEmpty() ? this.getScopes() : this.scope.peek()
278286
);
279287
}
280288

@@ -369,6 +377,24 @@ public Optional<ChainIndex> getChainIndex(
369377
}
370378
}
371379

380+
/**
381+
* Executes the given {@link Runnable} within the context of the specified {@link Scope scopes}.
382+
* The method temporarily pushes the provided scopes to the current scope stack,
383+
* executes the runnable, and ensures the stack is restored to its previous state
384+
* afterward, even if the runnable throws an exception.
385+
*
386+
* @param scopesToUse the set of scopes to apply during the execution of the runnable
387+
* @param runnable the code to be executed within the given scopes
388+
*/
389+
public void doWithScope(@Nonnull Set<Scope> scopesToUse, @Nonnull Runnable runnable) {
390+
try {
391+
this.scope.push(scopesToUse);
392+
runnable.run();
393+
} finally {
394+
this.scope.pop();
395+
}
396+
}
397+
372398
/**
373399
* DTO record enveloping comparators both for attributes on reference itself and the referenced entity.
374400
* Currently, the sorting allows to use only simple ordering constraints either on reference attributes or

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

+17-2
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.
@@ -68,7 +68,22 @@ public Stream<Sorter> createSorter(@Nonnull OrderInScope inScope, @Nonnull Order
6868

6969
@Override
7070
public void createComparator(@Nonnull OrderInScope inScope, @Nonnull ReferenceOrderByVisitor orderByVisitor) {
71-
// do nothing
71+
final Set<Scope> requestedScopes = orderByVisitor.getScopes();
72+
final Scope scopeToUse = inScope.getScope();
73+
Assert.isTrue(
74+
requestedScopes.contains(scopeToUse),
75+
"Scope `" + scopeToUse + "` used in `inScope` order container was not requested by `scope` constraint!"
76+
);
77+
78+
// process inner constraints
79+
orderByVisitor.doWithScope(
80+
Set.of(scopeToUse),
81+
() -> {
82+
for (OrderConstraint innerConstraint : inScope.getChildren()) {
83+
innerConstraint.accept(orderByVisitor);
84+
}
85+
}
86+
);
7287
}
7388

7489
}

0 commit comments

Comments
 (0)