[teiid-commits] teiid SVN: r2787 - in trunk: engine/src/main/java/org/teiid/query/optimizer/relational and 6 other directories.

teiid-commits at lists.jboss.org teiid-commits at lists.jboss.org
Mon Dec 20 11:52:46 EST 2010


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$
+    }
 
 }
 



More information about the teiid-commits mailing list