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: SQLSpecialColumns.c,v 1.7 2009/02/18 17:59:08 lurcher Exp $
31 *
32 * $Log: SQLSpecialColumns.c,v $
33 * Revision 1.7 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.6 2004/01/12 09:54:39 lurcher
37 *
38 * Fix problem where STATE_S5 stops metadata calls
39 *
40 * Revision 1.5 2003/10/30 18:20:46 lurcher
41 *
42 * Fix broken thread protection
43 * Remove SQLNumResultCols after execute, lease S4/S% to driver
44 * Fix string overrun in SQLDriverConnect
45 * Add initial support for Interix
46 *
47 * Revision 1.4 2003/02/27 12:19:40 lurcher
48 *
49 * Add the A functions as well as the W
50 *
51 * Revision 1.3 2002/12/05 17:44:31 lurcher
52 *
53 * Display unknown return values in return logging
54 *
55 * Revision 1.2 2002/07/24 08:49:52 lurcher
56 *
57 * Alter UNICODE support to use iconv for UNICODE-ANSI conversion
58 *
59 * Revision 1.1.1.1 2001/10/17 16:40:07 lurcher
60 *
61 * First upload to SourceForge
62 *
63 * Revision 1.6 2001/07/03 09:30:41 nick
64 *
65 * Add ability to alter size of displayed message in the log
66 *
67 * Revision 1.5 2001/04/12 17:43:36 nick
68 *
69 * Change logging and added autotest to odbctest
70 *
71 * Revision 1.4 2000/12/31 20:30:54 nick
72 *
73 * Add UNICODE support
74 *
75 * Revision 1.3 2000/12/05 16:49:21 nick
76 *
77 * Add missing identifier_type in SQLSpecialColumns log
78 *
79 * Revision 1.2 2000/11/22 19:03:40 nick
80 *
81 * Fix problem with error status in SQLSpecialColumns
82 *
83 * Revision 1.1.1.1 2000/09/04 16:42:52 nick
84 * Imported Sources
85 *
86 * Revision 1.7 1999/11/13 23:41:01 ngorham
87 *
88 * Alter the way DM logging works
89 * Upgrade the Postgres driver to 6.4.6
90 *
91 * Revision 1.6 1999/10/24 23:54:19 ngorham
92 *
93 * First part of the changes to the error reporting
94 *
95 * Revision 1.5 1999/09/21 22:34:26 ngorham
96 *
97 * Improve performance by removing unneeded logging calls when logging is
98 * disabled
99 *
100 * Revision 1.4 1999/07/10 21:10:17 ngorham
101 *
102 * Adjust error sqlstate from driver manager, depending on requested
103 * version (ODBC2/3)
104 *
105 * Revision 1.3 1999/07/04 21:05:08 ngorham
106 *
107 * Add LGPL Headers to code
108 *
109 * Revision 1.2 1999/06/30 23:56:56 ngorham
110 *
111 * Add initial thread safety code
112 *
113 * Revision 1.1.1.1 1999/05/29 13:41:09 sShandyb
114 * first go at it
115 *
116 * Revision 1.1.1.1 1999/05/27 18:23:18 pharvey
117 * Imported sources
118 *
119 * Revision 1.3 1999/05/03 19:50:43 nick
120 * Another check point
121 *
122 * Revision 1.2 1999/04/30 16:22:47 nick
123 * Another checkpoint
124 *
125 * Revision 1.1 1999/04/25 23:06:11 nick
126 * Initial revision
127 *
128 *
129 **********************************************************************/
130
131#include <config.h>
132#include "drivermanager.h"
133
134static char const rcsid[]= "$RCSfile: SQLSpecialColumns.c,v $ $Revision: 1.7 $";
135
136SQLRETURN SQLSpecialColumnsA( SQLHSTMT statement_handle,
137 SQLUSMALLINT identifier_type,
138 SQLCHAR *catalog_name,
139 SQLSMALLINT name_length1,
140 SQLCHAR *schema_name,
141 SQLSMALLINT name_length2,
142 SQLCHAR *table_name,
143 SQLSMALLINT name_length3,
144 SQLUSMALLINT scope,
145 SQLUSMALLINT nullable )
146{
147 return SQLSpecialColumns( statement_handle,
148 identifier_type,
149 catalog_name,
150 name_length1,
151 schema_name,
152 name_length2,
153 table_name,
154 name_length3,
155 scope,
156 nullable );
157}
158
159SQLRETURN SQLSpecialColumns( SQLHSTMT statement_handle,
160 SQLUSMALLINT identifier_type,
161 SQLCHAR *catalog_name,
162 SQLSMALLINT name_length1,
163 SQLCHAR *schema_name,
164 SQLSMALLINT name_length2,
165 SQLCHAR *table_name,
166 SQLSMALLINT name_length3,
167 SQLUSMALLINT scope,
168 SQLUSMALLINT nullable )
169{
170 DMHSTMT statement = (DMHSTMT) statement_handle;
171 SQLRETURN ret;
172 SQLCHAR s1[ 100 + LOG_MESSAGE_LEN ], s2[ 100 + LOG_MESSAGE_LEN ], s3[ 100 + LOG_MESSAGE_LEN ];
173
174 /*
175 * check statement
176 */
177
178 if ( !__validate_stmt( statement ))
179 {
180 dm_log_write( __FILE__,
181 __LINE__,
182 LOG_INFO,
183 LOG_INFO,
184 "Error: SQL_INVALID_HANDLE" );
185
186 return SQL_INVALID_HANDLE;
187 }
188
189 function_entry( statement );
190
191 if ( log_info.log_flag )
192 {
193 sprintf( statement -> msg, "\n\t\tEntry:\
194\n\t\t\tStatement = %p\
195\n\t\t\tIdentifier Type = %d\
196\n\t\t\tCatalog Name = %s\
197\n\t\t\tSchema Name = %s\
198\n\t\t\tTable Name = %s\
199\n\t\t\tScope = %d\
200\n\t\t\tNullable = %d",
201 statement,
202 identifier_type,
203 __string_with_length( s1, catalog_name, name_length1 ),
204 __string_with_length( s2, schema_name, name_length2 ),
205 __string_with_length( s3, table_name, name_length3 ),
206 scope,
207 nullable );
208
209 dm_log_write( __FILE__,
210 __LINE__,
211 LOG_INFO,
212 LOG_INFO,
213 statement -> msg );
214 }
215
216 thread_protect( SQL_HANDLE_STMT, statement );
217
218 if ( identifier_type != SQL_BEST_ROWID &&
219 identifier_type != SQL_ROWVER )
220 {
221 dm_log_write( __FILE__,
222 __LINE__,
223 LOG_INFO,
224 LOG_INFO,
225 "Error: HY097" );
226
227 __post_internal_error( &statement -> error,
228 ERROR_HY097, NULL,
229 statement -> connection -> environment -> requested_version );
230
231 return function_return_nodrv( SQL_HANDLE_STMT, statement, SQL_ERROR );
232 }
233
234 if ( name_length1 < 0 && name_length1 != SQL_NTS ||
235 name_length2 < 0 && name_length2 != SQL_NTS )
236 {
237 __post_internal_error( &statement -> error,
238 ERROR_HY090, NULL,
239 statement -> connection -> environment -> requested_version );
240
241 return function_return_nodrv( SQL_HANDLE_STMT, statement, SQL_ERROR );
242 }
243
244 if ( table_name == NULL )
245 {
246 __post_internal_error( &statement -> error,
247 ERROR_HY009, NULL,
248 statement -> connection -> environment -> requested_version );
249
250 return function_return_nodrv( SQL_HANDLE_STMT, statement, SQL_ERROR );
251 }
252
253 if ( name_length3 < 0 && name_length3 != SQL_NTS )
254 {
255 __post_internal_error( &statement -> error,
256 ERROR_HY090, NULL,
257 statement -> connection -> environment -> requested_version );
258
259 return function_return_nodrv( SQL_HANDLE_STMT, statement, SQL_ERROR );
260 }
261
262 /*
263 * Check the SQL_ATTR_METADATA_ID settings
264 */
265
266 if ( statement -> metadata_id == SQL_TRUE &&
267 schema_name == NULL )
268 {
269 __post_internal_error( &statement -> error,
270 ERROR_HY009, NULL,
271 statement -> connection -> environment -> requested_version );
272
273 return function_return_nodrv( SQL_HANDLE_STMT, statement, SQL_ERROR );
274 }
275
276 if ( scope != SQL_SCOPE_CURROW &&
277 scope != SQL_SCOPE_TRANSACTION &&
278 scope != SQL_SCOPE_SESSION )
279 {
280 dm_log_write( __FILE__,
281 __LINE__,
282 LOG_INFO,
283 LOG_INFO,
284 "Error: HY098" );
285
286 __post_internal_error( &statement -> error,
287 ERROR_HY098, NULL,
288 statement -> connection -> environment -> requested_version );
289
290 return function_return_nodrv( SQL_HANDLE_STMT, statement, SQL_ERROR );
291 }
292
293 if ( nullable != SQL_NO_NULLS &&
294 nullable != SQL_NULLABLE )
295 {
296 dm_log_write( __FILE__,
297 __LINE__,
298 LOG_INFO,
299 LOG_INFO,
300 "Error: HY099" );
301
302 __post_internal_error( &statement -> error,
303 ERROR_HY099, NULL,
304 statement -> connection -> environment -> requested_version );
305
306 return function_return_nodrv( SQL_HANDLE_STMT, statement, SQL_ERROR );
307 }
308
309 /*
310 * check states
311 */
312
313#ifdef NR_PROBE
314 if ( statement -> state == STATE_S5 ||
315 statement -> state == STATE_S6 ||
316 statement -> state == STATE_S7 )
317#else
318 if ( statement -> state == STATE_S6 ||
319 statement -> state == STATE_S7 )
320#endif
321 {
322 dm_log_write( __FILE__,
323 __LINE__,
324 LOG_INFO,
325 LOG_INFO,
326 "Error: 2400" );
327
328 __post_internal_error( &statement -> error,
329 ERROR_24000, NULL,
330 statement -> connection -> environment -> requested_version );
331
332 return function_return_nodrv( SQL_HANDLE_STMT, statement, SQL_ERROR );
333 }
334 else if ( statement -> state == STATE_S8 ||
335 statement -> state == STATE_S9 ||
336 statement -> state == STATE_S10 ||
337 statement -> state == STATE_S13 ||
338 statement -> state == STATE_S14 ||
339 statement -> state == STATE_S15 )
340 {
341 dm_log_write( __FILE__,
342 __LINE__,
343 LOG_INFO,
344 LOG_INFO,
345 "Error: HY010" );
346
347 __post_internal_error( &statement -> error,
348 ERROR_HY010, NULL,
349 statement -> connection -> environment -> requested_version );
350
351 return function_return_nodrv( SQL_HANDLE_STMT, statement, SQL_ERROR );
352 }
353
354 if ( statement -> state == STATE_S11 ||
355 statement -> state == STATE_S12 )
356 {
357 if ( statement -> interupted_func != SQL_API_SQLSPECIALCOLUMNS )
358 {
359 dm_log_write( __FILE__,
360 __LINE__,
361 LOG_INFO,
362 LOG_INFO,
363 "Error: HY010" );
364
365 __post_internal_error( &statement -> error,
366 ERROR_HY010, NULL,
367 statement -> connection -> environment -> requested_version );
368
369 return function_return_nodrv( SQL_HANDLE_STMT, statement, SQL_ERROR );
370 }
371 }
372
373 if ( statement -> connection -> unicode_driver )
374 {
375 SQLWCHAR *s1, *s2, *s3;
376 int wlen;
377
378 if ( !CHECK_SQLSPECIALCOLUMNSW( statement -> connection ))
379 {
380 dm_log_write( __FILE__,
381 __LINE__,
382 LOG_INFO,
383 LOG_INFO,
384 "Error: IM001" );
385
386 __post_internal_error( &statement -> error,
387 ERROR_IM001, NULL,
388 statement -> connection -> environment -> requested_version );
389
390 return function_return_nodrv( SQL_HANDLE_STMT, statement, SQL_ERROR );
391 }
392
393 s1 = ansi_to_unicode_alloc( catalog_name, name_length1, statement -> connection, &wlen );
394 name_length1 = wlen;
395 s2 = ansi_to_unicode_alloc( schema_name, name_length2, statement -> connection, &wlen );
396 name_length2 = wlen;
397 s3 = ansi_to_unicode_alloc( table_name, name_length3, statement -> connection, &wlen );
398 name_length3 = wlen;
399
400 ret = SQLSPECIALCOLUMNSW( statement -> connection ,
401 statement -> driver_stmt,
402 identifier_type,
403 s1,
404 name_length1,
405 s2,
406 name_length2,
407 s3,
408 name_length3,
409 scope,
410 nullable );
411
412 if( s1 )
413 free( s1 );
414 if( s2 )
415 free( s2 );
416 if( s3 )
417 free( s3 );
418 }
419 else
420 {
421 if ( !CHECK_SQLSPECIALCOLUMNS( statement -> connection ))
422 {
423 dm_log_write( __FILE__,
424 __LINE__,
425 LOG_INFO,
426 LOG_INFO,
427 "Error: IM001" );
428
429 __post_internal_error( &statement -> error,
430 ERROR_IM001, NULL,
431 statement -> connection -> environment -> requested_version );
432
433 return function_return_nodrv( SQL_HANDLE_STMT, statement, SQL_ERROR );
434 }
435
436 ret = SQLSPECIALCOLUMNS( statement -> connection ,
437 statement -> driver_stmt,
438 identifier_type,
439 catalog_name,
440 name_length1,
441 schema_name,
442 name_length2,
443 table_name,
444 name_length3,
445 scope,
446 nullable );
447 }
448
449 if ( SQL_SUCCEEDED( ret ))
450 {
451#ifdef NR_PROBE
452 /********
453 * Added this to get num cols from drivers which can only tell
454 * us after execute - PAH
455 */
456 /*
457 ret = SQLNUMRESULTCOLS( statement -> connection,
458 statement -> driver_stmt, &statement -> numcols );
459 */
460 statement -> numcols = 1;
461 /******/
462#endif
463 statement -> hascols = 1;
464 statement -> state = STATE_S5;
465 statement -> prepared = 0;
466 }
467 else if ( ret == SQL_STILL_EXECUTING )
468 {
469 statement -> interupted_func = SQL_API_SQLSPECIALCOLUMNS;
470 if ( statement -> state != STATE_S11 &&
471 statement -> state != STATE_S12 )
472 statement -> state = STATE_S11;
473 }
474 else
475 {
476 statement -> state = STATE_S1;
477 }
478
479 if ( log_info.log_flag )
480 {
481 sprintf( statement -> msg,
482 "\n\t\tExit:[%s]",
483 __get_return_status( ret, s1 ));
484
485 dm_log_write( __FILE__,
486 __LINE__,
487 LOG_INFO,
488 LOG_INFO,
489 statement -> msg );
490 }
491
492 return function_return( SQL_HANDLE_STMT, statement, ret );
493}
494