[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