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: SQLForeignKeysW.c,v 1.9 2009/02/18 17:59:08 lurcher Exp $
31 *
32 * $Log: SQLForeignKeysW.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:38 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/01/12 09:54:39 lurcher
43 *
44 * Fix problem where STATE_S5 stops metadata calls
45 *
46 * Revision 1.5 2003/10/30 18:20:45 lurcher
47 *
48 * Fix broken thread protection
49 * Remove SQLNumResultCols after execute, lease S4/S% to driver
50 * Fix string overrun in SQLDriverConnect
51 * Add initial support for Interix
52 *
53 * Revision 1.4 2002/12/05 17:44:30 lurcher
54 *
55 * Display unknown return values in return logging
56 *
57 * Revision 1.3 2002/08/23 09:42:37 lurcher
58 *
59 * Fix some build warnings with casts, and a AIX linker mod, to include
60 * deplib's on the link line, but not the libtool generated ones
61 *
62 * Revision 1.2 2002/07/24 08:49:52 lurcher
63 *
64 * Alter UNICODE support to use iconv for UNICODE-ANSI conversion
65 *
66 * Revision 1.1.1.1 2001/10/17 16:40:05 lurcher
67 *
68 * First upload to SourceForge
69 *
70 * Revision 1.3 2001/07/03 09:30:41 nick
71 *
72 * Add ability to alter size of displayed message in the log
73 *
74 * Revision 1.2 2001/04/12 17:43:36 nick
75 *
76 * Change logging and added autotest to odbctest
77 *
78 * Revision 1.1 2000/12/31 20:30:54 nick
79 *
80 * Add UNICODE support
81 *
82 *
83 **********************************************************************/
84
85#include <config.h>
86#include "drivermanager.h"
87
88static char const rcsid[]= "$RCSfile: SQLForeignKeysW.c,v $";
89
90SQLRETURN SQLForeignKeysW(
91 SQLHSTMT statement_handle,
92 SQLWCHAR *szpk_catalog_name,
93 SQLSMALLINT cbpk_catalog_name,
94 SQLWCHAR *szpk_schema_name,
95 SQLSMALLINT cbpk_schema_name,
96 SQLWCHAR *szpk_table_name,
97 SQLSMALLINT cbpk_table_name,
98 SQLWCHAR *szfk_catalog_name,
99 SQLSMALLINT cbfk_catalog_name,
100 SQLWCHAR *szfk_schema_name,
101 SQLSMALLINT cbfk_schema_name,
102 SQLWCHAR *szfk_table_name,
103 SQLSMALLINT cbfk_table_name )
104{
105 DMHSTMT statement = (DMHSTMT) statement_handle;
106 SQLRETURN ret;
107 SQLCHAR s1[ 100 + LOG_MESSAGE_LEN ], s2[ 100 + LOG_MESSAGE_LEN ], s3[ 100 + LOG_MESSAGE_LEN ], s4[ 100 + LOG_MESSAGE_LEN ];
108 SQLCHAR s5[ 100 + LOG_MESSAGE_LEN ], s6[ 100 + LOG_MESSAGE_LEN ];
109
110 /*
111 * check statement
112 */
113
114 if ( !__validate_stmt( statement ))
115 {
116 dm_log_write( __FILE__,
117 __LINE__,
118 LOG_INFO,
119 LOG_INFO,
120 "Error: SQL_INVALID_HANDLE" );
121
122#ifdef WITH_HANDLE_REDIRECT
123 {
124 DMHSTMT parent_statement;
125
126 parent_statement = find_parent_handle( statement, SQL_HANDLE_STMT );
127
128 if ( parent_statement ) {
129 dm_log_write( __FILE__,
130 __LINE__,
131 LOG_INFO,
132 LOG_INFO,
133 "Info: found parent handle" );
134
135 if ( CHECK_SQLFOREIGNKEYSW( parent_statement -> connection ))
136 {
137 dm_log_write( __FILE__,
138 __LINE__,
139 LOG_INFO,
140 LOG_INFO,
141 "Info: calling redirected driver function" );
142
143 return SQLFOREIGNKEYSW( parent_statement -> connection,
144 statement,
145 szpk_catalog_name,
146 cbpk_catalog_name,
147 szpk_schema_name,
148 cbpk_schema_name,
149 szpk_table_name,
150 cbpk_table_name,
151 szfk_catalog_name,
152 cbfk_catalog_name,
153 szfk_schema_name,
154 cbfk_schema_name,
155 szfk_table_name,
156 cbfk_table_name );
157 }
158 }
159 }
160#endif
161 return SQL_INVALID_HANDLE;
162 }
163
164 function_entry( statement );
165
166 if ( log_info.log_flag )
167 {
168 sprintf( statement -> msg, "\n\t\tEntry:\
169\n\t\t\tStatement = %p\
170\n\t\t\tPK Catalog Name = %s\
171\n\t\t\tPK Schema Name = %s\
172\n\t\t\tPK Table Name = %s\
173\n\t\t\tFK Catalog Name = %s\
174\n\t\t\tFK Schema Name = %s\
175\n\t\t\tFK Table Name = %s",
176 statement,
177 __wstring_with_length( s1, szpk_catalog_name, cbpk_catalog_name ),
178 __wstring_with_length( s2, szpk_schema_name, cbpk_schema_name ),
179 __wstring_with_length( s3, szpk_table_name, cbpk_table_name ),
180 __wstring_with_length( s4, szfk_catalog_name, cbfk_catalog_name ),
181 __wstring_with_length( s5, szfk_schema_name, cbfk_schema_name ),
182 __wstring_with_length( s6, szfk_table_name, cbfk_table_name ));
183
184 dm_log_write( __FILE__,
185 __LINE__,
186 LOG_INFO,
187 LOG_INFO,
188 statement -> msg );
189 }
190
191 thread_protect( SQL_HANDLE_STMT, statement );
192
193 if ( !szpk_table_name && !szfk_table_name )
194 {
195 __post_internal_error( &statement -> error,
196 ERROR_HY009, NULL,
197 statement -> connection -> environment -> requested_version );
198
199 return function_return_nodrv( SQL_HANDLE_STMT, statement, SQL_ERROR );
200 }
201
202 if (( cbpk_catalog_name < 0 && cbpk_catalog_name != SQL_NTS ) ||
203 ( cbpk_schema_name < 0 && cbpk_schema_name != SQL_NTS ) ||
204 ( cbpk_table_name < 0 && cbpk_table_name != SQL_NTS ) ||
205 ( cbfk_catalog_name < 0 && cbfk_catalog_name != SQL_NTS ) ||
206 ( cbfk_schema_name < 0 && cbfk_schema_name != SQL_NTS ) ||
207 ( cbfk_table_name < 0 && cbfk_table_name != SQL_NTS ))
208 {
209 __post_internal_error( &statement -> error,
210 ERROR_HY090, NULL,
211 statement -> connection -> environment -> requested_version );
212
213 return function_return_nodrv( SQL_HANDLE_STMT, statement, SQL_ERROR );
214 }
215
216 /*
217 * check states
218 */
219
220#ifdef NR_PROBE
221 if ( statement -> state == STATE_S5 ||
222 statement -> state == STATE_S6 ||
223 statement -> state == STATE_S7 )
224#else
225 if ( statement -> state == STATE_S6 ||
226 statement -> state == STATE_S7 )
227#endif
228 {
229 dm_log_write( __FILE__,
230 __LINE__,
231 LOG_INFO,
232 LOG_INFO,
233 "Error: 24000" );
234
235 __post_internal_error( &statement -> error,
236 ERROR_24000, NULL,
237 statement -> connection -> environment -> requested_version );
238
239 return function_return_nodrv( SQL_HANDLE_STMT, statement, SQL_ERROR );
240 }
241 else if ( statement -> state == STATE_S8 ||
242 statement -> state == STATE_S9 ||
243 statement -> state == STATE_S10 ||
244 statement -> state == STATE_S13 ||
245 statement -> state == STATE_S14 ||
246 statement -> state == STATE_S15 )
247 {
248 dm_log_write( __FILE__,
249 __LINE__,
250 LOG_INFO,
251 LOG_INFO,
252 "Error: HY010" );
253
254 __post_internal_error( &statement -> error,
255 ERROR_HY010, NULL,
256 statement -> connection -> environment -> requested_version );
257
258 return function_return_nodrv( SQL_HANDLE_STMT, statement, SQL_ERROR );
259 }
260
261 if ( statement -> state == STATE_S11 ||
262 statement -> state == STATE_S12 )
263 {
264 if ( statement -> interupted_func != SQL_API_SQLFOREIGNKEYS )
265 {
266 dm_log_write( __FILE__,
267 __LINE__,
268 LOG_INFO,
269 LOG_INFO,
270 "Error: HY010" );
271
272 __post_internal_error( &statement -> error,
273 ERROR_HY010, NULL,
274 statement -> connection -> environment -> requested_version );
275
276 return function_return_nodrv( SQL_HANDLE_STMT, statement, SQL_ERROR );
277 }
278 }
279
280 /*
281 * TO_DO Check the SQL_ATTR_METADATA_ID settings
282 */
283
284 if ( statement -> connection -> unicode_driver ||
285 CHECK_SQLFOREIGNKEYSW( statement -> connection ))
286 {
287 if ( !CHECK_SQLFOREIGNKEYSW( statement -> connection ))
288 {
289 dm_log_write( __FILE__,
290 __LINE__,
291 LOG_INFO,
292 LOG_INFO,
293 "Error: IM001" );
294
295 __post_internal_error( &statement -> error,
296 ERROR_IM001, NULL,
297 statement -> connection -> environment -> requested_version );
298
299 return function_return_nodrv( SQL_HANDLE_STMT, statement, SQL_ERROR );
300 }
301
302 ret = SQLFOREIGNKEYSW( statement -> connection ,
303 statement -> driver_stmt,
304 szpk_catalog_name,
305 cbpk_catalog_name,
306 szpk_schema_name,
307 cbpk_schema_name,
308 szpk_table_name,
309 cbpk_table_name,
310 szfk_catalog_name,
311 cbfk_catalog_name,
312 szfk_schema_name,
313 cbfk_schema_name,
314 szfk_table_name,
315 cbfk_table_name );
316 }
317 else
318 {
319 SQLCHAR *as1, *as2, *as3, *as4, *as5, *as6;
320 int clen;
321
322 if ( !CHECK_SQLFOREIGNKEYS( statement -> connection ))
323 {
324 dm_log_write( __FILE__,
325 __LINE__,
326 LOG_INFO,
327 LOG_INFO,
328 "Error: IM001" );
329
330 __post_internal_error( &statement -> error,
331 ERROR_IM001, NULL,
332 statement -> connection -> environment -> requested_version );
333
334 return function_return_nodrv( SQL_HANDLE_STMT, statement, SQL_ERROR );
335 }
336
337 as1 = (SQLCHAR*) unicode_to_ansi_alloc( szpk_catalog_name, cbpk_catalog_name, statement -> connection, &clen );
338 cbpk_catalog_name = clen;
339 as2 = (SQLCHAR*) unicode_to_ansi_alloc( szpk_schema_name, cbpk_schema_name, statement -> connection, &clen );
340 cbpk_schema_name = clen;
341 as3 = (SQLCHAR*) unicode_to_ansi_alloc( szpk_table_name, cbpk_table_name, statement -> connection, &clen );
342 cbpk_table_name = clen;
343 as4 = (SQLCHAR*) unicode_to_ansi_alloc( szfk_catalog_name, cbfk_catalog_name, statement -> connection, &clen );
344 cbfk_catalog_name = clen;
345 as5 = (SQLCHAR*) unicode_to_ansi_alloc( szfk_schema_name, cbfk_schema_name, statement -> connection, &clen );
346 cbfk_schema_name = clen;
347 as6 = (SQLCHAR*) unicode_to_ansi_alloc( szfk_table_name, cbfk_table_name, statement -> connection, &clen );
348 cbfk_table_name = clen;
349
350 ret = SQLFOREIGNKEYS( statement -> connection ,
351 statement -> driver_stmt,
352 as1,
353 cbpk_catalog_name,
354 as2,
355 cbpk_schema_name,
356 as3,
357 cbpk_table_name,
358 as4,
359 cbfk_catalog_name,
360 as5,
361 cbfk_schema_name,
362 as6,
363 cbfk_table_name );
364
365 if ( as1 ) free( as1 );
366 if ( as2 ) free( as2 );
367 if ( as3 ) free( as3 );
368 if ( as4 ) free( as4 );
369 if ( as5 ) free( as5 );
370 if ( as6 ) free( as6 );
371 }
372
373 if ( SQL_SUCCEEDED( ret ))
374 {
375#ifdef NR_PROBE
376 /********
377 * Added this to get num cols from drivers which can only tell
378 * us after execute - PAH
379 */
380
381 /*
382 * grab any errors
383 */
384
385 if ( ret == SQL_SUCCESS_WITH_INFO )
386 {
387 function_return_ex( IGNORE_THREAD, statement, ret, TRUE );
388 }
389
390 SQLNUMRESULTCOLS( statement -> connection,
391 statement -> driver_stmt, &statement -> numcols );
392 /******/
393#endif
394 statement -> hascols = 1;
395 statement -> state = STATE_S5;
396 statement -> prepared = 0;
397 }
398 else if ( ret == SQL_STILL_EXECUTING )
399 {
400 statement -> interupted_func = SQL_API_SQLFOREIGNKEYS;
401 if ( statement -> state != STATE_S11 &&
402 statement -> state != STATE_S12 )
403 statement -> state = STATE_S11;
404 }
405 else
406 {
407 statement -> state = STATE_S1;
408 }
409
410 if ( log_info.log_flag )
411 {
412 sprintf( statement -> msg,
413 "\n\t\tExit:[%s]",
414 __get_return_status( ret, s1 ));
415
416 dm_log_write( __FILE__,
417 __LINE__,
418 LOG_INFO,
419 LOG_INFO,
420 statement -> msg );
421 }
422
423 return function_return( SQL_HANDLE_STMT, statement, ret );
424}
425