1/*********************************************************************
2 *
3 * This is based on code created by Peter Harvey,
4 * (pharvey@codebydesign.com).
5 *
6 * Modified and extended by Nick Gorham
7 * (nick@lurcher.org).
8 *
9 * Any bugs or problems should be considered the fault of Nick and not
10 * Peter.
11 *
12 * copyright (c) 1999 Nick Gorham
13 *
14 * This library is free software; you can redistribute it and/or
15 * modify it under the terms of the GNU Lesser General Public
16 * License as published by the Free Software Foundation; either
17 * version 2 of the License, or (at your option) any later version.
18 *
19 * This library is distributed in the hope that it will be useful,
20 * but WITHOUT ANY WARRANTY; without even the implied warranty of
21 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
22 * Lesser General Public License for more details.
23 *
24 * You should have received a copy of the GNU Lesser General Public
25 * License along with this library; if not, write to the Free Software
26 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
27 *
28 **********************************************************************
29 *
30 * $Id: SQLFetchScroll.c,v 1.6 2009/02/18 17:59:08 lurcher Exp $
31 *
32 * $Log: SQLFetchScroll.c,v $
33 * Revision 1.6 2009/02/18 17:59:08 lurcher
34 * Shift to using config.h, the compile lines were making it hard to spot warnings
35 *
36 * Revision 1.5 2007/11/29 12:00:31 lurcher
37 * Add 64 bit type changes to SQLExtendedFetch etc
38 *
39 * Revision 1.4 2003/10/30 18:20:45 lurcher
40 *
41 * Fix broken thread protection
42 * Remove SQLNumResultCols after execute, lease S4/S% to driver
43 * Fix string overrun in SQLDriverConnect
44 * Add initial support for Interix
45 *
46 * Revision 1.3 2002/12/05 17:44:30 lurcher
47 *
48 * Display unknown return values in return logging
49 *
50 * Revision 1.2 2001/12/13 13:00:32 lurcher
51 *
52 * Remove most if not all warnings on 64 bit platforms
53 * Add support for new MS 3.52 64 bit changes
54 * Add override to disable the stopping of tracing
55 * Add MAX_ROWS support in postgres driver
56 *
57 * Revision 1.1.1.1 2001/10/17 16:40:05 lurcher
58 *
59 * First upload to SourceForge
60 *
61 * Revision 1.2 2001/04/12 17:43:36 nick
62 *
63 * Change logging and added autotest to odbctest
64 *
65 * Revision 1.1.1.1 2000/09/04 16:42:52 nick
66 * Imported Sources
67 *
68 * Revision 1.8 2000/05/22 17:10:34 ngorham
69 *
70 * Fix problems with the FetchScroll -> ExtendedFetch Mapping
71 *
72 * Revision 1.7 1999/11/13 23:40:59 ngorham
73 *
74 * Alter the way DM logging works
75 * Upgrade the Postgres driver to 6.4.6
76 *
77 * Revision 1.6 1999/10/24 23:54:18 ngorham
78 *
79 * First part of the changes to the error reporting
80 *
81 * Revision 1.5 1999/09/21 22:34:24 ngorham
82 *
83 * Improve performance by removing unneeded logging calls when logging is
84 * disabled
85 *
86 * Revision 1.4 1999/07/10 21:10:16 ngorham
87 *
88 * Adjust error sqlstate from driver manager, depending on requested
89 * version (ODBC2/3)
90 *
91 * Revision 1.3 1999/07/04 21:05:07 ngorham
92 *
93 * Add LGPL Headers to code
94 *
95 * Revision 1.2 1999/06/30 23:56:54 ngorham
96 *
97 * Add initial thread safety code
98 *
99 * Revision 1.1.1.1 1999/05/29 13:41:07 sShandyb
100 * first go at it
101 *
102 * Revision 1.2 1999/06/02 23:48:45 ngorham
103 *
104 * Added more 3-2 mapping
105 *
106 * Revision 1.1.1.1 1999/05/27 18:23:17 pharvey
107 * Imported sources
108 *
109 * Revision 1.2 1999/05/03 19:50:43 nick
110 * Another check point
111 *
112 * Revision 1.1 1999/04/25 23:06:11 nick
113 * Initial revision
114 *
115 *
116 **********************************************************************/
117
118#include <config.h>
119#include "drivermanager.h"
120
121static char const rcsid[]= "$RCSfile: SQLFetchScroll.c,v $ $Revision: 1.6 $";
122
123SQLRETURN SQLFetchScroll( SQLHSTMT statement_handle,
124 SQLSMALLINT fetch_orientation,
125 SQLLEN fetch_offset )
126{
127 DMHSTMT statement = (DMHSTMT) statement_handle;
128 SQLRETURN ret;
129 SQLCHAR s1[ 100 + LOG_MESSAGE_LEN ];
130
131 /*
132 * check statement
133 */
134
135 if ( !__validate_stmt( statement ))
136 {
137 dm_log_write( __FILE__,
138 __LINE__,
139 LOG_INFO,
140 LOG_INFO,
141 "Error: SQL_INVALID_HANDLE" );
142
143 return SQL_INVALID_HANDLE;
144 }
145
146 function_entry( statement );
147
148 if ( log_info.log_flag )
149 {
150 sprintf( statement -> msg, "\n\t\tEntry:\
151\n\t\t\tStatement = %p\
152\n\t\t\tFetch Orentation = %d\
153\n\t\t\tFetch Offset = %d",
154 statement,
155 fetch_orientation,
156 (int)fetch_offset );
157
158 dm_log_write( __FILE__,
159 __LINE__,
160 LOG_INFO,
161 LOG_INFO,
162 statement -> msg );
163 }
164
165 thread_protect( SQL_HANDLE_STMT, statement );
166
167 if ( fetch_orientation != SQL_FETCH_NEXT &&
168 fetch_orientation != SQL_FETCH_PRIOR &&
169 fetch_orientation != SQL_FETCH_FIRST &&
170 fetch_orientation != SQL_FETCH_LAST &&
171 fetch_orientation != SQL_FETCH_ABSOLUTE &&
172 fetch_orientation != SQL_FETCH_RELATIVE &&
173 fetch_orientation != SQL_FETCH_BOOKMARK ||
174 (fetch_orientation == SQL_FETCH_BOOKMARK
175 && statement -> bookmarks_on == SQL_UB_OFF) )
176 {
177 dm_log_write( __FILE__,
178 __LINE__,
179 LOG_INFO,
180 LOG_INFO,
181 "Error: HY106" );
182
183 __post_internal_error( &statement -> error,
184 ERROR_HY106, NULL,
185 statement -> connection -> environment -> requested_version );
186
187 return function_return_nodrv( SQL_HANDLE_STMT, statement, SQL_ERROR );
188 }
189
190 /*
191 * check states
192 */
193
194 if ( statement -> state == STATE_S1 ||
195 statement -> state == STATE_S2 ||
196 statement -> state == STATE_S3 )
197 {
198 dm_log_write( __FILE__,
199 __LINE__,
200 LOG_INFO,
201 LOG_INFO,
202 "Error: HY010" );
203
204 __post_internal_error( &statement -> error,
205 ERROR_HY010, NULL,
206 statement -> connection -> environment -> requested_version );
207
208 return function_return_nodrv( SQL_HANDLE_STMT, statement, SQL_ERROR );
209 }
210
211 if ( statement -> state == STATE_S4 )
212 {
213 dm_log_write( __FILE__,
214 __LINE__,
215 LOG_INFO,
216 LOG_INFO,
217 "Error: 24000" );
218
219 __post_internal_error( &statement -> error,
220 ERROR_24000, NULL,
221 statement -> connection -> environment -> requested_version );
222
223 return function_return_nodrv( SQL_HANDLE_STMT, statement, SQL_ERROR );
224 }
225
226 if ( statement -> state == STATE_S7 )
227 {
228 dm_log_write( __FILE__,
229 __LINE__,
230 LOG_INFO,
231 LOG_INFO,
232 "Error: HY010" );
233
234 __post_internal_error( &statement -> error,
235 ERROR_HY010, NULL,
236 statement -> connection -> environment -> requested_version );
237
238 return function_return_nodrv( SQL_HANDLE_STMT, statement, SQL_ERROR );
239 }
240
241 if ( statement -> state == STATE_S8 ||
242 statement -> state == STATE_S9 ||
243 statement -> state == STATE_S10 ||
244 statement -> state == STATE_S13 ||
245 statement -> state == STATE_S14 ||
246 statement -> state == STATE_S15 )
247 {
248 dm_log_write( __FILE__,
249 __LINE__,
250 LOG_INFO,
251 LOG_INFO,
252 "Error: HY010" );
253
254 __post_internal_error( &statement -> error,
255 ERROR_HY010, NULL,
256 statement -> connection -> environment -> requested_version );
257
258 return function_return_nodrv( SQL_HANDLE_STMT, statement, SQL_ERROR );
259 }
260
261 if ( statement -> state == STATE_S11 ||
262 statement -> state == STATE_S12 )
263 {
264 if ( statement -> interupted_func != SQL_API_SQLFETCHSCROLL )
265 {
266 dm_log_write( __FILE__,
267 __LINE__,
268 LOG_INFO,
269 LOG_INFO,
270 "Error: HY010" );
271
272 __post_internal_error( &statement -> error,
273 ERROR_HY010, NULL,
274 statement -> connection -> environment -> requested_version );
275
276 return function_return_nodrv( SQL_HANDLE_STMT, statement, SQL_ERROR );
277 }
278 }
279
280 if ( CHECK_SQLFETCHSCROLL( statement -> connection ))
281 {
282 ret = SQLFETCHSCROLL( statement -> connection,
283 statement -> driver_stmt,
284 fetch_orientation,
285 fetch_offset );
286 }
287 else if ( statement -> connection -> driver_act_ver == SQL_OV_ODBC2 &&
288 CHECK_SQLEXTENDEDFETCH( statement -> connection ))
289 {
290 /*
291 * map to ODBC 2 call
292 */
293 SQLINTEGER bm_ptr = 0;
294
295 if ( fetch_orientation == SQL_FETCH_BOOKMARK )
296 {
297 if ( statement -> fetch_bm_ptr )
298 bm_ptr = *statement -> fetch_bm_ptr;
299
300 ret = SQLEXTENDEDFETCH( statement -> connection,
301 statement -> driver_stmt,
302 fetch_orientation,
303 bm_ptr,
304 statement -> row_ct_ptr,
305 statement -> row_st_arr );
306 }
307 else
308 {
309 ret = SQLEXTENDEDFETCH( statement -> connection,
310 statement -> driver_stmt,
311 fetch_orientation,
312 fetch_offset,
313 statement -> row_ct_ptr,
314 statement -> row_st_arr );
315 }
316 }
317 else
318 {
319 dm_log_write( __FILE__,
320 __LINE__,
321 LOG_INFO,
322 LOG_INFO,
323 "Error: IM001" );
324
325 __post_internal_error( &statement -> error,
326 ERROR_IM001, NULL,
327 statement -> connection -> environment -> requested_version );
328
329 return function_return_nodrv( SQL_HANDLE_STMT, statement, SQL_ERROR );
330 }
331
332 if ( ret == SQL_STILL_EXECUTING )
333 {
334 statement -> interupted_func = SQL_API_SQLFETCHSCROLL;
335 if ( statement -> state != STATE_S11 &&
336 statement -> state != STATE_S12 )
337 statement -> state = STATE_S11;
338 }
339 else if ( SQL_SUCCEEDED( ret ))
340 {
341 statement -> eod = 0;
342 statement -> state = STATE_S6;
343 }
344 else if ( ret == SQL_NO_DATA ) {
345 statement -> eod = 1;
346 statement -> state = STATE_S6;
347 }
348
349 if ( log_info.log_flag )
350 {
351 sprintf( statement -> msg,
352 "\n\t\tExit:[%s]",
353 __get_return_status( ret, s1 ));
354
355 dm_log_write( __FILE__,
356 __LINE__,
357 LOG_INFO,
358 LOG_INFO,
359 statement -> msg );
360 }
361
362 return function_return( SQL_HANDLE_STMT, statement, ret );
363}
364