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: SQLGetDescFieldW.c,v 1.9 2009/02/18 17:59:08 lurcher Exp $
31 *
32 * $Log: SQLGetDescFieldW.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 2008/08/29 08:01:39 lurcher
37 * Alter the way W functions are passed to the driver
38 *
39 * Revision 1.7 2007/02/28 15:37:48 lurcher
40 * deal with drivers that call internal W functions and end up in the driver manager. controlled by the --enable-handlemap configure arg
41 *
42 * Revision 1.6 2004/11/22 17:02:49 lurcher
43 * Fix unicode/ansi conversion in the SQLGet functions
44 *
45 * Revision 1.5 2003/10/30 18:20:46 lurcher
46 *
47 * Fix broken thread protection
48 * Remove SQLNumResultCols after execute, lease S4/S% to driver
49 * Fix string overrun in SQLDriverConnect
50 * Add initial support for Interix
51 *
52 * Revision 1.4 2002/12/05 17:44:30 lurcher
53 *
54 * Display unknown return values in return logging
55 *
56 * Revision 1.3 2002/08/23 09:42:37 lurcher
57 *
58 * Fix some build warnings with casts, and a AIX linker mod, to include
59 * deplib's on the link line, but not the libtool generated ones
60 *
61 * Revision 1.2 2002/07/24 08:49:52 lurcher
62 *
63 * Alter UNICODE support to use iconv for UNICODE-ANSI conversion
64 *
65 * Revision 1.1.1.1 2001/10/17 16:40:05 lurcher
66 *
67 * First upload to SourceForge
68 *
69 * Revision 1.4 2001/07/03 09:30:41 nick
70 *
71 * Add ability to alter size of displayed message in the log
72 *
73 * Revision 1.3 2001/04/17 16:29:39 nick
74 *
75 * More checks and autotest fixes
76 *
77 * Revision 1.2 2001/04/12 17:43:36 nick
78 *
79 * Change logging and added autotest to odbctest
80 *
81 * Revision 1.1 2000/12/31 20:30:54 nick
82 *
83 * Add UNICODE support
84 *
85 *
86 **********************************************************************/
87
88#include <config.h>
89#include "drivermanager.h"
90
91static char const rcsid[]= "$RCSfile: SQLGetDescFieldW.c,v $";
92
93SQLRETURN SQLGetDescFieldW( SQLHDESC descriptor_handle,
94 SQLSMALLINT rec_number,
95 SQLSMALLINT field_identifier,
96 SQLPOINTER value,
97 SQLINTEGER buffer_length,
98 SQLINTEGER *string_length )
99{
100 /*
101 * not quite sure how the descriptor can be
102 * allocated to a statement, all the documentation talks
103 * about state transitions on statement states, but the
104 * descriptor may be allocated with more than one statement
105 * at one time. Which one should I check ?
106 */
107 DMHDESC descriptor = (DMHDESC) descriptor_handle;
108 SQLRETURN ret;
109 SQLCHAR s1[ 100 + LOG_MESSAGE_LEN ];
110 int isStrField = 0;
111
112 /*
113 * check descriptor
114 */
115
116 if ( !__validate_desc( descriptor ))
117 {
118 dm_log_write( __FILE__,
119 __LINE__,
120 LOG_INFO,
121 LOG_INFO,
122 "Error: SQL_INVALID_HANDLE" );
123
124#ifdef WITH_HANDLE_REDIRECT
125 {
126 DMHDESC parent_desc;
127
128 parent_desc = find_parent_handle( descriptor, SQL_HANDLE_DESC );
129
130 if ( parent_desc ) {
131 dm_log_write( __FILE__,
132 __LINE__,
133 LOG_INFO,
134 LOG_INFO,
135 "Info: found parent handle" );
136
137 if ( CHECK_SQLGETDESCFIELDW( parent_desc -> connection ))
138 {
139 dm_log_write( __FILE__,
140 __LINE__,
141 LOG_INFO,
142 LOG_INFO,
143 "Info: calling redirected driver function" );
144
145 return SQLGETDESCFIELDW( parent_desc -> connection,
146 descriptor,
147 rec_number,
148 field_identifier,
149 value,
150 buffer_length,
151 string_length );
152 }
153 }
154 }
155#endif
156 return SQL_INVALID_HANDLE;
157 }
158
159 function_entry( descriptor );
160
161 if ( log_info.log_flag )
162 {
163 sprintf( descriptor -> msg, "\n\t\tEntry:\
164\n\t\t\tDescriptor = %p\
165\n\t\t\tRec Number = %d\
166\n\t\t\tField Attr = %s\
167\n\t\t\tValue = %p\
168\n\t\t\tBuffer Length = %d\
169\n\t\t\tStrLen = %p",
170 descriptor,
171 rec_number,
172 __desc_attr_as_string( s1, field_identifier ),
173 value,
174 (int)buffer_length,
175 (void*)string_length );
176
177 dm_log_write( __FILE__,
178 __LINE__,
179 LOG_INFO,
180 LOG_INFO,
181 descriptor -> msg );
182 }
183
184 thread_protect( SQL_HANDLE_DESC, descriptor );
185
186 if ( descriptor -> connection -> state < STATE_C4 )
187 {
188 dm_log_write( __FILE__,
189 __LINE__,
190 LOG_INFO,
191 LOG_INFO,
192 "Error: HY010" );
193
194 __post_internal_error( &descriptor -> error,
195 ERROR_HY010, NULL,
196 descriptor -> connection -> environment -> requested_version );
197
198 return function_return_nodrv( SQL_HANDLE_DESC, descriptor, SQL_ERROR );
199 }
200
201 /*
202 * check status of statements associated with this descriptor
203 */
204
205 if( __check_stmt_from_desc( descriptor, STATE_S8 ) ||
206 __check_stmt_from_desc( descriptor, STATE_S9 ) ||
207 __check_stmt_from_desc( descriptor, STATE_S10 ) ||
208 __check_stmt_from_desc( descriptor, STATE_S11 ) ||
209 __check_stmt_from_desc( descriptor, STATE_S12 ) ||
210 __check_stmt_from_desc( descriptor, STATE_S13 ) ||
211 __check_stmt_from_desc( descriptor, STATE_S14 ) ||
212 __check_stmt_from_desc( descriptor, STATE_S15 )) {
213
214 dm_log_write( __FILE__,
215 __LINE__,
216 LOG_INFO,
217 LOG_INFO,
218 "Error: HY010" );
219
220 __post_internal_error( &descriptor -> error,
221 ERROR_HY010, NULL,
222 descriptor -> connection -> environment -> requested_version );
223
224 return function_return_nodrv( SQL_HANDLE_DESC, descriptor, SQL_ERROR );
225 }
226
227 if( __check_stmt_from_desc_ird( descriptor, STATE_S1 )) {
228
229 dm_log_write( __FILE__,
230 __LINE__,
231 LOG_INFO,
232 LOG_INFO,
233 "Error: HY007" );
234
235 __post_internal_error( &descriptor -> error,
236 ERROR_HY007, NULL,
237 descriptor -> connection -> environment -> requested_version );
238
239 return function_return_nodrv( SQL_HANDLE_DESC, descriptor, SQL_ERROR );
240 }
241
242 if ( rec_number < 0 )
243 {
244 __post_internal_error( &descriptor -> error,
245 ERROR_07009, NULL,
246 descriptor -> connection -> environment -> requested_version );
247
248 return function_return_nodrv( SQL_HANDLE_DESC, descriptor, SQL_ERROR );
249 }
250
251 switch ( field_identifier )
252 {
253 /* Fixed-length fields: buffer_length is ignored */
254 case SQL_DESC_ALLOC_TYPE:
255 case SQL_DESC_ARRAY_SIZE:
256 case SQL_DESC_ARRAY_STATUS_PTR:
257 case SQL_DESC_BIND_OFFSET_PTR:
258 case SQL_DESC_BIND_TYPE:
259 case SQL_DESC_COUNT:
260 case SQL_DESC_ROWS_PROCESSED_PTR:
261 case SQL_DESC_AUTO_UNIQUE_VALUE:
262 case SQL_DESC_CASE_SENSITIVE:
263 case SQL_DESC_CONCISE_TYPE:
264 case SQL_DESC_DATA_PTR:
265 case SQL_DESC_DATETIME_INTERVAL_CODE:
266 case SQL_DESC_DATETIME_INTERVAL_PRECISION:
267 case SQL_DESC_DISPLAY_SIZE:
268 case SQL_DESC_FIXED_PREC_SCALE:
269 case SQL_DESC_INDICATOR_PTR:
270 case SQL_DESC_LENGTH:
271 case SQL_DESC_NULLABLE:
272 case SQL_DESC_NUM_PREC_RADIX:
273 case SQL_DESC_OCTET_LENGTH:
274 case SQL_DESC_OCTET_LENGTH_PTR:
275 case SQL_DESC_PARAMETER_TYPE:
276 case SQL_DESC_PRECISION:
277 case SQL_DESC_ROWVER:
278 case SQL_DESC_SCALE:
279 case SQL_DESC_SEARCHABLE:
280 case SQL_DESC_TYPE:
281 case SQL_DESC_UNNAMED:
282 case SQL_DESC_UNSIGNED:
283 case SQL_DESC_UPDATABLE:
284 isStrField = 0;
285 break;
286 /* Pointer to data: buffer_length must be valid */
287 case SQL_DESC_BASE_COLUMN_NAME:
288 case SQL_DESC_BASE_TABLE_NAME:
289 case SQL_DESC_CATALOG_NAME:
290 case SQL_DESC_LABEL:
291 case SQL_DESC_LITERAL_PREFIX:
292 case SQL_DESC_LITERAL_SUFFIX:
293 case SQL_DESC_LOCAL_TYPE_NAME:
294 case SQL_DESC_NAME:
295 case SQL_DESC_SCHEMA_NAME:
296 case SQL_DESC_TABLE_NAME:
297 case SQL_DESC_TYPE_NAME:
298 isStrField = 1;
299 break;
300 default:
301 isStrField = buffer_length != SQL_IS_POINTER && buffer_length != SQL_IS_INTEGER
302 && buffer_length != SQL_IS_UINTEGER && buffer_length != SQL_IS_SMALLINT &&
303 buffer_length != SQL_IS_USMALLINT;
304 }
305
306 if ( isStrField && buffer_length < 0 )
307 {
308 __post_internal_error( &descriptor -> error,
309 ERROR_HY090, NULL,
310 descriptor -> connection -> environment -> requested_version );
311
312 return function_return_nodrv( SQL_HANDLE_DESC, descriptor, SQL_ERROR );
313 }
314
315 if ( descriptor -> connection -> unicode_driver ||
316 CHECK_SQLGETDESCFIELDW( descriptor -> connection ))
317 {
318 if ( !CHECK_SQLGETDESCFIELDW( descriptor -> connection ))
319 {
320 dm_log_write( __FILE__,
321 __LINE__,
322 LOG_INFO,
323 LOG_INFO,
324 "Error: IM001" );
325
326 __post_internal_error( &descriptor -> error,
327 ERROR_IM001, NULL,
328 descriptor -> connection -> environment -> requested_version );
329
330 return function_return_nodrv( SQL_HANDLE_DESC, descriptor, SQL_ERROR );
331 }
332
333 ret = SQLGETDESCFIELDW( descriptor -> connection,
334 descriptor -> driver_desc,
335 rec_number,
336 field_identifier,
337 value,
338 buffer_length,
339 string_length );
340 }
341 else
342 {
343 SQLCHAR *as1 = NULL;
344
345 if ( !CHECK_SQLGETDESCFIELD( descriptor -> connection ))
346 {
347 dm_log_write( __FILE__,
348 __LINE__,
349 LOG_INFO,
350 LOG_INFO,
351 "Error: IM001" );
352
353 __post_internal_error( &descriptor -> error,
354 ERROR_IM001, NULL,
355 descriptor -> connection -> environment -> requested_version );
356
357 return function_return_nodrv( SQL_HANDLE_DESC, descriptor, SQL_ERROR );
358 }
359
360 if ( isStrField && buffer_length > 0 && value )
361 {
362 as1 = malloc( buffer_length + 1 );
363 }
364
365 ret = SQLGETDESCFIELD( descriptor -> connection,
366 descriptor -> driver_desc,
367 rec_number,
368 field_identifier,
369 as1 ? as1 : value,
370 buffer_length,
371 string_length );
372
373 if ( isStrField && SQL_SUCCEEDED( ret ) && value )
374 {
375 if ( as1 && buffer_length > 0)
376 {
377 ansi_to_unicode_copy( value, (char*) as1, SQL_NTS, descriptor -> connection, NULL );
378 }
379 }
380
381 if ( as1 )
382 {
383 free( as1 );
384 }
385 }
386
387 if ( log_info.log_flag )
388 {
389 sprintf( descriptor -> msg,
390 "\n\t\tExit:[%s]",
391 __get_return_status( ret, s1 ));
392
393 dm_log_write( __FILE__,
394 __LINE__,
395 LOG_INFO,
396 LOG_INFO,
397 descriptor -> msg );
398 }
399
400 return function_return( SQL_HANDLE_DESC, descriptor, ret );
401}
402