[teiid-commits] teiid SVN: r1212 - in trunk/engine/src: main/java/com/metamatrix/query/resolver/util and 6 other directories.

teiid-commits at lists.jboss.org teiid-commits at lists.jboss.org
Tue Aug 4 12:37:03 EDT 2009


Author: shawkins
Date: 2009-08-04 12:37:03 -0400 (Tue, 04 Aug 2009)
New Revision: 1212

Modified:
   trunk/engine/src/main/java/com/metamatrix/query/optimizer/relational/rules/JoinRegion.java
   trunk/engine/src/main/java/com/metamatrix/query/optimizer/relational/rules/NewCalculateCostUtil.java
   trunk/engine/src/main/java/com/metamatrix/query/optimizer/relational/rules/RuleChooseDependent.java
   trunk/engine/src/main/java/com/metamatrix/query/optimizer/relational/rules/RuleCleanCriteria.java
   trunk/engine/src/main/java/com/metamatrix/query/optimizer/relational/rules/RuleCollapseSource.java
   trunk/engine/src/main/java/com/metamatrix/query/optimizer/relational/rules/RuleCopyCriteria.java
   trunk/engine/src/main/java/com/metamatrix/query/optimizer/relational/rules/RuleImplementJoinStrategy.java
   trunk/engine/src/main/java/com/metamatrix/query/optimizer/relational/rules/RuleMergeCriteria.java
   trunk/engine/src/main/java/com/metamatrix/query/optimizer/relational/rules/RulePushAggregates.java
   trunk/engine/src/main/java/com/metamatrix/query/optimizer/relational/rules/RulePushSelectCriteria.java
   trunk/engine/src/main/java/com/metamatrix/query/resolver/util/ResolverUtil.java
   trunk/engine/src/main/java/com/metamatrix/query/rewriter/QueryRewriter.java
   trunk/engine/src/test/java/com/metamatrix/query/optimizer/TestDependentJoins.java
   trunk/engine/src/test/java/com/metamatrix/query/optimizer/TestOptimizer.java
   trunk/engine/src/test/java/com/metamatrix/query/optimizer/relational/rules/TestCalculateCostUtil.java
   trunk/engine/src/test/java/com/metamatrix/query/optimizer/relational/rules/TestRulePushSelectCriteria.java
   trunk/engine/src/test/java/com/metamatrix/query/processor/TestProcessor.java
   trunk/engine/src/test/java/com/metamatrix/query/processor/xml/TestXMLProcessor.java
   trunk/engine/src/test/java/com/metamatrix/query/rewriter/TestQueryRewriter.java
Log:
TEIID-746 TEIID-747 updates to costing for composite keys and better handling of ndv, nnv, set ops, etc.

Modified: trunk/engine/src/main/java/com/metamatrix/query/optimizer/relational/rules/JoinRegion.java
===================================================================
--- trunk/engine/src/main/java/com/metamatrix/query/optimizer/relational/rules/JoinRegion.java	2009-07-31 15:42:46 UTC (rev 1211)
+++ trunk/engine/src/main/java/com/metamatrix/query/optimizer/relational/rules/JoinRegion.java	2009-08-04 16:37:03 UTC (rev 1212)
@@ -315,8 +315,7 @@
     public void initializeCostingInformation(QueryMetadataInterface metadata) throws QueryMetadataException, MetaMatrixComponentException {
         for (Iterator i = joinSourceNodes.values().iterator(); i.hasNext();) {
             PlanNode node = (PlanNode)i.next();
-            float value = NewCalculateCostUtil.computeCostForTree(node, metadata);
-            node.setProperty(NodeConstants.Info.EST_CARDINALITY, new Float(value));
+            NewCalculateCostUtil.computeCostForTree(node, metadata);
         }
         
         estimateCriteriaSelectivity(metadata);        

Modified: trunk/engine/src/main/java/com/metamatrix/query/optimizer/relational/rules/NewCalculateCostUtil.java
===================================================================
--- trunk/engine/src/main/java/com/metamatrix/query/optimizer/relational/rules/NewCalculateCostUtil.java	2009-07-31 15:42:46 UTC (rev 1211)
+++ trunk/engine/src/main/java/com/metamatrix/query/optimizer/relational/rules/NewCalculateCostUtil.java	2009-08-04 16:37:03 UTC (rev 1212)
@@ -26,6 +26,7 @@
 import java.sql.Time;
 import java.sql.Timestamp;
 import java.util.ArrayList;
+import java.util.Arrays;
 import java.util.Collection;
 import java.util.HashMap;
 import java.util.HashSet;
@@ -77,8 +78,6 @@
 
     public static final float UNKNOWN_VALUE = -1;
     
-    public static final int DEFAULT_STRONG_COST = 10;
-    
     // These batch size should generally not be used as they should be retrieved from the 
     // command context, however they might be used in test scenarios where that is undefined
     static final int DEFAULT_PROCESSOR_BATCH_SIZE = 2000;
@@ -86,7 +85,7 @@
     
     // the following variables are used to hold cost estimates (roughly in milliseconds)
     private final static float compareTime = .05f; //TODO: a better estimate would be based upon the number of conjuncts
-    private final static float readTime = .001f;
+    private final static float readTime = .001f; //TODO: should come from the connector
     private final static float procNewRequestTime = 100; //TODO: should come from the connector
     private final static float procMoreRequestTime = 15; //TODO: should come from the connector
     
@@ -177,48 +176,7 @@
             }
             case NodeConstants.Types.SET_OP: 
             {
-                float cost = 0;
-                
-                SetQuery.Operation op = (SetQuery.Operation)node.getProperty(NodeConstants.Info.SET_OPERATION);
-
-                if (op == SetQuery.Operation.UNION) {
-	                for (PlanNode childNode : node.getChildren()) {
-	                    float childCost1 = (Float)childNode.getProperty(NodeConstants.Info.EST_CARDINALITY);
-	                    if (childCost1 == UNKNOWN_VALUE) {
-	                        cost = UNKNOWN_VALUE;
-	                        break;
-	                    } 
-	                    // All rows will be projected so add both costs together.
-	                    cost += childCost1;
-	                }
-	                if (!node.hasBooleanProperty(NodeConstants.Info.USE_ALL)) {
-	                	cost = getDistinctEstimate(node, metadata, cost);
-	                }
-                } else {
-                	float leftCost = (Float)node.getFirstChild().getProperty(NodeConstants.Info.EST_CARDINALITY);                	
-                	leftCost = getDistinctEstimate(node.getFirstChild(), metadata, leftCost);
-                    
-                    float rightCost = (Float)node.getLastChild().getProperty(NodeConstants.Info.EST_CARDINALITY);
-                    rightCost = getDistinctEstimate(node.getLastChild(), metadata, rightCost);
-                    
-                    cost = leftCost;
-                    
-                	if (op == SetQuery.Operation.EXCEPT) {
-                        if (leftCost != UNKNOWN_VALUE && rightCost != UNKNOWN_VALUE) {
-                        	cost = Math.max(1, leftCost - rightCost);
-                        }                    		
-                	} else {
-                		if (rightCost != UNKNOWN_VALUE) {
-                			if (leftCost != UNKNOWN_VALUE) {
-                        		cost = Math.min(leftCost, rightCost);
-                			} else {
-                				cost = rightCost;
-                			}
-                		}
-                	}
-                }                
-                
-                setCardinalityEstimate(node, new Float(cost));
+                estimateSetOpCost(node, metadata);
                 break;
             }
             case NodeConstants.Types.TUPLE_LIMIT: 
@@ -249,14 +207,58 @@
         }
     }
 
+	private static void estimateSetOpCost(PlanNode node,
+			QueryMetadataInterface metadata) throws QueryMetadataException,
+			MetaMatrixComponentException {
+		float cost = 0;
+		
+		SetQuery.Operation op = (SetQuery.Operation)node.getProperty(NodeConstants.Info.SET_OPERATION);
+
+		float leftCost = (Float)node.getFirstChild().getProperty(NodeConstants.Info.EST_CARDINALITY);
+		float rightCost = (Float)node.getLastChild().getProperty(NodeConstants.Info.EST_CARDINALITY);
+		
+		if (!node.hasBooleanProperty(NodeConstants.Info.USE_ALL)) {
+			leftCost = getDistinctEstimate(node.getFirstChild(), metadata, leftCost);
+			rightCost = getDistinctEstimate(node.getLastChild(), metadata, rightCost);
+		}
+		
+		cost = leftCost;
+		
+		switch (op) {
+		case EXCEPT:
+			if (leftCost != UNKNOWN_VALUE && rightCost != UNKNOWN_VALUE) {
+		    	cost = Math.max(1, leftCost - .5f * rightCost);
+		    }
+			break;
+		case INTERSECT:
+			if (rightCost != UNKNOWN_VALUE) {
+				if (leftCost != UNKNOWN_VALUE) {
+		    		cost = .5f * Math.min(leftCost, rightCost);
+				} else {
+					cost = rightCost;
+				}
+			}
+			break;
+		default: //union
+			if (leftCost != UNKNOWN_VALUE && rightCost != UNKNOWN_VALUE) {
+		        if (!node.hasBooleanProperty(NodeConstants.Info.USE_ALL)) {
+		        	cost = Math.max(leftCost, rightCost) + .5f * Math.min(leftCost, rightCost);
+		        } else {
+		            cost = rightCost + leftCost;
+		        }
+			}
+			break;
+		}
+		
+		setCardinalityEstimate(node, new Float(cost));
+	}
+
 	private static float getDistinctEstimate(PlanNode node,
 			QueryMetadataInterface metadata, float cost)
 			throws QueryMetadataException, MetaMatrixComponentException {
-		if (!node.hasBooleanProperty(NodeConstants.Info.USE_ALL)) {
-			PlanNode projectNode = NodeEditor.findNodePreOrder(node, NodeConstants.Types.PROJECT);
-			if (projectNode != null) {
-				cost = getDistinctEstimate(projectNode, (List)projectNode.getProperty(NodeConstants.Info.PROJECT_COLS), metadata, cost);
-			}
+		PlanNode projectNode = NodeEditor.findNodePreOrder(node, NodeConstants.Types.PROJECT);
+		if (projectNode != null) {
+			cost = getDistinctEstimate(projectNode, (List)projectNode.getProperty(NodeConstants.Info.PROJECT_COLS), metadata, cost);
 		}
 		return cost;
 	}
@@ -393,14 +395,12 @@
         if(elements == null) {
             return new Float(childCost);
         }
-        HashSet elems = new HashSet();
-        for(Iterator iter = elements.iterator(); iter.hasNext();) {
-            Expression expression = (Expression)iter.next();
-            ElementCollectorVisitor.getElements(expression, elems);
+        HashSet<ElementSymbol> elems = new HashSet<ElementSymbol>();
+        ElementCollectorVisitor.getElements(elements, elems);
+        if (usesKey(elements, metadata)) {
+        	return new Float(childCost);
         }
-        elements = new ArrayList(elems);
-        
-        float ndvCost = getMaxNDV(elements, node, childCost, metadata);
+        float ndvCost = getNDV(elems, node, childCost, metadata);
         if(ndvCost == UNKNOWN_VALUE) {
             ndvCost = childCost;
         }
@@ -417,21 +417,15 @@
             CompoundCriteria compCrit = (CompoundCriteria) crit;
             if (compCrit.getOperator() == CompoundCriteria.OR) {
                 cost = 0;
-            } else { //check for composite key
-                HashSet elements = new HashSet();
-                Iterator crits = compCrit.getCriteria().iterator();
-                while(crits.hasNext()) { 
-                    Criteria aCrit =  (Criteria) crits.next();
-                    collectElementsOfValidCriteria(aCrit, elements);
-                }
-                if (usesKey(elements, metadata)) {
-                    return 1;
-                }
+            } 
+            HashSet<ElementSymbol> elements = new HashSet<ElementSymbol>();
+            collectElementsOfValidCriteria(compCrit, elements);
+            if (usesKey(elements, metadata)) {
+                return 1;
             }
 
-            Iterator iter = compCrit.getCriteria().iterator();
-            while(iter.hasNext()) { 
-                float nextCost = recursiveEstimateCostOfCriteria(childCost, currentNode, (Criteria) iter.next(), metadata);
+            for (Criteria critPart : compCrit.getCriteria()) {
+                float nextCost = recursiveEstimateCostOfCriteria(childCost, currentNode, critPart, metadata);
                 
                 if(compCrit.getOperator() == CompoundCriteria.AND) {
                     if (nextCost == UNKNOWN_VALUE) {
@@ -496,16 +490,29 @@
      * @param elements Collection to collect ElementSymbols in
      * @since 4.2
      */
-    private static void collectElementsOfValidCriteria(Criteria criteria, Collection elements) {
+    private static void collectElementsOfValidCriteria(Criteria criteria, Collection<ElementSymbol> elements) {
        
         if(criteria instanceof CompoundCriteria) {
             CompoundCriteria compCrit = (CompoundCriteria) criteria;
-            if(compCrit.getOperator() == CompoundCriteria.AND) {
-                Iterator iter = compCrit.getCriteria().iterator();
-                while(iter.hasNext()) { 
-                    collectElementsOfValidCriteria((Criteria) iter.next(), elements);
-                }
+            Iterator iter = compCrit.getCriteria().iterator();
+            boolean first = true;
+            Collection<ElementSymbol> savedElements = elements;
+            if(compCrit.getOperator() == CompoundCriteria.OR) {
+            	elements = new HashSet<ElementSymbol>();
             }
+            while(iter.hasNext()) { 
+            	if(compCrit.getOperator() == CompoundCriteria.AND || first) {
+            		collectElementsOfValidCriteria((Criteria) iter.next(), elements);
+            		first = false;
+            	} else {
+            		HashSet<ElementSymbol> other = new HashSet<ElementSymbol>();
+            		collectElementsOfValidCriteria((Criteria) iter.next(), other);
+            		elements.retainAll(other);
+            	}
+            }
+            if (compCrit.getOperator() == CompoundCriteria.OR) {
+            	savedElements.addAll(elements);
+            }
         } else if(criteria instanceof CompareCriteria) {
             CompareCriteria compCrit = (CompareCriteria)criteria;
             if (compCrit.getOperator() == CompareCriteria.EQ){
@@ -543,15 +550,15 @@
         
         Collection<ElementSymbol> elements = ElementCollectorVisitor.getElements(predicateCriteria, true);
         
-        Collection groups = GroupsUsedByElementsVisitor.getGroups(predicateCriteria);
+        Collection<GroupSymbol> groups = GroupsUsedByElementsVisitor.getGroups(elements);
         boolean multiGroup = groups.size() > 1;
         
         float cost = childCost;
-        float ndv = getMaxNDV(elements, currentNode, childCost, metadata);
+        float ndv = getNDV(elements, currentNode, childCost, metadata);
         
         boolean unknownChildCost = childCost == UNKNOWN_VALUE;
         boolean usesKey = usesKey(elements, metadata);
-
+        
         if (childCost == UNKNOWN_VALUE) {
             childCost = 1;
         }
@@ -599,7 +606,7 @@
             if (unknownChildCost) {
                 return UNKNOWN_VALUE;
             }
-            cost = Math.min(childCost, childCost * setCriteria.getNumberOfValues() / ndv);
+            cost = childCost * setCriteria.getNumberOfValues() / ndv;
             
             isNegatedPredicateCriteria = setCriteria.isNegated();
             
@@ -618,19 +625,14 @@
         } else if(predicateCriteria instanceof IsNullCriteria) {
             IsNullCriteria isNullCriteria = (IsNullCriteria)predicateCriteria;
 
-            if(isNullable(elements, metadata)) {
-                 
-                float nnv = getNNV(elements, metadata);
-                if (unknownChildCost) {
-                    return nnv;
-                } else if (nnv == UNKNOWN_VALUE) {
-                    cost = childCost / ndv;
-                } else {
-                    cost = childCost * (nnv / Math.max(1, getCardinality(elements, metadata)));
-                }
+            float nnv = getNNV(elements, currentNode, childCost, metadata);
+            if (nnv == UNKNOWN_VALUE) {
+            	if (unknownChildCost) {
+            		return UNKNOWN_VALUE;
+            	}
+                cost = childCost / ndv;
             } else {
-                // No nulls allowed
-                cost = 0;
+                cost = nnv;
             }
             
             isNegatedPredicateCriteria = isNullCriteria.isNegated();
@@ -655,11 +657,8 @@
     }
 
     /** 
-     * @param childCost
-     * @param cost
-     * @param ndv
-     * @param matchExpression
-     * @return
+     * TODO: does not check for escape char
+     * or if it will contain single match chars
      */
     private static float estimateMatchCost(float childCost,
                                            float ndv,
@@ -667,14 +666,8 @@
         Expression matchExpression = criteria.getRightExpression();
         if(matchExpression instanceof Constant && ((Constant)matchExpression).getType().equals(DataTypeManager.DefaultDataClasses.STRING)) {
             String compareValue = (String) ((Constant)matchExpression).getValue();
-            if(compareValue != null) {
-                if(compareValue.indexOf('%') >= 0) {
-                    if(compareValue.length() == 1) {
-                        return childCost;
-                    }
-                } else {
-                    return childCost / ndv;
-                }
+            if(compareValue != null && compareValue.indexOf('%') < 0) {
+            	return (childCost / 2) * (1 / 3f  + 1 / ndv); //without knowing length constraints we'll make an average guess
             }
         } else if (EvaluateExpressionVisitor.willBecomeConstant(criteria.getLeftExpression())) {
             return childCost / ndv;
@@ -768,7 +761,17 @@
         return cost;
     }
     
-    static boolean usesKey(Collection<? extends SingleElementSymbol> allElements, QueryMetadataInterface metadata)
+    static boolean usesKey(PlanNode planNode, Collection<? extends SingleElementSymbol> allElements, QueryMetadataInterface metadata) throws QueryMetadataException, MetaMatrixComponentException {
+    	return NodeEditor.findAllNodes(planNode, NodeConstants.Types.SOURCE, NodeConstants.Types.JOIN | NodeConstants.Types.SET_OP).size() == 1
+    	&& usesKey(allElements, metadata);
+    }
+    
+    /**
+     * TODO: this uses key check is not really accurate, it doesn't take into consideration where 
+     * we are in the plan.
+     * if a key column is used after a non 1-1 join or a union all, then it may be non-unique.
+     */
+    private static boolean usesKey(Collection<? extends SingleElementSymbol> allElements, QueryMetadataInterface metadata)
         throws QueryMetadataException, MetaMatrixComponentException {
     
         if(allElements == null || allElements.size() == 0) { 
@@ -814,77 +817,78 @@
         
         return false;    
     }
-
-    /** 
-     * @param elements
-     * @param metadata
-     * @return
-     * @since 4.3
+    
+    /**
+     * Get the scaled max ndv for a set of elements.
+     * 
+     * NOTE: this is not a good approximation over unions, joins, grouping, etc.
      */
-    private static float getCardinality(Collection elements, QueryMetadataInterface metadata) 
+    private static float getNDV(Collection<ElementSymbol> elements, PlanNode current, float cardinality, QueryMetadataInterface metadata) 
         throws QueryMetadataException, MetaMatrixComponentException {
+        float result = 1;
         
-        if(elements.size() != 1) {
-            return UNKNOWN_VALUE;
-        }
-        ElementSymbol elem = (ElementSymbol) elements.iterator().next();
-        Object groupID = elem.getGroupSymbol().getMetadataID();
-        return metadata.getCardinality(groupID);
-    }
-
-    private static float getMaxNDV(Collection elements, PlanNode currentNode, float estNodeCardinality, QueryMetadataInterface metadata) 
-        throws QueryMetadataException, MetaMatrixComponentException {
-        
-        if(elements.isEmpty()) {
-            return UNKNOWN_VALUE;
-        }
-
-        float ndv = UNKNOWN_VALUE;
-        
-        Iterator elementIterator = elements.iterator();
-        while(elementIterator.hasNext()) {
-            ElementSymbol elem = (ElementSymbol) elementIterator.next();
-            ndv = Math.max(ndv, estimateNDVForSymbol(elem, currentNode, estNodeCardinality, metadata));
-            if(ndv == UNKNOWN_VALUE) {
-                return UNKNOWN_VALUE;
+    	for (ElementSymbol elementSymbol : elements) {
+            Object elemID = elementSymbol.getMetadataID();
+            float ndv = metadata.getDistinctValues(elemID);
+            if (ndv == UNKNOWN_VALUE) {
+                if (metadata.isVirtualGroup(elementSymbol.getGroupSymbol().getMetadataID()) && !metadata.isProcedure(elementSymbol.getGroupSymbol().getMetadataID())) {
+            		PlanNode sourceNode = FrameUtil.findOriginatingNode(current, new HashSet<GroupSymbol>(Arrays.asList(elementSymbol.getGroupSymbol())));
+            		if (sourceNode != null) {
+	        			SymbolMap symbolMap = (SymbolMap)sourceNode.getProperty(NodeConstants.Info.SYMBOL_MAP);
+	        			Expression expr = symbolMap.getMappedExpression(elementSymbol);
+	        			ndv = getNDV(ElementCollectorVisitor.getElements(expr, true), sourceNode.getFirstChild(), cardinality, metadata);
+            		}
+            	}
+            	if (ndv == UNKNOWN_VALUE) {
+            		return UNKNOWN_VALUE;
+            	}
+            } else if (cardinality != UNKNOWN_VALUE) {
+            	int groupCardinality = metadata.getCardinality(elementSymbol.getGroupSymbol().getMetadataID());
+            	if (groupCardinality != UNKNOWN_VALUE) {
+            		ndv *= cardinality / Math.max(1, groupCardinality);
+            	}
             }
-        }
-                
-        return ndv;
+            result = Math.max(result, ndv);
+		}
+        return result;
     }
     
-    /** 
-     * @param elements
-     * @return
-     * @since 4.3
+    /**
+     * Get the scaled max nnv for a set of elements.
+     * 
+     * NOTE: assumes that the expression does not allow nulls
      */
-    private static boolean isNullable(Collection elements, QueryMetadataInterface metadata) 
+    private static float getNNV(Collection<ElementSymbol> elements, PlanNode current, float cardinality, QueryMetadataInterface metadata) 
         throws QueryMetadataException, MetaMatrixComponentException {
-        
-        if(elements.size() != 1) {
-            return true;
-        }
-        ElementSymbol elem = (ElementSymbol) elements.iterator().next();
-        Object elemID = elem.getMetadataID();
-        return metadata.elementSupports(elemID, SupportConstants.Element.NULL) || 
-            metadata.elementSupports(elemID, SupportConstants.Element.NULL_UNKNOWN);  
+        float result = 0;
+    	for (ElementSymbol elementSymbol : elements) {
+            Object elemID = elementSymbol.getMetadataID();
+            float nnv = metadata.getNullValues(elemID);
+            if (nnv == UNKNOWN_VALUE) {
+            	if (!metadata.elementSupports(elemID, SupportConstants.Element.NULL) 
+            			&& !metadata.elementSupports(elemID, SupportConstants.Element.NULL_UNKNOWN)) {
+            		nnv = 0;
+            	} else if (metadata.isVirtualGroup(elementSymbol.getGroupSymbol().getMetadataID()) && !metadata.isProcedure(elementSymbol.getGroupSymbol().getMetadataID())) {
+            		PlanNode sourceNode = FrameUtil.findOriginatingNode(current, new HashSet<GroupSymbol>(Arrays.asList(elementSymbol.getGroupSymbol())));
+            		if (sourceNode != null) {
+	        			SymbolMap symbolMap = (SymbolMap)sourceNode.getProperty(NodeConstants.Info.SYMBOL_MAP);
+	        			Expression expr = symbolMap.getMappedExpression(elementSymbol);
+	        			nnv = getNNV(ElementCollectorVisitor.getElements(expr, true), sourceNode.getFirstChild(), cardinality, metadata);
+            		}
+            	}
+            	if (nnv == UNKNOWN_VALUE) {
+            		return UNKNOWN_VALUE;
+            	}
+            } else if (cardinality != UNKNOWN_VALUE) {
+            	int groupCardinality = metadata.getCardinality(elementSymbol.getGroupSymbol().getMetadataID());
+            	if (groupCardinality != UNKNOWN_VALUE) {
+            		nnv *= cardinality / Math.max(1, groupCardinality);
+            	}
+            }
+            result = Math.max(result, nnv);
+		}
+        return result;
     }
-
-    /** 
-     * @param elements
-     * @return
-     * @since 4.3
-     */
-    private static float getNNV(Collection elements, QueryMetadataInterface metadata) 
-        throws QueryMetadataException, MetaMatrixComponentException {
-        
-        if(elements.size() != 1) {
-            return UNKNOWN_VALUE;
-        }
-        ElementSymbol elem = (ElementSymbol) elements.iterator().next();
-        Object elemID = elem.getMetadataID();
-        return metadata.getNullValues(elemID);
-    }
     
     /**
      * Computes the cost of a Merge Join
@@ -1066,9 +1070,9 @@
         float result = UNKNOWN_VALUE;
         for(Iterator iter = expressions.iterator(); iter.hasNext();) {
             Expression expr = (Expression)iter.next();
-            Collection symbols = ElementCollectorVisitor.getElements(expr, true);
+            Collection<ElementSymbol> symbols = ElementCollectorVisitor.getElements(expr, true);
             
-            float currentSymbolNDV = getMaxNDV(symbols, node, nodeCardinality, metadata);                
+            float currentSymbolNDV = getNDV(symbols, node, nodeCardinality, metadata);                
             
             if(currentSymbolNDV == UNKNOWN_VALUE) { 
                 if (usesKey(symbols, metadata)) {
@@ -1088,129 +1092,4 @@
         return Math.max(1, Math.min(nodeCardinality, result));
     }
     
-    /** 
-     * For virtual symbol, find a mapped physical symbol and look up it's NDV
-     *  
-     * @param currentDepSymbol The current virtual dependent symbol
-     * @param dependentNode The dependent node starting point
-     * @param metadata Metadata API
-     * @return NDV for currentDepSymbol
-     * @since 5.0.1
-     */
-    private static float getMappedPhysicalNDV(ElementSymbol currentDepSymbol,
-                                            PlanNode dependentNode,
-                                            QueryMetadataInterface metadata) throws MetaMatrixComponentException {
-        
-        PlanNode currentNode = dependentNode;
-        
-        while(true) {
-            // Walk down to a source node
-            PlanNode sourceNode = FrameUtil.findOriginatingNode(currentNode, dependentNode.getGroups());
-            if(sourceNode == null) {
-                break;
-            }
-            
-            if (sourceNode.getType() == NodeConstants.Types.SOURCE) {
-                SymbolMap symbolMap = (SymbolMap) sourceNode.getProperty(NodeConstants.Info.SYMBOL_MAP);
-                
-                if (symbolMap == null) {
-                    return UNKNOWN_VALUE;
-                }
-                
-                Expression currentExpr = symbolMap.getMappedExpression(currentDepSymbol);
-                
-                if (currentExpr == null) {
-                    return UNKNOWN_VALUE;
-                }
-                
-                if(! (currentExpr instanceof ElementSymbol)) {
-                    // Not a 1-to-1 mapping - check for single contained element to use instead.  This
-                    // is a bit of a hack as it will work just fine in some cases (like convert(elem, Double))
-                    // and will suck badly in others that change the size of the value domain.  If there is 
-                    // more than 1 element, we'll just give up for now - probably some heuristic we can use later.
-                    Collection elements = ElementCollectorVisitor.getElements(currentExpr, false, false);
-                    switch(elements.size()) {
-                        case 0:
-                        {
-                            // Must be a constant, so use NDV=1
-                            return 1;
-                        }
-                        case 1: 
-                        {
-                            // Just switch to using the current expression
-                            currentDepSymbol = (ElementSymbol) elements.iterator().next();
-                            break;
-                        }
-                        default:
-                        {
-                            // More than 1 element in lower expression - give up!
-                            return UNKNOWN_VALUE;
-                        }
-    
-                    }
-                }
-            }
-            
-            // Check for physical element and if so, break out of the loop
-            try {
-                if(! metadata.isVirtualGroup(currentDepSymbol.getGroupSymbol().getMetadataID())) {
-                    return metadata.getDistinctValues(currentDepSymbol.getMetadataID());
-                } 
-                currentNode = currentNode.getFirstChild();
-            } catch(QueryMetadataException e) {
-                throw new MetaMatrixComponentException(e, e.getMessage());
-            }
-        }
-        return UNKNOWN_VALUE;
-    }
-
-    /**
-     * This method will return an estimate NDV of a symbol based on the cost of the input node and the ratio of
-     * the input symbol's NDV value to the input symbol's Group's cardinality.
-     */
-    private static float estimateNDVForSymbol(ElementSymbol symbol, PlanNode currentNode, float estNodeCardinality, QueryMetadataInterface metadata) 
-        throws MetaMatrixComponentException, QueryMetadataException {
-        
-        if(symbol == null) {
-            return UNKNOWN_VALUE;
-        }
-        
-        float ndv = 0;
-        float tableCardinality = 0;
-        Object elemID = symbol.getMetadataID();
-        Object groupID = symbol.getGroupSymbol().getMetadataID();
-        
-        if (metadata.isVirtualGroup(groupID)) {
-            return getMappedPhysicalNDV(symbol, currentNode, metadata);
-        }
-        
-        if(elemID != null && groupID != null) {
-            ndv = metadata.getDistinctValues(elemID);
-            tableCardinality = metadata.getCardinality(groupID);
-        }
-        // if ndv is <= 0 the value is considered unknown and we return UNKNOWN_VALUE
-        if(ndv <= 0) {
-            return UNKNOWN_VALUE;
-        }
-        float estNDV = estNodeCardinality * ndv / tableCardinality;
-        if(estNDV < ndv) {
-            return Math.max(1, estNDV);
-        }
-        return Math.max(1, ndv);
-    }
-    
-    static boolean isNodeStrong(PlanNode accessNode, QueryMetadataInterface metadata, CommandContext context) 
-        throws QueryMetadataException, MetaMatrixComponentException {
-    
-        float result = computeCostForTree(accessNode, metadata);
-        
-        float strong_cost = DEFAULT_STRONG_COST;
-        
-        if(context != null) {
-            strong_cost = Math.min(strong_cost, context.getProcessorBatchSize()); 
-        }
-        
-        return result != UNKNOWN_VALUE && result <= strong_cost;
-    }
-    
 }

Modified: trunk/engine/src/main/java/com/metamatrix/query/optimizer/relational/rules/RuleChooseDependent.java
===================================================================
--- trunk/engine/src/main/java/com/metamatrix/query/optimizer/relational/rules/RuleChooseDependent.java	2009-07-31 15:42:46 UTC (rev 1211)
+++ trunk/engine/src/main/java/com/metamatrix/query/optimizer/relational/rules/RuleChooseDependent.java	2009-08-04 16:37:03 UTC (rev 1212)
@@ -61,6 +61,8 @@
         boolean leftCandidate;
         boolean rightCandidate;
     }
+
+	public static final int DEFAULT_INDEPENDENT_CARDINALITY = 10;
     
     public PlanNode execute(PlanNode plan, QueryMetadataInterface metadata, CapabilitiesFinder capFinder, RuleStack rules, AnalysisRecord analysisRecord, CommandContext context)
         throws QueryPlannerException, QueryMetadataException, MetaMatrixComponentException {
@@ -104,25 +106,14 @@
             if (depJoinCost != NewCalculateCostUtil.UNKNOWN_VALUE) {
                 pushCriteria |= decideForAgainstDependentJoin(depJoinCost, independentNode, dependentNode, joinNode, metadata, context);
             } else {
-                boolean siblingStrong = NewCalculateCostUtil.isNodeStrong(siblingNode, metadata, context);
-                boolean sourceStrong = NewCalculateCostUtil.isNodeStrong(sourceNode, metadata, context);
-                
-                if (!bothCandidates) {
-                    if (siblingStrong) {
-                        pushCriteria |= markDependent(sourceNode, joinNode);
-                    } 
-                } else {
-                    if (siblingStrong && !sourceStrong) {
-                        pushCriteria |= markDependent(sourceNode, joinNode);
-                    } else if (!siblingStrong && sourceStrong) {
-                        pushCriteria |= markDependent(siblingNode, joinNode);
-                    } else if (siblingStrong && sourceStrong) {
-                        if (NewCalculateCostUtil.computeCostForTree(sourceNode, metadata) <= NewCalculateCostUtil.computeCostForTree(siblingNode, metadata)) {
-                            pushCriteria |= markDependent(siblingNode, joinNode);
-                        } else {
-                            pushCriteria |= markDependent(sourceNode, joinNode);
-                        }
-                    }
+            	float sourceCost = NewCalculateCostUtil.computeCostForTree(sourceNode, metadata);
+            	float siblingCost = NewCalculateCostUtil.computeCostForTree(siblingNode, metadata);
+            	
+                if (bothCandidates && sourceCost != NewCalculateCostUtil.UNKNOWN_VALUE && sourceCost < RuleChooseDependent.DEFAULT_INDEPENDENT_CARDINALITY 
+                		&& (sourceCost < siblingCost || siblingCost == NewCalculateCostUtil.UNKNOWN_VALUE)) {
+                    pushCriteria |= markDependent(siblingNode, joinNode);
+                } else if (siblingCost != NewCalculateCostUtil.UNKNOWN_VALUE && siblingCost < RuleChooseDependent.DEFAULT_INDEPENDENT_CARDINALITY) {
+                    pushCriteria |= markDependent(sourceNode, joinNode);
                 }
             }
         }

Modified: trunk/engine/src/main/java/com/metamatrix/query/optimizer/relational/rules/RuleCleanCriteria.java
===================================================================
--- trunk/engine/src/main/java/com/metamatrix/query/optimizer/relational/rules/RuleCleanCriteria.java	2009-07-31 15:42:46 UTC (rev 1211)
+++ trunk/engine/src/main/java/com/metamatrix/query/optimizer/relational/rules/RuleCleanCriteria.java	2009-08-04 16:37:03 UTC (rev 1212)
@@ -22,9 +22,6 @@
 
 package com.metamatrix.query.optimizer.relational.rules;
 
-import java.util.Iterator;
-import java.util.List;
-
 import com.metamatrix.api.exception.MetaMatrixComponentException;
 import com.metamatrix.api.exception.query.CriteriaEvaluationException;
 import com.metamatrix.api.exception.query.QueryPlannerException;
@@ -53,14 +50,9 @@
     public PlanNode execute(PlanNode plan, QueryMetadataInterface metadata, CapabilitiesFinder capFinder, RuleStack rules, AnalysisRecord analysisRecord, CommandContext context)
         throws QueryPlannerException, MetaMatrixComponentException {
 
-        List criteria = NodeEditor.findAllNodes(plan, NodeConstants.Types.SELECT);
-        
-        Iterator critIter = criteria.iterator();
-        
         boolean pushRaiseNull = false;
         
-        while (critIter.hasNext()) {
-            PlanNode critNode = (PlanNode)critIter.next();
+        for (PlanNode critNode : NodeEditor.findAllNodes(plan, NodeConstants.Types.SELECT)) {
             
             if (critNode.hasBooleanProperty(NodeConstants.Info.IS_PHANTOM)) {
                 NodeEditor.removeChildNode(critNode.getParent(), critNode);

Modified: trunk/engine/src/main/java/com/metamatrix/query/optimizer/relational/rules/RuleCollapseSource.java
===================================================================
--- trunk/engine/src/main/java/com/metamatrix/query/optimizer/relational/rules/RuleCollapseSource.java	2009-07-31 15:42:46 UTC (rev 1211)
+++ trunk/engine/src/main/java/com/metamatrix/query/optimizer/relational/rules/RuleCollapseSource.java	2009-08-04 16:37:03 UTC (rev 1212)
@@ -160,7 +160,7 @@
 		 */
 		if (queryCommand instanceof SetQuery) {
 			((SetQuery)queryCommand).setAll(false);
-		} else if (!NewCalculateCostUtil.usesKey(queryCommand.getProjectedSymbols(), metadata) && CapabilitiesUtil.supports(Capability.QUERY_SELECT_DISTINCT, RuleRaiseAccess.getModelIDFromAccess(accessNode, metadata), metadata, capFinder)) {
+		} else if (!NewCalculateCostUtil.usesKey(accessNode, queryCommand.getProjectedSymbols(), metadata) && CapabilitiesUtil.supports(Capability.QUERY_SELECT_DISTINCT, RuleRaiseAccess.getModelIDFromAccess(accessNode, metadata), metadata, capFinder)) {
 			//TODO: could check for group by and a select clause containing all group by expressions
 			((Query)queryCommand).getSelect().setDistinct(true);
 		}

Modified: trunk/engine/src/main/java/com/metamatrix/query/optimizer/relational/rules/RuleCopyCriteria.java
===================================================================
--- trunk/engine/src/main/java/com/metamatrix/query/optimizer/relational/rules/RuleCopyCriteria.java	2009-07-31 15:42:46 UTC (rev 1211)
+++ trunk/engine/src/main/java/com/metamatrix/query/optimizer/relational/rules/RuleCopyCriteria.java	2009-08-04 16:37:03 UTC (rev 1212)
@@ -339,13 +339,13 @@
                                  Set allCriteria) {
         //First examine criteria in critNode for suitability
         Criteria crit = (Criteria) node.getProperty(NodeConstants.Info.SELECT_CRITERIA);
-        if(node.getGroups().size() == 1 && crit != null) {
-            
+        if(node.getGroups().size() == 1) {
+            List<Criteria> crits = Criteria.separateCriteriaByAnd(crit);
             if(!node.hasBooleanProperty(NodeConstants.Info.IS_HAVING) && node.getSubqueryContainers().isEmpty()) {
                 if (!node.hasBooleanProperty(NodeConstants.Info.IS_COPIED)) {
-                    toCopy.add(crit);
+                    toCopy.addAll(crits);
                 }
-                allCriteria.add(crit);
+                allCriteria.addAll(crits);
             }
         }
     }

Modified: trunk/engine/src/main/java/com/metamatrix/query/optimizer/relational/rules/RuleImplementJoinStrategy.java
===================================================================
--- trunk/engine/src/main/java/com/metamatrix/query/optimizer/relational/rules/RuleImplementJoinStrategy.java	2009-07-31 15:42:46 UTC (rev 1211)
+++ trunk/engine/src/main/java/com/metamatrix/query/optimizer/relational/rules/RuleImplementJoinStrategy.java	2009-08-04 16:37:03 UTC (rev 1212)
@@ -129,7 +129,7 @@
         PlanNode sortNode = createSortNode(orderSymbols, outputSymbols, directions);
         
         if (sourceNode.getType() == NodeConstants.Types.ACCESS) {
-        	if (NewCalculateCostUtil.usesKey(expressions, metadata)) {
+        	if (NewCalculateCostUtil.usesKey(sourceNode, expressions, metadata)) {
                 joinNode.setProperty(joinNode.getFirstChild() == childNode ? NodeConstants.Info.IS_LEFT_DISTINCT : NodeConstants.Info.IS_RIGHT_DISTINCT, true);
         	}
 	        if (attemptPush && RuleRaiseAccess.canRaiseOverSort(sourceNode, metadata, capFinder, sortNode)) {

Modified: trunk/engine/src/main/java/com/metamatrix/query/optimizer/relational/rules/RuleMergeCriteria.java
===================================================================
--- trunk/engine/src/main/java/com/metamatrix/query/optimizer/relational/rules/RuleMergeCriteria.java	2009-07-31 15:42:46 UTC (rev 1211)
+++ trunk/engine/src/main/java/com/metamatrix/query/optimizer/relational/rules/RuleMergeCriteria.java	2009-08-04 16:37:03 UTC (rev 1212)
@@ -42,6 +42,7 @@
 import com.metamatrix.query.util.CommandContext;
 
 /**
+ * TODO: this rule should attempt to intelligently order the criteria
  */
 public final class RuleMergeCriteria implements OptimizerRule {
 
@@ -92,14 +93,14 @@
         }
     }
 
-    void mergeChain(PlanNode chainRoot) {
+    static void mergeChain(PlanNode chainRoot) {
 
         // Remove all of chain except root, collect crit from each
         CompoundCriteria critParts = new CompoundCriteria();
         PlanNode current = chainRoot;
         boolean isDependentSet = false;
         while(current.getType() == NodeConstants.Types.SELECT) {
-            critParts.addCriteria((Criteria)current.getProperty(NodeConstants.Info.SELECT_CRITERIA)); 
+            critParts.getCriteria().add(0, (Criteria)current.getProperty(NodeConstants.Info.SELECT_CRITERIA)); 
             
             isDependentSet |= current.hasBooleanProperty(NodeConstants.Info.IS_DEPENDENT_SET);
             

Modified: trunk/engine/src/main/java/com/metamatrix/query/optimizer/relational/rules/RulePushAggregates.java
===================================================================
--- trunk/engine/src/main/java/com/metamatrix/query/optimizer/relational/rules/RulePushAggregates.java	2009-07-31 15:42:46 UTC (rev 1211)
+++ trunk/engine/src/main/java/com/metamatrix/query/optimizer/relational/rules/RulePushAggregates.java	2009-08-04 16:37:03 UTC (rev 1212)
@@ -409,10 +409,7 @@
             collectSymbolsFromOtherAggregates(allAggregates, aggregates, planNode, stagedGroupingSymbols);
             
             //if the grouping expressions are unique then there's no point in staging the aggregate
-            //TODO: the uses key check is not really accurate, it doesn't take into consideration where 
-            //we are in the plan.
-            //if a key column is used after a non 1-1 join or a union all, then it may be non-unique.
-            if (NewCalculateCostUtil.usesKey(stagedGroupingSymbols, metadata)) {
+            if (NewCalculateCostUtil.usesKey(planNode, stagedGroupingSymbols, metadata)) {
             	continue;
             }
 

Modified: trunk/engine/src/main/java/com/metamatrix/query/optimizer/relational/rules/RulePushSelectCriteria.java
===================================================================
--- trunk/engine/src/main/java/com/metamatrix/query/optimizer/relational/rules/RulePushSelectCriteria.java	2009-07-31 15:42:46 UTC (rev 1211)
+++ trunk/engine/src/main/java/com/metamatrix/query/optimizer/relational/rules/RulePushSelectCriteria.java	2009-08-04 16:37:03 UTC (rev 1212)
@@ -235,6 +235,8 @@
     void pushTowardOriginatingNode(PlanNode sourceNode, PlanNode critNode, QueryMetadataInterface metadata, CapabilitiesFinder capFinder)
 		throws QueryPlannerException, QueryMetadataException, MetaMatrixComponentException {
 
+    	boolean groupSelects = sourceNode.getParent().getType() == NodeConstants.Types.SELECT && sourceNode.getChildCount() == 0;
+        
         //to keep a stable criteria ordering, move the sourceNode to the top of the criteria chain
         while (sourceNode.getParent().getType() == NodeConstants.Types.SELECT) {
             sourceNode = sourceNode.getParent();
@@ -247,6 +249,9 @@
 		PlanNode destination = examinePath(critNode, sourceNode, metadata, capFinder);
         NodeEditor.removeChildNode(critNode.getParent(), critNode);
         destination.addAsParent(critNode);
+        if (groupSelects && destination == sourceNode) {
+        	RuleMergeCriteria.mergeChain(critNode);
+        }
 	}
 
     /**

Modified: trunk/engine/src/main/java/com/metamatrix/query/resolver/util/ResolverUtil.java
===================================================================
--- trunk/engine/src/main/java/com/metamatrix/query/resolver/util/ResolverUtil.java	2009-07-31 15:42:46 UTC (rev 1211)
+++ trunk/engine/src/main/java/com/metamatrix/query/resolver/util/ResolverUtil.java	2009-08-04 16:37:03 UTC (rev 1212)
@@ -493,9 +493,9 @@
      * The resolved elements may not contain non-selectable columns depending on the metadata first used for resolving.
      * 
      */
-    public static List resolveElementsInGroup(GroupSymbol group, QueryMetadataInterface metadata)
+    public static List<ElementSymbol> resolveElementsInGroup(GroupSymbol group, QueryMetadataInterface metadata)
     throws QueryMetadataException, MetaMatrixComponentException {
-        return new ArrayList(getGroupInfo(group, metadata).getSymbolList());
+        return new ArrayList<ElementSymbol>(getGroupInfo(group, metadata).getSymbolList());
     }
     
 	static GroupInfo getGroupInfo(GroupSymbol group,

Modified: trunk/engine/src/main/java/com/metamatrix/query/rewriter/QueryRewriter.java
===================================================================
--- trunk/engine/src/main/java/com/metamatrix/query/rewriter/QueryRewriter.java	2009-07-31 15:42:46 UTC (rev 1211)
+++ trunk/engine/src/main/java/com/metamatrix/query/rewriter/QueryRewriter.java	2009-08-04 16:37:03 UTC (rev 1212)
@@ -27,8 +27,6 @@
 import java.sql.Date;
 import java.sql.Time;
 import java.sql.Timestamp;
-import java.text.ParseException;
-import java.text.SimpleDateFormat;
 import java.util.ArrayList;
 import java.util.Arrays;
 import java.util.Collection;
@@ -1877,7 +1875,10 @@
                 // if both left and right expressions are strings, and the LIKE match characters ('*', '_') are not present 
                 //  in the right expression, rewrite the criteria as EQUALs rather than LIKE
                 if(DataTypeManager.DefaultDataClasses.STRING.equals(criteria.getLeftExpression().getType()) && value.indexOf(escape) < 0 && value.indexOf(MatchCriteria.MATCH_CHAR) < 0 && value.indexOf(MatchCriteria.WILDCARD_CHAR) < 0) {
-                    return rewriteCriteria(new CompareCriteria(criteria.getLeftExpression(), criteria.isNegated()?CompareCriteria.NE:CompareCriteria.EQ, criteria.getRightExpression()), procCommand, context, metadata);
+                    if (value.equals(MatchCriteria.WILDCARD_CHAR)) {
+                    	return TRUE_CRITERIA;
+                    }
+                	return rewriteCriteria(new CompareCriteria(criteria.getLeftExpression(), criteria.isNegated()?CompareCriteria.NE:CompareCriteria.EQ, criteria.getRightExpression()), procCommand, context, metadata);
                 }
             }
         }

Modified: trunk/engine/src/test/java/com/metamatrix/query/optimizer/TestDependentJoins.java
===================================================================
--- trunk/engine/src/test/java/com/metamatrix/query/optimizer/TestDependentJoins.java	2009-07-31 15:42:46 UTC (rev 1211)
+++ trunk/engine/src/test/java/com/metamatrix/query/optimizer/TestDependentJoins.java	2009-08-04 16:37:03 UTC (rev 1212)
@@ -34,7 +34,7 @@
 import com.metamatrix.query.optimizer.capabilities.BasicSourceCapabilities;
 import com.metamatrix.query.optimizer.capabilities.FakeCapabilitiesFinder;
 import com.metamatrix.query.optimizer.capabilities.SourceCapabilities.Capability;
-import com.metamatrix.query.optimizer.relational.rules.NewCalculateCostUtil;
+import com.metamatrix.query.optimizer.relational.rules.RuleChooseDependent;
 import com.metamatrix.query.processor.ProcessorPlan;
 import com.metamatrix.query.processor.relational.AccessNode;
 import com.metamatrix.query.processor.relational.DependentAccessNode;
@@ -496,7 +496,7 @@
 
         FakeMetadataFacade metadata = FakeMetadataFactory.example1();
         FakeMetadataObject obj = metadata.getStore().findObject("pm1.g1", FakeMetadataObject.GROUP); //$NON-NLS-1$
-        obj.putProperty(FakeMetadataObject.Props.CARDINALITY, new Integer(NewCalculateCostUtil.DEFAULT_STRONG_COST - 1));
+        obj.putProperty(FakeMetadataObject.Props.CARDINALITY, new Integer(RuleChooseDependent.DEFAULT_INDEPENDENT_CARDINALITY - 1));
     
         ProcessorPlan plan = TestOptimizer.helpPlan(sql, metadata,  
             null, capFinder,
@@ -532,7 +532,7 @@
 
         FakeMetadataFacade metadata = FakeMetadataFactory.example1();
         FakeMetadataObject obj = metadata.getStore().findObject("pm1.g1", FakeMetadataObject.GROUP); //$NON-NLS-1$
-        obj.putProperty(FakeMetadataObject.Props.CARDINALITY, new Integer(NewCalculateCostUtil.DEFAULT_STRONG_COST + 1));
+        obj.putProperty(FakeMetadataObject.Props.CARDINALITY, new Integer(RuleChooseDependent.DEFAULT_INDEPENDENT_CARDINALITY + 1));
     
         ProcessorPlan plan = TestOptimizer.helpPlan(sql, metadata,  
             null, capFinder,
@@ -571,11 +571,11 @@
 
         FakeMetadataFacade metadata = FakeMetadataFactory.example1();
         FakeMetadataObject g1 = metadata.getStore().findObject("pm1.g1", FakeMetadataObject.GROUP); //$NON-NLS-1$
-        g1.putProperty(FakeMetadataObject.Props.CARDINALITY, new Integer(NewCalculateCostUtil.DEFAULT_STRONG_COST + 1));
+        g1.putProperty(FakeMetadataObject.Props.CARDINALITY, new Integer(RuleChooseDependent.DEFAULT_INDEPENDENT_CARDINALITY + 1));
         FakeMetadataObject g2 = metadata.getStore().findObject("pm1.g2", FakeMetadataObject.GROUP); //$NON-NLS-1$
-        g2.putProperty(FakeMetadataObject.Props.CARDINALITY, new Integer(NewCalculateCostUtil.DEFAULT_STRONG_COST - 1 ));
+        g2.putProperty(FakeMetadataObject.Props.CARDINALITY, new Integer(RuleChooseDependent.DEFAULT_INDEPENDENT_CARDINALITY - 1 ));
         FakeMetadataObject g3 = metadata.getStore().findObject("pm1.g3", FakeMetadataObject.GROUP); //$NON-NLS-1$
-        g3.putProperty(FakeMetadataObject.Props.CARDINALITY, new Integer(NewCalculateCostUtil.DEFAULT_STRONG_COST + 1000));
+        g3.putProperty(FakeMetadataObject.Props.CARDINALITY, new Integer(RuleChooseDependent.DEFAULT_INDEPENDENT_CARDINALITY + 1000));
     
         ProcessorPlan plan = TestOptimizer.helpPlan(sql, metadata,  
             null, capFinder,
@@ -612,11 +612,11 @@
 
         FakeMetadataFacade metadata = FakeMetadataFactory.example1();
         FakeMetadataObject g1 = metadata.getStore().findObject("pm1.g1", FakeMetadataObject.GROUP); //$NON-NLS-1$
-        g1.putProperty(FakeMetadataObject.Props.CARDINALITY, new Integer(NewCalculateCostUtil.DEFAULT_STRONG_COST - 1));
+        g1.putProperty(FakeMetadataObject.Props.CARDINALITY, new Integer(RuleChooseDependent.DEFAULT_INDEPENDENT_CARDINALITY - 1));
         FakeMetadataObject g2 = metadata.getStore().findObject("pm1.g2", FakeMetadataObject.GROUP); //$NON-NLS-1$
-        g2.putProperty(FakeMetadataObject.Props.CARDINALITY, new Integer(NewCalculateCostUtil.DEFAULT_STRONG_COST + 1000));
+        g2.putProperty(FakeMetadataObject.Props.CARDINALITY, new Integer(RuleChooseDependent.DEFAULT_INDEPENDENT_CARDINALITY + 1000));
         FakeMetadataObject g3 = metadata.getStore().findObject("pm1.g3", FakeMetadataObject.GROUP); //$NON-NLS-1$
-        g3.putProperty(FakeMetadataObject.Props.CARDINALITY, new Integer(NewCalculateCostUtil.DEFAULT_STRONG_COST + 1000));
+        g3.putProperty(FakeMetadataObject.Props.CARDINALITY, new Integer(RuleChooseDependent.DEFAULT_INDEPENDENT_CARDINALITY + 1000));
     
         ProcessorPlan plan = TestOptimizer.helpPlan(sql, metadata,  
             null, capFinder,
@@ -660,11 +660,11 @@
 
         FakeMetadataFacade metadata = FakeMetadataFactory.example1();
         FakeMetadataObject g1 = metadata.getStore().findObject("pm1.g1", FakeMetadataObject.GROUP); //$NON-NLS-1$
-        g1.putProperty(FakeMetadataObject.Props.CARDINALITY, new Integer(NewCalculateCostUtil.DEFAULT_STRONG_COST - 1));
+        g1.putProperty(FakeMetadataObject.Props.CARDINALITY, new Integer(RuleChooseDependent.DEFAULT_INDEPENDENT_CARDINALITY - 1));
         FakeMetadataObject g2 = metadata.getStore().findObject("pm1.g2", FakeMetadataObject.GROUP); //$NON-NLS-1$
-        g2.putProperty(FakeMetadataObject.Props.CARDINALITY, new Integer(NewCalculateCostUtil.DEFAULT_STRONG_COST + 1000));
+        g2.putProperty(FakeMetadataObject.Props.CARDINALITY, new Integer(RuleChooseDependent.DEFAULT_INDEPENDENT_CARDINALITY + 1000));
         FakeMetadataObject g3 = metadata.getStore().findObject("pm1.g3", FakeMetadataObject.GROUP); //$NON-NLS-1$
-        g3.putProperty(FakeMetadataObject.Props.CARDINALITY, new Integer(NewCalculateCostUtil.DEFAULT_STRONG_COST + 1000));
+        g3.putProperty(FakeMetadataObject.Props.CARDINALITY, new Integer(RuleChooseDependent.DEFAULT_INDEPENDENT_CARDINALITY + 1000));
     
         ProcessorPlan plan = TestOptimizer.helpPlan(sql, metadata,  
             null, capFinder,
@@ -702,9 +702,9 @@
 
         FakeMetadataFacade metadata = FakeMetadataFactory.example1();
         FakeMetadataObject g1 = metadata.getStore().findObject("pm1.g1", FakeMetadataObject.GROUP); //$NON-NLS-1$
-        g1.putProperty(FakeMetadataObject.Props.CARDINALITY, new Integer(NewCalculateCostUtil.DEFAULT_STRONG_COST - 1));
+        g1.putProperty(FakeMetadataObject.Props.CARDINALITY, new Integer(RuleChooseDependent.DEFAULT_INDEPENDENT_CARDINALITY - 1));
         FakeMetadataObject g2 = metadata.getStore().findObject("pm1.g2", FakeMetadataObject.GROUP); //$NON-NLS-1$
-        g2.putProperty(FakeMetadataObject.Props.CARDINALITY, new Integer(NewCalculateCostUtil.DEFAULT_STRONG_COST + 1000));
+        g2.putProperty(FakeMetadataObject.Props.CARDINALITY, new Integer(RuleChooseDependent.DEFAULT_INDEPENDENT_CARDINALITY + 1000));
     
         ProcessorPlan plan = TestOptimizer.helpPlan(sql, metadata,  
             null, capFinder,
@@ -743,9 +743,9 @@
 
         FakeMetadataFacade metadata = FakeMetadataFactory.exampleBQT();
         FakeMetadataObject g1 = metadata.getStore().findObject("BQT1.SmallA", FakeMetadataObject.GROUP); //$NON-NLS-1$
-        g1.putProperty(FakeMetadataObject.Props.CARDINALITY, new Integer(NewCalculateCostUtil.DEFAULT_STRONG_COST + 1000));
+        g1.putProperty(FakeMetadataObject.Props.CARDINALITY, new Integer(RuleChooseDependent.DEFAULT_INDEPENDENT_CARDINALITY + 1000));
         FakeMetadataObject g2 = metadata.getStore().findObject("BQT2.SmallA", FakeMetadataObject.GROUP); //$NON-NLS-1$
-        g2.putProperty(FakeMetadataObject.Props.CARDINALITY, new Integer(NewCalculateCostUtil.DEFAULT_STRONG_COST - 1));
+        g2.putProperty(FakeMetadataObject.Props.CARDINALITY, new Integer(RuleChooseDependent.DEFAULT_INDEPENDENT_CARDINALITY - 1));
          
         ProcessorPlan plan = TestOptimizer.helpPlan(
             "SELECT table1comp.IntKey, table1comp.key1, BQT1.SmallA.StringKey FROM (SELECT t1.*, (STRINGKEY || STRINGNUM) AS key1 FROM BQT2.SmallA AS t1) AS table1comp, BQT1.SmallA WHERE table1comp.key1 = BQT1.SmallA.StringKey",  //$NON-NLS-1$
@@ -789,9 +789,9 @@
 
         FakeMetadataFacade metadata = FakeMetadataFactory.exampleBQT();
         FakeMetadataObject g1 = metadata.getStore().findObject("BQT1.SmallA", FakeMetadataObject.GROUP); //$NON-NLS-1$
-        g1.putProperty(FakeMetadataObject.Props.CARDINALITY, new Integer(NewCalculateCostUtil.DEFAULT_STRONG_COST + 1000));
+        g1.putProperty(FakeMetadataObject.Props.CARDINALITY, new Integer(RuleChooseDependent.DEFAULT_INDEPENDENT_CARDINALITY + 1000));
         FakeMetadataObject g2 = metadata.getStore().findObject("BQT2.SmallA", FakeMetadataObject.GROUP); //$NON-NLS-1$
-        g2.putProperty(FakeMetadataObject.Props.CARDINALITY, new Integer(NewCalculateCostUtil.DEFAULT_STRONG_COST - 1));
+        g2.putProperty(FakeMetadataObject.Props.CARDINALITY, new Integer(RuleChooseDependent.DEFAULT_INDEPENDENT_CARDINALITY - 1));
          
         ProcessorPlan plan = TestOptimizer.helpPlan(
             "SELECT table1comp.IntKey, table1comp.key1, BQT1.SmallA.StringKey FROM (SELECT t1.*, (STRINGKEY || STRINGNUM) AS key1 FROM BQT2.SmallA AS t1) AS table1comp, BQT1.SmallA WHERE table1comp.key1 = BQT1.SmallA.StringKey AND table1comp.key1 = BQT1.SmallA.StringNum",  //$NON-NLS-1$

Modified: trunk/engine/src/test/java/com/metamatrix/query/optimizer/TestOptimizer.java
===================================================================
--- trunk/engine/src/test/java/com/metamatrix/query/optimizer/TestOptimizer.java	2009-07-31 15:42:46 UTC (rev 1211)
+++ trunk/engine/src/test/java/com/metamatrix/query/optimizer/TestOptimizer.java	2009-08-04 16:37:03 UTC (rev 1212)
@@ -53,7 +53,7 @@
 import com.metamatrix.query.optimizer.capabilities.SourceCapabilities.Capability;
 import com.metamatrix.query.optimizer.relational.AliasGenerator;
 import com.metamatrix.query.optimizer.relational.rules.CapabilitiesUtil;
-import com.metamatrix.query.optimizer.relational.rules.NewCalculateCostUtil;
+import com.metamatrix.query.optimizer.relational.rules.RuleChooseDependent;
 import com.metamatrix.query.parser.QueryParser;
 import com.metamatrix.query.processor.ProcessorPlan;
 import com.metamatrix.query.processor.relational.AccessNode;
@@ -3085,7 +3085,7 @@
 
         FakeMetadataFacade metadata = FakeMetadataFactory.example1();
         FakeMetadataObject g1 = metadata.getStore().findObject("pm1.g1", FakeMetadataObject.GROUP); //$NON-NLS-1$
-        g1.putProperty(FakeMetadataObject.Props.CARDINALITY, new Integer(NewCalculateCostUtil.DEFAULT_STRONG_COST + 1));
+        g1.putProperty(FakeMetadataObject.Props.CARDINALITY, new Integer(RuleChooseDependent.DEFAULT_INDEPENDENT_CARDINALITY + 1));
     
         ProcessorPlan plan = helpPlan(sql, metadata,  
             null, capFinder,
@@ -3122,9 +3122,9 @@
 
         FakeMetadataFacade metadata = FakeMetadataFactory.example1();
         FakeMetadataObject g1 = metadata.getStore().findObject("pm1.g1", FakeMetadataObject.GROUP); //$NON-NLS-1$
-        g1.putProperty(FakeMetadataObject.Props.CARDINALITY, new Integer(NewCalculateCostUtil.DEFAULT_STRONG_COST + 500));
+        g1.putProperty(FakeMetadataObject.Props.CARDINALITY, new Integer(RuleChooseDependent.DEFAULT_INDEPENDENT_CARDINALITY + 500));
         FakeMetadataObject g2 = metadata.getStore().findObject("pm1.g2", FakeMetadataObject.GROUP); //$NON-NLS-1$
-        g2.putProperty(FakeMetadataObject.Props.CARDINALITY, new Integer(NewCalculateCostUtil.DEFAULT_STRONG_COST + 1000));
+        g2.putProperty(FakeMetadataObject.Props.CARDINALITY, new Integer(RuleChooseDependent.DEFAULT_INDEPENDENT_CARDINALITY + 1000));
     
         ProcessorPlan plan = helpPlan(sql, metadata,  
             null, capFinder,
@@ -3197,9 +3197,9 @@
 
         FakeMetadataFacade metadata = FakeMetadataFactory.example1();
         FakeMetadataObject g1 = metadata.getStore().findObject("pm1.g1", FakeMetadataObject.GROUP); //$NON-NLS-1$
-        g1.putProperty(FakeMetadataObject.Props.CARDINALITY, new Integer(NewCalculateCostUtil.DEFAULT_STRONG_COST + 500));
+        g1.putProperty(FakeMetadataObject.Props.CARDINALITY, new Integer(RuleChooseDependent.DEFAULT_INDEPENDENT_CARDINALITY + 500));
         FakeMetadataObject g2 = metadata.getStore().findObject("pm2.g2", FakeMetadataObject.GROUP); //$NON-NLS-1$
-        g2.putProperty(FakeMetadataObject.Props.CARDINALITY, new Integer(NewCalculateCostUtil.DEFAULT_STRONG_COST + 1000));
+        g2.putProperty(FakeMetadataObject.Props.CARDINALITY, new Integer(RuleChooseDependent.DEFAULT_INDEPENDENT_CARDINALITY + 1000));
     
         ProcessorPlan plan = helpPlan(sql, metadata,  
             null, capFinder,
@@ -3238,9 +3238,9 @@
 
         FakeMetadataFacade metadata = FakeMetadataFactory.example1();
         FakeMetadataObject g1 = metadata.getStore().findObject("pm1.g1", FakeMetadataObject.GROUP); //$NON-NLS-1$
-        g1.putProperty(FakeMetadataObject.Props.CARDINALITY, new Integer(NewCalculateCostUtil.DEFAULT_STRONG_COST + 500));
+        g1.putProperty(FakeMetadataObject.Props.CARDINALITY, new Integer(RuleChooseDependent.DEFAULT_INDEPENDENT_CARDINALITY + 500));
         FakeMetadataObject g2 = metadata.getStore().findObject("pm2.g2", FakeMetadataObject.GROUP); //$NON-NLS-1$
-        g2.putProperty(FakeMetadataObject.Props.CARDINALITY, new Integer(NewCalculateCostUtil.DEFAULT_STRONG_COST + 1000));
+        g2.putProperty(FakeMetadataObject.Props.CARDINALITY, new Integer(RuleChooseDependent.DEFAULT_INDEPENDENT_CARDINALITY + 1000));
     
         ProcessorPlan plan = helpPlan(sql, metadata,  
             null, capFinder,
@@ -3282,9 +3282,9 @@
         FakeMetadataObject model = metadata.getStore().findObject("pm1", FakeMetadataObject.MODEL); //$NON-NLS-1$
         FakeMetadataObject model2 = metadata.getStore().findObject("pm2", FakeMetadataObject.MODEL); //$NON-NLS-1$
         FakeMetadataObject g1 = metadata.getStore().findObject("pm1.g1", FakeMetadataObject.GROUP); //$NON-NLS-1$
-        g1.putProperty(FakeMetadataObject.Props.CARDINALITY, new Integer(NewCalculateCostUtil.DEFAULT_STRONG_COST + 500));
+        g1.putProperty(FakeMetadataObject.Props.CARDINALITY, new Integer(RuleChooseDependent.DEFAULT_INDEPENDENT_CARDINALITY + 500));
         FakeMetadataObject g2 = metadata.getStore().findObject("pm2.g2", FakeMetadataObject.GROUP); //$NON-NLS-1$
-        g2.putProperty(FakeMetadataObject.Props.CARDINALITY, new Integer(NewCalculateCostUtil.DEFAULT_STRONG_COST + 1000));
+        g2.putProperty(FakeMetadataObject.Props.CARDINALITY, new Integer(RuleChooseDependent.DEFAULT_INDEPENDENT_CARDINALITY + 1000));
     
         ProcessorPlan plan = helpPlan(sql, metadata,  
             null, capFinder,
@@ -3324,9 +3324,9 @@
         FakeMetadataFacade metadata = FakeMetadataFactory.example1();
         FakeMetadataObject model = metadata.getStore().findObject("pm1", FakeMetadataObject.MODEL); //$NON-NLS-1$
         FakeMetadataObject g1 = metadata.getStore().findObject("pm1.g1", FakeMetadataObject.GROUP); //$NON-NLS-1$
-        g1.putProperty(FakeMetadataObject.Props.CARDINALITY, new Integer(NewCalculateCostUtil.DEFAULT_STRONG_COST + 500));
+        g1.putProperty(FakeMetadataObject.Props.CARDINALITY, new Integer(RuleChooseDependent.DEFAULT_INDEPENDENT_CARDINALITY + 500));
         FakeMetadataObject g2 = metadata.getStore().findObject("pm1.g2", FakeMetadataObject.GROUP); //$NON-NLS-1$
-        g2.putProperty(FakeMetadataObject.Props.CARDINALITY, new Integer(NewCalculateCostUtil.DEFAULT_STRONG_COST + 1000));
+        g2.putProperty(FakeMetadataObject.Props.CARDINALITY, new Integer(RuleChooseDependent.DEFAULT_INDEPENDENT_CARDINALITY + 1000));
     
         ProcessorPlan plan = helpPlan(sql, metadata,  
             null, capFinder,
@@ -3364,11 +3364,11 @@
 
         FakeMetadataFacade metadata = FakeMetadataFactory.example1();
         FakeMetadataObject g1 = metadata.getStore().findObject("pm1.g1", FakeMetadataObject.GROUP); //$NON-NLS-1$
-        g1.putProperty(FakeMetadataObject.Props.CARDINALITY, new Integer(NewCalculateCostUtil.DEFAULT_STRONG_COST + 500));
+        g1.putProperty(FakeMetadataObject.Props.CARDINALITY, new Integer(RuleChooseDependent.DEFAULT_INDEPENDENT_CARDINALITY + 500));
         FakeMetadataObject g2 = metadata.getStore().findObject("pm1.g2", FakeMetadataObject.GROUP); //$NON-NLS-1$
-        g2.putProperty(FakeMetadataObject.Props.CARDINALITY, new Integer(NewCalculateCostUtil.DEFAULT_STRONG_COST + 1000));
+        g2.putProperty(FakeMetadataObject.Props.CARDINALITY, new Integer(RuleChooseDependent.DEFAULT_INDEPENDENT_CARDINALITY + 1000));
         FakeMetadataObject g3 = metadata.getStore().findObject("pm1.g3", FakeMetadataObject.GROUP); //$NON-NLS-1$
-        g3.putProperty(FakeMetadataObject.Props.CARDINALITY, new Integer(NewCalculateCostUtil.DEFAULT_STRONG_COST + 1000));
+        g3.putProperty(FakeMetadataObject.Props.CARDINALITY, new Integer(RuleChooseDependent.DEFAULT_INDEPENDENT_CARDINALITY + 1000));
     
         ProcessorPlan plan = helpPlan(sql, metadata,  
             null, capFinder,
@@ -3501,9 +3501,9 @@
 
         FakeMetadataFacade metadata = FakeMetadataFactory.example1();
         FakeMetadataObject g1 = metadata.getStore().findObject("pm1.g1", FakeMetadataObject.GROUP); //$NON-NLS-1$
-        g1.putProperty(FakeMetadataObject.Props.CARDINALITY, new Integer(NewCalculateCostUtil.DEFAULT_STRONG_COST - 1));
+        g1.putProperty(FakeMetadataObject.Props.CARDINALITY, new Integer(RuleChooseDependent.DEFAULT_INDEPENDENT_CARDINALITY - 1));
         FakeMetadataObject g2 = metadata.getStore().findObject("pm1.g2", FakeMetadataObject.GROUP); //$NON-NLS-1$
-        g2.putProperty(FakeMetadataObject.Props.CARDINALITY, new Integer(NewCalculateCostUtil.DEFAULT_STRONG_COST + 1000));
+        g2.putProperty(FakeMetadataObject.Props.CARDINALITY, new Integer(RuleChooseDependent.DEFAULT_INDEPENDENT_CARDINALITY + 1000));
     
         ProcessorPlan plan = helpPlan(sql, metadata,  
             null, capFinder,
@@ -4440,9 +4440,9 @@
 
         FakeMetadataFacade metadata = FakeMetadataFactory.exampleBQT();
         FakeMetadataObject g1 = metadata.getStore().findObject("BQT1.SmallA", FakeMetadataObject.GROUP); //$NON-NLS-1$
-        g1.putProperty(FakeMetadataObject.Props.CARDINALITY, new Integer(NewCalculateCostUtil.DEFAULT_STRONG_COST - 1));
+        g1.putProperty(FakeMetadataObject.Props.CARDINALITY, new Integer(RuleChooseDependent.DEFAULT_INDEPENDENT_CARDINALITY - 1));
         FakeMetadataObject g2 = metadata.getStore().findObject("BQT1.SmallB", FakeMetadataObject.GROUP); //$NON-NLS-1$
-        g2.putProperty(FakeMetadataObject.Props.CARDINALITY, new Integer(NewCalculateCostUtil.DEFAULT_STRONG_COST + 1000));
+        g2.putProperty(FakeMetadataObject.Props.CARDINALITY, new Integer(RuleChooseDependent.DEFAULT_INDEPENDENT_CARDINALITY + 1000));
          
         ProcessorPlan plan = helpPlan(
             "SELECT BQT1.SmallA.IntKey FROM BQT1.SmallA, BQT1.SmallB WHERE (BQT1.SmallA.IntKey = lookup('BQT1.SmallB', 'IntKey', 'StringKey', BQT1.SmallB.StringKey)) AND (BQT1.SmallA.IntKey = 1)",  //$NON-NLS-1$
@@ -4484,9 +4484,9 @@
 
         FakeMetadataFacade metadata = FakeMetadataFactory.exampleBQT();
         FakeMetadataObject g1 = metadata.getStore().findObject("BQT1.SmallA", FakeMetadataObject.GROUP); //$NON-NLS-1$
-        g1.putProperty(FakeMetadataObject.Props.CARDINALITY, new Integer(NewCalculateCostUtil.DEFAULT_STRONG_COST - 1));
+        g1.putProperty(FakeMetadataObject.Props.CARDINALITY, new Integer(RuleChooseDependent.DEFAULT_INDEPENDENT_CARDINALITY - 1));
         FakeMetadataObject g2 = metadata.getStore().findObject("BQT1.MediumB", FakeMetadataObject.GROUP); //$NON-NLS-1$
-        g2.putProperty(FakeMetadataObject.Props.CARDINALITY, new Integer(NewCalculateCostUtil.DEFAULT_STRONG_COST + 1000));
+        g2.putProperty(FakeMetadataObject.Props.CARDINALITY, new Integer(RuleChooseDependent.DEFAULT_INDEPENDENT_CARDINALITY + 1000));
          
         ProcessorPlan plan = helpPlan(
             "SELECT BQT1.SmallA.IntKey, BQT1.MediumB.IntKey FROM BQT1.SmallA LEFT OUTER JOIN BQT1.MediumB ON BQT1.SmallA.IntKey = lookup('BQT1.MediumB', 'IntKey', 'StringKey', BQT1.MediumB.StringKey)",  //$NON-NLS-1$
@@ -4528,9 +4528,9 @@
 
         FakeMetadataFacade metadata = FakeMetadataFactory.exampleBQT();
         FakeMetadataObject g1 = metadata.getStore().findObject("BQT1.SmallA", FakeMetadataObject.GROUP); //$NON-NLS-1$
-        g1.putProperty(FakeMetadataObject.Props.CARDINALITY, new Integer(NewCalculateCostUtil.DEFAULT_STRONG_COST - 1));
+        g1.putProperty(FakeMetadataObject.Props.CARDINALITY, new Integer(RuleChooseDependent.DEFAULT_INDEPENDENT_CARDINALITY - 1));
         FakeMetadataObject g2 = metadata.getStore().findObject("BQT1.MediumB", FakeMetadataObject.GROUP); //$NON-NLS-1$
-        g2.putProperty(FakeMetadataObject.Props.CARDINALITY, new Integer(NewCalculateCostUtil.DEFAULT_STRONG_COST + 1000));
+        g2.putProperty(FakeMetadataObject.Props.CARDINALITY, new Integer(RuleChooseDependent.DEFAULT_INDEPENDENT_CARDINALITY + 1000));
          
         ProcessorPlan plan = helpPlan(
             "SELECT BQT1.SmallA.IntKey, BQT1.MediumB.IntKey FROM BQT1.MediumB RIGHT OUTER JOIN BQT1.SmallA ON BQT1.SmallA.IntKey = lookup('BQT1.MediumB', 'IntKey', 'StringKey',BQT1.MediumB.StringKey)",  //$NON-NLS-1$          

Modified: trunk/engine/src/test/java/com/metamatrix/query/optimizer/relational/rules/TestCalculateCostUtil.java
===================================================================
--- trunk/engine/src/test/java/com/metamatrix/query/optimizer/relational/rules/TestCalculateCostUtil.java	2009-07-31 15:42:46 UTC (rev 1211)
+++ trunk/engine/src/test/java/com/metamatrix/query/optimizer/relational/rules/TestCalculateCostUtil.java	2009-08-04 16:37:03 UTC (rev 1212)
@@ -22,8 +22,10 @@
 
 package com.metamatrix.query.optimizer.relational.rules;
 
-import junit.framework.TestCase;
+import static org.junit.Assert.*;
 
+import org.junit.Test;
+
 import com.metamatrix.api.exception.MetaMatrixComponentException;
 import com.metamatrix.api.exception.query.QueryMetadataException;
 import com.metamatrix.api.exception.query.QueryParserException;
@@ -31,6 +33,7 @@
 import com.metamatrix.api.exception.query.QueryValidatorException;
 import com.metamatrix.query.metadata.QueryMetadataInterface;
 import com.metamatrix.query.optimizer.TestOptimizer;
+import com.metamatrix.query.optimizer.TestOptimizer.ComparisonMode;
 import com.metamatrix.query.optimizer.relational.GenerateCanonical;
 import com.metamatrix.query.optimizer.relational.plantree.NodeConstants;
 import com.metamatrix.query.optimizer.relational.plantree.NodeFactory;
@@ -46,19 +49,8 @@
 import com.metamatrix.query.unittest.FakeMetadataObject;
 import com.metamatrix.query.util.CommandContext;
 
-/**
- * Test of {@link CalculateCostUtil}
- */
-public class TestCalculateCostUtil extends TestCase {
+public class TestCalculateCostUtil {
 
-    /**
-     * Constructor for TestCapabilitiesUtil.
-     * @param name
-     */
-    public TestCalculateCostUtil(String name) {
-        super(name);
-    }
-    
     // =====================================================================
     // HELPERS
     // =====================================================================
@@ -100,58 +92,45 @@
     // TESTS
     // =====================================================================
     
-    /** Merrill ran into a problem with this type of criteria */
-    public void testEstimateCostOfCriteria() throws Exception {
+    @Test public void testEstimateCostOfCriteria() throws Exception {
         QueryMetadataInterface metadata = FakeMetadataFactory.example4();
         String critString = "pm2.g3.e1 = '3' or pm2.g3.e2 = 2"; //$NON-NLS-1$
         
         helpTestEstimateCost(critString, NewCalculateCostUtil.UNKNOWN_VALUE, NewCalculateCostUtil.UNKNOWN_VALUE, metadata);
     }
 
-    public void testEstimateCostOfCompareCriteria() throws Exception {
+    @Test public void testEstimateCostOfCompareCriteria() throws Exception {
         QueryMetadataInterface metadata = FakeMetadataFactory.example4();
         String critString = "pm1.g1.e1 = '3'"; //$NON-NLS-1$
         
         helpTestEstimateCost(critString, NewCalculateCostUtil.UNKNOWN_VALUE, 1, metadata);    
-    }    
-
-    /** defect 15045 */ 
-    public void testEstimateCostOfCompareCriteria2() throws Exception {
+    }  
+    
+    @Test public void testEstimateCostOfCompareCriteria1() throws Exception {
         QueryMetadataInterface metadata = FakeMetadataFactory.example4();
-        String critString = "'3' = pm1.g1.e1"; //$NON-NLS-1$
+        String critString = "pm1.g1.e1 < '3'"; //$NON-NLS-1$
         
-        helpTestEstimateCost(critString, NewCalculateCostUtil.UNKNOWN_VALUE, 1, metadata);
-    }    
-    
+        helpTestEstimateCost(critString, NewCalculateCostUtil.UNKNOWN_VALUE, NewCalculateCostUtil.UNKNOWN_VALUE, metadata);    
+    } 
+
     /**
      * usesKey = false
      * NOT = false
      */
-    public void testEstimateCostOfMatchCriteria1() throws Exception {
+    @Test public void testEstimateCostOfMatchCriteria1() throws Exception {
         QueryMetadataInterface metadata = FakeMetadataFactory.example4();
-        String critString = "pm2.g3.e1 LIKE '#'"; //$NON-NLS-1$
+        String critString = "pm2.g3.e1 LIKE '#%'"; //$NON-NLS-1$
         
         helpTestEstimateCost(critString, 300, 100, metadata);
     }
 
     /**
      * usesKey = false
-     * NOT = false
-     */
-    public void testEstimateCostOfMatchCriteria1a() throws Exception {
-        QueryMetadataInterface metadata = FakeMetadataFactory.example4();
-        String critString = "'#' LIKE pm2.g3.e1"; //$NON-NLS-1$
-        
-        helpTestEstimateCost(critString, 300, 100, metadata);
-    }    
-    
-    /**
-     * usesKey = false
      * NOT = true
      */
-    public void testEstimateCostOfMatchCriteria2() throws Exception {
+    @Test public void testEstimateCostOfMatchCriteria2() throws Exception {
         QueryMetadataInterface metadata = FakeMetadataFactory.example4();
-        String critString = "pm2.g3.e1 NOT LIKE '#'"; //$NON-NLS-1$
+        String critString = "pm2.g3.e1 NOT LIKE '#_'"; //$NON-NLS-1$
         
         helpTestEstimateCost(critString, 300, 200, metadata);
     }
@@ -160,51 +139,29 @@
      * usesKey = true
      * NOT = false
      */
-    public void testEstimateCostOfMatchCriteria3() throws Exception {
+    @Test public void testEstimateCostOfMatchCriteria3() throws Exception {
         QueryMetadataInterface metadata = FakeMetadataFactory.example4();
-        String critString = "pm1.g1.e1 LIKE '#'"; //$NON-NLS-1$
+        String critString = "pm1.g1.e1 LIKE '#_'"; //$NON-NLS-1$
         
-        helpTestEstimateCost(critString, 300, 1, metadata);
+        helpTestEstimateCost(critString, 300, 50, metadata);
     }
-
-    /**
-     * usesKey = true
-     * NOT = false
-     */
-    public void testEstimateCostOfMatchCriteria3a() throws Exception {
-        QueryMetadataInterface metadata = FakeMetadataFactory.example4();
-        String critString = "'#' LIKE pm1.g1.e1"; //$NON-NLS-1$
-        
-        helpTestEstimateCost(critString, 300, 1, metadata);
-    }    
     
     /**
      * usesKey = true
      * NOT = true
      */
-    public void testEstimateCostOfMatchCriteria4() throws Exception {
+    @Test public void testEstimateCostOfMatchCriteria4() throws Exception {
         QueryMetadataInterface metadata = FakeMetadataFactory.example4();
-        String critString = "pm1.g1.e1 NOT LIKE '#'"; //$NON-NLS-1$
+        String critString = "pm1.g1.e1 NOT LIKE '#_'"; //$NON-NLS-1$
         
-        helpTestEstimateCost(critString, 300, 299, metadata);
+        helpTestEstimateCost(critString, 300, 249, metadata);
     }
-
-    /**
-     * usesKey = true
-     * NOT = true
-     */
-    public void testEstimateCostOfMatchCriteria4a() throws Exception {
-        QueryMetadataInterface metadata = FakeMetadataFactory.example4();
-        String critString = "'#' NOT LIKE pm1.g1.e1"; //$NON-NLS-1$
-        
-        helpTestEstimateCost(critString, 300, 299, metadata);
-    }    
     
     /**
      * usesKey = false
      * NOT = false
      */
-    public void testEstimateCostOfIsNullCriteria1() throws Exception {
+    @Test public void testEstimateCostOfIsNullCriteria1() throws Exception {
         QueryMetadataInterface metadata = FakeMetadataFactory.example4();
         String critString = "pm2.g3.e1 IS NULL"; //$NON-NLS-1$
         
@@ -215,7 +172,7 @@
      * usesKey = false
      * NOT = true
      */
-    public void testEstimateCostOfIsNullCriteria2() throws Exception {
+    @Test public void testEstimateCostOfIsNullCriteria2() throws Exception {
         QueryMetadataInterface metadata = FakeMetadataFactory.example4();
         String critString = "pm2.g3.e1 IS NOT NULL"; //$NON-NLS-1$
         
@@ -226,7 +183,7 @@
      * usesKey = true
      * NOT = false
      */
-    public void testEstimateCostOfIsNullCriteria3() throws Exception {
+    @Test public void testEstimateCostOfIsNullCriteria3() throws Exception {
         QueryMetadataInterface metadata = FakeMetadataFactory.example4();
         String critString = "pm1.g1.e1 IS NULL"; //$NON-NLS-1$
         
@@ -237,7 +194,7 @@
      * usesKey = true
      * NOT = true
      */
-    public void testEstimateCostOfIsNullCriteria4() throws Exception {
+    @Test public void testEstimateCostOfIsNullCriteria4() throws Exception {
         QueryMetadataInterface metadata = FakeMetadataFactory.example4();
         String critString = "pm1.g1.e1 IS NOT NULL"; //$NON-NLS-1$
         
@@ -249,7 +206,7 @@
      * known child cost = false
      * NOT = false
      */
-    public void testEstimateCostOfSetCriteria1() throws Exception {
+    @Test public void testEstimateCostOfSetCriteria1() throws Exception {
         QueryMetadataInterface metadata = FakeMetadataFactory.example4();
         String critString = "pm2.g3.e1 IN ('2', '3')"; //$NON-NLS-1$
         
@@ -261,7 +218,7 @@
      * known child cost = false
      * NOT = true
      */
-    public void testEstimateCostOfSetCriteria2() throws Exception {
+    @Test public void testEstimateCostOfSetCriteria2() throws Exception {
         QueryMetadataInterface metadata = FakeMetadataFactory.example4();
         String critString = "pm2.g3.e1 NOT IN ('2', '3')"; //$NON-NLS-1$
         
@@ -273,7 +230,7 @@
      * known child cost = true
      * NOT = false
      */
-    public void testEstimateCostOfSetCriteria3() throws Exception {
+    @Test public void testEstimateCostOfSetCriteria3() throws Exception {
         QueryMetadataInterface metadata = FakeMetadataFactory.example4();
         String critString = "pm2.g3.e1 IN ('2', '3')"; //$NON-NLS-1$
         
@@ -285,7 +242,7 @@
      * known child cost = true
      * NOT = true
      */
-    public void testEstimateCostOfSetCriteria4() throws Exception {
+    @Test public void testEstimateCostOfSetCriteria4() throws Exception {
         QueryMetadataInterface metadata = FakeMetadataFactory.example4();
         String critString = "pm2.g3.e1 NOT IN ('2', '3')"; //$NON-NLS-1$
         
@@ -297,7 +254,7 @@
      * known child cost = false
      * NOT = false
      */
-    public void testEstimateCostOfSetCriteria5() throws Exception {
+    @Test public void testEstimateCostOfSetCriteria5() throws Exception {
         QueryMetadataInterface metadata = FakeMetadataFactory.example4();
         String critString = "pm1.g1.e1 IN ('2', '3')"; //$NON-NLS-1$
         
@@ -309,7 +266,7 @@
      * known child cost = false
      * NOT = true
      */
-    public void testEstimateCostOfSetCriteria6() throws Exception {
+    @Test public void testEstimateCostOfSetCriteria6() throws Exception {
         QueryMetadataInterface metadata = FakeMetadataFactory.example4();
         String critString = "pm1.g1.e1 NOT IN ('2', '3')"; //$NON-NLS-1$
         
@@ -321,7 +278,7 @@
      * known child cost = true
      * NOT = false
      */
-    public void testEstimateCostOfSetCriteria7() throws Exception {
+    @Test public void testEstimateCostOfSetCriteria7() throws Exception {
         QueryMetadataInterface metadata = FakeMetadataFactory.example4();
         String critString = "pm1.g1.e1 IN ('2', '3')"; //$NON-NLS-1$
         
@@ -333,14 +290,14 @@
      * known child cost = true
      * NOT = true
      */
-    public void testEstimateCostOfSetCriteria8() throws Exception{
+    @Test public void testEstimateCostOfSetCriteria8() throws Exception{
         QueryMetadataInterface metadata = FakeMetadataFactory.example4();
         String critString = "pm1.g1.e1 NOT IN ('2', '3')"; //$NON-NLS-1$
         
         helpTestEstimateCost(critString, 200, 198, metadata);
     }
     
-    public void testEstimateJoinNodeCost() throws Exception {
+    @Test public void testEstimateJoinNodeCost() throws Exception {
         QueryMetadataInterface metadata = FakeMetadataFactory.example4();
         PlanNode joinNode = helpGetJoinNode(NewCalculateCostUtil.UNKNOWN_VALUE, NewCalculateCostUtil.UNKNOWN_VALUE, JoinType.JOIN_CROSS);
         
@@ -349,11 +306,11 @@
     }
 
     /** 
-     * BOA cases 2159 and 2160, defect 14998
+     * cases 2159 and 2160, defect 14998
      * 
      * e1 and e2 make up a single compound key 
      */
-    public void testEstimateCostOfCriteriaCompoundKey() throws Exception {
+    @Test public void testEstimateCostOfCriteriaCompoundKey() throws Exception {
         QueryMetadataInterface metadata = FakeMetadataFactory.example4();
         String critString = "pm4.g1.e1 = '3' and pm4.g1.e2 = 2"; //$NON-NLS-1$
         
@@ -361,12 +318,12 @@
     }    
 
     /** 
-     * BOA cases 2159 and 2160, defect 14998
+     * cases 2159 and 2160, defect 14998
      * 
      * e1 and e2 make up a single compound key, so an OR criteria cannot be
      * predicted to reduce the cost of the join
      */
-    public void testEstimateCostOfCriteriaCompoundKey2() throws Exception {
+    @Test public void testEstimateCostOfCriteriaCompoundKey2() throws Exception {
         QueryMetadataInterface metadata = FakeMetadataFactory.example4();
         String critString = "pm4.g1.e1 = '3' or pm4.g1.e2 = 2"; //$NON-NLS-1$
         
@@ -374,12 +331,12 @@
     }     
 
     /** 
-     * BOA cases 2159 and 2160, defect 14998
+     * cases 2159 and 2160, defect 14998
      * 
      * e1 and e2 make up a single compound key - this criteria does not
      * lower the cost due to the NOT
      */
-    public void testEstimateCostOfCriteriaCompoundKey3() throws Exception {
+    @Test public void testEstimateCostOfCriteriaCompoundKey3() throws Exception {
         QueryMetadataInterface metadata = FakeMetadataFactory.example4();
         String critString = "pm4.g1.e1 = '3' and not pm4.g1.e2 = 2"; //$NON-NLS-1$
         
@@ -387,12 +344,12 @@
     }     
 
     /** 
-     * BOA cases 2159 and 2160, defect 14998
+     * cases 2159 and 2160, defect 14998
      * 
      * e1 and e2 make up a single compound key - this criteria does not
      * lower the cost due to the 0R
      */
-    public void testEstimateCostOfCriteriaCompoundKey4() throws Exception {
+    @Test public void testEstimateCostOfCriteriaCompoundKey4() throws Exception {
         QueryMetadataInterface metadata = FakeMetadataFactory.example4();
         String critString = "(pm4.g1.e1 = '3' or pm4.g1.e4 = 2.0) and not pm4.g1.e2 = 2"; //$NON-NLS-1$
         
@@ -400,12 +357,12 @@
     }      
 
     /** 
-     * BOA cases 2159 and 2160, defect 14998
+     * cases 2159 and 2160, defect 14998
      * 
      * e1 and e2 make up a single compound key - this criteria does not
      * lower the cost due to the OR
      */
-    public void testEstimateCostOfCriteriaCompoundKey5() throws Exception {
+    @Test public void testEstimateCostOfCriteriaCompoundKey5() throws Exception {
         QueryMetadataInterface metadata = FakeMetadataFactory.example4();
         String critString = "(pm4.g1.e1 = '3' or pm4.g1.e4 = 2.0) and pm4.g1.e2 = 2"; //$NON-NLS-1$
         
@@ -413,12 +370,12 @@
     }    
 
     /** 
-     * BOA cases 2159 and 2160, defect 14998
+     * cases 2159 and 2160, defect 14998
      * 
      * e1 and e2 make up a single compound key - this criteria does not
      * lower the cost due to the OR
      */
-    public void testEstimateCostOfCriteriaCompoundKey6() throws Exception {
+    @Test public void testEstimateCostOfCriteriaCompoundKey6() throws Exception {
         QueryMetadataInterface metadata = FakeMetadataFactory.example4();
         String critString = "(pm4.g1.e1 = '3' and pm4.g1.e2 = 2) or pm4.g1.e4 = 2.0"; //$NON-NLS-1$
         
@@ -426,51 +383,38 @@
     } 
 
     /** 
-     * BOA cases 2159 and 2160, defect 14998
+     * cases 2159 and 2160, defect 14998
      * 
      * e1 and e2 make up a single compound key - this criteria covers that
      * key so the cost should be low
      */
-    public void testEstimateCostOfCriteriaCompoundKey7() throws Exception {
+    @Test public void testEstimateCostOfCriteriaCompoundKey8() throws Exception {
         QueryMetadataInterface metadata = FakeMetadataFactory.example4();
-        String critString = "(pm4.g1.e1 = '3' and pm4.g1.e2 = 2) and pm4.g1.e4 = 2.0"; //$NON-NLS-1$
+        String critString = "pm4.g1.e1 LIKE '3%' and pm4.g1.e2 = 2"; //$NON-NLS-1$
         
         helpTestEstimateCost(critString, NewCalculateCostUtil.UNKNOWN_VALUE, 1, metadata);
-    }     
-
-    /** 
-     * BOA cases 2159 and 2160, defect 14998
-     * 
-     * e1 and e2 make up a single compound key - this criteria covers that
-     * key so the cost should be low
-     */
-    public void testEstimateCostOfCriteriaCompoundKey8() throws Exception {
-        QueryMetadataInterface metadata = FakeMetadataFactory.example4();
-        String critString = "pm4.g1.e1 LIKE '3' and pm4.g1.e2 = 2"; //$NON-NLS-1$
-        
-        helpTestEstimateCost(critString, NewCalculateCostUtil.UNKNOWN_VALUE, 1, metadata);
     }    
 
     /** 
-     * BOA cases 2159 and 2160, defect 14998
+     * cases 2159 and 2160, defect 14998
      * 
      * e1 and e2 make up a single compound key - this criteria does not
      * lower the cost due to the NOT
      */
-    public void testEstimateCostOfCriteriaCompoundKey9() throws Exception {
+    @Test public void testEstimateCostOfCriteriaCompoundKey9() throws Exception {
         QueryMetadataInterface metadata = FakeMetadataFactory.example4();
-        String critString = "pm4.g1.e1 NOT LIKE '3' and pm4.g1.e2 = 2"; //$NON-NLS-1$
+        String critString = "pm4.g1.e1 NOT LIKE '3%' and pm4.g1.e2 = 2"; //$NON-NLS-1$
         
         helpTestEstimateCost(critString, NewCalculateCostUtil.UNKNOWN_VALUE, NewCalculateCostUtil.UNKNOWN_VALUE, metadata);
     }    
 
     /** 
-     * BOA cases 2159 and 2160, defect 14998
+     * cases 2159 and 2160, defect 14998
      * 
      * e1 and e2 make up a single compound key - this criteria covers that
      * key so the cost should be low
      */
-    public void testEstimateCostOfCriteriaCompoundKey10() throws Exception {
+    @Test public void testEstimateCostOfCriteriaCompoundKey10() throws Exception {
         QueryMetadataInterface metadata = FakeMetadataFactory.example4();
         String critString = "'3' LIKE pm4.g1.e1 and pm4.g1.e2 = 2"; //$NON-NLS-1$
         
@@ -478,12 +422,12 @@
     }      
 
     /** 
-     * BOA cases 2159 and 2160, defect 14998
+     * cases 2159 and 2160, defect 14998
      * 
      * e1 and e2 make up a single compound key - this criteria covers that
      * key so the cost should be low
      */
-    public void testEstimateCostOfCriteriaCompoundKey11() throws Exception {
+    @Test public void testEstimateCostOfCriteriaCompoundKey11() throws Exception {
         QueryMetadataInterface metadata = FakeMetadataFactory.example4();
         String critString = "pm4.g1.e1 IS NULL and pm4.g1.e2 = 2"; //$NON-NLS-1$
         
@@ -491,12 +435,12 @@
     }    
 
     /** 
-     * BOA cases 2159 and 2160, defect 14998
+     * cases 2159 and 2160, defect 14998
      * 
      * e1 and e2 make up a single compound key - this criteria does not
      * lower the cost due to the NOT
      */
-    public void testEstimateCostOfCriteriaCompoundKey12() throws Exception {
+    @Test public void testEstimateCostOfCriteriaCompoundKey12() throws Exception {
         QueryMetadataInterface metadata = FakeMetadataFactory.example4();
         String critString = "pm4.g1.e1 IS NOT NULL and pm4.g1.e2 = 2"; //$NON-NLS-1$
         
@@ -504,12 +448,12 @@
     }      
 
     /** 
-     * BOA cases 2159 and 2160, defect 14998
+     * cases 2159 and 2160, defect 14998
      * 
      * e1 and e2 make up a single compound key - this criteria covers that
      * key so the cost should be low
      */
-    public void testEstimateCostOfCriteriaCompoundKey13() throws Exception {
+    @Test public void testEstimateCostOfCriteriaCompoundKey13() throws Exception {
         QueryMetadataInterface metadata = FakeMetadataFactory.example4();
         String critString = "pm4.g1.e1 IN ('3', '4') and pm4.g1.e2 = 2"; //$NON-NLS-1$
         
@@ -517,22 +461,29 @@
     }     
 
     /** 
-     * BOA cases 2159 and 2160, defect 14998
+     * cases 2159 and 2160, defect 14998
      * 
      * e1 and e2 make up a single compound key - this criteria does not
      * lower the cost due to the NOT
      */
-    public void testEstimateCostOfCriteriaCompoundKey14() throws Exception {
+    @Test public void testEstimateCostOfCriteriaCompoundKey14() throws Exception {
         QueryMetadataInterface metadata = FakeMetadataFactory.example4();
         String critString = "pm4.g1.e1 NOT IN ('3', '4') and pm4.g1.e2 = 2"; //$NON-NLS-1$
         
         helpTestEstimateCost(critString, NewCalculateCostUtil.UNKNOWN_VALUE, NewCalculateCostUtil.UNKNOWN_VALUE, metadata);
-    }    
+    } 
     
+    @Test public void testEstimateCostOfCriteriaCompoundKey15() throws Exception {
+        QueryMetadataInterface metadata = FakeMetadataFactory.example4();
+        String critString = "(pm4.g1.e1 = '3' or pm4.g1.e1 = '2') and (pm4.g1.e2 = 2 or pm4.g1.e2 = 1)"; //$NON-NLS-1$
+        
+        helpTestEstimateCost(critString, NewCalculateCostUtil.UNKNOWN_VALUE, 1, metadata);
+    }
+    
     /**
      *  usesKey true
      */
-    public void testEstimateCostOfCriteriaMultiGroup() throws Exception {
+    @Test public void testEstimateCostOfCriteriaMultiGroup() throws Exception {
         QueryMetadataInterface metadata = FakeMetadataFactory.example4();
         String critString = "pm4.g1.e1 = pm1.g1.e1"; //$NON-NLS-1$
         
@@ -542,7 +493,7 @@
     /**
      *  usesKey false
      */
-    public void testEstimateCostOfCriteriaMultiGroup1() throws Exception {
+    @Test public void testEstimateCostOfCriteriaMultiGroup1() throws Exception {
         QueryMetadataInterface metadata = FakeMetadataFactory.example4();
         String critString = "pm2.g3.e1 = pm4.g1.e1"; //$NON-NLS-1$
         
@@ -552,7 +503,7 @@
     /**
      *  usesKey true
      */
-    public void testEstimateCostOfCriteriaMultiGroup2() throws Exception {
+    @Test public void testEstimateCostOfCriteriaMultiGroup2() throws Exception {
         QueryMetadataInterface metadata = FakeMetadataFactory.example4();
         String critString = "pm4.g1.e1 = pm1.g1.e1"; //$NON-NLS-1$
         
@@ -562,7 +513,7 @@
     /**
      *  usesKey false
      */
-    public void testEstimateCostOfCriteriaMultiGroup3() throws Exception {
+    @Test public void testEstimateCostOfCriteriaMultiGroup3() throws Exception {
         QueryMetadataInterface metadata = FakeMetadataFactory.example4();
         String critString = "pm2.g3.e1 = pm4.g1.e1"; //$NON-NLS-1$
         
@@ -573,7 +524,7 @@
      *  Date Criteria - Case using valid max and min date strings.  In the case of date,
      *  the valid strings are timestamp format - since that is what our costing sets them as.
      */
-    public void testEstimateCostOfCriteriaDate1() throws Exception {
+    @Test public void testEstimateCostOfCriteriaDate1() throws Exception {
         QueryMetadataInterface metadata = FakeMetadataFactory.example1();
         FakeMetadataObject e2 = (FakeMetadataObject)metadata.getElementID("pm3.g1.e2"); //$NON-NLS-1$
         e2.putProperty(FakeMetadataObject.Props.MIN_VALUE,"2007-04-03 12:12:12.10"); //$NON-NLS-1$
@@ -587,7 +538,7 @@
      *  Date Criteria - Case using invalid max and min date strings.  In the case of date,
      *  one example of invalid strings is date format - since our costing sets them to timestamp.
      */
-    public void testEstimateCostOfCriteriaDate2() throws Exception {
+    @Test public void testEstimateCostOfCriteriaDate2() throws Exception {
         QueryMetadataInterface metadata = FakeMetadataFactory.example1();
         FakeMetadataObject e2 = (FakeMetadataObject)metadata.getElementID("pm3.g1.e2"); //$NON-NLS-1$
         e2.putProperty(FakeMetadataObject.Props.MIN_VALUE,"2007-04-03"); //$NON-NLS-1$
@@ -600,7 +551,7 @@
     /**
      *  Time Criteria - case using valid max and min time strings.
      */
-    public void testEstimateCostOfCriteriaTime1() throws Exception {
+    @Test public void testEstimateCostOfCriteriaTime1() throws Exception {
         QueryMetadataInterface metadata = FakeMetadataFactory.example1();
         FakeMetadataObject e3 = (FakeMetadataObject)metadata.getElementID("pm3.g1.e3"); //$NON-NLS-1$
         e3.putProperty(FakeMetadataObject.Props.MIN_VALUE,"12:12:12"); //$NON-NLS-1$
@@ -613,7 +564,7 @@
     /**
      *  Time Criteria - case using invalid max and min time strings
      */
-    public void testEstimateCostOfCriteriaTime2() throws Exception {
+    @Test public void testEstimateCostOfCriteriaTime2() throws Exception {
         QueryMetadataInterface metadata = FakeMetadataFactory.example1();
         FakeMetadataObject e3 = (FakeMetadataObject)metadata.getElementID("pm3.g1.e3"); //$NON-NLS-1$
         e3.putProperty(FakeMetadataObject.Props.MIN_VALUE,"2007-04-03 12:12:12.10"); //$NON-NLS-1$
@@ -626,7 +577,7 @@
     /**
      *  Timestamp Criteria - case using valid max and min timestamp strings
      */
-    public void testEstimateCostOfCriteriaTimestamp1() throws Exception {
+    @Test public void testEstimateCostOfCriteriaTimestamp1() throws Exception {
         QueryMetadataInterface metadata = FakeMetadataFactory.example1();
         FakeMetadataObject e4 = (FakeMetadataObject)metadata.getElementID("pm3.g1.e4"); //$NON-NLS-1$
         e4.putProperty(FakeMetadataObject.Props.MIN_VALUE,"2007-04-03 12:12:12.10"); //$NON-NLS-1$
@@ -639,7 +590,7 @@
     /**
      *  Timestamp Criteria - case using invalid max and min timestamp strings
      */
-    public void testEstimateCostOfCriteriaTimestamp2() throws Exception {
+    @Test public void testEstimateCostOfCriteriaTimestamp2() throws Exception {
         QueryMetadataInterface metadata = FakeMetadataFactory.example1();
         FakeMetadataObject e4 = (FakeMetadataObject)metadata.getElementID("pm3.g1.e4"); //$NON-NLS-1$
         e4.putProperty(FakeMetadataObject.Props.MIN_VALUE,"2007-04-03"); //$NON-NLS-1$
@@ -649,56 +600,56 @@
         helpTestEstimateCost(critString, 100, 33, metadata);
     }
 
-    public void testNDVEstimate() throws Exception {
+    @Test public void testNDVEstimate() throws Exception {
         String crit = "US.accounts.account = 10"; //$NON-NLS-1$
         
         helpTestEstimateCost(crit, 1000, 800, TestVirtualDepJoin.exampleVirtualDepJoin());
     }
     
-    public void testNDVEstimate1() throws Exception {
+    @Test public void testNDVEstimate1() throws Exception {
         String crit = "US.accounts.account = US.accounts.customer"; //$NON-NLS-1$
         
         helpTestEstimateCost(crit, 1000, 800, TestVirtualDepJoin.exampleVirtualDepJoin());
     }
     
-    public void testCompoundCriteriaEstimate() throws Exception {
+    @Test public void testCompoundCriteriaEstimate() throws Exception {
         String crit = "US.accounts.account = 10 and US.accounts.account = US.accounts.customer"; //$NON-NLS-1$
         
         helpTestEstimateCost(crit, 1000, 640, TestVirtualDepJoin.exampleVirtualDepJoin());
     }
 
-    public void testCompoundCriteriaEstimate1() throws Exception {
+    @Test public void testCompoundCriteriaEstimate1() throws Exception {
         String crit = "US.accounts.account = 10 or US.accounts.account = US.accounts.customer"; //$NON-NLS-1$
         
         helpTestEstimateCost(crit, 1000, 1000, TestVirtualDepJoin.exampleVirtualDepJoin());
     }
     
-    public void testNNVEstimate() throws Exception {
+    @Test public void testNNVEstimate() throws Exception {
         String crit = "US.accounts.account is null"; //$NON-NLS-1$
         
         helpTestEstimateCost(crit, 1000, 1, TestVirtualDepJoin.exampleVirtualDepJoin());
     }
     
-    public void testNNVEstimate1() throws Exception {
+    @Test public void testNNVEstimate1() throws Exception {
         String crit = "US.accounts.account is null"; //$NON-NLS-1$
         
         helpTestEstimateCost(crit, NewCalculateCostUtil.UNKNOWN_VALUE, 1, TestVirtualDepJoin.exampleVirtualDepJoin());
     }
     
-    public void testCompoundCriteriaEstimate2() throws Exception {
+    @Test public void testCompoundCriteriaEstimate2() throws Exception {
         String crit = "US.accounts.account is null and US.accounts.account = US.accounts.customer"; //$NON-NLS-1$
         
         helpTestEstimateCost(crit, 1000, 1, TestVirtualDepJoin.exampleVirtualDepJoin());
     }
     
-    public void testCompoundCriteriaEstimate3() throws Exception {
+    @Test public void testCompoundCriteriaEstimate3() throws Exception {
         String crit = "US.accounts.account is null or US.accounts.account = US.accounts.customer"; //$NON-NLS-1$
         
         helpTestEstimateCost(crit, 1000, 801, TestVirtualDepJoin.exampleVirtualDepJoin());
     }
     
     //ensures that the ordering of criteria does not effect the costing calculation
-    public void testCompoundCriteriaEstimate4() throws Exception {
+    @Test public void testCompoundCriteriaEstimate4() throws Exception {
         String crit = "US.accounts.account = 10 and US.accounts.account = US.accounts.customer and US.accounts.account < 100"; //$NON-NLS-1$
         
         helpTestEstimateCost(crit, 1000, 213, TestVirtualDepJoin.exampleVirtualDepJoin());
@@ -708,73 +659,99 @@
         helpTestEstimateCost(crit1, 1000, 213, TestVirtualDepJoin.exampleVirtualDepJoin());
     }
     
-    public void testCompoundCriteriaEstimate5() throws Exception {
+    @Test public void testCompoundCriteriaEstimate5() throws Exception {
         String crit = "US.accounts.account is null and US.accounts.account = US.accounts.customer"; //$NON-NLS-1$
         
         helpTestEstimateCost(crit, NewCalculateCostUtil.UNKNOWN_VALUE, 1, TestVirtualDepJoin.exampleVirtualDepJoin());
     }
     
-    public void testCompoundCriteriaEstimate6() throws Exception {
+    @Test public void testCompoundCriteriaEstimate6() throws Exception {
         String crit = "US.accounts.account is null or US.accounts.account = US.accounts.customer"; //$NON-NLS-1$
         
         helpTestEstimateCost(crit, NewCalculateCostUtil.UNKNOWN_VALUE, NewCalculateCostUtil.UNKNOWN_VALUE, TestVirtualDepJoin.exampleVirtualDepJoin());
     }
         
     //min and max are not set, so the default estimate is returned
-    public void testRangeEstimate() throws Exception {
+    @Test public void testRangeEstimate() throws Exception {
         String crit = "US.accounts.account < 100"; //$NON-NLS-1$
         
         helpTestEstimateCost(crit, 1000, 333, TestVirtualDepJoin.exampleVirtualDepJoin());
     }
     
-    public void testRangeEstimate1() throws Exception {
+    @Test public void testRangeEstimate1() throws Exception {
         String crit = "US.accounts.customer < 100"; //$NON-NLS-1$
         
         helpTestEstimateCost(crit, 1000, 100, TestVirtualDepJoin.exampleVirtualDepJoin());
     }
 
-    public void testRangeEstimate2() throws Exception {
+    @Test public void testRangeEstimate2() throws Exception {
         String crit = "US.accounts.customer > 100"; //$NON-NLS-1$
         
         helpTestEstimateCost(crit, 1000, 900, TestVirtualDepJoin.exampleVirtualDepJoin());
     }
     
-    public void testRangeEstimate3() throws Exception {
+    @Test public void testRangeEstimate3() throws Exception {
         String crit = "US.accounts.customer >= 1600"; //$NON-NLS-1$
         
         helpTestEstimateCost(crit, 1000, 1, TestVirtualDepJoin.exampleVirtualDepJoin());
     }
     
-    public void testRangeEstimate4() throws Exception {
+    @Test public void testRangeEstimate4() throws Exception {
         String crit = "US.accounts.customer < -1"; //$NON-NLS-1$
         
         helpTestEstimateCost(crit, 1000, 1, TestVirtualDepJoin.exampleVirtualDepJoin());
     }
     
-    public void testRangeEstimate5() throws Exception {
+    @Test public void testRangeEstimate5() throws Exception {
         String crit = "US.accounts.customer >= -1"; //$NON-NLS-1$
         
         helpTestEstimateCost(crit, 1000, 1000, TestVirtualDepJoin.exampleVirtualDepJoin());
     }
     
-    public void testRangeEstimate6() throws Exception {
+    @Test public void testRangeEstimate6() throws Exception {
         String crit = "US.accounts.pennies >= -2"; //$NON-NLS-1$
         
         helpTestEstimateCost(crit, 1000, 1000, TestVirtualDepJoin.exampleVirtualDepJoin());
     }
     
-    public void testRangeEstimate7() throws Exception {
+    @Test public void testRangeEstimate7() throws Exception {
         String crit = "US.accounts.pennies >= -6"; //$NON-NLS-1$
         
         helpTestEstimateCost(crit, 1000, 800, TestVirtualDepJoin.exampleVirtualDepJoin());
     }
     
-    public void testLimitWithUnknownChildCardinality() throws Exception {
+    @Test public void testLimitWithUnknownChildCardinality() throws Exception {
         String query = "select e1 from pm1.g1 limit 2"; //$NON-NLS-1$
         
         RelationalPlan plan = (RelationalPlan)TestOptimizer.helpPlan(query, FakeMetadataFactory.example1Cached(), new String[] {"SELECT e1 FROM pm1.g1"}); //$NON-NLS-1$
         
         assertEquals(new Float(2), plan.getRootNode().getEstimateNodeCardinality());
     }
+    
+    public void helpTestSetOp(String op, float cost) throws Exception {
+        String query = "SELECT customer as customer_id, convert(account, long) as account_id, convert(txnid, long) as transaction_id, case txn when 'DEP' then 1 when 'TFR' then 2 when 'WD' then 3 else -1 end as txn_type, (pennies + convert('0.00', bigdecimal)) / 100 as amount, 'US' as source FROM US.Accounts where txn != 'X'" +  //$NON-NLS-1$
+        op +  
+        "SELECT id, convert(accid / 10000, long), mod(accid, 10000), convert(type, integer), amount, 'EU' from Europe.CustAccts"; //$NON-NLS-1$
+        
+        RelationalPlan plan = (RelationalPlan)TestOptimizer.helpPlan(query, TestVirtualDepJoin.exampleVirtualDepJoin(), new String[] {"SELECT g_0.customer, g_0.account, g_0.txnid, g_0.txn, g_0.pennies FROM US.Accounts AS g_0 WHERE g_0.txn <> 'X'", "SELECT g_0.id, g_0.accid, g_0.type, g_0.amount FROM Europe.CustAccts AS g_0"}, ComparisonMode.EXACT_COMMAND_STRING); //$NON-NLS-1$ //$NON-NLS-2$
+        
+        assertEquals(cost, plan.getRootNode().getEstimateNodeCardinality());
+    }
+    
+    @Test public void testUnion() throws Exception {
+    	helpTestSetOp("UNION ", 1375000.0f); //$NON-NLS-1$
+    }
+    
+    @Test public void testUnionALL() throws Exception {
+    	helpTestSetOp("UNION ALL ", 1750000.0f); //$NON-NLS-1$
+    }
+    
+    @Test public void testExcept() throws Exception {
+    	helpTestSetOp("EXCEPT ", 250000.0f); //$NON-NLS-1$
+    }
+    
+    @Test public void testIntersect() throws Exception {
+    	helpTestSetOp("INTERSECT ", 375000.0f); //$NON-NLS-1$
+    }
 
 }

Modified: trunk/engine/src/test/java/com/metamatrix/query/optimizer/relational/rules/TestRulePushSelectCriteria.java
===================================================================
--- trunk/engine/src/test/java/com/metamatrix/query/optimizer/relational/rules/TestRulePushSelectCriteria.java	2009-07-31 15:42:46 UTC (rev 1211)
+++ trunk/engine/src/test/java/com/metamatrix/query/optimizer/relational/rules/TestRulePushSelectCriteria.java	2009-08-04 16:37:03 UTC (rev 1212)
@@ -45,7 +45,6 @@
 import com.metamatrix.query.parser.QueryParser;
 import com.metamatrix.query.sql.lang.Command;
 import com.metamatrix.query.sql.symbol.ElementSymbol;
-import com.metamatrix.query.sql.symbol.GroupSymbol;
 import com.metamatrix.query.sql.symbol.SingleElementSymbol;
 import com.metamatrix.query.sql.util.SymbolMap;
 import com.metamatrix.query.unittest.FakeMetadataFacade;

Modified: trunk/engine/src/test/java/com/metamatrix/query/processor/TestProcessor.java
===================================================================
--- trunk/engine/src/test/java/com/metamatrix/query/processor/TestProcessor.java	2009-07-31 15:42:46 UTC (rev 1211)
+++ trunk/engine/src/test/java/com/metamatrix/query/processor/TestProcessor.java	2009-08-04 16:37:03 UTC (rev 1212)
@@ -68,7 +68,7 @@
 import com.metamatrix.query.optimizer.capabilities.DefaultCapabilitiesFinder;
 import com.metamatrix.query.optimizer.capabilities.FakeCapabilitiesFinder;
 import com.metamatrix.query.optimizer.capabilities.SourceCapabilities.Capability;
-import com.metamatrix.query.optimizer.relational.rules.NewCalculateCostUtil;
+import com.metamatrix.query.optimizer.relational.rules.RuleChooseDependent;
 import com.metamatrix.query.parser.QueryParser;
 import com.metamatrix.query.processor.relational.JoinNode;
 import com.metamatrix.query.processor.relational.RelationalNode;
@@ -5211,9 +5211,9 @@
 
         FakeMetadataFacade metadata = FakeMetadataFactory.example1();
         FakeMetadataObject g1 = metadata.getStore().findObject("pm1.g1", FakeMetadataObject.GROUP); //$NON-NLS-1$
-        g1.putProperty(FakeMetadataObject.Props.CARDINALITY, new Integer(NewCalculateCostUtil.DEFAULT_STRONG_COST + 1000));
+        g1.putProperty(FakeMetadataObject.Props.CARDINALITY, new Integer(RuleChooseDependent.DEFAULT_INDEPENDENT_CARDINALITY + 1000));
         FakeMetadataObject g2 = metadata.getStore().findObject("pm2.g1", FakeMetadataObject.GROUP); //$NON-NLS-1$
-        g2.putProperty(FakeMetadataObject.Props.CARDINALITY, new Integer(NewCalculateCostUtil.DEFAULT_STRONG_COST - 1));
+        g2.putProperty(FakeMetadataObject.Props.CARDINALITY, new Integer(RuleChooseDependent.DEFAULT_INDEPENDENT_CARDINALITY - 1));
         
         Command command = helpParse(sql);   
         ProcessorPlan plan = helpGetPlan(command, metadata, capFinder);
@@ -5255,9 +5255,9 @@
 
         FakeMetadataFacade metadata = FakeMetadataFactory.example1();
         FakeMetadataObject g1 = metadata.getStore().findObject("pm4.g1", FakeMetadataObject.GROUP); //$NON-NLS-1$
-        g1.putProperty(FakeMetadataObject.Props.CARDINALITY, new Integer(NewCalculateCostUtil.DEFAULT_STRONG_COST + 1000));
+        g1.putProperty(FakeMetadataObject.Props.CARDINALITY, new Integer(RuleChooseDependent.DEFAULT_INDEPENDENT_CARDINALITY + 1000));
         FakeMetadataObject g2 = metadata.getStore().findObject("pm2.g1", FakeMetadataObject.GROUP); //$NON-NLS-1$
-        g2.putProperty(FakeMetadataObject.Props.CARDINALITY, new Integer(NewCalculateCostUtil.DEFAULT_STRONG_COST - 1));
+        g2.putProperty(FakeMetadataObject.Props.CARDINALITY, new Integer(RuleChooseDependent.DEFAULT_INDEPENDENT_CARDINALITY - 1));
         
         Command command = helpParse(sql);   
         ProcessorPlan plan = helpGetPlan(command, metadata, capFinder);

Modified: trunk/engine/src/test/java/com/metamatrix/query/processor/xml/TestXMLProcessor.java
===================================================================
--- trunk/engine/src/test/java/com/metamatrix/query/processor/xml/TestXMLProcessor.java	2009-07-31 15:42:46 UTC (rev 1211)
+++ trunk/engine/src/test/java/com/metamatrix/query/processor/xml/TestXMLProcessor.java	2009-08-04 16:37:03 UTC (rev 1212)
@@ -10000,7 +10000,7 @@
 
      
     /**
-     * Test for Merrill - if no data is contained in the soap elements
+     * if no data is contained in the soap elements
      * (e.g. ORG:ArrayOfTaxID) and the schema allows it, eliminate the 
      * whole fragment
      */        

Modified: trunk/engine/src/test/java/com/metamatrix/query/rewriter/TestQueryRewriter.java
===================================================================
--- trunk/engine/src/test/java/com/metamatrix/query/rewriter/TestQueryRewriter.java	2009-07-31 15:42:46 UTC (rev 1211)
+++ trunk/engine/src/test/java/com/metamatrix/query/rewriter/TestQueryRewriter.java	2009-08-04 16:37:03 UTC (rev 1212)
@@ -2216,4 +2216,11 @@
     	assertEquals( "e2 <= 5", ccrit.getCriteria(1).toString() ); //$NON-NLS-1$
     }
     
+    @Test public void testRewriteLike() {
+    	String original = "pm1.g1.e1 like '%'"; //$NON-NLS-1$
+    	String expected = "1 = 1"; //$NON-NLS-1$
+    	
+    	helpTestRewriteCriteria(original, expected);
+    }
+    
 }



More information about the teiid-commits mailing list