1 /**
2 * @file sqliteodbc.c
3 * SQLite ODBC Driver main module.
4 *
5 * $Id: sqliteodbc.c,v 1.225 2020/06/20 11:56:09 chw Exp chw $
6 *
7 * Copyright (c) 2001-2020 Christian Werner <chw@ch-werner.de>
8 * OS/2 Port Copyright (c) 2004 Lorne R. Sunley <lsunley@mb.sympatico.ca>
9 *
10 * See the file "license.terms" for information on usage
11 * and redistribution of this file and for a
12 * DISCLAIMER OF ALL WARRANTIES.
13 */
14
15 #include "sqliteodbc.h"
16
17 #ifdef SQLITE_UTF8
18 #ifndef WITHOUT_WINTERFACE
19 #define WINTERFACE
20 #define WCHARSUPPORT
21 #endif
22 #endif
23
24 #ifdef SQLITE_UTF8
25 #if !defined(_WIN32) && !defined(_WIN64)
26 #if !defined(WCHARSUPPORT) && defined(HAVE_SQLWCHAR) && (HAVE_SQLWCHAR)
27 #define WCHARSUPPORT
28 #endif
29 #endif
30 #endif
31
32 #if defined(WINTERFACE)
33 #include <sqlucode.h>
34 #endif
35
36 #if defined(_WIN32) || defined(_WIN64)
37 #include "resource.h"
38 #define ODBC_INI "ODBC.INI"
39 #ifndef DRIVER_VER_INFO
40 #define DRIVER_VER_INFO VERSION
41 #endif
42 #else
43 #ifdef __OS2__
44 #define ODBC_INI "ODBC.INI"
45 #else
46 #define ODBC_INI ".odbc.ini"
47 #endif
48 #endif
49
50 #if defined(__GNUC__) && ((__GNUC__ > 4) || ((__GNUC__ == 4) && (__GNUC_MINOR__ > 3)))
51 #define CANT_PASS_VALIST_AS_CHARPTR 1
52 #endif
53
54 #ifdef _WIN64
55 #undef CANT_PASS_VALIST_AS_CHARPTR
56 #define CANT_PASS_VALIST_AS_CHARPTR 1
57 #endif
58
59 #ifdef CANT_PASS_VALIST_AS_CHARPTR
60 #define MAX_PARAMS_FOR_VPRINTF 32
61 #endif
62
63 #ifndef DRIVER_VER_INFO
64 #define DRIVER_VER_INFO "0.0"
65 #endif
66
67 #ifndef COLATTRIBUTE_LAST_ARG_TYPE
68 #ifdef _WIN64
69 #define COLATTRIBUTE_LAST_ARG_TYPE SQLLEN *
70 #else
71 #define COLATTRIBUTE_LAST_ARG_TYPE SQLPOINTER
72 #endif
73 #endif
74
75 #ifndef SETSTMTOPTION_LAST_ARG_TYPE
76 #define SETSTMTOPTION_LAST_ARG_TYPE SQLROWCOUNT
77 #endif
78
79 #undef min
80 #define min(a, b) ((a) < (b) ? (a) : (b))
81 #undef max
82 #define max(a, b) ((a) < (b) ? (b) : (a))
83
84 #ifndef PTRDIFF_T
85 #define PTRDIFF_T int
86 #endif
87
88 #define array_size(x) (sizeof (x) / sizeof (x[0]))
89
90 #define stringify1(s) #s
91 #define stringify(s) stringify1(s)
92
93 #define verinfo(maj, min, lev) ((maj) << 16 | (min) << 8 | (lev))
94
95 /* Column types for static string column descriptions (SQLTables etc.) */
96
97 #if defined(WINTERFACE) && !defined(_WIN32) && !defined(_WIN64)
98 #define SCOL_VARCHAR SQL_WVARCHAR
99 #define SCOL_CHAR SQL_WCHAR
100 #else
101 #define SCOL_VARCHAR SQL_VARCHAR
102 #define SCOL_CHAR SQL_CHAR
103 #endif
104
105 #define ENV_MAGIC 0x53544145
106 #define DBC_MAGIC 0x53544144
107 #define DEAD_MAGIC 0xdeadbeef
108
109 #ifdef MEMORY_DEBUG
110
111 static void *
xmalloc_(int n,char * file,int line)112 xmalloc_(int n, char *file, int line)
113 {
114 int nn = n + 4 * sizeof (long);
115 long *p;
116
117 p = malloc(nn);
118 if (!p) {
119 #if (MEMORY_DEBUG > 1)
120 fprintf(stderr, "malloc\t%d\tNULL\t%s:%d\n", n, file, line);
121 #endif
122 return NULL;
123 }
124 p[0] = 0xdead1234;
125 nn = nn / sizeof (long) - 1;
126 p[1] = n;
127 p[nn] = 0xdead5678;
128 #if (MEMORY_DEBUG > 1)
129 fprintf(stderr, "malloc\t%d\t%p\t%s:%d\n", n, &p[2], file, line);
130 #endif
131 return (void *) &p[2];
132 }
133
134 static void *
xrealloc_(void * old,int n,char * file,int line)135 xrealloc_(void *old, int n, char *file, int line)
136 {
137 int nn = n + 4 * sizeof (long), nnn;
138 long *p, *pp;
139
140 if (n == 0 || !old) {
141 return xmalloc_(n, file, line);
142 }
143 p = &((long *) old)[-2];
144 if (p[0] != 0xdead1234) {
145 fprintf(stderr, "*** low end corruption @ %p\n", old);
146 abort();
147 }
148 nnn = p[1] + 4 * sizeof (long);
149 nnn = nnn / sizeof (long) - 1;
150 if (p[nnn] != 0xdead5678) {
151 fprintf(stderr, "*** high end corruption @ %p\n", old);
152 abort();
153 }
154 pp = realloc(p, nn);
155 if (!pp) {
156 #if (MEMORY_DEBUG > 1)
157 fprintf(stderr, "realloc\t%p,%d\tNULL\t%s:%d\n", old, n, file, line);
158 #endif
159 return NULL;
160 }
161 #if (MEMORY_DEBUG > 1)
162 fprintf(stderr, "realloc\t%p,%d\t%p\t%s:%d\n", old, n, &pp[2], file, line);
163 #endif
164 p = pp;
165 p[1] = n;
166 nn = nn / sizeof (long) - 1;
167 p[nn] = 0xdead5678;
168 return (void *) &p[2];
169 }
170
171 static void
xfree_(void * x,char * file,int line)172 xfree_(void *x, char *file, int line)
173 {
174 long *p;
175 int n;
176
177 if (!x) {
178 return;
179 }
180 p = &((long *) x)[-2];
181 if (p[0] != 0xdead1234) {
182 fprintf(stderr, "*** low end corruption @ %p\n", x);
183 abort();
184 }
185 n = p[1] + 4 * sizeof (long);
186 n = n / sizeof (long) - 1;
187 if (p[n] != 0xdead5678) {
188 fprintf(stderr, "*** high end corruption @ %p\n", x);
189 abort();
190 }
191 #if (MEMORY_DEBUG > 1)
192 fprintf(stderr, "free\t%p\t\t%s:%d\n", x, file, line);
193 #endif
194 free(p);
195 }
196
197 static void
xfree__(void * x)198 xfree__(void *x)
199 {
200 xfree_(x, "unknown location", 0);
201 }
202
203 static char *
xstrdup_(const char * str,char * file,int line)204 xstrdup_(const char *str, char *file, int line)
205 {
206 char *p;
207
208 if (!str) {
209 #if (MEMORY_DEBUG > 1)
210 fprintf(stderr, "strdup\tNULL\tNULL\t%s:%d\n", file, line);
211 #endif
212 return NULL;
213 }
214 p = xmalloc_(strlen(str) + 1, file, line);
215 if (p) {
216 strcpy(p, str);
217 }
218 #if (MEMORY_DEBUG > 1)
219 fprintf(stderr, "strdup\t%p\t%p\t%s:%d\n", str, p, file, line);
220 #endif
221 return p;
222 }
223
224 #define xmalloc(x) xmalloc_(x, __FILE__, __LINE__)
225 #define xrealloc(x,y) xrealloc_(x, y, __FILE__, __LINE__)
226 #define xfree(x) xfree_(x, __FILE__, __LINE__)
227 #define xstrdup(x) xstrdup_(x, __FILE__, __LINE__)
228
229 #else
230
231 #define xmalloc(x) malloc(x)
232 #define xrealloc(x,y) realloc(x, y)
233 #define xfree(x) free(x)
234 #define xstrdup(x) strdup_(x)
235
236 #endif
237
238 #if defined(_WIN32) || defined(_WIN64)
239
240 #define vsnprintf _vsnprintf
241 #define snprintf _snprintf
242 #define strcasecmp _stricmp
243 #define strncasecmp _strnicmp
244
245 static HINSTANCE NEAR hModule; /* Saved module handle for resources */
246
247 #endif
248
249 #if defined(_WIN32) || defined(_WIN64)
250
251 /*
252 * SQLHENV, SQLHDBC, and SQLHSTMT synchronization
253 * is done using a critical section in ENV structure.
254 */
255
256 #define HDBC_LOCK(hdbc) \
257 { \
258 DBC *d; \
259 \
260 if ((hdbc) == SQL_NULL_HDBC) { \
261 return SQL_INVALID_HANDLE; \
262 } \
263 d = (DBC *) (hdbc); \
264 if (d->magic != DBC_MAGIC) { \
265 return SQL_INVALID_HANDLE; \
266 } \
267 EnterCriticalSection(&d->cs); \
268 d->owner = GetCurrentThreadId(); \
269 }
270
271 #define HDBC_UNLOCK(hdbc) \
272 if ((hdbc) != SQL_NULL_HDBC) { \
273 DBC *d; \
274 \
275 d = (DBC *) (hdbc); \
276 if (d->magic == DBC_MAGIC) { \
277 d->owner = 0; \
278 LeaveCriticalSection(&d->cs); \
279 } \
280 }
281
282 #define HSTMT_LOCK(hstmt) \
283 { \
284 DBC *d; \
285 \
286 if ((hstmt) == SQL_NULL_HSTMT) { \
287 return SQL_INVALID_HANDLE; \
288 } \
289 d = (DBC *) ((STMT *) (hstmt))->dbc; \
290 if (d->magic != DBC_MAGIC) { \
291 return SQL_INVALID_HANDLE; \
292 } \
293 EnterCriticalSection(&d->cs); \
294 d->owner = GetCurrentThreadId(); \
295 }
296
297 #define HSTMT_UNLOCK(hstmt) \
298 if ((hstmt) != SQL_NULL_HSTMT) { \
299 DBC *d; \
300 \
301 d = (DBC *) ((STMT *) (hstmt))->dbc; \
302 if (d->magic == DBC_MAGIC) { \
303 d->owner = 0; \
304 LeaveCriticalSection(&d->cs); \
305 } \
306 }
307
308 #else
309
310 /*
311 * On UN*X assume that we are single-threaded or
312 * the driver manager provides serialization for us.
313 *
314 * In iODBC (3.52.x) serialization can be turned
315 * on using the DSN property "ThreadManager=yes".
316 *
317 * In unixODBC that property is named
318 * "Threading=0-3" and takes one of these values:
319 *
320 * 0 - no protection
321 * 1 - statement level protection
322 * 2 - connection level protection
323 * 3 - environment level protection
324 *
325 * unixODBC 2.2.11 uses environment level protection
326 * by default when it has been built with pthread
327 * support.
328 */
329
330 #define HDBC_LOCK(hdbc)
331 #define HDBC_UNLOCK(hdbc)
332 #define HSTMT_LOCK(hdbc)
333 #define HSTMT_UNLOCK(hdbc)
334
335 #endif
336
337 /*
338 * tolower() replacement w/o locale
339 */
340
341 static const char upper_chars[] = "ABCDEFGHIJKLMNOPQRSTUVWXYZ";
342 static const char lower_chars[] = "abcdefghijklmnopqrstuvwxyz";
343
344 static int
TOLOWER(int c)345 TOLOWER(int c)
346 {
347 if (c) {
348 char *p = strchr(upper_chars, c);
349
350 if (p) {
351 c = lower_chars[p - upper_chars];
352 }
353 }
354 return c;
355 }
356
357 /*
358 * isdigit() replacement w/o ctype.h
359 */
360
361 static const char digit_chars[] = "0123456789";
362
363 #define ISDIGIT(c) \
364 ((c) && strchr(digit_chars, (c)) != NULL)
365
366 /*
367 * isspace() replacement w/o ctype.h
368 */
369
370 static const char space_chars[] = " \f\n\r\t\v";
371
372 #define ISSPACE(c) \
373 ((c) && strchr(space_chars, (c)) != NULL)
374
375 /*
376 * Characters in named parameters
377 */
378
379 static const char id_chars[] = "ABCDEFGHIJKLMNOPQRSTUVWXYZ"
380 "abcdefghijklmnopqrstuvwxyz"
381 "_0123456789";
382
383 #define ISIDCHAR(c) \
384 ((c) && strchr(id_chars, (c)) != NULL)
385
386 /*
387 * Forward declarations of static functions.
388 */
389
390 static void freedyncols(STMT *s);
391 static void freeresult(STMT *s, int clrcols);
392 static void unbindcols(STMT *s);
393
394 static SQLRETURN drvexecute(SQLHSTMT stmt, int initial);
395 static SQLRETURN freestmt(HSTMT stmt);
396 static SQLRETURN mkbindcols(STMT *s, int ncols);
397 static SQLRETURN setupparbuf(STMT *s, BINDPARM *p);
398 static SQLRETURN starttran(STMT *s);
399 static SQLRETURN substparam(STMT *s, int pnum, char **outp);
400
401 #if (defined(_WIN32) || defined(_WIN64)) && defined(WINTERFACE)
402 /* MS Access hack part 1 (reserved error -7748) */
403 static COL *statSpec2P, *statSpec3P;
404 #endif
405
406 #if (MEMORY_DEBUG < 1)
407 /**
408 * Duplicate string using xmalloc().
409 * @param str string to be duplicated
410 * @result pointer to new string or NULL
411 */
412
413 static char *
strdup_(const char * str)414 strdup_(const char *str)
415 {
416 char *p = NULL;
417
418 if (str) {
419 p = xmalloc(strlen(str) + 1);
420 if (p) {
421 strcpy(p, str);
422 }
423 }
424 return p;
425 }
426 #endif
427
428 #ifdef WCHARSUPPORT
429 /**
430 * Return length of UNICODE string.
431 * @param str UNICODE string
432 * @result length of string in characters
433 */
434
435 static int
uc_strlen(SQLWCHAR * str)436 uc_strlen(SQLWCHAR *str)
437 {
438 int len = 0;
439
440 if (str) {
441 while (*str) {
442 ++len;
443 ++str;
444 }
445 }
446 return len;
447 }
448
449 /**
450 * Copy UNICODE string like strncpy().
451 * @param dest destination area
452 * @param src source area
453 * @param len length of source area in characters
454 * @return pointer to destination area
455 */
456
457 static SQLWCHAR *
uc_strncpy(SQLWCHAR * dest,SQLWCHAR * src,int len)458 uc_strncpy(SQLWCHAR *dest, SQLWCHAR *src, int len)
459 {
460 int i = 0;
461
462 while (i < len) {
463 if (!src[i]) {
464 break;
465 }
466 dest[i] = src[i];
467 ++i;
468 }
469 if (i < len) {
470 dest[i] = 0;
471 }
472 return dest;
473 }
474
475 /**
476 * Make UNICODE string from UTF8 string into buffer.
477 * @param str UTF8 string to be converted
478 * @param len length in characters of str or -1
479 * @param uc destination area to receive UNICODE string
480 * @param ucLen byte length of destination area
481 */
482
483 static void
uc_from_utf_buf(unsigned char * str,int len,SQLWCHAR * uc,int ucLen)484 uc_from_utf_buf(unsigned char *str, int len, SQLWCHAR *uc, int ucLen)
485 {
486 ucLen = ucLen / sizeof (SQLWCHAR);
487 if (!uc || ucLen < 0) {
488 return;
489 }
490 if (len < 0) {
491 len = ucLen * 5;
492 }
493 uc[0] = 0;
494 if (str) {
495 int i = 0;
496
497 while (i < len && *str && i < ucLen) {
498 unsigned char c = str[0];
499
500 if (c < 0x80) {
501 uc[i++] = c;
502 ++str;
503 } else if (c <= 0xc1 || c >= 0xf5) {
504 /* illegal, ignored */
505 ++str;
506 } else if (c < 0xe0) {
507 if ((str[1] & 0xc0) == 0x80) {
508 unsigned long t = ((c & 0x1f) << 6) | (str[1] & 0x3f);
509
510 uc[i++] = t;
511 str += 2;
512 } else {
513 uc[i++] = c;
514 ++str;
515 }
516 } else if (c < 0xf0) {
517 if ((str[1] & 0xc0) == 0x80 && (str[2] & 0xc0) == 0x80) {
518 unsigned long t = ((c & 0x0f) << 12) |
519 ((str[1] & 0x3f) << 6) | (str[2] & 0x3f);
520
521 uc[i++] = t;
522 str += 3;
523 } else {
524 uc[i++] = c;
525 ++str;
526 }
527 } else if (c < 0xf8) {
528 if ((str[1] & 0xc0) == 0x80 && (str[2] & 0xc0) == 0x80 &&
529 (str[3] & 0xc0) == 0x80) {
530 unsigned long t = ((c & 0x03) << 18) |
531 ((str[1] & 0x3f) << 12) | ((str[2] & 0x3f) << 6) |
532 (str[3] & 0x3f);
533
534 if (sizeof (SQLWCHAR) == 2 * sizeof (char) &&
535 t >= 0x10000) {
536 t -= 0x10000;
537 uc[i++] = 0xd800 | ((t >> 10) & 0x3ff);
538 if (i >= ucLen) {
539 break;
540 }
541 t = 0xdc00 | (t & 0x3ff);
542 }
543 uc[i++] = t;
544 str += 4;
545 } else {
546 uc[i++] = c;
547 ++str;
548 }
549 } else {
550 /* ignore */
551 ++str;
552 }
553 }
554 if (i < ucLen) {
555 uc[i] = 0;
556 }
557 }
558 }
559
560 /**
561 * Make UNICODE string from UTF8 string.
562 * @param str UTF8 string to be converted
563 * @param len length of UTF8 string
564 * @return alloc'ed UNICODE string to be free'd by uc_free()
565 */
566
567 static SQLWCHAR *
uc_from_utf(unsigned char * str,int len)568 uc_from_utf(unsigned char *str, int len)
569 {
570 SQLWCHAR *uc = NULL;
571 int ucLen;
572
573 if (str) {
574 if (len == SQL_NTS) {
575 len = strlen((char *) str);
576 }
577 ucLen = sizeof (SQLWCHAR) * (len + 1);
578 uc = xmalloc(ucLen);
579 if (uc) {
580 uc_from_utf_buf(str, len, uc, ucLen);
581 }
582 }
583 return uc;
584 }
585
586 /**
587 * Make UTF8 string from UNICODE string.
588 * @param str UNICODE string to be converted
589 * @param len length of UNICODE string in bytes
590 * @return alloc'ed UTF8 string to be free'd by uc_free()
591 */
592
593 static char *
uc_to_utf(SQLWCHAR * str,int len)594 uc_to_utf(SQLWCHAR *str, int len)
595 {
596 int i;
597 char *cp, *ret = NULL;
598
599 if (!str) {
600 return ret;
601 }
602 if (len == SQL_NTS) {
603 len = uc_strlen(str);
604 } else {
605 len = len / sizeof (SQLWCHAR);
606 }
607 cp = xmalloc(len * 6 + 1);
608 if (!cp) {
609 return ret;
610 }
611 ret = cp;
612 for (i = 0; i < len; i++) {
613 unsigned long c = str[i];
614
615 if (sizeof (SQLWCHAR) == 2 * sizeof (char)) {
616 c &= 0xffff;
617 }
618 if (c < 0x80) {
619 *cp++ = c;
620 } else if (c < 0x800) {
621 *cp++ = 0xc0 | ((c >> 6) & 0x1f);
622 *cp++ = 0x80 | (c & 0x3f);
623 } else if (c < 0x10000) {
624 if (sizeof (SQLWCHAR) == 2 * sizeof (char) &&
625 c >= 0xd800 && c <= 0xdbff && i + 1 < len) {
626 unsigned long c2 = str[i + 1] & 0xffff;
627
628 if (c2 >= 0xdc00 && c2 <= 0xdfff) {
629 c = (((c & 0x3ff) << 10) | (c2 & 0x3ff)) + 0x10000;
630 *cp++ = 0xf0 | ((c >> 18) & 0x07);
631 *cp++ = 0x80 | ((c >> 12) & 0x3f);
632 *cp++ = 0x80 | ((c >> 6) & 0x3f);
633 *cp++ = 0x80 | (c & 0x3f);
634 ++i;
635 continue;
636 }
637 }
638 *cp++ = 0xe0 | ((c >> 12) & 0x0f);
639 *cp++ = 0x80 | ((c >> 6) & 0x3f);
640 *cp++ = 0x80 | (c & 0x3f);
641 } else if (c <= 0x10ffff) {
642 *cp++ = 0xf0 | ((c >> 18) & 0x07);
643 *cp++ = 0x80 | ((c >> 12) & 0x3f);
644 *cp++ = 0x80 | ((c >> 6) & 0x3f);
645 *cp++ = 0x80 | (c & 0x3f);
646 }
647 }
648 *cp = '\0';
649 return ret;
650 }
651
652 #endif
653
654 #ifdef WINTERFACE
655
656 /**
657 * Make UTF8 string from UNICODE string.
658 * @param str UNICODE string to be converted
659 * @param len length of UNICODE string in characters
660 * @return alloc'ed UTF8 string to be free'd by uc_free()
661 */
662
663 static char *
uc_to_utf_c(SQLWCHAR * str,int len)664 uc_to_utf_c(SQLWCHAR *str, int len)
665 {
666 if (len != SQL_NTS) {
667 len = len * sizeof (SQLWCHAR);
668 }
669 return uc_to_utf(str, len);
670 }
671
672 #endif
673
674 #if defined(WINTERFACE) || defined(WCHARSUPPORT)
675
676 /**
677 * Free converted UTF8 or UNICODE string.
678 */
679
680 static void
uc_free(void * str)681 uc_free(void *str)
682 {
683 if (str) {
684 xfree(str);
685 }
686 }
687
688 #endif
689
690 #ifdef USE_DLOPEN_FOR_GPPS
691
692 #include <dlfcn.h>
693
694 #define SQLGetPrivateProfileString(A,B,C,D,E,F) drvgpps(d,A,B,C,D,E,F)
695
696 /*
697 * EXPERIMENTAL: SQLGetPrivateProfileString infrastructure using
698 * dlopen(), in theory this makes the driver independent from the
699 * driver manager, i.e. the same driver binary can run with iODBC
700 * and unixODBC.
701 */
702
703 static void
drvgetgpps(DBC * d)704 drvgetgpps(DBC *d)
705 {
706 void *lib;
707 int (*gpps)();
708
709 lib = dlopen("libodbcinst.so.2", RTLD_LAZY);
710 if (!lib) {
711 lib = dlopen("libodbcinst.so.1", RTLD_LAZY);
712 }
713 if (!lib) {
714 lib = dlopen("libodbcinst.so", RTLD_LAZY);
715 }
716 if (!lib) {
717 lib = dlopen("libiodbcinst.so.2", RTLD_LAZY);
718 }
719 if (!lib) {
720 lib = dlopen("libiodbcinst.so", RTLD_LAZY);
721 }
722 if (lib) {
723 gpps = (int (*)()) dlsym(lib, "SQLGetPrivateProfileString");
724 if (!gpps) {
725 dlclose(lib);
726 return;
727 }
728 d->instlib = lib;
729 d->gpps = gpps;
730 }
731 }
732
733 static void
drvrelgpps(DBC * d)734 drvrelgpps(DBC *d)
735 {
736 if (d->instlib) {
737 dlclose(d->instlib);
738 d->instlib = 0;
739 }
740 }
741
742 static int
drvgpps(DBC * d,char * sect,char * ent,char * def,char * buf,int bufsiz,char * fname)743 drvgpps(DBC *d, char *sect, char *ent, char *def, char *buf,
744 int bufsiz, char *fname)
745 {
746 if (d->gpps) {
747 return d->gpps(sect, ent, def, buf, bufsiz, fname);
748 }
749 strncpy(buf, def, bufsiz);
750 buf[bufsiz - 1] = '\0';
751 return 1;
752 }
753 #else
754 #include <odbcinst.h>
755 #define drvgetgpps(d)
756 #define drvrelgpps(d)
757 #endif
758
759 /**
760 * Set error message and SQL state on DBC
761 * @param d database connection pointer
762 * @param naterr native error code
763 * @param msg error message
764 * @param st SQL state
765 */
766
767 #if defined(__GNUC__) && (__GNUC__ >= 2)
768 static void setstatd(DBC *, int, char *, char *, ...)
769 __attribute__((format (printf, 3, 5)));
770 #endif
771
772 static void
setstatd(DBC * d,int naterr,char * msg,char * st,...)773 setstatd(DBC *d, int naterr, char *msg, char *st, ...)
774 {
775 va_list ap;
776
777 if (!d) {
778 return;
779 }
780 d->naterr = naterr;
781 d->logmsg[0] = '\0';
782 if (msg) {
783 int count;
784
785 va_start(ap, st);
786 count = vsnprintf((char *) d->logmsg, sizeof (d->logmsg), msg, ap);
787 va_end(ap);
788 if (count < 0) {
789 d->logmsg[sizeof (d->logmsg) - 1] = '\0';
790 }
791 }
792 if (!st) {
793 st = "?????";
794 }
795 strncpy(d->sqlstate, st, 5);
796 d->sqlstate[5] = '\0';
797 }
798
799 /**
800 * Set error message and SQL state on statement
801 * @param s statement pointer
802 * @param naterr native error code
803 * @param msg error message
804 * @param st SQL state
805 */
806
807 #if defined(__GNUC__) && (__GNUC__ >= 2)
808 static void setstat(STMT *, int, char *, char *, ...)
809 __attribute__((format (printf, 3, 5)));
810 #endif
811
812 static void
setstat(STMT * s,int naterr,char * msg,char * st,...)813 setstat(STMT *s, int naterr, char *msg, char *st, ...)
814 {
815 va_list ap;
816
817 if (!s) {
818 return;
819 }
820 s->naterr = naterr;
821 s->logmsg[0] = '\0';
822 if (msg) {
823 int count;
824
825 va_start(ap, st);
826 count = vsnprintf((char *) s->logmsg, sizeof (s->logmsg), msg, ap);
827 va_end(ap);
828 if (count < 0) {
829 s->logmsg[sizeof (s->logmsg) - 1] = '\0';
830 }
831 }
832 if (!st) {
833 st = "?????";
834 }
835 strncpy(s->sqlstate, st, 5);
836 s->sqlstate[5] = '\0';
837 }
838
839 /**
840 * Report IM001 (not implemented) SQL error code for HDBC.
841 * @param dbc database connection handle
842 * @result ODBC error code
843 */
844
845 static SQLRETURN
drvunimpldbc(HDBC dbc)846 drvunimpldbc(HDBC dbc)
847 {
848 DBC *d;
849
850 if (dbc == SQL_NULL_HDBC) {
851 return SQL_INVALID_HANDLE;
852 }
853 d = (DBC *) dbc;
854 setstatd(d, -1, "not supported", "IM001");
855 return SQL_ERROR;
856 }
857
858 /**
859 * Report IM001 (not implemented) SQL error code for HSTMT.
860 * @param stmt statement handle
861 * @result ODBC error code
862 */
863
864 static SQLRETURN
drvunimplstmt(HSTMT stmt)865 drvunimplstmt(HSTMT stmt)
866 {
867 STMT *s;
868
869 if (stmt == SQL_NULL_HSTMT) {
870 return SQL_INVALID_HANDLE;
871 }
872 s = (STMT *) stmt;
873 setstat(s, -1, "not supported", "IM001");
874 return SQL_ERROR;
875 }
876
877 /**
878 * Free memory given pointer to memory pointer.
879 * @param x pointer to pointer to memory to be free'd
880 */
881
882 static void
freep(void * x)883 freep(void *x)
884 {
885 if (x && ((char **) x)[0]) {
886 xfree(((char **) x)[0]);
887 ((char **) x)[0] = NULL;
888 }
889 }
890
891 /**
892 * Report S1000 (out of memory) SQL error given STMT.
893 * @param s statement pointer
894 * @result ODBC error code
895 */
896
897 static SQLRETURN
nomem(STMT * s)898 nomem(STMT *s)
899 {
900 setstat(s, -1, "out of memory", (*s->ov3) ? "HY000" : "S1000");
901 return SQL_ERROR;
902 }
903
904 /**
905 * Report S1000 (not connected) SQL error given STMT.
906 * @param s statement pointer
907 * @result ODBC error code
908 */
909
910 static SQLRETURN
noconn(STMT * s)911 noconn(STMT *s)
912 {
913 setstat(s, -1, "not connected", (*s->ov3) ? "HY000" : "S1000");
914 return SQL_ERROR;
915 }
916
917 /**
918 * Internal locale neutral strtod function.
919 * @param data pointer to string
920 * @param endp pointer for ending character
921 * @result double value
922 */
923
924 #if defined(HAVE_SQLITEATOF) && (HAVE_SQLITEATOF)
925
926 extern double sqliteAtoF(char *data, char **endp);
927
928 #define ln_strtod(A,B) sqliteAtoF(A,B)
929
930 #else
931
932 #if defined(HAVE_LOCALECONV) || defined(_WIN32) || defined(_WIN64)
933
934 static double
ln_strtod(const char * data,char ** endp)935 ln_strtod(const char *data, char **endp)
936 {
937 struct lconv *lc = 0;
938 char buf[128], *p, *end;
939 double value;
940
941 lc = localeconv();
942 if (lc && lc->decimal_point && lc->decimal_point[0] &&
943 lc->decimal_point[0] != '.') {
944 strncpy(buf, data, sizeof (buf) - 1);
945 buf[sizeof (buf) - 1] = '\0';
946 p = strchr(buf, '.');
947 if (p) {
948 *p = lc->decimal_point[0];
949 }
950 p = buf;
951 } else {
952 p = (char *) data;
953 }
954 value = strtod(p, &end);
955 end = (char *) data + (end - p);
956 if (endp) {
957 *endp = end;
958 }
959 return value;
960 }
961
962 #else
963
964 #define ln_strtod(A,B) strtod(A,B)
965
966 #endif
967
968 #endif
969
970 #if !defined(HAVE_SQLITEMPRINTF) || !(HAVE_SQLITEMPRINTF)
971 /**
972 * Internal locale neutral sprintf("%g") function.
973 * @param buf pointer to string
974 * @param value double value
975 */
976
977 static void
ln_sprintfg(char * buf,double value)978 ln_sprintfg(char *buf, double value)
979 {
980 #if defined(HAVE_LOCALECONV) || defined(_WIN32) || defined(_WIN64)
981 struct lconv *lc = 0;
982 char *p;
983
984 sprintf(buf, "%.16g", value);
985 lc = localeconv();
986 if (lc && lc->decimal_point && lc->decimal_point[0] &&
987 lc->decimal_point[0] != '.') {
988 p = strchr(buf, lc->decimal_point[0]);
989 if (p) {
990 *p = '.';
991 }
992 }
993 #else
994 sprintf(buf, "%.16g", value);
995 #endif
996 }
997 #endif
998
999 /**
1000 * Strip quotes from quoted string in-place.
1001 * @param str string
1002 */
1003
1004 static char *
unquote(char * str)1005 unquote(char *str)
1006 {
1007 if (str) {
1008 int len = strlen(str);
1009
1010 if (len > 1) {
1011 int end = len - 1;
1012
1013 if ((str[0] == '\'' && str[end] == '\'') ||
1014 (str[0] == '"' && str[end] == '"') ||
1015 (str[0] == '[' && str[end] == ']')) {
1016 memmove(str, str + 1, end - 1);
1017 str[end - 1] = '\0';
1018 }
1019 }
1020 }
1021 return str;
1022 }
1023
1024 /**
1025 * Unescape search pattern for e.g. table name in
1026 * catalog functions. Replacements in string are done in-place.
1027 * @param str string
1028 * @result number of pattern characters in string or 0
1029 */
1030
1031 static int
unescpat(char * str)1032 unescpat(char *str)
1033 {
1034 char *p, *q;
1035 int count = 0;
1036
1037 p = str;
1038 while ((q = strchr(p, '_')) != NULL) {
1039 if (q == str || q[-1] != '\\') {
1040 count++;
1041 }
1042 p = q + 1;
1043 }
1044 p = str;
1045 while ((q = strchr(p, '%')) != NULL) {
1046 if (q == str || q[-1] != '\\') {
1047 count++;
1048 }
1049 p = q + 1;
1050 }
1051 p = str;
1052 while ((q = strchr(p, '\\')) != NULL) {
1053 if (q[1] == '\\' || q[1] == '_' || q[1] == '%') {
1054 memmove(q, q + 1, strlen(q));
1055 }
1056 p = q + 1;
1057 }
1058 return count;
1059 }
1060
1061 /**
1062 * SQL LIKE string match with optional backslash escape handling.
1063 * @param str string
1064 * @param pat pattern
1065 * @param esc when true, treat literally "\\" as "\", "\%" as "%", "\_" as "_"
1066 * @result true when pattern matched
1067 */
1068
1069 static int
namematch(char * str,char * pat,int esc)1070 namematch(char *str, char *pat, int esc)
1071 {
1072 int cp, ch;
1073
1074 while (1) {
1075 cp = TOLOWER(*pat);
1076 if (cp == '\0') {
1077 if (*str != '\0') {
1078 goto nomatch;
1079 }
1080 break;
1081 }
1082 if (*str == '\0' && cp != '%') {
1083 goto nomatch;
1084 }
1085 if (cp == '%') {
1086 while (*pat == '%') {
1087 ++pat;
1088 }
1089 cp = TOLOWER(*pat);
1090 if (cp == '\0') {
1091 break;
1092 }
1093 while (1) {
1094 if (cp != '_' && cp != '\\') {
1095 while (*str) {
1096 ch = TOLOWER(*str);
1097 if (ch == cp) {
1098 break;
1099 }
1100 ++str;
1101 }
1102 }
1103 if (namematch(str, pat, esc)) {
1104 goto match;
1105 }
1106 if (*str == '\0') {
1107 goto nomatch;
1108 }
1109 ch = TOLOWER(*str);
1110 ++str;
1111 }
1112 }
1113 if (cp == '_') {
1114 pat++;
1115 str++;
1116 continue;
1117 }
1118 if (esc && cp == '\\' &&
1119 (pat[1] == '\\' || pat[1] == '%' || pat[1] == '_')) {
1120 ++pat;
1121 cp = TOLOWER(*pat);
1122 }
1123 ch = TOLOWER(*str++);
1124 ++pat;
1125 if (ch != cp) {
1126 goto nomatch;
1127 }
1128 }
1129 match:
1130 return 1;
1131 nomatch:
1132 return 0;
1133 }
1134
1135 /**
1136 * Busy callback for SQLite.
1137 * @param udata user data, pointer to DBC
1138 * @param table table name or NULL
1139 * @param count count of subsequenct calls
1140 * @result true of false
1141 */
1142
1143 static int
busy_handler(void * udata,const char * table,int count)1144 busy_handler(void *udata, const char *table, int count)
1145 {
1146 DBC *d = (DBC *) udata;
1147 long t1;
1148 int ret = 0;
1149 #if !defined(_WIN32) && !defined(_WIN64)
1150 struct timeval tv;
1151 #ifdef HAVE_NANOSLEEP
1152 struct timespec ts;
1153 #endif
1154 #endif
1155
1156 if (d->busyint) {
1157 d->busyint = 0;
1158 return ret;
1159 }
1160 if (d->timeout <= 0) {
1161 return ret;
1162 }
1163 if (count <= 1) {
1164 #if defined(_WIN32) || defined(_WIN64)
1165 d->t0 = GetTickCount();
1166 #else
1167 gettimeofday(&tv, NULL);
1168 d->t0 = tv.tv_sec * 1000 + tv.tv_usec / 1000;
1169 #endif
1170 }
1171 #if defined(_WIN32) || defined(_WIN64)
1172 t1 = GetTickCount();
1173 #else
1174 gettimeofday(&tv, NULL);
1175 t1 = tv.tv_sec * 1000 + tv.tv_usec / 1000;
1176 #endif
1177 if (t1 - d->t0 > d->timeout) {
1178 goto done;
1179 }
1180 #if defined(_WIN32) || defined(_WIN64)
1181 Sleep(10);
1182 #else
1183 #ifdef HAVE_NANOSLEEP
1184 ts.tv_sec = 0;
1185 ts.tv_nsec = 10000000;
1186 do {
1187 ret = nanosleep(&ts, &ts);
1188 if (ret < 0 && errno != EINTR) {
1189 ret = 0;
1190 }
1191 } while (ret);
1192 #else
1193 #ifdef HAVE_USLEEP
1194 usleep(10000);
1195 #else
1196 tv.tv_sec = 0;
1197 tv.tv_usec = 10000;
1198 select(0, NULL, NULL, NULL, &tv);
1199 #endif
1200 #endif
1201 #endif
1202 ret = 1;
1203 done:
1204 return ret;
1205 }
1206
1207 #ifdef HAVE_ENCDEC
1208 static void hextobin_func(sqlite_func *context, int argc, const char **argv);
1209 static void bintohex_func(sqlite_func *context, int argc, const char **argv);
1210 #endif
1211
1212 static void time_func(sqlite_func *context, int argc, const char **argv);
1213
1214 /**
1215 * Set SQLite options (PRAGMAs) given SQLite handle.
1216 * @param x SQLite database handle
1217 * @param d DBC pointer
1218 * @result SQLite error code
1219 *
1220 * "full_column_names" is always turned on to get the table
1221 * names in column labels. "count_changes" is always turned
1222 * on to get the number of affected rows for INSERTs et.al.
1223 * "empty_result_callbacks" is always turned on to get
1224 * column labels even when no rows are returned.
1225 * Starting from SQLite 2.6.0 data types are reported for
1226 * callback functions when the "show_datatypes" pragma is
1227 * asserted.
1228 */
1229
1230 static int
setsqliteopts(sqlite * x,DBC * d)1231 setsqliteopts(sqlite *x, DBC *d)
1232 {
1233 int count = 0, step = 0, rc;
1234
1235 while (step < 4) {
1236 if (step < 1) {
1237 rc = sqlite_exec(x, "PRAGMA full_column_names = on;",
1238 NULL, NULL, NULL);
1239 } else if (step < 2) {
1240 rc = sqlite_exec(x, "PRAGMA count_changes = on;",
1241 NULL, NULL, NULL);
1242 } else if (step < 3) {
1243 rc = sqlite_exec(x, "PRAGMA empty_result_callbacks = on;",
1244 NULL, NULL, NULL);
1245 } else {
1246 rc = sqlite_exec(x, "PRAGMA show_datatypes = on;",
1247 NULL, NULL, NULL);
1248 }
1249 if (rc != SQLITE_OK) {
1250 if (rc != SQLITE_BUSY ||
1251 !busy_handler((void *) d, NULL, ++count)) {
1252 return rc;
1253 }
1254 continue;
1255 }
1256 count = 0;
1257 ++step;
1258 }
1259 sqlite_busy_handler(x, busy_handler, (void *) d);
1260 #if (HAVE_ENCDEC)
1261 {
1262 char *fname;
1263
1264 fname = "hextobin";
1265 sqlite_create_function(x, fname, 1, hextobin_func, 0);
1266 sqlite_function_type(x, fname, SQLITE_TEXT);
1267 fname = "bintohex";
1268 sqlite_create_function(x, fname, 1, bintohex_func, 0);
1269 sqlite_function_type(x, fname, SQLITE_TEXT);
1270 }
1271 #endif
1272 {
1273 char *fname;
1274
1275 fname = "current_time_local";
1276 sqlite_create_function(x, fname, 0, time_func, (void *) 0);
1277 sqlite_function_type(x, fname, SQLITE_TEXT);
1278 fname = "current_time_utc";
1279 sqlite_create_function(x, fname, 0, time_func, (void *) 1);
1280 sqlite_function_type(x, fname, SQLITE_TEXT);
1281 fname = "current_date_local";
1282 sqlite_create_function(x, fname, 0, time_func, (void *) 2);
1283 sqlite_function_type(x, fname, SQLITE_TEXT);
1284 fname = "current_date_utc";
1285 sqlite_create_function(x, fname, 0, time_func, (void *) 3);
1286 sqlite_function_type(x, fname, SQLITE_TEXT);
1287 fname = "current_datetime_local";
1288 sqlite_create_function(x, fname, 0, time_func, (void *) 4);
1289 sqlite_function_type(x, fname, SQLITE_TEXT);
1290 fname = "current_datetime_utc";
1291 sqlite_create_function(x, fname, 0, time_func, (void *) 5);
1292 sqlite_function_type(x, fname, SQLITE_TEXT);
1293 fname = "current_timestamp_local";
1294 sqlite_create_function(x, fname, 0, time_func, (void *) 4);
1295 sqlite_function_type(x, fname, SQLITE_TEXT);
1296 fname = "current_timestamp_utc";
1297 sqlite_create_function(x, fname, 0, time_func, (void *) 5);
1298 sqlite_function_type(x, fname, SQLITE_TEXT);
1299 }
1300 return SQLITE_OK;
1301 }
1302
1303 /**
1304 * Free counted array of char pointers.
1305 * @param rowp pointer to char pointer array
1306 *
1307 * The -1-th element of the array holds the array size.
1308 * All non-NULL pointers of the array and then the array
1309 * itself are free'd.
1310 */
1311
1312 static void
freerows(char ** rowp)1313 freerows(char **rowp)
1314 {
1315 int size, i;
1316
1317 if (!rowp) {
1318 return;
1319 }
1320 --rowp;
1321 size = (PTRDIFF_T) rowp[0];
1322 for (i = 1; i <= size; i++) {
1323 freep(&rowp[i]);
1324 }
1325 freep(&rowp);
1326 }
1327
1328 /**
1329 * Map SQL field type from string to ODBC integer type code.
1330 * @param typename field type string
1331 * @param nosign pointer to indicator for unsigned field or NULL
1332 * @param ov3 boolean, true for SQL_OV_ODBC3
1333 * @param nowchar boolean, for WINTERFACE don't use WCHAR
1334 * @result SQL data type
1335 */
1336
1337 static int
mapsqltype(const char * typename,int * nosign,int ov3,int nowchar)1338 mapsqltype(const char *typename, int *nosign, int ov3, int nowchar)
1339 {
1340 char *p, *q;
1341 int testsign = 0, result;
1342
1343 #ifdef WINTERFACE
1344 result = nowchar ? SQL_VARCHAR : SQL_WVARCHAR;
1345 #else
1346 result = SQL_VARCHAR;
1347 #endif
1348 if (!typename) {
1349 return result;
1350 }
1351 q = p = xmalloc(strlen(typename) + 1);
1352 if (!p) {
1353 return result;
1354 }
1355 strcpy(p, typename);
1356 while (*q) {
1357 *q = TOLOWER(*q);
1358 ++q;
1359 }
1360 if (strncmp(p, "inter", 5) == 0) {
1361 } else if (strncmp(p, "int", 3) == 0 ||
1362 strncmp(p, "mediumint", 9) == 0) {
1363 testsign = 1;
1364 result = SQL_INTEGER;
1365 } else if (strncmp(p, "numeric", 7) == 0) {
1366 result = SQL_DOUBLE;
1367 } else if (strncmp(p, "tinyint", 7) == 0) {
1368 testsign = 1;
1369 result = SQL_TINYINT;
1370 } else if (strncmp(p, "smallint", 8) == 0) {
1371 testsign = 1;
1372 result = SQL_SMALLINT;
1373 } else if (strncmp(p, "float", 5) == 0) {
1374 result = SQL_DOUBLE;
1375 } else if (strncmp(p, "double", 6) == 0 ||
1376 strncmp(p, "real", 4) == 0) {
1377 result = SQL_DOUBLE;
1378 } else if (strncmp(p, "timestamp", 9) == 0) {
1379 #ifdef SQL_TYPE_TIMESTAMP
1380 result = ov3 ? SQL_TYPE_TIMESTAMP : SQL_TIMESTAMP;
1381 #else
1382 result = SQL_TIMESTAMP;
1383 #endif
1384 } else if (strncmp(p, "datetime", 8) == 0) {
1385 #ifdef SQL_TYPE_TIMESTAMP
1386 result = ov3 ? SQL_TYPE_TIMESTAMP : SQL_TIMESTAMP;
1387 #else
1388 result = SQL_TIMESTAMP;
1389 #endif
1390 } else if (strncmp(p, "time", 4) == 0) {
1391 #ifdef SQL_TYPE_TIME
1392 result = ov3 ? SQL_TYPE_TIME : SQL_TIME;
1393 #else
1394 result = SQL_TIME;
1395 #endif
1396 } else if (strncmp(p, "date", 4) == 0) {
1397 #ifdef SQL_TYPE_DATE
1398 result = ov3 ? SQL_TYPE_DATE : SQL_DATE;
1399 #else
1400 result = SQL_DATE;
1401 #endif
1402 #ifdef SQL_LONGVARCHAR
1403 } else if (strncmp(p, "text", 4) == 0 ||
1404 strncmp(p, "memo", 4) == 0 ||
1405 strncmp(p, "longvarchar", 11) == 0) {
1406 #ifdef WINTERFACE
1407 result = nowchar ? SQL_LONGVARCHAR : SQL_WLONGVARCHAR;
1408 #else
1409 result = SQL_LONGVARCHAR;
1410 #endif
1411 #ifdef WINTERFACE
1412 } else if (strncmp(p, "wtext", 5) == 0 ||
1413 strncmp(p, "wvarchar", 8) == 0 ||
1414 strncmp(p, "longwvarchar", 12) == 0) {
1415 result = SQL_WLONGVARCHAR;
1416 #endif
1417 #endif
1418 #if (HAVE_ENCDEC)
1419 } else if (strncmp(p, "binary", 6) == 0 ||
1420 strncmp(p, "varbinary", 9) == 0 ||
1421 strncmp(p, "bytea", 5) == 0 ||
1422 strncmp(p, "blob", 4) == 0 ||
1423 strncmp(p, "tinyblob", 8) == 0 ||
1424 strncmp(p, "mediumblob", 10) == 0) {
1425 result = SQL_VARBINARY;
1426 } else if (strncmp(p, "longbinary", 10) == 0 ||
1427 strncmp(p, "longvarbinary", 13) == 0 ||
1428 strncmp(p, "longblob", 8) == 0) {
1429 result = SQL_LONGVARBINARY;
1430 #endif
1431 #ifdef SQL_BIT
1432 } else if (strncmp(p, "bool", 4) == 0 ||
1433 strncmp(p, "bit", 3) == 0) {
1434 testsign = 0;
1435 result = SQL_BIT;
1436 #endif
1437 }
1438 if (nosign) {
1439 if (testsign) {
1440 *nosign = strstr(p, "unsigned") != NULL;
1441 } else {
1442 *nosign = 1;
1443 }
1444 }
1445 xfree(p);
1446 return result;
1447 }
1448
1449 /**
1450 * Get maximum display size and number of digits after decimal point
1451 * from field type specification.
1452 * @param typename field type specification
1453 * @param sqltype target SQL data type
1454 * @param mp pointer to maximum display size or NULL
1455 * @param dp pointer to number of digits after decimal point or NULL
1456 */
1457
1458 static void
getmd(const char * typename,int sqltype,int * mp,int * dp)1459 getmd(const char *typename, int sqltype, int *mp, int *dp)
1460 {
1461 int m = 0, d = 0;
1462
1463 switch (sqltype) {
1464 case SQL_INTEGER: m = 10; d = 9; break;
1465 case SQL_TINYINT: m = 4; d = 3; break;
1466 case SQL_SMALLINT: m = 6; d = 5; break;
1467 case SQL_FLOAT: m = 25; d = 24; break;
1468 case SQL_DOUBLE: m = 54; d = 53; break;
1469 case SQL_VARCHAR: m = 255; d = 0; break;
1470 #ifdef WINTERFACE
1471 #ifdef SQL_WVARCHAR
1472 case SQL_WVARCHAR: m = 255; d = 0; break;
1473 #endif
1474 #endif
1475 #ifdef SQL_TYPE_DATE
1476 case SQL_TYPE_DATE:
1477 #endif
1478 case SQL_DATE: m = 10; d = 0; break;
1479 #ifdef SQL_TYPE_TIME
1480 case SQL_TYPE_TIME:
1481 #endif
1482 case SQL_TIME: m = 8; d = 0; break;
1483 #ifdef SQL_TYPE_TIMESTAMP
1484 case SQL_TYPE_TIMESTAMP:
1485 #endif
1486 case SQL_TIMESTAMP: m = 32; d = 3; break;
1487 #ifdef SQL_LONGVARCHAR
1488 case SQL_LONGVARCHAR : m = 65536; d = 0; break;
1489 #endif
1490 #ifdef WINTERFACE
1491 #ifdef SQL_WLONGVARCHAR
1492 case SQL_WLONGVARCHAR: m = 65536; d = 0; break;
1493 #endif
1494 #endif
1495 #if (HAVE_ENCDEC)
1496 case SQL_BINARY:
1497 case SQL_VARBINARY: m = 255; d = 0; break;
1498 case SQL_LONGVARBINARY: m = 65536; d = 0; break;
1499 #endif
1500 #ifdef SQL_BIT
1501 case SQL_BIT: m = 1; d = 1; break;
1502 #endif
1503 }
1504 if (m && typename) {
1505 int mm, dd;
1506 char clbr[4];
1507
1508 if (sscanf(typename, "%*[^(](%d,%d %1[)]", &mm, &dd, clbr) == 3) {
1509 m = mm;
1510 d = dd;
1511 } else if (sscanf(typename, "%*[^(](%d %1[)]", &mm, clbr) == 2) {
1512 if (sqltype == SQL_TIMESTAMP) {
1513 d = mm;
1514 }
1515 #ifdef SQL_TYPE_TIMESTAMP
1516 if (sqltype == SQL_TYPE_TIMESTAMP) {
1517 d = mm;
1518 }
1519 #endif
1520 else {
1521 m = d = mm;
1522 }
1523 }
1524 }
1525 if (mp) {
1526 *mp = m;
1527 }
1528 if (dp) {
1529 *dp = d;
1530 }
1531 }
1532
1533 /**
1534 * Map SQL_C_DEFAULT to proper C type.
1535 * @param type input C type
1536 * @param stype input SQL type
1537 * @param nosign 0=signed, 0>unsigned, 0<undefined
1538 * @param nowchar when compiled with WINTERFACE don't use WCHAR
1539 * @result C type
1540 */
1541
1542 static int
mapdeftype(int type,int stype,int nosign,int nowchar)1543 mapdeftype(int type, int stype, int nosign, int nowchar)
1544 {
1545 if (type == SQL_C_DEFAULT) {
1546 switch (stype) {
1547 case SQL_INTEGER:
1548 type = (nosign > 0) ? SQL_C_ULONG : SQL_C_LONG;
1549 break;
1550 case SQL_TINYINT:
1551 type = (nosign > 0) ? SQL_C_UTINYINT : SQL_C_TINYINT;
1552 break;
1553 case SQL_SMALLINT:
1554 type = (nosign > 0) ? SQL_C_USHORT : SQL_C_SHORT;
1555 break;
1556 case SQL_FLOAT:
1557 type = SQL_C_FLOAT;
1558 break;
1559 case SQL_DOUBLE:
1560 type = SQL_C_DOUBLE;
1561 break;
1562 case SQL_TIMESTAMP:
1563 type = SQL_C_TIMESTAMP;
1564 break;
1565 case SQL_TIME:
1566 type = SQL_C_TIME;
1567 break;
1568 case SQL_DATE:
1569 type = SQL_C_DATE;
1570 break;
1571 #ifdef SQL_C_TYPE_TIMESTAMP
1572 case SQL_TYPE_TIMESTAMP:
1573 type = SQL_C_TYPE_TIMESTAMP;
1574 break;
1575 #endif
1576 #ifdef SQL_C_TYPE_TIME
1577 case SQL_TYPE_TIME:
1578 type = SQL_C_TYPE_TIME;
1579 break;
1580 #endif
1581 #ifdef SQL_C_TYPE_DATE
1582 case SQL_TYPE_DATE:
1583 type = SQL_C_TYPE_DATE;
1584 break;
1585 #endif
1586 #ifdef WINTERFACE
1587 case SQL_WVARCHAR:
1588 case SQL_WCHAR:
1589 #ifdef SQL_WLONGVARCHAR
1590 case SQL_WLONGVARCHAR:
1591 #endif
1592 type = nowchar ? SQL_C_CHAR : SQL_C_WCHAR;
1593 break;
1594 #endif
1595 #if (HAVE_ENCDEC)
1596 case SQL_BINARY:
1597 case SQL_VARBINARY:
1598 case SQL_LONGVARBINARY:
1599 type = SQL_C_BINARY;
1600 break;
1601 #endif
1602 #ifdef SQL_BIT
1603 case SQL_BIT:
1604 type = SQL_C_BIT;
1605 break;
1606 #endif
1607 default:
1608 #ifdef WINTERFACE
1609 type = nowchar ? SQL_C_CHAR : SQL_C_WCHAR;
1610 #else
1611 type = SQL_C_CHAR;
1612 #endif
1613 break;
1614 }
1615 }
1616 return type;
1617 }
1618
1619 /**
1620 * Check if query is a DDL statement.
1621 * @param sql query string
1622 * @result true or false
1623 */
1624
1625 static int
checkddl(char * sql)1626 checkddl(char *sql)
1627 {
1628 int isddl = 0;
1629
1630 while (*sql && ISSPACE(*sql)) {
1631 ++sql;
1632 }
1633 if (*sql && *sql != ';') {
1634 int i, size;
1635 static const struct {
1636 int len;
1637 const char *str;
1638 } ddlstr[] = {
1639 { 6, "attach" },
1640 { 5, "begin" },
1641 { 6, "commit" },
1642 { 6, "create" },
1643 { 6, "detach" },
1644 { 4, "drop" },
1645 { 3, "end" },
1646 { 8, "rollback" },
1647 { 6, "vacuum" }
1648 };
1649
1650 size = strlen(sql);
1651 for (i = 0; i < array_size(ddlstr); i++) {
1652 if (size >= ddlstr[i].len &&
1653 strncasecmp(sql, ddlstr[i].str, ddlstr[i].len) == 0) {
1654 isddl = 1;
1655 break;
1656 }
1657 }
1658 }
1659 return isddl;
1660 }
1661
1662 /**
1663 * Fixup query string with optional parameter markers.
1664 * @param sql original query string
1665 * @param sqlLen length of query string or SQL_NTS
1666 * @param nparam output number of parameters
1667 * @param isselect output indicator for SELECT (1) or DDL statement (2)
1668 * @param errmsg output error message
1669 * @param version SQLite version information
1670 * @param namepp pointer to parameter names array
1671 * @result newly allocated string containing query string for SQLite or NULL
1672 */
1673
1674 static char *
fixupsql(char * sql,int sqlLen,int * nparam,int * isselect,char ** errmsg,int version,char *** namepp)1675 fixupsql(char *sql, int sqlLen, int *nparam, int *isselect, char **errmsg,
1676 int version, char ***namepp)
1677 {
1678 char *q = sql, *qz = NULL, *p, *inq = NULL, *out;
1679 int np = 0, isddl = -1, size;
1680 char **npp = NULL, *ncp = NULL;
1681
1682 *errmsg = NULL;
1683 if (sqlLen != SQL_NTS) {
1684 qz = q = xmalloc(sqlLen + 1);
1685 if (!qz) {
1686 return NULL;
1687 }
1688 memcpy(q, sql, sqlLen);
1689 q[sqlLen] = '\0';
1690 size = sqlLen * 4;
1691 } else {
1692 size = strlen(sql) * 4;
1693 }
1694 size += sizeof (char *) - 1;
1695 size &= ~(sizeof (char *) - 1);
1696 p = xmalloc(2 * size + size * sizeof (char *) / 2);
1697 if (!p) {
1698 errout:
1699 freep(&qz);
1700 return NULL;
1701 }
1702 memset(p, 0, 2 * size + size * sizeof (char *) / 2);
1703 out = p;
1704 npp = (char **) (out + size);
1705 ncp = (char *) npp + size * sizeof (char *) / 2;
1706 while (*q) {
1707 switch (*q) {
1708 case '\'':
1709 case '\"':
1710 if (q == inq) {
1711 inq = NULL;
1712 } else if (!inq) {
1713 inq = q + 1;
1714
1715 while (*inq) {
1716 if (*inq == *q) {
1717 if (inq[1] == *q) {
1718 inq++;
1719 } else {
1720 break;
1721 }
1722 }
1723 inq++;
1724 }
1725 }
1726 *p++ = *q;
1727 break;
1728 case '?':
1729 if (inq) {
1730 *p++ = *q;
1731 } else {
1732 *p++ = '%';
1733 *p++ = 'Q';
1734 npp[np] = ncp;
1735 *ncp = '\0';
1736 ++ncp;
1737 np++;
1738 }
1739 break;
1740 case ':': /* ORACLE-style named parameter */
1741 case '@': /* ADO.NET-style named parameter */
1742 if (inq) {
1743 *p++ = *q;
1744 } else {
1745 int n = -1;
1746
1747 do {
1748 ++q;
1749 ++n;
1750 } while (*q && ISIDCHAR(*q));
1751 if (n > 0) {
1752 *p++ = '%';
1753 *p++ = 'Q';
1754 npp[np] = ncp;
1755 memcpy(ncp, q - n, n);
1756 ncp[n] = '\0';
1757 ncp += n + 1;
1758 np++;
1759 }
1760 --q;
1761 }
1762 break;
1763 case ';':
1764 if (!inq) {
1765 if (isddl < 0) {
1766 isddl = checkddl(out);
1767 }
1768 if (isddl == 0) {
1769 char *qq = q;
1770
1771 do {
1772 ++qq;
1773 } while (*qq && ISSPACE(*qq));
1774 if (*qq && *qq != ';') {
1775 freep(&out);
1776 *errmsg = "only one SQL statement allowed";
1777 goto errout;
1778 }
1779 }
1780 }
1781 *p++ = *q;
1782 break;
1783 case '%':
1784 *p++ = '%';
1785 *p++ = '%';
1786 break;
1787 case '{':
1788 /*
1789 * Deal with escape sequences:
1790 * {d 'YYYY-MM-DD'}, {t ...}, {ts ...}
1791 * {oj ...}, {fn ...} etc.
1792 */
1793 if (!inq) {
1794 int ojfn = 0;
1795 char *inq2 = NULL, *end = q + 1, *start;
1796
1797 while (*end && ISSPACE(*end)) {
1798 ++end;
1799 }
1800 if (*end != 'd' && *end != 'D' &&
1801 *end != 't' && *end != 'T') {
1802 ojfn = 1;
1803 }
1804 start = end;
1805 while (*end) {
1806 if (inq2 && *end == *inq2) {
1807 inq2 = NULL;
1808 } else if (inq2 == NULL && *end == '}') {
1809 break;
1810 } else if (inq2 == NULL && (*end == '\'' || *end == '"')) {
1811 inq2 = end;
1812 }
1813 ++end;
1814 }
1815 if (*end == '}') {
1816 char *end2 = end - 1;
1817
1818 if (ojfn) {
1819 while (start < end) {
1820 if (ISSPACE(*start)) {
1821 break;
1822 }
1823 ++start;
1824 }
1825 while (start < end) {
1826 *p++ = *start;
1827 ++start;
1828 }
1829 q = end;
1830 break;
1831 } else {
1832 while (start < end2 && *start != '\'') {
1833 ++start;
1834 }
1835 while (end2 > start && *end2 != '\'') {
1836 --end2;
1837 }
1838 if (*start == '\'' && *end2 == '\'') {
1839 while (start <= end2) {
1840 *p++ = *start;
1841 ++start;
1842 }
1843 q = end;
1844 break;
1845 }
1846 }
1847 }
1848 }
1849 /* FALL THROUGH */
1850 default:
1851 *p++ = *q;
1852 }
1853 ++q;
1854 }
1855 freep(&qz);
1856 *p = '\0';
1857 if (nparam) {
1858 *nparam = np;
1859 }
1860 if (isselect) {
1861 if (isddl < 0) {
1862 isddl = checkddl(out);
1863 }
1864 if (isddl > 0) {
1865 *isselect = 2;
1866 } else {
1867 int incom = 0;
1868
1869 p = out;
1870 while (*p) {
1871 switch (*p) {
1872 case '-':
1873 if (!incom && p[1] == '-') {
1874 incom = -1;
1875 }
1876 break;
1877 case '\n':
1878 if (incom < 0) {
1879 incom = 0;
1880 }
1881 break;
1882 case '/':
1883 if (incom > 0 && p[-1] == '*') {
1884 incom = 0;
1885 p++;
1886 continue;
1887 } else if (!incom && p[1] == '*') {
1888 incom = 1;
1889 }
1890 break;
1891 }
1892 if (!incom && !ISSPACE(*p)) {
1893 break;
1894 }
1895 ++p;
1896 }
1897 size = strlen(p);
1898 if (size >= 6 &&
1899 (strncasecmp(p, "select", 6) == 0 ||
1900 strncasecmp(p, "pragma", 6) == 0)) {
1901 *isselect = 1;
1902 } else if (size >= 7 &&
1903 strncasecmp(p, "explain", 7) == 0) {
1904 *isselect = 1;
1905 } else {
1906 *isselect = 0;
1907 }
1908 }
1909 }
1910 if (namepp) {
1911 *namepp = npp;
1912 }
1913 return out;
1914 }
1915
1916 /**
1917 * Find column given name in string array.
1918 * @param cols string array
1919 * @param ncols number of strings
1920 * @param name column name
1921 * @result >= 0 on success, -1 on error
1922 */
1923
1924 static int
findcol(char ** cols,int ncols,char * name)1925 findcol(char **cols, int ncols, char *name)
1926 {
1927 int i;
1928
1929 if (cols) {
1930 for (i = 0; i < ncols; i++) {
1931 if (strcmp(cols[i], name) == 0) {
1932 return i;
1933 }
1934 }
1935 }
1936 return -1;
1937 }
1938
1939 /**
1940 * Fixup column information for a running statement.
1941 * @param s statement to get fresh column information
1942 * @param sqlite SQLite database handle
1943 * @param types column types or NULL
1944 *
1945 * The column labels get the table names stripped
1946 * when there's more than one column and all table
1947 * names are identical.
1948 *
1949 * The "dyncols" field of STMT is filled with column
1950 * information obtained by SQLite "PRAGMA table_info"
1951 * for each column whose table name is known. If the
1952 * types are already present as with SQLite 2.5.7
1953 * this information is used instead.
1954 */
1955
1956 static void
fixupdyncols(STMT * s,sqlite * sqlite,const char ** types)1957 fixupdyncols(STMT *s, sqlite *sqlite, const char **types)
1958 {
1959 int i, k, pk, nn, t, r, nrows, ncols;
1960 char **rowp, *flagp, flags[128];
1961
1962 if (!s->dyncols) {
1963 return;
1964 }
1965 /* fixup labels */
1966 if (!s->longnames) {
1967 if (s->dcols > 1) {
1968 char *table = s->dyncols[0].table;
1969
1970 for (i = 1; table[0] && i < s->dcols; i++) {
1971 if (strcmp(s->dyncols[i].table, table)) {
1972 break;
1973 }
1974 }
1975 if (i >= s->dcols) {
1976 for (i = 0; i < s->dcols; i++) {
1977 s->dyncols[i].label = s->dyncols[i].column;
1978 }
1979 }
1980 } else if (s->dcols == 1) {
1981 s->dyncols[0].label = s->dyncols[0].column;
1982 }
1983 }
1984 if (types) {
1985 for (i = 0; i < s->dcols; i++) {
1986 freep(&s->dyncols[i].typename);
1987 s->dyncols[i].typename = xstrdup(types[i] ? types[i] : "text");
1988 s->dyncols[i].type =
1989 mapsqltype(types[i], &s->dyncols[i].nosign, *s->ov3,
1990 s->nowchar[0] || s->nowchar[1]);
1991 getmd(types[i], s->dyncols[i].type, &s->dyncols[i].size,
1992 &s->dyncols[i].prec);
1993 #ifdef SQL_LONGVARCHAR
1994 if (s->dyncols[i].type == SQL_VARCHAR &&
1995 s->dyncols[i].size > 255) {
1996 s->dyncols[i].type = SQL_LONGVARCHAR;
1997 }
1998 #endif
1999 #ifdef WINTERFACE
2000 #ifdef SQL_WLONGVARCHAR
2001 if (s->dyncols[i].type == SQL_WVARCHAR &&
2002 s->dyncols[i].size > 255) {
2003 s->dyncols[i].type = SQL_WLONGVARCHAR;
2004 }
2005 #endif
2006 #endif
2007 #if (HAVE_ENCDEC)
2008 if (s->dyncols[i].type == SQL_VARBINARY &&
2009 s->dyncols[i].size > 255) {
2010 s->dyncols[i].type = SQL_LONGVARBINARY;
2011 }
2012 #endif
2013 }
2014 }
2015 if (s->dcols > array_size(flags)) {
2016 flagp = xmalloc(sizeof (flags[0]) * s->dcols);
2017 if (flagp == NULL) {
2018 return;
2019 }
2020 } else {
2021 flagp = flags;
2022 }
2023 memset(flagp, 0, sizeof (flags[0]) * s->dcols);
2024 for (i = 0; i < s->dcols; i++) {
2025 s->dyncols[i].autoinc = SQL_FALSE;
2026 s->dyncols[i].notnull = SQL_NULLABLE;
2027 }
2028 for (i = 0; i < s->dcols; i++) {
2029 int ret, lastpk = -1, autoinccount = 0;
2030
2031 if (!s->dyncols[i].table[0]) {
2032 continue;
2033 }
2034 if (flagp[i]) {
2035 continue;
2036 }
2037 ret = sqlite_get_table_printf(sqlite,
2038 "PRAGMA table_info('%q')", &rowp,
2039 &nrows, &ncols, NULL,
2040 s->dyncols[i].table);
2041 if (ret != SQLITE_OK) {
2042 continue;
2043 }
2044 k = findcol(rowp, ncols, "name");
2045 t = findcol(rowp, ncols, "type");
2046 pk = findcol(rowp, ncols, "pk");
2047 nn = findcol(rowp, ncols, "notnull");
2048 if (k < 0 || t < 0) {
2049 goto freet;
2050 }
2051 for (r = 1; r <= nrows; r++) {
2052 int m;
2053
2054 for (m = i; m < s->dcols; m++) {
2055 if (!flagp[m] &&
2056 strcmp(s->dyncols[m].column, rowp[r * ncols + k]) == 0 &&
2057 strcmp(s->dyncols[m].table, s->dyncols[i].table) == 0) {
2058 char *typename = rowp[r * ncols + t];
2059
2060 flagp[m] = 1;
2061 freep(&s->dyncols[m].typename);
2062 s->dyncols[m].typename = xstrdup(typename);
2063 s->dyncols[m].type =
2064 mapsqltype(typename, &s->dyncols[m].nosign, *s->ov3,
2065 s->nowchar[0] || s->nowchar[1]);
2066 getmd(typename, s->dyncols[m].type, &s->dyncols[m].size,
2067 &s->dyncols[m].prec);
2068 #ifdef SQL_LONGVARCHAR
2069 if (s->dyncols[m].type == SQL_VARCHAR &&
2070 s->dyncols[m].size > 255) {
2071 s->dyncols[m].type = SQL_LONGVARCHAR;
2072 }
2073 #endif
2074 #ifdef WINTERFACE
2075 #ifdef SQL_WLONGVARCHAR
2076 if (s->dyncols[i].type == SQL_WVARCHAR &&
2077 s->dyncols[i].size > 255) {
2078 s->dyncols[i].type = SQL_WLONGVARCHAR;
2079 }
2080 #endif
2081 #endif
2082 #if (HAVE_ENCDEC)
2083 if (s->dyncols[i].type == SQL_VARBINARY &&
2084 s->dyncols[i].size > 255) {
2085 s->dyncols[i].type = SQL_LONGVARBINARY;
2086 }
2087 #endif
2088 if (pk >= 0 && strcmp(rowp[r * ncols + pk], "1") == 0) {
2089 if (++autoinccount > 1) {
2090 if (lastpk >= 0) {
2091 s->dyncols[lastpk].autoinc = SQL_FALSE;
2092 lastpk = -1;
2093 }
2094 } else {
2095 lastpk = m;
2096 if (strlen(typename) == 7 &&
2097 strncasecmp(typename, "integer", 7) == 0) {
2098 s->dyncols[m].autoinc = SQL_TRUE;
2099 }
2100 }
2101 }
2102 if (nn >= 0 && rowp[r * ncols + nn][0] != '0') {
2103 s->dyncols[m].notnull = SQL_NO_NULLS;
2104 }
2105 }
2106 }
2107 }
2108 freet:
2109 sqlite_free_table(rowp);
2110 }
2111 if (flagp != flags) {
2112 freep(&flagp);
2113 }
2114 }
2115
2116 /**
2117 * Return number of month days.
2118 * @param year
2119 * @param month 1..12
2120 * @result number of month days or 0
2121 */
2122
2123 static int
getmdays(int year,int month)2124 getmdays(int year, int month)
2125 {
2126 static const int mdays[] = {
2127 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31
2128 };
2129 int mday;
2130
2131 if (month < 1) {
2132 return 0;
2133 }
2134 mday = mdays[(month - 1) % 12];
2135 if (mday == 28 && year % 4 == 0 &&
2136 (!(year % 100 == 0) || year % 400 == 0)) {
2137 mday++;
2138 }
2139 return mday;
2140 }
2141
2142 /**
2143 * Convert string to ODBC DATE_STRUCT.
2144 * @param str string to be converted
2145 * @param ds output DATE_STRUCT
2146 * @result 0 on success, -1 on error
2147 *
2148 * Strings of the format 'YYYYMMDD' or 'YYYY-MM-DD' or
2149 * 'YYYY/MM/DD' or 'MM/DD/YYYY' are converted to a
2150 * DATE_STRUCT.
2151 */
2152
2153 static int
str2date(char * str,DATE_STRUCT * ds)2154 str2date(char *str, DATE_STRUCT *ds)
2155 {
2156 int i, err = 0;
2157 char *p, *q, sepc = '\0';
2158
2159 ds->year = ds->month = ds->day = 0;
2160 p = str;
2161 while (*p && !ISDIGIT(*p)) {
2162 ++p;
2163 }
2164 q = p;
2165 i = 0;
2166 while (*q && !ISDIGIT(*q)) {
2167 ++i;
2168 ++q;
2169 }
2170 if (i >= 8) {
2171 char buf[8];
2172
2173 strncpy(buf, p + 0, 4); buf[4] = '\0';
2174 ds->year = strtol(buf, NULL, 10);
2175 strncpy(buf, p + 4, 2); buf[2] = '\0';
2176 ds->month = strtol(buf, NULL, 10);
2177 strncpy(buf, p + 6, 2); buf[2] = '\0';
2178 ds->day = strtol(buf, NULL, 10);
2179 goto done;
2180 }
2181 i = 0;
2182 while (i < 3) {
2183 int n;
2184
2185 q = NULL;
2186 n = strtol(p, &q, 10);
2187 if (!q || q == p) {
2188 if (*q == '\0') {
2189 if (i == 0) {
2190 err = 1;
2191 }
2192 goto done;
2193 }
2194 }
2195 if (!sepc) {
2196 sepc = *q;
2197 }
2198 if (*q == '-' || *q == '/' || *q == '\0' || i == 2) {
2199 switch (i) {
2200 case 0: ds->year = n; break;
2201 case 1: ds->month = n; break;
2202 case 2: ds->day = n; break;
2203 }
2204 ++i;
2205 if (*q) {
2206 ++q;
2207 }
2208 } else {
2209 i = 0;
2210 while (*q && !ISDIGIT(*q)) {
2211 ++q;
2212 }
2213 }
2214 p = q;
2215 }
2216 done:
2217 /* final check for overflow */
2218 if (err ||
2219 ds->month < 1 || ds->month > 12 ||
2220 ds->day < 1 || ds->day > getmdays(ds->year, ds->month)) {
2221 if (sepc == '/') {
2222 /* Try MM/DD/YYYY format */
2223 int t[3];
2224
2225 t[0] = ds->year;
2226 t[1] = ds->month;
2227 t[2] = ds->day;
2228 ds->year = t[2];
2229 ds->day = t[1];
2230 ds->month = t[0];
2231 if (ds->month >= 1 && ds->month <= 12 &&
2232 ds->day >= 1 && ds->day <= getmdays(ds->year, ds->month)) {
2233 return 0;
2234 }
2235 }
2236 return -1;
2237 }
2238 return 0;
2239 }
2240
2241 /**
2242 * Convert string to ODBC TIME_STRUCT.
2243 * @param str string to be converted
2244 * @param ts output TIME_STRUCT
2245 * @result 0 on success, -1 on error
2246 *
2247 * Strings of the format 'HHMMSS' or 'HH:MM:SS'
2248 * are converted to a TIME_STRUCT.
2249 */
2250
2251 static int
str2time(char * str,TIME_STRUCT * ts)2252 str2time(char *str, TIME_STRUCT *ts)
2253 {
2254 int i, err = 0, ampm = -1;
2255 char *p, *q;
2256
2257 ts->hour = ts->minute = ts->second = 0;
2258 p = str;
2259 while (*p && !ISDIGIT(*p)) {
2260 ++p;
2261 }
2262 q = p;
2263 i = 0;
2264 while (*q && ISDIGIT(*q)) {
2265 ++i;
2266 ++q;
2267 }
2268 if (i >= 6) {
2269 char buf[4];
2270
2271 strncpy(buf, p + 0, 2); buf[2] = '\0';
2272 ts->hour = strtol(buf, NULL, 10);
2273 strncpy(buf, p + 2, 2); buf[2] = '\0';
2274 ts->minute = strtol(buf, NULL, 10);
2275 strncpy(buf, p + 4, 2); buf[2] = '\0';
2276 ts->second = strtol(buf, NULL, 10);
2277 goto done;
2278 }
2279 i = 0;
2280 while (i < 3) {
2281 int n;
2282
2283 q = NULL;
2284 n = strtol(p, &q, 10);
2285 if (!q || q == p) {
2286 if (*q == '\0') {
2287 if (i == 0) {
2288 err = 1;
2289 }
2290 goto done;
2291 }
2292 }
2293 if (*q == ':' || *q == '\0' || i == 2) {
2294 switch (i) {
2295 case 0: ts->hour = n; break;
2296 case 1: ts->minute = n; break;
2297 case 2: ts->second = n; break;
2298 }
2299 ++i;
2300 if (*q) {
2301 ++q;
2302 }
2303 } else {
2304 i = 0;
2305 while (*q && !ISDIGIT(*q)) {
2306 ++q;
2307 }
2308 }
2309 p = q;
2310 }
2311 if (!err) {
2312 while (*p) {
2313 if ((p[0] == 'p' || p[0] == 'P') &&
2314 (p[1] == 'm' || p[1] == 'M')) {
2315 ampm = 1;
2316 } else if ((p[0] == 'a' || p[0] == 'A') &&
2317 (p[1] == 'm' || p[1] == 'M')) {
2318 ampm = 0;
2319 }
2320 ++p;
2321 }
2322 if (ampm > 0) {
2323 if (ts->hour < 12) {
2324 ts->hour += 12;
2325 }
2326 } else if(ampm == 0) {
2327 if (ts->hour == 12) {
2328 ts->hour = 0;
2329 }
2330 }
2331 }
2332 done:
2333 /* final check for overflow */
2334 if (err || ts->hour > 23 || ts->minute > 59 || ts->second > 59) {
2335 return -1;
2336 }
2337 return 0;
2338 }
2339
2340 /**
2341 * Convert string to ODBC TIMESTAMP_STRUCT.
2342 * @param str string to be converted
2343 * @param tss output TIMESTAMP_STRUCT
2344 * @result 0 on success, -1 on error
2345 *
2346 * Strings of the format 'YYYYMMDDhhmmssff' or 'YYYY-MM-DD hh:mm:ss ff'
2347 * or 'YYYY/MM/DD hh:mm:ss ff' or 'hh:mm:ss ff YYYY-MM-DD' are
2348 * converted to a TIMESTAMP_STRUCT. The ISO8601 formats
2349 * YYYY-MM-DDThh:mm:ss[.f]Z
2350 * YYYY-MM-DDThh:mm:ss[.f]shh:mm
2351 * are also supported. In case a time zone field is present,
2352 * the resulting TIMESTAMP_STRUCT is expressed in UTC.
2353 */
2354
2355 static int
str2timestamp(char * str,TIMESTAMP_STRUCT * tss)2356 str2timestamp(char *str, TIMESTAMP_STRUCT *tss)
2357 {
2358 int i, m, n, err = 0, ampm = -1;
2359 char *p, *q, in = '\0', sepc = '\0';
2360
2361 tss->year = tss->month = tss->day = 0;
2362 tss->hour = tss->minute = tss->second = 0;
2363 tss->fraction = 0;
2364 p = str;
2365 while (*p && !ISDIGIT(*p)) {
2366 ++p;
2367 }
2368 q = p;
2369 i = 0;
2370 while (*q && ISDIGIT(*q)) {
2371 ++i;
2372 ++q;
2373 }
2374 if (i >= 14) {
2375 char buf[16];
2376
2377 strncpy(buf, p + 0, 4); buf[4] = '\0';
2378 tss->year = strtol(buf, NULL, 10);
2379 strncpy(buf, p + 4, 2); buf[2] = '\0';
2380 tss->month = strtol(buf, NULL, 10);
2381 strncpy(buf, p + 6, 2); buf[2] = '\0';
2382 tss->day = strtol(buf, NULL, 10);
2383 strncpy(buf, p + 8, 2); buf[2] = '\0';
2384 tss->hour = strtol(buf, NULL, 10);
2385 strncpy(buf, p + 10, 2); buf[2] = '\0';
2386 tss->minute = strtol(buf, NULL, 10);
2387 strncpy(buf, p + 12, 2); buf[2] = '\0';
2388 tss->second = strtol(buf, NULL, 10);
2389 if (i > 14) {
2390 m = i - 14;
2391 strncpy(buf, p + 14, m);
2392 while (m < 9) {
2393 buf[m] = '0';
2394 ++m;
2395 }
2396 buf[m] = '\0';
2397 tss->fraction = strtol(buf, NULL, 10);
2398 }
2399 m = 7;
2400 goto done;
2401 }
2402 m = i = 0;
2403 while ((m & 7) != 7) {
2404 q = NULL;
2405 n = strtol(p, &q, 10);
2406 if (!q || q == p) {
2407 if (*q == '\0') {
2408 if (m < 1) {
2409 err = 1;
2410 }
2411 goto done;
2412 }
2413 }
2414 if (in == '\0') {
2415 switch (*q) {
2416 case '-':
2417 case '/':
2418 if ((m & 1) == 0) {
2419 in = *q;
2420 i = 0;
2421 }
2422 break;
2423 case ':':
2424 if ((m & 2) == 0) {
2425 in = *q;
2426 i = 0;
2427 }
2428 break;
2429 case ' ':
2430 case '.':
2431 break;
2432 default:
2433 in = '\0';
2434 i = 0;
2435 break;
2436 }
2437 }
2438 switch (in) {
2439 case '-':
2440 case '/':
2441 if (!sepc) {
2442 sepc = in;
2443 }
2444 switch (i) {
2445 case 0: tss->year = n; break;
2446 case 1: tss->month = n; break;
2447 case 2: tss->day = n; break;
2448 }
2449 if (++i >= 3) {
2450 i = 0;
2451 m |= 1;
2452 if (!(m & 2)) {
2453 m |= 8;
2454 }
2455 goto skip;
2456 } else {
2457 ++q;
2458 }
2459 break;
2460 case ':':
2461 switch (i) {
2462 case 0: tss->hour = n; break;
2463 case 1: tss->minute = n; break;
2464 case 2: tss->second = n; break;
2465 }
2466 if (++i >= 3) {
2467 i = 0;
2468 m |= 2;
2469 if (*q == '.') {
2470 in = '.';
2471 goto skip2;
2472 }
2473 if (*q == ' ') {
2474 if ((m & 1) == 0) {
2475 char *e = NULL;
2476
2477 (void) strtol(q + 1, &e, 10);
2478 if (e && *e == '-') {
2479 goto skip;
2480 }
2481 }
2482 in = '.';
2483 goto skip2;
2484 }
2485 goto skip;
2486 } else {
2487 ++q;
2488 }
2489 break;
2490 case '.':
2491 if (++i >= 1) {
2492 int ndig = q - p;
2493
2494 if (p[0] == '+' || p[0] == '-') {
2495 ndig--;
2496 }
2497 while (ndig < 9) {
2498 n = n * 10;
2499 ++ndig;
2500 }
2501 tss->fraction = n;
2502 m |= 4;
2503 i = 0;
2504 }
2505 default:
2506 skip:
2507 in = '\0';
2508 skip2:
2509 while (*q && !ISDIGIT(*q)) {
2510 if ((q[0] == 'a' || q[0] == 'A') &&
2511 (q[1] == 'm' || q[1] == 'M')) {
2512 ampm = 0;
2513 ++q;
2514 } else if ((q[0] == 'p' || q[0] == 'P') &&
2515 (q[1] == 'm' || q[1] == 'M')) {
2516 ampm = 1;
2517 ++q;
2518 }
2519 ++q;
2520 }
2521 }
2522 p = q;
2523 }
2524 if ((m & 7) > 1 && (m & 8)) {
2525 /* ISO8601 timezone */
2526 if (p > str && ISDIGIT(*p)) {
2527 int nn, sign;
2528
2529 q = p - 1;
2530 if (*q != '+' && *q != '-') {
2531 goto done;
2532 }
2533 sign = (*q == '+') ? -1 : 1;
2534 q = NULL;
2535 n = strtol(p, &q, 10);
2536 if (!q || *q++ != ':' || !ISDIGIT(*q)) {
2537 goto done;
2538 }
2539 p = q;
2540 q = NULL;
2541 nn = strtol(p, &q, 10);
2542 tss->minute += nn * sign;
2543 if ((SQLSMALLINT) tss->minute < 0) {
2544 tss->hour -= 1;
2545 tss->minute += 60;
2546 } else if (tss->minute >= 60) {
2547 tss->hour += 1;
2548 tss->minute -= 60;
2549 }
2550 tss->hour += n * sign;
2551 if ((SQLSMALLINT) tss->hour < 0) {
2552 tss->day -= 1;
2553 tss->hour += 24;
2554 } else if (tss->hour >= 24) {
2555 tss->day += 1;
2556 tss->hour -= 24;
2557 }
2558 if ((short) tss->day < 1 || tss->day >= 28) {
2559 int mday, pday, pmon;
2560
2561 mday = getmdays(tss->year, tss->month);
2562 pmon = tss->month - 1;
2563 if (pmon < 1) {
2564 pmon = 12;
2565 }
2566 pday = getmdays(tss->year, pmon);
2567 if ((SQLSMALLINT) tss->day < 1) {
2568 tss->month -= 1;
2569 tss->day = pday;
2570 } else if (tss->day > mday) {
2571 tss->month += 1;
2572 tss->day = 1;
2573 }
2574 if ((SQLSMALLINT) tss->month < 1) {
2575 tss->year -= 1;
2576 tss->month = 12;
2577 } else if (tss->month > 12) {
2578 tss->year += 1;
2579 tss->month = 1;
2580 }
2581 }
2582 }
2583 }
2584 done:
2585 if ((m & 1) &&
2586 (tss->month < 1 || tss->month > 12 ||
2587 tss->day < 1 || tss->day > getmdays(tss->year, tss->month))) {
2588 if (sepc == '/') {
2589 /* Try MM/DD/YYYY format */
2590 int t[3];
2591
2592 t[0] = tss->year;
2593 t[1] = tss->month;
2594 t[2] = tss->day;
2595 tss->year = t[2];
2596 tss->day = t[1];
2597 tss->month = t[0];
2598 }
2599 }
2600 /* Replace missing year/month/day with current date */
2601 if (!err && (m & 1) == 0) {
2602 #ifdef _WIN32
2603 SYSTEMTIME t;
2604
2605 GetLocalTime(&t);
2606 tss->year = t.wYear;
2607 tss->month = t.wMonth;
2608 tss->day = t.wDay;
2609 #else
2610 struct timeval tv;
2611 struct tm tm;
2612
2613 gettimeofday(&tv, NULL);
2614 tm = *localtime(&tv.tv_sec);
2615 tss->year = tm.tm_year + 1900;
2616 tss->month = tm.tm_mon + 1;
2617 tss->day = tm.tm_mday;
2618 #endif
2619 }
2620 /* Normalize fraction */
2621 if (tss->fraction < 0) {
2622 tss->fraction = 0;
2623 }
2624 /* Final check for overflow */
2625 if (err ||
2626 tss->month < 1 || tss->month > 12 ||
2627 tss->day < 1 || tss->day > getmdays(tss->year, tss->month) ||
2628 tss->hour > 23 || tss->minute > 59 || tss->second > 59) {
2629 return -1;
2630 }
2631 if ((m & 7) > 1) {
2632 if (ampm > 0) {
2633 if (tss->hour < 12) {
2634 tss->hour += 12;
2635 }
2636 } else if (ampm == 0) {
2637 if (tss->hour == 12) {
2638 tss->hour = 0;
2639 }
2640 }
2641 }
2642 return ((m & 7) < 1) ? -1 : 0;
2643 }
2644
2645 /**
2646 * Get boolean flag from string.
2647 * @param string string to be inspected
2648 * @result true or false
2649 */
2650
2651 static int
getbool(char * string)2652 getbool(char *string)
2653 {
2654 if (string) {
2655 return string[0] && strchr("Yy123456789Tt", string[0]) != NULL;
2656 }
2657 return 0;
2658 }
2659
2660 #if defined(HAVE_SQLITETRACE) && (HAVE_SQLITETRACE)
2661 /**
2662 * SQLite trace callback
2663 * @param arg DBC pointer
2664 */
2665
2666 static void
dbtrace(void * arg,const char * msg)2667 dbtrace(void *arg, const char *msg)
2668 {
2669 DBC *d = (DBC *) arg;
2670
2671 if (msg && d->trace) {
2672 int len = strlen(msg);
2673
2674 if (len > 0) {
2675 char *end = "\n";
2676
2677 if (msg[len - 1] != ';') {
2678 end = ";\n";
2679 }
2680 fprintf(d->trace, "%s%s", msg, end);
2681 fflush(d->trace);
2682 }
2683 }
2684 }
2685
2686 /**
2687 * Trace function for SQLite return codes
2688 * @param rc SQLite return code
2689 * @param err error string or NULL
2690 */
2691
2692 static void
dbtracerc(DBC * d,int rc,char * err)2693 dbtracerc(DBC *d, int rc, char *err)
2694 {
2695 if (rc != SQLITE_OK && d->trace) {
2696 fprintf(d->trace, "-- SQLITE ERROR CODE %d", rc);
2697 fprintf(d->trace, err ? ": %s\n" : "\n", err);
2698 fflush(d->trace);
2699 }
2700 }
2701 #else
2702
2703 #define dbtracerc(a,b,c)
2704
2705 #endif
2706
2707 /**
2708 * Open SQLite database file given file name and flags.
2709 * @param d DBC pointer
2710 * @param name file name
2711 * @param dsn data source name
2712 * @param sflag STEPAPI flag
2713 * @param sflag NoTXN flag
2714 * @param busy busy/lock timeout
2715 * @result ODBC error code
2716 */
2717
2718 static SQLRETURN
dbopen(DBC * d,char * name,char * dsn,char * sflag,char * ntflag,char * busy)2719 dbopen(DBC *d, char *name, char *dsn, char *sflag, char *ntflag, char *busy)
2720 {
2721 char *errp = NULL, *endp = NULL;
2722 int tmp, busyto = 100000;
2723 #if defined(_WIN32) || defined(_WIN64)
2724 char expname[MAX_PATH];
2725 #endif
2726
2727 if (d->sqlite) {
2728 sqlite_close(d->sqlite);
2729 d->sqlite = NULL;
2730 }
2731 #if defined(_WIN32) || defined(_WIN64)
2732 expname[0] = '\0';
2733 tmp = ExpandEnvironmentStrings(name, expname, sizeof (expname));
2734 if (tmp <= sizeof (expname)) {
2735 name = expname;
2736 }
2737 #endif
2738 d->sqlite = sqlite_open(name, 0, &errp);
2739 if (d->sqlite == NULL) {
2740 connfail:
2741 setstatd(d, -1, "%s", (*d->ov3) ? "HY000" : "S1000",
2742 errp ? errp : "connect failed");
2743 if (errp) {
2744 sqlite_freemem(errp);
2745 errp = NULL;
2746 }
2747 return SQL_ERROR;
2748 }
2749 if (errp) {
2750 sqlite_freemem(errp);
2751 errp = NULL;
2752 }
2753 #if defined(HAVE_SQLITETRACE) && (HAVE_SQLITETRACE)
2754 if (d->trace) {
2755 sqlite_trace(d->sqlite, dbtrace, d);
2756 }
2757 #endif
2758 d->step_enable = getbool(sflag);
2759 d->trans_disable = getbool(ntflag);
2760 d->curtype = d->step_enable ?
2761 SQL_CURSOR_FORWARD_ONLY : SQL_CURSOR_STATIC;
2762 tmp = strtol(busy, &endp, 0);
2763 if (endp && *endp == '\0' && endp != busy) {
2764 busyto = tmp;
2765 }
2766 if (busyto < 1 || busyto > 1000000) {
2767 busyto = 1000000;
2768 }
2769 d->timeout = busyto;
2770 freep(&d->dbname);
2771 d->dbname = xstrdup(name);
2772 freep(&d->dsn);
2773 d->dsn = xstrdup(dsn);
2774 if (setsqliteopts(d->sqlite, d) != SQLITE_OK) {
2775 sqlite_close(d->sqlite);
2776 d->sqlite = NULL;
2777 goto connfail;
2778 }
2779 #if defined(_WIN32) || defined(_WIN64)
2780 {
2781 char pname[MAX_PATH];
2782 HANDLE h = OpenProcess(PROCESS_QUERY_INFORMATION | PROCESS_VM_READ,
2783 FALSE, GetCurrentProcessId());
2784
2785 pname[0] = '\0';
2786 if (h) {
2787 HMODULE m = NULL, l = LoadLibrary("psapi.dll");
2788 DWORD need;
2789 typedef BOOL (WINAPI *epmfunc)(HANDLE, HMODULE *, DWORD, LPDWORD);
2790 typedef BOOL (WINAPI *gmbfunc)(HANDLE, HMODULE, LPSTR, DWORD);
2791 epmfunc epm;
2792 gmbfunc gmb;
2793
2794 if (l) {
2795 epm = (epmfunc) GetProcAddress(l, "EnumProcessModules");
2796 gmb = (gmbfunc) GetProcAddress(l, "GetModuleBaseNameA");
2797 if (epm && gmb && epm(h, &m, sizeof (m), &need)) {
2798 gmb(h, m, pname, sizeof (pname));
2799 }
2800 FreeLibrary(l);
2801 }
2802 CloseHandle(h);
2803 }
2804 d->xcelqrx = strncasecmp(pname, "EXCEL", 5) == 0 ||
2805 strncasecmp(pname, "MSQRY", 5) == 0;
2806 if (d->trace && d->xcelqrx) {
2807 fprintf(d->trace, "-- enabled EXCEL quirks\n");
2808 fflush(d->trace);
2809 }
2810 }
2811 #endif
2812 return SQL_SUCCESS;
2813 }
2814
2815 /**
2816 * Do one VM step gathering one result row
2817 * @param s statement pointer
2818 * @result ODBC error code
2819 */
2820
2821 static int
vm_step(STMT * s)2822 vm_step(STMT *s)
2823 {
2824 DBC *d = (DBC *) s->dbc;
2825 char **rowd = NULL, *errp = NULL;
2826 const char **values, **cols;
2827 int i, ncols, rc;
2828
2829 if (s != d->vm_stmt || !s->vm) {
2830 setstat(s, -1, "stale statement", (*s->ov3) ? "HY000" : "S1000");
2831 return SQL_ERROR;
2832 }
2833 rc = sqlite_step(s->vm, &ncols, &values, &cols);
2834 if (rc == SQLITE_ROW || rc == SQLITE_DONE) {
2835 ++d->vm_rownum;
2836 if (d->vm_rownum == 0 && cols && ncols > 0) {
2837 int size;
2838 char *p;
2839 COL *dyncols;
2840
2841 for (i = size = 0; i < ncols; i++) {
2842 size += 3 + 3 * strlen(cols[i]);
2843 }
2844 dyncols = xmalloc(ncols * sizeof (COL) + size);
2845 if (!dyncols) {
2846 freedyncols(s);
2847 s->ncols = 0;
2848 sqlite_finalize(s->vm, NULL);
2849 s->vm = NULL;
2850 d->vm_stmt = NULL;
2851 return nomem(s);
2852 }
2853 p = (char *) (dyncols + ncols);
2854 for (i = 0; i < ncols; i++) {
2855 char *q;
2856
2857 dyncols[i].db = ((DBC *) (s->dbc))->dbname;
2858 strcpy(p, cols[i]);
2859 dyncols[i].label = p;
2860 p += strlen(p) + 1;
2861 q = strchr(cols[i], '.');
2862 if (q) {
2863 dyncols[i].table = p;
2864 strncpy(p, cols[i], q - cols[i]);
2865 p[q - cols[i]] = '\0';
2866 p += strlen(p) + 1;
2867 strcpy(p, q + 1);
2868 dyncols[i].column = p;
2869 p += strlen(p) + 1;
2870 } else {
2871 dyncols[i].table = "";
2872 strcpy(p, cols[i]);
2873 dyncols[i].column = p;
2874 p += strlen(p) + 1;
2875 }
2876 if (s->longnames) {
2877 dyncols[i].column = dyncols[i].label;
2878 }
2879 #ifdef SQL_LONGVARCHAR
2880 dyncols[i].type = SQL_LONGVARCHAR;
2881 dyncols[i].size = 65535;
2882 #else
2883 dyncols[i].type = SQL_VARCHAR;
2884 dyncols[i].size = 255;
2885 #endif
2886 dyncols[i].index = i;
2887 dyncols[i].scale = 0;
2888 dyncols[i].prec = 0;
2889 dyncols[i].nosign = 1;
2890 dyncols[i].autoinc = SQL_FALSE;
2891 dyncols[i].notnull = SQL_NULLABLE;
2892 dyncols[i].typename = NULL;
2893 }
2894 freedyncols(s);
2895 s->ncols = s->dcols = ncols;
2896 s->dyncols = s->cols = dyncols;
2897 fixupdyncols(s, d->sqlite, cols + ncols);
2898 mkbindcols(s, s->ncols);
2899 }
2900 if (!cols || ncols <= 0) {
2901 goto killvm;
2902 }
2903 if (!values) {
2904 if (rc == SQLITE_DONE) {
2905 freeresult(s, 0);
2906 s->nrows = 0;
2907 sqlite_finalize(s->vm, NULL);
2908 s->vm = NULL;
2909 d->vm_stmt = NULL;
2910 return SQL_SUCCESS;
2911 }
2912 goto killvm;
2913 }
2914 rowd = xmalloc((1 + 2 * ncols) * sizeof (char *));
2915 if (rowd) {
2916 rowd[0] = (char *) ((PTRDIFF_T) (ncols * 2));
2917 ++rowd;
2918 for (i = 0; i < ncols; i++) {
2919 rowd[i] = NULL;
2920 rowd[i + ncols] = xstrdup(values[i]);
2921 }
2922 for (i = 0; i < ncols; i++) {
2923 if (values[i] && !rowd[i + ncols]) {
2924 freerows(rowd);
2925 rowd = 0;
2926 break;
2927 }
2928 }
2929 }
2930 if (rowd) {
2931 freeresult(s, 0);
2932 s->nrows = 1;
2933 s->rows = rowd;
2934 s->rowfree = freerows;
2935 if (rc == SQLITE_DONE) {
2936 sqlite_finalize(s->vm, NULL);
2937 s->vm = NULL;
2938 d->vm_stmt = NULL;
2939 }
2940 return SQL_SUCCESS;
2941 }
2942 }
2943 killvm:
2944 sqlite_finalize(s->vm, &errp);
2945 s->vm = NULL;
2946 d->vm_stmt = NULL;
2947 setstat(s, rc, "%s (%d)", (*s->ov3) ? "HY000" : "S1000",
2948 errp ? errp : "unknown error", rc);
2949 if (errp) {
2950 sqlite_freemem(errp);
2951 errp = NULL;
2952 }
2953 return SQL_ERROR;
2954 }
2955
2956 /**
2957 * Stop running VM
2958 * @param s statement pointer
2959 */
2960
2961 static void
vm_end(STMT * s)2962 vm_end(STMT *s)
2963 {
2964 DBC *d;
2965
2966 if (!s || !s->vm) {
2967 return;
2968 }
2969 d = (DBC *) s->dbc;
2970 if (d) {
2971 d->busyint = 0;
2972 }
2973 sqlite_finalize(s->vm, NULL);
2974 s->vm = NULL;
2975 d->vm_stmt = NULL;
2976 }
2977
2978 /**
2979 * Conditionally stop running VM
2980 * @param s statement pointer
2981 */
2982
2983 static void
vm_end_if(STMT * s)2984 vm_end_if(STMT *s)
2985 {
2986 DBC *d = (DBC *) s->dbc;
2987
2988 if (d) {
2989 d->busyint = 0;
2990 }
2991 if (d && d->vm_stmt == s) {
2992 vm_end(s);
2993 }
2994 }
2995
2996 /**
2997 * Start VM for execution of SELECT statement.
2998 * @param s statement pointer
2999 * @param params string array of statement parameters
3000 * @result ODBC error code
3001 */
3002
3003 static SQLRETURN
vm_start(STMT * s,char ** params)3004 vm_start(STMT *s, char **params)
3005 {
3006 DBC *d = (DBC *) s->dbc;
3007 char *errp = NULL, *sql = NULL;
3008 const char *endp;
3009 sqlite_vm *vm;
3010 int rc;
3011
3012 #ifdef CANT_PASS_VALIST_AS_CHARPTR
3013 if (params) {
3014 sql = sqlite_mprintf((char *) s->query,
3015 params[0], params[1],
3016 params[2], params[3],
3017 params[4], params[5],
3018 params[6], params[7],
3019 params[8], params[9],
3020 params[10], params[11],
3021 params[12], params[13],
3022 params[14], params[15],
3023 params[16], params[17],
3024 params[18], params[19],
3025 params[20], params[21],
3026 params[22], params[23],
3027 params[24], params[25],
3028 params[26], params[27],
3029 params[28], params[29],
3030 params[30], params[31]);
3031 } else {
3032 sql = sqlite_mprintf((char *) s->query);
3033 }
3034 #else
3035 sql = sqlite_vmprintf((char *) s->query, (char *) params);
3036 #endif
3037 if (!sql) {
3038 return nomem(s);
3039 }
3040 rc = sqlite_compile(d->sqlite, sql, &endp, &vm, &errp);
3041 dbtracerc(d, rc, errp);
3042 sqlite_freemem(sql);
3043 if (rc != SQLITE_OK) {
3044 setstat(s, rc, "%s (%d)", (*s->ov3) ? "HY000" : "S1000",
3045 errp ? errp : "unknown error", rc);
3046 if (errp) {
3047 sqlite_freemem(errp);
3048 errp = NULL;
3049 }
3050 return SQL_ERROR;
3051 }
3052 s->vm = vm;
3053 d->vm_stmt = s;
3054 d->vm_rownum = -1;
3055 return SQL_SUCCESS;
3056 }
3057
3058 /**
3059 * Function not implemented.
3060 */
3061
3062 SQLRETURN SQL_API
SQLBulkOperations(SQLHSTMT stmt,SQLSMALLINT oper)3063 SQLBulkOperations(SQLHSTMT stmt, SQLSMALLINT oper)
3064 {
3065 SQLRETURN ret;
3066
3067 HSTMT_LOCK(stmt);
3068 ret = drvunimplstmt(stmt);
3069 HSTMT_UNLOCK(stmt);
3070 return ret;
3071 }
3072
3073 #ifndef WINTERFACE
3074 /**
3075 * Function not implemented.
3076 */
3077
3078 SQLRETURN SQL_API
SQLDataSources(SQLHENV env,SQLUSMALLINT dir,SQLCHAR * srvname,SQLSMALLINT buflen1,SQLSMALLINT * lenp1,SQLCHAR * desc,SQLSMALLINT buflen2,SQLSMALLINT * lenp2)3079 SQLDataSources(SQLHENV env, SQLUSMALLINT dir, SQLCHAR *srvname,
3080 SQLSMALLINT buflen1, SQLSMALLINT *lenp1,
3081 SQLCHAR *desc, SQLSMALLINT buflen2, SQLSMALLINT *lenp2)
3082 {
3083 if (env == SQL_NULL_HENV) {
3084 return SQL_INVALID_HANDLE;
3085 }
3086 return SQL_ERROR;
3087 }
3088 #endif
3089
3090 #ifdef WINTERFACE
3091 /**
3092 * Function not implemented.
3093 */
3094
3095 SQLRETURN SQL_API
SQLDataSourcesW(SQLHENV env,SQLUSMALLINT dir,SQLWCHAR * srvname,SQLSMALLINT buflen1,SQLSMALLINT * lenp1,SQLWCHAR * desc,SQLSMALLINT buflen2,SQLSMALLINT * lenp2)3096 SQLDataSourcesW(SQLHENV env, SQLUSMALLINT dir, SQLWCHAR *srvname,
3097 SQLSMALLINT buflen1, SQLSMALLINT *lenp1,
3098 SQLWCHAR *desc, SQLSMALLINT buflen2, SQLSMALLINT *lenp2)
3099 {
3100 if (env == SQL_NULL_HENV) {
3101 return SQL_INVALID_HANDLE;
3102 }
3103 return SQL_ERROR;
3104 }
3105 #endif
3106
3107 #ifndef WINTERFACE
3108 /**
3109 * Function not implemented.
3110 */
3111
3112 SQLRETURN SQL_API
SQLDrivers(SQLHENV env,SQLUSMALLINT dir,SQLCHAR * drvdesc,SQLSMALLINT descmax,SQLSMALLINT * desclenp,SQLCHAR * drvattr,SQLSMALLINT attrmax,SQLSMALLINT * attrlenp)3113 SQLDrivers(SQLHENV env, SQLUSMALLINT dir, SQLCHAR *drvdesc,
3114 SQLSMALLINT descmax, SQLSMALLINT *desclenp,
3115 SQLCHAR *drvattr, SQLSMALLINT attrmax, SQLSMALLINT *attrlenp)
3116 {
3117 if (env == SQL_NULL_HENV) {
3118 return SQL_INVALID_HANDLE;
3119 }
3120 return SQL_ERROR;
3121 }
3122 #endif
3123
3124 #ifdef WINTERFACE
3125 /**
3126 * Function not implemented.
3127 */
3128
3129 SQLRETURN SQL_API
SQLDriversW(SQLHENV env,SQLUSMALLINT dir,SQLWCHAR * drvdesc,SQLSMALLINT descmax,SQLSMALLINT * desclenp,SQLWCHAR * drvattr,SQLSMALLINT attrmax,SQLSMALLINT * attrlenp)3130 SQLDriversW(SQLHENV env, SQLUSMALLINT dir, SQLWCHAR *drvdesc,
3131 SQLSMALLINT descmax, SQLSMALLINT *desclenp,
3132 SQLWCHAR *drvattr, SQLSMALLINT attrmax, SQLSMALLINT *attrlenp)
3133 {
3134 if (env == SQL_NULL_HENV) {
3135 return SQL_INVALID_HANDLE;
3136 }
3137 return SQL_ERROR;
3138 }
3139 #endif
3140
3141 #ifndef WINTERFACE
3142 /**
3143 * Function not implemented.
3144 */
3145
3146 SQLRETURN SQL_API
SQLBrowseConnect(SQLHDBC dbc,SQLCHAR * connin,SQLSMALLINT conninLen,SQLCHAR * connout,SQLSMALLINT connoutMax,SQLSMALLINT * connoutLen)3147 SQLBrowseConnect(SQLHDBC dbc, SQLCHAR *connin, SQLSMALLINT conninLen,
3148 SQLCHAR *connout, SQLSMALLINT connoutMax,
3149 SQLSMALLINT *connoutLen)
3150 {
3151 SQLRETURN ret;
3152
3153 HDBC_LOCK(dbc);
3154 ret = drvunimpldbc(dbc);
3155 HDBC_UNLOCK(dbc);
3156 return ret;
3157 }
3158 #endif
3159
3160 #ifdef WINTERFACE
3161 /**
3162 * Function not implemented.
3163 */
3164
3165 SQLRETURN SQL_API
SQLBrowseConnectW(SQLHDBC dbc,SQLWCHAR * connin,SQLSMALLINT conninLen,SQLWCHAR * connout,SQLSMALLINT connoutMax,SQLSMALLINT * connoutLen)3166 SQLBrowseConnectW(SQLHDBC dbc, SQLWCHAR *connin, SQLSMALLINT conninLen,
3167 SQLWCHAR *connout, SQLSMALLINT connoutMax,
3168 SQLSMALLINT *connoutLen)
3169 {
3170 SQLRETURN ret;
3171
3172 HDBC_LOCK(dbc);
3173 ret = drvunimpldbc(dbc);
3174 HDBC_UNLOCK(dbc);
3175 return ret;
3176 }
3177 #endif
3178
3179 /**
3180 * SQLite function "current_time_local" etc.
3181 * @param context SQLite function context
3182 * @param argc number arguments
3183 * @param argv argument vector
3184 */
3185
3186 static void
time_func(sqlite_func * context,int argc,const char ** argv)3187 time_func(sqlite_func *context, int argc, const char **argv)
3188 {
3189 char buf[128];
3190 PTRDIFF_T what = (PTRDIFF_T) sqlite_user_data(context);
3191 #if defined(_WIN32) || defined(_WIN64)
3192 SYSTEMTIME st;
3193
3194 if (what & 1) {
3195 GetSystemTime(&st);
3196 } else {
3197 GetLocalTime(&st);
3198 }
3199 if (what & 4) {
3200 sprintf(buf, "%04d-%02d-%02d %02d:%02d:%02d",
3201 st.wYear, st.wMonth, st.wDay,
3202 st.wHour, st.wMinute, st.wSecond);
3203 } else if (what & 2) {
3204 sprintf(buf, "%04d-%02d-%02d", st.wYear, st.wMonth, st.wDay);
3205 } else {
3206 sprintf(buf, "%02d:%02d:%02d", st.wHour, st.wMinute, st.wSecond);
3207 }
3208 #else
3209 time_t t;
3210 struct tm tm;
3211
3212 time(&t);
3213 if (what & 1) {
3214 #ifdef HAVE_GMTIME_R
3215 gmtime_r(&t, &tm);
3216 #else
3217 tm = *gmtime(&t);
3218 #endif
3219 } else {
3220 #ifdef HAVE_LOCALTIME_R
3221 localtime_r(&t, &tm);
3222 #else
3223 tm = *localtime(&t);
3224 #endif
3225 }
3226 if (what & 4) {
3227 sprintf(buf, "%04d-%02d-%02d %02d:%02d:%02d",
3228 tm.tm_year + 1900, tm.tm_mon + 1, tm.tm_mday,
3229 tm.tm_hour, tm.tm_min, tm.tm_sec);
3230 } else if (what & 2) {
3231 sprintf(buf, "%04d-%02d-%02d",
3232 tm.tm_year + 1900, tm.tm_mon + 1, tm.tm_mday);
3233 } else {
3234 sprintf(buf, "%02d:%02d:%02d", tm.tm_hour, tm.tm_min, tm.tm_sec);
3235 }
3236 #endif
3237 sqlite_set_result_string(context, buf, -1);
3238 }
3239
3240 #if (HAVE_ENCDEC)
3241 static const char hexdigits[] = "0123456789ABCDEFabcdef";
3242
3243 /**
3244 * SQLite function "hextobin"
3245 * @param context SQLite function context
3246 * @param argc number arguments
3247 * @param argv argument vector
3248 */
3249
3250 static void
hextobin_func(sqlite_func * context,int argc,const char ** argv)3251 hextobin_func(sqlite_func *context, int argc, const char **argv)
3252 {
3253 int i, len;
3254 char *bin, *p;
3255
3256 if (argc < 1) {
3257 return;
3258 }
3259 if (!argv[0]) {
3260 sqlite_set_result_string(context, NULL, 4);
3261 return;
3262 }
3263 len = strlen(argv[0]) / 2;
3264 bin = xmalloc(len + 1);
3265 if (!bin) {
3266 oom:
3267 sqlite_set_result_error(context, "out of memory", -1);
3268 return;
3269 }
3270 if (len <= 0) {
3271 sqlite_set_result_string(context, bin, 0);
3272 freep(&bin);
3273 return;
3274 }
3275 for (i = 0, p = (char *) argv[0]; i < len; i++) {
3276 char *x;
3277 int v;
3278
3279 if (!*p || !(x = strchr(hexdigits, *p))) {
3280 goto converr;
3281 }
3282 v = x - hexdigits;
3283 bin[i] = (v >= 16) ? ((v - 6) << 4) : (v << 4);
3284 ++p;
3285 if (!*p || !(x = strchr(hexdigits, *p))) {
3286 converr:
3287 freep(&bin);
3288 sqlite_set_result_error(context, "conversion error", -1);
3289 return;
3290 }
3291 v = x - hexdigits;
3292 bin[i] |= (v >= 16) ? (v - 6) : v;
3293 ++p;
3294 }
3295 i = sqlite_encode_binary((unsigned char *) bin, len, 0);
3296 p = xmalloc(i + 1);
3297 if (!p) {
3298 freep(&bin);
3299 goto oom;
3300 }
3301 i = sqlite_encode_binary((unsigned char *) bin, len,
3302 (unsigned char *) p);
3303 sqlite_set_result_string(context, p, i);
3304 freep(&bin);
3305 freep(&p);
3306 }
3307
3308 /**
3309 * SQLite function "bintohex"
3310 * @param context SQLite function context
3311 * @param argc number arguments
3312 * @param argv argument vector
3313 */
3314
3315 static void
bintohex_func(sqlite_func * context,int argc,const char ** argv)3316 bintohex_func(sqlite_func *context, int argc, const char **argv)
3317 {
3318 int i, k, len;
3319 char *bin, *p;
3320
3321 if (argc < 1) {
3322 return;
3323 }
3324 if (!argv[0]) {
3325 empty:
3326 sqlite_set_result_string(context, "", 0);
3327 return;
3328 }
3329 bin = xmalloc(strlen(argv[0]) + 1);
3330 if (!bin) {
3331 oom:
3332 sqlite_set_result_error(context, "out of memory", -1);
3333 return;
3334 }
3335 len = sqlite_decode_binary((unsigned char *) argv[0],
3336 (unsigned char *) bin);
3337 if (len < 0) {
3338 freep(&bin);
3339 sqlite_set_result_error(context, "error decoding binary data", -1);
3340 return;
3341 }
3342 if (len == 0) {
3343 goto empty;
3344 }
3345 p = xmalloc(len * 2 + 1);
3346 if (!p) {
3347 goto oom;
3348 }
3349 for (i = 0, k = 0; i < len; i++) {
3350 p[k++] = hexdigits[(bin[i] >> 4) & 0x0f];
3351 p[k++] = hexdigits[bin[i] & 0x0f];
3352 }
3353 p[k] = '\0';
3354 sqlite_set_result_string(context, p, k);
3355 freep(&bin);
3356 freep(&p);
3357 }
3358
3359 /**
3360 * Encode hex (char) parameter to SQLite binary string.
3361 * @param s STMT pointer
3362 * @param p BINDPARM pointer
3363 * @result ODBD error code
3364 */
3365
3366 static SQLRETURN
hextobin(STMT * s,BINDPARM * p)3367 hextobin(STMT *s, BINDPARM *p)
3368 {
3369 int i, len = strlen(p->param) / 2;
3370 char *bin = xmalloc(len + 1), *pp;
3371
3372 if (!bin) {
3373 return nomem(s);
3374 }
3375 if (len <= 0) {
3376 bin[0] = '\0';
3377 freep(&p->parbuf);
3378 p->parbuf = p->param = bin;
3379 p->len = 0;
3380 return SQL_SUCCESS;
3381 }
3382 for (i = 0, pp = (char *) p->param; i < len; i++) {
3383 char *x;
3384 int v;
3385
3386 if (!*pp || !(x = strchr(hexdigits, *pp))) {
3387 goto converr;
3388 }
3389 v = x - hexdigits;
3390 bin[i] = (v >= 16) ? ((v - 6) << 4) : (v << 4);
3391 ++pp;
3392 if (!*pp || !(x = strchr(hexdigits, *pp))) {
3393 converr:
3394 freep(&bin);
3395 setstat(s, -1, "conversion error", (*s->ov3) ? "HY000" : "S1000");
3396 return SQL_ERROR;
3397 }
3398 v = x - hexdigits;
3399 bin[i] |= (v >= 16) ? (v - 6) : v;
3400 ++pp;
3401 }
3402 i = sqlite_encode_binary((unsigned char *) bin, len, 0);
3403 pp = xmalloc(i + 1);
3404 if (!pp) {
3405 freep(&bin);
3406 return nomem(s);
3407 }
3408 p->len = sqlite_encode_binary((unsigned char *) bin, len,
3409 (unsigned char *) pp);
3410 freep(&p->parbuf);
3411 p->parbuf = p->param = pp;
3412 freep(&bin);
3413 return SQL_SUCCESS;
3414 }
3415 #endif
3416
3417 /**
3418 * Internal put (partial) parameter data into executing statement.
3419 * @param stmt statement handle
3420 * @param data pointer to data
3421 * @param len length of data
3422 * @result ODBC error code
3423 */
3424
3425 static SQLRETURN
drvputdata(SQLHSTMT stmt,SQLPOINTER data,SQLLEN len)3426 drvputdata(SQLHSTMT stmt, SQLPOINTER data, SQLLEN len)
3427 {
3428 STMT *s;
3429 int i, dlen, done = 0;
3430 BINDPARM *p;
3431
3432 if (stmt == SQL_NULL_HSTMT) {
3433 return SQL_INVALID_HANDLE;
3434 }
3435 s = (STMT *) stmt;
3436 if (!s->query || s->nparams <= 0) {
3437 seqerr:
3438 setstat(s, -1, "sequence error", "HY010");
3439 return SQL_ERROR;
3440 }
3441 for (i = (s->pdcount < 0) ? 0 : s->pdcount; i < s->nparams; i++) {
3442 p = &s->bindparms[i];
3443 if (p->need > 0) {
3444 int type = mapdeftype(p->type, p->stype, -1, s->nowchar[0]);
3445
3446 if (len == SQL_NULL_DATA) {
3447 freep(&p->parbuf);
3448 p->param = NULL;
3449 p->len = SQL_NULL_DATA;
3450 p->need = -1;
3451 } else if (type != SQL_C_CHAR
3452 #ifdef WCHARSUPPORT
3453 && type != SQL_C_WCHAR
3454 #endif
3455 #if (HAVE_ENCDEC)
3456 && type != SQL_C_BINARY
3457 #endif
3458 ) {
3459 int size = 0;
3460
3461 switch (type) {
3462 case SQL_C_TINYINT:
3463 case SQL_C_UTINYINT:
3464 case SQL_C_STINYINT:
3465 #ifdef SQL_BIT
3466 case SQL_C_BIT:
3467 #endif
3468 size = sizeof (SQLCHAR);
3469 break;
3470 case SQL_C_SHORT:
3471 case SQL_C_USHORT:
3472 case SQL_C_SSHORT:
3473 size = sizeof (SQLSMALLINT);
3474 break;
3475 case SQL_C_LONG:
3476 case SQL_C_ULONG:
3477 case SQL_C_SLONG:
3478 size = sizeof (SQLINTEGER);
3479 break;
3480 case SQL_C_FLOAT:
3481 size = sizeof (float);
3482 break;
3483 case SQL_C_DOUBLE:
3484 size = sizeof (double);
3485 break;
3486 #ifdef SQL_C_TYPE_DATE
3487 case SQL_C_TYPE_DATE:
3488 #endif
3489 case SQL_C_DATE:
3490 size = sizeof (DATE_STRUCT);
3491 break;
3492 #ifdef SQL_C_TYPE_DATE
3493 case SQL_C_TYPE_TIME:
3494 #endif
3495 case SQL_C_TIME:
3496 size = sizeof (TIME_STRUCT);
3497 break;
3498 #ifdef SQL_C_TYPE_DATE
3499 case SQL_C_TYPE_TIMESTAMP:
3500 #endif
3501 case SQL_C_TIMESTAMP:
3502 size = sizeof (TIMESTAMP_STRUCT);
3503 break;
3504 }
3505 freep(&p->parbuf);
3506 p->parbuf = xmalloc(size);
3507 if (!p->parbuf) {
3508 return nomem(s);
3509 }
3510 p->param = p->parbuf;
3511 memcpy(p->param, data, size);
3512 p->len = size;
3513 p->need = -1;
3514 } else if (len == SQL_NTS && (
3515 type == SQL_C_CHAR
3516 #ifdef WCHARSUPPORT
3517 || type == SQL_C_WCHAR
3518 #endif
3519 )) {
3520 char *dp = data;
3521
3522 #ifdef WCHARSUPPORT
3523 if (type == SQL_C_WCHAR) {
3524 dp = uc_to_utf(data, len);
3525 if (!dp) {
3526 return nomem(s);
3527 }
3528 }
3529 #endif
3530 dlen = strlen(dp);
3531 freep(&p->parbuf);
3532 p->parbuf = xmalloc(dlen + 1);
3533 if (!p->parbuf) {
3534 #ifdef WCHARSUPPORT
3535 if (dp != data) {
3536 uc_free(dp);
3537 }
3538 #endif
3539 return nomem(s);
3540 }
3541 p->param = p->parbuf;
3542 strcpy(p->param, dp);
3543 #ifdef WCHARSUPPORT
3544 if (dp != data) {
3545 uc_free(dp);
3546 }
3547 #endif
3548 p->len = dlen;
3549 p->need = -1;
3550 } else if (len < 0) {
3551 setstat(s, -1, "invalid length", "HY090");
3552 return SQL_ERROR;
3553 } else {
3554 dlen = min(p->len - p->offs, len);
3555 if (!p->param) {
3556 setstat(s, -1, "no memory for parameter", "HY013");
3557 return SQL_ERROR;
3558 }
3559 memcpy((char *) p->param + p->offs, data, dlen);
3560 p->offs += dlen;
3561 if (p->offs >= p->len) {
3562 #ifdef WCHARSUPPORT
3563 if (type == SQL_C_WCHAR) {
3564 char *dp = uc_to_utf(p->param, p->len);
3565 char *np;
3566 int nlen;
3567
3568 if (!dp) {
3569 return nomem(s);
3570 }
3571 nlen = strlen(dp);
3572 np = xmalloc(nlen + 1);
3573 if (!np) {
3574 uc_free(dp);
3575 return nomem(s);
3576 }
3577 strcpy(np, dp);
3578 uc_free(dp);
3579 if (p->param == p->parbuf) {
3580 freep(&p->parbuf);
3581 }
3582 p->parbuf = p->param = np;
3583 p->len = nlen;
3584 } else {
3585 *((char *) p->param + p->len) = '\0';
3586 }
3587 #else
3588 #if defined(_WIN32) || defined(_WIN64)
3589 if (p->type == SQL_C_WCHAR &&
3590 (p->stype == SQL_VARCHAR ||
3591 p->stype == SQL_LONGVARCHAR) &&
3592 p->len == p->coldef * sizeof (SQLWCHAR)) {
3593 /* fix for MS-Access */
3594 p->len = p->coldef;
3595 }
3596 #endif
3597 *((char *) p->param + p->len) = '\0';
3598 #endif
3599 #if (HAVE_ENCDEC)
3600 if ((p->stype == SQL_BINARY ||
3601 p->stype == SQL_VARBINARY ||
3602 p->stype == SQL_LONGVARBINARY) &&
3603 #ifdef WCHARSUPPORT
3604 (type == SQL_C_CHAR || type == SQL_C_WCHAR)
3605 #else
3606 type == SQL_C_CHAR
3607 #endif
3608 ) {
3609 if (hextobin(s, p) != SQL_SUCCESS) {
3610 return SQL_ERROR;
3611 }
3612 } else if (type == SQL_C_BINARY) {
3613 int bsize;
3614 unsigned char *bin;
3615
3616 bsize = sqlite_encode_binary(p->param, p->len, 0);
3617 bin = xmalloc(bsize + 1);
3618 if (!bin) {
3619 return nomem(s);
3620 }
3621 p->len = sqlite_encode_binary(p->param, p->len, bin);
3622 if (p->param == p->parbuf) {
3623 freep(&p->parbuf);
3624 }
3625 p->parbuf = p->param = bin;
3626 }
3627 #endif
3628 p->need = -1;
3629 }
3630 }
3631 done = 1;
3632 break;
3633 }
3634 }
3635 if (!done) {
3636 goto seqerr;
3637 }
3638 return SQL_SUCCESS;
3639 }
3640
3641 /**
3642 * Put (partial) parameter data into executing statement.
3643 * @param stmt statement handle
3644 * @param data pointer to data
3645 * @param len length of data
3646 * @result ODBC error code
3647 */
3648
3649 SQLRETURN SQL_API
SQLPutData(SQLHSTMT stmt,SQLPOINTER data,SQLLEN len)3650 SQLPutData(SQLHSTMT stmt, SQLPOINTER data, SQLLEN len)
3651 {
3652 SQLRETURN ret;
3653
3654 HSTMT_LOCK(stmt);
3655 ret = drvputdata(stmt, data, len);
3656 HSTMT_UNLOCK(stmt);
3657 return ret;
3658 }
3659
3660 /**
3661 * Clear out parameter bindings, if any.
3662 * @param s statement pointer
3663 */
3664
3665 static SQLRETURN
freeparams(STMT * s)3666 freeparams(STMT *s)
3667 {
3668 if (s->bindparms) {
3669 int n;
3670
3671 for (n = 0; n < s->nbindparms; n++) {
3672 freep(&s->bindparms[n].parbuf);
3673 memset(&s->bindparms[n], 0, sizeof (BINDPARM));
3674 }
3675 }
3676 return SQL_SUCCESS;
3677 }
3678
3679 /**
3680 * Substitute parameter for statement.
3681 * @param s statement pointer
3682 * @param pnum parameter number
3683 * @param outp output pointer or NULL
3684 * @result ODBC error code
3685 *
3686 * If no output buffer is given, the function computes and
3687 * reports the space needed for the parameter. Otherwise
3688 * the parameter is converted to its string representation
3689 * in order to be presented to sqlite_exec_vprintf() et.al.
3690 */
3691
3692 static SQLRETURN
substparam(STMT * s,int pnum,char ** outp)3693 substparam(STMT *s, int pnum, char **outp)
3694 {
3695 char *outdata = NULL;
3696 int type, len, isnull = 0, needalloc = 0;
3697 BINDPARM *p;
3698 double dval;
3699 #if (HAVE_ENCDEC)
3700 int chkbin = 1;
3701 #endif
3702
3703 if (!s->bindparms || pnum < 0 || pnum >= s->nbindparms) {
3704 goto error;
3705 }
3706 p = &s->bindparms[pnum];
3707 type = mapdeftype(p->type, p->stype, -1, s->nowchar[0]);
3708
3709 #if (defined(_WIN32) || defined(_WIN64)) && defined(WINTERFACE)
3710 /* MS Access hack part 4 (map SQL_C_DEFAULT to SQL_C_CHAR) */
3711 if (type == SQL_C_WCHAR && p->type == SQL_C_DEFAULT) {
3712 type = SQL_C_CHAR;
3713 }
3714 #endif
3715
3716 if (p->need > 0) {
3717 return setupparbuf(s, p);
3718 }
3719 p->strbuf[0] = '\0';
3720 if (!p->param || (p->lenp && *p->lenp == SQL_NULL_DATA)) {
3721 isnull = 1;
3722 goto bind;
3723 }
3724 #if (HAVE_ENCDEC)
3725 if (type == SQL_C_CHAR &&
3726 (p->stype == SQL_BINARY ||
3727 p->stype == SQL_VARBINARY ||
3728 p->stype == SQL_LONGVARBINARY)) {
3729 type = SQL_C_BINARY;
3730 }
3731 #endif
3732 switch (type) {
3733 case SQL_C_CHAR:
3734 #ifdef WCHARSUPPORT
3735 case SQL_C_WCHAR:
3736 #endif
3737 #if (HAVE_ENCDEC)
3738 case SQL_C_BINARY:
3739 #endif
3740 break;
3741 #ifdef SQL_BIT
3742 case SQL_C_BIT:
3743 strcpy(p->strbuf, (*((unsigned char *) p->param)) ? "1" : "0");
3744 goto bind;
3745 #endif
3746 case SQL_C_UTINYINT:
3747 sprintf(p->strbuf, "%d", *((unsigned char *) p->param));
3748 goto bind;
3749 case SQL_C_TINYINT:
3750 case SQL_C_STINYINT:
3751 sprintf(p->strbuf, "%d", *((char *) p->param));
3752 goto bind;
3753 case SQL_C_USHORT:
3754 sprintf(p->strbuf, "%d", *((unsigned short *) p->param));
3755 goto bind;
3756 case SQL_C_SHORT:
3757 case SQL_C_SSHORT:
3758 sprintf(p->strbuf, "%d", *((short *) p->param));
3759 goto bind;
3760 case SQL_C_ULONG:
3761 case SQL_C_LONG:
3762 case SQL_C_SLONG:
3763 sprintf(p->strbuf, "%ld", *((long *) p->param));
3764 goto bind;
3765 case SQL_C_FLOAT:
3766 dval = *((float *) p->param);
3767 goto dodouble;
3768 case SQL_C_DOUBLE:
3769 dval = *((double *) p->param);
3770 dodouble:
3771 #if defined(HAVE_SQLITEMPRINTF) && (HAVE_SQLITEMPRINTF)
3772 {
3773 char *buf2 = sqlite_mprintf("%.16g", dval);
3774
3775 if (buf2) {
3776 strcpy(p->strbuf, buf2);
3777 sqlite_freemem(buf2);
3778 } else {
3779 isnull = 1;
3780 }
3781 }
3782 #else
3783 ln_sprintfg(p->strbuf, dval);
3784 #endif
3785 goto bind;
3786 #ifdef SQL_C_TYPE_DATE
3787 case SQL_C_TYPE_DATE:
3788 #endif
3789 case SQL_C_DATE:
3790 sprintf(p->strbuf, "%04d-%02d-%02d",
3791 ((DATE_STRUCT *) p->param)->year,
3792 ((DATE_STRUCT *) p->param)->month,
3793 ((DATE_STRUCT *) p->param)->day);
3794 goto bind;
3795 #ifdef SQL_C_TYPE_TIME
3796 case SQL_C_TYPE_TIME:
3797 #endif
3798 case SQL_C_TIME:
3799 sprintf(p->strbuf, "%02d:%02d:%02d",
3800 ((TIME_STRUCT *) p->param)->hour,
3801 ((TIME_STRUCT *) p->param)->minute,
3802 ((TIME_STRUCT *) p->param)->second);
3803 goto bind;
3804 #ifdef SQL_C_TYPE_TIMESTAMP
3805 case SQL_C_TYPE_TIMESTAMP:
3806 #endif
3807 case SQL_C_TIMESTAMP:
3808 len = (int) ((TIMESTAMP_STRUCT *) p->param)->fraction;
3809 len /= 1000000;
3810 len = len % 1000;
3811 if (len < 0) {
3812 len = 0;
3813 }
3814 if (p->coldef && p->coldef <= 16) {
3815 sprintf(p->strbuf, "%04d-%02d-%02d %02d:%02d:00.000",
3816 ((TIMESTAMP_STRUCT *) p->param)->year,
3817 ((TIMESTAMP_STRUCT *) p->param)->month,
3818 ((TIMESTAMP_STRUCT *) p->param)->day,
3819 ((TIMESTAMP_STRUCT *) p->param)->hour,
3820 ((TIMESTAMP_STRUCT *) p->param)->minute);
3821 } else if (p->coldef && p->coldef <= 19) {
3822 sprintf(p->strbuf, "%04d-%02d-%02d %02d:%02d:%02d.000",
3823 ((TIMESTAMP_STRUCT *) p->param)->year,
3824 ((TIMESTAMP_STRUCT *) p->param)->month,
3825 ((TIMESTAMP_STRUCT *) p->param)->day,
3826 ((TIMESTAMP_STRUCT *) p->param)->hour,
3827 ((TIMESTAMP_STRUCT *) p->param)->minute,
3828 ((TIMESTAMP_STRUCT *) p->param)->second);
3829 } else {
3830 sprintf(p->strbuf, "%04d-%02d-%02d %02d:%02d:%02d.%03d",
3831 ((TIMESTAMP_STRUCT *) p->param)->year,
3832 ((TIMESTAMP_STRUCT *) p->param)->month,
3833 ((TIMESTAMP_STRUCT *) p->param)->day,
3834 ((TIMESTAMP_STRUCT *) p->param)->hour,
3835 ((TIMESTAMP_STRUCT *) p->param)->minute,
3836 ((TIMESTAMP_STRUCT *) p->param)->second,
3837 len);
3838 }
3839 bind:
3840 if (outp) {
3841 *outp = isnull ? NULL : p->strbuf;
3842 }
3843 return SQL_SUCCESS;
3844 default:
3845 error:
3846 setstat(s, -1, "unsupported parameter type",
3847 (*s->ov3) ? "07009" : "S1093");
3848 return SQL_ERROR;
3849 }
3850 if (!p->parbuf) {
3851 #ifdef WCHARSUPPORT
3852 if (type == SQL_C_WCHAR) {
3853 if (!p->lenp || *p->lenp == SQL_NTS) {
3854 p->max = uc_strlen(p->param) * sizeof (SQLWCHAR);
3855 } else if (*p->lenp >= 0) {
3856 p->max = *p->lenp;
3857 }
3858 } else
3859 #endif
3860 if (type == SQL_C_CHAR) {
3861 if (!p->lenp || *p->lenp == SQL_NTS) {
3862 p->len = p->max = strlen(p->param);
3863 } else if (*p->lenp >= 0) {
3864 p->len = p->max = *p->lenp;
3865 needalloc = 1;
3866 }
3867 }
3868 #if (HAVE_ENCDEC)
3869 else if (type == SQL_C_BINARY) {
3870 p->len = p->max = p->lenp ? *p->lenp : 0;
3871 }
3872 #endif
3873 }
3874 if (p->need < 0 && p->parbuf == p->param) {
3875 outdata = p->param;
3876 goto putp;
3877 }
3878 #ifdef WCHARSUPPORT
3879 if (type == SQL_C_WCHAR) {
3880 char *dp = uc_to_utf(p->param, p->max);
3881
3882 if (!dp) {
3883 return nomem(s);
3884 }
3885 if (p->param == p->parbuf) {
3886 freep(&p->parbuf);
3887 }
3888 p->parbuf = p->param = dp;
3889 p->need = -1;
3890 p->len = strlen(p->param);
3891 outdata = p->param;
3892 } else
3893 #endif
3894 #if (HAVE_ENCDEC)
3895 if (type == SQL_C_BINARY) {
3896 int bsize;
3897 char *dp;
3898
3899 p->len = *p->lenp;
3900 if (p->len < 0) {
3901 setstat(s, -1, "invalid length reference", "HY009");
3902 return SQL_ERROR;
3903 }
3904 bsize = sqlite_encode_binary(p->param, p->len, 0);
3905 dp = xmalloc(bsize + 1);
3906 if (!dp) {
3907 return nomem(s);
3908 }
3909 p->len = sqlite_encode_binary(p->param, p->len, (unsigned char *) dp);
3910 if (p->param == p->parbuf) {
3911 freep(&p->parbuf);
3912 }
3913 p->parbuf = p->param = dp;
3914 p->need = -1;
3915 chkbin = 0;
3916 outdata = p->param;
3917 } else
3918 #endif
3919 if (type == SQL_C_CHAR) {
3920 outdata = p->param;
3921 if (needalloc) {
3922 char *dp;
3923
3924 freep(&p->parbuf);
3925 dp = xmalloc(p->len + 1);
3926 if (!dp) {
3927 return nomem(s);
3928 }
3929 memcpy(dp, p->param, p->len);
3930 dp[p->len] = '\0';
3931 p->parbuf = p->param = dp;
3932 p->need = -1;
3933 outdata = p->param;
3934 }
3935 } else {
3936 outdata = p->param;
3937 #if (HAVE_ENCDEC)
3938 chkbin = 0;
3939 #endif
3940 }
3941 #if (HAVE_ENCDEC)
3942 if (chkbin) {
3943 if (p->stype == SQL_BINARY ||
3944 p->stype == SQL_VARBINARY ||
3945 p->stype == SQL_LONGVARBINARY) {
3946 if (hextobin(s, p) != SQL_SUCCESS) {
3947 return SQL_ERROR;
3948 }
3949 outdata = p->param;
3950 }
3951 }
3952 #endif
3953 putp:
3954 if (outp) {
3955 *outp = outdata;
3956 }
3957 return SQL_SUCCESS;
3958 }
3959
3960 /**
3961 * Internal bind parameter on HSTMT.
3962 * @param stmt statement handle
3963 * @param pnum parameter number, starting at 1
3964 * @param iotype input/output type of parameter
3965 * @param buftype type of host variable
3966 * @param ptype
3967 * @param coldef
3968 * @param scale
3969 * @param data pointer to host variable
3970 * @param buflen length of host variable
3971 * @param len output length pointer
3972 * @result ODBC error code
3973 */
3974
3975 static SQLRETURN
drvbindparam(SQLHSTMT stmt,SQLUSMALLINT pnum,SQLSMALLINT iotype,SQLSMALLINT buftype,SQLSMALLINT ptype,SQLUINTEGER coldef,SQLSMALLINT scale,SQLPOINTER data,SQLINTEGER buflen,SQLLEN * len)3976 drvbindparam(SQLHSTMT stmt, SQLUSMALLINT pnum, SQLSMALLINT iotype,
3977 SQLSMALLINT buftype, SQLSMALLINT ptype, SQLUINTEGER coldef,
3978 SQLSMALLINT scale,
3979 SQLPOINTER data, SQLINTEGER buflen, SQLLEN *len)
3980 {
3981 STMT *s;
3982 BINDPARM *p;
3983
3984 if (stmt == SQL_NULL_HSTMT) {
3985 return SQL_INVALID_HANDLE;
3986 }
3987 s = (STMT *) stmt;
3988 if (pnum == 0) {
3989 setstat(s, -1, "invalid parameter", (*s->ov3) ? "07009" : "S1093");
3990 return SQL_ERROR;
3991 }
3992 if (!data && !len) {
3993 setstat(s, -1, "invalid buffer", "HY003");
3994 return SQL_ERROR;
3995 }
3996 --pnum;
3997 if (s->bindparms) {
3998 if (pnum >= s->nbindparms) {
3999 BINDPARM *newparms;
4000
4001 newparms = xrealloc(s->bindparms,
4002 (pnum + 1) * sizeof (BINDPARM));
4003 if (!newparms) {
4004 outofmem:
4005 return nomem(s);
4006 }
4007 s->bindparms = newparms;
4008 memset(&s->bindparms[s->nbindparms], 0,
4009 (pnum + 1 - s->nbindparms) * sizeof (BINDPARM));
4010 s->nbindparms = pnum + 1;
4011 }
4012 } else {
4013 int npar = max(10, pnum + 1);
4014
4015 s->bindparms = xmalloc(npar * sizeof (BINDPARM));
4016 if (!s->bindparms) {
4017 goto outofmem;
4018 }
4019 memset(s->bindparms, 0, npar * sizeof (BINDPARM));
4020 s->nbindparms = npar;
4021 }
4022 switch (buftype) {
4023 case SQL_C_STINYINT:
4024 case SQL_C_UTINYINT:
4025 case SQL_C_TINYINT:
4026 #ifdef SQL_C_BIT
4027 case SQL_C_BIT:
4028 #endif
4029 buflen = sizeof (char);
4030 break;
4031 case SQL_C_SHORT:
4032 case SQL_C_USHORT:
4033 case SQL_C_SSHORT:
4034 buflen = sizeof (short);
4035 break;
4036 case SQL_C_SLONG:
4037 case SQL_C_ULONG:
4038 case SQL_C_LONG:
4039 buflen = sizeof (long);
4040 break;
4041 case SQL_C_FLOAT:
4042 buflen = sizeof (float);
4043 break;
4044 case SQL_C_DOUBLE:
4045 buflen = sizeof (double);
4046 break;
4047 case SQL_C_TIMESTAMP:
4048 #ifdef SQL_C_TYPE_TIMESTAMP
4049 case SQL_C_TYPE_TIMESTAMP:
4050 #endif
4051 buflen = sizeof (TIMESTAMP_STRUCT);
4052 break;
4053 case SQL_C_TIME:
4054 #ifdef SQL_C_TYPE_TIME
4055 case SQL_C_TYPE_TIME:
4056 #endif
4057 buflen = sizeof (TIME_STRUCT);
4058 break;
4059 case SQL_C_DATE:
4060 #ifdef SQL_C_TYPE_DATE
4061 case SQL_C_TYPE_DATE:
4062 #endif
4063 buflen = sizeof (DATE_STRUCT);
4064 break;
4065 #ifdef SQL_C_UBIGINT
4066 case SQL_C_UBIGINT:
4067 buflen = sizeof (SQLBIGINT);
4068 break;
4069 #endif
4070 #ifdef SQL_C_SBIGINT
4071 case SQL_C_SBIGINT:
4072 buflen = sizeof (SQLBIGINT);
4073 break;
4074 #endif
4075 #ifdef SQL_C_BIGINT
4076 case SQL_C_BIGINT:
4077 buflen = sizeof (SQLBIGINT);
4078 break;
4079 #endif
4080 }
4081 p = &s->bindparms[pnum];
4082 p->type = buftype;
4083 p->stype = ptype;
4084 p->coldef = coldef;
4085 p->scale = scale;
4086 p->max = buflen;
4087 p->inc = buflen;
4088 p->lenp0 = p->lenp = len;
4089 p->offs = 0;
4090 p->len = 0;
4091 p->param0 = data;
4092 freep(&p->parbuf);
4093 p->param = p->param0;
4094 p->bound = 1;
4095 p->need = 0;
4096 return SQL_SUCCESS;
4097 }
4098
4099 /**
4100 * Bind parameter on HSTMT.
4101 * @param stmt statement handle
4102 * @param pnum parameter number, starting at 1
4103 * @param iotype input/output type of parameter
4104 * @param buftype type of host variable
4105 * @param ptype
4106 * @param coldef
4107 * @param scale
4108 * @param data pointer to host variable
4109 * @param buflen length of host variable
4110 * @param len output length pointer
4111 * @result ODBC error code
4112 */
4113
4114 SQLRETURN SQL_API
SQLBindParameter(SQLHSTMT stmt,SQLUSMALLINT pnum,SQLSMALLINT iotype,SQLSMALLINT buftype,SQLSMALLINT ptype,SQLULEN coldef,SQLSMALLINT scale,SQLPOINTER data,SQLLEN buflen,SQLLEN * len)4115 SQLBindParameter(SQLHSTMT stmt, SQLUSMALLINT pnum, SQLSMALLINT iotype,
4116 SQLSMALLINT buftype, SQLSMALLINT ptype, SQLULEN coldef,
4117 SQLSMALLINT scale,
4118 SQLPOINTER data, SQLLEN buflen, SQLLEN *len)
4119 {
4120 SQLRETURN ret;
4121
4122 HSTMT_LOCK(stmt);
4123 ret = drvbindparam(stmt, pnum, iotype, buftype, ptype, coldef,
4124 scale, data, buflen, len);
4125 HSTMT_UNLOCK(stmt);
4126 return ret;
4127 }
4128
4129 #ifndef HAVE_IODBC
4130 /**
4131 * Bind parameter on HSTMT.
4132 * @param stmt statement handle
4133 * @param pnum parameter number, starting at 1
4134 * @param vtype input/output type of parameter
4135 * @param ptype
4136 * @param lenprec
4137 * @param scale
4138 * @param val pointer to host variable
4139 * @param lenp output length pointer
4140 * @result ODBC error code
4141 */
4142
4143 SQLRETURN SQL_API
SQLBindParam(SQLHSTMT stmt,SQLUSMALLINT pnum,SQLSMALLINT vtype,SQLSMALLINT ptype,SQLULEN lenprec,SQLSMALLINT scale,SQLPOINTER val,SQLLEN * lenp)4144 SQLBindParam(SQLHSTMT stmt, SQLUSMALLINT pnum, SQLSMALLINT vtype,
4145 SQLSMALLINT ptype, SQLULEN lenprec,
4146 SQLSMALLINT scale, SQLPOINTER val,
4147 SQLLEN *lenp)
4148 {
4149 SQLRETURN ret;
4150
4151 HSTMT_LOCK(stmt);
4152 ret = drvbindparam(stmt, pnum, SQL_PARAM_INPUT, vtype, ptype,
4153 lenprec, scale, val, 0, lenp);
4154 HSTMT_UNLOCK(stmt);
4155 return ret;
4156 }
4157 #endif
4158
4159 /**
4160 * Return number of parameters.
4161 * @param stmt statement handle
4162 * @param nparam output parameter count
4163 * @result ODBC error code
4164 */
4165
4166 SQLRETURN SQL_API
SQLNumParams(SQLHSTMT stmt,SQLSMALLINT * nparam)4167 SQLNumParams(SQLHSTMT stmt, SQLSMALLINT *nparam)
4168 {
4169 STMT *s;
4170 SQLSMALLINT dummy;
4171
4172 HSTMT_LOCK(stmt);
4173 if (stmt == SQL_NULL_HSTMT) {
4174 return SQL_INVALID_HANDLE;
4175 }
4176 s = (STMT *) stmt;
4177 if (!nparam) {
4178 nparam = &dummy;
4179 }
4180 *nparam = s->nparams;
4181 HSTMT_UNLOCK(stmt);
4182 return SQL_SUCCESS;
4183 }
4184
4185 /**
4186 * Setup parameter buffer for deferred parameter.
4187 * @param s pointer to STMT
4188 * @param p pointer to BINDPARM
4189 * @result ODBC error code (success indicated by SQL_NEED_DATA)
4190 */
4191
4192 static SQLRETURN
setupparbuf(STMT * s,BINDPARM * p)4193 setupparbuf(STMT *s, BINDPARM *p)
4194 {
4195 if (!p->parbuf) {
4196 if (*p->lenp == SQL_DATA_AT_EXEC) {
4197 p->len = p->max;
4198 } else {
4199 p->len = SQL_LEN_DATA_AT_EXEC(*p->lenp);
4200 }
4201 if (p->len < 0 && p->len != SQL_NTS &&
4202 p->len != SQL_NULL_DATA) {
4203 setstat(s, -1, "invalid length", "HY009");
4204 return SQL_ERROR;
4205 }
4206 if (p->len >= 0) {
4207 p->parbuf = xmalloc(p->len + 1);
4208 if (!p->parbuf) {
4209 return nomem(s);
4210 }
4211 p->param = p->parbuf;
4212 } else {
4213 p->param = NULL;
4214 }
4215 }
4216 return SQL_NEED_DATA;
4217 }
4218
4219 /**
4220 * Retrieve next parameter for sending data to executing query.
4221 * @param stmt statement handle
4222 * @param pind pointer to output parameter indicator
4223 * @result ODBC error code
4224 */
4225
4226 SQLRETURN SQL_API
SQLParamData(SQLHSTMT stmt,SQLPOINTER * pind)4227 SQLParamData(SQLHSTMT stmt, SQLPOINTER *pind)
4228 {
4229 STMT *s;
4230 int i;
4231 SQLPOINTER dummy;
4232 SQLRETURN ret;
4233 BINDPARM *p;
4234
4235 HSTMT_LOCK(stmt);
4236 if (stmt == SQL_NULL_HSTMT) {
4237 return SQL_INVALID_HANDLE;
4238 }
4239 s = (STMT *) stmt;
4240 if (!pind) {
4241 pind = &dummy;
4242 }
4243 if (s->pdcount < s->nparams) {
4244 s->pdcount++;
4245 }
4246 for (i = 0; i < s->pdcount; i++) {
4247 p = &s->bindparms[i];
4248 if (p->need > 0) {
4249 p->need = -1;
4250 }
4251 }
4252 for (; i < s->nparams; i++) {
4253 p = &s->bindparms[i];
4254 if (p->need > 0) {
4255 *pind = (SQLPOINTER) p->param0;
4256 ret = setupparbuf(s, p);
4257 s->pdcount = i;
4258 goto done;
4259 }
4260 }
4261 ret = drvexecute(stmt, 0);
4262 done:
4263 HSTMT_UNLOCK(stmt);
4264 return ret;
4265 }
4266
4267 /**
4268 * Return information about parameter.
4269 * @param stmt statement handle
4270 * @param pnum parameter number, starting at 1
4271 * @param dtype output type indicator
4272 * @param size output size indicator
4273 * @param decdigits output number of digits
4274 * @param nullable output NULL allowed indicator
4275 * @result ODBC error code
4276 */
4277
4278 SQLRETURN SQL_API
SQLDescribeParam(SQLHSTMT stmt,SQLUSMALLINT pnum,SQLSMALLINT * dtype,SQLULEN * size,SQLSMALLINT * decdigits,SQLSMALLINT * nullable)4279 SQLDescribeParam(SQLHSTMT stmt, SQLUSMALLINT pnum, SQLSMALLINT *dtype,
4280 SQLULEN *size, SQLSMALLINT *decdigits, SQLSMALLINT *nullable)
4281 {
4282 STMT *s;
4283 SQLRETURN ret = SQL_ERROR;
4284
4285 HSTMT_LOCK(stmt);
4286 if (stmt == SQL_NULL_HSTMT) {
4287 return SQL_INVALID_HANDLE;
4288 }
4289 s = (STMT *) stmt;
4290 --pnum;
4291 if (pnum >= s->nparams) {
4292 setstat(s, -1, "invalid parameter index",
4293 (*s->ov3) ? "HY000" : "S1000");
4294 goto done;
4295 }
4296 if (dtype) {
4297 #ifdef SQL_LONGVARCHAR
4298 #ifdef WINTERFACE
4299 *dtype = s->nowchar[0] ? SQL_LONGVARCHAR : SQL_WLONGVARCHAR;
4300 #else
4301 *dtype = SQL_LONGVARCHAR;
4302 #endif
4303 #else
4304 #ifdef WINTERFACE
4305 *dtype = s->nowchar[0] ? SQL_VARCHAR : SQL_WVARCHAR;
4306 #else
4307 *dtype = SQL_VARCHAR;
4308 #endif
4309 #endif
4310 }
4311 if (size) {
4312 #ifdef SQL_LONGVARCHAR
4313 *size = 65536;
4314 #else
4315 *size = 255;
4316 #endif
4317 }
4318 if (decdigits) {
4319 *decdigits = 0;
4320 }
4321 if (nullable) {
4322 *nullable = SQL_NULLABLE;
4323 }
4324 ret = SQL_SUCCESS;
4325 done:
4326 HSTMT_UNLOCK(stmt);
4327 return ret;
4328 }
4329
4330 /**
4331 * Set information on parameter.
4332 * @param stmt statement handle
4333 * @param par parameter number, starting at 1
4334 * @param type type of host variable
4335 * @param sqltype
4336 * @param coldef
4337 * @param scale
4338 * @param val pointer to host variable
4339 * @param len output length pointer
4340 * @result ODBC error code
4341 */
4342
4343 SQLRETURN SQL_API
SQLSetParam(SQLHSTMT stmt,SQLUSMALLINT par,SQLSMALLINT type,SQLSMALLINT sqltype,SQLULEN coldef,SQLSMALLINT scale,SQLPOINTER val,SQLLEN * nval)4344 SQLSetParam(SQLHSTMT stmt, SQLUSMALLINT par, SQLSMALLINT type,
4345 SQLSMALLINT sqltype, SQLULEN coldef,
4346 SQLSMALLINT scale, SQLPOINTER val, SQLLEN *nval)
4347 {
4348 SQLRETURN ret;
4349
4350 HSTMT_LOCK(stmt);
4351 ret = drvbindparam(stmt, par, SQL_PARAM_INPUT,
4352 type, sqltype, coldef, scale, val,
4353 SQL_SETPARAM_VALUE_MAX, nval);
4354 HSTMT_UNLOCK(stmt);
4355 return ret;
4356 }
4357
4358 /**
4359 * Function not implemented.
4360 */
4361
4362 SQLRETURN SQL_API
SQLParamOptions(SQLHSTMT stmt,SQLULEN rows,SQLULEN * rowp)4363 SQLParamOptions(SQLHSTMT stmt, SQLULEN rows, SQLULEN *rowp)
4364 {
4365 SQLRETURN ret;
4366
4367 HSTMT_LOCK(stmt);
4368 ret = drvunimplstmt(stmt);
4369 HSTMT_UNLOCK(stmt);
4370 return ret;
4371 }
4372
4373 #ifndef WINTERFACE
4374 /**
4375 * Function not implemented.
4376 */
4377
4378 SQLRETURN SQL_API
SQLGetDescField(SQLHDESC handle,SQLSMALLINT recno,SQLSMALLINT fieldid,SQLPOINTER value,SQLINTEGER buflen,SQLINTEGER * strlen)4379 SQLGetDescField(SQLHDESC handle, SQLSMALLINT recno,
4380 SQLSMALLINT fieldid, SQLPOINTER value,
4381 SQLINTEGER buflen, SQLINTEGER *strlen)
4382 {
4383 return SQL_ERROR;
4384 }
4385 #endif
4386
4387 #ifdef WINTERFACE
4388 /**
4389 * Function not implemented.
4390 */
4391
4392 SQLRETURN SQL_API
SQLGetDescFieldW(SQLHDESC handle,SQLSMALLINT recno,SQLSMALLINT fieldid,SQLPOINTER value,SQLINTEGER buflen,SQLINTEGER * strlen)4393 SQLGetDescFieldW(SQLHDESC handle, SQLSMALLINT recno,
4394 SQLSMALLINT fieldid, SQLPOINTER value,
4395 SQLINTEGER buflen, SQLINTEGER *strlen)
4396 {
4397 return SQL_ERROR;
4398 }
4399 #endif
4400
4401 #ifndef WINTERFACE
4402 /**
4403 * Function not implemented.
4404 */
4405
4406 SQLRETURN SQL_API
SQLSetDescField(SQLHDESC handle,SQLSMALLINT recno,SQLSMALLINT fieldid,SQLPOINTER value,SQLINTEGER buflen)4407 SQLSetDescField(SQLHDESC handle, SQLSMALLINT recno,
4408 SQLSMALLINT fieldid, SQLPOINTER value,
4409 SQLINTEGER buflen)
4410 {
4411 return SQL_ERROR;
4412 }
4413 #endif
4414
4415 #ifdef WINTERFACE
4416 /**
4417 * Function not implemented.
4418 */
4419
4420 SQLRETURN SQL_API
SQLSetDescFieldW(SQLHDESC handle,SQLSMALLINT recno,SQLSMALLINT fieldid,SQLPOINTER value,SQLINTEGER buflen)4421 SQLSetDescFieldW(SQLHDESC handle, SQLSMALLINT recno,
4422 SQLSMALLINT fieldid, SQLPOINTER value,
4423 SQLINTEGER buflen)
4424 {
4425 return SQL_ERROR;
4426 }
4427 #endif
4428
4429 #ifndef WINTERFACE
4430 /**
4431 * Function not implemented.
4432 */
4433
4434 SQLRETURN SQL_API
SQLGetDescRec(SQLHDESC handle,SQLSMALLINT recno,SQLCHAR * name,SQLSMALLINT buflen,SQLSMALLINT * strlen,SQLSMALLINT * type,SQLSMALLINT * subtype,SQLLEN * len,SQLSMALLINT * prec,SQLSMALLINT * scale,SQLSMALLINT * nullable)4435 SQLGetDescRec(SQLHDESC handle, SQLSMALLINT recno,
4436 SQLCHAR *name, SQLSMALLINT buflen,
4437 SQLSMALLINT *strlen, SQLSMALLINT *type,
4438 SQLSMALLINT *subtype, SQLLEN *len,
4439 SQLSMALLINT *prec, SQLSMALLINT *scale,
4440 SQLSMALLINT *nullable)
4441 {
4442 return SQL_ERROR;
4443 }
4444 #endif
4445
4446 #ifdef WINTERFACE
4447 /**
4448 * Function not implemented.
4449 */
4450
4451 SQLRETURN SQL_API
SQLGetDescRecW(SQLHDESC handle,SQLSMALLINT recno,SQLWCHAR * name,SQLSMALLINT buflen,SQLSMALLINT * strlen,SQLSMALLINT * type,SQLSMALLINT * subtype,SQLLEN * len,SQLSMALLINT * prec,SQLSMALLINT * scale,SQLSMALLINT * nullable)4452 SQLGetDescRecW(SQLHDESC handle, SQLSMALLINT recno,
4453 SQLWCHAR *name, SQLSMALLINT buflen,
4454 SQLSMALLINT *strlen, SQLSMALLINT *type,
4455 SQLSMALLINT *subtype, SQLLEN *len,
4456 SQLSMALLINT *prec, SQLSMALLINT *scale,
4457 SQLSMALLINT *nullable)
4458 {
4459 return SQL_ERROR;
4460 }
4461 #endif
4462
4463 /**
4464 * Function not implemented.
4465 */
4466
4467 SQLRETURN SQL_API
SQLSetDescRec(SQLHDESC handle,SQLSMALLINT recno,SQLSMALLINT type,SQLSMALLINT subtype,SQLLEN len,SQLSMALLINT prec,SQLSMALLINT scale,SQLPOINTER data,SQLLEN * strlen,SQLLEN * indicator)4468 SQLSetDescRec(SQLHDESC handle, SQLSMALLINT recno,
4469 SQLSMALLINT type, SQLSMALLINT subtype,
4470 SQLLEN len, SQLSMALLINT prec,
4471 SQLSMALLINT scale, SQLPOINTER data,
4472 SQLLEN *strlen, SQLLEN *indicator)
4473 {
4474 return SQL_ERROR;
4475 }
4476
4477 /**
4478 * Setup empty result set from constant column specification.
4479 * @param stmt statement handle
4480 * @param colspec column specification array (default, ODBC2)
4481 * @param ncols number of columns (default, ODBC2)
4482 * @param colspec3 column specification array (ODBC3)
4483 * @param ncols3 number of columns (ODBC3)
4484 * @param nret returns number of columns
4485 * @result ODBC error code
4486 */
4487
4488 static SQLRETURN
mkresultset(HSTMT stmt,COL * colspec,int ncols,COL * colspec3,int ncols3,int * nret)4489 mkresultset(HSTMT stmt, COL *colspec, int ncols, COL *colspec3,
4490 int ncols3, int *nret)
4491 {
4492 STMT *s;
4493 DBC *d;
4494
4495 if (stmt == SQL_NULL_HSTMT) {
4496 return SQL_INVALID_HANDLE;
4497 }
4498 s = (STMT *) stmt;
4499 if (s->dbc == SQL_NULL_HDBC) {
4500 noconn:
4501 return noconn(s);
4502 }
4503 d = (DBC *) s->dbc;
4504 if (!d->sqlite) {
4505 goto noconn;
4506 }
4507 vm_end_if(s);
4508 freeresult(s, 0);
4509 if (colspec3 && *s->ov3) {
4510 s->ncols = ncols3;
4511 s->cols = colspec3;
4512 } else {
4513 s->ncols = ncols;
4514 s->cols = colspec;
4515 }
4516 mkbindcols(s, s->ncols);
4517 s->nowchar[1] = 1;
4518 s->nrows = 0;
4519 s->rowp = -1;
4520 s->isselect = -1;
4521 if (nret) {
4522 *nret = s->ncols;
4523 }
4524 return SQL_SUCCESS;
4525 }
4526
4527 /**
4528 * Columns for result set of SQLTablePrivileges().
4529 */
4530
4531 static COL tablePrivSpec2[] = {
4532 { "SYSTEM", "TABLEPRIV", "TABLE_QUALIFIER", SCOL_VARCHAR, 50 },
4533 { "SYSTEM", "TABLEPRIV", "TABLE_OWNER", SCOL_VARCHAR, 50 },
4534 { "SYSTEM", "TABLEPRIV", "TABLE_NAME", SCOL_VARCHAR, 255 },
4535 { "SYSTEM", "TABLEPRIV", "GRANTOR", SCOL_VARCHAR, 50 },
4536 { "SYSTEM", "TABLEPRIV", "GRANTEE", SCOL_VARCHAR, 50 },
4537 { "SYSTEM", "TABLEPRIV", "PRIVILEGE", SCOL_VARCHAR, 50 },
4538 { "SYSTEM", "TABLEPRIV", "IS_GRANTABLE", SCOL_VARCHAR, 50 }
4539 };
4540
4541 static COL tablePrivSpec3[] = {
4542 { "SYSTEM", "TABLEPRIV", "TABLE_CAT", SCOL_VARCHAR, 50 },
4543 { "SYSTEM", "TABLEPRIV", "TABLE_SCHEM", SCOL_VARCHAR, 50 },
4544 { "SYSTEM", "TABLEPRIV", "TABLE_NAME", SCOL_VARCHAR, 255 },
4545 { "SYSTEM", "TABLEPRIV", "GRANTOR", SCOL_VARCHAR, 50 },
4546 { "SYSTEM", "TABLEPRIV", "GRANTEE", SCOL_VARCHAR, 50 },
4547 { "SYSTEM", "TABLEPRIV", "PRIVILEGE", SCOL_VARCHAR, 50 },
4548 { "SYSTEM", "TABLEPRIV", "IS_GRANTABLE", SCOL_VARCHAR, 50 }
4549 };
4550
4551 /**
4552 * Retrieve privileges on tables and/or views.
4553 * @param stmt statement handle
4554 * @param cat catalog name/pattern or NULL
4555 * @param catLen length of catalog name/pattern or SQL_NTS
4556 * @param schema schema name/pattern or NULL
4557 * @param schemaLen length of schema name/pattern or SQL_NTS
4558 * @param table table name/pattern or NULL
4559 * @param tableLen length of table name/pattern or SQL_NTS
4560 * @result ODBC error code
4561 */
4562
4563 static SQLRETURN
drvtableprivileges(SQLHSTMT stmt,SQLCHAR * cat,SQLSMALLINT catLen,SQLCHAR * schema,SQLSMALLINT schemaLen,SQLCHAR * table,SQLSMALLINT tableLen)4564 drvtableprivileges(SQLHSTMT stmt,
4565 SQLCHAR *cat, SQLSMALLINT catLen,
4566 SQLCHAR *schema, SQLSMALLINT schemaLen,
4567 SQLCHAR *table, SQLSMALLINT tableLen)
4568 {
4569 SQLRETURN ret;
4570 STMT *s;
4571 DBC *d;
4572 int ncols, rc, size, npatt;
4573 char *errp = NULL, tname[512];
4574
4575 ret = mkresultset(stmt, tablePrivSpec2, array_size(tablePrivSpec2),
4576 tablePrivSpec3, array_size(tablePrivSpec3), NULL);
4577 if (ret != SQL_SUCCESS) {
4578 return ret;
4579 }
4580 s = (STMT *) stmt;
4581 d = (DBC *) s->dbc;
4582 if (cat && (catLen > 0 || catLen == SQL_NTS) && cat[0] == '%') {
4583 table = NULL;
4584 goto doit;
4585 }
4586 if (schema && (schemaLen > 0 || schemaLen == SQL_NTS) &&
4587 schema[0] == '%') {
4588 if ((!cat || catLen == 0 || !cat[0]) &&
4589 (!table || tableLen == 0 || !table[0])) {
4590 table = NULL;
4591 goto doit;
4592 }
4593 }
4594 doit:
4595 if (!table) {
4596 size = 1;
4597 tname[0] = '%';
4598 } else {
4599 if (tableLen == SQL_NTS) {
4600 size = sizeof (tname) - 1;
4601 } else {
4602 size = min(sizeof (tname) - 1, tableLen);
4603 }
4604 strncpy(tname, (char *) table, size);
4605 }
4606 tname[size] = '\0';
4607 npatt = unescpat(tname);
4608 ret = starttran(s);
4609 if (ret != SQL_SUCCESS) {
4610 return ret;
4611 }
4612 #if defined(_WIN32) || defined(_WIN64)
4613 if (npatt) {
4614 rc = sqlite_get_table_printf(d->sqlite,
4615 "select %s as 'TABLE_QUALIFIER', "
4616 "%s as 'TABLE_OWNER', "
4617 "tbl_name as 'TABLE_NAME', "
4618 "'' as 'GRANTOR', "
4619 "'' as 'GRANTEE', "
4620 "'SELECT' AS 'PRIVILEGE', "
4621 "NULL as 'IS_GRANTABLE' "
4622 "from sqlite_master where "
4623 "(type = 'table' or type = 'view') "
4624 "and tbl_name like '%q' "
4625 "UNION "
4626 "select %s as 'TABLE_QUALIFIER', "
4627 "%s as 'TABLE_OWNER', "
4628 "tbl_name as 'TABLE_NAME', "
4629 "'' as 'GRANTOR', "
4630 "'' as 'GRANTEE', "
4631 "'UPDATE' AS 'PRIVILEGE', "
4632 "NULL as 'IS_GRANTABLE' "
4633 "from sqlite_master where "
4634 "(type = 'table' or type = 'view') "
4635 "and tbl_name like '%q' "
4636 "UNION "
4637 "select %s as 'TABLE_QUALIFIER', "
4638 "%s as 'TABLE_OWNER', "
4639 "tbl_name as 'TABLE_NAME', "
4640 "'' as 'GRANTOR', "
4641 "'' as 'GRANTEE', "
4642 "'DELETE' AS 'PRIVILEGE', "
4643 "NULL as 'IS_GRANTABLE' "
4644 "from sqlite_master where "
4645 "(type = 'table' or type = 'view') "
4646 "and tbl_name like '%q' "
4647 "UNION "
4648 "select %s as 'TABLE_QUALIFIER', "
4649 "%s as 'TABLE_OWNER', "
4650 "tbl_name as 'TABLE_NAME', "
4651 "'' as 'GRANTOR', "
4652 "'' as 'GRANTEE', "
4653 "'INSERT' AS 'PRIVILEGE', "
4654 "NULL as 'IS_GRANTABLE' "
4655 "from sqlite_master where "
4656 "(type = 'table' or type = 'view') "
4657 "and tbl_name like '%q' "
4658 "UNION "
4659 "select %s as 'TABLE_QUALIFIER', "
4660 "%s as 'TABLE_OWNER', "
4661 "tbl_name as 'TABLE_NAME', "
4662 "'' as 'GRANTOR', "
4663 "'' as 'GRANTEE', "
4664 "'REFERENCES' AS 'PRIVILEGE', "
4665 "NULL as 'IS_GRANTABLE' "
4666 "from sqlite_master where "
4667 "(type = 'table' or type = 'view') "
4668 "and tbl_name like '%q'",
4669 &s->rows, &s->nrows, &ncols, &errp,
4670 d->xcelqrx ? "'main'" : "NULL",
4671 d->xcelqrx ? "''" : "NULL", tname,
4672 d->xcelqrx ? "'main'" : "NULL",
4673 d->xcelqrx ? "''" : "NULL", tname,
4674 d->xcelqrx ? "'main'" : "NULL",
4675 d->xcelqrx ? "''" : "NULL", tname,
4676 d->xcelqrx ? "'main'" : "NULL",
4677 d->xcelqrx ? "''" : "NULL", tname,
4678 d->xcelqrx ? "'main'" : "NULL",
4679 d->xcelqrx ? "''" : "NULL", tname);
4680 } else {
4681 rc = sqlite_get_table_printf(d->sqlite,
4682 "select %s as 'TABLE_QUALIFIER', "
4683 "%s as 'TABLE_OWNER', "
4684 "tbl_name as 'TABLE_NAME', "
4685 "'' as 'GRANTOR', "
4686 "'' as 'GRANTEE', "
4687 "'SELECT' AS 'PRIVILEGE', "
4688 "NULL as 'IS_GRANTABLE' "
4689 "from sqlite_master where "
4690 "(type = 'table' or type = 'view') "
4691 "and lower(tbl_name) = lower('%q') "
4692 "UNION "
4693 "select %s as 'TABLE_QUALIFIER', "
4694 "%s as 'TABLE_OWNER', "
4695 "tbl_name as 'TABLE_NAME', "
4696 "'' as 'GRANTOR', "
4697 "'' as 'GRANTEE', "
4698 "'UPDATE' AS 'PRIVILEGE', "
4699 "NULL as 'IS_GRANTABLE' "
4700 "from sqlite_master where "
4701 "(type = 'table' or type = 'view') "
4702 "and lower(tbl_name) = lower('%q') "
4703 "UNION "
4704 "select %s as 'TABLE_QUALIFIER', "
4705 "%s as 'TABLE_OWNER', "
4706 "tbl_name as 'TABLE_NAME', "
4707 "'' as 'GRANTOR', "
4708 "'' as 'GRANTEE', "
4709 "'DELETE' AS 'PRIVILEGE', "
4710 "NULL as 'IS_GRANTABLE' "
4711 "from sqlite_master where "
4712 "(type = 'table' or type = 'view') "
4713 "and lower(tbl_name) = lower('%q') "
4714 "UNION "
4715 "select %s as 'TABLE_QUALIFIER', "
4716 "%s as 'TABLE_OWNER', "
4717 "tbl_name as 'TABLE_NAME', "
4718 "'' as 'GRANTOR', "
4719 "'' as 'GRANTEE', "
4720 "'INSERT' AS 'PRIVILEGE', "
4721 "NULL as 'IS_GRANTABLE' "
4722 "from sqlite_master where "
4723 "(type = 'table' or type = 'view') "
4724 "and lower(tbl_name) = lower('%q') "
4725 "UNION "
4726 "select %s as 'TABLE_QUALIFIER', "
4727 "%s as 'TABLE_OWNER', "
4728 "tbl_name as 'TABLE_NAME', "
4729 "'' as 'GRANTOR', "
4730 "'' as 'GRANTEE', "
4731 "'REFERENCES' AS 'PRIVILEGE', "
4732 "NULL as 'IS_GRANTABLE' "
4733 "from sqlite_master where "
4734 "(type = 'table' or type = 'view') "
4735 "and lower(tbl_name) = lower('%q')",
4736 &s->rows, &s->nrows, &ncols, &errp,
4737 d->xcelqrx ? "'main'" : "NULL",
4738 d->xcelqrx ? "''" : "NULL", tname,
4739 d->xcelqrx ? "'main'" : "NULL",
4740 d->xcelqrx ? "''" : "NULL", tname,
4741 d->xcelqrx ? "'main'" : "NULL",
4742 d->xcelqrx ? "''" : "NULL", tname,
4743 d->xcelqrx ? "'main'" : "NULL",
4744 d->xcelqrx ? "''" : "NULL", tname,
4745 d->xcelqrx ? "'main'" : "NULL",
4746 d->xcelqrx ? "''" : "NULL", tname);
4747 }
4748 #else
4749 if (npatt) {
4750 rc = sqlite_get_table_printf(d->sqlite,
4751 "select NULL as 'TABLE_QUALIFIER', "
4752 "NULL as 'TABLE_OWNER', "
4753 "tbl_name as 'TABLE_NAME', "
4754 "'' as 'GRANTOR', "
4755 "'' as 'GRANTEE', "
4756 "'SELECT' AS 'PRIVILEGE', "
4757 "NULL as 'IS_GRANTABLE' "
4758 "from sqlite_master where "
4759 "(type = 'table' or type = 'view') "
4760 "and tbl_name like '%q' "
4761 "UNION "
4762 "select NULL as 'TABLE_QUALIFIER', "
4763 "NULL as 'TABLE_OWNER', "
4764 "tbl_name as 'TABLE_NAME', "
4765 "'' as 'GRANTOR', "
4766 "'' as 'GRANTEE', "
4767 "'UPDATE' AS 'PRIVILEGE', "
4768 "NULL as 'IS_GRANTABLE' "
4769 "from sqlite_master where "
4770 "(type = 'table' or type = 'view') "
4771 "and tbl_name like '%q' "
4772 "UNION "
4773 "select NULL as 'TABLE_QUALIFIER', "
4774 "NULL as 'TABLE_OWNER', "
4775 "tbl_name as 'TABLE_NAME', "
4776 "'' as 'GRANTOR', "
4777 "'' as 'GRANTEE', "
4778 "'DELETE' AS 'PRIVILEGE', "
4779 "NULL as 'IS_GRANTABLE' "
4780 "from sqlite_master where "
4781 "(type = 'table' or type = 'view') "
4782 "and tbl_name like '%q' "
4783 "UNION "
4784 "select NULL as 'TABLE_QUALIFIER', "
4785 "NULL as 'TABLE_OWNER', "
4786 "tbl_name as 'TABLE_NAME', "
4787 "'' as 'GRANTOR', "
4788 "'' as 'GRANTEE', "
4789 "'INSERT' AS 'PRIVILEGE', "
4790 "NULL as 'IS_GRANTABLE' "
4791 "from sqlite_master where "
4792 "(type = 'table' or type = 'view') "
4793 "and tbl_name like '%q' "
4794 "UNION "
4795 "select NULL as 'TABLE_QUALIFIER', "
4796 "NULL as 'TABLE_OWNER', "
4797 "tbl_name as 'TABLE_NAME', "
4798 "'' as 'GRANTOR', "
4799 "'' as 'GRANTEE', "
4800 "'REFERENCES' AS 'PRIVILEGE', "
4801 "NULL as 'IS_GRANTABLE' "
4802 "from sqlite_master where "
4803 "(type = 'table' or type = 'view') "
4804 "and tbl_name like '%q'",
4805 &s->rows, &s->nrows, &ncols, &errp,
4806 tname, tname, tname, tname, tname);
4807 } else {
4808 rc = sqlite_get_table_printf(d->sqlite,
4809 "select NULL as 'TABLE_QUALIFIER', "
4810 "NULL as 'TABLE_OWNER', "
4811 "tbl_name as 'TABLE_NAME', "
4812 "'' as 'GRANTOR', "
4813 "'' as 'GRANTEE', "
4814 "'SELECT' AS 'PRIVILEGE', "
4815 "NULL as 'IS_GRANTABLE' "
4816 "from sqlite_master where "
4817 "(type = 'table' or type = 'view') "
4818 "and lower(tbl_name) = lower('%q') "
4819 "UNION "
4820 "select NULL as 'TABLE_QUALIFIER', "
4821 "NULL as 'TABLE_OWNER', "
4822 "tbl_name as 'TABLE_NAME', "
4823 "'' as 'GRANTOR', "
4824 "'' as 'GRANTEE', "
4825 "'UPDATE' AS 'PRIVILEGE', "
4826 "NULL as 'IS_GRANTABLE' "
4827 "from sqlite_master where "
4828 "(type = 'table' or type = 'view') "
4829 "and lower(tbl_name) = lower('%q') "
4830 "UNION "
4831 "select NULL as 'TABLE_QUALIFIER', "
4832 "NULL as 'TABLE_OWNER', "
4833 "tbl_name as 'TABLE_NAME', "
4834 "'' as 'GRANTOR', "
4835 "'' as 'GRANTEE', "
4836 "'DELETE' AS 'PRIVILEGE', "
4837 "NULL as 'IS_GRANTABLE' "
4838 "from sqlite_master where "
4839 "(type = 'table' or type = 'view') "
4840 "and lower(tbl_name) = lower('%q') "
4841 "UNION "
4842 "select NULL as 'TABLE_QUALIFIER', "
4843 "NULL as 'TABLE_OWNER', "
4844 "tbl_name as 'TABLE_NAME', "
4845 "'' as 'GRANTOR', "
4846 "'' as 'GRANTEE', "
4847 "'INSERT' AS 'PRIVILEGE', "
4848 "NULL as 'IS_GRANTABLE' "
4849 "from sqlite_master where "
4850 "(type = 'table' or type = 'view') "
4851 "and lower(tbl_name) = lower('%q') "
4852 "UNION "
4853 "select NULL as 'TABLE_QUALIFIER', "
4854 "NULL as 'TABLE_OWNER', "
4855 "tbl_name as 'TABLE_NAME', "
4856 "'' as 'GRANTOR', "
4857 "'' as 'GRANTEE', "
4858 "'REFERENCES' AS 'PRIVILEGE', "
4859 "NULL as 'IS_GRANTABLE' "
4860 "from sqlite_master where "
4861 "(type = 'table' or type = 'view') "
4862 "and lower(tbl_name) = lower('%q')",
4863 &s->rows, &s->nrows, &ncols, &errp,
4864 tname, tname, tname, tname, tname);
4865 }
4866 #endif
4867 if (rc == SQLITE_OK) {
4868 if (ncols != s->ncols) {
4869 freeresult(s, 0);
4870 s->nrows = 0;
4871 } else {
4872 s->rowfree = sqlite_free_table;
4873 }
4874 } else {
4875 s->nrows = 0;
4876 s->rows = NULL;
4877 s->rowfree = NULL;
4878 }
4879 if (errp) {
4880 sqlite_freemem(errp);
4881 errp = NULL;
4882 }
4883 s->rowp = -1;
4884 return SQL_SUCCESS;
4885 }
4886
4887
4888 #if !defined(WINTERFACE) || (defined(HAVE_UNIXODBC) && (HAVE_UNIXODBC))
4889 /**
4890 * Retrieve privileges on tables and/or views.
4891 * @param stmt statement handle
4892 * @param catalog catalog name/pattern or NULL
4893 * @param catalogLen length of catalog name/pattern or SQL_NTS
4894 * @param schema schema name/pattern or NULL
4895 * @param schemaLen length of schema name/pattern or SQL_NTS
4896 * @param table table name/pattern or NULL
4897 * @param tableLen length of table name/pattern or SQL_NTS
4898 * @result ODBC error code
4899 */
4900
4901 SQLRETURN SQL_API
SQLTablePrivileges(SQLHSTMT stmt,SQLCHAR * catalog,SQLSMALLINT catalogLen,SQLCHAR * schema,SQLSMALLINT schemaLen,SQLCHAR * table,SQLSMALLINT tableLen)4902 SQLTablePrivileges(SQLHSTMT stmt,
4903 SQLCHAR *catalog, SQLSMALLINT catalogLen,
4904 SQLCHAR *schema, SQLSMALLINT schemaLen,
4905 SQLCHAR *table, SQLSMALLINT tableLen)
4906 {
4907 SQLRETURN ret;
4908
4909 HSTMT_LOCK(stmt);
4910 ret = drvtableprivileges(stmt, catalog, catalogLen, schema, schemaLen,
4911 table, tableLen);
4912 HSTMT_UNLOCK(stmt);
4913 return ret;
4914 }
4915 #endif
4916
4917 #if !defined(HAVE_UNIXODBC) || !(HAVE_UNIXODBC)
4918 #ifdef WINTERFACE
4919 /**
4920 * Retrieve privileges on tables and/or views (UNICODE version).
4921 * @param stmt statement handle
4922 * @param catalog catalog name/pattern or NULL
4923 * @param catalogLen length of catalog name/pattern or SQL_NTS
4924 * @param schema schema name/pattern or NULL
4925 * @param schemaLen length of schema name/pattern or SQL_NTS
4926 * @param table table name/pattern or NULL
4927 * @param tableLen length of table name/pattern or SQL_NTS
4928 * @result ODBC error code
4929 */
4930
4931 SQLRETURN SQL_API
SQLTablePrivilegesW(SQLHSTMT stmt,SQLWCHAR * catalog,SQLSMALLINT catalogLen,SQLWCHAR * schema,SQLSMALLINT schemaLen,SQLWCHAR * table,SQLSMALLINT tableLen)4932 SQLTablePrivilegesW(SQLHSTMT stmt,
4933 SQLWCHAR *catalog, SQLSMALLINT catalogLen,
4934 SQLWCHAR *schema, SQLSMALLINT schemaLen,
4935 SQLWCHAR *table, SQLSMALLINT tableLen)
4936 {
4937 char *c = NULL, *s = NULL, *t = NULL;
4938 SQLRETURN ret;
4939
4940 HSTMT_LOCK(stmt);
4941 if (catalog) {
4942 c = uc_to_utf_c(catalog, catalogLen);
4943 if (!c) {
4944 ret = nomem((STMT *) stmt);
4945 goto done;
4946 }
4947 }
4948 if (schema) {
4949 s = uc_to_utf_c(schema, schemaLen);
4950 if (!s) {
4951 ret = nomem((STMT *) stmt);
4952 goto done;
4953 }
4954 }
4955 if (table) {
4956 t = uc_to_utf_c(table, tableLen);
4957 if (!t) {
4958 ret = nomem((STMT *) stmt);
4959 goto done;
4960 }
4961 }
4962 ret = drvtableprivileges(stmt, (SQLCHAR *) c, SQL_NTS,
4963 (SQLCHAR *) s, SQL_NTS,
4964 (SQLCHAR *) t, SQL_NTS);
4965 done:
4966 HSTMT_UNLOCK(stmt);
4967 uc_free(t);
4968 uc_free(s);
4969 uc_free(c);
4970 return ret;
4971 }
4972 #endif
4973 #endif
4974
4975 /**
4976 * Columns for result set of SQLColumnPrivileges().
4977 */
4978
4979 static COL colPrivSpec2[] = {
4980 { "SYSTEM", "COLPRIV", "TABLE_QUALIFIER", SCOL_VARCHAR, 50 },
4981 { "SYSTEM", "COLPRIV", "TABLE_OWNER", SCOL_VARCHAR, 50 },
4982 { "SYSTEM", "COLPRIV", "TABLE_NAME", SCOL_VARCHAR, 255 },
4983 { "SYSTEM", "COLPRIV", "COLUMN_NAME", SCOL_VARCHAR, 255 },
4984 { "SYSTEM", "COLPRIV", "GRANTOR", SCOL_VARCHAR, 50 },
4985 { "SYSTEM", "COLPRIV", "GRANTEE", SCOL_VARCHAR, 50 },
4986 { "SYSTEM", "COLPRIV", "PRIVILEGE", SCOL_VARCHAR, 50 }
4987 };
4988
4989 static COL colPrivSpec3[] = {
4990 { "SYSTEM", "COLPRIV", "TABLE_CAT", SCOL_VARCHAR, 50 },
4991 { "SYSTEM", "COLPRIV", "TABLE_SCHEM", SCOL_VARCHAR, 50 },
4992 { "SYSTEM", "COLPRIV", "TABLE_NAME", SCOL_VARCHAR, 255 },
4993 { "SYSTEM", "COLPRIV", "COLUMN_NAME", SCOL_VARCHAR, 255 },
4994 { "SYSTEM", "COLPRIV", "GRANTOR", SCOL_VARCHAR, 50 },
4995 { "SYSTEM", "COLPRIV", "GRANTEE", SCOL_VARCHAR, 50 },
4996 { "SYSTEM", "COLPRIV", "PRIVILEGE", SCOL_VARCHAR, 50 }
4997 };
4998
4999 #if !defined(WINTERFACE) || (defined(HAVE_UNIXODBC) && (HAVE_UNIXODBC))
5000 /**
5001 * Retrieve privileges on columns.
5002 * @param stmt statement handle
5003 * @param catalog catalog name/pattern or NULL
5004 * @param catalogLen length of catalog name/pattern or SQL_NTS
5005 * @param schema schema name/pattern or NULL
5006 * @param schemaLen length of schema name/pattern or SQL_NTS
5007 * @param table table name/pattern or NULL
5008 * @param tableLen length of table name/pattern or SQL_NTS
5009 * @param column column name or NULL
5010 * @param columnLen length of column name or SQL_NTS
5011 * @result ODBC error code
5012 */
5013
5014 SQLRETURN SQL_API
SQLColumnPrivileges(SQLHSTMT stmt,SQLCHAR * catalog,SQLSMALLINT catalogLen,SQLCHAR * schema,SQLSMALLINT schemaLen,SQLCHAR * table,SQLSMALLINT tableLen,SQLCHAR * column,SQLSMALLINT columnLen)5015 SQLColumnPrivileges(SQLHSTMT stmt,
5016 SQLCHAR *catalog, SQLSMALLINT catalogLen,
5017 SQLCHAR *schema, SQLSMALLINT schemaLen,
5018 SQLCHAR *table, SQLSMALLINT tableLen,
5019 SQLCHAR *column, SQLSMALLINT columnLen)
5020 {
5021 SQLRETURN ret;
5022
5023 HSTMT_LOCK(stmt);
5024 ret = mkresultset(stmt, colPrivSpec2, array_size(colPrivSpec2),
5025 colPrivSpec3, array_size(colPrivSpec3), NULL);
5026 HSTMT_UNLOCK(stmt);
5027 return ret;
5028 }
5029 #endif
5030
5031 #if !defined(HAVE_UNIXODBC) || !(HAVE_UNIXODBC)
5032 #ifdef WINTERFACE
5033 /**
5034 * Retrieve privileges on columns (UNICODE version).
5035 * @param stmt statement handle
5036 * @param catalog catalog name/pattern or NULL
5037 * @param catalogLen length of catalog name/pattern or SQL_NTS
5038 * @param schema schema name/pattern or NULL
5039 * @param schemaLen length of schema name/pattern or SQL_NTS
5040 * @param table table name/pattern or NULL
5041 * @param tableLen length of table name/pattern or SQL_NTS
5042 * @param column column name or NULL
5043 * @param columnLen length of column name or SQL_NTS
5044 * @result ODBC error code
5045 */
5046
5047 SQLRETURN SQL_API
SQLColumnPrivilegesW(SQLHSTMT stmt,SQLWCHAR * catalog,SQLSMALLINT catalogLen,SQLWCHAR * schema,SQLSMALLINT schemaLen,SQLWCHAR * table,SQLSMALLINT tableLen,SQLWCHAR * column,SQLSMALLINT columnLen)5048 SQLColumnPrivilegesW(SQLHSTMT stmt,
5049 SQLWCHAR *catalog, SQLSMALLINT catalogLen,
5050 SQLWCHAR *schema, SQLSMALLINT schemaLen,
5051 SQLWCHAR *table, SQLSMALLINT tableLen,
5052 SQLWCHAR *column, SQLSMALLINT columnLen)
5053 {
5054 SQLRETURN ret;
5055
5056 HSTMT_LOCK(stmt);
5057 ret = mkresultset(stmt, colPrivSpec2, array_size(colPrivSpec2),
5058 colPrivSpec3, array_size(colPrivSpec3), NULL);
5059 HSTMT_UNLOCK(stmt);
5060 return ret;
5061 }
5062 #endif
5063 #endif
5064
5065 /**
5066 * Columns for result set of SQLPrimaryKeys().
5067 */
5068
5069 static COL pkeySpec2[] = {
5070 { "SYSTEM", "PRIMARYKEY", "TABLE_QUALIFIER", SCOL_VARCHAR, 50 },
5071 { "SYSTEM", "PRIMARYKEY", "TABLE_OWNER", SCOL_VARCHAR, 50 },
5072 { "SYSTEM", "PRIMARYKEY", "TABLE_NAME", SCOL_VARCHAR, 255 },
5073 { "SYSTEM", "PRIMARYKEY", "COLUMN_NAME", SCOL_VARCHAR, 255 },
5074 { "SYSTEM", "PRIMARYKEY", "KEY_SEQ", SQL_SMALLINT, 50 },
5075 { "SYSTEM", "PRIMARYKEY", "PK_NAME", SCOL_VARCHAR, 50 }
5076 };
5077
5078 static COL pkeySpec3[] = {
5079 { "SYSTEM", "PRIMARYKEY", "TABLE_CAT", SCOL_VARCHAR, 50 },
5080 { "SYSTEM", "PRIMARYKEY", "TABLE_SCHEM", SCOL_VARCHAR, 50 },
5081 { "SYSTEM", "PRIMARYKEY", "TABLE_NAME", SCOL_VARCHAR, 255 },
5082 { "SYSTEM", "PRIMARYKEY", "COLUMN_NAME", SCOL_VARCHAR, 255 },
5083 { "SYSTEM", "PRIMARYKEY", "KEY_SEQ", SQL_SMALLINT, 50 },
5084 { "SYSTEM", "PRIMARYKEY", "PK_NAME", SCOL_VARCHAR, 50 }
5085 };
5086
5087 /**
5088 * Internal retrieve information about indexed columns.
5089 * @param stmt statement handle
5090 * @param cat catalog name/pattern or NULL
5091 * @param catLen length of catalog name/pattern or SQL_NTS
5092 * @param schema schema name/pattern or NULL
5093 * @param schemaLen length of schema name/pattern or SQL_NTS
5094 * @param table table name/pattern or NULL
5095 * @param tableLen length of table name/pattern or SQL_NTS
5096 * @result ODBC error code
5097 */
5098
5099 static SQLRETURN
drvprimarykeys(SQLHSTMT stmt,SQLCHAR * cat,SQLSMALLINT catLen,SQLCHAR * schema,SQLSMALLINT schemaLen,SQLCHAR * table,SQLSMALLINT tableLen)5100 drvprimarykeys(SQLHSTMT stmt,
5101 SQLCHAR *cat, SQLSMALLINT catLen,
5102 SQLCHAR *schema, SQLSMALLINT schemaLen,
5103 SQLCHAR *table, SQLSMALLINT tableLen)
5104 {
5105 STMT *s;
5106 DBC *d;
5107 SQLRETURN sret;
5108 int i, asize, ret, nrows, ncols, nrows2 = 0, ncols2 = 0;
5109 int namec = -1, uniquec = -1, namec2 = -1, uniquec2 = -1, offs, seq = 1;
5110 PTRDIFF_T size;
5111 char **rowp = NULL, **rowp2 = NULL, *errp = NULL, tname[512];
5112
5113 sret = mkresultset(stmt, pkeySpec2, array_size(pkeySpec2),
5114 pkeySpec3, array_size(pkeySpec3), &asize);
5115 if (sret != SQL_SUCCESS) {
5116 return sret;
5117 }
5118 s = (STMT *) stmt;
5119 d = (DBC *) s->dbc;
5120 if (!table || table[0] == '\0' || table[0] == '%') {
5121 setstat(s, -1, "need table name", (*s->ov3) ? "HY000" : "S1000");
5122 return SQL_ERROR;
5123 }
5124 if (tableLen == SQL_NTS) {
5125 size = sizeof (tname) - 1;
5126 } else {
5127 size = min(sizeof (tname) - 1, tableLen);
5128 }
5129 strncpy(tname, (char *) table, size);
5130 tname[size] = '\0';
5131 unescpat(tname);
5132 sret = starttran(s);
5133 if (sret != SQL_SUCCESS) {
5134 return sret;
5135 }
5136 ret = sqlite_get_table_printf(d->sqlite,
5137 "PRAGMA table_info('%q')", &rowp,
5138 &nrows, &ncols, &errp, tname);
5139 if (ret != SQLITE_OK) {
5140 setstat(s, ret, "%s (%d)", (*s->ov3) ? "HY000" : "S1000",
5141 errp ? errp : "unknown error", ret);
5142 if (errp) {
5143 sqlite_freemem(errp);
5144 errp = NULL;
5145 }
5146 return SQL_ERROR;
5147 }
5148 if (errp) {
5149 sqlite_freemem(errp);
5150 errp = NULL;
5151 }
5152 size = 0;
5153 if (ncols * nrows > 0) {
5154 int typec;
5155
5156 namec = findcol(rowp, ncols, "name");
5157 uniquec = findcol(rowp, ncols, "pk");
5158 typec = findcol(rowp, ncols, "type");
5159 if (namec >= 0 && uniquec >= 0 && typec >= 0) {
5160 for (i = 1; i <= nrows; i++) {
5161 if (*rowp[i * ncols + uniquec] != '0') {
5162 size++;
5163 }
5164 }
5165 }
5166 }
5167 if (size == 0) {
5168 ret = sqlite_get_table_printf(d->sqlite,
5169 "PRAGMA index_list('%q')", &rowp2,
5170 &nrows2, &ncols2, &errp, tname);
5171 if (ret != SQLITE_OK) {
5172 sqlite_free_table(rowp);
5173 sqlite_free_table(rowp2);
5174 setstat(s, ret, "%s (%d)", (*s->ov3) ? "HY000" : "S1000",
5175 errp ? errp : "unknown error", ret);
5176 if (errp) {
5177 sqlite_freemem(errp);
5178 errp = NULL;
5179 }
5180 return SQL_ERROR;
5181 }
5182 if (errp) {
5183 sqlite_freemem(errp);
5184 errp = NULL;
5185 }
5186 }
5187 if (ncols2 * nrows2 > 0) {
5188 namec2 = findcol(rowp2, ncols, "name");
5189 uniquec2 = findcol(rowp2, ncols, "unique");
5190 if (namec2 >= 0 && uniquec2 >= 0) {
5191 for (i = 1; i <= nrows2; i++) {
5192 int nnrows, nncols;
5193 char **rowpp;
5194
5195 if (*rowp2[i * ncols2 + namec2] != '(' ||
5196 !strstr(rowp2[i * ncols2 + namec2], " autoindex ")) {
5197 continue;
5198 }
5199 if (*rowp2[i * ncols2 + uniquec2] != '0') {
5200 ret = sqlite_get_table_printf(d->sqlite,
5201 "PRAGMA index_info('%q')",
5202 &rowpp, &nnrows, &nncols,
5203 NULL,
5204 rowp2[i * ncols2 + namec2]);
5205 if (ret == SQLITE_OK) {
5206 size += nnrows;
5207 sqlite_free_table(rowpp);
5208 }
5209 }
5210 }
5211 }
5212 }
5213 if (size == 0) {
5214 sqlite_free_table(rowp);
5215 sqlite_free_table(rowp2);
5216 return SQL_SUCCESS;
5217 }
5218 s->nrows = size;
5219 size = (size + 1) * asize;
5220 s->rows = xmalloc((size + 1) * sizeof (char *));
5221 if (!s->rows) {
5222 s->nrows = 0;
5223 sqlite_free_table(rowp);
5224 sqlite_free_table(rowp2);
5225 return nomem(s);
5226 }
5227 s->rows[0] = (char *) size;
5228 s->rows += 1;
5229 memset(s->rows, 0, sizeof (char *) * size);
5230 s->rowfree = freerows;
5231 offs = s->ncols;
5232 if (rowp) {
5233 for (i = 1; i <= nrows; i++) {
5234 if (*rowp[i * ncols + uniquec] != '0') {
5235 char buf[32];
5236
5237 #if defined(_WIN32) || defined(_WIN64)
5238 s->rows[offs + 0] = xstrdup(d->xcelqrx ? "main" : "");
5239 s->rows[offs + 1] = xstrdup("");
5240 #else
5241 s->rows[offs + 0] = xstrdup("");
5242 s->rows[offs + 1] = xstrdup("");
5243 #endif
5244 s->rows[offs + 2] = xstrdup(tname);
5245 s->rows[offs + 3] = xstrdup(rowp[i * ncols + namec]);
5246 sprintf(buf, "%d", seq++);
5247 s->rows[offs + 4] = xstrdup(buf);
5248 offs += s->ncols;
5249 }
5250 }
5251 }
5252 if (rowp2) {
5253 for (i = 1; i <= nrows2; i++) {
5254 int nnrows, nncols;
5255 char **rowpp;
5256
5257 if (*rowp2[i * ncols2 + namec2] != '(' ||
5258 !strstr(rowp2[i * ncols2 + namec2], " autoindex ")) {
5259 continue;
5260 }
5261 if (*rowp2[i * ncols2 + uniquec2] != '0') {
5262 int k;
5263
5264 ret = sqlite_get_table_printf(d->sqlite,
5265 "PRAGMA index_info('%q')",
5266 &rowpp,
5267 &nnrows, &nncols, NULL,
5268 rowp2[i * ncols2 + namec2]);
5269 if (ret != SQLITE_OK) {
5270 continue;
5271 }
5272 for (k = 0; nnrows && k < nncols; k++) {
5273 if (strcmp(rowpp[k], "name") == 0) {
5274 int m;
5275
5276 for (m = 1; m <= nnrows; m++) {
5277 int roffs = offs + (m - 1) * s->ncols;
5278
5279 #if defined(_WIN32) || defined(_WIN64)
5280 s->rows[roffs + 0] =
5281 xstrdup(d->xcelqrx ? "main" : "");
5282 s->rows[roffs + 1] = xstrdup("");
5283 #else
5284 s->rows[roffs + 0] = xstrdup("");
5285 s->rows[roffs + 1] = xstrdup("");
5286 #endif
5287 s->rows[roffs + 2] = xstrdup(tname);
5288 s->rows[roffs + 3] =
5289 xstrdup(rowpp[m * nncols + k]);
5290 s->rows[roffs + 5] =
5291 xstrdup(rowp2[i * ncols2 + namec2]);
5292 }
5293 } else if (strcmp(rowpp[k], "seqno") == 0) {
5294 int m;
5295
5296 for (m = 1; m <= nnrows; m++) {
5297 int roffs = offs + (m - 1) * s->ncols;
5298 int pos = m - 1;
5299 char buf[32];
5300
5301 sscanf(rowpp[m * nncols + k], "%d", &pos);
5302 sprintf(buf, "%d", pos + 1);
5303 s->rows[roffs + 4] = xstrdup(buf);
5304 }
5305 }
5306 }
5307 offs += nnrows * s->ncols;
5308 sqlite_free_table(rowpp);
5309 }
5310 }
5311 }
5312 sqlite_free_table(rowp);
5313 sqlite_free_table(rowp2);
5314 return SQL_SUCCESS;
5315 }
5316
5317 #ifndef WINTERFACE
5318 /**
5319 * Retrieve information about indexed columns.
5320 * @param stmt statement handle
5321 * @param cat catalog name/pattern or NULL
5322 * @param catLen length of catalog name/pattern or SQL_NTS
5323 * @param schema schema name/pattern or NULL
5324 * @param schemaLen length of schema name/pattern or SQL_NTS
5325 * @param table table name/pattern or NULL
5326 * @param tableLen length of table name/pattern or SQL_NTS
5327 * @result ODBC error code
5328 */
5329
5330 SQLRETURN SQL_API
SQLPrimaryKeys(SQLHSTMT stmt,SQLCHAR * cat,SQLSMALLINT catLen,SQLCHAR * schema,SQLSMALLINT schemaLen,SQLCHAR * table,SQLSMALLINT tableLen)5331 SQLPrimaryKeys(SQLHSTMT stmt,
5332 SQLCHAR *cat, SQLSMALLINT catLen,
5333 SQLCHAR *schema, SQLSMALLINT schemaLen,
5334 SQLCHAR *table, SQLSMALLINT tableLen)
5335 {
5336 SQLRETURN ret;
5337
5338 HSTMT_LOCK(stmt);
5339 ret = drvprimarykeys(stmt, cat, catLen, schema, schemaLen,
5340 table, tableLen);
5341 HSTMT_UNLOCK(stmt);
5342 return ret;
5343 }
5344 #endif
5345
5346 #ifdef WINTERFACE
5347 /**
5348 * Retrieve information about indexed columns (UNICODE version).
5349 * @param stmt statement handle
5350 * @param cat catalog name/pattern or NULL
5351 * @param catLen length of catalog name/pattern or SQL_NTS
5352 * @param schema schema name/pattern or NULL
5353 * @param schemaLen length of schema name/pattern or SQL_NTS
5354 * @param table table name/pattern or NULL
5355 * @param tableLen length of table name/pattern or SQL_NTS
5356 * @result ODBC error code
5357 */
5358
5359 SQLRETURN SQL_API
SQLPrimaryKeysW(SQLHSTMT stmt,SQLWCHAR * cat,SQLSMALLINT catLen,SQLWCHAR * schema,SQLSMALLINT schemaLen,SQLWCHAR * table,SQLSMALLINT tableLen)5360 SQLPrimaryKeysW(SQLHSTMT stmt,
5361 SQLWCHAR *cat, SQLSMALLINT catLen,
5362 SQLWCHAR *schema, SQLSMALLINT schemaLen,
5363 SQLWCHAR *table, SQLSMALLINT tableLen)
5364 {
5365 char *c = NULL, *s = NULL, *t = NULL;
5366 SQLRETURN ret;
5367
5368 HSTMT_LOCK(stmt);
5369 if (cat) {
5370 c = uc_to_utf_c(cat, catLen);
5371 if (!c) {
5372 ret = nomem((STMT *) stmt);
5373 goto done;
5374 }
5375 }
5376 if (schema) {
5377 s = uc_to_utf_c(schema, schemaLen);
5378 if (!s) {
5379 ret = nomem((STMT *) stmt);
5380 goto done;
5381 }
5382 }
5383 if (table) {
5384 t = uc_to_utf_c(table, tableLen);
5385 if (!t) {
5386 ret = nomem((STMT *) stmt);
5387 goto done;
5388 }
5389 }
5390 ret = drvprimarykeys(stmt, (SQLCHAR *) c, SQL_NTS,
5391 (SQLCHAR *) s, SQL_NTS, (SQLCHAR *) t, SQL_NTS);
5392 done:
5393 HSTMT_UNLOCK(stmt);
5394 uc_free(t);
5395 uc_free(s);
5396 uc_free(c);
5397 return ret;
5398 }
5399 #endif
5400
5401 /**
5402 * Columns for result set of SQLSpecialColumns().
5403 */
5404
5405 static COL scolSpec2[] = {
5406 { "SYSTEM", "COLUMN", "SCOPE", SQL_SMALLINT, 1 },
5407 { "SYSTEM", "COLUMN", "COLUMN_NAME", SCOL_VARCHAR, 255 },
5408 { "SYSTEM", "COLUMN", "DATA_TYPE", SQL_SMALLINT, 50 },
5409 { "SYSTEM", "COLUMN", "TYPE_NAME", SCOL_VARCHAR, 50 },
5410 { "SYSTEM", "COLUMN", "PRECISION", SQL_INTEGER, 50 },
5411 { "SYSTEM", "COLUMN", "LENGTH", SQL_INTEGER, 50 },
5412 { "SYSTEM", "COLUMN", "DECIMAL_DIGITS", SQL_INTEGER, 50 },
5413 { "SYSTEM", "COLUMN", "PSEUDO_COLUMN", SQL_SMALLINT, 1 },
5414 { "SYSTEM", "COLUMN", "NULLABLE", SQL_SMALLINT, 1 }
5415 };
5416
5417 static COL scolSpec3[] = {
5418 { "SYSTEM", "COLUMN", "SCOPE", SQL_SMALLINT, 1 },
5419 { "SYSTEM", "COLUMN", "COLUMN_NAME", SCOL_VARCHAR, 255 },
5420 { "SYSTEM", "COLUMN", "DATA_TYPE", SQL_SMALLINT, 50 },
5421 { "SYSTEM", "COLUMN", "TYPE_NAME", SCOL_VARCHAR, 50 },
5422 { "SYSTEM", "COLUMN", "COLUMN_SIZE", SQL_INTEGER, 50 },
5423 { "SYSTEM", "COLUMN", "BUFFER_LENGTH", SQL_INTEGER, 50 },
5424 { "SYSTEM", "COLUMN", "DECIMAL_DIGITS", SQL_INTEGER, 50 },
5425 { "SYSTEM", "COLUMN", "PSEUDO_COLUMN", SQL_SMALLINT, 1 },
5426 { "SYSTEM", "COLUMN", "NULLABLE", SQL_SMALLINT, 1 }
5427 };
5428
5429 /**
5430 * Internal retrieve information about indexed columns.
5431 * @param stmt statement handle
5432 * @param id type of information, e.g. best row id
5433 * @param cat catalog name/pattern or NULL
5434 * @param catLen length of catalog name/pattern or SQL_NTS
5435 * @param schema schema name/pattern or NULL
5436 * @param schemaLen length of schema name/pattern or SQL_NTS
5437 * @param table table name/pattern or NULL
5438 * @param tableLen length of table name/pattern or SQL_NTS
5439 * @param scope
5440 * @param nullable
5441 * @result ODBC error code
5442 */
5443
5444 static SQLRETURN
drvspecialcolumns(SQLHSTMT stmt,SQLUSMALLINT id,SQLCHAR * cat,SQLSMALLINT catLen,SQLCHAR * schema,SQLSMALLINT schemaLen,SQLCHAR * table,SQLSMALLINT tableLen,SQLUSMALLINT scope,SQLUSMALLINT nullable)5445 drvspecialcolumns(SQLHSTMT stmt, SQLUSMALLINT id,
5446 SQLCHAR *cat, SQLSMALLINT catLen,
5447 SQLCHAR *schema, SQLSMALLINT schemaLen,
5448 SQLCHAR *table, SQLSMALLINT tableLen,
5449 SQLUSMALLINT scope, SQLUSMALLINT nullable)
5450 {
5451 STMT *s;
5452 DBC *d;
5453 SQLRETURN sret;
5454 int i, asize, ret, nrows, ncols, nnnrows, nnncols, offs;
5455 int namec = -1, uniquec = -1, namecc = -1, typecc = -1;
5456 int notnullcc = -1, mkrowid = 0;
5457 PTRDIFF_T size;
5458 char *errp = NULL, tname[512];
5459 char **rowp = NULL, **rowppp = NULL;
5460
5461 sret = mkresultset(stmt, scolSpec2, array_size(scolSpec2),
5462 scolSpec3, array_size(scolSpec3), &asize);
5463 if (sret != SQL_SUCCESS) {
5464 return sret;
5465 }
5466 s = (STMT *) stmt;
5467 d = (DBC *) s->dbc;
5468 if (!table || table[0] == '\0' || table[0] == '%') {
5469 setstat(s, -1, "need table name", (*s->ov3) ? "HY000" : "S1000");
5470 return SQL_ERROR;
5471 }
5472 if (tableLen == SQL_NTS) {
5473 size = sizeof (tname) - 1;
5474 } else {
5475 size = min(sizeof (tname) - 1, tableLen);
5476 }
5477 strncpy(tname, (char *) table, size);
5478 tname[size] = '\0';
5479 unescpat(tname);
5480 if (id != SQL_BEST_ROWID) {
5481 return SQL_SUCCESS;
5482 }
5483 sret = starttran(s);
5484 if (sret != SQL_SUCCESS) {
5485 return sret;
5486 }
5487 ret = sqlite_get_table_printf(d->sqlite, "PRAGMA index_list('%q')",
5488 &rowp, &nrows, &ncols, &errp, tname);
5489 if (ret != SQLITE_OK) {
5490 doerr:
5491 setstat(s, ret, "%s (%d)", (*s->ov3) ? "HY000" : "S1000",
5492 errp ? errp : "unknown error", ret);
5493 if (errp) {
5494 sqlite_freemem(errp);
5495 errp = NULL;
5496 }
5497 return SQL_ERROR;
5498 }
5499 if (errp) {
5500 sqlite_freemem(errp);
5501 errp = NULL;
5502 }
5503 size = 0; /* number result rows */
5504 if (ncols * nrows <= 0) {
5505 goto nodata_but_rowid;
5506 }
5507 ret = sqlite_get_table_printf(d->sqlite, "PRAGMA table_info('%q')",
5508 &rowppp, &nnnrows, &nnncols, &errp, tname);
5509 if (ret != SQLITE_OK) {
5510 sqlite_free_table(rowp);
5511 goto doerr;
5512 }
5513 if (errp) {
5514 sqlite_freemem(errp);
5515 errp = NULL;
5516 }
5517 namec = findcol(rowp, ncols, "name");
5518 uniquec = findcol(rowp, ncols, "unique");
5519 if (namec < 0 || uniquec < 0) {
5520 goto nodata_but_rowid;
5521 }
5522 namecc = findcol(rowppp, nnncols, "name");
5523 typecc = findcol(rowppp, nnncols, "type");
5524 notnullcc = findcol(rowppp, nnncols, "notnull");
5525 for (i = 1; i <= nrows; i++) {
5526 int nnrows, nncols;
5527 char **rowpp;
5528
5529 if (*rowp[i * ncols + uniquec] != '0') {
5530 ret = sqlite_get_table_printf(d->sqlite,
5531 "PRAGMA index_info('%q')", &rowpp,
5532 &nnrows, &nncols, NULL,
5533 rowp[i * ncols + namec]);
5534 if (ret == SQLITE_OK) {
5535 size += nnrows;
5536 sqlite_free_table(rowpp);
5537 }
5538 }
5539 }
5540 nodata_but_rowid:
5541 if (size == 0) {
5542 size = 1;
5543 mkrowid = 1;
5544 }
5545 s->nrows = size;
5546 size = (size + 1) * asize;
5547 s->rows = xmalloc((size + 1) * sizeof (char *));
5548 if (!s->rows) {
5549 s->nrows = 0;
5550 sqlite_free_table(rowp);
5551 sqlite_free_table(rowppp);
5552 return nomem(s);
5553 }
5554 s->rows[0] = (char *) size;
5555 s->rows += 1;
5556 memset(s->rows, 0, sizeof (char *) * size);
5557 s->rowfree = freerows;
5558 if (mkrowid) {
5559 s->nrows = 0;
5560 goto mkrowid;
5561 }
5562 offs = 0;
5563 for (i = 1; i <= nrows; i++) {
5564 int nnrows, nncols;
5565 char **rowpp;
5566
5567 if (*rowp[i * ncols + uniquec] != '0') {
5568 int k;
5569
5570 ret = sqlite_get_table_printf(d->sqlite,
5571 "PRAGMA index_info('%q')", &rowpp,
5572 &nnrows, &nncols, NULL,
5573 rowp[i * ncols + namec]);
5574 if (ret != SQLITE_OK) {
5575 continue;
5576 }
5577 for (k = 0; nnrows && k < nncols; k++) {
5578 if (strcmp(rowpp[k], "name") == 0) {
5579 int m;
5580
5581 for (m = 1; m <= nnrows; m++) {
5582 int roffs = (offs + m) * s->ncols;
5583
5584 s->rows[roffs + 0] =
5585 xstrdup(stringify(SQL_SCOPE_SESSION));
5586 s->rows[roffs + 1] = xstrdup(rowpp[m * nncols + k]);
5587 s->rows[roffs + 4] = xstrdup("0");
5588 s->rows[roffs + 7] =
5589 xstrdup(stringify(SQL_PC_NOT_PSEUDO));
5590 if (namecc >= 0 && typecc >= 0) {
5591 int ii;
5592
5593 for (ii = 1; ii <= nnnrows; ii++) {
5594 if (strcmp(rowppp[ii * nnncols + namecc],
5595 rowpp[m * nncols + k]) == 0) {
5596 char *typen = rowppp[ii * nnncols + typecc];
5597 int sqltype, mm, dd, isnullable = 0;
5598 char buf[32];
5599
5600 s->rows[roffs + 3] = xstrdup(typen);
5601 sqltype = mapsqltype(typen, NULL, *s->ov3,
5602 s->nowchar[0]);
5603 getmd(typen, sqltype, &mm, &dd);
5604 #ifdef SQL_LONGVARCHAR
5605 if (sqltype == SQL_VARCHAR && mm > 255) {
5606 sqltype = SQL_LONGVARCHAR;
5607 }
5608 #endif
5609 #ifdef WINTERFACE
5610 #ifdef SQL_WLONGVARCHAR
5611 if (sqltype == SQL_WVARCHAR && mm > 255) {
5612 sqltype = SQL_WLONGVARCHAR;
5613 }
5614 #endif
5615 #endif
5616 #if (HAVE_ENCDEC)
5617 if (sqltype == SQL_VARBINARY && mm > 255) {
5618 sqltype = SQL_LONGVARBINARY;
5619 }
5620 #endif
5621 sprintf(buf, "%d", sqltype);
5622 s->rows[roffs + 2] = xstrdup(buf);
5623 sprintf(buf, "%d", mm);
5624 s->rows[roffs + 5] = xstrdup(buf);
5625 sprintf(buf, "%d", dd);
5626 s->rows[roffs + 6] = xstrdup(buf);
5627 if (notnullcc >= 0) {
5628 char *inp =
5629 rowppp[ii * nnncols + notnullcc];
5630
5631 isnullable = inp[0] != '0';
5632 }
5633 sprintf(buf, "%d", isnullable);
5634 s->rows[roffs + 8] = xstrdup(buf);
5635 }
5636 }
5637 }
5638 }
5639 }
5640 }
5641 offs += nnrows;
5642 sqlite_free_table(rowpp);
5643 }
5644 }
5645 if (nullable == SQL_NO_NULLS) {
5646 for (i = 1; i < s->nrows; i++) {
5647 if (s->rows[i * s->ncols + 8][0] == '0') {
5648 int m, i1 = i + 1;
5649
5650 for (m = 0; m < s->ncols; m++) {
5651 freep(&s->rows[i * s->ncols + m]);
5652 }
5653 size = s->ncols * sizeof (char *) * (s->nrows - i1);
5654 if (size > 0) {
5655 memmove(s->rows + i * s->ncols,
5656 s->rows + i1 * s->ncols,
5657 size);
5658 memset(s->rows + s->nrows * s->ncols, 0,
5659 s->ncols * sizeof (char *));
5660 }
5661 s->nrows--;
5662 --i;
5663 }
5664 }
5665 }
5666 mkrowid:
5667 sqlite_free_table(rowp);
5668 sqlite_free_table(rowppp);
5669 if (s->nrows == 0) {
5670 s->rows[s->ncols + 0] = xstrdup(stringify(SQL_SCOPE_SESSION));
5671 s->rows[s->ncols + 1] = xstrdup("_ROWID_");
5672 s->rows[s->ncols + 2] = xstrdup(stringify(SQL_INTEGER));
5673 s->rows[s->ncols + 3] = xstrdup("integer");
5674 s->rows[s->ncols + 4] = xstrdup("0");
5675 s->rows[s->ncols + 5] = xstrdup("10");
5676 s->rows[s->ncols + 6] = xstrdup("9");
5677 s->rows[s->ncols + 7] = xstrdup(stringify(SQL_PC_PSEUDO));
5678 s->rows[s->ncols + 8] = xstrdup(stringify(SQL_FALSE));
5679 s->nrows = 1;
5680 }
5681 return SQL_SUCCESS;
5682 }
5683
5684 #ifndef WINTERFACE
5685 /**
5686 * Retrieve information about indexed columns.
5687 * @param stmt statement handle
5688 * @param id type of information, e.g. best row id
5689 * @param cat catalog name/pattern or NULL
5690 * @param catLen length of catalog name/pattern or SQL_NTS
5691 * @param schema schema name/pattern or NULL
5692 * @param schemaLen length of schema name/pattern or SQL_NTS
5693 * @param table table name/pattern or NULL
5694 * @param tableLen length of table name/pattern or SQL_NTS
5695 * @param scope
5696 * @param nullable
5697 * @result ODBC error code
5698 */
5699
5700 SQLRETURN SQL_API
SQLSpecialColumns(SQLHSTMT stmt,SQLUSMALLINT id,SQLCHAR * cat,SQLSMALLINT catLen,SQLCHAR * schema,SQLSMALLINT schemaLen,SQLCHAR * table,SQLSMALLINT tableLen,SQLUSMALLINT scope,SQLUSMALLINT nullable)5701 SQLSpecialColumns(SQLHSTMT stmt, SQLUSMALLINT id,
5702 SQLCHAR *cat, SQLSMALLINT catLen,
5703 SQLCHAR *schema, SQLSMALLINT schemaLen,
5704 SQLCHAR *table, SQLSMALLINT tableLen,
5705 SQLUSMALLINT scope, SQLUSMALLINT nullable)
5706 {
5707 SQLRETURN ret;
5708
5709 HSTMT_LOCK(stmt);
5710 ret = drvspecialcolumns(stmt, id, cat, catLen, schema, schemaLen,
5711 table, tableLen, scope, nullable);
5712 HSTMT_UNLOCK(stmt);
5713 return ret;
5714 }
5715 #endif
5716
5717 #ifdef WINTERFACE
5718 /**
5719 * Retrieve information about indexed columns (UNICODE version).
5720 * @param stmt statement handle
5721 * @param id type of information, e.g. best row id
5722 * @param cat catalog name/pattern or NULL
5723 * @param catLen length of catalog name/pattern or SQL_NTS
5724 * @param schema schema name/pattern or NULL
5725 * @param schemaLen length of schema name/pattern or SQL_NTS
5726 * @param table table name/pattern or NULL
5727 * @param tableLen length of table name/pattern or SQL_NTS
5728 * @param scope
5729 * @param nullable
5730 * @result ODBC error code
5731 */
5732
5733 SQLRETURN SQL_API
SQLSpecialColumnsW(SQLHSTMT stmt,SQLUSMALLINT id,SQLWCHAR * cat,SQLSMALLINT catLen,SQLWCHAR * schema,SQLSMALLINT schemaLen,SQLWCHAR * table,SQLSMALLINT tableLen,SQLUSMALLINT scope,SQLUSMALLINT nullable)5734 SQLSpecialColumnsW(SQLHSTMT stmt, SQLUSMALLINT id,
5735 SQLWCHAR *cat, SQLSMALLINT catLen,
5736 SQLWCHAR *schema, SQLSMALLINT schemaLen,
5737 SQLWCHAR *table, SQLSMALLINT tableLen,
5738 SQLUSMALLINT scope, SQLUSMALLINT nullable)
5739 {
5740 char *c = NULL, *s = NULL, *t = NULL;
5741 SQLRETURN ret;
5742
5743 HSTMT_LOCK(stmt);
5744 if (cat) {
5745 c = uc_to_utf_c(cat, catLen);
5746 if (!c) {
5747 ret = nomem((STMT *) stmt);
5748 goto done;
5749 }
5750 }
5751 if (schema) {
5752 s = uc_to_utf_c(schema, schemaLen);
5753 if (!s) {
5754 ret = nomem((STMT *) stmt);
5755 goto done;
5756 }
5757 }
5758 if (table) {
5759 t = uc_to_utf_c(table, tableLen);
5760 if (!t) {
5761 ret = nomem((STMT *) stmt);
5762 goto done;
5763 }
5764 }
5765 ret = drvspecialcolumns(stmt, id, (SQLCHAR *) c, SQL_NTS,
5766 (SQLCHAR *) s, SQL_NTS, (SQLCHAR *) t, SQL_NTS,
5767 scope, nullable);
5768 done:
5769 HSTMT_UNLOCK(stmt);
5770 uc_free(t);
5771 uc_free(s);
5772 uc_free(c);
5773 return ret;
5774 }
5775 #endif
5776
5777 /**
5778 * Columns for result set of SQLForeignKeys().
5779 */
5780
5781 static COL fkeySpec2[] = {
5782 { "SYSTEM", "FOREIGNKEY", "PKTABLE_QUALIFIER", SCOL_VARCHAR, 50 },
5783 { "SYSTEM", "FOREIGNKEY", "PKTABLE_OWNER", SCOL_VARCHAR, 50 },
5784 { "SYSTEM", "FOREIGNKEY", "PKTABLE_NAME", SCOL_VARCHAR, 255 },
5785 { "SYSTEM", "FOREIGNKEY", "PKCOLUMN_NAME", SCOL_VARCHAR, 255 },
5786 { "SYSTEM", "FOREIGNKEY", "FKTABLE_QUALIFIER", SCOL_VARCHAR, 50 },
5787 { "SYSTEM", "FOREIGNKEY", "FKTABLE_OWNER", SCOL_VARCHAR, 50 },
5788 { "SYSTEM", "FOREIGNKEY", "FKTABLE_NAME", SCOL_VARCHAR, 255 },
5789 { "SYSTEM", "FOREIGNKEY", "FKCOLUMN_NAME", SCOL_VARCHAR, 255 },
5790 { "SYSTEM", "FOREIGNKEY", "KEY_SEQ", SQL_SMALLINT, 5 },
5791 { "SYSTEM", "FOREIGNKEY", "UPDATE_RULE", SQL_SMALLINT, 5 },
5792 { "SYSTEM", "FOREIGNKEY", "DELETE_RULE", SQL_SMALLINT, 5 },
5793 { "SYSTEM", "FOREIGNKEY", "FK_NAME", SCOL_VARCHAR, 255 },
5794 { "SYSTEM", "FOREIGNKEY", "PK_NAME", SCOL_VARCHAR, 255 },
5795 { "SYSTEM", "FOREIGNKEY", "DEFERRABILITY", SQL_SMALLINT, 5 }
5796 };
5797
5798 static COL fkeySpec3[] = {
5799 { "SYSTEM", "FOREIGNKEY", "PKTABLE_CAT", SCOL_VARCHAR, 50 },
5800 { "SYSTEM", "FOREIGNKEY", "PKTABLE_SCHEM", SCOL_VARCHAR, 50 },
5801 { "SYSTEM", "FOREIGNKEY", "PKTABLE_NAME", SCOL_VARCHAR, 255 },
5802 { "SYSTEM", "FOREIGNKEY", "PKCOLUMN_NAME", SCOL_VARCHAR, 255 },
5803 { "SYSTEM", "FOREIGNKEY", "FKTABLE_CAT", SCOL_VARCHAR, 50 },
5804 { "SYSTEM", "FOREIGNKEY", "FKTABLE_SCHEM", SCOL_VARCHAR, 50 },
5805 { "SYSTEM", "FOREIGNKEY", "FKTABLE_NAME", SCOL_VARCHAR, 255 },
5806 { "SYSTEM", "FOREIGNKEY", "FKCOLUMN_NAME", SCOL_VARCHAR, 255 },
5807 { "SYSTEM", "FOREIGNKEY", "KEY_SEQ", SQL_SMALLINT, 5 },
5808 { "SYSTEM", "FOREIGNKEY", "UPDATE_RULE", SQL_SMALLINT, 5 },
5809 { "SYSTEM", "FOREIGNKEY", "DELETE_RULE", SQL_SMALLINT, 5 },
5810 { "SYSTEM", "FOREIGNKEY", "FK_NAME", SCOL_VARCHAR, 255 },
5811 { "SYSTEM", "FOREIGNKEY", "PK_NAME", SCOL_VARCHAR, 255 },
5812 { "SYSTEM", "FOREIGNKEY", "DEFERRABILITY", SQL_SMALLINT, 5 }
5813 };
5814
5815 /**
5816 * Internal retrieve information about primary/foreign keys.
5817 * @param stmt statement handle
5818 * @param PKcatalog primary key catalog name/pattern or NULL
5819 * @param PKcatalogLen length of PKcatalog or SQL_NTS
5820 * @param PKschema primary key schema name/pattern or NULL
5821 * @param PKschemaLen length of PKschema or SQL_NTS
5822 * @param PKtable primary key table name/pattern or NULL
5823 * @param PKtableLen length of PKtable or SQL_NTS
5824 * @param FKcatalog foreign key catalog name/pattern or NULL
5825 * @param FKcatalogLen length of FKcatalog or SQL_NTS
5826 * @param FKschema foreign key schema name/pattern or NULL
5827 * @param FKschemaLen length of FKschema or SQL_NTS
5828 * @param FKtable foreign key table name/pattern or NULL
5829 * @param FKtableLen length of FKtable or SQL_NTS
5830 * @result ODBC error code
5831 */
5832
5833 static SQLRETURN SQL_API
drvforeignkeys(SQLHSTMT stmt,SQLCHAR * PKcatalog,SQLSMALLINT PKcatalogLen,SQLCHAR * PKschema,SQLSMALLINT PKschemaLen,SQLCHAR * PKtable,SQLSMALLINT PKtableLen,SQLCHAR * FKcatalog,SQLSMALLINT FKcatalogLen,SQLCHAR * FKschema,SQLSMALLINT FKschemaLen,SQLCHAR * FKtable,SQLSMALLINT FKtableLen)5834 drvforeignkeys(SQLHSTMT stmt,
5835 SQLCHAR *PKcatalog, SQLSMALLINT PKcatalogLen,
5836 SQLCHAR *PKschema, SQLSMALLINT PKschemaLen,
5837 SQLCHAR *PKtable, SQLSMALLINT PKtableLen,
5838 SQLCHAR *FKcatalog, SQLSMALLINT FKcatalogLen,
5839 SQLCHAR *FKschema, SQLSMALLINT FKschemaLen,
5840 SQLCHAR *FKtable, SQLSMALLINT FKtableLen)
5841 {
5842 STMT *s;
5843 DBC *d;
5844 SQLRETURN sret;
5845 int i, asize, ret, nrows, ncols, offs, namec, seqc, fromc, toc;
5846 PTRDIFF_T size;
5847 char **rowp, *errp = NULL, pname[512], fname[512];
5848
5849 sret = mkresultset(stmt, fkeySpec2, array_size(fkeySpec2),
5850 fkeySpec3, array_size(fkeySpec3), &asize);
5851 if (sret != SQL_SUCCESS) {
5852 return sret;
5853 }
5854 s = (STMT *) stmt;
5855 sret = starttran(s);
5856 if (sret != SQL_SUCCESS) {
5857 return sret;
5858 }
5859 d = (DBC *) s->dbc;
5860 if ((!PKtable || PKtable[0] == '\0' || PKtable[0] == '%') &&
5861 (!FKtable || FKtable[0] == '\0' || FKtable[0] == '%')) {
5862 setstat(s, -1, "need table name", (*s->ov3) ? "HY000" : "S1000");
5863 return SQL_ERROR;
5864 }
5865 size = 0;
5866 if (PKtable) {
5867 if (PKtableLen == SQL_NTS) {
5868 size = sizeof (pname) - 1;
5869 } else {
5870 size = min(sizeof (pname) - 1, PKtableLen);
5871 }
5872 strncpy(pname, (char *) PKtable, size);
5873 }
5874 pname[size] = '\0';
5875 size = 0;
5876 if (FKtable) {
5877 if (FKtableLen == SQL_NTS) {
5878 size = sizeof (fname) - 1;
5879 } else {
5880 size = min(sizeof (fname) - 1, FKtableLen);
5881 }
5882 strncpy(fname, (char *) FKtable, size);
5883 }
5884 fname[size] = '\0';
5885 if (fname[0] != '\0') {
5886 int plen;
5887
5888 ret = sqlite_get_table_printf(d->sqlite,
5889 "PRAGMA foreign_key_list('%q')", &rowp,
5890 &nrows, &ncols, &errp, fname);
5891 if (ret != SQLITE_OK) {
5892 setstat(s, ret, "%s (%d)", (*s->ov3) ? "HY000" : "S1000",
5893 errp ? errp : "unknown error", ret);
5894 if (errp) {
5895 sqlite_freemem(errp);
5896 errp = NULL;
5897 }
5898 return SQL_ERROR;
5899 }
5900 if (errp) {
5901 sqlite_freemem(errp);
5902 errp = NULL;
5903 }
5904 if (ncols * nrows <= 0) {
5905 nodata:
5906 sqlite_free_table(rowp);
5907 return SQL_SUCCESS;
5908 }
5909 size = 0;
5910 namec = findcol(rowp, ncols, "table");
5911 seqc = findcol(rowp, ncols, "seq");
5912 fromc = findcol(rowp, ncols, "from");
5913 toc = findcol(rowp, ncols, "to");
5914 if (namec < 0 || seqc < 0 || fromc < 0 || toc < 0) {
5915 goto nodata;
5916 }
5917 plen = strlen(pname);
5918 for (i = 1; i <= nrows; i++) {
5919 char *ptab = unquote(rowp[i * ncols + namec]);
5920
5921 if (plen && ptab) {
5922 int len = strlen(ptab);
5923
5924 if (plen != len || strncasecmp(pname, ptab, plen) != 0) {
5925 continue;
5926 }
5927 }
5928 size++;
5929 }
5930 if (size == 0) {
5931 goto nodata;
5932 }
5933 s->nrows = size;
5934 size = (size + 1) * asize;
5935 s->rows = xmalloc((size + 1) * sizeof (char *));
5936 if (!s->rows) {
5937 s->nrows = 0;
5938 return nomem(s);
5939 }
5940 s->rows[0] = (char *) size;
5941 s->rows += 1;
5942 memset(s->rows, 0, sizeof (char *) * size);
5943 s->rowfree = freerows;
5944 offs = 0;
5945 for (i = 1; i <= nrows; i++) {
5946 int pos = 0, roffs = (offs + 1) * s->ncols;
5947 char *ptab = rowp[i * ncols + namec];
5948 char buf[32];
5949
5950 if (plen && ptab) {
5951 int len = strlen(ptab);
5952
5953 if (plen != len || strncasecmp(pname, ptab, plen) != 0) {
5954 continue;
5955 }
5956 }
5957 #if defined(_WIN32) || defined(_WIN64)
5958 s->rows[roffs + 0] = xstrdup(d->xcelqrx ? "main" : "");
5959 s->rows[roffs + 1] = xstrdup("");
5960 #else
5961 s->rows[roffs + 0] = xstrdup("");
5962 s->rows[roffs + 1] = xstrdup("");
5963 #endif
5964 s->rows[roffs + 2] = xstrdup(ptab);
5965 s->rows[roffs + 3] = xstrdup(rowp[i * ncols + toc]);
5966 s->rows[roffs + 4] = xstrdup("");
5967 s->rows[roffs + 5] = xstrdup("");
5968 s->rows[roffs + 6] = xstrdup(fname);
5969 s->rows[roffs + 7] = xstrdup(rowp[i * ncols + fromc]);
5970 sscanf(rowp[i * ncols + seqc], "%d", &pos);
5971 sprintf(buf, "%d", pos + 1);
5972 s->rows[roffs + 8] = xstrdup(buf);
5973 s->rows[roffs + 9] = xstrdup(stringify(SQL_NO_ACTION));
5974 s->rows[roffs + 10] = xstrdup(stringify(SQL_NO_ACTION));
5975 s->rows[roffs + 11] = NULL;
5976 s->rows[roffs + 12] = NULL;
5977 s->rows[roffs + 13] = xstrdup(stringify(SQL_NOT_DEFERRABLE));
5978 offs++;
5979 }
5980 sqlite_free_table(rowp);
5981 } else {
5982 int nnrows, nncols, plen = strlen(pname);
5983 char **rowpp;
5984
5985 ret = sqlite_get_table(d->sqlite,
5986 "select name from sqlite_master "
5987 "where type='table'", &rowp,
5988 &nrows, &ncols, &errp);
5989 if (ret != SQLITE_OK) {
5990 setstat(s, ret, "%s (%d)", (*s->ov3) ? "HY000" : "S1000",
5991 errp ? errp : "unknown error", ret);
5992 if (errp) {
5993 sqlite_freemem(errp);
5994 errp = NULL;
5995 }
5996 return SQL_ERROR;
5997 }
5998 if (errp) {
5999 sqlite_freemem(errp);
6000 errp = NULL;
6001 }
6002 if (ncols * nrows <= 0) {
6003 goto nodata;
6004 }
6005 size = 0;
6006 for (i = 1; i <= nrows; i++) {
6007 int k;
6008
6009 if (!rowp[i]) {
6010 continue;
6011 }
6012 ret = sqlite_get_table_printf(d->sqlite,
6013 "PRAGMA foreign_key_list('%q')",
6014 &rowpp,
6015 &nnrows, &nncols, NULL, rowp[i]);
6016 if (ret != SQLITE_OK || nncols * nnrows <= 0) {
6017 sqlite_free_table(rowpp);
6018 continue;
6019 }
6020 namec = findcol(rowpp, nncols, "table");
6021 seqc = findcol(rowpp, nncols, "seq");
6022 fromc = findcol(rowpp, nncols, "from");
6023 toc = findcol(rowpp, nncols, "to");
6024 if (namec < 0 || seqc < 0 || fromc < 0 || toc < 0) {
6025 sqlite_free_table(rowpp);
6026 continue;
6027 }
6028 for (k = 1; k <= nnrows; k++) {
6029 char *ptab = unquote(rowpp[k * nncols + namec]);
6030
6031 if (plen && ptab) {
6032 int len = strlen(ptab);
6033
6034 if (len != plen || strncasecmp(pname, ptab, plen) != 0) {
6035 continue;
6036 }
6037 }
6038 size++;
6039 }
6040 sqlite_free_table(rowpp);
6041 }
6042 if (size == 0) {
6043 goto nodata;
6044 }
6045 s->nrows = size;
6046 size = (size + 1) * asize;
6047 s->rows = xmalloc((size + 1) * sizeof (char *));
6048 if (!s->rows) {
6049 s->nrows = 0;
6050 return nomem(s);
6051 }
6052 s->rows[0] = (char *) size;
6053 s->rows += 1;
6054 memset(s->rows, 0, sizeof (char *) * size);
6055 s->rowfree = freerows;
6056 offs = 0;
6057 for (i = 1; i <= nrows; i++) {
6058 int k;
6059
6060 if (!rowp[i]) {
6061 continue;
6062 }
6063 ret = sqlite_get_table_printf(d->sqlite,
6064 "PRAGMA foreign_key_list('%q')",
6065 &rowpp,
6066 &nnrows, &nncols, NULL, rowp[i]);
6067 if (ret != SQLITE_OK || nncols * nnrows <= 0) {
6068 sqlite_free_table(rowpp);
6069 continue;
6070 }
6071 namec = findcol(rowpp, nncols, "table");
6072 seqc = findcol(rowpp, nncols, "seq");
6073 fromc = findcol(rowpp, nncols, "from");
6074 toc = findcol(rowpp, nncols, "to");
6075 if (namec < 0 || seqc < 0 || fromc < 0 || toc < 0) {
6076 sqlite_free_table(rowpp);
6077 continue;
6078 }
6079 for (k = 1; k <= nnrows; k++) {
6080 int pos = 0, roffs = (offs + 1) * s->ncols;
6081 char *ptab = unquote(rowpp[k * nncols + namec]);
6082 char buf[32];
6083
6084 if (plen && ptab) {
6085 int len = strlen(ptab);
6086
6087 if (len != plen || strncasecmp(pname, ptab, plen) != 0) {
6088 continue;
6089 }
6090 }
6091 #if defined(_WIN32) || defined(_WIN64)
6092 s->rows[roffs + 0] = xstrdup(d->xcelqrx ? "main" : "");
6093 s->rows[roffs + 1] = xstrdup("");
6094 #else
6095 s->rows[roffs + 0] = xstrdup("");
6096 s->rows[roffs + 1] = xstrdup("");
6097 #endif
6098 s->rows[roffs + 2] = xstrdup(ptab);
6099 s->rows[roffs + 3] = xstrdup(rowpp[k * nncols + toc]);
6100 s->rows[roffs + 4] = xstrdup("");
6101 s->rows[roffs + 5] = xstrdup("");
6102 s->rows[roffs + 6] = xstrdup(rowp[i]);
6103 s->rows[roffs + 7] = xstrdup(rowpp[k * nncols + fromc]);
6104 sscanf(rowpp[k * nncols + seqc], "%d", &pos);
6105 sprintf(buf, "%d", pos + 1);
6106 s->rows[roffs + 8] = xstrdup(buf);
6107 s->rows[roffs + 9] = xstrdup(stringify(SQL_NO_ACTION));
6108 s->rows[roffs + 10] = xstrdup(stringify(SQL_NO_ACTION));
6109 s->rows[roffs + 11] = NULL;
6110 s->rows[roffs + 12] = NULL;
6111 s->rows[roffs + 13] = xstrdup(stringify(SQL_NOT_DEFERRABLE));
6112 offs++;
6113 }
6114 sqlite_free_table(rowpp);
6115 }
6116 sqlite_free_table(rowp);
6117 }
6118 return SQL_SUCCESS;
6119 }
6120
6121 #ifndef WINTERFACE
6122 /**
6123 * Retrieve information about primary/foreign keys.
6124 * @param stmt statement handle
6125 * @param PKcatalog primary key catalog name/pattern or NULL
6126 * @param PKcatalogLen length of PKcatalog or SQL_NTS
6127 * @param PKschema primary key schema name/pattern or NULL
6128 * @param PKschemaLen length of PKschema or SQL_NTS
6129 * @param PKtable primary key table name/pattern or NULL
6130 * @param PKtableLen length of PKtable or SQL_NTS
6131 * @param FKcatalog foreign key catalog name/pattern or NULL
6132 * @param FKcatalogLen length of FKcatalog or SQL_NTS
6133 * @param FKschema foreign key schema name/pattern or NULL
6134 * @param FKschemaLen length of FKschema or SQL_NTS
6135 * @param FKtable foreign key table name/pattern or NULL
6136 * @param FKtableLen length of FKtable or SQL_NTS
6137 * @result ODBC error code
6138 */
6139
6140 SQLRETURN SQL_API
SQLForeignKeys(SQLHSTMT stmt,SQLCHAR * PKcatalog,SQLSMALLINT PKcatalogLen,SQLCHAR * PKschema,SQLSMALLINT PKschemaLen,SQLCHAR * PKtable,SQLSMALLINT PKtableLen,SQLCHAR * FKcatalog,SQLSMALLINT FKcatalogLen,SQLCHAR * FKschema,SQLSMALLINT FKschemaLen,SQLCHAR * FKtable,SQLSMALLINT FKtableLen)6141 SQLForeignKeys(SQLHSTMT stmt,
6142 SQLCHAR *PKcatalog, SQLSMALLINT PKcatalogLen,
6143 SQLCHAR *PKschema, SQLSMALLINT PKschemaLen,
6144 SQLCHAR *PKtable, SQLSMALLINT PKtableLen,
6145 SQLCHAR *FKcatalog, SQLSMALLINT FKcatalogLen,
6146 SQLCHAR *FKschema, SQLSMALLINT FKschemaLen,
6147 SQLCHAR *FKtable, SQLSMALLINT FKtableLen)
6148 {
6149 SQLRETURN ret;
6150
6151 HSTMT_LOCK(stmt);
6152 ret = drvforeignkeys(stmt,
6153 PKcatalog, PKcatalogLen,
6154 PKschema, PKschemaLen, PKtable, PKtableLen,
6155 FKcatalog, FKcatalogLen,
6156 FKschema, FKschemaLen,
6157 FKtable, FKtableLen);
6158 HSTMT_UNLOCK(stmt);
6159 return ret;
6160 }
6161 #endif
6162
6163 #ifdef WINTERFACE
6164 /**
6165 * Retrieve information about primary/foreign keys (UNICODE version).
6166 * @param stmt statement handle
6167 * @param PKcatalog primary key catalog name/pattern or NULL
6168 * @param PKcatalogLen length of PKcatalog or SQL_NTS
6169 * @param PKschema primary key schema name/pattern or NULL
6170 * @param PKschemaLen length of PKschema or SQL_NTS
6171 * @param PKtable primary key table name/pattern or NULL
6172 * @param PKtableLen length of PKtable or SQL_NTS
6173 * @param FKcatalog foreign key catalog name/pattern or NULL
6174 * @param FKcatalogLen length of FKcatalog or SQL_NTS
6175 * @param FKschema foreign key schema name/pattern or NULL
6176 * @param FKschemaLen length of FKschema or SQL_NTS
6177 * @param FKtable foreign key table name/pattern or NULL
6178 * @param FKtableLen length of FKtable or SQL_NTS
6179 * @result ODBC error code
6180 */
6181
6182 SQLRETURN SQL_API
SQLForeignKeysW(SQLHSTMT stmt,SQLWCHAR * PKcatalog,SQLSMALLINT PKcatalogLen,SQLWCHAR * PKschema,SQLSMALLINT PKschemaLen,SQLWCHAR * PKtable,SQLSMALLINT PKtableLen,SQLWCHAR * FKcatalog,SQLSMALLINT FKcatalogLen,SQLWCHAR * FKschema,SQLSMALLINT FKschemaLen,SQLWCHAR * FKtable,SQLSMALLINT FKtableLen)6183 SQLForeignKeysW(SQLHSTMT stmt,
6184 SQLWCHAR *PKcatalog, SQLSMALLINT PKcatalogLen,
6185 SQLWCHAR *PKschema, SQLSMALLINT PKschemaLen,
6186 SQLWCHAR *PKtable, SQLSMALLINT PKtableLen,
6187 SQLWCHAR *FKcatalog, SQLSMALLINT FKcatalogLen,
6188 SQLWCHAR *FKschema, SQLSMALLINT FKschemaLen,
6189 SQLWCHAR *FKtable, SQLSMALLINT FKtableLen)
6190 {
6191 char *pc = NULL, *ps = NULL, *pt = NULL;
6192 char *fc = NULL, *fs = NULL, *ft = NULL;
6193 SQLRETURN ret;
6194
6195 HSTMT_LOCK(stmt);
6196 if (PKcatalog) {
6197 pc = uc_to_utf_c(PKcatalog, PKcatalogLen);
6198 if (!pc) {
6199 ret = nomem((STMT *) stmt);
6200 goto done;
6201 }
6202 }
6203 if (PKschema) {
6204 ps = uc_to_utf_c(PKschema, PKschemaLen);
6205 if (!ps) {
6206 ret = nomem((STMT *) stmt);
6207 goto done;
6208 }
6209 }
6210 if (PKtable) {
6211 pt = uc_to_utf_c(PKtable, PKtableLen);
6212 if (!pt) {
6213 ret = nomem((STMT *) stmt);
6214 goto done;
6215 }
6216 }
6217 if (FKcatalog) {
6218 fc = uc_to_utf_c(FKcatalog, FKcatalogLen);
6219 if (!fc) {
6220 ret = nomem((STMT *) stmt);
6221 goto done;
6222 }
6223 }
6224 if (FKschema) {
6225 fs = uc_to_utf_c(FKschema, FKschemaLen);
6226 if (!fs) {
6227 ret = nomem((STMT *) stmt);
6228 goto done;
6229 }
6230 }
6231 if (FKtable) {
6232 ft = uc_to_utf_c(FKtable, FKtableLen);
6233 if (!ft) {
6234 ret = nomem((STMT *) stmt);
6235 goto done;
6236 }
6237 }
6238 ret = drvforeignkeys(stmt, (SQLCHAR *) pc, SQL_NTS,
6239 (SQLCHAR *) ps, SQL_NTS, (SQLCHAR *) pt, SQL_NTS,
6240 (SQLCHAR *) fc, SQL_NTS, (SQLCHAR *) fs, SQL_NTS,
6241 (SQLCHAR *) ft, SQL_NTS);
6242 done:
6243 HSTMT_UNLOCK(stmt);
6244 uc_free(ft);
6245 uc_free(fs);
6246 uc_free(fc);
6247 uc_free(pt);
6248 uc_free(ps);
6249 uc_free(pc);
6250 return ret;
6251 }
6252 #endif
6253
6254 /**
6255 * Start transaction when autocommit off
6256 * @param s statement pointer
6257 * @result ODBC error code
6258 */
6259
6260 static SQLRETURN
starttran(STMT * s)6261 starttran(STMT *s)
6262 {
6263 int ret = SQL_SUCCESS, rc;
6264 char *errp = NULL;
6265 DBC *d = (DBC *) s->dbc;
6266
6267 if (!d->autocommit && !d->intrans && !d->trans_disable) {
6268 rc = sqlite_exec(d->sqlite, "BEGIN TRANSACTION", NULL, NULL, &errp);
6269 dbtracerc(d, rc, errp);
6270 if (rc != SQLITE_OK) {
6271 setstat(s, rc, "%s (%d)", (*s->ov3) ? "HY000" : "S1000",
6272 errp ? errp : "unknown error", rc);
6273 ret = SQL_ERROR;
6274 } else {
6275 d->intrans = 1;
6276 }
6277 if (errp) {
6278 sqlite_freemem(errp);
6279 errp = NULL;
6280 }
6281 }
6282 return ret;
6283 }
6284
6285 /**
6286 * Internal commit or rollback transaction.
6287 * @param d database connection pointer
6288 * @param comptype type of transaction's end, SQL_COMMIT or SQL_ROLLBACK
6289 * @param force force action regardless of DBC's autocommit state
6290 * @result ODBC error code
6291 */
6292
6293 static SQLRETURN
endtran(DBC * d,SQLSMALLINT comptype,int force)6294 endtran(DBC *d, SQLSMALLINT comptype, int force)
6295 {
6296 int ret;
6297 char *sql, *errp = NULL;
6298
6299 if (!d->sqlite) {
6300 setstatd(d, -1, "not connected", (*d->ov3) ? "HY000" : "S1000");
6301 return SQL_ERROR;
6302 }
6303 if ((!force && d->autocommit) || !d->intrans) {
6304 return SQL_SUCCESS;
6305 }
6306 switch (comptype) {
6307 case SQL_COMMIT:
6308 sql = "COMMIT TRANSACTION";
6309 goto doit;
6310 case SQL_ROLLBACK:
6311 sql = "ROLLBACK TRANSACTION";
6312 doit:
6313 ret = sqlite_exec(d->sqlite, sql, NULL, NULL, &errp);
6314 dbtracerc(d, ret, errp);
6315 if (ret != SQLITE_OK) {
6316 setstatd(d, ret, "%s", (*d->ov3) ? "HY000" : "S1000",
6317 errp ? errp : "transaction failed");
6318 if (errp) {
6319 sqlite_freemem(errp);
6320 errp = NULL;
6321 }
6322 return SQL_ERROR;
6323 }
6324 if (errp) {
6325 sqlite_freemem(errp);
6326 errp = NULL;
6327 }
6328 d->intrans = 0;
6329 return SQL_SUCCESS;
6330 }
6331 setstatd(d, -1, "invalid completion type", (*d->ov3) ? "HY000" : "S1000");
6332 return SQL_ERROR;
6333 }
6334
6335 /**
6336 * Internal commit or rollback transaction.
6337 * @param type type of handle
6338 * @param handle HDBC, HENV, or HSTMT handle
6339 * @param comptype SQL_COMMIT or SQL_ROLLBACK
6340 * @result ODBC error code
6341 */
6342
6343 static SQLRETURN
drvendtran(SQLSMALLINT type,SQLHANDLE handle,SQLSMALLINT comptype)6344 drvendtran(SQLSMALLINT type, SQLHANDLE handle, SQLSMALLINT comptype)
6345 {
6346 DBC *dbc = NULL;
6347 int fail = 0;
6348 SQLRETURN ret;
6349 #if defined(_WIN32) || defined(_WIN64)
6350 ENV *env;
6351 #endif
6352
6353 switch (type) {
6354 case SQL_HANDLE_DBC:
6355 HDBC_LOCK((SQLHDBC) handle);
6356 if (handle == SQL_NULL_HDBC) {
6357 return SQL_INVALID_HANDLE;
6358 }
6359 dbc = (DBC *) handle;
6360 ret = endtran(dbc, comptype, 0);
6361 HDBC_UNLOCK((SQLHDBC) handle);
6362 return ret;
6363 case SQL_HANDLE_ENV:
6364 if (handle == SQL_NULL_HENV) {
6365 return SQL_INVALID_HANDLE;
6366 }
6367 #if defined(_WIN32) || defined(_WIN64)
6368 env = (ENV *) handle;
6369 if (env->magic != ENV_MAGIC) {
6370 return SQL_INVALID_HANDLE;
6371 }
6372 EnterCriticalSection(&env->cs);
6373 #endif
6374 dbc = ((ENV *) handle)->dbcs;
6375 while (dbc) {
6376 HDBC_LOCK((SQLHDBC) dbc);
6377 ret = endtran(dbc, comptype, 0);
6378 HDBC_UNLOCK((SQLHDBC) dbc);
6379 if (ret != SQL_SUCCESS) {
6380 fail++;
6381 }
6382 dbc = dbc->next;
6383 }
6384 #if defined(_WIN32) || defined(_WIN64)
6385 LeaveCriticalSection(&env->cs);
6386 #endif
6387 return fail ? SQL_ERROR : SQL_SUCCESS;
6388 }
6389 return SQL_INVALID_HANDLE;
6390 }
6391
6392 /**
6393 * Commit or rollback transaction.
6394 * @param type type of handle
6395 * @param handle HDBC, HENV, or HSTMT handle
6396 * @param comptype SQL_COMMIT or SQL_ROLLBACK
6397 * @result ODBC error code
6398 */
6399
6400 SQLRETURN SQL_API
SQLEndTran(SQLSMALLINT type,SQLHANDLE handle,SQLSMALLINT comptype)6401 SQLEndTran(SQLSMALLINT type, SQLHANDLE handle, SQLSMALLINT comptype)
6402 {
6403 return drvendtran(type, handle, comptype);
6404 }
6405
6406 /**
6407 * Commit or rollback transaction.
6408 * @param env environment handle or NULL
6409 * @param dbc database connection handle or NULL
6410 * @param type SQL_COMMIT or SQL_ROLLBACK
6411 * @result ODBC error code
6412 */
6413
6414 SQLRETURN SQL_API
SQLTransact(SQLHENV env,SQLHDBC dbc,SQLUSMALLINT type)6415 SQLTransact(SQLHENV env, SQLHDBC dbc, SQLUSMALLINT type)
6416 {
6417 if (dbc != SQL_NULL_HDBC) {
6418 return drvendtran(SQL_HANDLE_DBC, (SQLHANDLE) dbc, type);
6419 }
6420 return drvendtran(SQL_HANDLE_ENV, (SQLHANDLE) env, type);
6421 }
6422
6423 /**
6424 * Function not implemented.
6425 */
6426
6427 SQLRETURN SQL_API
SQLCopyDesc(SQLHDESC source,SQLHDESC target)6428 SQLCopyDesc(SQLHDESC source, SQLHDESC target)
6429 {
6430 return SQL_ERROR;
6431 }
6432
6433 #ifndef WINTERFACE
6434 /**
6435 * Translate SQL string.
6436 * @param stmt statement handle
6437 * @param sqlin input string
6438 * @param sqlinLen length of input string
6439 * @param sql output string
6440 * @param sqlMax max space in output string
6441 * @param sqlLen value return for length of output string
6442 * @result ODBC error code
6443 */
6444
6445 SQLRETURN SQL_API
SQLNativeSql(SQLHSTMT stmt,SQLCHAR * sqlin,SQLINTEGER sqlinLen,SQLCHAR * sql,SQLINTEGER sqlMax,SQLINTEGER * sqlLen)6446 SQLNativeSql(SQLHSTMT stmt, SQLCHAR *sqlin, SQLINTEGER sqlinLen,
6447 SQLCHAR *sql, SQLINTEGER sqlMax, SQLINTEGER *sqlLen)
6448 {
6449 int outLen = 0;
6450 SQLRETURN ret = SQL_SUCCESS;
6451
6452 HSTMT_LOCK(stmt);
6453 if (sqlinLen == SQL_NTS) {
6454 sqlinLen = strlen((char *) sqlin);
6455 }
6456 if (sql) {
6457 if (sqlMax > 0) {
6458 strncpy((char *) sql, (char *) sqlin, sqlMax - 1);
6459 sqlin[sqlMax - 1] = '\0';
6460 outLen = min(sqlMax - 1, sqlinLen);
6461 }
6462 } else {
6463 outLen = sqlinLen;
6464 }
6465 if (sqlLen) {
6466 *sqlLen = outLen;
6467 }
6468 if (sql && outLen < sqlinLen) {
6469 setstat((STMT *) stmt, -1, "data right truncated", "01004");
6470 ret = SQL_SUCCESS_WITH_INFO;
6471 }
6472 HSTMT_UNLOCK(stmt);
6473 return ret;
6474 }
6475 #endif
6476
6477 #ifdef WINTERFACE
6478 /**
6479 * Translate SQL string (UNICODE version).
6480 * @param stmt statement handle
6481 * @param sqlin input string
6482 * @param sqlinLen length of input string
6483 * @param sql output string
6484 * @param sqlMax max space in output string
6485 * @param sqlLen value return for length of output string
6486 * @result ODBC error code
6487 */
6488
6489 SQLRETURN SQL_API
SQLNativeSqlW(SQLHSTMT stmt,SQLWCHAR * sqlin,SQLINTEGER sqlinLen,SQLWCHAR * sql,SQLINTEGER sqlMax,SQLINTEGER * sqlLen)6490 SQLNativeSqlW(SQLHSTMT stmt, SQLWCHAR *sqlin, SQLINTEGER sqlinLen,
6491 SQLWCHAR *sql, SQLINTEGER sqlMax, SQLINTEGER *sqlLen)
6492 {
6493 int outLen = 0;
6494 SQLRETURN ret = SQL_SUCCESS;
6495
6496 HSTMT_LOCK(stmt);
6497 if (sqlinLen == SQL_NTS) {
6498 sqlinLen = uc_strlen(sqlin);
6499 }
6500 if (sql) {
6501 if (sqlMax > 0) {
6502 uc_strncpy(sql, sqlin, sqlMax - 1);
6503 sqlin[sqlMax - 1] = 0;
6504 outLen = min(sqlMax - 1, sqlinLen);
6505 }
6506 } else {
6507 outLen = sqlinLen;
6508 }
6509 if (sqlLen) {
6510 *sqlLen = outLen;
6511 }
6512 if (sql && outLen < sqlinLen) {
6513 setstat((STMT *) stmt, -1, "data right truncated", "01004");
6514 ret = SQL_SUCCESS_WITH_INFO;
6515 }
6516 HSTMT_UNLOCK(stmt);
6517 return ret;
6518 }
6519 #endif
6520
6521 /**
6522 * Columns for result set of SQLProcedures().
6523 */
6524
6525 static COL procSpec2[] = {
6526 { "SYSTEM", "PROCEDURE", "PROCEDURE_QUALIFIER", SCOL_VARCHAR, 50 },
6527 { "SYSTEM", "PROCEDURE", "PROCEDURE_OWNER", SCOL_VARCHAR, 50 },
6528 { "SYSTEM", "PROCEDURE", "PROCEDURE_NAME", SCOL_VARCHAR, 255 },
6529 { "SYSTEM", "PROCEDURE", "NUM_INPUT_PARAMS", SQL_SMALLINT, 5 },
6530 { "SYSTEM", "PROCEDURE", "NUM_OUTPUT_PARAMS", SQL_SMALLINT, 5 },
6531 { "SYSTEM", "PROCEDURE", "NUM_RESULT_SETS", SQL_SMALLINT, 5 },
6532 { "SYSTEM", "PROCEDURE", "REMARKS", SCOL_VARCHAR, 255 },
6533 { "SYSTEM", "PROCEDURE", "PROCEDURE_TYPE", SQL_SMALLINT, 5 }
6534 };
6535
6536 static COL procSpec3[] = {
6537 { "SYSTEM", "PROCEDURE", "PROCEDURE_CAT", SCOL_VARCHAR, 50 },
6538 { "SYSTEM", "PROCEDURE", "PROCEDURE_SCHEM", SCOL_VARCHAR, 50 },
6539 { "SYSTEM", "PROCEDURE", "PROCEDURE_NAME", SCOL_VARCHAR, 255 },
6540 { "SYSTEM", "PROCEDURE", "NUM_INPUT_PARAMS", SQL_SMALLINT, 5 },
6541 { "SYSTEM", "PROCEDURE", "NUM_OUTPUT_PARAMS", SQL_SMALLINT, 5 },
6542 { "SYSTEM", "PROCEDURE", "NUM_RESULT_SETS", SQL_SMALLINT, 5 },
6543 { "SYSTEM", "PROCEDURE", "REMARKS", SCOL_VARCHAR, 255 },
6544 { "SYSTEM", "PROCEDURE", "PROCEDURE_TYPE", SQL_SMALLINT, 5 }
6545 };
6546
6547 #ifndef WINTERFACE
6548 /**
6549 * Retrieve information about stored procedures.
6550 * @param stmt statement handle
6551 * @param catalog catalog name/pattern or NULL
6552 * @param catalogLen length of catalog or SQL_NTS
6553 * @param schema schema name/pattern or NULL
6554 * @param schemaLen length of schema or SQL_NTS
6555 * @param proc procedure name/pattern or NULL
6556 * @param procLen length of proc or SQL_NTS
6557 * @result ODBC error code
6558 */
6559
6560 SQLRETURN SQL_API
SQLProcedures(SQLHSTMT stmt,SQLCHAR * catalog,SQLSMALLINT catalogLen,SQLCHAR * schema,SQLSMALLINT schemaLen,SQLCHAR * proc,SQLSMALLINT procLen)6561 SQLProcedures(SQLHSTMT stmt,
6562 SQLCHAR *catalog, SQLSMALLINT catalogLen,
6563 SQLCHAR *schema, SQLSMALLINT schemaLen,
6564 SQLCHAR *proc, SQLSMALLINT procLen)
6565 {
6566 SQLRETURN ret;
6567
6568 HSTMT_LOCK(stmt);
6569 ret = mkresultset(stmt, procSpec2, array_size(procSpec2),
6570 procSpec3, array_size(procSpec3), NULL);
6571 HSTMT_UNLOCK(stmt);
6572 return ret;
6573 }
6574 #endif
6575
6576 #ifdef WINTERFACE
6577 /**
6578 * Retrieve information about stored procedures (UNICODE version).
6579 * @param stmt statement handle
6580 * @param catalog catalog name/pattern or NULL
6581 * @param catalogLen length of catalog or SQL_NTS
6582 * @param schema schema name/pattern or NULL
6583 * @param schemaLen length of schema or SQL_NTS
6584 * @param proc procedure name/pattern or NULL
6585 * @param procLen length of proc or SQL_NTS
6586 * @result ODBC error code
6587 */
6588
6589 SQLRETURN SQL_API
SQLProceduresW(SQLHSTMT stmt,SQLWCHAR * catalog,SQLSMALLINT catalogLen,SQLWCHAR * schema,SQLSMALLINT schemaLen,SQLWCHAR * proc,SQLSMALLINT procLen)6590 SQLProceduresW(SQLHSTMT stmt,
6591 SQLWCHAR *catalog, SQLSMALLINT catalogLen,
6592 SQLWCHAR *schema, SQLSMALLINT schemaLen,
6593 SQLWCHAR *proc, SQLSMALLINT procLen)
6594 {
6595 SQLRETURN ret;
6596
6597 HSTMT_LOCK(stmt);
6598 ret = mkresultset(stmt, procSpec2, array_size(procSpec2),
6599 procSpec3, array_size(procSpec3), NULL);
6600 HSTMT_UNLOCK(stmt);
6601 return ret;
6602 }
6603 #endif
6604
6605 /**
6606 * Columns for result set of SQLProcedureColumns().
6607 */
6608
6609 static COL procColSpec2[] = {
6610 { "SYSTEM", "PROCCOL", "PROCEDURE_QUALIFIER", SCOL_VARCHAR, 50 },
6611 { "SYSTEM", "PROCCOL", "PROCEDURE_OWNER", SCOL_VARCHAR, 50 },
6612 { "SYSTEM", "PROCCOL", "PROCEDURE_NAME", SCOL_VARCHAR, 255 },
6613 { "SYSTEM", "PROCCOL", "COLUMN_NAME", SCOL_VARCHAR, 255 },
6614 { "SYSTEM", "PROCCOL", "COLUMN_TYPE", SQL_SMALLINT, 5 },
6615 { "SYSTEM", "PROCCOL", "DATA_TYPE", SQL_SMALLINT, 5 },
6616 { "SYSTEM", "PROCCOL", "TYPE_NAME", SCOL_VARCHAR, 50 },
6617 { "SYSTEM", "PROCCOL", "PRECISION", SQL_INTEGER, 10 },
6618 { "SYSTEM", "PROCCOL", "LENGTH", SQL_INTEGER, 10 },
6619 { "SYSTEM", "PROCCOL", "SCALE", SQL_SMALLINT, 5 },
6620 { "SYSTEM", "PROCCOL", "RADIX", SQL_SMALLINT, 5 },
6621 { "SYSTEM", "PROCCOL", "NULLABLE", SQL_SMALLINT, 5 },
6622 { "SYSTEM", "PROCCOL", "REMARKS", SCOL_VARCHAR, 50 },
6623 { "SYSTEM", "PROCCOL", "COLUMN_DEF", SCOL_VARCHAR, 50 },
6624 { "SYSTEM", "PROCCOL", "SQL_DATA_TYPE", SQL_SMALLINT, 5 },
6625 { "SYSTEM", "PROCCOL", "SQL_DATETIME_SUB", SQL_SMALLINT, 5 },
6626 { "SYSTEM", "PROCCOL", "CHAR_OCTET_LENGTH", SQL_SMALLINT, 5 },
6627 { "SYSTEM", "PROCCOL", "ORDINAL_POSITION", SQL_SMALLINT, 5 },
6628 { "SYSTEM", "PROCCOL", "IS_NULLABLE", SCOL_VARCHAR, 50 }
6629 };
6630
6631 static COL procColSpec3[] = {
6632 { "SYSTEM", "PROCCOL", "PROCEDURE_CAT", SCOL_VARCHAR, 50 },
6633 { "SYSTEM", "PROCCOL", "PROCEDURE_SCHEM", SCOL_VARCHAR, 50 },
6634 { "SYSTEM", "PROCCOL", "PROCEDURE_NAME", SCOL_VARCHAR, 255 },
6635 { "SYSTEM", "PROCCOL", "COLUMN_NAME", SCOL_VARCHAR, 255 },
6636 { "SYSTEM", "PROCCOL", "COLUMN_TYPE", SQL_SMALLINT, 5 },
6637 { "SYSTEM", "PROCCOL", "DATA_TYPE", SQL_SMALLINT, 5 },
6638 { "SYSTEM", "PROCCOL", "TYPE_NAME", SCOL_VARCHAR, 50 },
6639 { "SYSTEM", "PROCCOL", "COLUMN_SIZE", SQL_INTEGER, 10 },
6640 { "SYSTEM", "PROCCOL", "BUFFER_LENGTH", SQL_INTEGER, 10 },
6641 { "SYSTEM", "PROCCOL", "DECIMAL_DIGITS", SQL_SMALLINT, 5 },
6642 { "SYSTEM", "PROCCOL", "NUM_PREC_RADIX", SQL_SMALLINT, 5 },
6643 { "SYSTEM", "PROCCOL", "NULLABLE", SQL_SMALLINT, 5 },
6644 { "SYSTEM", "PROCCOL", "REMARKS", SCOL_VARCHAR, 50 },
6645 { "SYSTEM", "PROCCOL", "COLUMN_DEF", SCOL_VARCHAR, 50 },
6646 { "SYSTEM", "PROCCOL", "SQL_DATA_TYPE", SQL_SMALLINT, 5 },
6647 { "SYSTEM", "PROCCOL", "SQL_DATETIME_SUB", SQL_SMALLINT, 5 },
6648 { "SYSTEM", "PROCCOL", "CHAR_OCTET_LENGTH", SQL_SMALLINT, 5 },
6649 { "SYSTEM", "PROCCOL", "ORDINAL_POSITION", SQL_SMALLINT, 5 },
6650 { "SYSTEM", "PROCCOL", "IS_NULLABLE", SCOL_VARCHAR, 50 }
6651 };
6652
6653 #ifndef WINTERFACE
6654 /**
6655 * Retrieve information about columns in result set of stored procedures.
6656 * @param stmt statement handle
6657 * @param catalog catalog name/pattern or NULL
6658 * @param catalogLen length of catalog or SQL_NTS
6659 * @param schema schema name/pattern or NULL
6660 * @param schemaLen length of schema or SQL_NTS
6661 * @param proc procedure name/pattern or NULL
6662 * @param procLen length of proc or SQL_NTS
6663 * @param column column name/pattern or NULL
6664 * @param columnLen length of column or SQL_NTS
6665 * @result ODBC error code
6666 */
6667
6668 SQLRETURN SQL_API
SQLProcedureColumns(SQLHSTMT stmt,SQLCHAR * catalog,SQLSMALLINT catalogLen,SQLCHAR * schema,SQLSMALLINT schemaLen,SQLCHAR * proc,SQLSMALLINT procLen,SQLCHAR * column,SQLSMALLINT columnLen)6669 SQLProcedureColumns(SQLHSTMT stmt,
6670 SQLCHAR *catalog, SQLSMALLINT catalogLen,
6671 SQLCHAR *schema, SQLSMALLINT schemaLen,
6672 SQLCHAR *proc, SQLSMALLINT procLen,
6673 SQLCHAR *column, SQLSMALLINT columnLen)
6674 {
6675 SQLRETURN ret;
6676
6677 HSTMT_LOCK(stmt);
6678 ret = mkresultset(stmt, procColSpec2, array_size(procColSpec2),
6679 procColSpec3, array_size(procColSpec3), NULL);
6680 HSTMT_UNLOCK(stmt);
6681 return ret;
6682 }
6683 #endif
6684
6685 #ifdef WINTERFACE
6686 /**
6687 * Retrieve information about columns in result
6688 * set of stored procedures (UNICODE version).
6689 * @param stmt statement handle
6690 * @param catalog catalog name/pattern or NULL
6691 * @param catalogLen length of catalog or SQL_NTS
6692 * @param schema schema name/pattern or NULL
6693 * @param schemaLen length of schema or SQL_NTS
6694 * @param proc procedure name/pattern or NULL
6695 * @param procLen length of proc or SQL_NTS
6696 * @param column column name/pattern or NULL
6697 * @param columnLen length of column or SQL_NTS
6698 * @result ODBC error code
6699 */
6700
6701 SQLRETURN SQL_API
SQLProcedureColumnsW(SQLHSTMT stmt,SQLWCHAR * catalog,SQLSMALLINT catalogLen,SQLWCHAR * schema,SQLSMALLINT schemaLen,SQLWCHAR * proc,SQLSMALLINT procLen,SQLWCHAR * column,SQLSMALLINT columnLen)6702 SQLProcedureColumnsW(SQLHSTMT stmt,
6703 SQLWCHAR *catalog, SQLSMALLINT catalogLen,
6704 SQLWCHAR *schema, SQLSMALLINT schemaLen,
6705 SQLWCHAR *proc, SQLSMALLINT procLen,
6706 SQLWCHAR *column, SQLSMALLINT columnLen)
6707 {
6708 SQLRETURN ret;
6709
6710 HSTMT_LOCK(stmt);
6711 ret = mkresultset(stmt, procColSpec2, array_size(procColSpec2),
6712 procColSpec3, array_size(procColSpec3), NULL);
6713 HSTMT_UNLOCK(stmt);
6714 return ret;
6715 }
6716 #endif
6717
6718 /**
6719 * Get information of HENV.
6720 * @param env environment handle
6721 * @param attr attribute to be retrieved
6722 * @param val output buffer
6723 * @param len length of output buffer
6724 * @param lenp output length
6725 * @result ODBC error code
6726 */
6727
6728 SQLRETURN SQL_API
SQLGetEnvAttr(SQLHENV env,SQLINTEGER attr,SQLPOINTER val,SQLINTEGER len,SQLINTEGER * lenp)6729 SQLGetEnvAttr(SQLHENV env, SQLINTEGER attr, SQLPOINTER val,
6730 SQLINTEGER len, SQLINTEGER *lenp)
6731 {
6732 ENV *e;
6733 SQLRETURN ret = SQL_ERROR;
6734
6735 if (env == SQL_NULL_HENV) {
6736 return SQL_INVALID_HANDLE;
6737 }
6738 e = (ENV *) env;
6739 if (!e || e->magic != ENV_MAGIC) {
6740 return SQL_INVALID_HANDLE;
6741 }
6742 #if defined(_WIN32) || defined(_WIN64)
6743 EnterCriticalSection(&e->cs);
6744 #endif
6745 switch (attr) {
6746 case SQL_ATTR_CONNECTION_POOLING:
6747 if (val) {
6748 *((SQLINTEGER *) val) = e->pool ?
6749 SQL_CP_ONE_PER_DRIVER : SQL_CP_OFF;
6750 }
6751 if (lenp) {
6752 *lenp = sizeof (SQLINTEGER);
6753 }
6754 ret = SQL_SUCCESS;
6755 break;
6756 case SQL_ATTR_CP_MATCH:
6757 *((SQLINTEGER *) val) = SQL_CP_RELAXED_MATCH;
6758 if (lenp) {
6759 *lenp = sizeof (SQLINTEGER);
6760 }
6761 ret = SQL_SUCCESS;
6762 break;
6763 case SQL_ATTR_OUTPUT_NTS:
6764 if (val) {
6765 *((SQLINTEGER *) val) = SQL_TRUE;
6766 }
6767 if (lenp) {
6768 *lenp = sizeof (SQLINTEGER);
6769 }
6770 ret = SQL_SUCCESS;
6771 break;
6772 case SQL_ATTR_ODBC_VERSION:
6773 if (val) {
6774 *((SQLINTEGER *) val) = e->ov3 ? SQL_OV_ODBC3 : SQL_OV_ODBC2;
6775 }
6776 if (lenp) {
6777 *lenp = sizeof (SQLINTEGER);
6778 }
6779 ret = SQL_SUCCESS;
6780 break;
6781 }
6782 #if defined(_WIN32) || defined(_WIN64)
6783 LeaveCriticalSection(&e->cs);
6784 #endif
6785 return ret;
6786 }
6787
6788 /**
6789 * Set information in HENV.
6790 * @param env environment handle
6791 * @param attr attribute to be retrieved
6792 * @param val parameter buffer
6793 * @param len length of parameter
6794 * @result ODBC error code
6795 */
6796
6797 SQLRETURN SQL_API
SQLSetEnvAttr(SQLHENV env,SQLINTEGER attr,SQLPOINTER val,SQLINTEGER len)6798 SQLSetEnvAttr(SQLHENV env, SQLINTEGER attr, SQLPOINTER val, SQLINTEGER len)
6799 {
6800 ENV *e;
6801 SQLRETURN ret = SQL_ERROR;
6802
6803 if (env == SQL_NULL_HENV) {
6804 return SQL_INVALID_HANDLE;
6805 }
6806 e = (ENV *) env;
6807 if (!e || e->magic != ENV_MAGIC) {
6808 return SQL_INVALID_HANDLE;
6809 }
6810 #if defined(_WIN32) || defined(_WIN64)
6811 EnterCriticalSection(&e->cs);
6812 #endif
6813 switch (attr) {
6814 case SQL_ATTR_CONNECTION_POOLING:
6815 if (val == (SQLPOINTER) SQL_CP_ONE_PER_DRIVER) {
6816 e->pool = 1;
6817 ret = SQL_SUCCESS;
6818 } else if (val == (SQLPOINTER) SQL_CP_OFF) {
6819 e->pool = 0;
6820 ret = SQL_SUCCESS;
6821 }
6822 break;
6823 case SQL_ATTR_CP_MATCH:
6824 ret = SQL_SUCCESS;
6825 break;
6826 case SQL_ATTR_OUTPUT_NTS:
6827 if (val == (SQLPOINTER) SQL_TRUE) {
6828 ret = SQL_SUCCESS;
6829 }
6830 break;
6831 case SQL_ATTR_ODBC_VERSION:
6832 if (!val) {
6833 ret = SQL_ERROR;
6834 break;
6835 }
6836 if (val == (SQLPOINTER) SQL_OV_ODBC2) {
6837 e->ov3 = 0;
6838 ret = SQL_SUCCESS;
6839 } else if (val == (SQLPOINTER) SQL_OV_ODBC3) {
6840 e->ov3 = 1;
6841 ret = SQL_SUCCESS;
6842 }
6843 break;
6844 }
6845 #if defined(_WIN32) || defined(_WIN64)
6846 LeaveCriticalSection(&e->cs);
6847 #endif
6848 return ret;
6849 }
6850
6851 /**
6852 * Internal get error message given handle (HENV, HDBC, or HSTMT).
6853 * @param htype handle type
6854 * @param handle HENV, HDBC, or HSTMT
6855 * @param recno
6856 * @param sqlstate output buffer for SQL state
6857 * @param nativeerr output buffer of native error code
6858 * @param msg output buffer for error message
6859 * @param buflen length of output buffer
6860 * @param msglen output length
6861 * @result ODBC error code
6862 */
6863
6864 static SQLRETURN
drvgetdiagrec(SQLSMALLINT htype,SQLHANDLE handle,SQLSMALLINT recno,SQLCHAR * sqlstate,SQLINTEGER * nativeerr,SQLCHAR * msg,SQLSMALLINT buflen,SQLSMALLINT * msglen)6865 drvgetdiagrec(SQLSMALLINT htype, SQLHANDLE handle, SQLSMALLINT recno,
6866 SQLCHAR *sqlstate, SQLINTEGER *nativeerr, SQLCHAR *msg,
6867 SQLSMALLINT buflen, SQLSMALLINT *msglen)
6868 {
6869 DBC *d = NULL;
6870 STMT *s = NULL;
6871 int len, naterr;
6872 char *logmsg, *sqlst;
6873 SQLRETURN ret = SQL_ERROR;
6874
6875 if (handle == SQL_NULL_HANDLE) {
6876 return SQL_INVALID_HANDLE;
6877 }
6878 if (sqlstate) {
6879 sqlstate[0] = '\0';
6880 }
6881 if (msg && buflen > 0) {
6882 msg[0] = '\0';
6883 }
6884 if (msglen) {
6885 *msglen = 0;
6886 }
6887 if (nativeerr) {
6888 *nativeerr = 0;
6889 }
6890 switch (htype) {
6891 case SQL_HANDLE_ENV:
6892 case SQL_HANDLE_DESC:
6893 return SQL_NO_DATA;
6894 case SQL_HANDLE_DBC:
6895 HDBC_LOCK((SQLHDBC) handle);
6896 d = (DBC *) handle;
6897 logmsg = (char *) d->logmsg;
6898 sqlst = d->sqlstate;
6899 naterr = d->naterr;
6900 break;
6901 case SQL_HANDLE_STMT:
6902 HSTMT_LOCK((SQLHSTMT) handle);
6903 s = (STMT *) handle;
6904 logmsg = (char *) s->logmsg;
6905 sqlst = s->sqlstate;
6906 naterr = s->naterr;
6907 break;
6908 default:
6909 return SQL_INVALID_HANDLE;
6910 }
6911 if (buflen < 0) {
6912 ret = SQL_ERROR;
6913 goto done;
6914 }
6915 if (recno > 1) {
6916 ret = SQL_NO_DATA;
6917 goto done;
6918 }
6919 len = strlen(logmsg);
6920 if (len == 0) {
6921 ret = SQL_NO_DATA;
6922 goto done;
6923 }
6924 if (nativeerr) {
6925 *nativeerr = naterr;
6926 }
6927 if (sqlstate) {
6928 strcpy((char *) sqlstate, sqlst);
6929 }
6930 if (msglen) {
6931 *msglen = len;
6932 }
6933 if (len >= buflen) {
6934 if (msg && buflen > 0) {
6935 strncpy((char *) msg, logmsg, buflen);
6936 msg[buflen - 1] = '\0';
6937 logmsg[0] = '\0';
6938 }
6939 } else if (msg) {
6940 strcpy((char *) msg, logmsg);
6941 logmsg[0] = '\0';
6942 }
6943 ret = SQL_SUCCESS;
6944 done:
6945 switch (htype) {
6946 case SQL_HANDLE_DBC:
6947 HDBC_UNLOCK((SQLHDBC) handle);
6948 break;
6949 case SQL_HANDLE_STMT:
6950 HSTMT_UNLOCK((SQLHSTMT) handle);
6951 break;
6952 }
6953 return ret;
6954 }
6955
6956 #if !defined(WINTERFACE) || (defined(HAVE_UNIXODBC) && (HAVE_UNIXODBC))
6957 /**
6958 * Get error message given handle (HENV, HDBC, or HSTMT).
6959 * @param htype handle type
6960 * @param handle HENV, HDBC, or HSTMT
6961 * @param recno
6962 * @param sqlstate output buffer for SQL state
6963 * @param nativeerr output buffer of native error code
6964 * @param msg output buffer for error message
6965 * @param buflen length of output buffer
6966 * @param msglen output length
6967 * @result ODBC error code
6968 */
6969
6970 SQLRETURN SQL_API
SQLGetDiagRec(SQLSMALLINT htype,SQLHANDLE handle,SQLSMALLINT recno,SQLCHAR * sqlstate,SQLINTEGER * nativeerr,SQLCHAR * msg,SQLSMALLINT buflen,SQLSMALLINT * msglen)6971 SQLGetDiagRec(SQLSMALLINT htype, SQLHANDLE handle, SQLSMALLINT recno,
6972 SQLCHAR *sqlstate, SQLINTEGER *nativeerr, SQLCHAR *msg,
6973 SQLSMALLINT buflen, SQLSMALLINT *msglen)
6974 {
6975 return drvgetdiagrec(htype, handle, recno, sqlstate,
6976 nativeerr, msg, buflen, msglen);
6977 }
6978 #endif
6979
6980 #if !defined(HAVE_UNIXODBC) || !(HAVE_UNIXODBC)
6981 #ifdef WINTERFACE
6982 /**
6983 * Get error message given handle (HENV, HDBC, or HSTMT)
6984 * (UNICODE version).
6985 * @param htype handle type
6986 * @param handle HENV, HDBC, or HSTMT
6987 * @param recno
6988 * @param sqlstate output buffer for SQL state
6989 * @param nativeerr output buffer of native error code
6990 * @param msg output buffer for error message
6991 * @param buflen length of output buffer
6992 * @param msglen output length
6993 * @result ODBC error code
6994 */
6995
6996 SQLRETURN SQL_API
SQLGetDiagRecW(SQLSMALLINT htype,SQLHANDLE handle,SQLSMALLINT recno,SQLWCHAR * sqlstate,SQLINTEGER * nativeerr,SQLWCHAR * msg,SQLSMALLINT buflen,SQLSMALLINT * msglen)6997 SQLGetDiagRecW(SQLSMALLINT htype, SQLHANDLE handle, SQLSMALLINT recno,
6998 SQLWCHAR *sqlstate, SQLINTEGER *nativeerr, SQLWCHAR *msg,
6999 SQLSMALLINT buflen, SQLSMALLINT *msglen)
7000 {
7001 char state[16];
7002 SQLSMALLINT len;
7003 SQLRETURN ret;
7004
7005 ret = drvgetdiagrec(htype, handle, recno, (SQLCHAR *) state,
7006 nativeerr, (SQLCHAR *) msg, buflen, &len);
7007 if (ret == SQL_SUCCESS) {
7008 if (sqlstate) {
7009 uc_from_utf_buf((SQLCHAR *) state, -1, sqlstate,
7010 6 * sizeof (SQLWCHAR));
7011 }
7012 if (msg) {
7013 if (len > 0) {
7014 SQLWCHAR *m = NULL;
7015
7016 m = uc_from_utf((unsigned char *) msg, len);
7017 if (m) {
7018 if (buflen) {
7019 buflen /= sizeof (SQLWCHAR);
7020 uc_strncpy(msg, m, buflen);
7021 m[len] = 0;
7022 len = min(buflen, uc_strlen(m));
7023 } else {
7024 len = uc_strlen(m);
7025 }
7026 uc_free(m);
7027 } else {
7028 len = 0;
7029 }
7030 }
7031 if (len <= 0) {
7032 len = 0;
7033 if (buflen > 0) {
7034 msg[0] = 0;
7035 }
7036 }
7037 } else {
7038 /* estimated length !!! */
7039 len *= sizeof (SQLWCHAR);
7040 }
7041 if (msglen) {
7042 *msglen = len;
7043 }
7044 } else if (ret == SQL_NO_DATA) {
7045 if (sqlstate) {
7046 sqlstate[0] = 0;
7047 }
7048 if (msg) {
7049 if (buflen > 0) {
7050 msg[0] = 0;
7051 }
7052 }
7053 if (msglen) {
7054 *msglen = 0;
7055 }
7056 }
7057 return ret;
7058 }
7059 #endif
7060 #endif
7061
7062 /**
7063 * Get error record given handle (HDBC or HSTMT).
7064 * @param htype handle type
7065 * @param handle HDBC or HSTMT
7066 * @param recno diag record number for which info to be retrieved
7067 * @param id diag id for which info to be retrieved
7068 * @param info output buffer for error message
7069 * @param buflen length of output buffer
7070 * @param stringlen output length
7071 * @result ODBC error code
7072 */
7073
7074 static SQLRETURN
drvgetdiagfield(SQLSMALLINT htype,SQLHANDLE handle,SQLSMALLINT recno,SQLSMALLINT id,SQLPOINTER info,SQLSMALLINT buflen,SQLSMALLINT * stringlen)7075 drvgetdiagfield(SQLSMALLINT htype, SQLHANDLE handle, SQLSMALLINT recno,
7076 SQLSMALLINT id, SQLPOINTER info,
7077 SQLSMALLINT buflen, SQLSMALLINT *stringlen)
7078 {
7079 DBC *d = NULL;
7080 STMT *s = NULL;
7081 int len, naterr, strbuf = 1;
7082 char *logmsg, *sqlst, *clrmsg = NULL;
7083 SQLRETURN ret = SQL_ERROR;
7084
7085 if (handle == SQL_NULL_HANDLE) {
7086 return SQL_INVALID_HANDLE;
7087 }
7088 if (stringlen) {
7089 *stringlen = 0;
7090 }
7091 switch (htype) {
7092 case SQL_HANDLE_ENV:
7093 case SQL_HANDLE_DESC:
7094 return SQL_NO_DATA;
7095 case SQL_HANDLE_DBC:
7096 HDBC_LOCK((SQLHDBC) handle);
7097 d = (DBC *) handle;
7098 logmsg = (char *) d->logmsg;
7099 sqlst = d->sqlstate;
7100 naterr = d->naterr;
7101 break;
7102 case SQL_HANDLE_STMT:
7103 HSTMT_LOCK((SQLHSTMT) handle);
7104 s = (STMT *) handle;
7105 d = (DBC *) s->dbc;
7106 logmsg = (char *) s->logmsg;
7107 sqlst = s->sqlstate;
7108 naterr = s->naterr;
7109 break;
7110 default:
7111 return SQL_INVALID_HANDLE;
7112 }
7113 if (buflen < 0) {
7114 switch (buflen) {
7115 case SQL_IS_POINTER:
7116 case SQL_IS_UINTEGER:
7117 case SQL_IS_INTEGER:
7118 case SQL_IS_USMALLINT:
7119 case SQL_IS_SMALLINT:
7120 strbuf = 0;
7121 break;
7122 default:
7123 ret = SQL_ERROR;
7124 goto done;
7125 }
7126 }
7127 if (recno > 1) {
7128 ret = SQL_NO_DATA;
7129 goto done;
7130 }
7131 switch (id) {
7132 case SQL_DIAG_CLASS_ORIGIN:
7133 logmsg = "ISO 9075";
7134 if (sqlst[0] == 'I' && sqlst[1] == 'M') {
7135 logmsg = "ODBC 3.0";
7136 }
7137 break;
7138 case SQL_DIAG_SUBCLASS_ORIGIN:
7139 logmsg = "ISO 9075";
7140 if (sqlst[0] == 'I' && sqlst[1] == 'M') {
7141 logmsg = "ODBC 3.0";
7142 } else if (sqlst[0] == 'H' && sqlst[1] == 'Y') {
7143 logmsg = "ODBC 3.0";
7144 } else if (sqlst[0] == '2' || sqlst[0] == '0' || sqlst[0] == '4') {
7145 logmsg = "ODBC 3.0";
7146 }
7147 break;
7148 case SQL_DIAG_CONNECTION_NAME:
7149 case SQL_DIAG_SERVER_NAME:
7150 logmsg = d->dsn ? d->dsn : "No DSN";
7151 break;
7152 case SQL_DIAG_SQLSTATE:
7153 logmsg = sqlst;
7154 break;
7155 case SQL_DIAG_MESSAGE_TEXT:
7156 if (info) {
7157 clrmsg = logmsg;
7158 }
7159 break;
7160 case SQL_DIAG_NUMBER:
7161 naterr = 1;
7162 /* fall through */
7163 case SQL_DIAG_NATIVE:
7164 len = strlen(logmsg);
7165 if (len == 0) {
7166 ret = SQL_NO_DATA;
7167 goto done;
7168 }
7169 if (info) {
7170 *((SQLINTEGER *) info) = naterr;
7171 }
7172 ret = SQL_SUCCESS;
7173 goto done;
7174 case SQL_DIAG_DYNAMIC_FUNCTION:
7175 logmsg = "";
7176 break;
7177 case SQL_DIAG_CURSOR_ROW_COUNT:
7178 if (htype == SQL_HANDLE_STMT) {
7179 SQLULEN count;
7180
7181 count = (s->isselect == 1 || s->isselect == -1) ? s->nrows : 0;
7182 *((SQLULEN *) info) = count;
7183 ret = SQL_SUCCESS;
7184 }
7185 goto done;
7186 case SQL_DIAG_ROW_COUNT:
7187 if (htype == SQL_HANDLE_STMT) {
7188 SQLULEN count;
7189
7190 count = s->isselect ? 0 : s->nrows;
7191 *((SQLULEN *) info) = count;
7192 ret = SQL_SUCCESS;
7193 }
7194 goto done;
7195 default:
7196 ret = SQL_ERROR;
7197 goto done;
7198 }
7199 if (info && buflen > 0) {
7200 ((char *) info)[0] = '\0';
7201 }
7202 len = strlen(logmsg);
7203 if (len == 0) {
7204 ret = SQL_NO_DATA;
7205 goto done;
7206 }
7207 if (stringlen) {
7208 *stringlen = len;
7209 }
7210 if (strbuf) {
7211 if (len >= buflen) {
7212 if (info && buflen > 0) {
7213 if (stringlen) {
7214 *stringlen = buflen - 1;
7215 }
7216 strncpy((char *) info, logmsg, buflen);
7217 ((char *) info)[buflen - 1] = '\0';
7218 }
7219 } else if (info) {
7220 strcpy((char *) info, logmsg);
7221 }
7222 }
7223 if (clrmsg) {
7224 *clrmsg = '\0';
7225 }
7226 ret = SQL_SUCCESS;
7227 done:
7228 switch (htype) {
7229 case SQL_HANDLE_DBC:
7230 HDBC_UNLOCK((SQLHDBC) handle);
7231 break;
7232 case SQL_HANDLE_STMT:
7233 HSTMT_UNLOCK((SQLHSTMT) handle);
7234 break;
7235 }
7236 return ret;
7237 }
7238
7239 #ifndef WINTERFACE
7240 /**
7241 * Get error record given handle (HDBC or HSTMT).
7242 * @param htype handle type
7243 * @param handle HDBC or HSTMT
7244 * @param recno diag record number for which info to be retrieved
7245 * @param id diag id for which info to be retrieved
7246 * @param info output buffer for error message
7247 * @param buflen length of output buffer
7248 * @param stringlen output length
7249 * @result ODBC error code
7250 */
7251
7252 SQLRETURN SQL_API
SQLGetDiagField(SQLSMALLINT htype,SQLHANDLE handle,SQLSMALLINT recno,SQLSMALLINT id,SQLPOINTER info,SQLSMALLINT buflen,SQLSMALLINT * stringlen)7253 SQLGetDiagField(SQLSMALLINT htype, SQLHANDLE handle, SQLSMALLINT recno,
7254 SQLSMALLINT id, SQLPOINTER info,
7255 SQLSMALLINT buflen, SQLSMALLINT *stringlen)
7256 {
7257 return drvgetdiagfield(htype, handle, recno, id, info, buflen, stringlen);
7258 }
7259 #endif
7260
7261 #ifdef WINTERFACE
7262 /**
7263 * Get error record given handle (HDBC or HSTMT).
7264 * @param htype handle type
7265 * @param handle HDBC or HSTMT
7266 * @param recno diag record number for which info to be retrieved
7267 * @param id diag id for which info to be retrieved
7268 * @param info output buffer for error message
7269 * @param buflen length of output buffer
7270 * @param stringlen output length
7271 * @result ODBC error code
7272 */
7273
7274 SQLRETURN SQL_API
SQLGetDiagFieldW(SQLSMALLINT htype,SQLHANDLE handle,SQLSMALLINT recno,SQLSMALLINT id,SQLPOINTER info,SQLSMALLINT buflen,SQLSMALLINT * stringlen)7275 SQLGetDiagFieldW(SQLSMALLINT htype, SQLHANDLE handle, SQLSMALLINT recno,
7276 SQLSMALLINT id, SQLPOINTER info,
7277 SQLSMALLINT buflen, SQLSMALLINT *stringlen)
7278 {
7279 SQLSMALLINT len;
7280 SQLRETURN ret;
7281
7282 ret = drvgetdiagfield(htype, handle, recno, id, info, buflen, &len);
7283 if (ret == SQL_SUCCESS) {
7284 if (info) {
7285 switch (id) {
7286 case SQL_DIAG_CLASS_ORIGIN:
7287 case SQL_DIAG_SUBCLASS_ORIGIN:
7288 case SQL_DIAG_CONNECTION_NAME:
7289 case SQL_DIAG_SERVER_NAME:
7290 case SQL_DIAG_SQLSTATE:
7291 case SQL_DIAG_MESSAGE_TEXT:
7292 case SQL_DIAG_DYNAMIC_FUNCTION:
7293 if (len > 0) {
7294 SQLWCHAR *m = NULL;
7295
7296 m = uc_from_utf((unsigned char *) info, len);
7297 if (m) {
7298 if (buflen) {
7299 buflen /= sizeof (SQLWCHAR);
7300 uc_strncpy(info, m, buflen);
7301 m[len] = 0;
7302 len = min(buflen, uc_strlen(m));
7303 } else {
7304 len = uc_strlen(m);
7305 }
7306 uc_free(m);
7307 len *= sizeof (SQLWCHAR);
7308 } else {
7309 len = 0;
7310 }
7311 }
7312 if (len <= 0) {
7313 len = 0;
7314 if (buflen > 0) {
7315 ((SQLWCHAR *) info)[0] = 0;
7316 }
7317 }
7318 }
7319 } else {
7320 switch (id) {
7321 case SQL_DIAG_CLASS_ORIGIN:
7322 case SQL_DIAG_SUBCLASS_ORIGIN:
7323 case SQL_DIAG_CONNECTION_NAME:
7324 case SQL_DIAG_SERVER_NAME:
7325 case SQL_DIAG_SQLSTATE:
7326 case SQL_DIAG_MESSAGE_TEXT:
7327 case SQL_DIAG_DYNAMIC_FUNCTION:
7328 len *= sizeof (SQLWCHAR);
7329 break;
7330 }
7331 }
7332 if (stringlen) {
7333 *stringlen = len;
7334 }
7335 }
7336 return ret;
7337 }
7338 #endif
7339
7340 /**
7341 * Internal get option of HSTMT.
7342 * @param stmt statement handle
7343 * @param attr attribute to be retrieved
7344 * @param val output buffer
7345 * @param bufmax length of output buffer
7346 * @param buflen output length
7347 * @result ODBC error code
7348 */
7349
7350 static SQLRETURN
drvgetstmtattr(SQLHSTMT stmt,SQLINTEGER attr,SQLPOINTER val,SQLINTEGER bufmax,SQLINTEGER * buflen)7351 drvgetstmtattr(SQLHSTMT stmt, SQLINTEGER attr, SQLPOINTER val,
7352 SQLINTEGER bufmax, SQLINTEGER *buflen)
7353 {
7354 STMT *s = (STMT *) stmt;
7355 DBC *d = (DBC *) s->dbc;
7356 SQLUINTEGER *uval = (SQLUINTEGER *) val;
7357 SQLINTEGER dummy;
7358 char dummybuf[16];
7359
7360 if (!buflen) {
7361 buflen = &dummy;
7362 }
7363 if (!uval) {
7364 uval = (SQLPOINTER) dummybuf;
7365 }
7366 switch (attr) {
7367 case SQL_QUERY_TIMEOUT:
7368 *uval = 0;
7369 *buflen = sizeof (SQLUINTEGER);
7370 return SQL_SUCCESS;
7371 case SQL_ATTR_CURSOR_TYPE:
7372 *uval = s->curtype;
7373 *buflen = sizeof (SQLUINTEGER);
7374 return SQL_SUCCESS;
7375 case SQL_ATTR_CURSOR_SCROLLABLE:
7376 *uval = (s->curtype != SQL_CURSOR_FORWARD_ONLY) ?
7377 SQL_SCROLLABLE : SQL_NONSCROLLABLE;
7378 *buflen = sizeof (SQLUINTEGER);
7379 return SQL_SUCCESS;
7380 #ifdef SQL_ATTR_CURSOR_SENSITIVITY
7381 case SQL_ATTR_CURSOR_SENSITIVITY:
7382 *uval = SQL_UNSPECIFIED;
7383 *buflen = sizeof (SQLUINTEGER);
7384 return SQL_SUCCESS;
7385 #endif
7386 case SQL_ATTR_ROW_NUMBER:
7387 if (s == d->vm_stmt) {
7388 *uval = (d->vm_rownum < 0) ?
7389 SQL_ROW_NUMBER_UNKNOWN : (d->vm_rownum + 1);
7390 } else {
7391 *uval = (s->rowp < 0) ? SQL_ROW_NUMBER_UNKNOWN : (s->rowp + 1);
7392 }
7393 *buflen = sizeof (SQLUINTEGER);
7394 return SQL_SUCCESS;
7395 case SQL_ATTR_ASYNC_ENABLE:
7396 *uval = SQL_ASYNC_ENABLE_OFF;
7397 *buflen = sizeof (SQLUINTEGER);
7398 return SQL_SUCCESS;
7399 case SQL_CONCURRENCY:
7400 *uval = SQL_CONCUR_LOCK;
7401 *buflen = sizeof (SQLUINTEGER);
7402 return SQL_SUCCESS;
7403 case SQL_ATTR_RETRIEVE_DATA:
7404 *uval = s->retr_data;
7405 *buflen = sizeof (SQLUINTEGER);
7406 return SQL_SUCCESS;
7407 case SQL_ROWSET_SIZE:
7408 case SQL_ATTR_ROW_ARRAY_SIZE:
7409 *uval = s->rowset_size;
7410 *buflen = sizeof (SQLUINTEGER);
7411 return SQL_SUCCESS;
7412 /* Needed for some driver managers, but dummies for now */
7413 case SQL_ATTR_IMP_ROW_DESC:
7414 case SQL_ATTR_APP_ROW_DESC:
7415 case SQL_ATTR_IMP_PARAM_DESC:
7416 case SQL_ATTR_APP_PARAM_DESC:
7417 *((SQLHDESC *) uval) = (SQLHDESC) DEAD_MAGIC;
7418 *buflen = sizeof (SQLHDESC);
7419 return SQL_SUCCESS;
7420 case SQL_ATTR_ROW_STATUS_PTR:
7421 *((SQLUSMALLINT **) uval) = s->row_status;
7422 *buflen = sizeof (SQLUSMALLINT *);
7423 return SQL_SUCCESS;
7424 case SQL_ATTR_ROWS_FETCHED_PTR:
7425 *((SQLULEN **) uval) = s->row_count;
7426 *buflen = sizeof (SQLULEN *);
7427 return SQL_SUCCESS;
7428 case SQL_ATTR_USE_BOOKMARKS: {
7429 STMT *s = (STMT *) stmt;
7430
7431 *(SQLUINTEGER *) uval = s->bkmrk ? SQL_UB_ON : SQL_UB_OFF;
7432 *buflen = sizeof (SQLUINTEGER);
7433 return SQL_SUCCESS;
7434 }
7435 case SQL_ATTR_PARAM_BIND_OFFSET_PTR:
7436 *((SQLULEN **) uval) = s->parm_bind_offs;
7437 *buflen = sizeof (SQLULEN *);
7438 return SQL_SUCCESS;
7439 case SQL_ATTR_PARAM_BIND_TYPE:
7440 *((SQLUINTEGER *) uval) = SQL_PARAM_BIND_BY_COLUMN;
7441 *buflen = sizeof (SQLUINTEGER);
7442 return SQL_SUCCESS;
7443 case SQL_ATTR_PARAM_OPERATION_PTR:
7444 *((SQLUSMALLINT **) uval) = s->parm_oper;
7445 *buflen = sizeof (SQLUSMALLINT *);
7446 return SQL_SUCCESS;
7447 case SQL_ATTR_PARAM_STATUS_PTR:
7448 *((SQLUSMALLINT **) uval) = s->parm_status;
7449 *buflen = sizeof (SQLUSMALLINT *);
7450 return SQL_SUCCESS;
7451 case SQL_ATTR_PARAMS_PROCESSED_PTR:
7452 *((SQLULEN **) uval) = s->parm_proc;
7453 *buflen = sizeof (SQLULEN *);
7454 return SQL_SUCCESS;
7455 case SQL_ATTR_PARAMSET_SIZE:
7456 *((SQLUINTEGER *) uval) = s->paramset_size;
7457 *buflen = sizeof (SQLUINTEGER);
7458 return SQL_SUCCESS;
7459 case SQL_ATTR_ROW_BIND_TYPE:
7460 *(SQLUINTEGER *) uval = s->bind_type;
7461 *buflen = sizeof (SQLUINTEGER);
7462 return SQL_SUCCESS;
7463 case SQL_ATTR_ROW_BIND_OFFSET_PTR:
7464 *((SQLULEN **) uval) = s->bind_offs;
7465 *buflen = sizeof (SQLULEN *);
7466 return SQL_SUCCESS;
7467 case SQL_ATTR_NOSCAN:
7468 *((SQLUINTEGER **) uval) = SQL_NOSCAN_OFF;
7469 *buflen = sizeof (SQLUINTEGER *);
7470 return SQL_SUCCESS;
7471 case SQL_ATTR_MAX_ROWS:
7472 *((SQLULEN *) uval) = 1000000000;
7473 *buflen = sizeof (SQLULEN);
7474 return SQL_SUCCESS;
7475 case SQL_ATTR_MAX_LENGTH:
7476 *((SQLULEN *) uval) = 1000000000;
7477 *buflen = sizeof (SQLULEN);
7478 return SQL_SUCCESS;
7479 }
7480 return drvunimplstmt(stmt);
7481 }
7482
7483 #if (defined(HAVE_UNIXODBC) && (HAVE_UNIXODBC)) || !defined(WINTERFACE)
7484 /**
7485 * Get option of HSTMT.
7486 * @param stmt statement handle
7487 * @param attr attribute to be retrieved
7488 * @param val output buffer
7489 * @param bufmax length of output buffer
7490 * @param buflen output length
7491 * @result ODBC error code
7492 */
7493
7494 SQLRETURN SQL_API
SQLGetStmtAttr(SQLHSTMT stmt,SQLINTEGER attr,SQLPOINTER val,SQLINTEGER bufmax,SQLINTEGER * buflen)7495 SQLGetStmtAttr(SQLHSTMT stmt, SQLINTEGER attr, SQLPOINTER val,
7496 SQLINTEGER bufmax, SQLINTEGER *buflen)
7497 {
7498 SQLRETURN ret;
7499
7500 HSTMT_LOCK(stmt);
7501 ret = drvgetstmtattr(stmt, attr, val, bufmax, buflen);
7502 HSTMT_UNLOCK(stmt);
7503 return ret;
7504 }
7505 #endif
7506
7507 #ifdef WINTERFACE
7508 /**
7509 * Get option of HSTMT (UNICODE version).
7510 * @param stmt statement handle
7511 * @param attr attribute to be retrieved
7512 * @param val output buffer
7513 * @param bufmax length of output buffer
7514 * @param buflen output length
7515 * @result ODBC error code
7516 */
7517
7518 SQLRETURN SQL_API
SQLGetStmtAttrW(SQLHSTMT stmt,SQLINTEGER attr,SQLPOINTER val,SQLINTEGER bufmax,SQLINTEGER * buflen)7519 SQLGetStmtAttrW(SQLHSTMT stmt, SQLINTEGER attr, SQLPOINTER val,
7520 SQLINTEGER bufmax, SQLINTEGER *buflen)
7521 {
7522 SQLRETURN ret;
7523
7524 HSTMT_LOCK(stmt);
7525 ret = drvgetstmtattr(stmt, attr, val, bufmax, buflen);
7526 HSTMT_UNLOCK(stmt);
7527 return ret;
7528 }
7529 #endif
7530
7531 /**
7532 * Internal set option on HSTMT.
7533 * @param stmt statement handle
7534 * @param attr attribute to be set
7535 * @param val input buffer (attribute value)
7536 * @param buflen length of input buffer
7537 * @result ODBC error code
7538 */
7539
7540 static SQLRETURN
drvsetstmtattr(SQLHSTMT stmt,SQLINTEGER attr,SQLPOINTER val,SQLINTEGER buflen)7541 drvsetstmtattr(SQLHSTMT stmt, SQLINTEGER attr, SQLPOINTER val,
7542 SQLINTEGER buflen)
7543 {
7544 STMT *s = (STMT *) stmt;
7545 #if defined(SQL_BIGINT) && defined(__WORDSIZE) && (__WORDSIZE == 64)
7546 SQLBIGINT uval;
7547
7548 uval = (SQLBIGINT) val;
7549 #else
7550 SQLULEN uval;
7551
7552 uval = (SQLULEN) val;
7553 #endif
7554 switch (attr) {
7555 case SQL_ATTR_CURSOR_TYPE:
7556 if (val == (SQLPOINTER) SQL_CURSOR_FORWARD_ONLY) {
7557 s->curtype = SQL_CURSOR_FORWARD_ONLY;
7558 } else {
7559 s->curtype = SQL_CURSOR_STATIC;
7560 }
7561 if (val != (SQLPOINTER) SQL_CURSOR_FORWARD_ONLY &&
7562 val != (SQLPOINTER) SQL_CURSOR_STATIC) {
7563 goto e01s02;
7564 }
7565 return SQL_SUCCESS;
7566 case SQL_ATTR_CURSOR_SCROLLABLE:
7567 if (val == (SQLPOINTER) SQL_NONSCROLLABLE) {
7568 s->curtype = SQL_CURSOR_FORWARD_ONLY;
7569 } else {
7570 s->curtype = SQL_CURSOR_STATIC;
7571 }
7572 return SQL_SUCCESS;
7573 case SQL_ATTR_ASYNC_ENABLE:
7574 if (val != (SQLPOINTER) SQL_ASYNC_ENABLE_OFF) {
7575 e01s02:
7576 setstat(s, -1, "option value changed", "01S02");
7577 return SQL_SUCCESS_WITH_INFO;
7578 }
7579 return SQL_SUCCESS;
7580 case SQL_CONCURRENCY:
7581 if (val != (SQLPOINTER) SQL_CONCUR_LOCK) {
7582 goto e01s02;
7583 }
7584 return SQL_SUCCESS;
7585 #ifdef SQL_ATTR_CURSOR_SENSITIVITY
7586 case SQL_ATTR_CURSOR_SENSITIVITY:
7587 if (val != (SQLPOINTER) SQL_UNSPECIFIED) {
7588 goto e01s02;
7589 }
7590 return SQL_SUCCESS;
7591 #endif
7592 case SQL_ATTR_QUERY_TIMEOUT:
7593 return SQL_SUCCESS;
7594 case SQL_ATTR_RETRIEVE_DATA:
7595 if (val != (SQLPOINTER) SQL_RD_ON &&
7596 val != (SQLPOINTER) SQL_RD_OFF) {
7597 goto e01s02;
7598 }
7599 s->retr_data = uval;
7600 return SQL_SUCCESS;
7601 case SQL_ROWSET_SIZE:
7602 case SQL_ATTR_ROW_ARRAY_SIZE:
7603 if (uval < 1) {
7604 setstat(s, -1, "invalid rowset size", "HY000");
7605 return SQL_ERROR;
7606 } else {
7607 SQLUSMALLINT *rst = &s->row_status1;
7608
7609 if (uval > 1) {
7610 rst = xmalloc(sizeof (SQLUSMALLINT) * uval);
7611 if (!rst) {
7612 return nomem(s);
7613 }
7614 }
7615 if (s->row_status0 != &s->row_status1) {
7616 freep(&s->row_status0);
7617 }
7618 s->row_status0 = rst;
7619 s->rowset_size = uval;
7620 }
7621 return SQL_SUCCESS;
7622 case SQL_ATTR_ROW_STATUS_PTR:
7623 s->row_status = (SQLUSMALLINT *) val;
7624 return SQL_SUCCESS;
7625 case SQL_ATTR_ROWS_FETCHED_PTR:
7626 s->row_count = (SQLULEN *) val;
7627 return SQL_SUCCESS;
7628 case SQL_ATTR_PARAM_BIND_OFFSET_PTR:
7629 s->parm_bind_offs = (SQLULEN *) val;
7630 return SQL_SUCCESS;
7631 case SQL_ATTR_PARAM_BIND_TYPE:
7632 s->parm_bind_type = uval;
7633 return SQL_SUCCESS;
7634 case SQL_ATTR_PARAM_OPERATION_PTR:
7635 s->parm_oper = (SQLUSMALLINT *) val;
7636 return SQL_SUCCESS;
7637 case SQL_ATTR_PARAM_STATUS_PTR:
7638 s->parm_status = (SQLUSMALLINT *) val;
7639 return SQL_SUCCESS;
7640 case SQL_ATTR_PARAMS_PROCESSED_PTR:
7641 s->parm_proc = (SQLULEN *) val;
7642 return SQL_SUCCESS;
7643 case SQL_ATTR_PARAMSET_SIZE:
7644 if ((PTRDIFF_T) val < 1) {
7645 goto e01s02;
7646 }
7647 s->paramset_size = uval;
7648 s->paramset_count = 0;
7649 return SQL_SUCCESS;
7650 case SQL_ATTR_ROW_BIND_TYPE:
7651 s->bind_type = uval;
7652 return SQL_SUCCESS;
7653 case SQL_ATTR_ROW_BIND_OFFSET_PTR:
7654 s->bind_offs = (SQLULEN *) val;
7655 return SQL_SUCCESS;
7656 case SQL_ATTR_USE_BOOKMARKS:
7657 if (val != (SQLPOINTER) SQL_UB_OFF &&
7658 val != (SQLPOINTER) SQL_UB_ON) {
7659 goto e01s02;
7660 }
7661 s->bkmrk = val == (SQLPOINTER) SQL_UB_ON;
7662 return SQL_SUCCESS;
7663 case SQL_ATTR_NOSCAN:
7664 if (val != (SQLPOINTER) SQL_NOSCAN_OFF) {
7665 goto e01s02;
7666 }
7667 return SQL_SUCCESS;
7668 case SQL_ATTR_MAX_ROWS:
7669 case SQL_ATTR_MAX_LENGTH:
7670 if (val != (SQLPOINTER) 1000000000) {
7671 goto e01s02;
7672 }
7673 return SQL_SUCCESS;
7674 }
7675 return drvunimplstmt(stmt);
7676 }
7677
7678 #if (defined(HAVE_UNIXODBC) && HAVE_UNIXODBC) || !defined(WINTERFACE)
7679 /**
7680 * Set option on HSTMT.
7681 * @param stmt statement handle
7682 * @param attr attribute to be set
7683 * @param val input buffer (attribute value)
7684 * @param buflen length of input buffer
7685 * @result ODBC error code
7686 */
7687
7688 SQLRETURN SQL_API
SQLSetStmtAttr(SQLHSTMT stmt,SQLINTEGER attr,SQLPOINTER val,SQLINTEGER buflen)7689 SQLSetStmtAttr(SQLHSTMT stmt, SQLINTEGER attr, SQLPOINTER val,
7690 SQLINTEGER buflen)
7691 {
7692 SQLRETURN ret;
7693
7694 HSTMT_LOCK(stmt);
7695 ret = drvsetstmtattr(stmt, attr, val, buflen);
7696 HSTMT_UNLOCK(stmt);
7697 return ret;
7698 }
7699 #endif
7700
7701 #ifdef WINTERFACE
7702 /**
7703 * Set option on HSTMT (UNICODE version).
7704 * @param stmt statement handle
7705 * @param attr attribute to be set
7706 * @param val input buffer (attribute value)
7707 * @param buflen length of input buffer
7708 * @result ODBC error code
7709 */
7710
7711 SQLRETURN SQL_API
SQLSetStmtAttrW(SQLHSTMT stmt,SQLINTEGER attr,SQLPOINTER val,SQLINTEGER buflen)7712 SQLSetStmtAttrW(SQLHSTMT stmt, SQLINTEGER attr, SQLPOINTER val,
7713 SQLINTEGER buflen)
7714 {
7715 SQLRETURN ret;
7716
7717 HSTMT_LOCK(stmt);
7718 ret = drvsetstmtattr(stmt, attr, val, buflen);
7719 HSTMT_UNLOCK(stmt);
7720 return ret;
7721 }
7722 #endif
7723
7724 /**
7725 * Internal get option of HSTMT.
7726 * @param stmt statement handle
7727 * @param opt option to be retrieved
7728 * @param param output buffer
7729 * @result ODBC error code
7730 */
7731
7732 static SQLRETURN
drvgetstmtoption(SQLHSTMT stmt,SQLUSMALLINT opt,SQLPOINTER param)7733 drvgetstmtoption(SQLHSTMT stmt, SQLUSMALLINT opt, SQLPOINTER param)
7734 {
7735 STMT *s = (STMT *) stmt;
7736 DBC *d = (DBC *) s->dbc;
7737 SQLUINTEGER *ret = (SQLUINTEGER *) param;
7738
7739 switch (opt) {
7740 case SQL_QUERY_TIMEOUT:
7741 *ret = 0;
7742 return SQL_SUCCESS;
7743 case SQL_CURSOR_TYPE:
7744 *ret = s->curtype;
7745 return SQL_SUCCESS;
7746 case SQL_ROW_NUMBER:
7747 if (s == d->vm_stmt) {
7748 *ret = (d->vm_rownum < 0) ?
7749 SQL_ROW_NUMBER_UNKNOWN : (d->vm_rownum + 1);
7750 } else {
7751 *ret = (s->rowp < 0) ? SQL_ROW_NUMBER_UNKNOWN : (s->rowp + 1);
7752 }
7753 return SQL_SUCCESS;
7754 case SQL_ASYNC_ENABLE:
7755 *ret = SQL_ASYNC_ENABLE_OFF;
7756 return SQL_SUCCESS;
7757 case SQL_CONCURRENCY:
7758 *ret = SQL_CONCUR_LOCK;
7759 return SQL_SUCCESS;
7760 case SQL_ATTR_RETRIEVE_DATA:
7761 *ret = s->retr_data;
7762 return SQL_SUCCESS;
7763 case SQL_ROWSET_SIZE:
7764 case SQL_ATTR_ROW_ARRAY_SIZE:
7765 *ret = s->rowset_size;
7766 return SQL_SUCCESS;
7767 case SQL_ATTR_NOSCAN:
7768 *ret = SQL_NOSCAN_OFF;
7769 return SQL_SUCCESS;
7770 case SQL_ATTR_MAX_ROWS:
7771 case SQL_ATTR_MAX_LENGTH:
7772 *ret = 1000000000;
7773 return SQL_SUCCESS;
7774 }
7775 return drvunimplstmt(stmt);
7776 }
7777
7778 /**
7779 * Get option of HSTMT.
7780 * @param stmt statement handle
7781 * @param opt option to be retrieved
7782 * @param param output buffer
7783 * @result ODBC error code
7784 */
7785
7786 SQLRETURN SQL_API
SQLGetStmtOption(SQLHSTMT stmt,SQLUSMALLINT opt,SQLPOINTER param)7787 SQLGetStmtOption(SQLHSTMT stmt, SQLUSMALLINT opt, SQLPOINTER param)
7788 {
7789 SQLRETURN ret;
7790
7791 HSTMT_LOCK(stmt);
7792 ret = drvgetstmtoption(stmt, opt, param);
7793 HSTMT_UNLOCK(stmt);
7794 return ret;
7795 }
7796
7797 #ifdef WINTERFACE
7798 /**
7799 * Get option of HSTMT (UNICODE version).
7800 * @param stmt statement handle
7801 * @param opt option to be retrieved
7802 * @param param output buffer
7803 * @result ODBC error code
7804 */
7805
7806 SQLRETURN SQL_API
SQLGetStmtOptionW(SQLHSTMT stmt,SQLUSMALLINT opt,SQLPOINTER param)7807 SQLGetStmtOptionW(SQLHSTMT stmt, SQLUSMALLINT opt, SQLPOINTER param)
7808 {
7809 SQLRETURN ret;
7810
7811 HSTMT_LOCK(stmt);
7812 ret = drvgetstmtoption(stmt, opt, param);
7813 HSTMT_UNLOCK(stmt);
7814 return ret;
7815 }
7816 #endif
7817
7818 /**
7819 * Internal set option on HSTMT.
7820 * @param stmt statement handle
7821 * @param opt option to be set
7822 * @param param input buffer (option value)
7823 * @result ODBC error code
7824 */
7825
7826 static SQLRETURN
drvsetstmtoption(SQLHSTMT stmt,SQLUSMALLINT opt,SQLUINTEGER param)7827 drvsetstmtoption(SQLHSTMT stmt, SQLUSMALLINT opt, SQLUINTEGER param)
7828 {
7829 STMT *s = (STMT *) stmt;
7830
7831 switch (opt) {
7832 case SQL_CURSOR_TYPE:
7833 if (param == SQL_CURSOR_FORWARD_ONLY) {
7834 s->curtype = param;
7835 } else {
7836 s->curtype = SQL_CURSOR_STATIC;
7837 }
7838 if (param != SQL_CURSOR_FORWARD_ONLY &&
7839 param != SQL_CURSOR_STATIC) {
7840 goto e01s02;
7841 }
7842 return SQL_SUCCESS;
7843 case SQL_ASYNC_ENABLE:
7844 if (param != SQL_ASYNC_ENABLE_OFF) {
7845 goto e01s02;
7846 }
7847 return SQL_SUCCESS;
7848 case SQL_CONCURRENCY:
7849 if (param != SQL_CONCUR_LOCK) {
7850 goto e01s02;
7851 }
7852 return SQL_SUCCESS;
7853 case SQL_QUERY_TIMEOUT:
7854 return SQL_SUCCESS;
7855 case SQL_RETRIEVE_DATA:
7856 if (param != SQL_RD_ON && param != SQL_RD_OFF) {
7857 e01s02:
7858 setstat(s, -1, "option value changed", "01S02");
7859 return SQL_SUCCESS_WITH_INFO;
7860 }
7861 s->retr_data = (int) param;
7862 return SQL_SUCCESS;
7863 case SQL_ROWSET_SIZE:
7864 case SQL_ATTR_ROW_ARRAY_SIZE:
7865 if (param < 1) {
7866 setstat(s, -1, "invalid rowset size", "HY000");
7867 return SQL_ERROR;
7868 } else {
7869 SQLUSMALLINT *rst = &s->row_status1;
7870
7871 if (param > 1) {
7872 rst = xmalloc(sizeof (SQLUSMALLINT) * param);
7873 if (!rst) {
7874 return nomem(s);
7875 }
7876 }
7877 if (s->row_status0 != &s->row_status1) {
7878 freep(&s->row_status0);
7879 }
7880 s->row_status0 = rst;
7881 s->rowset_size = param;
7882 }
7883 return SQL_SUCCESS;
7884 case SQL_ATTR_NOSCAN:
7885 if (param != SQL_NOSCAN_OFF) {
7886 goto e01s02;
7887 }
7888 return SQL_SUCCESS;
7889 case SQL_ATTR_MAX_ROWS:
7890 case SQL_ATTR_MAX_LENGTH:
7891 if (param != 1000000000) {
7892 goto e01s02;
7893 }
7894 return SQL_SUCCESS;
7895 }
7896 return drvunimplstmt(stmt);
7897 }
7898
7899 /**
7900 * Set option on HSTMT.
7901 * @param stmt statement handle
7902 * @param opt option to be set
7903 * @param param input buffer (option value)
7904 * @result ODBC error code
7905 */
7906
7907 SQLRETURN SQL_API
SQLSetStmtOption(SQLHSTMT stmt,SQLUSMALLINT opt,SETSTMTOPTION_LAST_ARG_TYPE param)7908 SQLSetStmtOption(SQLHSTMT stmt, SQLUSMALLINT opt,
7909 SETSTMTOPTION_LAST_ARG_TYPE param)
7910 {
7911 SQLRETURN ret;
7912
7913 HSTMT_LOCK(stmt);
7914 ret = drvsetstmtoption(stmt, opt, (SQLUINTEGER) param);
7915 HSTMT_UNLOCK(stmt);
7916 return ret;
7917 }
7918
7919 #ifdef WINTERFACE
7920 /**
7921 * Set option on HSTMT (UNICODE version).
7922 * @param stmt statement handle
7923 * @param opt option to be set
7924 * @param param input buffer (option value)
7925 * @result ODBC error code
7926 */
7927
7928 SQLRETURN SQL_API
SQLSetStmtOptionW(SQLHSTMT stmt,SQLUSMALLINT opt,SETSTMTOPTION_LAST_ARG_TYPE param)7929 SQLSetStmtOptionW(SQLHSTMT stmt, SQLUSMALLINT opt,
7930 SETSTMTOPTION_LAST_ARG_TYPE param)
7931 {
7932 SQLRETURN ret;
7933
7934 HSTMT_LOCK(stmt);
7935 ret = drvsetstmtoption(stmt, opt, (SQLUINTEGER) param);
7936 HSTMT_UNLOCK(stmt);
7937 return ret;
7938 }
7939 #endif
7940
7941 /*
7942 * Internal set position on result in HSTMT.
7943 * @param stmt statement handle
7944 * @param row row to be positioned
7945 * @param op operation code
7946 * @param lock locking type
7947 * @result ODBC error code
7948 */
7949
7950 static SQLRETURN
drvsetpos(SQLHSTMT stmt,SQLSETPOSIROW row,SQLUSMALLINT op,SQLUSMALLINT lock)7951 drvsetpos(SQLHSTMT stmt, SQLSETPOSIROW row, SQLUSMALLINT op, SQLUSMALLINT lock)
7952 {
7953 STMT *s = (STMT *) stmt;
7954 int rowp;
7955
7956 if (op != SQL_POSITION) {
7957 return drvunimplstmt(stmt);
7958 }
7959 rowp = s->rowp + row - 1;
7960 if (!s->rows || row <= 0 || rowp < -1 || rowp >= s->nrows) {
7961 setstat(s, -1, "row out of range", (*s->ov3) ? "HY107" : "S1107");
7962 return SQL_ERROR;
7963 }
7964 s->rowp = rowp;
7965 return SQL_SUCCESS;
7966 }
7967
7968 /**
7969 * Set position on result in HSTMT.
7970 * @param stmt statement handle
7971 * @param row row to be positioned
7972 * @param op operation code
7973 * @param lock locking type
7974 * @result ODBC error code
7975 */
7976
7977 SQLRETURN SQL_API
SQLSetPos(SQLHSTMT stmt,SQLSETPOSIROW row,SQLUSMALLINT op,SQLUSMALLINT lock)7978 SQLSetPos(SQLHSTMT stmt, SQLSETPOSIROW row, SQLUSMALLINT op, SQLUSMALLINT lock)
7979 {
7980 SQLRETURN ret;
7981
7982 HSTMT_LOCK(stmt);
7983 ret = drvsetpos(stmt, row, op, lock);
7984 HSTMT_UNLOCK(stmt);
7985 return ret;
7986 }
7987
7988 /**
7989 * Function not implemented.
7990 */
7991
7992 SQLRETURN SQL_API
SQLSetScrollOptions(SQLHSTMT stmt,SQLUSMALLINT concur,SQLLEN rowkeyset,SQLUSMALLINT rowset)7993 SQLSetScrollOptions(SQLHSTMT stmt, SQLUSMALLINT concur, SQLLEN rowkeyset,
7994 SQLUSMALLINT rowset)
7995 {
7996 SQLRETURN ret;
7997
7998 HSTMT_LOCK(stmt);
7999 ret = drvunimplstmt(stmt);
8000 HSTMT_UNLOCK(stmt);
8001 return ret;
8002 }
8003
8004 #define strmak(dst, src, max, lenp) { \
8005 int len = strlen(src); \
8006 int cnt = min(len + 1, max); \
8007 strncpy(dst, src, cnt); \
8008 *lenp = (cnt > len) ? len : cnt; \
8009 }
8010
8011 /**
8012 * Internal return information about what this ODBC driver supports.
8013 * @param dbc database connection handle
8014 * @param type type of information to be retrieved
8015 * @param val output buffer
8016 * @param valMax length of output buffer
8017 * @param valLen output length
8018 * @result ODBC error code
8019 */
8020
8021 static SQLRETURN
drvgetinfo(SQLHDBC dbc,SQLUSMALLINT type,SQLPOINTER val,SQLSMALLINT valMax,SQLSMALLINT * valLen)8022 drvgetinfo(SQLHDBC dbc, SQLUSMALLINT type, SQLPOINTER val, SQLSMALLINT valMax,
8023 SQLSMALLINT *valLen)
8024 {
8025 DBC *d;
8026 char dummyc[16];
8027 SQLSMALLINT dummy;
8028 #if defined(_WIN32) || defined(_WIN64)
8029 char pathbuf[301], *drvname;
8030 #else
8031 static char drvname[] =
8032 #ifdef __OS2__
8033 "SQLLODBC.DLL";
8034 #else
8035 "sqliteodbc.so";
8036 #endif
8037 #endif
8038
8039 if (dbc == SQL_NULL_HDBC) {
8040 return SQL_INVALID_HANDLE;
8041 }
8042 d = (DBC *) dbc;
8043 if (valMax) {
8044 valMax--;
8045 }
8046 if (!valLen) {
8047 valLen = &dummy;
8048 }
8049 if (!val) {
8050 val = dummyc;
8051 valMax = sizeof (dummyc) - 1;
8052 }
8053 switch (type) {
8054 case SQL_MAX_USER_NAME_LEN:
8055 *((SQLSMALLINT *) val) = 16;
8056 *valLen = sizeof (SQLSMALLINT);
8057 break;
8058 case SQL_USER_NAME:
8059 strmak(val, "", valMax, valLen);
8060 break;
8061 case SQL_DRIVER_ODBC_VER:
8062 #if 0
8063 strmak(val, (*d->ov3) ? "03.00" : "02.50", valMax, valLen);
8064 #else
8065 strmak(val, "03.00", valMax, valLen);
8066 #endif
8067 break;
8068 case SQL_ACTIVE_CONNECTIONS:
8069 case SQL_ACTIVE_STATEMENTS:
8070 *((SQLSMALLINT *) val) = 0;
8071 *valLen = sizeof (SQLSMALLINT);
8072 break;
8073 #ifdef SQL_ASYNC_MODE
8074 case SQL_ASYNC_MODE:
8075 *((SQLUINTEGER *) val) = SQL_AM_NONE;
8076 *valLen = sizeof (SQLUINTEGER);
8077 break;
8078 #endif
8079 #ifdef SQL_CREATE_TABLE
8080 case SQL_CREATE_TABLE:
8081 *((SQLUINTEGER *) val) = SQL_CT_CREATE_TABLE |
8082 SQL_CT_COLUMN_DEFAULT |
8083 SQL_CT_COLUMN_CONSTRAINT |
8084 SQL_CT_CONSTRAINT_NON_DEFERRABLE;
8085 *valLen = sizeof (SQLUINTEGER);
8086 break;
8087 #endif
8088 #ifdef SQL_CREATE_VIEW
8089 case SQL_CREATE_VIEW:
8090 *((SQLUINTEGER *) val) = SQL_CV_CREATE_VIEW;
8091 *valLen = sizeof (SQLUINTEGER);
8092 break;
8093 #endif
8094 #ifdef SQL_DDL_INDEX
8095 case SQL_DDL_INDEX:
8096 *((SQLUINTEGER *) val) = SQL_DI_CREATE_INDEX | SQL_DI_DROP_INDEX;
8097 *valLen = sizeof (SQLUINTEGER);
8098 break;
8099 #endif
8100 #ifdef SQL_DROP_TABLE
8101 case SQL_DROP_TABLE:
8102 *((SQLUINTEGER *) val) = SQL_DT_DROP_TABLE;
8103 *valLen = sizeof (SQLUINTEGER);
8104 break;
8105 #endif
8106 #ifdef SQL_DROP_VIEW
8107 case SQL_DROP_VIEW:
8108 *((SQLUINTEGER *) val) = SQL_DV_DROP_VIEW;
8109 *valLen = sizeof (SQLUINTEGER);
8110 break;
8111 #endif
8112 #ifdef SQL_INDEX_KEYWORDS
8113 case SQL_INDEX_KEYWORDS:
8114 *((SQLUINTEGER *) val) = SQL_IK_ALL;
8115 *valLen = sizeof (SQLUINTEGER);
8116 break;
8117 #endif
8118 case SQL_DATA_SOURCE_NAME:
8119 strmak(val, d->dsn ? d->dsn : "", valMax, valLen);
8120 break;
8121 case SQL_DRIVER_NAME:
8122 #if defined(_WIN32) || defined(_WIN64)
8123 GetModuleFileName(hModule, pathbuf, sizeof (pathbuf));
8124 drvname = strrchr(pathbuf, '\\');
8125 if (drvname == NULL) {
8126 drvname = strrchr(pathbuf, '/');
8127 }
8128 if (drvname == NULL) {
8129 drvname = pathbuf;
8130 } else {
8131 drvname++;
8132 }
8133 #endif
8134 strmak(val, drvname, valMax, valLen);
8135 break;
8136 case SQL_DRIVER_VER:
8137 strmak(val, DRIVER_VER_INFO, valMax, valLen);
8138 break;
8139 case SQL_FETCH_DIRECTION:
8140 *((SQLUINTEGER *) val) = SQL_FD_FETCH_NEXT | SQL_FD_FETCH_FIRST |
8141 SQL_FD_FETCH_LAST | SQL_FD_FETCH_PRIOR | SQL_FD_FETCH_ABSOLUTE;
8142 *valLen = sizeof (SQLUINTEGER);
8143 break;
8144 case SQL_ODBC_VER:
8145 strmak(val, (*d->ov3) ? "03.00" : "02.50", valMax, valLen);
8146 break;
8147 case SQL_ODBC_SAG_CLI_CONFORMANCE:
8148 *((SQLSMALLINT *) val) = SQL_OSCC_NOT_COMPLIANT;
8149 *valLen = sizeof (SQLSMALLINT);
8150 break;
8151 case SQL_STANDARD_CLI_CONFORMANCE:
8152 *((SQLUINTEGER *) val) = SQL_SCC_XOPEN_CLI_VERSION1;
8153 *valLen = sizeof (SQLUINTEGER);
8154 break;
8155 case SQL_SQL_CONFORMANCE:
8156 *((SQLUINTEGER *) val) = SQL_SC_SQL92_ENTRY;
8157 *valLen = sizeof (SQLUINTEGER);
8158 break;
8159 case SQL_SERVER_NAME:
8160 case SQL_DATABASE_NAME:
8161 strmak(val, d->dbname ? d->dbname : "", valMax, valLen);
8162 break;
8163 case SQL_SEARCH_PATTERN_ESCAPE:
8164 strmak(val, "\\", valMax, valLen);
8165 break;
8166 case SQL_ODBC_SQL_CONFORMANCE:
8167 *((SQLSMALLINT *) val) = SQL_OSC_MINIMUM;
8168 *valLen = sizeof (SQLSMALLINT);
8169 break;
8170 case SQL_ODBC_API_CONFORMANCE:
8171 *((SQLSMALLINT *) val) = SQL_OAC_LEVEL1;
8172 *valLen = sizeof (SQLSMALLINT);
8173 break;
8174 case SQL_DBMS_NAME:
8175 strmak(val, "SQLite", valMax, valLen);
8176 break;
8177 case SQL_DBMS_VER:
8178 strmak(val, SQLITE_VERSION, valMax, valLen);
8179 break;
8180 case SQL_COLUMN_ALIAS:
8181 case SQL_NEED_LONG_DATA_LEN:
8182 strmak(val, "Y", valMax, valLen);
8183 break;
8184 case SQL_ROW_UPDATES:
8185 case SQL_ACCESSIBLE_PROCEDURES:
8186 case SQL_PROCEDURES:
8187 case SQL_EXPRESSIONS_IN_ORDERBY:
8188 case SQL_ODBC_SQL_OPT_IEF:
8189 case SQL_LIKE_ESCAPE_CLAUSE:
8190 case SQL_ORDER_BY_COLUMNS_IN_SELECT:
8191 case SQL_OUTER_JOINS:
8192 case SQL_ACCESSIBLE_TABLES:
8193 case SQL_MULT_RESULT_SETS:
8194 case SQL_MULTIPLE_ACTIVE_TXN:
8195 case SQL_MAX_ROW_SIZE_INCLUDES_LONG:
8196 strmak(val, "N", valMax, valLen);
8197 break;
8198 #ifdef SQL_CATALOG_NAME
8199 case SQL_CATALOG_NAME:
8200 #if defined(_WIN32) || defined(_WIN64)
8201 strmak(val, d->xcelqrx ? "Y": "N", valMax, valLen);
8202 #else
8203 strmak(val, "N", valMax, valLen);
8204 #endif
8205 break;
8206 #endif
8207 case SQL_DATA_SOURCE_READ_ONLY:
8208 strmak(val, "N", valMax, valLen);
8209 break;
8210 #ifdef SQL_OJ_CAPABILITIES
8211 case SQL_OJ_CAPABILITIES:
8212 *((SQLUINTEGER *) val) = 0;
8213 *valLen = sizeof (SQLUINTEGER);
8214 break;
8215 #endif
8216 #ifdef SQL_MAX_IDENTIFIER_LEN
8217 case SQL_MAX_IDENTIFIER_LEN:
8218 *((SQLUSMALLINT *) val) = 255;
8219 *valLen = sizeof (SQLUSMALLINT);
8220 break;
8221 #endif
8222 case SQL_CONCAT_NULL_BEHAVIOR:
8223 *((SQLSMALLINT *) val) = SQL_CB_NULL;
8224 *valLen = sizeof (SQLSMALLINT);
8225 break;
8226 case SQL_CURSOR_COMMIT_BEHAVIOR:
8227 case SQL_CURSOR_ROLLBACK_BEHAVIOR:
8228 *((SQLSMALLINT *) val) = SQL_CB_PRESERVE;
8229 *valLen = sizeof (SQLSMALLINT);
8230 break;
8231 #ifdef SQL_CURSOR_SENSITIVITY
8232 case SQL_CURSOR_SENSITIVITY:
8233 *((SQLUINTEGER *) val) = SQL_UNSPECIFIED;
8234 *valLen = sizeof (SQLUINTEGER);
8235 break;
8236 #endif
8237 case SQL_DEFAULT_TXN_ISOLATION:
8238 *((SQLUINTEGER *) val) = SQL_TXN_SERIALIZABLE;
8239 *valLen = sizeof (SQLUINTEGER);
8240 break;
8241 #ifdef SQL_DESCRIBE_PARAMETER
8242 case SQL_DESCRIBE_PARAMETER:
8243 strmak(val, "Y", valMax, valLen);
8244 break;
8245 #endif
8246 case SQL_TXN_ISOLATION_OPTION:
8247 *((SQLUINTEGER *) val) = SQL_TXN_SERIALIZABLE;
8248 *valLen = sizeof (SQLUINTEGER);
8249 break;
8250 case SQL_IDENTIFIER_CASE:
8251 *((SQLSMALLINT *) val) = SQL_IC_SENSITIVE;
8252 *valLen = sizeof (SQLSMALLINT);
8253 break;
8254 case SQL_IDENTIFIER_QUOTE_CHAR:
8255 strmak(val, "\"", valMax, valLen);
8256 break;
8257 case SQL_MAX_TABLE_NAME_LEN:
8258 case SQL_MAX_COLUMN_NAME_LEN:
8259 *((SQLSMALLINT *) val) = 255;
8260 *valLen = sizeof (SQLSMALLINT);
8261 break;
8262 case SQL_MAX_CURSOR_NAME_LEN:
8263 *((SWORD *) val) = 255;
8264 *valLen = sizeof (SWORD);
8265 break;
8266 case SQL_MAX_PROCEDURE_NAME_LEN:
8267 *((SQLSMALLINT *) val) = 0;
8268 break;
8269 case SQL_MAX_QUALIFIER_NAME_LEN:
8270 case SQL_MAX_OWNER_NAME_LEN:
8271 *((SQLSMALLINT *) val) = 255;
8272 break;
8273 case SQL_OWNER_TERM:
8274 strmak(val, "", valMax, valLen);
8275 break;
8276 case SQL_PROCEDURE_TERM:
8277 strmak(val, "PROCEDURE", valMax, valLen);
8278 break;
8279 case SQL_QUALIFIER_NAME_SEPARATOR:
8280 strmak(val, ".", valMax, valLen);
8281 break;
8282 case SQL_QUALIFIER_TERM:
8283 #if defined(_WIN32) || defined(_WIN64)
8284 strmak(val, d->xcelqrx ? "CATALOG" : "", valMax, valLen);
8285 #else
8286 strmak(val, "", valMax, valLen);
8287 #endif
8288 break;
8289 case SQL_QUALIFIER_USAGE:
8290 #if defined(_WIN32) || defined(_WIN64)
8291 *((SQLUINTEGER *) val) = d->xcelqrx ?
8292 (SQL_CU_DML_STATEMENTS | SQL_CU_INDEX_DEFINITION |
8293 SQL_CU_TABLE_DEFINITION) : 0;
8294 #else
8295 *((SQLUINTEGER *) val) = 0;
8296 #endif
8297 *valLen = sizeof (SQLUINTEGER);
8298 break;
8299 case SQL_SCROLL_CONCURRENCY:
8300 *((SQLUINTEGER *) val) = SQL_SCCO_LOCK;
8301 *valLen = sizeof (SQLUINTEGER);
8302 break;
8303 case SQL_SCROLL_OPTIONS:
8304 *((SQLUINTEGER *) val) = SQL_SO_STATIC | SQL_SO_FORWARD_ONLY;
8305 *valLen = sizeof (SQLUINTEGER);
8306 break;
8307 case SQL_TABLE_TERM:
8308 strmak(val, "TABLE", valMax, valLen);
8309 break;
8310 case SQL_TXN_CAPABLE:
8311 *((SQLSMALLINT *) val) = SQL_TC_ALL;
8312 *valLen = sizeof (SQLSMALLINT);
8313 break;
8314 case SQL_CONVERT_FUNCTIONS:
8315 *((SQLUINTEGER *) val) = 0;
8316 *valLen = sizeof (SQLUINTEGER);
8317 break;
8318 case SQL_SYSTEM_FUNCTIONS:
8319 case SQL_NUMERIC_FUNCTIONS:
8320 case SQL_STRING_FUNCTIONS:
8321 case SQL_TIMEDATE_FUNCTIONS:
8322 *((SQLUINTEGER *) val) = 0;
8323 *valLen = sizeof (SQLUINTEGER);
8324 break;
8325 case SQL_CONVERT_BIGINT:
8326 case SQL_CONVERT_BIT:
8327 case SQL_CONVERT_CHAR:
8328 case SQL_CONVERT_DATE:
8329 case SQL_CONVERT_DECIMAL:
8330 case SQL_CONVERT_DOUBLE:
8331 case SQL_CONVERT_FLOAT:
8332 case SQL_CONVERT_INTEGER:
8333 case SQL_CONVERT_LONGVARCHAR:
8334 case SQL_CONVERT_NUMERIC:
8335 case SQL_CONVERT_REAL:
8336 case SQL_CONVERT_SMALLINT:
8337 case SQL_CONVERT_TIME:
8338 case SQL_CONVERT_TIMESTAMP:
8339 case SQL_CONVERT_TINYINT:
8340 case SQL_CONVERT_VARCHAR:
8341 *((SQLUINTEGER *) val) =
8342 SQL_CVT_CHAR | SQL_CVT_NUMERIC | SQL_CVT_DECIMAL |
8343 SQL_CVT_INTEGER | SQL_CVT_SMALLINT | SQL_CVT_FLOAT | SQL_CVT_REAL |
8344 SQL_CVT_DOUBLE | SQL_CVT_VARCHAR | SQL_CVT_LONGVARCHAR |
8345 SQL_CVT_BIT | SQL_CVT_TINYINT | SQL_CVT_BIGINT |
8346 SQL_CVT_DATE | SQL_CVT_TIME | SQL_CVT_TIMESTAMP;
8347 *valLen = sizeof (SQLUINTEGER);
8348 break;
8349 case SQL_CONVERT_BINARY:
8350 case SQL_CONVERT_VARBINARY:
8351 case SQL_CONVERT_LONGVARBINARY:
8352 *((SQLUINTEGER *) val) = 0;
8353 *valLen = sizeof (SQLUINTEGER);
8354 break;
8355 case SQL_POSITIONED_STATEMENTS:
8356 case SQL_LOCK_TYPES:
8357 *((SQLUINTEGER *) val) = 0;
8358 *valLen = sizeof (SQLUINTEGER);
8359 break;
8360 case SQL_BOOKMARK_PERSISTENCE:
8361 *((SQLUINTEGER *) val) = SQL_BP_SCROLL;
8362 *valLen = sizeof (SQLUINTEGER);
8363 break;
8364 case SQL_UNION:
8365 *((SQLUINTEGER *) val) = SQL_U_UNION | SQL_U_UNION_ALL;
8366 *valLen = sizeof (SQLUINTEGER);
8367 break;
8368 case SQL_OWNER_USAGE:
8369 case SQL_SUBQUERIES:
8370 case SQL_TIMEDATE_ADD_INTERVALS:
8371 case SQL_TIMEDATE_DIFF_INTERVALS:
8372 *((SQLUINTEGER *) val) = 0;
8373 *valLen = sizeof (SQLUINTEGER);
8374 break;
8375 case SQL_QUOTED_IDENTIFIER_CASE:
8376 *((SQLUSMALLINT *) val) = SQL_IC_SENSITIVE;
8377 *valLen = sizeof (SQLUSMALLINT);
8378 break;
8379 case SQL_POS_OPERATIONS:
8380 *((SQLUINTEGER *) val) = 0;
8381 *valLen = sizeof (SQLUINTEGER);
8382 break;
8383 case SQL_ALTER_TABLE:
8384 *((SQLUINTEGER *) val) = 0;
8385 *valLen = sizeof (SQLUINTEGER);
8386 break;
8387 case SQL_CORRELATION_NAME:
8388 *((SQLSMALLINT *) val) = SQL_CN_DIFFERENT;
8389 *valLen = sizeof (SQLSMALLINT);
8390 break;
8391 case SQL_NON_NULLABLE_COLUMNS:
8392 *((SQLSMALLINT *) val) = SQL_NNC_NON_NULL;
8393 *valLen = sizeof (SQLSMALLINT);
8394 break;
8395 case SQL_NULL_COLLATION:
8396 *((SQLSMALLINT *) val) = SQL_NC_START;
8397 *valLen = sizeof(SQLSMALLINT);
8398 break;
8399 case SQL_MAX_COLUMNS_IN_GROUP_BY:
8400 case SQL_MAX_COLUMNS_IN_ORDER_BY:
8401 case SQL_MAX_COLUMNS_IN_SELECT:
8402 case SQL_MAX_COLUMNS_IN_TABLE:
8403 case SQL_MAX_ROW_SIZE:
8404 case SQL_MAX_TABLES_IN_SELECT:
8405 *((SQLSMALLINT *) val) = 0;
8406 *valLen = sizeof (SQLSMALLINT);
8407 break;
8408 case SQL_MAX_BINARY_LITERAL_LEN:
8409 case SQL_MAX_CHAR_LITERAL_LEN:
8410 *((SQLUINTEGER *) val) = 0;
8411 *valLen = sizeof (SQLUINTEGER);
8412 break;
8413 case SQL_MAX_COLUMNS_IN_INDEX:
8414 *((SQLSMALLINT *) val) = 0;
8415 *valLen = sizeof (SQLSMALLINT);
8416 break;
8417 case SQL_MAX_INDEX_SIZE:
8418 *((SQLUINTEGER *) val) = 0;
8419 *valLen = sizeof(SQLUINTEGER);
8420 break;
8421 #ifdef SQL_MAX_IDENTIFIER_LENGTH
8422 case SQL_MAX_IDENTIFIER_LENGTH:
8423 *((SQLUINTEGER *) val) = 255;
8424 *valLen = sizeof (SQLUINTEGER);
8425 break;
8426 #endif
8427 case SQL_MAX_STATEMENT_LEN:
8428 *((SQLUINTEGER *) val) = 16384;
8429 *valLen = sizeof (SQLUINTEGER);
8430 break;
8431 case SQL_QUALIFIER_LOCATION:
8432 *((SQLSMALLINT *) val) = SQL_QL_START;
8433 *valLen = sizeof (SQLSMALLINT);
8434 break;
8435 case SQL_GETDATA_EXTENSIONS:
8436 *((SQLUINTEGER *) val) =
8437 SQL_GD_ANY_COLUMN | SQL_GD_ANY_ORDER | SQL_GD_BOUND;
8438 *valLen = sizeof (SQLUINTEGER);
8439 break;
8440 case SQL_STATIC_SENSITIVITY:
8441 *((SQLUINTEGER *) val) = 0;
8442 *valLen = sizeof (SQLUINTEGER);
8443 break;
8444 case SQL_FILE_USAGE:
8445 #if defined(_WIN32) || defined(_WIN64)
8446 *((SQLSMALLINT *) val) =
8447 d->xcelqrx ? SQL_FILE_CATALOG : SQL_FILE_NOT_SUPPORTED;
8448 #else
8449 *((SQLSMALLINT *) val) = SQL_FILE_NOT_SUPPORTED;
8450 #endif
8451 *valLen = sizeof (SQLSMALLINT);
8452 break;
8453 case SQL_GROUP_BY:
8454 *((SQLSMALLINT *) val) = SQL_GB_GROUP_BY_EQUALS_SELECT;
8455 *valLen = sizeof (SQLSMALLINT);
8456 break;
8457 case SQL_KEYWORDS:
8458 strmak(val, "CREATE,SELECT,DROP,DELETE,UPDATE,INSERT,"
8459 "INTO,VALUES,TABLE,INDEX,FROM,SET,WHERE,AND,CURRENT,OF",
8460 valMax, valLen);
8461 break;
8462 case SQL_SPECIAL_CHARACTERS:
8463 #ifdef SQL_COLLATION_SEQ
8464 case SQL_COLLATION_SEQ:
8465 #endif
8466 strmak(val, "", valMax, valLen);
8467 break;
8468 case SQL_BATCH_SUPPORT:
8469 case SQL_BATCH_ROW_COUNT:
8470 case SQL_PARAM_ARRAY_ROW_COUNTS:
8471 *((SQLUINTEGER *) val) = 0;
8472 *valLen = sizeof (SQLUINTEGER);
8473 break;
8474 case SQL_FORWARD_ONLY_CURSOR_ATTRIBUTES1:
8475 *((SQLUINTEGER *) val) = SQL_CA1_NEXT | SQL_CA1_BOOKMARK;
8476 *valLen = sizeof (SQLUINTEGER);
8477 break;
8478 case SQL_STATIC_CURSOR_ATTRIBUTES1:
8479 *((SQLUINTEGER *) val) = SQL_CA1_NEXT | SQL_CA1_ABSOLUTE |
8480 SQL_CA1_RELATIVE | SQL_CA1_BOOKMARK;
8481 *valLen = sizeof (SQLUINTEGER);
8482 break;
8483 case SQL_FORWARD_ONLY_CURSOR_ATTRIBUTES2:
8484 case SQL_STATIC_CURSOR_ATTRIBUTES2:
8485 *((SQLUINTEGER *) val) = SQL_CA2_READ_ONLY_CONCURRENCY |
8486 SQL_CA2_LOCK_CONCURRENCY;
8487 *valLen = sizeof (SQLUINTEGER);
8488 break;
8489 case SQL_KEYSET_CURSOR_ATTRIBUTES1:
8490 case SQL_KEYSET_CURSOR_ATTRIBUTES2:
8491 case SQL_DYNAMIC_CURSOR_ATTRIBUTES1:
8492 case SQL_DYNAMIC_CURSOR_ATTRIBUTES2:
8493 *((SQLUINTEGER *) val) = 0;
8494 *valLen = sizeof (SQLUINTEGER);
8495 break;
8496 case SQL_ODBC_INTERFACE_CONFORMANCE:
8497 *((SQLUINTEGER *) val) = SQL_OIC_CORE;
8498 *valLen = sizeof (SQLUINTEGER);
8499 break;
8500 default:
8501 setstatd(d, -1, "unsupported info option %d",
8502 (*d->ov3) ? "HYC00" : "S1C00", type);
8503 return SQL_ERROR;
8504 }
8505 return SQL_SUCCESS;
8506 }
8507
8508 #if (defined(HAVE_UNIXODBC) && (HAVE_UNIXODBC)) || !defined(WINTERFACE)
8509 /**
8510 * Return information about what this ODBC driver supports.
8511 * @param dbc database connection handle
8512 * @param type type of information to be retrieved
8513 * @param val output buffer
8514 * @param valMax length of output buffer
8515 * @param valLen output length
8516 * @result ODBC error code
8517 */
8518
8519 SQLRETURN SQL_API
SQLGetInfo(SQLHDBC dbc,SQLUSMALLINT type,SQLPOINTER val,SQLSMALLINT valMax,SQLSMALLINT * valLen)8520 SQLGetInfo(SQLHDBC dbc, SQLUSMALLINT type, SQLPOINTER val, SQLSMALLINT valMax,
8521 SQLSMALLINT *valLen)
8522 {
8523 SQLRETURN ret;
8524
8525 HDBC_LOCK(dbc);
8526 ret = drvgetinfo(dbc, type, val, valMax, valLen);
8527 HDBC_UNLOCK(dbc);
8528 return ret;
8529 }
8530 #endif
8531
8532 #ifdef WINTERFACE
8533 /**
8534 * Return information about what this ODBC driver supports.
8535 * @param dbc database connection handle
8536 * @param type type of information to be retrieved
8537 * @param val output buffer
8538 * @param valMax length of output buffer
8539 * @param valLen output length
8540 * @result ODBC error code
8541 */
8542
8543 SQLRETURN SQL_API
SQLGetInfoW(SQLHDBC dbc,SQLUSMALLINT type,SQLPOINTER val,SQLSMALLINT valMax,SQLSMALLINT * valLen)8544 SQLGetInfoW(SQLHDBC dbc, SQLUSMALLINT type, SQLPOINTER val, SQLSMALLINT valMax,
8545 SQLSMALLINT *valLen)
8546 {
8547 SQLRETURN ret;
8548 SQLSMALLINT len = 0;
8549
8550 HDBC_LOCK(dbc);
8551 ret = drvgetinfo(dbc, type, val, valMax, &len);
8552 HDBC_UNLOCK(dbc);
8553 if (ret == SQL_SUCCESS) {
8554 SQLWCHAR *v = NULL;
8555
8556 switch (type) {
8557 case SQL_USER_NAME:
8558 case SQL_DRIVER_ODBC_VER:
8559 case SQL_DATA_SOURCE_NAME:
8560 case SQL_DRIVER_NAME:
8561 case SQL_DRIVER_VER:
8562 case SQL_ODBC_VER:
8563 case SQL_SERVER_NAME:
8564 case SQL_DATABASE_NAME:
8565 case SQL_SEARCH_PATTERN_ESCAPE:
8566 case SQL_DBMS_NAME:
8567 case SQL_DBMS_VER:
8568 case SQL_NEED_LONG_DATA_LEN:
8569 case SQL_ROW_UPDATES:
8570 case SQL_ACCESSIBLE_PROCEDURES:
8571 case SQL_PROCEDURES:
8572 case SQL_EXPRESSIONS_IN_ORDERBY:
8573 case SQL_ODBC_SQL_OPT_IEF:
8574 case SQL_LIKE_ESCAPE_CLAUSE:
8575 case SQL_ORDER_BY_COLUMNS_IN_SELECT:
8576 case SQL_OUTER_JOINS:
8577 case SQL_COLUMN_ALIAS:
8578 case SQL_ACCESSIBLE_TABLES:
8579 case SQL_MULT_RESULT_SETS:
8580 case SQL_MULTIPLE_ACTIVE_TXN:
8581 case SQL_MAX_ROW_SIZE_INCLUDES_LONG:
8582 case SQL_DATA_SOURCE_READ_ONLY:
8583 #ifdef SQL_DESCRIBE_PARAMETER
8584 case SQL_DESCRIBE_PARAMETER:
8585 #endif
8586 case SQL_IDENTIFIER_QUOTE_CHAR:
8587 case SQL_OWNER_TERM:
8588 case SQL_PROCEDURE_TERM:
8589 case SQL_QUALIFIER_NAME_SEPARATOR:
8590 case SQL_QUALIFIER_TERM:
8591 case SQL_TABLE_TERM:
8592 case SQL_KEYWORDS:
8593 case SQL_SPECIAL_CHARACTERS:
8594 #ifdef SQL_CATALOG_NAME
8595 case SQL_CATALOG_NAME:
8596 #endif
8597 #ifdef SQL_COLLATION_SEQ
8598 case SQL_COLLATION_SEQ:
8599 #endif
8600 if (val) {
8601 if (len > 0) {
8602 v = uc_from_utf((SQLCHAR *) val, len);
8603 if (v) {
8604 int vmax = valMax / sizeof (SQLWCHAR);
8605
8606 uc_strncpy(val, v, vmax);
8607 if (len < vmax) {
8608 len = min(vmax, uc_strlen(v));
8609 v[len] = 0;
8610 } else {
8611 len = vmax;
8612 }
8613 uc_free(v);
8614 len *= sizeof (SQLWCHAR);
8615 } else {
8616 len = 0;
8617 }
8618 }
8619 if (len <= 0) {
8620 len = 0;
8621 if (valMax >= sizeof (SQLWCHAR)) {
8622 *((SQLWCHAR *)val) = 0;
8623 }
8624 }
8625 } else {
8626 len *= sizeof (SQLWCHAR);
8627 }
8628 break;
8629 }
8630 if (valLen) {
8631 *valLen = len;
8632 }
8633 }
8634 return ret;
8635 }
8636 #endif
8637
8638 /**
8639 * Return information about supported ODBC API functions.
8640 * @param dbc database connection handle
8641 * @param func function code to be retrieved
8642 * @param flags output indicator
8643 * @result ODBC error code
8644 */
8645
8646 SQLRETURN SQL_API
SQLGetFunctions(SQLHDBC dbc,SQLUSMALLINT func,SQLUSMALLINT * flags)8647 SQLGetFunctions(SQLHDBC dbc, SQLUSMALLINT func,
8648 SQLUSMALLINT *flags)
8649 {
8650 int i;
8651 SQLUSMALLINT exists[100];
8652
8653 if (dbc == SQL_NULL_HDBC) {
8654 return SQL_INVALID_HANDLE;
8655 }
8656 for (i = 0; i < array_size(exists); i++) {
8657 exists[i] = SQL_FALSE;
8658 }
8659 exists[SQL_API_SQLALLOCCONNECT] = SQL_TRUE;
8660 exists[SQL_API_SQLFETCH] = SQL_TRUE;
8661 exists[SQL_API_SQLALLOCENV] = SQL_TRUE;
8662 exists[SQL_API_SQLFREECONNECT] = SQL_TRUE;
8663 exists[SQL_API_SQLALLOCSTMT] = SQL_TRUE;
8664 exists[SQL_API_SQLFREEENV] = SQL_TRUE;
8665 exists[SQL_API_SQLBINDCOL] = SQL_TRUE;
8666 exists[SQL_API_SQLFREESTMT] = SQL_TRUE;
8667 exists[SQL_API_SQLCANCEL] = SQL_TRUE;
8668 exists[SQL_API_SQLGETCURSORNAME] = SQL_TRUE;
8669 exists[SQL_API_SQLCOLATTRIBUTES] = SQL_TRUE;
8670 exists[SQL_API_SQLNUMRESULTCOLS] = SQL_TRUE;
8671 exists[SQL_API_SQLCONNECT] = SQL_TRUE;
8672 exists[SQL_API_SQLPREPARE] = SQL_TRUE;
8673 exists[SQL_API_SQLDESCRIBECOL] = SQL_TRUE;
8674 exists[SQL_API_SQLROWCOUNT] = SQL_TRUE;
8675 exists[SQL_API_SQLDISCONNECT] = SQL_TRUE;
8676 exists[SQL_API_SQLSETCURSORNAME] = SQL_TRUE;
8677 exists[SQL_API_SQLERROR] = SQL_TRUE;
8678 exists[SQL_API_SQLSETPARAM] = SQL_TRUE;
8679 exists[SQL_API_SQLEXECDIRECT] = SQL_TRUE;
8680 exists[SQL_API_SQLTRANSACT] = SQL_TRUE;
8681 exists[SQL_API_SQLEXECUTE] = SQL_TRUE;
8682 exists[SQL_API_SQLBINDPARAMETER] = SQL_TRUE;
8683 exists[SQL_API_SQLGETTYPEINFO] = SQL_TRUE;
8684 exists[SQL_API_SQLCOLUMNS] = SQL_TRUE;
8685 exists[SQL_API_SQLPARAMDATA] = SQL_TRUE;
8686 exists[SQL_API_SQLDRIVERCONNECT] = SQL_TRUE;
8687 exists[SQL_API_SQLPUTDATA] = SQL_TRUE;
8688 exists[SQL_API_SQLGETCONNECTOPTION] = SQL_TRUE;
8689 exists[SQL_API_SQLSETCONNECTOPTION] = SQL_TRUE;
8690 exists[SQL_API_SQLGETDATA] = SQL_TRUE;
8691 exists[SQL_API_SQLSETSTMTOPTION] = SQL_TRUE;
8692 exists[SQL_API_SQLGETFUNCTIONS] = SQL_TRUE;
8693 exists[SQL_API_SQLSPECIALCOLUMNS] = SQL_TRUE;
8694 exists[SQL_API_SQLGETINFO] = SQL_TRUE;
8695 exists[SQL_API_SQLSTATISTICS] = SQL_TRUE;
8696 exists[SQL_API_SQLGETSTMTOPTION] = SQL_TRUE;
8697 exists[SQL_API_SQLTABLES] = SQL_TRUE;
8698 exists[SQL_API_SQLBROWSECONNECT] = SQL_FALSE;
8699 exists[SQL_API_SQLNUMPARAMS] = SQL_TRUE;
8700 exists[SQL_API_SQLCOLUMNPRIVILEGES] = SQL_FALSE;
8701 exists[SQL_API_SQLPARAMOPTIONS] = SQL_FALSE;
8702 exists[SQL_API_SQLDATASOURCES] = SQL_TRUE;
8703 exists[SQL_API_SQLPRIMARYKEYS] = SQL_TRUE;
8704 exists[SQL_API_SQLDESCRIBEPARAM] = SQL_TRUE;
8705 exists[SQL_API_SQLPROCEDURECOLUMNS] = SQL_TRUE;
8706 exists[SQL_API_SQLDRIVERS] = SQL_FALSE;
8707 exists[SQL_API_SQLPROCEDURES] = SQL_TRUE;
8708 exists[SQL_API_SQLEXTENDEDFETCH] = SQL_TRUE;
8709 exists[SQL_API_SQLSETPOS] = SQL_TRUE;
8710 exists[SQL_API_SQLFOREIGNKEYS] = SQL_TRUE;
8711 exists[SQL_API_SQLSETSCROLLOPTIONS] = SQL_TRUE;
8712 exists[SQL_API_SQLMORERESULTS] = SQL_TRUE;
8713 exists[SQL_API_SQLTABLEPRIVILEGES] = SQL_TRUE;
8714 exists[SQL_API_SQLNATIVESQL] = SQL_TRUE;
8715 if (func == SQL_API_ALL_FUNCTIONS) {
8716 memcpy(flags, exists, sizeof (exists));
8717 } else if (func == SQL_API_ODBC3_ALL_FUNCTIONS) {
8718 int i;
8719 #define SET_EXISTS(x) \
8720 flags[(x) >> 4] |= (1 << ((x) & 0xF))
8721 #define CLR_EXISTS(x) \
8722 flags[(x) >> 4] &= ~(1 << ((x) & 0xF))
8723
8724 memset(flags, 0,
8725 sizeof (SQLUSMALLINT) * SQL_API_ODBC3_ALL_FUNCTIONS_SIZE);
8726 for (i = 0; i < array_size(exists); i++) {
8727 if (exists[i]) {
8728 flags[i >> 4] |= (1 << (i & 0xF));
8729 }
8730 }
8731 SET_EXISTS(SQL_API_SQLALLOCHANDLE);
8732 SET_EXISTS(SQL_API_SQLFREEHANDLE);
8733 SET_EXISTS(SQL_API_SQLGETSTMTATTR);
8734 SET_EXISTS(SQL_API_SQLSETSTMTATTR);
8735 SET_EXISTS(SQL_API_SQLGETCONNECTATTR);
8736 SET_EXISTS(SQL_API_SQLSETCONNECTATTR);
8737 SET_EXISTS(SQL_API_SQLGETENVATTR);
8738 SET_EXISTS(SQL_API_SQLSETENVATTR);
8739 SET_EXISTS(SQL_API_SQLCLOSECURSOR);
8740 SET_EXISTS(SQL_API_SQLBINDPARAM);
8741 #if !defined(HAVE_UNIXODBC) || !(HAVE_UNIXODBC)
8742 /*
8743 * Some unixODBC versions have problems with
8744 * SQLError() vs. SQLGetDiagRec() with loss
8745 * of error/warning messages.
8746 */
8747 SET_EXISTS(SQL_API_SQLGETDIAGREC);
8748 #endif
8749 SET_EXISTS(SQL_API_SQLFETCHSCROLL);
8750 SET_EXISTS(SQL_API_SQLENDTRAN);
8751 } else {
8752 if (func < array_size(exists)) {
8753 *flags = exists[func];
8754 } else {
8755 switch (func) {
8756 case SQL_API_SQLALLOCHANDLE:
8757 case SQL_API_SQLFREEHANDLE:
8758 case SQL_API_SQLGETSTMTATTR:
8759 case SQL_API_SQLSETSTMTATTR:
8760 case SQL_API_SQLGETCONNECTATTR:
8761 case SQL_API_SQLSETCONNECTATTR:
8762 case SQL_API_SQLGETENVATTR:
8763 case SQL_API_SQLSETENVATTR:
8764 case SQL_API_SQLCLOSECURSOR:
8765 case SQL_API_SQLBINDPARAM:
8766 #if !defined(HAVE_UNIXODBC) || !(HAVE_UNIXODBC)
8767 /*
8768 * Some unixODBC versions have problems with
8769 * SQLError() vs. SQLGetDiagRec() with loss
8770 * of error/warning messages.
8771 */
8772 case SQL_API_SQLGETDIAGREC:
8773 #endif
8774 case SQL_API_SQLFETCHSCROLL:
8775 case SQL_API_SQLENDTRAN:
8776 *flags = SQL_TRUE;
8777 break;
8778 default:
8779 *flags = SQL_FALSE;
8780 }
8781 }
8782 }
8783 return SQL_SUCCESS;
8784 }
8785
8786 /**
8787 * Internal allocate HENV.
8788 * @param env pointer to environment handle
8789 * @result ODBC error code
8790 */
8791
8792 static SQLRETURN
drvallocenv(SQLHENV * env)8793 drvallocenv(SQLHENV *env)
8794 {
8795 ENV *e;
8796
8797 if (env == NULL) {
8798 return SQL_INVALID_HANDLE;
8799 }
8800 e = (ENV *) xmalloc(sizeof (ENV));
8801 if (e == NULL) {
8802 *env = SQL_NULL_HENV;
8803 return SQL_ERROR;
8804 }
8805 e->magic = ENV_MAGIC;
8806 e->ov3 = 0;
8807 e->pool = 0;
8808 #if defined(_WIN32) || defined(_WIN64)
8809 InitializeCriticalSection(&e->cs);
8810 #endif
8811 e->dbcs = NULL;
8812 *env = (SQLHENV) e;
8813 return SQL_SUCCESS;
8814 }
8815
8816 /**
8817 * Allocate HENV.
8818 * @param env pointer to environment handle
8819 * @result ODBC error code
8820 */
8821
8822 SQLRETURN SQL_API
SQLAllocEnv(SQLHENV * env)8823 SQLAllocEnv(SQLHENV *env)
8824 {
8825 return drvallocenv(env);
8826 }
8827
8828 /**
8829 * Internal free HENV.
8830 * @param env environment handle
8831 * @result ODBC error code
8832 */
8833
8834 static SQLRETURN
drvfreeenv(SQLHENV env)8835 drvfreeenv(SQLHENV env)
8836 {
8837 ENV *e;
8838
8839 if (env == SQL_NULL_HENV) {
8840 return SQL_INVALID_HANDLE;
8841 }
8842 e = (ENV *) env;
8843 if (e->magic != ENV_MAGIC) {
8844 return SQL_SUCCESS;
8845 }
8846 #if defined(_WIN32) || defined(_WIN64)
8847 EnterCriticalSection(&e->cs);
8848 #endif
8849 if (e->dbcs) {
8850 #if defined(_WIN32) || defined(_WIN64)
8851 LeaveCriticalSection(&e->cs);
8852 #endif
8853 return SQL_ERROR;
8854 }
8855 e->magic = DEAD_MAGIC;
8856 #if defined(_WIN32) || defined(_WIN64)
8857 LeaveCriticalSection(&e->cs);
8858 DeleteCriticalSection(&e->cs);
8859 #endif
8860 xfree(e);
8861 return SQL_SUCCESS;
8862 }
8863
8864 /**
8865 * Free HENV.
8866 * @param env environment handle
8867 * @result ODBC error code
8868 */
8869
8870 SQLRETURN SQL_API
SQLFreeEnv(SQLHENV env)8871 SQLFreeEnv(SQLHENV env)
8872 {
8873 return drvfreeenv(env);
8874 }
8875
8876 /**
8877 * Internal allocate HDBC.
8878 * @param env environment handle
8879 * @param dbc pointer to database connection handle
8880 * @result ODBC error code
8881 */
8882
8883 static SQLRETURN
drvallocconnect(SQLHENV env,SQLHDBC * dbc)8884 drvallocconnect(SQLHENV env, SQLHDBC *dbc)
8885 {
8886 DBC *d;
8887 ENV *e;
8888 const char *verstr;
8889 int maj = 0, min = 0, lev = 0;
8890
8891 if (dbc == NULL) {
8892 return SQL_ERROR;
8893 }
8894 d = (DBC *) xmalloc(sizeof (DBC));
8895 if (d == NULL) {
8896 *dbc = SQL_NULL_HDBC;
8897 return SQL_ERROR;
8898 }
8899 memset(d, 0, sizeof (DBC));
8900 d->curtype = SQL_CURSOR_STATIC;
8901 #if (HAVE_LIBVERSION)
8902 verstr = sqlite_libversion();
8903 #else
8904 verstr = sqlite_version;
8905 #endif
8906 sscanf(verstr, "%d.%d.%d", &maj, &min, &lev);
8907 d->version = verinfo(maj & 0xFF, min & 0xFF, lev & 0xFF);
8908 if (d->version < verinfo(2, 8, 0)) {
8909 xfree(d);
8910 return SQL_ERROR;
8911 }
8912 d->ov3 = &d->ov3val;
8913 e = (ENV *) env;
8914 #if defined(_WIN32) || defined(_WIN64)
8915 if (e->magic == ENV_MAGIC) {
8916 EnterCriticalSection(&e->cs);
8917 }
8918 #endif
8919 if (e->magic == ENV_MAGIC) {
8920 DBC *n, *p;
8921
8922 d->env = e;
8923 d->ov3 = &e->ov3;
8924 p = NULL;
8925 n = e->dbcs;
8926 while (n) {
8927 p = n;
8928 n = n->next;
8929 }
8930 if (p) {
8931 p->next = d;
8932 } else {
8933 e->dbcs = d;
8934 }
8935 }
8936 #if defined(_WIN32) || defined(_WIN64)
8937 InitializeCriticalSection(&d->cs);
8938 d->owner = 0;
8939 if (e->magic == ENV_MAGIC) {
8940 LeaveCriticalSection(&e->cs);
8941 }
8942 #endif
8943 d->autocommit = 1;
8944 d->magic = DBC_MAGIC;
8945 *dbc = (SQLHDBC) d;
8946 drvgetgpps(d);
8947 return SQL_SUCCESS;
8948 }
8949
8950 /**
8951 * Allocate HDBC.
8952 * @param env environment handle
8953 * @param dbc pointer to database connection handle
8954 * @result ODBC error code
8955 */
8956
8957 SQLRETURN SQL_API
SQLAllocConnect(SQLHENV env,SQLHDBC * dbc)8958 SQLAllocConnect(SQLHENV env, SQLHDBC *dbc)
8959 {
8960 return drvallocconnect(env, dbc);
8961 }
8962
8963 /**
8964 * Internal free connection (HDBC).
8965 * @param dbc database connection handle
8966 * @result ODBC error code
8967 */
8968
8969 static SQLRETURN
drvfreeconnect(SQLHDBC dbc)8970 drvfreeconnect(SQLHDBC dbc)
8971 {
8972 DBC *d;
8973 ENV *e;
8974 SQLRETURN ret = SQL_ERROR;
8975
8976 if (dbc == SQL_NULL_HDBC) {
8977 return SQL_INVALID_HANDLE;
8978 }
8979 d = (DBC *) dbc;
8980 if (d->magic != DBC_MAGIC) {
8981 return SQL_INVALID_HANDLE;
8982 }
8983 e = d->env;
8984 if (e && e->magic == ENV_MAGIC) {
8985 #if defined(_WIN32) || defined(_WIN64)
8986 EnterCriticalSection(&e->cs);
8987 #endif
8988 } else {
8989 e = NULL;
8990 }
8991 HDBC_LOCK(dbc);
8992 if (d->sqlite) {
8993 setstatd(d, -1, "not disconnected", (*d->ov3) ? "HY000" : "S1000");
8994 HDBC_UNLOCK(dbc);
8995 goto done;
8996 }
8997 while (d->stmt) {
8998 freestmt((HSTMT) d->stmt);
8999 }
9000 if (e && e->magic == ENV_MAGIC) {
9001 DBC *n, *p;
9002
9003 p = NULL;
9004 n = e->dbcs;
9005 while (n) {
9006 if (n == d) {
9007 break;
9008 }
9009 p = n;
9010 n = n->next;
9011 }
9012 if (n) {
9013 if (p) {
9014 p->next = d->next;
9015 } else {
9016 e->dbcs = d->next;
9017 }
9018 }
9019 }
9020 drvrelgpps(d);
9021 d->magic = DEAD_MAGIC;
9022 #if defined(HAVE_SQLITETRACE) && (HAVE_SQLITETRACE)
9023 if (d->trace) {
9024 fclose(d->trace);
9025 }
9026 #endif
9027 #if defined(_WIN32) || defined(_WIN64)
9028 d->owner = 0;
9029 LeaveCriticalSection(&d->cs);
9030 DeleteCriticalSection(&d->cs);
9031 #endif
9032 xfree(d);
9033 ret = SQL_SUCCESS;
9034 done:
9035 #if defined(_WIN32) || defined(_WIN64)
9036 if (e) {
9037 LeaveCriticalSection(&e->cs);
9038 }
9039 #endif
9040 return ret;
9041 }
9042
9043 /**
9044 * Free connection (HDBC).
9045 * @param dbc database connection handle
9046 * @result ODBC error code
9047 */
9048
9049 SQLRETURN SQL_API
SQLFreeConnect(SQLHDBC dbc)9050 SQLFreeConnect(SQLHDBC dbc)
9051 {
9052 return drvfreeconnect(dbc);
9053 }
9054
9055 /**
9056 * Internal get connect attribute of HDBC.
9057 * @param dbc database connection handle
9058 * @param attr option to be retrieved
9059 * @param val output buffer
9060 * @param bufmax size of output buffer
9061 * @param buflen output length
9062 * @result ODBC error code
9063 */
9064
9065 static SQLRETURN
drvgetconnectattr(SQLHDBC dbc,SQLINTEGER attr,SQLPOINTER val,SQLINTEGER bufmax,SQLINTEGER * buflen)9066 drvgetconnectattr(SQLHDBC dbc, SQLINTEGER attr, SQLPOINTER val,
9067 SQLINTEGER bufmax, SQLINTEGER *buflen)
9068 {
9069 DBC *d;
9070 SQLINTEGER dummy;
9071
9072 if (dbc == SQL_NULL_HDBC) {
9073 return SQL_INVALID_HANDLE;
9074 }
9075 d = (DBC *) dbc;
9076 if (!val) {
9077 val = (SQLPOINTER) &dummy;
9078 }
9079 if (!buflen) {
9080 buflen = &dummy;
9081 }
9082 switch (attr) {
9083 case SQL_ATTR_CONNECTION_DEAD:
9084 *((SQLINTEGER *) val) = d->sqlite ? SQL_CD_FALSE : SQL_CD_TRUE;
9085 *buflen = sizeof (SQLINTEGER);
9086 break;
9087 case SQL_ATTR_ACCESS_MODE:
9088 *((SQLINTEGER *) val) = SQL_MODE_READ_WRITE;
9089 *buflen = sizeof (SQLINTEGER);
9090 break;
9091 case SQL_ATTR_AUTOCOMMIT:
9092 *((SQLINTEGER *) val) =
9093 d->autocommit ? SQL_AUTOCOMMIT_ON : SQL_AUTOCOMMIT_OFF;
9094 *buflen = sizeof (SQLINTEGER);
9095 break;
9096 case SQL_ATTR_LOGIN_TIMEOUT:
9097 *((SQLINTEGER *) val) = 100;
9098 *buflen = sizeof (SQLINTEGER);
9099 break;
9100 case SQL_ATTR_ODBC_CURSORS:
9101 *((SQLINTEGER *) val) = SQL_CUR_USE_DRIVER;
9102 *buflen = sizeof (SQLINTEGER);
9103 break;
9104 case SQL_ATTR_PACKET_SIZE:
9105 *((SQLINTEGER *) val) = 16384;
9106 *buflen = sizeof (SQLINTEGER);
9107 break;
9108 case SQL_ATTR_TXN_ISOLATION:
9109 *((SQLINTEGER *) val) = SQL_TXN_SERIALIZABLE;
9110 *buflen = sizeof (SQLINTEGER);
9111 break;
9112 case SQL_ATTR_TRACEFILE:
9113 case SQL_ATTR_TRANSLATE_LIB:
9114 *((SQLCHAR *) val) = 0;
9115 *buflen = 0;
9116 break;
9117 case SQL_ATTR_CURRENT_CATALOG:
9118 #if defined(_WIN32) || defined(_WIN64)
9119 if (d->xcelqrx) {
9120 if ((bufmax > 4) && (val != (SQLPOINTER) &dummy)) {
9121 strcpy((char *) val, "main");
9122 *buflen = 4;
9123 break;
9124 }
9125 }
9126 #endif
9127 *((SQLCHAR *) val) = 0;
9128 *buflen = 0;
9129 break;
9130 case SQL_ATTR_TRACE:
9131 case SQL_ATTR_QUIET_MODE:
9132 case SQL_ATTR_TRANSLATE_OPTION:
9133 case SQL_ATTR_KEYSET_SIZE:
9134 case SQL_ATTR_QUERY_TIMEOUT:
9135 *((SQLINTEGER *) val) = 0;
9136 *buflen = sizeof (SQLINTEGER);
9137 break;
9138 case SQL_ATTR_PARAM_BIND_TYPE:
9139 *((SQLUINTEGER *) val) = SQL_PARAM_BIND_BY_COLUMN;
9140 *buflen = sizeof (SQLUINTEGER);
9141 break;
9142 case SQL_ATTR_ROW_BIND_TYPE:
9143 *((SQLUINTEGER *) val) = SQL_BIND_BY_COLUMN;
9144 *buflen = sizeof (SQLUINTEGER);
9145 break;
9146 case SQL_ATTR_USE_BOOKMARKS:
9147 *((SQLINTEGER *) val) = SQL_UB_OFF;
9148 *buflen = sizeof (SQLINTEGER);
9149 break;
9150 case SQL_ATTR_ASYNC_ENABLE:
9151 *((SQLINTEGER *) val) = SQL_ASYNC_ENABLE_OFF;
9152 *buflen = sizeof (SQLINTEGER);
9153 break;
9154 case SQL_ATTR_NOSCAN:
9155 *((SQLINTEGER *) val) = SQL_NOSCAN_OFF;
9156 *buflen = sizeof (SQLINTEGER);
9157 break;
9158 case SQL_ATTR_CONCURRENCY:
9159 *((SQLINTEGER *) val) = SQL_CONCUR_LOCK;
9160 *buflen = sizeof (SQLINTEGER);
9161 break;
9162 #ifdef SQL_ATTR_CURSOR_SENSITIVITY
9163 case SQL_ATTR_CURSOR_SENSITIVITY:
9164 *((SQLINTEGER *) val) = SQL_UNSPECIFIED;
9165 *buflen = sizeof (SQLINTEGER);
9166 break;
9167 #endif
9168 case SQL_ATTR_SIMULATE_CURSOR:
9169 *((SQLINTEGER *) val) = SQL_SC_NON_UNIQUE;
9170 *buflen = sizeof (SQLINTEGER);
9171 break;
9172 case SQL_ATTR_MAX_ROWS:
9173 case SQL_ATTR_MAX_LENGTH:
9174 *((SQLINTEGER *) val) = 1000000000;
9175 *buflen = sizeof (SQLINTEGER);
9176 break;
9177 case SQL_ATTR_CURSOR_TYPE:
9178 *((SQLINTEGER *) val) = d->curtype;
9179 *buflen = sizeof (SQLINTEGER);
9180 break;
9181 case SQL_ATTR_RETRIEVE_DATA:
9182 *((SQLINTEGER *) val) = SQL_RD_ON;
9183 *buflen = sizeof (SQLINTEGER);
9184 break;
9185 default:
9186 setstatd(d, -1, "unsupported connect attribute %d",
9187 (*d->ov3) ? "HYC00" : "S1C00", (int) attr);
9188 return SQL_ERROR;
9189 }
9190 return SQL_SUCCESS;
9191 }
9192
9193 #ifndef WINTERFACE
9194 /**
9195 * Get connect attribute of HDBC.
9196 * @param dbc database connection handle
9197 * @param attr option to be retrieved
9198 * @param val output buffer
9199 * @param bufmax size of output buffer
9200 * @param buflen output length
9201 * @result ODBC error code
9202 */
9203
9204 SQLRETURN SQL_API
SQLGetConnectAttr(SQLHDBC dbc,SQLINTEGER attr,SQLPOINTER val,SQLINTEGER bufmax,SQLINTEGER * buflen)9205 SQLGetConnectAttr(SQLHDBC dbc, SQLINTEGER attr, SQLPOINTER val,
9206 SQLINTEGER bufmax, SQLINTEGER *buflen)
9207 {
9208 SQLRETURN ret;
9209
9210 HDBC_LOCK(dbc);
9211 ret = drvgetconnectattr(dbc, attr, val, bufmax, buflen);
9212 HDBC_UNLOCK(dbc);
9213 return ret;
9214 }
9215 #endif
9216
9217 #ifdef WINTERFACE
9218 /**
9219 * Get connect attribute of HDBC (UNICODE version).
9220 * @param dbc database connection handle
9221 * @param attr option to be retrieved
9222 * @param val output buffer
9223 * @param bufmax size of output buffer
9224 * @param buflen output length
9225 * @result ODBC error code
9226 */
9227
9228 SQLRETURN SQL_API
SQLGetConnectAttrW(SQLHDBC dbc,SQLINTEGER attr,SQLPOINTER val,SQLINTEGER bufmax,SQLINTEGER * buflen)9229 SQLGetConnectAttrW(SQLHDBC dbc, SQLINTEGER attr, SQLPOINTER val,
9230 SQLINTEGER bufmax, SQLINTEGER *buflen)
9231 {
9232 SQLRETURN ret;
9233 SQLINTEGER len = 0;
9234
9235 HDBC_LOCK(dbc);
9236 ret = drvgetconnectattr(dbc, attr, val, bufmax, &len);
9237 if (ret == SQL_SUCCESS) {
9238 SQLWCHAR *v = NULL;
9239
9240 switch (attr) {
9241 case SQL_ATTR_TRACEFILE:
9242 case SQL_ATTR_CURRENT_CATALOG:
9243 case SQL_ATTR_TRANSLATE_LIB:
9244 if (val) {
9245 if (len > 0) {
9246 v = uc_from_utf((SQLCHAR *) val, len);
9247 if (v) {
9248 int vmax = bufmax / sizeof (SQLWCHAR);
9249
9250 uc_strncpy(val, v, vmax);
9251 if (len < vmax) {
9252 len = min(vmax, uc_strlen(v));
9253 v[len] = 0;
9254 } else {
9255 len = vmax;
9256 }
9257 uc_free(v);
9258 len *= sizeof (SQLWCHAR);
9259 } else {
9260 len = 0;
9261 }
9262 }
9263 if (len <= 0) {
9264 len = 0;
9265 if (bufmax >= sizeof (SQLWCHAR)) {
9266 *((SQLWCHAR *)val) = 0;
9267 }
9268 }
9269 } else {
9270 len *= sizeof (SQLWCHAR);
9271 }
9272 break;
9273 }
9274 if (buflen) {
9275 *buflen = len;
9276 }
9277 }
9278 HDBC_UNLOCK(dbc);
9279 return ret;
9280 }
9281 #endif
9282
9283 /**
9284 * Internal set connect attribute of HDBC.
9285 * @param dbc database connection handle
9286 * @param attr option to be set
9287 * @param val option value
9288 * @param len size of option
9289 * @result ODBC error code
9290 */
9291
9292 static SQLRETURN
drvsetconnectattr(SQLHDBC dbc,SQLINTEGER attr,SQLPOINTER val,SQLINTEGER len)9293 drvsetconnectattr(SQLHDBC dbc, SQLINTEGER attr, SQLPOINTER val,
9294 SQLINTEGER len)
9295 {
9296 DBC *d;
9297
9298 if (dbc == SQL_NULL_HDBC) {
9299 return SQL_INVALID_HANDLE;
9300 }
9301 d = (DBC *) dbc;
9302 switch (attr) {
9303 case SQL_AUTOCOMMIT:
9304 d->autocommit = val == (SQLPOINTER) SQL_AUTOCOMMIT_ON;
9305 if (d->autocommit && d->intrans) {
9306 return endtran(d, SQL_COMMIT, 1);
9307 } else if (!d->autocommit) {
9308 vm_end(d->vm_stmt);
9309 }
9310 break;
9311 default:
9312 setstatd(d, -1, "option value changed", "01S02");
9313 return SQL_SUCCESS_WITH_INFO;
9314 }
9315 return SQL_SUCCESS;
9316 }
9317
9318 #ifndef WINTERFACE
9319 /**
9320 * Set connect attribute of HDBC.
9321 * @param dbc database connection handle
9322 * @param attr option to be set
9323 * @param val option value
9324 * @param len size of option
9325 * @result ODBC error code
9326 */
9327
9328 SQLRETURN SQL_API
SQLSetConnectAttr(SQLHDBC dbc,SQLINTEGER attr,SQLPOINTER val,SQLINTEGER len)9329 SQLSetConnectAttr(SQLHDBC dbc, SQLINTEGER attr, SQLPOINTER val,
9330 SQLINTEGER len)
9331 {
9332 SQLRETURN ret;
9333
9334 HDBC_LOCK(dbc);
9335 ret = drvsetconnectattr(dbc, attr, val, len);
9336 HDBC_UNLOCK(dbc);
9337 return ret;
9338 }
9339 #endif
9340
9341 #ifdef WINTERFACE
9342 /**
9343 * Set connect attribute of HDBC (UNICODE version).
9344 * @param dbc database connection handle
9345 * @param attr option to be set
9346 * @param val option value
9347 * @param len size of option
9348 * @result ODBC error code
9349 */
9350
9351 SQLRETURN SQL_API
SQLSetConnectAttrW(SQLHDBC dbc,SQLINTEGER attr,SQLPOINTER val,SQLINTEGER len)9352 SQLSetConnectAttrW(SQLHDBC dbc, SQLINTEGER attr, SQLPOINTER val,
9353 SQLINTEGER len)
9354 {
9355 SQLRETURN ret;
9356
9357 HDBC_LOCK(dbc);
9358 ret = drvsetconnectattr(dbc, attr, val, len);
9359 HDBC_UNLOCK(dbc);
9360 return ret;
9361 }
9362 #endif
9363
9364 /**
9365 * Internal get connect option of HDBC.
9366 * @param dbc database connection handle
9367 * @param opt option to be retrieved
9368 * @param param output buffer
9369 * @result ODBC error code
9370 */
9371
9372 static SQLRETURN
drvgetconnectoption(SQLHDBC dbc,SQLUSMALLINT opt,SQLPOINTER param)9373 drvgetconnectoption(SQLHDBC dbc, SQLUSMALLINT opt, SQLPOINTER param)
9374 {
9375 DBC *d;
9376 SQLINTEGER dummy;
9377
9378 if (dbc == SQL_NULL_HDBC) {
9379 return SQL_INVALID_HANDLE;
9380 }
9381 d = (DBC *) dbc;
9382 if (!param) {
9383 param = (SQLPOINTER) &dummy;
9384 }
9385 switch (opt) {
9386 case SQL_ACCESS_MODE:
9387 *((SQLINTEGER *) param) = SQL_MODE_READ_WRITE;
9388 break;
9389 case SQL_AUTOCOMMIT:
9390 *((SQLINTEGER *) param) =
9391 d->autocommit ? SQL_AUTOCOMMIT_ON : SQL_AUTOCOMMIT_OFF;
9392 break;
9393 case SQL_LOGIN_TIMEOUT:
9394 *((SQLINTEGER *) param) = 100;
9395 break;
9396 case SQL_ODBC_CURSORS:
9397 *((SQLINTEGER *) param) = SQL_CUR_USE_DRIVER;
9398 break;
9399 case SQL_PACKET_SIZE:
9400 *((SQLINTEGER *) param) = 16384;
9401 break;
9402 case SQL_TXN_ISOLATION:
9403 *((SQLINTEGER *) param) = SQL_TXN_SERIALIZABLE;
9404 break;
9405 case SQL_OPT_TRACEFILE:
9406 case SQL_CURRENT_QUALIFIER:
9407 case SQL_TRANSLATE_DLL:
9408 *((SQLCHAR *) param) = 0;
9409 break;
9410 case SQL_OPT_TRACE:
9411 case SQL_QUIET_MODE:
9412 case SQL_KEYSET_SIZE:
9413 case SQL_QUERY_TIMEOUT:
9414 case SQL_BIND_TYPE:
9415 case SQL_TRANSLATE_OPTION:
9416 *((SQLINTEGER *) param) = 0;
9417 break;
9418 case SQL_USE_BOOKMARKS:
9419 *((SQLINTEGER *) param) = SQL_UB_OFF;
9420 break;
9421 case SQL_ASYNC_ENABLE:
9422 *((SQLINTEGER *) param) = SQL_ASYNC_ENABLE_OFF;
9423 break;
9424 case SQL_NOSCAN:
9425 *((SQLINTEGER *) param) = SQL_NOSCAN_OFF;
9426 break;
9427 case SQL_CONCURRENCY:
9428 *((SQLINTEGER *) param) = SQL_CONCUR_LOCK;
9429 break;
9430 case SQL_SIMULATE_CURSOR:
9431 *((SQLINTEGER *) param) = SQL_SC_NON_UNIQUE;
9432 break;
9433 case SQL_ROWSET_SIZE:
9434 case SQL_MAX_ROWS:
9435 case SQL_MAX_LENGTH:
9436 *((SQLINTEGER *) param) = 1000000000;
9437 break;
9438 case SQL_CURSOR_TYPE:
9439 *((SQLINTEGER *) param) = d->curtype;
9440 break;
9441 case SQL_RETRIEVE_DATA:
9442 *((SQLINTEGER *) param) = SQL_RD_ON;
9443 break;
9444 default:
9445 setstatd(d, -1, "unsupported connect option %d",
9446 (*d->ov3) ? "HYC00" : "S1C00", opt);
9447 return SQL_ERROR;
9448 }
9449 return SQL_SUCCESS;
9450 }
9451
9452 #ifndef WINTERFACE
9453 /**
9454 * Get connect option of HDBC.
9455 * @param dbc database connection handle
9456 * @param opt option to be retrieved
9457 * @param param output buffer
9458 * @result ODBC error code
9459 */
9460
9461 SQLRETURN SQL_API
SQLGetConnectOption(SQLHDBC dbc,SQLUSMALLINT opt,SQLPOINTER param)9462 SQLGetConnectOption(SQLHDBC dbc, SQLUSMALLINT opt, SQLPOINTER param)
9463 {
9464 SQLRETURN ret;
9465
9466 HDBC_LOCK(dbc);
9467 ret = drvgetconnectoption(dbc, opt, param);
9468 HDBC_UNLOCK(dbc);
9469 return ret;
9470 }
9471 #endif
9472
9473 #ifdef WINTERFACE
9474 /**
9475 * Get connect option of HDBC (UNICODE version).
9476 * @param dbc database connection handle
9477 * @param opt option to be retrieved
9478 * @param param output buffer
9479 * @result ODBC error code
9480 */
9481
9482 SQLRETURN SQL_API
SQLGetConnectOptionW(SQLHDBC dbc,SQLUSMALLINT opt,SQLPOINTER param)9483 SQLGetConnectOptionW(SQLHDBC dbc, SQLUSMALLINT opt, SQLPOINTER param)
9484 {
9485 SQLRETURN ret;
9486
9487 HDBC_LOCK(dbc);
9488 ret = drvgetconnectoption(dbc, opt, param);
9489 if (SQL_SUCCEEDED(ret)) {
9490 switch (opt) {
9491 case SQL_OPT_TRACEFILE:
9492 case SQL_CURRENT_QUALIFIER:
9493 case SQL_TRANSLATE_DLL:
9494 if (param) {
9495 *(SQLWCHAR *) param = 0;
9496 }
9497 break;
9498 }
9499 }
9500 HDBC_UNLOCK(dbc);
9501 return ret;
9502 }
9503 #endif
9504
9505 /**
9506 * Internal set option on HDBC.
9507 * @param dbc database connection handle
9508 * @param opt option to be set
9509 * @param param option value
9510 * @result ODBC error code
9511 */
9512
9513 static SQLRETURN
drvsetconnectoption(SQLHDBC dbc,SQLUSMALLINT opt,SQLUINTEGER param)9514 drvsetconnectoption(SQLHDBC dbc, SQLUSMALLINT opt, SQLUINTEGER param)
9515 {
9516 DBC *d;
9517
9518 if (dbc == SQL_NULL_HDBC) {
9519 return SQL_INVALID_HANDLE;
9520 }
9521 d = (DBC *) dbc;
9522 switch (opt) {
9523 case SQL_AUTOCOMMIT:
9524 d->autocommit = param == SQL_AUTOCOMMIT_ON;
9525 if (d->autocommit && d->intrans) {
9526 return endtran(d, SQL_COMMIT, 1);
9527 } else if (!d->autocommit) {
9528 vm_end(d->vm_stmt);
9529 }
9530 break;
9531 default:
9532 setstatd(d, -1, "option value changed", "01S02");
9533 return SQL_SUCCESS_WITH_INFO;
9534 }
9535 return SQL_SUCCESS;
9536 }
9537
9538 #ifndef WINTERFACE
9539 /**
9540 * Set option on HDBC.
9541 * @param dbc database connection handle
9542 * @param opt option to be set
9543 * @param param option value
9544 * @result ODBC error code
9545 */
9546
9547 SQLRETURN SQL_API
SQLSetConnectOption(SQLHDBC dbc,SQLUSMALLINT opt,SQLULEN param)9548 SQLSetConnectOption(SQLHDBC dbc, SQLUSMALLINT opt, SQLULEN param)
9549 {
9550 SQLRETURN ret;
9551
9552 HDBC_LOCK(dbc);
9553 ret = drvsetconnectoption(dbc, opt, param);
9554 HDBC_UNLOCK(dbc);
9555 return ret;
9556 }
9557 #endif
9558
9559 #ifdef WINTERFACE
9560 /**
9561 * Set option on HDBC (UNICODE version).
9562 * @param dbc database connection handle
9563 * @param opt option to be set
9564 * @param param option value
9565 * @result ODBC error code
9566 */
9567
9568 SQLRETURN SQL_API
SQLSetConnectOptionW(SQLHDBC dbc,SQLUSMALLINT opt,SQLULEN param)9569 SQLSetConnectOptionW(SQLHDBC dbc, SQLUSMALLINT opt, SQLULEN param)
9570 {
9571 SQLRETURN ret;
9572
9573 HDBC_LOCK(dbc);
9574 ret = drvsetconnectoption(dbc, opt, param);
9575 HDBC_UNLOCK(dbc);
9576 return ret;
9577 }
9578 #endif
9579
9580 #if defined(WITHOUT_DRIVERMGR) || (!defined(_WIN32) && !defined(_WIN64) && !defined(__OS2__))
9581
9582 /**
9583 * Handling of SQLConnect() connection attributes
9584 * for standalone operation without driver manager.
9585 * @param dsn DSN/driver connection string
9586 * @param attr attribute string to be retrieved
9587 * @param out output buffer
9588 * @param outLen length of output buffer
9589 * @result true or false
9590 */
9591
9592 static int
getdsnattr(char * dsn,char * attr,char * out,int outLen)9593 getdsnattr(char *dsn, char *attr, char *out, int outLen)
9594 {
9595 char *str = dsn, *start;
9596 int len = strlen(attr);
9597
9598 while (*str) {
9599 while (*str && *str == ';') {
9600 ++str;
9601 }
9602 start = str;
9603 if ((str = strchr(str, '=')) == NULL) {
9604 return 0;
9605 }
9606 if (str - start == len && strncasecmp(start, attr, len) == 0) {
9607 start = ++str;
9608 while (*str && *str != ';') {
9609 ++str;
9610 }
9611 len = min(outLen - 1, str - start);
9612 strncpy(out, start, len);
9613 out[len] = '\0';
9614 return 1;
9615 }
9616 while (*str && *str != ';') {
9617 ++str;
9618 }
9619 }
9620 return 0;
9621 }
9622 #endif
9623
9624 /**
9625 * Internal connect to SQLite database.
9626 * @param dbc database connection handle
9627 * @param dsn DSN string
9628 * @param dsnLen length of DSN string or SQL_NTS
9629 * @result ODBC error code
9630 */
9631
9632 static SQLRETURN
drvconnect(SQLHDBC dbc,SQLCHAR * dsn,SQLSMALLINT dsnLen)9633 drvconnect(SQLHDBC dbc, SQLCHAR *dsn, SQLSMALLINT dsnLen)
9634 {
9635 DBC *d;
9636 int len;
9637 char buf[SQL_MAX_MESSAGE_LENGTH * 6], dbname[SQL_MAX_MESSAGE_LENGTH];
9638 char busy[SQL_MAX_MESSAGE_LENGTH / 4];
9639 char sflag[32], ntflag[32], nwflag[32], lnflag[32];
9640 #if defined(HAVE_SQLITETRACE) && (HAVE_SQLITETRACE)
9641 char tracef[SQL_MAX_MESSAGE_LENGTH];
9642 #endif
9643
9644 if (dbc == SQL_NULL_HDBC) {
9645 return SQL_INVALID_HANDLE;
9646 }
9647 d = (DBC *) dbc;
9648 if (d->magic != DBC_MAGIC) {
9649 return SQL_INVALID_HANDLE;
9650 }
9651 if (d->sqlite != NULL) {
9652 setstatd(d, -1, "connection already established", "08002");
9653 return SQL_ERROR;
9654 }
9655 buf[0] = '\0';
9656 if (dsnLen == SQL_NTS) {
9657 len = sizeof (buf) - 1;
9658 } else {
9659 len = min(sizeof (buf) - 1, dsnLen);
9660 }
9661 if (dsn != NULL) {
9662 strncpy(buf, (char *) dsn, len);
9663 }
9664 buf[len] = '\0';
9665 if (buf[0] == '\0') {
9666 setstatd(d, -1, "invalid DSN", (*d->ov3) ? "HY090" : "S1090");
9667 return SQL_ERROR;
9668 }
9669 busy[0] = '\0';
9670 dbname[0] = '\0';
9671 #ifdef WITHOUT_DRIVERMGR
9672 getdsnattr(buf, "database", dbname, sizeof (dbname));
9673 if (dbname[0] == '\0') {
9674 strncpy(dbname, buf, sizeof (dbname));
9675 dbname[sizeof (dbname) - 1] = '\0';
9676 }
9677 getdsnattr(buf, "timeout", busy, sizeof (busy));
9678 sflag[0] = '\0';
9679 ntflag[0] = '\0';
9680 nwflag[0] = '\0';
9681 lnflag[0] = '\0';
9682 getdsnattr(buf, "stepapi", sflag, sizeof (sflag));
9683 getdsnattr(buf, "notxn", ntflag, sizeof (ntflag));
9684 getdsnattr(buf, "nowchar", nwflag, sizeof (nwflag));
9685 getdsnattr(buf, "longnames", lnflag, sizeof (lnflag));
9686 #else
9687 SQLGetPrivateProfileString(buf, "timeout", "100000",
9688 busy, sizeof (busy), ODBC_INI);
9689 SQLGetPrivateProfileString(buf, "database", "",
9690 dbname, sizeof (dbname), ODBC_INI);
9691 SQLGetPrivateProfileString(buf, "stepapi", "",
9692 sflag, sizeof (sflag), ODBC_INI);
9693 SQLGetPrivateProfileString(buf, "notxn", "",
9694 ntflag, sizeof (ntflag), ODBC_INI);
9695 SQLGetPrivateProfileString(buf, "nowchar", "",
9696 nwflag, sizeof (nwflag), ODBC_INI);
9697 SQLGetPrivateProfileString(buf, "longnames", "",
9698 lnflag, sizeof (lnflag), ODBC_INI);
9699 #endif
9700 #if defined(HAVE_SQLITETRACE) && (HAVE_SQLITETRACE)
9701 tracef[0] = '\0';
9702 #ifdef WITHOUT_DRIVERMGR
9703 getdsnattr(buf, "tracefile", tracef, sizeof (tracef));
9704 #else
9705 SQLGetPrivateProfileString(buf, "tracefile", "",
9706 tracef, sizeof (tracef), ODBC_INI);
9707 #endif
9708 if (tracef[0] != '\0') {
9709 d->trace = fopen(tracef, "a");
9710 }
9711 #endif
9712 d->nowchar = getbool(nwflag);
9713 d->longnames = getbool(lnflag);
9714 return dbopen(d, dbname, (char *) dsn, sflag, ntflag, busy);
9715 }
9716
9717 #ifndef WINTERFACE
9718 /**
9719 * Connect to SQLite database.
9720 * @param dbc database connection handle
9721 * @param dsn DSN string
9722 * @param dsnLen length of DSN string or SQL_NTS
9723 * @param uid user id string or NULL
9724 * @param uidLen length of user id string or SQL_NTS
9725 * @param pass password string or NULL
9726 * @param passLen length of password string or SQL_NTS
9727 * @result ODBC error code
9728 */
9729
9730 SQLRETURN SQL_API
SQLConnect(SQLHDBC dbc,SQLCHAR * dsn,SQLSMALLINT dsnLen,SQLCHAR * uid,SQLSMALLINT uidLen,SQLCHAR * pass,SQLSMALLINT passLen)9731 SQLConnect(SQLHDBC dbc, SQLCHAR *dsn, SQLSMALLINT dsnLen,
9732 SQLCHAR *uid, SQLSMALLINT uidLen,
9733 SQLCHAR *pass, SQLSMALLINT passLen)
9734 {
9735 SQLRETURN ret;
9736
9737 HDBC_LOCK(dbc);
9738 ret = drvconnect(dbc, dsn, dsnLen);
9739 HDBC_UNLOCK(dbc);
9740 return ret;
9741 }
9742 #endif
9743
9744 #ifdef WINTERFACE
9745 /**
9746 * Connect to SQLite database.
9747 * @param dbc database connection handle
9748 * @param dsn DSN string
9749 * @param dsnLen length of DSN string or SQL_NTS
9750 * @param uid user id string or NULL
9751 * @param uidLen length of user id string or SQL_NTS
9752 * @param pass password string or NULL
9753 * @param passLen length of password string or SQL_NTS
9754 * @result ODBC error code
9755 */
9756
9757 SQLRETURN SQL_API
SQLConnectW(SQLHDBC dbc,SQLWCHAR * dsn,SQLSMALLINT dsnLen,SQLWCHAR * uid,SQLSMALLINT uidLen,SQLWCHAR * pass,SQLSMALLINT passLen)9758 SQLConnectW(SQLHDBC dbc, SQLWCHAR *dsn, SQLSMALLINT dsnLen,
9759 SQLWCHAR *uid, SQLSMALLINT uidLen,
9760 SQLWCHAR *pass, SQLSMALLINT passLen)
9761 {
9762 char *dsna = NULL;
9763 SQLRETURN ret;
9764
9765 HDBC_LOCK(dbc);
9766 if (dsn) {
9767 dsna = uc_to_utf_c(dsn, dsnLen);
9768 if (!dsna) {
9769 DBC *d = (DBC *) dbc;
9770
9771 setstatd(d, -1, "out of memory", (*d->ov3) ? "HY000" : "S1000");
9772 return SQL_ERROR;
9773 }
9774 }
9775 ret = drvconnect(dbc, (SQLCHAR *) dsna, SQL_NTS);
9776 HDBC_UNLOCK(dbc);
9777 uc_free(dsna);
9778 return ret;
9779 }
9780 #endif
9781
9782 /**
9783 * Internal disconnect given HDBC.
9784 * @param dbc database connection handle
9785 * @result ODBC error code
9786 */
9787
9788 static SQLRETURN
drvdisconnect(SQLHDBC dbc)9789 drvdisconnect(SQLHDBC dbc)
9790 {
9791 DBC *d;
9792
9793 if (dbc == SQL_NULL_HDBC) {
9794 return SQL_INVALID_HANDLE;
9795 }
9796 d = (DBC *) dbc;
9797 if (d->magic != DBC_MAGIC) {
9798 return SQL_INVALID_HANDLE;
9799 }
9800 if (d->intrans) {
9801 setstatd(d, -1, "incomplete transaction", "25000");
9802 return SQL_ERROR;
9803 }
9804 if (d->vm_stmt) {
9805 vm_end(d->vm_stmt);
9806 }
9807 if (d->sqlite) {
9808 sqlite_close(d->sqlite);
9809 d->sqlite = NULL;
9810 }
9811 freep(&d->dbname);
9812 freep(&d->dsn);
9813 return SQL_SUCCESS;
9814 }
9815
9816 /**
9817 * Disconnect given HDBC.
9818 * @param dbc database connection handle
9819 * @result ODBC error code
9820 */
9821
9822 SQLRETURN SQL_API
SQLDisconnect(SQLHDBC dbc)9823 SQLDisconnect(SQLHDBC dbc)
9824 {
9825 SQLRETURN ret;
9826
9827 HDBC_LOCK(dbc);
9828 ret = drvdisconnect(dbc);
9829 HDBC_UNLOCK(dbc);
9830 return ret;
9831 }
9832
9833 #if defined(WITHOUT_DRIVERMGR) || (!defined(_WIN32) && !defined(_WIN64) && !defined(__OS2__))
9834
9835 /**
9836 * Internal standalone (w/o driver manager) database connect.
9837 * @param dbc database connection handle
9838 * @param hwnd dummy window handle or NULL
9839 * @param connIn driver connect input string
9840 * @param connInLen length of driver connect input string or SQL_NTS
9841 * @param connOut driver connect output string
9842 * @param connOutMax length of driver connect output string
9843 * @param connOutLen output length of driver connect output string
9844 * @param drvcompl completion type
9845 * @result ODBC error code
9846 */
9847
9848 static SQLRETURN
drvdriverconnect(SQLHDBC dbc,SQLHWND hwnd,SQLCHAR * connIn,SQLSMALLINT connInLen,SQLCHAR * connOut,SQLSMALLINT connOutMax,SQLSMALLINT * connOutLen,SQLUSMALLINT drvcompl)9849 drvdriverconnect(SQLHDBC dbc, SQLHWND hwnd,
9850 SQLCHAR *connIn, SQLSMALLINT connInLen,
9851 SQLCHAR *connOut, SQLSMALLINT connOutMax,
9852 SQLSMALLINT *connOutLen, SQLUSMALLINT drvcompl)
9853 {
9854 DBC *d;
9855 int len;
9856 char buf[SQL_MAX_MESSAGE_LENGTH * 6], dbname[SQL_MAX_MESSAGE_LENGTH];
9857 char dsn[SQL_MAX_MESSAGE_LENGTH], busy[SQL_MAX_MESSAGE_LENGTH / 4];
9858 char sflag[32], ntflag[32], lnflag[32];
9859 #if defined(HAVE_SQLITETRACE) && (HAVE_SQLITETRACE)
9860 char tracef[SQL_MAX_MESSAGE_LENGTH];
9861 #endif
9862
9863 if (dbc == SQL_NULL_HDBC) {
9864 return SQL_INVALID_HANDLE;
9865 }
9866 if (drvcompl != SQL_DRIVER_COMPLETE &&
9867 drvcompl != SQL_DRIVER_COMPLETE_REQUIRED &&
9868 drvcompl != SQL_DRIVER_PROMPT &&
9869 drvcompl != SQL_DRIVER_NOPROMPT) {
9870 return SQL_NO_DATA;
9871 }
9872 d = (DBC *) dbc;
9873 if (d->sqlite) {
9874 setstatd(d, -1, "connection already established", "08002");
9875 return SQL_ERROR;
9876 }
9877 buf[0] = '\0';
9878 if (connInLen == SQL_NTS) {
9879 len = sizeof (buf) - 1;
9880 } else {
9881 len = min(connInLen, sizeof (buf) - 1);
9882 }
9883 if (connIn != NULL) {
9884 strncpy(buf, (char *) connIn, len);
9885 }
9886 buf[len] = '\0';
9887 if (!buf[0]) {
9888 setstatd(d, -1, "invalid connect attributes",
9889 (*d->ov3) ? "HY090" : "S1090");
9890 return SQL_ERROR;
9891 }
9892 dsn[0] = '\0';
9893 getdsnattr(buf, "DSN", dsn, sizeof (dsn));
9894
9895 /* special case: connIn is sole DSN value without keywords */
9896 if (!dsn[0] && !strchr(buf, ';') && !strchr(buf, '=')) {
9897 strncpy(dsn, buf, sizeof (dsn) - 1);
9898 dsn[sizeof (dsn) - 1] = '\0';
9899 }
9900
9901 busy[0] = '\0';
9902 getdsnattr(buf, "timeout", busy, sizeof (busy));
9903 #ifndef WITHOUT_DRIVERMGR
9904 if (dsn[0] && !busy[0]) {
9905 SQLGetPrivateProfileString(dsn, "timeout", "100000",
9906 busy, sizeof (busy), ODBC_INI);
9907 }
9908 #endif
9909 dbname[0] = '\0';
9910 getdsnattr(buf, "database", dbname, sizeof (dbname));
9911 #ifndef WITHOUT_DRIVERMGR
9912 if (dsn[0] && !dbname[0]) {
9913 SQLGetPrivateProfileString(dsn, "database", "",
9914 dbname, sizeof (dbname), ODBC_INI);
9915 }
9916 #endif
9917 sflag[0] = '\0';
9918 getdsnattr(buf, "stepapi", sflag, sizeof (sflag));
9919 #ifndef WITHOUT_DRIVERMGR
9920 if (dsn[0] && !sflag[0]) {
9921 SQLGetPrivateProfileString(dsn, "stepapi", "",
9922 sflag, sizeof (sflag), ODBC_INI);
9923 }
9924 #endif
9925 ntflag[0] = '\0';
9926 getdsnattr(buf, "notxn", ntflag, sizeof (ntflag));
9927 #ifndef WITHOUT_DRIVERMGR
9928 if (dsn[0] && !ntflag[0]) {
9929 SQLGetPrivateProfileString(dsn, "notxn", "",
9930 ntflag, sizeof (ntflag), ODBC_INI);
9931 }
9932 #endif
9933 lnflag[0] = '\0';
9934 getdsnattr(buf, "longnames", lnflag, sizeof (lnflag));
9935 #ifndef WITHOUT_DRIVERMGR
9936 if (dsn[0] && !lnflag[0]) {
9937 SQLGetPrivateProfileString(dsn, "longnames", "",
9938 lnflag, sizeof (lnflag), ODBC_INI);
9939 }
9940 #endif
9941 if (!dbname[0] && !dsn[0]) {
9942 strcpy(dsn, "SQLite");
9943 strncpy(dbname, buf, sizeof (dbname));
9944 dbname[sizeof (dbname) - 1] = '\0';
9945 }
9946 #if defined(HAVE_SQLITETRACE) && (HAVE_SQLITETRACE)
9947 tracef[0] = '\0';
9948 getdsnattr(buf, "tracefile", tracef, sizeof (tracef));
9949 #ifndef WITHOUT_DRIVERMGR
9950 if (dsn[0] && !tracef[0]) {
9951 SQLGetPrivateProfileString(dsn, "tracefile", "",
9952 tracef, sizeof (tracef), ODBC_INI);
9953 }
9954 #endif
9955 #endif
9956 if (connOut || connOutLen) {
9957 int count;
9958
9959 buf[0] = '\0';
9960 count = snprintf(buf, sizeof (buf),
9961 #if defined(HAVE_SQLITETRACE) && (HAVE_SQLITETRACE)
9962 "DSN=%s;Database=%s;StepAPI=%s;NoTXN=%s;"
9963 "Timeout=%s;LongNames=%s;Tracefile=%s",
9964 dsn, dbname, sflag, ntflag, busy, lnflag, tracef
9965 #else
9966 "DSN=%s;Database=%s;StepAPI=%s;NoTXN=%s;"
9967 "Timeout=%s;LongNames=%s",
9968 dsn, dbname, sflag, ntflag, busy, lnflag
9969 #endif
9970 );
9971 if (count < 0) {
9972 buf[sizeof (buf) - 1] = '\0';
9973 }
9974 len = min(connOutMax - 1, strlen(buf));
9975 if (connOut) {
9976 strncpy((char *) connOut, buf, len);
9977 connOut[len] = '\0';
9978 }
9979 if (connOutLen) {
9980 *connOutLen = len;
9981 }
9982 }
9983 #if defined(HAVE_SQLITETRACE) && (HAVE_SQLITETRACE)
9984 if (tracef[0] != '\0') {
9985 d->trace = fopen(tracef, "a");
9986 }
9987 #endif
9988 d->longnames = getbool(lnflag);
9989 return dbopen(d, dbname, dsn, sflag, ntflag, busy);
9990 }
9991 #endif
9992
9993 /**
9994 * Internal free function for HSTMT.
9995 * @param stmt statement handle
9996 * @result ODBC error code
9997 */
9998
9999 static SQLRETURN
freestmt(SQLHSTMT stmt)10000 freestmt(SQLHSTMT stmt)
10001 {
10002 STMT *s;
10003 DBC *d;
10004
10005 if (stmt == SQL_NULL_HSTMT) {
10006 return SQL_INVALID_HANDLE;
10007 }
10008 s = (STMT *) stmt;
10009 freeresult(s, 1);
10010 freep(&s->query);
10011 d = (DBC *) s->dbc;
10012 if (d && d->magic == DBC_MAGIC) {
10013 STMT *p, *n;
10014
10015 p = NULL;
10016 n = d->stmt;
10017 while (n) {
10018 if (n == s) {
10019 break;
10020 }
10021 p = n;
10022 n = n->next;
10023 }
10024 if (n) {
10025 if (p) {
10026 p->next = s->next;
10027 } else {
10028 d->stmt = s->next;
10029 }
10030 }
10031 }
10032 freeparams(s);
10033 freep(&s->bindparms);
10034 if (s->row_status0 != &s->row_status1) {
10035 freep(&s->row_status0);
10036 s->rowset_size = 1;
10037 s->row_status0 = &s->row_status1;
10038 }
10039 xfree(s);
10040 return SQL_SUCCESS;
10041 }
10042
10043 /**
10044 * Allocate HSTMT given HDBC (driver internal version).
10045 * @param dbc database connection handle
10046 * @param stmt pointer to statement handle
10047 * @result ODBC error code
10048 */
10049
10050 static SQLRETURN
drvallocstmt(SQLHDBC dbc,SQLHSTMT * stmt)10051 drvallocstmt(SQLHDBC dbc, SQLHSTMT *stmt)
10052 {
10053 DBC *d;
10054 STMT *s, *sl, *pl;
10055
10056 if (dbc == SQL_NULL_HDBC) {
10057 return SQL_INVALID_HANDLE;
10058 }
10059 d = (DBC *) dbc;
10060 if (d->magic != DBC_MAGIC || stmt == NULL) {
10061 return SQL_INVALID_HANDLE;
10062 }
10063 s = (STMT *) xmalloc(sizeof (STMT));
10064 if (s == NULL) {
10065 *stmt = SQL_NULL_HSTMT;
10066 return SQL_ERROR;
10067 }
10068 *stmt = (SQLHSTMT) s;
10069 memset(s, 0, sizeof (STMT));
10070 s->dbc = dbc;
10071 s->ov3 = d->ov3;
10072 s->nowchar[0] = d->nowchar;
10073 s->nowchar[1] = 0;
10074 s->longnames = d->longnames;
10075 s->curtype = d->curtype;
10076 s->row_status0 = &s->row_status1;
10077 s->rowset_size = 1;
10078 s->retr_data = SQL_RD_ON;
10079 s->bind_type = SQL_BIND_BY_COLUMN;
10080 s->bind_offs = NULL;
10081 s->paramset_size = 1;
10082 s->parm_bind_type = SQL_PARAM_BIND_BY_COLUMN;
10083 #ifdef _WIN64
10084 sprintf((char *) s->cursorname, "CUR_%I64X", (SQLUBIGINT) *stmt);
10085 #else
10086 sprintf((char *) s->cursorname, "CUR_%016lX", (long) *stmt);
10087 #endif
10088 sl = d->stmt;
10089 pl = NULL;
10090 while (sl) {
10091 pl = sl;
10092 sl = sl->next;
10093 }
10094 if (pl) {
10095 pl->next = s;
10096 } else {
10097 d->stmt = s;
10098 }
10099 return SQL_SUCCESS;
10100 }
10101
10102 /**
10103 * Allocate HSTMT given HDBC.
10104 * @param dbc database connection handle
10105 * @param stmt pointer to statement handle
10106 * @result ODBC error code
10107 */
10108
10109 SQLRETURN SQL_API
SQLAllocStmt(SQLHDBC dbc,SQLHSTMT * stmt)10110 SQLAllocStmt(SQLHDBC dbc, SQLHSTMT *stmt)
10111 {
10112 SQLRETURN ret;
10113
10114 HDBC_LOCK(dbc);
10115 ret = drvallocstmt(dbc, stmt);
10116 HDBC_UNLOCK(dbc);
10117 return ret;
10118 }
10119
10120 /**
10121 * Internal function to perform certain kinds of free/close on STMT.
10122 * @param stmt statement handle
10123 * @param opt SQL_RESET_PARAMS, SQL_UNBIND, SQL_CLOSE, or SQL_DROP
10124 * @result ODBC error code
10125 */
10126
10127 static SQLRETURN
drvfreestmt(SQLHSTMT stmt,SQLUSMALLINT opt)10128 drvfreestmt(SQLHSTMT stmt, SQLUSMALLINT opt)
10129 {
10130 STMT *s;
10131 SQLRETURN ret = SQL_SUCCESS;
10132 SQLHDBC dbc;
10133
10134 if (stmt == SQL_NULL_HSTMT) {
10135 return SQL_INVALID_HANDLE;
10136 }
10137 HSTMT_LOCK(stmt);
10138 s = (STMT *) stmt;
10139 dbc = s->dbc;
10140 switch (opt) {
10141 case SQL_RESET_PARAMS:
10142 freeparams(s);
10143 break;
10144 case SQL_UNBIND:
10145 unbindcols(s);
10146 break;
10147 case SQL_CLOSE:
10148 vm_end_if(s);
10149 freeresult(s, 0);
10150 break;
10151 case SQL_DROP:
10152 vm_end_if(s);
10153 ret = freestmt(stmt);
10154 break;
10155 default:
10156 setstat(s, -1, "unsupported option", (*s->ov3) ? "HYC00" : "S1C00");
10157 ret = SQL_ERROR;
10158 break;
10159 }
10160 HDBC_UNLOCK(dbc);
10161 return ret;
10162 }
10163
10164 /**
10165 * Free HSTMT.
10166 * @param stmt statement handle
10167 * @param opt SQL_RESET_PARAMS, SQL_UNBIND, SQL_CLOSE, or SQL_DROP
10168 * @result ODBC error code
10169 */
10170
10171 SQLRETURN SQL_API
SQLFreeStmt(SQLHSTMT stmt,SQLUSMALLINT opt)10172 SQLFreeStmt(SQLHSTMT stmt, SQLUSMALLINT opt)
10173 {
10174 return drvfreestmt(stmt, opt);
10175 }
10176
10177 /**
10178 * Cancel HSTMT closing cursor.
10179 * @param stmt statement handle
10180 * @result ODBC error code
10181 */
10182
10183 SQLRETURN SQL_API
SQLCancel(SQLHSTMT stmt)10184 SQLCancel(SQLHSTMT stmt)
10185 {
10186 if (stmt != SQL_NULL_HSTMT) {
10187 DBC *d = (DBC *) ((STMT *) stmt)->dbc;
10188 #if defined(_WIN32) || defined(_WIN64)
10189 /* interrupt when other thread owns critical section */
10190 if (d->magic == DBC_MAGIC && d->owner != GetCurrentThreadId() &&
10191 d->owner != 0) {
10192 d->busyint = 1;
10193 sqlite_interrupt(d->sqlite);
10194 return SQL_SUCCESS;
10195 }
10196 #else
10197 if (d->magic == DBC_MAGIC) {
10198 d->busyint = 1;
10199 sqlite_interrupt(d->sqlite);
10200 }
10201 #endif
10202 }
10203 return drvfreestmt(stmt, SQL_CLOSE);
10204 }
10205
10206 /**
10207 * Internal function to get cursor name of STMT.
10208 * @param stmt statement handle
10209 * @param cursor output buffer
10210 * @param buflen length of output buffer
10211 * @param lenp output length
10212 * @result ODBC error code
10213 */
10214
10215 static SQLRETURN
drvgetcursorname(SQLHSTMT stmt,SQLCHAR * cursor,SQLSMALLINT buflen,SQLSMALLINT * lenp)10216 drvgetcursorname(SQLHSTMT stmt, SQLCHAR *cursor, SQLSMALLINT buflen,
10217 SQLSMALLINT *lenp)
10218 {
10219 STMT *s;
10220
10221 if (stmt == SQL_NULL_HSTMT) {
10222 return SQL_INVALID_HANDLE;
10223 }
10224 s = (STMT *) stmt;
10225 if (lenp && !cursor) {
10226 *lenp = strlen((char *) s->cursorname);
10227 return SQL_SUCCESS;
10228 }
10229 if (cursor) {
10230 if (buflen > 0) {
10231 strncpy((char *) cursor, (char *) s->cursorname, buflen - 1);
10232 cursor[buflen - 1] = '\0';
10233 }
10234 if (lenp) {
10235 *lenp = min(strlen((char *) s->cursorname), buflen - 1);
10236 }
10237 }
10238 return SQL_SUCCESS;
10239 }
10240
10241 #ifndef WINTERFACE
10242 /**
10243 * Get cursor name of STMT.
10244 * @param stmt statement handle
10245 * @param cursor output buffer
10246 * @param buflen length of output buffer
10247 * @param lenp output length
10248 * @result ODBC error code
10249 */
10250
10251 SQLRETURN SQL_API
SQLGetCursorName(SQLHSTMT stmt,SQLCHAR * cursor,SQLSMALLINT buflen,SQLSMALLINT * lenp)10252 SQLGetCursorName(SQLHSTMT stmt, SQLCHAR *cursor, SQLSMALLINT buflen,
10253 SQLSMALLINT *lenp)
10254 {
10255 SQLRETURN ret;
10256
10257 HSTMT_LOCK(stmt);
10258 ret = drvgetcursorname(stmt, cursor, buflen, lenp);
10259 HSTMT_UNLOCK(stmt);
10260 return ret;
10261 }
10262 #endif
10263
10264 #ifdef WINTERFACE
10265 /**
10266 * Get cursor name of STMT (UNICODE version).
10267 * @param stmt statement handle
10268 * @param cursor output buffer
10269 * @param buflen length of output buffer
10270 * @param lenp output length
10271 * @result ODBC error code
10272 */
10273
10274 SQLRETURN SQL_API
SQLGetCursorNameW(SQLHSTMT stmt,SQLWCHAR * cursor,SQLSMALLINT buflen,SQLSMALLINT * lenp)10275 SQLGetCursorNameW(SQLHSTMT stmt, SQLWCHAR *cursor, SQLSMALLINT buflen,
10276 SQLSMALLINT *lenp)
10277 {
10278 SQLRETURN ret;
10279 SQLSMALLINT len = 0;
10280
10281 HSTMT_LOCK(stmt);
10282 ret = drvgetcursorname(stmt, (SQLCHAR *) cursor, buflen, &len);
10283 if (ret == SQL_SUCCESS) {
10284 SQLWCHAR *c = NULL;
10285
10286 if (cursor) {
10287 c = uc_from_utf((SQLCHAR *) cursor, len);
10288 if (!c) {
10289 ret = nomem((STMT *) stmt);
10290 goto done;
10291 }
10292 c[len] = 0;
10293 len = uc_strlen(c);
10294 if (buflen > 0) {
10295 uc_strncpy(cursor, c, buflen - 1);
10296 cursor[buflen - 1] = 0;
10297 }
10298 uc_free(c);
10299 }
10300 if (lenp) {
10301 *lenp = min(len, buflen - 1);
10302 }
10303 }
10304 done:
10305 HSTMT_UNLOCK(stmt);
10306 return ret;
10307 }
10308 #endif
10309
10310 /**
10311 * Internal function to set cursor name on STMT.
10312 * @param stmt statement handle
10313 * @param cursor new cursor name
10314 * @param len length of cursor name or SQL_NTS
10315 * @result ODBC error code
10316 */
10317
10318 static SQLRETURN
drvsetcursorname(SQLHSTMT stmt,SQLCHAR * cursor,SQLSMALLINT len)10319 drvsetcursorname(SQLHSTMT stmt, SQLCHAR *cursor, SQLSMALLINT len)
10320 {
10321 STMT *s;
10322
10323 if (stmt == SQL_NULL_HSTMT) {
10324 return SQL_INVALID_HANDLE;
10325 }
10326 s = (STMT *) stmt;
10327 if (!cursor ||
10328 !((cursor[0] >= 'A' && cursor[0] <= 'Z') ||
10329 (cursor[0] >= 'a' && cursor[0] <= 'z'))) {
10330 setstat(s, -1, "invalid cursor name", (*s->ov3) ? "HYC00" : "S1C00");
10331 return SQL_ERROR;
10332 }
10333 if (len == SQL_NTS) {
10334 len = sizeof (s->cursorname) - 1;
10335 } else {
10336 len = min(sizeof (s->cursorname) - 1, len);
10337 }
10338 strncpy((char *) s->cursorname, (char *) cursor, len);
10339 s->cursorname[len] = '\0';
10340 return SQL_SUCCESS;
10341 }
10342
10343 #ifndef WINTERFACE
10344 /**
10345 * Set cursor name on STMT.
10346 * @param stmt statement handle
10347 * @param cursor new cursor name
10348 * @param len length of cursor name or SQL_NTS
10349 * @result ODBC error code
10350 */
10351
10352 SQLRETURN SQL_API
SQLSetCursorName(SQLHSTMT stmt,SQLCHAR * cursor,SQLSMALLINT len)10353 SQLSetCursorName(SQLHSTMT stmt, SQLCHAR *cursor, SQLSMALLINT len)
10354 {
10355 SQLRETURN ret;
10356
10357 HSTMT_LOCK(stmt);
10358 ret = drvsetcursorname(stmt, cursor, len);
10359 HSTMT_UNLOCK(stmt);
10360 return ret;
10361 }
10362 #endif
10363
10364 #ifdef WINTERFACE
10365 /**
10366 * Set cursor name on STMT (UNICODE version).
10367 * @param stmt statement handle
10368 * @param cursor new cursor name
10369 * @param len length of cursor name or SQL_NTS
10370 * @result ODBC error code
10371 */
10372
10373 SQLRETURN SQL_API
SQLSetCursorNameW(SQLHSTMT stmt,SQLWCHAR * cursor,SQLSMALLINT len)10374 SQLSetCursorNameW(SQLHSTMT stmt, SQLWCHAR *cursor, SQLSMALLINT len)
10375 {
10376 char *c = NULL;
10377 SQLRETURN ret;
10378
10379 HSTMT_LOCK(stmt);
10380 if (cursor) {
10381 c = uc_to_utf_c(cursor, len);
10382 if (!c) {
10383 ret = nomem((STMT *) stmt);
10384 goto done;
10385 }
10386 }
10387 ret = drvsetcursorname(stmt, (SQLCHAR *) c, SQL_NTS);
10388 done:
10389 HSTMT_UNLOCK(stmt);
10390 uc_free(c);
10391 return ret;
10392 }
10393 #endif
10394
10395 /**
10396 * Close open cursor.
10397 * @param stmt statement handle
10398 * @return ODBC error code
10399 */
10400
10401 SQLRETURN SQL_API
SQLCloseCursor(SQLHSTMT stmt)10402 SQLCloseCursor(SQLHSTMT stmt)
10403 {
10404 return drvfreestmt(stmt, SQL_CLOSE);
10405 }
10406
10407 /**
10408 * Allocate a HENV, HDBC, or HSTMT handle.
10409 * @param type handle type
10410 * @param input input handle (HENV, HDBC)
10411 * @param output pointer to output handle (HENV, HDBC, HSTMT)
10412 * @result ODBC error code
10413 */
10414
10415 SQLRETURN SQL_API
SQLAllocHandle(SQLSMALLINT type,SQLHANDLE input,SQLHANDLE * output)10416 SQLAllocHandle(SQLSMALLINT type, SQLHANDLE input, SQLHANDLE *output)
10417 {
10418 SQLRETURN ret;
10419
10420 switch (type) {
10421 case SQL_HANDLE_ENV:
10422 ret = drvallocenv((SQLHENV *) output);
10423 if (ret == SQL_SUCCESS) {
10424 ENV *e = (ENV *) *output;
10425
10426 if (e && e->magic == ENV_MAGIC) {
10427 e->ov3 = 1;
10428 }
10429 }
10430 return ret;
10431 case SQL_HANDLE_DBC:
10432 return drvallocconnect((SQLHENV) input, (SQLHDBC *) output);
10433 case SQL_HANDLE_STMT:
10434 HDBC_LOCK((SQLHDBC) input);
10435 ret = drvallocstmt((SQLHDBC) input, (SQLHSTMT *) output);
10436 HDBC_UNLOCK((SQLHDBC) input);
10437 return ret;
10438 }
10439 return SQL_ERROR;
10440 }
10441
10442 /**
10443 * Free a HENV, HDBC, or HSTMT handle.
10444 * @param type handle type
10445 * @param h handle (HENV, HDBC, or HSTMT)
10446 * @result ODBC error code
10447 */
10448
10449 SQLRETURN SQL_API
SQLFreeHandle(SQLSMALLINT type,SQLHANDLE h)10450 SQLFreeHandle(SQLSMALLINT type, SQLHANDLE h)
10451 {
10452 switch (type) {
10453 case SQL_HANDLE_ENV:
10454 return drvfreeenv((SQLHENV) h);
10455 case SQL_HANDLE_DBC:
10456 return drvfreeconnect((SQLHDBC) h);
10457 case SQL_HANDLE_STMT:
10458 return drvfreestmt((SQLHSTMT) h, SQL_DROP);
10459 }
10460 return SQL_ERROR;
10461 }
10462
10463 /**
10464 * Free dynamically allocated column descriptions of STMT.
10465 * @param s statement pointer
10466 */
10467
10468 static void
freedyncols(STMT * s)10469 freedyncols(STMT *s)
10470 {
10471 if (s->dyncols) {
10472 int i;
10473
10474 for (i = 0; i < s->dcols; i++) {
10475 freep(&s->dyncols[i].typename);
10476 }
10477 if (s->cols == s->dyncols) {
10478 s->cols = NULL;
10479 s->ncols = 0;
10480 }
10481 freep(&s->dyncols);
10482 }
10483 s->dcols = 0;
10484 }
10485
10486 /**
10487 * Free statement's result.
10488 * @param s statement pointer
10489 * @param clrcols flag to clear column information
10490 *
10491 * The result rows are free'd using the rowfree function pointer.
10492 * If clrcols is greater than zero, then column bindings and dynamic column
10493 * descriptions are free'd.
10494 * If clrcols is less than zero, then dynamic column descriptions are free'd.
10495 */
10496
10497 static void
freeresult(STMT * s,int clrcols)10498 freeresult(STMT *s, int clrcols)
10499 {
10500 #if (HAVE_ENCDEC)
10501 freep(&s->bincache);
10502 freep(&s->hexcache);
10503 s->bincell = NULL;
10504 #endif
10505 if (s->rows) {
10506 if (s->rowfree) {
10507 s->rowfree(s->rows);
10508 s->rowfree = NULL;
10509 }
10510 s->rows = NULL;
10511 }
10512 s->nrows = -1;
10513 if (clrcols > 0) {
10514 freep(&s->bindcols);
10515 s->nbindcols = 0;
10516 }
10517 if (clrcols) {
10518 freedyncols(s);
10519 s->cols = NULL;
10520 s->ncols = 0;
10521 s->nowchar[1] = 0;
10522 }
10523 }
10524
10525 /**
10526 * Reset bound columns to unbound state.
10527 * @param s statement pointer
10528 */
10529
10530 static void
unbindcols(STMT * s)10531 unbindcols(STMT *s)
10532 {
10533 int i;
10534
10535 for (i = 0; s->bindcols && i < s->nbindcols; i++) {
10536 s->bindcols[i].type = SQL_UNKNOWN_TYPE;
10537 s->bindcols[i].max = 0;
10538 s->bindcols[i].lenp = NULL;
10539 s->bindcols[i].valp = NULL;
10540 s->bindcols[i].index = i;
10541 s->bindcols[i].offs = 0;
10542 }
10543 }
10544
10545 /**
10546 * Reallocate space for bound columns.
10547 * @param s statement pointer
10548 * @param ncols number of columns
10549 * @result ODBC error code
10550 */
10551
10552 static SQLRETURN
mkbindcols(STMT * s,int ncols)10553 mkbindcols(STMT *s, int ncols)
10554 {
10555 if (s->bindcols) {
10556 if (s->nbindcols < ncols) {
10557 int i;
10558 BINDCOL *bindcols =
10559 xrealloc(s->bindcols, ncols * sizeof (BINDCOL));
10560
10561 if (!bindcols) {
10562 return nomem(s);
10563 }
10564 for (i = s->nbindcols; i < ncols; i++) {
10565 bindcols[i].type = SQL_UNKNOWN_TYPE;
10566 bindcols[i].max = 0;
10567 bindcols[i].lenp = NULL;
10568 bindcols[i].valp = NULL;
10569 bindcols[i].index = i;
10570 bindcols[i].offs = 0;
10571 }
10572 s->bindcols = bindcols;
10573 s->nbindcols = ncols;
10574 }
10575 } else if (ncols > 0) {
10576 s->bindcols = (BINDCOL *) xmalloc(ncols * sizeof (BINDCOL));
10577 if (!s->bindcols) {
10578 return nomem(s);
10579 }
10580 s->nbindcols = ncols;
10581 unbindcols(s);
10582 }
10583 return SQL_SUCCESS;
10584 }
10585
10586 /**
10587 * Internal function to retrieve row data, used by SQLFetch() and
10588 * friends and SQLGetData().
10589 * @param s statement pointer
10590 * @param col column number, 0 based
10591 * @param otype output data type
10592 * @param val output buffer
10593 * @param len length of output buffer
10594 * @param lenp output length
10595 * @param partial flag for partial data retrieval
10596 * @result ODBC error code
10597 */
10598
10599 static SQLRETURN
getrowdata(STMT * s,SQLUSMALLINT col,SQLSMALLINT otype,SQLPOINTER val,SQLLEN len,SQLLEN * lenp,int partial)10600 getrowdata(STMT *s, SQLUSMALLINT col, SQLSMALLINT otype,
10601 SQLPOINTER val, SQLLEN len, SQLLEN *lenp, int partial)
10602 {
10603 char **data, valdummy[16];
10604 SQLLEN dummy;
10605 SQLINTEGER *ilenp = NULL;
10606 int valnull = 0;
10607 int type = otype;
10608 SQLRETURN sret = SQL_NO_DATA;
10609
10610 if (!lenp) {
10611 lenp = &dummy;
10612 }
10613 /* workaround for JDK 1.7.0 on x86_64 */
10614 if (((SQLINTEGER *) lenp) + 1 == (SQLINTEGER *) val) {
10615 ilenp = (SQLINTEGER *) lenp;
10616 lenp = &dummy;
10617 }
10618 if (col >= s->ncols) {
10619 setstat(s, -1, "invalid column", (*s->ov3) ? "07009" : "S1002");
10620 return SQL_ERROR;
10621 }
10622 if (s->retr_data != SQL_RD_ON) {
10623 return SQL_SUCCESS;
10624 }
10625 if (!s->rows) {
10626 *lenp = SQL_NULL_DATA;
10627 goto done;
10628 }
10629 if (s->rowp < 0 || s->rowp >= s->nrows) {
10630 *lenp = SQL_NULL_DATA;
10631 goto done;
10632 }
10633 type = mapdeftype(type, s->cols[col].type, s->cols[col].nosign ? 1 : 0,
10634 s->nowchar[0]);
10635
10636 #if (defined(_WIN32) || defined(_WIN64)) && defined(WINTERFACE)
10637 /* MS Access hack part 3 (map SQL_C_DEFAULT to SQL_C_CHAR) */
10638 if (type == SQL_C_WCHAR && otype == SQL_C_DEFAULT) {
10639 type = SQL_C_CHAR;
10640 }
10641 #endif
10642
10643 #if (HAVE_ENCDEC)
10644 if (type == SQL_C_CHAR) {
10645 switch (s->cols[col].type) {
10646 case SQL_BINARY:
10647 case SQL_VARBINARY:
10648 case SQL_LONGVARBINARY:
10649 type = SQL_C_BINARY;
10650 break;
10651 }
10652 #ifdef WCHARSUPPORT
10653 } else if (type == SQL_C_WCHAR) {
10654 switch (s->cols[col].type) {
10655 case SQL_BINARY:
10656 case SQL_VARBINARY:
10657 case SQL_LONGVARBINARY:
10658 type = SQL_C_BINARY;
10659 break;
10660 }
10661 #endif
10662 }
10663 #endif
10664 data = s->rows + s->ncols + (s->rowp * s->ncols) + col;
10665 if (!val) {
10666 valnull = 1;
10667 val = (SQLPOINTER) valdummy;
10668 }
10669 if (*data == NULL) {
10670 *lenp = SQL_NULL_DATA;
10671 switch (type) {
10672 case SQL_C_UTINYINT:
10673 case SQL_C_TINYINT:
10674 case SQL_C_STINYINT:
10675 #ifdef SQL_BIT
10676 case SQL_C_BIT:
10677 #endif
10678 *((char *) val) = 0;
10679 break;
10680 case SQL_C_USHORT:
10681 case SQL_C_SHORT:
10682 case SQL_C_SSHORT:
10683 *((short *) val) = 0;
10684 break;
10685 case SQL_C_ULONG:
10686 case SQL_C_LONG:
10687 case SQL_C_SLONG:
10688 *((SQLINTEGER *) val) = 0;
10689 break;
10690 case SQL_C_FLOAT:
10691 *((float *) val) = 0;
10692 break;
10693 case SQL_C_DOUBLE:
10694 *((double *) val) = 0;
10695 break;
10696 case SQL_C_BINARY:
10697 case SQL_C_CHAR:
10698 #ifdef WCHARSUPPORT
10699 case SQL_C_WCHAR:
10700 if (type == SQL_C_WCHAR) {
10701 *((SQLWCHAR *) val) = '\0';
10702 } else {
10703 *((char *) val) = '\0';
10704 }
10705 #else
10706 *((char *) val) = '\0';
10707 #endif
10708 break;
10709 #ifdef SQL_C_TYPE_DATE
10710 case SQL_C_TYPE_DATE:
10711 #endif
10712 case SQL_C_DATE:
10713 memset((DATE_STRUCT *) val, 0, sizeof (DATE_STRUCT));
10714 break;
10715 #ifdef SQL_C_TYPE_TIME
10716 case SQL_C_TYPE_TIME:
10717 #endif
10718 case SQL_C_TIME:
10719 memset((TIME_STRUCT *) val, 0, sizeof (TIME_STRUCT));
10720 break;
10721 #ifdef SQL_C_TYPE_TIMESTAMP
10722 case SQL_C_TYPE_TIMESTAMP:
10723 #endif
10724 case SQL_C_TIMESTAMP:
10725 memset((TIMESTAMP_STRUCT *) val, 0, sizeof (TIMESTAMP_STRUCT));
10726 break;
10727 default:
10728 return SQL_ERROR;
10729 }
10730 } else {
10731 char *endp = NULL;
10732
10733 switch (type) {
10734 case SQL_C_UTINYINT:
10735 case SQL_C_TINYINT:
10736 case SQL_C_STINYINT:
10737 *((char *) val) = strtol(*data, &endp, 0);
10738 if (endp && endp == *data) {
10739 *lenp = SQL_NULL_DATA;
10740 } else {
10741 *lenp = sizeof (char);
10742 }
10743 break;
10744 #ifdef SQL_BIT
10745 case SQL_C_BIT:
10746 *((char *) val) = getbool(*data);
10747 *lenp = sizeof (char);
10748 break;
10749 #endif
10750 case SQL_C_USHORT:
10751 case SQL_C_SHORT:
10752 case SQL_C_SSHORT:
10753 *((short *) val) = strtol(*data, &endp, 0);
10754 if (endp && endp == *data) {
10755 *lenp = SQL_NULL_DATA;
10756 } else {
10757 *lenp = sizeof (short);
10758 }
10759 break;
10760 case SQL_C_ULONG:
10761 case SQL_C_LONG:
10762 case SQL_C_SLONG:
10763 *((SQLINTEGER *) val) = strtol(*data, &endp, 0);
10764 if (endp && endp == *data) {
10765 *lenp = SQL_NULL_DATA;
10766 } else {
10767 *lenp = sizeof (SQLINTEGER);
10768 }
10769 break;
10770 case SQL_C_FLOAT:
10771 *((float *) val) = ln_strtod(*data, &endp);
10772 if (endp && endp == *data) {
10773 *lenp = SQL_NULL_DATA;
10774 } else {
10775 *lenp = sizeof (float);
10776 }
10777 break;
10778 case SQL_C_DOUBLE:
10779 *((double *) val) = ln_strtod(*data, &endp);
10780 if (endp && endp == *data) {
10781 *lenp = SQL_NULL_DATA;
10782 } else {
10783 *lenp = sizeof (double);
10784 }
10785 break;
10786 case SQL_C_BINARY:
10787 #if (HAVE_ENCDEC)
10788 {
10789 int dlen, offs = 0;
10790 char *bin;
10791
10792 if (*data == s->bincell && s->bincache) {
10793 bin = s->bincache;
10794 dlen = s->binlen;
10795 } else {
10796 freep(&s->bincache);
10797 freep(&s->hexcache);
10798 s->bincell = NULL;
10799 dlen = strlen(*data);
10800 bin = xmalloc(dlen + 1);
10801 if (!bin) {
10802 return nomem(s);
10803 }
10804 dlen = sqlite_decode_binary((unsigned char *) *data,
10805 (unsigned char *) bin);
10806 if (dlen < 0) {
10807 freep(&bin);
10808 setstat(s, -1, "error decoding binary data",
10809 (*s->ov3) ? "HY000" : "S1000");
10810 return SQL_ERROR;
10811 }
10812 s->bincache = bin;
10813 s->binlen = dlen;
10814 s->bincell = *data;
10815 }
10816 if (partial && len && s->bindcols) {
10817 if (s->bindcols[col].offs >= dlen) {
10818 *lenp = 0;
10819 if (!dlen && s->bindcols[col].offs == dlen) {
10820 s->bindcols[col].offs = 1;
10821 sret = SQL_SUCCESS;
10822 goto done;
10823 }
10824 s->bindcols[col].offs = 0;
10825 sret = SQL_NO_DATA;
10826 goto done;
10827 }
10828 offs = s->bindcols[col].offs;
10829 dlen -= offs;
10830 }
10831 if (val && !valnull && len) {
10832 memcpy(val, bin + offs, min(len, dlen));
10833 }
10834 if (valnull || len < 1) {
10835 *lenp = dlen;
10836 } else {
10837 *lenp = min(len, dlen);
10838 if (*lenp == len && *lenp != dlen) {
10839 *lenp = SQL_NO_TOTAL;
10840 }
10841 }
10842 if (partial && len && s->bindcols) {
10843 if (*lenp == SQL_NO_TOTAL) {
10844 *lenp = dlen;
10845 s->bindcols[col].offs += len;
10846 setstat(s, -1, "data right truncated", "01004");
10847 if (s->bindcols[col].lenp) {
10848 *s->bindcols[col].lenp = dlen;
10849 }
10850 sret = SQL_SUCCESS_WITH_INFO;
10851 goto done;
10852 }
10853 s->bindcols[col].offs += *lenp;
10854 }
10855 if (*lenp == SQL_NO_TOTAL) {
10856 *lenp = dlen;
10857 setstat(s, -1, "data right truncated", "01004");
10858 sret = SQL_SUCCESS_WITH_INFO;
10859 goto done;
10860 }
10861 break;
10862 }
10863 #endif
10864 #ifdef WCHARSUPPORT
10865 case SQL_C_WCHAR:
10866 #endif
10867 case SQL_C_CHAR: {
10868 int doz, zlen = len - 1;
10869 int dlen = strlen(*data);
10870 int offs = 0;
10871 #ifdef WCHARSUPPORT
10872 SQLWCHAR *ucdata = NULL;
10873 #endif
10874
10875 #if (defined(_WIN32) || defined(_WIN64)) && defined(WINTERFACE)
10876 /* MS Access hack part 2 (reserved error -7748) */
10877 if (!valnull &&
10878 (s->cols == statSpec2P || s->cols == statSpec3P) &&
10879 type == SQL_C_WCHAR) {
10880 if (len > 0 && len <= sizeof (SQLWCHAR)) {
10881 ((char *) val)[0] = data[0][0];
10882 memset((char *) val + 1, 0, len - 1);
10883 *lenp = 1;
10884 sret = SQL_SUCCESS;
10885 goto done;
10886 }
10887 }
10888 #endif
10889
10890 #ifdef WCHARSUPPORT
10891 switch (type) {
10892 case SQL_C_CHAR:
10893 doz = 1;
10894 break;
10895 case SQL_C_WCHAR:
10896 doz = sizeof (SQLWCHAR);
10897 break;
10898 default:
10899 doz = 0;
10900 break;
10901 }
10902 if (type == SQL_C_WCHAR) {
10903 ucdata = uc_from_utf((SQLCHAR *) *data, dlen);
10904 if (!ucdata) {
10905 return nomem(s);
10906 }
10907 dlen = uc_strlen(ucdata) * sizeof (SQLWCHAR);
10908 }
10909 #else
10910 doz = type == SQL_C_CHAR ? 1 : 0;
10911 #endif
10912 if (partial && len && s->bindcols) {
10913 if (s->bindcols[col].offs >= dlen) {
10914 #ifdef WCHARSUPPORT
10915 uc_free(ucdata);
10916 #endif
10917 *lenp = 0;
10918 if (doz && val) {
10919 #ifdef WCHARSUPPORT
10920 if (type == SQL_C_WCHAR) {
10921 ((SQLWCHAR *) val)[0] = 0;
10922 } else {
10923 ((char *) val)[0] = '\0';
10924 }
10925 #else
10926 ((char *) val)[0] = '\0';
10927 #endif
10928 }
10929 if (!dlen && s->bindcols[col].offs == dlen) {
10930 s->bindcols[col].offs = 1;
10931 sret = SQL_SUCCESS;
10932 goto done;
10933 }
10934 s->bindcols[col].offs = 0;
10935 sret = SQL_NO_DATA;
10936 goto done;
10937 }
10938 offs = s->bindcols[col].offs;
10939 dlen -= offs;
10940 }
10941 if (val && !valnull && len) {
10942 #ifdef WCHARSUPPORT
10943 if (type == SQL_C_WCHAR) {
10944 uc_strncpy(val, ucdata + offs / sizeof (SQLWCHAR),
10945 (len - doz) / sizeof (SQLWCHAR));
10946 } else {
10947 strncpy(val, *data + offs, len - doz);
10948 }
10949 #else
10950 strncpy(val, *data + offs, len - doz);
10951 #endif
10952 }
10953 if (valnull || len < 1) {
10954 *lenp = dlen;
10955 } else {
10956 *lenp = min(len - doz, dlen);
10957 if (*lenp == len - doz && *lenp != dlen) {
10958 *lenp = SQL_NO_TOTAL;
10959 } else if (*lenp < zlen) {
10960 zlen = *lenp;
10961 }
10962 }
10963 if (len && !valnull && doz) {
10964 #ifdef WCHARSUPPORT
10965 if (type == SQL_C_WCHAR) {
10966 ((SQLWCHAR *) val)[zlen / sizeof (SQLWCHAR)] = 0;
10967 } else {
10968 ((char *) val)[zlen] = '\0';
10969 }
10970 #else
10971 ((char *) val)[zlen] = '\0';
10972 #endif
10973 }
10974 #ifdef WCHARSUPPORT
10975 uc_free(ucdata);
10976 #endif
10977 if (partial && len && s->bindcols) {
10978 if (*lenp == SQL_NO_TOTAL) {
10979 *lenp = dlen;
10980 s->bindcols[col].offs += len - doz;
10981 setstat(s, -1, "data right truncated", "01004");
10982 if (s->bindcols[col].lenp) {
10983 *s->bindcols[col].lenp = dlen;
10984 }
10985 sret = SQL_SUCCESS_WITH_INFO;
10986 goto done;
10987 }
10988 s->bindcols[col].offs += *lenp;
10989 }
10990 if (*lenp == SQL_NO_TOTAL) {
10991 *lenp = dlen;
10992 setstat(s, -1, "data right truncated", "01004");
10993 sret = SQL_SUCCESS_WITH_INFO;
10994 goto done;
10995 }
10996 break;
10997 }
10998 #ifdef SQL_C_TYPE_DATE
10999 case SQL_C_TYPE_DATE:
11000 #endif
11001 case SQL_C_DATE:
11002 if (str2date(*data, (DATE_STRUCT *) val) < 0) {
11003 *lenp = SQL_NULL_DATA;
11004 } else {
11005 *lenp = sizeof (DATE_STRUCT);
11006 }
11007 break;
11008 #ifdef SQL_C_TYPE_TIME
11009 case SQL_C_TYPE_TIME:
11010 #endif
11011 case SQL_C_TIME:
11012 if (str2time(*data, (TIME_STRUCT *) val) < 0) {
11013 *lenp = SQL_NULL_DATA;
11014 } else {
11015 *lenp = sizeof (TIME_STRUCT);
11016 }
11017 break;
11018 #ifdef SQL_C_TYPE_TIMESTAMP
11019 case SQL_C_TYPE_TIMESTAMP:
11020 #endif
11021 case SQL_C_TIMESTAMP:
11022 if (str2timestamp(*data, (TIMESTAMP_STRUCT *) val) < 0) {
11023 *lenp = SQL_NULL_DATA;
11024 } else {
11025 *lenp = sizeof (TIMESTAMP_STRUCT);
11026 }
11027 switch (s->cols[col].prec) {
11028 case 0:
11029 ((TIMESTAMP_STRUCT *) val)->fraction = 0;
11030 break;
11031 case 1:
11032 ((TIMESTAMP_STRUCT *) val)->fraction /= 100000000;
11033 ((TIMESTAMP_STRUCT *) val)->fraction *= 100000000;
11034 break;
11035 case 2:
11036 ((TIMESTAMP_STRUCT *) val)->fraction /= 10000000;
11037 ((TIMESTAMP_STRUCT *) val)->fraction *= 10000000;
11038 break;
11039 }
11040 break;
11041 default:
11042 return SQL_ERROR;
11043 }
11044 }
11045 sret = SQL_SUCCESS;
11046 done:
11047 if (ilenp) {
11048 *ilenp = *lenp;
11049 }
11050 return sret;
11051 }
11052
11053 /**
11054 * Internal bind C variable to column of result set.
11055 * @param stmt statement handle
11056 * @param col column number, starting at 1
11057 * @param type output type
11058 * @param val output buffer
11059 * @param max length of output buffer
11060 * @param lenp output length pointer
11061 * @result ODBC error code
11062 */
11063
11064 static SQLRETURN
drvbindcol(SQLHSTMT stmt,SQLUSMALLINT col,SQLSMALLINT type,SQLPOINTER val,SQLLEN max,SQLLEN * lenp)11065 drvbindcol(SQLHSTMT stmt, SQLUSMALLINT col, SQLSMALLINT type,
11066 SQLPOINTER val, SQLLEN max, SQLLEN *lenp)
11067 {
11068 STMT *s;
11069 int sz = 0;
11070
11071 if (stmt == SQL_NULL_HSTMT) {
11072 return SQL_INVALID_HANDLE;
11073 }
11074 s = (STMT *) stmt;
11075 if (col < 1) {
11076 if (col == 0 && s->bkmrk && type == SQL_C_BOOKMARK) {
11077 s->bkmrkcol.type = val ? type : SQL_UNKNOWN_TYPE;
11078 s->bkmrkcol.max = val ? sizeof (SQLINTEGER) : 0;
11079 s->bkmrkcol.lenp = val ? lenp : 0;
11080 s->bkmrkcol.valp = val;
11081 s->bkmrkcol.offs = 0;
11082 if (val && lenp) {
11083 *lenp = 0;
11084 }
11085 return SQL_SUCCESS;
11086 }
11087 setstat(s, -1, "invalid column", (*s->ov3) ? "07009" : "S1002");
11088 return SQL_ERROR;
11089 }
11090 if (mkbindcols(s, col) != SQL_SUCCESS) {
11091 return SQL_ERROR;
11092 }
11093 --col;
11094 if (type == SQL_C_DEFAULT) {
11095 type = mapdeftype(type, s->cols[col].type, 0,
11096 s->nowchar[0] || s->nowchar[1]);
11097 }
11098 switch (type) {
11099 case SQL_C_LONG:
11100 case SQL_C_ULONG:
11101 case SQL_C_SLONG:
11102 sz = sizeof (SQLINTEGER);
11103 break;
11104 case SQL_C_TINYINT:
11105 case SQL_C_UTINYINT:
11106 case SQL_C_STINYINT:
11107 sz = sizeof (SQLCHAR);
11108 break;
11109 case SQL_C_SHORT:
11110 case SQL_C_USHORT:
11111 case SQL_C_SSHORT:
11112 sz = sizeof (short);
11113 break;
11114 case SQL_C_FLOAT:
11115 sz = sizeof (SQLFLOAT);
11116 break;
11117 case SQL_C_DOUBLE:
11118 sz = sizeof (SQLDOUBLE);
11119 break;
11120 case SQL_C_TIMESTAMP:
11121 sz = sizeof (SQL_TIMESTAMP_STRUCT);
11122 break;
11123 case SQL_C_TIME:
11124 sz = sizeof (SQL_TIME_STRUCT);
11125 break;
11126 case SQL_C_DATE:
11127 sz = sizeof (SQL_DATE_STRUCT);
11128 break;
11129 case SQL_C_CHAR:
11130 break;
11131 #ifdef WCHARSUPPORT
11132 case SQL_C_WCHAR:
11133 break;
11134 #endif
11135 #ifdef SQL_C_TYPE_DATE
11136 case SQL_C_TYPE_DATE:
11137 sz = sizeof (SQL_DATE_STRUCT);
11138 break;
11139 #endif
11140 #ifdef SQL_C_TYPE_TIME
11141 case SQL_C_TYPE_TIME:
11142 sz = sizeof (SQL_TIME_STRUCT);
11143 break;
11144 #endif
11145 #ifdef SQL_C_TYPE_TIMESTAMP
11146 case SQL_C_TYPE_TIMESTAMP:
11147 sz = sizeof (SQL_TIMESTAMP_STRUCT);
11148 break;
11149 #endif
11150 #ifdef SQL_BIT
11151 case SQL_C_BIT:
11152 sz = sizeof (SQLCHAR);
11153 break;
11154 #endif
11155 #if (HAVE_ENCDEC)
11156 case SQL_C_BINARY:
11157 break;
11158 #endif
11159 default:
11160 if (val == NULL) {
11161 /* fall through, unbinding column */
11162 break;
11163 }
11164 setstat(s, -1, "invalid type %d", "HY003", type);
11165 return SQL_ERROR;
11166 }
11167 if (val == NULL) {
11168 /* unbind column */
11169 s->bindcols[col].type = SQL_UNKNOWN_TYPE;
11170 s->bindcols[col].max = 0;
11171 s->bindcols[col].lenp = NULL;
11172 s->bindcols[col].valp = NULL;
11173 s->bindcols[col].offs = 0;
11174 } else {
11175 if (sz == 0 && max < 0) {
11176 setstat(s, -1, "invalid length", "HY090");
11177 return SQL_ERROR;
11178 }
11179 s->bindcols[col].type = type;
11180 s->bindcols[col].max = (sz == 0) ? max : sz;
11181 s->bindcols[col].lenp = lenp;
11182 s->bindcols[col].valp = val;
11183 s->bindcols[col].offs = 0;
11184 if (lenp) {
11185 *lenp = 0;
11186 }
11187 }
11188 return SQL_SUCCESS;
11189 }
11190
11191 /**
11192 * Bind C variable to column of result set.
11193 * @param stmt statement handle
11194 * @param col column number, starting at 1
11195 * @param type output type
11196 * @param val output buffer
11197 * @param max length of output buffer
11198 * @param lenp output length pointer
11199 * @result ODBC error code
11200 */
11201
11202 SQLRETURN SQL_API
SQLBindCol(SQLHSTMT stmt,SQLUSMALLINT col,SQLSMALLINT type,SQLPOINTER val,SQLLEN max,SQLLEN * lenp)11203 SQLBindCol(SQLHSTMT stmt, SQLUSMALLINT col, SQLSMALLINT type,
11204 SQLPOINTER val, SQLLEN max, SQLLEN *lenp)
11205 {
11206 SQLRETURN ret;
11207
11208 HSTMT_LOCK(stmt);
11209 ret = drvbindcol(stmt, col, type, val, max, lenp);
11210 HSTMT_UNLOCK(stmt);
11211 return ret;
11212 }
11213
11214 /**
11215 * Columns for result set of SQLTables().
11216 */
11217
11218 static COL tableSpec2[] = {
11219 { "SYSTEM", "COLUMN", "TABLE_QUALIFIER", SCOL_VARCHAR, 50 },
11220 { "SYSTEM", "COLUMN", "TABLE_OWNER", SCOL_VARCHAR, 50 },
11221 { "SYSTEM", "COLUMN", "TABLE_NAME", SCOL_VARCHAR, 255 },
11222 { "SYSTEM", "COLUMN", "TABLE_TYPE", SCOL_VARCHAR, 50 },
11223 { "SYSTEM", "COLUMN", "REMARKS", SCOL_VARCHAR, 50 }
11224 };
11225
11226 static COL tableSpec3[] = {
11227 { "SYSTEM", "COLUMN", "TABLE_CAT", SCOL_VARCHAR, 50 },
11228 { "SYSTEM", "COLUMN", "TABLE_SCHEM", SCOL_VARCHAR, 50 },
11229 { "SYSTEM", "COLUMN", "TABLE_NAME", SCOL_VARCHAR, 255 },
11230 { "SYSTEM", "COLUMN", "TABLE_TYPE", SCOL_VARCHAR, 50 },
11231 { "SYSTEM", "COLUMN", "REMARKS", SCOL_VARCHAR, 50 }
11232 };
11233
11234 /**
11235 * Retrieve information on tables and/or views.
11236 * @param stmt statement handle
11237 * @param cat catalog name/pattern or NULL
11238 * @param catLen length of catalog name/pattern or SQL_NTS
11239 * @param schema schema name/pattern or NULL
11240 * @param schemaLen length of schema name/pattern or SQL_NTS
11241 * @param table table name/pattern or NULL
11242 * @param tableLen length of table name/pattern or SQL_NTS
11243 * @param type types of tables string or NULL
11244 * @param typeLen length of types of tables string or SQL_NTS
11245 * @result ODBC error code
11246 */
11247
11248 static SQLRETURN
drvtables(SQLHSTMT stmt,SQLCHAR * cat,SQLSMALLINT catLen,SQLCHAR * schema,SQLSMALLINT schemaLen,SQLCHAR * table,SQLSMALLINT tableLen,SQLCHAR * type,SQLSMALLINT typeLen)11249 drvtables(SQLHSTMT stmt,
11250 SQLCHAR *cat, SQLSMALLINT catLen,
11251 SQLCHAR *schema, SQLSMALLINT schemaLen,
11252 SQLCHAR *table, SQLSMALLINT tableLen,
11253 SQLCHAR *type, SQLSMALLINT typeLen)
11254 {
11255 SQLRETURN ret;
11256 STMT *s;
11257 DBC *d;
11258 int ncols, asize, rc, size, npatt;
11259 char *errp = NULL, tname[512];
11260 char *where = "(type = 'table' or type = 'view')";
11261
11262 ret = mkresultset(stmt, tableSpec2, array_size(tableSpec2),
11263 tableSpec3, array_size(tableSpec3), &asize);
11264 if (ret != SQL_SUCCESS) {
11265 return ret;
11266 }
11267 s = (STMT *) stmt;
11268 d = (DBC *) s->dbc;
11269 if (type && (typeLen > 0 || typeLen == SQL_NTS) && type[0] == '%') {
11270 int size = 3 * asize;
11271
11272 s->rows = xmalloc(size * sizeof (char *));
11273 if (!s->rows) {
11274 s->nrows = 0;
11275 return nomem(s);
11276 }
11277 memset(s->rows, 0, sizeof (char *) * size);
11278 s->ncols = asize;
11279 s->rows[s->ncols + 0] = "";
11280 s->rows[s->ncols + 1] = "";
11281 s->rows[s->ncols + 2] = "";
11282 s->rows[s->ncols + 3] = "TABLE";
11283 s->rows[s->ncols + 5] = "";
11284 s->rows[s->ncols + 6] = "";
11285 s->rows[s->ncols + 7] = "";
11286 s->rows[s->ncols + 8] = "VIEW";
11287 #ifdef MEMORY_DEBUG
11288 s->rowfree = xfree__;
11289 #else
11290 s->rowfree = free;
11291 #endif
11292 s->nrows = 2;
11293 s->rowp = -1;
11294 return SQL_SUCCESS;
11295 }
11296 if (cat && (catLen > 0 || catLen == SQL_NTS) && cat[0] == '%') {
11297 table = NULL;
11298 goto doit;
11299 }
11300 if (schema && (schemaLen > 0 || schemaLen == SQL_NTS) &&
11301 schema[0] == '%') {
11302 if ((!cat || catLen == 0 || !cat[0]) &&
11303 (!table || tableLen == 0 || !table[0])) {
11304 table = NULL;
11305 goto doit;
11306 }
11307 }
11308 if (type && (typeLen > 0 || typeLen == SQL_NTS) && type[0] != '\0') {
11309 char tmp[256], *t;
11310 int with_view = 0, with_table = 0;
11311
11312 if (typeLen == SQL_NTS) {
11313 strncpy(tmp, (char *) type, sizeof (tmp));
11314 tmp[sizeof (tmp) - 1] = '\0';
11315 } else {
11316 int len = min(sizeof (tmp) - 1, typeLen);
11317
11318 strncpy(tmp, (char *) type, len);
11319 tmp[len] = '\0';
11320 }
11321 t = tmp;
11322 while (*t) {
11323 *t = TOLOWER(*t);
11324 t++;
11325 }
11326 t = tmp;
11327 unescpat(t);
11328 while (t) {
11329 if (t[0] == '\'') {
11330 ++t;
11331 }
11332 if (strncmp(t, "table", 5) == 0) {
11333 with_table++;
11334 } else if (strncmp(t, "view", 4) == 0) {
11335 with_view++;
11336 }
11337 t = strchr(t, ',');
11338 if (t) {
11339 ++t;
11340 }
11341 }
11342 if (with_view && with_table) {
11343 /* where is already preset */
11344 } else if (with_view && !with_table) {
11345 where = "type = 'view'";
11346 } else if (!with_view && with_table) {
11347 where = "type = 'table'";
11348 } else {
11349 return SQL_SUCCESS;
11350 }
11351 }
11352 doit:
11353 if (!table) {
11354 size = 1;
11355 tname[0] = '%';
11356 } else {
11357 if (tableLen == SQL_NTS) {
11358 size = sizeof (tname) - 1;
11359 } else {
11360 size = min(sizeof (tname) - 1, tableLen);
11361 }
11362 strncpy(tname, (char *) table, size);
11363 }
11364 tname[size] = '\0';
11365 npatt = unescpat(tname);
11366 ret = starttran(s);
11367 if (ret != SQL_SUCCESS) {
11368 return ret;
11369 }
11370 #if defined(_WIN32) || defined(_WIN64)
11371 if (npatt) {
11372 rc = sqlite_get_table_printf(d->sqlite,
11373 "select %s as 'TABLE_QUALIFIER', "
11374 "%s as 'TABLE_OWNER', "
11375 "tbl_name as 'TABLE_NAME', "
11376 "upper(type) as 'TABLE_TYPE', "
11377 "NULL as 'REMARKS' "
11378 "from sqlite_master where %s "
11379 "and tbl_name like '%q'",
11380 &s->rows, &s->nrows, &ncols, &errp,
11381 d->xcelqrx ? "'main'" : "NULL",
11382 d->xcelqrx ? "''" : "NULL",
11383 where, tname);
11384 } else {
11385 rc = sqlite_get_table_printf(d->sqlite,
11386 "select %s as 'TABLE_QUALIFIER', "
11387 "%s as 'TABLE_OWNER', "
11388 "tbl_name as 'TABLE_NAME', "
11389 "upper(type) as 'TABLE_TYPE', "
11390 "NULL as 'REMARKS' "
11391 "from sqlite_master where %s "
11392 "and lower(tbl_name) = lower('%q')",
11393 &s->rows, &s->nrows, &ncols, &errp,
11394 d->xcelqrx ? "'main'" : "NULL",
11395 d->xcelqrx ? "''" : "NULL",
11396 where, tname);
11397 }
11398 #else
11399 if (npatt) {
11400 rc = sqlite_get_table_printf(d->sqlite,
11401 "select NULL as 'TABLE_QUALIFIER', "
11402 "NULL as 'TABLE_OWNER', "
11403 "tbl_name as 'TABLE_NAME', "
11404 "upper(type) as 'TABLE_TYPE', "
11405 "NULL as 'REMARKS' "
11406 "from sqlite_master where %s "
11407 "and tbl_name like '%q'",
11408 &s->rows, &s->nrows, &ncols, &errp,
11409 where, tname);
11410 } else {
11411 rc = sqlite_get_table_printf(d->sqlite,
11412 "select NULL as 'TABLE_QUALIFIER', "
11413 "NULL as 'TABLE_OWNER', "
11414 "tbl_name as 'TABLE_NAME', "
11415 "upper(type) as 'TABLE_TYPE', "
11416 "NULL as 'REMARKS' "
11417 "from sqlite_master where %s "
11418 "and lower(tbl_name) = lower('%q')",
11419 &s->rows, &s->nrows, &ncols, &errp,
11420 where, tname);
11421 }
11422 #endif
11423 if (rc == SQLITE_OK) {
11424 if (ncols != s->ncols) {
11425 freeresult(s, 0);
11426 s->nrows = 0;
11427 } else {
11428 s->rowfree = sqlite_free_table;
11429 }
11430 } else {
11431 s->nrows = 0;
11432 s->rows = NULL;
11433 s->rowfree = NULL;
11434 }
11435 if (errp) {
11436 sqlite_freemem(errp);
11437 errp = NULL;
11438 }
11439 s->rowp = -1;
11440 return SQL_SUCCESS;
11441 }
11442
11443 #ifndef WINTERFACE
11444 /**
11445 * Retrieve information on tables and/or views.
11446 * @param stmt statement handle
11447 * @param cat catalog name/pattern or NULL
11448 * @param catLen length of catalog name/pattern or SQL_NTS
11449 * @param schema schema name/pattern or NULL
11450 * @param schemaLen length of schema name/pattern or SQL_NTS
11451 * @param table table name/pattern or NULL
11452 * @param tableLen length of table name/pattern or SQL_NTS
11453 * @param type types of tables string or NULL
11454 * @param typeLen length of types of tables string or SQL_NTS
11455 * @result ODBC error code
11456 */
11457
11458 SQLRETURN SQL_API
SQLTables(SQLHSTMT stmt,SQLCHAR * cat,SQLSMALLINT catLen,SQLCHAR * schema,SQLSMALLINT schemaLen,SQLCHAR * table,SQLSMALLINT tableLen,SQLCHAR * type,SQLSMALLINT typeLen)11459 SQLTables(SQLHSTMT stmt,
11460 SQLCHAR *cat, SQLSMALLINT catLen,
11461 SQLCHAR *schema, SQLSMALLINT schemaLen,
11462 SQLCHAR *table, SQLSMALLINT tableLen,
11463 SQLCHAR *type, SQLSMALLINT typeLen)
11464 {
11465 SQLRETURN ret;
11466
11467 HSTMT_LOCK(stmt);
11468 ret = drvtables(stmt, cat, catLen, schema, schemaLen,
11469 table, tableLen, type, typeLen);
11470 HSTMT_UNLOCK(stmt);
11471 return ret;
11472 }
11473 #endif
11474
11475 #ifdef WINTERFACE
11476 /**
11477 * Retrieve information on tables and/or views.
11478 * @param stmt statement handle
11479 * @param cat catalog name/pattern or NULL
11480 * @param catLen length of catalog name/pattern or SQL_NTS
11481 * @param schema schema name/pattern or NULL
11482 * @param schemaLen length of schema name/pattern or SQL_NTS
11483 * @param table table name/pattern or NULL
11484 * @param tableLen length of table name/pattern or SQL_NTS
11485 * @param type types of tables string or NULL
11486 * @param typeLen length of types of tables string or SQL_NTS
11487 * @result ODBC error code
11488 */
11489
11490 SQLRETURN SQL_API
SQLTablesW(SQLHSTMT stmt,SQLWCHAR * cat,SQLSMALLINT catLen,SQLWCHAR * schema,SQLSMALLINT schemaLen,SQLWCHAR * table,SQLSMALLINT tableLen,SQLWCHAR * type,SQLSMALLINT typeLen)11491 SQLTablesW(SQLHSTMT stmt,
11492 SQLWCHAR *cat, SQLSMALLINT catLen,
11493 SQLWCHAR *schema, SQLSMALLINT schemaLen,
11494 SQLWCHAR *table, SQLSMALLINT tableLen,
11495 SQLWCHAR *type, SQLSMALLINT typeLen)
11496 {
11497 char *c = NULL, *s = NULL, *t = NULL, *y = NULL;
11498 SQLRETURN ret;
11499
11500 HSTMT_LOCK(stmt);
11501 if (cat) {
11502 c = uc_to_utf_c(cat, catLen);
11503 if (!c) {
11504 ret = nomem((STMT *) stmt);
11505 goto done;
11506 }
11507 }
11508 if (schema) {
11509 s = uc_to_utf_c(schema, schemaLen);
11510 if (!s) {
11511 ret = nomem((STMT *) stmt);
11512 goto done;
11513 }
11514 }
11515 if (table) {
11516 t = uc_to_utf_c(table, tableLen);
11517 if (!t) {
11518 ret = nomem((STMT *) stmt);
11519 goto done;
11520 }
11521 }
11522 if (type) {
11523 y = uc_to_utf_c(type, typeLen);
11524 if (!y) {
11525 ret = nomem((STMT *) stmt);
11526 goto done;
11527 }
11528 }
11529 ret = drvtables(stmt, (SQLCHAR *) c, SQL_NTS, (SQLCHAR *) s, SQL_NTS,
11530 (SQLCHAR *) t, SQL_NTS, (SQLCHAR *) y, SQL_NTS);
11531 done:
11532 HSTMT_UNLOCK(stmt);
11533 uc_free(y);
11534 uc_free(t);
11535 uc_free(s);
11536 uc_free(c);
11537 return ret;
11538 }
11539 #endif
11540
11541 /**
11542 * Columns for result set of SQLColumns().
11543 */
11544
11545 static COL colSpec2[] = {
11546 { "SYSTEM", "COLUMN", "TABLE_QUALIFIER", SCOL_VARCHAR, 50 },
11547 { "SYSTEM", "COLUMN", "TABLE_OWNER", SCOL_VARCHAR, 50 },
11548 { "SYSTEM", "COLUMN", "TABLE_NAME", SCOL_VARCHAR, 255 },
11549 { "SYSTEM", "COLUMN", "COLUMN_NAME", SCOL_VARCHAR, 255 },
11550 { "SYSTEM", "COLUMN", "DATA_TYPE", SQL_SMALLINT, 50 },
11551 { "SYSTEM", "COLUMN", "TYPE_NAME", SCOL_VARCHAR, 50 },
11552 { "SYSTEM", "COLUMN", "PRECISION", SQL_INTEGER, 50 },
11553 { "SYSTEM", "COLUMN", "LENGTH", SQL_INTEGER, 50 },
11554 { "SYSTEM", "COLUMN", "SCALE", SQL_SMALLINT, 50 },
11555 { "SYSTEM", "COLUMN", "RADIX", SQL_SMALLINT, 50 },
11556 { "SYSTEM", "COLUMN", "NULLABLE", SQL_SMALLINT, 50 },
11557 { "SYSTEM", "COLUMN", "REMARKS", SCOL_VARCHAR, 50 },
11558 { "SYSTEM", "COLUMN", "COLUMN_DEF", SCOL_VARCHAR, 50 },
11559 { "SYSTEM", "COLUMN", "SQL_DATA_TYPE", SQL_SMALLINT, 50 },
11560 { "SYSTEM", "COLUMN", "SQL_DATETIME_SUB", SQL_SMALLINT, 50 },
11561 { "SYSTEM", "COLUMN", "CHAR_OCTET_LENGTH", SQL_SMALLINT, 50 },
11562 { "SYSTEM", "COLUMN", "ORDINAL_POSITION", SQL_SMALLINT, 50 },
11563 { "SYSTEM", "COLUMN", "IS_NULLABLE", SCOL_VARCHAR, 50 }
11564 };
11565
11566 static COL colSpec3[] = {
11567 { "SYSTEM", "COLUMN", "TABLE_CAT", SCOL_VARCHAR, 50 },
11568 { "SYSTEM", "COLUMN", "TABLE_SCHEM", SCOL_VARCHAR, 50 },
11569 { "SYSTEM", "COLUMN", "TABLE_NAME", SCOL_VARCHAR, 255 },
11570 { "SYSTEM", "COLUMN", "COLUMN_NAME", SCOL_VARCHAR, 255 },
11571 { "SYSTEM", "COLUMN", "DATA_TYPE", SQL_SMALLINT, 50 },
11572 { "SYSTEM", "COLUMN", "TYPE_NAME", SCOL_VARCHAR, 50 },
11573 { "SYSTEM", "COLUMN", "COLUMN_SIZE", SQL_INTEGER, 50 },
11574 { "SYSTEM", "COLUMN", "BUFFER_LENGTH", SQL_INTEGER, 50 },
11575 { "SYSTEM", "COLUMN", "DECIMAL_DIGITS", SQL_SMALLINT, 50 },
11576 { "SYSTEM", "COLUMN", "NUM_PREC_RADIX", SQL_SMALLINT, 50 },
11577 { "SYSTEM", "COLUMN", "NULLABLE", SQL_SMALLINT, 50 },
11578 { "SYSTEM", "COLUMN", "REMARKS", SCOL_VARCHAR, 50 },
11579 { "SYSTEM", "COLUMN", "COLUMN_DEF", SCOL_VARCHAR, 50 },
11580 { "SYSTEM", "COLUMN", "SQL_DATA_TYPE", SQL_SMALLINT, 50 },
11581 { "SYSTEM", "COLUMN", "SQL_DATETIME_SUB", SQL_SMALLINT, 50 },
11582 { "SYSTEM", "COLUMN", "CHAR_OCTET_LENGTH", SQL_SMALLINT, 50 },
11583 { "SYSTEM", "COLUMN", "ORDINAL_POSITION", SQL_SMALLINT, 50 },
11584 { "SYSTEM", "COLUMN", "IS_NULLABLE", SCOL_VARCHAR, 50 }
11585 };
11586
11587 /**
11588 * Internal retrieve column information on table.
11589 * @param stmt statement handle
11590 * @param cat catalog name/pattern or NULL
11591 * @param catLen length of catalog name/pattern or SQL_NTS
11592 * @param schema schema name/pattern or NULL
11593 * @param schemaLen length of schema name/pattern or SQL_NTS
11594 * @param table table name/pattern or NULL
11595 * @param tableLen length of table name/pattern or SQL_NTS
11596 * @param col column name/pattern or NULL
11597 * @param colLen length of column name/pattern or SQL_NTS
11598 * @result ODBC error code
11599 */
11600
11601 static SQLRETURN
drvcolumns(SQLHSTMT stmt,SQLCHAR * cat,SQLSMALLINT catLen,SQLCHAR * schema,SQLSMALLINT schemaLen,SQLCHAR * table,SQLSMALLINT tableLen,SQLCHAR * col,SQLSMALLINT colLen)11602 drvcolumns(SQLHSTMT stmt,
11603 SQLCHAR *cat, SQLSMALLINT catLen,
11604 SQLCHAR *schema, SQLSMALLINT schemaLen,
11605 SQLCHAR *table, SQLSMALLINT tableLen,
11606 SQLCHAR *col, SQLSMALLINT colLen)
11607 {
11608 SQLRETURN sret;
11609 STMT *s;
11610 DBC *d;
11611 int ret, nrows, ncols, asize, i, k, roffs, namec;
11612 int tnrows, tncols, npatt;
11613 PTRDIFF_T size;
11614 char *errp = NULL, tname[512], cname[512], **rowp, **trows;
11615
11616 sret = mkresultset(stmt, colSpec2, array_size(colSpec2),
11617 colSpec3, array_size(colSpec3), &asize);
11618 if (sret != SQL_SUCCESS) {
11619 return sret;
11620 }
11621 s = (STMT *) stmt;
11622 d = (DBC *) s->dbc;
11623 if (!table) {
11624 size = 1;
11625 tname[0] = '%';
11626 } else {
11627 if (tableLen == SQL_NTS) {
11628 size = sizeof (tname) - 1;
11629 } else {
11630 size = min(sizeof (tname) - 1, tableLen);
11631 }
11632 strncpy(tname, (char *) table, size);
11633 }
11634 tname[size] = '\0';
11635 npatt = unescpat(tname);
11636 size = 0;
11637 if (col) {
11638 if (colLen == SQL_NTS) {
11639 size = sizeof (cname) - 1;
11640 } else {
11641 size = min(sizeof (cname) - 1, colLen);
11642 }
11643 strncpy(cname, (char *) col, size);
11644 }
11645 cname[size] = '\0';
11646 if (!strcmp(cname, "%")) {
11647 cname[0] = '\0';
11648 }
11649 sret = starttran(s);
11650 if (sret != SQL_SUCCESS) {
11651 return sret;
11652 }
11653 if (npatt) {
11654 ret = sqlite_get_table_printf(d->sqlite,
11655 "select tbl_name from sqlite_master "
11656 "where (type = 'table' or type = 'view')"
11657 " and tbl_name like '%q'",
11658 &trows, &tnrows, &tncols, &errp, tname);
11659 } else {
11660 ret = sqlite_get_table_printf(d->sqlite,
11661 "select tbl_name from sqlite_master "
11662 "where (type = 'table' or type = 'view')"
11663 " and lower(tbl_name) = lower('%q')",
11664 &trows, &tnrows, &tncols, &errp, tname);
11665 }
11666 if (ret != SQLITE_OK) {
11667 setstat(s, ret, "%s (%d)", (*s->ov3) ? "HY000" : "S1000",
11668 errp ? errp : "unknown error", ret);
11669 if (errp) {
11670 sqlite_freemem(errp);
11671 errp = NULL;
11672 }
11673 return SQL_ERROR;
11674 }
11675 /* pass 1; compute number of rows of result set */
11676 if (tncols * tnrows <= 0) {
11677 sqlite_free_table(trows);
11678 return SQL_SUCCESS;
11679 }
11680 size = 0;
11681 for (i = 1; i <= tnrows; i++) {
11682 ret = sqlite_get_table_printf(d->sqlite, "PRAGMA table_info('%q')",
11683 &rowp, &nrows, &ncols, &errp, trows[i]);
11684 if (ret != SQLITE_OK) {
11685 setstat(s, ret, "%s (%d)", (*s->ov3) ? "HY000" : "S1000",
11686 errp ? errp : "unknown error", ret);
11687 if (errp) {
11688 sqlite_freemem(errp);
11689 errp = NULL;
11690 }
11691 return SQL_ERROR;
11692 }
11693 if (errp) {
11694 sqlite_freemem(errp);
11695 errp = NULL;
11696 }
11697 if (ncols * nrows > 0) {
11698 namec = -1;
11699 for (k = 0; k < ncols; k++) {
11700 if (strcmp(rowp[k], "name") == 0) {
11701 namec = k;
11702 break;
11703 }
11704 }
11705 if (cname[0]) {
11706 for (k = 1; k <= nrows; k++) {
11707 if (namematch(rowp[k * ncols + namec], cname, 1)) {
11708 size++;
11709 }
11710 }
11711 } else {
11712 size += nrows;
11713 }
11714 }
11715 sqlite_free_table(rowp);
11716 }
11717 /* pass 2: fill result set */
11718 if (size <= 0) {
11719 sqlite_free_table(trows);
11720 return SQL_SUCCESS;
11721 }
11722 s->nrows = size;
11723 size = (size + 1) * asize;
11724 s->rows = xmalloc((size + 1) * sizeof (char *));
11725 if (!s->rows) {
11726 s->nrows = 0;
11727 sqlite_free_table(trows);
11728 return nomem(s);
11729 }
11730 s->rows[0] = (char *) size;
11731 s->rows += 1;
11732 memset(s->rows, 0, sizeof (char *) * size);
11733 s->rowfree = freerows;
11734 roffs = 1;
11735 for (i = 1; i <= tnrows; i++) {
11736 ret = sqlite_get_table_printf(d->sqlite, "PRAGMA table_info('%q')",
11737 &rowp, &nrows, &ncols, &errp, trows[i]);
11738 if (ret != SQLITE_OK) {
11739 setstat(s, ret, "%s (%d)", (*s->ov3) ? "HY000" : "S1000",
11740 errp ? errp : "unknown error", ret);
11741 if (errp) {
11742 sqlite_freemem(errp);
11743 errp = NULL;
11744 }
11745 sqlite_free_table(trows);
11746 return SQL_ERROR;
11747 }
11748 if (errp) {
11749 sqlite_freemem(errp);
11750 errp = NULL;
11751 }
11752 if (ncols * nrows > 0) {
11753 int m, mr, nr = nrows;
11754
11755 namec = -1;
11756 for (k = 0; k < ncols; k++) {
11757 if (strcmp(rowp[k], "name") == 0) {
11758 namec = k;
11759 break;
11760 }
11761 }
11762 if (cname[0]) {
11763 nr = 0;
11764 for (k = 1; k <= nrows; k++) {
11765 if (namematch(rowp[k * ncols + namec], cname, 1)) {
11766 nr++;
11767 }
11768 }
11769 }
11770 for (k = 0; k < nr; k++) {
11771 m = asize * (roffs + k);
11772 #if defined(_WIN32) || defined(_WIN64)
11773 s->rows[m + 0] = xstrdup(d->xcelqrx ? "main" : "");
11774 s->rows[m + 1] = xstrdup("");
11775 #else
11776 s->rows[m + 0] = xstrdup("");
11777 s->rows[m + 1] = xstrdup("");
11778 #endif
11779 s->rows[m + 2] = xstrdup(trows[i]);
11780 s->rows[m + 8] = xstrdup("10");
11781 s->rows[m + 9] = xstrdup("0");
11782 s->rows[m + 15] = xstrdup("16384");
11783 }
11784 for (k = 0; nr && k < ncols; k++) {
11785 if (strcmp(rowp[k], "cid") == 0) {
11786 for (mr = 0, m = 1; m <= nrows; m++) {
11787 char buf[256];
11788 int ir, coln = i;
11789
11790 if (cname[0] &&
11791 !namematch(rowp[m * ncols + namec], cname, 1)) {
11792 continue;
11793 }
11794 ir = asize * (roffs + mr);
11795 sscanf(rowp[m * ncols + k], "%d", &coln);
11796 sprintf(buf, "%d", coln + 1);
11797 s->rows[ir + 16] = xstrdup(buf);
11798 ++mr;
11799 }
11800 } else if (k == namec) {
11801 for (mr = 0, m = 1; m <= nrows; m++) {
11802 int ir;
11803
11804 if (cname[0] &&
11805 !namematch(rowp[m * ncols + namec], cname, 1)) {
11806 continue;
11807 }
11808 ir = asize * (roffs + mr);
11809 s->rows[ir + 3] = xstrdup(rowp[m * ncols + k]);
11810 ++mr;
11811 }
11812 } else if (strcmp(rowp[k], "notnull") == 0) {
11813 for (mr = 0, m = 1; m <= nrows; m++) {
11814 int ir;
11815
11816 if (cname[0] &&
11817 !namematch(rowp[m * ncols + namec], cname, 1)) {
11818 continue;
11819 }
11820 ir = asize * (roffs + mr);
11821 if (*rowp[m * ncols + k] != '0') {
11822 s->rows[ir + 10] = xstrdup(stringify(SQL_FALSE));
11823 } else {
11824 s->rows[ir + 10] = xstrdup(stringify(SQL_TRUE));
11825 }
11826 s->rows[ir + 17] =
11827 xstrdup((*rowp[m * ncols + k] != '0') ?
11828 "NO" : "YES");
11829 ++mr;
11830 }
11831 } else if (strcmp(rowp[k], "dflt_value") == 0) {
11832 for (mr = 0, m = 1; m <= nrows; m++) {
11833 char *dflt = rowp[m * ncols + k];
11834 int ir;
11835
11836 if (cname[0] &&
11837 !namematch(rowp[m * ncols + namec], cname, 1)) {
11838 continue;
11839 }
11840 ir = asize * (roffs + mr);
11841 s->rows[ir + 12] = xstrdup(dflt ? dflt : "NULL");
11842 ++mr;
11843 }
11844 } else if (strcmp(rowp[k], "type") == 0) {
11845 for (mr = 0, m = 1; m <= nrows; m++) {
11846 char *typename = rowp[m * ncols + k];
11847 int sqltype, mm, dd, ir;
11848 char buf[256];
11849
11850 if (cname[0] &&
11851 !namematch(rowp[m * ncols + namec], cname, 1)) {
11852 continue;
11853 }
11854 ir = asize * (roffs + mr);
11855 s->rows[ir + 5] = xstrdup(typename);
11856 sqltype = mapsqltype(typename, NULL, *s->ov3,
11857 s->nowchar[0]);
11858 getmd(typename, sqltype, &mm, &dd);
11859 #ifdef SQL_LONGVARCHAR
11860 if (sqltype == SQL_VARCHAR && mm > 255) {
11861 sqltype = SQL_LONGVARCHAR;
11862 }
11863 #endif
11864 #ifdef WINTERFACE
11865 #ifdef SQL_WLONGVARCHAR
11866 if (sqltype == SQL_WVARCHAR && mm > 255) {
11867 sqltype = SQL_WLONGVARCHAR;
11868 }
11869 #endif
11870 #endif
11871 #if (HAVE_ENCDEC)
11872 if (sqltype == SQL_VARBINARY && mm > 255) {
11873 sqltype = SQL_LONGVARBINARY;
11874 }
11875 #endif
11876 sprintf(buf, "%d", sqltype);
11877 s->rows[ir + 4] = xstrdup(buf);
11878 s->rows[ir + 13] = xstrdup(buf);
11879 sprintf(buf, "%d", mm);
11880 s->rows[ir + 7] = xstrdup(buf);
11881 sprintf(buf, "%d", dd);
11882 s->rows[ir + 6] = xstrdup(buf);
11883 ++mr;
11884 }
11885 }
11886 }
11887 roffs += nr;
11888 }
11889 sqlite_free_table(rowp);
11890 }
11891 sqlite_free_table(trows);
11892 return SQL_SUCCESS;
11893 }
11894
11895 #ifndef WINTERFACE
11896 /**
11897 * Retrieve column information on table.
11898 * @param stmt statement handle
11899 * @param cat catalog name/pattern or NULL
11900 * @param catLen length of catalog name/pattern or SQL_NTS
11901 * @param schema schema name/pattern or NULL
11902 * @param schemaLen length of schema name/pattern or SQL_NTS
11903 * @param table table name/pattern or NULL
11904 * @param tableLen length of table name/pattern or SQL_NTS
11905 * @param col column name/pattern or NULL
11906 * @param colLen length of column name/pattern or SQL_NTS
11907 * @result ODBC error code
11908 */
11909
11910 SQLRETURN SQL_API
SQLColumns(SQLHSTMT stmt,SQLCHAR * cat,SQLSMALLINT catLen,SQLCHAR * schema,SQLSMALLINT schemaLen,SQLCHAR * table,SQLSMALLINT tableLen,SQLCHAR * col,SQLSMALLINT colLen)11911 SQLColumns(SQLHSTMT stmt,
11912 SQLCHAR *cat, SQLSMALLINT catLen,
11913 SQLCHAR *schema, SQLSMALLINT schemaLen,
11914 SQLCHAR *table, SQLSMALLINT tableLen,
11915 SQLCHAR *col, SQLSMALLINT colLen)
11916 {
11917 SQLRETURN ret;
11918
11919 HSTMT_LOCK(stmt);
11920 ret = drvcolumns(stmt, cat, catLen, schema, schemaLen,
11921 table, tableLen, col, colLen);
11922 HSTMT_UNLOCK(stmt);
11923 return ret;
11924 }
11925 #endif
11926
11927 #ifdef WINTERFACE
11928 /**
11929 * Retrieve column information on table (UNICODE version).
11930 * @param stmt statement handle
11931 * @param cat catalog name/pattern or NULL
11932 * @param catLen length of catalog name/pattern or SQL_NTS
11933 * @param schema schema name/pattern or NULL
11934 * @param schemaLen length of schema name/pattern or SQL_NTS
11935 * @param table table name/pattern or NULL
11936 * @param tableLen length of table name/pattern or SQL_NTS
11937 * @param col column name/pattern or NULL
11938 * @param colLen length of column name/pattern or SQL_NTS
11939 * @result ODBC error code
11940 */
11941
11942 SQLRETURN SQL_API
SQLColumnsW(SQLHSTMT stmt,SQLWCHAR * cat,SQLSMALLINT catLen,SQLWCHAR * schema,SQLSMALLINT schemaLen,SQLWCHAR * table,SQLSMALLINT tableLen,SQLWCHAR * col,SQLSMALLINT colLen)11943 SQLColumnsW(SQLHSTMT stmt,
11944 SQLWCHAR *cat, SQLSMALLINT catLen,
11945 SQLWCHAR *schema, SQLSMALLINT schemaLen,
11946 SQLWCHAR *table, SQLSMALLINT tableLen,
11947 SQLWCHAR *col, SQLSMALLINT colLen)
11948 {
11949 char *c = NULL, *s = NULL, *t = NULL, *k = NULL;
11950 SQLRETURN ret;
11951
11952 HSTMT_LOCK(stmt);
11953 if (cat) {
11954 c = uc_to_utf_c(cat, catLen);
11955 if (!c) {
11956 ret = nomem((STMT *) stmt);
11957 goto done;
11958 }
11959 }
11960 if (schema) {
11961 s = uc_to_utf_c(schema, schemaLen);
11962 if (!s) {
11963 ret = nomem((STMT *) stmt);
11964 goto done;
11965 }
11966 }
11967 if (table) {
11968 t = uc_to_utf_c(table, tableLen);
11969 if (!t) {
11970 ret = nomem((STMT *) stmt);
11971 goto done;
11972 }
11973 }
11974 if (col) {
11975 k = uc_to_utf_c(col, colLen);
11976 if (!k) {
11977 ret = nomem((STMT *) stmt);
11978 goto done;
11979 }
11980 }
11981 ret = drvcolumns(stmt, (SQLCHAR *) c, SQL_NTS, (SQLCHAR *) s, SQL_NTS,
11982 (SQLCHAR *) t, SQL_NTS, (SQLCHAR *) k, SQL_NTS);
11983 done:
11984 HSTMT_UNLOCK(stmt);
11985 uc_free(k);
11986 uc_free(t);
11987 uc_free(s);
11988 uc_free(c);
11989 return ret;
11990
11991 }
11992 #endif
11993
11994 /**
11995 * Columns for result set of SQLGetTypeInfo().
11996 */
11997
11998 static COL typeSpec2[] = {
11999 { "SYSTEM", "TYPE", "TYPE_NAME", SCOL_VARCHAR, 50 },
12000 { "SYSTEM", "TYPE", "DATA_TYPE", SQL_SMALLINT, 2 },
12001 { "SYSTEM", "TYPE", "PRECISION", SQL_INTEGER, 9 },
12002 { "SYSTEM", "TYPE", "LITERAL_PREFIX", SCOL_VARCHAR, 50 },
12003 { "SYSTEM", "TYPE", "LITERAL_SUFFIX", SCOL_VARCHAR, 50 },
12004 { "SYSTEM", "TYPE", "CREATE_PARAMS", SCOL_VARCHAR, 50 },
12005 { "SYSTEM", "TYPE", "NULLABLE", SQL_SMALLINT, 2 },
12006 { "SYSTEM", "TYPE", "CASE_SENSITIVE", SQL_SMALLINT, 2 },
12007 { "SYSTEM", "TYPE", "SEARCHABLE", SQL_SMALLINT, 2 },
12008 { "SYSTEM", "TYPE", "UNSIGNED_ATTRIBUTE", SQL_SMALLINT, 2 },
12009 { "SYSTEM", "TYPE", "MONEY", SQL_SMALLINT, 2 },
12010 { "SYSTEM", "TYPE", "AUTO_INCREMENT", SQL_SMALLINT, 2 },
12011 { "SYSTEM", "TYPE", "LOCAL_TYPE_NAME", SCOL_VARCHAR, 50 },
12012 { "SYSTEM", "TYPE", "MINIMUM_SCALE", SQL_SMALLINT, 2 },
12013 { "SYSTEM", "TYPE", "MAXIMUM_SCALE", SQL_SMALLINT, 2 }
12014 };
12015
12016 static COL typeSpec3[] = {
12017 { "SYSTEM", "TYPE", "TYPE_NAME", SCOL_VARCHAR, 50 },
12018 { "SYSTEM", "TYPE", "DATA_TYPE", SQL_SMALLINT, 2 },
12019 { "SYSTEM", "TYPE", "COLUMN_SIZE", SQL_INTEGER, 9 },
12020 { "SYSTEM", "TYPE", "LITERAL_PREFIX", SCOL_VARCHAR, 50 },
12021 { "SYSTEM", "TYPE", "LITERAL_SUFFIX", SCOL_VARCHAR, 50 },
12022 { "SYSTEM", "TYPE", "CREATE_PARAMS", SCOL_VARCHAR, 50 },
12023 { "SYSTEM", "TYPE", "NULLABLE", SQL_SMALLINT, 2 },
12024 { "SYSTEM", "TYPE", "CASE_SENSITIVE", SQL_SMALLINT, 2 },
12025 { "SYSTEM", "TYPE", "SEARCHABLE", SQL_SMALLINT, 2 },
12026 { "SYSTEM", "TYPE", "UNSIGNED_ATTRIBUTE", SQL_SMALLINT, 2 },
12027 { "SYSTEM", "TYPE", "FIXED_PREC_SCALE", SQL_SMALLINT, 2 },
12028 { "SYSTEM", "TYPE", "AUTO_UNIQUE_VALUE", SQL_SMALLINT, 2 },
12029 { "SYSTEM", "TYPE", "LOCAL_TYPE_NAME", SCOL_VARCHAR, 50 },
12030 { "SYSTEM", "TYPE", "MINIMUM_SCALE", SQL_SMALLINT, 2 },
12031 { "SYSTEM", "TYPE", "MAXIMUM_SCALE", SQL_SMALLINT, 2 },
12032 { "SYSTEM", "TYPE", "SQL_DATA_TYPE", SQL_SMALLINT, 2 },
12033 { "SYSTEM", "TYPE", "SQL_DATETIME_SUB", SQL_SMALLINT, 2 },
12034 { "SYSTEM", "TYPE", "NUM_PREC_RADIX", SQL_INTEGER, 4 },
12035 { "SYSTEM", "TYPE", "INTERVAL_PRECISION", SQL_SMALLINT, 2 }
12036 };
12037
12038 /**
12039 * Internal function to build up data type information as row in result set.
12040 * @param s statement pointer
12041 * @param row row number
12042 * @param asize number of items in a row
12043 * @param typename name of type
12044 * @param type integer SQL type
12045 * @param tind type index
12046 */
12047
12048 static void
mktypeinfo(STMT * s,int row,int asize,char * typename,int type,int tind)12049 mktypeinfo(STMT *s, int row, int asize, char *typename, int type, int tind)
12050 {
12051 int offs = row * asize;
12052 char *tcode, *crpar = NULL, *quote = NULL, *sign = stringify(SQL_FALSE);
12053 static char tcodes[32 * 32];
12054
12055 if (tind <= 0) {
12056 tind = row;
12057 }
12058 tcode = tcodes + tind * 32;
12059 sprintf(tcode, "%d", type);
12060 s->rows[offs + 0] = typename;
12061 s->rows[offs + 1] = tcode;
12062 if (asize >= 17) {
12063 s->rows[offs + 15] = tcode;
12064 s->rows[offs + 16] = "0";
12065 }
12066 switch (type) {
12067 default:
12068 #ifdef SQL_LONGVARCHAR
12069 case SQL_LONGVARCHAR:
12070 #ifdef WINTERFACE
12071 case SQL_WLONGVARCHAR:
12072 #endif
12073 crpar = "length";
12074 quote = "'";
12075 sign = NULL;
12076 s->rows[offs + 2] = "65536";
12077 break;
12078 #endif
12079 case SQL_CHAR:
12080 case SQL_VARCHAR:
12081 #ifdef WINTERFACE
12082 case SQL_WCHAR:
12083 case SQL_WVARCHAR:
12084 #endif
12085 s->rows[offs + 2] = "255";
12086 crpar = "length";
12087 quote = "'";
12088 sign = NULL;
12089 break;
12090 case SQL_TINYINT:
12091 s->rows[offs + 2] = "3";
12092 break;
12093 case SQL_SMALLINT:
12094 s->rows[offs + 2] = "5";
12095 break;
12096 case SQL_INTEGER:
12097 s->rows[offs + 2] = "9";
12098 break;
12099 case SQL_FLOAT:
12100 s->rows[offs + 2] = "7";
12101 break;
12102 case SQL_DOUBLE:
12103 s->rows[offs + 2] = "15";
12104 break;
12105 #ifdef SQL_TYPE_DATE
12106 case SQL_TYPE_DATE:
12107 #endif
12108 case SQL_DATE:
12109 s->rows[offs + 2] = "10";
12110 quote = "'";
12111 sign = NULL;
12112 break;
12113 #ifdef SQL_TYPE_TIME
12114 case SQL_TYPE_TIME:
12115 #endif
12116 case SQL_TIME:
12117 s->rows[offs + 2] = "8";
12118 quote = "'";
12119 sign = NULL;
12120 break;
12121 #ifdef SQL_TYPE_TIMESTAMP
12122 case SQL_TYPE_TIMESTAMP:
12123 #endif
12124 case SQL_TIMESTAMP:
12125 s->rows[offs + 2] = "32";
12126 quote = "'";
12127 sign = NULL;
12128 break;
12129 #if (HAVE_ENCDEC)
12130 case SQL_VARBINARY:
12131 sign = NULL;
12132 s->rows[offs + 2] = "255";
12133 break;
12134 case SQL_LONGVARBINARY:
12135 sign = NULL;
12136 s->rows[offs + 2] = "65536";
12137 break;
12138 #endif
12139 #ifdef SQL_BIT
12140 case SQL_BIT:
12141 sign = NULL;
12142 s->rows[offs + 2] = "1";
12143 break;
12144 #endif
12145 }
12146 s->rows[offs + 3] = s->rows[offs + 4] = quote;
12147 s->rows[offs + 5] = crpar;
12148 s->rows[offs + 6] = stringify(SQL_NULLABLE);
12149 s->rows[offs + 7] = stringify(SQL_FALSE);
12150 s->rows[offs + 8] = stringify(SQL_SEARCHABLE);
12151 s->rows[offs + 9] = sign;
12152 s->rows[offs + 10] = stringify(SQL_FALSE);
12153 s->rows[offs + 11] = stringify(SQL_FALSE);
12154 s->rows[offs + 12] = typename;
12155 switch (type) {
12156 case SQL_DATE:
12157 case SQL_TIME:
12158 s->rows[offs + 13] = "0";
12159 s->rows[offs + 14] = "0";
12160 break;
12161 #ifdef SQL_TYPE_TIMESTAMP
12162 case SQL_TYPE_TIMESTAMP:
12163 #endif
12164 case SQL_TIMESTAMP:
12165 s->rows[offs + 13] = "0";
12166 s->rows[offs + 14] = "3";
12167 break;
12168 default:
12169 s->rows[offs + 13] = NULL;
12170 s->rows[offs + 14] = NULL;
12171 break;
12172 }
12173 }
12174
12175 /**
12176 * Helper function to sort type information.
12177 * Callback for qsort().
12178 * @param a first item to compare
12179 * @param b second item to compare
12180 * @result ==0, <0, >0 according to data type number
12181 */
12182
12183 static int
typeinfosort(const void * a,const void * b)12184 typeinfosort(const void *a, const void *b)
12185 {
12186 char **pa = (char **) a;
12187 char **pb = (char **) b;
12188 int na, nb;
12189
12190 na = strtol(pa[1], NULL, 0);
12191 nb = strtol(pb[1], NULL, 0);
12192 return na - nb;
12193 }
12194
12195 /**
12196 * Internal return data type information.
12197 * @param stmt statement handle
12198 * @param sqltype which type to retrieve
12199 * @result ODBC error code
12200 */
12201
12202 static SQLRETURN
drvgettypeinfo(SQLHSTMT stmt,SQLSMALLINT sqltype)12203 drvgettypeinfo(SQLHSTMT stmt, SQLSMALLINT sqltype)
12204 {
12205 SQLRETURN ret;
12206 STMT *s;
12207 int asize;
12208
12209 ret = mkresultset(stmt, typeSpec2, array_size(typeSpec2),
12210 typeSpec3, array_size(typeSpec3), &asize);
12211 if (ret != SQL_SUCCESS) {
12212 return ret;
12213 }
12214 s = (STMT *) stmt;
12215 #ifdef WINTERFACE
12216 #ifdef SQL_LONGVARCHAR
12217 #ifdef SQL_WLONGVARCHAR
12218 if (s->nowchar[0]) {
12219 s->nrows = (sqltype == SQL_ALL_TYPES) ? 13 : 1;
12220 } else {
12221 s->nrows = (sqltype == SQL_ALL_TYPES) ? 17 : 1;
12222 }
12223 #else
12224 if (s->nowchar[0]) {
12225 s->nrows = (sqltype == SQL_ALL_TYPES) ? 12 : 1;
12226 } else {
12227 s->nrows = (sqltype == SQL_ALL_TYPES) ? 16 : 1;
12228 }
12229 #endif
12230 #else
12231 s->nrows = (sqltype == SQL_ALL_TYPES) ? 15 : 1;
12232 #endif
12233 #else
12234 #ifdef SQL_LONGVARCHAR
12235 s->nrows = (sqltype == SQL_ALL_TYPES) ? 13 : 1;
12236 #else
12237 s->nrows = (sqltype == SQL_ALL_TYPES) ? 12 : 1;
12238 #endif
12239 #endif
12240 #if (HAVE_ENCDEC)
12241 if (sqltype == SQL_ALL_TYPES) {
12242 s->nrows += 2;
12243 }
12244 #endif
12245 #ifdef SQL_BIT
12246 if (sqltype == SQL_ALL_TYPES) {
12247 s->nrows += 1;
12248 }
12249 #endif
12250 s->rows = (char **) xmalloc(sizeof (char *) * (s->nrows + 1) * asize);
12251 if (!s->rows) {
12252 s->nrows = 0;
12253 return nomem(s);
12254 }
12255 #ifdef MEMORY_DEBUG
12256 s->rowfree = xfree__;
12257 #else
12258 s->rowfree = free;
12259 #endif
12260 memset(s->rows, 0, sizeof (char *) * (s->nrows + 1) * asize);
12261 if (sqltype == SQL_ALL_TYPES) {
12262 int cc = 1;
12263
12264 mktypeinfo(s, cc++, asize, "varchar", SQL_VARCHAR, 0);
12265 mktypeinfo(s, cc++, asize, "tinyint", SQL_TINYINT, 0);
12266 mktypeinfo(s, cc++, asize, "smallint", SQL_SMALLINT, 0);
12267 mktypeinfo(s, cc++, asize, "integer", SQL_INTEGER, 0);
12268 mktypeinfo(s, cc++, asize, "float", SQL_FLOAT, 0);
12269 mktypeinfo(s, cc++, asize, "double", SQL_DOUBLE, 0);
12270 #ifdef SQL_TYPE_DATE
12271 mktypeinfo(s, cc++, asize, "date",
12272 (*s->ov3) ? SQL_TYPE_DATE : SQL_DATE, 0);
12273 #else
12274 mktypeinfo(s, cc++, asize, "date", SQL_DATE, 0);
12275 #endif
12276 #ifdef SQL_TYPE_TIME
12277 mktypeinfo(s, cc++, asize, "time",
12278 (*s->ov3) ? SQL_TYPE_TIME : SQL_TIME, 0);
12279 #else
12280 mktypeinfo(s, cc++, asize, "time", SQL_TIME, 0);
12281 #endif
12282 #ifdef SQL_TYPE_TIMESTAMP
12283 mktypeinfo(s, cc++, asize, "timestamp",
12284 (*s->ov3) ? SQL_TYPE_TIMESTAMP : SQL_TIMESTAMP, 0);
12285 #else
12286 mktypeinfo(s, cc++, asize, "timestamp", SQL_TIMESTAMP, 0);
12287 #endif
12288 mktypeinfo(s, cc++, asize, "char", SQL_CHAR, 0);
12289 mktypeinfo(s, cc++, asize, "numeric", SQL_DOUBLE, 0);
12290 #ifdef SQL_LONGVARCHAR
12291 mktypeinfo(s, cc++, asize, "text", SQL_LONGVARCHAR, 0);
12292 mktypeinfo(s, cc++, asize, "longvarchar", SQL_LONGVARCHAR, 0);
12293 #else
12294 mktypeinfo(s, cc++, asize, "text", SQL_VARCHAR, 0);
12295 #endif
12296 #ifdef WINTERFACE
12297 if (!s->nowchar[0]) {
12298 mktypeinfo(s, cc++, asize, "wvarchar", SQL_WVARCHAR, 0);
12299 #ifdef SQL_LONGVARCHAR
12300 mktypeinfo(s, cc++, asize, "wchar", SQL_WCHAR, 0);
12301 mktypeinfo(s, cc++, asize, "wtext", SQL_WLONGVARCHAR, 0);
12302 #ifdef SQL_WLONGVARCHAR
12303 mktypeinfo(s, cc++, asize, "longwvarchar", SQL_WLONGVARCHAR, 0);
12304 #endif
12305 #else
12306 mktypeinfo(s, cc++, asize, "wvarchar", SQL_WVARCHAR, 0);
12307 mktypeinfo(s, cc++, asize, "wchar", SQL_WCHAR, 0);
12308 mktypeinfo(s, cc++, asize, "wtext", SQL_WVARCHAR, 0);
12309 #endif
12310 }
12311 #endif
12312 #if (HAVE_ENCDEC)
12313 mktypeinfo(s, cc++, asize, "varbinary", SQL_VARBINARY, 0);
12314 mktypeinfo(s, cc++, asize, "longvarbinary", SQL_LONGVARBINARY, 0);
12315 #endif
12316 #ifdef SQL_BIT
12317 mktypeinfo(s, cc++, asize, "bit", SQL_BIT, 0);
12318 #endif
12319 qsort(s->rows + asize, s->nrows, sizeof (char *) * asize,
12320 typeinfosort);
12321 } else {
12322 switch (sqltype) {
12323 case SQL_CHAR:
12324 mktypeinfo(s, 1, asize, "char", SQL_CHAR, 10);
12325 break;
12326 case SQL_VARCHAR:
12327 mktypeinfo(s, 1, asize, "varchar", SQL_VARCHAR, 1);
12328 break;
12329 case SQL_TINYINT:
12330 mktypeinfo(s, 1, asize, "tinyint", SQL_TINYINT, 2);
12331 break;
12332 case SQL_SMALLINT:
12333 mktypeinfo(s, 1, asize, "smallint", SQL_SMALLINT, 3);
12334 break;
12335 case SQL_INTEGER:
12336 mktypeinfo(s, 1, asize, "integer", SQL_INTEGER, 4);
12337 break;
12338 case SQL_FLOAT:
12339 mktypeinfo(s, 1, asize, "float", SQL_FLOAT, 5);
12340 break;
12341 case SQL_DOUBLE:
12342 mktypeinfo(s, 1, asize, "double", SQL_DOUBLE, 6);
12343 break;
12344 #ifdef SQL_TYPE_DATE
12345 case SQL_TYPE_DATE:
12346 mktypeinfo(s, 1, asize, "date", SQL_TYPE_DATE, 25);
12347 break;
12348 #endif
12349 case SQL_DATE:
12350 mktypeinfo(s, 1, asize, "date", SQL_DATE, 7);
12351 break;
12352 #ifdef SQL_TYPE_TIME
12353 case SQL_TYPE_TIME:
12354 mktypeinfo(s, 1, asize, "time", SQL_TYPE_TIME, 26);
12355 break;
12356 #endif
12357 case SQL_TIME:
12358 mktypeinfo(s, 1, asize, "time", SQL_TIME, 8);
12359 break;
12360 #ifdef SQL_TYPE_TIMESTAMP
12361 case SQL_TYPE_TIMESTAMP:
12362 mktypeinfo(s, 1, asize, "timestamp", SQL_TYPE_TIMESTAMP, 27);
12363 break;
12364 #endif
12365 case SQL_TIMESTAMP:
12366 mktypeinfo(s, 1, asize, "timestamp", SQL_TIMESTAMP, 9);
12367 break;
12368 #ifdef SQL_LONGVARCHAR
12369 case SQL_LONGVARCHAR:
12370 mktypeinfo(s, 1, asize, "longvarchar", SQL_LONGVARCHAR, 12);
12371 break;
12372 #endif
12373 #ifdef WINTERFACE
12374 #ifdef SQL_WCHAR
12375 case SQL_WCHAR:
12376 mktypeinfo(s, 1, asize, "wchar", SQL_WCHAR, 18);
12377 break;
12378 #endif
12379 #ifdef SQL_WVARCHAR
12380 case SQL_WVARCHAR:
12381 mktypeinfo(s, 1, asize, "wvarchar", SQL_WVARCHAR, 19);
12382 break;
12383 #endif
12384 #ifdef SQL_WLONGVARCHAR
12385 case SQL_WLONGVARCHAR:
12386 mktypeinfo(s, 1, asize, "longwvarchar", SQL_WLONGVARCHAR, 20);
12387 break;
12388 #endif
12389 #endif
12390 #if (HAVE_ENCDEC)
12391 case SQL_VARBINARY:
12392 mktypeinfo(s, 1, asize, "varbinary", SQL_VARBINARY, 30);
12393 break;
12394 case SQL_LONGVARBINARY:
12395 mktypeinfo(s, 1, asize, "longvarbinary", SQL_LONGVARBINARY, 31);
12396 break;
12397 #endif
12398 #ifdef SQL_BIT
12399 case SQL_BIT:
12400 mktypeinfo(s, 1, asize, "bit", SQL_BIT, 29);
12401 break;
12402 #endif
12403 default:
12404 s->nrows = 0;
12405 }
12406 }
12407 return SQL_SUCCESS;
12408 }
12409
12410 #ifndef WINTERFACE
12411 /**
12412 * Return data type information.
12413 * @param stmt statement handle
12414 * @param sqltype which type to retrieve
12415 * @result ODBC error code
12416 */
12417
12418 SQLRETURN SQL_API
SQLGetTypeInfo(SQLHSTMT stmt,SQLSMALLINT sqltype)12419 SQLGetTypeInfo(SQLHSTMT stmt, SQLSMALLINT sqltype)
12420 {
12421 SQLRETURN ret;
12422
12423 HSTMT_LOCK(stmt);
12424 ret = drvgettypeinfo(stmt, sqltype);
12425 HSTMT_UNLOCK(stmt);
12426 return ret;
12427 }
12428 #endif
12429
12430 #ifdef WINTERFACE
12431 /**
12432 * Return data type information (UNICODE version).
12433 * @param stmt statement handle
12434 * @param sqltype which type to retrieve
12435 * @result ODBC error code
12436 */
12437
12438 SQLRETURN SQL_API
SQLGetTypeInfoW(SQLHSTMT stmt,SQLSMALLINT sqltype)12439 SQLGetTypeInfoW(SQLHSTMT stmt, SQLSMALLINT sqltype)
12440 {
12441 SQLRETURN ret;
12442
12443 HSTMT_LOCK(stmt);
12444 ret = drvgettypeinfo(stmt, sqltype);
12445 HSTMT_UNLOCK(stmt);
12446 return ret;
12447 }
12448 #endif
12449
12450 /**
12451 * Columns for result set of SQLStatistics().
12452 */
12453
12454 static COL statSpec2[] = {
12455 { "SYSTEM", "STATISTICS", "TABLE_QUALIFIER", SCOL_VARCHAR, 50 },
12456 { "SYSTEM", "STATISTICS", "TABLE_OWNER", SCOL_VARCHAR, 50 },
12457 { "SYSTEM", "STATISTICS", "TABLE_NAME", SCOL_VARCHAR, 255 },
12458 { "SYSTEM", "STATISTICS", "NON_UNIQUE", SQL_SMALLINT, 50 },
12459 { "SYSTEM", "STATISTICS", "INDEX_QUALIFIER", SCOL_VARCHAR, 255 },
12460 { "SYSTEM", "STATISTICS", "INDEX_NAME", SCOL_VARCHAR, 255 },
12461 { "SYSTEM", "STATISTICS", "TYPE", SQL_SMALLINT, 50 },
12462 { "SYSTEM", "STATISTICS", "SEQ_IN_INDEX", SQL_SMALLINT, 50 },
12463 { "SYSTEM", "STATISTICS", "COLUMN_NAME", SCOL_VARCHAR, 255 },
12464 { "SYSTEM", "STATISTICS", "COLLATION", SCOL_CHAR, 1 },
12465 { "SYSTEM", "STATISTICS", "CARDINALITY", SQL_INTEGER, 50 },
12466 { "SYSTEM", "STATISTICS", "PAGES", SQL_INTEGER, 50 },
12467 { "SYSTEM", "STATISTICS", "FILTER_CONDITION", SCOL_VARCHAR, 255 }
12468 };
12469
12470 static COL statSpec3[] = {
12471 { "SYSTEM", "STATISTICS", "TABLE_CAT", SCOL_VARCHAR, 50 },
12472 { "SYSTEM", "STATISTICS", "TABLE_SCHEM", SCOL_VARCHAR, 50 },
12473 { "SYSTEM", "STATISTICS", "TABLE_NAME", SCOL_VARCHAR, 255 },
12474 { "SYSTEM", "STATISTICS", "NON_UNIQUE", SQL_SMALLINT, 50 },
12475 { "SYSTEM", "STATISTICS", "INDEX_QUALIFIER", SCOL_VARCHAR, 255 },
12476 { "SYSTEM", "STATISTICS", "INDEX_NAME", SCOL_VARCHAR, 255 },
12477 { "SYSTEM", "STATISTICS", "TYPE", SQL_SMALLINT, 50 },
12478 { "SYSTEM", "STATISTICS", "ORDINAL_POSITION", SQL_SMALLINT, 50 },
12479 { "SYSTEM", "STATISTICS", "COLUMN_NAME", SCOL_VARCHAR, 255 },
12480 { "SYSTEM", "STATISTICS", "ASC_OR_DESC", SCOL_CHAR, 1 },
12481 { "SYSTEM", "STATISTICS", "CARDINALITY", SQL_INTEGER, 50 },
12482 { "SYSTEM", "STATISTICS", "PAGES", SQL_INTEGER, 50 },
12483 { "SYSTEM", "STATISTICS", "FILTER_CONDITION", SCOL_VARCHAR, 255 }
12484 };
12485
12486 /**
12487 * Internal return statistic information on table indices.
12488 * @param stmt statement handle
12489 * @param cat catalog name/pattern or NULL
12490 * @param catLen length of catalog name/pattern or SQL_NTS
12491 * @param schema schema name/pattern or NULL
12492 * @param schemaLen length of schema name/pattern or SQL_NTS
12493 * @param table table name/pattern or NULL
12494 * @param tableLen length of table name/pattern or SQL_NTS
12495 * @param itype type of index information
12496 * @param resv reserved
12497 * @result ODBC error code
12498 */
12499
12500 static SQLRETURN
drvstatistics(SQLHSTMT stmt,SQLCHAR * cat,SQLSMALLINT catLen,SQLCHAR * schema,SQLSMALLINT schemaLen,SQLCHAR * table,SQLSMALLINT tableLen,SQLUSMALLINT itype,SQLUSMALLINT resv)12501 drvstatistics(SQLHSTMT stmt, SQLCHAR *cat, SQLSMALLINT catLen,
12502 SQLCHAR *schema, SQLSMALLINT schemaLen,
12503 SQLCHAR *table, SQLSMALLINT tableLen,
12504 SQLUSMALLINT itype, SQLUSMALLINT resv)
12505 {
12506 SQLRETURN sret;
12507 STMT *s;
12508 DBC *d;
12509 int i, asize, ret, nrows, ncols, offs, namec, uniquec, addipk = 0;
12510 PTRDIFF_T size;
12511 char **rowp, *errp = NULL, tname[512];
12512
12513 sret = mkresultset(stmt, statSpec2, array_size(statSpec2),
12514 statSpec3, array_size(statSpec3), &asize);
12515 if (sret != SQL_SUCCESS) {
12516 return sret;
12517 }
12518 s = (STMT *) stmt;
12519 d = (DBC *) s->dbc;
12520 if (!table || table[0] == '\0' || table[0] == '%') {
12521 setstat(s, -1, "need table name", (*s->ov3) ? "HY000" : "S1000");
12522 return SQL_ERROR;
12523 }
12524 if (tableLen == SQL_NTS) {
12525 size = sizeof (tname) - 1;
12526 } else {
12527 size = min(sizeof (tname) - 1, tableLen);
12528 }
12529 strncpy(tname, (char *) table, size);
12530 tname[size] = '\0';
12531 unescpat(tname);
12532 sret = starttran(s);
12533 if (sret != SQL_SUCCESS) {
12534 return sret;
12535 }
12536 /*
12537 * Try integer primary key (autoincrement) first
12538 */
12539 if (itype == SQL_INDEX_UNIQUE || itype == SQL_INDEX_ALL) {
12540 int colid, typec, npk = 0, npkint = 0;
12541
12542 rowp = 0;
12543 ret = sqlite_get_table_printf(d->sqlite,
12544 "PRAGMA table_info('%q')", &rowp,
12545 &nrows, &ncols, NULL, tname);
12546 if (ret != SQLITE_OK) {
12547 goto noipk;
12548 }
12549 namec = findcol(rowp, ncols, "name");
12550 uniquec = findcol(rowp, ncols, "pk");
12551 typec = findcol(rowp, ncols, "type");
12552 colid = findcol(rowp, ncols, "cid");
12553 if (namec < 0 || uniquec < 0 || typec < 0 || colid < 0) {
12554 goto noipk;
12555 }
12556 for (i = 1; i <= nrows; i++) {
12557 if (*rowp[i * ncols + uniquec] != '0') {
12558 npk++;
12559 if (strlen(rowp[i * ncols + typec]) == 7 &&
12560 strncasecmp(rowp[i * ncols + typec], "integer", 7)
12561 == 0) {
12562 npkint++;
12563 }
12564 }
12565 }
12566 if (npkint == 1 && npk == npkint) {
12567 addipk = 1;
12568 }
12569 noipk:
12570 sqlite_free_table(rowp);
12571 }
12572 ret = sqlite_get_table_printf(d->sqlite,
12573 "PRAGMA index_list('%q')", &rowp,
12574 &nrows, &ncols, &errp, tname);
12575 if (ret != SQLITE_OK) {
12576 setstat(s, ret, "%s (%d)", (*s->ov3) ? "HY000" : "S1000",
12577 errp ? errp : "unknown error", ret);
12578 if (errp) {
12579 sqlite_freemem(errp);
12580 errp = NULL;
12581 }
12582 return SQL_ERROR;
12583 }
12584 if (errp) {
12585 sqlite_freemem(errp);
12586 errp = NULL;
12587 }
12588 size = 0;
12589 namec = findcol(rowp, ncols, "name");
12590 uniquec = findcol(rowp, ncols, "unique");
12591 if (namec < 0 || uniquec < 0) {
12592 goto nodata;
12593 }
12594 for (i = 1; i <= nrows; i++) {
12595 int nnrows, nncols;
12596 char **rowpp;
12597 int isuniq;
12598
12599 isuniq = *rowp[i * ncols + uniquec] != '0';
12600 if (isuniq || itype == SQL_INDEX_ALL) {
12601 ret = sqlite_get_table_printf(d->sqlite,
12602 "PRAGMA index_info('%q')", &rowpp,
12603 &nnrows, &nncols, NULL,
12604 rowp[i * ncols + namec]);
12605 if (ret == SQLITE_OK) {
12606 size += nnrows;
12607 sqlite_free_table(rowpp);
12608 }
12609 }
12610 }
12611 nodata:
12612 if (addipk) {
12613 size++;
12614 }
12615 if (size == 0) {
12616 sqlite_free_table(rowp);
12617 return SQL_SUCCESS;
12618 }
12619 s->nrows = size;
12620 size = (size + 1) * asize;
12621 s->rows = xmalloc((size + 1) * sizeof (char *));
12622 if (!s->rows) {
12623 s->nrows = 0;
12624 return nomem(s);
12625 }
12626 s->rows[0] = (char *) size;
12627 s->rows += 1;
12628 memset(s->rows, 0, sizeof (char *) * size);
12629 s->rowfree = freerows;
12630 offs = 0;
12631 if (addipk) {
12632 char **rowpp;
12633 int ncols2, nrows2;
12634
12635 rowpp = 0;
12636 ret = sqlite_get_table_printf(d->sqlite,
12637 "PRAGMA table_info('%q')", &rowpp,
12638 &nrows2, &ncols2, NULL, tname);
12639 if (ret == SQLITE_OK) {
12640 int namecc, uniquecc, colid, typec, roffs;
12641
12642 namecc = findcol(rowpp, ncols2, "name");
12643 uniquecc = findcol(rowpp, ncols2, "pk");
12644 typec = findcol(rowpp, ncols2, "type");
12645 colid = findcol(rowpp, ncols2, "cid");
12646 if (namecc < 0 || uniquecc < 0 || typec < 0 || colid < 0) {
12647 addipk = 0;
12648 s->nrows--;
12649 goto nodata2;
12650 }
12651 for (i = 1; i <= nrows2; i++) {
12652 if (*rowpp[i * ncols2 + uniquecc] != '0' &&
12653 strlen(rowpp[i * ncols2 + typec]) == 7 &&
12654 strncasecmp(rowpp[i * ncols2 + typec], "integer", 7)
12655 == 0) {
12656 break;
12657 }
12658 }
12659 if (i > nrows) {
12660 addipk = 0;
12661 s->nrows--;
12662 goto nodata2;
12663 }
12664 roffs = s->ncols;
12665 #if defined(_WIN32) || defined(_WIN64)
12666 s->rows[roffs + 0] = xstrdup(d->xcelqrx ? "main" : "");
12667 s->rows[roffs + 1] = xstrdup("");
12668 #else
12669 s->rows[roffs + 0] = xstrdup("");
12670 s->rows[roffs + 1] = xstrdup("");
12671 #endif
12672 s->rows[roffs + 2] = xstrdup(tname);
12673 s->rows[roffs + 3] = xstrdup(stringify(SQL_FALSE));
12674 s->rows[roffs + 5] = xstrdup("(autoindex 0)");
12675 s->rows[roffs + 6] = xstrdup(stringify(SQL_INDEX_OTHER));
12676 s->rows[roffs + 7] = xstrdup("1");
12677 s->rows[roffs + 8] = xstrdup(rowpp[i * ncols2 + namecc]);
12678 s->rows[roffs + 9] = xstrdup("A");
12679 }
12680 nodata2:
12681 sqlite_free_table(rowpp);
12682 }
12683 for (i = 1; i <= nrows; i++) {
12684 int nnrows, nncols;
12685 char **rowpp;
12686
12687 if (*rowp[i * ncols + uniquec] != '0' || itype == SQL_INDEX_ALL) {
12688 int k;
12689
12690 ret = sqlite_get_table_printf(d->sqlite,
12691 "PRAGMA index_info('%q')", &rowpp,
12692 &nnrows, &nncols, NULL,
12693 rowp[i * ncols + namec]);
12694 if (ret != SQLITE_OK) {
12695 continue;
12696 }
12697 for (k = 0; nnrows && k < nncols; k++) {
12698 if (strcmp(rowpp[k], "name") == 0) {
12699 int m;
12700
12701 for (m = 1; m <= nnrows; m++) {
12702 int roffs = (offs + addipk + m) * s->ncols;
12703 int isuniq;
12704
12705 isuniq = *rowp[i * ncols + uniquec] != '0';
12706 s->rows[roffs + 0] = xstrdup("");
12707 s->rows[roffs + 1] = xstrdup("");
12708 s->rows[roffs + 2] = xstrdup(tname);
12709 if (isuniq) {
12710 s->rows[roffs + 3] = xstrdup(stringify(SQL_FALSE));
12711 } else {
12712 s->rows[roffs + 3] = xstrdup(stringify(SQL_TRUE));
12713 }
12714 s->rows[roffs + 5] = xstrdup(rowp[i * ncols + namec]);
12715 s->rows[roffs + 6] =
12716 xstrdup(stringify(SQL_INDEX_OTHER));
12717 s->rows[roffs + 8] = xstrdup(rowpp[m * nncols + k]);
12718 s->rows[roffs + 9] = xstrdup("A");
12719 }
12720 } else if (strcmp(rowpp[k], "seqno") == 0) {
12721 int m;
12722
12723 for (m = 1; m <= nnrows; m++) {
12724 int roffs = (offs + addipk + m) * s->ncols;
12725 int pos = m - 1;
12726 char buf[32];
12727
12728 sscanf(rowpp[m * nncols + k], "%d", &pos);
12729 sprintf(buf, "%d", pos + 1);
12730 s->rows[roffs + 7] = xstrdup(buf);
12731 }
12732 }
12733 }
12734 offs += nnrows;
12735 sqlite_free_table(rowpp);
12736 }
12737 }
12738 sqlite_free_table(rowp);
12739 return SQL_SUCCESS;
12740 }
12741
12742 #ifndef WINTERFACE
12743 /**
12744 * Return statistic information on table indices.
12745 * @param stmt statement handle
12746 * @param cat catalog name/pattern or NULL
12747 * @param catLen length of catalog name/pattern or SQL_NTS
12748 * @param schema schema name/pattern or NULL
12749 * @param schemaLen length of schema name/pattern or SQL_NTS
12750 * @param table table name/pattern or NULL
12751 * @param tableLen length of table name/pattern or SQL_NTS
12752 * @param itype type of index information
12753 * @param resv reserved
12754 * @result ODBC error code
12755 */
12756
12757 SQLRETURN SQL_API
SQLStatistics(SQLHSTMT stmt,SQLCHAR * cat,SQLSMALLINT catLen,SQLCHAR * schema,SQLSMALLINT schemaLen,SQLCHAR * table,SQLSMALLINT tableLen,SQLUSMALLINT itype,SQLUSMALLINT resv)12758 SQLStatistics(SQLHSTMT stmt, SQLCHAR *cat, SQLSMALLINT catLen,
12759 SQLCHAR *schema, SQLSMALLINT schemaLen,
12760 SQLCHAR *table, SQLSMALLINT tableLen,
12761 SQLUSMALLINT itype, SQLUSMALLINT resv)
12762 {
12763 SQLRETURN ret;
12764
12765 HSTMT_LOCK(stmt);
12766 ret = drvstatistics(stmt, cat, catLen, schema, schemaLen,
12767 table, tableLen, itype, resv);
12768 HSTMT_UNLOCK(stmt);
12769 return ret;
12770 }
12771 #endif
12772
12773 #ifdef WINTERFACE
12774 /**
12775 * Return statistic information on table indices (UNICODE version).
12776 * @param stmt statement handle
12777 * @param cat catalog name/pattern or NULL
12778 * @param catLen length of catalog name/pattern or SQL_NTS
12779 * @param schema schema name/pattern or NULL
12780 * @param schemaLen length of schema name/pattern or SQL_NTS
12781 * @param table table name/pattern or NULL
12782 * @param tableLen length of table name/pattern or SQL_NTS
12783 * @param itype type of index information
12784 * @param resv reserved
12785 * @result ODBC error code
12786 */
12787
12788 SQLRETURN SQL_API
SQLStatisticsW(SQLHSTMT stmt,SQLWCHAR * cat,SQLSMALLINT catLen,SQLWCHAR * schema,SQLSMALLINT schemaLen,SQLWCHAR * table,SQLSMALLINT tableLen,SQLUSMALLINT itype,SQLUSMALLINT resv)12789 SQLStatisticsW(SQLHSTMT stmt, SQLWCHAR *cat, SQLSMALLINT catLen,
12790 SQLWCHAR *schema, SQLSMALLINT schemaLen,
12791 SQLWCHAR *table, SQLSMALLINT tableLen,
12792 SQLUSMALLINT itype, SQLUSMALLINT resv)
12793 {
12794 char *c = NULL, *s = NULL, *t = NULL;
12795 SQLRETURN ret;
12796
12797 HSTMT_LOCK(stmt);
12798 if (cat) {
12799 c = uc_to_utf_c(cat, catLen);
12800 if (!c) {
12801 ret = nomem((STMT *) stmt);
12802 goto done;
12803 }
12804 }
12805 if (schema) {
12806 s = uc_to_utf_c(schema, schemaLen);
12807 if (!s) {
12808 ret = nomem((STMT *) stmt);
12809 goto done;
12810 }
12811 }
12812 if (table) {
12813 t = uc_to_utf_c(table, tableLen);
12814 if (!t) {
12815 ret = nomem((STMT *) stmt);
12816 goto done;
12817 }
12818 }
12819 ret = drvstatistics(stmt, (SQLCHAR *) c, SQL_NTS, (SQLCHAR *) s, SQL_NTS,
12820 (SQLCHAR *) t, SQL_NTS, itype, resv);
12821 done:
12822 HSTMT_UNLOCK(stmt);
12823 uc_free(t);
12824 uc_free(s);
12825 uc_free(c);
12826 return ret;
12827 }
12828 #endif
12829
12830 /**
12831 * Retrieve row data after fetch.
12832 * @param stmt statement handle
12833 * @param col column number, starting at 1
12834 * @param type output type
12835 * @param val output buffer
12836 * @param len length of output buffer
12837 * @param lenp output length
12838 * @result ODBC error code
12839 */
12840
12841 SQLRETURN SQL_API
SQLGetData(SQLHSTMT stmt,SQLUSMALLINT col,SQLSMALLINT type,SQLPOINTER val,SQLLEN len,SQLLEN * lenp)12842 SQLGetData(SQLHSTMT stmt, SQLUSMALLINT col, SQLSMALLINT type,
12843 SQLPOINTER val, SQLLEN len, SQLLEN *lenp)
12844 {
12845 STMT *s;
12846 SQLRETURN ret = SQL_ERROR;
12847
12848 HSTMT_LOCK(stmt);
12849 if (stmt == SQL_NULL_HSTMT) {
12850 return SQL_INVALID_HANDLE;
12851 }
12852 s = (STMT *) stmt;
12853 if (col == 0 && s->bkmrk && type == SQL_C_BOOKMARK) {
12854 *((long *) val) = s->rowp;
12855 if (lenp) {
12856 *lenp = sizeof (long);
12857 }
12858 ret = SQL_SUCCESS;
12859 goto done;
12860 }
12861 if (col < 1 || col > s->ncols) {
12862 setstat(s, -1, "invalid column", (*s->ov3) ? "07009" : "S1002");
12863 goto done;
12864 }
12865 --col;
12866 ret = getrowdata(s, col, type, val, len, lenp, 1);
12867 done:
12868 HSTMT_UNLOCK(stmt);
12869 return ret;
12870 }
12871
12872 /**
12873 * Internal: fetch and bind from statement's current row
12874 * @param s statement pointer
12875 * @param rsi rowset index
12876 * @result ODBC error code
12877 */
12878
12879 static SQLRETURN
dofetchbind(STMT * s,int rsi)12880 dofetchbind(STMT *s, int rsi)
12881 {
12882 int ret, i, withinfo = 0;
12883
12884 s->row_status0[rsi] = SQL_ROW_SUCCESS;
12885 if (s->bkmrk && s->bkmrkcol.valp) {
12886 long *val;
12887
12888 if (s->bind_type != SQL_BIND_BY_COLUMN) {
12889 val = (long *) ((char *) s->bkmrkcol.valp + s->bind_type * rsi);
12890 } else {
12891 val = (long *) s->bkmrkcol.valp + rsi;
12892 }
12893 if (s->bind_offs) {
12894 val = (long *) ((char *) val + *s->bind_offs);
12895 }
12896 *val = s->rowp;
12897 if (s->bkmrkcol.lenp) {
12898 SQLLEN *ival;
12899
12900 if (s->bind_type != SQL_BIND_BY_COLUMN) {
12901 ival = (SQLLEN *) ((char *) s->bkmrkcol.lenp +
12902 s->bind_type * rsi);
12903 } else {
12904 ival = &s->bkmrkcol.lenp[rsi];
12905 }
12906 if (s->bind_offs) {
12907 ival = (SQLLEN *) ((char *) ival + *s->bind_offs);
12908 }
12909 *ival = sizeof (long);
12910 }
12911 }
12912 ret = SQL_SUCCESS;
12913 for (i = 0; s->bindcols && i < s->ncols; i++) {
12914 BINDCOL *b = &s->bindcols[i];
12915 SQLPOINTER dp = 0;
12916 SQLLEN *lp = 0;
12917
12918 b->offs = 0;
12919 if (b->valp) {
12920 if (s->bind_type != SQL_BIND_BY_COLUMN) {
12921 dp = (SQLPOINTER) ((char *) b->valp + s->bind_type * rsi);
12922 } else {
12923 dp = (SQLPOINTER) ((char *) b->valp + b->max * rsi);
12924 }
12925 if (s->bind_offs) {
12926 dp = (SQLPOINTER) ((char *) dp + *s->bind_offs);
12927 }
12928 }
12929 if (b->lenp) {
12930 if (s->bind_type != SQL_BIND_BY_COLUMN) {
12931 lp = (SQLLEN *) ((char *) b->lenp + s->bind_type * rsi);
12932 } else {
12933 lp = b->lenp + rsi;
12934 }
12935 if (s->bind_offs) {
12936 lp = (SQLLEN *) ((char *) lp + *s->bind_offs);
12937 }
12938 }
12939 if (dp || lp) {
12940 ret = getrowdata(s, (SQLUSMALLINT) i, b->type, dp, b->max, lp, 0);
12941 if (!SQL_SUCCEEDED(ret)) {
12942 s->row_status0[rsi] = SQL_ROW_ERROR;
12943 break;
12944 }
12945 if (ret != SQL_SUCCESS) {
12946 withinfo = 1;
12947 #ifdef SQL_ROW_SUCCESS_WITH_INFO
12948 s->row_status0[rsi] = SQL_ROW_SUCCESS_WITH_INFO;
12949 #endif
12950 }
12951 }
12952 }
12953 if (SQL_SUCCEEDED(ret)) {
12954 ret = withinfo ? SQL_SUCCESS_WITH_INFO : SQL_SUCCESS;
12955 }
12956 return ret;
12957 }
12958
12959 /**
12960 * Internal fetch function for SQLFetchScroll() and SQLExtendedFetch().
12961 * @param stmt statement handle
12962 * @param orient fetch direction
12963 * @param offset offset for fetch direction
12964 * @result ODBC error code
12965 */
12966
12967 static SQLRETURN
drvfetchscroll(SQLHSTMT stmt,SQLSMALLINT orient,SQLINTEGER offset)12968 drvfetchscroll(SQLHSTMT stmt, SQLSMALLINT orient, SQLINTEGER offset)
12969 {
12970 STMT *s;
12971 int i, withinfo = 0;
12972 SQLRETURN ret;
12973
12974 if (stmt == SQL_NULL_HSTMT) {
12975 return SQL_INVALID_HANDLE;
12976 }
12977 s = (STMT *) stmt;
12978 for (i = 0; i < s->rowset_size; i++) {
12979 s->row_status0[i] = SQL_ROW_NOROW;
12980 }
12981 if (s->row_status) {
12982 memcpy(s->row_status, s->row_status0,
12983 sizeof (SQLUSMALLINT) * s->rowset_size);
12984 }
12985 s->row_count0 = 0;
12986 if (s->row_count) {
12987 *s->row_count = s->row_count0;
12988 }
12989 if (!s->bindcols) {
12990 for (i = 0; i < s->rowset_size; i++) {
12991 s->row_status0[i] = SQL_ROW_ERROR;
12992 }
12993 ret = SQL_ERROR;
12994 i = 0;
12995 goto done2;
12996 }
12997 if (s->isselect != 1 && s->isselect != -1) {
12998 setstat(s, -1, "no result set available", "24000");
12999 ret = SQL_ERROR;
13000 i = s->nrows;
13001 goto done2;
13002 }
13003 if (s->curtype == SQL_CURSOR_FORWARD_ONLY && orient != SQL_FETCH_NEXT) {
13004 setstat(s, -1, "wrong fetch direction", "01000");
13005 ret = SQL_ERROR;
13006 i = 0;
13007 goto done2;
13008 }
13009 ret = SQL_SUCCESS;
13010 i = 0;
13011 if (((DBC *) (s->dbc))->vm_stmt == s && s->vm) {
13012 s->rowp = 0;
13013 for (; i < s->rowset_size; i++) {
13014 ret = vm_step(s);
13015 if (ret != SQL_SUCCESS) {
13016 s->row_status0[i] = SQL_ROW_ERROR;
13017 break;
13018 }
13019 if (s->nrows < 1) {
13020 break;
13021 }
13022 ret = dofetchbind(s, i);
13023 if (!SQL_SUCCEEDED(ret)) {
13024 break;
13025 } else if (ret == SQL_SUCCESS_WITH_INFO) {
13026 withinfo = 1;
13027 }
13028 }
13029 } else if (s->rows) {
13030 switch (orient) {
13031 case SQL_FETCH_NEXT:
13032 if (s->nrows < 1) {
13033 return SQL_NO_DATA;
13034 }
13035 if (s->rowp < 0) {
13036 s->rowp = -1;
13037 }
13038 if (s->rowp >= s->nrows) {
13039 s->rowp = s->nrows;
13040 return SQL_NO_DATA;
13041 }
13042 break;
13043 case SQL_FETCH_PRIOR:
13044 if (s->nrows < 1 || s->rowp <= 0) {
13045 s->rowp = -1;
13046 return SQL_NO_DATA;
13047 }
13048 s->rowp -= s->rowset_size + 1;
13049 if (s->rowp < -1) {
13050 s->rowp = -1;
13051 return SQL_NO_DATA;
13052 }
13053 break;
13054 case SQL_FETCH_FIRST:
13055 if (s->nrows < 1) {
13056 return SQL_NO_DATA;
13057 }
13058 s->rowp = -1;
13059 break;
13060 case SQL_FETCH_LAST:
13061 if (s->nrows < 1) {
13062 return SQL_NO_DATA;
13063 }
13064 s->rowp = s->nrows - s->rowset_size;
13065 if (--s->rowp < -1) {
13066 s->rowp = -1;
13067 }
13068 break;
13069 case SQL_FETCH_ABSOLUTE:
13070 if (offset == 0) {
13071 s->rowp = -1;
13072 return SQL_NO_DATA;
13073 } else if (offset < 0) {
13074 if (0 - offset <= s->nrows) {
13075 s->rowp = s->nrows + offset - 1;
13076 break;
13077 }
13078 s->rowp = -1;
13079 return SQL_NO_DATA;
13080 } else if (offset > s->nrows) {
13081 s->rowp = s->nrows;
13082 return SQL_NO_DATA;
13083 }
13084 s->rowp = offset - 1 - 1;
13085 break;
13086 case SQL_FETCH_RELATIVE:
13087 if (offset >= 0) {
13088 s->rowp += offset * s->rowset_size - 1;
13089 if (s->rowp >= s->nrows) {
13090 s->rowp = s->nrows;
13091 return SQL_NO_DATA;
13092 }
13093 } else {
13094 s->rowp += offset * s->rowset_size - 1;
13095 if (s->rowp < -1) {
13096 s->rowp = -1;
13097 return SQL_NO_DATA;
13098 }
13099 }
13100 break;
13101 case SQL_FETCH_BOOKMARK:
13102 if (s->bkmrk) {
13103 if (offset < 0 || offset >= s->nrows) {
13104 return SQL_NO_DATA;
13105 }
13106 s->rowp = offset - 1;
13107 break;
13108 }
13109 /* fall through */
13110 default:
13111 s->row_status0[0] = SQL_ROW_ERROR;
13112 ret = SQL_ERROR;
13113 goto done;
13114 }
13115 for (; i < s->rowset_size; i++) {
13116 ++s->rowp;
13117 if (s->rowp < 0 || s->rowp >= s->nrows) {
13118 break;
13119 }
13120 ret = dofetchbind(s, i);
13121 if (!SQL_SUCCEEDED(ret)) {
13122 break;
13123 } else if (ret == SQL_SUCCESS_WITH_INFO) {
13124 withinfo = 1;
13125 }
13126 }
13127 }
13128 done:
13129 if (i == 0) {
13130 if (SQL_SUCCEEDED(ret)) {
13131 return SQL_NO_DATA;
13132 }
13133 return ret;
13134 }
13135 if (SQL_SUCCEEDED(ret)) {
13136 ret = withinfo ? SQL_SUCCESS_WITH_INFO : SQL_SUCCESS;
13137 }
13138 done2:
13139 if (s->row_status) {
13140 memcpy(s->row_status, s->row_status0,
13141 sizeof (SQLUSMALLINT) * s->rowset_size);
13142 }
13143 s->row_count0 = i;
13144 if (s->row_count) {
13145 *s->row_count = s->row_count0;
13146 }
13147 return ret;
13148 }
13149
13150 /**
13151 * Fetch next result row.
13152 * @param stmt statement handle
13153 * @result ODBC error code
13154 */
13155
13156 SQLRETURN SQL_API
SQLFetch(SQLHSTMT stmt)13157 SQLFetch(SQLHSTMT stmt)
13158 {
13159 SQLRETURN ret;
13160
13161 HSTMT_LOCK(stmt);
13162 ret = drvfetchscroll(stmt, SQL_FETCH_NEXT, 0);
13163 HSTMT_UNLOCK(stmt);
13164 return ret;
13165 }
13166
13167 /**
13168 * Fetch result row with scrolling.
13169 * @param stmt statement handle
13170 * @param orient fetch direction
13171 * @param offset offset for fetch direction
13172 * @result ODBC error code
13173 */
13174
13175 SQLRETURN SQL_API
SQLFetchScroll(SQLHSTMT stmt,SQLSMALLINT orient,SQLLEN offset)13176 SQLFetchScroll(SQLHSTMT stmt, SQLSMALLINT orient, SQLLEN offset)
13177 {
13178 SQLRETURN ret;
13179
13180 HSTMT_LOCK(stmt);
13181 ret = drvfetchscroll(stmt, orient, offset);
13182 HSTMT_UNLOCK(stmt);
13183 return ret;
13184 }
13185
13186 /**
13187 * Fetch result row with scrolling and row status.
13188 * @param stmt statement handle
13189 * @param orient fetch direction
13190 * @param offset offset for fetch direction
13191 * @param rowcount output number of fetched rows
13192 * @param rowstatus array for row stati
13193 * @result ODBC error code
13194 */
13195
13196 SQLRETURN SQL_API
SQLExtendedFetch(SQLHSTMT stmt,SQLUSMALLINT orient,SQLROWOFFSET offset,SQLROWSETSIZE * rowcount,SQLUSMALLINT * rowstatus)13197 SQLExtendedFetch(SQLHSTMT stmt, SQLUSMALLINT orient, SQLROWOFFSET offset,
13198 SQLROWSETSIZE *rowcount, SQLUSMALLINT *rowstatus)
13199 {
13200 STMT *s;
13201 SQLRETURN ret;
13202 SQLUSMALLINT *rst;
13203
13204 HSTMT_LOCK(stmt);
13205 if (stmt == SQL_NULL_HSTMT) {
13206 return SQL_INVALID_HANDLE;
13207 }
13208 s = (STMT *) stmt;
13209 /* temporarily turn off SQL_ATTR_ROW_STATUS_PTR */
13210 rst = s->row_status;
13211 s->row_status = 0;
13212 ret = drvfetchscroll(stmt, orient, offset);
13213 s->row_status = rst;
13214 if (rowstatus) {
13215 memcpy(rowstatus, s->row_status0,
13216 sizeof (SQLUSMALLINT) * s->rowset_size);
13217 }
13218 if (rowcount) {
13219 *rowcount = s->row_count0;
13220 }
13221 HSTMT_UNLOCK(stmt);
13222 return ret;
13223 }
13224
13225 /**
13226 * Return number of affected rows of HSTMT.
13227 * @param stmt statement handle
13228 * @param nrows output number of rows
13229 * @result ODBC error code
13230 */
13231
13232 SQLRETURN SQL_API
SQLRowCount(SQLHSTMT stmt,SQLLEN * nrows)13233 SQLRowCount(SQLHSTMT stmt, SQLLEN *nrows)
13234 {
13235 STMT *s;
13236
13237 HSTMT_LOCK(stmt);
13238 if (stmt == SQL_NULL_HSTMT) {
13239 return SQL_INVALID_HANDLE;
13240 }
13241 s = (STMT *) stmt;
13242 if (nrows) {
13243 *nrows = s->isselect ? 0 : s->nrows;
13244 }
13245 HSTMT_UNLOCK(stmt);
13246 return SQL_SUCCESS;
13247 }
13248
13249 /**
13250 * Return number of columns of result set given HSTMT.
13251 * @param stmt statement handle
13252 * @param ncols output number of columns
13253 * @result ODBC error code
13254 */
13255
13256 SQLRETURN SQL_API
SQLNumResultCols(SQLHSTMT stmt,SQLSMALLINT * ncols)13257 SQLNumResultCols(SQLHSTMT stmt, SQLSMALLINT *ncols)
13258 {
13259 STMT *s;
13260
13261 HSTMT_LOCK(stmt);
13262 if (stmt == SQL_NULL_HSTMT) {
13263 return SQL_INVALID_HANDLE;
13264 }
13265 s = (STMT *) stmt;
13266 if (ncols) {
13267 *ncols = s->ncols;
13268 }
13269 HSTMT_UNLOCK(stmt);
13270 return SQL_SUCCESS;
13271 }
13272
13273 /**
13274 * Internal describe column information.
13275 * @param stmt statement handle
13276 * @param col column number, starting at 1
13277 * @param name buffer for column name
13278 * @param nameMax length of name buffer
13279 * @param nameLen output length of column name
13280 * @param type output SQL type
13281 * @param size output column size
13282 * @param digits output number of digits
13283 * @param nullable output NULL allowed indicator
13284 * @result ODBC error code
13285 */
13286
13287 static SQLRETURN
drvdescribecol(SQLHSTMT stmt,SQLUSMALLINT col,SQLCHAR * name,SQLSMALLINT nameMax,SQLSMALLINT * nameLen,SQLSMALLINT * type,SQLULEN * size,SQLSMALLINT * digits,SQLSMALLINT * nullable)13288 drvdescribecol(SQLHSTMT stmt, SQLUSMALLINT col, SQLCHAR *name,
13289 SQLSMALLINT nameMax, SQLSMALLINT *nameLen,
13290 SQLSMALLINT *type, SQLULEN *size,
13291 SQLSMALLINT *digits, SQLSMALLINT *nullable)
13292 {
13293 STMT *s;
13294 COL *c;
13295 int didname = 0;
13296
13297 if (stmt == SQL_NULL_HSTMT) {
13298 return SQL_INVALID_HANDLE;
13299 }
13300 s = (STMT *) stmt;
13301 if (!s->cols) {
13302 setstat(s, -1, "no columns", (*s->ov3) ? "07009" : "S1002");
13303 return SQL_ERROR;
13304 }
13305 if (col < 1 || col > s->ncols) {
13306 setstat(s, -1, "invalid column", (*s->ov3) ? "07009" : "S1002");
13307 return SQL_ERROR;
13308 }
13309 c = s->cols + col - 1;
13310 if (name && nameMax > 0) {
13311 strncpy((char *) name, c->column, nameMax);
13312 name[nameMax - 1] = '\0';
13313 didname = 1;
13314 }
13315 if (nameLen) {
13316 if (didname) {
13317 *nameLen = strlen((char *) name);
13318 } else {
13319 *nameLen = strlen(c->column);
13320 }
13321 }
13322 if (type) {
13323 *type = c->type;
13324 #ifdef WINTERFACE
13325 if (s->nowchar[0] || s->nowchar[1]) {
13326 switch (c->type) {
13327 case SQL_WCHAR:
13328 *type = SQL_CHAR;
13329 break;
13330 case SQL_WVARCHAR:
13331 *type = SQL_VARCHAR;
13332 break;
13333 #ifdef SQL_LONGVARCHAR
13334 case SQL_WLONGVARCHAR:
13335 *type = SQL_LONGVARCHAR;
13336 break;
13337 #endif
13338 }
13339 }
13340 #endif
13341 }
13342 if (size) {
13343 *size = c->size;
13344 }
13345 if (digits) {
13346 *digits = 0;
13347 }
13348 if (nullable) {
13349 *nullable = 1;
13350 }
13351 return SQL_SUCCESS;
13352 }
13353
13354 #ifndef WINTERFACE
13355 /**
13356 * Describe column information.
13357 * @param stmt statement handle
13358 * @param col column number, starting at 1
13359 * @param name buffer for column name
13360 * @param nameMax length of name buffer
13361 * @param nameLen output length of column name
13362 * @param type output SQL type
13363 * @param size output column size
13364 * @param digits output number of digits
13365 * @param nullable output NULL allowed indicator
13366 * @result ODBC error code
13367 */
13368
13369 SQLRETURN SQL_API
SQLDescribeCol(SQLHSTMT stmt,SQLUSMALLINT col,SQLCHAR * name,SQLSMALLINT nameMax,SQLSMALLINT * nameLen,SQLSMALLINT * type,SQLULEN * size,SQLSMALLINT * digits,SQLSMALLINT * nullable)13370 SQLDescribeCol(SQLHSTMT stmt, SQLUSMALLINT col, SQLCHAR *name,
13371 SQLSMALLINT nameMax, SQLSMALLINT *nameLen,
13372 SQLSMALLINT *type, SQLULEN *size,
13373 SQLSMALLINT *digits, SQLSMALLINT *nullable)
13374 {
13375 SQLRETURN ret;
13376
13377 HSTMT_LOCK(stmt);
13378 ret = drvdescribecol(stmt, col, name, nameMax, nameLen,
13379 type, size, digits, nullable);
13380 HSTMT_UNLOCK(stmt);
13381 return ret;
13382 }
13383 #endif
13384
13385 #ifdef WINTERFACE
13386 /**
13387 * Describe column information (UNICODE version).
13388 * @param stmt statement handle
13389 * @param col column number, starting at 1
13390 * @param name buffer for column name
13391 * @param nameMax length of name buffer
13392 * @param nameLen output length of column name
13393 * @param type output SQL type
13394 * @param size output column size
13395 * @param digits output number of digits
13396 * @param nullable output NULL allowed indicator
13397 * @result ODBC error code
13398 */
13399
13400 SQLRETURN SQL_API
SQLDescribeColW(SQLHSTMT stmt,SQLUSMALLINT col,SQLWCHAR * name,SQLSMALLINT nameMax,SQLSMALLINT * nameLen,SQLSMALLINT * type,SQLULEN * size,SQLSMALLINT * digits,SQLSMALLINT * nullable)13401 SQLDescribeColW(SQLHSTMT stmt, SQLUSMALLINT col, SQLWCHAR *name,
13402 SQLSMALLINT nameMax, SQLSMALLINT *nameLen,
13403 SQLSMALLINT *type, SQLULEN *size,
13404 SQLSMALLINT *digits, SQLSMALLINT *nullable)
13405 {
13406 SQLRETURN ret;
13407 SQLSMALLINT len = 0;
13408
13409 HSTMT_LOCK(stmt);
13410 ret = drvdescribecol(stmt, col, (SQLCHAR *) name,
13411 (SQLSMALLINT) (nameMax * sizeof (SQLWCHAR)),
13412 &len, type, size, digits, nullable);
13413 if (ret == SQL_SUCCESS) {
13414 if (name) {
13415 if (len > 0) {
13416 SQLWCHAR *n = NULL;
13417
13418 n = uc_from_utf((SQLCHAR *) name, len);
13419 if (n) {
13420 uc_strncpy(name, n, nameMax);
13421 n[len] = 0;
13422 len = min(nameMax, uc_strlen(n));
13423 uc_free(n);
13424 } else {
13425 len = 0;
13426 }
13427 }
13428 if (len <= 0) {
13429 len = 0;
13430 if (nameMax > 0) {
13431 name[0] = 0;
13432 }
13433 }
13434 } else {
13435 STMT *s = (STMT *) stmt;
13436 COL *c = s->cols + col - 1;
13437
13438 len = 0;
13439 if (c->column) {
13440 len = strlen(c->column);
13441 }
13442 }
13443 if (nameLen) {
13444 *nameLen = len;
13445 }
13446 }
13447 HSTMT_UNLOCK(stmt);
13448 return ret;
13449 }
13450 #endif
13451
13452 /**
13453 * Internal retrieve column attributes.
13454 * @param stmt statement handle
13455 * @param col column number, starting at 1
13456 * @param id attribute id
13457 * @param val output buffer
13458 * @param valMax length of output buffer
13459 * @param valLen output length
13460 * @param val2 integer output buffer
13461 * @result ODBC error code
13462 */
13463
13464 static SQLRETURN
drvcolattributes(SQLHSTMT stmt,SQLUSMALLINT col,SQLUSMALLINT id,SQLPOINTER val,SQLSMALLINT valMax,SQLSMALLINT * valLen,SQLLEN * val2)13465 drvcolattributes(SQLHSTMT stmt, SQLUSMALLINT col, SQLUSMALLINT id,
13466 SQLPOINTER val, SQLSMALLINT valMax, SQLSMALLINT *valLen,
13467 SQLLEN *val2)
13468 {
13469 STMT *s;
13470 COL *c;
13471 SQLSMALLINT dummy;
13472 char *valc = (char *) val;
13473
13474 if (stmt == SQL_NULL_HSTMT) {
13475 return SQL_INVALID_HANDLE;
13476 }
13477 s = (STMT *) stmt;
13478 if (!s->cols) {
13479 return SQL_ERROR;
13480 }
13481 if (!valLen) {
13482 valLen = &dummy;
13483 }
13484 if (id == SQL_COLUMN_COUNT) {
13485 if (val2) {
13486 *val2 = s->ncols;
13487 }
13488 *valLen = sizeof (int);
13489 return SQL_SUCCESS;
13490 }
13491 if (id == SQL_COLUMN_TYPE && col == 0) {
13492 if (val2) {
13493 *val2 = SQL_INTEGER;
13494 }
13495 *valLen = sizeof (int);
13496 return SQL_SUCCESS;
13497 }
13498 #ifdef SQL_DESC_OCTET_LENGTH
13499 if (id == SQL_DESC_OCTET_LENGTH && col == 0) {
13500 if (val2) {
13501 *val2 = 4;
13502 }
13503 *valLen = sizeof (int);
13504 return SQL_SUCCESS;
13505 }
13506 #endif
13507 if (col < 1 || col > s->ncols) {
13508 setstat(s, -1, "invalid column", (*s->ov3) ? "07009": "S1002");
13509 return SQL_ERROR;
13510 }
13511 c = s->cols + col - 1;
13512
13513 switch (id) {
13514 case SQL_COLUMN_LABEL:
13515 if (c->label) {
13516 if (valc && valMax > 0) {
13517 strncpy(valc, c->label, valMax);
13518 valc[valMax - 1] = '\0';
13519 }
13520 *valLen = strlen(c->label);
13521 goto checkLen;
13522 }
13523 /* fall through */
13524 case SQL_COLUMN_NAME:
13525 case SQL_DESC_NAME:
13526 if (valc && valMax > 0) {
13527 strncpy(valc, c->column, valMax);
13528 valc[valMax - 1] = '\0';
13529 }
13530 *valLen = strlen(c->column);
13531 checkLen:
13532 if (*valLen >= valMax) {
13533 setstat(s, -1, "data right truncated", "01004");
13534 return SQL_SUCCESS_WITH_INFO;
13535 }
13536 return SQL_SUCCESS;
13537 #ifdef SQL_DESC_BASE_COLUMN_NAME
13538 case SQL_DESC_BASE_COLUMN_NAME:
13539 if (strchr(c->column, '(') || strchr(c->column, ')')) {
13540 if (valc && valMax > 0) {
13541 valc[0] = '\0';
13542 }
13543 *valLen = 0;
13544 } else if (valc && valMax > 0) {
13545 strncpy(valc, c->column, valMax);
13546 valc[valMax - 1] = '\0';
13547 *valLen = strlen(c->column);
13548 }
13549 goto checkLen;
13550 #endif
13551 case SQL_COLUMN_TYPE:
13552 case SQL_DESC_TYPE:
13553 #ifdef WINTERFACE
13554 {
13555 int type = c->type;
13556
13557 if (s->nowchar[0] || s->nowchar[1]) {
13558 switch (type) {
13559 case SQL_WCHAR:
13560 type = SQL_CHAR;
13561 break;
13562 case SQL_WVARCHAR:
13563 type = SQL_VARCHAR;
13564 break;
13565 #ifdef SQL_LONGVARCHAR
13566 case SQL_WLONGVARCHAR:
13567 type = SQL_LONGVARCHAR;
13568 break;
13569 }
13570 }
13571 if (val2) {
13572 *val2 = type;
13573 }
13574 #endif
13575 }
13576 #else
13577 if (val2) {
13578 *val2 = c->type;
13579 }
13580 #endif
13581 *valLen = sizeof (int);
13582 return SQL_SUCCESS;
13583 case SQL_COLUMN_DISPLAY_SIZE:
13584 if (val2) {
13585 *val2 = c->size;
13586 }
13587 *valLen = sizeof (int);
13588 return SQL_SUCCESS;
13589 case SQL_COLUMN_UNSIGNED:
13590 if (val2) {
13591 *val2 = c->nosign ? SQL_TRUE : SQL_FALSE;
13592 }
13593 *valLen = sizeof (int);
13594 return SQL_SUCCESS;
13595 case SQL_COLUMN_SCALE:
13596 case SQL_DESC_SCALE:
13597 if (val2) {
13598 *val2 = c->scale;
13599 }
13600 *valLen = sizeof (int);
13601 return SQL_SUCCESS;
13602 case SQL_COLUMN_PRECISION:
13603 case SQL_DESC_PRECISION:
13604 if (val2) {
13605 switch (c->type) {
13606 case SQL_SMALLINT:
13607 *val2 = 5;
13608 break;
13609 case SQL_INTEGER:
13610 *val2 = 10;
13611 break;
13612 case SQL_FLOAT:
13613 case SQL_REAL:
13614 case SQL_DOUBLE:
13615 *val2 = 15;
13616 break;
13617 case SQL_DATE:
13618 *val2 = 0;
13619 break;
13620 case SQL_TIME:
13621 *val2 = 0;
13622 break;
13623 #ifdef SQL_TYPE_TIMESTAMP
13624 case SQL_TYPE_TIMESTAMP:
13625 #endif
13626 case SQL_TIMESTAMP:
13627 *val2 = (c->prec >= 0 && c->prec <= 3) ? c->prec : 3;
13628 break;
13629 default:
13630 *val2 = c->prec;
13631 break;
13632 }
13633 }
13634 *valLen = sizeof (int);
13635 return SQL_SUCCESS;
13636 case SQL_COLUMN_MONEY:
13637 if (val2) {
13638 *val2 = SQL_FALSE;
13639 }
13640 *valLen = sizeof (int);
13641 return SQL_SUCCESS;
13642 case SQL_COLUMN_AUTO_INCREMENT:
13643 if (val2) {
13644 *val2 = c->autoinc;
13645 }
13646 *valLen = sizeof (int);
13647 return SQL_SUCCESS;
13648 case SQL_COLUMN_LENGTH:
13649 case SQL_DESC_LENGTH:
13650 if (val2) {
13651 *val2 = c->size;
13652 }
13653 *valLen = sizeof (int);
13654 return SQL_SUCCESS;
13655 case SQL_COLUMN_NULLABLE:
13656 case SQL_DESC_NULLABLE:
13657 if (val2) {
13658 *val2 = c->notnull;
13659 }
13660 *valLen = sizeof (int);
13661 return SQL_SUCCESS;
13662 case SQL_COLUMN_SEARCHABLE:
13663 if (val2) {
13664 *val2 = SQL_SEARCHABLE;
13665 }
13666 *valLen = sizeof (int);
13667 return SQL_SUCCESS;
13668 case SQL_COLUMN_CASE_SENSITIVE:
13669 if (val2) {
13670 *val2 = SQL_TRUE;
13671 }
13672 *valLen = sizeof (int);
13673 return SQL_SUCCESS;
13674 case SQL_COLUMN_UPDATABLE:
13675 if (val2) {
13676 *val2 = SQL_TRUE;
13677 }
13678 *valLen = sizeof (int);
13679 return SQL_SUCCESS;
13680 case SQL_DESC_COUNT:
13681 if (val2) {
13682 *val2 = s->ncols;
13683 }
13684 *valLen = sizeof (int);
13685 return SQL_SUCCESS;
13686 case SQL_COLUMN_TYPE_NAME: {
13687 char *p = NULL, *tn = c->typename ? c->typename : "varchar";
13688
13689 #ifdef WINTERFACE
13690 if (c->type == SQL_WCHAR ||
13691 c->type == SQL_WVARCHAR ||
13692 c->type == SQL_WLONGVARCHAR) {
13693 if (!(s->nowchar[0] || s->nowchar[1])) {
13694 if (strcasecmp(tn, "varchar") == 0) {
13695 tn = "wvarchar";
13696 }
13697 }
13698 }
13699 #endif
13700 if (valc && valMax > 0) {
13701 strncpy(valc, tn, valMax);
13702 valc[valMax - 1] = '\0';
13703 p = strchr(valc, '(');
13704 if (p) {
13705 *p = '\0';
13706 while (p > valc && ISSPACE(p[-1])) {
13707 --p;
13708 *p = '\0';
13709 }
13710 }
13711 *valLen = strlen(valc);
13712 } else {
13713 *valLen = strlen(tn);
13714 p = strchr(tn, '(');
13715 if (p) {
13716 *valLen = p - tn;
13717 while (p > tn && ISSPACE(p[-1])) {
13718 --p;
13719 *valLen -= 1;
13720 }
13721 }
13722 }
13723 goto checkLen;
13724 }
13725 case SQL_COLUMN_OWNER_NAME:
13726 case SQL_COLUMN_QUALIFIER_NAME: {
13727 char *z = "";
13728
13729 if (valc && valMax > 0) {
13730 strncpy(valc, z, valMax);
13731 valc[valMax - 1] = '\0';
13732 }
13733 *valLen = strlen(z);
13734 goto checkLen;
13735 }
13736 case SQL_COLUMN_TABLE_NAME:
13737 #if (SQL_COLUMN_TABLE_NAME != SQL_DESC_TABLE_NAME)
13738 case SQL_DESC_TABLE_NAME:
13739 #endif
13740 #ifdef SQL_DESC_BASE_TABLE_NAME
13741 case SQL_DESC_BASE_TABLE_NAME:
13742 #endif
13743 if (valc && valMax > 0) {
13744 strncpy(valc, c->table, valMax);
13745 valc[valMax - 1] = '\0';
13746 }
13747 *valLen = strlen(c->table);
13748 goto checkLen;
13749 #ifdef SQL_DESC_NUM_PREC_RADIX
13750 case SQL_DESC_NUM_PREC_RADIX:
13751 if (val2) {
13752 switch (c->type) {
13753 #ifdef WINTERFACE
13754 case SQL_WCHAR:
13755 case SQL_WVARCHAR:
13756 #ifdef SQL_LONGVARCHAR
13757 case SQL_WLONGVARCHAR:
13758 #endif
13759 #endif
13760 case SQL_CHAR:
13761 case SQL_VARCHAR:
13762 #ifdef SQL_LONGVARCHAR
13763 case SQL_LONGVARCHAR:
13764 #endif
13765 case SQL_BINARY:
13766 case SQL_VARBINARY:
13767 case SQL_LONGVARBINARY:
13768 *val2 = 0;
13769 break;
13770 default:
13771 *val2 = 2;
13772 }
13773 }
13774 *valLen = sizeof (int);
13775 return SQL_SUCCESS;
13776 #endif
13777 }
13778 setstat(s, -1, "unsupported column attributes %d", "HY091", id);
13779 return SQL_ERROR;
13780 }
13781
13782 #ifndef WINTERFACE
13783 /**
13784 * Retrieve column attributes.
13785 * @param stmt statement handle
13786 * @param col column number, starting at 1
13787 * @param id attribute id
13788 * @param val output buffer
13789 * @param valMax length of output buffer
13790 * @param valLen output length
13791 * @param val2 integer output buffer
13792 * @result ODBC error code
13793 */
13794
13795 SQLRETURN SQL_API
SQLColAttributes(SQLHSTMT stmt,SQLUSMALLINT col,SQLUSMALLINT id,SQLPOINTER val,SQLSMALLINT valMax,SQLSMALLINT * valLen,SQLLEN * val2)13796 SQLColAttributes(SQLHSTMT stmt, SQLUSMALLINT col, SQLUSMALLINT id,
13797 SQLPOINTER val, SQLSMALLINT valMax, SQLSMALLINT *valLen,
13798 SQLLEN *val2)
13799 {
13800 SQLRETURN ret;
13801
13802 HSTMT_LOCK(stmt);
13803 ret = drvcolattributes(stmt, col, id, val, valMax, valLen, val2);
13804 HSTMT_UNLOCK(stmt);
13805 return ret;
13806 }
13807 #endif
13808
13809 #ifdef WINTERFACE
13810 /**
13811 * Retrieve column attributes (UNICODE version).
13812 * @param stmt statement handle
13813 * @param col column number, starting at 1
13814 * @param id attribute id
13815 * @param val output buffer
13816 * @param valMax length of output buffer
13817 * @param valLen output length
13818 * @param val2 integer output buffer
13819 * @result ODBC error code
13820 */
13821
13822 SQLRETURN SQL_API
SQLColAttributesW(SQLHSTMT stmt,SQLUSMALLINT col,SQLUSMALLINT id,SQLPOINTER val,SQLSMALLINT valMax,SQLSMALLINT * valLen,SQLLEN * val2)13823 SQLColAttributesW(SQLHSTMT stmt, SQLUSMALLINT col, SQLUSMALLINT id,
13824 SQLPOINTER val, SQLSMALLINT valMax, SQLSMALLINT *valLen,
13825 SQLLEN *val2)
13826 {
13827 SQLRETURN ret;
13828 SQLSMALLINT len = 0;
13829
13830 HSTMT_LOCK(stmt);
13831 ret = drvcolattributes(stmt, col, id, val, valMax, &len, val2);
13832 if (SQL_SUCCEEDED(ret)) {
13833 SQLWCHAR *v = NULL;
13834
13835 switch (id) {
13836 case SQL_COLUMN_LABEL:
13837 case SQL_COLUMN_NAME:
13838 case SQL_DESC_NAME:
13839 case SQL_COLUMN_TYPE_NAME:
13840 case SQL_COLUMN_OWNER_NAME:
13841 case SQL_COLUMN_QUALIFIER_NAME:
13842 case SQL_COLUMN_TABLE_NAME:
13843 #if (SQL_COLUMN_TABLE_NAME != SQL_DESC_TABLE_NAME)
13844 case SQL_DESC_TABLE_NAME:
13845 #endif
13846 #ifdef SQL_DESC_BASE_COLUMN_NAME
13847 case SQL_DESC_BASE_COLUMN_NAME:
13848 #endif
13849 #ifdef SQL_DESC_BASE_TABLE_NAME
13850 case SQL_DESC_BASE_TABLE_NAME:
13851 #endif
13852 if (val && valMax > 0) {
13853 int vmax = valMax / sizeof (SQLWCHAR);
13854
13855 v = uc_from_utf((SQLCHAR *) val, SQL_NTS);
13856 if (v) {
13857 uc_strncpy(val, v, vmax);
13858 len = min(vmax, uc_strlen(v));
13859 uc_free(v);
13860 len *= sizeof (SQLWCHAR);
13861 }
13862 if (vmax > 0) {
13863 v = (SQLWCHAR *) val;
13864 v[vmax - 1] = '\0';
13865 }
13866 }
13867 if (len <= 0) {
13868 len = 0;
13869 }
13870 break;
13871 }
13872 if (valLen) {
13873 *valLen = len;
13874 }
13875 }
13876 HSTMT_UNLOCK(stmt);
13877 return ret;
13878 }
13879 #endif
13880
13881 /**
13882 * Internal retrieve column attributes.
13883 * @param stmt statement handle
13884 * @param col column number, starting at 1
13885 * @param id attribute id
13886 * @param val output buffer
13887 * @param valMax length of output buffer
13888 * @param valLen output length
13889 * @param val2 integer output buffer
13890 * @result ODBC error code
13891 */
13892
13893 static SQLRETURN
drvcolattribute(SQLHSTMT stmt,SQLUSMALLINT col,SQLUSMALLINT id,SQLPOINTER val,SQLSMALLINT valMax,SQLSMALLINT * valLen,SQLPOINTER val2)13894 drvcolattribute(SQLHSTMT stmt, SQLUSMALLINT col, SQLUSMALLINT id,
13895 SQLPOINTER val, SQLSMALLINT valMax, SQLSMALLINT *valLen,
13896 SQLPOINTER val2)
13897 {
13898 STMT *s;
13899 COL *c;
13900 int v = 0;
13901 char *valc = (char *) val;
13902 SQLSMALLINT dummy;
13903
13904 if (stmt == SQL_NULL_HSTMT) {
13905 return SQL_INVALID_HANDLE;
13906 }
13907 s = (STMT *) stmt;
13908 if (!s->cols) {
13909 return SQL_ERROR;
13910 }
13911 if (col < 1 || col > s->ncols) {
13912 setstat(s, -1, "invalid column", (*s->ov3) ? "07009" : "S1002");
13913 return SQL_ERROR;
13914 }
13915 if (!valLen) {
13916 valLen = &dummy;
13917 }
13918 c = s->cols + col - 1;
13919 switch (id) {
13920 case SQL_DESC_COUNT:
13921 v = s->ncols;
13922 break;
13923 case SQL_DESC_CATALOG_NAME:
13924 if (valc && valMax > 0) {
13925 strncpy(valc, c->db, valMax);
13926 valc[valMax - 1] = '\0';
13927 }
13928 *valLen = strlen(c->db);
13929 checkLen:
13930 if (*valLen >= valMax) {
13931 setstat(s, -1, "data right truncated", "01004");
13932 return SQL_SUCCESS_WITH_INFO;
13933 }
13934 break;
13935 case SQL_COLUMN_LENGTH:
13936 case SQL_DESC_LENGTH:
13937 v = c->size;
13938 break;
13939 case SQL_COLUMN_LABEL:
13940 if (c->label) {
13941 if (valc && valMax > 0) {
13942 strncpy(valc, c->label, valMax);
13943 valc[valMax - 1] = '\0';
13944 }
13945 *valLen = strlen(c->label);
13946 goto checkLen;
13947 }
13948 /* fall through */
13949 case SQL_COLUMN_NAME:
13950 case SQL_DESC_NAME:
13951 if (valc && valMax > 0) {
13952 strncpy(valc, c->column, valMax);
13953 valc[valMax - 1] = '\0';
13954 }
13955 *valLen = strlen(c->column);
13956 goto checkLen;
13957 case SQL_DESC_SCHEMA_NAME: {
13958 char *z = "";
13959
13960 if (valc && valMax > 0) {
13961 strncpy(valc, z, valMax);
13962 valc[valMax - 1] = '\0';
13963 }
13964 *valLen = strlen(z);
13965 goto checkLen;
13966 }
13967 #ifdef SQL_DESC_BASE_COLUMN_NAME
13968 case SQL_DESC_BASE_COLUMN_NAME:
13969 if (strchr(c->column, '(') || strchr(c->column, ')')) {
13970 valc[0] = '\0';
13971 *valLen = 0;
13972 } else if (valc && valMax > 0) {
13973 strncpy(valc, c->column, valMax);
13974 valc[valMax - 1] = '\0';
13975 *valLen = strlen(c->column);
13976 }
13977 goto checkLen;
13978 #endif
13979 case SQL_DESC_TYPE_NAME: {
13980 char *p = NULL, *tn = c->typename ? c->typename : "varchar";
13981
13982 #ifdef WINTERFACE
13983 if (c->type == SQL_WCHAR ||
13984 c->type == SQL_WVARCHAR ||
13985 c->type == SQL_WLONGVARCHAR) {
13986 if (!(s->nowchar[0] || s->nowchar[1])) {
13987 if (strcasecmp(tn, "varchar") == 0) {
13988 tn = "wvarchar";
13989 }
13990 }
13991 }
13992 #endif
13993 if (valc && valMax > 0) {
13994 strncpy(valc, tn, valMax);
13995 valc[valMax - 1] = '\0';
13996 p = strchr(valc, '(');
13997 if (p) {
13998 *p = '\0';
13999 while (p > valc && ISSPACE(p[-1])) {
14000 --p;
14001 *p = '\0';
14002 }
14003 }
14004 *valLen = strlen(valc);
14005 } else {
14006 *valLen = strlen(tn);
14007 p = strchr(tn, '(');
14008 if (p) {
14009 *valLen = p - tn;
14010 while (p > tn && ISSPACE(p[-1])) {
14011 --p;
14012 *valLen -= 1;
14013 }
14014 }
14015 }
14016 goto checkLen;
14017 }
14018 case SQL_DESC_OCTET_LENGTH:
14019 v = c->size;
14020 #ifdef WINTERFACE
14021 if (c->type == SQL_WCHAR ||
14022 c->type == SQL_WVARCHAR ||
14023 c->type == SQL_WLONGVARCHAR) {
14024 if (!(s->nowchar[0] || s->nowchar[1])) {
14025 v *= sizeof (SQLWCHAR);
14026 }
14027 }
14028 #endif
14029 break;
14030 #if (SQL_COLUMN_TABLE_NAME != SQL_DESC_TABLE_NAME)
14031 case SQL_COLUMN_TABLE_NAME:
14032 #endif
14033 case SQL_DESC_TABLE_NAME:
14034 #ifdef SQL_DESC_BASE_TABLE_NAME
14035 case SQL_DESC_BASE_TABLE_NAME:
14036 #endif
14037 if (valc && valMax > 0) {
14038 strncpy(valc, c->table, valMax);
14039 valc[valMax - 1] = '\0';
14040 }
14041 *valLen = strlen(c->table);
14042 goto checkLen;
14043 case SQL_DESC_TYPE:
14044 v = c->type;
14045 #ifdef WINTERFACE
14046 if (s->nowchar[0] || s->nowchar[1]) {
14047 switch (v) {
14048 case SQL_WCHAR:
14049 v = SQL_CHAR;
14050 break;
14051 case SQL_WVARCHAR:
14052 v = SQL_VARCHAR;
14053 break;
14054 #ifdef SQL_LONGVARCHAR
14055 case SQL_WLONGVARCHAR:
14056 v = SQL_LONGVARCHAR;
14057 break;
14058 #endif
14059 }
14060 }
14061 #endif
14062 break;
14063 case SQL_DESC_CONCISE_TYPE:
14064 switch (c->type) {
14065 case SQL_INTEGER:
14066 v = SQL_C_LONG;
14067 break;
14068 case SQL_TINYINT:
14069 v = SQL_C_TINYINT;
14070 break;
14071 case SQL_SMALLINT:
14072 v = SQL_C_SHORT;
14073 break;
14074 case SQL_FLOAT:
14075 v = SQL_C_FLOAT;
14076 break;
14077 case SQL_DOUBLE:
14078 v = SQL_C_DOUBLE;
14079 break;
14080 case SQL_TIMESTAMP:
14081 v = SQL_C_TIMESTAMP;
14082 break;
14083 case SQL_TIME:
14084 v = SQL_C_TIME;
14085 break;
14086 case SQL_DATE:
14087 v = SQL_C_DATE;
14088 break;
14089 #ifdef SQL_C_TYPE_TIMESTAMP
14090 case SQL_TYPE_TIMESTAMP:
14091 v = SQL_C_TYPE_TIMESTAMP;
14092 break;
14093 #endif
14094 #ifdef SQL_C_TYPE_TIME
14095 case SQL_TYPE_TIME:
14096 v = SQL_C_TYPE_TIME;
14097 break;
14098 #endif
14099 #ifdef SQL_C_TYPE_DATE
14100 case SQL_TYPE_DATE:
14101 v = SQL_C_TYPE_DATE;
14102 break;
14103 #endif
14104 #ifdef SQL_BIT
14105 case SQL_BIT:
14106 v = SQL_C_BIT;
14107 break;
14108 #endif
14109 default:
14110 #ifdef WINTERFACE
14111 v = (s->nowchar[0] || s->nowchar[1]) ? SQL_C_CHAR : SQL_C_WCHAR;
14112 #else
14113 v = SQL_C_CHAR;
14114 #endif
14115 break;
14116 }
14117 break;
14118 case SQL_DESC_UPDATABLE:
14119 v = SQL_TRUE;
14120 break;
14121 case SQL_COLUMN_DISPLAY_SIZE:
14122 v = c->size;
14123 break;
14124 case SQL_COLUMN_UNSIGNED:
14125 v = c->nosign ? SQL_TRUE : SQL_FALSE;
14126 break;
14127 case SQL_COLUMN_SEARCHABLE:
14128 v = SQL_SEARCHABLE;
14129 break;
14130 case SQL_COLUMN_SCALE:
14131 case SQL_DESC_SCALE:
14132 v = c->scale;
14133 break;
14134 case SQL_COLUMN_PRECISION:
14135 case SQL_DESC_PRECISION:
14136 switch (c->type) {
14137 case SQL_SMALLINT:
14138 v = 5;
14139 break;
14140 case SQL_INTEGER:
14141 v = 10;
14142 break;
14143 case SQL_FLOAT:
14144 case SQL_REAL:
14145 case SQL_DOUBLE:
14146 v = 15;
14147 break;
14148 case SQL_DATE:
14149 v = 0;
14150 break;
14151 case SQL_TIME:
14152 v = 0;
14153 break;
14154 #ifdef SQL_TYPE_TIMESTAMP
14155 case SQL_TYPE_TIMESTAMP:
14156 #endif
14157 case SQL_TIMESTAMP:
14158 v = (c->prec >= 0 && c->prec <= 3) ? c->prec : 3;
14159 break;
14160 default:
14161 v = c->prec;
14162 break;
14163 }
14164 break;
14165 case SQL_COLUMN_MONEY:
14166 v = SQL_FALSE;
14167 break;
14168 case SQL_COLUMN_AUTO_INCREMENT:
14169 v = c->autoinc;
14170 break;
14171 case SQL_DESC_NULLABLE:
14172 v = c->notnull;
14173 break;
14174 #ifdef SQL_DESC_NUM_PREC_RADIX
14175 case SQL_DESC_NUM_PREC_RADIX:
14176 switch (c->type) {
14177 #ifdef WINTERFACE
14178 case SQL_WCHAR:
14179 case SQL_WVARCHAR:
14180 #ifdef SQL_LONGVARCHAR
14181 case SQL_WLONGVARCHAR:
14182 #endif
14183 #endif
14184 case SQL_CHAR:
14185 case SQL_VARCHAR:
14186 #ifdef SQL_LONGVARCHAR
14187 case SQL_LONGVARCHAR:
14188 #endif
14189 case SQL_BINARY:
14190 case SQL_VARBINARY:
14191 case SQL_LONGVARBINARY:
14192 v = 0;
14193 break;
14194 default:
14195 v = 2;
14196 }
14197 break;
14198 #endif
14199 default:
14200 setstat(s, -1, "unsupported column attribute %d", "HY091", id);
14201 return SQL_ERROR;
14202 }
14203 if (val2) {
14204 *(SQLLEN *) val2 = v;
14205 }
14206 return SQL_SUCCESS;
14207 }
14208
14209 #ifndef WINTERFACE
14210 /**
14211 * Retrieve column attributes.
14212 * @param stmt statement handle
14213 * @param col column number, starting at 1
14214 * @param id attribute id
14215 * @param val output buffer
14216 * @param valMax length of output buffer
14217 * @param valLen output length
14218 * @param val2 integer output buffer
14219 * @result ODBC error code
14220 */
14221
14222 SQLRETURN SQL_API
SQLColAttribute(SQLHSTMT stmt,SQLUSMALLINT col,SQLUSMALLINT id,SQLPOINTER val,SQLSMALLINT valMax,SQLSMALLINT * valLen,COLATTRIBUTE_LAST_ARG_TYPE val2)14223 SQLColAttribute(SQLHSTMT stmt, SQLUSMALLINT col, SQLUSMALLINT id,
14224 SQLPOINTER val, SQLSMALLINT valMax, SQLSMALLINT *valLen,
14225 COLATTRIBUTE_LAST_ARG_TYPE val2)
14226 {
14227 SQLRETURN ret;
14228
14229 HSTMT_LOCK(stmt);
14230 ret = drvcolattribute(stmt, col, id, val, valMax, valLen,
14231 (SQLPOINTER) val2);
14232 HSTMT_UNLOCK(stmt);
14233 return ret;
14234 }
14235 #endif
14236
14237 #ifdef WINTERFACE
14238 /**
14239 * Retrieve column attributes (UNICODE version).
14240 * @param stmt statement handle
14241 * @param col column number, starting at 1
14242 * @param id attribute id
14243 * @param val output buffer
14244 * @param valMax length of output buffer
14245 * @param valLen output length
14246 * @param val2 integer output buffer
14247 * @result ODBC error code
14248 */
14249
14250 SQLRETURN SQL_API
SQLColAttributeW(SQLHSTMT stmt,SQLUSMALLINT col,SQLUSMALLINT id,SQLPOINTER val,SQLSMALLINT valMax,SQLSMALLINT * valLen,COLATTRIBUTE_LAST_ARG_TYPE val2)14251 SQLColAttributeW(SQLHSTMT stmt, SQLUSMALLINT col, SQLUSMALLINT id,
14252 SQLPOINTER val, SQLSMALLINT valMax, SQLSMALLINT *valLen,
14253 COLATTRIBUTE_LAST_ARG_TYPE val2)
14254 {
14255 SQLRETURN ret;
14256 SQLSMALLINT len = 0;
14257
14258 HSTMT_LOCK(stmt);
14259 ret = drvcolattribute(stmt, col, id, val, valMax, &len,
14260 (SQLPOINTER) val2);
14261 if (SQL_SUCCEEDED(ret)) {
14262 SQLWCHAR *v = NULL;
14263
14264 switch (id) {
14265 case SQL_DESC_SCHEMA_NAME:
14266 case SQL_DESC_CATALOG_NAME:
14267 case SQL_COLUMN_LABEL:
14268 case SQL_DESC_NAME:
14269 case SQL_DESC_TABLE_NAME:
14270 #ifdef SQL_DESC_BASE_TABLE_NAME
14271 case SQL_DESC_BASE_TABLE_NAME:
14272 #endif
14273 #ifdef SQL_DESC_BASE_COLUMN_NAME
14274 case SQL_DESC_BASE_COLUMN_NAME:
14275 #endif
14276 case SQL_DESC_TYPE_NAME:
14277 if (val && valMax > 0) {
14278 int vmax = valMax / sizeof (SQLWCHAR);
14279
14280 v = uc_from_utf((SQLCHAR *) val, SQL_NTS);
14281 if (v) {
14282 uc_strncpy(val, v, vmax);
14283 len = min(vmax, uc_strlen(v));
14284 uc_free(v);
14285 len *= sizeof (SQLWCHAR);
14286 }
14287 if (vmax > 0) {
14288 v = (SQLWCHAR *) val;
14289 v[vmax - 1] = '\0';
14290 }
14291 }
14292 if (len <= 0) {
14293 len = 0;
14294 }
14295 break;
14296 }
14297 if (valLen) {
14298 *valLen = len;
14299 }
14300 }
14301 HSTMT_UNLOCK(stmt);
14302 return ret;
14303 }
14304 #endif
14305
14306 /**
14307 * Internal return last HDBC or HSTMT error message.
14308 * @param env environment handle or NULL
14309 * @param dbc database connection handle or NULL
14310 * @param stmt statement handle or NULL
14311 * @param sqlState output buffer for SQL state
14312 * @param nativeErr output buffer for native error code
14313 * @param errmsg output buffer for error message
14314 * @param errmax length of output buffer for error message
14315 * @param errlen output length of error message
14316 * @result ODBC error code
14317 */
14318
14319 static SQLRETURN
drverror(SQLHENV env,SQLHDBC dbc,SQLHSTMT stmt,SQLCHAR * sqlState,SQLINTEGER * nativeErr,SQLCHAR * errmsg,SQLSMALLINT errmax,SQLSMALLINT * errlen)14320 drverror(SQLHENV env, SQLHDBC dbc, SQLHSTMT stmt,
14321 SQLCHAR *sqlState, SQLINTEGER *nativeErr,
14322 SQLCHAR *errmsg, SQLSMALLINT errmax, SQLSMALLINT *errlen)
14323 {
14324 SQLCHAR dummy0[6];
14325 SQLINTEGER dummy1;
14326 SQLSMALLINT dummy2;
14327
14328 if (env == SQL_NULL_HENV &&
14329 dbc == SQL_NULL_HDBC &&
14330 stmt == SQL_NULL_HSTMT) {
14331 return SQL_INVALID_HANDLE;
14332 }
14333 if (sqlState) {
14334 sqlState[0] = '\0';
14335 } else {
14336 sqlState = dummy0;
14337 }
14338 if (!nativeErr) {
14339 nativeErr = &dummy1;
14340 }
14341 *nativeErr = 0;
14342 if (!errlen) {
14343 errlen = &dummy2;
14344 }
14345 *errlen = 0;
14346 if (errmsg) {
14347 if (errmax > 0) {
14348 errmsg[0] = '\0';
14349 }
14350 } else {
14351 errmsg = dummy0;
14352 errmax = 0;
14353 }
14354 if (stmt) {
14355 STMT *s = (STMT *) stmt;
14356
14357 HSTMT_LOCK(stmt);
14358 if (s->logmsg[0] == '\0') {
14359 HSTMT_UNLOCK(stmt);
14360 goto noerr;
14361 }
14362 *nativeErr = s->naterr;
14363 strcpy((char *) sqlState, s->sqlstate);
14364 if (errmax == SQL_NTS) {
14365 strcpy((char *) errmsg, "[SQLite]");
14366 strcat((char *) errmsg, (char *) s->logmsg);
14367 *errlen = strlen((char *) errmsg);
14368 } else {
14369 strncpy((char *) errmsg, "[SQLite]", errmax);
14370 if (errmax - 8 > 0) {
14371 strncpy((char *) errmsg + 8, (char *) s->logmsg, errmax - 8);
14372 }
14373 *errlen = min(strlen((char *) s->logmsg) + 8, errmax);
14374 }
14375 s->logmsg[0] = '\0';
14376 HSTMT_UNLOCK(stmt);
14377 return SQL_SUCCESS;
14378 }
14379 if (dbc) {
14380 DBC *d = (DBC *) dbc;
14381
14382 HDBC_LOCK(dbc);
14383 if (d->magic != DBC_MAGIC || d->logmsg[0] == '\0') {
14384 HDBC_UNLOCK(dbc);
14385 goto noerr;
14386 }
14387 *nativeErr = d->naterr;
14388 strcpy((char *) sqlState, d->sqlstate);
14389 if (errmax == SQL_NTS) {
14390 strcpy((char *) errmsg, "[SQLite]");
14391 strcat((char *) errmsg, (char *) d->logmsg);
14392 *errlen = strlen((char *) errmsg);
14393 } else {
14394 strncpy((char *) errmsg, "[SQLite]", errmax);
14395 if (errmax - 8 > 0) {
14396 strncpy((char *) errmsg + 8, (char *) d->logmsg, errmax - 8);
14397 }
14398 *errlen = min(strlen((char *) d->logmsg) + 8, errmax);
14399 }
14400 d->logmsg[0] = '\0';
14401 HDBC_UNLOCK(dbc);
14402 return SQL_SUCCESS;
14403 }
14404 noerr:
14405 sqlState[0] = '\0';
14406 errmsg[0] = '\0';
14407 *nativeErr = 0;
14408 *errlen = 0;
14409 return SQL_NO_DATA;
14410 }
14411
14412 #ifndef WINTERFACE
14413 /**
14414 * Return last HDBC or HSTMT error message.
14415 * @param env environment handle or NULL
14416 * @param dbc database connection handle or NULL
14417 * @param stmt statement handle or NULL
14418 * @param sqlState output buffer for SQL state
14419 * @param nativeErr output buffer for native error code
14420 * @param errmsg output buffer for error message
14421 * @param errmax length of output buffer for error message
14422 * @param errlen output length of error message
14423 * @result ODBC error code
14424 */
14425
14426 SQLRETURN SQL_API
SQLError(SQLHENV env,SQLHDBC dbc,SQLHSTMT stmt,SQLCHAR * sqlState,SQLINTEGER * nativeErr,SQLCHAR * errmsg,SQLSMALLINT errmax,SQLSMALLINT * errlen)14427 SQLError(SQLHENV env, SQLHDBC dbc, SQLHSTMT stmt,
14428 SQLCHAR *sqlState, SQLINTEGER *nativeErr,
14429 SQLCHAR *errmsg, SQLSMALLINT errmax, SQLSMALLINT *errlen)
14430 {
14431 return drverror(env, dbc, stmt, sqlState, nativeErr,
14432 errmsg, errmax, errlen);
14433 }
14434 #endif
14435
14436 #ifdef WINTERFACE
14437 /**
14438 * Return last HDBC or HSTMT error message (UNICODE version).
14439 * @param env environment handle or NULL
14440 * @param dbc database connection handle or NULL
14441 * @param stmt statement handle or NULL
14442 * @param sqlState output buffer for SQL state
14443 * @param nativeErr output buffer for native error code
14444 * @param errmsg output buffer for error message
14445 * @param errmax length of output buffer for error message
14446 * @param errlen output length of error message
14447 * @result ODBC error code
14448 */
14449
14450 SQLRETURN SQL_API
SQLErrorW(SQLHENV env,SQLHDBC dbc,SQLHSTMT stmt,SQLWCHAR * sqlState,SQLINTEGER * nativeErr,SQLWCHAR * errmsg,SQLSMALLINT errmax,SQLSMALLINT * errlen)14451 SQLErrorW(SQLHENV env, SQLHDBC dbc, SQLHSTMT stmt,
14452 SQLWCHAR *sqlState, SQLINTEGER *nativeErr,
14453 SQLWCHAR *errmsg, SQLSMALLINT errmax, SQLSMALLINT *errlen)
14454 {
14455 char state[16];
14456 SQLSMALLINT len = 0;
14457 SQLRETURN ret;
14458
14459 ret = drverror(env, dbc, stmt, (SQLCHAR *) state, nativeErr,
14460 (SQLCHAR *) errmsg, errmax, &len);
14461 if (ret == SQL_SUCCESS) {
14462 if (sqlState) {
14463 uc_from_utf_buf((SQLCHAR *) state, -1, sqlState,
14464 6 * sizeof (SQLWCHAR));
14465 }
14466 if (errmsg) {
14467 if (len > 0) {
14468 SQLWCHAR *e = NULL;
14469
14470 e = uc_from_utf((SQLCHAR *) errmsg, len);
14471 if (e) {
14472 if (errmax > 0) {
14473 uc_strncpy(errmsg, e, errmax);
14474 e[len] = 0;
14475 len = min(errmax, uc_strlen(e));
14476 } else {
14477 len = uc_strlen(e);
14478 }
14479 uc_free(e);
14480 } else {
14481 len = 0;
14482 }
14483 }
14484 if (len <= 0) {
14485 len = 0;
14486 if (errmax > 0) {
14487 errmsg[0] = 0;
14488 }
14489 }
14490 } else {
14491 len = 0;
14492 }
14493 if (errlen) {
14494 *errlen = len;
14495 }
14496 } else if (ret == SQL_NO_DATA) {
14497 if (sqlState) {
14498 sqlState[0] = 0;
14499 }
14500 if (errmsg) {
14501 if (errmax > 0) {
14502 errmsg[0] = 0;
14503 }
14504 }
14505 if (errlen) {
14506 *errlen = 0;
14507 }
14508 }
14509 return ret;
14510 }
14511 #endif
14512
14513 /**
14514 * Return information for more result sets.
14515 * @param stmt statement handle
14516 * @result ODBC error code
14517 */
14518
14519 SQLRETURN SQL_API
SQLMoreResults(SQLHSTMT stmt)14520 SQLMoreResults(SQLHSTMT stmt)
14521 {
14522 HSTMT_LOCK(stmt);
14523 if (stmt == SQL_NULL_HSTMT) {
14524 return SQL_INVALID_HANDLE;
14525 }
14526 HSTMT_UNLOCK(stmt);
14527 return SQL_NO_DATA;
14528 }
14529
14530 /**
14531 * SQLite callback during drvprepare(), used to collect column information.
14532 * @param arg user data, actually a statement pointer
14533 * @param ncols number of columns
14534 * @param values value string array
14535 * @param cols column name string array
14536 * @result always 1 to abort sqlite_exec()
14537 */
14538
14539 static int
selcb(void * arg,int ncols,char ** values,char ** cols)14540 selcb(void *arg, int ncols, char **values, char **cols)
14541 {
14542 STMT *s = (STMT *) arg;
14543
14544 if (ncols > 0) {
14545 int i, size;
14546 char *p;
14547 COL *dyncols;
14548 DBC *d = (DBC *) s->dbc;
14549
14550 for (i = size = 0; i < ncols; i++) {
14551 size += 3 + 3 * strlen(cols[i]);
14552 }
14553 dyncols = xmalloc(ncols * sizeof (COL) + size);
14554 if (!dyncols) {
14555 freedyncols(s);
14556 s->ncols = 0;
14557 return 1;
14558 }
14559 p = (char *) (dyncols + ncols);
14560 for (i = 0; i < ncols; i++) {
14561 char *q;
14562
14563 dyncols[i].db = ((DBC *) (s->dbc))->dbname;
14564 strcpy(p, cols[i]);
14565 dyncols[i].label = p;
14566 p += strlen(p) + 1;
14567 q = strchr(cols[i], '.');
14568 if (q) {
14569 dyncols[i].table = p;
14570 strncpy(p, cols[i], q - cols[i]);
14571 p[q - cols[i]] = '\0';
14572 p += strlen(p) + 1;
14573 strcpy(p, q + 1);
14574 dyncols[i].column = p;
14575 p += strlen(p) + 1;
14576 } else {
14577 dyncols[i].table = "";
14578 strcpy(p, cols[i]);
14579 dyncols[i].column = p;
14580 p += strlen(p) + 1;
14581 }
14582 if (s->longnames) {
14583 dyncols[i].column = dyncols[i].label;
14584 }
14585 #ifdef SQL_LONGVARCHAR
14586 dyncols[i].type = SQL_LONGVARCHAR;
14587 dyncols[i].size = 65535;
14588 #else
14589 dyncols[i].type = SQL_VARCHAR;
14590 dyncols[i].size = 255;
14591 #endif
14592 dyncols[i].index = i;
14593 dyncols[i].scale = 0;
14594 dyncols[i].prec = 0;
14595 dyncols[i].nosign = 1;
14596 dyncols[i].autoinc = SQL_FALSE;
14597 dyncols[i].notnull = SQL_NULLABLE;
14598 dyncols[i].typename = NULL;
14599 }
14600 freedyncols(s);
14601 s->dyncols = s->cols = dyncols;
14602 s->dcols = ncols;
14603 fixupdyncols(s, d->sqlite, (const char **) cols + ncols);
14604 }
14605 s->ncols = ncols;
14606 return 1;
14607 }
14608
14609 /**
14610 * Internal query preparation used by SQLPrepare() and SQLExecDirect().
14611 * @param stmt statement handle
14612 * @param query query string
14613 * @param queryLen length of query string or SQL_NTS
14614 * @result ODBC error code
14615 */
14616
14617 static SQLRETURN
drvprepare(SQLHSTMT stmt,SQLCHAR * query,SQLINTEGER queryLen)14618 drvprepare(SQLHSTMT stmt, SQLCHAR *query, SQLINTEGER queryLen)
14619 {
14620 STMT *s;
14621 DBC *d;
14622 char *errp = NULL;
14623 SQLRETURN sret;
14624
14625 if (stmt == SQL_NULL_HSTMT) {
14626 return SQL_INVALID_HANDLE;
14627 }
14628 s = (STMT *) stmt;
14629 if (s->dbc == SQL_NULL_HDBC) {
14630 noconn:
14631 return noconn(s);
14632 }
14633 d = s->dbc;
14634 if (!d->sqlite) {
14635 goto noconn;
14636 }
14637 vm_end(s);
14638 sret = starttran(s);
14639 if (sret != SQL_SUCCESS) {
14640 return sret;
14641 }
14642 freep(&s->query);
14643 s->query = (SQLCHAR *) fixupsql((char *) query, queryLen, &s->nparams,
14644 &s->isselect, &errp,
14645 d->version, &s->parmnames);
14646 if (!s->query) {
14647 if (errp) {
14648 setstat(s, -1, "%s", (*s->ov3) ? "HY000" : "S1000", errp);
14649 return SQL_ERROR;
14650 }
14651 return nomem(s);
14652 }
14653 #ifdef CANT_PASS_VALIST_AS_CHARPTR
14654 if (s->nparams > MAX_PARAMS_FOR_VPRINTF) {
14655 freep(&s->query);
14656 setstat(s, -1, "too much parameters in query",
14657 (*s->ov3) ? "HY000" : "S1000");
14658 return SQL_ERROR;
14659 }
14660 #endif
14661 errp = NULL;
14662 freeresult(s, -1);
14663 if (s->isselect == 1) {
14664 int ret;
14665 char **params = NULL;
14666
14667 if (s->nparams) {
14668 int i, maxp;
14669
14670 #ifdef CANT_PASS_VALIST_AS_CHARPTR
14671 maxp = MAX_PARAMS_FOR_VPRINTF;
14672 #else
14673 maxp = s->nparams;
14674 #endif
14675 params = xmalloc(maxp * sizeof (char *));
14676 if (!params) {
14677 return nomem(s);
14678 }
14679 for (i = 0; i < maxp; i++) {
14680 params[i] = NULL;
14681 }
14682 }
14683 #ifdef CANT_PASS_VALIST_AS_CHARPTR
14684 if (params) {
14685 ret = sqlite_exec_printf(d->sqlite, (char *) s->query, selcb, s,
14686 &errp,
14687 params[0], params[1],
14688 params[2], params[3],
14689 params[4], params[5],
14690 params[6], params[7],
14691 params[8], params[9],
14692 params[10], params[11],
14693 params[12], params[13],
14694 params[14], params[15],
14695 params[16], params[17],
14696 params[18], params[19],
14697 params[20], params[21],
14698 params[22], params[23],
14699 params[24], params[25],
14700 params[26], params[27],
14701 params[28], params[29],
14702 params[30], params[31]);
14703 } else {
14704 ret = sqlite_exec_printf(d->sqlite, (char *) s->query, selcb,
14705 s, &errp);
14706 }
14707 #else
14708 ret = sqlite_exec_vprintf(d->sqlite, (char *) s->query, selcb, s,
14709 &errp, (char *) params);
14710 #endif
14711 if (ret != SQLITE_ABORT && ret != SQLITE_OK) {
14712 dbtracerc(d, ret, errp);
14713 freep(¶ms);
14714 setstat(s, ret, "%s (%d)", (*s->ov3) ? "HY000" : "S1000",
14715 errp ? errp : "unknown error", ret);
14716 if (errp) {
14717 sqlite_freemem(errp);
14718 errp = NULL;
14719 }
14720 return SQL_ERROR;
14721 }
14722 freep(¶ms);
14723 if (errp) {
14724 sqlite_freemem(errp);
14725 errp = NULL;
14726 }
14727 }
14728 mkbindcols(s, s->ncols);
14729 s->paramset_count = 0;
14730 return SQL_SUCCESS;
14731 }
14732
14733 /**
14734 * Internal query execution used by SQLExecute() and SQLExecDirect().
14735 * @param stmt statement handle
14736 * @param initial false when called from SQLPutData()
14737 * @result ODBC error code
14738 */
14739
14740 static SQLRETURN
drvexecute(SQLHSTMT stmt,int initial)14741 drvexecute(SQLHSTMT stmt, int initial)
14742 {
14743 STMT *s;
14744 DBC *d;
14745 char *errp = NULL, **params = NULL;
14746 int rc, i, ncols;
14747 SQLRETURN ret;
14748
14749 if (stmt == SQL_NULL_HSTMT) {
14750 return SQL_INVALID_HANDLE;
14751 }
14752 s = (STMT *) stmt;
14753 if (s->dbc == SQL_NULL_HDBC) {
14754 noconn:
14755 return noconn(s);
14756 }
14757 d = (DBC *) s->dbc;
14758 if (!d->sqlite) {
14759 goto noconn;
14760 }
14761 if (!s->query) {
14762 setstat(s, -1, "no query prepared", (*s->ov3) ? "HY000" : "S1000");
14763 return SQL_ERROR;
14764 }
14765 if (s->nbindparms < s->nparams) {
14766 unbound:
14767 setstat(s, -1, "unbound parameters in query",
14768 (*s->ov3) ? "HY000" : "S1000");
14769 return SQL_ERROR;
14770 }
14771 for (i = 0; i < s->nparams; i++) {
14772 BINDPARM *p = &s->bindparms[i];
14773
14774 if (!p->bound) {
14775 goto unbound;
14776 }
14777 if (initial) {
14778 SQLLEN *lenp = p->lenp;
14779
14780 if (lenp && *lenp < 0 && *lenp > SQL_LEN_DATA_AT_EXEC_OFFSET &&
14781 *lenp != SQL_NTS && *lenp != SQL_NULL_DATA &&
14782 *lenp != SQL_DATA_AT_EXEC) {
14783 setstat(s, -1, "invalid length reference", "HY009");
14784 return SQL_ERROR;
14785 }
14786 if (lenp && (*lenp <= SQL_LEN_DATA_AT_EXEC_OFFSET ||
14787 *lenp == SQL_DATA_AT_EXEC)) {
14788 p->need = 1;
14789 p->offs = 0;
14790 p->len = 0;
14791 }
14792 }
14793 }
14794 ret = starttran(s);
14795 if (ret != SQL_SUCCESS) {
14796 goto cleanup;
14797 }
14798 again:
14799 vm_end(s);
14800 if (initial) {
14801 /* fixup data-at-execution parameters and alloc'ed blobs */
14802 s->pdcount = -1;
14803 for (i = 0; i < s->nparams; i++) {
14804 BINDPARM *p = &s->bindparms[i];
14805
14806 if (p->param == p->parbuf) {
14807 p->param = NULL;
14808 }
14809 freep(&p->parbuf);
14810 if (p->need <= 0 &&
14811 p->lenp && (*p->lenp <= SQL_LEN_DATA_AT_EXEC_OFFSET ||
14812 *p->lenp == SQL_DATA_AT_EXEC)) {
14813 p->need = 1;
14814 p->offs = 0;
14815 p->len = 0;
14816 }
14817 }
14818 }
14819 if (s->nparams) {
14820 int maxp;
14821
14822 #ifdef CANT_PASS_VALIST_AS_CHARPTR
14823 maxp = MAX_PARAMS_FOR_VPRINTF;
14824 #else
14825 maxp = s->nparams;
14826 #endif
14827 params = xmalloc(maxp * sizeof (char *));
14828 if (!params) {
14829 ret = nomem(s);
14830 goto cleanup;
14831 }
14832 for (i = 0; i < maxp; i++) {
14833 params[i] = NULL;
14834 }
14835 for (i = 0; i < s->nparams; i++) {
14836 ret = substparam(s, i, ¶ms[i]);
14837 if (ret != SQL_SUCCESS) {
14838 freep(¶ms);
14839 goto cleanup;
14840 }
14841 }
14842 }
14843 freeresult(s, 0);
14844 if (s->isselect == 1 && !d->intrans &&
14845 s->curtype == SQL_CURSOR_FORWARD_ONLY &&
14846 d->step_enable && s->nparams == 0 && d->vm_stmt == NULL) {
14847 s->nrows = -1;
14848 ret = vm_start(s, params);
14849 if (ret == SQL_SUCCESS) {
14850 freep(¶ms);
14851 goto done2;
14852 }
14853 }
14854 #ifdef CANT_PASS_VALIST_AS_CHARPTR
14855 if (params) {
14856 rc = sqlite_get_table_printf(d->sqlite, (char *) s->query, &s->rows,
14857 &s->nrows, &ncols, &errp,
14858 params[0], params[1],
14859 params[2], params[3],
14860 params[4], params[5],
14861 params[6], params[7],
14862 params[8], params[9],
14863 params[10], params[11],
14864 params[12], params[13],
14865 params[14], params[15],
14866 params[16], params[17],
14867 params[18], params[19],
14868 params[20], params[21],
14869 params[22], params[23],
14870 params[24], params[25],
14871 params[26], params[27],
14872 params[28], params[29],
14873 params[30], params[31]);
14874 } else {
14875 rc = sqlite_get_table_printf(d->sqlite, (char *) s->query, &s->rows,
14876 &s->nrows, &ncols, &errp);
14877 }
14878 #else
14879 rc = sqlite_get_table_vprintf(d->sqlite, (char *) s->query, &s->rows,
14880 &s->nrows, &ncols, &errp, (char *) params);
14881 #endif
14882 dbtracerc(d, rc, errp);
14883 if (rc != SQLITE_OK) {
14884 freep(¶ms);
14885 setstat(s, rc, "%s (%d)", (*s->ov3) ? "HY000" : "S1000",
14886 errp ? errp : "unknown error", rc);
14887 if (errp) {
14888 sqlite_freemem(errp);
14889 errp = NULL;
14890 }
14891 ret = SQL_ERROR;
14892 goto cleanup;
14893 }
14894 freep(¶ms);
14895 if (errp) {
14896 sqlite_freemem(errp);
14897 errp = NULL;
14898 }
14899 s->rowfree = sqlite_free_table;
14900 if (ncols == 1 && (s->isselect <= 0 || s->isselect > 1)) {
14901 /*
14902 * INSERT/UPDATE/DELETE or DDL results are immediately released.
14903 */
14904 if (strcmp(s->rows[0], "rows inserted") == 0 ||
14905 strcmp(s->rows[0], "rows updated") == 0 ||
14906 strcmp(s->rows[0], "rows deleted") == 0) {
14907 int nrows = 0;
14908
14909 nrows = strtol(s->rows[1], NULL, 0);
14910 freeresult(s, -1);
14911 s->nrows = nrows;
14912 goto done;
14913 }
14914 }
14915 if (s->ncols != ncols) {
14916 int size;
14917 char *p;
14918 COL *dyncols;
14919
14920 for (i = size = 0; i < ncols; i++) {
14921 size += 3 + 3 * strlen(s->rows[i]);
14922 }
14923 if (size == 0) {
14924 freeresult(s, -1);
14925 goto done;
14926 }
14927 dyncols = xmalloc(ncols * sizeof (COL) + size);
14928 if (!dyncols) {
14929 ret = nomem(s);
14930 goto cleanup;
14931 }
14932 p = (char *) (dyncols + ncols);
14933 for (i = 0; i < ncols; i++) {
14934 char *q;
14935
14936 dyncols[i].db = d->dbname;
14937 strcpy(p, s->rows[i]);
14938 dyncols[i].label = p;
14939 p += strlen(p) + 1;
14940 q = strchr(s->rows[i], '.');
14941 if (q) {
14942 dyncols[i].table = p;
14943 strncpy(p, s->rows[i], q - s->rows[i]);
14944 p[q - s->rows[i]] = '\0';
14945 p += strlen(p) + 1;
14946 dyncols[i].column = q + 1;
14947 } else {
14948 dyncols[i].table = "";
14949 dyncols[i].column = s->rows[i];
14950 }
14951 if (s->longnames) {
14952 dyncols[i].column = dyncols[i].label;
14953 }
14954 #ifdef SQL_LONGVARCHAR
14955 dyncols[i].type = SQL_LONGVARCHAR;
14956 dyncols[i].size = 65536;
14957 #else
14958 dyncols[i].type = SQL_VARCHAR;
14959 dyncols[i].size = 255;
14960 #endif
14961 dyncols[i].index = i;
14962 dyncols[i].scale = 0;
14963 dyncols[i].prec = 0;
14964 dyncols[i].nosign = 1;
14965 dyncols[i].autoinc = SQL_FALSE;
14966 dyncols[i].notnull = SQL_NULLABLE;
14967 dyncols[i].typename = NULL;
14968 }
14969 freedyncols(s);
14970 s->ncols = s->dcols = ncols;
14971 s->dyncols = s->cols = dyncols;
14972 fixupdyncols(s, d->sqlite, NULL);
14973 }
14974 done:
14975 mkbindcols(s, s->ncols);
14976 done2:
14977 ret = SQL_SUCCESS;
14978 s->rowp = -1;
14979 s->paramset_count++;
14980 s->paramset_nrows += s->nrows;
14981 if (s->paramset_count < s->paramset_size) {
14982 for (i = 0; i < s->nparams; i++) {
14983 BINDPARM *p = &s->bindparms[i];
14984
14985 if (p->param == p->parbuf) {
14986 p->param = NULL;
14987 }
14988 freep(&p->parbuf);
14989 if (p->lenp0 &&
14990 s->parm_bind_type != SQL_PARAM_BIND_BY_COLUMN) {
14991 p->lenp = (SQLLEN *) ((char *) p->lenp0 +
14992 s->paramset_count * s->parm_bind_type);
14993 } else if (p->lenp0 && p->inc > 0) {
14994 p->lenp = p->lenp0 + s->paramset_count;
14995 }
14996 if (!p->lenp || (*p->lenp > SQL_LEN_DATA_AT_EXEC_OFFSET &&
14997 *p->lenp != SQL_DATA_AT_EXEC)) {
14998 if (p->param0 &&
14999 s->parm_bind_type != SQL_PARAM_BIND_BY_COLUMN) {
15000 p->param = (char *) p->param0 +
15001 s->paramset_count * s->parm_bind_type;
15002 } else if (p->param0 && p->inc > 0) {
15003 p->param = (char *) p->param0 +
15004 s->paramset_count * p->inc;
15005 }
15006 } else if (p->lenp && (*p->lenp <= SQL_LEN_DATA_AT_EXEC_OFFSET ||
15007 *p->lenp == SQL_DATA_AT_EXEC)) {
15008 p->need = 1;
15009 p->offs = 0;
15010 p->len = 0;
15011 }
15012 }
15013 goto again;
15014 }
15015 cleanup:
15016 if (ret != SQL_NEED_DATA) {
15017 for (i = 0; i < s->nparams; i++) {
15018 BINDPARM *p = &s->bindparms[i];
15019
15020 if (p->param == p->parbuf) {
15021 p->param = NULL;
15022 }
15023 freep(&p->parbuf);
15024 if (!p->lenp || (*p->lenp > SQL_LEN_DATA_AT_EXEC_OFFSET &&
15025 *p->lenp != SQL_DATA_AT_EXEC)) {
15026 p->param = p->param0;
15027 }
15028 p->lenp = p->lenp0;
15029 }
15030 s->nrows = s->paramset_nrows;
15031 if (s->parm_proc) {
15032 *s->parm_proc = s->paramset_count;
15033 }
15034 s->paramset_count = 0;
15035 s->paramset_nrows = 0;
15036 }
15037 return ret;
15038 }
15039
15040 #ifndef WINTERFACE
15041 /**
15042 * Prepare HSTMT.
15043 * @param stmt statement handle
15044 * @param query query string
15045 * @param queryLen length of query string or SQL_NTS
15046 * @result ODBC error code
15047 */
15048
15049 SQLRETURN SQL_API
SQLPrepare(SQLHSTMT stmt,SQLCHAR * query,SQLINTEGER queryLen)15050 SQLPrepare(SQLHSTMT stmt, SQLCHAR *query, SQLINTEGER queryLen)
15051 {
15052 SQLRETURN ret;
15053
15054 HSTMT_LOCK(stmt);
15055 ret = drvprepare(stmt, query, queryLen);
15056 HSTMT_UNLOCK(stmt);
15057 return ret;
15058 }
15059 #endif
15060
15061 #ifdef WINTERFACE
15062 /**
15063 * Prepare HSTMT (UNICODE version).
15064 * @param stmt statement handle
15065 * @param query query string
15066 * @param queryLen length of query string or SQL_NTS
15067 * @result ODBC error code
15068 */
15069
15070 SQLRETURN SQL_API
SQLPrepareW(SQLHSTMT stmt,SQLWCHAR * query,SQLINTEGER queryLen)15071 SQLPrepareW(SQLHSTMT stmt, SQLWCHAR *query, SQLINTEGER queryLen)
15072 {
15073 SQLRETURN ret;
15074 char *q = uc_to_utf_c(query, queryLen);
15075
15076 HSTMT_LOCK(stmt);
15077 if (!q) {
15078 ret = nomem((STMT *) stmt);
15079 goto done;
15080 }
15081 ret = drvprepare(stmt, (SQLCHAR *) q, SQL_NTS);
15082 uc_free(q);
15083 done:
15084 HSTMT_UNLOCK(stmt);
15085 return ret;
15086 }
15087 #endif
15088
15089 /**
15090 * Execute query.
15091 * @param stmt statement handle
15092 * @result ODBC error code
15093 */
15094
15095 SQLRETURN SQL_API
SQLExecute(SQLHSTMT stmt)15096 SQLExecute(SQLHSTMT stmt)
15097 {
15098 SQLRETURN ret;
15099
15100 HSTMT_LOCK(stmt);
15101 ret = drvexecute(stmt, 1);
15102 HSTMT_UNLOCK(stmt);
15103 return ret;
15104 }
15105
15106 #ifndef WINTERFACE
15107 /**
15108 * Execute query directly.
15109 * @param stmt statement handle
15110 * @param query query string
15111 * @param queryLen length of query string or SQL_NTS
15112 * @result ODBC error code
15113 */
15114
15115 SQLRETURN SQL_API
SQLExecDirect(SQLHSTMT stmt,SQLCHAR * query,SQLINTEGER queryLen)15116 SQLExecDirect(SQLHSTMT stmt, SQLCHAR *query, SQLINTEGER queryLen)
15117 {
15118 SQLRETURN ret;
15119
15120 HSTMT_LOCK(stmt);
15121 ret = drvprepare(stmt, query, queryLen);
15122 if (ret == SQL_SUCCESS) {
15123 ret = drvexecute(stmt, 1);
15124 }
15125 HSTMT_UNLOCK(stmt);
15126 return ret;
15127 }
15128 #endif
15129
15130 #ifdef WINTERFACE
15131 /**
15132 * Execute query directly (UNICODE version).
15133 * @param stmt statement handle
15134 * @param query query string
15135 * @param queryLen length of query string or SQL_NTS
15136 * @result ODBC error code
15137 */
15138
15139 SQLRETURN SQL_API
SQLExecDirectW(SQLHSTMT stmt,SQLWCHAR * query,SQLINTEGER queryLen)15140 SQLExecDirectW(SQLHSTMT stmt, SQLWCHAR *query, SQLINTEGER queryLen)
15141 {
15142 SQLRETURN ret;
15143 char *q = uc_to_utf_c(query, queryLen);
15144
15145 HSTMT_LOCK(stmt);
15146 if (!q) {
15147 ret = nomem((STMT *) stmt);
15148 goto done;
15149 }
15150 ret = drvprepare(stmt, (SQLCHAR *) q, SQL_NTS);
15151 uc_free(q);
15152 if (ret == SQL_SUCCESS) {
15153 ret = drvexecute(stmt, 1);
15154 }
15155 done:
15156 HSTMT_UNLOCK(stmt);
15157 return ret;
15158 }
15159 #endif
15160
15161 #if defined(_WIN32) || defined(_WIN64) || defined(__OS2__)
15162
15163 #ifndef WITHOUT_DRIVERMGR
15164
15165 #if defined(_WIN32) || defined(_WIN64)
15166 /*
15167 * Windows configuration dialog stuff.
15168 */
15169
15170 #include <windowsx.h>
15171 #include <winuser.h>
15172
15173 #endif
15174
15175 #ifdef __OS2__
15176 #define INCL_WIN
15177 #define INCL_PM
15178 #define INCL_DOSMODULEMGR
15179 #define INCL_DOSERRORS
15180 #define INCL_WINSTDFILE
15181
15182 #include <os2.h>
15183 #include <stdlib.h>
15184
15185 #include "resourceos2.h"
15186
15187 #endif
15188
15189 #define MAXPATHLEN (259+1) /* Max path length */
15190 #define MAXKEYLEN (15+1) /* Max keyword length */
15191 #define MAXDESC (255+1) /* Max description length */
15192 #define MAXDSNAME (255+1) /* Max data source name length */
15193 #define MAXTONAME (32+1) /* Max timeout length */
15194 #define MAXDBNAME MAXPATHLEN
15195
15196 /* Attribute key indexes into an array of Attr structs, see below */
15197
15198 #define KEY_DSN 0
15199 #define KEY_DESC 1
15200 #define KEY_DBNAME 2
15201 #define KEY_BUSY 3
15202 #define KEY_DRIVER 4
15203 #define KEY_NOWCHAR 5
15204 #define KEY_STEPAPI 6
15205 #define KEY_NOTXN 7
15206 #define KEY_LONGNAM 8
15207 #define NUMOFKEYS 9
15208
15209 typedef struct {
15210 BOOL supplied;
15211 char attr[MAXPATHLEN];
15212 } ATTR;
15213
15214 typedef struct {
15215 SQLHWND parent;
15216 #ifdef __OS2__
15217 HMODULE hDLL;
15218 #endif
15219 LPCSTR driver;
15220 ATTR attr[NUMOFKEYS];
15221 char DSN[MAXDSNAME];
15222 BOOL newDSN;
15223 BOOL defDSN;
15224 } SETUPDLG;
15225
15226 static struct {
15227 char *key;
15228 int ikey;
15229 } attrLookup[] = {
15230 { "DSN", KEY_DSN },
15231 { "DESC", KEY_DESC },
15232 { "Description", KEY_DESC},
15233 { "Database", KEY_DBNAME },
15234 { "Timeout", KEY_BUSY },
15235 { "Driver", KEY_DRIVER },
15236 { "NoWCHAR", KEY_NOWCHAR },
15237 { "StepAPI", KEY_STEPAPI },
15238 { "NoTXN", KEY_NOTXN },
15239 { "LongNames", KEY_LONGNAM },
15240 { NULL, 0 }
15241 };
15242
15243 /**
15244 * Setup dialog data from datasource attributes.
15245 * @param attribs attribute string
15246 * @param setupdlg pointer to dialog data
15247 */
15248
15249 static void
ParseAttributes(LPCSTR attribs,SETUPDLG * setupdlg)15250 ParseAttributes(LPCSTR attribs, SETUPDLG *setupdlg)
15251 {
15252 char *str = (char *) attribs, *start, key[MAXKEYLEN];
15253 int elem, nkey;
15254
15255 while (*str) {
15256 start = str;
15257 if ((str = strchr(str, '=')) == NULL) {
15258 return;
15259 }
15260 elem = -1;
15261 nkey = str - start;
15262 if (nkey < sizeof (key)) {
15263 int i;
15264
15265 memcpy(key, start, nkey);
15266 key[nkey] = '\0';
15267 for (i = 0; attrLookup[i].key; i++) {
15268 if (strcasecmp(attrLookup[i].key, key) == 0) {
15269 elem = attrLookup[i].ikey;
15270 break;
15271 }
15272 }
15273 }
15274 start = ++str;
15275 while (*str && *str != ';') {
15276 ++str;
15277 }
15278 if (elem >= 0) {
15279 int end = min(str - start, sizeof (setupdlg->attr[elem].attr) - 1);
15280
15281 setupdlg->attr[elem].supplied = TRUE;
15282 memcpy(setupdlg->attr[elem].attr, start, end);
15283 setupdlg->attr[elem].attr[end] = '\0';
15284 }
15285 ++str;
15286 }
15287 }
15288
15289 /**
15290 * Set datasource attributes in registry.
15291 * @param parent handle of parent window
15292 * @param setupdlg pointer to dialog data
15293 * @result true or false
15294 */
15295
15296 static BOOL
SetDSNAttributes(HWND parent,SETUPDLG * setupdlg)15297 SetDSNAttributes(HWND parent, SETUPDLG *setupdlg)
15298 {
15299 char *dsn = setupdlg->attr[KEY_DSN].attr;
15300
15301 if (setupdlg->newDSN && strlen(dsn) == 0) {
15302 return FALSE;
15303 }
15304 if (!SQLWriteDSNToIni(dsn, setupdlg->driver)) {
15305 if (parent) {
15306 #if defined(_WIN32) || defined(_WIN64)
15307 char buf[MAXPATHLEN], msg[MAXPATHLEN];
15308
15309 LoadString(hModule, IDS_BADDSN, buf, sizeof (buf));
15310 wsprintf(msg, buf, dsn);
15311 LoadString(hModule, IDS_MSGTITLE, buf, sizeof (buf));
15312 MessageBox(parent, msg, buf,
15313 MB_ICONEXCLAMATION | MB_OK | MB_TASKMODAL |
15314 MB_SETFOREGROUND);
15315 #endif
15316 #ifdef __OS2__
15317 WinMessageBox(HWND_DESKTOP, parent, "Bad DSN", "Configure Error",
15318 0, MB_ERROR | MB_OK );
15319 #endif
15320 }
15321 return FALSE;
15322 }
15323 if (parent || setupdlg->attr[KEY_DESC].supplied) {
15324 SQLWritePrivateProfileString(dsn, "Description",
15325 setupdlg->attr[KEY_DESC].attr,
15326 ODBC_INI);
15327 }
15328 if (parent || setupdlg->attr[KEY_DBNAME].supplied) {
15329 SQLWritePrivateProfileString(dsn, "Database",
15330 setupdlg->attr[KEY_DBNAME].attr,
15331 ODBC_INI);
15332 }
15333 if (parent || setupdlg->attr[KEY_BUSY].supplied) {
15334 SQLWritePrivateProfileString(dsn, "Timeout",
15335 setupdlg->attr[KEY_BUSY].attr,
15336 ODBC_INI);
15337 }
15338 if (parent || setupdlg->attr[KEY_NOWCHAR].supplied) {
15339 SQLWritePrivateProfileString(dsn, "NoWCHAR",
15340 setupdlg->attr[KEY_NOWCHAR].attr,
15341 ODBC_INI);
15342 }
15343 if (parent || setupdlg->attr[KEY_STEPAPI].supplied) {
15344 SQLWritePrivateProfileString(dsn, "StepAPI",
15345 setupdlg->attr[KEY_STEPAPI].attr,
15346 ODBC_INI);
15347 }
15348 if (parent || setupdlg->attr[KEY_NOTXN].supplied) {
15349 SQLWritePrivateProfileString(dsn, "NoTXN",
15350 setupdlg->attr[KEY_NOTXN].attr,
15351 ODBC_INI);
15352 }
15353 if (parent || setupdlg->attr[KEY_LONGNAM].supplied) {
15354 SQLWritePrivateProfileString(dsn, "LongNames",
15355 setupdlg->attr[KEY_LONGNAM].attr,
15356 ODBC_INI);
15357 }
15358 if (setupdlg->attr[KEY_DSN].supplied &&
15359 strcasecmp(setupdlg->DSN, setupdlg->attr[KEY_DSN].attr)) {
15360 SQLRemoveDSNFromIni(setupdlg->DSN);
15361 }
15362 return TRUE;
15363 }
15364
15365 /**
15366 * Get datasource attributes from registry.
15367 * @param setupdlg pointer to dialog data
15368 */
15369
15370 static void
GetAttributes(SETUPDLG * setupdlg)15371 GetAttributes(SETUPDLG *setupdlg)
15372 {
15373 char *dsn = setupdlg->attr[KEY_DSN].attr;
15374
15375 if (!setupdlg->attr[KEY_DESC].supplied) {
15376 SQLGetPrivateProfileString(dsn, "Description", "",
15377 setupdlg->attr[KEY_DESC].attr,
15378 sizeof (setupdlg->attr[KEY_DESC].attr),
15379 ODBC_INI);
15380 }
15381 if (!setupdlg->attr[KEY_DBNAME].supplied) {
15382 SQLGetPrivateProfileString(dsn, "Database", "",
15383 setupdlg->attr[KEY_DBNAME].attr,
15384 sizeof (setupdlg->attr[KEY_DBNAME].attr),
15385 ODBC_INI);
15386 }
15387 if (!setupdlg->attr[KEY_BUSY].supplied) {
15388 SQLGetPrivateProfileString(dsn, "Timeout", "100000",
15389 setupdlg->attr[KEY_BUSY].attr,
15390 sizeof (setupdlg->attr[KEY_BUSY].attr),
15391 ODBC_INI);
15392 }
15393 if (!setupdlg->attr[KEY_NOWCHAR].supplied) {
15394 SQLGetPrivateProfileString(dsn, "NoWCHAR", "",
15395 setupdlg->attr[KEY_NOWCHAR].attr,
15396 sizeof (setupdlg->attr[KEY_NOWCHAR].attr),
15397 ODBC_INI);
15398 }
15399 if (!setupdlg->attr[KEY_STEPAPI].supplied) {
15400 SQLGetPrivateProfileString(dsn, "StepAPI", "0",
15401 setupdlg->attr[KEY_STEPAPI].attr,
15402 sizeof (setupdlg->attr[KEY_STEPAPI].attr),
15403 ODBC_INI);
15404 }
15405 if (!setupdlg->attr[KEY_NOTXN].supplied) {
15406 SQLGetPrivateProfileString(dsn, "NoTXN", "",
15407 setupdlg->attr[KEY_NOTXN].attr,
15408 sizeof (setupdlg->attr[KEY_NOTXN].attr),
15409 ODBC_INI);
15410 }
15411 if (!setupdlg->attr[KEY_LONGNAM].supplied) {
15412 SQLGetPrivateProfileString(dsn, "LongNames", "",
15413 setupdlg->attr[KEY_LONGNAM].attr,
15414 sizeof (setupdlg->attr[KEY_LONGNAM].attr),
15415 ODBC_INI);
15416 }
15417 }
15418
15419 /**
15420 * Open file dialog for selection of SQLite database file.
15421 * @param hdlg handle of originating dialog window
15422 */
15423
15424 static void
GetDBFile(HWND hdlg)15425 GetDBFile(HWND hdlg)
15426 {
15427 #if defined(_WIN32) || defined(_WIN64)
15428 #ifdef _WIN64
15429 SETUPDLG *setupdlg = (SETUPDLG *) GetWindowLongPtr(hdlg, DWLP_USER);
15430 #else
15431 SETUPDLG *setupdlg = (SETUPDLG *) GetWindowLong(hdlg, DWL_USER);
15432 #endif
15433 OPENFILENAME ofn;
15434
15435 memset(&ofn, 0, sizeof (ofn));
15436 ofn.lStructSize = sizeof (ofn);
15437 ofn.hwndOwner = hdlg;
15438 #ifdef _WIN64
15439 ofn.hInstance = (HINSTANCE) GetWindowLongPtr(hdlg, GWLP_HINSTANCE);
15440 #else
15441 ofn.hInstance = (HINSTANCE) GetWindowLong(hdlg, GWL_HINSTANCE);
15442 #endif
15443 ofn.lpstrFile = (LPTSTR) setupdlg->attr[KEY_DBNAME].attr;
15444 ofn.nMaxFile = MAXPATHLEN;
15445 ofn.Flags = OFN_HIDEREADONLY | OFN_PATHMUSTEXIST |
15446 OFN_NOCHANGEDIR | OFN_EXPLORER | OFN_FILEMUSTEXIST;
15447 if (GetOpenFileName(&ofn)) {
15448 SetDlgItemText(hdlg, IDC_DBNAME, setupdlg->attr[KEY_DBNAME].attr);
15449 setupdlg->attr[KEY_DBNAME].supplied = TRUE;
15450 }
15451 #endif
15452 #ifdef __OS2__
15453 SETUPDLG *setupdlg = (SETUPDLG *) WinQueryWindowULong(hdlg, QWL_USER);
15454 FILEDLG ofn;
15455
15456 memset(&ofn, 0, sizeof (ofn));
15457 ofn.cbSize = sizeof (FILEDLG);
15458 strcpy(ofn.szFullFile, setupdlg->attr[KEY_DBNAME].attr);
15459 ofn.fl = FDS_OPEN_DIALOG | FDS_CENTER;
15460 WinFileDlg(hdlg, hdlg, &ofn);
15461 if (ofn.lReturn == DID_OK) {
15462 strcpy(setupdlg->attr[KEY_DBNAME].attr, ofn.szFullFile);
15463 WinSetDlgItemText(hdlg, EF_DATABASE, setupdlg->attr[KEY_DBNAME].attr);
15464 setupdlg->attr[KEY_DBNAME].supplied = TRUE;
15465 }
15466 #endif
15467 }
15468
15469 #if defined(_WIN32) || defined(_WIN64)
15470 /**
15471 * Dialog procedure for ConfigDSN().
15472 * @param hdlg handle of dialog window
15473 * @param wmsg type of message
15474 * @param wparam wparam of message
15475 * @param lparam lparam of message
15476 * @result true or false
15477 */
15478
15479 static BOOL CALLBACK
ConfigDlgProc(HWND hdlg,WORD wmsg,WPARAM wparam,LPARAM lparam)15480 ConfigDlgProc(HWND hdlg, WORD wmsg, WPARAM wparam, LPARAM lparam)
15481 {
15482 SETUPDLG *setupdlg = NULL;
15483
15484 switch (wmsg) {
15485 case WM_INITDIALOG:
15486 #ifdef _WIN64
15487 SetWindowLongPtr(hdlg, DWLP_USER, lparam);
15488 #else
15489 SetWindowLong(hdlg, DWL_USER, lparam);
15490 #endif
15491 setupdlg = (SETUPDLG *) lparam;
15492 GetAttributes(setupdlg);
15493 SetDlgItemText(hdlg, IDC_DSNAME, setupdlg->attr[KEY_DSN].attr);
15494 SetDlgItemText(hdlg, IDC_DESC, setupdlg->attr[KEY_DESC].attr);
15495 SetDlgItemText(hdlg, IDC_DBNAME, setupdlg->attr[KEY_DBNAME].attr);
15496 SetDlgItemText(hdlg, IDC_TONAME, setupdlg->attr[KEY_BUSY].attr);
15497 SendDlgItemMessage(hdlg, IDC_DSNAME, EM_LIMITTEXT,
15498 (WPARAM) (MAXDSNAME - 1), (LPARAM) 0);
15499 SendDlgItemMessage(hdlg, IDC_DESC, EM_LIMITTEXT,
15500 (WPARAM) (MAXDESC - 1), (LPARAM) 0);
15501 SendDlgItemMessage(hdlg, IDC_DBNAME, EM_LIMITTEXT,
15502 (WPARAM) (MAXDBNAME - 1), (LPARAM) 0);
15503 SendDlgItemMessage(hdlg, IDC_TONAME, EM_LIMITTEXT,
15504 (WPARAM) (MAXTONAME - 1), (LPARAM) 0);
15505 CheckDlgButton(hdlg, IDC_NOWCHAR,
15506 getbool(setupdlg->attr[KEY_NOWCHAR].attr) ?
15507 BST_CHECKED : BST_UNCHECKED);
15508 CheckDlgButton(hdlg, IDC_STEPAPI,
15509 getbool(setupdlg->attr[KEY_STEPAPI].attr) ?
15510 BST_CHECKED : BST_UNCHECKED);
15511 CheckDlgButton(hdlg, IDC_NOTXN,
15512 getbool(setupdlg->attr[KEY_NOTXN].attr) ?
15513 BST_CHECKED : BST_UNCHECKED);
15514 CheckDlgButton(hdlg, IDC_LONGNAM,
15515 getbool(setupdlg->attr[KEY_LONGNAM].attr) ?
15516 BST_CHECKED : BST_UNCHECKED);
15517 if (setupdlg->defDSN) {
15518 EnableWindow(GetDlgItem(hdlg, IDC_DSNAME), FALSE);
15519 EnableWindow(GetDlgItem(hdlg, IDC_DSNAMETEXT), FALSE);
15520 }
15521 return TRUE;
15522 case WM_COMMAND:
15523 switch (GET_WM_COMMAND_ID(wparam, lparam)) {
15524 case IDC_DSNAME:
15525 if (GET_WM_COMMAND_CMD(wparam, lparam) == EN_CHANGE) {
15526 char item[MAXDSNAME];
15527
15528 EnableWindow(GetDlgItem(hdlg, IDOK),
15529 GetDlgItemText(hdlg, IDC_DSNAME,
15530 item, sizeof (item)));
15531 return TRUE;
15532 }
15533 break;
15534 case IDC_BROWSE:
15535 GetDBFile(hdlg);
15536 break;
15537 case IDOK:
15538 #ifdef _WIN64
15539 setupdlg = (SETUPDLG *) GetWindowLongPtr(hdlg, DWLP_USER);
15540 #else
15541 setupdlg = (SETUPDLG *) GetWindowLong(hdlg, DWL_USER);
15542 #endif
15543 if (!setupdlg->defDSN) {
15544 GetDlgItemText(hdlg, IDC_DSNAME,
15545 setupdlg->attr[KEY_DSN].attr,
15546 sizeof (setupdlg->attr[KEY_DSN].attr));
15547 }
15548 GetDlgItemText(hdlg, IDC_DESC,
15549 setupdlg->attr[KEY_DESC].attr,
15550 sizeof (setupdlg->attr[KEY_DESC].attr));
15551 GetDlgItemText(hdlg, IDC_DBNAME,
15552 setupdlg->attr[KEY_DBNAME].attr,
15553 sizeof (setupdlg->attr[KEY_DBNAME].attr));
15554 GetDlgItemText(hdlg, IDC_TONAME,
15555 setupdlg->attr[KEY_BUSY].attr,
15556 sizeof (setupdlg->attr[KEY_BUSY].attr));
15557 strcpy(setupdlg->attr[KEY_NOWCHAR].attr,
15558 (IsDlgButtonChecked(hdlg, IDC_NOWCHAR) == BST_CHECKED) ?
15559 "1" : "0");
15560 strcpy(setupdlg->attr[KEY_STEPAPI].attr,
15561 (IsDlgButtonChecked(hdlg, IDC_STEPAPI) == BST_CHECKED) ?
15562 "1" : "0");
15563 strcpy(setupdlg->attr[KEY_NOTXN].attr,
15564 (IsDlgButtonChecked(hdlg, IDC_NOTXN) == BST_CHECKED) ?
15565 "1" : "0");
15566 strcpy(setupdlg->attr[KEY_LONGNAM].attr,
15567 (IsDlgButtonChecked(hdlg, IDC_LONGNAM) == BST_CHECKED) ?
15568 "1" : "0");
15569 SetDSNAttributes(hdlg, setupdlg);
15570 /* FALL THROUGH */
15571 case IDCANCEL:
15572 EndDialog(hdlg, wparam);
15573 return TRUE;
15574 }
15575 break;
15576 }
15577 return FALSE;
15578 }
15579 #endif
15580
15581 #ifdef __OS2__
15582 /**
15583 * Dialog procedure for ConfigDSN().
15584 * @param hdlg handle of dialog window
15585 * @param wmsg type of message
15586 * @param wparam wparam of message
15587 * @param lparam lparam of message
15588 * @result standard MRESULT
15589 */
15590
15591 static MRESULT EXPENTRY
ConfigDlgProc(HWND hdlg,ULONG wmsg,MPARAM wparam,MPARAM lparam)15592 ConfigDlgProc(HWND hdlg, ULONG wmsg, MPARAM wparam, MPARAM lparam)
15593 {
15594 SETUPDLG *setupdlg = NULL;
15595
15596 switch (wmsg) {
15597 case WM_INITDLG:
15598 WinSetWindowULong(hdlg, QWL_USER, (ULONG) lparam);
15599 setupdlg = (SETUPDLG *) lparam;
15600 GetAttributes(setupdlg);
15601 WinSetDlgItemText(hdlg, EF_DSNNAME, setupdlg->attr[KEY_DSN].attr);
15602 WinSetDlgItemText(hdlg, EF_DSNDESC, setupdlg->attr[KEY_DESC].attr);
15603 WinSetDlgItemText(hdlg, EF_DATABASE, setupdlg->attr[KEY_DBNAME].attr);
15604 WinSetDlgItemText(hdlg, EF_TIMEOUT, setupdlg->attr[KEY_BUSY].attr);
15605 WinSendDlgItemMsg(hdlg, EF_DSNNAME, EM_SETTEXTLIMIT,
15606 MPFROMSHORT(MAXDSNAME - 1), 0L);
15607 WinSendDlgItemMsg(hdlg, EF_DSNDESC, EM_SETTEXTLIMIT,
15608 MPFROMSHORT(MAXDESC - 1), 0L);
15609 WinSendDlgItemMsg(hdlg, EF_DATABASE, EM_SETTEXTLIMIT,
15610 MPFROMSHORT(MAXDBNAME - 1), 0L);
15611 WinSendDlgItemMsg(hdlg, EF_TIMEOUT, EM_SETTEXTLIMIT,
15612 MPFROMSHORT(MAXTONAME - 1), 0L);
15613 WinCheckButton(hdlg, IDC_NOWCHAR,
15614 getbool(setupdlg->attr[KEY_NOWCHAR].attr));
15615 WinCheckButton(hdlg, IDC_STEPAPI,
15616 getbool(setupdlg->attr[KEY_STEPAPI].attr));
15617 WinCheckButton(hdlg, IDC_NOTXN,
15618 getbool(setupdlg->attr[KEY_NOTXN].attr));
15619 WinCheckButton(hdlg, IDC_LONGNAM,
15620 getbool(setupdlg->attr[KEY_LONGNAM].attr));
15621 if (setupdlg->defDSN) {
15622 WinEnableWindow(WinWindowFromID(hdlg, EF_DSNNAME), FALSE);
15623 }
15624 return 0;
15625 case WM_COMMAND:
15626 switch (SHORT1FROMMP(wparam)) {
15627 case IDC_BROWSE:
15628 GetDBFile(hdlg);
15629 break;
15630 case DID_OK:
15631 setupdlg = (SETUPDLG *) WinQueryWindowULong(hdlg, QWL_USER);
15632 if (!setupdlg->defDSN) {
15633 WinQueryDlgItemText(hdlg, EF_DSNNAME,
15634 sizeof (setupdlg->attr[KEY_DSN].attr),
15635 setupdlg->attr[KEY_DSN].attr);
15636 }
15637 WinQueryDlgItemText(hdlg, EF_DSNDESC,
15638 sizeof (setupdlg->attr[KEY_DESC].attr),
15639 setupdlg->attr[KEY_DESC].attr);
15640 WinQueryDlgItemText(hdlg, EF_DATABASE,
15641 sizeof (setupdlg->attr[KEY_DBNAME].attr),
15642 setupdlg->attr[KEY_DBNAME].attr);
15643 WinQueryDlgItemText(hdlg, EF_TIMEOUT,
15644 sizeof (setupdlg->attr[KEY_BUSY].attr),
15645 setupdlg->attr[KEY_BUSY].attr);
15646 if ((ULONG)WinSendDlgItemMsg(hdlg, IDC_NOWCHAR, BM_QUERYCHECK,
15647 0, 0) == 1) {
15648 strcpy(setupdlg->attr[KEY_NOWCHAR].attr, "1");
15649 } else {
15650 strcpy(setupdlg->attr[KEY_NOWCHAR].attr, "0");
15651 }
15652 if ((ULONG)WinSendDlgItemMsg(hdlg, IDC_STEPAPI, BM_QUERYCHECK,
15653 0, 0) == 1) {
15654 strcpy(setupdlg->attr[KEY_STEPAPI].attr, "1");
15655 } else {
15656 strcpy(setupdlg->attr[KEY_STEPAPI].attr, "0");
15657 }
15658 if ((ULONG)WinSendDlgItemMsg(hdlg, IDC_NOTXN, BM_QUERYCHECK,
15659 0, 0) == 1) {
15660 strcpy(setupdlg->attr[KEY_NOTXN].attr, "1");
15661 } else {
15662 strcpy(setupdlg->attr[KEY_NOTXN].attr, "0");
15663 }
15664 if ((ULONG)WinSendDlgItemMsg(hdlg, IDC_LONGNAM, BM_QUERYCHECK,
15665 0, 0) == 1) {
15666 strcpy(setupdlg->attr[KEY_LONGNAM].attr, "1");
15667 } else {
15668 strcpy(setupdlg->attr[KEY_LONGNAM].attr, "0");
15669 }
15670 SetDSNAttributes(hdlg, setupdlg);
15671 WinDismissDlg(hdlg, DID_OK);
15672 return 0;
15673 case DID_CANCEL:
15674 WinDismissDlg(hdlg, DID_OK);
15675 return 0;
15676 }
15677 break;
15678 }
15679 return WinDefDlgProc(hdlg, wmsg, wparam, lparam);
15680 }
15681 #endif
15682
15683 /**
15684 * ODBC INSTAPI procedure for DSN configuration.
15685 * @param hwnd parent window handle
15686 * @param request type of request
15687 * @param driver driver name
15688 * @param attribs attribute string of DSN
15689 * @result true or false
15690 */
15691
15692 BOOL INSTAPI
ConfigDSN(HWND hwnd,WORD request,LPCSTR driver,LPCSTR attribs)15693 ConfigDSN(HWND hwnd, WORD request, LPCSTR driver, LPCSTR attribs)
15694 {
15695 BOOL success;
15696 SETUPDLG *setupdlg;
15697
15698 setupdlg = (SETUPDLG *) xmalloc(sizeof (SETUPDLG));
15699 if (setupdlg == NULL) {
15700 return FALSE;
15701 }
15702 memset(setupdlg, 0, sizeof (SETUPDLG));
15703 if (attribs) {
15704 ParseAttributes(attribs, setupdlg);
15705 }
15706 if (setupdlg->attr[KEY_DSN].supplied) {
15707 strcpy(setupdlg->DSN, setupdlg->attr[KEY_DSN].attr);
15708 } else {
15709 setupdlg->DSN[0] = '\0';
15710 }
15711 if (request == ODBC_REMOVE_DSN) {
15712 if (!setupdlg->attr[KEY_DSN].supplied) {
15713 success = FALSE;
15714 } else {
15715 success = SQLRemoveDSNFromIni(setupdlg->attr[KEY_DSN].attr);
15716 }
15717 } else {
15718 #if defined(_WIN32) || defined(_WIN64)
15719 setupdlg->parent = hwnd;
15720 #endif
15721 #ifdef __OS2__
15722 setupdlg->parent = (SQLHWND) hwnd;
15723 #endif
15724 setupdlg->driver = driver;
15725 setupdlg->newDSN = request == ODBC_ADD_DSN;
15726 setupdlg->defDSN = strcasecmp(setupdlg->attr[KEY_DSN].attr,
15727 "Default") == 0;
15728 if (hwnd) {
15729 #if defined(_WIN32) || defined(_WIN64)
15730 success = DialogBoxParam(hModule, MAKEINTRESOURCE(CONFIGDSN),
15731 hwnd, (DLGPROC) ConfigDlgProc,
15732 (LPARAM) setupdlg) == IDOK;
15733 #endif
15734 #ifdef __OS2__
15735 HMODULE hDLL;
15736
15737 DosQueryModuleHandle("SQLLODBC.DLL", &hDLL);
15738 setupdlg->hDLL = hDLL;
15739 success = WinDlgBox(HWND_DESKTOP, hwnd, ConfigDlgProc, hDLL,
15740 DLG_SQLITEODBCCONFIGURATION, setupdlg);
15741 success = (success == DID_OK) ? TRUE : FALSE;
15742 #endif
15743 } else if (setupdlg->attr[KEY_DSN].supplied) {
15744 success = SetDSNAttributes(hwnd, setupdlg);
15745 } else {
15746 success = FALSE;
15747 }
15748 }
15749 xfree(setupdlg);
15750 return success;
15751 }
15752
15753 #if defined(_WIN32) || defined(_WIN64)
15754 /**
15755 * Dialog procedure for SQLDriverConnect().
15756 * @param hdlg handle of dialog window
15757 * @param wmsg type of message
15758 * @param wparam wparam of message
15759 * @param lparam lparam of message
15760 * @result true or false
15761 */
15762
15763 static BOOL CALLBACK
DriverConnectProc(HWND hdlg,WORD wmsg,WPARAM wparam,LPARAM lparam)15764 DriverConnectProc(HWND hdlg, WORD wmsg, WPARAM wparam, LPARAM lparam)
15765 {
15766 SETUPDLG *setupdlg;
15767
15768 switch (wmsg) {
15769 case WM_INITDIALOG:
15770 #ifdef _WIN64
15771 SetWindowLongPtr(hdlg, DWLP_USER, lparam);
15772 #else
15773 SetWindowLong(hdlg, DWL_USER, lparam);
15774 #endif
15775 setupdlg = (SETUPDLG *) lparam;
15776 SetDlgItemText(hdlg, IDC_DSNAME, setupdlg->attr[KEY_DSN].attr);
15777 SetDlgItemText(hdlg, IDC_DESC, setupdlg->attr[KEY_DESC].attr);
15778 SetDlgItemText(hdlg, IDC_DBNAME, setupdlg->attr[KEY_DBNAME].attr);
15779 SetDlgItemText(hdlg, IDC_TONAME, setupdlg->attr[KEY_BUSY].attr);
15780 SendDlgItemMessage(hdlg, IDC_DSNAME, EM_LIMITTEXT,
15781 (WPARAM) (MAXDSNAME - 1), (LPARAM) 0);
15782 SendDlgItemMessage(hdlg, IDC_DESC, EM_LIMITTEXT,
15783 (WPARAM) (MAXDESC - 1), (LPARAM) 0);
15784 SendDlgItemMessage(hdlg, IDC_DBNAME, EM_LIMITTEXT,
15785 (WPARAM) (MAXDBNAME - 1), (LPARAM) 0);
15786 SendDlgItemMessage(hdlg, IDC_TONAME, EM_LIMITTEXT,
15787 (WPARAM) (MAXTONAME - 1), (LPARAM) 0);
15788 CheckDlgButton(hdlg, IDC_NOWCHAR,
15789 getbool(setupdlg->attr[KEY_NOWCHAR].attr) ?
15790 BST_CHECKED : BST_UNCHECKED);
15791 CheckDlgButton(hdlg, IDC_STEPAPI,
15792 getbool(setupdlg->attr[KEY_STEPAPI].attr) ?
15793 BST_CHECKED : BST_UNCHECKED);
15794 CheckDlgButton(hdlg, IDC_NOTXN,
15795 getbool(setupdlg->attr[KEY_NOTXN].attr) ?
15796 BST_CHECKED : BST_UNCHECKED);
15797 CheckDlgButton(hdlg, IDC_LONGNAM,
15798 getbool(setupdlg->attr[KEY_LONGNAM].attr) ?
15799 BST_CHECKED : BST_UNCHECKED);
15800 if (setupdlg->defDSN) {
15801 EnableWindow(GetDlgItem(hdlg, IDC_DSNAME), FALSE);
15802 EnableWindow(GetDlgItem(hdlg, IDC_DSNAMETEXT), FALSE);
15803 }
15804 return TRUE;
15805 case WM_COMMAND:
15806 switch (GET_WM_COMMAND_ID(wparam, lparam)) {
15807 case IDC_BROWSE:
15808 GetDBFile(hdlg);
15809 break;
15810 case IDOK:
15811 #ifdef _WIN64
15812 setupdlg = (SETUPDLG *) GetWindowLongPtr(hdlg, DWLP_USER);
15813 #else
15814 setupdlg = (SETUPDLG *) GetWindowLong(hdlg, DWL_USER);
15815 #endif
15816 GetDlgItemText(hdlg, IDC_DSNAME,
15817 setupdlg->attr[KEY_DSN].attr,
15818 sizeof (setupdlg->attr[KEY_DSN].attr));
15819 GetDlgItemText(hdlg, IDC_DBNAME,
15820 setupdlg->attr[KEY_DBNAME].attr,
15821 sizeof (setupdlg->attr[KEY_DBNAME].attr));
15822 GetDlgItemText(hdlg, IDC_TONAME,
15823 setupdlg->attr[KEY_BUSY].attr,
15824 sizeof (setupdlg->attr[KEY_BUSY].attr));
15825 strcpy(setupdlg->attr[KEY_NOWCHAR].attr,
15826 (IsDlgButtonChecked(hdlg, IDC_NOWCHAR) == BST_CHECKED) ?
15827 "1" : "0");
15828 strcpy(setupdlg->attr[KEY_STEPAPI].attr,
15829 (IsDlgButtonChecked(hdlg, IDC_STEPAPI) == BST_CHECKED) ?
15830 "1" : "0");
15831 strcpy(setupdlg->attr[KEY_NOTXN].attr,
15832 (IsDlgButtonChecked(hdlg, IDC_NOTXN) == BST_CHECKED) ?
15833 "1" : "0");
15834 strcpy(setupdlg->attr[KEY_LONGNAM].attr,
15835 (IsDlgButtonChecked(hdlg, IDC_LONGNAM) == BST_CHECKED) ?
15836 "1" : "0");
15837 /* FALL THROUGH */
15838 case IDCANCEL:
15839 EndDialog(hdlg, GET_WM_COMMAND_ID(wparam, lparam) == IDOK);
15840 return TRUE;
15841 }
15842 }
15843 return FALSE;
15844 }
15845 #endif
15846
15847 #ifdef __OS2__
15848 /**
15849 * Dialog procedure for SQLDriverConnect().
15850 * @param hdlg handle of dialog window
15851 * @param wmsg type of message
15852 * @param wparam wparam of message
15853 * @param lparam lparam of message
15854 * @result standard MRESULT
15855 */
15856
15857 static MRESULT EXPENTRY
DriverConnectProc(HWND hdlg,ULONG wmsg,MPARAM wparam,MPARAM lparam)15858 DriverConnectProc(HWND hdlg, ULONG wmsg, MPARAM wparam, MPARAM lparam)
15859 {
15860 SETUPDLG *setupdlg;
15861
15862 switch (wmsg) {
15863 case WM_INITDLG:
15864 WinSetWindowULong(hdlg, QWL_USER, (ULONG) lparam);
15865 setupdlg = (SETUPDLG *) lparam;
15866 WinSetDlgItemText(hdlg, EF_DSNNAME, setupdlg->attr[KEY_DSN].attr);
15867 WinSetDlgItemText(hdlg, EF_DSNDESC, setupdlg->attr[KEY_DESC].attr);
15868 WinSetDlgItemText(hdlg, EF_DATABASE, setupdlg->attr[KEY_DBNAME].attr);
15869 WinSetDlgItemText(hdlg, EF_TIMEOUT, setupdlg->attr[KEY_BUSY].attr);
15870 WinCheckButton(hdlg, IDC_NOWCHAR,
15871 getbool(setupdlg->attr[KEY_NOWCHAR].attr));
15872 WinCheckButton(hdlg, IDC_STEPAPI,
15873 getbool(setupdlg->attr[KEY_STEPAPI].attr));
15874 WinCheckButton(hdlg, IDC_NOTXN,
15875 getbool(setupdlg->attr[KEY_NOTXN].attr));
15876 WinCheckButton(hdlg, IDC_LONGNAM,
15877 getbool(setupdlg->attr[KEY_LONGNAM].attr));
15878 return 0;
15879 case WM_COMMAND:
15880 switch (SHORT1FROMMP(wparam)) {
15881 case IDC_BROWSE:
15882 GetDBFile(hdlg);
15883 return 0;
15884 case DID_OK:
15885 setupdlg = (SETUPDLG *) WinQueryWindowULong(hdlg, QWL_USER);
15886 WinQueryDlgItemText(hdlg, EF_DSNNAME,
15887 sizeof (setupdlg->attr[KEY_DSN].attr),
15888 setupdlg->attr[KEY_DSN].attr);
15889 WinQueryDlgItemText(hdlg, EF_DATABASE,
15890 sizeof (setupdlg->attr[KEY_DBNAME].attr),
15891 setupdlg->attr[KEY_DBNAME].attr);
15892 WinQueryDlgItemText(hdlg, EF_TIMEOUT,
15893 sizeof (setupdlg->attr[KEY_BUSY].attr),
15894 setupdlg->attr[KEY_BUSY].attr);
15895 if ((ULONG)WinSendDlgItemMsg(hdlg, IDC_NOWCHAR, BM_QUERYCHECK,
15896 0, 0) == 1) {
15897 strcpy(setupdlg->attr[KEY_NOWCHAR].attr, "1");
15898 } else {
15899 strcpy(setupdlg->attr[KEY_NOWCHAR].attr, "0");
15900 }
15901 if ((ULONG)WinSendDlgItemMsg(hdlg, IDC_STEPAPI, BM_QUERYCHECK,
15902 0, 0) == 1) {
15903 strcpy(setupdlg->attr[KEY_STEPAPI].attr, "1");
15904 } else {
15905 strcpy(setupdlg->attr[KEY_STEPAPI].attr, "0");
15906 }
15907 if ((ULONG)WinSendDlgItemMsg(hdlg, IDC_NOTXN, BM_QUERYCHECK,
15908 0, 0) == 1) {
15909 strcpy(setupdlg->attr[KEY_NOTXN].attr, "1");
15910 } else {
15911 strcpy(setupdlg->attr[KEY_NOTXN].attr, "0");
15912 }
15913 if ((ULONG)WinSendDlgItemMsg(hdlg, IDC_LONGNAM, BM_QUERYCHECK,
15914 0, 0) == 1) {
15915 strcpy(setupdlg->attr[KEY_LONGNAM].attr, "1");
15916 } else {
15917 strcpy(setupdlg->attr[KEY_LONGNAM].attr, "0");
15918 }
15919 WinDismissDlg(hdlg, DID_OK);
15920 return 0;
15921 case DID_CANCEL:
15922 WinDismissDlg(hdlg, DID_CANCEL);
15923 return 0;
15924 }
15925 }
15926 return WinDefDlgProc(hdlg, wmsg, wparam, lparam);
15927 }
15928 #endif
15929
15930 /**
15931 * Internal connect using a driver connection string.
15932 * @param dbc database connection handle
15933 * @param hwnd parent window handle
15934 * @param connIn driver connect input string
15935 * @param connInLen length of driver connect input string or SQL_NTS
15936 * @param connOut driver connect output string
15937 * @param connOutMax length of driver connect output string
15938 * @param connOutLen output length of driver connect output string
15939 * @param drvcompl completion type
15940 * @result ODBC error code
15941 */
15942
15943 static SQLRETURN
drvdriverconnect(SQLHDBC dbc,SQLHWND hwnd,SQLCHAR * connIn,SQLSMALLINT connInLen,SQLCHAR * connOut,SQLSMALLINT connOutMax,SQLSMALLINT * connOutLen,SQLUSMALLINT drvcompl)15944 drvdriverconnect(SQLHDBC dbc, SQLHWND hwnd,
15945 SQLCHAR *connIn, SQLSMALLINT connInLen,
15946 SQLCHAR *connOut, SQLSMALLINT connOutMax,
15947 SQLSMALLINT *connOutLen, SQLUSMALLINT drvcompl)
15948 {
15949 BOOL maybeprompt, prompt = FALSE, defaultdsn = FALSE;
15950 DBC *d;
15951 SETUPDLG *setupdlg;
15952 SQLRETURN ret;
15953
15954 if (dbc == SQL_NULL_HDBC) {
15955 return SQL_INVALID_HANDLE;
15956 }
15957 d = (DBC *) dbc;
15958 if (d->sqlite) {
15959 setstatd(d, -1, "connection already established", "08002");
15960 return SQL_ERROR;
15961 }
15962 setupdlg = (SETUPDLG *) xmalloc(sizeof (SETUPDLG));
15963 if (setupdlg == NULL) {
15964 return SQL_ERROR;
15965 }
15966 memset(setupdlg, 0, sizeof (SETUPDLG));
15967 maybeprompt = drvcompl == SQL_DRIVER_COMPLETE ||
15968 drvcompl == SQL_DRIVER_COMPLETE_REQUIRED;
15969 if (connIn == NULL || !connInLen ||
15970 (connInLen == SQL_NTS && !connIn[0])) {
15971 prompt = TRUE;
15972 } else {
15973 ParseAttributes((LPCSTR) connIn, setupdlg);
15974 if (!setupdlg->attr[KEY_DSN].attr[0] &&
15975 drvcompl == SQL_DRIVER_COMPLETE_REQUIRED) {
15976 strcpy(setupdlg->attr[KEY_DSN].attr, "DEFAULT");
15977 defaultdsn = TRUE;
15978 }
15979 GetAttributes(setupdlg);
15980 if (drvcompl == SQL_DRIVER_PROMPT ||
15981 (maybeprompt &&
15982 !setupdlg->attr[KEY_DBNAME].attr[0])) {
15983 prompt = TRUE;
15984 }
15985 }
15986 retry:
15987 if (prompt) {
15988 short dlgret;
15989
15990 setupdlg->defDSN = setupdlg->attr[KEY_DRIVER].attr[0] != '\0';
15991 #if defined(_WIN32) || defined(_WIN64)
15992 dlgret = DialogBoxParam(hModule, MAKEINTRESOURCE(DRIVERCONNECT),
15993 hwnd, (DLGPROC) DriverConnectProc,
15994 (LPARAM) setupdlg);
15995 #endif
15996 #ifdef __OS2__
15997 HMODULE hDLL;
15998
15999 DosQueryModuleHandle("SQLLODBC.DLL", &hDLL);
16000 setupdlg->hDLL = hDLL;
16001 dlgret = WinDlgBox(HWND_DESKTOP, (HWND) hwnd, DriverConnectProc, hDLL,
16002 DLG_SQLITEODBCCONFIGURATION, setupdlg);
16003 #endif
16004 if (!dlgret || dlgret == -1) {
16005 xfree(setupdlg);
16006 return SQL_NO_DATA;
16007 }
16008 }
16009 if (connOut || connOutLen) {
16010 char buf[SQL_MAX_MESSAGE_LENGTH * 8];
16011 int len, count;
16012 char dsn_0 = (setupdlg->attr[KEY_DSN].attr[0] && !defaultdsn) ?
16013 setupdlg->attr[KEY_DSN].attr[0] : '\0';
16014 char drv_0 = setupdlg->attr[KEY_DRIVER].attr[0];
16015
16016 buf[0] = '\0';
16017 count = snprintf(buf, sizeof (buf),
16018 "%s%s%s%s%s%sDatabase=%s;StepAPI=%s;"
16019 "NoTXN=%s;Timeout=%s;NoWCHAR=%s;LongNames=%s",
16020 dsn_0 ? "DSN=" : "",
16021 dsn_0 ? setupdlg->attr[KEY_DSN].attr : "",
16022 dsn_0 ? ";" : "",
16023 drv_0 ? "Driver=" : "",
16024 drv_0 ? setupdlg->attr[KEY_DRIVER].attr : "",
16025 drv_0 ? ";" : "",
16026 setupdlg->attr[KEY_DBNAME].attr,
16027 setupdlg->attr[KEY_STEPAPI].attr,
16028 setupdlg->attr[KEY_NOTXN].attr,
16029 setupdlg->attr[KEY_BUSY].attr,
16030 setupdlg->attr[KEY_NOWCHAR].attr,
16031 setupdlg->attr[KEY_LONGNAM].attr);
16032 if (count < 0) {
16033 buf[sizeof (buf) - 1] = '\0';
16034 }
16035 len = min(connOutMax - 1, strlen(buf));
16036 if (connOut) {
16037 strncpy((char *) connOut, buf, len);
16038 connOut[len] = '\0';
16039 }
16040 if (connOutLen) {
16041 *connOutLen = len;
16042 }
16043 }
16044 #if defined(HAVE_SQLITETRACE) && (HAVE_SQLITETRACE)
16045 if (setupdlg->attr[KEY_DSN].attr[0]) {
16046 char tracef[SQL_MAX_MESSAGE_LENGTH];
16047
16048 tracef[0] = '\0';
16049 SQLGetPrivateProfileString(setupdlg->attr[KEY_DSN].attr,
16050 "tracefile", "", tracef,
16051 sizeof (tracef), ODBC_INI);
16052 if (tracef[0] != '\0') {
16053 d->trace = fopen(tracef, "a");
16054 }
16055 }
16056 #endif
16057 d->nowchar = getbool(setupdlg->attr[KEY_NOWCHAR].attr);
16058 d->longnames = getbool(setupdlg->attr[KEY_LONGNAM].attr);
16059 ret = dbopen(d, setupdlg->attr[KEY_DBNAME].attr,
16060 setupdlg->attr[KEY_DSN].attr,
16061 setupdlg->attr[KEY_STEPAPI].attr,
16062 setupdlg->attr[KEY_NOTXN].attr,
16063 setupdlg->attr[KEY_BUSY].attr);
16064 if (ret != SQL_SUCCESS) {
16065 if (maybeprompt && !prompt) {
16066 prompt = TRUE;
16067 goto retry;
16068 }
16069 xfree(setupdlg);
16070 return ret;
16071 }
16072 xfree(setupdlg);
16073 return SQL_SUCCESS;
16074 }
16075
16076 #endif /* WITHOUT_DRIVERMGR */
16077 #endif /* _WIN32 || _WIN64 || __OS2__ */
16078
16079 #ifndef WINTERFACE
16080 /**
16081 * Connect using a driver connection string.
16082 * @param dbc database connection handle
16083 * @param hwnd parent window handle
16084 * @param connIn driver connect input string
16085 * @param connInLen length of driver connect input string or SQL_NTS
16086 * @param connOut driver connect output string
16087 * @param connOutMax length of driver connect output string
16088 * @param connOutLen output length of driver connect output string
16089 * @param drvcompl completion type
16090 * @result ODBC error code
16091 */
16092
16093 SQLRETURN SQL_API
SQLDriverConnect(SQLHDBC dbc,SQLHWND hwnd,SQLCHAR * connIn,SQLSMALLINT connInLen,SQLCHAR * connOut,SQLSMALLINT connOutMax,SQLSMALLINT * connOutLen,SQLUSMALLINT drvcompl)16094 SQLDriverConnect(SQLHDBC dbc, SQLHWND hwnd,
16095 SQLCHAR *connIn, SQLSMALLINT connInLen,
16096 SQLCHAR *connOut, SQLSMALLINT connOutMax,
16097 SQLSMALLINT *connOutLen, SQLUSMALLINT drvcompl)
16098 {
16099 SQLRETURN ret;
16100
16101 HDBC_LOCK(dbc);
16102 ret = drvdriverconnect(dbc, hwnd, connIn, connInLen,
16103 connOut, connOutMax, connOutLen, drvcompl);
16104 HDBC_UNLOCK(dbc);
16105 return ret;
16106 }
16107 #endif
16108
16109 #ifdef WINTERFACE
16110 /**
16111 * Connect using a driver connection string (UNICODE version).
16112 * @param dbc database connection handle
16113 * @param hwnd parent window handle
16114 * @param connIn driver connect input string
16115 * @param connInLen length of driver connect input string or SQL_NTS
16116 * @param connOut driver connect output string
16117 * @param connOutMax length of driver connect output string
16118 * @param connOutLen output length of driver connect output string
16119 * @param drvcompl completion type
16120 * @result ODBC error code
16121 */
16122
16123 SQLRETURN SQL_API
SQLDriverConnectW(SQLHDBC dbc,SQLHWND hwnd,SQLWCHAR * connIn,SQLSMALLINT connInLen,SQLWCHAR * connOut,SQLSMALLINT connOutMax,SQLSMALLINT * connOutLen,SQLUSMALLINT drvcompl)16124 SQLDriverConnectW(SQLHDBC dbc, SQLHWND hwnd,
16125 SQLWCHAR *connIn, SQLSMALLINT connInLen,
16126 SQLWCHAR *connOut, SQLSMALLINT connOutMax,
16127 SQLSMALLINT *connOutLen, SQLUSMALLINT drvcompl)
16128 {
16129 SQLRETURN ret;
16130 char *ci = NULL;
16131 SQLSMALLINT len = 0;
16132
16133 HDBC_LOCK(dbc);
16134 if (connIn) {
16135 if (connInLen == SQL_NTS) {
16136 connInLen = -1;
16137 }
16138 ci = uc_to_utf_c(connIn, connInLen);
16139 if (!ci) {
16140 DBC *d = (DBC *) dbc;
16141
16142 setstatd(d, -1, "out of memory", (*d->ov3) ? "HY000" : "S1000");
16143 HDBC_UNLOCK(dbc);
16144 return SQL_ERROR;
16145 }
16146 }
16147 ret = drvdriverconnect(dbc, hwnd, (SQLCHAR *) ci, SQL_NTS,
16148 (SQLCHAR *) connOut, connOutMax, &len, drvcompl);
16149 HDBC_UNLOCK(dbc);
16150 uc_free(ci);
16151 if (ret == SQL_SUCCESS) {
16152 SQLWCHAR *co = NULL;
16153
16154 if (connOut) {
16155 if (len > 0) {
16156 co = uc_from_utf((SQLCHAR *) connOut, len);
16157 if (co) {
16158 uc_strncpy(connOut, co, connOutMax / sizeof (SQLWCHAR));
16159 len = min(connOutMax / sizeof (SQLWCHAR), uc_strlen(co));
16160 uc_free(co);
16161 } else {
16162 len = 0;
16163 }
16164 }
16165 if (len <= 0) {
16166 len = 0;
16167 connOut[0] = 0;
16168 }
16169 } else {
16170 len = 0;
16171 }
16172 if (connOutLen) {
16173 *connOutLen = len;
16174 }
16175 }
16176 return ret;
16177 }
16178 #endif
16179
16180 #if defined(_WIN32) || defined(_WIN64)
16181
16182 /**
16183 * DLL initializer for WIN32.
16184 * @param hinst instance handle
16185 * @param reason reason code for entry point
16186 * @param reserved
16187 * @result always true
16188 */
16189
16190 BOOL APIENTRY
LibMain(HANDLE hinst,DWORD reason,LPVOID reserved)16191 LibMain(HANDLE hinst, DWORD reason, LPVOID reserved)
16192 {
16193 static int initialized = 0;
16194
16195 switch (reason) {
16196 case DLL_PROCESS_ATTACH:
16197 if (!initialized++) {
16198 hModule = hinst;
16199 #ifdef WINTERFACE
16200 /* MS Access hack part 1 (reserved error -7748) */
16201 statSpec2P = statSpec2;
16202 statSpec3P = statSpec3;
16203 #endif
16204 }
16205 break;
16206 case DLL_THREAD_ATTACH:
16207 break;
16208 case DLL_PROCESS_DETACH:
16209 --initialized;
16210 break;
16211 case DLL_THREAD_DETACH:
16212 break;
16213 default:
16214 break;
16215 }
16216 return TRUE;
16217 }
16218
16219 /**
16220 * DLL entry point for WIN32.
16221 * @param hinst instance handle
16222 * @param reason reason code for entry point
16223 * @param reserved
16224 * @result always true
16225 */
16226
16227 int __stdcall
DllMain(HANDLE hinst,DWORD reason,LPVOID reserved)16228 DllMain(HANDLE hinst, DWORD reason, LPVOID reserved)
16229 {
16230 return LibMain(hinst, reason, reserved);
16231 }
16232
16233 #ifndef WITHOUT_INSTALLER
16234
16235 /**
16236 * Handler for driver installer/uninstaller error messages.
16237 * @param name name of API function for which to show error messages
16238 * @result true when error message retrieved
16239 */
16240
16241 static BOOL
InUnError(char * name)16242 InUnError(char *name)
16243 {
16244 WORD err = 1;
16245 DWORD code;
16246 char errmsg[301];
16247 WORD errlen, errmax = sizeof (errmsg) - 1;
16248 int sqlret;
16249 BOOL ret = FALSE;
16250
16251 do {
16252 errmsg[0] = '\0';
16253 sqlret = SQLInstallerError(err, &code, errmsg, errmax, &errlen);
16254 if (SQL_SUCCEEDED(sqlret)) {
16255 MessageBox(NULL, errmsg, name,
16256 MB_ICONSTOP | MB_OK | MB_TASKMODAL | MB_SETFOREGROUND);
16257 ret = TRUE;
16258 }
16259 err++;
16260 } while (sqlret != SQL_NO_DATA);
16261 return ret;
16262 }
16263
16264 /**
16265 * Built in driver installer/uninstaller.
16266 * @param remove true for uninstall
16267 * @param cmdline command line string of rundll32
16268 */
16269
16270 static BOOL
InUn(int remove,char * cmdline)16271 InUn(int remove, char *cmdline)
16272 {
16273 #ifdef WINTERFACE
16274 static char *drivername = "SQLite ODBC (UTF-8) Driver";
16275 static char *dsname = "SQLite3 UTF-8 Datasource";
16276 #else
16277 static char *drivername = "SQLite3 ODBC Driver";
16278 static char *dsname = "SQLite Datasource";
16279 #endif
16280 char *dllname, *p;
16281 char dllbuf[301], path[301], driver[300], attr[300], inst[400];
16282 WORD pathmax = sizeof (path) - 1, pathlen;
16283 DWORD usecnt, mincnt;
16284 int quiet = 0;
16285
16286 dllbuf[0] = '\0';
16287 GetModuleFileName(hModule, dllbuf, sizeof (dllbuf));
16288 p = strrchr(dllbuf, '\\');
16289 dllname = p ? (p + 1) : dllbuf;
16290 quiet = cmdline && strstr(cmdline, "quiet");
16291 if (SQLInstallDriverManager(path, pathmax, &pathlen)) {
16292 sprintf(driver, "%s;Driver=%s;Setup=%s;",
16293 drivername, dllname, dllname);
16294 p = driver;
16295 while (*p) {
16296 if (*p == ';') {
16297 *p = '\0';
16298 }
16299 ++p;
16300 }
16301 usecnt = 0;
16302 path[0] = '\0';
16303 SQLInstallDriverEx(driver, NULL, path, pathmax, NULL,
16304 ODBC_INSTALL_INQUIRY, &usecnt);
16305 pathlen = strlen(path);
16306 while (pathlen > 0 && path[pathlen - 1] == '\\') {
16307 --pathlen;
16308 path[pathlen] = '\0';
16309 }
16310 sprintf(driver, "%s;Driver=%s\\%s;Setup=%s\\%s;",
16311 drivername, path, dllname, path, dllname);
16312 p = driver;
16313 while (*p) {
16314 if (*p == ';') {
16315 *p = '\0';
16316 }
16317 ++p;
16318 }
16319 sprintf(inst, "%s\\%s", path, dllname);
16320 if (!remove && usecnt > 0) {
16321 /* first install try: copy over driver dll, keeping DSNs */
16322 if (GetFileAttributesA(dllbuf) != INVALID_FILE_ATTRIBUTES &&
16323 CopyFile(dllbuf, inst, 0)) {
16324 if (!quiet) {
16325 char buf[512];
16326
16327 sprintf(buf, "%s replaced.", drivername);
16328 MessageBox(NULL, buf, "Info",
16329 MB_ICONINFORMATION | MB_OK | MB_TASKMODAL |
16330 MB_SETFOREGROUND);
16331 }
16332 return TRUE;
16333 }
16334 }
16335 mincnt = remove ? 1 : 0;
16336 while (usecnt != mincnt) {
16337 if (!SQLRemoveDriver(driver, TRUE, &usecnt)) {
16338 break;
16339 }
16340 }
16341 if (remove) {
16342 if (usecnt && !SQLRemoveDriver(driver, TRUE, &usecnt)) {
16343 InUnError("SQLRemoveDriver");
16344 return FALSE;
16345 }
16346 if (!usecnt) {
16347 char buf[512];
16348
16349 DeleteFile(inst);
16350 if (!quiet) {
16351 sprintf(buf, "%s uninstalled.", drivername);
16352 MessageBox(NULL, buf, "Info",
16353 MB_ICONINFORMATION | MB_OK | MB_TASKMODAL |
16354 MB_SETFOREGROUND);
16355 }
16356 }
16357 sprintf(attr, "DSN=%s;Database=;", dsname);
16358 p = attr;
16359 while (*p) {
16360 if (*p == ';') {
16361 *p = '\0';
16362 }
16363 ++p;
16364 }
16365 SQLConfigDataSource(NULL, ODBC_REMOVE_SYS_DSN, drivername, attr);
16366 return TRUE;
16367 }
16368 if (GetFileAttributesA(dllbuf) == INVALID_FILE_ATTRIBUTES) {
16369 return FALSE;
16370 }
16371 if (strcasecmp(dllbuf, inst) != 0 && !CopyFile(dllbuf, inst, 0)) {
16372 char buf[512];
16373
16374 sprintf(buf, "Copy %s to %s failed.", dllbuf, inst);
16375 MessageBox(NULL, buf, "CopyFile",
16376 MB_ICONSTOP | MB_OK | MB_TASKMODAL | MB_SETFOREGROUND);
16377 return FALSE;
16378 }
16379 if (!SQLInstallDriverEx(driver, path, path, pathmax, &pathlen,
16380 ODBC_INSTALL_COMPLETE, &usecnt)) {
16381 InUnError("SQLInstallDriverEx");
16382 return FALSE;
16383 }
16384 sprintf(attr, "DSN=%s;Database=;", dsname);
16385 p = attr;
16386 while (*p) {
16387 if (*p == ';') {
16388 *p = '\0';
16389 }
16390 ++p;
16391 }
16392 SQLConfigDataSource(NULL, ODBC_REMOVE_SYS_DSN, drivername, attr);
16393 if (!SQLConfigDataSource(NULL, ODBC_ADD_SYS_DSN, drivername, attr)) {
16394 InUnError("SQLConfigDataSource");
16395 return FALSE;
16396 }
16397 if (!quiet) {
16398 char buf[512];
16399
16400 sprintf(buf, "%s installed.", drivername);
16401 MessageBox(NULL, buf, "Info",
16402 MB_ICONINFORMATION | MB_OK | MB_TASKMODAL |
16403 MB_SETFOREGROUND);
16404 }
16405 } else {
16406 InUnError("SQLInstallDriverManager");
16407 return FALSE;
16408 }
16409 return TRUE;
16410 }
16411
16412 /**
16413 * RunDLL32 entry point for driver installation.
16414 * @param hwnd window handle of caller
16415 * @param hinst of this DLL
16416 * @param lpszCmdLine rundll32 command line tail
16417 * @param nCmdShow ignored
16418 */
16419
16420 void CALLBACK
install(HWND hwnd,HINSTANCE hinst,LPSTR lpszCmdLine,int nCmdShow)16421 install(HWND hwnd, HINSTANCE hinst, LPSTR lpszCmdLine, int nCmdShow)
16422 {
16423 InUn(0, lpszCmdLine);
16424 }
16425
16426 /**
16427 * RunDLL32 entry point for driver uninstallation.
16428 * @param hwnd window handle of caller
16429 * @param hinst of this DLL
16430 * @param lpszCmdLine rundll32 command line tail
16431 * @param nCmdShow ignored
16432 */
16433
16434 void CALLBACK
uninstall(HWND hwnd,HINSTANCE hinst,LPSTR lpszCmdLine,int nCmdShow)16435 uninstall(HWND hwnd, HINSTANCE hinst, LPSTR lpszCmdLine, int nCmdShow)
16436 {
16437 InUn(1, lpszCmdLine);
16438 }
16439
16440 #endif /* WITHOUT_INSTALLER */
16441
16442 #ifndef WITHOUT_SHELL
16443
16444 /**
16445 * Setup argv vector from string
16446 * @param argcp pointer to argc
16447 * @param argvp pointer to argv
16448 * @param cmdline command line string
16449 * @param argv0 0th element for argv or NULL, must be static
16450 */
16451
16452 static void
setargv(int * argcp,char *** argvp,char * cmdline,char * argv0)16453 setargv(int *argcp, char ***argvp, char *cmdline, char *argv0)
16454 {
16455 char *p, *arg, *argspace, **argv;
16456 int argc, size, inquote, copy, slashes;
16457
16458 size = 2 + (argv0 ? 1 : 0);
16459 for (p = cmdline; *p != '\0'; p++) {
16460 if (ISSPACE(*p)) {
16461 size++;
16462 while (ISSPACE(*p)) {
16463 p++;
16464 }
16465 if (*p == '\0') {
16466 break;
16467 }
16468 }
16469 }
16470 argspace = malloc(size * sizeof (char *) + strlen(cmdline) + 1);
16471 argv = (char **) argspace;
16472 argspace += size * sizeof (char *);
16473 size--;
16474 argc = 0;
16475 if (argv0) {
16476 argv[argc++] = argv0;
16477 }
16478 p = cmdline;
16479 for (; argc < size; argc++) {
16480 argv[argc] = arg = argspace;
16481 while (ISSPACE(*p)) {
16482 p++;
16483 }
16484 if (*p == '\0') {
16485 break;
16486 }
16487 inquote = 0;
16488 slashes = 0;
16489 while (1) {
16490 copy = 1;
16491 while (*p == '\\') {
16492 slashes++;
16493 p++;
16494 }
16495 if (*p == '"') {
16496 if ((slashes & 1) == 0) {
16497 copy = 0;
16498 if (inquote && p[1] == '"') {
16499 p++;
16500 copy = 1;
16501 } else {
16502 inquote = !inquote;
16503 }
16504 }
16505 slashes >>= 1;
16506 }
16507 while (slashes) {
16508 *arg = '\\';
16509 arg++;
16510 slashes--;
16511 }
16512 if (*p == '\0' || (!inquote && ISSPACE(*p))) {
16513 break;
16514 }
16515 if (copy != 0) {
16516 *arg = *p;
16517 arg++;
16518 }
16519 p++;
16520 }
16521 *arg = '\0';
16522 argspace = arg + 1;
16523 }
16524 argv[argc] = 0;
16525 *argcp = argc;
16526 *argvp = argv;
16527 }
16528
16529 /**
16530 * RunDLL32 entry point for SQLite shell
16531 * @param hwnd window handle of caller
16532 * @param hinst of this DLL
16533 * @param lpszCmdLine rundll32 command line tail
16534 * @param nCmdShow ignored
16535 */
16536
16537 void CALLBACK
shell(HWND hwnd,HINSTANCE hinst,LPSTR lpszCmdLine,int nCmdShow)16538 shell(HWND hwnd, HINSTANCE hinst, LPSTR lpszCmdLine, int nCmdShow)
16539 {
16540 int argc, needcon = 0;
16541 char **argv;
16542 extern int sqlite_main(int, char **);
16543 static const char *name = "SQLite Shell";
16544 DWORD ftype0, ftype1, ftype2;
16545
16546 ftype0 = GetFileType(GetStdHandle(STD_INPUT_HANDLE));
16547 ftype1 = GetFileType(GetStdHandle(STD_OUTPUT_HANDLE));
16548 ftype2 = GetFileType(GetStdHandle(STD_ERROR_HANDLE));
16549 if (ftype0 != FILE_TYPE_DISK && ftype0 != FILE_TYPE_CHAR &&
16550 ftype0 != FILE_TYPE_PIPE) {
16551 fclose(stdin);
16552 ++needcon;
16553 ftype0 = FILE_TYPE_UNKNOWN;
16554 }
16555 if (ftype1 != FILE_TYPE_DISK && ftype1 != FILE_TYPE_CHAR &&
16556 ftype1 != FILE_TYPE_PIPE) {
16557 fclose(stdout);
16558 ++needcon;
16559 ftype1 = FILE_TYPE_UNKNOWN;
16560 }
16561 if (ftype2 != FILE_TYPE_DISK && ftype2 != FILE_TYPE_CHAR &&
16562 ftype2 != FILE_TYPE_PIPE) {
16563 fclose(stderr);
16564 ++needcon;
16565 ftype2 = FILE_TYPE_UNKNOWN;
16566 }
16567 if (needcon > 0) {
16568 AllocConsole();
16569 SetConsoleTitle(name);
16570 }
16571 if (ftype0 == FILE_TYPE_UNKNOWN) {
16572 freopen("CONIN$", "r", stdin);
16573 }
16574 if (ftype1 == FILE_TYPE_UNKNOWN) {
16575 freopen("CONOUT$", "w", stdout);
16576 }
16577 if (ftype2 == FILE_TYPE_UNKNOWN) {
16578 freopen("CONOUT$", "w", stderr);
16579 }
16580 setargv(&argc, &argv, lpszCmdLine, (char *) name);
16581 sqlite_main(argc, argv);
16582 }
16583
16584 #endif /* WITHOUT_SHELL */
16585
16586 #endif /* _WIN32 || _WIN64 */
16587
16588 #if defined(HAVE_ODBCINSTEXT_H) && (HAVE_ODBCINSTEXT_H)
16589
16590 /*
16591 * unixODBC property page for this driver,
16592 * may or may not work depending on unixODBC version.
16593 */
16594
16595 #include <odbcinstext.h>
16596
16597 int
ODBCINSTGetProperties(HODBCINSTPROPERTY prop)16598 ODBCINSTGetProperties(HODBCINSTPROPERTY prop)
16599 {
16600 static const char *instYN[] = { "No", "Yes", NULL };
16601
16602 prop->pNext = (HODBCINSTPROPERTY) malloc(sizeof (ODBCINSTPROPERTY));
16603 prop = prop->pNext;
16604 memset(prop, 0, sizeof (ODBCINSTPROPERTY));
16605 prop->nPromptType = ODBCINST_PROMPTTYPE_FILENAME;
16606 strncpy(prop->szName, "Database", INI_MAX_PROPERTY_NAME);
16607 strncpy(prop->szValue, "", INI_MAX_PROPERTY_VALUE);
16608 prop->pNext = (HODBCINSTPROPERTY) malloc(sizeof (ODBCINSTPROPERTY));
16609 prop = prop->pNext;
16610 memset(prop, 0, sizeof (ODBCINSTPROPERTY));
16611 prop->nPromptType = ODBCINST_PROMPTTYPE_TEXTEDIT;
16612 strncpy(prop->szName, "Timeout", INI_MAX_PROPERTY_NAME);
16613 strncpy(prop->szValue, "100000", INI_MAX_PROPERTY_VALUE);
16614 prop->pNext = (HODBCINSTPROPERTY) malloc(sizeof (ODBCINSTPROPERTY));
16615 prop = prop->pNext;
16616 memset(prop, 0, sizeof (ODBCINSTPROPERTY));
16617 prop->nPromptType = ODBCINST_PROMPTTYPE_COMBOBOX;
16618 prop->aPromptData = malloc(sizeof (instYN));
16619 memcpy(prop->aPromptData, instYN, sizeof (instYN));
16620 strncpy(prop->szName, "StepAPI", INI_MAX_PROPERTY_NAME);
16621 strncpy(prop->szValue, "No", INI_MAX_PROPERTY_VALUE);
16622 #ifdef WINTERFACE
16623 prop->pNext = (HODBCINSTPROPERTY) malloc(sizeof (ODBCINSTPROPERTY));
16624 prop = prop->pNext;
16625 memset(prop, 0, sizeof (ODBCINSTPROPERTY));
16626 prop->nPromptType = ODBCINST_PROMPTTYPE_COMBOBOX;
16627 prop->aPromptData = malloc(sizeof (instYN));
16628 memcpy(prop->aPromptData, instYN, sizeof (instYN));
16629 strncpy(prop->szName, "NoWCHAR", INI_MAX_PROPERTY_NAME);
16630 strncpy(prop->szValue, "No", INI_MAX_PROPERTY_VALUE);
16631 #endif
16632 prop->pNext = (HODBCINSTPROPERTY) malloc(sizeof (ODBCINSTPROPERTY));
16633 prop = prop->pNext;
16634 memset(prop, 0, sizeof (ODBCINSTPROPERTY));
16635 prop->nPromptType = ODBCINST_PROMPTTYPE_COMBOBOX;
16636 prop->aPromptData = malloc(sizeof (instYN));
16637 memcpy(prop->aPromptData, instYN, sizeof (instYN));
16638 strncpy(prop->szName, "LongNames", INI_MAX_PROPERTY_NAME);
16639 strncpy(prop->szValue, "No", INI_MAX_PROPERTY_VALUE);
16640 return 1;
16641 }
16642
16643 #endif /* HAVE_ODBCINSTEXT_H */
16644
16645 /*
16646 * Local Variables:
16647 * mode: c
16648 * c-basic-offset: 4
16649 * fill-column: 78
16650 * tab-width: 8
16651 * End:
16652 */
16653