001: /*
002:
003: Derby - Class org.apache.derby.client.net.NetResultSetRequest
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:
022: package org.apache.derby.client.net;
023:
024: import org.apache.derby.client.am.ColumnMetaData;
025: import org.apache.derby.client.am.ResultSet;
026: import org.apache.derby.client.am.Section;
027: import org.apache.derby.client.am.SqlException;
028: import org.apache.derby.client.am.ClientMessageId;
029:
030: import org.apache.derby.shared.common.reference.SQLState;
031:
032: public class NetResultSetRequest extends NetStatementRequest implements
033: ResultSetRequestInterface {
034: public NetResultSetRequest(NetAgent netAgent,
035: CcsidManager ccsidManager, int bufferSize) {
036: super (netAgent, ccsidManager, bufferSize);
037: }
038:
039: //----------------------------- entry points ---------------------------------
040: public void writeFetch(NetResultSet resultSet, Section section,
041: int fetchSize) throws SqlException {
042: // - for forward-only cursors we do not send qryrowset on OPNQRY, fetchSize is ignored.
043: // but qryrowset is sent on EXCSQLSTT for a stored procedure call.
044: boolean sendQryrowset = ((NetStatement) resultSet.statement_.materialStatement_).qryrowsetSentOnOpnqry_;
045:
046: boolean sendRtnextdta = false;
047: if (sendQryrowset
048: && resultSet.resultSetType_ == java.sql.ResultSet.TYPE_FORWARD_ONLY
049: && ((NetCursor) resultSet.cursor_).hasLobs_) {
050: fetchSize = 1;
051: resultSet.fetchSize_ = 1;
052: sendRtnextdta = true;
053: ((NetCursor) resultSet.cursor_).rtnextrow_ = false;
054: }
055: // if one of the result sets returned from a stored procedure is scrollable,
056: // then we set netStatement_.qryrowsetSentOnOpnqry_ to true even though we didn't really
057: // send a qryrowset on excsqlstt for sqlam >= 7. this is ok for scrollable cursors,
058: // but will cause a problem for forward-only cursors. Because if fetchSize was never
059: // set, we will send qryrowset(0), which will cause a syntaxrm.
060: else if (resultSet.fetchSize_ == 0) {
061: sendQryrowset = false;
062: }
063:
064: buildCNTQRY(section, sendQryrowset,
065: resultSet.queryInstanceIdentifier_, fetchSize,
066: sendRtnextdta);
067:
068: buildOUTOVR(resultSet, resultSet.resultSetMetaData_,
069: resultSet.firstOutovrBuilt_,
070: ((NetCursor) resultSet.cursor_).hasLobs_);
071: }
072:
073: public void writeScrollableFetch(NetResultSet resultSet,
074: Section section, int fetchSize, int orientation,
075: long rowToFetch, boolean resetQueryBlocks)
076: throws SqlException {
077: int protocolOrientation = computePROTOCOLOrientation(orientation);
078:
079: // - for sensitive-static cursors:
080: // * qryrowset must be sent on opnqry to indicate to the server that the cursor is
081: // going to be used in a scrollable fashion. (sqlam<7)
082: // * if qryrowset is sent on opnqry, then it must be sent on all subsequent cntqry's
083: // - for sensitive-dynamic non-rowset cursors: (we should never be in this case)
084: // * qryrowset is NOT ALLOWED on cntqry's
085: // - for rowset cursors:
086: // * qryrowset is optional. it is ignored on opnqry. if not sent on cntqry,
087: // then the fetch is going fetch next row as opposed to fetch next rowset.
088: boolean sendQryrowset = (resultSet.isRowsetCursor_ || (((NetStatement) resultSet.statement_.materialStatement_).qryrowsetSentOnOpnqry_ && (resultSet.sensitivity_ == ResultSet.sensitivity_sensitive_static__ || ((NetCursor) resultSet.cursor_).blocking_)));
089:
090: buildScrollCNTQRY(protocolOrientation, rowToFetch, section,
091: sendQryrowset, resultSet.queryInstanceIdentifier_,
092: fetchSize, resetQueryBlocks);
093:
094: buildOUTOVR(resultSet, resultSet.resultSetMetaData_,
095: resultSet.firstOutovrBuilt_,
096: ((NetCursor) resultSet.cursor_).hasLobs_);
097: }
098:
099: public void writePositioningFetch(NetResultSet resultSet,
100: Section section, int orientation, long rowToFetch)
101: throws SqlException {
102: int protocolOrientation = computePROTOCOLOrientation(orientation);
103:
104: // do not send qryrowste if the cursor is a non-rowset, sensitive dynamic cursor
105: boolean sendQryrowset = resultSet.isRowsetCursor_
106: || (((NetStatement) resultSet.statement_.materialStatement_).qryrowsetSentOnOpnqry_ && resultSet.sensitivity_ != resultSet.sensitivity_sensitive_dynamic__);
107:
108: buildPositioningCNTQRY(protocolOrientation, rowToFetch,
109: section, sendQryrowset,
110: resultSet.queryInstanceIdentifier_,
111: resultSet.fetchSize_);
112:
113: buildOUTOVR(resultSet, resultSet.resultSetMetaData_,
114: resultSet.firstOutovrBuilt_,
115: ((NetCursor) resultSet.cursor_).hasLobs_);
116: }
117:
118: public void writeCursorClose(NetResultSet resultSet, Section section)
119: throws SqlException {
120: buildCLSQRY(section, resultSet.queryInstanceIdentifier_);
121: }
122:
123: //----------------------helper methods----------------------------------------
124: // These methods are "private protected", which is not a recognized java privilege,
125: // but means that these methods are private to this class and to subclasses,
126: // and should not be used as package-wide friendly methods.
127:
128: private void buildCLSQRY(Section section,
129: long queryInstanceIdentifier) throws SqlException {
130: createCommand();
131: markLengthBytes(CodePoint.CLSQRY);
132: buildPKGNAMCSN(section);
133: buildQRYINSID(queryInstanceIdentifier);
134: updateLengthBytes();
135: }
136:
137: private void buildCNTQRY(Section section, boolean sendQryrowset,
138: long queryInstanceIdentifier, int qryrowsetSize,
139: boolean sendRtnextdta) throws SqlException {
140: buildCoreCNTQRY(section, sendQryrowset,
141: queryInstanceIdentifier, qryrowsetSize);
142:
143: // We will always let RTNEXTDTA default to RTNEXTROW. The only time we need to send
144: // RTNEXTDTA RTNEXTALL is for a stored procedure returned forward-only ResultSet
145: // that has LOB columns. Since there are LOBs in the
146: // ResultSet, no QRYDTA is returned on execute. On the CNTQRY's, we will
147: // send qryrowset(1) and rtnextall.
148: if (sendRtnextdta) {
149: buildRTNEXTDTA(CodePoint.RTNEXTALL);
150: }
151:
152: updateLengthBytes();
153: }
154:
155: // buildCoreCntqry builds the common parameters
156: private void buildCoreCNTQRY(Section section,
157: boolean sendQryrowset, long queryInstanceIdentifier,
158: int qryrowsetSize) throws SqlException {
159: createCommand();
160: markLengthBytes(CodePoint.CNTQRY);
161:
162: buildPKGNAMCSN(section); // 1. packageNameAndConsistencyToken
163: buildQRYBLKSZ(); // 2. qryblksz
164:
165: // maxblkext (-1) tells the server that the client is capable of receiving any number of query blocks
166: if (sendQryrowset) {
167: buildMAXBLKEXT(-1); // 3. maxblkext
168: }
169:
170: // 4. qryinsid
171: buildQRYINSID(queryInstanceIdentifier);
172:
173: if (sendQryrowset) {
174: buildQRYROWSET(qryrowsetSize); // 5. qryrowset
175: }
176: }
177:
178: // Send CNTQRY to get a new rowset from the target server.
179: private void buildScrollCNTQRY(int scrollOrientation,
180: long rowNumber, Section section, boolean sendQryrowset,
181: long queryInstanceIdentifier, int qryrowsetSize,
182: boolean resetQueryBlocks) throws SqlException {
183: buildCoreCNTQRY(section, sendQryrowset,
184: queryInstanceIdentifier, qryrowsetSize);
185:
186: buildQRYSCRORN(scrollOrientation); // qryscrorn
187:
188: if (scrollOrientation == CodePoint.QRYSCRABS
189: || scrollOrientation == CodePoint.QRYSCRREL) {
190: buildQRYROWNBR(rowNumber);
191: }
192:
193: if (resetQueryBlocks) {
194: buildQRYBLKRST(0xF1); // do reset the rowset
195: } else {
196: buildQRYBLKRST(0xF0); // do not reset the rowset
197: }
198:
199: buildQRYRTNDTA(0xF1); // do return data
200:
201: updateLengthBytes();
202: }
203:
204: // Send CTNQRY to reposition the cursor on the target server.
205: private void buildPositioningCNTQRY(int scrollOrientation,
206: long rowNumber, Section section, boolean sendQryrowset,
207: long queryInstanceIdentifier, int qryrowsetSize)
208: throws SqlException {
209: createCommand();
210: markLengthBytes(CodePoint.CNTQRY);
211:
212: buildPKGNAMCSN(section); // 1. pkgnamcsn
213: buildQRYBLKSZ(); // 2. qryblksz
214:
215: buildQRYINSID(queryInstanceIdentifier); // 3. qryinsid
216:
217: if (sendQryrowset) {
218: buildQRYROWSET(qryrowsetSize); // 4. qryrowset
219: }
220:
221: buildQRYSCRORN(scrollOrientation); // 5. qryscrorn
222:
223: if (scrollOrientation == CodePoint.QRYSCRABS
224: || scrollOrientation == CodePoint.QRYSCRREL) {
225: buildQRYROWNBR(rowNumber); // 6. qryrownbr
226: }
227:
228: buildQRYBLKRST(0xF1); // 7. do reset the rowset
229: buildQRYRTNDTA(0xF0); // 8. do not return data
230:
231: updateLengthBytes(); // for cntqry
232: }
233:
234: private void buildOUTOVR(ResultSet resultSet,
235: ColumnMetaData resultSetMetaData, boolean firstOutovrBuilt,
236: boolean hasLobs) throws SqlException {
237: return;
238: }
239:
240: private void buildRTNEXTDTA(int rtnextdta) throws SqlException {
241: writeScalar1Byte(CodePoint.RTNEXTDTA, rtnextdta);
242: }
243:
244: private void buildQRYSCRORN(int scrollOrientation)
245: throws SqlException {
246: writeScalar1Byte(CodePoint.QRYSCRORN, scrollOrientation);
247: }
248:
249: private void buildQRYBLKRST(int qryblkrst) throws SqlException {
250: writeScalar1Byte(CodePoint.QRYBLKRST, qryblkrst);
251: }
252:
253: private void buildQRYROWNBR(long rowNumber) throws SqlException {
254: writeScalar8Bytes(CodePoint.QRYROWNBR, rowNumber);
255: }
256:
257: private void buildQRYRTNDTA(int qryrtndta) throws SqlException {
258: writeScalar1Byte(CodePoint.QRYRTNDTA, qryrtndta);
259: }
260:
261: //----------------------non-parsing computational helper methods--------------
262: // These methods are "private protected", which is not a recognized java privilege,
263: // but means that these methods are private to this class and to subclasses,
264: // and should not be used as package-wide friendly methods.
265:
266: // Called by NetResultSetRequest.writeScrollableFetch()
267: private int computePROTOCOLOrientation(int orientation)
268: throws SqlException {
269: switch (orientation) {
270: case ResultSet.scrollOrientation_absolute__:
271: return CodePoint.QRYSCRABS;
272:
273: case ResultSet.scrollOrientation_after__:
274: return CodePoint.QRYSCRAFT;
275:
276: case ResultSet.scrollOrientation_before__:
277: return CodePoint.QRYSCRBEF;
278:
279: case ResultSet.scrollOrientation_relative__:
280: return CodePoint.QRYSCRREL;
281:
282: default:
283: throw new SqlException(netAgent_.logWriter_,
284: new ClientMessageId(
285: SQLState.NET_INVALID_SCROLL_ORIENTATION));
286: }
287: }
288:
289: }
|