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: SQLNativeSql.c,v 1.9 2009/02/18 17:59:08 lurcher Exp $
31 *
32 * $Log: SQLNativeSql.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/09/29 14:02:45 lurcher
37 * Fix missing dlfcn group option
38 *
39 * Revision 1.7 2003/10/30 18:20:46 lurcher
40 *
41 * Fix broken thread protection
42 * Remove SQLNumResultCols after execute, lease S4/S% to driver
43 * Fix string overrun in SQLDriverConnect
44 * Add initial support for Interix
45 *
46 * Revision 1.6 2003/02/27 12:19:39 lurcher
47 *
48 * Add the A functions as well as the W
49 *
50 * Revision 1.5 2002/12/05 17:44:31 lurcher
51 *
52 * Display unknown return values in return logging
53 *
54 * Revision 1.4 2002/08/23 09:42:37 lurcher
55 *
56 * Fix some build warnings with casts, and a AIX linker mod, to include
57 * deplib's on the link line, but not the libtool generated ones
58 *
59 * Revision 1.3 2002/07/24 08:49:52 lurcher
60 *
61 * Alter UNICODE support to use iconv for UNICODE-ANSI conversion
62 *
63 * Revision 1.2 2001/12/13 13:00:32 lurcher
64 *
65 * Remove most if not all warnings on 64 bit platforms
66 * Add support for new MS 3.52 64 bit changes
67 * Add override to disable the stopping of tracing
68 * Add MAX_ROWS support in postgres driver
69 *
70 * Revision 1.1.1.1 2001/10/17 16:40:06 lurcher
71 *
72 * First upload to SourceForge
73 *
74 * Revision 1.4 2001/04/12 17:43:36 nick
75 *
76 * Change logging and added autotest to odbctest
77 *
78 * Revision 1.3 2001/01/02 09:55:04 nick
79 *
80 * More unicode bits
81 *
82 * Revision 1.2 2000/12/31 20:30:54 nick
83 *
84 * Add UNICODE support
85 *
86 * Revision 1.1.1.1 2000/09/04 16:42:52 nick
87 * Imported Sources
88 *
89 * Revision 1.7 1999/11/13 23:41:00 ngorham
90 *
91 * Alter the way DM logging works
92 * Upgrade the Postgres driver to 6.4.6
93 *
94 * Revision 1.6 1999/10/24 23:54:18 ngorham
95 *
96 * First part of the changes to the error reporting
97 *
98 * Revision 1.5 1999/09/21 22:34:25 ngorham
99 *
100 * Improve performance by removing unneeded logging calls when logging is
101 * disabled
102 *
103 * Revision 1.4 1999/07/10 21:10:16 ngorham
104 *
105 * Adjust error sqlstate from driver manager, depending on requested
106 * version (ODBC2/3)
107 *
108 * Revision 1.3 1999/07/04 21:05:08 ngorham
109 *
110 * Add LGPL Headers to code
111 *
112 * Revision 1.2 1999/06/30 23:56:55 ngorham
113 *
114 * Add initial thread safety code
115 *
116 * Revision 1.1.1.1 1999/05/29 13:41:08 sShandyb
117 * first go at it
118 *
119 * Revision 1.1.1.1 1999/05/27 18:23:18 pharvey
120 * Imported sources
121 *
122 * Revision 1.3 1999/04/30 16:22:47 nick
123 * Another checkpoint
124 *
125 * Revision 1.2 1999/04/29 21:40:58 nick
126 * End of another night :-)
127 *
128 * Revision 1.1 1999/04/25 23:06:11 nick
129 * Initial revision
130 *
131 *
132 **********************************************************************/
133
134#include <config.h>
135#include "drivermanager.h"
136
137static char const rcsid[]= "$RCSfile: SQLNativeSql.c,v $ $Revision: 1.9 $";
138
139SQLRETURN SQLNativeSqlA(
140 SQLHDBC hdbc,
141 SQLCHAR *sz_sql_str_in,
142 SQLINTEGER cb_sql_str_in,
143 SQLCHAR *sz_sql_str,
144 SQLINTEGER cb_sql_str_max,
145 SQLINTEGER *pcb_sql_str )
146{
147 return SQLNativeSql( hdbc,
148 sz_sql_str_in,
149 cb_sql_str_in,
150 sz_sql_str,
151 cb_sql_str_max,
152 pcb_sql_str );
153}
154
155SQLRETURN SQLNativeSql(
156 SQLHDBC hdbc,
157 SQLCHAR *sz_sql_str_in,
158 SQLINTEGER cb_sql_str_in,
159 SQLCHAR *sz_sql_str,
160 SQLINTEGER cb_sql_str_max,
161 SQLINTEGER *pcb_sql_str )
162{
163 DMHDBC connection = (DMHDBC)hdbc;
164 SQLRETURN ret;
165 SQLCHAR *s1;
166 SQLCHAR s2[ 100 + LOG_MESSAGE_LEN ];
167
168 /*
169 * check connection
170 */
171
172 if ( !__validate_dbc( connection ))
173 {
174 dm_log_write( __FILE__,
175 __LINE__,
176 LOG_INFO,
177 LOG_INFO,
178 "Error: SQL_INVALID_HANDLE" );
179
180 return SQL_INVALID_HANDLE;
181 }
182
183 function_entry( connection );
184
185 if ( log_info.log_flag )
186 {
187 /*
188 * allocate some space for the buffer
189 */
190
191 if ( sz_sql_str_in && cb_sql_str_in == SQL_NTS )
192 {
193 s1 = malloc( strlen((char*) sz_sql_str_in ) + 100 );
194 }
195 else if ( sz_sql_str_in )
196 {
197 s1 = malloc( cb_sql_str_in + 100 );
198 }
199 else
200 {
201 s1 = malloc( 101 );
202 }
203
204 sprintf( connection -> msg, "\n\t\tEntry:\
205\n\t\t\tConnection = %p\
206\n\t\t\tSQL In = %s\
207\n\t\t\tSQL Out = %p\
208\n\t\t\tSQL Out Len = %d\
209\n\t\t\tSQL Len Ptr = %p",
210 connection,
211 __string_with_length( s1, sz_sql_str_in, cb_sql_str_in ),
212 sz_sql_str,
213 (int)cb_sql_str_max,
214 pcb_sql_str );
215
216 free( s1 );
217
218 dm_log_write( __FILE__,
219 __LINE__,
220 LOG_INFO,
221 LOG_INFO,
222 connection -> msg );
223 }
224
225 thread_protect( SQL_HANDLE_DBC, connection );
226
227 if ( !sz_sql_str_in )
228 {
229 __post_internal_error( &connection -> error,
230 ERROR_HY009, NULL,
231 connection -> environment -> requested_version );
232
233 return function_return_nodrv( SQL_HANDLE_DBC, connection, SQL_ERROR );
234 }
235
236 if ( cb_sql_str_in < 0 &&
237 cb_sql_str_in != SQL_NTS )
238 {
239 dm_log_write( __FILE__,
240 __LINE__,
241 LOG_INFO,
242 LOG_INFO,
243 "Error: HY090" );
244
245 __post_internal_error( &connection -> error,
246 ERROR_HY090, NULL,
247 connection -> environment -> requested_version );
248
249 return function_return_nodrv( SQL_HANDLE_DBC, connection, SQL_ERROR );
250 }
251
252 if ( sz_sql_str &&
253 cb_sql_str_max < 0 )
254 {
255 dm_log_write( __FILE__,
256 __LINE__,
257 LOG_INFO,
258 LOG_INFO,
259 "Error: HY090" );
260
261 __post_internal_error( &connection -> error,
262 ERROR_HY090, NULL,
263 connection -> environment -> requested_version );
264
265 return function_return_nodrv( SQL_HANDLE_DBC, connection, SQL_ERROR );
266 }
267
268 if ( connection -> state == STATE_C2 ||
269 connection -> state == STATE_C3 )
270 {
271 dm_log_write( __FILE__,
272 __LINE__,
273 LOG_INFO,
274 LOG_INFO,
275 "Error: 08003" );
276
277 __post_internal_error( &connection -> error,
278 ERROR_08003, NULL,
279 connection -> environment -> requested_version );
280
281 return function_return_nodrv( SQL_HANDLE_DBC, connection, SQL_ERROR );
282 }
283
284 if ( connection -> unicode_driver )
285 {
286 SQLWCHAR *s1, *s2 = NULL;
287
288 if ( !CHECK_SQLNATIVESQLW( connection ))
289 {
290 dm_log_write( __FILE__,
291 __LINE__,
292 LOG_INFO,
293 LOG_INFO,
294 "Error: IM001" );
295
296 __post_internal_error( &connection -> error,
297 ERROR_IM001, NULL,
298 connection -> environment -> requested_version );
299
300 return function_return_nodrv( SQL_HANDLE_DBC, connection, SQL_ERROR );
301 }
302
303 s1 = ansi_to_unicode_alloc( sz_sql_str_in, cb_sql_str_in, connection, NULL );
304
305 if ( sz_sql_str && cb_sql_str_max > 0 )
306 {
307 s2 = malloc( sizeof( SQLWCHAR ) * ( cb_sql_str_max + 1 ));
308 }
309
310 ret = SQLNATIVESQLW( connection,
311 connection -> driver_dbc,
312 s1,
313 cb_sql_str_in,
314 s2,
315 cb_sql_str_max,
316 pcb_sql_str );
317
318 if ( SQL_SUCCEEDED( ret ) && s2 && sz_sql_str )
319 {
320 unicode_to_ansi_copy((char*) sz_sql_str, cb_sql_str_max, s2, SQL_NTS, connection, NULL );
321 }
322
323 if ( s1 )
324 free( s1 );
325
326 if ( s2 )
327 free( s2 );
328 }
329 else
330 {
331 if ( !CHECK_SQLNATIVESQL( connection ))
332 {
333 dm_log_write( __FILE__,
334 __LINE__,
335 LOG_INFO,
336 LOG_INFO,
337 "Error: IM001" );
338
339 __post_internal_error( &connection -> error,
340 ERROR_IM001, NULL,
341 connection -> environment -> requested_version );
342
343 return function_return_nodrv( SQL_HANDLE_DBC, connection, SQL_ERROR );
344 }
345
346 ret = SQLNATIVESQL( connection,
347 connection -> driver_dbc,
348 sz_sql_str_in,
349 cb_sql_str_in,
350 sz_sql_str,
351 cb_sql_str_max,
352 pcb_sql_str );
353 }
354 if ( log_info.log_flag )
355 {
356 /*
357 * allocate some space for the buffer
358 */
359
360 if ( sz_sql_str && pcb_sql_str && *pcb_sql_str == SQL_NTS )
361 {
362 s1 = malloc( strlen((char*) sz_sql_str ) + 100 );
363 }
364 else if ( sz_sql_str && pcb_sql_str )
365 {
366 s1 = malloc( *pcb_sql_str + 100 );
367 }
368 else if ( sz_sql_str )
369 {
370 s1 = malloc( strlen((char*) sz_sql_str ) + 100 );
371 }
372 else
373 {
374 s1 = malloc( 101 );
375 }
376
377 sprintf( connection -> msg,
378 "\n\t\tExit:[%s]\
379\n\t\t\tSQL Out = %s",
380 __get_return_status( ret, s2 ),
381 __idata_as_string( s1, SQL_CHAR,
382 pcb_sql_str, sz_sql_str ));
383
384 free( s1 );
385
386 dm_log_write( __FILE__,
387 __LINE__,
388 LOG_INFO,
389 LOG_INFO,
390 connection -> msg );
391 }
392
393 return function_return( SQL_HANDLE_DBC, connection, ret );
394}
395