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: SQLSpecialColumnsW.c,v 1.9 2009/02/18 17:59:08 lurcher Exp $
31 *
32 * $Log: SQLSpecialColumnsW.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:49 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:46 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:31 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:07 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: SQLSpecialColumnsW.c,v $";
89
90SQLRETURN SQLSpecialColumnsW( SQLHSTMT statement_handle,
91 SQLUSMALLINT identifier_type,
92 SQLWCHAR *catalog_name,
93 SQLSMALLINT name_length1,
94 SQLWCHAR *schema_name,
95 SQLSMALLINT name_length2,
96 SQLWCHAR *table_name,
97 SQLSMALLINT name_length3,
98 SQLUSMALLINT scope,
99 SQLUSMALLINT nullable )
100{
101 DMHSTMT statement = (DMHSTMT) statement_handle;
102 SQLRETURN ret;
103 SQLCHAR s1[ 100 + LOG_MESSAGE_LEN ], s2[ 100 + LOG_MESSAGE_LEN ], s3[ 100 + LOG_MESSAGE_LEN ];
104
105 /*
106 * check statement
107 */
108
109 if ( !__validate_stmt( statement ))
110 {
111 dm_log_write( __FILE__,
112 __LINE__,
113 LOG_INFO,
114 LOG_INFO,
115 "Error: SQL_INVALID_HANDLE" );
116
117#ifdef WITH_HANDLE_REDIRECT
118 {
119 DMHSTMT parent_statement;
120
121 parent_statement = find_parent_handle( statement, SQL_HANDLE_STMT );
122
123 if ( parent_statement ) {
124 dm_log_write( __FILE__,
125 __LINE__,
126 LOG_INFO,
127 LOG_INFO,
128 "Info: found parent handle" );
129
130 if ( CHECK_SQLSPECIALCOLUMNSW( parent_statement -> connection ))
131 {
132 dm_log_write( __FILE__,
133 __LINE__,
134 LOG_INFO,
135 LOG_INFO,
136 "Info: calling redirected driver function" );
137
138 return SQLSPECIALCOLUMNSW( parent_statement -> connection,
139 statement_handle,
140 identifier_type,
141 catalog_name,
142 name_length1,
143 schema_name,
144 name_length2,
145 table_name,
146 name_length3,
147 scope,
148 nullable );
149 }
150 }
151 }
152#endif
153 return SQL_INVALID_HANDLE;
154 }
155
156 function_entry( statement );
157
158 if ( log_info.log_flag )
159 {
160 sprintf( statement -> msg, "\n\t\tEntry:\
161\n\t\t\tStatement = %p\
162\n\t\t\tIdentifier Type = %d\
163\n\t\t\tCatalog Name = %s\
164\n\t\t\tSchema Name = %s\
165\n\t\t\tTable Name = %s\
166\n\t\t\tScope = %d\
167\n\t\t\tNullable = %d",
168 statement,
169 identifier_type,
170 __wstring_with_length( s1, catalog_name, name_length1 ),
171 __wstring_with_length( s2, schema_name, name_length2 ),
172 __wstring_with_length( s3, table_name, name_length3 ),
173 scope,
174 nullable );
175
176 dm_log_write( __FILE__,
177 __LINE__,
178 LOG_INFO,
179 LOG_INFO,
180 statement -> msg );
181 }
182
183 thread_protect( SQL_HANDLE_STMT, statement );
184
185 if ( identifier_type != SQL_BEST_ROWID &&
186 identifier_type != SQL_ROWVER )
187 {
188 dm_log_write( __FILE__,
189 __LINE__,
190 LOG_INFO,
191 LOG_INFO,
192 "Error: HY097" );
193
194 __post_internal_error( &statement -> error,
195 ERROR_HY097, NULL,
196 statement -> connection -> environment -> requested_version );
197
198 return function_return_nodrv( SQL_HANDLE_STMT, statement, SQL_ERROR );
199 }
200
201 if ( name_length1 < 0 && name_length1 != SQL_NTS ||
202 name_length2 < 0 && name_length2 != SQL_NTS )
203 {
204 __post_internal_error( &statement -> error,
205 ERROR_HY090, NULL,
206 statement -> connection -> environment -> requested_version );
207
208 return function_return_nodrv( SQL_HANDLE_STMT, statement, SQL_ERROR );
209 }
210
211 if ( table_name == NULL )
212 {
213 __post_internal_error( &statement -> error,
214 ERROR_HY009, NULL,
215 statement -> connection -> environment -> requested_version );
216
217 return function_return_nodrv( SQL_HANDLE_STMT, statement, SQL_ERROR );
218 }
219
220 if ( name_length3 < 0 && name_length3 != SQL_NTS )
221 {
222 __post_internal_error( &statement -> error,
223 ERROR_HY090, NULL,
224 statement -> connection -> environment -> requested_version );
225
226 return function_return_nodrv( SQL_HANDLE_STMT, statement, SQL_ERROR );
227 }
228
229 /*
230 * Check the SQL_ATTR_METADATA_ID settings
231 */
232
233 if ( statement -> metadata_id == SQL_TRUE &&
234 schema_name == NULL )
235 {
236 __post_internal_error( &statement -> error,
237 ERROR_HY009, NULL,
238 statement -> connection -> environment -> requested_version );
239
240 return function_return_nodrv( SQL_HANDLE_STMT, statement, SQL_ERROR );
241 }
242
243 if ( scope != SQL_SCOPE_CURROW &&
244 scope != SQL_SCOPE_TRANSACTION &&
245 scope != SQL_SCOPE_SESSION )
246 {
247 dm_log_write( __FILE__,
248 __LINE__,
249 LOG_INFO,
250 LOG_INFO,
251 "Error: HY098" );
252
253 __post_internal_error( &statement -> error,
254 ERROR_HY098, NULL,
255 statement -> connection -> environment -> requested_version );
256
257 return function_return_nodrv( SQL_HANDLE_STMT, statement, SQL_ERROR );
258 }
259
260 if ( nullable != SQL_NO_NULLS &&
261 nullable != SQL_NULLABLE )
262 {
263 dm_log_write( __FILE__,
264 __LINE__,
265 LOG_INFO,
266 LOG_INFO,
267 "Error: HY099" );
268
269 __post_internal_error( &statement -> error,
270 ERROR_HY099, NULL,
271 statement -> connection -> environment -> requested_version );
272
273 return function_return_nodrv( SQL_HANDLE_STMT, statement, SQL_ERROR );
274 }
275
276 /*
277 * check states
278 */
279
280#ifdef NR_PROBE
281 if ( statement -> state == STATE_S5 ||
282 statement -> state == STATE_S6 ||
283 statement -> state == STATE_S7 )
284#else
285 if ( statement -> state == STATE_S6 ||
286 statement -> state == STATE_S7 )
287#endif
288 {
289 dm_log_write( __FILE__,
290 __LINE__,
291 LOG_INFO,
292 LOG_INFO,
293 "Error: 2400" );
294
295 __post_internal_error( &statement -> error,
296 ERROR_24000, NULL,
297 statement -> connection -> environment -> requested_version );
298
299 return function_return_nodrv( SQL_HANDLE_STMT, statement, SQL_ERROR );
300 }
301 else if ( statement -> state == STATE_S8 ||
302 statement -> state == STATE_S9 ||
303 statement -> state == STATE_S10 ||
304 statement -> state == STATE_S13 ||
305 statement -> state == STATE_S14 ||
306 statement -> state == STATE_S15 )
307 {
308 dm_log_write( __FILE__,
309 __LINE__,
310 LOG_INFO,
311 LOG_INFO,
312 "Error: HY010" );
313
314 __post_internal_error( &statement -> error,
315 ERROR_HY010, NULL,
316 statement -> connection -> environment -> requested_version );
317
318 return function_return_nodrv( SQL_HANDLE_STMT, statement, SQL_ERROR );
319 }
320
321 if ( statement -> state == STATE_S11 ||
322 statement -> state == STATE_S12 )
323 {
324 if ( statement -> interupted_func != SQL_API_SQLSPECIALCOLUMNS )
325 {
326 dm_log_write( __FILE__,
327 __LINE__,
328 LOG_INFO,
329 LOG_INFO,
330 "Error: HY010" );
331
332 __post_internal_error( &statement -> error,
333 ERROR_HY010, NULL,
334 statement -> connection -> environment -> requested_version );
335
336 return function_return_nodrv( SQL_HANDLE_STMT, statement, SQL_ERROR );
337 }
338 }
339
340 if ( statement -> connection -> unicode_driver ||
341 CHECK_SQLSPECIALCOLUMNSW( statement -> connection ))
342 {
343 if ( !CHECK_SQLSPECIALCOLUMNSW( statement -> connection ))
344 {
345 dm_log_write( __FILE__,
346 __LINE__,
347 LOG_INFO,
348 LOG_INFO,
349 "Error: IM001" );
350
351 __post_internal_error( &statement -> error,
352 ERROR_IM001, NULL,
353 statement -> connection -> environment -> requested_version );
354
355 return function_return_nodrv( SQL_HANDLE_STMT, statement, SQL_ERROR );
356 }
357
358 ret = SQLSPECIALCOLUMNSW( statement -> connection ,
359 statement -> driver_stmt,
360 identifier_type,
361 catalog_name,
362 name_length1,
363 schema_name,
364 name_length2,
365 table_name,
366 name_length3,
367 scope,
368 nullable );
369 }
370 else
371 {
372 SQLCHAR *as1, *as2, *as3;
373 int clen;
374
375 if ( !CHECK_SQLSPECIALCOLUMNS( statement -> connection ))
376 {
377 dm_log_write( __FILE__,
378 __LINE__,
379 LOG_INFO,
380 LOG_INFO,
381 "Error: IM001" );
382
383 __post_internal_error( &statement -> error,
384 ERROR_IM001, NULL,
385 statement -> connection -> environment -> requested_version );
386
387 return function_return_nodrv( SQL_HANDLE_STMT, statement, SQL_ERROR );
388 }
389
390 as1 = (SQLCHAR*) unicode_to_ansi_alloc( catalog_name, name_length1, statement -> connection, &clen );
391 name_length1 = clen;
392 as2 = (SQLCHAR*) unicode_to_ansi_alloc( schema_name, name_length2, statement -> connection, &clen );
393 name_length2 = clen;
394 as3 = (SQLCHAR*) unicode_to_ansi_alloc( table_name, name_length3, statement -> connection, &clen );
395 name_length3 = clen;
396
397 ret = SQLSPECIALCOLUMNS( statement -> connection ,
398 statement -> driver_stmt,
399 identifier_type,
400 as1,
401 name_length1,
402 as2,
403 name_length2,
404 as3,
405 name_length3,
406 scope,
407 nullable );
408
409 if ( as1 ) free( as1 );
410 if ( as2 ) free( as2 );
411 if ( as3 ) free( as3 );
412 }
413
414 if ( SQL_SUCCEEDED( ret ))
415 {
416#ifdef NR_PROBE
417 /********
418 * Added this to get num cols from drivers which can only tell
419 * us after execute - PAH
420 */
421 /*
422 ret = SQLNUMRESULTCOLS( statement -> connection,
423 statement -> driver_stmt, &statement -> numcols );
424 */
425 statement -> numcols = 1;
426 /******/
427#endif
428 statement -> hascols = 1;
429 statement -> state = STATE_S5;
430 statement -> prepared = 0;
431 }
432 else if ( ret == SQL_STILL_EXECUTING )
433 {
434 statement -> interupted_func = SQL_API_SQLSPECIALCOLUMNS;
435 if ( statement -> state != STATE_S11 &&
436 statement -> state != STATE_S12 )
437 statement -> state = STATE_S11;
438 }
439 else
440 {
441 statement -> state = STATE_S1;
442 }
443
444 if ( log_info.log_flag )
445 {
446 sprintf( statement -> msg,
447 "\n\t\tExit:[%s]",
448 __get_return_status( ret, s1 ));
449
450 dm_log_write( __FILE__,
451 __LINE__,
452 LOG_INFO,
453 LOG_INFO,
454 statement -> msg );
455 }
456
457 return function_return( SQL_HANDLE_STMT, statement, ret );
458}
459