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: SQLGetStmtAttr.c,v 1.8 2009/02/18 17:59:08 lurcher Exp $
31 *
32 * $Log: SQLGetStmtAttr.c,v $
33 * Revision 1.8 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.7 2009/02/17 09:47:44 lurcher
37 * Clear up a number of bugs
38 *
39 * Revision 1.6 2009/02/04 09:30:02 lurcher
40 * Fix some SQLINTEGER/SQLLEN conflicts
41 *
42 * Revision 1.5 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.4 2003/02/27 12:19:39 lurcher
50 *
51 * Add the A functions as well as the W
52 *
53 * Revision 1.3 2002/12/05 17:44:31 lurcher
54 *
55 * Display unknown return values in return logging
56 *
57 * Revision 1.2 2002/07/16 13:08:18 lurcher
58 *
59 * Filter attribute values from SQLSetStmtAttr to SQLSetStmtOption to fit
60 * within ODBC 2
61 * Make DSN's double clickable in ODBCConfig
62 *
63 * Revision 1.1.1.1 2001/10/17 16:40:05 lurcher
64 *
65 * First upload to SourceForge
66 *
67 * Revision 1.5 2001/07/03 09:30:41 nick
68 *
69 * Add ability to alter size of displayed message in the log
70 *
71 * Revision 1.4 2001/04/18 15:03:37 nick
72 *
73 * Fix problem when going to DB2 unicode driver
74 *
75 * Revision 1.3 2001/04/12 17:43:36 nick
76 *
77 * Change logging and added autotest to odbctest
78 *
79 * Revision 1.2 2000/12/31 20:30:54 nick
80 *
81 * Add UNICODE support
82 *
83 * Revision 1.1.1.1 2000/09/04 16:42:52 nick
84 * Imported Sources
85 *
86 * Revision 1.11 2000/06/24 18:45:09 ngorham
87 *
88 * Fix for SQLExtendedFetch on big endian platforms. the row count pointer
89 * was declared as a small not a int.
90 *
91 * Revision 1.10 2000/02/06 23:26:10 ngorham
92 *
93 * Fix bug with missing '&' with SQLGetStmtAttr
94 *
95 * Revision 1.9 1999/11/13 23:40:59 ngorham
96 *
97 * Alter the way DM logging works
98 * Upgrade the Postgres driver to 6.4.6
99 *
100 * Revision 1.8 1999/10/29 21:07:40 ngorham
101 *
102 * Fix some stupid bugs in the DM
103 * Make the postgres driver work via unix sockets
104 *
105 * Revision 1.7 1999/10/24 23:54:18 ngorham
106 *
107 * First part of the changes to the error reporting
108 *
109 * Revision 1.6 1999/09/21 22:34:25 ngorham
110 *
111 * Improve performance by removing unneeded logging calls when logging is
112 * disabled
113 *
114 * Revision 1.5 1999/07/10 21:10:16 ngorham
115 *
116 * Adjust error sqlstate from driver manager, depending on requested
117 * version (ODBC2/3)
118 *
119 * Revision 1.4 1999/07/04 21:05:07 ngorham
120 *
121 * Add LGPL Headers to code
122 *
123 * Revision 1.3 1999/06/30 23:56:55 ngorham
124 *
125 * Add initial thread safety code
126 *
127 * Revision 1.2 1999/06/19 17:51:40 ngorham
128 *
129 * Applied assorted minor bug fixes
130 *
131 * Revision 1.1.1.1 1999/05/29 13:41:07 sShandyb
132 * first go at it
133 *
134 * Revision 1.4 1999/06/02 23:48:45 ngorham
135 *
136 * Added more 3-2 mapping
137 *
138 * Revision 1.3 1999/06/02 20:12:10 ngorham
139 *
140 * Fixed botched log entry, and removed the dos \r from the sql header files.
141 *
142 * Revision 1.2 1999/06/02 19:57:20 ngorham
143 *
144 * Added code to check if a attempt is being made to compile with a C++
145 * Compiler, and issue a message.
146 * Start work on the ODBC2-3 conversions.
147 *
148 * Revision 1.1.1.1 1999/05/27 18:23:18 pharvey
149 * Imported sources
150 *
151 * Revision 1.3 1999/05/09 23:27:11 nick
152 * All the API done now
153 *
154 * Revision 1.2 1999/05/03 19:50:43 nick
155 * Another check point
156 *
157 * Revision 1.1 1999/04/25 23:06:11 nick
158 * Initial revision
159 *
160 *
161 **********************************************************************/
162
163#include <config.h>
164#include "drivermanager.h"
165
166static char const rcsid[]= "$RCSfile: SQLGetStmtAttr.c,v $ $Revision: 1.8 $";
167
168SQLRETURN SQLGetStmtAttrA( SQLHSTMT statement_handle,
169 SQLINTEGER attribute,
170 SQLPOINTER value,
171 SQLINTEGER buffer_length,
172 SQLINTEGER *string_length )
173{
174 return SQLGetStmtAttr( statement_handle,
175 attribute,
176 value,
177 buffer_length,
178 string_length );
179}
180
181SQLRETURN SQLGetStmtAttr( SQLHSTMT statement_handle,
182 SQLINTEGER attribute,
183 SQLPOINTER value,
184 SQLINTEGER buffer_length,
185 SQLINTEGER *string_length )
186{
187 DMHSTMT statement = (DMHSTMT) statement_handle;
188 SQLRETURN ret;
189 SQLCHAR s1[ 100 + LOG_MESSAGE_LEN ];
190
191 /*
192 * check statement
193 */
194
195 if ( !__validate_stmt( statement ))
196 {
197 dm_log_write( __FILE__,
198 __LINE__,
199 LOG_INFO,
200 LOG_INFO,
201 "Error: SQL_INVALID_HANDLE" );
202
203 return SQL_INVALID_HANDLE;
204 }
205
206 function_entry( statement );
207
208 if ( log_info.log_flag )
209 {
210 sprintf( statement -> msg, "\n\t\tEntry:\
211\n\t\t\tStatement = %p\
212\n\t\t\tAttribute = %s\
213\n\t\t\tValue = %p\
214\n\t\t\tBuffer Length = %d\
215\n\t\t\tStrLen = %p",
216 statement,
217 __stmt_attr_as_string( s1, attribute ),
218 value,
219 (int)buffer_length,
220 (void*)string_length );
221
222 dm_log_write( __FILE__,
223 __LINE__,
224 LOG_INFO,
225 LOG_INFO,
226 statement -> msg );
227 }
228
229 thread_protect( SQL_HANDLE_STMT, statement );
230
231 /*
232 * check states
233 */
234
235 if ( attribute == SQL_ATTR_ROW_NUMBER || attribute == SQL_GET_BOOKMARK )
236 {
237 if ( statement -> state == STATE_S1 ||
238 statement -> state == STATE_S2 ||
239 statement -> state == STATE_S3 ||
240 statement -> state == STATE_S4 ||
241 statement -> state == STATE_S5 ||
242 ( statement -> state == STATE_S6 ||
243 statement -> state == STATE_S7 ) && statement -> eod )
244 {
245 dm_log_write( __FILE__,
246 __LINE__,
247 LOG_INFO,
248 LOG_INFO,
249 "Error: 24000" );
250
251 __post_internal_error( &statement -> error,
252 ERROR_24000, NULL,
253 statement -> connection -> environment -> requested_version );
254
255 return function_return_nodrv( SQL_HANDLE_STMT, statement, SQL_ERROR );
256 }
257 }
258
259 if ( statement -> state == STATE_S8 ||
260 statement -> state == STATE_S9 ||
261 statement -> state == STATE_S10 ||
262 statement -> state == STATE_S11 ||
263 statement -> state == STATE_S12 ||
264 statement -> state == STATE_S13 ||
265 statement -> state == STATE_S14 ||
266 statement -> state == STATE_S15 )
267 {
268 dm_log_write( __FILE__,
269 __LINE__,
270 LOG_INFO,
271 LOG_INFO,
272 "Error: HY010" );
273
274 __post_internal_error( &statement -> error,
275 ERROR_HY010, NULL,
276 statement -> connection -> environment -> requested_version );
277
278 return function_return_nodrv( SQL_HANDLE_STMT, statement, SQL_ERROR );
279 }
280
281 /*
282 * states S5 - S7 are handled by the driver
283 */
284
285 if ( statement -> connection -> unicode_driver )
286 {
287 if ( !CHECK_SQLGETSTMTATTRW( statement -> connection ) &&
288 !CHECK_SQLGETSTMTOPTIONW( statement -> connection ) &&
289 !CHECK_SQLGETSTMTATTR( statement -> connection ) &&
290 !CHECK_SQLGETSTMTOPTION( statement -> connection ))
291 {
292 dm_log_write( __FILE__,
293 __LINE__,
294 LOG_INFO,
295 LOG_INFO,
296 "Error: IM001" );
297
298 __post_internal_error( &statement -> error,
299 ERROR_IM001, NULL,
300 statement -> connection -> environment -> requested_version );
301
302 return function_return_nodrv( SQL_HANDLE_STMT, statement, SQL_ERROR );
303 }
304 }
305 else
306 {
307 if ( !CHECK_SQLGETSTMTATTR( statement -> connection ) &&
308 !CHECK_SQLGETSTMTOPTION( statement -> connection ))
309 {
310 dm_log_write( __FILE__,
311 __LINE__,
312 LOG_INFO,
313 LOG_INFO,
314 "Error: IM001" );
315
316 __post_internal_error( &statement -> error,
317 ERROR_IM001, NULL,
318 statement -> connection -> environment -> requested_version );
319
320 return function_return_nodrv( SQL_HANDLE_STMT, statement, SQL_ERROR );
321 }
322 }
323
324 /*
325 * map descriptors to our copies
326 */
327
328 if ( attribute == SQL_ATTR_APP_ROW_DESC )
329 {
330 if ( value )
331 memcpy( value, &statement -> ard, sizeof( statement -> ard ));
332
333 ret = SQL_SUCCESS;
334 }
335 else if ( attribute == SQL_ATTR_APP_PARAM_DESC )
336 {
337 if ( value )
338 memcpy( value, &statement -> apd, sizeof( SQLHANDLE ));
339
340 ret = SQL_SUCCESS;
341 }
342 else if ( attribute == SQL_ATTR_IMP_ROW_DESC )
343 {
344 if ( value )
345 memcpy( value, &statement -> ird, sizeof( SQLHANDLE ));
346
347 ret = SQL_SUCCESS;
348 }
349 else if ( attribute == SQL_ATTR_IMP_PARAM_DESC )
350 {
351 if ( value )
352 memcpy( value, &statement -> ipd, sizeof( SQLHANDLE ));
353
354 ret = SQL_SUCCESS;
355 }
356
357 /*
358 * does the call need mapping from 3 to 2
359 */
360
361 else if ( attribute == SQL_ATTR_FETCH_BOOKMARK_PTR &&
362 statement -> connection -> driver_act_ver == SQL_OV_ODBC2 &&
363 CHECK_SQLEXTENDEDFETCH( statement -> connection ))
364 {
365 if ( value )
366 memcpy( value, &statement -> fetch_bm_ptr, sizeof( SQLULEN * ));
367
368 ret = SQL_SUCCESS;
369 }
370 else if ( attribute == SQL_ATTR_ROW_STATUS_PTR &&
371 statement -> connection -> driver_act_ver == SQL_OV_ODBC2 &&
372 CHECK_SQLEXTENDEDFETCH( statement -> connection ))
373 {
374 if ( value )
375 memcpy( value, &statement -> row_st_arr, sizeof( SQLULEN * ));
376
377 ret = SQL_SUCCESS;
378 }
379 else if ( attribute == SQL_ATTR_ROWS_FETCHED_PTR &&
380 statement -> connection -> driver_act_ver == SQL_OV_ODBC2 &&
381 CHECK_SQLEXTENDEDFETCH( statement -> connection ))
382 {
383 if ( value )
384 memcpy( value, &statement -> row_ct_ptr, sizeof( SQLULEN * ));
385
386 ret = SQL_SUCCESS;
387 }
388 else if ( statement -> connection -> unicode_driver &&
389 attribute == SQL_ATTR_ROW_ARRAY_SIZE &&
390 statement -> connection -> driver_act_ver == SQL_OV_ODBC2 )
391 {
392 if ( CHECK_SQLGETSTMTATTRW( statement -> connection ))
393 {
394 ret = SQLGETSTMTATTRW( statement -> connection,
395 statement -> driver_stmt,
396 SQL_ROWSET_SIZE,
397 value,
398 buffer_length,
399 string_length );
400 }
401 else
402 {
403 ret = SQLGETSTMTATTR( statement -> connection,
404 statement -> driver_stmt,
405 SQL_ROWSET_SIZE,
406 value,
407 buffer_length,
408 string_length );
409 }
410 }
411 else if ( !statement -> connection -> unicode_driver &&
412 attribute == SQL_ATTR_ROW_ARRAY_SIZE &&
413 statement -> connection -> driver_act_ver == SQL_OV_ODBC2 &&
414 CHECK_SQLGETSTMTATTR( statement -> connection ))
415 {
416 ret = SQLGETSTMTATTR( statement -> connection,
417 statement -> driver_stmt,
418 SQL_ROWSET_SIZE,
419 value,
420 buffer_length,
421 string_length );
422 }
423 else if ( attribute == SQL_ATTR_ROW_ARRAY_SIZE &&
424 statement -> connection -> driver_act_ver == SQL_OV_ODBC2 )
425 {
426 if ( statement -> connection -> unicode_driver &&
427 CHECK_SQLGETSTMTOPTIONW( statement -> connection ))
428 {
429 ret = SQLGETSTMTOPTIONW( statement -> connection,
430 statement -> driver_stmt,
431 SQL_ROWSET_SIZE,
432 value );
433 }
434 else
435 {
436 ret = SQLGETSTMTOPTION( statement -> connection,
437 statement -> driver_stmt,
438 SQL_ROWSET_SIZE,
439 value );
440 }
441 }
442 else if ( statement -> connection -> unicode_driver &&
443 ( CHECK_SQLGETSTMTATTRW( statement -> connection ) ||
444 CHECK_SQLGETSTMTATTR( statement -> connection )))
445 {
446 if ( CHECK_SQLGETSTMTATTRW( statement -> connection ))
447 {
448 ret = SQLGETSTMTATTRW( statement -> connection,
449 statement -> driver_stmt,
450 attribute,
451 value,
452 buffer_length,
453 string_length );
454 }
455 else
456 {
457 ret = SQLGETSTMTATTR( statement -> connection,
458 statement -> driver_stmt,
459 attribute,
460 value,
461 buffer_length,
462 string_length );
463 }
464 }
465 else if ( !statement -> connection -> unicode_driver &&
466 CHECK_SQLGETSTMTATTR( statement -> connection ))
467 {
468 ret = SQLGETSTMTATTR( statement -> connection,
469 statement -> driver_stmt,
470 attribute,
471 value,
472 buffer_length,
473 string_length );
474 }
475 else if ( statement -> connection -> unicode_driver &&
476 CHECK_SQLGETSTMTOPTIONW( statement -> connection ))
477 {
478 /*
479 * Is it in the legal range of values
480 */
481
482 if ( attribute < SQL_STMT_DRIVER_MIN &&
483 ( attribute > SQL_ROW_NUMBER || attribute < SQL_QUERY_TIMEOUT ))
484 {
485 dm_log_write( __FILE__,
486 __LINE__,
487 LOG_INFO,
488 LOG_INFO,
489 "Error: HY092" );
490
491 __post_internal_error( &statement -> error,
492 ERROR_HY092, NULL,
493 statement -> connection -> environment -> requested_version );
494
495 return function_return_nodrv( SQL_HANDLE_STMT, statement, SQL_ERROR );
496 }
497
498 ret = SQLGETSTMTOPTIONW( statement -> connection,
499 statement -> driver_stmt,
500 attribute,
501 value );
502 }
503 else
504 {
505 /*
506 * Is it in the legal range of values
507 */
508
509 if ( attribute < SQL_STMT_DRIVER_MIN &&
510 ( attribute > SQL_ROW_NUMBER || attribute < SQL_QUERY_TIMEOUT ))
511 {
512 dm_log_write( __FILE__,
513 __LINE__,
514 LOG_INFO,
515 LOG_INFO,
516 "Error: HY092" );
517
518 __post_internal_error( &statement -> error,
519 ERROR_HY092, NULL,
520 statement -> connection -> environment -> requested_version );
521
522 return function_return_nodrv( SQL_HANDLE_STMT, statement, SQL_ERROR );
523 }
524
525 ret = SQLGETSTMTOPTION( statement -> connection,
526 statement -> driver_stmt,
527 attribute,
528 value );
529 }
530
531 if ( log_info.log_flag )
532 {
533 sprintf( statement -> msg,
534 "\n\t\tExit:[%s]",
535 __get_return_status( ret, s1 ));
536
537 dm_log_write( __FILE__,
538 __LINE__,
539 LOG_INFO,
540 LOG_INFO,
541 statement -> msg );
542 }
543
544 return function_return( SQL_HANDLE_STMT, statement, ret );
545}
546