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: SQLTables.c,v 1.7 2009/02/18 17:59:08 lurcher Exp $
31 *
32 * $Log: SQLTables.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.4 2001/07/03 09:30:41 nick
64 *
65 * Add ability to alter size of displayed message in the log
66 *
67 * Revision 1.3 2001/04/12 17:43:36 nick
68 *
69 * Change logging and added autotest to odbctest
70 *
71 * Revision 1.2 2000/12/31 20:30:54 nick
72 *
73 * Add UNICODE support
74 *
75 * Revision 1.1.1.1 2000/09/04 16:42:52 nick
76 * Imported Sources
77 *
78 * Revision 1.8 2000/08/16 14:31:11 ngorham
79 *
80 * Add fix for broken version of EXCEL
81 *
82 * Revision 1.7 1999/11/13 23:41:01 ngorham
83 *
84 * Alter the way DM logging works
85 * Upgrade the Postgres driver to 6.4.6
86 *
87 * Revision 1.6 1999/10/24 23:54:19 ngorham
88 *
89 * First part of the changes to the error reporting
90 *
91 * Revision 1.5 1999/09/21 22:34:26 ngorham
92 *
93 * Improve performance by removing unneeded logging calls when logging is
94 * disabled
95 *
96 * Revision 1.4 1999/07/10 21:10:17 ngorham
97 *
98 * Adjust error sqlstate from driver manager, depending on requested
99 * version (ODBC2/3)
100 *
101 * Revision 1.3 1999/07/04 21:05:08 ngorham
102 *
103 * Add LGPL Headers to code
104 *
105 * Revision 1.2 1999/06/30 23:56:56 ngorham
106 *
107 * Add initial thread safety code
108 *
109 * Revision 1.1.1.1 1999/05/29 13:41:09 sShandyb
110 * first go at it
111 *
112 * Revision 1.2 1999/06/07 01:29:31 pharvey
113 * *** empty log message ***
114 *
115 * Revision 1.1.1.1 1999/05/27 18:23:18 pharvey
116 * Imported sources
117 *
118 * Revision 1.4 1999/05/03 19:50:43 nick
119 * Another check point
120 *
121 * Revision 1.3 1999/04/30 16:22:47 nick
122 * Another checkpoint
123 *
124 * Revision 1.2 1999/04/29 20:47:37 nick
125 * Another checkpoint
126 *
127 * Revision 1.1 1999/04/25 23:06:11 nick
128 * Initial revision
129 *
130 *
131 **********************************************************************/
132
133#include <config.h>
134#include "drivermanager.h"
135
136static char const rcsid[]= "$RCSfile: SQLTables.c,v $ $Revision: 1.7 $";
137
138SQLRETURN SQLTablesA( SQLHSTMT statement_handle,
139 SQLCHAR *catalog_name,
140 SQLSMALLINT name_length1,
141 SQLCHAR *schema_name,
142 SQLSMALLINT name_length2,
143 SQLCHAR *table_name,
144 SQLSMALLINT name_length3,
145 SQLCHAR *table_type,
146 SQLSMALLINT name_length4 )
147{
148 return SQLTables( statement_handle,
149 catalog_name,
150 name_length1,
151 schema_name,
152 name_length2,
153 table_name,
154 name_length3,
155 table_type,
156 name_length4 );
157}
158
159SQLRETURN SQLTables( SQLHSTMT statement_handle,
160 SQLCHAR *catalog_name,
161 SQLSMALLINT name_length1,
162 SQLCHAR *schema_name,
163 SQLSMALLINT name_length2,
164 SQLCHAR *table_name,
165 SQLSMALLINT name_length3,
166 SQLCHAR *table_type,
167 SQLSMALLINT name_length4 )
168{
169 DMHSTMT statement = (DMHSTMT) statement_handle;
170 SQLRETURN ret;
171 SQLCHAR s1[ 100 + LOG_MESSAGE_LEN ], s2[ 100 + LOG_MESSAGE_LEN ], s3[ 100 + LOG_MESSAGE_LEN ], s4[ 100 + LOG_MESSAGE_LEN ];
172
173 /*
174 * check statement
175 */
176 if ( !__validate_stmt( statement ))
177 {
178 dm_log_write( __FILE__,
179 __LINE__,
180 LOG_INFO,
181 LOG_INFO,
182 "Error: SQL_INVALID_HANDLE" );
183
184 return SQL_INVALID_HANDLE;
185 }
186
187 function_entry( statement );
188
189 if ( log_info.log_flag )
190 {
191 sprintf( statement -> msg, "\n\t\tEntry:\
192\n\t\t\tStatement = %p\
193\n\t\t\tCatalog Name = %s\
194\n\t\t\tSchema Name = %s\
195\n\t\t\tTable Name = %s\
196\n\t\t\tTable Type = %s",
197 statement,
198 __string_with_length( s1, catalog_name, name_length1 ),
199 __string_with_length( s2, schema_name, name_length2 ),
200 __string_with_length( s3, table_name, name_length3 ),
201 __string_with_length( s4, table_type, name_length4 ));
202
203 dm_log_write( __FILE__,
204 __LINE__,
205 LOG_INFO,
206 LOG_INFO,
207 statement -> msg );
208 }
209
210 thread_protect( SQL_HANDLE_STMT, statement );
211
212 /*
213 * this is a fix for old version of EXCEL
214 */
215
216 if ( !catalog_name )
217 name_length1 = 0;
218 if ( !schema_name )
219 name_length2 = 0;
220 if ( !table_name )
221 name_length3 = 0;
222 if ( !table_type )
223 name_length4 = 0;
224
225 if (( name_length1 < 0 && name_length1 != SQL_NTS ) ||
226 ( name_length2 < 0 && name_length2 != SQL_NTS ) ||
227 ( name_length3 < 0 && name_length3 != SQL_NTS ) ||
228 ( name_length4 < 0 && name_length4 != SQL_NTS ))
229 {
230 dm_log_write( __FILE__,
231 __LINE__,
232 LOG_INFO,
233 LOG_INFO,
234 "Error: HY090" );
235
236 __post_internal_error( &statement -> error,
237 ERROR_HY090, NULL,
238 statement -> connection -> environment -> requested_version );
239
240 return function_return_nodrv( SQL_HANDLE_STMT, statement, SQL_ERROR );
241 }
242
243 /*
244 * check states
245 */
246
247#ifdef NR_PROBE
248 if ( statement -> state == STATE_S5 ||
249 statement -> state == STATE_S6 ||
250 statement -> state == STATE_S7 )
251#else
252 if (( statement -> state == STATE_S6 && statement -> eod == 0 ) ||
253 statement -> state == STATE_S7 )
254#endif
255 {
256 dm_log_write( __FILE__,
257 __LINE__,
258 LOG_INFO,
259 LOG_INFO,
260 "Error: 24000" );
261
262 __post_internal_error( &statement -> error,
263 ERROR_24000, NULL,
264 statement -> connection -> environment -> requested_version );
265
266 return function_return_nodrv( SQL_HANDLE_STMT, statement, SQL_ERROR );
267 }
268 else if ( statement -> state == STATE_S8 ||
269 statement -> state == STATE_S9 ||
270 statement -> state == STATE_S10 ||
271 statement -> state == STATE_S13 ||
272 statement -> state == STATE_S14 ||
273 statement -> state == STATE_S15 )
274 {
275 dm_log_write( __FILE__,
276 __LINE__,
277 LOG_INFO,
278 LOG_INFO,
279 "Error: HY010" );
280
281 __post_internal_error( &statement -> error,
282 ERROR_HY010, NULL,
283 statement -> connection -> environment -> requested_version );
284
285 return function_return_nodrv( SQL_HANDLE_STMT, statement, SQL_ERROR );
286 }
287
288 if ( statement -> state == STATE_S11 ||
289 statement -> state == STATE_S12 )
290 {
291 if ( statement -> interupted_func != SQL_API_SQLTABLES )
292 {
293 dm_log_write( __FILE__,
294 __LINE__,
295 LOG_INFO,
296 LOG_INFO,
297 "Error: HY010" );
298
299 __post_internal_error( &statement -> error,
300 ERROR_HY010, NULL,
301 statement -> connection -> environment -> requested_version );
302
303 return function_return_nodrv( SQL_HANDLE_STMT, statement, SQL_ERROR );
304 }
305 }
306
307 /*
308 * TO_DO Check the SQL_ATTR_METADATA_ID settings
309 */
310
311 if ( statement -> connection -> unicode_driver )
312 {
313 int wlen;
314 SQLWCHAR *s1, *s2, *s3, *s4;
315
316 if ( !CHECK_SQLTABLESW( statement -> connection ))
317 {
318 dm_log_write( __FILE__,
319 __LINE__,
320 LOG_INFO,
321 LOG_INFO,
322 "Error: IM001" );
323
324 __post_internal_error( &statement -> error,
325 ERROR_IM001, NULL,
326 statement -> connection -> environment -> requested_version );
327
328 return function_return_nodrv( SQL_HANDLE_STMT, statement, SQL_ERROR );
329 }
330
331 s1 = ansi_to_unicode_alloc( catalog_name, name_length1, statement -> connection, &wlen );
332 name_length1 = wlen;
333 s2 = ansi_to_unicode_alloc( schema_name, name_length2, statement -> connection, &wlen );
334 name_length2 = wlen;
335 s3 = ansi_to_unicode_alloc( table_name, name_length3, statement -> connection, &wlen );
336 name_length3 = wlen;
337 s4 = ansi_to_unicode_alloc( table_type, name_length4, statement -> connection, &wlen );
338 name_length4 = wlen;
339
340 ret = SQLTABLESW( statement -> connection ,
341 statement -> driver_stmt,
342 s1,
343 name_length1,
344 s2,
345 name_length2,
346 s3,
347 name_length3,
348 s4,
349 name_length4 );
350
351 if( s1 )
352 free( s1 );
353 if( s2 )
354 free( s2 );
355 if( s3 )
356 free( s3 );
357 if( s4 )
358 free( s4 );
359 }
360 else
361 {
362 if ( !CHECK_SQLTABLES( statement -> connection ))
363 {
364 dm_log_write( __FILE__,
365 __LINE__,
366 LOG_INFO,
367 LOG_INFO,
368 "Error: IM001" );
369
370 __post_internal_error( &statement -> error,
371 ERROR_IM001, NULL,
372 statement -> connection -> environment -> requested_version );
373
374 return function_return_nodrv( SQL_HANDLE_STMT, statement, SQL_ERROR );
375 }
376
377 ret = SQLTABLES( statement -> connection ,
378 statement -> driver_stmt,
379 catalog_name,
380 name_length1,
381 schema_name,
382 name_length2,
383 table_name,
384 name_length3,
385 table_type,
386 name_length4 );
387 }
388
389 if ( SQL_SUCCEEDED( ret ))
390 {
391#ifdef NR_PROBE
392 /********
393 * Added this to get num cols from drivers which can only tell
394 * us after execute - PAH
395 */
396 /*
397 * There is no point in doing this as we can't trust the value
398 * from SQLPrepare, so we can't perform checks on the column number
399 *
400 ret = SQLNUMRESULTCOLS( statement -> connection,
401 statement -> driver_stmt, &statement -> numcols );
402 */
403 statement -> numcols = 1;
404 /******/
405#endif
406 statement -> hascols = 1;
407 statement -> state = STATE_S5;
408 statement -> prepared = 0;
409 }
410 else if ( ret == SQL_STILL_EXECUTING )
411 {
412 statement -> interupted_func = SQL_API_SQLTABLES;
413 if ( statement -> state != STATE_S11 &&
414 statement -> state != STATE_S12 )
415 statement -> state = STATE_S11;
416 }
417 else
418 {
419 statement -> state = STATE_S1;
420 }
421
422 if ( log_info.log_flag )
423 {
424 sprintf( statement -> msg,
425 "\n\t\tExit:[%s]",
426 __get_return_status( ret, s1 ));
427
428 dm_log_write( __FILE__,
429 __LINE__,
430 LOG_INFO,
431 LOG_INFO,
432 statement -> msg );
433 }
434
435 return function_return( SQL_HANDLE_STMT, statement, ret );
436}
437