[teiid-commits] teiid SVN: r2644 - in trunk: engine/src/main/java/org/teiid/dqp/internal/process/multisource and 5 other directories.

teiid-commits at lists.jboss.org teiid-commits at lists.jboss.org
Tue Oct 12 16:23:15 EDT 2010


Author: rareddy
Date: 2010-10-12 16:23:14 -0400 (Tue, 12 Oct 2010)
New Revision: 2644

Modified:
   trunk/documentation/reference/src/main/docbook/en-US/content/translators.xml
   trunk/engine/src/main/java/org/teiid/dqp/internal/process/multisource/MultiSourceElementReplacementVisitor.java
   trunk/engine/src/main/java/org/teiid/dqp/internal/process/multisource/MultiSourceMetadataWrapper.java
   trunk/engine/src/main/java/org/teiid/dqp/internal/process/multisource/MultiSourcePlanToProcessConverter.java
   trunk/engine/src/main/java/org/teiid/query/processor/relational/RelationalNode.java
   trunk/engine/src/main/java/org/teiid/query/processor/relational/RelationalNodeUtil.java
   trunk/engine/src/main/java/org/teiid/query/processor/relational/RelationalPlan.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/dqp/internal/process/multisource/TestMultiSourceElementReplacementVisitor.java
   trunk/engine/src/test/java/org/teiid/query/validator/TestValidator.java
Log:
TEIID-1273, TEIID-1295, TEIID-1296: multi-source insert capability is added. Also corrected update count and mark them as transactional when more than single source is involved.

Modified: trunk/documentation/reference/src/main/docbook/en-US/content/translators.xml
===================================================================
--- trunk/documentation/reference/src/main/docbook/en-US/content/translators.xml	2010-10-12 18:04:46 UTC (rev 2643)
+++ trunk/documentation/reference/src/main/docbook/en-US/content/translators.xml	2010-10-12 20:23:14 UTC (rev 2644)
@@ -1229,7 +1229,7 @@
         <para>
         To mark a model as multi-source, the user needs to supply property called 
         <property>supports-multi-source-bindings</property>, in the "vdb.xml" file.  
-        Also, the user needs to define multiple sources. Here is code example showing single model with 
+        Also, the user needs to define multiple sources. Here is code example showing dynamic vdb with single model with 
         multiple sources defined.
         </para>
         
@@ -1258,12 +1258,13 @@
         
         <programlisting language="SQL"><![CDATA[select * from table where SOURCE_NAME = 'newyork'
 update table column=value  where SOURCE_NAME='chicago'
-delete from table where column = x and SOURCE_NAME='la']]></programlisting>
+delete from table where column = x and SOURCE_NAME='la'
+insert into table (column, SOURCE_NAME) VALUES ('value', 'newyork')]]></programlisting>
       
         <para>
-        Note that when user do not supply the "SOURCE_NAME" in the criteria, it applies 
-        to all the sources. Unfortunately Teiid currently does not support INSERT, this 
-        planned for future releases. Another useful feature along with this feature is 
+        Note that when user do not supply the "SOURCE_NAME" in the criteria, the command applies 
+        to all the sources. If SOURCE_NAME supplied, the query is executed only aginst the source specified. 
+        Another useful feature along with this feature is 
         "partial results" to skip unavailable sources if they are down.
         </para>
         
@@ -1273,7 +1274,7 @@
             limited, so if you need to use this feature build the VDB as usual in 
             the Teiid Designer and then edit the "vdb.xml" file in the VDB archive 
             using a Text editor to add the additional sources as defined above. 
-            You must deploy a data source for each source defined.
+            You must deploy a separate data source for each source defined in the xml file.
             </para>
         </note>
         

Modified: trunk/engine/src/main/java/org/teiid/dqp/internal/process/multisource/MultiSourceElementReplacementVisitor.java
===================================================================
--- trunk/engine/src/main/java/org/teiid/dqp/internal/process/multisource/MultiSourceElementReplacementVisitor.java	2010-10-12 18:04:46 UTC (rev 2643)
+++ trunk/engine/src/main/java/org/teiid/dqp/internal/process/multisource/MultiSourceElementReplacementVisitor.java	2010-10-12 20:23:14 UTC (rev 2644)
@@ -23,6 +23,11 @@
 package org.teiid.dqp.internal.process.multisource;
 
 import org.teiid.core.types.DataTypeManager;
+import org.teiid.query.rewriter.QueryRewriter;
+import org.teiid.query.sql.lang.From;
+import org.teiid.query.sql.lang.Insert;
+import org.teiid.query.sql.lang.Query;
+import org.teiid.query.sql.lang.Select;
 import org.teiid.query.sql.symbol.Constant;
 import org.teiid.query.sql.symbol.ElementSymbol;
 import org.teiid.query.sql.symbol.Expression;
@@ -50,4 +55,29 @@
         
         return expr;
     }
+    
+    public void visit(Insert obj) {
+    	for (int i = 0; i < obj.getVariables().size(); i++) {
+    		Expression expr = (Expression)obj.getVariables().get(i);
+            if(expr instanceof ElementSymbol) {
+                ElementSymbol elem = (ElementSymbol) expr;
+                Object metadataID = elem.getMetadataID();            
+                if(metadataID instanceof MultiSourceElement) {
+                	Constant source = (Constant)obj.getValues().get(i);
+            		obj.getVariables().remove(i);
+            		obj.getValues().remove(i);
+                	if (!source.getValue().equals(this.bindingName)) {
+	                	Select select = new Select(obj.getVariables());
+	                    From from = new From();
+	                    from.addGroup(obj.getGroup());	                    
+	                    Query query = new Query();
+	                    query.setSelect(select);
+	                    query.setFrom(from);
+	                    query.setCriteria(QueryRewriter.FALSE_CRITERIA);
+	                    obj.setQueryExpression(query);                		
+                	}
+                }
+            }
+    	}
+    }    
 }

Modified: trunk/engine/src/main/java/org/teiid/dqp/internal/process/multisource/MultiSourceMetadataWrapper.java
===================================================================
--- trunk/engine/src/main/java/org/teiid/dqp/internal/process/multisource/MultiSourceMetadataWrapper.java	2010-10-12 18:04:46 UTC (rev 2643)
+++ trunk/engine/src/main/java/org/teiid/dqp/internal/process/multisource/MultiSourceMetadataWrapper.java	2010-10-12 20:23:14 UTC (rev 2644)
@@ -271,7 +271,7 @@
                 case SupportConstants.Element.SELECT:
                     return true;
                 case SupportConstants.Element.UPDATE:
-                    return false;
+                    return true;
                 case SupportConstants.Element.DEFAULT_VALUE:
                     return false;
                 case SupportConstants.Element.AUTO_INCREMENT:

Modified: trunk/engine/src/main/java/org/teiid/dqp/internal/process/multisource/MultiSourcePlanToProcessConverter.java
===================================================================
--- trunk/engine/src/main/java/org/teiid/dqp/internal/process/multisource/MultiSourcePlanToProcessConverter.java	2010-10-12 18:04:46 UTC (rev 2643)
+++ trunk/engine/src/main/java/org/teiid/dqp/internal/process/multisource/MultiSourcePlanToProcessConverter.java	2010-10-12 20:23:14 UTC (rev 2644)
@@ -33,20 +33,31 @@
 import org.teiid.core.TeiidComponentException;
 import org.teiid.core.TeiidProcessingException;
 import org.teiid.core.id.IDGenerator;
+import org.teiid.core.types.DataTypeManager;
 import org.teiid.dqp.internal.process.DQPWorkContext;
+import org.teiid.language.SQLConstants.NonReserved;
 import org.teiid.query.analysis.AnalysisRecord;
+import org.teiid.query.function.FunctionLibrary;
 import org.teiid.query.metadata.QueryMetadataInterface;
 import org.teiid.query.optimizer.capabilities.CapabilitiesFinder;
 import org.teiid.query.optimizer.relational.PlanToProcessConverter;
 import org.teiid.query.optimizer.relational.plantree.PlanNode;
 import org.teiid.query.processor.relational.AccessNode;
+import org.teiid.query.processor.relational.GroupingNode;
 import org.teiid.query.processor.relational.NullNode;
+import org.teiid.query.processor.relational.ProjectNode;
 import org.teiid.query.processor.relational.RelationalNode;
 import org.teiid.query.processor.relational.RelationalNodeUtil;
 import org.teiid.query.processor.relational.UnionAllNode;
+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.navigator.DeepPreOrderNavigator;
+import org.teiid.query.sql.symbol.AggregateSymbol;
+import org.teiid.query.sql.symbol.Constant;
+import org.teiid.query.sql.symbol.Expression;
+import org.teiid.query.sql.symbol.ExpressionSymbol;
+import org.teiid.query.sql.symbol.Function;
 import org.teiid.query.util.CommandContext;
 
 
@@ -102,6 +113,10 @@
             // Replace all multi-source elements with the source name
             DeepPreOrderNavigator.doVisit(command, new MultiSourceElementReplacementVisitor(sourceName));
 
+            if (!RelationalNodeUtil.shouldExecute(command, false)) {
+                continue;
+            }
+            
             // Rewrite the command now that criteria may have been simplified
             try {
                 command = QueryRewriter.rewrite(command, metadata, null);                    
@@ -133,17 +148,44 @@
             }
             default:
             {
-                // More than 1 access node - replace with a union
+
+            	UnionAllNode unionNode = new UnionAllNode(getID());
+            	unionNode.setElements(accessNode.getElements());
                 
-                UnionAllNode unionNode = new UnionAllNode(getID());
-                unionNode.setElements(accessNode.getElements());
-                
-                RelationalNode parent = unionNode;
-                                
                 for (AccessNode newNode : accessNodes) {
-                    unionNode.addChild(newNode);
+                	unionNode.addChild(newNode);
                 }
+            	
+            	RelationalNode parent = unionNode;
+            	
+                // More than 1 access node - replace with a union
+            	if (RelationalNodeUtil.isUpdate(accessNode.getCommand())) {
+            		
+            		GroupingNode groupNode = new GroupingNode(getID());                    
+            		AggregateSymbol sumCount = new AggregateSymbol("SumCount", NonReserved.SUM, false, (Expression)accessNode.getElements().get(0)); //$NON-NLS-1$          		
+            		List outputElements = new ArrayList();            		
+            		outputElements.add(sumCount); 
+            		groupNode.setElements(outputElements);
+            		groupNode.addChild(unionNode);
+            		
+            		ProjectNode projectNode = new ProjectNode(getID());
+            		// two converts because, the 2nd one does not resolve because of no metadata about the expression.
+            		Function convertFunc = new Function(FunctionLibrary.CONVERT, new Expression[] {new Constant(new Long(0)), new Constant(DataTypeManager.DefaultDataTypes.INTEGER)});
+            		ResolverVisitor.resolveLanguageObject(convertFunc, metadata);
+            		Function convertFunc2 = new Function(FunctionLibrary.CONVERT, new Expression[] {sumCount, new Constant(DataTypeManager.DefaultDataTypes.INTEGER)});
+            		convertFunc2.setFunctionDescriptor(convertFunc.getFunctionDescriptor());
+            		
+            		Expression rowCount = new ExpressionSymbol("RowCount", convertFunc2); //$NON-NLS-1$            		
+            		outputElements = new ArrayList();            		
+            		outputElements.add(rowCount);             		
+            		projectNode.setElements(outputElements);
+            		projectNode.setSelectSymbols(outputElements);
+            		projectNode.addChild(groupNode);
+            		
+            		parent = projectNode;
+            	}
                 
+                parent.setMultiSource(true);
                 return parent;
             }
         }

Modified: trunk/engine/src/main/java/org/teiid/query/processor/relational/RelationalNode.java
===================================================================
--- trunk/engine/src/main/java/org/teiid/query/processor/relational/RelationalNode.java	2010-10-12 18:04:46 UTC (rev 2643)
+++ trunk/engine/src/main/java/org/teiid/query/processor/relational/RelationalNode.java	2010-10-12 20:23:14 UTC (rev 2644)
@@ -87,6 +87,8 @@
 
 	/** Child nodes, usually just 1 or 2 */
 	private RelationalNode[] children = new RelationalNode[2];
+	
+	private boolean multiSource;
 
 	protected RelationalNode() {
 		
@@ -596,4 +598,12 @@
 		}
 		return processingState;
 	}
+	
+	public boolean isMultiSource() {
+		return multiSource;
+	}
+
+	public void setMultiSource(boolean multiSource) {
+		this.multiSource = multiSource;
+	}	
 }
\ No newline at end of file

Modified: trunk/engine/src/main/java/org/teiid/query/processor/relational/RelationalNodeUtil.java
===================================================================
--- trunk/engine/src/main/java/org/teiid/query/processor/relational/RelationalNodeUtil.java	2010-10-12 18:04:46 UTC (rev 2643)
+++ trunk/engine/src/main/java/org/teiid/query/processor/relational/RelationalNodeUtil.java	2010-10-12 20:23:14 UTC (rev 2644)
@@ -29,6 +29,7 @@
 import org.teiid.query.sql.lang.Command;
 import org.teiid.query.sql.lang.Criteria;
 import org.teiid.query.sql.lang.Delete;
+import org.teiid.query.sql.lang.Insert;
 import org.teiid.query.sql.lang.Limit;
 import org.teiid.query.sql.lang.Query;
 import org.teiid.query.sql.lang.QueryCommand;
@@ -123,6 +124,13 @@
                     return true;
                 }
                 break;
+            case Command.TYPE_INSERT:
+            	Insert insert = (Insert) command;
+            	QueryCommand expr = insert.getQueryExpression();
+            	if (expr != null) {
+            		return shouldExecute(expr, simplifyCriteria);
+            	}
+            	return true;
             case Command.TYPE_UPDATE:
                 Update update = (Update) command;
                 
@@ -174,7 +182,7 @@
      * @return
      * @since 4.2
      */
-    static boolean isUpdate(Command command) {
+    public static boolean isUpdate(Command command) {
         int commandType = command.getType();
         return commandType == Command.TYPE_INSERT ||
                commandType == Command.TYPE_UPDATE ||

Modified: trunk/engine/src/main/java/org/teiid/query/processor/relational/RelationalPlan.java
===================================================================
--- trunk/engine/src/main/java/org/teiid/query/processor/relational/RelationalPlan.java	2010-10-12 18:04:46 UTC (rev 2643)
+++ trunk/engine/src/main/java/org/teiid/query/processor/relational/RelationalPlan.java	2010-10-12 20:23:14 UTC (rev 2644)
@@ -239,6 +239,9 @@
 				}
 			}
     	}
+    	if (this.root.isMultiSource()) {
+    		return true;
+    	}
     	return requiresTransaction(transactionalReads, root);
     }
     

Modified: trunk/engine/src/main/java/org/teiid/query/validator/ValidationVisitor.java
===================================================================
--- trunk/engine/src/main/java/org/teiid/query/validator/ValidationVisitor.java	2010-10-12 18:04:46 UTC (rev 2643)
+++ trunk/engine/src/main/java/org/teiid/query/validator/ValidationVisitor.java	2010-10-12 20:23:14 UTC (rev 2644)
@@ -42,6 +42,7 @@
 import org.teiid.core.TeiidProcessingException;
 import org.teiid.core.types.DataTypeManager;
 import org.teiid.core.util.EquivalenceUtil;
+import org.teiid.dqp.internal.process.multisource.MultiSourceElement;
 import org.teiid.query.QueryPlugin;
 import org.teiid.query.eval.Evaluator;
 import org.teiid.query.function.FunctionLibrary;
@@ -788,7 +789,8 @@
 	            ElementSymbol nextElmnt = (ElementSymbol) ignoreIter.next();
 				if(!getMetadata().elementSupports(nextElmnt.getMetadataID(), SupportConstants.Element.DEFAULT_VALUE) &&
 					!getMetadata().elementSupports(nextElmnt.getMetadataID(), SupportConstants.Element.NULL) &&
-                    !getMetadata().elementSupports(nextElmnt.getMetadataID(), SupportConstants.Element.AUTO_INCREMENT)) {
+                    !getMetadata().elementSupports(nextElmnt.getMetadataID(), SupportConstants.Element.AUTO_INCREMENT) &&
+                     !(nextElmnt.getMetadataID() instanceof MultiSourceElement)) {
 		                handleValidationError(QueryPlugin.Util.getString("ERR.015.012.0053", new Object[] {insertGroup, nextElmnt}), nextElmnt); //$NON-NLS-1$
 				}
 			}
@@ -843,6 +845,11 @@
                 if(! getMetadata().elementSupports(elementID.getMetadataID(), SupportConstants.Element.UPDATE)) {
                     handleValidationError(QueryPlugin.Util.getString("ERR.015.012.0059", elementID), elementID); //$NON-NLS-1$
                 }
+                
+                Object metadataID = elementID.getMetadataID();
+                if (metadataID instanceof MultiSourceElement){
+                	handleValidationError(QueryPlugin.Util.getString("multi_source_update_not_allowed", elementID), elementID); //$NON-NLS-1$
+                }
 
 			    // Check that right expression is a constant and is non-null
                 Expression value = entry.getValue();

Modified: trunk/engine/src/main/resources/org/teiid/query/i18n.properties
===================================================================
--- trunk/engine/src/main/resources/org/teiid/query/i18n.properties	2010-10-12 18:04:46 UTC (rev 2643)
+++ trunk/engine/src/main/resources/org/teiid/query/i18n.properties	2010-10-12 20:23:14 UTC (rev 2644)
@@ -860,4 +860,5 @@
 RequestWorkItem.cache_nondeterministic=Caching command '{0}'' at a session level, but less deterministic functions were evaluated. 
 not_found_cache=Results not found in cache
 failed_to_unwrap_connection=Failed to unwrap the source connection.
-connection_factory_not_found=Failed to the Connection Factory with JNDI name {0}. Please check the name for spelling or deploy the Connection Factory with specified name. 
\ No newline at end of file
+connection_factory_not_found=Failed to the Connection Factory with JNDI name {0}. Please check the name for spelling or deploy the Connection Factory with specified name. 
+multi_source_update_not_allowed=Update of the column {0} is not allowed.
\ No newline at end of file

Modified: trunk/engine/src/test/java/org/teiid/dqp/internal/process/multisource/TestMultiSourceElementReplacementVisitor.java
===================================================================
--- trunk/engine/src/test/java/org/teiid/dqp/internal/process/multisource/TestMultiSourceElementReplacementVisitor.java	2010-10-12 18:04:46 UTC (rev 2643)
+++ trunk/engine/src/test/java/org/teiid/dqp/internal/process/multisource/TestMultiSourceElementReplacementVisitor.java	2010-10-12 20:23:14 UTC (rev 2644)
@@ -45,7 +45,7 @@
         
         QueryMetadataInterface metadata = FakeMetadataFactory.exampleMultiBinding();
         Set<String> multiSourceModels = new HashSet<String>();
-        multiSourceModels.add("MultiModel");
+        multiSourceModels.add("MultiModel"); //$NON-NLS-1$
         MultiSourceMetadataWrapper wrapper = new MultiSourceMetadataWrapper(metadata, multiSourceModels);  
         
         return wrapper;
@@ -121,5 +121,23 @@
                  getMetadata(),
                  "SELECT a FROM MultiModel.Phys WHERE 'x' = (SELECT b FROM MultiModel.Phys WHERE 'x' IN ('x'))"); //$NON-NLS-1$
     }
+    
+    public void testInsertMatching() throws Exception {
+        helpTest("INSERT INTO MultiModel.Phys(a, SOURCE_NAME) VALUES('a', 'x')", //$NON-NLS-1$
+                 getMetadata(),
+                 "INSERT INTO MultiModel.Phys (a, SOURCE_NAME) SELECT a WHERE '1' = '2'"); //$NON-NLS-1$
+    }
+    
+    public void testInsertNotMatching() throws Exception {
+        helpTest("INSERT INTO MultiModel.Phys(a, SOURCE_NAME) VALUES('a', 'y')", //$NON-NLS-1$
+                 getMetadata(),
+                 "INSERT INTO MultiModel.Phys (a, SOURCE_NAME) SELECT a WHERE '1' = '2'"); //$NON-NLS-1$
+    }
+    
+    public void testInsertAll() throws Exception {
+        helpTest("INSERT INTO MultiModel.Phys(a) VALUES('a')", //$NON-NLS-1$
+                 getMetadata(),
+                 "INSERT INTO MultiModel.Phys (a) VALUES ('a')"); //$NON-NLS-1$
+    }
 
 }

Modified: trunk/engine/src/test/java/org/teiid/query/validator/TestValidator.java
===================================================================
--- trunk/engine/src/test/java/org/teiid/query/validator/TestValidator.java	2010-10-12 18:04:46 UTC (rev 2643)
+++ trunk/engine/src/test/java/org/teiid/query/validator/TestValidator.java	2010-10-12 20:23:14 UTC (rev 2644)
@@ -22,7 +22,9 @@
 
 package org.teiid.query.validator;
 
-import static org.junit.Assert.*;
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertTrue;
+import static org.junit.Assert.fail;
 
 import java.util.ArrayList;
 import java.util.Arrays;
@@ -44,6 +46,7 @@
 import org.teiid.core.TeiidException;
 import org.teiid.core.TeiidRuntimeException;
 import org.teiid.core.types.DataTypeManager;
+import org.teiid.dqp.internal.process.multisource.MultiSourceMetadataWrapper;
 import org.teiid.query.analysis.AnalysisRecord;
 import org.teiid.query.mapping.relational.QueryNode;
 import org.teiid.query.mapping.xml.MappingDocument;
@@ -2030,4 +2033,10 @@
         helpValidate("SELECT e2, (SELECT e1, e2 FROM pm1.g1 WHERE e2 = '3') FROM pm1.g2", new String[] {"SELECT e1, e2 FROM pm1.g1 WHERE e2 = '3'"}, FakeMetadataFactory.example1Cached()); //$NON-NLS-1$ //$NON-NLS-2$
     }
 
+    @Test public void testDisallowUpdateOnMultisourceElement() throws Exception {  
+    	Set<String> models = new HashSet<String>();
+    	models.add("pm1");
+        ValidatorReport report = helpValidateInModeler("pm1.vsp36", "UPDATE PM1.G1 set SOURCE_NAME='blah'", new MultiSourceMetadataWrapper(FakeMetadataFactory.example1Cached(), models));  //$NON-NLS-1$
+        assertEquals(report.toString(), 1, report.getItems().size());
+    }
 }



More information about the teiid-commits mailing list