teiid SVN: r4310 - trunk/jboss-integration/src/main/resources/org/teiid/jboss.
by teiid-commits@lists.jboss.org
Author: rareddy
Date: 2012-08-13 09:45:19 -0400 (Mon, 13 Aug 2012)
New Revision: 4310
Modified:
trunk/jboss-integration/src/main/resources/org/teiid/jboss/i18n.properties
Log:
TEIID-2143: Adding spaces between the possible cipher names for web console help system
Modified: trunk/jboss-integration/src/main/resources/org/teiid/jboss/i18n.properties
===================================================================
--- trunk/jboss-integration/src/main/resources/org/teiid/jboss/i18n.properties 2012-08-10 17:12:21 UTC (rev 4309)
+++ trunk/jboss-integration/src/main/resources/org/teiid/jboss/i18n.properties 2012-08-13 13:45:19 UTC (rev 4310)
@@ -151,7 +151,7 @@
ssl-authentication-mode.describe=Authentication Mode (1-way, 2-way, anonymous)
ssl-ssl-protocol.describe=SSL protocol used
ssl-keymanagement-algorithm.describe=Use key management algorithm
-enabled-cipher-suites.describe=Cipher suites that are allowed to be used for SSL. Use to restrict encryption strength(128 bit, 256 bit). Only provide encryption suites that are supported by both client and server JVM. ex:SSL_RSA_WITH_RC4_128_MD5,SSL_RSA_WITH_RC4_128_SHA,SSL_RSA_WITH_3DES_EDE_CBC_SHA,SSL_DHE_DSS_WITH_3DES_EDE_CBC_SHA,SSL_DHE_RSA_WITH_3DES_EDE_CBC_SHA,TLS_DHE_RSA_WITH_AES_128_CBC_SHA,TLS_DHE_DSS_WITH_AES_128_CBC_SHA,TLS_KRB5_WITH_RC4_128_MD5,TLS_KRB5_WITH_RC4_128_SHA,TLS_RSA_WITH_AES_128_CBC_SHA,TLS_KRB5_WITH_3DES_EDE_CBC_MD5,TLS_KRB5_WITH_3DES_EDE_CBC_SHA,TLS_DHE_RSA_WITH_AES_256_CBC_SHA,TLS_DHE_DSS_WITH_AES_256_CBC_SHA,TLS_RSA_WITH_AES_256_CBC_SHA
+enabled-cipher-suites.describe=Cipher suites that are allowed to be used for SSL. Use to restrict encryption strength(128 bit, 256 bit). Only provide encryption suites that are supported by both client and server JVM. ex:SSL_RSA_WITH_RC4_128_MD5, SSL_RSA_WITH_RC4_128_SHA, SSL_RSA_WITH_3DES_EDE_CBC_SHA, SSL_DHE_DSS_WITH_3DES_EDE_CBC_SHA, SSL_DHE_RSA_WITH_3DES_EDE_CBC_SHA, TLS_DHE_RSA_WITH_AES_128_CBC_SHA, TLS_DHE_DSS_WITH_AES_128_CBC_SHA, TLS_KRB5_WITH_RC4_128_MD5, TLS_KRB5_WITH_RC4_128_SHA, TLS_RSA_WITH_AES_128_CBC_SHA, TLS_KRB5_WITH_3DES_EDE_CBC_MD5, TLS_KRB5_WITH_3DES_EDE_CBC_SHA, TLS_DHE_RSA_WITH_AES_256_CBC_SHA, TLS_DHE_DSS_WITH_AES_256_CBC_SHA, TLS_RSA_WITH_AES_256_CBC_SHA
keystore-name.describe=Keystore File Name
keystore-password.describe=Keystore password
keystore-type.describe=Keystore type
12 years
teiid SVN: r4309 - in trunk: engine/src/main/java/org/teiid/query/function and 1 other directories.
by teiid-commits@lists.jboss.org
Author: shawkins
Date: 2012-08-10 13:12:21 -0400 (Fri, 10 Aug 2012)
New Revision: 4309
Modified:
trunk/build/kits/jboss-as7/docs/teiid/teiid-releasenotes.html
trunk/engine/src/main/java/org/teiid/query/function/FunctionMethods.java
trunk/runtime/src/main/java/org/teiid/transport/PgBackendProtocol.java
Log:
TEIID-2138 changing the pg standard_conforming_strings default
Modified: trunk/build/kits/jboss-as7/docs/teiid/teiid-releasenotes.html
===================================================================
--- trunk/build/kits/jboss-as7/docs/teiid/teiid-releasenotes.html 2012-08-10 17:10:29 UTC (rev 4308)
+++ trunk/build/kits/jboss-as7/docs/teiid/teiid-releasenotes.html 2012-08-10 17:12:21 UTC (rev 4309)
@@ -64,6 +64,7 @@
<li>TEIID-2105 It was an undocumented behavior that is a source did not specify a jndi connection that "java:/name" would be assumed. That is no longer the case. It the source needs a connection, then one must be specified.
<li>TEIID-2127 if ExecutionFactory.isSourceRequired returns true (the default) then not obtaining a connection will for an Execution will result in an error. If an ExecutionFactory does not use a source, then no connection-jndi-name should be
specified and isSourceRequired should return false (see setSourceRequired). If isSourceRequired returns false and a connection-jndi-name is specified, then Teiid will still attempt to obtain a connection, but no exception will be thrown if a connection isn't available.
+ <li>TEIID-2138 the odbc layer will report standard_conforming_strings as on, rather than off to better reflect the string literal handling of Teiid.
<ul>
<h4>from 7.x</h4>
Modified: trunk/engine/src/main/java/org/teiid/query/function/FunctionMethods.java
===================================================================
--- trunk/engine/src/main/java/org/teiid/query/function/FunctionMethods.java 2012-08-10 17:10:29 UTC (rev 4308)
+++ trunk/engine/src/main/java/org/teiid/query/function/FunctionMethods.java 2012-08-10 17:12:21 UTC (rev 4309)
@@ -392,13 +392,9 @@
public static int dayOfWeek(Date x) {
int result = getField(x, Calendar.DAY_OF_WEEK);
if (TimestampWithTimezone.ISO8601_WEEK) {
- result -= 1;
- if (result == 0) {
- return 7;
- }
- return result;
+ return (result + 6) % 7;
}
- return getField(x, Calendar.DAY_OF_WEEK);
+ return result;
}
// ================== Function = dayofyear =====================
Modified: trunk/runtime/src/main/java/org/teiid/transport/PgBackendProtocol.java
===================================================================
--- trunk/runtime/src/main/java/org/teiid/transport/PgBackendProtocol.java 2012-08-10 17:10:29 UTC (rev 4308)
+++ trunk/runtime/src/main/java/org/teiid/transport/PgBackendProtocol.java 2012-08-10 17:12:21 UTC (rev 4309)
@@ -266,7 +266,7 @@
sendParameterStatus("server_encoding", "SQL_ASCII");
sendParameterStatus("server_version", "8.1.4");
sendParameterStatus("session_authorization", this.props.getProperty("user"));
- sendParameterStatus("standard_conforming_strings", "off");
+ sendParameterStatus("standard_conforming_strings", "on");
sendParameterStatus("application_name", this.props.getProperty("application_name", "ODBCClient"));
// TODO PostgreSQL TimeZone
12 years
teiid SVN: r4308 - in trunk: connectors/translator-jdbc/src/main/java/org/teiid/translator/jdbc/postgresql and 1 other directory.
by teiid-commits@lists.jboss.org
Author: shawkins
Date: 2012-08-10 13:10:29 -0400 (Fri, 10 Aug 2012)
New Revision: 4308
Modified:
trunk/build/kits/jboss-as7/docs/teiid/teiid-releasenotes.html
trunk/connectors/translator-jdbc/src/main/java/org/teiid/translator/jdbc/postgresql/PostgreSQLExecutionFactory.java
Log:
TEIID-2036 adding pg
Modified: trunk/build/kits/jboss-as7/docs/teiid/teiid-releasenotes.html
===================================================================
--- trunk/build/kits/jboss-as7/docs/teiid/teiid-releasenotes.html 2012-08-10 14:52:39 UTC (rev 4307)
+++ trunk/build/kits/jboss-as7/docs/teiid/teiid-releasenotes.html 2012-08-10 17:10:29 UTC (rev 4308)
@@ -34,7 +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.
+ <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, PG, and H2 translators are already marked as supporting array types.
</UL>
<h2><a name="Compatibility">Compatibility Issues</a></h2>
Modified: trunk/connectors/translator-jdbc/src/main/java/org/teiid/translator/jdbc/postgresql/PostgreSQLExecutionFactory.java
===================================================================
--- trunk/connectors/translator-jdbc/src/main/java/org/teiid/translator/jdbc/postgresql/PostgreSQLExecutionFactory.java 2012-08-10 14:52:39 UTC (rev 4307)
+++ trunk/connectors/translator-jdbc/src/main/java/org/teiid/translator/jdbc/postgresql/PostgreSQLExecutionFactory.java 2012-08-10 17:10:29 UTC (rev 4308)
@@ -542,4 +542,9 @@
return OracleFormatFunctionModifier.supportsLiteral(literal);
}
+ @Override
+ public boolean supportsArrayType() {
+ return true;
+ }
+
}
12 years
teiid SVN: r4307 - in trunk: api/src/main/java/org/teiid/language/visitor and 22 other directories.
by teiid-commits@lists.jboss.org
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$
+ }
}
12 years
teiid SVN: r4306 - in trunk/engine/src: test/java/org/teiid/query/sql/visitor and 1 other directory.
by teiid-commits@lists.jboss.org
Author: shawkins
Date: 2012-08-07 19:34:56 -0400 (Tue, 07 Aug 2012)
New Revision: 4306
Added:
trunk/engine/src/test/java/org/teiid/query/sql/visitor/TestCorrelatedReferenceCollectorVisitor.java
Modified:
trunk/engine/src/main/java/org/teiid/query/sql/visitor/CorrelatedReferenceCollectorVisitor.java
Log:
TEIID-1374 Added removal of intermediate groups to ensure that we get a proper set of references.
Modified: trunk/engine/src/main/java/org/teiid/query/sql/visitor/CorrelatedReferenceCollectorVisitor.java
===================================================================
--- trunk/engine/src/main/java/org/teiid/query/sql/visitor/CorrelatedReferenceCollectorVisitor.java 2012-08-07 17:43:21 UTC (rev 4305)
+++ trunk/engine/src/main/java/org/teiid/query/sql/visitor/CorrelatedReferenceCollectorVisitor.java 2012-08-07 23:34:56 UTC (rev 4306)
@@ -23,12 +23,17 @@
package org.teiid.query.sql.visitor;
import java.util.Collection;
+import java.util.HashSet;
import java.util.List;
+import java.util.Set;
import org.teiid.query.sql.LanguageObject;
import org.teiid.query.sql.LanguageVisitor;
-import org.teiid.query.sql.navigator.DeepPreOrderNavigator;
-import org.teiid.query.sql.symbol.*;
+import org.teiid.query.sql.lang.Query;
+import org.teiid.query.sql.navigator.PreOrPostOrderNavigator;
+import org.teiid.query.sql.symbol.ElementSymbol;
+import org.teiid.query.sql.symbol.GroupSymbol;
+import org.teiid.query.sql.symbol.Reference;
/**
@@ -79,11 +84,29 @@
* that the client (outer query) is interested in references to from the correlated subquery
* @param correlatedReferences List of References collected
*/
- public static final void collectReferences(LanguageObject obj, Collection<GroupSymbol> groupSymbols, List<Reference> correlatedReferences){
+ public static final void collectReferences(final LanguageObject obj, final Collection<GroupSymbol> groupSymbols, List<Reference> correlatedReferences){
+ final Set<GroupSymbol> groups = new HashSet<GroupSymbol>(groupSymbols);
+ CorrelatedReferenceCollectorVisitor visitor =
+ new CorrelatedReferenceCollectorVisitor(groups, correlatedReferences);
+ obj.acceptVisitor(new PreOrPostOrderNavigator(visitor, PreOrPostOrderNavigator.PRE_ORDER, true) {
- CorrelatedReferenceCollectorVisitor visitor =
- new CorrelatedReferenceCollectorVisitor(groupSymbols, correlatedReferences);
- DeepPreOrderNavigator.doVisit(obj, visitor);
+ @Override
+ public void visit(Query query) {
+ //don't allow confusion with deep nesting by removing intermediate groups
+ List<GroupSymbol> fromGroups = null;
+ if (query != obj && query.getFrom() != null) {
+ fromGroups = query.getFrom().getGroups();
+ if (!groups.removeAll(fromGroups)) {
+ fromGroups = null;
+ }
+ }
+ super.visit(query);
+ if (fromGroups != null) {
+ fromGroups.retainAll(groupSymbols);
+ groups.addAll(fromGroups);
+ }
+ }
+ });
}
}
Added: trunk/engine/src/test/java/org/teiid/query/sql/visitor/TestCorrelatedReferenceCollectorVisitor.java
===================================================================
--- trunk/engine/src/test/java/org/teiid/query/sql/visitor/TestCorrelatedReferenceCollectorVisitor.java (rev 0)
+++ trunk/engine/src/test/java/org/teiid/query/sql/visitor/TestCorrelatedReferenceCollectorVisitor.java 2012-08-07 23:34:56 UTC (rev 4306)
@@ -0,0 +1,56 @@
+/*
+ * 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.visitor;
+
+import static org.junit.Assert.*;
+
+import java.util.Arrays;
+import java.util.LinkedList;
+
+import org.junit.Test;
+import org.teiid.query.resolver.TestResolver;
+import org.teiid.query.resolver.util.ResolverUtil;
+import org.teiid.query.rewriter.QueryRewriter;
+import org.teiid.query.sql.lang.Command;
+import org.teiid.query.sql.lang.ExistsCriteria;
+import org.teiid.query.sql.lang.Query;
+import org.teiid.query.sql.symbol.GroupSymbol;
+import org.teiid.query.sql.symbol.Reference;
+import org.teiid.query.unittest.RealMetadataFactory;
+
+@SuppressWarnings("nls")
+public class TestCorrelatedReferenceCollectorVisitor {
+
+ @Test public void testDeepNesting() throws Exception {
+ String sql = "select * from bqt1.smalla where exists (select intnum from bqt1.smalla x where smalla.intnum = x.intnum and exists (select intnum from bqt1.smalla where exists (select intnum from bqt1.smalla x where smalla.intnum = x.intnum)))";
+ Command command = TestResolver.helpResolve(sql, RealMetadataFactory.exampleBQTCached());
+ command = QueryRewriter.rewrite(command, RealMetadataFactory.exampleBQTCached(), null);
+ command = ((ExistsCriteria)((Query)command).getCriteria()).getCommand();
+ LinkedList<Reference> correlatedReferences = new LinkedList<Reference>();
+ GroupSymbol gs = new GroupSymbol("bqt1.smalla");
+ ResolverUtil.resolveGroup(gs, RealMetadataFactory.exampleBQTCached());
+ CorrelatedReferenceCollectorVisitor.collectReferences(command, Arrays.asList(gs), correlatedReferences);
+ assertEquals(1, correlatedReferences.size());
+ }
+
+}
Property changes on: trunk/engine/src/test/java/org/teiid/query/sql/visitor/TestCorrelatedReferenceCollectorVisitor.java
___________________________________________________________________
Added: svn:mime-type
+ text/plain
12 years
teiid SVN: r4305 - in trunk: engine/src/main/java/org/teiid/query/metadata and 5 other directories.
by teiid-commits@lists.jboss.org
Author: shawkins
Date: 2012-08-07 13:43:21 -0400 (Tue, 07 Aug 2012)
New Revision: 4305
Modified:
trunk/engine/src/main/java/org/teiid/query/QueryPlugin.java
trunk/engine/src/main/java/org/teiid/query/metadata/MetadataValidator.java
trunk/engine/src/main/java/org/teiid/query/optimizer/relational/rules/CapabilitiesUtil.java
trunk/engine/src/main/java/org/teiid/query/resolver/ProcedureContainerResolver.java
trunk/engine/src/main/java/org/teiid/query/resolver/QueryResolver.java
trunk/engine/src/main/resources/org/teiid/query/i18n.properties
trunk/engine/src/test/java/org/teiid/query/metadata/TestMetadataValidator.java
trunk/test-integration/common/src/test/java/org/teiid/jdbc/TestLocalConnections.java
Log:
TEIID-2136 allowing virtual entries on physical models
Modified: trunk/engine/src/main/java/org/teiid/query/QueryPlugin.java
===================================================================
--- trunk/engine/src/main/java/org/teiid/query/QueryPlugin.java 2012-08-07 17:25:38 UTC (rev 4304)
+++ trunk/engine/src/main/java/org/teiid/query/QueryPlugin.java 2012-08-07 17:43:21 UTC (rev 4305)
@@ -493,9 +493,7 @@
TEIID31071,
TEIID31072,
TEIID31073,
- TEIID31074,
TEIID31075,
- TEIID31076,
TEIID31077,
TEIID31078,
TEIID31079,
Modified: trunk/engine/src/main/java/org/teiid/query/metadata/MetadataValidator.java
===================================================================
--- trunk/engine/src/main/java/org/teiid/query/metadata/MetadataValidator.java 2012-08-07 17:25:38 UTC (rev 4304)
+++ trunk/engine/src/main/java/org/teiid/query/metadata/MetadataValidator.java 2012-08-07 17:43:21 UTC (rev 4305)
@@ -107,10 +107,6 @@
for (Schema schema:store.getSchemaList()) {
ModelMetaData model = vdb.getModel(schema.getName());
for (Table t:schema.getTables().values()) {
- if (t.isVirtual() && model.isSource()) {
- metadataValidator.log(report, model, QueryPlugin.Util.gs(QueryPlugin.Event.TEIID31074, t.getName(), model.getName()));
- }
-
if (t.isPhysical() && !model.isSource()) {
metadataValidator.log(report, model, QueryPlugin.Util.gs(QueryPlugin.Event.TEIID31075, t.getName(), model.getName()));
}
@@ -131,10 +127,6 @@
metadataValidator.log(report, model, QueryPlugin.Util.gs(QueryPlugin.Event.TEIID31106, p.getFullName(), param.getName()));
}
}
- if (p.isVirtual() && model.isSource()) {
- metadataValidator.log(report, model, QueryPlugin.Util.gs(QueryPlugin.Event.TEIID31076, p.getName(), model.getName()));
- }
-
if (!p.isVirtual() && !model.isSource()) {
metadataValidator.log(report, model, QueryPlugin.Util.gs(QueryPlugin.Event.TEIID31077, p.getName(), model.getName()));
}
Modified: trunk/engine/src/main/java/org/teiid/query/optimizer/relational/rules/CapabilitiesUtil.java
===================================================================
--- trunk/engine/src/main/java/org/teiid/query/optimizer/relational/rules/CapabilitiesUtil.java 2012-08-07 17:25:38 UTC (rev 4304)
+++ trunk/engine/src/main/java/org/teiid/query/optimizer/relational/rules/CapabilitiesUtil.java 2012-08-07 17:43:21 UTC (rev 4305)
@@ -32,6 +32,7 @@
import org.teiid.core.types.DataTypeManager;
import org.teiid.language.SortSpecification.NullOrdering;
import org.teiid.metadata.Schema;
+import org.teiid.metadata.FunctionMethod.PushDown;
import org.teiid.query.function.FunctionLibrary;
import org.teiid.query.metadata.QueryMetadataInterface;
import org.teiid.query.optimizer.capabilities.CapabilitiesFinder;
@@ -220,7 +221,7 @@
public static boolean supportsScalarFunction(Object modelID, Function function, QueryMetadataInterface metadata, CapabilitiesFinder capFinder)
throws QueryMetadataException, TeiidComponentException {
- if (metadata.isVirtualModel(modelID)){
+ if (metadata.isVirtualModel(modelID) || function.getFunctionDescriptor().getMethod().getPushdown() == PushDown.CANNOT_PUSHDOWN){
return false;
}
@@ -244,7 +245,7 @@
return caps.supportsConvert(DataTypeManager.getTypeCode(fromType), DataTypeManager.getTypeCode(targetType));
}
} else if (!isSameConnector(modelID, schema, metadata, capFinder)) {
- return false; //not the right schema
+ return caps.supportsFunction(function.getFunctionDescriptor().getMethod().getFullName());
}
return true;
Modified: trunk/engine/src/main/java/org/teiid/query/resolver/ProcedureContainerResolver.java
===================================================================
--- trunk/engine/src/main/java/org/teiid/query/resolver/ProcedureContainerResolver.java 2012-08-07 17:25:38 UTC (rev 4304)
+++ trunk/engine/src/main/java/org/teiid/query/resolver/ProcedureContainerResolver.java 2012-08-07 17:43:21 UTC (rev 4305)
@@ -146,7 +146,7 @@
private String getPlan(QueryMetadataInterface metadata, ProcedureContainer procCommand)
throws TeiidComponentException, QueryMetadataException,
QueryResolverException {
- if(!procCommand.getGroup().isTempGroupSymbol() && metadata.isVirtualGroup(procCommand.getGroup().getMetadataID())) {
+ if(!procCommand.getGroup().isTempTable() && metadata.isVirtualGroup(procCommand.getGroup().getMetadataID())) {
String plan = getPlan(metadata, procCommand.getGroup());
if (plan == null && !metadata.isProcedure(procCommand.getGroup().getMetadataID())) {
int type = procCommand.getType();
Modified: trunk/engine/src/main/java/org/teiid/query/resolver/QueryResolver.java
===================================================================
--- trunk/engine/src/main/java/org/teiid/query/resolver/QueryResolver.java 2012-08-07 17:25:38 UTC (rev 4304)
+++ trunk/engine/src/main/java/org/teiid/query/resolver/QueryResolver.java 2012-08-07 17:43:21 UTC (rev 4305)
@@ -492,7 +492,7 @@
public static boolean isView(GroupSymbol virtualGroup,
QueryMetadataInterface qmi) throws TeiidComponentException,
QueryMetadataException {
- return !virtualGroup.isTempGroupSymbol() && qmi.isVirtualGroup(virtualGroup.getMetadataID()) && qmi.isVirtualModel(qmi.getModelID(virtualGroup.getMetadataID()));
+ return !(virtualGroup.getMetadataID() instanceof TempMetadataID) && qmi.isVirtualGroup(virtualGroup.getMetadataID());// && qmi.isVirtualModel(qmi.getModelID(virtualGroup.getMetadataID()));
}
private static UpdateType determineType(String plan) {
Modified: trunk/engine/src/main/resources/org/teiid/query/i18n.properties
===================================================================
--- trunk/engine/src/main/resources/org/teiid/query/i18n.properties 2012-08-07 17:25:38 UTC (rev 4304)
+++ trunk/engine/src/main/resources/org/teiid/query/i18n.properties 2012-08-07 17:43:21 UTC (rev 4305)
@@ -984,9 +984,7 @@
TEIID31071=Invalid table; Table {0} has no columns defined
TEIID31072=Invalid Procedure {0}; No return has been defined.
TEIID31073=Invalid functions; {0}
-TEIID31074=View table {0} is only allowed in VIRTUAL Model; {1} is defined as PHYSICAL model
TEIID31075=Foreign table {0} is only allowed to be defined on PHYSICAL model; {1} is defined as VIRTUAL model.
-TEIID31076=Virtual procedure {0} is only allowed to be defined on VIRTUAL model; {1} is defined as PHYSICAL model.
TEIID31077=Source Stored procedure {0} is only allowed to be defined on PHYSICAL model; {1} is defined as VIRTUAL model.
TEIID31078=Pushdown function {0} must be defined on PHYSICAL model; {1} is VIRTUAL model.
TEIID31079=View {0} is not defined by a query expression.
Modified: trunk/engine/src/test/java/org/teiid/query/metadata/TestMetadataValidator.java
===================================================================
--- trunk/engine/src/test/java/org/teiid/query/metadata/TestMetadataValidator.java 2012-08-07 17:25:38 UTC (rev 4304)
+++ trunk/engine/src/test/java/org/teiid/query/metadata/TestMetadataValidator.java 2012-08-07 17:43:21 UTC (rev 4305)
@@ -76,7 +76,7 @@
buildModel("pm1", true, this.vdb, this.store, ddl);
ValidatorReport report = new ValidatorReport();
new MetadataValidator.SourceModelArtifacts().execute(vdb, store, report, new MetadataValidator());
- assertTrue(printError(report), report.hasItems());
+ assertFalse(printError(report), report.hasItems());
}
private String printError(ValidatorReport report) {
Modified: trunk/test-integration/common/src/test/java/org/teiid/jdbc/TestLocalConnections.java
===================================================================
--- trunk/test-integration/common/src/test/java/org/teiid/jdbc/TestLocalConnections.java 2012-08-07 17:25:38 UTC (rev 4304)
+++ trunk/test-integration/common/src/test/java/org/teiid/jdbc/TestLocalConnections.java 2012-08-07 17:43:21 UTC (rev 4305)
@@ -67,7 +67,7 @@
private final class SimpleUncaughtExceptionHandler implements
UncaughtExceptionHandler {
- Throwable t;
+ volatile Throwable t;
@Override
public void uncaughtException(Thread arg0, Throwable arg1) {
@@ -248,16 +248,14 @@
if (t.isAlive()) {
fail();
}
-
+ if (handler.t != null) {
+ throw handler.t;
+ }
for (int i = 0; !server.getDqp().getRequests().isEmpty() && i < 40; i++) {
//the concurrent modification may not be seen initially
Thread.sleep(50);
}
assertTrue(server.getDqp().getRequests().isEmpty());
-
- if (handler.t != null) {
- throw handler.t;
- }
}
@Test public void testWait() throws Throwable {
12 years
teiid SVN: r4304 - in trunk: engine/src/main/javacc/org/teiid/query/parser and 1 other directory.
by teiid-commits@lists.jboss.org
Author: shawkins
Date: 2012-08-07 13:25:38 -0400 (Tue, 07 Aug 2012)
New Revision: 4304
Modified:
trunk/build/kits/jboss-as7/docs/teiid/teiid-releasenotes.html
trunk/engine/src/main/javacc/org/teiid/query/parser/SQLParser.jj
Log:
TEIID-2113 minor corrections
Modified: trunk/build/kits/jboss-as7/docs/teiid/teiid-releasenotes.html
===================================================================
--- trunk/build/kits/jboss-as7/docs/teiid/teiid-releasenotes.html 2012-08-07 13:59:20 UTC (rev 4303)
+++ trunk/build/kits/jboss-as7/docs/teiid/teiid-releasenotes.html 2012-08-07 17:25:38 UTC (rev 4304)
@@ -32,7 +32,7 @@
<LI>TEIID-2105 <B>Improved VDB loading</B> - vdb loading logic was refined to make administration easier. ExecutionFactory now has is/setSourceRequiredForMetadata() to indicate whether a source connection is needed for the getMetadata call.
<LI>TEIID-1598 <B>Translator Result Caching</B> - translators can interact with the result set caching facility via a CacheDirective. See the Developer's Guide for more.
<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 i.e. -col1, the FOR keyword is optional for TEXTAGG,
+ <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.
</UL>
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 13:59:20 UTC (rev 4303)
+++ trunk/engine/src/main/javacc/org/teiid/query/parser/SQLParser.jj 2012-08-07 17:25:38 UTC (rev 4304)
@@ -1459,7 +1459,7 @@
/*
name=named parameter list
description=A list of named parameters.
-example={code:sql}param1 := 'x', param2 := 1{code}
+example={code:sql}param1 => 'x', param2 => 1{code}
*/
void executeNamedParams(ParseInfo info, StoredProcedure storedProcedure) :
{
12 years
teiid SVN: r4303 - trunk/build/kits/jboss-as7/docs/teiid.
by teiid-commits@lists.jboss.org
Author: shawkins
Date: 2012-08-07 09:59:20 -0400 (Tue, 07 Aug 2012)
New Revision: 4303
Modified:
trunk/build/kits/jboss-as7/docs/teiid/teiid-releasenotes.html
Log:
TEIID-2127 adding a release note to describe the change in behavior.
Modified: trunk/build/kits/jboss-as7/docs/teiid/teiid-releasenotes.html
===================================================================
--- trunk/build/kits/jboss-as7/docs/teiid/teiid-releasenotes.html 2012-08-07 13:49:31 UTC (rev 4302)
+++ trunk/build/kits/jboss-as7/docs/teiid/teiid-releasenotes.html 2012-08-07 13:59:20 UTC (rev 4303)
@@ -61,6 +61,8 @@
<li>transport ssl config no longer uses the enabled attribute. Use mode=disabled to disable the usage of encryption.
<li>TEIID-2105 If a MetadataRepository throws a RuntimeException during load, that will be treated as a non-recoverable error and the VDB will have a FAILED status.
<li>TEIID-2105 It was an undocumented behavior that is a source did not specify a jndi connection that "java:/name" would be assumed. That is no longer the case. It the source needs a connection, then one must be specified.
+ <li>TEIID-2127 if ExecutionFactory.isSourceRequired returns true (the default) then not obtaining a connection will for an Execution will result in an error. If an ExecutionFactory does not use a source, then no connection-jndi-name should be
+specified and isSourceRequired should return false (see setSourceRequired). If isSourceRequired returns false and a connection-jndi-name is specified, then Teiid will still attempt to obtain a connection, but no exception will be thrown if a connection isn't available.
<ul>
<h4>from 7.x</h4>
12 years
teiid SVN: r4302 - trunk/engine/src/main/javacc/org/teiid/query/parser.
by teiid-commits@lists.jboss.org
Author: shawkins
Date: 2012-08-07 09:49:31 -0400 (Tue, 07 Aug 2012)
New Revision: 4302
Modified:
trunk/engine/src/main/javacc/org/teiid/query/parser/SQLParser.jj
Log:
TEIID-2113 changing the set clause list to not use a java production
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 13:41:48 UTC (rev 4301)
+++ trunk/engine/src/main/javacc/org/teiid/query/parser/SQLParser.jj 2012-08-07 13:49:31 UTC (rev 4302)
@@ -1310,23 +1310,24 @@
{
SetClauseList using = new SetClauseList();
String element = null;
+ Expression value = null;
}
{
element = id()
<EQ>
+ value = expression(info)
{
String symbolName = shortName?validateElementName(element):element;
ElementSymbol symbol = new ElementSymbol(symbolName);
- Expression value = expression(info);
using.addClause(symbol, value);
}
(<COMMA>
element = id()
<EQ>
+ value = expression(info)
{
symbolName = shortName?validateElementName(element):element;
symbol = new ElementSymbol(symbolName);
- value = expression(info);
using.addClause(symbol, value);
}
)*
12 years
teiid SVN: r4301 - in trunk: engine/src/main/java/org/teiid/query/parser and 4 other directories.
by teiid-commits@lists.jboss.org
Author: shawkins
Date: 2012-08-07 09:41:48 -0400 (Tue, 07 Aug 2012)
New Revision: 4301
Modified:
trunk/build/kits/jboss-as7/docs/teiid/teiid-releasenotes.html
trunk/engine/src/main/java/org/teiid/query/parser/SQLParserUtil.java
trunk/engine/src/main/javacc/org/teiid/query/parser/SQLParser.jj
trunk/engine/src/test/java/org/teiid/query/parser/TestParser.java
trunk/engine/src/test/java/org/teiid/query/validator/TestValidator.java
trunk/test-integration/common/src/test/java/org/teiid/jdbc/TestDynamicImportedMetaData.java
Log:
TEIID-2113 adding additional doc features and minor parsing improvements
Modified: trunk/build/kits/jboss-as7/docs/teiid/teiid-releasenotes.html
===================================================================
--- trunk/build/kits/jboss-as7/docs/teiid/teiid-releasenotes.html 2012-08-06 20:18:00 UTC (rev 4300)
+++ trunk/build/kits/jboss-as7/docs/teiid/teiid-releasenotes.html 2012-08-07 13:41:48 UTC (rev 4301)
@@ -32,6 +32,8 @@
<LI>TEIID-2105 <B>Improved VDB loading</B> - vdb loading logic was refined to make administration easier. ExecutionFactory now has is/setSourceRequiredForMetadata() to indicate whether a source connection is needed for the getMetadata call.
<LI>TEIID-1598 <B>Translator Result Caching</B> - translators can interact with the result set caching facility via a CacheDirective. See the Developer's Guide for more.
<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 i.e. -col1, the FOR keyword is optional for TEXTAGG,
+and the BNF documentation was dramatically improved.
</UL>
<h2><a name="Compatibility">Compatibility Issues</a></h2>
Modified: trunk/engine/src/main/java/org/teiid/query/parser/SQLParserUtil.java
===================================================================
--- trunk/engine/src/main/java/org/teiid/query/parser/SQLParserUtil.java 2012-08-06 20:18:00 UTC (rev 4300)
+++ trunk/engine/src/main/java/org/teiid/query/parser/SQLParserUtil.java 2012-08-07 13:41:48 UTC (rev 4301)
@@ -45,6 +45,7 @@
import org.teiid.query.sql.lang.ExistsCriteria.SubqueryHint;
import org.teiid.query.sql.proc.Block;
import org.teiid.query.sql.proc.Statement;
+import org.teiid.query.sql.symbol.Expression;
import org.teiid.query.sql.symbol.GroupSymbol;
import org.teiid.translator.TranslatorException;
@@ -54,6 +55,21 @@
public static final boolean DECIMAL_AS_DOUBLE = PropertiesUtils.getBooleanProperty(System.getProperties(), "org.teiid.decimalAsDouble", false); //$NON-NLS-1$
+ String prependSign(String sign, String literal) {
+ if (sign != null && sign.charAt(0) == '-') {
+ return sign + literal;
+ }
+ return literal;
+ }
+
+ void convertToParameters(List<Expression> values, StoredProcedure storedProcedure) {
+ for (Expression value : values) {
+ SPParameter parameter = new SPParameter(storedProcedure.getParameters().size() + 1, value);
+ parameter.setParameterType(SPParameter.IN);
+ storedProcedure.setParameter(parameter);
+ }
+ }
+
String matchesAny(String arg, String ... expected) {
for (String string : expected) {
if (string.equalsIgnoreCase(arg)) {
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-06 20:18:00 UTC (rev 4300)
+++ trunk/engine/src/main/javacc/org/teiid/query/parser/SQLParser.jj 2012-08-07 13:41:48 UTC (rev 4301)
@@ -16,6 +16,7 @@
import java.math.BigInteger;
import java.util.*;
import org.teiid.core.types.*;
+import org.teiid.core.util.StringUtil;
import org.teiid.query.QueryPlugin;
import org.teiid.query.sql.LanguageObject;
import org.teiid.query.sql.lang.*;
@@ -413,7 +414,6 @@
| <FIRST: "first">
| <LAST: "last">
| <NEXT: "next">
-| <FN: "fn">
| <SUBSTRING: "substring">
| <EXTRACT: "extract">
| <TO_CHARS: "to_chars">
@@ -444,7 +444,6 @@
| <PASSING: "passing">
| <NAME: "name">
| <ENCODING: "encoding">
-| <OJ: "oj">
| <COLUMNS: "columns">
| <DELIMITER: "delimiter">
| <QUOTE: "quote">
@@ -452,33 +451,55 @@
| <NULLS: "nulls">
}
+/*
+name=all in group identifier
+*/
+TOKEN : { < ALL_IN_GROUP: <ID> <PERIOD> <STAR> > }
+/*
+name=identifier
+*/
+TOKEN : { < ID: <QUOTED_ID> (<PERIOD> <QUOTED_ID>)* > }
+TOKEN : { < #QUOTED_ID: <ID_PART> | ("\"" (("\"\"") | ~["\""] )+ "\"") > }
+TOKEN : { < #ID_PART: (("@" | "#" | <LETTER>) (<LETTER> | "_" | <DIGIT>)*) > }
+/*
+name=escaped function
+*/
+TOKEN : { < ESCAPEDFUNCTION: "{" "fn" > }
+/*
+name=escaped join
+*/
+TOKEN : { < ESCAPEDJOIN: "{" "oj" > }
+/*
+name=escaped type
+*/
+TOKEN : { < ESCAPEDTYPE: "{" ("d" | "t" | "ts" | "b") > }
+/*
+name=decimal numeric literal
+*/
+TOKEN : { < DECIMALVAL: (<DIGIT>)* <PERIOD> <UNSIGNEDINTEGER> > }
+/*
+name=approximate numeric literal
+*/
+TOKEN : { < FLOATVAL: <DIGIT> <PERIOD> <UNSIGNEDINTEGER>
+ ["e", "E"] (<PLUS>|<MINUS>)? <UNSIGNEDINTEGER> > }
+/*
+name=string literal
+*/
+TOKEN : { < STRINGVAL: (("N"|"E")? "'" ( ("''") | ~["'"] )* "'") > }
+TOKEN : { < #LETTER: (["a"-"z","A"-"Z"] | ["\u0153"-"\ufffd"]) > }
+TOKEN : { < #DIGIT: ["0"-"9"] > }
+/*
+name=unsigned integer literal
+*/
+TOKEN : { < UNSIGNEDINTEGER: (<DIGIT>)+ > }
+/*
+name=binary string literal
+*/
+TOKEN : { < BINARYSTRINGVAL: ("X"|"x" "'" ( <HEXIT><HEXIT> )+ "'") > }
+TOKEN : { < #HEXIT: (["a"-"f","A"-"F"] | <DIGIT> ) > }
-TOKEN : /* User variables and literals */
+TOKEN :
{
- < ALL_IN_GROUP: <ID> <PERIOD> <STAR> >
-
-| < ID: <QUOTED_ID> (<PERIOD> <QUOTED_ID>)* >
-| < #QUOTED_ID: <ID_PART> | ("\"" (("\"\"") | ~["\""] )+ "\"") >
-| < #ID_PART: (("@" | "#" | <LETTER>) (<LETTER> | "_" | <DIGIT>)*) >
-
-| < DATETYPE: "{" "d" >
-| < TIMETYPE: "{" "t" >
-| < TIMESTAMPTYPE: "{" "ts" >
-| < BOOLEANTYPE: "{" "b" >
-| < POS_REF: ["$"] (<DIGIT>)+ >
-| < INTEGERVAL: (<MINUS>)?(<DIGIT>)+ >
-| < DECIMALVAL: (<MINUS>)? (<DIGIT>)* <PERIOD> (<DIGIT>)+ >
-| < FLOATVAL: (<MINUS>)? <DIGIT> <PERIOD> (<DIGIT>)+
- ["e", "E"] (["+","-"])? (<DIGIT>)+ >
-| < STRINGVAL: (("N"|"E")? "'" ( ("''") | ~["'"] )* "'") >
-| < #LETTER: (["a"-"z","A"-"Z"] | ["\u0153"-"\ufffd"]) >
-| < #DIGIT: ["0"-"9"] >
-| < BINARYSTRINGVAL: ("X"|"x" "'" ( <HEXIT><HEXIT> )+ "'") >
-| < #HEXIT: (["a"-"f","A"-"F"] | <DIGIT> ) >
-}
-
-TOKEN : /* Punctuation */
-{
<COMMA: ",">
| <PERIOD: ".">
| <LPAREN: "(">
@@ -505,30 +526,42 @@
| <CONCAT_OP: "||">
}
-//----------------------------------------------------
-//----------------------------------------------------
-
+/*
+name=string
+description=A string literal value. Use '' to escape ' in the string.
+example={code:sql}'a string'{code}\n{code:sql}'it''s a string'{code}
+*/
String stringVal() :
{
Token t = null;
}
{
- (t = <STRINGVAL>)
+ t = <STRINGVAL>
{
return normalizeStringLiteral(t.image);
}
}
+/*
+name=non-reserved identifier
+description=Allows non-reserved keywords to be parsed as identifiers
+example=SELECT *COUNT* FROM ...
+*/
Token nonReserved() :
{
}
{
- (<INSTEAD>|<VIEW>|<ENABLED>|<DISABLED>|<KEY>|<SERIAL>|<TEXTAGG>|<COUNT>|<ROW_NUMBER>|<RANK>|<DENSE_RANK>|<SUM>|<AVG>|<MIN>|<MAX>|<EVERY>|<STDDEV_POP>|<STDDEV_SAMP>|<VAR_SAMP>|<VAR_POP>|<DOCUMENT>|<CONTENT>|<TRIM>|<EMPTY>|<ORDINALITY>|<PATH>|<FIRST>|<LAST>|<NEXT>|<FN>|<SUBSTRING>|<EXTRACT>|<TO_CHARS>|<TO_BYTES>|<TIMESTAMPADD>|<TIMESTAMPDIFF>|<QUERYSTRING>|<NAMESPACE>|<RESULT>|<INDEX>|<ACCESSPATTERN>|<AUTO_INCREMENT>|<WELLFORMED>|<SQL_TSI_FRAC_SECOND>|<SQL_TSI_SECOND>|<SQL_TSI_MINUTE>|<SQL_TSI_HOUR>|<SQL_TSI_DAY>|<SQL_TSI_WEEK>|<SQL_TSI_MONTH>|<SQL_TSI_QUARTER>|<SQL_TSI_YEAR>|<TEXTTABLE>|<ARRAYTABLE>|<SELECTOR>|<SKIP_KEYWORD>|<WIDTH>|<PASSING>|<NAME>|<ENCODING>|<OJ>|<COLUMNS>|<DELIMITER>|<QUOTE>|<HEADER>|<NULLS>)
+ (<INSTEAD>|<VIEW>|<ENABLED>|<DISABLED>|<KEY>|<SERIAL>|<TEXTAGG>|<COUNT>|<ROW_NUMBER>|<RANK>|<DENSE_RANK>|<SUM>|<AVG>|<MIN>|<MAX>|<EVERY>|<STDDEV_POP>|<STDDEV_SAMP>|<VAR_SAMP>|<VAR_POP>|<DOCUMENT>|<CONTENT>|<TRIM>|<EMPTY>|<ORDINALITY>|<PATH>|<FIRST>|<LAST>|<NEXT>|<SUBSTRING>|<EXTRACT>|<TO_CHARS>|<TO_BYTES>|<TIMESTAMPADD>|<TIMESTAMPDIFF>|<QUERYSTRING>|<NAMESPACE>|<RESULT>|<INDEX>|<ACCESSPATTERN>|<AUTO_INCREMENT>|<WELLFORMED>|<SQL_TSI_FRAC_SECOND>|<SQL_TSI_SECOND>|<SQL_TSI_MINUTE>|<SQL_TSI_HOUR>|<SQL_TSI_DAY>|<SQL_TSI_WEEK>|<SQL_TSI_MONTH>|<SQL_TSI_QUARTER>|<SQL_TSI_YEAR>|<TEXTTABLE>|<ARRAYTABLE>|<SELECTOR>|<SKIP_KEYWORD>|<WIDTH>|<PASSING>|<NAME>|<ENCODING>|<COLUMNS>|<DELIMITER>|<QUOTE>|<HEADER>|<NULLS>)
{
return getToken(0);
}
}
+/*
+name=identifier
+description=Partial or full name of a single entity.
+example={code:sql}tbl.col{code}\n{code:sql}"tbl"."col"{code}
+*/
String id() :
{
}
@@ -539,12 +572,9 @@
}
}
-/**
- * Parse any of several command types - this is the main parser entry point.
- * @param info instructions to parse the command
- * @return Parsed command
- * @throws ParseException if parsing failed
- */
+/* TODO: createProcedure should not be here, but is due to all of the legacy tests
+unused=true
+*/
Command command(ParseInfo info) :
{
Command command = null;
@@ -561,6 +591,9 @@
}
}
+/*
+unused=true
+*/
Command designerCommand(ParseInfo info) :
{
Command command = null;
@@ -577,6 +610,11 @@
}
}
+/*
+name=create trigger
+description=Creates a trigger action on the given target.
+example={code:sql}CREATE TRIGGER ON vw INSTEAD OF INSERT AS FOR EACH ROW BEGIN ATOMIC ... END{code}
+*/
Command createTrigger(ParseInfo info) :
{
String target = null;
@@ -598,6 +636,11 @@
}
}
+/*
+name=alter
+description=Alter the given target.
+example={code:sql}ALTER VIEW vw AS SELECT col FROM tbl{code}
+*/
Command alter(ParseInfo info) :
{
String target = null;
@@ -649,6 +692,11 @@
)
}
+/*
+name=for each row trigger action
+description=Defines an action to perform on each row.
+example={code:sql}FOR EACH ROW BEGIN ATOMIC ... END{code}
+*/
TriggerAction forEachRowTriggerAction(ParseInfo info) :
{
Block b = new Block();
@@ -679,6 +727,12 @@
}
}
+/*
+name=directly executable statement
+description=A statement that can be executed at runtime.
+example={code:sql}SELECT * FROM tbl{code}
+index=true
+*/
Command userCommand(ParseInfo info) :
{
Command command = null;
@@ -716,12 +770,11 @@
}
}
-/**
- * Parse drop table command.
- * @param info instructions to parse the command
- * @return Parsed command
- * @throws ParseException if parsing failed
- */
+/*
+name=drop table
+description=Creates a trigger action on the given target.
+example={code:sql}CREATE TRIGGER ON vw INSTEAD OF INSERT AS FOR EACH ROW BEGIN ATOMIC ... END{code}
+*/
Command dropTable(ParseInfo info) :
{
Drop drop = new Drop();
@@ -736,12 +789,11 @@
}
}
-/**
- * Parse create temp table command.
- * @param info instructions to parse the command
- * @return Parsed command
- * @throws ParseException if parsing failed
- */
+/*
+name=create temporary table
+description=Creates a temporary table.
+example={code:sql}CREATE LOCAL TEMPORARY TABLE tmp (col integer){code}
+*/
Command createTempTable(ParseInfo info) :
{
Create create = new Create();
@@ -784,6 +836,11 @@
}
}
+/*
+name=temporary table element
+description=Defines a temporary table column.
+example={code:sql}col string NOT NULL{code}
+*/
Column tableElement(ParseInfo info) :
{
String element = null;
@@ -814,10 +871,11 @@
}
}
-/**
- * Parse error statement
- * @throws ParseException if parsing failed
- */
+/*
+name=raise error statement
+description=Raises an error with the given message.
+example={code:sql}ERROR 'something went wrong'{code}
+*/
RaiseErrorStatement errorStatement(ParseInfo info) :
{
Expression errMsg = null;
@@ -832,10 +890,11 @@
}
}
-/**
- * Parse statement
- * @throws ParseException if parsing failed
- */
+/*
+name=statement
+description=A procedure statement.
+example={code:sql}IF (x = 5) BEGIN ... END{code}
+*/
Statement statement(ParseInfo info) :
{
Statement stmt = null;
@@ -865,6 +924,11 @@
}
}
+/*
+name=delimited statement
+description=A procedure statement terminated by ;.
+example={code:sql}SELECT * FROM tbl;{code}
+*/
Statement delimitedStatement(ParseInfo info) :
{
Statement stmt = null;
@@ -882,6 +946,11 @@
}
}
+/*
+name=compound statement
+description=A procedure statement block contained in BEGIN END.
+example={code:sql}BEGIN NOT ATOMIC ... END{code}
+*/
Block compoundStatement(ParseInfo info) :
{
Statement stmt = null;
@@ -905,10 +974,11 @@
}
}
-/**
- * Parse break statement
- * @throws ParseException if parsing failed
- */
+/*
+name=branching statement
+description=A procedure branching control statement, which typically specifies a label to return control to.
+example={code:sql}BREAK x{code}
+*/
BranchingStatement branchingStatement(ParseInfo info) :
{
BranchingStatement breakStmt = new BranchingStatement();
@@ -930,10 +1000,11 @@
}
}
-/**
- * Parse while statement
- * @throws ParseException if parsing failed
- */
+/*
+name=while statement
+description=A procedure while statement that executes until its condition is false.
+example={code:sql}WHILE (var) BEGIN ... END{code}
+*/
WhileStatement whileStatement(ParseInfo info) :
{
WhileStatement whileStmt = null;
@@ -952,10 +1023,11 @@
}
}
-/**
- * Parse loop statement
- * @throws ParseException if parsing failed
- */
+/*
+name=loop statement
+description=A procedure loop statement that executes over the given cursor.
+example={code:sql}LOOP ON (SELECT * FROM tbl) AS x BEGIN ... END{code}
+*/
LoopStatement loopStatement(ParseInfo info) :
{
LoopStatement loopStmt = null;
@@ -978,10 +1050,11 @@
}
}
-/**
- * Parse if statement
- * @throws ParseException if parsing failed
- */
+/*
+name=if statement
+description=A procedure loop statement that executes over the given cursor.
+example={code:sql}LOOP ON (SELECT * FROM tbl) AS x BEGIN ... END{code}
+*/
IfStatement ifStatement(ParseInfo info) :
{
IfStatement ifStmt = null;
@@ -1004,21 +1077,22 @@
}
}
-/**
- * Parse declare statement
- * @throws ParseException if parsing failed
- */
+/*
+name=declare statement
+description=A procedure declaration statement that creates a variable and optionally assigns a value.
+example={code:sql}DECLARE STRING x := 'a'{code}
+*/
DeclareStatement declareStatement(ParseInfo info) :
{
DeclareStatement declStmt = null;
String var = null;
- Constant type = null;
+ ParsedDataType type = null;
ElementSymbol variableID = null;
LanguageObject value = null;
}
{
<DECLARE>
- type = dataType()
+ type = parseDataType()
var = id()
{
variableID = new ElementSymbol(var);
@@ -1029,19 +1103,20 @@
{
if (value instanceof Expression) {
- return new DeclareStatement(variableID, (String)type.getValue(), (Expression)value);
+ return new DeclareStatement(variableID, type.type, (Expression)value);
}
if (value instanceof QueryCommand) {
- return new DeclareStatement(variableID, (String)type.getValue(), new ScalarSubquery((QueryCommand)value));
+ return new DeclareStatement(variableID, type.type, new ScalarSubquery((QueryCommand)value));
}
- return new DeclareStatement(variableID, (String)type.getValue(), (Command)value);
+ return new DeclareStatement(variableID, type.type, (Command)value);
}
}
-/**
- * Parse assignment statement
- * @throws ParseException if parsing failed
- */
+/*
+name=assignment statement
+description=Assigns a variable a value in a procedure.
+example={code:sql}x := 'b'{code}
+*/
AssignmentStatement assignStatement(ParseInfo info) :
{
LanguageObject value = null;
@@ -1067,11 +1142,10 @@
}
}
-/**
- * Parse operand of assignment statement, which can be nested
- * arbitrarily deeply in parentheses.
- * @throws ParseException if parsing failed
- */
+/*
+name=assignment statement operand
+description=A value or command that can be used in an assignment. {note}All assigments except for expression are deprecated.{note}
+*/
LanguageObject assignStatementOperand(ParseInfo info) :
{
LanguageObject value = null;
@@ -1091,10 +1165,10 @@
}
}
-/**
- * Parse sql statement
- * @throws ParseException if parsing failed
- */
+/*
+name=data statement
+description=A procedure statement that executes a SQL statement. An update statement can have its update count accessed via the ROWS_UPDATED variable.
+*/
CommandStatement sqlStatement(ParseInfo info) :
{
CommandStatement cmdStmt = null;
@@ -1127,10 +1201,9 @@
}
}
-/**
- * Parse create update procedure command
- * @throws ParseException if parsing failed
- */
+/*
+unused=true
+*/
CreateProcedureCommand createProcedure(ParseInfo info) :
{
CreateProcedureCommand procCmd =
@@ -1146,6 +1219,12 @@
}
}
+/*
+name=procedure body definition
+description=Defines a procedure body on a Procedure metadata object.
+example={code:sql}CREATE VIRTUAL PROCEDURE BEGIN ... END{code}
+index=true
+*/
CreateProcedureCommand procedureBodyCommand(ParseInfo info) :
{
CreateProcedureCommand procCmd =
@@ -1161,17 +1240,17 @@
}
}
-/**
- * Parse error statement
- * @throws ParseException if parsing failed
- */
+/*
+name=dynamic data statement
+description=A procedure statement that can execute arbitrary sql.
+example={code:sql}EXECUTE IMMEDIATE 'SELECT * FROM tbl' AS x STRING INTO #temp{code}
+*/
DynamicCommand dynamicCommand(ParseInfo info) :
{
Expression sql = null;
String groupID = null;
GroupSymbol group = null;
int updateCount = 0;
- Token updateToken = null;
List<TableFunctionReference.ProjectedColumn> elements = null;
SetClauseList using = null;
DynamicCommand dcStmt = new DynamicCommand();
@@ -1209,12 +1288,9 @@
}
]
[<UPDATE>
- ((updateToken = <INTEGERVAL>)
- {
- updateCount = Integer.parseInt(updateToken.image);
- }
+ (updateCount = intVal()
|
- (<STAR>)
+ <STAR>
{
updateCount = 2;
})
@@ -1225,6 +1301,11 @@
}
}
+/*
+name=set clause list
+description=A list of value assignments.
+example={code:sql}col1 = 'x', col2 = 'y' ...{code}
+*/
SetClauseList setClauseList(boolean shortName, ParseInfo info) :
{
SetClauseList using = new SetClauseList();
@@ -1254,10 +1335,11 @@
}
}
-/**
- * Create elements with datatypes
- * @throws ParseException if parsing failed
- */
+/*
+name=typed element list
+description=A list of typed elements.
+example={code:sql}col1 string, col2 integer ...{code}
+*/
List<TableFunctionReference.ProjectedColumn> createElementsWithTypes(ParseInfo info) :
{
String element = null;
@@ -1284,15 +1366,21 @@
}
}
+/*
+name=callable statement
+description=A callable statement defined using JDBC escape syntax.
+example={code:sql}{? = CALL proc}{code}
+index=true
+*/
StoredProcedure callableStatement(ParseInfo info) :
{
StoredProcedure storedProcedure = new StoredProcedure();
storedProcedure.setCallableStatement(true);
- Token call = null;
String procName = null;
Option option = null;
SPParameter parameter = null;
int parameterIndex = 1;
+ List<Expression> values = null;
}
{
<LBRACE>
@@ -1311,10 +1399,7 @@
//parameters
[<LPAREN>
-
- (
- storedProcedure = executeUnnamedParams(info, storedProcedure, parameterIndex)
- )
+ [values = expressionList(info) { convertToParameters(values, storedProcedure); }]
<RPAREN>
]
<RBRACE>
@@ -1329,15 +1414,16 @@
}
}
-
-/**
- * * Parse stored query command
- * @throws ParseException if parsing failed
- */
+/*
+name=call statement
+description=Executes the procedure with the given parameters.
+example={code:sql}CALL proc('a', 1){code}
+*/
StoredProcedure storedProcedure(ParseInfo info, StoredProcedure storedProcedure) :
{
String procName = null;
Option option = null;
+ List<Expression> values = null;
}
{
(
@@ -1352,9 +1438,9 @@
(
LOOKAHEAD(2)
- storedProcedure = executeNamedParams(info, storedProcedure)
+ executeNamedParams(info, storedProcedure)
|
- storedProcedure = executeUnnamedParams(info, storedProcedure, storedProcedure.getParameters().size() + 1)
+ [values = expressionList(info) { convertToParameters(values, storedProcedure); }]
)
<RPAREN>
@@ -1369,43 +1455,13 @@
}
}
-/**
- * <p>Parse an exec statement with unnamed parameters</p>
- * @throws ParseException if parsing failed
- */
-StoredProcedure executeUnnamedParams(ParseInfo info, StoredProcedure storedProcedure, int parameterIndex) :
+/*
+name=named parameter list
+description=A list of named parameters.
+example={code:sql}param1 := 'x', param2 := 1{code}
+*/
+void executeNamedParams(ParseInfo info, StoredProcedure storedProcedure) :
{
- SPParameter parameter = null;
- Expression value = null;
-}
-{
-
- (value = expression(info)
- {
- parameter = new SPParameter(parameterIndex++, value);
- parameter.setParameterType(SPParameter.IN);
- storedProcedure.setParameter(parameter);
- }
- ( <COMMA>
- value = expression(info)
- {
- parameter = new SPParameter(parameterIndex++, value);
- parameter.setParameterType(SPParameter.IN);
- storedProcedure.setParameter(parameter);
- }
- )*
- )?
- {
- return storedProcedure;
- }
-}
-
-/**
- * <p>Parse an exec statement with named parameters</p>
- * @throws ParseException if parsing failed
- */
-StoredProcedure executeNamedParams(ParseInfo info, StoredProcedure storedProcedure) :
-{
String name = null;
Expression value = null;
SPParameter parameter = null;
@@ -1438,17 +1494,13 @@
}
)*
)
- {
-
- return storedProcedure;
- }
}
-/**
- * Parse an INSERT command
- * @return Parsed insert statement
- * @throws ParseException if parsing failed
- */
+/*
+name=insert statement
+description=Inserts values into the given target.
+example={code:sql}INSERT INTO tbl (col1, col2) VALUES ('a', 1){code}
+*/
Insert insert(ParseInfo info) :
{
Insert insert = new Insert();
@@ -1497,6 +1549,11 @@
}
}
+/*
+name=column list
+description=A list of column references.
+example={code:sql}(col1, col2, ...){code}
+*/
List<ElementSymbol> columnList(boolean validate) :
{
String element = null;
@@ -1526,11 +1583,11 @@
}
}
-/**
- * Parse row values - this is a comma separated list of values.
- * @return List of values, never null
- * @throws ParseException if parsing failed
- */
+/*
+name=expression list
+description=A list of expressions.
+example={code:sql}col1, 'a', ...{code}
+*/
ArrayList<Expression> expressionList(ParseInfo info) :
{
ArrayList<Expression> rowVals = new ArrayList<Expression>(4);
@@ -1552,11 +1609,11 @@
}
}
-/**
- * Parse an UPDATE command
- * @return Parsed update statement
- * @throws ParseException if parsing failed
- */
+/*
+name=update statement
+description=Update values in the given target.
+example={code:sql}UPDATE tbl SET (col1 = 'a') WHERE col2 = 1{code}
+*/
Update update(ParseInfo info) :
{
Update update = new Update();
@@ -1592,12 +1649,11 @@
}
}
-
-/**
- * Parse a DELETE command
- * @return Parsed delete statement
- * @throws ParseException if parsing failed
- */
+/*
+name=delete statement
+description=Delete rows from the given target.
+example={code:sql}DELETE FROM tbl WHERE col2 = 1{code}
+*/
Delete delete(ParseInfo info) :
{
String group = null;
@@ -1622,6 +1678,11 @@
}
}
+/*
+name=query expression
+description=A declarative query for data.
+example={code:sql}SELECT * FROM tbl WHERE col2 = 1{code}
+*/
QueryCommand queryExpression(ParseInfo info) :
{
QueryCommand query = null;
@@ -1648,6 +1709,11 @@
}
}
+/*
+name=with list element
+description=A query expression for use in the enclosing query.
+example={code:sql}X (Y, Z) AS (SELECT 1, 2){code}
+*/
WithQueryCommand withListElement(ParseInfo info) :
{
String name = null;
@@ -1663,6 +1729,11 @@
}
}
+/*
+name=query expression body
+description=The body of a query expression, which can optionally be ordered and limited.
+example={code:sql}SELECT * FROM tbl ORDER BY col1 LIMIT 1{code}
+*/
QueryCommand queryExpressionBody(ParseInfo info) :
{
QueryCommand query = null;
@@ -1691,6 +1762,11 @@
}
}
+/*
+name=query term
+description=Used to establish INTERSECT precedence.
+example={code:sql}SELECT * FROM tbl{code}\n{code:sql}SELECT * FROM tbl1 INTERSECT SELECT * FROM tbl2{code}
+*/
QueryCommand queryTerm(ParseInfo info) :
{
QueryCommand query = null;
@@ -1712,6 +1788,11 @@
}
}
+/*
+name=query primary
+description=A declarative source of rows.
+example={code:sql}TABLE tbl{code}\n{code:sql}SELECT * FROM tbl1{code}
+*/
QueryCommand queryPrimary(ParseInfo info) :
{
QueryCommand query = null;
@@ -1733,11 +1814,11 @@
}
}
-/**
- * Parse a SELECT query
- * @return Parsed query
- * @throws ParseException if parsing failed
- */
+/*
+name=query
+description=A SELECT query.
+example={code:sql}SELECT col1, max(col2) FROM tbl GROUP BY col1{code}
+*/
Query query(ParseInfo info) :
{
Select select = null;
@@ -1770,6 +1851,11 @@
}
}
+/*
+name=into clause
+description=Used to direct the query into a table. {note}This is deprecated. Use INSERT INTO with a query expression instead.{note}
+example={code:sql}INTO tbl{code}
+*/
Into into(ParseInfo info) :
{
String groupID = null;
@@ -1784,18 +1870,10 @@
}
}
-/**
- * <p>Parse a SELECT clause. The select must handle elements, aliased elements
- * (x AS y), group.*, and *. It also must handle an optional DISTINCT at the
- * beginning of the select list. It also must handle a scalar subquery expression
- * in parentheses.</p>
- * <p>Example: "SELECT group.element, group2.element2 AS x, group3.*". </p>
- * <p>Example: "SELECT *". </p>
- * <p>Example: "SELECT DISTINCT a, b, c".</p>
- * <p>Example: "SELECT a, (SELECT b FROM groupC)".</p>
- * <p>Example: "SELECT a, (SELECT b FROM groupC) as d".</p>
- * @return Parsed select
- * @throws ParseException if parsing failed
+/*
+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}
*/
Select select(ParseInfo info) :
{
@@ -1823,6 +1901,11 @@
}
}
+/*
+name=select sublist
+description=An element in the select clause
+example={code:sql}tbl.*{code}\n{code:sql}tbl.col AS x{code}
+*/
Expression selectSymbol(ParseInfo info) :
{
Expression symbol = null;
@@ -1838,6 +1921,11 @@
}
}
+/*
+name=select derived column
+description=A select clause item that selects a single column. {note}This is slightly different than a derived column in that the AS keyword is optional.{note}
+example={code:sql}tbl.col AS x{code}
+*/
Expression selectExpression(ParseInfo info) :
{
Expression expression = null;
@@ -1858,6 +1946,11 @@
}
}
+/*
+name=derived column
+description=An optionally named expression.
+example={code:sql}tbl.col AS x{code}
+*/
DerivedColumn derivedColumn(ParseInfo info) :
{
Expression expression = null;
@@ -1877,6 +1970,11 @@
}
}
+/*
+name=all in group
+description=A select sublist that can select all columns from the given group.
+example={code:sql}tbl.*{code}
+*/
MultipleElementSymbol allInGroupSymbol() :
{
Token allInGroupToken = null;
@@ -1889,6 +1987,11 @@
}
}
+/*
+name=ordered aggreate function
+description=An aggregate function that can optionally be ordered.
+example={code:sql}XMLAGG(col1) ORDER BY col2{code}\n{code:sql}ARRAY_AGG(col1){code}
+*/
AggregateSymbol orderedAgg(ParseInfo info) :
{
Token t = null;
@@ -1909,6 +2012,11 @@
}
}
+/*
+name=text aggreate function
+description=An aggregate function for creating separated value clobs.
+example={code:sql}TEXTAGG (col1 as t1, col2 as t2 DELIMITER ',' HEADER){code}
+*/
AggregateSymbol textAgg(ParseInfo info) :
{
DerivedColumn expression = null;
@@ -1964,6 +2072,11 @@
}
}
+/*
+name=standard aggregate function
+description=A standard aggregate function.
+example={code:sql}COUNT(*){code}
+*/
AggregateSymbol aggregateSymbol(ParseInfo info) :
{
Token func = null;
@@ -2001,6 +2114,11 @@
}
}
+/*
+name=analytic aggregate function
+description=An analytic aggregate function.
+example={code:sql}ROW_NUMBER(){code}
+*/
AggregateSymbol analyticAggregateSymbol(ParseInfo info) :
{
Token func = null;
@@ -2013,7 +2131,11 @@
}
}
-
+/*
+name=filter clause
+description=An aggregate filter clause applied prior to accumulating the value.
+example={code:sql}FILTER (WHERE col1='a'){code}
+*/
Expression filterClause(ParseInfo info) :
{
Expression condition = null;
@@ -2025,16 +2147,11 @@
}
}
-/**
- * <p>Parse a FROM. The from must handle groups, aliased groups or
- * joined groups. This also handles JDBC escape processinf syntax for outer joins.</p>
- * <p>Example: "FROM a, b". </p>
- * <p>Example: "FROM a AS x, b as Y". </p>
- * <p>Example: "FROM a right outer join b, c, d join e".</p>
- * @param from object which is to be updated with the details in the from clause.
- * @return list containing criteria objects.
- * @throws ParseException if parsing failed
- */
+/*
+name=from clause
+description=A query from clause containing a list of table references.
+example={code:sql}FROM a, b{code}\n{code:sql}FROM a right outer join b, c, d join e".</p>{code}
+*/
From from(ParseInfo info) :
{
FromClause clause = null;
@@ -2061,12 +2178,11 @@
}
}
-/**
- * <p>Parse a join predicate clause, which occurs as an element in the FROM clause.
- * The join predicate combines two from clauses with a join.</p>
- * @return Join predicate
- * @throws ParseException if parsing failed
- */
+/*
+name=table reference
+description=An optionally escaped joined table.
+example={code:sql}a{code}\n{code:sql}a inner join b{code}
+*/
FromClause tableReference(ParseInfo info) :
{
FromClause result = null;
@@ -2074,7 +2190,7 @@
{
(
(
- <LBRACE> <OJ>
+ <ESCAPEDJOIN>
result=joinedTable(info)
<RBRACE>
)
@@ -2086,6 +2202,11 @@
}
}
+/*
+name=joined table
+description=A table or join.
+example={code:sql}a{code}\n{code:sql}a inner join b{code}
+*/
FromClause joinedTable(ParseInfo info) :
{
FromClause result = null;
@@ -2107,6 +2228,11 @@
}
}
+/*
+name=cross join
+description=A cross join.
+example={code:sql}a CROSS JOIN b{code}
+*/
JoinPredicate crossJoin(ParseInfo info) :
{
JoinPredicate result = new JoinPredicate();
@@ -2122,6 +2248,11 @@
}
}
+/*
+name=qualified table
+description=An INNER or OUTER join.
+example={code:sql}a inner join b{code}
+*/
JoinPredicate qualifiedJoin(ParseInfo info) :
{
JoinPredicate result = new JoinPredicate();
@@ -2144,6 +2275,11 @@
}
}
+/*
+name=table primary
+description=A single source of rows.
+example={code:sql}a{code}
+*/
FromClause tablePrimary(ParseInfo info) :
{
FromClause clause = null;
@@ -2175,6 +2311,11 @@
}
}
+/*
+name=xml serialize
+description=Serializes an XML value.
+example={code:sql}XMLSERIALIZE(col1 AS CLOB){code}
+*/
XMLSerialize xmlSerialize(ParseInfo info) :
{
Expression expr = null;
@@ -2202,6 +2343,11 @@
}
}
+/*
+name=array table
+description=The ARRAYTABLE table function creates tabular results from arrays. It can be used as a nested table reference.
+example={code:sql}ARRAYTABLE (col1 COLUMNS x STRING) AS y{code}
+*/
ArrayTable arrayTable(ParseInfo info) :
{
Expression array = null;
@@ -2223,6 +2369,11 @@
}
}
+/*
+name=text table
+description=The TEXTTABLE table function creates tabular results from text. It can be used as a nested table reference.
+example={code:sql}TEXTTABLE (file COLUMNS x STRING) AS y{code}
+*/
TextTable textTable(ParseInfo info) :
{
Expression file = null;
@@ -2302,10 +2453,15 @@
}
}
+/*
+name=text table column
+description=A text table column.
+example={code:sql}x INTEGER WIDTH 6{code}
+*/
TextTable.TextColumn textColumn(ParseInfo info):
{
String name = null;
- Constant datatype = null;
+ ParsedDataType datatype = null;
Integer width = null;
boolean noTrim = false;
String selector = null;
@@ -2313,7 +2469,7 @@
}
{
name = id()
- datatype = dataType()
+ datatype = parseDataType()
[
<WIDTH>
width = intVal()
@@ -2330,13 +2486,18 @@
position = intVal()
]
{
- TextTable.TextColumn result = new TextTable.TextColumn(validateElementName(name), (String)datatype.getValue(), width, noTrim);
+ TextTable.TextColumn result = new TextTable.TextColumn(validateElementName(name), datatype.type, width, noTrim);
result.setSelector(selector);
result.setPosition(position);
return result;
}
}
+/*
+name=xml query
+description=Executes an XQuery to return an XML result.
+example={code:sql}XMLQUERY('<a>...</a>' PASSING doc){code}
+*/
XMLQuery xmlQuery(ParseInfo info) :
{
String xquery = null;
@@ -2391,6 +2552,11 @@
}
}
+/*
+name=xml table
+description=Returns table results by processing an XQuery.
+example={code:sql}XMLTABLE('/a/b' PASSING doc COLUMNS col XML PATH '.') AS X{code}
+*/
XMLTable xmlTable(ParseInfo info) :
{
String xquery = null;
@@ -2420,7 +2586,6 @@
}
)*
]
-
[
<COLUMNS>
column = xmlColumn(info)
@@ -2447,10 +2612,15 @@
}
}
+/*
+name=xml table column
+description=XML table column.
+example={code:sql}y FOR ORDINALITY{code}
+*/
XMLTable.XMLColumn xmlColumn(ParseInfo info):
{
String name = null;
- Constant datatype = null;
+ ParsedDataType datatype = null;
String path = null;
Expression defaultExpr = null;
}
@@ -2463,7 +2633,7 @@
return new XMLTable.XMLColumn(name);
}
) | (
- datatype = dataType()
+ datatype = parseDataType()
[
<DEFAULT_KEYWORD> defaultExpr = expression(info)
]
@@ -2471,17 +2641,22 @@
<PATH> path = stringVal()
]
{
- return new XMLTable.XMLColumn(name, (String)datatype.getValue(), path, defaultExpr);
+ return new XMLTable.XMLColumn(name, datatype.type, path, defaultExpr);
}
))
}
+/*
+name=unsigned integer
+description=An unsigned interger value.
+example={code:sql}12345{code}
+*/
int intVal() :
{
Token t;
}
{
- t = <INTEGERVAL>
+ t = <UNSIGNEDINTEGER>
{
try {
return Integer.valueOf(t.image);
@@ -2491,12 +2666,11 @@
}
}
-
-/**
- * Parse a unary from clause, which is just a single group name and an optional alias.
- * @return Unary from clause containing the group
- * @throws ParseException if parsing failed
- */
+/*
+name=table subquery
+description=A table defined by a subquery.
+example={code:sql}(SELECT * FROM tbl) AS x{code}
+*/
SubqueryFromClause subqueryFromClause(ParseInfo info) :
{
String aliasID = null;
@@ -2506,7 +2680,7 @@
}
{
[
- <TABLE> { table = true; }
+ (<TABLE>|<LATERAL>) { table = true; }
]
lparen = <LPAREN>
( command = queryExpression(info) |
@@ -2523,11 +2697,11 @@
}
}
-/**
- * Parse a unary from clause, which is just a single group name and an optional alias.
- * @return Unary from clause containing the group
- * @throws ParseException if parsing failed
- */
+/*
+name=table name
+description=A table named in the FROM clause.
+example={code:sql}tbl AS x{code}
+*/
UnaryFromClause unaryFromClause(ParseInfo info) :
{
GroupSymbol group = null;
@@ -2550,11 +2724,11 @@
}
}
-/**
- * <p>Parse a WHERE clause. The where clause holds a criteria.
- * @return Parsed where
- * @throws ParseException if parsing failed
- */
+/*
+name=where clause
+description=Specifies a search condition
+example={code:sql}WHERE x = 'a'{code}
+*/
Criteria where(ParseInfo info) :
{
Criteria criteria = null;
@@ -2568,11 +2742,10 @@
}
}
-/**
- * <p>Parse a criteria. This will parse any criteria expression.</p>
- * @return Parsed criteria
- * @throws ParseException if parsing failed
- */
+/*
+name=condition
+description=A boolean expression.
+*/
Criteria criteria(ParseInfo info) :
{
Criteria criteria = null;
@@ -2585,11 +2758,10 @@
}
}
-/**
- * <p>Parse a compound logical OR criteria.</p>
- * @return Parsed OR criteria
- * @throws ParseException if parsing failed
- */
+/*
+name=boolean value expression
+description=An optionally ORed boolean expression.
+*/
Criteria compoundCritOr(ParseInfo info) :
{
ArrayList logicList = null;
@@ -2609,11 +2781,10 @@
}
}
-/**
- * <p>Parse a compound logical AND criteria.</p>
- * @return Parsed AND criteria
- * @throws ParseException if parsing failed
- */
+/*
+name=boolean term
+description=An optional ANDed boolean factor.
+*/
Criteria compoundCritAnd(ParseInfo info) :
{
ArrayList logicList = null;
@@ -2633,11 +2804,11 @@
}
}
-/**
- * <p>Parse a logical NOT criteria.</p>
- * @return Parsed NOT criteria
- * @throws ParseException if parsing failed
- */
+/*
+name=boolean factor
+description=A boolean factor.
+example={code:sql}NOT x = 'a'{code}
+*/
Criteria notCrit(ParseInfo info) :
{
Expression ex = null;
@@ -2662,11 +2833,11 @@
}
}
-/**
- * <p>Parse a boolean primary.</p>
- * @return criteria
- * @throws ParseException if parsing failed
- */
+/*
+name=boolean primary
+description=A boolean predicate or simple expression.
+example={code:sql}col LIKE 'a%'{code}
+*/
Expression booleanPrimary(ParseInfo info) :
{
Expression ex = null;
@@ -2692,6 +2863,11 @@
}
}
+/*
+name=comparison operator
+description=A comparison operator.
+example={code:sql}={code}
+*/
Token operator() :
{
Token operator = null;
@@ -2710,12 +2886,11 @@
}
}
-
-/**
- * <p>Parse a compare criteria.</p>
- * @return Parsed compare criteria
- * @throws ParseException if parsing failed
- */
+/*
+name=comparison predicate
+description=A value comparison.
+example={code:sql}x = 'a'{code}
+*/
CompareCriteria compareCrit(ParseInfo info, Expression expression) :
{
Expression value = null;
@@ -2740,6 +2915,11 @@
}
}
+/*
+name=subquery
+description=A subquery.
+example={code:sql}(SELECT * FROM tbl){code}
+*/
QueryCommand subquery(ParseInfo info) :
{
QueryCommand subquery = null;
@@ -2761,24 +2941,11 @@
}
}
-Object[] subqueryAndHint(ParseInfo info) :
-{
- QueryCommand subquery = null;
- Token lparen = null;
-}
-{
- {lparen = getToken(1);}
- subquery = subquery(info)
- {
- return new Object[] {subquery, getSubqueryHint(lparen)};
- }
-}
-
-/**
- * <p>Parse a subquery compare criteria.</p>
- * @return Parsed subquery compare criteria
- * @throws ParseException if parsing failed
- */
+/*
+name=quantified comparison predicate
+description=A subquery comparison.
+example={code:sql}= ANY (SELECT col FROM tbl){code}
+*/
SubqueryCompareCriteria subqueryCompareCriteria(ParseInfo info, Expression expression) :
{
SubqueryCompareCriteria subqueryCrit = null;
@@ -2816,11 +2983,11 @@
}
}
-/**
- * <p>Parse a match criteria. Also parses JDBC escape syntax for match criteria.</p>
- * @return Parsed match criteria
- * @throws ParseException if parsing failed
- */
+/*
+name=match predicate
+description=Matches based upon a pattern.
+example={code:sql}LIKE 'a_'{code}
+*/
MatchCriteria matchCrit(ParseInfo info, Expression expression) :
{
Character esc = null;
@@ -2846,6 +3013,11 @@
}
}
+/*
+name=like regex predicate
+description=A regular expression match.
+example={code:sql}LIKE_REGEX 'a.*b'{code}
+*/
MatchCriteria regexMatchCrit(ParseInfo info, Expression expression) :
{
Expression value = null;
@@ -2863,6 +3035,11 @@
}
}
+/*
+name=character
+description=A single character.
+example={code:sql}'a'{code}
+*/
Character charVal(ParseInfo info, String type) :
{
String escStr = null;
@@ -2877,11 +3054,11 @@
}
}
-/**
- * <p>Parse an [NOT] BETWEEN criteria.</p>
- * @return Parsed BETWEEN criteria
- * @throws ParseException if parsing failed
- */
+/*
+name=between predicate
+description=A comparison between two values.
+example={code:sql}BETWEEN 1 AND 5{code}
+*/
BetweenCriteria betweenCrit(ParseInfo info, Expression expression) :
{
Expression lowerExpression = null, upperExpression = null;
@@ -2901,11 +3078,11 @@
}
}
-/**
- * <p>Parse an IS [NOT] NULL criteria.</p>
- * @return Parsed IS NULL criteria
- * @throws ParseException if parsing failed
- */
+/*
+name=is null predicate
+description=A null test.
+example={code:sql}IS NOT NULL{code}
+*/
IsNullCriteria isNullCrit(ParseInfo info, Expression expression) :
{
boolean negated = false;
@@ -2923,16 +3100,17 @@
}
}
-/**
- * <p>Parse a set criteria.</p>
- * @return Parsed set criteria
- * @throws ParseException if parsing failed
- */
+/*
+name=in predicate
+description=A comparison with multiple values.
+example={code:sql}IN (1, 5){code}
+*/
AbstractSetCriteria setCrit(ParseInfo info, Expression expression) :
{
Expression value = null;
List setList = new ArrayList();
- Object[] command = null;
+ QueryCommand command = null;
+ ExistsCriteria.SubqueryHint hint = null;
boolean negated = false;
AbstractSetCriteria criteria = null;
}
@@ -2940,7 +3118,7 @@
[<NOT> {negated = true;}]
<IN>
(
- LOOKAHEAD(subquery(info)) (command = subqueryAndHint(info)) |
+ LOOKAHEAD(subquery(info)) { hint = getSubqueryHint(getToken(1)); } (command = subquery(info)) |
(
<LPAREN>
value = commonValueExpression(info)
@@ -2958,8 +3136,8 @@
)
{
if (command != null) {
- SubquerySetCriteria ssc = new SubquerySetCriteria(expression, (QueryCommand)command[0]);
- ssc.setSubqueryHint((ExistsCriteria.SubqueryHint)command[1]);
+ SubquerySetCriteria ssc = new SubquerySetCriteria(expression, command);
+ ssc.setSubqueryHint(hint);
criteria = ssc;
} else {
criteria = new SetCriteria(expression, setList);
@@ -2969,31 +3147,32 @@
}
}
-/**
- * <p>Parse an exists criteria.</p>
- * @return Parsed exists criteria
- * @throws ParseException if parsing failed
- */
+/*
+name=exists predicate
+description=A test if rows exist.
+example={code:sql}EXISTS (SELECT col FROM tbl){code}
+*/
ExistsCriteria existsCriteria(ParseInfo info) :
{
- Object[] subquery = null;
+ QueryCommand subquery = null;
+ ExistsCriteria.SubqueryHint hint = null;
}
{
- <EXISTS>
- subquery = subqueryAndHint(info)
+ <EXISTS> { hint = getSubqueryHint(getToken(1)); }
+ subquery = subquery(info)
{
- ExistsCriteria existsCrit = new ExistsCriteria((QueryCommand)subquery[0]);
- existsCrit.setSubqueryHint((ExistsCriteria.SubqueryHint)subquery[1]);
+ ExistsCriteria existsCrit = new ExistsCriteria(subquery);
+ existsCrit.setSubqueryHint(hint);
return existsCrit;
}
}
-/**
- * <p>Parse a GROUP BY clause. </p>
- * @return Parsed group by
- * @throws ParseException if parsing failed
- */
+/*
+name=group by clause
+description=Defines the grouping columns
+example={code:sql}GROUP BY col1, col2{code}
+*/
GroupBy groupBy(ParseInfo info) :
{
List<Expression> expressions = null;
@@ -3006,11 +3185,11 @@
}
}
-/**
- * <p>Parse a HAVING clause. </p>
- * @return Parsed having
- * @throws ParseException if parsing failed
- */
+/*
+name=having clause
+description=Search condition applied after grouping.
+example={code:sql}HAVING max(col1) = 5{code}
+*/
Criteria having(ParseInfo info) :
{
Criteria criteria = null;
@@ -3023,12 +3202,11 @@
}
}
-
-/**
- * <p>Parse an ORDER BY clause.</p>
- * @return Parsed ORDER BY
- * @throws ParseException if parsing failed
- */
+/*
+name=order by clause
+description=Specifices row ordering.
+example={code:sql}ORDER BY x, y DESC{code}
+*/
OrderBy orderby(ParseInfo info) :
{
OrderBy orderby = new OrderBy();
@@ -3051,6 +3229,11 @@
}
}
+/*
+name=sort specification
+description=Defines how to sort on a particular expression
+example={code:sql}col1 NULLS FIRST{code}
+*/
OrderByItem sortSpecification(ParseInfo info) :
{
Expression ex = null;
@@ -3070,6 +3253,11 @@
}
}
+/*
+name=sort key
+description=A sort expression.
+example={code:sql}col1{code}
+*/
Expression sortKey(ParseInfo info) :
{
Expression ex = null;
@@ -3093,6 +3281,11 @@
}
}
+/*
+name=integer parameter
+description=A literal integer or parameter reference to an integer.
+example={code:sql}?{code}
+*/
Expression intParam(ParseInfo info) :
{
Integer val = null;
@@ -3107,11 +3300,11 @@
}
}
-/**
- * <p>Parse an LIMIT clause.</p>
- * @return Parsed LIMIT
- * @throws ParseException if parsing failed
- */
+/*
+name=limit clause
+description=Limits and/or offsets the resultant rows.
+example={code:sql}LIMIT 2{code}
+*/
Limit limit(ParseInfo info) :
{
Expression limit = null;
@@ -3140,6 +3333,11 @@
}
}
+/*
+name=fetch clause
+description=ANSI limit.
+example={code:sql}FETCH FIRST 1 ROWS ONLY{code}
+*/
Expression fetchLimit(ParseInfo info) :
{
Expression limit = null;
@@ -3154,11 +3352,11 @@
}
}
-/**
- * <p>Parse an OPTION clause.</p>
- * @return Parsed OPTION clause
- * @throws ParseException if parsing failed
- */
+/*
+name=option clause
+description=Specifies query options.
+example={code:sql}OPTION MAKEDEP tbl{code}
+*/
Option option(ParseInfo info) :
{
String id = null;
@@ -3210,11 +3408,11 @@
}
}
-/**
- * <p>Parse an expression - made up of literals and functions.</p>
- * @return Expression
- * @throws ParseException if parsing failed
- */
+/*
+name=expression
+description=A value.
+example={code:sql}col1{code}
+*/
Expression expression(ParseInfo info) :
{
Expression expression = null;
@@ -3229,6 +3427,11 @@
}
}
+/*
+name=common value expression
+description=Establishes the precedence of concat.
+example={code:sql}'a' || 'b'{code}
+*/
Expression commonValueExpression(ParseInfo info) :
{
Expression leftExpression = null;
@@ -3251,11 +3454,10 @@
}
}
-/**
- * <p>Parse an expression - made up of literals and functions.</p>
- * @return Expression
- * @throws ParseException if parsing failed
- */
+/*
+name=numeric value expression
+example={code:sql}1 + 2{code}
+*/
Expression plusExpression(ParseInfo info) :
{
Expression leftExpression = null;
@@ -3265,7 +3467,7 @@
{
( leftExpression=timesExpression(info)
(
- operator=plusOperator()
+ operator=plusMinus()
rightExpression=timesExpression(info)
{
leftExpression = new Function(operator, new Expression[] { leftExpression, rightExpression });
@@ -3280,30 +3482,26 @@
}
}
-/**
- * <p>Parse the add/subtract operators.</p>
- * @return "+" or "-"
- * @throws ParseException if parsing failed
- */
-String plusOperator() :
+/*
+name=plus or minus
+description=The + or - operator.
+example={code:sql}+{code}
+*/
+String plusMinus() :
{
- Token operator = null;
}
{
- ( operator = <PLUS> |
- operator = <MINUS>
- )
-
+ (<PLUS> | <MINUS>)
{
- return operator.image;
+ return getToken(0).image;
}
}
-/**
- * <p>Parse an expression - made up of literals and functions.</p>
- * @return Expression
- * @throws ParseException if parsing failed
- */
+/*
+name=term
+description=A numeric term
+example={code:sql}1 * 2{code}
+*/
Expression timesExpression(ParseInfo info) :
{
Expression leftExpression = null;
@@ -3328,11 +3526,11 @@
}
}
-/**
- * <p>Parse the multiply/divide operator.</p>
- * @return "*" or "/"
- * @throws ParseException if parsing failed
- */
+/*
+name=star or slash
+description=The * or / operator.
+example={code:sql}/{code}
+*/
String timesOperator() :
{
Token operator = null;
@@ -3347,33 +3545,56 @@
}
}
-/**
- * <p>Parse a basic expression.</p>
- * @return Expression
- * @throws ParseException if parsing failed
- */
+/*
+name=value expression primary
+description=A simple value expression.
+example={code:sql}+col1{code}
+*/
Expression valueExpressionPrimary(ParseInfo info) :
{
- Token refToken = null;
+ String strVal = null;
+ Expression ex = null;
+}
+{
+ // Literal
+ (ex=nonNumericLiteral()
+ | [strVal = plusMinus()]
+ (ex = unsignedNumericLiteral(strVal)
+ |
+ ex = unsignedValueExpressionPrimary(info) {
+ if (strVal != null && strVal.charAt(0) == '-') {
+ ex = new Function("*", new Expression[] { new Constant(-1), ex });
+ }
+ }
+ )
+ )
+ {
+ return ex;
+ }
+}
+
+/*
+name=unsigned value expression primary
+description=An unsigned simple value expression.
+example={code:sql}col1{code}
+*/
+Expression unsignedValueExpressionPrimary(ParseInfo info) :
+{
Expression expression = null;
Token symbol = null;
- Constant literal = null;
QueryCommand subquery = null;
- Integer arrayIndex = null;
+ Integer index = null;
Expression condition = null;
}
{
(
// Reference
- refToken=<QMARK>
+ <QMARK> {return new Reference(info.referenceCount++);}
|
- refToken=<POS_REF>
+ (<DOLLAR> index = intVal() {return new Reference(index -1); })
|
- // Literal
- literal=literal()
- |
// Escaped function
- ( <LBRACE> <FN>
+ ( <ESCAPEDFUNCTION>
expression=function(info)
<RBRACE>
)
@@ -3390,11 +3611,10 @@
((symbol=<ID> {
String symbolImage = symbol.image;
if(isStringLiteral(symbolImage, info)) {
- literal = new Constant(normalizeStringLiteral(symbolImage));
- symbol = null;
+ return new Constant(normalizeStringLiteral(symbolImage));
}
} | symbol=nonReserved())
- (<LSBRACE> arrayIndex = intVal() <RSBRACE>)?
+ (<LSBRACE> index = intVal() <RSBRACE>)?
)
|
LOOKAHEAD(subquery(info)) subquery = subquery(info)
@@ -3402,7 +3622,7 @@
( <LPAREN>
expression = expression(info)
<RPAREN>
- (<LSBRACE> arrayIndex = intVal() <RSBRACE>)?
+ (<LSBRACE> index = intVal() <RSBRACE>)?
)
|
// Searched CASE expressions
@@ -3413,28 +3633,26 @@
)
{
- if(refToken != null) {
- if (refToken.image.charAt(0) == '$') {
- return new Reference(Integer.parseInt(refToken.image.substring(1)) -1);
- }
- expression = new Reference(info.referenceCount++);
- } else if(symbol != null) {
+ if(symbol != null) {
expression = new ElementSymbol(normalizeId(symbol.image));
- } else if(literal != null) {
- expression = literal; // may be null literal
} else if (subquery != null){
expression = new ScalarSubquery(subquery);
}
if (condition != null) {
((AggregateSymbol)expression).setCondition(condition);
}
- if (arrayIndex != null) {
- expression = new Function("array_get", new Expression[] {expression, new Constant(arrayIndex)});
+ if (index != null) {
+ expression = new Function("array_get", new Expression[] {expression, new Constant(index)});
}
return expression;
}
}
+/*
+name=window specification
+description=The window specification for an analytical or windowed aggregate function.
+example={code:sql}OVER (PARTION BY col1){code}
+*/
Expression windowSpecification(Expression agg, ParseInfo info) :
{
List<Expression> partitionList = null;
@@ -3460,11 +3678,11 @@
}
}
-/**
- * Parse a non-searched CASE expression.
- * @return CaseExpression
- * @throws ParseException if parsing failed
- */
+/*
+name=case expression
+description=If/then/else chain using a common search predicand.
+example={code:sql}CASE col1 WHEN 'a' THEN 1 ELSE 2{code}
+*/
CaseExpression caseExpression(ParseInfo info) :
{
Expression expression = null, whenExpression = null, thenExpression = null, elseExpression = null;
@@ -3493,11 +3711,11 @@
}
}
-/**
- * Parse a searched CASE expression.
- * @return SearchedCaseExpression
- * @throws ParseException if parsing failed
- */
+/*
+name=searched case expression
+description=If/then/else chain using multiple search conditions.
+example={code:sql}CASE WHEN x = 'a' THEN 1 WHEN y = 'b' THEN 2{code}
+*/
SearchedCaseExpression searchedCaseExpression(ParseInfo info) :
{
Expression thenExpression = null, elseExpression = null;
@@ -3527,11 +3745,11 @@
}
}
-/**
- * <p>Parse a function. </p>
- * @return Parsed function
- * @throws ParseException if parsing failed
- */
+/*
+name=function
+description=Calls a scalar function.
+example={code:sql}func('1', col1){code}
+*/
Expression function(ParseInfo info) :
{
String funcName = null;
@@ -3543,6 +3761,8 @@
Boolean distinct = null;
OrderBy orderBy = null;
Expression condition = null;
+ String literal = null;
+ ParsedDataType type = null;
}
{
(( funcToken = <CONVERT>
@@ -3552,9 +3772,9 @@
args.add(expression);
}
<COMMA>
- expression = dataType()
+ type = parseDataType()
{
- args.add(expression);
+ args.add(new Constant(type.type));
}
<RPAREN>
)
@@ -3567,9 +3787,9 @@
args.add(expression);
}
<AS>
- expression = dataType()
+ type = parseDataType()
{
- args.add(expression);
+ args.add(new Constant(type.type));
}
<RPAREN>
)
@@ -3658,9 +3878,9 @@
args.add(expression);
}
<COMMA>
- expression = stringConstant()
+ literal = stringVal()
{
- args.add(expression);
+ args.add(new Constant(literal));
}
<RPAREN>
)
@@ -3717,10 +3937,10 @@
| ( funcToken = <XMLPI>
<LPAREN>
(
- [LOOKAHEAD(1) <NAME>] expression = idExpression()
+ [LOOKAHEAD(1) <NAME>] literal = id()
)
{
- args.add(expression);
+ args.add(new Constant(literal));
}
[
<COMMA> expression = expression(info)
@@ -3764,17 +3984,11 @@
}
}
-Constant stringConstant() :
-{
- String val = null;
-}
-{
- val = stringVal()
- {
- return new Constant(val);
- }
-}
-
+/*
+name=xml parse
+description=Parses the given value as XML.
+example={code:sql}XMLPARSE(DOCUMENT doc WELLFORMED){code}
+*/
XMLParse xmlParse(ParseInfo info) :
{
Expression expr = null;
@@ -3800,6 +4014,11 @@
}
}
+/*
+name=querystring function
+description=Produces a URL query string from the given arguments.
+example={code:sql}QUERYSTRING(col1 AS opt, col2 AS val){code}
+*/
QueryString queryString(ParseInfo info) :
{
Expression path = null;
@@ -3821,6 +4040,11 @@
}
}
+/*
+name=xml element
+description=Creates an XML element.
+example={code:sql}XMLELEMENT(NAME "root", child){code}
+*/
XMLElement xmlElement(ParseInfo info) :
{
String name = null;
@@ -3854,6 +4078,11 @@
}
}
+/*
+name=xml attributes
+description=Creates attributes for the containing element.
+example={code:sql}XMLATTRIBUTES(col1 AS attr1, col2 AS attr2){code}
+*/
XMLAttributes xmlAttributes(ParseInfo info) :
{
DerivedColumn expression = null;
@@ -3876,6 +4105,11 @@
}
}
+/*
+name=xml forest
+description=Produces an element for each derived column.
+example={code:sql}XMLFOREST(col1 AS ELEM1, col2 AS ELEM2){code}
+*/
XMLForest xmlForest(ParseInfo info) :
{
DerivedColumn expression = null;
@@ -3904,6 +4138,11 @@
}
}
+/*
+name=xml namespaces
+description=Defines XML namespace URI/prefix combinations
+example={code:sql}XMLNAMESPACES('http://foo' AS foo){code}
+*/
XMLNamespaces xmlNamespaces(ParseInfo info) :
{
ArrayList namespaces = new ArrayList(2);
@@ -3926,6 +4165,11 @@
}
}
+/*
+name=xml namespace element
+description=An xml namespace
+example={code:sql}NO DEFAULT{code}
+*/
XMLNamespaces.NamespaceItem namespaceItem() :
{
String uri = null;
@@ -3950,82 +4194,64 @@
)
}
-Constant idExpression() :
-{
- String id = null;
-}
-{
- id = id()
- {
- return new Constant(id);
- }
-}
-
+/*
+name=data type
+description=A data type.
+example={code:sql}STRING{code}
+*/
ParsedDataType parseDataType() :
{
Token typeToken = null;
- Token lengthToken = null;
- Token scaleToken = null;
+ Integer length = null;
+ Integer scale = null;
boolean precision = true;
}
{
(
- (typeToken = <STRING> ([<LPAREN>lengthToken=<INTEGERVAL><RPAREN>]) {precision = false;} ) |
- (typeToken = <VARCHAR> ([<LPAREN>lengthToken=<INTEGERVAL><RPAREN>]) {precision = false;} ) |
+ (typeToken = <STRING> ([<LPAREN>length=intVal()<RPAREN>]) {precision = false;} ) |
+ (typeToken = <VARCHAR> ([<LPAREN>length=intVal()<RPAREN>]) {precision = false;} ) |
typeToken = <BOOLEAN> |
typeToken = <BYTE> |
typeToken = <TINYINT> |
typeToken = <SHORT> |
typeToken = <SMALLINT> |
- (typeToken = <CHAR> ([<LPAREN>lengthToken=<INTEGERVAL><RPAREN>]) {precision = false;} ) |
+ (typeToken = <CHAR> ([<LPAREN>length=intVal()<RPAREN>]) {precision = false;} ) |
typeToken = <INTEGER> |
typeToken = <LONG> |
typeToken = <BIGINT> |
- (typeToken = <BIGINTEGER> [<LPAREN>lengthToken=<INTEGERVAL><RPAREN>]) |
+ (typeToken = <BIGINTEGER> [<LPAREN>length=intVal()<RPAREN>]) |
typeToken = <FLOAT> |
typeToken = <REAL> |
typeToken = <DOUBLE> |
- (typeToken = <BIGDECIMAL> [<LPAREN>lengthToken=<INTEGERVAL>[<COMMA>scaleToken=<INTEGERVAL>]<RPAREN>])|
- (typeToken = <DECIMAL> [<LPAREN>lengthToken=<INTEGERVAL>[<COMMA>scaleToken=<INTEGERVAL>]<RPAREN>])|
+ (typeToken = <BIGDECIMAL> [<LPAREN>length=intVal()[<COMMA>scale=intVal()]<RPAREN>])|
+ (typeToken = <DECIMAL> [<LPAREN>length=intVal()[<COMMA>scale=intVal()]<RPAREN>])|
typeToken = <DATE> |
typeToken = <TIME> |
typeToken = <TIMESTAMP> |
typeToken = <OBJECT> |
- (typeToken = <BLOB> ([<LPAREN>lengthToken=<INTEGERVAL><RPAREN>]) {precision = false;} )|
- (typeToken = <CLOB> ([<LPAREN>lengthToken=<INTEGERVAL><RPAREN>]) {precision = false;} )|
- (typeToken = <VARBINARY> ([<LPAREN>lengthToken=<INTEGERVAL><RPAREN>]) {precision = false;} ) |
+ (typeToken = <BLOB> ([<LPAREN>length=intVal()<RPAREN>]) {precision = false;} )|
+ (typeToken = <CLOB> ([<LPAREN>length=intVal()<RPAREN>]) {precision = false;} )|
+ (typeToken = <VARBINARY> ([<LPAREN>length=intVal()<RPAREN>]) {precision = false;} ) |
typeToken = <XML>
)
{
- if (scaleToken != null){
- return new ParsedDataType(typeToken.image, Integer.parseInt(lengthToken.image), Integer.parseInt(scaleToken.image), precision);
+ if (scale != null){
+ return new ParsedDataType(typeToken.image, length, scale, precision);
}
- else if (scaleToken == null && lengthToken != null){
- return new ParsedDataType(typeToken.image, Integer.parseInt(lengthToken.image), precision);
+ else if (length != null){
+ return new ParsedDataType(typeToken.image, length, precision);
}
return new ParsedDataType(typeToken.image);
}
}
-
-Constant dataType() :
-{
- ParsedDataType type = null;
-}
-{
- type = parseDataType()
- {
- return new Constant(type.type);
- }
-}
-
-/**
- * Parse an interval type name - used only in TIMESTAMPADD and TIMESTAMPDIFF functions.
- * @return Interval type parsed into a constant string object
- * @throws ParseException if parsing failed
- */
+/*
+name=time interval
+description=A time interval keyword.
+example={code:sql}SQL_TSI_HOUR{code}
+*/
Constant intervalType() :
{
Token type = null;
@@ -4046,16 +4272,16 @@
return new Constant(type.image);
}
}
-/**
- * <p>Parse a literal - strings must be wrapped in either '' or "".
- * JDBC escape syntax is parsed for Date, Time and Timestamp value.</p>
- * @return Parsed literal
- * @throws ParseException if parsing failed
- */
-Constant literal() :
+
+/*
+name=non numeric literal
+description=An escaped or simple non numeric literal.
+example={code:sql}'a'{code}
+*/
+Constant nonNumericLiteral() :
{
Token t = null;
- String strVal = null;
+ String strVal = "";
Class escapeType = null;
Constant constant = null;
}
@@ -4064,84 +4290,107 @@
strVal=stringVal() {
constant = new Constant(strVal, DataTypeManager.DefaultDataClasses.STRING);
} |
-
- t=<INTEGERVAL> {
+ t=<BINARYSTRINGVAL> { constant = new Constant(new BinaryType(javax.xml.bind.DatatypeConverter.parseHexBinary(t.image.substring(2, t.image.length() - 1))), DataTypeManager.DefaultDataClasses.VARBINARY); } |
+ t=<FALSE> { constant = new Constant(Boolean.FALSE, DataTypeManager.DefaultDataClasses.BOOLEAN); } |
+ t=<TRUE> { constant = new Constant(Boolean.TRUE, DataTypeManager.DefaultDataClasses.BOOLEAN); } |
+ t=<UNKNOWN> { constant = new Constant(null, DataTypeManager.DefaultDataClasses.BOOLEAN); } |
+ t=<NULL> { constant = new Constant(null); } |
+
+ ( <ESCAPEDTYPE> {
+ String image = getToken(0).image;
+ if (StringUtil.endsWithIgnoreCase(image, "b")) {
+ escapeType=DataTypeManager.DefaultDataClasses.BOOLEAN;
+ } else if (StringUtil.endsWithIgnoreCase(image, "ts")) {
+ escapeType=DataTypeManager.DefaultDataClasses.TIMESTAMP;
+ } else if (StringUtil.endsWithIgnoreCase(image, "d")) {
+ escapeType=DataTypeManager.DefaultDataClasses.DATE;
+ } else {
+ escapeType=DataTypeManager.DefaultDataClasses.TIME;
+ }
+ } strVal=stringVal() {
+ try {
+ constant = new Constant(DataTypeManager.transformValue(strVal, escapeType), escapeType);
+ } catch (TransformationException e) {
+ throw new ParseException(e.getMessage()); //$NON-NLS-1$
+ }
+ } <RBRACE> )
+
+ )
+ {
+ return constant;
+ }
+}
+
+/*
+name=unsigned numeric literal
+description=An unsigned numeric literal value.
+example={code:sql}1.234{code}
+*/
+Constant unsignedNumericLiteral(String strVal) :
+{
+ Token t = null;
+}
+{
+ (t=<UNSIGNEDINTEGER> {
try {
+ strVal = prependSign(strVal, t.image);
// First try as integer - this should nearly always work
- constant = new Constant(Integer.valueOf(t.image), DataTypeManager.DefaultDataClasses.INTEGER);
+ return new Constant(Integer.valueOf(strVal), DataTypeManager.DefaultDataClasses.INTEGER);
} catch(NumberFormatException e1) {
try {
// Second try as a long
- constant = new Constant(Long.valueOf(t.image), DataTypeManager.DefaultDataClasses.LONG);
+ return new Constant(Long.valueOf(strVal), DataTypeManager.DefaultDataClasses.LONG);
} catch(NumberFormatException e2) {
try {
// Third try as a biginteger
- constant = new Constant(new BigInteger(t.image), DataTypeManager.DefaultDataClasses.BIG_INTEGER);
+ return new Constant(new BigInteger(strVal), DataTypeManager.DefaultDataClasses.BIG_INTEGER);
} catch(NumberFormatException e3) {
- Object[] params = new Object[] { t.image };
+ Object[] params = new Object[] { strVal };
throw new ParseException(QueryPlugin.Util.getString("SQLParser.Integer_parse", params)); //$NON-NLS-1$
}
}
}
- } |
-
- t=<FLOATVAL> {
+ } | t=<FLOATVAL> {
+ strVal = prependSign(strVal, t.image);
try {
- constant = new Constant(Double.valueOf(t.image), DataTypeManager.DefaultDataClasses.DOUBLE);
+ return new Constant(Double.valueOf(strVal), DataTypeManager.DefaultDataClasses.DOUBLE);
} catch(NumberFormatException e) {
- Object[] params = new Object[] { t.image };
+ Object[] params = new Object[] { strVal };
throw new ParseException(QueryPlugin.Util.getString("SQLParser.Float_parse", params)); //$NON-NLS-1$
}
- } |
- t=<DECIMALVAL> {
+ } | t=<DECIMALVAL> {
+ strVal = prependSign(strVal, t.image);
try {
if (DECIMAL_AS_DOUBLE) {
- constant = new Constant(Double.valueOf(t.image), DataTypeManager.DefaultDataClasses.DOUBLE);
+ return new Constant(Double.valueOf(strVal), DataTypeManager.DefaultDataClasses.DOUBLE);
} else {
- constant = new Constant(new java.math.BigDecimal(t.image), DataTypeManager.DefaultDataClasses.BIG_DECIMAL);
+ return new Constant(new java.math.BigDecimal(strVal), DataTypeManager.DefaultDataClasses.BIG_DECIMAL);
}
} catch(NumberFormatException e) {
Object[] params = new Object[] { t.image };
throw new ParseException(QueryPlugin.Util.getString("SQLParser.decimal_parse", params)); //$NON-NLS-1$
}
- } |
- t=<BINARYSTRINGVAL> { constant = new Constant(new BinaryType(javax.xml.bind.DatatypeConverter.parseHexBinary(t.image.substring(2, t.image.length() - 1))), DataTypeManager.DefaultDataClasses.VARBINARY); } |
- t=<FALSE> { constant = new Constant(Boolean.FALSE, DataTypeManager.DefaultDataClasses.BOOLEAN); } |
- t=<TRUE> { constant = new Constant(Boolean.TRUE, DataTypeManager.DefaultDataClasses.BOOLEAN); } |
- t=<UNKNOWN> { constant = new Constant(null, DataTypeManager.DefaultDataClasses.BOOLEAN); } |
- t=<NULL> { constant = new Constant(null); } |
-
- ( (<BOOLEANTYPE> { escapeType=DataTypeManager.DefaultDataClasses.BOOLEAN; } |
- <TIMESTAMPTYPE> { escapeType=DataTypeManager.DefaultDataClasses.TIMESTAMP; } |
- <DATETYPE> { escapeType=DataTypeManager.DefaultDataClasses.DATE; } |
- <TIMETYPE> { escapeType=DataTypeManager.DefaultDataClasses.TIME; }) strVal=stringVal() {
- try {
- constant = new Constant(DataTypeManager.transformValue(strVal, escapeType), escapeType);
- } catch (TransformationException e) {
- throw new ParseException(e.getMessage()); //$NON-NLS-1$
- }
- } <RBRACE> )
-
- )
- {
- return constant;
- }
+ } )
}
-
-
-/*
- * DDL specific parser
- */
-
+/*
+unused=true
+*/
void parseMetadata(MetadataFactory factory) :
{
}
{
- ddlStmts(factory) [<SEMICOLON>] (ddlStmts(factory) [<SEMICOLON>])*
+ (ddlStmt(factory))*
+ <EOF>
}
-void ddlStmts(MetadataFactory factory) :
+/*
+name=ddl statement
+description=A data definition statement.
+example={code:sql}CREATE FOREIGN TABLE X (Y STRING){code}
+index=true
+*/
+void ddlStmt(MetadataFactory factory) :
{
Command command = null;
}
@@ -4154,8 +4403,14 @@
createDDLTrigger(factory, (AlterTrigger)command);
}
)
+ [<SEMICOLON>]
}
+/*
+name=option namespace
+description=A namespace used to shorten the full name of an option key.
+example={code:sql}SET NAMESPACE 'http://foo' AS foo{code}
+*/
void createNameSpace(MetadataFactory factory) :
{
String uri = null;
@@ -4164,14 +4419,15 @@
{
<SET> <NAMESPACE> uri = stringVal() <AS> prefix = id()
{
- factory.addNamespace(prefix, uri);
+ factory.addNamespace(validateAlias(prefix), uri);
}
}
-/**
- * Parse create update procedure command
- * @throws ParseException if parsing failed
- */
+/*
+name=create procedure
+description=Defines a procedure or function invocation.
+example={code:sql}CREATE FOREIGN PROCEDURE proc (param STRING) RETURNS STRING{code}
+*/
CreateProcedureCommand createDDLProcedure(MetadataFactory factory, ParseInfo info) :
{
boolean virtual = true;
@@ -4234,6 +4490,11 @@
}
}
+/*
+name=procedure parameter
+description=A procedure or function parameter
+example={code:sql}OUT x INTEGER{code}
+*/
void procedureParameter(MetadataFactory factory, Procedure proc) :
{
String name = null;
@@ -4277,25 +4538,23 @@
]
}
+/*
+name=procedure result column
+description=A procedure result column.
+example={code:sql}x INTEGER{code}
+*/
void procedureRsColumn(MetadataFactory factory, Procedure proc) :
{
String name = null;
-}
-{
- name = id()
- procedureColumn(factory, proc, name, true)
-}
-
-void procedureColumn(MetadataFactory factory, Procedure proc, String name, boolean rs) :
-{
ParsedDataType type = null;
boolean notNull = false;
BaseColumn column = null;
}
{
+ name = id()
type = parseDataType()
{
- column = addProcColumn(factory, proc, name, type, rs);
+ column = addProcColumn(factory, proc, name, type, true);
}
[<NOT> <NULL> {column.setNullType(Column.NullType.No_Nulls);}]
[optionsClause(column, factory)
@@ -4305,6 +4564,11 @@
]
}
+/*
+name=create table
+description=Defines a table or view.
+example={code:sql}CREATE VIEW vw AS SELECT 1{code}
+*/
void createTable(MetadataFactory factory) :
{
Table table = null;
@@ -4358,6 +4622,11 @@
}
}
+/*
+name=foreign key
+description=Defines the foreign key referential constraint.
+example={code:sql}FOREIGN KEY (a, b) REFERENCES tbl (x, y){code}
+*/
void foreignKeys(MetadataFactory factory, Table table) :
{
List<String> columnNames = null;
@@ -4393,6 +4662,11 @@
]
}
+/*
+name=primary key
+description=Defines the primary key.
+example={code:sql}PRIMARY KEY (a, b){code}
+*/
void primaryKeys(MetadataFactory factory, Table table) :
{
List<String> columnNames = null;
@@ -4422,6 +4696,11 @@
]
}
+/*
+name=other constraints
+description=Defines ACCESSPATTERN and UNIQUE constraints and INDEXes.
+example={code:sql}UNIQUE (a){code}
+*/
void constraints(MetadataFactory factory, Table table) :
{
KeyRecord keyrecord = null;
@@ -4458,6 +4737,11 @@
]
}
+/*
+name=column name list
+description=A list of column names.
+example={code:sql}(a, b){code}
+*/
ArrayList<String> getColumnNames() :
{
ArrayList list = new ArrayList<String>();
@@ -4480,6 +4764,11 @@
}
}
+/*
+name=table element
+description=Defines a table column.
+example={code:sql}x INTEGER NOT NULL{code}
+*/
void createColumn(MetadataFactory factory, Table table) :
{
String element = null;
@@ -4548,6 +4837,11 @@
}
}
+/*
+name=options clause
+description=A list of statement options.
+example={code:sql}OPTIONS ('x' 'y', 'a' 'b'){code}
+*/
void optionsClause(AbstractMetadataRecord record, MetadataFactory factory) :
{
}
@@ -4557,28 +4851,28 @@
<RPAREN>
}
+/*
+name=option pair
+description=An option key/value pair.
+example={code:sql}'key' 'value'{code}
+*/
void optionPair(AbstractMetadataRecord record, MetadataFactory factory) :
{
- String value = null;
+ Constant value = null;
String key = null;
Token t = null;
+ String strVal = null;
}
{
key = id()
- (value = stringVal()
- |
- t = <INTEGERVAL>
- |
- t = <DECIMALVAL>
- |
- t = <TRUE>
- |
- t = <FALSE>)
+ (value = nonNumericLiteral()
+ | [strVal = plusMinus()] value = unsignedNumericLiteral(strVal))
{
- if (t != null) {
- value = t.image;
+ key = resolvePropertyKey(factory, key);
+ String val = null;
+ if (!value.isNull()) {
+ val = value.getValue().toString();
}
- key = resolvePropertyKey(factory, key);
- record.setProperty(key, value);
+ record.setProperty(key, val);
}
}
Modified: trunk/engine/src/test/java/org/teiid/query/parser/TestParser.java
===================================================================
--- trunk/engine/src/test/java/org/teiid/query/parser/TestParser.java 2012-08-06 20:18:00 UTC (rev 4300)
+++ trunk/engine/src/test/java/org/teiid/query/parser/TestParser.java 2012-08-07 13:41:48 UTC (rev 4301)
@@ -558,7 +558,26 @@
"SELECT (5 + length(concat(a, 'x'))) FROM g", //$NON-NLS-1$
query);
}
+
+ @Test public void testSignedExpression() {
+ GroupSymbol g = new GroupSymbol("g"); //$NON-NLS-1$
+ From from = new From();
+ from.addGroup(g);
+ Function f = new Function("*", new Expression[] {new Constant(-1), new ElementSymbol("x")});
+ Select select = new Select();
+ select.addSymbol(f);
+ select.addSymbol(new ElementSymbol("x"));
+ select.addSymbol(new Constant(5));
+
+ Query query = new Query();
+ query.setSelect(select);
+ query.setFrom(from);
+ helpTest("SELECT -x, +x, +5 FROM g", //$NON-NLS-1$
+ "SELECT (-1 * x), x, 5 FROM g", //$NON-NLS-1$
+ query);
+ }
+
/** SELECT REPLACE(a, 'x', 'y') AS y FROM g */
@Test public void testAliasedFunction() {
GroupSymbol g = new GroupSymbol("g"); //$NON-NLS-1$
@@ -1472,52 +1491,18 @@
Select select = new Select();
select.addSymbol(new Constant(new Double(1.3e8))); //$NON-NLS-1$
-
- Query query = new Query();
- query.setSelect(select);
- query.setFrom(from);
-
- helpTest("SELECT 1.3e8 FROM a.g1", //$NON-NLS-1$
- "SELECT 1.3E8 FROM a.g1", //$NON-NLS-1$
- query);
- }
-
- /** SELECT -1.3e-6 FROM a.g1 */
- @Test public void testFloatWithMinusE() {
- GroupSymbol g = new GroupSymbol("a.g1"); //$NON-NLS-1$
- From from = new From();
- from.addGroup(g);
-
- Select select = new Select();
- select.addSymbol(new Constant(new Double(-1.3e-6))); //$NON-NLS-1$
-
- Query query = new Query();
- query.setSelect(select);
- query.setFrom(from);
-
- helpTest("SELECT -1.3e-6 FROM a.g1", //$NON-NLS-1$
- "SELECT -1.3E-6 FROM a.g1", //$NON-NLS-1$
- query);
- }
-
- /** SELECT -1.3e+8 FROM a.g1 */
- @Test public void testFloatWithPlusE() {
- GroupSymbol g = new GroupSymbol("a.g1"); //$NON-NLS-1$
- From from = new From();
- from.addGroup(g);
-
- Select select = new Select();
select.addSymbol(new Constant(new Double(-1.3e+8))); //$NON-NLS-1$
+ select.addSymbol(new Constant(new Double(+1.3e-8))); //$NON-NLS-1$
Query query = new Query();
query.setSelect(select);
query.setFrom(from);
- helpTest("SELECT -1.3e+8 FROM a.g1", //$NON-NLS-1$
- "SELECT -1.3E8 FROM a.g1", //$NON-NLS-1$
+ helpTest("SELECT 1.3e8, -1.3e+8, +1.3e-8 FROM a.g1", //$NON-NLS-1$
+ "SELECT 1.3E8, -1.3E8, 1.3E-8 FROM a.g1", //$NON-NLS-1$
query);
}
-
+
/** SELECT {d'2002-10-02'} FROM m.g1 */
@Test public void testDateLiteral1() {
GroupSymbol g = new GroupSymbol("m.g1"); //$NON-NLS-1$
@@ -5232,5 +5217,17 @@
Query actualCommand = (Query)QueryParser.getQueryParser().parseCommand("SELECT foo(distinct x, y) over ()", new ParseInfo());
assertEquals("SELECT foo(DISTINCT x, y) OVER ()", actualCommand.toString());
}
+
+ @Test public void testInvalidLimit() {
+ helpException("SELECT * FROM pm1.g1 LIMIT -5");
+ }
+ @Test public void testInvalidLimit_Offset() {
+ helpException("SELECT * FROM pm1.g1 LIMIT -1, 100");
+ }
+
+ @Test public void testTextTableNegativeWidth() {
+ helpException("SELECT * from texttable(null columns x string width -1) as x");
+ }
+
}
Modified: trunk/engine/src/test/java/org/teiid/query/validator/TestValidator.java
===================================================================
--- trunk/engine/src/test/java/org/teiid/query/validator/TestValidator.java 2012-08-06 20:18:00 UTC (rev 4300)
+++ trunk/engine/src/test/java/org/teiid/query/validator/TestValidator.java 2012-08-07 13:41:48 UTC (rev 4301)
@@ -1367,14 +1367,6 @@
helpValidate("select group2.e1, group3.e2 from group2, group3 WHERE group2.e0 = group3.e0 OPTION MAKEDEP group2 MAKENOTDEP group2, group3", new String[] {"OPTION MAKEDEP group2 MAKENOTDEP group2, group3"}, exampleMetadata()); //$NON-NLS-1$ //$NON-NLS-2$
}
- @Test public void testInvalidLimit() {
- helpValidate("SELECT * FROM pm1.g1 LIMIT -5", new String[] {"LIMIT -5"}, RealMetadataFactory.example1Cached()); //$NON-NLS-1$ //$NON-NLS-2$
- }
-
- @Test public void testInvalidLimit_Offset() {
- helpValidate("SELECT * FROM pm1.g1 LIMIT -1, 100", new String[] {"LIMIT -1, 100"}, RealMetadataFactory.example1Cached()); //$NON-NLS-1$ //$NON-NLS-2$
- }
-
/**
* Test case 4237. This test simulates the way the modeler transformation
* panel uses the query resolver and validator to validate a transformation for
@@ -1536,10 +1528,6 @@
helpValidate(userSql, new String[] {"xpathValue('<?xml version=\"1.0\" encoding=\"utf-8\" ?><a><b><c>test</c></b></a>', '//*[local-name()=''bookName\"]')"}, RealMetadataFactory.exampleBQTCached());
}
- @Test public void testTextTableNegativeWidth() {
- helpValidate("SELECT * from texttable(null columns x string width -1) as x", new String[] {"TEXTTABLE(null COLUMNS x string WIDTH -1) AS x"}, RealMetadataFactory.exampleBQTCached());
- }
-
@Test public void testTextTableNoWidth() {
helpValidate("SELECT * from texttable(null columns x string width 1, y integer) as x", new String[] {"TEXTTABLE(null COLUMNS x string WIDTH 1, y integer) AS x"}, RealMetadataFactory.exampleBQTCached());
}
Modified: trunk/test-integration/common/src/test/java/org/teiid/jdbc/TestDynamicImportedMetaData.java
===================================================================
--- trunk/test-integration/common/src/test/java/org/teiid/jdbc/TestDynamicImportedMetaData.java 2012-08-06 20:18:00 UTC (rev 4300)
+++ trunk/test-integration/common/src/test/java/org/teiid/jdbc/TestDynamicImportedMetaData.java 2012-08-07 13:41:48 UTC (rev 4301)
@@ -170,10 +170,9 @@
QueryParser.getQueryParser().parseDDL(mf, ddl);
MetadataStore ms = mf.asMetadataStore();
- String ddl2 = "CREATE VIEW stock (symbol string, price bigdecimal) " +
+ String ddl2 = "CREATE VIEW stock (symbol string, price bigdecimal) OPTIONS (UUID 'uuid')" +
"AS select stock.* from (call MarketData.getTextFiles('*.txt')) f, " +
- "TEXTTABLE(f.file COLUMNS symbol string, price bigdecimal HEADER) stock " +
- "OPTIONS (UUID 'uuid')";
+ "TEXTTABLE(f.file COLUMNS symbol string, price bigdecimal HEADER) stock;";
MetadataFactory m2 = createMetadataFactory("portfolio", new Properties());
QueryParser.getQueryParser().parseDDL(m2, ddl2);
12 years