[teiid-commits] teiid SVN: r1884 - in trunk: engine/src/main/java/com/metamatrix/query/function and 1 other directories.

teiid-commits at lists.jboss.org teiid-commits at lists.jboss.org
Mon Mar 1 16:33:09 EST 2010


Author: shawkins
Date: 2010-03-01 16:33:09 -0500 (Mon, 01 Mar 2010)
New Revision: 1884

Modified:
   trunk/common-core/src/main/java/com/metamatrix/common/types/DataTypeManager.java
   trunk/engine/src/main/java/com/metamatrix/query/function/FunctionLibrary.java
   trunk/engine/src/test/java/com/metamatrix/query/function/TestFunctionLibrary.java
Log:
TEIID-1004 adding a check to filter nan/infinite values

Modified: trunk/common-core/src/main/java/com/metamatrix/common/types/DataTypeManager.java
===================================================================
--- trunk/common-core/src/main/java/com/metamatrix/common/types/DataTypeManager.java	2010-03-01 21:26:34 UTC (rev 1883)
+++ trunk/common-core/src/main/java/com/metamatrix/common/types/DataTypeManager.java	2010-03-01 21:33:09 UTC (rev 1884)
@@ -97,7 +97,6 @@
 	private static class HashedValueCache<T> implements ValueCache<T> {
 		
 		final Object[] cache;
-		final boolean weak = false;
 		
 		HashedValueCache(int size) {
 			cache = new Object[1 << size];
@@ -842,10 +841,9 @@
     		}
     		//TODO: this initial lookup is inefficient, since there are likely collisions
 	    	ValueCache valueCache = valueMaps.get(value.getClass());
-	    	if (valueCache == null) {
-	    		return value;
+	    	if (valueCache != null) {
+	    		value = (T)valueCache.getValue(value);
 	    	}
-	    	return (T)valueCache.getValue(value);
     	}
 		return value;
     }

Modified: trunk/engine/src/main/java/com/metamatrix/query/function/FunctionLibrary.java
===================================================================
--- trunk/engine/src/main/java/com/metamatrix/query/function/FunctionLibrary.java	2010-03-01 21:26:34 UTC (rev 1883)
+++ trunk/engine/src/main/java/com/metamatrix/query/function/FunctionLibrary.java	2010-03-01 21:33:09 UTC (rev 1884)
@@ -31,6 +31,7 @@
 import com.metamatrix.api.exception.query.QueryResolverException;
 import com.metamatrix.common.types.DataTypeManager;
 import com.metamatrix.common.types.TransformationException;
+import com.metamatrix.common.util.PropertiesUtils;
 import com.metamatrix.query.QueryPlugin;
 import com.metamatrix.query.function.metadata.FunctionMethod;
 import com.metamatrix.query.function.metadata.FunctionParameter;
@@ -45,8 +46,10 @@
  * functions are available, resolve function signatures, and invoke system
  * and user-defined functions.
  */
-public class FunctionLibrary {
-
+public class FunctionLibrary {
+	
+	private static final boolean ALLOW_NAN_INFINITY = PropertiesUtils.getBooleanProperty(System.getProperties(), "org.teiid.allowNanInfinity", false); //$NON-NLS-1$
+	
 	// Special type conversion functions
 	public static final String CONVERT = "convert"; //$NON-NLS-1$
 	public static final String CAST = "cast"; //$NON-NLS-1$
@@ -393,6 +396,19 @@
         		values = newValues;
         	}
             Object result = method.invoke(null, values);
+            if (!ALLOW_NAN_INFINITY) {
+        		if (result instanceof Double) {
+	            	Double floatVal = (Double)result;
+	            	if (Double.isInfinite(floatVal) || Double.isNaN(floatVal)) {
+	            		throw new FunctionExecutionException(new ArithmeticException("Infinite or invalid result"), ErrorMessageKeys.FUNCTION_0003, QueryPlugin.Util.getString(ErrorMessageKeys.FUNCTION_0003, fd.getName())); //$NON-NLS-1$
+	            	}
+	            } else if (result instanceof Float) {
+	            	Float floatVal = (Float)result;
+	            	if (Float.isInfinite(floatVal) || Float.isNaN(floatVal)) {
+	            		throw new FunctionExecutionException(new ArithmeticException("Infinite or invalid result"), ErrorMessageKeys.FUNCTION_0003, QueryPlugin.Util.getString(ErrorMessageKeys.FUNCTION_0003, fd.getName())); //$NON-NLS-1$
+	            	}
+	            }
+        	}
             result = DataTypeManager.convertToRuntimeType(result);
             result = DataTypeManager.transformValue(result, fd.getReturnType());
             return result;

Modified: trunk/engine/src/test/java/com/metamatrix/query/function/TestFunctionLibrary.java
===================================================================
--- trunk/engine/src/test/java/com/metamatrix/query/function/TestFunctionLibrary.java	2010-03-01 21:26:34 UTC (rev 1883)
+++ trunk/engine/src/test/java/com/metamatrix/query/function/TestFunctionLibrary.java	2010-03-01 21:33:09 UTC (rev 1884)
@@ -168,19 +168,31 @@
 	}
 
 	private void helpInvokeMethod(String fname, Object[] inputs, Object expectedOutput) {
-        // Build type signature
-        Class[] types = new Class[inputs.length];
-        for(int i=0; i<inputs.length; i++) { 
-            types[i] = DataTypeManager.determineDataTypeClass(inputs[i]);   
-        }        
         try {
-            helpInvokeMethod(fname, types, inputs, new CommandContext(), expectedOutput);
+            helpInvokeMethod(fname, null, inputs, null, expectedOutput);
         } catch (Exception err) {
             throw new RuntimeException(err);
         } 
 	}
     
-    private void helpInvokeMethod(String fname, Class[] types, Object[] inputs, CommandContext context , Object expectedOutput) throws InvalidFunctionException, FunctionExecutionException {
+    private void helpInvokeMethod(String fname, Class[] types, Object[] inputs, CommandContext context, Object expectedOutput) throws InvalidFunctionException, FunctionExecutionException {
+    	Object actualOutput = helpInvokeMethod(fname, types, inputs, context);
+        assertEquals("Actual function output not equal to expected: ", expectedOutput, actualOutput); //$NON-NLS-1$
+    }
+
+	private Object helpInvokeMethod(String fname, Class[] types,
+			Object[] inputs, CommandContext context)
+			throws InvalidFunctionException, FunctionExecutionException {
+		if (types == null) {
+            // Build type signature
+            types = new Class[inputs.length];
+            for(int i=0; i<inputs.length; i++) { 
+                types[i] = DataTypeManager.determineDataTypeClass(inputs[i]);   
+            }        
+    	}
+    	if (context == null) {
+    		context = new CommandContext();
+    	}
         Object actualOutput = null;
         // Find function descriptor
         FunctionDescriptor descriptor = library.findFunction(fname, types);         
@@ -197,64 +209,18 @@
             // Invoke function with inputs
             actualOutput = library.invokeFunction(descriptor, inputs);                
         }
-        assertEquals("Actual function output not equal to expected: ", expectedOutput, actualOutput); //$NON-NLS-1$
-    }
+		return actualOutput;
+	}
     	    
-	private void helpInvokeMethodFail(String fname, Object[] inputs, Object expectedException) {
-		Object actualOutput = null;
-		try {
-			// Build type signature
-			Class[] types = new Class[inputs.length];
-			for(int i=0; i<inputs.length; i++) { 
-				types[i] = DataTypeManager.determineDataTypeClass(inputs[i]);   
-			}
-		    
-            // Find function descriptor
-            FunctionDescriptor descriptor = library.findFunction(fname, types);         
-            if (descriptor != null && descriptor.requiresContext()) {
-                // Invoke function with inputs
-                Object[] in = new Object[inputs.length+1];
-                in[0] = new CommandContext();
-                for (int i = 0; i < inputs.length; i++) {
-                    in[i+1] = inputs[i];
-                }
-                actualOutput = library.invokeFunction(descriptor, in);
-            }
-            else {
-                // Invoke function with inputs
-                actualOutput = library.invokeFunction(descriptor, inputs);                
-            }	  
-		    
-		} catch(Throwable e) { 
-			//e.printStackTrace();
-			assertNull(actualOutput);
-			assertEquals("Unexpected exception.", e.getClass().getName(), ((FunctionExecutionException)expectedException).getClass().getName());    //$NON-NLS-1$
-		}    
+	private void helpInvokeMethodFail(String fname, Object[] inputs) throws InvalidFunctionException {
+		   helpInvokeMethodFail(fname, null, inputs);
 	}	
     	
-    private void helpInvokeMethodFail(String fname, Class types[], Object[] inputs, Object expectedException) {
-        Object actualOutput = null;
-        try {            
-            // Find function descriptor
-            FunctionDescriptor descriptor = library.findFunction(fname, types);         
-            if (descriptor != null && descriptor.requiresContext()) {
-                // Invoke function with inputs
-                Object[] in = new Object[inputs.length+1];
-                in[0] = new CommandContext();
-                for (int i = 0; i < inputs.length; i++) {
-                    in[i+1] = inputs[i];
-                }
-                actualOutput = library.invokeFunction(descriptor, in);
-            }
-            else {
-                // Invoke function with inputs
-                actualOutput = library.invokeFunction(descriptor, inputs);                
-            }     
-            
-        } catch(Throwable e) { 
-            //e.printStackTrace();
-            assertNull(actualOutput);
-            assertEquals("Unexpected exception.", e.getClass().getName(), ((FunctionExecutionException)expectedException).getClass().getName());    //$NON-NLS-1$
+    private void helpInvokeMethodFail(String fname, Class<?> types[], Object[] inputs) throws InvalidFunctionException {
+    	try {
+            helpInvokeMethod(fname, types, inputs, null);
+            fail("expected exception"); //$NON-NLS-1$
+        } catch (FunctionExecutionException err) {
         }    
     }    
 	// ################################## ACTUAL TESTS ################################
@@ -635,6 +601,10 @@
         helpInvokeMethod("/", new Object[] { new BigDecimal("3"), new BigDecimal("2") }, new BigDecimal("2"));   //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$ //$NON-NLS-4$
     }
     
+    @Test public void testInvokeDivide7() throws Exception {
+        helpInvokeMethodFail("/", new Object[] { new Float("3"), new Float("0") });   //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$ //$NON-NLS-4$
+    }
+    
     @Test public void testInvokeDivideMod() {
         helpInvokeMethod("mod", new Object[] { new BigDecimal("3.1"), new BigDecimal("2") }, new BigDecimal("1.1"));   //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$ //$NON-NLS-4$
     }
@@ -802,9 +772,8 @@
 			helpInvokeMethod("formatTimestamp", new Object[] {TimestampUtil.createTimestamp(103, 2, 5, 3, 4, 12, 255), new String("yyyy-mm-dd hh:mm:ss.SSSS") }, "2003-04-05 03:04:12.0000");	 //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$
 	}
 		
-	@Test public void testInvokeFormatTimestampFail() {
-		helpInvokeMethodFail("formatTimestamp", new Object[] {TimestampUtil.createTimestamp(103, 2, 5, 3, 4, 12, 255), new String("mm/dd/nn h:mm a") },  //$NON-NLS-1$ //$NON-NLS-2$
-			new FunctionExecutionException("")); //$NON-NLS-1$
+	@Test public void testInvokeFormatTimestampFail() throws Exception {
+		helpInvokeMethodFail("formatTimestamp", new Object[] {TimestampUtil.createTimestamp(103, 2, 5, 3, 4, 12, 255), new String("mm/dd/nn h:mm a") }); //$NON-NLS-1$
 	}
 	
 	@Test public void testInvokeParseTimestamp1() {
@@ -991,15 +960,15 @@
 	}
 
 	/** should fail, with start > string1.length() */
-	@Test public void testInvokeInsert4() {
+	@Test public void testInvokeInsert4() throws Exception {
 		helpInvokeMethodFail("insert", new Object[] {new String(""), new Integer(2),  //$NON-NLS-1$ //$NON-NLS-2$
-			new Integer(0), new String("cat")}, new FunctionExecutionException("")); //$NON-NLS-1$ //$NON-NLS-2$
+			new Integer(0), new String("cat")}); //$NON-NLS-1$ //$NON-NLS-2$
 	}
 
 	/** should fail, with length > 0 and input string1.length() = 0 */
-	@Test public void testInvokeInsert5() {
+	@Test public void testInvokeInsert5() throws Exception {
 		helpInvokeMethodFail("insert", new Object[] {new String(""), new Integer(1),  //$NON-NLS-1$ //$NON-NLS-2$
-			new Integer(1), new String("cat")}, new FunctionExecutionException(""));	 //$NON-NLS-1$ //$NON-NLS-2$
+			new Integer(1), new String("cat")});	 //$NON-NLS-1$ //$NON-NLS-2$
 	}
 
 	/**  (length + start) > string1.length(), then just append str2 starting at start position */
@@ -1210,11 +1179,10 @@
         helpInvokeMethod("modifyTimeZone", new Object[] {ts, "America/New_York" }, out); //$NON-NLS-1$ //$NON-NLS-2$
     }
 
-    @Test public void testInvokeRand() {
+    @Test public void testInvokeRand() throws Exception {
         helpInvokeMethod("rand", new Object[] {new Integer(100)}, new Double(0.7220096548596434)); //$NON-NLS-1$ 
-        helpInvokeMethodFail("rand", new Class[] {Integer.class}, new Object[] {new Double(100)}, new FunctionExecutionException("")); //$NON-NLS-1$ //$NON-NLS-2$
         // this does not actually fail but returns a result
-        helpInvokeMethodFail("rand", new Class[] {Integer.class}, new Object[] {null}, new FunctionExecutionException("")); //$NON-NLS-1$ //$NON-NLS-2$
+        assertNotNull(helpInvokeMethod("rand", new Class[] {Integer.class}, new Object[] {null}, null)); //$NON-NLS-1$
     }
     
     @Test public void testInvokeUser() throws Exception {
@@ -1271,6 +1239,10 @@
         helpInvokeMethod("log10", new Object[] { new Double("10") }, new Double("1")); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$
     }
     
+    @Test public void testInvokeLog10Error() throws Exception {
+        helpInvokeMethodFail("log10", new Object[] { new Double("0") }); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$
+    }
+    
     @Test public void testInvokePower() {
         helpInvokeMethod("power", new Object[] { new Double("10"), new Double("2") }, new Double("100")); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$ //$NON-NLS-4$
     }



More information about the teiid-commits mailing list