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: SQLSetScrollOptions.c,v 1.9 2009/02/18 17:59:08 lurcher Exp $
31 *
32 * $Log: SQLSetScrollOptions.c,v $
33 * Revision 1.9 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.8 2007/01/02 10:27:50 lurcher
37 * Fix descriptor leak with unicode only driver
38 *
39 * Revision 1.7 2005/11/23 08:29:16 lurcher
40 * Add cleanup in postgres driver
41 *
42 * Revision 1.6 2003/10/30 18:20:46 lurcher
43 *
44 * Fix broken thread protection
45 * Remove SQLNumResultCols after execute, lease S4/S% to driver
46 * Fix string overrun in SQLDriverConnect
47 * Add initial support for Interix
48 *
49 * Revision 1.5 2002/12/05 17:44:31 lurcher
50 *
51 * Display unknown return values in return logging
52 *
53 * Revision 1.4 2002/01/15 10:31:34 lurcher
54 *
55 * Fix invalid diag message
56 *
57 * Revision 1.3 2001/12/13 13:00:32 lurcher
58 *
59 * Remove most if not all warnings on 64 bit platforms
60 * Add support for new MS 3.52 64 bit changes
61 * Add override to disable the stopping of tracing
62 * Add MAX_ROWS support in postgres driver
63 *
64 * Revision 1.2 2001/12/04 10:16:59 lurcher
65 *
66 * Fix SQLSetScrollOption problem
67 *
68 * Revision 1.1.1.1 2001/10/17 16:40:07 lurcher
69 *
70 * First upload to SourceForge
71 *
72 * Revision 1.2 2001/04/12 17:43:36 nick
73 *
74 * Change logging and added autotest to odbctest
75 *
76 * Revision 1.1.1.1 2000/09/04 16:42:52 nick
77 * Imported Sources
78 *
79 * Revision 1.7 1999/11/13 23:41:01 ngorham
80 *
81 * Alter the way DM logging works
82 * Upgrade the Postgres driver to 6.4.6
83 *
84 * Revision 1.6 1999/10/24 23:54:19 ngorham
85 *
86 * First part of the changes to the error reporting
87 *
88 * Revision 1.5 1999/09/21 22:34:26 ngorham
89 *
90 * Improve performance by removing unneeded logging calls when logging is
91 * disabled
92 *
93 * Revision 1.4 1999/07/10 21:10:17 ngorham
94 *
95 * Adjust error sqlstate from driver manager, depending on requested
96 * version (ODBC2/3)
97 *
98 * Revision 1.3 1999/07/04 21:05:08 ngorham
99 *
100 * Add LGPL Headers to code
101 *
102 * Revision 1.2 1999/06/30 23:56:55 ngorham
103 *
104 * Add initial thread safety code
105 *
106 * Revision 1.1.1.1 1999/05/29 13:41:08 sShandyb
107 * first go at it
108 *
109 * Revision 1.5 1999/06/03 22:20:25 ngorham
110 *
111 * Finished off the ODBC3-2 mapping
112 *
113 * Revision 1.4 1999/06/02 23:48:45 ngorham
114 *
115 * Added more 3-2 mapping
116 *
117 * Revision 1.3 1999/06/02 20:12:10 ngorham
118 *
119 * Fixed botched log entry, and removed the dos \r from the sql header files.
120 *
121 * Revision 1.2 1999/06/02 19:57:21 ngorham
122 *
123 * Added code to check if a attempt is being made to compile with a C++
124 * Compiler, and issue a message.
125 * Start work on the ODBC2-3 conversions.
126 *
127 * Revision 1.1.1.1 1999/05/27 18:23:18 pharvey
128 * Imported sources
129 *
130 * Revision 1.2 1999/05/09 23:27:11 nick
131 * All the API done now
132 *
133 * Revision 1.1 1999/04/25 23:06:11 nick
134 * Initial revision
135 *
136 *
137 **********************************************************************/
138
139#include <config.h>
140#include "drivermanager.h"
141
142static char const rcsid[]= "$RCSfile: SQLSetScrollOptions.c,v $ $Revision: 1.9 $";
143
144SQLRETURN SQLSetScrollOptions(
145 SQLHSTMT statement_handle,
146 SQLUSMALLINT f_concurrency,
147 SQLLEN crow_keyset,
148 SQLUSMALLINT crow_rowset )
149{
150 DMHSTMT statement = (DMHSTMT) statement_handle;
151 SQLRETURN ret;
152 SQLCHAR s1[ 100 + LOG_MESSAGE_LEN ];
153
154 /*
155 * check statement
156 */
157
158 if ( !__validate_stmt( statement ))
159 {
160 dm_log_write( __FILE__,
161 __LINE__,
162 LOG_INFO,
163 LOG_INFO,
164 "Error: SQL_INVALID_HANDLE" );
165
166 return SQL_INVALID_HANDLE;
167 }
168
169 function_entry( statement );
170
171 if ( log_info.log_flag )
172 {
173 sprintf( statement -> msg, "\n\t\tEntry:\
174\n\t\t\tStatement = %p\
175\n\t\t\tConcurrency = %d\
176\n\t\t\tKeyset = %d\
177\n\t\t\tRowset = %d",
178 statement,
179 f_concurrency,
180 (int)crow_keyset,
181 crow_rowset );
182
183 dm_log_write( __FILE__,
184 __LINE__,
185 LOG_INFO,
186 LOG_INFO,
187 statement -> msg );
188 }
189
190 thread_protect( SQL_HANDLE_STMT, statement );
191
192 /*
193 * check states
194 */
195
196 if ( statement -> state != STATE_S1 )
197 {
198 dm_log_write( __FILE__,
199 __LINE__,
200 LOG_INFO,
201 LOG_INFO,
202 "Error: S1010" );
203
204 __post_internal_error( &statement -> error,
205 ERROR_S1010, NULL,
206 statement -> connection -> environment -> requested_version );
207
208 return function_return_nodrv( SQL_HANDLE_STMT, statement, SQL_ERROR );
209 }
210
211 if ( crow_keyset != SQL_SCROLL_FORWARD_ONLY &&
212 crow_keyset != SQL_SCROLL_STATIC &&
213 crow_keyset != SQL_SCROLL_KEYSET_DRIVEN &&
214 crow_keyset != SQL_SCROLL_DYNAMIC ||
215 !crow_rowset)
216 {
217 dm_log_write( __FILE__,
218 __LINE__,
219 LOG_INFO,
220 LOG_INFO,
221 "Error: S1107" );
222
223 __post_internal_error( &statement -> error,
224 ERROR_S1107, NULL,
225 statement -> connection -> environment -> requested_version );
226
227 return function_return_nodrv( SQL_HANDLE_STMT, statement, SQL_ERROR );
228 }
229
230 if ( f_concurrency != SQL_CONCUR_READ_ONLY &&
231 f_concurrency != SQL_CONCUR_LOCK &&
232 f_concurrency != SQL_CONCUR_ROWVER &&
233 f_concurrency != SQL_CONCUR_VALUES )
234 {
235 dm_log_write( __FILE__,
236 __LINE__,
237 LOG_INFO,
238 LOG_INFO,
239 "Error: S1108" );
240
241 __post_internal_error( &statement -> error,
242 ERROR_S1108, NULL,
243 statement -> connection -> environment -> requested_version );
244
245 return function_return_nodrv( SQL_HANDLE_STMT, statement, SQL_ERROR );
246 }
247
248 if ( CHECK_SQLSETSCROLLOPTIONS( statement -> connection ))
249 {
250 ret = SQLSETSCROLLOPTIONS( statement -> connection,
251 statement -> driver_stmt,
252 f_concurrency,
253 crow_keyset,
254 crow_rowset );
255 }
256 else if ( statement -> connection -> driver_act_ver >= SQL_OV_ODBC3 &&
257 (CHECK_SQLGETINFO( statement -> connection ) ||
258 CHECK_SQLGETINFOW( statement -> connection )) &&
259 (CHECK_SQLSETSTMTATTR( statement -> connection ) ||
260 CHECK_SQLSETSTMTATTRW( statement -> connection )))
261 {
262 SQLINTEGER info_type, ivp;
263
264 switch( crow_keyset )
265 {
266 case SQL_SCROLL_FORWARD_ONLY:
267 info_type = SQL_FORWARD_ONLY_CURSOR_ATTRIBUTES2;
268 break;
269
270 case SQL_SCROLL_STATIC:
271 info_type = SQL_STATIC_CURSOR_ATTRIBUTES2;
272 break;
273
274 case SQL_SCROLL_KEYSET_DRIVEN:
275 info_type = SQL_KEYSET_CURSOR_ATTRIBUTES2;
276 break;
277
278 case SQL_SCROLL_DYNAMIC:
279 info_type = SQL_DYNAMIC_CURSOR_ATTRIBUTES2;
280 break;
281
282 default:
283 if ( crow_keyset > crow_rowset )
284 {
285 info_type = SQL_KEYSET_CURSOR_ATTRIBUTES2;
286 }
287 else
288 {
289 dm_log_write( __FILE__,
290 __LINE__,
291 LOG_INFO,
292 LOG_INFO,
293 "Error: S1107" );
294
295 __post_internal_error( &statement -> error,
296 ERROR_S1107, NULL,
297 statement -> connection -> environment -> requested_version );
298
299 return function_return_nodrv( SQL_HANDLE_STMT, statement, SQL_ERROR );
300 }
301 break;
302 }
303
304 ret = __SQLGetInfo( statement -> connection,
305 info_type,
306 &ivp,
307 sizeof( ivp ),
308 0 );
309
310 if( !SQL_SUCCEEDED( ret ))
311 {
312 dm_log_write( __FILE__,
313 __LINE__,
314 LOG_INFO,
315 LOG_INFO,
316 "Error: SQLGetInfo fails" );
317
318 return function_return( SQL_HANDLE_STMT, statement, SQL_ERROR );
319 }
320
321 if ( f_concurrency == SQL_CONCUR_READ_ONLY &&
322 !( ivp & SQL_CA2_READ_ONLY_CONCURRENCY ))
323 {
324 dm_log_write( __FILE__,
325 __LINE__,
326 LOG_INFO,
327 LOG_INFO,
328 "Error: S1C00" );
329
330 __post_internal_error( &statement -> error,
331 ERROR_S1C00, NULL,
332 statement -> connection -> environment -> requested_version );
333
334 return function_return( SQL_HANDLE_STMT, statement, SQL_ERROR );
335 }
336 else if ( f_concurrency == SQL_CONCUR_LOCK &&
337 !( ivp & SQL_CA2_LOCK_CONCURRENCY ))
338 {
339 dm_log_write( __FILE__,
340 __LINE__,
341 LOG_INFO,
342 LOG_INFO,
343 "Error: S1C00" );
344
345 __post_internal_error( &statement -> error,
346 ERROR_S1C00, NULL,
347 statement -> connection -> environment -> requested_version );
348
349 return function_return( SQL_HANDLE_STMT, statement, SQL_ERROR );
350 }
351 else if ( f_concurrency == SQL_CONCUR_ROWVER &&
352 !( ivp & SQL_CA2_OPT_ROWVER_CONCURRENCY ))
353 {
354 dm_log_write( __FILE__,
355 __LINE__,
356 LOG_INFO,
357 LOG_INFO,
358 "Error: S1C00" );
359
360 __post_internal_error( &statement -> error,
361 ERROR_S1C00, NULL,
362 statement -> connection -> environment -> requested_version );
363
364 return function_return( SQL_HANDLE_STMT, statement, SQL_ERROR );
365 }
366 if ( f_concurrency == SQL_CONCUR_VALUES &&
367 !( ivp & SQL_CA2_OPT_VALUES_CONCURRENCY ))
368 {
369 dm_log_write( __FILE__,
370 __LINE__,
371 LOG_INFO,
372 LOG_INFO,
373 "Error: S1C00" );
374
375 __post_internal_error( &statement -> error,
376 ERROR_S1C00, NULL,
377 statement -> connection -> environment -> requested_version );
378
379 return function_return( SQL_HANDLE_STMT, statement, SQL_ERROR );
380 }
381 if ( f_concurrency != SQL_CONCUR_READ_ONLY &&
382 f_concurrency != SQL_CONCUR_LOCK &&
383 f_concurrency != SQL_CONCUR_ROWVER &&
384 f_concurrency != SQL_CONCUR_VALUES )
385 {
386 dm_log_write( __FILE__,
387 __LINE__,
388 LOG_INFO,
389 LOG_INFO,
390 "Error: S1108" );
391
392 __post_internal_error( &statement -> error,
393 ERROR_S1108, NULL,
394 statement -> connection -> environment -> requested_version );
395
396 return function_return( SQL_HANDLE_STMT, statement, SQL_ERROR );
397 }
398
399 if(CHECK_SQLSETSTMTATTR( statement -> connection ))
400 {
401 ret = SQLSETSTMTATTR( statement -> connection,
402 statement -> driver_stmt,
403 SQL_ATTR_CONCURRENCY,
404 f_concurrency,
405 0 );
406 }
407 else if ( CHECK_SQLSETSTMTATTRW( statement -> connection ))
408 {
409 ret = SQLSETSTMTATTRW( statement -> connection,
410 statement -> driver_stmt,
411 SQL_ATTR_CONCURRENCY,
412 f_concurrency,
413 0 );
414 }
415
416 if ( !SQL_SUCCEEDED( ret ))
417 {
418 dm_log_write( __FILE__,
419 __LINE__,
420 LOG_INFO,
421 LOG_INFO,
422 "Error: SQLSetStmtAttr fails" );
423
424 return function_return( SQL_HANDLE_STMT, statement, SQL_ERROR );
425 }
426
427
428 switch( crow_keyset )
429 {
430 case SQL_SCROLL_FORWARD_ONLY:
431 info_type = SQL_CURSOR_FORWARD_ONLY;
432 break;
433
434 case SQL_SCROLL_STATIC:
435 info_type = SQL_CURSOR_STATIC;
436 break;
437
438 case SQL_SCROLL_KEYSET_DRIVEN:
439 info_type = SQL_CURSOR_KEYSET_DRIVEN;
440 break;
441
442 case SQL_SCROLL_DYNAMIC:
443 info_type = SQL_CURSOR_DYNAMIC;
444 break;
445
446 default:
447 if ( crow_keyset > crow_rowset )
448 {
449 info_type = SQL_CURSOR_KEYSET_DRIVEN;
450 }
451 else
452 {
453 dm_log_write( __FILE__,
454 __LINE__,
455 LOG_INFO,
456 LOG_INFO,
457 "Error: S1107" );
458
459 __post_internal_error( &statement -> error,
460 ERROR_S1107, NULL,
461 statement -> connection -> environment -> requested_version );
462
463 return function_return( SQL_HANDLE_STMT, statement, SQL_ERROR );
464 }
465 break;
466 }
467
468 if(CHECK_SQLSETSTMTATTR( statement -> connection ))
469 {
470 ret = SQLSETSTMTATTR( statement -> connection,
471 statement -> driver_stmt,
472 SQL_ATTR_CURSOR_TYPE,
473 info_type,
474 0 );
475 }
476 else if(CHECK_SQLSETSTMTATTRW( statement -> connection ))
477 {
478 ret = SQLSETSTMTATTRW( statement -> connection,
479 statement -> driver_stmt,
480 SQL_ATTR_CURSOR_TYPE,
481 info_type,
482 0 );
483 }
484
485 if ( !SQL_SUCCEEDED( ret ))
486 {
487 dm_log_write( __FILE__,
488 __LINE__,
489 LOG_INFO,
490 LOG_INFO,
491 "Error: SQLSetStmtAttr fails" );
492
493 return function_return( SQL_HANDLE_STMT, statement, SQL_ERROR );
494 }
495
496 if ( crow_keyset > 0 )
497 {
498 if(CHECK_SQLSETSTMTATTR( statement -> connection ))
499 {
500 ret = SQLSETSTMTATTR( statement -> connection,
501 statement -> driver_stmt,
502 SQL_ATTR_KEYSET_SIZE,
503 crow_keyset,
504 0 );
505 }
506 else if(CHECK_SQLSETSTMTATTRW( statement -> connection ))
507 {
508 ret = SQLSETSTMTATTRW( statement -> connection,
509 statement -> driver_stmt,
510 SQL_ATTR_KEYSET_SIZE,
511 crow_keyset,
512 0 );
513 }
514
515 if ( !SQL_SUCCEEDED( ret ))
516 {
517 dm_log_write( __FILE__,
518 __LINE__,
519 LOG_INFO,
520 LOG_INFO,
521 "Error: SQLSetStmtAttr fails" );
522
523 return function_return( SQL_HANDLE_STMT, statement, SQL_ERROR );
524 }
525 }
526 if(CHECK_SQLSETSTMTATTR( statement -> connection ))
527 {
528 ret = SQLSETSTMTATTR( statement -> connection,
529 statement -> driver_stmt,
530 SQL_ROWSET_SIZE,
531 crow_rowset,
532 0 );
533 }
534 else if(CHECK_SQLSETSTMTATTRW( statement -> connection ))
535 {
536 ret = SQLSETSTMTATTRW( statement -> connection,
537 statement -> driver_stmt,
538 SQL_ROWSET_SIZE,
539 crow_rowset,
540 0 );
541 }
542 }
543 else
544 {
545 dm_log_write( __FILE__,
546 __LINE__,
547 LOG_INFO,
548 LOG_INFO,
549 "Error: IM001" );
550
551 __post_internal_error( &statement -> error,
552 ERROR_IM001, NULL,
553 statement -> connection -> environment -> requested_version );
554
555 return function_return_nodrv( SQL_HANDLE_STMT, statement, SQL_ERROR );
556 }
557
558 if ( log_info.log_flag )
559 {
560 sprintf( statement -> msg,
561 "\n\t\tExit:[%s]",
562 __get_return_status( ret, s1 ));
563
564 dm_log_write( __FILE__,
565 __LINE__,
566 LOG_INFO,
567 LOG_INFO,
568 statement -> msg );
569 }
570
571 return function_return( SQL_HANDLE_STMT, statement, ret );
572}
573