]> git.saurik.com Git - wxWidgets.git/blame - src/iodbc/info.c
End of stream reading stuff
[wxWidgets.git] / src / iodbc / info.c
CommitLineData
cd5bf2a6
RR
1/*
2 * info.c
3 *
4 * $Id$
5 *
6 * Information functions
7 *
8 * The iODBC driver manager.
9 *
10 * Copyright (C) 1995 by Ke Jin <kejin@empress.com>
11 *
12 * This library is free software; you can redistribute it and/or
13 * modify it under the terms of the GNU Library General Public
14 * License as published by the Free Software Foundation; either
15 * version 2 of the License, or (at your option) any later version.
16 *
17 * This library is distributed in the hope that it will be useful,
18 * but WITHOUT ANY WARRANTY; without even the implied warranty of
19 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
20 * Library General Public License for more details.
21 *
22 * You should have received a copy of the GNU Library General Public
23 * License along with this library; if not, write to the Free
24 * Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
25 */
26
88ac883a 27#include "config.h"
cd5bf2a6 28
88ac883a
VZ
29#include "isql.h"
30#include "isqlext.h"
cd5bf2a6 31
88ac883a 32#include "dlproc.h"
cd5bf2a6 33
88ac883a
VZ
34#include "herr.h"
35#include "henv.h"
36#include "hdbc.h"
37#include "hstmt.h"
cd5bf2a6 38
88ac883a 39#include "itrace.h"
cd5bf2a6
RR
40
41#include <stdio.h>
42#include <ctype.h>
43
44#define SECT1 "ODBC Data Sources"
45#define SECT2 "Default"
46#define MAX_ENTRIES 1024
47
48extern char * _iodbcdm_getinifile (char *buf, int size);
49extern char * _iodbcdm_getkeyvalbydsn (char *dsn, int dsnlen, char *keywd, char *value, int size);
50
51static int
52stricmp (const char *s1, const char *s2)
1a6944fd 53{
cd5bf2a6
RR
54 int cmp;
55
56 while (*s1)
57 {
58 if ((cmp = toupper (*s1) - toupper (*s2)) != 0)
59 return cmp;
60 s1++;
61 s2++;
62 }
63 return (*s2) ? -1 : 0;
64}
7e616b10 65
cd5bf2a6
RR
66static int
67SectSorter (const void *p1, const void *p2)
68{
69 char **s1 = (char **) p1;
70 char **s2 = (char **) p2;
7e616b10 71
cd5bf2a6
RR
72 return stricmp (*s1, *s2);
73}
7e616b10 74
7e616b10 75
cd5bf2a6
RR
76RETCODE SQL_API
77SQLDataSources (
78 HENV henv,
79 UWORD fDir,
80 UCHAR FAR * szDSN,
81 SWORD cbDSNMax,
82 SWORD FAR * pcbDSN,
83 UCHAR FAR * szDesc,
84 SWORD cbDescMax,
85 SWORD FAR * pcbDesc)
86{
87 GENV_t FAR *genv = (GENV_t FAR *) henv;
88 char *path;
89 char buf[1024];
90 FILE *fp;
91 int i;
92 static int cur_entry = -1;
93 static int num_entries = 0;
94 static char **sect = NULL;
95
96 if (henv == SQL_NULL_HENV)
97 {
98 return SQL_INVALID_HANDLE;
99 }
100 /* check argument */
101 if (cbDSNMax < 0 || cbDescMax < 0)
102 {
103 PUSHSQLERR (genv->herr, en_S1090);
104
105 return SQL_ERROR;
106 }
107 if (fDir != SQL_FETCH_FIRST
108 && fDir != SQL_FETCH_NEXT)
109 {
110 PUSHSQLERR (genv->herr, en_S1103);
111
112 return SQL_ERROR;
113 }
114 if (cur_entry < 0 || fDir == SQL_FETCH_FIRST)
115 {
116 cur_entry = 0;
117 num_entries = 0;
118
119
120 /*
121 * Open the odbc.ini file
122 */
123 path = (char *) _iodbcdm_getinifile (buf, sizeof (buf));
124 if ((fp = fopen (path, "r")) == NULL)
125 {
126 return SQL_NO_DATA_FOUND;
127 }
128 /*
129 * Free old section list
130 */
131 if (sect)
132 {
133 for (i = 0; i < MAX_ENTRIES; i++)
134 if (sect[i])
135 free (sect[i]);
136 free (sect);
137 }
138 if ((sect = (char **) calloc (MAX_ENTRIES, sizeof (char *))) == NULL)
139 {
140 PUSHSQLERR (genv->herr, en_S1011);
141
142 return SQL_ERROR;
143 }
144 /*
145 * Build a dynamic list of sections
146 */
147 while (1)
148 {
149 char *str, *p;
150
151 str = fgets (buf, sizeof (buf), fp);
152
153 if (str == NULL)
154 break;
155
156 if (*str == '[')
157 {
158 str++;
159 for (p = str; *p; p++)
160 if (*p == ']')
161 *p = '\0';
162
163 if (!strcmp (str, SECT1))
164 continue;
165 if (!strcmp (str, SECT2))
166 continue;
167
168 /*
169 * Add this section to the comma separated list
170 */
171 if (num_entries >= MAX_ENTRIES)
172 break; /* Skip the rest */
173
174 sect[num_entries++] = (char *) strdup (str);
175 }
176 }
177
178 /*
179 * Sort all entries so we can present a nice list
180 */
181 if (num_entries > 1)
182 qsort (sect, num_entries, sizeof (char *), SectSorter);
183 }
184 /*
185 * Try to get to the next item
186 */
187 if (cur_entry >= num_entries)
188 {
189 cur_entry = 0; /* Next time, start all over again */
190 return SQL_NO_DATA_FOUND;
191 }
192 /*
193 * Copy DSN information
194 */
195 STRNCPY (szDSN, sect[cur_entry], cbDSNMax);
0bd55cfa
GT
196/*
197glt??? pcbDSN = strlen(szDSN);
198*/
cd5bf2a6
RR
199 /*
200 * And find the description that goes with this entry
201 */
202 _iodbcdm_getkeyvalbydsn (sect[cur_entry], strlen (sect[cur_entry]),
11e1c70d 203 "Description", (char*) szDesc, cbDescMax);
0bd55cfa
GT
204/*
205glt??? pcbDesc = strlen(szDesc);
206*/
cd5bf2a6
RR
207 /*
208 * Next record
209 */
210 cur_entry++;
211
212 return SQL_SUCCESS;
7e616b10
RR
213}
214
cd5bf2a6
RR
215
216RETCODE SQL_API
217SQLDrivers (
218 HENV henv,
219 UWORD fDir,
220 UCHAR FAR * szDrvDesc,
221 SWORD cbDrvDescMax,
222 SWORD FAR * pcbDrvDesc,
223 UCHAR FAR * szDrvAttr,
224 SWORD cbDrvAttrMax,
225 SWORD FAR * pcbDrvAttr)
1a6944fd 226{
cd5bf2a6 227 GENV_t FAR *genv = (GENV_t FAR *) henv;
7e616b10 228
cd5bf2a6
RR
229 if (henv == SQL_NULL_HENV)
230 {
231 return SQL_INVALID_HANDLE;
232 }
7e616b10 233
cd5bf2a6
RR
234 if (cbDrvDescMax < 0 || cbDrvAttrMax < 0 || cbDrvAttrMax == 1)
235 {
236 PUSHSQLERR (genv->herr, en_S1090);
7e616b10 237
cd5bf2a6
RR
238 return SQL_ERROR;
239 }
7e616b10 240
cd5bf2a6
RR
241 if (fDir != SQL_FETCH_FIRST || fDir != SQL_FETCH_NEXT)
242 {
243 PUSHSQLERR (genv->herr, en_S1103);
7e616b10 244
cd5bf2a6
RR
245 return SQL_ERROR;
246 }
7e616b10 247
cd5bf2a6
RR
248/*********************/
249 return SQL_NO_DATA_FOUND;
1a6944fd
RR
250}
251
252
cd5bf2a6
RR
253RETCODE SQL_API
254SQLGetInfo (
255 HDBC hdbc,
256 UWORD fInfoType,
257 PTR rgbInfoValue,
258 SWORD cbInfoValueMax,
259 SWORD FAR * pcbInfoValue)
1a6944fd 260{
cd5bf2a6
RR
261 DBC_t FAR *pdbc = (DBC_t FAR *) hdbc;
262 ENV_t FAR *penv;
263 STMT_t FAR *pstmt = NULL;
264 STMT_t FAR *tpstmt;
265 HPROC hproc;
266 RETCODE retcode = SQL_SUCCESS;
267
268 DWORD dword;
269 int size = 0, len = 0;
270 char buf[16] = {'\0'};
271
272 if (hdbc == SQL_NULL_HDBC || pdbc->henv == SQL_NULL_HENV)
273 {
274 return SQL_INVALID_HANDLE;
275 }
276
277 if (cbInfoValueMax < 0)
278 {
279 PUSHSQLERR (pdbc->herr, en_S1090);
280
281 return SQL_ERROR;
282 }
283
284 if ( /* fInfoType < SQL_INFO_FIRST || */
285 (fInfoType > SQL_INFO_LAST
286 && fInfoType < SQL_INFO_DRIVER_START))
287 {
288 PUSHSQLERR (pdbc->herr, en_S1096);
289
290 return SQL_ERROR;
291 }
292
293 if (fInfoType == SQL_ODBC_VER)
294 {
295 sprintf (buf, "%02d.%02d",
296 (ODBCVER) >> 8, 0x00FF & (ODBCVER));
297
298
299 if (rgbInfoValue != NULL
300 && cbInfoValueMax > 0)
301 {
302 len = STRLEN (buf);
303
304 if (len < cbInfoValueMax - 1)
305 {
306 len = cbInfoValueMax - 1;
307 PUSHSQLERR (pdbc->herr, en_01004);
308
309 retcode = SQL_SUCCESS_WITH_INFO;
310 }
311
312 STRNCPY (rgbInfoValue, buf, len);
313 ((char FAR *) rgbInfoValue)[len] = '\0';
314 }
315
316 if (pcbInfoValue != NULL)
317 {
318 *pcbInfoValue = (SWORD) len;
319 }
320
321 return retcode;
322 }
323
324 if (pdbc->state == en_dbc_allocated || pdbc->state == en_dbc_needdata)
325 {
326 PUSHSQLERR (pdbc->herr, en_08003);
327
328 return SQL_ERROR;
329 }
330
331 switch (fInfoType)
332 {
333 case SQL_DRIVER_HDBC:
334 dword = (DWORD) (pdbc->dhdbc);
335 size = sizeof (dword);
336 break;
337
338 case SQL_DRIVER_HENV:
339 penv = (ENV_t FAR *) (pdbc->henv);
340 dword = (DWORD) (penv->dhenv);
341 size = sizeof (dword);
342 break;
343
344 case SQL_DRIVER_HLIB:
345 penv = (ENV_t FAR *) (pdbc->henv);
346 dword = (DWORD) (penv->hdll);
347 size = sizeof (dword);
348 break;
349
350 case SQL_DRIVER_HSTMT:
351 if (rgbInfoValue != NULL)
352 {
353 pstmt = *((STMT_t FAR **) rgbInfoValue);
354 }
355
356 for (tpstmt = (STMT_t FAR *) (pdbc->hstmt);
357 tpstmt != NULL;
358 tpstmt = tpstmt->next)
359 {
360 if (tpstmt == pstmt)
361 {
362 break;
363 }
364 }
365
366 if (tpstmt == NULL)
367 {
368 PUSHSQLERR (pdbc->herr, en_S1009);
369
370 return SQL_ERROR;
371 }
372
373 dword = (DWORD) (pstmt->dhstmt);
374 size = sizeof (dword);
375 break;
376
377 default:
378 break;
379 }
380
381 if (size)
382 {
383 if (rgbInfoValue != NULL)
384 {
385 *((DWORD *) rgbInfoValue) = dword;
386 }
387
388 if (pcbInfoValue != NULL)
389 {
390 *(pcbInfoValue) = (SWORD) size;
391 }
392
393 return SQL_SUCCESS;
394 }
395
396 hproc = _iodbcdm_getproc (hdbc, en_GetInfo);
397
398 if (hproc == SQL_NULL_HPROC)
399 {
400 PUSHSQLERR (pdbc->herr, en_IM001);
401
402 return SQL_ERROR;
403 }
404
405 CALL_DRIVER (hdbc, retcode, hproc, en_GetInfo,
406 (pdbc->dhdbc, fInfoType, rgbInfoValue, cbInfoValueMax, pcbInfoValue))
407
408 if (retcode == SQL_ERROR
409 && fInfoType == SQL_DRIVER_ODBC_VER)
410 {
411 STRCPY (buf, "01.00");
412
413 if (rgbInfoValue != NULL
414 && cbInfoValueMax > 0)
415 {
416 len = STRLEN (buf);
417
418 if (len < cbInfoValueMax - 1)
419 {
420 len = cbInfoValueMax - 1;
421 PUSHSQLERR (pdbc->herr, en_01004);
422 }
423
424 STRNCPY (rgbInfoValue, buf, len);
425 ((char FAR *) rgbInfoValue)[len] = '\0';
426 }
427
428 if (pcbInfoValue != NULL)
429 {
430 *pcbInfoValue = (SWORD) len;
431 }
432
433 /* what should we return in this case ???? */
434 }
435
436 return retcode;
7e616b10 437}
1a6944fd 438
cd5bf2a6
RR
439
440RETCODE SQL_API
441SQLGetFunctions (
442 HDBC hdbc,
443 UWORD fFunc,
444 UWORD FAR * pfExists)
1a6944fd 445{
cd5bf2a6
RR
446 DBC_t FAR *pdbc = (DBC_t FAR *) hdbc;
447 HPROC hproc;
448 RETCODE retcode;
449
450 if (hdbc == SQL_NULL_HDBC)
451 {
452 return SQL_INVALID_HANDLE;
453 }
454
455 if (fFunc > SQL_EXT_API_LAST)
456 {
457 PUSHSQLERR (pdbc->herr, en_S1095);
458
459 return SQL_ERROR;
460 }
461
462 if (pdbc->state == en_dbc_allocated
463 || pdbc->state == en_dbc_needdata)
464 {
465 PUSHSQLERR (pdbc->herr, en_S1010);
466
467 return SQL_ERROR;
468 }
469
470 if (pfExists == NULL)
471 {
472 return SQL_SUCCESS;
473 }
474
475 hproc = _iodbcdm_getproc (hdbc, en_GetFunctions);
476
477 if (hproc != SQL_NULL_HPROC)
478 {
479 CALL_DRIVER (hdbc, retcode, hproc, en_GetFunctions,
480 (pdbc->dhdbc, fFunc, pfExists))
481
482 return retcode;
483 }
484
485 if (fFunc == SQL_API_SQLSETPARAM)
486 {
487 fFunc = SQL_API_SQLBINDPARAMETER;
488 }
489
490 if (fFunc != SQL_API_ALL_FUNCTIONS)
491 {
492 hproc = _iodbcdm_getproc (hdbc, fFunc);
493
494 if (hproc == SQL_NULL_HPROC)
495 {
496 *pfExists = (UWORD) 0;
497 }
498 else
499 {
500 *pfExists = (UWORD) 1;
501 }
502
503 return SQL_SUCCESS;
504 }
505
506 for (fFunc = 0; fFunc < 100; fFunc++)
507 {
508 hproc = _iodbcdm_getproc (hdbc, fFunc);
509
510 if (hproc == SQL_NULL_HPROC)
511 {
512 pfExists[fFunc] = (UWORD) 0;
513 }
514 else
515 {
516 pfExists[fFunc] = (UWORD) 1;
517 }
518 }
519
520 return SQL_SUCCESS;
1a6944fd 521}