Author: shawkins
Date: 2011-03-18 21:18:44 -0400 (Fri, 18 Mar 2011)
New Revision: 3009
Modified:
trunk/common-core/src/main/java/org/teiid/core/util/ReflectionHelper.java
trunk/common-core/src/test/java/org/teiid/core/util/TestReflectionHelper.java
trunk/engine/src/main/java/org/teiid/query/optimizer/relational/rules/RulePushAggregates.java
trunk/engine/src/main/java/org/teiid/query/optimizer/relational/rules/RuleRemoveOptionalJoins.java
trunk/engine/src/main/java/org/teiid/query/resolver/QueryResolver.java
trunk/engine/src/main/java/org/teiid/query/rewriter/QueryRewriter.java
trunk/engine/src/main/java/org/teiid/query/sql/lang/Select.java
trunk/engine/src/main/java/org/teiid/query/sql/symbol/AggregateSymbol.java
trunk/engine/src/main/java/org/teiid/query/sql/visitor/AggregateSymbolCollectorVisitor.java
trunk/engine/src/main/java/org/teiid/query/sql/visitor/ExpressionMappingVisitor.java
trunk/engine/src/test/java/org/teiid/query/optimizer/TestSubqueryPushdown.java
Log:
TEIID-1497 expanding the checks performed in the rewriter to allow more conversions to
joins
Modified: trunk/common-core/src/main/java/org/teiid/core/util/ReflectionHelper.java
===================================================================
--- trunk/common-core/src/main/java/org/teiid/core/util/ReflectionHelper.java 2011-03-18
18:50:32 UTC (rev 3008)
+++ trunk/common-core/src/main/java/org/teiid/core/util/ReflectionHelper.java 2011-03-19
01:18:44 UTC (rev 3009)
@@ -40,8 +40,8 @@
public class ReflectionHelper {
- private Class targetClass;
- private Map methodMap = null; // used for the brute-force method finder
+ private Class<?> targetClass;
+ private Map<String, LinkedList<Method>> methodMap = null; // used
for the brute-force method finder
/**
* Construct a ReflectionHelper instance that cache's some information about
@@ -50,7 +50,7 @@
* @param targetClass the target class
* @throws IllegalArgumentException if the target class is null
*/
- public ReflectionHelper( Class targetClass ) {
+ public ReflectionHelper( Class<?> targetClass ) {
if ( targetClass == null ) {
throw new
IllegalArgumentException(CorePlugin.Util.getString("ReflectionHelper.errorConstructing"));
//$NON-NLS-1$
}
@@ -79,10 +79,10 @@
return findBestMethodWithSignature(methodName, Collections.EMPTY_LIST);
}
int size = arguments.length;
- List argumentClasses = new ArrayList(size);
+ List<Class<?>> argumentClasses = new
ArrayList<Class<?>>(size);
for (int i=0; i!=size; ++i) {
if ( arguments[i] != null ) {
- Class clazz = arguments[i].getClass();
+ Class<?> clazz = arguments[i].getClass();
argumentClasses.add( clazz );
} else {
argumentClasses.add(null);
@@ -122,7 +122,7 @@
* @throws NoSuchMethodException if a matching method is not found.
* @throws SecurityException if access to the information is denied.
*/
- public Method findBestMethodWithSignature( String methodName, List argumentsClasses )
throws NoSuchMethodException, SecurityException {
+ public Method findBestMethodWithSignature( String methodName,
List<Class<?>> argumentsClasses ) throws NoSuchMethodException,
SecurityException {
// Attempt to find the method
Method result = null;
Class[] classArgs = new Class[argumentsClasses.size()];
@@ -141,7 +141,7 @@
//
---------------------------------------------------------------------------------------------
// Then try to find a method with the argument classes converted to a primitive,
if possible ...
//
---------------------------------------------------------------------------------------------
- List argumentsClassList = convertArgumentClassesToPrimitives(argumentsClasses);
+ List<Class<?>> argumentsClassList =
convertArgumentClassesToPrimitives(argumentsClasses);
argumentsClassList.toArray(classArgs);
try {
result = this.targetClass.getMethod(methodName,classArgs); // this may throw
an exception if not found
@@ -156,20 +156,20 @@
// the arguments). There is no canned algorithm in Java to do this, so we have
to brute-force it.
//
---------------------------------------------------------------------------------------------
if ( this.methodMap == null ) {
- this.methodMap = new HashMap();
+ this.methodMap = new HashMap<String, LinkedList<Method>>();
Method[] methods = this.targetClass.getMethods();
for ( int i=0; i!=methods.length; ++i ) {
Method method = methods[i];
- LinkedList methodsWithSameName = (LinkedList)
this.methodMap.get(method.getName());
+ LinkedList<Method> methodsWithSameName =
this.methodMap.get(method.getName());
if ( methodsWithSameName == null ) {
- methodsWithSameName = new LinkedList();
+ methodsWithSameName = new LinkedList<Method>();
this.methodMap.put(method.getName(),methodsWithSameName);
}
methodsWithSameName.addFirst(method); // add lower methods first
}
}
- LinkedList<Method> methodsWithSameName = (LinkedList)
this.methodMap.get(methodName);
+ LinkedList<Method> methodsWithSameName = this.methodMap.get(methodName);
if ( methodsWithSameName == null ) {
throw new NoSuchMethodException(methodName);
}
@@ -180,8 +180,8 @@
}
boolean allMatch = true; // assume all args match
for ( int i=0; i<args.length && allMatch == true; ++i ) {
- Class primitiveClazz = (Class) argumentsClassList.get(i);
- Class objectClazz = (Class) argumentsClasses.get(i);
+ Class<?> primitiveClazz = argumentsClassList.get(i);
+ Class<?> objectClazz = argumentsClasses.get(i);
if ( objectClazz != null ) {
// Check for possible matches with (converted) primitive types
// as well as the original Object type
@@ -216,11 +216,9 @@
* @return the list of Class instances in which any classes that could be
represented
* by primitives (e.g., Boolean) were replaced with the primitive classes (e.g.,
Boolean.TYPE).
*/
- private static List convertArgumentClassesToPrimitives( List arguments ) {
- List result = new ArrayList(arguments.size());
- Iterator iter = arguments.iterator();
- while ( iter.hasNext() ) {
- Class clazz = (Class) iter.next();
+ private static List<Class<?>> convertArgumentClassesToPrimitives(
List<Class<?>> arguments ) {
+ List<Class<?>> result = new
ArrayList<Class<?>>(arguments.size());
+ for (Class<?> clazz : arguments) {
if ( clazz == Boolean.class ) clazz = Boolean.TYPE;
else if ( clazz == Character.class ) clazz = Character.TYPE;
else if ( clazz == Byte.class ) clazz = Byte.TYPE;
@@ -244,8 +242,8 @@
* @return Class is the instance of the class
* @throws ClassNotFoundException
*/
- private static final Class loadClass(final String className, final ClassLoader
classLoader) throws ClassNotFoundException {
- Class cls = null;
+ private static final Class<?> loadClass(final String className, final
ClassLoader classLoader) throws ClassNotFoundException {
+ Class<?> cls = null;
if ( classLoader == null ) {
cls = Class.forName(className.trim());
} else {
@@ -290,9 +288,9 @@
public static final Object create(String className, Object[] ctorObjs,
Class<?>[] argTypes,
final ClassLoader classLoader) throws TeiidException {
try {
- final Class cls = loadClass(className,classLoader);
+ final Class<?> cls = loadClass(className,classLoader);
- Constructor ctor = cls.getDeclaredConstructor(argTypes);
+ Constructor<?> ctor = cls.getDeclaredConstructor(argTypes);
return ctor.newInstance(ctorObjs);
Modified: trunk/common-core/src/test/java/org/teiid/core/util/TestReflectionHelper.java
===================================================================
---
trunk/common-core/src/test/java/org/teiid/core/util/TestReflectionHelper.java 2011-03-18
18:50:32 UTC (rev 3008)
+++
trunk/common-core/src/test/java/org/teiid/core/util/TestReflectionHelper.java 2011-03-19
01:18:44 UTC (rev 3009)
@@ -22,28 +22,21 @@
package org.teiid.core.util;
+import static org.junit.Assert.*;
+
import java.io.Serializable;
import java.lang.reflect.Method;
import java.util.ArrayList;
import java.util.List;
-import org.teiid.core.util.ReflectionHelper;
+import org.junit.Test;
-import junit.framework.TestCase;
-
/**
* TestReflectionHelper
*/
-public class TestReflectionHelper extends TestCase {
+@SuppressWarnings("unchecked")
+public class TestReflectionHelper {
- /**
- * Constructor for TestReflectionHelper.
- * @param name
- */
- public TestReflectionHelper(String name) {
- super(name);
- }
-
// =========================================================================
// H E L P E R M E T H O D S
// =========================================================================
@@ -68,7 +61,7 @@
// T E S T C A S E S
// =========================================================================
- public void testConstructorWithNullTargetClass() {
+ @Test public void testConstructorWithNullTargetClass() {
try {
new ReflectionHelper(null);
fail("Should have caught null target class passed to constructor");
//$NON-NLS-1$
@@ -77,7 +70,7 @@
}
}
- public void testConstructorWithValidTargetClass() {
+ @Test public void testConstructorWithValidTargetClass() {
final ReflectionHelper helper = new ReflectionHelper(String.class);
assertNotNull(helper);
}
@@ -85,7 +78,7 @@
//
===============================================================================================
// Test overloaded methods
//
===============================================================================================
- public void testFindBestMethodWithSignature_String() throws Exception {
+ @Test public void testFindBestMethodWithSignature_String() throws Exception {
ReflectionHelper helper = new ReflectionHelper(FakeInterface.class);
Class[] signatureSought = new Class[] {String.class};
Method theMethod = helper.findBestMethodWithSignature("method",
signatureSought ); //$NON-NLS-1$
@@ -98,7 +91,7 @@
helpAssertSameMethodSignature("Found wrong method signature",
signatureExpected, signatureFound); //$NON-NLS-1$
}
- public void testFindBestMethodWithSignature_Serializable() throws Exception {
+ @Test public void testFindBestMethodWithSignature_Serializable() throws Exception {
ReflectionHelper helper = new ReflectionHelper(FakeInterface.class);
Class[] signatureSought = new Class[] {Serializable.class};
Method theMethod = helper.findBestMethodWithSignature("method",
signatureSought ); //$NON-NLS-1$
@@ -111,7 +104,7 @@
helpAssertSameMethodSignature("Found wrong method signature",
signatureExpected, signatureFound); //$NON-NLS-1$
}
- public void testFindBestMethodWithSignature_Object() throws Exception {
+ @Test public void testFindBestMethodWithSignature_Object() throws Exception {
ReflectionHelper helper = new ReflectionHelper(FakeInterface.class);
Class[] signatureSought = new Class[] {NullPointerException.class};
try {
@@ -122,7 +115,7 @@
}
}
- public void testFindBestMethodWithSignature_StringArray() throws Exception {
+ @Test public void testFindBestMethodWithSignature_StringArray() throws Exception {
ReflectionHelper helper = new ReflectionHelper(FakeInterface.class);
Class[] signatureSought = new Class[] {String[].class};
Method theMethod = helper.findBestMethodWithSignature("method",
signatureSought ); //$NON-NLS-1$
@@ -135,7 +128,7 @@
helpAssertSameMethodSignature("Found wrong method signature",
signatureExpected, signatureFound); //$NON-NLS-1$
}
- public void testFindBestMethodWithSignature_Integer() throws Exception {
+ @Test public void testFindBestMethodWithSignature_Integer() throws Exception {
ReflectionHelper helper = new ReflectionHelper(FakeInterface.class);
Class[] signatureSought = new Class[] {Integer.class};
Method theMethod = helper.findBestMethodWithSignature("method",
signatureSought ); //$NON-NLS-1$
@@ -148,7 +141,7 @@
helpAssertSameMethodSignature("Found wrong method signature",
signatureExpected, signatureFound); //$NON-NLS-1$
}
- public void testFindBestMethodWithSignature_long() throws Exception {
+ @Test public void testFindBestMethodWithSignature_long() throws Exception {
ReflectionHelper helper = new ReflectionHelper(FakeInterface.class);
Class[] signatureSought = new Class[] {Long.TYPE};
Method theMethod = helper.findBestMethodWithSignature("method",
signatureSought ); //$NON-NLS-1$
@@ -161,7 +154,7 @@
helpAssertSameMethodSignature("Found wrong method signature",
signatureExpected, signatureFound); //$NON-NLS-1$
}
- public void testFindBestMethodWithSignature_2ArgSerializableAndNumber() throws
Exception {
+ @Test public void testFindBestMethodWithSignature_2ArgSerializableAndNumber() throws
Exception {
ReflectionHelper helper = new ReflectionHelper(FakeInterface.class);
Class[] signatureSought = new Class[] {Integer.class, Integer.class};
Method theMethod = helper.findBestMethodWithSignature("method",
signatureSought ); //$NON-NLS-1$
@@ -177,7 +170,7 @@
//
===============================================================================================
// Test explicit method names
//
===============================================================================================
- public void testFindBestMethodWithSignature_StringAndMethodName() throws Exception {
+ @Test public void testFindBestMethodWithSignature_StringAndMethodName() throws
Exception {
ReflectionHelper helper = new ReflectionHelper(FakeInterface.class);
Class[] signatureSought = new Class[] {String.class};
Method theMethod = helper.findBestMethodWithSignature("methodString",
signatureSought ); //$NON-NLS-1$
@@ -190,7 +183,7 @@
helpAssertSameMethodSignature("Found wrong method signature",
signatureExpected, signatureFound); //$NON-NLS-1$
}
- public void testFindBestMethodWithSignature_ObjectAndMethodName() throws Exception {
+ @Test public void testFindBestMethodWithSignature_ObjectAndMethodName() throws
Exception {
ReflectionHelper helper = new ReflectionHelper(FakeInterface.class);
Class[] signatureSought = new Class[] {NullPointerException.class};
Method theMethod = helper.findBestMethodWithSignature("methodObject",
signatureSought ); //$NON-NLS-1$
@@ -203,7 +196,7 @@
helpAssertSameMethodSignature("Found wrong method signature",
signatureExpected, signatureFound); //$NON-NLS-1$
}
- public void testFindBestMethodWithSignature_SerializableAndMethodName() throws
Exception {
+ @Test public void testFindBestMethodWithSignature_SerializableAndMethodName() throws
Exception {
ReflectionHelper helper = new ReflectionHelper(FakeInterface.class);
Class[] signatureSought = new Class[] {NullPointerException.class};
Method theMethod =
helper.findBestMethodWithSignature("methodSerializable", signatureSought );
//$NON-NLS-1$
@@ -216,7 +209,7 @@
helpAssertSameMethodSignature("Found wrong method signature",
signatureExpected, signatureFound); //$NON-NLS-1$
}
- public void testFindBestMethodWithSignature_ObjectSerializableAndMethodName() throws
Exception {
+ @Test public void testFindBestMethodWithSignature_ObjectSerializableAndMethodName()
throws Exception {
ReflectionHelper helper = new ReflectionHelper(FakeInterface.class);
Class[] signatureSought = new Class[] {NullPointerException.class};
Method theMethod =
helper.findBestMethodWithSignature("methodSerializable", signatureSought );
//$NON-NLS-1$
@@ -229,7 +222,7 @@
helpAssertSameMethodSignature("Found wrong method signature",
signatureExpected, signatureFound); //$NON-NLS-1$
}
- public void testFindBestMethodWithSignature_IntegerSerializableAndMethodName() throws
Exception {
+ @Test public void testFindBestMethodWithSignature_IntegerSerializableAndMethodName()
throws Exception {
ReflectionHelper helper = new ReflectionHelper(FakeInterface.class);
Class[] signatureSought = new Class[] {Integer.class};
Method theMethod =
helper.findBestMethodWithSignature("methodSerializable", signatureSought );
//$NON-NLS-1$
@@ -242,7 +235,7 @@
helpAssertSameMethodSignature("Found wrong method signature",
signatureExpected, signatureFound); //$NON-NLS-1$
}
- public void testFindBestMethodWithSignature_StringArrayAndMethodName() throws
Exception {
+ @Test public void testFindBestMethodWithSignature_StringArrayAndMethodName() throws
Exception {
ReflectionHelper helper = new ReflectionHelper(FakeInterface.class);
Class[] signatureSought = new Class[] {String[].class};
Method theMethod =
helper.findBestMethodWithSignature("methodStringArray", signatureSought );
//$NON-NLS-1$
@@ -255,7 +248,7 @@
helpAssertSameMethodSignature("Found wrong method signature",
signatureExpected, signatureFound); //$NON-NLS-1$
}
- public void testFindBestMethodWithSignature_ListAndMethodName() throws Exception {
+ @Test public void testFindBestMethodWithSignature_ListAndMethodName() throws
Exception {
ReflectionHelper helper = new ReflectionHelper(FakeInterface.class);
Class[] signatureSought = new Class[] {ArrayList.class};
Method theMethod = helper.findBestMethodWithSignature("methodList",
signatureSought ); //$NON-NLS-1$
@@ -268,7 +261,7 @@
helpAssertSameMethodSignature("Found wrong method signature",
signatureExpected, signatureFound); //$NON-NLS-1$
}
- public void testFindBestMethodWithSignature_IntegerAndMethodName() throws Exception
{
+ @Test public void testFindBestMethodWithSignature_IntegerAndMethodName() throws
Exception {
ReflectionHelper helper = new ReflectionHelper(FakeInterface.class);
Class[] signatureSought = new Class[] {Integer.class};
Method theMethod = helper.findBestMethodWithSignature("methodInteger",
signatureSought ); //$NON-NLS-1$
@@ -281,7 +274,7 @@
helpAssertSameMethodSignature("Found wrong method signature",
signatureExpected, signatureFound); //$NON-NLS-1$
}
- public void testFindBestMethodWithSignature_IntegerObjectAndMethodName() throws
Exception {
+ @Test public void testFindBestMethodWithSignature_IntegerObjectAndMethodName() throws
Exception {
ReflectionHelper helper = new ReflectionHelper(FakeInterface.class);
Class[] signatureSought = new Class[] {Integer.class};
Method theMethod = helper.findBestMethodWithSignature("methodObject",
signatureSought ); //$NON-NLS-1$
@@ -294,7 +287,7 @@
helpAssertSameMethodSignature("Found wrong method signature",
signatureExpected, signatureFound); //$NON-NLS-1$
}
- public void testFindBestMethodWithSignature_LongObjectAndMethodName() throws
Exception {
+ @Test public void testFindBestMethodWithSignature_LongObjectAndMethodName() throws
Exception {
ReflectionHelper helper = new ReflectionHelper(FakeInterface.class);
Class[] signatureSought = new Class[] {Long.class};
Method theMethod = helper.findBestMethodWithSignature("methodObject",
signatureSought ); //$NON-NLS-1$
@@ -307,7 +300,7 @@
helpAssertSameMethodSignature("Found wrong method signature",
signatureExpected, signatureFound); //$NON-NLS-1$
}
- public void testFindBestMethodWithSignature_longAndMethodName() throws Exception {
+ @Test public void testFindBestMethodWithSignature_longAndMethodName() throws
Exception {
ReflectionHelper helper = new ReflectionHelper(FakeInterface.class);
Class[] signatureSought = new Class[] {Long.TYPE};
Method theMethod = helper.findBestMethodWithSignature("method_long",
signatureSought ); //$NON-NLS-1$
@@ -323,7 +316,7 @@
//
===============================================================================================
// Test 2-arg methods
//
===============================================================================================
- public void testFindBestMethodWithSignature_2ArgIntegerObjectAndMethodName() throws
Exception {
+ @Test public void testFindBestMethodWithSignature_2ArgIntegerObjectAndMethodName()
throws Exception {
ReflectionHelper helper = new ReflectionHelper(FakeInterface.class);
Class[] signatureSought = new Class[] {Integer.class, Integer.class};
Method theMethod =
helper.findBestMethodWithSignature("twoArgMethod_Object_Object", signatureSought
); //$NON-NLS-1$
@@ -336,7 +329,7 @@
helpAssertSameMethodSignature("Found wrong method signature",
signatureExpected, signatureFound); //$NON-NLS-1$
}
- public void testFindBestMethodWithSignature_2ArgLongObjectAndMethodName() throws
Exception {
+ @Test public void testFindBestMethodWithSignature_2ArgLongObjectAndMethodName()
throws Exception {
ReflectionHelper helper = new ReflectionHelper(FakeInterface.class);
Class[] signatureSought = new Class[] {Long.class, Long.class};
Method theMethod =
helper.findBestMethodWithSignature("twoArgMethod_Object_Object", signatureSought
); //$NON-NLS-1$
@@ -349,7 +342,7 @@
helpAssertSameMethodSignature("Found wrong method signature",
signatureExpected, signatureFound); //$NON-NLS-1$
}
- public void testFindBestMethodWithSignature_2ArgSerializableNumberAndMethodName()
throws Exception {
+ @Test public void
testFindBestMethodWithSignature_2ArgSerializableNumberAndMethodName() throws Exception {
ReflectionHelper helper = new ReflectionHelper(FakeInterface.class);
Class[] signatureSought = new Class[] {Long.class, Long.class};
Method theMethod =
helper.findBestMethodWithSignature("twoArgMethod_Serializable_Number",
signatureSought ); //$NON-NLS-1$
@@ -365,7 +358,7 @@
//
===============================================================================================
// Test overridden methods
//
===============================================================================================
- public void testFindBestMethodWithSignature_SubInterface_2ArgSerializableAndNumber()
throws Exception {
+ @Test public void
testFindBestMethodWithSignature_SubInterface_2ArgSerializableAndNumber() throws Exception
{
ReflectionHelper helper = new ReflectionHelper(FakeSubInterface.class);
Class[] signatureSought = new Class[] {Serializable.class, Number.class};
Method theMethod = helper.findBestMethodWithSignature("method",
signatureSought ); //$NON-NLS-1$
@@ -378,7 +371,7 @@
helpAssertSameMethodSignature("Found wrong method signature",
signatureExpected, signatureFound); //$NON-NLS-1$
}
- public void testFindBestMethodWithSignature_SubInterface_2ArgSerializableAndLong()
throws Exception {
+ @Test public void
testFindBestMethodWithSignature_SubInterface_2ArgSerializableAndLong() throws Exception {
ReflectionHelper helper = new ReflectionHelper(FakeSubInterface.class);
Class[] signatureSought = new Class[] {Serializable.class, Long.class};
Method theMethod = helper.findBestMethodWithSignature("method",
signatureSought ); //$NON-NLS-1$
@@ -390,12 +383,12 @@
assertEquals("Wrong class", theMethod.getDeclaringClass().getName(),
FakeSubInterface.class.getName()); //$NON-NLS-1$
helpAssertSameMethodSignature("Found wrong method signature",
signatureExpected, signatureFound); //$NON-NLS-1$
}
-
+
/**
* Test base interface
*/
public interface FakeInterface {
-
+
void method(String arg);
void method(Serializable arg);
void method(Object arg);
Modified:
trunk/engine/src/main/java/org/teiid/query/optimizer/relational/rules/RulePushAggregates.java
===================================================================
---
trunk/engine/src/main/java/org/teiid/query/optimizer/relational/rules/RulePushAggregates.java 2011-03-18
18:50:32 UTC (rev 3008)
+++
trunk/engine/src/main/java/org/teiid/query/optimizer/relational/rules/RulePushAggregates.java 2011-03-19
01:18:44 UTC (rev 3009)
@@ -186,7 +186,7 @@
Map<ElementSymbol, List<Set<Constant>>> partitionInfo =
(Map<ElementSymbol,
List<Set<Constant>>>)child.getProperty(Info.PARTITION_INFO);
//check to see if any aggregate is dependent upon cardinality
- boolean cardinalityDependent =
RuleRemoveOptionalJoins.areAggregatesCardinalityDependent(aggregates);
+ boolean cardinalityDependent =
AggregateSymbol.areAggregatesCardinalityDependent(aggregates);
LinkedList<PlanNode> unionChildren = new LinkedList<PlanNode>();
findUnionChildren(unionChildren, cardinalityDependent, setOp);
@@ -747,7 +747,7 @@
if (originatingNode.getParent() == groupNode) {
//anything logically applied after the join and is
//dependent upon the cardinality prevents us from optimizing.
- if (aggs &&
RuleRemoveOptionalJoins.isCardinalityDependent((AggregateSymbol)aggregateSymbol)) {
+ if (aggs &&
((AggregateSymbol)aggregateSymbol).isCardinalityDependent()) {
return null;
}
continue;
Modified:
trunk/engine/src/main/java/org/teiid/query/optimizer/relational/rules/RuleRemoveOptionalJoins.java
===================================================================
---
trunk/engine/src/main/java/org/teiid/query/optimizer/relational/rules/RuleRemoveOptionalJoins.java 2011-03-18
18:50:32 UTC (rev 3008)
+++
trunk/engine/src/main/java/org/teiid/query/optimizer/relational/rules/RuleRemoveOptionalJoins.java 2011-03-19
01:18:44 UTC (rev 3009)
@@ -226,7 +226,7 @@
}
case NodeConstants.Types.GROUP: {
Set<AggregateSymbol> aggs = RulePushAggregates.collectAggregates(parent);
- return areAggregatesCardinalityDependent(aggs);
+ return AggregateSymbol.areAggregatesCardinalityDependent(aggs);
}
case NodeConstants.Types.TUPLE_LIMIT: {
if (!(parent.getProperty(NodeConstants.Info.MAX_TUPLE_LIMIT) instanceof Constant)
@@ -245,33 +245,7 @@
return true;
}
- static boolean areAggregatesCardinalityDependent(Set<AggregateSymbol> aggs) {
- for (AggregateSymbol aggregateSymbol : aggs) {
- if (isCardinalityDependent(aggregateSymbol)) {
- return true;
- }
- }
- return false;
- }
-
- static boolean isCardinalityDependent(AggregateSymbol aggregateSymbol) {
- if (aggregateSymbol.isDistinct()) {
- return false;
- }
- switch (aggregateSymbol.getAggregateFunction()) {
- case COUNT:
- case AVG:
- case STDDEV_POP:
- case STDDEV_SAMP:
- case VAR_POP:
- case VAR_SAMP:
- case SUM:
- return true;
- }
- return false;
- }
-
- public String toString() {
+ public String toString() {
return "RuleRemoveOptionalJoins"; //$NON-NLS-1$
}
Modified: trunk/engine/src/main/java/org/teiid/query/resolver/QueryResolver.java
===================================================================
--- trunk/engine/src/main/java/org/teiid/query/resolver/QueryResolver.java 2011-03-18
18:50:32 UTC (rev 3008)
+++ trunk/engine/src/main/java/org/teiid/query/resolver/QueryResolver.java 2011-03-19
01:18:44 UTC (rev 3009)
@@ -222,7 +222,6 @@
TempMetadataStore result = resolveCommand(currentCommand, metadata, false);
if (replaceBindings && symbolMap != null && !symbolMap.isEmpty()) {
ExpressionMappingVisitor emv = new ExpressionMappingVisitor(symbolMap);
- emv.setClone(true);
DeepPostOrderNavigator.doVisit(currentCommand, emv);
}
return result;
Modified: trunk/engine/src/main/java/org/teiid/query/rewriter/QueryRewriter.java
===================================================================
--- trunk/engine/src/main/java/org/teiid/query/rewriter/QueryRewriter.java 2011-03-18
18:50:32 UTC (rev 3008)
+++ trunk/engine/src/main/java/org/teiid/query/rewriter/QueryRewriter.java 2011-03-19
01:18:44 UTC (rev 3009)
@@ -55,6 +55,7 @@
import org.teiid.core.util.Assertion;
import org.teiid.core.util.TimestampWithTimezone;
import org.teiid.language.SQLConstants.NonReserved;
+import org.teiid.metadata.FunctionMethod.Determinism;
import org.teiid.query.QueryPlugin;
import org.teiid.query.eval.Evaluator;
import org.teiid.query.function.FunctionDescriptor;
@@ -62,6 +63,7 @@
import org.teiid.query.function.FunctionMethods;
import org.teiid.query.metadata.QueryMetadataInterface;
import org.teiid.query.metadata.TempMetadataAdapter;
+import org.teiid.query.metadata.TempMetadataID;
import org.teiid.query.metadata.TempMetadataStore;
import org.teiid.query.optimizer.relational.rules.NewCalculateCostUtil;
import org.teiid.query.optimizer.relational.rules.RuleMergeCriteria;
@@ -159,6 +161,8 @@
import org.teiid.query.sql.visitor.ElementCollectorVisitor;
import org.teiid.query.sql.visitor.EvaluatableVisitor;
import org.teiid.query.sql.visitor.ExpressionMappingVisitor;
+import org.teiid.query.sql.visitor.FunctionCollectorVisitor;
+import org.teiid.query.sql.visitor.ValueIteratorProviderCollectorVisitor;
import org.teiid.query.sql.visitor.EvaluatableVisitor.EvaluationLevel;
import org.teiid.query.util.CommandContext;
import org.teiid.query.validator.UpdateValidator.UpdateInfo;
@@ -685,6 +689,8 @@
continue;
}
if (plannedResult.query.getCorrelatedReferences() == null) {
+ //create the correlated refs if they exist
+ //there is a little bit of a design problem here that null usually means no refs.
ArrayList<Reference> correlatedReferences = new ArrayList<Reference>();
CorrelatedReferenceCollectorVisitor.collectReferences(plannedResult.query, groups,
correlatedReferences);
if (!correlatedReferences.isEmpty()) {
@@ -695,26 +701,30 @@
plannedResult.query.setCorrelatedReferences(map);
}
}
- if (!rmc.planQuery(groups, true, plannedResult)) {
+ boolean requiresDistinct = requiresDistinctRows(query);
+ if (!rmc.planQuery(groups, requiresDistinct, plannedResult)) {
continue;
}
- HashSet<GroupSymbol> keyPreservingGroups = new HashSet<GroupSymbol>();
- if (query.getFrom().getClauses().size() > 1) {
- continue;
+ if (requiresDistinct) {
+ //check for key preservation
+ HashSet<GroupSymbol> keyPreservingGroups = new HashSet<GroupSymbol>();
+ ResolverUtil.findKeyPreserved(query, keyPreservingGroups, metadata);
+ if (!NewCalculateCostUtil.usesKey(plannedResult.leftExpressions, keyPreservingGroups,
metadata, true)) {
+ //if not key perserved then the semi-join will not remain in tact
+ continue;
+ }
}
- ResolverUtil.findKeyPreserved(query, keyPreservingGroups, metadata);
- if (!NewCalculateCostUtil.usesKey(plannedResult.leftExpressions, keyPreservingGroups,
metadata, true)) {
- continue;
- }
crits.remove();
GroupSymbol viewName = RulePlaceAccess.recontextSymbol(new GroupSymbol("X"),
names); //$NON-NLS-1$
+ viewName.setName(viewName.getCanonicalName());
+ viewName.setDefinition(null);
Query q = createInlineViewQuery(viewName, plannedResult.query, metadata,
plannedResult.query.getSelect().getProjectedSymbols());
- Iterator iter = q.getSelect().getProjectedSymbols().iterator();
+ Iterator<SingleElementSymbol> iter =
q.getSelect().getProjectedSymbols().iterator();
HashMap<Expression, SingleElementSymbol> expressionMap = new
HashMap<Expression, SingleElementSymbol>();
- for (SingleElementSymbol symbol :
(List<SingleElementSymbol>)plannedResult.query.getSelect().getProjectedSymbols()) {
- expressionMap.put(SymbolMap.getExpression(symbol),
(SingleElementSymbol)iter.next());
+ for (SingleElementSymbol symbol :
plannedResult.query.getSelect().getProjectedSymbols()) {
+ expressionMap.put(SymbolMap.getExpression(symbol), iter.next());
}
for (int i = 0; i < plannedResult.leftExpressions.size(); i++) {
plannedResult.nonEquiJoinCriteria.add(new
CompareCriteria(SymbolMap.getExpression((Expression)plannedResult.leftExpressions.get(i)),
CompareCriteria.EQ, (Expression)plannedResult.rightExpressions.get(i)));
@@ -729,6 +739,32 @@
query.setCriteria(Criteria.combineCriteria(query.getCriteria(),
Criteria.combineCriteria(current)));
}
+ private boolean requiresDistinctRows(Query query) {
+ Set<AggregateSymbol> aggs = new HashSet<AggregateSymbol>();
+ aggs.addAll(AggregateSymbolCollectorVisitor.getAggregates(query.getSelect(), false));
+ aggs.addAll(AggregateSymbolCollectorVisitor.getAggregates(query.getHaving(), false));
+ if (!aggs.isEmpty() || query.getGroupBy() != null) {
+ if (!AggregateSymbol.areAggregatesCardinalityDependent(aggs)) {
+ return false;
+ }
+ } else if (query.getSelect().isDistinct()) {
+ for (SingleElementSymbol projectSymbol : query.getSelect().getProjectedSymbols()) {
+ Expression ex = SymbolMap.getExpression(projectSymbol);
+ Collection<Function> functions =
FunctionCollectorVisitor.getFunctions(ex, true, false);
+ for (Function function : functions) {
+ if ( function.getFunctionDescriptor().getDeterministic() ==
Determinism.NONDETERMINISTIC) {
+ return true;
+ }
+ }
+ if
(!ValueIteratorProviderCollectorVisitor.getValueIteratorProviders(ex).isEmpty()) {
+ return true;
+ }
+ }
+ return false;
+ }
+ return true;
+ }
+
/**
* Converts a group by with expressions into a group by with only element symbols and an
inline view
* @param query
@@ -792,10 +828,10 @@
} catch (TeiidException err) {
throw new TeiidRuntimeException(err);
}
- Iterator iter = outerQuery.getSelect().getProjectedSymbols().iterator();
+ Iterator<SingleElementSymbol> iter =
outerQuery.getSelect().getProjectedSymbols().iterator();
HashMap<Expression, SingleElementSymbol> expressionMap = new
HashMap<Expression, SingleElementSymbol>();
- for (SingleElementSymbol symbol :
(List<SingleElementSymbol>)query.getSelect().getProjectedSymbols()) {
- expressionMap.put(SymbolMap.getExpression(symbol),
(SingleElementSymbol)iter.next());
+ for (SingleElementSymbol symbol : query.getSelect().getProjectedSymbols()) {
+ expressionMap.put(SymbolMap.getExpression(symbol), iter.next());
}
ExpressionMappingVisitor.mapExpressions(groupBy, expressionMap);
outerQuery.setGroupBy(groupBy);
@@ -819,7 +855,7 @@
return false;
}
HashSet<Expression> selectExpressions = new HashSet<Expression>();
- for (SingleElementSymbol selectExpr :
(List<SingleElementSymbol>)query.getSelect().getProjectedSymbols()) {
+ for (SingleElementSymbol selectExpr : query.getSelect().getProjectedSymbols()) {
selectExpressions.add(SymbolMap.getExpression(selectExpr));
}
for (SingleElementSymbol groupByExpr :
(List<SingleElementSymbol>)groupBy.getSymbols()) {
@@ -873,7 +909,7 @@
return queryCommand;
}
Select select = queryCommand.getProjectedQuery().getSelect();
- final List projectedSymbols = select.getProjectedSymbols();
+ final List<SingleElementSymbol> projectedSymbols =
select.getProjectedSymbols();
LinkedList<OrderByItem> unrelatedItems = new
LinkedList<OrderByItem>();
@@ -904,10 +940,10 @@
try {
top = createInlineViewQuery(new GroupSymbol("X"), query, metadata,
select.getProjectedSymbols()); //$NON-NLS-1$
- Iterator iter = top.getSelect().getProjectedSymbols().iterator();
+ Iterator<SingleElementSymbol> iter =
top.getSelect().getProjectedSymbols().iterator();
HashMap<Expression, SingleElementSymbol> expressionMap = new
HashMap<Expression, SingleElementSymbol>();
- for (SingleElementSymbol symbol :
(List<SingleElementSymbol>)select.getProjectedSymbols()) {
- SingleElementSymbol ses = (SingleElementSymbol)iter.next();
+ for (SingleElementSymbol symbol : select.getProjectedSymbols()) {
+ SingleElementSymbol ses = iter.next();
expressionMap.put(SymbolMap.getExpression(symbol), ses);
expressionMap.put(new ElementSymbol(symbol.getName()), ses);
}
@@ -2739,8 +2775,8 @@
Query firstProject = ((QueryCommand)nested).getProjectedQuery();
makeSelectUnique(firstProject.getSelect(), false);
}
- store.addTempGroup(inlineGroup.getName(), nested.getProjectedSymbols());
- inlineGroup.setMetadataID(store.getTempGroupID(inlineGroup.getName()));
+ TempMetadataID gid = store.addTempGroup(inlineGroup.getName(),
nested.getProjectedSymbols());
+ inlineGroup.setMetadataID(gid);
List<Class<?>> actualTypes = new
ArrayList<Class<?>>(nested.getProjectedSymbols().size());
for (SingleElementSymbol ses : actualSymbols) {
Modified: trunk/engine/src/main/java/org/teiid/query/sql/lang/Select.java
===================================================================
--- trunk/engine/src/main/java/org/teiid/query/sql/lang/Select.java 2011-03-18 18:50:32
UTC (rev 3008)
+++ trunk/engine/src/main/java/org/teiid/query/sql/lang/Select.java 2011-03-19 01:18:44
UTC (rev 3009)
@@ -22,12 +22,22 @@
package org.teiid.query.sql.lang;
-import java.util.*;
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.Iterator;
+import java.util.List;
import org.teiid.core.util.EquivalenceUtil;
import org.teiid.core.util.HashCodeUtil;
-import org.teiid.query.sql.*;
-import org.teiid.query.sql.symbol.*;
+import org.teiid.query.sql.LanguageObject;
+import org.teiid.query.sql.LanguageVisitor;
+import org.teiid.query.sql.symbol.AllInGroupSymbol;
+import org.teiid.query.sql.symbol.AllSymbol;
+import org.teiid.query.sql.symbol.ElementSymbol;
+import org.teiid.query.sql.symbol.GroupSymbol;
+import org.teiid.query.sql.symbol.MultipleElementSymbol;
+import org.teiid.query.sql.symbol.SelectSymbol;
+import org.teiid.query.sql.symbol.SingleElementSymbol;
import org.teiid.query.sql.visitor.SQLStringVisitor;
@@ -200,15 +210,15 @@
* single column.
* @return Ordered list of SingleElementSymbol
*/
- public List getProjectedSymbols() {
- ArrayList projectedSymbols = new ArrayList();
+ public List<SingleElementSymbol> getProjectedSymbols() {
+ ArrayList<SingleElementSymbol> projectedSymbols = new
ArrayList<SingleElementSymbol>();
Iterator iter = symbols.iterator();
while(iter.hasNext()) {
SelectSymbol symbol = (SelectSymbol) iter.next();
if(symbol instanceof SingleElementSymbol) {
- projectedSymbols.add(symbol);
+ projectedSymbols.add((SingleElementSymbol)symbol);
} else {
- List multiSymbols = ((MultipleElementSymbol)symbol).getElementSymbols();
+ List<ElementSymbol> multiSymbols =
((MultipleElementSymbol)symbol).getElementSymbols();
if(multiSymbols != null) {
projectedSymbols.addAll(multiSymbols);
}
Modified: trunk/engine/src/main/java/org/teiid/query/sql/symbol/AggregateSymbol.java
===================================================================
--- trunk/engine/src/main/java/org/teiid/query/sql/symbol/AggregateSymbol.java 2011-03-18
18:50:32 UTC (rev 3008)
+++ trunk/engine/src/main/java/org/teiid/query/sql/symbol/AggregateSymbol.java 2011-03-19
01:18:44 UTC (rev 3009)
@@ -22,6 +22,7 @@
package org.teiid.query.sql.symbol;
+import java.util.Collection;
import java.util.HashMap;
import java.util.Map;
@@ -244,5 +245,31 @@
&& EquivalenceUtil.areEqual(this.getExpression(),
other.getExpression())
&& EquivalenceUtil.areEqual(this.getOrderBy(), other.getOrderBy());
}
+
+ public boolean isCardinalityDependent() {
+ if (isDistinct()) {
+ return false;
+ }
+ switch (getAggregateFunction()) {
+ case COUNT:
+ case AVG:
+ case STDDEV_POP:
+ case STDDEV_SAMP:
+ case VAR_POP:
+ case VAR_SAMP:
+ case SUM:
+ return true;
+ }
+ return false;
+ }
+ public static boolean
areAggregatesCardinalityDependent(Collection<AggregateSymbol> aggs) {
+ for (AggregateSymbol aggregateSymbol : aggs) {
+ if (aggregateSymbol.isCardinalityDependent()) {
+ return true;
+ }
+ }
+ return false;
+ }
+
}
Modified:
trunk/engine/src/main/java/org/teiid/query/sql/visitor/AggregateSymbolCollectorVisitor.java
===================================================================
---
trunk/engine/src/main/java/org/teiid/query/sql/visitor/AggregateSymbolCollectorVisitor.java 2011-03-18
18:50:32 UTC (rev 3008)
+++
trunk/engine/src/main/java/org/teiid/query/sql/visitor/AggregateSymbolCollectorVisitor.java 2011-03-19
01:18:44 UTC (rev 3009)
@@ -24,6 +24,7 @@
import java.util.ArrayList;
import java.util.Collection;
+import java.util.Collections;
import java.util.HashSet;
import org.teiid.query.sql.LanguageObject;
@@ -98,6 +99,9 @@
}
public static final Collection<AggregateSymbol> getAggregates(LanguageObject
obj, boolean removeDuplicates) {
+ if (obj == null) {
+ return Collections.emptyList();
+ }
Collection<AggregateSymbol> aggregates = null;
if (removeDuplicates) {
aggregates = new HashSet<AggregateSymbol>();
Modified:
trunk/engine/src/main/java/org/teiid/query/sql/visitor/ExpressionMappingVisitor.java
===================================================================
---
trunk/engine/src/main/java/org/teiid/query/sql/visitor/ExpressionMappingVisitor.java 2011-03-18
18:50:32 UTC (rev 3008)
+++
trunk/engine/src/main/java/org/teiid/query/sql/visitor/ExpressionMappingVisitor.java 2011-03-19
01:18:44 UTC (rev 3009)
@@ -77,7 +77,7 @@
public class ExpressionMappingVisitor extends LanguageVisitor {
private Map symbolMap;
- private boolean clone;
+ private boolean clone = true;
/**
* Constructor for ExpressionMappingVisitor.
Modified: trunk/engine/src/test/java/org/teiid/query/optimizer/TestSubqueryPushdown.java
===================================================================
---
trunk/engine/src/test/java/org/teiid/query/optimizer/TestSubqueryPushdown.java 2011-03-18
18:50:32 UTC (rev 3008)
+++
trunk/engine/src/test/java/org/teiid/query/optimizer/TestSubqueryPushdown.java 2011-03-19
01:18:44 UTC (rev 3009)
@@ -754,8 +754,26 @@
ProcessorPlan plan = helpPlan("Select e1, (select e1 FROM pm2.g1 where e1 =
'x') from pm1.g1", FakeMetadataFactory.example1Cached(), //$NON-NLS-1$
new String[] { "SELECT g_0.e1, (SELECT g_0.e1 FROM pm2.g1 AS g_0 WHERE
g_0.e1 = 'x') FROM pm1.g1 AS g_0" }, ComparisonMode.EXACT_COMMAND_STRING);
//$NON-NLS-1$
checkNodeTypes(plan, FULL_PUSHDOWN);
- }
+ }
+ @Test public void testSubqueryRewriteToJoinDistinct() throws Exception {
+ TestQueryRewriter.helpTestRewriteCommand("Select distinct e1 from pm1.g1 as
x where exists (select pm1.g1.e1 FROM pm1.g1 where e1 = x.e1)", "SELECT DISTINCT
e1 FROM pm1.g1 AS x, (SELECT pm1.g1.e1 FROM pm1.g1) AS X__1 WHERE x.e1 = X__1.e1",
FakeMetadataFactory.example1Cached());
+ }
+
+ /**
+ * Agg does not depend on cardinality
+ */
+ @Test public void testSubqueryRewriteToJoinGroupBy() throws Exception {
+ TestQueryRewriter.helpTestRewriteCommand("Select max(e1) from pm1.g1 as x
where exists (select pm1.g1.e1 FROM pm1.g1 where e1 = x.e1) group by e2",
"SELECT MAX(e1) FROM pm1.g1 AS x, (SELECT pm1.g1.e1 FROM pm1.g1) AS X__1 WHERE x.e1 =
X__1.e1 GROUP BY e2", FakeMetadataFactory.example1Cached());
+ }
+
+ /**
+ * Agg does depend on cardinality
+ */
+ @Test public void testSubqueryRewriteToJoinGroupBy1() throws Exception {
+ TestQueryRewriter.helpTestRewriteCommand("Select avg(e1) from pm1.g1 as x
where exists (select pm1.g1.e1 FROM pm1.g1 where e1 = x.e1) group by e2",
"SELECT AVG(e1) FROM pm1.g1 AS x WHERE EXISTS (SELECT pm1.g1.e1 FROM pm1.g1 WHERE e1
= x.e1 LIMIT 1) GROUP BY e2", FakeMetadataFactory.example1Cached());
+ }
+
@Test public void testSubqueryRewriteToJoin() throws Exception {
TestQueryRewriter.helpTestRewriteCommand("Select e1 from pm3.g1 where exists
(select pm1.g1.e1 FROM pm1.g1 where e1 = pm3.g1.e1)", "SELECT e1 FROM pm3.g1,
(SELECT pm1.g1.e1 FROM pm1.g1) AS X__1 WHERE pm3.g1.e1 = X__1.e1",
FakeMetadataFactory.example4());
}