Menu

Sybase15 segfaults on BigDecimal insert

Help
Vaidotas
2012-08-17
2012-08-20
  • Vaidotas

    Vaidotas - 2012-08-17

    Hello,

    our company is using Sybase with jTDS driver and we ran into the following problem while migrating to Sybase 15.
    Our application started crashing on inserts containing BigDecimals, NUMERIC(20, 2) on Sybase (changing NUMERIC to MONEY did not help).

    I am not sure weather this is a jTDS bug, or should this be addressed to the Sybase team. I am providing the logs, code to reproduce the issue and some observations I have made.

    On the Java side we are getting I/O Errors after the statement is executed (nothing gets inserted):

    java.sql.SQLException: I/O Error: DB server closed connection.
        at net.sourceforge.jtds.jdbc.TdsCore.sybasePrepare(TdsCore.java:1281)
        at net.sourceforge.jtds.jdbc.ConnectionJDBC2.prepareSQL(ConnectionJDBC2.java:704)
        at net.sourceforge.jtds.jdbc.JtdsPreparedStatement.execute(JtdsPreparedStatement.java:557)
    

    The Sybase log shows a SEGFAULT in the connection's process:

    01:00000:00023:2012/08/17 09:00:12.92 kernel  Address 0x0000000080497934 (_$o1cexwZ0.s_retparams+0x20), siginfo (code, address) = (1, 0xe800010065c
    45440)
    01:00000:00023:2012/08/17 09:00:12.92 kernel  Saved signal context address 0x0000010004bb5b30
    01:00000:00023:2012/08/17 09:00:12.92 kernel  pc=0x0000000080497934  npc=0x0000000080497938
    01:00000:00023:2012/08/17 09:00:12.92 kernel  g0-g2 0x0000000000000000 0x0000000000000000 0x0000000000000000
    01:00000:00023:2012/08/17 09:00:12.92 kernel  g3-g5 0x0000000000000000 0x0000000082042691 0x0000000000000001
    01:00000:00023:2012/08/17 09:00:12.92 kernel  g6-g7 0x0000000000000000 0xffffffff7eb00200
    01:00000:00023:2012/08/17 09:00:12.92 kernel  o0-o2 0x0000000000000001 0x0000010065c45388 0x000001004aab0d00
    01:00000:00023:2012/08/17 09:00:12.92 kernel  o3-o5 0x0000010065c453c8 0x0000000000004000 0x0000000080c0112c
    01:00000:00023:2012/08/17 09:00:12.92 kernel  o6-o7 0x0000010004bb5711 0x0000000080cc4f8c
    01:00000:00023:2012/08/17 09:00:12.92 kernel  l0-l2 0x0000000000000000 0x00000100e5067f90 0x0000000000000000
    01:00000:00023:2012/08/17 09:00:12.92 kernel  l3-l5 0x0000000081d37470 0x0000000000000000 0x00000101a733d000
    01:00000:00023:2012/08/17 09:00:12.92 kernel  l6-l7 0x0000000000000001 0x0000000000000003
    01:00000:00023:2012/08/17 09:00:12.92 kernel  i0-i2 0x000001004aa9d3d8 0xe800010065c45440 0x0000010070639058
    01:00000:00023:2012/08/17 09:00:12.92 kernel  i3-i5 0x00000100706390a8 0x0000000000000003 0x0000000000000038
    01:00000:00023:2012/08/17 09:00:12.92 kernel  i6-i7 0x0000010004bb57e1 0x00000000803c8fa0
    01:00000:00023:2012/08/17 09:00:12.92 kernel  ************************************
    01:00000:00023:2012/08/17 09:00:12.92 kernel  SQL causing error : insert into jtds_test ( bigDecimal, intField )      values ( @P0 ,  @P1 ) SELECT
    @@IDENTITY AS IDģ^V
    01:00000:00023:2012/08/17 09:00:12.92 kernel  Current statement number: 2 Current line number: 1
    01:00000:00023:2012/08/17 09:00:12.92 kernel  ************************************
    01:00000:00023:2012/08/17 09:00:12.92 server  SQL Text: insert into jtds_test ( bigDecimal, intField )      values ( @P0 ,  @P1 ) SELECT @@IDENTITY
     AS IDģ^V
    01:00000:00023:2012/08/17 09:00:12.92 kernel  curdb = 9 tempdb = 2 pstat = 0x10000
    01:00000:00023:2012/08/17 09:00:12.92 kernel  lasterror = 0 preverror = 0 transtate = 0
    01:00000:00023:2012/08/17 09:00:12.92 kernel  curcmd = 195 program = jTDS
    01:00000:00023:2012/08/17 09:00:12.92 kernel  extended error information: hostname: ___ login: ___
    01:00000:00023:2012/08/17 09:00:12.92 kernel  pc: 0x0000000080f7f268 pcstkwalk+0x24(0x0000010004bb4850, 0x0000010004bb26c8, 0x000000000000270f, 0x0
    000000000000002, 0x0000000000000000)
    01:00000:00023:2012/08/17 09:00:12.92 kernel  pc: 0x0000000080f7f0b0 ucstkgentrace+0x1d0(0x000001004aa9d3d8, 0x0000000000000002, 0x000000000000270f
    , 0x0000000000000000, 0x0000000000000000)
    01:00000:00023:2012/08/17 09:00:12.92 kernel  pc: 0x0000000080f094a4 ucbacktrace+0xb4(0x0000000000000000, 0x0000000000000001, 0x0000000000007c00, 0
    x000001004aa9d3d8, 0x000001004e6757f8)
    01:00000:00023:2012/08/17 09:00:12.92 kernel  pc: 0x00000000805a6fe4 terminate_process+0x132c(0x0000000000007e70, 0x0000000000000000, 0x000001004aa
    9d3d8, 0x0000000081c338d0, 0x0000000000009000)
    01:00000:00023:2012/08/17 09:00:12.92 kernel  pc: 0x0000000080f43148 kisignal+0x418(0x0000000000000058, 0x0000010004bb5e10, 0x0000010004bb5b30, 0x0
    000010004bb5b70, 0x000000000001adda)
    01:00000:00023:2012/08/17 09:00:12.92 kernel  pc: 0x0000000080497934 _$o1cexwZ0.s_retparams+0x20(0x000001004aa9d3d8, 0xe800010065c45440, 0x00000100
    70639058, 0x00000100706390a8, 0x0000000000000003)
    01:00000:00023:2012/08/17 09:00:12.92 kernel  pc: 0x00000000803c8fa0 s_setreturns+0x1a0(0x0000000000000001, 0x000001004aa9d3d8, 0x0000010065c45198,
     0x00000100e5067f90, 0x0000000000800000)
    01:00000:00023:2012/08/17 09:00:12.92 kernel  pc: 0x00000000803c5ba4 execproc+0x444(0x0000000000000000, 0x0000000081c33800, 0x00000000000076d0, 0x0
    000000000000000, 0x00000100e5067800)
    01:00000:00023:2012/08/17 09:00:12.92 kernel  pc: 0x00000000804215fc _$o1cexpF0.s_execute+0xa1c(0x0000000000000001, 0x000001004aa9d3d8, 0x000000000
    0000000, 0x0000000000000000, 0x00000000000000e0)
    01:00000:00023:2012/08/17 09:00:12.92 kernel  [Handler pc: 0x0000000080cc3db8 hdl_stack installed by the following function:-]
    01:00000:00023:2012/08/17 09:00:12.92 kernel  [Handler pc: 0x0000000080c73abc s_handle installed by the following function:-]
    01:00000:00023:2012/08/17 09:00:12.92 kernel  pc: 0x00000000803c6f14 sequencer+0x254(0x0000000000007b60, 0x0000000000000003, 0xffffffffffffffff, 0x0000000000000000, 0x000000008272d000)
    01:00000:00023:2012/08/17 09:00:12.92 kernel  [Handler pc: 0x0000000080e9e8c8 ut_handle installed by the following function:-]
    01:00000:00023:2012/08/17 09:00:12.92 kernel  pc: 0x00000000803d414c _$o1cexkX0.conn_hdlr+0x8c(0x000000000000009e, 0x0000000000000000, 0x0000000000007800, 0xffffffffffffffff, 0x0000000000009b14)
    01:00000:00023:2012/08/17 09:00:12.92 kernel  pc: 0x0000000080f95f74 _coldstart(0x00000000000000a1, 0x00000000803d426c, 0x0000000000000000, 0x0000000000000000, 0x0000000000000000)
    01:00000:00023:2012/08/17 09:00:12.92 kernel  end of stack trace, spid 23, kpid 676987018, suid 203
    

    Sybase version:
    Adaptive Server Enterprise/15.0.3/EBF 18902 ESD#4 ONE-OFF/P/Sun_svr4/OS 5.8/ase1503/2768/64-bit/FBO/Fri Apr 1 17:59:58 2011
    jTDS version:
    1.2.6 (the same problem occurs with earlier versions as well)

    The code:

    package foo.bar.test;
    
    import static org.junit.Assert.assertFalse;
    import static org.junit.Assert.fail;
    
    import java.math.BigDecimal;
    import java.math.RoundingMode;
    import java.sql.Connection;
    import java.sql.DriverManager;
    import java.sql.PreparedStatement;
    import java.sql.ResultSet;
    import java.sql.SQLException;
    
    import org.junit.After;
    import org.junit.Before;
    import org.junit.Test;
    
    public class TestJdtsBigDecimalSybase15 {
    
        private static final String DB_URL = "jdbc:jtds:sybase://***";
        private static final String DB_USER = "***";
        private static final String DB_PASSWORD = "***";
    
        private static final String CREATE_SQL = "CREATE TABLE testBigDecimalJtds ( "
    
                + "idField INT  IDENTITY, bigDecimalField NUMERIC(20 , 2)  NOT NULL, "
                + "intField INT NULL )";
        private static final String DROP_SQL = "DROP TABLE testBigDecimalJtds";
    
        private static final String INSERT_SQL = "INSERT INTO testBigDecimalJtds (bigDecimalField, intField) VALUES (?, ?)";
        private static final String IDENTITY_SQL = "SELECT @@IDENTITY";
    
        @Before
        public void setUp() throws Exception {
            DriverManager.registerDriver(new net.sourceforge.jtds.jdbc.Driver());
    
            Connection connection = getConnection();
            PreparedStatement stmt = connection.prepareStatement(CREATE_SQL);
            stmt.execute();
        }
    
        @After
        public void tearDown() throws Exception {
            Connection connection = getConnection();
            PreparedStatement stmt = connection.prepareStatement(DROP_SQL);
            stmt.execute();
        }
    
        private Connection getConnection() throws SQLException {
            Connection connection = DriverManager.getConnection(DB_URL, DB_USER, DB_PASSWORD);
            connection.setAutoCommit(false);
            return connection;
        }
    
        @Test
        public void test() {
            BigDecimal from;
            BigDecimal to;
            BigDecimal augend;
            try {
                from = new BigDecimal(10.00d).setScale(2, RoundingMode.HALF_UP);
                to = new BigDecimal(11.00d).setScale(2, RoundingMode.HALF_UP);
                augend = new BigDecimal(0.01d).setScale(2, RoundingMode.HALF_UP);
                for (BigDecimal i = from; i.compareTo(to) <= 0; i = i.add(augend)) {
                    doInsert(getConnection(), i);
                }
    
                from = new BigDecimal(9999999999999.00d).setScale(2, RoundingMode.HALF_UP);
                to = new BigDecimal(10000000000000.00d).setScale(2, RoundingMode.HALF_UP);
                augend = new BigDecimal(0.01d).setScale(2, RoundingMode.HALF_UP);
                for (BigDecimal i = from; i.compareTo(to) <= 0; i = i.add(augend)) {
                    doInsert(getConnection(), i);
                }
            } catch (SQLException ex) {
                ex.printStackTrace();
                fail(ex.getMessage());
            }
        }
    
        private void doInsert(Connection connection, BigDecimal bigDecimalValue) throws SQLException {
            try {
                PreparedStatement stmt = connection.prepareStatement(INSERT_SQL,
                        PreparedStatement.RETURN_GENERATED_KEYS);
    
                stmt.setBigDecimal(1, bigDecimalValue);
                stmt.setInt(2, 0);
    
                stmt.executeUpdate();
                assertFalse("nothing was inserted", 0 == stmt.getUpdateCount());
    
                stmt = connection.prepareStatement(IDENTITY_SQL);
                stmt.execute();
                ResultSet rs = stmt.getResultSet();
                if (!rs.next()) {
                    fail("no identity column returned");
                }
                assertFalse("Identity == 0", 0 == rs.getInt(1));
                rs.close();
                connection.commit();
            } catch (SQLException ex) {
                ex.printStackTrace();
                connection.rollback();
                throw ex;
            } finally {
                connection.close();
            }
        }
    }
    

    Observations:

    • works on Sybase ASE 12;
    • works without PreparedStatement.RETURN_GENERATED_KEYS, data gets inserted;
    • inserting just the BigDecimal and leaving the last argument default to NULL, works;
    • doing "INSERT INTO testBigDecimalJtds (intField, bigDecimalField) VALUES (?, ?)" and
      stmt.setInt(1, 0);
      stmt.setBigDecimal(2, bigDecimalValue);
      also works in this test case, however leaving BigDecimal as the last parameter still causes Sybase to segfault with production code (larger tables, multiple NUMERIC fields);
    • stmt.setObject(1, bigDecimalValue); also causes the same segfault;

    In this case where only two decimal places precision is required, using
    stmt.setDouble(1, bigDecimalValue.setScale(2, RoundingMode.HALF_UP).doubleValue());
    seems to do the trick as a temporary workaround, however I do not like it as a permanent solution.

    Please share your insights about this problem.

    Thanks,
    Vaidotas

     
    • momo

      momo - 2012-08-17

      Hi Vaidotas,

      at a first glance, I do not see how jTDS could directly be responsible for that SEGFAULT. The exception at the Java side is just normal, given the server side process crashed.

      Unfortunately I don't have access to an ASE 15 at the moment, so I am not able to verify the problem. But maybe you could get some help from Sybase support? Btw., did you try the jConnect driver? Does it cause crashes as well?

      Cheers,
      momo

       
  • Vaidotas

    Vaidotas - 2012-08-17

    Hi momo,

    the jConnect7 driver does not crash and passes the given test case. It returns the generated identity column ResultSet value through stmt.getGeneratedKeys(). However jConnect is not compatible with our persistence framework.
    I will try the Sybase support as well.

    Vaidotas

     
    • momo

      momo - 2012-08-19

      Thank you for clarification. Maybe I get access to an ASA 15 somehow so I can have a closer look. Please keep me updated meanwhile if you get any response from Sybase.

      Cheers,
      momo

      Vaidotas schrieb am 17.08.12 15:10:

      Hi momo,
      the jConnect7 driver does not crash and passes the given test case. It returns the generated identity column ResultSet value through stmt.getGeneratedKeys(). However jConnect is not compatible with our persistence framework.
      I will try the Sybase support as well.
      Vaidotas

      Sent from sourceforge.net because you indicated interest in https://sourceforge.net/p/jtds/discussion/104389/
      To unsubscribe from further messages, please visit https://sourceforge.net/auth/prefs/

       

Log in to post a comment.

MongoDB Logo MongoDB