[teiid-commits] teiid SVN: r4447 - in trunk: connectors/translator-jdbc/src/main/java/org/teiid/translator/jdbc/oracle and 13 other directories.

teiid-commits at lists.jboss.org teiid-commits at lists.jboss.org
Fri Sep 14 13:19:06 EDT 2012


Author: shawkins
Date: 2012-09-14 13:19:05 -0400 (Fri, 14 Sep 2012)
New Revision: 4447

Modified:
   trunk/api/src/main/java/org/teiid/translator/SourceSystemFunctions.java
   trunk/connectors/translator-jdbc/src/main/java/org/teiid/translator/jdbc/oracle/OracleExecutionFactory.java
   trunk/connectors/translator-jdbc/src/test/java/org/teiid/translator/jdbc/TestSQLConversionVisitor.java
   trunk/connectors/translator-jdbc/src/test/java/org/teiid/translator/jdbc/db2/TestDB2SqlTranslator.java
   trunk/connectors/translator-jdbc/src/test/java/org/teiid/translator/jdbc/derby/TestDerbySQLTranslator.java
   trunk/connectors/translator-jdbc/src/test/java/org/teiid/translator/jdbc/oracle/TestOracleTranslator.java
   trunk/engine/src/main/java/org/teiid/dqp/internal/datamgr/ConnectorWorkItem.java
   trunk/engine/src/main/java/org/teiid/dqp/internal/datamgr/LanguageBridgeFactory.java
   trunk/engine/src/main/java/org/teiid/query/function/FunctionMethods.java
   trunk/engine/src/main/java/org/teiid/query/function/source/SystemSource.java
   trunk/engine/src/main/java/org/teiid/query/optimizer/relational/rules/CapabilitiesUtil.java
   trunk/engine/src/main/java/org/teiid/query/rewriter/QueryRewriter.java
   trunk/engine/src/test/java/org/teiid/cdk/CommandBuilder.java
   trunk/engine/src/test/java/org/teiid/dqp/internal/datamgr/TestFunctionImpl.java
   trunk/engine/src/test/java/org/teiid/query/processor/TestFunctionPushdown.java
   trunk/engine/src/test/java/org/teiid/query/rewriter/TestQueryRewriter.java
Log:
TEIID-2188 adding support for CONCAT2 pushdown

Modified: trunk/api/src/main/java/org/teiid/translator/SourceSystemFunctions.java
===================================================================
--- trunk/api/src/main/java/org/teiid/translator/SourceSystemFunctions.java	2012-09-14 16:04:37 UTC (rev 4446)
+++ trunk/api/src/main/java/org/teiid/translator/SourceSystemFunctions.java	2012-09-14 17:19:05 UTC (rev 4447)
@@ -44,6 +44,7 @@
 	public static final String ASCII = "ascii"; //$NON-NLS-1$
 	public static final String CHAR = "char"; //$NON-NLS-1$
 	public static final String CONCAT = "concat"; //$NON-NLS-1$
+	public static final String CONCAT2 = "concat2"; //$NON-NLS-1$
 	//public static final String DIFFERENCE = "difference";
 	public static final String INITCAP = "initcap"; //$NON-NLS-1$
 	public static final String INSERT = "insert"; //$NON-NLS-1$

Modified: trunk/connectors/translator-jdbc/src/main/java/org/teiid/translator/jdbc/oracle/OracleExecutionFactory.java
===================================================================
--- trunk/connectors/translator-jdbc/src/main/java/org/teiid/translator/jdbc/oracle/OracleExecutionFactory.java	2012-09-14 16:04:37 UTC (rev 4446)
+++ trunk/connectors/translator-jdbc/src/main/java/org/teiid/translator/jdbc/oracle/OracleExecutionFactory.java	2012-09-14 17:19:05 UTC (rev 4447)
@@ -126,6 +126,7 @@
         registerFunctionModifier(SourceSystemFunctions.LEFT, new LeftOrRightFunctionModifier(getLanguageFactory()));
         registerFunctionModifier(SourceSystemFunctions.RIGHT, new LeftOrRightFunctionModifier(getLanguageFactory()));
         registerFunctionModifier(SourceSystemFunctions.CONCAT, new ConcatFunctionModifier(getLanguageFactory())); 
+        registerFunctionModifier(SourceSystemFunctions.CONCAT2, new AliasModifier("||")); //$NON-NLS-1$
         registerFunctionModifier(SourceSystemFunctions.COT, new FunctionModifier() {
 			@Override
 			public List<?> translate(Function function) {
@@ -589,6 +590,7 @@
         supportedFunctions.add("CHAR"); //$NON-NLS-1$
         supportedFunctions.add("CHR"); //$NON-NLS-1$
         supportedFunctions.add("CONCAT"); //$NON-NLS-1$
+        supportedFunctions.add(SourceSystemFunctions.CONCAT2);
         supportedFunctions.add("||"); //$NON-NLS-1$
         supportedFunctions.add("INITCAP"); //$NON-NLS-1$
         supportedFunctions.add("LCASE"); //$NON-NLS-1$

Modified: trunk/connectors/translator-jdbc/src/test/java/org/teiid/translator/jdbc/TestSQLConversionVisitor.java
===================================================================
--- trunk/connectors/translator-jdbc/src/test/java/org/teiid/translator/jdbc/TestSQLConversionVisitor.java	2012-09-14 16:04:37 UTC (rev 4446)
+++ trunk/connectors/translator-jdbc/src/test/java/org/teiid/translator/jdbc/TestSQLConversionVisitor.java	2012-09-14 17:19:05 UTC (rev 4447)
@@ -441,5 +441,12 @@
             input, 
             output, TRANSLATOR);
     }
+    
+    @Test public void testConcat2() {
+        helpTestVisitor(getTestVDB(),
+                        "select part_name from parts where concat2(part_name, 'x') = concat2(part_weight, part_id)", //$NON-NLS-1$
+                        "SELECT PARTS.PART_NAME FROM PARTS WHERE concat(ifnull(PARTS.PART_NAME, ''), 'x') = CASE WHEN PARTS.PART_WEIGHT IS NULL AND PARTS.PART_ID IS NULL THEN NULL ELSE concat(ifnull(PARTS.PART_WEIGHT, ''), ifnull(PARTS.PART_ID, '')) END", //$NON-NLS-1$
+                        true); 
+    }
 
 }

Modified: trunk/connectors/translator-jdbc/src/test/java/org/teiid/translator/jdbc/db2/TestDB2SqlTranslator.java
===================================================================
--- trunk/connectors/translator-jdbc/src/test/java/org/teiid/translator/jdbc/db2/TestDB2SqlTranslator.java	2012-09-14 16:04:37 UTC (rev 4446)
+++ trunk/connectors/translator-jdbc/src/test/java/org/teiid/translator/jdbc/db2/TestDB2SqlTranslator.java	2012-09-14 17:19:05 UTC (rev 4447)
@@ -98,7 +98,7 @@
     @Test
     public void testConcat2() throws Exception {
         String input = "select concat2(stringnum, stringnum) from BQT1.Smalla"; //$NON-NLS-1$       
-        String output = "SELECT CASE WHEN SmallA.StringNum IS NULL THEN NULL ELSE concat(coalesce(SmallA.StringNum, ''), coalesce(SmallA.StringNum, '')) END FROM SmallA";  //$NON-NLS-1$
+        String output = "SELECT CASE WHEN SmallA.StringNum IS NULL AND SmallA.StringNum IS NULL THEN NULL ELSE concat(coalesce(SmallA.StringNum, ''), coalesce(SmallA.StringNum, '')) END FROM SmallA";  //$NON-NLS-1$
         
         helpTestVisitor(FakeTranslationFactory.getInstance().getBQTTranslationUtility(),
                 input, 

Modified: trunk/connectors/translator-jdbc/src/test/java/org/teiid/translator/jdbc/derby/TestDerbySQLTranslator.java
===================================================================
--- trunk/connectors/translator-jdbc/src/test/java/org/teiid/translator/jdbc/derby/TestDerbySQLTranslator.java	2012-09-14 16:04:37 UTC (rev 4446)
+++ trunk/connectors/translator-jdbc/src/test/java/org/teiid/translator/jdbc/derby/TestDerbySQLTranslator.java	2012-09-14 17:19:05 UTC (rev 4447)
@@ -67,7 +67,7 @@
     @Test
     public void testConcat2() throws Exception {
         String input = "select concat2(stringnum, stringnum) from BQT1.Smalla"; //$NON-NLS-1$       
-        String output = "SELECT CASE WHEN SmallA.StringNum IS NULL THEN NULL ELSE {fn concat(coalesce(SmallA.StringNum, ''), coalesce(SmallA.StringNum, ''))} END FROM SmallA";  //$NON-NLS-1$
+        String output = "SELECT CASE WHEN SmallA.StringNum IS NULL AND SmallA.StringNum IS NULL THEN NULL ELSE {fn concat(coalesce(SmallA.StringNum, ''), coalesce(SmallA.StringNum, ''))} END FROM SmallA";  //$NON-NLS-1$
         
         TranslationHelper.helpTestVisitor(TranslationHelper.BQT_VDB, input, output, TRANSLATOR);
     }    

Modified: trunk/connectors/translator-jdbc/src/test/java/org/teiid/translator/jdbc/oracle/TestOracleTranslator.java
===================================================================
--- trunk/connectors/translator-jdbc/src/test/java/org/teiid/translator/jdbc/oracle/TestOracleTranslator.java	2012-09-14 16:04:37 UTC (rev 4446)
+++ trunk/connectors/translator-jdbc/src/test/java/org/teiid/translator/jdbc/oracle/TestOracleTranslator.java	2012-09-14 17:19:05 UTC (rev 4447)
@@ -380,18 +380,22 @@
     
     @Test public void testConcat2_useLiteral() throws Exception {        
         String input = "select concat2(stringnum,'_xx') from bqt1.Smalla"; //$NON-NLS-1$
-        String output = "SELECT concat(nvl(SmallA.StringNum, ''), '_xx') FROM SmallA"; //$NON-NLS-1$
-        TranslationHelper.helpTestVisitor(TranslationHelper.BQT_VDB, UDF,
-                input, output, 
-                TRANSLATOR);
+        String output = "SELECT (g_0.StringNum || '_xx') FROM SmallA g_0"; //$NON-NLS-1$
+        
+        CommandBuilder commandBuilder = new CommandBuilder(RealMetadataFactory.exampleBQTCached());
+        commandBuilder.getLanguageBridgeFactory().setSupportsConcat2(true);
+        Command obj = commandBuilder.getCommand(input, true, true);
+        TranslationHelper.helpTestVisitor(output, TRANSLATOR, obj);
     }
 
     @Test public void testConcat2() throws Exception {        
         String input = "select concat2(stringnum, stringkey) from bqt1.Smalla"; //$NON-NLS-1$
-        String output = "SELECT CASE WHEN SmallA.StringNum IS NULL AND SmallA.StringKey IS NULL THEN NULL ELSE concat(nvl(SmallA.StringNum, ''), nvl(SmallA.StringKey, '')) END FROM SmallA"; //$NON-NLS-1$
-        TranslationHelper.helpTestVisitor(TranslationHelper.BQT_VDB, UDF,
-                input, output, 
-                TRANSLATOR);
+        String output = "SELECT (g_0.StringNum || g_0.StringKey) FROM SmallA g_0"; //$NON-NLS-1$
+        
+        CommandBuilder commandBuilder = new CommandBuilder(RealMetadataFactory.exampleBQTCached());
+        commandBuilder.getLanguageBridgeFactory().setSupportsConcat2(true);
+        Command obj = commandBuilder.getCommand(input, true, true);
+        TranslationHelper.helpTestVisitor(output, TRANSLATOR, obj);
     }
     
     /**

Modified: trunk/engine/src/main/java/org/teiid/dqp/internal/datamgr/ConnectorWorkItem.java
===================================================================
--- trunk/engine/src/main/java/org/teiid/dqp/internal/datamgr/ConnectorWorkItem.java	2012-09-14 16:04:37 UTC (rev 4446)
+++ trunk/engine/src/main/java/org/teiid/dqp/internal/datamgr/ConnectorWorkItem.java	2012-09-14 17:19:05 UTC (rev 4447)
@@ -30,6 +30,7 @@
 
 import org.teiid.adminapi.impl.VDBMetaData;
 import org.teiid.client.ResizingArrayList;
+import org.teiid.core.TeiidComponentException;
 import org.teiid.core.TeiidProcessingException;
 import org.teiid.core.util.Assertion;
 import org.teiid.dqp.internal.process.RequestWorkItem;
@@ -48,15 +49,7 @@
 import org.teiid.query.sql.lang.QueryCommand;
 import org.teiid.query.sql.lang.StoredProcedure;
 import org.teiid.resource.spi.WrappedConnection;
-import org.teiid.translator.CacheDirective;
-import org.teiid.translator.DataNotAvailableException;
-import org.teiid.translator.Execution;
-import org.teiid.translator.ExecutionFactory;
-import org.teiid.translator.ProcedureExecution;
-import org.teiid.translator.ResultSetExecution;
-import org.teiid.translator.ReusableExecution;
-import org.teiid.translator.TranslatorException;
-import org.teiid.translator.UpdateExecution;
+import org.teiid.translator.*;
 
 public class ConnectorWorkItem implements ConnectorWork {
 	
@@ -85,7 +78,7 @@
 	
 	private DataNotAvailableException dnae;
     
-    ConnectorWorkItem(AtomicRequestMessage message, ConnectorManager manager) {
+    ConnectorWorkItem(AtomicRequestMessage message, ConnectorManager manager) throws TeiidComponentException {
         this.id = message.getAtomicRequestID();
         this.requestMsg = message;
         this.manager = manager;
@@ -108,6 +101,7 @@
 		this.securityContext.setTransactional(requestMsg.isTransactional());
         LanguageBridgeFactory factory = new LanguageBridgeFactory(this.queryMetadata);
         factory.setConvertIn(!this.connector.supportsInCriteria());
+        factory.setSupportsConcat2(manager.getCapabilities().supportsFunction(SourceSystemFunctions.CONCAT2));
         translatedCommand = factory.translate(message.getCommand());
     }
     

Modified: trunk/engine/src/main/java/org/teiid/dqp/internal/datamgr/LanguageBridgeFactory.java
===================================================================
--- trunk/engine/src/main/java/org/teiid/dqp/internal/datamgr/LanguageBridgeFactory.java	2012-09-14 16:04:37 UTC (rev 4446)
+++ trunk/engine/src/main/java/org/teiid/dqp/internal/datamgr/LanguageBridgeFactory.java	2012-09-14 17:19:05 UTC (rev 4447)
@@ -46,6 +46,7 @@
 import org.teiid.metadata.ProcedureParameter;
 import org.teiid.metadata.FunctionMethod.PushDown;
 import org.teiid.query.QueryPlugin;
+import org.teiid.query.function.FunctionDescriptor;
 import org.teiid.query.metadata.QueryMetadataInterface;
 import org.teiid.query.sql.lang.*;
 import org.teiid.query.sql.lang.Command;
@@ -63,6 +64,7 @@
 import org.teiid.query.sql.symbol.Function;
 import org.teiid.query.sql.symbol.ScalarSubquery;
 import org.teiid.query.sql.symbol.WindowFunction;
+import org.teiid.translator.SourceSystemFunctions;
 import org.teiid.translator.TranslatorException;
 
 
@@ -135,6 +137,7 @@
     private List<List<?>> allValues = new LinkedList<List<?>>();
     private Map<String, List<? extends List<?>>> dependentSets;
     private boolean convertIn;
+    private boolean supportsConcat2;
 
     public LanguageBridgeFactory(QueryMetadataInterface metadata) {
         if (metadata != null) {
@@ -149,6 +152,10 @@
     public void setConvertIn(boolean convertIn) {
 		this.convertIn = convertIn;
 	}
+    
+    public void setSupportsConcat2(boolean supportsConcat2) {
+		this.supportsConcat2 = supportsConcat2;
+	}
 
     public org.teiid.language.Command translate(Command command) {
     	try {
@@ -619,7 +626,7 @@
         return result;
     }
 
-    org.teiid.language.Function translate(Function function) {
+    org.teiid.language.Expression translate(Function function) {
         Expression [] args = function.getArgs();
         List<org.teiid.language.Expression> params = new ArrayList<org.teiid.language.Expression>(args.length);
         for (int i = 0; i < args.length; i++) {
@@ -628,6 +635,43 @@
         String name = function.getName();
         if (function.getFunctionDescriptor() != null) {
         	name = function.getFunctionDescriptor().getName();
+        	if (!supportsConcat2 && function.getFunctionDescriptor().getMethod().getParent() == null && name.equalsIgnoreCase(SourceSystemFunctions.CONCAT2)) {
+				Expression[] newArgs = new Expression[args.length];
+
+				boolean useCase = true;
+				for(int i=0; i<args.length; i++) {
+					if (args[i] instanceof Constant) {
+						newArgs[i] = args[i];
+						useCase = false;
+					} else {
+						Function f = new Function(SourceSystemFunctions.IFNULL, new Expression[] {args[i], new Constant("")}); //$NON-NLS-1$
+						newArgs[i] = f;
+						f.setType(args[i].getType());
+				        FunctionDescriptor descriptor = 
+				        	metadataFactory.getMetadata().getFunctionLibrary().findFunction(SourceSystemFunctions.IFNULL, new Class[] { args[i].getType(), DataTypeManager.DefaultDataClasses.STRING });
+				        f.setFunctionDescriptor(descriptor);
+					} 
+				}
+				
+				Function concat = new Function(SourceSystemFunctions.CONCAT, newArgs);
+				concat.setType(DataTypeManager.DefaultDataClasses.STRING);
+				
+				if (!useCase) {
+					return translate(concat);
+				}
+				
+				FunctionDescriptor descriptor = 
+					metadataFactory.getMetadata().getFunctionLibrary().findFunction(SourceSystemFunctions.CONCAT, new Class[] { DataTypeManager.DefaultDataClasses.STRING, DataTypeManager.DefaultDataClasses.STRING });
+				concat.setFunctionDescriptor(descriptor);
+				
+				List<CompoundCriteria> when = Arrays.asList(new CompoundCriteria(CompoundCriteria.AND, new IsNullCriteria(args[0]), new IsNullCriteria(args[1])));
+				Constant nullConstant = new Constant(null, DataTypeManager.DefaultDataClasses.STRING);
+				List<Constant> then = Arrays.asList(nullConstant);
+				SearchedCaseExpression caseExpr = new SearchedCaseExpression(when, then);
+				caseExpr.setElseExpression(concat);
+				caseExpr.setType(DataTypeManager.DefaultDataClasses.STRING);
+				return translate(caseExpr);
+        	}
         	//check for translator pushdown functions, and use the name in source if possible
         	if (function.getFunctionDescriptor().getPushdown() == PushDown.MUST_PUSHDOWN 
         			&& function.getFunctionDescriptor().getSchema().equalsIgnoreCase(CoreConstants.SYSTEM_MODEL)

Modified: trunk/engine/src/main/java/org/teiid/query/function/FunctionMethods.java
===================================================================
--- trunk/engine/src/main/java/org/teiid/query/function/FunctionMethods.java	2012-09-14 16:04:37 UTC (rev 4446)
+++ trunk/engine/src/main/java/org/teiid/query/function/FunctionMethods.java	2012-09-14 17:19:05 UTC (rev 4447)
@@ -620,14 +620,27 @@
 	// ================== Function = length =====================
 
 	public static Object length(String str) {
-		return new Integer(str.length());
+		return str.length();
 	}
 
 	// ================== Function = concat =====================
 
-	public static Object concat(String str1, String str2) {
+	public static String concat(String str1, String str2) {
 		return str1 + str2;
 	}
+	
+	public static String concat2(String str1, String str2) {
+		if (str1 == null) {
+			if (str2 == null) {
+				return null;
+			}
+			return str2;
+		}
+		if (str2 == null) {
+			return str1;
+		}
+		return str1 + str2;
+	}
 
 	// ================== Function = substring =====================
 

Modified: trunk/engine/src/main/java/org/teiid/query/function/source/SystemSource.java
===================================================================
--- trunk/engine/src/main/java/org/teiid/query/function/source/SystemSource.java	2012-09-14 16:04:37 UTC (rev 4446)
+++ trunk/engine/src/main/java/org/teiid/query/function/source/SystemSource.java	2012-09-14 17:19:05 UTC (rev 4447)
@@ -540,11 +540,12 @@
                     new FunctionParameter("string2", DataTypeManager.DefaultDataTypes.STRING, QueryPlugin.Util.getString("SystemSource.Concatop_arg2")) }, //$NON-NLS-1$ //$NON-NLS-2$
                 new FunctionParameter("result", DataTypeManager.DefaultDataTypes.STRING, QueryPlugin.Util.getString("SystemSource.Concatop_result_desc")) ) );                 //$NON-NLS-1$ //$NON-NLS-2$
         
-        FunctionMethod concat2 = new FunctionMethod("concat2", QueryPlugin.Util.getString("SystemSource.Concat_desc"), STRING, PushDown.SYNTHETIC, null, null, //$NON-NLS-1$ //$NON-NLS-2$ 
-                           Arrays.asList(
-                               new FunctionParameter("string1", DataTypeManager.DefaultDataTypes.STRING, QueryPlugin.Util.getString("SystemSource.Concat_arg1")), //$NON-NLS-1$ //$NON-NLS-2$
-                               new FunctionParameter("string2", DataTypeManager.DefaultDataTypes.STRING, QueryPlugin.Util.getString("SystemSource.Concat_arg2")) ), //$NON-NLS-1$ //$NON-NLS-2$
-                           new FunctionParameter("result", DataTypeManager.DefaultDataTypes.STRING, QueryPlugin.Util.getString("SystemSource.Concat_result_desc")), false, Determinism.DETERMINISTIC ); //$NON-NLS-1$ //$NON-NLS-2$
+        FunctionMethod concat2 = new FunctionMethod(SourceSystemFunctions.CONCAT2, QueryPlugin.Util.getString("SystemSource.Concat_desc"), STRING, FUNCTION_CLASS, "concat2", //$NON-NLS-1$ //$NON-NLS-2$ 
+                new FunctionParameter[] {
+            		new FunctionParameter("string1", DataTypeManager.DefaultDataTypes.STRING, QueryPlugin.Util.getString("SystemSource.Concat_arg1")), //$NON-NLS-1$ //$NON-NLS-2$
+            		new FunctionParameter("string2", DataTypeManager.DefaultDataTypes.STRING, QueryPlugin.Util.getString("SystemSource.Concat_arg2")) }, //$NON-NLS-1$ //$NON-NLS-2$
+            	new FunctionParameter("result", DataTypeManager.DefaultDataTypes.STRING, QueryPlugin.Util.getString("SystemSource.Concat_result_desc")) );                 //$NON-NLS-1$ //$NON-NLS-2$
+        concat2.setNullOnNull(false);
         functions.add(concat2);                         
     }
 

Modified: trunk/engine/src/main/java/org/teiid/query/optimizer/relational/rules/CapabilitiesUtil.java
===================================================================
--- trunk/engine/src/main/java/org/teiid/query/optimizer/relational/rules/CapabilitiesUtil.java	2012-09-14 16:04:37 UTC (rev 4446)
+++ trunk/engine/src/main/java/org/teiid/query/optimizer/relational/rules/CapabilitiesUtil.java	2012-09-14 17:19:05 UTC (rev 4447)
@@ -48,6 +48,7 @@
 import org.teiid.query.sql.symbol.Function;
 import org.teiid.query.sql.symbol.AggregateSymbol.Type;
 import org.teiid.query.sql.visitor.ElementCollectorVisitor;
+import org.teiid.translator.SourceSystemFunctions;
 import org.teiid.translator.ExecutionFactory.NullOrder;
 import org.teiid.translator.ExecutionFactory.SupportedJoinCriteria;
 
@@ -231,10 +232,16 @@
         //technically the other functions are scoped to SYS or their function model, but that's 
         //not formally part of their metadata yet
         Schema schema = function.getFunctionDescriptor().getMethod().getParent();
+        String fullName = function.getFunctionDescriptor().getMethod().getFullName();
         if (schema == null || !schema.isPhysical()) {
             // Find capabilities
-            if (!caps.supportsFunction(function.getFunctionDescriptor().getMethod().getFullName())) {
-                return false;
+        	
+            if (!caps.supportsFunction(fullName)) {
+            	//special handling for delayed rewrite of concat2
+            	return (schema == null && SourceSystemFunctions.CONCAT2.equalsIgnoreCase(fullName)
+                		&& caps.supportsFunction(SourceSystemFunctions.CONCAT) 
+                		&& caps.supportsFunction(SourceSystemFunctions.IFNULL)
+                		&& caps.supportsCapability(Capability.QUERY_SEARCHED_CASE));
             }
             if (FunctionLibrary.isConvert(function)) {
                 Class<?> fromType = function.getArg(0).getType();
@@ -245,7 +252,7 @@
                 return caps.supportsConvert(DataTypeManager.getTypeCode(fromType), DataTypeManager.getTypeCode(targetType));
             }
         } else if (!isSameConnector(modelID, schema, metadata, capFinder)) {
-        	return caps.supportsFunction(function.getFunctionDescriptor().getMethod().getFullName());
+        	return caps.supportsFunction(fullName);
         }
         
         return true;

Modified: trunk/engine/src/main/java/org/teiid/query/rewriter/QueryRewriter.java
===================================================================
--- trunk/engine/src/main/java/org/teiid/query/rewriter/QueryRewriter.java	2012-09-14 16:04:37 UTC (rev 4446)
+++ trunk/engine/src/main/java/org/teiid/query/rewriter/QueryRewriter.java	2012-09-14 17:19:05 UTC (rev 4447)
@@ -2097,6 +2097,7 @@
             }
         }
 		
+		boolean omitNull = false;
 		Integer code = FUNCTION_MAP.get(functionName);
 		if (code != null) {
 			switch (code) {
@@ -2145,33 +2146,9 @@
 				}
 				break;
 			}
-			case 4: { //rewrite concat2 - CONCAT2(a, b) ==> CASE WHEN (a is NULL AND b is NULL) THEN NULL ELSE CONCAT( NVL(a, ''), NVL(b, '') )
-				Expression[] args = function.getArgs();
-				Function[] newArgs = new Function[args.length];
-
-				for(int i=0; i<args.length; i++) {
-					newArgs[i] = new Function(SourceSystemFunctions.IFNULL, new Expression[] {args[i], new Constant("")}); //$NON-NLS-1$
-					newArgs[i].setType(args[i].getType());
-					Assertion.assertTrue(args[i].getType() == DataTypeManager.DefaultDataClasses.STRING);
-			        FunctionDescriptor descriptor = 
-			        	funcLibrary.findFunction(SourceSystemFunctions.IFNULL, new Class[] { args[i].getType(), DataTypeManager.DefaultDataClasses.STRING });
-			        newArgs[i].setFunctionDescriptor(descriptor);
-				}
-				
-				Function concat = new Function(SourceSystemFunctions.CONCAT, newArgs);
-				concat.setType(DataTypeManager.DefaultDataClasses.STRING);
-				FunctionDescriptor descriptor = 
-					funcLibrary.findFunction(SourceSystemFunctions.CONCAT, new Class[] { DataTypeManager.DefaultDataClasses.STRING, DataTypeManager.DefaultDataClasses.STRING });
-				concat.setFunctionDescriptor(descriptor);
-				
-				List when = Arrays.asList(new Criteria[] {new CompoundCriteria(CompoundCriteria.AND, new IsNullCriteria(args[0]), new IsNullCriteria(args[1]))});
-				Constant nullConstant = new Constant(null, DataTypeManager.DefaultDataClasses.STRING);
-				List then = Arrays.asList(new Expression[] {nullConstant});
-				SearchedCaseExpression caseExpr = new SearchedCaseExpression(when, then);
-				caseExpr.setElseExpression(concat);
-				caseExpr.setType(DataTypeManager.DefaultDataClasses.STRING);
-				return rewriteExpressionDirect(caseExpr);
-			}
+			case 4:
+				omitNull = true;
+				break;
 			case 5: {
 				if (function.getType() != DataTypeManager.DefaultDataClasses.TIMESTAMP) {
 					FunctionDescriptor descriptor = 
@@ -2229,14 +2206,32 @@
 						
 		Expression[] args = function.getArgs();
 		Expression[] newArgs = new Expression[args.length];
-		        
+		    
         // Rewrite args
+		int j = 0;
 		for(int i=0; i<args.length; i++) {
-			newArgs[i] = rewriteExpressionDirect(args[i]);
-            if (isNull(newArgs[i]) && !function.getFunctionDescriptor().isNullDependent()) {
-                return new Constant(null, function.getType());
+			Expression ex = rewriteExpressionDirect(args[i]);
+            if (isNull(ex)) {
+            	if (!function.getFunctionDescriptor().isNullDependent()) {
+            		return new Constant(null, function.getType());
+            	}
+            	if (omitNull) {
+            		continue;
+            	}
             }
+        	newArgs[j++] = ex;
         }
+		if (omitNull) {
+			if (j==0) {
+				return new Constant(null, function.getType());
+			}
+			if (j==1) {
+				return newArgs[0];
+			}
+			if (j!=args.length) {
+				newArgs = Arrays.copyOf(newArgs, j);
+			}
+		}
         function.setArgs(newArgs);
 
         if( FunctionLibrary.isConvert(function)) {

Modified: trunk/engine/src/test/java/org/teiid/cdk/CommandBuilder.java
===================================================================
--- trunk/engine/src/test/java/org/teiid/cdk/CommandBuilder.java	2012-09-14 16:04:37 UTC (rev 4446)
+++ trunk/engine/src/test/java/org/teiid/cdk/CommandBuilder.java	2012-09-14 17:19:05 UTC (rev 4447)
@@ -52,14 +52,20 @@
 	}
 
     private QueryMetadataInterface metadata;
+	private LanguageBridgeFactory languageBridgeFactory;
     
     /**
      * @param metadata The metadata describing the datasource which the query is for.
      */
     public CommandBuilder(QueryMetadataInterface metadata) {
         this.metadata = metadata;
+        this.languageBridgeFactory = new LanguageBridgeFactory(metadata);
     }
     
+    public LanguageBridgeFactory getLanguageBridgeFactory() {
+		return languageBridgeFactory;
+	}
+    
     public org.teiid.language.Command getCommand(String queryString) {
         return getCommand(queryString, false, false);
     }
@@ -75,7 +81,7 @@
             	command = (Command)command.clone();
                 command.acceptVisitor(new AliasGenerator(supportsGroupAlias));
             }
-            return new LanguageBridgeFactory(metadata).translate(command);
+			return languageBridgeFactory.translate(command);
         } catch (TeiidException e) {
             throw new TeiidRuntimeException(e);
 		}

Modified: trunk/engine/src/test/java/org/teiid/dqp/internal/datamgr/TestFunctionImpl.java
===================================================================
--- trunk/engine/src/test/java/org/teiid/dqp/internal/datamgr/TestFunctionImpl.java	2012-09-14 16:04:37 UTC (rev 4446)
+++ trunk/engine/src/test/java/org/teiid/dqp/internal/datamgr/TestFunctionImpl.java	2012-09-14 17:19:05 UTC (rev 4447)
@@ -50,7 +50,7 @@
     }
     
     public static Function example(String name) throws Exception {
-        return TstLanguageBridgeFactory.factory.translate(helpExample(name));
+        return (Function) TstLanguageBridgeFactory.factory.translate(helpExample(name));
     }
 
     public void testGetName() throws Exception {

Modified: trunk/engine/src/test/java/org/teiid/query/processor/TestFunctionPushdown.java
===================================================================
--- trunk/engine/src/test/java/org/teiid/query/processor/TestFunctionPushdown.java	2012-09-14 16:04:37 UTC (rev 4446)
+++ trunk/engine/src/test/java/org/teiid/query/processor/TestFunctionPushdown.java	2012-09-14 17:19:05 UTC (rev 4447)
@@ -37,8 +37,10 @@
 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.parser.TestDDLParser;
 import org.teiid.query.unittest.RealMetadataFactory;
+import org.teiid.translator.SourceSystemFunctions;
 
 @SuppressWarnings({"nls", "unchecked"})
 public class TestFunctionPushdown {
@@ -141,6 +143,34 @@
                 new String[] {"SELECT g_0.e1 FROM pm1.g1 AS g_0"}, ComparisonMode.EXACT_COMMAND_STRING); //$NON-NLS-1$         
 	}
 	
+	@Test public void testConcat2() throws Exception {
+		QueryMetadataInterface metadata = RealMetadataFactory.example1Cached();
+		
+        FakeCapabilitiesFinder capFinder = new FakeCapabilitiesFinder();
+        BasicSourceCapabilities caps = TestOptimizer.getTypicalCapabilities();
+        caps.setFunctionSupport(SourceSystemFunctions.CONCAT2, true);
+        capFinder.addCapabilities("pm1", caps); //$NON-NLS-1$
+        
+        String sql = "select concat2(x.e1, x.e1) from pm1.g1 as x"; //$NON-NLS-1$
+        
+        helpPlan(sql, metadata, null, capFinder, 
+                                      new String[] {"SELECT concat2(g_0.e1, g_0.e1) FROM pm1.g1 AS g_0"}, ComparisonMode.EXACT_COMMAND_STRING); //$NON-NLS-1$ 
+        
+        //cannot pushdown
+        caps.setFunctionSupport(SourceSystemFunctions.CONCAT2, false);
+        
+        helpPlan(sql, metadata, null, capFinder, 
+                new String[] {"SELECT g_0.e1 FROM pm1.g1 AS g_0"}, ComparisonMode.EXACT_COMMAND_STRING); //$NON-NLS-1$
+        
+        caps.setFunctionSupport(SourceSystemFunctions.CONCAT, true);
+        caps.setFunctionSupport(SourceSystemFunctions.IFNULL, true);
+        caps.setCapabilitySupport(Capability.QUERY_SEARCHED_CASE, true);
+        
+        //will get replaced in the LanguageBridgeFactory
+        helpPlan(sql, metadata, null, capFinder, 
+                new String[] {"SELECT concat2(g_0.e1, g_0.e1) FROM pm1.g1 AS g_0"}, ComparisonMode.EXACT_COMMAND_STRING); //$NON-NLS-1$
+	}
+	
 	public static String sourceFunc(String msg) {
 		return msg;
 	}

Modified: trunk/engine/src/test/java/org/teiid/query/rewriter/TestQueryRewriter.java
===================================================================
--- trunk/engine/src/test/java/org/teiid/query/rewriter/TestQueryRewriter.java	2012-09-14 16:04:37 UTC (rev 4446)
+++ trunk/engine/src/test/java/org/teiid/query/rewriter/TestQueryRewriter.java	2012-09-14 17:19:05 UTC (rev 4447)
@@ -1336,15 +1336,11 @@
     }
 
     @Test public void testRewriteConcat2_2() throws Exception {
-        helpTestRewriteCriteria("concat2(pm1.g1.e1, null) = 'xyz'", "CASE WHEN pm1.g1.e1 IS NULL THEN null ELSE concat(ifnull(pm1.g1.e1, ''), '') END = 'xyz'", true); //$NON-NLS-1$ //$NON-NLS-2$
+        helpTestRewriteCriteria("concat2(pm1.g1.e1, null) = 'xyz'", "pm1.g1.e1 = 'xyz'", true); //$NON-NLS-1$ //$NON-NLS-2$
     }
 
-    @Test public void testRewriteConcat2_3() throws Exception {
-        helpTestRewriteCriteria("concat2(pm1.g1.e1, convert(pm1.g1.e2, string)) = 'xyz'", "CASE WHEN (pm1.g1.e1 IS NULL) AND (convert(pm1.g1.e2, string) IS NULL) THEN null ELSE concat(ifnull(pm1.g1.e1, ''), ifnull(convert(pm1.g1.e2, string), '')) END = 'xyz'", true); //$NON-NLS-1$ //$NON-NLS-2$
-    }
-
     @Test public void testRewriteConcat2_4() throws Exception {
-        helpTestRewriteCriteria("concat2('a', pm1.g1.e1) = 'xyz'", "concat('a', ifnull(pm1.g1.e1, '')) = 'xyz'"); //$NON-NLS-1$ //$NON-NLS-2$
+        helpTestRewriteCriteria("concat2('a', pm1.g1.e1) = 'xyz'", "concat2('a', pm1.g1.e1) = 'xyz'"); //$NON-NLS-1$ //$NON-NLS-2$
     }
     
     @Test public void testRewriteFromUnixTime() throws Exception {



More information about the teiid-commits mailing list