/**
*
* Copyright (c) 2006-2017, Speedment, Inc. All Rights Reserved.
*
* 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.speedment.runtime.core.internal.component.sql.optimiser;
import com.speedment.runtime.core.internal.component.sql.optimizer.FilterSortedSkipOptimizer;
import com.speedment.runtime.core.component.sql.Metrics;
import com.speedment.runtime.core.db.DbmsType;
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.PeekAction;
import com.speedment.runtime.core.internal.stream.builder.action.reference.SkipAction;
import com.speedment.runtime.core.internal.stream.builder.action.reference.SortedComparatorAction;
import com.speedment.runtime.core.internal.stream.builder.pipeline.PipelineImpl;
import com.speedment.common.combinatorics.Permutation;
import com.speedment.runtime.core.stream.Pipeline;
import com.speedment.runtime.core.stream.action.Action;
import com.speedment.runtime.test_support.MockDbmsType;
import com.speedment.runtime.test_support.MockEntity;
import com.speedment.runtime.test_support.MockEntityUtil;
import java.util.List;
import java.util.function.Supplier;
import java.util.stream.BaseStream;
import static java.util.stream.Collectors.toList;
import java.util.stream.Stream;
import static org.junit.Assert.assertEquals;
import org.junit.Before;
import org.junit.Test;
/**
*
* @author Per Minborg
*/
public class FilterSortedSkipOptimizer_MetricsTest {
private static final DbmsType DBMS_TYPE = new MockDbmsType();
private static final Supplier<BaseStream<?, ?>> STREAM_SUPPLIER = () -> MockEntityUtil.stream(2);
private static final FilterAction<MockEntity> FILTER_ACTION = new FilterAction<>(MockEntity.ID.equal(1));
private static final SortedComparatorAction<MockEntity> SORTED_ACTION = new SortedComparatorAction<>(MockEntity.NAME.comparator());
private static final SkipAction<MockEntity> SKIP_ACTION = new SkipAction<>(1);
private static final LimitAction<MockEntity> LIMIT_ACTION = new LimitAction<>(1);
private static final PeekAction<MockEntity> PEEK_ACTION = new PeekAction<>(System.out::println);
private FilterSortedSkipOptimizer<MockEntity> instance;
@Before
public void setUp() {
instance = new FilterSortedSkipOptimizer<>();
}
@Test
public void testFilter1Order1Skip1() {
final Pipeline pipeline = pipelineOf(FILTER_ACTION, SORTED_ACTION, SKIP_ACTION);
final Metrics metrics = instance.metrics(pipeline, DBMS_TYPE);
assertEquals(3, metrics.getPipelineReductions());
}
@Test
public void testFilter0Order1Skip1() {
final Pipeline pipeline = pipelineOf(SORTED_ACTION, SKIP_ACTION);
final Metrics metrics = instance.metrics(pipeline, DBMS_TYPE);
assertEquals(2, metrics.getPipelineReductions());
}
@Test
public void testFilter1Order0Skip1() {
final Pipeline pipeline = pipelineOf(FILTER_ACTION, SKIP_ACTION);
final Metrics metrics = instance.metrics(pipeline, DBMS_TYPE);
assertEquals(2, metrics.getPipelineReductions());
}
@Test
public void testFilter1Order1Skip0() {
final Pipeline pipeline = pipelineOf(FILTER_ACTION, SORTED_ACTION);
final Metrics metrics = instance.metrics(pipeline, DBMS_TYPE);
assertEquals(2, metrics.getPipelineReductions());
}
@Test
public void testFilter1Order0Skip0() {
final Pipeline pipeline = pipelineOf(SORTED_ACTION, SKIP_ACTION);
final Metrics metrics = instance.metrics(pipeline, DBMS_TYPE);
assertEquals(2, metrics.getPipelineReductions());
}
@Test
public void testFilter0Order1Skip0() {
final Pipeline pipeline = pipelineOf(FILTER_ACTION, SKIP_ACTION);
final Metrics metrics = instance.metrics(pipeline, DBMS_TYPE);
assertEquals(2, metrics.getPipelineReductions());
}
@Test
public void testFilter0Order0Skip1() {
final Pipeline pipeline = pipelineOf(FILTER_ACTION, SORTED_ACTION);
final Metrics metrics = instance.metrics(pipeline, DBMS_TYPE);
assertEquals(2, metrics.getPipelineReductions());
}
@Test
public void testFilter0Order0Skip0() {
final Pipeline pipeline = pipelineOf();
final Metrics metrics = instance.metrics(pipeline, DBMS_TYPE);
assertEquals(0, metrics.getPipelineReductions());
}
@Test
public void testSkip0LimitFilter0Order0() {
final Pipeline pipeline = pipelineOf(SKIP_ACTION, LIMIT_ACTION, FILTER_ACTION, SORTED_ACTION);
final Metrics metrics = instance.metrics(pipeline, DBMS_TYPE);
assertEquals(2, metrics.getPipelineReductions());
}
@Test
public void focus() {
final Pipeline pipeline = pipelineOf(FILTER_ACTION, SKIP_ACTION, SORTED_ACTION, LIMIT_ACTION, PEEK_ACTION);
final Metrics metrics = instance.metrics(pipeline, DBMS_TYPE);
assertEquals(2, metrics.getPipelineReductions());
}
//// Polution...
@Test
public void testPolution() {
Permutation.of(FILTER_ACTION, SORTED_ACTION, SKIP_ACTION, LIMIT_ACTION, PEEK_ACTION)
.map(s -> s.collect(toList()))
.forEachOrdered(l -> {
int expected = expectedMetrics(l);
//
// if (l.get(0) == FILTER_ACTION) {
// expected += 10;
// if (l.get(1) == SORTED_ACTION) {
// expected += 10;
// if (l.get(2) == SKIP_ACTION) {
// expected += 10;
// }
// }
// }
// expected = expected == 0 ? Integer.MIN_VALUE : expected;
Pipeline pipeline = pipelineOf(l.stream().toArray(Action[]::new));
assertEquals("Failed for " + l, expected, instance.metrics(pipeline, DBMS_TYPE).getPipelineReductions());
}
);
}
private int expectedMetrics(List<? extends Action<Stream<MockEntity>, Stream<MockEntity>>> l) {
// Filter first
if ((l.get(0) == FILTER_ACTION)
&& (l.get(1) == SORTED_ACTION)
&& (l.get(2) == SKIP_ACTION)
&& (l.get(3) == LIMIT_ACTION)) {
return 4;
}
if ((l.get(0) == FILTER_ACTION)
&& (l.get(1) == SORTED_ACTION)
&& (l.get(2) == SKIP_ACTION)) {
return 3;
}
if ((l.get(0) == FILTER_ACTION)
&& (l.get(1) == SORTED_ACTION)
&& (l.get(2) == LIMIT_ACTION)) {
return 3;
}
if ((l.get(0) == FILTER_ACTION)
&& (l.get(1) == SORTED_ACTION)) {
return 2;
}
if ((l.get(0) == FILTER_ACTION)
&& (l.get(1) == SKIP_ACTION)
&& (l.get(2) == LIMIT_ACTION)) {
return 3;
}
if ((l.get(0) == FILTER_ACTION)
&& (l.get(1) == SKIP_ACTION)) {
return 2;
}
if ((l.get(0) == FILTER_ACTION)
&& (l.get(1) == LIMIT_ACTION)) {
return 2;
}
if ((l.get(0) == FILTER_ACTION)) {
return 1;
}
// Sorted first
if ((l.get(0) == SORTED_ACTION)
&& (l.get(1) == FILTER_ACTION)
&& (l.get(2) == SKIP_ACTION)
&& (l.get(3) == LIMIT_ACTION)) {
return 4;
}
if ((l.get(0) == SORTED_ACTION)
&& (l.get(1) == FILTER_ACTION)
&& (l.get(2) == SKIP_ACTION)) {
return 3;
}
if ((l.get(0) == SORTED_ACTION)
&& (l.get(1) == FILTER_ACTION)
&& (l.get(2) == LIMIT_ACTION)) {
return 3;
}
if ((l.get(0) == SORTED_ACTION)
&& (l.get(1) == FILTER_ACTION)
&& (l.get(2) == LIMIT_ACTION)) {
return 2;
}
if ((l.get(0) == SORTED_ACTION)
&& (l.get(1) == FILTER_ACTION)) {
return 2;
}
if ((l.get(0) == SORTED_ACTION)
&& (l.get(1) == SKIP_ACTION)
&& (l.get(2) == LIMIT_ACTION)) {
return 3;
}
if ((l.get(0) == SORTED_ACTION)
&& (l.get(1) == SKIP_ACTION)) {
return 2;
}
if ((l.get(0) == SORTED_ACTION)
&& (l.get(1) == LIMIT_ACTION)) {
return 2;
}
if ((l.get(0) == SORTED_ACTION)) {
return 1;
}
// Skip first
if ((l.get(0) == SKIP_ACTION)
&& (l.get(1) == LIMIT_ACTION)) {
return 2;
}
if ((l.get(0) == SKIP_ACTION)) {
return 1;
}
// Limit first
if ((l.get(0) == LIMIT_ACTION)) {
return 1;
}
return 0;
}
private Pipeline pipelineOf(Action<?, ?>... actions) {
return Stream.of(actions)
.collect(
() -> new PipelineImpl<>(STREAM_SUPPLIER),
PipelineImpl::addLast,
(a, b) -> b.stream().forEachOrdered(a::add)
);
}
}