All Downloads are FREE. Search and download functionalities are using the official Maven repository.

io.vertx.db2client.impl.drda.DRDAQueryResponse Maven / Gradle / Ivy

The newest version!
/*
 * Copyright (C) 2019,2020 IBM Corporation
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 * http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
package io.vertx.db2client.impl.drda;

import java.util.ArrayList;
import java.util.List;
import java.util.Objects;

import io.netty.buffer.ByteBuf;

public class DRDAQueryResponse extends DRDAConnectResponse {

//    protected boolean ensuredLengthForDecryption_ = false; // A layer lengths have already been ensured in decrypt method.
//    protected byte[] longBufferForDecryption_ = null;
//    protected int longPosForDecryption_ = 0;
//    protected ByteBuf longValueForDecryption_ = null;
//    protected int longCountForDecryption_ = 0;

    private ColumnMetaData outputColumnMetaData = null;
    private ColumnMetaData inputColumnMetaData = null;

    private Cursor cursor;

    private NetSqlca sqlca;

    private long queryInstanceId = 0;

    public DRDAQueryResponse(ByteBuf buffer, ConnectionMetaData metadata) {
        super(buffer, metadata);
    }

    public void readPrepareDescribeOutput() { // @AGG removed callback StatementCallbackInterface statement) {
        startSameIdChainParse();
        parsePRPSQLSTTreply(); // @AGG removed callback statement);
        endOfSameIdChainData();
    }

    public void readPrepareDescribeInputOutput() {
        readPrepareDescribeOutput();
        readDescribeInput();
        completePrepareDescribe();
    }

    private void completePrepareDescribe() {
        if (outputColumnMetaData == null) {
            return;
        }
        // TODO: @AGG move this stuff to non-DRDA class
//        parameters_ = expandObjectArray(parameters_, parameterMetaData_.columns_);
//        parameterSet_ = expandBooleanArray(parameterSet_, parameterMetaData_.columns_);
//        parameterRegistered_ = expandBooleanArray(parameterRegistered_, parameterMetaData_.columns_);
    }


    public void readDescribeInput(/*PreparedStatementCallbackInterface preparedStatement*/) {
        // @AGG no encryption
//        if (longBufferForDecryption_ != null) {
//            buffer_ = longBufferForDecryption_;
//            pos_ = longPosForDecryption_;
//            count_ = longCountForDecryption_;
//            if (longBufferForDecryption_ != null && count_ > longBufferForDecryption_.length) {
//                count_ = longBufferForDecryption_.length;
//            }
//            dssLength_ = 0;
//            longBufferForDecryption_ = null;
//        }

        startSameIdChainParse();
        parseDSCSQLSTTreply(/*preparedStatement, */false);
        endOfSameIdChainData();
    }

    // Parse the reply for the Describe SQL Statement Command.
    // This method handles the parsing of all command replies and reply data
    // for the dscsqlstt command.
    private void parseDSCSQLSTTreply(boolean isOutput) {
        int peekCP = parseTypdefsOrMgrlvlovrs();

        ColumnMetaData columnMetaData = new ColumnMetaData();
        if (isOutput)
            outputColumnMetaData = columnMetaData;
        else
            inputColumnMetaData = columnMetaData;

        if (peekCP == CodePoint.SQLDARD) {
            // SQLDARD here means we have some data to parse
            NetSqlca netSqlca = parseSQLDARD(columnMetaData, false);  // false means do not skip SQLDARD bytes
            NetSqlca.complete(netSqlca);
        } else if (peekCP == CodePoint.SQLCARD) {
            // SQLCARD here means there was no data to parse, just a return code
            NetSqlca netSqlca = parseSQLCARD(null);
            NetSqlca.complete(netSqlca);
        } else {
            throw new IllegalStateException("Parse describe error");
            //parseDescribeError(ps);
        }
    }

    @Deprecated // @AGG reads all data sync
    public void readOpenQuery() { // @AGG removed callback StatementCallbackInterface statement) {
        startSameIdChainParse();
        parseOPNQRYreply(); // @AGG removed callback statement);
        endOfSameIdChainData();
    }

    /**
     * Parse the reply for the Open Query Command. This method handles the
     * parsing of all command replies and reply data for the opnqry command.
     */
    public void readBeginOpenQuery() { // @AGG removed callback StatementCallbackInterface statementI) {
      startSameIdChainParse();
        int peekCP = peekCodePoint();

        if (peekCP == CodePoint.OPNQRYRM) {
          parseBeginOpenQuery();
//            parseOpenQuery(); // @AGG removed callback statementI);
//            peekCP = peekCodePoint();
//            if (peekCP == CodePoint.RDBUPDRM) {
//                parseRDBUPDRM();
//                peekCP = peekCodePoint();
//            }
        } else if (peekCP == CodePoint.RDBUPDRM) {
            parseRDBUPDRM();
            parseBeginOpenQuery();
//            parseOpenQuery(); // @AGG removed callback statementI);
//            peekCP = peekCodePoint();
        } else if (peekCP == CodePoint.OPNQFLRM) {
            parseOpenQueryFailure(); // @AGG removed callback statementI);
            //peekCP = peekCodePoint();
        } else {
            parseOpenQueryError(); // @AGG removed callback statementI);
            //peekCP = peekCodePoint();
        }

//        if (peekCP == CodePoint.PBSD) {
//            parsePBSD();
//        }
    }

    /**
     * Reads the following items:
     * - Open Query Complete (OPNQRYRM)
     * - Query Answer Set Description (QRYDSC)
     * Does NOT parse result data
     */
    private void parseBeginOpenQuery() {
        int peekCP = peekCodePoint();

        if (peekCP == CodePoint.OPNQRYRM) {
            parseOPNQRYRM(true);

            //NetSqlca sqlca = null;
            peekCP = peekCodePoint();
            if (peekCP != CodePoint.QRYDSC) {

                peekCP = parseTypdefsOrMgrlvlovrs();

                if (peekCP == CodePoint.SQLDARD) {
                    outputColumnMetaData = new ColumnMetaData();// ClientDriver.getFactory().newColumnMetaData(netAgent_.logWriter_);
                    NetSqlca netSqlca = parseSQLDARD(outputColumnMetaData, false);  // false means do not skip SQLDARD bytes

                    //For java stored procedure, we got the resultSetMetaData from server,
                    //Do we need to save the resultSetMetaData and propagate netSqlca?
                    //The following statement are doing the both, but it do more than
                    //we want. It also mark the completion of Prepare statement.
                    //
                    // this will override the same call made from parsePrepareDescribe
                    //  this will not work, this is not the DA for the stored proc params
                    //
                    // We may now receive a new SQLDARD (unrequested, a
                    // DRDA protocol extension) when a query is opened iff the
                    // underlying server's prepared statement has been recompiled
                    // since the client first received metadata when preparing the
                    // statement.
                    if (netSqlca != null) {
                        NetSqlca.complete(netSqlca);
                    }
                    peekCP = parseTypdefsOrMgrlvlovrs();
                }
                // check if the DARD is mutually exclusive with CARD, if so, then the following if should be an elese

                if (peekCP == CodePoint.SQLCARD) {
                    sqlca = parseSQLCARD(null);
                    peekCP = parseTypdefsOrMgrlvlovrs();
                }
            }
            parseQRYDSC(/*netResultSet.netCursor_*/);
        }
    }

    public void readFetch(Cursor c) {
        startSameIdChainParse();

        // Carry over state from previous request
        cursor = c;
        cursor.resetDataBuffer();
//        if (cursor != null)
//            throw new IllegalStateException("Invoking readFetch on a request that has already created a cursor");
//        cursor = new Cursor();
////        setOutputColumnMetaData(columnMetadata);
//        cursor.initializeColumnInfoArrays(Typdef.targetTypdef, columnMetadata.columns_);
//
//        cursor.qrydscTypdef_.updateColumn(cursor, i, readFastUnsignedByte(), readFastUnsignedShort());
//        Typdef.targetTypdef.updateColumn(netCursor, columnIndex, protocolLid, protocolLength);

        parseCNTQRYreply(true); // true means we expect row data
        endOfSameIdChainData();
    }

    public void readCursorClose() {
        startSameIdChainParse();
        parseCLSQRYreply();
        endOfSameIdChainData();
    }

    public long readExecuteImmediate() {
        startSameIdChainParse();
        long updateCount = parseEXCSQLIMMreply();
        endOfSameIdChainData();
        return updateCount;
    }

    public long readExecute(/*PreparedStatementCallbackInterface preparedStatement*/) {
        startSameIdChainParse();
        long updateCount = parseEXCSQLSTTreply();//preparedStatement);
        endOfSameIdChainData();
        return updateCount;
    }

    // Parse the reply for the Continue Query Command.
    // This method handles the parsing of all command replies and reply data for the cntqry command.
    // If doCopyQrydta==false, then there is no data, and we're only parsing out the sqlca to get the row count.
    private void parseCNTQRYreply(/*ResultSetCallbackInterface resultSetI, */
                                  boolean doCopyQrydta) {
        boolean found = false;
        int peekCP = peekCodePoint();
        if (peekCP == CodePoint.RDBUPDRM) {
            found = true;
            parseRDBUPDRM();
            peekCP = peekCodePoint();
        }

        if (peekCP == CodePoint.QRYDTA) {
            found = true;
            if (!doCopyQrydta) {
                throw new UnsupportedOperationException("Not implemented");
//                parseLengthAndMatchCodePoint(CodePoint.QRYDTA);
//                //we don't need to copy QRYDTA since there is no data
//                if (longValueForDecryption_ != null) {
//                    longValueForDecryption_ = null;
//                }
//                if (longBufferForDecryption_ != null) {
//                    longBufferForDecryption_ = null;
//                }
//
//                int ddmLength = getDdmLength();
//                ensureBLayerDataInBuffer(ddmLength);
//                ((ClientResultSet) resultSetI).expandRowsetSqlca();
//                NetSqlca sqlca = parseSQLCARDrow(/*((ClientResultSet) resultSetI).rowsetSqlca_*/);
//                int daNullIndicator = readFastByte();
//                adjustLengths(getDdmLength());
//                // define event interface and use the event method
//                // only get the rowCount_ if sqlca is not null and rowCount_ is unknown
//                if (sqlca != null && sqlca.containsSqlcax()) {
//                    ((ClientResultSet)resultSetI).setRowCountEvent(
//                        sqlca.getRowCount());
//                }
//
//                peekCP = peekCodePoint();
//                if (peekCP == CodePoint.SQLCARD) {
//                    NetSqlca netSqlca = parseSQLCARD(((ClientResultSet) resultSetI).rowsetSqlca_);
//                    resultSetI.completeSqlca(netSqlca);
//                }
//                if (peekCP == CodePoint.RDBUPDRM) {
//                    parseRDBUPDRM();
//                    peekCP = peekCodePoint();
//                }
//                if (peekCP == CodePoint.PBSD) {
//                    parsePBSD();
//                }
//                return;
            }
            do {
                parseQRYDTA();
                peekCP = peekCodePoint();
            } while (peekCP == CodePoint.QRYDTA);
        }

        if (peekCP == CodePoint.EXTDTA) {
            found = true;
            throw new UnsupportedOperationException("Not implemented");
//            do {
//                copyEXTDTA((NetCursor) ((ClientResultSet) resultSetI).cursor_);
//                if (longBufferForDecryption_ != null) {//encrypted EXTDTA
//                    buffer_ = longBufferForDecryption_;
//                    pos_ = longPosForDecryption_;
//                    if (longBufferForDecryption_ != null && count_ > longBufferForDecryption_.length) {
//                        count_ = longBufferForDecryption_.length;
//                    }
//                }
//
//                peekCP = peekCodePoint();
//            } while (peekCP == CodePoint.EXTDTA);
        }

        if (peekCP == CodePoint.SQLCARD) {
            found = true;
            throw new UnsupportedOperationException("Read SQLCARD on fetch");
//            ((ClientResultSet) resultSetI).expandRowsetSqlca();
//            NetSqlca netSqlca = parseSQLCARD(((ClientResultSet)resultSetI).rowsetSqlca_);
//            // for an atomic operation, the SQLCA contains the sqlcode for the first (statement
//            // terminating)error, the last warning, or zero.  all multi-row fetch operatons are
//            // atomic.  (the only operation that is not atomic is multi-row insert).
//            if (((ClientResultSet)resultSetI).sensitivity_ !=
//                ClientResultSet.sensitivity_sensitive_dynamic__) {
//
//                if (netSqlca != null && netSqlca.containsSqlcax() && netSqlca.getRowsetRowCount() == 0) {
//                    ((ClientResultSet)resultSetI).setRowCountEvent(
//                        netSqlca.getRowCount());
//                }
//            }
//            resultSetI.completeSqlca(netSqlca);
//            peekCP = peekCodePoint();
        }

        if (peekCP == CodePoint.ENDQRYRM) {
            found = true;
            parseEndQuery();
            peekCP = peekCodePoint();
        }

        if (peekCP == CodePoint.RDBUPDRM) {
            found = true;
            parseRDBUPDRM();
            peekCP = peekCodePoint();
        }

        if (!found) {
            parseFetchError();
        }

        if (peekCP == CodePoint.PBSD) {
            parsePBSD();
        }

        // TODO encryption
//        if (longBufferForDecryption_ != null) {
//            // Not a good idea to create a new buffer_
//            buffer_ = new byte[DEFAULT_BUFFER_SIZE];
//            longBufferForDecryption_ = null;
//        }
    }

    private void parseFetchError() {

        int peekCP = peekCodePoint();
        switch (peekCP) {
        case CodePoint.ABNUOWRM:
            {
                //passing the ResultSetCallbackInterface implementation will
                //help in retrieving the the UnitOfWorkListener that needs to
                //be rolled back
                throw new IllegalStateException("Abnormal UOW end");
//                NetSqlca sqlca = parseAbnormalEndUow(resultSetI);
//                resultSetI.completeSqlca(sqlca);
//                break;
            }
        case CodePoint.CMDCHKRM:
            parseCMDCHKRM();
            break;
        case CodePoint.CMDNSPRM:
            parseCMDNSPRM();
            break;
        case CodePoint.QRYNOPRM:
            parseQRYNOPRM();
            break;
        case CodePoint.RDBNACRM:
            parseRDBNACRM();
            break;
        default:
            parseCommonError(peekCP);
        }
    }

    // Query Not Opened Reply Message is issued if a CNTQRY or CLSQRY
    // command is issued for a query that is not open.  A previous
    // ENDQRYRM, ENDUOWRM, or ABNUOWRM reply message might have
    // terminated the command.
    // PROTOCOL architects the SQLSTATE value depending on SVRCOD
    // SVRCOD 4 -> SQLSTATE is 24501
    // SVRCOD 8 -> SQLSTATE of 58008 or 58009
    //
    // if SVRCOD is 4 then SQLSTATE 24501, SQLCODE -501
    // else SQLSTATE 58009, SQLCODE -30020
    //
    // Messages
    // SQLSTATE : 24501
    //     The identified cursor is not open.
    //     SQLCODE : -501
    //     The cursor specified in a FETCH or CLOSE statement is not open.
    //     The statement cannot be processed.
    // SQLSTATE : 58009
    //     Execution failed due to a distribution protocol error that caused deallocation of the conversation.
    //     SQLCODE : -30020
    //     Execution failed because of a Distributed Protocol
    //         Error that will affect the successful execution of subsequent
    //         commands and SQL statements: Reason Code .
    //     Some possible reason codes include:
    //     121C Indicates that the user is not authorized to perform the requested command.
    //     1232 The command could not be completed because of a permanent error.
    //         In most cases, the server will be in the process of an abend.
    //     220A The target server has received an invalid data description.
    //         If a user SQLDA is specified, ensure that the fields are
    //         initialized correctly. Also, ensure that the length does not exceed
    //         the maximum allowed length for the data type being used.
    //
    //     The command or statement cannot be processed.  The current
    //         transaction is rolled back and the application is disconnected
    //         from the remote database.
    //
    // Returned from Server:
    // SVRCOD - required  (4 - WARNING, 8 - ERROR)
    // RDBNAM - required
    // PKGNAMCSN - required
    //
    private void parseQRYNOPRM(/*ResultSetCallbackInterface resultSet*/) {
        boolean svrcodReceived = false;
        int svrcod = CodePoint.SVRCOD_INFO;
        boolean rdbnamReceived = false;
        String rdbnam = null;
        boolean pkgnamcsnReceived = false;
        Object pkgnamcsn = null;

        parseLengthAndMatchCodePoint(CodePoint.QRYNOPRM);
        pushLengthOnCollectionStack();
        int peekCP = peekCodePoint();

        while (peekCP != END_OF_COLLECTION) {

            boolean foundInPass = false;

            if (peekCP == CodePoint.SVRCOD) {
                foundInPass = true;
                svrcodReceived = checkAndGetReceivedFlag(svrcodReceived);
                svrcod = parseSVRCOD(CodePoint.SVRCOD_WARNING, CodePoint.SVRCOD_ERROR);
                peekCP = peekCodePoint();
            }

            if (peekCP == CodePoint.RDBNAM) {
                foundInPass = true;
                rdbnamReceived = checkAndGetReceivedFlag(rdbnamReceived);
                rdbnam = parseRDBNAM(true);
                peekCP = peekCodePoint();
            }

            if (peekCP == CodePoint.PKGNAMCSN) {
                foundInPass = true;
                pkgnamcsnReceived = checkAndGetReceivedFlag(pkgnamcsnReceived);
                pkgnamcsn = parsePKGNAMCSN(true);
                peekCP = peekCodePoint();
            }

            if (!foundInPass) {
                throwUnknownCodepoint(peekCP);
            }

        }
        popCollectionStack();
        if (!svrcodReceived)
            throwMissingRequiredCodepoint("SVRCOD", CodePoint.SVRCOD);
        if (!rdbnamReceived)
            throwMissingRequiredCodepoint("RDBNAM", CodePoint.RDBNAM);
        if (!pkgnamcsnReceived)
            throwMissingRequiredCodepoint("PKGNAMCSN", CodePoint.PKGNAMCSN);

//        netAgent_.setSvrcod(svrcod);
        if (svrcod == CodePoint.SVRCOD_WARNING) {
//            netAgent_.accumulateReadException(new SqlException(netAgent_.logWriter_,
//                new ClientMessageId(SQLState.DRDA_CURSOR_NOT_OPEN)));
            throw new IllegalStateException("DRDA_CURSOR_NOT_OPEN");
        } else {
//            agent_.accumulateChainBreakingReadExceptionAndThrow(new DisconnectException(agent_,
//                new ClientMessageId(SQLState.DRDA_CONNECTION_TERMINATED),
//                    SqlException.getMessageUtil().
//                    getTextMessage(MessageId.CONN_CURSOR_NOT_OPEN)));
            throw new IllegalStateException("DRDA_CURSOR_NOT_OPEN");
        }
    }

    // Parse the reply for the Execute SQL Statement Command.
    // This method handles the parsing of all command replies and reply data
    // for the excsqlstt command.
    // Also called by ClientCallableStatement.readExecuteCall()
    private long parseEXCSQLSTTreply(/*StatementCallbackInterface statementI*/) {
        // first handle the transaction component, which consists of one or more
        // reply messages indicating the transaction state.
        // These are ENDUOWRM, CMMRQSRM, or RDBUPDRM.  If RDBUPDRM is returned,
        // it may be followed by ENDUOWRM or CMMRQSRM
        int peekCP = peekCodePoint();
        if (peekCP == CodePoint.RDBUPDRM) {
            parseRDBUPDRM();
            peekCP = peekCodePoint();
        }

        if (peekCP == CodePoint.ENDUOWRM) {
            parseENDUOWRM();//statementI.getConnectionCallbackInterface());
            peekCP = peekCodePoint();
        }

        // Check for a RSLSETRM, this is first rm of the result set summary component
        // which would be returned if a stored procedure was called which returned result sets.
        if (peekCP == CodePoint.RSLSETRM) {
            parseResultSetProcedure();
            peekCP = peekCodePoint();
            if (peekCP == CodePoint.RDBUPDRM) {
                parseRDBUPDRM();
                peekCP = peekCodePoint();
            }

            if (peekCP == CodePoint.PBSD) {
                parsePBSD();
            }
            return 0;
        }

        // check for a possible TYPDEFNAM or TYPDEFOVR which may be present
        // before the SQLCARD or SQLDTARD.
        peekCP = parseTypdefsOrMgrlvlovrs();

        // an SQLCARD may be retunred if there was no output data, result sets or parameters,
        // or in the case of an error.
        long updateCount = 0;
        if (peekCP == CodePoint.SQLCARD) {
            NetSqlca netSqlca = parseSQLCARD(null);

            //statementI.completeExecute(netSqlca);
            NetSqlca.complete(netSqlca);
            updateCount = netSqlca == null ? 0 : netSqlca.getUpdateCount();
            peekCP = peekCodePoint();
        } else if (peekCP == CodePoint.SQLDTARD) {
            throw new UnsupportedOperationException("stored procedure");
//            // in the case of singleton select or if a stored procedure was called which had
//            // parameters but no result sets, an SQLSTARD may be returned
//            // keep the PreparedStatementCallbackInterface, since only preparedstatement and callablestatement
//            // has parameters or singleton select which translates to sqldtard.
//            NetSqldta netSqldta = null;
//            boolean useCachedSingletonRowData = false;
//            if (((ClientStatement)statementI).cachedSingletonRowData_ == null) {
//                netSqldta = new NetSqldta(netAgent_);
//            } else {
//                netSqldta = (NetSqldta)((ClientStatement) statementI).
//                    cachedSingletonRowData_;
//                netSqldta.resetDataBuffer();
//                netSqldta.extdtaData_.clear();
//                useCachedSingletonRowData = true;
//            }
//            NetSqlca netSqlca =
//                    parseSQLDTARD(netSqldta);
//
//            // there may be externalized LOB data which also gets returned.
//            peekCP = peekCodePoint();
//            while (peekCP == CodePoint.EXTDTA) {
//                copyEXTDTA(netSqldta);
//                peekCP = peekCodePoint();
//            }
//            statementI.completeExecuteCall(netSqlca, netSqldta);
        } else {
            // if here, then assume an error reply message was returned.
            parseExecuteError();
        }

        if (peekCP == CodePoint.PBSD) {
            parsePBSD();
            peekCP = peekCodePoint();
        }
        return updateCount;
    }

    private void parseResultSetProcedure(/*StatementCallbackInterface statementI*/) {
        // when a stored procedure is called which returns result sets,
        // the next thing to be returned after the optional transaction component
        // is the summary component.
        //
        // Parse the Result Set Summary Component which consists of a
        // Result Set Reply Message, SQLCARD or SQLDTARD, and an SQL Result Set
        // Reply data object.  Also check for possible TYPDEF overrides before the
        // OBJDSSs.
        // This method returns an ArrayList of generated sections which contain the
        // package and section information for the result sets which were opened on the
        // server.

        // the result set summary component consists of a result set reply message.
        List
sectionAL = parseRSLSETRM(); // following the RSLSETRM is an SQLCARD or an SQLDTARD. check for a // TYPDEFNAM or TYPDEFOVR before looking for these objects. int peekCP = parseTypdefsOrMgrlvlovrs(); // The SQLCARD and the SQLDTARD are mutually exclusive. // The SQLDTARD is returned if the stored procedure had parameters. // (Note: the SQLDTARD contains an sqlca also. this is the sqlca for the // stored procedure call. // Cursor netSqldta = null; NetSqlca netSqlca = null; if (peekCP == CodePoint.SQLCARD) { netSqlca = parseSQLCARD(null); } else { // keep the PreparedStatementCallbackInterface, since only preparedstatement and callablestatement // has parameters or singleton select which translates to sqldtard. cursor = new Cursor(metadata); netSqlca = parseSQLDTARD();//netSqldta); } // check for a possible TYPDEFNAM or TYPDEFOVR // before the SQL Result Set Reply Data object peekCP = parseTypdefsOrMgrlvlovrs(); int numberOfResultSets = parseSQLRSLRD(sectionAL); // The result set summary component parsed above indicated how many result sets were opened // by the stored pocedure call. It contained section information for // each of these result sets. Loop through the section array and // parse the result set component for each of the retunred result sets. if(true) throw new UnsupportedOperationException("Results for stored procedures not implemented"); // NetResultSet[] resultSets = new NetResultSet[numberOfResultSets]; // for (int i = 0; i < numberOfResultSets; i++) { // // parse the result set component of the stored procedure reply. // NetResultSet netResultSet = parseResultSetCursor(statementI, sectionAL.get(i)); // resultSets[i] = netResultSet; // } // LOBs may have been returned for one of the stored procedure parameters so // check for any externalized data. peekCP = peekCodePoint(); while (peekCP == CodePoint.EXTDTA) { copyEXTDTA(); peekCP = peekCodePoint(); } // statementI.completeExecuteCall(netSqlca, cursor, resultSets); completeExecute(netSqlca); } public void completeExecute(NetSqlca sqlca) { if (sqlca == null) { return; } int sqlcode = sqlca.getSqlCode(); if (sqlcode < 0) { throw new IllegalStateException("" + sqlcode); // agent_.accumulateReadException(new SqlException(agent_.logWriter_, sqlca)); } else { long updateCount_ = sqlca.getUpdateCount(); // TODO: @AGG return this? // sometime for call statement, protocol will return updateCount_, we will always set that to 0 // sqlMode_ is not set for statements, only for prepared statements // if (sqlMode_ == isCall__) { // updateCount_ = -1L; // } // Sqlcode 466 indicates a call statement has issued and result sets returned. // This is a good place to set some state variable to indicate result sets are open // for call, so that when autocommit is true, commit will not be issued until the // result sets are closed. // Currently, commit is not issued even there is no result set. // do not externalize sqlcode +100 if (sqlcode > 0 && sqlcode != 466 && sqlcode != 100) { System.out.println("WARN: sqlcode: " + sqlcode); // accumulateWarning(new SqlWarning(agent_.logWriter_, sqlca)); } } } void copyEXTDTA() { // try { parseLengthAndMatchCodePoint(CodePoint.EXTDTA); byte[] data = null; // TODO @AGG encryption // if (longValueForDecryption_ == null) { //data = (getData(null)).toByteArray(); data = getData().array(); // } else { // data = longValueForDecryption_; // dssLength_ = 0; // longValueForDecryption_ = null; // } cursor.extdtaData_.add(data); // } catch (OutOfMemoryError e) { // agent_.accumulateChainBreakingReadExceptionAndThrow(new DisconnectException(agent_, // new ClientMessageId(SQLState.NET_LOB_DATA_TOO_LARGE_FOR_JVM), e)); // } } private int parseSQLRSLRD(List
sections) { parseLengthAndMatchCodePoint(CodePoint.SQLRSLRD); return parseSQLRSLRDarray(sections); } // SQLRSLRD : FDOCA EARLY ARRAY // Data Array of a Result Set // // FORMAT FOR ALL SQLAM LEVELS // SQLNUMROW; ROW LID 0x68; ELEMENT TAKEN 0(all); REP FACTOR 1 // SQLRSROW; ROW LID 0x6F; ELEMENT TAKEN 0(all); REP FACTOR 0(all) // // SQL Result Set Reply Data (SQLRSLRD) is a byte string that specifies // information about result sets returned as reply data in the response to // an EXCSQLSTT command that invokes a stored procedure private int parseSQLRSLRDarray(List
sections) { int numOfResultSets = parseSQLNUMROW(); for (int i = 0; i < numOfResultSets; i++) { parseSQLRSROW(sections.get(i)); } return numOfResultSets; } // SQLRSROW : FDOCA EARLY ROW // SQL Row Description for One Result Set Row // // FORMAT FOR ALL SQLAM LEVELS // SQLRSGRP; GROUP LID 0x5F; ELEMENT TAKEN 0(all); REP FACTOR 1 private void parseSQLRSROW(Section section) { parseSQLRSGRP(section); } // SQLRSGRP : EARLY FDOCA GROUP // SQL Result Set Group Description // // FORMAT FOR SQLAM >= 7 // SQLRSLOCATOR; PROTOCOL TYPE RSL; ENVLID 0x14; Length Override 4 // SQLRSNAME_m; PROTOCOL TYPE VCM; ENVLID 0x3E; Length Override 255 // SQLRSNAME_s; PROTOCOL TYPE VCS; ENVLID 0x32; Length Override 255 // SQLRSNUMROWS; PROTOCOL TYPE I4; ENVLID 0x02; Length Override 4 private void parseSQLRSGRP(Section section) { int rsLocator = buffer.readInt();//readInt(); String rsName = parseVCMorVCS(); // ignore length change bt SQLAM 6 and 7 int rsNumRows = buffer.readInt();//readInt(); // currently rsLocator and rsNumRows are not being used. // section.setCursorName(rsName); } private String parseVCMorVCS() { String stringToBeSet = null; int vcm_length = readUnsignedShort(); if (vcm_length > 0) { stringToBeSet = readString(vcm_length, Typdef.targetTypdef.getCcsidMbcEncoding()); } int vcs_length = readUnsignedShort(); if (vcm_length > 0 && vcs_length > 0) { throw new IllegalStateException("NET_VCM_VCS_LENGTHS_INVALID"); // agent_.accumulateChainBreakingReadExceptionAndThrow(new DisconnectException(agent_, // new ClientMessageId(SQLState.NET_VCM_VCS_LENGTHS_INVALID))); } else if (vcs_length > 0) { stringToBeSet = readString(vcs_length, Typdef.targetTypdef.getCcsidSbcEncoding()); } return stringToBeSet; } // SQL Data Reply Data consists of output data from the relational database (RDB) // processing of an SQL statement. It also includes a description of the data. // // Returned from Server: // FDODSC - required // FDODTA - required private NetSqlca parseSQLDTARD() { //Cursor netSqldta) { boolean fdodscReceived = false; boolean fdodtaReceived = false; parseLengthAndMatchCodePoint(CodePoint.SQLDTARD); pushLengthOnCollectionStack(); NetSqlca netSqlca = null; int peekCP = peekCodePoint(); while (peekCP != END_OF_COLLECTION) { boolean foundInPass = false; if (peekCP == CodePoint.FDODSC) { foundInPass = true; fdodscReceived = checkAndGetReceivedFlag(fdodscReceived); parseFDODSC();//netSqldta); peekCP = peekCodePoint(); } if (peekCP == CodePoint.FDODTA) { foundInPass = true; fdodtaReceived = checkAndGetReceivedFlag(fdodtaReceived); netSqlca = parseFDODTA();//netSqldta); peekCP = peekCodePoint(); } if (!foundInPass) { throwUnknownCodepoint(peekCP); } } popCollectionStack(); if (!fdodscReceived) throwMissingRequiredCodepoint("FDODSC", CodePoint.FDODSC); if (!fdodtaReceived) throwMissingRequiredCodepoint("FDODTA", CodePoint.FDODTA); cursor.calculateColumnOffsetsForRow(); return netSqlca; } private void parseFDODSC() { parseLengthAndMatchCodePoint(CodePoint.FDODSC); parseSQLDTARDarray(false); // false means don't just skip the bytes } private NetSqlca parseFDODTA() { parseLengthAndMatchCodePoint(CodePoint.FDODTA); int ddmLength = getDdmLength(); ensureBLayerDataInBuffer(ddmLength); int start = buffer.readerIndex(); // mark(); NetSqlca netSqlca = parseSQLCARDrow(null); // int length = getFastSkipSQLCARDrowLength(); int length = buffer.readerIndex() - start; adjustLengths(length); parseFastSQLDTARDdata();//netCursor); return netSqlca; } private void parseFastSQLDTARDdata() { parseSQLDTARDdata(); // netCursor.dataBufferStream_ = getFastData(netCursor.dataBufferStream_); // netCursor.dataBuffer_ = netCursor.dataBufferStream_.toByteArray(); // netCursor.lastValidBytePosition_ = netCursor.dataBuffer_.length; } // RDB Result Set Reply Message (RSLSETRM) indicates that an // EXCSQLSTT command invoked a stored procedure, that the execution // of the stored procedure generated one or more result sets, and // additional information aobut these result sets follows the SQLCARD and // SQLDTARD in the reply data of the response // // Returned from Server: // SVRCOD - required (0 INFO) // PKGSNLST - required // SRVDGN - optional private List
parseRSLSETRM() { boolean svrcodReceived = false; int svrcod = CodePoint.SVRCOD_INFO; boolean pkgsnlstReceived = false; List
pkgsnlst = null; parseLengthAndMatchCodePoint(CodePoint.RSLSETRM); pushLengthOnCollectionStack(); int peekCP = peekCodePoint(); while (peekCP != END_OF_COLLECTION) { boolean foundInPass = false; if (peekCP == CodePoint.SVRCOD) { foundInPass = true; svrcodReceived = checkAndGetReceivedFlag(svrcodReceived); svrcod = parseSVRCOD(CodePoint.SVRCOD_INFO, CodePoint.SVRCOD_INFO); peekCP = peekCodePoint(); } if (peekCP == CodePoint.PKGSNLST) { // contain repeatable PKGNAMCSN foundInPass = true; pkgsnlstReceived = checkAndGetReceivedFlag(pkgsnlstReceived); pkgsnlst = parsePKGSNLST(); peekCP = peekCodePoint(); } if (!foundInPass) { throwUnknownCodepoint(peekCP); // doPrmnsprmSemantics(peekCP); } } popCollectionStack(); if (!svrcodReceived) throwMissingRequiredCodepoint("SVRCOD", CodePoint.SVRCOD); if (!pkgsnlstReceived) throwMissingRequiredCodepoint("PKGSNLST", CodePoint.PKGSNLST); // netAgent_.setSvrcod(svrcod); return pkgsnlst; } // RDB Package Namce, Consistency Token, and Section Number List // specifies a list of fully qualified names of specific sections // within one or more packages. private List
parsePKGSNLST() { ArrayList
pkgsnlst = new ArrayList
(); parseLengthAndMatchCodePoint(CodePoint.PKGSNLST); pushLengthOnCollectionStack(); while (peekCodePoint() != END_OF_COLLECTION) { pkgsnlst.add(parsePKGNAMCSN(false)); } popCollectionStack(); return pkgsnlst; } // RDB Package name, consistency token, and section number // specifies the fully qualified name of a relational // database package, its consistency token, and a specific // section within a package. // // Only called for generated secctions from a callable statement. // Section parsePKGNAMCSN(boolean skip) { parseLengthAndMatchCodePoint(CodePoint.PKGNAMCSN); if (skip) { skipBytes(); return null; } // Still need to populate the logical members in case of an "set current packageset" String rdbnam = null; String rdbcolid = null; String pkgid = null; byte[] pkgcnstkn = null; int pkgsn = 0; byte[] pkgnamcsnBytes = null; int pkgnamcsnLength = 0; int ddmLength = getDdmLength(); int offset = 0; ensureBLayerDataInBuffer(ddmLength); int maxDDMlength; // if (netAgent_.netConnection_.databaseMetaData_.serverSupportLongRDBNAM()) { maxDDMlength = 781 - DRDAConstants.PKG_IDENTIFIER_MAX_LEN + DRDAConstants.RDBNAM_MAX_LEN; // } else { // maxDDMlength = 781; // } if (ddmLength == 64) { // read all the bytes except the section number into the byte[] for caching pkgnamcsnLength = ddmLength - 2; //pkgnamcsnBytes = readBytes (pkgnamcsnLength); pkgnamcsnBytes = new byte[pkgnamcsnLength]; // readFast() does a read without moving the read head. offset = peekFastBytes(pkgnamcsnBytes, offset, pkgnamcsnLength); // populate the logical members rdbnam = readFastString(18); // RDB name rdbcolid = readFastString(18); // RDB Collection ID pkgid = readFastString(18); // RDB Package ID pkgcnstkn = readFastBytes(8); // Package Consistency Token } else if ((ddmLength >= 71) && (ddmLength <= maxDDMlength)) { // this is the new SCLDTA format. // new up a byte[] to cache all the bytes except the 2-byte section number pkgnamcsnBytes = new byte[ddmLength - 2]; // get rdbnam int scldtaLen = peekFastLength(); int maxRDBlength = DRDAConstants.RDBNAM_MAX_LEN; // ((netAgent_.netConnection_.databaseMetaData_.serverSupportLongRDBNAM())? // NetConfiguration.RDBNAM_MAX_LEN // : NetConfiguration.PKG_IDENTIFIER_MAX_LEN); if (scldtaLen < DRDAConstants.PKG_IDENTIFIER_FIXED_LEN || scldtaLen > maxRDBlength) { throw new IllegalStateException("NET_SQLCDTA_INVALID_FOR_RDBNAM " + scldtaLen); // agent_.accumulateChainBreakingReadExceptionAndThrow( // new DisconnectException(agent_, // new ClientMessageId( // SQLState.NET_SQLCDTA_INVALID_FOR_RDBNAM), // scldtaLen)); // return null; } // read 2+scldtaLen number of bytes from the reply buffer into the pkgnamcsnBytes //offset = readBytes (pkgnamcsnBytes, offset, 2+scldtaLen); offset = peekFastBytes(pkgnamcsnBytes, offset, 2 + scldtaLen); skipFastBytes(2); rdbnam = readFastString(scldtaLen); // get rdbcolid scldtaLen = peekFastLength(); if (scldtaLen < 18 || scldtaLen > 255) { throw new IllegalStateException("NET_SQLCDTA_INVALID_FOR_RDBCOLID " + scldtaLen); // agent_.accumulateChainBreakingReadExceptionAndThrow(new DisconnectException(agent_, // new ClientMessageId(SQLState.NET_SQLCDTA_INVALID_FOR_RDBCOLID), // scldtaLen)); // return null; } // read 2+scldtaLen number of bytes from the reply buffer into the pkgnamcsnBytes offset = peekFastBytes(pkgnamcsnBytes, offset, 2 + scldtaLen); skipFastBytes(2); rdbcolid = readFastString(scldtaLen); // get pkgid scldtaLen = peekFastLength(); if (scldtaLen < 18 || scldtaLen > 255) { throw new IllegalStateException("NET_SQLCDTA_INVALID_FOR_PKGID " + scldtaLen); // agent_.accumulateChainBreakingReadExceptionAndThrow(new DisconnectException(agent_, // new ClientMessageId(SQLState.NET_SQLCDTA_INVALID_FOR_PKGID), // scldtaLen)); // return null; // To make compiler happy. } // read 2+scldtaLen number of bytes from the reply buffer into the pkgnamcsnBytes offset = peekFastBytes(pkgnamcsnBytes, offset, 2 + scldtaLen); skipFastBytes(2); pkgid = readFastString(scldtaLen); // get consistency token offset = peekFastBytes(pkgnamcsnBytes, offset, 8); pkgcnstkn = readFastBytes(8); } else { throw new IllegalStateException("NET_PGNAMCSN_INVALID_AT_SQLAM " + ddmLength); // agent_.accumulateChainBreakingReadExceptionAndThrow(new DisconnectException(agent_, // new ClientMessageId(SQLState.NET_PGNAMCSN_INVALID_AT_SQLAM), // ddmLength, netAgent_.targetSqlam_)); // return null; // To make compiler happy. } pkgsn = readFastUnsignedShort(); // Package Section Number. adjustLengths(ddmLength); // // this is a server generated section // // the -1 is set for holdability and it is not used for generated sections // Section section = new Section(pkgid, pkgsn, null, -1, true); // section.setPKGNAMCBytes(pkgnamcsnBytes); // return section; throw new UnsupportedOperationException("Server generated sections not implemented"); } private void parseExecuteError() { int peekCP = peekCodePoint(); switch (peekCP) { case CodePoint.ABNUOWRM: { throw new IllegalStateException("Abnormal end UOW"); // //passing the StatementCallbackInterface implementation will // //help in retrieving the the UnitOfWorkListener that needs to // //be rolled back // NetSqlca sqlca = parseAbnormalEndUow(statementI); // statementI.completeSqlca(sqlca); // break; } case CodePoint.CMDCHKRM: parseCMDCHKRM(); break; case CodePoint.DTAMCHRM: parseDTAMCHRM(); break; case CodePoint.OBJNSPRM: parseOBJNSPRM(); break; case CodePoint.RDBNACRM: parseRDBNACRM(); break; case CodePoint.SQLERRRM: { NetSqlca sqlca = parseSqlErrorCondition(); NetSqlca.complete(sqlca); //statementI.completeSqlca(sqlca); break; } default: parseCommonError(peekCP); break; } } // Parse the reply for the Close Query Command. // This method handles the parsing of all command replies and reply data // for the clsqry command. private void parseCLSQRYreply() { int peekCP = parseTypdefsOrMgrlvlovrs(); if (peekCP == CodePoint.SQLCARD) { NetSqlca netSqlca = parseSQLCARD(null); //@f48553sxg - null means rowsetSqlca_ is null // Set the cursor state if null SQLCA or sqlcode is equal to 0. if (netSqlca != null) { int sqlcode = netSqlca.getSqlCode(); if (sqlcode == 100 || sqlcode == 20237) { cursor.setAllRowsReceivedFromServer(true); } else { NetSqlca.complete(netSqlca); } } } else { throwUnknownCodepoint(peekCP); // parseCloseError(resultSet); } } /** * Reads the bytes for the current QRYDTA into the cursor's buffer * @return */ public boolean readOpenQueryData() { int peekCP = peekCodePoint(); if (peekCP == CodePoint.QRYDTA) { parseQRYDTA(/*NetResultSet*/); return true; } return false; } public boolean isQueryComplete() { if (cursor.allRowsReceivedFromServer()) return true; int peekCP = peekCodePoint(); boolean isQueryComplete = (peekCP == CodePoint.SQLCARD || peekCP == CodePoint.ENDQRYRM); if (isQueryComplete) cursor.setAllRowsReceivedFromServer(true); return isQueryComplete; } public void readEndOpenQuery() { int peekCP = peekCodePoint(); if (peekCP == CodePoint.SQLCARD) { NetSqlca netSqlca = parseSQLCARD(null); NetSqlca.complete(netSqlca); peekCP = peekCodePoint(); } if (peekCP == CodePoint.ENDQRYRM) { parseEndQuery(/*netResultSet*/); } completeOpenQuery(sqlca); endOfSameIdChainData(); } // Parse the reply for the Execute Immediate SQL Statement Command. // This method handles the parsing of all command replies and reply data // for the excsqlimm command. private long parseEXCSQLIMMreply() { int peekCP = parseTypdefsOrMgrlvlovrs(); if (peekCP == CodePoint.RDBUPDRM) { parseRDBUPDRM(); peekCP = parseTypdefsOrMgrlvlovrs(); } long updateCount = 0; switch (peekCP) { case CodePoint.ENDUOWRM: parseENDUOWRM(); parseTypdefsOrMgrlvlovrs(); case CodePoint.SQLCARD: NetSqlca netSqlca = parseSQLCARD(null); if (netSqlca != null) { NetSqlca.complete(netSqlca, 100); // sqlcode=100 means no rows updated if (netSqlca.getSqlCode() >= 0) { updateCount = netSqlca.getUpdateCount(); } } break; default: parseExecuteImmediateError(); break; } peekCP = peekCodePoint(); if (peekCP == CodePoint.PBSD) { parsePBSD(); } return updateCount; } private void parseExecuteImmediateError() { int peekCP = peekCodePoint(); switch (peekCP) { case CodePoint.ABNUOWRM: { throw new IllegalStateException("Abnormal ending to UOW"); // //passing the StatementCallbackInterface implementation will // //help in retrieving the the UnitOfWorkListener that needs to // //be rolled back // NetSqlca sqlca = parseAbnormalEndUow(); // statement.completeSqlca(sqlca); // break; } case CodePoint.CMDCHKRM: parseCMDCHKRM(); break; case CodePoint.DTAMCHRM: parseDTAMCHRM(); break; case CodePoint.OBJNSPRM: parseOBJNSPRM(); break; case CodePoint.RDBNACRM: parseRDBNACRM(); break; case CodePoint.SQLERRRM: { NetSqlca sqlca = parseSqlErrorCondition(); NetSqlca.complete(sqlca); break; } default: throwUnknownCodepoint(peekCP); break; } } /** * Parse the reply for the Open Query Command. This method handles the * parsing of all command replies and reply data for the opnqry command. * will be replaced by parseOPNQRYreply (see parseOPNQRYreplyProto) * @param statementI statement to invoke callbacks on */ private void parseOPNQRYreply() { // @AGG removed callback StatementCallbackInterface statementI) { int peekCP = peekCodePoint(); if (peekCP == CodePoint.OPNQRYRM) { parseOpenQuery(); // @AGG removed callback statementI); peekCP = peekCodePoint(); if (peekCP == CodePoint.RDBUPDRM) { parseRDBUPDRM(); peekCP = peekCodePoint(); } } else if (peekCP == CodePoint.RDBUPDRM) { parseRDBUPDRM(); parseOpenQuery(); // @AGG removed callback statementI); peekCP = peekCodePoint(); } else if (peekCP == CodePoint.OPNQFLRM) { parseOpenQueryFailure(); // @AGG removed callback statementI); //peekCP = peekCodePoint(); } else { parseOpenQueryError(); // @AGG removed callback statementI); //peekCP = peekCodePoint(); } if (peekCP == CodePoint.PBSD) { parsePBSD(); } } private void parseOpenQueryError() { int peekCP = peekCodePoint(); switch (peekCP) { case CodePoint.ABNUOWRM: { //passing the StatementCallbackInterface implementation will //help in retrieving the the UnitOfWorkListener that needs to //be rolled back NetSqlca sqlca = parseAbnormalEndUow(); NetSqlca.complete(sqlca); // statementI.completeSqlca(sqlca); break; } case CodePoint.CMDCHKRM: parseCMDCHKRM(); break; case CodePoint.DTAMCHRM: parseDTAMCHRM(); break; case CodePoint.OBJNSPRM: parseOBJNSPRM(); break; case CodePoint.QRYPOPRM: parseQRYPOPRM(); break; case CodePoint.RDBNACRM: parseRDBNACRM(); break; default: parseCommonError(peekCP); } } /** * Perform necessary actions for parsing of a ABNUOWRM message. * * @param connection an implementation of the ConnectionCallbackInterface * * @return an NetSqlca object obtained from parsing the ABNUOWRM */ private NetSqlca parseAbnormalEndUow() { parseABNUOWRM(); if (peekCodePoint() != CodePoint.SQLCARD) { parseTypdefsOrMgrlvlovrs(); } NetSqlca netSqlca = parseSQLCARD(null); // if(ExceptionUtil.getSeverityFromIdentifier(netSqlca.getSqlState()) > // ExceptionSeverity.STATEMENT_SEVERITY || uwl == null) // connection.completeAbnormalUnitOfWork(); // else // connection.completeAbnormalUnitOfWork(uwl); return netSqlca; } // Query Previously Opened Reply Message is issued when an // OPNQRY command is issued for a query that is already open. // A previous OPNQRY command might have opened the query // which may not be closed. // PROTOCOL Architects an SQLSTATE of 58008 or 58009. // // Messages // SQLSTATE : 58009 // Execution failed due to a distribution protocol error that caused deallocation of the conversation. // SQLCODE : -30020 // Execution failed because of a Distributed Protocol // Error that will affect the successful execution of subsequent // commands and SQL statements: Reason Code . // Some possible reason codes include: // 121C Indicates that the user is not authorized to perform the requested command. // 1232 The command could not be completed because of a permanent error. // In most cases, the server will be in the process of an abend. // 220A The target server has received an invalid data description. // If a user SQLDA is specified, ensure that the fields are // initialized correctly. Also, ensure that the length does not // exceed the maximum allowed length for the data type being used. // // The command or statement cannot be processed. The current // transaction is rolled back and the application is disconnected // from the remote database. // // // Returned from Server: // SVRCOD - required (8 - ERROR) // RDBNAM - required // PKGNAMCSN - required // SRVDGN - optional // private void parseQRYPOPRM() { boolean svrcodReceived = false; int svrcod = CodePoint.SVRCOD_INFO; boolean rdbnamReceived = false; String rdbnam = null; boolean pkgnamcsnReceived = false; Object pkgnamcsn = null; parseLengthAndMatchCodePoint(CodePoint.QRYPOPRM); pushLengthOnCollectionStack(); int peekCP = peekCodePoint(); while (peekCP != END_OF_COLLECTION) { boolean foundInPass = false; if (peekCP == CodePoint.SVRCOD) { foundInPass = true; svrcodReceived = checkAndGetReceivedFlag(svrcodReceived); svrcod = parseSVRCOD(CodePoint.SVRCOD_ERROR, CodePoint.SVRCOD_ERROR); peekCP = peekCodePoint(); } if (peekCP == CodePoint.RDBNAM) { foundInPass = true; rdbnamReceived = checkAndGetReceivedFlag(rdbnamReceived); rdbnam = parseRDBNAM(true); peekCP = peekCodePoint(); } if (peekCP == CodePoint.PKGNAMCSN) { foundInPass = true; pkgnamcsnReceived = checkAndGetReceivedFlag(pkgnamcsnReceived); pkgnamcsn = parsePKGNAMCSN(true); peekCP = peekCodePoint(); } if (!foundInPass) { throwUnknownCodepoint(peekCP); } } popCollectionStack(); if (!svrcodReceived) throwMissingRequiredCodepoint("SVRCOD", CodePoint.SVRCOD); if (!rdbnamReceived) throwMissingRequiredCodepoint("RDBNAM", CodePoint.RDBNAM); if (!pkgnamcsnReceived) throwMissingRequiredCodepoint("PKGNAMCSN", CodePoint.PKGNAMCSN); // netAgent_.setSvrcod(svrcod); // @AGG removed throw new IllegalStateException("DRDA_CONNECTION_TERMINATED CONN_DRDA_QRYOPEN"); // agent_.accumulateChainBreakingReadExceptionAndThrow(new DisconnectException(agent_, // new ClientMessageId(SQLState.DRDA_CONNECTION_TERMINATED), // MessageUtil.getCompleteMessage(MessageId.CONN_DRDA_QRYOPEN, // SqlException.CLIENT_MESSAGE_RESOURCE_NAME, // (Object [])null))); } /** * Parse a PBSD - PiggyBackedSessionData code point. Can contain one or * both of, a PBSD_ISO code point followed by a byte representing the jdbc * isolation level, and a PBSD_SCHEMA code point followed by the name of the * current schema as an UTF-8 String. */ void parsePBSD() { parseLengthAndMatchCodePoint(CodePoint.PBSD); int peekCP = peekCodePoint(); while (peekCP != END_OF_SAME_ID_CHAIN) { parseLengthAndMatchCodePoint(peekCP); switch (peekCP) { case CodePoint.PBSD_ISO: throw new UnsupportedOperationException("PBSD_ISO not implemented"); // netAgent_.netConnection_. // completePiggyBackIsolation(readUnsignedByte()); case CodePoint.PBSD_SCHEMA: throw new UnsupportedOperationException("PBSD_ISO not implemented"); // netAgent_.netConnection_. // completePiggyBackSchema // (readString(getDdmLength(), Typdef.UTF8ENCODING)); default: //parseCommonError(peekCP); throwUnknownCodepoint(peekCP); } peekCP = peekCodePoint(); } } // RDB Update Reply Message indicates that a DDM command resulted // in an update at the target relational database. If a command // generated multiple reply messages including an RDBUPDRM, then // the RDBUPDRM must be the first reply message for the command. // For each target server, the RDBUPDRM must be returned the first // time an update is made to the target RDB within a unit of work. // The target server may optionally return the RDBUPDRM after subsequent // updates within the UOW. If multiple target RDBs are involved with // the current UOW and updates are made with any of them, then the RDBUPDRM // must be returned in response to the first update at each of them. protected void parseRDBUPDRM() { boolean svrcodReceived = false; int svrcod = CodePoint.SVRCOD_INFO; boolean rdbnamReceived = false; parseLengthAndMatchCodePoint(CodePoint.RDBUPDRM); pushLengthOnCollectionStack(); int peekCP = peekCodePoint(); while (peekCP != END_OF_COLLECTION) { boolean foundInPass = false; if (peekCP == CodePoint.SVRCOD) { foundInPass = true; svrcodReceived = checkAndGetReceivedFlag(svrcodReceived); svrcod = parseSVRCOD(CodePoint.SVRCOD_INFO, CodePoint.SVRCOD_INFO); peekCP = peekCodePoint(); } if (peekCP == CodePoint.RDBNAM) { foundInPass = true; rdbnamReceived = checkAndGetReceivedFlag(rdbnamReceived); parseRDBNAM(true); peekCP = peekCodePoint(); } if (!foundInPass) { throwUnknownCodepoint(peekCP); //doPrmnsprmSemantics(peekCP); } } popCollectionStack(); if (!svrcodReceived) throwMissingRequiredCodepoint("SVRCOD", CodePoint.SVRCOD); if (!rdbnamReceived) throwMissingRequiredCodepoint("RDBNAM", CodePoint.RDBNAM); //checkRequiredObjects(svrcodReceived, rdbnamReceived); // call an event to indicate the server has been updated // @AGG unused netAgent_.setSvrcod(svrcod); } @Deprecated // @AGG splitting this out private void parseOpenQuery() { // @AGG removed callback StatementCallbackInterface statementI) { //NetResultSet netResultSet = parseOPNQRYRM(statementI, true); parseOPNQRYRM(true); NetSqlca sqlca = null; int peekCP = peekCodePoint(); if (peekCP != CodePoint.QRYDSC) { peekCP = parseTypdefsOrMgrlvlovrs(); if (peekCP == CodePoint.SQLDARD) { outputColumnMetaData = new ColumnMetaData();// ClientDriver.getFactory().newColumnMetaData(netAgent_.logWriter_); NetSqlca netSqlca = parseSQLDARD(outputColumnMetaData, false); // false means do not skip SQLDARD bytes //For java stored procedure, we got the resultSetMetaData from server, //Do we need to save the resultSetMetaData and propagate netSqlca? //The following statement are doing the both, but it do more than //we want. It also mark the completion of Prepare statement. // // this will override the same call made from parsePrepareDescribe // this will not work, this is not the DA for the stored proc params // // We may now receive a new SQLDARD (unrequested, a // DRDA protocol extension) when a query is opened iff the // underlying server's prepared statement has been recompiled // since the client first received metadata when preparing the // statement. NetSqlca.complete(netSqlca); peekCP = parseTypdefsOrMgrlvlovrs(); } // check if the DARD is mutually exclusive with CARD, if so, then the following if should be an elese if (peekCP == CodePoint.SQLCARD) { sqlca = parseSQLCARD(null); peekCP = parseTypdefsOrMgrlvlovrs(); } } parseQRYDSC(/*netResultSet.netCursor_*/); peekCP = peekCodePoint(); while (peekCP == CodePoint.QRYDTA) { parseQRYDTA(/*NetResultSet*/); peekCP = peekCodePoint(); } if (peekCP == CodePoint.SQLCARD) { NetSqlca netSqlca = parseSQLCARD(null); NetSqlca.complete(netSqlca); peekCP = peekCodePoint(); } if (peekCP == CodePoint.ENDQRYRM) { parseEndQuery(/*netResultSet*/); } completeOpenQuery(sqlca); } private void parseOpenQueryFailure() { parseOPNQFLRM(); parseTypdefsOrMgrlvlovrs(); NetSqlca netSqlca = parseSQLCARD(null); NetSqlca.complete(netSqlca); } // Open Query Failure (OPNQFLRM) Reply Message indicates that the // OPNQRY command failed to open the query. The reason that the // target relational database was unable to open the query is reported in an // SQLCARD reply data object. // Whenever an OPNQFLRM is returned, an SQLCARD object must also be returned // following the OPNQFLRM. // // Returned from Server: // SVRCOD - required (8 - ERROR) // RDBNAM - required // SRVDGN - optional private void parseOPNQFLRM() { boolean svrcodReceived = false; int svrcod = CodePoint.SVRCOD_INFO; boolean rdbnamReceived = false; String rdbnam = null; parseLengthAndMatchCodePoint(CodePoint.OPNQFLRM); pushLengthOnCollectionStack(); int peekCP = peekCodePoint(); while (peekCP != END_OF_COLLECTION) { boolean foundInPass = false; if (peekCP == CodePoint.SVRCOD) { foundInPass = true; svrcodReceived = checkAndGetReceivedFlag(svrcodReceived); svrcod = parseSVRCOD(CodePoint.SVRCOD_ERROR, CodePoint.SVRCOD_ERROR); peekCP = peekCodePoint(); } if (peekCP == CodePoint.RDBNAM) { // skip the rdbnam since it doesn't tell us anything new. // there is no way to return it to the application anyway. // not having to convert this to a string is a time saver also. foundInPass = true; rdbnamReceived = checkAndGetReceivedFlag(rdbnamReceived); rdbnam = parseRDBNAM(true); peekCP = peekCodePoint(); } if (!foundInPass) { throwUnknownCodepoint(peekCP); } } popCollectionStack(); if (!svrcodReceived) throwMissingRequiredCodepoint("SVRCOD", CodePoint.SVRCOD); if (!rdbnamReceived) throwMissingRequiredCodepoint("RDBNAM", CodePoint.RDBNAM); // @AGG removed netAgent_.setSvrcod(svrcod); // get SQLSTATE from SQLCARD... } public void completeOpenQuery(NetSqlca sqlca/*, ClientResultSet resultSet*/) { NetSqlca.complete(sqlca); // resultSet_ = resultSet; // // For NET, resultSet_ == null when open query fails and receives OPNQFLRM. // // Then, in NetStatementReply.parseOpenQueryFailure(), completeOpenQuery() is // // invoked with resultSet explicitly set to null. // if (resultSet == null) { // return; // } // resultSet.resultSetMetaData_ = resultSetMetaData_; // resultSet.resultSetMetaData_.resultSetConcurrency_ = resultSet.resultSetConcurrency_; // // Create tracker for LOB locator columns. // resultSet.createLOBColumnTracker(); // // // only cache the Cursor object for a PreparedStatement and if a Cursor object is // // not already cached. // if (cachedCursor_ == null && isPreparedStatement_) { // cachedCursor_ = resultSet_.cursor_; // } // The following two assignments should have already happened via prepareEvent(), // but are included here for safety for the time being. if (sqlca != null && sqlca.getSqlCode() < 0) { return; } // resultSet.cursor_.rowsRead_ = fetchedRowBase; // // Set fetchSize_ to the default(64) if not set by the user if the resultset is scrollable. // // This fetchSize_ is used to check for a complete rowset when rowsets are parsed. // // For scrollable cursors when the fetchSize_ is not set, (fetchSize_ == 0), a default // // fetchSize of 64 is sent on behalf of the application, so we need to update the fetchSize_ // // here to 64. // if (fetchSize_ == 0 && // (resultSet_.resultSetType_ == ResultSet.TYPE_SCROLL_INSENSITIVE || // resultSet_.resultSetType_ == ResultSet.TYPE_SCROLL_SENSITIVE)) { // fetchSize = DRDAQueryRequest.defaultFetchSize; // } // @AGG customize fetchSize here if needed // @AGG assuming always TYPE_FORWARD_ONLY } void parseEndQuery(/*ResultSetCallbackInterface resultSetI*/) { parseENDQRYRM(/*resultSetI*/); parseTypdefsOrMgrlvlovrs(); NetSqlca netSqlca = parseSQLCARD(null); cursor.setAllRowsReceivedFromServer(true); int peekCP = peekCodePoint(); if (peekCP == CodePoint.RDBUPDRM) { parseRDBUPDRM(); } } // Also called by NetResultSetReply subclass. // The End of Query Reply Message indicates that the query process has // terminated in such a manner that the query or result set is now closed. // It cannot be resumed with the CNTQRY command or closed with the CLSQRY command. // The ENDQRYRM is always followed by an SQLCARD. private void parseENDQRYRM(/*ResultSetCallbackInterface resultSetI*/) { boolean svrcodReceived = false; int svrcod = CodePoint.SVRCOD_INFO; boolean rdbnamReceived = false; String rdbnam = null; parseLengthAndMatchCodePoint(CodePoint.ENDQRYRM); pushLengthOnCollectionStack(); int peekCP = peekCodePoint(); while (peekCP != END_OF_COLLECTION) { boolean foundInPass = false; if (peekCP == CodePoint.SVRCOD) { foundInPass = true; svrcodReceived = checkAndGetReceivedFlag(svrcodReceived); svrcod = parseSVRCOD(CodePoint.SVRCOD_WARNING, CodePoint.SVRCOD_ERROR); peekCP = peekCodePoint(); } if (peekCP == CodePoint.RDBNAM) { foundInPass = true; rdbnamReceived = checkAndGetReceivedFlag(rdbnamReceived); rdbnam = parseRDBNAM(true); peekCP = peekCodePoint(); } if (!foundInPass) { throwUnknownCodepoint(peekCP); // doPrmnsprmSemantics(peekCP); } } popCollectionStack(); if(!svrcodReceived) throwMissingRequiredCodepoint("SVRCOD", CodePoint.SVRCOD); // checkRequiredObjects(svrcodReceived); // netAgent_.setSvrcod(svrcod); @AGG removed } void parseQRYDTA(/*NetResultSet netResultSet*/) { parseLengthAndMatchCodePoint(CodePoint.QRYDTA); // @AGG assume no encryption // if (longValueForDecryption_ == null) { int ddmLength = getDdmLength(); ensureBLayerDataInBuffer(ddmLength); // } parseSQLDTARDdata(/*netResultSet.netCursor_*/); // @AGG assume no encryption // if (longValueForDecryption_ == null) { adjustLengths(getDdmLength()); // } else { // longValueForDecryption_ = null; // } // if (longBufferForDecryption_ != null) { // buffer_ = longBufferForDecryption_; // pos_ = longPosForDecryption_; // if (count_ > longBufferForDecryption_.length) { // count_ = longBufferForDecryption_.length; // } else if (longCountForDecryption_ != 0) { // count_ = longCountForDecryption_; // longCountForDecryption_ = 0; // } // dssLength_ = 0; // longBufferForDecryption_ = null; // } } public Cursor getCursor() { if (cursor == null) throw new IllegalStateException("Cursor has not been created yet"); return cursor; } public long getQueryInstanceId() { return queryInstanceId; } public ColumnMetaData getOutputColumnMetaData() { if (outputColumnMetaData == null) throw new IllegalStateException("ColumnMetaData has not been created yet"); return outputColumnMetaData; } public void setOutputColumnMetaData(ColumnMetaData md) { Objects.requireNonNull(md); this.outputColumnMetaData = md; } public ColumnMetaData getInputColumnMetaData() { if (inputColumnMetaData == null) throw new IllegalStateException("ColumnMetaData has not been created yet"); return inputColumnMetaData; } private void parseSQLDTARDdata(/*NetCursor netCursor*/) { // if (longValueForDecryption_ == null) { // netCursor.dataBufferStream_ = getData(/*netCursor.dataBufferStream_*/); // netCursor.dataBuffer_ = netCursor.dataBufferStream_.toByteArray(); if (cursor == null) cursor = new Cursor(metadata); cursor.dataBuffer_ = getData(); // } else { // int size = netCursor.dataBufferStream_.size(); // if (size == 0) { // netCursor.dataBuffer_ = longValueForDecryption_; // //longValue_ = null; // } else { // byte[] newArray = new byte[size + longValueForDecryption_.length]; // System.arraycopy(netCursor.dataBuffer_, 0, newArray, 0, size); // System.arraycopy(longValueForDecryption_, 0, newArray, size, longValueForDecryption_.length); // netCursor.dataBuffer_ = newArray; // //longValue_ = null; // } // } // netCursor.lastValidBytePosition_ = netCursor.dataBuffer_.length; cursor.lastValidBytePosition_ = cursor.dataBuffer_.capacity(); } // This will be the new and improved getData that handles all QRYDTA/EXTDTA // Returns the stream so that the caller can cache it final ByteBuf getData(/*ByteArrayOutputStream existingBuffer*/) { boolean readHeader; int copySize; ByteBuf baos = null; // ByteArrayOutputStream baos; // // note: an empty baos can yield an allocated and empty byte[] // if (existingBuffer != null) { // baos = existingBuffer; // } else { // if (ddmScalarLen_ != -1) { // // allocate a stream based on a known amount of data // baos = new ByteArrayOutputStream(ddmScalarLen_); // } else { // // allocate a stream to hold an unknown amount of data // baos = new ByteArrayOutputStream(); // //isLengthAndNullabilityUnknown = true; // } // } // set the amount to read for the first segment copySize = dssLength_; // note: has already been adjusted for headers do { // determine if a continuation header needs to be read after the data if (dssIsContinued_) { readHeader = true; } else { readHeader = false; } // read the segment ensureALayerDataInBuffer(copySize); adjustLengths(copySize); baos = buffer.readRetainedSlice(copySize).asReadOnly(); // baos.write(buffer_, pos_, copySize); // pos_ += copySize; // read the continuation header, if necessary if (readHeader) { readDSSContinuationHeader(); } copySize = dssLength_; } while (readHeader == true); return baos; } private void parseQRYDSC() { parseLengthAndMatchCodePoint(CodePoint.QRYDSC); parseSQLDTARDarray(false); // false means don't just skip the bytes } private void parseSQLDTARDarray(boolean skipBytes) { if (skipBytes) { skipBytes(); } int previousTripletType = FdocaConstants.SQLDTARD_TRIPLET_TYPE_START; int previousTripletId = FdocaConstants.SQLDTARD_TRIPLET_ID_START; int mddProtocolType = 0; int columnCount = 0; Typdef.targetTypdef.clearMddOverrides(); // netAgent_.targetTypdef_.clearMddOverrides(); int ddmLength = getDdmLength(); ensureBLayerDataInBuffer(ddmLength); while (ddmLength > 0) { int tripletLength = readFastUnsignedByte(); int tripletType = readFastUnsignedByte(); int tripletId = readFastUnsignedByte(); switch (tripletType) { case FdocaConstants.MDD_TRIPLET_TYPE: if ((tripletLength != FdocaConstants.MDD_TRIPLET_SIZE) || (tripletId != FdocaConstants.NULL_LID)) { descriptorErrorDetected(); } checkPreviousSQLDTARDtriplet(previousTripletType, FdocaConstants.SQLDTARD_TRIPLET_TYPE_MDD, previousTripletId, FdocaConstants.SQLDTARD_TRIPLET_ID_0); previousTripletType = FdocaConstants.SQLDTARD_TRIPLET_TYPE_MDD; previousTripletId = FdocaConstants.SQLDTARD_TRIPLET_ID_0; // read in remaining MDD bytes int mddClass = readFastUnsignedByte(); int mddType = readFastUnsignedByte(); int mddRefType = readFastUnsignedByte(); mddProtocolType = readFastUnsignedByte(); break; case FdocaConstants.NGDA_TRIPLET_TYPE: // rename to NGDA_TRIPLET_CODEPOINT if (tripletId != FdocaConstants.SQLDTAGRP_LID) { descriptorErrorDetected(); } checkPreviousSQLDTARDtriplet(previousTripletType, FdocaConstants.SQLDTARD_TRIPLET_TYPE_GDA, previousTripletId, FdocaConstants.SQLDTARD_TRIPLET_ID_D0); previousTripletType = FdocaConstants.SQLDTARD_TRIPLET_TYPE_GDA; previousTripletId = FdocaConstants.SQLDTARD_TRIPLET_ID_0; // add a quick check to see if the table is altered (columns are added or deleted) // before reusing the cached cursor. note: this check does not catch the case // where the number of columns stay the same, but the column type or length changes, // i.e. from integer to char. int columns = peekTotalColumnCount(tripletLength); // peek ahead to get the total number of columns. outputColumnMetaData.setColumnCount(columns); cursor.initializeColumnInfoArrays(Typdef.targetTypdef, columns); columnCount += parseSQLDTAGRPdataLabelsAndUpdateColumn(/*cursor, */columnCount, tripletLength); break; case FdocaConstants.RLO_TRIPLET_TYPE: // rename to RLO_TRIPLET_CODEPOINT switch (tripletId) { case FdocaConstants.SQLCADTA_LID: if (tripletLength != FdocaConstants.SQLCADTA_RLO_SIZE) { descriptorErrorDetected(); // DSCERRCD_06 } checkPreviousSQLDTARDtriplet(previousTripletType, FdocaConstants.SQLDTARD_TRIPLET_TYPE_RLO, previousTripletId, FdocaConstants.SQLDTARD_TRIPLET_ID_E0); previousTripletType = FdocaConstants.SQLDTARD_TRIPLET_TYPE_RLO; previousTripletId = FdocaConstants.SQLDTARD_TRIPLET_ID_E0; checkFastRLO(FdocaConstants.RLO_SQLCADTA); break; case FdocaConstants.SQLDTARD_LID: if (tripletLength != FdocaConstants.SQLDTARD_RLO_SIZE) { descriptorErrorDetected(); // DSCERRCD_06 } checkPreviousSQLDTARDtriplet(previousTripletType, FdocaConstants.SQLDTARD_TRIPLET_TYPE_RLO, previousTripletId, FdocaConstants.SQLDTARD_TRIPLET_ID_F0); previousTripletType = FdocaConstants.SQLDTARD_TRIPLET_TYPE_RLO; previousTripletId = FdocaConstants.SQLDTARD_TRIPLET_ID_F0; checkFastRLO(FdocaConstants.RLO_SQLDTARD); break; default: descriptorErrorDetected(); // DSCERRCD_07 break; } break; case FdocaConstants.CPT_TRIPLET_TYPE: // rename to CPT_TRIPLET_CODEPOINT if (tripletId != FdocaConstants.NULL_LID) { descriptorErrorDetected(); } checkPreviousSQLDTARDtriplet(previousTripletType, FdocaConstants.SQLDTARD_TRIPLET_TYPE_CPT, previousTripletId, FdocaConstants.SQLDTARD_TRIPLET_ID_0); previousTripletType = FdocaConstants.SQLDTARD_TRIPLET_TYPE_CPT; previousTripletId = FdocaConstants.SQLDTARD_TRIPLET_ID_0; columnCount += parseSQLDTAGRPdataLabelsAndUpdateColumn(/*cursor, */columnCount, tripletLength); break; case FdocaConstants.SDA_TRIPLET_TYPE: // rename to SDA_TRIPLET_CODEPOINT if (tripletLength != FdocaConstants.SDA_TRIPLET_SIZE) { descriptorErrorDetected(); // DSCERRCD_06 } checkPreviousSQLDTARDtriplet(previousTripletType, FdocaConstants.SQLDTARD_TRIPLET_TYPE_SDA, previousTripletId, FdocaConstants.SQLDTARD_TRIPLET_ID_SDA); previousTripletType = FdocaConstants.SQLDTARD_TRIPLET_TYPE_SDA; previousTripletId = FdocaConstants.SQLDTARD_TRIPLET_ID_SDA; Typdef.targetTypdef.setMddOverride(mddProtocolType, // mdd protocol type tripletId, // fdocaTripletLid readFastUnsignedByte(), // fdocaFieldType readFastInt(), // ccsid readFastUnsignedByte(), // characterSize readFastUnsignedByte(), // mode readFastShort()); break; default: descriptorErrorDetected(); //DSCERRCD_01 break; } ddmLength -= tripletLength; } adjustLengths(getDdmLength()); // Allocate a char buffer after all of the descriptors have been parsed out. // cursor.allocateCharBuffer(); checkPreviousSQLDTARDtriplet(previousTripletType, FdocaConstants.SQLDTARD_TRIPLET_TYPE_END, previousTripletId, FdocaConstants.SQLDTARD_TRIPLET_ID_END); } private void checkFastRLO(int[][] rlo) { for (int i = 0; i < rlo.length; i++) { int lid = readFastUnsignedByte(); if (lid != rlo[i][FdocaConstants.RLO_GROUP_LID]) { descriptorErrorDetected(); // DSCERRCD_42 } int elementTaken = readFastUnsignedByte(); if (elementTaken != rlo[i][FdocaConstants.RLO_ELEMENT_TAKEN]) { descriptorErrorDetected(); // DSCERRCD_07 } int repFactor = readFastUnsignedByte(); if (repFactor != rlo[i][FdocaConstants.RLO_REP_FACTOR]) { descriptorErrorDetected(); // DSCERRCD_07 } } } private int parseSQLDTAGRPdataLabelsAndUpdateColumn(/*NetCursor cursor, */int columnIndex, int tripletLength) { int numColumns = (tripletLength - 3) / 3; for (int i = columnIndex; i < columnIndex + numColumns; i++) { cursor.qrydscTypdef_.updateColumn(cursor, metadata, i, readFastUnsignedByte(), readFastUnsignedShort()); } return numColumns; } protected final int peekTotalColumnCount(int tripletLength) { int columnCount = 0; //int offset = 0; int tripletType = FdocaConstants.CPT_TRIPLET_TYPE; while (tripletType == FdocaConstants.CPT_TRIPLET_TYPE) { columnCount += ((tripletLength - 3) / 3); // Peek ahead for the next triplet's tripletLength and tripletType. // The number of bytes to skip before the next tripletType is tripletLength - 3. ensureBLayerDataInBuffer(tripletLength - 3); buffer.markReaderIndex(); buffer.skipBytes(tripletLength - 3); //offset += (tripletLength - 3); tripletLength = buffer.readByte(); // tripletLength = (buffer_[pos_ + offset++] & 0xff); tripletType = buffer.readByte(); // tripletType = (buffer_[pos_ + offset++] & 0xff); // Skip the 1-byte tripletId. //offset++; buffer.resetReaderIndex(); } return columnCount; } private void checkPreviousSQLDTARDtriplet(int previousTripletType, int tripletType, int previousTripletId, int tripletId) { if (FdocaConstants.SQLDTARD_TRIPLET_TYPES[previousTripletType][tripletType] == false) { descriptorErrorDetected(); // DSCERRCD_02 move error identity into array } if (FdocaConstants.SQLDTARD_TRIPLET_IDS[previousTripletId][tripletId] == false) { descriptorErrorDetected(); // DSCERRCD_02 move error identity into array } } // Possible errors to detect include: // DSCERRCD_01 - FDOCA triplet is not used in PROTOCOL descriptors or type code is invalid // DSCERRCD_02 - FDOCA triplet sequence error // DSCERRCD_03 - An array description is required and this is not one // (too many or too few RLO triplets) // DSCERRCD_04 - A row description is required and this is not one // (too many or too few RLO triplets) // DSCERRCD_05 - Late Environmental Descriptor just received not supported // DSCERRCD_06 - Malformed triplet, required parameter is missing // DSCERRCD_07 - Parameter value is not acceptable // DSCERRCD_11 - MDD present is not recognized as an SQL descriptor // DSCERRCD_12 - MDD class is not recognized as a valid SQL class // DSCERRCD_13 - MDD type not recognized as a valid SQL type // DSCERRCD_21 - Representation is incompatible with SQL type (in prior MDD) // DSCERRCD_22 - CCSID is not supported // DSCERRCD_32 - GDA references a local identifier which is not an SDA or GDA // DSCERRCD_33 - GDA length override exceeds limits // DSCERRCD_34 - GDA precision exceeds limits // DSCERRCD_35 - GDA scale greater than precision or scale negative // DSCERRCD_36 - GDA length override missing or incompatible with data type // DSCERRCD_41 - RLO references a LID which is not an RLO or GDA. // DSCERRCD_42 - RLO fails to reference a required GDA or RLO. private void descriptorErrorDetected() { throw new IllegalStateException("MessageId.CONN_DRDA_INVALIDFDOCA"); // agent_.accumulateChainBreakingReadExceptionAndThrow(new DisconnectException(agent_, // new ClientMessageId(SQLState.DRDA_CONNECTION_TERMINATED), // MessageUtil.getCompleteMessage(MessageId.CONN_DRDA_INVALIDFDOCA, // SqlException.CLIENT_MESSAGE_RESOURCE_NAME, // (Object [])null))); } /** * Open Query Complete Reply Message indicates to the requester * that an OPNQRY or EXCSQLSTT command completed normally and that * the query process has been initiated. It also indicates the * type of query protocol and cursor used for the query. *

* When an EXCSQLSTT contains an SQL statement that invokes a * stored procedure, and the procedure completes, an OPNQRYRM is * returned for each answer set. * * @param statementI statement callback interface * @param isOPNQRYreply If true, parse a reply to an OPNQRY * command. Otherwise, parse a reply to an EXCSQLSTT command. * @return a NetResultSet value */ //private NetResultSet parseOPNQRYRM(boolean isOPNQRYreply) { private void parseOPNQRYRM(boolean isOPNQRYreply) { // these need to be initialized to the correct default values. int svrcod = CodePoint.SVRCOD_INFO; boolean svrcodReceived = false; int qryprctyp = 0; boolean qryprctypReceived = false; int sqlcsrhld = 0xF0; // 0xF0 is false (default), 0xF1 is true. boolean sqlcsrhldReceived = false; int qryattscr = 0xF0; // 0xF0 is false (default), 0xF1 is true. boolean qryattscrReceived = false; int qryattsns = CodePoint.QRYUNK; boolean qryattsnsReceived = false; int qryattupd = CodePoint.QRYUNK; boolean qryattupdReceived = false; long qryinsid = 0; boolean qryinsidReceived = false; int qryattset = 0xF0; // 0xF0 is false (default), 0xF1 is true. boolean qryattsetReceived = false; parseLengthAndMatchCodePoint(CodePoint.OPNQRYRM); //pushLengthOnCollectionStack(); int ddmLength = getDdmLength(); ensureBLayerDataInBuffer(ddmLength); int peekCP = peekCodePoint(); int length = 0; //while (peekCP != Reply.END_OF_COLLECTION) { while (ddmLength > 0) { boolean foundInPass = false; if (peekCP == CodePoint.SVRCOD) { foundInPass = true; svrcodReceived = checkAndGetReceivedFlag(svrcodReceived); length = peekedLength_; svrcod = parseFastSVRCOD(CodePoint.SVRCOD_INFO, CodePoint.SVRCOD_SESDMG); ddmLength = adjustDdmLength(ddmLength, length); peekCP = peekCodePoint(); } if (peekCP == CodePoint.QRYPRCTYP) { foundInPass = true; qryprctypReceived = checkAndGetReceivedFlag(qryprctypReceived); length = peekedLength_; qryprctyp = parseFastQRYPRCTYP(); ddmLength = adjustDdmLength(ddmLength, length); peekCP = peekCodePoint(); } if (peekCP == CodePoint.SQLCSRHLD) { // Indicates whether the requester specified the HOLD option. // When specified, the cursor is not closed upon execution of a commit operation. foundInPass = true; sqlcsrhldReceived = checkAndGetReceivedFlag(sqlcsrhldReceived); length = peekedLength_; sqlcsrhld = parseFastSQLCSRHLD(); ddmLength = adjustDdmLength(ddmLength, length); peekCP = peekCodePoint(); } if (peekCP == CodePoint.QRYATTSCR) { foundInPass = true; qryattscrReceived = checkAndGetReceivedFlag(qryattscrReceived); length = peekedLength_; qryattscr = parseFastQRYATTSCR(); ddmLength = adjustDdmLength(ddmLength, length); peekCP = peekCodePoint(); } if (peekCP == CodePoint.QRYATTSNS) { foundInPass = true; qryattsnsReceived = checkAndGetReceivedFlag(qryattsnsReceived); length = peekedLength_; qryattsns = parseFastQRYATTSNS(); ddmLength = adjustDdmLength(ddmLength, length); peekCP = peekCodePoint(); } if (peekCP == CodePoint.QRYATTUPD) { foundInPass = true; qryattupdReceived = checkAndGetReceivedFlag(qryattupdReceived); length = peekedLength_; qryattupd = parseFastQRYATTUPD(); ddmLength = adjustDdmLength(ddmLength, length); peekCP = peekCodePoint(); } if (peekCP == CodePoint.QRYINSID) { foundInPass = true; qryinsidReceived = checkAndGetReceivedFlag(qryinsidReceived); length = peekedLength_; qryinsid = parseFastQRYINSID(); queryInstanceId = qryinsid; ddmLength = adjustDdmLength(ddmLength, length); peekCP = peekCodePoint(); } if (peekCP == CodePoint.QRYATTSET) { foundInPass = true; qryattsetReceived = checkAndGetReceivedFlag(qryattsetReceived); length = peekedLength_; qryattset = parseFastQRYATTSET(); ddmLength = adjustDdmLength(ddmLength, length); peekCP = peekCodePoint(); } if (peekCP == CodePoint.QRYATTISOL) { // @AGG added foundInPass = true; length = peekedLength_; parseFastQRYATTISOL(); ddmLength = adjustDdmLength(ddmLength, length); peekCP = peekCodePoint(); } if (peekCP == CodePoint.QRYBLKFCT) { // @MJS added foundInPass = true; length = peekedLength_; parseFastQRYBLKFCT(); ddmLength = adjustDdmLength(ddmLength, length); peekCP = peekCodePoint(); } if (!foundInPass) { //doPrmnsprmSemantics(peekCP); throwUnknownCodepoint(peekCP); } } //checkRequiredObjects(svrcodReceived, qryprctypReceived, qryinsidReceived); if (!svrcodReceived) throwMissingRequiredCodepoint("SVRCOD", CodePoint.SVRCOD); if (!qryprctypReceived) throwMissingRequiredCodepoint("QRYPRCTYP", CodePoint.QRYPRCTYP); if (!qryinsidReceived) throwMissingRequiredCodepoint("QRYINSID", CodePoint.QRYINSID); // @AGG not implemented netAgent_.setSvrcod(svrcod); // hack for now until event methods are used below // ClientStatement statement = (ClientStatement) statementI; // if there is a cached Cursor object, then use the cached cursor object. // NetResultSet rs = null; // if (statement.cachedCursor_ != null) { // statement.cachedCursor_.resetDataBuffer(); // ((NetCursor) statement.cachedCursor_).extdtaData_.clear(); // try { // rs = (NetResultSet) ClientDriver.getFactory().newNetResultSet // (netAgent_, // (NetStatement) statement.getMaterialStatement(), // statement.cachedCursor_, // qryprctyp, //protocolType, CodePoint.FIXROWPRC | // // CodePoint.LMTBLKPRC // sqlcsrhld, //holdOption, 0xF0 for false (default) | 0xF1 for true. // qryattscr, //scrollOption, 0xF0 for false (default) | 0xF1 for true. // qryattsns, //sensitivity, CodePoint.QRYUNK | // // CodePoint.QRYINS | // // CodePoint.QRYSNSSTC // qryattset, // qryinsid, //instanceIdentifier, 0 (if not returned, check default) or number // calculateResultSetType(qryattscr, qryattsns, statement.resultSetType_), // calculateResultSetConcurrency(qryattupd, statement.resultSetConcurrency_), // calculateResultSetHoldability(sqlcsrhld)); // } catch(SqlException sqle) { // throw new DisconnectException(netAgent_,sqle); // } // } else { // try { // rs = (NetResultSet)ClientDriver.getFactory().newNetResultSet // (netAgent_, // (NetStatement) statement.getMaterialStatement(), // new NetCursor(netAgent_, qryprctyp), // qryprctyp, //protocolType, CodePoint.FIXROWPRC | // // CodePoint.LMTBLKPRC // sqlcsrhld, //holdOption, 0xF0 for false (default) | 0xF1 for true. // qryattscr, //scrollOption, 0xF0 for false (default) | 0xF1 for true. // qryattsns, //sensitivity, CodePoint.QRYUNK | CodePoint.QRYINS // qryattset, // qryinsid, //instanceIdentifier, 0 (if not returned, check default) or number // calculateResultSetType(qryattscr, qryattsns, statement.resultSetType_), // calculateResultSetConcurrency(qryattupd, statement.resultSetConcurrency_), // calculateResultSetHoldability(sqlcsrhld)); // } catch(SqlException sqle) { // throw new DisconnectException(netAgent_,sqle); // } // } // @AGG returning a cursor instead of a ResultSet cursor = new Cursor(metadata); // QRYCLSIMP only applies to OPNQRY, not EXCSQLSTT // final boolean qryclsimp = // isOPNQRYreply && // (rs.resultSetType_ == ResultSet.TYPE_FORWARD_ONLY) && // netAgent_.netConnection_.serverSupportsQryclsimp(); // rs.netCursor_.setQryclsimpEnabled(qryclsimp); // return rs; } private int parseFastSQLCSRHLD() { matchCodePoint(CodePoint.SQLCSRHLD); int sqlcsrhld = readFastUnsignedByte(); // 0xF0 is false (default), 0xF1 is true // use constants in if if ((sqlcsrhld != 0xF0) && (sqlcsrhld != 0xF1)) { doValnsprmSemantics(CodePoint.SQLCSRHLD, sqlcsrhld); } return sqlcsrhld; } private int parseFastQRYATTSCR() { matchCodePoint(CodePoint.QRYATTSCR); int qryattscr = readFastUnsignedByte(); // use constants in if if ((qryattscr != 0xF0) && (qryattscr != 0xF1)) { doValnsprmSemantics(CodePoint.QRYATTSCR, qryattscr); } return qryattscr; } private int parseFastQRYATTSET() { matchCodePoint(CodePoint.QRYATTSET); int qryattset = readFastUnsignedByte(); // use constants in if if ((qryattset != 0xF0) && (qryattset != 0xF1)) { doValnsprmSemantics(CodePoint.QRYATTSET, qryattset); } return qryattset; } private int parseFastQRYATTISOL() { // @AGG added matchCodePoint(CodePoint.QRYATTISOL); return readUnsignedShort(); } private int parseFastQRYBLKFCT() { //@MJS added matchCodePoint(CodePoint.QRYBLKFCT); return readFastInt(); } private int parseFastQRYATTSNS() { matchCodePoint(CodePoint.QRYATTSNS); int qryattsns = readFastUnsignedByte(); switch (qryattsns) { case CodePoint.QRYUNK: case CodePoint.QRYSNSSTC: case CodePoint.QRYINS: break; default: doValnsprmSemantics(CodePoint.QRYATTSNS, qryattsns); break; } return qryattsns; } private int parseFastQRYATTUPD() { matchCodePoint(CodePoint.QRYATTUPD); int qryattupd = readFastUnsignedByte(); switch (qryattupd) { case CodePoint.QRYUNK: case CodePoint.QRYRDO: case CodePoint.QRYUPD: break; default: doValnsprmSemantics(CodePoint.QRYATTUPD, qryattupd); break; } return qryattupd; } private long parseFastQRYINSID() { matchCodePoint(CodePoint.QRYINSID); return readFastLong(); } private int parseFastQRYPRCTYP() { matchCodePoint(CodePoint.QRYPRCTYP); int qryprctyp = readFastUnsignedShort(); if ((qryprctyp != CodePoint.FIXROWPRC) && (qryprctyp != CodePoint.LMTBLKPRC)) { doValnsprmSemantics(CodePoint.QRYPRCTYP, qryprctyp); } return qryprctyp; } int parseFastSVRCOD(int minSvrcod, int maxSvrcod) { matchCodePoint(CodePoint.SVRCOD); int svrcod = readFastUnsignedShort(); if ((svrcod != CodePoint.SVRCOD_INFO) && (svrcod != CodePoint.SVRCOD_WARNING) && (svrcod != CodePoint.SVRCOD_ERROR) && (svrcod != CodePoint.SVRCOD_SEVERE) && (svrcod != CodePoint.SVRCOD_ACCDMG) && (svrcod != CodePoint.SVRCOD_PRMDMG) && (svrcod != CodePoint.SVRCOD_SESDMG)) { doValnsprmSemantics(CodePoint.SVRCOD, svrcod); } if (svrcod < minSvrcod || svrcod > maxSvrcod) { doValnsprmSemantics(CodePoint.SVRCOD, svrcod); } return svrcod; } // This method is only used to match the codePoint for those class instance variables // that are embedded in other reply messages. final protected void matchCodePoint(int expectedCodePoint) { int actualCodePoint = 0; actualCodePoint = peekedCodePoint_; buffer.skipBytes(4); //pos_ += 4; if (actualCodePoint != expectedCodePoint) { // agent_.accumulateChainBreakingReadExceptionAndThrow( // new DisconnectException(agent_, // new ClientMessageId(SQLState.NET_NOT_EXPECTED_CODEPOINT), // actualCodePoint, expectedCodePoint)); throw new IllegalStateException("SQLState.NET_NOT_EXPECTED_CODEPOINT"); } } private void parsePRPSQLSTTreply() { // @AGG removed callback StatementCallbackInterface statement) { int peekCP = parseTypdefsOrMgrlvlovrs(); outputColumnMetaData = new ColumnMetaData(); if (peekCP == CodePoint.SQLDARD) { // the sqlcagrp is most likely null for insert/update/deletes. if it is null, then we can // peek ahead for the column number which most likely will be 0. if it is 0, then we will // not new up a ColumnMetaData, and we can skip the rest of the bytes in sqldard. // if sqlcargrp is not null, (most likely for select's) then we will not peek ahead for the // column number since it will never be 0 in a select case. //ColumnMetaData columnMetaData = null; NetSqlca netSqlca = null; boolean nullSqlca = peekForNullSqlcagrp(); if (nullSqlca && peekNumOfColumns() == 0) { netSqlca = parseSQLDARD(outputColumnMetaData, true); // true means to skip the rest of SQLDARD bytes } else { //columnMetaData = ClientDriver.getFactory().newColumnMetaData(netAgent_.logWriter_); // @AGG Moved this up so we get non-null col metadata for SQLDARD AND SQLCARD scenarios //outputColumnMetaData = new ColumnMetaData(); netSqlca = parseSQLDARD(outputColumnMetaData, false); // false means do not skip SQLDARD bytes. } // @AGG not implemented, checks for error codes on the sqlca NetSqlca.complete(netSqlca); // statement.completePrepareDescribeOutput(columnMetaData, // netSqlca); } else if (peekCP == CodePoint.SQLCARD) { NetSqlca netSqlca = parseSQLCARD(null); NetSqlca.complete(netSqlca); } else { //throw new IllegalStateException("Unable to prepare statement"); parsePrepareError(); } } private void parsePrepareError() { // @AGG removed callback StatementCallbackInterface statement) { int peekCP = peekCodePoint(); switch (peekCP) { case CodePoint.ABNUOWRM: { // passing the StatementCallbackInterface implementation will // help in retrieving the the UnitOfWorkListener that needs to // be rolled back //NetSqlca sqlca = parseAbnormalEndUow(); // @AGG removed callback statement); //statement.completeSqlca(sqlca); //break; throw new UnsupportedOperationException("Abnormal end UOW handling not implemented"); } case CodePoint.CMDCHKRM: parseCMDCHKRM(); break; case CodePoint.DTAMCHRM: parseDTAMCHRM(); break; case CodePoint.OBJNSPRM: parseOBJNSPRM(); break; case CodePoint.RDBNACRM: parseRDBNACRM(); break; case CodePoint.SQLERRRM: { NetSqlca sqlca = parseSqlErrorCondition(); NetSqlca.complete(sqlca); break; } default: throwUnknownCodepoint(peekCP); // parseCommonError(peekCP); } } NetSqlca parseSqlErrorCondition() { parseSQLERRRM(); parseTypdefsOrMgrlvlovrs(); NetSqlca netSqlca = parseSQLCARD(null); return netSqlca; } // SQL Error Condition Reply Message indicates that an SQL error // has occurred. It may be sent even though no reply message // precedes the SQLCARD object that is the normal // response to a command when an exception occurs. // The SQLERRM is also used when a BNDSQLSTT command is terminated // by an INTRRDBRQS command. // This reply message must precede an SQLCARD object. // The SQLSTATE is returned in the SQLCARD. // // Returned from Server: // SVRCOD - required (8 - ERROR) // RDBNAM - optional // SRVDGN - optional // // Also called by NetResultSetReply and NetStatementReply private void parseSQLERRRM() { // TODO @AGG we let this information flow up into the Sqlca so the // user is presented with as much information as possible on errors boolean svrcodReceived = false; int svrcod = CodePoint.SVRCOD_INFO; boolean rdbnamReceived = false; String rdbnam = null; String serverDiagnostics = null; parseLengthAndMatchCodePoint(CodePoint.SQLERRRM); pushLengthOnCollectionStack(); int peekCP = peekCodePoint(); while (peekCP != END_OF_COLLECTION) { boolean foundInPass = false; if (peekCP == CodePoint.SVRCOD) { foundInPass = true; svrcodReceived = checkAndGetReceivedFlag(svrcodReceived); svrcod = parseSVRCOD(CodePoint.SVRCOD_ERROR, CodePoint.SVRCOD_ERROR); peekCP = peekCodePoint(); } if (peekCP == CodePoint.RDBNAM) { foundInPass = true; rdbnamReceived = checkAndGetReceivedFlag(rdbnamReceived); rdbnam = parseRDBNAM(true); peekCP = peekCodePoint(); } if (peekCP == CodePoint.SRVDGN) { foundInPass = true; serverDiagnostics = parseSRVDGN(); peekCP = peekCodePoint(); } if (!foundInPass) { throwUnknownCodepoint(peekCP); // doPrmnsprmSemantics(peekCP); } } popCollectionStack(); if (!svrcodReceived) throwMissingRequiredCodepoint("SVRCOD", CodePoint.SVRCOD); // checkRequiredObjects(svrcodReceived); // move into a method // @AGG unused netAgent_.setSvrcod(svrcod); } // RDB Not Accessed Reply Message indicates that the access relational // database command (ACCRDB) was not issued prior to a command // requesting the RDB Services. // PROTOCOL Architects an SQLSTATE of 58008 or 58009. // // Messages // SQLSTATE : 58009 // Execution failed due to a distribution protocol error that caused deallocation of the conversation. // SQLCODE : -30020 // Execution failed because of a Distributed Protocol // Error that will affect the successful execution of subsequent // commands and SQL statements: Reason Code . // Some possible reason codes include: // 121C Indicates that the user is not authorized to perform the requested command. // 1232 The command could not be completed because of a permanent error. // In most cases, the server will be in the process of an abend. // 220A The target server has received an invalid data description. // If a user SQLDA is specified, ensure that the fields are // initialized correctly. Also, ensure that the length does not // exceed the maximum allowed length for the data type being used. // // The command or statement cannot be processed. The current // transaction is rolled back and the application is disconnected // from the remote database. // // // Returned from Server: // SVRCOD - required (8 - ERROR) // RDBNAM - required // // Called by all the NET*Reply classes. void parseRDBNACRM() { boolean svrcodReceived = false; int svrcod = CodePoint.SVRCOD_INFO; boolean rdbnamReceived = false; String rdbnam = null; parseLengthAndMatchCodePoint(CodePoint.RDBNACRM); pushLengthOnCollectionStack(); int peekCP = peekCodePoint(); while (peekCP != END_OF_COLLECTION) { boolean foundInPass = false; if (peekCP == CodePoint.SVRCOD) { foundInPass = true; svrcodReceived = checkAndGetReceivedFlag(svrcodReceived); svrcod = parseSVRCOD(CodePoint.SVRCOD_ERROR, CodePoint.SVRCOD_ERROR); peekCP = peekCodePoint(); } if (peekCP == CodePoint.RDBNAM) { foundInPass = true; rdbnamReceived = checkAndGetReceivedFlag(rdbnamReceived); rdbnam = parseRDBNAM(true); peekCP = peekCodePoint(); } if (!foundInPass) { throwUnknownCodepoint(peekCP); // doPrmnsprmSemantics(peekCP); } } popCollectionStack(); if (!svrcodReceived) throwMissingRequiredCodepoint("SVRCOD", CodePoint.SVRCOD); if (!rdbnamReceived) throwMissingRequiredCodepoint("RDBNAM", CodePoint.RDBNAM); // checkRequiredObjects(svrcodReceived, rdbnamReceived); // @AGG unused netAgent_.setSvrcod(svrcod); // agent_.accumulateChainBreakingReadExceptionAndThrow( // new DisconnectException(agent_, // new ClientMessageId(SQLState.DRDA_CONNECTION_TERMINATED), // msgutil_.getTextMessage(MessageId.CONN_DRDA_RDBNACRM))); throw new IllegalStateException("SQLState.DRDA_CONNECTION_TERMINATED"); } // Object Not Supported Reply Message indicates that the target // server does not recognize or support the object // specified as data in an OBJDSS for the command associated // with the object. // The OBJNSPRM is also returned if an object is found in a // valid collection in an OBJDSS (such as RECAL collection) // that that is not valid for that collection. // PROTOCOL Architects an SQLSTATE of 58015. // // Messages // SQLSTATE : 58015 // The DDM object is not supported. // SQLCODE : -30071 // Object is not supported. // The current transaction is rolled back and the application // is disconnected from the remote database. The command // cannot be processed. // // // Returned from Server: // SVRCOD - required (8 - ERROR, 16 - SEVERE) // CODPNT - required // RECCNT - optional (MINVAL 0) (will not be returned - should be ignored) // RDBNAM - optional (MINLVL 3) // // Also called by NetPackageReply and NetStatementReply void parseOBJNSPRM() { boolean svrcodReceived = false; int svrcod = CodePoint.SVRCOD_INFO; boolean rdbnamReceived = false; String rdbnam = null; boolean codpntReceived = false; int codpnt = 0; parseLengthAndMatchCodePoint(CodePoint.OBJNSPRM); pushLengthOnCollectionStack(); int peekCP = peekCodePoint(); while (peekCP != END_OF_COLLECTION) { boolean foundInPass = false; if (peekCP == CodePoint.SVRCOD) { foundInPass = true; svrcodReceived = checkAndGetReceivedFlag(svrcodReceived); svrcod = parseSVRCOD(CodePoint.SVRCOD_ERROR, CodePoint.SVRCOD_SEVERE); peekCP = peekCodePoint(); } if (peekCP == CodePoint.RDBNAM) { foundInPass = true; rdbnamReceived = checkAndGetReceivedFlag(rdbnamReceived); rdbnam = parseRDBNAM(true); peekCP = peekCodePoint(); } if (peekCP == CodePoint.CODPNT) { foundInPass = true; codpntReceived = checkAndGetReceivedFlag(codpntReceived); codpnt = parseCODPNT(); peekCP = peekCodePoint(); } // skip the RECCNT if (!foundInPass) { throwUnknownCodepoint(peekCP);; // doPrmnsprmSemantics(peekCP); } } popCollectionStack(); if (!svrcodReceived) throwMissingRequiredCodepoint("SVRCOD", CodePoint.SVRCOD); if (!codpntReceived) throwMissingRequiredCodepoint("CODPNT", CodePoint.CODPNT); // checkRequiredObjects(svrcodReceived, codpntReceived); // @AGG don't think this is used netAgent_.setSvrcod(svrcod); //doObjnsprmSemantics(codpnt); throw new IllegalStateException("SQLState.DRDA_DDM_OBJECT_NOT_SUPPORTED"); } // The Code Point Data specifies a scalar value that is an architected code point. private int parseCODPNT() { parseLengthAndMatchCodePoint(CodePoint.CODPNT); return readUnsignedShort(); } void parseDTAMCHRM() { boolean svrcodReceived = false; int svrcod = CodePoint.SVRCOD_INFO; boolean srvdgnReceived = false; String serverDiagnostics = null; boolean rdbnamReceived = false; String rdbnam = null; parseLengthAndMatchCodePoint(CodePoint.DTAMCHRM); pushLengthOnCollectionStack(); int peekCP = peekCodePoint(); while (peekCP != END_OF_COLLECTION) { boolean foundInPass = false; if (peekCP == CodePoint.SVRCOD) { foundInPass = true; svrcodReceived = checkAndGetReceivedFlag(svrcodReceived); svrcod = parseSVRCOD(CodePoint.SVRCOD_ERROR, CodePoint.SVRCOD_ERROR); peekCP = peekCodePoint(); } if (peekCP == CodePoint.RDBNAM) { foundInPass = true; rdbnamReceived = checkAndGetReceivedFlag(rdbnamReceived); rdbnam = parseRDBNAM(true); peekCP = peekCodePoint(); } // Optional code point if (peekCP == CodePoint.SRVDGN) { foundInPass = true; srvdgnReceived = checkAndGetReceivedFlag(srvdgnReceived); serverDiagnostics = parseSRVDGN(); peekCP = peekCodePoint(); } if (!foundInPass) { throwUnknownCodepoint(peekCP); //doPrmnsprmSemantics(peekCP); } } popCollectionStack(); if (!svrcodReceived) throwMissingRequiredCodepoint("SVRCOD", CodePoint.SVRCOD); if (!rdbnamReceived) throwMissingRequiredCodepoint("RDBNAM", CodePoint.RDBNAM); //checkRequiredObjects(svrcodReceived, rdbnamReceived); // @AGG not used netAgent_.setSvrcod(svrcod); throw new IllegalStateException("SQLState.DRDA_CONNECTION_TERMINATED"); //doDtamchrmSemantics(); } // Command Check Reply Message indicates that the requested // command encountered an unarchitected and implementation-specific // condition for which there is no architected message. If the severity // code value is ERROR or greater, the command has failed. The // message can be accompanied by other messages that help to identify // the specific condition. // The CMDCHKRM should not be used as a general catch-all in place of // product-defined messages when using product extensions to DDM. // PROTOCOL architects the SQLSTATE value depending on SVRCOD // SVRCOD 0 -> SQLSTATE is not returned // SVRCOD 8 -> SQLSTATE of 58008 or 58009 // SVRCOD 16,32,64,128 -> SQLSTATE of 58009 // // Messages // SQLSTATE : 58009 // Execution failed due to a distribution protocol error that caused deallocation of the conversation. // SQLCODE : -30020 // Execution failed because of a Distributed Protocol // Error that will affect the successful execution of subsequent // commands and SQL statements: Reason Code . // Some possible reason codes include: // 121C Indicates that the user is not authorized to perform the requested command. // 1232 The command could not be completed because of a permanent error. // In most cases, the server will be in the process of an abend. // 220A The target server has received an invalid data description. // If a user SQLDA is specified, ensure that the fields are // initialized correctly. Also, ensure that the length does not // exceed the maximum allowed length for the data type being used. // // The command or statement cannot be processed. The current // transaction is rolled back and the application is disconnected // from the remote database. // // // Returned from Server: // SVRCOD - required (0 - INFO, 4 - WARNING, 8 - ERROR, 16 - SEVERE, // 32 - ACCDMG, 64 - PRMDMG, 128 - SESDMG)) // RDBNAM - optional (MINLVL 3) // RECCNT - optional (MINVAL 0, MINLVL 3) // // Called by all the Reply classesCMDCHKRM void parseCMDCHKRM() { boolean svrcodReceived = false; int svrcod = CodePoint.SVRCOD_INFO; boolean rdbnamReceived = false; String rdbnam = null; parseLengthAndMatchCodePoint(CodePoint.CMDCHKRM); pushLengthOnCollectionStack(); int peekCP = peekCodePoint(); while (peekCP != END_OF_COLLECTION) { boolean foundInPass = false; if (peekCP == CodePoint.SVRCOD) { foundInPass = true; svrcodReceived = checkAndGetReceivedFlag(svrcodReceived); svrcod = parseSVRCOD(CodePoint.SVRCOD_INFO, CodePoint.SVRCOD_SESDMG); peekCP = peekCodePoint(); } if (peekCP == CodePoint.RDBNAM) { foundInPass = true; rdbnamReceived = checkAndGetReceivedFlag(rdbnamReceived); rdbnam = parseRDBNAM(true); peekCP = peekCodePoint(); } // skip over the RECCNT since it can't be found in the DDM book. if (peekCP == 0x115C) { foundInPass = true; parseLengthAndMatchCodePoint(0x115C); skipBytes(); peekCP = peekCodePoint(); } if (!foundInPass) { throwUnknownCodepoint(peekCP); //doPrmnsprmSemantics(peekCP); } } popCollectionStack(); if (!svrcodReceived) throwMissingRequiredCodepoint("SVRCOD", CodePoint.SVRCOD); // checkRequiredObjects(svrcodReceived); //netAgent_.setSvrcod(svrcod); @AGG not setting svrcod, doesn't seem to be needed NetSqlca netSqlca = parseSQLCARD(null); NetSqlca.complete(netSqlca); // agent_.accumulateChainBreakingReadExceptionAndThrow( // new DisconnectException( // agent_, // new ClientMessageId(SQLState.DRDA_CONNECTION_TERMINATED), // new SqlException(agent_.logWriter_, netSqlca), // msgutil_.getTextMessage(MessageId.CONN_DRDA_CMDCHKRM))); throw new IllegalStateException("SQLState.DRDA_CONNECTION_TERMINATED"); } // Abnormal End Unit of Work Condition Reply Message indicates // that the current unit of work ended abnormally because // of some action at the target server. This can be caused by a // deadlock resolution, operator intervention, or some similar // situation that caused the relational database to rollback // the current unit of work. This reply message is returned only // if an SQLAM issues the command. Whenever an ABNUOWRM is returned // in response to a command, an SQLCARD object must also be returned // following the ABNUOWRM. The SQLSTATE is returned in the SQLCARD. // // Returned from Server: // SVRCOD - required (8 - ERROR) // RDBNAM - required // // Called by all the NET*Reply classes. private void parseABNUOWRM() { boolean svrcodReceived = false; int svrcod = CodePoint.SVRCOD_INFO; boolean rdbnamReceived = false; parseLengthAndMatchCodePoint(CodePoint.ABNUOWRM); pushLengthOnCollectionStack(); int peekCP = peekCodePoint(); while (peekCP != END_OF_COLLECTION) { boolean foundInPass = false; if (peekCP == CodePoint.SVRCOD) { foundInPass = true; svrcodReceived = checkAndGetReceivedFlag(svrcodReceived); svrcod = parseSVRCOD(CodePoint.SVRCOD_ERROR, CodePoint.SVRCOD_ERROR); peekCP = peekCodePoint(); } if (peekCP == CodePoint.RDBNAM) { // skip the rbbnam since it doesn't tell us anything new. // there is no way to return it to the application anyway. // not having to convert this to a string is a time saver also. foundInPass = true; rdbnamReceived = checkAndGetReceivedFlag(rdbnamReceived); String rdbnam = parseRDBNAM(true); peekCP = peekCodePoint(); } if (!foundInPass) { throwUnknownCodepoint(peekCP); } } popCollectionStack(); if (!svrcodReceived) throwMissingRequiredCodepoint("SVRCOD", CodePoint.SVRCOD); if (!rdbnamReceived) throwMissingRequiredCodepoint("RDBNAM", CodePoint.RDBNAM); // the abnuowrm has been received, do whatever state changes are necessary //netAgent_.setSvrcod(svrcod); } // Relational Database Name specifies the name of a relational // database of the server. A server can have more than one RDB. String parseRDBNAM(boolean skip) { parseLengthAndMatchCodePoint(CodePoint.RDBNAM); if (skip) { skipBytes(); return null; } return readString(); }; // /** // * Perform necessary actions for parsing of a ABNUOWRM message. // * // * @param s an implementation of the StatementCallbackInterface // * // * @return an NetSqlca object obtained from parsing the ABNUOWRM // * // */ // NetSqlca parseAbnormalEndUow(StatementCallbackInterface s) { // return parseAbnormalEndUow(s.getConnectionCallbackInterface(),s); // } // // /** // * Perform necessary actions for parsing of a ABNUOWRM message. // * // * @param r an implementation of the ResultsetCallbackInterface // * // * @return an NetSqlca object obtained from parsing the ABNUOWRM // * // */ // NetSqlca parseAbnormalEndUow(ResultSetCallbackInterface r) { // return parseAbnormalEndUow(r.getConnectionCallbackInterface(),r); // } // /** // * Perform necessary actions for parsing of a ABNUOWRM message. // * // * @param connection an implementation of the ConnectionCallbackInterface // * // * @return an NetSqlca object obtained from parsing the ABNUOWRM // * // */ // private NetSqlca parseAbnormalEndUow( // ConnectionCallbackInterface connection, // UnitOfWorkListener uwl) { // // parseABNUOWRM(); // if (peekCodePoint() != CodePoint.SQLCARD) { // parseTypdefsOrMgrlvlovrs(); // } // // NetSqlca netSqlca = parseSQLCARD(null); // //// if(ExceptionUtil.getSeverityFromIdentifier(netSqlca.getSqlState()) > //// ExceptionSeverity.STATEMENT_SEVERITY || uwl == null) // connection.completeAbnormalUnitOfWork(); //// else //// connection.completeAbnormalUnitOfWork(uwl); // // return netSqlca; // } private NetSqlca parseSQLDARD(ColumnMetaData columnMetaData, boolean skipBytes) { parseLengthAndMatchCodePoint(CodePoint.SQLDARD); return parseSQLDARDarray(columnMetaData, skipBytes); } // SQLDARD : FDOCA EARLY ARRAY // SQL Descriptor Area Row Description with SQL Communications Area // // FORMAT FOR SQLAM <= 6 // SQLCARD; ROW LID 0x64; ELEMENT TAKEN 0(all); REP FACTOR 1 // SQLNUMROW; ROW LID 0x68; ELEMENT TAKEN 0(all); REP FACTOR 1 // SQLDAROW; ROW LID 0x60; ELEMENT TAKEN 0(all); REP FACTOR 0(all) // // FORMAT FOR SQLAM >= 7 // SQLCARD; ROW LID 0x64; ELEMENT TAKEN 0(all); REP FACTOR 1 // SQLDHROW; ROW LID 0xE0; ELEMENT TAKEN 0(all); REP FACTOR 1 // SQLNUMROW; ROW LID 0x68; ELEMENT TAKEN 0(all); REP FACTOR 1 // SQLDAROW; ROW LID 0x60; ELEMENT TAKEN 0(all); REP FACTOR 0(all) private NetSqlca parseSQLDARDarray(ColumnMetaData columnMetaData, boolean skipBytes) { int ddmLength = 0; // if (!ensuredLengthForDecryption_ && longValueForDecryption_ == null) { //if ensuredLength = true, means we already ensured length in decryptData, so don't need to do it again ddmLength = getDdmLength(); ensureBLayerDataInBuffer(ddmLength); // } // if (longValueForDecryption_ != null) { // buffer = longValueForDecryption_; // pos_ = 0; // count_ = longValueForDecryption_.length; // } // @AGG assuming no encryption NetSqlca netSqlca = null; if (skipBytes) { int startPos = buffer.readerIndex(); // mark(); netSqlca = parseSQLCARDrow(null); skipFastBytes(ddmLength - (buffer.readerIndex() - startPos));//getFastSkipSQLCARDrowLength()); adjustLengths(getDdmLength()); return netSqlca; } else { netSqlca = parseSQLCARDrow(null); } parseSQLDHROW(columnMetaData); // buffer.skipBytes(6); // @AGG manually added 6 byte skip int numColumns = parseSQLNUMROW(); columnMetaData.setColumnCount(numColumns); // if (columns > columnMetaData.columns_) // this will only be true when columnMetaData.columns_ = 0 under deferred prepare // // under deferred prepare the CMD arrays are not allocated until now, no guesses were made // { // columnMetaData.initializeCache(columns); // } else // column count was guessed, don't bother reallocating arrays, just truncate their lengths // { // columnMetaData.columns_ = columns; // } // is this correct for 0 SQLNUMROW // does rest of code expect a null ColumnMetaData object // or does rest of code expect an non null object // with columns_ set to 0 for (int i = 0; i < columnMetaData.columns_; i++) { parseSQLDAROW(columnMetaData, i); } // @AGG assuming no encryption // if (longValueForDecryption_ == null) { adjustLengths(getDdmLength()); // } else { // dssLength_ = 0; // longValueForDecryption_ = null; // } return netSqlca; } // SQLDAROW : FDOCA EARLY ROW // SQL Data Area Row Description // // FORMAT FOR ALL SQLAM LEVELS // SQLDAGRP; GROUP LID 0x50; ELEMENT TAKEN 0(all); REP FACTOR 1 private void parseSQLDAROW(ColumnMetaData columnMetaData, int columnNumber) { parseSQLDAGRP(columnMetaData, columnNumber); } // SQLDAGRP : EARLY FDOCA GROUP // SQL Data Area Group Description // // FORMAT FOR SQLAM <= 6 // SQLPRECISION; PROTOCOL TYPE I2; ENVLID 0x04; Length Override 2 // SQLSCALE; PROTOCOL TYPE I2; ENVLID 0x04; Length Override 2 // SQLLENGTH; PROTOCOL TYPE I4; ENVLID 0x02; Length Override 4 // SQLTYPE; PROTOCOL TYPE I2; ENVLID 0x04; Length Override 2 // SQLCCSID; PROTOCOL TYPE FB; ENVLID 0x26; Length Override 2 // SQLNAME_m; PROTOCOL TYPE VCM; ENVLID 0x3E; Length Override 30 // SQLNAME_s; PROTOCOL TYPE VCS; ENVLID 0x32; Length Override 30 // SQLLABEL_m; PROTOCOL TYPE VCM; ENVLID 0x3E; Length Override 30 // SQLLABEL_s; PROTOCOL TYPE VCS; ENVLID 0x32; Length Override 30 // SQLCOMMENTS_m; PROTOCOL TYPE VCM; ENVLID 0x3E; Length Override 254 // SQLCOMMENTS_m; PROTOCOL TYPE VCS; ENVLID 0x32; Length Override 254 // // FORMAT FOR SQLAM == 6 // SQLPRECISION; PROTOCOL TYPE I2; ENVLID 0x04; Length Override 2 // SQLSCALE; PROTOCOL TYPE I2; ENVLID 0x04; Length Override 2 // SQLLENGTH; PROTOCOL TYPE I8; ENVLID 0x16; Length Override 8 // SQLTYPE; PROTOCOL TYPE I2; ENVLID 0x04; Length Override 2 // SQLCCSID; PROTOCOL TYPE FB; ENVLID 0x26; Length Override 2 // SQLNAME_m; PROTOCOL TYPE VCM; ENVLID 0x3E; Length Override 30 // SQLNAME_s; PROTOCOL TYPE VCS; ENVLID 0x32; Length Override 30 // SQLLABEL_m; PROTOCOL TYPE VCM; ENVLID 0x3E; Length Override 30 // SQLLABEL_s; PROTOCOL TYPE VCS; ENVLID 0x32; Length Override 30 // SQLCOMMENTS_m; PROTOCOL TYPE VCM; ENVLID 0x3E; Length Override 254 // SQLCOMMENTS_m; PROTOCOL TYPE VCS; ENVLID 0x32; Length Override 254 // SQLUDTGRP; PROTOCOL TYPE N-GDA; ENVLID 0x51; Length Override 0 // // FORMAT FOR SQLAM >= 7 // SQLPRECISION; PROTOCOL TYPE I2; ENVLID 0x04; Length Override 2 // SQLSCALE; PROTOCOL TYPE I2; ENVLID 0x04; Length Override 2 // SQLLENGTH; PROTOCOL TYPE I8; ENVLID 0x16; Length Override 8 // SQLTYPE; PROTOCOL TYPE I2; ENVLID 0x04; Length Override 2 // SQLCCSID; PROTOCOL TYPE FB; ENVLID 0x26; Length Override 2 // SQLDOPTGRP; PROTOCOL TYPE N-GDA; ENVLID 0xD2; Length Override 0 private void parseSQLDAGRP(ColumnMetaData columnMetaData, int columnNumber) { long columnLength = 0; // 2-byte precision int precision = readFastShort(); // 2-byte scale int scale = readFastShort(); // 8 byte sqllength columnLength = readFastLong(); // create a set method after sqlType and ccsid is read // possibly have it set the nullable int sqlType = readFastShort(); // 2-byte sqlccsid // (NOTE: SQLCCSID is always flown as BIG ENDIAN, not as data!) // The C-Common Client also does the following: // 1. Determine which type of code page is to be used for this variable: // 2. Map the CCSID to the correct codepage: // 3. "Split" the CCSID to see whether it is for SBCS or MBCS: int ccsid = readFastUnsignedShort(); columnMetaData.sqlPrecision_[columnNumber] = precision; columnMetaData.sqlScale_[columnNumber] = scale; columnMetaData.sqlLength_[columnNumber] = columnLength; columnMetaData.sqlType_[columnNumber] = sqlType; // Set the nullables columnMetaData.nullable_[columnNumber] = (sqlType | 0x01) == sqlType; //Utils.isSqlTypeNullable(sqlType); columnMetaData.sqlCcsid_[columnNumber] = ccsid; columnMetaData.types_[columnNumber] = ClientTypes.mapDB2TypeToDriverType( true, sqlType, columnLength, ccsid); // true means isDescribed parseSQLDOPTGRP(columnMetaData, columnNumber); } // SQLDOPTGRP : EARLY FDOCA GROUP // SQL Descriptor Optional Group Description // // FORMAT FOR SQLAM >= 7 // SQLUNNAMED; PROTOCOL TYPE I2; ENVLID 0x04; Length Override 2 // SQLNAME_m; PROTOCOL TYPE VCM; ENVLID 0x3E; Length Override 255 // SQLNAME_s; PROTOCOL TYPE VCS; ENVLID 0x32; Length Override 255 // SQLLABEL_m; PROTOCOL TYPE VCM; ENVLID 0x3E; Length Override 255 // SQLLABEL_s; PROTOCOL TYPE VCS; ENVLID 0x32; Length Override 255 // SQLCOMMENTS_m; PROTOCOL TYPE VCM; ENVLID 0x3E; Length Override 255 // SQLCOMMENTS_s; PROTOCOL TYPE VCS; ENVLID 0x32; Length Override 255 // SQLUDTGRP; PROTOCOL TYPE N-GDA; ENVLID 0x5B; Length Override 0 // SQLDXGRP; PROTOCOL TYPE N-GDA; ENVLID 0xD4; Length Override 0 private void parseSQLDOPTGRP(ColumnMetaData columnMetaData, int columnNumber) { if (readFastUnsignedByte() == CodePoint.NULLDATA) { return; } // SQLUNNAMED; PROTOCOL TYPE I2; ENVLID 0x04; Length Override 2 // has value of 0 or 1. Value of 1 indicates name is generated by the DB. // Value of 0 otherwise short sqlunnamed = readFastShort(); // 0 or 1 // SQLNAME_m; PROTOCOL TYPE VCM; ENVLID 0x3E; Length Override 255 // SQLNAME_s; PROTOCOL TYPE VCS; ENVLID 0x32; Length Override 255 String name = parseFastVCMorVCS(); // * or id? // SQLLABEL_m; PROTOCOL TYPE VCM; ENVLID 0x3E; Length Override 255 // SQLLABEL_s; PROTOCOL TYPE VCS; ENVLID 0x32; Length Override 255 String label = parseFastVCMorVCS(); // id? // SQLCOMMENTS_m; PROTOCOL TYPE VCM; ENVLID 0x3E; Length Override 255 // SQLCOMMENTS_s; PROTOCOL TYPE VCS; ENVLID 0x32; Length Override 255 String colComments = parseFastVCMorVCS(); if (columnMetaData.sqlName_ == null) { columnMetaData.sqlName_ = new String[columnMetaData.columns_]; } if (columnMetaData.sqlLabel_ == null) { columnMetaData.sqlLabel_ = new String[columnMetaData.columns_]; } if (columnMetaData.sqlUnnamed_ == null) { columnMetaData.sqlUnnamed_ = new short[columnMetaData.columns_]; } if (columnMetaData.sqlComment_ == null) { columnMetaData.sqlComment_ = new String[columnMetaData.columns_]; } columnMetaData.sqlName_[columnNumber] = name; columnMetaData.sqlLabel_[columnNumber] = label; columnMetaData.sqlUnnamed_[columnNumber] = sqlunnamed; columnMetaData.sqlComment_[columnNumber] = colComments; // possibly move all the assignments into a single method on the columnMetaData object parseSQLUDTGRP(columnMetaData, columnNumber); parseSQLDXGRP(columnMetaData, columnNumber); } // SQLUDTGRP : EARLY FDOCA GROUP // SQL User-Defined Data Group Description // // For an explanation of the format, see the header comment on // DRDAConnThread.writeSQLUDTGRP(). // private void parseSQLUDTGRP(ColumnMetaData columnMetaData, int columnNumber) { int jdbcType = columnMetaData.types_[columnNumber]; if (!(jdbcType == ClientTypes.JAVA_OBJECT)) { // || // !netAgent_.netConnection_.serverSupportsUDTs()) { // @AGG assume supported if (readFastUnsignedByte() == CodePoint.NULLDATA) { return; } } else { String typeName = parseFastVCMorVCS(); String className = parseFastVCMorVCS(); columnMetaData.sqlUDTname_[columnNumber] = typeName; columnMetaData.sqlUDTclassName_[columnNumber] = className; } } // SQLDXGRP : EARLY FDOCA GROUP // SQL Descriptor Extended Group Description // // FORMAT FOR SQLAM >=7 // SQLXKEYMEM; PROTOCOL TYPE I2; ENVLID 0x04; Length Override 2 // SQLXUPDATEABLE; PROTOCOL TYPE I2; ENVLID 0x04; Length Override 2 // SQLXGENERATED; PROTOCOL TYPE I2; ENVLID 0x04; Length Override 2 // SQLXPARMMODE; PROTOCOL TYPE I2; ENVLID 0x04; Length Override 2 // SQLXRDBNAM; PROTOCOL TYPE VCS; ENVLID 0x32; Length Override 1024 // SQLXCORNAME_m; PROTOCOL TYPE VCM; ENVLID 0x3E; Length Override 255 // SQLXCORNAME_s; PROTOCOL TYPE VCS; ENVLID 0x32; Length Override 255 // SQLXBASENAME_m; PROTOCOL TYPE VCM; ENVLID 0x3E; Length Override 255 // SQLXBASENAME_s; PROTOCOL TYPE VCS; ENVLID 0x32; Length Override 255 // SQLXSCHEMA_m; PROTOCOL TYPE VCM; ENVLID 0x3E; Length Override 255 // SQLXSCHEMA_s; PROTOCOL TYPE VCS; ENVLID 0x32; Length Override 255 // SQLXNAME_m; PROTOCOL TYPE VCM; ENVLID 0x3E; Length Override 255 // SQLXNAME_s; PROTOCOL TYPE VCS; ENVLID 0x32; Length Override 255 private void parseSQLDXGRP(ColumnMetaData columnMetaData, int column) { if (readFastUnsignedByte() == CodePoint.NULLDATA) { return; } //buffer.skipBytes(8); // @AGG manually skip 8 bytes // SQLXKEYMEM; PROTOCOL TYPE I2; ENVLID 0x04; Length Override 2 short sqlxkeymem = readFastShort(); // primary key == 1 // SQLXUPDATEABLE; PROTOCOL TYPE I2; ENVLID 0x04; Length Override 2 short sqlxupdateable = readFastShort(); // 0 or 1 // SQLXGENERATED; PROTOCOL TYPE I2; ENVLID 0x04; Length Override 2 short sqlxgenerated = readFastShort(); // 0 // SQLXPARMMODE; PROTOCOL TYPE I2; ENVLID 0x04; Length Override 2 short sqlxparmmode = readFastShort(); // 0 // SQLXRDBNAM; PROTOCOL TYPE VCS; ENVLID 0x32; Length Override 1024 String sqlxrdbnam = parseFastVCS(); // db name // SQLXCORNAME_m; PROTOCOL TYPE VCM; ENVLID 0x3E; Length Override 255 // SQLXCORNAME_s; PROTOCOL TYPE VCS; ENVLID 0x32; Length Override 255 String sqlxcorname = parseFastVCMorVCS(); // null or USERS? // SQLXBASENAME_m; PROTOCOL TYPE VCM; ENVLID 0x3E; Length Override 255 // SQLXBASENAME_s; PROTOCOL TYPE VCS; ENVLID 0x32; Length Override 255 String sqlxbasename = parseFastVCMorVCS(); // USERS // SQLXSCHEMA_m; PROTOCOL TYPE VCM; ENVLID 0x3E; Length Override 255 // SQLXSCHEMA_s; PROTOCOL TYPE VCS; ENVLID 0x32; Length Override 255 String sqlxschema = parseFastVCMorVCS(); // username // SQLXNAME_m; PROTOCOL TYPE VCM; ENVLID 0x3E; Length Override 255 // SQLXNAME_s; PROTOCOL TYPE VCS; ENVLID 0x32; Length Override 255 String sqlxname = parseFastVCMorVCS(); // ID if (columnMetaData.sqlxKeymem_ == null) { columnMetaData.sqlxKeymem_ = new short[columnMetaData.columns_]; } if (columnMetaData.sqlxGenerated_ == null) { columnMetaData.sqlxGenerated_ = new short[columnMetaData.columns_]; } if (columnMetaData.sqlxParmmode_ == null) { columnMetaData.sqlxParmmode_ = new short[columnMetaData.columns_]; } if (columnMetaData.sqlxCorname_ == null) { columnMetaData.sqlxCorname_ = new String[columnMetaData.columns_]; } if (columnMetaData.sqlxName_ == null) { columnMetaData.sqlxName_ = new String[columnMetaData.columns_]; } if (columnMetaData.sqlxBasename_ == null) { columnMetaData.sqlxBasename_ = new String[columnMetaData.columns_]; } if (columnMetaData.sqlxUpdatable_ == null) { columnMetaData.sqlxUpdatable_ = new int[columnMetaData.columns_]; } if (columnMetaData.sqlxSchema_ == null) { columnMetaData.sqlxSchema_ = new String[columnMetaData.columns_]; } if (columnMetaData.sqlxRdbnam_ == null) { columnMetaData.sqlxRdbnam_ = new String[columnMetaData.columns_]; } columnMetaData.sqlxKeymem_[column] = sqlxkeymem; columnMetaData.sqlxGenerated_[column] = sqlxgenerated; columnMetaData.sqlxParmmode_[column] = sqlxparmmode; columnMetaData.sqlxCorname_[column] = sqlxcorname; columnMetaData.sqlxName_[column] = sqlxname; columnMetaData.sqlxBasename_[column] = sqlxbasename; columnMetaData.sqlxUpdatable_[column] = sqlxupdateable; columnMetaData.sqlxSchema_[column] = (sqlxschema == null) ? columnMetaData.sqldSchema_ : sqlxschema; columnMetaData.sqlxRdbnam_[column] = (sqlxrdbnam == null) ? columnMetaData.sqldRdbnam_ : sqlxrdbnam; } // SQLDHROW : FDOCA EARLY ROW // SQL Descriptor Header Row Description // // FORMAT FOR SQLAM >= 7 // SQLDHGRP; GROUP LID 0xD0; ELEMENT TAKEN 0(all); REP FACTOR 1 private void parseSQLDHROW(ColumnMetaData columnMetaData) { parseSQLDHGRP(columnMetaData); } // SQLDHGRP : EARLY FDOCA GROUP // SQL Descriptor Header Group Description // See DRDA V3 Vol 1 pg. 288 // // FORMAT FOR SQLAM >= 7 // SQLDHOLD; PROTOCOL TYPE I2; ENVLID 0x04; Length Override 2 // SQLDRETURN; PROTOCOL TYPE I2; ENVLID 0x04; Length Override 2 // SQLDSCROLL; PROTOCOL TYPE I2; ENVLID 0x04; Length Override 2 // SQLDSENSITIVE; PROTOCOL TYPE I2; ENVLID 0x04; Length Override 2 // SQLDFCODE; PROTOCOL TYPE I2; ENVLID 0x04; Length Override 2 // SQLDKEYTYPE; PROTOCOL TYPE I2; ENVLID 0x04; Length Override 2 // SQLDRDBNAM; PROTOCOL TYPE VCS; ENVLID 0x32; Length Override 1024 // SQLDSCHEMA_m; PROTOCOL TYPE VCM; ENVLID 0x3E; Length Override 255 // SQLDSCHEMA_s; PROTOCOL TYPE VCS; ENVLID 0x32; Length Override 255 private void parseSQLDHGRP(ColumnMetaData columnMetaData) { if (readFastUnsignedByte() == CodePoint.NULLDATA) { return; } // SQLDHOLD; PROTOCOL TYPE I2; ENVLID 0x04; Length Override 2 // value of 0 or 1. Value of 1 indicates WITH HOLD. Otherwise 0 short sqldhold = readFastShort(); // SQLDRETURN; PROTOCOL TYPE I2; ENVLID 0x04; Length Override 2 // value of 0, 1, or 2. Value of 1 indicates WITH RETURN CLIENT. // value of 2 indicates WITH RETURN CALLER. Otherwise 0 short sqldreturn = readFastShort(); // SQLDSCROLL; PROTOCOL TYPE I2; ENVLID 0x04; Length Override 2 // Value of 1 indicates stmt related to a cursor with SCROLL clause. Otherwise 0 short sqldscroll = readFastShort(); // SQLDSENSITIVE; PROTOCOL TYPE I2; ENVLID 0x04; Length Override 2 // 0 statement not related to a cursor and SQLDSCROLL field has value of 0 // 1 statement related to cursor that is SENSITIVE DYNAMIC // 2 statement related to cursor that is SENSITIVE STATIC // 3 statement related to cursor that is INSENSITIVE short sqldsensitive = readFastShort(); // SQLDFCODE; PROTOCOL TYPE I2; ENVLID 0x04; Length Override 2 // Type of SQL statement short sqldfcode = readFastShort(); // SQLDKEYTYPE; PROTOCOL TYPE I2; ENVLID 0x04; Length Override 2 // 0 key type when descriptor is not describing the column of a query; for example, a describe input // 1 The select list includes all the columns of the primary key of // 2 The table referenced by the query does not have a primary key but the select list includes a set of columns that are short sqldkeytype = readFastShort(); // SQLDRDBNAM; PROTOCOL TYPE VCS; ENVLID 0x32; Length Override 1024 String sqldrdbnam = parseFastVCS(); // SQLDSCHEMA_m; PROTOCOL TYPE VCM; ENVLID 0x3E; Length Override 255 // SQLDSCHEMA_s; PROTOCOL TYPE VCS; ENVLID 0x32; Length Override 255 String sqldschema = parseFastVCMorVCS(); columnMetaData.sqldHold_ = sqldhold; columnMetaData.sqldReturn_ = sqldreturn; columnMetaData.sqldScroll_ = sqldscroll; columnMetaData.sqldSensitive_ = sqldsensitive; columnMetaData.sqldFcode_ = sqldfcode; columnMetaData.sqldKeytype_ = sqldkeytype; columnMetaData.sqldRdbnam_ = sqldrdbnam; columnMetaData.sqldSchema_ = sqldschema; } // final int getFastSkipSQLCARDrowLength() { // return pos_ - popMark(); // } protected final boolean peekForNullSqlcagrp() { // skip the 4-byte LLCP and any extended length bytes int offset = (4 + peekedNumOfExtendedLenBytes_); int nullInd = buffer.getByte(buffer.readerIndex() + offset); //int nullInd = buffer_[pos_ + offset] & 0xff; return (nullInd == CodePoint.NULLDATA); } protected final int peekNumOfColumns() { // skip the 4-byte LLCP and any extended length bytes + 1-byte null sqlcagrp null indicator int offset = (4 + peekedNumOfExtendedLenBytes_ + 1); offset = skipSQLDHROW(offset); //return SignedBinary.getShort(buffer_, pos_ + offset); if (metadata.isZos()) return buffer.getShort(buffer.readerIndex() + offset); else return buffer.getShortLE(buffer.readerIndex() + offset); } private int skipSQLDHROW(int offset) { buffer.markReaderIndex(); buffer.readerIndex(offset); //int sqldhrowgrpNullInd = buffer_[pos_ + offset++] & 0xff; int sqldhrowgrpNullInd = buffer.readByte(); if (sqldhrowgrpNullInd == CodePoint.NULLDATA) { return offset; } offset += 12; // skip sqldrdbnam // int stringLength = ((buffer_[pos_ + offset++] & 0xff) << 8) + // ((buffer_[pos_ + offset++] & 0xff) << 0); int stringLength = buffer.readShort(); offset += stringLength; // skip sqldschema // stringLength = ((buffer_[pos_ + offset++] & 0xff) << 8) + // ((buffer_[pos_ + offset++] & 0xff) << 0); stringLength = buffer.readShort(); offset += stringLength; // stringLength = ((buffer_[pos_ + offset++] & 0xff) << 8) + // ((buffer_[pos_ + offset++] & 0xff) << 0); stringLength = buffer.readShort(); offset += stringLength; buffer.resetReaderIndex(); return offset; } }





© 2015 - 2024 Weber Informatics LLC | Privacy Policy