[teiid-commits] teiid SVN: r2904 - in trunk: common-core/src/main/java/org/teiid/core/util and 5 other directories.

teiid-commits at lists.jboss.org teiid-commits at lists.jboss.org
Sun Feb 13 20:30:07 EST 2011


Author: rareddy
Date: 2011-02-13 20:30:06 -0500 (Sun, 13 Feb 2011)
New Revision: 2904

Modified:
   trunk/build/kits/jboss-container/deploy/teiid/teiid-jboss-beans.xml
   trunk/common-core/src/main/java/org/teiid/core/util/ObjectConverterUtil.java
   trunk/engine/src/main/java/org/teiid/dqp/internal/process/DQPConfiguration.java
   trunk/jboss-integration/src/main/java/org/teiid/jboss/deployers/RuntimeEngineDeployer.java
   trunk/runtime/src/main/java/org/teiid/odbc/ODBCClientRemote.java
   trunk/runtime/src/main/java/org/teiid/odbc/ODBCServerRemote.java
   trunk/runtime/src/main/java/org/teiid/odbc/ODBCServerRemoteImpl.java
   trunk/runtime/src/main/java/org/teiid/transport/ODBCSocketListener.java
   trunk/runtime/src/main/java/org/teiid/transport/PgBackendProtocol.java
   trunk/runtime/src/main/java/org/teiid/transport/PgFrontendProtocol.java
   trunk/runtime/src/main/resources/org/teiid/runtime/i18n.properties
Log:
TEIID-1163: Adding lob support for ODBC using postges 'bytea' data type. This data type does not support streaming.

Modified: trunk/build/kits/jboss-container/deploy/teiid/teiid-jboss-beans.xml
===================================================================
--- trunk/build/kits/jboss-container/deploy/teiid/teiid-jboss-beans.xml	2011-02-10 19:56:37 UTC (rev 2903)
+++ trunk/build/kits/jboss-container/deploy/teiid/teiid-jboss-beans.xml	2011-02-14 01:30:06 UTC (rev 2904)
@@ -110,6 +110,8 @@
         <property name="maxSourceRows">-1</property>
 		<!-- Indicates if an exception should be thrown if the specified value for Maximum Source Rows is exceeded; only up to the maximum rows will be consumed. -->        
         <property name="exceptionOnMaxSourceRows">true</property>
+        <!-- Maximum size of lob allowed through ODBC connection in bytes (default 5MB) -->
+        <property name="maxODBCLobSizeAllowed">5242880</property>
     </bean>
 
     <!-- JDBC Socket connection properties (SSL see below) -->

Modified: trunk/common-core/src/main/java/org/teiid/core/util/ObjectConverterUtil.java
===================================================================
--- trunk/common-core/src/main/java/org/teiid/core/util/ObjectConverterUtil.java	2011-02-10 19:56:37 UTC (rev 2903)
+++ trunk/common-core/src/main/java/org/teiid/core/util/ObjectConverterUtil.java	2011-02-14 01:30:06 UTC (rev 2904)
@@ -90,16 +90,32 @@
      * @throws IOException if a problem occurred reading the stream.
      */
     public static byte[] convertToByteArray(final InputStream is, int length) throws IOException {
+    	return convertToByteArray(is, length, true);
+    }
+    
+    public static byte[] convertToByteArray(final InputStream is, int length, boolean close) throws IOException {
         ByteArrayOutputStream out = new ByteArrayOutputStream();
-        write(out, is, length);
-        return out.toByteArray();
+        write(out, is, length, close);
+        out.close();
+        return out.toByteArray();    	
     }
+
+    public static int write(final OutputStream out, final InputStream is, byte[] l_buffer, int length) throws IOException {
+        return write(out, is, l_buffer, length, true);
+    }
     
-    public static int write(final OutputStream out, final InputStream is, byte[] l_buffer, int length) throws IOException {
+    public static int write(final OutputStream out, final InputStream is, byte[] l_buffer, int length, boolean close) throws IOException {
     	int writen = 0;
         try {
 	        int l_nbytes = 0;  // Number of bytes read
-	        while ((l_nbytes = is.read(l_buffer)) != -1) {
+	        int readLength = length;
+	        if (length == -1) {
+	        	readLength = l_buffer.length;
+	        }
+	        else {
+	        	readLength = Math.min(length, l_buffer.length);
+	        }
+	        while ((l_nbytes = is.read(l_buffer, 0, readLength)) != -1) {
 	        	if (length != -1 && writen > length - l_nbytes) {
 		        	out.write(l_buffer, 0, writen + l_nbytes - length); 
 		        	break;
@@ -109,16 +125,22 @@
 	        }
 	        return writen;
         } finally {
-        	try {
-        		is.close();
-        	} finally {
-        		out.close();
+        	if (close) {
+	        	try {
+	       			is.close();
+	        	} finally {
+	        		out.close();
+	        	}
         	}
         }
     }
+
+    public static int write(final OutputStream out, final InputStream is, int length) throws IOException {
+       return write(out, is, length, true);    	
+    }    
     
-    public static void write(final OutputStream out, final InputStream is, int length) throws IOException {
-    	write(out, is, new byte[DEFAULT_READING_SIZE], length); // buffer holding bytes to be transferred
+    public static int write(final OutputStream out, final InputStream is, int length, boolean close) throws IOException {
+    	return write(out, is, new byte[DEFAULT_READING_SIZE], length, close); // buffer holding bytes to be transferred
     }
     
     public static void write(final Writer out, final Reader is, int length) throws IOException {

Modified: trunk/engine/src/main/java/org/teiid/dqp/internal/process/DQPConfiguration.java
===================================================================
--- trunk/engine/src/main/java/org/teiid/dqp/internal/process/DQPConfiguration.java	2011-02-10 19:56:37 UTC (rev 2903)
+++ trunk/engine/src/main/java/org/teiid/dqp/internal/process/DQPConfiguration.java	2011-02-14 01:30:06 UTC (rev 2904)
@@ -51,6 +51,7 @@
 	private int maxSourceRows = -1;
 	private int maxActivePlans = DEFAULT_MAX_ACTIVE_PLANS;
 	private CacheConfiguration resultsetCacheConfig;
+	private int maxODBCLobSizeAllowed = 5*1024*1024; // 5 MB
 
 	@ManagementProperty(description="Max active plans (default 20).  Increase this value, and max threads, on highly concurrent systems - but ensure that the underlying pools can handle the increased load without timeouts.")
 	public int getMaxActivePlans() {
@@ -185,4 +186,13 @@
 	public void setMaxSourceRows(int maxSourceRows) {
 		this.maxSourceRows = maxSourceRows;
 	}
+	
+	@ManagementProperty(description="Maximum Lob Size allowed over ODBC (default 5MB)")
+	public int getMaxODBCLobSizeAllowed() {
+		return this.maxODBCLobSizeAllowed;
+	}
+	
+	public void setMaxODBCLobSizeAllowed(int lobSize) {
+		this.maxODBCLobSizeAllowed = lobSize;
+	}
 }

Modified: trunk/jboss-integration/src/main/java/org/teiid/jboss/deployers/RuntimeEngineDeployer.java
===================================================================
--- trunk/jboss-integration/src/main/java/org/teiid/jboss/deployers/RuntimeEngineDeployer.java	2011-02-10 19:56:37 UTC (rev 2903)
+++ trunk/jboss-integration/src/main/java/org/teiid/jboss/deployers/RuntimeEngineDeployer.java	2011-02-14 01:30:06 UTC (rev 2904)
@@ -192,7 +192,7 @@
     	
     	if (this.odbcSocketConfiguration.getEnabled()) {
     		this.vdbRepository.odbcEnabled();
-	    	this.odbcSocket = new ODBCSocketListener(this.odbcSocketConfiguration, this.dqpCore.getBufferManager(), offset);
+	    	this.odbcSocket = new ODBCSocketListener(this.odbcSocketConfiguration, this.dqpCore.getBufferManager(), offset, getMaxODBCLobSizeAllowed());
 	    	LogManager.logInfo(LogConstants.CTX_RUNTIME, IntegrationPlugin.Util.getString("odbc_enabled","Teiid ODBC - SSL=", (this.odbcSocketConfiguration.getSSLConfiguration().isSslEnabled()?"ON":"OFF")+" Host = "+this.odbcSocketConfiguration.getHostAddress().getHostName()+" Port = "+(this.odbcSocketConfiguration.getPortNumber()+offset))); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$ //$NON-NLS-4$ //$NON-NLS-5$ //$NON-NLS-6$
     	} else {
     		LogManager.logInfo(LogConstants.CTX_RUNTIME, IntegrationPlugin.Util.getString("odbc_not_enabled")); //$NON-NLS-1$

Modified: trunk/runtime/src/main/java/org/teiid/odbc/ODBCClientRemote.java
===================================================================
--- trunk/runtime/src/main/java/org/teiid/odbc/ODBCClientRemote.java	2011-02-10 19:56:37 UTC (rev 2903)
+++ trunk/runtime/src/main/java/org/teiid/odbc/ODBCClientRemote.java	2011-02-14 01:30:06 UTC (rev 2904)
@@ -79,6 +79,12 @@
 
 	void flush();
 	
+	// FunctionCallResponse (B)
+	void functionCallResponse(byte[] data);
+	void functionCallResponse(int data);
+	
+	void sslDenied();
+	
 	// unimplemented backend messages
 	
 	//	AuthenticationKerberosV5 (B)
@@ -95,8 +101,6 @@
 	//	CopyInResponse (B)
 	//	CopyOutResponse (B)
 	
-	//	FunctionCallResponse (B)
-	
 	//	NoticeResponse (B)
 	//	NotificationResponse (B)
 	

Modified: trunk/runtime/src/main/java/org/teiid/odbc/ODBCServerRemote.java
===================================================================
--- trunk/runtime/src/main/java/org/teiid/odbc/ODBCServerRemote.java	2011-02-10 19:56:37 UTC (rev 2903)
+++ trunk/runtime/src/main/java/org/teiid/odbc/ODBCServerRemote.java	2011-02-14 01:30:06 UTC (rev 2904)
@@ -56,13 +56,14 @@
 
 	void flush();
 
+	void functionCall(int oid);
+	
+	void sslRequest();
+	
 	//  unimplemented frontend messages
 	//	CopyData (F & B)
 	//	CopyDone (F & B)
 	//	CopyFail (F)
-	//	Flush (F)
-	//	FunctionCall (F)
-	//	SSLRequest (F)
 }
 
 

Modified: trunk/runtime/src/main/java/org/teiid/odbc/ODBCServerRemoteImpl.java
===================================================================
--- trunk/runtime/src/main/java/org/teiid/odbc/ODBCServerRemoteImpl.java	2011-02-10 19:56:37 UTC (rev 2903)
+++ trunk/runtime/src/main/java/org/teiid/odbc/ODBCServerRemoteImpl.java	2011-02-14 01:30:06 UTC (rev 2904)
@@ -571,7 +571,18 @@
 	public void flush() {
 		this.client.flush();
 	}
-
+	
+	@Override
+	public void functionCall(int oid) {
+		this.client.errorOccurred(RuntimePlugin.Util.getString("lo_not_supported")); //$NON-NLS-1$
+		sync();
+	}
+	
+	@Override
+	public void sslRequest() {
+		this.client.sslDenied();
+	}
+	
     /**
      * Represents a PostgreSQL Prepared object.
      */

Modified: trunk/runtime/src/main/java/org/teiid/transport/ODBCSocketListener.java
===================================================================
--- trunk/runtime/src/main/java/org/teiid/transport/ODBCSocketListener.java	2011-02-10 19:56:37 UTC (rev 2903)
+++ trunk/runtime/src/main/java/org/teiid/transport/ODBCSocketListener.java	2011-02-14 01:30:06 UTC (rev 2904)
@@ -32,10 +32,12 @@
 
 public class ODBCSocketListener extends SocketListener {
 	private ODBCServerRemote.AuthenticationType authType = ODBCServerRemote.AuthenticationType.CLEARTEXT;
+	private int maxLobSize;
 	
-	public ODBCSocketListener(SocketConfiguration config, StorageManager storageManager, int portOffset) {
+	public ODBCSocketListener(SocketConfiguration config, StorageManager storageManager, int portOffset, int maxLobSize) {
 		//the clientserviceregistry isn't actually used by ODBC 
 		super(config, new ClientServiceRegistryImpl(ClientServiceRegistry.Type.ODBC), storageManager, portOffset);
+		this.maxLobSize = maxLobSize;
 	}
 
 	@Override
@@ -49,7 +51,7 @@
 			        pipeline.addLast("ssl", new SslHandler(engine)); //$NON-NLS-1$
 			    }
 			    pipeline.addLast("odbcFrontendProtocol", new PgFrontendProtocol(1 << 20)); //$NON-NLS-1$
-			    pipeline.addLast("odbcBackendProtocol", new PgBackendProtocol()); //$NON-NLS-1$
+			    pipeline.addLast("odbcBackendProtocol", new PgBackendProtocol(maxLobSize)); //$NON-NLS-1$
 			    pipeline.addLast("handler", this); //$NON-NLS-1$
 			    return pipeline;
 			}			

Modified: trunk/runtime/src/main/java/org/teiid/transport/PgBackendProtocol.java
===================================================================
--- trunk/runtime/src/main/java/org/teiid/transport/PgBackendProtocol.java	2011-02-10 19:56:37 UTC (rev 2903)
+++ trunk/runtime/src/main/java/org/teiid/transport/PgBackendProtocol.java	2011-02-14 01:30:06 UTC (rev 2904)
@@ -27,10 +27,13 @@
 import java.lang.reflect.InvocationTargetException;
 import java.lang.reflect.Method;
 import java.nio.charset.Charset;
+import java.sql.Blob;
+import java.sql.Clob;
 import java.sql.ParameterMetaData;
 import java.sql.ResultSet;
 import java.sql.ResultSetMetaData;
 import java.sql.SQLException;
+import java.sql.SQLXML;
 import java.sql.Types;
 import java.util.Properties;
 
@@ -41,6 +44,8 @@
 import org.jboss.netty.channel.ChannelHandlerContext;
 import org.jboss.netty.channel.Channels;
 import org.jboss.netty.channel.MessageEvent;
+import org.teiid.core.util.ObjectConverterUtil;
+import org.teiid.core.util.ReaderInputStream;
 import org.teiid.core.util.ReflectionHelper;
 import org.teiid.jdbc.TeiidSQLException;
 import org.teiid.logging.LogConstants;
@@ -64,15 +69,16 @@
     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_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_TEXTARRAY = 1009;
+    //private static final int PG_TYPE_TEXTARRAY = 1009;
     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;
@@ -82,7 +88,12 @@
     private ReflectionHelper clientProxy = new ReflectionHelper(ODBCClientRemote.class);
     private ChannelHandlerContext ctx;
     private MessageEvent message;
+    private int maxLobSize = (2*1024*1024); // 2 MB
     
+    public PgBackendProtocol(int maxLobSize) {
+    	this.maxLobSize = maxLobSize;
+    }
+    
 	@Override
 	public void handleDownstream(ChannelHandlerContext ctx, ChannelEvent evt) throws Exception {
         if (!(evt instanceof MessageEvent)) {
@@ -210,7 +221,7 @@
 					if (paramType != null && paramType[i] != 0) {
 						type = paramType[i];
 					} else {
-						type = PG_TYPE_VARCHAR;
+						type = convertType(meta.getParameterType(i+1));
 					}
 					writeInt(type);
 				}
@@ -244,8 +255,13 @@
             		ResultSetMetaData meta = rs.getMetaData();
             		sendRowDescription(meta);
             	}
+            	int columns = rs.getMetaData().getColumnCount();
+            	int[] types = new int[columns];
+            	for(int i = 0; i < columns; i++) {
+            		types[i] = rs.getMetaData().getColumnType(i+1);
+            	}
                 while (rs.next()) {
-                    sendDataRow(rs);
+                    sendDataRow(rs, columns, types);
                 }
                 sendCommandComplete(sql, 0);
 			} catch (SQLException e) {
@@ -331,27 +347,81 @@
 		sendMessage();
 	}
 
-	private void sendDataRow(ResultSet rs) throws SQLException, IOException {
-		int columns = rs.getMetaData().getColumnCount();
-		String[] values = new String[columns];
-		for (int i = 0; i < columns; i++) {
-			values[i] = rs.getString(i + 1);
-		}
+	private void sendDataRow(ResultSet rs, int columns, int[] types) throws SQLException, IOException {
 		startMessage('D');
 		writeShort(columns);
-		for (String s : values) {
-			if (s == null) {
+		for (int i = 0; i < columns; i++) {
+			byte[] bytes = getContent(rs, types[i], i+1);			
+			if (bytes == null) {
 				writeInt(-1);
 			} else {
-				// TODO write Binary data
-				byte[] d2 = s.getBytes(this.encoding);
-				writeInt(d2.length);
-				write(d2);
+				writeInt(bytes.length);
+				write(bytes);
 			}
 		}
 		sendMessage();
 	}
 
+	private byte[] getContent(ResultSet rs, int type, int column) throws SQLException, TeiidSQLException, IOException {
+		byte[] bytes = null;
+		switch (type) {
+		    case Types.BOOLEAN:
+		    case Types.VARCHAR:       
+		    case Types.CHAR:
+		    case Types.SMALLINT:
+		    case Types.INTEGER:
+		    case Types.BIGINT:
+		    case Types.NUMERIC:
+		    case Types.DECIMAL:
+		    case Types.FLOAT:
+		    case Types.REAL:
+		    case Types.DOUBLE:
+		    case Types.TIME:
+		    case Types.DATE:
+		    case Types.TIMESTAMP:
+		    	String value = rs.getString(column);
+		    	if (value != null) {
+		    		bytes = value.getBytes(this.encoding);
+		    	}
+		    	break;
+		    
+		    case Types.LONGVARCHAR:
+		    case Types.CLOB:    
+		    	Clob clob = rs.getClob(column);
+		    	if (clob != null) {
+		    		bytes = ObjectConverterUtil.convertToByteArray(new ReaderInputStream(clob.getCharacterStream(), this.encoding), this.maxLobSize);
+		    	}		        	
+		    	break;
+		    	
+		    case Types.SQLXML:  
+		    	SQLXML xml = rs.getSQLXML(column);
+		    	if (xml != null) {
+		    		bytes = ObjectConverterUtil.convertToByteArray(new ReaderInputStream(xml.getCharacterStream(), this.encoding), this.maxLobSize);		    		
+		    	}		        	
+		    	break;
+		    	
+		    case Types.BINARY:
+		    case Types.VARBINARY:		        	
+		    case Types.LONGVARBINARY:
+		    case Types.BLOB:
+		    	Blob blob = rs.getBlob(column);
+		    	if (blob != null) {
+		    		bytes = toHex(ObjectConverterUtil.convertToByteArray(blob.getBinaryStream(), this.maxLobSize));
+		    	}
+		    	break;
+		    default:
+		    	throw new TeiidSQLException("unknown datatype failed to convert"); 
+		}
+		return bytes;
+	}
+	
+	@Override
+	public void sslDenied() {
+		ChannelBuffer buffer = ChannelBuffers.directBuffer(1);
+		buffer.writeByte('N');
+		Channels.write(this.ctx, this.message.getFuture(), buffer, this.message.getRemoteAddress());		
+	}
+	
 	private void sendErrorResponse(Throwable t) throws IOException {
 		trace(t.getMessage());
 		SQLException e = TeiidSQLException.create(t);
@@ -496,6 +566,35 @@
 		writeString(value);
 		sendMessage();
 	}
+	
+	@Override
+	public void functionCallResponse(byte[] data) {
+		try {
+			startMessage('V');
+			if (data == null) {
+				writeInt(-1);
+			}
+			else {
+				writeInt(data.length);
+				write(data);
+			}
+			sendMessage();
+		} catch (IOException e) {
+			terminate(e);
+		}		
+	}
+	
+	@Override
+	public void functionCallResponse(int data) {
+		try {
+			startMessage('V');
+			writeInt(4);
+			writeInt(data);
+			sendMessage();
+		} catch (IOException e) {
+			terminate(e);
+		}		
+	}
 
 	private void writeString(String s) throws IOException {
 		write(s.getBytes(this.encoding));
@@ -543,26 +642,30 @@
 		LogManager.logTrace(LogConstants.CTX_ODBC, msg);
 	}
 	
+	/**
+	 * Types.ARRAY is not supported
+	 */
     private static int convertType(final int type) {
         switch (type) {
         case Types.BOOLEAN:
-            return PG_TYPE_BOOL;
+            return PG_TYPE_BOOL;        
         case Types.VARCHAR:
-            return PG_TYPE_VARCHAR;
-        case Types.CLOB:
-            return PG_TYPE_TEXT;
+            return PG_TYPE_VARCHAR;        
         case Types.CHAR:
-            return PG_TYPE_BPCHAR;
+            return PG_TYPE_BPCHAR;        
+        case Types.TINYINT:
         case Types.SMALLINT:
-            return PG_TYPE_INT2;
+            return PG_TYPE_INT2;            
         case Types.INTEGER:
-            return PG_TYPE_INT4;
+            return PG_TYPE_INT4;            
         case Types.BIGINT:
-            return PG_TYPE_INT8;
+            return PG_TYPE_INT8;            
+        case Types.NUMERIC:
         case Types.DECIMAL:
-            return PG_TYPE_NUMERIC;
+            return PG_TYPE_NUMERIC;        
+        case Types.FLOAT:
         case Types.REAL:
-            return PG_TYPE_FLOAT4;
+            return PG_TYPE_FLOAT4;            
         case Types.DOUBLE:
             return PG_TYPE_FLOAT8;
         case Types.TIME:
@@ -571,14 +674,44 @@
             return PG_TYPE_DATE;
         case Types.TIMESTAMP:
             return PG_TYPE_TIMESTAMP_NO_TMZONE;
-        case Types.VARBINARY:
-            return PG_TYPE_BYTEA;
-        case Types.BLOB:
-            return PG_TYPE_OID;
-        case Types.ARRAY:
-            return PG_TYPE_TEXTARRAY;
+            
+        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;
         }
     }
+    
+	private static final byte[] hexChars = {'0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'a', 'b', 'c', 'd', 'e','f' };
+	
+	/**
+	 * When sending the byteA content to client convert into Hex before sending the content.
+	 * @param b
+	 * @return
+	 * @throws IOException
+	 */
+	static byte[] toHex(byte[] b) throws IOException {
+		byte[] hexbytes = PgFrontendProtocol.createByteArray((2 * b.length)+2);
+		hexbytes[0] = '\\';
+		hexbytes[1] = 'x';
+			
+		for (int i = 0; i < b.length; i++) {
+			int index = (i*2)+2;
+			int v = b[i] & 0xff;
+			hexbytes[index] = hexChars[v >> 4];
+			hexbytes[index+1] = hexChars[v & 0xf];
+		}
+		return hexbytes;
+	}      
 }

Modified: trunk/runtime/src/main/java/org/teiid/transport/PgFrontendProtocol.java
===================================================================
--- trunk/runtime/src/main/java/org/teiid/transport/PgFrontendProtocol.java	2011-02-10 19:56:37 UTC (rev 2903)
+++ trunk/runtime/src/main/java/org/teiid/transport/PgFrontendProtocol.java	2011-02-14 01:30:06 UTC (rev 2904)
@@ -47,6 +47,15 @@
 @SuppressWarnings("nls")
 public class PgFrontendProtocol extends FrameDecoder {
 
+	private static final int LO_CREAT =	957;
+	private static final int LO_OPEN = 952;
+	private static final int LO_CLOSE = 953;
+	private static final int LO_READ = 954;
+	private static final int LO_WRITE = 955;
+	private static final int LO_LSEEK = 956;
+	private static final int LO_TELL = 958;
+	private static final int LO_UNLINK = 964;
+	
 	private int maxObjectSize;
 	private Byte messageType;
 	private Integer dataLength;
@@ -148,7 +157,9 @@
         case 'C':
         	return buildClose(data);
         case 'H':
-        	return buildFlush();        	       
+        	return buildFlush();
+        case 'F':
+        	return buildFunctionCall(data);        	               	
         default:
         	return buildError();
         }
@@ -179,6 +190,13 @@
         int version = data.readInt();
         props.setProperty("version", Integer.toString(version));
         
+        // SSL Request
+        if (version == 80877103) {
+        	this.initialized = false;
+        	this.odbcProxy.sslRequest();
+        	return message;
+        }
+        
         trace("StartupMessage");
         trace(" version " + version + " (" + (version >> 16) + "." + (version & 0xff) + ")");
         
@@ -235,7 +253,7 @@
         }
         
         int paramCount = data.readShort();
-        Object[] params = new String[paramCount];
+        Object[] params = new Object[paramCount];
         for (int i = 0; i < paramCount; i++) {
             int paramLen = data.readInt();
             byte[] paramdata = createByteArray(paramLen);
@@ -299,7 +317,7 @@
         return message;
 	}	
 	
-	private byte[] createByteArray(int length) throws StreamCorruptedException{
+	static byte[] createByteArray(int length) throws StreamCorruptedException{
 		try {
 			return new byte[length];
 		} catch(OutOfMemoryError e) {
@@ -322,6 +340,66 @@
 		return message;
 	}	
 	
+	/**
+	 * LO functions are always binary, so I am ignoring the formats, return types. The below is not used
+	 * leaving for future if ever LO is revisited
+	 */
+	@SuppressWarnings("unused")
+	private Object buildFunctionCall(NullTerminatedStringDataInputStream data) throws IOException {
+		int funcID = data.readInt();
+		
+		// read data types of arguments 
+		int formatCount = data.readShort();
+		int[] formatTypes = new int[formatCount];
+		for (int i = 0; i< formatCount; i++) {
+			formatTypes[i] = data.readShort();
+		}
+		
+		// arguments	
+		data.readShort(); // ignore the param count; we know them by functions supported.
+		int oid = readInt(data);
+		switch(funcID) {
+		case LO_CREAT:
+			break;
+		case LO_OPEN:
+			int mode = readInt(data);
+			break;
+		case LO_CLOSE:
+			break;			
+		case LO_READ:
+			int length = readInt(data);
+			break;
+		case LO_WRITE:
+			byte[] contents = readByteArray(data);
+			break;
+		case LO_LSEEK:
+			int offset = readInt(data);
+			int where = readInt(data);
+			break;
+		case LO_TELL:
+			break;
+		case LO_UNLINK:			
+			break;		
+		}
+		this.odbcProxy.functionCall(oid);
+		return message;
+	}	
+	
+	private int readInt(NullTerminatedStringDataInputStream data) throws IOException {
+		data.readInt(); // ignore this this is length always 4
+		return data.readInt();
+	}
+	
+	private byte[] readByteArray(NullTerminatedStringDataInputStream data) throws IOException {
+		int length = data.readInt();
+		if (length == -1 || length == 0) {
+			return null;
+		}
+		byte[] content = createByteArray(length);
+		data.read(content, 0, length);
+		return content;
+	}
+	
 	static class NullTerminatedStringDataInputStream extends DataInputStream{
 		private String encoding;
 		

Modified: trunk/runtime/src/main/resources/org/teiid/runtime/i18n.properties
===================================================================
--- trunk/runtime/src/main/resources/org/teiid/runtime/i18n.properties	2011-02-10 19:56:37 UTC (rev 2903)
+++ trunk/runtime/src/main/resources/org/teiid/runtime/i18n.properties	2011-02-14 01:30:06 UTC (rev 2904)
@@ -87,3 +87,4 @@
 error_closing_stmt=Error closing portal statement {0}
 model_metadata_loading=VDB "{0}" - "{1}" model metadata is currently being loaded. Start Time: {2}
 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
\ No newline at end of file



More information about the teiid-commits mailing list