Return-Path: Mailing-List: contact torque-dev-help@db.apache.org; run by ezmlm Delivered-To: mailing list torque-dev@db.apache.org Received: (qmail 98493 invoked from network); 9 Apr 2003 22:20:47 -0000 Received: from owlery.vecna.com (207.188.238.194) by daedalus.apache.org with SMTP; 9 Apr 2003 22:20:47 -0000 Received: from vecna.com (pcpmd.vecna.com [207.188.238.201]) by owlery.vecna.com (8.11.6/8.11.6) with ESMTP id h39MKro17760 for ; Wed, 9 Apr 2003 18:20:54 -0400 Message-ID: <3E949CC5.9010605@vecna.com> Date: Wed, 09 Apr 2003 18:20:53 -0400 From: Scott Miller User-Agent: Mozilla/5.0 (X11; U; Linux i686; en-US; rv:1.0.1) Gecko/20021003 X-Accept-Language: en-us, en MIME-Version: 1.0 To: Turbine Torque Developers List Subject: Re: Village Patch (Oracle Clobs) References: <3E947048.9090608@vecna.com> <3E947450.7010808@marmot.at> <3E947810.50902@vecna.com> Content-Type: text/plain; charset=us-ascii; format=flowed Content-Transfer-Encoding: 7bit X-Spam-Rating: daedalus.apache.org 1.6.2 0/1000/N Through some more testing today I found that this method does not work for Oracle 8 JDBC drivers. I am sure a very similar method would work, however one of the methods I access via reflection does not exist in the v8 drivers. Here is the new, updated dif. I added in a check for the version of the currently used driver. Index: com/workingdogs/village/Value.java =================================================================== RCS file: /home/cvspublic/village/com/workingdogs/village/Value.java,v retrieving revision 1.18 diff -u -r1.18 Value.java --- com/workingdogs/village/Value.java 30 Jul 2002 23:20:51 -0000 1.18 +++ com/workingdogs/village/Value.java 9 Apr 2003 22:14:37 -0000 @@ -53,7 +53,18 @@ package com.workingdogs.village; +import java.lang.Class; +import java.lang.ClassNotFoundException; +import java.lang.IllegalAccessError; +import java.lang.NoSuchFieldException; +import java.lang.NoSuchMethodException; +import java.lang.reflect.Field; +import java.lang.reflect.InvocationTargetException; +import java.lang.reflect.Method; import java.math.BigDecimal; +import java.io.IOException; +import java.io.Writer; +import java.sql.Clob; import java.sql.PreparedStatement; import java.sql.ResultSet; import java.sql.SQLException; @@ -67,7 +78,7 @@ cross between a row and column and contains the information held there. @author Jon S. Stevens jon@latchkey.com -@version $Revision: 1.18 $ +@version $Revision: 1.0 $ */ public class Value { @@ -77,6 +88,10 @@ private int columnNumber; /** what sql type of object is this? */ private int type; + /** Name of the oracle driver -- used to support Oracle clobs as a special case */ + private static final String ORACLE_DRIVER_NAME = "Oracle JDBC driver"; + /** Version of the oracle driver being supported with cloba */ + private static final int ORACLE_DRIVER_VERSION = 9; /** * Creates a new Value object based on the ResultSet, columnNumber and type @@ -152,7 +167,42 @@ case Types.BLOB: valueObject = rs.getBytes (columnNumber); break; - + + case Types.CLOB: + // read any CLOBs as strings + Clob clob = rs.getClob(columnNumber); + if( clob == null ) + { + valueObject = null; + } + else + { + long remainingLength = clob.length(); + long currentPosition = 1; + + String valueString = ""; + while( remainingLength > 0 ) + { + int readLength = 0; + if( remainingLength > Integer.MAX_VALUE ) + { + // there will be more iterations + readLength = Integer.MAX_VALUE; + } + else + { + // this is the last iteration + readLength = (int)remainingLength; + } + + valueString += clob.getSubString( currentPosition, readLength ); + currentPosition += readLength; + remainingLength -= readLength; + } + valueObject = valueString; + } + break; + case Types.LONGVARCHAR: case Types.CHAR: case Types.VARCHAR: @@ -267,6 +317,105 @@ stmt.setBytes (stmtNumber, this.asBytes()); break; + case Types.CLOB: + if( ORACLE_DRIVER_NAME.equals( stmt.getConnection().getMetaData().getDriverName() ) && + stmt.getConnection().getMetaData().getDriverMajorVersion() >= ORACLE_DRIVER_VERSION ) + { + try + { + // support oracle clobs without requiring oracle libraries + // at compile time + // Note this assumes that if you are using the Oracle Driver. + // then you have access to the oracle.sql.CLOB class + + // First get the oracle clob class + Class oracleClobClass = Class.forName("oracle.sql.CLOB"); + + // now get the static factory method + Class partypes[] = new Class[3]; + partypes[0] = Class.forName("java.sql.Connection"); + partypes[1] = Boolean.TYPE; + partypes[2] = Integer.TYPE; + Method createTemporaryMethod = oracleClobClass.getDeclaredMethod( "createTemporary", partypes ); + + // now get ready to call the factory method + Field durationSessionField = oracleClobClass.getField( "DURATION_SESSION" ); + Object arglist[] = new Object[3]; + arglist[0] = stmt.getConnection(); + arglist[1] = Boolean.TRUE; + arglist[2] = durationSessionField.get(null); //null is valid because of static field + + // Create our CLOB + Object tempClob = createTemporaryMethod.invoke( null, arglist ); //null is valid because of static method + + // get the open method + partypes = new Class[1]; + partypes[0] = Integer.TYPE; + Method openMethod = oracleClobClass.getDeclaredMethod( "open", partypes ); + + // prepare to call the method + Field modeReadWriteField = oracleClobClass.getField( "MODE_READWRITE" ); + arglist = new Object[1]; + arglist[0] = modeReadWriteField.get(null); //null is valid because of static field + + // call open(CLOB.MODE_READWRITE); + openMethod.invoke( tempClob, arglist ); + + // get the getCharacterOutputStream method + Method getCharacterOutputStreamMethod = oracleClobClass.getDeclaredMethod( "getCharacterOutputStream", null ); + + // call the getCharacterOutpitStream method + Writer tempClobWriter = (Writer) getCharacterOutputStreamMethod.invoke( tempClob, null ); + + // write the string to the clob + tempClobWriter.write(this.asString()); + tempClobWriter.flush(); + tempClobWriter.close(); + + // get the close method + Method closeMethod = oracleClobClass.getDeclaredMethod( "close", null ); + + // call the close method + closeMethod.invoke( tempClob, null ); + + // add the clob to the statement + stmt.setClob( stmtNumber, (Clob)tempClob ); + } + catch( ClassNotFoundException e ) + { + // could not find the class with reflection + throw new DataSetException("Unable to find a required class.\n" + e.getMessage()); + } + catch( NoSuchMethodException e ) + { + // could not find the metho with reflection + throw new DataSetException("Unable to find a required method.\n" + e.getMessage()); + } + catch( NoSuchFieldException e ) + { + // could not find the field with reflection + throw new DataSetException("Unable to find a required field.\n" + e.getMessage()); + } + catch( IllegalAccessException e ) + { + throw new DataSetException("Unable to access a required method or field.\n" + e.getMessage()); + } + catch( InvocationTargetException e ) + { + throw new DataSetException(e.getMessage()); + } + catch( IOException e ) + { + throw new DataSetException(e.getMessage()); + } + } + else + { + stmt.setString( stmtNumber, this.asString() ); + } + + break; + case Types.LONGVARCHAR: case Types.CHAR: case Types.VARCHAR: cvs server: Diffing docs -Scott