[teiid-commits] teiid SVN: r4634 - in branches/7.7.x: test-integration/common/src/test/java/org/teiid/transport and 1 other directory.

teiid-commits at lists.jboss.org teiid-commits at lists.jboss.org
Wed Apr 23 13:49:00 EDT 2014


Author: jolee
Date: 2014-04-23 13:48:59 -0400 (Wed, 23 Apr 2014)
New Revision: 4634

Modified:
   branches/7.7.x/runtime/src/main/java/org/teiid/odbc/ODBCServerRemoteImpl.java
   branches/7.7.x/test-integration/common/src/test/java/org/teiid/transport/TestODBCSocketTransport.java
Log:
TEIID-2930: SCROLL keyword for DECLARE CURSOR not being parsed correctly

Modified: branches/7.7.x/runtime/src/main/java/org/teiid/odbc/ODBCServerRemoteImpl.java
===================================================================
--- branches/7.7.x/runtime/src/main/java/org/teiid/odbc/ODBCServerRemoteImpl.java	2014-04-22 14:11:47 UTC (rev 4633)
+++ branches/7.7.x/runtime/src/main/java/org/teiid/odbc/ODBCServerRemoteImpl.java	2014-04-23 17:48:59 UTC (rev 4634)
@@ -149,8 +149,8 @@
 		
 	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.DOTALL|Pattern.CASE_INSENSITIVE); //$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 cursorSelectPattern = Pattern.compile("DECLARE\\s+\"(\\w+)\"(?:\\s+INSENSITIVE)?(\\s+(NO\\s+)?SCROLL)?\\s+CURSOR\\s+FOR\\s+(.*)", Pattern.CASE_INSENSITIVE|Pattern.DOTALL); //$NON-NLS-1$
 	private static Pattern fetchPattern = Pattern.compile("FETCH (\\d+) IN \"(\\w+)\".*", Pattern.DOTALL|Pattern.CASE_INSENSITIVE); //$NON-NLS-1$
 	private static Pattern movePattern = Pattern.compile("MOVE (\\d+) IN \"(\\w+)\".*", Pattern.DOTALL|Pattern.CASE_INSENSITIVE); //$NON-NLS-1$
 	private static Pattern closePattern = Pattern.compile("CLOSE \"(\\w+)\"", Pattern.DOTALL|Pattern.CASE_INSENSITIVE); //$NON-NLS-1$
@@ -250,38 +250,46 @@
 		}
 	}	
 	
-	private void cursorExecute(final String cursorName, final String sql, final ResultsFuture<Integer> completion) {
-		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(ResultsMode.RESULTSET);
-                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", null); //$NON-NLS-1$		                            
-	    						completion.getResultsReceiver().receiveResults(0);
-                        	}
-    					} catch (Throwable e) {
-    						completion.getResultsReceiver().exceptionOccurred(e);
-    					}
-	        		}
-				});					
-			} catch (SQLException e) {
-				completion.getResultsReceiver().exceptionOccurred(e);
-			} 
-		}
+	private void cursorExecute(String cursorName, final String sql, final ResultsFuture<Integer> completion, boolean scroll) {
+		try {
+			// close if the name is already used or the unnamed prepare; otherwise
+			// stmt is alive until session ends.
+			this.preparedMap.remove(UNNAMED);
+			Portal p = this.portalMap.remove(UNNAMED);
+			if (p != null) {
+				closePortal(p);
+			}
+			if (cursorName == null || cursorName.length() == 0) {
+				cursorName = UNNAMED;
+			}
+			Cursor cursor = cursorMap.get(cursorName);
+			if (cursor != null) {
+				errorOccurred("Cannot use the portal name " + cursorName + " until the exiting instance is closed.");
+				return;
+			}
+			
+			final PreparedStatementImpl stmt = this.connection.prepareStatement(sql, scroll?ResultSet.TYPE_SCROLL_INSENSITIVE:ResultSet.TYPE_FORWARD_ONLY, ResultSet.CONCUR_READ_ONLY);
+            this.executionFuture = stmt.submitExecute(ResultsMode.RESULTSET);
+            final String name = cursorName;
+            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(name, new Cursor(name, sql, stmt, null, stmt.getResultSet(), cols));
+    						client.sendCommandComplete("DECLARE CURSOR", null); //$NON-NLS-1$		                            
+							completion.getResultsReceiver().receiveResults(0);
+						}
+					} catch (Throwable e) {
+						completion.getResultsReceiver().exceptionOccurred(e);
+					}
+        		}
+			});					
+		} catch (SQLException e) {
+			completion.getResultsReceiver().exceptionOccurred(e);
+		} 
 	}
 	
 	private void cursorFetch(String cursorName, int rows, final ResultsFuture<Integer> completion) throws SQLException {
@@ -788,6 +796,23 @@
 			}
 		}
 	}
+	
+	private void closePortal(Portal query) {
+		ResultSet rs = query.rs;
+		if (rs != null) {
+			try {
+				rs.close();
+			} catch (SQLException e) {
+				LogManager.logDetail(LogConstants.CTX_ODBC, e, "Did not successfully close portal", query.name); //$NON-NLS-1$
+			}
+			query.rs = null;
+		}
+		try {
+			query.stmt.close();
+		} catch (SQLException e) {
+			LogManager.logDetail(LogConstants.CTX_ODBC, e, "Did not successfully close portal", query.name); //$NON-NLS-1$
+		}
+	}
 
 	@Override
 	public void closePreparedStatement(String preparedName) {
@@ -930,7 +955,11 @@
 		    			
 		            	Matcher m = null;
 		    	        if ((m = cursorSelectPattern.matcher(sql)).matches()){
-		    				cursorExecute(m.group(1), fixSQL(m.group(4)), results);
+		    	        	boolean scroll = false;
+		    	        	if (m.group(2) != null && m.group(3) == null ) {
+	    	        			scroll = true;
+		    	        	}
+		    				cursorExecute(m.group(1), fixSQL(m.group(4)), results, scroll);
 		    			}
 		    			else if ((m = fetchPattern.matcher(sql)).matches()){
 		    				cursorFetch(m.group(2), Integer.parseInt(m.group(1)), results);
@@ -1064,6 +1093,8 @@
          * The format used in the result set columns (if set).
          */
         int[] resultColumnFormat;
+        
+        volatile ResultSetImpl rs;
 
         /**
          * The prepared statement.

Modified: branches/7.7.x/test-integration/common/src/test/java/org/teiid/transport/TestODBCSocketTransport.java
===================================================================
--- branches/7.7.x/test-integration/common/src/test/java/org/teiid/transport/TestODBCSocketTransport.java	2014-04-22 14:11:47 UTC (rev 4633)
+++ branches/7.7.x/test-integration/common/src/test/java/org/teiid/transport/TestODBCSocketTransport.java	2014-04-23 17:48:59 UTC (rev 4634)
@@ -50,6 +50,7 @@
 import org.mockito.Mockito;
 import org.postgresql.Driver;
 import org.teiid.client.security.ILogon;
+import org.postgresql.core.v3.ExtendedQueryExectutorImpl;
 import org.teiid.common.buffer.BufferManagerFactory;
 import org.teiid.core.util.UnitTestUtil;
 import org.teiid.jdbc.FakeServer;
@@ -318,6 +319,26 @@
 		rs.next();		
 	}	
 	
+	@Test public void testScrollCursor() throws Exception {
+		Statement stmt = conn.createStatement();
+		ExtendedQueryExectutorImpl.simplePortal = "foo";
+		try {
+			assertFalse(stmt.execute("declare \"foo\" insensitive scroll cursor for select * from pg_proc;"));
+			assertFalse(stmt.execute("move 5 in \"foo\""));
+			stmt.execute("fetch 10 in \"foo\"");
+			ResultSet rs = stmt.getResultSet();
+			int rowCount = 0;
+			while (rs.next()) {
+				rowCount++;
+			}
+			assertEquals(6, rowCount);
+			stmt.execute("close \"foo\"");
+		} finally {
+			ExtendedQueryExectutorImpl.simplePortal = null;
+		}
+		
+	}
+	
 	@Test public void testPgProcedure() throws Exception {
 		Statement stmt = conn.createStatement();
 		ResultSet rs = stmt.executeQuery("select has_function_privilege(100, 'foo')");



More information about the teiid-commits mailing list