[teiid-commits] teiid SVN: r2764 - in trunk: documentation/reference/src/main/docbook/en-US/content and 5 other directories.

teiid-commits at lists.jboss.org teiid-commits at lists.jboss.org
Wed Dec 8 15:55:36 EST 2010


Author: shawkins
Date: 2010-12-08 15:55:34 -0500 (Wed, 08 Dec 2010)
New Revision: 2764

Added:
   trunk/engine/src/test/java/org/teiid/query/function/TestFunctionMethods.java
Modified:
   trunk/api/src/main/java/org/teiid/metadata/FunctionMethod.java
   trunk/documentation/reference/src/main/docbook/en-US/content/scalar_functions.xml
   trunk/engine/src/main/java/org/teiid/query/function/FunctionMethods.java
   trunk/engine/src/main/java/org/teiid/query/function/FunctionTree.java
   trunk/engine/src/main/java/org/teiid/query/function/metadata/FunctionMethod.java
   trunk/engine/src/main/java/org/teiid/query/function/source/SystemSource.java
   trunk/engine/src/main/resources/org/teiid/query/i18n.properties
   trunk/engine/src/test/java/org/teiid/query/function/TestFunctionLibrary.java
Log:
TEIID-1385 adding support for an unescape method to handle escape sequences in strings

Modified: trunk/api/src/main/java/org/teiid/metadata/FunctionMethod.java
===================================================================
--- trunk/api/src/main/java/org/teiid/metadata/FunctionMethod.java	2010-12-08 16:34:59 UTC (rev 2763)
+++ trunk/api/src/main/java/org/teiid/metadata/FunctionMethod.java	2010-12-08 20:55:34 UTC (rev 2764)
@@ -22,7 +22,6 @@
 
 package org.teiid.metadata;
 
-import java.io.Serializable;
 import java.util.Arrays;
 
 import javax.xml.bind.annotation.XmlAttribute;
@@ -55,7 +54,7 @@
  *
  * @see FunctionParameter
  */
-public class FunctionMethod extends AbstractMetadataRecord implements Serializable {
+public class FunctionMethod extends AbstractMetadataRecord {
 	private static final long serialVersionUID = -8039086494296455152L;
 
 	private static final String NOT_ALLOWED = "NOT_ALLOWED"; //$NON-NLS-1$
@@ -101,7 +100,7 @@
     private PushDown pushdown = PushDown.CAN_PUSHDOWN;
     private String invocationClass;
     private String invocationMethod;
-    private boolean nullDependent;
+    private boolean nullOnNull;
     
     private Determinism determinism = Determinism.DETERMINISTIC;
         
@@ -439,14 +438,14 @@
     }
 
     /**
-     * Returns true if the function can produce a non-null output from a null parameter
+     * Returns true if the function returns null on any null input
      */
     public boolean isNullOnNull() {
-        return this.nullDependent;
+        return this.nullOnNull;
     }
     
-    public void setNullOnNull(boolean nullSafe) {
-        this.nullDependent = nullSafe;
+    public void setNullOnNull(boolean nullOnNull) {
+        this.nullOnNull = nullOnNull;
     }
 
     public Determinism getDeterminism() {

Modified: trunk/documentation/reference/src/main/docbook/en-US/content/scalar_functions.xml
===================================================================
--- trunk/documentation/reference/src/main/docbook/en-US/content/scalar_functions.xml	2010-12-08 16:34:59 UTC (rev 2763)
+++ trunk/documentation/reference/src/main/docbook/en-US/content/scalar_functions.xml	2010-12-08 20:55:34 UTC (rev 2764)
@@ -1072,6 +1072,18 @@
               <para>x in {string}</para>
             </entry>
           </row>
+          <row>
+            <entry>
+              <para>UNESCAPE(x)</para>
+            </entry>
+            <entry>
+              <para>Unescaped version of x.  Possible escape sequences are \b - backspace, \t - tab, \n - line feed, \f - form feed, \r - carriage return.  \uXXXX, where X is a hex value, can be used to specify any unicode character.  \XXX, where X is an octal digit, can be used to specify an octal byte value.  
+              If any other character appears after an escape character, that character will appear in the output and the escape character will be ignored.</para>
+            </entry>
+            <entry>
+              <para>x in {string}</para>
+            </entry>
+          </row>
         </tbody>
       </tgroup>
     </informaltable>

Modified: trunk/engine/src/main/java/org/teiid/query/function/FunctionMethods.java
===================================================================
--- trunk/engine/src/main/java/org/teiid/query/function/FunctionMethods.java	2010-12-08 16:34:59 UTC (rev 2763)
+++ trunk/engine/src/main/java/org/teiid/query/function/FunctionMethods.java	2010-12-08 20:55:34 UTC (rev 2764)
@@ -1304,5 +1304,75 @@
     	}
     	return Charset.forName(encoding);
 	}
+
+    public static String unescape(String string) {
+    	StringBuilder sb = new StringBuilder();
+    	boolean escaped = false;
+    	for (int i = 0; i < string.length(); i++) {
+    		char c = string.charAt(i);
+    		if (escaped) {
+	    		switch (c) {
+	    		case 'b':
+	    			sb.append('\b');
+	    			break;
+	    		case 't':
+	    			sb.append('\t');
+	    			break;
+	    		case 'n':
+	    			sb.append('\n');
+	    			break;
+	    		case 'f':
+	    			sb.append('\f');
+	    			break;
+	    		case 'r':
+	    			sb.append('\r');
+	    			break;
+	    		case 'u':
+					i = parseNumericValue(string, sb, i, 0, 4, 4);
+					//TODO: this should probably be strict about needing 4 digits
+	    			break;
+    			default:
+    				int value = Character.digit(c, 8);
+					if (value == -1) {
+						sb.append(c);
+					} else {
+						int possibleDigits = value < 3 ? 2:1;
+						int radixExp = 3;
+    					i = parseNumericValue(string, sb, i, value, possibleDigits, radixExp);
+    				}
+	    		}
+	    		escaped = false;
+    		} else {
+    			if (c == '\\') {
+    				escaped = true;
+    			} else {
+					sb.append(c);
+    			}
+    		}
+    	}
+    	//TODO: should this be strict?
+    	//if (escaped) {
+    		//throw new FunctionExecutionException();
+    	//}
+    	return sb.toString();
+    }
+
+	private static int parseNumericValue(String string, StringBuilder sb,
+			int i, int value, int possibleDigits, int radixExp) {
+		for (int j = 0; j < possibleDigits; j++) {
+			if (i + 1 == string.length()) {
+				break;
+			}
+			char digit = string.charAt(i + 1);
+			int val = Character.digit(digit, 1 << radixExp);
+			if (val == -1) {
+				break;
+			}
+			i++;
+			value = (value << radixExp) + val;
+		}
+		sb.append((char)value);
+		return i;
+	}
     
 }

Modified: trunk/engine/src/main/java/org/teiid/query/function/FunctionTree.java
===================================================================
--- trunk/engine/src/main/java/org/teiid/query/function/FunctionTree.java	2010-12-08 16:34:59 UTC (rev 2763)
+++ trunk/engine/src/main/java/org/teiid/query/function/FunctionTree.java	2010-12-08 20:55:34 UTC (rev 2764)
@@ -329,7 +329,7 @@
             inputTypes.add(0, CommandContext.class);
         }
 
-        FunctionDescriptor descriptor = new FunctionDescriptor(method.getName(), method.getPushdown(), types, outputType, invocationMethod, requiresContext, method.isNullOnNull(), method.getDeterminism());
+        FunctionDescriptor descriptor = new FunctionDescriptor(method.getName(), method.getPushdown(), types, outputType, invocationMethod, requiresContext, !method.isNullOnNull(), method.getDeterminism());
         // Store this path in the function tree
         
         int index = -1;

Modified: trunk/engine/src/main/java/org/teiid/query/function/metadata/FunctionMethod.java
===================================================================
--- trunk/engine/src/main/java/org/teiid/query/function/metadata/FunctionMethod.java	2010-12-08 16:34:59 UTC (rev 2763)
+++ trunk/engine/src/main/java/org/teiid/query/function/metadata/FunctionMethod.java	2010-12-08 20:55:34 UTC (rev 2764)
@@ -45,24 +45,8 @@
     public FunctionMethod(String name, String description, String category, 
         String invocationClass, String invocationMethod, 
         FunctionParameter[] inputParams, FunctionParameter outputParam) {
-        this(name, description, category, invocationClass, invocationMethod, inputParams, outputParam, Determinism.DETERMINISTIC);
+        super(name, description, category, PushDown.CAN_PUSHDOWN, invocationClass, invocationMethod, inputParams, outputParam, true, Determinism.DETERMINISTIC);
     }
-    
-    /**
-     * Construct a function method with default pushdown and null dependent attributes.
-     * @param name Function name
-     * @param description Function description
-     * @param category Function category
-     * @param invocationClass Invocation class
-     * @param invocationMethod Invocation method
-     * @param inputParams Input parameters
-     * @param outputParam Output parameter (return parameter)
-     */
-    public FunctionMethod(String name, String description, String category, 
-        String invocationClass, String invocationMethod, 
-        FunctionParameter[] inputParams, FunctionParameter outputParam, Determinism deterministic) {
-        super(name, description, category, PushDown.CAN_PUSHDOWN, invocationClass, invocationMethod, inputParams, outputParam, false, deterministic);
-    }
 
     /**
      * Construct a function method with all parameters assuming null dependent and non-deterministic.
@@ -77,13 +61,9 @@
     public FunctionMethod(String name, String description, String category, 
         PushDown pushdown, String invocationClass, String invocationMethod, 
         FunctionParameter[] inputParams, FunctionParameter outputParam) {
-        super(name, description, category, pushdown, invocationClass, invocationMethod, inputParams, outputParam, true,Determinism.NONDETERMINISTIC);
+        super(name, description, category, pushdown, invocationClass, invocationMethod, inputParams, outputParam, false,Determinism.NONDETERMINISTIC);
     }
     
-    public FunctionMethod(String name, String description, String category, FunctionParameter[] inputParams, FunctionParameter outputParam) {
-    	super(name, description, category, PushDown.MUST_PUSHDOWN, null, null, inputParams, outputParam, false, Determinism.DETERMINISTIC);
-    } 
-    
     public FunctionMethod(String name,
             String description,
             String category,
@@ -94,6 +74,6 @@
             FunctionParameter outputParam,
             boolean nullDependent,
             Determinism deterministic) {
-    	super(name, description, category, pushdown, invocationClass, invocationMethod, inputParams, outputParam, nullDependent, deterministic);
+    	super(name, description, category, pushdown, invocationClass, invocationMethod, inputParams, outputParam, !nullDependent, deterministic);
     }
 }

Modified: trunk/engine/src/main/java/org/teiid/query/function/source/SystemSource.java
===================================================================
--- trunk/engine/src/main/java/org/teiid/query/function/source/SystemSource.java	2010-12-08 16:34:59 UTC (rev 2763)
+++ trunk/engine/src/main/java/org/teiid/query/function/source/SystemSource.java	2010-12-08 20:55:34 UTC (rev 2764)
@@ -191,9 +191,19 @@
         	}
         	addTypedCoalesceFunction(type);
         }
+        
+        addUnescape();
     }
 
-    private void addSecurityFunctions() {
+    private void addUnescape() {
+    	functions.add(new FunctionMethod("unescape", QueryPlugin.Util.getString("SystemSource.unescape_desc"), STRING, PushDown.CANNOT_PUSHDOWN, FUNCTION_CLASS, "unescape", //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$
+                new FunctionParameter[] { 
+                    new FunctionParameter("string", DataTypeManager.DefaultDataTypes.STRING, QueryPlugin.Util.getString("SystemSource.unescape_param1"))}, //$NON-NLS-1$ //$NON-NLS-2$
+                new FunctionParameter("result", DataTypeManager.DefaultDataTypes.STRING, QueryPlugin.Util.getString("SystemSource.unescape_result")), false, Determinism.DETERMINISTIC ) );       //$NON-NLS-1$ //$NON-NLS-2$
+
+	}
+
+	private void addSecurityFunctions() {
         functions.add(new FunctionMethod("hasRole", QueryPlugin.Util.getString("SystemSource.hasRole_description"), SECURITY, PushDown.CANNOT_PUSHDOWN, SECURITY_FUNCTION_CLASS, "hasRole", //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$
                                         new FunctionParameter[] { 
                                             new FunctionParameter("roleType", DataTypeManager.DefaultDataTypes.STRING, QueryPlugin.Util.getString("SystemSource.hasRole_param1")), //$NON-NLS-1$ //$NON-NLS-2$
@@ -263,13 +273,16 @@
         // With Seed
         FunctionMethod rand = new FunctionMethod(SourceSystemFunctions.RAND, QueryPlugin.Util.getString("SystemSource.Rand_desc"), NUMERIC, FUNCTION_CLASS, "rand", //$NON-NLS-1$ //$NON-NLS-2$ 
                                           new FunctionParameter[] {new FunctionParameter("seed", DataTypeManager.DefaultDataTypes.INTEGER, QueryPlugin.Util.getString("SystemSource.Rand_arg")) }, //$NON-NLS-1$ //$NON-NLS-2$
-                                          new FunctionParameter("result", DataTypeManager.DefaultDataTypes.DOUBLE, QueryPlugin.Util.getString("SystemSource.Rand_result_desc")), Determinism.NONDETERMINISTIC );                 //$NON-NLS-1$ //$NON-NLS-2$
-        rand.setNullOnNull(true);
+                                          new FunctionParameter("result", DataTypeManager.DefaultDataTypes.DOUBLE, QueryPlugin.Util.getString("SystemSource.Rand_result_desc")) );                 //$NON-NLS-1$ //$NON-NLS-2$
+        rand.setNullOnNull(false);
+        rand.setDeterminism(Determinism.NONDETERMINISTIC);
         functions.add(rand);
         // Without Seed
-        functions.add( new FunctionMethod(SourceSystemFunctions.RAND, QueryPlugin.Util.getString("SystemSource.Rand_desc"), NUMERIC, FUNCTION_CLASS, "rand", //$NON-NLS-1$ //$NON-NLS-2$ 
+        rand = new FunctionMethod(SourceSystemFunctions.RAND, QueryPlugin.Util.getString("SystemSource.Rand_desc"), NUMERIC, FUNCTION_CLASS, "rand", //$NON-NLS-1$ //$NON-NLS-2$ 
                                           new FunctionParameter[] {}, 
-                                          new FunctionParameter("result", DataTypeManager.DefaultDataTypes.DOUBLE, QueryPlugin.Util.getString("SystemSource.Rand_result_desc")), Determinism.NONDETERMINISTIC ) ); //$NON-NLS-1$ //$NON-NLS-2$                
+                                          new FunctionParameter("result", DataTypeManager.DefaultDataTypes.DOUBLE, QueryPlugin.Util.getString("SystemSource.Rand_result_desc")) ); //$NON-NLS-1$ //$NON-NLS-2$
+        rand.setDeterminism(Determinism.NONDETERMINISTIC);
+        functions.add(rand);
     }
 
 	private void addDoubleFunction(String name, String description) {
@@ -374,10 +387,11 @@
      * evaluation.
      */
     private void addConstantDateFunction(String name, String description, String methodName, String returnType) {
-        functions.add(
-            new FunctionMethod(name, description, DATETIME, FUNCTION_CLASS, methodName,
+        FunctionMethod method = new FunctionMethod(name, description, DATETIME, FUNCTION_CLASS, methodName,
                 new FunctionParameter[] {},
-                new FunctionParameter("result", returnType, description), Determinism.COMMAND_DETERMINISTIC ) );                 //$NON-NLS-1$
+                new FunctionParameter("result", returnType, description));                 //$NON-NLS-1$
+        method.setDeterminism(Determinism.COMMAND_DETERMINISTIC);
+        functions.add(method);
     }
 
     private void addDateFunction(String name, String methodName, String dateDesc, String timestampDesc, String returnType) {
@@ -539,7 +553,7 @@
                     new FunctionParameter("string", DataTypeManager.DefaultDataTypes.STRING, QueryPlugin.Util.getString("SystemSource.Locate_arg2")), //$NON-NLS-1$ //$NON-NLS-2$
                     new FunctionParameter("index", DataTypeManager.DefaultDataTypes.INTEGER, QueryPlugin.Util.getString("SystemSource.Locate_arg3")) }, //$NON-NLS-1$ //$NON-NLS-2$
                 new FunctionParameter("result", DataTypeManager.DefaultDataTypes.INTEGER, QueryPlugin.Util.getString("SystemSource.Locate_result")) );                 //$NON-NLS-1$ //$NON-NLS-2$
-        func.setNullOnNull(true);
+        func.setNullOnNull(false);
         functions.add(func);
         functions.add(
             new FunctionMethod(SourceSystemFunctions.LOCATE, QueryPlugin.Util.getString("SystemSource.Locate2_desc"), STRING, FUNCTION_CLASS, "locate", //$NON-NLS-1$ //$NON-NLS-2$ 
@@ -826,7 +840,7 @@
                     new FunctionParameter("value", valueType, QueryPlugin.Util.getString("SystemSource.Nvl_arg1")), //$NON-NLS-1$ //$NON-NLS-2$
                     new FunctionParameter("valueIfNull", valueType, QueryPlugin.Util.getString("SystemSource.Nvl_arg2")) }, //$NON-NLS-1$ //$NON-NLS-2$
                 new FunctionParameter("result", valueType, QueryPlugin.Util.getString("SystemSource.Nvl_result")) ); //$NON-NLS-1$ //$NON-NLS-2$
-        nvl.setNullOnNull(true);
+        nvl.setNullOnNull(false);
         functions.add(nvl); 
     }
 
@@ -837,7 +851,7 @@
 					new FunctionParameter("value", valueType, QueryPlugin.Util.getString("SystemSource.Ifnull_arg1")), //$NON-NLS-1$ //$NON-NLS-2$
 					new FunctionParameter("valueIfNull", valueType, QueryPlugin.Util.getString("SystemSource.Ifnull_arg2")) }, //$NON-NLS-1$ //$NON-NLS-2$
 				new FunctionParameter("result", valueType, QueryPlugin.Util.getString("SystemSource.Ifnull_result")) ); //$NON-NLS-1$ //$NON-NLS-2$
-        nvl.setNullOnNull(true);
+        nvl.setNullOnNull(false);
         functions.add(nvl); 
 	}
 			

Modified: trunk/engine/src/main/resources/org/teiid/query/i18n.properties
===================================================================
--- trunk/engine/src/main/resources/org/teiid/query/i18n.properties	2010-12-08 16:34:59 UTC (rev 2763)
+++ trunk/engine/src/main/resources/org/teiid/query/i18n.properties	2010-12-08 20:55:34 UTC (rev 2764)
@@ -273,6 +273,9 @@
 SQLParser.Invalid_short_name=Invalid simple identifier format: [{0}]
 SQLParser.Invalid_char={0} value must be a single character: [{1}].
 SQLParser.expected_non_reserved=Expected non-reserved word {0}, but was {1}.
+SystemSource.Add_desc=Converts escape sequences in the given string to their actual characters. 
+SystemSource.unescape_param1=String to be unescaped
+SystemSource.unescape_result=Unescaped string
 SystemSource.Add_desc=Add two numbers
 SystemSource.Add_result_desc=Left operand + right operand
 SystemSource.Subtract_desc=Subtract two numbers

Modified: trunk/engine/src/test/java/org/teiid/query/function/TestFunctionLibrary.java
===================================================================
--- trunk/engine/src/test/java/org/teiid/query/function/TestFunctionLibrary.java	2010-12-08 16:34:59 UTC (rev 2763)
+++ trunk/engine/src/test/java/org/teiid/query/function/TestFunctionLibrary.java	2010-12-08 20:55:34 UTC (rev 2764)
@@ -1407,4 +1407,8 @@
 		helpInvokeMethod("to_bytes", new Class[] {DefaultDataClasses.CLOB, DefaultDataClasses.STRING}, new Object[] { new ClobType(new SerialClob("a".toCharArray())), "BASE64" }, null); //$NON-NLS-1$
 	}
 	
+	@Test() public void testunescape() throws Exception {
+		assertEquals("\r\t", helpInvokeMethod("unescape", new Class[] {DefaultDataClasses.STRING}, new Object[] { "\r\\\t" }, null)); //$NON-NLS-1$
+	}
+	
 }

Added: trunk/engine/src/test/java/org/teiid/query/function/TestFunctionMethods.java
===================================================================
--- trunk/engine/src/test/java/org/teiid/query/function/TestFunctionMethods.java	                        (rev 0)
+++ trunk/engine/src/test/java/org/teiid/query/function/TestFunctionMethods.java	2010-12-08 20:55:34 UTC (rev 2764)
@@ -0,0 +1,40 @@
+/*
+ * 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.query.function;
+
+import static org.junit.Assert.*;
+
+import org.junit.Test;
+
+ at SuppressWarnings("nls")
+public class TestFunctionMethods {
+	
+	@Test public void testUnescape() {
+		assertEquals("a\t\n\n%6", FunctionMethods.unescape("a\\t\\n\\012\\456"));
+	}
+	
+	@Test public void testUnescape1() {
+		assertEquals("a\u45AA'", FunctionMethods.unescape("a\\u45Aa\'"));
+	}
+
+}


Property changes on: trunk/engine/src/test/java/org/teiid/query/function/TestFunctionMethods.java
___________________________________________________________________
Name: svn:mime-type
   + text/plain



More information about the teiid-commits mailing list