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: SQLNativeSqlW.c,v 1.9 2009/02/18 17:59:08 lurcher Exp $
31 *
32 * $Log: SQLNativeSqlW.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 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/08/23 09:42:37 lurcher
54 *
55 * Fix some build warnings with casts, and a AIX linker mod, to include
56 * deplib's on the link line, but not the libtool generated ones
57 *
58 * Revision 1.3 2002/07/24 08:49:52 lurcher
59 *
60 * Alter UNICODE support to use iconv for UNICODE-ANSI conversion
61 *
62 * Revision 1.2 2001/12/13 13:00:32 lurcher
63 *
64 * Remove most if not all warnings on 64 bit platforms
65 * Add support for new MS 3.52 64 bit changes
66 * Add override to disable the stopping of tracing
67 * Add MAX_ROWS support in postgres driver
68 *
69 * Revision 1.1.1.1 2001/10/17 16:40:06 lurcher
70 *
71 * First upload to SourceForge
72 *
73 * Revision 1.3 2001/04/12 17:43:36 nick
74 *
75 * Change logging and added autotest to odbctest
76 *
77 * Revision 1.2 2001/01/02 09:55:04 nick
78 *
79 * More unicode bits
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: SQLNativeSqlW.c,v $";
92
93SQLRETURN SQLNativeSqlW(
94 SQLHDBC hdbc,
95 SQLWCHAR *sz_sql_str_in,
96 SQLINTEGER cb_sql_str_in,
97 SQLWCHAR *sz_sql_str,
98 SQLINTEGER cb_sql_str_max,
99 SQLINTEGER *pcb_sql_str )
100{
101 DMHDBC connection = (DMHDBC)hdbc;
102 SQLRETURN ret;
103 SQLCHAR *s1;
104 SQLCHAR s2[ 100 + LOG_MESSAGE_LEN ];
105
106 /*
107 * check connection
108 */
109
110 if ( !__validate_dbc( connection ))
111 {
112 dm_log_write( __FILE__,
113 __LINE__,
114 LOG_INFO,
115 LOG_INFO,
116 "Error: SQL_INVALID_HANDLE" );
117
118#ifdef WITH_HANDLE_REDIRECT
119 {
120 DMHDBC parent_connection;
121
122 parent_connection = find_parent_handle( connection, SQL_HANDLE_DBC );
123
124 if ( parent_connection ) {
125 dm_log_write( __FILE__,
126 __LINE__,
127 LOG_INFO,
128 LOG_INFO,
129 "Info: found parent handle" );
130
131 if ( CHECK_SQLNATIVESQLW( parent_connection ))
132 {
133 dm_log_write( __FILE__,
134 __LINE__,
135 LOG_INFO,
136 LOG_INFO,
137 "Info: calling redirected driver function" );
138
139 return SQLNATIVESQLW( parent_connection,
140 connection,
141 sz_sql_str_in,
142 cb_sql_str_in,
143 sz_sql_str,
144 cb_sql_str_max,
145 pcb_sql_str );
146 }
147 }
148 }
149#endif
150 return SQL_INVALID_HANDLE;
151 }
152
153 function_entry( connection );
154
155 if ( log_info.log_flag )
156 {
157 /*
158 * allocate some space for the buffer
159 */
160
161 if ( sz_sql_str_in && cb_sql_str_in == SQL_NTS )
162 {
163 s1 = malloc(( wide_strlen( sz_sql_str_in ) * 2 ) + 100 );
164 }
165 else if ( sz_sql_str_in )
166 {
167 s1 = malloc( cb_sql_str_in + 100 );
168 }
169 else
170 {
171 s1 = malloc( 101 );
172 }
173
174 sprintf( connection -> msg, "\n\t\tEntry:\
175\n\t\t\tConnection = %p\
176\n\t\t\tSQL In = %s\
177\n\t\t\tSQL Out = %p\
178\n\t\t\tSQL Out Len = %d\
179\n\t\t\tSQL Len Ptr = %p",
180 connection,
181 __wstring_with_length( s1, sz_sql_str_in, cb_sql_str_in ),
182 sz_sql_str,
183 (int)cb_sql_str_max,
184 pcb_sql_str );
185
186 free( s1 );
187
188 dm_log_write( __FILE__,
189 __LINE__,
190 LOG_INFO,
191 LOG_INFO,
192 connection -> msg );
193 }
194
195 thread_protect( SQL_HANDLE_DBC, connection );
196
197 if ( !sz_sql_str_in )
198 {
199 __post_internal_error( &connection -> error,
200 ERROR_HY009, NULL,
201 connection -> environment -> requested_version );
202
203 return function_return_nodrv( SQL_HANDLE_DBC, connection, SQL_ERROR );
204 }
205
206 if ( cb_sql_str_in < 0 &&
207 cb_sql_str_in != SQL_NTS )
208 {
209 dm_log_write( __FILE__,
210 __LINE__,
211 LOG_INFO,
212 LOG_INFO,
213 "Error: HY090" );
214
215 __post_internal_error( &connection -> error,
216 ERROR_HY090, NULL,
217 connection -> environment -> requested_version );
218
219 return function_return_nodrv( SQL_HANDLE_DBC, connection, SQL_ERROR );
220 }
221
222 if ( sz_sql_str &&
223 cb_sql_str_max < 0 )
224 {
225 dm_log_write( __FILE__,
226 __LINE__,
227 LOG_INFO,
228 LOG_INFO,
229 "Error: HY090" );
230
231 __post_internal_error( &connection -> error,
232 ERROR_HY090, NULL,
233 connection -> environment -> requested_version );
234
235 return function_return_nodrv( SQL_HANDLE_DBC, connection, SQL_ERROR );
236 }
237
238 if ( connection -> state == STATE_C2 ||
239 connection -> state == STATE_C3 )
240 {
241 dm_log_write( __FILE__,
242 __LINE__,
243 LOG_INFO,
244 LOG_INFO,
245 "Error: 08003" );
246
247 __post_internal_error( &connection -> error,
248 ERROR_08003, NULL,
249 connection -> environment -> requested_version );
250
251 return function_return_nodrv( SQL_HANDLE_DBC, connection, SQL_ERROR );
252 }
253
254 if ( connection -> unicode_driver ||
255 CHECK_SQLNATIVESQLW( connection ))
256 {
257 if ( !CHECK_SQLNATIVESQLW( connection ))
258 {
259 dm_log_write( __FILE__,
260 __LINE__,
261 LOG_INFO,
262 LOG_INFO,
263 "Error: IM001" );
264
265 __post_internal_error( &connection -> error,
266 ERROR_IM001, NULL,
267 connection -> environment -> requested_version );
268
269 return function_return_nodrv( SQL_HANDLE_DBC, connection, SQL_ERROR );
270 }
271
272 ret = SQLNATIVESQLW( connection,
273 connection -> driver_dbc,
274 sz_sql_str_in,
275 cb_sql_str_in,
276 sz_sql_str,
277 cb_sql_str_max,
278 pcb_sql_str );
279 }
280 else
281 {
282 SQLCHAR *as1 = NULL, *as2 = NULL;
283 int clen;
284
285 if ( !CHECK_SQLNATIVESQL( connection ))
286 {
287 dm_log_write( __FILE__,
288 __LINE__,
289 LOG_INFO,
290 LOG_INFO,
291 "Error: IM001" );
292
293 __post_internal_error( &connection -> error,
294 ERROR_IM001, NULL,
295 connection -> environment -> requested_version );
296
297 return function_return_nodrv( SQL_HANDLE_DBC, connection, SQL_ERROR );
298 }
299
300 as1 = (SQLCHAR*) unicode_to_ansi_alloc( sz_sql_str_in, cb_sql_str_in, connection, &clen );
301
302 cb_sql_str_in = clen;
303
304 if ( cb_sql_str_max > 0 && sz_sql_str )
305 {
306 as2 = malloc( cb_sql_str_max + 1 );
307 }
308
309 ret = SQLNATIVESQL( connection,
310 connection -> driver_dbc,
311 as1 ? as1 : (SQLCHAR*) sz_sql_str_in,
312 cb_sql_str_in,
313 as2 ? as2 : (SQLCHAR*) sz_sql_str,
314 cb_sql_str_max,
315 pcb_sql_str );
316
317 if ( SQL_SUCCEEDED( ret ) && as2 && sz_sql_str )
318 {
319 ansi_to_unicode_copy( sz_sql_str, (char*) as2, SQL_NTS, connection, NULL );
320 }
321
322 if ( as1 ) free( as1 );
323 if ( as2 ) free( as2 );
324 }
325
326 if ( log_info.log_flag )
327 {
328 /*
329 * allocate some space for the buffer
330 */
331
332 if ( sz_sql_str && pcb_sql_str && *pcb_sql_str == SQL_NTS )
333 {
334 s1 = malloc( wide_strlen( sz_sql_str ) * 2 + 100 );
335 }
336 else if ( sz_sql_str && pcb_sql_str )
337 {
338 s1 = malloc( *pcb_sql_str + 100 );
339 }
340 else if ( sz_sql_str )
341 {
342 s1 = malloc( wide_strlen( sz_sql_str ) * 2 + 100 );
343 }
344 else
345 {
346 s1 = malloc( 101 );
347 }
348
349 sprintf( connection -> msg,
350 "\n\t\tExit:[%s]\
351\n\t\t\tSQL Out = %s",
352 __get_return_status( ret, s2 ),
353 __idata_as_string( s1, SQL_CHAR,
354 pcb_sql_str, sz_sql_str ));
355
356 free( s1 );
357
358 dm_log_write( __FILE__,
359 __LINE__,
360 LOG_INFO,
361 LOG_INFO,
362 connection -> msg );
363 }
364
365 return function_return( SQL_HANDLE_DBC, connection, ret );
366}
367