0001 /*
0002 
0003    Derby - Class org.apache.derby.client.net.NetStatementReply
0004 
0005    Copyright (c) 2001, 2005 The Apache Software Foundation or its licensors, where applicable.
0006 
0007    Licensed under the Apache License, Version 2.0 (the "License");
0008    you may not use this file except in compliance with the License.
0009    You may obtain a copy of the License at
0010 
0011       http://www.apache.org/licenses/LICENSE-2.0
0012 
0013    Unless required by applicable law or agreed to in writing, software
0014    distributed under the License is distributed on an "AS IS" BASIS,
0015    WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
0016    See the License for the specific language governing permissions and
0017    limitations under the License.
0018 
0019 */
0020 
0021 package org.apache.derby.client.net;
0022 
0023 import org.apache.derby.client.am.ColumnMetaData;
0024 import org.apache.derby.client.am.DisconnectException;
0025 import org.apache.derby.client.am.PreparedStatementCallbackInterface;
0026 import org.apache.derby.client.am.ResultSetCallbackInterface;
0027 import org.apache.derby.client.am.Section;
0028 import org.apache.derby.client.am.SqlState;
0029 import org.apache.derby.client.am.Statement;
0030 import org.apache.derby.client.am.StatementCallbackInterface;
0031 import org.apache.derby.client.am.Types;
0032 import org.apache.derby.client.am.Utils;
0033 
0034 
0035 public class NetStatementReply extends NetPackageReply implements StatementReplyInterface {
0036     NetStatementReply(NetAgent netAgent, int bufferSize) {
0037         super(netAgent, bufferSize);
0038     }
0039 
0040     //----------------------------- entry points ---------------------------------
0041 
0042     public void readPrepareDescribeOutput(StatementCallbackInterface statementthrows DisconnectException {
0043         startSameIdChainParse();
0044         parsePRPSQLSTTreply(statement);
0045         endOfSameIdChainData();
0046     }
0047 
0048     public void readExecuteImmediate(StatementCallbackInterface statementthrows DisconnectException {
0049         startSameIdChainParse();
0050         parseEXCSQLIMMreply(statement);
0051         endOfSameIdChainData();
0052     }
0053 
0054     public void readOpenQuery(StatementCallbackInterface statementthrows DisconnectException {
0055         startSameIdChainParse();
0056         parseOPNQRYreply(statement);
0057         endOfSameIdChainData();
0058     }
0059 
0060     public void readExecute(PreparedStatementCallbackInterface preparedStatementthrows DisconnectException {
0061         startSameIdChainParse();
0062         parseEXCSQLSTTreply(preparedStatement);
0063         endOfSameIdChainData();
0064     }
0065 
0066     public void readPrepare(StatementCallbackInterface statementthrows DisconnectException {
0067         startSameIdChainParse();
0068         parsePRPSQLSTTreply(statement);
0069         endOfSameIdChainData();
0070     }
0071 
0072     public void readDescribeInput(PreparedStatementCallbackInterface preparedStatementthrows DisconnectException {
0073         if (longBufferForDecryption_ != null) {
0074             buffer_ = longBufferForDecryption_;
0075             pos_ = longPosForDecryption_;
0076             count_ = longCountForDecryption_;
0077             if (longBufferForDecryption_ != null && count_ > longBufferForDecryption_.length) {
0078                 count_ = longBufferForDecryption_.length;
0079             }
0080             dssLength_ = 0;
0081             longBufferForDecryption_ = null;
0082         }
0083 
0084         startSameIdChainParse();
0085         parseDSCSQLSTTreply(preparedStatement, 1)// anything other than 0 for input
0086         endOfSameIdChainData();
0087     }
0088 
0089     public void readDescribeOutput(PreparedStatementCallbackInterface preparedStatementthrows DisconnectException {
0090         startSameIdChainParse();
0091         parseDSCSQLSTTreply(preparedStatement, 0);  // 0 for output
0092         endOfSameIdChainData();
0093     }
0094 
0095     public void readExecuteCall(StatementCallbackInterface statementthrows DisconnectException {
0096         startSameIdChainParse();
0097         parseEXCSQLSTTreply(statement);
0098         endOfSameIdChainData();
0099     }
0100 
0101 
0102     //----------------------helper methods----------------------------------------
0103 
0104     //------------------parse reply for specific command--------------------------
0105 
0106     // These methods are "private protected", which is not a recognized java privilege,
0107     // but means that these methods are private to this class and to subclasses,
0108     // and should not be used as package-wide friendly methods.
0109 
0110     private void parsePRPSQLSTTreply(StatementCallbackInterface statementthrows DisconnectException {
0111         int peekCP = parseTypdefsOrMgrlvlovrs();
0112 
0113         if (peekCP == CodePoint.SQLDARD) {
0114             // the sqlcagrp is most likely null for insert/update/deletes.  if it is null, then we can
0115             // peek ahead for the column number which most likely will be 0.  if it is 0, then we will
0116             // not new up a ColumnMetaData, and we can skip the rest of the bytes in sqldard.
0117             // if sqlcargrp is not null, (most likely for select's) then we will not peek ahead for the
0118             // column number since it will never be 0 in a select case.
0119             ColumnMetaData columnMetaData = null;
0120             NetSqlca netSqlca = null;
0121             boolean nullSqlca = peekForNullSqlcagrp();
0122             if (nullSqlca && peekNumOfColumns() == 0) {
0123                 netSqlca = parseSQLDARD(columnMetaData, true)// true means to skip the rest of SQLDARD bytes
0124             else {
0125                 columnMetaData = new ColumnMetaData(netAgent_.logWriter_);
0126                 netSqlca = parseSQLDARD(columnMetaData, false)// false means do not skip SQLDARD bytes.
0127             }
0128 
0129             statement.completePrepareDescribeOutput(columnMetaData,
0130                     netSqlca);
0131         else if (peekCP == CodePoint.SQLCARD) {
0132             NetSqlca netSqlca = parseSQLCARD(null);
0133             statement.completePrepare(netSqlca);
0134         else {
0135             parsePrepareError(statement);
0136         }
0137 
0138     }
0139 
0140     // Parse the reply for the Describe SQL Statement Command.
0141     // This method handles the parsing of all command replies and reply data
0142     // for the dscsqlstt command.
0143     private void parseDSCSQLSTTreply(PreparedStatementCallbackInterface ps,
0144                                      int metaDataType// 0 is output, else input
0145             throws DisconnectException {
0146         int peekCP = parseTypdefsOrMgrlvlovrs();
0147 
0148         if (peekCP == CodePoint.SQLDARD) {
0149             ColumnMetaData columnMetaData = null;
0150 
0151             if (columnMetaData == null) {
0152                 columnMetaData = new ColumnMetaData(netAgent_.logWriter_);
0153             }
0154 
0155             NetSqlca netSqlca = parseSQLDARD(columnMetaData, false);  // false means do not skip SQLDARD bytes
0156             if (columnMetaData.columns_ == 0) {
0157                 columnMetaData = null;
0158             }
0159 
0160             if (metaDataType == 0// DESCRIBE OUTPUT
0161             {
0162                 ps.completeDescribeOutput(columnMetaData, netSqlca);
0163             else {
0164                 ps.completeDescribeInput(columnMetaData, netSqlca);
0165             }
0166         else if (peekCP == CodePoint.SQLCARD) {
0167             NetSqlca netSqlca = parseSQLCARD(null);
0168             if (metaDataType == 0// DESCRIBE OUTPUT
0169             {
0170                 ps.completeDescribeOutput(null, netSqlca);
0171             else {
0172                 ps.completeDescribeInput(null, netSqlca);
0173             }
0174         else {
0175             parseDescribeError(ps);
0176         }
0177 
0178     }
0179 
0180     // Parse the reply for the Execute Immediate SQL Statement Command.
0181     // This method handles the parsing of all command replies and reply data
0182     // for the excsqlimm command.
0183     private void parseEXCSQLIMMreply(StatementCallbackInterface statementthrows DisconnectException {
0184         int peekCP = parseTypdefsOrMgrlvlovrs();
0185 
0186         if (peekCP == CodePoint.RDBUPDRM) {
0187             parseRDBUPDRM();
0188             peekCP = parseTypdefsOrMgrlvlovrs();
0189         }
0190 
0191         switch (peekCP) {
0192         case CodePoint.ENDUOWRM:
0193             parseENDUOWRM(statement.getConnectionCallbackInterface());
0194             parseTypdefsOrMgrlvlovrs();
0195         case CodePoint.SQLCARD:
0196             NetSqlca netSqlca = parseSQLCARD(null);
0197 
0198 
0199             statement.completeExecuteImmediate(netSqlca);
0200             break;
0201         default:
0202             parseExecuteImmediateError(statement);
0203             break;
0204         }
0205 
0206     }
0207 
0208     // Parse the reply for the Open Query Command.
0209     // This method handles the parsing of all command replies and reply data for the opnqry command.
0210     // will be replaced by parseOPNQRYreply (see parseOPNQRYreplyProto)
0211     private void parseOPNQRYreply(StatementCallbackInterface statementIthrows DisconnectException {
0212         int peekCP = peekCodePoint();
0213 
0214         if (peekCP == CodePoint.OPNQRYRM) {
0215             parseOpenQuery(statementI);
0216             peekCP = peekCodePoint();
0217             if (peekCP == CodePoint.RDBUPDRM) {
0218                 parseRDBUPDRM();
0219                 peekCP = peekCodePoint();
0220             }
0221         else if (peekCP == CodePoint.RDBUPDRM) {
0222             parseRDBUPDRM();
0223             parseOpenQuery(statementI);
0224             peekCP = peekCodePoint();
0225         else if (peekCP == CodePoint.OPNQFLRM) {
0226             parseOpenQueryFailure(statementI);
0227             peekCP = peekCodePoint();
0228         else {
0229             parseOpenQueryError(statementI);
0230             peekCP = peekCodePoint();
0231         }
0232 
0233     }
0234 
0235     // Called by NETSetClientPiggybackCommand.read()
0236     private void parseEXCSQLSETreply(StatementCallbackInterface statementthrows DisconnectException {
0237         int peekCP = parseTypdefsOrMgrlvlovrs();
0238 
0239         if (peekCP == CodePoint.RDBUPDRM) {
0240             parseRDBUPDRM();
0241             parseTypdefsOrMgrlvlovrs();
0242         else if (peekCP == CodePoint.ENDUOWRM) {
0243             parseENDUOWRM(statement.getConnectionCallbackInterface());
0244             parseTypdefsOrMgrlvlovrs();
0245         }
0246 
0247         if (peekCP == CodePoint.SQLCARD) {
0248             NetSqlca netSqlca = parseSQLCARD(null);
0249             statement.completeExecuteSetStatement(netSqlca);
0250         else {
0251             parseExecuteSetStatementError(statement);
0252         }
0253 
0254     }
0255 
0256     // Parse the reply for the Execute SQL Statement Command.
0257     // This method handles the parsing of all command replies and reply data
0258     // for the excsqlstt command.
0259     // Also called by CallableStatement.readExecuteCall()
0260     private void parseEXCSQLSTTreply(StatementCallbackInterface statementIthrows DisconnectException {
0261         // first handle the transaction component, which consists of one or more
0262         // reply messages indicating the transaction state.
0263         // These are ENDUOWRM, CMMRQSRM, or RDBUPDRM.  If RDBUPDRM is returned,
0264         // it may be followed by ENDUOWRM or CMMRQSRM
0265         int peekCP = peekCodePoint();
0266         if (peekCP == CodePoint.RDBUPDRM) {
0267             parseRDBUPDRM();
0268             peekCP = peekCodePoint();
0269         }
0270 
0271         if (peekCP == CodePoint.ENDUOWRM) {
0272             parseENDUOWRM(statementI.getConnectionCallbackInterface());
0273             peekCP = peekCodePoint();
0274         }
0275 
0276         // Check for a RSLSETRM, this is first rm of the result set summary component
0277         // which would be returned if a stored procedure was called which returned result sets.
0278         if (peekCP == CodePoint.RSLSETRM) {
0279             parseResultSetProcedure(statementI);
0280             peekCP = peekCodePoint();
0281             if (peekCP == CodePoint.RDBUPDRM) {
0282                 parseRDBUPDRM();
0283             }
0284             return;
0285         }
0286 
0287         // check for a possible TYPDEFNAM or TYPDEFOVR which may be present
0288         // before the SQLCARD or SQLDTARD.
0289         peekCP = parseTypdefsOrMgrlvlovrs();
0290 
0291         // an SQLCARD may be retunred if there was no output data, result sets or parameters,
0292         // or in the case of an error.
0293         if (peekCP == CodePoint.SQLCARD) {
0294             NetSqlca netSqlca = parseSQLCARD(null);
0295 
0296             statementI.completeExecute(netSqlca);
0297         else if (peekCP == CodePoint.SQLDTARD) {
0298             // in the case of singleton select or if a stored procedure was called which had
0299             // parameters but no result sets, an SQLSTARD may be returned
0300             // keep the PreparedStatementCallbackInterface, since only preparedstatement and callablestatement
0301             // has parameters or singleton select which translates to sqldtard.
0302             NetSqldta netSqldta = null;
0303             boolean useCachedSingletonRowData = false;
0304             if (((StatementstatementI).cachedSingletonRowData_ == null) {
0305                 netSqldta = new NetSqldta(netAgent_);
0306             else {
0307                 netSqldta = (NetSqldta) ((StatementstatementI).cachedSingletonRowData_;
0308                 netSqldta.resetDataBuffer();
0309                 netSqldta.extdtaData_.clear();
0310                 useCachedSingletonRowData = true;
0311             }
0312             NetSqlca netSqlca =
0313                     parseSQLDTARD(netSqldta);
0314 
0315             // there may be externalized LOB data which also gets returned.
0316             peekCP = peekCodePoint();
0317             while (peekCP == CodePoint.EXTDTA) {
0318                 copyEXTDTA(netSqldta);
0319                 peekCP = peekCodePoint();
0320             }
0321             statementI.completeExecuteCall(netSqlca, netSqldta);
0322         else {
0323             // if here, then assume an error reply message was returned.
0324             parseExecuteError(statementI);
0325         }
0326 
0327     }
0328 
0329     protected void parseResultSetProcedure(StatementCallbackInterface statementIthrows DisconnectException {
0330         // when a stored procedure is called which returns result sets,
0331         // the next thing to be returned after the optional transaction component
0332         // is the summary component.
0333         //
0334         // Parse the Result Set Summary Component which consists of a
0335         // Result Set Reply Message, SQLCARD or SQLDTARD, and an SQL Result Set
0336         // Reply data object.  Also check for possible TYPDEF overrides before the
0337         // OBJDSSs.
0338         // This method returns an ArrayList of generated sections which contain the
0339         // package and section information for the result sets which were opened on the
0340         // server.
0341 
0342         // the result set summary component consists of a result set reply message.
0343         java.util.ArrayList sectionAL = parseRSLSETRM();
0344 
0345         // following the RSLSETRM is an SQLCARD or an SQLDTARD.  check for a
0346         // TYPDEFNAM or TYPDEFOVR before looking for these objects.
0347         int peekCP = parseTypdefsOrMgrlvlovrs();
0348 
0349         // The SQLCARD and the SQLDTARD are mutually exclusive.
0350         // The SQLDTARD is returned if the stored procedure had parameters.
0351         // (Note: the SQLDTARD contains an sqlca also.  this is the sqlca for the
0352         // stored procedure call.
0353         NetSqldta netSqldta = null;
0354         NetSqlca netSqlca = null;
0355         if (peekCP == CodePoint.SQLCARD) {
0356             netSqlca = parseSQLCARD(null);
0357         else {
0358             // keep the PreparedStatementCallbackInterface, since only preparedstatement and callablestatement
0359             // has parameters or singleton select which translates to sqldtard.
0360             netSqldta = new NetSqldta(netAgent_);
0361             netSqlca = parseSQLDTARD(netSqldta);
0362         }
0363 
0364         // check for a possible TYPDEFNAM or TYPDEFOVR
0365         // before the SQL Result Set Reply Data object
0366         peekCP = parseTypdefsOrMgrlvlovrs();
0367 
0368         int numberOfResultSets = parseSQLRSLRD(sectionAL);
0369 
0370         // The result set summary component parsed above indicated how many result sets were opened
0371         // by the stored pocedure call.  It contained section information for
0372         // each of these result sets.  Loop through the section array and
0373         // parse the result set component for each of the retunred result sets.
0374         NetResultSet[] resultSets = new NetResultSet[numberOfResultSets];
0375         for (int i = 0; i < numberOfResultSets; i++) {
0376             // parse the result set component of the stored procedure reply.
0377             NetResultSet netResultSet = parseResultSetCursor(statementI, (SectionsectionAL.get(i));
0378             resultSets[i= netResultSet;
0379         }
0380 
0381         // LOBs may have been returned for one of the stored procedure parameters so
0382         // check for any externalized data.
0383         peekCP = peekCodePoint();
0384         while (peekCP == CodePoint.EXTDTA) {
0385             copyEXTDTA(netSqldta);
0386             peekCP = peekCodePoint();
0387         }
0388         statementI.completeExecuteCall(netSqlca, netSqldta, resultSets);
0389     }
0390 
0391     // Parse the Result Set component of the reply for a stored procedure
0392     // call which returns result sets.
0393     // The Result Set component consists of an Open Query Reply Message
0394     // followed by an optional SQLCARD, followed by an optional
0395     // SQL Column Information Reply data object, followed by a Query Descriptor.
0396     // There may also be Query Data or an End of Query Reply Message.
0397     protected NetResultSet parseResultSetCursor(StatementCallbackInterface statementI,
0398                                                 Section sectionthrows DisconnectException {
0399         // The first item returne is an OPNQRYRM.
0400         NetResultSet netResultSet = parseOPNQRYRM(statementI);
0401 
0402         // The next to be returned is an OBJDSS so check for any TYPDEF overrides.
0403         int peekCP = parseTypdefsOrMgrlvlovrs();
0404 
0405         // An SQLCARD may be returned if there were any warnings on the OPEN.
0406         NetSqlca netSqlca = null;
0407         if (peekCP == CodePoint.SQLCARD) {
0408             netSqlca = parseSQLCARD(null);
0409             peekCP = parseTypdefsOrMgrlvlovrs();
0410         }
0411 
0412         // the SQLCINRD contains SQLDA like information for the result set.
0413         ColumnMetaData resultSetMetaData = null;
0414         if (peekCP == CodePoint.SQLCINRD) {
0415             resultSetMetaData = parseSQLCINRD();
0416             peekCP = parseTypdefsOrMgrlvlovrs();
0417         }
0418 
0419         // A Query Descriptor must be present.
0420         // We cannot cache the cursor if result set is returned from a stored procedure, so
0421         // there is no cached cursor to use here.
0422         parseQRYDSC(netResultSet.netCursor_);
0423         peekCP = peekCodePoint();
0424         statementI.completeExecuteCallOpenQuery(netSqlca, netResultSet, resultSetMetaData, section);
0425 
0426         // Depending on the blocking rules, QRYDTA may have been returned on the open.
0427         while (peekCP == CodePoint.QRYDTA) {
0428             parseQRYDTA(netResultSet);
0429             peekCP = peekCodePoint();
0430         }
0431 
0432         // Under some circumstances, the server may have closed the cursor.
0433         // This will be indicated by an ENDQRYRM.
0434         if (peekCP == CodePoint.ENDQRYRM) {
0435             parseEndQuery((ResultSetCallbackInterfacenetResultSet);
0436         }
0437 
0438         return netResultSet;
0439     }
0440 
0441     protected void parseOpenQuery(StatementCallbackInterface statementIthrows DisconnectException {
0442         NetResultSet netResultSet = parseOPNQRYRM(statementI);
0443 
0444         NetSqlca sqlca = null;
0445         int peekCP = peekCodePoint();
0446         if (peekCP != CodePoint.QRYDSC) {
0447 
0448             peekCP = parseTypdefsOrMgrlvlovrs();
0449 
0450             if (peekCP == CodePoint.SQLDARD) {
0451                 ColumnMetaData columnMetaData = new ColumnMetaData(netAgent_.logWriter_);
0452                 NetSqlca netSqlca = parseSQLDARD(columnMetaData, false);  // false means do not skip SQLDARD bytes
0453 
0454                 //For java stored procedure, we got the resultSetMetaData from server,
0455                 //Do we need to save the resultSetMetaData and propagate netSqlca?
0456                 //The following statement are doing the both, but it do more than
0457                 //we want. It also mark the completion of Prepare statement.
0458                 //
0459                 // this will override the same call made from parsePrepareDescribe
0460                 //  this will not work, this is not the DA for the stored proc params
0461                 statementI.completePrepareDescribeOutput(columnMetaData, netSqlca);
0462                 peekCP = parseTypdefsOrMgrlvlovrs();
0463             }
0464             // check if the DARD is mutually exclusive with CARD, if so, then the following if should be an elese
0465 
0466             if (peekCP == CodePoint.SQLCARD) {
0467                 sqlca = parseSQLCARD(null);
0468                 peekCP = parseTypdefsOrMgrlvlovrs();
0469             }
0470         }
0471         parseQRYDSC(netResultSet.netCursor_);
0472 
0473         peekCP = peekCodePoint();
0474         while (peekCP == CodePoint.QRYDTA) {
0475             parseQRYDTA(netResultSet);
0476             peekCP = peekCodePoint();
0477         }
0478 
0479         if (peekCP == CodePoint.SQLCARD) {
0480             NetSqlca netSqlca = parseSQLCARD(null);
0481             statementI.completeSqlca(netSqlca);
0482             peekCP = peekCodePoint();
0483         }
0484 
0485         if (peekCP == CodePoint.ENDQRYRM) {
0486             parseEndQuery(netResultSet);
0487         }
0488 
0489         statementI.completeOpenQuery(sqlca, netResultSet);
0490     }
0491 
0492     protected void parseEndQuery(ResultSetCallbackInterface resultSetIthrows DisconnectException {
0493         parseENDQRYRM(resultSetI);
0494         parseTypdefsOrMgrlvlovrs();
0495         NetSqlca netSqlca = parseSQLCARD(null);
0496&