[teiid-commits] teiid SVN: r3359 - in trunk: api/src/main/java/org/teiid/language/visitor and 27 other directories.

teiid-commits at lists.jboss.org teiid-commits at lists.jboss.org
Thu Aug 4 10:50:38 EDT 2011


Author: shawkins
Date: 2011-08-04 10:50:37 -0400 (Thu, 04 Aug 2011)
New Revision: 3359

Modified:
   trunk/api/src/main/java/org/teiid/language/SQLConstants.java
   trunk/api/src/main/java/org/teiid/language/visitor/SQLStringVisitor.java
   trunk/api/src/main/java/org/teiid/translator/SourceSystemFunctions.java
   trunk/build/kits/jboss-container/teiid-releasenotes.html
   trunk/connectors/translator-jdbc/src/main/java/org/teiid/translator/jdbc/db2/DB2ExecutionFactory.java
   trunk/connectors/translator-jdbc/src/main/java/org/teiid/translator/jdbc/derby/DerbyExecutionFactory.java
   trunk/connectors/translator-jdbc/src/main/java/org/teiid/translator/jdbc/h2/H2ExecutionFactory.java
   trunk/connectors/translator-jdbc/src/main/java/org/teiid/translator/jdbc/hsql/HsqlExecutionFactory.java
   trunk/connectors/translator-jdbc/src/main/java/org/teiid/translator/jdbc/mysql/MySQLExecutionFactory.java
   trunk/connectors/translator-jdbc/src/main/java/org/teiid/translator/jdbc/oracle/OracleExecutionFactory.java
   trunk/connectors/translator-jdbc/src/main/java/org/teiid/translator/jdbc/postgresql/PostgreSQLExecutionFactory.java
   trunk/connectors/translator-jdbc/src/main/java/org/teiid/translator/jdbc/teiid/TeiidExecutionFactory.java
   trunk/connectors/translator-jdbc/src/main/java/org/teiid/translator/jdbc/teradata/TeradataExecutionFactory.java
   trunk/connectors/translator-jdbc/src/test/java/org/teiid/translator/jdbc/db2/TestDB2SqlTranslator.java
   trunk/connectors/translator-jdbc/src/test/java/org/teiid/translator/jdbc/derby/TestDerbyCapabilities.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/source/SystemSource.java
   trunk/engine/src/main/java/org/teiid/query/resolver/util/ResolverVisitor.java
   trunk/engine/src/main/java/org/teiid/query/rewriter/QueryRewriter.java
   trunk/engine/src/main/java/org/teiid/query/sql/visitor/SQLStringVisitor.java
   trunk/engine/src/main/javacc/org/teiid/query/parser/SQLParser.jj
   trunk/engine/src/main/resources/org/teiid/query/i18n.properties
   trunk/engine/src/test/java/org/teiid/query/function/TestFunctionLibrary.java
   trunk/engine/src/test/java/org/teiid/query/parser/TestParser.java
   trunk/engine/src/test/java/org/teiid/query/processor/eval/TestExpressionEvaluator.java
   trunk/engine/src/test/java/org/teiid/query/resolver/TestResolver.java
   trunk/engine/src/test/java/org/teiid/query/rewriter/TestQueryRewriter.java
   trunk/test-integration/common/src/test/java/org/teiid/connector/visitor/util/TestSQLStringVisitor.java
Log:
TEIID-1694 adding support for trim and standard substring syntax

Modified: trunk/api/src/main/java/org/teiid/language/SQLConstants.java
===================================================================
--- trunk/api/src/main/java/org/teiid/language/SQLConstants.java	2011-08-04 12:09:55 UTC (rev 3358)
+++ trunk/api/src/main/java/org/teiid/language/SQLConstants.java	2011-08-04 14:50:37 UTC (rev 3359)
@@ -111,6 +111,8 @@
 		public static final String INSTEAD = "INSTEAD"; //$NON-NLS-1$
 		public static final String ENABLED = "ENABLED"; //$NON-NLS-1$
 		public static final String DISABLED = "DISABLED"; //$NON-NLS-1$
+		
+		public static final String TRIM = "TRIM";
 	}
 	
 	public interface Reserved {

Modified: trunk/api/src/main/java/org/teiid/language/visitor/SQLStringVisitor.java
===================================================================
--- trunk/api/src/main/java/org/teiid/language/visitor/SQLStringVisitor.java	2011-08-04 12:09:55 UTC (rev 3358)
+++ trunk/api/src/main/java/org/teiid/language/visitor/SQLStringVisitor.java	2011-08-04 14:50:37 UTC (rev 3359)
@@ -410,7 +410,20 @@
                 }
             }
             buffer.append(Tokens.RPAREN);
-
+        } else if (name.equalsIgnoreCase(NonReserved.TRIM)) {
+        	buffer.append(name);
+        	buffer.append(Tokens.LPAREN);
+        	String value = (String)((Literal)args.get(0)).getValue();
+        	if (!value.equalsIgnoreCase(BOTH)) {
+                buffer.append(value);
+                buffer.append(Tokens.SPACE);
+        	}
+            append(args.get(1));
+            buffer.append(" "); //$NON-NLS-1$
+            buffer.append(FROM);
+            buffer.append(" "); //$NON-NLS-1$
+            buffer.append(args.get(2));
+            buffer.append(")"); //$NON-NLS-1$
         } else {
 
             buffer.append(obj.getName())

Modified: trunk/api/src/main/java/org/teiid/translator/SourceSystemFunctions.java
===================================================================
--- trunk/api/src/main/java/org/teiid/translator/SourceSystemFunctions.java	2011-08-04 12:09:55 UTC (rev 3358)
+++ trunk/api/src/main/java/org/teiid/translator/SourceSystemFunctions.java	2011-08-04 14:50:37 UTC (rev 3359)
@@ -58,6 +58,10 @@
 	public static final String SUBSTRING = "substring"; //$NON-NLS-1$
 	public static final String TO_BYTES = "to_bytes"; //$NON-NLS-1$
 	public static final String TO_CHARS = "to_chars"; //$NON-NLS-1$
+	/**
+	 * The trim function is only used for a non-space trim character
+	 */
+	public static final String TRIM = "trim"; //$NON-NLS-1$
 	public static final String UCASE = "ucase"; //$NON-NLS-1$
 	public static final String UNESCAPE = "unescape"; //$NON-NLS-1$
 	

Modified: trunk/build/kits/jboss-container/teiid-releasenotes.html
===================================================================
--- trunk/build/kits/jboss-container/teiid-releasenotes.html	2011-08-04 12:09:55 UTC (rev 3358)
+++ trunk/build/kits/jboss-container/teiid-releasenotes.html	2011-08-04 14:50:37 UTC (rev 3359)
@@ -35,7 +35,7 @@
 	<LI><B>Streaming XQuery</B> - in situations where document projection applies if the XMLQUERY/XMLTABLE path expressions meet certain conditions, then the incoming document will not only be projected, but the independent subtrees will be processed without loading the entire document.  This allows for nearly arbitrarily large XML documents to be processed.  See the Reference for more.
 	<LI><B>Logging Procedures</B> - added SYSADMIN.isLoggable and SYSADMIN.logMsg to aid in debugging procedure logic.
 	<LI><B>ANSI OFFSET/FETCH FIRST</B> - instead of the limit clause, a standard OFFSET and/or FETCH FIRST/NEXT clause can be used to limit results.
-	<LI><B>ODBC Cursors</B> - Capability to use "UseDeclareFetch" with ODBC is added. This enables user to read the results in batches, especially useful when dealing with large row count of results.
+	<LI><B>ODBC Cursors</B> - added the capability to use "UseDeclareFetch" with ODBC. This enables users to read results in batches, which is especially useful when dealing with large row counts.
 	<LI><B>Internal Materialized Views</B>
 		<UL>
 			<LI><B>Distributed Refresh</B> - When a internal materialized view is refreshed at one node, an event is issued to all other nodes in the cluster to asynchronously fetch the new contents.

Modified: trunk/connectors/translator-jdbc/src/main/java/org/teiid/translator/jdbc/db2/DB2ExecutionFactory.java
===================================================================
--- trunk/connectors/translator-jdbc/src/main/java/org/teiid/translator/jdbc/db2/DB2ExecutionFactory.java	2011-08-04 12:09:55 UTC (rev 3358)
+++ trunk/connectors/translator-jdbc/src/main/java/org/teiid/translator/jdbc/db2/DB2ExecutionFactory.java	2011-08-04 14:50:37 UTC (rev 3359)
@@ -23,9 +23,16 @@
 package org.teiid.translator.jdbc.db2;
 
 import java.util.ArrayList;
+import java.util.Arrays;
 import java.util.List;
 
+import org.teiid.language.Expression;
+import org.teiid.language.Function;
+import org.teiid.language.Literal;
+import org.teiid.translator.SourceSystemFunctions;
 import org.teiid.translator.Translator;
+import org.teiid.translator.TranslatorException;
+import org.teiid.translator.jdbc.FunctionModifier;
 
 @Translator(name="db2", description="A translator for IBM DB2 Database")
 public class DB2ExecutionFactory extends BaseDB2ExecutionFactory {
@@ -80,6 +87,7 @@
 		supportedFunctions.add("RIGHT"); //$NON-NLS-1$
 		supportedFunctions.add("RTRIM"); //$NON-NLS-1$
 		supportedFunctions.add("SUBSTRING"); //$NON-NLS-1$
+		supportedFunctions.add(SourceSystemFunctions.TRIM);
 		//supportedFunctions.add("TRANSLATE"); //$NON-NLS-1$
 		supportedFunctions.add("UCASE"); //$NON-NLS-1$
 		supportedFunctions.add("UPPER"); //$NON-NLS-1$
@@ -129,5 +137,18 @@
 	public boolean supportsElementaryOlapOperations() {
 		return getDatabaseVersion().compareTo(NINE_1) >= 0;
 	}
-
+	
+	@Override
+	public void start() throws TranslatorException {
+		super.start();
+		registerFunctionModifier(SourceSystemFunctions.TRIM, new FunctionModifier() {
+			
+			@Override
+			public List<?> translate(Function function) {
+				List<Expression> p = function.getParameters();
+				return Arrays.asList("STRIP(", p.get(2), ", ", ((Literal)p.get(0)).getValue(), ", ", p.get(1), ")"); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$ //$NON-NLS-4$
+			}
+		});
+	}
+	
 }

Modified: trunk/connectors/translator-jdbc/src/main/java/org/teiid/translator/jdbc/derby/DerbyExecutionFactory.java
===================================================================
--- trunk/connectors/translator-jdbc/src/main/java/org/teiid/translator/jdbc/derby/DerbyExecutionFactory.java	2011-08-04 12:09:55 UTC (rev 3358)
+++ trunk/connectors/translator-jdbc/src/main/java/org/teiid/translator/jdbc/derby/DerbyExecutionFactory.java	2011-08-04 14:50:37 UTC (rev 3359)
@@ -40,6 +40,7 @@
 	
 	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_3 = "10.3"; //$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$
 	
@@ -130,6 +131,9 @@
         //supportedFunctions.add("RPAD"); //$NON-NLS-1$
         supportedFunctions.add("RTRIM"); //$NON-NLS-1$
         supportedFunctions.add("SUBSTRING"); //$NON-NLS-1$
+        if (getDatabaseVersion().compareTo(TEN_3) >= 0) {
+        	supportedFunctions.add(SourceSystemFunctions.TRIM);
+        }
         supportedFunctions.add("UCASE"); //$NON-NLS-1$
         
         // These are executed within the server and never pushed down

Modified: trunk/connectors/translator-jdbc/src/main/java/org/teiid/translator/jdbc/h2/H2ExecutionFactory.java
===================================================================
--- trunk/connectors/translator-jdbc/src/main/java/org/teiid/translator/jdbc/h2/H2ExecutionFactory.java	2011-08-04 12:09:55 UTC (rev 3358)
+++ trunk/connectors/translator-jdbc/src/main/java/org/teiid/translator/jdbc/h2/H2ExecutionFactory.java	2011-08-04 14:50:37 UTC (rev 3359)
@@ -28,9 +28,9 @@
 import java.util.ArrayList;
 import java.util.List;
 
+import org.teiid.translator.SourceSystemFunctions;
 import org.teiid.translator.Translator;
 import org.teiid.translator.TranslatorException;
-import org.teiid.translator.SourceSystemFunctions;
 import org.teiid.translator.jdbc.AliasModifier;
 import org.teiid.translator.jdbc.ConvertModifier;
 import org.teiid.translator.jdbc.FunctionModifier;
@@ -139,6 +139,7 @@
         supportedFunctions.add(SourceSystemFunctions.RPAD);
         supportedFunctions.add(SourceSystemFunctions.RTRIM);
         supportedFunctions.add(SourceSystemFunctions.SUBSTRING);
+        supportedFunctions.add(SourceSystemFunctions.TRIM);
         supportedFunctions.add(SourceSystemFunctions.UCASE);
         supportedFunctions.add(SourceSystemFunctions.UNESCAPE);
         

Modified: trunk/connectors/translator-jdbc/src/main/java/org/teiid/translator/jdbc/hsql/HsqlExecutionFactory.java
===================================================================
--- trunk/connectors/translator-jdbc/src/main/java/org/teiid/translator/jdbc/hsql/HsqlExecutionFactory.java	2011-08-04 12:09:55 UTC (rev 3358)
+++ trunk/connectors/translator-jdbc/src/main/java/org/teiid/translator/jdbc/hsql/HsqlExecutionFactory.java	2011-08-04 14:50:37 UTC (rev 3359)
@@ -28,9 +28,9 @@
 import java.util.ArrayList;
 import java.util.List;
 
+import org.teiid.translator.SourceSystemFunctions;
 import org.teiid.translator.Translator;
 import org.teiid.translator.TranslatorException;
-import org.teiid.translator.SourceSystemFunctions;
 import org.teiid.translator.jdbc.ConvertModifier;
 import org.teiid.translator.jdbc.FunctionModifier;
 import org.teiid.translator.jdbc.JDBCExecutionFactory;
@@ -125,6 +125,7 @@
         supportedFunctions.add(SourceSystemFunctions.RPAD);
         supportedFunctions.add(SourceSystemFunctions.RTRIM);
         supportedFunctions.add(SourceSystemFunctions.SUBSTRING);
+        supportedFunctions.add(SourceSystemFunctions.TRIM);
         supportedFunctions.add(SourceSystemFunctions.UCASE);
         
         supportedFunctions.add(SourceSystemFunctions.DAYNAME);

Modified: trunk/connectors/translator-jdbc/src/main/java/org/teiid/translator/jdbc/mysql/MySQLExecutionFactory.java
===================================================================
--- trunk/connectors/translator-jdbc/src/main/java/org/teiid/translator/jdbc/mysql/MySQLExecutionFactory.java	2011-08-04 12:09:55 UTC (rev 3358)
+++ trunk/connectors/translator-jdbc/src/main/java/org/teiid/translator/jdbc/mysql/MySQLExecutionFactory.java	2011-08-04 14:50:37 UTC (rev 3359)
@@ -177,6 +177,7 @@
         supportedFunctions.add(SourceSystemFunctions.RPAD);
         supportedFunctions.add(SourceSystemFunctions.RTRIM);
         supportedFunctions.add(SourceSystemFunctions.SUBSTRING);
+        supportedFunctions.add(SourceSystemFunctions.TRIM);
         supportedFunctions.add(SourceSystemFunctions.UCASE);
         
         // These are executed within the server and never pushed down

Modified: trunk/connectors/translator-jdbc/src/main/java/org/teiid/translator/jdbc/oracle/OracleExecutionFactory.java
===================================================================
--- trunk/connectors/translator-jdbc/src/main/java/org/teiid/translator/jdbc/oracle/OracleExecutionFactory.java	2011-08-04 12:09:55 UTC (rev 3358)
+++ trunk/connectors/translator-jdbc/src/main/java/org/teiid/translator/jdbc/oracle/OracleExecutionFactory.java	2011-08-04 14:50:37 UTC (rev 3359)
@@ -454,6 +454,7 @@
         supportedFunctions.add("RTRIM"); //$NON-NLS-1$
         supportedFunctions.add("SUBSTRING"); //$NON-NLS-1$
         supportedFunctions.add("TRANSLATE"); //$NON-NLS-1$
+        supportedFunctions.add(SourceSystemFunctions.TRIM);
         supportedFunctions.add("UCASE"); //$NON-NLS-1$
         supportedFunctions.add("UPPER"); //$NON-NLS-1$
         supportedFunctions.add("HOUR"); //$NON-NLS-1$

Modified: trunk/connectors/translator-jdbc/src/main/java/org/teiid/translator/jdbc/postgresql/PostgreSQLExecutionFactory.java
===================================================================
--- trunk/connectors/translator-jdbc/src/main/java/org/teiid/translator/jdbc/postgresql/PostgreSQLExecutionFactory.java	2011-08-04 12:09:55 UTC (rev 3358)
+++ trunk/connectors/translator-jdbc/src/main/java/org/teiid/translator/jdbc/postgresql/PostgreSQLExecutionFactory.java	2011-08-04 14:50:37 UTC (rev 3359)
@@ -302,6 +302,7 @@
         supportedFunctions.add("RPAD"); //$NON-NLS-1$
         supportedFunctions.add("RTRIM"); //$NON-NLS-1$
         supportedFunctions.add("SUBSTRING"); //$NON-NLS-1$
+        supportedFunctions.add(SourceSystemFunctions.TRIM);
         supportedFunctions.add("UCASE"); //$NON-NLS-1$
         supportedFunctions.add("UPPER"); //$NON-NLS-1$
         

Modified: trunk/connectors/translator-jdbc/src/main/java/org/teiid/translator/jdbc/teiid/TeiidExecutionFactory.java
===================================================================
--- trunk/connectors/translator-jdbc/src/main/java/org/teiid/translator/jdbc/teiid/TeiidExecutionFactory.java	2011-08-04 12:09:55 UTC (rev 3358)
+++ trunk/connectors/translator-jdbc/src/main/java/org/teiid/translator/jdbc/teiid/TeiidExecutionFactory.java	2011-08-04 14:50:37 UTC (rev 3359)
@@ -145,14 +145,18 @@
         
         if (getDatabaseVersion().compareTo(SEVEN_3) >= 0) {
         	supportedFunctions.add(SourceSystemFunctions.UNESCAPE);
-        	
-            if (getDatabaseVersion().compareTo(SEVEN_4) >= 0) {
-            	supportedFunctions.add(SourceSystemFunctions.UUID);
-            	supportedFunctions.add(SourceSystemFunctions.ARRAY_GET);
-            	supportedFunctions.add(SourceSystemFunctions.ARRAY_LENGTH);
-            }
         }
         
+        if (getDatabaseVersion().compareTo(SEVEN_4) >= 0) {
+        	supportedFunctions.add(SourceSystemFunctions.UUID);
+        	supportedFunctions.add(SourceSystemFunctions.ARRAY_GET);
+        	supportedFunctions.add(SourceSystemFunctions.ARRAY_LENGTH);
+        }
+        
+        if (getDatabaseVersion().compareTo(SEVEN_5) >= 0) {
+        	supportedFunctions.add(SourceSystemFunctions.TRIM);
+        }
+        
         return supportedFunctions;
     }
     

Modified: trunk/connectors/translator-jdbc/src/main/java/org/teiid/translator/jdbc/teradata/TeradataExecutionFactory.java
===================================================================
--- trunk/connectors/translator-jdbc/src/main/java/org/teiid/translator/jdbc/teradata/TeradataExecutionFactory.java	2011-08-04 12:09:55 UTC (rev 3358)
+++ trunk/connectors/translator-jdbc/src/main/java/org/teiid/translator/jdbc/teradata/TeradataExecutionFactory.java	2011-08-04 14:50:37 UTC (rev 3359)
@@ -251,6 +251,7 @@
         supportedFunctions.add(SourceSystemFunctions.SQRT);
         supportedFunctions.add(SourceSystemFunctions.SUBSTRING);
         supportedFunctions.add(SourceSystemFunctions.TAN);
+        supportedFunctions.add(SourceSystemFunctions.TRIM);
         supportedFunctions.add(SourceSystemFunctions.UCASE);
         supportedFunctions.add(SourceSystemFunctions.YEAR);
 

Modified: trunk/connectors/translator-jdbc/src/test/java/org/teiid/translator/jdbc/db2/TestDB2SqlTranslator.java
===================================================================
--- trunk/connectors/translator-jdbc/src/test/java/org/teiid/translator/jdbc/db2/TestDB2SqlTranslator.java	2011-08-04 12:09:55 UTC (rev 3358)
+++ trunk/connectors/translator-jdbc/src/test/java/org/teiid/translator/jdbc/db2/TestDB2SqlTranslator.java	2011-08-04 14:50:37 UTC (rev 3359)
@@ -270,5 +270,14 @@
                 input, output, 
                 TRANSLATOR);
     }
+    
+    @Test public void testTrim() throws Exception {
+        String input = "SELECT trim(leading 'x' from stringnum) FROM BQT1.SMALLA"; //$NON-NLS-1$
+        String output = "SELECT STRIP(SmallA.StringNum, leading, 'x') FROM SmallA";  //$NON-NLS-1$
 
+        TranslationHelper.helpTestVisitor(TranslationHelper.BQT_VDB,
+                input, output, 
+                TRANSLATOR);
+    }
+
 }

Modified: trunk/connectors/translator-jdbc/src/test/java/org/teiid/translator/jdbc/derby/TestDerbyCapabilities.java
===================================================================
--- trunk/connectors/translator-jdbc/src/test/java/org/teiid/translator/jdbc/derby/TestDerbyCapabilities.java	2011-08-04 12:09:55 UTC (rev 3358)
+++ trunk/connectors/translator-jdbc/src/test/java/org/teiid/translator/jdbc/derby/TestDerbyCapabilities.java	2011-08-04 14:50:37 UTC (rev 3359)
@@ -22,9 +22,7 @@
 
 package org.teiid.translator.jdbc.derby;
 
-import static org.junit.Assert.assertEquals;
-import static org.junit.Assert.assertFalse;
-import static org.junit.Assert.assertTrue;
+import static org.junit.Assert.*;
 
 import org.junit.Test;
 
@@ -41,7 +39,7 @@
 		DerbyExecutionFactory derbyCapabilities = new DerbyExecutionFactory();
 		assertEquals(27, derbyCapabilities.getSupportedFunctions().size());
 		derbyCapabilities.setDatabaseVersion(DerbyExecutionFactory.TEN_4);
-		assertEquals(43, derbyCapabilities.getSupportedFunctions().size());
+		assertEquals(44, derbyCapabilities.getSupportedFunctions().size());
 	}
 
 }

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	2011-08-04 12:09:55 UTC (rev 3358)
+++ trunk/documentation/reference/src/main/docbook/en-US/content/scalar_functions.xml	2011-08-04 14:50:37 UTC (rev 3359)
@@ -1005,6 +1005,7 @@
           <row>
             <entry>
               <para>SUBSTRING(x, y)</para>
+              <para>SUBSTRING(x FROM y)</para>
             </entry>
             <entry>
               <para>Get substring from x, from position y to the end of x
@@ -1017,6 +1018,7 @@
           <row>
             <entry>
               <para>SUBSTRING(x, y, z)</para>
+              <para>SUBSTRING(x FROM y FOR z)</para>
             </entry>
             <entry>
               <para>Get substring from x from position y with length z
@@ -1063,6 +1065,18 @@
           </row>
           <row>
             <entry>
+              <para>TRIM([[LEADING|TRAILING|BOTH] [x] FROM] y)</para>
+            </entry>
+            <entry>
+              <para>Trim the leading, trailing, or both ends of a string y of character x.  
+              If LEADING/TRAILING/BOTH is not specified, BOTH is used.  If no trim character x is specficed then the blank space ' ' is used.</para>
+            </entry>
+            <entry>
+              <para>x in {character}, y in {string}</para>
+            </entry>
+          </row>
+          <row>
+            <entry>
               <para>UCASE(x)</para>
             </entry>
             <entry>

Modified: trunk/engine/src/main/java/org/teiid/query/function/FunctionMethods.java
===================================================================
--- trunk/engine/src/main/java/org/teiid/query/function/FunctionMethods.java	2011-08-04 12:09:55 UTC (rev 3358)
+++ trunk/engine/src/main/java/org/teiid/query/function/FunctionMethods.java	2011-08-04 14:50:37 UTC (rev 3359)
@@ -56,6 +56,7 @@
 import org.teiid.core.types.InputStreamFactory.BlobInputStreamFactory;
 import org.teiid.core.types.InputStreamFactory.ClobInputStreamFactory;
 import org.teiid.core.util.TimestampWithTimezone;
+import org.teiid.language.SQLConstants;
 import org.teiid.language.SQLConstants.NonReserved;
 import org.teiid.query.QueryPlugin;
 import org.teiid.query.util.CommandContext;
@@ -694,14 +695,30 @@
 		return new Integer(str.indexOf(sub, start.intValue() - 1) + 1);
 	}
 
+	public static String trim(String trimSpec, String trimChar, String string) throws FunctionExecutionException {
+		if (trimChar.length() != 1) {
+			throw new FunctionExecutionException(QueryPlugin.Util.getString("SQLParser.Invalid_char", "trim char", trimChar)); //$NON-NLS-1$ //$NON-NLS-2$
+		}
+		if (!trimSpec.equalsIgnoreCase(SQLConstants.Reserved.LEADING)) {
+			string = rightTrim(string, trimChar.charAt(0));
+		}
+		if (!trimSpec.equalsIgnoreCase(SQLConstants.Reserved.TRAILING)) {
+			string = leftTrim(string, trimChar.charAt(0));
+		}
+		return string;
+	}
+	
 	// ================== Function = lefttrim =====================
 
 	private static final char SPACE = ' ';
 
-	public static Object leftTrim(String string) {
+	public static String leftTrim(String string, char trimChar) {
 		for(int i=0; i<string.length(); i++) {
-			if(string.charAt(i) != SPACE) {
+			if(string.charAt(i) != trimChar) {
 				// end of trim, return what's left
+				if (i==0) {
+					return string;
+				}
 				return new String(string.substring(i));
 			}
 		}
@@ -709,13 +726,21 @@
 		// All spaces, so trim it all
 		return ""; //$NON-NLS-1$
 	}
+	
+	
+	public static String leftTrim(String string) {
+		return leftTrim(string, SPACE);
+	}
 
 	// ================== Function = righttrim =====================
 
-	public static Object rightTrim(String string) {
+	public static String rightTrim(String string, char trimChar) {
 		for(int i=string.length()-1; i>=0; i--) {
-			if(string.charAt(i) != SPACE) {
+			if(string.charAt(i) != trimChar) {
 				// end of trim, return what's left
+				if (i==string.length()-1) {
+					return string;
+				}
 				return new String(string.substring(0, i+1));
 			}
 		}
@@ -723,6 +748,10 @@
 		// All spaces, so trim it all
 		return ""; //$NON-NLS-1$
 	}
+	
+	public static Object rightTrim(String string) {
+		return rightTrim(string, SPACE);
+	}
 
 	// ================== Function = replace =====================
 

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	2011-08-04 12:09:55 UTC (rev 3358)
+++ trunk/engine/src/main/java/org/teiid/query/function/source/SystemSource.java	2011-08-04 14:50:37 UTC (rev 3359)
@@ -29,8 +29,8 @@
 
 import org.teiid.core.types.DataTypeManager;
 import org.teiid.metadata.FunctionParameter;
+import org.teiid.metadata.FunctionMethod.Determinism;
 import org.teiid.metadata.FunctionMethod.PushDown;
-import org.teiid.metadata.FunctionMethod.Determinism;
 import org.teiid.query.QueryPlugin;
 import org.teiid.query.function.FunctionLibrary;
 import org.teiid.query.function.FunctionMetadataSource;
@@ -196,7 +196,18 @@
         addUuidFunction();
         addArrayGet();
         addArrayLength();
+        addTrimFunction();
     }
+    
+    private void addTrimFunction() {
+        functions.add(
+            new FunctionMethod(SourceSystemFunctions.TRIM, QueryPlugin.Util.getString("SystemSource.trim_desc"), STRING, FUNCTION_CLASS, SourceSystemFunctions.TRIM,//$NON-NLS-1$ 
+                new FunctionParameter[] {
+            		new FunctionParameter("spec", DataTypeManager.DefaultDataTypes.STRING, QueryPlugin.Util.getString("SystemSource.trim_arg1")),//$NON-NLS-1$ //$NON-NLS-2$
+            		new FunctionParameter("trimChar", DataTypeManager.DefaultDataTypes.STRING, QueryPlugin.Util.getString("SystemSource.trim_arg2")),//$NON-NLS-1$ //$NON-NLS-2$
+                    new FunctionParameter("string", DataTypeManager.DefaultDataTypes.STRING, QueryPlugin.Util.getString("SystemSource.trim_arg3")) }, //$NON-NLS-1$ //$NON-NLS-2$
+                new FunctionParameter("result", DataTypeManager.DefaultDataTypes.STRING, QueryPlugin.Util.getString("SystemSource.trim_result")) ) );   //$NON-NLS-1$ //$NON-NLS-2$
+    }
 
     private void addArrayLength() {
     	functions.add(new FunctionMethod(SourceSystemFunctions.ARRAY_LENGTH, QueryPlugin.Util.getString("SystemSource.array_length_desc"), MISCELLANEOUS, PushDown.CAN_PUSHDOWN, FUNCTION_CLASS, SourceSystemFunctions.ARRAY_LENGTH, //$NON-NLS-1$ 

Modified: trunk/engine/src/main/java/org/teiid/query/resolver/util/ResolverVisitor.java
===================================================================
--- trunk/engine/src/main/java/org/teiid/query/resolver/util/ResolverVisitor.java	2011-08-04 12:09:55 UTC (rev 3358)
+++ trunk/engine/src/main/java/org/teiid/query/resolver/util/ResolverVisitor.java	2011-08-04 14:50:37 UTC (rev 3359)
@@ -529,11 +529,11 @@
 	    
 	    if(fd.getName().equalsIgnoreCase(FunctionLibrary.CONVERT) || fd.getName().equalsIgnoreCase(FunctionLibrary.CAST)) {
 	        String dataType = (String) ((Constant)args[1]).getValue();
-	        Class dataTypeClass = DataTypeManager.getDataTypeClass(dataType);
+	        Class<?> dataTypeClass = DataTypeManager.getDataTypeClass(dataType);
 	        fd = library.findTypedConversionFunction(args[0].getType(), dataTypeClass);
 	
 	        // Verify that the type conversion from src to type is even valid
-	        Class srcTypeClass = args[0].getType();
+	        Class<?> srcTypeClass = args[0].getType();
 	        if(srcTypeClass != null && dataTypeClass != null &&
 	           !srcTypeClass.equals(dataTypeClass) &&
 	           !DataTypeManager.isTransformable(srcTypeClass, dataTypeClass)) {
@@ -545,7 +545,6 @@
 			fd = library.copyFunctionChangeReturnType(fd, lookup.getReturnElement().getType());
 	    } 
 	
-	    // Resolve the function
 	    function.setFunctionDescriptor(fd);
 	    function.setType(fd.getReturnType());
 	}

Modified: trunk/engine/src/main/java/org/teiid/query/rewriter/QueryRewriter.java
===================================================================
--- trunk/engine/src/main/java/org/teiid/query/rewriter/QueryRewriter.java	2011-08-04 12:09:55 UTC (rev 3358)
+++ trunk/engine/src/main/java/org/teiid/query/rewriter/QueryRewriter.java	2011-08-04 14:50:37 UTC (rev 3359)
@@ -55,6 +55,7 @@
 import org.teiid.core.types.Transform;
 import org.teiid.core.util.Assertion;
 import org.teiid.core.util.TimestampWithTimezone;
+import org.teiid.language.SQLConstants;
 import org.teiid.language.SQLConstants.NonReserved;
 import org.teiid.query.QueryPlugin;
 import org.teiid.query.eval.Evaluator;
@@ -2281,6 +2282,7 @@
     	FUNCTION_MAP.put(FunctionLibrary.PARSETIME.toLowerCase(), 7);
     	FUNCTION_MAP.put(FunctionLibrary.FORMATDATE.toLowerCase(), 8);
     	FUNCTION_MAP.put(FunctionLibrary.FORMATTIME.toLowerCase(), 9);
+    	FUNCTION_MAP.put(SourceSystemFunctions.TRIM.toLowerCase(), 10);
     }
     
 	private Expression rewriteFunction(Function function) throws TeiidComponentException, TeiidProcessingException{
@@ -2407,7 +2409,27 @@
 				function.getArgs()[0] = ResolverUtil.getConversion(function.getArg(0), DataTypeManager.getDataTypeName(function.getArg(0).getType()), DataTypeManager.DefaultDataTypes.TIMESTAMP, false, funcLibrary);
 				break;
 			}
+			case 10: {
+				if (new Constant(" ").equals(function.getArg(1))) { //$NON-NLS-1$
+					String spec = (String)((Constant)function.getArg(0)).getValue();
+					Expression string = function.getArg(2);
+					if (!SQLConstants.Reserved.TRAILING.equalsIgnoreCase(spec)) {
+						function = new Function(SourceSystemFunctions.LTRIM, new Expression[] {string});
+						FunctionDescriptor descriptor = funcLibrary.findFunction(SourceSystemFunctions.LTRIM, new Class[] { DataTypeManager.DefaultDataClasses.STRING });
+						function.setFunctionDescriptor(descriptor);
+						function.setType(DataTypeManager.DefaultDataClasses.STRING);
+						string = function;
+					}
+					if (!SQLConstants.Reserved.LEADING.equalsIgnoreCase(spec)) {
+						function = new Function(SourceSystemFunctions.RTRIM, new Expression[] {string});
+						FunctionDescriptor descriptor = funcLibrary.findFunction(SourceSystemFunctions.RTRIM, new Class[] { DataTypeManager.DefaultDataClasses.STRING });
+						function.setFunctionDescriptor(descriptor);
+						function.setType(DataTypeManager.DefaultDataClasses.STRING);
+					}
+				}
+				break;
 			}
+			}
 		}
 						
 		Expression[] args = function.getArgs();

Modified: trunk/engine/src/main/java/org/teiid/query/sql/visitor/SQLStringVisitor.java
===================================================================
--- trunk/engine/src/main/java/org/teiid/query/sql/visitor/SQLStringVisitor.java	2011-08-04 12:09:55 UTC (rev 3358)
+++ trunk/engine/src/main/java/org/teiid/query/sql/visitor/SQLStringVisitor.java	2011-08-04 14:50:37 UTC (rev 3359)
@@ -1304,6 +1304,20 @@
             outputDisplayName((String)((Constant)args[0]).getValue());
             registerNodes(args, 1);
             append(")"); //$NON-NLS-1$
+        } else if (name.equalsIgnoreCase(SourceSystemFunctions.TRIM)) {
+        	append(name);
+        	append(SQLConstants.Tokens.LPAREN);
+        	String value = (String)((Constant)args[0]).getValue();
+        	if (!value.equalsIgnoreCase(BOTH)) {
+	        	append(((Constant)args[0]).getValue());
+	            append(" "); //$NON-NLS-1$
+        	}
+            append(args[1]);
+            append(" "); //$NON-NLS-1$
+            append(FROM);
+            append(" "); //$NON-NLS-1$
+            append(args[2]);
+            append(")"); //$NON-NLS-1$
         } else {
             append(name);
             append("("); //$NON-NLS-1$

Modified: trunk/engine/src/main/javacc/org/teiid/query/parser/SQLParser.jj
===================================================================
--- trunk/engine/src/main/javacc/org/teiid/query/parser/SQLParser.jj	2011-08-04 12:09:55 UTC (rev 3358)
+++ trunk/engine/src/main/javacc/org/teiid/query/parser/SQLParser.jj	2011-08-04 14:50:37 UTC (rev 3359)
@@ -3548,16 +3548,14 @@
 		expression = expression(info)
 		{
 			args.add(expression);
-			expression = null;
 		}
 		<COMMA>
 		expression = dataType()	
 		{
 			args.add(expression);
-			expression = null;			
 		}
 		<RPAREN> 
-	)	
+	)
 	|
 	(			
 		funcToken = <CAST>
@@ -3565,30 +3563,83 @@
 		expression = expression(info)
 		{
 			args.add(expression);
-			expression = null;
 		} 
 		<AS>
 		expression = dataType()
 		{
 			args.add(expression);
-			expression = null;
 		}
 		<RPAREN>				
 	)
 	|
+	LOOKAHEAD(4, {getToken(1).image.equalsIgnoreCase("SUBSTRING")}) (
+	   funcName = nonReserved("SUBSTRING")
+	   <LPAREN>
+	   expression = expression(info)
+	   {
+	      args.add(expression);
+	   }
+	   <FROM> expression = expression(info)
+	   {
+	      args.add(expression);
+	   }
+  	   [<FOR> expression = expression(info)
+	    {
+	      args.add(expression);
+	    }
+	   ]
+	   <RPAREN>
+	)
+	|
+	LOOKAHEAD(1, {getToken(1).image.equalsIgnoreCase("TRIM")}) (
+	   funcName= nonReserved("TRIM")
+	   <LPAREN>
+	   { funcToken = null; expression = null;}
+	   [
+	    LOOKAHEAD(2) (((funcToken = <LEADING>|
+	      funcToken = <TRAILING>|
+	      funcToken = <BOTH>)
+	    [expression = expression(info)])
+	    |
+	    expression = expression(info))
+		<FROM>
+	   ]
+  	   {
+	      if (funcToken == null) {
+	      	  args.add(new Constant("BOTH"));
+	      } else {
+	          args.add(new Constant(funcToken.image));
+	      }
+	      if (expression == null) {
+	          args.add(new Constant(" "));
+	      } else {
+	          if (expression instanceof Constant) {
+	              Object value = ((Constant)expression).getValue();
+	              if (value instanceof String && ((String)value).length() != 1) {
+				      throw new ParseException(QueryPlugin.Util.getString("SQLParser.Invalid_char", "TRIM CHAR", value)); //$NON-NLS-1$
+	              }
+	          }
+	          args.add(expression);
+	      }
+	   }
+	   expression = expression(info)
+	   {
+	      args.add(expression);
+	   }
+	   <RPAREN>
+	)
+	|
 	LOOKAHEAD(<ID>, {matchesAny(getToken(1).image, "to_chars", "to_bytes") != null}) (	
 		funcName = nonReserved("TO_CHARS", "TO_BYTES")
 		<LPAREN>
 		expression = expression(info) 
 		{		
 			args.add(expression);
-			expression = null;
 		}
 		<COMMA>
 		expression = stringConstant()
 		{
 			args.add(expression);
-			expression = null;
 		} 
 		<RPAREN>				
 	)
@@ -3599,19 +3650,16 @@
 		expression = intervalType() 
 		{		
 			args.add(expression);
-			expression = null;
 		}
 		<COMMA>
 		expression = expression(info)
 		{
 			args.add(expression);
-			expression = null;
 		} 
 		<COMMA>
 		expression = expression(info)
 		{
 			args.add(expression);
-			expression = null;
 		} 
 		<RPAREN>				
 	)
@@ -3654,13 +3702,11 @@
 		)
 		{
 			args.add(expression);	
-			expression = null;
 		}
 		[
 			<COMMA> expression = expression(info)
 			{
 				args.add(expression);	
-				expression = null;
 			}	
 		]
 		<RPAREN>
@@ -3773,7 +3819,6 @@
 	(<COMMA> expression=expression(info)
 	{
 		content.add(expression);
-		expression = null;
 	}
 	)*
 	<RPAREN>
@@ -3795,12 +3840,10 @@
 	expression = derivedColumn(info)
 	{
 		args.add(expression);
-		expression = null;
 	}
 	(<COMMA> expression=derivedColumn(info)
 	 {
 		args.add(expression);
-		expression = null;
 	 }
 	)*
 	<RPAREN>  		
@@ -3823,12 +3866,10 @@
 	expression = derivedColumn(info)
 	{
 		args.add(expression);
-		expression = null;
 	}
 	(<COMMA> expression=derivedColumn(info)
 	 {
 		args.add(expression);
-		expression = null;
 	 }
 	)*
 	<RPAREN>  		

Modified: trunk/engine/src/main/resources/org/teiid/query/i18n.properties
===================================================================
--- trunk/engine/src/main/resources/org/teiid/query/i18n.properties	2011-08-04 12:09:55 UTC (rev 3358)
+++ trunk/engine/src/main/resources/org/teiid/query/i18n.properties	2011-08-04 14:50:37 UTC (rev 3359)
@@ -395,6 +395,11 @@
 SystemSource.Rand_result_desc=Generated Random Number
 SystemSource.uuid_desc=UUID
 SystemSource.uuid_result_desc=type 4 UUID
+SystemSource.trim_desc=Trim characters from the front and/or back of a string
+SystemSource.trim_arg1=Trim specification, can be one of TRAILING, LEADING, or BOTH
+SystemSource.trim_arg2=Trim character - must be a single character
+SystemSource.trim_arg3=String to trim
+SystemSource.trim_result=Trimmed string
 SystemSource.Double_arg2=Number
 SystemSource.Atan_arg1=Number parameter1 
 SystemSource.Atan_arg2=Number parameter2 

Modified: trunk/engine/src/test/java/org/teiid/query/function/TestFunctionLibrary.java
===================================================================
--- trunk/engine/src/test/java/org/teiid/query/function/TestFunctionLibrary.java	2011-08-04 12:09:55 UTC (rev 3358)
+++ trunk/engine/src/test/java/org/teiid/query/function/TestFunctionLibrary.java	2011-08-04 14:50:37 UTC (rev 3359)
@@ -1408,4 +1408,16 @@
 		assertEquals(1, helpInvokeMethod("array_get", new Class<?>[] {DefaultDataClasses.OBJECT, DefaultDataClasses.INTEGER}, new Object[] {new Object[] {1}, 1}, null)); //$NON-NLS-1$
 	}
 	
+	@Test() public void testTrim() throws Exception {
+		helpInvokeMethod("trim", new Object[] {"leading", "x", "xaxx"}, "axx"); //$NON-NLS-1$
+	}
+
+	@Test() public void testTrim1() throws Exception {
+		helpInvokeMethod("trim", new Object[] {"both", " ", "   a   "}, "a"); //$NON-NLS-1$
+	}
+
+	@Test() public void testTrim2() throws Exception {
+		helpInvokeMethod("trim", new Object[] {"trailing", "x", "xaxx"}, "xa"); //$NON-NLS-1$
+	}
+
 }

Modified: trunk/engine/src/test/java/org/teiid/query/parser/TestParser.java
===================================================================
--- trunk/engine/src/test/java/org/teiid/query/parser/TestParser.java	2011-08-04 12:09:55 UTC (rev 3358)
+++ trunk/engine/src/test/java/org/teiid/query/parser/TestParser.java	2011-08-04 14:50:37 UTC (rev 3359)
@@ -6859,5 +6859,9 @@
     	query.setFrom(new From(Arrays.asList(new UnaryFromClause(new GroupSymbol("g")))));
         helpTest(sql, "SELECT ROW_NUMBER() OVER (PARTITION BY x ORDER BY y) FROM g", query);
     }
+    
+    @Test public void testTrim1() {
+    	helpException("select trim('xy' from e1) from pm1.g1");
+    }
 
 }

Modified: trunk/engine/src/test/java/org/teiid/query/processor/eval/TestExpressionEvaluator.java
===================================================================
--- trunk/engine/src/test/java/org/teiid/query/processor/eval/TestExpressionEvaluator.java	2011-08-04 12:09:55 UTC (rev 3358)
+++ trunk/engine/src/test/java/org/teiid/query/processor/eval/TestExpressionEvaluator.java	2011-08-04 14:50:37 UTC (rev 3359)
@@ -432,4 +432,9 @@
     	assertEquals(Boolean.TRUE, Evaluator.evaluate(inc));
     }
     
+    @Test public void testSubstring() throws Exception {
+    	Expression ex = TestFunctionResolving.getExpression("substring('abcd' from 2 for 2)");
+    	assertEquals("bc", Evaluator.evaluate(ex));
+    }
+    
 }

Modified: trunk/engine/src/test/java/org/teiid/query/resolver/TestResolver.java
===================================================================
--- trunk/engine/src/test/java/org/teiid/query/resolver/TestResolver.java	2011-08-04 12:09:55 UTC (rev 3358)
+++ trunk/engine/src/test/java/org/teiid/query/resolver/TestResolver.java	2011-08-04 14:50:37 UTC (rev 3359)
@@ -2977,4 +2977,14 @@
 
         helpResolveUpdateProcedure(procedure, userQuery);
 	}
+    
+    @Test public void testTrim() {
+    	Query query = (Query)helpResolve("select trim(e1) from pm1.g1");
+    	assertEquals(DataTypeManager.DefaultDataClasses.STRING, query.getProjectedSymbols().get(0).getType());
+    }
+    
+    @Test public void testTrim1() {
+    	helpResolve("select trim('x' from e1) from pm1.g1");
+    }
+
 }
\ No newline at end of file

Modified: trunk/engine/src/test/java/org/teiid/query/rewriter/TestQueryRewriter.java
===================================================================
--- trunk/engine/src/test/java/org/teiid/query/rewriter/TestQueryRewriter.java	2011-08-04 12:09:55 UTC (rev 3358)
+++ trunk/engine/src/test/java/org/teiid/query/rewriter/TestQueryRewriter.java	2011-08-04 14:50:37 UTC (rev 3359)
@@ -2464,4 +2464,12 @@
     	helpTestRewriteCommand("select max(1) from pm1.g1 group by e1", "SELECT 1 FROM pm1.g1 GROUP BY e1");
     }
     
+    @Test public void testRewriteTrim() throws Exception {
+    	helpTestRewriteExpression("trim(pm1.g1.e1)", "rtrim(ltrim(pm1.g1.e1))", RealMetadataFactory.example1Cached());
+    }
+
+    @Test public void testRewriteTrim1() throws Exception {
+    	helpTestRewriteExpression("trim(leading from pm1.g1.e1)", "ltrim(pm1.g1.e1)", RealMetadataFactory.example1Cached());
+    }
+
 }

Modified: trunk/test-integration/common/src/test/java/org/teiid/connector/visitor/util/TestSQLStringVisitor.java
===================================================================
--- trunk/test-integration/common/src/test/java/org/teiid/connector/visitor/util/TestSQLStringVisitor.java	2011-08-04 12:09:55 UTC (rev 3358)
+++ trunk/test-integration/common/src/test/java/org/teiid/connector/visitor/util/TestSQLStringVisitor.java	2011-08-04 14:50:37 UTC (rev 3359)
@@ -432,5 +432,12 @@
     	Command command = FakeTranslationFactory.getInstance().getBQTTranslationUtility().parseCommand(sql, true, true);
     	assertEquals("SELECT MAX(g_0.IntNum) OVER (ORDER BY g_0.IntKey NULLS FIRST) FROM SmallA AS g_0", command.toString()); //$NON-NLS-1$
     }
+    
+    @Test public void testTrim() throws Exception {
+    	String sql = "select trim(both 'x' from stringkey) from bqt1.smalla";
+    	
+    	Command command = FakeTranslationFactory.getInstance().getBQTTranslationUtility().parseCommand(sql, true, true);
+    	assertEquals("SELECT trim('x' FROM g_0.StringKey) FROM SmallA AS g_0", command.toString()); //$NON-NLS-1$
+    }
 
 }



More information about the teiid-commits mailing list