Source Code Cross Referenced for NetCursor.java in  » Database-DBMS » db-derby-10.2 » org » apache » derby » client » net » Java Source Code / Java DocumentationJava Source Code and Java Documentation

Java Source Code / Java Documentation
1. 6.0 JDK Core
2. 6.0 JDK Modules
3. 6.0 JDK Modules com.sun
4. 6.0 JDK Modules com.sun.java
5. 6.0 JDK Modules sun
6. 6.0 JDK Platform
7. Ajax
8. Apache Harmony Java SE
9. Aspect oriented
10. Authentication Authorization
11. Blogger System
12. Build
13. Byte Code
14. Cache
15. Chart
16. Chat
17. Code Analyzer
18. Collaboration
19. Content Management System
20. Database Client
21. Database DBMS
22. Database JDBC Connection Pool
23. Database ORM
24. Development
25. EJB Server geronimo
26. EJB Server GlassFish
27. EJB Server JBoss 4.2.1
28. EJB Server resin 3.1.5
29. ERP CRM Financial
30. ESB
31. Forum
32. GIS
33. Graphic Library
34. Groupware
35. HTML Parser
36. IDE
37. IDE Eclipse
38. IDE Netbeans
39. Installer
40. Internationalization Localization
41. Inversion of Control
42. Issue Tracking
43. J2EE
44. JBoss
45. JMS
46. JMX
47. Library
48. Mail Clients
49. Net
50. Parser
51. PDF
52. Portal
53. Profiler
54. Project Management
55. Report
56. RSS RDF
57. Rule Engine
58. Science
59. Scripting
60. Search Engine
61. Security
62. Sevlet Container
63. Source Control
64. Swing Library
65. Template Engine
66. Test Coverage
67. Testing
68. UML
69. Web Crawler
70. Web Framework
71. Web Mail
72. Web Server
73. Web Services
74. Web Services apache cxf 2.0.1
75. Web Services AXIS2
76. Wiki Engine
77. Workflow Engines
78. XML
79. XML UI
Java
Java Tutorial
Java Open Source
Jar File Download
Java Articles
Java Products
Java by API
Photoshop Tutorials
Maya Tutorials
Flash Tutorials
3ds-Max Tutorials
Illustrator Tutorials
GIMP Tutorials
C# / C Sharp
C# / CSharp Tutorial
C# / CSharp Open Source
ASP.Net
ASP.NET Tutorial
JavaScript DHTML
JavaScript Tutorial
JavaScript Reference
HTML / CSS
HTML CSS Reference
C / ANSI-C
C Tutorial
C++
C++ Tutorial
Ruby
PHP
Python
Python Tutorial
Python Open Source
SQL Server / T-SQL
SQL Server / T-SQL Tutorial
Oracle PL / SQL
Oracle PL/SQL Tutorial
PostgreSQL
SQL / MySQL
MySQL Tutorial
VB.Net
VB.Net Tutorial
Flash / Flex / ActionScript
VBA / Excel / Access / Word
XML
XML Tutorial
Microsoft Office PowerPoint 2007 Tutorial
Microsoft Office Excel 2007 Tutorial
Microsoft Office Word 2007 Tutorial
Java Source Code / Java Documentation » Database DBMS » db derby 10.2 » org.apache.derby.client.net 
Source Cross Referenced  Class Diagram Java Document (Java Doc) 


0001:        /*
0002:
0003:           Derby - Class org.apache.derby.client.net.NetCursor
0004:
0005:           Licensed to the Apache Software Foundation (ASF) under one or more
0006:           contributor license agreements.  See the NOTICE file distributed with
0007:           this work for additional information regarding copyright ownership.
0008:           The ASF licenses this file to You under the Apache License, Version 2.0
0009:           (the "License"); you may not use this file except in compliance with
0010:           the License.  You may obtain a copy of the License at
0011:
0012:              http://www.apache.org/licenses/LICENSE-2.0
0013:
0014:           Unless required by applicable law or agreed to in writing, software
0015:           distributed under the License is distributed on an "AS IS" BASIS,
0016:           WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
0017:           See the License for the specific language governing permissions and
0018:           limitations under the License.
0019:
0020:         */
0021:
0022:        package org.apache.derby.client.net;
0023:
0024:        import org.apache.derby.client.am.Agent;
0025:        import org.apache.derby.client.am.Blob;
0026:        import org.apache.derby.client.am.Clob;
0027:        import org.apache.derby.client.am.DisconnectException;
0028:        import org.apache.derby.client.am.SignedBinary;
0029:        import org.apache.derby.client.am.SqlException;
0030:        import org.apache.derby.client.am.ClientMessageId;
0031:        import org.apache.derby.client.am.SqlWarning;
0032:        import org.apache.derby.client.am.Types;
0033:        import org.apache.derby.client.am.SqlCode;
0034:        import org.apache.derby.shared.common.reference.SQLState;
0035:        import org.apache.derby.shared.common.sanity.SanityManager;
0036:
0037:        public class NetCursor extends org.apache.derby.client.am.Cursor {
0038:
0039:            NetResultSet netResultSet_;
0040:            NetAgent netAgent_;
0041:
0042:            Typdef qrydscTypdef_;
0043:
0044:            int targetSqlamForTypdef_;
0045:
0046:            // override column meta data
0047:            int numMddOverrides_;
0048:            int maximumRowSize_;
0049:            boolean blocking_; // if true, multiple rows may be "blocked" in a single reply
0050:
0051:            // Raw fdoca column meta data.
0052:            int[] typeToUseForComputingDataLength_;
0053:            boolean[] isGraphic_;
0054:
0055:            // key = column position, value = index into extdtaData_
0056:            java.util.HashMap extdtaPositions_;
0057:            java.util.ArrayList extdtaData_; // queue to hold EXTDTA data that hasn't been correlated to its column #
0058:
0059:            boolean rtnextrow_ = true;
0060:
0061:            /** Flag indicating whether the result set on the server is
0062:             * implicitly closed when end-of-data is received. */
0063:            private boolean qryclsimpEnabled_;
0064:
0065:            //-----------------------------constants--------------------------------------
0066:
0067:            //---------------------constructors/finalizer---------------------------------
0068:
0069:            NetCursor(NetAgent netAgent) {
0070:                super (netAgent);
0071:                netAgent_ = netAgent;
0072:                numMddOverrides_ = 0;
0073:                maximumRowSize_ = 0;
0074:                extdtaPositions_ = new java.util.HashMap();
0075:                extdtaData_ = new java.util.ArrayList();
0076:            }
0077:
0078:            NetCursor(NetAgent netAgent, int qryprctyp) //protocolType, CodePoint.FIXROWPRC | CodePoint.LMTBLKPRC
0079:            {
0080:                this (netAgent);
0081:                if (qryprctyp == CodePoint.FIXROWPRC) {
0082:                    blocking_ = false;
0083:                } else if (qryprctyp == CodePoint.LMTBLKPRC) {
0084:                    blocking_ = true;
0085:                }
0086:            }
0087:
0088:            //-----------------------------parsing the data buffer------------------------
0089:
0090:            /**
0091:             * Calculate the column offsets for a row.
0092:             * <p>
0093:             * Pseudo-code:
0094:             * <ol>
0095:             * <li>parse thru the current row in dataBuffer computing column
0096:             * offsets</li>
0097:             * <li>if (we hit the super.lastValidBytePosition, ie. encounter
0098:             * partial row)
0099:             *   <ol>
0100:             *     <li>shift partial row bytes to beginning of dataBuffer
0101:             *     (this.shiftPartialRowToBeginning())</li>
0102:             *     <li>reset current row position (also done by
0103:             *     this.shiftPartialRowToBeginning())</li>
0104:             *     <li>send and recv continue-query into commBuffer
0105:             *     (rs.flowContinueQuery())</li>
0106:             *     <li>parse commBuffer up to QRYDTA
0107:             *     (rs.flowContinueQuery())</li>
0108:             *     <li>copy query data from reply's commBuffer to our
0109:             *     dataBuffer (this.copyQrydta())</li>
0110:             *   </ol>
0111:             * </ol>
0112:             *
0113:             * @param rowIndex row index
0114:             * @param allowServerFetch if true, allow fetching more data from
0115:             * server
0116:             * @return <code>true</code> if the current row position is a
0117:             * valid row position.
0118:             * @exception SqlException
0119:             * @exception DisconnectException
0120:             */
0121:            protected boolean calculateColumnOffsetsForRow_(int rowIndex,
0122:                    boolean allowServerFetch) throws SqlException,
0123:                    DisconnectException {
0124:                int daNullIndicator = CodePoint.NULLDATA;
0125:                int colNullIndicator = CodePoint.NULLDATA;
0126:                int length;
0127:
0128:                int[] columnDataPosition = null;
0129:                int[] columnDataComputedLength = null;
0130:                boolean[] columnDataIsNull = null;
0131:                boolean receivedDeleteHoleWarning = false;
0132:                boolean receivedRowUpdatedWarning = false;
0133:
0134:                if ((position_ == lastValidBytePosition_)
0135:                        && (netResultSet_ != null)
0136:                        && (netResultSet_.scrollable_)) {
0137:                    return false;
0138:                }
0139:
0140:                if (hasLobs_) {
0141:                    extdtaPositions_.clear(); // reset positions for this row
0142:                }
0143:
0144:                NetSqlca[] netSqlca = this .parseSQLCARD(qrydscTypdef_);
0145:
0146:                if (netSqlca != null) {
0147:                    for (int i = 0; i < netSqlca.length; i++) {
0148:                        int sqlcode = netSqlca[i].getSqlCode();
0149:                        if (sqlcode < 0) {
0150:                            throw new SqlException(netAgent_.logWriter_,
0151:                                    netSqlca[i]);
0152:                        } else {
0153:                            if (sqlcode == SqlCode.END_OF_DATA.getCode()) {
0154:                                setAllRowsReceivedFromServer(true);
0155:                                if (netResultSet_ != null
0156:                                        && netSqlca[i].containsSqlcax()) {
0157:                                    netResultSet_.setRowCountEvent(netSqlca[i]
0158:                                            .getRowCount(qrydscTypdef_));
0159:                                }
0160:                            } else if (netResultSet_ != null && sqlcode > 0) {
0161:                                String sqlState = netSqlca[i].getSqlState();
0162:                                if (!sqlState.equals(SQLState.ROW_DELETED)
0163:                                        && !sqlState
0164:                                                .equals(SQLState.ROW_UPDATED)) {
0165:                                    netResultSet_
0166:                                            .accumulateWarning(new SqlWarning(
0167:                                                    agent_.logWriter_,
0168:                                                    netSqlca[i]));
0169:                                } else {
0170:                                    receivedDeleteHoleWarning |= sqlState
0171:                                            .equals(SQLState.ROW_DELETED);
0172:                                    receivedRowUpdatedWarning |= sqlState
0173:                                            .equals(SQLState.ROW_UPDATED);
0174:                                }
0175:                            }
0176:                        }
0177:                    }
0178:                }
0179:
0180:                setIsUpdataDeleteHole(rowIndex, receivedDeleteHoleWarning);
0181:                setIsRowUpdated(receivedRowUpdatedWarning);
0182:
0183:                // If we don't have at least one byte in the buffer for the DA null indicator,
0184:                // then we need to send a CNTQRY request to fetch the next block of data.
0185:                // Read the DA null indicator.
0186:                daNullIndicator = readFdocaOneByte();
0187:
0188:                // In the case for held cursors, the +100 comes back as part of the QRYDTA, and as
0189:                // we are parsing through the row that contains the SQLCA with +100, we mark the
0190:                // nextRowPosition_ which is the lastValidBytePosition_, but we don't mark the
0191:                // currentRowPosition_ until the next time next() is called causing the check
0192:                // cursor_.currentRowPositionIsEqualToNextRowPosition () to fail in getRow() and thus
0193:                // not returning 0 when it should. So we need to mark the current row position immediately
0194:                // in order for getRow() to be able to pick it up.
0195:
0196:                // markNextRowPosition() is called again once this method returns, but it is ok
0197:                // since it's only resetting nextRowPosition_ to position_ and position_ will
0198:                // not change again from this point.
0199:
0200:                if (allRowsReceivedFromServer()
0201:                        && (position_ == lastValidBytePosition_)) {
0202:                    markNextRowPosition();
0203:                    makeNextRowPositionCurrent();
0204:                    return false;
0205:                }
0206:
0207:                // If data flows....
0208:                if (daNullIndicator == 0x0) {
0209:
0210:                    if (SanityManager.DEBUG && receivedDeleteHoleWarning) {
0211:                        SanityManager
0212:                                .THROWASSERT("Delete hole warning received: nulldata expected");
0213:                    }
0214:                    incrementRowsReadEvent();
0215:
0216:                    // netResultSet_ is null if this method is invoked from Lob.position()
0217:                    // If row has exceeded the size of the ArrayList, new up a new int[] and add it to the
0218:                    // ArrayList, otherwise just reuse the int[].
0219:                    if (netResultSet_ != null && netResultSet_.scrollable_) {
0220:                        columnDataPosition = allocateColumnDataPositionArray(rowIndex);
0221:                        columnDataComputedLength = allocateColumnDataComputedLengthArray(rowIndex);
0222:                        columnDataIsNull = allocateColumnDataIsNullArray(rowIndex);
0223:                        // Since we are no longer setting the int[]'s to null for a delete/update hole, we need
0224:                        // another way of keeping track of the delete/update holes.
0225:                        setIsUpdataDeleteHole(rowIndex, false);
0226:                    } else {
0227:                        // Use the arrays defined on the Cursor for forward-only cursors.
0228:                        // can they ever be null
0229:                        if (columnDataPosition_ == null
0230:                                || columnDataComputedLength_ == null
0231:                                || isNull_ == null) {
0232:                            allocateColumnOffsetAndLengthArrays();
0233:                        }
0234:                        columnDataPosition = columnDataPosition_;
0235:                        columnDataComputedLength = columnDataComputedLength_;
0236:                        columnDataIsNull = isNull_;
0237:                    }
0238:
0239:                    // Loop through the columns
0240:                    for (int index = 0; index < columns_; index++) {
0241:                        // If column is nullable, read the 1-byte null indicator.
0242:                        if (nullable_[index])
0243:                        // Need to pass the column index so all previously calculated offsets can be
0244:                        // readjusted if the query block splits on a column null indicator.
0245:
0246:                        // null indicators from FD:OCA data
0247:                        // 0 to 127: a data value will flow.
0248:                        // -1 to -128: no data value will flow.
0249:                        {
0250:                            colNullIndicator = readFdocaOneByte(index);
0251:                        }
0252:
0253:                        // If non-null column data
0254:                        if (!nullable_[index]
0255:                                || (colNullIndicator >= 0 && colNullIndicator <= 127)) {
0256:
0257:                            // Set the isNull indicator to false
0258:                            columnDataIsNull[index] = false;
0259:
0260:                            switch (typeToUseForComputingDataLength_[index]) {
0261:                            // for fixed length data
0262:                            case Typdef.FIXEDLENGTH:
0263:                                columnDataPosition[index] = position_;
0264:                                if (isGraphic_[index]) {
0265:                                    columnDataComputedLength[index] = skipFdocaBytes(
0266:                                            fdocaLength_[index] * 2, index);
0267:                                } else {
0268:                                    columnDataComputedLength[index] = skipFdocaBytes(
0269:                                            fdocaLength_[index], index);
0270:                                }
0271:                                break;
0272:
0273:                            // for variable character string and variable byte string,
0274:                            // there are 2-byte of length in front of the data
0275:                            case Typdef.TWOBYTELENGTH:
0276:                                columnDataPosition[index] = position_;
0277:                                length = readFdocaTwoByteLength(index);
0278:                                // skip length + the 2-byte length field
0279:                                if (isGraphic_[index]) {
0280:                                    columnDataComputedLength[index] = skipFdocaBytes(
0281:                                            length * 2, index) + 2;
0282:                                } else {
0283:                                    columnDataComputedLength[index] = skipFdocaBytes(
0284:                                            length, index) + 2;
0285:                                }
0286:                                break;
0287:
0288:                            // For decimal columns, determine the precision, scale, and the representation
0289:                            case Typdef.DECIMALLENGTH:
0290:                                columnDataPosition[index] = position_;
0291:                                columnDataComputedLength[index] = skipFdocaBytes(
0292:                                        getDecimalLength(index), index);
0293:                                break;
0294:
0295:                            case Typdef.LOBLENGTH:
0296:                                columnDataPosition[index] = position_;
0297:                                columnDataComputedLength[index] = this 
0298:                                        .skipFdocaBytes(
0299:                                                fdocaLength_[index] & 0x7fff,
0300:                                                index);
0301:                                break;
0302:
0303:                            // for short variable character string and short variable byte string,
0304:                            // there is a 1-byte length in front of the data
0305:                            case Typdef.ONEBYTELENGTH:
0306:                                columnDataPosition[index] = position_;
0307:                                length = readFdocaOneByte(index);
0308:                                // skip length + the 1-byte length field
0309:                                if (isGraphic_[index]) {
0310:                                    columnDataComputedLength[index] = skipFdocaBytes(
0311:                                            length * 2, index) + 1;
0312:                                } else {
0313:                                    columnDataComputedLength[index] = skipFdocaBytes(
0314:                                            length, index) + 1;
0315:                                }
0316:                                break;
0317:
0318:                            default:
0319:                                columnDataPosition[index] = position_;
0320:                                if (isGraphic_[index]) {
0321:                                    columnDataComputedLength[index] = skipFdocaBytes(
0322:                                            fdocaLength_[index] * 2, index);
0323:                                } else {
0324:                                    columnDataComputedLength[index] = skipFdocaBytes(
0325:                                            fdocaLength_[index], index);
0326:                                }
0327:                                break;
0328:                            }
0329:                        } else if ((colNullIndicator & 0x80) == 0x80) {
0330:                            // Null data. Set the isNull indicator to true.
0331:                            columnDataIsNull[index] = true;
0332:                        }
0333:                    }
0334:
0335:                    // set column offsets for the current row.
0336:                    columnDataPosition_ = columnDataPosition;
0337:                    columnDataComputedLength_ = columnDataComputedLength;
0338:                    isNull_ = columnDataIsNull;
0339:
0340:                    if (!allRowsReceivedFromServer()) {
0341:                        calculateLobColumnPositionsForRow();
0342:                        // Flow another CNTQRY if we are blocking, are using rtnextrow, and expect
0343:                        // non-trivial EXTDTAs for forward only cursors.  Note we do not support
0344:                        // EXTDTA retrieval for scrollable cursors.
0345:                        // if qryrowset was sent on excsqlstt for a sp call, which is only the case
0346:                        if (blocking_ && rtnextrow_
0347:                                && !netResultSet_.scrollable_
0348:                                && !extdtaPositions_.isEmpty()) {
0349:                            if (allowServerFetch) {
0350:                                netResultSet_.flowFetch();
0351:                            } else {
0352:                                return false;
0353:                            }
0354:                        }
0355:                    }
0356:                } else {
0357:                    if (netResultSet_ != null && netResultSet_.scrollable_) {
0358:                        if (receivedDeleteHoleWarning) {
0359:                            setIsUpdataDeleteHole(rowIndex, true);
0360:                        } else {
0361:                            if (SanityManager.DEBUG) {
0362:                                // Invariant: for SUR, we introduced the warning
0363:                                // in addition to null data.
0364:                                SanityManager
0365:                                        .THROWASSERT("Delete hole warning expected");
0366:                            }
0367:                        }
0368:                    }
0369:                }
0370:
0371:                // If blocking protocol is used, we could have already received an ENDQRYRM,
0372:                // which sets allRowsReceivedFromServer_ to true.  It's safe to assume that all of
0373:                // our QRYDTA's have been successfully copied to the dataBuffer.  And even though
0374:                // the flag for allRowsReceivedFromServer_ is set, we still want to continue to parse through
0375:                // the data in the dataBuffer.
0376:                // But in the case where fixed row protocol is used,
0377:                if (!blocking_ && allRowsReceivedFromServer()
0378:                        && daNullIndicator == 0xFF) {
0379:                    return false;
0380:                } else {
0381:                    return true;
0382:                }
0383:            }
0384:
0385:            /**
0386:             * Scan the data buffer to see if end of data (SQL state 02000)
0387:             * has been received. This method should only be called when the
0388:             * cursor is being closed since the pointer to the current row can
0389:             * be modified.
0390:             *
0391:             * @exception SqlException
0392:             */
0393:            void scanDataBufferForEndOfData() throws SqlException {
0394:                while (!allRowsReceivedFromServer()
0395:                        && (position_ != lastValidBytePosition_)) {
0396:                    stepNext(false);
0397:                }
0398:            }
0399:
0400:            protected boolean isDataBufferNull() {
0401:                if (dataBuffer_ == null) {
0402:                    return true;
0403:                } else {
0404:                    return false;
0405:                }
0406:            }
0407:
0408:            protected void allocateDataBuffer() {
0409:                int length;
0410:                if (maximumRowSize_ > DssConstants.MAX_DSS_LEN) {
0411:                    length = maximumRowSize_;
0412:                } else {
0413:                    length = DssConstants.MAX_DSS_LEN;
0414:                }
0415:
0416:                dataBuffer_ = new byte[length];
0417:                position_ = 0;
0418:                lastValidBytePosition_ = 0;
0419:            }
0420:
0421:            protected void allocateDataBuffer(int length) {
0422:                dataBuffer_ = new byte[length];
0423:            }
0424:
0425:            private int readFdocaInt()
0426:                    throws org.apache.derby.client.am.DisconnectException,
0427:                    SqlException {
0428:                if ((position_ + 4) > lastValidBytePosition_) {
0429:                    // Check for ENDQRYRM, throw SqlException if already received one.
0430:                    checkAndThrowReceivedEndqryrm();
0431:
0432:                    // Send CNTQRY to complete the row/rowset.
0433:                    int lastValidByteBeforeFetch = completeSplitRow();
0434:
0435:                    // if lastValidBytePosition_ has not changed, and an ENDQRYRM was received,
0436:                    // throw a SqlException for the ENDQRYRM.
0437:                    checkAndThrowReceivedEndqryrm(lastValidByteBeforeFetch);
0438:                }
0439:
0440:                int i = SignedBinary.getInt(dataBuffer_, position_);
0441:                position_ += 4;
0442:                return i;
0443:            }
0444:
0445:            // Reads 8-bytes from the dataBuffer from the current position.
0446:            // If position is already at the end of the buffer, send CNTQRY to get more 
0447:            // data.
0448:            private long readFdocaLong()
0449:                    throws org.apache.derby.client.am.DisconnectException,
0450:                    SqlException {
0451:                if ((position_ + 8) > lastValidBytePosition_) {
0452:                    // Check for ENDQRYRM, throw SqlException if already received one.
0453:                    checkAndThrowReceivedEndqryrm();
0454:
0455:                    // Send CNTQRY to complete the row/rowset.
0456:                    int lastValidByteBeforeFetch = completeSplitRow();
0457:
0458:                    // if lastValidBytePosition_ has not changed, and an ENDQRYRM was 
0459:                    // received, throw a SqlException for the ENDQRYRM.
0460:                    checkAndThrowReceivedEndqryrm(lastValidByteBeforeFetch);
0461:                }
0462:
0463:                long i = SignedBinary.getLong(dataBuffer_, position_);
0464:                position_ += 8;
0465:                return i;
0466:            }
0467:
0468:            // Reads 1-byte from the dataBuffer from the current position.
0469:            // If position is already at the end of the buffer, send CNTQRY to get more data.
0470:            private int readFdocaOneByte()
0471:                    throws org.apache.derby.client.am.DisconnectException,
0472:                    SqlException {
0473:                // For singleton select, the complete row always comes back, even if multiple query blocks are required,
0474:                // so there is no need to drive a flowFetch (continue query) request for singleton select.
0475:                if (position_ == lastValidBytePosition_) {
0476:                    // Check for ENDQRYRM, throw SqlException if already received one.
0477:                    checkAndThrowReceivedEndqryrm();
0478:
0479:                    // Send CNTQRY to complete the row/rowset.
0480:                    int lastValidByteBeforeFetch = completeSplitRow();
0481:
0482:                    // if lastValidBytePosition_ has not changed, and an ENDQRYRM was received,
0483:                    // throw a SqlException for the ENDQRYRM.
0484:                    checkAndThrowReceivedEndqryrm(lastValidByteBeforeFetch);
0485:                }
0486:                return dataBuffer_[position_++] & 0xff;
0487:            }
0488:
0489:            // Reads 1-byte from the dataBuffer from the current position.
0490:            // If position is already at the end of the buffer, send CNTQRY to get more data.
0491:            private int readFdocaOneByte(int index)
0492:                    throws org.apache.derby.client.am.DisconnectException,
0493:                    SqlException {
0494:                // For singleton select, the complete row always comes back, even if multiple query blocks are required,
0495:                // so there is no need to drive a flowFetch (continue query) request for singleton select.
0496:                if (position_ == lastValidBytePosition_) {
0497:                    // Check for ENDQRYRM, throw SqlException if already received one.
0498:                    checkAndThrowReceivedEndqryrm();
0499:
0500:                    // Send CNTQRY to complete the row/rowset.
0501:                    int lastValidByteBeforeFetch = completeSplitRow(index);
0502:
0503:                    // if lastValidBytePosition_ has not changed, and an ENDQRYRM was received,
0504:                    // throw a SqlException for the ENDQRYRM.
0505:                    checkAndThrowReceivedEndqryrm(lastValidByteBeforeFetch);
0506:                }
0507:                return dataBuffer_[position_++] & 0xff;
0508:            }
0509:
0510:            // Reads <i>length</i> number of bytes from the dataBuffer starting from the
0511:            // current position.  Returns a new byte array which contains the bytes read.
0512:            // If current position plus length goes past the lastValidBytePosition, send
0513:            // CNTQRY to get more data.
0514:            private byte[] readFdocaBytes(int length)
0515:                    throws org.apache.derby.client.am.DisconnectException,
0516:                    SqlException {
0517:                byte[] b = new byte[length];
0518:                ;
0519:
0520:                // For singleton select, the complete row always comes back, even if multiple query blocks are required,
0521:                // so there is no need to drive a flowFetch (continue query) request for singleton select.
0522:                if ((position_ + length) > lastValidBytePosition_) {
0523:                    // Check for ENDQRYRM, throw SqlException if already received one.
0524:                    checkAndThrowReceivedEndqryrm();
0525:
0526:                    // Send CNTQRY to complete the row/rowset.
0527:                    int lastValidByteBeforeFetch = completeSplitRow();
0528:
0529:                    // if lastValidBytePosition_ has not changed, and an ENDQRYRM was received,
0530:                    // throw a SqlException for the ENDQRYRM.
0531:                    checkAndThrowReceivedEndqryrm(lastValidByteBeforeFetch);
0532:                }
0533:
0534:                for (int i = 0; i < length; i++) {
0535:                    b[i] = dataBuffer_[position_++];
0536:                }
0537:
0538:                return b;
0539:            }
0540:
0541:            // Reads 2-bytes from the dataBuffer starting from the current position, and
0542:            // returns an integer constructed from the 2-bytes.  If current position plus
0543:            // 2 bytes goes past the lastValidBytePosition, send CNTQRY to get more data.
0544:            private int readFdocaTwoByteLength()
0545:                    throws org.apache.derby.client.am.DisconnectException,
0546:                    SqlException {
0547:                // For singleton select, the complete row always comes back, even if multiple query blocks are required,
0548:                // so there is no need to drive a flowFetch (continue query) request for singleton select.
0549:                if ((position_ + 2) > lastValidBytePosition_) {
0550:                    // Check for ENDQRYRM, throw SqlException if already received one.
0551:                    checkAndThrowReceivedEndqryrm();
0552:
0553:                    // Send CNTQRY to complete the row/rowset.
0554:                    int lastValidByteBeforeFetch = completeSplitRow();
0555:
0556:                    // if lastValidBytePosition_ has not changed, and an ENDQRYRM was received,
0557:                    // throw a SqlException for the ENDQRYRM.
0558:                    checkAndThrowReceivedEndqryrm(lastValidByteBeforeFetch);
0559:                }
0560:
0561:                return ((dataBuffer_[position_++] & 0xff) << 8)
0562:                        + ((dataBuffer_[position_++] & 0xff) << 0);
0563:            }
0564:
0565:            private int readFdocaTwoByteLength(int index)
0566:                    throws org.apache.derby.client.am.DisconnectException,
0567:                    SqlException {
0568:                // For singleton select, the complete row always comes back, even if multiple query blocks are required,
0569:                // so there is no need to drive a flowFetch (continue query) request for singleton select.
0570:                if ((position_ + 2) > lastValidBytePosition_) {
0571:                    // Check for ENDQRYRM, throw SqlException if already received one.
0572:                    checkAndThrowReceivedEndqryrm();
0573:
0574:                    // Send CNTQRY to complete the row/rowset.
0575:                    int lastValidByteBeforeFetch = completeSplitRow(index);
0576:
0577:                    // if lastValidBytePosition_ has not changed, and an ENDQRYRM was received,
0578:                    // throw a SqlException for the ENDQRYRM.
0579:                    checkAndThrowReceivedEndqryrm(lastValidByteBeforeFetch);
0580:                }
0581:
0582:                return ((dataBuffer_[position_++] & 0xff) << 8)
0583:                        + ((dataBuffer_[position_++] & 0xff) << 0);
0584:            }
0585:
0586:            // Check if position plus length goes past the lastValidBytePosition.
0587:            // If so, send CNTQRY to get more data.
0588:            // length - number of bytes to skip
0589:            // returns the number of bytes skipped
0590:            private int skipFdocaBytes(int length)
0591:                    throws org.apache.derby.client.am.DisconnectException,
0592:                    SqlException {
0593:                // For singleton select, the complete row always comes back, even if multiple query blocks are required,
0594:                // so there is no need to drive a flowFetch (continue query) request for singleton select.
0595:                if ((position_ + length) > lastValidBytePosition_) {
0596:                    // Check for ENDQRYRM, throw SqlException if already received one.
0597:                    checkAndThrowReceivedEndqryrm();
0598:
0599:                    // Send CNTQRY to complete the row/rowset.
0600:                    int lastValidByteBeforeFetch = completeSplitRow();
0601:
0602:                    // if lastValidBytePosition_ has not changed, and an ENDQRYRM was received,
0603:                    // throw a SqlException for the ENDQRYRM.
0604:                    checkAndThrowReceivedEndqryrm(lastValidByteBeforeFetch);
0605:                }
0606:                position_ += length;
0607:                return length;
0608:            }
0609:
0610:            private int skipFdocaBytes(int length, int index)
0611:                    throws org.apache.derby.client.am.DisconnectException,
0612:                    SqlException {
0613:                // For singleton select, the complete row always comes back, even if multiple query blocks are required,
0614:                // so there is no need to drive a flowFetch (continue query) request for singleton select.
0615:                if ((position_ + length) > lastValidBytePosition_) {
0616:                    // Check for ENDQRYRM, throw SqlException if already received one.
0617:                    checkAndThrowReceivedEndqryrm();
0618:
0619:                    // Send CNTQRY to complete the row/rowset.
0620:                    int lastValidByteBeforeFetch = completeSplitRow(index);
0621:
0622:                    // if lastValidBytePosition_ has not changed, and an ENDQRYRM was received,
0623:                    // throw a SqlException for the ENDQRYRM.
0624:                    checkAndThrowReceivedEndqryrm(lastValidByteBeforeFetch);
0625:                }
0626:
0627:                position_ += length;
0628:                return length;
0629:            }
0630:
0631:            // Shift partial row bytes to beginning of dataBuffer,
0632:            // and resets current row position, and lastValidBytePosition.
0633:            // When we shift partial row, we'll have to recalculate column offsets
0634:            // up to this column.
0635:            private void shiftPartialRowToBeginning() {
0636:                // Get the length to shift from the beginning of the partial row.
0637:                int length = lastValidBytePosition_ - currentRowPosition_;
0638:
0639:                // shift the data in the dataBufferStream
0640:                dataBufferStream_.reset();
0641:                if (dataBuffer_ != null) {
0642:                    dataBufferStream_.write(dataBuffer_, currentRowPosition_,
0643:                            length);
0644:                }
0645:
0646:                for (int i = 0; i < length; i++) {
0647:                    dataBuffer_[i] = dataBuffer_[currentRowPosition_ + i];
0648:                }
0649:
0650:                position_ = length - (lastValidBytePosition_ - position_);
0651:                lastValidBytePosition_ = length;
0652:            }
0653:
0654:            private void adjustColumnOffsetsForColumnsPreviouslyCalculated(
0655:                    int index) {
0656:                for (int j = 0; j <= index; j++) {
0657:                    columnDataPosition_[j] -= currentRowPosition_;
0658:                }
0659:            }
0660:
0661:            private void resetCurrentRowPosition() {
0662:                currentRowPosition_ = 0;
0663:            }
0664:
0665:            // Calculates the column index for Lob objects constructed from EXTDTA data.
0666:            // Describe information isn't sufficient because we have to check
0667:            // for trivial values (nulls or zero-length) and exclude them.
0668:            void calculateLobColumnPositionsForRow() {
0669:                int currentPosition = 0;
0670:
0671:                for (int i = 0; i < columns_; i++) {
0672:                    if (isNonTrivialDataLob(i))
0673:                    // key = column position, data = index to corresponding data in extdtaData_
0674:                    // ASSERT: the server always returns the EXTDTA objects in ascending order
0675:                    {
0676:                        extdtaPositions_.put(new Integer(i + 1), new Integer(
0677:                                currentPosition++));
0678:                    }
0679:                }
0680:            }
0681:
0682:            // prereq: the base data for the cursor has been processed for offsets and lengths
0683:            boolean isNonTrivialDataLob(int index) {
0684:                long length = 0L;
0685:
0686:                if (isNull_[index]
0687:                        || (jdbcTypes_[index] != Types.BLOB && jdbcTypes_[index] != Types.CLOB)) {
0688:                    return false;
0689:                }
0690:
0691:                int position = columnDataPosition_[index];
0692:
0693:                // if the high-order bit is set, length is unknown -> set value to x'FF..FF'
0694:                if (((dataBuffer_[position]) & 0x80) == 0x80) {
0695:                    length = -1;
0696:                } else {
0697:
0698:                    byte[] lengthBytes = new byte[columnDataComputedLength_[index]];
0699:                    byte[] longBytes = new byte[8];
0700:
0701:                    System.arraycopy(dataBuffer_, position, lengthBytes, 0,
0702:                            columnDataComputedLength_[index]);
0703:
0704:                    // right-justify for BIG ENDIAN
0705:                    int j = 0;
0706:                    for (int i = 8 - columnDataComputedLength_[index]; i < 8; i++) {
0707:                        longBytes[i] = lengthBytes[j];
0708:                        j++;
0709:                    }
0710:                    length = SignedBinary.getLong(longBytes, 0);
0711:                }
0712:                return (length != 0L) ? true : false;
0713:            }
0714:
0715:            protected void clearLobData_() {
0716:                extdtaData_.clear();
0717:                extdtaPositions_.clear();
0718:            }
0719:
0720:            // SQLCARD : FDOCA EARLY ROW
0721:            // SQL Communications Area Row Description
0722:            //
0723:            // FORMAT FOR ALL SQLAM LEVELS
0724:            //   SQLCAGRP; GROUP LID 0x54; ELEMENT TAKEN 0(all); REP FACTOR 1
0725:            NetSqlca[] parseSQLCARD(Typdef typdef)
0726:                    throws org.apache.derby.client.am.DisconnectException,
0727:                    SqlException {
0728:                return parseSQLCAGRP(typdef);
0729:            }
0730:
0731:            // SQLCAGRP : FDOCA EARLY GROUP
0732:            // SQL Communcations Area Group Description
0733:            //
0734:            // FORMAT FOR SQLAM <= 6
0735:            //   SQLCODE; PROTOCOL TYPE I4; ENVLID 0x02; Length Override 4
0736:            //   SQLSTATE; PROTOCOL TYPE FCS; ENVLID 0x30; Length Override 5
0737:            //   SQLERRPROC; PROTOCOL TYPE FCS; ENVLID 0x30; Length Override 8
0738:            //   SQLCAXGRP; PROTOCOL TYPE N-GDA; ENVLID 0x52; Length Override 0
0739:            //
0740:            // FORMAT FOR SQLAM >= 7
0741:            //   SQLCODE; PROTOCOL TYPE I4; ENVLID 0x02; Length Override 4
0742:            //   SQLSTATE; PROTOCOL TYPE FCS; ENVLID 0x30; Length Override 5
0743:            //   SQLERRPROC; PROTOCOL TYPE FCS; ENVLID 0x30; Length Override 8
0744:            //   SQLCAXGRP; PROTOCOL TYPE N-GDA; ENVLID 0x52; Length Override 0
0745:            //   SQLDIAGGRP; PROTOCOL TYPE N-GDA; ENVLID 0x56; Length Override 0
0746:            private NetSqlca[] parseSQLCAGRP(Typdef typdef)
0747:                    throws org.apache.derby.client.am.DisconnectException,
0748:                    SqlException {
0749:                if (readFdocaOneByte() == CodePoint.NULLDATA) {
0750:                    return null;
0751:                }
0752:                int sqlcode = readFdocaInt();
0753:                byte[] sqlstate = readFdocaBytes(5);
0754:                byte[] sqlerrproc = readFdocaBytes(8);
0755:                NetSqlca netSqlca = new NetSqlca(netAgent_.netConnection_,
0756:                        sqlcode, sqlstate, sqlerrproc);
0757:
0758:                parseSQLCAXGRP(typdef, netSqlca);
0759:
0760:                NetSqlca[] sqlCa = parseSQLDIAGGRP();
0761:
0762:                NetSqlca[] ret_val;
0763:                if (sqlCa != null) {
0764:                    ret_val = new NetSqlca[sqlCa.length + 1];
0765:                    System.arraycopy(sqlCa, 0, ret_val, 1, sqlCa.length);
0766:                } else {
0767:                    ret_val = new NetSqlca[1];
0768:                }
0769:                ret_val[0] = netSqlca;
0770:
0771:                return ret_val;
0772:            }
0773:
0774:            // SQLCAXGRP : EARLY FDOCA GROUP
0775:            // SQL Communications Area Exceptions Group Description
0776:            //
0777:            // FORMAT FOR SQLAM <= 6
0778:            //   SQLRDBNME; PROTOCOL TYPE FCS; ENVLID 0x30; Length Override 18
0779:            //   SQLERRD1; PROTOCOL TYPE I4; ENVLID 0x02; Length Override 4
0780:            //   SQLERRD2; PROTOCOL TYPE I4; ENVLID 0x02; Length Override 4
0781:            //   SQLERRD3; PROTOCOL TYPE I4; ENVLID 0x02; Length Override 4
0782:            //   SQLERRD4; PROTOCOL TYPE I4; ENVLID 0x02; Length Override 4
0783:            //   SQLERRD5; PROTOCOL TYPE I4; ENVLID 0x02; Length Override 4
0784:            //   SQLERRD6; PROTOCOL TYPE I4; ENVLID 0x02; Length Override 4
0785:            //   SQLWARN0; PROTOCOL TYPE FCS; ENVLID 0x30; Length Override 1
0786:            //   SQLWARN1; PROTOCOL TYPE FCS; ENVLID 0x30; Length Override 1
0787:            //   SQLWARN2; PROTOCOL TYPE FCS; ENVLID 0x30; Length Override 1
0788:            //   SQLWARN3; PROTOCOL TYPE FCS; ENVLID 0x30; Length Override 1
0789:            //   SQLWARN4; PROTOCOL TYPE FCS; ENVLID 0x30; Length Override 1
0790:            //   SQLWARN5; PROTOCOL TYPE FCS; ENVLID 0x30; Length Override 1
0791:            //   SQLWARN6; PROTOCOL TYPE FCS; ENVLID 0x30; Length Override 1
0792:            //   SQLWARN7; PROTOCOL TYPE FCS; ENVLID 0x30; Length Override 1
0793:            //   SQLWARN8; PROTOCOL TYPE FCS; ENVLID 0x30; Length Override 1
0794:            //   SQLWARN9; PROTOCOL TYPE FCS; ENVLID 0x30; Length Override 1
0795:            //   SQLWARNA; PROTOCOL TYPE FCS; ENVLID 0x30; Length Override 1
0796:            //   SQLERRMSG_m; PROTOCOL TYPE VCM; ENVLID 0x3E; Length Override 70
0797:            //   SQLERRMSG_s; PROTOCOL TYPE VCS; ENVLID 0x32; Length Override 70
0798:            //
0799:            // FORMAT FOR SQLAM >= 7
0800:            //   SQLERRD1; PROTOCOL TYPE I4; ENVLID 0x02; Length Override 4
0801:            //   SQLERRD2; PROTOCOL TYPE I4; ENVLID 0x02; Length Override 4
0802:            //   SQLERRD3; PROTOCOL TYPE I4; ENVLID 0x02; Length Override 4
0803:            //   SQLERRD4; PROTOCOL TYPE I4; ENVLID 0x02; Length Override 4
0804:            //   SQLERRD5; PROTOCOL TYPE I4; ENVLID 0x02; Length Override 4
0805:            //   SQLERRD6; PROTOCOL TYPE I4; ENVLID 0x02; Length Override 4
0806:            //   SQLWARN0; PROTOCOL TYPE FCS; ENVLID 0x30; Length Override 1
0807:            //   SQLWARN1; PROTOCOL TYPE FCS; ENVLID 0x30; Length Override 1
0808:            //   SQLWARN2; PROTOCOL TYPE FCS; ENVLID 0x30; Length Override 1
0809:            //   SQLWARN3; PROTOCOL TYPE FCS; ENVLID 0x30; Length Override 1
0810:            //   SQLWARN4; PROTOCOL TYPE FCS; ENVLID 0x30; Length Override 1
0811:            //   SQLWARN5; PROTOCOL TYPE FCS; ENVLID 0x30; Length Override 1
0812:            //   SQLWARN6; PROTOCOL TYPE FCS; ENVLID 0x30; Length Override 1
0813:            //   SQLWARN7; PROTOCOL TYPE FCS; ENVLID 0x30; Length Override 1
0814:            //   SQLWARN8; PROTOCOL TYPE FCS; ENVLID 0x30; Length Override 1
0815:            //   SQLWARN9; PROTOCOL TYPE FCS; ENVLID 0x30; Length Override 1
0816:            //   SQLWARNA; PROTOCOL TYPE FCS; ENVLID 0x30; Length Override 1
0817:            //   SQLRDBNAME; PROTOCOL TYPE VCS; ENVLID 0x32; Length Override 255
0818:            //   SQLERRMSG_m; PROTOCOL TYPE VCM; ENVLID 0x3E; Length Override 70
0819:            //   SQLERRMSG_s; PROTOCOL TYPE VCS; ENVLID 0x32; Length Override 70
0820:            private void parseSQLCAXGRP(Typdef typdef, NetSqlca netSqlca)
0821:                    throws DisconnectException, SqlException {
0822:                if (readFdocaOneByte() == CodePoint.NULLDATA) {
0823:                    netSqlca.setContainsSqlcax(false);
0824:                    return;
0825:                }
0826:
0827:                //   SQLERRD1 to SQLERRD6; PROTOCOL TYPE I4; ENVLID 0x02; Length Override 4
0828:                int[] sqlerrd = new int[6];
0829:                for (int i = 0; i < sqlerrd.length; i++) {
0830:                    sqlerrd[i] = readFdocaInt();
0831:                }
0832:
0833:                //   SQLWARN0 to SQLWARNA; PROTOCOL TYPE FCS; ENVLID 0x30; Length Override 1
0834:                byte[] sqlwarn = readFdocaBytes(11);
0835:
0836:                // skip over the rdbnam for now
0837:                // SQLRDBNAME; PROTOCOL TYPE VCS; ENVLID 0x32; Length Override 255
0838:                parseVCS(typdef);
0839:
0840:                //   SQLERRMSG_m; PROTOCOL TYPE VCM; ENVLID 0x3E; Length Override 70
0841:                //   SQLERRMSG_s; PROTOCOL TYPE VCS; ENVLID 0x32; Length Override 70
0842:                int varcharLength = readFdocaTwoByteLength(); // mixed length
0843:                byte[] sqlerrmc = null;
0844:                int sqlerrmcCcsid = 0;
0845:                if (varcharLength != 0) { // if mixed
0846:                    sqlerrmc = readFdocaBytes(varcharLength); // read mixed bytes
0847:                    sqlerrmcCcsid = typdef.getCcsidMbc();
0848:                    skipFdocaBytes(2); // skip single length
0849:                } else {
0850:                    varcharLength = readFdocaTwoByteLength(); // read single length
0851:                    sqlerrmc = readFdocaBytes(varcharLength); // read single bytes
0852:                    sqlerrmcCcsid = typdef.getCcsidSbc();
0853:                }
0854:
0855:                netSqlca.setSqlerrd(sqlerrd);
0856:                netSqlca.setSqlwarnBytes(sqlwarn);
0857:                netSqlca.setSqlerrmcBytes(sqlerrmc, sqlerrmcCcsid);
0858:            }
0859:
0860:            // SQLDIAGGRP : FDOCA EARLY GROUP
0861:            private NetSqlca[] parseSQLDIAGGRP() throws DisconnectException,
0862:                    SqlException {
0863:                if (readFdocaOneByte() == CodePoint.NULLDATA) {
0864:                    return null;
0865:                }
0866:
0867:                parseSQLDIAGSTT();
0868:                NetSqlca[] sqlca = parseSQLDIAGCI();
0869:                parseSQLDIAGCN();
0870:
0871:                return sqlca;
0872:            }
0873:
0874:            // SQL Diagnostics Statement Group Description - Identity 0xD3
0875:            // NULLDATA will be received for now
0876:            private void parseSQLDIAGSTT() throws DisconnectException,
0877:                    SqlException {
0878:                if (readFdocaOneByte() == CodePoint.NULLDATA) {
0879:                    return;
0880:                }
0881:
0882:                // The server should send NULLDATA
0883:                netAgent_
0884:                        .accumulateChainBreakingReadExceptionAndThrow(new DisconnectException(
0885:                                netAgent_, new ClientMessageId(
0886:                                        SQLState.DRDA_COMMAND_NOT_IMPLEMENTED),
0887:                                "parseSQLDIAGSTT"));
0888:            }
0889:
0890:            // SQL Diagnostics Condition Information Array - Identity 0xF5
0891:            // SQLNUMROW; ROW LID 0x68; ELEMENT TAKEN 0(all); REP FACTOR 1
0892:            // SQLDCIROW; ROW LID 0xE5; ELEMENT TAKEN 0(all); REP FACTOR 0(all)
0893:            private NetSqlca[] parseSQLDIAGCI() throws DisconnectException,
0894:                    SqlException {
0895:                int num = readFdocaTwoByteLength(); // SQLNUMGRP - SQLNUMROW
0896:                NetSqlca[] ret_val = null;
0897:                if (num != 0) {
0898:                    ret_val = new NetSqlca[num];
0899:                }
0900:
0901:                for (int i = 0; i < num; i++) {
0902:                    ret_val[i] = parseSQLDCROW();
0903:                }
0904:                return ret_val;
0905:            }
0906:
0907:            // SQL Diagnostics Connection Array - Identity 0xF6
0908:            // NULLDATA will be received for now
0909:            private void parseSQLDIAGCN() throws DisconnectException,
0910:                    SqlException {
0911:                if (readFdocaOneByte() == CodePoint.NULLDATA) {
0912:                    return;
0913:                }
0914:
0915:                // The server should send NULLDATA
0916:                netAgent_
0917:                        .accumulateChainBreakingReadExceptionAndThrow(new DisconnectException(
0918:                                netAgent_, new ClientMessageId(
0919:                                        SQLState.DRDA_COMMAND_NOT_IMPLEMENTED),
0920:                                "parseSQLDIAGCN"));
0921:            }
0922:
0923:            // SQL Diagnostics Condition Group Description
0924:            //
0925:            // SQLDCCODE; PROTOCOL TYPE I4; ENVLID 0x02; Length Override 4
0926:            // SQLDCSTATE; PROTOCOL TYPE FCS; ENVLID Ox30; Lengeh Override 5
0927:            // SQLDCREASON; PROTOCOL TYPE I4; ENVLID 0x02; Length Override 4
0928:            // SQLDCLINEN; PROTOCOL TYPE I4; ENVLID 0x02; Length Override 4
0929:            // SQLDCROWN; PROTOCOL TYPE I8; ENVLID 0x16; Lengeh Override 8
0930:            // SQLDCER01; PROTOCOL TYPE I4; ENVLID 0x02; Length Override 4
0931:            // SQLDCER02; PROTOCOL TYPE I4; ENVLID 0x02; Length Override 4
0932:            // SQLDCER03; PROTOCOL TYPE I4; ENVLID 0x02; Length Override 4
0933:            // SQLDCER04; PROTOCOL TYPE I4; ENVLID 0x02; Length Override 4
0934:            // SQLDCPART; PROTOCOL TYPE I4; ENVLID 0x02; Length Override 4
0935:            // SQLDCPPOP; PROTOCOL TYPE I4; ENVLID 0x02; Length Override 4
0936:            // SQLDCMSGID; PROTOCOL TYPE FCS; ENVLID 0x30; Length Override 10
0937:            // SQLDCMDE; PROTOCOL TYPE FCS; ENVLID 0x30; Length Override 8
0938:            // SQLDCPMOD; PROTOCOL TYPE FCS; ENVLID 0x30; Length Override 5
0939:            // SQLDCRDB; PROTOCOL TYPE VCS; ENVLID 0x32; Length Override 255
0940:            // SQLDCTOKS; PROTOCOL TYPE N-RLO; ENVLID 0xF7; Length Override 0
0941:            // SQLDCMSG_m; PROTOCOL TYPE NVMC; ENVLID 0x3F; Length Override 32672
0942:            // SQLDCMSG_S; PROTOCOL TYPE NVCS; ENVLID 0x33; Length Override 32672
0943:            // SQLDCCOLN_m; PROTOCOL TYPE NVCM ; ENVLID 0x3F; Length Override 255
0944:            // SQLDCCOLN_s; PROTOCOL TYPE NVCS; ENVLID 0x33; Length Override 255
0945:            // SQLDCCURN_m; PROTOCOL TYPE NVCM; ENVLID 0x3F; Length Override 255
0946:            // SQLDCCURN_s; PROTOCOL TYPE NVCS; ENVLID 0x33; Length Override 255
0947:            // SQLDCPNAM_m; PROTOCOL TYPE NVCM; ENVLID 0x3F; Length Override 255
0948:            // SQLDCPNAM_s; PROTOCOL TYPE NVCS; ENVLID 0x33; Length Override 255
0949:            // SQLDCXGRP; PROTOCOL TYPE N-GDA; ENVLID 0xD3; Length Override 1
0950:            private NetSqlca parseSQLDCGRP() throws DisconnectException,
0951:                    SqlException {
0952:
0953:                int sqldcCode = readFdocaInt(); // SQLCODE
0954:                String sqldcState = readFdocaString(5, netAgent_.targetTypdef_
0955:                        .getCcsidSbcEncoding()); // SQLSTATE
0956:                int sqldcReason = readFdocaInt(); // REASON_CODE
0957:
0958:                skipFdocaBytes(12); // LINE_NUMBER + ROW_NUMBER
0959:
0960:                NetSqlca sqlca = new NetSqlca(netAgent_.netConnection_,
0961:                        sqldcCode, sqldcState, (byte[]) null);
0962:
0963:                skipFdocaBytes(49); // SQLDCER01-04 + SQLDCPART + SQLDCPPOP + SQLDCMSGID
0964:                // SQLDCMDE + SQLDCPMOD + RDBNAME
0965:                parseSQLDCTOKS(); // MESSAGE_TOKENS
0966:
0967:                String sqldcMsg = parseVCS(qrydscTypdef_); // MESSAGE_TEXT
0968:
0969:                if (sqldcMsg != null) {
0970:                    sqlca.setSqlerrmcBytes(sqldcMsg.getBytes(),
0971:                            netAgent_.targetTypdef_.getByteOrder());
0972:                }
0973:
0974:                skipFdocaBytes(12); // COLUMN_NAME + PARAMETER_NAME + EXTENDED_NAMES
0975:
0976:                parseSQLDCXGRP(); // SQLDCXGRP
0977:                return sqlca;
0978:            }
0979:
0980:            // SQL Diagnostics Condition Row - Identity 0xE5
0981:            // SQLDCGRP; GROUP LID 0xD5; ELEMENT TAKEN 0(all); REP FACTOR 1
0982:            private NetSqlca parseSQLDCROW() throws DisconnectException,
0983:                    SqlException {
0984:                return parseSQLDCGRP();
0985:            }
0986:
0987:            // SQL Diagnostics Condition Token Array - Identity 0xF7
0988:            // NULLDATA will be received for now
0989:            void parseSQLDCTOKS() throws DisconnectException, SqlException {
0990:                if (readFdocaOneByte() == CodePoint.NULLDATA) {
0991:                    return;
0992:                }
0993:
0994:                // The server should send NULLDATA
0995:                netAgent_
0996:                        .accumulateChainBreakingReadExceptionAndThrow(new DisconnectException(
0997:                                netAgent_, new ClientMessageId(
0998:                                        SQLState.DRDA_COMMAND_NOT_IMPLEMENTED),
0999:                                "parseSQLDCTOKS"));
1000:            }
1001:
1002:            // SQL Diagnostics Extended Names Group Description - Identity 0xD5
1003:            // NULLDATA will be received for now
1004:            private void parseSQLDCXGRP() throws DisconnectException,
1005:                    SqlException {
1006:                if (readFdocaOneByte() == CodePoint.NULLDATA) {
1007:                    return;
1008:                }
1009:
1010:                // The server should send NULLDATA
1011:                netAgent_
1012:                        .accumulateChainBreakingReadExceptionAndThrow(new DisconnectException(
1013:                                netAgent_, new ClientMessageId(
1014:                                        SQLState.DRDA_COMMAND_NOT_IMPLEMENTED),
1015:                                "parseSQLDCXGRP"));
1016:            }
1017:
1018:            private String parseVCS(Typdef typdefInEffect)
1019:                    throws DisconnectException, SqlException {
1020:                return readFdocaString(readFdocaTwoByteLength(), typdefInEffect
1021:                        .getCcsidSbcEncoding());
1022:            }
1023:
1024:            // This is not used for column data.
1025:            private String readFdocaString(int length, String encoding)
1026:                    throws DisconnectException, SqlException {
1027:                if (length == 0) {
1028:                    return null;
1029:                }
1030:
1031:                // For singleton select, the complete row always comes back, even if multiple query blocks are required,
1032:                // so there is no need to drive a flowFetch (continue query) request for singleton select.
1033:                if ((position_ + length) > lastValidBytePosition_) {
1034:                    // Check for ENDQRYRM, throw SqlException if already received one.
1035:                    checkAndThrowReceivedEndqryrm();
1036:
1037:                    // Send CNTQRY to complete the row/rowset.
1038:                    int lastValidByteBeforeFetch = completeSplitRow();
1039:
1040:                    // if lastValidBytePosition_ has not changed, and an ENDQRYRM was received,
1041:                    // throw a SqlException for the ENDQRYRM.
1042:                    checkAndThrowReceivedEndqryrm(lastValidByteBeforeFetch);
1043:                }
1044:
1045:                String s = null;
1046:
1047:                try {
1048:                    s = new String(dataBuffer_, position_, length, encoding);
1049:                } catch (java.io.UnsupportedEncodingException e) {
1050:                    netAgent_
1051:                            .accumulateChainBreakingReadExceptionAndThrow(new org.apache.derby.client.am.DisconnectException(
1052:                                    netAgent_,
1053:                                    new ClientMessageId(
1054:                                            SQLState.NET_ENCODING_NOT_SUPPORTED),
1055:                                    e));
1056:                }
1057:
1058:                position_ += length;
1059:                return s;
1060:            }
1061:
1062:            void allocateColumnOffsetAndLengthArrays() {
1063:                columnDataPosition_ = new int[columns_];
1064:                columnDataComputedLength_ = new int[columns_];
1065:                isNull_ = new boolean[columns_];
1066:            }
1067:
1068:            void setBlocking(int queryProtocolType) {
1069:                if (queryProtocolType == CodePoint.LMTBLKPRC) {
1070:                    blocking_ = true;
1071:                } else {
1072:                    blocking_ = false;
1073:                }
1074:            }
1075:
1076:            protected byte[] findExtdtaData(int column) {
1077:                byte[] data = null;
1078:
1079:                // locate the EXTDTA bytes, if any
1080:                Integer key = new Integer(column);
1081:
1082:                if (extdtaPositions_.containsKey(key)) {
1083:                    //  found, get the data
1084:                    int extdtaQueuePosition = ((Integer) extdtaPositions_
1085:                            .get(key)).intValue();
1086:                    data = (byte[]) (extdtaData_.get(extdtaQueuePosition));
1087:                }
1088:
1089:                return data;
1090:            }
1091:
1092:            public Blob getBlobColumn_(int column, Agent agent)
1093:                    throws SqlException {
1094:                int index = column - 1;
1095:                int dataOffset;
1096:                byte[] data;
1097:                Blob blob = null;
1098:
1099:                // locate the EXTDTA bytes, if any
1100:                data = findExtdtaData(column);
1101:
1102:                if (data != null) {
1103:                    // data found
1104:                    // set data offset based on the presence of a null indicator
1105:                    if (!nullable_[index]) {
1106:                        dataOffset = 0;
1107:                    } else {
1108:                        dataOffset = 1;
1109:                    }
1110:
1111:                    blob = new Blob(data, agent, dataOffset);
1112:                } else {
1113:                    blob = new Blob(new byte[0], agent, 0);
1114:                }
1115:
1116:                return blob;
1117:            }
1118:
1119:            public Clob getClobColumn_(int column, Agent agent)
1120:                    throws SqlException {
1121:                int index = column - 1;
1122:                int dataOffset;
1123:                byte[] data;
1124:                Clob clob = null;
1125:
1126:                // locate the EXTDTA bytes, if any
1127:                data = findExtdtaData(column);
1128:
1129:                if (data != null) {
1130:                    // data found
1131:                    // set data offset based on the presence of a null indicator
1132:                    if (!nullable_[index]) {
1133:                        dataOffset = 0;
1134:                    } else {
1135:                        dataOffset = 1;
1136:                    }
1137:                    clob = new Clob(agent, data, charsetName_[index],
1138:                            dataOffset);
1139:                } else {
1140:                    // the locator is not valid, it is a zero-length LOB
1141:                    clob = new Clob(agent, "");
1142:                }
1143:
1144:                return clob;
1145:            }
1146:
1147:            public byte[] getClobBytes_(int column, int[] dataOffset /*output*/)
1148:                    throws SqlException {
1149:                int index = column - 1;
1150:                byte[] data = null;
1151:
1152:                // locate the EXTDTA bytes, if any
1153:                data = findExtdtaData(column);
1154:
1155:                if (data != null) {
1156:                    // data found
1157:                    // set data offset based on the presence of a null indicator
1158:                    if (!nullable_[index]) {
1159:                        dataOffset[0] = 0;
1160:                    } else {
1161:                        dataOffset[0] = 1;
1162:                    }
1163:                }
1164:
1165:                return data;
1166:            }
1167:
1168:            // this is really an event-callback from NetStatementReply.parseSQLDTARDarray()
1169:            void initializeColumnInfoArrays(Typdef typdef, int columnCount,
1170:                    int targetSqlamForTypdef) throws DisconnectException {
1171:                qrydscTypdef_ = typdef;
1172:
1173:                // Allocate  arrays to hold the descriptor information.
1174:                setNumberOfColumns(columnCount);
1175:                fdocaLength_ = new int[columnCount];
1176:                isGraphic_ = new boolean[columnCount];
1177:                typeToUseForComputingDataLength_ = new int[columnCount];
1178:                targetSqlamForTypdef_ = targetSqlamForTypdef;
1179:            }
1180:
1181:            int ensureSpaceForDataBuffer(int ddmLength) {
1182:                if (dataBuffer_ == null) {
1183:                    allocateDataBuffer();
1184:                }
1185:                //super.resultSet.cursor.clearColumnDataOffsetsCache();
1186:                // Need to know how many bytes to ask from the Reply object,
1187:                // and handle the case where buffer is not big enough for all the bytes.
1188:                // Get the length in front of the code point first.
1189:
1190:                int bytesAvailableInDataBuffer = dataBuffer_.length
1191:                        - lastValidBytePosition_;
1192:
1193:                // Make sure the buffer has at least ddmLength amount of room left.
1194:                // If not, expand the buffer before calling the getQrydtaData() method.
1195:                if (bytesAvailableInDataBuffer < ddmLength) {
1196:
1197:                    // Get a new buffer that is twice the size of the current buffer.
1198:                    // Copy the contents from the old buffer to the new buffer.
1199:                    int newBufferSize = 2 * dataBuffer_.length;
1200:
1201:                    while (newBufferSize < ddmLength) {
1202:                        newBufferSize = 2 * newBufferSize;
1203:                    }
1204:
1205:                    byte[] tempBuffer = new byte[newBufferSize];
1206:
1207:                    System.arraycopy(dataBuffer_, 0, tempBuffer, 0,
1208:                            lastValidBytePosition_);
1209:
1210:                    // Make the new buffer the dataBuffer.
1211:                    dataBuffer_ = tempBuffer;
1212:
1213:                    // Recalculate bytesAvailableInDataBuffer
1214:                    bytesAvailableInDataBuffer = dataBuffer_.length
1215:                            - lastValidBytePosition_;
1216:                }
1217:                return bytesAvailableInDataBuffer;
1218:            }
1219:
1220:            protected void getMoreData_() throws SqlException {
1221:                // reset the dataBuffer_ before getting more data if cursor is foward-only.
1222:                // getMoreData() is only called in Cursor.next() when current position is
1223:                // equal to lastValidBytePosition_.
1224:                if (netResultSet_.resultSetType_ == java.sql.ResultSet.TYPE_FORWARD_ONLY) {
1225:                    resetDataBuffer();
1226:                }
1227:                netResultSet_.flowFetch();
1228:            }
1229:
1230:            public void nullDataForGC() // memory leak fix
1231:            {
1232:                super .nullDataForGC();
1233:                qrydscTypdef_ = null;
1234:                typeToUseForComputingDataLength_ = null;
1235:                isGraphic_ = null;
1236:
1237:                if (extdtaPositions_ != null) {
1238:                    extdtaPositions_.clear();
1239:                }
1240:                extdtaPositions_ = null;
1241:
1242:                if (extdtaData_ != null) {
1243:                    extdtaData_.clear();
1244:                }
1245:                extdtaData_ = null;
1246:            }
1247:
1248:            // It is possible for the driver to have received an QRYDTA(with incomplete row)+ENDQRYRM+SQLCARD.
1249:            // This means some error has occurred on the server and the server is terminating the query.
1250:            // Before sending a CNTQRY to retrieve the rest of the split row, check if an ENDQRYRM has already
1251:            // been received.  If so, do not send CNTQRY because the cursor is already closed on the server.
1252:            // Instead, throw a SqlException.  Since we did not receive a complete row, it is not safe to
1253:            // allow the application to continue to access the ResultSet, so we close it.
1254:            private void checkAndThrowReceivedEndqryrm() throws SqlException {
1255:                // If we are in a split row, and before sending CNTQRY, check whether an ENDQRYRM
1256:                // has been received.
1257:                if (!netResultSet_.openOnServer_) {
1258:                    SqlException sqlException = null;
1259:                    int sqlcode = org.apache.derby.client.am.Utils
1260:                            .getSqlcodeFromSqlca(netResultSet_.queryTerminatingSqlca_);
1261:                    if (sqlcode < 0) {
1262:                        sqlException = new SqlException(agent_.logWriter_,
1263:                                netResultSet_.queryTerminatingSqlca_);
1264:                    } else {
1265:                        sqlException = new SqlException(
1266:                                agent_.logWriter_,
1267:                                new ClientMessageId(
1268:                                        SQLState.NET_QUERY_PROCESSING_TERMINATED));
1269:                    }
1270:                    try {
1271:                        netResultSet_.closeX(); // the auto commit logic is in closeX()
1272:                    } catch (SqlException e) {
1273:                        sqlException.setNextException(e);
1274:                    }
1275:                    throw sqlException;
1276:                }
1277:            }
1278:
1279:            private void checkAndThrowReceivedEndqryrm(
1280:                    int lastValidBytePositionBeforeFetch) throws SqlException {
1281:                // if we have received more data in the dataBuffer_, just return.
1282:                if (lastValidBytePosition_ > lastValidBytePositionBeforeFetch) {
1283:                    return;
1284:                }
1285:                checkAndThrowReceivedEndqryrm();
1286:            }
1287:
1288:            private int completeSplitRow() throws DisconnectException,
1289:                    SqlException {
1290:                int lastValidBytePositionBeforeFetch = 0;
1291:                if (netResultSet_ != null && netResultSet_.scrollable_) {
1292:                    lastValidBytePositionBeforeFetch = lastValidBytePosition_;
1293:                    netResultSet_.flowFetchToCompleteRowset();
1294:                } else {
1295:                    // Shift partial row to the beginning of the dataBuffer
1296:                    shiftPartialRowToBeginning();
1297:                    resetCurrentRowPosition();
1298:                    lastValidBytePositionBeforeFetch = lastValidBytePosition_;
1299:                    netResultSet_.flowFetch();
1300:                }
1301:                return lastValidBytePositionBeforeFetch;
1302:            }
1303:
1304:            private int completeSplitRow(int index) throws DisconnectException,
1305:                    SqlException {
1306:                int lastValidBytePositionBeforeFetch = 0;
1307:                if (netResultSet_ != null && netResultSet_.scrollable_) {
1308:                    lastValidBytePositionBeforeFetch = lastValidBytePosition_;
1309:                    netResultSet_.flowFetchToCompleteRowset();
1310:                } else {
1311:                    // Shift partial row to the beginning of the dataBuffer
1312:                    shiftPartialRowToBeginning();
1313:                    adjustColumnOffsetsForColumnsPreviouslyCalculated(index);
1314:                    resetCurrentRowPosition();
1315:                    lastValidBytePositionBeforeFetch = lastValidBytePosition_;
1316:                    netResultSet_.flowFetch();
1317:                }
1318:                return lastValidBytePositionBeforeFetch;
1319:            }
1320:
1321:            private int[] allocateColumnDataPositionArray(int row) {
1322:                int[] columnDataPosition;
1323:                if (columnDataPositionCache_.size() == row) {
1324:                    columnDataPosition = new int[columns_];
1325:                    columnDataPositionCache_.add(columnDataPosition);
1326:                } else {
1327:                    columnDataPosition = (int[]) columnDataPositionCache_
1328:                            .get(row);
1329:                }
1330:                return columnDataPosition;
1331:            }
1332:
1333:            private int[] allocateColumnDataComputedLengthArray(int row) {
1334:                int[] columnDataComputedLength;
1335:                if (columnDataLengthCache_.size() == row) {
1336:                    columnDataComputedLength = new int[columns_];
1337:                    columnDataLengthCache_.add(columnDataComputedLength);
1338:                } else {
1339:                    columnDataComputedLength = (int[]) columnDataLengthCache_
1340:                            .get(row);
1341:                }
1342:                return columnDataComputedLength;
1343:            }
1344:
1345:            private boolean[] allocateColumnDataIsNullArray(int row) {
1346:                boolean[] columnDataIsNull;
1347:                if (columnDataIsNullCache_.size() <= row) {
1348:                    columnDataIsNull = new boolean[columns_];
1349:                    columnDataIsNullCache_.add(columnDataIsNull);
1350:                } else {
1351:                    columnDataIsNull = (boolean[]) columnDataIsNullCache_
1352:                            .get(row);
1353:                }
1354:                return columnDataIsNull;
1355:            }
1356:
1357:            protected int getDecimalLength(int index) {
1358:                return (((fdocaLength_[index] >> 8) & 0xff) + 2) / 2;
1359:            }
1360:
1361:            /**
1362:             * Set the value of value of allRowsReceivedFromServer_.
1363:             *
1364:             * @param b a <code>boolean</code> value indicating whether all
1365:             * rows are received from the server
1366:             */
1367:            public final void setAllRowsReceivedFromServer(boolean b) {
1368:                if (b && qryclsimpEnabled_) {
1369:                    netResultSet_.markClosedOnServer();
1370:                }
1371:                super .setAllRowsReceivedFromServer(b);
1372:            }
1373:
1374:            /**
1375:             * Set a flag indicating whether QRYCLSIMP is enabled.
1376:             *
1377:             * @param flag true if QRYCLSIMP is enabled
1378:             */
1379:            final void setQryclsimpEnabled(boolean flag) {
1380:                qryclsimpEnabled_ = flag;
1381:            }
1382:
1383:            /**
1384:             * Check whether QRYCLSIMP is enabled on this cursor.
1385:             *
1386:             * @return true if QRYCLSIMP is enabled
1387:             */
1388:            final boolean getQryclsimpEnabled() {
1389:                return qryclsimpEnabled_;
1390:            }
1391:        }
www.java2java.com | Contact Us
Copyright 2009 - 12 Demo Source and Support. All rights reserved.
All other trademarks are property of their respective owners.