Subject Possible Bug in Jaybird fresh from CVS
Author Ryan Baldwin
Hi,

I believe I may have found a bug in the latest Jaybird code from cvs that is
not in RC1. I dont have much time until after the weekend but I've posted a
test case as text bellow. I appologise for the messy code - but I will clean
this up and do more testing after the weekend if necesary.

The test case that shows this possible bug is in the testLockUp method. When
the first execute update is called the thread will end up blocked on a
socket read indefinitly as far as I have seen. This occurs with clean
checkout from CVS but not with RC1. I havent had time to test against the
RC3 build yet but I assume its very close if not the same as the latest CVS.

I appologise if this has already been fixed and I havent had a moment to
look at bug reporting policy for the project yet but will do before posting
my next bug report. I thought you might want to see this anyhow is it seems
like a serious problem.

Also in the code bellow is somthing that tests a problem with result sets on
closed connections but I will post more on this later.

Thanks
Ryan



package org.firebirdsql.jdbc;

import java.sql.*;
import java.util.ArrayList;
import java.util.List;

public class TestBoundary extends BaseFBTest
{
public TestBoundary(String testName) {
super(testName);
}

Connection connection = null;

protected void setUp() throws Exception
{
super.setUp();
Class.forName(FBDriver.class.getName());
connection = DriverManager.getConnection(DB_DRIVER_URL, DB_INFO);
connection.setAutoCommit(false);

}

protected void tearDown() throws Exception
{
connection.close();
super.tearDown();
}

final String CREATE_META_ONE = "CREATE TABLE COMMUNICATIONS_FIT ( \n" +
"ID INTEGER NOT NULL, \n" +
"GUIDID CHAR(16), \n" +
"NAME VARCHAR(64) CHARACTER SET ISO8859_1 COLLATE EN_UK, \n" +
"SDESC VARCHAR(256) CHARACTER SET ISO8859_1 COLLATE EN_UK, \n" +
"LDESC BLOB SUB_TYPE 1, \n" +
"STATUS INTEGER, \n" +
"PRIMARY KEY (ID) \n" +
") \n" ;

final String CREATE_META_TWO = "CREATE GENERATOR COMMUNICATIONS_FIT_ID";

final String CREATE_META_THREE = "CREATE PROCEDURE COMMUNICATIONS_FIT_ID
(NumberToAllocate INTEGER) RETURNS ( NewId INTEGER ) \n"+
"AS \n" +
"BEGIN \n" +
"NewId = GEN_ID(COMMUNICATIONS_FIT_ID, :NumberToAllocate); \n"+
"SUSPEND; \n"+
"END; \n";

public void testLockUp() throws Exception
{
// createMetadata(connection);

final int idBase = allocateIds(connection, 3);

final PreparedStatement statement =
connection.prepareStatement("INSERT INTO COMMUNICATIONS_FIT ( \n " +

"GUIDID, \n" +

"NAME, \n" +

"SDESC, \n" +

"LDESC, \n" +

"STATUS, \n" +
"ID
\n" +
")
\n" +

"VALUES ( ?, ?, ?, ?, ?, ? ) \n");

for( int i = 0, n = 3; i<n; i++ )
{
statement.clearParameters();
writeRecordToStatement( idBase+i, statement );
statement.executeUpdate(); // <---- WE WILL LOCKL
}
}

private void writeRecordToStatement(int i, PreparedStatement statement)
throws SQLException
{
statement.setBytes( 1, new byte[16] );
statement.setString( 2, "Further" );
statement.setString( 3, "Further infomation field");
statement.setString( 4, "Field to provide Further infomation
capture");
statement.setInt( 5, 2 );
statement.setInt( 6, 1 );
}

private void createMetadata(Connection conn) throws SQLException
{
final Statement stmnt = conn.createStatement();
try
{
stmnt.executeUpdate(CREATE_META_ONE);
conn.commit();

stmnt.executeUpdate(CREATE_META_TWO);
conn.commit();

stmnt.executeUpdate(CREATE_META_THREE);
conn.commit();
}
finally
{
stmnt.close();
}
}

private int allocateIds(Connection conn, int amount) throws SQLException
{
Statement stmnt = null;
ResultSet results = null;
try
{
stmnt = conn.createStatement();

final String sql ="SELECT * FROM COMMUNICATIONS_FIT_ID('3')";

results = stmnt.executeQuery(sql);
if( !results.next() )
assert(false);

final int lastId = results.getInt(1);
return lastId-amount;
}
finally
{
try { if( results != null ) { results.close(); } } catch(
Throwable ex ) { ex.printStackTrace(); }
try { if( stmnt != null ) { stmnt.close(); } } catch( Throwable
ex ) { ex.printStackTrace(); }
}
}

public void testClosedAutocommitResultset() throws Exception
{
final List list = new ArrayList();

String sql = "SELECT rdb$relation_name FROM rdb$relations";
ResultSet results = executeQuery(sql);

while(results.next())
list.add(results.getString(1).trim().toUpperCase());

}

private ResultSet executeQuery(String query) throws SQLException
{
Statement stmt = connection.createStatement();

stmt.setFetchSize(1);

ResultSet results = stmt.executeQuery(query);
freeConnection(connection);
return results;
}

protected void freeConnection(Connection connection)
{
if (connection == null) return;

try
{
if (connection.isClosed()) return;
connection.commit();
connection.close();
}
catch (SQLException e)
{
e.printStackTrace();
}
}

}