]> git.saurik.com Git - wxWidgets.git/blob - src/iodbc/info.c
OnEnter/OnDragOver API update (compiles, links, somewhat runs under wxGTK)
[wxWidgets.git] / src / iodbc / info.c
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
27 #include "config.h"
28
29 #include "isql.h"
30 #include "isqlext.h"
31
32 #include "dlproc.h"
33
34 #include "herr.h"
35 #include "henv.h"
36 #include "hdbc.h"
37 #include "hstmt.h"
38
39 #include "itrace.h"
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
48 extern char * _iodbcdm_getinifile (char *buf, int size);
49 extern char * _iodbcdm_getkeyvalbydsn (char *dsn, int dsnlen, char *keywd, char *value, int size);
50
51 static int
52 stricmp (const char *s1, const char *s2)
53 {
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 }
65
66 static int
67 SectSorter (const void *p1, const void *p2)
68 {
69 char **s1 = (char **) p1;
70 char **s2 = (char **) p2;
71
72 return stricmp (*s1, *s2);
73 }
74
75
76 RETCODE SQL_API
77 SQLDataSources (
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);
196
197 /*
198 * And find the description that goes with this entry
199 */
200 _iodbcdm_getkeyvalbydsn (sect[cur_entry], strlen (sect[cur_entry]),
201 "Description", szDesc, cbDescMax);
202
203 /*
204 * Next record
205 */
206 cur_entry++;
207
208 return SQL_SUCCESS;
209 }
210
211
212 RETCODE SQL_API
213 SQLDrivers (
214 HENV henv,
215 UWORD fDir,
216 UCHAR FAR * szDrvDesc,
217 SWORD cbDrvDescMax,
218 SWORD FAR * pcbDrvDesc,
219 UCHAR FAR * szDrvAttr,
220 SWORD cbDrvAttrMax,
221 SWORD FAR * pcbDrvAttr)
222 {
223 GENV_t FAR *genv = (GENV_t FAR *) henv;
224
225 if (henv == SQL_NULL_HENV)
226 {
227 return SQL_INVALID_HANDLE;
228 }
229
230 if (cbDrvDescMax < 0 || cbDrvAttrMax < 0 || cbDrvAttrMax == 1)
231 {
232 PUSHSQLERR (genv->herr, en_S1090);
233
234 return SQL_ERROR;
235 }
236
237 if (fDir != SQL_FETCH_FIRST || fDir != SQL_FETCH_NEXT)
238 {
239 PUSHSQLERR (genv->herr, en_S1103);
240
241 return SQL_ERROR;
242 }
243
244 /*********************/
245 return SQL_NO_DATA_FOUND;
246 }
247
248
249 RETCODE SQL_API
250 SQLGetInfo (
251 HDBC hdbc,
252 UWORD fInfoType,
253 PTR rgbInfoValue,
254 SWORD cbInfoValueMax,
255 SWORD FAR * pcbInfoValue)
256 {
257 DBC_t FAR *pdbc = (DBC_t FAR *) hdbc;
258 ENV_t FAR *penv;
259 STMT_t FAR *pstmt = NULL;
260 STMT_t FAR *tpstmt;
261 HPROC hproc;
262 RETCODE retcode = SQL_SUCCESS;
263
264 DWORD dword;
265 int size = 0, len = 0;
266 char buf[16] = {'\0'};
267
268 if (hdbc == SQL_NULL_HDBC || pdbc->henv == SQL_NULL_HENV)
269 {
270 return SQL_INVALID_HANDLE;
271 }
272
273 if (cbInfoValueMax < 0)
274 {
275 PUSHSQLERR (pdbc->herr, en_S1090);
276
277 return SQL_ERROR;
278 }
279
280 if ( /* fInfoType < SQL_INFO_FIRST || */
281 (fInfoType > SQL_INFO_LAST
282 && fInfoType < SQL_INFO_DRIVER_START))
283 {
284 PUSHSQLERR (pdbc->herr, en_S1096);
285
286 return SQL_ERROR;
287 }
288
289 if (fInfoType == SQL_ODBC_VER)
290 {
291 sprintf (buf, "%02d.%02d",
292 (ODBCVER) >> 8, 0x00FF & (ODBCVER));
293
294
295 if (rgbInfoValue != NULL
296 && cbInfoValueMax > 0)
297 {
298 len = STRLEN (buf);
299
300 if (len < cbInfoValueMax - 1)
301 {
302 len = cbInfoValueMax - 1;
303 PUSHSQLERR (pdbc->herr, en_01004);
304
305 retcode = SQL_SUCCESS_WITH_INFO;
306 }
307
308 STRNCPY (rgbInfoValue, buf, len);
309 ((char FAR *) rgbInfoValue)[len] = '\0';
310 }
311
312 if (pcbInfoValue != NULL)
313 {
314 *pcbInfoValue = (SWORD) len;
315 }
316
317 return retcode;
318 }
319
320 if (pdbc->state == en_dbc_allocated || pdbc->state == en_dbc_needdata)
321 {
322 PUSHSQLERR (pdbc->herr, en_08003);
323
324 return SQL_ERROR;
325 }
326
327 switch (fInfoType)
328 {
329 case SQL_DRIVER_HDBC:
330 dword = (DWORD) (pdbc->dhdbc);
331 size = sizeof (dword);
332 break;
333
334 case SQL_DRIVER_HENV:
335 penv = (ENV_t FAR *) (pdbc->henv);
336 dword = (DWORD) (penv->dhenv);
337 size = sizeof (dword);
338 break;
339
340 case SQL_DRIVER_HLIB:
341 penv = (ENV_t FAR *) (pdbc->henv);
342 dword = (DWORD) (penv->hdll);
343 size = sizeof (dword);
344 break;
345
346 case SQL_DRIVER_HSTMT:
347 if (rgbInfoValue != NULL)
348 {
349 pstmt = *((STMT_t FAR **) rgbInfoValue);
350 }
351
352 for (tpstmt = (STMT_t FAR *) (pdbc->hstmt);
353 tpstmt != NULL;
354 tpstmt = tpstmt->next)
355 {
356 if (tpstmt == pstmt)
357 {
358 break;
359 }
360 }
361
362 if (tpstmt == NULL)
363 {
364 PUSHSQLERR (pdbc->herr, en_S1009);
365
366 return SQL_ERROR;
367 }
368
369 dword = (DWORD) (pstmt->dhstmt);
370 size = sizeof (dword);
371 break;
372
373 default:
374 break;
375 }
376
377 if (size)
378 {
379 if (rgbInfoValue != NULL)
380 {
381 *((DWORD *) rgbInfoValue) = dword;
382 }
383
384 if (pcbInfoValue != NULL)
385 {
386 *(pcbInfoValue) = (SWORD) size;
387 }
388
389 return SQL_SUCCESS;
390 }
391
392 hproc = _iodbcdm_getproc (hdbc, en_GetInfo);
393
394 if (hproc == SQL_NULL_HPROC)
395 {
396 PUSHSQLERR (pdbc->herr, en_IM001);
397
398 return SQL_ERROR;
399 }
400
401 CALL_DRIVER (hdbc, retcode, hproc, en_GetInfo,
402 (pdbc->dhdbc, fInfoType, rgbInfoValue, cbInfoValueMax, pcbInfoValue))
403
404 if (retcode == SQL_ERROR
405 && fInfoType == SQL_DRIVER_ODBC_VER)
406 {
407 STRCPY (buf, "01.00");
408
409 if (rgbInfoValue != NULL
410 && cbInfoValueMax > 0)
411 {
412 len = STRLEN (buf);
413
414 if (len < cbInfoValueMax - 1)
415 {
416 len = cbInfoValueMax - 1;
417 PUSHSQLERR (pdbc->herr, en_01004);
418 }
419
420 STRNCPY (rgbInfoValue, buf, len);
421 ((char FAR *) rgbInfoValue)[len] = '\0';
422 }
423
424 if (pcbInfoValue != NULL)
425 {
426 *pcbInfoValue = (SWORD) len;
427 }
428
429 /* what should we return in this case ???? */
430 }
431
432 return retcode;
433 }
434
435
436 RETCODE SQL_API
437 SQLGetFunctions (
438 HDBC hdbc,
439 UWORD fFunc,
440 UWORD FAR * pfExists)
441 {
442 DBC_t FAR *pdbc = (DBC_t FAR *) hdbc;
443 HPROC hproc;
444 RETCODE retcode;
445
446 if (hdbc == SQL_NULL_HDBC)
447 {
448 return SQL_INVALID_HANDLE;
449 }
450
451 if (fFunc > SQL_EXT_API_LAST)
452 {
453 PUSHSQLERR (pdbc->herr, en_S1095);
454
455 return SQL_ERROR;
456 }
457
458 if (pdbc->state == en_dbc_allocated
459 || pdbc->state == en_dbc_needdata)
460 {
461 PUSHSQLERR (pdbc->herr, en_S1010);
462
463 return SQL_ERROR;
464 }
465
466 if (pfExists == NULL)
467 {
468 return SQL_SUCCESS;
469 }
470
471 hproc = _iodbcdm_getproc (hdbc, en_GetFunctions);
472
473 if (hproc != SQL_NULL_HPROC)
474 {
475 CALL_DRIVER (hdbc, retcode, hproc, en_GetFunctions,
476 (pdbc->dhdbc, fFunc, pfExists))
477
478 return retcode;
479 }
480
481 if (fFunc == SQL_API_SQLSETPARAM)
482 {
483 fFunc = SQL_API_SQLBINDPARAMETER;
484 }
485
486 if (fFunc != SQL_API_ALL_FUNCTIONS)
487 {
488 hproc = _iodbcdm_getproc (hdbc, fFunc);
489
490 if (hproc == SQL_NULL_HPROC)
491 {
492 *pfExists = (UWORD) 0;
493 }
494 else
495 {
496 *pfExists = (UWORD) 1;
497 }
498
499 return SQL_SUCCESS;
500 }
501
502 for (fFunc = 0; fFunc < 100; fFunc++)
503 {
504 hproc = _iodbcdm_getproc (hdbc, fFunc);
505
506 if (hproc == SQL_NULL_HPROC)
507 {
508 pfExists[fFunc] = (UWORD) 0;
509 }
510 else
511 {
512 pfExists[fFunc] = (UWORD) 1;
513 }
514 }
515
516 return SQL_SUCCESS;
517 }