Skip to content

Commit

Permalink
Merge pull request #715 from FgForrest/2024-11-patch
Browse files Browse the repository at this point in the history
Fix patch
  • Loading branch information
novoj authored Oct 24, 2024
2 parents 80ab0e4 + 909701f commit 70ba229
Show file tree
Hide file tree
Showing 58 changed files with 1,462 additions and 491 deletions.
117 changes: 99 additions & 18 deletions .idea/compiler.xml

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

Original file line number Diff line number Diff line change
Expand Up @@ -78,6 +78,7 @@ public class EvitaRequest {
throw new UnsupportedOperationException();
};
private static final int[] EMPTY_INTS = new int[0];
private static final String[] EMPTY_PRICE_LISTS = new String[0];
@Getter private final Query query;
@Getter private final OffsetDateTime alignedNow;
private final String entityType;
Expand Down Expand Up @@ -577,15 +578,15 @@ public PriceContentMode getRequiresEntityPrices() {
final EntityFetch entityFetch = QueryUtils.findRequire(query, EntityFetch.class, SeparateEntityContentRequireContainer.class);
if (entityFetch == null) {
this.entityPrices = PriceContentMode.NONE;
this.additionalPriceLists = PriceContent.EMPTY_PRICE_LISTS;
this.additionalPriceLists = EMPTY_PRICE_LISTS;
} else {
final Optional<PriceContent> priceContentRequirement = ofNullable(QueryUtils.findConstraint(entityFetch, PriceContent.class, SeparateEntityContentRequireContainer.class));
this.entityPrices = priceContentRequirement
.map(PriceContent::getFetchMode)
.orElse(PriceContentMode.NONE);
this.additionalPriceLists = priceContentRequirement
.map(PriceContent::getAdditionalPriceListsToFetch)
.orElse(PriceContent.EMPTY_PRICE_LISTS);
.orElse(EMPTY_PRICE_LISTS);
}
}
return this.entityPrices;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@
* | __/\ V /| | || (_| | |_| | |_) |
* \___| \_/ |_|\__\__,_|____/|____/
*
* Copyright (c) 2023
* Copyright (c) 2024
*
* Licensed under the Business Source License, Version 1.1 (the "License");
* you may not use this file except in compliance with the License.
Expand All @@ -21,28 +21,23 @@
* limitations under the License.
*/

package io.evitadb.api.query.require;
package io.evitadb.core.query;

import io.evitadb.api.query.EntityConstraint;
import io.evitadb.api.query.RequireConstraint;

import javax.annotation.Nonnull;
import javax.annotation.Nullable;

/**
* Ancestor for all requirement containers that serves as entity richness definers.
* Interface allowing to exclude implementation of {@link #isPrefetchPossible()} from automatic delegation in query
* context. Provides information whether it's possible and safe to use prefetched entities (or prefetch them) in specific
* context.
*
* @author Lukáš Hornych, FG Forrest a.s. (c) 2022
* @author Jan Novotný (novotny@fg.cz), FG Forrest a.s. (c) 2024
*/
public interface EntityRequire extends EntityConstraint<RequireConstraint>, RequireConstraint {

@Nonnull
EntityContentRequire[] getRequirements();
public interface PrefetchStrategyResolver {

/**
* Method allows to combine two requirements of same type (that needs to be compatible with "this" type) into one
* combining the arguments of both of them.
* Returns true if the prefetch is possible.
*
* @return true if the prefetch is possible
*/
@Nonnull
<T extends EntityRequire> T combineWith(@Nullable T anotherRequirement);
boolean isPrefetchPossible();

}
Original file line number Diff line number Diff line change
Expand Up @@ -24,13 +24,13 @@
package io.evitadb.core.query;

import io.evitadb.api.query.require.EntityContentRequire;
import io.evitadb.api.query.require.FetchRequirementCollector;
import io.evitadb.core.metric.event.query.FinishedEvent;
import io.evitadb.core.query.algebra.Formula;
import io.evitadb.core.query.algebra.base.EmptyFormula;
import io.evitadb.core.query.algebra.prefetch.PrefetchFactory;
import io.evitadb.core.query.algebra.prefetch.PrefetchFormulaVisitor;
import io.evitadb.core.query.extraResult.ExtraResultProducer;
import io.evitadb.core.query.fetch.FetchRequirementCollector;
import io.evitadb.core.query.filter.FilterByVisitor;
import io.evitadb.core.query.indexSelection.TargetIndexes;
import io.evitadb.core.query.sort.NoSorter;
Expand Down Expand Up @@ -101,8 +101,14 @@ public static QueryPlan empty(@Nonnull QueryPlanningContext queryContext) {
}

@Override
public void addRequirementToPrefetch(@Nonnull EntityContentRequire... require) {
prefetchFormulaVisitor.addRequirement(require);
public void addRequirementsToPrefetch(@Nonnull EntityContentRequire... require) {
this.queryContext.addRequirementToPrefetch(require);
}

@Nonnull
@Override
public EntityContentRequire[] getRequirementsToPrefetch() {
return this.queryContext.getRequirementsToPrefetch();
}

/**
Expand Down Expand Up @@ -151,10 +157,16 @@ public void appendExtraResultProducers(@Nonnull Collection<ExtraResultProducer>
public QueryPlan build() {
ofNullable(queryContext.getQueryFinishedEvent())
.ifPresent(FinishedEvent::startExecuting);
// propagate all collected requirements to the prefetch formula visitor
this.prefetchFormulaVisitor.addRequirement(
this.queryContext.getRequirementsToPrefetch()
);
return new QueryPlan(
queryContext,
targetIndexes.getIndexDescription(), filterFormula, prefetchFormulaVisitor,
sorter, extraResultProducers
this.queryContext,
this.targetIndexes.getIndexDescription(),
this.filterFormula,
this.prefetchFormulaVisitor,
this.sorter, extraResultProducers
);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -348,7 +348,7 @@ private static void createSorter(
}
try {
final OrderByVisitor orderByVisitor = new OrderByVisitor(
queryContext, targetIndexes, builder,
queryContext, targetIndexes,
builder.getFilterByVisitor(),
builder.getFilterFormula()
);
Expand Down Expand Up @@ -408,7 +408,6 @@ private static void createExtraResultProducers(
final ExtraResultPlanningVisitor extraResultPlanner = new ExtraResultPlanningVisitor(
queryContext,
builder.getTargetIndexes(),
builder,
builder.getFilterFormula(),
builder.getFilterByVisitor(),
builder.getSorter()
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -32,10 +32,13 @@
import io.evitadb.api.query.Query;
import io.evitadb.api.query.RequireConstraint;
import io.evitadb.api.query.require.DebugMode;
import io.evitadb.api.query.require.DefaultPrefetchRequirementCollector;
import io.evitadb.api.query.require.EntityContentRequire;
import io.evitadb.api.query.require.EntityFetchRequire;
import io.evitadb.api.query.require.FacetGroupsConjunction;
import io.evitadb.api.query.require.FacetGroupsDisjunction;
import io.evitadb.api.query.require.FacetGroupsNegation;
import io.evitadb.api.query.require.FetchRequirementCollector;
import io.evitadb.api.query.require.QueryPriceMode;
import io.evitadb.api.requestResponse.EvitaRequest;
import io.evitadb.api.requestResponse.EvitaRequest.FacetFilterBy;
Expand Down Expand Up @@ -98,13 +101,18 @@
*
* @author Jan Novotný (novotny@fg.cz), FG Forrest a.s. (c) 2022
*/
public class QueryPlanningContext implements LocaleProvider {
public class QueryPlanningContext implements LocaleProvider, PrefetchStrategyResolver {
private static final EntityIndexKey GLOBAL_INDEX_KEY = new EntityIndexKey(EntityIndexType.GLOBAL);

/**
* Contains reference to the parent context of this one. The reference is not NULL only for sub-queries.
*/
@Nullable private final QueryPlanningContext parentContext;
/**
* Reference to the collector of requirements for entity prefetch phase.
*/
@Nonnull @Getter
private final FetchRequirementCollector fetchRequirementCollector = new DefaultPrefetchRequirementCollector();
/**
* Contains reference to the policy that controls the interaction with cache and drives the query planning strategy.
*/
Expand Down Expand Up @@ -286,19 +294,34 @@ private <S extends IndexKey, T extends Index<S>> QueryPlanningContext(
}

/**
* Returns true if the input {@link #evitaRequest} contains specification of the entity collection.
* Delegates method to {@link FetchRequirementCollector#addRequirementsToPrefetch(EntityContentRequire...)}.
*
* @param require the requirement to prefetch
*/
public boolean isEntityTypeKnown() {
return entityType != null;
public void addRequirementToPrefetch(@Nonnull EntityContentRequire... require) {
this.fetchRequirementCollector.addRequirementsToPrefetch(require);
}

/**
* Returns true if the prefetch is possible.
* Delegates method to {@link FetchRequirementCollector#getRequirementsToPrefetch()}.
*
* @return true if the prefetch is possible
* @return an array of {@link EntityContentRequire} representing the requirements to prefetch
*/
@Nonnull
public EntityContentRequire[] getRequirementsToPrefetch() {
return this.fetchRequirementCollector.getRequirementsToPrefetch();
}

/**
* Returns true if the input {@link #evitaRequest} contains specification of the entity collection.
*/
public boolean isEntityTypeKnown() {
return entityType != null;
}

@Override
public boolean isPrefetchPossible() {
return prefetchPossible && planningPolicy.getPrefetchPolicy() == PrefetchPolicy.ALLOW;
return this.prefetchPossible && this.planningPolicy.getPrefetchPolicy() == PrefetchPolicy.ALLOW;
}

/**
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,7 @@
import io.evitadb.api.query.order.EntityGroupProperty;
import io.evitadb.api.query.order.EntityProperty;
import io.evitadb.api.query.order.OrderBy;
import io.evitadb.api.query.require.DefaultPrefetchRequirementCollector;
import io.evitadb.api.query.require.EntityFetch;
import io.evitadb.api.query.require.HierarchyContent;
import io.evitadb.api.query.require.ManagedReferencesBehaviour;
Expand Down Expand Up @@ -66,7 +67,6 @@
import io.evitadb.core.query.algebra.base.EmptyFormula;
import io.evitadb.core.query.algebra.utils.FormulaFactory;
import io.evitadb.core.query.extraResult.translator.hierarchyStatistics.AbstractHierarchyTranslator.TraversalDirection;
import io.evitadb.core.query.fetch.DefaultPrefetchRequirementCollector;
import io.evitadb.core.query.filter.FilterByVisitor;
import io.evitadb.core.query.filter.FilterByVisitor.ProcessingScope;
import io.evitadb.core.query.indexSelection.TargetIndexes;
Expand Down Expand Up @@ -936,7 +936,7 @@ public <T extends SealedEntity> List<T> initReferenceIndex(@Nonnull List<T> enti
.toArray()
);

return richEnoughEntities;
return entities;
}

@Nonnull
Expand Down Expand Up @@ -1055,7 +1055,7 @@ private EvitaRequest prefetchEntities(
final ReferenceSchemaContract referenceSchema = entitySchema.getReferenceOrThrowException(referenceName);
// initialize requirements with requested attributes
if (requirements.attributeContent() != null) {
globalPrefetchCollector.addRequirementToPrefetch(requirements.attributeContent());
globalPrefetchCollector.addRequirementsToPrefetch(requirements.attributeContent());
}

final Optional<OrderingDescriptor> orderingDescriptor = ofNullable(requirements.orderBy())
Expand Down
Loading

0 comments on commit 70ba229

Please sign in to comment.