Skip to content

Commit

Permalink
runtime-field: make AbstractCombinedPredicate immutable
Browse files Browse the repository at this point in the history
  • Loading branch information
minborg committed May 1, 2017
1 parent ab63606 commit 6ca6657
Show file tree
Hide file tree
Showing 6 changed files with 705 additions and 176 deletions.
Expand Up @@ -24,20 +24,18 @@
import com.speedment.runtime.core.db.DbmsType;
import static com.speedment.runtime.core.db.DbmsType.SkipLimitSupport.NONE;
import static com.speedment.runtime.core.db.DbmsType.SkipLimitSupport.ONLY_AFTER_SORTED;
import com.speedment.runtime.core.db.FieldPredicateView;
import com.speedment.runtime.core.db.SqlPredicateFragment;
import com.speedment.runtime.core.internal.stream.builder.action.reference.FilterAction;
import com.speedment.runtime.core.internal.stream.builder.action.reference.LimitAction;
import com.speedment.runtime.core.internal.stream.builder.action.reference.SkipAction;
import com.speedment.runtime.core.internal.stream.builder.action.reference.SortedComparatorAction;
import static com.speedment.runtime.core.internal.stream.builder.streamterminator.StreamTerminatorUtil.isFilterActionWithFieldPredicate;
import com.speedment.runtime.core.internal.stream.builder.streamterminator.StreamTerminatorUtil;
import com.speedment.runtime.core.internal.stream.builder.streamterminator.StreamTerminatorUtil.RenderResult;
import static com.speedment.runtime.core.internal.stream.builder.streamterminator.StreamTerminatorUtil.isContainingOnlyFieldPredicate;
import static com.speedment.runtime.core.internal.stream.builder.streamterminator.StreamTerminatorUtil.isSortedActionWithFieldPredicate;
import com.speedment.runtime.core.stream.Pipeline;
import com.speedment.runtime.core.stream.action.Action;
import com.speedment.runtime.field.Field;
import com.speedment.runtime.field.comparator.FieldComparator;
import com.speedment.runtime.field.predicate.FieldPredicate;
import com.speedment.runtime.typemapper.TypeMapper;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.HashSet;
Expand All @@ -46,7 +44,7 @@
import java.util.Set;
import java.util.concurrent.atomic.AtomicInteger;
import java.util.function.Consumer;
import static java.util.stream.Collectors.joining;
import java.util.function.Predicate;
import static java.util.stream.Collectors.toList;

/**
Expand Down Expand Up @@ -144,36 +142,52 @@ public <P extends Pipeline> P optimize(
sql.append(info.getSqlSelect());

if (!filters.isEmpty()) {
final FieldPredicateView spv = info.getDbmsType().getFieldPredicateView();

@SuppressWarnings("unchecked")
final List<SqlPredicateFragment> fragments = filters.stream()
.map(f -> f.getPredicate())
.map(p -> (FieldPredicate<ENTITY>) p)
.map(sp -> spv.transform(info.getSqlColumnNamer(), info.getSqlDatabaseTypeFunction(), sp))
List<Predicate<ENTITY>> predicates = filters.stream()
.map(FilterAction::getPredicate)
.map(p -> (Predicate<ENTITY>) p)
// .map(p -> (FieldPredicate<ENTITY>) p)
.collect(toList());

// Todo: Make this in one sweep
String expression = fragments.stream()
.map(SqlPredicateFragment::getSql)
.collect(joining(" AND "));

sql.append(" WHERE ").append(expression);

for (int i = 0; i < fragments.size(); i++) {

@SuppressWarnings("unchecked")
final FieldPredicate<ENTITY> p = (FieldPredicate<ENTITY>) filters.get(i).getPredicate();
final Field<ENTITY> referenceFieldTrait = p.getField();

@SuppressWarnings("unchecked")
final TypeMapper<Object, Object> tm = (TypeMapper<Object, Object>) referenceFieldTrait.typeMapper();

fragments.get(i).objects()
.map(tm::toDatabaseType)
.forEach(values::add);
final RenderResult rr = StreamTerminatorUtil.renderSqlWhere(
info.getDbmsType(),
info.getSqlColumnNamer(),
info.getSqlDatabaseTypeFunction(),
predicates
);

}
// final FieldPredicateView spv = info.getDbmsType().getFieldPredicateView();
//
// // Todo: Allow composite predicates
// @SuppressWarnings("unchecked")
// final List<SqlPredicateFragment> fragments = filters.stream()
// .map(f -> f.getPredicate())
// .map(p -> (FieldPredicate<ENTITY>) p)
// .map(sp -> spv.transform(info.getSqlColumnNamer(), info.getSqlDatabaseTypeFunction(), sp))
// .collect(toList());
//
// // Todo: Make this in one sweep
// String expression = fragments.stream()
// .map(SqlPredicateFragment::getSql)
// .collect(joining(" AND "));
// sql.append(" WHERE ").append(expression);
//
// for (int i = 0; i < fragments.size(); i++) {
//
// @SuppressWarnings("unchecked")
// final FieldPredicate<ENTITY> p = (FieldPredicate<ENTITY>) filters.get(i).getPredicate();
// final Field<ENTITY> referenceFieldTrait = p.getField();
//
// @SuppressWarnings("unchecked")
// final TypeMapper<Object, Object> tm = (TypeMapper<Object, Object>) referenceFieldTrait.typeMapper();
//
// fragments.get(i).objects()
// .map(tm::toDatabaseType)
// .forEachOrdered(values::add);
//
// }
sql.append(" WHERE ").append(rr.getSql());
values.addAll(rr.getValues());

}

Expand Down Expand Up @@ -237,7 +251,7 @@ private void traverse(Pipeline pipeline,

final Action<?, ?> firstAction = pipeline.getFirst();
final List<Operation<ENTITY>> path;
if (isFilterActionWithFieldPredicate(firstAction)) {
if (isFilterActionAndContainingOnlyFieldPredicate(firstAction)) {
path = FILTER_SORTED_SKIP_PATH;
} else {
path = SORTED_FILTER_SKIP_PATH;
Expand Down Expand Up @@ -305,59 +319,15 @@ private void traverse(Pipeline pipeline,
}
}

// private void traverseOld(Pipeline pipeline,
// final Consumer<? super FilterAction<ENTITY>> filterConsumer,
// final Consumer<? super SortedComparatorAction<ENTITY>> sortedConsumer,
// final Consumer<? super SkipAction<ENTITY>> skipConsumer
// ) {
//
// State state = FILTER;
//
// for (Action<?, ?> action : pipeline) {
//
// if (state == FILTER) {
// if (isFilterActionWithFieldPredicate(action)) {
// @SuppressWarnings("unchecked")
// final FilterAction<ENTITY> filterAction = (FilterAction<ENTITY>) action;
// filterConsumer.accept(filterAction);
// } else {
// if (isSortedActionWithFieldPredicate(action)) { // Note: SortedAction will not work because an Entity is not Comparable
// state = SORTED;
// } else {
// if (action instanceof SkipAction) {
// state = SKIP;
// } else {
// return;
// }
// }
// }
// }
//
// if (state == SORTED) {
// if (isSortedActionWithFieldPredicate(action)) {
// @SuppressWarnings("unchecked")
// final SortedComparatorAction<ENTITY> sortedAction = (SortedComparatorAction<ENTITY>) action;
// sortedConsumer.accept(sortedAction);
// } else {
// if (action instanceof SkipAction) {
// state = SKIP;
// } else {
// return;
// }
// }
// }
//
// if (state == SKIP) {
// if (action instanceof SkipAction) {
// @SuppressWarnings("unchecked")
// final SkipAction<ENTITY> skipAction = (SkipAction<ENTITY>) action;
// skipConsumer.accept(skipAction);
// } else {
// return;
// }
// }
// }
// }
private boolean isFilterActionAndContainingOnlyFieldPredicate(Action<?, ?> action) {
if (action instanceof FilterAction) {
@SuppressWarnings("unchecked")
final FilterAction<ENTITY> filterAction = (FilterAction<ENTITY>) action;
return isContainingOnlyFieldPredicate(filterAction.getPredicate());
}
return false;
}

private static class Consumers<ENTITY> {

private final Consumer<? super FilterAction<ENTITY>> filterConsumer;
Expand Down Expand Up @@ -407,7 +377,7 @@ private class FilterOperation implements Operation<ENTITY> {

@Override
public boolean is(Action<?, ?> action) {
return isFilterActionWithFieldPredicate(action);
return isFilterActionAndContainingOnlyFieldPredicate(action);
}

@Override
Expand Down
Expand Up @@ -18,6 +18,7 @@

import com.speedment.runtime.core.component.sql.SqlStreamOptimizerInfo;
import com.speedment.runtime.core.db.AsynchronousQueryResult;
import com.speedment.runtime.core.db.DbmsType;
import com.speedment.runtime.core.db.FieldPredicateView;
import com.speedment.runtime.core.db.SqlPredicateFragment;
import com.speedment.runtime.core.internal.stream.builder.action.reference.FilterAction;
Expand All @@ -28,12 +29,15 @@
import com.speedment.runtime.field.Field;
import com.speedment.runtime.field.comparator.FieldComparator;
import com.speedment.runtime.field.internal.predicate.AbstractCombinedPredicate;
import com.speedment.runtime.field.predicate.CombinedPredicate;
import com.speedment.runtime.field.predicate.FieldPredicate;
import com.speedment.runtime.typemapper.TypeMapper;
import java.util.ArrayList;
import java.util.List;
import static java.util.Objects.requireNonNull;
import java.util.Optional;
import java.util.concurrent.atomic.AtomicInteger;
import java.util.function.Function;
import java.util.function.Predicate;
import static java.util.stream.Collectors.joining;
import static java.util.stream.Collectors.toList;
Expand Down Expand Up @@ -86,15 +90,15 @@ public static <ENTITY> List<FieldPredicate<?>> andPredicates(FilterAction<ENTITY
return andPredicateBuilders;
}

public static boolean isFilterActionWithFieldPredicate(Action<?, ?> action) {
if (action instanceof FilterAction) {
if (((FilterAction) action).getPredicate() instanceof FieldPredicate) {
return true;
}
public static <ENTITY> boolean isContainingOnlyFieldPredicate(Predicate<ENTITY> predicate) {
if (predicate instanceof FieldPredicate) {
return true;
} else if (predicate instanceof CombinedPredicate) {
return ((CombinedPredicate<ENTITY>) predicate).stream().allMatch(StreamTerminatorUtil::isContainingOnlyFieldPredicate);
}
return false;
}

public static boolean isSortedActionWithFieldPredicate(Action<?, ?> action) {
if (action instanceof SortedComparatorAction) {
if (((SortedComparatorAction) action).getComparator() instanceof FieldComparator) {
Expand All @@ -103,7 +107,7 @@ public static boolean isSortedActionWithFieldPredicate(Action<?, ?> action) {
}
return false;
}

public static <ENTITY> void modifySource(
final List<FieldPredicate<ENTITY>> predicateBuilders,
final SqlStreamOptimizerInfo<ENTITY> info,
Expand Down Expand Up @@ -140,8 +144,110 @@ public static <ENTITY> void modifySource(
query.setSql(sql);
query.setValues(values);
}



private StreamTerminatorUtil() {throw new UnsupportedOperationException();}
}

public interface RenderResult {

String getSql();

List<Object> getValues();

//Pipeline getPipeline();
}

private static final class RenderResultImpl implements RenderResult {

private final String sql;
private final List<Object> values;

public RenderResultImpl(String sql, List<Object> values /*, Pipeline pipeline*/) {
this.sql = sql;
this.values = values;
}

@Override
public String getSql() {
return sql;
}

@Override
public List<Object> getValues() {
return values;
}

@Override
public String toString() {
return String.format("RenderResultImpl {sql=%s, values=%s}", sql, values);
}
}

public static <T extends Pipeline, ENTITY> RenderResult renderSqlWhere(
final DbmsType dbmsType,
final Function<Field<ENTITY>, String> columnNamer,
final Function<Field<ENTITY>, Class<?>> columnDbTypeFunction,
final List<Predicate<ENTITY>> predicates
) {
final FieldPredicateView predicateView = dbmsType.getFieldPredicateView();
final StringBuilder sql = new StringBuilder();
final List<Object> values = new ArrayList<>();
final AtomicInteger cnt = new AtomicInteger();
predicates.forEach(predicate -> {
if (cnt.getAndIncrement() != 0) {
sql.append(" AND ");
}
renderSqlWhileHelper(predicateView, columnNamer, columnDbTypeFunction, sql, values, predicate);
});
return new RenderResultImpl(sql.toString(), values);
}

private static <T extends Pipeline, ENTITY> void renderSqlWhileHelper(
final FieldPredicateView spv,
final Function<Field<ENTITY>, String> columnNamer,
final Function<Field<ENTITY>, Class<?>> columnDbTypeFunction,
final StringBuilder sql,
final List<Object> values,
final Predicate<ENTITY> predicate
) {
if (predicate instanceof FieldPredicate) {
final FieldPredicate<ENTITY> fieldPredicate = (FieldPredicate<ENTITY>) predicate;
final SqlPredicateFragment fragment = spv.transform(columnNamer, columnDbTypeFunction, fieldPredicate);
final Field<ENTITY> referenceFieldTrait = fieldPredicate.getField();
@SuppressWarnings("unchecked")
final TypeMapper<Object, Object> tm = (TypeMapper<Object, Object>) referenceFieldTrait.typeMapper();

sql.append(fragment.getSql());
fragment.objects().map(tm::toDatabaseType).forEachOrdered(values::add);
} else if (predicate instanceof CombinedPredicate) {
final CombinedPredicate<ENTITY> combinedPredicate = (CombinedPredicate<ENTITY>) predicate;
final StringBuilder internalSql = new StringBuilder();
final List<Object> internalValues = new ArrayList<>();
final AtomicInteger cnt = new AtomicInteger();
combinedPredicate.stream().forEachOrdered(internalPredicate -> {
if (cnt.getAndIncrement() != 0) {
internalSql.append(" ").append(combinedPredicate.getType().toString()).append(" ");
}
@SuppressWarnings("unchecked")
final Predicate<ENTITY> castedInternalPredicate = (Predicate<ENTITY>) internalPredicate;
renderSqlWhileHelper(
spv,
columnNamer,
columnDbTypeFunction,
internalSql,
internalValues,
castedInternalPredicate
);
});
if (combinedPredicate.isNegated()) {
sql.append("(NOT (").append(internalSql).append("))");
} else {
sql.append("(").append(internalSql).append(")");
}
values.addAll(internalValues);
} else {
throw new IllegalArgumentException("A predicate that is not instanceof FieldPredicate was given:" + predicate.toString());
}
}

private StreamTerminatorUtil() {
throw new UnsupportedOperationException();
}
}

0 comments on commit 6ca6657

Please sign in to comment.