[teiid-commits] teiid SVN: r1189 - in trunk/connectors/connector-jdbc/src: main/java/org/teiid/connector/jdbc/derby and 9 other directories.

teiid-commits at lists.jboss.org teiid-commits at lists.jboss.org
Sun Jul 26 12:53:56 EDT 2009


Author: shawkins
Date: 2009-07-26 12:53:56 -0400 (Sun, 26 Jul 2009)
New Revision: 1189

Added:
   trunk/connectors/connector-jdbc/src/main/java/org/teiid/connector/jdbc/translator/MODFunctionModifier.java
   trunk/connectors/connector-jdbc/src/test/java/org/teiid/connector/jdbc/derby/TestDerbyCapabilities.java
   trunk/connectors/connector-jdbc/src/test/java/org/teiid/connector/jdbc/translator/TestMODFunctionModifier.java
Modified:
   trunk/connectors/connector-jdbc/src/main/java/org/teiid/connector/jdbc/db2/DB2Capabilities.java
   trunk/connectors/connector-jdbc/src/main/java/org/teiid/connector/jdbc/db2/DB2ConvertModifier.java
   trunk/connectors/connector-jdbc/src/main/java/org/teiid/connector/jdbc/db2/DB2SQLTranslator.java
   trunk/connectors/connector-jdbc/src/main/java/org/teiid/connector/jdbc/derby/DerbyCapabilities.java
   trunk/connectors/connector-jdbc/src/main/java/org/teiid/connector/jdbc/derby/DerbyConvertModifier.java
   trunk/connectors/connector-jdbc/src/main/java/org/teiid/connector/jdbc/derby/DerbySQLTranslator.java
   trunk/connectors/connector-jdbc/src/main/java/org/teiid/connector/jdbc/oracle/ConcatFunctionModifier.java
   trunk/connectors/connector-jdbc/src/main/java/org/teiid/connector/jdbc/postgresql/PostgreSQLCapabilities.java
   trunk/connectors/connector-jdbc/src/main/java/org/teiid/connector/jdbc/postgresql/PostgreSQLTranslator.java
   trunk/connectors/connector-jdbc/src/main/java/org/teiid/connector/jdbc/sqlserver/SqlServerCapabilities.java
   trunk/connectors/connector-jdbc/src/main/resources/connector-jdbc.xml
   trunk/connectors/connector-jdbc/src/test/java/org/teiid/connector/jdbc/db2/TestDB2SqlTranslator.java
   trunk/connectors/connector-jdbc/src/test/java/org/teiid/connector/jdbc/oracle/TestLeftOrRightFunctionModifier.java
Log:
TEIID-710 TEIID-486 TEIID-739 consolidating db2 and derby connector code, also adding Larry's fix for selected null literals and mod function handling

Modified: trunk/connectors/connector-jdbc/src/main/java/org/teiid/connector/jdbc/db2/DB2Capabilities.java
===================================================================
--- trunk/connectors/connector-jdbc/src/main/java/org/teiid/connector/jdbc/db2/DB2Capabilities.java	2009-07-25 20:58:40 UTC (rev 1188)
+++ trunk/connectors/connector-jdbc/src/main/java/org/teiid/connector/jdbc/db2/DB2Capabilities.java	2009-07-26 16:53:56 UTC (rev 1189)
@@ -40,8 +40,8 @@
     /**
      * @see com.metamatrix.data.ConnectorCapabilities#getSupportedFunctions()
      */
-    public List getSupportedFunctions() {
-        List supportedFunctions = new ArrayList();
+    public List<String> getSupportedFunctions() {
+        List<String> supportedFunctions = new ArrayList<String>();
         supportedFunctions.addAll(super.getSupportedFunctions());
         supportedFunctions.add("ABS"); //$NON-NLS-1$
         supportedFunctions.add("ACOS"); //$NON-NLS-1$

Modified: trunk/connectors/connector-jdbc/src/main/java/org/teiid/connector/jdbc/db2/DB2ConvertModifier.java
===================================================================
--- trunk/connectors/connector-jdbc/src/main/java/org/teiid/connector/jdbc/db2/DB2ConvertModifier.java	2009-07-25 20:58:40 UTC (rev 1188)
+++ trunk/connectors/connector-jdbc/src/main/java/org/teiid/connector/jdbc/db2/DB2ConvertModifier.java	2009-07-26 16:53:56 UTC (rev 1189)
@@ -29,14 +29,17 @@
 import org.teiid.connector.api.TypeFacility;
 import org.teiid.connector.jdbc.translator.BasicFunctionModifier;
 import org.teiid.connector.jdbc.translator.DropFunctionModifier;
-import org.teiid.connector.jdbc.translator.FunctionModifier;
-import org.teiid.connector.language.*;
+import org.teiid.connector.language.ICompareCriteria;
+import org.teiid.connector.language.IExpression;
+import org.teiid.connector.language.IFunction;
+import org.teiid.connector.language.ILanguageFactory;
+import org.teiid.connector.language.ILiteral;
 import org.teiid.connector.language.ICompareCriteria.Operator;
 
 
 /**
  */
-public class DB2ConvertModifier extends BasicFunctionModifier implements FunctionModifier {
+public class DB2ConvertModifier extends BasicFunctionModifier {
 
     private static DropFunctionModifier DROP_MODIFIER = new DropFunctionModifier();
 
@@ -227,7 +230,7 @@
         return null;
     }
 
-    private IExpression convertToReal(IExpression expression, Class sourceType) {
+    protected IExpression convertToReal(IExpression expression, Class sourceType) {
         
         if(sourceType.equals(TypeFacility.RUNTIME_TYPES.STRING) ||
                         sourceType.equals(TypeFacility.RUNTIME_TYPES.DOUBLE) || 
@@ -243,7 +246,7 @@
         return null;
     }
 
-    private IExpression convertToDouble(IExpression expression, Class sourceType) {
+    protected IExpression convertToDouble(IExpression expression, Class sourceType) {
         
         if(sourceType.equals(TypeFacility.RUNTIME_TYPES.STRING)){
 
@@ -257,7 +260,7 @@
         return null;
     }
 
-    private IExpression convertToBigDecimal(IExpression expression, Class sourceType) {
+    protected IExpression convertToBigDecimal(IExpression expression, Class sourceType) {
         
         if(sourceType.equals(TypeFacility.RUNTIME_TYPES.STRING)){
 

Modified: trunk/connectors/connector-jdbc/src/main/java/org/teiid/connector/jdbc/db2/DB2SQLTranslator.java
===================================================================
--- trunk/connectors/connector-jdbc/src/main/java/org/teiid/connector/jdbc/db2/DB2SQLTranslator.java	2009-07-25 20:58:40 UTC (rev 1188)
+++ trunk/connectors/connector-jdbc/src/main/java/org/teiid/connector/jdbc/db2/DB2SQLTranslator.java	2009-07-26 16:53:56 UTC (rev 1189)
@@ -22,6 +22,7 @@
 
 package org.teiid.connector.jdbc.db2;
 
+import java.util.ArrayList;
 import java.util.Arrays;
 import java.util.List;
 
@@ -31,13 +32,18 @@
 import org.teiid.connector.api.ExecutionContext;
 import org.teiid.connector.api.SourceSystemFunctions;
 import org.teiid.connector.api.TypeFacility;
+import org.teiid.connector.api.TypeFacility.RUNTIME_TYPES;
 import org.teiid.connector.jdbc.translator.AliasModifier;
+import org.teiid.connector.jdbc.translator.MODFunctionModifier;
 import org.teiid.connector.jdbc.translator.Translator;
 import org.teiid.connector.language.ICommand;
+import org.teiid.connector.language.IExpression;
 import org.teiid.connector.language.IJoin;
 import org.teiid.connector.language.ILimit;
 import org.teiid.connector.language.ILiteral;
 import org.teiid.connector.language.IQuery;
+import org.teiid.connector.language.ISelect;
+import org.teiid.connector.language.ISelectSymbol;
 import org.teiid.connector.language.ICompareCriteria.Operator;
 import org.teiid.connector.language.IJoin.JoinType;
 import org.teiid.connector.visitor.framework.HierarchyVisitor;
@@ -55,6 +61,12 @@
         registerFunctionModifier(SourceSystemFunctions.DAYOFMONTH, new AliasModifier("day")); //$NON-NLS-1$ 
         registerFunctionModifier(SourceSystemFunctions.IFNULL, new AliasModifier("coalesce")); //$NON-NLS-1$ 
         registerFunctionModifier(SourceSystemFunctions.SUBSTRING, new AliasModifier("substr")); //$NON-NLS-1$ 
+
+        List<Class<?>> supportedModTypes = new ArrayList<Class<?>>(3);
+        supportedModTypes.add(RUNTIME_TYPES.SHORT);
+        supportedModTypes.add(RUNTIME_TYPES.INTEGER);
+        supportedModTypes.add(RUNTIME_TYPES.LONG);
+        registerFunctionModifier(SourceSystemFunctions.MOD, new MODFunctionModifier(getLanguageFactory(), "MOD", supportedModTypes));  //$NON-NLS-1$
     }
 		
 	@SuppressWarnings("unchecked")
@@ -79,6 +91,16 @@
 			};
 			
 			command.acceptVisitor(hierarchyVisitor);
+			
+			ISelect select = ((IQuery)command).getSelect();
+			for (ISelectSymbol selectSymbol : select.getSelectSymbols()) {
+				if (selectSymbol.getExpression() instanceof ILiteral) {
+					ILiteral literal = (ILiteral)selectSymbol.getExpression();
+					if (literal.getValue() == null) {
+						selectSymbol.setExpression(createCastToExprType(literal));
+					}
+				}
+			}
 		}
 		return command;
 	}
@@ -92,5 +114,67 @@
 	public Class<? extends ConnectorCapabilities> getDefaultCapabilities() {
 		return DB2Capabilities.class;
 	}
-    
+    
+	/**
+	 * Create and return an expression to cast <code>expr</code> to <code>expr</code>'s
+	 * type.
+	 * <p>  
+	 * If a compatible type is not found, <code>expr</code> is returned unmodified.
+	 * <p>
+	 * <em>WARNING</em>: This method currently returns the smallest type associated with 
+	 * the run-time type. So, all <code>String</code> expressions, regardless of
+	 * their value's length are returned as CHAR.
+	 * <p>
+	 * For example, if <code>expr</code> is "e1" of type <code>String</code> the 
+	 * returned expression would be "CAST(expr AS CHAR)".
+	 *  
+	 * @param expr
+	 * @return
+	 */
+	private IExpression createCastToExprType(IExpression expr) {
+		String typeName = null;
+		if ( RUNTIME_TYPES.STRING.equals(expr.getType()) ) {
+			typeName = "CHAR"; //$NON-NLS-1$
+		} else if ( RUNTIME_TYPES.BOOLEAN.equals(expr.getType()) ) {
+			typeName = "SMALLINT"; //$NON-NLS-1$
+		} else if ( RUNTIME_TYPES.BYTE.equals(expr.getType()) ) {
+			typeName = "SMALLINT"; //$NON-NLS-1$
+		} else if ( RUNTIME_TYPES.SHORT.equals(expr.getType()) ) {
+			typeName = "SMALLINT"; //$NON-NLS-1$
+		} else if ( RUNTIME_TYPES.CHAR.equals(expr.getType()) ) {
+			typeName = "CHAR"; //$NON-NLS-1$
+		} else if ( RUNTIME_TYPES.INTEGER.equals(expr.getType()) ) {
+			typeName = "INTEGER"; //$NON-NLS-1$
+		} else if ( RUNTIME_TYPES.LONG.equals(expr.getType()) ) {
+			typeName = "BIGINT"; //$NON-NLS-1$
+		} else if ( RUNTIME_TYPES.BIG_INTEGER.equals(expr.getType()) ) {
+			typeName = "BIGINT"; //$NON-NLS-1$
+		} else if ( RUNTIME_TYPES.FLOAT.equals(expr.getType()) ) {
+			typeName = "REAL"; //$NON-NLS-1$
+		} else if ( RUNTIME_TYPES.DOUBLE.equals(expr.getType()) ) {
+			typeName = "DOUBLE"; //$NON-NLS-1$
+		} else if ( RUNTIME_TYPES.BIG_DECIMAL.equals(expr.getType()) ) {
+			typeName = "DECIMAL"; //$NON-NLS-1$
+		} else if ( RUNTIME_TYPES.DATE.equals(expr.getType()) ) {
+			typeName = "DATE"; //$NON-NLS-1$
+		} else if ( RUNTIME_TYPES.TIME.equals(expr.getType()) ) {
+			typeName = "TIME"; //$NON-NLS-1$
+		} else if ( RUNTIME_TYPES.TIMESTAMP.equals(expr.getType()) ) {
+			typeName = "TIMESTAMP"; //$NON-NLS-1$
+		} else if ( RUNTIME_TYPES.OBJECT.equals(expr.getType()) ) {
+			typeName = "BLOB"; //$NON-NLS-1$
+		} else if ( RUNTIME_TYPES.BLOB.equals(expr.getType()) ) {
+			typeName = "BLOB"; //$NON-NLS-1$
+		} else if ( RUNTIME_TYPES.CLOB.equals(expr.getType()) ) {
+			typeName = "CLOB"; //$NON-NLS-1$
+		} else if ( RUNTIME_TYPES.XML.equals(expr.getType()) ) {
+			typeName = "CLOB"; //$NON-NLS-1$
+		}	
+		if ( typeName != null ) {
+			return getLanguageFactory().createFunction("CAST", Arrays.asList(expr, getLanguageFactory().createLiteral(typeName, String.class)), expr.getType()); //$NON-NLS-1$
+		}
+		return expr;
+	}
+
+	
 }

Modified: trunk/connectors/connector-jdbc/src/main/java/org/teiid/connector/jdbc/derby/DerbyCapabilities.java
===================================================================
--- trunk/connectors/connector-jdbc/src/main/java/org/teiid/connector/jdbc/derby/DerbyCapabilities.java	2009-07-25 20:58:40 UTC (rev 1188)
+++ trunk/connectors/connector-jdbc/src/main/java/org/teiid/connector/jdbc/derby/DerbyCapabilities.java	2009-07-26 16:53:56 UTC (rev 1189)
@@ -32,51 +32,64 @@
 /** 
  * @since 5.0
  */
-public class DerbyCapabilities extends JDBCCapabilities {
+public class DerbyCapabilities extends JDBCCapabilities {
+	
+	public static final String TEN_1 = "10.1"; //$NON-NLS-1$
+	public static final String TEN_2 = "10.2"; //$NON-NLS-1$
+	public static final String TEN_4 = "10.4"; //$NON-NLS-1$
+	public static final String TEN_5 = "10.5"; //$NON-NLS-1$
+	
+	private String version = TEN_1;
 
-    public List getSupportedFunctions() {
-        List supportedFunctions = new ArrayList();
+    public List<String> getSupportedFunctions() {
+        List<String> supportedFunctions = new ArrayList<String>();
         supportedFunctions.addAll(super.getSupportedFunctions());
 
-        supportedFunctions.add("ABS"); //$NON-NLS-1$
-        //supportedFunctions.add("ACOS"); //$NON-NLS-1$
-        //supportedFunctions.add("ASIN"); //$NON-NLS-1$
-        //supportedFunctions.add("ATAN"); //$NON-NLS-1$
-        //supportedFunctions.add("ATAN2"); //$NON-NLS-1$
+        supportedFunctions.add("ABS"); //$NON-NLS-1$
+        if (version.compareTo(TEN_2) >= 0) {
+        	supportedFunctions.add("ACOS"); //$NON-NLS-1$
+        	supportedFunctions.add("ASIN"); //$NON-NLS-1$
+        	supportedFunctions.add("ATAN"); //$NON-NLS-1$
+        }
+        if (version.compareTo(TEN_4) >= 0) {
+        	supportedFunctions.add("ATAN2"); //$NON-NLS-1$
+        }
         // These are executed within the server and never pushed down
         //supportedFunctions.add("BITAND"); //$NON-NLS-1$
         //supportedFunctions.add("BITNOT"); //$NON-NLS-1$
         //supportedFunctions.add("BITOR"); //$NON-NLS-1$
-        //supportedFunctions.add("BITXOR"); //$NON-NLS-1$
-        //supportedFunctions.add("CEILING"); //$NON-NLS-1$
-        //supportedFunctions.add("COS"); //$NON-NLS-1$
-        //supportedFunctions.add("COT"); //$NON-NLS-1$
-        //supportedFunctions.add("DEGREES"); //$NON-NLS-1$
-        //supportedFunctions.add("EXP"); //$NON-NLS-1$
-        //supportedFunctions.add("FLOOR"); //$NON-NLS-1$
-        //supportedFunctions.add("LOG"); //$NON-NLS-1$
-        //supportedFunctions.add("LOG10"); //$NON-NLS-1$
-        supportedFunctions.add("MOD"); //$NON-NLS-1$
-        //supportedFunctions.add("PI"); //$NON-NLS-1$
-        //supportedFunctions.add("POWER"); //$NON-NLS-1$
-        //supportedFunctions.add("RADIANS"); //$NON-NLS-1$
-        //supportedFunctions.add("ROUND"); //$NON-NLS-1$
-        //supportedFunctions.add("SIGN"); //$NON-NLS-1$
-        //supportedFunctions.add("SIN"); //$NON-NLS-1$
+        //supportedFunctions.add("BITXOR"); //$NON-NLS-1$
+        if (version.compareTo(TEN_2) >= 0) {
+	        supportedFunctions.add("CEILING"); //$NON-NLS-1$
+	        supportedFunctions.add("COS"); //$NON-NLS-1$
+	        supportedFunctions.add("COT"); //$NON-NLS-1$
+	        supportedFunctions.add("DEGREES"); //$NON-NLS-1$
+	        supportedFunctions.add("EXP"); //$NON-NLS-1$
+	        supportedFunctions.add("FLOOR"); //$NON-NLS-1$
+	        supportedFunctions.add("LOG"); //$NON-NLS-1$
+	        supportedFunctions.add("LOG10"); //$NON-NLS-1$
+        }
+        supportedFunctions.add("MOD"); //$NON-NLS-1$
+        if (version.compareTo(TEN_2) >= 0) {
+        	supportedFunctions.add("PI"); //$NON-NLS-1$
+        	//supportedFunctions.add("POWER"); //$NON-NLS-1$
+        	supportedFunctions.add("RADIANS"); //$NON-NLS-1$
+        	//supportedFunctions.add("ROUND"); //$NON-NLS-1$
+        	supportedFunctions.add("SIGN"); //$NON-NLS-1$
+        	supportedFunctions.add("SIN"); //$NON-NLS-1$
+        }
         supportedFunctions.add("SQRT"); //$NON-NLS-1$
         //supportedFunctions.add("TAN"); //$NON-NLS-1$
         
         //supportedFunctions.add("ASCII"); //$NON-NLS-1$
         //supportedFunctions.add("CHR"); //$NON-NLS-1$
         //supportedFunctions.add("CHAR"); //$NON-NLS-1$
-        supportedFunctions.add("||"); //$NON-NLS-1$
         supportedFunctions.add("CONCAT"); //$NON-NLS-1$
         //supportedFunctions.add("INSERT"); //$NON-NLS-1$
         supportedFunctions.add("LCASE"); //$NON-NLS-1$
-        //supportedFunctions.add("LEFT"); //$NON-NLS-1$
+        supportedFunctions.add("LEFT"); //$NON-NLS-1$
         supportedFunctions.add("LENGTH"); //$NON-NLS-1$
         supportedFunctions.add("LOCATE"); //$NON-NLS-1$
-        supportedFunctions.add("LOWER"); //$NON-NLS-1$
         //supportedFunctions.add("LPAD"); //$NON-NLS-1$
         supportedFunctions.add("LTRIM"); //$NON-NLS-1$
         //supportedFunctions.add("REPEAT"); //$NON-NLS-1$
@@ -86,7 +99,6 @@
         supportedFunctions.add("RTRIM"); //$NON-NLS-1$
         supportedFunctions.add("SUBSTRING"); //$NON-NLS-1$
         supportedFunctions.add("UCASE"); //$NON-NLS-1$
-        supportedFunctions.add("UPPER"); //$NON-NLS-1$
         
         // These are executed within the server and never pushed down
         //supportedFunctions.add("CURDATE"); //$NON-NLS-1$
@@ -117,13 +129,15 @@
         //supportedFunctions.add("WEEK"); //$NON-NLS-1$
         supportedFunctions.add("YEAR"); //$NON-NLS-1$
         
-        supportedFunctions.add("CAST"); //$NON-NLS-1$
         supportedFunctions.add("CONVERT"); //$NON-NLS-1$
         supportedFunctions.add("IFNULL"); //$NON-NLS-1$
-        supportedFunctions.add("NVL"); //$NON-NLS-1$
         supportedFunctions.add("COALESCE"); //$NON-NLS-1$
         return supportedFunctions;
-    }
+    }
+    
+    public void setVersion(String version) {
+		this.version = version;
+	}
 
     /**
      * Derby supports only SearchedCaseExpression, not CaseExpression. 
@@ -152,11 +166,6 @@
         return true;
     }
     
-    @Override
-    public boolean supportsSetQueryOrderBy() {
-    	return false;
-    }
-    
     /** 
      * @see org.teiid.connector.basic.BasicConnectorCapabilities#supportsExcept()
      */
@@ -171,6 +180,11 @@
     @Override
     public boolean supportsIntersect() {
         return true;
+    }
+    
+    @Override
+    public boolean supportsRowLimit() {
+    	return this.version.compareTo(TEN_5) >= 0;
     }
 
 }

Modified: trunk/connectors/connector-jdbc/src/main/java/org/teiid/connector/jdbc/derby/DerbyConvertModifier.java
===================================================================
--- trunk/connectors/connector-jdbc/src/main/java/org/teiid/connector/jdbc/derby/DerbyConvertModifier.java	2009-07-25 20:58:40 UTC (rev 1188)
+++ trunk/connectors/connector-jdbc/src/main/java/org/teiid/connector/jdbc/derby/DerbyConvertModifier.java	2009-07-26 16:53:56 UTC (rev 1189)
@@ -22,213 +22,29 @@
 
 package org.teiid.connector.jdbc.derby;
 
-import java.util.ArrayList;
 import java.util.Arrays;
-import java.util.List;
 
 import org.teiid.connector.api.TypeFacility;
-import org.teiid.connector.jdbc.translator.BasicFunctionModifier;
-import org.teiid.connector.jdbc.translator.DropFunctionModifier;
-import org.teiid.connector.jdbc.translator.FunctionModifier;
-import org.teiid.connector.language.*;
-import org.teiid.connector.language.ICompareCriteria.Operator;
+import org.teiid.connector.jdbc.db2.DB2ConvertModifier;
+import org.teiid.connector.language.IExpression;
+import org.teiid.connector.language.IFunction;
+import org.teiid.connector.language.ILanguageFactory;
 
 
 /**
  */
-public class DerbyConvertModifier extends BasicFunctionModifier implements FunctionModifier {
+public class DerbyConvertModifier extends DB2ConvertModifier {
 
-    private static DropFunctionModifier DROP_MODIFIER = new DropFunctionModifier();
-
     private ILanguageFactory langFactory;
     
     public DerbyConvertModifier(ILanguageFactory langFactory) {
+    	super(langFactory);
         this.langFactory = langFactory;
     }
-
-    public IExpression modify(IFunction function) {
-        List<IExpression> args = function.getParameters();
-        Class sourceType = args.get(0).getType();
-        String targetTypeString = getTargetType(args.get(1));
-        Class targetType = TypeFacility.getDataTypeClass(targetTypeString);
-        IExpression returnExpr = null;
-        
-        if(targetType != null) {
-        
-            // targetType is always lower-case due to getTargetType implementation
-            if(targetType.equals(TypeFacility.RUNTIME_TYPES.STRING)) { 
-                returnExpr = convertToString(args.get(0), sourceType);
-                
-            } else if(targetType.equals(TypeFacility.RUNTIME_TYPES.TIMESTAMP)) { 
-                returnExpr = convertToTimestamp(args.get(0), sourceType);
-                
-            } else if(targetType.equals(TypeFacility.RUNTIME_TYPES.DATE)) { 
-                returnExpr = convertToDate(args.get(0), sourceType);
-                
-            } else if(targetType.equals(TypeFacility.RUNTIME_TYPES.TIME)) { 
-                returnExpr = convertToTime(args.get(0), sourceType);
-                
-            } else if(targetType.equals(TypeFacility.RUNTIME_TYPES.BOOLEAN) || 
-                            targetType.equals(TypeFacility.RUNTIME_TYPES.BYTE) || 
-                            targetType.equals(TypeFacility.RUNTIME_TYPES.SHORT)) {  
-                returnExpr = convertToSmallInt(args.get(0), sourceType, targetType);
-                
-            } else if(targetType.equals(TypeFacility.RUNTIME_TYPES.INTEGER)) {  
-                returnExpr = convertToInteger(args.get(0), sourceType);
-                
-            } else if(targetType.equals(TypeFacility.RUNTIME_TYPES.LONG) || 
-                            targetType.equals(TypeFacility.RUNTIME_TYPES.BIG_INTEGER)) {  
-                returnExpr = convertToBigInt(args.get(0), sourceType);
-                
-            } else if(targetType.equals(TypeFacility.RUNTIME_TYPES.FLOAT)) {  
-                returnExpr = convertToFloat(args.get(0), sourceType);
-
-            } else if(targetType.equals(TypeFacility.RUNTIME_TYPES.DOUBLE)) {  
-                returnExpr = convertToDouble(args.get(0), sourceType);
-
-            } else if(targetType.equals(TypeFacility.RUNTIME_TYPES.BIG_DECIMAL)) {  
-                returnExpr = convertToBigDecimal(args.get(0), sourceType);
-
-            } else if(targetType.equals(TypeFacility.RUNTIME_TYPES.CHAR)) { 
-                returnExpr = convertToChar(args.get(0), sourceType);
-            } 
-            
-            if(returnExpr != null) {
-                return returnExpr;
-            }
-        }
-        
-        // Last resort - just drop the convert and let the db figure it out
-        return DROP_MODIFIER.modify(function);  
-    }
-
-    /** 
-     * @param expression
-     * @return
-     * @since 4.2
-     */
-    private String getTargetType(IExpression expression) {
-        if(expression != null && expression instanceof ILiteral) {
-            String target = (String) ((ILiteral)expression).getValue();
-            return target.toLowerCase();
-        } 
-        
-        return null;            
-    }
     
-
-    /** 
-     * @param expression
-     * @param sourceType
-     * @return
-     * @since 4.2
-     */
-    private IExpression convertToString(IExpression expression,
-                                        Class sourceType) {
-        if(sourceType.equals(TypeFacility.RUNTIME_TYPES.BOOLEAN)) {
-            // BEFORE: convert(booleanExpression, string)
-            // AFTER:  CASE WHEN booleanExpression = 0 THEN 'false' ELSE 'true' END
-
-            ILiteral literalZero = this.langFactory.createLiteral(new Integer(0), TypeFacility.RUNTIME_TYPES.INTEGER);
-            ICompareCriteria when = this.langFactory.createCompareCriteria(Operator.EQ, expression, literalZero);
-            List whens = new ArrayList(1);
-            whens.add(when);
-            
-            ILiteral literalFalse = this.langFactory.createLiteral("false", TypeFacility.RUNTIME_TYPES.STRING); //$NON-NLS-1$
-            List thens = new ArrayList(1);
-            thens.add(literalFalse);
-            
-            ILiteral literalTrue = this.langFactory.createLiteral("true", TypeFacility.RUNTIME_TYPES.STRING); //$NON-NLS-1$
-                        
-            return this.langFactory.createSearchedCaseExpression(whens, thens, literalTrue, TypeFacility.RUNTIME_TYPES.STRING);
-            
-        } else if(sourceType.equals(TypeFacility.RUNTIME_TYPES.CHAR)) {
-            // Drop convert entirely for char
-            return null;
-            
-        } else {
-            // BEFORE: convert(EXPR, string) 
-            // AFTER:  char(EXPR) 
-            return wrapNewFunction(expression, "char", TypeFacility.RUNTIME_TYPES.STRING); //$NON-NLS-1$            
-        }
-    }
-    
-    private IExpression convertToChar(IExpression expression,
-                                        Class sourceType) {
-        if(sourceType.equals(TypeFacility.RUNTIME_TYPES.STRING)) {
-            ILiteral literalOne = this.langFactory.createLiteral(new Integer(1), TypeFacility.RUNTIME_TYPES.INTEGER);
-            return this.langFactory.createFunction("char", Arrays.asList( expression, literalOne ), TypeFacility.RUNTIME_TYPES.CHAR); //$NON-NLS-1$
-        } 
+    @Override
+    protected IExpression convertToReal(IExpression expression, Class sourceType) {
         
-        return null;
-    }
-
-    private IExpression convertToSmallInt(IExpression expression,
-                                        Class sourceType, Class targetType) {
-        
-        if(sourceType.equals(TypeFacility.RUNTIME_TYPES.STRING) && targetType.equals(TypeFacility.RUNTIME_TYPES.BOOLEAN)) { 
-            // BEFORE: convert(stringExpression, boolean)
-            // AFTER:  CASE WHEN stringExpression = 'true' THEN 1 ELSE 0 END
-            ILiteral literalTrue = this.langFactory.createLiteral("true", TypeFacility.RUNTIME_TYPES.STRING); //$NON-NLS-1$
-            ICompareCriteria when = this.langFactory.createCompareCriteria(Operator.EQ, expression, literalTrue);
-            List whens = new ArrayList(1);
-            whens.add(when);
-            
-            ILiteral literalOne = this.langFactory.createLiteral(new Integer(1), TypeFacility.RUNTIME_TYPES.INTEGER);
-            List thens = new ArrayList(1);
-            thens.add(literalOne);
-            
-            ILiteral literalZero = this.langFactory.createLiteral(new Integer(0), TypeFacility.RUNTIME_TYPES.INTEGER);
-                                    
-            return this.langFactory.createSearchedCaseExpression(whens, thens, literalZero, TypeFacility.RUNTIME_TYPES.STRING);
-            
-        } else if(sourceType.equals(TypeFacility.RUNTIME_TYPES.BOOLEAN) || 
-                        sourceType.equals(TypeFacility.RUNTIME_TYPES.BYTE) || 
-                        sourceType.equals(TypeFacility.RUNTIME_TYPES.SHORT)){
-            
-            // Just drop these
-            return null;
-        }
-
-        // BEFORE: convert(expression, [boolean,byte,short])
-        // AFTER:  smallint(expression)
-        return wrapNewFunction(expression, "smallint", targetType); //$NON-NLS-1$
-    }
-
-    private IExpression convertToInteger(IExpression expression, Class sourceType) {
-          
-          if(sourceType.equals(TypeFacility.RUNTIME_TYPES.BOOLEAN) || 
-                          sourceType.equals(TypeFacility.RUNTIME_TYPES.BYTE) || 
-                          sourceType.equals(TypeFacility.RUNTIME_TYPES.SHORT)){
-              
-              // Just drop these
-              return null;
-          } 
-
-          // BEFORE: convert(expression, integer)
-          // AFTER:  integer(expression)
-          return wrapNewFunction(expression, "integer", TypeFacility.RUNTIME_TYPES.INTEGER); //$NON-NLS-1$
-      }
-
-    private IExpression convertToBigInt(IExpression expression, Class sourceType) {
-        
-        if(sourceType.equals(TypeFacility.RUNTIME_TYPES.STRING) ||
-                        sourceType.equals(TypeFacility.RUNTIME_TYPES.FLOAT) || 
-                        sourceType.equals(TypeFacility.RUNTIME_TYPES.DOUBLE) || 
-                        sourceType.equals(TypeFacility.RUNTIME_TYPES.BIG_DECIMAL)){
-
-            // BEFORE: convert(expression, [long, biginteger])
-            // AFTER:  bigint(expression)
-            return wrapNewFunction(expression, "bigint", TypeFacility.RUNTIME_TYPES.LONG); //$NON-NLS-1$
-
-        } 
-
-        // Just drop anything else
-        return null;
-    }
-
-    private IExpression convertToFloat(IExpression expression, Class sourceType) {
-        
         if(sourceType.equals(TypeFacility.RUNTIME_TYPES.STRING)){
 
             // BEFORE: convert(string_expr, float)
@@ -257,7 +73,8 @@
         return null;
     }
 
-    private IExpression convertToDouble(IExpression expression, Class sourceType) {
+    @Override
+    protected IExpression convertToDouble(IExpression expression, Class sourceType) {
 
         if(sourceType.equals(TypeFacility.RUNTIME_TYPES.STRING)){
             // BEFORE: convert(string_expr, double)
@@ -275,7 +92,8 @@
         return null;
     }
 
-    private IExpression convertToBigDecimal(IExpression expression, Class sourceType) {
+    @Override
+    protected IExpression convertToBigDecimal(IExpression expression, Class sourceType) {
         
         if(sourceType.equals(TypeFacility.RUNTIME_TYPES.STRING)){
             // BEFORE: convert(string_expr, bigdecimal)
@@ -288,66 +106,5 @@
         // Just drop anything else
         return null;
     }
-
-    /** 
-     * @param expression
-     * @param sourceType
-     * @return
-     * @since 4.2
-     */
-    private IExpression convertToDate(IExpression expression,
-                                      Class sourceType) {
-                                
-        // BEFORE: convert(EXPR, date) 
-        // AFTER:  date(EXPR) 
-        return wrapNewFunction(expression, "date", TypeFacility.RUNTIME_TYPES.DATE); //$NON-NLS-1$
-    }
-
-    private IExpression convertToTime(IExpression expression,
-                                      Class sourceType) {
-                                
-        // BEFORE: convert(EXPR, time) 
-        // AFTER:  time(EXPR) 
-        return wrapNewFunction(expression, "time", TypeFacility.RUNTIME_TYPES.DATE); //$NON-NLS-1$
-    }
-
-    private IExpression convertToTimestamp(IExpression expression,
-                                            Class sourceType) {
-        
-        if(sourceType.equals(TypeFacility.RUNTIME_TYPES.STRING)) {
-            // BEFORE: convert(EXPR, timestamp)
-            // AFTER:  timestamp(expr)
-            return wrapNewFunction(expression, "timestamp", TypeFacility.RUNTIME_TYPES.TIMESTAMP); //$NON-NLS-1$
-            
-        } else if(sourceType.equals(TypeFacility.RUNTIME_TYPES.DATE)) {
-            // BEFORE: convert(EXPR, timestamp)
-            // AFTER:  timestamp(EXPR, '00:00:00')
-            ILiteral timeString = this.langFactory.createLiteral("00:00:00", TypeFacility.RUNTIME_TYPES.STRING); //$NON-NLS-1$
-            return this.langFactory.createFunction("timestamp", Arrays.asList(expression, timeString), TypeFacility.RUNTIME_TYPES.TIMESTAMP);             //$NON-NLS-1$
-            
-        } else if(sourceType.equals(TypeFacility.RUNTIME_TYPES.TIME)) {
-            // BEFORE: convert(EXPR, timestamp)
-            // AFTER:  timestamp(EXPR, '1970-01-01', EXPR)
-            ILiteral dateString = this.langFactory.createLiteral("1970-01-01", TypeFacility.RUNTIME_TYPES.STRING); //$NON-NLS-1$
-            return this.langFactory.createFunction("timestamp", Arrays.asList(dateString, expression), TypeFacility.RUNTIME_TYPES.TIMESTAMP);             //$NON-NLS-1$
-        }
-        
-        return null;
-    }
     
-    /** 
-     * @param expression
-     * @param functionName
-     * @param outputType
-     * @return
-     * @since 4.2
-     */
-    private IFunction wrapNewFunction(IExpression expression,
-                                      String functionName,
-                                      Class outputType) {
-        return langFactory.createFunction(functionName, 
-            Arrays.asList( expression ),
-            outputType);
-    }
-
 }

Modified: trunk/connectors/connector-jdbc/src/main/java/org/teiid/connector/jdbc/derby/DerbySQLTranslator.java
===================================================================
--- trunk/connectors/connector-jdbc/src/main/java/org/teiid/connector/jdbc/derby/DerbySQLTranslator.java	2009-07-25 20:58:40 UTC (rev 1188)
+++ trunk/connectors/connector-jdbc/src/main/java/org/teiid/connector/jdbc/derby/DerbySQLTranslator.java	2009-07-26 16:53:56 UTC (rev 1189)
@@ -26,28 +26,30 @@
 import org.teiid.connector.api.ConnectorEnvironment;
 import org.teiid.connector.api.ConnectorException;
 import org.teiid.connector.api.SourceSystemFunctions;
-import org.teiid.connector.jdbc.translator.AliasModifier;
+import org.teiid.connector.jdbc.db2.DB2SQLTranslator;
+import org.teiid.connector.jdbc.oracle.LeftOrRightFunctionModifier;
 import org.teiid.connector.jdbc.translator.EscapeSyntaxModifier;
-import org.teiid.connector.jdbc.translator.Translator;
 
 
 
 /** 
  * @since 4.3
  */
-public class DerbySQLTranslator extends Translator {
+public class DerbySQLTranslator extends DB2SQLTranslator {
+	
+	public static final String DATABASE_VERSION = "DatabaseVersion"; //$NON-NLS-1$
 
 	@Override
 	public void initialize(ConnectorEnvironment env) throws ConnectorException {
 		super.initialize(env);
-        registerFunctionModifier(SourceSystemFunctions.CONCAT, new EscapeSyntaxModifier()); 
-        registerFunctionModifier(SourceSystemFunctions.SUBSTRING, new AliasModifier("substr")); //$NON-NLS-1$ 
-        registerFunctionModifier(SourceSystemFunctions.DAYOFMONTH, new AliasModifier("day")); //$NON-NLS-1$ 
+		//additional derby functions
         registerFunctionModifier(SourceSystemFunctions.TIMESTAMPADD, new EscapeSyntaxModifier()); 
-        registerFunctionModifier(SourceSystemFunctions.TIMESTAMPDIFF, new EscapeSyntaxModifier()); 
+        registerFunctionModifier(SourceSystemFunctions.TIMESTAMPDIFF, new EscapeSyntaxModifier()); 
+        registerFunctionModifier(SourceSystemFunctions.LEFT, new LeftOrRightFunctionModifier(getLanguageFactory()));
+        
+        //overrides of db2 functions
+        registerFunctionModifier(SourceSystemFunctions.CONCAT, new EscapeSyntaxModifier()); 
         registerFunctionModifier(SourceSystemFunctions.CONVERT, new DerbyConvertModifier(getLanguageFactory())); 
-        registerFunctionModifier(SourceSystemFunctions.IFNULL, new AliasModifier("coalesce")); //$NON-NLS-1$ 
-        registerFunctionModifier(SourceSystemFunctions.COALESCE, new AliasModifier("coalesce")); //$NON-NLS-1$ 
     }  
  
     @Override
@@ -63,6 +65,16 @@
     @Override
     public Class<? extends ConnectorCapabilities> getDefaultCapabilities() {
     	return DerbyCapabilities.class;
+    }
+    
+    @Override
+    public ConnectorCapabilities getConnectorCapabilities()
+    		throws ConnectorException {
+    	ConnectorCapabilities capabilities = super.getConnectorCapabilities();
+    	if (capabilities instanceof DerbyCapabilities) {
+    		((DerbyCapabilities)capabilities).setVersion(getEnvironment().getProperties().getProperty(DATABASE_VERSION, DerbyCapabilities.TEN_1));
+    	}
+    	return capabilities;
     }
 
 }

Modified: trunk/connectors/connector-jdbc/src/main/java/org/teiid/connector/jdbc/oracle/ConcatFunctionModifier.java
===================================================================
--- trunk/connectors/connector-jdbc/src/main/java/org/teiid/connector/jdbc/oracle/ConcatFunctionModifier.java	2009-07-25 20:58:40 UTC (rev 1188)
+++ trunk/connectors/connector-jdbc/src/main/java/org/teiid/connector/jdbc/oracle/ConcatFunctionModifier.java	2009-07-26 16:53:56 UTC (rev 1189)
@@ -40,7 +40,6 @@
 
 /**
  * This Function modifier used to support ANSI concat on Oracle 9i.
- * TODO: this is no longer necessary on Oracle 10g and later. 
  * <code>
  * CONCAT(a, b) ==> CASE WHEN (a is NULL OR b is NULL) THEN NULL ELSE CONCAT(a, b)
  * </code>   

Modified: trunk/connectors/connector-jdbc/src/main/java/org/teiid/connector/jdbc/postgresql/PostgreSQLCapabilities.java
===================================================================
--- trunk/connectors/connector-jdbc/src/main/java/org/teiid/connector/jdbc/postgresql/PostgreSQLCapabilities.java	2009-07-25 20:58:40 UTC (rev 1188)
+++ trunk/connectors/connector-jdbc/src/main/java/org/teiid/connector/jdbc/postgresql/PostgreSQLCapabilities.java	2009-07-26 16:53:56 UTC (rev 1189)
@@ -35,8 +35,8 @@
 public class PostgreSQLCapabilities extends JDBCCapabilities {
     
     
-    public List getSupportedFunctions() {
-        List supportedFunctions = new ArrayList();
+    public List<String> getSupportedFunctions() {
+        List<String> supportedFunctions = new ArrayList<String>();
         supportedFunctions.addAll(super.getSupportedFunctions());
     
         supportedFunctions.add("ABS"); //$NON-NLS-1$

Modified: trunk/connectors/connector-jdbc/src/main/java/org/teiid/connector/jdbc/postgresql/PostgreSQLTranslator.java
===================================================================
--- trunk/connectors/connector-jdbc/src/main/java/org/teiid/connector/jdbc/postgresql/PostgreSQLTranslator.java	2009-07-25 20:58:40 UTC (rev 1188)
+++ trunk/connectors/connector-jdbc/src/main/java/org/teiid/connector/jdbc/postgresql/PostgreSQLTranslator.java	2009-07-26 16:53:56 UTC (rev 1189)
@@ -37,6 +37,7 @@
 import org.teiid.connector.jdbc.oracle.LeftOrRightFunctionModifier;
 import org.teiid.connector.jdbc.oracle.MonthOrDayNameFunctionModifier;
 import org.teiid.connector.jdbc.translator.AliasModifier;
+import org.teiid.connector.jdbc.translator.EscapeSyntaxModifier;
 import org.teiid.connector.jdbc.translator.ExtractFunctionModifier;
 import org.teiid.connector.jdbc.translator.Translator;
 import org.teiid.connector.language.IAggregate;
@@ -86,8 +87,8 @@
         registerFunctionModifier(SourceSystemFunctions.YEAR, new ExtractFunctionModifier()); 
         
         //specific to 8.2 client or later
-        //registerFunctionModifier(SourceSystemFunctions.TIMESTAMPADD, new EscapeSyntaxModifier());
-        //registerFunctionModifier(SourceSystemFunctions.TIMESTAMPDIFF, new EscapeSyntaxModifier());
+        registerFunctionModifier(SourceSystemFunctions.TIMESTAMPADD, new EscapeSyntaxModifier());
+        registerFunctionModifier(SourceSystemFunctions.TIMESTAMPDIFF, new EscapeSyntaxModifier());
         
         registerFunctionModifier(SourceSystemFunctions.IFNULL, new AliasModifier("coalesce")); //$NON-NLS-1$ 
         registerFunctionModifier(SourceSystemFunctions.CONVERT, new PostgreSQLConvertModifier(getLanguageFactory()));        

Modified: trunk/connectors/connector-jdbc/src/main/java/org/teiid/connector/jdbc/sqlserver/SqlServerCapabilities.java
===================================================================
--- trunk/connectors/connector-jdbc/src/main/java/org/teiid/connector/jdbc/sqlserver/SqlServerCapabilities.java	2009-07-25 20:58:40 UTC (rev 1188)
+++ trunk/connectors/connector-jdbc/src/main/java/org/teiid/connector/jdbc/sqlserver/SqlServerCapabilities.java	2009-07-26 16:53:56 UTC (rev 1189)
@@ -39,8 +39,8 @@
     /**
      * @see com.metamatrix.data.ConnectorCapabilities#getSupportedFunctions()
      */
-    public List getSupportedFunctions() {
-        List supportedFunctions = new ArrayList();
+    public List<String> getSupportedFunctions() {
+        List<String> supportedFunctions = new ArrayList<String>();
         supportedFunctions.addAll(super.getSupportedFunctions());
         supportedFunctions.add("ABS"); //$NON-NLS-1$
         supportedFunctions.add("ACOS"); //$NON-NLS-1$

Added: trunk/connectors/connector-jdbc/src/main/java/org/teiid/connector/jdbc/translator/MODFunctionModifier.java
===================================================================
--- trunk/connectors/connector-jdbc/src/main/java/org/teiid/connector/jdbc/translator/MODFunctionModifier.java	                        (rev 0)
+++ trunk/connectors/connector-jdbc/src/main/java/org/teiid/connector/jdbc/translator/MODFunctionModifier.java	2009-07-26 16:53:56 UTC (rev 1189)
@@ -0,0 +1,185 @@
+/*
+ * 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.connector.jdbc.translator;
+
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.List;
+
+import org.teiid.connector.api.TypeFacility.RUNTIME_TYPES;
+import org.teiid.connector.language.IExpression;
+import org.teiid.connector.language.IFunction;
+import org.teiid.connector.language.ILanguageFactory;
+
+/**
+ * A modifier class that can be used to translate the scalar function 
+ * <code>mod(x, y)</code> to a function or expression that can be used at the 
+ * data source.
+ * <p>
+ * If the default implementation is used, a function name of MOD will be used 
+ * for the alias name and the expression will be unmodified if the data type 
+ * of the <code>x</code> parameter is one of {@link RUNTIME_TYPES#BYTE}, 
+ * {@link RUNTIME_TYPES#SHORT}, {@link RUNTIME_TYPES#INTEGER}, or 
+ * {@link RUNTIME_TYPES#LONG}.  If the data type is not one of these types, the
+ * expression will be modified to return: <code>(x - (TRUNC((x / y), 0) * y))</code>
+ * 
+ * @since 6.2
+ */
+public class MODFunctionModifier extends AliasModifier {
+
+	private static List<Class<?>> DEFAULT_TYPELIST = new ArrayList<Class<?>>(4);
+	static {
+		DEFAULT_TYPELIST.add(RUNTIME_TYPES.BYTE);
+		DEFAULT_TYPELIST.add(RUNTIME_TYPES.SHORT);
+		DEFAULT_TYPELIST.add(RUNTIME_TYPES.INTEGER);
+		DEFAULT_TYPELIST.add(RUNTIME_TYPES.LONG);
+	}
+	private static String DEFAULT_FUNCTIONNAME = "MOD"; //$NON-NLS-1$
+
+	private ILanguageFactory langFactory;
+	private List<Class<?>> supTypeList;
+    
+	/**
+	 * Constructs a {@link AliasModifier} object that can be used to translate 
+	 * the use of the scalar function MOD() to a source specific scalar function 
+	 * or expression.
+	 * <p>
+	 * This constructor invokes {@link #MODFunctionModifier(ILanguageFactory, String, List)}
+	 * passing it <code>langFactory</code>, {@link #DEFAULT_FUNCTIONNAME}, and 
+	 * {@link #DEFAULT_TYPELIST}.
+	 * 
+	 * @param langFactory the language factory associated with translation
+	 */
+    public MODFunctionModifier(ILanguageFactory langFactory) {
+    	this(langFactory, DEFAULT_FUNCTIONNAME, DEFAULT_TYPELIST);
+    }
+	
+    /**
+	 * Constructs a {@link AliasModifier} object that can be used to translate 
+	 * the use of the scalar function MOD() to a source specific scalar function 
+	 * or expression.
+	 * <p>
+	 * <code>functionName</code> is used to construct the parent {@link AliasModifier}
+	 * and should represent the default function name or alias used by the data 
+	 * source.
+	 * <p>
+	 * <code>supportedTypeList</code> should contain a list of <code>Class</code> 
+	 * objects that represent the data types that the data source can support  
+	 * with its implementation of the MOD() scalar function.  
+     * 
+     * @param langFactory the language factory associated with translation
+     * @param functionName the function name or alias that should be used 
+     *                     instead of MOD
+     * @param supportedTypeList a list of type classes that is supported by the 
+     *                          data source's MOD function
+     */
+    public MODFunctionModifier(ILanguageFactory langFactory, String functionName, List<Class<?>>supportedTypeList) {
+    	super(functionName);
+        this.langFactory = langFactory;
+        if ( supportedTypeList != null ) {
+        	this.supTypeList = supportedTypeList;
+        } else {
+        	this.supTypeList = MODFunctionModifier.DEFAULT_TYPELIST;
+        }
+    }
+	
+	/**
+	 * Returns a version of <code>function</code> suitable for executing at the 
+	 * data source.
+	 * <p>
+	 * If the data type of the parameters in <code>function</code> is in the 
+	 * list of supported data types, this method simply returns <code>super.modify(function)</code>.
+	 * <p>
+	 * If the data type of the parameters in <code>function</code are not in the 
+	 * list of supported data types, this method will return an expression that 
+	 * is valid at the data source and will yield the same result as the original 
+	 * MOD() scalar function.  To build the expression, a call is make to 
+	 * {@link #getQuotientExpression(IExpression)} and its result is multiplied 
+	 * by the second parameter of <code>function</code> and that result is then 
+	 * subtracted from the first parameter of <code>function</code>.
+	 * <p>
+	 * For example:
+	 * <code>mod(x, y)  --->  (x - (getQuotientExpression((x / y)) * y))</code>
+	 * 
+	 * @param function the MOD function that may need to be modified
+	 * @see org.teiid.connector.jdbc.translator.AliasModifier#modify(org.teiid.connector.language.IFunction)
+	 */
+	@Override
+	public IExpression modify(IFunction function) {
+		List<IExpression> expressions = function.getParameters();
+		IExpression dividend = expressions.get(0);
+		IExpression divisor = expressions.get(1);
+
+		// Check to see if parameters are supported by source MOD function
+		if (this.supTypeList.contains(dividend.getType())) {
+			return super.modify(function);
+		}
+
+		/* 
+		 * Parameters are not supported by source MOD function so modify 
+		 * MOD(<dividend>, <divisor>)  -->  (<dividend> - (<func_getQuotient((<dividend> / <divisor>))> * <divisor>))
+		 */
+		// -->   (<dividend> / <divisor>)
+		IFunction divide = langFactory.createFunction("/", Arrays.asList(dividend, divisor), dividend.getType()); //$NON-NLS-1$
+		// -->   <func_getQuotient(<divide>)>  -- i.e. TRUNC(<divide>, 0)
+		IFunction quotient = (IFunction) this.getQuotientExpression(divide);
+		// -->   (<quotient> * <divisor>)
+		List<IExpression> multiplyArgs = Arrays.asList(quotient, divisor);
+		IFunction multiply = langFactory.createFunction("*", multiplyArgs, divisor.getType()); //$NON-NLS-1$
+		// -->   (<dividend> - <multiply>)
+		List<IExpression> minusArgs = Arrays.asList(dividend, multiply);
+		return langFactory.createFunction("-", minusArgs, dividend.getType()); //$NON-NLS-1$
+	}
+
+	/**
+	 * Return an expression that will result in the quotient of </code>division</code>. 
+	 * Quotient should always be represented as an integer (no remainder).
+	 * <p>
+	 * <code>division</code> will represent simple division that may result in a
+	 * fraction.  <code>division</code> should be returned within a helper 
+	 * function or expression that will result in an integer return value (no 
+	 * decimal or fraction).
+	 * <p>
+	 * If this method is not overriden, the result will be:
+	 * <p>
+	 * <ul>TRUNC(<code>division</code>, 0)</ul>
+	 * <p>
+	 * For the default TRUNC() function to work, the source must support it.  
+	 * TRUNC was used instead of FLOOR because FLOOR rounds to the nearest
+	 * integer toward negative infinity.  This would result in incorrect values 
+	 * when performing MOD on negative float, double, etc. values.
+	 *   
+	 * @param division an expression representing simple division
+	 * @return an expression that will extract the quotient from the 
+	 *         <code>division</code> expression
+	 */
+	protected IExpression getQuotientExpression(IExpression division) {
+		// -->   TRUNC(<division>, 0)
+		return langFactory.createFunction("TRUNC", Arrays.asList(division, langFactory.createLiteral(0, RUNTIME_TYPES.SHORT)), division.getType()); //$NON-NLS-1$
+	}
+
+	protected ILanguageFactory getLanguageFactory() {
+		return this.langFactory;
+	}
+	
+}


Property changes on: trunk/connectors/connector-jdbc/src/main/java/org/teiid/connector/jdbc/translator/MODFunctionModifier.java
___________________________________________________________________
Name: svn:mime-type
   + text/plain

Modified: trunk/connectors/connector-jdbc/src/main/resources/connector-jdbc.xml
===================================================================
--- trunk/connectors/connector-jdbc/src/main/resources/connector-jdbc.xml	2009-07-25 20:58:40 UTC (rev 1188)
+++ trunk/connectors/connector-jdbc/src/main/resources/connector-jdbc.xml	2009-07-26 16:53:56 UTC (rev 1189)
@@ -99,11 +99,13 @@
             <PropertyDefinition Name="ConnectionSource" DisplayName="Connection Source Class" ShortDescription="Driver, DataSource, or XADataSource class name" DefaultValue="org.apache.derby.jdbc.EmbeddedDriver" IsRequired="true"   />        
             <PropertyDefinition Name="URL" DisplayName="JDBC URL" ShortDescription="" DefaultValue="jdbc:derby:&lt;databaseName&gt;" IsRequired="true" PropertyType="String"    IsMasked="false"   />
             <PropertyDefinition Name="ExtensionTranslationClass" DisplayName="Extension SQL Translation Class" ShortDescription="" DefaultValue="org.teiid.connector.jdbc.derby.DerbySQLTranslator"  PropertyType="String"   IsExpert="true"  IsMasked="false"   />
+			<PropertyDefinition Name="DatabaseVersion" DisplayName="Database Version" ShortDescription="Derby Version i.e. 10.3" DefaultValue="10.1" PropertyType="String" />             
         </ComponentType>
         <ComponentType Name="Apache Derby Network Connector" ComponentTypeCode="2" Deployable="true" Deprecated="false" Monitorable="false" SuperComponentType="JDBC Connector" ParentComponentType="Connectors" LastChangedBy="ConfigurationStartup" CreatedBy="ConfigurationStartup">
             <PropertyDefinition Name="ConnectionSource" DisplayName="Connection Source Class" ShortDescription="Driver, DataSource, or XADataSource class name" DefaultValue="org.apache.derby.jdbc.ClientDriver" IsRequired="true"   />        
             <PropertyDefinition Name="URL" DisplayName="JDBC URL" ShortDescription="" DefaultValue="jdbc:derby://localhost:1527/&lt;path/to/db&gt;" IsRequired="true" PropertyType="String"    IsMasked="false"   />
             <PropertyDefinition Name="ExtensionTranslationClass" DisplayName="Extension SQL Translation Class" ShortDescription="" DefaultValue="org.teiid.connector.jdbc.derby.DerbySQLTranslator"  PropertyType="String"   IsExpert="true"  IsMasked="false"   />
+            <PropertyDefinition Name="DatabaseVersion" DisplayName="Database Version" ShortDescription="Derby Version i.e. 10.3" DefaultValue="10.1" PropertyType="String" />
         </ComponentType>
         <ComponentType Name="Teiid 6 JDBC Connector" ComponentTypeCode="2" Deployable="true" Deprecated="false" Monitorable="false" SuperComponentType="JDBC Connector" ParentComponentType="Connectors" LastChangedBy="ConfigurationStartup" CreatedBy="ConfigurationStartup">
             <PropertyDefinition Name="ConnectionSource" DisplayName="Connection Source Class" ShortDescription="Driver, DataSource, or XADataSource class name" DefaultValue="com.metamatrix.jdbc.MMDriver" IsRequired="true"   />

Modified: trunk/connectors/connector-jdbc/src/test/java/org/teiid/connector/jdbc/db2/TestDB2SqlTranslator.java
===================================================================
--- trunk/connectors/connector-jdbc/src/test/java/org/teiid/connector/jdbc/db2/TestDB2SqlTranslator.java	2009-07-25 20:58:40 UTC (rev 1188)
+++ trunk/connectors/connector-jdbc/src/test/java/org/teiid/connector/jdbc/db2/TestDB2SqlTranslator.java	2009-07-26 16:53:56 UTC (rev 1189)
@@ -58,7 +58,7 @@
         // Convert from sql to objects
         ICommand obj = util.parseCommand(input);
         
-        ExecutionContext context = EnvironmentUtility.createSecurityContext("user");
+        ExecutionContext context = EnvironmentUtility.createSecurityContext("user"); //$NON-NLS-1$
                 
         TranslatedCommand tc = new TranslatedCommand(context, TRANSLATOR);
         tc.translateCommand(obj);
@@ -106,5 +106,16 @@
                 input, 
                 output);
     }    
+    
+    @Test
+    public void testSelectNullLiteral() throws Exception {
+        String input = "select null + 1 as x, null || 'a' from BQT1.Smalla"; //$NON-NLS-1$       
+        String output = "SELECT CAST(NULL AS INTEGER) AS x, CAST(NULL AS CHAR) FROM SmallA";  //$NON-NLS-1$
+        
+        helpTestVisitor(FakeTranslationFactory.getInstance().getBQTTranslationUtility(),
+                input, 
+                output);
+    }    
 
+
 }

Added: trunk/connectors/connector-jdbc/src/test/java/org/teiid/connector/jdbc/derby/TestDerbyCapabilities.java
===================================================================
--- trunk/connectors/connector-jdbc/src/test/java/org/teiid/connector/jdbc/derby/TestDerbyCapabilities.java	                        (rev 0)
+++ trunk/connectors/connector-jdbc/src/test/java/org/teiid/connector/jdbc/derby/TestDerbyCapabilities.java	2009-07-26 16:53:56 UTC (rev 1189)
@@ -0,0 +1,45 @@
+/*
+ * 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.connector.jdbc.derby;
+
+import static org.junit.Assert.*;
+
+import org.junit.Test;
+
+public class TestDerbyCapabilities {
+	
+	@Test public void testLimitSupport() {
+		DerbyCapabilities derbyCapabilities = new DerbyCapabilities();
+		assertFalse(derbyCapabilities.supportsRowLimit());
+		derbyCapabilities.setVersion(DerbyCapabilities.TEN_5);
+		assertTrue(derbyCapabilities.supportsRowLimit());
+	}
+	
+	@Test public void testFunctionSupport() {
+		DerbyCapabilities derbyCapabilities = new DerbyCapabilities();
+		assertEquals(32, derbyCapabilities.getSupportedFunctions().size());
+		derbyCapabilities.setVersion(DerbyCapabilities.TEN_4);
+		assertEquals(48, derbyCapabilities.getSupportedFunctions().size());
+	}
+
+}


Property changes on: trunk/connectors/connector-jdbc/src/test/java/org/teiid/connector/jdbc/derby/TestDerbyCapabilities.java
___________________________________________________________________
Name: svn:mime-type
   + text/plain

Modified: trunk/connectors/connector-jdbc/src/test/java/org/teiid/connector/jdbc/oracle/TestLeftOrRightFunctionModifier.java
===================================================================
--- trunk/connectors/connector-jdbc/src/test/java/org/teiid/connector/jdbc/oracle/TestLeftOrRightFunctionModifier.java	2009-07-25 20:58:40 UTC (rev 1188)
+++ trunk/connectors/connector-jdbc/src/test/java/org/teiid/connector/jdbc/oracle/TestLeftOrRightFunctionModifier.java	2009-07-26 16:53:56 UTC (rev 1189)
@@ -25,16 +25,14 @@
 import java.util.Arrays;
 import java.util.Properties;
 
-import org.teiid.connector.jdbc.oracle.LeftOrRightFunctionModifier;
-import org.teiid.connector.jdbc.oracle.OracleSQLTranslator;
+import junit.framework.TestCase;
+
 import org.teiid.connector.jdbc.translator.SQLConversionVisitor;
 import org.teiid.connector.language.IExpression;
 import org.teiid.connector.language.IFunction;
 import org.teiid.connector.language.ILanguageFactory;
 import org.teiid.connector.language.ILiteral;
 
-import junit.framework.TestCase;
-
 import com.metamatrix.cdk.CommandBuilder;
 import com.metamatrix.cdk.api.EnvironmentUtility;
 

Added: trunk/connectors/connector-jdbc/src/test/java/org/teiid/connector/jdbc/translator/TestMODFunctionModifier.java
===================================================================
--- trunk/connectors/connector-jdbc/src/test/java/org/teiid/connector/jdbc/translator/TestMODFunctionModifier.java	                        (rev 0)
+++ trunk/connectors/connector-jdbc/src/test/java/org/teiid/connector/jdbc/translator/TestMODFunctionModifier.java	2009-07-26 16:53:56 UTC (rev 1189)
@@ -0,0 +1,1253 @@
+/*
+ * 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.connector.jdbc.translator;
+
+import java.math.BigDecimal;
+import java.math.BigInteger;
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.List;
+import java.util.Properties;
+
+import junit.framework.TestCase;
+
+import org.teiid.connector.api.ConnectorEnvironment;
+import org.teiid.connector.api.ConnectorException;
+import org.teiid.connector.api.SourceSystemFunctions;
+import org.teiid.connector.language.IExpression;
+import org.teiid.connector.language.IFunction;
+import org.teiid.connector.language.ILanguageFactory;
+
+import com.metamatrix.cdk.CommandBuilder;
+import com.metamatrix.cdk.api.EnvironmentUtility;
+
+/**
+ * Test <code>ModFunctionModifier</code> by invoking its methods with varying 
+ * parameters to validate it performs as designed and expected. 
+ */
+public class TestMODFunctionModifier extends TestCase {
+
+    private static final ILanguageFactory LANG_FACTORY = CommandBuilder.getLanuageFactory();
+
+    /**
+     * Constructor for TestModFunctionModifier.
+     * @param name
+     */
+    public TestMODFunctionModifier(String name) {
+        super(name);
+    }
+
+
+    /**
+     * Create an expression containing a MOD function using <code>args</code> 
+     * and pass it to the <code>Translator</code>'s MOD function modifier and 
+     * compare the resulting expression to <code>expectedStr</code>.
+     * 
+     * @param args An array of <code>IExpression</code>'s to use as the 
+     *             arguments to the MOD() function
+     * @param expectedStr A string representing the modified expression
+     * @return On success, the modified expression.
+     * @throws Exception
+     */
+    public IExpression helpTestMod(IExpression[] args, String expectedStr) throws Exception {
+    	return this.helpTestMod(null, null, args, expectedStr);
+    }
+
+    /**
+     * Create an expression containing a MOD function using a function name of 
+     * <code>modFunctionName</code> which supports types of <code>supportedTypes</code>
+     * and uses the arguments <code>args</code> and pass it to the 
+     * <code>Translator</code>'s MOD function modifier and compare the resulting 
+     * expression to <code>expectedStr</code>.
+     *
+     * @param modFunctionName the name to use for the function modifier
+     * @param supportedTypes a list of types that the mod function should support
+     * @param args an array of <code>IExpression</code>'s to use as the 
+     *             arguments to the MOD() function
+     * @param expectedStr A string representing the modified expression
+     * @return On success, the modified expression.
+     * @throws Exception
+     */
+    public IExpression helpTestMod(final String modFunctionName, final List<Class<?>> supportedTypes, IExpression[] args, String expectedStr) throws Exception {
+    	IExpression param1 = null;
+    	IExpression param2 = null;
+    	
+    	if (args.length < 2) {
+    		param2 = LANG_FACTORY.createLiteral(null, Short.class);
+    		if (args.length < 1) {
+        		param1 = LANG_FACTORY.createLiteral(null, Short.class);
+    		} else {
+    			param1 = args[0];
+    		}
+    	} else {
+    		param1 = args[0];
+    		param2 = args[1];
+    	}
+    	
+    	if ( !param1.getType().equals(param2.getType()) ) {
+    		if (param2.getType().equals(BigDecimal.class)) {
+    			param1.setType(param2.getType());
+    		} else if (param1.getType().equals(BigDecimal.class)) {
+    			param2.setType(param1.getType());
+    		} else if (param2.getType().equals(BigInteger.class)) {
+    			param1.setType(param2.getType());
+    		} else if (param1.getType().equals(BigInteger.class)) {
+    			param2.setType(param1.getType());
+    		} else if (param2.getType().equals(Float.class)) {
+    			param1.setType(param2.getType());
+    		} else if (param1.getType().equals(Float.class)) {
+    			param2.setType(param1.getType());
+    		} else if (param2.getType().equals(Long.class)) {
+    			param1.setType(param2.getType());
+    		} else if (param1.getType().equals(Long.class)) {
+    			param2.setType(param1.getType());
+    		} else if (param2.getType().equals(Integer.class)) {
+    			param1.setType(param2.getType());
+    		} else if (param1.getType().equals(Integer.class)) {
+    			param2.setType(param1.getType());
+    		} else if (param2.getType().equals(Short.class)) {
+    			param1.setType(param2.getType());
+    		} else if (param1.getType().equals(Short.class)) {
+    			param2.setType(param1.getType());
+    		} else {
+    			throw new IllegalArgumentException("Parameters must be of numeric types"); //$NON-NLS-1$
+    		}
+    	}
+
+    	IFunction func = LANG_FACTORY.createFunction(modFunctionName,
+            Arrays.asList(param1, param2), param1.getType());
+
+    	Translator trans = new Translator() {
+			@Override
+			public void initialize(ConnectorEnvironment env)
+					throws ConnectorException {
+				super.initialize(env);
+				if (modFunctionName == null) {
+					registerFunctionModifier(SourceSystemFunctions.MOD, new MODFunctionModifier(getLanguageFactory()));
+				} else {
+					registerFunctionModifier(SourceSystemFunctions.MOD, new MODFunctionModifier(getLanguageFactory(), modFunctionName, supportedTypes));
+				}
+			}
+    	};
+    	
+        trans.initialize(EnvironmentUtility.createEnvironment(new Properties(), false));
+
+        IExpression expr = trans.getFunctionModifiers().get(SourceSystemFunctions.MOD).modify(func);
+        
+        SQLConversionVisitor sqlVisitor = trans.getSQLConversionVisitor(); 
+        sqlVisitor.append(expr);  
+        
+        assertEquals("Modified function does not match", expectedStr, sqlVisitor.toString()); //$NON-NLS-1$
+        
+        return expr;
+    }
+
+    /**
+     * Test {@link MODFunctionModifier#modify(IFunction)} to validate a call to 
+     * MOD(x,y) using {@link Short} constants for both parameters returns MOD(x,y). 
+     * {@link MODFunctionModifier} will be constructed without specifying a 
+     * function name or a supported type list.
+     * 
+     * @throws Exception
+     */
+    public void testTwoShortConst() throws Exception {
+        IExpression[] args = new IExpression[] {
+            LANG_FACTORY.createLiteral(new Short((short) 10), Short.class),
+            LANG_FACTORY.createLiteral(new Short((short) 6), Short.class)           
+        };
+        // default / default
+        helpTestMod(args, "MOD(10, 6)"); //$NON-NLS-1$
+    }
+
+    /**
+     * Test {@link MODFunctionModifier#modify(IFunction)} to validate a call to 
+     * MOD(x,y) using {@link Short} constants for both parameters returns MOD(x,y). 
+     * {@link MODFunctionModifier} will be constructed with a function name of 
+     * "MOD" but without a supported type list.
+     *  
+     * @throws Exception
+     */
+    public void testTwoShortConst2() throws Exception {
+        IExpression[] args = new IExpression[] {
+            LANG_FACTORY.createLiteral(new Short((short) 10), Short.class),
+            LANG_FACTORY.createLiteral(new Short((short) 6), Short.class)           
+        };
+        // mod / default 
+        helpTestMod("MOD", null, args, "MOD(10, 6)"); //$NON-NLS-1$ //$NON-NLS-2$
+    }
+
+    /**
+     * Test {@link MODFunctionModifier#modify(IFunction)} to validate a call to 
+     * MOD(x,y) using {@link Short} constants for both parameters returns MOD(x,y). 
+     * {@link MODFunctionModifier} will be constructed with a function name of 
+     * "MOD" and a supported type list which contains {@link Short}. 
+     * 
+     * @throws Exception
+     */
+    public void testTwoShortConst3() throws Exception {
+        IExpression[] args = new IExpression[] {
+            LANG_FACTORY.createLiteral(new Short((short) 10), Short.class),
+            LANG_FACTORY.createLiteral(new Short((short) 6), Short.class)           
+        };
+        // mod / Short
+        List<Class<?>> typeList = new ArrayList<Class<?>>(1);
+        typeList.add(Short.class);
+        helpTestMod("MOD", typeList, args, "MOD(10, 6)"); //$NON-NLS-1$ //$NON-NLS-2$
+    }
+
+    /**
+     * Test {@link MODFunctionModifier#modify(IFunction)} to validate a call to 
+     * MOD(x,y) using {@link Short} constants for both parameters returns 
+     * (x - (TRUNC((x / y), 0) * y)).  {@link MODFunctionModifier} will be 
+     * constructed with a function name of "MOD" and a supported type list which 
+     * does not contains {@link Short}. 
+     * 
+     * @throws Exception
+     */
+    public void testTwoShortConst4() throws Exception {
+        IExpression[] args = new IExpression[] {
+            LANG_FACTORY.createLiteral(new Short((short) 10), Short.class),
+            LANG_FACTORY.createLiteral(new Short((short) 6), Short.class)           
+        };
+        // mod / Integer
+        List<Class<?>> typeList = new ArrayList<Class<?>>(1);
+        typeList.add(Integer.class);
+        helpTestMod("MOD", typeList, args, "(10 - (TRUNC((10 / 6), 0) * 6))"); //$NON-NLS-1$ //$NON-NLS-2$
+    }
+
+    /**
+     * Test {@link MODFunctionModifier#modify(IFunction)} to validate a call to 
+     * x % y using {@link Short} constants for both parameters returns (x % y).  
+     * {@link MODFunctionModifier} will be constructed with a function name of 
+     * "%" and no supported type list. 
+     * 
+     * @throws Exception
+     */
+    public void testTwoShortConst5() throws Exception {
+        IExpression[] args = new IExpression[] {
+            LANG_FACTORY.createLiteral(new Short((short) 10), Short.class),
+            LANG_FACTORY.createLiteral(new Short((short) 6), Short.class)           
+        };
+        // % / default 
+        helpTestMod("%", null, args, "(10 % 6)"); //$NON-NLS-1$ //$NON-NLS-2$
+    }
+
+    /**
+     * Test {@link MODFunctionModifier#modify(IFunction)} to validate a call to 
+     * x % y using {@link Short} constants for both parameters returns (x % y).  
+     * {@link MODFunctionModifier} will be constructed with a function name of 
+     * "%" and a supported type list which contains {@link Short}. 
+     * 
+     * @throws Exception
+     */
+    public void testTwoShortConst6() throws Exception {
+        IExpression[] args = new IExpression[] {
+            LANG_FACTORY.createLiteral(new Short((short) 10), Short.class),
+            LANG_FACTORY.createLiteral(new Short((short) 6), Short.class)           
+        };
+        // % / Short
+        List<Class<?>> typeList = new ArrayList<Class<?>>(1);
+        typeList.add(Short.class);
+        helpTestMod("%", typeList, args, "(10 % 6)"); //$NON-NLS-1$ //$NON-NLS-2$
+    }
+
+    /**
+     * Test {@link MODFunctionModifier#modify(IFunction)} to validate a call to 
+     * x % y using {@link Short} constants for both parameters returns 
+     * (10 - (TRUNC((10 / 6), 0) * 6)).  {@link MODFunctionModifier} will be 
+     * constructed with a function name of "%" and a supported type list does not 
+     * contain {@link Short}. 
+     * 
+     * @throws Exception
+     */
+    public void testTwoShortConst7() throws Exception {
+        IExpression[] args = new IExpression[] {
+            LANG_FACTORY.createLiteral(new Short((short) 10), Short.class),
+            LANG_FACTORY.createLiteral(new Short((short) 6), Short.class)           
+        };
+        // % / Integer
+        List<Class<?>> typeList = new ArrayList<Class<?>>(1);
+        typeList.add(Integer.class);
+        helpTestMod("%", typeList, args, "(10 - (TRUNC((10 / 6), 0) * 6))"); //$NON-NLS-1$ //$NON-NLS-2$
+    }
+
+    /**
+     * Test {@link MODFunctionModifier#modify(IFunction)} to validate a call to 
+     * MOD(x,y) using {@link Integer} constants for both parameters returns 
+     * MOD(x,y).  {@link MODFunctionModifier} will be constructed without 
+     * specifying a function name or a supported type list.
+     * 
+     * @throws Exception
+     */
+    public void testTwoIntConst() throws Exception {
+        IExpression[] args = new IExpression[] {
+                LANG_FACTORY.createLiteral(new Integer(10), Integer.class),
+                LANG_FACTORY.createLiteral(new Integer(6), Integer.class)           
+        };
+        // default / default
+        helpTestMod(args, "MOD(10, 6)"); //$NON-NLS-1$
+    }
+
+    /**
+     * Test {@link MODFunctionModifier#modify(IFunction)} to validate a call to 
+     * MOD(x,y) using {@link Integer} constants for both parameters returns 
+     * MOD(x,y).  {@link MODFunctionModifier} will be constructed with a 
+     * function name of "MOD" but without a supported type list.
+     *  
+     * @throws Exception
+     */
+    public void testTwoIntConst2() throws Exception {
+        IExpression[] args = new IExpression[] {
+                LANG_FACTORY.createLiteral(new Integer(10), Integer.class),
+                LANG_FACTORY.createLiteral(new Integer(6), Integer.class)           
+        };
+        // mod / default 
+        helpTestMod("MOD", null, args, "MOD(10, 6)"); //$NON-NLS-1$ //$NON-NLS-2$
+    }
+
+    /**
+     * Test {@link MODFunctionModifier#modify(IFunction)} to validate a call to 
+     * MOD(x,y) using {@link Integer} constants for both parameters returns 
+     * MOD(x,y).  {@link MODFunctionModifier} will be constructed with a 
+     * function name of "MOD" and a supported type list which contains {@link Integer}. 
+     * 
+     * @throws Exception
+     */
+    public void testTwoIntConst3() throws Exception {
+        IExpression[] args = new IExpression[] {
+                LANG_FACTORY.createLiteral(new Integer(10), Integer.class),
+                LANG_FACTORY.createLiteral(new Integer(6), Integer.class)           
+        };
+        // mod / Short
+        List<Class<?>> typeList = new ArrayList<Class<?>>(1);
+        typeList.add(Integer.class);
+        helpTestMod("MOD", typeList, args, "MOD(10, 6)"); //$NON-NLS-1$ //$NON-NLS-2$
+    }
+
+    /**
+     * Test {@link MODFunctionModifier#modify(IFunction)} to validate a call to 
+     * MOD(x,y) using {@link Integer} constants for both parameters returns 
+     * (x - (TRUNC((x / y), 0) * y)).  {@link MODFunctionModifier} will be 
+     * constructed with a function name of "MOD" and a supported type list which 
+     * does not contain {@link Integer}. 
+     * 
+     * @throws Exception
+     */
+    public void testTwoIntConst4() throws Exception {
+        IExpression[] args = new IExpression[] {
+                LANG_FACTORY.createLiteral(new Integer(10), Integer.class),
+                LANG_FACTORY.createLiteral(new Integer(6), Integer.class)           
+        };
+        // mod / Integer
+        List<Class<?>> typeList = new ArrayList<Class<?>>(1);
+        typeList.add(Short.class);
+        helpTestMod("MOD", typeList, args, "(10 - (TRUNC((10 / 6), 0) * 6))"); //$NON-NLS-1$ //$NON-NLS-2$
+    }
+
+    /**
+     * Test {@link MODFunctionModifier#modify(IFunction)} to validate a call to 
+     * x % y using {@link Integer} constants for both parameters returns (x % y).  
+     * {@link MODFunctionModifier} will be constructed with a function name of 
+     * "%" and no supported type list. 
+     * 
+     * @throws Exception
+     */
+    public void testTwoIntConst5() throws Exception {
+        IExpression[] args = new IExpression[] {
+        		LANG_FACTORY.createLiteral(new Integer(10), Integer.class),
+                LANG_FACTORY.createLiteral(new Integer(6), Integer.class)           
+        };
+        // % / default 
+        helpTestMod("%", null, args, "(10 % 6)"); //$NON-NLS-1$ //$NON-NLS-2$
+    }
+
+    /**
+     * Test {@link MODFunctionModifier#modify(IFunction)} to validate a call to 
+     * x % y using {@link Integer} constants for both parameters returns (x % y).  
+     * {@link MODFunctionModifier} will be constructed with a function name of 
+     * "%" and a supported type list which contains {@link Integer}. 
+     * 
+     * @throws Exception
+     */
+    public void testTwoIntConst6() throws Exception {
+        IExpression[] args = new IExpression[] {
+                LANG_FACTORY.createLiteral(new Integer(10), Integer.class),
+                LANG_FACTORY.createLiteral(new Integer(6), Integer.class)           
+        };
+        // % / Short
+        List<Class<?>> typeList = new ArrayList<Class<?>>(1);
+        typeList.add(Integer.class);
+        helpTestMod("%", typeList, args, "(10 % 6)"); //$NON-NLS-1$ //$NON-NLS-2$
+    }
+
+    /**
+     * Test {@link MODFunctionModifier#modify(IFunction)} to validate a call to 
+     * x % y using {@link Integer} constants for both parameters returns 
+     * (10 - (TRUNC((10 / 6), 0) * 6)).  {@link MODFunctionModifier} will be 
+     * constructed with a function name of "%" and a supported type list that 
+     * does not contain {@link Integer}. 
+     * 
+     * @throws Exception
+     */
+    public void testTwoIntConst7() throws Exception {
+        IExpression[] args = new IExpression[] {
+            LANG_FACTORY.createLiteral(new Integer(10), Integer.class),
+            LANG_FACTORY.createLiteral(new Integer(6), Integer.class)           
+        };
+        // % / Integer
+        List<Class<?>> typeList = new ArrayList<Class<?>>(1);
+        typeList.add(Short.class);
+        helpTestMod("%", typeList, args, "(10 - (TRUNC((10 / 6), 0) * 6))"); //$NON-NLS-1$ //$NON-NLS-2$
+    }
+
+    /**
+     * Test {@link MODFunctionModifier#modify(IFunction)} to validate a call to 
+     * MOD(x,y) using {@link Long} constants for both parameters returns 
+     * MOD(x,y).  {@link MODFunctionModifier} will be constructed without 
+     * specifying a function name or a supported type list.
+     * 
+     * @throws Exception
+     */
+    public void testTwoLongConst() throws Exception {
+        IExpression[] args = new IExpression[] {
+                LANG_FACTORY.createLiteral(new Long(10), Long.class),
+                LANG_FACTORY.createLiteral(new Long(6), Long.class)           
+        };
+        // default / default
+        helpTestMod(args, "MOD(10, 6)"); //$NON-NLS-1$
+    }
+
+    /**
+     * Test {@link MODFunctionModifier#modify(IFunction)} to validate a call to 
+     * MOD(x,y) using {@link Long} constants for both parameters returns 
+     * MOD(x,y).  {@link MODFunctionModifier} will be constructed with a 
+     * function name of "MOD" but without a supported type list.
+     *  
+     * @throws Exception
+     */
+    public void testTwoLongConst2() throws Exception {
+        IExpression[] args = new IExpression[] {
+                LANG_FACTORY.createLiteral(new Long(10), Long.class),
+                LANG_FACTORY.createLiteral(new Long(6), Long.class)           
+        };
+        // mod / default 
+        helpTestMod("MOD", null, args, "MOD(10, 6)"); //$NON-NLS-1$ //$NON-NLS-2$
+    }
+
+    /**
+     * Test {@link MODFunctionModifier#modify(IFunction)} to validate a call to 
+     * MOD(x,y) using {@link Long} constants for both parameters returns 
+     * MOD(x,y).  {@link MODFunctionModifier} will be constructed with a 
+     * function name of "MOD" and a supported type list which contains {@link Long}. 
+     * 
+     * @throws Exception
+     */
+    public void testTwoLongConst3() throws Exception {
+        IExpression[] args = new IExpression[] {
+                LANG_FACTORY.createLiteral(new Long(10), Long.class),
+                LANG_FACTORY.createLiteral(new Long(6), Long.class)           
+        };
+        // mod / Long
+        List<Class<?>> typeList = new ArrayList<Class<?>>(1);
+        typeList.add(Long.class);
+        helpTestMod("MOD", typeList, args, "MOD(10, 6)"); //$NON-NLS-1$ //$NON-NLS-2$
+    }
+
+    /**
+     * Test {@link MODFunctionModifier#modify(IFunction)} to validate a call to 
+     * MOD(x,y) using {@link Long} constants for both parameters returns 
+     * (x - (TRUNC((x / y), 0) * y)).  {@link MODFunctionModifier} will be 
+     * constructed with a function name of "MOD" and a supported type list which 
+     * does not contain {@link Long}. 
+     * 
+     * @throws Exception
+     */
+    public void testTwoLongConst4() throws Exception {
+        IExpression[] args = new IExpression[] {
+                LANG_FACTORY.createLiteral(new Long(10), Long.class),
+                LANG_FACTORY.createLiteral(new Long(6), Long.class)           
+        };
+        // mod / Short
+        List<Class<?>> typeList = new ArrayList<Class<?>>(1);
+        typeList.add(Short.class);
+        helpTestMod("MOD", typeList, args, "(10 - (TRUNC((10 / 6), 0) * 6))"); //$NON-NLS-1$ //$NON-NLS-2$
+    }
+
+    /**
+     * Test {@link MODFunctionModifier#modify(IFunction)} to validate a call to 
+     * x % y using {@link Long} constants for both parameters returns (x % y).  
+     * {@link MODFunctionModifier} will be constructed with a function name of 
+     * "%" and no supported type list. 
+     * 
+     * @throws Exception
+     */
+    public void testTwoLongConst5() throws Exception {
+        IExpression[] args = new IExpression[] {
+                LANG_FACTORY.createLiteral(new Long(10), Long.class),
+                LANG_FACTORY.createLiteral(new Long(6), Long.class)           
+        };
+        // % / default 
+        helpTestMod("%", null, args, "(10 % 6)"); //$NON-NLS-1$ //$NON-NLS-2$
+    }
+
+    /**
+     * Test {@link MODFunctionModifier#modify(IFunction)} to validate a call to 
+     * x % y using {@link Long} constants for both parameters returns (x % y).  
+     * {@link MODFunctionModifier} will be constructed with a function name of 
+     * "%" and a supported type list which contains {@link Long}. 
+     * 
+     * @throws Exception
+     */
+    public void testTwoLongConst6() throws Exception {
+        IExpression[] args = new IExpression[] {
+                LANG_FACTORY.createLiteral(new Long(10), Long.class),
+                LANG_FACTORY.createLiteral(new Long(6), Long.class)           
+        };
+        // % / Long
+        List<Class<?>> typeList = new ArrayList<Class<?>>(1);
+        typeList.add(Long.class);
+        helpTestMod("%", typeList, args, "(10 % 6)"); //$NON-NLS-1$ //$NON-NLS-2$
+    }
+
+    /**
+     * Test {@link MODFunctionModifier#modify(IFunction)} to validate a call to 
+     * x % y using {@link Long} constants for both parameters returns 
+     * (10 - (TRUNC((10 / 6), 0) * 6)).  {@link MODFunctionModifier} will be 
+     * constructed with a function name of "%" and a supported type list that 
+     * does not contain {@link Long}. 
+     * 
+     * @throws Exception
+     */
+    public void testTwoLongConst7() throws Exception {
+        IExpression[] args = new IExpression[] {
+                LANG_FACTORY.createLiteral(new Long(10), Long.class),
+                LANG_FACTORY.createLiteral(new Long(6), Long.class)           
+        };
+        // % / Short
+        List<Class<?>> typeList = new ArrayList<Class<?>>(1);
+        typeList.add(Short.class);
+        helpTestMod("%", typeList, args, "(10 - (TRUNC((10 / 6), 0) * 6))"); //$NON-NLS-1$ //$NON-NLS-2$
+    }
+
+    /**
+     * Test {@link MODFunctionModifier#modify(IFunction)} to validate a call to 
+     * MOD(x,y) using {@link Float} constants for both parameters returns 
+     * (x - (TRUNC((x / y), 0) * y)).  {@link MODFunctionModifier} will be 
+     * constructed without specifying a function name or a supported type list.
+     * 
+     * @throws Exception
+     */
+    public void testTwoFloatConst() throws Exception {
+        IExpression[] args = new IExpression[] {
+                LANG_FACTORY.createLiteral(new Float(10), Float.class),
+                LANG_FACTORY.createLiteral(new Float(6), Float.class)           
+        };
+        // default / default
+        helpTestMod(args, "(10.0 - (TRUNC((10.0 / 6.0), 0) * 6.0))"); //$NON-NLS-1$
+    }
+
+    /**
+     * Test {@link MODFunctionModifier#modify(IFunction)} to validate a call to 
+     * MOD(x,y) using {@link Float} constants for both parameters returns 
+     * (x - (TRUNC((x / y), 0) * y)).  {@link MODFunctionModifier} will be 
+     * constructed with a function name of "MOD" but without a supported type 
+     * list.
+     *  
+     * @throws Exception
+     */
+    public void testTwoFloatConst2() throws Exception {
+        IExpression[] args = new IExpression[] {
+                LANG_FACTORY.createLiteral(new Float(10), Float.class),
+                LANG_FACTORY.createLiteral(new Float(6), Float.class)           
+        };
+        // mod / default 
+        helpTestMod("MOD", null, args, "(10.0 - (TRUNC((10.0 / 6.0), 0) * 6.0))"); //$NON-NLS-1$ //$NON-NLS-2$
+    }
+
+    /**
+     * Test {@link MODFunctionModifier#modify(IFunction)} to validate a call to 
+     * MOD(x,y) using {@link Float} constants for both parameters returns 
+     * MOD(x,y).  {@link MODFunctionModifier} will be constructed with a 
+     * function name of "MOD" and a supported type list which contains {@link Float}. 
+     * 
+     * @throws Exception
+     */
+    public void testTwoFloatConst3() throws Exception {
+        IExpression[] args = new IExpression[] {
+                LANG_FACTORY.createLiteral(new Float(10), Float.class),
+                LANG_FACTORY.createLiteral(new Float(6), Float.class)           
+        };
+        // mod / Float
+        List<Class<?>> typeList = new ArrayList<Class<?>>(1);
+        typeList.add(Float.class);
+        helpTestMod("MOD", typeList, args, "MOD(10.0, 6.0)"); //$NON-NLS-1$ //$NON-NLS-2$
+    }
+
+    /**
+     * Test {@link MODFunctionModifier#modify(IFunction)} to validate a call to 
+     * MOD(x,y) using {@link Float} constants for both parameters returns 
+     * (x - (TRUNC((x / y), 0) * y)).  {@link MODFunctionModifier} will be 
+     * constructed with a function name of "MOD" and a supported type list which 
+     * does not contain {@link Float}. 
+     * 
+     * @throws Exception
+     */
+    public void testTwoFloatConst4() throws Exception {
+        IExpression[] args = new IExpression[] {
+                LANG_FACTORY.createLiteral(new Float(10), Float.class),
+                LANG_FACTORY.createLiteral(new Float(6), Float.class)           
+        };
+        // mod / Short
+        List<Class<?>> typeList = new ArrayList<Class<?>>(1);
+        typeList.add(Short.class);
+        helpTestMod("MOD", typeList, args, "(10.0 - (TRUNC((10.0 / 6.0), 0) * 6.0))"); //$NON-NLS-1$ //$NON-NLS-2$
+    }
+
+    /**
+     * Test {@link MODFunctionModifier#modify(IFunction)} to validate a call to 
+     * x % y using {@link Float} constants for both parameters returns  
+     * (x - (TRUNC((x / y), 0) * x)).  {@link MODFunctionModifier} will be 
+     * constructed with a function name of "%" and no supported type list. 
+     * 
+     * @throws Exception
+     */
+    public void testTwoFloatConst5() throws Exception {
+        IExpression[] args = new IExpression[] {
+                LANG_FACTORY.createLiteral(new Float(10), Float.class),
+                LANG_FACTORY.createLiteral(new Float(6), Float.class)           
+        };
+        // % / default 
+        helpTestMod("%", null, args, "(10.0 - (TRUNC((10.0 / 6.0), 0) * 6.0))"); //$NON-NLS-1$ //$NON-NLS-2$
+    }
+
+    /**
+     * Test {@link MODFunctionModifier#modify(IFunction)} to validate a call to 
+     * x % y using {@link Float} constants for both parameters returns (x % y).  
+     * {@link MODFunctionModifier} will be constructed with a function name of 
+     * "%" and a supported type list which contains {@link Float}. 
+     * 
+     * @throws Exception
+     */
+    public void testTwoFloatConst6() throws Exception {
+        IExpression[] args = new IExpression[] {
+                LANG_FACTORY.createLiteral(new Float(10), Float.class),
+                LANG_FACTORY.createLiteral(new Float(6), Float.class)           
+        };
+        // % / Float
+        List<Class<?>> typeList = new ArrayList<Class<?>>(1);
+        typeList.add(Float.class);
+        helpTestMod("%", typeList, args, "(10.0 % 6.0)"); //$NON-NLS-1$ //$NON-NLS-2$
+    }
+
+    /**
+     * Test {@link MODFunctionModifier#modify(IFunction)} to validate a call to 
+     * x % y using {@link Float} constants for both parameters returns 
+     * (x - (TRUNC((x / y), 0) * x)).  {@link MODFunctionModifier} will be 
+     * constructed with a function name of "%" and a supported type list that 
+     * does not contain {@link Float}. 
+     * 
+     * @throws Exception
+     */
+    public void testTwoFloatConst7() throws Exception {
+        IExpression[] args = new IExpression[] {
+                LANG_FACTORY.createLiteral(new Float(10), Float.class),
+                LANG_FACTORY.createLiteral(new Float(6), Float.class)           
+        };
+        // % / Short
+        List<Class<?>> typeList = new ArrayList<Class<?>>(1);
+        typeList.add(Short.class);
+        helpTestMod("%", typeList, args, "(10.0 - (TRUNC((10.0 / 6.0), 0) * 6.0))"); //$NON-NLS-1$ //$NON-NLS-2$
+    }
+
+    /**
+     * Test {@link MODFunctionModifier#modify(IFunction)} to validate a call to 
+     * MOD(x,y) using {@link BigInteger} constants for both parameters returns 
+     * (x - (TRUNC((x / y), 0) * y)).  {@link MODFunctionModifier} will be 
+     * constructed without specifying a function name or a supported type list.
+     * 
+     * @throws Exception
+     */
+    public void testTwoBigIntConst() throws Exception {
+        IExpression[] args = new IExpression[] {
+                LANG_FACTORY.createLiteral(new BigInteger("10"), BigInteger.class), //$NON-NLS-1$
+                LANG_FACTORY.createLiteral(new BigInteger("6"), BigInteger.class) //$NON-NLS-1$
+        };
+        // default / default
+        helpTestMod(args, "(10 - (TRUNC((10 / 6), 0) * 6))"); //$NON-NLS-1$
+    }
+
+    /**
+     * Test {@link MODFunctionModifier#modify(IFunction)} to validate a call to 
+     * MOD(x,y) using {@link BigInteger} constants for both parameters returns 
+     * (x - (TRUNC((x / y), 0) * y)).  {@link MODFunctionModifier} will be 
+     * constructed with a function name of "MOD" but without a supported type 
+     * list.
+     *  
+     * @throws Exception
+     */
+    public void testTwoBigIntConst2() throws Exception {
+        IExpression[] args = new IExpression[] {
+                LANG_FACTORY.createLiteral(new BigInteger("10"), BigInteger.class), //$NON-NLS-1$
+                LANG_FACTORY.createLiteral(new BigInteger("6"), BigInteger.class) //$NON-NLS-1$
+        };
+        // mod / default 
+        helpTestMod("MOD", null, args, "(10 - (TRUNC((10 / 6), 0) * 6))"); //$NON-NLS-1$ //$NON-NLS-2$
+    }
+
+    /**
+     * Test {@link MODFunctionModifier#modify(IFunction)} to validate a call to 
+     * MOD(x,y) using {@link BigInteger} constants for both parameters returns 
+     * MOD(x,y).  {@link MODFunctionModifier} will be constructed with a 
+     * function name of "MOD" and a supported type list which contains {@link BigInteger}. 
+     * 
+     * @throws Exception
+     */
+    public void testTwoBigIntConst3() throws Exception {
+        IExpression[] args = new IExpression[] {
+                LANG_FACTORY.createLiteral(new BigInteger("10"), BigInteger.class), //$NON-NLS-1$
+                LANG_FACTORY.createLiteral(new BigInteger("6"), BigInteger.class) //$NON-NLS-1$
+        };
+        // mod / BigInteger
+        List<Class<?>> typeList = new ArrayList<Class<?>>(1);
+        typeList.add(BigInteger.class);
+        helpTestMod("MOD", typeList, args, "MOD(10, 6)"); //$NON-NLS-1$ //$NON-NLS-2$
+    }
+
+    /**
+     * Test {@link MODFunctionModifier#modify(IFunction)} to validate a call to 
+     * MOD(x,y) using {@link BigInteger} constants for both parameters returns 
+     * (x - (TRUNC((x / y), 0) * y)).  {@link MODFunctionModifier} will be 
+     * constructed with a function name of "MOD" and a supported type list which 
+     * does not contain {@link BigInteger}. 
+     * 
+     * @throws Exception
+     */
+    public void testTwoBigIntConst4() throws Exception {
+        IExpression[] args = new IExpression[] {
+                LANG_FACTORY.createLiteral(new BigInteger("10"), BigInteger.class), //$NON-NLS-1$
+                LANG_FACTORY.createLiteral(new BigInteger("6"), BigInteger.class) //$NON-NLS-1$
+        };
+        // mod / Short
+        List<Class<?>> typeList = new ArrayList<Class<?>>(1);
+        typeList.add(Short.class);
+        helpTestMod("MOD", typeList, args, "(10 - (TRUNC((10 / 6), 0) * 6))"); //$NON-NLS-1$ //$NON-NLS-2$
+    }
+
+    /**
+     * Test {@link MODFunctionModifier#modify(IFunction)} to validate a call to 
+     * x % y using {@link BigInteger} constants for both parameters returns  
+     * (x - (TRUNC((x / y), 0) * x)).  {@link MODFunctionModifier} will be 
+     * constructed with a function name of "%" and no supported type list. 
+     * 
+     * @throws Exception
+     */
+    public void testTwoBigIntConst5() throws Exception {
+        IExpression[] args = new IExpression[] {
+                LANG_FACTORY.createLiteral(new BigInteger("10"), BigInteger.class), //$NON-NLS-1$
+                LANG_FACTORY.createLiteral(new BigInteger("6"), BigInteger.class) //$NON-NLS-1$
+        };
+        // % / default 
+        helpTestMod("%", null, args, "(10 - (TRUNC((10 / 6), 0) * 6))"); //$NON-NLS-1$ //$NON-NLS-2$
+    }
+
+    /**
+     * Test {@link MODFunctionModifier#modify(IFunction)} to validate a call to 
+     * x % y using {@link BigInteger} constants for both parameters returns 
+     * (x % y).  {@link MODFunctionModifier} will be constructed with a function 
+     * name of "%" and a supported type list which contains {@link BigInteger}. 
+     * 
+     * @throws Exception
+     */
+    public void testTwoBigIntConst6() throws Exception {
+        IExpression[] args = new IExpression[] {
+                LANG_FACTORY.createLiteral(new BigInteger("10"), BigInteger.class), //$NON-NLS-1$
+                LANG_FACTORY.createLiteral(new BigInteger("6"), BigInteger.class) //$NON-NLS-1$
+        };
+        // % / BigInteger
+        List<Class<?>> typeList = new ArrayList<Class<?>>(1);
+        typeList.add(BigInteger.class);
+        helpTestMod("%", typeList, args, "(10 % 6)"); //$NON-NLS-1$ //$NON-NLS-2$
+    }
+
+    /**
+     * Test {@link MODFunctionModifier#modify(IFunction)} to validate a call to 
+     * x % y using {@link BigInteger} constants for both parameters returns 
+     * (x - (TRUNC((x / y), 0) * x)).  {@link MODFunctionModifier} will be 
+     * constructed with a function name of "%" and a supported type list that 
+     * does not contain {@link BigInteger}. 
+     * 
+     * @throws Exception
+     */
+    public void testTwoBigIntConst7() throws Exception {
+        IExpression[] args = new IExpression[] {
+                LANG_FACTORY.createLiteral(new BigInteger("10"), BigInteger.class), //$NON-NLS-1$
+                LANG_FACTORY.createLiteral(new BigInteger("6"), BigInteger.class) //$NON-NLS-1$
+        };
+        // % / Short
+        List<Class<?>> typeList = new ArrayList<Class<?>>(1);
+        typeList.add(Short.class);
+        helpTestMod("%", typeList, args, "(10 - (TRUNC((10 / 6), 0) * 6))"); //$NON-NLS-1$ //$NON-NLS-2$
+    }
+
+    /**
+     * Test {@link MODFunctionModifier#modify(IFunction)} to validate a call to 
+     * MOD(x,y) using {@link BigDecimal} constants for both parameters returns 
+     * (x - (TRUNC((x / y), 0) * y)).  {@link MODFunctionModifier} will be 
+     * constructed without specifying a function name or a supported type list.
+     * 
+     * @throws Exception
+     */
+    public void testTwoBigDecConst() throws Exception {
+        IExpression[] args = new IExpression[] {
+                LANG_FACTORY.createLiteral(new BigDecimal("10"), BigDecimal.class), //$NON-NLS-1$
+                LANG_FACTORY.createLiteral(new BigDecimal("6"), BigDecimal.class) //$NON-NLS-1$
+        };
+        // default / default
+        helpTestMod(args, "(10 - (TRUNC((10 / 6), 0) * 6))"); //$NON-NLS-1$
+    }
+
+    /**
+     * Test {@link MODFunctionModifier#modify(IFunction)} to validate a call to 
+     * MOD(x,y) using {@link BigDecimal} constants for both parameters returns 
+     * (x - (TRUNC((x / y), 0) * y)).  {@link MODFunctionModifier} will be 
+     * constructed with a function name of "MOD" but without a supported type 
+     * list.
+     *  
+     * @throws Exception
+     */
+    public void testTwoBigDecConst2() throws Exception {
+        IExpression[] args = new IExpression[] {
+                LANG_FACTORY.createLiteral(new BigDecimal("10"), BigDecimal.class), //$NON-NLS-1$
+                LANG_FACTORY.createLiteral(new BigDecimal("6"), BigDecimal.class) //$NON-NLS-1$
+        };
+        // mod / default 
+        helpTestMod("MOD", null, args, "(10 - (TRUNC((10 / 6), 0) * 6))"); //$NON-NLS-1$ //$NON-NLS-2$
+    }
+
+    /**
+     * Test {@link MODFunctionModifier#modify(IFunction)} to validate a call to 
+     * MOD(x,y) using {@link BigDecimal} constants for both parameters returns 
+     * MOD(x,y).  {@link MODFunctionModifier} will be constructed with a 
+     * function name of "MOD" and a supported type list which contains {@link BigDecimal}. 
+     * 
+     * @throws Exception
+     */
+    public void testTwoBigDecConst3() throws Exception {
+        IExpression[] args = new IExpression[] {
+                LANG_FACTORY.createLiteral(new BigDecimal("10"), BigDecimal.class), //$NON-NLS-1$
+                LANG_FACTORY.createLiteral(new BigDecimal("6"), BigDecimal.class) //$NON-NLS-1$
+        };
+        // mod / BigDecimal
+        List<Class<?>> typeList = new ArrayList<Class<?>>(1);
+        typeList.add(BigDecimal.class);
+        helpTestMod("MOD", typeList, args, "MOD(10, 6)"); //$NON-NLS-1$ //$NON-NLS-2$
+    }
+
+    /**
+     * Test {@link MODFunctionModifier#modify(IFunction)} to validate a call to 
+     * MOD(x,y) using {@link BigDecimal} constants for both parameters returns 
+     * (x - (TRUNC((x / y), 0) * y)).  {@link MODFunctionModifier} will be 
+     * constructed with a function name of "MOD" and a supported type list which 
+     * does not contain {@link BigDecimal}. 
+     * 
+     * @throws Exception
+     */
+    public void testTwoBigDecConst4() throws Exception {
+        IExpression[] args = new IExpression[] {
+                LANG_FACTORY.createLiteral(new BigDecimal("10"), BigDecimal.class), //$NON-NLS-1$
+                LANG_FACTORY.createLiteral(new BigDecimal("6"), BigDecimal.class) //$NON-NLS-1$
+        };
+        // mod / Short
+        List<Class<?>> typeList = new ArrayList<Class<?>>(1);
+        typeList.add(Short.class);
+        helpTestMod("MOD", typeList, args, "(10 - (TRUNC((10 / 6), 0) * 6))"); //$NON-NLS-1$ //$NON-NLS-2$
+    }
+
+    /**
+     * Test {@link MODFunctionModifier#modify(IFunction)} to validate a call to 
+     * x % y using {@link BigDecimal} constants for both parameters returns  
+     * (x - (TRUNC((x / y), 0) * x)).  {@link MODFunctionModifier} will be 
+     * constructed with a function name of "%" and no supported type list. 
+     * 
+     * @throws Exception
+     */
+    public void testTwoBigDecConst5() throws Exception {
+        IExpression[] args = new IExpression[] {
+                LANG_FACTORY.createLiteral(new BigDecimal("10"), BigDecimal.class), //$NON-NLS-1$
+                LANG_FACTORY.createLiteral(new BigDecimal("6"), BigDecimal.class) //$NON-NLS-1$
+        };
+        // % / default 
+        helpTestMod("%", null, args, "(10 - (TRUNC((10 / 6), 0) * 6))"); //$NON-NLS-1$ //$NON-NLS-2$
+    }
+
+    /**
+     * Test {@link MODFunctionModifier#modify(IFunction)} to validate a call to 
+     * x % y using {@link BigDecimal} constants for both parameters returns 
+     * (x % y).  {@link MODFunctionModifier} will be constructed with a function 
+     * name of "%" and a supported type list which contains {@link BigDecimal}. 
+     * 
+     * @throws Exception
+     */
+    public void testTwoBigDecConst6() throws Exception {
+        IExpression[] args = new IExpression[] {
+                LANG_FACTORY.createLiteral(new BigDecimal("10"), BigDecimal.class), //$NON-NLS-1$
+                LANG_FACTORY.createLiteral(new BigDecimal("6"), BigDecimal.class) //$NON-NLS-1$
+        };
+        // % / BigDecimal
+        List<Class<?>> typeList = new ArrayList<Class<?>>(1);
+        typeList.add(BigDecimal.class);
+        helpTestMod("%", typeList, args, "(10 % 6)"); //$NON-NLS-1$ //$NON-NLS-2$
+    }
+
+    /**
+     * Test {@link MODFunctionModifier#modify(IFunction)} to validate a call to 
+     * x % y using {@link BigDecimal} constants for both parameters returns 
+     * (x - (TRUNC((x / y), 0) * x)).  {@link MODFunctionModifier} will be 
+     * constructed with a function name of "%" and a supported type list that 
+     * does not contain {@link BigDecimal}. 
+     * 
+     * @throws Exception
+     */
+    public void testTwoBigDecConst7() throws Exception {
+        IExpression[] args = new IExpression[] {
+                LANG_FACTORY.createLiteral(new BigDecimal("10"), BigDecimal.class), //$NON-NLS-1$
+                LANG_FACTORY.createLiteral(new BigDecimal("6"), BigDecimal.class) //$NON-NLS-1$
+        };
+        // % / Short
+        List<Class<?>> typeList = new ArrayList<Class<?>>(1);
+        typeList.add(Short.class);
+        helpTestMod("%", typeList, args, "(10 - (TRUNC((10 / 6), 0) * 6))"); //$NON-NLS-1$ //$NON-NLS-2$
+    }
+
+    /**
+     * Test {@link MODFunctionModifier#modify(IFunction)} to validate a call to 
+     * MOD(e1,y) using a {@link Integer} element and a {@link Integer} constant 
+     * for parameters returns MOD(e1,y).  {@link MODFunctionModifier} will be 
+     * constructed without specifying a function name or a supported type list.
+     * 
+     * @throws Exception
+     */
+    public void testOneIntElemOneIntConst() throws Exception {
+        IExpression[] args = new IExpression[] {
+                LANG_FACTORY.createElement("e1", null, null, Integer.class), //$NON-NLS-1$
+                LANG_FACTORY.createLiteral(new Integer(6), Integer.class)
+        };
+        // default / default
+        helpTestMod(args, "MOD(e1, 6)"); //$NON-NLS-1$
+    }
+
+    /**
+     * Test {@link MODFunctionModifier#modify(IFunction)} to validate a call to 
+     * MOD(e1,y) using a {@link Integer} element and a {@link Integer} constant 
+     * for parameters returns MOD(e1,y).  {@link MODFunctionModifier} will be 
+     * constructed with a function name of "MOD" but without a supported type 
+     * list.
+     *  
+     * @throws Exception
+     */
+    public void testOneIntElemOneIntConst2() throws Exception {
+        IExpression[] args = new IExpression[] {
+                LANG_FACTORY.createElement("e1", null, null, Integer.class), //$NON-NLS-1$
+                LANG_FACTORY.createLiteral(new Integer(6), Integer.class)
+        };
+        // mod / default 
+        helpTestMod("MOD", null, args, "MOD(e1, 6)"); //$NON-NLS-1$ //$NON-NLS-2$
+    }
+
+    /**
+     * Test {@link MODFunctionModifier#modify(IFunction)} to validate a call to 
+     * MOD(e1,y) using a {@link Integer} element and a {@link Integer} constant 
+     * for parameters returns MOD(e1,y).  {@link MODFunctionModifier} will be 
+     * constructed with a function name of "MOD" and a supported type list which 
+     * contains {@link Integer}. 
+     * 
+     * @throws Exception
+     */
+    public void testOneIntElemOneIntConst3() throws Exception {
+        IExpression[] args = new IExpression[] {
+                LANG_FACTORY.createElement("e1", null, null, Integer.class), //$NON-NLS-1$
+                LANG_FACTORY.createLiteral(new Integer(6), Integer.class)
+        };
+        // mod / Integer
+        List<Class<?>> typeList = new ArrayList<Class<?>>(1);
+        typeList.add(Integer.class);
+        helpTestMod("MOD", typeList, args, "MOD(e1, 6)"); //$NON-NLS-1$ //$NON-NLS-2$
+    }
+
+    /**
+     * Test {@link MODFunctionModifier#modify(IFunction)} to validate a call to 
+     * MOD(e1,y) using a {@link Integer} element and a {@link Integer} constant 
+     * for parameters returns (e1 - (TRUNC((e1 / y), 0) * y)).  
+     * {@link MODFunctionModifier} will be constructed with a function name of 
+     * "MOD" and a supported type list which does not contain {@link Integer}. 
+     * 
+     * @throws Exception
+     */
+    public void testOneIntElemOneIntConst4() throws Exception {
+        IExpression[] args = new IExpression[] {
+                LANG_FACTORY.createElement("e1", null, null, Integer.class), //$NON-NLS-1$
+                LANG_FACTORY.createLiteral(new Integer(6), Integer.class)
+        };
+        // mod / Short
+        List<Class<?>> typeList = new ArrayList<Class<?>>(1);
+        typeList.add(Short.class);
+        helpTestMod("MOD", typeList, args, "(e1 - (TRUNC((e1 / 6), 0) * 6))"); //$NON-NLS-1$ //$NON-NLS-2$
+    }
+
+    /**
+     * Test {@link MODFunctionModifier#modify(IFunction)} to validate a call to 
+     * e1 % y using a {@link Integer} element and a {@link Integer} constant for 
+     * parameters returns (e1 % y).  {@link MODFunctionModifier} will be 
+     * constructed with a function name of "%" and no supported type list. 
+     * 
+     * @throws Exception
+     */
+    public void testOneIntElemOneIntConst5() throws Exception {
+        IExpression[] args = new IExpression[] {
+                LANG_FACTORY.createElement("e1", null, null, Integer.class), //$NON-NLS-1$
+                LANG_FACTORY.createLiteral(new Integer(6), Integer.class)
+        };
+        // % / default 
+        helpTestMod("%", null, args, "(e1 % 6)"); //$NON-NLS-1$ //$NON-NLS-2$
+    }
+
+    /**
+     * Test {@link MODFunctionModifier#modify(IFunction)} to validate a call to 
+     * e1 % y using a {@link Integer} element and a {@link Integer} constant for 
+     * parameters returns (e1 % y).  {@link MODFunctionModifier} will be 
+     * constructed with a function name of "%" and a supported type list which 
+     * contains {@link Integer}. 
+     * 
+     * @throws Exception
+     */
+    public void testOneIntElemOneIntConst6() throws Exception {
+        IExpression[] args = new IExpression[] {
+                LANG_FACTORY.createElement("e1", null, null, Integer.class), //$NON-NLS-1$
+                LANG_FACTORY.createLiteral(new Integer(6), Integer.class)
+        };
+        // % / Integer
+        List<Class<?>> typeList = new ArrayList<Class<?>>(1);
+        typeList.add(Integer.class);
+        helpTestMod("%", typeList, args, "(e1 % 6)"); //$NON-NLS-1$ //$NON-NLS-2$
+    }
+
+    /**
+     * Test {@link MODFunctionModifier#modify(IFunction)} to validate a call to 
+     * e1 % y using a {@link Integer} element and a {@link Integer} constant for 
+     * parameters returns (e1 - (TRUNC((e1 / y), 0) * y)).  
+     * {@link MODFunctionModifier} will be constructed with a function name of 
+     * "%" and a supported type list that does not contain {@link Integer}. 
+     * 
+     * @throws Exception
+     */
+    public void testOneIntElemOneIntConst7() throws Exception {
+        IExpression[] args = new IExpression[] {
+                LANG_FACTORY.createElement("e1", null, null, Integer.class), //$NON-NLS-1$
+                LANG_FACTORY.createLiteral(new Integer(6), Integer.class)
+        };
+        // % / Short
+        List<Class<?>> typeList = new ArrayList<Class<?>>(1);
+        typeList.add(Short.class);
+        helpTestMod("%", typeList, args, "(e1 - (TRUNC((e1 / 6), 0) * 6))"); //$NON-NLS-1$ //$NON-NLS-2$
+    }
+
+    /**
+     * Test {@link MODFunctionModifier#modify(IFunction)} to validate a call to 
+     * MOD(e1,y) using a {@link BigDecimal} element and a {@link BigDecimal} 
+     * constant for parameters returns (e1 - (TRUNC((e1 / y), 0) * y)).  
+     * {@link MODFunctionModifier} will be constructed without specifying a 
+     * function name or a supported type list.
+     * 
+     * @throws Exception
+     */
+    public void testOneBigDecElemOneBigDecConst() throws Exception {
+        IExpression[] args = new IExpression[] {
+                LANG_FACTORY.createElement("e1", null, null, BigDecimal.class), //$NON-NLS-1$
+                LANG_FACTORY.createLiteral(new BigDecimal(6), BigDecimal.class)
+        };
+        // default / default
+        helpTestMod(args, "(e1 - (TRUNC((e1 / 6), 0) * 6))"); //$NON-NLS-1$
+    }
+
+    /**
+     * Test {@link MODFunctionModifier#modify(IFunction)} to validate a call to 
+     * MOD(e1,y) using a {@link BigDecimal} element and a {@link BigDecimal} 
+     * constant for parameters returns (e1 - (TRUNC((e1 / y), 0) * y)).  
+     * {@link MODFunctionModifier} will be constructed with a function name of 
+     * "MOD" but without a supported type list.
+     *  
+     * @throws Exception
+     */
+    public void testOneBigDecElemOneBigDecConst2() throws Exception {
+        IExpression[] args = new IExpression[] {
+                LANG_FACTORY.createElement("e1", null, null, BigDecimal.class), //$NON-NLS-1$
+                LANG_FACTORY.createLiteral(new BigDecimal(6), BigDecimal.class)
+        };
+        // mod / default 
+        helpTestMod("MOD", null, args, "(e1 - (TRUNC((e1 / 6), 0) * 6))"); //$NON-NLS-1$ //$NON-NLS-2$
+    }
+
+    /**
+     * Test {@link MODFunctionModifier#modify(IFunction)} to validate a call to 
+     * MOD(e1,y) using a {@link BigDecimal} element and a {@link BigDecimal} 
+     * constant for parameters returns MOD(e1,y).  {@link MODFunctionModifier} 
+     * will be constructed with a function name of "MOD" and a supported type 
+     * list which contains {@link BigDecimal}. 
+     * 
+     * @throws Exception
+     */
+    public void testOneBigDecElemOneBigDecConst3() throws Exception {
+        IExpression[] args = new IExpression[] {
+                LANG_FACTORY.createElement("e1", null, null, BigDecimal.class), //$NON-NLS-1$
+                LANG_FACTORY.createLiteral(new BigDecimal(6), BigDecimal.class)
+        };
+        // mod / Integer
+        List<Class<?>> typeList = new ArrayList<Class<?>>(1);
+        typeList.add(BigDecimal.class);
+        helpTestMod("MOD", typeList, args, "MOD(e1, 6)"); //$NON-NLS-1$ //$NON-NLS-2$
+    }
+
+    /**
+     * Test {@link MODFunctionModifier#modify(IFunction)} to validate a call to 
+     * MOD(e1,y) using a {@link BigDecimal} element and a {@link BigDecimal} 
+     * constant for parameters returns (e1 - (TRUNC((e1 / y), 0) * y)).  
+     * {@link MODFunctionModifier} will be constructed with a function name of 
+     * "MOD" and a supported type list which does not contain {@link BigDecimal}. 
+     * 
+     * @throws Exception
+     */
+    public void testOneBigDecElemOneBigDecConst4() throws Exception {
+        IExpression[] args = new IExpression[] {
+                LANG_FACTORY.createElement("e1", null, null, BigDecimal.class), //$NON-NLS-1$
+                LANG_FACTORY.createLiteral(new BigDecimal(6), BigDecimal.class)
+        };
+        // mod / Short
+        List<Class<?>> typeList = new ArrayList<Class<?>>(1);
+        typeList.add(Short.class);
+        helpTestMod("MOD", typeList, args, "(e1 - (TRUNC((e1 / 6), 0) * 6))"); //$NON-NLS-1$ //$NON-NLS-2$
+    }
+
+    /**
+     * Test {@link MODFunctionModifier#modify(IFunction)} to validate a call to 
+     * e1 % y using a {@link BigDecimal} element and a {@link BigDecimal} 
+     * constant for parameters returns (e1 % y).  {@link MODFunctionModifier} 
+     * will be constructed with a function name of "%" and no supported type 
+     * list. 
+     * 
+     * @throws Exception
+     */
+    public void testOneBigDecElemOneBigDecConst5() throws Exception {
+        IExpression[] args = new IExpression[] {
+                LANG_FACTORY.createElement("e1", null, null, BigDecimal.class), //$NON-NLS-1$
+                LANG_FACTORY.createLiteral(new BigDecimal(6), BigDecimal.class)
+        };
+        // % / default 
+        helpTestMod("%", null, args, "(e1 - (TRUNC((e1 / 6), 0) * 6))"); //$NON-NLS-1$ //$NON-NLS-2$
+    }
+
+    /**
+     * Test {@link MODFunctionModifier#modify(IFunction)} to validate a call to 
+     * e1 % y using a {@link BigDecimal} element and a {@link BigDecimal} 
+     * constant for parameters returns (e1 % y).  {@link MODFunctionModifier} 
+     * will be constructed with a function name of "%" and a supported type list 
+     * which contains {@link BigDecimal}. 
+     * 
+     * @throws Exception
+     */
+    public void testOneBigDecElemOneBigDecConst6() throws Exception {
+        IExpression[] args = new IExpression[] {
+                LANG_FACTORY.createElement("e1", null, null, BigDecimal.class), //$NON-NLS-1$
+                LANG_FACTORY.createLiteral(new BigDecimal(6), BigDecimal.class)
+        };
+        // % / BigDecimal
+        List<Class<?>> typeList = new ArrayList<Class<?>>(1);
+        typeList.add(BigDecimal.class);
+        helpTestMod("%", typeList, args, "(e1 % 6)"); //$NON-NLS-1$ //$NON-NLS-2$
+    }
+
+    /**
+     * Test {@link MODFunctionModifier#modify(IFunction)} to validate a call to 
+     * e1 % y using a {@link BigDecimal} element and a {@link BigDecimal} 
+     * constant for parameters returns (e1 - (TRUNC((e1 / y), 0) * y)).  
+     * {@link MODFunctionModifier} will be constructed with a function name of 
+     * "%" and a supported type list that does not contain {@link BigDecimal}. 
+     * 
+     * @throws Exception
+     */
+    public void testOneBigDecElemOneBigDecConst7() throws Exception {
+        IExpression[] args = new IExpression[] {
+                LANG_FACTORY.createElement("e1", null, null, BigDecimal.class), //$NON-NLS-1$
+                LANG_FACTORY.createLiteral(new BigDecimal(6), BigDecimal.class)
+        };
+        // % / Short
+        List<Class<?>> typeList = new ArrayList<Class<?>>(1);
+        typeList.add(Short.class);
+        helpTestMod("%", typeList, args, "(e1 - (TRUNC((e1 / 6), 0) * 6))"); //$NON-NLS-1$ //$NON-NLS-2$
+    }
+
+    /**
+     * Test {@link MODFunctionModifier#modify(IFunction)} to validate a call to 
+     * MOD(x,e1) using a {@link Float} literal and a {@link Float} element for 
+     * parameters returns (x - (floor((x / e1)) * e1)).  {@link MODFunctionModifier} 
+     * will be constructed with a function name of "MOD" and no supported type 
+     * list.  The test explicitly overrides 
+     * {@link MODFunctionModifier#getQuotientExpression(IExpression)} to produce 
+     * output that uses the floor(z) function. 
+     * 
+     * @throws Exception
+     */
+    public void testOverrideGetQuotient() throws Exception {
+    	final Class<?> dataType = Float.class;
+    	final String modFunctionName = "MOD"; //$NON-NLS-1$
+    	final String expectedStr = "(1000.23 - (floor((1000.23 / e1)) * e1))"; //$NON-NLS-1$
+    	
+        IExpression[] args = new IExpression[] {
+                LANG_FACTORY.createLiteral(new Float(1000.23), dataType),
+                LANG_FACTORY.createElement("e1", null, null, dataType), //$NON-NLS-1$
+        };
+    	IFunction func = LANG_FACTORY.createFunction(modFunctionName, args, dataType);
+
+    	final Translator trans = new Translator() {
+			@Override
+			public void initialize(ConnectorEnvironment env)
+					throws ConnectorException {
+				super.initialize(env);
+				registerFunctionModifier(SourceSystemFunctions.MOD, new MODFunctionModifier(getLanguageFactory(), modFunctionName, null) {
+					@Override
+					protected IExpression getQuotientExpression(
+							IExpression division) {
+						return getLanguageFactory().createFunction("floor", Arrays.asList(division), division.getType()); //$NON-NLS-1$
+					}
+					
+				});
+			}
+    	};
+
+        trans.initialize(EnvironmentUtility.createEnvironment(new Properties(), false));
+
+        IExpression expr = trans.getFunctionModifiers().get(SourceSystemFunctions.MOD).modify(func);
+        SQLConversionVisitor sqlVisitor = trans.getSQLConversionVisitor(); 
+        sqlVisitor.append(expr);  
+        assertEquals("Modified function does not match", expectedStr, sqlVisitor.toString()); //$NON-NLS-1$
+    }
+}


Property changes on: trunk/connectors/connector-jdbc/src/test/java/org/teiid/connector/jdbc/translator/TestMODFunctionModifier.java
___________________________________________________________________
Name: svn:mime-type
   + text/plain



More information about the teiid-commits mailing list