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 statement) throws DisconnectException {
0043 startSameIdChainParse();
0044 parsePRPSQLSTTreply(statement);
0045 endOfSameIdChainData();
0046 }
0047
0048 public void readExecuteImmediate(StatementCallbackInterface statement) throws DisconnectException {
0049 startSameIdChainParse();
0050 parseEXCSQLIMMreply(statement);
0051 endOfSameIdChainData();
0052 }
0053
0054 public void readOpenQuery(StatementCallbackInterface statement) throws DisconnectException {
0055 startSameIdChainParse();
0056 parseOPNQRYreply(statement);
0057 endOfSameIdChainData();
0058 }
0059
0060 public void readExecute(PreparedStatementCallbackInterface preparedStatement) throws DisconnectException {
0061 startSameIdChainParse();
0062 parseEXCSQLSTTreply(preparedStatement);
0063 endOfSameIdChainData();
0064 }
0065
0066 public void readPrepare(StatementCallbackInterface statement) throws DisconnectException {
0067 startSameIdChainParse();
0068 parsePRPSQLSTTreply(statement);
0069 endOfSameIdChainData();
0070 }
0071
0072 public void readDescribeInput(PreparedStatementCallbackInterface preparedStatement) throws 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 preparedStatement) throws DisconnectException {
0090 startSameIdChainParse();
0091 parseDSCSQLSTTreply(preparedStatement, 0); // 0 for output
0092 endOfSameIdChainData();
0093 }
0094
0095 public void readExecuteCall(StatementCallbackInterface statement) throws 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 statement) throws 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 statement) throws 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 statementI) throws 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 statement) throws 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 statementI) throws 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 (((Statement) statementI).cachedSingletonRowData_ == null) {
0305 netSqldta = new NetSqldta(netAgent_);
0306 } else {
0307 netSqldta = (NetSqldta) ((Statement) statementI).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 statementI) throws 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, (Section) sectionAL.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 section) throws 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((ResultSetCallbackInterface) netResultSet);
0436 }
0437
0438 return netResultSet;
0439 }
0440
0441 protected void parseOpenQuery(StatementCallbackInterface statementI) throws 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 resultSetI) throws DisconnectException {
0493 parseENDQRYRM(resultSetI);
0494 parseTypdefsOrMgrlvlovrs();
0495 NetSqlca netSqlca = parseSQLCARD(null);
0496& |