001: /*
002:
003: Derby - Class org.apache.derby.client.net.NetResultSet
004:
005: Licensed to the Apache Software Foundation (ASF) under one or more
006: contributor license agreements. See the NOTICE file distributed with
007: this work for additional information regarding copyright ownership.
008: The ASF licenses this file to You under the Apache License, Version 2.0
009: (the "License"); you may not use this file except in compliance with
010: the License. You may obtain a copy of the License at
011:
012: http://www.apache.org/licenses/LICENSE-2.0
013:
014: Unless required by applicable law or agreed to in writing, software
015: distributed under the License is distributed on an "AS IS" BASIS,
016: WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
017: See the License for the specific language governing permissions and
018: limitations under the License.
019:
020: */
021: package org.apache.derby.client.net;
022:
023: import org.apache.derby.client.am.Cursor;
024: import org.apache.derby.client.am.DisconnectException;
025: import org.apache.derby.client.am.Section;
026: import org.apache.derby.client.am.SqlException;
027:
028: public class NetResultSet extends org.apache.derby.client.am.ResultSet {
029: // Alias for (NetConnection) super.statement.connection
030: private final NetConnection netConnection_;
031:
032: // Alias for (NetStatement) super.statement
033: private final NetStatement netStatement_;
034:
035: // Alias for (NetCursor) super.cursor
036: final NetCursor netCursor_;
037:
038: // Alias for (NetAgent) super.agent
039: final private NetAgent netAgent_;
040:
041: // Indicates whether the fixed row protocol is being used. If so,
042: // the fetch size will always be 1.
043: private boolean isFixedRowProtocol = false;
044:
045: //-----------------------------state------------------------------------------
046:
047: // This is used to avoid sending multiple outovr over subsequent next()'s
048: public boolean firstOutovrBuilt_ = false;
049:
050: //---------------------constructors/finalizer---------------------------------
051:
052: // parseOpnqrym() is called right after this constructor is called.
053:
054: NetResultSet(
055: NetAgent netAgent,
056: NetStatement netStatement,
057: Cursor cursor,
058: int qryprctyp, //protocolType, CodePoint.FIXROWPRC |
059: // CodePoint.LMTBLKPRC
060: int sqlcsrhld, // holdOption, 0xF0 for false (default) | 0xF1 for true.
061: int qryattscr, // scrollOption, 0xF0 for false (default) | 0xF1 for true.
062: int qryattsns, // sensitivity, CodePoint.QRYUNK |
063: // CodePoint.QRYINS |
064: // CodePoint.QRYSNSSTC
065: int qryattset, // rowsetCursor, 0xF0 for false (default) | 0xF1 for true.
066: long qryinsid, // instanceIdentifier, 0 (if not returned, check default) or number
067: int actualResultSetType, int actualResultSetConcurrency,
068: int actualResultSetHoldability) //throws DisconnectException
069: {
070: super (netAgent,
071: netStatement.statement_,
072: //new NetCursor (netAgent, qryprctyp),
073: cursor,
074: // call the constructor with the real resultSetType and resultSetConcurrency
075: // returned from the server
076: actualResultSetType, actualResultSetConcurrency,
077: actualResultSetHoldability);
078:
079: netAgent_ = netAgent;
080:
081: // Set up cheat-links
082: netCursor_ = (NetCursor) cursor_;
083: netStatement_ = netStatement;
084: netConnection_ = netStatement.netConnection_;
085:
086: netCursor_.netResultSet_ = this ;
087:
088: cursorHold_ = (sqlcsrhld != 0xf0);
089: if (qryattscr == 0xF1) {
090: scrollable_ = true;
091: }
092:
093: // The number of rows returned by the server will always be 1 when the
094: // Fixed Row Protocol is being used.
095: if (qryprctyp == CodePoint.FIXROWPRC) {
096: isFixedRowProtocol = true;
097: fetchSize_ = 1;
098: } else {
099: fetchSize_ = suggestedFetchSize_;
100: }
101:
102: switch (qryattsns) {
103: case CodePoint.QRYUNK:
104: sensitivity_ = sensitivity_unknown__;
105: break;
106: case CodePoint.QRYINS:
107: sensitivity_ = sensitivity_insensitive__;
108: break;
109: case CodePoint.QRYSNSSTC:
110: sensitivity_ = sensitivity_sensitive_static__;
111: break;
112: default: // shouldn't happen
113: break;
114: }
115:
116: if (qryattset == 0xF1) {
117: isRowsetCursor_ = true;
118: }
119:
120: queryInstanceIdentifier_ = qryinsid;
121: nestingLevel_ = (int) ((queryInstanceIdentifier_ >>> 48) & 0xFFFF);
122: }
123:
124: //-------------------------------flow methods---------------------------------
125:
126: // Go through the QRYDTA's received, and calculate the column offsets for each row.
127: protected void parseRowset_() throws SqlException {
128: int row = 0;
129: // Parse all the rows received in the rowset
130: // The index we are passing will keep track of which row in the rowset we are parsing
131: // so we can reuse the columnDataPosition/Length/IsNull arrays.
132: while (netCursor_.calculateColumnOffsetsForRow_(row, true)) {
133: rowsReceivedInCurrentRowset_++;
134: row++;
135: }
136:
137: // if rowset is not complete and an endqryrm was received, will skip the while loop
138: // and go to the checkAndThrow method. otherwise flow an cntqry to try to complete
139: // the rowset.
140: // -- there is no need to complete the rowset for rowset cursors. fetching stops when
141: // the end of data is returned or when an error occurs. all successfully fetched rows
142: // are returned to the user. the specific error is not returned until the next fetch.
143: while (rowsReceivedInCurrentRowset_ != fetchSize_
144: && !netCursor_.allRowsReceivedFromServer()
145: && !isRowsetCursor_
146: && sensitivity_ != sensitivity_sensitive_dynamic__
147: && sensitivity_ != sensitivity_sensitive_static__) {
148: flowFetchToCompleteRowset();
149: while (netCursor_.calculateColumnOffsetsForRow_(row, true)) {
150: rowsReceivedInCurrentRowset_++;
151: row++;
152: }
153: }
154: checkAndThrowReceivedQueryTerminatingException();
155: }
156:
157: public void setFetchSize_(int rows) {
158: // Do not change the fetchSize for Fixed Row Protocol
159: suggestedFetchSize_ = (rows == 0) ? 64 : rows;
160: if (!isFixedRowProtocol) {
161: fetchSize_ = suggestedFetchSize_;
162: }
163: }
164:
165: //-----------------------------helper methods---------------------------------
166:
167: void flowFetchToCompleteRowset() throws DisconnectException {
168: try {
169: agent_.beginWriteChain(statement_);
170:
171: writeScrollableFetch_(
172: (generatedSection_ == null) ? statement_.section_
173: : generatedSection_, fetchSize_
174: - rowsReceivedInCurrentRowset_,
175: scrollOrientation_relative__, 1, false); // false means do not disard pending
176: // partial row and pending query blocks
177:
178: agent_.flow(statement_);
179: readScrollableFetch_();
180: agent_.endReadChain();
181: } catch (SqlException e) {
182: throw new DisconnectException(agent_, e);
183: }
184: }
185:
186: void queryDataWasReturnedOnOpen() throws DisconnectException {
187: }
188:
189: // ------------------------------- abstract box car methods --------------------------------------
190: public void writeFetch_(Section section) throws SqlException {
191: if (resultSetType_ == java.sql.ResultSet.TYPE_FORWARD_ONLY
192: && fetchSize_ != 0 && rowsYetToBeReceivedForRowset_ > 0) {
193: netAgent_.resultSetRequest_.writeFetch(this , section,
194: rowsYetToBeReceivedForRowset_);
195: } else {
196: netAgent_.resultSetRequest_.writeFetch(this , section,
197: fetchSize_);
198: }
199: }
200:
201: public void readFetch_() throws SqlException {
202: netAgent_.resultSetReply_.readFetch(this );
203: }
204:
205: public void writeScrollableFetch_(Section section, int fetchSize,
206: int orientation, long rowToFetch, boolean resetQueryBlocks)
207: throws SqlException {
208: netAgent_.resultSetRequest_.writeScrollableFetch(this , section,
209: fetchSize, orientation, rowToFetch, resetQueryBlocks);
210: }
211:
212: // think about splitting out the position cursor stuff from the fetch stuff
213: // use commented out abstract position cursor methods above
214: public void readScrollableFetch_() throws SqlException {
215: netAgent_.resultSetReply_.readScrollableFetch(this );
216: }
217:
218: public void writePositioningFetch_(Section section,
219: int orientation, long rowToFetch) throws SqlException {
220: netAgent_.resultSetRequest_.writePositioningFetch(this ,
221: section, orientation, rowToFetch);
222: }
223:
224: public void readPositioningFetch_() throws SqlException {
225: netAgent_.resultSetReply_.readPositioningFetch(this );
226: }
227:
228: public void writeCursorClose_(Section section) throws SqlException {
229: netAgent_.resultSetRequest_.writeCursorClose(this , section);
230: }
231:
232: public void readCursorClose_() throws SqlException {
233: netAgent_.resultSetReply_.readCursorClose(this );
234: }
235:
236: /**
237: * Method that is invoked by <code>closeX()</code> before the
238: * result set is actually being closed. If QRYCLSIMP is enabled on
239: * the cursor, scan data buffer for end of data (SQL state
240: * 02000). If end of data is received, the result set is closed on
241: * the server.
242: *
243: * @exception SqlException
244: */
245: protected void preClose_() throws SqlException {
246: if (netCursor_.getQryclsimpEnabled()) {
247: netCursor_.scanDataBufferForEndOfData();
248: }
249: }
250: }
|