Skip to content

Commit

Permalink
Rework expression modifier and transformer pipeline, Prepare for subs…
Browse files Browse the repository at this point in the history
…elect fetching
  • Loading branch information
beikov committed Dec 7, 2016
1 parent 9b4b6bf commit 60bbe47
Show file tree
Hide file tree
Showing 71 changed files with 2,016 additions and 1,435 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -55,12 +55,12 @@
import com.blazebit.persistence.impl.query.DefaultQuerySpecification;
import com.blazebit.persistence.impl.query.EntityFunctionNode;
import com.blazebit.persistence.impl.query.QuerySpecification;
import com.blazebit.persistence.impl.transform.ExpressionTransformer;
import com.blazebit.persistence.impl.transform.ExpressionTransformerGroup;
import com.blazebit.persistence.impl.transform.OuterFunctionTransformer;
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.SubqueryRecursiveExpressionTransformer;
import com.blazebit.persistence.impl.transform.SubqueryRecursiveExpressionVisitor;
import com.blazebit.persistence.spi.ConfigurationSource;
import com.blazebit.persistence.spi.DbmsDialect;
import com.blazebit.persistence.spi.DbmsModificationState;
Expand Down Expand Up @@ -156,8 +156,7 @@ public abstract class AbstractCommonQueryBuilder<QueryResultType, BuilderType, S
private boolean needsCheck = true;
private boolean implicitJoinsApplied = false;

private final List<ExpressionTransformer> transformers;
private final List<ExpressionTransformerGroup> transformerGroups;
private final List<ExpressionTransformerGroup<?>> transformerGroups;

/**
* Create flat copy of builder
Expand Down Expand Up @@ -187,7 +186,6 @@ protected AbstractCommonQueryBuilder(AbstractCommonQueryBuilder<QueryResultType,
this.subqueryInitFactory = builder.subqueryInitFactory;
this.aliasManager = builder.aliasManager;
this.expressionFactory = builder.expressionFactory;
this.transformers = builder.transformers;
this.transformerGroups = builder.transformerGroups;
this.resultType = builder.resultType;
}
Expand Down Expand Up @@ -236,20 +234,21 @@ protected AbstractCommonQueryBuilder(MainQuery mainQuery, boolean isMainQuery, D
}
}

this.subqueryInitFactory = new SubqueryInitiatorFactory(mainQuery, this.aliasManager, joinManager);
this.joinManager.setSubqueryInitFactory(subqueryInitFactory);
this.subqueryInitFactory = joinManager.getSubqueryInitFactory();

this.whereManager = new WhereManager<BuilderType>(queryGenerator, parameterManager, subqueryInitFactory, expressionFactory);
this.havingManager = new HavingManager<BuilderType>(queryGenerator, parameterManager, subqueryInitFactory, expressionFactory);
this.groupByManager = new GroupByManager(queryGenerator, parameterManager);
this.groupByManager = new GroupByManager(queryGenerator, parameterManager, subqueryInitFactory);

this.selectManager = new SelectManager<QueryResultType>(queryGenerator, parameterManager, this.joinManager, this.aliasManager, subqueryInitFactory, expressionFactory, jpaProvider, resultClazz);
this.orderByManager = new OrderByManager(queryGenerator, parameterManager, this.aliasManager, jpaProvider);
this.orderByManager = new OrderByManager(queryGenerator, parameterManager, subqueryInitFactory, this.aliasManager, jpaProvider);
this.keysetManager = new KeysetManager(queryGenerator, parameterManager);

final SizeTransformationVisitor sizeTransformationVisitor = new SizeTransformationVisitor(mainQuery, subqueryInitFactory, joinManager, groupByManager, dbmsDialect, jpaProvider);
this.transformers = Arrays.asList(new OuterFunctionTransformer(joinManager), new SubqueryRecursiveExpressionTransformer());
this.transformerGroups = Arrays.asList((ExpressionTransformerGroup) new SizeTransformerGroup(sizeTransformationVisitor, orderByManager, selectManager, joinManager, groupByManager));
this.transformerGroups = Arrays.<ExpressionTransformerGroup<?>>asList(
new SimpleTransformerGroup(new OuterFunctionVisitor(joinManager)),
new SimpleTransformerGroup(new SubqueryRecursiveExpressionVisitor()),
new SizeTransformerGroup(sizeTransformationVisitor, orderByManager, selectManager, joinManager, groupByManager));
this.resultType = resultClazz;

this.finalSetOperationBuilder = finalSetOperationBuilder;
Expand Down Expand Up @@ -1360,41 +1359,9 @@ protected void applyVisitor(VisitorAdapter expressionVisitor) {
}

public void applyExpressionTransformers() {
// run through expressions
// for each arrayExpression, look up the alias in the joinManager's aliasMap
// do the transformation using the alias
// exchange old arrayExpression with new PathExpression
// introduce applyTransformer method in managers
// transformer has a method that returns the transformed Expression
// the applyTransformer method will replace the transformed expression with the original one

// Problem we must have the complete (i.e. including array indices) absolute path available during array transformation of a
// path expression
// since the path expression might not be based on the root node
// we must track absolute paths to detect redundancies
// However, the absolute path in the path expression's join node does not contain information about the indices so far but it
// would
// also be a wrong match to add the indices in this structure since there can be multiple indices for the same join path element
// consider d.contacts[l] and d.contacts[x], the absolute join path is d.contacts but this path occurs with two different
// indices
// So where should be store this information or from where should we retrieve it during arrayTransformation?
// i think the answer is: we can't
// d.contacts[1].localized[1]
// d.contacts contacts, contacts.localized localized
// or we remember the already transfomred path in a Set<(BaseNode, RelativePath)> - maybe this would be sufficient
// because access to the same array with two different indices has an empty result set anyway. so if we had basePaths with
// two different indices for the same array we would output the two accesses for the subpath and the access for the current path
// just once (and not once for each distinct subpath)
for (ExpressionTransformer transformer : transformers) {
joinManager.applyTransformer(transformer);
selectManager.applyTransformer(transformer);
whereManager.applyTransformer(transformer);
groupByManager.applyTransformer(transformer);
havingManager.applyTransformer(transformer);
orderByManager.applyTransformer(transformer);
}

for (ExpressionTransformerGroup transformerGroup : transformerGroups) {
int size = transformerGroups.size();
for (int i = 0; i < size; i++) {
ExpressionTransformerGroup transformerGroup = transformerGroups.get(i);
transformerGroup.applyExpressionTransformer(joinManager);
transformerGroup.applyExpressionTransformer(selectManager);
transformerGroup.applyExpressionTransformer(whereManager);
Expand All @@ -1406,13 +1373,12 @@ public void applyExpressionTransformers() {
}

// After all transformations are done, we can finally check if aggregations are used
AggregateDetectionVisitor aggregateDetector = new AggregateDetectionVisitor();
hasGroupBy = groupByManager.hasGroupBys();
hasGroupBy = hasGroupBy || Boolean.TRUE.equals(selectManager.acceptVisitor(aggregateDetector, true));
hasGroupBy = hasGroupBy || Boolean.TRUE.equals(joinManager.acceptVisitor(aggregateDetector, true));
hasGroupBy = hasGroupBy || Boolean.TRUE.equals(whereManager.acceptVisitor(aggregateDetector));
hasGroupBy = hasGroupBy || Boolean.TRUE.equals(orderByManager.acceptVisitor(aggregateDetector, true));
hasGroupBy = hasGroupBy || Boolean.TRUE.equals(havingManager.acceptVisitor(aggregateDetector));
hasGroupBy = hasGroupBy || Boolean.TRUE.equals(selectManager.acceptVisitor(AggregateDetectionVisitor.INSTANCE, true));
hasGroupBy = hasGroupBy || Boolean.TRUE.equals(joinManager.acceptVisitor(AggregateDetectionVisitor.INSTANCE, true));
hasGroupBy = hasGroupBy || Boolean.TRUE.equals(whereManager.acceptVisitor(AggregateDetectionVisitor.INSTANCE));
hasGroupBy = hasGroupBy || Boolean.TRUE.equals(orderByManager.acceptVisitor(AggregateDetectionVisitor.INSTANCE, true));
hasGroupBy = hasGroupBy || Boolean.TRUE.equals(havingManager.acceptVisitor(AggregateDetectionVisitor.INSTANCE));
}

public Class<QueryResultType> getResultType() {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -57,8 +57,11 @@ public AbstractCustomQuery(QuerySpecification<T> querySpecification, CommonQuery
if (!valuesParameterMap.containsKey(valuesName)) {
ValuesParameter param = new ValuesParameter(valuesName, valuesBinders.get(valuesName));
parameters.add(param);
parametersToSet.add(valuesName);
valuesParameterMap.put(valuesName, param);

if (!q.isBound(p)) {
parametersToSet.add(valuesName);
}
}
}

Expand All @@ -68,7 +71,9 @@ public AbstractCustomQuery(QuerySpecification<T> querySpecification, CommonQuery
parameterQueries.put(name, queries);
if (valuesName == null) {
parameters.add(p);
parametersToSet.add(name);
if (!q.isBound(p)) {
parametersToSet.add(name);
}
}
}
queries.add(q);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -16,25 +16,28 @@

package com.blazebit.persistence.impl;

import com.blazebit.persistence.impl.expression.Expression;
import com.blazebit.persistence.impl.expression.modifier.ExpressionModifier;
import com.blazebit.persistence.impl.transform.ExpressionModifierVisitor;

import java.util.Iterator;
import java.util.Set;

import com.blazebit.persistence.impl.expression.Expression;
import com.blazebit.persistence.impl.transform.ExpressionTransformer;

/**
*
* @author Moritz Becker
* @since 1.0
*/
public abstract class AbstractManager {
public abstract class AbstractManager<T extends ExpressionModifier> {

protected final ResolvingQueryGenerator queryGenerator;
protected final ParameterManager parameterManager;
protected final SubqueryInitiatorFactory subqueryInitFactory;

protected AbstractManager(ResolvingQueryGenerator queryGenerator, ParameterManager parameterManager) {
protected AbstractManager(ResolvingQueryGenerator queryGenerator, ParameterManager parameterManager, SubqueryInitiatorFactory subqueryInitFactory) {
this.queryGenerator = queryGenerator;
this.parameterManager = parameterManager;
this.subqueryInitFactory = subqueryInitFactory;
}

protected void registerParameterExpressions(Expression expression) {
Expand All @@ -56,7 +59,7 @@ protected void build(StringBuilder sb, Set<String> clauses) {
}
}

public abstract void applyTransformer(ExpressionTransformer transformer);
public abstract void apply(ExpressionModifierVisitor<? super T> visitor);

public abstract ClauseType getClauseType();

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -18,10 +18,16 @@

import com.blazebit.persistence.impl.expression.AbortableVisitorAdapter;
import com.blazebit.persistence.impl.expression.AggregateExpression;
import com.blazebit.persistence.impl.expression.Expression;
import com.blazebit.persistence.impl.expression.FunctionExpression;

class AggregateDetectionVisitor extends AbortableVisitorAdapter {

public static final Expression.ResultVisitor<Boolean> INSTANCE = new AggregateDetectionVisitor();

private AggregateDetectionVisitor() {
}

@Override
public Boolean visit(FunctionExpression expression) {
if (expression instanceof AggregateExpression) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -103,14 +103,16 @@ private Integer getCounterHierarchical(String alias) {

public void unregisterAliasInfoForBottomLevel(AliasInfo aliasInfo) {
String alias = aliasInfo.getAlias();
aliasMap.remove(alias);
int counter = aliasCounterMap.get(alias).intValue();

if (alias.endsWith("_" + counter)) {
if (counter == 1) {
aliasCounterMap.remove(alias);
} else {
aliasCounterMap.put(alias, counter - 1);
if (alias != null) {
aliasMap.remove(alias);
int counter = aliasCounterMap.get(alias).intValue();

if (alias.endsWith("_" + counter)) {
if (counter == 1) {
aliasCounterMap.remove(alias);
} else {
aliasCounterMap.put(alias, counter - 1);
}
}
}
}
Expand Down
Loading

0 comments on commit 60bbe47

Please sign in to comment.