teiid SVN: r2790 - branches/7.1.x/connectors/connector-salesforce/src/main/java/org/teiid/resource/adapter/salesforce.
by teiid-commits@lists.jboss.org
Author: shawkins
Date: 2010-12-22 09:39:41 -0500 (Wed, 22 Dec 2010)
New Revision: 2790
Modified:
branches/7.1.x/connectors/connector-salesforce/src/main/java/org/teiid/resource/adapter/salesforce/SalesforceConnectionImpl.java
Log:
TEIID-1402 TEIID-1408 ensuring that the queryresult is marked as done for retrieve and that exceptions are simply bubbled up.
Modified: branches/7.1.x/connectors/connector-salesforce/src/main/java/org/teiid/resource/adapter/salesforce/SalesforceConnectionImpl.java
===================================================================
--- branches/7.1.x/connectors/connector-salesforce/src/main/java/org/teiid/resource/adapter/salesforce/SalesforceConnectionImpl.java 2010-12-21 15:36:39 UTC (rev 2789)
+++ branches/7.1.x/connectors/connector-salesforce/src/main/java/org/teiid/resource/adapter/salesforce/SalesforceConnectionImpl.java 2010-12-22 14:39:41 UTC (rev 2790)
@@ -80,7 +80,7 @@
try {
return sfSoap.getUserInfo(sh).getUserName();
} catch (com.sforce.soap.partner.UnexpectedErrorFault e) {
- throw new ResourceException(e.getMessage());
+ throw new ResourceException(e);
}
}
@@ -108,11 +108,11 @@
((BindingProvider)sfSoap).getRequestContext().put(BindingProvider.ENDPOINT_ADDRESS_PROPERTY, url.toExternalForm());
loginResult = sfSoap.login(username, password);
} catch (LoginFault e) {
- throw new ResourceException(e.getCause().getMessage());
+ throw new ResourceException(e);
} catch (InvalidIdFault e) {
- throw new ResourceException(e.getCause().getMessage());
+ throw new ResourceException(e);
} catch (com.sforce.soap.partner.UnexpectedErrorFault e) {
- throw new ResourceException(e.getCause().getMessage());
+ throw new ResourceException(e);
}
LogManager.logTrace(LogConstants.CTX_CONNECTOR, "Login was successful for username " + username); //$NON-NLS-1$
@@ -130,7 +130,7 @@
try {
sfSoap.getUserInfo(sh);
} catch (com.sforce.soap.partner.UnexpectedErrorFault e) {
- throw new ResourceException(e.getMessage());
+ throw new ResourceException(e);
}
}
}
@@ -171,17 +171,17 @@
qr = sfSoap.query(queryString, sh);
}
} catch (InvalidFieldFault e) {
- throw new ResourceException(e.getMessage(), e);
+ throw new ResourceException(e);
} catch (MalformedQueryFault e) {
- throw new ResourceException(e.getMessage(), e);
+ throw new ResourceException(e);
} catch (com.sforce.soap.partner.InvalidSObjectFault e) {
- throw new ResourceException(e.getMessage(), e);
+ throw new ResourceException(e);
} catch (InvalidIdFault e) {
- throw new ResourceException(e.getMessage(), e);
+ throw new ResourceException(e);
} catch (com.sforce.soap.partner.UnexpectedErrorFault e) {
- throw new ResourceException(e.getMessage(), e);
+ throw new ResourceException(e);
} catch (com.sforce.soap.partner.InvalidQueryLocatorFault e) {
- throw new ResourceException(e.getMessage(), e);
+ throw new ResourceException(e);
}
return qr;
}
@@ -192,11 +192,11 @@
try {
return sfSoap.queryMore(queryLocator, sh);
} catch (InvalidFieldFault e) {
- throw new ResourceException(e.getMessage(), e);
+ throw new ResourceException(e);
} catch (com.sforce.soap.partner.UnexpectedErrorFault e) {
- throw new ResourceException(e.getMessage(), e);
+ throw new ResourceException(e);
} catch (com.sforce.soap.partner.InvalidQueryLocatorFault e) {
- throw new ResourceException(e.getMessage(), e);
+ throw new ResourceException(e);
}
}
@@ -206,7 +206,7 @@
try {
results = sfSoap.delete(Arrays.asList(ids), sh);
} catch (com.sforce.soap.partner.UnexpectedErrorFault e) {
- throw new ResourceException(e.getMessage(), e);
+ throw new ResourceException(e);
}
boolean allGood = true;
@@ -244,13 +244,13 @@
try {
result = sfSoap.create(objects, sh);
} catch (InvalidFieldFault e) {
- throw new ResourceException(e.getMessage(), e);
+ throw new ResourceException(e);
} catch (com.sforce.soap.partner.InvalidSObjectFault e) {
- throw new ResourceException(e.getMessage(), e);
+ throw new ResourceException(e);
} catch (InvalidIdFault e) {
- throw new ResourceException(e.getMessage(), e);
+ throw new ResourceException(e);
} catch (com.sforce.soap.partner.UnexpectedErrorFault e) {
- throw new ResourceException(e.getMessage(), e);
+ throw new ResourceException(e);
}
return analyzeResult(result);
}
@@ -269,13 +269,13 @@
try {
result = sfSoap.update(params, sh);
} catch (InvalidFieldFault e) {
- throw new ResourceException(e.getMessage(),e);
+ throw new ResourceException(e);
} catch (com.sforce.soap.partner.InvalidSObjectFault e) {
- throw new ResourceException(e.getMessage(),e);
+ throw new ResourceException(e);
} catch (InvalidIdFault e) {
- throw new ResourceException(e.getMessage(),e);
+ throw new ResourceException(e);
} catch (com.sforce.soap.partner.UnexpectedErrorFault e) {
- throw new ResourceException(e.getMessage(),e);
+ throw new ResourceException(e);
}
return analyzeResult(result);
}
@@ -294,9 +294,9 @@
try {
updated = sfSoap.getUpdated(objectType, startDate, endDate, sh);
} catch (com.sforce.soap.partner.InvalidSObjectFault e) {
- throw new ResourceException(e.getMessage(), e);
+ throw new ResourceException(e);
} catch (com.sforce.soap.partner.UnexpectedErrorFault e) {
- throw new ResourceException(e.getMessage(), e);
+ throw new ResourceException(e);
}
UpdatedResult result = new UpdatedResult();
result.setLatestDateCovered(updated.getLatestDateCovered().toGregorianCalendar());
@@ -310,9 +310,9 @@
try {
deleted = sfSoap.getDeleted(objectName, startCalendar, endCalendar, sh);
} catch (com.sforce.soap.partner.InvalidSObjectFault e) {
- throw new ResourceException(e.getMessage(), e);
+ throw new ResourceException(e);
} catch (com.sforce.soap.partner.UnexpectedErrorFault e) {
- throw new ResourceException(e.getMessage(), e);
+ throw new ResourceException(e);
}
DeletedResult result = new DeletedResult();
result.setLatestDateCovered(deleted.getLatestDateCovered().toGregorianCalendar());
@@ -338,17 +338,18 @@
QueryResult result = new QueryResult();
result.getRecords().addAll(objects);
result.setSize(objects.size());
+ result.setDone(true);
return result;
} catch (InvalidFieldFault e) {
- throw new ResourceException(e.getMessage(),e);
+ throw new ResourceException(e);
} catch (MalformedQueryFault e) {
- throw new ResourceException(e.getMessage(), e);
+ throw new ResourceException(e);
} catch (com.sforce.soap.partner.InvalidSObjectFault e) {
- throw new ResourceException(e.getMessage(), e);
+ throw new ResourceException(e);
} catch (InvalidIdFault e) {
- throw new ResourceException(e.getMessage(), e);
+ throw new ResourceException(e);
} catch (com.sforce.soap.partner.UnexpectedErrorFault e) {
- throw new ResourceException(e.getMessage(),e);
+ throw new ResourceException(e);
}
}
@@ -357,9 +358,7 @@
try {
return sfSoap.describeGlobal(sh);
} catch (com.sforce.soap.partner.UnexpectedErrorFault e) {
- ResourceException ce = new ResourceException(e.getCause().getMessage());
- ce.initCause(e.getCause());
- throw ce;
+ throw new ResourceException(e);
}
}
@@ -367,9 +366,9 @@
try {
return sfSoap.describeSObject(objectName, sh);
} catch (com.sforce.soap.partner.InvalidSObjectFault e) {
- throw new ResourceException(e.getMessage(), e);
+ throw new ResourceException(e);
} catch (com.sforce.soap.partner.UnexpectedErrorFault e) {
- throw new ResourceException(e.getMessage(), e);
+ throw new ResourceException(e);
}
}
14 years
teiid SVN: r2789 - in branches/7.1.x/connectors/translator-salesforce/src: test/java/org/teiid/translator/salesforce/execution/visitors and 1 other directory.
by teiid-commits@lists.jboss.org
Author: shawkins
Date: 2010-12-21 10:36:39 -0500 (Tue, 21 Dec 2010)
New Revision: 2789
Modified:
branches/7.1.x/connectors/translator-salesforce/src/main/java/org/teiid/translator/salesforce/execution/visitors/CriteriaVisitor.java
branches/7.1.x/connectors/translator-salesforce/src/test/java/org/teiid/translator/salesforce/execution/visitors/TestVisitors.java
Log:
TEIID-1402 handling a comparison against an id the same as IN
Modified: branches/7.1.x/connectors/translator-salesforce/src/main/java/org/teiid/translator/salesforce/execution/visitors/CriteriaVisitor.java
===================================================================
--- branches/7.1.x/connectors/translator-salesforce/src/main/java/org/teiid/translator/salesforce/execution/visitors/CriteriaVisitor.java 2010-12-21 14:54:25 UTC (rev 2788)
+++ branches/7.1.x/connectors/translator-salesforce/src/main/java/org/teiid/translator/salesforce/execution/visitors/CriteriaVisitor.java 2010-12-21 15:36:39 UTC (rev 2789)
@@ -23,6 +23,7 @@
import java.sql.Timestamp;
import java.util.ArrayList;
+import java.util.Arrays;
import java.util.HashMap;
import java.util.Iterator;
import java.util.LinkedList;
@@ -102,6 +103,9 @@
addCompareCriteria(criteriaList, criteria);
boolean isAcceptableID = (Operator.EQ == criteria.getOperator() && isIdColumn(criteria.getLeftExpression()));
setHasCriteria(true, isAcceptableID);
+ if (isAcceptableID) {
+ this.idInCriteria = new In(criteria.getLeftExpression(), Arrays.asList(criteria.getRightExpression()), false);
+ }
} catch (TranslatorException e) {
exceptions.add(e);
}
Modified: branches/7.1.x/connectors/translator-salesforce/src/test/java/org/teiid/translator/salesforce/execution/visitors/TestVisitors.java
===================================================================
--- branches/7.1.x/connectors/translator-salesforce/src/test/java/org/teiid/translator/salesforce/execution/visitors/TestVisitors.java 2010-12-21 14:54:25 UTC (rev 2788)
+++ branches/7.1.x/connectors/translator-salesforce/src/test/java/org/teiid/translator/salesforce/execution/visitors/TestVisitors.java 2010-12-21 15:36:39 UTC (rev 2789)
@@ -27,6 +27,7 @@
import java.util.List;
import org.junit.Test;
+import org.mockito.Mockito;
import org.teiid.cdk.api.TranslationUtility;
import org.teiid.core.types.DataTypeManager;
import org.teiid.language.Select;
@@ -40,10 +41,14 @@
import org.teiid.query.metadata.TransformationMetadata;
import org.teiid.query.unittest.FakeMetadataFactory;
import org.teiid.query.unittest.RealMetadataFactory;
+import org.teiid.translator.ExecutionContext;
+import org.teiid.translator.salesforce.Constants;
+import org.teiid.translator.salesforce.SalesforceConnection;
+import org.teiid.translator.salesforce.execution.QueryExecutionImpl;
import org.teiid.translator.salesforce.execution.visitors.JoinQueryVisitor;
import org.teiid.translator.salesforce.execution.visitors.SelectVisitor;
-
+@SuppressWarnings("nls")
public class TestVisitors {
public static QueryMetadataInterface exampleSalesforce() {
@@ -52,9 +57,10 @@
Schema salesforceModel = RealMetadataFactory.createPhysicalModel("SalesforceModel", store); //$NON-NLS-1$
// Create Account group
- Table accounTable = RealMetadataFactory.createPhysicalGroup("Account", salesforceModel); //$NON-NLS-1$
- accounTable.setNameInSource("Account"); //$NON-NLS-1$
- accounTable.setProperty("Supports Query", Boolean.TRUE.toString()); //$NON-NLS-1$
+ Table accountTable = RealMetadataFactory.createPhysicalGroup("Account", salesforceModel); //$NON-NLS-1$
+ accountTable.setNameInSource("Account"); //$NON-NLS-1$
+ accountTable.setProperty("Supports Query", Boolean.TRUE.toString()); //$NON-NLS-1$
+ accountTable.setProperty(Constants.SUPPORTS_RETRIEVE, Boolean.TRUE.toString());
// Create Account Columns
String[] acctNames = new String[] {
"ID", "Name", "Stuff", "Industry" //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$ //$NON-NLS-4$
@@ -63,7 +69,7 @@
DataTypeManager.DefaultDataTypes.STRING, DataTypeManager.DefaultDataTypes.STRING, DataTypeManager.DefaultDataTypes.STRING, DataTypeManager.DefaultDataTypes.STRING
};
- List<Column> acctCols = RealMetadataFactory.createElements(accounTable, acctNames, acctTypes);
+ List<Column> acctCols = RealMetadataFactory.createElements(accountTable, acctNames, acctTypes);
acctCols.get(2).setNativeType("multipicklist"); //$NON-NLS-1$
acctCols.get(2).setSearchType(SearchType.Like_Only);
// Set name in source on each column
@@ -170,5 +176,13 @@
visitor.visit(command);
assertEquals("SELECT Contact.ContactName FROM Contact WHERE ContactName IN('x','y')", visitor.getQuery().toString().trim()); //$NON-NLS-1$
}
+
+ @Test public void testIDCriteria() throws Exception {
+ Select command = (Select)translationUtility.parseCommand("select id, name from Account where id = 'bar'"); //$NON-NLS-1$
+ SalesforceConnection sfc = Mockito.mock(SalesforceConnection.class);
+ QueryExecutionImpl qei = new QueryExecutionImpl(command, sfc, translationUtility.createRuntimeMetadata(), Mockito.mock(ExecutionContext.class));
+ qei.execute();
+ Mockito.verify(sfc).retrieve("Account.id, Account.AccountName", "Account", Arrays.asList("bar"));
+ }
}
14 years
teiid SVN: r2788 - in branches/7.1.x/runtime/src/main: resources and 1 other directory.
by teiid-commits@lists.jboss.org
Author: shawkins
Date: 2010-12-21 09:54:25 -0500 (Tue, 21 Dec 2010)
New Revision: 2788
Removed:
branches/7.1.x/runtime/src/main/java/org/teiid/logging/CommonsLogManagerAdapter.java
branches/7.1.x/runtime/src/main/resources/commons-logging.properties
Log:
TEIID-1404 removing commons logging handling from the runtime jar
Deleted: branches/7.1.x/runtime/src/main/java/org/teiid/logging/CommonsLogManagerAdapter.java
===================================================================
--- branches/7.1.x/runtime/src/main/java/org/teiid/logging/CommonsLogManagerAdapter.java 2010-12-20 16:52:45 UTC (rev 2787)
+++ branches/7.1.x/runtime/src/main/java/org/teiid/logging/CommonsLogManagerAdapter.java 2010-12-21 14:54:25 UTC (rev 2788)
@@ -1,128 +0,0 @@
-/*
- * 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.logging;
-
-import org.apache.commons.logging.Log;
-
-
-/**
- * This class is bridge for hooking LogManager into systems that use apache commons logging. In the Teiid
- * JBoss cache/Jboss Transactions use commons logging. This class used in "commons-logging.properties" file.
- */
-public class CommonsLogManagerAdapter implements Log {
- String context;
-
- public CommonsLogManagerAdapter(String context) {
- this.context = context;
- }
-
- @Override
- public void debug(Object arg0) {
- LogManager.log(MessageLevel.DETAIL, this.context, arg0);
- }
-
- @Override
- public void debug(Object arg0, Throwable arg1) {
- LogManager.log(MessageLevel.DETAIL, this.context, arg1, arg0);
- }
-
- @Override
- public void error(Object arg0) {
- LogManager.log(MessageLevel.ERROR, this.context, arg0);
- }
-
- @Override
- public void error(Object arg0, Throwable arg1) {
- LogManager.log(MessageLevel.ERROR, this.context, arg1, arg0);
- }
-
- @Override
- public void fatal(Object arg0) {
- LogManager.log(MessageLevel.CRITICAL, this.context, arg0);
- }
-
- @Override
- public void fatal(Object arg0, Throwable arg1) {
- LogManager.log(MessageLevel.CRITICAL, this.context, arg1, arg0);
- }
-
- @Override
- public void info(Object arg0) {
- LogManager.log(MessageLevel.INFO, this.context, arg0);
- }
-
- @Override
- public void info(Object arg0, Throwable arg1) {
- LogManager.log(MessageLevel.INFO, this.context, arg1, arg0);
- }
-
- @Override
- public void trace(Object arg0) {
- LogManager.log(MessageLevel.TRACE, this.context, arg0);
- }
-
- @Override
- public void trace(Object arg0, Throwable arg1) {
- LogManager.log(MessageLevel.TRACE, this.context, arg1, arg0);
- }
-
- @Override
- public void warn(Object arg0) {
- LogManager.log(MessageLevel.WARNING, this.context, arg0);
- }
-
- @Override
- public void warn(Object arg0, Throwable arg1) {
- LogManager.log(MessageLevel.WARNING, this.context, arg1, arg0);
- }
-
- @Override
- public boolean isDebugEnabled() {
- return LogManager.isMessageToBeRecorded(this.context, MessageLevel.DETAIL);
- }
-
- @Override
- public boolean isErrorEnabled() {
- return LogManager.isMessageToBeRecorded(this.context, MessageLevel.ERROR);
- }
-
- @Override
- public boolean isFatalEnabled() {
- return LogManager.isMessageToBeRecorded(this.context, MessageLevel.CRITICAL);
- }
-
- @Override
- public boolean isInfoEnabled() {
- return LogManager.isMessageToBeRecorded(this.context, MessageLevel.INFO);
- }
-
- @Override
- public boolean isTraceEnabled() {
- return LogManager.isMessageToBeRecorded(this.context, MessageLevel.TRACE);
- }
-
- @Override
- public boolean isWarnEnabled() {
- return LogManager.isMessageToBeRecorded(this.context, MessageLevel.WARNING);
- }
-}
Deleted: branches/7.1.x/runtime/src/main/resources/commons-logging.properties
===================================================================
--- branches/7.1.x/runtime/src/main/resources/commons-logging.properties 2010-12-20 16:52:45 UTC (rev 2787)
+++ branches/7.1.x/runtime/src/main/resources/commons-logging.properties 2010-12-21 14:54:25 UTC (rev 2788)
@@ -1,2 +0,0 @@
-# overrides the logging in jboss cache and jboss transactions integration code
-org.apache.commons.logging.Log=org.teiid.logging.CommonsLogManagerAdapter
\ No newline at end of file
14 years
teiid SVN: r2787 - in trunk: engine/src/main/java/org/teiid/query/optimizer/relational and 6 other directories.
by teiid-commits@lists.jboss.org
Author: shawkins
Date: 2010-12-20 11:52:45 -0500 (Mon, 20 Dec 2010)
New Revision: 2787
Modified:
trunk/documentation/reference/src/main/docbook/en-US/content/federated_planning.xml
trunk/documentation/reference/src/main/docbook/en-US/content/updatable_views.xml
trunk/engine/src/main/java/org/teiid/query/optimizer/relational/PartitionAnalyzer.java
trunk/engine/src/main/java/org/teiid/query/optimizer/relational/RelationalPlanner.java
trunk/engine/src/main/java/org/teiid/query/resolver/ProcedureContainerResolver.java
trunk/engine/src/main/java/org/teiid/query/rewriter/QueryRewriter.java
trunk/engine/src/main/java/org/teiid/query/validator/UpdateValidator.java
trunk/engine/src/main/java/org/teiid/query/validator/ValidationVisitor.java
trunk/engine/src/main/resources/org/teiid/query/i18n.properties
trunk/engine/src/test/java/org/teiid/query/processor/TestInherintlyUpdatableViews.java
trunk/engine/src/test/java/org/teiid/query/validator/TestUpdateValidator.java
Log:
TEIID-1376 adding support for partition wise joins. also updating the docs and allowing for inserts against views defined by partitioned unions
Modified: trunk/documentation/reference/src/main/docbook/en-US/content/federated_planning.xml
===================================================================
--- trunk/documentation/reference/src/main/docbook/en-US/content/federated_planning.xml 2010-12-17 21:22:54 UTC (rev 2786)
+++ trunk/documentation/reference/src/main/docbook/en-US/content/federated_planning.xml 2010-12-20 16:52:45 UTC (rev 2787)
@@ -1,8 +1,5 @@
<?xml version="1.0" encoding="UTF-8"?>
-<!DOCTYPE chapter PUBLIC "-//OASIS//DTD DocBook XML V4.5//EN" "http://www.oasis-open.org/docbook/xml/4.5/docbookx.dtd"
-[
- <!ENTITY access_pattern "<link linkend='access_patterns'>access patterns</link>">
-]>
+<!DOCTYPE chapter PUBLIC "-//OASIS//DTD DocBook XML V4.5//EN" "http://www.oasis-open.org/docbook/xml/4.5/docbookx.dtd">
<chapter id="federated_planning">
<title>Federated Planning</title>
<para>Teiid at its core is a federated relational query
@@ -173,7 +170,7 @@
data retrieved from the second source and the number of join
comparisons that must be performed.</para>
<para> The conditions when a dependent join is used are determined
- by the query planner based on &access_pattern;, hints, and
+ by the query planner based on <xref linkend='access_patterns'/>, hints, and
costing information.</para>
<para>
Teiid supports the MAKEDEP and MAKENOTDEP hints. Theses are
@@ -181,7 +178,7 @@
<link linkend="option_clause">OPTION clause</link>
or directly in the
<link linkend="from_clause">FROM clause</link>
- . As long as all &access_patterns; can be met, the MAKEDEP and
+ . As long as all <xref linkend='access_patterns'/> can be met, the MAKEDEP and
MAKENOTDEP hints override any use of costing information.
</para>
<tip>
@@ -248,6 +245,18 @@
treated as an optional join and does not require a hint.</para>
</tip>
</section>
+ <section id="partitioned_union">
+ <title>Partitioned Union</title>
+ <para>Union partitioning is inferred from the transformation/inline view. If one (or more) of the UNION columns is defined by constants and/or has WHERE clause IN predicates containing only constants
+ that make each branch mutually exclusive, then the UNION is considered partitioned.
+ UNION ALL must be used and the UNION cannot have a LIMIT, WITH, or ORDER BY clause (although individual branches may use LIMIT, WITH, or ORDER BY).
+ Partitioning values should not be null.
+ For example the view definition "select 1 as x, y from foo union all select z, a from foo1 where z in (2, 3)" would be considered partitioned on column x,
+ since the first branch can only be the value 1 and the second branch can only be the values 2 or 3.
+ Note that more advanced or explicit partition could be considered in the future.
+ The concept of a partitioned union is used for performing partition-wise joins and in <xref linkend="updatable_views"/>.
+ </para>
+ </section>
<section id="standard_relational_techniques">
<title>Standard Relational Techniques</title>
<para>
@@ -697,7 +706,7 @@
gets pushed to the source. Later rules focus on either pushing stuff
under the access or pulling the access node up the tree to move more
work down to the data sources. This rule is also responsible for
- placing &access_patterns;.</para>
+ placing <xref linkend='access_patterns'/>.</para>
</listitem>
<listitem>
<para>RulePushSelectCriteria - pushes select criteria down through
@@ -813,9 +822,9 @@
<listitem>
<para>RulePlanJoins – this rule attempts to find an optimal
ordering of the joins performed in the plan, while ensuring that
- &access_patterns; dependencies are met. This rule has three main
+ <xref linkend='access_patterns'/> dependencies are met. This rule has three main
steps. First it must determine an ordering of joins that satisfy
- the &access_patterns; present. Second it will heuristically create
+ the access patterns present. Second it will heuristically create
joins that can be pushed to the source (if a set of joins are pushed
to the source, we will not attempt to create an optimal ordering
within that set. More than likely it will be sent to the source in
@@ -914,6 +923,11 @@
choice of a hash join would also be evaluated here. Also costing
should be used to determine the strategy cost. </para>
</listitem>
+ <listitem>
+ <para>RuleDecomposeJoin - this rule perfomrs a partition-wise join optimization on joins of <xref linkend="partitioned_union"/>.
+ The decision to decompose is based upon detecting that each side of the join is a partitioned union (note that non-ansi joins of more than 2 tables may cause the optimization to not detect the appropriate join).
+ The rule currently only looks for situations where at most 1 partition matches from each side.</para>
+ </listitem>
<listitem>
<para>RuleCollapseSource - this rule removes all nodes below an
Access node and collapses them into an equivalent query that is
Modified: trunk/documentation/reference/src/main/docbook/en-US/content/updatable_views.xml
===================================================================
--- trunk/documentation/reference/src/main/docbook/en-US/content/updatable_views.xml 2010-12-17 21:22:54 UTC (rev 2786)
+++ trunk/documentation/reference/src/main/docbook/en-US/content/updatable_views.xml 2010-12-20 16:52:45 UTC (rev 2787)
@@ -27,7 +27,8 @@
</itemizedlist>
<para>A UNION ALL can define an inherently updatable view only if each of the UNION branches is itself inherently updatable.
- A view defined by a UNION ALL though does not support inherent INSERTs.</para>
+ A view defined by a UNION ALL can support inherent INSERTs if it is a <xref linkend="partitioned_union"/> and
+ the INSERT specifies values that belong to a single partition.</para>
<para>Any view column that is not mapped directly to a column is not updatable and cannot be targeted by an UPDATE set
clause or be an INSERT column.</para>
Modified: trunk/engine/src/main/java/org/teiid/query/optimizer/relational/PartitionAnalyzer.java
===================================================================
--- trunk/engine/src/main/java/org/teiid/query/optimizer/relational/PartitionAnalyzer.java 2010-12-17 21:22:54 UTC (rev 2786)
+++ trunk/engine/src/main/java/org/teiid/query/optimizer/relational/PartitionAnalyzer.java 2010-12-20 16:52:45 UTC (rev 2787)
@@ -34,6 +34,7 @@
import java.util.Set;
import java.util.TreeSet;
+import org.teiid.core.types.DataTypeManager;
import org.teiid.query.sql.lang.Criteria;
import org.teiid.query.sql.lang.Query;
import org.teiid.query.sql.lang.QueryCommand;
@@ -92,10 +93,10 @@
return partitions;
}
- private static boolean extractQueries(QueryCommand queryCommand, List<Query> result) {
+ public static boolean extractQueries(QueryCommand queryCommand, List<Query> result) {
if (queryCommand instanceof SetQuery) {
SetQuery sq = (SetQuery)queryCommand;
- if (sq.isAll() && sq.getOperation() == Operation.UNION && sq.getOrderBy() == null && sq.getLimit() == null) {
+ if (sq.isAll() && sq.getOperation() == Operation.UNION && sq.getOrderBy() == null && sq.getLimit() == null && sq.getWith() == null) {
if (!extractQueries(sq.getLeftQuery(), result)) {
return false;
}
@@ -136,7 +137,9 @@
Map<ElementSymbol, Set<Constant>> result = new HashMap<ElementSymbol, Set<Constant>>();
for (int i = 0; i < projected.size(); i++) {
Expression ex = SymbolMap.getExpression(projected.get(i));
-
+ if (DataTypeManager.isNonComparable(DataTypeManager.getDataTypeName(ex.getType()))) {
+ continue;
+ }
if (ex instanceof Constant) {
result.put(projectedSymbols.get(i), Collections.singleton((Constant)ex));
} else {
Modified: trunk/engine/src/main/java/org/teiid/query/optimizer/relational/RelationalPlanner.java
===================================================================
--- trunk/engine/src/main/java/org/teiid/query/optimizer/relational/RelationalPlanner.java 2010-12-17 21:22:54 UTC (rev 2786)
+++ trunk/engine/src/main/java/org/teiid/query/optimizer/relational/RelationalPlanner.java 2010-12-20 16:52:45 UTC (rev 2787)
@@ -887,6 +887,7 @@
SymbolMap map = SymbolMap.createSymbolMap(group, projectCols, metadata);
node.setProperty(NodeConstants.Info.SYMBOL_MAP, map);
if (nestedCommand instanceof SetQuery) {
+ //TODO: should cache for views
Map<ElementSymbol, List<Set<Constant>>> partitionInfo = PartitionAnalyzer.extractPartionInfo((SetQuery)nestedCommand, map.getKeys());
node.setProperty(NodeConstants.Info.PARTITION_INFO, partitionInfo);
}
Modified: trunk/engine/src/main/java/org/teiid/query/resolver/ProcedureContainerResolver.java
===================================================================
--- trunk/engine/src/main/java/org/teiid/query/resolver/ProcedureContainerResolver.java 2010-12-17 21:22:54 UTC (rev 2786)
+++ trunk/engine/src/main/java/org/teiid/query/resolver/ProcedureContainerResolver.java 2010-12-20 16:52:45 UTC (rev 2787)
@@ -235,20 +235,16 @@
if(!procCommand.getGroup().isTempGroupSymbol() && metadata.isVirtualGroup(procCommand.getGroup().getMetadataID())) {
String plan = getPlan(metadata, procCommand.getGroup());
if (plan == null && !metadata.isProcedure(procCommand.getGroup().getMetadataID())) {
- UpdateInfo info = getUpdateInfo(procCommand.getGroup(), metadata);
int type = procCommand.getType();
- if ((info.isDeleteValidationError() && type == Command.TYPE_DELETE)
- || (info.isUpdateValidationError() && type == Command.TYPE_UPDATE)
- || (info.isInsertValidationError() && type == Command.TYPE_INSERT)) {
- throw new QueryResolverException("ERR.015.008.0009", QueryPlugin.Util.getString("ERR.015.008.0009", procCommand.getGroup(), procCommand.getClass().getSimpleName())); //$NON-NLS-1$ //$NON-NLS-2$
- }
+ //force validation
+ getUpdateInfo(procCommand.getGroup(), metadata, type);
}
return plan;
}
return null;
}
- public static UpdateInfo getUpdateInfo(GroupSymbol group, QueryMetadataInterface metadata) throws QueryMetadataException, TeiidComponentException, QueryResolverException {
+ public static UpdateInfo getUpdateInfo(GroupSymbol group, QueryMetadataInterface metadata, int type) throws QueryMetadataException, TeiidComponentException, QueryResolverException {
//if this is not a view, just return null
if(group.isTempGroupSymbol() || !metadata.isVirtualGroup(group.getMetadataID())) {
return null;
@@ -268,6 +264,18 @@
}
metadata.addToMetadataCache(group.getMetadataID(), "UpdateInfo", info); //$NON-NLS-1$
}
+
+ if ((info.isDeleteValidationError() && type == Command.TYPE_DELETE)
+ || (info.isUpdateValidationError() && type == Command.TYPE_UPDATE)
+ || (info.isInsertValidationError() && type == Command.TYPE_INSERT)) {
+ String name = "Delete"; //$NON-NLS-1$
+ if (type == Command.TYPE_UPDATE) {
+ name = "Update"; //$NON-NLS-1$
+ } else if (type == Command.TYPE_INSERT) {
+ name = "Insert"; //$NON-NLS-1$
+ }
+ throw new QueryResolverException("ERR.015.008.0009", QueryPlugin.Util.getString("ERR.015.008.0009", group, name)); //$NON-NLS-1$ //$NON-NLS-2$
+ }
return info;
}
@@ -283,7 +291,7 @@
// Resolve group so we can tell whether it is an update procedure
GroupSymbol group = procCommand.getGroup();
ResolverUtil.resolveGroup(group, metadata);
- procCommand.setUpdateInfo(ProcedureContainerResolver.getUpdateInfo(group, metadata));
+ procCommand.setUpdateInfo(ProcedureContainerResolver.getUpdateInfo(group, metadata, procCommand.getType()));
}
public static GroupSymbol addScalarGroup(String name, TempMetadataStore metadata, GroupContext externalGroups, List symbols) {
Modified: trunk/engine/src/main/java/org/teiid/query/rewriter/QueryRewriter.java
===================================================================
--- trunk/engine/src/main/java/org/teiid/query/rewriter/QueryRewriter.java 2010-12-17 21:22:54 UTC (rev 2786)
+++ trunk/engine/src/main/java/org/teiid/query/rewriter/QueryRewriter.java 2010-12-20 16:52:45 UTC (rev 2787)
@@ -2547,8 +2547,8 @@
private Insert rewriteInsert(Insert insert) throws TeiidComponentException, TeiidProcessingException{
UpdateInfo info = insert.getUpdateInfo();
if (info != null && info.isInherentInsert()) {
- //pass through
- UpdateMapping mapping = info.findUpdateMapping(insert.getVariables(), false);
+ //TODO: update error messages
+ UpdateMapping mapping = info.findInsertUpdateMapping(insert, true);
if (mapping == null) {
throw new QueryValidatorException(QueryPlugin.Util.getString("ValidationVisitor.nonUpdatable", insert.getVariables())); //$NON-NLS-1$
}
@@ -2559,7 +2559,7 @@
}
insert.setVariables(mappedSymbols);
insert.setGroup(mapping.getGroup().clone());
- insert.setUpdateInfo(ProcedureContainerResolver.getUpdateInfo(insert.getGroup(), metadata));
+ insert.setUpdateInfo(ProcedureContainerResolver.getUpdateInfo(insert.getGroup(), metadata, Command.TYPE_INSERT));
return rewriteInsert(insert);
}
@@ -2731,7 +2731,7 @@
update.setCriteria(Criteria.combineCriteria(update.getCriteria(), (Criteria)info.getViewDefinition().getCriteria().clone()));
}
//resolve
- update.setUpdateInfo(ProcedureContainerResolver.getUpdateInfo(update.getGroup(), metadata));
+ update.setUpdateInfo(ProcedureContainerResolver.getUpdateInfo(update.getGroup(), metadata, Command.TYPE_UPDATE));
return rewriteUpdate(update);
}
Query query = (Query)info.getViewDefinition().clone();
@@ -2893,7 +2893,7 @@
delete.setGroup(mapping.getGroup().clone());
//TODO: properly handle correlated references
DeepPostOrderNavigator.doVisit(delete, new ExpressionMappingVisitor(mapping.getUpdatableViewSymbols(), true));
- delete.setUpdateInfo(ProcedureContainerResolver.getUpdateInfo(delete.getGroup(), metadata));
+ delete.setUpdateInfo(ProcedureContainerResolver.getUpdateInfo(delete.getGroup(), metadata, Command.TYPE_DELETE));
if (info.getViewDefinition().getCriteria() != null) {
delete.setCriteria(Criteria.combineCriteria(delete.getCriteria(), (Criteria)info.getViewDefinition().getCriteria().clone()));
}
Modified: trunk/engine/src/main/java/org/teiid/query/validator/UpdateValidator.java
===================================================================
--- trunk/engine/src/main/java/org/teiid/query/validator/UpdateValidator.java 2010-12-17 21:22:54 UTC (rev 2786)
+++ trunk/engine/src/main/java/org/teiid/query/validator/UpdateValidator.java 2010-12-20 16:52:45 UTC (rev 2787)
@@ -22,27 +22,31 @@
package org.teiid.query.validator;
+import java.util.ArrayList;
import java.util.Collection;
import java.util.HashMap;
import java.util.HashSet;
import java.util.LinkedList;
import java.util.List;
import java.util.Map;
+import java.util.Set;
import org.teiid.api.exception.query.QueryMetadataException;
+import org.teiid.api.exception.query.QueryValidatorException;
import org.teiid.core.TeiidComponentException;
import org.teiid.core.util.StringUtil;
import org.teiid.language.SQLConstants;
import org.teiid.query.QueryPlugin;
import org.teiid.query.metadata.QueryMetadataInterface;
import org.teiid.query.metadata.SupportConstants;
+import org.teiid.query.optimizer.relational.PartitionAnalyzer;
import org.teiid.query.resolver.util.ResolverUtil;
import org.teiid.query.sql.lang.Command;
+import org.teiid.query.sql.lang.Insert;
import org.teiid.query.sql.lang.Query;
-import org.teiid.query.sql.lang.QueryCommand;
import org.teiid.query.sql.lang.SetQuery;
import org.teiid.query.sql.lang.UnaryFromClause;
-import org.teiid.query.sql.lang.SetQuery.Operation;
+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.GroupSymbol;
@@ -54,6 +58,8 @@
* the virtual group is always a <code>Query</code>. This object visits various parts of
* this <code>Query</code> and verifies if the virtual group definition will allows it to be
* updated.</p>
+ *
+ * TODO: add insert support based upon partitioning
*/
public class UpdateValidator {
@@ -111,8 +117,13 @@
private UpdateType insertType;
private boolean insertValidationError;
private Query view;
+ private Map<ElementSymbol, List<Set<Constant>>> partitionInfo;
private List<UpdateInfo> unionBranches = new LinkedList<UpdateInfo>();
+ public Map<ElementSymbol, List<Set<Constant>>> getPartitionInfo() {
+ return partitionInfo;
+ }
+
public boolean isSimple() {
return isSimple;
}
@@ -154,6 +165,9 @@
}
public UpdateMapping findUpdateMapping(Collection<ElementSymbol> updateCols, boolean insert) {
+ if (updateCols.isEmpty() && this.updatableGroups.size() > 1) {
+ return null;
+ }
for (UpdateMapping entry : this.updatableGroups.values()) {
if (((insert && entry.insertAllowed) || (!insert && entry.updateAllowed)) && entry.updatableViewSymbols.keySet().containsAll(updateCols)) {
return entry;
@@ -162,6 +176,56 @@
return null;
}
+ public UpdateMapping findInsertUpdateMapping(Insert insert, boolean rewrite) throws QueryValidatorException {
+ if (getUnionBranches().isEmpty()) {
+ return findUpdateMapping(insert.getVariables(), true);
+ }
+ if (insert.getQueryExpression() != null) {
+ //TODO: this could be done in a loop, see about adding a validation
+ throw new QueryValidatorException(QueryPlugin.Util.getString("ValidationVisitor.insert_qe_partition", insert.getGroup())); //$NON-NLS-1$
+ }
+ int partition = -1;
+ List<ElementSymbol> filteredColumns = new LinkedList<ElementSymbol>();
+ for (Map.Entry<ElementSymbol, List<Set<Constant>>> entry : partitionInfo.entrySet()) {
+ int index = insert.getVariables().indexOf(entry.getKey());
+ if (index == -1) {
+ continue;
+ }
+ Expression value = (Expression)insert.getValues().get(index);
+ if (!(value instanceof Constant)) {
+ continue;
+ }
+ for (int i = 0; i < entry.getValue().size(); i++) {
+ if (entry.getValue().get(i).contains(value)) {
+ if (entry.getValue().get(i).size() == 1) {
+ filteredColumns.add(entry.getKey());
+ }
+ if (partition == -1) {
+ partition = i;
+ } else if (partition != i) {
+ throw new QueryValidatorException(QueryPlugin.Util.getString("ValidationVisitor.insert_no_partition", insert.getGroup(), insert.getVariables())); //$NON-NLS-1$
+ }
+ }
+ }
+ }
+ if (partition == -1) {
+ throw new QueryValidatorException(QueryPlugin.Util.getString("ValidationVisitor.insert_no_partition", insert.getGroup(), insert.getVariables())); //$NON-NLS-1$
+ }
+ UpdateInfo info = this;
+ if (partition > 0) {
+ info = info.getUnionBranches().get(partition - 1);
+ }
+ List<ElementSymbol> variables = rewrite?insert.getVariables():new ArrayList<ElementSymbol>(insert.getVariables());
+ for (ElementSymbol elementSymbol : filteredColumns) {
+ int index = insert.getVariables().indexOf(elementSymbol);
+ variables.remove(index);
+ if (rewrite) {
+ insert.getValues().remove(index);
+ }
+ }
+ return info.findUpdateMapping(variables, true);
+ }
+
public Query getViewDefinition() {
return view;
}
@@ -229,15 +293,43 @@
handleValidationError(QueryPlugin.Util.getString("ERR.015.012.0013"), true, true, true); //$NON-NLS-1$
return;
}
- if (setQuery.getOperation() != Operation.UNION || !setQuery.isAll()) {
- handleValidationError(QueryPlugin.Util.getString("ERR.015.012.0001"), true, true, true); //$NON-NLS-1$
- return;
+ LinkedList<Query> queries = new LinkedList<Query>();
+ if (!PartitionAnalyzer.extractQueries((SetQuery)command, queries)) {
+ handleValidationError(QueryPlugin.Util.getString("ERR.015.012.0001"), true, true, true); //$NON-NLS-1$
+ return;
+ }
+ Map<ElementSymbol, List<Set<Constant>>> partitions = PartitionAnalyzer.extractPartionInfo((SetQuery)command, viewSymbols);
+ this.updateInfo.partitionInfo = partitions;
+ if (partitions.isEmpty()) {
+ handleValidationError(QueryPlugin.Util.getString("ERR.015.012.0018"), false, true, false); //$NON-NLS-1$
}
- validateBranch(viewSymbols, setQuery.getLeftQuery());
- validateBranch(viewSymbols, setQuery.getRightQuery());
+ boolean first = true;
+ for (Query query : queries) {
+ UpdateInfo ui = this.updateInfo;
+ if (!first) {
+ this.updateInfo = new UpdateInfo();
+ this.updateInfo.deleteType = ui.deleteType;
+ this.updateInfo.insertType = ui.insertType;
+ this.updateInfo.updateType = ui.updateType;
+ }
+ internalValidate(query, viewSymbols);
+ //accumulate the errors on the first branch - will be checked at resolve time
+ ui.deleteValidationError |= this.updateInfo.deleteValidationError;
+ ui.updateValidationError |= this.updateInfo.updateValidationError;
+ ui.insertValidationError |= this.updateInfo.insertValidationError;
+ if (!first) {
+ ui.unionBranches.add(this.updateInfo);
+ this.updateInfo = ui;
+ } else {
+ first = false;
+ }
+ }
return;
}
-
+ internalValidate(command, viewSymbols);
+ }
+
+ private void internalValidate(Command command, List<ElementSymbol> viewSymbols) throws QueryMetadataException, TeiidComponentException {
if (!(command instanceof Query)) {
handleValidationError(QueryPlugin.Util.getString("ERR.015.012.0001"), true, true, true); //$NON-NLS-1$
return;
@@ -251,7 +343,7 @@
}
if (query.getWith() != null) {
- handleValidationError(QueryPlugin.Util.getString("ERR.015.012.0002"), true, true, true); //$NON-NLS-1$
+ report.handleValidationError(QueryPlugin.Util.getString("ERR.015.012.0002")); //$NON-NLS-1$
updateInfo.isSimple = false;
}
@@ -364,35 +456,6 @@
}
}
- private void validateBranch(List<ElementSymbol> viewSymbols,
- QueryCommand query) throws QueryMetadataException,
- TeiidComponentException {
- if (!this.updateInfo.insertValidationError) {
- handleValidationError(QueryPlugin.Util.getString("ERR.015.012.0018"), false, true, false); //$NON-NLS-1$
- }
- if (!this.updateInfo.isInherentDelete() && !this.updateInfo.isInherentUpdate()) {
- return; //don't bother
- }
- UpdateValidator uv = this;
- if (this.updateInfo.view != null) {
- uv = new UpdateValidator(metadata, null, null, null);
- uv.updateInfo.deleteType = this.updateInfo.deleteType;
- uv.updateInfo.insertType = this.updateInfo.insertType;
- uv.updateInfo.updateType = this.updateInfo.updateType;
- }
- uv.validate(query, viewSymbols);
- if (uv != this) {
- UpdateInfo info = uv.getUpdateInfo();
- this.updateInfo.deleteValidationError |= info.deleteValidationError;
- this.updateInfo.updateValidationError |= info.updateValidationError;
- if (info.view != null) {
- this.updateInfo.unionBranches.add(info);
- } else {
- this.updateInfo.unionBranches.addAll(info.unionBranches);
- }
- }
- }
-
private void setUpdateFlags(GroupSymbol groupSymbol) throws QueryMetadataException, TeiidComponentException {
UpdateMapping info = updateInfo.updatableGroups.get(groupSymbol.getCanonicalName());
Modified: trunk/engine/src/main/java/org/teiid/query/validator/ValidationVisitor.java
===================================================================
--- trunk/engine/src/main/java/org/teiid/query/validator/ValidationVisitor.java 2010-12-17 21:22:54 UTC (rev 2786)
+++ trunk/engine/src/main/java/org/teiid/query/validator/ValidationVisitor.java 2010-12-20 16:52:45 UTC (rev 2787)
@@ -244,10 +244,13 @@
validateMultisourceInsert(obj.getGroup());
}
if (obj.getUpdateInfo() != null && obj.getUpdateInfo().isInherentInsert()) {
- Collection<ElementSymbol> updateCols = obj.getVariables();
- if (obj.getUpdateInfo().findUpdateMapping(updateCols, false) == null) {
- handleValidationError(QueryPlugin.Util.getString("ValidationVisitor.nonUpdatable", updateCols), obj); //$NON-NLS-1$
- }
+ try {
+ if (obj.getUpdateInfo().findInsertUpdateMapping(obj, false) == null) {
+ handleValidationError(QueryPlugin.Util.getString("ValidationVisitor.nonUpdatable", obj.getVariables()), obj); //$NON-NLS-1$
+ }
+ } catch (QueryValidatorException e) {
+ handleValidationError(e.getMessage(), obj);
+ }
}
}
Modified: trunk/engine/src/main/resources/org/teiid/query/i18n.properties
===================================================================
--- trunk/engine/src/main/resources/org/teiid/query/i18n.properties 2010-12-17 21:22:54 UTC (rev 2786)
+++ trunk/engine/src/main/resources/org/teiid/query/i18n.properties 2010-12-20 16:52:45 UTC (rev 2787)
@@ -199,6 +199,8 @@
ValidationVisitor.multisource_insert = A multi-source table, {0}, cannot be used in an INSERT with query expression or SELECT INTO statement.
ValidationVisitor.invalid_encoding = Invalid encoding: {0}.
ValidationVisitor.nonUpdatable = The specified change set {0} against an inherently updatable view does not map to a key preserving group.
+ValidationVisitor.insert_qe_partition = Inserts with query expressions cannot be performed against a partitioned UNION view {0}.
+ValidationVisitor.insert_no_partition = Could not determine INSERT target for a partitioned UNION view {0} with values {1}.
ERR.015.012.0029 = INSERT, UPDATE, and DELETE not allowed on XML documents
ERR.015.012.0030 = Commands used in stored procedure language not allowed on XML documents
ERR.015.012.0031 = Queries against XML documents can not have a GROUP By clause
Modified: trunk/engine/src/test/java/org/teiid/query/processor/TestInherintlyUpdatableViews.java
===================================================================
--- trunk/engine/src/test/java/org/teiid/query/processor/TestInherintlyUpdatableViews.java 2010-12-17 21:22:54 UTC (rev 2786)
+++ trunk/engine/src/test/java/org/teiid/query/processor/TestInherintlyUpdatableViews.java 2010-12-20 16:52:45 UTC (rev 2787)
@@ -131,5 +131,16 @@
helpTest(userSql, viewSql, "CREATE PROCEDURE\nBEGIN\nLOOP ON (SELECT pm1.g2.e2 AS s_0 FROM pm1.g1 INNER JOIN pm1.g2 ON g1.e1 = g2.e1 WHERE pm1.g2.e2 < 10) AS X\nBEGIN\nDELETE FROM pm1.g2 WHERE pm1.g2.e2 = X.s_0;\nVARIABLES.ROWS_UPDATED = (VARIABLES.ROWS_UPDATED + 1);\nEND\nEND",
dm);
}
+
+ /**
+ * Here we should use the partitioning
+ * @throws Exception
+ */
+ @Test public void testInsertPartitionedUnion() throws Exception {
+ String userSql = "insert into vm1.gx (e1, e2) values (1, 2)"; //$NON-NLS-1$
+ String viewSql = "select 1 as e1, e2 from pm1.g1 union all select 2 as e1, e2 from pm1.g2";
+ String expectedSql = "INSERT INTO pm1.g1 (e2) VALUES (2)";
+ helpTest(userSql, viewSql, expectedSql, null);
+ }
}
Modified: trunk/engine/src/test/java/org/teiid/query/validator/TestUpdateValidator.java
===================================================================
--- trunk/engine/src/test/java/org/teiid/query/validator/TestUpdateValidator.java 2010-12-17 21:22:54 UTC (rev 2786)
+++ trunk/engine/src/test/java/org/teiid/query/validator/TestUpdateValidator.java 2010-12-20 16:52:45 UTC (rev 2787)
@@ -160,19 +160,19 @@
Table vm1g5 = RealMetadataFactory.createVirtualGroup("g5", vm1, vm1g5n1); //$NON-NLS-1$
// Create virtual elements
- List<Column> vm1g1e = RealMetadataFactory.createElements(vm1g1,
+ RealMetadataFactory.createElements(vm1g1,
new String[] { "a", "e2"}, //$NON-NLS-1$ //$NON-NLS-2$
new String[] { DataTypeManager.DefaultDataTypes.STRING, DataTypeManager.DefaultDataTypes.INTEGER});
- List<Column> vm1g2e = RealMetadataFactory.createElements(vm1g2,
+ RealMetadataFactory.createElements(vm1g2,
new String[] { "e1", "e2","e3", "e4"}, //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$ //$NON-NLS-4$
new String[] { DataTypeManager.DefaultDataTypes.STRING, DataTypeManager.DefaultDataTypes.INTEGER, DataTypeManager.DefaultDataTypes.BOOLEAN, DataTypeManager.DefaultDataTypes.DOUBLE });
- List<Column> vm1g3e = RealMetadataFactory.createElements(vm1g3,
+ RealMetadataFactory.createElements(vm1g3,
new String[] { "e1", "e2"}, //$NON-NLS-1$ //$NON-NLS-2$
new String[] { DataTypeManager.DefaultDataTypes.STRING, DataTypeManager.DefaultDataTypes.INTEGER, });
- List<Column> vm1g4e = RealMetadataFactory.createElements(vm1g4,
+ RealMetadataFactory.createElements(vm1g4,
new String[] { "e1", "e3"}, //$NON-NLS-1$ //$NON-NLS-2$
new String[] { DataTypeManager.DefaultDataTypes.STRING, DataTypeManager.DefaultDataTypes.BOOLEAN });
- List<Column> vm1g5e = RealMetadataFactory.createElements(vm1g5,
+ RealMetadataFactory.createElements(vm1g5,
new String[] { "e2","e3"}, //$NON-NLS-1$ //$NON-NLS-2$
new String[] { DataTypeManager.DefaultDataTypes.INTEGER, DataTypeManager.DefaultDataTypes.BOOLEAN });
@@ -335,6 +335,11 @@
helpTest("SELECT g1.e1, x.e2 FROM pm1.g2 x inner join pm1.g1 on (x.e1 = g1.e1) union all select pm1.g2.e1, pm1.g2.e2 from pm1.g2",
example1(), true, false, false); //$NON-NLS-1$
}
+
+ @Test public void testParitionedUnionAll() {
+ helpTest("SELECT g1.e1, x.e2 FROM pm1.g2 x inner join pm1.g1 on (x.e1 = g1.e1) where x.e2 in (1, 2) union all select pm1.g2.e1, pm1.g2.e2 from pm1.g2 where pm1.g2.e2 in (3, 4)",
+ example1(), false, false, false); //$NON-NLS-1$
+ }
}
14 years
teiid SVN: r2786 - in trunk/engine/src: test/java/org/teiid/query/optimizer and 1 other directories.
by teiid-commits@lists.jboss.org
Author: shawkins
Date: 2010-12-17 16:22:54 -0500 (Fri, 17 Dec 2010)
New Revision: 2786
Modified:
trunk/engine/src/main/java/org/teiid/query/rewriter/QueryRewriter.java
trunk/engine/src/test/java/org/teiid/query/optimizer/FakeFunctionMetadataSource.java
trunk/engine/src/test/java/org/teiid/query/rewriter/TestQueryRewriter.java
Log:
TEIID-1401 fixing parse/format rewrite logic
Modified: trunk/engine/src/main/java/org/teiid/query/rewriter/QueryRewriter.java
===================================================================
--- trunk/engine/src/main/java/org/teiid/query/rewriter/QueryRewriter.java 2010-12-17 17:48:17 UTC (rev 2785)
+++ trunk/engine/src/main/java/org/teiid/query/rewriter/QueryRewriter.java 2010-12-17 21:22:54 UTC (rev 2786)
@@ -185,6 +185,11 @@
ALIASED_FUNCTIONS.put("chr", SourceSystemFunctions.CHAR); //$NON-NLS-1$
}
+ private static final Set<String> PARSE_FORMAT_TYPES = new HashSet<String>(Arrays.asList(DataTypeManager.DefaultDataTypes.TIME,
+ DataTypeManager.DefaultDataTypes.DATE, DataTypeManager.DefaultDataTypes.TIMESTAMP, DataTypeManager.DefaultDataTypes.BIG_DECIMAL,
+ DataTypeManager.DefaultDataTypes.BIG_INTEGER, DataTypeManager.DefaultDataTypes.INTEGER, DataTypeManager.DefaultDataTypes.LONG,
+ DataTypeManager.DefaultDataTypes.FLOAT, DataTypeManager.DefaultDataTypes.DOUBLE));
+
private QueryMetadataInterface metadata;
private CommandContext context;
private CreateUpdateProcedureCommand procCommand;
@@ -1779,9 +1784,15 @@
String inverseFunction = null;
if(funcName.startsWith("parse")) { //$NON-NLS-1$
String type = funcName.substring(5);
+ if (!PARSE_FORMAT_TYPES.contains(type)) {
+ return crit;
+ }
inverseFunction = "format" + type; //$NON-NLS-1$
} else if(funcName.startsWith("format")) { //$NON-NLS-1$
String type = funcName.substring(6);
+ if (!PARSE_FORMAT_TYPES.contains(type)) {
+ return crit;
+ }
inverseFunction = "parse" + type; //$NON-NLS-1$
isFormat = true;
} else {
Modified: trunk/engine/src/test/java/org/teiid/query/optimizer/FakeFunctionMetadataSource.java
===================================================================
--- trunk/engine/src/test/java/org/teiid/query/optimizer/FakeFunctionMetadataSource.java 2010-12-17 17:48:17 UTC (rev 2785)
+++ trunk/engine/src/test/java/org/teiid/query/optimizer/FakeFunctionMetadataSource.java 2010-12-17 21:22:54 UTC (rev 2786)
@@ -26,6 +26,8 @@
import java.util.Collection;
import java.util.List;
+import org.teiid.core.types.DataTypeManager;
+import org.teiid.metadata.Datatype;
import org.teiid.metadata.FunctionParameter;
import org.teiid.metadata.FunctionMethod.PushDown;
import org.teiid.query.function.FunctionMetadataSource;
@@ -34,8 +36,8 @@
public class FakeFunctionMetadataSource implements FunctionMetadataSource {
- public Collection getFunctionMethods() {
- List methods = new ArrayList();
+ public Collection<org.teiid.metadata.FunctionMethod> getFunctionMethods() {
+ List<org.teiid.metadata.FunctionMethod> methods = new ArrayList<org.teiid.metadata.FunctionMethod>();
methods.add(new FunctionMethod("xyz", "", "misc", PushDown.MUST_PUSHDOWN, //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$
FakeFunctionMetadataSource.class.getName(), "xyz", //$NON-NLS-1$
new FunctionParameter[0],
@@ -51,6 +53,10 @@
FunctionMethod method2 = new FunctionMethod("misc.namespace.func", "", "", null, null, new FunctionParameter[] {p1}, result); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$
method2.setPushdown(PushDown.MUST_PUSHDOWN);
methods.add(method2);
+
+ FunctionMethod method3 = new FunctionMethod("parsedate_", "", "", null, null, new FunctionParameter[] {p1}, new FunctionParameter("", DataTypeManager.DefaultDataTypes.DATE)); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$
+ method3.setPushdown(PushDown.MUST_PUSHDOWN);
+ methods.add(method3);
return methods;
}
Modified: trunk/engine/src/test/java/org/teiid/query/rewriter/TestQueryRewriter.java
===================================================================
--- trunk/engine/src/test/java/org/teiid/query/rewriter/TestQueryRewriter.java 2010-12-17 17:48:17 UTC (rev 2785)
+++ trunk/engine/src/test/java/org/teiid/query/rewriter/TestQueryRewriter.java 2010-12-17 21:22:54 UTC (rev 2786)
@@ -39,16 +39,19 @@
import org.teiid.client.metadata.ParameterInfo;
import org.teiid.common.buffer.BufferManagerFactory;
import org.teiid.core.TeiidComponentException;
+import org.teiid.core.TeiidException;
import org.teiid.core.TeiidProcessingException;
-import org.teiid.core.TeiidException;
import org.teiid.core.TeiidRuntimeException;
import org.teiid.core.types.DataTypeManager;
import org.teiid.core.util.TimestampWithTimezone;
+import org.teiid.query.function.FunctionLibrary;
+import org.teiid.query.function.FunctionTree;
+import org.teiid.query.function.UDFSource;
import org.teiid.query.metadata.QueryMetadataInterface;
+import org.teiid.query.optimizer.FakeFunctionMetadataSource;
import org.teiid.query.parser.QueryParser;
import org.teiid.query.resolver.QueryResolver;
import org.teiid.query.resolver.util.ResolverVisitor;
-import org.teiid.query.rewriter.QueryRewriter;
import org.teiid.query.sql.lang.Command;
import org.teiid.query.sql.lang.CompareCriteria;
import org.teiid.query.sql.lang.CompoundCriteria;
@@ -2359,5 +2362,12 @@
@Test public void testRewritePredicateOptimization7() throws Exception {
helpTestRewriteCriteria("pm1.g1.e2 > 5 and pm1.g1.e2 < 2", "1 = 0");
}
+
+ @Test public void testUDFParse() throws Exception {
+ FunctionLibrary funcLibrary = new FunctionLibrary(FakeMetadataFactory.SFM.getSystemFunctions(), new FunctionTree(new UDFSource(new FakeFunctionMetadataSource().getFunctionMethods())));
+ FakeMetadataFacade metadata = new FakeMetadataFacade(FakeMetadataFactory.example1Cached().getStore(), funcLibrary);
+ String sql = "parsedate_(pm1.g1.e1) = {d'2001-01-01'}";
+ helpTestRewriteCriteria(sql, parseCriteria(sql, metadata), metadata);
+ }
}
14 years
teiid SVN: r2785 - in trunk: engine/src/main/java/org/teiid/query/optimizer/relational and 7 other directories.
by teiid-commits@lists.jboss.org
Author: shawkins
Date: 2010-12-17 12:48:17 -0500 (Fri, 17 Dec 2010)
New Revision: 2785
Added:
trunk/engine/src/main/java/org/teiid/query/optimizer/relational/PartitionAnalyzer.java
trunk/engine/src/main/java/org/teiid/query/optimizer/relational/rules/RuleDecomposeJoin.java
Modified:
trunk/build/kits/jboss-container/teiid-releasenotes.html
trunk/engine/src/main/java/org/teiid/query/optimizer/relational/RelationalPlanner.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/RuleConstants.java
trunk/engine/src/main/java/org/teiid/query/optimizer/relational/rules/RulePlanUnions.java
trunk/engine/src/main/java/org/teiid/query/optimizer/relational/rules/RulePushAggregates.java
trunk/engine/src/main/java/org/teiid/query/optimizer/relational/rules/RulePushSelectCriteria.java
trunk/engine/src/main/java/org/teiid/query/resolver/command/SimpleQueryResolver.java
trunk/engine/src/main/java/org/teiid/query/resolver/util/ResolverUtil.java
trunk/engine/src/main/java/org/teiid/query/rewriter/QueryRewriter.java
trunk/engine/src/main/resources/org/teiid/query/i18n.properties
trunk/engine/src/test/java/org/teiid/query/optimizer/TestUnionPlanning.java
Log:
TEIID-1376 adding support for partition wise joins
Modified: trunk/build/kits/jboss-container/teiid-releasenotes.html
===================================================================
--- trunk/build/kits/jboss-container/teiid-releasenotes.html 2010-12-15 21:45:25 UTC (rev 2784)
+++ trunk/build/kits/jboss-container/teiid-releasenotes.html 2010-12-17 17:48:17 UTC (rev 2785)
@@ -34,7 +34,9 @@
</UL>
<LI><B>UDF</B> - new API objects added to teiid-api to support user defined functions that are capable of pushdown to source.
<LI><B>Unescape Function</B> - a new system function, unescape, was added to handle common \ escaping in strings including octal, hex/unicode, \b, \r, \n, \f, and \t.
- <LI><B>Predicate Optimization<B> - expanded optimizations for detecting always false conditions when using IS NULL, IN, or comparison predicates with literal values.
+ <LI><B>Predicate Optimization</B> - expanded optimizations for detecting always false conditions when using IS NULL, IN, or comparison predicates with literal values.
+ <LI><B>Partition-wise Joins</B> - Views defined by partitioned unions (union alls where each branch has a projected literal or an IN predicate that makes its values mutually exclusive from the other branches) can
+ be joined against other partitioned unions and the optimizer will reorganize the join of unions into a union of joins.
</UL>
<h2><a name="Compatibility">Compatibility Issues</a></h2>
Added: trunk/engine/src/main/java/org/teiid/query/optimizer/relational/PartitionAnalyzer.java
===================================================================
--- trunk/engine/src/main/java/org/teiid/query/optimizer/relational/PartitionAnalyzer.java (rev 0)
+++ trunk/engine/src/main/java/org/teiid/query/optimizer/relational/PartitionAnalyzer.java 2010-12-17 17:48:17 UTC (rev 2785)
@@ -0,0 +1,152 @@
+/*
+ * JBoss, Home of Professional Open Source.
+ * See the COPYRIGHT.txt file distributed with this work for information
+ * regarding copyright ownership. Some portions may be licensed
+ * to Red Hat, Inc. under one or more contributor license agreements.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+ * 02110-1301 USA.
+ */
+
+package org.teiid.query.optimizer.relational;
+
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.Collections;
+import java.util.HashMap;
+import java.util.Iterator;
+import java.util.LinkedHashMap;
+import java.util.LinkedList;
+import java.util.List;
+import java.util.Map;
+import java.util.Set;
+import java.util.TreeSet;
+
+import org.teiid.query.sql.lang.Criteria;
+import org.teiid.query.sql.lang.Query;
+import org.teiid.query.sql.lang.QueryCommand;
+import org.teiid.query.sql.lang.SetCriteria;
+import org.teiid.query.sql.lang.SetQuery;
+import org.teiid.query.sql.lang.SetQuery.Operation;
+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.SingleElementSymbol;
+import org.teiid.query.sql.util.SymbolMap;
+
+/**
+ * TODO: support recursive detection of partitions
+ *
+ * Extracts a map of partitioning information from a union
+ */
+public class PartitionAnalyzer {
+
+ public static Map<ElementSymbol, List<Set<Constant>>> extractPartionInfo(SetQuery setQuery, List<ElementSymbol> projectedSymbols) {
+ List<Query> queries = new LinkedList<Query>();
+ if (!extractQueries(setQuery, queries)) {
+ return Collections.emptyMap();
+ }
+ Map<ElementSymbol, List<Set<Constant>>> partitions = new LinkedHashMap<ElementSymbol, List<Set<Constant>>>();
+ boolean first = true;
+ for (Query query : queries) {
+ Map<ElementSymbol, Set<Constant>> info = extractPartitionInfo(query, projectedSymbols);
+
+ partitions.keySet().retainAll(info.keySet());
+
+ if (first) {
+ first = false;
+ for (Map.Entry<ElementSymbol, Set<Constant>> entry : info.entrySet()) {
+ ArrayList<Set<Constant>> values = new ArrayList<Set<Constant>>(queries.size());
+ partitions.put(entry.getKey(), values);
+ values.add(entry.getValue());
+ }
+ continue;
+ }
+ Set<ElementSymbol> keys = partitions.keySet();
+
+ for (Iterator<ElementSymbol> iter = keys.iterator(); iter.hasNext();) {
+ ElementSymbol elementSymbol = iter.next();
+ List<Set<Constant>> values = partitions.get(elementSymbol);
+ Set<Constant> value = info.get(elementSymbol);
+ for (Set<Constant> set : values) {
+ if (!Collections.disjoint(set, value)) {
+ iter.remove();
+ continue;
+ }
+ }
+ values.add(value);
+ }
+ }
+ return partitions;
+ }
+
+ private static boolean extractQueries(QueryCommand queryCommand, List<Query> result) {
+ if (queryCommand instanceof SetQuery) {
+ SetQuery sq = (SetQuery)queryCommand;
+ if (sq.isAll() && sq.getOperation() == Operation.UNION && sq.getOrderBy() == null && sq.getLimit() == null) {
+ if (!extractQueries(sq.getLeftQuery(), result)) {
+ return false;
+ }
+ if (!extractQueries(sq.getRightQuery(), result)) {
+ return false;
+ }
+ return true;
+ }
+ return false;
+ }
+ result.add((Query)queryCommand);
+ return true;
+ }
+
+ private static Map<ElementSymbol, Set<Constant>> extractPartitionInfo(Query query, List<ElementSymbol> projectedSymbols) {
+ List<SingleElementSymbol> projected = query.getSelect().getProjectedSymbols();
+ List<Criteria> crits = Criteria.separateCriteriaByAnd(query.getCriteria());
+ Map<Expression, TreeSet<Constant>> inMap = new HashMap<Expression, TreeSet<Constant>>();
+ for (Criteria criteria : crits) {
+ if (!(criteria instanceof SetCriteria)) {
+ continue;
+ }
+ SetCriteria sc = (SetCriteria)criteria;
+ TreeSet<Constant> values = new TreeSet<Constant>();
+ boolean allConstants = true;
+ for (Expression exp : (Collection<Expression>)sc.getValues()) {
+ if (exp instanceof Constant) {
+ values.add((Constant)exp);
+ } else {
+ allConstants = false;
+ break;
+ }
+ }
+ if (allConstants) {
+ inMap.put(sc.getExpression(), values);
+ }
+ }
+ Map<ElementSymbol, Set<Constant>> result = new HashMap<ElementSymbol, Set<Constant>>();
+ for (int i = 0; i < projected.size(); i++) {
+ Expression ex = SymbolMap.getExpression(projected.get(i));
+
+ if (ex instanceof Constant) {
+ result.put(projectedSymbols.get(i), Collections.singleton((Constant)ex));
+ } else {
+ TreeSet<Constant> values = inMap.get(ex);
+ if (values != null) {
+ result.put(projectedSymbols.get(i), values);
+ }
+ }
+ }
+ return result;
+ }
+
+}
Property changes on: trunk/engine/src/main/java/org/teiid/query/optimizer/relational/PartitionAnalyzer.java
___________________________________________________________________
Name: svn:mime-type
+ text/plain
Modified: trunk/engine/src/main/java/org/teiid/query/optimizer/relational/RelationalPlanner.java
===================================================================
--- trunk/engine/src/main/java/org/teiid/query/optimizer/relational/RelationalPlanner.java 2010-12-15 21:45:25 UTC (rev 2784)
+++ trunk/engine/src/main/java/org/teiid/query/optimizer/relational/RelationalPlanner.java 2010-12-17 17:48:17 UTC (rev 2785)
@@ -106,6 +106,8 @@
import org.teiid.query.sql.proc.CreateUpdateProcedureCommand;
import org.teiid.query.sql.proc.TriggerAction;
import org.teiid.query.sql.symbol.AllSymbol;
+import org.teiid.query.sql.symbol.Constant;
+import org.teiid.query.sql.symbol.ElementSymbol;
import org.teiid.query.sql.symbol.GroupSymbol;
import org.teiid.query.sql.symbol.Reference;
import org.teiid.query.sql.symbol.SelectSymbol;
@@ -427,6 +429,10 @@
if(hints.hasCriteria) {
rules.push(RuleConstants.PUSH_SELECT_CRITERIA);
}
+ if (hints.hasJoin && hints.hasSetQuery) {
+ rules.push(RuleConstants.DECOMPOSE_JOIN);
+ rules.push(RuleConstants.MERGE_VIRTUAL);
+ }
if (hints.hasJoin && hints.hasOptionalJoin) {
rules.push(RuleConstants.REMOVE_OPTIONAL_JOINS);
}
@@ -878,7 +884,12 @@
PlanNode childRoot = generatePlan(nestedCommand);
node.addFirstChild(childRoot);
List<SingleElementSymbol> projectCols = nestedCommand.getProjectedSymbols();
- node.setProperty(NodeConstants.Info.SYMBOL_MAP, SymbolMap.createSymbolMap(group, projectCols, metadata));
+ SymbolMap map = SymbolMap.createSymbolMap(group, projectCols, metadata);
+ node.setProperty(NodeConstants.Info.SYMBOL_MAP, map);
+ if (nestedCommand instanceof SetQuery) {
+ Map<ElementSymbol, List<Set<Constant>>> partitionInfo = PartitionAnalyzer.extractPartionInfo((SetQuery)nestedCommand, map.getKeys());
+ node.setProperty(NodeConstants.Info.PARTITION_INFO, partitionInfo);
+ }
} else {
QueryMetadataInterface actualMetadata = metadata;
if (actualMetadata instanceof TempMetadataAdapter) {
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 2010-12-15 21:45:25 UTC (rev 2784)
+++ trunk/engine/src/main/java/org/teiid/query/optimizer/relational/plantree/NodeConstants.java 2010-12-17 17:48:17 UTC (rev 2785)
@@ -117,6 +117,7 @@
// Source node properties
SYMBOL_MAP, // SymbolMap
+ PARTITION_INFO, // Map<ElementSymbol, List<Set<Constant>>>
VIRTUAL_COMMAND, // Command
MAKE_DEP, // ??? List of Groups ???
PROCESSOR_PLAN, // ProcessorPlan for non-relational sub plan
@@ -133,7 +134,7 @@
OUTPUT_COLS, // List <SingleElementSymbol>
// Plan Node Cost Estimate Constants
- EST_SET_SIZE, // Integer represents the estimated set size this node would produce for a sibling node as the indenpendent node in a dependent join scenario
+ EST_SET_SIZE, // Integer represents the estimated set size this node would produce for a sibling node as the independent node in a dependent join scenario
EST_DEP_CARDINALITY, // Float value that represents the estimated cardinality (amount of rows) produced by this node as the dependent node in a dependent join scenario
EST_DEP_JOIN_COST, // Float value that represents the estimated cost of a dependent join (the join strategy for this could be Nested Loop or Merge)
EST_JOIN_COST, // Float value that represents the estimated cost of a merge join (the join strategy for this could be Nested Loop or Merge)
Modified: trunk/engine/src/main/java/org/teiid/query/optimizer/relational/rules/RuleConstants.java
===================================================================
--- trunk/engine/src/main/java/org/teiid/query/optimizer/relational/rules/RuleConstants.java 2010-12-15 21:45:25 UTC (rev 2784)
+++ trunk/engine/src/main/java/org/teiid/query/optimizer/relational/rules/RuleConstants.java 2010-12-17 17:48:17 UTC (rev 2785)
@@ -51,4 +51,5 @@
public static final OptimizerRule PLAN_PROCEDURES = new RulePlanProcedures();
public static final OptimizerRule CALCULATE_COST = new RuleCalculateCost();
public static final OptimizerRule PLAN_SORTS = new RulePlanSorts();
+ public static final OptimizerRule DECOMPOSE_JOIN = new RuleDecomposeJoin();
}
Added: trunk/engine/src/main/java/org/teiid/query/optimizer/relational/rules/RuleDecomposeJoin.java
===================================================================
--- trunk/engine/src/main/java/org/teiid/query/optimizer/relational/rules/RuleDecomposeJoin.java (rev 0)
+++ trunk/engine/src/main/java/org/teiid/query/optimizer/relational/rules/RuleDecomposeJoin.java 2010-12-17 17:48:17 UTC (rev 2785)
@@ -0,0 +1,353 @@
+/*
+ * JBoss, Home of Professional Open Source.
+ * See the COPYRIGHT.txt file distributed with this work for information
+ * regarding copyright ownership. Some portions may be licensed
+ * to Red Hat, Inc. under one or more contributor license agreements.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+ * 02110-1301 USA.
+ */
+
+package org.teiid.query.optimizer.relational.rules;
+
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.HashMap;
+import java.util.HashSet;
+import java.util.LinkedHashMap;
+import java.util.LinkedList;
+import java.util.List;
+import java.util.Map;
+import java.util.Set;
+
+import org.teiid.api.exception.query.QueryMetadataException;
+import org.teiid.api.exception.query.QueryPlannerException;
+import org.teiid.core.TeiidComponentException;
+import org.teiid.query.analysis.AnalysisRecord;
+import org.teiid.query.metadata.QueryMetadataInterface;
+import org.teiid.query.optimizer.capabilities.CapabilitiesFinder;
+import org.teiid.query.optimizer.relational.OptimizerRule;
+import org.teiid.query.optimizer.relational.RuleStack;
+import org.teiid.query.optimizer.relational.plantree.NodeConstants;
+import org.teiid.query.optimizer.relational.plantree.NodeEditor;
+import org.teiid.query.optimizer.relational.plantree.NodeFactory;
+import org.teiid.query.optimizer.relational.plantree.PlanNode;
+import org.teiid.query.optimizer.relational.plantree.NodeConstants.Info;
+import org.teiid.query.processor.relational.JoinNode.JoinStrategyType;
+import org.teiid.query.rewriter.QueryRewriter;
+import org.teiid.query.sql.LanguageObject;
+import org.teiid.query.sql.lang.Criteria;
+import org.teiid.query.sql.lang.JoinType;
+import org.teiid.query.sql.lang.Select;
+import org.teiid.query.sql.lang.SetQuery.Operation;
+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.GroupSymbol;
+import org.teiid.query.sql.symbol.SingleElementSymbol;
+import org.teiid.query.sql.util.SymbolMap;
+import org.teiid.query.util.CommandContext;
+
+/**
+ * Perform the optimization:<pre>
+ * source
+ * inner join union all
+ * source inner join
+ * union all => source
+ * a a
+ * b source
+ * source c
+ * union all inner join
+ * c source
+ * d b
+ * source
+ * d
+ * </pre>
+ *
+ * TODO: non-ansi joins
+ */
+public class RuleDecomposeJoin implements OptimizerRule {
+
+ @Override
+ public PlanNode execute(PlanNode plan, QueryMetadataInterface metadata,
+ CapabilitiesFinder capabilitiesFinder, RuleStack rules,
+ AnalysisRecord analysisRecord, CommandContext context)
+ throws QueryPlannerException, QueryMetadataException,
+ TeiidComponentException {
+
+ for (PlanNode unionNode : NodeEditor.findAllNodes(plan, NodeConstants.Types.SET_OP, NodeConstants.Types.SET_OP | NodeConstants.Types.ACCESS)) {
+ plan = decomposeJoin(unionNode, plan, metadata, context);
+ }
+
+ return plan;
+ }
+
+ public PlanNode decomposeJoin(PlanNode unionNode, PlanNode root, QueryMetadataInterface metadata, CommandContext context) throws TeiidComponentException, QueryPlannerException {
+ Operation op = (Operation)unionNode.getProperty(NodeConstants.Info.SET_OPERATION);
+
+ if (op != Operation.UNION
+ || unionNode.getParent() == null
+ || unionNode.getParent().getType() != NodeConstants.Types.SOURCE
+ || unionNode.getParent().getParent().getType() != NodeConstants.Types.JOIN) {
+ return root;
+ }
+
+ PlanNode joinNode = unionNode.getParent().getParent();
+
+ //TODO: should be done based upon join region to allow more than a 2-way non-ansi join
+
+ JoinType joinType = (JoinType)joinNode.getProperty(Info.JOIN_TYPE);
+ if (joinType != JoinType.JOIN_INNER) {
+ return root;
+ }
+
+ Map<ElementSymbol, List<Set<Constant>>> partitionInfo = (Map<ElementSymbol, List<Set<Constant>>>)unionNode.getParent().getProperty(Info.PARTITION_INFO);
+
+ if (partitionInfo == null) {
+ return root;
+ }
+
+ boolean left = unionNode == unionNode.getParent().getFirstChild();
+
+ PlanNode otherSide = left?joinNode.getLastChild():joinNode.getFirstChild();
+
+ if (otherSide.getType() != NodeConstants.Types.SOURCE) {
+ return root;
+ }
+
+ Map<ElementSymbol, List<Set<Constant>>> partitionInfoOther = (Map<ElementSymbol, List<Set<Constant>>>)otherSide.getProperty(Info.PARTITION_INFO);
+
+ if (partitionInfoOther == null) {
+ return root;
+ }
+
+ List<Criteria> criteria = (List<Criteria>)joinNode.getProperty(Info.JOIN_CRITERIA);
+
+ List<Expression> expr = new ArrayList<Expression>();
+ List<Expression> exprOther = new ArrayList<Expression>();
+ RuleChooseJoinStrategy.separateCriteria(unionNode.getParent().getGroups(), otherSide.getGroups(), expr, exprOther, criteria, new LinkedList<Criteria>());
+
+ if (expr.isEmpty()) {
+ return root; //no equi-join
+ }
+
+ List<int[]> matches = findMatches(partitionInfo, partitionInfoOther, expr, exprOther);
+
+ if (matches == null) {
+ return root; //no non-overlapping partitions
+ }
+
+ int branchSize = partitionInfo.values().iterator().next().size();
+ int otherBranchSize = partitionInfoOther.values().iterator().next().size();
+
+ if (matches.isEmpty()) {
+ //no matches mean that we can just insert a null node (false criteria) and be done with it
+ PlanNode critNode = NodeFactory.getNewNode(NodeConstants.Types.SELECT);
+ critNode.setProperty(Info.SELECT_CRITERIA, QueryRewriter.FALSE_CRITERIA);
+ unionNode.addAsParent(critNode);
+ return root;
+ }
+
+ List<PlanNode> branches = new ArrayList<PlanNode>();
+ RulePushSelectCriteria.collectUnionChildren(unionNode, branches);
+
+ if (branches.size() != branchSize) {
+ return root; //sanity check
+ }
+
+ List<PlanNode> otherBranches = new ArrayList<PlanNode>();
+ RulePushSelectCriteria.collectUnionChildren(otherSide.getFirstChild(), otherBranches);
+
+ if (otherBranches.size() != otherBranchSize) {
+ return root; //sanity check
+ }
+
+ PlanNode newUnion = buildUnion(unionNode, otherSide, criteria, matches, branches, otherBranches);
+ PlanNode view = rebuild(unionNode, metadata, context, joinNode, otherSide, newUnion);
+
+ SymbolMap symbolmap = (SymbolMap)view.getProperty(Info.SYMBOL_MAP);
+ HashMap<ElementSymbol, List<Set<Constant>>> newPartitionInfo = new LinkedHashMap<ElementSymbol, List<Set<Constant>>>();
+ for (int[] match : matches) {
+ updatePartitionInfo(partitionInfo, matches, symbolmap, newPartitionInfo, 0, match[0]);
+ updatePartitionInfo(partitionInfoOther, matches, symbolmap, newPartitionInfo, partitionInfo.size(), match[1]);
+ }
+ view.setProperty(Info.PARTITION_INFO, newPartitionInfo);
+
+ //since we've created a new union node, there's a chance we can decompose again
+ return decomposeJoin(newUnion, root, metadata, context);
+ }
+
+ private void updatePartitionInfo(
+ Map<ElementSymbol, List<Set<Constant>>> partitionInfo,
+ List<int[]> matches, SymbolMap symbolmap,
+ HashMap<ElementSymbol, List<Set<Constant>>> newPartitionInfo, int start, int index) {
+ for (Map.Entry<ElementSymbol, List<Set<Constant>>> entry : partitionInfo.entrySet()) {
+ ElementSymbol newSymbol = symbolmap.getKeys().get(start++);
+ List<Set<Constant>> values = newPartitionInfo.get(newSymbol);
+ if (values == null) {
+ values = new ArrayList<Set<Constant>>(matches.size());
+ newPartitionInfo.put(newSymbol, values);
+ }
+ values.add(entry.getValue().get(index));
+ }
+ }
+
+ /**
+ * Add the new union back in under a view
+ */
+ private PlanNode rebuild(PlanNode unionNode,
+ QueryMetadataInterface metadata, CommandContext context,
+ PlanNode joinNode, PlanNode otherSide, PlanNode newUnion)
+ throws TeiidComponentException, QueryPlannerException,
+ QueryMetadataException {
+ Set<String> groups = context.getGroups();
+ if (groups == null) {
+ groups = new HashSet<String>();
+ context.setGroups(groups);
+ }
+
+ GroupSymbol group = unionNode.getParent().getGroups().iterator().next();
+ group = RulePlaceAccess.recontextSymbol(group, groups);
+
+ PlanNode projectNode = NodeEditor.findNodePreOrder(newUnion, NodeConstants.Types.PROJECT);
+ List<? extends SingleElementSymbol> projectedSymbols = (List<? extends SingleElementSymbol>)projectNode.getProperty(Info.PROJECT_COLS);
+
+ PlanNode view = RulePushAggregates.createView(group, projectedSymbols, newUnion, metadata);
+
+ SymbolMap newSymbolMap = (SymbolMap)view.getProperty(Info.SYMBOL_MAP);
+
+ HashMap<ElementSymbol, ElementSymbol> inverseMap = new HashMap<ElementSymbol, ElementSymbol>();
+ List<ElementSymbol> viewSymbols = newSymbolMap.getKeys();
+ for (int i = 0; i < projectedSymbols.size(); i++) {
+ inverseMap.put((ElementSymbol)SymbolMap.getExpression(projectedSymbols.get(i)), viewSymbols.get(i));
+ }
+ joinNode.getParent().replaceChild(joinNode, view);
+
+ FrameUtil.convertFrame(view, unionNode.getParent().getGroups().iterator().next(), Collections.singleton(group), inverseMap, metadata);
+ FrameUtil.convertFrame(view, otherSide.getGroups().iterator().next(), Collections.singleton(group), inverseMap, metadata);
+
+ return view;
+ }
+
+ /**
+ * Search each equi-join for partitioning
+ */
+ private List<int[]> findMatches(
+ Map<ElementSymbol, List<Set<Constant>>> partitionInfo,
+ Map<ElementSymbol, List<Set<Constant>>> partitionInfoOther,
+ List<Expression> expr, List<Expression> exprOther) {
+ List<int[]> matches = null;
+ for (int i = 0; i < expr.size() && matches == null; i++) {
+ if (!(expr.get(i) instanceof ElementSymbol) || !(exprOther.get(i) instanceof ElementSymbol)) {
+ continue;
+ }
+ ElementSymbol es = (ElementSymbol)expr.get(i);
+ ElementSymbol esOther = (ElementSymbol)exprOther.get(i);
+ List<Set<Constant>> partLists = partitionInfo.get(es);
+ List<Set<Constant>> partListsOther = partitionInfoOther.get(esOther);
+ if (partLists == null || partListsOther == null) {
+ continue;
+ }
+ matches = findMatches(partLists, partListsOther);
+ }
+ return matches;
+ }
+
+ /**
+ * Find overlaps in the given partition lists
+ */
+ private List<int[]> findMatches(List<Set<Constant>> partLists,
+ List<Set<Constant>> partListsOther) {
+ List<int[]> matches = new LinkedList<int[]>();
+ for (int j = 0; j < partLists.size(); j++) {
+ int[] match = null;
+ Set<Constant> vals = partLists.get(j);
+ for (int k = 0; k < partListsOther.size(); k++) {
+ if (!Collections.disjoint(vals, partListsOther.get(k))) {
+ if (match == null) {
+ match = new int[] {j, k};
+ } else {
+ //TODO: we currently do handle a situation where multiple
+ //partitions overlap.
+ return null;
+ }
+ }
+ }
+ if (match != null) {
+ matches.add(match);
+ }
+ }
+ return matches;
+ }
+
+ private PlanNode buildUnion(PlanNode unionNode, PlanNode otherSide,
+ List<Criteria> criteria, List<int[]> matches,
+ List<PlanNode> branches, List<PlanNode> otherBranches) {
+ SymbolMap symbolMap = (SymbolMap)unionNode.getParent().getProperty(Info.SYMBOL_MAP);
+ SymbolMap otherSymbolMap = (SymbolMap)otherSide.getProperty(Info.SYMBOL_MAP);
+
+ List<PlanNode> joins = new LinkedList<PlanNode>();
+ for (int i = 0; i < matches.size(); i++) {
+ int[] is = matches.get(i);
+ PlanNode branch = branches.get(is[0]);
+ PlanNode branchSource = createSource(unionNode, symbolMap);
+
+ PlanNode otherBranch = otherBranches.get(is[1]);
+ PlanNode otherBranchSource = createSource(otherSide.getFirstChild(), otherSymbolMap);
+
+ PlanNode newJoinNode = NodeFactory.getNewNode(NodeConstants.Types.JOIN);
+ branchSource.addFirstChild(branch);
+ otherBranchSource.addFirstChild(otherBranch);
+ newJoinNode.addLastChild(branchSource);
+ newJoinNode.addLastChild(otherBranchSource);
+
+ newJoinNode.setProperty(Info.JOIN_STRATEGY, JoinStrategyType.NESTED_LOOP);
+ newJoinNode.setProperty(Info.JOIN_TYPE, JoinType.JOIN_INNER);
+ newJoinNode.setProperty(Info.JOIN_CRITERIA, LanguageObject.Util.deepClone(criteria, Criteria.class));
+ newJoinNode.addGroups(branchSource.getGroups());
+ newJoinNode.addGroups(otherBranchSource.getGroups());
+
+ PlanNode projectPlanNode = NodeFactory.getNewNode(NodeConstants.Types.PROJECT);
+ newJoinNode.addAsParent(projectPlanNode);
+
+ Select allSymbols = new Select(symbolMap.getKeys());
+ allSymbols.addSymbols(otherSymbolMap.getKeys());
+ if (i == 0) {
+ QueryRewriter.makeSelectUnique(allSymbols, false);
+ }
+ projectPlanNode.setProperty(NodeConstants.Info.PROJECT_COLS, allSymbols.getSymbols());
+ projectPlanNode.addGroups(newJoinNode.getGroups());
+
+ joins.add(projectPlanNode);
+ }
+
+ PlanNode newUnion = RulePlanUnions.buildUnionTree(unionNode, joins);
+ return newUnion;
+ }
+
+ private PlanNode createSource(PlanNode unionNode, SymbolMap symbolMap) {
+ PlanNode branchSource = NodeFactory.getNewNode(NodeConstants.Types.SOURCE);
+ branchSource.addGroups(unionNode.getParent().getGroups());
+ PlanNode projectNode = NodeEditor.findNodePreOrder(unionNode, NodeConstants.Types.PROJECT);
+ branchSource.setProperty(Info.SYMBOL_MAP, SymbolMap.createSymbolMap(symbolMap.getKeys(), (List<? extends SingleElementSymbol>)projectNode.getProperty(Info.PROJECT_COLS)));
+ return branchSource;
+ }
+
+ @Override
+ public String toString() {
+ return "DecomposeJoin"; //$NON-NLS-1$
+ }
+
+}
Property changes on: trunk/engine/src/main/java/org/teiid/query/optimizer/relational/rules/RuleDecomposeJoin.java
___________________________________________________________________
Name: svn:mime-type
+ text/plain
Modified: trunk/engine/src/main/java/org/teiid/query/optimizer/relational/rules/RulePlanUnions.java
===================================================================
--- trunk/engine/src/main/java/org/teiid/query/optimizer/relational/rules/RulePlanUnions.java 2010-12-15 21:45:25 UTC (rev 2784)
+++ trunk/engine/src/main/java/org/teiid/query/optimizer/relational/rules/RulePlanUnions.java 2010-12-17 17:48:17 UTC (rev 2785)
@@ -23,7 +23,6 @@
package org.teiid.query.optimizer.relational.rules;
import java.util.ArrayList;
-import java.util.Iterator;
import java.util.LinkedHashMap;
import java.util.LinkedList;
import java.util.List;
@@ -80,7 +79,7 @@
TeiidComponentException {
//look for all union branches and their sources
for (PlanNode unionNode : NodeEditor.findAllNodes(plan, NodeConstants.Types.SET_OP, NodeConstants.Types.SET_OP | NodeConstants.Types.ACCESS)) {
- List accessNodes = NodeEditor.findAllNodes(unionNode, NodeConstants.Types.ACCESS);
+ List<PlanNode> accessNodes = NodeEditor.findAllNodes(unionNode, NodeConstants.Types.ACCESS);
Object id = getModelId(metadata, accessNodes, capabilitiesFinder);
@@ -89,12 +88,13 @@
continue;
}
- //a linked hasmap is used so that the first entry is logically the first branch
- Map sourceNodes = new LinkedHashMap();
+ //a linked hashmap is used so that the first entry is logically the first branch
+ Map<Object, List<PlanNode>> sourceNodes = new LinkedHashMap<Object, List<PlanNode>>();
- boolean all = Boolean.TRUE.equals(unionNode.getProperty(NodeConstants.Info.USE_ALL));
+ boolean all = unionNode.hasBooleanProperty(NodeConstants.Info.USE_ALL);
+ Operation op = (Operation)unionNode.getProperty(NodeConstants.Info.SET_OPERATION);
- collectUnionSources(metadata, capabilitiesFinder, unionNode, sourceNodes, all, (Operation)unionNode.getProperty(NodeConstants.Info.SET_OPERATION));
+ collectUnionSources(metadata, capabilitiesFinder, unionNode, sourceNodes, all, op);
if (sourceNodes.size() == 1) {
continue;
@@ -103,26 +103,24 @@
//rebuild unions based upon the source map
boolean shouldRebuild = false;
- for (Iterator j = sourceNodes.entrySet().iterator(); j.hasNext();) {
- Map.Entry entry = (Map.Entry)j.next();
-
- if (entry.getKey() != null && ((List)entry.getValue()).size() > 1) {
- shouldRebuild = true;
- break;
- }
+ for (Map.Entry<Object, List<PlanNode>> entry : sourceNodes.entrySet()) {
+ if (entry.getKey() != null
+ && entry.getValue().size() > 1
+ && CapabilitiesUtil.supportsSetOp(entry.getKey(), (Operation)unionNode.getProperty(NodeConstants.Info.SET_OPERATION), metadata, capabilitiesFinder)) {
+ shouldRebuild = true;
+ break;
+ }
}
if (!shouldRebuild) {
continue;
}
- List sourceUnions = new LinkedList();
+ List<PlanNode> sourceUnions = new LinkedList<PlanNode>();
- for (Iterator j = sourceNodes.entrySet().iterator(); j.hasNext();) {
- Map.Entry entry = (Map.Entry)j.next();
+ for (Map.Entry<Object, List<PlanNode>> entry : sourceNodes.entrySet()) {
+ List<PlanNode> sources = entry.getValue();
- List sources = (List)entry.getValue();
-
sourceUnions.add(buildUnionTree(unionNode, sources));
}
@@ -133,14 +131,12 @@
}
}
- private PlanNode buildUnionTree(PlanNode rootUnionNode,
- List sources) {
+ static PlanNode buildUnionTree(PlanNode rootUnionNode,
+ List<PlanNode> sources) {
PlanNode root = null;
- for (Iterator k = sources.iterator(); k.hasNext();) {
- PlanNode source = (PlanNode)k.next();
-
+ for (PlanNode source : sources) {
if (root == null) {
root = source;
} else {
@@ -149,8 +145,6 @@
union.setProperty(NodeConstants.Info.USE_ALL, rootUnionNode.getProperty(NodeConstants.Info.USE_ALL));
union.addLastChild(root);
union.addLastChild(source);
- union.addGroups(root.getGroups());
- union.addGroups(source.getGroups());
root = union;
}
}
@@ -164,7 +158,7 @@
private void collectUnionSources(QueryMetadataInterface metadata,
CapabilitiesFinder capabilitiesFinder,
PlanNode unionNode,
- Map sourceNodes,
+ Map<Object, List<PlanNode>> sourceNodes,
boolean all, Operation setOp) throws QueryMetadataException,
TeiidComponentException {
for (PlanNode child : unionNode.getChildren()) {
@@ -174,7 +168,7 @@
child.setProperty(NodeConstants.Info.USE_ALL, Boolean.TRUE);
}
if ((!all || child.hasBooleanProperty(NodeConstants.Info.USE_ALL)) && setOp.equals(child.getProperty(NodeConstants.Info.SET_OPERATION)) && setOp != Operation.EXCEPT) { //keep collecting sources
- List accessNodes = NodeEditor.findAllNodes(child, NodeConstants.Types.ACCESS);
+ List<PlanNode> accessNodes = NodeEditor.findAllNodes(child, NodeConstants.Types.ACCESS);
Object id = getModelId(metadata, accessNodes, capabilitiesFinder);
@@ -187,21 +181,13 @@
optimizeUnions(child, metadata, capabilitiesFinder);
}
} else { //this must be a source, see if it has a consistent access node
- List accessNodes = NodeEditor.findAllNodes(child, NodeConstants.Types.ACCESS);
+ List<PlanNode> accessNodes = NodeEditor.findAllNodes(child, NodeConstants.Types.ACCESS);
Object id = getModelId(metadata, accessNodes, capabilitiesFinder);
- //don't bother optimizing sources that don't support unions
- boolean supportsUnions = true;
-
- if (id != null && !CapabilitiesUtil.supportsSetOp(id, (Operation)unionNode.getProperty(NodeConstants.Info.SET_OPERATION), metadata, capabilitiesFinder)) {
- supportsUnions = false;
- id = null;
- }
-
buildModelMap(metadata, capabilitiesFinder, sourceNodes, child, id);
- if (id == null && supportsUnions) {
+ if (id == null) {
//recursively optimize below this point
optimizeUnions(child, metadata, capabilitiesFinder);
}
@@ -210,12 +196,11 @@
}
private Object getModelId(QueryMetadataInterface metadata,
- List accessNodes, CapabilitiesFinder capFinder) throws QueryMetadataException,
+ List<PlanNode> accessNodes, CapabilitiesFinder capFinder) throws QueryMetadataException,
TeiidComponentException {
Object modelID = null;
- for (Iterator k = accessNodes.iterator(); k.hasNext();) {
- PlanNode accessNode = (PlanNode)k.next();
+ for (PlanNode accessNode : accessNodes) {
Object accessModelID = RuleRaiseAccess.getModelIDFromAccess(accessNode, metadata);
@@ -249,23 +234,24 @@
*/
static void buildModelMap(QueryMetadataInterface metadata,
CapabilitiesFinder capFinder,
- Map accessMap,
+ Map<Object, List<PlanNode>> accessMap,
PlanNode node,
Object accessModelID) throws QueryMetadataException,
TeiidComponentException {
- List accessNodes = null;
+ List<PlanNode> accessNodes = accessMap.get(accessModelID);
- for (Iterator i = accessMap.entrySet().iterator(); i.hasNext();) {
- Map.Entry entry = (Map.Entry)i.next();
- if (accessModelID == entry.getKey() || CapabilitiesUtil.isSameConnector(accessModelID, entry.getKey(), metadata, capFinder)) {
- accessNodes = (List)entry.getValue();
- break;
- }
- }
-
if (accessNodes == null) {
- accessNodes = new ArrayList();
- accessMap.put(accessModelID, accessNodes);
+ for (Map.Entry<Object, List<PlanNode>> entry : accessMap.entrySet() ) {
+ if (accessModelID == entry.getKey() || CapabilitiesUtil.isSameConnector(accessModelID, entry.getKey(), metadata, capFinder)) {
+ accessNodes = entry.getValue();
+ break;
+ }
+ }
+
+ if (accessNodes == null) {
+ accessNodes = new ArrayList<PlanNode>();
+ accessMap.put(accessModelID, accessNodes);
+ }
}
accessNodes.add(node);
}
Modified: trunk/engine/src/main/java/org/teiid/query/optimizer/relational/rules/RulePushAggregates.java
===================================================================
--- trunk/engine/src/main/java/org/teiid/query/optimizer/relational/rules/RulePushAggregates.java 2010-12-15 21:45:25 UTC (rev 2784)
+++ trunk/engine/src/main/java/org/teiid/query/optimizer/relational/rules/RulePushAggregates.java 2010-12-17 17:48:17 UTC (rev 2785)
@@ -320,22 +320,11 @@
updateSymbolName(projectCols, i, virtualElem, projectedSymbol);
}
}
- PlanNode intermediateView = NodeFactory.getNewNode(NodeConstants.Types.SOURCE);
- unionSource.addAsParent(intermediateView);
+ GroupSymbol group = new GroupSymbol("X"); //$NON-NLS-1$
+
+ PlanNode intermediateView = createView(group, virtualElements, unionSource, metadata);
+ SymbolMap symbolMap = (SymbolMap)intermediateView.getProperty(Info.SYMBOL_MAP);
unionSource = intermediateView;
- TempMetadataStore store = new TempMetadataStore();
- TempMetadataAdapter tma = new TempMetadataAdapter(metadata, store);
- GroupSymbol group = new GroupSymbol("X"); //$NON-NLS-1$
- try {
- group.setMetadataID(ResolverUtil.addTempGroup(tma, group, virtualElements, false));
- } catch (QueryResolverException e) {
- throw new TeiidComponentException(e);
- }
- intermediateView.addGroup(group);
- List<ElementSymbol> projectedSymbols = ResolverUtil.resolveElementsInGroup(group, metadata);
- SymbolMap symbolMap = SymbolMap.createSymbolMap(projectedSymbols,
- (List<Expression>)NodeEditor.findNodePreOrder(unionSource, NodeConstants.Types.PROJECT).getProperty(NodeConstants.Info.PROJECT_COLS));
- intermediateView.setProperty(NodeConstants.Info.SYMBOL_MAP, symbolMap);
Set<SingleElementSymbol> newGroupingExpressions = Collections.emptySet();
if (groupingExpressions != null) {
@@ -345,9 +334,9 @@
}
}
- List<SingleElementSymbol> projectedViewSymbols = Util.deepClone(projectedSymbols, SingleElementSymbol.class);
+ List<SingleElementSymbol> projectedViewSymbols = Util.deepClone(symbolMap.getKeys(), SingleElementSymbol.class);
- SymbolMap viewMapping = SymbolMap.createSymbolMap(NodeEditor.findParent(unionSource, NodeConstants.Types.SOURCE).getGroups().iterator().next(), projectedSymbols, metadata);
+ SymbolMap viewMapping = SymbolMap.createSymbolMap(NodeEditor.findParent(unionSource, NodeConstants.Types.SOURCE).getGroups().iterator().next(), projectedViewSymbols, metadata);
for (AggregateSymbol agg : aggregates) {
agg = (AggregateSymbol)agg.clone();
ExpressionMappingVisitor.mapExpressions(agg, viewMapping.asMap());
@@ -391,6 +380,24 @@
}
}
}
+
+ static PlanNode createView(GroupSymbol group, List<? extends SingleElementSymbol> virtualElements, PlanNode child, QueryMetadataInterface metadata) throws TeiidComponentException {
+ PlanNode intermediateView = NodeFactory.getNewNode(NodeConstants.Types.SOURCE);
+ TempMetadataStore store = new TempMetadataStore();
+ TempMetadataAdapter tma = new TempMetadataAdapter(metadata, store);
+ try {
+ group.setMetadataID(ResolverUtil.addTempGroup(tma, group, virtualElements, false));
+ } catch (QueryResolverException e) {
+ throw new TeiidComponentException(e);
+ }
+ intermediateView.addGroup(group);
+ List<ElementSymbol> projectedSymbols = ResolverUtil.resolveElementsInGroup(group, metadata);
+ SymbolMap symbolMap = SymbolMap.createSymbolMap(projectedSymbols,
+ (List<Expression>)NodeEditor.findNodePreOrder(child, NodeConstants.Types.PROJECT).getProperty(NodeConstants.Info.PROJECT_COLS));
+ intermediateView.setProperty(NodeConstants.Info.SYMBOL_MAP, symbolMap);
+ child.addAsParent(intermediateView);
+ return intermediateView;
+ }
private void updateSymbolName(List<SingleElementSymbol> projectCols, int i,
ElementSymbol virtualElem, SingleElementSymbol projectedSymbol) {
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 2010-12-15 21:45:25 UTC (rev 2784)
+++ trunk/engine/src/main/java/org/teiid/query/optimizer/relational/rules/RulePushSelectCriteria.java 2010-12-17 17:48:17 UTC (rev 2785)
@@ -523,7 +523,7 @@
return false;
}
- void collectUnionChildren(PlanNode unionNode, LinkedList<PlanNode> unionChildren) {
+ static void collectUnionChildren(PlanNode unionNode, List<PlanNode> unionChildren) {
for (PlanNode child : unionNode.getChildren()) {
if(child.getType() == NodeConstants.Types.SET_OP) {
collectUnionChildren(child, unionChildren);
Modified: trunk/engine/src/main/java/org/teiid/query/resolver/command/SimpleQueryResolver.java
===================================================================
--- trunk/engine/src/main/java/org/teiid/query/resolver/command/SimpleQueryResolver.java 2010-12-15 21:45:25 UTC (rev 2784)
+++ trunk/engine/src/main/java/org/teiid/query/resolver/command/SimpleQueryResolver.java 2010-12-17 17:48:17 UTC (rev 2785)
@@ -155,12 +155,12 @@
}
if (!discoveredGroups.add(obj.getGroupSymbol())) {
- throw new QueryResolverException("Duplicate WITH clause item name {0}");
+ throw new QueryResolverException(QueryPlugin.Util.getString("SimpleQueryResolver.duplicate_with", obj.getGroupSymbol())); //$NON-NLS-1$
}
List<? extends SingleElementSymbol> projectedSymbols = obj.getCommand().getProjectedSymbols();
if (obj.getColumns() != null && !obj.getColumns().isEmpty()) {
if (obj.getColumns().size() != projectedSymbols.size()) {
- throw new QueryResolverException("The number of WITH clause columns for item {0} do not match the query expression");
+ throw new QueryResolverException(QueryPlugin.Util.getString("SimpleQueryResolver.mismatched_with_columns", obj.getGroupSymbol())); //$NON-NLS-1$
}
Iterator<ElementSymbol> iter = obj.getColumns().iterator();
for (SingleElementSymbol singleElementSymbol : projectedSymbols) {
@@ -460,7 +460,7 @@
storedProcedureCommand.setProcedureRelational(true);
storedProcedureCommand.setProcedureName(fullName);
- List metadataParams = storedProcedureInfo.getParameters();
+ List<SPParameter> metadataParams = storedProcedureInfo.getParameters();
Query procQuery = new Query();
From from = new From();
@@ -474,8 +474,7 @@
int paramIndex = 1;
- for(Iterator paramIter = metadataParams.iterator(); paramIter.hasNext();){
- SPParameter metadataParameter = (SPParameter)paramIter.next();
+ for (SPParameter metadataParameter : metadataParams) {
SPParameter clonedParam = (SPParameter)metadataParameter.clone();
if (clonedParam.getParameterType()==ParameterInfo.IN || metadataParameter.getParameterType()==ParameterInfo.INOUT) {
ElementSymbol paramSymbol = clonedParam.getParameterSymbol();
@@ -499,12 +498,11 @@
QueryResolver.resolveCommand(procQuery, Collections.EMPTY_MAP, metadata.getMetadata(), analysis);
- List projectedSymbols = procQuery.getProjectedSymbols();
+ List<SingleElementSymbol> projectedSymbols = procQuery.getProjectedSymbols();
HashSet<String> foundNames = new HashSet<String>();
- for (Iterator i = projectedSymbols.iterator(); i.hasNext();) {
- SingleElementSymbol ses = (SingleElementSymbol)i.next();
+ for (SingleElementSymbol ses : projectedSymbols) {
if (!foundNames.add(ses.getShortCanonicalName())) {
throw new QueryResolverException(QueryPlugin.Util.getString("SimpleQueryResolver.Proc_Relational_Name_conflict", fullName)); //$NON-NLS-1$
}
Modified: trunk/engine/src/main/java/org/teiid/query/resolver/util/ResolverUtil.java
===================================================================
--- trunk/engine/src/main/java/org/teiid/query/resolver/util/ResolverUtil.java 2010-12-15 21:45:25 UTC (rev 2784)
+++ trunk/engine/src/main/java/org/teiid/query/resolver/util/ResolverUtil.java 2010-12-17 17:48:17 UTC (rev 2785)
@@ -983,20 +983,27 @@
}
HashMap<List<GroupSymbol>, List<HashSet<Object>>> crits = createGroupMap(leftExpressions, rightExpressions);
HashSet<GroupSymbol> tempSet = new HashSet<GroupSymbol>();
+ HashSet<GroupSymbol> nonKeyPreserved = new HashSet<GroupSymbol>();
for (GroupSymbol group : groups) {
LinkedHashSet<GroupSymbol> visited = new LinkedHashSet<GroupSymbol>();
LinkedList<GroupSymbol> toVisit = new LinkedList<GroupSymbol>();
toVisit.add(group);
while (!toVisit.isEmpty()) {
GroupSymbol visiting = toVisit.removeLast();
- if (!visited.add(visiting)) {
+ if (!visited.add(visiting) || nonKeyPreserved.contains(visiting)) {
continue;
}
+ if (keyPreservingGroups.contains(visiting)) {
+ visited.addAll(groups);
+ break;
+ }
toVisit.addAll(findKeyPreserved(tempSet, Collections.singleton(visiting), crits, true, metadata, groups));
toVisit.addAll(findKeyPreserved(tempSet, Collections.singleton(visiting), crits, false, metadata, groups));
}
if (visited.containsAll(groups)) {
keyPreservingGroups.add(group);
+ } else {
+ nonKeyPreserved.add(group);
}
}
}
Modified: trunk/engine/src/main/java/org/teiid/query/rewriter/QueryRewriter.java
===================================================================
--- trunk/engine/src/main/java/org/teiid/query/rewriter/QueryRewriter.java 2010-12-15 21:45:25 UTC (rev 2784)
+++ trunk/engine/src/main/java/org/teiid/query/rewriter/QueryRewriter.java 2010-12-17 17:48:17 UTC (rev 2785)
@@ -1240,10 +1240,14 @@
exprMap.put(sc.getExpression(), converted);
} else if (crit instanceof SetCriteria) {
SetCriteria sc1 = (SetCriteria)crit;
+ newCrits.remove(sc1);
sc1.getValues().retainAll(sc.getValues());
if (sc1.getValues().isEmpty()) {
return FALSE_CRITERIA;
}
+ //TODO: single value as compare criteria
+ newCrits.add(sc1);
+ exprMap.put(sc1.getExpression(), sc1);
continue;
} else {
CompareCriteria cc = (CompareCriteria)crit;
@@ -1252,12 +1256,12 @@
exprIter.remove();
}
}
- //TODO: single value as compare criteria
if (sc.getValues().isEmpty()) {
return FALSE_CRITERIA;
}
if (cc.getOperator() != CompareCriteria.EQ) {
newCrits.remove(cc);
+ //TODO: single value as compare criteria
exprMap.put(sc.getExpression(), sc);
} else {
continue;
@@ -1293,6 +1297,7 @@
exprMap.put(cc.getLeftExpression(), cc);
} else if (modified) {
newCrits.add(sc);
+ exprMap.put(sc.getExpression(), sc);
continue;
}
} else {
Modified: trunk/engine/src/main/resources/org/teiid/query/i18n.properties
===================================================================
--- trunk/engine/src/main/resources/org/teiid/query/i18n.properties 2010-12-15 21:45:25 UTC (rev 2784)
+++ trunk/engine/src/main/resources/org/teiid/query/i18n.properties 2010-12-17 17:48:17 UTC (rev 2785)
@@ -660,6 +660,8 @@
SimpleQueryResolver.Query_was_redirected_to_Mat_table=The query against {0} was redirected to the materialization table {1}.
SimpleQueryResolver.ambiguous_all_in_group=The symbol {0} refers to more than one group defined in the FROM clause.
SimpleQueryResolver.Proc_Relational_Name_conflict=Cannot access procedure {0} using table semantics since the parameter and result set column names are not all unique.
+SimpleQueryResolver.duplicate_with=Duplicate WITH clause item name {0}
+SimpleQueryResolver.mismatched_with_columns=The number of WITH clause columns for item {0} do not match the query expression
QueryResolver.invalid_xpath=Invalid xpath value: {0}
ResolveVariablesVisitor.reserved_word_for_temporary_used=Cursor names cannot begin with "#" as that indicates the name of a temporary table: {0}.
SimpleQueryResolver.materialized_table_not_used=The query against {0} did not use materialization table {1} due to the use of OPTION NOCACHE.
Modified: trunk/engine/src/test/java/org/teiid/query/optimizer/TestUnionPlanning.java
===================================================================
--- trunk/engine/src/test/java/org/teiid/query/optimizer/TestUnionPlanning.java 2010-12-15 21:45:25 UTC (rev 2784)
+++ trunk/engine/src/test/java/org/teiid/query/optimizer/TestUnionPlanning.java 2010-12-17 17:48:17 UTC (rev 2785)
@@ -22,18 +22,18 @@
package org.teiid.query.optimizer;
+import org.junit.Test;
+import org.teiid.query.optimizer.TestOptimizer.ComparisonMode;
import org.teiid.query.optimizer.capabilities.BasicSourceCapabilities;
import org.teiid.query.optimizer.capabilities.FakeCapabilitiesFinder;
import org.teiid.query.optimizer.capabilities.SourceCapabilities.Capability;
import org.teiid.query.processor.ProcessorPlan;
import org.teiid.query.unittest.FakeMetadataFactory;
+@SuppressWarnings("nls")
+public class TestUnionPlanning {
-import junit.framework.TestCase;
-
-public class TestUnionPlanning extends TestCase {
-
- public void testUnionPushDown() {
+ @Test public void testUnionPushDown() {
FakeCapabilitiesFinder capFinder = new FakeCapabilitiesFinder();
BasicSourceCapabilities caps = TestOptimizer.getTypicalCapabilities();
caps.setCapabilitySupport(Capability.QUERY_UNION, true);
@@ -65,7 +65,7 @@
/**
* Here the change in the all causes us not to pushdown
*/
- public void testUnionPushDown1() {
+ @Test public void testUnionPushDown1() {
FakeCapabilitiesFinder capFinder = new FakeCapabilitiesFinder();
BasicSourceCapabilities caps = TestOptimizer.getTypicalCapabilities();
caps.setCapabilitySupport(Capability.QUERY_UNION, true);
@@ -94,7 +94,7 @@
});
}
- public void testUnionPushDown2() {
+ @Test public void testUnionPushDown2() {
FakeCapabilitiesFinder capFinder = new FakeCapabilitiesFinder();
BasicSourceCapabilities caps = TestOptimizer.getTypicalCapabilities();
caps.setCapabilitySupport(Capability.QUERY_UNION, true);
@@ -155,5 +155,56 @@
2 // UnionAll
});
}
+
+ @Test public void testUnionPushDownWithJoin() {
+ ProcessorPlan plan = TestOptimizer.helpPlan("select * from (SELECT IntKey FROM BQT1.SmallA where intkey in (1, 2) UNION ALL SELECT intkey FROM BQT2.SmallA where intkey in (3, 4)) A inner join (SELECT intkey FROM BQT1.SmallB where intkey in (1, 2) UNION ALL SELECT intkey FROM BQT2.SmallB where intkey in (3, 4)) B on a.intkey = b.intkey", FakeMetadataFactory.exampleBQTCached(), null, TestOptimizer.getGenericFinder(),//$NON-NLS-1$
+ new String[] { "SELECT g_1.intkey, g_0.intkey FROM BQT2.SmallA AS g_0, BQT2.SmallB AS g_1 WHERE (g_0.intkey = g_1.intkey) AND (g_0.intkey IN (3, 4)) AND (g_1.intkey IN (3, 4))",
+ "SELECT g_1.intkey, g_0.IntKey FROM BQT1.SmallA AS g_0, BQT1.SmallB AS g_1 WHERE (g_0.IntKey = g_1.intkey) AND (g_0.intkey IN (1, 2)) AND (g_1.intkey IN (1, 2))" }, TestOptimizer.SHOULD_SUCCEED);
+
+ TestOptimizer.checkNodeTypes(plan, new int[] {
+ 2, // Access
+ 0, // DependentAccess
+ 0, // DependentSelect
+ 0, // DependentProject
+ 0, // DupRemove
+ 0, // Grouping
+ 0, // NestedLoopJoinStrategy
+ 0, // MergeJoinStrategy
+ 0, // Null
+ 0, // PlanExecution
+ 0, // Project
+ 0, // Select
+ 0, // Sort
+ 1 // UnionAll
+ });
+ }
+ @Test public void testUnionPushDownWithJoinNoMatches() {
+ TestOptimizer.helpPlan("select * from (SELECT IntKey FROM BQT1.SmallA where intkey in (1, 2) UNION ALL SELECT intkey FROM BQT2.SmallA where intkey in (3, 4)) A inner join (SELECT intkey FROM BQT1.SmallB where intkey in (5, 6) UNION ALL SELECT intkey FROM BQT2.SmallB where intkey in (7, 8)) B on a.intkey = b.intkey", FakeMetadataFactory.exampleBQTCached(), null, TestOptimizer.getGenericFinder(),//$NON-NLS-1$
+ new String[] {}, TestOptimizer.SHOULD_SUCCEED); //$NON-NLS-1$
+ }
+
+ @Test public void testUnionPushDownWithJoin1() throws Exception {
+ ProcessorPlan plan = TestOptimizer.helpPlan("select * from (SELECT IntKey FROM BQT1.SmallA where intkey in (1, 2) UNION ALL SELECT intkey FROM BQT2.SmallA where intkey in (3, 4)) A inner join (SELECT intkey FROM BQT1.SmallB where intkey in (1, 2) UNION ALL SELECT intkey FROM BQT2.SmallB where intkey in (3, 4)) B on a.intkey = b.intkey where a.intkey in (1, 4)", FakeMetadataFactory.exampleBQTCached(), null, TestOptimizer.getGenericFinder(),//$NON-NLS-1$
+ new String[] { "SELECT g_1.intkey, g_0.intkey FROM BQT2.SmallA AS g_0, BQT2.SmallB AS g_1 WHERE (g_0.intkey = g_1.intkey) AND (g_0.intkey IN (4)) AND (g_0.intkey = 4) AND (g_1.intkey = 4)",
+ "SELECT g_1.intkey, g_0.IntKey FROM BQT1.SmallA AS g_0, BQT1.SmallB AS g_1 WHERE (g_0.IntKey = g_1.intkey) AND (g_0.intkey IN (1)) AND (g_0.IntKey = 1) AND (g_1.intkey IN (1)) AND (g_1.intkey = 1)" }, ComparisonMode.EXACT_COMMAND_STRING);
+
+ TestOptimizer.checkNodeTypes(plan, new int[] {
+ 2, // Access
+ 0, // DependentAccess
+ 0, // DependentSelect
+ 0, // DependentProject
+ 0, // DupRemove
+ 0, // Grouping
+ 0, // NestedLoopJoinStrategy
+ 0, // MergeJoinStrategy
+ 0, // Null
+ 0, // PlanExecution
+ 0, // Project
+ 0, // Select
+ 0, // Sort
+ 1 // UnionAll
+ });
+ }
+
}
14 years
teiid SVN: r2784 - branches/7.1.x/documentation/reference/src/main/docbook/en-US/content.
by teiid-commits@lists.jboss.org
Author: rareddy
Date: 2010-12-15 16:45:25 -0500 (Wed, 15 Dec 2010)
New Revision: 2784
Modified:
branches/7.1.x/documentation/reference/src/main/docbook/en-US/content/system_schema.xml
Log:
TEIID-1373: documenting that OID in system schema is only unique in a given VDB version.
Modified: branches/7.1.x/documentation/reference/src/main/docbook/en-US/content/system_schema.xml
===================================================================
--- branches/7.1.x/documentation/reference/src/main/docbook/en-US/content/system_schema.xml 2010-12-15 21:16:24 UTC (rev 2783)
+++ branches/7.1.x/documentation/reference/src/main/docbook/en-US/content/system_schema.xml 2010-12-15 21:45:25 UTC (rev 2784)
@@ -176,7 +176,7 @@
<para>integer</para>
</entry>
<entry>
- <para>Unique ID</para>
+ <para>Unique ID (see note below)</para>
</entry>
</row>
<row>
@@ -269,7 +269,7 @@
<para>integer</para>
</entry>
<entry>
- <para>Unique ID</para>
+ <para>Unique ID (see note below)</para>
</entry>
</row>
</tbody>
@@ -397,7 +397,7 @@
<para>integer</para>
</entry>
<entry>
- <para>Unique ID</para>
+ <para>Unique ID (see note below)</para>
</entry>
</row>
<row>
@@ -915,7 +915,7 @@
<para>integer</para>
</entry>
<entry>
- <para>Unique ID</para>
+ <para>Unique ID (see note below)</para>
</entry>
</row>
<row>
@@ -1074,7 +1074,7 @@
<para>integer</para>
</entry>
<entry>
- <para>Unique ID</para>
+ <para>Unique ID (see note below)</para>
</entry>
</row>
</tbody>
@@ -1199,7 +1199,7 @@
<para>integer</para>
</entry>
<entry>
- <para>Unique ID</para>
+ <para>Unique ID (see note below)</para>
</entry>
</row>
<row>
@@ -1317,7 +1317,7 @@
<para>integer</para>
</entry>
<entry>
- <para>Unique ID</para>
+ <para>Unique ID (see note below)</para>
</entry>
</row>
<row>
@@ -1710,7 +1710,7 @@
<para>integer</para>
</entry>
<entry>
- <para>Unique ID</para>
+ <para>Unique ID (see note below)</para>
</entry>
</row>
<row>
@@ -1751,6 +1751,12 @@
</informaltable>
</section>
</section>
+ <warning>
+ <para>OID column is is guranteed to be unique only for given version of the VDB. If the VDB is updated and a different version of
+ the VDB is deployed, these IDs are not guranteed to be unique across both versions of VDB. UID is unique across different versions
+ only if the VDB is generated from Designer and metadata from old models are used(i.e. no re-importing from sources).
+ UID column in a Dynamic VDB behaves same as OID column.</para>
+ </warning>
</section>
<section id="system_procedures">
<title>System Procedures</title>
14 years
teiid SVN: r2783 - branches/7.1.x/build/kits/jboss-container/teiid-examples/jca.
by teiid-commits@lists.jboss.org
Author: rareddy
Date: 2010-12-15 16:16:24 -0500 (Wed, 15 Dec 2010)
New Revision: 2783
Added:
branches/7.1.x/build/kits/jboss-container/teiid-examples/jca/odbc-ds.xml
Log:
TEIID-1357: Example data source template for the ODBC based sources.
Added: branches/7.1.x/build/kits/jboss-container/teiid-examples/jca/odbc-ds.xml
===================================================================
--- branches/7.1.x/build/kits/jboss-container/teiid-examples/jca/odbc-ds.xml (rev 0)
+++ branches/7.1.x/build/kits/jboss-container/teiid-examples/jca/odbc-ds.xml 2010-12-15 21:16:24 UTC (rev 2783)
@@ -0,0 +1,23 @@
+<?xml version="1.0" encoding="UTF-8"?>
+
+<datasources>
+ <!-- Sample data source using JDBC-ODBC bridge to connect to ODBC source -->
+ <no-tx-datasource>
+ <jndi-name>odbcDS</jndi-name>
+
+ <!-- Create a DSN using ODBC driver manager, and replace {DSN} below with your DSN name -->
+ <connection-url>jdbc:odbc:{DSN}</connection-url>
+
+ <!-- For DSN less connection URL use the below form to connect to a Excel Sheet
+ <connection-url>jdbc:odbc:Driver={Microsoft Excel Driver (*.xls)};Dbq=c:\ODBC\ExcelData.xls</connection-url>
+ -->
+
+ <driver-class>sun.jdbc.odbc.JdbcOdbcDriver</driver-class>
+
+ <transaction-isolation>TRANSACTION_NONE</transaction-isolation>
+ <min-pool-size>1</min-pool-size>
+ <max-pool-size>1</max-pool-size>
+ <idle-timeout-minutes>5</idle-timeout-minutes>
+ </no-tx-datasource>
+
+</datasources>
\ No newline at end of file
Property changes on: branches/7.1.x/build/kits/jboss-container/teiid-examples/jca/odbc-ds.xml
___________________________________________________________________
Name: svn:mime-type
+ text/plain
14 years
teiid SVN: r2782 - in branches/7.1.x: engine/src/main/java/org/teiid/dqp/service and 4 other directories.
by teiid-commits@lists.jboss.org
Author: shawkins
Date: 2010-12-15 14:00:32 -0500 (Wed, 15 Dec 2010)
New Revision: 2782
Modified:
branches/7.1.x/engine/src/main/java/org/teiid/dqp/internal/process/DQPCore.java
branches/7.1.x/engine/src/main/java/org/teiid/dqp/internal/process/RequestWorkItem.java
branches/7.1.x/engine/src/main/java/org/teiid/dqp/internal/process/TransactionServerImpl.java
branches/7.1.x/engine/src/main/java/org/teiid/dqp/service/TransactionService.java
branches/7.1.x/jboss-integration/src/main/java/org/teiid/jboss/deployers/RuntimeEngineDeployer.java
branches/7.1.x/runtime/src/main/java/org/teiid/services/SessionServiceImpl.java
branches/7.1.x/runtime/src/main/java/org/teiid/transport/ClientServiceRegistry.java
branches/7.1.x/runtime/src/main/java/org/teiid/transport/ClientServiceRegistryImpl.java
branches/7.1.x/runtime/src/main/java/org/teiid/transport/ODBCSocketListener.java
branches/7.1.x/runtime/src/main/resources/org/teiid/runtime/i18n.properties
Log:
TEIID-1387 enforcing that only admin connections can be made over the admin port and vice versa
Modified: branches/7.1.x/engine/src/main/java/org/teiid/dqp/internal/process/DQPCore.java
===================================================================
--- branches/7.1.x/engine/src/main/java/org/teiid/dqp/internal/process/DQPCore.java 2010-12-15 16:43:07 UTC (rev 2781)
+++ branches/7.1.x/engine/src/main/java/org/teiid/dqp/internal/process/DQPCore.java 2010-12-15 19:00:32 UTC (rev 2782)
@@ -479,7 +479,7 @@
public void terminateSession(String sessionId) {
// sometimes there will not be any atomic requests pending, in that
// situation we still need to clear the master request from our map
- ClientState state = getClientState(sessionId, false);
+ ClientState state = this.clientState.remove(sessionId);
if (state != null) {
for (RequestID reqId : state.getRequests()) {
try {
@@ -488,7 +488,6 @@
LogManager.logWarning(LogConstants.CTX_DQP, err, "Failed to cancel " + reqId); //$NON-NLS-1$
}
}
- this.clientState.remove(sessionId);
}
try {
Modified: branches/7.1.x/engine/src/main/java/org/teiid/dqp/internal/process/RequestWorkItem.java
===================================================================
--- branches/7.1.x/engine/src/main/java/org/teiid/dqp/internal/process/RequestWorkItem.java 2010-12-15 16:43:07 UTC (rev 2781)
+++ branches/7.1.x/engine/src/main/java/org/teiid/dqp/internal/process/RequestWorkItem.java 2010-12-15 19:00:32 UTC (rev 2782)
@@ -269,9 +269,6 @@
suspend();
}
}
- else if (this.transactionState == TransactionState.NONE && this.transactionContext != null) {
- this.transactionService.closeTransactionContext(this.transactionContext);
- }
sendResultsIfNeeded(null);
} else {
moreWork(false); // If the timeslice expired, then the processor can probably produce more batches.
Modified: branches/7.1.x/engine/src/main/java/org/teiid/dqp/internal/process/TransactionServerImpl.java
===================================================================
--- branches/7.1.x/engine/src/main/java/org/teiid/dqp/internal/process/TransactionServerImpl.java 2010-12-15 16:43:07 UTC (rev 2781)
+++ branches/7.1.x/engine/src/main/java/org/teiid/dqp/internal/process/TransactionServerImpl.java 2010-12-15 19:00:32 UTC (rev 2782)
@@ -459,10 +459,6 @@
return transactions.getOrCreateTransactionContext(threadId);
}
- public void closeTransactionContext(TransactionContext tc) {
- transactions.removeTransactionContext(tc);
- }
-
/**
* Request level transaction
*/
@@ -494,7 +490,7 @@
}
public void cancelTransactions(String threadId, boolean requestOnly) throws XATransactionException {
- TransactionContext tc = transactions.getTransactionContext(threadId);
+ TransactionContext tc = requestOnly?transactions.getTransactionContext(threadId):transactions.removeTransactionContext(threadId);
if (tc == null || tc.getTransactionType() == TransactionContext.Scope.NONE
|| (requestOnly && tc.getTransactionType() != TransactionContext.Scope.REQUEST)) {
Modified: branches/7.1.x/engine/src/main/java/org/teiid/dqp/service/TransactionService.java
===================================================================
--- branches/7.1.x/engine/src/main/java/org/teiid/dqp/service/TransactionService.java 2010-12-15 16:43:07 UTC (rev 2781)
+++ branches/7.1.x/engine/src/main/java/org/teiid/dqp/service/TransactionService.java 2010-12-15 19:00:32 UTC (rev 2782)
@@ -47,8 +47,6 @@
TransactionContext getOrCreateTransactionContext(String threadId);
- void closeTransactionContext(TransactionContext tc);
-
void suspend(TransactionContext context) throws XATransactionException;
void resume(TransactionContext context) throws XATransactionException;
Modified: branches/7.1.x/jboss-integration/src/main/java/org/teiid/jboss/deployers/RuntimeEngineDeployer.java
===================================================================
--- branches/7.1.x/jboss-integration/src/main/java/org/teiid/jboss/deployers/RuntimeEngineDeployer.java 2010-12-15 16:43:07 UTC (rev 2781)
+++ branches/7.1.x/jboss-integration/src/main/java/org/teiid/jboss/deployers/RuntimeEngineDeployer.java 2010-12-15 19:00:32 UTC (rev 2782)
@@ -161,24 +161,30 @@
}
}
}
- /*
- * having only a single clientserviceregistry means that the admin and jdbc ports are functionally equivalent.
- * this is an undocuemented feature. Designer integration relies on this to use the same port
- * for admin and preview logic.
- */
+
this.csr.registerClientService(ILogon.class, logon, LogConstants.CTX_SECURITY);
- this.csr.registerClientService(DQP.class, proxyService(DQP.class, this.dqpCore, LogConstants.CTX_DQP), LogConstants.CTX_DQP);
- this.csr.registerClientService(Admin.class, proxyService(Admin.class, admin, LogConstants.CTX_ADMIN_API), LogConstants.CTX_ADMIN_API);
+ DQP dqpProxy = proxyService(DQP.class, this.dqpCore, LogConstants.CTX_DQP);
+ this.csr.registerClientService(DQP.class, dqpProxy, LogConstants.CTX_DQP);
+ Admin adminProxy = proxyService(Admin.class, admin, LogConstants.CTX_ADMIN_API);
+ this.csr.registerClientService(Admin.class, adminProxy, LogConstants.CTX_ADMIN_API);
+ ClientServiceRegistryImpl jdbcCsr = new ClientServiceRegistryImpl();
+ jdbcCsr.registerClientService(ILogon.class, logon, LogConstants.CTX_SECURITY);
+ jdbcCsr.registerClientService(DQP.class, dqpProxy, LogConstants.CTX_DQP);
+
if (this.jdbcSocketConfiguration.getEnabled()) {
- this.jdbcSocket = new SocketListener(this.jdbcSocketConfiguration, csr, this.dqpCore.getBufferManager(), offset);
+ this.jdbcSocket = new SocketListener(this.jdbcSocketConfiguration, jdbcCsr, this.dqpCore.getBufferManager(), offset);
LogManager.logInfo(LogConstants.CTX_RUNTIME, IntegrationPlugin.Util.getString("socket_enabled","Teiid JDBC = ",(this.jdbcSocketConfiguration.getSSLConfiguration().isSslEnabled()?"mms://":"mm://")+this.jdbcSocketConfiguration.getHostAddress().getHostName()+":"+(this.jdbcSocketConfiguration.getPortNumber()+offset))); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$ //$NON-NLS-4$ //$NON-NLS-5$
} else {
LogManager.logInfo(LogConstants.CTX_RUNTIME, IntegrationPlugin.Util.getString("socket_not_enabled", "jdbc connections")); //$NON-NLS-1$ //$NON-NLS-2$
}
+ ClientServiceRegistryImpl adminCsr = new ClientServiceRegistryImpl(Type.Admin);
+ adminCsr.registerClientService(ILogon.class, logon, LogConstants.CTX_SECURITY);
+ adminCsr.registerClientService(Admin.class, adminProxy, LogConstants.CTX_ADMIN_API);
+
if (this.adminSocketConfiguration.getEnabled()) {
- this.adminSocket = new SocketListener(this.adminSocketConfiguration, csr, this.dqpCore.getBufferManager(), offset);
+ this.adminSocket = new SocketListener(this.adminSocketConfiguration, adminCsr, this.dqpCore.getBufferManager(), offset);
LogManager.logInfo(LogConstants.CTX_RUNTIME, IntegrationPlugin.Util.getString("socket_enabled","Teiid Admin", (this.adminSocketConfiguration.getSSLConfiguration().isSslEnabled()?"mms://":"mm://")+this.adminSocketConfiguration.getHostAddress().getHostName()+":"+(this.adminSocketConfiguration.getPortNumber()+offset))); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$ //$NON-NLS-4$ //$NON-NLS-5$
} else {
LogManager.logInfo(LogConstants.CTX_RUNTIME, IntegrationPlugin.Util.getString("socket_not_enabled", "admin connections")); //$NON-NLS-1$ //$NON-NLS-2$
@@ -186,7 +192,7 @@
if (this.odbcSocketConfiguration.getEnabled()) {
this.vdbRepository.odbcEnabled();
- this.odbcSocket = new ODBCSocketListener(this.odbcSocketConfiguration, csr, this.dqpCore.getBufferManager(), offset);
+ this.odbcSocket = new ODBCSocketListener(this.odbcSocketConfiguration, this.dqpCore.getBufferManager(), offset);
LogManager.logInfo(LogConstants.CTX_RUNTIME, IntegrationPlugin.Util.getString("odbc_enabled","Teiid ODBC - SSL=", (this.odbcSocketConfiguration.getSSLConfiguration().isSslEnabled()?"ON":"OFF")+" Host = "+this.odbcSocketConfiguration.getHostAddress().getHostName()+" Port = "+(this.odbcSocketConfiguration.getPortNumber()+offset))); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$ //$NON-NLS-4$ //$NON-NLS-5$ //$NON-NLS-6$
} else {
LogManager.logInfo(LogConstants.CTX_RUNTIME, IntegrationPlugin.Util.getString("odbc_not_enabled")); //$NON-NLS-1$
Modified: branches/7.1.x/runtime/src/main/java/org/teiid/services/SessionServiceImpl.java
===================================================================
--- branches/7.1.x/runtime/src/main/java/org/teiid/services/SessionServiceImpl.java 2010-12-15 16:43:07 UTC (rev 2781)
+++ branches/7.1.x/runtime/src/main/java/org/teiid/services/SessionServiceImpl.java 2010-12-15 19:00:32 UTC (rev 2782)
@@ -103,7 +103,7 @@
closeSession(info.getSessionId());
}
} catch (Exception e) {
- LogManager.logDetail(LogConstants.CTX_SECURITY, e, "error running session monitor, unable to monitor: " + info.getSessionId()); //$NON-NLS-1$
+ LogManager.logDetail(LogConstants.CTX_SECURITY, e, "error running session monitor, unable to monitor:", info.getSessionId()); //$NON-NLS-1$
}
}
}
@@ -192,7 +192,7 @@
newSession.setLoginContext(loginContext);
newSession.setSecurityContext(securityContext);
newSession.setVdb(vdb);
- LogManager.logDetail(LogConstants.CTX_SECURITY, new Object[] {"Logon successful for \"", userName, "\" - created SessionID \"", "" + newSession.getSessionToken().getSessionID(), "\"" }); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$ //$NON-NLS-4$
+ LogManager.logDetail(LogConstants.CTX_SECURITY, new Object[] {"Logon successful for \"", userName, "\" - created SessionID \"", newSession.getSessionToken().getSessionID(), "\"" }); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$
this.sessionCache.put(newSession.getSessionId(), newSession);
return newSession;
}
@@ -279,7 +279,7 @@
SessionMetadata info = getSessionInfo(sessionID);
info.setLastPingTime(System.currentTimeMillis());
this.sessionCache.put(sessionID, info);
- LogManager.logDetail(LogConstants.CTX_SECURITY, "Keep-alive ping received for session:"+sessionID); //$NON-NLS-1$
+ LogManager.logDetail(LogConstants.CTX_SECURITY, "Keep-alive ping received for session:", sessionID); //$NON-NLS-1$
}
@Override
Modified: branches/7.1.x/runtime/src/main/java/org/teiid/transport/ClientServiceRegistry.java
===================================================================
--- branches/7.1.x/runtime/src/main/java/org/teiid/transport/ClientServiceRegistry.java 2010-12-15 16:43:07 UTC (rev 2781)
+++ branches/7.1.x/runtime/src/main/java/org/teiid/transport/ClientServiceRegistry.java 2010-12-15 19:00:32 UTC (rev 2782)
@@ -28,6 +28,10 @@
public interface ClientServiceRegistry {
+ public enum Type {
+ ODBC, JDBC, Admin
+ }
+
<T> T getClientService(Class<T> iface) throws ComponentNotFoundException;
SecurityHelper getSecurityHelper();
Modified: branches/7.1.x/runtime/src/main/java/org/teiid/transport/ClientServiceRegistryImpl.java
===================================================================
--- branches/7.1.x/runtime/src/main/java/org/teiid/transport/ClientServiceRegistryImpl.java 2010-12-15 16:43:07 UTC (rev 2781)
+++ branches/7.1.x/runtime/src/main/java/org/teiid/transport/ClientServiceRegistryImpl.java 2010-12-15 19:00:32 UTC (rev 2782)
@@ -31,7 +31,7 @@
public class ClientServiceRegistryImpl implements ClientServiceRegistry {
-
+
public static class ClientService {
private Object instance;
private String loggingContext;
@@ -57,6 +57,15 @@
private HashMap<String, ClientService> clientServices = new HashMap<String, ClientService>();
private SecurityHelper securityHelper;
+ private Type type = Type.JDBC;
+
+ public ClientServiceRegistryImpl() {
+
+ }
+
+ public ClientServiceRegistryImpl(Type type) {
+ this.type = type;
+ }
public <T> T getClientService(Class<T> iface) throws ComponentNotFoundException {
ClientService cs = getClientService(iface.getName());
@@ -66,7 +75,7 @@
public ClientService getClientService(String iface) throws ComponentNotFoundException {
ClientService cs = clientServices.get(iface);
if (cs == null) {
- throw new ComponentNotFoundException(RuntimePlugin.Util.getString("ServerWorkItem.Component_Not_Found", iface)); //$NON-NLS-1$
+ throw new ComponentNotFoundException(RuntimePlugin.Util.getString("ServerWorkItem.Component_Not_Found", type, iface)); //$NON-NLS-1$
}
return cs;
}
Modified: branches/7.1.x/runtime/src/main/java/org/teiid/transport/ODBCSocketListener.java
===================================================================
--- branches/7.1.x/runtime/src/main/java/org/teiid/transport/ODBCSocketListener.java 2010-12-15 16:43:07 UTC (rev 2781)
+++ branches/7.1.x/runtime/src/main/java/org/teiid/transport/ODBCSocketListener.java 2010-12-15 19:00:32 UTC (rev 2782)
@@ -33,8 +33,9 @@
public class ODBCSocketListener extends SocketListener {
private ODBCServerRemote.AuthenticationType authType = ODBCServerRemote.AuthenticationType.CLEARTEXT;
- public ODBCSocketListener(SocketConfiguration config, ClientServiceRegistryImpl csr, StorageManager storageManager, int portOffset) {
- super(config, csr, storageManager, portOffset);
+ public ODBCSocketListener(SocketConfiguration config, StorageManager storageManager, int portOffset) {
+ //the clientserviceregistry isn't actually used by ODBC
+ super(config, new ClientServiceRegistryImpl(ClientServiceRegistry.Type.ODBC), storageManager, portOffset);
}
@Override
Modified: branches/7.1.x/runtime/src/main/resources/org/teiid/runtime/i18n.properties
===================================================================
--- branches/7.1.x/runtime/src/main/resources/org/teiid/runtime/i18n.properties 2010-12-15 16:43:07 UTC (rev 2781)
+++ branches/7.1.x/runtime/src/main/resources/org/teiid/runtime/i18n.properties 2010-12-15 19:00:32 UTC (rev 2782)
@@ -42,16 +42,16 @@
ServerWorkItem.Received_exception_processing_request=Unexpected exception for session {0}
ServerWorkItem.processing_error=Processing exception ''{0}'' for session {1}. Exception type {2} thrown from {3}. Enable more detailed logging to see the entire stacktrace.
-ServerWorkItem.Component_Not_Found=Component not found: {0}
+ServerWorkItem.Component_Not_Found=Only {0} connections are allowed on this port. Component not found: {1}
SocketTransport.1=Bound to address {0} listening on port {1}
-LocalTransportHandler.Transport_shutdown=Tranport has been shutdown.
+LocalTransportHandler.Transport_shutdown=Transport has been shutdown.
SocketClientInstance.invalid_sessionkey=Invalid session key used during handshake
SSLAwareChannelHandler.channel_closed=Channel closed
invlaid_vdb_file=Invalid VDB file deployment failed {0}
redeploying_vdb=Re-deploying VDB {0}
-validity_errors_in_vdb=VDB has validaity errors; failed to deploy - {0}
+validity_errors_in_vdb=VDB has validity errors; failed to deploy - {0}
vdb_save_failed=Failed to save metadata for VDB {0}
vdb_delete_failed=Failed to delete the cached metadata files due to:
vdb_deployed=VDB "{0}" deployed in {1} state.
14 years