Hi Julo,

Thanks for this updates and insight. Please read the in-line comments.


Julius Stroffek wrote:
Hi Saurabh,

I went through the code and here are my observations:

1.) The error related to the main issue is detected correctly in the function org.apache.derby.client.net.Request.writePlainScalarStream. It is reported throught the call to netAgent_.accumulateReadException and more errors are reported this way. Probably none of these errors are handled in a way that this issue suppose they should be. The exception reported by the 'repro' code attached to the issue is thrown by the client code it self. However, the client sends some codepoints (probably the whole request) which are sent correctly to the server and executed.
This is correct .

2.) The accumulated exceptions are checked by the following code in org.apache.derby.client.am.PreparedStatement.flowExecute(int executeType)

                if (chainAutoCommit) {
// we have encountered an error in writing the execute, so do not
                    // flow an autocommit
                    if (agent_.accumulatedReadExceptions_ != null) {
// currently, the only write exception we encounter is for // data truncation: SQLSTATE 01004, so we don't bother checking for this
                        connection_.writeCommitSubstitute_();
                        commitSubstituted = true;
                    } else {
                        // there is no write error, so flow the commit
                        connection_.writeCommit();
                    }
                }

3.) The writeCommitSubstitute function sends only a EXCSAT codepoint (exchange server attributes), thus should not affect committing or roll backing a transaction. I think that the transaction stays uncommitted after these exceptions. The writeCommit function sends RDBCMM codepoint (commit).
Correct, at this point the transaction is not committed, this only gets committed by the next select statement.

4.) I would guess, that the error bit specified in DSS header is applied only for errors detected by the server not those detected by the client. Thus in my opinion it makes no sense to change it.

5.) If you look at the page http://publib.boulder.ibm.com/html/as400/v4r5/ic2924/info/db2/rbafymstposcodes.htm, this error is described as warning (SQLSTATE 01004). Considering this and the code in derby, I think current behavior of derby was an intent. However, how should I make difference between exception thrown as a warning and an exception thrown as error? Even the code differentiating exception to errors and warning have to be really ugly. Even the different behavior of embedded driver a derby network client is not a good idea.

6.) I can see only one solution to this error - calling a writeRollback method instead of writeCommitSubstitute in the code above and handle the case when the auto commit is turned off in a similar way. This changes a behavior of derby a bit - every error will rollback the current transaction. Is it possible to do this? Any other suggestions?
I tried this approach and found the repro works absolutely fine. Following are the changes I had made :

org.apache.derby.client.am.PreparedStatement.flowExecute(int executeType)
------------ code snippet-----------------
if (chainAutoCommit) { // we have encountered an error in writing the execute, so do not
                   // flow an autocommit
                   if (agent_.accumulatedReadExceptions_ != null) {
// currently, the only write exception we encounter is for // data truncation: SQLSTATE 01004, so we don't bother checking for this
                       *//connection_.writeCommitSubstitute_();
connection_.writeLocalRollback_(); // applied RollBack Approach
                       //commitSubstituted = true;*
} else {
                       // there is no write error, so flow the commit
                       connection_.writeCommit();
                   }
               }

Well the writeLocalRollback_() method calls buildRDBRLLBCK() and sends RDBRLLBCK code-point. I am not sure that this approach can be used for all the cases. Or do we need to implement writeRollback() as a new method to handle this particular case (accumulatedReadException). Comments/Suggestions please.

Thanks,
Saurabh

Cheers

Julo

Saurabh Vyas wrote:
Hi All,

I was looking into Derby-2017 (https://issues.apache.org/jira/browse/DERBY-2017) the following were my findings : - when error occurs, then a dummyDSS is built and the partial data (which is *'this' *in the repro ) is sent across to NetworkServer. Now when the next select statement is executed, it commits the transaction and the partial data gets committed and select returns the incorrect committed data.

- I modified the repro to rollback the transaction when error occurs, then it behaves correctly.

code snippet....................

StringReader reader = new StringReader("this string is way too long");
        ps.setCharacterStream(1, reader, 5);

        try {
            ps.executeUpdate();
        } catch (SQLException e) {
            *c.rollback(); //see here*
            System.out.println(e);
        }
---------------------------------------------------

- DRDA Header specifications provides a flag which can notify that error had occurred & do not continue.

/**
     * Read DSS header
     * DSS Header format is
     *     2 bytes    - length
     *    1 byte    - 'D0'    - indicates DDM data
     *     1 byte    - DSS format
     *        |---|---------|----------|
     *        | 0    |  flags  |  type    |
     *        |---|---------|----------|
     *        | 0 | 1  2  3 | 4 5 6 7  |
     *        |---|---------|----------|
     *        bit 0 - '0'
     *        bit 1 - '0' - unchained, '1' - chained
* *bit 2 - '0' - do not continue on error, '1' - continue on error //See Here* * bit 3 - '0' - next DSS has different correlator, '1' - next DSS has
     *                        same correlator
..........
*/

- What I observed is, when error occurs (i.e. accumulateReadError) and writeCommitSubstitute is called where a dummy DSS is built (buildDummyEXCSAT()). - buildDss() method write the header information and here we should set the CONTINUE_ON_ERROR flag to '0' thus the data shold not be send to NetworkServer. Is my understanding correct? I am new to this part of derby and not familiar with the DRDA implementation.
Comments/Suggestions please.

I tried to follow Army's work on DERBY-35, but that is much target for chaining and I am not aware about Tomohito 's work in Layer B streaming. Can anyone help me out in this.

Thanks,
Saurabh

Reply via email to