From: Roman R. <rro...@us...> - 2003-06-22 22:40:28
|
Update of /cvsroot/firebird/client-java/src/main/org/firebirdsql/jdbc In directory sc8-pr-cvs1:/tmp/cvs-serv15731 Modified Files: FBBlob.java FBConnection.java FBPreparedStatement.java FBStatement.java Added Files: FirebirdBlob.java FirebirdConnection.java Synchronizable.java Log Message: added some synchronization introduced firebird specific interfaces for connection and blobs --- FirebirdBlob.java ADDED --- --- FirebirdConnection.java ADDED --- --- Synchronizable.java ADDED --- Index: FBBlob.java =================================================================== RCS file: /cvsroot/firebird/client-java/src/main/org/firebirdsql/jdbc/FBBlob.java,v retrieving revision 1.10 retrieving revision 1.11 diff -b -U3 -r1.10 -r1.11 --- FBBlob.java 20 Jun 2003 20:03:55 -0000 1.10 +++ FBBlob.java 22 Jun 2003 22:40:25 -0000 1.11 @@ -20,27 +20,12 @@ package org.firebirdsql.jdbc; +import java.io.*; import java.sql.Blob; import java.sql.SQLException; +import java.util.*; -import java.io.BufferedInputStream; -import java.io.InputStream; -import java.io.Reader; -import java.io.OutputStreamWriter; -import java.io.IOException; -import java.util.Collection; -import java.util.Iterator; -import java.util.HashSet; - -import org.firebirdsql.gds.isc_blob_handle; -import org.firebirdsql.gds.GDSException; -import org.firebirdsql.gds.ISCConstants; -import org.firebirdsql.logging.Logger; -import org.firebirdsql.logging.LoggerFactory; - -import java.io.OutputStream; -import java.io.BufferedOutputStream; -import org.firebirdsql.gds.GDS; +import org.firebirdsql.gds.*; /** @@ -78,7 +63,7 @@ * @since 1.2 */ -public class FBBlob implements Blob{ +public class FBBlob implements FirebirdBlob { private static final boolean SEGMENTED = false; public static final int READ_FULLY_BUFFER_SIZE = 16 * 1024; @@ -130,7 +115,6 @@ * @see <a href="package-summary.html#2.0 API">What Is in the JDBC 2.0 API</a> */ public long length() throws SQLException { - //throw new SQLException("Not yet implemented"); try { byte[] info = getInfo( new byte[]{ISCConstants.isc_info_blob_total_length}, 20); @@ -164,6 +148,12 @@ info, position + 3, dataLength); } + /** + * Check if blob is segmented. + * + * @return <code>true</code> if this blob is segmented, + * otherwise <code>false</code> + */ public boolean isSegmented() throws SQLException { try { byte[] info = getInfo( @@ -185,6 +175,26 @@ } /** + * Detach this blob. This method creates new instance of the same blob + * database object that is not under result set control. When result set + * is closed, all associated resources are also released, including open + * blob streams. This method creates an new instance of blob object with + * the same blob ID that can be used even when result set is closed. + * <p> + * Note, detached blob will not remember the stream position of this object. + * This means that you cannot start reading data from the blob, then detach + * it, and then continue reading. Reading from detached blob will begin at + * the blob start. + * + * @return instance of {@link FBBlob} that is not under result set control. + * + * @throws SQLException if Blob cannot be detached. + */ + public FirebirdBlob detach() throws SQLException { + return new FBBlob(c, blob_id); + } + + /** * Returns as an array of bytes, part or all of the <code>BLOB</code> * value that this <code>Blob</code> object designates. The byte * array contains up to <code>length</code> consecutive bytes @@ -217,7 +227,7 @@ * @see <a href="package-summary.html#2.0 API">What Is in the JDBC 2.0 API</a> */ public InputStream getBinaryStream () throws SQLException { - FBBlobInputStream blobstream = new FBBlobInputStream(); + FBBlobInputStream blobstream = new FBBlobInputStream(this); inputStreams.add(blobstream); //return new BufferedInputStream(blobstream, bufferlength); return blobstream; @@ -322,7 +332,8 @@ //copy pos bytes from input to output //implement this later } - return new BufferedOutputStream(blobOut, bufferlength); + // return new BufferedOutputStream(blobOut, bufferlength); + return blobOut; } @@ -373,7 +384,9 @@ //Inner classes - public class FBBlobInputStream extends InputStream { + public class FBBlobInputStream extends InputStream + implements FirebirdBlob.BlobInputStream + { /** @@ -398,7 +411,10 @@ private boolean closed; - private FBBlobInputStream() throws SQLException { + private FBBlob owner; + + private FBBlobInputStream(FBBlob owner) throws SQLException { + this.owner = owner; closed = false; @@ -413,22 +429,31 @@ } } - public void seek(int position) throws SQLException { + public FirebirdBlob getBlob() { + return owner; + } + + public void seek(int position) throws IOException { try { c.getInternalAPIHandler().isc_seek_blob(blob, position); } catch(GDSException ex) { - throw new FBSQLException(ex); + /** @todo fix this */ + //throw new FBSQLException(ex); + throw new IOException(ex.getMessage()); } } - public long length() throws SQLException { + public long length() throws IOException { try { byte[] info = c.getInternalAPIHandler().isc_blob_info(blob, new byte[]{ISCConstants.isc_info_blob_total_length}, 20); return interpretLength(info, 0); } catch(GDSException ex) { - throw new FBSQLException(ex); + //throw new FBSQLException(ex); + throw new IOException(ex.getMessage()); + } catch(SQLException ex) { + throw new IOException(ex.getMessage()); } } @@ -491,6 +516,9 @@ System.arraycopy(buffer, 0, b, pos, counter); pos += counter; } + + if (pos < length()) + throw new EOFException(); } public void readFully(byte[] b) throws IOException { @@ -515,7 +543,9 @@ } } - public class FBBlobOutputStream extends OutputStream { + public class FBBlobOutputStream extends OutputStream + implements FirebirdBlob.BlobOutputStream + { private isc_blob_handle blob; @@ -539,14 +569,16 @@ } } - public long length() throws SQLException { + public long length() throws IOException { try { byte[] info = c.getInternalAPIHandler().isc_blob_info(blob, new byte[]{ISCConstants.isc_info_blob_total_length}, 20); return interpretLength(info, 0); } catch(GDSException ex) { - throw new FBSQLException(ex); + throw new IOException(ex.getMessage()); + } catch(SQLException ex) { + throw new IOException(ex.getMessage()); } } Index: FBConnection.java =================================================================== RCS file: /cvsroot/firebird/client-java/src/main/org/firebirdsql/jdbc/FBConnection.java,v retrieving revision 1.23 retrieving revision 1.24 diff -b -U3 -r1.23 -r1.24 --- FBConnection.java 14 Jun 2003 17:32:44 -0000 1.23 +++ FBConnection.java 22 Jun 2003 22:40:25 -0000 1.24 @@ -19,31 +19,12 @@ package org.firebirdsql.jdbc; -import java.sql.Blob; -import java.sql.CallableStatement; -import java.sql.Connection; -import java.sql.DatabaseMetaData; -import java.sql.PreparedStatement; -import java.sql.ResultSet; -import java.sql.SQLException; -import java.sql.SQLWarning; -import java.sql.Savepoint; -import java.sql.Statement; -import java.util.HashMap; -import java.util.HashSet; -import java.util.List; -import java.util.Set; -import java.util.Iterator; -import javax.resource.ResourceException; -import org.firebirdsql.gds.ISCConstants; -import org.firebirdsql.gds.isc_stmt_handle; -import org.firebirdsql.gds.isc_blob_handle; -import org.firebirdsql.gds.isc_db_handle; -import org.firebirdsql.gds.GDSException; -import org.firebirdsql.gds.GDS; -import org.firebirdsql.jca.FBLocalTransaction; -import org.firebirdsql.jca.FBManagedConnection; -import java.util.Map; +import java.sql.*; +import java.util.*; +import javax.resource.*; + +import org.firebirdsql.gds.*; +import org.firebirdsql.jca.*; /** * The class <code>FBConnection</code> is a handle to a FBManagedConnection. @@ -51,7 +32,7 @@ * @author <a href="mailto:d_j...@us...">David Jencks</a> * @version 1.0 */ -public class FBConnection implements Connection +public class FBConnection implements Connection, FirebirdConnection /*, javax.resource.cci.Connection * It is not possible to implement both Connection interfaces in one class * due to conflicting exception signatures. @@ -955,7 +936,7 @@ * into a blob field without needing a preexisting blob * to modify. **/ - public synchronized Blob createBlob() throws SQLException { + public synchronized FirebirdBlob createBlob() throws SQLException { /** @todo check if this is correct code */ if (!getAutoCommit()) Index: FBPreparedStatement.java =================================================================== RCS file: /cvsroot/firebird/client-java/src/main/org/firebirdsql/jdbc/FBPreparedStatement.java,v retrieving revision 1.21 retrieving revision 1.22 diff -b -U3 -r1.21 -r1.22 --- FBPreparedStatement.java 5 Jun 2003 23:22:32 -0000 1.21 +++ FBPreparedStatement.java 22 Jun 2003 22:40:25 -0000 1.22 @@ -19,28 +19,15 @@ package org.firebirdsql.jdbc; -import java.io.InputStream; -import java.io.Reader; -import java.math.BigDecimal; -import java.net.URL; -import java.sql.Array; -import java.sql.Blob; -import java.sql.Clob; +import java.io.*; +import java.math.*; +import java.net.*; +import java.sql.*; import java.sql.Date; -import java.sql.ParameterMetaData; -import java.sql.PreparedStatement; -import java.sql.Ref; -import java.sql.ResultSet; -import java.sql.ResultSetMetaData; -import java.sql.SQLException; -import java.sql.Time; -import java.sql.Timestamp; -import java.sql.Types; -import java.util.Calendar; -import org.firebirdsql.gds.GDSException; -import org.firebirdsql.gds.XSQLVAR; -import org.firebirdsql.logging.Logger; -import org.firebirdsql.logging.LoggerFactory; +import java.util.*; + +import org.firebirdsql.gds.*; +import org.firebirdsql.logging.*; /** * @@ -71,15 +58,21 @@ FBPreparedStatement(FBConnection c, String sql) throws SQLException { super(c); + + Object syncObject = getSynchronizationObject(); + synchronized(syncObject) { try { c.ensureInTransaction(); prepareFixedStatement(sql, true); } catch (GDSException ge) { - if (log!=null) log.info("GDSException in PreparedStatement constructor", ge); + if (log != null) + log.info("GDSException in PreparedStatement constructor", + ge); throw new FBSQLException(ge); } finally { c.checkEndTransaction(); - }// end of try-catch-finally + } // end of try-catch-finally + } } @@ -93,26 +86,23 @@ * @exception SQLException if a database access error occurs */ public ResultSet executeQuery() throws SQLException { - try - { + Object syncObject = getSynchronizationObject(); + + synchronized(syncObject) { + try { c.ensureInTransaction(); - if (!internalExecute(isExecuteProcedureStatement)) - { + if (!internalExecute(isExecuteProcedureStatement)) { throw new SQLException("No resultset for sql"); } - if (c.willEndTransaction()) - { + if (c.willEndTransaction()) { return getCachedResultSet(false); - } // end of if () - else - { + } else { return getResultSet(); - } // end of else } - finally - { + } finally { c.checkEndTransaction(); - } // end of finally + } + } } @@ -128,18 +118,20 @@ * @exception SQLException if a database access error occurs */ public int executeUpdate() throws SQLException { - try - { + + Object syncObject = getSynchronizationObject(); + + synchronized(syncObject) { + try { c.ensureInTransaction(); if (internalExecute(isExecuteProcedureStatement)) { throw new SQLException("update statement returned results!"); } return getUpdateCount(); - } - finally - { + } finally { c.checkEndTransaction(); - } // end of finally + } + } } @@ -376,20 +368,22 @@ * @see Statement#execute */ public boolean execute() throws SQLException { - try - { + + Object syncObject = getSynchronizationObject(); + + synchronized(syncObject) { + try { c.ensureInTransaction(); - boolean hasResultSet = internalExecute(isExecuteProcedureStatement); - if (hasResultSet && c.willEndTransaction()) - { + boolean hasResultSet = internalExecute( + isExecuteProcedureStatement); + if (hasResultSet && c.willEndTransaction()) { getCachedResultSet(false); - } // end of if () - return hasResultSet; } - finally - { + return hasResultSet; + } finally { c.checkEndTransaction(); - } // end of finally + } + } } protected boolean internalExecute(boolean sendOutParams) throws SQLException @@ -403,9 +397,12 @@ throw new SQLException("Not all parameters were set. " + "Cannot execute query."); - if (hasBlobs){ - for(int i = 0; i < isParamSet.length; i++){ - if (isBlob[i]){ + Object syncObject = getSynchronizationObject(); + + synchronized(syncObject) { + if (hasBlobs) { + for (int i = 0; i < isParamSet.length; i++) { + if (isBlob[i]) { FBFlushableField flushableField = (FBFlushableField)getField(i + 1); @@ -413,14 +410,15 @@ } } } + try { closeResultSet(); c.executeStatement(fixedStmt, sendOutParams); isResultSet = (fixedStmt.getOutSqlda().sqld > 0); return (fixedStmt.getOutSqlda().sqld > 0); - } - catch (GDSException ge) { + } catch (GDSException ge) { throw new FBSQLException(ge); + } } } Index: FBStatement.java =================================================================== RCS file: /cvsroot/firebird/client-java/src/main/org/firebirdsql/jdbc/FBStatement.java,v retrieving revision 1.16 retrieving revision 1.17 diff -b -U3 -r1.16 -r1.17 --- FBStatement.java 5 Jun 2003 23:22:32 -0000 1.16 +++ FBStatement.java 22 Jun 2003 22:40:25 -0000 1.17 @@ -51,7 +51,7 @@ * @see Connection#createStatement * @see ResultSet */ -public class FBStatement implements Statement { +public class FBStatement implements Statement, Synchronizable { protected FBConnection c; @@ -82,6 +82,22 @@ } /** + * Get synchronization object for this statement object. + * + * @return object that will be used for synchronization. + * + * @throws SQLException if something went wrong. + */ + public Object getSynchronizationObject() throws SQLException { + synchronized(c) { + if (c.getAutoCommit()) + return c; + else + return this; + } + } + + /** * Executes an SQL statement that returns a single <code>ResultSet</code> object. * * @param sql typically this is a static SQL <code>SELECT</code> statement @@ -92,32 +108,29 @@ public ResultSet executeQuery(String sql) throws SQLException { if (closed) throw new SQLException("Statement is closed"); - try - { + + Object syncObject = getSynchronizationObject(); + + synchronized(syncObject) { + try { c.ensureInTransaction(); if (!internalExecute(sql)) { - throw new SQLException("query did not return a result set: " + sql); + throw new SQLException( + "query did not return a result set: " + sql); } - if (c.willEndTransaction()) - { + if (c.willEndTransaction()) { ResultSet rs = getCachedResultSet(false); //autocommits. return rs; - } // end of if () - else - { + } else { // end of if () return getResultSet(); } // end of else - } - catch (GDSException ge) - { + } catch (GDSException ge) { throw new FBSQLException(ge); - } // end of try-catch - finally - { + } finally { // end of try-catch c.checkEndTransaction(); } // end of finally - + } } @@ -136,23 +149,23 @@ public int executeUpdate(String sql) throws SQLException { if(closed) throw new SQLException("Statement is closed"); - try - { + + Object syncObject = getSynchronizationObject(); + + synchronized(syncObject) { + try { c.ensureInTransaction(); if (internalExecute(sql)) { throw new SQLException("update statement returned results!"); } return getUpdateCount(); - } - catch (GDSException ge) - { + } catch (GDSException ge) { throw new FBSQLException(ge); - } // end of try-catch - finally - { + } finally { // end of try-catch c.checkEndTransaction(); } // end of finally } + } /** * jdbc 3 @@ -207,28 +220,29 @@ if (closed) throw new SQLException("This statement is already closed."); + Object syncObject = getSynchronizationObject(); + + synchronized(syncObject) { try { if (fixedStmt != null) { try { //may need ensureTransaction? c.closeStatement(fixedStmt, true); - } - catch (GDSException ge) { + } catch (GDSException ge) { throw new FBSQLException(ge); - } - finally { + } finally { fixedStmt = null; currentRs = null; currentCachedResultSet = null; closed = true; } - } - else + } else closed = true; } finally { c.notifyStatementClosed(this); } } + } /** * Check if this statement was closed. This is quick workaround to avoid @@ -461,23 +475,23 @@ public boolean execute(String sql) throws SQLException { if (closed) throw new SQLException("Statement is closed"); + + Object syncObject = getSynchronizationObject(); + + synchronized(syncObject) { try { c.ensureInTransaction(); boolean hasResultSet = internalExecute(sql); - if (hasResultSet && c.willEndTransaction()) - { + if (hasResultSet && c.willEndTransaction()) { getCachedResultSet(false); } // end of if () return hasResultSet; - } - catch (GDSException ge) - { + } catch (GDSException ge) { throw new FBSQLException(ge); - } // end of try-catch - finally - { + } finally { // end of try-catch c.checkEndTransaction(); } // end of finally + } } /** |