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 
102 static char const rcsid[]= "$RCSfile: SQLGetDescRecW.c,v $";
103 
SQLGetDescRecW(SQLHDESC descriptor_handle,SQLSMALLINT rec_number,SQLWCHAR * name,SQLSMALLINT buffer_length,SQLSMALLINT * string_length,SQLSMALLINT * type,SQLSMALLINT * sub_type,SQLLEN * length,SQLSMALLINT * precision,SQLSMALLINT * scale,SQLSMALLINT * nullable)104 SQLRETURN 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, DEFER_R3 );
372 }
373