1 | /* |
2 | |
3 | Derby - Class org.apache.derby.client.net.NetResultSetRequest |
4 | |
5 | Copyright (c) 2001, 2005 The Apache Software Foundation or its licensors, where applicable. |
6 | |
7 | Licensed under the Apache License, Version 2.0 (the "License"); |
8 | you may not use this file except in compliance with the License. |
9 | You may obtain a copy of the License at |
10 | |
11 | http://www.apache.org/licenses/LICENSE-2.0 |
12 | |
13 | Unless required by applicable law or agreed to in writing, software |
14 | distributed under the License is distributed on an "AS IS" BASIS, |
15 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
16 | See the License for the specific language governing permissions and |
17 | limitations under the License. |
18 | |
19 | */ |
20 | |
21 | package org.apache.derby.client.net; |
22 | |
23 | import org.apache.derby.client.am.ColumnMetaData; |
24 | import org.apache.derby.client.am.ResultSet; |
25 | import org.apache.derby.client.am.Section; |
26 | import org.apache.derby.client.am.SqlException; |
27 | import org.apache.derby.client.am.ClientMessageId; |
28 | |
29 | import org.apache.derby.shared.common.reference.SQLState; |
30 | |
31 | public class NetResultSetRequest extends NetStatementRequest |
32 | implements ResultSetRequestInterface { |
33 | public NetResultSetRequest(NetAgent netAgent, CcsidManager ccsidManager, int bufferSize) { |
34 | super(netAgent, ccsidManager, bufferSize); |
35 | } |
36 | |
37 | //----------------------------- entry points --------------------------------- |
38 | public void writeFetch(NetResultSet resultSet, |
39 | Section section, |
40 | int fetchSize) throws SqlException { |
41 | // - for forward-only cursors we do not send qryrowset on OPNQRY, fetchSize is ignored. |
42 | // but qryrowset is sent on EXCSQLSTT for a stored procedure call. |
43 | boolean sendQryrowset = |
44 | ((NetStatement) resultSet.statement_.materialStatement_).qryrowsetSentOnOpnqry_; |
45 | |
46 | boolean sendRtnextdta = false; |
47 | if (sendQryrowset && resultSet.resultSetType_ == java.sql.ResultSet.TYPE_FORWARD_ONLY && |
48 | ((NetCursor) resultSet.cursor_).hasLobs_) { |
49 | fetchSize = 1; |
50 | resultSet.fetchSize_ = 1; |
51 | sendRtnextdta = true; |
52 | ((NetCursor) resultSet.cursor_).rtnextrow_ = false; |
53 | } |
54 | // if one of the result sets returned from a stored procedure is scrollable, |
55 | // then we set netStatement_.qryrowsetSentOnOpnqry_ to true even though we didn't really |
56 | // send a qryrowset on excsqlstt for sqlam >= 7. this is ok for scrollable cursors, |
57 | // but will cause a problem for forward-only cursors. Because if fetchSize was never |
58 | // set, we will send qryrowset(0), which will cause a syntaxrm. |
59 | else if (resultSet.fetchSize_ == 0) { |
60 | sendQryrowset = false; |
61 | } |
62 | |
63 | buildCNTQRY(section, |
64 | sendQryrowset, |
65 | resultSet.queryInstanceIdentifier_, |
66 | fetchSize, |
67 | sendRtnextdta); |
68 | |
69 | buildOUTOVR(resultSet, |
70 | resultSet.resultSetMetaData_, |
71 | resultSet.firstOutovrBuilt_, |
72 | ((NetCursor) resultSet.cursor_).hasLobs_); |
73 | } |
74 | |
75 | public void writeScrollableFetch(NetResultSet resultSet, |
76 | Section section, |
77 | int fetchSize, |
78 | int orientation, |
79 | long rowToFetch, |
80 | boolean resetQueryBlocks) throws SqlException { |
81 | int protocolOrientation = computePROTOCOLOrientation(orientation); |
82 | |
83 | // - for sensitive-static cursors: |
84 | // * qryrowset must be sent on opnqry to indicate to the server that the cursor is |
85 | // going to be used in a scrollable fashion. (sqlam<7) |
86 | // * if qryrowset is sent on opnqry, then it must be sent on all subsequent cntqry's |
87 | // - for sensitive-dynamic non-rowset cursors: (we should never be in this case) |
88 | // * qryrowset is NOT ALLOWED on cntqry's |
89 | // - for rowset cursors: |
90 | // * qryrowset is optional. it is ignored on opnqry. if not sent on cntqry, |
91 | // then the fetch is going fetch next row as opposed to fetch next rowset. |
92 | boolean sendQryrowset = |
93 | (resultSet.isRowsetCursor_ || |
94 | (((NetStatement) resultSet.statement_.materialStatement_).qryrowsetSentOnOpnqry_ && |
95 | (resultSet.sensitivity_ == ResultSet.sensitivity_sensitive_static__ || |
96 | ((NetCursor) resultSet.cursor_).blocking_))); |
97 | |
98 | buildScrollCNTQRY(protocolOrientation, |
99 | rowToFetch, |
100 | section, |
101 | sendQryrowset, |
102 | resultSet.queryInstanceIdentifier_, |
103 | fetchSize, |
104 | resetQueryBlocks); |
105 | |
106 | buildOUTOVR(resultSet, |
107 | resultSet.resultSetMetaData_, |
108 | resultSet.firstOutovrBuilt_, |
109 | ((NetCursor) resultSet.cursor_).hasLobs_); |
110 | } |
111 | |
112 | public void writePositioningFetch(NetResultSet resultSet, |
113 | Section section, |
114 | int orientation, |
115 | long rowToFetch) throws SqlException { |
116 | int protocolOrientation = computePROTOCOLOrientation(orientation); |
117 | |
118 | // do not send qryrowste if the cursor is a non-rowset, sensitive dynamic cursor |
119 | boolean sendQryrowset = |
120 | resultSet.isRowsetCursor_ || |
121 | (((NetStatement) resultSet.statement_.materialStatement_).qryrowsetSentOnOpnqry_ && |
122 | resultSet.sensitivity_ != resultSet.sensitivity_sensitive_dynamic__); |
123 | |
124 | buildPositioningCNTQRY(protocolOrientation, |
125 | rowToFetch, |
126 | section, |
127 | sendQryrowset, |
128 | resultSet.queryInstanceIdentifier_, |
129 | resultSet.fetchSize_); |
130 | |
131 | buildOUTOVR(resultSet, |
132 | resultSet.resultSetMetaData_, |
133 | resultSet.firstOutovrBuilt_, |
134 | ((NetCursor) resultSet.cursor_).hasLobs_); |
135 | } |
136 | |
137 | public void writeCursorClose(NetResultSet resultSet, |
138 | Section section) throws SqlException { |
139 | buildCLSQRY(section, |
140 | resultSet.queryInstanceIdentifier_); |
141 | } |
142 | |
143 | //----------------------helper methods---------------------------------------- |
144 | // These methods are "private protected", which is not a recognized java privilege, |
145 | // but means that these methods are private to this class and to subclasses, |
146 | // and should not be used as package-wide friendly methods. |
147 | |
148 | private void buildCLSQRY(Section section, |
149 | long queryInstanceIdentifier) |
150 | throws SqlException { |
151 | createCommand(); |
152 | markLengthBytes(CodePoint.CLSQRY); |
153 | buildPKGNAMCSN(section); |
154 | buildQRYINSID(queryInstanceIdentifier); |
155 | updateLengthBytes(); |
156 | } |
157 | |
158 | private void buildCNTQRY(Section section, |
159 | boolean sendQryrowset, |
160 | long queryInstanceIdentifier, |
161 | int qryrowsetSize, |
162 | boolean sendRtnextdta) throws SqlException { |
163 | buildCoreCNTQRY(section, |
164 | sendQryrowset, |
165 | queryInstanceIdentifier, |
166 | qryrowsetSize); |
167 | |
168 | // We will always let RTNEXTDTA default to RTNEXTROW. The only time we need to send |
169 | // RTNEXTDTA RTNEXTALL is for a stored procedure returned forward-only ResultSet |
170 | // that has LOB columns. Since there are LOBs in the |
171 | // ResultSet, no QRYDTA is returned on execute. On the CNTQRY's, we will |
172 | // send qryrowset(1) and rtnextall. |
173 | if (sendRtnextdta) { |
174 | buildRTNEXTDTA(CodePoint.RTNEXTALL); |
175 | } |
176 | |
177 | |
178 | updateLengthBytes(); |
179 | } |
180 | |
181 | // buildCoreCntqry builds the common parameters |
182 | private void buildCoreCNTQRY(Section section, |
183 | boolean sendQryrowset, |
184 | long queryInstanceIdentifier, |
185 | int qryrowsetSize) |
186 | throws SqlException { |
187 | createCommand(); |
188 | markLengthBytes(CodePoint.CNTQRY); |
189 | |
190 | buildPKGNAMCSN(section); // 1. packageNameAndConsistencyToken |
191 | buildQRYBLKSZ(); // 2. qryblksz |
192 | |
193 | // maxblkext (-1) tells the server that the client is capable of receiving any number of query blocks |
194 | if (sendQryrowset) { |
195 | buildMAXBLKEXT(-1); // 3. maxblkext |
196 | } |
197 | |
198 | // 4. qryinsid |
199 | buildQRYINSID(queryInstanceIdentifier); |
200 | |
201 | if (sendQryrowset) { |
202 | buildQRYROWSET(qryrowsetSize); // 5. qryrowset |
203 | } |
204 | } |
205 | |
206 | // Send CNTQRY to get a new rowset from the target server. |
207 | private void buildScrollCNTQRY(int scrollOrientation, |
208 | long rowNumber, |
209 | Section section, |
210 | boolean sendQryrowset, |
211 | long queryInstanceIdentifier, |
212 | int qryrowsetSize, |
213 | boolean resetQueryBlocks) |
214 | throws SqlException { |
215 | buildCoreCNTQRY(section, |
216 | sendQryrowset, |
217 | queryInstanceIdentifier, |
218 | qryrowsetSize); |
219 | |
220 | buildQRYSCRORN(scrollOrientation); // qryscrorn |
221 | |
222 | if (scrollOrientation == CodePoint.QRYSCRABS || scrollOrientation == CodePoint.QRYSCRREL) { |
223 | buildQRYROWNBR(rowNumber); |
224 | } |
225 | |
226 | if (resetQueryBlocks) { |
227 | buildQRYBLKRST(0xF1); // do reset the rowset |
228 | } else { |
229 | buildQRYBLKRST(0xF0); // do not reset the rowset |
230 | } |
231 | |
232 | buildQRYRTNDTA(0xF1); // do return data |
233 | |
234 | updateLengthBytes(); |
235 | } |
236 | |
237 | // Send CTNQRY to reposition the cursor on the target server. |
238 | private void buildPositioningCNTQRY(int scrollOrientation, |
239 | long rowNumber, |
240 | Section section, |
241 | boolean sendQryrowset, |
242 | long queryInstanceIdentifier, |
243 | int qryrowsetSize) |
244 | throws SqlException { |
245 | createCommand(); |
246 | markLengthBytes(CodePoint.CNTQRY); |
247 | |
248 | buildPKGNAMCSN(section); // 1. pkgnamcsn |
249 | buildQRYBLKSZ(); // 2. qryblksz |
250 | |
251 | buildQRYINSID(queryInstanceIdentifier); // 3. qryinsid |
252 | |
253 | if (sendQryrowset) { |
254 | buildQRYROWSET(qryrowsetSize); // 4. qryrowset |
255 | } |
256 | |
257 | buildQRYSCRORN(scrollOrientation); // 5. qryscrorn |
258 | |
259 | if (scrollOrientation == CodePoint.QRYSCRABS || scrollOrientation == CodePoint.QRYSCRREL) { |
260 | buildQRYROWNBR(rowNumber); // 6. qryrownbr |
261 | } |
262 | |
263 | buildQRYBLKRST(0xF1); // 7. do reset the rowset |
264 | buildQRYRTNDTA(0xF0); // 8. do not return data |
265 | |
266 | |
267 | updateLengthBytes(); // for cntqry |
268 | } |
269 | |
270 | private void buildOUTOVR(ResultSet resultSet, |
271 | ColumnMetaData resultSetMetaData, |
272 | boolean firstOutovrBuilt, |
273 | boolean hasLobs) throws SqlException { |
274 | return; |
275 | } |
276 | |
277 | private void buildRTNEXTDTA(int rtnextdta) throws SqlException { |
278 | writeScalar1Byte(CodePoint.RTNEXTDTA, rtnextdta); |
279 | } |
280 | |
281 | private void buildQRYSCRORN(int scrollOrientation) throws SqlException { |
282 | writeScalar1Byte(CodePoint.QRYSCRORN, scrollOrientation); |
283 | } |
284 | |
285 | private void buildQRYBLKRST(int qryblkrst) throws SqlException { |
286 | writeScalar1Byte(CodePoint.QRYBLKRST, qryblkrst); |
287 | } |
288 | |
289 | private void buildQRYROWNBR(long rowNumber) throws SqlException { |
290 | writeScalar8Bytes(CodePoint.QRYROWNBR, rowNumber); |
291 | } |
292 | |
293 | private void buildQRYRTNDTA(int qryrtndta) throws SqlException { |
294 | writeScalar1Byte(CodePoint.QRYRTNDTA, qryrtndta); |
295 | } |
296 | |
297 | //----------------------non-parsing computational helper methods-------------- |
298 | // These methods are "private protected", which is not a recognized java privilege, |
299 | // but means that these methods are private to this class and to subclasses, |
300 | // and should not be used as package-wide friendly methods. |
301 | |
302 | // Called by NetResultSetRequest.writeScrollableFetch() |
303 | private int computePROTOCOLOrientation(int orientation) throws SqlException { |
304 | switch (orientation) { |
305 | case ResultSet.scrollOrientation_absolute__: |
306 | return CodePoint.QRYSCRABS; |
307 | |
308 | case ResultSet.scrollOrientation_after__: |
309 | return CodePoint.QRYSCRAFT; |
310 | |
311 | case ResultSet.scrollOrientation_before__: |
312 | return CodePoint.QRYSCRBEF; |
313 | |
314 | case ResultSet.scrollOrientation_relative__: |
315 | return CodePoint.QRYSCRREL; |
316 | |
317 | default: |
318 | throw new SqlException(netAgent_.logWriter_, |
319 | new ClientMessageId(SQLState.NET_INVALID_SCROLL_ORIENTATION)); |
320 | } |
321 | } |
322 | |
323 | } |