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

teiid-commits at lists.jboss.org teiid-commits at lists.jboss.org
Fri Jul 22 12:26:10 EDT 2011


Author: shawkins
Date: 2011-07-22 12:26:08 -0400 (Fri, 22 Jul 2011)
New Revision: 3327

Added:
   trunk/runtime/src/main/java/org/teiid/odbc/PGUtil.java
   trunk/test-integration/common/src/test/resources/TestODBCSocketTransport/testColumnMetadataWithAlias.expected
Modified:
   trunk/api/src/main/java/org/teiid/language/visitor/SQLStringVisitor.java
   trunk/build/kits/jboss-container/deploy/teiid/teiid-cache-manager-jboss-beans-rename-me.xml
   trunk/build/kits/jboss-container/teiid-releasenotes.html
   trunk/cache-jbosscache/src/main/java/org/teiid/cache/jboss/JBossCacheFactory.java
   trunk/client/src/main/java/org/teiid/jdbc/DatabaseMetaDataImpl.java
   trunk/client/src/main/java/org/teiid/jdbc/JDBCURL.java
   trunk/client/src/main/java/org/teiid/jdbc/ResultSetMetaDataImpl.java
   trunk/client/src/main/java/org/teiid/jdbc/StatementImpl.java
   trunk/client/src/test/java/org/teiid/jdbc/TestConnection.java
   trunk/client/src/test/java/org/teiid/jdbc/TestTeiidDriver.java
   trunk/connectors/translator-jdbc/src/main/java/org/teiid/translator/jdbc/sqlserver/SQLServerExecutionFactory.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/sqlserver/TestSqlServerConversionVisitor.java
   trunk/connectors/translator-jdbc/src/test/java/org/teiid/translator/jdbc/teradata/TestTeradataTranslator.java
   trunk/documentation/client-developers-guide/src/main/docbook/en-US/content/jdbc-connection.xml
   trunk/documentation/client-developers-guide/src/main/docbook/en-US/content/jdbc-extensions.xml
   trunk/engine/pom.xml
   trunk/engine/src/main/java/org/teiid/dqp/internal/datamgr/LanguageBridgeFactory.java
   trunk/engine/src/main/java/org/teiid/dqp/internal/process/AbstractWorkItem.java
   trunk/engine/src/main/java/org/teiid/dqp/internal/process/DQPCore.java
   trunk/engine/src/main/java/org/teiid/dqp/internal/process/DQPWorkContext.java
   trunk/engine/src/main/java/org/teiid/dqp/internal/process/RequestWorkItem.java
   trunk/engine/src/main/java/org/teiid/query/mapping/xml/MappingNode.java
   trunk/engine/src/main/java/org/teiid/query/optimizer/relational/plantree/NodeConstants.java
   trunk/engine/src/main/java/org/teiid/query/optimizer/relational/rules/FrameUtil.java
   trunk/engine/src/main/java/org/teiid/query/optimizer/relational/rules/RuleMergeCriteria.java
   trunk/engine/src/main/java/org/teiid/query/rewriter/QueryRewriter.java
   trunk/engine/src/main/java/org/teiid/query/sql/symbol/QueryString.java
   trunk/engine/src/main/java/org/teiid/query/tempdata/TempTableStore.java
   trunk/engine/src/main/java/org/teiid/query/validator/UpdateValidator.java
   trunk/engine/src/main/java/org/teiid/query/xquery/saxon/DocumentWrapper.java
   trunk/engine/src/main/java/org/teiid/query/xquery/saxon/NodeWrapper.java
   trunk/engine/src/main/java/org/teiid/query/xquery/saxon/StreamingUtils.java
   trunk/engine/src/main/resources/org/teiid/query/i18n.properties
   trunk/engine/src/test/java/org/teiid/common/buffer/TestSTree.java
   trunk/engine/src/test/java/org/teiid/dqp/internal/datamgr/FakeConnector.java
   trunk/engine/src/test/java/org/teiid/dqp/internal/datamgr/TestConnectorManager.java
   trunk/engine/src/test/java/org/teiid/dqp/internal/datamgr/TestConnectorWorkItem.java
   trunk/engine/src/test/java/org/teiid/dqp/internal/datamgr/TestElementImpl.java
   trunk/engine/src/test/java/org/teiid/dqp/internal/process/TestWorkItemState.java
   trunk/engine/src/test/java/org/teiid/query/function/TestFunction.java
   trunk/engine/src/test/java/org/teiid/query/optimizer/TestSubqueryPushdown.java
   trunk/engine/src/test/java/org/teiid/query/processor/TestSQLXMLProcessing.java
   trunk/engine/src/test/java/org/teiid/query/rewriter/TestQueryRewriter.java
   trunk/engine/src/test/java/org/teiid/query/validator/TestValidator.java
   trunk/pom.xml
   trunk/runtime/src/main/java/org/teiid/odbc/ODBCClientRemote.java
   trunk/runtime/src/main/java/org/teiid/odbc/ODBCServerRemoteImpl.java
   trunk/runtime/src/main/java/org/teiid/transport/PgBackendProtocol.java
   trunk/runtime/src/main/resources/org/teiid/runtime/i18n.properties
   trunk/test-integration/common/src/test/java/org/teiid/jdbc/TestLocalConnections.java
   trunk/test-integration/common/src/test/java/org/teiid/jdbc/TestMMDatabaseMetaData.java
   trunk/test-integration/common/src/test/java/org/teiid/transport/TestODBCSocketTransport.java
   trunk/test-integration/common/src/test/resources/TestODBCSocketTransport/testPk.expected
   trunk/test-integration/common/src/test/resources/TestODBCSocketTransport/testPkPrepared.expected
Log:
forward merge of 7.4.1

Modified: trunk/api/src/main/java/org/teiid/language/visitor/SQLStringVisitor.java
===================================================================
--- trunk/api/src/main/java/org/teiid/language/visitor/SQLStringVisitor.java	2011-07-22 15:32:56 UTC (rev 3326)
+++ trunk/api/src/main/java/org/teiid/language/visitor/SQLStringVisitor.java	2011-07-22 16:26:08 UTC (rev 3327)
@@ -284,8 +284,7 @@
         if(elementID != null) {
             elemShortName = getName(elementID);            
         } else {
-            String elementName = obj.getName();
-            elemShortName = getShortName(elementName);
+            elemShortName = obj.getName();
         }
 
         // Check whether a subclass wants to replace the element name to use in special circumstances

Modified: trunk/build/kits/jboss-container/deploy/teiid/teiid-cache-manager-jboss-beans-rename-me.xml
===================================================================
--- trunk/build/kits/jboss-container/deploy/teiid/teiid-cache-manager-jboss-beans-rename-me.xml	2011-07-22 15:32:56 UTC (rev 3326)
+++ trunk/build/kits/jboss-container/deploy/teiid/teiid-cache-manager-jboss-beans-rename-me.xml	2011-07-22 16:26:08 UTC (rev 3327)
@@ -85,7 +85,7 @@
                             <!-- Hibernate 2LC can replicate custom types, so we use marshalling -->
                             <property name="useRegionBasedMarshalling">true</property>
                             <!-- Must match the value of "useRegionBasedMarshalling" -->
-                            <property name="inactiveOnStartup">true</property>
+                            <property name="inactiveOnStartup">false</property>
 
                             <!-- Disable asynchronous RPC marshalling/sending -->
                             <property name="serializationExecutorPoolSize">0</property>

Modified: trunk/build/kits/jboss-container/teiid-releasenotes.html
===================================================================
--- trunk/build/kits/jboss-container/teiid-releasenotes.html	2011-07-22 15:32:56 UTC (rev 3326)
+++ trunk/build/kits/jboss-container/teiid-releasenotes.html	2011-07-22 16:26:08 UTC (rev 3327)
@@ -34,7 +34,9 @@
 	<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.
 </UL>
+
 <h2><a name="Compatibility">Compatibility Issues</a></h2>
 <ul>
   <li>TRANSLATE/HAS CRITERIA has been deprecated.  An alternative approach to update procedures will be introduced in a subsequent version.
@@ -45,6 +47,8 @@
 <h4>from 7.4</h4>
 <ul>
   <li>OFFSET was added as a keyword. 
+  <li>ColumnReference.getName will always return just the element name.  Previously it inconsistently returned the qualified and unqualified form depending upon where the ColumnReference appeared.
+  <li>As per JDBC4, ResultSetMetadata.getColumnName will return the unaliased column name if available rather than return the alias.  Set useJDBC4ColumnNameAndLabelSemantics to false to use the alias name as the column name.
 </ul>
 
 <h4>from 7.3</h4>

Modified: trunk/cache-jbosscache/src/main/java/org/teiid/cache/jboss/JBossCacheFactory.java
===================================================================
--- trunk/cache-jbosscache/src/main/java/org/teiid/cache/jboss/JBossCacheFactory.java	2011-07-22 15:32:56 UTC (rev 3326)
+++ trunk/cache-jbosscache/src/main/java/org/teiid/cache/jboss/JBossCacheFactory.java	2011-07-22 16:26:08 UTC (rev 3327)
@@ -59,6 +59,7 @@
 			
 			if (!this.cacheStore.getCacheStatus().allowInvocations()) {
 				this.cacheStore.start();
+				this.cacheStore.getRegion(this.cacheStore.getRoot().getFqn(), true).activate();
 			}
 			
 			Node cacheRoot = this.cacheStore.getRoot().addChild(Fqn.fromString("Teiid")); //$NON-NLS-1$
@@ -67,6 +68,7 @@
 			
 			Region cacheRegion = this.cacheStore.getRegion(node.getFqn(), true);
 			cacheRegion.setEvictionRegionConfig(buildEvictionConfig(node.getFqn(), config));
+			cacheRegion.activate();
 						
 			JBossCache jc = null;
 			if (config != null && config.getPolicy().equals(Policy.EXPIRATION)) {

Modified: trunk/client/src/main/java/org/teiid/jdbc/DatabaseMetaDataImpl.java
===================================================================
--- trunk/client/src/main/java/org/teiid/jdbc/DatabaseMetaDataImpl.java	2011-07-22 15:32:56 UTC (rev 3326)
+++ trunk/client/src/main/java/org/teiid/jdbc/DatabaseMetaDataImpl.java	2011-07-22 16:26:08 UTC (rev 3327)
@@ -1433,18 +1433,21 @@
         // query string to be submitted to get table metadata info
         StringBuffer sqlQuery = new StringBuffer(QUERY_TABLES);
 
-        StringBuffer typesString = new StringBuffer("("); // criteria string for different table types //$NON-NLS-1$
-        
         if (types != null) {
-            // construct the criteria string
-            for(int i=0; i < types.length; i++) {
-                if (types[i] != null && types[i].length() > 0) {
-                    if (i > 0) {
-                        typesString.append(" OR "); //$NON-NLS-1$
-                    } 
-                    typesString.append(TABLE_TYPE).append(LIKE_ESCAPE);
-                }
-            }
+        	StringBuffer typesString = new StringBuffer("("); // criteria string for different table types //$NON-NLS-1$
+        	if (types.length == 0) {
+        		typesString.append("1 = 0"); //$NON-NLS-1$
+        	} else {
+	            // construct the criteria string
+	            for(int i=0; i < types.length; i++) {
+	                if (types[i] != null && types[i].length() > 0) {
+	                    if (i > 0) {
+	                        typesString.append(" OR "); //$NON-NLS-1$
+	                    } 
+	                    typesString.append(TABLE_TYPE).append(LIKE_ESCAPE);
+	                }
+	            }
+        	}
             typesString.append(")"); //$NON-NLS-1$
             sqlQuery.append(" AND ").append(typesString.toString()); //$NON-NLS-1$
         }


Property changes on: trunk/client/src/main/java/org/teiid/jdbc/DatabaseMetaDataImpl.java
___________________________________________________________________
Added: svn:mergeinfo
   + /branches/7.4.x/client/src/main/java/org/teiid/jdbc/DatabaseMetaDataImpl.java:3281-3325

Modified: trunk/client/src/main/java/org/teiid/jdbc/JDBCURL.java
===================================================================
--- trunk/client/src/main/java/org/teiid/jdbc/JDBCURL.java	2011-07-22 15:32:56 UTC (rev 3326)
+++ trunk/client/src/main/java/org/teiid/jdbc/JDBCURL.java	2011-07-22 16:26:08 UTC (rev 3327)
@@ -58,7 +58,8 @@
             ExecutionProperties.PROP_XML_FORMAT,
             ExecutionProperties.PROP_XML_VALIDATION,
             EmbeddedProfile.USE_CALLING_THREAD,
-            ExecutionProperties.DISABLE_LOCAL_TRANSACTIONS)));
+            ExecutionProperties.DISABLE_LOCAL_TRANSACTIONS,
+            ExecutionProperties.JDBC4COLUMNNAMEANDLABELSEMANTICS)));
     
     public static final Set<String> KNOWN_PROPERTIES = getKnownProperties();
     


Property changes on: trunk/client/src/main/java/org/teiid/jdbc/JDBCURL.java
___________________________________________________________________
Modified: svn:mergeinfo
   - /branches/7.4.x/client/src/main/java/org/teiid/jdbc/JDBCURL.java:3149-3217
   + /branches/7.4.x/client/src/main/java/org/teiid/jdbc/JDBCURL.java:3149-3217,3281-3325

Modified: trunk/client/src/main/java/org/teiid/jdbc/ResultSetMetaDataImpl.java
===================================================================
--- trunk/client/src/main/java/org/teiid/jdbc/ResultSetMetaDataImpl.java	2011-07-22 15:32:56 UTC (rev 3326)
+++ trunk/client/src/main/java/org/teiid/jdbc/ResultSetMetaDataImpl.java	2011-07-22 16:26:08 UTC (rev 3327)
@@ -39,7 +39,9 @@
     
     public ResultSetMetaDataImpl(MetadataProvider provider, String supportBackwardsCompatibility) {
     	this.provider = provider;
-    	this.useJDBC4ColumnNameAndLabelSemantics = (supportBackwardsCompatibility != null && supportBackwardsCompatibility.equalsIgnoreCase("false") ? false : true);
+    	if (supportBackwardsCompatibility != null) {
+    		this.useJDBC4ColumnNameAndLabelSemantics = Boolean.parseBoolean(supportBackwardsCompatibility);
+    	}
     }    
     
     /**


Property changes on: trunk/client/src/main/java/org/teiid/jdbc/ResultSetMetaDataImpl.java
___________________________________________________________________
Added: svn:mergeinfo
   + /branches/7.4.x/client/src/main/java/org/teiid/jdbc/ResultSetMetaDataImpl.java:3281-3325

Modified: trunk/client/src/main/java/org/teiid/jdbc/StatementImpl.java
===================================================================
--- trunk/client/src/main/java/org/teiid/jdbc/StatementImpl.java	2011-07-22 15:32:56 UTC (rev 3326)
+++ trunk/client/src/main/java/org/teiid/jdbc/StatementImpl.java	2011-07-22 16:26:08 UTC (rev 3327)
@@ -40,8 +40,6 @@
 import java.util.Properties;
 import java.util.TimeZone;
 import java.util.concurrent.ExecutionException;
-import java.util.concurrent.TimeUnit;
-import java.util.concurrent.TimeoutException;
 import java.util.logging.Level;
 import java.util.logging.Logger;
 import java.util.regex.Matcher;
@@ -538,11 +536,7 @@
 		});
     	if (synch) {
     		try {
-    			if (queryTimeoutMS > 0) {
-    				pendingResult.get(queryTimeoutMS, TimeUnit.MILLISECONDS);
-    			} else {
-    				pendingResult.get();
-    			}
+				pendingResult.get();
     			result.get(); //throw an exception if needed
     			return result;
     		} catch (ExecutionException e) {
@@ -552,8 +546,6 @@
     			throw TeiidSQLException.create(e);
     		} catch (InterruptedException e) {
     			timeoutOccurred();
-    		} catch (TimeoutException e) {
-    			timeoutOccurred();
 			}
     		throw new TeiidSQLException(JDBCPlugin.Util.getString("MMStatement.Timeout_before_complete")); //$NON-NLS-1$
     	}
@@ -578,7 +570,7 @@
         reqMsg.setExecutionId(this.currentRequestID);
         
         ResultsFuture.CompletionListener<ResultsMessage> compeletionListener = null;
-		if (queryTimeoutMS > 0 && !synch) {
+		if (queryTimeoutMS > 0) {
 			final CancelTask c = new QueryTimeoutCancelTask(queryTimeoutMS, this);
 			cancellationTimer.add(c);
 			compeletionListener = new ResultsFuture.CompletionListener<ResultsMessage>() {


Property changes on: trunk/client/src/main/java/org/teiid/jdbc/StatementImpl.java
___________________________________________________________________
Modified: svn:mergeinfo
   - /branches/7.4.x/client/src/main/java/org/teiid/jdbc/StatementImpl.java:3149-3217,3220-3275
   + /branches/7.4.x/client/src/main/java/org/teiid/jdbc/StatementImpl.java:3149-3217,3220-3275,3281-3325

Modified: trunk/client/src/test/java/org/teiid/jdbc/TestConnection.java
===================================================================
--- trunk/client/src/test/java/org/teiid/jdbc/TestConnection.java	2011-07-22 15:32:56 UTC (rev 3326)
+++ trunk/client/src/test/java/org/teiid/jdbc/TestConnection.java	2011-07-22 16:26:08 UTC (rev 3327)
@@ -22,7 +22,8 @@
 
 package org.teiid.jdbc;
 
-import static org.mockito.Mockito.*;
+import static org.mockito.Mockito.mock;
+import static org.mockito.Mockito.stub;
 
 import java.sql.SQLException;
 import java.util.Properties;
@@ -38,8 +39,6 @@
 import org.teiid.client.util.ResultsFuture;
 import org.teiid.client.xa.XATransactionException;
 import org.teiid.client.xa.XidImpl;
-import org.teiid.jdbc.BaseDataSource;
-import org.teiid.jdbc.ConnectionImpl;
 import org.teiid.net.ServerConnection;
 
 
@@ -48,13 +47,28 @@
 	protected static final String STD_DATABASE_NAME         = "QT_Ora9DS"; //$NON-NLS-1$
     protected static final int STD_DATABASE_VERSION      = 1; 
     
-    static String serverUrl = "jdbc:metamatrix:QT_Ora9DS at mm://localhost:7001;version=1;user=metamatrixadmin;password=mm"; //$NON-NLS-1$
+    static String serverUrl = "jdbc:teiid:QT_Ora9DS at mm://localhost:7001;version=1;user=metamatrixadmin;password=mm"; //$NON-NLS-1$
 
     public TestConnection(String name) {
         super(name);
     }
     
+    static class  InnerDriver extends TeiidDriver {
+    	String iurl = null;
+    	public InnerDriver(String url) {
+    		iurl = url;
+    	}
+
+    	public void parseUrl(Properties props) throws SQLException {
+ 				super.parseURL(iurl, props);
+    	}
+    }
+    
     public static ConnectionImpl getMMConnection() {
+    	return getMMConnection(serverUrl);  	
+    }
+    
+    public static ConnectionImpl getMMConnection(String url) {
     	ServerConnection mock = mock(ServerConnection.class);
     	DQP dqp = mock(DQP.class);
     	try {
@@ -79,13 +93,20 @@
 		} catch (XATransactionException e) {
 			throw new RuntimeException(e);
 		}
+		
+		Properties props = new Properties();
+		
+		try {
+			new InnerDriver(url).parseUrl(props);
+		} catch (SQLException e) {
+			// TODO Auto-generated catch block
+			e.printStackTrace();
+		}
+		
     	stub(mock.getService(DQP.class)).toReturn(dqp);
-    	Properties props = new Properties();
-    	props.setProperty(BaseDataSource.VDB_NAME, STD_DATABASE_NAME);
-    	props.setProperty(BaseDataSource.VDB_VERSION, String.valueOf(STD_DATABASE_VERSION));
-    	props.setProperty(BaseDataSource.USER_NAME, "metamatrixadmin"); //$NON-NLS-1$
-    	stub(mock.getLogonResult()).toReturn(new LogonResult(new SessionToken(1, "metamatrixadmin"), STD_DATABASE_NAME,STD_DATABASE_VERSION , "fake")); //$NON-NLS-1$
-    	return new ConnectionImpl(mock, props, serverUrl);
+    	
+    	stub(mock.getLogonResult()).toReturn(new LogonResult(new SessionToken(1, "admin"), STD_DATABASE_NAME,STD_DATABASE_VERSION , "fake")); //$NON-NLS-1$
+    	return new ConnectionImpl(mock, props, url);
     }
 
     public void testGetMetaData() throws Exception {
@@ -103,7 +124,7 @@
 
     /** test getUserName() through DriverManager */
     public void testGetUserName2() throws Exception {        
-        assertEquals("Actual userName is not equal to the expected one. ", "metamatrixadmin", getMMConnection().getUserName()); //$NON-NLS-1$ //$NON-NLS-2$
+        assertEquals("Actual userName is not equal to the expected one. ", "admin", getMMConnection().getUserName()); //$NON-NLS-1$ //$NON-NLS-2$
     }
       
     /** test isReadOnly default value on Connection */
@@ -129,4 +150,27 @@
             // error expected
         }
     }
+    
+    /**
+     * Test the default of the JDBC4 spec semantics is true
+     */
+    public void testDefaultSpec() throws Exception {
+        assertEquals("true",
+        		(getMMConnection().getExecutionProperties().getProperty(ExecutionProperties.JDBC4COLUMNNAMEANDLABELSEMANTICS) == null ? "true" : "false"));
+    } 
+    
+    /**
+     * Test turning off the JDBC 4 semantics
+     */
+    public void testTurnOnSpec() throws Exception {
+        assertEquals("true", getMMConnection(serverUrl + ";useJDBC4ColumnNameAndLabelSemantics=true").getExecutionProperties().getProperty(ExecutionProperties.JDBC4COLUMNNAMEANDLABELSEMANTICS));
+    }    
+    
+    /**
+     * Test turning off the JDBC 4 semantics
+     */
+    public void testTurnOffSpec() throws Exception {
+        assertEquals("false", getMMConnection(serverUrl + ";useJDBC4ColumnNameAndLabelSemantics=false").getExecutionProperties().getProperty(ExecutionProperties.JDBC4COLUMNNAMEANDLABELSEMANTICS));
+    }
+
 }


Property changes on: trunk/client/src/test/java/org/teiid/jdbc/TestConnection.java
___________________________________________________________________
Added: svn:mergeinfo
   + /branches/7.4.x/client/src/test/java/org/teiid/jdbc/TestConnection.java:3281-3325

Modified: trunk/client/src/test/java/org/teiid/jdbc/TestTeiidDriver.java
===================================================================
--- trunk/client/src/test/java/org/teiid/jdbc/TestTeiidDriver.java	2011-07-22 15:32:56 UTC (rev 3326)
+++ trunk/client/src/test/java/org/teiid/jdbc/TestTeiidDriver.java	2011-07-22 16:26:08 UTC (rev 3327)
@@ -138,7 +138,7 @@
     @Test public void testGetPropertyInfo1() throws Exception {        
         DriverPropertyInfo info[] = drv.getPropertyInfo("jdbc:teiid:vdb at mm://localhost:12345;applicationName=x", null); //$NON-NLS-1$
 
-        assertEquals(20, info.length);
+        assertEquals(21, info.length);
         assertEquals(false, info[0].required);
         assertEquals("ApplicationName", info[0].name); //$NON-NLS-1$
         assertEquals("x", info[0].value); //$NON-NLS-1$


Property changes on: trunk/client/src/test/java/org/teiid/jdbc/TestTeiidDriver.java
___________________________________________________________________
Modified: svn:mergeinfo
   - /branches/7.4.x/client/src/test/java/org/teiid/jdbc/TestTeiidDriver.java:3149-3217
   + /branches/7.4.x/client/src/test/java/org/teiid/jdbc/TestTeiidDriver.java:3149-3217,3281-3325

Modified: trunk/connectors/translator-jdbc/src/main/java/org/teiid/translator/jdbc/sqlserver/SQLServerExecutionFactory.java
===================================================================
--- trunk/connectors/translator-jdbc/src/main/java/org/teiid/translator/jdbc/sqlserver/SQLServerExecutionFactory.java	2011-07-22 15:32:56 UTC (rev 3326)
+++ trunk/connectors/translator-jdbc/src/main/java/org/teiid/translator/jdbc/sqlserver/SQLServerExecutionFactory.java	2011-07-22 16:26:08 UTC (rev 3327)
@@ -24,6 +24,8 @@
  */
 package org.teiid.translator.jdbc.sqlserver;
 
+import java.sql.Date;
+import java.sql.Timestamp;
 import java.util.ArrayList;
 import java.util.Arrays;
 import java.util.List;
@@ -203,8 +205,16 @@
     }
     
     @Override
+    public String translateLiteralDate(Date dateValue) {
+    	if (getDatabaseVersion().compareTo(V_2008) >= 0) {
+    		return super.translateLiteralDate(dateValue);
+    	}
+    	return super.translateLiteralTimestamp(new Timestamp(dateValue.getTime()));
+    }
+    
+    @Override
     public boolean hasTimeType() {
-    	return getDatabaseVersion().compareTo(V_2005) >= 0;
+    	return getDatabaseVersion().compareTo(V_2008) >= 0;
     }
     
     @Override

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-07-22 15:32:56 UTC (rev 3326)
+++ trunk/connectors/translator-jdbc/src/main/java/org/teiid/translator/jdbc/teradata/TeradataExecutionFactory.java	2011-07-22 16:26:08 UTC (rev 3327)
@@ -29,13 +29,21 @@
 import java.sql.Timestamp;
 import java.util.ArrayList;
 import java.util.Arrays;
+import java.util.HashMap;
 import java.util.List;
+import java.util.Map;
 
 import org.teiid.language.ColumnReference;
+import org.teiid.language.Command;
+import org.teiid.language.DerivedColumn;
 import org.teiid.language.Expression;
 import org.teiid.language.Function;
 import org.teiid.language.LanguageFactory;
 import org.teiid.language.Literal;
+import org.teiid.language.QueryExpression;
+import org.teiid.language.Select;
+import org.teiid.language.SortSpecification;
+import org.teiid.translator.ExecutionContext;
 import org.teiid.translator.SourceSystemFunctions;
 import org.teiid.translator.Translator;
 import org.teiid.translator.TranslatorException;
@@ -107,21 +115,12 @@
     	convert.addNumericBooleanConversions();
 		
 		registerFunctionModifier(SourceSystemFunctions.CONVERT, convert);
-		registerFunctionModifier(SourceSystemFunctions.SUBSTRING, new SubstrModifier(this.convert)); 
+		registerFunctionModifier(SourceSystemFunctions.SUBSTRING, new AliasModifier("substr")); //$NON-NLS-1$	
 		registerFunctionModifier(SourceSystemFunctions.RAND, new AliasModifier("random")); //$NON-NLS-1$				
 		registerFunctionModifier(SourceSystemFunctions.LOG, new AliasModifier("LN")); //$NON-NLS-1$
-		registerFunctionModifier(SourceSystemFunctions.LCASE, new StringOnlyModifier("LOWER", this.convert)); //$NON-NLS-1$
-		registerFunctionModifier(SourceSystemFunctions.UCASE, new StringOnlyModifier("UPPER", this.convert)); //$NON-NLS-1$
-		registerFunctionModifier(SourceSystemFunctions.LENGTH, new FunctionModifier() {
-			@Override
-			public List<?> translate(Function function) {
-				ArrayList target = new ArrayList();
-				target.add("character_length("); //$NON-NLS-1$
-				target.addAll(expressionToString(function.getParameters().get(0), convert));
-				target.add(")"); //$NON-NLS-1$
-				return target;
-			}
-		});
+		registerFunctionModifier(SourceSystemFunctions.LCASE, new AliasModifier("LOWER")); //$NON-NLS-1$
+		registerFunctionModifier(SourceSystemFunctions.UCASE, new AliasModifier("UPPER")); //$NON-NLS-1$
+		registerFunctionModifier(SourceSystemFunctions.LENGTH, new AliasModifier("character_length")); //$NON-NLS-1$
 		registerFunctionModifier(SourceSystemFunctions.CURDATE, new AliasModifier("CURRENT_DATE")); //$NON-NLS-1$
 		registerFunctionModifier(SourceSystemFunctions.CURTIME, new AliasModifier("CURRENT_TIME")); //$NON-NLS-1$
 		registerFunctionModifier(SourceSystemFunctions.YEAR, new ExtractModifier("YEAR")); //$NON-NLS-1$
@@ -143,9 +142,9 @@
         registerFunctionModifier(SourceSystemFunctions.LTRIM, new FunctionModifier() {
 			@Override
 			public List<?> translate(Function function) {
-				ArrayList target = new ArrayList();
+				ArrayList<Object> target = new ArrayList<Object>();
 				target.add("TRIM(LEADING FROM ");//$NON-NLS-1$
-				target.addAll(expressionToString(function.getParameters().get(0), convert));
+				target.add(function.getParameters().get(0));
 				target.add(")"); //$NON-NLS-1$				
 				return target; 
 			}
@@ -153,9 +152,9 @@
         registerFunctionModifier(SourceSystemFunctions.RTRIM, new FunctionModifier() {
 			@Override
 			public List<?> translate(Function function) {
-				ArrayList target = new ArrayList();
+				ArrayList<Object> target = new ArrayList<Object>();
 				target.add("TRIM(TRAILING FROM ");//$NON-NLS-1$
-				target.addAll(expressionToString(function.getParameters().get(0), convert));
+				target.add(function.getParameters().get(0));
 				target.add(")"); //$NON-NLS-1$
 				return target; 
 			}
@@ -216,7 +215,7 @@
 	
 	
     @Override
-    public List getSupportedFunctions() {
+    public List<String> getSupportedFunctions() {
         List<String> supportedFunctions = new ArrayList<String>();
         supportedFunctions.addAll(super.getSupportedFunctions());
 
@@ -317,8 +316,37 @@
     }
     
     @Override
-    public boolean supportsSetQueryOrderBy() {
-    	return false;
+    public List<?> translateCommand(Command command, ExecutionContext context) {
+    	if (command instanceof QueryExpression) {
+    		QueryExpression qe = (QueryExpression)command;
+    		//teradata prefers positional ordering
+    		if (qe.getOrderBy() != null) {
+    			Select select = qe.getProjectedQuery();
+    			List<DerivedColumn> derivedColumns = select.getDerivedColumns();
+    			Map<String, Integer> positions = new HashMap<String, Integer>();
+    			int i = 1;
+    			for (DerivedColumn derivedColumn : derivedColumns) {
+    				String name = derivedColumn.getAlias();
+    				if (name == null && derivedColumn.getExpression() instanceof ColumnReference) {
+    					ColumnReference cr = (ColumnReference)derivedColumn.getExpression();
+    					name = cr.toString();
+    				}
+					positions.put(name, i++);
+				}
+    			for (SortSpecification ss : qe.getOrderBy().getSortSpecifications()) {
+    				Expression ex = ss.getExpression();
+    				if (!(ex instanceof ColumnReference)) {
+    					continue;
+    				} 
+    				ColumnReference cr = (ColumnReference)ex;
+    				Integer position = positions.get(cr.toString());
+    				if (position != null) {
+    					ss.setExpression(new Literal(position, TypeFacility.RUNTIME_TYPES.INTEGER));
+    				}
+				}
+    		}
+    	}
+    	return super.translateCommand(command, context);
     }
     
     public static class LocateModifier extends FunctionModifier {
@@ -330,67 +358,31 @@
 		
     	@Override
 		public List<?> translate(Function function) {
-    		ArrayList target = new ArrayList();
+    		ArrayList<Object> target = new ArrayList<Object>();
     		Expression expr1 =  function.getParameters().get(0);
     		Expression expr2 =  function.getParameters().get(1);
     		if (function.getParameters().size() > 2) {
     			Expression expr3 =  function.getParameters().get(2);
 	    		target.add("position("); //$NON-NLS-1$
-	    		target.addAll(expressionToString(expr1, this.convertModifier));
+	    		target.add(expr1);
 	    		target.add( " in "); //$NON-NLS-1$
 	    		target.add("substr("); //$NON-NLS-1$
-	    		target.addAll(expressionToString(expr2, this.convertModifier));
+	    		target.add(expr2);
 	    		target.add(","); //$NON-NLS-1$
 	    		target.add(expr3);
 	    		target.add("))"); //$NON-NLS-1$	    		
     		}
     		else {
 	    		target.add("position("); //$NON-NLS-1$
-	    		target.addAll(expressionToString(expr1, this.convertModifier));
+	    		target.add(expr1);
 	    		target.add( " in "); //$NON-NLS-1$
-	    		target.addAll(expressionToString(expr2, this.convertModifier));
+	    		target.add(expr2);
 	    		target.add(")"); //$NON-NLS-1$
     		}
     		return target;
 		}
 	}
     
-    private static List<?> expressionToString(Expression expr, ConvertModifier modifier) {
-    	Class tgtType = expr.getType();
-		if (tgtType.equals(String.class) && ((expr instanceof Literal) || expr instanceof ColumnReference)) {
-			return Arrays.asList(expr);  
-		}
-		else if (tgtType.equals(String.class) && (expr instanceof Function)) {
-			
-			Function func = (Function)expr;
-			while(true) {
-				Expression arg1 = func.getParameters().get(0);
-				if ((arg1 instanceof Function) && ((Function)arg1).getName().equals("convert")) { //$NON-NLS-1$
-					func = (Function)arg1;
-				}
-				else {
-					break;
-				}
-			}
-			Expression arg1 = func.getParameters().get(0);
-			if (arg1 instanceof ColumnReference) {
-				ColumnReference ref = (ColumnReference)func.getParameters().get(0);
-				if(Number.class.isAssignableFrom(ref.getType())) {
-					ArrayList target = new ArrayList();
-					target.add("cast("); //$NON-NLS-1$
-					target.add(func.getParameters().get(0));
-					target.add(" AS varchar(100))"); //$NON-NLS-1$
-					return target;
-				}
-				else if (String.class.isAssignableFrom(ref.getType())) {
-					return Arrays.asList(ref);
-				}
-			}
-			return modifier.translate(func);	
-		} 
-		return Arrays.asList("cast(" , expr, " AS varchar(100))"); //$NON-NLS-1$ //$NON-NLS-2$ 
-    }
-
 	public static class ExtractModifier extends FunctionModifier {
     	private String type;
     	public ExtractModifier(String type) {
@@ -413,47 +405,6 @@
 		}
 	}
     
-    public static class StringOnlyModifier extends FunctionModifier {
-    	String funcName;
-    	ConvertModifier convertModifier;
-    	public StringOnlyModifier(String name, ConvertModifier converModifier) {
-    		this.funcName = name;
-    		this.convertModifier = converModifier;
-    	}
-    	@Override
-		public List<?> translate(Function function) {
-			Expression expr = function.getParameters().get(0);
-			ArrayList target = new ArrayList();
-			target.add(this.funcName);
-			target.add("("); //$NON-NLS-1$
-			target.addAll(expressionToString(expr, this.convertModifier));
-			target.add(")"); //$NON-NLS-1$
-			return target;
-		}
-	}
-    
-    public static class SubstrModifier extends FunctionModifier {
-    	ConvertModifier convertModifier;
-    	public SubstrModifier(ConvertModifier converModifier) {
-    		this.convertModifier = converModifier;
-    	}
-    	@Override
-		public List<?> translate(Function function) {
-			Expression expr = function.getParameters().get(0);
-			ArrayList target = new ArrayList();
-			target.add("substr("); //$NON-NLS-1$
-			target.addAll(expressionToString(expr, this.convertModifier));
-			target.add(","); //$NON-NLS-1$
-			target.add(function.getParameters().get(1)); 
-			if (function.getParameters().size() > 2 ) {
-				target.add(","); //$NON-NLS-1$
-				target.add(function.getParameters().get(2)); 
-			}
-			target.add(")"); //$NON-NLS-1$
-			return target;
-		}
-	}    
-    
     public static class LeftOrRightFunctionModifier extends FunctionModifier {
         private LanguageFactory langFactory;
         ConvertModifier convertModifier;
@@ -466,11 +417,11 @@
         @Override
         public List<?> translate(Function function) {
             List<Expression> args = function.getParameters();
-            ArrayList target = new ArrayList();
+            ArrayList<Object> target = new ArrayList<Object>();
             if (function.getName().equalsIgnoreCase("left")) { //$NON-NLS-1$
             	//substr(string, 1, length)
             	target.add("substr("); //$NON-NLS-1$
-            	target.addAll(expressionToString(args.get(0), this.convertModifier));
+            	target.add(args.get(0));
             	target.add(","); //$NON-NLS-1$
             	target.add(langFactory.createLiteral(Integer.valueOf(1), TypeFacility.RUNTIME_TYPES.INTEGER));
             	target.add(","); //$NON-NLS-1$
@@ -479,10 +430,10 @@
             } else if (function.getName().equalsIgnoreCase("right")) { //$NON-NLS-1$
             	//substr(case_size, character_length(case_size) -4) 
             	target.add("substr("); //$NON-NLS-1$
-            	target.addAll(expressionToString(args.get(0), this.convertModifier));
+            	target.add(args.get(0));
             	
             	target.add(",(character_length("); //$NON-NLS-1$
-            	target.addAll(expressionToString(args.get(0), this.convertModifier));
+            	target.add(args.get(0));
             	target.add(")-"); //$NON-NLS-1$
             	target.add(args.get(1));
             	target.add("+1))"); //$NON-NLS-1$ // offset for 1 based index
@@ -491,22 +442,4 @@
         }
     }    
     
-    public static class UpperOrLowerModifier extends FunctionModifier {
-    	String funcName;
-    	ConvertModifier convertModifier;
-    	public UpperOrLowerModifier(String name, ConvertModifier converModifier) {
-    		this.funcName = name;
-    		this.convertModifier = converModifier;
-    	}
-    	@Override
-		public List<?> translate(Function function) {
-			Expression expr = function.getParameters().get(0);
-			ArrayList target = new ArrayList();
-			target.add(this.funcName);
-			target.add("("); //$NON-NLS-1$
-			target.addAll(expressionToString(expr, this.convertModifier));
-			target.add(")"); //$NON-NLS-1$
-			return target;
-		}
-	}    
 }

Modified: trunk/connectors/translator-jdbc/src/test/java/org/teiid/translator/jdbc/sqlserver/TestSqlServerConversionVisitor.java
===================================================================
--- trunk/connectors/translator-jdbc/src/test/java/org/teiid/translator/jdbc/sqlserver/TestSqlServerConversionVisitor.java	2011-07-22 15:32:56 UTC (rev 3326)
+++ trunk/connectors/translator-jdbc/src/test/java/org/teiid/translator/jdbc/sqlserver/TestSqlServerConversionVisitor.java	2011-07-22 16:26:08 UTC (rev 3327)
@@ -49,9 +49,13 @@
     private static SQLServerExecutionFactory trans = new SQLServerExecutionFactory();
     
     @BeforeClass
-    public static void setup() throws TranslatorException {
+    public static void oneTimeSetup() throws TranslatorException {
         trans.start();
     }
+    
+    public void setUp() throws Exception {
+    	trans.setDatabaseVersion(SQLServerExecutionFactory.V_2005);
+    }
 
     public String getTestVDB() {
         return TranslationHelper.PARTS_VDB;
@@ -143,6 +147,25 @@
             output);        
     }
     
+    @Test public void testConvertDate() throws Exception {
+        String input = "select stringkey from bqt1.smalla where BQT1.SmallA.DateValue IN (convert('2000-01-12', date), convert('2000-02-02', date))"; //$NON-NLS-1$
+        String output = "SELECT SmallA.StringKey FROM SmallA WHERE SmallA.DateValue IN (CAST('2000-01-12 00:00:00.0' AS DATETIME), CAST('2000-02-02 00:00:00.0' AS DATETIME))"; //$NON-NLS-1$
+               
+        helpTestVisitor(getBQTVDB(),
+            input, 
+            output);        
+    }
+    
+    @Test public void testConvertDate2008() throws Exception {
+    	trans.setDatabaseVersion(SQLServerExecutionFactory.V_2008);
+        String input = "select stringkey from bqt1.smalla where BQT1.SmallA.DateValue IN (convert('2000-01-12', date), convert('2000-02-02', date))"; //$NON-NLS-1$
+        String output = "SELECT SmallA.StringKey FROM SmallA WHERE SmallA.DateValue IN (CAST('2000-01-12' AS DATE), CAST('2000-02-02' AS DATE))"; //$NON-NLS-1$
+               
+        helpTestVisitor(getBQTVDB(),
+            input, 
+            output);        
+    }
+    
     @Test public void testUniqueidentifier() throws Exception {
     	MetadataStore metadataStore = new MetadataStore();
     	Schema foo = RealMetadataFactory.createPhysicalModel("foo", metadataStore); //$NON-NLS-1$

Modified: trunk/connectors/translator-jdbc/src/test/java/org/teiid/translator/jdbc/teradata/TestTeradataTranslator.java
===================================================================
--- trunk/connectors/translator-jdbc/src/test/java/org/teiid/translator/jdbc/teradata/TestTeradataTranslator.java	2011-07-22 15:32:56 UTC (rev 3326)
+++ trunk/connectors/translator-jdbc/src/test/java/org/teiid/translator/jdbc/teradata/TestTeradataTranslator.java	2011-07-22 16:26:08 UTC (rev 3327)
@@ -31,6 +31,8 @@
 
 import org.junit.BeforeClass;
 import org.junit.Test;
+import org.teiid.cdk.api.TranslationUtility;
+import org.teiid.language.Command;
 import org.teiid.language.Expression;
 import org.teiid.language.Function;
 import org.teiid.language.In;
@@ -82,35 +84,61 @@
     
     @Test public void testIntegerToString() throws Exception {
         String input = "SELECT lcase(bigdecimalvalue) FROM BQT1.SMALLA"; 
-        String output = "SELECT LOWER(cast(SmallA.BigDecimalValue AS varchar(100))) FROM SmallA"; 
+        String output = "SELECT LOWER(cast(SmallA.BigDecimalValue AS varchar(4000))) FROM SmallA"; 
         TranslationHelper.helpTestVisitor(TranslationHelper.BQT_VDB, input, output, TRANSLATOR);    	
     }    
     
     @Test public void testSubString() throws Exception {
         String input = "SELECT intkey FROM BQT1.SmallA WHERE SUBSTRING(BQT1.SmallA.IntKey, 1) = '1' ORDER BY intkey"; 
-        String output = "SELECT SmallA.IntKey FROM SmallA WHERE substr(cast(SmallA.IntKey AS varchar(100)),1) = '1' ORDER BY SmallA.IntKey"; 
+        String output = "SELECT SmallA.IntKey FROM SmallA WHERE substr(cast(SmallA.IntKey AS varchar(4000)), 1) = '1' ORDER BY 1"; 
         TranslationHelper.helpTestVisitor(TranslationHelper.BQT_VDB, input, output, TRANSLATOR);    	
     }  
     
     @Test public void testSubString2() throws Exception {
         String input = "SELECT intkey FROM BQT1.SmallA WHERE SUBSTRING(BQT1.SmallA.IntKey, 1, 2) = '1' ORDER BY intkey"; 
-        String output = "SELECT SmallA.IntKey FROM SmallA WHERE substr(cast(SmallA.IntKey AS varchar(100)),1,2) = '1' ORDER BY SmallA.IntKey"; 
+        String output = "SELECT SmallA.IntKey FROM SmallA WHERE substr(cast(SmallA.IntKey AS varchar(4000)), 1, 2) = '1' ORDER BY 1"; 
         TranslationHelper.helpTestVisitor(TranslationHelper.BQT_VDB, input, output, TRANSLATOR);    	
     }     
     
     @Test public void testDateToString() throws Exception {
         String input = "SELECT intkey, UPPER(timevalue) AS UPPER FROM BQT1.SmallA ORDER BY intkey"; 
-        String output = "SELECT SmallA.IntKey, UPPER(cast(cast(SmallA.TimeValue AS FORMAT 'HH:MI:SS') AS VARCHAR(9))) AS UPPER FROM SmallA ORDER BY SmallA.IntKey"; 
+        String output = "SELECT SmallA.IntKey, UPPER(cast(cast(SmallA.TimeValue AS FORMAT 'HH:MI:SS') AS VARCHAR(9))) AS UPPER FROM SmallA ORDER BY 1"; 
         TranslationHelper.helpTestVisitor(TranslationHelper.BQT_VDB, input, output, TRANSLATOR);    	
     }    
     
     @Test public void testLocate() throws Exception {
         String input = "SELECT INTKEY, BIGDECIMALVALUE FROM BQT1.SmallA WHERE LOCATE('-', BIGDECIMALVALUE) = 1 ORDER BY intkey"; 
-        String output = "SELECT SmallA.IntKey, SmallA.BigDecimalValue FROM SmallA WHERE position('-' in cast(SmallA.BigDecimalValue AS varchar(100))) = 1 ORDER BY SmallA.IntKey"; 
+        String output = "SELECT SmallA.IntKey, SmallA.BigDecimalValue FROM SmallA WHERE position('-' in cast(SmallA.BigDecimalValue AS varchar(4000))) = 1 ORDER BY 1"; 
         TranslationHelper.helpTestVisitor(TranslationHelper.BQT_VDB, input, output, TRANSLATOR);    	
     }      
     
+    @Test public void testPositionalOrderBy() throws Exception {
+        String input = "SELECT INTKEY, BIGDECIMALVALUE FROM BQT1.SmallA ORDER BY intkey"; 
+        String output = "SELECT g_0.IntKey AS c_0, g_0.BigDecimalValue AS c_1 FROM SmallA AS g_0 ORDER BY 1"; 
+
+        TranslationUtility tu = TranslationHelper.getTranslationUtility(TranslationHelper.BQT_VDB, null);
+        Command command = tu.parseCommand(input, true, true);
+    	TranslationHelper.helpTestVisitor(output, TRANSLATOR, command);	
+    }
     
+    @Test public void testPositionalOrderByUnion() throws Exception {
+        String input = "SELECT a as b, b as a from (SELECT intkey as a, stringkey as b from BQT1.smalla union SELECT intkey as a, stringkey as b from BQT1.smalla) as x order by a"; 
+        String output = "SELECT v_0.c_0, v_0.c_1 FROM (SELECT g_1.IntKey AS c_0, g_1.StringKey AS c_1 FROM SmallA AS g_1 UNION SELECT g_0.IntKey AS c_0, g_0.StringKey AS c_1 FROM SmallA AS g_0) AS v_0 ORDER BY 2"; 
+
+        TranslationUtility tu = TranslationHelper.getTranslationUtility(TranslationHelper.BQT_VDB, null);
+        Command command = tu.parseCommand(input, true, true);
+    	TranslationHelper.helpTestVisitor(output, TRANSLATOR, command);	
+    }
+    
+    @Test public void testPositionalOrderByUnion1() throws Exception {
+        String input = "SELECT a as b from (SELECT intkey as a, stringkey as b from BQT1.smalla union SELECT intkey as a, stringkey as b from BQT1.smalla) as x order by x.b"; 
+        String output = "SELECT v_0.c_0 FROM (SELECT g_1.IntKey AS c_0, g_1.StringKey AS c_1 FROM SmallA AS g_1 UNION SELECT g_0.IntKey AS c_0, g_0.StringKey AS c_1 FROM SmallA AS g_0) AS v_0 ORDER BY v_0.c_1"; 
+
+        TranslationUtility tu = TranslationHelper.getTranslationUtility(TranslationHelper.BQT_VDB, null);
+        Command command = tu.parseCommand(input, true, true);
+    	TranslationHelper.helpTestVisitor(output, TRANSLATOR, command);	
+    }
+    
     @Test public void testByteToString() throws Exception {
         helpTest(LANG_FACTORY.createLiteral(new Byte((byte)1), Byte.class), "string", "cast(1 AS varchar(4000))"); 
     }
@@ -194,13 +222,13 @@
 	
 	@Test public void testRightFunction() throws Exception {
 		String input = "SELECT INTKEY, FLOATNUM FROM BQT1.SmallA WHERE right(FLOATNUM, 2) <> 0 ORDER BY INTKEY";
-		String out = "SELECT SmallA.IntKey, SmallA.FloatNum FROM SmallA WHERE substr(cast(SmallA.FloatNum AS varchar(100)),(character_length(cast(SmallA.FloatNum AS varchar(100)))-2+1)) <> '0' ORDER BY SmallA.IntKey";
+		String out = "SELECT SmallA.IntKey, SmallA.FloatNum FROM SmallA WHERE substr(cast(SmallA.FloatNum AS varchar(4000)),(character_length(cast(SmallA.FloatNum AS varchar(4000)))-2+1)) <> '0' ORDER BY 1";
 		TranslationHelper.helpTestVisitor(TranslationHelper.BQT_VDB, null, input, out, TRANSLATOR);		
 	}
 	
 	@Test public void testLocateFunction() throws Exception {
 		String input = "SELECT INTKEY, STRINGKEY, SHORTVALUE FROM BQT1.SmallA WHERE (LOCATE(0, STRINGKEY) = 2) OR (LOCATE(2, SHORTVALUE, 4) = 6) ORDER BY intkey";
-		String out = "SELECT SmallA.IntKey, SmallA.StringKey, SmallA.ShortValue FROM SmallA WHERE position('0' in SmallA.StringKey) = 2 OR position('2' in substr(cast(SmallA.ShortValue AS varchar(100)),4)) = 6 ORDER BY SmallA.IntKey";
+		String out = "SELECT SmallA.IntKey, SmallA.StringKey, SmallA.ShortValue FROM SmallA WHERE position('0' in SmallA.StringKey) = 2 OR position('2' in substr(cast(SmallA.ShortValue AS varchar(4000)),4)) = 6 ORDER BY 1";
 		TranslationHelper.helpTestVisitor(TranslationHelper.BQT_VDB, null, input, out, TRANSLATOR);		
 	}	
 }

Modified: trunk/documentation/client-developers-guide/src/main/docbook/en-US/content/jdbc-connection.xml
===================================================================
--- trunk/documentation/client-developers-guide/src/main/docbook/en-US/content/jdbc-connection.xml	2011-07-22 15:32:56 UTC (rev 3326)
+++ trunk/documentation/client-developers-guide/src/main/docbook/en-US/content/jdbc-connection.xml	2011-07-22 16:26:08 UTC (rev 3327)
@@ -250,10 +250,9 @@
                             <code>boolean</code>
                         </entry>						
                         <entry>
-                            <para>A change was made in JDBC4 so that when an 'Alias' is used it will
-							now be returned as the label.   Prior to this, it was returned as
-							the name.   Setting this property to false will enable
-							backwards compatibility when JDBC3 and older support is still required.
+                           <para>A change was made in JDBC4 to return unaliased column names as the ResultSetMetadata column name. 
+                            Prior to this, if a column alias were used it was returned as the column name.   Setting this property to false will enable
+							backwards compatibility when JDBC3 and older support is still required.  Defaults to true.
 							</para>
                         </entry>
                     </row>						

Modified: trunk/documentation/client-developers-guide/src/main/docbook/en-US/content/jdbc-extensions.xml
===================================================================
--- trunk/documentation/client-developers-guide/src/main/docbook/en-US/content/jdbc-extensions.xml	2011-07-22 15:32:56 UTC (rev 3326)
+++ trunk/documentation/client-developers-guide/src/main/docbook/en-US/content/jdbc-extensions.xml	2011-07-22 16:26:08 UTC (rev 3327)
@@ -175,11 +175,7 @@
                             <code>JDBC4COLUMNNAMEANDLABELSEMANTICS / useJDBC4ColumnNameAndLabelSemantics</code>
                         </entry>
                         <entry>
-                            <para>A change was made in JDBC4 so that when an 'Alias' is used it will.
-							now be returned as the label.   Prior to this, it was returned as
-							the name.   Setting this property to false will enable
-							backwards compatibility when JDBC3 and older support is still required.
-							</para>
+                            <para>Same as the connection property.</para>
                         </entry>
                     </row>						
                  </tbody>

Modified: trunk/engine/pom.xml
===================================================================
--- trunk/engine/pom.xml	2011-07-22 15:32:56 UTC (rev 3326)
+++ trunk/engine/pom.xml	2011-07-22 16:26:08 UTC (rev 3327)
@@ -78,14 +78,8 @@
 
 		<dependency>
 			<groupId>net.sourceforge.saxon</groupId>
-			<artifactId>saxon</artifactId>
+			<artifactId>saxonhe</artifactId>
 		</dependency>
-
-		<dependency>
-			<groupId>net.sourceforge.saxon</groupId>
-			<classifier>dom</classifier>
-			<artifactId>saxon</artifactId>
-		</dependency>
 		
 		<dependency>
 			<groupId>com.googlecode.json-simple</groupId>
@@ -106,4 +100,4 @@
 
 	</dependencies>
 
-</project>
\ No newline at end of file
+</project>

Modified: trunk/engine/src/main/java/org/teiid/dqp/internal/datamgr/LanguageBridgeFactory.java
===================================================================
--- trunk/engine/src/main/java/org/teiid/dqp/internal/datamgr/LanguageBridgeFactory.java	2011-07-22 15:32:56 UTC (rev 3326)
+++ trunk/engine/src/main/java/org/teiid/dqp/internal/datamgr/LanguageBridgeFactory.java	2011-07-22 16:26:08 UTC (rev 3327)
@@ -115,6 +115,7 @@
 import org.teiid.query.sql.symbol.GroupSymbol;
 import org.teiid.query.sql.symbol.ScalarSubquery;
 import org.teiid.query.sql.symbol.SearchedCaseExpression;
+import org.teiid.query.sql.symbol.SelectSymbol;
 import org.teiid.query.sql.symbol.SingleElementSymbol;
 import org.teiid.translator.TranslatorException;
 
@@ -179,9 +180,9 @@
 
     /* Query */
     Select translate(Query query) {
-        List symbols = query.getSelect().getSymbols();
+        List<SelectSymbol> symbols = query.getSelect().getSymbols();
         List<DerivedColumn> translatedSymbols = new ArrayList<DerivedColumn>(symbols.size());
-        for (Iterator i = symbols.iterator(); i.hasNext();) {
+        for (Iterator<SelectSymbol> i = symbols.iterator(); i.hasNext();) {
             SingleElementSymbol symbol = (SingleElementSymbol)i.next();
             String alias = null;
             if(symbol instanceof AliasSymbol) {
@@ -375,7 +376,7 @@
 
     In translate(SetCriteria criteria) {
         Collection expressions = criteria.getValues();
-        List translatedExpressions = new ArrayList();
+        List<org.teiid.language.Expression> translatedExpressions = new ArrayList<org.teiid.language.Expression>();
         for (Iterator i = expressions.iterator(); i.hasNext();) {
             translatedExpressions.add(translate((Expression)i.next()));
         }
@@ -423,13 +424,13 @@
         return new SubqueryComparison(translate(criteria.getLeftExpression()),
                                   operator,
                                   quantifier,
-                                  translate((QueryCommand)criteria.getCommand()));
+                                  translate(criteria.getCommand()));
     }
 
     SubqueryIn translate(SubquerySetCriteria criteria) {
         return new SubqueryIn(translate(criteria.getExpression()),
                                   criteria.isNegated(),
-                                  translate((QueryCommand)criteria.getCommand()));
+                                  translate(criteria.getCommand()));
     }
 
     Not translate(NotCriteria criteria) {
@@ -462,7 +463,7 @@
             if(items.get(i).isUnrelated() || (!set && symbol instanceof ElementSymbol)){
             	orderByItem = new SortSpecification(direction, translate(symbol));                                
             } else {
-            	orderByItem = new SortSpecification(direction, new ColumnReference(null, symbol.getOutputName(), null, symbol.getType()));
+            	orderByItem = new SortSpecification(direction, new ColumnReference(null, SingleElementSymbol.getShortName(symbol.getOutputName()), null, symbol.getType()));
             }
             orderByItem.setNullOrdering(items.get(i).getNullOrdering());
             translatedItems.add(orderByItem);
@@ -558,7 +559,7 @@
     }
 
     ColumnReference translate(ElementSymbol symbol) {
-        ColumnReference element = new ColumnReference(translate(symbol.getGroupSymbol()), symbol.getOutputName(), null, symbol.getType());
+        ColumnReference element = new ColumnReference(translate(symbol.getGroupSymbol()), SingleElementSymbol.getShortName(symbol.getOutputName()), null, symbol.getType());
         if (element.getTable().getMetadataObject() == null) {
             return element;
         }
@@ -746,10 +747,10 @@
     
     /* Batched Updates */
     BatchedUpdates translate(BatchedUpdateCommand command) {
-        List updates = command.getUpdateCommands();
+        List<Command> updates = command.getUpdateCommands();
         List<org.teiid.language.Command> translatedUpdates = new ArrayList<org.teiid.language.Command>(updates.size());
-        for (Iterator i = updates.iterator(); i.hasNext();) {
-            translatedUpdates.add(translate((Command)i.next()));
+        for (Iterator<Command> i = updates.iterator(); i.hasNext();) {
+            translatedUpdates.add(translate(i.next()));
         }
         return new BatchedUpdates(translatedUpdates);
     }

Modified: trunk/engine/src/main/java/org/teiid/dqp/internal/process/AbstractWorkItem.java
===================================================================
--- trunk/engine/src/main/java/org/teiid/dqp/internal/process/AbstractWorkItem.java	2011-07-22 15:32:56 UTC (rev 3326)
+++ trunk/engine/src/main/java/org/teiid/dqp/internal/process/AbstractWorkItem.java	2011-07-22 16:26:08 UTC (rev 3327)
@@ -26,7 +26,6 @@
 import javax.resource.spi.work.WorkEvent;
 import javax.resource.spi.work.WorkListener;
 
-import org.teiid.core.TeiidRuntimeException;
 import org.teiid.logging.LogManager;
 
 
@@ -43,23 +42,14 @@
     
     private ThreadState threadState = ThreadState.MORE_WORK;
     private volatile boolean isProcessing;
-    private Thread callingThread;
     
-    public AbstractWorkItem(Thread callingThread) {
-    	this.callingThread = callingThread;
-    }
-    
     public void run() {
-    	do {
-			startProcessing();
-			try {
-				process();
-			} finally {
-				if (!endProcessing()) {
-					break;
-				}
-			}
-    	} while (!isDoneProcessing());
+		startProcessing();
+		try {
+			process();
+		} finally {
+			endProcessing();
+		}
     }
     
     synchronized ThreadState getThreadState() {
@@ -79,10 +69,7 @@
     	this.threadState = ThreadState.WORKING;
 	}
     
-    /**
-     * @return true if processing should be continued
-     */
-    final private synchronized boolean endProcessing() {
+    private synchronized void endProcessing() {
     	isProcessing = false;
     	logTrace("end processing"); //$NON-NLS-1$
     	switch (this.threadState) {
@@ -92,21 +79,20 @@
 	        		this.threadState = ThreadState.DONE;
 	        	} else {
 		    		this.threadState = ThreadState.IDLE;
-		    		return pauseProcessing();
+		    		pauseProcessing();
 	        	}
 	    		break;
 	    	case MORE_WORK:
 	    		if (isDoneProcessing()) {
 	    			logTrace("done processing - ignoring more"); //$NON-NLS-1$
 	        		this.threadState = ThreadState.DONE;
-	        	} else if (this.callingThread == null) {
-        			resumeProcessing();
+	        	} else {
+	        		resumeProcessing();
 	        	}
 	    		break;
     		default:
     			throw new IllegalStateException("Should not END on " + this.threadState); //$NON-NLS-1$
     	}
-    	return this.callingThread != null;
     }
     
     protected boolean isIdle() {
@@ -117,8 +103,9 @@
     	moreWork(true);
     }
     
-    final protected synchronized void moreWork(boolean ignoreDone) {
+    protected synchronized void moreWork(boolean ignoreDone) {
     	logTrace("more work"); //$NON-NLS-1$
+    	this.notifyAll();
     	switch (this.threadState) {
 	    	case WORKING:
 	    		this.threadState = ThreadState.MORE_WORK;
@@ -127,15 +114,7 @@
 	    		break;
 	    	case IDLE:
 	    		this.threadState = ThreadState.MORE_WORK;
-        		if (this.callingThread != null) {
-        			if (this.callingThread == Thread.currentThread()) {
-        				run(); //restart with the calling thread
-        			} else {
-        				this.notifyAll(); //notify the waiting caller
-        			}
-        		} else {
-        			resumeProcessing();
-        		}
+	    		resumeProcessing();
 	    		break;
 			default:
 				if (!ignoreDone) {
@@ -151,33 +130,8 @@
     
     protected abstract void process();
 
-	protected boolean pauseProcessing() {
-		if (this.callingThread != null && !shouldPause()) {
-			return false;
-		}
-		while (this.callingThread != null && this.getThreadState() == ThreadState.IDLE) {
-			try {
-				this.wait(); //the lock should already be held
-			} catch (InterruptedException e) {
-				interrupted(e);
-			}
-		}
-		return this.callingThread != null;
+	protected void pauseProcessing() {
 	}
-	
-	/**
-	 * only called for synch processing
-	 */
-	protected boolean shouldPause() {
-		return false;
-	}
-
-	/**
-	 * only called for synch processing
-	 */
-	protected void interrupted(InterruptedException e) {
-		throw new TeiidRuntimeException(e);
-	}
     
     protected abstract void resumeProcessing();
 	

Modified: trunk/engine/src/main/java/org/teiid/dqp/internal/process/DQPCore.java
===================================================================
--- trunk/engine/src/main/java/org/teiid/dqp/internal/process/DQPCore.java	2011-07-22 15:32:56 UTC (rev 3326)
+++ trunk/engine/src/main/java/org/teiid/dqp/internal/process/DQPCore.java	2011-07-22 16:26:08 UTC (rev 3327)
@@ -93,9 +93,11 @@
 		private long creationTime = System.currentTimeMillis();
 		private DQPWorkContext workContext = DQPWorkContext.getWorkContext();
 		private List<CompletionListener<T>> completionListeners = new LinkedList<CompletionListener<T>>();
+		private String parentName;
 
 		public FutureWork(final Callable<T> processor, int priority) {
 			super(processor);
+			this.parentName = Thread.currentThread().getName();
 			this.priority = priority;
 		}
 		
@@ -105,6 +107,12 @@
 		}
 		
 		@Override
+		public void run() {
+			LogManager.logDetail(LogConstants.CTX_DQP, "Running task for parent thread", parentName); //$NON-NLS-1$
+			super.run();
+		}
+		
+		@Override
 		public int getPriority() {
 			return priority;
 		}
@@ -344,6 +352,7 @@
 			}
 		}
         if (runInThread) {
+        	workItem.useCallingThread = true;
         	workItem.run();
         }
         return resultsFuture;
@@ -721,6 +730,8 @@
         processorDataManager.setMetadataRepository(metadataRepository);
 		dataTierMgr = new TempTableDataManager(processorDataManager, this.bufferManager, this.processWorkerPool, this.rsCache, this.matTables, this.cacheFactory);
         dataTierMgr.setEventDistributor(eventDistributor);
+        
+        LogManager.logDetail(LogConstants.CTX_DQP, "DQPCore started maxThreads", this.config.getMaxThreads(), "maxActivePlans", this.maxActivePlans, "source concurrency", this.userRequestSourceConcurrency); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$
 	}
 	
 	public void setBufferService(BufferService service) {

Modified: trunk/engine/src/main/java/org/teiid/dqp/internal/process/DQPWorkContext.java
===================================================================
--- trunk/engine/src/main/java/org/teiid/dqp/internal/process/DQPWorkContext.java	2011-07-22 15:32:56 UTC (rev 3326)
+++ trunk/engine/src/main/java/org/teiid/dqp/internal/process/DQPWorkContext.java	2011-07-22 16:26:08 UTC (rev 3327)
@@ -188,11 +188,8 @@
 	}
 	
 	public void runInContext(final Runnable runnable) {
-		DQPWorkContext.setWorkContext(this);
-		boolean associated = false;
-		if (securityHelper != null && this.getSubject() != null) {
-			associated = securityHelper.assosiateSecurityContext(this.getSecurityDomain(), this.getSecurityContext());			
-		}
+		DQPWorkContext previous = DQPWorkContext.getWorkContext();
+		boolean associated = attachDQPWorkContext();
 		try {
 			runnable.run();
 		} finally {
@@ -200,9 +197,21 @@
 				securityHelper.clearSecurityContext(this.getSecurityDomain());			
 			}
 			DQPWorkContext.releaseWorkContext();
+			if (previous != null) {
+				previous.attachDQPWorkContext();
+			}
 		}
 	}
 
+	private boolean attachDQPWorkContext() {
+		DQPWorkContext.setWorkContext(this);
+		boolean associated = false;
+		if (securityHelper != null && this.getSubject() != null) {
+			associated = securityHelper.assosiateSecurityContext(this.getSecurityDomain(), this.getSecurityContext());			
+		}
+		return associated;
+	}
+
 	public HashMap<String, DataPolicy> getAllowedDataPolicies() {
 		if (this.policies == null) {
 	    	this.policies = new HashMap<String, DataPolicy>();

Modified: trunk/engine/src/main/java/org/teiid/dqp/internal/process/RequestWorkItem.java
===================================================================
--- trunk/engine/src/main/java/org/teiid/dqp/internal/process/RequestWorkItem.java	2011-07-22 15:32:56 UTC (rev 3326)
+++ trunk/engine/src/main/java/org/teiid/dqp/internal/process/RequestWorkItem.java	2011-07-22 16:26:08 UTC (rev 3327)
@@ -162,8 +162,10 @@
     /**The time when command begins processing on the server.*/
     private long processingTimestamp = System.currentTimeMillis();
     
+    protected boolean useCallingThread;
+    private volatile boolean hasThread;
+    
     public RequestWorkItem(DQPCore dqpCore, RequestMessage requestMsg, Request request, ResultsReceiver<ResultsMessage> receiver, RequestID requestID, DQPWorkContext workContext) {
-    	super(workContext.useCallingThread() || requestMsg.isSync() ? Thread.currentThread() : null);
         this.requestMsg = requestMsg;
         this.requestID = requestID;
         this.processorTimeslice = dqpCore.getProcessorTimeSlice();
@@ -196,24 +198,65 @@
 	protected boolean isDoneProcessing() {
 		return isClosed;
 	}
+		
+	@Override
+	public void run() {
+		hasThread = true;
+		try {
+			while (!isDoneProcessing()) {
+				super.run();
+				if (!useCallingThread) {
+					break;
+				}
+				//should use the calling thread
+				synchronized (this) {
+					if (this.resultsReceiver == null) {
+						break; //allow results to be processed by calling thread
+					}
+					if (this.getThreadState() == ThreadState.MORE_WORK) {
+						continue;
+					}
+					try {
+						wait();
+					} catch (InterruptedException e) {
+						try {
+							requestCancel();
+						} catch (TeiidComponentException e1) {
+							throw new TeiidRuntimeException(e1);
+						}
+					}
+				}
+			}
+		} finally {
+			hasThread = false;
+		}
+	}
 
 	@Override
 	protected void resumeProcessing() {
-		if (doneProducingBatches && !closeRequested && !isCanceled) {
-			this.run(); // just run in the IO thread
-		} else {
+		if (!this.useCallingThread) {
 			dqpCore.addWork(this);
 		}
 	}
 	
-	@Override
-	protected void interrupted(InterruptedException e) {
-		try {
-			this.requestCancel();
-		} catch (TeiidComponentException e1) {
-			throw new TeiidRuntimeException(e1);
+	/**
+	 * Special call from request threads to allow resumption of processing by
+	 * the calling thread.
+	 */
+	public void doMoreWork() {
+		boolean run = false;
+		synchronized (this) {
+			moreWork();
+			if (!useCallingThread || this.getThreadState() != ThreadState.MORE_WORK) {
+				return;
+			}
+			run = !hasThread;
 		}
-		super.interrupted(e);
+		if (run) {
+			//run outside of the lock
+			LogManager.logDetail(LogConstants.CTX_DQP, "Restarting processing using the calling thread", requestID); //$NON-NLS-1$
+			run();
+		}
 	}
 	
 	@Override
@@ -293,7 +336,7 @@
 	}
 
 	private void suspend() {
-		if (this.transactionState == TransactionState.ACTIVE && this.transactionContext.getTransaction() != null) {
+		if ((this.transactionState != TransactionState.NONE) && this.transactionContext.getTransaction() != null) {
 			try {
 				this.transactionService.suspend(this.transactionContext);
 			} catch (XATransactionException e) {
@@ -650,12 +693,6 @@
 		return new TeiidProcessingException(exception, SQLStates.QUERY_CANCELED, exception.getMessage());
 	}
     
-    @Override
-    protected boolean shouldPause() {
-    	//if we are waiting on results it's ok to pause
-    	return this.resultsReceiver != null;
-    }
-
     private static List<ParameterInfo> getParameterInfo(StoredProcedure procedure) {
         List<ParameterInfo> paramInfos = new ArrayList<ParameterInfo>();
         
@@ -750,12 +787,12 @@
     	if (!this.doneProducingBatches) {
     		this.requestCancel(); //pending work should be canceled for fastest clean up
     	}
-    	this.moreWork();
+    	this.doMoreWork();
     }
     
     public void requestMore(int batchFirst, int batchLast, ResultsReceiver<ResultsMessage> receiver) {
     	this.requestResults(batchFirst, batchLast, receiver);
-    	this.moreWork(); 
+    	this.doMoreWork(); 
     }
     
     public void closeAtomicRequest(AtomicRequestID atomicRequestId) {

Modified: trunk/engine/src/main/java/org/teiid/query/mapping/xml/MappingNode.java
===================================================================
--- trunk/engine/src/main/java/org/teiid/query/mapping/xml/MappingNode.java	2011-07-22 15:32:56 UTC (rev 3326)
+++ trunk/engine/src/main/java/org/teiid/query/mapping/xml/MappingNode.java	2011-07-22 16:26:08 UTC (rev 3327)
@@ -25,8 +25,8 @@
 import java.io.PrintStream;
 import java.io.Serializable;
 import java.util.ArrayList;
-import java.util.HashMap;
 import java.util.Iterator;
+import java.util.LinkedHashMap;
 import java.util.LinkedList;
 import java.util.List;
 import java.util.Map;
@@ -214,7 +214,7 @@
      */
     public Map<MappingNodeConstants.Properties, Object> getNodeProperties(){
         if(nodeProperties == null) {
-            nodeProperties = new HashMap<MappingNodeConstants.Properties, Object>();
+            nodeProperties = new LinkedHashMap<MappingNodeConstants.Properties, Object>();
         }
         return nodeProperties;
     }

Modified: trunk/engine/src/main/java/org/teiid/query/optimizer/relational/plantree/NodeConstants.java
===================================================================
--- trunk/engine/src/main/java/org/teiid/query/optimizer/relational/plantree/NodeConstants.java	2011-07-22 15:32:56 UTC (rev 3326)
+++ trunk/engine/src/main/java/org/teiid/query/optimizer/relational/plantree/NodeConstants.java	2011-07-22 16:26:08 UTC (rev 3327)
@@ -43,7 +43,6 @@
         public static final int SET_OP = 1<<8;
         public static final int NULL = 1<<9;
         public static final int TUPLE_LIMIT = 1<<10;
-        public static final int WITH = 1<<11;
     }
 
     /**
@@ -64,7 +63,6 @@
             case NodeConstants.Types.SET_OP:        return "SetOperation"; //$NON-NLS-1$
             case NodeConstants.Types.NULL:          return "Null"; //$NON-NLS-1$
             case NodeConstants.Types.TUPLE_LIMIT:   return "TupleLimit"; //$NON-NLS-1$
-            case NodeConstants.Types.WITH:   		return "With"; //$NON-NLS-1$
             default:                                return "Unknown: " + type; //$NON-NLS-1$
         }
     }

Modified: trunk/engine/src/main/java/org/teiid/query/optimizer/relational/rules/FrameUtil.java
===================================================================
--- trunk/engine/src/main/java/org/teiid/query/optimizer/relational/rules/FrameUtil.java	2011-07-22 15:32:56 UTC (rev 3326)
+++ trunk/engine/src/main/java/org/teiid/query/optimizer/relational/rules/FrameUtil.java	2011-07-22 16:26:08 UTC (rev 3327)
@@ -37,7 +37,6 @@
 import org.teiid.api.exception.query.QueryPlannerException;
 import org.teiid.core.TeiidComponentException;
 import org.teiid.core.TeiidProcessingException;
-import org.teiid.core.TeiidRuntimeException;
 import org.teiid.core.util.Assertion;
 import org.teiid.query.QueryPlugin;
 import org.teiid.query.metadata.QueryMetadataInterface;
@@ -50,17 +49,21 @@
 import org.teiid.query.resolver.util.AccessPattern;
 import org.teiid.query.resolver.util.ResolverUtil;
 import org.teiid.query.rewriter.QueryRewriter;
+import org.teiid.query.sql.LanguageObject;
 import org.teiid.query.sql.lang.Command;
 import org.teiid.query.sql.lang.CompoundCriteria;
 import org.teiid.query.sql.lang.Criteria;
 import org.teiid.query.sql.lang.GroupBy;
 import org.teiid.query.sql.lang.OrderBy;
+import org.teiid.query.sql.lang.OrderByItem;
 import org.teiid.query.sql.lang.QueryCommand;
 import org.teiid.query.sql.lang.Select;
 import org.teiid.query.sql.lang.StoredProcedure;
+import org.teiid.query.sql.symbol.AliasSymbol;
 import org.teiid.query.sql.symbol.Constant;
 import org.teiid.query.sql.symbol.ElementSymbol;
 import org.teiid.query.sql.symbol.Expression;
+import org.teiid.query.sql.symbol.ExpressionSymbol;
 import org.teiid.query.sql.symbol.GroupSymbol;
 import org.teiid.query.sql.symbol.SingleElementSymbol;
 import org.teiid.query.sql.util.SymbolMap;
@@ -125,15 +128,15 @@
 	}
     
     static boolean canConvertAccessPatterns(PlanNode sourceNode) {
-        List accessPatterns = (List)sourceNode.getProperty(NodeConstants.Info.ACCESS_PATTERNS);
+        List<AccessPattern> accessPatterns = (List)sourceNode.getProperty(NodeConstants.Info.ACCESS_PATTERNS);
         if (accessPatterns == null) {
             return true;
         }
         SymbolMap symbolMap = (SymbolMap)sourceNode.getProperty(NodeConstants.Info.SYMBOL_MAP);
-        for (Iterator i = accessPatterns.iterator(); i.hasNext();) {
-            AccessPattern ap = (AccessPattern)i.next();
-            for (Iterator elems = ap.getUnsatisfied().iterator(); elems.hasNext();) {
-                ElementSymbol symbol = (ElementSymbol)elems.next();
+        for (Iterator<AccessPattern> i = accessPatterns.iterator(); i.hasNext();) {
+            AccessPattern ap = i.next();
+            for (Iterator<ElementSymbol> elems = ap.getUnsatisfied().iterator(); elems.hasNext();) {
+                ElementSymbol symbol = elems.next();
                 Expression mapped = convertExpression(symbol, symbolMap.asMap());
                 if (ElementCollectorVisitor.getElements(mapped, true).isEmpty()) {
                     return false;
@@ -154,15 +157,15 @@
         if (accessPatterns != null) {
         	for (AccessPattern ap : accessPatterns) {
                 Set<ElementSymbol> newElements = new HashSet<ElementSymbol>();
-                for (Iterator elems = ap.getUnsatisfied().iterator(); elems.hasNext();) {
-                    ElementSymbol symbol = (ElementSymbol)elems.next();
+                for (Iterator<ElementSymbol> elems = ap.getUnsatisfied().iterator(); elems.hasNext();) {
+                    ElementSymbol symbol = elems.next();
                     Expression mapped = convertExpression(symbol, symbolMap);
                     newElements.addAll(ElementCollectorVisitor.getElements(mapped, true));
                 }
                 ap.setUnsatisfied(newElements);
                 Set<ElementSymbol> newHistory = new HashSet<ElementSymbol>();
-                for (Iterator elems = ap.getCurrentElements().iterator(); elems.hasNext();) {
-                    ElementSymbol symbol = (ElementSymbol)elems.next();
+                for (Iterator<ElementSymbol> elems = ap.getCurrentElements().iterator(); elems.hasNext();) {
+                    ElementSymbol symbol = elems.next();
                     Expression mapped = convertExpression(symbol, symbolMap);
                     newHistory.addAll(ElementCollectorVisitor.getElements(mapped, true));
                 }
@@ -233,6 +236,11 @@
             List<SingleElementSymbol> projectedSymbols = (List<SingleElementSymbol>)node.getProperty(NodeConstants.Info.PROJECT_COLS);
             Select select = new Select(projectedSymbols);
             ExpressionMappingVisitor.mapExpressions(select, symbolMap);
+            if (rewrite) {
+            	for (LanguageObject expr : select.getSymbols()) {
+					rewriteSingleElementSymbol(metadata, (SingleElementSymbol) expr);
+				}
+            }
             node.setProperty(NodeConstants.Info.PROJECT_COLS, select.getSymbols());
             if (!singleMapping) {
                 GroupsUsedByElementsVisitor.getGroups(select, groups);
@@ -257,6 +265,11 @@
         } else if(type == NodeConstants.Types.SORT) { 
         	OrderBy orderBy = (OrderBy)node.getProperty(NodeConstants.Info.SORT_ORDER);
             ExpressionMappingVisitor.mapExpressions(orderBy, symbolMap);
+            if (rewrite) {
+            	for (OrderByItem item : orderBy.getOrderByItems()) {
+            		rewriteSingleElementSymbol(metadata, item.getSymbol());
+            	}
+            }
             if (!singleMapping) {
                 GroupsUsedByElementsVisitor.getGroups(orderBy, groups);
             }
@@ -278,6 +291,25 @@
             convertAccessPatterns(symbolMap, node);
         }
     }
+
+	private static void rewriteSingleElementSymbol(
+			QueryMetadataInterface metadata, SingleElementSymbol ses) throws QueryPlannerException {
+		try {
+			if (ses instanceof AliasSymbol) {
+				ses = ((AliasSymbol)ses).getSymbol();
+			} 
+			if (ses instanceof ExpressionSymbol) {
+				ExpressionSymbol es = (ExpressionSymbol)ses;
+				if (es.getExpression() != null) {
+					es.setExpression(QueryRewriter.rewriteExpression(es.getExpression(), null, null, metadata));
+				}
+			}
+		} catch(TeiidProcessingException e) {
+		    throw new QueryPlannerException(e, QueryPlugin.Util.getString("ERR.015.004.0023", ses)); //$NON-NLS-1$
+		} catch (TeiidComponentException e) {
+			throw new QueryPlannerException(e, QueryPlugin.Util.getString("ERR.015.004.0023", ses)); //$NON-NLS-1$
+		}
+	}
     
     private static Expression convertExpression(Expression expression, Map symbolMap) {
         
@@ -314,7 +346,7 @@
         } catch(TeiidProcessingException e) {
             throw new QueryPlannerException(e, QueryPlugin.Util.getString("ERR.015.004.0023", criteria)); //$NON-NLS-1$
         } catch (TeiidComponentException e) {
-        	throw new TeiidRuntimeException(e);
+        	throw new QueryPlannerException(e, QueryPlugin.Util.getString("ERR.015.004.0023", criteria)); //$NON-NLS-1$
         }
     }
 

Modified: trunk/engine/src/main/java/org/teiid/query/optimizer/relational/rules/RuleMergeCriteria.java
===================================================================
--- trunk/engine/src/main/java/org/teiid/query/optimizer/relational/rules/RuleMergeCriteria.java	2011-07-22 15:32:56 UTC (rev 3326)
+++ trunk/engine/src/main/java/org/teiid/query/optimizer/relational/rules/RuleMergeCriteria.java	2011-07-22 16:26:08 UTC (rev 3327)
@@ -419,11 +419,11 @@
 			result.type = crit.getClass();
 			result.not = exists.isNegated();
 			//the correlations can only be in where (if no group by or aggregates) or having
-			result.query = (Query)exists.getCommand();
 			result.mergeJoin = exists.getSubqueryHint().isMergeJoin();
 			if (!UNNEST && !result.mergeJoin) {
 				return result;
 			}
+			result.query = (Query)exists.getCommand();
 		}
 		return result;
 	}

Modified: trunk/engine/src/main/java/org/teiid/query/rewriter/QueryRewriter.java
===================================================================
--- trunk/engine/src/main/java/org/teiid/query/rewriter/QueryRewriter.java	2011-07-22 15:32:56 UTC (rev 3326)
+++ trunk/engine/src/main/java/org/teiid/query/rewriter/QueryRewriter.java	2011-07-22 16:26:08 UTC (rev 3327)
@@ -52,6 +52,7 @@
 import org.teiid.core.TeiidProcessingException;
 import org.teiid.core.TeiidRuntimeException;
 import org.teiid.core.types.DataTypeManager;
+import org.teiid.core.types.Transform;
 import org.teiid.core.util.Assertion;
 import org.teiid.core.util.TimestampWithTimezone;
 import org.teiid.language.SQLConstants.NonReserved;
@@ -148,7 +149,6 @@
 import org.teiid.query.sql.symbol.Reference;
 import org.teiid.query.sql.symbol.ScalarSubquery;
 import org.teiid.query.sql.symbol.SearchedCaseExpression;
-import org.teiid.query.sql.symbol.SelectSymbol;
 import org.teiid.query.sql.symbol.SingleElementSymbol;
 import org.teiid.query.sql.symbol.AggregateSymbol.Type;
 import org.teiid.query.sql.util.SymbolMap;
@@ -240,6 +240,7 @@
      * @throws QueryValidatorException
      */
 	private Command rewriteCommand(Command command, boolean removeOrderBy) throws TeiidComponentException, TeiidProcessingException{
+		boolean oldRewriteAggs = rewriteAggs;
 		QueryMetadataInterface oldMetadata = metadata;
 		CreateUpdateProcedureCommand oldProcCommand = procCommand;
         
@@ -299,6 +300,7 @@
             	break;
 		}
         
+        this.rewriteAggs = oldRewriteAggs;
         this.metadata = oldMetadata;
         this.procCommand = oldProcCommand;
         return command;
@@ -605,9 +607,9 @@
         From from = query.getFrom();
         if(from != null){
             List<FromClause> clauses = new ArrayList<FromClause>(from.getClauses().size());
-            Iterator clauseIter = from.getClauses().iterator();
+            Iterator<FromClause> clauseIter = from.getClauses().iterator();
             while(clauseIter.hasNext()) {
-                clauses.add( rewriteFromClause(query, (FromClause) clauseIter.next()) );
+                clauses.add( rewriteFromClause(query, clauseIter.next()) );
             }
             from.setClauses(clauses);
         } else {
@@ -765,6 +767,7 @@
 	 */
 	private Query rewriteGroupBy(Query query) throws TeiidComponentException, TeiidProcessingException {
 		if (query.getGroupBy() == null) {
+			rewriteAggs = false;
 			return query;
 		}
 		if (isDistinctWithGroupBy(query)) {
@@ -811,11 +814,11 @@
         try {
             PostOrderNavigator.doVisit(obj, visitor);
         } catch (TeiidRuntimeException err) {
-            if (err.getChild() instanceof TeiidComponentException) {
-                throw (TeiidComponentException)err.getChild();
+            if (err.getCause() instanceof TeiidComponentException) {
+                throw (TeiidComponentException)err.getCause();
             } 
-            if (err.getChild() instanceof TeiidProcessingException) {
-                throw (TeiidProcessingException)err.getChild();
+            if (err.getCause() instanceof TeiidProcessingException) {
+                throw (TeiidProcessingException)err.getCause();
             } 
             throw err;
         }
@@ -1552,6 +1555,7 @@
     private BigDecimal BIG_DECIMAL_ZERO = new BigDecimal("0"); //$NON-NLS-1$
     private Short SHORT_ZERO = new Short((short)0);
     private Byte BYTE_ZERO = new Byte((byte)0);
+	private boolean rewriteAggs = true;
 
     /**
      * @param criteria
@@ -2246,6 +2250,9 @@
     			expression.setAggregateFunction(Type.MAX);
     		}
     	}
+    	if (rewriteAggs && expression.getExpression() != null && EvaluatableVisitor.willBecomeConstant(expression.getExpression())) {
+    		return expression.getExpression();
+    	}
     	if (expression.getExpression() != null && expression.getCondition() != null && !expression.respectsNulls()) {
     		Expression cond = expression.getCondition();
     		Expression ex = expression.getExpression();
@@ -2414,17 +2421,44 @@
         }
         function.setArgs(newArgs);
 
-        if( FunctionLibrary.isConvert(function) &&
-            newArgs[1] instanceof Constant) {
-            
-            Class srcType = newArgs[0].getType();
-            String tgtTypeName = (String) ((Constant)newArgs[1]).getValue();
-            Class tgtType = DataTypeManager.getDataTypeClass(tgtTypeName);
+        if( FunctionLibrary.isConvert(function)) {
+            Class<?> srcType = newArgs[0].getType();
+            Class<?> tgtType = function.getType();
 
             if(srcType != null && tgtType != null && srcType.equals(tgtType)) {
-                return newArgs[0];
+                return newArgs[0]; //unnecessary conversion
             }
-
+            
+            if (!(newArgs[0] instanceof Function) || tgtType == DataTypeManager.DefaultDataClasses.OBJECT) {
+            	return function;
+            }
+        	Function nested = (Function) newArgs[0];
+        	if (!FunctionLibrary.isConvert(nested)) {
+        		return function;
+        	}
+    		Class<?> nestedType = nested.getArgs()[0].getType();
+    		
+            Transform t = DataTypeManager.getTransform(nestedType, nested.getType());
+            if (t.isExplicit()) {
+            	//explicit conversions are required
+            	return function;
+            }
+            if (DataTypeManager.getTransform(nestedType, tgtType) == null) {
+            	//no direct conversion exists
+            	return function;
+            }
+    		//can't remove a convert that would alter the lexical form
+    		if (tgtType == DataTypeManager.DefaultDataClasses.STRING &&
+    				(nestedType == DataTypeManager.DefaultDataClasses.BOOLEAN
+    				|| nestedType == DataTypeManager.DefaultDataClasses.DATE
+    				|| nestedType == DataTypeManager.DefaultDataClasses.TIME
+    				|| tgtType == DataTypeManager.DefaultDataClasses.BIG_DECIMAL
+    				|| tgtType == DataTypeManager.DefaultDataClasses.FLOAT
+    				|| (tgtType == DataTypeManager.DefaultDataClasses.DOUBLE && srcType != DataTypeManager.DefaultDataClasses.FLOAT))) {
+    			return function;
+    		}
+        	//nested implicit transform is not needed
+        	return rewriteExpressionDirect(ResolverUtil.getConversion(nested.getArgs()[0], DataTypeManager.getDataTypeName(nestedType), DataTypeManager.getDataTypeName(tgtType), false, funcLibrary));
         }
 
         //convert DECODESTRING function to CASE expression
@@ -2702,7 +2736,7 @@
         
         select.setSymbols(select.getProjectedSymbols());
         
-        List<SelectSymbol> symbols = select.getSymbols();
+        List symbols = select.getSymbols();
         
         HashSet<String> uniqueNames = new HashSet<String>();
         

Modified: trunk/engine/src/main/java/org/teiid/query/sql/symbol/QueryString.java
===================================================================
--- trunk/engine/src/main/java/org/teiid/query/sql/symbol/QueryString.java	2011-07-22 15:32:56 UTC (rev 3326)
+++ trunk/engine/src/main/java/org/teiid/query/sql/symbol/QueryString.java	2011-07-22 16:26:08 UTC (rev 3327)
@@ -30,7 +30,7 @@
 import org.teiid.query.sql.visitor.SQLStringVisitor;
 
 /**
- * Represents XMLATTRIBUTES name value pairs
+ * Represents query string name value pairs
  */
 public class QueryString implements Expression {
 

Modified: trunk/engine/src/main/java/org/teiid/query/tempdata/TempTableStore.java
===================================================================
--- trunk/engine/src/main/java/org/teiid/query/tempdata/TempTableStore.java	2011-07-22 15:32:56 UTC (rev 3326)
+++ trunk/engine/src/main/java/org/teiid/query/tempdata/TempTableStore.java	2011-07-22 16:26:08 UTC (rev 3327)
@@ -37,6 +37,8 @@
 import org.teiid.common.buffer.BufferManager;
 import org.teiid.core.TeiidComponentException;
 import org.teiid.language.SQLConstants;
+import org.teiid.logging.LogConstants;
+import org.teiid.logging.LogManager;
 import org.teiid.query.QueryPlugin;
 import org.teiid.query.metadata.QueryMetadataInterface;
 import org.teiid.query.metadata.TempMetadataID;
@@ -96,6 +98,7 @@
 		
 		public synchronized MatState setState(MatState state, Boolean valid, Long timestamp) {
 			MatState oldState = this.state;
+			LogManager.logDetail(LogConstants.CTX_MATVIEWS, this, "setting matState to", state, valid, timestamp, "old values", oldState, this.valid); //$NON-NLS-1$ //$NON-NLS-2$
 			if (valid != null) {
 				this.valid = valid;
 			}

Modified: trunk/engine/src/main/java/org/teiid/query/validator/UpdateValidator.java
===================================================================
--- trunk/engine/src/main/java/org/teiid/query/validator/UpdateValidator.java	2011-07-22 15:32:56 UTC (rev 3326)
+++ trunk/engine/src/main/java/org/teiid/query/validator/UpdateValidator.java	2011-07-22 16:26:08 UTC (rev 3327)
@@ -404,7 +404,7 @@
             	String groupName = es.getGroupSymbol().getCanonicalName();
         		UpdateMapping info = updateInfo.updatableGroups.get(groupName);
         		if (es.getGroupSymbol().getDefinition() != null) {
-            		ElementSymbol clone = (ElementSymbol)es.clone();
+            		ElementSymbol clone = es.clone();
             		clone.setOutputName(null);
             		clone.getGroupSymbol().setName(clone.getGroupSymbol().getNonCorrelationName());
             		clone.getGroupSymbol().setDefinition(null);

Modified: trunk/engine/src/main/java/org/teiid/query/xquery/saxon/DocumentWrapper.java
===================================================================
--- trunk/engine/src/main/java/org/teiid/query/xquery/saxon/DocumentWrapper.java	2011-07-22 15:32:56 UTC (rev 3326)
+++ trunk/engine/src/main/java/org/teiid/query/xquery/saxon/DocumentWrapper.java	2011-07-22 16:26:08 UTC (rev 3327)
@@ -115,7 +115,7 @@
 	 * @return the unique number identifying this document within the name pool
 	 */
 
-	public int getDocumentNumber() {
+	public long getDocumentNumber() {
 		return documentNumber;
 	}
 
@@ -124,12 +124,16 @@
 	 * 
 	 * @param id
 	 *            the required ID value
+	 * @param getParent
+	 *            true if running the element-with-id() function rather than the id()
+	 *            function; the difference is that in the case of an element of type xs:ID,
+	 *            the parent of the element should be returned, not the element itself.
 	 * @return the element with the given ID, or null if there is no such ID
 	 *         present (or if the parser has not notified attributes as being of
 	 *         type ID).
 	 */
 
-	public NodeInfo selectID(String id) {
+	public NodeInfo selectID(String id, boolean getParent) {
 		if (idIndex == null) {
 			Element elem;
 			switch (nodeKind) {
@@ -145,7 +149,14 @@
 			idIndex = new HashMap(50);
 			buildIDIndex(elem);
 		}
-		return (NodeInfo) idIndex.get(id);
+
+		NodeInfo result = (NodeInfo) idIndex.get(id);
+
+		if (result != null && getParent && result.isId() && result.getStringValue().equals(id)) {
+            result = result.getParent();
+        }
+
+		return result ;
 	}
 	
 	

Modified: trunk/engine/src/main/java/org/teiid/query/xquery/saxon/NodeWrapper.java
===================================================================
--- trunk/engine/src/main/java/org/teiid/query/xquery/saxon/NodeWrapper.java	2011-07-22 15:32:56 UTC (rev 3326)
+++ trunk/engine/src/main/java/org/teiid/query/xquery/saxon/NodeWrapper.java	2011-07-22 16:26:08 UTC (rev 3327)
@@ -160,6 +160,14 @@
 	}
 
 	/**
+	 * Get the real XOM node, to implement the VirtualNode interface
+	 */
+
+	public Object getRealNode() {
+		return node;
+	}
+
+	/**
 	 * Get the name pool for this node
 	 *
 	 * @return the NamePool
@@ -799,7 +807,7 @@
 	 * free-standing orphan node, just return the hashcode.
 	 */
 
-	public int getDocumentNumber() {
+	public long getDocumentNumber() {
 		return docWrapper.getDocumentNumber();
 	}
 

Modified: trunk/engine/src/main/java/org/teiid/query/xquery/saxon/StreamingUtils.java
===================================================================
--- trunk/engine/src/main/java/org/teiid/query/xquery/saxon/StreamingUtils.java	2011-07-22 15:32:56 UTC (rev 3326)
+++ trunk/engine/src/main/java/org/teiid/query/xquery/saxon/StreamingUtils.java	2011-07-22 16:26:08 UTC (rev 3327)
@@ -256,6 +256,7 @@
 
 	public void close() throws XPathException {
 		reciever.close();
+		super.close();
 	}
 
 	public void comment(CharSequence content, int locationId, int properties)
@@ -265,6 +266,7 @@
 
 	public void endDocument() throws XPathException {
 		reciever.endDocument();
+		super.endDocument() ;
 	}
 
 	public void endElement() throws XPathException {
@@ -285,6 +287,7 @@
 	}
 
 	public void open() throws XPathException {
+		super.open();
 		reciever.open();
 	}
 
@@ -295,10 +298,12 @@
 
 	public void setPipelineConfiguration(PipelineConfiguration config) {
 		reciever.setPipelineConfiguration(config);
+		super.setPipelineConfiguration(config);
 	}
 
 	public void setSystemId(String systemId) {
 		reciever.setSystemId(systemId);
+		super.setSystemId(systemId);
 	}
 
 	public void setUnparsedEntity(String name, String systemID,
@@ -311,6 +316,7 @@
 	}
 
 	public void startDocument(int properties) throws XPathException {
+		super.startDocument(properties);
 		reciever.startDocument(properties);
 	}
 

Modified: trunk/engine/src/main/resources/org/teiid/query/i18n.properties
===================================================================
--- trunk/engine/src/main/resources/org/teiid/query/i18n.properties	2011-07-22 15:32:56 UTC (rev 3326)
+++ trunk/engine/src/main/resources/org/teiid/query/i18n.properties	2011-07-22 16:26:08 UTC (rev 3327)
@@ -232,7 +232,7 @@
 ERR.015.004.0010= Unknown group specified in OPTION MAKEDEP/MAKENOTDEP: {0}
 ERR.015.004.0012= Group has an access pattern which has not been met: group(s) {0}; access pattern(s) {1}
 ERR.015.004.0020= Error getting model for {0}
-ERR.015.004.0023= Error rewriting criteria: {0}
+ERR.015.004.0023= Error rewriting: {0}
 ERR.015.004.0024= Unable to create a query plan that sends a criteria to \"{0}\".  This connection factory requires criteria set to true indicating that a query against this model requires criteria.  
 ERR.015.004.0029= Could not resolve group symbol {0}
 ERR.015.004.0035= The criteria {0} has elements from the root staging table and the document nodes which is not allowed.

Modified: trunk/engine/src/test/java/org/teiid/common/buffer/TestSTree.java
===================================================================
--- trunk/engine/src/test/java/org/teiid/common/buffer/TestSTree.java	2011-07-22 15:32:56 UTC (rev 3326)
+++ trunk/engine/src/test/java/org/teiid/common/buffer/TestSTree.java	2011-07-22 16:26:08 UTC (rev 3327)
@@ -33,7 +33,7 @@
 import org.teiid.core.TeiidComponentException;
 import org.teiid.query.sql.symbol.ElementSymbol;
 
- at SuppressWarnings("nls")
+ at SuppressWarnings({"nls", "unchecked"})
 public class TestSTree {
 	
 	@Test public void testRemoveAll() throws TeiidComponentException {
@@ -42,7 +42,7 @@
 		e1.setType(Integer.class);
 		ElementSymbol e2 = new ElementSymbol("y");
 		e2.setType(String.class);
-		List elements = Arrays.asList(e1, e2);
+		List<ElementSymbol> elements = Arrays.asList(e1, e2);
 		STree map = bm.createSTree(elements, "1", 1);
 		
 		for (int i = 20000; i > 0; i--) {
@@ -83,7 +83,7 @@
 		
 		ElementSymbol e1 = new ElementSymbol("x");
 		e1.setType(Integer.class);
-		List elements = Arrays.asList(e1);
+		List<ElementSymbol> elements = Arrays.asList(e1);
 		STree map = bm.createSTree(elements, "1", 1);
 		
 		int size = (1<<16)+(1<<4)+1;

Modified: trunk/engine/src/test/java/org/teiid/dqp/internal/datamgr/FakeConnector.java
===================================================================
--- trunk/engine/src/test/java/org/teiid/dqp/internal/datamgr/FakeConnector.java	2011-07-22 15:32:56 UTC (rev 3326)
+++ trunk/engine/src/test/java/org/teiid/dqp/internal/datamgr/FakeConnector.java	2011-07-22 16:26:08 UTC (rev 3327)
@@ -22,35 +22,25 @@
 
 package org.teiid.dqp.internal.datamgr;
 
+import java.util.ArrayList;
 import java.util.Arrays;
 import java.util.List;
 
-import junit.framework.Assert;
-
 import org.teiid.language.Command;
-import org.teiid.language.QueryExpression;
 import org.teiid.metadata.RuntimeMetadata;
-import org.teiid.translator.TranslatorException;
 import org.teiid.translator.DataNotAvailableException;
 import org.teiid.translator.Execution;
 import org.teiid.translator.ExecutionContext;
 import org.teiid.translator.ExecutionFactory;
 import org.teiid.translator.ResultSetExecution;
+import org.teiid.translator.TranslatorException;
 import org.teiid.translator.UpdateExecution;
 
-public class FakeConnector extends ExecutionFactory {
-	private static final int RESULT_SIZE = 5;
-	
-	private boolean executeBlocks;
-    private boolean nextBatchBlocks;
-    private boolean returnsFinalBatch;
-    private boolean driverThrowsExceptionOnCancel;
-    private long simulatedBatchRetrievalTime = 1000L;
-    private ClassLoader classloader;
+public class FakeConnector extends ExecutionFactory<Object, Object> {
     
     private int connectionCount;
     private int executionCount;
-    
+
     public int getConnectionCount() {
 		return connectionCount;
 	}
@@ -62,123 +52,52 @@
     @Override
     public Execution createExecution(Command command, ExecutionContext executionContext, RuntimeMetadata metadata, Object connection) throws TranslatorException {
     	executionCount++;
-        return new FakeBlockingExecution(executionContext);
+        return new FakeExecution(executionContext);
     }
     
-    public Object getConnection() {
-        return new FakeConnection();
-    }
-    
     @Override
     public Object getConnection(Object factory) throws TranslatorException {
+    	connectionCount++;
     	return factory;
     }
     
     @Override
     public void closeConnection(Object connection, Object factory) {
     }
-	
-    private class FakeConnection {
-    	public FakeConnection() {
-			connectionCount++;
-		}
-    	
-        public boolean released = false;
-        public void close() {
-            Assert.assertFalse("The connection should not be released more than once", released); //$NON-NLS-1$
-            released = true;
-        }
-    }   
     
-    private final class FakeBlockingExecution implements ResultSetExecution, UpdateExecution {
-        private boolean closed = false;
-        private boolean cancelled = false;
+    public final class FakeExecution implements ResultSetExecution, UpdateExecution {
         private int rowCount;
         ExecutionContext ec;
-        public FakeBlockingExecution(ExecutionContext ec) {
+        
+        public FakeExecution(ExecutionContext ec) {
             this.ec = ec;
         }
-        public void execute(QueryExpression query, int maxBatchSize) throws TranslatorException {
-            if (executeBlocks) {
-                waitForCancel();
-            }
-            if (classloader != null) {
-            	Assert.assertSame(classloader, Thread.currentThread().getContextClassLoader());
-            }
-        }
-        public synchronized void cancel() throws TranslatorException {
-            cancelled = true;
-            this.notify();
-        }
-        public void close() {
-            Assert.assertFalse("The execution should not be closed more than once", closed); //$NON-NLS-1$
-            closed = true;
-        }
         @Override
         public void execute() throws TranslatorException {
             ec.addWarning(new Exception("Some warning")); //$NON-NLS-1$
         }
         @Override
-        public List next() throws TranslatorException, DataNotAvailableException {
-        	if (nextBatchBlocks) {
-                waitForCancel();
-            }
-            if (this.rowCount >= RESULT_SIZE || returnsFinalBatch) {
+        public List<?> next() throws TranslatorException, DataNotAvailableException {
+            if (this.rowCount == 1) {
             	return null;
             }
             this.rowCount++;
-            return Arrays.asList(this.rowCount - 1);
+            return new ArrayList<Object>(Arrays.asList(this.rowCount - 1));
         }
-        private synchronized void waitForCancel() throws TranslatorException {
-            try {
-                this.wait(simulatedBatchRetrievalTime);
-                if (cancelled && driverThrowsExceptionOnCancel) {
-                    throw new TranslatorException("Request cancelled"); //$NON-NLS-1$
-                }
-            } catch (InterruptedException e) {
-                throw new RuntimeException(e);
-            }
-        }
 		@Override
 		public int[] getUpdateCounts() throws DataNotAvailableException,
 				TranslatorException {
 			return new int[] {1};
 		}
+		
+		@Override
+		public void close() {
+		}
+		
+		@Override
+		public void cancel() throws TranslatorException {
+		}
     }
 
-	public boolean isExecuteBlocks() {
-		return executeBlocks;
-	}
-	public void setExecuteBlocks(boolean executeBlocks) {
-		this.executeBlocks = executeBlocks;
-	}
-	public boolean isNextBatchBlocks() {
-		return nextBatchBlocks;
-	}
-	public void setNextBatchBlocks(boolean nextBatchBlocks) {
-		this.nextBatchBlocks = nextBatchBlocks;
-	}
-	public boolean isReturnsFinalBatch() {
-		return returnsFinalBatch;
-	}
-	public void setReturnsFinalBatch(boolean returnsFinalBatch) {
-		this.returnsFinalBatch = returnsFinalBatch;
-	}
-	public boolean isDriverThrowsExceptionOnCancel() {
-		return driverThrowsExceptionOnCancel;
-	}
-	public void setDriverThrowsExceptionOnCancel(
-			boolean driverThrowsExceptionOnCancel) {
-		this.driverThrowsExceptionOnCancel = driverThrowsExceptionOnCancel;
-	}
-	public long getSimulatedBatchRetrievalTime() {
-		return simulatedBatchRetrievalTime;
-	}
-	public void setSimulatedBatchRetrievalTime(long simulatedBatchRetrievalTime) {
-		this.simulatedBatchRetrievalTime = simulatedBatchRetrievalTime;
-	}
 	
-	public void setClassloader(ClassLoader classloader) {
-		this.classloader = classloader;
-	}
 }

Modified: trunk/engine/src/test/java/org/teiid/dqp/internal/datamgr/TestConnectorManager.java
===================================================================
--- trunk/engine/src/test/java/org/teiid/dqp/internal/datamgr/TestConnectorManager.java	2011-07-22 15:32:56 UTC (rev 3326)
+++ trunk/engine/src/test/java/org/teiid/dqp/internal/datamgr/TestConnectorManager.java	2011-07-22 16:26:08 UTC (rev 3327)
@@ -50,7 +50,7 @@
 				return c;
 			}
 			protected Object getConnectionFactory(){
-				return c.getConnection();
+				return c;
 			}
 		};
 		cm.start();

Modified: trunk/engine/src/test/java/org/teiid/dqp/internal/datamgr/TestConnectorWorkItem.java
===================================================================
--- trunk/engine/src/test/java/org/teiid/dqp/internal/datamgr/TestConnectorWorkItem.java	2011-07-22 15:32:56 UTC (rev 3326)
+++ trunk/engine/src/test/java/org/teiid/dqp/internal/datamgr/TestConnectorWorkItem.java	2011-07-22 16:26:08 UTC (rev 3327)
@@ -87,7 +87,7 @@
 		int total_columns = 3;
 		StoredProcedure command = (StoredProcedure)helpGetCommand("{call pm2.spTest8(?)}", EXAMPLE_BQT); //$NON-NLS-1$      
 		command.getInputParameters().get(0).setExpression(new Constant(1));
-		Call proc = (Call)new LanguageBridgeFactory(EXAMPLE_BQT).translate(command);
+		Call proc = new LanguageBridgeFactory(EXAMPLE_BQT).translate(command);
 
 		ProcedureBatchHandler pbh = new ProcedureBatchHandler(proc, exec);
 

Modified: trunk/engine/src/test/java/org/teiid/dqp/internal/datamgr/TestElementImpl.java
===================================================================
--- trunk/engine/src/test/java/org/teiid/dqp/internal/datamgr/TestElementImpl.java	2011-07-22 15:32:56 UTC (rev 3326)
+++ trunk/engine/src/test/java/org/teiid/dqp/internal/datamgr/TestElementImpl.java	2011-07-22 16:26:08 UTC (rev 3327)
@@ -72,7 +72,7 @@
     
     public void testGetName() throws Exception {
         Object metadataID = TstLanguageBridgeFactory.metadata.getElementID("pm1.g1.e1"); //$NON-NLS-1$
-        assertEquals("pm1.g1.e1", example("pm1.g1", "e1", metadataID).getName()); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$
+        assertEquals("e1", example("pm1.g1", "e1", metadataID).getName()); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$
     }
 
     public void testGetGroup() throws Exception {

Modified: trunk/engine/src/test/java/org/teiid/dqp/internal/process/TestWorkItemState.java
===================================================================
--- trunk/engine/src/test/java/org/teiid/dqp/internal/process/TestWorkItemState.java	2011-07-22 15:32:56 UTC (rev 3326)
+++ trunk/engine/src/test/java/org/teiid/dqp/internal/process/TestWorkItemState.java	2011-07-22 16:26:08 UTC (rev 3327)
@@ -25,20 +25,10 @@
 import static org.junit.Assert.*;
 
 import org.junit.Test;
-import org.teiid.dqp.internal.process.AbstractWorkItem.ThreadState;
 
 
 public class TestWorkItemState {
 	
-	private final class WorkItemRunner implements Runnable {
-		TestWorkItem workItem;
-
-		@Override
-		public void run() {
-			workItem.run();
-		}
-	}
-
 	private class TestWorkItem extends AbstractWorkItem {
 
 		private boolean isDone;
@@ -50,11 +40,6 @@
 		}
 		
 		private TestWorkItem(boolean done, boolean callMoreWork) {
-			this(done, callMoreWork, null);
-		}
-		
-		private TestWorkItem(boolean done, boolean callMoreWork, Thread callingThread) {
-			super(callingThread);
 			this.isDone = done;
 			this.callMoreWork = callMoreWork;
 		}
@@ -167,26 +152,4 @@
     	}
     }
     
-    @Test public void testUsingCallingThreadIdle() throws Exception {
-    	WorkItemRunner r = new WorkItemRunner();
-    	Thread t = new Thread(r);
-    	final TestWorkItem item = new TestWorkItem(false, false, t) {
-    		@Override
-    		protected boolean shouldPause() {
-    			return true;
-    		}
-    	};
-    	r.workItem = item;
-    	t.start();
-		for (int i = 0; i < 10 && item.getThreadState() != ThreadState.IDLE; i++) {
-			Thread.sleep(100);
-		}
-		if (item.getThreadState() != ThreadState.IDLE) {
-			fail();
-		}
-		item.moreWork();
-		//if we don't return from this call, that means that this thread has been hijacked -
-		//we should instead use t.
-    }
-        
 }

Modified: trunk/engine/src/test/java/org/teiid/query/function/TestFunction.java
===================================================================
--- trunk/engine/src/test/java/org/teiid/query/function/TestFunction.java	2011-07-22 15:32:56 UTC (rev 3326)
+++ trunk/engine/src/test/java/org/teiid/query/function/TestFunction.java	2011-07-22 16:26:08 UTC (rev 3327)
@@ -1000,9 +1000,10 @@
     }
 
     @Test public void testTimestampDiffTimeStamp_Day_1() throws Exception {
+    	// Moving to June, March fails because of DST
         helpTestTimestampDiff(NonReserved.SQL_TSI_DAY,
-                              TimestampUtil.createTimestamp((2004-1900), 2, 1, 0, 0, 0, 0),
-                              TimestampUtil.createTimestamp((2004-1900), 3, 1, 0, 0, 0, 0),
+                              TimestampUtil.createTimestamp((2004-1900), 4, 1, 0, 0, 0, 0),
+                              TimestampUtil.createTimestamp((2004-1900), 5, 1, 0, 0, 0, 0),
                               new Long(31));
     }
 


Property changes on: trunk/engine/src/test/java/org/teiid/query/function/TestFunction.java
___________________________________________________________________
Added: svn:mergeinfo
   + /branches/7.4.x/engine/src/test/java/org/teiid/query/function/TestFunction.java:3281-3325

Modified: trunk/engine/src/test/java/org/teiid/query/optimizer/TestSubqueryPushdown.java
===================================================================
--- trunk/engine/src/test/java/org/teiid/query/optimizer/TestSubqueryPushdown.java	2011-07-22 15:32:56 UTC (rev 3326)
+++ trunk/engine/src/test/java/org/teiid/query/optimizer/TestSubqueryPushdown.java	2011-07-22 16:26:08 UTC (rev 3327)
@@ -757,6 +757,7 @@
     }
     
     @Test public void testSubqueryRewriteToJoinDistinct() throws Exception {
+    	System.setProperty(RuleMergeCriteria.UNNEST_DEFAULT, Boolean.TRUE.toString());
         TestQueryRewriter.helpTestRewriteCommand("Select distinct e1 from pm1.g1 as x where exists (select pm1.g1.e1 FROM pm1.g1 where e1 = x.e1)", "SELECT DISTINCT e1 FROM pm1.g1 AS x, (SELECT pm1.g1.e1 FROM pm1.g1) AS X__1 WHERE x.e1 = X__1.e1", RealMetadataFactory.example1Cached());
     }
     
@@ -764,6 +765,7 @@
      * Agg does not depend on cardinality
      */
     @Test public void testSubqueryRewriteToJoinGroupBy() throws Exception {
+    	System.setProperty(RuleMergeCriteria.UNNEST_DEFAULT, Boolean.TRUE.toString());
         TestQueryRewriter.helpTestRewriteCommand("Select max(e1) from pm1.g1 as x where exists (select pm1.g1.e1 FROM pm1.g1 where e1 = x.e1) group by e2", "SELECT MAX(e1) FROM pm1.g1 AS x, (SELECT pm1.g1.e1 FROM pm1.g1) AS X__1 WHERE x.e1 = X__1.e1 GROUP BY e2", RealMetadataFactory.example1Cached());
     }
     
@@ -775,6 +777,7 @@
     }
     
     @Test public void testSubqueryRewriteToJoin() throws Exception {
+    	System.setProperty(RuleMergeCriteria.UNNEST_DEFAULT, Boolean.TRUE.toString());
         TestQueryRewriter.helpTestRewriteCommand("Select e1 from pm3.g1 where exists (select pm1.g1.e1 FROM pm1.g1 where e1 = pm3.g1.e1)", "SELECT e1 FROM pm3.g1, (SELECT pm1.g1.e1 FROM pm1.g1) AS X__1 WHERE pm3.g1.e1 = X__1.e1", RealMetadataFactory.example4());
     }
     
@@ -919,6 +922,7 @@
      * Same as above, but the source is much larger, so a semi-join is favorable
      */
     @Test public void testSemiJoinExistsCosting() {
+    	System.setProperty(RuleMergeCriteria.UNNEST_DEFAULT, Boolean.TRUE.toString());
         ProcessorPlan plan = helpPlan("Select e1 from pm2.g2 as o where not exists (select 1 from pm3.g1 where e1 = o.e1 having o.e2 = count(e2))", RealMetadataFactory.example4(),  //$NON-NLS-1$
             new String[] { "SELECT g_0.e1 AS c_0, g_0.e2 AS c_1 FROM pm2.g2 AS g_0 ORDER BY c_0, c_1" }); //$NON-NLS-1$
         checkNodeTypes(plan, new int[] {


Property changes on: trunk/engine/src/test/java/org/teiid/query/optimizer/TestSubqueryPushdown.java
___________________________________________________________________
Modified: svn:mergeinfo
   - /branches/7.4.x/engine/src/test/java/org/teiid/query/optimizer/TestSubqueryPushdown.java:3149-3217
   + /branches/7.4.x/engine/src/test/java/org/teiid/query/optimizer/TestSubqueryPushdown.java:3149-3217,3281-3325

Modified: trunk/engine/src/test/java/org/teiid/query/processor/TestSQLXMLProcessing.java
===================================================================
--- trunk/engine/src/test/java/org/teiid/query/processor/TestSQLXMLProcessing.java	2011-07-22 15:32:56 UTC (rev 3326)
+++ trunk/engine/src/test/java/org/teiid/query/processor/TestSQLXMLProcessing.java	2011-07-22 16:26:08 UTC (rev 3327)
@@ -202,8 +202,8 @@
         String sql = "select * from xmltable('/a/b' passing convert('<a><b>first</b><b x=\"1\">second</b></a>', xml) columns val xml path '.') as x"; //$NON-NLS-1$
         
         List<?>[] expected = new List<?>[] {
-        		Arrays.asList("<b>first</b>"),
-        		Arrays.asList("<b x=\"1\">second</b>"),
+        		Arrays.asList("<b xmlns=\"\">first</b>"),
+        		Arrays.asList("<b xmlns=\"\" x=\"1\">second</b>"),
         };    
     
         process(sql, expected);
@@ -286,7 +286,7 @@
     	String sql = "select xmlquery('/a/b' passing xmlparse(document '<a><b x=''1''/><b x=''2''/></a>') null on empty)"; //$NON-NLS-1$
         
         List<?>[] expected = new List<?>[] {
-        		Arrays.asList("<b x=\"1\"/><b x=\"2\"/>")
+        		Arrays.asList("<b xmlns=\"\" x=\"1\"/><b xmlns=\"\" x=\"2\"/>")
         };    
     
         process(sql, expected);


Property changes on: trunk/engine/src/test/java/org/teiid/query/processor/TestSQLXMLProcessing.java
___________________________________________________________________
Modified: svn:mergeinfo
   - /branches/7.4.x/engine/src/test/java/org/teiid/query/processor/TestSQLXMLProcessing.java:3149-3217,3220-3275
   + /branches/7.4.x/engine/src/test/java/org/teiid/query/processor/TestSQLXMLProcessing.java:3149-3217,3220-3275,3281-3325

Modified: trunk/engine/src/test/java/org/teiid/query/rewriter/TestQueryRewriter.java
===================================================================
--- trunk/engine/src/test/java/org/teiid/query/rewriter/TestQueryRewriter.java	2011-07-22 15:32:56 UTC (rev 3326)
+++ trunk/engine/src/test/java/org/teiid/query/rewriter/TestQueryRewriter.java	2011-07-22 16:26:08 UTC (rev 3327)
@@ -124,11 +124,11 @@
     }
     
     private Map<ElementSymbol, Integer> elements;
-    private List<List> tuples;
+    private List<List<? extends Object>> tuples;
     
     @Before public void setUp() {
     	elements = null;
-    	tuples = new ArrayList<List>();
+    	tuples = new ArrayList<List<? extends Object>>();
     }
 
     private Criteria helpTestRewriteCriteria(String original, Criteria expectedCrit, QueryMetadataInterface metadata) {
@@ -138,7 +138,7 @@
         // rewrite
         try { 
         	ArrayList<Boolean> booleanVals = new ArrayList<Boolean>(tuples.size());
-        	for (List<Object> tuple : tuples) {
+        	for (List<?> tuple : tuples) {
             	booleanVals.add(new Evaluator(elements, null, null).evaluate(origCrit, tuple));
 			}
             actual = QueryRewriter.rewriteCriteria(origCrit, null, null, metadata);
@@ -2085,10 +2085,6 @@
         helpTestRewriteCriteria("concat2('a', pm1.g1.e1) = 'xyz'", "concat('a', ifnull(pm1.g1.e1, '')) = 'xyz'"); //$NON-NLS-1$ //$NON-NLS-2$
     }
     
-    @Test public void testRewiteEvaluatableAggregate() {
-    	helpTestRewriteCommand("select max(1) from pm1.g1", "SELECT MAX(1) FROM pm1.g1"); //$NON-NLS-1$ //$NON-NLS-2$
-    }
-    
     @Test public void testRewriteFromUnixTime() throws Exception {
     	TimestampWithTimezone.resetCalendar(TimeZone.getTimeZone("GMT-06:00")); //$NON-NLS-1$
     	try {
@@ -2448,5 +2444,21 @@
 		String sql = "parsedate_(pm1.g1.e1) = {d'2001-01-01'}";
         helpTestRewriteCriteria(sql, parseCriteria(sql, metadata), metadata);  		
 	} 
+	
+    @Test public void testRewriteNestedConvert() throws Exception {
+        helpTestRewriteExpression("cast(cast(pm1.g1.e3 as integer) as long)", "cast(pm1.g1.e3 as long)", RealMetadataFactory.example1Cached()); //$NON-NLS-1$ //$NON-NLS-2$
+    }
+    
+    @Test public void testRewriteNestedConvert1() throws Exception {
+        helpTestRewriteExpression("cast(cast(pm1.g1.e3 as integer) as string)", "convert(convert(pm1.g1.e3, integer), string)", RealMetadataFactory.example1Cached()); //$NON-NLS-1$ //$NON-NLS-2$
+    }
 
+    @Test public void testRewriteNestedConvert2() throws Exception {
+        helpTestRewriteExpression("cast(cast(pm1.g1.e3 as string) as clob)", "convert(convert(pm1.g1.e3, string), clob)", RealMetadataFactory.example1Cached()); //$NON-NLS-1$ //$NON-NLS-2$
+    }
+    
+    @Test public void testRewriteConstantAgg() throws Exception {
+    	helpTestRewriteCommand("select max(1) from pm1.g1 group by e1", "SELECT 1 FROM pm1.g1 GROUP BY e1");
+    }
+    
 }

Modified: trunk/engine/src/test/java/org/teiid/query/validator/TestValidator.java
===================================================================
--- trunk/engine/src/test/java/org/teiid/query/validator/TestValidator.java	2011-07-22 15:32:56 UTC (rev 3326)
+++ trunk/engine/src/test/java/org/teiid/query/validator/TestValidator.java	2011-07-22 16:26:08 UTC (rev 3327)
@@ -419,6 +419,14 @@
                      new String[] {"COUNT(DISTINCT ObjectValue)"}, RealMetadataFactory.exampleBQTCached() ); //$NON-NLS-1$
     }
     
+    /**
+     * previously failed on stringkey, which is not entirely correct
+     */
+    @Test public void testInvalidAggregate10() {
+        helpValidate("SELECT xmlparse(document stringkey) FROM BQT1.SmallA GROUP BY xmlparse(document stringkey)", //$NON-NLS-1$
+                     new String[] {"XMLPARSE(DOCUMENT stringkey)"}, RealMetadataFactory.exampleBQTCached() ); //$NON-NLS-1$
+    }
+    
     @Test public void testInvalidAggregateIssue190644() {
         helpValidate("SELECT e3 + 1 from pm1.g1 GROUP BY e2 + 1 HAVING e2 + 1 = 5", new String[] {"e3"}, RealMetadataFactory.example1Cached()); //$NON-NLS-1$ //$NON-NLS-2$
     }
@@ -436,6 +444,11 @@
             "FROM BQT1.SmallA GROUP BY case when IntKey>=5000 then '5000 +' else '0-999' end", //$NON-NLS-1$
             new String[] {}, RealMetadataFactory.exampleBQTCached());
     }
+    
+    @Test public void testValidAggregate4() {
+        helpValidate("SELECT max(e1), e2 is null from pm1.g1 GROUP BY e2 is null", new String[] {}, RealMetadataFactory.example1Cached()); //$NON-NLS-1$ 
+    }
+
 	@Test public void testInvalidHaving1() {        
         helpValidate("SELECT e3 FROM test.group HAVING e3 > 0", new String[] {"e3"}, exampleMetadata()); //$NON-NLS-1$ //$NON-NLS-2$
 	}

Modified: trunk/pom.xml
===================================================================
--- trunk/pom.xml	2011-07-22 15:32:56 UTC (rev 3326)
+++ trunk/pom.xml	2011-07-22 16:26:08 UTC (rev 3327)
@@ -439,16 +439,10 @@
             </dependency>            
 			<dependency>
 				<groupId>net.sourceforge.saxon</groupId>
-				<artifactId>saxon</artifactId>
-				<version>9.1.0.8</version>
+				<artifactId>saxonhe</artifactId>
+				<version>9.2.1.5</version>
 			</dependency>
 			<dependency>
-				<groupId>net.sourceforge.saxon</groupId>
-				<artifactId>saxon</artifactId>
-				<classifier>dom</classifier>
-				<version>9.1.0.8</version>
-			</dependency>
-			<dependency>
 				<groupId>org.jboss.netty</groupId>
 				<artifactId>netty</artifactId>
 				<version>3.2.1.Final</version>
@@ -493,4 +487,4 @@
             <url>https://repository.jboss.org/nexus/content/repositories/snapshots/</url>
         </snapshotRepository>
     </distributionManagement>
-</project>
\ No newline at end of file
+</project>

Modified: trunk/runtime/src/main/java/org/teiid/odbc/ODBCClientRemote.java
===================================================================
--- trunk/runtime/src/main/java/org/teiid/odbc/ODBCClientRemote.java	2011-07-22 15:32:56 UTC (rev 3326)
+++ trunk/runtime/src/main/java/org/teiid/odbc/ODBCClientRemote.java	2011-07-22 16:26:08 UTC (rev 3327)
@@ -21,13 +21,14 @@
  */
 package org.teiid.odbc;
 
+import java.io.IOException;
 import java.sql.ParameterMetaData;
-import java.sql.ResultSetMetaData;
-import java.sql.Statement;
+import java.util.List;
 import java.util.Properties;
 
 import org.teiid.client.util.ResultsFuture;
 import org.teiid.jdbc.ResultSetImpl;
+import org.teiid.odbc.PGUtil.PgColInfo;
 
 public interface ODBCClientRemote {
 	
@@ -62,11 +63,19 @@
 
 	//	RowDescription (B)
 	//	NoData (B)
-	void sendResultSetDescription(ResultSetMetaData metaData, Statement stmt);
+	void sendResultSetDescription(List<PgColInfo> cols);
 	
 	//	DataRow (B)
 	//	CommandComplete (B)
-	void sendResults(String sql, ResultSetImpl rs, ResultsFuture<Void> result, boolean describeRows);
+	void sendResults(String sql, ResultSetImpl rs, List<PgColInfo> cols, ResultsFuture<Integer> result, boolean describeRows);
+	
+	void sendCursorResults(ResultSetImpl rs, List<PgColInfo> cols, ResultsFuture<Integer> result, int rowCount);
+	
+	void sendPortalResults(String sql, ResultSetImpl rs, List<PgColInfo> cols, ResultsFuture<Integer> result, int rowCount, boolean portal);
+	
+	void sendMoveCursor(ResultSetImpl rs, int rowCount, ResultsFuture<Integer> results);
+	
+	void sendCommandComplete(String sql, int updateCount) throws IOException;	
 
 	//	CommandComplete (B)
 	void sendUpdateCount(String sql, int updateCount);
@@ -106,8 +115,5 @@
 	//	NoticeResponse (B)
 	//	NotificationResponse (B)
 	
-	//	PortalSuspended (B)
-	
-		
-
+	void sendPortalSuspended();
 }

Modified: trunk/runtime/src/main/java/org/teiid/odbc/ODBCServerRemoteImpl.java
===================================================================
--- trunk/runtime/src/main/java/org/teiid/odbc/ODBCServerRemoteImpl.java	2011-07-22 15:32:56 UTC (rev 3326)
+++ trunk/runtime/src/main/java/org/teiid/odbc/ODBCServerRemoteImpl.java	2011-07-22 16:26:08 UTC (rev 3327)
@@ -21,14 +21,19 @@
  */
 package org.teiid.odbc;
 
+import static org.teiid.odbc.PGUtil.convertType;
+
 import java.io.IOException;
 import java.io.StringReader;
 import java.sql.ResultSet;
+import java.sql.ResultSetMetaData;
 import java.sql.SQLException;
 import java.sql.Statement;
+import java.util.ArrayList;
 import java.util.Collections;
 import java.util.Enumeration;
 import java.util.HashMap;
+import java.util.List;
 import java.util.Map;
 import java.util.Properties;
 import java.util.concurrent.ExecutionException;
@@ -40,10 +45,12 @@
 import org.teiid.core.util.StringUtil;
 import org.teiid.jdbc.ConnectionImpl;
 import org.teiid.jdbc.PreparedStatementImpl;
+import org.teiid.jdbc.ResultSetImpl;
 import org.teiid.jdbc.StatementImpl;
 import org.teiid.jdbc.TeiidDriver;
 import org.teiid.logging.LogConstants;
 import org.teiid.logging.LogManager;
+import org.teiid.odbc.PGUtil.PgColInfo;
 import org.teiid.runtime.RuntimePlugin;
 import org.teiid.transport.ODBCClientInstance;
 
@@ -133,11 +140,17 @@
 	private static Pattern preparedAutoIncrement = Pattern.compile("select 1 \\s*from pg_catalog.pg_attrdef \\s*where adrelid = \\$1 AND adnum = \\$2 " + //$NON-NLS-1$
 			"\\s*and pg_catalog.pg_get_expr\\(adbin, adrelid\\) \\s*like '%nextval\\(%'", Pattern.CASE_INSENSITIVE); //$NON-NLS-1$
 	
-	private static Pattern deallocatePattern = Pattern.compile("DEALLOCATE \"(\\w+\\d+_*)\""); //$NON-NLS-1$
-	private static Pattern releasePattern = Pattern.compile("RELEASE (\\w+\\d+_*)"); //$NON-NLS-1$
-	private static Pattern savepointPattern = Pattern.compile("SAVEPOINT (\\w+\\d+_*)"); //$NON-NLS-1$
-	private static Pattern rollbackPattern = Pattern.compile("ROLLBACK\\s*(to)*\\s*(\\w+\\d+_*)*"); //$NON-NLS-1$
+	private static Pattern cursorSelectPattern = Pattern.compile("DECLARE \"(\\w+)\" CURSOR(\\s(WITH HOLD|SCROLL))? FOR (.*)", Pattern.CASE_INSENSITIVE|Pattern.DOTALL); //$NON-NLS-1$
+	private static Pattern fetchPattern = Pattern.compile("FETCH (\\d+) IN \"(\\w+)\".*", Pattern.CASE_INSENSITIVE); //$NON-NLS-1$
+	private static Pattern movePattern = Pattern.compile("MOVE (\\d+) IN \"(\\w+)\".*", Pattern.CASE_INSENSITIVE); //$NON-NLS-1$
+	private static Pattern closePattern = Pattern.compile("CLOSE \"(\\w+)\"", Pattern.CASE_INSENSITIVE); //$NON-NLS-1$
 	
+	private static Pattern deallocatePattern = Pattern.compile("DEALLOCATE \"(\\w+\\d+_*)\"", Pattern.CASE_INSENSITIVE); //$NON-NLS-1$
+	private static Pattern releasePattern = Pattern.compile("RELEASE (\\w+\\d?_*)", Pattern.CASE_INSENSITIVE); //$NON-NLS-1$
+	private static Pattern savepointPattern = Pattern.compile("SAVEPOINT (\\w+\\d?_*)", Pattern.CASE_INSENSITIVE); //$NON-NLS-1$
+	private static Pattern rollbackPattern = Pattern.compile("ROLLBACK\\s*(to)*\\s*(\\w+\\d+_*)*", Pattern.CASE_INSENSITIVE); //$NON-NLS-1$
+	
+	
 	private TeiidDriver driver;
 	private ODBCClientRemote client;
 	private Properties props;
@@ -151,6 +164,7 @@
 	// TODO: this is unbounded map; need to define some boundaries as to how many stmts each session can have
 	private Map<String, Prepared> preparedMap = Collections.synchronizedMap(new HashMap<String, Prepared>());
 	private Map<String, Portal> portalMap = Collections.synchronizedMap(new HashMap<String, Portal>());
+	private Map<String, Cursor> cursorMap = Collections.synchronizedMap(new HashMap<String, Cursor>());
 	
 	public ODBCServerRemoteImpl(ODBCClientInstance client, AuthenticationType authType, TeiidDriver driver) {
 		this.driver = driver;
@@ -196,6 +210,173 @@
 		} 
 	}	
 	
+	private void cursorExecute(final String cursorName, final String sql, final ResultsFuture<Integer> completion) {
+		if (this.connection != null) {
+			if (sql != null) {
+				try {
+					// close if the name is already used or the unnamed prepare; otherwise
+					// stmt is alive until session ends.
+					Prepared previous = this.preparedMap.remove(cursorName);
+					if (previous != null) {
+						previous.stmt.close();
+					}
+					
+					final PreparedStatementImpl stmt = this.connection.prepareStatement(sql);
+	                this.executionFuture = stmt.submitExecute();
+	                this.executionFuture.addCompletionListener(new ResultsFuture.CompletionListener<Boolean>() {
+		        		@Override
+		        		public void onCompletion(ResultsFuture<Boolean> future) {
+		        			executionFuture = null;
+	                        try {
+				                if (future.get()) {
+				                	List<PgColInfo> cols = getPgColInfo(stmt.getResultSet().getMetaData());
+		                            cursorMap.put(cursorName, new Cursor(cursorName, sql, stmt, null, stmt.getResultSet(), cols));
+		        					client.sendCommandComplete("DECLARE CURSOR", 0); //$NON-NLS-1$		                            
+				                }
+				                else {
+				                	errorOccurred(RuntimePlugin.Util.getString("execution_failed")); //$NON-NLS-1$
+				                }
+	                        } catch (Throwable e) {
+	                            errorOccurred(e);
+	                        }
+			                completion.getResultsReceiver().receiveResults(1);			                	                        
+		        		}
+					});					
+				} catch (SQLException e) {
+					errorOccurred(e);
+					completion.getResultsReceiver().receiveResults(1);
+				} 
+			}
+		}
+		else {
+			errorOccurred(RuntimePlugin.Util.getString("no_active_connection")); //$NON-NLS-1$
+			completion.getResultsReceiver().receiveResults(1);
+		}
+		
+	}
+	
+	private void cursorFetch(String cursorName, int rows, final ResultsFuture<Integer> completion) {
+		Cursor cursor = this.cursorMap.get(cursorName);
+		if (cursor != null) {
+			cursor.fetchSize = rows;
+			ResultsFuture<Integer> result = new ResultsFuture<Integer>();
+			this.client.sendCursorResults(cursor.rs, cursor.columnMetadata, result, rows);
+			result.addCompletionListener(new ResultsFuture.CompletionListener<Integer>() {
+            	public void onCompletion(ResultsFuture<Integer> future) {
+            		int rowsSent = 0;
+            		try {
+						rowsSent = future.get();
+						client.sendCommandComplete("FETCH", rowsSent); //$NON-NLS-1$						
+					} catch (InterruptedException e) {
+						throw new AssertionError(e);
+					} catch (ExecutionException e) {
+						errorOccurred(e.getCause());
+					} catch (IOException e) {
+						errorOccurred(e);
+					}
+					completion.getResultsReceiver().receiveResults(rowsSent);
+            	};
+			});
+		}
+		else {
+			errorOccurred(RuntimePlugin.Util.getString("not_bound", cursorName)); //$NON-NLS-1$
+			completion.getResultsReceiver().receiveResults(1);
+		}
+	}
+	
+	private void cursorMove(String prepareName, int rows, final ResultsFuture<Integer> completion) {
+		
+		// win odbc driver sending a move after close; and error is ending up in failure; since the below
+		// is not harmful it is ok to send empty move.
+		if (rows == 0) {
+			try {
+				client.sendCommandComplete("MOVE", 0); //$NON-NLS-1$
+			} catch (IOException e) {
+				errorOccurred(e);
+			}
+			completion.getResultsReceiver().receiveResults(0);
+			return;			
+		}
+		
+		Cursor cursor = this.cursorMap.get(prepareName);
+		if (cursor != null) {
+			ResultsFuture<Integer> result = new ResultsFuture<Integer>();
+			this.client.sendMoveCursor(cursor.rs, rows, result);
+			result.addCompletionListener(new ResultsFuture.CompletionListener<Integer>() {
+            	public void onCompletion(ResultsFuture<Integer> future) {
+            		int rowsMoved = 0;
+            		try {
+						rowsMoved = future.get();
+						client.sendCommandComplete("MOVE", rowsMoved); //$NON-NLS-1$						
+					} catch (InterruptedException e) {
+						throw new AssertionError(e);
+					} catch (ExecutionException e) {
+						errorOccurred(e.getCause());
+					} catch (IOException e) {
+						errorOccurred(e);
+					}
+					completion.getResultsReceiver().receiveResults(rowsMoved);
+            	};
+			});			
+		}
+		else {
+			errorOccurred(RuntimePlugin.Util.getString("not_bound", prepareName)); //$NON-NLS-1$
+			completion.getResultsReceiver().receiveResults(1);
+		}
+	}	
+	
+	private void cursorClose(String prepareName) throws SQLException, IOException {
+		Cursor cursor = this.cursorMap.remove(prepareName);
+		if (cursor != null) {
+			cursor.rs.close();
+			cursor.stmt.close();
+			this.client.sendCommandComplete("CLOSE CURSOR", 0); //$NON-NLS-1$
+		}
+	}	
+	
+    private void sqlExecute(final String sql, final ResultsFuture<Integer> completion) throws SQLException {
+    	String modfiedSQL = fixSQL(sql); 
+    	final StatementImpl stmt = connection.createStatement();
+        executionFuture = stmt.submitExecute(modfiedSQL);
+        executionFuture.addCompletionListener(new ResultsFuture.CompletionListener<Boolean>() {
+    		@Override
+    		public void onCompletion(ResultsFuture<Boolean> future) {
+    			executionFuture = null;
+    			try {
+    				ResultsFuture<Integer> result = new ResultsFuture<Integer>();
+	                if (future.get()) {
+	                	if (stmt.getResultSet() != null) {
+	                		List<PgColInfo> cols = getPgColInfo(stmt.getResultSet().getMetaData());
+                            client.sendResults(sql, stmt.getResultSet(), cols, result, true);
+	                	}
+	                	else {
+	                		// handles the "SET" commands.
+		                	client.sendUpdateCount(sql, 0);
+		                	result.getResultsReceiver().receiveResults(1);
+	                	}					                	
+	                } else {
+	                	client.sendUpdateCount(sql, stmt.getUpdateCount());
+	                	setEncoding();
+	                	result.getResultsReceiver().receiveResults(1);
+	                }
+	                result.addCompletionListener(new ResultsFuture.CompletionListener<Integer>() {
+	                	public void onCompletion(ResultsFuture<Integer> future) {
+							try {
+								stmt.close();
+							} catch (SQLException e) {
+								LogManager.logDetail(LogConstants.CTX_ODBC, e, "Error closing statement"); //$NON-NLS-1$
+							}
+							completion.getResultsReceiver().receiveResults(1);
+	                	}
+	                });
+    			} catch (Throwable e) {
+    				errorOccurred(e);
+    				completion.getResultsReceiver().receiveResults(1);
+    			}
+    		}
+		});    	
+    }	
+	
 	@Override
 	public void prepare(String prepareName, String sql, int[] paramType) {
 		if (this.connection != null) {
@@ -274,60 +455,96 @@
 			bindName  = UNNAMED;
 		}		
 		
+		// special case cursor execution through portal
+		final Cursor cursor = this.cursorMap.get(bindName);
+		if (cursor != null) {
+			sendCursorResults(cursor);
+			return;
+		}		
+		
 		final Portal query = this.portalMap.get(bindName);
 		if (query == null) {
 			errorOccurred(RuntimePlugin.Util.getString("not_bound", bindName)); //$NON-NLS-1$
-		}				
-		else {
-			if (query.sql.trim().isEmpty()) {
-				this.client.emptyQueryReceived();
-				return;
-			}
-			
-            final PreparedStatementImpl stmt = query.stmt;
-            try {
-            	// maxRows = 0, means unlimited.
-            	if (maxRows != 0) {
-            		stmt.setMaxRows(maxRows);
-            	}
-            	
-                this.executionFuture = stmt.submitExecute();
-                executionFuture.addCompletionListener(new ResultsFuture.CompletionListener<Boolean>() {
-	        		@Override
-	        		public void onCompletion(ResultsFuture<Boolean> future) {
-	        			executionFuture = null;
-                        try {
-                        	ResultsFuture<Void> result = null;
-			                if (future.get()) {
-			                	result = new ResultsFuture<Void>();
-	                            client.sendResults(query.sql, stmt.getResultSet(), result, true);
-			                } else {
-			                	result = ResultsFuture.NULL_FUTURE;
-			                	client.sendUpdateCount(query.sql, stmt.getUpdateCount());
-			                	setEncoding();
-			                }
-		        			result.addCompletionListener(new ResultsFuture.CompletionListener<Void>() {
-                            	public void onCompletion(ResultsFuture<Void> future) {
-                            		try {
-										future.get();
-	                            		doneExecuting();
-									} catch (InterruptedException e) {
-										throw new AssertionError(e);
-									} catch (ExecutionException e) {
-										errorOccurred(e.getCause());
-									}
-                            	};
-							});
-                        } catch (Throwable e) {
-                            errorOccurred(e);
-                        }
-	        		}
-				});
-            } catch (SQLException e) {
-            	errorOccurred(e);
-            }			
+			return;
+		}	
+		
+		if (query.sql.trim().isEmpty()) {
+			this.client.emptyQueryReceived();
+			return;
 		}
+		
+        sendPortalResults(maxRows, query);			
 	}
+
+	private void sendPortalResults(int maxRows, final Portal query) {
+		final PreparedStatementImpl stmt = query.stmt;
+        try {
+        	// maxRows = 0, means unlimited.
+        	if (maxRows != 0) {
+        		stmt.setMaxRows(maxRows);
+        	}
+        	
+            this.executionFuture = stmt.submitExecute();
+            executionFuture.addCompletionListener(new ResultsFuture.CompletionListener<Boolean>() {
+        		@Override
+        		public void onCompletion(ResultsFuture<Boolean> future) {
+        			executionFuture = null;
+                    try {
+                    	ResultsFuture<Integer> result = new ResultsFuture<Integer>();
+		                if (future.get()) {
+		                	List<PgColInfo> cols = getPgColInfo(stmt.getResultSet().getMetaData());
+                            client.sendResults(query.sql, stmt.getResultSet(), cols, result, true);
+		                } else {
+		                	// null future
+		                	client.sendUpdateCount(query.sql, stmt.getUpdateCount());
+		                	setEncoding();
+		                	result.getResultsReceiver().receiveResults(1);
+		                }
+	        			result.addCompletionListener(new ResultsFuture.CompletionListener<Integer>() {
+                        	public void onCompletion(ResultsFuture<Integer> future) {
+                        		try {
+									future.get();
+                            		doneExecuting();
+								} catch (InterruptedException e) {
+									throw new AssertionError(e);
+								} catch (ExecutionException e) {
+									errorOccurred(e.getCause());
+								}
+                        	};
+						});
+                    } catch (Throwable e) {
+                        errorOccurred(e);
+                    }
+        		}
+			});
+        } catch (SQLException e) {
+        	errorOccurred(e);
+        }
+	}
+
+	private void sendCursorResults(final Cursor cursor) {
+		ResultsFuture<Integer> result = new ResultsFuture<Integer>();
+		this.client.sendPortalResults(cursor.sql, cursor.rs, cursor.columnMetadata, result, cursor.fetchSize, true);
+		result.addCompletionListener(new ResultsFuture.CompletionListener<Integer>() {
+			public void onCompletion(ResultsFuture<Integer> future) {
+				try {
+					int rowsSent = future.get();
+					if (rowsSent < cursor.fetchSize) {
+						client.sendCommandComplete(cursor.sql, 0);
+					}
+					else {
+						client.sendPortalSuspended();
+					}
+				} catch (InterruptedException e) {
+					throw new AssertionError(e);
+				} catch (ExecutionException e) {
+					errorOccurred(e.getCause());
+				} catch (IOException e) {
+					errorOccurred(e);
+				}
+			};
+		});
+	}
 	
 	private String fixSQL(String sql) {
 		String modified = modifySQL(sql);
@@ -409,16 +626,6 @@
 			}
 			else if ((m = rollbackPattern.matcher(modified)).matches()) {
 				return "ROLLBACK"; //$NON-NLS-1$
-			}	
-			else if ((m = savepointPattern.matcher(modified)).matches()) {
-				return "SELECT 'SAVEPOINT'"; //$NON-NLS-1$
-			}
-			else if ((m = releasePattern.matcher(modified)).matches()) {
-				return "SELECT 'RELEASE'"; //$NON-NLS-1$
-			}		
-			else if ((m = deallocatePattern.matcher(modified)).matches()) {
-				closePreparedStatement(m.group(1));
-				return "SELECT 'DEALLOCATE'"; //$NON-NLS-1$
 			}					
 		}
 		modified = sql;
@@ -431,7 +638,7 @@
 	@Override
 	public void executeQuery(final String query) {
 		if (beginExecution()) {
-			this.client.errorOccurred("Awaiting asynch result"); //$NON-NLS-1$
+			errorOccurred("Awaiting asynch result"); //$NON-NLS-1$
 			ready();
 			return;
 		}
@@ -482,7 +689,8 @@
 				
 				// followed by a RowDescription message describing the rows that will be returned when the statement  
 				// is eventually executed (or a NoData message if the statement will not return rows).
-				this.client.sendResultSetDescription(query.stmt.getMetaData(), query.stmt);
+				List<PgColInfo> cols = getPgColInfo(query.stmt.getMetaData());
+				this.client.sendResultSetDescription(cols);
 			} catch (SQLException e) {
 				errorOccurred(e);
 			}
@@ -516,7 +724,8 @@
 		}
 		else {
 			try {
-				this.client.sendResultSetDescription(query.stmt.getMetaData(), query.stmt);
+				List<PgColInfo> cols = getPgColInfo(query.stmt.getMetaData());
+				this.client.sendResultSetDescription(cols);
 			} catch (SQLException e) {
 				errorOccurred(e);
 			}
@@ -622,6 +831,9 @@
 			
 		try {			
 			if (this.connection != null) {
+				if (!this.connection.getAutoCommit()) {
+					this.connection.rollback(false);
+				}
 				this.connection.close();
 			}
 		} catch (SQLException e) {
@@ -663,90 +875,124 @@
 	
     private final class QueryWorkItem implements Runnable {
 		private final ScriptReader reader;
-		String modfiedSQL;
 		String sql;
 
 		private QueryWorkItem(String query) {
-			this.reader = new ScriptReader(new StringReader(query));
+			this.reader = new ScriptReader(new StringReader(query));		
 		}
 
 		@Override
 		public void run() {
 			try {
-				if (modfiedSQL == null) {
+				if (sql == null) {
 					sql = reader.readStatement();
-			        modfiedSQL = fixSQL(sql);
 				}
-		        while (modfiedSQL != null) {
+		        while (sql != null) {
 		            try {
-		            	final StatementImpl stmt = connection.createStatement();
-		                executionFuture = stmt.submitExecute(modfiedSQL);
-		                executionFuture.addCompletionListener(new ResultsFuture.CompletionListener<Boolean>() {
-			        		@Override
-			        		public void onCompletion(ResultsFuture<Boolean> future) {
-			        			executionFuture = null;
-			        			try {
-			        				ResultsFuture<Void> result = null;
-					                if (future.get()) {
-					                	if (stmt.getResultSet() != null) {
-						                	result = new ResultsFuture<Void>();
-				                            client.sendResults(sql, stmt.getResultSet(), result, true);
-					                	}
-					                	else {
-					                		// handles the "SET" commands.
-						                	result = ResultsFuture.NULL_FUTURE;
-						                	client.sendUpdateCount(sql, 0);
-					                	}					                	
-					                } else {
-					                	result = ResultsFuture.NULL_FUTURE;
-					                	client.sendUpdateCount(sql, stmt.getUpdateCount());
-					                	setEncoding();
-					                }
-					                result.addCompletionListener(new ResultsFuture.CompletionListener<Void>() {
-		                            	public void onCompletion(ResultsFuture<Void> future) {
-		                            		try {
-												future.get();
-								                sql = reader.readStatement();
-								                modfiedSQL = fixSQL(sql);
-											} catch (InterruptedException e) {
-												throw new AssertionError(e);
-											} catch (IOException e) {
-												client.errorOccurred(e);
-												return;
-											} catch (ExecutionException e) {
-												client.errorOccurred(e.getCause());
-												return;
-											} finally {
-												try {
-													stmt.close();
-												} catch (SQLException e) {
-													LogManager.logDetail(LogConstants.CTX_ODBC, e, "Error closing statement"); //$NON-NLS-1$
-												}
-											}
-						        			QueryWorkItem.this.run(); //continue processing
-		                            	};
-									});
-			        			} catch (Throwable e) {
-			        				client.errorOccurred(e);
-			        				return;
-			        			}
-			        		}
-						});
+		    			
+		            	ResultsFuture<Integer> results = new ResultsFuture<Integer>();
+		    			results.addCompletionListener(new ResultsFuture.CompletionListener<Integer>() {
+		                	public void onCompletion(ResultsFuture<Integer> future) {
+		                		try {		                			
+		    						future.get();
+		    		                sql = reader.readStatement();
+		    					} catch (InterruptedException e) {
+		    						throw new AssertionError(e);
+		    					} catch (IOException e) {
+		    						client.errorOccurred(e);
+		    						return;
+		    					} catch (ExecutionException e) {
+		    						client.errorOccurred(e.getCause());
+		    						return;
+		    					}
+		            			QueryWorkItem.this.run(); //continue processing
+		                	};
+		    			});	
+		    			
+		    			if (isErrorOccurred()) {
+		    				if (!connection.getAutoCommit()) {
+		    					connection.rollback(false);
+		    				}
+		    				break;
+		    			}
+		    			
+		            	Matcher m = null;
+		    	        if ((m = cursorSelectPattern.matcher(sql)).matches()){
+		    				cursorExecute(m.group(1), fixSQL(m.group(4)), results);
+		    			}
+		    			else if ((m = fetchPattern.matcher(sql)).matches()){
+		    				cursorFetch(m.group(2), Integer.parseInt(m.group(1)), results);
+		    			}
+		    			else if ((m = movePattern.matcher(sql)).matches()){
+		    				cursorMove(m.group(2), Integer.parseInt(m.group(1)), results);
+		    			}
+		    			else if ((m = closePattern.matcher(sql)).matches()){
+		    				cursorClose(m.group(1));
+		    				results.getResultsReceiver().receiveResults(1);
+		    			}
+		    			else if ((m = savepointPattern.matcher(sql)).matches()) {
+		    				client.sendCommandComplete("SAVEPOINT", 0); //$NON-NLS-1$
+		    				results.getResultsReceiver().receiveResults(1);
+		    			}
+		    			else if ((m = releasePattern.matcher(sql)).matches()) {
+		    				client.sendCommandComplete("RELEASE", 0); //$NON-NLS-1$
+		    				results.getResultsReceiver().receiveResults(1);
+		    			}		
+		    			else if ((m = deallocatePattern.matcher(sql)).matches()) { 
+		    				closePreparedStatement(m.group(1));
+		    				client.sendCommandComplete("DEALLOCATE", 0); //$NON-NLS-1$
+		    				results.getResultsReceiver().receiveResults(1);
+		    			}
+		    			else {
+		    				sqlExecute(sql, results);
+		    			}
 		                return; //wait for the execution to finish
 		            } catch (SQLException e) {
-		                client.errorOccurred(e);
+		                errorOccurred(e);
 		                break;
 		            } 
 		        }
 			} catch(IOException e) {
-				client.errorOccurred(e);
+				errorOccurred(e);
 			}
 			doneExecuting();
 			ready();
 		}
-
 	}
-
+    
+	private List<PgColInfo> getPgColInfo(ResultSetMetaData meta)
+			throws SQLException {
+		int columns = meta.getColumnCount();
+		final ArrayList<PgColInfo> result = new ArrayList<PgColInfo>(columns);
+		for (int i = 1; i < columns + 1; i++) {
+			final PgColInfo info = new PgColInfo();
+			info.name = meta.getColumnLabel(i).toLowerCase();
+			info.type = meta.getColumnType(i);
+			info.type = convertType(info.type);
+			info.precision = meta.getColumnDisplaySize(i);
+			String name = meta.getColumnName(i);
+			String table = meta.getTableName(i);
+			String schema = meta.getSchemaName(i);
+			if (schema != null) {
+				final PreparedStatementImpl ps = this.connection.prepareStatement("select attrelid, attnum, typoid from matpg_relatt where attname = ? and relname = ? and nspname = ?"); //$NON-NLS-1$
+				ps.setString(1, name);
+				ps.setString(2, table);
+				ps.setString(3, schema);	
+				ResultSet rs = ps.executeQuery();
+				if (rs.next()) {
+					info.reloid = rs.getInt(1);
+					info.attnum = rs.getShort(2);
+					int specificType = rs.getInt(3);
+					if (!rs.wasNull()) {
+						info.type = specificType;
+					}
+				}					
+			}
+			result.add(info);
+		}
+		return result;
+	}  
+    
 	/**
      * Represents a PostgreSQL Prepared object.
      */
@@ -777,7 +1023,7 @@
         /**
          * The list of parameter types (if set).
          */
-        int[] paramType;
+        int[] paramType;        
     }
 
     /**
@@ -813,7 +1059,22 @@
         /**
          * The prepared statement.
          */
-        PreparedStatementImpl stmt;
+        PreparedStatementImpl stmt;        
     }
+    
+    static class Cursor extends Prepared {
+    	ResultSetImpl rs;
+    	int fetchSize = 1000;
+        /**
+         * calculated column metadata
+         */
+        List<PgColInfo> columnMetadata;	
+    	
+    	public Cursor (String name, String sql, PreparedStatementImpl stmt, int[] paramType, ResultSetImpl rs, List<PgColInfo> colMetadata) {
+    		super(name, sql, stmt, paramType);
+    		this.rs = rs;
+    		this.columnMetadata = colMetadata;
+    	}
+    }    
 
 }

Copied: trunk/runtime/src/main/java/org/teiid/odbc/PGUtil.java (from rev 3325, branches/7.4.x/runtime/src/main/java/org/teiid/odbc/PGUtil.java)
===================================================================
--- trunk/runtime/src/main/java/org/teiid/odbc/PGUtil.java	                        (rev 0)
+++ trunk/runtime/src/main/java/org/teiid/odbc/PGUtil.java	2011-07-22 16:26:08 UTC (rev 3327)
@@ -0,0 +1,114 @@
+/*
+ * 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.odbc;
+
+import java.sql.Types;
+
+import org.teiid.deployers.PgCatalogMetadataStore;
+
+public class PGUtil {
+
+	public static final int PG_TYPE_VARCHAR = 1043;
+
+	public static final int PG_TYPE_BOOL = 16;
+	public static final int PG_TYPE_BYTEA = 17;
+	public static final int PG_TYPE_BPCHAR = 1042;
+	public static final int PG_TYPE_INT8 = 20;
+	public static final int PG_TYPE_INT2 = 21;
+	public static final int PG_TYPE_INT4 = 23;
+	public static final int PG_TYPE_TEXT = 25;
+    //private static final int PG_TYPE_OID = 26;
+	public static final int PG_TYPE_FLOAT4 = 700;
+	public static final int PG_TYPE_FLOAT8 = 701;
+	public static final int PG_TYPE_UNKNOWN = 705;
+    
+	public static final int PG_TYPE_OIDVECTOR = PgCatalogMetadataStore.PG_TYPE_OIDVECTOR;
+	public static final int PG_TYPE_OIDARRAY = PgCatalogMetadataStore.PG_TYPE_OIDARRAY;
+	public static final int PG_TYPE_CHARARRAY = PgCatalogMetadataStore.PG_TYPE_CHARARRAY;
+	public static final int PG_TYPE_TEXTARRAY = PgCatalogMetadataStore.PG_TYPE_TEXTARRAY;
+    
+	public static final int PG_TYPE_DATE = 1082;
+	public static final int PG_TYPE_TIME = 1083;
+	public static final int PG_TYPE_TIMESTAMP_NO_TMZONE = 1114;
+	public static final int PG_TYPE_NUMERIC = 1700;
+    //private static final int PG_TYPE_LO = 14939;
+    
+	public static class PgColInfo {
+		public String name;
+		public int reloid;
+		public short attnum;
+		public int type;
+		public int precision;
+	}
+		
+	/**
+	 * Types.ARRAY is not supported
+	 */
+	public static int convertType(final int type) {
+        switch (type) {
+        case Types.BIT:
+        case Types.BOOLEAN:
+            return PG_TYPE_BOOL;
+        case Types.VARCHAR:
+            return PG_TYPE_VARCHAR;        
+        case Types.CHAR:
+            return PG_TYPE_BPCHAR;
+        case Types.TINYINT:
+        case Types.SMALLINT:
+        	return PG_TYPE_INT2;
+        case Types.INTEGER:
+            return PG_TYPE_INT4;
+        case Types.BIGINT:
+            return PG_TYPE_INT8;
+        case Types.NUMERIC:
+        case Types.DECIMAL:
+            return PG_TYPE_NUMERIC;
+        case Types.FLOAT:
+        case Types.REAL:
+            return PG_TYPE_FLOAT4;
+        case Types.DOUBLE:
+            return PG_TYPE_FLOAT8;
+        case Types.TIME:
+            return PG_TYPE_TIME;
+        case Types.DATE:
+            return PG_TYPE_DATE;
+        case Types.TIMESTAMP:
+            return PG_TYPE_TIMESTAMP_NO_TMZONE;
+            
+        case Types.BLOB:            
+        case Types.BINARY:
+        case Types.VARBINARY:
+        case Types.LONGVARBINARY:
+        	return PG_TYPE_BYTEA;
+        	
+        case Types.LONGVARCHAR:
+        case Types.CLOB:            
+        	return PG_TYPE_TEXT;
+        
+        case Types.SQLXML:        	
+            return PG_TYPE_TEXT;
+            
+        default:
+            return PG_TYPE_UNKNOWN;
+        }
+	}	
+}

Modified: trunk/runtime/src/main/java/org/teiid/transport/PgBackendProtocol.java
===================================================================
--- trunk/runtime/src/main/java/org/teiid/transport/PgBackendProtocol.java	2011-07-22 15:32:56 UTC (rev 3326)
+++ trunk/runtime/src/main/java/org/teiid/transport/PgBackendProtocol.java	2011-07-22 16:26:08 UTC (rev 3327)
@@ -21,6 +21,26 @@
  * 02110-1301 USA.
  */package org.teiid.transport;
 
+import static org.teiid.odbc.PGUtil.PG_TYPE_BOOL;
+import static org.teiid.odbc.PGUtil.PG_TYPE_BPCHAR;
+import static org.teiid.odbc.PGUtil.PG_TYPE_BYTEA;
+import static org.teiid.odbc.PGUtil.PG_TYPE_CHARARRAY;
+import static org.teiid.odbc.PGUtil.PG_TYPE_DATE;
+import static org.teiid.odbc.PGUtil.PG_TYPE_FLOAT4;
+import static org.teiid.odbc.PGUtil.PG_TYPE_FLOAT8;
+import static org.teiid.odbc.PGUtil.PG_TYPE_INT2;
+import static org.teiid.odbc.PGUtil.PG_TYPE_INT4;
+import static org.teiid.odbc.PGUtil.PG_TYPE_INT8;
+import static org.teiid.odbc.PGUtil.PG_TYPE_NUMERIC;
+import static org.teiid.odbc.PGUtil.PG_TYPE_OIDARRAY;
+import static org.teiid.odbc.PGUtil.PG_TYPE_OIDVECTOR;
+import static org.teiid.odbc.PGUtil.PG_TYPE_TEXT;
+import static org.teiid.odbc.PGUtil.PG_TYPE_TEXTARRAY;
+import static org.teiid.odbc.PGUtil.PG_TYPE_TIME;
+import static org.teiid.odbc.PGUtil.PG_TYPE_TIMESTAMP_NO_TMZONE;
+import static org.teiid.odbc.PGUtil.PG_TYPE_UNKNOWN;
+import static org.teiid.odbc.PGUtil.PG_TYPE_VARCHAR;
+
 import java.io.ByteArrayOutputStream;
 import java.io.DataOutputStream;
 import java.io.IOException;
@@ -32,13 +52,9 @@
 import java.sql.Blob;
 import java.sql.Clob;
 import java.sql.ParameterMetaData;
-import java.sql.PreparedStatement;
 import java.sql.ResultSet;
-import java.sql.ResultSetMetaData;
 import java.sql.SQLException;
-import java.sql.Statement;
 import java.sql.Types;
-import java.util.ArrayList;
 import java.util.List;
 import java.util.Properties;
 
@@ -58,16 +74,15 @@
 import org.teiid.core.util.ObjectConverterUtil;
 import org.teiid.core.util.ReaderInputStream;
 import org.teiid.core.util.ReflectionHelper;
-import org.teiid.deployers.PgCatalogMetadataStore;
 import org.teiid.jdbc.ResultSetImpl;
 import org.teiid.jdbc.TeiidSQLException;
 import org.teiid.logging.LogConstants;
 import org.teiid.logging.LogManager;
 import org.teiid.net.socket.ServiceInvocationStruct;
 import org.teiid.odbc.ODBCClientRemote;
+import org.teiid.odbc.PGUtil.PgColInfo;
 import org.teiid.runtime.RuntimePlugin;
 import org.teiid.transport.pg.PGbytea;
-
 /**
  * Represents the messages going from Server --> PG ODBC Client  
  * Some parts of this code is taken from H2's implementation of ODBC
@@ -92,19 +107,24 @@
 			}
 		}
 	}
-
+	
+    // 300k
+	static int ODBC_SOCKET_BUFF_SIZE = Integer.parseInt(System.getProperty("ODBCPacketSize", "307200"));
+	
 	private final class ResultsWorkItem implements Runnable {
 		private final List<PgColInfo> cols;
-		private final String sql;
 		private final ResultSetImpl rs;
-		private final ResultsFuture<Void> result;
+		private final ResultsFuture<Integer> result;
+		private int rows2Send;
+		private int rowsSent = 0;
+		private int rowsInBuffer = 0;
+		private ChannelBuffer buffer = ChannelBuffers.directBuffer(ODBC_SOCKET_BUFF_SIZE);
 
-		private ResultsWorkItem(List<PgColInfo> cols, String sql,
-				ResultSetImpl rs, ResultsFuture<Void> result) {
+		private ResultsWorkItem(List<PgColInfo> cols, ResultSetImpl rs, ResultsFuture<Integer> result, int rows2Send) {
 			this.cols = cols;
-			this.sql = sql;
 			this.rs = rs;
 			this.result = result;
+			this.rows2Send = rows2Send;
 		}
 
 		@Override
@@ -117,8 +137,10 @@
 				    		@Override
 				    		public void onCompletion(ResultsFuture<Boolean> future) {
 				    			if (processRow(future)) {
-				    				//this can be recursive, but ideally won't be called many times 
-				    				ResultsWorkItem.this.run();
+				    				if (rowsSent != rows2Send) {
+				    					//this can be recursive, but ideally won't be called many times 
+				    					ResultsWorkItem.this.run();
+				    				}
 				    			}
 				    		}
 						});
@@ -138,10 +160,18 @@
 			boolean processNext = true;
 			try {
     			if (future.get()) {
-    				sendDataRow(rs, cols);
+    				sendDataRow(rs, cols, buffer);
+    				rowsSent++;
+    				rowsInBuffer++;
+    				boolean done = rowsSent == rows2Send;
+    				flushResults(done);
+    				processNext = !done;
+    				if (done) {
+    					result.getResultsReceiver().receiveResults(rowsSent);
+    				}
     			} else {
-    				sendCommandComplete(sql, 0);
-    				result.getResultsReceiver().receiveResults(null);
+    				sendContents(buffer);
+    				result.getResultsReceiver().receiveResults(rowsSent);
     				processNext = false;
     			}
 			} catch (Throwable t) {
@@ -150,33 +180,17 @@
 			}
 			return processNext;
 		}
+		
+		private void flushResults(boolean force) {
+			int avgRowsize = buffer.readableBytes()/rowsInBuffer;
+			if (force || buffer.writableBytes() < (avgRowsize*2)) {
+				sendContents(buffer);
+				buffer= ChannelBuffers.directBuffer(ODBC_SOCKET_BUFF_SIZE);
+				rowsInBuffer = 0;
+			}			
+		}
 	}
-
-	private static final int PG_TYPE_VARCHAR = 1043;
-
-    private static final int PG_TYPE_BOOL = 16;
-    private static final int PG_TYPE_BYTEA = 17;
-    private static final int PG_TYPE_BPCHAR = 1042;
-    private static final int PG_TYPE_INT8 = 20;
-    private static final int PG_TYPE_INT2 = 21;
-    private static final int PG_TYPE_INT4 = 23;
-    private static final int PG_TYPE_TEXT = 25;
-    //private static final int PG_TYPE_OID = 26;
-    private static final int PG_TYPE_FLOAT4 = 700;
-    private static final int PG_TYPE_FLOAT8 = 701;
-    private static final int PG_TYPE_UNKNOWN = 705;
     
-    private static final int PG_TYPE_OIDVECTOR = PgCatalogMetadataStore.PG_TYPE_OIDVECTOR;
-    private static final int PG_TYPE_OIDARRAY = PgCatalogMetadataStore.PG_TYPE_OIDARRAY;
-    private static final int PG_TYPE_CHARARRAY = PgCatalogMetadataStore.PG_TYPE_CHARARRAY;
-    private static final int PG_TYPE_TEXTARRAY = PgCatalogMetadataStore.PG_TYPE_TEXTARRAY;
-    
-    private static final int PG_TYPE_DATE = 1082;
-    private static final int PG_TYPE_TIME = 1083;
-    private static final int PG_TYPE_TIMESTAMP_NO_TMZONE = 1114;
-    private static final int PG_TYPE_NUMERIC = 1700;
-    //private static final int PG_TYPE_LO = 14939;
-    
     private DataOutputStream dataOut;
     private ByteArrayOutputStream outBuffer;
     private char messageType;
@@ -191,7 +205,7 @@
 
 	private SSLConfiguration config;
 
-    public PgBackendProtocol(int maxLobSize, SSLConfiguration config) {
+	public PgBackendProtocol(int maxLobSize, SSLConfiguration config) {
     	this.maxLobSize = maxLobSize;
     	this.config = config;
     }
@@ -340,35 +354,65 @@
 	}
 
 	@Override
-	public void sendResultSetDescription(ResultSetMetaData metaData, Statement stmt) {
+	public void sendResultSetDescription(List<PgColInfo> cols) {
 		try {
+			sendRowDescription(cols);
+		} catch (IOException e) {
+			terminate(e);
+		}
+	}
+	
+	@Override
+	public void sendCursorResults(ResultSetImpl rs, List<PgColInfo> cols, ResultsFuture<Integer> result, int rowCount) {
+		try {
+        	sendRowDescription(cols);
+
+        	ResultsWorkItem r = new ResultsWorkItem(cols, rs, result, rowCount);
+        	r.run();  	        					
+		} catch (IOException e) {
+			terminate(e);
+		}
+	}
+	
+	@Override
+	public void sendPortalResults(String sql, ResultSetImpl rs, List<PgColInfo> cols, ResultsFuture<Integer> result, int rowCount, boolean portal) {
+    	ResultsWorkItem r = new ResultsWorkItem(cols, rs, result, rowCount);
+    	r.run();	        	
+	}
+	
+	@Override
+	public void sendMoveCursor(ResultSetImpl rs, int rowCount, ResultsFuture<Integer> results) {
+		try {
 			try {
-        		List<PgColInfo> cols = getPgColInfo(metaData, stmt);
-				sendRowDescription(cols);
+				int rowsMoved = 0;
+				for (int i = 0; i < rowCount; i++) {
+					if (!rs.next()) {
+						break;
+					}
+					rowsMoved++;
+				}				
+				results.getResultsReceiver().receiveResults(rowsMoved);
 			} catch (SQLException e) {
-				sendErrorResponse(e);				
-			}			
+				sendErrorResponse(e);
+			}
 		} catch (IOException e) {
 			terminate(e);
 		}
-	}
+	}		
 	
 	@Override
-	public void sendResults(final String sql, final ResultSetImpl rs, ResultsFuture<Void> result, boolean describeRows) {
+	public void sendResults(final String sql, final ResultSetImpl rs, List<PgColInfo> cols, ResultsFuture<Integer> result, boolean describeRows) {
 		try {
 			if (nextFuture != null) {
 				sendErrorResponse(new IllegalStateException("Pending results have not been sent")); //$NON-NLS-1$
 			}
         	
-			ResultSetMetaData meta = rs.getMetaData();
-    		List<PgColInfo> cols = getPgColInfo(meta, rs.getStatement());
         	if (describeRows) {
         		sendRowDescription(cols);
         	}
-        	Runnable r = new ResultsWorkItem(cols, sql, rs, result);
+        	ResultsWorkItem r = new ResultsWorkItem(cols, rs, result, -1);
         	r.run();    
-		} catch (SQLException e) {
-			result.getResultsReceiver().exceptionOccurred(e);
+        	sendCommandComplete(sql, 0);
 		} catch (IOException e) {
 			terminate(e);
 		}
@@ -425,8 +469,9 @@
 		startMessage('I');
 		sendMessage();
 	}
-		
-	private void sendCommandComplete(String sql, int updateCount) throws IOException {
+
+	@Override
+	public void sendCommandComplete(String sql, int updateCount) throws IOException {
 		startMessage('C');
 		sql = sql.trim().toUpperCase();
 		// TODO remove remarks at the beginning
@@ -439,7 +484,7 @@
 			tag = "UPDATE " + updateCount;
 		} else if (sql.startsWith("SELECT") || sql.startsWith("CALL")) {
 			tag = "SELECT";
-		} else if (sql.startsWith("BEGIN")) {
+		} else if (sql.startsWith("BEGIN") || sql.startsWith("START TRANSACTION")) {
 			tag = "BEGIN";
 		} else if (sql.startsWith("COMMIT")) {
 			tag = "COMMIT";
@@ -447,15 +492,23 @@
 			tag = "ROLLBACK";
 		} else if (sql.startsWith("SET ")) {
 			tag = "SET";
-		}else {
-			trace("Check command tag:", sql);
-			tag = "UPDATE " + updateCount;
+		}  else if (sql.startsWith("DECLARE CURSOR")) {
+			tag = "DECLARE CURSOR";
+		} else if (sql.startsWith("CLOSE CURSOR")) {
+			tag = "CLOSE CURSOR";
+		} else if (sql.startsWith("FETCH")) {
+			tag = "FETCH "+ updateCount;
+		}  else if (sql.startsWith("MOVE")) {
+			tag = "MOVE "+ updateCount;
 		}
+		else {
+			tag = sql;
+		}
 		writeString(tag);
 		sendMessage();
 	}
 
-	private void sendDataRow(ResultSet rs, List<PgColInfo> cols) throws SQLException, IOException {
+	private void sendDataRow(ResultSet rs, List<PgColInfo> cols, ChannelBuffer buffer) throws SQLException, IOException {
 		startMessage('D');
 		writeShort(cols.size());
 		for (int i = 0; i < cols.size(); i++) {
@@ -467,9 +520,18 @@
 				write(bytes);
 			}
 		}
-		sendMessage();
+		
+		byte[] buff = outBuffer.toByteArray();
+		int len = buff.length;
+		this.outBuffer = null;
+		this.dataOut = null;
+		
+		// now build the wire contents.
+		buffer.writeByte((byte)this.messageType);
+		buffer.writeInt(len+4);
+		buffer.writeBytes(buff);
 	}
-
+	
 	private byte[] getContent(ResultSet rs, PgColInfo col, int column) throws SQLException, TeiidSQLException, IOException {
 		byte[] bytes = null;
 		switch (col.type) {
@@ -612,20 +674,7 @@
 		write(0);
 		sendMessage();
 	}
-
-	private void sendNoData() {
-		startMessage('n');
-		sendMessage();
-	}
 	
-	private static class PgColInfo {
-		String name;
-		int reloid;
-		short attnum;
-		int type;
-		int precision;
-	}
-
 	private void sendRowDescription(List<PgColInfo> cols) throws IOException {
 		startMessage('T');
 		writeShort(cols.size());
@@ -647,46 +696,6 @@
 		sendMessage();
 	}
 
-	private List<PgColInfo> getPgColInfo(ResultSetMetaData meta, Statement stmt)
-			throws SQLException {
-		int columns = meta.getColumnCount();
-		ArrayList<PgColInfo> result = new ArrayList<PgColInfo>(columns);
-		for (int i = 1; i < columns + 1; i++) {
-	 		PgColInfo info = new PgColInfo();
-			info.name = meta.getColumnName(i).toLowerCase();
-			info.type = meta.getColumnType(i);
-			info.type = convertType(info.type);
-			info.precision = meta.getColumnDisplaySize(i);
-			String name = meta.getColumnName(i);
-			String table = meta.getTableName(i);
-			String schema = meta.getSchemaName(i);
-			if (schema != null) {
-				PreparedStatement ps = null;
-				try {
-					ps = stmt.getConnection().prepareStatement("select attrelid, attnum, typoid from matpg_relatt where attname = ? and relname = ? and nspname = ?");
-					ps.setString(1, name);
-					ps.setString(2, table);
-					ps.setString(3, schema);
-					ResultSet rs = ps.executeQuery();
-					if (rs.next()) {
-						info.reloid = rs.getInt(1);
-						info.attnum = rs.getShort(2);
-						int specificType = rs.getInt(3);
-						if (!rs.wasNull()) {
-							info.type = specificType;
-						}
-					}
-				} finally {
-					if (ps != null) {
-						ps.close();
-					}
-				}
-			}
-			result.add(info);
-		}
-		return result;
-	}
-
 	private int getTypeSize(int pgType, int precision) {
 		switch (pgType) {
 		case PG_TYPE_VARCHAR:
@@ -728,6 +737,12 @@
 		startMessage('2');
 		sendMessage();
 	}
+	
+	@Override
+	public void sendPortalSuspended() {
+		startMessage('s');
+		sendMessage();
+	}	
 
 	private void sendAuthenticationCleartextPassword() throws IOException {
 		startMessage('R');
@@ -844,6 +859,10 @@
 		buffer.writeBytes(buff);
 		Channels.write(this.ctx, this.message.getFuture(), buffer, this.message.getRemoteAddress());
 	}
+	
+	private void sendContents(ChannelBuffer buffer) {
+		Channels.write(this.ctx, this.message.getFuture(), buffer, this.message.getRemoteAddress());
+	}
 
 	private static void trace(String... msg) {
 		LogManager.logTrace(LogConstants.CTX_ODBC, (Object[])msg);

Modified: trunk/runtime/src/main/resources/org/teiid/runtime/i18n.properties
===================================================================
--- trunk/runtime/src/main/resources/org/teiid/runtime/i18n.properties	2011-07-22 15:32:56 UTC (rev 3326)
+++ trunk/runtime/src/main/resources/org/teiid/runtime/i18n.properties	2011-07-22 16:26:08 UTC (rev 3327)
@@ -92,5 +92,6 @@
 ambigious_name=Ambiguous VDB name specified. Only single occurrence of the "." is allowed in the VDB name. Also, when version based vdb name is specified, then a separate "version" connection option is not allowed:{0}.{1} 
 lo_not_supported=LO functions are not supported
 SSLConfiguration.no_anonymous=The anonymous cipher suite TLS_DH_anon_WITH_AES_128_CBC_SHA is not available.  Please change the transport to be non-SSL or use non-anonymous SSL.
+execution_failed=Cursor execution failed
 
 PgBackendProtocol.ssl_error=Could not initialize ODBC SSL.  non-SSL connections will still be allowed.
\ No newline at end of file

Modified: trunk/test-integration/common/src/test/java/org/teiid/jdbc/TestLocalConnections.java
===================================================================
--- trunk/test-integration/common/src/test/java/org/teiid/jdbc/TestLocalConnections.java	2011-07-22 15:32:56 UTC (rev 3326)
+++ trunk/test-integration/common/src/test/java/org/teiid/jdbc/TestLocalConnections.java	2011-07-22 16:26:08 UTC (rev 3327)
@@ -26,24 +26,39 @@
 
 import java.lang.Thread.UncaughtExceptionHandler;
 import java.sql.Connection;
+import java.sql.ResultSet;
+import java.sql.SQLException;
 import java.sql.Statement;
-import java.util.LinkedHashMap;
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.Collection;
+import java.util.Collections;
+import java.util.HashMap;
+import java.util.List;
+import java.util.concurrent.Semaphore;
 import java.util.concurrent.TimeUnit;
 import java.util.concurrent.locks.Condition;
 import java.util.concurrent.locks.ReentrantLock;
 
-import org.jboss.netty.handler.timeout.TimeoutException;
 import org.junit.AfterClass;
 import org.junit.BeforeClass;
 import org.junit.Test;
 import org.teiid.core.types.DataTypeManager;
+import org.teiid.core.util.UnitTestUtil;
+import org.teiid.dqp.internal.datamgr.ConnectorManager;
+import org.teiid.dqp.internal.datamgr.ConnectorManagerRepository;
+import org.teiid.language.Command;
 import org.teiid.metadata.FunctionMethod;
 import org.teiid.metadata.FunctionParameter;
-import org.teiid.metadata.MetadataStore;
-import org.teiid.metadata.Schema;
+import org.teiid.metadata.RuntimeMetadata;
 import org.teiid.metadata.FunctionMethod.PushDown;
 import org.teiid.query.function.metadata.FunctionCategoryConstants;
-import org.teiid.query.metadata.TransformationMetadata.Resource;
+import org.teiid.translator.DataNotAvailableException;
+import org.teiid.translator.Execution;
+import org.teiid.translator.ExecutionContext;
+import org.teiid.translator.ExecutionFactory;
+import org.teiid.translator.ResultSetExecution;
+import org.teiid.translator.TranslatorException;
 
 @SuppressWarnings("nls")
 public class TestLocalConnections {
@@ -62,12 +77,14 @@
 	static Condition waiting = lock.newCondition();
 	static Condition wait = lock.newCondition();
 	
+	static Semaphore sourceCounter = new Semaphore(0);
+	
 	public static int blocking() throws InterruptedException {
 		lock.lock();
 		try {
 			waiting.signal();
 			if (!wait.await(2, TimeUnit.SECONDS)) {
-				throw new TimeoutException();
+				throw new RuntimeException();
 			}
 		} finally {
 			lock.unlock();
@@ -77,15 +94,75 @@
 
 	static FakeServer server = new FakeServer();
 	
-	@BeforeClass public static void oneTimeSetup() {
+	@SuppressWarnings("serial")
+	@BeforeClass public static void oneTimeSetup() throws Exception {
     	server.setUseCallingThread(true);
-    	MetadataStore ms = new MetadataStore();
-    	Schema s = new Schema();
-    	s.setName("test");
+    	server.setConnectorManagerRepository(new ConnectorManagerRepository() {
+    		@Override
+    		public ConnectorManager getConnectorManager(String connectorName) {
+    			return new ConnectorManager(connectorName, connectorName) {
+    				@Override
+    				protected ExecutionFactory<Object, Object> getExecutionFactory() {
+    					return new ExecutionFactory<Object, Object>() {
+    						@Override
+    						public Execution createExecution(Command command,
+    								ExecutionContext executionContext,
+    								RuntimeMetadata metadata, Object connection)
+    								throws TranslatorException {
+    						    return new ResultSetExecution() {
+    						    	
+    						    	boolean returnedRow = false;
+    						    	
+									@Override
+									public void execute() throws TranslatorException {
+										lock.lock();
+										try {
+											sourceCounter.release();
+											if (!wait.await(2, TimeUnit.SECONDS)) {
+												throw new RuntimeException();
+											}
+										} catch (InterruptedException e) {
+											throw new RuntimeException(e);
+										} finally {
+											lock.unlock();
+										}
+									}
+									
+									@Override
+									public void close() {
+										
+									}
+									
+									@Override
+									public void cancel() throws TranslatorException {
+										
+									}
+									
+									@Override
+									public List<?> next() throws TranslatorException, DataNotAvailableException {
+										if (returnedRow) {
+											return null;
+										}
+										returnedRow = true;
+										return new ArrayList<Object>(Collections.singleton(null));
+									}
+								};
+    						}
+    					};
+    				}
+    				
+    				@Override
+    				protected Object getConnectionFactory()
+    						throws TranslatorException {
+    					return null;
+    				}
+    			};
+    		}
+    	});
     	FunctionMethod function = new FunctionMethod("foo", null, FunctionCategoryConstants.MISCELLANEOUS, PushDown.CANNOT_PUSHDOWN, TestLocalConnections.class.getName(), "blocking", new FunctionParameter[0], new FunctionParameter("result", DataTypeManager.DefaultDataTypes.INTEGER), true, FunctionMethod.Determinism.NONDETERMINISTIC);
-    	s.addFunction(function);
-    	ms.addSchema(s);
-    	server.deployVDB("test", ms, new LinkedHashMap<String, Resource>());
+    	HashMap<String, Collection<FunctionMethod>> udfs = new HashMap<String, Collection<FunctionMethod>>();
+    	udfs.put("test", Arrays.asList(function));
+    	server.deployVDB("test", UnitTestUtil.getTestDataPath() + "/PartsSupplier.vdb", udfs);
 	}
 	
 	@AfterClass public static void oneTimeTearDown() {
@@ -102,6 +179,7 @@
 	    	    	
 	    	    	Statement s = c.createStatement();
 	    	    	s.execute("select foo()");
+	    	    	s.close();
     			} catch (Exception e) {
     				throw new RuntimeException(e);
     			}
@@ -131,9 +209,129 @@
     	if (t.isAlive()) {
     		fail();
     	}
+    	s.close();
     	if (handler.t != null) {
     		throw handler.t;
     	}
 	}
 	
+	@Test public void testUseInDifferentThreads() throws Throwable {
+		Connection c = server.createConnection("jdbc:teiid:test");
+    	
+    	final Statement s = c.createStatement();
+    	s.execute("select 1");
+    	
+    	assertFalse(server.dqp.getRequests().isEmpty());
+
+    	Thread t = new Thread() {
+    		public void run() {
+    			try {
+					s.close();
+				} catch (SQLException e) {
+					throw new RuntimeException(e);
+				}
+    		}
+    	};
+    	SimpleUncaughtExceptionHandler handler = new SimpleUncaughtExceptionHandler();
+    	t.setUncaughtExceptionHandler(handler);
+    	t.start();
+    	t.join(2000);
+    	if (t.isAlive()) {
+    		fail();
+    	}
+    	
+    	assertTrue(server.dqp.getRequests().isEmpty());
+    	
+    	if (handler.t != null) {
+    		throw handler.t;
+    	}
+	}
+	
+	@Test public void testWait() throws Throwable {
+		final Connection c = server.createConnection("jdbc:teiid:test");
+    	
+		Thread t = new Thread() {
+			public void run() {
+		    	Statement s;
+				try {
+					s = c.createStatement();
+			    	assertTrue(s.execute("select part_id from parts"));
+				} catch (SQLException e) {
+					throw new RuntimeException(e);
+				}
+			}
+		};
+    	t.start();
+    	SimpleUncaughtExceptionHandler handler = new SimpleUncaughtExceptionHandler();
+    	t.setUncaughtExceptionHandler(handler);
+    	
+    	sourceCounter.acquire();
+    	
+    	//t should now be waiting also
+    	
+    	lock.lock();
+    	try {
+    		wait.signal();
+    	} finally {
+    		lock.unlock();
+    	}
+
+    	//t should finish
+    	t.join();
+    	
+    	if (handler.t != null) {
+    		throw handler.t;
+    	}
+	}
+	
+	@Test public void testWaitMultiple() throws Throwable {
+		final Connection c = server.createConnection("jdbc:teiid:test");
+    	
+		Thread t = new Thread() {
+			public void run() {
+		    	Statement s;
+				try {
+					s = c.createStatement();
+			    	assertTrue(s.execute("select part_id from parts union all select part_id from parts"));
+			    	ResultSet r = s.getResultSet();
+			    	
+			    	//wake up the other source thread, should put the requestworkitem into the more work state 
+			    	lock.lock();
+			    	try {
+			    		wait.signal();
+			    	} finally {
+			    		lock.unlock();
+			    	}
+			    	Thread.sleep(1000); //TODO: need a better hook to determine that connector work has finished
+			    	while (r.next()) {
+			    		//will hang unless this thread is allowed to resume processing
+			    	}
+				} catch (Exception e) {
+					throw new RuntimeException(e);
+				}
+			}
+		};
+    	t.start();
+    	SimpleUncaughtExceptionHandler handler = new SimpleUncaughtExceptionHandler();
+    	t.setUncaughtExceptionHandler(handler);
+    	
+    	sourceCounter.acquire(2);
+    	
+    	//t should now be waiting also
+    	
+    	//wake up 1 source thread
+    	lock.lock();
+    	try {
+    		wait.signal();
+    	} finally {
+    		lock.unlock();
+    	}
+    	
+    	t.join();
+    	
+    	if (handler.t != null) {
+    		throw handler.t;
+    	}
+	}
+	
 }

Modified: trunk/test-integration/common/src/test/java/org/teiid/jdbc/TestMMDatabaseMetaData.java
===================================================================
--- trunk/test-integration/common/src/test/java/org/teiid/jdbc/TestMMDatabaseMetaData.java	2011-07-22 15:32:56 UTC (rev 3326)
+++ trunk/test-integration/common/src/test/java/org/teiid/jdbc/TestMMDatabaseMetaData.java	2011-07-22 16:26:08 UTC (rev 3327)
@@ -615,6 +615,12 @@
         ResultSet rs = dbmd.getTables(null, "SYSTEM", "VIRTUALDATABASES", null); //$NON-NLS-1$ //$NON-NLS-2$
         compareResultSet(rs);
     }
+    
+    @Test
+    public void testGetTables_noTypes() throws Exception {
+        ResultSet rs = dbmd.getTables(null, "SYSTEM", "VIRTUALDATABASES", new String[0]); //$NON-NLS-1$ //$NON-NLS-2$
+        assertFalse(rs.next());
+    }
 
     @Test
     public void testGetTables_specificTableTypes() throws Exception {

Modified: trunk/test-integration/common/src/test/java/org/teiid/transport/TestODBCSocketTransport.java
===================================================================
--- trunk/test-integration/common/src/test/java/org/teiid/transport/TestODBCSocketTransport.java	2011-07-22 15:32:56 UTC (rev 3326)
+++ trunk/test-integration/common/src/test/java/org/teiid/transport/TestODBCSocketTransport.java	2011-07-22 16:26:08 UTC (rev 3327)
@@ -222,6 +222,12 @@
 		TestMMDatabaseMetaData.compareResultSet(rs);
 	}	
 	
+	@Test public void testColumnMetadataWithAlias() throws Exception {
+		PreparedStatement stmt = conn.prepareStatement("select ta.attname as x from pg_catalog.pg_attribute ta limit 1");
+		ResultSet rs = stmt.executeQuery();
+		TestMMDatabaseMetaData.compareResultSet(rs);
+	}	
+	
 	@Test public void testPreparedError() throws Exception {
 		PreparedStatement stmt = conn.prepareStatement("select cast(? as integer)");
 		stmt.setString(1, "a");
@@ -255,6 +261,13 @@
 		assertEquals("oid", rs.getArray("proargtypes").getBaseTypeName());
 	}
 	
+	// this does not work as JDBC always sends the queries in prepared form
+	public void testPgDeclareCursor() throws Exception {
+		Statement stmt = conn.createStatement();
+		ResultSet rs = stmt.executeQuery("begin;declare \"foo\" cursor for select * from pg_proc;fetch 10 in \"foo\"; close \"foo\"");
+		rs.next();		
+	}	
+	
 	@Test public void testPgProcedure() throws Exception {
 		Statement stmt = conn.createStatement();
 		ResultSet rs = stmt.executeQuery("select has_function_privilege(100, 'foo')");


Property changes on: trunk/test-integration/common/src/test/java/org/teiid/transport/TestODBCSocketTransport.java
___________________________________________________________________
Modified: svn:mergeinfo
   - /branches/7.4.x/test-integration/common/src/test/java/org/teiid/transport/TestODBCSocketTransport.java:3149-3217
   + /branches/7.4.x/test-integration/common/src/test/java/org/teiid/transport/TestODBCSocketTransport.java:3149-3217,3281-3325

Added: trunk/test-integration/common/src/test/resources/TestODBCSocketTransport/testColumnMetadataWithAlias.expected
===================================================================
--- trunk/test-integration/common/src/test/resources/TestODBCSocketTransport/testColumnMetadataWithAlias.expected	                        (rev 0)
+++ trunk/test-integration/common/src/test/resources/TestODBCSocketTransport/testColumnMetadataWithAlias.expected	2011-07-22 16:26:08 UTC (rev 3327)
@@ -0,0 +1,6 @@
+varchar                                                          
+x                                                                
+PART_ID                                                          
+Row Count : 1
+getColumnName  getColumnType  getCatalogName  getColumnClassName  getColumnLabel  getColumnTypeName  getSchemaName  getTableName  getColumnDisplaySize  getPrecision  getScale  isAutoIncrement  isCaseSensitive  isCurrency  isDefinitelyWritable  isNullable  isReadOnly  isSearchable  isSigned  isWritable  
+x              12                             java.lang.String    x               varchar                                         2147483647            0             0         false            true             false       false                 1           false       true          false     true        

Modified: trunk/test-integration/common/src/test/resources/TestODBCSocketTransport/testPk.expected
===================================================================
--- trunk/test-integration/common/src/test/resources/TestODBCSocketTransport/testPk.expected	2011-07-22 15:32:56 UTC (rev 3326)
+++ trunk/test-integration/common/src/test/resources/TestODBCSocketTransport/testPk.expected	2011-07-22 16:26:08 UTC (rev 3327)
@@ -1,10 +1,10 @@
 varchar                                                            int2    varchar                                                            varchar                                                            varchar                                                          
-name                                                               attnum  tablename                                                          schemaname                                                         tablename                                                        
+attname                                                            attnum  relname                                                            nspname                                                            relname                                                          
 oid                                                                1       pg_attribute                                                       pg_catalog                                                         pg_attribute                                                     
 Row Count : 1
 getColumnName  getColumnType  getCatalogName  getColumnClassName  getColumnLabel  getColumnTypeName  getSchemaName  getTableName  getColumnDisplaySize  getPrecision  getScale  isAutoIncrement  isCaseSensitive  isCurrency  isDefinitelyWritable  isNullable  isReadOnly  isSearchable  isSigned  isWritable  
-name           12                             java.lang.String    name            varchar                                         2147483647            0             0         false            true             false       false                 0           false       true          false     true        
+attname        12                             java.lang.String    attname         varchar                                         2147483647            0             0         false            true             false       false                 0           false       true          false     true        
 attnum         5                              java.lang.Integer   attnum          int2                                            6                     5             0         false            false            false       false                 2           false       true          true      true        
-tablename      12                             java.lang.String    tablename       varchar                                         2147483647            0             0         false            true             false       false                 0           false       true          false     true        
-schemaname     12                             java.lang.String    schemaname      varchar                                         2147483647            0             0         false            true             false       false                 1           false       true          false     true        
-tablename      12                             java.lang.String    tablename       varchar                                         2147483647            0             0         false            true             false       false                 0           false       true          false     true        
+relname        12                             java.lang.String    relname         varchar                                         2147483647            0             0         false            true             false       false                 0           false       true          false     true        
+nspname        12                             java.lang.String    nspname         varchar                                         2147483647            0             0         false            true             false       false                 1           false       true          false     true        
+relname        12                             java.lang.String    relname         varchar                                         2147483647            0             0         false            true             false       false                 0           false       true          false     true        


Property changes on: trunk/test-integration/common/src/test/resources/TestODBCSocketTransport/testPk.expected
___________________________________________________________________
Added: svn:mergeinfo
   + /branches/7.4.x/test-integration/common/src/test/resources/TestODBCSocketTransport/testPk.expected:3281-3325

Modified: trunk/test-integration/common/src/test/resources/TestODBCSocketTransport/testPkPrepared.expected
===================================================================
--- trunk/test-integration/common/src/test/resources/TestODBCSocketTransport/testPkPrepared.expected	2011-07-22 15:32:56 UTC (rev 3326)
+++ trunk/test-integration/common/src/test/resources/TestODBCSocketTransport/testPkPrepared.expected	2011-07-22 16:26:08 UTC (rev 3327)
@@ -1,10 +1,10 @@
 varchar                                                            int2    varchar                                                            varchar                                                            varchar                                                          
-name                                                               attnum  tablename                                                          schemaname                                                         tablename                                                        
+attname                                                            attnum  relname                                                            nspname                                                            relname                                                          
 oid                                                                1       pg_attribute                                                       pg_catalog                                                         pg_attribute                                                     
 Row Count : 1
 getColumnName  getColumnType  getCatalogName  getColumnClassName  getColumnLabel  getColumnTypeName  getSchemaName  getTableName  getColumnDisplaySize  getPrecision  getScale  isAutoIncrement  isCaseSensitive  isCurrency  isDefinitelyWritable  isNullable  isReadOnly  isSearchable  isSigned  isWritable  
-name           12                             java.lang.String    name            varchar                                         2147483647            0             0         false            true             false       false                 0           false       true          false     true        
+attname        12                             java.lang.String    attname         varchar                                         2147483647            0             0         false            true             false       false                 0           false       true          false     true        
 attnum         5                              java.lang.Integer   attnum          int2                                            6                     5             0         false            false            false       false                 2           false       true          true      true        
-tablename      12                             java.lang.String    tablename       varchar                                         2147483647            0             0         false            true             false       false                 0           false       true          false     true        
-schemaname     12                             java.lang.String    schemaname      varchar                                         2147483647            0             0         false            true             false       false                 1           false       true          false     true        
-tablename      12                             java.lang.String    tablename       varchar                                         2147483647            0             0         false            true             false       false                 0           false       true          false     true        
+relname        12                             java.lang.String    relname         varchar                                         2147483647            0             0         false            true             false       false                 0           false       true          false     true        
+nspname        12                             java.lang.String    nspname         varchar                                         2147483647            0             0         false            true             false       false                 1           false       true          false     true        
+relname        12                             java.lang.String    relname         varchar                                         2147483647            0             0         false            true             false       false                 0           false       true          false     true        


Property changes on: trunk/test-integration/common/src/test/resources/TestODBCSocketTransport/testPkPrepared.expected
___________________________________________________________________
Added: svn:mergeinfo
   + /branches/7.4.x/test-integration/common/src/test/resources/TestODBCSocketTransport/testPkPrepared.expected:3281-3325



More information about the teiid-commits mailing list