Author: shawkins
Date: 2012-08-10 10:52:39 -0400 (Fri, 10 Aug 2012)
New Revision: 4307
Added:
trunk/api/src/main/java/org/teiid/language/Array.java
trunk/engine/src/main/java/org/teiid/query/sql/symbol/Array.java
trunk/engine/src/main/java/org/teiid/query/sql/symbol/ArrayValue.java
trunk/engine/src/test/java/org/teiid/query/sql/symbol/TestArray.java
Modified:
trunk/api/src/main/java/org/teiid/language/visitor/AbstractLanguageVisitor.java
trunk/api/src/main/java/org/teiid/language/visitor/LanguageObjectVisitor.java
trunk/api/src/main/java/org/teiid/language/visitor/SQLStringVisitor.java
trunk/api/src/main/java/org/teiid/translator/BaseDelegatingExecutionFactory.java
trunk/api/src/main/java/org/teiid/translator/ExecutionFactory.java
trunk/build/kits/jboss-as7/docs/teiid/teiid-releasenotes.html
trunk/common-core/src/main/java/org/teiid/core/types/DataTypeManager.java
trunk/connectors/translator-jdbc/src/main/java/org/teiid/translator/jdbc/h2/H2ExecutionFactory.java
trunk/connectors/translator-jdbc/src/main/java/org/teiid/translator/jdbc/oracle/OracleExecutionFactory.java
trunk/connectors/translator-jdbc/src/test/java/org/teiid/translator/jdbc/oracle/TestOracleTranslator.java
trunk/engine/src/main/java/org/teiid/dqp/internal/datamgr/CapabilitiesConverter.java
trunk/engine/src/main/java/org/teiid/dqp/internal/datamgr/LanguageBridgeFactory.java
trunk/engine/src/main/java/org/teiid/query/eval/Evaluator.java
trunk/engine/src/main/java/org/teiid/query/optimizer/capabilities/SourceCapabilities.java
trunk/engine/src/main/java/org/teiid/query/optimizer/relational/plantree/NodeConstants.java
trunk/engine/src/main/java/org/teiid/query/optimizer/relational/rules/NewCalculateCostUtil.java
trunk/engine/src/main/java/org/teiid/query/optimizer/relational/rules/RuleChooseDependent.java
trunk/engine/src/main/java/org/teiid/query/optimizer/relational/rules/RulePlanProcedures.java
trunk/engine/src/main/java/org/teiid/query/optimizer/relational/rules/RulePushSelectCriteria.java
trunk/engine/src/main/java/org/teiid/query/processor/relational/DependentCriteriaProcessor.java
trunk/engine/src/main/java/org/teiid/query/processor/relational/DependentProcedureCriteriaProcessor.java
trunk/engine/src/main/java/org/teiid/query/processor/relational/DependentValueSource.java
trunk/engine/src/main/java/org/teiid/query/processor/relational/TupleSourceValueIterator.java
trunk/engine/src/main/java/org/teiid/query/sql/LanguageVisitor.java
trunk/engine/src/main/java/org/teiid/query/sql/lang/DependentSetCriteria.java
trunk/engine/src/main/java/org/teiid/query/sql/lang/ExistsCriteria.java
trunk/engine/src/main/java/org/teiid/query/sql/lang/SubqueryCompareCriteria.java
trunk/engine/src/main/java/org/teiid/query/sql/lang/SubquerySetCriteria.java
trunk/engine/src/main/java/org/teiid/query/sql/navigator/PreOrPostOrderNavigator.java
trunk/engine/src/main/java/org/teiid/query/sql/symbol/ContextReference.java
trunk/engine/src/main/java/org/teiid/query/sql/symbol/Reference.java
trunk/engine/src/main/java/org/teiid/query/sql/symbol/ScalarSubquery.java
trunk/engine/src/main/java/org/teiid/query/sql/visitor/ExpressionMappingVisitor.java
trunk/engine/src/main/java/org/teiid/query/sql/visitor/SQLStringVisitor.java
trunk/engine/src/main/javacc/org/teiid/query/parser/SQLParser.jj
trunk/engine/src/test/java/org/teiid/query/optimizer/TestDependentJoins.java
trunk/engine/src/test/java/org/teiid/query/processor/TestDependentJoins.java
trunk/engine/src/test/java/org/teiid/query/sql/visitor/TestExpressionMappingVisitor.java
trunk/engine/src/test/java/org/teiid/query/sql/visitor/TestSQLStringVisitor.java
Log:
TEIID-2036 added support for array comparisons in multi-attribute dependent joins.
Added: trunk/api/src/main/java/org/teiid/language/Array.java
===================================================================
--- trunk/api/src/main/java/org/teiid/language/Array.java (rev 0)
+++ trunk/api/src/main/java/org/teiid/language/Array.java 2012-08-10 14:52:39 UTC (rev
4307)
@@ -0,0 +1,62 @@
+/*
+ * JBoss, Home of Professional Open Source.
+ * See the COPYRIGHT.txt file distributed with this work for information
+ * regarding copyright ownership. Some portions may be licensed
+ * to Red Hat, Inc. under one or more contributor license agreements.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+ * 02110-1301 USA.
+ */
+
+package org.teiid.language;
+
+import java.util.List;
+
+import org.teiid.language.visitor.LanguageObjectVisitor;
+import org.teiid.translator.TypeFacility;
+
+public class Array implements Expression {
+
+ private Class<?> baseType;
+ private List<Expression> expressions;
+
+ public Array(Class<?> baseType, List<Expression> expresssions) {
+ this.baseType = baseType;
+ this.expressions = expresssions;
+ }
+
+ @Override
+ public Class<?> getType() {
+ return TypeFacility.RUNTIME_TYPES.OBJECT;
+ }
+
+ @Override
+ public void acceptVisitor(LanguageObjectVisitor visitor) {
+ visitor.visit(this);
+ }
+
+ public Class<?> getBaseType() {
+ return baseType;
+ }
+
+ public void setBaseType(Class<?> baseType) {
+ this.baseType = baseType;
+ }
+
+ public List<Expression> getExpressions() {
+ return expressions;
+ }
+
+}
Property changes on: trunk/api/src/main/java/org/teiid/language/Array.java
___________________________________________________________________
Added: svn:mime-type
+ text/plain
Modified: trunk/api/src/main/java/org/teiid/language/visitor/AbstractLanguageVisitor.java
===================================================================
---
trunk/api/src/main/java/org/teiid/language/visitor/AbstractLanguageVisitor.java 2012-08-07
23:34:56 UTC (rev 4306)
+++
trunk/api/src/main/java/org/teiid/language/visitor/AbstractLanguageVisitor.java 2012-08-10
14:52:39 UTC (rev 4307)
@@ -121,4 +121,6 @@
public void visit(With obj) {}
@Override
public void visit(WithItem obj) {}
+ @Override
+ public void visit(Array array) {}
}
Modified: trunk/api/src/main/java/org/teiid/language/visitor/LanguageObjectVisitor.java
===================================================================
---
trunk/api/src/main/java/org/teiid/language/visitor/LanguageObjectVisitor.java 2012-08-07
23:34:56 UTC (rev 4306)
+++
trunk/api/src/main/java/org/teiid/language/visitor/LanguageObjectVisitor.java 2012-08-10
14:52:39 UTC (rev 4307)
@@ -66,4 +66,5 @@
public void visit(WindowFunction windowFunction);
public void visit(WindowSpecification windowSpecification);
public void visit(Parameter obj);
+ public void visit(Array array);
}
Modified: trunk/api/src/main/java/org/teiid/language/visitor/SQLStringVisitor.java
===================================================================
--- trunk/api/src/main/java/org/teiid/language/visitor/SQLStringVisitor.java 2012-08-07
23:34:56 UTC (rev 4306)
+++ trunk/api/src/main/java/org/teiid/language/visitor/SQLStringVisitor.java 2012-08-10
14:52:39 UTC (rev 4307)
@@ -160,9 +160,13 @@
buffer.append(Tokens.SPACE);
buffer.append(obj.getOperator());
buffer.append(Tokens.SPACE);
- append(obj.getRightExpression());
+ appendRightComparison(obj);
}
+ protected void appendRightComparison(Comparison obj) {
+ append(obj.getRightExpression());
+ }
+
public void visit(AndOr obj) {
String opString = obj.getOperator().toString();
@@ -942,6 +946,13 @@
}
buffer.append(Tokens.RPAREN);
}
+
+ @Override
+ public void visit(Array array) {
+ buffer.append(Tokens.LPAREN);
+ append(array.getExpressions());
+ buffer.append(Tokens.RPAREN);
+ }
/**
* Gets the SQL string representation for a given LanguageObject.
Modified:
trunk/api/src/main/java/org/teiid/translator/BaseDelegatingExecutionFactory.java
===================================================================
---
trunk/api/src/main/java/org/teiid/translator/BaseDelegatingExecutionFactory.java 2012-08-07
23:34:56 UTC (rev 4306)
+++
trunk/api/src/main/java/org/teiid/translator/BaseDelegatingExecutionFactory.java 2012-08-10
14:52:39 UTC (rev 4307)
@@ -447,4 +447,8 @@
public boolean isForkable() {
return delegate.isForkable();
}
+ @Override
+ public boolean supportsArrayType() {
+ return delegate.supportsArrayType();
+ }
}
Modified: trunk/api/src/main/java/org/teiid/translator/ExecutionFactory.java
===================================================================
--- trunk/api/src/main/java/org/teiid/translator/ExecutionFactory.java 2012-08-07 23:34:56
UTC (rev 4306)
+++ trunk/api/src/main/java/org/teiid/translator/ExecutionFactory.java 2012-08-10 14:52:39
UTC (rev 4307)
@@ -1027,5 +1027,13 @@
public boolean isForkable() {
return true;
}
+
+ /**
+ * The engine currently uses array types for dependent joins.
+ * @return true if an array type is supported.
+ */
+ public boolean supportsArrayType() {
+ return false;
+ }
}
Modified: trunk/build/kits/jboss-as7/docs/teiid/teiid-releasenotes.html
===================================================================
--- trunk/build/kits/jboss-as7/docs/teiid/teiid-releasenotes.html 2012-08-07 23:34:56 UTC
(rev 4306)
+++ trunk/build/kits/jboss-as7/docs/teiid/teiid-releasenotes.html 2012-08-10 14:52:39 UTC
(rev 4307)
@@ -34,6 +34,7 @@
<LI>TEIID-2077 <B>Result reuse</B> - the engine will automatically
detect if the same source query is used multiple times in a plan and reuse the result
rather than issuing another query.
<LI>TEIID-2113 <B>Misc parser improvements</B> - the parser will now
accept the LATERAL keyword for defining a LATERAL join (previously we just used the TABLE
keyword), unary negation is now supported e.g. -col1, the FOR keyword is optional for
TEXTAGG,
and the BNF documentation was dramatically improved.
+ <LI>TEIID-2036 <B>Dependent Join Array Comparison</B> - platforms
supporting array comparisons can have multi-attribute dependent joins pushed down as array
comparisons. Oracle and H2 translators are already marked as supporting array types.
</UL>
<h2><a name="Compatibility">Compatibility
Issues</a></h2>
Modified: trunk/common-core/src/main/java/org/teiid/core/types/DataTypeManager.java
===================================================================
--- trunk/common-core/src/main/java/org/teiid/core/types/DataTypeManager.java 2012-08-07
23:34:56 UTC (rev 4306)
+++ trunk/common-core/src/main/java/org/teiid/core/types/DataTypeManager.java 2012-08-10
14:52:39 UTC (rev 4307)
@@ -901,7 +901,8 @@
}
return !(type == DataTypeManager.DefaultDataClasses.BIG_DECIMAL
|| type == DataTypeManager.DefaultDataClasses.BLOB
- || type == DataTypeManager.DefaultDataClasses.CLOB);
+ || type == DataTypeManager.DefaultDataClasses.CLOB
+ || type == DataTypeManager.DefaultDataClasses.OBJECT);
}
}
Modified:
trunk/connectors/translator-jdbc/src/main/java/org/teiid/translator/jdbc/h2/H2ExecutionFactory.java
===================================================================
---
trunk/connectors/translator-jdbc/src/main/java/org/teiid/translator/jdbc/h2/H2ExecutionFactory.java 2012-08-07
23:34:56 UTC (rev 4306)
+++
trunk/connectors/translator-jdbc/src/main/java/org/teiid/translator/jdbc/h2/H2ExecutionFactory.java 2012-08-10
14:52:39 UTC (rev 4307)
@@ -210,4 +210,9 @@
public String getLikeRegexString() {
return "REGEXP"; //$NON-NLS-1$
}
+
+ @Override
+ public boolean supportsArrayType() {
+ return true;
+ }
}
Modified:
trunk/connectors/translator-jdbc/src/main/java/org/teiid/translator/jdbc/oracle/OracleExecutionFactory.java
===================================================================
---
trunk/connectors/translator-jdbc/src/main/java/org/teiid/translator/jdbc/oracle/OracleExecutionFactory.java 2012-08-07
23:34:56 UTC (rev 4306)
+++
trunk/connectors/translator-jdbc/src/main/java/org/teiid/translator/jdbc/oracle/OracleExecutionFactory.java 2012-08-10
14:52:39 UTC (rev 4307)
@@ -506,6 +506,18 @@
}
super.visit(obj);
}
+
+ @Override
+ protected void appendRightComparison(Comparison obj) {
+ if (obj.getRightExpression() instanceof Array) {
+ //oracle needs rhs arrays nested in extra parens
+ buffer.append(SQLConstants.Tokens.LPAREN);
+ super.appendRightComparison(obj);
+ buffer.append(SQLConstants.Tokens.RPAREN);
+ } else {
+ super.appendRightComparison(obj);
+ }
+ }
private boolean isChar(Expression obj) {
if (!(obj instanceof ColumnReference)) {
@@ -738,4 +750,9 @@
return OracleFormatFunctionModifier.supportsLiteral(literal);
}
+ @Override
+ public boolean supportsArrayType() {
+ return true;
+ }
+
}
Modified:
trunk/connectors/translator-jdbc/src/test/java/org/teiid/translator/jdbc/oracle/TestOracleTranslator.java
===================================================================
---
trunk/connectors/translator-jdbc/src/test/java/org/teiid/translator/jdbc/oracle/TestOracleTranslator.java 2012-08-07
23:34:56 UTC (rev 4306)
+++
trunk/connectors/translator-jdbc/src/test/java/org/teiid/translator/jdbc/oracle/TestOracleTranslator.java 2012-08-10
14:52:39 UTC (rev 4307)
@@ -41,6 +41,7 @@
import org.teiid.core.util.UnitTestUtil;
import org.teiid.dqp.internal.datamgr.ExecutionContextImpl;
import org.teiid.dqp.internal.datamgr.FakeExecutionContextImpl;
+import org.teiid.language.Array;
import org.teiid.language.Command;
import org.teiid.language.Comparison;
import org.teiid.language.Literal;
@@ -59,6 +60,7 @@
import org.teiid.query.unittest.RealMetadataFactory;
import org.teiid.translator.ExecutionContext;
import org.teiid.translator.TranslatorException;
+import org.teiid.translator.TypeFacility;
import org.teiid.translator.jdbc.JDBCProcedureExecution;
import org.teiid.translator.jdbc.JDBCQueryExecution;
import org.teiid.translator.jdbc.SQLConversionVisitor;
@@ -955,5 +957,18 @@
Command obj = commandBuilder.getCommand(input, true, true);
TranslationHelper.helpTestVisitor(output, TRANSLATOR, obj);
}
+
+ @Test public void testArrayComparison() throws Exception {
+ String input = "select intkey from bqt1.smalla where intkey = 5";
//$NON-NLS-1$
+ String output = "SELECT g_0.IntKey FROM SmallA g_0 WHERE (g_0.IntKey,
g_0.IntKey) = ((5, 2))"; //$NON-NLS-1$
+
+ CommandBuilder commandBuilder = new
CommandBuilder(RealMetadataFactory.exampleBQTCached());
+ Select obj = (Select)commandBuilder.getCommand(input, true, true);
+ Comparison comp = (Comparison)obj.getWhere();
+ //modify to an array comparison, since there is not yet parsing support
+ comp.setLeftExpression(new Array(comp.getLeftExpression().getType(),
Arrays.asList(comp.getLeftExpression(), comp.getLeftExpression())));
+ comp.setRightExpression(new Array(comp.getLeftExpression().getType(),
Arrays.asList(comp.getRightExpression(), new Literal(2,
TypeFacility.RUNTIME_TYPES.INTEGER))));
+ TranslationHelper.helpTestVisitor(output, TRANSLATOR, obj);
+ }
}
Modified:
trunk/engine/src/main/java/org/teiid/dqp/internal/datamgr/CapabilitiesConverter.java
===================================================================
---
trunk/engine/src/main/java/org/teiid/dqp/internal/datamgr/CapabilitiesConverter.java 2012-08-07
23:34:56 UTC (rev 4306)
+++
trunk/engine/src/main/java/org/teiid/dqp/internal/datamgr/CapabilitiesConverter.java 2012-08-10
14:52:39 UTC (rev 4307)
@@ -113,6 +113,7 @@
tgtCaps.setCapabilitySupport(Capability.CRITERIA_ONLY_LITERAL_COMPARE,
srcCaps.supportsOnlyLiteralComparison());
tgtCaps.setCapabilitySupport(Capability.DEPENDENT_JOIN,
srcCaps.supportsDependentJoins());
tgtCaps.setCapabilitySupport(Capability.CRITERIA_ON_SUBQUERY,
srcCaps.supportsSubqueryInOn());
+ tgtCaps.setCapabilitySupport(Capability.ARRAY_TYPE,
srcCaps.supportsArrayType());
List<String> functions = srcCaps.getSupportedFunctions();
if(functions != null && functions.size() > 0) {
Modified:
trunk/engine/src/main/java/org/teiid/dqp/internal/datamgr/LanguageBridgeFactory.java
===================================================================
---
trunk/engine/src/main/java/org/teiid/dqp/internal/datamgr/LanguageBridgeFactory.java 2012-08-07
23:34:56 UTC (rev 4306)
+++
trunk/engine/src/main/java/org/teiid/dqp/internal/datamgr/LanguageBridgeFactory.java 2012-08-10
14:52:39 UTC (rev 4307)
@@ -32,6 +32,7 @@
import org.teiid.core.TeiidComponentException;
import org.teiid.core.TeiidProcessingException;
import org.teiid.core.TeiidRuntimeException;
+import org.teiid.core.types.DataTypeManager;
import org.teiid.language.*;
import org.teiid.language.DerivedColumn;
import org.teiid.language.Select;
@@ -56,6 +57,7 @@
import org.teiid.query.sql.lang.SetQuery;
import org.teiid.query.sql.lang.Update;
import org.teiid.query.sql.symbol.*;
+import org.teiid.query.sql.symbol.Array;
import org.teiid.query.sql.symbol.Expression;
import org.teiid.query.sql.symbol.Function;
import org.teiid.query.sql.symbol.ScalarSubquery;
@@ -416,10 +418,7 @@
Condition translate(SetCriteria criteria) {
Collection expressions = criteria.getValues();
- List<org.teiid.language.Expression> translatedExpressions = new
ArrayList<org.teiid.language.Expression>();
- for (Iterator i = expressions.iterator(); i.hasNext();) {
- translatedExpressions.add(translate((Expression)i.next()));
- }
+ List<org.teiid.language.Expression> translatedExpressions =
translateExpressionList(expressions);
org.teiid.language.Expression expr = translate(criteria.getExpression());
if (convertIn) {
Condition condition = null;
@@ -545,10 +544,16 @@
return translate((Criteria)expr);
} else if (expr instanceof WindowFunction) {
return translate((WindowFunction)expr);
+ } else if (expr instanceof Array) {
+ return translate((Array)expr);
}
throw new AssertionError();
}
+ org.teiid.language.Array translate(Array array) {
+ return new org.teiid.language.Array(array.getBaseType(),
translateExpressionList(array.getExpressions()));
+ }
+
org.teiid.language.WindowFunction translate(WindowFunction windowFunction) {
org.teiid.language.WindowFunction result = new org.teiid.language.WindowFunction();
result.setFunction(translate(windowFunction.getFunction()));
@@ -556,17 +561,23 @@
ws.setOrderBy(translate(windowFunction.getWindowSpecification().getOrderBy(),
false));
List<Expression> partition =
windowFunction.getWindowSpecification().getPartition();
if (partition != null) {
- ArrayList<org.teiid.language.Expression> partitionList = new
ArrayList<org.teiid.language.Expression>(partition.size());
- for (Expression ex : partition) {
- partitionList.add(translate(ex));
- }
+ ArrayList<org.teiid.language.Expression> partitionList =
translateExpressionList(partition);
ws.setPartition(partitionList);
}
result.setWindowSpecification(ws);
return result;
}
+
+ private ArrayList<org.teiid.language.Expression> translateExpressionList(
+ Collection<? extends Expression> list) {
+ ArrayList<org.teiid.language.Expression> result = new
ArrayList<org.teiid.language.Expression>(list.size());
+ for (Expression ex : list) {
+ result.add(translate(ex));
+ }
+ return result;
+ }
- org.teiid.language.Expression translate(Constant constant) {
+ org.teiid.language.Expression translate(Constant constant) {
if (constant.isMultiValued()) {
Parameter result = new Parameter();
result.setType(constant.getType());
@@ -575,6 +586,33 @@
result.setValueIndex(valueIndex++);
return result;
}
+ if (constant.getValue() instanceof ArrayValue) {
+ //TODO: we could check if there is a common base type (also needs to be in the
dependent logic)
+ // and expand binding options in the translators
+
+ //we currently support the notion of a mixed type array, since we consider object a
common base type
+ //that will not work for all sources, so instead of treating this a single array
(as commented out below),
+ //we just turn it into an array of parameters
+ //Literal result = new Literal(av.getValues(), org.teiid.language.Array.class);
+ //result.setBindEligible(constant.isBindEligible());
+ //return result;
+
+ ArrayValue av = (ArrayValue)constant.getValue();
+ List<Constant> vals = new ArrayList<Constant>();
+ Class<?> baseType = null;
+ for (Object o : av.getValues()) {
+ Constant c = new Constant(o);
+ c.setBindEligible(constant.isBindEligible());
+ vals.add(c);
+ if (baseType == null) {
+ baseType = c.getType();
+ } else if (!baseType.equals(c.getType())) {
+ baseType = DataTypeManager.DefaultDataClasses.OBJECT;
+ }
+ }
+ return new org.teiid.language.Array(baseType, translateExpressionList(vals));
+
+ }
Literal result = new Literal(constant.getValue(), constant.getType());
result.setBindEligible(constant.isBindEligible());
return result;
Modified: trunk/engine/src/main/java/org/teiid/query/eval/Evaluator.java
===================================================================
--- trunk/engine/src/main/java/org/teiid/query/eval/Evaluator.java 2012-08-07 23:34:56 UTC
(rev 4306)
+++ trunk/engine/src/main/java/org/teiid/query/eval/Evaluator.java 2012-08-10 14:52:39 UTC
(rev 4307)
@@ -398,7 +398,7 @@
}
valueIter = new CollectionValueIterator(((SetCriteria)criteria).getValues());
} else if (criteria instanceof DependentSetCriteria){
- ContextReference ref = (ContextReference)criteria;
+ DependentSetCriteria ref = (DependentSetCriteria)criteria;
VariableContext vc = getContext(criteria).getVariableContext();
ValueIteratorSource vis =
(ValueIteratorSource)vc.getGlobalValue(ref.getContextSymbol());
Set<Object> values;
@@ -639,6 +639,17 @@
return evaluateQueryString(tuple, (QueryString)expression);
} else if (expression instanceof XMLParse){
return evaluateXMLParse(tuple, (XMLParse)expression);
+ } else if (expression instanceof Array) {
+ Array array = (Array)expression;
+ List<Expression> exprs = array.getExpressions();
+ Object[] result = new Object[exprs.size()];
+ for (int i = 0; i < exprs.size(); i++) {
+ result[i] = internalEvaluate(exprs.get(i), tuple);
+ if (result[i] == null) {
+ return null; //TODO: this is a hack
+ }
+ }
+ return new ArrayValue(result);
} else {
throw new TeiidComponentException(QueryPlugin.Event.TEIID30329,
QueryPlugin.Util.gs(QueryPlugin.Event.TEIID30329, expression.getClass().getName()));
}
Modified:
trunk/engine/src/main/java/org/teiid/query/optimizer/capabilities/SourceCapabilities.java
===================================================================
---
trunk/engine/src/main/java/org/teiid/query/optimizer/capabilities/SourceCapabilities.java 2012-08-07
23:34:56 UTC (rev 4306)
+++
trunk/engine/src/main/java/org/teiid/query/optimizer/capabilities/SourceCapabilities.java 2012-08-10
14:52:39 UTC (rev 4307)
@@ -331,7 +331,8 @@
WINDOW_FUNCTION_DISTINCT_AGGREGATES("WindowDistinctAggregates"),
//$NON-NLS-1$
QUERY_ONLY_SINGLE_TABLE_GROUP_BY,
ONLY_FORMAT_LITERALS,
- CRITERIA_ON_SUBQUERY;
+ CRITERIA_ON_SUBQUERY,
+ ARRAY_TYPE;
private final String toString;
Modified:
trunk/engine/src/main/java/org/teiid/query/optimizer/relational/plantree/NodeConstants.java
===================================================================
---
trunk/engine/src/main/java/org/teiid/query/optimizer/relational/plantree/NodeConstants.java 2012-08-07
23:34:56 UTC (rev 4306)
+++
trunk/engine/src/main/java/org/teiid/query/optimizer/relational/plantree/NodeConstants.java 2012-08-10
14:52:39 UTC (rev 4307)
@@ -143,7 +143,6 @@
EST_CARDINALITY, // Float represents the estimated cardinality (amount of
rows) produced by this node
EST_COL_STATS,
EST_SELECTIVITY, // Float that represents the selectivity of a criteria node
- MAX_NDV, // The max NDV before the dependent join will be aborted
// Tuple limit and offset
MAX_TUPLE_LIMIT, // Expression that evaluates to the max number of tuples
generated
Modified:
trunk/engine/src/main/java/org/teiid/query/optimizer/relational/rules/NewCalculateCostUtil.java
===================================================================
---
trunk/engine/src/main/java/org/teiid/query/optimizer/relational/rules/NewCalculateCostUtil.java 2012-08-07
23:34:56 UTC (rev 4306)
+++
trunk/engine/src/main/java/org/teiid/query/optimizer/relational/rules/NewCalculateCostUtil.java 2012-08-10
14:52:39 UTC (rev 4307)
@@ -1324,7 +1324,7 @@
break;
}
case NodeConstants.Types.GROUP: {
- if (rpsc.pushAcrossGroupBy(sourceNode, critNode, metadata, false)) {
+ if (rpsc.pushAcrossGroupBy(sourceNode, critNode, metadata, false, capFinder)) {
critNodes.add(critNode);
initialTargets.add(sourceNode.getFirstChild());
}
Modified:
trunk/engine/src/main/java/org/teiid/query/optimizer/relational/rules/RuleChooseDependent.java
===================================================================
---
trunk/engine/src/main/java/org/teiid/query/optimizer/relational/rules/RuleChooseDependent.java 2012-08-07
23:34:56 UTC (rev 4306)
+++
trunk/engine/src/main/java/org/teiid/query/optimizer/relational/rules/RuleChooseDependent.java 2012-08-10
14:52:39 UTC (rev 4307)
@@ -25,13 +25,13 @@
import java.util.ArrayList;
import java.util.Collection;
import java.util.Iterator;
-import java.util.LinkedList;
import java.util.List;
import java.util.concurrent.atomic.AtomicInteger;
import org.teiid.api.exception.query.QueryMetadataException;
import org.teiid.api.exception.query.QueryPlannerException;
import org.teiid.core.TeiidComponentException;
+import org.teiid.core.types.DataTypeManager.DefaultDataClasses;
import org.teiid.query.analysis.AnalysisRecord;
import org.teiid.query.metadata.QueryMetadataInterface;
import org.teiid.query.optimizer.capabilities.CapabilitiesFinder;
@@ -44,6 +44,8 @@
import
org.teiid.query.optimizer.relational.rules.NewCalculateCostUtil.DependentCostAnalysis;
import org.teiid.query.sql.lang.DependentSetCriteria;
import org.teiid.query.sql.lang.JoinType;
+import org.teiid.query.sql.lang.DependentSetCriteria.AttributeComparison;
+import org.teiid.query.sql.symbol.Array;
import org.teiid.query.sql.symbol.ElementSymbol;
import org.teiid.query.sql.symbol.Expression;
import org.teiid.query.sql.util.SymbolMap;
@@ -274,14 +276,9 @@
// Create DependentValueSource and set on the independent side as this will feed
the values
joinNode.setProperty(NodeConstants.Info.DEPENDENT_VALUE_SOURCE, id);
- List<PlanNode> crits = getDependentCriteriaNodes(id,
independentExpressions, dependentExpressions,
isLeft?joinNode.getLastChild():joinNode.getFirstChild(), metadata, dca);
+ PlanNode crit = getDependentCriteriaNode(id, independentExpressions,
dependentExpressions, isLeft?joinNode.getLastChild():joinNode.getFirstChild(), metadata,
dca);
- PlanNode newRoot = sourceNode;
-
- for (PlanNode crit : crits) {
- newRoot.addAsParent(crit);
- newRoot = crit;
- }
+ sourceNode.addAsParent(crit);
if (isLeft) {
JoinUtil.swapJoinChildren(joinNode);
@@ -297,47 +294,92 @@
* @throws QueryMetadataException
* @since 4.3
*/
- private List<PlanNode> getDependentCriteriaNodes(String id, List
independentExpressions,
- List dependentExpressions, PlanNode indNode,
QueryMetadataInterface metadata, DependentCostAnalysis dca) throws QueryMetadataException,
TeiidComponentException {
+ private PlanNode getDependentCriteriaNode(String id, List<Expression>
independentExpressions,
+ List<Expression> dependentExpressions,
PlanNode indNode, QueryMetadataInterface metadata, DependentCostAnalysis dca) throws
QueryMetadataException, TeiidComponentException {
- List<PlanNode> result = new LinkedList<PlanNode>();
-
Float cardinality = null;
+ List<DependentSetCriteria.AttributeComparison> expressions = new
ArrayList<DependentSetCriteria.AttributeComparison>(dependentExpressions.size());
+
for (int i = 0; i < dependentExpressions.size(); i++) {
- Expression depExpr = (Expression) dependentExpressions.get(i);
- Expression indepExpr = (Expression) independentExpressions.get(i);
- DependentSetCriteria crit = new
DependentSetCriteria(SymbolMap.getExpression(depExpr), id);
- float ndv = NewCalculateCostUtil.UNKNOWN_VALUE;
- Float maxNdv = null;
+ Expression depExpr = dependentExpressions.get(i);
+ Expression indExpr = independentExpressions.get(i);
+
+ DependentSetCriteria.AttributeComparison comp = new
DependentSetCriteria.AttributeComparison();
if (dca != null && dca.expectedNdv[i] != null) {
if (dca.expectedNdv[i] > 4*dca.maxNdv[i]) {
continue; //not necessary to use
}
- ndv = dca.expectedNdv[i];
- maxNdv = dca.maxNdv[i];
- crit.setMaxNdv(dca.maxNdv[i]);
+ comp.ndv = dca.expectedNdv[i];
+ comp.maxNdv = dca.maxNdv[i];
} else {
- Collection<ElementSymbol> elems =
ElementCollectorVisitor.getElements(indepExpr, true);
- if (cardinality == null) {
- cardinality = NewCalculateCostUtil.computeCostForTree(indNode, metadata);
- }
- ndv = NewCalculateCostUtil.getNDVEstimate(indNode, metadata, cardinality,
elems, true);
+ Collection<ElementSymbol> elems =
ElementCollectorVisitor.getElements(indExpr, true);
+ if (cardinality == null) {
+ cardinality = NewCalculateCostUtil.computeCostForTree(indNode,
metadata);
+ }
+ comp.ndv = NewCalculateCostUtil.getNDVEstimate(indNode, metadata,
cardinality, elems, true);
}
- crit.setNdv(ndv);
- crit.setValueExpression(indepExpr);
-
- PlanNode selectNode = RelationalPlanner.createSelectNode(crit, false);
-
- selectNode.setProperty(NodeConstants.Info.IS_DEPENDENT_SET, Boolean.TRUE);
- if (maxNdv != null) {
- selectNode.setProperty(NodeConstants.Info.MAX_NDV, maxNdv);
- }
- result.add(selectNode);
+ comp.ind = indExpr;
+ comp.dep = SymbolMap.getExpression(depExpr);
+ expressions.add(comp);
}
+
+ return createDependentSetNode(id, expressions);
+
+ }
+
+ static PlanNode createDependentSetNode(String id,
List<DependentSetCriteria.AttributeComparison> expressions) {
+ DependentSetCriteria crit = createDependentSetCriteria(id, expressions);
+
+ PlanNode selectNode = RelationalPlanner.createSelectNode(crit, false);
- return result;
- }
+ selectNode.setProperty(NodeConstants.Info.IS_DEPENDENT_SET, Boolean.TRUE);
+ return selectNode;
+ }
+
+ static DependentSetCriteria createDependentSetCriteria(String id,
List<DependentSetCriteria.AttributeComparison> expressions) {
+ if (expressions.isEmpty()) {
+ return null;
+ }
+
+ Expression indEx = null;
+ Expression depEx = null;
+ float maxNdv = NewCalculateCostUtil.UNKNOWN_VALUE;
+ float ndv = NewCalculateCostUtil.UNKNOWN_VALUE;
+ if (expressions.size() == 1) {
+ AttributeComparison attributeComparison = expressions.get(0);
+ indEx = attributeComparison.ind;
+ depEx = attributeComparison.dep;
+ maxNdv = attributeComparison.maxNdv;
+ ndv = attributeComparison.ndv;
+ } else {
+ List<Expression> indExprs = new
ArrayList<Expression>(expressions.size());
+ List<Expression> depExprs = new
ArrayList<Expression>(expressions.size());
+ boolean unknown = false;
+ for (DependentSetCriteria.AttributeComparison comp : expressions) {
+ indExprs.add(comp.ind);
+ depExprs.add(comp.dep);
+ if (comp.ndv == NewCalculateCostUtil.UNKNOWN_VALUE) {
+ ndv = NewCalculateCostUtil.UNKNOWN_VALUE;
+ maxNdv = NewCalculateCostUtil.UNKNOWN_VALUE;
+ unknown = true;
+ } else if (!unknown) {
+ ndv = Math.max(ndv, comp.ndv);
+ maxNdv = Math.max(maxNdv, comp.maxNdv);
+ }
+ }
+ //TODO: detect a base type
+ indEx = new Array(DefaultDataClasses.OBJECT, indExprs);
+ depEx = new Array(DefaultDataClasses.OBJECT, depExprs);
+ }
+
+ DependentSetCriteria crit = new DependentSetCriteria(depEx, id);
+ crit.setValueExpression(indEx);
+ crit.setAttributes(expressions);
+ crit.setMaxNdv(maxNdv);
+ crit.setNdv(ndv);
+ return crit;
+ }
public String toString() {
return "ChooseDependent"; //$NON-NLS-1$
Modified:
trunk/engine/src/main/java/org/teiid/query/optimizer/relational/rules/RulePlanProcedures.java
===================================================================
---
trunk/engine/src/main/java/org/teiid/query/optimizer/relational/rules/RulePlanProcedures.java 2012-08-07
23:34:56 UTC (rev 4306)
+++
trunk/engine/src/main/java/org/teiid/query/optimizer/relational/rules/RulePlanProcedures.java 2012-08-10
14:52:39 UTC (rev 4307)
@@ -50,6 +50,7 @@
import org.teiid.query.sql.lang.SPParameter;
import org.teiid.query.sql.lang.SetCriteria;
import org.teiid.query.sql.lang.StoredProcedure;
+import org.teiid.query.sql.lang.DependentSetCriteria.AttributeComparison;
import org.teiid.query.sql.symbol.ElementSymbol;
import org.teiid.query.sql.symbol.Expression;
import org.teiid.query.sql.symbol.Reference;
@@ -185,9 +186,23 @@
}
public void visit(DependentSetCriteria obj) {
- if (!obj.isNegated() && checkForInput(obj.getExpression()))
{
- addInputNode((Reference)obj.getExpression());
+ if (obj.isNegated()) {
+ return; //just a sanity check
}
+ if (obj.hasMultipleAttributes()) {
+ for (AttributeComparison comp : obj.getAttributes()) {
+ if (!checkForInput(comp.dep)) {
+ return;
+ }
+ }
+ for (AttributeComparison comp : obj.getAttributes()) {
+ params.add(((Reference)comp.dep).getExpression());
+ }
+ conjuncts.add(crit);
+ NodeEditor.removeChildNode(currentNode.getParent(),
currentNode);
+ } else if (checkForInput(obj.getExpression())) {
+ addInputNode((Reference)obj.getExpression());
+ }
}
boolean checkForInput(Expression expr) {
@@ -218,7 +233,9 @@
}
};
- crit.acceptVisitor(visitor);
+ for (Criteria conjunct : Criteria.separateCriteriaByAnd(crit)) {
+ conjunct.acceptVisitor(visitor);
+ }
}
}
Modified:
trunk/engine/src/main/java/org/teiid/query/optimizer/relational/rules/RulePushSelectCriteria.java
===================================================================
---
trunk/engine/src/main/java/org/teiid/query/optimizer/relational/rules/RulePushSelectCriteria.java 2012-08-07
23:34:56 UTC (rev 4306)
+++
trunk/engine/src/main/java/org/teiid/query/optimizer/relational/rules/RulePushSelectCriteria.java 2012-08-10
14:52:39 UTC (rev 4307)
@@ -22,6 +22,8 @@
package org.teiid.query.optimizer.relational.rules;
+import java.util.ArrayList;
+import java.util.Arrays;
import java.util.Collection;
import java.util.Collections;
import java.util.HashSet;
@@ -37,6 +39,7 @@
import org.teiid.query.analysis.AnalysisRecord;
import org.teiid.query.metadata.QueryMetadataInterface;
import org.teiid.query.optimizer.capabilities.CapabilitiesFinder;
+import org.teiid.query.optimizer.capabilities.SourceCapabilities.Capability;
import org.teiid.query.optimizer.relational.OptimizerRule;
import org.teiid.query.optimizer.relational.RuleStack;
import org.teiid.query.optimizer.relational.plantree.NodeConstants;
@@ -47,8 +50,10 @@
import org.teiid.query.resolver.util.AccessPattern;
import org.teiid.query.sql.lang.CompoundCriteria;
import org.teiid.query.sql.lang.Criteria;
+import org.teiid.query.sql.lang.DependentSetCriteria;
import org.teiid.query.sql.lang.JoinType;
import org.teiid.query.sql.lang.SubqueryContainer;
+import org.teiid.query.sql.lang.DependentSetCriteria.AttributeComparison;
import org.teiid.query.sql.symbol.ElementSymbol;
import org.teiid.query.sql.symbol.Expression;
import org.teiid.query.sql.symbol.GroupSymbol;
@@ -56,6 +61,7 @@
import org.teiid.query.sql.util.SymbolMap;
import org.teiid.query.sql.visitor.AggregateSymbolCollectorVisitor;
import org.teiid.query.sql.visitor.ElementCollectorVisitor;
+import org.teiid.query.sql.visitor.GroupsUsedByElementsVisitor;
import org.teiid.query.sql.visitor.ValueIteratorProviderCollectorVisitor;
import org.teiid.query.util.CommandContext;
@@ -111,19 +117,23 @@
deadNodes.add(critNode);
continue;
}
- pushTowardOriginatingNode(sourceNode, critNode, metadata, capFinder);
-
- boolean moved = false;
+ boolean moved = pushTowardOriginatingNode(sourceNode, critNode, metadata,
capFinder);
if(critNode.hasBooleanProperty(Info.IS_PUSHED) ||
(critNode.getGroups().isEmpty() && critNode.getSubqueryContainers().isEmpty()) ||
!atBoundary(critNode, sourceNode)) {
deadNodes.add(critNode);
+ movedAnyNode |= moved;
continue;
}
switch (sourceNode.getType()) {
case NodeConstants.Types.SOURCE:
{
- moved = pushAcrossFrame(sourceNode, critNode, metadata);
+ Boolean acrossFrame = pushAcrossFrame(sourceNode, critNode,
metadata);
+ if (acrossFrame != null) {
+ moved = acrossFrame;
+ } else {
+ movedAnyNode = true; //new nodes created
+ }
break;
}
case NodeConstants.Types.JOIN:
@@ -136,7 +146,7 @@
}
case NodeConstants.Types.GROUP:
{
- moved = pushAcrossGroupBy(sourceNode, critNode, metadata, true);
+ moved = pushAcrossGroupBy(sourceNode, critNode, metadata, true,
capFinder);
}
}
@@ -152,24 +162,25 @@
}
boolean pushAcrossGroupBy(PlanNode sourceNode,
- PlanNode critNode, QueryMetadataInterface metadata, boolean inPlan)
- throws QueryPlannerException {
+ PlanNode critNode, QueryMetadataInterface metadata, boolean inPlan, CapabilitiesFinder
capFinder)
+ throws QueryPlannerException, QueryMetadataException, TeiidComponentException {
+ if (critNode.hasBooleanProperty(NodeConstants.Info.IS_HAVING)) {
+ return false;
+ }
boolean moved = false;
- if (!critNode.hasBooleanProperty(NodeConstants.Info.IS_HAVING)) {
- SymbolMap symbolMap = (SymbolMap)
sourceNode.getProperty(NodeConstants.Info.SYMBOL_MAP);
- FrameUtil.convertNode(critNode, null, null, symbolMap.asMap(), metadata, true);
- if (inPlan) {
- NodeEditor.removeChildNode(critNode.getParent(), critNode);
- sourceNode.getFirstChild().addAsParent(critNode);
+ SymbolMap symbolMap = (SymbolMap)
sourceNode.getProperty(NodeConstants.Info.SYMBOL_MAP);
+ FrameUtil.convertNode(critNode, null, null, symbolMap.asMap(), metadata, true);
+ if (inPlan) {
+ NodeEditor.removeChildNode(critNode.getParent(), critNode);
+ sourceNode.getFirstChild().addAsParent(critNode);
+ }
+ moved = true;
+ if (critNode.hasBooleanProperty(NodeConstants.Info.IS_DEPENDENT_SET)) {
+ PlanNode accessNode = NodeEditor.findParent(critNode, NodeConstants.Types.ACCESS);
+ if (accessNode != null) {
+ markDependent(critNode, accessNode, metadata, capFinder);
+ moved = false; //terminal position
}
- moved = true;
- if (critNode.hasBooleanProperty(NodeConstants.Info.IS_DEPENDENT_SET)) {
- PlanNode accessNode = NodeEditor.findParent(critNode, NodeConstants.Types.ACCESS);
- if (accessNode != null) {
- markDependent(critNode, accessNode);
- moved = false; //terminal position
- }
- }
}
return moved;
}
@@ -230,14 +241,13 @@
if (jt == JoinType.JOIN_CROSS) {
joinNode.setProperty(NodeConstants.Info.JOIN_TYPE, JoinType.JOIN_INNER);
}
+ return moveCriteriaIntoOnClause(critNode, joinNode);
+ }
+ JoinType optimized = JoinUtil.optimizeJoinType(critNode, joinNode, metadata);
+
+ if (optimized == JoinType.JOIN_INNER) {
moveCriteriaIntoOnClause(critNode, joinNode);
- } else {
- JoinType optimized = JoinUtil.optimizeJoinType(critNode, joinNode,
metadata);
-
- if (optimized == JoinType.JOIN_INNER) {
- moveCriteriaIntoOnClause(critNode, joinNode);
- return true; //return true since the join type has changed
- }
+ return true; //return true since the join type has changed
}
return false;
}
@@ -246,8 +256,10 @@
* @param critNode
* @param joinNode
*/
- private void moveCriteriaIntoOnClause(PlanNode critNode,
+ private boolean moveCriteriaIntoOnClause(PlanNode critNode,
PlanNode joinNode) {
+ NodeEditor.removeChildNode(critNode.getParent(), critNode);
+
List joinCriteria =
(List)joinNode.getProperty(NodeConstants.Info.JOIN_CRITERIA);
Criteria criteria =
(Criteria)critNode.getProperty(NodeConstants.Info.SELECT_CRITERIA);
@@ -257,13 +269,52 @@
joinNode.setProperty(NodeConstants.Info.JOIN_CRITERIA, joinCriteria);
}
- if (!joinCriteria.contains(criteria)) {
- joinCriteria.add(criteria);
- if(critNode.hasBooleanProperty(NodeConstants.Info.IS_DEPENDENT_SET)) {
- joinNode.setProperty(NodeConstants.Info.IS_DEPENDENT_SET, Boolean.TRUE);
- }
+ if (joinCriteria.contains(criteria)) {
+ return false;
}
- NodeEditor.removeChildNode(critNode.getParent(), critNode);
+ boolean moved = false;
+ if(critNode.hasBooleanProperty(NodeConstants.Info.IS_DEPENDENT_SET)) {
+ if (criteria instanceof DependentSetCriteria) {
+ DependentSetCriteria dsc = (DependentSetCriteria)criteria;
+ if (dsc.hasMultipleAttributes()) {
+ //split the array based upon the join children.
+ List<DependentSetCriteria.AttributeComparison> joinExprs = new
ArrayList<DependentSetCriteria.AttributeComparison>();
+ List<DependentSetCriteria.AttributeComparison> leftExprs = new
ArrayList<DependentSetCriteria.AttributeComparison>();
+ List<DependentSetCriteria.AttributeComparison> rightExprs = new
ArrayList<DependentSetCriteria.AttributeComparison>();
+ PlanNode leftJoinSource =
FrameUtil.findJoinSourceNode(joinNode.getFirstChild());
+ PlanNode rightJoinSource =
FrameUtil.findJoinSourceNode(joinNode.getLastChild());
+ for (int i = 0; i < dsc.getAttributes().size(); i++) {
+ DependentSetCriteria.AttributeComparison comp = dsc.getAttributes().get(i);
+ Set<GroupSymbol> groups =
GroupsUsedByElementsVisitor.getGroups(comp.dep);
+ if (leftJoinSource.getGroups().containsAll(groups)) {
+ leftExprs.add(comp);
+ } else if (rightJoinSource.getGroups().containsAll(groups)){
+ rightExprs.add(comp);
+ } else {
+ joinExprs.add(comp);
+ }
+ }
+ criteria = RuleChooseDependent.createDependentSetCriteria(dsc.getContextSymbol(),
joinExprs);
+ PlanNode left =
RuleChooseDependent.createDependentSetNode(dsc.getContextSymbol(), leftExprs);
+ if (left != null) {
+ moved = true;
+ joinNode.getFirstChild().addAsParent(left);
+ }
+ PlanNode right =
RuleChooseDependent.createDependentSetNode(dsc.getContextSymbol(), rightExprs);
+ if (right != null) {
+ moved = true;
+ joinNode.getLastChild().addAsParent(right);
+ }
+ }
+ }
+ if (criteria != null) {
+ joinNode.setProperty(NodeConstants.Info.IS_DEPENDENT_SET, Boolean.TRUE);
+ }
+ }
+ if (criteria != null) {
+ joinCriteria.add(criteria);
+ }
+ return moved;
}
/**
@@ -275,7 +326,7 @@
* @throws QueryMetadataException
* @throws TeiidComponentException
*/
- void pushTowardOriginatingNode(PlanNode sourceNode, PlanNode critNode,
QueryMetadataInterface metadata, CapabilitiesFinder capFinder)
+ boolean pushTowardOriginatingNode(PlanNode sourceNode, PlanNode critNode, final
QueryMetadataInterface metadata, final CapabilitiesFinder capFinder)
throws QueryPlannerException, QueryMetadataException, TeiidComponentException {
boolean groupSelects = sourceNode.getParent().getType() ==
NodeConstants.Types.SELECT && sourceNode.getChildCount() == 0;
@@ -284,20 +335,76 @@
while (sourceNode.getParent().getType() == NodeConstants.Types.SELECT) {
sourceNode = sourceNode.getParent();
if (sourceNode == critNode) {
- return;
+ return false;
}
}
// See how far we can move it towards the SOURCE node
- PlanNode destination = examinePath(critNode, sourceNode, metadata, capFinder);
+ final PlanNode destination = examinePath(critNode, sourceNode, metadata, capFinder);
+ boolean result = false;
+ if (createdNodes == null & destination.getType() == NodeConstants.Types.ACCESS
&& isDependentFinalDestination(critNode, destination)) {
+ Criteria crit =
(Criteria)critNode.getProperty(NodeConstants.Info.SELECT_CRITERIA);
+ if (isMultiAttributeDependentSet(crit)) {
+ result = splitSet(critNode, new DependentNodeTest() {
+
+ @Override
+ public boolean isValid(PlanNode copyNode) throws QueryMetadataException,
+ QueryPlannerException, TeiidComponentException {
+ return RuleRaiseAccess.canRaiseOverSelect(destination, metadata, capFinder,
copyNode, null);
+ }
+ }, (DependentSetCriteria)crit, destination);
+ }
+ }
+
NodeEditor.removeChildNode(critNode.getParent(), critNode);
destination.addAsParent(critNode);
if (groupSelects && destination == sourceNode) {
//Help with the detection of composite keys in pushed criteria
RuleMergeCriteria.mergeChain(critNode, metadata);
}
+
+ return result;
}
+
+ private interface DependentNodeTest {
+ boolean isValid(PlanNode copyNode) throws QueryMetadataException,
QueryPlannerException, TeiidComponentException;
+ }
+ private boolean splitSet(PlanNode critNode, DependentNodeTest test, DependentSetCriteria
dscOrig, PlanNode destination)
+ throws QueryMetadataException, TeiidComponentException,
+ QueryPlannerException {
+ boolean result = false;
+ List<DependentSetCriteria> dscList = splitDependentSetCriteria(dscOrig);
+ List<DependentSetCriteria.AttributeComparison> pushable = new
ArrayList<AttributeComparison>();
+ List<DependentSetCriteria.AttributeComparison> nonPushable = new
ArrayList<AttributeComparison>();
+ for (DependentSetCriteria dsc : dscList) {
+ PlanNode copyNode = copyNode(critNode);
+ setCriteria(dsc, copyNode);
+ if (test.isValid(copyNode)) {
+ pushable.add(dsc.getAttributes().get(0));
+ } else {
+ nonPushable.add(dsc.getAttributes().get(0));
+ }
+ }
+ if (!pushable.isEmpty()) {
+ result = true; //signal that we should run again
+ if (nonPushable.isEmpty()) {
+ throw new AssertionError("should not be completely pushed"); //$NON-NLS-1$
+ }
+ setCriteria(RuleChooseDependent.createDependentSetCriteria(dscOrig.getContextSymbol(),
nonPushable), critNode);
+ PlanNode copyNode = copyNode(critNode);
+ setCriteria(RuleChooseDependent.createDependentSetCriteria(dscOrig.getContextSymbol(),
pushable), copyNode);
+ destination.addAsParent(copyNode); //it should be pushed in the next run
+ }
+ return result;
+ }
+
+ private void setCriteria(DependentSetCriteria dsc, PlanNode copyNode) {
+ copyNode.setProperty(NodeConstants.Info.SELECT_CRITERIA, dsc);
+ copyNode.getGroups().clear();
+ copyNode.addGroups(GroupsUsedByElementsVisitor.getGroups(dsc));
+ }
+
/**
* Examine the path from crit node to source node to determine how far down a node
* can be pushed.
@@ -329,12 +436,10 @@
satisfyAccessPatterns(critNode, currentNode);
}
- if (critNode.hasBooleanProperty(NodeConstants.Info.IS_DEPENDENT_SET)
- && NodeEditor.findNodePreOrder(currentNode.getFirstChild(),
NodeConstants.Types.GROUP, NodeConstants.Types.SOURCE) == null) {
+ if (isDependentFinalDestination(critNode, currentNode)) {
//once a dependent crit node is pushed, don't bother pushing
it further into the command
//dependent access node will use this as an assumption for where
dependent sets can appear in the command
- critNode.setProperty(NodeConstants.Info.IS_PUSHED,
Boolean.TRUE);
- currentNode.setProperty(NodeConstants.Info.IS_DEPENDENT_SET,
Boolean.TRUE);
+ markDependent(critNode,currentNode, metadata, capFinder);
return currentNode.getFirstChild();
}
} catch(QueryMetadataException e) {
@@ -373,17 +478,45 @@
return sourceNode;
}
- private void markDependent(PlanNode critNode, PlanNode accessNode) {
+ private boolean isMultiAttributeDependentSet(Criteria crit) {
+ return crit instanceof DependentSetCriteria &&
((DependentSetCriteria)crit).hasMultipleAttributes();
+ }
+
+ private boolean isDependentFinalDestination(PlanNode critNode,
+ PlanNode currentNode) {
+ return critNode.hasBooleanProperty(NodeConstants.Info.IS_DEPENDENT_SET)
+ && NodeEditor.findNodePreOrder(currentNode.getFirstChild(),
NodeConstants.Types.GROUP, NodeConstants.Types.SOURCE) == null;
+ }
+
+ private void markDependent(PlanNode critNode, PlanNode accessNode,
QueryMetadataInterface metadata, CapabilitiesFinder capFinder) throws
QueryMetadataException, TeiidComponentException {
//once a dependent crit node is pushed, don't bother pushing it further into the
command
//dependent access node will use this as an assumption for where dependent sets can
appear in the command
critNode.setProperty(NodeConstants.Info.IS_PUSHED, Boolean.TRUE);
- if (createdNodes == null) {
- accessNode.setProperty(NodeConstants.Info.IS_DEPENDENT_SET, Boolean.TRUE);
+ if (createdNodes != null) {
+ return; //this is during a planning run and should not cause additional side-effects
}
+ accessNode.setProperty(NodeConstants.Info.IS_DEPENDENT_SET, Boolean.TRUE);
+ Criteria crit = (Criteria) critNode.getProperty(NodeConstants.Info.SELECT_CRITERIA);
+ if (isMultiAttributeDependentSet(crit)
+ && !CapabilitiesUtil.supports(Capability.ARRAY_TYPE,
RuleRaiseAccess.getModelIDFromAccess(accessNode, metadata), metadata, capFinder)) {
+ //split the criteria into individual predicates
+ List<DependentSetCriteria> crits =
splitDependentSetCriteria((DependentSetCriteria) crit);
+ critNode.setProperty(NodeConstants.Info.SELECT_CRITERIA, new
CompoundCriteria(crits));
+ }
}
- boolean pushAcrossFrame(PlanNode sourceNode, PlanNode critNode, QueryMetadataInterface
metadata)
- throws QueryPlannerException {
+ private List<DependentSetCriteria> splitDependentSetCriteria(DependentSetCriteria
dsc) {
+ List<AttributeComparison> attributes = dsc.getAttributes();
+ List<DependentSetCriteria> crits = new
ArrayList<DependentSetCriteria>(attributes.size());
+ for (int i = 0; i < attributes.size(); i++) {
+ DependentSetCriteria.AttributeComparison comp = attributes.get(i);
+ crits.add(RuleChooseDependent.createDependentSetCriteria(dsc.getContextSymbol(),
Arrays.asList(comp)));
+ }
+ return crits;
+ }
+
+ Boolean pushAcrossFrame(PlanNode sourceNode, PlanNode critNode, QueryMetadataInterface
metadata)
+ throws QueryPlannerException, QueryMetadataException, TeiidComponentException {
//ensure that the criteria can be pushed further
if (sourceNode.getChildCount() == 1 &&
FrameUtil.isOrderedOrStrictLimit(sourceNode.getFirstChild())) {
@@ -427,26 +560,42 @@
return true;
}
- boolean moveNodeAcrossFrame(PlanNode critNode, PlanNode sourceNode,
QueryMetadataInterface metadata)
- throws QueryPlannerException {
+ Boolean moveNodeAcrossFrame(PlanNode critNode, PlanNode sourceNode, final
QueryMetadataInterface metadata)
+ throws QueryPlannerException, QueryMetadataException, TeiidComponentException {
// Check that sourceNode has a child to push across
if(sourceNode.getChildCount() == 0) {
return false;
}
- PlanNode projectNode = NodeEditor.findNodePreOrder(sourceNode.getFirstChild(),
NodeConstants.Types.PROJECT, NodeConstants.Types.SOURCE);
+ final PlanNode projectNode =
NodeEditor.findNodePreOrder(sourceNode.getFirstChild(), NodeConstants.Types.PROJECT,
NodeConstants.Types.SOURCE);
if(FrameUtil.isProcedure(projectNode)) {
return false;
}
- SymbolMap symbolMap = (SymbolMap)
sourceNode.getProperty(NodeConstants.Info.SYMBOL_MAP);
+ final SymbolMap symbolMap = (SymbolMap)
sourceNode.getProperty(NodeConstants.Info.SYMBOL_MAP);
- if (!createConvertedSelectNode(critNode,
sourceNode.getGroups().iterator().next(), projectNode, symbolMap, metadata)) {
+ final GroupSymbol sourceGroup = sourceNode.getGroups().iterator().next();
+ if (!placeConvertedSelectNode(critNode, sourceGroup, projectNode, symbolMap, metadata))
{
+ if (createdNodes == null) {
+ Criteria crit =
(Criteria)critNode.getProperty(NodeConstants.Info.SELECT_CRITERIA);
+ if (isMultiAttributeDependentSet(crit) && splitSet(critNode, new
DependentNodeTest() {
+
+ @Override
+ public boolean isValid(PlanNode copyNode) throws QueryMetadataException,
+ QueryPlannerException, TeiidComponentException {
+ return createConvertedSelectNode(copyNode, sourceGroup, projectNode,
symbolMap, metadata) != null;
+ }
+ }, (DependentSetCriteria)crit, sourceNode)) {
+ return null;
+ }
+ }
return false;
}
- satisfyAccessPatterns(critNode, sourceNode);
+ if (createdNodes == null) {
+ satisfyAccessPatterns(critNode, sourceNode);
+ }
// Mark critNode as a "phantom"
critNode.setProperty(NodeConstants.Info.IS_PHANTOM, Boolean.TRUE);
@@ -537,7 +686,9 @@
// Find source node above union and grab the symbol map
PlanNode sourceNode = NodeEditor.findParent(setOp, NodeConstants.Types.SOURCE);
GroupSymbol virtualGroup = sourceNode.getGroups().iterator().next();
- satisfyAccessPatterns(critNode, sourceNode);
+ if (createdNodes == null) {
+ satisfyAccessPatterns(critNode, sourceNode);
+ }
SymbolMap symbolMap = (SymbolMap)
sourceNode.getProperty(NodeConstants.Info.SYMBOL_MAP);
SymbolMap childMap = symbolMap;
@@ -557,7 +708,7 @@
}
// Move the node
- if(createConvertedSelectNode(critNode, virtualGroup, projectNode, childMap, metadata))
{
+ if(placeConvertedSelectNode(critNode, virtualGroup, projectNode, childMap, metadata))
{
movedCount++;
}
@@ -584,14 +735,32 @@
}
}
- private boolean createConvertedSelectNode(PlanNode critNode,
+ private boolean placeConvertedSelectNode(PlanNode critNode,
GroupSymbol sourceGroup,
PlanNode projectNode,
SymbolMap symbolMap,
QueryMetadataInterface metadata) throws
QueryPlannerException {
- // If projectNode has children, then it is from a SELECT without a FROM and the
criteria should not be pushed
+ PlanNode copyNode = createConvertedSelectNode(critNode, sourceGroup,
+ projectNode, symbolMap, metadata);
+ if (copyNode == null) {
+ return false;
+ }
+
+ PlanNode intermediateParent = NodeEditor.findParent(projectNode,
NodeConstants.Types.ACCESS, NodeConstants.Types.SOURCE | NodeConstants.Types.SET_OP);
+ if (intermediateParent != null) {
+ intermediateParent.addAsParent(copyNode);
+ } else {
+ projectNode.getFirstChild().addAsParent(copyNode);
+ }
+ return true;
+ }
+
+ private PlanNode createConvertedSelectNode(PlanNode critNode,
+ GroupSymbol sourceGroup, PlanNode projectNode, SymbolMap symbolMap,
+ QueryMetadataInterface metadata) throws QueryPlannerException {
+ // If projectNode has children, then it is from a SELECT without a FROM and the
criteria should not be pushed
if(projectNode.getChildCount() == 0) {
- return false;
+ return null;
}
List<WindowFunction> windowFunctions = null;
if (projectNode.hasBooleanProperty(Info.HAS_WINDOW_FUNCTIONS)) {
@@ -603,12 +772,12 @@
Boolean conversionResult = checkConversion(symbolMap,
ElementCollectorVisitor.getElements(crit, true), windowFunctions);
if (conversionResult == Boolean.FALSE) {
- return false; //not convertable
+ return null; //not convertable
}
if (!critNode.getSubqueryContainers().isEmpty()
&& checkConversion(symbolMap,
critNode.getCorrelatedReferenceElements(), windowFunctions) != null) {
- return false; //not convertable, or has an aggregate for a correlated reference
+ return null; //not convertable, or has an aggregate for a correlated reference
}
PlanNode copyNode = copyNode(critNode);
@@ -624,17 +793,10 @@
if (this.createdNodes != null) {
this.createdNodes.remove(this.createdNodes.size() - 1);
}
- return false;
+ return null;
}
-
- PlanNode intermediateParent = NodeEditor.findParent(projectNode,
NodeConstants.Types.ACCESS, NodeConstants.Types.SOURCE | NodeConstants.Types.SET_OP);
- if (intermediateParent != null) {
- intermediateParent.addAsParent(copyNode);
- } else {
- projectNode.getFirstChild().addAsParent(copyNode);
- }
- return true;
- }
+ return copyNode;
+ }
private Boolean checkConversion(SymbolMap symbolMap,
Collection<ElementSymbol> elements, List<WindowFunction> windowFunctions)
{
Modified:
trunk/engine/src/main/java/org/teiid/query/processor/relational/DependentCriteriaProcessor.java
===================================================================
---
trunk/engine/src/main/java/org/teiid/query/processor/relational/DependentCriteriaProcessor.java 2012-08-07
23:34:56 UTC (rev 4306)
+++
trunk/engine/src/main/java/org/teiid/query/processor/relational/DependentCriteriaProcessor.java 2012-08-10
14:52:39 UTC (rev 4307)
@@ -43,6 +43,7 @@
import org.teiid.query.sql.lang.DependentSetCriteria;
import org.teiid.query.sql.lang.OrderBy;
import org.teiid.query.sql.lang.SetCriteria;
+import org.teiid.query.sql.symbol.Array;
import org.teiid.query.sql.symbol.Constant;
import org.teiid.query.sql.symbol.Expression;
import org.teiid.query.sql.util.ValueIterator;
@@ -65,6 +66,13 @@
float maxNdv = NewCalculateCostUtil.UNKNOWN_VALUE;
boolean overMax;
+
+ long replacementSize() {
+ return replacement.size() * valueCount;
+ }
+
+ long valueCount = 1;
+
}
class TupleState {
@@ -86,11 +94,17 @@
if (!originalVs.isDistinct()) {
if (sortUtility == null) {
List<Expression> sortSymbols = new
ArrayList<Expression>(dependentSetStates.size());
- List<Boolean> sortDirection = new
ArrayList<Boolean>(sortSymbols.size());
for (int i = 0; i < dependentSetStates.size(); i++) {
- sortDirection.add(Boolean.valueOf(OrderBy.ASC));
- sortSymbols.add(dependentSetStates.get(i).valueExpression);
+ if (dependentSetStates.get(i).valueExpression instanceof Array) {
+ Array array = (Array)dependentSetStates.get(i).valueExpression;
+ for (Expression ex : array.getExpressions()) {
+ sortSymbols.add(ex);
+ }
+ } else {
+ sortSymbols.add(dependentSetStates.get(i).valueExpression);
+ }
}
+ List<Boolean> sortDirection =
Collections.nCopies(sortSymbols.size(), OrderBy.ASC);
this.sortUtility = new
SortUtility(originalVs.getTupleBuffer().createIndexedTupleSource(), sortSymbols,
sortDirection, Mode.DUP_REMOVE, dependentNode.getBufferManager(),
dependentNode.getConnectionID(), originalVs.getTupleBuffer().getSchema());
}
dvs = new DependentValueSource(sortUtility.sort());
@@ -221,6 +235,9 @@
SetState state = new SetState();
setStates.put(i, state);
state.valueExpression = dsc.getValueExpression();
+ if (dsc.hasMultipleAttributes()) {
+ state.valueCount =
((Array)dsc.getExpression()).getExpressions().size();
+ }
TupleState ts = dependentState.get(source);
if (ts == null) {
ts = new TupleState(source);
@@ -357,7 +374,7 @@
}
isNull |= state.isNull;
- lessThanMax &= state.replacement.size() < maxSize * (run +
1);
+ lessThanMax &= state.replacementSize() < maxSize * (run +
1);
}
if (doneCount == source.size()) {
@@ -383,7 +400,7 @@
}
for (SetState setState : source) {
- currentPredicates +=
setState.replacement.size()/maxSize+(setState.replacement.size()%maxSize!=0?1:0);
+ currentPredicates +=
setState.replacementSize()/maxSize+(setState.replacementSize()%maxSize!=0?1:0);
}
}
@@ -417,7 +434,7 @@
int numberOfSets = 1;
int maxSize = Integer.MAX_VALUE;
if (this.maxSetSize > 0) {
- maxSize = this.maxSetSize;
+ maxSize = (int) Math.max(1, this.maxSetSize/state.valueCount);
numberOfSets = state.replacement.size()/maxSize +
(state.replacement.size()%maxSize!=0?1:0);
}
Iterator<Object> iter = state.replacement.iterator();
Modified:
trunk/engine/src/main/java/org/teiid/query/processor/relational/DependentProcedureCriteriaProcessor.java
===================================================================
---
trunk/engine/src/main/java/org/teiid/query/processor/relational/DependentProcedureCriteriaProcessor.java 2012-08-07
23:34:56 UTC (rev 4306)
+++
trunk/engine/src/main/java/org/teiid/query/processor/relational/DependentProcedureCriteriaProcessor.java 2012-08-10
14:52:39 UTC (rev 4307)
@@ -34,6 +34,8 @@
import org.teiid.query.sql.lang.CompareCriteria;
import org.teiid.query.sql.lang.Criteria;
import org.teiid.query.sql.lang.IsNullCriteria;
+import org.teiid.query.sql.symbol.Array;
+import org.teiid.query.sql.symbol.ArrayValue;
import org.teiid.query.sql.symbol.ElementSymbol;
import org.teiid.query.sql.symbol.Expression;
import org.teiid.query.sql.symbol.Reference;
@@ -77,8 +79,8 @@
boolean validRow = true;
- for (Iterator i = Criteria.separateCriteriaByAnd(critInProgress).iterator();
i.hasNext();) {
- Criteria crit = (Criteria)i.next();
+ for (Iterator<Criteria> i =
Criteria.separateCriteriaByAnd(critInProgress).iterator(); i.hasNext() &&
validRow;) {
+ Criteria crit = i.next();
Object value = null;
boolean nullAllowed = false;
@@ -90,31 +92,30 @@
} else if (crit instanceof CompareCriteria) {
CompareCriteria compare = (CompareCriteria)crit;
value = compare.getRightExpression();
+ if (compare.getLeftExpression() instanceof Array) {
+ Array array = (Array)compare.getLeftExpression();
+ if (value instanceof Expression) {
+ value = eval.evaluate((Expression)value, null);
+ }
+ if (value == null) {
+ validRow = false;
+ break;
+ }
+ ArrayValue valueArray = (ArrayValue)value;
+ for (int j = 0; j < array.getExpressions().size(); j++) {
+ validRow = setParam(context, valueArray.getValues()[j], nullAllowed,
(Reference) array.getExpressions().get(j));
+ if (!validRow) {
+ break;
+ }
+ }
+ continue;
+ }
parameter = (Reference)compare.getLeftExpression();
} else {
Assertion.failed("Unknown predicate type"); //$NON-NLS-1$
}
- if (value instanceof Expression) {
- value = eval.evaluate((Expression)value, null);
- }
-
- if (value == null && !nullAllowed) {
- validRow = false;
- break;
- }
-
- ElementSymbol parameterSymbol = parameter.getExpression();
- if (context.containsVariable(parameterSymbol)) {
- Object existingValue = context.getValue(parameterSymbol);
-
- if ((value != null && !value.equals(existingValue)) || (value ==
null && existingValue != null)) {
- validRow = false;
- break;
- }
- }
-
- context.setValue(parameterSymbol, value);
+ validRow = setParam(context, value, nullAllowed, parameter);
}
critInProgress = null;
@@ -136,5 +137,30 @@
return true;
}
+
+ private boolean setParam(VariableContext context,
+ Object value, boolean nullAllowed, Reference parameter)
+ throws ExpressionEvaluationException, BlockedException,
+ TeiidComponentException {
+ if (value instanceof Expression) {
+ value = eval.evaluate((Expression)value, null);
+ }
+
+ if (value == null && !nullAllowed) {
+ return false;
+ }
+
+ ElementSymbol parameterSymbol = parameter.getExpression();
+ if (context.containsVariable(parameterSymbol)) {
+ Object existingValue = context.getValue(parameterSymbol);
+
+ if ((value != null && !value.equals(existingValue)) || (value == null
&& existingValue != null)) {
+ return false;
+ }
+ }
+
+ context.setValue(parameterSymbol, value);
+ return true;
+ }
}
Modified:
trunk/engine/src/main/java/org/teiid/query/processor/relational/DependentValueSource.java
===================================================================
---
trunk/engine/src/main/java/org/teiid/query/processor/relational/DependentValueSource.java 2012-08-07
23:34:56 UTC (rev 4306)
+++
trunk/engine/src/main/java/org/teiid/query/processor/relational/DependentValueSource.java 2012-08-10
14:52:39 UTC (rev 4307)
@@ -35,9 +35,10 @@
import org.teiid.core.TeiidProcessingException;
import org.teiid.core.types.DataTypeManager;
import org.teiid.core.util.Assertion;
+import org.teiid.query.sql.symbol.Array;
+import org.teiid.query.sql.symbol.ArrayValue;
import org.teiid.query.sql.symbol.Constant;
import org.teiid.query.sql.symbol.Expression;
-import org.teiid.query.sql.util.ValueIterator;
import org.teiid.query.sql.util.ValueIteratorSource;
@@ -70,15 +71,42 @@
* @throws TeiidComponentException
* @see
org.teiid.query.sql.util.ValueIteratorSource#getValueIterator(org.teiid.query.sql.symbol.Expression)
*/
- public ValueIterator getValueIterator(Expression valueExpression) throws
TeiidComponentException {
+ public TupleSourceValueIterator getValueIterator(Expression valueExpression) throws
TeiidComponentException {
IndexedTupleSource its = buffer.createIndexedTupleSource();
int index = 0;
if (valueExpression != null) {
- index = schema.indexOf(valueExpression);
- Assertion.assertTrue(index != -1);
+ if (valueExpression instanceof Array) {
+ Array array = (Array)valueExpression;
+ List<Expression> exprs = array.getExpressions();
+ final int[] indexes = new int[exprs.size()];
+ for (int i = 0; i < exprs.size(); i++) {
+ indexes[i] = getIndex(exprs.get(i));
+ }
+ return new TupleSourceValueIterator(its, index) {
+ @Override
+ public Object next() throws TeiidComponentException {
+ List<?> tuple = super.nextTuple();
+ Object[] a = new Object[indexes.length];
+ for (int i = 0; i < indexes.length; i++) {
+ a[i] = tuple.get(indexes[i]);
+ if (a[i] == null) {
+ return null; //TODO: this is a hack
+ }
+ }
+ return new ArrayValue(a);
+ }
+ };
+ }
+ index = getIndex(valueExpression);
}
return new TupleSourceValueIterator(its, index);
}
+
+ private int getIndex(Expression valueExpression) {
+ int index = schema.indexOf(valueExpression);
+ Assertion.assertTrue(index != -1);
+ return index;
+ }
public Set<Object> getCachedSet(Expression valueExpression) throws
TeiidComponentException, TeiidProcessingException {
Set<Object> result = null;
@@ -89,25 +117,31 @@
if (buffer.getRowCount() > buffer.getBatchSize()) {
return null;
}
- IndexedTupleSource its = buffer.createIndexedTupleSource();
+ TupleSourceValueIterator ve = getValueIterator(valueExpression);
int index = 0;
- if (valueExpression != null) {
- index = schema.indexOf(valueExpression);
+ Class<?> type = null;
+ if (valueExpression instanceof Array) {
+ type = ((Array)valueExpression).getBaseType();
+ } else {
+ if (valueExpression != null) {
+ index = schema.indexOf(valueExpression);
+ Assertion.assertTrue(index != -1);
+ }
+ type = ((Expression)schema.get(index)).getType();
}
- Assertion.assertTrue(index != -1);
- Class<?> type = ((Expression)schema.get(index)).getType();
+
if (!DataTypeManager.isHashable(type)) {
result = new TreeSet<Object>(Constant.COMPARATOR);
} else {
result = new HashSet<Object>();
}
- while (its.hasNext()) {
- Object value = its.nextTuple().get(index);
+ while (ve.hasNext()) {
+ Object value = ve.next();
if (value != null) {
result.add(value);
}
}
- its.closeSource();
+ ve.close();
if (cachedSets == null) {
cachedSets = new HashMap<Expression, Set<Object>>();
}
Modified:
trunk/engine/src/main/java/org/teiid/query/processor/relational/TupleSourceValueIterator.java
===================================================================
---
trunk/engine/src/main/java/org/teiid/query/processor/relational/TupleSourceValueIterator.java 2012-08-07
23:34:56 UTC (rev 4306)
+++
trunk/engine/src/main/java/org/teiid/query/processor/relational/TupleSourceValueIterator.java 2012-08-10
14:52:39 UTC (rev 4307)
@@ -22,10 +22,11 @@
package org.teiid.query.processor.relational;
+import java.util.List;
+
import org.teiid.common.buffer.IndexedTupleSource;
import org.teiid.core.TeiidComponentException;
import org.teiid.core.TeiidProcessingException;
-import org.teiid.query.QueryPlugin;
import org.teiid.query.sql.util.ValueIterator;
@@ -63,12 +64,20 @@
* @see java.util.Iterator#next()
*/
public Object next() throws TeiidComponentException{
- try {
- return tupleSourceIterator.nextTuple().get(columnIndex);
+ return nextTuple().get(columnIndex);
+ }
+
+ protected List<?> nextTuple() throws TeiidComponentException {
+ try {
+ return tupleSourceIterator.nextTuple();
} catch (TeiidProcessingException e) {
throw new TeiidComponentException(e);
}
}
+
+ public void close() {
+ this.tupleSourceIterator.closeSource();
+ }
/**
* Flags a reset as being needed
Modified: trunk/engine/src/main/java/org/teiid/query/sql/LanguageVisitor.java
===================================================================
--- trunk/engine/src/main/java/org/teiid/query/sql/LanguageVisitor.java 2012-08-07
23:34:56 UTC (rev 4306)
+++ trunk/engine/src/main/java/org/teiid/query/sql/LanguageVisitor.java 2012-08-10
14:52:39 UTC (rev 4307)
@@ -22,85 +22,9 @@
package org.teiid.query.sql;
-import org.teiid.query.sql.lang.AlterProcedure;
-import org.teiid.query.sql.lang.AlterTrigger;
-import org.teiid.query.sql.lang.AlterView;
-import org.teiid.query.sql.lang.ArrayTable;
-import org.teiid.query.sql.lang.BatchedUpdateCommand;
-import org.teiid.query.sql.lang.BetweenCriteria;
-import org.teiid.query.sql.lang.CompareCriteria;
-import org.teiid.query.sql.lang.CompoundCriteria;
-import org.teiid.query.sql.lang.Create;
-import org.teiid.query.sql.lang.Delete;
-import org.teiid.query.sql.lang.DependentSetCriteria;
-import org.teiid.query.sql.lang.Drop;
-import org.teiid.query.sql.lang.DynamicCommand;
-import org.teiid.query.sql.lang.ExistsCriteria;
-import org.teiid.query.sql.lang.ExpressionCriteria;
-import org.teiid.query.sql.lang.From;
-import org.teiid.query.sql.lang.GroupBy;
-import org.teiid.query.sql.lang.Insert;
-import org.teiid.query.sql.lang.Into;
-import org.teiid.query.sql.lang.IsNullCriteria;
-import org.teiid.query.sql.lang.JoinPredicate;
-import org.teiid.query.sql.lang.JoinType;
-import org.teiid.query.sql.lang.Limit;
-import org.teiid.query.sql.lang.MatchCriteria;
-import org.teiid.query.sql.lang.NotCriteria;
-import org.teiid.query.sql.lang.Option;
-import org.teiid.query.sql.lang.OrderBy;
-import org.teiid.query.sql.lang.OrderByItem;
-import org.teiid.query.sql.lang.ProcedureContainer;
-import org.teiid.query.sql.lang.Query;
-import org.teiid.query.sql.lang.Select;
-import org.teiid.query.sql.lang.SetClause;
-import org.teiid.query.sql.lang.SetClauseList;
-import org.teiid.query.sql.lang.SetCriteria;
-import org.teiid.query.sql.lang.SetQuery;
-import org.teiid.query.sql.lang.StoredProcedure;
-import org.teiid.query.sql.lang.SubqueryCompareCriteria;
-import org.teiid.query.sql.lang.SubqueryFromClause;
-import org.teiid.query.sql.lang.SubquerySetCriteria;
-import org.teiid.query.sql.lang.TextTable;
-import org.teiid.query.sql.lang.UnaryFromClause;
-import org.teiid.query.sql.lang.Update;
-import org.teiid.query.sql.lang.WithQueryCommand;
-import org.teiid.query.sql.lang.XMLTable;
-import org.teiid.query.sql.proc.AssignmentStatement;
-import org.teiid.query.sql.proc.Block;
-import org.teiid.query.sql.proc.BranchingStatement;
-import org.teiid.query.sql.proc.CommandStatement;
-import org.teiid.query.sql.proc.CreateProcedureCommand;
-import org.teiid.query.sql.proc.DeclareStatement;
-import org.teiid.query.sql.proc.IfStatement;
-import org.teiid.query.sql.proc.LoopStatement;
-import org.teiid.query.sql.proc.RaiseErrorStatement;
-import org.teiid.query.sql.proc.TriggerAction;
-import org.teiid.query.sql.proc.WhileStatement;
-import org.teiid.query.sql.symbol.AggregateSymbol;
-import org.teiid.query.sql.symbol.AliasSymbol;
-import org.teiid.query.sql.symbol.CaseExpression;
-import org.teiid.query.sql.symbol.Constant;
-import org.teiid.query.sql.symbol.DerivedColumn;
-import org.teiid.query.sql.symbol.ElementSymbol;
-import org.teiid.query.sql.symbol.ExpressionSymbol;
-import org.teiid.query.sql.symbol.Function;
-import org.teiid.query.sql.symbol.GroupSymbol;
-import org.teiid.query.sql.symbol.MultipleElementSymbol;
-import org.teiid.query.sql.symbol.QueryString;
-import org.teiid.query.sql.symbol.Reference;
-import org.teiid.query.sql.symbol.ScalarSubquery;
-import org.teiid.query.sql.symbol.SearchedCaseExpression;
-import org.teiid.query.sql.symbol.TextLine;
-import org.teiid.query.sql.symbol.WindowFunction;
-import org.teiid.query.sql.symbol.WindowSpecification;
-import org.teiid.query.sql.symbol.XMLAttributes;
-import org.teiid.query.sql.symbol.XMLElement;
-import org.teiid.query.sql.symbol.XMLForest;
-import org.teiid.query.sql.symbol.XMLNamespaces;
-import org.teiid.query.sql.symbol.XMLParse;
-import org.teiid.query.sql.symbol.XMLQuery;
-import org.teiid.query.sql.symbol.XMLSerialize;
+import org.teiid.query.sql.lang.*;
+import org.teiid.query.sql.proc.*;
+import org.teiid.query.sql.symbol.*;
/**
* <p>The LanguageVisitor can be used to visit a LanguageObject as if it were a
tree
@@ -218,4 +142,6 @@
public void visit(WindowFunction windowFunction) {}
public void visit(WindowSpecification windowSpecification) {}
+
+ public void visit(Array array) {}
}
Modified: trunk/engine/src/main/java/org/teiid/query/sql/lang/DependentSetCriteria.java
===================================================================
---
trunk/engine/src/main/java/org/teiid/query/sql/lang/DependentSetCriteria.java 2012-08-07
23:34:56 UTC (rev 4306)
+++
trunk/engine/src/main/java/org/teiid/query/sql/lang/DependentSetCriteria.java 2012-08-10
14:52:39 UTC (rev 4307)
@@ -22,11 +22,16 @@
package org.teiid.query.sql.lang;
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.List;
+
import org.teiid.core.util.EquivalenceUtil;
import org.teiid.core.util.HashCodeUtil;
import org.teiid.query.optimizer.relational.rules.NewCalculateCostUtil;
import org.teiid.query.processor.relational.DependentValueSource;
import org.teiid.query.sql.LanguageVisitor;
+import org.teiid.query.sql.symbol.Array;
import org.teiid.query.sql.symbol.ContextReference;
import org.teiid.query.sql.symbol.Expression;
@@ -40,6 +45,13 @@
*/
public class DependentSetCriteria extends AbstractSetCriteria implements ContextReference
{
+ public static class AttributeComparison {
+ public Expression dep;
+ public Expression ind;
+ public float ndv;
+ public float maxNdv;
+ }
+
/**
* Specifies the expression whose values we want to return in the iterator
*/
@@ -51,6 +63,9 @@
private float ndv = NewCalculateCostUtil.UNKNOWN_VALUE;
private float maxNdv = NewCalculateCostUtil.UNKNOWN_VALUE;
+ private float[] ndvs;
+ private float[] maxNdvs;
+
/**
* set only for dependent pushdown
*/
@@ -62,9 +77,47 @@
public DependentSetCriteria(Expression expr, String id) {
setExpression(expr);
this.id = id;
- }
+ }
+
+ public void setAttributes(List<AttributeComparison> attributes) {
+ this.ndvs = new float[attributes.size()];
+ this.maxNdvs = new float[attributes.size()];
+ for (int i = 0; i < attributes.size(); i++) {
+ AttributeComparison comp = attributes.get(i);
+ this.ndvs[i] = comp.ndv;
+ this.maxNdvs[i] = comp.maxNdv;
+ }
+ }
+
+ /**
+ * There is a mismatch between the expression form and the more convenient attribute
comparison,
+ * so we reconstruct when needed
+ */
+ public List<AttributeComparison> getAttributes() {
+ if (!hasMultipleAttributes()) {
+ AttributeComparison comp = new AttributeComparison();
+ comp.dep = getExpression();
+ comp.ind = getValueExpression();
+ comp.ndv = ndv;
+ comp.maxNdv = maxNdv;
+ return Arrays.asList(comp);
+ }
+ ArrayList<AttributeComparison> result = new
ArrayList<AttributeComparison>();
+ for (int i = 0; i < ndvs.length; i++) {
+ AttributeComparison comp = new AttributeComparison();
+ comp.dep = ((Array)getExpression()).getExpressions().get(i);
+ comp.ind = ((Array)getValueExpression()).getExpressions().get(i);
+ comp.ndv = ndv;
+ comp.maxNdv = maxNdv;
+ result.add(comp);
+ }
+ return result;
+ }
+
+ public boolean hasMultipleAttributes() {
+ return this.ndvs != null && this.ndvs.length > 1;
+ }
- @Override
public String getContextSymbol() {
return id;
}
@@ -161,6 +214,8 @@
criteriaCopy.id = this.id;
criteriaCopy.ndv = this.ndv;
criteriaCopy.maxNdv = this.maxNdv;
+ criteriaCopy.maxNdvs = this.maxNdvs;
+ criteriaCopy.ndvs = this.ndvs;
return criteriaCopy;
}
Modified: trunk/engine/src/main/java/org/teiid/query/sql/lang/ExistsCriteria.java
===================================================================
--- trunk/engine/src/main/java/org/teiid/query/sql/lang/ExistsCriteria.java 2012-08-07
23:34:56 UTC (rev 4306)
+++ trunk/engine/src/main/java/org/teiid/query/sql/lang/ExistsCriteria.java 2012-08-10
14:52:39 UTC (rev 4307)
@@ -29,7 +29,6 @@
import org.teiid.query.sql.LanguageVisitor;
import org.teiid.query.sql.lang.PredicateCriteria.Negatable;
import org.teiid.query.sql.symbol.ContextReference;
-import org.teiid.query.sql.symbol.Expression;
/**
@@ -130,11 +129,6 @@
return id;
}
- @Override
- public Expression getValueExpression() {
- return null;
- }
-
public QueryCommand getCommand() {
return this.command;
}
Modified:
trunk/engine/src/main/java/org/teiid/query/sql/lang/SubqueryCompareCriteria.java
===================================================================
---
trunk/engine/src/main/java/org/teiid/query/sql/lang/SubqueryCompareCriteria.java 2012-08-07
23:34:56 UTC (rev 4306)
+++
trunk/engine/src/main/java/org/teiid/query/sql/lang/SubqueryCompareCriteria.java 2012-08-10
14:52:39 UTC (rev 4307)
@@ -90,11 +90,6 @@
return id;
}
- @Override
- public Expression getValueExpression() {
- return null;
- }
-
/**
* Get the predicate quantifier - returns one of the following:
* <ul><li>{@link #NO_QUANTIFIER}</li>
Modified: trunk/engine/src/main/java/org/teiid/query/sql/lang/SubquerySetCriteria.java
===================================================================
---
trunk/engine/src/main/java/org/teiid/query/sql/lang/SubquerySetCriteria.java 2012-08-07
23:34:56 UTC (rev 4306)
+++
trunk/engine/src/main/java/org/teiid/query/sql/lang/SubquerySetCriteria.java 2012-08-10
14:52:39 UTC (rev 4307)
@@ -70,11 +70,6 @@
return id;
}
- @Override
- public Expression getValueExpression() {
- return null;
- }
-
/**
* Set the subquery command (either a SELECT or a procedure execution).
* @param command Command to execute to get the values for the criteria
Modified:
trunk/engine/src/main/java/org/teiid/query/sql/navigator/PreOrPostOrderNavigator.java
===================================================================
---
trunk/engine/src/main/java/org/teiid/query/sql/navigator/PreOrPostOrderNavigator.java 2012-08-07
23:34:56 UTC (rev 4306)
+++
trunk/engine/src/main/java/org/teiid/query/sql/navigator/PreOrPostOrderNavigator.java 2012-08-10
14:52:39 UTC (rev 4307)
@@ -617,6 +617,13 @@
postVisitVisitor(obj);
}
+ @Override
+ public void visit(Array array) {
+ preVisitVisitor(array);
+ visitNodes(array.getExpressions());
+ postVisitVisitor(array);
+ }
+
public static void doVisit(LanguageObject object, LanguageVisitor visitor, boolean
order) {
doVisit(object, visitor, order, false);
}
Added: trunk/engine/src/main/java/org/teiid/query/sql/symbol/Array.java
===================================================================
--- trunk/engine/src/main/java/org/teiid/query/sql/symbol/Array.java
(rev 0)
+++ trunk/engine/src/main/java/org/teiid/query/sql/symbol/Array.java 2012-08-10 14:52:39
UTC (rev 4307)
@@ -0,0 +1,93 @@
+/*
+ * JBoss, Home of Professional Open Source.
+ * See the COPYRIGHT.txt file distributed with this work for information
+ * regarding copyright ownership. Some portions may be licensed
+ * to Red Hat, Inc. under one or more contributor license agreements.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+ * 02110-1301 USA.
+ */
+
+package org.teiid.query.sql.symbol;
+
+import java.util.List;
+
+import org.teiid.core.types.DataTypeManager;
+import org.teiid.core.util.EquivalenceUtil;
+import org.teiid.core.util.HashCodeUtil;
+import org.teiid.query.sql.LanguageObject;
+import org.teiid.query.sql.LanguageVisitor;
+import org.teiid.query.sql.visitor.SQLStringVisitor;
+
+public class Array implements Expression {
+
+ private Class<?> baseType;
+ private List<Expression> expressions;
+
+ public Array(Class<?> baseType, List<Expression> expresssions) {
+ this.baseType = baseType;
+ this.expressions = expresssions;
+ }
+
+ @Override
+ public Class<?> getType() {
+ return DataTypeManager.DefaultDataClasses.OBJECT;
+ }
+
+ @Override
+ public void acceptVisitor(LanguageVisitor visitor) {
+ visitor.visit(this);
+ }
+
+ @Override
+ public Array clone() {
+ return new Array(baseType, LanguageObject.Util.deepClone(getExpressions(),
Expression.class));
+ }
+
+ public Class<?> getBaseType() {
+ return baseType;
+ }
+
+ public void setBaseType(Class<?> baseType) {
+ this.baseType = baseType;
+ }
+
+ public List<Expression> getExpressions() {
+ return expressions;
+ }
+
+ @Override
+ public int hashCode() {
+ return HashCodeUtil.hashCode(0, getExpressions());
+ }
+
+ @Override
+ public boolean equals(Object obj) {
+ if (this == obj) {
+ return true;
+ }
+ if (!(obj instanceof Array)) {
+ return false;
+ }
+ Array other = (Array) obj;
+ return EquivalenceUtil.areEqual(baseType, other.baseType) &&
EquivalenceUtil.areEqual(expressions, other.expressions);
+ }
+
+ @Override
+ public String toString() {
+ return SQLStringVisitor.getSQLString(this);
+ }
+
+}
Property changes on: trunk/engine/src/main/java/org/teiid/query/sql/symbol/Array.java
___________________________________________________________________
Added: svn:mime-type
+ text/plain
Added: trunk/engine/src/main/java/org/teiid/query/sql/symbol/ArrayValue.java
===================================================================
--- trunk/engine/src/main/java/org/teiid/query/sql/symbol/ArrayValue.java
(rev 0)
+++ trunk/engine/src/main/java/org/teiid/query/sql/symbol/ArrayValue.java 2012-08-10
14:52:39 UTC (rev 4307)
@@ -0,0 +1,79 @@
+/*
+ * JBoss, Home of Professional Open Source.
+ * See the COPYRIGHT.txt file distributed with this work for information
+ * regarding copyright ownership. Some portions may be licensed
+ * to Red Hat, Inc. under one or more contributor license agreements.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+ * 02110-1301 USA.
+ */
+
+package org.teiid.query.sql.symbol;
+
+import java.util.Arrays;
+
+public class ArrayValue implements Comparable<ArrayValue> {
+ private Object[] values;
+
+ public ArrayValue(Object[] values) {
+ this.values = values;
+ }
+
+ @Override
+ public int compareTo(ArrayValue o) {
+ int len1 = values.length;
+ int len2 = o.values.length;
+ int lim = Math.min(len1, len2);
+ for (int k = 0; k < lim; k++) {
+ Object object1 = values[k];
+ Object object2 = o.values[k];
+ if (object1 == null) {
+ if (object2 != null) {
+ return -1;
+ }
+ continue;
+ } else if (object2 == null) {
+ return 1;
+ }
+ int comp = Constant.COMPARATOR.compare(object1, object2);
+ if (comp != 0) {
+ return comp;
+ }
+ }
+ return len1 - len2;
+ }
+
+ @Override
+ public int hashCode() {
+ return Arrays.hashCode(values);
+ }
+
+ @Override
+ public boolean equals(Object obj) {
+ if (obj == this) {
+ return true;
+ }
+ if (!(obj instanceof ArrayValue)) {
+ return false;
+ }
+ ArrayValue other = (ArrayValue)obj;
+ return Arrays.equals(values, other.values);
+ }
+
+ public Object[] getValues() {
+ return values;
+ }
+
+}
Property changes on:
trunk/engine/src/main/java/org/teiid/query/sql/symbol/ArrayValue.java
___________________________________________________________________
Added: svn:mime-type
+ text/plain
Modified: trunk/engine/src/main/java/org/teiid/query/sql/symbol/ContextReference.java
===================================================================
--- trunk/engine/src/main/java/org/teiid/query/sql/symbol/ContextReference.java 2012-08-07
23:34:56 UTC (rev 4306)
+++ trunk/engine/src/main/java/org/teiid/query/sql/symbol/ContextReference.java 2012-08-10
14:52:39 UTC (rev 4307)
@@ -26,6 +26,4 @@
public String getContextSymbol();
- public Expression getValueExpression();
-
}
Modified: trunk/engine/src/main/java/org/teiid/query/sql/symbol/Reference.java
===================================================================
--- trunk/engine/src/main/java/org/teiid/query/sql/symbol/Reference.java 2012-08-07
23:34:56 UTC (rev 4306)
+++ trunk/engine/src/main/java/org/teiid/query/sql/symbol/Reference.java 2012-08-10
14:52:39 UTC (rev 4307)
@@ -92,11 +92,6 @@
return "$param/pos" + this.refIndex; //$NON-NLS-1$
}
- @Override
- public Expression getValueExpression() {
- return this.expression;
- }
-
public ElementSymbol getExpression() {
return this.expression;
}
Modified: trunk/engine/src/main/java/org/teiid/query/sql/symbol/ScalarSubquery.java
===================================================================
--- trunk/engine/src/main/java/org/teiid/query/sql/symbol/ScalarSubquery.java 2012-08-07
23:34:56 UTC (rev 4306)
+++ trunk/engine/src/main/java/org/teiid/query/sql/symbol/ScalarSubquery.java 2012-08-10
14:52:39 UTC (rev 4307)
@@ -72,11 +72,6 @@
return id;
}
- @Override
- public Expression getValueExpression() {
- return null;
- }
-
/**
* @see org.teiid.query.sql.symbol.Expression#getType()
*/
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 2012-08-07
23:34:56 UTC (rev 4306)
+++
trunk/engine/src/main/java/org/teiid/query/sql/visitor/ExpressionMappingVisitor.java 2012-08-10
14:52:39 UTC (rev 4307)
@@ -426,4 +426,12 @@
}
}
+ @Override
+ public void visit(Array array) {
+ List<Expression> exprs = array.getExpressions();
+ for (int i = 0; i < exprs.size(); i++) {
+ exprs.set(i, replaceExpression(exprs.get(i)));
+ }
+ }
+
}
Modified: trunk/engine/src/main/java/org/teiid/query/sql/visitor/SQLStringVisitor.java
===================================================================
---
trunk/engine/src/main/java/org/teiid/query/sql/visitor/SQLStringVisitor.java 2012-08-07
23:34:56 UTC (rev 4306)
+++
trunk/engine/src/main/java/org/teiid/query/sql/visitor/SQLStringVisitor.java 2012-08-10
14:52:39 UTC (rev 4307)
@@ -2041,6 +2041,13 @@
}
append(Tokens.RPAREN);
}
+
+ @Override
+ public void visit(Array array) {
+ append(Tokens.LPAREN);
+ registerNodes(array.getExpressions(), 0);
+ append(Tokens.RPAREN);
+ }
public static String escapeSinglePart( String part ) {
if (isReservedWord(part)) {
Modified: trunk/engine/src/main/javacc/org/teiid/query/parser/SQLParser.jj
===================================================================
--- trunk/engine/src/main/javacc/org/teiid/query/parser/SQLParser.jj 2012-08-07 23:34:56
UTC (rev 4306)
+++ trunk/engine/src/main/javacc/org/teiid/query/parser/SQLParser.jj 2012-08-10 14:52:39
UTC (rev 4307)
@@ -1874,7 +1874,7 @@
/*
name=select clause
description=The columns returned by a query. Can optionally be distinct.
-example={code:sql}SELECT *{code}\n{code:sql}"SELECT DISTINCT a, b, c{code}
+example={code:sql}SELECT *{code}\n{code:sql}SELECT DISTINCT a, b, c{code}
*/
Select select(ParseInfo info) :
{
Modified: trunk/engine/src/test/java/org/teiid/query/optimizer/TestDependentJoins.java
===================================================================
---
trunk/engine/src/test/java/org/teiid/query/optimizer/TestDependentJoins.java 2012-08-07
23:34:56 UTC (rev 4306)
+++
trunk/engine/src/test/java/org/teiid/query/optimizer/TestDependentJoins.java 2012-08-10
14:52:39 UTC (rev 4307)
@@ -744,6 +744,7 @@
caps.setCapabilitySupport(Capability.QUERY_SEARCHED_CASE, true);
caps.setCapabilitySupport(Capability.QUERY_FROM_JOIN_INNER, true);
caps.setCapabilitySupport(Capability.QUERY_FROM_GROUP_ALIAS, true);
+ caps.setCapabilitySupport(Capability.ARRAY_TYPE, true);
caps.setSourceProperty(Capability.MAX_IN_CRITERIA_SIZE, new Integer(1000));
caps.setFunctionSupport("||", true); //$NON-NLS-1$
capFinder.addCapabilities("BQT1", caps); //$NON-NLS-1$
@@ -757,7 +758,7 @@
"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$
metadata,
null, capFinder,
- new String[] {"SELECT g_0.StringKey, g_0.StringNum, g_0.IntKey FROM
BQT2.SmallA AS g_0", "SELECT g_0.StringKey, g_0.StringNum FROM BQT1.SmallA AS
g_0 WHERE (g_0.StringNum = g_0.StringKey) AND (g_0.StringKey IN (<dependent
values>)) AND (g_0.StringNum IN (<dependent values>))"}, //$NON-NLS-1$
//$NON-NLS-2$
+ new String[] {"SELECT g_0.StringKey, g_0.StringNum, g_0.IntKey FROM
BQT2.SmallA AS g_0", "SELECT g_0.StringKey, g_0.StringNum FROM BQT1.SmallA AS
g_0 WHERE (g_0.StringNum = g_0.StringKey) AND ((g_0.StringKey, g_0.StringNum) IN
(<dependent values>))"}, //$NON-NLS-1$ //$NON-NLS-2$
TestOptimizer.ComparisonMode.EXACT_COMMAND_STRING );
TestOptimizer.checkNodeTypes(plan, new int[] {
Modified: trunk/engine/src/test/java/org/teiid/query/processor/TestDependentJoins.java
===================================================================
---
trunk/engine/src/test/java/org/teiid/query/processor/TestDependentJoins.java 2012-08-07
23:34:56 UTC (rev 4306)
+++
trunk/engine/src/test/java/org/teiid/query/processor/TestDependentJoins.java 2012-08-10
14:52:39 UTC (rev 4307)
@@ -163,7 +163,33 @@
// Run query
TestProcessor.helpProcess(plan, dataManager, expected);
}
+
+ @Test public void testMultiCritDepJoin2a() {
+ // Create query
+ String sql = "SELECT pm1.g1.e1 FROM pm1.g1, pm2.g1 WHERE pm2.g1.e1=pm1.g1.e1
AND pm1.g1.e2=pm2.g1.e2 order by pm1.g1.e1 option makedep pm1.g1"; //$NON-NLS-1$
+
+ // Create expected results
+ List[] expected = new List[] {
+ Arrays.asList(new Object[] { "a" }), //$NON-NLS-1$
+ Arrays.asList(new Object[] { "a" }), //$NON-NLS-1$
+ Arrays.asList(new Object[] { "a" }), //$NON-NLS-1$
+ Arrays.asList(new Object[] { "a" }), //$NON-NLS-1$
+ Arrays.asList(new Object[] { "a" }), //$NON-NLS-1$
+ Arrays.asList(new Object[] { "b" }), //$NON-NLS-1$
+ Arrays.asList(new Object[] { "c" }) //$NON-NLS-1$
+ };
+
+ // Construct data manager with data
+ FakeDataManager dataManager = new FakeDataManager();
+ TestProcessor.sampleData1(dataManager);
+ BasicSourceCapabilities bsc = TestOptimizer.getTypicalCapabilities();
+ bsc.setCapabilitySupport(Capability.ARRAY_TYPE, true);
+ ProcessorPlan plan = helpGetPlan(sql);
+ // Run query
+ TestProcessor.helpProcess(plan, dataManager, expected);
+ }
+
/** SELECT pm1.g1.e1 FROM pm1.g1, pm2.g1 WHERE pm2.g1.e1=pm1.g1.e1 AND
pm1.g1.e2=pm2.g1.e2 */
@Test public void testMultiCritDepJoin3() {
// Create query
@@ -1034,7 +1060,12 @@
}
@Test public void testMakeIndHintPushdown() {
- // Create query
+ helpTestPushdown(true);
+ helpTestPushdown(false);
+ }
+
+ private void helpTestPushdown(boolean supportsArrayType) {
+ // Create query
String sql = "SELECT pm1.g1.e1 FROM /*+ MAKEIND */ pm1.g1, pm2.g1 WHERE
pm1.g1.e1 = pm2.g1.e1 AND pm1.g1.e2=pm2.g1.e2 order by pm1.g1.e1"; //$NON-NLS-1$
// Create expected results
@@ -1045,9 +1076,14 @@
// Construct data manager with data
HardcodedDataManager dataManager = new
HardcodedDataManager(RealMetadataFactory.example1Cached());
dataManager.addData("SELECT g_0.e1 AS c_0, g_0.e2 AS c_1 FROM g1 AS g_0
ORDER BY c_0, c_1", new List[] {Arrays.asList("a", 1)});
- dataManager.addData("SELECT g_0.e1 AS c_0, g_0.e2 AS c_1 FROM g1 AS g_0
WHERE g_0.e1 = ? AND g_0.e2 = ? ORDER BY c_0, c_1", new List[]
{Arrays.asList("a", 1)});
+ if (supportsArrayType) {
+ dataManager.addData("SELECT g_0.e1 AS c_0, g_0.e2 AS c_1 FROM g1 AS g_0
WHERE (g_0.e1, g_0.e2) = ? ORDER BY c_0, c_1", new List[]
{Arrays.asList("a", 1)});
+ } else {
+ dataManager.addData("SELECT g_0.e1 AS c_0, g_0.e2 AS c_1 FROM g1 AS g_0
WHERE g_0.e1 = ? AND g_0.e2 = ? ORDER BY c_0, c_1", new List[]
{Arrays.asList("a", 1)});
+ }
BasicSourceCapabilities bsc = TestOptimizer.getTypicalCapabilities();
bsc.setCapabilitySupport(Capability.DEPENDENT_JOIN, true);
+ bsc.setCapabilitySupport(Capability.ARRAY_TYPE, supportsArrayType);
DefaultCapabilitiesFinder dcf = new DefaultCapabilitiesFinder(bsc);
// Plan query
ProcessorPlan plan = TestProcessor.helpGetPlan(sql,
RealMetadataFactory.example1Cached(), dcf);
@@ -1060,6 +1096,6 @@
assertEquals(1, s.getDependentValues().size());
List<? extends List<?>> vals =
s.getDependentValues().values().iterator().next();
assertEquals(1, vals.size());
- }
+ }
}
Added: trunk/engine/src/test/java/org/teiid/query/sql/symbol/TestArray.java
===================================================================
--- trunk/engine/src/test/java/org/teiid/query/sql/symbol/TestArray.java
(rev 0)
+++ trunk/engine/src/test/java/org/teiid/query/sql/symbol/TestArray.java 2012-08-10
14:52:39 UTC (rev 4307)
@@ -0,0 +1,55 @@
+/*
+ * JBoss, Home of Professional Open Source.
+ * See the COPYRIGHT.txt file distributed with this work for information
+ * regarding copyright ownership. Some portions may be licensed
+ * to Red Hat, Inc. under one or more contributor license agreements.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+ * 02110-1301 USA.
+ */
+
+package org.teiid.query.sql.symbol;
+
+import static org.junit.Assert.*;
+
+import java.util.Arrays;
+
+import org.junit.Test;
+import org.teiid.core.types.DataTypeManager;
+import org.teiid.core.util.UnitTestUtil;
+
+@SuppressWarnings("nls")
+public class TestArray {
+
+ @Test public void testArrayValueCompare() {
+ ArrayValue a1 = new ArrayValue(new Object[] {1, 2, 3});
+
+ UnitTestUtil.helpTestEquivalence(0, a1, a1);
+
+ ArrayValue a2 = new ArrayValue(new Object[] {1, 2});
+
+ UnitTestUtil.helpTestEquivalence(1, a1, a2);
+ }
+
+ @Test public void testArrayClone() {
+ Array array = new Array(DataTypeManager.DefaultDataClasses.OBJECT,
Arrays.asList((Expression)new ElementSymbol("e1")));
+
+ Array a1 = array.clone();
+
+ assertNotSame(a1, array);
+ assertNotSame(a1.getExpressions().get(0), array.getExpressions().get(0));
+ }
+
+}
Property changes on: trunk/engine/src/test/java/org/teiid/query/sql/symbol/TestArray.java
___________________________________________________________________
Added: svn:mime-type
+ text/plain
Modified:
trunk/engine/src/test/java/org/teiid/query/sql/visitor/TestExpressionMappingVisitor.java
===================================================================
---
trunk/engine/src/test/java/org/teiid/query/sql/visitor/TestExpressionMappingVisitor.java 2012-08-07
23:34:56 UTC (rev 4306)
+++
trunk/engine/src/test/java/org/teiid/query/sql/visitor/TestExpressionMappingVisitor.java 2012-08-10
14:52:39 UTC (rev 4307)
@@ -31,27 +31,20 @@
import java.util.Map;
import org.junit.Test;
+import org.teiid.core.types.DataTypeManager;
import org.teiid.language.SQLConstants.NonReserved;
import org.teiid.query.sql.LanguageObject;
import org.teiid.query.sql.lang.CompareCriteria;
import org.teiid.query.sql.lang.Select;
import org.teiid.query.sql.lang.SetCriteria;
-import org.teiid.query.sql.symbol.AggregateSymbol;
-import org.teiid.query.sql.symbol.CaseExpression;
-import org.teiid.query.sql.symbol.Constant;
-import org.teiid.query.sql.symbol.ElementSymbol;
-import org.teiid.query.sql.symbol.Expression;
-import org.teiid.query.sql.symbol.Function;
-import org.teiid.query.sql.symbol.SearchedCaseExpression;
-import org.teiid.query.sql.symbol.TestCaseExpression;
-import org.teiid.query.sql.symbol.TestSearchedCaseExpression;
+import org.teiid.query.sql.symbol.*;
import org.teiid.translator.SourceSystemFunctions;
-
+@SuppressWarnings("nls")
public class TestExpressionMappingVisitor {
- public void helpTest(LanguageObject original, Map map, LanguageObject expected) {
+ public void helpTest(LanguageObject original, Map<Expression, Expression> map,
LanguageObject expected) {
ExpressionMappingVisitor.mapExpressions(original, map);
assertEquals("Did not get expected mapped expression", expected,
original); //$NON-NLS-1$
@@ -60,7 +53,7 @@
@Test public void testCompareCriteria1() {
ElementSymbol e1 = new ElementSymbol("e1"); //$NON-NLS-1$
Function f = new Function("+", new Expression[] { new Constant(new
Integer(2)), new Constant(new Integer(5)) }); //$NON-NLS-1$
- Map map = new HashMap();
+ Map<Expression, Expression> map = new HashMap<Expression,
Expression>();
map.put(e1, f);
CompareCriteria before = new CompareCriteria(e1, CompareCriteria.EQ, new
Constant("xyz")); //$NON-NLS-1$
CompareCriteria after = new CompareCriteria(f, CompareCriteria.EQ, new
Constant("xyz")); //$NON-NLS-1$
@@ -70,7 +63,7 @@
@Test public void testCompareCriteria2() {
ElementSymbol e1 = new ElementSymbol("e1"); //$NON-NLS-1$
Function f = new Function("+", new Expression[] { new Constant(new
Integer(2)), new Constant(new Integer(5)) }); //$NON-NLS-1$
- Map map = new HashMap();
+ Map<Expression, Expression> map = new HashMap<Expression,
Expression>();
map.put(e1, f);
CompareCriteria before = new CompareCriteria(new Constant("xyz"),
CompareCriteria.EQ, e1); //$NON-NLS-1$
CompareCriteria after = new CompareCriteria(new Constant("xyz"),
CompareCriteria.EQ, f); //$NON-NLS-1$
@@ -91,7 +84,7 @@
ElementSymbol e7 = new ElementSymbol("e7"); //$NON-NLS-1$
Function f4 = new Function("*", new Expression[] { e5, e6 });
//$NON-NLS-1$
- Map map = new HashMap();
+ Map<Expression, Expression> map = new HashMap<Expression,
Expression>();
map.put(e3, f4);
map.put(e2, e7);
@@ -107,14 +100,14 @@
Constant c1 = new Constant("xyz"); //$NON-NLS-1$
Constant c2 = new Constant("abc"); //$NON-NLS-1$
Constant c3 = new Constant("def"); //$NON-NLS-1$
- List values = new ArrayList();
+ List<Expression> values = new ArrayList<Expression>();
values.add(c1);
values.add(c2);
- List mappedValues = new ArrayList();
+ List<Expression> mappedValues = new ArrayList<Expression>();
mappedValues.add(c1);
mappedValues.add(c3);
- Map map = new HashMap();
+ Map<Expression, Expression> map = new HashMap<Expression,
Expression>();
map.put(e1, e2);
map.put(c2, c3);
@@ -129,11 +122,11 @@
Constant a = new Constant(String.valueOf('a'));
Constant z = new Constant(String.valueOf('z'));
- HashMap map = new HashMap();
+ HashMap<Expression, Expression> map = new HashMap<Expression,
Expression>();
map.put(x, y);
map.put(a, z);
- ArrayList whens = new ArrayList(), thens = new ArrayList();
+ ArrayList<Expression> whens = new ArrayList<Expression>(), thens =
new ArrayList<Expression>();
whens.add(new Constant(String.valueOf('z')));
thens.add(new Constant(new Integer(0)));
whens.add(new Constant(String.valueOf('b')));
@@ -150,10 +143,10 @@
ElementSymbol x = new ElementSymbol("x"); //$NON-NLS-1$
ElementSymbol y = new ElementSymbol("y"); //$NON-NLS-1$
- HashMap map = new HashMap();
+ HashMap<Expression, Expression> map = new HashMap<Expression,
Expression>();
map.put(x, y);
- ArrayList whens = new ArrayList(), thens = new ArrayList();
+ ArrayList<Expression> whens = new ArrayList<Expression>(), thens =
new ArrayList<Expression>();
whens.add(new CompareCriteria(y, CompareCriteria.EQ, new Constant(new
Integer(0))));
thens.add(new Constant(new Integer(0)));
whens.add(new CompareCriteria(y, CompareCriteria.EQ, new Constant(new
Integer(1))));
@@ -170,7 +163,7 @@
ElementSymbol x = new ElementSymbol("y.x"); //$NON-NLS-1$
ElementSymbol y = new ElementSymbol("z.X"); //$NON-NLS-1$
- HashMap map = new HashMap();
+ HashMap<Expression, Expression> map = new HashMap<Expression,
Expression>();
map.put(x, y);
LanguageObject toMap = new Select(Arrays.asList(x));
@@ -215,4 +208,14 @@
assertEquals("(SUM(SUM(g1.e1)) + SUM(SUM(g1.e1)))", f.toString());
//$NON-NLS-1$
}
+ @Test public void testArray() {
+ Expression e1 = new ElementSymbol("g1.e1"); //$NON-NLS-1$
+ Expression e2 = new ElementSymbol("g1.e2"); //$NON-NLS-1$
+ Map<Expression, ElementSymbol> map = new HashMap<Expression,
ElementSymbol>();
+ map.put(e1, new ElementSymbol("foo"));
+ Array a = new Array(DataTypeManager.DefaultDataClasses.OBJECT, Arrays.asList(e1,
e2));
+ ExpressionMappingVisitor.mapExpressions(a, map);
+ assertEquals("(foo, g1.e2)", a.toString()); //$NON-NLS-1$
+ }
+
}
Modified:
trunk/engine/src/test/java/org/teiid/query/sql/visitor/TestSQLStringVisitor.java
===================================================================
---
trunk/engine/src/test/java/org/teiid/query/sql/visitor/TestSQLStringVisitor.java 2012-08-07
23:34:56 UTC (rev 4306)
+++
trunk/engine/src/test/java/org/teiid/query/sql/visitor/TestSQLStringVisitor.java 2012-08-10
14:52:39 UTC (rev 4307)
@@ -47,6 +47,7 @@
import org.teiid.query.sql.proc.RaiseErrorStatement;
import org.teiid.query.sql.symbol.*;
import org.teiid.query.unittest.RealMetadataFactory;
+import org.teiid.translator.TypeFacility;
@SuppressWarnings("nls")
public class TestSQLStringVisitor {
@@ -1696,5 +1697,10 @@
String sql = "SELECT * from texttable(file columns x string WIDTH 1 NO TRIM NO
ROW DELIMITER) as x"; //$NON-NLS-1$
helpTest(QueryParser.getQueryParser().parseCommand(sql), "SELECT * FROM
TEXTTABLE(file COLUMNS x string WIDTH 1 NO TRIM NO ROW DELIMITER) AS x");
}
+
+ @Test public void testArray() {
+ Array array = new Array(TypeFacility.RUNTIME_TYPES.INTEGER, Arrays.asList(new
ElementSymbol("e1"), new Constant(1)));
+ helpTest(array, "(e1, 1)"); //$NON-NLS-1$
+ }
}