Skip to content

Commit

Permalink
[Blazebit#725] Test and fix for issues with stripped off select items…
Browse files Browse the repository at this point in the history
… in copied queries. Inlining select alias expressions now
  • Loading branch information
beikov committed Feb 10, 2019
1 parent 8f531aa commit 7cd8bb9
Show file tree
Hide file tree
Showing 5 changed files with 103 additions and 8 deletions.
Expand Up @@ -56,13 +56,15 @@
import com.blazebit.persistence.impl.query.EntityFunctionNode;
import com.blazebit.persistence.impl.query.ObjectBuilderTypedQuery;
import com.blazebit.persistence.impl.query.QuerySpecification;
import com.blazebit.persistence.impl.transform.ExpressionModifierVisitor;
import com.blazebit.persistence.impl.transform.ExpressionTransformerGroup;
import com.blazebit.persistence.impl.transform.OuterFunctionVisitor;
import com.blazebit.persistence.impl.transform.SimpleTransformerGroup;
import com.blazebit.persistence.impl.transform.SizeTransformationVisitor;
import com.blazebit.persistence.impl.transform.SizeTransformerGroup;
import com.blazebit.persistence.impl.transform.SubqueryRecursiveExpressionVisitor;
import com.blazebit.persistence.impl.util.SqlUtils;
import com.blazebit.persistence.parser.AliasReplacementVisitor;
import com.blazebit.persistence.parser.EntityMetamodel;
import com.blazebit.persistence.parser.expression.Expression;
import com.blazebit.persistence.parser.expression.ExpressionFactory;
Expand Down Expand Up @@ -247,7 +249,7 @@ protected AbstractCommonQueryBuilder(AbstractCommonQueryBuilder<QueryResultType,
this.groupByManager = new GroupByManager(queryGenerator, parameterManager, subqueryInitFactory, mainQuery.jpaProvider, this.aliasManager, embeddableSplittingVisitor, groupByExpressionGatheringVisitor);
this.havingManager = new HavingManager<>(queryGenerator, parameterManager, subqueryInitFactory, expressionFactory, groupByExpressionGatheringVisitor);

this.selectManager = new SelectManager<>(queryGenerator, parameterManager, this.joinManager, this.aliasManager, subqueryInitFactory, expressionFactory, mainQuery.jpaProvider, mainQuery, groupByExpressionGatheringVisitor, builder.resultType);
this.selectManager = new SelectManager<>(queryGenerator, parameterManager, this, this.joinManager, this.aliasManager, subqueryInitFactory, expressionFactory, mainQuery.jpaProvider, mainQuery, groupByExpressionGatheringVisitor, builder.resultType);
this.orderByManager = new OrderByManager(queryGenerator, parameterManager, subqueryInitFactory, this.joinManager, this.aliasManager, embeddableSplittingVisitor, functionalDependencyAnalyzerVisitor, mainQuery.metamodel, mainQuery.jpaProvider, groupByExpressionGatheringVisitor);
this.keysetManager = new KeysetManager(this, queryGenerator, parameterManager, mainQuery.jpaProvider, mainQuery.dbmsDialect);

Expand Down Expand Up @@ -317,7 +319,7 @@ protected AbstractCommonQueryBuilder(MainQuery mainQuery, QueryContext queryCont
this.groupByManager = new GroupByManager(queryGenerator, parameterManager, subqueryInitFactory, mainQuery.jpaProvider, this.aliasManager, embeddableSplittingVisitor, groupByExpressionGatheringVisitor);
this.havingManager = new HavingManager<>(queryGenerator, parameterManager, subqueryInitFactory, expressionFactory, groupByExpressionGatheringVisitor);

this.selectManager = new SelectManager<>(queryGenerator, parameterManager, this.joinManager, this.aliasManager, subqueryInitFactory, expressionFactory, mainQuery.jpaProvider, mainQuery, groupByExpressionGatheringVisitor, resultClazz);
this.selectManager = new SelectManager<>(queryGenerator, parameterManager, this, this.joinManager, this.aliasManager, subqueryInitFactory, expressionFactory, mainQuery.jpaProvider, mainQuery, groupByExpressionGatheringVisitor, resultClazz);
this.orderByManager = new OrderByManager(queryGenerator, parameterManager, subqueryInitFactory, this.joinManager, this.aliasManager, embeddableSplittingVisitor, functionalDependencyAnalyzerVisitor, mainQuery.metamodel, mainQuery.jpaProvider, groupByExpressionGatheringVisitor);
this.keysetManager = new KeysetManager(this, queryGenerator, parameterManager, mainQuery.jpaProvider, mainQuery.dbmsDialect);

Expand Down Expand Up @@ -364,7 +366,7 @@ void applyFrom(AbstractCommonQueryBuilder<?, ?, ?, ?, ?> builder, boolean fixedS

selectManager.setDefaultSelect(nodeMapping, builder.selectManager.getSelectInfos());
if (fixedSelect) {
selectManager.unserDefaultSelect();
selectManager.unsetDefaultSelect();
}
// No need to copy the finalSetOperationBuilder as that is only necessary for further builders which isn't possible after copying
collectParameters();
Expand Down Expand Up @@ -1727,6 +1729,26 @@ protected JoinVisitor applyImplicitJoins(JoinVisitor parentVisitor) {
return joinVisitor;
}

void inlineSelectAlias(String selectAlias, Expression expression) {
final AliasReplacementVisitor aliasReplacementVisitor = new AliasReplacementVisitor(expression, selectAlias);
ExpressionModifierVisitor<ExpressionModifier> expressionModifierVisitor = new ExpressionModifierVisitor<ExpressionModifier>() {
@Override
public void visit(ExpressionModifier expressionModifier, ClauseType clauseType) {
Expression expr = expressionModifier.get();
Expression newExpr = expr.accept(aliasReplacementVisitor);
if (expr != newExpr) {
expressionModifier.set(newExpr);
}
}
};
joinManager.apply(expressionModifierVisitor);
selectManager.apply(expressionModifierVisitor);
whereManager.apply(expressionModifierVisitor);
havingManager.apply(expressionModifierVisitor);
groupByManager.apply(expressionModifierVisitor);
orderByManager.apply(expressionModifierVisitor);
}

protected void implicitJoinWhereClause() {
final JoinVisitor joinVisitor = new JoinVisitor(mainQuery, null, joinManager, parameterManager, !mainQuery.jpaProvider.supportsSingleValuedAssociationIdExpressions());
joinVisitor.setJoinRequired(true);
Expand Down
Expand Up @@ -80,6 +80,7 @@ public class SelectManager<T> extends AbstractManager<SelectInfo> {
private final Map<String, Integer> selectAliasToPositionMap = new HashMap<String, Integer>();
private final SelectObjectBuilderEndedListenerImpl selectObjectBuilderEndedListener = new SelectObjectBuilderEndedListenerImpl();
private CaseExpressionBuilderListener caseExpressionBuilderListener;
private final AbstractCommonQueryBuilder<?, ?, ?, ?, ?> queryBuilder;
private final GroupByExpressionGatheringVisitor groupByExpressionGatheringVisitor;
private final JoinManager joinManager;
private final AliasManager aliasManager;
Expand All @@ -89,9 +90,10 @@ public class SelectManager<T> extends AbstractManager<SelectInfo> {
private final Class<?> resultClazz;

@SuppressWarnings("unchecked")
public SelectManager(ResolvingQueryGenerator queryGenerator, ParameterManager parameterManager, JoinManager joinManager, AliasManager aliasManager, SubqueryInitiatorFactory subqueryInitFactory, ExpressionFactory expressionFactory, JpaProvider jpaProvider,
public SelectManager(ResolvingQueryGenerator queryGenerator, ParameterManager parameterManager, AbstractCommonQueryBuilder<?, ?, ?, ?, ?> queryBuilder, JoinManager joinManager, AliasManager aliasManager, SubqueryInitiatorFactory subqueryInitFactory, ExpressionFactory expressionFactory, JpaProvider jpaProvider,
MainQuery mainQuery, GroupByExpressionGatheringVisitor groupByExpressionGatheringVisitor, Class<?> resultClazz) {
super(queryGenerator, parameterManager, subqueryInitFactory);
this.queryBuilder = queryBuilder;
this.groupByExpressionGatheringVisitor = groupByExpressionGatheringVisitor;
this.joinManager = joinManager;
this.aliasManager = aliasManager;
Expand Down Expand Up @@ -539,7 +541,7 @@ boolean isDistinct() {
return this.distinct;
}

void unserDefaultSelect() {
void unsetDefaultSelect() {
hasDefaultSelect = false;
}

Expand All @@ -550,6 +552,9 @@ private void clearDefaultSelects() {

for (int i = 0; i < selectInfos.size(); i++) {
SelectInfo selectInfo = selectInfos.get(i);
if (selectInfo.getAlias() != null) {
queryBuilder.inlineSelectAlias(selectInfo.getAlias(), selectInfo.getExpression());
}
aliasManager.unregisterAliasInfoForBottomLevel(selectInfo);
unregisterParameterExpressions(selectInfo.getExpression());
}
Expand Down
Expand Up @@ -69,10 +69,17 @@ public AbstractCorrelatedSubselectTupleListTransformer(ExpressionFactory ef, Cor
super(ef, correlator, viewRootType, embeddingViewType, correlationResult, correlationProviderFactory, attributePath, fetches, viewRootIndex, embeddingViewIndex, tupleIndex, correlationBasisType, correlationBasisEntity, entityViewConfiguration);
this.evm = evm;
this.viewRootAlias = viewRootAlias;
this.viewRootIdExpression = viewRootAlias + "." + getEntityIdName(viewRootType.getEntityClass());
String viewRootAliasPrefix = viewRootAlias + ".";
this.viewRootIdExpression = viewRootAliasPrefix + getEntityIdName(viewRootType.getEntityClass());
this.viewRootIdMapperCount = viewIdMapperCount(viewRootType);
this.embeddingViewPath = embeddingViewPath;
this.embeddingViewIdExpression = viewRootAlias.equals(embeddingViewPath) ? viewRootAlias + "." + getEntityIdName(embeddingViewType.getEntityClass()) : viewRootAlias + "." + embeddingViewPath + "." + getEntityIdName(embeddingViewType.getEntityClass());
if (viewRootAlias.equals(embeddingViewPath)) {
this.embeddingViewIdExpression = viewRootAliasPrefix + getEntityIdName(embeddingViewType.getEntityClass());
} else if (embeddingViewPath.startsWith(viewRootAliasPrefix)) {
this.embeddingViewIdExpression = embeddingViewPath + "." + getEntityIdName(embeddingViewType.getEntityClass());
} else {
this.embeddingViewIdExpression = viewRootAlias + "." + embeddingViewPath + "." + getEntityIdName(embeddingViewType.getEntityClass());
}
this.embeddingViewIdMapperCount = viewIdMapperCount(embeddingViewType);
this.maximumViewMapperCount = Math.max(1, Math.max(viewRootIdMapperCount, embeddingViewIdMapperCount));
this.correlationBasisExpression = correlationBasisExpression;
Expand Down
Expand Up @@ -26,9 +26,11 @@
import com.blazebit.persistence.view.EntityViewManager;
import com.blazebit.persistence.view.EntityViewSetting;
import com.blazebit.persistence.view.EntityViews;
import com.blazebit.persistence.view.Sorters;
import com.blazebit.persistence.view.spi.EntityViewConfiguration;
import com.blazebit.persistence.view.testsuite.AbstractEntityViewTest;
import com.blazebit.persistence.view.testsuite.fetch.subview.model.DocumentSelectSubviewTestView;
import com.blazebit.persistence.view.testsuite.fetch.subview.model.DocumentSubselectSubviewTestView;
import com.blazebit.persistence.view.testsuite.fetch.subview.model.PersonSelectSubview;
import org.junit.Before;
import org.junit.Test;
Expand Down Expand Up @@ -80,7 +82,7 @@ public void setUp() {
@Test
// NOTE: Eclipselink and Datanucleus don't support the single valued id access optimization which causes a cyclic join dependency
@Category({ NoDatanucleus.class, NoOpenJPA.class, NoEclipselink.class })
public void testSubqueryFetch() {
public void testSubqueryFetchOptional() {
EntityViewConfiguration cfg = EntityViews.createDefaultConfiguration();
cfg.addEntityView(DocumentSelectSubviewTestView.class);
cfg.addEntityView(PersonSelectSubview.class);
Expand All @@ -93,4 +95,21 @@ public void testSubqueryFetch() {

assertEquals(1, results.size());
}

@Test
// NOTE: Eclipselink and Datanucleus don't support the single valued id access optimization which causes a cyclic join dependency
@Category({ NoDatanucleus.class, NoOpenJPA.class, NoEclipselink.class })
public void testSubselectFetchWithSorter() {
EntityViewConfiguration cfg = EntityViews.createDefaultConfiguration();
cfg.addEntityView(DocumentSubselectSubviewTestView.class);
EntityViewManager evm = cfg.createEntityViewManager(cbf);

CriteriaBuilder<Document> criteria = cbf.create(em, Document.class, "d").orderByAsc("id");
EntityViewSetting<DocumentSubselectSubviewTestView, CriteriaBuilder<DocumentSubselectSubviewTestView>> setting = EntityViewSetting.create(DocumentSubselectSubviewTestView.class);
setting.addAttributeSorter("name", Sorters.ascending());
CriteriaBuilder<DocumentSubselectSubviewTestView> cb = evm.applySetting(setting, criteria);
List<DocumentSubselectSubviewTestView> results = cb.getResultList();

assertEquals(1, results.size());
}
}
@@ -0,0 +1,42 @@
/*
* Copyright 2014 - 2019 Blazebit.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/

package com.blazebit.persistence.view.testsuite.fetch.subview.model;

import com.blazebit.persistence.testsuite.entity.Document;
import com.blazebit.persistence.testsuite.entity.Person;
import com.blazebit.persistence.view.EntityView;
import com.blazebit.persistence.view.FetchStrategy;
import com.blazebit.persistence.view.IdMapping;
import com.blazebit.persistence.view.Mapping;

/**
*
* @author Christian Beikov
* @since 1.4.0
*/
@EntityView(Document.class)
public interface DocumentSubselectSubviewTestView {

@IdMapping
public Long getId();

public String getName();

@Mapping(fetch = FetchStrategy.SUBSELECT)
public Person getOwner();

}

0 comments on commit 7cd8bb9

Please sign in to comment.