/*
* Copyright (C) 2010 eXo Platform SAS.
*
* This is free software; you can redistribute it and/or modify it
* under the terms of the GNU Lesser General Public License as
* published by the Free Software Foundation; either version 2.1 of
* the License, or (at your option) any later version.
*
* This software is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this software; if not, write to the Free
* Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
* 02110-1301 USA, or see the FSF site: http://www.fsf.org.
*/
package org.xcmis.search.query.optimizer;
import static org.hamcrest.core.Is.is;
import static org.hamcrest.core.IsSame.sameInstance;
import static org.junit.Assert.assertThat;
import static org.mockito.Mockito.mock;
import org.junit.Before;
import org.junit.Test;
import org.xcmis.search.content.Schema;
import org.xcmis.search.query.QueryExecutionContext;
import org.xcmis.search.query.QueryExecutionExceptions;
import org.xcmis.search.query.optimize.OptimizerCriteria;
import org.xcmis.search.query.optimize.PushWhereCriteria;
import org.xcmis.search.query.plan.QueryExecutionPlan;
import java.util.LinkedList;
/**
* Test for {@link PushWhereCriteria}
*/
public class PushWhereCriteriaTest
{
private PushWhereCriteria rule;
private QueryExecutionContext context;
@Before
public void beforeEach()
{
context = new QueryExecutionContext(mock(Schema.class), new QueryExecutionExceptions(), null);
rule = PushWhereCriteria.INSTANCE;
}
/**
* Before:
*
* <pre>
* ...
* |
* PROJECT with the list of columns being SELECTed
* |
* SELECT1
* | One or more SELECT plan nodes that each have
* SELECT2 a single non-join constraint that are then all AND-ed
* | together
* SELECTn
* |
* ACCESS
* |
* SOURCE
* </pre>
*
* And after:
*
* <pre>
* ...
* |
* PROJECT with the list of columns being SELECTed
* |
* ACCESS
* |
* SELECT1
* | One or more SELECT plan nodes that each have
* SELECT2 a single non-join constraint that are then all AND-ed
* | together
* SELECTn
* |
* SOURCE
* </pre>
*/
@Test
public void shouldPushDownAllSelectNodesThatApplyToSelectorBelowAccessNodeButAboveSourceNodeUsingSameSelector()
{
// Each of the PROJECT, SELECT, and SELECT nodes must have the names of the selectors that they apply to ...
QueryExecutionPlan project = null;// new QueryExecutionPlan(Type.PROJECT, selector("Selector1"));
QueryExecutionPlan select1 = null;// //new QueryExecutionPlan(Type.WHERE, project, selector("Selector1"));
QueryExecutionPlan select2 = null;//new QueryExecutionPlan(Type.WHERE, select1, selector("Selector1"));
QueryExecutionPlan select3 = null;//new QueryExecutionPlan(Type.WHERE, select2, selector("Selector1"));
QueryExecutionPlan select4 = null;//new QueryExecutionPlan(Type.WHERE, select3, selector("Selector1"));
QueryExecutionPlan access = null;//new QueryExecutionPlan(Type.ACCESS, select4, selector("Selector1"));
QueryExecutionPlan source = null;//new QueryExecutionPlan(Type.SELECTOR, access, selector("Selector1"));
// Execute the rule ...
QueryExecutionPlan result = rule.execute(context, project, new LinkedList<OptimizerCriteria>());
assertThat(result, is(sameInstance(project)));
assertChildren(project, access);
assertChildren(access, select1);
assertChildren(select1, select2);
assertChildren(select2, select3);
assertChildren(select3, select4);
assertChildren(select4, source);
assertChildren(source);
}
@Test
public void shouldNotPushDownSelectNodesThatUseDifferentSelectorNamesThanSourceNode()
{
// Each of the PROJECT, SELECT, and SELECT nodes must have the names of the selectors that they apply to ...
QueryExecutionPlan project = null;// new QueryExecutionPlan(Type.PROJECT, selector("Selector1"));
QueryExecutionPlan select1 = null;//new QueryExecutionPlan(Type.WHERE, project, selector("Selector2"));
QueryExecutionPlan select2 = null;//new QueryExecutionPlan(Type.WHERE, select1, selector("Selector1"));
QueryExecutionPlan select3 = null;//new QueryExecutionPlan(Type.WHERE, select2, selector("Selector2"));
QueryExecutionPlan select4 = null;// new QueryExecutionPlan(Type.WHERE, select3, selector("Selector1"));
QueryExecutionPlan access = null;// new QueryExecutionPlan(Type.ACCESS, select4, selector("Selector1"));
QueryExecutionPlan source = null;//new QueryExecutionPlan(Type.SELECTOR, access, selector("Selector1"));
// Execute the rule ...
QueryExecutionPlan result = rule.execute(context, project, new LinkedList<OptimizerCriteria>());
assertThat(result, is(sameInstance(project)));
assertChildren(project, select1);
assertChildren(select1, select3);
assertChildren(select3, access);
assertChildren(access, select2);
assertChildren(select2, select4);
assertChildren(select4, source);
assertChildren(source);
}
/**
* Before:
*
* <pre>
* ...
* |
* PROJECT ('s1','s2') with the list of columns being SELECTed (from 's1' and 's2' selectors)
* |
* SELECT1 ('s1')
* | One or more SELECT plan nodes that each have
* SELECT2 ('s2') a single non-join constraint that are then all AND-ed
* | together, and that each have the selector(s) they apply to
* SELECT3 ('s1','s2')
* |
* SELECT4 ('s1')
* |
* JOIN ('s1','s2')
* / \
* / \
* ACCESS ACCESS
* ('s1') ('s2')
* | |
* SOURCE SOURCE
* ('s1') ('s2')
* </pre>
*
* And after:
*
* <pre>
* ...
* |
* PROJECT ('s1','s2') with the list of columns being SELECTed (from 's1' and 's2' selectors)
* |
* SELECT3 ('s1','s2') Any SELECT plan nodes that apply to multiple selectors are left above
* | the ACCESS nodes.
* JOIN ('s1','s2')
* / \
* / \
* ACCESS ACCESS
* ('s1') ('s2')
* | |
* SELECT1 SELECT2
* ('s1') ('s2')
* | |
* SELECT4 SOURCE
* ('s1') ('s2')
* |
* SOURCE
* ('s1')
* </pre>
*/
@Test
public void shouldPushDownAllSelectNodesThatApplyToOneSelectorToBelowAccessNodeForThatSelector()
{
// Each of the PROJECT, SELECT, and SELECT nodes must have the names of the selectors that they apply to ...
QueryExecutionPlan project = null;//new QueryExecutionPlan(Type.PROJECT, selector("Selector1"), selector("Selector2"));
QueryExecutionPlan select1 = null;// new QueryExecutionPlan(Type.WHERE, project, selector("Selector1"));
QueryExecutionPlan select2 = null;//new QueryExecutionPlan(Type.WHERE, select1, selector("Selector2"));
QueryExecutionPlan select3 = null;// new QueryExecutionPlan(Type.WHERE, select2, selector("Selector1"), selector("Selector2"));
QueryExecutionPlan select4 = null;//new QueryExecutionPlan(Type.WHERE, select3, selector("Selector1"));
QueryExecutionPlan join = null;// new QueryExecutionPlan(Type.JOIN, select4, selector("Selector1"), selector("Selector2"));
QueryExecutionPlan s1Access = null;// new QueryExecutionPlan(Type.ACCESS, join, selector("Selector1"));
QueryExecutionPlan s1Source = null;//new QueryExecutionPlan(Type.SELECTOR, s1Access, selector("Selector1"));
QueryExecutionPlan s2Access = null;// new QueryExecutionPlan(Type.ACCESS, join, selector("Selector2"));
QueryExecutionPlan s2Source = null;//new QueryExecutionPlan(Type.SELECTOR, s2Access, selector("Selector2"));
// Set the join type ...
//join.setProperty("JOIN_TYPE", JoinType.INNER);
// Execute the rule ...
QueryExecutionPlan result = rule.execute(context, project, new LinkedList<OptimizerCriteria>());
// System.out.println(result);
assertThat(result, is(sameInstance(project)));
assertChildren(project, select3);
assertChildren(select3, join);
assertChildren(join, s1Access, s2Access);
assertChildren(s1Access, select1);
assertChildren(select1, select4);
assertChildren(select4, s1Source);
assertChildren(s2Access, select2);
assertChildren(select2, s2Source);
assertChildren(s2Source);
assertChildren(s1Source);
}
private void assertChildren(Object obj, Object obj2, Object obj3)
{
}
private void assertChildren(Object obj, Object obj2)
{
}
private void assertChildren(Object obj)
{
}
}