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: SQLGetDescRecW.c,v 1.11 2009/02/18 17:59:08 lurcher Exp $
31 *
32 * $Log: SQLGetDescRecW.c,v $
33 * Revision 1.11 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.10 2008/08/29 08:01:39 lurcher
37 * Alter the way W functions are passed to the driver
38 *
39 * Revision 1.9 2007/04/02 10:50:19 lurcher
40 * Fix some 64bit problems (only when sizeof(SQLLEN) == 8 )
41 *
42 * Revision 1.8 2007/02/28 15:37:48 lurcher
43 * deal with drivers that call internal W functions and end up in the driver manager. controlled by the --enable-handlemap configure arg
44 *
45 * Revision 1.7 2004/11/22 17:02:49 lurcher
46 * Fix unicode/ansi conversion in the SQLGet functions
47 *
48 * Revision 1.6 2003/10/30 18:20:46 lurcher
49 *
50 * Fix broken thread protection
51 * Remove SQLNumResultCols after execute, lease S4/S% to driver
52 * Fix string overrun in SQLDriverConnect
53 * Add initial support for Interix
54 *
55 * Revision 1.5 2002/12/05 17:44:30 lurcher
56 *
57 * Display unknown return values in return logging
58 *
59 * Revision 1.4 2002/08/23 09:42:37 lurcher
60 *
61 * Fix some build warnings with casts, and a AIX linker mod, to include
62 * deplib's on the link line, but not the libtool generated ones
63 *
64 * Revision 1.3 2002/07/24 08:49:52 lurcher
65 *
66 * Alter UNICODE support to use iconv for UNICODE-ANSI conversion
67 *
68 * Revision 1.2 2001/12/13 13:00:32 lurcher
69 *
70 * Remove most if not all warnings on 64 bit platforms
71 * Add support for new MS 3.52 64 bit changes
72 * Add override to disable the stopping of tracing
73 * Add MAX_ROWS support in postgres driver
74 *
75 * Revision 1.1.1.1 2001/10/17 16:40:05 lurcher
76 *
77 * First upload to SourceForge
78 *
79 * Revision 1.4 2001/07/03 09:30:41 nick
80 *
81 * Add ability to alter size of displayed message in the log
82 *
83 * Revision 1.3 2001/04/12 17:43:36 nick
84 *
85 * Change logging and added autotest to odbctest
86 *
87 * Revision 1.2 2001/01/04 13:16:25 nick
88 *
89 * Add support for GNU portable threads and tidy up some UNICODE compile
90 * warnings
91 *
92 * Revision 1.1 2000/12/31 20:30:54 nick
93 *
94 * Add UNICODE support
95 *
96 *
97 **********************************************************************/
98
99#include <config.h>
100#include "drivermanager.h"
101
102static char const rcsid[]= "$RCSfile: SQLGetDescRecW.c,v $";
103
104SQLRETURN SQLGetDescRecW( SQLHDESC descriptor_handle,
105 SQLSMALLINT rec_number,
106 SQLWCHAR *name,
107 SQLSMALLINT buffer_length,
108 SQLSMALLINT *string_length,
109 SQLSMALLINT *type,
110 SQLSMALLINT *sub_type,
111 SQLLEN *length,
112 SQLSMALLINT *precision,
113 SQLSMALLINT *scale,
114 SQLSMALLINT *nullable )
115{
116 /*
117 * not quite sure how the descriptor can be
118 * allocated to a statement, all the documentation talks
119 * about state transitions on statement states, but the
120 * descriptor may be allocated with more than one statement
121 * at one time. Which one should I check ?
122 */
123 DMHDESC descriptor = (DMHDESC) descriptor_handle;
124 SQLRETURN ret;
125 SQLCHAR s1[ 100 + LOG_MESSAGE_LEN ], s2[ 100 + LOG_MESSAGE_LEN ], s3[ 100 + LOG_MESSAGE_LEN ], s4[ 100 + LOG_MESSAGE_LEN ];
126 SQLCHAR s5[ 100 + LOG_MESSAGE_LEN ], s6[ 100 + LOG_MESSAGE_LEN ], s7[ 100 + LOG_MESSAGE_LEN ];
127 SQLCHAR s8[ 100 + LOG_MESSAGE_LEN ];
128
129
130 /*
131 * check descriptor
132 */
133
134 if ( !__validate_desc( descriptor ))
135 {
136 dm_log_write( __FILE__,
137 __LINE__,
138 LOG_INFO,
139 LOG_INFO,
140 "Error: SQL_INVALID_HANDLE" );
141
142#ifdef WITH_HANDLE_REDIRECT
143 {
144 DMHDESC parent_desc;
145
146 parent_desc = find_parent_handle( descriptor, SQL_HANDLE_DESC );
147
148 if ( parent_desc ) {
149 dm_log_write( __FILE__,
150 __LINE__,
151 LOG_INFO,
152 LOG_INFO,
153 "Info: found parent handle" );
154
155 if ( CHECK_SQLGETDESCRECW( parent_desc -> connection ))
156 {
157 dm_log_write( __FILE__,
158 __LINE__,
159 LOG_INFO,
160 LOG_INFO,
161 "Info: calling redirected driver function" );
162
163 return SQLGETDESCRECW( parent_desc -> connection,
164 descriptor,
165 rec_number,
166 name,
167 buffer_length,
168 string_length,
169 type,
170 sub_type,
171 length,
172 precision,
173 scale,
174 nullable );
175 }
176 }
177 }
178#endif
179 return SQL_INVALID_HANDLE;
180 }
181
182 function_entry( descriptor );
183
184 if ( log_info.log_flag )
185 {
186 sprintf( descriptor -> msg, "\n\t\tEntry:\
187\n\t\t\tDescriptor = %p\
188\n\t\t\tRec Number = %d\
189\n\t\t\tName = %p\
190\n\t\t\tBuffer length = %d\
191\n\t\t\tString Length = %p\
192\n\t\t\tType = %p\
193\n\t\t\tSub Type = %p\
194\n\t\t\tLength = %p\
195\n\t\t\tPrecision = %p\
196\n\t\t\tScale = %p\
197\n\t\t\tNullable = %p",
198 descriptor,
199 rec_number,
200 name,
201 buffer_length,
202 string_length,
203 type,
204 sub_type,
205 length,
206 precision,
207 scale,
208 nullable );
209
210 dm_log_write( __FILE__,
211 __LINE__,
212 LOG_INFO,
213 LOG_INFO,
214 descriptor -> msg );
215 }
216
217 thread_protect( SQL_HANDLE_DESC, descriptor );
218
219 /*
220 * check status of statements associated with this descriptor
221 */
222
223 if( __check_stmt_from_desc( descriptor, STATE_S8 ) ||
224 __check_stmt_from_desc( descriptor, STATE_S9 ) ||
225 __check_stmt_from_desc( descriptor, STATE_S10 ) ||
226 __check_stmt_from_desc( descriptor, STATE_S11 ) ||
227 __check_stmt_from_desc( descriptor, STATE_S12 ) ||
228 __check_stmt_from_desc( descriptor, STATE_S13 ) ||
229 __check_stmt_from_desc( descriptor, STATE_S14 ) ||
230 __check_stmt_from_desc( descriptor, STATE_S15 )) {
231
232 dm_log_write( __FILE__,
233 __LINE__,
234 LOG_INFO,
235 LOG_INFO,
236 "Error: HY010" );
237
238 __post_internal_error( &descriptor -> error,
239 ERROR_HY010, NULL,
240 descriptor -> connection -> environment -> requested_version );
241
242 return function_return_nodrv( SQL_HANDLE_DESC, descriptor, SQL_ERROR );
243 }
244
245 if( __check_stmt_from_desc_ird( descriptor, STATE_S1 )) {
246
247 dm_log_write( __FILE__,
248 __LINE__,
249 LOG_INFO,
250 LOG_INFO,
251 "Error: HY007" );
252
253 __post_internal_error( &descriptor -> error,
254 ERROR_HY007, NULL,
255 descriptor -> connection -> environment -> requested_version );
256
257 return function_return_nodrv( SQL_HANDLE_DESC, descriptor, SQL_ERROR );
258 }
259
260
261 if ( descriptor -> connection -> unicode_driver ||
262 CHECK_SQLGETDESCRECW( descriptor -> connection ))
263 {
264 if ( !CHECK_SQLGETDESCRECW( descriptor -> connection ))
265 {
266 dm_log_write( __FILE__,
267 __LINE__,
268 LOG_INFO,
269 LOG_INFO,
270 "Error: IM001" );
271
272 __post_internal_error( &descriptor -> error,
273 ERROR_IM001, NULL,
274 descriptor -> connection -> environment -> requested_version );
275
276 return function_return_nodrv( SQL_HANDLE_DESC, descriptor, SQL_ERROR );
277 }
278
279 ret = SQLGETDESCRECW( descriptor -> connection,
280 descriptor -> driver_desc,
281 rec_number,
282 name,
283 buffer_length,
284 string_length,
285 type,
286 sub_type,
287 length,
288 precision,
289 scale,
290 nullable );
291 }
292 else
293 {
294 SQLCHAR *as1 = NULL;
295
296 if ( !CHECK_SQLGETDESCREC( descriptor -> connection ))
297 {
298 dm_log_write( __FILE__,
299 __LINE__,
300 LOG_INFO,
301 LOG_INFO,
302 "Error: IM001" );
303
304 __post_internal_error( &descriptor -> error,
305 ERROR_IM001, NULL,
306 descriptor -> connection -> environment -> requested_version );
307
308 return function_return_nodrv( SQL_HANDLE_DESC, descriptor, SQL_ERROR );
309 }
310
311 if ( name && buffer_length > 0 )
312 {
313 as1 = malloc( buffer_length + 1 );
314 }
315
316 ret = SQLGETDESCREC( descriptor -> connection,
317 descriptor -> driver_desc,
318 rec_number,
319 as1 ? as1 : (SQLCHAR*) name,
320 buffer_length,
321 string_length,
322 type,
323 sub_type,
324 length,
325 precision,
326 scale,
327 nullable );
328
329 if ( SQL_SUCCEEDED( ret ) && name && as1 )
330 {
331 ansi_to_unicode_copy( name, (char*) as1, SQL_NTS, descriptor -> connection, NULL );
332 }
333 if ( as1 )
334 {
335 free( as1 );
336 }
337 if ( SQL_SUCCEEDED( ret ) && string_length )
338 {
339 *string_length *= sizeof( SQLWCHAR );
340 }
341 }
342
343 if ( log_info.log_flag )
344 {
345 sprintf( descriptor -> msg,
346 "\n\t\tExit:[%s]\
347\n\t\t\tName = %s\
348\n\t\t\tType = %s\
349\n\t\t\tSub Type = %s\
350\n\t\t\tLength = %s\
351\n\t\t\tPrecision = %s\
352\n\t\t\tScale = %s\
353\n\t\t\tNullable = %s",
354 __get_return_status( ret, s8 ),
355 __sdata_as_string( s1, SQL_WCHAR,
356 string_length, name ),
357 __sptr_as_string( s2, type ),
358 __sptr_as_string( s3, sub_type ),
359 __ptr_as_string( s4, length ),
360 __sptr_as_string( s5, precision ),
361 __sptr_as_string( s6, scale ),
362 __sptr_as_string( s7, nullable ));
363
364 dm_log_write( __FILE__,
365 __LINE__,
366 LOG_INFO,
367 LOG_INFO,
368 descriptor -> msg );
369 }
370
371 return function_return( SQL_HANDLE_DESC, descriptor, ret );
372}
373