/* * JBoss, Home of Professional Open Source. * See the COPYRIGHT.txt file distributed with this work for information * regarding copyright ownership. Some portions may be licensed * to Red Hat, Inc. under one or more contributor license agreements. * * This library 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 library 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 library; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA * 02110-1301 USA. */ package org.teiid.query.optimizer.relational.rules; import static org.junit.Assert.*; import java.util.ArrayList; import java.util.Arrays; import java.util.Collection; import java.util.Collections; import java.util.Iterator; import java.util.LinkedList; import java.util.List; import org.junit.Test; import org.teiid.api.exception.query.QueryMetadataException; import org.teiid.api.exception.query.QueryPlannerException; import org.teiid.core.TeiidComponentException; import org.teiid.query.analysis.AnalysisRecord; import org.teiid.query.metadata.QueryMetadataInterface; import org.teiid.query.optimizer.TestOptimizer; import org.teiid.query.optimizer.capabilities.FakeCapabilitiesFinder; import org.teiid.query.optimizer.relational.RuleStack; import org.teiid.query.optimizer.relational.plantree.NodeConstants; import org.teiid.query.optimizer.relational.plantree.NodeFactory; import org.teiid.query.optimizer.relational.plantree.PlanNode; import org.teiid.query.processor.relational.JoinNode.JoinStrategyType; import org.teiid.query.resolver.util.ResolverUtil; import org.teiid.query.rewriter.QueryRewriter; import org.teiid.query.sql.lang.*; import org.teiid.query.sql.symbol.Constant; import org.teiid.query.sql.symbol.ElementSymbol; import org.teiid.query.sql.symbol.GroupSymbol; import org.teiid.query.unittest.RealMetadataFactory; import org.teiid.query.util.CommandContext; @SuppressWarnings("unchecked") public class TestRuleChooseDependent { /* Make Left Side Dependent */ private static final int LEFT_SIDE = 1; /* Make Right Side Dependent */ private static final int RIGHT_SIDE = 2; /* Make Neither Side Dependent */ private static final int NEITHER_SIDE = 3; private QueryMetadataInterface metadata = RealMetadataFactory.example1Cached(); // ################################## TEST HELPERS ################################ public PlanNode createAccessNode(Collection groupSymbols) throws Exception { PlanNode accessNode = NodeFactory.getNewNode(NodeConstants.Types.ACCESS); PlanNode joinNode = NodeFactory.getNewNode(NodeConstants.Types.JOIN); PlanNode sourceNode = NodeFactory.getNewNode(NodeConstants.Types.SOURCE); joinNode.setProperty(NodeConstants.Info.JOIN_TYPE, JoinType.JOIN_INNER); List crits = new ArrayList(); crits.add(new CompareCriteria(getElementSymbol(1,1), CompareCriteria.EQ, getElementSymbol(2,1))); joinNode.setProperty(NodeConstants.Info.JOIN_CRITERIA, crits); joinNode.addFirstChild(accessNode); accessNode.addFirstChild(sourceNode); Iterator i = groupSymbols.iterator(); while (i.hasNext()) { GroupSymbol gs = (GroupSymbol)i.next(); accessNode.addGroup(gs); sourceNode.addGroup(gs); } return accessNode; } public GroupSymbol getVirtualGroup() throws Exception { GroupSymbol gs = new GroupSymbol("vm1.g1"); //$NON-NLS-1$ ResolverUtil.resolveGroup(gs, metadata); return gs; } public GroupSymbol getPhysicalGroup(int num) throws Exception { String id = "pm1.g" + num; //$NON-NLS-1$ GroupSymbol gs = new GroupSymbol(id); ResolverUtil.resolveGroup(gs, metadata); return gs; } public GroupSymbol getPhysicalGroup(int modelNum, int num) throws Exception { String id = "pm" + modelNum + ".g" + num; //$NON-NLS-1$ //$NON-NLS-2$ GroupSymbol gs = new GroupSymbol(id); ResolverUtil.resolveGroup(gs, metadata); return gs; } public GroupSymbol getPhysicalGroupWithAlias(int num, String alias) throws Exception { String id = "pm1.g" + num; //$NON-NLS-1$ GroupSymbol gs = new GroupSymbol(alias, id); ResolverUtil.resolveGroup(gs, metadata); return gs; } public ElementSymbol getElementSymbol(int groupNum, int elementNum) throws Exception { String id = "pm1.g" + groupNum + ".e" + elementNum; //$NON-NLS-1$ //$NON-NLS-2$ ElementSymbol es = new ElementSymbol(id); es.setMetadataID(this.metadata.getElementID(id)); es.setGroupSymbol(getPhysicalGroup(groupNum)); return es; } public ElementSymbol getElementSymbol(int modelNum, int groupNum, int elementNum) throws Exception { String id = "pm" + modelNum + ".g" + groupNum + ".e" + elementNum; //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$ ElementSymbol es = new ElementSymbol(id); es.setMetadataID(this.metadata.getElementID(id)); es.setGroupSymbol(getPhysicalGroup(modelNum, groupNum)); return es; } public ElementSymbol getElementSymbolWithGroupAlias(int groupNum, int elementNum, String alias) throws Exception { String id = "pm1.g" + groupNum + ".e" + elementNum; //$NON-NLS-1$ //$NON-NLS-2$ ElementSymbol es = new ElementSymbol(id); es.setMetadataID(this.metadata.getElementID(id)); es.setGroupSymbol(getPhysicalGroupWithAlias(groupNum, alias)); return es; } public Query createBaseQuery() throws Exception { Query query = new Query(); Select select = new Select(); select.addSymbol(getElementSymbol(1,1)); query.setSelect(select); From from = new From(); from.addGroup(getPhysicalGroup(1)); query.setFrom(from); return query; } public void helpTestValidJoin(PlanNode joinNode, PlanNode accessNode, boolean expectedValid) throws QueryMetadataException, TeiidComponentException { RuleChooseDependent rule = new RuleChooseDependent(); RuleChooseJoinStrategy.chooseJoinStrategy(joinNode, metadata); boolean isValid = rule.isValidJoin(joinNode, accessNode, AnalysisRecord.createNonRecordingRecord()); assertEquals("Valid join check is wrong ", expectedValid, isValid); //$NON-NLS-1$ } /** * Tests choosing from two eligible sibling access nodes, and then tests marking * the chosen one dependent. This method sets up a bogus plan tree using a * bogus project parent node, an inner join node using the supplied join criteria, and * two access nodes using each of the groups and (optional) atomic criteria. Then * this method tests that, if an access node is chosen, it can be marked dependent, * and that the chosen one is the one which was expected to be marked dependent. * @param atomicRequestGroup1 GroupSymbol to select * from in atomic request 1 * @param atomicRequestCrit1 optional, may be null * @param atomicRequestGroup2 GroupSymbol to select * from in atomic request 2 * @param atomicRequestCrit2 optional, may be null * @param joinCriteria Collection of Criteria to add to join node * @param expectedMadeDependent one of the three outcome possibility class constants * @throws TeiidComponentException * @throws QueryMetadataException * @throws QueryPlannerException */ private void helpTestChooseSiblingAndMarkDependent(GroupSymbol atomicRequestGroup1, Criteria atomicRequestCrit1, GroupSymbol atomicRequestGroup2, Criteria atomicRequestCrit2, Collection joinCriteria, int expectedMadeDependent) throws QueryPlannerException, QueryMetadataException, TeiidComponentException { helpTestChooseSiblingAndMarkDependent(atomicRequestGroup1, atomicRequestCrit1, null, null, null, atomicRequestGroup2, atomicRequestCrit2, null, null, null, joinCriteria, expectedMadeDependent, null, null); } /** * Tests choosing from two eligible sibling access nodes, and then tests marking * the chosen one dependent. This method sets up a bogus plan tree using a * bogus project parent node, a join node using the supplied join criteria, and * two access nodes using each of the groups and (optional) atomic criteria and * join criteria. Then * this method tests that, if an access node is chosen, it is marked dependent, * and that the chosen one is the one which was expected to be marked dependent. * @param atomicRequestGroup1 GroupSymbol to select from in atomic request 1 * @param atomicRequestCrit1 optional, may be null * @param atomicRequestGroup1a optional, may be null * @param atomicRequestCrit1a optional, may be null * @param atomicJoinCriteria1 optional, may be null * @param atomicRequestGroup2 GroupSymbol to select from in atomic request 2 * @param atomicRequestCrit2 optional, may be null * @param atomicRequestGroup2a optional, may be null * @param atomicRequestCrit2a optional, may be null * @param atomicJoinCriteria2 optional, may be null * @param joinCriteria Collection of Criteria to add to outer join node * @param expectedMadeDependent one of the three outcome possibility class constants * @throws TeiidComponentException * @throws QueryMetadataException * @throws QueryPlannerException */ private void helpTestChooseSiblingAndMarkDependent(GroupSymbol atomicRequestGroup1, Criteria atomicRequestCrit1, //optional GroupSymbol atomicRequestGroup1a, //optional Criteria atomicRequestCrit1a, //optional Collection atomicJoinCriteria1, //optional GroupSymbol atomicRequestGroup2, Criteria atomicRequestCrit2, //optional GroupSymbol atomicRequestGroup2a, //optional Criteria atomicRequestCrit2a, //optional Collection atomicJoinCriteria2, //optional Collection joinCriteria, int expectedMadeDependent, Number expectedCost1, Number expectedCost2) throws QueryPlannerException, QueryMetadataException, TeiidComponentException { //EXAMPLE: // Project(groups=[]) // Join(groups=[], props={21=joinCriteria, 23=true, 22=INNER JOIN}) // Access(groups=[atomicRequestGroup1], props={...}) // Source(groups=[atomicRequestGroup1]) // Access(groups=[atomicRequestGroup2, atomicRequestGroup2a], props={...}) // Join(groups=[atomicRequestGroup2, atomicRequestGroup2a], props={21=[atomicJoinCriteria2], 23=true, 22=INNER JOIN}) // Select(groups=[atomicRequestGroup2], props={40=atomicRequestCrit2}) // Source(groups=[atomicRequestGroup2]) // Source(groups=[atomicRequestGroup2a]) PlanNode accessNode1 = NodeFactory.getNewNode(NodeConstants.Types.ACCESS); accessNode1.addGroup(atomicRequestGroup1); if (atomicRequestGroup1a != null){ accessNode1.addGroup(atomicRequestGroup1a); } PlanNode accessNode2 = NodeFactory.getNewNode(NodeConstants.Types.ACCESS); accessNode2.addGroup(atomicRequestGroup2); if (atomicRequestGroup2a != null){ accessNode2.addGroup(atomicRequestGroup2a); } PlanNode joinNode = NodeFactory.getNewNode(NodeConstants.Types.JOIN); joinNode.setProperty(NodeConstants.Info.JOIN_TYPE, JoinType.JOIN_INNER); joinNode.setProperty(NodeConstants.Info.JOIN_CRITERIA, joinCriteria); joinNode.setProperty(NodeConstants.Info.JOIN_STRATEGY, JoinStrategyType.NESTED_LOOP); joinNode.addLastChild(accessNode1); joinNode.addLastChild(accessNode2); PlanNode bogusParentNode = NodeFactory.getNewNode(NodeConstants.Types.PROJECT); bogusParentNode.addLastChild(joinNode); //FIRST (LEFT) BRANCH OF TREE PlanNode sourceNode1 = NodeFactory.getNewNode(NodeConstants.Types.SOURCE); sourceNode1.addGroup(atomicRequestGroup1); if (atomicRequestCrit1 != null){ PlanNode selectNode1 = NodeFactory.getNewNode(NodeConstants.Types.SELECT); selectNode1.setProperty(NodeConstants.Info.SELECT_CRITERIA, atomicRequestCrit1); selectNode1.addGroup(atomicRequestGroup1); selectNode1.addFirstChild(sourceNode1); if (atomicRequestGroup1a != null){ PlanNode atomicJoinNode1 = NodeFactory.getNewNode(NodeConstants.Types.JOIN); if (atomicJoinCriteria1.isEmpty()){ atomicJoinNode1.setProperty(NodeConstants.Info.JOIN_TYPE, JoinType.JOIN_CROSS); } else { atomicJoinNode1.setProperty(NodeConstants.Info.JOIN_TYPE, JoinType.JOIN_INNER); atomicJoinNode1.setProperty(NodeConstants.Info.JOIN_CRITERIA, atomicJoinCriteria1); } atomicJoinNode1.addGroup(atomicRequestGroup1); atomicJoinNode1.addGroup(atomicRequestGroup1a); atomicJoinNode1.addLastChild(selectNode1); PlanNode sourceNode1a = NodeFactory.getNewNode(NodeConstants.Types.SOURCE); sourceNode1a.addGroup(atomicRequestGroup1a); if (atomicRequestCrit1a != null){ PlanNode selectNode1a = NodeFactory.getNewNode(NodeConstants.Types.SELECT); selectNode1a.setProperty(NodeConstants.Info.SELECT_CRITERIA, atomicRequestCrit1a); selectNode1a.addGroup(atomicRequestGroup1a); selectNode1a.addFirstChild(sourceNode1a); atomicJoinNode1.addLastChild(selectNode1a); } else { atomicJoinNode1.addLastChild(sourceNode1a); } accessNode1.addLastChild(atomicJoinNode1); } else { accessNode1.addFirstChild(selectNode1); } } else { accessNode1.addFirstChild(sourceNode1); } //SECOND (RIGHT) BRANCH OF TREE PlanNode sourceNode2 = NodeFactory.getNewNode(NodeConstants.Types.SOURCE); sourceNode2.addGroup(atomicRequestGroup2); if (atomicRequestCrit2 != null){ PlanNode selectNode2 = NodeFactory.getNewNode(NodeConstants.Types.SELECT); selectNode2.setProperty(NodeConstants.Info.SELECT_CRITERIA, atomicRequestCrit2); selectNode2.addGroup(atomicRequestGroup2); selectNode2.addFirstChild(sourceNode2); if (atomicRequestGroup2a != null){ PlanNode atomicJoinNode2 = NodeFactory.getNewNode(NodeConstants.Types.JOIN); if (atomicJoinCriteria2.isEmpty()){ atomicJoinNode2.setProperty(NodeConstants.Info.JOIN_TYPE, JoinType.JOIN_CROSS); } else { atomicJoinNode2.setProperty(NodeConstants.Info.JOIN_TYPE, JoinType.JOIN_INNER); atomicJoinNode2.setProperty(NodeConstants.Info.JOIN_CRITERIA, atomicJoinCriteria2); } atomicJoinNode2.addGroup(atomicRequestGroup2); atomicJoinNode2.addGroup(atomicRequestGroup2a); atomicJoinNode2.addLastChild(selectNode2); PlanNode sourceNode2a = NodeFactory.getNewNode(NodeConstants.Types.SOURCE); sourceNode2a.addGroup(atomicRequestGroup2a); if (atomicRequestCrit2a != null){ PlanNode selectNode2a = NodeFactory.getNewNode(NodeConstants.Types.SELECT); selectNode2a.setProperty(NodeConstants.Info.SELECT_CRITERIA, atomicRequestCrit2a); selectNode2a.addGroup(atomicRequestGroup2a); selectNode2a.addFirstChild(sourceNode2a); atomicJoinNode2.addLastChild(selectNode2a); } else { atomicJoinNode2.addLastChild(sourceNode2a); } accessNode2.addLastChild(atomicJoinNode2); } else { accessNode2.addFirstChild(selectNode2); } } else { accessNode2.addFirstChild(sourceNode2); } //Add access pattern(s) RulePlaceAccess.addAccessPatternsProperty(accessNode1, metadata); RulePlaceAccess.addAccessPatternsProperty(accessNode2, metadata); if (DEBUG){ System.out.println("Before."); //$NON-NLS-1$ System.out.println(bogusParentNode); } RuleChooseDependent rule = new RuleChooseDependent(); RuleChooseJoinStrategy.chooseJoinStrategy(joinNode, metadata); FakeCapabilitiesFinder capFinder = new FakeCapabilitiesFinder(); capFinder.addCapabilities("pm1", TestOptimizer.getTypicalCapabilities()); //$NON-NLS-1$ capFinder.addCapabilities("pm2", TestOptimizer.getTypicalCapabilities()); //$NON-NLS-1$ capFinder.addCapabilities("pm3", TestOptimizer.getTypicalCapabilities()); //$NON-NLS-1$ capFinder.addCapabilities("pm4", TestOptimizer.getTypicalCapabilities()); //$NON-NLS-1$ rule.execute(bogusParentNode, metadata, capFinder, new RuleStack(), null, new CommandContext()); if (DEBUG){ System.out.println("Done."); //$NON-NLS-1$ System.out.println(bogusParentNode); } Object prop1 = joinNode.getProperty(NodeConstants.Info.DEPENDENT_VALUE_SOURCE); if (expectedMadeDependent == LEFT_SIDE){ assertNotNull("Expected one side to be made dependent", prop1); //$NON-NLS-1$ assertEquals(accessNode1, FrameUtil.findJoinSourceNode(joinNode.getLastChild())); } else if (expectedMadeDependent == RIGHT_SIDE){ assertNotNull("Expected one side to be made dependent", prop1); //$NON-NLS-1$ assertEquals(accessNode2, FrameUtil.findJoinSourceNode(joinNode.getLastChild())); } else if (expectedMadeDependent == NEITHER_SIDE){ assertNull("Neither side should be dependent", prop1); //$NON-NLS-1$ } else { fail("Invalid test constant " + expectedMadeDependent); //$NON-NLS-1$ } Float cost1 = (Float)accessNode1.getProperty(NodeConstants.Info.EST_CARDINALITY); Float cost2 = (Float)accessNode2.getProperty(NodeConstants.Info.EST_CARDINALITY); assertNotNull(cost2); assertNotNull(cost1); if (expectedCost1 != null) { assertEquals(expectedCost1.longValue(), cost1.longValue()); assertEquals(expectedCost2.longValue(), cost2.longValue()); } } // ################################## ACTUAL TESTS ################################ @Test public void testValidJoin1() throws Exception { PlanNode accessNode = NodeFactory.getNewNode(NodeConstants.Types.ACCESS); accessNode.addGroup(getPhysicalGroup(1)); PlanNode joinNode = NodeFactory.getNewNode(NodeConstants.Types.JOIN); joinNode.setProperty(NodeConstants.Info.JOIN_TYPE, JoinType.JOIN_CROSS); joinNode.addFirstChild(accessNode); helpTestValidJoin(joinNode, accessNode, false); } @Test public void testValidJoin2() throws Exception { PlanNode accessNode = NodeFactory.getNewNode(NodeConstants.Types.ACCESS); accessNode.addGroup(getPhysicalGroup(1)); PlanNode joinNode = NodeFactory.getNewNode(NodeConstants.Types.JOIN); joinNode.setProperty(NodeConstants.Info.JOIN_TYPE, JoinType.JOIN_FULL_OUTER); joinNode.setProperty(NodeConstants.Info.JOIN_CRITERIA, Arrays.asList(QueryRewriter.FALSE_CRITERIA)); joinNode.addFirstChild(accessNode); helpTestValidJoin(joinNode, accessNode, false); } @Test public void testValidJoin3() throws Exception { PlanNode accessNode1 = NodeFactory.getNewNode(NodeConstants.Types.ACCESS); PlanNode accessNode2 = NodeFactory.getNewNode(NodeConstants.Types.ACCESS); accessNode1.addGroup(getPhysicalGroup(1)); accessNode2.addGroup(getPhysicalGroup(2)); PlanNode joinNode = NodeFactory.getNewNode(NodeConstants.Types.JOIN); joinNode.setProperty(NodeConstants.Info.JOIN_TYPE, JoinType.JOIN_RIGHT_OUTER); List crits = new ArrayList(); crits.add(new CompareCriteria(getElementSymbol(1,1), CompareCriteria.EQ, getElementSymbol(2,1))); joinNode.setProperty(NodeConstants.Info.JOIN_CRITERIA, crits); joinNode.addLastChild(accessNode1); joinNode.addLastChild(accessNode2); helpTestValidJoin(joinNode, accessNode1, true); } @Test public void testValidJoin4() throws Exception { PlanNode accessNode1 = NodeFactory.getNewNode(NodeConstants.Types.ACCESS); PlanNode accessNode2 = NodeFactory.getNewNode(NodeConstants.Types.ACCESS); PlanNode joinNode = NodeFactory.getNewNode(NodeConstants.Types.JOIN); joinNode.setProperty(NodeConstants.Info.JOIN_TYPE, JoinType.JOIN_RIGHT_OUTER); List crits = new ArrayList(); crits.add(new CompareCriteria(getElementSymbol(1,1), CompareCriteria.EQ, getElementSymbol(2,1))); joinNode.setProperty(NodeConstants.Info.JOIN_CRITERIA, crits); joinNode.addLastChild(accessNode1); joinNode.addLastChild(accessNode2); helpTestValidJoin(joinNode, accessNode2, false); } @Test public void testValidJoin5() throws Exception { PlanNode accessNode1 = NodeFactory.getNewNode(NodeConstants.Types.ACCESS); PlanNode accessNode2 = NodeFactory.getNewNode(NodeConstants.Types.ACCESS); PlanNode joinNode = NodeFactory.getNewNode(NodeConstants.Types.JOIN); joinNode.setProperty(NodeConstants.Info.JOIN_TYPE, JoinType.JOIN_LEFT_OUTER); List crits = new ArrayList(); crits.add(new CompareCriteria(getElementSymbol(1,1), CompareCriteria.EQ, getElementSymbol(2,1))); joinNode.setProperty(NodeConstants.Info.JOIN_CRITERIA, crits); joinNode.addLastChild(accessNode1); joinNode.addLastChild(accessNode2); helpTestValidJoin(joinNode, accessNode1, false); } @Test public void testValidJoin6() throws Exception { PlanNode accessNode1 = NodeFactory.getNewNode(NodeConstants.Types.ACCESS); PlanNode accessNode2 = NodeFactory.getNewNode(NodeConstants.Types.ACCESS); accessNode1.addGroup(getPhysicalGroup(1)); accessNode2.addGroup(getPhysicalGroup(2)); PlanNode joinNode = NodeFactory.getNewNode(NodeConstants.Types.JOIN); joinNode.setProperty(NodeConstants.Info.JOIN_TYPE, JoinType.JOIN_LEFT_OUTER); List crits = new ArrayList(); crits.add(new CompareCriteria(getElementSymbol(1,1), CompareCriteria.EQ, getElementSymbol(2,1))); joinNode.setProperty(NodeConstants.Info.JOIN_CRITERIA, crits); joinNode.addLastChild(accessNode1); joinNode.addLastChild(accessNode2); helpTestValidJoin(joinNode, accessNode2, true); } /** * Tests that heuristics will take a primary key in the atomic criteria into account when * making a dependent join. */ @Test public void testChooseKey() throws Exception { //override default metadata this.metadata = RealMetadataFactory.example4(); GroupSymbol group1 = getPhysicalGroup(2,3); GroupSymbol group2 = getPhysicalGroup(3,3); //Join criteria ElementSymbol group1e1 = getElementSymbol(2,3,1); ElementSymbol group2e1 = getElementSymbol(3,3,1); CompareCriteria crit = new CompareCriteria(group2e1, CompareCriteria.EQ, group1e1); ArrayList crits = new ArrayList(1); crits.add(crit); Criteria atomicCrit1 = null; Criteria atomicCrit2 = new CompareCriteria(group2e1, CompareCriteria.EQ, new Constant(new Integer(5))); int expected = LEFT_SIDE; helpTestChooseSiblingAndMarkDependent(group1, atomicCrit1, group2, atomicCrit2, crits, expected); expected = RIGHT_SIDE; helpTestChooseSiblingAndMarkDependent(group2, atomicCrit2, group1, atomicCrit1, crits, expected); } /** * Neither side should be chosen since the left side lacks cardinality information and the right is not strong */ @Test public void testChooseKey2() throws Exception { //override default metadata this.metadata = RealMetadataFactory.example4(); GroupSymbol group1 = getPhysicalGroup(2,3); //no key GroupSymbol group1a = null; GroupSymbol group2 = getPhysicalGroup(3,3); //has key GroupSymbol group2a = getPhysicalGroup(3,2); //no key ElementSymbol group1e1 = getElementSymbol(2,3,1); ElementSymbol group2e1 = getElementSymbol(3,3,1); ElementSymbol group2e2 = getElementSymbol(3,3,2); ElementSymbol group2ae1 = getElementSymbol(3,2,1); //Outer Join criteria CompareCriteria crit = new CompareCriteria(group2e1, CompareCriteria.EQ, group1e1); ArrayList crits = new ArrayList(1); crits.add(crit); //atomic select criteria Criteria atomicCrit1 = null; Criteria atomicCrit1a = null; Criteria atomicCrit2 = new CompareCriteria(group2e2, CompareCriteria.EQ, new Constant(new Integer(5))); Criteria atomicCrit2a = null; //atomic Join criteria 1 Collection atomicJoinCrits1 = null; //atomic Join criteria 2 CompareCriteria atomicJoinCrit2 = new CompareCriteria(group2ae1, CompareCriteria.EQ, group2e1); ArrayList atomicJoinCrits2 = new ArrayList(1); atomicJoinCrits2.add(atomicJoinCrit2); int expected = NEITHER_SIDE; helpTestChooseSiblingAndMarkDependent( group1, atomicCrit1, group1a, atomicCrit1a, atomicJoinCrits1, group2, atomicCrit2, group2a, atomicCrit2a, atomicJoinCrits2, crits, expected, -1, 99798); } /** * Tests that heuristics will take cardinality of a group into account when * making a dependent join. */ @Test public void testCardinality() throws Exception { //override default metadata this.metadata = RealMetadataFactory.example4(); GroupSymbol group1 = getPhysicalGroup(1,2); GroupSymbol group2 = getPhysicalGroup(2,2); //Join criteria ElementSymbol pm1g2e1 = getElementSymbol(1,2,1); ElementSymbol pm2g2e1 = getElementSymbol(2,2,1); CompareCriteria crit = new CompareCriteria(pm2g2e1, CompareCriteria.EQ, pm1g2e1); ArrayList crits = new ArrayList(2); crits.add(crit); ElementSymbol pm1g2e2 = getElementSymbol(1,2,2); ElementSymbol pm2g2e2 = getElementSymbol(2,2,2); CompareCriteria crit2 = new CompareCriteria(pm1g2e2, CompareCriteria.EQ, pm2g2e2); crits.add(crit2); Criteria atomicCrit1 = null; Criteria atomicCrit2 = null; int expected = RIGHT_SIDE; helpTestChooseSiblingAndMarkDependent(group1, atomicCrit1, group2, atomicCrit2, crits, expected); expected = LEFT_SIDE; helpTestChooseSiblingAndMarkDependent(group2, atomicCrit2, group1, atomicCrit1, crits, expected); } /** * Tests that heuristics will take cardinality of a group into account when * making a dependent join, and that this information supercedes a key * in the atomic criteria. */ @Test public void testCardinalityAndKey() throws Exception { //override default metadata this.metadata = RealMetadataFactory.example4(); GroupSymbol group1 = getPhysicalGroup(1,2); GroupSymbol group2 = getPhysicalGroup(2,2); //Join criteria ElementSymbol pm1g2e1 = getElementSymbol(1,2,1); ElementSymbol pm2g2e1 = getElementSymbol(2,2,1); CompareCriteria crit = new CompareCriteria(pm2g2e1, CompareCriteria.EQ, pm1g2e1); ArrayList crits = new ArrayList(1); crits.add(crit); ElementSymbol pm1g2e2 = getElementSymbol(1,2,2); ElementSymbol pm2g2e2 = getElementSymbol(2,2,2); CompareCriteria crit2 = new CompareCriteria(pm1g2e2, CompareCriteria.EQ, pm2g2e2); crits.add(crit2); Criteria atomicCrit1 = null; Criteria atomicCrit2 = null; int expected = RIGHT_SIDE; helpTestChooseSiblingAndMarkDependent(group1, atomicCrit1, group2, atomicCrit2, crits, expected); expected = LEFT_SIDE; helpTestChooseSiblingAndMarkDependent(group2, atomicCrit2, group1, atomicCrit1, crits, expected); } @Test public void testCardinalityAndKeyNestedLoop() throws Exception { //override default metadata this.metadata = RealMetadataFactory.example4(); GroupSymbol group1 = getPhysicalGroup(1,2); GroupSymbol group2 = getPhysicalGroup(2,2); //Join criteria ElementSymbol pm1g2e1 = getElementSymbol(1,2,1); ElementSymbol pm2g2e1 = getElementSymbol(2,2,1); CompareCriteria crit = new CompareCriteria(pm2g2e1, CompareCriteria.EQ, pm1g2e1); ArrayList crits = new ArrayList(1); crits.add(crit); ElementSymbol pm1g2e2 = getElementSymbol(1,2,2); ElementSymbol pm2g2e2 = getElementSymbol(2,2,2); CompareCriteria crit2 = new CompareCriteria(pm1g2e2, CompareCriteria.LT, pm2g2e2); crits.add(crit2); Criteria atomicCrit1 = null; Criteria atomicCrit2 = null; int expected = RIGHT_SIDE; helpTestChooseSiblingAndMarkDependent(group1, atomicCrit1, group2, atomicCrit2, crits, expected); expected = LEFT_SIDE; helpTestChooseSiblingAndMarkDependent(group2, atomicCrit2, group1, atomicCrit1, crits, expected); } @Test public void testRejectDependentJoin() throws Exception { //override default metadata this.metadata = RealMetadataFactory.example4(); GroupSymbol group1 = getPhysicalGroup(3,1); GroupSymbol group2 = getPhysicalGroup(3,2); //Join criteria ElementSymbol pm3g1e2 = getElementSymbol(3,1,2); ElementSymbol pm3g2e2 = getElementSymbol(3,2,2); CompareCriteria crit = new CompareCriteria(pm3g1e2, CompareCriteria.EQ, pm3g2e2); ArrayList crits = new ArrayList(1); crits.add(crit); Criteria atomicCrit1 = null; Criteria atomicCrit2 = null; int expected = NEITHER_SIDE; helpTestChooseSiblingAndMarkDependent(group1, atomicCrit1, group2, atomicCrit2, crits, expected); expected = NEITHER_SIDE; helpTestChooseSiblingAndMarkDependent(group2, atomicCrit2, group1, atomicCrit1, crits, expected); } /** * Tests that join side with larger cardinality will still have a lower * cost computed because it has a criteria including a primary key */ @Test public void testCardinalityWithKeyCrit() throws Exception { //override default metadata this.metadata = RealMetadataFactory.example4(); GroupSymbol group1 = getPhysicalGroup(1,2); ElementSymbol g1e2 = getElementSymbol(1,2,2); GroupSymbol group2 = getPhysicalGroup(3,3); ElementSymbol g2e1 = getElementSymbol(3,3,1); ElementSymbol g2e2 = getElementSymbol(3,3,2); //Join criteria ArrayList crits = new ArrayList(1); CompareCriteria crit2 = new CompareCriteria(g1e2, CompareCriteria.EQ, g2e2); crits.add(crit2); Criteria atomicCrit1 = null; Criteria atomicCrit2 = new CompareCriteria(g2e1, CompareCriteria.EQ, new Constant(new Integer(5))); int expected = LEFT_SIDE; helpTestChooseSiblingAndMarkDependent(group1, atomicCrit1, group2, atomicCrit2, crits, expected); expected = RIGHT_SIDE; helpTestChooseSiblingAndMarkDependent(group2, atomicCrit2, group1, atomicCrit1, crits, expected); } /** * Tests that join side with larger cardinality will still have a lower * cost computed because it has a criteria including a primary key */ @Test public void testCardinalityWithKeyCompoundCritAND() throws Exception { //override default metadata this.metadata = RealMetadataFactory.example4(); GroupSymbol group1 = getPhysicalGroup(1,2); ElementSymbol g1e2 = getElementSymbol(1,2,2); GroupSymbol group2 = getPhysicalGroup(3,3); ElementSymbol g2e1 = getElementSymbol(3,3,1); ElementSymbol g2e2 = getElementSymbol(3,3,2); //Join criteria ArrayList crits = new ArrayList(1); crits.add(new CompareCriteria(g1e2, CompareCriteria.EQ, g2e2)); Criteria atomicCrit1 = null; Criteria crit1 = new CompareCriteria(g2e1, CompareCriteria.EQ, new Constant(new Integer(5))); Criteria crit2 = new CompareCriteria(g2e1, CompareCriteria.EQ, new Constant(new Integer(7))); CompoundCriteria atomicCrit2 = new CompoundCriteria(CompoundCriteria.AND, crit1, crit2); int expected = LEFT_SIDE; helpTestChooseSiblingAndMarkDependent(group1, atomicCrit1, group2, atomicCrit2, crits, expected); expected = RIGHT_SIDE; helpTestChooseSiblingAndMarkDependent(group2, atomicCrit2, group1, atomicCrit1, crits, expected); } /** * Tests that join side with larger cardinality will still have a lower * cost computed because it has a criteria including a primary key. * Defect 8445 */ @Test public void testCardinalityWithKeyCompoundCritOR() throws Exception { //override default metadata this.metadata = RealMetadataFactory.example4(); GroupSymbol group1 = getPhysicalGroup(1,2); ElementSymbol g1e2 = getElementSymbol(1,2,2); GroupSymbol group2 = getPhysicalGroup(3,3); ElementSymbol g2e1 = getElementSymbol(3,3,1); ElementSymbol g2e2 = getElementSymbol(3,3,2); //Join criteria ArrayList crits = new ArrayList(1); crits.add(new CompareCriteria(g1e2, CompareCriteria.EQ, g2e2)); Criteria atomicCrit1 = null; Criteria crit1 = new CompareCriteria(g2e1, CompareCriteria.EQ, new Constant(new Integer(5))); Criteria crit2 = new CompareCriteria(g2e1, CompareCriteria.EQ, new Constant(new Integer(7))); CompoundCriteria atomicCrit2 = new CompoundCriteria(CompoundCriteria.OR, crit1, crit2); int expected = LEFT_SIDE; helpTestChooseSiblingAndMarkDependent(group1, atomicCrit1, group2, atomicCrit2, crits, expected); expected = RIGHT_SIDE; helpTestChooseSiblingAndMarkDependent(group2, atomicCrit2, group1, atomicCrit1, crits, expected); } /** * Tests SetCriteria against a key column in the atomic criteria */ @Test public void testCardinalityWithKeySetCrit() throws Exception { //override default metadata this.metadata = RealMetadataFactory.example4(); GroupSymbol group1 = getPhysicalGroup(1,2); ElementSymbol g1e2 = getElementSymbol(1,2,2); GroupSymbol group2 = getPhysicalGroup(3,3); ElementSymbol g2e1 = getElementSymbol(3,3,1); ElementSymbol g2e2 = getElementSymbol(3,3,2); //Join criteria ArrayList crits = new ArrayList(1); CompareCriteria crit2 = new CompareCriteria(g1e2, CompareCriteria.EQ, g2e2); crits.add(crit2); Criteria atomicCrit1 = null; Collection values = new LinkedList(); values.add(new Constant(new Integer(3))); values.add(new Constant(new Integer(4))); values.add(new Constant(new Integer(5))); Criteria atomicCrit2 = new SetCriteria(g2e1, values); int expected = LEFT_SIDE; helpTestChooseSiblingAndMarkDependent(group1, atomicCrit1, group2, atomicCrit2, crits, expected); expected = RIGHT_SIDE; helpTestChooseSiblingAndMarkDependent(group2, atomicCrit2, group1, atomicCrit1, crits, expected); } /** * Tests SetCriteria in the atomic criteria */ @Test public void testCardinalityWithKeyMatchCrit() throws Exception { //override default metadata this.metadata = RealMetadataFactory.example4(); GroupSymbol group1 = getPhysicalGroup(1,2); ElementSymbol g1e2 = getElementSymbol(1,2,2); GroupSymbol group2 = getPhysicalGroup(3,3); ElementSymbol g2e1 = getElementSymbol(3,3,1); ElementSymbol g2e2 = getElementSymbol(3,3,2); //Join criteria ArrayList crits = new ArrayList(1); CompareCriteria crit2 = new CompareCriteria(g1e2, CompareCriteria.EQ, g2e2); crits.add(crit2); Criteria atomicCrit1 = null; Criteria atomicCrit2 = new MatchCriteria(g2e1, new Constant(new String("ab%"))); //$NON-NLS-1$ int expected = RIGHT_SIDE; helpTestChooseSiblingAndMarkDependent(group1, atomicCrit1, group2, atomicCrit2, crits, expected); expected = LEFT_SIDE; helpTestChooseSiblingAndMarkDependent(group2, atomicCrit2, group1, atomicCrit1, crits, expected); } /** * Tests SetCriteria in the atomic criteria */ @Test public void testCardinalityWithKeyIsNullCrit() throws Exception { //override default metadata this.metadata = RealMetadataFactory.example4(); GroupSymbol group1 = getPhysicalGroup(1,2); ElementSymbol g1e2 = getElementSymbol(1,2,2); GroupSymbol group2 = getPhysicalGroup(3,3); ElementSymbol g2e1 = getElementSymbol(3,3,1); ElementSymbol g2e2 = getElementSymbol(3,3,2); //Join criteria ArrayList crits = new ArrayList(1); CompareCriteria crit2 = new CompareCriteria(g1e2, CompareCriteria.EQ, g2e2); crits.add(crit2); Criteria atomicCrit1 = null; Criteria atomicCrit2 = new IsNullCriteria(g2e1); int expected = LEFT_SIDE; helpTestChooseSiblingAndMarkDependent(group1, atomicCrit1, group2, atomicCrit2, crits, expected); expected = RIGHT_SIDE; helpTestChooseSiblingAndMarkDependent(group2, atomicCrit2, group1, atomicCrit1, crits, expected); } /** * Tests NotCriteria in the atomic criteria */ @Test public void testCardinalityWithKeyNotCrit() throws Exception { //override default metadata this.metadata = RealMetadataFactory.example4(); GroupSymbol group1 = getPhysicalGroup(1,2); ElementSymbol g1e2 = getElementSymbol(1,2,2); GroupSymbol group2 = getPhysicalGroup(3,3); ElementSymbol g2e1 = getElementSymbol(3,3,1); ElementSymbol g2e2 = getElementSymbol(3,3,2); //Join criteria ArrayList crits = new ArrayList(1); CompareCriteria crit2 = new CompareCriteria(g1e2, CompareCriteria.EQ, g2e2); crits.add(crit2); Criteria atomicCrit1 = null; Criteria atomicCrit2 = new CompareCriteria(g2e1, CompareCriteria.EQ, new Constant(new Integer(5))); atomicCrit2 = new NotCriteria(atomicCrit2); int expected = RIGHT_SIDE; helpTestChooseSiblingAndMarkDependent(group1, atomicCrit1, group2, atomicCrit2, crits, expected); expected = LEFT_SIDE; helpTestChooseSiblingAndMarkDependent(group2, atomicCrit2, group1, atomicCrit1, crits, expected); } /** * Tests that join side with larger cardinality will still have a lower * cost computed because it has a criteria including a primary key */ @Test public void testCardinalityWithKeyComplexCrit() throws Exception { //override default metadata this.metadata = RealMetadataFactory.example4(); GroupSymbol group1 = getPhysicalGroup(1,2); ElementSymbol g1e2 = getElementSymbol(1,2,2); GroupSymbol group2 = getPhysicalGroup(3,3); ElementSymbol g2e1 = getElementSymbol(3,3,1); ElementSymbol g2e2 = getElementSymbol(3,3,2); //Join criteria ArrayList crits = new ArrayList(1); crits.add(new CompareCriteria(g1e2, CompareCriteria.EQ, g2e2)); Criteria atomicCrit1 = null; Criteria crit1 = new CompareCriteria(g2e1, CompareCriteria.EQ, new Constant(new Integer(5))); Criteria crit2 = new CompareCriteria(g2e1, CompareCriteria.EQ, new Constant(new Integer(7))); CompoundCriteria atomicCrit2 = new CompoundCriteria(CompoundCriteria.AND, crit1, crit2); Criteria crit3 = new MatchCriteria(g2e1, new Constant(new String("ab"))); //$NON-NLS-1$ atomicCrit2 = new CompoundCriteria(CompoundCriteria.OR, atomicCrit2, crit3); int expected = LEFT_SIDE; helpTestChooseSiblingAndMarkDependent(group1, atomicCrit1, group2, atomicCrit2, crits, expected); expected = RIGHT_SIDE; helpTestChooseSiblingAndMarkDependent(group2, atomicCrit2, group1, atomicCrit1, crits, expected); } @Test public void testCardinalityWithKeyComplexCrit2() throws Exception { //override default metadata this.metadata = RealMetadataFactory.example4(); GroupSymbol group1 = getPhysicalGroup(1,2); ElementSymbol g1e2 = getElementSymbol(1,2,2); GroupSymbol group2 = getPhysicalGroup(3,3); ElementSymbol g2e1 = getElementSymbol(3,3,1); ElementSymbol g2e2 = getElementSymbol(3,3,2); //Join criteria ArrayList crits = new ArrayList(1); crits.add(new CompareCriteria(g1e2, CompareCriteria.EQ, g2e2)); Criteria atomicCrit1 = null; Criteria crit1 = new CompareCriteria(g2e1, CompareCriteria.GT, new Constant(new Integer(5))); Criteria crit2 = new CompareCriteria(g2e1, CompareCriteria.LT, new Constant(new Integer(7))); Criteria atomicCrit2 = new CompoundCriteria(CompoundCriteria.AND, crit1, crit2); Criteria crit3 = new MatchCriteria(g2e1, new Constant(new String("cd%"))); //$NON-NLS-1$ atomicCrit2 = new CompoundCriteria(CompoundCriteria.OR, atomicCrit2, crit3); atomicCrit2 = new NotCriteria(atomicCrit2); int expected = RIGHT_SIDE; helpTestChooseSiblingAndMarkDependent(group1, atomicCrit1, group2, atomicCrit2, crits, expected); expected = LEFT_SIDE; helpTestChooseSiblingAndMarkDependent(group2, atomicCrit2, group1, atomicCrit1, crits, expected); } @Test public void testCardinalityWithKeyComplexCrit3() throws Exception { //override default metadata this.metadata = RealMetadataFactory.example4(); GroupSymbol group1 = getPhysicalGroup(1,2); ElementSymbol g1e2 = getElementSymbol(1,2,2); GroupSymbol group2 = getPhysicalGroup(3,3); ElementSymbol g2e1 = getElementSymbol(3,3,1); ElementSymbol g2e2 = getElementSymbol(3,3,2); //Join criteria ArrayList crits = new ArrayList(1); crits.add(new CompareCriteria(g1e2, CompareCriteria.EQ, g2e2)); Criteria atomicCrit1 = null; Criteria crit1 = new CompareCriteria(g2e1, CompareCriteria.GE, new Constant(new Integer(5))); Criteria crit2 = new CompareCriteria(g2e1, CompareCriteria.NE, new Constant(new Integer(7))); Criteria atomicCrit2 = new CompoundCriteria(CompoundCriteria.OR, crit1, crit2); atomicCrit2 = new NotCriteria(atomicCrit2); Criteria crit3 = new CompareCriteria(g2e1, CompareCriteria.LE, new Constant(new Integer(25))); atomicCrit2 = new CompoundCriteria(CompoundCriteria.AND, atomicCrit2, crit3); int expected = LEFT_SIDE; helpTestChooseSiblingAndMarkDependent(group1, atomicCrit1, group2, atomicCrit2, crits, expected); expected = RIGHT_SIDE; helpTestChooseSiblingAndMarkDependent(group2, atomicCrit2, group1, atomicCrit1, crits, expected); } /** * Tests that join side with larger cardinality and non-key criteria * will be made dependent */ @Test public void testCardinalityWithNonKeyCrit() throws Exception { //override default metadata this.metadata = RealMetadataFactory.example4(); GroupSymbol group1 = getPhysicalGroup(1,2); ElementSymbol g1e1 = getElementSymbol(1,2,1); // ElementSymbol g1e2 = getElementSymbol(1,2,2); GroupSymbol group2 = getPhysicalGroup(3,3); ElementSymbol g2e1 = getElementSymbol(3,3,1); ElementSymbol g2e2 = getElementSymbol(3,3,2); //Join criteria ArrayList crits = new ArrayList(1); CompareCriteria crit2 = new CompareCriteria(g1e1, CompareCriteria.EQ, g2e1); crits.add(crit2); Criteria atomicCrit1 = null; Criteria atomicCrit2 = new CompareCriteria(g2e2, CompareCriteria.EQ, new Constant(new Integer(5))); int expected = RIGHT_SIDE; helpTestChooseSiblingAndMarkDependent(group1, atomicCrit1, group2, atomicCrit2, crits, expected); expected = LEFT_SIDE; helpTestChooseSiblingAndMarkDependent(group2, atomicCrit2, group1, atomicCrit1, crits, expected); } /** * Tests that join side with larger cardinality will still have a lower * cost computed because it has a criteria including a primary key */ @Test public void testCardinalityWithCriteriaAndJoin() throws Exception { //override default metadata this.metadata = RealMetadataFactory.example4(); GroupSymbol group1 = getPhysicalGroup(2,2); //no key GroupSymbol group1a = null; GroupSymbol group2 = getPhysicalGroup(3,3); //has key GroupSymbol group2a = getPhysicalGroup(3,1); //has key ElementSymbol group1e1 = getElementSymbol(2,2,1); ElementSymbol group2e1 = getElementSymbol(3,3,1); ElementSymbol group2e2 = getElementSymbol(3,3,2); ElementSymbol group2ae1 = getElementSymbol(3,1,1); ElementSymbol group2ae2 = getElementSymbol(3,1,2); //Outer Join criteria CompareCriteria crit = new CompareCriteria(group2e1, CompareCriteria.EQ, group1e1); ArrayList crits = new ArrayList(1); crits.add(crit); //atomic select criteria Criteria atomicCrit1 = null; Criteria atomicCrit1a = null; Criteria atomicCrit2 = new CompareCriteria(group2e1, CompareCriteria.EQ, new Constant(new Integer(5))); Criteria atomicCrit2a = new CompareCriteria(group2ae1, CompareCriteria.EQ, new Constant(new Integer(5))); //atomic Join criteria 1 Collection atomicJoinCrits1 = null; //atomic Join criteria 2 CompareCriteria atomicJoinCrit2 = new CompareCriteria(group2ae2, CompareCriteria.EQ, group2e2); ArrayList atomicJoinCrits2 = new ArrayList(1); atomicJoinCrits2.add(atomicJoinCrit2); int expected = LEFT_SIDE; helpTestChooseSiblingAndMarkDependent( group1, atomicCrit1, group1a, atomicCrit1a, atomicJoinCrits1, group2, atomicCrit2, group2a, atomicCrit2a, atomicJoinCrits2, crits, expected, 1000, 1); } @Test public void testCardinalityWithAtomicCrossJoin() throws Exception { //override default metadata this.metadata = RealMetadataFactory.example4(); GroupSymbol group1 = getPhysicalGroup(2,2); //no key GroupSymbol group1a = null; GroupSymbol group2 = getPhysicalGroup(3,3); //has key GroupSymbol group2a = getPhysicalGroup(3,1); //has key ElementSymbol group1e1 = getElementSymbol(2,2,1); ElementSymbol group2e1 = getElementSymbol(3,3,1); //Outer Join criteria CompareCriteria crit = new CompareCriteria(group2e1, CompareCriteria.EQ, group1e1); ArrayList crits = new ArrayList(1); crits.add(crit); //atomic select criteria Criteria atomicCrit1 = null; Criteria atomicCrit1a = null; Criteria atomicCrit2 = new CompareCriteria(group2e1, CompareCriteria.EQ, new Constant(new Integer(5))); Criteria atomicCrit2a = null; //atomic Join criteria 1 Collection atomicJoinCrits1 = null; //atomic Join criteria 2 List atomicJoinCrits2 = Collections.EMPTY_LIST; //INDICATES CROSS JOIN int expected = NEITHER_SIDE; helpTestChooseSiblingAndMarkDependent( group1, atomicCrit1, group1a, atomicCrit1a, atomicJoinCrits1, group2, atomicCrit2, group2a, atomicCrit2a, atomicJoinCrits2, crits, expected, 1000, 1E5); } @Test public void testCardinalityWithAtomicCrossJoin2() throws Exception { //override default metadata this.metadata = RealMetadataFactory.example4(); GroupSymbol group1 = getPhysicalGroup(2,2); //no key GroupSymbol group1a = null; GroupSymbol group2 = getPhysicalGroup(3,3); //has key GroupSymbol group2a = getPhysicalGroup(3,1); //has key ElementSymbol group1e1 = getElementSymbol(2,2,1); ElementSymbol group2e1 = getElementSymbol(3,3,1); //Outer Join criteria CompareCriteria crit = new CompareCriteria(group2e1, CompareCriteria.EQ, group1e1); ArrayList crits = new ArrayList(1); crits.add(crit); //atomic select criteria Criteria atomicCrit1 = null; Criteria atomicCrit1a = null; Criteria atomicCrit2 = new CompareCriteria(group2e1, CompareCriteria.NE, new Constant(new Integer(5))); Criteria atomicCrit2a = null; //atomic Join criteria 1 Collection atomicJoinCrits1 = null; //atomic Join criteria 2 List atomicJoinCrits2 = Collections.EMPTY_LIST; //INDICATES CROSS JOIN int expected = RIGHT_SIDE; helpTestChooseSiblingAndMarkDependent( group1, atomicCrit1, group1a, atomicCrit1a, atomicJoinCrits1, group2, atomicCrit2, group2a, atomicCrit2a, atomicJoinCrits2, crits, expected, 1000, 10000000000l); } // ################################## TEST SUITE ################################ private static final boolean DEBUG = false; }