1 /**
2 * @file sqlite4odbc.c
3 * SQLite4 ODBC Driver main module.
4 *
5 * $Id: sqlite4odbc.c,v 1.24 2020/06/20 11:56:09 chw Exp chw $
6 *
7 * Copyright (c) 2014-2020 Christian Werner <chw@ch-werner.de>
8 *
9 * See the file "license.terms" for information on usage
10 * and redistribution of this file and for a
11 * DISCLAIMER OF ALL WARRANTIES.
12 */
13
14 #if defined(SQLITE_HAS_CODEC) && defined(SQLITE_API)
15 #undef WITH_SQLITE_DLLS
16 #undef SQLITE_DYNLOAD
17 #include "sqlite4.c"
18 #endif
19
20 #if defined(WITH_SQLITE_DLLS) && (WITH_SQLITE_DLLS > 1)
21 #define SQLITE_DYNLOAD 1
22 #endif
23
24 #include "sqlite4odbc.h"
25
26 #ifdef SQLITE_DYNLOAD
27
28 #undef MEMORY_DEBUG
29
30 #if defined(_WIN32) || defined(_WIN64)
31 static void dls_init(void);
32 static void dls_fini(void);
33 #else
34 void dls_init(void);
35 void dls_fini(void);
36 #endif
37
38 static struct dl_sqlite4_funcs {
39 int (*bind_blob)(sqlite4_stmt *p0, int p1, const void *p2, int p3,
40 void (*p4)(void *, void *), void *p5);
41 int (*bind_double)(sqlite4_stmt *p0, int p1, double p2);
42 int (*bind_int)(sqlite4_stmt *p0, int p1, int p2);
43 int (*bind_int64)(sqlite4_stmt *p0, int p1, sqlite4_int64 p2);
44 int (*bind_null)(sqlite4_stmt *p0, int p1);
45 int (*bind_parameter_count)(sqlite4_stmt *p0);
46 int (*bind_text)(sqlite4_stmt *p0, int p1, const char *p2, int p3,
47 void (*p4)(void *, void *), void *p5);
48 int (*changes)(sqlite4 *p0);
49 int (*close)(sqlite4 *p0, unsigned int p1);
50 const void * (*column_blob)(sqlite4_stmt *p0, int p1, int p2);
51 int (*column_bytes)(sqlite4_stmt *p0, int p1);
52 int (*column_count)(sqlite4_stmt *p0);
53 const char * (*column_database_name)(sqlite4_stmt *p0, int p1);
54 const char * (*column_decltype)(sqlite4_stmt *p0, int p1);
55 double (*column_double)(sqlite4_stmt *p0);
56 const char * (*column_name)(sqlite4_stmt *p0, int p1);
57 const char * (*column_origin_name)(sqlite4_stmt *p0, int p1);
58 const char * (*column_table_name)(sqlite4_stmt *p0, int p1);
59 const char * (*column_text)(sqlite4_stmt *p0, int p1, p2);
60 int (*column_type)(sqlite4_stmt *p0, int p1);
61 int (*create_function)(sqlite4 *p0, const char *p1, int p2,
62 void *p4,
63 void (*p5)(sqlite4_context *, int, sqlite4_value **),
64 void (*p6)(sqlite4_context *, int, sqlite4_value **),
65 void (*p7)(sqlite4_context *),
66 void (*p8)(void *));
67 int (*errcode)(sqlite4 *p0);
68 const char * (*errmsg)(sqlite4 *p0);
69 int (*exec)(sqlite4 *p0, const char *p1,
70 int (*p2)(void *, int, char **, char **),
71 void *p3);
72 int (*finalize)(sqlite4_stmt *p0);
73 void (*free)(sqlite4_env *p0, void *p1);
74 void (*interrupt)(sqlite4 *p0);
75 #if 0
76 sqlite4_int64 (*last_insert_rowid)(sqlite4 *p0);
77 #endif
78 const char * (*libversion)(void);
79 #if 0
80 int (*load_extension)(sqlite4 *p0, const char *p1, const char *p2,
81 char **p3);
82 #endif
83 void * (*malloc)(sqlite4_env *p0, int p1);
84 char * (*mprintf)(sqlite4_env *p0, const char *p1, ...);
85 int (*open)(sqlite4_env *p0, const char *p1, sqlite4 **p2, ...);
86 int (*prepare)(sqlite4 *p0, const char *p1, int p2, sqlite4_stmt **p3,
87 int *p4);
88 void (*profile)(sqlite4 *p0, void *p1,
89 void (*p2)(void *, const char *, sqlite4_uint64),
90 void *p3);
91 void * (*realloc)(sqlite4_env *p0, void *p1, int p2);
92 int (*reset)(sqlite4_stmt *p0);
93 void (*result_blob)(sqlite4_context *p0, const void *p1,
94 int p2, void (*p3)(void *, void *), void *p4);
95 void (*result_error)(sqlite4_context *p0, const char *p1, int p2);
96 void (*result_int)(sqlite4_context *p0, int p1);
97 void (*result_null)(sqlite4_context *p0);
98 int (*step)(sqlite4_stmt *p0);
99 int (*xstrnicmp)(const char *p0, const char *p1, int p2);
100 #if 0
101 int (*table_column_metadata)(sqlite4 *p0, const char *p1,
102 const char *p2, const char *p3,
103 char const **p4, char const **p5,
104 int *p6, int *p7, int *p8);
105 #endif
106 void (*trace)(sqlite4 *p0, void *p1, void (*p2)(void *, const char *),
107 void *p2);
108 void * (*user_data)(sqlite4_context *p0);
109 const void * (*value_blob)(sqlite4_value *p0, int *p1);
110 int (*value_bytes)(sqlite4_value *p0);
111 const char * (*value_text)(sqlite4_value *p0, int *p1);
112 int (*value_type)(sqlite4_value *p0);
113 } dls_funcs;
114
115 #define sqlite4_bind_blob dls_funcs.bind_blob
116 #define sqlite4_bind_double dls_funcs.bind_double
117 #define sqlite4_bind_int dls_funcs.bind_int
118 #define sqlite4_bind_int64 dls_funcs.bind_int64
119 #define sqlite4_bind_null dls_funcs.bind_null
120 #define sqlite4_bind_parameter_count dls_funcs.bind_parameter_count
121 #define sqlite4_bind_text dls_funcs.bind_text
122 #define sqlite4_changes dls_funcs.changes
123 #define sqlite4_close dls_funcs.close
124 #define sqlite4_column_blob dls_funcs.column_blob
125 #define sqlite4_column_bytes dls_funcs.column_bytes
126 #define sqlite4_column_count dls_funcs.column_count
127 #define sqlite4_column_database_name dls_funcs.column_database_name
128 #define sqlite4_column_decltype dls_funcs.column_decltype
129 #define sqlite4_column_double dls_funcs.column_double
130 #define sqlite4_column_name dls_funcs.column_name
131 #define sqlite4_column_origin_name dls_funcs.column_origin_name
132 #define sqlite4_column_table_name dls_funcs.column_table_name
133 #define sqlite4_column_text dls_funcs.column_text
134 #define sqlite4_column_type dls_funcs.column_type
135 #define sqlite4_create_function dls_funcs.create_function
136 #define sqlite4_errcode dls_funcs.errcode
137 #define sqlite4_errmsg dls_funcs.errmsg
138 #define sqlite4_exec dls_funcs.exec
139 #define sqlite4_finalize dls_funcs.finalize
140 #define sqlite4_free dls_funcs.free
141 #define sqlite4_interrupt dls_funcs.interrupt
142 #if 0
143 #define sqlite4_last_insert_rowid dls_funcs.last_insert_rowid
144 #endif
145 #define sqlite4_libversion dls_funcs.libversion
146 #if 0
147 #define sqlite4_load_extension dls_funcs.load_extension
148 #endif
149 #define sqlite4_malloc dls_funcs.malloc
150 #define sqlite4_mprintf dls_funcs.mprintf
151 #define sqlite4_open dls_funcs.open
152 #define sqlite4_prepare dls_funcs.prepare
153 #define sqlite4_profile dls_funcs.profile
154 #define sqlite4_realloc dls_funcs.realloc
155 #define sqlite4_reset dls_funcs.reset
156 #define sqlite4_result_blob dls_funcs.result_blob
157 #define sqlite4_result_error dls_funcs.result_error
158 #define sqlite4_result_int dls_funcs.result_int
159 #define sqlite4_result_null dls_funcs.result_null
160 #define sqlite4_step dls_funcs.step
161 #define sqlite4_strnicmp dls_funcs.xstrnicmp
162 #if 0
163 #define sqlite4_table_column_metadata dls_funcs.table_column_metadata
164 #endif
165 #define sqlite4_trace dls_funcs.trace
166 #define sqlite4_user_data dls_funcs.user_data
167 #define sqlite4_value_blob dls_funcs.value_blob
168 #define sqlite4_value_bytes dls_funcs.value_bytes
169 #define sqlite4_value_text dls_funcs.value_text
170 #define sqlite4_value_type dls_funcs.value_type
171
172 #endif
173
174 #ifndef WITHOUT_WINTERFACE
175 #define WINTERFACE
176 #define WCHARSUPPORT
177 #endif
178
179 #if !defined(_WIN32) && !defined(_WIN64)
180 #if !defined(WCHARSUPPORT) && defined(HAVE_SQLWCHAR) && (HAVE_SQLWCHAR)
181 #define WCHARSUPPORT
182 #endif
183 #endif
184
185 #if defined(WINTERFACE)
186 #include <sqlucode.h>
187 #endif
188
189 #if defined(_WIN32) || defined(_WIN64)
190 #include "resource3.h"
191 #define ODBC_INI "ODBC.INI"
192 #ifndef DRIVER_VER_INFO
193 #define DRIVER_VER_INFO VERSION
194 #endif
195 #else
196 #define ODBC_INI ".odbc.ini"
197 #endif
198
199 #ifndef DRIVER_VER_INFO
200 #define DRIVER_VER_INFO "0.0"
201 #endif
202
203 #ifndef COLATTRIBUTE_LAST_ARG_TYPE
204 #ifdef _WIN64
205 #define COLATTRIBUTE_LAST_ARG_TYPE SQLLEN *
206 #else
207 #define COLATTRIBUTE_LAST_ARG_TYPE SQLPOINTER
208 #endif
209 #endif
210
211 #ifndef SETSTMTOPTION_LAST_ARG_TYPE
212 #define SETSTMTOPTION_LAST_ARG_TYPE SQLROWCOUNT
213 #endif
214
215 #undef min
216 #define min(a, b) ((a) < (b) ? (a) : (b))
217 #undef max
218 #define max(a, b) ((a) < (b) ? (b) : (a))
219
220 #ifndef PTRDIFF_T
221 #define PTRDIFF_T int
222 #endif
223
224 #define array_size(x) (sizeof (x) / sizeof (x[0]))
225
226 #define stringify1(s) #s
227 #define stringify(s) stringify1(s)
228
229 #define verinfo(maj, min, lev) ((maj) << 16 | (min) << 8 | (lev))
230
231 /* Column types for static string column descriptions (SQLTables etc.) */
232
233 #if defined(WINTERFACE) && !defined(_WIN32) && !defined(_WIN64)
234 #define SCOL_VARCHAR SQL_WVARCHAR
235 #define SCOL_CHAR SQL_WCHAR
236 #else
237 #define SCOL_VARCHAR SQL_VARCHAR
238 #define SCOL_CHAR SQL_CHAR
239 #endif
240
241 #define ENV_MAGIC 0x53544145
242 #define DBC_MAGIC 0x53544144
243 #define DEAD_MAGIC 0xdeadbeef
244
245 /**
246 * @typedef dstr
247 * @struct dstr
248 * Internal structure representing dynamic strings.
249 */
250
251 typedef struct dstr {
252 int len; /**< Current length. */
253 int max; /**< Maximum length of buffer. */
254 int oom; /**< True when out of memory. */
255 char buffer[1]; /**< String buffer. */
256 } dstr;
257
258 static const char *xdigits = "0123456789ABCDEFabcdef";
259
260 #ifdef MEMORY_DEBUG
261
262 static void *
xmalloc_(int n,char * file,int line)263 xmalloc_(int n, char *file, int line)
264 {
265 int nn = n + 4 * sizeof (long);
266 long *p;
267
268 p = malloc(nn);
269 if (!p) {
270 #if (MEMORY_DEBUG > 1)
271 fprintf(stderr, "malloc\t%d\tNULL\t%s:%d\n", n, file, line);
272 #endif
273 return NULL;
274 }
275 p[0] = 0xdead1234;
276 nn = nn / sizeof (long) - 1;
277 p[1] = n;
278 p[nn] = 0xdead5678;
279 #if (MEMORY_DEBUG > 1)
280 fprintf(stderr, "malloc\t%d\t%p\t%s:%d\n", n, &p[2], file, line);
281 #endif
282 return (void *) &p[2];
283 }
284
285 static void *
xrealloc_(void * old,int n,char * file,int line)286 xrealloc_(void *old, int n, char *file, int line)
287 {
288 int nn = n + 4 * sizeof (long), nnn;
289 long *p, *pp;
290
291 if (n == 0 || !old) {
292 return xmalloc_(n, file, line);
293 }
294 p = &((long *) old)[-2];
295 if (p[0] != 0xdead1234) {
296 fprintf(stderr, "*** low end corruption @ %p\n", old);
297 abort();
298 }
299 nnn = p[1] + 4 * sizeof (long);
300 nnn = nnn / sizeof (long) - 1;
301 if (p[nnn] != 0xdead5678) {
302 fprintf(stderr, "*** high end corruption @ %p\n", old);
303 abort();
304 }
305 pp = realloc(p, nn);
306 if (!pp) {
307 #if (MEMORY_DEBUG > 1)
308 fprintf(stderr, "realloc\t%p,%d\tNULL\t%s:%d\n", old, n, file, line);
309 #endif
310 return NULL;
311 }
312 #if (MEMORY_DEBUG > 1)
313 fprintf(stderr, "realloc\t%p,%d\t%p\t%s:%d\n", old, n, &pp[2], file, line);
314 #endif
315 p = pp;
316 p[1] = n;
317 nn = nn / sizeof (long) - 1;
318 p[nn] = 0xdead5678;
319 return (void *) &p[2];
320 }
321
322 static void
xfree_(void * x,char * file,int line)323 xfree_(void *x, char *file, int line)
324 {
325 long *p;
326 int n;
327
328 if (!x) {
329 return;
330 }
331 p = &((long *) x)[-2];
332 if (p[0] != 0xdead1234) {
333 fprintf(stderr, "*** low end corruption @ %p\n", x);
334 abort();
335 }
336 n = p[1] + 4 * sizeof (long);
337 n = n / sizeof (long) - 1;
338 if (p[n] != 0xdead5678) {
339 fprintf(stderr, "*** high end corruption @ %p\n", x);
340 abort();
341 }
342 #if (MEMORY_DEBUG > 1)
343 fprintf(stderr, "free\t%p\t\t%s:%d\n", x, file, line);
344 #endif
345 free(p);
346 }
347
348 static void
xfree__(void * x)349 xfree__(void *x)
350 {
351 xfree_(x, "unknown location", 0);
352 }
353
354 static char *
xstrdup_(const char * str,char * file,int line)355 xstrdup_(const char *str, char *file, int line)
356 {
357 char *p;
358
359 if (!str) {
360 #if (MEMORY_DEBUG > 1)
361 fprintf(stderr, "strdup\tNULL\tNULL\t%s:%d\n", file, line);
362 #endif
363 return NULL;
364 }
365 p = xmalloc_(strlen(str) + 1, file, line);
366 if (p) {
367 strcpy(p, str);
368 }
369 #if (MEMORY_DEBUG > 1)
370 fprintf(stderr, "strdup\t%p\t%p\t%s:%d\n", str, p, file, line);
371 #endif
372 return p;
373 }
374
375 #define xmalloc(x) xmalloc_(x, __FILE__, __LINE__)
376 #define xrealloc(x,y) xrealloc_(x, y, __FILE__, __LINE__)
377 #define xfree(x) xfree_(x, __FILE__, __LINE__)
378 #define xstrdup(x) xstrdup_(x, __FILE__, __LINE__)
379
380 #else
381
382 #define xmalloc(x) sqlite4_malloc(0, x)
383 #define xrealloc(x,y) sqlite4_realloc(0, x, y)
384 #define xfree(x) sqlite4_free(0, x)
385 #define xstrdup(x) strdup_(x)
386
387 #endif
388
389 #if defined(_WIN32) || defined(_WIN64)
390
391 #define vsnprintf _vsnprintf
392 #define snprintf _snprintf
393 #define strcasecmp _stricmp
394 #define strncasecmp _strnicmp
395
396 #ifdef _MSC_VER
397 #define strtoll _strtoi64
398 #define strtoull _strtoui64
399 #endif
400
401 static HINSTANCE NEAR hModule; /* Saved module handle for resources */
402
403 #endif
404
405 #undef strncasecmp
406 #define strncasecmp(A,B,C) sqlite4_strnicmp(A,B,C)
407 #undef strcasecmp
408 #define strcasecmp(A,B) strcasecmp_(A,B)
409
410 #if defined(__GNUC__) && (__GNUC__ >= 2)
411 static int strcasecmp_(const char *a, const char *b)
412 __attribute__((__unused__));
413 #endif
414
strcasecmp_(const char * a,const char * b)415 static int strcasecmp_(const char *a, const char *b)
416 {
417 int c = strlen(a), d = strlen(b);
418
419 if (c > d) {
420 return strncasecmp(a, b, c);
421 }
422 return strncasecmp(a, b, d);
423 }
424
425 #if defined(_WIN32) || defined(_WIN64)
426
427 /*
428 * SQLHENV, SQLHDBC, and SQLHSTMT synchronization
429 * is done using a critical section in ENV and DBC
430 * structures.
431 */
432
433 #define HDBC_LOCK(hdbc) \
434 { \
435 DBC *d; \
436 \
437 if ((hdbc) == SQL_NULL_HDBC) { \
438 return SQL_INVALID_HANDLE; \
439 } \
440 d = (DBC *) (hdbc); \
441 if (d->magic != DBC_MAGIC) { \
442 return SQL_INVALID_HANDLE; \
443 } \
444 EnterCriticalSection(&d->cs); \
445 d->owner = GetCurrentThreadId(); \
446 }
447
448 #define HDBC_UNLOCK(hdbc) \
449 if ((hdbc) != SQL_NULL_HDBC) { \
450 DBC *d; \
451 \
452 d = (DBC *) (hdbc); \
453 if (d->magic == DBC_MAGIC) { \
454 LeaveCriticalSection(&d->cs); \
455 } \
456 }
457
458 #define HSTMT_LOCK(hstmt) \
459 { \
460 DBC *d; \
461 \
462 if ((hstmt) == SQL_NULL_HSTMT) { \
463 return SQL_INVALID_HANDLE; \
464 } \
465 d = (DBC *) ((STMT *) (hstmt))->dbc; \
466 if (d->magic != DBC_MAGIC) { \
467 return SQL_INVALID_HANDLE; \
468 } \
469 if (d->env->magic != ENV_MAGIC) { \
470 return SQL_INVALID_HANDLE; \
471 } \
472 EnterCriticalSection(&d->cs); \
473 d->owner = GetCurrentThreadId(); \
474 }
475
476 #define HSTMT_UNLOCK(hstmt) \
477 if ((hstmt) != SQL_NULL_HSTMT) { \
478 DBC *d; \
479 \
480 d = (DBC *) ((STMT *) (hstmt))->dbc; \
481 if (d->magic == DBC_MAGIC) { \
482 LeaveCriticalSection(&d->cs); \
483 } \
484 }
485
486 #else
487
488 /*
489 * On UN*X assume that we are single-threaded or
490 * the driver manager provides serialization for us.
491 *
492 * In iODBC (3.52.x) serialization can be turned
493 * on using the DSN property "ThreadManager=yes".
494 *
495 * In unixODBC that property is named
496 * "Threading=0-3" and takes one of these values:
497 *
498 * 0 - no protection
499 * 1 - statement level protection
500 * 2 - connection level protection
501 * 3 - environment level protection
502 *
503 * unixODBC 2.2.11 uses environment level protection
504 * by default when it has been built with pthread
505 * support.
506 */
507
508 #define HDBC_LOCK(hdbc)
509 #define HDBC_UNLOCK(hdbc)
510 #define HSTMT_LOCK(hdbc)
511 #define HSTMT_UNLOCK(hdbc)
512
513 #endif
514
515 /*
516 * tolower() replacement w/o locale
517 */
518
519 static const char upper_chars[] = "ABCDEFGHIJKLMNOPQRSTUVWXYZ";
520 static const char lower_chars[] = "abcdefghijklmnopqrstuvwxyz";
521
522 static int
TOLOWER(int c)523 TOLOWER(int c)
524 {
525 if (c) {
526 char *p = strchr(upper_chars, c);
527
528 if (p) {
529 c = lower_chars[p - upper_chars];
530 }
531 }
532 return c;
533 }
534
535 /*
536 * isdigit() replacement w/o ctype.h
537 */
538
539 static const char digit_chars[] = "0123456789";
540
541 #define ISDIGIT(c) \
542 ((c) && strchr(digit_chars, (c)) != NULL)
543
544 /*
545 * isspace() replacement w/o ctype.h
546 */
547
548 static const char space_chars[] = " \f\n\r\t\v";
549
550 #define ISSPACE(c) \
551 ((c) && strchr(space_chars, (c)) != NULL)
552
553
554 /*
555 * Forward declarations of static functions.
556 */
557
558 static void dbtraceapi(DBC *d, char *fn, const char *sql);
559 static void freedyncols(STMT *s);
560 static void freeresult(STMT *s, int clrcols);
561 static void freerows(char **rowp);
562 static void unbindcols(STMT *s);
563 static void s4stmt_drop(STMT *s);
564
565 static SQLRETURN drvexecute(SQLHSTMT stmt, int initial);
566 static SQLRETURN freestmt(HSTMT stmt);
567 static SQLRETURN mkbindcols(STMT *s, int ncols);
568 static SQLRETURN setupdyncols(STMT *s, sqlite4_stmt *s4stmt, int *ncolsp);
569 static SQLRETURN setupparbuf(STMT *s, BINDPARM *p);
570 static SQLRETURN starttran(STMT *s);
571 static SQLRETURN setupparam(STMT *s, char *sql, int pnum);
572 static SQLRETURN getrowdata(STMT *s, SQLUSMALLINT col, SQLSMALLINT otype,
573 SQLPOINTER val, SQLINTEGER len, SQLLEN *lenp,
574 int partial);
575
576 #if (defined(_WIN32) || defined(_WIN64)) && defined(WINTERFACE)
577 /* MS Access hack part 1 (reserved error -7748) */
578 static COL *statSpec2P, *statSpec3P;
579 #endif
580
581 #if (MEMORY_DEBUG < 1)
582 /**
583 * Duplicate string using xmalloc().
584 * @param str string to be duplicated
585 * @result pointer to new string or NULL
586 */
587
588 static char *
strdup_(const char * str)589 strdup_(const char *str)
590 {
591 char *p = NULL;
592
593 if (str) {
594 p = xmalloc(strlen(str) + 1);
595 if (p) {
596 strcpy(p, str);
597 }
598 }
599 return p;
600 }
601 #endif
602
603 /**
604 * Append string to dynamic string.
605 * @param dsp dstr pointer
606 * @param str string to append
607 * @result dsp result dstr pointer or NULL.
608 */
609
610 static dstr *
dsappend(dstr * dsp,const char * str)611 dsappend(dstr *dsp, const char *str)
612 {
613 int len;
614
615 if (!str) {
616 return dsp;
617 }
618 len = strlen(str);
619 if (!dsp) {
620 int max = 256;
621
622 if (max < len) {
623 max += len;
624 }
625 dsp = xmalloc(max);
626 if (dsp) {
627 dsp->max = max;
628 dsp->len = dsp->oom = 0;
629 goto copy;
630 }
631 return dsp;
632 }
633 if (dsp->oom) {
634 return dsp;
635 }
636 if (dsp->len + len > dsp->max) {
637 int max = dsp->max + len + 256;
638 dstr *ndsp = xrealloc(dsp, max);
639
640 if (!ndsp) {
641 strcpy(dsp->buffer, "OUT OF MEMORY");
642 dsp->max = dsp->len = 13;
643 dsp->oom = 1;
644 return dsp;
645 }
646 dsp = ndsp;
647 dsp->max = max;
648 }
649 copy:
650 strcpy(dsp->buffer + dsp->len, str);
651 dsp->len += len;
652 return dsp;
653 }
654
655 /**
656 * Append a string double quoted to dynamic string.
657 * @param dsp dstr pointer
658 * @param str string to append
659 * @result dsp result dstr pointer or NULL.
660 */
661
662 static dstr *
dsappendq(dstr * dsp,const char * str)663 dsappendq(dstr *dsp, const char *str)
664 {
665 int len;
666 const char *p;
667 char *q;
668
669 if (!str) {
670 return dsp;
671 }
672 len = strlen(str);
673 for (p = str; *p; ++p) {
674 if (p[0] == '"') {
675 ++len;
676 }
677 }
678 len += 2;
679 if (!dsp) {
680 int max = 256;
681
682 if (max < len) {
683 max += len;
684 }
685 dsp = xmalloc(max);
686 if (dsp) {
687 dsp->max = max;
688 dsp->len = dsp->oom = 0;
689 goto copy;
690 }
691 return dsp;
692 }
693 if (dsp->oom) {
694 return dsp;
695 }
696 if (dsp->len + len > dsp->max) {
697 int max = dsp->max + len + 256;
698 dstr *ndsp = xrealloc(dsp, max);
699
700 if (!ndsp) {
701 strcpy(dsp->buffer, "OUT OF MEMORY");
702 dsp->max = dsp->len = 13;
703 dsp->oom = 1;
704 return dsp;
705 }
706 dsp = ndsp;
707 dsp->max = max;
708 }
709 copy:
710 q = dsp->buffer + dsp->len;
711 *q++ = '"';
712 for (p = str; *p; ++p) {
713 *q++ = *p;
714 if (p[0] == '"') {
715 *q++ = '"';
716 }
717 }
718 *q++ = '"';
719 *q = '\0';
720 dsp->len += len;
721 return dsp;
722 }
723
724 /**
725 * Return dynamic string's value.
726 * @param dsp dstr pointer
727 * @result string value
728 */
729
730 static const char *
dsval(dstr * dsp)731 dsval(dstr *dsp)
732 {
733 if (dsp) {
734 return (const char *) dsp->buffer;
735 }
736 return "ERROR";
737 }
738
739 /**
740 * Check error on dynamic string.
741 * @param dsp dstr pointer
742 * @result true when error pending
743 */
744
745 static int
dserr(dstr * dsp)746 dserr(dstr *dsp)
747 {
748 return !dsp || dsp->oom;
749 }
750
751 /**
752 * Free dynamic string.
753 * @param dsp dstr pointer
754 */
755
756 static void
dsfree(dstr * dsp)757 dsfree(dstr *dsp)
758 {
759 if (dsp) {
760 xfree(dsp);
761 }
762 }
763
764 #ifdef WCHARSUPPORT
765
766 /**
767 * Return length of UNICODE string.
768 * @param str UNICODE string
769 * @result length of string in characters
770 */
771
772 static int
uc_strlen(SQLWCHAR * str)773 uc_strlen(SQLWCHAR *str)
774 {
775 int len = 0;
776
777 if (str) {
778 while (*str) {
779 ++len;
780 ++str;
781 }
782 }
783 return len;
784 }
785
786 /**
787 * Copy UNICODE string like strncpy().
788 * @param dest destination area
789 * @param src source area
790 * @param len length of source area in characters
791 * @return pointer to destination area
792 */
793
794 static SQLWCHAR *
uc_strncpy(SQLWCHAR * dest,SQLWCHAR * src,int len)795 uc_strncpy(SQLWCHAR *dest, SQLWCHAR *src, int len)
796 {
797 int i = 0;
798
799 while (i < len) {
800 if (!src[i]) {
801 break;
802 }
803 dest[i] = src[i];
804 ++i;
805 }
806 if (i < len) {
807 dest[i] = 0;
808 }
809 return dest;
810 }
811
812 /**
813 * Make UNICODE string from UTF8 string into buffer.
814 * @param str UTF8 string to be converted
815 * @param len length in characters of str or -1
816 * @param uc destination area to receive UNICODE string
817 * @param ucLen byte length of destination area
818 */
819
820 static void
uc_from_utf_buf(unsigned char * str,int len,SQLWCHAR * uc,int ucLen)821 uc_from_utf_buf(unsigned char *str, int len, SQLWCHAR *uc, int ucLen)
822 {
823 ucLen = ucLen / sizeof (SQLWCHAR);
824 if (!uc || ucLen < 0) {
825 return;
826 }
827 if (len < 0) {
828 len = ucLen * 5;
829 }
830 uc[0] = 0;
831 if (str) {
832 int i = 0;
833
834 while (i < len && *str && i < ucLen) {
835 unsigned char c = str[0];
836
837 if (c < 0x80) {
838 uc[i++] = c;
839 ++str;
840 } else if (c <= 0xc1 || c >= 0xf5) {
841 /* illegal, ignored */
842 ++str;
843 } else if (c < 0xe0) {
844 if ((str[1] & 0xc0) == 0x80) {
845 unsigned long t = ((c & 0x1f) << 6) | (str[1] & 0x3f);
846
847 uc[i++] = t;
848 str += 2;
849 } else {
850 uc[i++] = c;
851 ++str;
852 }
853 } else if (c < 0xf0) {
854 if ((str[1] & 0xc0) == 0x80 && (str[2] & 0xc0) == 0x80) {
855 unsigned long t = ((c & 0x0f) << 12) |
856 ((str[1] & 0x3f) << 6) | (str[2] & 0x3f);
857
858 uc[i++] = t;
859 str += 3;
860 } else {
861 uc[i++] = c;
862 ++str;
863 }
864 } else if (c < 0xf8) {
865 if ((str[1] & 0xc0) == 0x80 && (str[2] & 0xc0) == 0x80 &&
866 (str[3] & 0xc0) == 0x80) {
867 unsigned long t = ((c & 0x03) << 18) |
868 ((str[1] & 0x3f) << 12) | ((str[2] & 0x3f) << 6) |
869 (str[3] & 0x3f);
870
871 if (sizeof (SQLWCHAR) == 2 * sizeof (char) &&
872 t >= 0x10000) {
873 t -= 0x10000;
874 uc[i++] = 0xd800 | ((t >> 10) & 0x3ff);
875 if (i >= ucLen) {
876 break;
877 }
878 t = 0xdc00 | (t & 0x3ff);
879 }
880 uc[i++] = t;
881 str += 4;
882 } else {
883 uc[i++] = c;
884 ++str;
885 }
886 }
887 }
888 if (i < ucLen) {
889 uc[i] = 0;
890 }
891 }
892 }
893
894 /**
895 * Make UNICODE string from UTF8 string.
896 * @param str UTF8 string to be converted
897 * @param len length of UTF8 string
898 * @return alloc'ed UNICODE string to be free'd by uc_free()
899 */
900
901 static SQLWCHAR *
uc_from_utf(unsigned char * str,int len)902 uc_from_utf(unsigned char *str, int len)
903 {
904 SQLWCHAR *uc = NULL;
905 int ucLen;
906
907 if (str) {
908 if (len == SQL_NTS) {
909 len = strlen((char *) str);
910 }
911 ucLen = sizeof (SQLWCHAR) * (len + 1);
912 uc = xmalloc(ucLen);
913 if (uc) {
914 uc_from_utf_buf(str, len, uc, ucLen);
915 }
916 }
917 return uc;
918 }
919
920 /**
921 * Make UTF8 string from UNICODE string.
922 * @param str UNICODE string to be converted
923 * @param len length of UNICODE string in bytes
924 * @return alloc'ed UTF8 string to be free'd by uc_free()
925 */
926
927 static char *
uc_to_utf(SQLWCHAR * str,int len)928 uc_to_utf(SQLWCHAR *str, int len)
929 {
930 int i;
931 char *cp, *ret = NULL;
932
933 if (!str) {
934 return ret;
935 }
936 if (len == SQL_NTS) {
937 len = uc_strlen(str);
938 } else {
939 len = len / sizeof (SQLWCHAR);
940 }
941 cp = xmalloc(len * 6 + 1);
942 if (!cp) {
943 return ret;
944 }
945 ret = cp;
946 for (i = 0; i < len; i++) {
947 unsigned long c = str[i];
948
949 if (sizeof (SQLWCHAR) == 2 * sizeof (char)) {
950 c &= 0xffff;
951 }
952 if (c < 0x80) {
953 *cp++ = c;
954 } else if (c < 0x800) {
955 *cp++ = 0xc0 | ((c >> 6) & 0x1f);
956 *cp++ = 0x80 | (c & 0x3f);
957 } else if (c < 0x10000) {
958 if (sizeof (SQLWCHAR) == 2 * sizeof (char) &&
959 c >= 0xd800 && c <= 0xdbff && i + 1 < len) {
960 unsigned long c2 = str[i + 1] & 0xffff;
961
962 if (c2 >= 0xdc00 && c2 <= 0xdfff) {
963 c = (((c & 0x3ff) << 10) | (c2 & 0x3ff)) + 0x10000;
964 *cp++ = 0xf0 | ((c >> 18) & 0x07);
965 *cp++ = 0x80 | ((c >> 12) & 0x3f);
966 *cp++ = 0x80 | ((c >> 6) & 0x3f);
967 *cp++ = 0x80 | (c & 0x3f);
968 ++i;
969 continue;
970 }
971 }
972 *cp++ = 0xe0 | ((c >> 12) & 0x0f);
973 *cp++ = 0x80 | ((c >> 6) & 0x3f);
974 *cp++ = 0x80 | (c & 0x3f);
975 } else if (c <= 0x10ffff) {
976 *cp++ = 0xf0 | ((c >> 18) & 0x07);
977 *cp++ = 0x80 | ((c >> 12) & 0x3f);
978 *cp++ = 0x80 | ((c >> 6) & 0x3f);
979 *cp++ = 0x80 | (c & 0x3f);
980 }
981 }
982 *cp = '\0';
983 return ret;
984 }
985
986 #endif
987
988 #ifdef WINTERFACE
989
990 /**
991 * Make UTF8 string from UNICODE string.
992 * @param str UNICODE string to be converted
993 * @param len length of UNICODE string in characters
994 * @return alloc'ed UTF8 string to be free'd by uc_free()
995 */
996
997 static char *
uc_to_utf_c(SQLWCHAR * str,int len)998 uc_to_utf_c(SQLWCHAR *str, int len)
999 {
1000 if (len != SQL_NTS) {
1001 len = len * sizeof (SQLWCHAR);
1002 }
1003 return uc_to_utf(str, len);
1004 }
1005
1006 #endif
1007
1008 #if defined(WCHARSUPPORT) || defined(_WIN32) || defined(_WIN64)
1009
1010 /**
1011 * Free converted UTF8 or UNICODE string.
1012 * @param str string to be free'd
1013 */
1014
1015 static void
uc_free(void * str)1016 uc_free(void *str)
1017 {
1018 if (str) {
1019 xfree(str);
1020 }
1021 }
1022
1023 #endif
1024
1025 #if defined(_WIN32) || defined(_WIN64)
1026
1027 /**
1028 * Convert multibyte, current code page string to UTF8 string,
1029 * @param str multibyte string to be converted
1030 * @param len length of multibyte string
1031 * @return alloc'ed UTF8 string to be free'd by uc_free()
1032 */
1033
1034 static char *
wmb_to_utf(char * str,int len)1035 wmb_to_utf(char *str, int len)
1036 {
1037 WCHAR *wstr;
1038 OSVERSIONINFO ovi;
1039 int nchar, is2k, cp = CP_OEMCP;
1040
1041 ovi.dwOSVersionInfoSize = sizeof (ovi);
1042 GetVersionEx(&ovi);
1043 is2k = ovi.dwPlatformId == VER_PLATFORM_WIN32_NT && ovi.dwMajorVersion > 4;
1044 if (AreFileApisANSI()) {
1045 cp = is2k ? CP_THREAD_ACP : CP_ACP;
1046 }
1047 nchar = MultiByteToWideChar(cp, 0, str, len, NULL, 0);
1048 wstr = xmalloc((nchar + 1) * sizeof (WCHAR));
1049 if (!wstr) {
1050 return NULL;
1051 }
1052 wstr[0] = 0;
1053 nchar = MultiByteToWideChar(cp, 0, str, len, wstr, nchar);
1054 wstr[nchar] = 0;
1055 str = xmalloc((nchar + 1) * 7);
1056 if (!str) {
1057 xfree(wstr);
1058 return NULL;
1059 }
1060 str[0] = '\0';
1061 nchar = WideCharToMultiByte(CP_UTF8, 0, wstr, -1, str, nchar * 7, 0, 0);
1062 str[nchar] = '\0';
1063 xfree(wstr);
1064 return str;
1065 }
1066
1067 #ifndef WINTERFACE
1068
1069 /**
1070 * Convert multibyte, current code page string to UTF8 string,
1071 * @param str multibyte string to be converted
1072 * @param len length of multibyte string
1073 * @return alloc'ed UTF8 string to be free'd by uc_free()
1074 */
1075
1076 static char *
wmb_to_utf_c(char * str,int len)1077 wmb_to_utf_c(char *str, int len)
1078 {
1079 if (len == SQL_NTS) {
1080 len = strlen(str);
1081 }
1082 return wmb_to_utf(str, len);
1083 }
1084
1085 #endif
1086
1087 /**
1088 * Convert UTF8 string to multibyte, current code page string,
1089 * @param str UTF8 string to be converted
1090 * @param len length of UTF8 string
1091 * @return alloc'ed multibyte string to be free'd by uc_free()
1092 */
1093
1094 static char *
utf_to_wmb(char * str,int len)1095 utf_to_wmb(char *str, int len)
1096 {
1097 WCHAR *wstr;
1098 OSVERSIONINFO ovi;
1099 int nchar, is2k, cp = CP_OEMCP;
1100
1101 ovi.dwOSVersionInfoSize = sizeof (ovi);
1102 GetVersionEx(&ovi);
1103 is2k = ovi.dwPlatformId == VER_PLATFORM_WIN32_NT && ovi.dwMajorVersion > 4;
1104 if (AreFileApisANSI()) {
1105 cp = is2k ? CP_THREAD_ACP : CP_ACP;
1106 }
1107 nchar = MultiByteToWideChar(CP_UTF8, 0, str, len, NULL, 0);
1108 wstr = xmalloc((nchar + 1) * sizeof (WCHAR));
1109 if (!wstr) {
1110 return NULL;
1111 }
1112 wstr[0] = 0;
1113 nchar = MultiByteToWideChar(CP_UTF8, 0, str, len, wstr, nchar);
1114 wstr[nchar] = 0;
1115 str = xmalloc((nchar + 1) * 7);
1116 if (!str) {
1117 xfree(wstr);
1118 return NULL;
1119 }
1120 str[0] = '\0';
1121 nchar = WideCharToMultiByte(cp, 0, wstr, -1, str, nchar * 7, 0, 0);
1122 str[nchar] = '\0';
1123 xfree(wstr);
1124 return str;
1125 }
1126
1127 #ifdef WINTERFACE
1128
1129 /**
1130 * Convert multibyte, current code page string to UNICODE string,
1131 * @param str multibyte string to be converted
1132 * @param len length of multibyte string
1133 * @return alloc'ed UNICODE string to be free'd by uc_free()
1134 */
1135
1136 static WCHAR *
wmb_to_uc(char * str,int len)1137 wmb_to_uc(char *str, int len)
1138 {
1139 WCHAR *wstr;
1140 OSVERSIONINFO ovi;
1141 int nchar, is2k, cp = CP_OEMCP;
1142
1143 ovi.dwOSVersionInfoSize = sizeof (ovi);
1144 GetVersionEx(&ovi);
1145 is2k = ovi.dwPlatformId == VER_PLATFORM_WIN32_NT && ovi.dwMajorVersion > 4;
1146 if (AreFileApisANSI()) {
1147 cp = is2k ? CP_THREAD_ACP : CP_ACP;
1148 }
1149 nchar = MultiByteToWideChar(cp, 0, str, len, NULL, 0);
1150 wstr = xmalloc((nchar + 1) * sizeof (WCHAR));
1151 if (!wstr) {
1152 return NULL;
1153 }
1154 wstr[0] = 0;
1155 nchar = MultiByteToWideChar(cp, 0, str, len, wstr, nchar);
1156 wstr[nchar] = 0;
1157 return wstr;
1158 }
1159
1160 /**
1161 * Convert UNICODE string to multibyte, current code page string,
1162 * @param str UNICODE string to be converted
1163 * @param len length of UNICODE string
1164 * @return alloc'ed multibyte string to be free'd by uc_free()
1165 */
1166
1167 static char *
uc_to_wmb(WCHAR * wstr,int len)1168 uc_to_wmb(WCHAR *wstr, int len)
1169 {
1170 char *str;
1171 OSVERSIONINFO ovi;
1172 int nchar, is2k, cp = CP_OEMCP;
1173
1174 ovi.dwOSVersionInfoSize = sizeof (ovi);
1175 GetVersionEx(&ovi);
1176 is2k = ovi.dwPlatformId == VER_PLATFORM_WIN32_NT && ovi.dwMajorVersion > 4;
1177 if (AreFileApisANSI()) {
1178 cp = is2k ? CP_THREAD_ACP : CP_ACP;
1179 }
1180 nchar = WideCharToMultiByte(cp, 0, wstr, len, NULL, 0, 0, 0);
1181 str = xmalloc((nchar + 1) * 2);
1182 if (!str) {
1183 return NULL;
1184 }
1185 str[0] = '\0';
1186 nchar = WideCharToMultiByte(cp, 0, wstr, len, str, nchar * 2, 0, 0);
1187 str[nchar] = '\0';
1188 return str;
1189 }
1190
1191 #endif /* WINTERFACE */
1192
1193 #endif /* _WIN32 || _WIN64 */
1194
1195
1196 #ifdef USE_DLOPEN_FOR_GPPS
1197
1198 #include <dlfcn.h>
1199
1200 #define SQLGetPrivateProfileString(A,B,C,D,E,F) drvgpps(d,A,B,C,D,E,F)
1201
1202 /*
1203 * EXPERIMENTAL: SQLGetPrivateProfileString infrastructure using
1204 * dlopen(), in theory this makes the driver independent from the
1205 * driver manager, i.e. the same driver binary can run with iODBC
1206 * and unixODBC.
1207 */
1208
1209 static void
drvgetgpps(DBC * d)1210 drvgetgpps(DBC *d)
1211 {
1212 void *lib;
1213 int (*gpps)();
1214
1215 lib = dlopen("libodbcinst.so.2", RTLD_LAZY);
1216 if (!lib) {
1217 lib = dlopen("libodbcinst.so.1", RTLD_LAZY);
1218 }
1219 if (!lib) {
1220 lib = dlopen("libodbcinst.so", RTLD_LAZY);
1221 }
1222 if (!lib) {
1223 lib = dlopen("libiodbcinst.so.2", RTLD_LAZY);
1224 }
1225 if (!lib) {
1226 lib = dlopen("libiodbcinst.so", RTLD_LAZY);
1227 }
1228 if (lib) {
1229 gpps = (int (*)()) dlsym(lib, "SQLGetPrivateProfileString");
1230 if (!gpps) {
1231 dlclose(lib);
1232 return;
1233 }
1234 d->instlib = lib;
1235 d->gpps = gpps;
1236 }
1237 }
1238
1239 static void
drvrelgpps(DBC * d)1240 drvrelgpps(DBC *d)
1241 {
1242 if (d->instlib) {
1243 dlclose(d->instlib);
1244 d->instlib = 0;
1245 }
1246 }
1247
1248 static int
drvgpps(DBC * d,char * sect,char * ent,char * def,char * buf,int bufsiz,char * fname)1249 drvgpps(DBC *d, char *sect, char *ent, char *def, char *buf,
1250 int bufsiz, char *fname)
1251 {
1252 if (d->gpps) {
1253 return d->gpps(sect, ent, def, buf, bufsiz, fname);
1254 }
1255 strncpy(buf, def, bufsiz);
1256 buf[bufsiz - 1] = '\0';
1257 return 1;
1258 }
1259 #else
1260 #include <odbcinst.h>
1261 #define drvgetgpps(d)
1262 #define drvrelgpps(d)
1263 #endif
1264
1265 /*
1266 * Internal function to bind sqlite4 parameters.
1267 */
1268
1269 static void
s4bind(DBC * d,sqlite4_stmt * stmt,int nparams,BINDPARM * p)1270 s4bind(DBC *d, sqlite4_stmt *stmt, int nparams, BINDPARM *p)
1271 {
1272 int i;
1273
1274 if (stmt && p && nparams > 0) {
1275 for (i = 0; i < nparams; i++, p++) {
1276 switch (p->s4type) {
1277 default:
1278 case SQLITE4_NULL:
1279 sqlite4_bind_null(stmt, i + 1);
1280 if (d->trace) {
1281 fprintf(d->trace, "-- parameter %d: NULL\n", i + 1);
1282 fflush(d->trace);
1283 }
1284 break;
1285 case SQLITE4_TEXT:
1286 sqlite4_bind_text(stmt, i + 1, p->s4val, p->s4size,
1287 SQLITE4_STATIC, 0);
1288 if (d->trace) {
1289 fprintf(d->trace, "-- parameter %d: '%*s'\n", i + 1,
1290 p->s4size, (char *) p->s4val);
1291 fflush(d->trace);
1292 }
1293 break;
1294 case SQLITE4_BLOB:
1295 sqlite4_bind_blob(stmt, i + 1, p->s4val, p->s4size,
1296 SQLITE4_STATIC, 0);
1297 if (d->trace) {
1298 fprintf(d->trace, "-- parameter %d: [BLOB]'\n", i + 1);
1299 fflush(d->trace);
1300 }
1301 break;
1302 case SQLITE4_FLOAT:
1303 sqlite4_bind_double(stmt, i + 1, p->s4dval);
1304 if (d->trace) {
1305 fprintf(d->trace, "-- parameter %d: %g\n",
1306 i + 1, p->s4dval);
1307 fflush(d->trace);
1308 }
1309 break;
1310 case SQLITE4_INTEGER:
1311 if (p->s4size > sizeof (int)) {
1312 sqlite4_bind_int64(stmt, i + 1, p->s4lival);
1313 if (d->trace) {
1314 fprintf(d->trace,
1315 #ifdef _WIN32
1316 "-- parameter %d: %I64d\n",
1317 #else
1318 "-- parameter %d: %lld\n",
1319 #endif
1320 i + 1, p->s4lival);
1321 fflush(d->trace);
1322 }
1323 } else {
1324 sqlite4_bind_int(stmt, i + 1, p->s4ival);
1325 if (d->trace) {
1326 fprintf(d->trace, "-- parameter %d: %d\n",
1327 i + 1, p->s4ival);
1328 fflush(d->trace);
1329 }
1330 }
1331 break;
1332 }
1333 }
1334 }
1335 }
1336
1337 /**
1338 * @typedef TBLRES
1339 * @struct tblres
1340 * Internal structure for managing driver's
1341 * sqlite4_get_table() implementation.
1342 */
1343
1344 typedef struct tblres {
1345 char **resarr; /**< result array */
1346 char *errmsg; /**< error message or NULL */
1347 sqlite4_stmt *stmt; /**< sqlite4 statement pointer */
1348 STMT *s; /**< Driver statement pointer */
1349 int nalloc; /**< alloc'ed size of result array */
1350 int nrow; /**< number of rows in result array */
1351 int ncol; /**< number of columns in result array */
1352 PTRDIFF_T ndata; /**< index into result array */
1353 int rc; /**< SQLite return code */
1354 } TBLRES;
1355
1356 /*
1357 * Driver's version of sqlite4_get_table() and friends which are
1358 * capable of dealing with blobs.
1359 */
1360
1361 static int
drvgettable_row(TBLRES * t,int ncol,int rc)1362 drvgettable_row(TBLRES *t, int ncol, int rc)
1363 {
1364 int need;
1365 int i;
1366 char *p;
1367
1368 if (t->nrow == 0 && rc == SQLITE4_ROW) {
1369 need = ncol * 2;
1370 } else {
1371 need = ncol;
1372 }
1373 if (t->ndata + need >= t->nalloc) {
1374 char **resnew;
1375 int nalloc = t->nalloc * 2 + need + 1;
1376
1377 resnew = xrealloc(t->resarr, sizeof (char *) * nalloc);
1378 if (!resnew) {
1379 nomem:
1380 t->rc = SQLITE4_NOMEM;
1381 return 1;
1382 }
1383 t->nalloc = nalloc;
1384 t->resarr = resnew;
1385 }
1386 /* column names when first row */
1387 if (t->nrow == 0) {
1388 t->ncol = ncol;
1389 for (i = 0; i < ncol; i++) {
1390 p = (char *) sqlite4_column_name(t->stmt, i);
1391 if (p) {
1392 char *q = xmalloc(strlen(p) + 1);
1393
1394 if (!q) {
1395 goto nomem;
1396 }
1397 strcpy(q, p);
1398 p = q;
1399 }
1400 t->resarr[t->ndata++] = p;
1401 }
1402 if (t->s && t->s->guessed_types) {
1403 int ncol2 = ncol;
1404
1405 setupdyncols(t->s, t->stmt, &ncol2);
1406 t->s->guessed_types = 0;
1407 t->s->ncols = ncol;
1408 }
1409 } else if (t->ncol != ncol) {
1410 t->errmsg = sqlite4_mprintf(0, "drvgettable() called with two or"
1411 " more incompatible queries");
1412 t->rc = SQLITE4_ERROR;
1413 return 1;
1414 }
1415 /* copy row data */
1416 if (rc == SQLITE4_ROW) {
1417 for (i = 0; i < ncol; i++) {
1418 int coltype = sqlite4_column_type(t->stmt, i);
1419
1420 p = NULL;
1421 if (coltype == SQLITE4_BLOB) {
1422 int k, nbytes;
1423 char *qp;
1424 unsigned const char *bp;
1425
1426 bp = sqlite4_column_blob(t->stmt, i, &nbytes);
1427 qp = xmalloc(nbytes * 2 + 4);
1428 if (!qp) {
1429 goto nomem;
1430 }
1431 p = qp;
1432 *qp++ = 'X';
1433 *qp++ = '\'';
1434 for (k = 0; k < nbytes; k++) {
1435 *qp++ = xdigits[(bp[k] >> 4)];
1436 *qp++ = xdigits[(bp[k] & 0xF)];
1437 }
1438 *qp++ = '\'';
1439 *qp = '\0';
1440 } else if (coltype != SQLITE4_NULL) {
1441 int nbytes;
1442
1443 p = xstrdup((char *) sqlite4_column_text(t->stmt, i, &nbytes));
1444 if (!p) {
1445 goto nomem;
1446 }
1447 }
1448 t->resarr[t->ndata++] = p;
1449 }
1450 t->nrow++;
1451 }
1452 return 0;
1453 }
1454
1455 static int
drvgettable(STMT * s,const char * sql,char *** resp,int * nrowp,int * ncolp,char ** errp,int nparam,BINDPARM * p)1456 drvgettable(STMT *s, const char *sql, char ***resp, int *nrowp,
1457 int *ncolp, char **errp, int nparam, BINDPARM *p)
1458 {
1459 DBC *d = (DBC *) s->dbc;
1460 int rc = SQLITE4_OK, keep = sql == NULL;
1461 TBLRES tres;
1462 int sqlleft = 0;
1463 int nretry = 0, haveerr = 0;
1464
1465 if (!resp) {
1466 return SQLITE4_ERROR;
1467 }
1468 *resp = NULL;
1469 if (nrowp) {
1470 *nrowp = 0;
1471 }
1472 if (ncolp) {
1473 *ncolp = 0;
1474 }
1475 tres.errmsg = NULL;
1476 tres.nrow = 0;
1477 tres.ncol = 0;
1478 tres.ndata = 1;
1479 tres.nalloc = 20;
1480 tres.rc = SQLITE4_OK;
1481 tres.resarr = xmalloc(sizeof (char *) * tres.nalloc);
1482 tres.stmt = NULL;
1483 tres.s = s;
1484 if (!tres.resarr) {
1485 return SQLITE4_NOMEM;
1486 }
1487 tres.resarr[0] = 0;
1488 if (sql == NULL) {
1489 tres.stmt = s->s4stmt;
1490 if (tres.stmt == NULL) {
1491 return SQLITE4_NOMEM;
1492 }
1493 goto retrieve;
1494 }
1495 while (sql && *sql && (rc == SQLITE4_OK ||
1496 (rc == SQLITE4_SCHEMA && (++nretry) < 2))) {
1497 int ncol;
1498
1499 tres.stmt = NULL;
1500 dbtraceapi(d, "sqlite4_prepare", sql);
1501 rc = sqlite4_prepare(d->sqlite, sql, -1, &tres.stmt, &sqlleft);
1502 if (rc != SQLITE4_OK) {
1503 if (tres.stmt) {
1504 dbtraceapi(d, "sqlite4_finalize", 0);
1505 sqlite4_finalize(tres.stmt);
1506 tres.stmt = NULL;
1507 }
1508 continue;
1509 }
1510 if (!tres.stmt) {
1511 /* this happens for a comment or white-space */
1512 sql += sqlleft;
1513 continue;
1514 }
1515 retrieve:
1516 if (sqlite4_bind_parameter_count(tres.stmt) != nparam) {
1517 if (errp) {
1518 *errp =
1519 sqlite4_mprintf(0, "%s",
1520 "parameter marker count incorrect");
1521 }
1522 haveerr = 1;
1523 rc = SQLITE4_ERROR;
1524 goto tbldone;
1525 }
1526 s4bind(d, tres.stmt, nparam, p);
1527 ncol = sqlite4_column_count(tres.stmt);
1528 while (1) {
1529 if (s->max_rows && tres.nrow >= s->max_rows) {
1530 rc = SQLITE4_OK;
1531 break;
1532 }
1533 rc = sqlite4_step(tres.stmt);
1534 if (rc == SQLITE4_ROW || rc == SQLITE4_DONE) {
1535 if (drvgettable_row(&tres, ncol, rc)) {
1536 rc = SQLITE4_ABORT;
1537 goto tbldone;
1538 }
1539 }
1540 if (rc != SQLITE4_ROW) {
1541 if (keep) {
1542 dbtraceapi(d, "sqlite4_reset", 0);
1543 rc = sqlite4_reset(tres.stmt);
1544 s->s4stmt_noreset = 1;
1545 } else {
1546 dbtraceapi(d, "sqlite4_finalize", 0);
1547 rc = sqlite4_finalize(tres.stmt);
1548 }
1549 tres.stmt = 0;
1550 if (rc != SQLITE4_SCHEMA) {
1551 nretry = 0;
1552 sql += sqlleft;
1553 while (sql && ISSPACE(*sql)) {
1554 sql++;
1555 }
1556 }
1557 if (rc == SQLITE4_DONE) {
1558 rc = SQLITE4_OK;
1559 }
1560 break;
1561 }
1562 }
1563 }
1564 tbldone:
1565 if (tres.stmt) {
1566 if (keep) {
1567 if (!s->s4stmt_noreset) {
1568 dbtraceapi(d, "sqlite4_reset", 0);
1569 sqlite4_reset(tres.stmt);
1570 s->s4stmt_noreset = 1;
1571 }
1572 } else {
1573 dbtraceapi(d, "sqlite4_finalize", 0);
1574 sqlite4_finalize(tres.stmt);
1575 }
1576 }
1577 if (haveerr) {
1578 /* message already in *errp if any */
1579 } else if (rc != SQLITE4_OK && rc == sqlite4_errcode(d->sqlite) && errp) {
1580 *errp = sqlite4_mprintf(0, "%s", sqlite4_errmsg(d->sqlite));
1581 } else if (errp) {
1582 *errp = NULL;
1583 }
1584 if (tres.resarr) {
1585 tres.resarr[0] = (char *) (tres.ndata - 1);
1586 }
1587 if (rc == SQLITE4_ABORT) {
1588 freerows(&tres.resarr[1]);
1589 if (tres.errmsg) {
1590 if (errp) {
1591 if (*errp) {
1592 sqlite4_free(0, *errp);
1593 }
1594 *errp = tres.errmsg;
1595 } else {
1596 sqlite4_free(0, tres.errmsg);
1597 }
1598 }
1599 return tres.rc;
1600 }
1601 sqlite4_free(0, tres.errmsg);
1602 if (rc != SQLITE4_OK) {
1603 freerows(&tres.resarr[1]);
1604 return rc;
1605 }
1606 *resp = &tres.resarr[1];
1607 if (ncolp) {
1608 *ncolp = tres.ncol;
1609 }
1610 if (nrowp) {
1611 *nrowp = tres.nrow;
1612 }
1613 return rc;
1614 }
1615
1616 static int
sqlite4_get_table(sqlite4 * db,const char * sql,char *** resp,int * nrowp,int * ncolp,char ** errp)1617 sqlite4_get_table(sqlite4 *db, const char *sql, char ***resp, int *nrowp,
1618 int *ncolp, char **errp)
1619 {
1620 int rc = SQLITE4_OK;
1621 TBLRES tres;
1622 int sqlleft = 0;
1623 int nretry = 0, haveerr = 0;
1624
1625 if (!resp) {
1626 return SQLITE4_ERROR;
1627 }
1628 *resp = NULL;
1629 if (nrowp) {
1630 *nrowp = 0;
1631 }
1632 if (ncolp) {
1633 *ncolp = 0;
1634 }
1635 tres.errmsg = NULL;
1636 tres.nrow = 0;
1637 tres.ncol = 0;
1638 tres.ndata = 1;
1639 tres.nalloc = 20;
1640 tres.rc = SQLITE4_OK;
1641 tres.resarr = xmalloc(sizeof (char *) * tres.nalloc);
1642 tres.stmt = NULL;
1643 tres.s = 0;
1644 if (!tres.resarr) {
1645 return SQLITE4_NOMEM;
1646 }
1647 tres.resarr[0] = 0;
1648 while (sql && *sql && (rc == SQLITE4_OK ||
1649 (rc == SQLITE4_SCHEMA && (++nretry) < 2))) {
1650 int ncol;
1651
1652 tres.stmt = NULL;
1653 rc = sqlite4_prepare(db, sql, -1, &tres.stmt, &sqlleft);
1654 if (rc != SQLITE4_OK) {
1655 if (tres.stmt) {
1656 sqlite4_finalize(tres.stmt);
1657 tres.stmt = NULL;
1658 }
1659 continue;
1660 }
1661 if (!tres.stmt) {
1662 /* this happens for a comment or white-space */
1663 sql += sqlleft;
1664 continue;
1665 }
1666 ncol = sqlite4_column_count(tres.stmt);
1667 while (1) {
1668 rc = sqlite4_step(tres.stmt);
1669 if (rc == SQLITE4_ROW || rc == SQLITE4_DONE) {
1670 if (drvgettable_row(&tres, ncol, rc)) {
1671 rc = SQLITE4_ABORT;
1672 goto tbldone;
1673 }
1674 }
1675 if (rc != SQLITE4_ROW) {
1676 rc = sqlite4_finalize(tres.stmt);
1677 tres.stmt = 0;
1678 if (rc != SQLITE4_SCHEMA) {
1679 nretry = 0;
1680 sql += sqlleft;
1681 while (sql && ISSPACE(*sql)) {
1682 sql++;
1683 }
1684 }
1685 if (rc == SQLITE4_DONE) {
1686 rc = SQLITE4_OK;
1687 }
1688 break;
1689 }
1690 }
1691 }
1692 tbldone:
1693 if (tres.stmt) {
1694 sqlite4_finalize(tres.stmt);
1695 }
1696 if (haveerr) {
1697 /* message already in *errp if any */
1698 } else if (rc != SQLITE4_OK && rc == sqlite4_errcode(db) && errp) {
1699 *errp = sqlite4_mprintf(0, "%s", sqlite4_errmsg(db));
1700 } else if (errp) {
1701 *errp = NULL;
1702 }
1703 if (tres.resarr) {
1704 tres.resarr[0] = (char *) (tres.ndata - 1);
1705 }
1706 if (rc == SQLITE4_ABORT) {
1707 freerows(&tres.resarr[1]);
1708 if (tres.errmsg) {
1709 if (errp) {
1710 if (*errp) {
1711 sqlite4_free(0, *errp);
1712 }
1713 *errp = tres.errmsg;
1714 } else {
1715 sqlite4_free(0, tres.errmsg);
1716 }
1717 }
1718 return tres.rc;
1719 }
1720 sqlite4_free(0, tres.errmsg);
1721 if (rc != SQLITE4_OK) {
1722 freerows(&tres.resarr[1]);
1723 return rc;
1724 }
1725 *resp = &tres.resarr[1];
1726 if (ncolp) {
1727 *ncolp = tres.ncol;
1728 }
1729 if (nrowp) {
1730 *nrowp = tres.nrow;
1731 }
1732 return rc;
1733 }
1734
1735 /**
1736 * Set error message and SQL state on DBC
1737 * @param d database connection pointer
1738 * @param naterr native error code
1739 * @param msg error message
1740 * @param st SQL state
1741 */
1742
1743 #if defined(__GNUC__) && (__GNUC__ >= 2)
1744 static void setstatd(DBC *, int, char *, char *, ...)
1745 __attribute__((format (printf, 3, 5)));
1746 #endif
1747
1748 static void
setstatd(DBC * d,int naterr,char * msg,char * st,...)1749 setstatd(DBC *d, int naterr, char *msg, char *st, ...)
1750 {
1751 va_list ap;
1752
1753 if (!d) {
1754 return;
1755 }
1756 d->naterr = naterr;
1757 d->logmsg[0] = '\0';
1758 if (msg) {
1759 int count;
1760
1761 va_start(ap, st);
1762 count = vsnprintf((char *) d->logmsg, sizeof (d->logmsg), msg, ap);
1763 va_end(ap);
1764 if (count < 0) {
1765 d->logmsg[sizeof (d->logmsg) - 1] = '\0';
1766 }
1767 }
1768 if (!st) {
1769 st = "?????";
1770 }
1771 strncpy(d->sqlstate, st, 5);
1772 d->sqlstate[5] = '\0';
1773 }
1774
1775 /**
1776 * Set error message and SQL state on statement
1777 * @param s statement pointer
1778 * @param naterr native error code
1779 * @param msg error message
1780 * @param st SQL state
1781 */
1782
1783 #if defined(__GNUC__) && (__GNUC__ >= 2)
1784 static void setstat(STMT *, int, char *, char *, ...)
1785 __attribute__((format (printf, 3, 5)));
1786 #endif
1787
1788 static void
setstat(STMT * s,int naterr,char * msg,char * st,...)1789 setstat(STMT *s, int naterr, char *msg, char *st, ...)
1790 {
1791 va_list ap;
1792
1793 if (!s) {
1794 return;
1795 }
1796 s->naterr = naterr;
1797 s->logmsg[0] = '\0';
1798 if (msg) {
1799 int count;
1800
1801 va_start(ap, st);
1802 count = vsnprintf((char *) s->logmsg, sizeof (s->logmsg), msg, ap);
1803 va_end(ap);
1804 if (count < 0) {
1805 s->logmsg[sizeof (s->logmsg) - 1] = '\0';
1806 }
1807 }
1808 if (!st) {
1809 st = "?????";
1810 }
1811 strncpy(s->sqlstate, st, 5);
1812 s->sqlstate[5] = '\0';
1813 }
1814
1815 /**
1816 * Report IM001 (not implemented) SQL error code for HDBC.
1817 * @param dbc database connection handle
1818 * @result ODBC error code
1819 */
1820
1821 static SQLRETURN
drvunimpldbc(HDBC dbc)1822 drvunimpldbc(HDBC dbc)
1823 {
1824 DBC *d;
1825
1826 if (dbc == SQL_NULL_HDBC) {
1827 return SQL_INVALID_HANDLE;
1828 }
1829 d = (DBC *) dbc;
1830 setstatd(d, -1, "not supported", "IM001");
1831 return SQL_ERROR;
1832 }
1833
1834 /**
1835 * Report IM001 (not implemented) SQL error code for HSTMT.
1836 * @param stmt statement handle
1837 * @result ODBC error code
1838 */
1839
1840 static SQLRETURN
drvunimplstmt(HSTMT stmt)1841 drvunimplstmt(HSTMT stmt)
1842 {
1843 STMT *s;
1844
1845 if (stmt == SQL_NULL_HSTMT) {
1846 return SQL_INVALID_HANDLE;
1847 }
1848 s = (STMT *) stmt;
1849 setstat(s, -1, "not supported", "IM001");
1850 return SQL_ERROR;
1851 }
1852
1853 /**
1854 * Free memory given pointer to memory pointer.
1855 * @param x pointer to pointer to memory to be free'd
1856 */
1857
1858 static void
freep(void * x)1859 freep(void *x)
1860 {
1861 if (x && ((char **) x)[0]) {
1862 xfree(((char **) x)[0]);
1863 ((char **) x)[0] = NULL;
1864 }
1865 }
1866
1867 /**
1868 * Report S1000 (out of memory) SQL error given STMT.
1869 * @param s statement pointer
1870 * @result ODBC error code
1871 */
1872
1873 static SQLRETURN
nomem(STMT * s)1874 nomem(STMT *s)
1875 {
1876 setstat(s, -1, "out of memory", (*s->ov3) ? "HY000" : "S1000");
1877 return SQL_ERROR;
1878 }
1879
1880 /**
1881 * Report S1000 (not connected) SQL error given STMT.
1882 * @param s statement pointer
1883 * @result ODBC error code
1884 */
1885
1886 static SQLRETURN
noconn(STMT * s)1887 noconn(STMT *s)
1888 {
1889 setstat(s, -1, "not connected", (*s->ov3) ? "HY000" : "S1000");
1890 return SQL_ERROR;
1891 }
1892
1893 /**
1894 * Internal locale neutral strtod function.
1895 * @param data pointer to string
1896 * @param endp pointer for ending character
1897 * @result double value
1898 */
1899
1900 #if defined(HAVE_LOCALECONV) || defined(_WIN32) || defined(_WIN64)
1901
1902 static double
ln_strtod(const char * data,char ** endp)1903 ln_strtod(const char *data, char **endp)
1904 {
1905 struct lconv *lc = 0;
1906 char buf[128], *p, *end;
1907 double value;
1908
1909 lc = localeconv();
1910 if (lc && lc->decimal_point && lc->decimal_point[0] &&
1911 lc->decimal_point[0] != '.') {
1912 strncpy(buf, data, sizeof (buf) - 1);
1913 buf[sizeof (buf) - 1] = '\0';
1914 p = strchr(buf, '.');
1915 if (p) {
1916 *p = lc->decimal_point[0];
1917 }
1918 p = buf;
1919 } else {
1920 p = (char *) data;
1921 }
1922 value = strtod(p, &end);
1923 end = (char *) data + (end - p);
1924 if (endp) {
1925 *endp = end;
1926 }
1927 return value;
1928 }
1929
1930 #else
1931
1932 #define ln_strtod(A,B) strtod(A,B)
1933
1934 #endif
1935
1936 /**
1937 * Strip quotes from quoted string in-place.
1938 * @param str string
1939 */
1940
1941 static char *
unquote(char * str)1942 unquote(char *str)
1943 {
1944 if (str) {
1945 int len = strlen(str);
1946
1947 if (len > 1) {
1948 int end = len - 1;
1949
1950 if ((str[0] == '\'' && str[end] == '\'') ||
1951 (str[0] == '"' && str[end] == '"') ||
1952 (str[0] == '[' && str[end] == ']')) {
1953 memmove(str, str + 1, end - 1);
1954 str[end - 1] = '\0';
1955 }
1956 }
1957 }
1958 return str;
1959 }
1960
1961 /**
1962 * Unescape search pattern for e.g. table name in
1963 * catalog functions. Replacements in string are done in-place.
1964 * @param str string
1965 * @result number of pattern characters in string or 0
1966 */
1967
1968 static int
unescpat(char * str)1969 unescpat(char *str)
1970 {
1971 char *p, *q;
1972 int count = 0;
1973
1974 p = str;
1975 while ((q = strchr(p, '_')) != NULL) {
1976 if (q == str || q[-1] != '\\') {
1977 count++;
1978 }
1979 p = q + 1;
1980 }
1981 p = str;
1982 while ((q = strchr(p, '%')) != NULL) {
1983 if (q == str || q[-1] != '\\') {
1984 count++;
1985 }
1986 p = q + 1;
1987 }
1988 p = str;
1989 while ((q = strchr(p, '\\')) != NULL) {
1990 if (q[1] == '\\' || q[1] == '_' || q[1] == '%') {
1991 memmove(q, q + 1, strlen(q));
1992 }
1993 p = q + 1;
1994 }
1995 return count;
1996 }
1997
1998 /**
1999 * SQL LIKE string match with optional backslash escape handling.
2000 * @param str string
2001 * @param pat pattern
2002 * @param esc when true, treat literally "\\" as "\", "\%" as "%", "\_" as "_"
2003 * @result true when pattern matched
2004 */
2005
2006 static int
namematch(char * str,char * pat,int esc)2007 namematch(char *str, char *pat, int esc)
2008 {
2009 int cp, ch;
2010
2011 while (1) {
2012 cp = TOLOWER(*pat);
2013 if (cp == '\0') {
2014 if (*str != '\0') {
2015 goto nomatch;
2016 }
2017 break;
2018 }
2019 if (*str == '\0' && cp != '%') {
2020 goto nomatch;
2021 }
2022 if (cp == '%') {
2023 while (*pat == '%') {
2024 ++pat;
2025 }
2026 cp = TOLOWER(*pat);
2027 if (cp == '\0') {
2028 break;
2029 }
2030 while (1) {
2031 if (cp != '_' && cp != '\\') {
2032 while (*str) {
2033 ch = TOLOWER(*str);
2034 if (ch == cp) {
2035 break;
2036 }
2037 ++str;
2038 }
2039 }
2040 if (namematch(str, pat, esc)) {
2041 goto match;
2042 }
2043 if (*str == '\0') {
2044 goto nomatch;
2045 }
2046 ch = TOLOWER(*str);
2047 ++str;
2048 }
2049 }
2050 if (cp == '_') {
2051 pat++;
2052 str++;
2053 continue;
2054 }
2055 if (esc && cp == '\\' &&
2056 (pat[1] == '\\' || pat[1] == '%' || pat[1] == '_')) {
2057 ++pat;
2058 cp = TOLOWER(*pat);
2059 }
2060 ch = TOLOWER(*str++);
2061 ++pat;
2062 if (ch != cp) {
2063 goto nomatch;
2064 }
2065 }
2066 match:
2067 return 1;
2068 nomatch:
2069 return 0;
2070 }
2071
2072 /**
2073 * Set SQLite options (PRAGMAs) given SQLite handle.
2074 * @param x SQLite database handle
2075 * @param d DBC pointer
2076 * @result SQLite error code
2077 *
2078 * SQLite < 3.3.x and not shortnames DSN option:
2079 * "full_column_names" is always turned on and "short_column_names"
2080 * is always turned off, to get the table names in column labels.
2081 */
2082
2083 static int
setsqliteopts(sqlite4 * x,DBC * d)2084 setsqliteopts(sqlite4 *x, DBC *d)
2085 {
2086 int count = 0, step = 0, max, rc = SQLITE4_ERROR;
2087
2088 max = d->longnames ? 3 : 1;
2089 if (d->shortnames) {
2090 max = 3;
2091 }
2092 while (step < max) {
2093 if (step < 1) {
2094 rc = sqlite4_exec(x, "PRAGMA empty_result_callbacks = on;",
2095 NULL, NULL);
2096 if (rc == SQLITE4_OK) {
2097 rc = sqlite4_exec(x, d->fksupport ?
2098 "PRAGMA foreign_keys = on;" :
2099 "PRAGMA foreign_keys = off;",
2100 NULL, NULL);
2101 }
2102 } else if (step < 2) {
2103 rc = sqlite4_exec(x, d->shortnames ?
2104 "PRAGMA full_column_names = off;" :
2105 "PRAGMA full_column_names = on;",
2106 NULL, NULL);
2107 } else if (step < 3) {
2108 rc = sqlite4_exec(x, d->shortnames ?
2109 "PRAGMA short_column_names = on;" :
2110 "PRAGMA short_column_names = off;",
2111 NULL, NULL);
2112 }
2113 if (rc != SQLITE4_OK) {
2114 return rc;
2115 }
2116 count = 0;
2117 ++step;
2118 }
2119 return SQLITE4_OK;
2120 }
2121
2122 /**
2123 * Free counted array of char pointers.
2124 * @param rowp pointer to char pointer array
2125 *
2126 * The -1-th element of the array holds the array size.
2127 * All non-NULL pointers of the array and then the array
2128 * itself are free'd.
2129 */
2130
2131 static void
freerows(char ** rowp)2132 freerows(char **rowp)
2133 {
2134 PTRDIFF_T size, i;
2135
2136 if (!rowp) {
2137 return;
2138 }
2139 --rowp;
2140 size = (PTRDIFF_T) rowp[0];
2141 for (i = 1; i <= size; i++) {
2142 freep(&rowp[i]);
2143 }
2144 freep(&rowp);
2145 }
2146
2147 /**
2148 * Map SQL field type from string to ODBC integer type code.
2149 * @param typename field type string
2150 * @param nosign pointer to indicator for unsigned field or NULL
2151 * @param ov3 boolean, true for SQL_OV_ODBC3
2152 * @param nowchar boolean, for WINTERFACE don't use WCHAR
2153 * @param dobigint boolean, force SQL_BIGINT on INTEGER columns
2154 * @result SQL data type
2155 */
2156
2157 static int
mapsqltype(const char * typename,int * nosign,int ov3,int nowchar,int dobigint)2158 mapsqltype(const char *typename, int *nosign, int ov3, int nowchar,
2159 int dobigint)
2160 {
2161 char *p, *q;
2162 int testsign = 0, result;
2163
2164 #ifdef WINTERFACE
2165 result = nowchar ? SQL_VARCHAR : SQL_WVARCHAR;
2166 #else
2167 result = SQL_VARCHAR;
2168 #endif
2169 if (!typename) {
2170 return result;
2171 }
2172 q = p = xmalloc(strlen(typename) + 1);
2173 if (!p) {
2174 return result;
2175 }
2176 strcpy(p, typename);
2177 while (*q) {
2178 *q = TOLOWER(*q);
2179 ++q;
2180 }
2181 if (strncmp(p, "inter", 5) == 0) {
2182 } else if (strncmp(p, "int", 3) == 0 ||
2183 strncmp(p, "mediumint", 9) == 0) {
2184 testsign = 1;
2185 result = SQL_INTEGER;
2186 } else if (strncmp(p, "numeric", 7) == 0) {
2187 result = SQL_DOUBLE;
2188 } else if (strncmp(p, "tinyint", 7) == 0) {
2189 testsign = 1;
2190 result = SQL_TINYINT;
2191 } else if (strncmp(p, "smallint", 8) == 0) {
2192 testsign = 1;
2193 result = SQL_SMALLINT;
2194 } else if (strncmp(p, "float", 5) == 0) {
2195 result = SQL_DOUBLE;
2196 } else if (strncmp(p, "double", 6) == 0 ||
2197 strncmp(p, "real", 4) == 0) {
2198 result = SQL_DOUBLE;
2199 } else if (strncmp(p, "timestamp", 9) == 0) {
2200 #ifdef SQL_TYPE_TIMESTAMP
2201 result = ov3 ? SQL_TYPE_TIMESTAMP : SQL_TIMESTAMP;
2202 #else
2203 result = SQL_TIMESTAMP;
2204 #endif
2205 } else if (strncmp(p, "datetime", 8) == 0) {
2206 #ifdef SQL_TYPE_TIMESTAMP
2207 result = ov3 ? SQL_TYPE_TIMESTAMP : SQL_TIMESTAMP;
2208 #else
2209 result = SQL_TIMESTAMP;
2210 #endif
2211 } else if (strncmp(p, "time", 4) == 0) {
2212 #ifdef SQL_TYPE_TIME
2213 result = ov3 ? SQL_TYPE_TIME : SQL_TIME;
2214 #else
2215 result = SQL_TIME;
2216 #endif
2217 } else if (strncmp(p, "date", 4) == 0) {
2218 #ifdef SQL_TYPE_DATE
2219 result = ov3 ? SQL_TYPE_DATE : SQL_DATE;
2220 #else
2221 result = SQL_DATE;
2222 #endif
2223 #ifdef SQL_LONGVARCHAR
2224 } else if (strncmp(p, "text", 4) == 0 ||
2225 strncmp(p, "memo", 4) == 0 ||
2226 strncmp(p, "longvarchar", 11) == 0) {
2227 #ifdef WINTERFACE
2228 result = nowchar ? SQL_LONGVARCHAR : SQL_WLONGVARCHAR;
2229 #else
2230 result = SQL_LONGVARCHAR;
2231 #endif
2232 #ifdef WINTERFACE
2233 } else if (strncmp(p, "wtext", 5) == 0 ||
2234 strncmp(p, "wvarchar", 8) == 0 ||
2235 strncmp(p, "longwvarchar", 12) == 0) {
2236 result = SQL_WLONGVARCHAR;
2237 #endif
2238 #endif
2239 #ifdef SQL_BIT
2240 } else if (strncmp(p, "bool", 4) == 0 ||
2241 strncmp(p, "bit", 3) == 0) {
2242 result = SQL_BIT;
2243 #endif
2244 #ifdef SQL_BIGINT
2245 } else if (strncmp(p, "bigint", 6) == 0) {
2246 testsign = 1;
2247 result = SQL_BIGINT;
2248 #endif
2249 } else if (strncmp(p, "blob", 4) == 0) {
2250 result = SQL_BINARY;
2251 } else if (strncmp(p, "varbinary", 9) == 0) {
2252 result = SQL_VARBINARY;
2253 } else if (strncmp(p, "longvarbinary", 13) == 0) {
2254 result = SQL_LONGVARBINARY;
2255 }
2256 if (nosign) {
2257 if (testsign) {
2258 *nosign = strstr(p, "unsigned") != NULL;
2259 } else {
2260 *nosign = 1;
2261 }
2262 }
2263 #ifdef SQL_BIGINT
2264 if (dobigint && result == SQL_INTEGER) {
2265 result = SQL_BIGINT;
2266 }
2267 #endif
2268 xfree(p);
2269 return result;
2270 }
2271
2272 /**
2273 * Get maximum display size and number of digits after decimal point
2274 * from field type specification.
2275 * @param typename field type specification
2276 * @param sqltype target SQL data type
2277 * @param mp pointer to maximum display size or NULL
2278 * @param dp pointer to number of digits after decimal point or NULL
2279 */
2280
2281 static void
getmd(const char * typename,int sqltype,int * mp,int * dp)2282 getmd(const char *typename, int sqltype, int *mp, int *dp)
2283 {
2284 int m = 0, d = 0;
2285
2286 switch (sqltype) {
2287 case SQL_INTEGER: m = 10; d = 9; break;
2288 case SQL_TINYINT: m = 4; d = 3; break;
2289 case SQL_SMALLINT: m = 6; d = 5; break;
2290 case SQL_FLOAT: m = 25; d = 24; break;
2291 case SQL_DOUBLE: m = 54; d = 53; break;
2292 case SQL_VARCHAR: m = 255; d = 0; break;
2293 #ifdef WINTERFACE
2294 #ifdef SQL_WVARCHAR
2295 case SQL_WVARCHAR: m = 255; d = 0; break;
2296 #endif
2297 #endif
2298 #ifdef SQL_TYPE_DATE
2299 case SQL_TYPE_DATE:
2300 #endif
2301 case SQL_DATE: m = 10; d = 0; break;
2302 #ifdef SQL_TYPE_TIME
2303 case SQL_TYPE_TIME:
2304 #endif
2305 case SQL_TIME: m = 8; d = 0; break;
2306 #ifdef SQL_TYPE_TIMESTAMP
2307 case SQL_TYPE_TIMESTAMP:
2308 #endif
2309 case SQL_TIMESTAMP: m = 32; d = 3; break;
2310 #ifdef SQL_LONGVARCHAR
2311 case SQL_LONGVARCHAR : m = 65536; d = 0; break;
2312 #endif
2313 #ifdef WINTERFACE
2314 #ifdef SQL_WLONGVARCHAR
2315 case SQL_WLONGVARCHAR: m = 65536; d = 0; break;
2316 #endif
2317 #endif
2318 case SQL_BINARY:
2319 case SQL_VARBINARY: m = 255; d = 0; break;
2320 case SQL_LONGVARBINARY: m = 65536; d = 0; break;
2321 #ifdef SQL_BIGINT
2322 case SQL_BIGINT: m = 20; d = 19; break;
2323 #endif
2324 #ifdef SQL_BIT
2325 case SQL_BIT: m = 1; d = 1; break;
2326 #endif
2327 }
2328 if (m && typename) {
2329 int mm, dd;
2330 char clbr[4];
2331
2332 if (sscanf(typename, "%*[^(](%d,%d %1[)]", &mm, &dd, clbr) == 3) {
2333 m = mm;
2334 d = dd;
2335 } else if (sscanf(typename, "%*[^(](%d %1[)]", &mm, clbr) == 2) {
2336 if (sqltype == SQL_TIMESTAMP) {
2337 d = mm;
2338 }
2339 #ifdef SQL_TYPE_TIMESTAMP
2340 else if (sqltype == SQL_TYPE_TIMESTAMP) {
2341 d = mm;
2342 }
2343 #endif
2344 else {
2345 m = d = mm;
2346 }
2347 }
2348 }
2349 if (mp) {
2350 *mp = m;
2351 }
2352 if (dp) {
2353 *dp = d;
2354 }
2355 }
2356
2357 /**
2358 * Map SQL_C_DEFAULT to proper C type.
2359 * @param type input C type
2360 * @param stype input SQL type
2361 * @param nosign 0=signed, 0>unsigned, 0<undefined
2362 * @param nowchar when compiled with WINTERFACE don't use WCHAR
2363 * @result C type
2364 */
2365
2366 static int
mapdeftype(int type,int stype,int nosign,int nowchar)2367 mapdeftype(int type, int stype, int nosign, int nowchar)
2368 {
2369 if (type == SQL_C_DEFAULT) {
2370 switch (stype) {
2371 case SQL_INTEGER:
2372 type = (nosign > 0) ? SQL_C_ULONG : SQL_C_LONG;
2373 break;
2374 case SQL_TINYINT:
2375 type = (nosign > 0) ? SQL_C_UTINYINT : SQL_C_TINYINT;
2376 break;
2377 case SQL_SMALLINT:
2378 type = (nosign > 0) ? SQL_C_USHORT : SQL_C_SHORT;
2379 break;
2380 case SQL_FLOAT:
2381 type = SQL_C_FLOAT;
2382 break;
2383 case SQL_DOUBLE:
2384 type = SQL_C_DOUBLE;
2385 break;
2386 case SQL_TIMESTAMP:
2387 type = SQL_C_TIMESTAMP;
2388 break;
2389 case SQL_TIME:
2390 type = SQL_C_TIME;
2391 break;
2392 case SQL_DATE:
2393 type = SQL_C_DATE;
2394 break;
2395 #ifdef SQL_C_TYPE_TIMESTAMP
2396 case SQL_TYPE_TIMESTAMP:
2397 type = SQL_C_TYPE_TIMESTAMP;
2398 break;
2399 #endif
2400 #ifdef SQL_C_TYPE_TIME
2401 case SQL_TYPE_TIME:
2402 type = SQL_C_TYPE_TIME;
2403 break;
2404 #endif
2405 #ifdef SQL_C_TYPE_DATE
2406 case SQL_TYPE_DATE:
2407 type = SQL_C_TYPE_DATE;
2408 break;
2409 #endif
2410 #ifdef WINTERFACE
2411 case SQL_WVARCHAR:
2412 case SQL_WCHAR:
2413 #ifdef SQL_WLONGVARCHAR
2414 case SQL_WLONGVARCHAR:
2415 #endif
2416 type = nowchar ? SQL_C_CHAR : SQL_C_WCHAR;
2417 break;
2418 #endif
2419 case SQL_BINARY:
2420 case SQL_VARBINARY:
2421 case SQL_LONGVARBINARY:
2422 type = SQL_C_BINARY;
2423 break;
2424 #ifdef SQL_BIT
2425 case SQL_BIT:
2426 type = SQL_C_BIT;
2427 break;
2428 #endif
2429 #ifdef SQL_BIGINT
2430 case SQL_BIGINT:
2431 type = SQL_C_CHAR;
2432 break;
2433 #endif
2434 default:
2435 #ifdef WINTERFACE
2436 type = nowchar ? SQL_C_CHAR : SQL_C_WCHAR;
2437 #else
2438 type = SQL_C_CHAR;
2439 #endif
2440 break;
2441 }
2442 }
2443 return type;
2444 }
2445
2446 /**
2447 * Check if query is a DDL statement.
2448 * @param sql query string
2449 * @result true or false
2450 */
2451
2452 static int
checkddl(char * sql)2453 checkddl(char *sql)
2454 {
2455 int isddl = 0;
2456
2457 while (*sql && ISSPACE(*sql)) {
2458 ++sql;
2459 }
2460 if (*sql && *sql != ';') {
2461 int i, size;
2462 static const struct {
2463 int len;
2464 const char *str;
2465 } ddlstr[] = {
2466 { 5, "alter" },
2467 { 7, "analyze" },
2468 { 6, "attach" },
2469 { 5, "begin" },
2470 { 6, "commit" },
2471 { 6, "create" },
2472 { 6, "detach" },
2473 { 4, "drop" },
2474 { 3, "end" },
2475 { 7, "reindex" },
2476 { 7, "release" },
2477 { 8, "rollback" },
2478 { 9, "savepoint" },
2479 { 6, "vacuum" }
2480 };
2481
2482 size = strlen(sql);
2483 for (i = 0; i < array_size(ddlstr); i++) {
2484 if (size >= ddlstr[i].len &&
2485 strncasecmp(sql, ddlstr[i].str, ddlstr[i].len) == 0) {
2486 isddl = 1;
2487 break;
2488 }
2489 }
2490 }
2491 return isddl;
2492 }
2493
2494 /**
2495 * Fixup query string with optional parameter markers.
2496 * @param sql original query string
2497 * @param sqlLen length of query string or SQL_NTS
2498 * @param nparam output number of parameters
2499 * @param isselect output indicator for SELECT (1) or DDL statement (2)
2500 * @param errmsg output error message
2501 * @result newly allocated string containing query string for SQLite or NULL
2502 */
2503
2504 static char *
fixupsql(char * sql,int sqlLen,int * nparam,int * isselect,char ** errmsg)2505 fixupsql(char *sql, int sqlLen, int *nparam, int *isselect, char **errmsg)
2506 {
2507 char *q = sql, *qz = NULL, *p, *inq = NULL, *out;
2508 int np = 0, isddl = -1, size;
2509
2510 if (errmsg) {
2511 *errmsg = NULL;
2512 }
2513 if (sqlLen != SQL_NTS) {
2514 qz = q = xmalloc(sqlLen + 1);
2515 if (!qz) {
2516 return NULL;
2517 }
2518 memcpy(q, sql, sqlLen);
2519 q[sqlLen] = '\0';
2520 size = sqlLen * 4;
2521 } else {
2522 size = strlen(sql) * 4;
2523 }
2524 size += sizeof (char *) - 1;
2525 size &= ~(sizeof (char *) - 1);
2526 p = xmalloc(size);
2527 if (!p) {
2528 errout:
2529 freep(&qz);
2530 return NULL;
2531 }
2532 memset(p, 0, size);
2533 out = p;
2534 while (*q) {
2535 switch (*q) {
2536 case '\'':
2537 case '\"':
2538 if (q == inq) {
2539 inq = NULL;
2540 } else if (!inq) {
2541 inq = q + 1;
2542
2543 while (*inq) {
2544 if (*inq == *q) {
2545 if (inq[1] == *q) {
2546 inq++;
2547 } else {
2548 break;
2549 }
2550 }
2551 inq++;
2552 }
2553 }
2554 *p++ = *q;
2555 break;
2556 case '?':
2557 *p++ = *q;
2558 if (!inq) {
2559 np++;
2560 }
2561 break;
2562 case ';':
2563 if (!inq) {
2564 if (isddl < 0) {
2565 isddl = checkddl(out);
2566 }
2567 if (isddl == 0) {
2568 char *qq = q;
2569
2570 do {
2571 ++qq;
2572 } while (*qq && ISSPACE(*qq));
2573 if (*qq && *qq != ';') {
2574 freep(&out);
2575 if (errmsg) {
2576 *errmsg = "only one SQL statement allowed";
2577 }
2578 goto errout;
2579 }
2580 }
2581 }
2582 *p++ = *q;
2583 break;
2584 case '{':
2585 /*
2586 * Deal with escape sequences:
2587 * {d 'YYYY-MM-DD'}, {t ...}, {ts ...}
2588 * {oj ...}, {fn ...} etc.
2589 */
2590 if (!inq) {
2591 int ojfn = 0, brc = 0;
2592 char *inq2 = NULL, *end = q + 1, *start;
2593
2594 while (*end && ISSPACE(*end)) {
2595 ++end;
2596 }
2597 if (*end != 'd' && *end != 'D' &&
2598 *end != 't' && *end != 'T') {
2599 ojfn = 1;
2600 }
2601 start = end;
2602 while (*end) {
2603 if (inq2 && *end == *inq2) {
2604 inq2 = NULL;
2605 } else if (inq2 == NULL && *end == '{') {
2606 char *nerr = 0, *nsql;
2607
2608 nsql = fixupsql(end, SQL_NTS, 0, 0, &nerr);
2609 if (nsql && !nerr) {
2610 strcpy(end, nsql);
2611 } else {
2612 brc++;
2613 }
2614 freep(&nsql);
2615 } else if (inq2 == NULL && *end == '}') {
2616 if (brc-- <= 0) {
2617 break;
2618 }
2619 } else if (inq2 == NULL && (*end == '\'' || *end == '"')) {
2620 inq2 = end;
2621 } else if (inq2 == NULL && *end == '?') {
2622 np++;
2623 }
2624 ++end;
2625 }
2626 if (*end == '}') {
2627 char *end2 = end - 1;
2628
2629 if (ojfn) {
2630 while (start < end) {
2631 if (ISSPACE(*start)) {
2632 break;
2633 }
2634 ++start;
2635 }
2636 while (start < end) {
2637 *p++ = *start;
2638 ++start;
2639 }
2640 q = end;
2641 break;
2642 } else {
2643 while (start < end2 && *start != '\'') {
2644 ++start;
2645 }
2646 while (end2 > start && *end2 != '\'') {
2647 --end2;
2648 }
2649 if (*start == '\'' && *end2 == '\'') {
2650 while (start <= end2) {
2651 *p++ = *start;
2652 ++start;
2653 }
2654 q = end;
2655 break;
2656 }
2657 }
2658 }
2659 }
2660 /* FALL THROUGH */
2661 default:
2662 *p++ = *q;
2663 }
2664 ++q;
2665 }
2666 freep(&qz);
2667 *p = '\0';
2668 if (nparam) {
2669 *nparam = np;
2670 }
2671 if (isselect) {
2672 if (isddl < 0) {
2673 isddl = checkddl(out);
2674 }
2675 if (isddl > 0) {
2676 *isselect = 2;
2677 } else {
2678 int incom = 0;
2679
2680 p = out;
2681 while (*p) {
2682 switch (*p) {
2683 case '-':
2684 if (!incom && p[1] == '-') {
2685 incom = -1;
2686 }
2687 break;
2688 case '\n':
2689 if (incom < 0) {
2690 incom = 0;
2691 }
2692 break;
2693 case '/':
2694 if (incom > 0 && p[-1] == '*') {
2695 incom = 0;
2696 p++;
2697 continue;
2698 } else if (!incom && p[1] == '*') {
2699 incom = 1;
2700 }
2701 break;
2702 }
2703 if (!incom && !ISSPACE(*p)) {
2704 break;
2705 }
2706 p++;
2707 }
2708 size = strlen(p);
2709 if (size >= 6 &&
2710 (strncasecmp(p, "select", 6) == 0 ||
2711 strncasecmp(p, "pragma", 6) == 0)) {
2712 *isselect = 1;
2713 } else if (size >= 7 &&
2714 strncasecmp(p, "explain", 7) == 0) {
2715 *isselect = 1;
2716 } else {
2717 *isselect = 0;
2718 }
2719 }
2720 }
2721 return out;
2722 }
2723
2724 /**
2725 * Find column given name in string array.
2726 * @param cols string array
2727 * @param ncols number of strings
2728 * @param name column name
2729 * @result >= 0 on success, -1 on error
2730 */
2731
2732 static int
findcol(char ** cols,int ncols,char * name)2733 findcol(char **cols, int ncols, char *name)
2734 {
2735 int i;
2736
2737 if (cols) {
2738 for (i = 0; i < ncols; i++) {
2739 if (strcmp(cols[i], name) == 0) {
2740 return i;
2741 }
2742 }
2743 }
2744 return -1;
2745 }
2746
2747 /**
2748 * Fixup column information for a running statement.
2749 * @param s statement to get fresh column information
2750 * @param d DBC pointer
2751 *
2752 * The column labels get the table names stripped
2753 * when there's more than one column and all table
2754 * names are identical.
2755 *
2756 * The "dyncols" field of STMT is filled with column
2757 * information obtained by SQLite "PRAGMA table_info"
2758 * for each column whose table name is known. If the
2759 * types are already present as with SQLite 2.5.7
2760 * this information is used instead.
2761 */
2762
2763 static void
fixupdyncols(STMT * s,DBC * d)2764 fixupdyncols(STMT *s, DBC *d)
2765 {
2766 int i, k;
2767
2768 if (!s->dyncols) {
2769 return;
2770 }
2771 /* fixup labels */
2772 if (!s->longnames) {
2773 if (s->dcols > 1) {
2774 char *table = s->dyncols[0].table;
2775
2776 for (i = 1; table[0] && i < s->dcols; i++) {
2777 if (strcmp(s->dyncols[i].table, table)) {
2778 break;
2779 }
2780 }
2781 if (i >= s->dcols) {
2782 for (i = 0; i < s->dcols; i++) {
2783 s->dyncols[i].label = s->dyncols[i].column;
2784 }
2785 }
2786 } else if (s->dcols == 1) {
2787 s->dyncols[0].label = s->dyncols[0].column;
2788 }
2789 }
2790 for (i = 0; i < s->dcols; i++) {
2791 s->dyncols[i].type =
2792 mapsqltype(s->dyncols[i].typename, &s->dyncols[i].nosign, *s->ov3,
2793 s->nowchar[0] || s->nowchar[1], s->dobigint);
2794 getmd(s->dyncols[i].typename, s->dyncols[i].type,
2795 &s->dyncols[i].size, &s->dyncols[i].prec);
2796 #ifdef SQL_LONGVARCHAR
2797 if (s->dyncols[i].type == SQL_VARCHAR &&
2798 s->dyncols[i].size > 255) {
2799 s->dyncols[i].type = SQL_LONGVARCHAR;
2800 }
2801 #endif
2802 #ifdef WINTERFACE
2803 #ifdef SQL_WLONGVARCHAR
2804 if (s->dyncols[i].type == SQL_WVARCHAR &&
2805 s->dyncols[i].size > 255) {
2806 s->dyncols[i].type = SQL_WLONGVARCHAR;
2807 }
2808 #endif
2809 #endif
2810 if (s->dyncols[i].type == SQL_VARBINARY &&
2811 s->dyncols[i].size > 255) {
2812 s->dyncols[i].type = SQL_LONGVARBINARY;
2813 }
2814 }
2815 for (i = 1, k = 0; i < s->dcols; i++) {
2816 if (strcmp(s->dyncols[i].table, s->dyncols[0].table) == 0) {
2817 k++;
2818 }
2819 }
2820 s->one_tbl = (k && k + 1 == s->dcols) ? 1 : 0;
2821 k = 0;
2822 if (s->one_tbl) {
2823 for (i = 0; i < s->dcols; i++) {
2824 if (s->dyncols[i].ispk > 0) {
2825 ++k;
2826 if (s->has_rowid < 0 && s->dyncols[i].isrowid > 0) {
2827 s->has_rowid = i;
2828 }
2829 }
2830 }
2831 }
2832 s->has_pk = k;
2833 }
2834
2835 /**
2836 * Return number of month days.
2837 * @param year
2838 * @param month 1..12
2839 * @result number of month days or 0
2840 */
2841
2842 static int
getmdays(int year,int month)2843 getmdays(int year, int month)
2844 {
2845 static const int mdays[] = {
2846 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31
2847 };
2848 int mday;
2849
2850 if (month < 1) {
2851 return 0;
2852 }
2853 mday = mdays[(month - 1) % 12];
2854 if (mday == 28 && year % 4 == 0 &&
2855 (!(year % 100 == 0) || year % 400 == 0)) {
2856 mday++;
2857 }
2858 return mday;
2859 }
2860
2861 /**
2862 * Convert string to ODBC DATE_STRUCT.
2863 * @param str string to be converted
2864 * @param ds output DATE_STRUCT
2865 * @result 0 on success, -1 on error
2866 *
2867 * Strings of the format 'YYYYMMDD' or 'YYYY-MM-DD' or
2868 * 'YYYY/MM/DD' or 'MM/DD/YYYY' are converted to a
2869 * DATE_STRUCT.
2870 */
2871
2872 static int
str2date(char * str,DATE_STRUCT * ds)2873 str2date(char *str, DATE_STRUCT *ds)
2874 {
2875 int i, err = 0;
2876 char *p, *q, sepc = '\0';
2877
2878 ds->year = ds->month = ds->day = 0;
2879 p = str;
2880 while (*p && !ISDIGIT(*p)) {
2881 ++p;
2882 }
2883 q = p;
2884 i = 0;
2885 while (*q && !ISDIGIT(*q)) {
2886 ++i;
2887 ++q;
2888 }
2889 if (i >= 8) {
2890 char buf[8];
2891
2892 strncpy(buf, p + 0, 4); buf[4] = '\0';
2893 ds->year = strtol(buf, NULL, 10);
2894 strncpy(buf, p + 4, 2); buf[2] = '\0';
2895 ds->month = strtol(buf, NULL, 10);
2896 strncpy(buf, p + 6, 2); buf[2] = '\0';
2897 ds->day = strtol(buf, NULL, 10);
2898 goto done;
2899 }
2900 i = 0;
2901 while (i < 3) {
2902 int n;
2903
2904 q = NULL;
2905 n = strtol(p, &q, 10);
2906 if (!q || q == p) {
2907 if (*q == '\0') {
2908 if (i == 0) {
2909 err = 1;
2910 }
2911 goto done;
2912 }
2913 }
2914 if (!sepc) {
2915 sepc = *q;
2916 }
2917 if (*q == '-' || *q == '/' || *q == '\0' || i == 2) {
2918 switch (i) {
2919 case 0: ds->year = n; break;
2920 case 1: ds->month = n; break;
2921 case 2: ds->day = n; break;
2922 }
2923 ++i;
2924 if (*q) {
2925 ++q;
2926 }
2927 } else {
2928 i = 0;
2929 while (*q && !ISDIGIT(*q)) {
2930 ++q;
2931 }
2932 }
2933 p = q;
2934 }
2935 done:
2936 /* final check for overflow */
2937 if (err ||
2938 ds->month < 1 || ds->month > 12 ||
2939 ds->day < 1 || ds->day > getmdays(ds->year, ds->month)) {
2940 if (sepc == '/') {
2941 /* Try MM/DD/YYYY format */
2942 int t[3];
2943
2944 t[0] = ds->year;
2945 t[1] = ds->month;
2946 t[2] = ds->day;
2947 ds->year = t[2];
2948 ds->day = t[1];
2949 ds->month = t[0];
2950 if (ds->month >= 1 && ds->month <= 12 &&
2951 (ds->day >= 1 || ds->day <= getmdays(ds->year, ds->month))) {
2952 return 0;
2953 }
2954 }
2955 return -1;
2956 }
2957 return 0;
2958 }
2959
2960 /**
2961 * Convert string to ODBC TIME_STRUCT.
2962 * @param str string to be converted
2963 * @param ts output TIME_STRUCT
2964 * @result 0 on success, -1 on error
2965 *
2966 * Strings of the format 'HHMMSS' or 'HH:MM:SS'
2967 * are converted to a TIME_STRUCT.
2968 */
2969
2970 static int
str2time(char * str,TIME_STRUCT * ts)2971 str2time(char *str, TIME_STRUCT *ts)
2972 {
2973 int i, err = 0, ampm = -1;
2974 char *p, *q;
2975
2976 ts->hour = ts->minute = ts->second = 0;
2977 p = str;
2978 while (*p && !ISDIGIT(*p)) {
2979 ++p;
2980 }
2981 q = p;
2982 i = 0;
2983 while (*q && ISDIGIT(*q)) {
2984 ++i;
2985 ++q;
2986 }
2987 if (i >= 6) {
2988 char buf[4];
2989
2990 strncpy(buf, p + 0, 2); buf[2] = '\0';
2991 ts->hour = strtol(buf, NULL, 10);
2992 strncpy(buf, p + 2, 2); buf[2] = '\0';
2993 ts->minute = strtol(buf, NULL, 10);
2994 strncpy(buf, p + 4, 2); buf[2] = '\0';
2995 ts->second = strtol(buf, NULL, 10);
2996 goto done;
2997 }
2998 i = 0;
2999 while (i < 3) {
3000 int n;
3001
3002 q = NULL;
3003 n = strtol(p, &q, 10);
3004 if (!q || q == p) {
3005 if (*q == '\0') {
3006 if (i == 0) {
3007 err = 1;
3008 }
3009 goto done;
3010 }
3011 }
3012 if (*q == ':' || *q == '\0' || i == 2) {
3013 switch (i) {
3014 case 0: ts->hour = n; break;
3015 case 1: ts->minute = n; break;
3016 case 2: ts->second = n; break;
3017 }
3018 ++i;
3019 if (*q) {
3020 ++q;
3021 }
3022 } else {
3023 i = 0;
3024 while (*q && !ISDIGIT(*q)) {
3025 ++q;
3026 }
3027 }
3028 p = q;
3029 }
3030 if (!err) {
3031 while (*p) {
3032 if ((p[0] == 'p' || p[0] == 'P') &&
3033 (p[1] == 'm' || p[1] == 'M')) {
3034 ampm = 1;
3035 } else if ((p[0] == 'a' || p[0] == 'A') &&
3036 (p[1] == 'm' || p[1] == 'M')) {
3037 ampm = 0;
3038 }
3039 ++p;
3040 }
3041 if (ampm > 0) {
3042 if (ts->hour < 12) {
3043 ts->hour += 12;
3044 }
3045 } else if (ampm == 0) {
3046 if (ts->hour == 12) {
3047 ts->hour = 0;
3048 }
3049 }
3050 }
3051 done:
3052 /* final check for overflow */
3053 if (err || ts->hour > 23 || ts->minute > 59 || ts->second > 59) {
3054 return -1;
3055 }
3056 return 0;
3057 }
3058
3059 /**
3060 * Convert string to ODBC TIMESTAMP_STRUCT.
3061 * @param str string to be converted
3062 * @param tss output TIMESTAMP_STRUCT
3063 * @result 0 on success, -1 on error
3064 *
3065 * Strings of the format 'YYYYMMDDhhmmssff' or 'YYYY-MM-DD hh:mm:ss ff'
3066 * or 'YYYY/MM/DD hh:mm:ss ff' or 'hh:mm:ss ff YYYY-MM-DD' are
3067 * converted to a TIMESTAMP_STRUCT. The ISO8601 formats
3068 * YYYY-MM-DDThh:mm:ss[.f]Z
3069 * YYYY-MM-DDThh:mm:ss[.f]shh:mm
3070 * are also supported. In case a time zone field is present,
3071 * the resulting TIMESTAMP_STRUCT is expressed in UTC.
3072 */
3073
3074 static int
str2timestamp(char * str,TIMESTAMP_STRUCT * tss)3075 str2timestamp(char *str, TIMESTAMP_STRUCT *tss)
3076 {
3077 int i, m, n, err = 0, ampm = -1;
3078 char *p, *q, in = '\0', sepc = '\0';
3079
3080 tss->year = tss->month = tss->day = 0;
3081 tss->hour = tss->minute = tss->second = 0;
3082 tss->fraction = 0;
3083 p = str;
3084 while (*p && !ISDIGIT(*p)) {
3085 ++p;
3086 }
3087 q = p;
3088 i = 0;
3089 while (*q && ISDIGIT(*q)) {
3090 ++i;
3091 ++q;
3092 }
3093 if (i >= 14) {
3094 char buf[16];
3095
3096 strncpy(buf, p + 0, 4); buf[4] = '\0';
3097 tss->year = strtol(buf, NULL, 10);
3098 strncpy(buf, p + 4, 2); buf[2] = '\0';
3099 tss->month = strtol(buf, NULL, 10);
3100 strncpy(buf, p + 6, 2); buf[2] = '\0';
3101 tss->day = strtol(buf, NULL, 10);
3102 strncpy(buf, p + 8, 2); buf[2] = '\0';
3103 tss->hour = strtol(buf, NULL, 10);
3104 strncpy(buf, p + 10, 2); buf[2] = '\0';
3105 tss->minute = strtol(buf, NULL, 10);
3106 strncpy(buf, p + 12, 2); buf[2] = '\0';
3107 tss->second = strtol(buf, NULL, 10);
3108 if (i > 14) {
3109 m = i - 14;
3110 strncpy(buf, p + 14, m);
3111 while (m < 9) {
3112 buf[m] = '0';
3113 ++m;
3114 }
3115 buf[m] = '\0';
3116 tss->fraction = strtol(buf, NULL, 10);
3117 }
3118 m = 7;
3119 goto done;
3120 }
3121 m = i = 0;
3122 while ((m & 7) != 7) {
3123 q = NULL;
3124 n = strtol(p, &q, 10);
3125 if (!q || q == p) {
3126 if (*q == '\0') {
3127 if (m < 1) {
3128 err = 1;
3129 }
3130 goto done;
3131 }
3132 }
3133 if (in == '\0') {
3134 switch (*q) {
3135 case '-':
3136 case '/':
3137 if ((m & 1) == 0) {
3138 in = *q;
3139 i = 0;
3140 }
3141 break;
3142 case ':':
3143 if ((m & 2) == 0) {
3144 in = *q;
3145 i = 0;
3146 }
3147 break;
3148 case ' ':
3149 case '.':
3150 break;
3151 default:
3152 in = '\0';
3153 i = 0;
3154 break;
3155 }
3156 }
3157 switch (in) {
3158 case '-':
3159 case '/':
3160 if (!sepc) {
3161 sepc = in;
3162 }
3163 switch (i) {
3164 case 0: tss->year = n; break;
3165 case 1: tss->month = n; break;
3166 case 2: tss->day = n; break;
3167 }
3168 if (++i >= 3) {
3169 i = 0;
3170 m |= 1;
3171 if (!(m & 2)) {
3172 m |= 8;
3173 }
3174 goto skip;
3175 } else {
3176 ++q;
3177 }
3178 break;
3179 case ':':
3180 switch (i) {
3181 case 0: tss->hour = n; break;
3182 case 1: tss->minute = n; break;
3183 case 2: tss->second = n; break;
3184 }
3185 if (++i >= 3) {
3186 i = 0;
3187 m |= 2;
3188 if (*q == '.') {
3189 in = '.';
3190 goto skip2;
3191 }
3192 if (*q == ' ') {
3193 if ((m & 1) == 0) {
3194 char *e = NULL;
3195
3196 (void) strtol(q + 1, &e, 10);
3197 if (e && *e == '-') {
3198 goto skip;
3199 }
3200 }
3201 in = '.';
3202 goto skip2;
3203 }
3204 goto skip;
3205 } else {
3206 ++q;
3207 }
3208 break;
3209 case '.':
3210 if (++i >= 1) {
3211 int ndig = q - p;
3212
3213 if (p[0] == '+' || p[0] == '-') {
3214 ndig--;
3215 }
3216 while (ndig < 9) {
3217 n = n * 10;
3218 ++ndig;
3219 }
3220 tss->fraction = n;
3221 m |= 4;
3222 i = 0;
3223 }
3224 default:
3225 skip:
3226 in = '\0';
3227 skip2:
3228 while (*q && !ISDIGIT(*q)) {
3229 if ((q[0] == 'a' || q[0] == 'A') &&
3230 (q[1] == 'm' || q[1] == 'M')) {
3231 ampm = 0;
3232 ++q;
3233 } else if ((q[0] == 'p' || q[0] == 'P') &&
3234 (q[1] == 'm' || q[1] == 'M')) {
3235 ampm = 1;
3236 ++q;
3237 }
3238 ++q;
3239 }
3240 }
3241 p = q;
3242 }
3243 if ((m & 7) > 1 && (m & 8)) {
3244 /* ISO8601 timezone */
3245 if (p > str && ISDIGIT(*p)) {
3246 int nn, sign;
3247
3248 q = p - 1;
3249 if (*q != '+' && *q != '-') {
3250 goto done;
3251 }
3252 sign = (*q == '+') ? -1 : 1;
3253 q = NULL;
3254 n = strtol(p, &q, 10);
3255 if (!q || *q++ != ':' || !ISDIGIT(*q)) {
3256 goto done;
3257 }
3258 p = q;
3259 q = NULL;
3260 nn = strtol(p, &q, 10);
3261 tss->minute += nn * sign;
3262 if ((SQLSMALLINT) tss->minute < 0) {
3263 tss->hour -= 1;
3264 tss->minute += 60;
3265 } else if (tss->minute >= 60) {
3266 tss->hour += 1;
3267 tss->minute -= 60;
3268 }
3269 tss->hour += n * sign;
3270 if ((SQLSMALLINT) tss->hour < 0) {
3271 tss->day -= 1;
3272 tss->hour += 24;
3273 } else if (tss->hour >= 24) {
3274 tss->day += 1;
3275 tss->hour -= 24;
3276 }
3277 if ((short) tss->day < 1 || tss->day >= 28) {
3278 int mday, pday, pmon;
3279
3280 mday = getmdays(tss->year, tss->month);
3281 pmon = tss->month - 1;
3282 if (pmon < 1) {
3283 pmon = 12;
3284 }
3285 pday = getmdays(tss->year, pmon);
3286 if ((SQLSMALLINT) tss->day < 1) {
3287 tss->month -= 1;
3288 tss->day = pday;
3289 } else if (tss->day > mday) {
3290 tss->month += 1;
3291 tss->day = 1;
3292 }
3293 if ((SQLSMALLINT) tss->month < 1) {
3294 tss->year -= 1;
3295 tss->month = 12;
3296 } else if (tss->month > 12) {
3297 tss->year += 1;
3298 tss->month = 1;
3299 }
3300 }
3301 }
3302 }
3303 done:
3304 if ((m & 1) &&
3305 (tss->month < 1 || tss->month > 12 ||
3306 tss->day < 1 || tss->day > getmdays(tss->year, tss->month))) {
3307 if (sepc == '/') {
3308 /* Try MM/DD/YYYY format */
3309 int t[3];
3310
3311 t[0] = tss->year;
3312 t[1] = tss->month;
3313 t[2] = tss->day;
3314 tss->year = t[2];
3315 tss->day = t[1];
3316 tss->month = t[0];
3317 }
3318 }
3319 /* Replace missing year/month/day with current date */
3320 if (!err && (m & 1) == 0) {
3321 #ifdef _WIN32
3322 SYSTEMTIME t;
3323
3324 GetLocalTime(&t);
3325 tss->year = t.wYear;
3326 tss->month = t.wMonth;
3327 tss->day = t.wDay;
3328 #else
3329 struct timeval tv;
3330 struct tm tm;
3331
3332 gettimeofday(&tv, NULL);
3333 tm = *localtime(&tv.tv_sec);
3334 tss->year = tm.tm_year + 1900;
3335 tss->month = tm.tm_mon + 1;
3336 tss->day = tm.tm_mday;
3337 #endif
3338 }
3339 /* Normalize fraction */
3340 if (tss->fraction < 0) {
3341 tss->fraction = 0;
3342 }
3343 /* Final check for overflow */
3344 if (err ||
3345 tss->month < 1 || tss->month > 12 ||
3346 tss->day < 1 || tss->day > getmdays(tss->year, tss->month) ||
3347 tss->hour > 23 || tss->minute > 59 || tss->second > 59) {
3348 return -1;
3349 }
3350 if ((m & 7) > 1) {
3351 if (ampm > 0) {
3352 if (tss->hour < 12) {
3353 tss->hour += 12;
3354 }
3355 } else if (ampm == 0) {
3356 if (tss->hour == 12) {
3357 tss->hour = 0;
3358 }
3359 }
3360 }
3361 return ((m & 7) < 1) ? -1 : 0;
3362 }
3363
3364 /**
3365 * Get boolean flag from string.
3366 * @param string string to be inspected
3367 * @result true or false
3368 */
3369
3370 static int
getbool(char * string)3371 getbool(char *string)
3372 {
3373 if (string) {
3374 return string[0] && strchr("Yy123456789Tt", string[0]) != NULL;
3375 }
3376 return 0;
3377 }
3378
3379 /**
3380 * Internal function to release memory of blob
3381 * @param dummy unused
3382 * @param p pointer to memory
3383 */
3384
3385 static void
blob_free(void * dummy,void * p)3386 blob_free(void *dummy, void *p)
3387 {
3388 sqlite4_free(0, p);
3389 }
3390
3391 /**
3392 * SQLite function to import a BLOB from a file
3393 * @param ctx function context
3394 * @param nargs number arguments
3395 * @param args arguments
3396 */
3397
3398 static void
blob_import(sqlite4_context * ctx,int nargs,sqlite4_value ** args)3399 blob_import(sqlite4_context *ctx, int nargs, sqlite4_value **args)
3400 {
3401 #if 0
3402 DBC *d = (DBC *) sqlite4_user_data(ctx);
3403 #endif
3404 char *filename = 0;
3405
3406 if (nargs > 0) {
3407 if (sqlite4_value_type(args[0]) != SQLITE4_NULL) {
3408 int nbytes;
3409
3410 filename = (char *) sqlite4_value_text(args[0], &nbytes);
3411 }
3412 }
3413 if (filename) {
3414 #ifdef _WIN32
3415 char *wname = utf_to_wmb(filename, -1);
3416 FILE *f;
3417 #else
3418 FILE *f = fopen(filename, "r");
3419 #endif
3420 char *p;
3421 long n, nn;
3422
3423 #ifdef _WIN32
3424 if (wname) {
3425 f = fopen(wname, "rb");
3426 } else {
3427 sqlite4_result_error(ctx, "out of memory", -1);
3428 return;
3429 }
3430 uc_free(wname);
3431 #endif
3432 if (f) {
3433 if (fseek(f, 0, SEEK_END) == 0) {
3434 n = ftell(f);
3435 if (fseek(f, 0, SEEK_SET) == 0) {
3436 p = sqlite4_malloc(0, n);
3437 if (p) {
3438 nn = fread(p, 1, n, f);
3439 if (nn != n) {
3440 sqlite4_result_error(ctx, "read error", -1);
3441 sqlite4_free(0, p);
3442 } else {
3443 sqlite4_result_blob(ctx, p, n, blob_free, 0);
3444 }
3445 } else {
3446 sqlite4_result_error(ctx, "out of memory", -1);
3447 }
3448 } else {
3449 sqlite4_result_error(ctx, "seek error", -1);
3450 }
3451 } else {
3452 sqlite4_result_error(ctx, "seek error", -1);
3453 }
3454 fclose(f);
3455 } else {
3456 sqlite4_result_error(ctx, "cannot open file", -1);
3457 }
3458 } else {
3459 sqlite4_result_error(ctx, "no filename given", -1);
3460 }
3461 }
3462
3463 /**
3464 * SQLite function to export a BLOB to a file
3465 * @param ctx function context
3466 * @param nargs number arguments
3467 * @param args arguments
3468 */
3469
3470 static void
blob_export(sqlite4_context * ctx,int nargs,sqlite4_value ** args)3471 blob_export(sqlite4_context *ctx, int nargs, sqlite4_value **args)
3472 {
3473 #if 0
3474 DBC *d = (DBC *) sqlite4_user_data(ctx);
3475 #endif
3476 char *filename = 0;
3477 char *p = 0;
3478 int n = 0;
3479
3480 if (nargs > 0) {
3481 p = (char *) sqlite4_value_blob(args[0], &n);
3482 }
3483 if (nargs > 1) {
3484 if (sqlite4_value_type(args[1]) != SQLITE4_NULL) {
3485 int nbytes;
3486
3487 filename = (char *) sqlite4_value_text(args[1], &nbytes);
3488 }
3489 }
3490 if (p) {
3491 if (filename) {
3492 #ifdef _WIN32
3493 char *wname = utf_to_wmb(filename, -1);
3494 FILE *f;
3495 #else
3496 FILE *f = fopen(filename, "w");
3497 #endif
3498 int nn;
3499
3500 #ifdef _WIN32
3501 if (wname) {
3502 f = fopen(wname, "wb");
3503 } else {
3504 sqlite4_result_error(ctx, "out of memory", -1);
3505 return;
3506 }
3507 uc_free(wname);
3508 #endif
3509 if (f) {
3510 nn = fwrite(p, 1, n, f);
3511 fclose(f);
3512 if (nn != n) {
3513 sqlite4_result_error(ctx, "write error", -1);
3514 } else {
3515 sqlite4_result_int(ctx, nn);
3516 }
3517 } else {
3518 sqlite4_result_error(ctx, "cannot open file", -1);
3519 }
3520 } else {
3521 sqlite4_result_error(ctx, "no filename given", -1);
3522 }
3523 } else {
3524 sqlite4_result_null(ctx);
3525 }
3526 }
3527
3528 /**
3529 * SQLite trace or profile callback
3530 * @param arg DBC pointer
3531 * @param msg log message, SQL text
3532 * @param et elapsed time
3533 */
3534
3535 static void
dbtrace(void * arg,const char * msg,sqlite4_uint64 et)3536 dbtrace(void *arg, const char *msg, sqlite4_uint64 et)
3537 {
3538 DBC *d = (DBC *) arg;
3539
3540 if (msg && d->trace) {
3541 int len = strlen(msg);
3542 unsigned long s, f;
3543
3544 if (len > 0) {
3545 char *end = "\n";
3546
3547 if (msg[len - 1] != ';') {
3548 end = ";\n";
3549 }
3550 fprintf(d->trace, "%s%s", msg, end);
3551 s = et / 1000000000LL;
3552 f = et % 1000000000LL;
3553 fprintf(d->trace, "-- took %lu.%09lu seconds\n", s, f);
3554 fflush(d->trace);
3555 }
3556 }
3557 }
3558
3559 /**
3560 * Trace function for SQLite API calls
3561 * @param d pointer to database connection handle
3562 * @param fn SQLite function name
3563 * @param sql SQL string
3564 */
3565
3566 static void
dbtraceapi(DBC * d,char * fn,const char * sql)3567 dbtraceapi(DBC *d, char *fn, const char *sql)
3568 {
3569 if (fn && d->trace) {
3570 if (sql) {
3571 fprintf(d->trace, "-- %s: %s\n", fn, sql);
3572 } else {
3573 fprintf(d->trace, "-- %s\n", fn);
3574 }
3575 fflush(d->trace);
3576 }
3577 }
3578
3579 /**
3580 * Trace function for SQLite return codes
3581 * @param d pointer to database connection handle
3582 * @param rc SQLite return code
3583 * @param err error string or NULL
3584 */
3585
3586 static void
dbtracerc(DBC * d,int rc,char * err)3587 dbtracerc(DBC *d, int rc, char *err)
3588 {
3589 if (rc != SQLITE4_OK && d->trace) {
3590 fprintf(d->trace, "-- SQLITE ERROR CODE %d", rc);
3591 fprintf(d->trace, err ? ": %s\n" : "\n", err);
3592 fflush(d->trace);
3593 }
3594 }
3595
3596 /**
3597 * Open SQLite database file given file name and flags.
3598 * @param d DBC pointer
3599 * @param name file name
3600 * @param isu true/false: file name is UTF8 encoded
3601 * @param dsn data source name
3602 * @param sflag STEPAPI flag
3603 * @param spflag SyncPragma string
3604 * @param ntflag NoTransaction string
3605 * @param jmode JournalMode string
3606 * @param busy busy/lock timeout
3607 * @result ODBC error code
3608 */
3609
3610 static SQLRETURN
dbopen(DBC * d,char * name,int isu,char * dsn,char * sflag,char * spflag,char * ntflag,char * jmode,char * busy)3611 dbopen(DBC *d, char *name, int isu, char *dsn, char *sflag,
3612 char *spflag, char *ntflag, char *jmode, char *busy)
3613 {
3614 char *endp = NULL;
3615 int rc, tmp, busyto = 100000;
3616 int flags = SQLITE4_OPEN_READWRITE | SQLITE4_OPEN_CREATE;
3617 char *uname = name;
3618
3619 if (d->sqlite) {
3620 if (d->trace) {
3621 fprintf(d->trace, "-- sqlite4_close (deferred): '%s'\n",
3622 d->dbname);
3623 fflush(d->trace);
3624 }
3625 sqlite4_close(d->sqlite, 0);
3626 d->sqlite = NULL;
3627 }
3628 if (d->nocreat) {
3629 flags &= ~ SQLITE4_OPEN_CREATE;
3630 }
3631 #if defined(_WIN32) || defined(_WIN64)
3632 if (!isu) {
3633 char expname[SQL_MAX_MESSAGE_LENGTH * 2];
3634
3635 expname[0] = '\0';
3636 rc = ExpandEnvironmentStrings(name, expname, sizeof (expname));
3637 if (rc <= sizeof (expname)) {
3638 uname = wmb_to_utf(expname, rc - 1);
3639 } else {
3640 uname = wmb_to_utf(name, -1);
3641 }
3642 if (!uname) {
3643 rc = SQLITE4_NOMEM;
3644 setstatd(d, rc, "out of memory", (*d->ov3) ? "HY000" : "S1000");
3645 return SQL_ERROR;
3646 }
3647 }
3648 #endif
3649 #ifdef SQLITE4_OPEN_URI
3650 flags |= SQLITE4_OPEN_URI;
3651 #endif
3652 rc = sqlite4_open(0, uname, &d->sqlite, /* flags ?? */ 0);
3653 #if defined(WINTERFACE) || defined(_WIN32) || defined(_WIN64)
3654 if (uname != name) {
3655 uc_free(uname);
3656 }
3657 #endif
3658 if (rc != SQLITE4_OK) {
3659 connfail:
3660 setstatd(d, rc, "connect failed", (*d->ov3) ? "HY000" : "S1000");
3661 if (d->sqlite) {
3662 sqlite4_close(d->sqlite, 0);
3663 d->sqlite = NULL;
3664 }
3665 return SQL_ERROR;
3666 }
3667 d->pwd = NULL;
3668 d->pwdLen = 0;
3669 if (d->trace) {
3670 sqlite4_profile(d->sqlite, d, dbtrace, 0);
3671 }
3672 d->step_enable = getbool(sflag);
3673 d->trans_disable = getbool(ntflag);
3674 d->curtype = d->step_enable ?
3675 SQL_CURSOR_FORWARD_ONLY : SQL_CURSOR_STATIC;
3676 tmp = strtol(busy, &endp, 0);
3677 if (endp && *endp == '\0' && endp != busy) {
3678 busyto = tmp;
3679 }
3680 if (busyto < 1 || busyto > 1000000) {
3681 busyto = 1000000;
3682 }
3683 d->timeout = busyto;
3684 freep(&d->dbname);
3685 d->dbname = xstrdup(name);
3686 freep(&d->dsn);
3687 d->dsn = xstrdup(dsn);
3688 if ((rc = setsqliteopts(d->sqlite, d)) != SQLITE4_OK) {
3689 if (d->trace) {
3690 fprintf(d->trace, "-- sqlite4_close: '%s'\n",
3691 d->dbname);
3692 fflush(d->trace);
3693 }
3694 sqlite4_close(d->sqlite, 0);
3695 d->sqlite = NULL;
3696 goto connfail;
3697 }
3698 if (!spflag || spflag[0] == '\0') {
3699 spflag = "NORMAL";
3700 }
3701 if (spflag[0] != '\0') {
3702 char syncp[128];
3703
3704 sprintf(syncp, "PRAGMA synchronous = %8.8s;", spflag);
3705 sqlite4_exec(d->sqlite, syncp, NULL, NULL);
3706 }
3707 if (jmode[0] != '\0') {
3708 char jourp[128];
3709
3710 sprintf(jourp, "PRAGMA journal_mode = %16.16s;", jmode);
3711 sqlite4_exec(d->sqlite, jourp, NULL, NULL);
3712 }
3713 if (d->trace) {
3714 fprintf(d->trace, "-- sqlite4_open: '%s'\n", d->dbname);
3715 fflush(d->trace);
3716 }
3717 #if defined(_WIN32) || defined(_WIN64)
3718 {
3719 char pname[MAX_PATH];
3720 HANDLE h = OpenProcess(PROCESS_QUERY_INFORMATION | PROCESS_VM_READ,
3721 FALSE, GetCurrentProcessId());
3722
3723 pname[0] = '\0';
3724 if (h) {
3725 HMODULE m = NULL, l = LoadLibrary("psapi.dll");
3726 DWORD need;
3727 typedef BOOL (WINAPI *epmfunc)(HANDLE, HMODULE *, DWORD, LPDWORD);
3728 typedef BOOL (WINAPI *gmbfunc)(HANDLE, HMODULE, LPSTR, DWORD);
3729 epmfunc epm;
3730 gmbfunc gmb;
3731
3732 if (l) {
3733 epm = (epmfunc) GetProcAddress(l, "EnumProcessModules");
3734 gmb = (gmbfunc) GetProcAddress(l, "GetModuleBaseNameA");
3735 if (epm && gmb && epm(h, &m, sizeof (m), &need)) {
3736 gmb(h, m, pname, sizeof (pname));
3737 }
3738 FreeLibrary(l);
3739 }
3740 CloseHandle(h);
3741 }
3742 d->xcelqrx = strncasecmp(pname, "EXCEL", 5) == 0 ||
3743 strncasecmp(pname, "MSQRY", 5) == 0;
3744 if (d->trace && d->xcelqrx) {
3745 fprintf(d->trace, "-- enabled EXCEL quirks\n");
3746 fflush(d->trace);
3747 }
3748 }
3749 #endif
3750 sqlite4_create_function(d->sqlite, "blob_import", 1, d,
3751 blob_import, 0, 0, 0);
3752 sqlite4_create_function(d->sqlite, "blob_export", 2, d,
3753 blob_export, 0, 0, 0);
3754 return SQL_SUCCESS;
3755 }
3756
3757 /**
3758 * Load SQLite extension modules, if any
3759 * @param d DBC pointer
3760 * @param exts string, comma separated extension names
3761 */
3762
3763 static void
dbloadext(DBC * d,char * exts)3764 dbloadext(DBC *d, char *exts)
3765 {
3766 #if 0
3767 char *p;
3768 char path[SQL_MAX_MESSAGE_LENGTH];
3769 int plen = 0;
3770
3771 if (!d->sqlite) {
3772 return;
3773 }
3774 #if defined(_WIN32) || defined(_WIN64)
3775 GetModuleFileName(hModule, path, sizeof (path));
3776 p = strrchr(path, '\\');
3777 plen = p ? ((p + 1) - path) : 0;
3778 #endif
3779 do {
3780 p = strchr(exts, ',');
3781 if (p) {
3782 strncpy(path + plen, exts, p - exts);
3783 path[plen + (p - exts)] = '\0';
3784 } else {
3785 strcpy(path + plen, exts);
3786 }
3787 if (exts[0]) {
3788 char *errmsg = NULL;
3789 int rc;
3790 #if defined(_WIN32) || defined(_WIN64)
3791 char *q;
3792
3793 q = path + plen;
3794 if (!(q[0] &&
3795 ((q[1] == ':' && (q[2] == '\\' || q[2] == '/')) ||
3796 q[0] == '\\' || q[0] == '/' || q[0] == '.'))) {
3797 q = path;
3798 }
3799 rc = sqlite4_load_extension(d->sqlite, q, 0, &errmsg);
3800 #else
3801 rc = sqlite4_load_extension(d->sqlite, path, 0, &errmsg);
3802 #endif
3803 if (rc != SQLITE4_OK) {
3804 #if defined(_WIN32) || defined(_WIN64)
3805 char buf[512], msg[512];
3806
3807 LoadString(hModule, IDS_EXTERR, buf, sizeof (buf));
3808 wsprintf(msg, buf, q, errmsg ?
3809 errmsg : "no error info available");
3810 LoadString(hModule, IDS_EXTTITLE, buf, sizeof (buf));
3811 MessageBox(NULL, msg, buf,
3812 MB_ICONEXCLAMATION | MB_OK | MB_TASKMODAL |
3813 MB_SETFOREGROUND);
3814 #else
3815 fprintf(stderr, "extension '%s' did not load%s%s\n",
3816 path, errmsg ? ": " : "", errmsg ? errmsg : "");
3817 #endif
3818 }
3819 }
3820 if (p) {
3821 exts = p + 1;
3822 }
3823 } while (p);
3824 #endif
3825 }
3826
3827 /**
3828 * Find out column type
3829 * @param s4stmt SQLite statement pointer
3830 * @param col column number
3831 * @param d DBC pointer (for tracing only)
3832 * @param guessed_types flag array
3833 * @result type name as string
3834 */
3835
3836 static char *
s4stmt_coltype(sqlite4_stmt * s4stmt,int col,DBC * d,int * guessed_types)3837 s4stmt_coltype(sqlite4_stmt *s4stmt, int col, DBC *d, int *guessed_types)
3838 {
3839 char *typename = (char *) sqlite4_column_decltype(s4stmt, col);
3840 char guess[64];
3841
3842 guess[0] = '\0';
3843 if (!typename) {
3844 int coltype = sqlite4_column_type(s4stmt, col);
3845
3846 if (guessed_types) {
3847 guessed_types[0]++;
3848 }
3849 if (d->trace) {
3850 sprintf(guess, " (guessed from %d)", coltype);
3851 }
3852 switch (coltype) {
3853 case SQLITE4_INTEGER: typename = "integer"; break;
3854 case SQLITE4_FLOAT: typename = "double"; break;
3855 default:
3856 case SQLITE4_TEXT: typename = "varchar"; break;
3857 case SQLITE4_BLOB: typename = "blob"; break;
3858 #if 0
3859 case SQLITE4_NULL: typename = "null"; break;
3860 #endif
3861 }
3862 }
3863 if (d->trace) {
3864 fprintf(d->trace, "-- column %d type%s: '%s'\n", col + 1,
3865 guess, typename);
3866 fflush(d->trace);
3867 }
3868 return typename;
3869 }
3870
3871 /**
3872 * Add meta data for column
3873 * @param s4stmt SQLite statement pointer
3874 * @param col column number
3875 * @param d DBC pointer (for tracing only)
3876 * @param ci pointer to COL
3877 */
3878
3879 static void
s4stmt_addmeta(sqlite4_stmt * s4stmt,int col,DBC * d,COL * ci)3880 s4stmt_addmeta(sqlite4_stmt *s4stmt, int col, DBC *d, COL *ci)
3881 {
3882 int nn = 0, pk = 0, ai = 0;
3883 const char *dn, *tn, *cn, *dummy[4];
3884
3885 dn = sqlite4_column_database_name(s4stmt, col);
3886 tn = sqlite4_column_table_name(s4stmt, col);
3887 cn = sqlite4_column_origin_name(s4stmt, col);
3888 dummy[0] = dummy[1] = 0;
3889 #if 0
3890 if (tn && cn) {
3891 sqlite4_table_column_metadata(d->sqlite, dn, tn, cn,
3892 dummy, dummy + 1,
3893 &nn, &pk, &ai);
3894 }
3895 #endif
3896 ci->autoinc = ai ? SQL_TRUE: SQL_FALSE;
3897 ci->notnull = nn ? SQL_NO_NULLS : SQL_NULLABLE;
3898 ci->ispk = pk ? 1 : 0;
3899 if (d->trace) {
3900 fprintf(d->trace, "-- column %d %s\n",
3901 col + 1, nn ? "notnull" : "nullable");
3902 if (ai) {
3903 fprintf(d->trace, "-- column %d autoincrement\n", col + 1);
3904 }
3905 fflush(d->trace);
3906 }
3907 ci->isrowid = 0;
3908 if (ci->ispk && tn) {
3909 nn = pk = ai = 0;
3910 dummy[2] = dummy[3] = 0;
3911
3912 #if 0
3913 sqlite4_table_column_metadata(d->sqlite, dn, tn, "rowid",
3914 dummy + 2, dummy + 3,
3915 &nn, &pk, &ai);
3916 #endif
3917 if (pk && dummy[0] && dummy[0] == dummy[2]) {
3918 ci->isrowid = 1;
3919 }
3920 }
3921 }
3922
3923 /**
3924 * Do one sqlite statement step gathering one result row
3925 * @param s statement pointer
3926 * @result ODBC error code
3927 */
3928
3929 static int
s4stmt_step(STMT * s)3930 s4stmt_step(STMT *s)
3931 {
3932 DBC *d = (DBC *) s->dbc;
3933 char **rowd = NULL;
3934 const char *errp = NULL;
3935 int i, ncols, rc;
3936
3937 if (s != d->cur_s4stmt || !s->s4stmt) {
3938 setstat(s, -1, "stale statement", (*s->ov3) ? "HY000" : "S1000");
3939 return SQL_ERROR;
3940 }
3941 rc = sqlite4_step(s->s4stmt);
3942 if (rc == SQLITE4_ROW || rc == SQLITE4_DONE) {
3943 ++s->s4stmt_rownum;
3944 ncols = sqlite4_column_count(s->s4stmt);
3945 if (d->s4stmt_needmeta && s->s4stmt_rownum == 0 && ncols > 0) {
3946 PTRDIFF_T size;
3947 char *p;
3948 COL *dyncols;
3949 const char *colname, *typename;
3950 char *tblname, *dbname;
3951
3952 for (i = size = 0; i < ncols; i++) {
3953 colname = sqlite4_column_name(s->s4stmt, i);
3954 size += 3 + 3 * strlen(colname);
3955 }
3956 tblname = (char *) size;
3957 for (i = 0; i < ncols; i++) {
3958 p = (char *) sqlite4_column_table_name(s->s4stmt, i);
3959 size += 2 + (p ? strlen(p) : 0);
3960 }
3961 dbname = (char *) size;
3962 for (i = 0; i < ncols; i++) {
3963 p = (char *) sqlite4_column_database_name(s->s4stmt, i);
3964 size += 2 + (p ? strlen(p) : 0);
3965 }
3966 dyncols = xmalloc(ncols * sizeof (COL) + size);
3967 if (!dyncols) {
3968 freedyncols(s);
3969 s->ncols = 0;
3970 dbtraceapi(d, "sqlite4_finalize", 0);
3971 sqlite4_finalize(s->s4stmt);
3972 s->s4stmt = NULL;
3973 d->cur_s4stmt = NULL;
3974 return nomem(s);
3975 }
3976 p = (char *) (dyncols + ncols);
3977 tblname = p + (PTRDIFF_T) tblname;
3978 dbname = p + (PTRDIFF_T) dbname;
3979 for (i = 0; i < ncols; i++) {
3980 char *q;
3981
3982 colname = sqlite4_column_name(s->s4stmt, i);
3983 if (d->trace) {
3984 fprintf(d->trace, "-- column %d name: '%s'\n",
3985 i + 1, colname);
3986 fflush(d->trace);
3987 }
3988 q = (char *) sqlite4_column_table_name(s->s4stmt, i);
3989 strcpy(tblname, q ? q : "");
3990 if (d->trace) {
3991 fprintf(d->trace, "-- table %d name: '%s'\n",
3992 i + 1, tblname);
3993 fflush(d->trace);
3994 }
3995 dyncols[i].table = tblname;
3996 tblname += strlen(tblname) + 1;
3997 q = (char *) sqlite4_column_database_name(s->s4stmt, i);
3998 strcpy(dbname, q ? q : "");
3999 if (d->trace) {
4000 fprintf(d->trace, "-- database %d name: '%s'\n",
4001 i + 1, dbname);
4002 fflush(d->trace);
4003 }
4004 dyncols[i].db = dbname;
4005 dbname += strlen(dbname) + 1;
4006 typename = s4stmt_coltype(s->s4stmt, i, d, 0);
4007 strcpy(p, colname);
4008 dyncols[i].label = p;
4009 p += strlen(p) + 1;
4010 q = strchr(colname, '.');
4011 if (q) {
4012 char *q2 = strchr(q + 1, '.');
4013
4014 /* SQLite 3.3.4 produces view.table.column sometimes */
4015 if (q2) {
4016 q = q2;
4017 }
4018 }
4019 if (q) {
4020 strncpy(p, colname, q - colname);
4021 p[q - colname] = '\0';
4022 p += strlen(p) + 1;
4023 strcpy(p, q + 1);
4024 dyncols[i].column = p;
4025 p += strlen(p) + 1;
4026 } else {
4027 strcpy(p, colname);
4028 dyncols[i].column = p;
4029 p += strlen(p) + 1;
4030 }
4031 if (s->longnames) {
4032 dyncols[i].column = dyncols[i].label;
4033 }
4034 #ifdef SQL_LONGVARCHAR
4035 dyncols[i].type = SQL_LONGVARCHAR;
4036 dyncols[i].size = 65535;
4037 #else
4038 dyncols[i].type = SQL_VARCHAR;
4039 dyncols[i].size = 255;
4040 #endif
4041 dyncols[i].index = i;
4042 dyncols[i].scale = 0;
4043 dyncols[i].prec = 0;
4044 dyncols[i].nosign = 1;
4045 s4stmt_addmeta(s->s4stmt, i, d, &dyncols[i]);
4046 dyncols[i].typename = xstrdup(typename);
4047 }
4048 freedyncols(s);
4049 s->ncols = s->dcols = ncols;
4050 s->dyncols = s->cols = dyncols;
4051 fixupdyncols(s, d);
4052 mkbindcols(s, s->ncols);
4053 d->s4stmt_needmeta = 0;
4054 }
4055 if (ncols <= 0) {
4056 goto killstmt;
4057 }
4058 if (rc == SQLITE4_DONE) {
4059 freeresult(s, 0);
4060 s->nrows = 0;
4061 dbtraceapi(d, "sqlite4_finalize", 0);
4062 sqlite4_finalize(s->s4stmt);
4063 s->s4stmt = NULL;
4064 d->cur_s4stmt = NULL;
4065 return SQL_SUCCESS;
4066 }
4067 rowd = xmalloc((1 + 2 * ncols) * sizeof (char *));
4068 if (rowd) {
4069 const char *value;
4070
4071 rowd[0] = (char *) ((PTRDIFF_T) (ncols * 2));
4072 ++rowd;
4073 for (i = 0; i < ncols; i++) {
4074 int coltype = sqlite4_column_type(s->s4stmt, i);
4075
4076 rowd[i] = rowd[i + ncols] = NULL;
4077 if (coltype == SQLITE4_BLOB) {
4078 int k, nbytes;
4079 char *qp;
4080 unsigned const char *bp;
4081
4082 bp = sqlite4_column_blob(s->s4stmt, i, &nbytes);
4083 qp = xmalloc(nbytes * 2 + 4);
4084 if (qp) {
4085 rowd[i + ncols] = qp;
4086 *qp++ = 'X';
4087 *qp++ = '\'';
4088 for (k = 0; k < nbytes; k++) {
4089 *qp++ = xdigits[(bp[k] >> 4)];
4090 *qp++ = xdigits[(bp[k] & 0xF)];
4091 }
4092 *qp++ = '\'';
4093 *qp = '\0';
4094 }
4095 #ifdef _MSC_VER
4096 } else if (coltype == SQLITE4_FLOAT) {
4097 struct lconv *lc = 0;
4098 double d = sqlite4_column_double(s->s4stmt, i);
4099 char *p, buffer[128];
4100
4101 /*
4102 * This avoids floating point rounding
4103 * and formatting problems of some SQLite
4104 * versions in conjunction with MSVC 2010.
4105 */
4106 snprintf(buffer, sizeof (buffer), "%.15g", d);
4107 lc = localeconv();
4108 if (lc && lc->decimal_point && lc->decimal_point[0] &&
4109 lc->decimal_point[0] != '.') {
4110 p = strchr(buffer, lc->decimal_point[0]);
4111 if (p) {
4112 *p = '.';
4113 }
4114 }
4115 rowd[i + ncols] = xstrdup(buffer);
4116 #endif
4117 } else if (coltype != SQLITE4_NULL) {
4118 int nbytes;
4119
4120 value = sqlite4_column_text(s->s4stmt, i, &nbytes);
4121 rowd[i + ncols] = xstrdup((char *) value);
4122 }
4123 }
4124 for (i = 0; i < ncols; i++) {
4125 int coltype = sqlite4_column_type(s->s4stmt, i);
4126
4127 value = NULL;
4128 if (coltype == SQLITE4_BLOB) {
4129 int nbytes;
4130
4131 value = sqlite4_column_blob(s->s4stmt, i, &nbytes);
4132 } else if (coltype != SQLITE4_NULL) {
4133 int nbytes;
4134
4135 value = sqlite4_column_text(s->s4stmt, i, &nbytes);
4136 }
4137 if (value && !rowd[i + ncols]) {
4138 freerows(rowd);
4139 rowd = 0;
4140 break;
4141 }
4142 }
4143 }
4144 if (rowd) {
4145 freeresult(s, 0);
4146 s->nrows = 1;
4147 s->rows = rowd;
4148 s->rowfree = freerows;
4149 if (rc == SQLITE4_DONE) {
4150 dbtraceapi(d, "sqlite4_finalize", 0);
4151 sqlite4_finalize(s->s4stmt);
4152 s->s4stmt = NULL;
4153 d->cur_s4stmt = NULL;
4154 }
4155 return SQL_SUCCESS;
4156 }
4157 }
4158 killstmt:
4159 dbtraceapi(d, "sqlite4_reset", 0);
4160 rc = sqlite4_reset(s->s4stmt);
4161 s->s4stmt_noreset = 1;
4162 errp = sqlite4_errmsg(d->sqlite);
4163 if (d->cur_s4stmt == s) {
4164 d->cur_s4stmt = NULL;
4165 }
4166 setstat(s, rc, "%s (%d)", (*s->ov3) ? "HY000" : "S1000",
4167 errp ? errp : "unknown error", rc);
4168 return SQL_ERROR;
4169 }
4170
4171 /**
4172 * Stop running sqlite statement
4173 * @param s statement pointer
4174 */
4175
4176 static void
s4stmt_end(STMT * s)4177 s4stmt_end(STMT *s)
4178 {
4179 DBC *d;
4180
4181 if (!s || !s->s4stmt) {
4182 return;
4183 }
4184 d = (DBC *) s->dbc;
4185 if (d) {
4186 d->busyint = 0;
4187 }
4188 if (!s->s4stmt_noreset) {
4189 dbtraceapi(d, "sqlite4_reset", 0);
4190 sqlite4_reset(s->s4stmt);
4191 s->s4stmt_noreset = 1;
4192 s->s4stmt_rownum = -1;
4193 }
4194 if (d->cur_s4stmt == s) {
4195 d->cur_s4stmt = NULL;
4196 }
4197 }
4198
4199 /**
4200 * Conditionally stop running sqlite statement
4201 * @param s statement pointer
4202 */
4203
4204 static void
s4stmt_end_if(STMT * s)4205 s4stmt_end_if(STMT *s)
4206 {
4207 DBC *d = (DBC *) s->dbc;
4208
4209 if (d) {
4210 d->busyint = 0;
4211 }
4212 if (d && d->cur_s4stmt == s) {
4213 s4stmt_end(s);
4214 }
4215 }
4216
4217 /**
4218 * Drop running sqlite statement in STMT
4219 * @param s statement pointer
4220 */
4221
4222 static void
s4stmt_drop(STMT * s)4223 s4stmt_drop(STMT *s)
4224 {
4225 if (s->s4stmt) {
4226 DBC *d = (DBC *) s->dbc;
4227
4228 if (d) {
4229 dbtraceapi(d, "sqlite4_finalize", 0);
4230 }
4231 sqlite4_finalize(s->s4stmt);
4232 s->s4stmt = NULL;
4233 s->s4stmt_rownum = 0;
4234 }
4235 }
4236
4237 /**
4238 * Start sqlite statement for execution of SELECT statement.
4239 * @param s statement pointer
4240 * @result ODBC error code
4241 */
4242
4243 static SQLRETURN
s4stmt_start(STMT * s)4244 s4stmt_start(STMT *s)
4245 {
4246 DBC *d = (DBC *) s->dbc;
4247 int sqlleft;
4248 sqlite4_stmt *s4stmt = NULL;
4249 int rc, nretry = 0;
4250
4251 d->s4stmt_needmeta = 0;
4252 if (!s->s4stmt) {
4253 dbtraceapi(d, "sqlite4_prepare", (char *) s->query);
4254 do {
4255 s4stmt = NULL;
4256 rc = sqlite4_prepare(d->sqlite, (char *) s->query, -1,
4257 &s4stmt, &sqlleft);
4258 if (rc != SQLITE4_OK) {
4259 if (s4stmt) {
4260 sqlite4_finalize(s4stmt);
4261 s4stmt = NULL;
4262 }
4263 }
4264 } while (rc == SQLITE4_SCHEMA && (++nretry) < 2);
4265 dbtracerc(d, rc, NULL);
4266 if (rc != SQLITE4_OK) {
4267 if (s4stmt) {
4268 dbtraceapi(d, "sqlite4_finalize", NULL);
4269 sqlite4_finalize(s4stmt);
4270 }
4271 setstat(s, rc, "%s (%d)", (*s->ov3) ? "HY000" : "S1000",
4272 sqlite4_errmsg(d->sqlite), rc);
4273 return SQL_ERROR;
4274 }
4275 if (sqlite4_bind_parameter_count(s4stmt) != s->nparams) {
4276 dbtraceapi(d, "sqlite4_finalize", 0);
4277 sqlite4_finalize(s4stmt);
4278 setstat(s, SQLITE4_ERROR, "parameter marker count incorrect",
4279 (*s->ov3) ? "HY000" : "S1000");
4280 return SQL_ERROR;
4281 }
4282 s->s4stmt = s4stmt;
4283 s->s4stmt_noreset = 1;
4284 d->s4stmt_needmeta = 1;
4285 }
4286 d->cur_s4stmt = s;
4287 s->s4stmt_rownum = -1;
4288 s4bind(d, s->s4stmt, s->nparams, s->bindparms);
4289 return SQL_SUCCESS;
4290 }
4291
4292 #ifndef WINTERFACE
4293 /**
4294 * Function not implemented.
4295 */
4296
4297 SQLRETURN SQL_API
SQLDataSources(SQLHENV env,SQLUSMALLINT dir,SQLCHAR * srvname,SQLSMALLINT buflen1,SQLSMALLINT * lenp1,SQLCHAR * desc,SQLSMALLINT buflen2,SQLSMALLINT * lenp2)4298 SQLDataSources(SQLHENV env, SQLUSMALLINT dir, SQLCHAR *srvname,
4299 SQLSMALLINT buflen1, SQLSMALLINT *lenp1,
4300 SQLCHAR *desc, SQLSMALLINT buflen2, SQLSMALLINT *lenp2)
4301 {
4302 if (env == SQL_NULL_HENV) {
4303 return SQL_INVALID_HANDLE;
4304 }
4305 return SQL_ERROR;
4306 }
4307 #endif
4308
4309 #ifdef WINTERFACE
4310 /**
4311 * Function not implemented.
4312 */
4313
4314 SQLRETURN SQL_API
SQLDataSourcesW(SQLHENV env,SQLUSMALLINT dir,SQLWCHAR * srvname,SQLSMALLINT buflen1,SQLSMALLINT * lenp1,SQLWCHAR * desc,SQLSMALLINT buflen2,SQLSMALLINT * lenp2)4315 SQLDataSourcesW(SQLHENV env, SQLUSMALLINT dir, SQLWCHAR *srvname,
4316 SQLSMALLINT buflen1, SQLSMALLINT *lenp1,
4317 SQLWCHAR *desc, SQLSMALLINT buflen2, SQLSMALLINT *lenp2)
4318 {
4319 if (env == SQL_NULL_HENV) {
4320 return SQL_INVALID_HANDLE;
4321 }
4322 return SQL_ERROR;
4323 }
4324 #endif
4325
4326 #ifndef WINTERFACE
4327 /**
4328 * Function not implemented.
4329 */
4330
4331 SQLRETURN SQL_API
SQLDrivers(SQLHENV env,SQLUSMALLINT dir,SQLCHAR * drvdesc,SQLSMALLINT descmax,SQLSMALLINT * desclenp,SQLCHAR * drvattr,SQLSMALLINT attrmax,SQLSMALLINT * attrlenp)4332 SQLDrivers(SQLHENV env, SQLUSMALLINT dir, SQLCHAR *drvdesc,
4333 SQLSMALLINT descmax, SQLSMALLINT *desclenp,
4334 SQLCHAR *drvattr, SQLSMALLINT attrmax, SQLSMALLINT *attrlenp)
4335 {
4336 if (env == SQL_NULL_HENV) {
4337 return SQL_INVALID_HANDLE;
4338 }
4339 return SQL_ERROR;
4340 }
4341 #endif
4342
4343 #ifdef WINTERFACE
4344 /**
4345 * Function not implemented.
4346 */
4347
4348 SQLRETURN SQL_API
SQLDriversW(SQLHENV env,SQLUSMALLINT dir,SQLWCHAR * drvdesc,SQLSMALLINT descmax,SQLSMALLINT * desclenp,SQLWCHAR * drvattr,SQLSMALLINT attrmax,SQLSMALLINT * attrlenp)4349 SQLDriversW(SQLHENV env, SQLUSMALLINT dir, SQLWCHAR *drvdesc,
4350 SQLSMALLINT descmax, SQLSMALLINT *desclenp,
4351 SQLWCHAR *drvattr, SQLSMALLINT attrmax, SQLSMALLINT *attrlenp)
4352 {
4353 if (env == SQL_NULL_HENV) {
4354 return SQL_INVALID_HANDLE;
4355 }
4356 return SQL_ERROR;
4357 }
4358 #endif
4359
4360 #ifndef WINTERFACE
4361 /**
4362 * Function not implemented.
4363 */
4364
4365 SQLRETURN SQL_API
SQLBrowseConnect(SQLHDBC dbc,SQLCHAR * connin,SQLSMALLINT conninLen,SQLCHAR * connout,SQLSMALLINT connoutMax,SQLSMALLINT * connoutLen)4366 SQLBrowseConnect(SQLHDBC dbc, SQLCHAR *connin, SQLSMALLINT conninLen,
4367 SQLCHAR *connout, SQLSMALLINT connoutMax,
4368 SQLSMALLINT *connoutLen)
4369 {
4370 SQLRETURN ret;
4371
4372 HDBC_LOCK(dbc);
4373 ret = drvunimpldbc(dbc);
4374 HDBC_UNLOCK(dbc);
4375 return ret;
4376 }
4377 #endif
4378
4379 #ifdef WINTERFACE
4380 /**
4381 * Function not implemented.
4382 */
4383
4384 SQLRETURN SQL_API
SQLBrowseConnectW(SQLHDBC dbc,SQLWCHAR * connin,SQLSMALLINT conninLen,SQLWCHAR * connout,SQLSMALLINT connoutMax,SQLSMALLINT * connoutLen)4385 SQLBrowseConnectW(SQLHDBC dbc, SQLWCHAR *connin, SQLSMALLINT conninLen,
4386 SQLWCHAR *connout, SQLSMALLINT connoutMax,
4387 SQLSMALLINT *connoutLen)
4388 {
4389 SQLRETURN ret;
4390
4391 HDBC_LOCK(dbc);
4392 ret = drvunimpldbc(dbc);
4393 HDBC_UNLOCK(dbc);
4394 return ret;
4395 }
4396 #endif
4397
4398 /**
4399 * Internal put (partial) parameter data into executing statement.
4400 * @param stmt statement handle
4401 * @param data pointer to data
4402 * @param len length of data
4403 * @result ODBC error code
4404 */
4405
4406 static SQLRETURN
drvputdata(SQLHSTMT stmt,SQLPOINTER data,SQLLEN len)4407 drvputdata(SQLHSTMT stmt, SQLPOINTER data, SQLLEN len)
4408 {
4409 STMT *s;
4410 int i, dlen, done = 0;
4411 BINDPARM *p;
4412
4413 if (stmt == SQL_NULL_HSTMT) {
4414 return SQL_INVALID_HANDLE;
4415 }
4416 s = (STMT *) stmt;
4417 if (!s->query || s->nparams <= 0) {
4418 seqerr:
4419 setstat(s, -1, "sequence error", "HY010");
4420 return SQL_ERROR;
4421 }
4422 for (i = (s->pdcount < 0) ? 0 : s->pdcount; i < s->nparams; i++) {
4423 p = &s->bindparms[i];
4424 if (p->need > 0) {
4425 int type = mapdeftype(p->type, p->stype, -1, s->nowchar[0]);
4426
4427 if (len == SQL_NULL_DATA) {
4428 freep(&p->parbuf);
4429 p->param = NULL;
4430 p->len = SQL_NULL_DATA;
4431 p->need = -1;
4432 } else if (type != SQL_C_CHAR
4433 #ifdef WCHARSUPPORT
4434 && type != SQL_C_WCHAR
4435 #endif
4436 && type != SQL_C_BINARY) {
4437 int size = 0;
4438
4439 switch (type) {
4440 case SQL_C_TINYINT:
4441 case SQL_C_UTINYINT:
4442 case SQL_C_STINYINT:
4443 #ifdef SQL_BIT
4444 case SQL_C_BIT:
4445 #endif
4446 size = sizeof (SQLCHAR);
4447 break;
4448 case SQL_C_SHORT:
4449 case SQL_C_USHORT:
4450 case SQL_C_SSHORT:
4451 size = sizeof (SQLSMALLINT);
4452 break;
4453 case SQL_C_LONG:
4454 case SQL_C_ULONG:
4455 case SQL_C_SLONG:
4456 size = sizeof (SQLINTEGER);
4457 break;
4458 #ifdef SQL_BIGINT
4459 case SQL_C_UBIGINT:
4460 case SQL_C_SBIGINT:
4461 size = sizeof (SQLBIGINT);
4462 break;
4463 #endif
4464 case SQL_C_FLOAT:
4465 size = sizeof (float);
4466 break;
4467 case SQL_C_DOUBLE:
4468 size = sizeof (double);
4469 break;
4470 #ifdef SQL_C_TYPE_DATE
4471 case SQL_C_TYPE_DATE:
4472 #endif
4473 case SQL_C_DATE:
4474 size = sizeof (DATE_STRUCT);
4475 break;
4476 #ifdef SQL_C_TYPE_DATE
4477 case SQL_C_TYPE_TIME:
4478 #endif
4479 case SQL_C_TIME:
4480 size = sizeof (TIME_STRUCT);
4481 break;
4482 #ifdef SQL_C_TYPE_DATE
4483 case SQL_C_TYPE_TIMESTAMP:
4484 #endif
4485 case SQL_C_TIMESTAMP:
4486 size = sizeof (TIMESTAMP_STRUCT);
4487 break;
4488 }
4489 freep(&p->parbuf);
4490 p->parbuf = xmalloc(size);
4491 if (!p->parbuf) {
4492 return nomem(s);
4493 }
4494 p->param = p->parbuf;
4495 memcpy(p->param, data, size);
4496 p->len = size;
4497 p->need = -1;
4498 } else if (len == SQL_NTS && (
4499 type == SQL_C_CHAR
4500 #ifdef WCHARSUPPORT
4501 || type == SQL_C_WCHAR
4502 #endif
4503 )) {
4504 char *dp = data;
4505
4506 #ifdef WCHARSUPPORT
4507 if (type == SQL_C_WCHAR) {
4508 dp = uc_to_utf(data, len);
4509 if (!dp) {
4510 return nomem(s);
4511 }
4512 }
4513 #endif
4514 #if defined(_WIN32) || defined(_WIN64)
4515 if (*s->oemcp) {
4516 dp = wmb_to_utf(data, strlen (data));
4517 if (!dp) {
4518 return nomem(s);
4519 }
4520 }
4521 #endif
4522 dlen = strlen(dp);
4523 freep(&p->parbuf);
4524 p->parbuf = xmalloc(dlen + 1);
4525 if (!p->parbuf) {
4526 if (dp != data) {
4527 uc_free(dp);
4528 }
4529 return nomem(s);
4530 }
4531 p->param = p->parbuf;
4532 strcpy(p->param, dp);
4533 if (dp != data) {
4534 uc_free(dp);
4535 }
4536 p->len = dlen;
4537 p->need = -1;
4538 } else if (len < 0) {
4539 setstat(s, -1, "invalid length", "HY090");
4540 return SQL_ERROR;
4541 } else {
4542 dlen = min(p->len - p->offs, len);
4543 if (!p->param) {
4544 setstat(s, -1, "no memory for parameter", "HY013");
4545 return SQL_ERROR;
4546 }
4547 memcpy((char *) p->param + p->offs, data, dlen);
4548 p->offs += dlen;
4549 if (p->offs >= p->len) {
4550 #ifdef WCHARSUPPORT
4551 if (type == SQL_C_WCHAR) {
4552 char *dp = uc_to_utf(p->param, p->len);
4553 char *np;
4554 int nlen;
4555
4556 if (!dp) {
4557 return nomem(s);
4558 }
4559 nlen = strlen(dp);
4560 np = xmalloc(nlen + 1);
4561 if (!np) {
4562 uc_free(dp);
4563 return nomem(s);
4564 }
4565 strcpy(np, dp);
4566 uc_free(dp);
4567 if (p->param == p->parbuf) {
4568 freep(&p->parbuf);
4569 }
4570 p->parbuf = p->param = np;
4571 p->len = nlen;
4572 } else {
4573 *((char *) p->param + p->len) = '\0';
4574 }
4575 p->need = (type == SQL_C_CHAR || type == SQL_C_WCHAR)
4576 ? -1 : 0;
4577 #else
4578 *((char *) p->param + p->len) = '\0';
4579 p->need = (type == SQL_C_CHAR) ? -1 : 0;
4580 #endif
4581 #if defined(_WIN32) || defined(_WIN64)
4582 if (type == SQL_C_CHAR && *s->oemcp &&
4583 !(p->stype == SQL_BINARY ||
4584 p->stype == SQL_VARBINARY ||
4585 p->stype == SQL_LONGVARBINARY)) {
4586 char *dp = wmb_to_utf(p->param, p->len);
4587
4588 if (!dp) {
4589 return nomem(s);
4590 }
4591 if (p->param == p->parbuf) {
4592 freep(&p->parbuf);
4593 }
4594 p->parbuf = p->param = dp;
4595 p->len = strlen(dp);
4596 }
4597 if (p->type == SQL_C_WCHAR &&
4598 (p->stype == SQL_VARCHAR ||
4599 p->stype == SQL_LONGVARCHAR) &&
4600 p->len == p->coldef * sizeof (SQLWCHAR)) {
4601 /* fix for MS-Access */
4602 p->len = p->coldef;
4603 }
4604 #endif
4605 }
4606 }
4607 done = 1;
4608 break;
4609 }
4610 }
4611 if (!done) {
4612 goto seqerr;
4613 }
4614 return SQL_SUCCESS;
4615 }
4616
4617 /**
4618 * Put (partial) parameter data into executing statement.
4619 * @param stmt statement handle
4620 * @param data pointer to data
4621 * @param len length of data
4622 * @result ODBC error code
4623 */
4624
4625 SQLRETURN SQL_API
SQLPutData(SQLHSTMT stmt,SQLPOINTER data,SQLLEN len)4626 SQLPutData(SQLHSTMT stmt, SQLPOINTER data, SQLLEN len)
4627 {
4628 SQLRETURN ret;
4629
4630 HSTMT_LOCK(stmt);
4631 ret = drvputdata(stmt, data, len);
4632 HSTMT_UNLOCK(stmt);
4633 return ret;
4634 }
4635
4636 /**
4637 * Clear out parameter bindings, if any.
4638 * @param s statement pointer
4639 */
4640
4641 static SQLRETURN
freeparams(STMT * s)4642 freeparams(STMT *s)
4643 {
4644 if (s->bindparms) {
4645 int n;
4646
4647 for (n = 0; n < s->nbindparms; n++) {
4648 freep(&s->bindparms[n].parbuf);
4649 memset(&s->bindparms[n], 0, sizeof (BINDPARM));
4650 }
4651 }
4652 return SQL_SUCCESS;
4653 }
4654
4655 /**
4656 * Setup sqlite4 parameter for statement parameter.
4657 * @param s statement pointer
4658 * @param sql sql string
4659 * @param pnum parameter number
4660 * @result ODBC error code
4661 *
4662 * The parameter is converted within BINDPARM in order to
4663 * be presented to sqlite4_bind_*() functions.
4664 */
4665
4666 static SQLRETURN
setupparam(STMT * s,char * sql,int pnum)4667 setupparam(STMT *s, char *sql, int pnum)
4668 {
4669 int type, len = 0, needalloc = 0;
4670 BINDPARM *p;
4671
4672 if (!s->bindparms || pnum < 0 || pnum >= s->nbindparms) {
4673 goto error;
4674 }
4675 p = &s->bindparms[pnum];
4676 type = mapdeftype(p->type, p->stype, -1, s->nowchar[0]);
4677 #if (defined(_WIN32) || defined(_WIN64)) && defined(WINTERFACE)
4678 /* MS Access hack part 4 (map SQL_C_DEFAULT to SQL_C_CHAR) */
4679 if (type == SQL_C_WCHAR && p->type == SQL_C_DEFAULT) {
4680 type = SQL_C_CHAR;
4681 }
4682 #endif
4683 if (p->need > 0) {
4684 return setupparbuf(s, p);
4685 }
4686 p->strbuf[0] = '\0';
4687 if (!p->param || (p->lenp && *p->lenp == SQL_NULL_DATA)) {
4688 p->s4type = SQLITE4_NULL;
4689 p->s4size = 0;
4690 return SQL_SUCCESS;
4691 }
4692 if (type == SQL_C_CHAR &&
4693 (p->stype == SQL_BINARY ||
4694 p->stype == SQL_VARBINARY ||
4695 p->stype == SQL_LONGVARBINARY)) {
4696 type = SQL_C_BINARY;
4697 }
4698 switch (type) {
4699 case SQL_C_BINARY:
4700 p->s4type = SQLITE4_BLOB;
4701 p->s4size = p->len;
4702 p->s4val = p->param;
4703 if (p->need < 0) {
4704 break;
4705 }
4706 if (!p->lenp) {
4707 len = p->len;
4708 } else if (*p->lenp == SQL_DATA_AT_EXEC) {
4709 len = p->len;
4710 } else {
4711 len = *p->lenp;
4712 if (len <= SQL_LEN_DATA_AT_EXEC_OFFSET) {
4713 len = SQL_LEN_DATA_AT_EXEC(len);
4714 }
4715 }
4716 if (len < 0) {
4717 setstat(s, -1, "invalid length", "HY009");
4718 return SQL_ERROR;
4719 }
4720 p->len = len;
4721 p->max = p->len;
4722 p->need = -1;
4723 p->s4size = len;
4724 break;
4725 #ifdef WCHARSUPPORT
4726 case SQL_C_WCHAR:
4727 #endif
4728 case SQL_C_CHAR:
4729 p->s4type = SQLITE4_TEXT;
4730 p->s4size = -1;
4731 p->s4val = p->param;
4732 if (!p->parbuf) {
4733 #ifdef WCHARSUPPORT
4734 if (type == SQL_C_WCHAR) {
4735 if (!p->lenp || *p->lenp == SQL_NTS) {
4736 p->max = uc_strlen(p->param) * sizeof (SQLWCHAR);
4737 } else if (*p->lenp >= 0) {
4738 p->max = *p->lenp;
4739 }
4740 } else
4741 #endif
4742 if (type == SQL_C_CHAR) {
4743 if (!p->lenp || *p->lenp == SQL_NTS) {
4744 p->len = p->max = strlen(p->param);
4745 #if defined(_WIN32) || defined(_WIN64)
4746 needalloc = 1;
4747 #endif
4748 } else if (*p->lenp >= 0) {
4749 p->len = p->max = *p->lenp;
4750 needalloc = 1;
4751 }
4752 }
4753 }
4754 if (p->need < 0 && p->parbuf == p->param) {
4755 break;
4756 }
4757 #ifdef WCHARSUPPORT
4758 if (type == SQL_C_WCHAR) {
4759 char *dp = uc_to_utf(p->param, p->max);
4760
4761 if (!dp) {
4762 return nomem(s);
4763 }
4764 if (p->param == p->parbuf) {
4765 freep(&p->parbuf);
4766 }
4767 p->parbuf = p->param = dp;
4768 p->need = -1;
4769 p->len = strlen(p->param);
4770 p->s4val = p->param;
4771 p->s4size = p->len;
4772 } else
4773 #endif
4774 if (type == SQL_C_CHAR) {
4775 p->s4val = p->param;
4776 if (needalloc) {
4777 char *dp;
4778
4779 #if defined(_WIN32) || defined(_WIN64)
4780 if (*s->oemcp) {
4781 dp = wmb_to_utf(p->param, p->len);
4782 } else {
4783 dp = xmalloc(p->len + 1);
4784 }
4785 #else
4786 dp = xmalloc(p->len + 1);
4787 #endif
4788 if (!dp) {
4789 return nomem(s);
4790 }
4791 #if defined(_WIN32) || defined(_WIN64)
4792 if (*s->oemcp) {
4793 p->len = strlen(dp);
4794 } else {
4795 memcpy(dp, p->param, p->len);
4796 dp[p->len] = '\0';
4797 }
4798 #else
4799 memcpy(dp, p->param, p->len);
4800 dp[p->len] = '\0';
4801 #endif
4802 if (p->param == p->parbuf) {
4803 freep(&p->parbuf);
4804 }
4805 p->parbuf = p->param = dp;
4806 p->need = -1;
4807 p->s4val = p->param;
4808 p->s4size = p->len;
4809 }
4810 }
4811 break;
4812 case SQL_C_UTINYINT:
4813 case SQL_C_TINYINT:
4814 case SQL_C_STINYINT:
4815 p->s4type = SQLITE4_INTEGER;
4816 p->s4size = sizeof (int);
4817 p->s4ival = *((SQLCHAR *) p->param);
4818 break;
4819 case SQL_C_USHORT:
4820 p->s4type = SQLITE4_INTEGER;
4821 p->s4size = sizeof (int);
4822 p->s4ival = *((SQLUSMALLINT *) p->param);
4823 break;
4824 case SQL_C_SHORT:
4825 case SQL_C_SSHORT:
4826 p->s4type = SQLITE4_INTEGER;
4827 p->s4size = sizeof (int);
4828 p->s4ival = *((SQLSMALLINT *) p->param);
4829 break;
4830 case SQL_C_ULONG:
4831 p->s4type = SQLITE4_INTEGER;
4832 p->s4size = sizeof (int);
4833 p->s4ival = *((SQLUINTEGER *) p->param);
4834 break;
4835 case SQL_C_LONG:
4836 case SQL_C_SLONG:
4837 p->s4type = SQLITE4_INTEGER;
4838 p->s4size = sizeof (int);
4839 p->s4ival = *((SQLINTEGER *) p->param);
4840 break;
4841 #ifdef SQL_BIT
4842 case SQL_C_BIT:
4843 p->s4type = SQLITE4_INTEGER;
4844 p->s4size = sizeof (int);
4845 p->s4ival = (*((SQLCHAR *) p->param)) ? 1 : 0;
4846 break;
4847 #endif
4848 #ifdef SQL_BIGINT
4849 case SQL_C_SBIGINT:
4850 p->s4type = SQLITE4_INTEGER;
4851 p->s4size = sizeof (sqlite4_int64);
4852 p->s4lival = *((sqlite4_int64 *) p->param);
4853 break;
4854 case SQL_C_UBIGINT:
4855 p->s4type = SQLITE4_INTEGER;
4856 p->s4size = sizeof (sqlite4_int64);
4857 p->s4lival = *((sqlite4_uint64 *) p->param);
4858 break;
4859 #endif
4860 case SQL_C_FLOAT:
4861 p->s4type = SQLITE4_FLOAT;
4862 p->s4size = sizeof (double);
4863 p->s4dval = *((float *) p->param);
4864 break;
4865 case SQL_C_DOUBLE:
4866 p->s4type = SQLITE4_FLOAT;
4867 p->s4size = sizeof (double);
4868 p->s4dval = *((double *) p->param);
4869 break;
4870 #ifdef SQL_C_TYPE_DATE
4871 case SQL_C_TYPE_DATE:
4872 #endif
4873 case SQL_C_DATE:
4874 sprintf(p->strbuf, "%04d-%02d-%02d",
4875 ((DATE_STRUCT *) p->param)->year,
4876 ((DATE_STRUCT *) p->param)->month,
4877 ((DATE_STRUCT *) p->param)->day);
4878 p->s4type = SQLITE4_TEXT;
4879 p->s4size = -1;
4880 p->s4val = p->strbuf;
4881 break;
4882 #ifdef SQL_C_TYPE_TIME
4883 case SQL_C_TYPE_TIME:
4884 #endif
4885 case SQL_C_TIME:
4886 sprintf(p->strbuf, "%02d:%02d:%02d",
4887 ((TIME_STRUCT *) p->param)->hour,
4888 ((TIME_STRUCT *) p->param)->minute,
4889 ((TIME_STRUCT *) p->param)->second);
4890 p->s4type = SQLITE4_TEXT;
4891 p->s4size = -1;
4892 p->s4val = p->strbuf;
4893 break;
4894 #ifdef SQL_C_TYPE_TIMESTAMP
4895 case SQL_C_TYPE_TIMESTAMP:
4896 #endif
4897 case SQL_C_TIMESTAMP:
4898 len = (int) ((TIMESTAMP_STRUCT *) p->param)->fraction;
4899 len /= 1000000;
4900 len = len % 1000;
4901 if (len < 0) {
4902 len = 0;
4903 }
4904 if (p->coldef && p->coldef <= 16) {
4905 sprintf(p->strbuf, "%04d-%02d-%02d %02d:%02d:00.000",
4906 ((TIMESTAMP_STRUCT *) p->param)->year,
4907 ((TIMESTAMP_STRUCT *) p->param)->month,
4908 ((TIMESTAMP_STRUCT *) p->param)->day,
4909 ((TIMESTAMP_STRUCT *) p->param)->hour,
4910 ((TIMESTAMP_STRUCT *) p->param)->minute);
4911 } else if (p->coldef && p->coldef <= 19) {
4912 sprintf(p->strbuf, "%04d-%02d-%02d %02d:%02d:%02d.000",
4913 ((TIMESTAMP_STRUCT *) p->param)->year,
4914 ((TIMESTAMP_STRUCT *) p->param)->month,
4915 ((TIMESTAMP_STRUCT *) p->param)->day,
4916 ((TIMESTAMP_STRUCT *) p->param)->hour,
4917 ((TIMESTAMP_STRUCT *) p->param)->minute,
4918 ((TIMESTAMP_STRUCT *) p->param)->second);
4919 } else {
4920 sprintf(p->strbuf, "%04d-%02d-%02d %02d:%02d:%02d.%03d",
4921 ((TIMESTAMP_STRUCT *) p->param)->year,
4922 ((TIMESTAMP_STRUCT *) p->param)->month,
4923 ((TIMESTAMP_STRUCT *) p->param)->day,
4924 ((TIMESTAMP_STRUCT *) p->param)->hour,
4925 ((TIMESTAMP_STRUCT *) p->param)->minute,
4926 ((TIMESTAMP_STRUCT *) p->param)->second,
4927 len);
4928 }
4929 p->s4type = SQLITE4_TEXT;
4930 p->s4size = -1;
4931 p->s4val = p->strbuf;
4932 break;
4933 default:
4934 error:
4935 setstat(s, -1, "unsupported parameter type",
4936 (*s->ov3) ? "07009" : "S1093");
4937 return SQL_ERROR;
4938 }
4939 return SQL_SUCCESS;
4940 }
4941
4942 /**
4943 * Internal bind parameter on HSTMT.
4944 * @param stmt statement handle
4945 * @param pnum parameter number, starting at 1
4946 * @param iotype input/output type of parameter
4947 * @param buftype type of host variable
4948 * @param ptype
4949 * @param coldef
4950 * @param scale
4951 * @param data pointer to host variable
4952 * @param buflen length of host variable
4953 * @param len output length pointer
4954 * @result ODBC error code
4955 */
4956
4957 static SQLRETURN
drvbindparam(SQLHSTMT stmt,SQLUSMALLINT pnum,SQLSMALLINT iotype,SQLSMALLINT buftype,SQLSMALLINT ptype,SQLUINTEGER coldef,SQLSMALLINT scale,SQLPOINTER data,SQLINTEGER buflen,SQLLEN * len)4958 drvbindparam(SQLHSTMT stmt, SQLUSMALLINT pnum, SQLSMALLINT iotype,
4959 SQLSMALLINT buftype, SQLSMALLINT ptype, SQLUINTEGER coldef,
4960 SQLSMALLINT scale,
4961 SQLPOINTER data, SQLINTEGER buflen, SQLLEN *len)
4962 {
4963 STMT *s;
4964 BINDPARM *p;
4965
4966 if (stmt == SQL_NULL_HSTMT) {
4967 return SQL_INVALID_HANDLE;
4968 }
4969 s = (STMT *) stmt;
4970 if (pnum == 0) {
4971 setstat(s, -1, "invalid parameter", (*s->ov3) ? "07009" : "S1093");
4972 return SQL_ERROR;
4973 }
4974 if (!data && !len) {
4975 setstat(s, -1, "invalid buffer", "HY003");
4976 return SQL_ERROR;
4977 }
4978 --pnum;
4979 if (s->bindparms) {
4980 if (pnum >= s->nbindparms) {
4981 BINDPARM *newparms;
4982
4983 newparms = xrealloc(s->bindparms,
4984 (pnum + 1) * sizeof (BINDPARM));
4985 if (!newparms) {
4986 outofmem:
4987 return nomem(s);
4988 }
4989 s->bindparms = newparms;
4990 memset(&s->bindparms[s->nbindparms], 0,
4991 (pnum + 1 - s->nbindparms) * sizeof (BINDPARM));
4992 s->nbindparms = pnum + 1;
4993 }
4994 } else {
4995 int npar = max(10, pnum + 1);
4996
4997 s->bindparms = xmalloc(npar * sizeof (BINDPARM));
4998 if (!s->bindparms) {
4999 goto outofmem;
5000 }
5001 memset(s->bindparms, 0, npar * sizeof (BINDPARM));
5002 s->nbindparms = npar;
5003 }
5004 switch (buftype) {
5005 case SQL_C_STINYINT:
5006 case SQL_C_UTINYINT:
5007 case SQL_C_TINYINT:
5008 #ifdef SQL_C_BIT
5009 case SQL_C_BIT:
5010 #endif
5011 buflen = sizeof (SQLCHAR);
5012 break;
5013 case SQL_C_SHORT:
5014 case SQL_C_USHORT:
5015 case SQL_C_SSHORT:
5016 buflen = sizeof (SQLSMALLINT);
5017 break;
5018 case SQL_C_SLONG:
5019 case SQL_C_ULONG:
5020 case SQL_C_LONG:
5021 buflen = sizeof (SQLINTEGER);
5022 break;
5023 case SQL_C_FLOAT:
5024 buflen = sizeof (float);
5025 break;
5026 case SQL_C_DOUBLE:
5027 buflen = sizeof (double);
5028 break;
5029 case SQL_C_TIMESTAMP:
5030 #ifdef SQL_C_TYPE_TIMESTAMP
5031 case SQL_C_TYPE_TIMESTAMP:
5032 #endif
5033 buflen = sizeof (TIMESTAMP_STRUCT);
5034 break;
5035 case SQL_C_TIME:
5036 #ifdef SQL_C_TYPE_TIME
5037 case SQL_C_TYPE_TIME:
5038 #endif
5039 buflen = sizeof (TIME_STRUCT);
5040 break;
5041 case SQL_C_DATE:
5042 #ifdef SQL_C_TYPE_DATE
5043 case SQL_C_TYPE_DATE:
5044 #endif
5045 buflen = sizeof (DATE_STRUCT);
5046 break;
5047 #ifdef SQL_C_UBIGINT
5048 case SQL_C_UBIGINT:
5049 buflen = sizeof (SQLBIGINT);
5050 break;
5051 #endif
5052 #ifdef SQL_C_SBIGINT
5053 case SQL_C_SBIGINT:
5054 buflen = sizeof (SQLBIGINT);
5055 break;
5056 #endif
5057 #ifdef SQL_C_BIGINT
5058 case SQL_C_BIGINT:
5059 buflen = sizeof (SQLBIGINT);
5060 break;
5061 #endif
5062 }
5063 p = &s->bindparms[pnum];
5064 p->type = buftype;
5065 p->stype = ptype;
5066 p->coldef = coldef;
5067 p->scale = scale;
5068 p->max = buflen;
5069 p->inc = buflen;
5070 p->lenp = p->lenp0 = len;
5071 p->offs = 0;
5072 p->len = 0;
5073 p->param0 = data;
5074 freep(&p->parbuf);
5075 p->param = p->param0;
5076 p->bound = 1;
5077 p->need = 0;
5078 return SQL_SUCCESS;
5079 }
5080
5081 /**
5082 * Bind parameter on HSTMT.
5083 * @param stmt statement handle
5084 * @param pnum parameter number, starting at 1
5085 * @param iotype input/output type of parameter
5086 * @param buftype type of host variable
5087 * @param ptype
5088 * @param coldef
5089 * @param scale
5090 * @param data pointer to host variable
5091 * @param buflen length of host variable
5092 * @param len output length pointer
5093 * @result ODBC error code
5094 */
5095
5096 SQLRETURN SQL_API
SQLBindParameter(SQLHSTMT stmt,SQLUSMALLINT pnum,SQLSMALLINT iotype,SQLSMALLINT buftype,SQLSMALLINT ptype,SQLULEN coldef,SQLSMALLINT scale,SQLPOINTER data,SQLLEN buflen,SQLLEN * len)5097 SQLBindParameter(SQLHSTMT stmt, SQLUSMALLINT pnum, SQLSMALLINT iotype,
5098 SQLSMALLINT buftype, SQLSMALLINT ptype, SQLULEN coldef,
5099 SQLSMALLINT scale,
5100 SQLPOINTER data, SQLLEN buflen, SQLLEN *len)
5101 {
5102 SQLRETURN ret;
5103
5104 HSTMT_LOCK(stmt);
5105 ret = drvbindparam(stmt, pnum, iotype, buftype, ptype, coldef,
5106 scale, data, buflen, len);
5107 HSTMT_UNLOCK(stmt);
5108 return ret;
5109 }
5110
5111 #ifndef HAVE_IODBC
5112 /**
5113 * Bind parameter on HSTMT.
5114 * @param stmt statement handle
5115 * @param pnum parameter number, starting at 1
5116 * @param vtype input/output type of parameter
5117 * @param ptype
5118 * @param lenprec
5119 * @param scale
5120 * @param val pointer to host variable
5121 * @param lenp output length pointer
5122 * @result ODBC error code
5123 */
5124
5125 SQLRETURN SQL_API
SQLBindParam(SQLHSTMT stmt,SQLUSMALLINT pnum,SQLSMALLINT vtype,SQLSMALLINT ptype,SQLULEN lenprec,SQLSMALLINT scale,SQLPOINTER val,SQLLEN * lenp)5126 SQLBindParam(SQLHSTMT stmt, SQLUSMALLINT pnum, SQLSMALLINT vtype,
5127 SQLSMALLINT ptype, SQLULEN lenprec,
5128 SQLSMALLINT scale, SQLPOINTER val,
5129 SQLLEN *lenp)
5130 {
5131 SQLRETURN ret;
5132
5133 HSTMT_LOCK(stmt);
5134 ret = drvbindparam(stmt, pnum, SQL_PARAM_INPUT, vtype, ptype,
5135 lenprec, scale, val, 0, lenp);
5136 HSTMT_UNLOCK(stmt);
5137 return ret;
5138 }
5139 #endif
5140
5141 /**
5142 * Return number of parameters.
5143 * @param stmt statement handle
5144 * @param nparam output parameter count
5145 * @result ODBC error code
5146 */
5147
5148 SQLRETURN SQL_API
SQLNumParams(SQLHSTMT stmt,SQLSMALLINT * nparam)5149 SQLNumParams(SQLHSTMT stmt, SQLSMALLINT *nparam)
5150 {
5151 STMT *s;
5152 SQLSMALLINT dummy;
5153
5154 HSTMT_LOCK(stmt);
5155 if (stmt == SQL_NULL_HSTMT) {
5156 return SQL_INVALID_HANDLE;
5157 }
5158 s = (STMT *) stmt;
5159 if (!nparam) {
5160 nparam = &dummy;
5161 }
5162 *nparam = s->nparams;
5163 HSTMT_UNLOCK(stmt);
5164 return SQL_SUCCESS;
5165 }
5166
5167 /**
5168 * Setup parameter buffer for deferred parameter.
5169 * @param s pointer to STMT
5170 * @param p pointer to BINDPARM
5171 * @result ODBC error code (success indicated by SQL_NEED_DATA)
5172 */
5173
5174 static SQLRETURN
setupparbuf(STMT * s,BINDPARM * p)5175 setupparbuf(STMT *s, BINDPARM *p)
5176 {
5177 if (!p->parbuf) {
5178 if (*p->lenp == SQL_DATA_AT_EXEC) {
5179 p->len = p->max;
5180 } else {
5181 p->len = SQL_LEN_DATA_AT_EXEC(*p->lenp);
5182 }
5183 if (p->len < 0 && p->len != SQL_NTS &&
5184 p->len != SQL_NULL_DATA) {
5185 setstat(s, -1, "invalid length", "HY009");
5186 return SQL_ERROR;
5187 }
5188 if (p->len >= 0) {
5189 p->parbuf = xmalloc(p->len + 2);
5190 if (!p->parbuf) {
5191 return nomem(s);
5192 }
5193 p->param = p->parbuf;
5194 } else {
5195 p->param = NULL;
5196 }
5197 }
5198 return SQL_NEED_DATA;
5199 }
5200
5201 /**
5202 * Retrieve next parameter for sending data to executing query.
5203 * @param stmt statement handle
5204 * @param pind pointer to output parameter indicator
5205 * @result ODBC error code
5206 */
5207
5208 SQLRETURN SQL_API
SQLParamData(SQLHSTMT stmt,SQLPOINTER * pind)5209 SQLParamData(SQLHSTMT stmt, SQLPOINTER *pind)
5210 {
5211 STMT *s;
5212 int i;
5213 SQLPOINTER dummy;
5214 SQLRETURN ret;
5215 BINDPARM *p;
5216
5217 HSTMT_LOCK(stmt);
5218 if (stmt == SQL_NULL_HSTMT) {
5219 return SQL_INVALID_HANDLE;
5220 }
5221 s = (STMT *) stmt;
5222 if (!pind) {
5223 pind = &dummy;
5224 }
5225 if (s->pdcount < s->nparams) {
5226 s->pdcount++;
5227 }
5228 for (i = 0; i < s->pdcount; i++) {
5229 p = &s->bindparms[i];
5230 if (p->need > 0) {
5231 int type = mapdeftype(p->type, p->stype, -1, s->nowchar[0]);
5232
5233 p->need = (type == SQL_C_CHAR || type == SQL_C_WCHAR) ? -1 : 0;
5234 }
5235 }
5236 for (; i < s->nparams; i++) {
5237 p = &s->bindparms[i];
5238 if (p->need > 0) {
5239 *pind = (SQLPOINTER) p->param0;
5240 ret = setupparbuf(s, p);
5241 s->pdcount = i;
5242 goto done;
5243 }
5244 }
5245 ret = drvexecute(stmt, 0);
5246 done:
5247 HSTMT_UNLOCK(stmt);
5248 return ret;
5249 }
5250
5251 /**
5252 * Return information about parameter.
5253 * @param stmt statement handle
5254 * @param pnum parameter number, starting at 1
5255 * @param dtype output type indicator
5256 * @param size output size indicator
5257 * @param decdigits output number of digits
5258 * @param nullable output NULL allowed indicator
5259 * @result ODBC error code
5260 */
5261
5262 SQLRETURN SQL_API
SQLDescribeParam(SQLHSTMT stmt,SQLUSMALLINT pnum,SQLSMALLINT * dtype,SQLULEN * size,SQLSMALLINT * decdigits,SQLSMALLINT * nullable)5263 SQLDescribeParam(SQLHSTMT stmt, SQLUSMALLINT pnum, SQLSMALLINT *dtype,
5264 SQLULEN *size, SQLSMALLINT *decdigits, SQLSMALLINT *nullable)
5265 {
5266 STMT *s;
5267 SQLRETURN ret = SQL_ERROR;
5268
5269 HSTMT_LOCK(stmt);
5270 if (stmt == SQL_NULL_HSTMT) {
5271 return SQL_INVALID_HANDLE;
5272 }
5273 s = (STMT *) stmt;
5274 --pnum;
5275 if (pnum >= s->nparams) {
5276 setstat(s, -1, "invalid parameter index",
5277 (*s->ov3) ? "HY000" : "S1000");
5278 goto done;
5279 }
5280 if (dtype) {
5281 #ifdef SQL_LONGVARCHAR
5282 #ifdef WINTERFACE
5283 *dtype = s->nowchar[0] ? SQL_LONGVARCHAR : SQL_WLONGVARCHAR;
5284 #else
5285 *dtype = SQL_LONGVARCHAR;
5286 #endif
5287 #else
5288 #ifdef WINTERFACE
5289 *dtype = s->nowchar[0] ? SQL_VARCHAR : SQL_WVARCHAR;
5290 #else
5291 *dtype = SQL_VARCHAR;
5292 #endif
5293 #endif
5294 }
5295 if (size) {
5296 #ifdef SQL_LONGVARCHAR
5297 *size = 65536;
5298 #else
5299 *size = 255;
5300 #endif
5301 }
5302 if (decdigits) {
5303 *decdigits = 0;
5304 }
5305 if (nullable) {
5306 *nullable = SQL_NULLABLE;
5307 }
5308 ret = SQL_SUCCESS;
5309 done:
5310 HSTMT_UNLOCK(stmt);
5311 return ret;
5312 }
5313
5314 /**
5315 * Set information on parameter.
5316 * @param stmt statement handle
5317 * @param par parameter number, starting at 1
5318 * @param type type of host variable
5319 * @param sqltype
5320 * @param coldef
5321 * @param scale
5322 * @param val pointer to host variable
5323 * @param nval output length pointer
5324 * @result ODBC error code
5325 */
5326
5327 SQLRETURN SQL_API
SQLSetParam(SQLHSTMT stmt,SQLUSMALLINT par,SQLSMALLINT type,SQLSMALLINT sqltype,SQLULEN coldef,SQLSMALLINT scale,SQLPOINTER val,SQLLEN * nval)5328 SQLSetParam(SQLHSTMT stmt, SQLUSMALLINT par, SQLSMALLINT type,
5329 SQLSMALLINT sqltype, SQLULEN coldef,
5330 SQLSMALLINT scale, SQLPOINTER val, SQLLEN *nval)
5331 {
5332 SQLRETURN ret;
5333
5334 HSTMT_LOCK(stmt);
5335 ret = drvbindparam(stmt, par, SQL_PARAM_INPUT,
5336 type, sqltype, coldef, scale, val,
5337 SQL_SETPARAM_VALUE_MAX, nval);
5338 HSTMT_UNLOCK(stmt);
5339 return ret;
5340 }
5341
5342 /**
5343 * Function not implemented.
5344 */
5345
5346 SQLRETURN SQL_API
SQLParamOptions(SQLHSTMT stmt,SQLULEN rows,SQLULEN * rowp)5347 SQLParamOptions(SQLHSTMT stmt, SQLULEN rows, SQLULEN *rowp)
5348 {
5349 SQLRETURN ret;
5350
5351 HSTMT_LOCK(stmt);
5352 ret = drvunimplstmt(stmt);
5353 HSTMT_UNLOCK(stmt);
5354 return ret;
5355 }
5356
5357 #ifndef WINTERFACE
5358 /**
5359 * Function not implemented.
5360 */
5361
5362 SQLRETURN SQL_API
SQLGetDescField(SQLHDESC handle,SQLSMALLINT recno,SQLSMALLINT fieldid,SQLPOINTER value,SQLINTEGER buflen,SQLINTEGER * strlen)5363 SQLGetDescField(SQLHDESC handle, SQLSMALLINT recno,
5364 SQLSMALLINT fieldid, SQLPOINTER value,
5365 SQLINTEGER buflen, SQLINTEGER *strlen)
5366 {
5367 return SQL_ERROR;
5368 }
5369 #endif
5370
5371 #ifdef WINTERFACE
5372 /**
5373 * Function not implemented.
5374 */
5375
5376 SQLRETURN SQL_API
SQLGetDescFieldW(SQLHDESC handle,SQLSMALLINT recno,SQLSMALLINT fieldid,SQLPOINTER value,SQLINTEGER buflen,SQLINTEGER * strlen)5377 SQLGetDescFieldW(SQLHDESC handle, SQLSMALLINT recno,
5378 SQLSMALLINT fieldid, SQLPOINTER value,
5379 SQLINTEGER buflen, SQLINTEGER *strlen)
5380 {
5381 return SQL_ERROR;
5382 }
5383 #endif
5384
5385 #ifndef WINTERFACE
5386 /**
5387 * Function not implemented.
5388 */
5389
5390 SQLRETURN SQL_API
SQLSetDescField(SQLHDESC handle,SQLSMALLINT recno,SQLSMALLINT fieldid,SQLPOINTER value,SQLINTEGER buflen)5391 SQLSetDescField(SQLHDESC handle, SQLSMALLINT recno,
5392 SQLSMALLINT fieldid, SQLPOINTER value,
5393 SQLINTEGER buflen)
5394 {
5395 return SQL_ERROR;
5396 }
5397 #endif
5398
5399 #ifdef WINTERFACE
5400 /**
5401 * Function not implemented.
5402 */
5403
5404 SQLRETURN SQL_API
SQLSetDescFieldW(SQLHDESC handle,SQLSMALLINT recno,SQLSMALLINT fieldid,SQLPOINTER value,SQLINTEGER buflen)5405 SQLSetDescFieldW(SQLHDESC handle, SQLSMALLINT recno,
5406 SQLSMALLINT fieldid, SQLPOINTER value,
5407 SQLINTEGER buflen)
5408 {
5409 return SQL_ERROR;
5410 }
5411 #endif
5412
5413 #ifndef WINTERFACE
5414 /**
5415 * Function not implemented.
5416 */
5417
5418 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)5419 SQLGetDescRec(SQLHDESC handle, SQLSMALLINT recno,
5420 SQLCHAR *name, SQLSMALLINT buflen,
5421 SQLSMALLINT *strlen, SQLSMALLINT *type,
5422 SQLSMALLINT *subtype, SQLLEN *len,
5423 SQLSMALLINT *prec, SQLSMALLINT *scale,
5424 SQLSMALLINT *nullable)
5425 {
5426 return SQL_ERROR;
5427 }
5428 #endif
5429
5430 #ifdef WINTERFACE
5431 /**
5432 * Function not implemented.
5433 */
5434
5435 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)5436 SQLGetDescRecW(SQLHDESC handle, SQLSMALLINT recno,
5437 SQLWCHAR *name, SQLSMALLINT buflen,
5438 SQLSMALLINT *strlen, SQLSMALLINT *type,
5439 SQLSMALLINT *subtype, SQLLEN *len,
5440 SQLSMALLINT *prec, SQLSMALLINT *scale,
5441 SQLSMALLINT *nullable)
5442 {
5443 return SQL_ERROR;
5444 }
5445 #endif
5446
5447 /**
5448 * Function not implemented.
5449 */
5450
5451 SQLRETURN SQL_API
SQLSetDescRec(SQLHDESC handle,SQLSMALLINT recno,SQLSMALLINT type,SQLSMALLINT subtype,SQLLEN len,SQLSMALLINT prec,SQLSMALLINT scale,SQLPOINTER data,SQLLEN * strlen,SQLLEN * indicator)5452 SQLSetDescRec(SQLHDESC handle, SQLSMALLINT recno,
5453 SQLSMALLINT type, SQLSMALLINT subtype,
5454 SQLLEN len, SQLSMALLINT prec,
5455 SQLSMALLINT scale, SQLPOINTER data,
5456 SQLLEN *strlen, SQLLEN *indicator)
5457 {
5458 return SQL_ERROR;
5459 }
5460
5461 /**
5462 * Setup empty result set from constant column specification.
5463 * @param stmt statement handle
5464 * @param colspec column specification array (default, ODBC2)
5465 * @param ncols number of columns (default, ODBC2)
5466 * @param colspec3 column specification array (ODBC3)
5467 * @param ncols4 number of columns (ODBC3)
5468 * @param nret returns number of columns
5469 * @result ODBC error code
5470 */
5471
5472 static SQLRETURN
mkresultset(HSTMT stmt,COL * colspec,int ncols,COL * colspec3,int ncols4,int * nret)5473 mkresultset(HSTMT stmt, COL *colspec, int ncols, COL *colspec3,
5474 int ncols4, int *nret)
5475 {
5476 STMT *s;
5477 DBC *d;
5478
5479 if (stmt == SQL_NULL_HSTMT) {
5480 return SQL_INVALID_HANDLE;
5481 }
5482 s = (STMT *) stmt;
5483 if (s->dbc == SQL_NULL_HDBC) {
5484 noconn:
5485 return noconn(s);
5486 }
5487 d = (DBC *) s->dbc;
5488 if (!d->sqlite) {
5489 goto noconn;
5490 }
5491 s4stmt_end_if(s);
5492 freeresult(s, 0);
5493 if (colspec3 && *s->ov3) {
5494 s->ncols = ncols4;
5495 s->cols = colspec3;
5496 } else {
5497 s->ncols = ncols;
5498 s->cols = colspec;
5499 }
5500 mkbindcols(s, s->ncols);
5501 s->nowchar[1] = 1;
5502 s->nrows = 0;
5503 s->rowp = s->rowprs = -1;
5504 s->isselect = -1;
5505 if (nret) {
5506 *nret = s->ncols;
5507 }
5508 return SQL_SUCCESS;
5509 }
5510
5511 /**
5512 * Columns for result set of SQLTablePrivileges().
5513 */
5514
5515 static COL tablePrivSpec2[] = {
5516 { "SYSTEM", "TABLEPRIV", "TABLE_QUALIFIER", SCOL_VARCHAR, 50 },
5517 { "SYSTEM", "TABLEPRIV", "TABLE_OWNER", SCOL_VARCHAR, 50 },
5518 { "SYSTEM", "TABLEPRIV", "TABLE_NAME", SCOL_VARCHAR, 255 },
5519 { "SYSTEM", "TABLEPRIV", "GRANTOR", SCOL_VARCHAR, 50 },
5520 { "SYSTEM", "TABLEPRIV", "GRANTEE", SCOL_VARCHAR, 50 },
5521 { "SYSTEM", "TABLEPRIV", "PRIVILEGE", SCOL_VARCHAR, 50 },
5522 { "SYSTEM", "TABLEPRIV", "IS_GRANTABLE", SCOL_VARCHAR, 50 }
5523 };
5524
5525 static COL tablePrivSpec3[] = {
5526 { "SYSTEM", "TABLEPRIV", "TABLE_CAT", SCOL_VARCHAR, 50 },
5527 { "SYSTEM", "TABLEPRIV", "TABLE_SCHEM", SCOL_VARCHAR, 50 },
5528 { "SYSTEM", "TABLEPRIV", "TABLE_NAME", SCOL_VARCHAR, 255 },
5529 { "SYSTEM", "TABLEPRIV", "GRANTOR", SCOL_VARCHAR, 50 },
5530 { "SYSTEM", "TABLEPRIV", "GRANTEE", SCOL_VARCHAR, 50 },
5531 { "SYSTEM", "TABLEPRIV", "PRIVILEGE", SCOL_VARCHAR, 50 },
5532 { "SYSTEM", "TABLEPRIV", "IS_GRANTABLE", SCOL_VARCHAR, 50 }
5533 };
5534
5535 /**
5536 * Retrieve privileges on tables and/or views.
5537 * @param stmt statement handle
5538 * @param cat catalog name/pattern or NULL
5539 * @param catLen length of catalog name/pattern or SQL_NTS
5540 * @param schema schema name/pattern or NULL
5541 * @param schemaLen length of schema name/pattern or SQL_NTS
5542 * @param table table name/pattern or NULL
5543 * @param tableLen length of table name/pattern or SQL_NTS
5544 * @result ODBC error code
5545 */
5546
5547 static SQLRETURN
drvtableprivileges(SQLHSTMT stmt,SQLCHAR * cat,SQLSMALLINT catLen,SQLCHAR * schema,SQLSMALLINT schemaLen,SQLCHAR * table,SQLSMALLINT tableLen)5548 drvtableprivileges(SQLHSTMT stmt,
5549 SQLCHAR *cat, SQLSMALLINT catLen,
5550 SQLCHAR *schema, SQLSMALLINT schemaLen,
5551 SQLCHAR *table, SQLSMALLINT tableLen)
5552 {
5553 SQLRETURN ret;
5554 STMT *s;
5555 DBC *d;
5556 int ncols, rc, size, npatt;
5557 char *errp = NULL, *sql, tname[512];
5558
5559 ret = mkresultset(stmt, tablePrivSpec2, array_size(tablePrivSpec2),
5560 tablePrivSpec3, array_size(tablePrivSpec3), NULL);
5561 if (ret != SQL_SUCCESS) {
5562 return ret;
5563 }
5564 s = (STMT *) stmt;
5565 d = (DBC *) s->dbc;
5566 if (cat && (catLen > 0 || catLen == SQL_NTS) && cat[0] == '%') {
5567 table = NULL;
5568 goto doit;
5569 }
5570 if (schema && (schemaLen > 0 || schemaLen == SQL_NTS) &&
5571 schema[0] == '%') {
5572 if ((!cat || catLen == 0 || !cat[0]) &&
5573 (!table || tableLen == 0 || !table[0])) {
5574 table = NULL;
5575 goto doit;
5576 }
5577 }
5578 doit:
5579 if (!table) {
5580 size = 1;
5581 tname[0] = '%';
5582 } else {
5583 if (tableLen == SQL_NTS) {
5584 size = sizeof (tname) - 1;
5585 } else {
5586 size = min(sizeof (tname) - 1, tableLen);
5587 }
5588 strncpy(tname, (char *) table, size);
5589 }
5590 tname[size] = '\0';
5591 npatt = unescpat(tname);
5592 #if defined(_WIN32) || defined(_WIN64)
5593 if (npatt) {
5594 sql = sqlite4_mprintf(0, "select %s as 'TABLE_QUALIFIER', "
5595 "%s as 'TABLE_OWNER', "
5596 "tbl_name as 'TABLE_NAME', "
5597 "'' as 'GRANTOR', "
5598 "'' as 'GRANTEE', "
5599 "'SELECT' AS 'PRIVILEGE', "
5600 "NULL as 'IS_GRANTABLE' "
5601 "from sqlite_master where "
5602 "(type = 'table' or type = 'view') "
5603 "and tbl_name like %Q "
5604 "UNION "
5605 "select %s as 'TABLE_QUALIFIER', "
5606 "%s as 'TABLE_OWNER', "
5607 "tbl_name as 'TABLE_NAME', "
5608 "'' as 'GRANTOR', "
5609 "'' as 'GRANTEE', "
5610 "'UPDATE' AS 'PRIVILEGE', "
5611 "NULL as 'IS_GRANTABLE' "
5612 "from sqlite_master where "
5613 "(type = 'table' or type = 'view') "
5614 "and tbl_name like %Q "
5615 "UNION "
5616 "select %s as 'TABLE_QUALIFIER', "
5617 "%s as 'TABLE_OWNER', "
5618 "tbl_name as 'TABLE_NAME', "
5619 "'' as 'GRANTOR', "
5620 "'' as 'GRANTEE', "
5621 "'DELETE' AS 'PRIVILEGE', "
5622 "NULL as 'IS_GRANTABLE' "
5623 "from sqlite_master where "
5624 "(type = 'table' or type = 'view') "
5625 "and tbl_name like %Q "
5626 "UNION "
5627 "select %s as 'TABLE_QUALIFIER', "
5628 "%s as 'TABLE_OWNER', "
5629 "tbl_name as 'TABLE_NAME', "
5630 "'' as 'GRANTOR', "
5631 "'' as 'GRANTEE', "
5632 "'INSERT' AS 'PRIVILEGE', "
5633 "NULL as 'IS_GRANTABLE' "
5634 "from sqlite_master where "
5635 "(type = 'table' or type = 'view') "
5636 "and tbl_name like %Q "
5637 "UNION "
5638 "select %s as 'TABLE_QUALIFIER', "
5639 "%s as 'TABLE_OWNER', "
5640 "tbl_name as 'TABLE_NAME', "
5641 "'' as 'GRANTOR', "
5642 "'' as 'GRANTEE', "
5643 "'REFERENCES' AS 'PRIVILEGE', "
5644 "NULL as 'IS_GRANTABLE' "
5645 "from sqlite_master where "
5646 "(type = 'table' or type = 'view') "
5647 "and tbl_name like %Q",
5648 d->xcelqrx ? "'main'" : "NULL",
5649 d->xcelqrx ? "''" : "NULL",
5650 tname,
5651 d->xcelqrx ? "'main'" : "NULL",
5652 d->xcelqrx ? "''" : "NULL",
5653 tname,
5654 d->xcelqrx ? "'main'" : "NULL",
5655 d->xcelqrx ? "''" : "NULL",
5656 tname,
5657 d->xcelqrx ? "'main'" : "NULL",
5658 d->xcelqrx ? "''" : "NULL",
5659 tname,
5660 d->xcelqrx ? "'main'" : "NULL",
5661 d->xcelqrx ? "''" : "NULL",
5662 tname);
5663 } else {
5664 sql = sqlite4_mprintf(0, "select %s as 'TABLE_QUALIFIER', "
5665 "%s as 'TABLE_OWNER', "
5666 "tbl_name as 'TABLE_NAME', "
5667 "'' as 'GRANTOR', "
5668 "'' as 'GRANTEE', "
5669 "'SELECT' AS 'PRIVILEGE', "
5670 "NULL as 'IS_GRANTABLE' "
5671 "from sqlite_master where "
5672 "(type = 'table' or type = 'view') "
5673 "and lower(tbl_name) = lower(%Q) "
5674 "UNION "
5675 "select %s as 'TABLE_QUALIFIER', "
5676 "%s as 'TABLE_OWNER', "
5677 "tbl_name as 'TABLE_NAME', "
5678 "'' as 'GRANTOR', "
5679 "'' as 'GRANTEE', "
5680 "'UPDATE' AS 'PRIVILEGE', "
5681 "NULL as 'IS_GRANTABLE' "
5682 "from sqlite_master where "
5683 "(type = 'table' or type = 'view') "
5684 "and lower(tbl_name) = lower(%Q) "
5685 "UNION "
5686 "select %s as 'TABLE_QUALIFIER', "
5687 "%s as 'TABLE_OWNER', "
5688 "tbl_name as 'TABLE_NAME', "
5689 "'' as 'GRANTOR', "
5690 "'' as 'GRANTEE', "
5691 "'DELETE' AS 'PRIVILEGE', "
5692 "NULL as 'IS_GRANTABLE' "
5693 "from sqlite_master where "
5694 "(type = 'table' or type = 'view') "
5695 "and lower(tbl_name) = lower(%Q) "
5696 "UNION "
5697 "select %s as 'TABLE_QUALIFIER', "
5698 "%s as 'TABLE_OWNER', "
5699 "tbl_name as 'TABLE_NAME', "
5700 "'' as 'GRANTOR', "
5701 "'' as 'GRANTEE', "
5702 "'INSERT' AS 'PRIVILEGE', "
5703 "NULL as 'IS_GRANTABLE' "
5704 "from sqlite_master where "
5705 "(type = 'table' or type = 'view') "
5706 "and lower(tbl_name) = lower(%Q) "
5707 "UNION "
5708 "select %s as 'TABLE_QUALIFIER', "
5709 "%s as 'TABLE_OWNER', "
5710 "tbl_name as 'TABLE_NAME', "
5711 "'' as 'GRANTOR', "
5712 "'' as 'GRANTEE', "
5713 "'REFERENCES' AS 'PRIVILEGE', "
5714 "NULL as 'IS_GRANTABLE' "
5715 "from sqlite_master where "
5716 "(type = 'table' or type = 'view') "
5717 "and lower(tbl_name) = lower(%Q)",
5718 d->xcelqrx ? "'main'" : "NULL",
5719 d->xcelqrx ? "''" : "NULL",
5720 tname,
5721 d->xcelqrx ? "'main'" : "NULL",
5722 d->xcelqrx ? "''" : "NULL",
5723 tname,
5724 d->xcelqrx ? "'main'" : "NULL",
5725 d->xcelqrx ? "''" : "NULL",
5726 tname,
5727 d->xcelqrx ? "'main'" : "NULL",
5728 d->xcelqrx ? "''" : "NULL",
5729 tname,
5730 d->xcelqrx ? "'main'" : "NULL",
5731 d->xcelqrx ? "''" : "NULL",
5732 tname);
5733 }
5734 #else
5735 if (npatt) {
5736 sql = sqlite4_mprintf(0, "select NULL as 'TABLE_QUALIFIER', "
5737 "NULL as 'TABLE_OWNER', "
5738 "tbl_name as 'TABLE_NAME', "
5739 "'' as 'GRANTOR', "
5740 "'' as 'GRANTEE', "
5741 "'SELECT' AS 'PRIVILEGE', "
5742 "NULL as 'IS_GRANTABLE' "
5743 "from sqlite_master where "
5744 "(type = 'table' or type = 'view') "
5745 "and tbl_name like %Q "
5746 "UNION "
5747 "select NULL as 'TABLE_QUALIFIER', "
5748 "NULL as 'TABLE_OWNER', "
5749 "tbl_name as 'TABLE_NAME', "
5750 "'' as 'GRANTOR', "
5751 "'' as 'GRANTEE', "
5752 "'UPDATE' AS 'PRIVILEGE', "
5753 "NULL as 'IS_GRANTABLE' "
5754 "from sqlite_master where "
5755 "(type = 'table' or type = 'view') "
5756 "and tbl_name like %Q "
5757 "UNION "
5758 "select NULL as 'TABLE_QUALIFIER', "
5759 "NULL as 'TABLE_OWNER', "
5760 "tbl_name as 'TABLE_NAME', "
5761 "'' as 'GRANTOR', "
5762 "'' as 'GRANTEE', "
5763 "'DELETE' AS 'PRIVILEGE', "
5764 "NULL as 'IS_GRANTABLE' "
5765 "from sqlite_master where "
5766 "(type = 'table' or type = 'view') "
5767 "and tbl_name like %Q "
5768 "UNION "
5769 "select NULL as 'TABLE_QUALIFIER', "
5770 "NULL as 'TABLE_OWNER', "
5771 "tbl_name as 'TABLE_NAME', "
5772 "'' as 'GRANTOR', "
5773 "'' as 'GRANTEE', "
5774 "'INSERT' AS 'PRIVILEGE', "
5775 "NULL as 'IS_GRANTABLE' "
5776 "from sqlite_master where "
5777 "(type = 'table' or type = 'view') "
5778 "and tbl_name like %Q "
5779 "UNION "
5780 "select NULL as 'TABLE_QUALIFIER', "
5781 "NULL as 'TABLE_OWNER', "
5782 "tbl_name as 'TABLE_NAME', "
5783 "'' as 'GRANTOR', "
5784 "'' as 'GRANTEE', "
5785 "'REFERENCES' AS 'PRIVILEGE', "
5786 "NULL as 'IS_GRANTABLE' "
5787 "from sqlite_master where "
5788 "(type = 'table' or type = 'view') "
5789 "and tbl_name like %Q",
5790 tname, tname, tname, tname, tname);
5791 } else {
5792 sql = sqlite4_mprintf(0, "select NULL as 'TABLE_QUALIFIER', "
5793 "NULL as 'TABLE_OWNER', "
5794 "tbl_name as 'TABLE_NAME', "
5795 "'' as 'GRANTOR', "
5796 "'' as 'GRANTEE', "
5797 "'SELECT' AS 'PRIVILEGE', "
5798 "NULL as 'IS_GRANTABLE' "
5799 "from sqlite_master where "
5800 "(type = 'table' or type = 'view') "
5801 "and lower(tbl_name) = lower(%Q) "
5802 "UNION "
5803 "select NULL as 'TABLE_QUALIFIER', "
5804 "NULL as 'TABLE_OWNER', "
5805 "tbl_name as 'TABLE_NAME', "
5806 "'' as 'GRANTOR', "
5807 "'' as 'GRANTEE', "
5808 "'UPDATE' AS 'PRIVILEGE', "
5809 "NULL as 'IS_GRANTABLE' "
5810 "from sqlite_master where "
5811 "(type = 'table' or type = 'view') "
5812 "and lower(tbl_name) = lower(%Q) "
5813 "UNION "
5814 "select NULL as 'TABLE_QUALIFIER', "
5815 "NULL as 'TABLE_OWNER', "
5816 "tbl_name as 'TABLE_NAME', "
5817 "'' as 'GRANTOR', "
5818 "'' as 'GRANTEE', "
5819 "'DELETE' AS 'PRIVILEGE', "
5820 "NULL as 'IS_GRANTABLE' "
5821 "from sqlite_master where "
5822 "(type = 'table' or type = 'view') "
5823 "and lower(tbl_name) = lower(%Q) "
5824 "UNION "
5825 "select NULL as 'TABLE_QUALIFIER', "
5826 "NULL as 'TABLE_OWNER', "
5827 "tbl_name as 'TABLE_NAME', "
5828 "'' as 'GRANTOR', "
5829 "'' as 'GRANTEE', "
5830 "'INSERT' AS 'PRIVILEGE', "
5831 "NULL as 'IS_GRANTABLE' "
5832 "from sqlite_master where "
5833 "(type = 'table' or type = 'view') "
5834 "and lower(tbl_name) = lower(%Q) "
5835 "UNION "
5836 "select NULL as 'TABLE_QUALIFIER', "
5837 "NULL as 'TABLE_OWNER', "
5838 "tbl_name as 'TABLE_NAME', "
5839 "'' as 'GRANTOR', "
5840 "'' as 'GRANTEE', "
5841 "'REFERENCES' AS 'PRIVILEGE', "
5842 "NULL as 'IS_GRANTABLE' "
5843 "from sqlite_master where "
5844 "(type = 'table' or type = 'view') "
5845 "and lower(tbl_name) = lower(%Q)",
5846 tname, tname, tname, tname, tname);
5847 }
5848 #endif
5849 if (!sql) {
5850 return nomem(s);
5851 }
5852 ret = starttran(s);
5853 if (ret != SQL_SUCCESS) {
5854 sqlite4_free(0, sql);
5855 return ret;
5856 }
5857 dbtraceapi(d, "sqlite4_get_table", sql);
5858 rc = sqlite4_get_table(d->sqlite, sql, &s->rows, &s->nrows, &ncols, &errp);
5859 sqlite4_free(0, sql);
5860 if (rc == SQLITE4_OK) {
5861 if (ncols != s->ncols) {
5862 freeresult(s, 0);
5863 s->nrows = 0;
5864 } else {
5865 s->rowfree = freerows;
5866 }
5867 } else {
5868 s->nrows = 0;
5869 s->rows = NULL;
5870 s->rowfree = NULL;
5871 }
5872 if (errp) {
5873 sqlite4_free(0, errp);
5874 errp = NULL;
5875 }
5876 s->rowp = s->rowprs = -1;
5877 return SQL_SUCCESS;
5878 }
5879
5880 #if !defined(WINTERFACE) || (defined(HAVE_UNIXODBC) && (HAVE_UNIXODBC))
5881 /**
5882 * Retrieve privileges on tables and/or views.
5883 * @param stmt statement handle
5884 * @param catalog catalog name/pattern or NULL
5885 * @param catalogLen length of catalog name/pattern or SQL_NTS
5886 * @param schema schema name/pattern or NULL
5887 * @param schemaLen length of schema name/pattern or SQL_NTS
5888 * @param table table name/pattern or NULL
5889 * @param tableLen length of table name/pattern or SQL_NTS
5890 * @result ODBC error code
5891 */
5892
5893 SQLRETURN SQL_API
SQLTablePrivileges(SQLHSTMT stmt,SQLCHAR * catalog,SQLSMALLINT catalogLen,SQLCHAR * schema,SQLSMALLINT schemaLen,SQLCHAR * table,SQLSMALLINT tableLen)5894 SQLTablePrivileges(SQLHSTMT stmt,
5895 SQLCHAR *catalog, SQLSMALLINT catalogLen,
5896 SQLCHAR *schema, SQLSMALLINT schemaLen,
5897 SQLCHAR *table, SQLSMALLINT tableLen)
5898 {
5899 #if defined(_WIN32) || defined(_WIN64)
5900 char *c = NULL, *s = NULL, *t = NULL;
5901 #endif
5902 SQLRETURN ret;
5903
5904 HSTMT_LOCK(stmt);
5905 #if defined(_WIN32) || defined(_WIN64)
5906 if (!((STMT *) stmt)->oemcp[0]) {
5907 ret = drvtableprivileges(stmt, catalog, catalogLen, schema, schemaLen,
5908 table, tableLen);
5909 goto done2;
5910 }
5911 if (catalog) {
5912 c = wmb_to_utf_c((char *) catalog, catalogLen);
5913 if (!c) {
5914 ret = nomem((STMT *) stmt);
5915 goto done;
5916 }
5917 }
5918 if (schema) {
5919 s = wmb_to_utf_c((char *) schema, schemaLen);
5920 if (!s) {
5921 ret = nomem((STMT *) stmt);
5922 goto done;
5923 }
5924 }
5925 if (table) {
5926 t = wmb_to_utf_c((char *) table, tableLen);
5927 if (!t) {
5928 ret = nomem((STMT *) stmt);
5929 goto done;
5930 }
5931 }
5932 ret = drvtableprivileges(stmt, (SQLCHAR *) c, SQL_NTS,
5933 (SQLCHAR *) s, SQL_NTS,
5934 (SQLCHAR *) t, SQL_NTS);
5935 #else
5936 ret = drvtableprivileges(stmt, catalog, catalogLen, schema, schemaLen,
5937 table, tableLen);
5938 #endif
5939 #if defined(_WIN32) || defined(_WIN64)
5940 done:
5941 uc_free(t);
5942 uc_free(s);
5943 uc_free(c);
5944 done2:
5945 ;
5946 #endif
5947 HSTMT_UNLOCK(stmt);
5948 return ret;
5949 }
5950 #endif
5951
5952 #if !defined(HAVE_UNIXODBC) || !(HAVE_UNIXODBC)
5953 #ifdef WINTERFACE
5954 /**
5955 * Retrieve privileges on tables and/or views (UNICODE version).
5956 * @param stmt statement handle
5957 * @param catalog catalog name/pattern or NULL
5958 * @param catalogLen length of catalog name/pattern or SQL_NTS
5959 * @param schema schema name/pattern or NULL
5960 * @param schemaLen length of schema name/pattern or SQL_NTS
5961 * @param table table name/pattern or NULL
5962 * @param tableLen length of table name/pattern or SQL_NTS
5963 * @result ODBC error code
5964 */
5965
5966 SQLRETURN SQL_API
SQLTablePrivilegesW(SQLHSTMT stmt,SQLWCHAR * catalog,SQLSMALLINT catalogLen,SQLWCHAR * schema,SQLSMALLINT schemaLen,SQLWCHAR * table,SQLSMALLINT tableLen)5967 SQLTablePrivilegesW(SQLHSTMT stmt,
5968 SQLWCHAR *catalog, SQLSMALLINT catalogLen,
5969 SQLWCHAR *schema, SQLSMALLINT schemaLen,
5970 SQLWCHAR *table, SQLSMALLINT tableLen)
5971 {
5972 char *c = NULL, *s = NULL, *t = NULL;
5973 SQLRETURN ret;
5974
5975 HSTMT_LOCK(stmt);
5976 if (catalog) {
5977 c = uc_to_utf_c(catalog, catalogLen);
5978 if (!c) {
5979 ret = nomem((STMT *) stmt);
5980 goto done;
5981 }
5982 }
5983 if (schema) {
5984 s = uc_to_utf_c(schema, schemaLen);
5985 if (!s) {
5986 ret = nomem((STMT *) stmt);
5987 goto done;
5988 }
5989 }
5990 if (table) {
5991 t = uc_to_utf_c(table, tableLen);
5992 if (!t) {
5993 ret = nomem((STMT *) stmt);
5994 goto done;
5995 }
5996 }
5997 ret = drvtableprivileges(stmt, (SQLCHAR *) c, SQL_NTS,
5998 (SQLCHAR *) s, SQL_NTS,
5999 (SQLCHAR *) t, SQL_NTS);
6000 done:
6001 uc_free(t);
6002 uc_free(s);
6003 uc_free(c);
6004 HSTMT_UNLOCK(stmt);
6005 return ret;
6006 }
6007 #endif
6008 #endif
6009
6010 /**
6011 * Columns for result set of SQLColumnPrivileges().
6012 */
6013
6014 static COL colPrivSpec2[] = {
6015 { "SYSTEM", "COLPRIV", "TABLE_QUALIFIER", SCOL_VARCHAR, 50 },
6016 { "SYSTEM", "COLPRIV", "TABLE_OWNER", SCOL_VARCHAR, 50 },
6017 { "SYSTEM", "COLPRIV", "TABLE_NAME", SCOL_VARCHAR, 255 },
6018 { "SYSTEM", "COLPRIV", "COLUMN_NAME", SCOL_VARCHAR, 255 },
6019 { "SYSTEM", "COLPRIV", "GRANTOR", SCOL_VARCHAR, 50 },
6020 { "SYSTEM", "COLPRIV", "GRANTEE", SCOL_VARCHAR, 50 },
6021 { "SYSTEM", "COLPRIV", "PRIVILEGE", SCOL_VARCHAR, 50 }
6022 };
6023
6024 static COL colPrivSpec3[] = {
6025 { "SYSTEM", "COLPRIV", "TABLE_CAT", SCOL_VARCHAR, 50 },
6026 { "SYSTEM", "COLPRIV", "TABLE_SCHEM", SCOL_VARCHAR, 50 },
6027 { "SYSTEM", "COLPRIV", "TABLE_NAME", SCOL_VARCHAR, 255 },
6028 { "SYSTEM", "COLPRIV", "COLUMN_NAME", SCOL_VARCHAR, 255 },
6029 { "SYSTEM", "COLPRIV", "GRANTOR", SCOL_VARCHAR, 50 },
6030 { "SYSTEM", "COLPRIV", "GRANTEE", SCOL_VARCHAR, 50 },
6031 { "SYSTEM", "COLPRIV", "PRIVILEGE", SCOL_VARCHAR, 50 }
6032 };
6033
6034 #if !defined(WINTERFACE) || (defined(HAVE_UNIXODBC) && (HAVE_UNIXODBC))
6035 /**
6036 * Retrieve privileges on columns.
6037 * @param stmt statement handle
6038 * @param catalog catalog name/pattern or NULL
6039 * @param catalogLen length of catalog name/pattern or SQL_NTS
6040 * @param schema schema name/pattern or NULL
6041 * @param schemaLen length of schema name/pattern or SQL_NTS
6042 * @param table table name/pattern or NULL
6043 * @param tableLen length of table name/pattern or SQL_NTS
6044 * @param column column name or NULL
6045 * @param columnLen length of column name or SQL_NTS
6046 * @result ODBC error code
6047 */
6048
6049 SQLRETURN SQL_API
SQLColumnPrivileges(SQLHSTMT stmt,SQLCHAR * catalog,SQLSMALLINT catalogLen,SQLCHAR * schema,SQLSMALLINT schemaLen,SQLCHAR * table,SQLSMALLINT tableLen,SQLCHAR * column,SQLSMALLINT columnLen)6050 SQLColumnPrivileges(SQLHSTMT stmt,
6051 SQLCHAR *catalog, SQLSMALLINT catalogLen,
6052 SQLCHAR *schema, SQLSMALLINT schemaLen,
6053 SQLCHAR *table, SQLSMALLINT tableLen,
6054 SQLCHAR *column, SQLSMALLINT columnLen)
6055 {
6056 SQLRETURN ret;
6057
6058 HSTMT_LOCK(stmt);
6059 ret = mkresultset(stmt, colPrivSpec2, array_size(colPrivSpec2),
6060 colPrivSpec3, array_size(colPrivSpec3), NULL);
6061 HSTMT_UNLOCK(stmt);
6062 return ret;
6063 }
6064 #endif
6065
6066 #if !defined(HAVE_UNIXODBC) || !(HAVE_UNIXODBC)
6067 #ifdef WINTERFACE
6068 /**
6069 * Retrieve privileges on columns (UNICODE version).
6070 * @param stmt statement handle
6071 * @param catalog catalog name/pattern or NULL
6072 * @param catalogLen length of catalog name/pattern or SQL_NTS
6073 * @param schema schema name/pattern or NULL
6074 * @param schemaLen length of schema name/pattern or SQL_NTS
6075 * @param table table name/pattern or NULL
6076 * @param tableLen length of table name/pattern or SQL_NTS
6077 * @param column column name or NULL
6078 * @param columnLen length of column name or SQL_NTS
6079 * @result ODBC error code
6080 */
6081
6082 SQLRETURN SQL_API
SQLColumnPrivilegesW(SQLHSTMT stmt,SQLWCHAR * catalog,SQLSMALLINT catalogLen,SQLWCHAR * schema,SQLSMALLINT schemaLen,SQLWCHAR * table,SQLSMALLINT tableLen,SQLWCHAR * column,SQLSMALLINT columnLen)6083 SQLColumnPrivilegesW(SQLHSTMT stmt,
6084 SQLWCHAR *catalog, SQLSMALLINT catalogLen,
6085 SQLWCHAR *schema, SQLSMALLINT schemaLen,
6086 SQLWCHAR *table, SQLSMALLINT tableLen,
6087 SQLWCHAR *column, SQLSMALLINT columnLen)
6088 {
6089 SQLRETURN ret;
6090
6091 HSTMT_LOCK(stmt);
6092 ret = mkresultset(stmt, colPrivSpec2, array_size(colPrivSpec2),
6093 colPrivSpec3, array_size(colPrivSpec3), NULL);
6094 HSTMT_UNLOCK(stmt);
6095 return ret;
6096 }
6097 #endif
6098 #endif
6099
6100 /**
6101 * Columns for result set of SQLPrimaryKeys().
6102 */
6103
6104 static COL pkeySpec2[] = {
6105 { "SYSTEM", "PRIMARYKEY", "TABLE_QUALIFIER", SCOL_VARCHAR, 50 },
6106 { "SYSTEM", "PRIMARYKEY", "TABLE_OWNER", SCOL_VARCHAR, 50 },
6107 { "SYSTEM", "PRIMARYKEY", "TABLE_NAME", SCOL_VARCHAR, 255 },
6108 { "SYSTEM", "PRIMARYKEY", "COLUMN_NAME", SCOL_VARCHAR, 255 },
6109 { "SYSTEM", "PRIMARYKEY", "KEY_SEQ", SQL_SMALLINT, 50 },
6110 { "SYSTEM", "PRIMARYKEY", "PK_NAME", SCOL_VARCHAR, 50 }
6111 };
6112
6113 static COL pkeySpec3[] = {
6114 { "SYSTEM", "PRIMARYKEY", "TABLE_CAT", SCOL_VARCHAR, 50 },
6115 { "SYSTEM", "PRIMARYKEY", "TABLE_SCHEM", SCOL_VARCHAR, 50 },
6116 { "SYSTEM", "PRIMARYKEY", "TABLE_NAME", SCOL_VARCHAR, 255 },
6117 { "SYSTEM", "PRIMARYKEY", "COLUMN_NAME", SCOL_VARCHAR, 255 },
6118 { "SYSTEM", "PRIMARYKEY", "KEY_SEQ", SQL_SMALLINT, 50 },
6119 { "SYSTEM", "PRIMARYKEY", "PK_NAME", SCOL_VARCHAR, 50 }
6120 };
6121
6122 /**
6123 * Internal retrieve information about indexed columns.
6124 * @param stmt statement handle
6125 * @param cat catalog name/pattern or NULL
6126 * @param catLen length of catalog name/pattern or SQL_NTS
6127 * @param schema schema name/pattern or NULL
6128 * @param schemaLen length of schema name/pattern or SQL_NTS
6129 * @param table table name/pattern or NULL
6130 * @param tableLen length of table name/pattern or SQL_NTS
6131 * @result ODBC error code
6132 */
6133
6134 static SQLRETURN
drvprimarykeys(SQLHSTMT stmt,SQLCHAR * cat,SQLSMALLINT catLen,SQLCHAR * schema,SQLSMALLINT schemaLen,SQLCHAR * table,SQLSMALLINT tableLen)6135 drvprimarykeys(SQLHSTMT stmt,
6136 SQLCHAR *cat, SQLSMALLINT catLen,
6137 SQLCHAR *schema, SQLSMALLINT schemaLen,
6138 SQLCHAR *table, SQLSMALLINT tableLen)
6139 {
6140 STMT *s;
6141 DBC *d;
6142 SQLRETURN sret;
6143 int i, asize, ret, nrows, ncols, nrows2 = 0, ncols2 = 0;
6144 int namec = -1, uniquec = -1, namec2 = -1, uniquec2 = -1, offs, seq = 1;
6145 PTRDIFF_T size;
6146 char **rowp = NULL, **rowp2 = NULL, *errp = NULL, *sql, tname[512];
6147
6148 sret = mkresultset(stmt, pkeySpec2, array_size(pkeySpec2),
6149 pkeySpec3, array_size(pkeySpec3), &asize);
6150 if (sret != SQL_SUCCESS) {
6151 return sret;
6152 }
6153 s = (STMT *) stmt;
6154 d = (DBC *) s->dbc;
6155 if (!table || table[0] == '\0' || table[0] == '%') {
6156 setstat(s, -1, "need table name", (*s->ov3) ? "HY000" : "S1000");
6157 return SQL_ERROR;
6158 }
6159 if (tableLen == SQL_NTS) {
6160 size = sizeof (tname) - 1;
6161 } else {
6162 size = min(sizeof (tname) - 1, tableLen);
6163 }
6164 strncpy(tname, (char *) table, size);
6165 tname[size] = '\0';
6166 unescpat(tname);
6167 sql = sqlite4_mprintf(0, "PRAGMA table_info(%Q)", tname);
6168 if (!sql) {
6169 return nomem(s);
6170 }
6171 sret = starttran(s);
6172 if (sret != SQL_SUCCESS) {
6173 sqlite4_free(0, sql);
6174 return sret;
6175 }
6176 dbtraceapi(d, "sqlite4_get_table", sql);
6177 ret = sqlite4_get_table(d->sqlite, sql, &rowp, &nrows, &ncols, &errp);
6178 sqlite4_free(0, sql);
6179 if (ret != SQLITE4_OK) {
6180 setstat(s, ret, "%s (%d)", (*s->ov3) ? "HY000" : "S1000",
6181 errp ? errp : "unknown error", ret);
6182 if (errp) {
6183 sqlite4_free(0, errp);
6184 errp = NULL;
6185 }
6186 return SQL_ERROR;
6187 }
6188 if (errp) {
6189 sqlite4_free(0, errp);
6190 errp = NULL;
6191 }
6192 size = 0;
6193 if (ncols * nrows > 0) {
6194 int typec;
6195
6196 namec = findcol(rowp, ncols, "name");
6197 uniquec = findcol(rowp, ncols, "pk");
6198 typec = findcol(rowp, ncols, "type");
6199 if (namec >= 0 && uniquec >= 0 && typec >= 0) {
6200 for (i = 1; i <= nrows; i++) {
6201 if (*rowp[i * ncols + uniquec] != '0') {
6202 size++;
6203 }
6204 }
6205 }
6206 }
6207 if (size == 0) {
6208 sql = sqlite4_mprintf(0, "PRAGMA index_list(%Q)", tname);
6209 if (!sql) {
6210 freerows(rowp);
6211 return nomem(s);
6212 }
6213 dbtraceapi(d, "sqlite4_get_table", sql);
6214 ret = sqlite4_get_table(d->sqlite, sql, &rowp2, &nrows2, &ncols2,
6215 &errp);
6216 sqlite4_free(0, sql);
6217 if (ret != SQLITE4_OK) {
6218 freerows(rowp);
6219 freerows(rowp2);
6220 setstat(s, ret, "%s (%d)", (*s->ov3) ? "HY000" : "S1000",
6221 errp ? errp : "unknown error", ret);
6222 if (errp) {
6223 sqlite4_free(0, errp);
6224 errp = NULL;
6225 }
6226 return SQL_ERROR;
6227 }
6228 if (errp) {
6229 sqlite4_free(0, errp);
6230 errp = NULL;
6231 }
6232 }
6233 if (ncols2 * nrows2 > 0) {
6234 namec2 = findcol(rowp2, ncols2, "name");
6235 uniquec2 = findcol(rowp2, ncols2, "unique");
6236 if (namec2 >= 0 && uniquec2 >= 0) {
6237 for (i = 1; i <= nrows2; i++) {
6238 int nnrows, nncols, nlen = 0;
6239 char **rowpp;
6240
6241 if (rowp2[i * ncols2 + namec2]) {
6242 nlen = strlen(rowp2[i * ncols2 + namec2]);
6243 }
6244 if (nlen < 17 ||
6245 strncmp(rowp2[i * ncols2 + namec2],
6246 "sqlite_autoindex_", 17)) {
6247 continue;
6248 }
6249 if (*rowp2[i * ncols2 + uniquec2] != '0') {
6250 ret = SQLITE4_ERROR;
6251 sql = sqlite4_mprintf(0, "PRAGMA index_info(%Q)",
6252 rowp2[i * ncols2 + namec2]);
6253 if (sql) {
6254 dbtraceapi(d, "sqlite4_get_table", sql);
6255 ret = sqlite4_get_table(d->sqlite, sql, &rowpp,
6256 &nnrows, &nncols, NULL);
6257 sqlite4_free(0, sql);
6258 }
6259 if (ret == SQLITE4_OK) {
6260 size += nnrows;
6261 freerows(rowpp);
6262 }
6263 }
6264 }
6265 }
6266 }
6267 if (size == 0) {
6268 freerows(rowp);
6269 freerows(rowp2);
6270 return SQL_SUCCESS;
6271 }
6272 s->nrows = size;
6273 size = (size + 1) * asize;
6274 s->rows = xmalloc((size + 1) * sizeof (char *));
6275 if (!s->rows) {
6276 s->nrows = 0;
6277 freerows(rowp);
6278 freerows(rowp2);
6279 return nomem(s);
6280 }
6281 s->rows[0] = (char *) size;
6282 s->rows += 1;
6283 memset(s->rows, 0, sizeof (char *) * size);
6284 s->rowfree = freerows;
6285 offs = s->ncols;
6286 if (rowp) {
6287 for (i = 1; i <= nrows; i++) {
6288 if (*rowp[i * ncols + uniquec] != '0') {
6289 char buf[32];
6290
6291 #if defined(_WIN32) || defined(_WIN64)
6292 s->rows[offs + 0] = xstrdup(d->xcelqrx ? "main" : "");
6293 s->rows[offs + 1] = xstrdup("");
6294 #else
6295 s->rows[offs + 0] = xstrdup("");
6296 s->rows[offs + 1] = xstrdup("");
6297 #endif
6298 s->rows[offs + 2] = xstrdup(tname);
6299 s->rows[offs + 3] = xstrdup(rowp[i * ncols + namec]);
6300 sprintf(buf, "%d", seq++);
6301 s->rows[offs + 4] = xstrdup(buf);
6302 offs += s->ncols;
6303 }
6304 }
6305 }
6306 if (rowp2) {
6307 for (i = 1; i <= nrows2; i++) {
6308 int nnrows, nncols, nlen = 0;
6309 char **rowpp;
6310
6311 if (rowp2[i * ncols2 + namec2]) {
6312 nlen = strlen(rowp2[i * ncols2 + namec2]);
6313 }
6314 if (nlen < 17 ||
6315 strncmp(rowp2[i * ncols2 + namec2], "sqlite_autoindex_", 17)) {
6316 continue;
6317 }
6318 if (*rowp2[i * ncols2 + uniquec2] != '0') {
6319 int k;
6320
6321 ret = SQLITE4_ERROR;
6322 sql = sqlite4_mprintf(0, "PRAGMA index_info(%Q)",
6323 rowp2[i * ncols2 + namec2]);
6324 if (sql) {
6325 dbtraceapi(d, "sqlite4_get_table", sql);
6326 ret = sqlite4_get_table(d->sqlite, sql, &rowpp,
6327 &nnrows, &nncols, NULL);
6328 sqlite4_free(0, sql);
6329 }
6330 if (ret != SQLITE4_OK) {
6331 continue;
6332 }
6333 for (k = 0; nnrows && k < nncols; k++) {
6334 if (strcmp(rowpp[k], "name") == 0) {
6335 int m;
6336
6337 for (m = 1; m <= nnrows; m++) {
6338 int roffs = offs + (m - 1) * s->ncols;
6339
6340 #if defined(_WIN32) || defined(_WIN64)
6341 s->rows[roffs + 0] =
6342 xstrdup(d->xcelqrx ? "main" : "");
6343 s->rows[roffs + 1] = xstrdup("");
6344 #else
6345 s->rows[roffs + 0] = xstrdup("");
6346 s->rows[roffs + 1] = xstrdup("");
6347 #endif
6348 s->rows[roffs + 2] = xstrdup(tname);
6349 s->rows[roffs + 3] =
6350 xstrdup(rowpp[m * nncols + k]);
6351 s->rows[roffs + 5] =
6352 xstrdup(rowp2[i * ncols2 + namec2]);
6353 }
6354 } else if (strcmp(rowpp[k], "seqno") == 0) {
6355 int m;
6356
6357 for (m = 1; m <= nnrows; m++) {
6358 int roffs = offs + (m - 1) * s->ncols;
6359 int pos = m - 1;
6360 char buf[32];
6361
6362 sscanf(rowpp[m * nncols + k], "%d", &pos);
6363 sprintf(buf, "%d", pos + 1);
6364 s->rows[roffs + 4] = xstrdup(buf);
6365 }
6366 }
6367 }
6368 offs += nnrows * s->ncols;
6369 freerows(rowpp);
6370 }
6371 }
6372 }
6373 freerows(rowp);
6374 freerows(rowp2);
6375 return SQL_SUCCESS;
6376 }
6377
6378 #ifndef WINTERFACE
6379 /**
6380 * Retrieve information about indexed columns.
6381 * @param stmt statement handle
6382 * @param cat catalog name/pattern or NULL
6383 * @param catLen length of catalog name/pattern or SQL_NTS
6384 * @param schema schema name/pattern or NULL
6385 * @param schemaLen length of schema name/pattern or SQL_NTS
6386 * @param table table name/pattern or NULL
6387 * @param tableLen length of table name/pattern or SQL_NTS
6388 * @result ODBC error code
6389 */
6390
6391 SQLRETURN SQL_API
SQLPrimaryKeys(SQLHSTMT stmt,SQLCHAR * cat,SQLSMALLINT catLen,SQLCHAR * schema,SQLSMALLINT schemaLen,SQLCHAR * table,SQLSMALLINT tableLen)6392 SQLPrimaryKeys(SQLHSTMT stmt,
6393 SQLCHAR *cat, SQLSMALLINT catLen,
6394 SQLCHAR *schema, SQLSMALLINT schemaLen,
6395 SQLCHAR *table, SQLSMALLINT tableLen)
6396 {
6397 #if defined(_WIN32) || defined(_WIN64)
6398 char *c = NULL, *s = NULL, *t = NULL;
6399 #endif
6400 SQLRETURN ret;
6401
6402 HSTMT_LOCK(stmt);
6403 #if defined(_WIN32) || defined(_WIN64)
6404 if (!((STMT *) stmt)->oemcp[0]) {
6405 ret = drvprimarykeys(stmt, cat, catLen, schema, schemaLen,
6406 table, tableLen);
6407 goto done2;
6408 }
6409 if (cat) {
6410 c = wmb_to_utf_c((char *) cat, catLen);
6411 if (!c) {
6412 ret = nomem((STMT *) stmt);
6413 goto done;
6414 }
6415 }
6416 if (schema) {
6417 s = wmb_to_utf_c((char *) schema, schemaLen);
6418 if (!s) {
6419 ret = nomem((STMT *) stmt);
6420 goto done;
6421 }
6422 }
6423 if (table) {
6424 t = wmb_to_utf_c((char *) table, tableLen);
6425 if (!t) {
6426 ret = nomem((STMT *) stmt);
6427 goto done;
6428 }
6429 }
6430 ret = drvprimarykeys(stmt, (SQLCHAR *) c, SQL_NTS,
6431 (SQLCHAR *) s, SQL_NTS, (SQLCHAR *) t, SQL_NTS);
6432 #else
6433 ret = drvprimarykeys(stmt, cat, catLen, schema, schemaLen,
6434 table, tableLen);
6435 #endif
6436 #if defined(_WIN32) || defined(_WIN64)
6437 done:
6438 uc_free(t);
6439 uc_free(s);
6440 uc_free(c);
6441 done2:
6442 ;
6443 #endif
6444 HSTMT_UNLOCK(stmt);
6445 return ret;
6446 }
6447 #endif
6448
6449 #ifdef WINTERFACE
6450 /**
6451 * Retrieve information about indexed columns (UNICODE version).
6452 * @param stmt statement handle
6453 * @param cat catalog name/pattern or NULL
6454 * @param catLen length of catalog name/pattern or SQL_NTS
6455 * @param schema schema name/pattern or NULL
6456 * @param schemaLen length of schema name/pattern or SQL_NTS
6457 * @param table table name/pattern or NULL
6458 * @param tableLen length of table name/pattern or SQL_NTS
6459 * @result ODBC error code
6460 */
6461
6462 SQLRETURN SQL_API
SQLPrimaryKeysW(SQLHSTMT stmt,SQLWCHAR * cat,SQLSMALLINT catLen,SQLWCHAR * schema,SQLSMALLINT schemaLen,SQLWCHAR * table,SQLSMALLINT tableLen)6463 SQLPrimaryKeysW(SQLHSTMT stmt,
6464 SQLWCHAR *cat, SQLSMALLINT catLen,
6465 SQLWCHAR *schema, SQLSMALLINT schemaLen,
6466 SQLWCHAR *table, SQLSMALLINT tableLen)
6467 {
6468 char *c = NULL, *s = NULL, *t = NULL;
6469 SQLRETURN ret;
6470
6471 HSTMT_LOCK(stmt);
6472 if (cat) {
6473 c = uc_to_utf_c(cat, catLen);
6474 if (!c) {
6475 ret = nomem((STMT *) stmt);
6476 goto done;
6477 }
6478 }
6479 if (schema) {
6480 s = uc_to_utf_c(schema, schemaLen);
6481 if (!s) {
6482 ret = nomem((STMT *) stmt);
6483 goto done;
6484 }
6485 }
6486 if (table) {
6487 t = uc_to_utf_c(table, tableLen);
6488 if (!t) {
6489 ret = nomem((STMT *) stmt);
6490 goto done;
6491 }
6492 }
6493 ret = drvprimarykeys(stmt, (SQLCHAR *) c, SQL_NTS,
6494 (SQLCHAR *) s, SQL_NTS, (SQLCHAR *) t, SQL_NTS);
6495 done:
6496 uc_free(t);
6497 uc_free(s);
6498 uc_free(c);
6499 HSTMT_UNLOCK(stmt);
6500 return ret;
6501 }
6502 #endif
6503
6504 /**
6505 * Columns for result set of SQLSpecialColumns().
6506 */
6507
6508 static COL scolSpec2[] = {
6509 { "SYSTEM", "COLUMN", "SCOPE", SQL_SMALLINT, 1 },
6510 { "SYSTEM", "COLUMN", "COLUMN_NAME", SCOL_VARCHAR, 255 },
6511 { "SYSTEM", "COLUMN", "DATA_TYPE", SQL_SMALLINT, 50 },
6512 { "SYSTEM", "COLUMN", "TYPE_NAME", SCOL_VARCHAR, 50 },
6513 { "SYSTEM", "COLUMN", "PRECISION", SQL_INTEGER, 50 },
6514 { "SYSTEM", "COLUMN", "LENGTH", SQL_INTEGER, 50 },
6515 { "SYSTEM", "COLUMN", "DECIMAL_DIGITS", SQL_INTEGER, 50 },
6516 { "SYSTEM", "COLUMN", "PSEUDO_COLUMN", SQL_SMALLINT, 1 },
6517 { "SYSTEM", "COLUMN", "NULLABLE", SQL_SMALLINT, 1 }
6518 };
6519
6520 static COL scolSpec3[] = {
6521 { "SYSTEM", "COLUMN", "SCOPE", SQL_SMALLINT, 1 },
6522 { "SYSTEM", "COLUMN", "COLUMN_NAME", SCOL_VARCHAR, 255 },
6523 { "SYSTEM", "COLUMN", "DATA_TYPE", SQL_SMALLINT, 50 },
6524 { "SYSTEM", "COLUMN", "TYPE_NAME", SCOL_VARCHAR, 50 },
6525 { "SYSTEM", "COLUMN", "COLUMN_SIZE", SQL_INTEGER, 50 },
6526 { "SYSTEM", "COLUMN", "BUFFER_LENGTH", SQL_INTEGER, 50 },
6527 { "SYSTEM", "COLUMN", "DECIMAL_DIGITS", SQL_INTEGER, 50 },
6528 { "SYSTEM", "COLUMN", "PSEUDO_COLUMN", SQL_SMALLINT, 1 },
6529 { "SYSTEM", "COLUMN", "NULLABLE", SQL_SMALLINT, 1 }
6530 };
6531
6532 /**
6533 * Internal retrieve information about indexed columns.
6534 * @param stmt statement handle
6535 * @param id type of information, e.g. best row id
6536 * @param cat catalog name/pattern or NULL
6537 * @param catLen length of catalog name/pattern or SQL_NTS
6538 * @param schema schema name/pattern or NULL
6539 * @param schemaLen length of schema name/pattern or SQL_NTS
6540 * @param table table name/pattern or NULL
6541 * @param tableLen length of table name/pattern or SQL_NTS
6542 * @param scope
6543 * @param nullable
6544 * @result ODBC error code
6545 */
6546
6547 static SQLRETURN
drvspecialcolumns(SQLHSTMT stmt,SQLUSMALLINT id,SQLCHAR * cat,SQLSMALLINT catLen,SQLCHAR * schema,SQLSMALLINT schemaLen,SQLCHAR * table,SQLSMALLINT tableLen,SQLUSMALLINT scope,SQLUSMALLINT nullable)6548 drvspecialcolumns(SQLHSTMT stmt, SQLUSMALLINT id,
6549 SQLCHAR *cat, SQLSMALLINT catLen,
6550 SQLCHAR *schema, SQLSMALLINT schemaLen,
6551 SQLCHAR *table, SQLSMALLINT tableLen,
6552 SQLUSMALLINT scope, SQLUSMALLINT nullable)
6553 {
6554 STMT *s;
6555 DBC *d;
6556 SQLRETURN sret;
6557 int i, asize, ret, nrows, ncols, nnnrows, nnncols, offs;
6558 PTRDIFF_T size;
6559 int namec = -1, uniquec = -1, namecc = -1, typecc = -1;
6560 int notnullcc = -1, mkrowid = 0;
6561 char *errp = NULL, *sql, tname[512];
6562 char **rowp = NULL, **rowppp = NULL;
6563
6564 sret = mkresultset(stmt, scolSpec2, array_size(scolSpec2),
6565 scolSpec3, array_size(scolSpec3), &asize);
6566 if (sret != SQL_SUCCESS) {
6567 return sret;
6568 }
6569 s = (STMT *) stmt;
6570 d = (DBC *) s->dbc;
6571 if (!table || table[0] == '\0' || table[0] == '%') {
6572 setstat(s, -1, "need table name", (*s->ov3) ? "HY000" : "S1000");
6573 return SQL_ERROR;
6574 }
6575 if (tableLen == SQL_NTS) {
6576 size = sizeof (tname) - 1;
6577 } else {
6578 size = min(sizeof (tname) - 1, tableLen);
6579 }
6580 strncpy(tname, (char *) table, size);
6581 tname[size] = '\0';
6582 unescpat(tname);
6583 if (id != SQL_BEST_ROWID) {
6584 return SQL_SUCCESS;
6585 }
6586 sql = sqlite4_mprintf(0, "PRAGMA index_list(%Q)", tname);
6587 if (!sql) {
6588 return nomem(s);
6589 }
6590 sret = starttran(s);
6591 if (sret != SQL_SUCCESS) {
6592 sqlite4_free(0, sql);
6593 return sret;
6594 }
6595 dbtraceapi(d, "sqlite4_get_table", sql);
6596 ret = sqlite4_get_table(d->sqlite, sql, &rowp, &nrows, &ncols, &errp);
6597 sqlite4_free(0, sql);
6598 if (ret != SQLITE4_OK) {
6599 doerr:
6600 setstat(s, ret, "%s (%d)", (*s->ov3) ? "HY000" : "S1000",
6601 errp ? errp : "unknown error", ret);
6602 if (errp) {
6603 sqlite4_free(0, errp);
6604 errp = NULL;
6605 }
6606 return SQL_ERROR;
6607 }
6608 if (errp) {
6609 sqlite4_free(0, errp);
6610 errp = NULL;
6611 }
6612 size = 0; /* number result rows */
6613 if (ncols * nrows <= 0) {
6614 goto nodata_but_rowid;
6615 }
6616 sql = sqlite4_mprintf(0, "PRAGMA table_info(%Q)", tname);
6617 if (!sql) {
6618 return nomem(s);
6619 }
6620 dbtraceapi(d, "sqlite4_get_table", sql);
6621 ret = sqlite4_get_table(d->sqlite, sql, &rowppp, &nnnrows, &nnncols,
6622 &errp);
6623 sqlite4_free(0, sql);
6624 if (ret != SQLITE4_OK) {
6625 freerows(rowp);
6626 goto doerr;
6627 }
6628 if (errp) {
6629 sqlite4_free(0, errp);
6630 errp = NULL;
6631 }
6632 namec = findcol(rowp, ncols, "name");
6633 uniquec = findcol(rowp, ncols, "unique");
6634 if (namec < 0 || uniquec < 0) {
6635 goto nodata_but_rowid;
6636 }
6637 namecc = findcol(rowppp, nnncols, "name");
6638 typecc = findcol(rowppp, nnncols, "type");
6639 notnullcc = findcol(rowppp, nnncols, "notnull");
6640 for (i = 1; i <= nrows; i++) {
6641 int nnrows, nncols;
6642 char **rowpp = NULL;
6643
6644 if (*rowp[i * ncols + uniquec] != '0') {
6645 ret = SQLITE4_ERROR;
6646 sql = sqlite4_mprintf(0, "PRAGMA index_info(%Q)",
6647 rowp[i * ncols + namec]);
6648 if (sql) {
6649 dbtraceapi(d, "sqlite4_get_table", sql);
6650 ret = sqlite4_get_table(d->sqlite, sql, &rowpp,
6651 &nnrows, &nncols, NULL);
6652 sqlite4_free(0, sql);
6653 }
6654 if (ret == SQLITE4_OK) {
6655 size += nnrows;
6656 freerows(rowpp);
6657 }
6658 }
6659 }
6660 nodata_but_rowid:
6661 if (size == 0) {
6662 size = 1;
6663 mkrowid = 1;
6664 }
6665 s->nrows = size;
6666 size = (size + 1) * asize;
6667 s->rows = xmalloc((size + 1) * sizeof (char *));
6668 if (!s->rows) {
6669 s->nrows = 0;
6670 freerows(rowp);
6671 freerows(rowppp);
6672 return nomem(s);
6673 }
6674 s->rows[0] = (char *) size;
6675 s->rows += 1;
6676 memset(s->rows, 0, sizeof (char *) * size);
6677 s->rowfree = freerows;
6678 if (mkrowid) {
6679 s->nrows = 0;
6680 goto mkrowid;
6681 }
6682 offs = 0;
6683 for (i = 1; i <= nrows; i++) {
6684 int nnrows, nncols;
6685 char **rowpp = NULL;
6686
6687 if (*rowp[i * ncols + uniquec] != '0') {
6688 int k;
6689
6690 ret = SQLITE4_ERROR;
6691 sql = sqlite4_mprintf(0, "PRAGMA index_info(%Q)",
6692 rowp[i * ncols + namec]);
6693 if (sql) {
6694 dbtraceapi(d, "sqlite4_get_table", sql);
6695 ret = sqlite4_get_table(d->sqlite, sql, &rowpp,
6696 &nnrows, &nncols, NULL);
6697 sqlite4_free(0, sql);
6698 }
6699 if (ret != SQLITE4_OK) {
6700 continue;
6701 }
6702 for (k = 0; nnrows && k < nncols; k++) {
6703 if (strcmp(rowpp[k], "name") == 0) {
6704 int m;
6705
6706 for (m = 1; m <= nnrows; m++) {
6707 int roffs = (offs + m) * s->ncols;
6708
6709 s->rows[roffs + 0] =
6710 xstrdup(stringify(SQL_SCOPE_SESSION));
6711 s->rows[roffs + 1] = xstrdup(rowpp[m * nncols + k]);
6712 s->rows[roffs + 4] = xstrdup("0");
6713 s->rows[roffs + 7] =
6714 xstrdup(stringify(SQL_PC_NOT_PSEUDO));
6715 if (namecc >= 0 && typecc >= 0) {
6716 int ii;
6717
6718 for (ii = 1; ii <= nnnrows; ii++) {
6719 if (strcmp(rowppp[ii * nnncols + namecc],
6720 rowpp[m * nncols + k]) == 0) {
6721 char *typen = rowppp[ii * nnncols + typecc];
6722 int sqltype, mm, dd, isnullable = 0;
6723 char buf[32];
6724
6725 s->rows[roffs + 3] = xstrdup(typen);
6726 sqltype = mapsqltype(typen, NULL, *s->ov3,
6727 s->nowchar[0],
6728 s->dobigint);
6729 getmd(typen, sqltype, &mm, &dd);
6730 #ifdef SQL_LONGVARCHAR
6731 if (sqltype == SQL_VARCHAR && mm > 255) {
6732 sqltype = SQL_LONGVARCHAR;
6733 }
6734 #endif
6735 #ifdef WINTERFACE
6736 #ifdef SQL_WLONGVARCHAR
6737 if (sqltype == SQL_WVARCHAR && mm > 255) {
6738 sqltype = SQL_WLONGVARCHAR;
6739 }
6740 #endif
6741 #endif
6742 if (sqltype == SQL_VARBINARY && mm > 255) {
6743 sqltype = SQL_LONGVARBINARY;
6744 }
6745 sprintf(buf, "%d", sqltype);
6746 s->rows[roffs + 2] = xstrdup(buf);
6747 sprintf(buf, "%d", mm);
6748 s->rows[roffs + 5] = xstrdup(buf);
6749 sprintf(buf, "%d", dd);
6750 s->rows[roffs + 6] = xstrdup(buf);
6751 if (notnullcc >= 0) {
6752 char *inp =
6753 rowppp[ii * nnncols + notnullcc];
6754
6755 isnullable = inp[0] != '0';
6756 }
6757 sprintf(buf, "%d", isnullable);
6758 s->rows[roffs + 8] = xstrdup(buf);
6759 }
6760 }
6761 }
6762 }
6763 }
6764 }
6765 offs += nnrows;
6766 freerows(rowpp);
6767 }
6768 }
6769 if (nullable == SQL_NO_NULLS) {
6770 for (i = 1; i < s->nrows; i++) {
6771 if (s->rows[i * s->ncols + 8][0] == '0') {
6772 int m, i1 = i + 1;
6773
6774 for (m = 0; m < s->ncols; m++) {
6775 freep(&s->rows[i * s->ncols + m]);
6776 }
6777 size = s->ncols * sizeof (char *) * (s->nrows - i1);
6778 if (size > 0) {
6779 memmove(s->rows + i * s->ncols,
6780 s->rows + i1 * s->ncols,
6781 size);
6782 memset(s->rows + s->nrows * s->ncols, 0,
6783 s->ncols * sizeof (char *));
6784 }
6785 s->nrows--;
6786 --i;
6787 }
6788 }
6789 }
6790 mkrowid:
6791 freerows(rowp);
6792 freerows(rowppp);
6793 if (s->nrows == 0) {
6794 s->rows[s->ncols + 0] = xstrdup(stringify(SQL_SCOPE_SESSION));
6795 s->rows[s->ncols + 1] = xstrdup("_ROWID_");
6796 s->rows[s->ncols + 2] = xstrdup(stringify(SQL_INTEGER));
6797 s->rows[s->ncols + 3] = xstrdup("integer");
6798 s->rows[s->ncols + 4] = xstrdup("0");
6799 s->rows[s->ncols + 5] = xstrdup("10");
6800 s->rows[s->ncols + 6] = xstrdup("9");
6801 s->rows[s->ncols + 7] = xstrdup(stringify(SQL_PC_PSEUDO));
6802 s->rows[s->ncols + 8] = xstrdup(stringify(SQL_FALSE));
6803 s->nrows = 1;
6804 }
6805 return SQL_SUCCESS;
6806 }
6807
6808 #ifndef WINTERFACE
6809 /**
6810 * Retrieve information about indexed columns.
6811 * @param stmt statement handle
6812 * @param id type of information, e.g. best row id
6813 * @param cat catalog name/pattern or NULL
6814 * @param catLen length of catalog name/pattern or SQL_NTS
6815 * @param schema schema name/pattern or NULL
6816 * @param schemaLen length of schema name/pattern or SQL_NTS
6817 * @param table table name/pattern or NULL
6818 * @param tableLen length of table name/pattern or SQL_NTS
6819 * @param scope
6820 * @param nullable
6821 * @result ODBC error code
6822 */
6823
6824 SQLRETURN SQL_API
SQLSpecialColumns(SQLHSTMT stmt,SQLUSMALLINT id,SQLCHAR * cat,SQLSMALLINT catLen,SQLCHAR * schema,SQLSMALLINT schemaLen,SQLCHAR * table,SQLSMALLINT tableLen,SQLUSMALLINT scope,SQLUSMALLINT nullable)6825 SQLSpecialColumns(SQLHSTMT stmt, SQLUSMALLINT id,
6826 SQLCHAR *cat, SQLSMALLINT catLen,
6827 SQLCHAR *schema, SQLSMALLINT schemaLen,
6828 SQLCHAR *table, SQLSMALLINT tableLen,
6829 SQLUSMALLINT scope, SQLUSMALLINT nullable)
6830 {
6831 #if defined(_WIN32) || defined(_WIN64)
6832 char *c = NULL, *s = NULL, *t = NULL;
6833 #endif
6834 SQLRETURN ret;
6835
6836 HSTMT_LOCK(stmt);
6837 #if defined(_WIN32) || defined(_WIN64)
6838 if (!((STMT *) stmt)->oemcp[0]) {
6839 ret = drvspecialcolumns(stmt, id, cat, catLen, schema, schemaLen,
6840 table, tableLen, scope, nullable);
6841 goto done2;
6842 }
6843 if (cat) {
6844 c = wmb_to_utf_c((char *) cat, catLen);
6845 if (!c) {
6846 ret = nomem((STMT *) stmt);
6847 goto done;
6848 }
6849 }
6850 if (schema) {
6851 s = wmb_to_utf_c((char *) schema, schemaLen);
6852 if (!s) {
6853 ret = nomem((STMT *) stmt);
6854 goto done;
6855 }
6856 }
6857 if (table) {
6858 t = wmb_to_utf_c((char *) table, tableLen);
6859 if (!t) {
6860 ret = nomem((STMT *) stmt);
6861 goto done;
6862 }
6863 }
6864 ret = drvspecialcolumns(stmt, id, (SQLCHAR *) c, SQL_NTS,
6865 (SQLCHAR *) s, SQL_NTS, (SQLCHAR *) t, SQL_NTS,
6866 scope, nullable);
6867 #else
6868 ret = drvspecialcolumns(stmt, id, cat, catLen, schema, schemaLen,
6869 table, tableLen, scope, nullable);
6870 #endif
6871 #if defined(_WIN32) || defined(_WIN64)
6872 done:
6873 uc_free(t);
6874 uc_free(s);
6875 uc_free(c);
6876 done2:
6877 ;
6878 #endif
6879 HSTMT_UNLOCK(stmt);
6880 return ret;
6881 }
6882 #endif
6883
6884 #ifdef WINTERFACE
6885 /**
6886 * Retrieve information about indexed columns (UNICODE version).
6887 * @param stmt statement handle
6888 * @param id type of information, e.g. best row id
6889 * @param cat catalog name/pattern or NULL
6890 * @param catLen length of catalog name/pattern or SQL_NTS
6891 * @param schema schema name/pattern or NULL
6892 * @param schemaLen length of schema name/pattern or SQL_NTS
6893 * @param table table name/pattern or NULL
6894 * @param tableLen length of table name/pattern or SQL_NTS
6895 * @param scope
6896 * @param nullable
6897 * @result ODBC error code
6898 */
6899
6900 SQLRETURN SQL_API
SQLSpecialColumnsW(SQLHSTMT stmt,SQLUSMALLINT id,SQLWCHAR * cat,SQLSMALLINT catLen,SQLWCHAR * schema,SQLSMALLINT schemaLen,SQLWCHAR * table,SQLSMALLINT tableLen,SQLUSMALLINT scope,SQLUSMALLINT nullable)6901 SQLSpecialColumnsW(SQLHSTMT stmt, SQLUSMALLINT id,
6902 SQLWCHAR *cat, SQLSMALLINT catLen,
6903 SQLWCHAR *schema, SQLSMALLINT schemaLen,
6904 SQLWCHAR *table, SQLSMALLINT tableLen,
6905 SQLUSMALLINT scope, SQLUSMALLINT nullable)
6906 {
6907 char *c = NULL, *s = NULL, *t = NULL;
6908 SQLRETURN ret;
6909
6910 HSTMT_LOCK(stmt);
6911 if (cat) {
6912 c = uc_to_utf_c(cat, catLen);
6913 if (!c) {
6914 ret = nomem((STMT *) stmt);
6915 goto done;
6916 }
6917 }
6918 if (schema) {
6919 s = uc_to_utf_c(schema, schemaLen);
6920 if (!s) {
6921 ret = nomem((STMT *) stmt);
6922 goto done;
6923 }
6924 }
6925 if (table) {
6926 t = uc_to_utf_c(table, tableLen);
6927 if (!t) {
6928 ret = nomem((STMT *) stmt);
6929 goto done;
6930 }
6931 }
6932 ret = drvspecialcolumns(stmt, id, (SQLCHAR *) c, SQL_NTS,
6933 (SQLCHAR *) s, SQL_NTS, (SQLCHAR *) t, SQL_NTS,
6934 scope, nullable);
6935 done:
6936 uc_free(t);
6937 uc_free(s);
6938 uc_free(c);
6939 HSTMT_UNLOCK(stmt);
6940 return ret;
6941 }
6942 #endif
6943
6944 /**
6945 * Columns for result set of SQLForeignKeys().
6946 */
6947
6948 static COL fkeySpec2[] = {
6949 { "SYSTEM", "FOREIGNKEY", "PKTABLE_QUALIFIER", SCOL_VARCHAR, 50 },
6950 { "SYSTEM", "FOREIGNKEY", "PKTABLE_OWNER", SCOL_VARCHAR, 50 },
6951 { "SYSTEM", "FOREIGNKEY", "PKTABLE_NAME", SCOL_VARCHAR, 255 },
6952 { "SYSTEM", "FOREIGNKEY", "PKCOLUMN_NAME", SCOL_VARCHAR, 255 },
6953 { "SYSTEM", "FOREIGNKEY", "FKTABLE_QUALIFIER", SCOL_VARCHAR, 50 },
6954 { "SYSTEM", "FOREIGNKEY", "FKTABLE_OWNER", SCOL_VARCHAR, 50 },
6955 { "SYSTEM", "FOREIGNKEY", "FKTABLE_NAME", SCOL_VARCHAR, 255 },
6956 { "SYSTEM", "FOREIGNKEY", "FKCOLUMN_NAME", SCOL_VARCHAR, 255 },
6957 { "SYSTEM", "FOREIGNKEY", "KEY_SEQ", SQL_SMALLINT, 5 },
6958 { "SYSTEM", "FOREIGNKEY", "UPDATE_RULE", SQL_SMALLINT, 5 },
6959 { "SYSTEM", "FOREIGNKEY", "DELETE_RULE", SQL_SMALLINT, 5 },
6960 { "SYSTEM", "FOREIGNKEY", "FK_NAME", SCOL_VARCHAR, 255 },
6961 { "SYSTEM", "FOREIGNKEY", "PK_NAME", SCOL_VARCHAR, 255 },
6962 { "SYSTEM", "FOREIGNKEY", "DEFERRABILITY", SQL_SMALLINT, 5 }
6963 };
6964
6965 static COL fkeySpec3[] = {
6966 { "SYSTEM", "FOREIGNKEY", "PKTABLE_CAT", SCOL_VARCHAR, 50 },
6967 { "SYSTEM", "FOREIGNKEY", "PKTABLE_SCHEM", SCOL_VARCHAR, 50 },
6968 { "SYSTEM", "FOREIGNKEY", "PKTABLE_NAME", SCOL_VARCHAR, 255 },
6969 { "SYSTEM", "FOREIGNKEY", "PKCOLUMN_NAME", SCOL_VARCHAR, 255 },
6970 { "SYSTEM", "FOREIGNKEY", "FKTABLE_CAT", SCOL_VARCHAR, 50 },
6971 { "SYSTEM", "FOREIGNKEY", "FKTABLE_SCHEM", SCOL_VARCHAR, 50 },
6972 { "SYSTEM", "FOREIGNKEY", "FKTABLE_NAME", SCOL_VARCHAR, 255 },
6973 { "SYSTEM", "FOREIGNKEY", "FKCOLUMN_NAME", SCOL_VARCHAR, 255 },
6974 { "SYSTEM", "FOREIGNKEY", "KEY_SEQ", SQL_SMALLINT, 5 },
6975 { "SYSTEM", "FOREIGNKEY", "UPDATE_RULE", SQL_SMALLINT, 5 },
6976 { "SYSTEM", "FOREIGNKEY", "DELETE_RULE", SQL_SMALLINT, 5 },
6977 { "SYSTEM", "FOREIGNKEY", "FK_NAME", SCOL_VARCHAR, 255 },
6978 { "SYSTEM", "FOREIGNKEY", "PK_NAME", SCOL_VARCHAR, 255 },
6979 { "SYSTEM", "FOREIGNKEY", "DEFERRABILITY", SQL_SMALLINT, 5 }
6980 };
6981
6982 /**
6983 * Internal retrieve information about primary/foreign keys.
6984 * @param stmt statement handle
6985 * @param PKcatalog primary key catalog name/pattern or NULL
6986 * @param PKcatalogLen length of PKcatalog or SQL_NTS
6987 * @param PKschema primary key schema name/pattern or NULL
6988 * @param PKschemaLen length of PKschema or SQL_NTS
6989 * @param PKtable primary key table name/pattern or NULL
6990 * @param PKtableLen length of PKtable or SQL_NTS
6991 * @param FKcatalog foreign key catalog name/pattern or NULL
6992 * @param FKcatalogLen length of FKcatalog or SQL_NTS
6993 * @param FKschema foreign key schema name/pattern or NULL
6994 * @param FKschemaLen length of FKschema or SQL_NTS
6995 * @param FKtable foreign key table name/pattern or NULL
6996 * @param FKtableLen length of FKtable or SQL_NTS
6997 * @result ODBC error code
6998 */
6999
7000 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)7001 drvforeignkeys(SQLHSTMT stmt,
7002 SQLCHAR *PKcatalog, SQLSMALLINT PKcatalogLen,
7003 SQLCHAR *PKschema, SQLSMALLINT PKschemaLen,
7004 SQLCHAR *PKtable, SQLSMALLINT PKtableLen,
7005 SQLCHAR *FKcatalog, SQLSMALLINT FKcatalogLen,
7006 SQLCHAR *FKschema, SQLSMALLINT FKschemaLen,
7007 SQLCHAR *FKtable, SQLSMALLINT FKtableLen)
7008 {
7009 STMT *s;
7010 DBC *d;
7011 SQLRETURN sret;
7012 int i, asize, ret, nrows, ncols, offs, namec, seqc, fromc, toc;
7013 int onu, ond;
7014 PTRDIFF_T size;
7015 char **rowp, *errp = NULL, *sql, pname[512], fname[512];
7016
7017 sret = mkresultset(stmt, fkeySpec2, array_size(fkeySpec2),
7018 fkeySpec3, array_size(fkeySpec3), &asize);
7019 if (sret != SQL_SUCCESS) {
7020 return sret;
7021 }
7022 s = (STMT *) stmt;
7023 sret = starttran(s);
7024 if (sret != SQL_SUCCESS) {
7025 return sret;
7026 }
7027 d = (DBC *) s->dbc;
7028 if ((!PKtable || PKtable[0] == '\0' || PKtable[0] == '%') &&
7029 (!FKtable || FKtable[0] == '\0' || FKtable[0] == '%')) {
7030 setstat(s, -1, "need table name", (*s->ov3) ? "HY000" : "S1000");
7031 return SQL_ERROR;
7032 }
7033 size = 0;
7034 if (PKtable) {
7035 if (PKtableLen == SQL_NTS) {
7036 size = sizeof (pname) - 1;
7037 } else {
7038 size = min(sizeof (pname) - 1, PKtableLen);
7039 }
7040 strncpy(pname, (char *) PKtable, size);
7041 }
7042 pname[size] = '\0';
7043 size = 0;
7044 if (FKtable) {
7045
7046 if (FKtableLen == SQL_NTS) {
7047 size = sizeof (fname) - 1;
7048 } else {
7049 size = min(sizeof (fname) - 1, FKtableLen);
7050 }
7051 strncpy(fname, (char *) FKtable, size);
7052 }
7053 fname[size] = '\0';
7054 if (fname[0] != '\0') {
7055 int plen;
7056
7057 ret = SQLITE4_ERROR;
7058 sql = sqlite4_mprintf(0, "PRAGMA foreign_key_list(%Q)", fname);
7059 if (sql) {
7060 dbtraceapi(d, "sqlite4_get_table", sql);
7061 ret = sqlite4_get_table(d->sqlite, sql, &rowp,
7062 &nrows, &ncols, &errp);
7063 sqlite4_free(0, sql);
7064 }
7065 if (ret != SQLITE4_OK) {
7066 setstat(s, ret, "%s (%d)", (*s->ov3) ? "HY000" : "S1000",
7067 errp ? errp : "unknown error", ret);
7068 if (errp) {
7069 sqlite4_free(0, errp);
7070 errp = NULL;
7071 }
7072 return SQL_ERROR;
7073 }
7074 if (errp) {
7075 sqlite4_free(0, errp);
7076 errp = NULL;
7077 }
7078 if (ncols * nrows <= 0) {
7079 nodata:
7080 freerows(rowp);
7081 return SQL_SUCCESS;
7082 }
7083 size = 0;
7084 namec = findcol(rowp, ncols, "table");
7085 seqc = findcol(rowp, ncols, "seq");
7086 fromc = findcol(rowp, ncols, "from");
7087 toc = findcol(rowp, ncols, "to");
7088 onu = findcol(rowp, ncols, "on_update");
7089 ond = findcol(rowp, ncols, "on_delete");
7090 if (namec < 0 || seqc < 0 || fromc < 0 || toc < 0) {
7091 goto nodata;
7092 }
7093 plen = strlen(pname);
7094 for (i = 1; i <= nrows; i++) {
7095 char *ptab = unquote(rowp[i * ncols + namec]);
7096
7097 if (plen && ptab) {
7098 int len = strlen(ptab);
7099
7100 if (plen != len || strncasecmp(pname, ptab, plen) != 0) {
7101 continue;
7102 }
7103 }
7104 size++;
7105 }
7106 if (size == 0) {
7107 goto nodata;
7108 }
7109 s->nrows = size;
7110 size = (size + 1) * asize;
7111 s->rows = xmalloc((size + 1) * sizeof (char *));
7112 if (!s->rows) {
7113 s->nrows = 0;
7114 return nomem(s);
7115 }
7116 s->rows[0] = (char *) size;
7117 s->rows += 1;
7118 memset(s->rows, 0, sizeof (char *) * size);
7119 s->rowfree = freerows;
7120 offs = 0;
7121 for (i = 1; i <= nrows; i++) {
7122 int pos = 0, roffs = (offs + 1) * s->ncols;
7123 char *ptab = rowp[i * ncols + namec];
7124 char buf[32];
7125
7126 if (plen && ptab) {
7127 int len = strlen(ptab);
7128
7129 if (plen != len || strncasecmp(pname, ptab, plen) != 0) {
7130 continue;
7131 }
7132 }
7133 #if defined(_WIN32) || defined(_WIN64)
7134 s->rows[roffs + 0] = xstrdup(d->xcelqrx ? "main" : "");
7135 s->rows[roffs + 1] = xstrdup("");
7136 #else
7137 s->rows[roffs + 0] = xstrdup("");
7138 s->rows[roffs + 1] = xstrdup("");
7139 #endif
7140 s->rows[roffs + 2] = xstrdup(ptab);
7141 s->rows[roffs + 3] = xstrdup(rowp[i * ncols + toc]);
7142 s->rows[roffs + 4] = xstrdup("");
7143 s->rows[roffs + 5] = xstrdup("");
7144 s->rows[roffs + 6] = xstrdup(fname);
7145 s->rows[roffs + 7] = xstrdup(rowp[i * ncols + fromc]);
7146 sscanf(rowp[i * ncols + seqc], "%d", &pos);
7147 sprintf(buf, "%d", pos + 1);
7148 s->rows[roffs + 8] = xstrdup(buf);
7149 if (onu < 0) {
7150 s->rows[roffs + 9] = xstrdup(stringify(SQL_NO_ACTION));
7151 } else {
7152 if (strcmp(rowp[i * ncols + onu], "SET NULL") == 0) {
7153 s->rows[roffs + 9] = xstrdup(stringify(SQL_SET_NULL));
7154 } else if (strcmp(rowp[i * ncols + onu], "SET DEFAULT") == 0) {
7155 s->rows[roffs + 9] = xstrdup(stringify(SQL_SET_DEFAULT));
7156 } else if (strcmp(rowp[i * ncols + onu], "CASCADE") == 0) {
7157 s->rows[roffs + 9] = xstrdup(stringify(SQL_CASCADE));
7158 } else if (strcmp(rowp[i * ncols + onu], "RESTRICT") == 0) {
7159 s->rows[roffs + 9] = xstrdup(stringify(SQL_RESTRICT));
7160 } else {
7161 s->rows[roffs + 9] = xstrdup(stringify(SQL_NO_ACTION));
7162 }
7163 }
7164 if (ond < 0) {
7165 s->rows[roffs + 10] = xstrdup(stringify(SQL_NO_ACTION));
7166 } else {
7167 if (strcmp(rowp[i * ncols + ond], "SET NULL") == 0) {
7168 s->rows[roffs + 10] = xstrdup(stringify(SQL_SET_NULL));
7169 } else if (strcmp(rowp[i * ncols + ond], "SET DEFAULT") == 0) {
7170 s->rows[roffs + 10] = xstrdup(stringify(SQL_SET_DEFAULT));
7171 } else if (strcmp(rowp[i * ncols + ond], "CASCADE") == 0) {
7172 s->rows[roffs + 10] = xstrdup(stringify(SQL_CASCADE));
7173 } else if (strcmp(rowp[i * ncols + ond], "RESTRICT") == 0) {
7174 s->rows[roffs + 10] = xstrdup(stringify(SQL_RESTRICT));
7175 } else {
7176 s->rows[roffs + 10] = xstrdup(stringify(SQL_NO_ACTION));
7177 }
7178 }
7179 s->rows[roffs + 11] = NULL;
7180 s->rows[roffs + 12] = NULL;
7181 s->rows[roffs + 13] = xstrdup(stringify(SQL_NOT_DEFERRABLE));
7182 offs++;
7183 }
7184 freerows(rowp);
7185 } else {
7186 int nnrows, nncols, plen = strlen(pname);
7187 char **rowpp;
7188
7189 sql = "select name from sqlite_master where type='table'";
7190 dbtraceapi(d, "sqlite4_get_table", sql);
7191 ret = sqlite4_get_table(d->sqlite, sql, &rowp, &nrows, &ncols, &errp);
7192 if (ret != SQLITE4_OK) {
7193 setstat(s, ret, "%s (%d)", (*s->ov3) ? "HY000" : "S1000",
7194 errp ? errp : "unknown error", ret);
7195 if (errp) {
7196 sqlite4_free(0, errp);
7197 errp = NULL;
7198 }
7199 return SQL_ERROR;
7200 }
7201 if (errp) {
7202 sqlite4_free(0, errp);
7203 errp = NULL;
7204 }
7205 if (ncols * nrows <= 0) {
7206 goto nodata;
7207 }
7208 size = 0;
7209 for (i = 1; i <= nrows; i++) {
7210 int k;
7211
7212 if (!rowp[i]) {
7213 continue;
7214 }
7215 rowpp = NULL;
7216 ret = SQLITE4_ERROR;
7217 sql = sqlite4_mprintf(0, "PRAGMA foreign_key_list(%Q)", rowp[i]);
7218 if (sql) {
7219 dbtraceapi(d, "sqlite4_get_table", sql);
7220 ret = sqlite4_get_table(d->sqlite, sql, &rowpp,
7221 &nnrows, &nncols, NULL);
7222 sqlite4_free(0, sql);
7223 }
7224 if (ret != SQLITE4_OK || nncols * nnrows <= 0) {
7225 freerows(rowpp);
7226 continue;
7227 }
7228 namec = findcol(rowpp, nncols, "table");
7229 seqc = findcol(rowpp, nncols, "seq");
7230 fromc = findcol(rowpp, nncols, "from");
7231 toc = findcol(rowpp, nncols, "to");
7232 if (namec < 0 || seqc < 0 || fromc < 0 || toc < 0) {
7233 freerows(rowpp);
7234 continue;
7235 }
7236 for (k = 1; k <= nnrows; k++) {
7237 char *ptab = unquote(rowpp[k * nncols + namec]);
7238
7239 if (plen && ptab) {
7240 int len = strlen(ptab);
7241
7242 if (len != plen || strncasecmp(pname, ptab, plen) != 0) {
7243 continue;
7244 }
7245 }
7246 size++;
7247 }
7248 freerows(rowpp);
7249 }
7250 if (size == 0) {
7251 goto nodata;
7252 }
7253 s->nrows = size;
7254 size = (size + 1) * asize;
7255 s->rows = xmalloc((size + 1) * sizeof (char *));
7256 if (!s->rows) {
7257 s->nrows = 0;
7258 return nomem(s);
7259 }
7260 s->rows[0] = (char *) size;
7261 s->rows += 1;
7262 memset(s->rows, 0, sizeof (char *) * size);
7263 s->rowfree = freerows;
7264 offs = 0;
7265 for (i = 1; i <= nrows; i++) {
7266 int k;
7267
7268 if (!rowp[i]) {
7269 continue;
7270 }
7271 rowpp = NULL;
7272 ret = SQLITE4_ERROR;
7273 sql = sqlite4_mprintf(0, "PRAGMA foreign_key_list(%Q)", rowp[i]);
7274 if (sql) {
7275 dbtraceapi(d, "sqlite4_get_table", sql);
7276 ret = sqlite4_get_table(d->sqlite, sql, &rowpp,
7277 &nnrows, &nncols, NULL);
7278 sqlite4_free(0, sql);
7279 }
7280 if (ret != SQLITE4_OK || nncols * nnrows <= 0) {
7281 freerows(rowpp);
7282 continue;
7283 }
7284 namec = findcol(rowpp, nncols, "table");
7285 seqc = findcol(rowpp, nncols, "seq");
7286 fromc = findcol(rowpp, nncols, "from");
7287 toc = findcol(rowpp, nncols, "to");
7288 onu = findcol(rowpp, nncols, "on_update");
7289 ond = findcol(rowpp, nncols, "on_delete");
7290 if (namec < 0 || seqc < 0 || fromc < 0 || toc < 0) {
7291 freerows(rowpp);
7292 continue;
7293 }
7294 for (k = 1; k <= nnrows; k++) {
7295 int pos = 0, roffs = (offs + 1) * s->ncols;
7296 char *ptab = unquote(rowpp[k * nncols + namec]);
7297 char buf[32];
7298
7299 if (plen && ptab) {
7300 int len = strlen(ptab);
7301
7302 if (len != plen || strncasecmp(pname, ptab, plen) != 0) {
7303 continue;
7304 }
7305 }
7306 #if defined(_WIN32) || defined(_WIN64)
7307 s->rows[roffs + 0] = xstrdup(d->xcelqrx ? "main" : "");
7308 s->rows[roffs + 1] = xstrdup("");
7309 #else
7310 s->rows[roffs + 0] = xstrdup("");
7311 s->rows[roffs + 1] = xstrdup("");
7312 #endif
7313 s->rows[roffs + 2] = xstrdup(ptab);
7314 s->rows[roffs + 3] = xstrdup(rowpp[k * nncols + toc]);
7315 s->rows[roffs + 4] = xstrdup("");
7316 s->rows[roffs + 5] = xstrdup("");
7317 s->rows[roffs + 6] = xstrdup(rowp[i]);
7318 s->rows[roffs + 7] = xstrdup(rowpp[k * nncols + fromc]);
7319 sscanf(rowpp[k * nncols + seqc], "%d", &pos);
7320 sprintf(buf, "%d", pos + 1);
7321 s->rows[roffs + 8] = xstrdup(buf);
7322 if (onu < 0) {
7323 s->rows[roffs + 9] = xstrdup(stringify(SQL_NO_ACTION));
7324 } else {
7325 if (strcmp(rowpp[k * nncols + onu], "SET NULL") == 0) {
7326 s->rows[roffs + 9] = xstrdup(stringify(SQL_SET_NULL));
7327 } else if (strcmp(rowpp[k * nncols + onu], "SET DEFAULT")
7328 == 0) {
7329 s->rows[roffs + 9] =
7330 xstrdup(stringify(SQL_SET_DEFAULT));
7331 } else if (strcmp(rowpp[k * nncols + onu], "CASCADE")
7332 == 0) {
7333 s->rows[roffs + 9] = xstrdup(stringify(SQL_CASCADE));
7334 } else if (strcmp(rowpp[k * nncols + onu], "RESTRICT")
7335 == 0) {
7336 s->rows[roffs + 9] = xstrdup(stringify(SQL_RESTRICT));
7337 } else {
7338 s->rows[roffs + 9] =
7339 xstrdup(stringify(SQL_NO_ACTION));
7340 }
7341 }
7342 if (ond < 0) {
7343 s->rows[roffs + 10] = xstrdup(stringify(SQL_NO_ACTION));
7344 } else {
7345 if (strcmp(rowpp[k * nncols + ond], "SET NULL") == 0) {
7346 s->rows[roffs + 10] = xstrdup(stringify(SQL_SET_NULL));
7347 } else if (strcmp(rowpp[k * nncols + ond], "SET DEFAULT")
7348 == 0) {
7349 s->rows[roffs + 10] =
7350 xstrdup(stringify(SQL_SET_DEFAULT));
7351 } else if (strcmp(rowpp[k * nncols + ond], "CASCADE")
7352 == 0) {
7353 s->rows[roffs + 10] = xstrdup(stringify(SQL_CASCADE));
7354 } else if (strcmp(rowpp[k * nncols + ond], "RESTRICT")
7355 == 0) {
7356 s->rows[roffs + 10] = xstrdup(stringify(SQL_RESTRICT));
7357 } else {
7358 s->rows[roffs + 10] =
7359 xstrdup(stringify(SQL_NO_ACTION));
7360 }
7361 }
7362 s->rows[roffs + 11] = NULL;
7363 s->rows[roffs + 12] = NULL;
7364 s->rows[roffs + 13] = xstrdup(stringify(SQL_NOT_DEFERRABLE));
7365 offs++;
7366 }
7367 freerows(rowpp);
7368 }
7369 freerows(rowp);
7370 }
7371 return SQL_SUCCESS;
7372 }
7373
7374 #ifndef WINTERFACE
7375 /**
7376 * Retrieve information about primary/foreign keys.
7377 * @param stmt statement handle
7378 * @param PKcatalog primary key catalog name/pattern or NULL
7379 * @param PKcatalogLen length of PKcatalog or SQL_NTS
7380 * @param PKschema primary key schema name/pattern or NULL
7381 * @param PKschemaLen length of PKschema or SQL_NTS
7382 * @param PKtable primary key table name/pattern or NULL
7383 * @param PKtableLen length of PKtable or SQL_NTS
7384 * @param FKcatalog foreign key catalog name/pattern or NULL
7385 * @param FKcatalogLen length of FKcatalog or SQL_NTS
7386 * @param FKschema foreign key schema name/pattern or NULL
7387 * @param FKschemaLen length of FKschema or SQL_NTS
7388 * @param FKtable foreign key table name/pattern or NULL
7389 * @param FKtableLen length of FKtable or SQL_NTS
7390 * @result ODBC error code
7391 */
7392
7393 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)7394 SQLForeignKeys(SQLHSTMT stmt,
7395 SQLCHAR *PKcatalog, SQLSMALLINT PKcatalogLen,
7396 SQLCHAR *PKschema, SQLSMALLINT PKschemaLen,
7397 SQLCHAR *PKtable, SQLSMALLINT PKtableLen,
7398 SQLCHAR *FKcatalog, SQLSMALLINT FKcatalogLen,
7399 SQLCHAR *FKschema, SQLSMALLINT FKschemaLen,
7400 SQLCHAR *FKtable, SQLSMALLINT FKtableLen)
7401 {
7402 #if defined(_WIN32) || defined(_WIN64)
7403 char *pc = NULL, *ps = NULL, *pt = NULL;
7404 char *fc = NULL, *fs = NULL, *ft = NULL;
7405 #endif
7406 SQLRETURN ret;
7407
7408 HSTMT_LOCK(stmt);
7409 #if defined(_WIN32) || defined(_WIN64)
7410 if (!((STMT *) stmt)->oemcp[0]) {
7411 ret = drvforeignkeys(stmt,
7412 PKcatalog, PKcatalogLen,
7413 PKschema, PKschemaLen, PKtable, PKtableLen,
7414 FKcatalog, FKcatalogLen,
7415 FKschema, FKschemaLen,
7416 FKtable, FKtableLen);
7417 goto done2;
7418 }
7419 if (PKcatalog) {
7420 pc = wmb_to_utf_c((char *) PKcatalog, PKcatalogLen);
7421 if (!pc) {
7422 ret = nomem((STMT *) stmt);
7423 goto done;
7424 }
7425 }
7426 if (PKschema) {
7427 ps = wmb_to_utf_c((char *) PKschema, PKschemaLen);
7428 if (!ps) {
7429 ret = nomem((STMT *) stmt);
7430 goto done;
7431 }
7432 }
7433 if (PKtable) {
7434 pt = wmb_to_utf_c((char *) PKtable, PKtableLen);
7435 if (!pt) {
7436 ret = nomem((STMT *) stmt);
7437 goto done;
7438 }
7439 }
7440 if (FKcatalog) {
7441 fc = wmb_to_utf_c((char *) FKcatalog, FKcatalogLen);
7442 if (!fc) {
7443 ret = nomem((STMT *) stmt);
7444 goto done;
7445 }
7446 }
7447 if (FKschema) {
7448 fs = wmb_to_utf_c((char *) FKschema, FKschemaLen);
7449 if (!fs) {
7450 ret = nomem((STMT *) stmt);
7451 goto done;
7452 }
7453 }
7454 if (FKtable) {
7455 ft = wmb_to_utf_c((char *) FKtable, FKtableLen);
7456 if (!ft) {
7457 ret = nomem((STMT *) stmt);
7458 goto done;
7459 }
7460 }
7461 ret = drvforeignkeys(stmt, (SQLCHAR *) pc, SQL_NTS,
7462 (SQLCHAR *) ps, SQL_NTS, (SQLCHAR *) pt, SQL_NTS,
7463 (SQLCHAR *) fc, SQL_NTS, (SQLCHAR *) fs, SQL_NTS,
7464 (SQLCHAR *) ft, SQL_NTS);
7465 #else
7466 ret = drvforeignkeys(stmt,
7467 PKcatalog, PKcatalogLen,
7468 PKschema, PKschemaLen, PKtable, PKtableLen,
7469 FKcatalog, FKcatalogLen,
7470 FKschema, FKschemaLen,
7471 FKtable, FKtableLen);
7472 #endif
7473 #if defined(_WIN32) || defined(_WIN64)
7474 done:
7475 uc_free(ft);
7476 uc_free(fs);
7477 uc_free(fc);
7478 uc_free(pt);
7479 uc_free(ps);
7480 uc_free(pc);
7481 done2:
7482 ;
7483 #endif
7484 HSTMT_UNLOCK(stmt);
7485 return ret;
7486 }
7487 #endif
7488
7489 #ifdef WINTERFACE
7490 /**
7491 * Retrieve information about primary/foreign keys (UNICODE version).
7492 * @param stmt statement handle
7493 * @param PKcatalog primary key catalog name/pattern or NULL
7494 * @param PKcatalogLen length of PKcatalog or SQL_NTS
7495 * @param PKschema primary key schema name/pattern or NULL
7496 * @param PKschemaLen length of PKschema or SQL_NTS
7497 * @param PKtable primary key table name/pattern or NULL
7498 * @param PKtableLen length of PKtable or SQL_NTS
7499 * @param FKcatalog foreign key catalog name/pattern or NULL
7500 * @param FKcatalogLen length of FKcatalog or SQL_NTS
7501 * @param FKschema foreign key schema name/pattern or NULL
7502 * @param FKschemaLen length of FKschema or SQL_NTS
7503 * @param FKtable foreign key table name/pattern or NULL
7504 * @param FKtableLen length of FKtable or SQL_NTS
7505 * @result ODBC error code
7506 */
7507
7508 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)7509 SQLForeignKeysW(SQLHSTMT stmt,
7510 SQLWCHAR *PKcatalog, SQLSMALLINT PKcatalogLen,
7511 SQLWCHAR *PKschema, SQLSMALLINT PKschemaLen,
7512 SQLWCHAR *PKtable, SQLSMALLINT PKtableLen,
7513 SQLWCHAR *FKcatalog, SQLSMALLINT FKcatalogLen,
7514 SQLWCHAR *FKschema, SQLSMALLINT FKschemaLen,
7515 SQLWCHAR *FKtable, SQLSMALLINT FKtableLen)
7516 {
7517 char *pc = NULL, *ps = NULL, *pt = NULL;
7518 char *fc = NULL, *fs = NULL, *ft = NULL;
7519 SQLRETURN ret;
7520
7521 HSTMT_LOCK(stmt);
7522 if (PKcatalog) {
7523 pc = uc_to_utf_c(PKcatalog, PKcatalogLen);
7524 if (!pc) {
7525 ret = nomem((STMT *) stmt);
7526 goto done;
7527 }
7528 }
7529 if (PKschema) {
7530 ps = uc_to_utf_c(PKschema, PKschemaLen);
7531 if (!ps) {
7532 ret = nomem((STMT *) stmt);
7533 goto done;
7534 }
7535 }
7536 if (PKtable) {
7537 pt = uc_to_utf_c(PKtable, PKtableLen);
7538 if (!pt) {
7539 ret = nomem((STMT *) stmt);
7540 goto done;
7541 }
7542 }
7543 if (FKcatalog) {
7544 fc = uc_to_utf_c(FKcatalog, FKcatalogLen);
7545 if (!fc) {
7546 ret = nomem((STMT *) stmt);
7547 goto done;
7548 }
7549 }
7550 if (FKschema) {
7551 fs = uc_to_utf_c(FKschema, FKschemaLen);
7552 if (!fs) {
7553 ret = nomem((STMT *) stmt);
7554 goto done;
7555 }
7556 }
7557 if (FKtable) {
7558 ft = uc_to_utf_c(FKtable, FKtableLen);
7559 if (!ft) {
7560 ret = nomem((STMT *) stmt);
7561 goto done;
7562 }
7563 }
7564 ret = drvforeignkeys(stmt, (SQLCHAR *) pc, SQL_NTS,
7565 (SQLCHAR *) ps, SQL_NTS, (SQLCHAR *) pt, SQL_NTS,
7566 (SQLCHAR *) fc, SQL_NTS, (SQLCHAR *) fs, SQL_NTS,
7567 (SQLCHAR *) ft, SQL_NTS);
7568 done:
7569 uc_free(ft);
7570 uc_free(fs);
7571 uc_free(fc);
7572 uc_free(pt);
7573 uc_free(ps);
7574 uc_free(pc);
7575 HSTMT_UNLOCK(stmt);
7576 return ret;
7577 }
7578 #endif
7579
7580 /**
7581 * Start transaction when autocommit off
7582 * @param s statement pointer
7583 * @result ODBC error code
7584 */
7585
7586 static SQLRETURN
starttran(STMT * s)7587 starttran(STMT *s)
7588 {
7589 int ret = SQL_SUCCESS, rc;
7590 char *errp = NULL;
7591 DBC *d = (DBC *) s->dbc;
7592
7593 if (!d->autocommit && !d->intrans && !d->trans_disable) {
7594 rc = sqlite4_exec(d->sqlite, "BEGIN TRANSACTION", NULL, NULL);
7595 dbtracerc(d, rc, NULL);
7596 if (rc != SQLITE4_OK) {
7597 setstat(s, rc, "%s (%d)", (*s->ov3) ? "HY000" : "S1000",
7598 errp ? errp : "unknown error", rc);
7599 ret = SQL_ERROR;
7600 } else {
7601 d->intrans = 1;
7602 }
7603 if (errp) {
7604 sqlite4_free(0, errp);
7605 errp = NULL;
7606 }
7607 }
7608 return ret;
7609 }
7610
7611 /**
7612 * Internal commit or rollback transaction.
7613 * @param d database connection pointer
7614 * @param comptype type of transaction's end, SQL_COMMIT or SQL_ROLLBACK
7615 * @param force force action regardless of DBC's autocommit state
7616 * @result ODBC error code
7617 */
7618
7619 static SQLRETURN
endtran(DBC * d,SQLSMALLINT comptype,int force)7620 endtran(DBC *d, SQLSMALLINT comptype, int force)
7621 {
7622 int ret;
7623 char *sql, *errp = NULL;
7624
7625 if (!d->sqlite) {
7626 setstatd(d, -1, "not connected", (*d->ov3) ? "HY000" : "S1000");
7627 return SQL_ERROR;
7628 }
7629 if ((!force && d->autocommit) || !d->intrans) {
7630 return SQL_SUCCESS;
7631 }
7632 switch (comptype) {
7633 case SQL_COMMIT:
7634 sql = "COMMIT TRANSACTION";
7635 goto doit;
7636 case SQL_ROLLBACK:
7637 sql = "ROLLBACK TRANSACTION";
7638 doit:
7639 ret = sqlite4_exec(d->sqlite, sql, NULL, NULL);
7640 dbtracerc(d, ret, NULL);
7641 if (ret != SQLITE4_OK) {
7642 setstatd(d, ret, "%s", (*d->ov3) ? "HY000" : "S1000",
7643 errp ? errp : "transaction failed");
7644 if (errp) {
7645 sqlite4_free(0, errp);
7646 errp = NULL;
7647 }
7648 return SQL_ERROR;
7649 }
7650 if (errp) {
7651 sqlite4_free(0, errp);
7652 errp = NULL;
7653 }
7654 d->intrans = 0;
7655 return SQL_SUCCESS;
7656 }
7657 setstatd(d, -1, "invalid completion type", (*d->ov3) ? "HY000" : "S1000");
7658 return SQL_ERROR;
7659 }
7660
7661 /**
7662 * Internal commit or rollback transaction.
7663 * @param type type of handle
7664 * @param handle HDBC, HENV, or HSTMT handle
7665 * @param comptype SQL_COMMIT or SQL_ROLLBACK
7666 * @result ODBC error code
7667 */
7668
7669 static SQLRETURN
drvendtran(SQLSMALLINT type,SQLHANDLE handle,SQLSMALLINT comptype)7670 drvendtran(SQLSMALLINT type, SQLHANDLE handle, SQLSMALLINT comptype)
7671 {
7672 DBC *dbc = NULL;
7673 int fail = 0;
7674 SQLRETURN ret;
7675 #if defined(_WIN32) || defined(_WIN64)
7676 ENV *env;
7677 #endif
7678
7679 switch (type) {
7680 case SQL_HANDLE_DBC:
7681 HDBC_LOCK((SQLHDBC) handle);
7682 if (handle == SQL_NULL_HDBC) {
7683 return SQL_INVALID_HANDLE;
7684 }
7685 dbc = (DBC *) handle;
7686 ret = endtran(dbc, comptype, 0);
7687 HDBC_UNLOCK((SQLHDBC) handle);
7688 return ret;
7689 case SQL_HANDLE_ENV:
7690 if (handle == SQL_NULL_HENV) {
7691 return SQL_INVALID_HANDLE;
7692 }
7693 #if defined(_WIN32) || defined(_WIN64)
7694 env = (ENV *) handle;
7695 if (env->magic != ENV_MAGIC) {
7696 return SQL_INVALID_HANDLE;
7697 }
7698 EnterCriticalSection(&env->cs);
7699 #endif
7700 dbc = ((ENV *) handle)->dbcs;
7701 while (dbc) {
7702 HDBC_LOCK((SQLHDBC) dbc);
7703 ret = endtran(dbc, comptype, 0);
7704 HDBC_UNLOCK((SQLHDBC) dbc);
7705 if (ret != SQL_SUCCESS) {
7706 fail++;
7707 }
7708 dbc = dbc->next;
7709 }
7710 #if defined(_WIN32) || defined(_WIN64)
7711 LeaveCriticalSection(&env->cs);
7712 #endif
7713 return fail ? SQL_ERROR : SQL_SUCCESS;
7714 }
7715 return SQL_INVALID_HANDLE;
7716 }
7717
7718 /**
7719 * Commit or rollback transaction.
7720 * @param type type of handle
7721 * @param handle HDBC, HENV, or HSTMT handle
7722 * @param comptype SQL_COMMIT or SQL_ROLLBACK
7723 * @result ODBC error code
7724 */
7725
7726 SQLRETURN SQL_API
SQLEndTran(SQLSMALLINT type,SQLHANDLE handle,SQLSMALLINT comptype)7727 SQLEndTran(SQLSMALLINT type, SQLHANDLE handle, SQLSMALLINT comptype)
7728 {
7729 return drvendtran(type, handle, comptype);
7730 }
7731
7732 /**
7733 * Commit or rollback transaction.
7734 * @param env environment handle or NULL
7735 * @param dbc database connection handle or NULL
7736 * @param type SQL_COMMIT or SQL_ROLLBACK
7737 * @result ODBC error code
7738 */
7739
7740 SQLRETURN SQL_API
SQLTransact(SQLHENV env,SQLHDBC dbc,SQLUSMALLINT type)7741 SQLTransact(SQLHENV env, SQLHDBC dbc, SQLUSMALLINT type)
7742 {
7743 if (dbc != SQL_NULL_HDBC) {
7744 return drvendtran(SQL_HANDLE_DBC, (SQLHANDLE) dbc, type);
7745 }
7746 return drvendtran(SQL_HANDLE_ENV, (SQLHANDLE) env, type);
7747 }
7748
7749 /**
7750 * Function not implemented.
7751 */
7752
7753 SQLRETURN SQL_API
SQLCopyDesc(SQLHDESC source,SQLHDESC target)7754 SQLCopyDesc(SQLHDESC source, SQLHDESC target)
7755 {
7756 return SQL_ERROR;
7757 }
7758
7759 #ifndef WINTERFACE
7760 /**
7761 * Translate SQL string.
7762 * @param stmt statement handle
7763 * @param sqlin input string
7764 * @param sqlinLen length of input string
7765 * @param sql output string
7766 * @param sqlMax max space in output string
7767 * @param sqlLen value return for length of output string
7768 * @result ODBC error code
7769 */
7770
7771 SQLRETURN SQL_API
SQLNativeSql(SQLHSTMT stmt,SQLCHAR * sqlin,SQLINTEGER sqlinLen,SQLCHAR * sql,SQLINTEGER sqlMax,SQLINTEGER * sqlLen)7772 SQLNativeSql(SQLHSTMT stmt, SQLCHAR *sqlin, SQLINTEGER sqlinLen,
7773 SQLCHAR *sql, SQLINTEGER sqlMax, SQLINTEGER *sqlLen)
7774 {
7775 int outLen = 0;
7776 SQLRETURN ret = SQL_SUCCESS;
7777
7778 HSTMT_LOCK(stmt);
7779 if (sqlinLen == SQL_NTS) {
7780 sqlinLen = strlen((char *) sqlin);
7781 }
7782 if (sql) {
7783 if (sqlMax > 0) {
7784 strncpy((char *) sql, (char *) sqlin, sqlMax - 1);
7785 sqlin[sqlMax - 1] = '\0';
7786 outLen = min(sqlMax - 1, sqlinLen);
7787 }
7788 } else {
7789 outLen = sqlinLen;
7790 }
7791 if (sqlLen) {
7792 *sqlLen = outLen;
7793 }
7794 if (sql && outLen < sqlinLen) {
7795 setstat((STMT *) stmt, -1, "data right truncated", "01004");
7796 ret = SQL_SUCCESS_WITH_INFO;
7797 }
7798 HSTMT_UNLOCK(stmt);
7799 return ret;
7800 }
7801 #endif
7802
7803 #ifdef WINTERFACE
7804 /**
7805 * Translate SQL string (UNICODE version).
7806 * @param stmt statement handle
7807 * @param sqlin input string
7808 * @param sqlinLen length of input string
7809 * @param sql output string
7810 * @param sqlMax max space in output string
7811 * @param sqlLen value return for length of output string
7812 * @result ODBC error code
7813 */
7814
7815 SQLRETURN SQL_API
SQLNativeSqlW(SQLHSTMT stmt,SQLWCHAR * sqlin,SQLINTEGER sqlinLen,SQLWCHAR * sql,SQLINTEGER sqlMax,SQLINTEGER * sqlLen)7816 SQLNativeSqlW(SQLHSTMT stmt, SQLWCHAR *sqlin, SQLINTEGER sqlinLen,
7817 SQLWCHAR *sql, SQLINTEGER sqlMax, SQLINTEGER *sqlLen)
7818 {
7819 int outLen = 0;
7820 SQLRETURN ret = SQL_SUCCESS;
7821
7822 HSTMT_LOCK(stmt);
7823 if (sqlinLen == SQL_NTS) {
7824 sqlinLen = uc_strlen(sqlin);
7825 }
7826 if (sql) {
7827 if (sqlMax > 0) {
7828 uc_strncpy(sql, sqlin, sqlMax - 1);
7829 sqlin[sqlMax - 1] = 0;
7830 outLen = min(sqlMax - 1, sqlinLen);
7831 }
7832 } else {
7833 outLen = sqlinLen;
7834 }
7835 if (sqlLen) {
7836 *sqlLen = outLen;
7837 }
7838 if (sql && outLen < sqlinLen) {
7839 setstat((STMT *) stmt, -1, "data right truncated", "01004");
7840 ret = SQL_SUCCESS_WITH_INFO;
7841 }
7842 HSTMT_UNLOCK(stmt);
7843 return ret;
7844 }
7845 #endif
7846
7847 /**
7848 * Columns for result set of SQLProcedures().
7849 */
7850
7851 static COL procSpec2[] = {
7852 { "SYSTEM", "PROCEDURE", "PROCEDURE_QUALIFIER", SCOL_VARCHAR, 50 },
7853 { "SYSTEM", "PROCEDURE", "PROCEDURE_OWNER", SCOL_VARCHAR, 50 },
7854 { "SYSTEM", "PROCEDURE", "PROCEDURE_NAME", SCOL_VARCHAR, 255 },
7855 { "SYSTEM", "PROCEDURE", "NUM_INPUT_PARAMS", SQL_SMALLINT, 5 },
7856 { "SYSTEM", "PROCEDURE", "NUM_OUTPUT_PARAMS", SQL_SMALLINT, 5 },
7857 { "SYSTEM", "PROCEDURE", "NUM_RESULT_SETS", SQL_SMALLINT, 5 },
7858 { "SYSTEM", "PROCEDURE", "REMARKS", SCOL_VARCHAR, 255 },
7859 { "SYSTEM", "PROCEDURE", "PROCEDURE_TYPE", SQL_SMALLINT, 5 }
7860 };
7861
7862 static COL procSpec3[] = {
7863 { "SYSTEM", "PROCEDURE", "PROCEDURE_CAT", SCOL_VARCHAR, 50 },
7864 { "SYSTEM", "PROCEDURE", "PROCEDURE_SCHEM", SCOL_VARCHAR, 50 },
7865 { "SYSTEM", "PROCEDURE", "PROCEDURE_NAME", SCOL_VARCHAR, 255 },
7866 { "SYSTEM", "PROCEDURE", "NUM_INPUT_PARAMS", SQL_SMALLINT, 5 },
7867 { "SYSTEM", "PROCEDURE", "NUM_OUTPUT_PARAMS", SQL_SMALLINT, 5 },
7868 { "SYSTEM", "PROCEDURE", "NUM_RESULT_SETS", SQL_SMALLINT, 5 },
7869 { "SYSTEM", "PROCEDURE", "REMARKS", SCOL_VARCHAR, 255 },
7870 { "SYSTEM", "PROCEDURE", "PROCEDURE_TYPE", SQL_SMALLINT, 5 }
7871 };
7872
7873 #ifndef WINTERFACE
7874 /**
7875 * Retrieve information about stored procedures.
7876 * @param stmt statement handle
7877 * @param catalog catalog name/pattern or NULL
7878 * @param catalogLen length of catalog or SQL_NTS
7879 * @param schema schema name/pattern or NULL
7880 * @param schemaLen length of schema or SQL_NTS
7881 * @param proc procedure name/pattern or NULL
7882 * @param procLen length of proc or SQL_NTS
7883 * @result ODBC error code
7884 */
7885
7886 SQLRETURN SQL_API
SQLProcedures(SQLHSTMT stmt,SQLCHAR * catalog,SQLSMALLINT catalogLen,SQLCHAR * schema,SQLSMALLINT schemaLen,SQLCHAR * proc,SQLSMALLINT procLen)7887 SQLProcedures(SQLHSTMT stmt,
7888 SQLCHAR *catalog, SQLSMALLINT catalogLen,
7889 SQLCHAR *schema, SQLSMALLINT schemaLen,
7890 SQLCHAR *proc, SQLSMALLINT procLen)
7891 {
7892 SQLRETURN ret;
7893
7894 HSTMT_LOCK(stmt);
7895 ret = mkresultset(stmt, procSpec2, array_size(procSpec2),
7896 procSpec3, array_size(procSpec3), NULL);
7897 HSTMT_UNLOCK(stmt);
7898 return ret;
7899 }
7900 #endif
7901
7902 #ifdef WINTERFACE
7903 /**
7904 * Retrieve information about stored procedures (UNICODE version).
7905 * @param stmt statement handle
7906 * @param catalog catalog name/pattern or NULL
7907 * @param catalogLen length of catalog or SQL_NTS
7908 * @param schema schema name/pattern or NULL
7909 * @param schemaLen length of schema or SQL_NTS
7910 * @param proc procedure name/pattern or NULL
7911 * @param procLen length of proc or SQL_NTS
7912 * @result ODBC error code
7913 */
7914
7915 SQLRETURN SQL_API
SQLProceduresW(SQLHSTMT stmt,SQLWCHAR * catalog,SQLSMALLINT catalogLen,SQLWCHAR * schema,SQLSMALLINT schemaLen,SQLWCHAR * proc,SQLSMALLINT procLen)7916 SQLProceduresW(SQLHSTMT stmt,
7917 SQLWCHAR *catalog, SQLSMALLINT catalogLen,
7918 SQLWCHAR *schema, SQLSMALLINT schemaLen,
7919 SQLWCHAR *proc, SQLSMALLINT procLen)
7920 {
7921 SQLRETURN ret;
7922
7923 HSTMT_LOCK(stmt);
7924 ret = mkresultset(stmt, procSpec2, array_size(procSpec2),
7925 procSpec3, array_size(procSpec3), NULL);
7926 HSTMT_UNLOCK(stmt);
7927 return ret;
7928 }
7929 #endif
7930
7931 /**
7932 * Columns for result set of SQLProcedureColumns().
7933 */
7934
7935 static COL procColSpec2[] = {
7936 { "SYSTEM", "PROCCOL", "PROCEDURE_QUALIFIER", SCOL_VARCHAR, 50 },
7937 { "SYSTEM", "PROCCOL", "PROCEDURE_OWNER", SCOL_VARCHAR, 50 },
7938 { "SYSTEM", "PROCCOL", "PROCEDURE_NAME", SCOL_VARCHAR, 255 },
7939 { "SYSTEM", "PROCCOL", "COLUMN_NAME", SCOL_VARCHAR, 255 },
7940 { "SYSTEM", "PROCCOL", "COLUMN_TYPE", SQL_SMALLINT, 5 },
7941 { "SYSTEM", "PROCCOL", "DATA_TYPE", SQL_SMALLINT, 5 },
7942 { "SYSTEM", "PROCCOL", "TYPE_NAME", SCOL_VARCHAR, 50 },
7943 { "SYSTEM", "PROCCOL", "PRECISION", SQL_INTEGER, 10 },
7944 { "SYSTEM", "PROCCOL", "LENGTH", SQL_INTEGER, 10 },
7945 { "SYSTEM", "PROCCOL", "SCALE", SQL_SMALLINT, 5 },
7946 { "SYSTEM", "PROCCOL", "RADIX", SQL_SMALLINT, 5 },
7947 { "SYSTEM", "PROCCOL", "NULLABLE", SQL_SMALLINT, 5 },
7948 { "SYSTEM", "PROCCOL", "REMARKS", SCOL_VARCHAR, 50 },
7949 { "SYSTEM", "PROCCOL", "COLUMN_DEF", SCOL_VARCHAR, 50 },
7950 { "SYSTEM", "PROCCOL", "SQL_DATA_TYPE", SQL_SMALLINT, 5 },
7951 { "SYSTEM", "PROCCOL", "SQL_DATETIME_SUB", SQL_SMALLINT, 5 },
7952 { "SYSTEM", "PROCCOL", "CHAR_OCTET_LENGTH", SQL_SMALLINT, 5 },
7953 { "SYSTEM", "PROCCOL", "ORDINAL_POSITION", SQL_SMALLINT, 5 },
7954 { "SYSTEM", "PROCCOL", "IS_NULLABLE", SCOL_VARCHAR, 50 }
7955 };
7956
7957 static COL procColSpec3[] = {
7958 { "SYSTEM", "PROCCOL", "PROCEDURE_CAT", SCOL_VARCHAR, 50 },
7959 { "SYSTEM", "PROCCOL", "PROCEDURE_SCHEM", SCOL_VARCHAR, 50 },
7960 { "SYSTEM", "PROCCOL", "PROCEDURE_NAME", SCOL_VARCHAR, 255 },
7961 { "SYSTEM", "PROCCOL", "COLUMN_NAME", SCOL_VARCHAR, 255 },
7962 { "SYSTEM", "PROCCOL", "COLUMN_TYPE", SQL_SMALLINT, 5 },
7963 { "SYSTEM", "PROCCOL", "DATA_TYPE", SQL_SMALLINT, 5 },
7964 { "SYSTEM", "PROCCOL", "TYPE_NAME", SCOL_VARCHAR, 50 },
7965 { "SYSTEM", "PROCCOL", "COLUMN_SIZE", SQL_INTEGER, 10 },
7966 { "SYSTEM", "PROCCOL", "BUFFER_LENGTH", SQL_INTEGER, 10 },
7967 { "SYSTEM", "PROCCOL", "DECIMAL_DIGITS", SQL_SMALLINT, 5 },
7968 { "SYSTEM", "PROCCOL", "NUM_PREC_RADIX", SQL_SMALLINT, 5 },
7969 { "SYSTEM", "PROCCOL", "NULLABLE", SQL_SMALLINT, 5 },
7970 { "SYSTEM", "PROCCOL", "REMARKS", SCOL_VARCHAR, 50 },
7971 { "SYSTEM", "PROCCOL", "COLUMN_DEF", SCOL_VARCHAR, 50 },
7972 { "SYSTEM", "PROCCOL", "SQL_DATA_TYPE", SQL_SMALLINT, 5 },
7973 { "SYSTEM", "PROCCOL", "SQL_DATETIME_SUB", SQL_SMALLINT, 5 },
7974 { "SYSTEM", "PROCCOL", "CHAR_OCTET_LENGTH", SQL_SMALLINT, 5 },
7975 { "SYSTEM", "PROCCOL", "ORDINAL_POSITION", SQL_SMALLINT, 5 },
7976 { "SYSTEM", "PROCCOL", "IS_NULLABLE", SCOL_VARCHAR, 50 }
7977 };
7978
7979 #ifndef WINTERFACE
7980 /**
7981 * Retrieve information about columns in result set of stored procedures.
7982 * @param stmt statement handle
7983 * @param catalog catalog name/pattern or NULL
7984 * @param catalogLen length of catalog or SQL_NTS
7985 * @param schema schema name/pattern or NULL
7986 * @param schemaLen length of schema or SQL_NTS
7987 * @param proc procedure name/pattern or NULL
7988 * @param procLen length of proc or SQL_NTS
7989 * @param column column name/pattern or NULL
7990 * @param columnLen length of column or SQL_NTS
7991 * @result ODBC error code
7992 */
7993
7994 SQLRETURN SQL_API
SQLProcedureColumns(SQLHSTMT stmt,SQLCHAR * catalog,SQLSMALLINT catalogLen,SQLCHAR * schema,SQLSMALLINT schemaLen,SQLCHAR * proc,SQLSMALLINT procLen,SQLCHAR * column,SQLSMALLINT columnLen)7995 SQLProcedureColumns(SQLHSTMT stmt,
7996 SQLCHAR *catalog, SQLSMALLINT catalogLen,
7997 SQLCHAR *schema, SQLSMALLINT schemaLen,
7998 SQLCHAR *proc, SQLSMALLINT procLen,
7999 SQLCHAR *column, SQLSMALLINT columnLen)
8000 {
8001 SQLRETURN ret;
8002
8003 HSTMT_LOCK(stmt);
8004 ret = mkresultset(stmt, procColSpec2, array_size(procColSpec2),
8005 procColSpec3, array_size(procColSpec3), NULL);
8006 HSTMT_UNLOCK(stmt);
8007 return ret;
8008 }
8009 #endif
8010
8011 #ifdef WINTERFACE
8012 /**
8013 * Retrieve information about columns in result
8014 * set of stored procedures (UNICODE version).
8015 * @param stmt statement handle
8016 * @param catalog catalog name/pattern or NULL
8017 * @param catalogLen length of catalog or SQL_NTS
8018 * @param schema schema name/pattern or NULL
8019 * @param schemaLen length of schema or SQL_NTS
8020 * @param proc procedure name/pattern or NULL
8021 * @param procLen length of proc or SQL_NTS
8022 * @param column column name/pattern or NULL
8023 * @param columnLen length of column or SQL_NTS
8024 * @result ODBC error code
8025 */
8026
8027 SQLRETURN SQL_API
SQLProcedureColumnsW(SQLHSTMT stmt,SQLWCHAR * catalog,SQLSMALLINT catalogLen,SQLWCHAR * schema,SQLSMALLINT schemaLen,SQLWCHAR * proc,SQLSMALLINT procLen,SQLWCHAR * column,SQLSMALLINT columnLen)8028 SQLProcedureColumnsW(SQLHSTMT stmt,
8029 SQLWCHAR *catalog, SQLSMALLINT catalogLen,
8030 SQLWCHAR *schema, SQLSMALLINT schemaLen,
8031 SQLWCHAR *proc, SQLSMALLINT procLen,
8032 SQLWCHAR *column, SQLSMALLINT columnLen)
8033 {
8034 SQLRETURN ret;
8035
8036 HSTMT_LOCK(stmt);
8037 ret = mkresultset(stmt, procColSpec2, array_size(procColSpec2),
8038 procColSpec3, array_size(procColSpec3), NULL);
8039 HSTMT_UNLOCK(stmt);
8040 return ret;
8041 }
8042 #endif
8043
8044 /**
8045 * Get information of HENV.
8046 * @param env environment handle
8047 * @param attr attribute to be retrieved
8048 * @param val output buffer
8049 * @param len length of output buffer
8050 * @param lenp output length
8051 * @result ODBC error code
8052 */
8053
8054 SQLRETURN SQL_API
SQLGetEnvAttr(SQLHENV env,SQLINTEGER attr,SQLPOINTER val,SQLINTEGER len,SQLINTEGER * lenp)8055 SQLGetEnvAttr(SQLHENV env, SQLINTEGER attr, SQLPOINTER val,
8056 SQLINTEGER len, SQLINTEGER *lenp)
8057 {
8058 ENV *e;
8059 SQLRETURN ret = SQL_ERROR;
8060
8061 if (env == SQL_NULL_HENV) {
8062 return SQL_INVALID_HANDLE;
8063 }
8064 e = (ENV *) env;
8065 if (!e || e->magic != ENV_MAGIC) {
8066 return SQL_INVALID_HANDLE;
8067 }
8068 #if defined(_WIN32) || defined(_WIN64)
8069 EnterCriticalSection(&e->cs);
8070 #endif
8071 switch (attr) {
8072 case SQL_ATTR_CONNECTION_POOLING:
8073 if (val) {
8074 *((SQLINTEGER *) val) = e->pool ?
8075 SQL_CP_ONE_PER_DRIVER : SQL_CP_OFF;
8076 }
8077 if (lenp) {
8078 *lenp = sizeof (SQLINTEGER);
8079 }
8080 ret = SQL_SUCCESS;
8081 break;
8082 case SQL_ATTR_CP_MATCH:
8083 *((SQLINTEGER *) val) = SQL_CP_RELAXED_MATCH;
8084 if (lenp) {
8085 *lenp = sizeof (SQLINTEGER);
8086 }
8087 ret = SQL_SUCCESS;
8088 break;
8089 case SQL_ATTR_OUTPUT_NTS:
8090 if (val) {
8091 *((SQLINTEGER *) val) = SQL_TRUE;
8092 }
8093 if (lenp) {
8094 *lenp = sizeof (SQLINTEGER);
8095 }
8096 ret = SQL_SUCCESS;
8097 break;
8098 case SQL_ATTR_ODBC_VERSION:
8099 if (val) {
8100 *((SQLINTEGER *) val) = e->ov3 ? SQL_OV_ODBC3 : SQL_OV_ODBC2;
8101 }
8102 if (lenp) {
8103 *lenp = sizeof (SQLINTEGER);
8104 }
8105 ret = SQL_SUCCESS;
8106 break;
8107 }
8108 #if defined(_WIN32) || defined(_WIN64)
8109 LeaveCriticalSection(&e->cs);
8110 #endif
8111 return ret;
8112 }
8113
8114 /**
8115 * Set information in HENV.
8116 * @param env environment handle
8117 * @param attr attribute to be retrieved
8118 * @param val parameter buffer
8119 * @param len length of parameter
8120 * @result ODBC error code
8121 */
8122
8123 SQLRETURN SQL_API
SQLSetEnvAttr(SQLHENV env,SQLINTEGER attr,SQLPOINTER val,SQLINTEGER len)8124 SQLSetEnvAttr(SQLHENV env, SQLINTEGER attr, SQLPOINTER val, SQLINTEGER len)
8125 {
8126 ENV *e;
8127 SQLRETURN ret = SQL_ERROR;
8128
8129 if (env == SQL_NULL_HENV) {
8130 return SQL_INVALID_HANDLE;
8131 }
8132 e = (ENV *) env;
8133 if (!e || e->magic != ENV_MAGIC) {
8134 return SQL_INVALID_HANDLE;
8135 }
8136 #if defined(_WIN32) || defined(_WIN64)
8137 EnterCriticalSection(&e->cs);
8138 #endif
8139 switch (attr) {
8140 case SQL_ATTR_CONNECTION_POOLING:
8141 if (val == (SQLPOINTER) SQL_CP_ONE_PER_DRIVER) {
8142 e->pool = 1;
8143 ret = SQL_SUCCESS;
8144 } else if (val == (SQLPOINTER) SQL_CP_OFF) {
8145 e->pool = 0;
8146 ret = SQL_SUCCESS;
8147 }
8148 break;
8149 case SQL_ATTR_CP_MATCH:
8150 ret = SQL_SUCCESS;
8151 break;
8152 case SQL_ATTR_OUTPUT_NTS:
8153 if (val == (SQLPOINTER) SQL_TRUE) {
8154 ret = SQL_SUCCESS;
8155 }
8156 break;
8157 case SQL_ATTR_ODBC_VERSION:
8158 if (!val) {
8159 break;
8160 }
8161 if (val == (SQLPOINTER) SQL_OV_ODBC2) {
8162 e->ov3 = 0;
8163 ret = SQL_SUCCESS;
8164 } else if (val == (SQLPOINTER) SQL_OV_ODBC3) {
8165 e->ov3 = 1;
8166 ret = SQL_SUCCESS;
8167 }
8168 break;
8169 }
8170 #if defined(_WIN32) || defined(_WIN64)
8171 LeaveCriticalSection(&e->cs);
8172 #endif
8173 return ret;
8174 }
8175
8176 /**
8177 * Internal get error message given handle (HENV, HDBC, or HSTMT).
8178 * @param htype handle type
8179 * @param handle HENV, HDBC, or HSTMT
8180 * @param recno
8181 * @param sqlstate output buffer for SQL state
8182 * @param nativeerr output buffer of native error code
8183 * @param msg output buffer for error message
8184 * @param buflen length of output buffer
8185 * @param msglen output length
8186 * @result ODBC error code
8187 */
8188
8189 static SQLRETURN
drvgetdiagrec(SQLSMALLINT htype,SQLHANDLE handle,SQLSMALLINT recno,SQLCHAR * sqlstate,SQLINTEGER * nativeerr,SQLCHAR * msg,SQLSMALLINT buflen,SQLSMALLINT * msglen)8190 drvgetdiagrec(SQLSMALLINT htype, SQLHANDLE handle, SQLSMALLINT recno,
8191 SQLCHAR *sqlstate, SQLINTEGER *nativeerr, SQLCHAR *msg,
8192 SQLSMALLINT buflen, SQLSMALLINT *msglen)
8193 {
8194 DBC *d = NULL;
8195 STMT *s = NULL;
8196 int len, naterr;
8197 char *logmsg, *sqlst;
8198 SQLRETURN ret = SQL_ERROR;
8199
8200 if (handle == SQL_NULL_HANDLE) {
8201 return SQL_INVALID_HANDLE;
8202 }
8203 if (sqlstate) {
8204 sqlstate[0] = '\0';
8205 }
8206 if (msg && buflen > 0) {
8207 msg[0] = '\0';
8208 }
8209 if (msglen) {
8210 *msglen = 0;
8211 }
8212 if (nativeerr) {
8213 *nativeerr = 0;
8214 }
8215 switch (htype) {
8216 case SQL_HANDLE_ENV:
8217 case SQL_HANDLE_DESC:
8218 return SQL_NO_DATA;
8219 case SQL_HANDLE_DBC:
8220 HDBC_LOCK((SQLHDBC) handle);
8221 d = (DBC *) handle;
8222 logmsg = (char *) d->logmsg;
8223 sqlst = d->sqlstate;
8224 naterr = d->naterr;
8225 break;
8226 case SQL_HANDLE_STMT:
8227 HSTMT_LOCK((SQLHSTMT) handle);
8228 s = (STMT *) handle;
8229 logmsg = (char *) s->logmsg;
8230 sqlst = s->sqlstate;
8231 naterr = s->naterr;
8232 break;
8233 default:
8234 return SQL_INVALID_HANDLE;
8235 }
8236 if (buflen < 0) {
8237 goto done;
8238 }
8239 if (recno > 1) {
8240 ret = SQL_NO_DATA;
8241 goto done;
8242 }
8243 len = strlen(logmsg);
8244 if (len == 0) {
8245 ret = SQL_NO_DATA;
8246 goto done;
8247 }
8248 if (nativeerr) {
8249 *nativeerr = naterr;
8250 }
8251 if (sqlstate) {
8252 strcpy((char *) sqlstate, sqlst);
8253 }
8254 if (msglen) {
8255 *msglen = len;
8256 }
8257 if (len >= buflen) {
8258 if (msg && buflen > 0) {
8259 strncpy((char *) msg, logmsg, buflen);
8260 msg[buflen - 1] = '\0';
8261 logmsg[0] = '\0';
8262 }
8263 } else if (msg) {
8264 strcpy((char *) msg, logmsg);
8265 logmsg[0] = '\0';
8266 }
8267 ret = SQL_SUCCESS;
8268 done:
8269 switch (htype) {
8270 case SQL_HANDLE_DBC:
8271 HDBC_UNLOCK((SQLHDBC) handle);
8272 break;
8273 case SQL_HANDLE_STMT:
8274 HSTMT_UNLOCK((SQLHSTMT) handle);
8275 break;
8276 }
8277 return ret;
8278 }
8279
8280 #if !defined(WINTERFACE) || (defined(HAVE_UNIXODBC) && (HAVE_UNIXODBC))
8281 /**
8282 * Get error message given handle (HENV, HDBC, or HSTMT).
8283 * @param htype handle type
8284 * @param handle HENV, HDBC, or HSTMT
8285 * @param recno
8286 * @param sqlstate output buffer for SQL state
8287 * @param nativeerr output buffer of native error code
8288 * @param msg output buffer for error message
8289 * @param buflen length of output buffer
8290 * @param msglen output length
8291 * @result ODBC error code
8292 */
8293
8294 SQLRETURN SQL_API
SQLGetDiagRec(SQLSMALLINT htype,SQLHANDLE handle,SQLSMALLINT recno,SQLCHAR * sqlstate,SQLINTEGER * nativeerr,SQLCHAR * msg,SQLSMALLINT buflen,SQLSMALLINT * msglen)8295 SQLGetDiagRec(SQLSMALLINT htype, SQLHANDLE handle, SQLSMALLINT recno,
8296 SQLCHAR *sqlstate, SQLINTEGER *nativeerr, SQLCHAR *msg,
8297 SQLSMALLINT buflen, SQLSMALLINT *msglen)
8298 {
8299 return drvgetdiagrec(htype, handle, recno, sqlstate,
8300 nativeerr, msg, buflen, msglen);
8301 }
8302 #endif
8303
8304 #if !defined(HAVE_UNIXODBC) || !(HAVE_UNIXODBC)
8305 #ifdef WINTERFACE
8306 /**
8307 * Get error message given handle (HENV, HDBC, or HSTMT)
8308 * (UNICODE version).
8309 * @param htype handle type
8310 * @param handle HENV, HDBC, or HSTMT
8311 * @param recno
8312 * @param sqlstate output buffer for SQL state
8313 * @param nativeerr output buffer of native error code
8314 * @param msg output buffer for error message
8315 * @param buflen length of output buffer
8316 * @param msglen output length
8317 * @result ODBC error code
8318 */
8319
8320 SQLRETURN SQL_API
SQLGetDiagRecW(SQLSMALLINT htype,SQLHANDLE handle,SQLSMALLINT recno,SQLWCHAR * sqlstate,SQLINTEGER * nativeerr,SQLWCHAR * msg,SQLSMALLINT buflen,SQLSMALLINT * msglen)8321 SQLGetDiagRecW(SQLSMALLINT htype, SQLHANDLE handle, SQLSMALLINT recno,
8322 SQLWCHAR *sqlstate, SQLINTEGER *nativeerr, SQLWCHAR *msg,
8323 SQLSMALLINT buflen, SQLSMALLINT *msglen)
8324 {
8325 char state[16];
8326 SQLSMALLINT len;
8327 SQLRETURN ret;
8328
8329 ret = drvgetdiagrec(htype, handle, recno, (SQLCHAR *) state,
8330 nativeerr, (SQLCHAR *) msg, buflen, &len);
8331 if (ret == SQL_SUCCESS) {
8332 if (sqlstate) {
8333 uc_from_utf_buf((SQLCHAR *) state, -1, sqlstate,
8334 6 * sizeof (SQLWCHAR));
8335 }
8336 if (msg) {
8337 if (len > 0) {
8338 SQLWCHAR *m = NULL;
8339
8340 m = uc_from_utf((unsigned char *) msg, len);
8341 if (m) {
8342 if (buflen) {
8343 buflen /= sizeof (SQLWCHAR);
8344 uc_strncpy(msg, m, buflen);
8345 m[len] = 0;
8346 len = min(buflen, uc_strlen(m));
8347 } else {
8348 len = uc_strlen(m);
8349 }
8350 uc_free(m);
8351 } else {
8352 len = 0;
8353 }
8354 }
8355 if (len <= 0) {
8356 len = 0;
8357 if (buflen > 0) {
8358 msg[0] = 0;
8359 }
8360 }
8361 } else {
8362 /* estimated length !!! */
8363 len *= sizeof (SQLWCHAR);
8364 }
8365 if (msglen) {
8366 *msglen = len;
8367 }
8368 } else if (ret == SQL_NO_DATA) {
8369 if (sqlstate) {
8370 sqlstate[0] = 0;
8371 }
8372 if (msg) {
8373 if (buflen > 0) {
8374 msg[0] = 0;
8375 }
8376 }
8377 if (msglen) {
8378 *msglen = 0;
8379 }
8380 }
8381 return ret;
8382 }
8383 #endif
8384 #endif
8385
8386 /**
8387 * Get error record given handle (HDBC or HSTMT).
8388 * @param htype handle type
8389 * @param handle HDBC or HSTMT
8390 * @param recno diag record number for which info to be retrieved
8391 * @param id diag id for which info to be retrieved
8392 * @param info output buffer for error message
8393 * @param buflen length of output buffer
8394 * @param stringlen output length
8395 * @result ODBC error code
8396 */
8397
8398 static SQLRETURN
drvgetdiagfield(SQLSMALLINT htype,SQLHANDLE handle,SQLSMALLINT recno,SQLSMALLINT id,SQLPOINTER info,SQLSMALLINT buflen,SQLSMALLINT * stringlen)8399 drvgetdiagfield(SQLSMALLINT htype, SQLHANDLE handle, SQLSMALLINT recno,
8400 SQLSMALLINT id, SQLPOINTER info,
8401 SQLSMALLINT buflen, SQLSMALLINT *stringlen)
8402 {
8403 DBC *d = NULL;
8404 STMT *s = NULL;
8405 int len, naterr, strbuf = 1;
8406 char *logmsg, *sqlst, *clrmsg = NULL;
8407 SQLRETURN ret = SQL_ERROR;
8408
8409 if (handle == SQL_NULL_HANDLE) {
8410 return SQL_INVALID_HANDLE;
8411 }
8412 if (stringlen) {
8413 *stringlen = 0;
8414 }
8415 switch (htype) {
8416 case SQL_HANDLE_ENV:
8417 case SQL_HANDLE_DESC:
8418 return SQL_NO_DATA;
8419 case SQL_HANDLE_DBC:
8420 HDBC_LOCK((SQLHDBC) handle);
8421 d = (DBC *) handle;
8422 logmsg = (char *) d->logmsg;
8423 sqlst = d->sqlstate;
8424 naterr = d->naterr;
8425 break;
8426 case SQL_HANDLE_STMT:
8427 HSTMT_LOCK((SQLHSTMT) handle);
8428 s = (STMT *) handle;
8429 d = (DBC *) s->dbc;
8430 logmsg = (char *) s->logmsg;
8431 sqlst = s->sqlstate;
8432 naterr = s->naterr;
8433 break;
8434 default:
8435 return SQL_INVALID_HANDLE;
8436 }
8437 if (buflen < 0) {
8438 switch (buflen) {
8439 case SQL_IS_POINTER:
8440 case SQL_IS_UINTEGER:
8441 case SQL_IS_INTEGER:
8442 case SQL_IS_USMALLINT:
8443 case SQL_IS_SMALLINT:
8444 strbuf = 0;
8445 break;
8446 default:
8447 ret = SQL_ERROR;
8448 goto done;
8449 }
8450 }
8451 if (recno > 1) {
8452 ret = SQL_NO_DATA;
8453 goto done;
8454 }
8455 switch (id) {
8456 case SQL_DIAG_CLASS_ORIGIN:
8457 logmsg = "ISO 9075";
8458 if (sqlst[0] == 'I' && sqlst[1] == 'M') {
8459 logmsg = "ODBC 3.0";
8460 }
8461 break;
8462 case SQL_DIAG_SUBCLASS_ORIGIN:
8463 logmsg = "ISO 9075";
8464 if (sqlst[0] == 'I' && sqlst[1] == 'M') {
8465 logmsg = "ODBC 3.0";
8466 } else if (sqlst[0] == 'H' && sqlst[1] == 'Y') {
8467 logmsg = "ODBC 3.0";
8468 } else if (sqlst[0] == '2' || sqlst[0] == '0' || sqlst[0] == '4') {
8469 logmsg = "ODBC 3.0";
8470 }
8471 break;
8472 case SQL_DIAG_CONNECTION_NAME:
8473 case SQL_DIAG_SERVER_NAME:
8474 logmsg = d->dsn ? d->dsn : "No DSN";
8475 break;
8476 case SQL_DIAG_SQLSTATE:
8477 logmsg = sqlst;
8478 break;
8479 case SQL_DIAG_MESSAGE_TEXT:
8480 if (info) {
8481 clrmsg = logmsg;
8482 }
8483 break;
8484 case SQL_DIAG_NUMBER:
8485 naterr = 1;
8486 /* fall through */
8487 case SQL_DIAG_NATIVE:
8488 len = strlen(logmsg);
8489 if (len == 0) {
8490 ret = SQL_NO_DATA;
8491 goto done;
8492 }
8493 if (info) {
8494 *((SQLINTEGER *) info) = naterr;
8495 }
8496 ret = SQL_SUCCESS;
8497 goto done;
8498 case SQL_DIAG_DYNAMIC_FUNCTION:
8499 logmsg = "";
8500 break;
8501 case SQL_DIAG_CURSOR_ROW_COUNT:
8502 if (htype == SQL_HANDLE_STMT) {
8503 SQLULEN count;
8504
8505 count = (s->isselect == 1 || s->isselect == -1) ? s->nrows : 0;
8506 *((SQLULEN *) info) = count;
8507 ret = SQL_SUCCESS;
8508 }
8509 goto done;
8510 case SQL_DIAG_ROW_COUNT:
8511 if (htype == SQL_HANDLE_STMT) {
8512 SQLULEN count;
8513
8514 count = s->isselect ? 0 : s->nrows;
8515 *((SQLULEN *) info) = count;
8516 ret = SQL_SUCCESS;
8517 }
8518 goto done;
8519 default:
8520 goto done;
8521 }
8522 if (info && buflen > 0) {
8523 ((char *) info)[0] = '\0';
8524 }
8525 len = strlen(logmsg);
8526 if (len == 0) {
8527 ret = SQL_NO_DATA;
8528 goto done;
8529 }
8530 if (stringlen) {
8531 *stringlen = len;
8532 }
8533 if (strbuf) {
8534 if (len >= buflen) {
8535 if (info && buflen > 0) {
8536 if (stringlen) {
8537 *stringlen = buflen - 1;
8538 }
8539 strncpy((char *) info, logmsg, buflen);
8540 ((char *) info)[buflen - 1] = '\0';
8541 }
8542 } else if (info) {
8543 strcpy((char *) info, logmsg);
8544 }
8545 }
8546 if (clrmsg) {
8547 *clrmsg = '\0';
8548 }
8549 ret = SQL_SUCCESS;
8550 done:
8551 switch (htype) {
8552 case SQL_HANDLE_DBC:
8553 HDBC_UNLOCK((SQLHDBC) handle);
8554 break;
8555 case SQL_HANDLE_STMT:
8556 HSTMT_UNLOCK((SQLHSTMT) handle);
8557 break;
8558 }
8559 return ret;
8560 }
8561
8562 #ifndef WINTERFACE
8563 /**
8564 * Get error record given handle (HDBC or HSTMT).
8565 * @param htype handle type
8566 * @param handle HDBC or HSTMT
8567 * @param recno diag record number for which info to be retrieved
8568 * @param id diag id for which info to be retrieved
8569 * @param info output buffer for error message
8570 * @param buflen length of output buffer
8571 * @param stringlen output length
8572 * @result ODBC error code
8573 */
8574
8575 SQLRETURN SQL_API
SQLGetDiagField(SQLSMALLINT htype,SQLHANDLE handle,SQLSMALLINT recno,SQLSMALLINT id,SQLPOINTER info,SQLSMALLINT buflen,SQLSMALLINT * stringlen)8576 SQLGetDiagField(SQLSMALLINT htype, SQLHANDLE handle, SQLSMALLINT recno,
8577 SQLSMALLINT id, SQLPOINTER info,
8578 SQLSMALLINT buflen, SQLSMALLINT *stringlen)
8579 {
8580 return drvgetdiagfield(htype, handle, recno, id, info, buflen, stringlen);
8581 }
8582 #endif
8583
8584 #ifdef WINTERFACE
8585 /**
8586 * Get error record given handle (HDBC or HSTMT).
8587 * @param htype handle type
8588 * @param handle HDBC or HSTMT
8589 * @param recno diag record number for which info to be retrieved
8590 * @param id diag id for which info to be retrieved
8591 * @param info output buffer for error message
8592 * @param buflen length of output buffer
8593 * @param stringlen output length
8594 * @result ODBC error code
8595 */
8596
8597 SQLRETURN SQL_API
SQLGetDiagFieldW(SQLSMALLINT htype,SQLHANDLE handle,SQLSMALLINT recno,SQLSMALLINT id,SQLPOINTER info,SQLSMALLINT buflen,SQLSMALLINT * stringlen)8598 SQLGetDiagFieldW(SQLSMALLINT htype, SQLHANDLE handle, SQLSMALLINT recno,
8599 SQLSMALLINT id, SQLPOINTER info,
8600 SQLSMALLINT buflen, SQLSMALLINT *stringlen)
8601 {
8602 SQLSMALLINT len;
8603 SQLRETURN ret;
8604
8605 ret = drvgetdiagfield(htype, handle, recno, id, info, buflen, &len);
8606 if (ret == SQL_SUCCESS) {
8607 if (info) {
8608 switch (id) {
8609 case SQL_DIAG_CLASS_ORIGIN:
8610 case SQL_DIAG_SUBCLASS_ORIGIN:
8611 case SQL_DIAG_CONNECTION_NAME:
8612 case SQL_DIAG_SERVER_NAME:
8613 case SQL_DIAG_SQLSTATE:
8614 case SQL_DIAG_MESSAGE_TEXT:
8615 case SQL_DIAG_DYNAMIC_FUNCTION:
8616 if (len > 0) {
8617 SQLWCHAR *m = NULL;
8618
8619 m = uc_from_utf((unsigned char *) info, len);
8620 if (m) {
8621 if (buflen) {
8622 buflen /= sizeof (SQLWCHAR);
8623 uc_strncpy(info, m, buflen);
8624 m[len] = 0;
8625 len = min(buflen, uc_strlen(m));
8626 } else {
8627 len = uc_strlen(m);
8628 }
8629 uc_free(m);
8630 len *= sizeof (SQLWCHAR);
8631 } else {
8632 len = 0;
8633 }
8634 }
8635 if (len <= 0) {
8636 len = 0;
8637 if (buflen > 0) {
8638 ((SQLWCHAR *) info)[0] = 0;
8639 }
8640 }
8641 }
8642 } else {
8643 switch (id) {
8644 case SQL_DIAG_CLASS_ORIGIN:
8645 case SQL_DIAG_SUBCLASS_ORIGIN:
8646 case SQL_DIAG_CONNECTION_NAME:
8647 case SQL_DIAG_SERVER_NAME:
8648 case SQL_DIAG_SQLSTATE:
8649 case SQL_DIAG_MESSAGE_TEXT:
8650 case SQL_DIAG_DYNAMIC_FUNCTION:
8651 len *= sizeof (SQLWCHAR);
8652 break;
8653 }
8654 }
8655 if (stringlen) {
8656 *stringlen = len;
8657 }
8658 }
8659 return ret;
8660 }
8661 #endif
8662
8663 /**
8664 * Internal get option of HSTMT.
8665 * @param stmt statement handle
8666 * @param attr attribute to be retrieved
8667 * @param val output buffer
8668 * @param bufmax length of output buffer
8669 * @param buflen output length
8670 * @result ODBC error code
8671 */
8672
8673 static SQLRETURN
drvgetstmtattr(SQLHSTMT stmt,SQLINTEGER attr,SQLPOINTER val,SQLINTEGER bufmax,SQLINTEGER * buflen)8674 drvgetstmtattr(SQLHSTMT stmt, SQLINTEGER attr, SQLPOINTER val,
8675 SQLINTEGER bufmax, SQLINTEGER *buflen)
8676 {
8677 STMT *s = (STMT *) stmt;
8678 SQLULEN *uval = (SQLULEN *) val;
8679 SQLINTEGER dummy;
8680 char dummybuf[16];
8681
8682 if (!buflen) {
8683 buflen = &dummy;
8684 }
8685 if (!uval) {
8686 uval = (SQLPOINTER) dummybuf;
8687 }
8688 switch (attr) {
8689 case SQL_QUERY_TIMEOUT:
8690 *uval = 0;
8691 *buflen = sizeof (SQLULEN);
8692 return SQL_SUCCESS;
8693 case SQL_ATTR_CURSOR_TYPE:
8694 *uval = s->curtype;
8695 *buflen = sizeof (SQLULEN);
8696 return SQL_SUCCESS;
8697 case SQL_ATTR_CURSOR_SCROLLABLE:
8698 *uval = (s->curtype != SQL_CURSOR_FORWARD_ONLY) ?
8699 SQL_SCROLLABLE : SQL_NONSCROLLABLE;
8700 *buflen = sizeof (SQLULEN);
8701 return SQL_SUCCESS;
8702 #ifdef SQL_ATTR_CURSOR_SENSITIVITY
8703 case SQL_ATTR_CURSOR_SENSITIVITY:
8704 *uval = SQL_UNSPECIFIED;
8705 *buflen = sizeof (SQLULEN);
8706 return SQL_SUCCESS;
8707 #endif
8708 case SQL_ATTR_ROW_NUMBER:
8709 if (s->s4stmt) {
8710 *uval = (s->s4stmt_rownum < 0) ?
8711 SQL_ROW_NUMBER_UNKNOWN : (s->s4stmt_rownum + 1);
8712 } else {
8713 *uval = (s->rowp < 0) ? SQL_ROW_NUMBER_UNKNOWN : (s->rowp + 1);
8714 }
8715 *buflen = sizeof (SQLULEN);
8716 return SQL_SUCCESS;
8717 case SQL_ATTR_ASYNC_ENABLE:
8718 *uval = SQL_ASYNC_ENABLE_OFF;
8719 *buflen = sizeof (SQLULEN);
8720 return SQL_SUCCESS;
8721 case SQL_CONCURRENCY:
8722 *uval = SQL_CONCUR_LOCK;
8723 *buflen = sizeof (SQLULEN);
8724 return SQL_SUCCESS;
8725 case SQL_ATTR_RETRIEVE_DATA:
8726 *uval = s->retr_data;
8727 *buflen = sizeof (SQLULEN);
8728 return SQL_SUCCESS;
8729 case SQL_ROWSET_SIZE:
8730 case SQL_ATTR_ROW_ARRAY_SIZE:
8731 *uval = s->rowset_size;
8732 *buflen = sizeof (SQLULEN);
8733 return SQL_SUCCESS;
8734 /* Needed for some driver managers, but dummies for now */
8735 case SQL_ATTR_IMP_ROW_DESC:
8736 case SQL_ATTR_APP_ROW_DESC:
8737 case SQL_ATTR_IMP_PARAM_DESC:
8738 case SQL_ATTR_APP_PARAM_DESC:
8739 *((SQLHDESC *) uval) = (SQLHDESC) DEAD_MAGIC;
8740 *buflen = sizeof (SQLHDESC);
8741 return SQL_SUCCESS;
8742 case SQL_ATTR_ROW_STATUS_PTR:
8743 *((SQLUSMALLINT **) uval) = s->row_status;
8744 *buflen = sizeof (SQLUSMALLINT *);
8745 return SQL_SUCCESS;
8746 case SQL_ATTR_ROWS_FETCHED_PTR:
8747 *((SQLULEN **) uval) = s->row_count;
8748 *buflen = sizeof (SQLULEN *);
8749 return SQL_SUCCESS;
8750 case SQL_ATTR_USE_BOOKMARKS: {
8751 STMT *s = (STMT *) stmt;
8752
8753 *(SQLUINTEGER *) uval = s->bkmrk;
8754 *buflen = sizeof (SQLUINTEGER);
8755 return SQL_SUCCESS;
8756 }
8757 case SQL_ATTR_FETCH_BOOKMARK_PTR:
8758 *(SQLPOINTER *) uval = s->bkmrkptr;
8759 *buflen = sizeof (SQLPOINTER);
8760 return SQL_SUCCESS;
8761 case SQL_ATTR_PARAM_BIND_OFFSET_PTR:
8762 *((SQLULEN **) uval) = s->parm_bind_offs;
8763 *buflen = sizeof (SQLULEN *);
8764 return SQL_SUCCESS;
8765 case SQL_ATTR_PARAM_BIND_TYPE:
8766 *((SQLULEN *) uval) = s->parm_bind_type;
8767 *buflen = sizeof (SQLULEN);
8768 return SQL_SUCCESS;
8769 case SQL_ATTR_PARAM_OPERATION_PTR:
8770 *((SQLUSMALLINT **) uval) = s->parm_oper;
8771 *buflen = sizeof (SQLUSMALLINT *);
8772 return SQL_SUCCESS;
8773 case SQL_ATTR_PARAM_STATUS_PTR:
8774 *((SQLUSMALLINT **) uval) = s->parm_status;
8775 *buflen = sizeof (SQLUSMALLINT *);
8776 return SQL_SUCCESS;
8777 case SQL_ATTR_PARAMS_PROCESSED_PTR:
8778 *((SQLULEN **) uval) = s->parm_proc;
8779 *buflen = sizeof (SQLULEN *);
8780 return SQL_SUCCESS;
8781 case SQL_ATTR_PARAMSET_SIZE:
8782 *((SQLULEN *) uval) = s->paramset_size;
8783 *buflen = sizeof (SQLULEN);
8784 return SQL_SUCCESS;
8785 case SQL_ATTR_ROW_BIND_TYPE:
8786 *(SQLULEN *) uval = s->bind_type;
8787 *buflen = sizeof (SQLULEN);
8788 return SQL_SUCCESS;
8789 case SQL_ATTR_ROW_BIND_OFFSET_PTR:
8790 *((SQLULEN **) uval) = s->bind_offs;
8791 *buflen = sizeof (SQLULEN *);
8792 return SQL_SUCCESS;
8793 case SQL_ATTR_MAX_ROWS:
8794 *((SQLULEN *) uval) = s->max_rows;
8795 *buflen = sizeof (SQLULEN);
8796 return SQL_SUCCESS;
8797 case SQL_ATTR_MAX_LENGTH:
8798 *((SQLULEN *) uval) = 1000000000;
8799 *buflen = sizeof (SQLULEN);
8800 return SQL_SUCCESS;
8801 #ifdef SQL_ATTR_METADATA_ID
8802 case SQL_ATTR_METADATA_ID:
8803 *((SQLULEN *) uval) = SQL_FALSE;
8804 *buflen = sizeof (SQLULEN);
8805 return SQL_SUCCESS;
8806 #endif
8807 }
8808 return drvunimplstmt(stmt);
8809 }
8810
8811 #if (defined(HAVE_UNIXODBC) && (HAVE_UNIXODBC)) || !defined(WINTERFACE)
8812 /**
8813 * Get option of HSTMT.
8814 * @param stmt statement handle
8815 * @param attr attribute to be retrieved
8816 * @param val output buffer
8817 * @param bufmax length of output buffer
8818 * @param buflen output length
8819 * @result ODBC error code
8820 */
8821
8822 SQLRETURN SQL_API
SQLGetStmtAttr(SQLHSTMT stmt,SQLINTEGER attr,SQLPOINTER val,SQLINTEGER bufmax,SQLINTEGER * buflen)8823 SQLGetStmtAttr(SQLHSTMT stmt, SQLINTEGER attr, SQLPOINTER val,
8824 SQLINTEGER bufmax, SQLINTEGER *buflen)
8825 {
8826 SQLRETURN ret;
8827
8828 HSTMT_LOCK(stmt);
8829 ret = drvgetstmtattr(stmt, attr, val, bufmax, buflen);
8830 HSTMT_UNLOCK(stmt);
8831 return ret;
8832 }
8833 #endif
8834
8835 #ifdef WINTERFACE
8836 /**
8837 * Get option of HSTMT (UNICODE version).
8838 * @param stmt statement handle
8839 * @param attr attribute to be retrieved
8840 * @param val output buffer
8841 * @param bufmax length of output buffer
8842 * @param buflen output length
8843 * @result ODBC error code
8844 */
8845
8846 SQLRETURN SQL_API
SQLGetStmtAttrW(SQLHSTMT stmt,SQLINTEGER attr,SQLPOINTER val,SQLINTEGER bufmax,SQLINTEGER * buflen)8847 SQLGetStmtAttrW(SQLHSTMT stmt, SQLINTEGER attr, SQLPOINTER val,
8848 SQLINTEGER bufmax, SQLINTEGER *buflen)
8849 {
8850 SQLRETURN ret;
8851
8852 HSTMT_LOCK(stmt);
8853 ret = drvgetstmtattr(stmt, attr, val, bufmax, buflen);
8854 HSTMT_UNLOCK(stmt);
8855 return ret;
8856 }
8857 #endif
8858
8859 /**
8860 * Internal set option on HSTMT.
8861 * @param stmt statement handle
8862 * @param attr attribute to be set
8863 * @param val input buffer (attribute value)
8864 * @param buflen length of input buffer
8865 * @result ODBC error code
8866 */
8867
8868 static SQLRETURN
drvsetstmtattr(SQLHSTMT stmt,SQLINTEGER attr,SQLPOINTER val,SQLINTEGER buflen)8869 drvsetstmtattr(SQLHSTMT stmt, SQLINTEGER attr, SQLPOINTER val,
8870 SQLINTEGER buflen)
8871 {
8872 STMT *s = (STMT *) stmt;
8873 #if defined(SQL_BIGINT) && defined(__WORDSIZE) && (__WORDSIZE == 64)
8874 SQLBIGINT uval;
8875
8876 uval = (SQLBIGINT) val;
8877 #else
8878 SQLULEN uval;
8879
8880 uval = (SQLULEN) val;
8881 #endif
8882 switch (attr) {
8883 case SQL_ATTR_CURSOR_TYPE:
8884 if (val == (SQLPOINTER) SQL_CURSOR_FORWARD_ONLY) {
8885 s->curtype = SQL_CURSOR_FORWARD_ONLY;
8886 } else {
8887 s->curtype = SQL_CURSOR_STATIC;
8888 }
8889 if (val != (SQLPOINTER) SQL_CURSOR_FORWARD_ONLY &&
8890 val != (SQLPOINTER) SQL_CURSOR_STATIC) {
8891 goto e01s02;
8892 }
8893 return SQL_SUCCESS;
8894 case SQL_ATTR_CURSOR_SCROLLABLE:
8895 if (val == (SQLPOINTER) SQL_NONSCROLLABLE) {
8896 s->curtype = SQL_CURSOR_FORWARD_ONLY;
8897 } else {
8898 s->curtype = SQL_CURSOR_STATIC;
8899 }
8900 return SQL_SUCCESS;
8901 case SQL_ATTR_ASYNC_ENABLE:
8902 if (val != (SQLPOINTER) SQL_ASYNC_ENABLE_OFF) {
8903 e01s02:
8904 setstat(s, -1, "option value changed", "01S02");
8905 return SQL_SUCCESS_WITH_INFO;
8906 }
8907 return SQL_SUCCESS;
8908 case SQL_CONCURRENCY:
8909 if (val != (SQLPOINTER) SQL_CONCUR_LOCK) {
8910 goto e01s02;
8911 }
8912 return SQL_SUCCESS;
8913 #ifdef SQL_ATTR_CURSOR_SENSITIVITY
8914 case SQL_ATTR_CURSOR_SENSITIVITY:
8915 if (val != (SQLPOINTER) SQL_UNSPECIFIED) {
8916 goto e01s02;
8917 }
8918 return SQL_SUCCESS;
8919 #endif
8920 case SQL_ATTR_QUERY_TIMEOUT:
8921 return SQL_SUCCESS;
8922 case SQL_ATTR_RETRIEVE_DATA:
8923 if (val != (SQLPOINTER) SQL_RD_ON &&
8924 val != (SQLPOINTER) SQL_RD_OFF) {
8925 goto e01s02;
8926 }
8927 s->retr_data = uval;
8928 return SQL_SUCCESS;
8929 case SQL_ROWSET_SIZE:
8930 case SQL_ATTR_ROW_ARRAY_SIZE:
8931 if (uval < 1) {
8932 setstat(s, -1, "invalid rowset size", "HY000");
8933 return SQL_ERROR;
8934 } else {
8935 SQLUSMALLINT *rst = &s->row_status1;
8936
8937 if (uval > 1) {
8938 rst = xmalloc(sizeof (SQLUSMALLINT) * uval);
8939 if (!rst) {
8940 return nomem(s);
8941 }
8942 }
8943 if (s->row_status0 != &s->row_status1) {
8944 freep(&s->row_status0);
8945 }
8946 s->row_status0 = rst;
8947 s->rowset_size = uval;
8948 }
8949 return SQL_SUCCESS;
8950 case SQL_ATTR_ROW_STATUS_PTR:
8951 s->row_status = (SQLUSMALLINT *) val;
8952 return SQL_SUCCESS;
8953 case SQL_ATTR_ROWS_FETCHED_PTR:
8954 s->row_count = (SQLULEN *) val;
8955 return SQL_SUCCESS;
8956 case SQL_ATTR_PARAM_BIND_OFFSET_PTR:
8957 s->parm_bind_offs = (SQLULEN *) val;
8958 return SQL_SUCCESS;
8959 case SQL_ATTR_PARAM_BIND_TYPE:
8960 s->parm_bind_type = uval;
8961 return SQL_SUCCESS;
8962 case SQL_ATTR_PARAM_OPERATION_PTR:
8963 s->parm_oper = (SQLUSMALLINT *) val;
8964 return SQL_SUCCESS;
8965 case SQL_ATTR_PARAM_STATUS_PTR:
8966 s->parm_status = (SQLUSMALLINT *) val;
8967 return SQL_SUCCESS;
8968 case SQL_ATTR_PARAMS_PROCESSED_PTR:
8969 s->parm_proc = (SQLULEN *) val;
8970 return SQL_SUCCESS;
8971 case SQL_ATTR_PARAMSET_SIZE:
8972 if (uval < 1) {
8973 goto e01s02;
8974 }
8975 s->paramset_size = uval;
8976 s->paramset_count = 0;
8977 return SQL_SUCCESS;
8978 case SQL_ATTR_ROW_BIND_TYPE:
8979 s->bind_type = uval;
8980 return SQL_SUCCESS;
8981 case SQL_ATTR_ROW_BIND_OFFSET_PTR:
8982 s->bind_offs = (SQLULEN *) val;
8983 return SQL_SUCCESS;
8984 case SQL_ATTR_USE_BOOKMARKS:
8985 if (val != (SQLPOINTER) SQL_UB_OFF &&
8986 val != (SQLPOINTER) SQL_UB_ON &&
8987 val != (SQLPOINTER) SQL_UB_VARIABLE) {
8988 goto e01s02;
8989 }
8990 if (*s->ov3 && val == (SQLPOINTER) SQL_UB_VARIABLE) {
8991 s->bkmrk = SQL_UB_VARIABLE;
8992 return SQL_SUCCESS;
8993 }
8994 if (val == (SQLPOINTER) SQL_UB_VARIABLE) {
8995 s->bkmrk = SQL_UB_ON;
8996 goto e01s02;
8997 }
8998 s->bkmrk = (val == (SQLPOINTER) SQL_UB_ON) ? SQL_UB_ON : SQL_UB_OFF;
8999 return SQL_SUCCESS;
9000 case SQL_ATTR_FETCH_BOOKMARK_PTR:
9001 s->bkmrkptr = (SQLINTEGER *) val;
9002 return SQL_SUCCESS;
9003 case SQL_ATTR_MAX_ROWS:
9004 s->max_rows = uval;
9005 return SQL_SUCCESS;
9006 case SQL_ATTR_MAX_LENGTH:
9007 if (val != (SQLPOINTER) 1000000000) {
9008 goto e01s02;
9009 }
9010 return SQL_SUCCESS;
9011 #ifdef SQL_ATTR_METADATA_ID
9012 case SQL_ATTR_METADATA_ID:
9013 if (val != (SQLPOINTER) SQL_FALSE) {
9014 goto e01s02;
9015 }
9016 return SQL_SUCCESS;
9017 #endif
9018 }
9019 return drvunimplstmt(stmt);
9020 }
9021
9022 #if (defined(HAVE_UNIXODBC) && (HAVE_UNIXODBC)) || !defined(WINTERFACE)
9023 /**
9024 * Set option on HSTMT.
9025 * @param stmt statement handle
9026 * @param attr attribute to be set
9027 * @param val input buffer (attribute value)
9028 * @param buflen length of input buffer
9029 * @result ODBC error code
9030 */
9031
9032 SQLRETURN SQL_API
SQLSetStmtAttr(SQLHSTMT stmt,SQLINTEGER attr,SQLPOINTER val,SQLINTEGER buflen)9033 SQLSetStmtAttr(SQLHSTMT stmt, SQLINTEGER attr, SQLPOINTER val,
9034 SQLINTEGER buflen)
9035 {
9036 SQLRETURN ret;
9037
9038 HSTMT_LOCK(stmt);
9039 ret = drvsetstmtattr(stmt, attr, val, buflen);
9040 HSTMT_UNLOCK(stmt);
9041 return ret;
9042 }
9043 #endif
9044
9045 #ifdef WINTERFACE
9046 /**
9047 * Set option on HSTMT (UNICODE version).
9048 * @param stmt statement handle
9049 * @param attr attribute to be set
9050 * @param val input buffer (attribute value)
9051 * @param buflen length of input buffer
9052 * @result ODBC error code
9053 */
9054
9055 SQLRETURN SQL_API
SQLSetStmtAttrW(SQLHSTMT stmt,SQLINTEGER attr,SQLPOINTER val,SQLINTEGER buflen)9056 SQLSetStmtAttrW(SQLHSTMT stmt, SQLINTEGER attr, SQLPOINTER val,
9057 SQLINTEGER buflen)
9058 {
9059 SQLRETURN ret;
9060
9061 HSTMT_LOCK(stmt);
9062 ret = drvsetstmtattr(stmt, attr, val, buflen);
9063 HSTMT_UNLOCK(stmt);
9064 return ret;
9065 }
9066 #endif
9067
9068 /**
9069 * Internal get option of HSTMT.
9070 * @param stmt statement handle
9071 * @param opt option to be retrieved
9072 * @param param output buffer
9073 * @result ODBC error code
9074 */
9075
9076 static SQLRETURN
drvgetstmtoption(SQLHSTMT stmt,SQLUSMALLINT opt,SQLPOINTER param)9077 drvgetstmtoption(SQLHSTMT stmt, SQLUSMALLINT opt, SQLPOINTER param)
9078 {
9079 STMT *s = (STMT *) stmt;
9080 SQLUINTEGER *ret = (SQLUINTEGER *) param;
9081
9082 switch (opt) {
9083 case SQL_QUERY_TIMEOUT:
9084 *ret = 0;
9085 return SQL_SUCCESS;
9086 case SQL_CURSOR_TYPE:
9087 *ret = s->curtype;
9088 return SQL_SUCCESS;
9089 case SQL_ROW_NUMBER:
9090 if (s->s4stmt) {
9091 *ret = (s->s4stmt_rownum < 0) ?
9092 SQL_ROW_NUMBER_UNKNOWN : (s->s4stmt_rownum + 1);
9093 } else {
9094 *ret = (s->rowp < 0) ? SQL_ROW_NUMBER_UNKNOWN : (s->rowp + 1);
9095 }
9096 return SQL_SUCCESS;
9097 case SQL_ASYNC_ENABLE:
9098 *ret = SQL_ASYNC_ENABLE_OFF;
9099 return SQL_SUCCESS;
9100 case SQL_CONCURRENCY:
9101 *ret = SQL_CONCUR_LOCK;
9102 return SQL_SUCCESS;
9103 case SQL_ATTR_RETRIEVE_DATA:
9104 *ret = s->retr_data;
9105 return SQL_SUCCESS;
9106 case SQL_ROWSET_SIZE:
9107 case SQL_ATTR_ROW_ARRAY_SIZE:
9108 *ret = s->rowset_size;
9109 return SQL_SUCCESS;
9110 case SQL_ATTR_MAX_ROWS:
9111 *ret = s->max_rows;
9112 return SQL_SUCCESS;
9113 case SQL_ATTR_MAX_LENGTH:
9114 *ret = 1000000000;
9115 return SQL_SUCCESS;
9116 }
9117 return drvunimplstmt(stmt);
9118 }
9119
9120 /**
9121 * Get option of HSTMT.
9122 * @param stmt statement handle
9123 * @param opt option to be retrieved
9124 * @param param output buffer
9125 * @result ODBC error code
9126 */
9127
9128 SQLRETURN SQL_API
SQLGetStmtOption(SQLHSTMT stmt,SQLUSMALLINT opt,SQLPOINTER param)9129 SQLGetStmtOption(SQLHSTMT stmt, SQLUSMALLINT opt, SQLPOINTER param)
9130 {
9131 SQLRETURN ret;
9132
9133 HSTMT_LOCK(stmt);
9134 ret = drvgetstmtoption(stmt, opt, param);
9135 HSTMT_UNLOCK(stmt);
9136 return ret;
9137 }
9138
9139 #ifdef WINTERFACE
9140 /**
9141 * Get option of HSTMT (UNICODE version).
9142 * @param stmt statement handle
9143 * @param opt option to be retrieved
9144 * @param param output buffer
9145 * @result ODBC error code
9146 */
9147
9148 SQLRETURN SQL_API
SQLGetStmtOptionW(SQLHSTMT stmt,SQLUSMALLINT opt,SQLPOINTER param)9149 SQLGetStmtOptionW(SQLHSTMT stmt, SQLUSMALLINT opt, SQLPOINTER param)
9150 {
9151 SQLRETURN ret;
9152
9153 HSTMT_LOCK(stmt);
9154 ret = drvgetstmtoption(stmt, opt, param);
9155 HSTMT_UNLOCK(stmt);
9156 return ret;
9157 }
9158 #endif
9159
9160 /**
9161 * Internal set option on HSTMT.
9162 * @param stmt statement handle
9163 * @param opt option to be set
9164 * @param param input buffer (option value)
9165 * @result ODBC error code
9166 */
9167
9168 static SQLRETURN
drvsetstmtoption(SQLHSTMT stmt,SQLUSMALLINT opt,SQLUINTEGER param)9169 drvsetstmtoption(SQLHSTMT stmt, SQLUSMALLINT opt, SQLUINTEGER param)
9170 {
9171 STMT *s = (STMT *) stmt;
9172
9173 switch (opt) {
9174 case SQL_CURSOR_TYPE:
9175 if (param == SQL_CURSOR_FORWARD_ONLY) {
9176 s->curtype = param;
9177 } else {
9178 s->curtype = SQL_CURSOR_STATIC;
9179 }
9180 if (param != SQL_CURSOR_FORWARD_ONLY &&
9181 param != SQL_CURSOR_STATIC) {
9182 goto e01s02;
9183 }
9184 return SQL_SUCCESS;
9185 case SQL_ASYNC_ENABLE:
9186 if (param != SQL_ASYNC_ENABLE_OFF) {
9187 goto e01s02;
9188 }
9189 return SQL_SUCCESS;
9190 case SQL_CONCURRENCY:
9191 if (param != SQL_CONCUR_LOCK) {
9192 goto e01s02;
9193 }
9194 return SQL_SUCCESS;
9195 case SQL_QUERY_TIMEOUT:
9196 return SQL_SUCCESS;
9197 case SQL_RETRIEVE_DATA:
9198 if (param != SQL_RD_ON && param != SQL_RD_OFF) {
9199 e01s02:
9200 setstat(s, -1, "option value changed", "01S02");
9201 return SQL_SUCCESS_WITH_INFO;
9202 }
9203 s->retr_data = (int) param;
9204 return SQL_SUCCESS;
9205 case SQL_ROWSET_SIZE:
9206 case SQL_ATTR_ROW_ARRAY_SIZE:
9207 if (param < 1) {
9208 setstat(s, -1, "invalid rowset size", "HY000");
9209 return SQL_ERROR;
9210 } else {
9211 SQLUSMALLINT *rst = &s->row_status1;
9212
9213 if (param > 1) {
9214 rst = xmalloc(sizeof (SQLUSMALLINT) * param);
9215 if (!rst) {
9216 return nomem(s);
9217 }
9218 }
9219 if (s->row_status0 != &s->row_status1) {
9220 freep(&s->row_status0);
9221 }
9222 s->row_status0 = rst;
9223 s->rowset_size = param;
9224 }
9225 return SQL_SUCCESS;
9226 case SQL_ATTR_MAX_ROWS:
9227 s->max_rows = param;
9228 return SQL_SUCCESS;
9229 case SQL_ATTR_MAX_LENGTH:
9230 if (param != 1000000000) {
9231 goto e01s02;
9232 }
9233 return SQL_SUCCESS;
9234 }
9235 return drvunimplstmt(stmt);
9236 }
9237
9238 /**
9239 * Set option on HSTMT.
9240 * @param stmt statement handle
9241 * @param opt option to be set
9242 * @param param input buffer (option value)
9243 * @result ODBC error code
9244 */
9245
9246 SQLRETURN SQL_API
SQLSetStmtOption(SQLHSTMT stmt,SQLUSMALLINT opt,SETSTMTOPTION_LAST_ARG_TYPE param)9247 SQLSetStmtOption(SQLHSTMT stmt, SQLUSMALLINT opt,
9248 SETSTMTOPTION_LAST_ARG_TYPE param)
9249 {
9250 SQLRETURN ret;
9251
9252 HSTMT_LOCK(stmt);
9253 ret = drvsetstmtoption(stmt, opt, (SQLUINTEGER) param);
9254 HSTMT_UNLOCK(stmt);
9255 return ret;
9256 }
9257
9258 #ifdef WINTERFACE
9259 /**
9260 * Set option on HSTMT (UNICODE version).
9261 * @param stmt statement handle
9262 * @param opt option to be set
9263 * @param param input buffer (option value)
9264 * @result ODBC error code
9265 */
9266
9267 SQLRETURN SQL_API
SQLSetStmtOptionW(SQLHSTMT stmt,SQLUSMALLINT opt,SETSTMTOPTION_LAST_ARG_TYPE param)9268 SQLSetStmtOptionW(SQLHSTMT stmt, SQLUSMALLINT opt,
9269 SETSTMTOPTION_LAST_ARG_TYPE param)
9270 {
9271 SQLRETURN ret;
9272
9273 HSTMT_LOCK(stmt);
9274 ret = drvsetstmtoption(stmt, opt, (SQLUINTEGER) param);
9275 HSTMT_UNLOCK(stmt);
9276 return ret;
9277 }
9278 #endif
9279
9280 /**
9281 * Check for unbound result columns.
9282 * @param s statement handle
9283 * @result ODBC error code
9284 */
9285
9286 static SQLRETURN
chkunbound(STMT * s)9287 chkunbound(STMT *s)
9288 {
9289 int i;
9290
9291 if (!s->bindcols || s->nbindcols < s->ncols) {
9292 unbound:
9293 setstat(s, -1, "unbound columns", (*s->ov3) ? "HY000" : "S1000");
9294 return SQL_ERROR;
9295 }
9296 for (i = 0; i < s->ncols; i++) {
9297 BINDCOL *b = &s->bindcols[i];
9298
9299 if (b->type == SQL_UNKNOWN_TYPE || !b->valp) {
9300 goto unbound;
9301 }
9302 }
9303 return SQL_SUCCESS;
9304 }
9305
9306 /**
9307 * Internal handler to setup parameters for positional updates
9308 * from bound user buffers.
9309 * @param s statement handle
9310 * @param stmt SQLite4 statement pointer
9311 * @param i result set column index
9312 * @param si SQLite4 parameter index
9313 * @param rsi result set row index
9314 * @result ODBC error code
9315 */
9316
9317 static SQLRETURN
setposbind(STMT * s,sqlite4_stmt * stmt,int i,int si,int rsi)9318 setposbind(STMT *s, sqlite4_stmt *stmt, int i, int si, int rsi)
9319 {
9320 DBC *d = (DBC *) s->dbc;
9321 SQLPOINTER dp = 0;
9322 SQLLEN *lp = 0;
9323 BINDCOL *b = &s->bindcols[i];
9324 COL *c = &s->cols[i];
9325 int frac;
9326 char strbuf[128], *cp;
9327
9328 if (b->valp) {
9329 if (s->bind_type != SQL_BIND_BY_COLUMN) {
9330 dp = (SQLPOINTER) ((char *) b->valp + s->bind_type * rsi);
9331 } else {
9332 dp = (SQLPOINTER) ((char *) b->valp + b->max * rsi);
9333 }
9334 if (s->bind_offs) {
9335 dp = (SQLPOINTER) ((char *) dp + *s->bind_offs);
9336 }
9337 }
9338 if (b->lenp) {
9339 if (s->bind_type != SQL_BIND_BY_COLUMN) {
9340 lp = (SQLLEN *) ((char *) b->lenp + s->bind_type * rsi);
9341 } else {
9342 lp = b->lenp + rsi;
9343 }
9344 if (s->bind_offs) {
9345 lp = (SQLLEN *) ((char *) lp + *s->bind_offs);
9346 }
9347 }
9348 if (!dp || !lp) {
9349 setstat(s, -1, "unbound column in positional update",
9350 (*s->ov3) ? "HY000" : "S1000");
9351 return SQL_ERROR;
9352 }
9353 if (*lp == SQL_NULL_DATA) {
9354 sqlite4_bind_null(stmt, si);
9355 if (d->trace) {
9356 fprintf(d->trace, "-- parameter %d: NULL\n", si);
9357 fflush(d->trace);
9358 }
9359 return SQL_SUCCESS;
9360 }
9361 switch (b->type) {
9362 case SQL_C_UTINYINT:
9363 case SQL_C_TINYINT:
9364 case SQL_C_STINYINT:
9365 sqlite4_bind_int(stmt, si, *(SQLCHAR *) dp);
9366 if (d->trace) {
9367 fprintf(d->trace, "-- parameter %d: %d\n", si, *(SQLCHAR *) dp);
9368 fflush(d->trace);
9369 }
9370 break;
9371 #ifdef SQL_BIT
9372 case SQL_C_BIT:
9373 sqlite4_bind_int(stmt, si, (*(SQLCHAR *) dp) ? 1 : 0);
9374 if (d->trace) {
9375 fprintf(d->trace, "-- parameter %d: %d\n", si,
9376 (*(SQLCHAR *) dp) ? 1 : 0);
9377 fflush(d->trace);
9378 }
9379 break;
9380 #endif
9381 case SQL_C_USHORT:
9382 sqlite4_bind_int(stmt, si, *(SQLUSMALLINT *) dp);
9383 if (d->trace) {
9384 fprintf(d->trace, "-- parameter %d: %d\n", si,
9385 *(SQLUSMALLINT *) dp);
9386 fflush(d->trace);
9387 }
9388 break;
9389 case SQL_C_SHORT:
9390 case SQL_C_SSHORT:
9391 sqlite4_bind_int(stmt, si, *(SQLSMALLINT *) dp);
9392 if (d->trace) {
9393 fprintf(d->trace, "-- parameter %d: %d\n", si,
9394 *(SQLSMALLINT *) dp);
9395 fflush(d->trace);
9396 }
9397 break;
9398 case SQL_C_ULONG:
9399 sqlite4_bind_int(stmt, si, *(SQLUINTEGER *) dp);
9400 if (d->trace) {
9401 fprintf(d->trace, "-- parameter %d: %ld\n", si,
9402 (long) *(SQLUINTEGER *) dp);
9403 fflush(d->trace);
9404 }
9405 break;
9406 case SQL_C_LONG:
9407 case SQL_C_SLONG:
9408 sqlite4_bind_int(stmt, si, *(SQLINTEGER *) dp);
9409 if (d->trace) {
9410 fprintf(d->trace, "-- parameter %d: %ld\n", si,
9411 (long) *(SQLINTEGER *) dp);
9412 fflush(d->trace);
9413 }
9414 break;
9415 #ifdef SQL_BIGINT
9416 case SQL_C_UBIGINT:
9417 case SQL_C_SBIGINT:
9418 sqlite4_bind_int64(stmt, si, *(SQLBIGINT *) dp);
9419 if (d->trace) {
9420 fprintf(d->trace,
9421 #ifdef _WIN32
9422 "-- parameter %d: %I64d\n",
9423 #else
9424 "-- parameter %d: %lld\n",
9425 #endif
9426 si, (sqlite4_int64) *(SQLBIGINT *) dp);
9427 fflush(d->trace);
9428 }
9429 break;
9430 #endif
9431 case SQL_C_FLOAT:
9432 sqlite4_bind_double(stmt, si, *(float *) dp);
9433 if (d->trace) {
9434 fprintf(d->trace, "-- parameter %d: %g\n", si,
9435 *(float *) dp);
9436 fflush(d->trace);
9437 }
9438 break;
9439 case SQL_C_DOUBLE:
9440 sqlite4_bind_double(stmt, si, *(double *) dp);
9441 if (d->trace) {
9442 fprintf(d->trace, "-- parameter %d: %g\n", si,
9443 *(double *) dp);
9444 fflush(d->trace);
9445 }
9446 break;
9447 case SQL_C_BINARY:
9448 sqlite4_bind_blob(stmt, si, (char *) dp, *lp, SQLITE4_STATIC, 0);
9449 if (d->trace) {
9450 fprintf(d->trace, "-- parameter %d: [BLOB]\n", si);
9451 fflush(d->trace);
9452 }
9453 break;
9454 #ifdef WCHARSUPPORT
9455 case SQL_C_WCHAR:
9456 cp = uc_to_utf((SQLWCHAR *) dp, *lp);
9457 if (!cp) {
9458 return nomem(s);
9459 }
9460 sqlite4_bind_text(stmt, si, cp, -1, SQLITE4_TRANSIENT, 0);
9461 if (d->trace) {
9462 fprintf(d->trace, "-- parameter %d: '%s'\n", si, cp);
9463 fflush(d->trace);
9464 }
9465 uc_free(cp);
9466 break;
9467 #endif
9468 case SQL_C_CHAR:
9469 #if defined(_WIN32) || defined(_WIN64)
9470 if (*s->oemcp) {
9471 cp = wmb_to_utf((char *) dp, *lp);
9472 if (!cp) {
9473 return nomem(s);
9474 }
9475 sqlite4_bind_text(stmt, si, cp, -1, SQLITE4_TRANSIENT, 0);
9476 if (d->trace) {
9477 fprintf(d->trace, "-- parameter %d: '%s'\n", si, cp);
9478 fflush(d->trace);
9479 }
9480 uc_free(cp);
9481 } else
9482 #endif
9483 {
9484 if (*lp == SQL_NTS) {
9485 sqlite4_bind_text(stmt, si, (char *) dp, -1,
9486 SQLITE4_STATIC, 0);
9487 if (d->trace) {
9488 fprintf(d->trace, "-- parameter %d: '%s'\n", si,
9489 (char *) dp);
9490 fflush(d->trace);
9491 }
9492 } else {
9493 sqlite4_bind_text(stmt, si, (char *) dp, *lp,
9494 SQLITE4_STATIC, 0);
9495 if (d->trace) {
9496 fprintf(d->trace, "-- parameter %d: '%*s'\n", si,
9497 (int) *lp, (char *) dp);
9498 fflush(d->trace);
9499 }
9500 }
9501 }
9502 break;
9503 #ifdef SQL_C_TYPE_DATE
9504 case SQL_C_TYPE_DATE:
9505 #endif
9506 case SQL_C_DATE:
9507 sprintf(strbuf, "%04d-%02d-%02d",
9508 ((DATE_STRUCT *) dp)->year,
9509 ((DATE_STRUCT *) dp)->month,
9510 ((DATE_STRUCT *) dp)->day);
9511 sqlite4_bind_text(stmt, si, strbuf, -1, SQLITE4_TRANSIENT, 0);
9512 if (d->trace) {
9513 fprintf(d->trace, "-- parameter %d: '%s'\n", si, strbuf);
9514 fflush(d->trace);
9515 }
9516 break;
9517 #ifdef SQL_C_TYPE_TIME
9518 case SQL_C_TYPE_TIME:
9519 #endif
9520 case SQL_C_TIME:
9521 sprintf(strbuf, "%02d:%02d:%02d",
9522 ((TIME_STRUCT *) dp)->hour,
9523 ((TIME_STRUCT *) dp)->minute,
9524 ((TIME_STRUCT *) dp)->second);
9525 sqlite4_bind_text(stmt, si, strbuf, -1, SQLITE4_TRANSIENT, 0);
9526 if (d->trace) {
9527 fprintf(d->trace, "-- parameter %d: '%s'\n", si, strbuf);
9528 fflush(d->trace);
9529 }
9530 break;
9531 #ifdef SQL_C_TYPE_TIMESTAMP
9532 case SQL_C_TYPE_TIMESTAMP:
9533 #endif
9534 case SQL_C_TIMESTAMP:
9535 frac = (int) ((TIMESTAMP_STRUCT *) dp)->fraction;
9536 frac /= 1000000;
9537 frac = frac % 1000;
9538 if (frac < 0) {
9539 frac = 0;
9540 }
9541 if (c->prec && c->prec <= 16) {
9542 sprintf(strbuf, "%04d-%02d-%02d %02d:%02d:00.000",
9543 ((TIMESTAMP_STRUCT *) dp)->year,
9544 ((TIMESTAMP_STRUCT *) dp)->month,
9545 ((TIMESTAMP_STRUCT *) dp)->day,
9546 ((TIMESTAMP_STRUCT *) dp)->hour,
9547 ((TIMESTAMP_STRUCT *) dp)->minute);
9548 } else if (c->prec && c->prec <= 19) {
9549 sprintf(strbuf, "%04d-%02d-%02d %02d:%02d:%02d.000",
9550 ((TIMESTAMP_STRUCT *) dp)->year,
9551 ((TIMESTAMP_STRUCT *) dp)->month,
9552 ((TIMESTAMP_STRUCT *) dp)->day,
9553 ((TIMESTAMP_STRUCT *) dp)->hour,
9554 ((TIMESTAMP_STRUCT *) dp)->minute,
9555 ((TIMESTAMP_STRUCT *) dp)->second);
9556 } else {
9557 sprintf(strbuf, "%04d-%02d-%02d %02d:%02d:%02d.%03d",
9558 ((TIMESTAMP_STRUCT *) dp)->year,
9559 ((TIMESTAMP_STRUCT *) dp)->month,
9560 ((TIMESTAMP_STRUCT *) dp)->day,
9561 ((TIMESTAMP_STRUCT *) dp)->hour,
9562 ((TIMESTAMP_STRUCT *) dp)->minute,
9563 ((TIMESTAMP_STRUCT *) dp)->second,
9564 frac);
9565 }
9566 sqlite4_bind_text(stmt, si, strbuf, -1, SQLITE4_TRANSIENT, 0);
9567 if (d->trace) {
9568 fprintf(d->trace, "-- parameter %d: '%s'\n", si, strbuf);
9569 fflush(d->trace);
9570 }
9571 break;
9572 default:
9573 setstat(s, -1, "unsupported column type in positional update",
9574 (*s->ov3) ? "HY000" : "S1000");
9575 return SQL_ERROR;
9576 }
9577 return SQL_SUCCESS;
9578 }
9579
9580 /**
9581 * Internal handler to setup parameters for positional updates
9582 * from driver side result set.
9583 * @param s statement handle
9584 * @param stmt SQLite4 statement pointer
9585 * @param i result set column index
9586 * @param si SQLite4 parameter index
9587 * @param rsi result set row index
9588 * @result ODBC error code
9589 */
9590
9591 static SQLRETURN
setposibind(STMT * s,sqlite4_stmt * stmt,int i,int si,int rsi)9592 setposibind(STMT *s, sqlite4_stmt *stmt, int i, int si, int rsi)
9593 {
9594 DBC *d = (DBC *) s->dbc;
9595 char **data;
9596 int pos;
9597
9598 pos = s->rowprs;
9599 if (pos < 0) {
9600 setstat(s, -1, "row out of range", (*s->ov3) ? "HY107" : "S1107");
9601 return SQL_ERROR;
9602 }
9603 pos += rsi;
9604 data = s->rows + s->ncols + (pos * s->ncols) + i;
9605 if (*data == NULL) {
9606 sqlite4_bind_null(stmt, si);
9607 if (d->trace) {
9608 fprintf(d->trace, "-- parameter %d: NULL\n", si);
9609 fflush(d->trace);
9610 }
9611 } else {
9612 sqlite4_bind_text(stmt, si, *data, -1, SQLITE4_STATIC, 0);
9613 if (d->trace) {
9614 fprintf(d->trace, "-- parameter %d: '%s'\n", si, *data);
9615 fflush(d->trace);
9616 }
9617 }
9618 return SQL_SUCCESS;
9619 }
9620
9621 /**
9622 * Internal handler to refresh user buffers from driver side result set.
9623 * @param s statement handle
9624 * @param rsi result set row index
9625 * @result ODBC error code
9626 */
9627
9628 static SQLRETURN
setposrefr(STMT * s,int rsi)9629 setposrefr(STMT *s, int rsi)
9630 {
9631 int i, withinfo = 0;
9632 SQLRETURN ret = SQL_SUCCESS;
9633
9634 for (i = 0; s->bindcols && i < s->ncols; i++) {
9635 BINDCOL *b = &s->bindcols[i];
9636 SQLPOINTER dp = 0;
9637 SQLLEN *lp = 0;
9638
9639 b->offs = 0;
9640 if (b->valp) {
9641 if (s->bind_type != SQL_BIND_BY_COLUMN) {
9642 dp = (SQLPOINTER) ((char *) b->valp + s->bind_type * rsi);
9643 } else {
9644 dp = (SQLPOINTER) ((char *) b->valp + b->max * rsi);
9645 }
9646 if (s->bind_offs) {
9647 dp = (SQLPOINTER) ((char *) dp + *s->bind_offs);
9648 }
9649 }
9650 if (b->lenp) {
9651 if (s->bind_type != SQL_BIND_BY_COLUMN) {
9652 lp = (SQLLEN *) ((char *) b->lenp + s->bind_type * rsi);
9653 } else {
9654 lp = b->lenp + rsi;
9655 }
9656 if (s->bind_offs) {
9657 lp = (SQLLEN *) ((char *) lp + *s->bind_offs);
9658 }
9659 }
9660 if (dp || lp) {
9661 int rowp = s->rowp;
9662
9663 s->rowp = s->rowprs + rsi;
9664 ret = getrowdata(s, (SQLUSMALLINT) i, b->type, dp,
9665 b->max, lp, 0);
9666 s->rowp = rowp;
9667 if (!SQL_SUCCEEDED(ret)) {
9668 s->row_status0[rsi] = SQL_ROW_ERROR;
9669 break;
9670 }
9671 if (ret != SQL_SUCCESS) {
9672 withinfo = 1;
9673 #ifdef SQL_ROW_SUCCESS_WITH_INFO
9674 s->row_status0[rsi] = SQL_ROW_SUCCESS_WITH_INFO;
9675 #endif
9676 }
9677 }
9678 }
9679 if (SQL_SUCCEEDED(ret)) {
9680 ret = withinfo ? SQL_SUCCESS_WITH_INFO : SQL_SUCCESS;
9681 }
9682 return ret;
9683 }
9684
9685 /**
9686 * Internal set position on result in HSTMT.
9687 * @param stmt statement handle
9688 * @param row row to be positioned
9689 * @param op operation code
9690 * @param lock locking type
9691 * @result ODBC error code
9692 */
9693
9694 static SQLRETURN
drvsetpos(SQLHSTMT stmt,SQLSETPOSIROW row,SQLUSMALLINT op,SQLUSMALLINT lock)9695 drvsetpos(SQLHSTMT stmt, SQLSETPOSIROW row, SQLUSMALLINT op, SQLUSMALLINT lock)
9696 {
9697 STMT *s = (STMT *) stmt;
9698 DBC *d = (DBC *) s->dbc;
9699 int rowp, i, k, rc;
9700 dstr *sql = 0;
9701 int sqlleft;
9702 sqlite4_stmt *s4stmt = NULL;
9703 SQLRETURN ret;
9704
9705 if (lock != SQL_LOCK_NO_CHANGE) {
9706 setstat(s, -1, "unsupported locking mode",
9707 (*s->ov3) ? "HY000" : "S1000");
9708 return SQL_ERROR;
9709 }
9710 if (s->isselect != 1 || s->curtype != SQL_CURSOR_STATIC) {
9711 setstat(s, -1, "incompatible statement",
9712 (*s->ov3) ? "HY000" : "S1000");
9713 return SQL_ERROR;
9714 }
9715 if (op == SQL_ADD) {
9716 if (s->one_tbl <= 0) {
9717 setstat(s, -1, "incompatible rowset",
9718 (*s->ov3) ? "HY000" : "S1000");
9719 return SQL_ERROR;
9720 }
9721 if (row == 0 || row > s->rowset_size + 1) {
9722 goto rowoor;
9723 }
9724 ret = chkunbound(s);
9725 if (ret != SQL_SUCCESS) {
9726 return ret;
9727 }
9728 sql = dsappend(sql, "INSERT INTO ");
9729 if (s->dyncols[0].db && s->dyncols[0].db[0]) {
9730 sql = dsappendq(sql, s->dyncols[0].db);
9731 sql = dsappend(sql, ".");
9732 }
9733 sql = dsappendq(sql, s->dyncols[0].table);
9734 for (i = 0; i < s->ncols; i++) {
9735 sql = dsappend(sql, (i > 0) ? "," : "(");
9736 sql = dsappendq(sql, s->dyncols[i].column);
9737 }
9738 sql = dsappend(sql, ") VALUES ");
9739 for (i = 0; i < s->ncols; i++) {
9740 sql = dsappend(sql, (i > 0) ? ",?" : "(?");
9741 }
9742 sql = dsappend(sql, ")");
9743 if (dserr(sql)) {
9744 dsfree(sql);
9745 return nomem(s);
9746 }
9747 dbtraceapi(d, "sqlite4_prepare", dsval(sql));
9748 s4stmt = NULL;
9749 rc = sqlite4_prepare(d->sqlite, dsval(sql), -1, &s4stmt, &sqlleft);
9750 dbtracerc(d, rc, NULL);
9751 dsfree(sql);
9752 if (rc != SQLITE4_OK) {
9753 istmterr:
9754 setstat(s, rc, "%s (%d)", (*s->ov3) ? "HY000" : "S1000",
9755 sqlite4_errmsg(d->sqlite), rc);
9756 if (s4stmt) {
9757 dbtraceapi(d, "sqlite4_finalize", NULL);
9758 sqlite4_finalize(s4stmt);
9759 }
9760 return SQL_ERROR;
9761 }
9762 for (i = 0, k = 1; s->bindcols && i < s->ncols; i++) {
9763 ret = setposbind(s, s4stmt, i, k, row - 1);
9764 if (ret != SQL_SUCCESS) {
9765 dbtraceapi(d, "sqlite4_finalize", NULL);
9766 sqlite4_finalize(s4stmt);
9767 return ret;
9768 }
9769 k++;
9770 }
9771 rc = sqlite4_step(s4stmt);
9772 if (rc != SQLITE4_DONE) {
9773 goto istmterr;
9774 }
9775 sqlite4_finalize(s4stmt);
9776 if (sqlite4_changes(d->sqlite) > 0 && row <= s->rowset_size) {
9777 if (s->row_status0) {
9778 s->row_status0[row - 1] = SQL_ROW_ADDED;
9779 }
9780 if (s->row_status) {
9781 s->row_status[row - 1] = SQL_ROW_ADDED;
9782 }
9783 }
9784 return SQL_SUCCESS;
9785 } else if (op == SQL_UPDATE || op == SQL_DELETE) {
9786 if (s->one_tbl <= 0 || s->has_pk <= 0) {
9787 setstat(s, -1, "incompatible rowset",
9788 (*s->ov3) ? "HY000" : "S1000");
9789 return SQL_ERROR;
9790 }
9791 if (row == 0) {
9792 ret = SQL_SUCCESS;
9793 for (i = 1; i <= s->rowset_size; i++) {
9794 ret = drvsetpos(stmt, i, op, lock);
9795 if (!SQL_SUCCEEDED(ret)) {
9796 break;
9797 }
9798 }
9799 return ret;
9800 }
9801 if (row > s->rowset_size) {
9802 goto rowoor;
9803 }
9804 }
9805 if (op != SQL_POSITION && op != SQL_REFRESH &&
9806 op != SQL_DELETE && op != SQL_UPDATE) {
9807 return drvunimplstmt(stmt);
9808 }
9809 if (op == SQL_POSITION) {
9810 rowp = s->rowp + row - 1;
9811 if (!s->rows || row == 0 || rowp < -1 || rowp >= s->nrows) {
9812 rowoor:
9813 setstat(s, -1, "row out of range", (*s->ov3) ? "HY107" : "S1107");
9814 return SQL_ERROR;
9815 }
9816 s->rowp = rowp;
9817 } else if (op == SQL_REFRESH) {
9818 if (row > s->rowset_size) {
9819 goto rowoor;
9820 }
9821 if (row == 0) {
9822 ret = SQL_SUCCESS;
9823 for (i = 0; i < s->rowset_size; i++) {
9824 ret = setposrefr(s, i);
9825 if (!SQL_SUCCEEDED(ret)) {
9826 break;
9827 }
9828 }
9829 return ret;
9830 }
9831 return setposrefr(s, row - 1);
9832 } else if (op == SQL_DELETE) {
9833 sql = dsappend(sql, "DELETE FROM ");
9834 if (s->dyncols[0].db && s->dyncols[0].db[0]) {
9835 sql = dsappendq(sql, s->dyncols[0].db);
9836 sql = dsappend(sql, ".");
9837 }
9838 sql = dsappendq(sql, s->dyncols[0].table);
9839 for (i = k = 0; i < s->ncols; i++) {
9840 if (s->dyncols[i].ispk <= 0) {
9841 continue;
9842 }
9843 sql = dsappend(sql, (k > 0) ? " AND " : " WHERE ");
9844 sql = dsappendq(sql, s->dyncols[i].column);
9845 sql = dsappend(sql, " = ?");
9846 k++;
9847 }
9848 if (dserr(sql)) {
9849 dsfree(sql);
9850 return nomem(s);
9851 }
9852 dbtraceapi(d, "sqlite4_prepare", dsval(sql));
9853 s4stmt = NULL;
9854 rc = sqlite4_prepare(d->sqlite, dsval(sql), -1, &s4stmt, &sqlleft);
9855 dbtracerc(d, rc, NULL);
9856 dsfree(sql);
9857 if (rc != SQLITE4_OK) {
9858 dstmterr:
9859 setstat(s, rc, "%s (%d)", (*s->ov3) ? "HY000" : "S1000",
9860 sqlite4_errmsg(d->sqlite), rc);
9861 if (s4stmt) {
9862 dbtraceapi(d, "sqlite4_finalize", NULL);
9863 sqlite4_finalize(s4stmt);
9864 }
9865 return SQL_ERROR;
9866 }
9867 for (i = 0, k = 1; s->bindcols && i < s->ncols; i++) {
9868 if (s->dyncols[i].ispk <= 0) {
9869 continue;
9870 }
9871 ret = setposibind(s, s4stmt, i, k, row - 1);
9872 if (ret != SQL_SUCCESS) {
9873 dbtraceapi(d, "sqlite4_finalize", NULL);
9874 sqlite4_finalize(s4stmt);
9875 return ret;
9876 }
9877 k++;
9878 }
9879 rc = sqlite4_step(s4stmt);
9880 if (rc != SQLITE4_DONE) {
9881 goto dstmterr;
9882 }
9883 sqlite4_finalize(s4stmt);
9884 if (sqlite4_changes(d->sqlite) > 0) {
9885 if (s->row_status0) {
9886 s->row_status0[row - 1] = SQL_ROW_DELETED;
9887 }
9888 if (s->row_status) {
9889 s->row_status[row - 1] = SQL_ROW_DELETED;
9890 }
9891 }
9892 return SQL_SUCCESS;
9893 } else if (op == SQL_UPDATE) {
9894 ret = chkunbound(s);
9895 if (ret != SQL_SUCCESS) {
9896 return ret;
9897 }
9898 sql = dsappend(sql, "UPDATE ");
9899 if (s->dyncols[0].db && s->dyncols[0].db[0]) {
9900 sql = dsappendq(sql, s->dyncols[0].db);
9901 sql = dsappend(sql, ".");
9902 }
9903 sql = dsappendq(sql, s->dyncols[0].table);
9904 for (i = 0; i < s->ncols; i++) {
9905 sql = dsappend(sql, (i > 0) ? ", " : " SET ");
9906 sql = dsappendq(sql, s->dyncols[i].column);
9907 sql = dsappend(sql, " = ?");
9908 }
9909 for (i = k = 0; i < s->ncols; i++) {
9910 if (s->dyncols[i].ispk <= 0) {
9911 continue;
9912 }
9913 sql = dsappend(sql, (k > 0) ? " AND " : " WHERE ");
9914 sql = dsappendq(sql, s->dyncols[i].column);
9915 sql = dsappend(sql, " = ?");
9916 k++;
9917 }
9918 if (dserr(sql)) {
9919 dsfree(sql);
9920 return nomem(s);
9921 }
9922 dbtraceapi(d, "sqlite4_prepare", dsval(sql));
9923 s4stmt = NULL;
9924 rc = sqlite4_prepare(d->sqlite, dsval(sql), -1, &s4stmt, &sqlleft);
9925 dbtracerc(d, rc, NULL);
9926 dsfree(sql);
9927 if (rc != SQLITE4_OK) {
9928 ustmterr:
9929 setstat(s, rc, "%s (%d)", (*s->ov3) ? "HY000" : "S1000",
9930 sqlite4_errmsg(d->sqlite), rc);
9931 if (s4stmt) {
9932 dbtraceapi(d, "sqlite4_finalize", NULL);
9933 sqlite4_finalize(s4stmt);
9934 }
9935 return SQL_ERROR;
9936 }
9937 for (i = 0, k = 1; s->bindcols && i < s->ncols; i++) {
9938 ret = setposbind(s, s4stmt, i, k, row - 1);
9939 if (ret != SQL_SUCCESS) {
9940 dbtraceapi(d, "sqlite4_finalize", NULL);
9941 sqlite4_finalize(s4stmt);
9942 return ret;
9943 }
9944 k++;
9945 }
9946 for (i = 0; s->bindcols && i < s->ncols; i++) {
9947 if (s->dyncols[i].ispk <= 0) {
9948 continue;
9949 }
9950 ret = setposibind(s, s4stmt, i, k, row - 1);
9951 if (ret != SQL_SUCCESS) {
9952 dbtraceapi(d, "sqlite4_finalize", NULL);
9953 sqlite4_finalize(s4stmt);
9954 return ret;
9955 }
9956 k++;
9957 }
9958 rc = sqlite4_step(s4stmt);
9959 if (rc != SQLITE4_DONE) {
9960 goto ustmterr;
9961 }
9962 sqlite4_finalize(s4stmt);
9963 if (sqlite4_changes(d->sqlite) > 0) {
9964 if (s->row_status0) {
9965 s->row_status0[row - 1] = SQL_ROW_UPDATED;
9966 }
9967 if (s->row_status) {
9968 s->row_status[row - 1] = SQL_ROW_UPDATED;
9969 }
9970 }
9971 return SQL_SUCCESS;
9972 }
9973 return SQL_SUCCESS;
9974 }
9975
9976 /**
9977 * Set position on result in HSTMT.
9978 * @param stmt statement handle
9979 * @param row row to be positioned
9980 * @param op operation code
9981 * @param lock locking type
9982 * @result ODBC error code
9983 */
9984
9985 SQLRETURN SQL_API
SQLSetPos(SQLHSTMT stmt,SQLSETPOSIROW row,SQLUSMALLINT op,SQLUSMALLINT lock)9986 SQLSetPos(SQLHSTMT stmt, SQLSETPOSIROW row, SQLUSMALLINT op, SQLUSMALLINT lock)
9987 {
9988 SQLRETURN ret;
9989
9990 HSTMT_LOCK(stmt);
9991 ret = drvsetpos(stmt, row, op, lock);
9992 HSTMT_UNLOCK(stmt);
9993 return ret;
9994 }
9995
9996 /**
9997 * Internal perform bulk operation on HSTMT.
9998 * @param stmt statement handle
9999 * @param op operation to be performed
10000 * @result ODBC error code
10001 */
10002
10003 static SQLRETURN
drvbulkoperations(SQLHSTMT stmt,SQLSMALLINT op)10004 drvbulkoperations(SQLHSTMT stmt, SQLSMALLINT op)
10005 {
10006 STMT *s = (STMT *) stmt;
10007 DBC *d = (DBC *) s->dbc;
10008 int row, i, k, rc;
10009 dstr *sql = 0;
10010 int sqlleft;
10011 sqlite4_stmt *s4stmt = NULL;
10012 SQLRETURN ret;
10013
10014 if (s->isselect != 1 || s->curtype != SQL_CURSOR_STATIC) {
10015 setstat(s, -1, "incompatible statement",
10016 (*s->ov3) ? "HY000" : "S1000");
10017 return SQL_ERROR;
10018 }
10019 if (op == SQL_ADD) {
10020 if (s->one_tbl <= 0) {
10021 setstat(s, -1, "incompatible rowset",
10022 (*s->ov3) ? "HY000" : "S1000");
10023 return SQL_ERROR;
10024 }
10025 ret = chkunbound(s);
10026 if (ret != SQL_SUCCESS) {
10027 return ret;
10028 }
10029 sql = dsappend(sql, "INSERT INTO ");
10030 if (s->dyncols[0].db && s->dyncols[0].db[0]) {
10031 sql = dsappendq(sql, s->dyncols[0].db);
10032 sql = dsappend(sql, ".");
10033 }
10034 sql = dsappendq(sql, s->dyncols[0].table);
10035 for (i = 0; i < s->ncols; i++) {
10036 sql = dsappend(sql, (i > 0) ? "," : "(");
10037 sql = dsappendq(sql, s->dyncols[i].column);
10038 }
10039 sql = dsappend(sql, ") VALUES ");
10040 for (i = 0; i < s->ncols; i++) {
10041 sql = dsappend(sql, (i > 0) ? ",?" : "(?");
10042 }
10043 sql = dsappend(sql, ")");
10044 if (dserr(sql)) {
10045 dsfree(sql);
10046 return nomem(s);
10047 }
10048 dbtraceapi(d, "sqlite4_prepare", dsval(sql));
10049 s4stmt = NULL;
10050 rc = sqlite4_prepare(d->sqlite, dsval(sql), -1, &s4stmt, &sqlleft);
10051 dbtracerc(d, rc, NULL);
10052 dsfree(sql);
10053 if (rc != SQLITE4_OK) {
10054 setstat(s, rc, "%s (%d)", (*s->ov3) ? "HY000" : "S1000",
10055 sqlite4_errmsg(d->sqlite), rc);
10056 if (s4stmt) {
10057 dbtraceapi(d, "sqlite4_finalize", NULL);
10058 sqlite4_finalize(s4stmt);
10059 }
10060 return SQL_ERROR;
10061 }
10062 for (row = 0; row < s->rowset_size; row++) {
10063 for (i = 0, k = 1; s->bindcols && i < s->ncols; i++) {
10064 ret = setposbind(s, s4stmt, i, k, row);
10065 if (ret != SQL_SUCCESS) {
10066 istmterr:
10067 if (s->row_status0) {
10068 s->row_status0[row] = SQL_ROW_ERROR;
10069 }
10070 if (s->row_status) {
10071 s->row_status[row] = SQL_ROW_ERROR;
10072 }
10073 dbtraceapi(d, "sqlite4_finalize", NULL);
10074 sqlite4_finalize(s4stmt);
10075 return ret;
10076 }
10077 k++;
10078 }
10079 rc = sqlite4_step(s4stmt);
10080 if (rc != SQLITE4_DONE) {
10081 setstat(s, rc, "%s (%d)", (*s->ov3) ? "HY000" : "S1000",
10082 sqlite4_errmsg(d->sqlite), rc);
10083 ret = SQL_ERROR;
10084 goto istmterr;
10085 }
10086 if (sqlite4_changes(d->sqlite) > 0) {
10087 if (s->row_status0) {
10088 s->row_status0[row] = SQL_ROW_ADDED;
10089 }
10090 if (s->row_status) {
10091 s->row_status[row] = SQL_ROW_ADDED;
10092 }
10093 }
10094 if (s->bkmrk == SQL_UB_VARIABLE &&
10095 s->bkmrkcol.type == SQL_C_VARBOOKMARK &&
10096 s->bkmrkcol.valp) {
10097 SQLPOINTER *val;
10098
10099 if (s->bind_type != SQL_BIND_BY_COLUMN) {
10100 val = (SQLPOINTER)
10101 ((char *) s->bkmrkcol.valp + s->bind_type * row);
10102 } else {
10103 val = (SQLPOINTER)
10104 ((char *) s->bkmrkcol.valp + s->bkmrkcol.max * row);
10105 }
10106 if (s->bind_offs) {
10107 val = (SQLPOINTER) ((char *) val + *s->bind_offs);
10108 }
10109 #if 0
10110 *(sqlite4_int64 *) val = sqlite4_last_insert_rowid(d->sqlite);
10111 #else
10112 *(sqlite4_int64 *) val = 0;
10113 #endif
10114 if (s->bkmrkcol.lenp) {
10115 SQLLEN *ival;
10116
10117 if (s->bind_type != SQL_BIND_BY_COLUMN) {
10118 ival = (SQLLEN *)
10119 ((char *) s->bkmrkcol.lenp + s->bind_type * row);
10120 } else {
10121 ival = &s->bkmrkcol.lenp[row];
10122 }
10123 if (s->bind_offs) {
10124 ival = (SQLLEN *) ((char *) ival + *s->bind_offs);
10125 }
10126 *ival = sizeof (sqlite4_int64);
10127 }
10128 }
10129 dbtraceapi(d, "sqlite4_reset", NULL);
10130 sqlite4_reset(s4stmt);
10131 }
10132 dbtraceapi(d, "sqlite4_finalize", NULL);
10133 sqlite4_finalize(s4stmt);
10134 return SQL_SUCCESS;
10135 } else if (op == SQL_DELETE_BY_BOOKMARK) {
10136 if (s->has_rowid < 0 ||
10137 s->bkmrk != SQL_UB_VARIABLE ||
10138 s->bkmrkcol.type != SQL_C_VARBOOKMARK ||
10139 !s->bkmrkcol.valp) {
10140 setstat(s, -1, "incompatible rowset",
10141 (*s->ov3) ? "HY000" : "S1000");
10142 return SQL_ERROR;
10143 }
10144 sql = dsappend(sql, "DELETE FROM ");
10145 if (s->dyncols[0].db && s->dyncols[0].db[0]) {
10146 sql = dsappendq(sql, s->dyncols[0].db);
10147 sql = dsappend(sql, ".");
10148 }
10149 sql = dsappendq(sql, s->dyncols[0].table);
10150 sql = dsappend(sql, " WHERE ");
10151 sql = dsappendq(sql, s->dyncols[0].column);
10152 sql = dsappend(sql, " = ?");
10153 if (dserr(sql)) {
10154 dsfree(sql);
10155 return nomem(s);
10156 }
10157 dbtraceapi(d, "sqlite4_prepare", dsval(sql));
10158 s4stmt = NULL;
10159 rc = sqlite4_prepare(d->sqlite, dsval(sql), -1, &s4stmt, &sqlleft);
10160 dbtracerc(d, rc, NULL);
10161 dsfree(sql);
10162 if (rc != SQLITE4_OK) {
10163 setstat(s, rc, "%s (%d)", (*s->ov3) ? "HY000" : "S1000",
10164 sqlite4_errmsg(d->sqlite), rc);
10165 if (s4stmt) {
10166 dbtraceapi(d, "sqlite4_finalize", NULL);
10167 sqlite4_finalize(s4stmt);
10168 }
10169 return SQL_ERROR;
10170 }
10171 for (row = 0; row < s->rowset_size; row++) {
10172 SQLPOINTER *val;
10173 sqlite4_int64 rowid;
10174
10175 if (s->bind_type != SQL_BIND_BY_COLUMN) {
10176 val = (SQLPOINTER)
10177 ((char *) s->bkmrkcol.valp + s->bind_type * row);
10178 } else {
10179 val = (SQLPOINTER)
10180 ((char *) s->bkmrkcol.valp + s->bkmrkcol.max * row);
10181 }
10182 if (s->bind_offs) {
10183 val = (SQLPOINTER) ((char *) val + *s->bind_offs);
10184 }
10185 if (s->bkmrkcol.lenp) {
10186 SQLLEN *ival;
10187
10188 if (s->bind_type != SQL_BIND_BY_COLUMN) {
10189 ival = (SQLLEN *)
10190 ((char *) s->bkmrkcol.lenp + s->bind_type * row);
10191 } else {
10192 ival = &s->bkmrkcol.lenp[row];
10193 }
10194 if (s->bind_offs) {
10195 ival = (SQLLEN *) ((char *) ival + *s->bind_offs);
10196 }
10197 if (*ival != sizeof (sqlite4_int64)) {
10198 continue;
10199 }
10200 }
10201 rowid = *(sqlite4_int64 *) val;
10202 sqlite4_bind_int64(s4stmt, 1, rowid);
10203 if (d->trace) {
10204 fprintf(d->trace,
10205 #ifdef _WIN32
10206 "-- parameter 1: %I64d\n",
10207 #else
10208 "-- parameter 1: %lld\n",
10209 #endif
10210 rowid);
10211 fflush(d->trace);
10212 }
10213 rc = sqlite4_step(s4stmt);
10214 if (rc != SQLITE4_DONE) {
10215 setstat(s, rc, "%s (%d)", (*s->ov3) ? "HY000" : "S1000",
10216 sqlite4_errmsg(d->sqlite), rc);
10217 if (s->row_status0) {
10218 s->row_status0[row] = SQL_ROW_ERROR;
10219 }
10220 if (s->row_status) {
10221 s->row_status[row] = SQL_ROW_ERROR;
10222 }
10223 dbtraceapi(d, "sqlite4_finalize", NULL);
10224 sqlite4_finalize(s4stmt);
10225 return SQL_ERROR;
10226 }
10227 if (sqlite4_changes(d->sqlite) > 0) {
10228 if (s->row_status0) {
10229 s->row_status0[row] = SQL_ROW_DELETED;
10230 }
10231 if (s->row_status) {
10232 s->row_status[row] = SQL_ROW_DELETED;
10233 }
10234 }
10235 dbtraceapi(d, "sqlite4_reset", NULL);
10236 sqlite4_reset(s4stmt);
10237 }
10238 dbtraceapi(d, "sqlite4_finalize", NULL);
10239 sqlite4_finalize(s4stmt);
10240 return SQL_SUCCESS;
10241 } else if (op == SQL_UPDATE_BY_BOOKMARK) {
10242 if (s->has_rowid < 0 ||
10243 s->bkmrk != SQL_UB_VARIABLE ||
10244 s->bkmrkcol.type != SQL_C_VARBOOKMARK ||
10245 !s->bkmrkcol.valp) {
10246 setstat(s, -1, "incompatible rowset",
10247 (*s->ov3) ? "HY000" : "S1000");
10248 return SQL_ERROR;
10249 }
10250 ret = chkunbound(s);
10251 if (ret != SQL_SUCCESS) {
10252 return ret;
10253 }
10254 sql = dsappend(sql, "UPDATE ");
10255 if (s->dyncols[0].db && s->dyncols[0].db[0]) {
10256 sql = dsappendq(sql, s->dyncols[0].db);
10257 sql = dsappend(sql, ".");
10258 }
10259 sql = dsappendq(sql, s->dyncols[0].table);
10260 for (i = 0, k = 0; i < s->ncols; i++) {
10261 sql = dsappend(sql, (k > 0) ? ", " : " SET ");
10262 sql = dsappendq(sql, s->dyncols[i].column);
10263 sql = dsappend(sql, " = ?");
10264 k++;
10265 }
10266 sql = dsappend(sql, " WHERE ");
10267 sql = dsappendq(sql, s->dyncols[s->has_rowid].column);
10268 sql = dsappend(sql, " = ?");
10269 if (dserr(sql)) {
10270 dsfree(sql);
10271 return nomem(s);
10272 }
10273 dbtraceapi(d, "sqlite4_prepare", dsval(sql));
10274 s4stmt = NULL;
10275 rc = sqlite4_prepare(d->sqlite, dsval(sql), -1, &s4stmt, &sqlleft);
10276 dbtracerc(d, rc, NULL);
10277 dsfree(sql);
10278 if (rc != SQLITE4_OK) {
10279 setstat(s, rc, "%s (%d)", (*s->ov3) ? "HY000" : "S1000",
10280 sqlite4_errmsg(d->sqlite), rc);
10281 if (s4stmt) {
10282 dbtraceapi(d, "sqlite4_finalize", NULL);
10283 sqlite4_finalize(s4stmt);
10284 }
10285 return SQL_ERROR;
10286 }
10287 for (row = 0; row < s->rowset_size; row++) {
10288 SQLPOINTER *val;
10289 sqlite4_int64 rowid;
10290
10291 if (s->bind_type != SQL_BIND_BY_COLUMN) {
10292 val = (SQLPOINTER)
10293 ((char *) s->bkmrkcol.valp + s->bind_type * row);
10294 } else {
10295 val = (SQLPOINTER)
10296 ((char *) s->bkmrkcol.valp + s->bkmrkcol.max * row);
10297 }
10298 if (s->bind_offs) {
10299 val = (SQLPOINTER) ((char *) val + *s->bind_offs);
10300 }
10301 if (s->bkmrkcol.lenp) {
10302 SQLLEN *ival;
10303
10304 if (s->bind_type != SQL_BIND_BY_COLUMN) {
10305 ival = (SQLLEN *)
10306 ((char *) s->bkmrkcol.lenp + s->bind_type * row);
10307 } else {
10308 ival = &s->bkmrkcol.lenp[row];
10309 }
10310 if (s->bind_offs) {
10311 ival = (SQLLEN *) ((char *) ival + *s->bind_offs);
10312 }
10313 if (*ival != sizeof (sqlite4_int64)) {
10314 continue;
10315 }
10316 }
10317 for (i = 0, k = 1; s->bindcols && i < s->ncols; i++) {
10318 ret = setposbind(s, s4stmt, i, k, row);
10319 if (ret != SQL_SUCCESS) {
10320 ustmterr:
10321 if (s->row_status0) {
10322 s->row_status0[row] = SQL_ROW_ERROR;
10323 }
10324 if (s->row_status) {
10325 s->row_status[row] = SQL_ROW_ERROR;
10326 }
10327 dbtraceapi(d, "sqlite4_finalize", NULL);
10328 sqlite4_finalize(s4stmt);
10329 return ret;
10330 }
10331 k++;
10332 }
10333 rowid = *(sqlite4_int64 *) val;
10334 sqlite4_bind_int64(s4stmt, k, rowid);
10335 if (d->trace) {
10336 fprintf(d->trace,
10337 #ifdef _WIN32
10338 "-- parameter %d: %I64d\n",
10339 #else
10340 "-- parameter %d: %lld\n",
10341 #endif
10342 k, rowid);
10343 fflush(d->trace);
10344 }
10345 rc = sqlite4_step(s4stmt);
10346 if (rc != SQLITE4_DONE) {
10347 setstat(s, rc, "%s (%d)", (*s->ov3) ? "HY000" : "S1000",
10348 sqlite4_errmsg(d->sqlite), rc);
10349 ret = SQL_ERROR;
10350 goto ustmterr;
10351 }
10352 if (sqlite4_changes(d->sqlite) > 0) {
10353 if (s->row_status0) {
10354 s->row_status0[row] = SQL_ROW_UPDATED;
10355 }
10356 if (s->row_status) {
10357 s->row_status[row] = SQL_ROW_UPDATED;
10358 }
10359 }
10360 dbtraceapi(d, "sqlite4_reset", NULL);
10361 sqlite4_reset(s4stmt);
10362 }
10363 dbtraceapi(d, "sqlite4_finalize", NULL);
10364 sqlite4_finalize(s4stmt);
10365 return SQL_SUCCESS;
10366 }
10367 setstat(s, -1, "unsupported operation", (*s->ov3) ? "HY000" : "S1000");
10368 return SQL_ERROR;
10369 }
10370
10371 /**
10372 * Perform bulk operation on HSTMT.
10373 * @param stmt statement handle
10374 * @param oper operation to be performed
10375 * @result ODBC error code
10376 */
10377
10378 SQLRETURN SQL_API
SQLBulkOperations(SQLHSTMT stmt,SQLSMALLINT oper)10379 SQLBulkOperations(SQLHSTMT stmt, SQLSMALLINT oper)
10380 {
10381 SQLRETURN ret;
10382
10383 HSTMT_LOCK(stmt);
10384 ret = drvbulkoperations(stmt, oper);
10385 HSTMT_UNLOCK(stmt);
10386 return ret;
10387 }
10388
10389 /**
10390 * Function not implemented.
10391 */
10392
10393 SQLRETURN SQL_API
SQLSetScrollOptions(SQLHSTMT stmt,SQLUSMALLINT concur,SQLLEN rowkeyset,SQLUSMALLINT rowset)10394 SQLSetScrollOptions(SQLHSTMT stmt, SQLUSMALLINT concur, SQLLEN rowkeyset,
10395 SQLUSMALLINT rowset)
10396 {
10397 SQLRETURN ret;
10398
10399 HSTMT_LOCK(stmt);
10400 ret = drvunimplstmt(stmt);
10401 HSTMT_UNLOCK(stmt);
10402 return ret;
10403 }
10404
10405 #define strmak(dst, src, max, lenp) { \
10406 int len = strlen(src); \
10407 int cnt = min(len + 1, max); \
10408 strncpy(dst, src, cnt); \
10409 *lenp = (cnt > len) ? len : cnt; \
10410 }
10411
10412 /**
10413 * Internal return information about what this ODBC driver supports.
10414 * @param dbc database connection handle
10415 * @param type type of information to be retrieved
10416 * @param val output buffer
10417 * @param valMax length of output buffer
10418 * @param valLen output length
10419 * @result ODBC error code
10420 */
10421
10422 static SQLRETURN
drvgetinfo(SQLHDBC dbc,SQLUSMALLINT type,SQLPOINTER val,SQLSMALLINT valMax,SQLSMALLINT * valLen)10423 drvgetinfo(SQLHDBC dbc, SQLUSMALLINT type, SQLPOINTER val, SQLSMALLINT valMax,
10424 SQLSMALLINT *valLen)
10425 {
10426 DBC *d;
10427 char dummyc[301];
10428 SQLSMALLINT dummy;
10429 #if defined(_WIN32) || defined(_WIN64)
10430 char pathbuf[301], *drvname;
10431 #else
10432 static char drvname[] = "sqlite4odbc.so";
10433 #endif
10434
10435 if (dbc == SQL_NULL_HDBC) {
10436 return SQL_INVALID_HANDLE;
10437 }
10438 d = (DBC *) dbc;
10439 if (valMax) {
10440 valMax--;
10441 }
10442 if (!valLen) {
10443 valLen = &dummy;
10444 }
10445 if (!val) {
10446 val = dummyc;
10447 valMax = sizeof (dummyc) - 1;
10448 }
10449 switch (type) {
10450 case SQL_MAX_USER_NAME_LEN:
10451 *((SQLSMALLINT *) val) = 16;
10452 *valLen = sizeof (SQLSMALLINT);
10453 break;
10454 case SQL_USER_NAME:
10455 strmak(val, "", valMax, valLen);
10456 break;
10457 case SQL_DRIVER_ODBC_VER:
10458 #if 0
10459 strmak(val, (*d->ov3) ? "03.00" : "02.50", valMax, valLen);
10460 #else
10461 strmak(val, "03.00", valMax, valLen);
10462 #endif
10463 break;
10464 case SQL_ACTIVE_CONNECTIONS:
10465 case SQL_ACTIVE_STATEMENTS:
10466 *((SQLSMALLINT *) val) = 0;
10467 *valLen = sizeof (SQLSMALLINT);
10468 break;
10469 #ifdef SQL_ASYNC_MODE
10470 case SQL_ASYNC_MODE:
10471 *((SQLUINTEGER *) val) = SQL_AM_NONE;
10472 *valLen = sizeof (SQLUINTEGER);
10473 break;
10474 #endif
10475 #ifdef SQL_CREATE_TABLE
10476 case SQL_CREATE_TABLE:
10477 *((SQLUINTEGER *) val) = SQL_CT_CREATE_TABLE |
10478 SQL_CT_COLUMN_DEFAULT |
10479 SQL_CT_COLUMN_CONSTRAINT |
10480 SQL_CT_CONSTRAINT_NON_DEFERRABLE;
10481 *valLen = sizeof (SQLUINTEGER);
10482 break;
10483 #endif
10484 #ifdef SQL_CREATE_VIEW
10485 case SQL_CREATE_VIEW:
10486 *((SQLUINTEGER *) val) = SQL_CV_CREATE_VIEW;
10487 *valLen = sizeof (SQLUINTEGER);
10488 break;
10489 #endif
10490 #ifdef SQL_DDL_INDEX
10491 case SQL_DDL_INDEX:
10492 *((SQLUINTEGER *) val) = SQL_DI_CREATE_INDEX | SQL_DI_DROP_INDEX;
10493 *valLen = sizeof (SQLUINTEGER);
10494 break;
10495 #endif
10496 #ifdef SQL_DROP_TABLE
10497 case SQL_DROP_TABLE:
10498 *((SQLUINTEGER *) val) = SQL_DT_DROP_TABLE;
10499 *valLen = sizeof (SQLUINTEGER);
10500 break;
10501 #endif
10502 #ifdef SQL_DROP_VIEW
10503 case SQL_DROP_VIEW:
10504 *((SQLUINTEGER *) val) = SQL_DV_DROP_VIEW;
10505 *valLen = sizeof (SQLUINTEGER);
10506 break;
10507 #endif
10508 #ifdef SQL_INDEX_KEYWORDS
10509 case SQL_INDEX_KEYWORDS:
10510 *((SQLUINTEGER *) val) = SQL_IK_ALL;
10511 *valLen = sizeof (SQLUINTEGER);
10512 break;
10513 #endif
10514 case SQL_DATA_SOURCE_NAME:
10515 strmak(val, d->dsn ? d->dsn : "", valMax, valLen);
10516 break;
10517 case SQL_DRIVER_NAME:
10518 #if defined(_WIN32) || defined(_WIN64)
10519 GetModuleFileName(hModule, pathbuf, sizeof (pathbuf));
10520 drvname = strrchr(pathbuf, '\\');
10521 if (drvname == NULL) {
10522 drvname = strrchr(pathbuf, '/');
10523 }
10524 if (drvname == NULL) {
10525 drvname = pathbuf;
10526 } else {
10527 drvname++;
10528 }
10529 #endif
10530 strmak(val, drvname, valMax, valLen);
10531 break;
10532 case SQL_DRIVER_VER:
10533 strmak(val, DRIVER_VER_INFO, valMax, valLen);
10534 break;
10535 case SQL_FETCH_DIRECTION:
10536 *((SQLUINTEGER *) val) = SQL_FD_FETCH_NEXT | SQL_FD_FETCH_FIRST |
10537 SQL_FD_FETCH_LAST | SQL_FD_FETCH_PRIOR | SQL_FD_FETCH_ABSOLUTE;
10538 *valLen = sizeof (SQLUINTEGER);
10539 break;
10540 case SQL_ODBC_VER:
10541 strmak(val, (*d->ov3) ? "03.00" : "02.50", valMax, valLen);
10542 break;
10543 case SQL_ODBC_SAG_CLI_CONFORMANCE:
10544 *((SQLSMALLINT *) val) = SQL_OSCC_NOT_COMPLIANT;
10545 *valLen = sizeof (SQLSMALLINT);
10546 break;
10547 case SQL_STANDARD_CLI_CONFORMANCE:
10548 *((SQLUINTEGER *) val) = SQL_SCC_XOPEN_CLI_VERSION1;
10549 *valLen = sizeof (SQLUINTEGER);
10550 break;
10551 case SQL_SQL_CONFORMANCE:
10552 *((SQLUINTEGER *) val) = SQL_SC_SQL92_ENTRY;
10553 *valLen = sizeof (SQLUINTEGER);
10554 break;
10555 case SQL_SERVER_NAME:
10556 case SQL_DATABASE_NAME:
10557 strmak(val, d->dbname ? d->dbname : "", valMax, valLen);
10558 break;
10559 case SQL_SEARCH_PATTERN_ESCAPE:
10560 strmak(val, "\\", valMax, valLen);
10561 break;
10562 case SQL_ODBC_SQL_CONFORMANCE:
10563 *((SQLSMALLINT *) val) = SQL_OSC_MINIMUM;
10564 *valLen = sizeof (SQLSMALLINT);
10565 break;
10566 case SQL_ODBC_API_CONFORMANCE:
10567 *((SQLSMALLINT *) val) = SQL_OAC_LEVEL1;
10568 *valLen = sizeof (SQLSMALLINT);
10569 break;
10570 case SQL_DBMS_NAME:
10571 strmak(val, "SQLite", valMax, valLen);
10572 break;
10573 case SQL_DBMS_VER:
10574 strmak(val, SQLITE4_VERSION, valMax, valLen);
10575 break;
10576 case SQL_COLUMN_ALIAS:
10577 case SQL_NEED_LONG_DATA_LEN:
10578 case SQL_OUTER_JOINS:
10579 strmak(val, "Y", valMax, valLen);
10580 break;
10581 case SQL_ROW_UPDATES:
10582 case SQL_ACCESSIBLE_PROCEDURES:
10583 case SQL_PROCEDURES:
10584 case SQL_EXPRESSIONS_IN_ORDERBY:
10585 case SQL_ODBC_SQL_OPT_IEF:
10586 case SQL_LIKE_ESCAPE_CLAUSE:
10587 case SQL_ORDER_BY_COLUMNS_IN_SELECT:
10588 case SQL_ACCESSIBLE_TABLES:
10589 case SQL_MULT_RESULT_SETS:
10590 case SQL_MULTIPLE_ACTIVE_TXN:
10591 case SQL_MAX_ROW_SIZE_INCLUDES_LONG:
10592 strmak(val, "N", valMax, valLen);
10593 break;
10594 #ifdef SQL_CATALOG_NAME
10595 case SQL_CATALOG_NAME:
10596 #if defined(_WIN32) || defined(_WIN64)
10597 strmak(val, d->xcelqrx ? "Y" : "N", valMax, valLen);
10598 #else
10599 strmak(val, "N", valMax, valLen);
10600 #endif
10601 break;
10602 #endif
10603 case SQL_DATA_SOURCE_READ_ONLY:
10604 strmak(val, "N", valMax, valLen);
10605 break;
10606 #ifdef SQL_OJ_CAPABILITIES
10607 case SQL_OJ_CAPABILITIES:
10608 *((SQLUINTEGER *) val) = SQL_OJ_LEFT;
10609 *valLen = sizeof (SQLUINTEGER);
10610 break;
10611 #endif
10612 #ifdef SQL_MAX_IDENTIFIER_LEN
10613 case SQL_MAX_IDENTIFIER_LEN:
10614 *((SQLUSMALLINT *) val) = 255;
10615 *valLen = sizeof (SQLUSMALLINT);
10616 break;
10617 #endif
10618 case SQL_CONCAT_NULL_BEHAVIOR:
10619 *((SQLSMALLINT *) val) = SQL_CB_NULL;
10620 *valLen = sizeof (SQLSMALLINT);
10621 break;
10622 case SQL_CURSOR_COMMIT_BEHAVIOR:
10623 case SQL_CURSOR_ROLLBACK_BEHAVIOR:
10624 *((SQLSMALLINT *) val) = SQL_CB_PRESERVE;
10625 *valLen = sizeof (SQLSMALLINT);
10626 break;
10627 #ifdef SQL_CURSOR_SENSITIVITY
10628 case SQL_CURSOR_SENSITIVITY:
10629 *((SQLUINTEGER *) val) = SQL_UNSPECIFIED;
10630 *valLen = sizeof (SQLUINTEGER);
10631 break;
10632 #endif
10633 case SQL_DEFAULT_TXN_ISOLATION:
10634 *((SQLUINTEGER *) val) = SQL_TXN_SERIALIZABLE;
10635 *valLen = sizeof (SQLUINTEGER);
10636 break;
10637 #ifdef SQL_DESCRIBE_PARAMETER
10638 case SQL_DESCRIBE_PARAMETER:
10639 strmak(val, "Y", valMax, valLen);
10640 break;
10641 #endif
10642 case SQL_TXN_ISOLATION_OPTION:
10643 *((SQLUINTEGER *) val) = SQL_TXN_SERIALIZABLE;
10644 *valLen = sizeof (SQLUINTEGER);
10645 break;
10646 case SQL_IDENTIFIER_CASE:
10647 *((SQLSMALLINT *) val) = SQL_IC_SENSITIVE;
10648 *valLen = sizeof (SQLSMALLINT);
10649 break;
10650 case SQL_IDENTIFIER_QUOTE_CHAR:
10651 strmak(val, "\"", valMax, valLen);
10652 break;
10653 case SQL_MAX_TABLE_NAME_LEN:
10654 case SQL_MAX_COLUMN_NAME_LEN:
10655 *((SQLSMALLINT *) val) = 255;
10656 *valLen = sizeof (SQLSMALLINT);
10657 break;
10658 case SQL_MAX_CURSOR_NAME_LEN:
10659 *((SQLSMALLINT *) val) = 255;
10660 *valLen = sizeof (SQLSMALLINT);
10661 break;
10662 case SQL_MAX_PROCEDURE_NAME_LEN:
10663 *((SQLSMALLINT *) val) = 0;
10664 break;
10665 case SQL_MAX_QUALIFIER_NAME_LEN:
10666 case SQL_MAX_OWNER_NAME_LEN:
10667 *((SQLSMALLINT *) val) = 255;
10668 break;
10669 case SQL_OWNER_TERM:
10670 strmak(val, "", valMax, valLen);
10671 break;
10672 case SQL_PROCEDURE_TERM:
10673 strmak(val, "PROCEDURE", valMax, valLen);
10674 break;
10675 case SQL_QUALIFIER_NAME_SEPARATOR:
10676 strmak(val, ".", valMax, valLen);
10677 break;
10678 case SQL_QUALIFIER_TERM:
10679 #if defined(_WIN32) || defined(_WIN64)
10680 strmak(val, d->xcelqrx ? "catalog" : "", valMax, valLen);
10681 #else
10682 strmak(val, "", valMax, valLen);
10683 #endif
10684 break;
10685 case SQL_QUALIFIER_USAGE:
10686 #if defined(_WIN32) || defined(_WIN64)
10687 *((SQLUINTEGER *) val) = d->xcelqrx ?
10688 (SQL_CU_DML_STATEMENTS | SQL_CU_INDEX_DEFINITION |
10689 SQL_CU_TABLE_DEFINITION) : 0;
10690 #else
10691 *((SQLUINTEGER *) val) = 0;
10692 #endif
10693 *valLen = sizeof (SQLUINTEGER);
10694 break;
10695 case SQL_SCROLL_CONCURRENCY:
10696 *((SQLUINTEGER *) val) = SQL_SCCO_LOCK;
10697 *valLen = sizeof (SQLUINTEGER);
10698 break;
10699 case SQL_SCROLL_OPTIONS:
10700 *((SQLUINTEGER *) val) = SQL_SO_STATIC | SQL_SO_FORWARD_ONLY;
10701 *valLen = sizeof (SQLUINTEGER);
10702 break;
10703 case SQL_TABLE_TERM:
10704 strmak(val, "TABLE", valMax, valLen);
10705 break;
10706 case SQL_TXN_CAPABLE:
10707 *((SQLSMALLINT *) val) = SQL_TC_ALL;
10708 *valLen = sizeof (SQLSMALLINT);
10709 break;
10710 case SQL_CONVERT_FUNCTIONS:
10711 *((SQLUINTEGER *) val) = 0;
10712 *valLen = sizeof (SQLUINTEGER);
10713 break;
10714 case SQL_SYSTEM_FUNCTIONS:
10715 case SQL_NUMERIC_FUNCTIONS:
10716 case SQL_STRING_FUNCTIONS:
10717 case SQL_TIMEDATE_FUNCTIONS:
10718 *((SQLUINTEGER *) val) = 0;
10719 *valLen = sizeof (SQLUINTEGER);
10720 break;
10721 case SQL_CONVERT_BIGINT:
10722 case SQL_CONVERT_BIT:
10723 case SQL_CONVERT_CHAR:
10724 case SQL_CONVERT_DATE:
10725 case SQL_CONVERT_DECIMAL:
10726 case SQL_CONVERT_DOUBLE:
10727 case SQL_CONVERT_FLOAT:
10728 case SQL_CONVERT_INTEGER:
10729 case SQL_CONVERT_LONGVARCHAR:
10730 case SQL_CONVERT_NUMERIC:
10731 case SQL_CONVERT_REAL:
10732 case SQL_CONVERT_SMALLINT:
10733 case SQL_CONVERT_TIME:
10734 case SQL_CONVERT_TIMESTAMP:
10735 case SQL_CONVERT_TINYINT:
10736 case SQL_CONVERT_VARCHAR:
10737 *((SQLUINTEGER *) val) =
10738 SQL_CVT_CHAR | SQL_CVT_NUMERIC | SQL_CVT_DECIMAL |
10739 SQL_CVT_INTEGER | SQL_CVT_SMALLINT | SQL_CVT_FLOAT | SQL_CVT_REAL |
10740 SQL_CVT_DOUBLE | SQL_CVT_VARCHAR | SQL_CVT_LONGVARCHAR |
10741 SQL_CVT_BIT | SQL_CVT_TINYINT | SQL_CVT_BIGINT |
10742 SQL_CVT_DATE | SQL_CVT_TIME | SQL_CVT_TIMESTAMP;
10743 *valLen = sizeof (SQLUINTEGER);
10744 break;
10745 case SQL_CONVERT_BINARY:
10746 case SQL_CONVERT_VARBINARY:
10747 case SQL_CONVERT_LONGVARBINARY:
10748 *((SQLUINTEGER *) val) = 0;
10749 *valLen = sizeof (SQLUINTEGER);
10750 break;
10751 case SQL_POSITIONED_STATEMENTS:
10752 *((SQLUINTEGER *) val) = 0;
10753 *valLen = sizeof (SQLUINTEGER);
10754 break;
10755 case SQL_LOCK_TYPES:
10756 *((SQLUINTEGER *) val) = SQL_LCK_NO_CHANGE;
10757 *valLen = sizeof (SQLUINTEGER);
10758 break;
10759 case SQL_BOOKMARK_PERSISTENCE:
10760 *((SQLUINTEGER *) val) = SQL_BP_SCROLL;
10761 *valLen = sizeof (SQLUINTEGER);
10762 break;
10763 case SQL_UNION:
10764 *((SQLUINTEGER *) val) = SQL_U_UNION | SQL_U_UNION_ALL;
10765 *valLen = sizeof (SQLUINTEGER);
10766 break;
10767 case SQL_OWNER_USAGE:
10768 case SQL_SUBQUERIES:
10769 case SQL_TIMEDATE_ADD_INTERVALS:
10770 case SQL_TIMEDATE_DIFF_INTERVALS:
10771 *((SQLUINTEGER *) val) = 0;
10772 *valLen = sizeof (SQLUINTEGER);
10773 break;
10774 case SQL_QUOTED_IDENTIFIER_CASE:
10775 *((SQLUSMALLINT *) val) = SQL_IC_SENSITIVE;
10776 *valLen = sizeof (SQLUSMALLINT);
10777 break;
10778 case SQL_POS_OPERATIONS:
10779 *((SQLUINTEGER *) val) = SQL_POS_POSITION | SQL_POS_UPDATE |
10780 SQL_POS_DELETE | SQL_POS_ADD | SQL_POS_REFRESH;
10781 *valLen = sizeof (SQLUINTEGER);
10782 break;
10783 case SQL_ALTER_TABLE:
10784 *((SQLUINTEGER *) val) = 0;
10785 *valLen = sizeof (SQLUINTEGER);
10786 break;
10787 case SQL_CORRELATION_NAME:
10788 *((SQLSMALLINT *) val) = SQL_CN_DIFFERENT;
10789 *valLen = sizeof (SQLSMALLINT);
10790 break;
10791 case SQL_NON_NULLABLE_COLUMNS:
10792 *((SQLSMALLINT *) val) = SQL_NNC_NON_NULL;
10793 *valLen = sizeof (SQLSMALLINT);
10794 break;
10795 case SQL_NULL_COLLATION:
10796 *((SQLSMALLINT *) val) = SQL_NC_START;
10797 *valLen = sizeof (SQLSMALLINT);
10798 break;
10799 case SQL_MAX_COLUMNS_IN_GROUP_BY:
10800 case SQL_MAX_COLUMNS_IN_ORDER_BY:
10801 case SQL_MAX_COLUMNS_IN_SELECT:
10802 case SQL_MAX_COLUMNS_IN_TABLE:
10803 case SQL_MAX_ROW_SIZE:
10804 case SQL_MAX_TABLES_IN_SELECT:
10805 *((SQLSMALLINT *) val) = 0;
10806 *valLen = sizeof (SQLSMALLINT);
10807 break;
10808 case SQL_MAX_BINARY_LITERAL_LEN:
10809 case SQL_MAX_CHAR_LITERAL_LEN:
10810 *((SQLUINTEGER *) val) = 0;
10811 *valLen = sizeof (SQLUINTEGER);
10812 break;
10813 case SQL_MAX_COLUMNS_IN_INDEX:
10814 *((SQLSMALLINT *) val) = 0;
10815 *valLen = sizeof (SQLSMALLINT);
10816 break;
10817 case SQL_MAX_INDEX_SIZE:
10818 *((SQLUINTEGER *) val) = 0;
10819 *valLen = sizeof (SQLUINTEGER);
10820 break;
10821 #ifdef SQL_MAX_IDENTIFIER_LENGTH
10822 case SQL_MAX_IDENTIFIER_LENGTH:
10823 *((SQLUINTEGER *) val) = 255;
10824 *valLen = sizeof (SQLUINTEGER);
10825 break;
10826 #endif
10827 case SQL_MAX_STATEMENT_LEN:
10828 *((SQLUINTEGER *) val) = 16384;
10829 *valLen = sizeof (SQLUINTEGER);
10830 break;
10831 case SQL_QUALIFIER_LOCATION:
10832 *((SQLSMALLINT *) val) = SQL_QL_START;
10833 *valLen = sizeof (SQLSMALLINT);
10834 break;
10835 case SQL_GETDATA_EXTENSIONS:
10836 *((SQLUINTEGER *) val) =
10837 SQL_GD_ANY_COLUMN | SQL_GD_ANY_ORDER | SQL_GD_BOUND;
10838 *valLen = sizeof (SQLUINTEGER);
10839 break;
10840 case SQL_STATIC_SENSITIVITY:
10841 *((SQLUINTEGER *) val) = 0;
10842 *valLen = sizeof (SQLUINTEGER);
10843 break;
10844 case SQL_FILE_USAGE:
10845 #if defined(_WIN32) || defined(_WIN64)
10846 *((SQLSMALLINT *) val) =
10847 d->xcelqrx ? SQL_FILE_CATALOG : SQL_FILE_NOT_SUPPORTED;
10848 #else
10849 *((SQLSMALLINT *) val) = SQL_FILE_NOT_SUPPORTED;
10850 #endif
10851 *valLen = sizeof (SQLSMALLINT);
10852 break;
10853 case SQL_GROUP_BY:
10854 *((SQLSMALLINT *) val) = SQL_GB_GROUP_BY_EQUALS_SELECT;
10855 *valLen = sizeof (SQLSMALLINT);
10856 break;
10857 case SQL_KEYWORDS:
10858 strmak(val, "CREATE,SELECT,DROP,DELETE,UPDATE,INSERT,"
10859 "INTO,VALUES,TABLE,INDEX,FROM,SET,WHERE,AND,CURRENT,OF",
10860 valMax, valLen);
10861 break;
10862 case SQL_SPECIAL_CHARACTERS:
10863 #ifdef SQL_COLLATION_SEQ
10864 case SQL_COLLATION_SEQ:
10865 #endif
10866 strmak(val, "", valMax, valLen);
10867 break;
10868 case SQL_BATCH_SUPPORT:
10869 case SQL_BATCH_ROW_COUNT:
10870 case SQL_PARAM_ARRAY_ROW_COUNTS:
10871 *((SQLUINTEGER *) val) = 0;
10872 *valLen = sizeof (SQLUINTEGER);
10873 break;
10874 case SQL_FORWARD_ONLY_CURSOR_ATTRIBUTES1:
10875 *((SQLUINTEGER *) val) = SQL_CA1_NEXT | SQL_CA1_BOOKMARK;
10876 *valLen = sizeof (SQLUINTEGER);
10877 break;
10878 case SQL_STATIC_CURSOR_ATTRIBUTES1:
10879 *((SQLUINTEGER *) val) = SQL_CA1_NEXT | SQL_CA1_ABSOLUTE |
10880 SQL_CA1_RELATIVE | SQL_CA1_BOOKMARK | SQL_CA1_POS_POSITION |
10881 SQL_CA1_POS_DELETE | SQL_CA1_POS_UPDATE | SQL_CA1_POS_REFRESH |
10882 SQL_CA1_LOCK_NO_CHANGE | SQL_CA1_BULK_ADD |
10883 SQL_CA1_BULK_UPDATE_BY_BOOKMARK | SQL_CA1_BULK_DELETE_BY_BOOKMARK;
10884 *valLen = sizeof (SQLUINTEGER);
10885 break;
10886 case SQL_FORWARD_ONLY_CURSOR_ATTRIBUTES2:
10887 case SQL_STATIC_CURSOR_ATTRIBUTES2:
10888 *((SQLUINTEGER *) val) = SQL_CA2_READ_ONLY_CONCURRENCY |
10889 SQL_CA2_LOCK_CONCURRENCY;
10890 *valLen = sizeof (SQLUINTEGER);
10891 break;
10892 case SQL_KEYSET_CURSOR_ATTRIBUTES1:
10893 case SQL_KEYSET_CURSOR_ATTRIBUTES2:
10894 case SQL_DYNAMIC_CURSOR_ATTRIBUTES1:
10895 case SQL_DYNAMIC_CURSOR_ATTRIBUTES2:
10896 *((SQLUINTEGER *) val) = 0;
10897 *valLen = sizeof (SQLUINTEGER);
10898 break;
10899 case SQL_ODBC_INTERFACE_CONFORMANCE:
10900 *((SQLUINTEGER *) val) = SQL_OIC_CORE;
10901 *valLen = sizeof (SQLUINTEGER);
10902 break;
10903 default:
10904 setstatd(d, -1, "unsupported info option %d",
10905 (*d->ov3) ? "HYC00" : "S1C00", type);
10906 return SQL_ERROR;
10907 }
10908 return SQL_SUCCESS;
10909 }
10910
10911 #if (defined(HAVE_UNIXODBC) && (HAVE_UNIXODBC)) || !defined(WINTERFACE)
10912 /**
10913 * Return information about what this ODBC driver supports.
10914 * @param dbc database connection handle
10915 * @param type type of information to be retrieved
10916 * @param val output buffer
10917 * @param valMax length of output buffer
10918 * @param valLen output length
10919 * @result ODBC error code
10920 */
10921
10922 SQLRETURN SQL_API
SQLGetInfo(SQLHDBC dbc,SQLUSMALLINT type,SQLPOINTER val,SQLSMALLINT valMax,SQLSMALLINT * valLen)10923 SQLGetInfo(SQLHDBC dbc, SQLUSMALLINT type, SQLPOINTER val, SQLSMALLINT valMax,
10924 SQLSMALLINT *valLen)
10925 {
10926 SQLRETURN ret;
10927
10928 HDBC_LOCK(dbc);
10929 ret = drvgetinfo(dbc, type, val, valMax, valLen);
10930 HDBC_UNLOCK(dbc);
10931 return ret;
10932 }
10933 #endif
10934
10935 #ifdef WINTERFACE
10936 /**
10937 * Return information about what this ODBC driver supports.
10938 * @param dbc database connection handle
10939 * @param type type of information to be retrieved
10940 * @param val output buffer
10941 * @param valMax length of output buffer
10942 * @param valLen output length
10943 * @result ODBC error code
10944 */
10945
10946 SQLRETURN SQL_API
SQLGetInfoW(SQLHDBC dbc,SQLUSMALLINT type,SQLPOINTER val,SQLSMALLINT valMax,SQLSMALLINT * valLen)10947 SQLGetInfoW(SQLHDBC dbc, SQLUSMALLINT type, SQLPOINTER val, SQLSMALLINT valMax,
10948 SQLSMALLINT *valLen)
10949 {
10950 SQLRETURN ret;
10951 SQLSMALLINT len = 0;
10952
10953 HDBC_LOCK(dbc);
10954 ret = drvgetinfo(dbc, type, val, valMax, &len);
10955 HDBC_UNLOCK(dbc);
10956 if (ret == SQL_SUCCESS) {
10957 SQLWCHAR *v = NULL;
10958
10959 switch (type) {
10960 case SQL_USER_NAME:
10961 case SQL_DRIVER_ODBC_VER:
10962 case SQL_DATA_SOURCE_NAME:
10963 case SQL_DRIVER_NAME:
10964 case SQL_DRIVER_VER:
10965 case SQL_ODBC_VER:
10966 case SQL_SERVER_NAME:
10967 case SQL_DATABASE_NAME:
10968 case SQL_SEARCH_PATTERN_ESCAPE:
10969 case SQL_DBMS_NAME:
10970 case SQL_DBMS_VER:
10971 case SQL_NEED_LONG_DATA_LEN:
10972 case SQL_ROW_UPDATES:
10973 case SQL_ACCESSIBLE_PROCEDURES:
10974 case SQL_PROCEDURES:
10975 case SQL_EXPRESSIONS_IN_ORDERBY:
10976 case SQL_ODBC_SQL_OPT_IEF:
10977 case SQL_LIKE_ESCAPE_CLAUSE:
10978 case SQL_ORDER_BY_COLUMNS_IN_SELECT:
10979 case SQL_OUTER_JOINS:
10980 case SQL_COLUMN_ALIAS:
10981 case SQL_ACCESSIBLE_TABLES:
10982 case SQL_MULT_RESULT_SETS:
10983 case SQL_MULTIPLE_ACTIVE_TXN:
10984 case SQL_MAX_ROW_SIZE_INCLUDES_LONG:
10985 case SQL_DATA_SOURCE_READ_ONLY:
10986 #ifdef SQL_DESCRIBE_PARAMETER
10987 case SQL_DESCRIBE_PARAMETER:
10988 #endif
10989 case SQL_IDENTIFIER_QUOTE_CHAR:
10990 case SQL_OWNER_TERM:
10991 case SQL_PROCEDURE_TERM:
10992 case SQL_QUALIFIER_NAME_SEPARATOR:
10993 case SQL_QUALIFIER_TERM:
10994 case SQL_TABLE_TERM:
10995 case SQL_KEYWORDS:
10996 case SQL_SPECIAL_CHARACTERS:
10997 #ifdef SQL_CATALOG_NAME
10998 case SQL_CATALOG_NAME:
10999 #endif
11000 #ifdef SQL_COLLATION_SEQ
11001 case SQL_COLLATION_SEQ:
11002 #endif
11003 if (val) {
11004 if (len > 0) {
11005 v = uc_from_utf((SQLCHAR *) val, len);
11006 if (v) {
11007 int vmax = valMax / sizeof (SQLWCHAR);
11008
11009 uc_strncpy(val, v, vmax);
11010 if (len < vmax) {
11011 len = min(vmax, uc_strlen(v));
11012 v[len] = 0;
11013 } else {
11014 len = vmax;
11015 }
11016 uc_free(v);
11017 len *= sizeof (SQLWCHAR);
11018 } else {
11019 len = 0;
11020 }
11021 }
11022 if (len <= 0) {
11023 len = 0;
11024 if (valMax >= sizeof (SQLWCHAR)) {
11025 *((SQLWCHAR *)val) = 0;
11026 }
11027 }
11028 } else {
11029 len *= sizeof (SQLWCHAR);
11030 }
11031 break;
11032 }
11033 if (valLen) {
11034 *valLen = len;
11035 }
11036 }
11037 return ret;
11038 }
11039 #endif
11040
11041 /**
11042 * Return information about supported ODBC API functions.
11043 * @param dbc database connection handle
11044 * @param func function code to be retrieved
11045 * @param flags output indicator
11046 * @result ODBC error code
11047 */
11048
11049 SQLRETURN SQL_API
SQLGetFunctions(SQLHDBC dbc,SQLUSMALLINT func,SQLUSMALLINT * flags)11050 SQLGetFunctions(SQLHDBC dbc, SQLUSMALLINT func,
11051 SQLUSMALLINT *flags)
11052 {
11053 int i;
11054 SQLUSMALLINT exists[100];
11055
11056 if (dbc == SQL_NULL_HDBC) {
11057 return SQL_INVALID_HANDLE;
11058 }
11059 for (i = 0; i < array_size(exists); i++) {
11060 exists[i] = SQL_FALSE;
11061 }
11062 exists[SQL_API_SQLALLOCCONNECT] = SQL_TRUE;
11063 exists[SQL_API_SQLFETCH] = SQL_TRUE;
11064 exists[SQL_API_SQLALLOCENV] = SQL_TRUE;
11065 exists[SQL_API_SQLFREECONNECT] = SQL_TRUE;
11066 exists[SQL_API_SQLALLOCSTMT] = SQL_TRUE;
11067 exists[SQL_API_SQLFREEENV] = SQL_TRUE;
11068 exists[SQL_API_SQLBINDCOL] = SQL_TRUE;
11069 exists[SQL_API_SQLFREESTMT] = SQL_TRUE;
11070 exists[SQL_API_SQLCANCEL] = SQL_TRUE;
11071 exists[SQL_API_SQLGETCURSORNAME] = SQL_TRUE;
11072 exists[SQL_API_SQLCOLATTRIBUTES] = SQL_TRUE;
11073 exists[SQL_API_SQLNUMRESULTCOLS] = SQL_TRUE;
11074 exists[SQL_API_SQLCONNECT] = SQL_TRUE;
11075 exists[SQL_API_SQLPREPARE] = SQL_TRUE;
11076 exists[SQL_API_SQLDESCRIBECOL] = SQL_TRUE;
11077 exists[SQL_API_SQLROWCOUNT] = SQL_TRUE;
11078 exists[SQL_API_SQLDISCONNECT] = SQL_TRUE;
11079 exists[SQL_API_SQLSETCURSORNAME] = SQL_FALSE;
11080 exists[SQL_API_SQLERROR] = SQL_TRUE;
11081 exists[SQL_API_SQLSETPARAM] = SQL_TRUE;
11082 exists[SQL_API_SQLEXECDIRECT] = SQL_TRUE;
11083 exists[SQL_API_SQLTRANSACT] = SQL_TRUE;
11084 exists[SQL_API_SQLBULKOPERATIONS] = SQL_TRUE;
11085 exists[SQL_API_SQLEXECUTE] = SQL_TRUE;
11086 exists[SQL_API_SQLBINDPARAMETER] = SQL_TRUE;
11087 exists[SQL_API_SQLGETTYPEINFO] = SQL_TRUE;
11088 exists[SQL_API_SQLCOLUMNS] = SQL_TRUE;
11089 exists[SQL_API_SQLPARAMDATA] = SQL_TRUE;
11090 exists[SQL_API_SQLDRIVERCONNECT] = SQL_TRUE;
11091 exists[SQL_API_SQLPUTDATA] = SQL_TRUE;
11092 exists[SQL_API_SQLGETCONNECTOPTION] = SQL_TRUE;
11093 exists[SQL_API_SQLSETCONNECTOPTION] = SQL_TRUE;
11094 exists[SQL_API_SQLGETDATA] = SQL_TRUE;
11095 exists[SQL_API_SQLSETSTMTOPTION] = SQL_TRUE;
11096 exists[SQL_API_SQLGETFUNCTIONS] = SQL_TRUE;
11097 exists[SQL_API_SQLSPECIALCOLUMNS] = SQL_TRUE;
11098 exists[SQL_API_SQLGETINFO] = SQL_TRUE;
11099 exists[SQL_API_SQLSTATISTICS] = SQL_TRUE;
11100 exists[SQL_API_SQLGETSTMTOPTION] = SQL_TRUE;
11101 exists[SQL_API_SQLTABLES] = SQL_TRUE;
11102 exists[SQL_API_SQLBROWSECONNECT] = SQL_FALSE;
11103 exists[SQL_API_SQLNUMPARAMS] = SQL_TRUE;
11104 exists[SQL_API_SQLCOLUMNPRIVILEGES] = SQL_FALSE;
11105 exists[SQL_API_SQLPARAMOPTIONS] = SQL_FALSE;
11106 exists[SQL_API_SQLDATASOURCES] = SQL_TRUE;
11107 exists[SQL_API_SQLPRIMARYKEYS] = SQL_TRUE;
11108 exists[SQL_API_SQLDESCRIBEPARAM] = SQL_TRUE;
11109 exists[SQL_API_SQLPROCEDURECOLUMNS] = SQL_TRUE;
11110 exists[SQL_API_SQLDRIVERS] = SQL_FALSE;
11111 exists[SQL_API_SQLPROCEDURES] = SQL_TRUE;
11112 exists[SQL_API_SQLEXTENDEDFETCH] = SQL_TRUE;
11113 exists[SQL_API_SQLSETPOS] = SQL_TRUE;
11114 exists[SQL_API_SQLFOREIGNKEYS] = SQL_TRUE;
11115 exists[SQL_API_SQLSETSCROLLOPTIONS] = SQL_TRUE;
11116 exists[SQL_API_SQLMORERESULTS] = SQL_TRUE;
11117 exists[SQL_API_SQLTABLEPRIVILEGES] = SQL_TRUE;
11118 exists[SQL_API_SQLNATIVESQL] = SQL_TRUE;
11119 if (func == SQL_API_ALL_FUNCTIONS) {
11120 memcpy(flags, exists, sizeof (exists));
11121 } else if (func == SQL_API_ODBC3_ALL_FUNCTIONS) {
11122 int i;
11123 #define SET_EXISTS(x) \
11124 flags[(x) >> 4] |= (1 << ((x) & 0xF))
11125 #define CLR_EXISTS(x) \
11126 flags[(x) >> 4] &= ~(1 << ((x) & 0xF))
11127
11128 memset(flags, 0,
11129 sizeof (SQLUSMALLINT) * SQL_API_ODBC3_ALL_FUNCTIONS_SIZE);
11130 for (i = 0; i < array_size(exists); i++) {
11131 if (exists[i]) {
11132 flags[i >> 4] |= (1 << (i & 0xF));
11133 }
11134 }
11135 SET_EXISTS(SQL_API_SQLALLOCHANDLE);
11136 SET_EXISTS(SQL_API_SQLFREEHANDLE);
11137 SET_EXISTS(SQL_API_SQLGETSTMTATTR);
11138 SET_EXISTS(SQL_API_SQLSETSTMTATTR);
11139 SET_EXISTS(SQL_API_SQLGETCONNECTATTR);
11140 SET_EXISTS(SQL_API_SQLSETCONNECTATTR);
11141 SET_EXISTS(SQL_API_SQLGETENVATTR);
11142 SET_EXISTS(SQL_API_SQLSETENVATTR);
11143 SET_EXISTS(SQL_API_SQLCLOSECURSOR);
11144 SET_EXISTS(SQL_API_SQLBINDPARAM);
11145 #if !defined(HAVE_UNIXODBC) || !(HAVE_UNIXODBC)
11146 /*
11147 * Some unixODBC versions have problems with
11148 * SQLError() vs. SQLGetDiagRec() with loss
11149 * of error/warning messages.
11150 */
11151 SET_EXISTS(SQL_API_SQLGETDIAGREC);
11152 #endif
11153 SET_EXISTS(SQL_API_SQLGETDIAGFIELD);
11154 SET_EXISTS(SQL_API_SQLFETCHSCROLL);
11155 SET_EXISTS(SQL_API_SQLENDTRAN);
11156 } else {
11157 if (func < array_size(exists)) {
11158 *flags = exists[func];
11159 } else {
11160 switch (func) {
11161 case SQL_API_SQLALLOCHANDLE:
11162 case SQL_API_SQLFREEHANDLE:
11163 case SQL_API_SQLGETSTMTATTR:
11164 case SQL_API_SQLSETSTMTATTR:
11165 case SQL_API_SQLGETCONNECTATTR:
11166 case SQL_API_SQLSETCONNECTATTR:
11167 case SQL_API_SQLGETENVATTR:
11168 case SQL_API_SQLSETENVATTR:
11169 case SQL_API_SQLCLOSECURSOR:
11170 case SQL_API_SQLBINDPARAM:
11171 #if !defined(HAVE_UNIXODBC) || !(HAVE_UNIXODBC)
11172 /*
11173 * Some unixODBC versions have problems with
11174 * SQLError() vs. SQLGetDiagRec() with loss
11175 * of error/warning messages.
11176 */
11177 case SQL_API_SQLGETDIAGREC:
11178 #endif
11179 case SQL_API_SQLGETDIAGFIELD:
11180 case SQL_API_SQLFETCHSCROLL:
11181 case SQL_API_SQLENDTRAN:
11182 *flags = SQL_TRUE;
11183 break;
11184 default:
11185 *flags = SQL_FALSE;
11186 }
11187 }
11188 }
11189 return SQL_SUCCESS;
11190 }
11191
11192 /**
11193 * Internal allocate HENV.
11194 * @param env pointer to environment handle
11195 * @result ODBC error code
11196 */
11197
11198 static SQLRETURN
drvallocenv(SQLHENV * env)11199 drvallocenv(SQLHENV *env)
11200 {
11201 ENV *e;
11202
11203 if (env == NULL) {
11204 return SQL_INVALID_HANDLE;
11205 }
11206 e = (ENV *) xmalloc(sizeof (ENV));
11207 if (e == NULL) {
11208 *env = SQL_NULL_HENV;
11209 return SQL_ERROR;
11210 }
11211 e->magic = ENV_MAGIC;
11212 e->ov3 = 0;
11213 e->pool = 0;
11214 #if defined(_WIN32) || defined(_WIN64)
11215 InitializeCriticalSection(&e->cs);
11216 #endif
11217 e->dbcs = NULL;
11218 *env = (SQLHENV) e;
11219 return SQL_SUCCESS;
11220 }
11221
11222 /**
11223 * Allocate HENV.
11224 * @param env pointer to environment handle
11225 * @result ODBC error code
11226 */
11227
11228 SQLRETURN SQL_API
SQLAllocEnv(SQLHENV * env)11229 SQLAllocEnv(SQLHENV *env)
11230 {
11231 return drvallocenv(env);
11232 }
11233
11234 /**
11235 * Internal free HENV.
11236 * @param env environment handle
11237 * @result ODBC error code
11238 */
11239
11240 static SQLRETURN
drvfreeenv(SQLHENV env)11241 drvfreeenv(SQLHENV env)
11242 {
11243 ENV *e;
11244
11245 if (env == SQL_NULL_HENV) {
11246 return SQL_INVALID_HANDLE;
11247 }
11248 e = (ENV *) env;
11249 if (e->magic != ENV_MAGIC) {
11250 return SQL_SUCCESS;
11251 }
11252 #if defined(_WIN32) || defined(_WIN64)
11253 EnterCriticalSection(&e->cs);
11254 #endif
11255 if (e->dbcs) {
11256 #if defined(_WIN32) || defined(_WIN64)
11257 LeaveCriticalSection(&e->cs);
11258 #endif
11259 return SQL_ERROR;
11260 }
11261 e->magic = DEAD_MAGIC;
11262 #if defined(_WIN32) || defined(_WIN64)
11263 LeaveCriticalSection(&e->cs);
11264 DeleteCriticalSection(&e->cs);
11265 #endif
11266 xfree(e);
11267 return SQL_SUCCESS;
11268 }
11269
11270 /**
11271 * Free HENV.
11272 * @param env environment handle
11273 * @result ODBC error code
11274 */
11275
11276 SQLRETURN SQL_API
SQLFreeEnv(SQLHENV env)11277 SQLFreeEnv(SQLHENV env)
11278 {
11279 return drvfreeenv(env);
11280 }
11281
11282 /**
11283 * Internal allocate HDBC.
11284 * @param env environment handle
11285 * @param dbc pointer to database connection handle
11286 * @result ODBC error code
11287 */
11288
11289 static SQLRETURN
drvallocconnect(SQLHENV env,SQLHDBC * dbc)11290 drvallocconnect(SQLHENV env, SQLHDBC *dbc)
11291 {
11292 DBC *d;
11293 ENV *e;
11294 const char *verstr;
11295 int maj = 0, min = 0, lev = 0;
11296
11297 if (dbc == NULL) {
11298 return SQL_ERROR;
11299 }
11300 d = (DBC *) xmalloc(sizeof (DBC));
11301 if (d == NULL) {
11302 *dbc = SQL_NULL_HDBC;
11303 return SQL_ERROR;
11304 }
11305 memset(d, 0, sizeof (DBC));
11306 d->curtype = SQL_CURSOR_STATIC;
11307 d->ov3 = &d->ov3val;
11308 verstr = sqlite4_libversion();
11309 sscanf(verstr, "%d.%d.%d", &maj, &min, &lev);
11310 d->version = verinfo(maj & 0xFF, min & 0xFF, lev & 0xFF);
11311 e = (ENV *) env;
11312 #if defined(_WIN32) || defined(_WIN64)
11313 if (e->magic == ENV_MAGIC) {
11314 EnterCriticalSection(&e->cs);
11315 }
11316 #endif
11317 if (e->magic == ENV_MAGIC) {
11318 DBC *n, *p;
11319
11320 d->env = e;
11321 d->ov3 = &e->ov3;
11322 p = NULL;
11323 n = e->dbcs;
11324 while (n) {
11325 p = n;
11326 n = n->next;
11327 }
11328 if (p) {
11329 p->next = d;
11330 } else {
11331 e->dbcs = d;
11332 }
11333 }
11334 #if defined(_WIN32) || defined(_WIN64)
11335 InitializeCriticalSection(&d->cs);
11336 d->owner = 0;
11337 if (e->magic == ENV_MAGIC) {
11338 LeaveCriticalSection(&e->cs);
11339 }
11340 d->oemcp = 1;
11341 #endif
11342 d->autocommit = 1;
11343 d->magic = DBC_MAGIC;
11344 *dbc = (SQLHDBC) d;
11345 drvgetgpps(d);
11346 return SQL_SUCCESS;
11347 }
11348
11349 /**
11350 * Allocate HDBC.
11351 * @param env environment handle
11352 * @param dbc pointer to database connection handle
11353 * @result ODBC error code
11354 */
11355
11356 SQLRETURN SQL_API
SQLAllocConnect(SQLHENV env,SQLHDBC * dbc)11357 SQLAllocConnect(SQLHENV env, SQLHDBC *dbc)
11358 {
11359 return drvallocconnect(env, dbc);
11360 }
11361
11362 /**
11363 * Internal free connection (HDBC).
11364 * @param dbc database connection handle
11365 * @result ODBC error code
11366 */
11367
11368 static SQLRETURN
drvfreeconnect(SQLHDBC dbc)11369 drvfreeconnect(SQLHDBC dbc)
11370 {
11371 DBC *d;
11372 ENV *e;
11373 SQLRETURN ret = SQL_ERROR;
11374
11375 if (dbc == SQL_NULL_HDBC) {
11376 return SQL_INVALID_HANDLE;
11377 }
11378 d = (DBC *) dbc;
11379 if (d->magic != DBC_MAGIC) {
11380 return SQL_INVALID_HANDLE;
11381 }
11382 e = d->env;
11383 if (e && e->magic == ENV_MAGIC) {
11384 #if defined(_WIN32) || defined(_WIN64)
11385 EnterCriticalSection(&e->cs);
11386 #endif
11387 } else {
11388 e = NULL;
11389 }
11390 HDBC_LOCK(dbc);
11391 if (d->sqlite) {
11392 setstatd(d, -1, "not disconnected", (*d->ov3) ? "HY000" : "S1000");
11393 HDBC_UNLOCK(dbc);
11394 goto done;
11395 }
11396 while (d->stmt) {
11397 freestmt((HSTMT) d->stmt);
11398 }
11399 if (e && e->magic == ENV_MAGIC) {
11400 DBC *n, *p;
11401
11402 p = NULL;
11403 n = e->dbcs;
11404 while (n) {
11405 if (n == d) {
11406 break;
11407 }
11408 p = n;
11409 n = n->next;
11410 }
11411 if (n) {
11412 if (p) {
11413 p->next = d->next;
11414 } else {
11415 e->dbcs = d->next;
11416 }
11417 }
11418 }
11419 drvrelgpps(d);
11420 d->magic = DEAD_MAGIC;
11421 if (d->trace) {
11422 fclose(d->trace);
11423 }
11424 #if defined(_WIN32) || defined(_WIN64)
11425 d->owner = 0;
11426 LeaveCriticalSection(&d->cs);
11427 DeleteCriticalSection(&d->cs);
11428 #endif
11429 xfree(d);
11430 ret = SQL_SUCCESS;
11431 done:
11432 #if defined(_WIN32) || defined(_WIN64)
11433 if (e) {
11434 LeaveCriticalSection(&e->cs);
11435 }
11436 #endif
11437 return ret;
11438 }
11439
11440 /**
11441 * Free connection (HDBC).
11442 * @param dbc database connection handle
11443 * @result ODBC error code
11444 */
11445
11446 SQLRETURN SQL_API
SQLFreeConnect(SQLHDBC dbc)11447 SQLFreeConnect(SQLHDBC dbc)
11448 {
11449 return drvfreeconnect(dbc);
11450 }
11451
11452 /**
11453 * Internal get connect attribute of HDBC.
11454 * @param dbc database connection handle
11455 * @param attr option to be retrieved
11456 * @param val output buffer
11457 * @param bufmax size of output buffer
11458 * @param buflen output length
11459 * @result ODBC error code
11460 */
11461
11462 static SQLRETURN
drvgetconnectattr(SQLHDBC dbc,SQLINTEGER attr,SQLPOINTER val,SQLINTEGER bufmax,SQLINTEGER * buflen)11463 drvgetconnectattr(SQLHDBC dbc, SQLINTEGER attr, SQLPOINTER val,
11464 SQLINTEGER bufmax, SQLINTEGER *buflen)
11465 {
11466 DBC *d;
11467 SQLINTEGER dummy;
11468
11469 if (dbc == SQL_NULL_HDBC) {
11470 return SQL_INVALID_HANDLE;
11471 }
11472 d = (DBC *) dbc;
11473 if (!val) {
11474 val = (SQLPOINTER) &dummy;
11475 }
11476 if (!buflen) {
11477 buflen = &dummy;
11478 }
11479 switch (attr) {
11480 case SQL_ATTR_CONNECTION_DEAD:
11481 *((SQLINTEGER *) val) = d->sqlite ? SQL_CD_FALSE : SQL_CD_TRUE;
11482 *buflen = sizeof (SQLINTEGER);
11483 break;
11484 case SQL_ATTR_ACCESS_MODE:
11485 *((SQLINTEGER *) val) = SQL_MODE_READ_WRITE;
11486 *buflen = sizeof (SQLINTEGER);
11487 break;
11488 case SQL_ATTR_AUTOCOMMIT:
11489 *((SQLINTEGER *) val) =
11490 d->autocommit ? SQL_AUTOCOMMIT_ON : SQL_AUTOCOMMIT_OFF;
11491 *buflen = sizeof (SQLINTEGER);
11492 break;
11493 case SQL_ATTR_LOGIN_TIMEOUT:
11494 *((SQLINTEGER *) val) = 100;
11495 *buflen = sizeof (SQLINTEGER);
11496 break;
11497 case SQL_ATTR_ODBC_CURSORS:
11498 *((SQLINTEGER *) val) = SQL_CUR_USE_DRIVER;
11499 *buflen = sizeof (SQLINTEGER);
11500 break;
11501 case SQL_ATTR_PACKET_SIZE:
11502 *((SQLINTEGER *) val) = 16384;
11503 *buflen = sizeof (SQLINTEGER);
11504 break;
11505 case SQL_ATTR_TXN_ISOLATION:
11506 *((SQLINTEGER *) val) = SQL_TXN_SERIALIZABLE;
11507 *buflen = sizeof (SQLINTEGER);
11508 break;
11509 case SQL_ATTR_TRACEFILE:
11510 case SQL_ATTR_TRANSLATE_LIB:
11511 *((SQLCHAR *) val) = 0;
11512 *buflen = 0;
11513 break;
11514 case SQL_ATTR_CURRENT_CATALOG:
11515 #if defined(_WIN32) || defined(_WIN64)
11516 if (d->xcelqrx) {
11517 if ((bufmax > 4) && (val != (SQLPOINTER) &dummy)) {
11518 strcpy((char *) val, "main");
11519 *buflen = 4;
11520 break;
11521 }
11522 }
11523 #endif
11524 *((SQLCHAR *) val) = 0;
11525 *buflen = 0;
11526 break;
11527 case SQL_ATTR_TRACE:
11528 case SQL_ATTR_QUIET_MODE:
11529 case SQL_ATTR_TRANSLATE_OPTION:
11530 case SQL_ATTR_KEYSET_SIZE:
11531 case SQL_ATTR_QUERY_TIMEOUT:
11532 *((SQLINTEGER *) val) = 0;
11533 *buflen = sizeof (SQLINTEGER);
11534 break;
11535 case SQL_ATTR_PARAM_BIND_TYPE:
11536 *((SQLULEN *) val) = SQL_PARAM_BIND_BY_COLUMN;
11537 *buflen = sizeof (SQLUINTEGER);
11538 break;
11539 case SQL_ATTR_ROW_BIND_TYPE:
11540 *((SQLULEN *) val) = SQL_BIND_BY_COLUMN;
11541 *buflen = sizeof (SQLULEN);
11542 break;
11543 case SQL_ATTR_USE_BOOKMARKS:
11544 *((SQLINTEGER *) val) = SQL_UB_OFF;
11545 *buflen = sizeof (SQLINTEGER);
11546 break;
11547 case SQL_ATTR_ASYNC_ENABLE:
11548 *((SQLINTEGER *) val) = SQL_ASYNC_ENABLE_OFF;
11549 *buflen = sizeof (SQLINTEGER);
11550 break;
11551 case SQL_ATTR_NOSCAN:
11552 *((SQLINTEGER *) val) = SQL_NOSCAN_ON;
11553 *buflen = sizeof (SQLINTEGER);
11554 break;
11555 case SQL_ATTR_CONCURRENCY:
11556 *((SQLINTEGER *) val) = SQL_CONCUR_LOCK;
11557 *buflen = sizeof (SQLINTEGER);
11558 break;
11559 #ifdef SQL_ATTR_CURSOR_SENSITIVITY
11560 case SQL_ATTR_CURSOR_SENSITIVITY:
11561 *((SQLINTEGER *) val) = SQL_UNSPECIFIED;
11562 *buflen = sizeof (SQLINTEGER);
11563 break;
11564 #endif
11565 case SQL_ATTR_SIMULATE_CURSOR:
11566 *((SQLINTEGER *) val) = SQL_SC_NON_UNIQUE;
11567 *buflen = sizeof (SQLINTEGER);
11568 break;
11569 case SQL_ATTR_MAX_ROWS:
11570 *((SQLINTEGER *) val) = 0;
11571 *buflen = sizeof (SQLINTEGER);
11572 case SQL_ATTR_MAX_LENGTH:
11573 *((SQLINTEGER *) val) = 1000000000;
11574 *buflen = sizeof (SQLINTEGER);
11575 break;
11576 case SQL_ATTR_CURSOR_TYPE:
11577 *((SQLINTEGER *) val) = d->curtype;
11578 *buflen = sizeof (SQLINTEGER);
11579 break;
11580 case SQL_ATTR_RETRIEVE_DATA:
11581 *((SQLINTEGER *) val) = SQL_RD_ON;
11582 *buflen = sizeof (SQLINTEGER);
11583 break;
11584 #ifdef SQL_ATTR_METADATA_ID
11585 case SQL_ATTR_METADATA_ID:
11586 *((SQLULEN *) val) = SQL_FALSE;
11587 return SQL_SUCCESS;
11588 #endif
11589 default:
11590 *((SQLINTEGER *) val) = 0;
11591 *buflen = sizeof (SQLINTEGER);
11592 setstatd(d, -1, "unsupported connect attribute %d",
11593 (*d->ov3) ? "HYC00" : "S1C00", (int) attr);
11594 return SQL_ERROR;
11595 }
11596 return SQL_SUCCESS;
11597 }
11598
11599 #ifndef WINTERFACE
11600 /**
11601 * Get connect attribute of HDBC.
11602 * @param dbc database connection handle
11603 * @param attr option to be retrieved
11604 * @param val output buffer
11605 * @param bufmax size of output buffer
11606 * @param buflen output length
11607 * @result ODBC error code
11608 */
11609
11610 SQLRETURN SQL_API
SQLGetConnectAttr(SQLHDBC dbc,SQLINTEGER attr,SQLPOINTER val,SQLINTEGER bufmax,SQLINTEGER * buflen)11611 SQLGetConnectAttr(SQLHDBC dbc, SQLINTEGER attr, SQLPOINTER val,
11612 SQLINTEGER bufmax, SQLINTEGER *buflen)
11613 {
11614 SQLRETURN ret;
11615
11616 HDBC_LOCK(dbc);
11617 ret = drvgetconnectattr(dbc, attr, val, bufmax, buflen);
11618 HDBC_UNLOCK(dbc);
11619 return ret;
11620 }
11621 #endif
11622
11623 #ifdef WINTERFACE
11624 /**
11625 * Get connect attribute of HDBC (UNICODE version).
11626 * @param dbc database connection handle
11627 * @param attr option to be retrieved
11628 * @param val output buffer
11629 * @param bufmax size of output buffer
11630 * @param buflen output length
11631 * @result ODBC error code
11632 */
11633
11634 SQLRETURN SQL_API
SQLGetConnectAttrW(SQLHDBC dbc,SQLINTEGER attr,SQLPOINTER val,SQLINTEGER bufmax,SQLINTEGER * buflen)11635 SQLGetConnectAttrW(SQLHDBC dbc, SQLINTEGER attr, SQLPOINTER val,
11636 SQLINTEGER bufmax, SQLINTEGER *buflen)
11637 {
11638 SQLRETURN ret;
11639 SQLINTEGER len = 0;
11640
11641 HDBC_LOCK(dbc);
11642 ret = drvgetconnectattr(dbc, attr, val, bufmax, &len);
11643 if (ret == SQL_SUCCESS) {
11644 SQLWCHAR *v = NULL;
11645
11646 switch (attr) {
11647 case SQL_ATTR_TRACEFILE:
11648 case SQL_ATTR_CURRENT_CATALOG:
11649 case SQL_ATTR_TRANSLATE_LIB:
11650 if (val) {
11651 if (len > 0) {
11652 v = uc_from_utf((SQLCHAR *) val, len);
11653 if (v) {
11654 int vmax = bufmax / sizeof (SQLWCHAR);
11655
11656 uc_strncpy(val, v, vmax);
11657 if (len < vmax) {
11658 len = min(vmax, uc_strlen(v));
11659 v[len] = 0;
11660 } else {
11661 len = vmax;
11662 }
11663 uc_free(v);
11664 len *= sizeof (SQLWCHAR);
11665 } else {
11666 len = 0;
11667 }
11668 }
11669 if (len <= 0) {
11670 len = 0;
11671 if (bufmax >= sizeof (SQLWCHAR)) {
11672 *((SQLWCHAR *)val) = 0;
11673 }
11674 }
11675 } else {
11676 len *= sizeof (SQLWCHAR);
11677 }
11678 break;
11679 }
11680 if (buflen) {
11681 *buflen = len;
11682 }
11683 }
11684 HDBC_UNLOCK(dbc);
11685 return ret;
11686 }
11687 #endif
11688
11689 /**
11690 * Internal set connect attribute of HDBC.
11691 * @param dbc database connection handle
11692 * @param attr option to be set
11693 * @param val option value
11694 * @param len size of option
11695 * @result ODBC error code
11696 */
11697
11698 static SQLRETURN
drvsetconnectattr(SQLHDBC dbc,SQLINTEGER attr,SQLPOINTER val,SQLINTEGER len)11699 drvsetconnectattr(SQLHDBC dbc, SQLINTEGER attr, SQLPOINTER val,
11700 SQLINTEGER len)
11701 {
11702 DBC *d;
11703
11704 if (dbc == SQL_NULL_HDBC) {
11705 return SQL_INVALID_HANDLE;
11706 }
11707 d = (DBC *) dbc;
11708 switch (attr) {
11709 case SQL_AUTOCOMMIT:
11710 d->autocommit = val == (SQLPOINTER) SQL_AUTOCOMMIT_ON;
11711 if (d->autocommit && d->intrans) {
11712 return endtran(d, SQL_COMMIT, 1);
11713 } else if (!d->autocommit) {
11714 s4stmt_end(d->cur_s4stmt);
11715 }
11716 break;
11717 #ifdef SQL_ATTR_METADATA_ID
11718 case SQL_ATTR_METADATA_ID:
11719 if (val == (SQLPOINTER) SQL_FALSE) {
11720 break;
11721 }
11722 /* fall through */
11723 #endif
11724 default:
11725 setstatd(d, -1, "option value changed", "01S02");
11726 return SQL_SUCCESS_WITH_INFO;
11727 }
11728 return SQL_SUCCESS;
11729 }
11730
11731 #ifndef WINTERFACE
11732 /**
11733 * Set connect attribute of HDBC.
11734 * @param dbc database connection handle
11735 * @param attr option to be set
11736 * @param val option value
11737 * @param len size of option
11738 * @result ODBC error code
11739 */
11740
11741 SQLRETURN SQL_API
SQLSetConnectAttr(SQLHDBC dbc,SQLINTEGER attr,SQLPOINTER val,SQLINTEGER len)11742 SQLSetConnectAttr(SQLHDBC dbc, SQLINTEGER attr, SQLPOINTER val,
11743 SQLINTEGER len)
11744 {
11745 SQLRETURN ret;
11746
11747 HDBC_LOCK(dbc);
11748 ret = drvsetconnectattr(dbc, attr, val, len);
11749 HDBC_UNLOCK(dbc);
11750 return ret;
11751 }
11752 #endif
11753
11754 #ifdef WINTERFACE
11755 /**
11756 * Set connect attribute of HDBC (UNICODE version).
11757 * @param dbc database connection handle
11758 * @param attr option to be set
11759 * @param val option value
11760 * @param len size of option
11761 * @result ODBC error code
11762 */
11763
11764 SQLRETURN SQL_API
SQLSetConnectAttrW(SQLHDBC dbc,SQLINTEGER attr,SQLPOINTER val,SQLINTEGER len)11765 SQLSetConnectAttrW(SQLHDBC dbc, SQLINTEGER attr, SQLPOINTER val,
11766 SQLINTEGER len)
11767 {
11768 SQLRETURN ret;
11769
11770 HDBC_LOCK(dbc);
11771 ret = drvsetconnectattr(dbc, attr, val, len);
11772 HDBC_UNLOCK(dbc);
11773 return ret;
11774 }
11775 #endif
11776
11777 /**
11778 * Internal get connect option of HDBC.
11779 * @param dbc database connection handle
11780 * @param opt option to be retrieved
11781 * @param param output buffer
11782 * @result ODBC error code
11783 */
11784
11785 static SQLRETURN
drvgetconnectoption(SQLHDBC dbc,SQLUSMALLINT opt,SQLPOINTER param)11786 drvgetconnectoption(SQLHDBC dbc, SQLUSMALLINT opt, SQLPOINTER param)
11787 {
11788 DBC *d;
11789 SQLINTEGER dummy;
11790
11791 if (dbc == SQL_NULL_HDBC) {
11792 return SQL_INVALID_HANDLE;
11793 }
11794 d = (DBC *) dbc;
11795 if (!param) {
11796 param = (SQLPOINTER) &dummy;
11797 }
11798 switch (opt) {
11799 case SQL_ACCESS_MODE:
11800 *((SQLINTEGER *) param) = SQL_MODE_READ_WRITE;
11801 break;
11802 case SQL_AUTOCOMMIT:
11803 *((SQLINTEGER *) param) =
11804 d->autocommit ? SQL_AUTOCOMMIT_ON : SQL_AUTOCOMMIT_OFF;
11805 break;
11806 case SQL_LOGIN_TIMEOUT:
11807 *((SQLINTEGER *) param) = 100;
11808 break;
11809 case SQL_ODBC_CURSORS:
11810 *((SQLINTEGER *) param) = SQL_CUR_USE_DRIVER;
11811 break;
11812 case SQL_PACKET_SIZE:
11813 *((SQLINTEGER *) param) = 16384;
11814 break;
11815 case SQL_TXN_ISOLATION:
11816 *((SQLINTEGER *) param) = SQL_TXN_SERIALIZABLE;
11817 break;
11818 case SQL_OPT_TRACE:
11819 case SQL_OPT_TRACEFILE:
11820 case SQL_QUIET_MODE:
11821 case SQL_TRANSLATE_DLL:
11822 case SQL_TRANSLATE_OPTION:
11823 case SQL_KEYSET_SIZE:
11824 case SQL_QUERY_TIMEOUT:
11825 case SQL_BIND_TYPE:
11826 case SQL_CURRENT_QUALIFIER:
11827 *((SQLINTEGER *) param) = 0;
11828 break;
11829 case SQL_USE_BOOKMARKS:
11830 *((SQLINTEGER *) param) = SQL_UB_OFF;
11831 break;
11832 case SQL_ASYNC_ENABLE:
11833 *((SQLINTEGER *) param) = SQL_ASYNC_ENABLE_OFF;
11834 break;
11835 case SQL_NOSCAN:
11836 *((SQLINTEGER *) param) = SQL_NOSCAN_ON;
11837 break;
11838 case SQL_CONCURRENCY:
11839 *((SQLINTEGER *) param) = SQL_CONCUR_LOCK;
11840 break;
11841 case SQL_SIMULATE_CURSOR:
11842 *((SQLINTEGER *) param) = SQL_SC_NON_UNIQUE;
11843 break;
11844 case SQL_MAX_ROWS:
11845 *((SQLINTEGER *) param) = 0;
11846 break;
11847 case SQL_ROWSET_SIZE:
11848 case SQL_MAX_LENGTH:
11849 *((SQLINTEGER *) param) = 1000000000;
11850 break;
11851 case SQL_CURSOR_TYPE:
11852 *((SQLINTEGER *) param) = d->curtype;
11853 break;
11854 case SQL_RETRIEVE_DATA:
11855 *((SQLINTEGER *) param) = SQL_RD_ON;
11856 break;
11857 default:
11858 *((SQLINTEGER *) param) = 0;
11859 setstatd(d, -1, "unsupported connect option %d",
11860 (*d->ov3) ? "HYC00" : "S1C00", opt);
11861 return SQL_ERROR;
11862 }
11863 return SQL_SUCCESS;
11864 }
11865
11866 #ifndef WINTERFACE
11867 /**
11868 * Get connect option of HDBC.
11869 * @param dbc database connection handle
11870 * @param opt option to be retrieved
11871 * @param param output buffer
11872 * @result ODBC error code
11873 */
11874
11875 SQLRETURN SQL_API
SQLGetConnectOption(SQLHDBC dbc,SQLUSMALLINT opt,SQLPOINTER param)11876 SQLGetConnectOption(SQLHDBC dbc, SQLUSMALLINT opt, SQLPOINTER param)
11877 {
11878 SQLRETURN ret;
11879
11880 HDBC_LOCK(dbc);
11881 ret = drvgetconnectoption(dbc, opt, param);
11882 HDBC_UNLOCK(dbc);
11883 return ret;
11884 }
11885 #endif
11886
11887 #ifdef WINTERFACE
11888 /**
11889 * Get connect option of HDBC (UNICODE version).
11890 * @param dbc database connection handle
11891 * @param opt option to be retrieved
11892 * @param param output buffer
11893 * @result ODBC error code
11894 */
11895
11896 SQLRETURN SQL_API
SQLGetConnectOptionW(SQLHDBC dbc,SQLUSMALLINT opt,SQLPOINTER param)11897 SQLGetConnectOptionW(SQLHDBC dbc, SQLUSMALLINT opt, SQLPOINTER param)
11898 {
11899 SQLRETURN ret;
11900
11901 HDBC_LOCK(dbc);
11902 ret = drvgetconnectoption(dbc, opt, param);
11903 if (SQL_SUCCEEDED(ret)) {
11904 switch (opt) {
11905 case SQL_OPT_TRACEFILE:
11906 case SQL_CURRENT_QUALIFIER:
11907 case SQL_TRANSLATE_DLL:
11908 if (param) {
11909 *(SQLWCHAR *) param = 0;
11910 }
11911 break;
11912 }
11913 }
11914 HDBC_UNLOCK(dbc);
11915 return ret;
11916 }
11917 #endif
11918
11919 /**
11920 * Internal set option on HDBC.
11921 * @param dbc database connection handle
11922 * @param opt option to be set
11923 * @param param option value
11924 * @result ODBC error code
11925 */
11926
11927 static SQLRETURN
drvsetconnectoption(SQLHDBC dbc,SQLUSMALLINT opt,SQLUINTEGER param)11928 drvsetconnectoption(SQLHDBC dbc, SQLUSMALLINT opt, SQLUINTEGER param)
11929 {
11930 DBC *d;
11931
11932 if (dbc == SQL_NULL_HDBC) {
11933 return SQL_INVALID_HANDLE;
11934 }
11935 d = (DBC *) dbc;
11936 switch (opt) {
11937 case SQL_AUTOCOMMIT:
11938 d->autocommit = param == SQL_AUTOCOMMIT_ON;
11939 if (d->autocommit && d->intrans) {
11940 return endtran(d, SQL_COMMIT, 1);
11941 } else if (!d->autocommit) {
11942 s4stmt_end(d->cur_s4stmt);
11943 }
11944 break;
11945 default:
11946 setstatd(d, -1, "option value changed", "01S02");
11947 return SQL_SUCCESS_WITH_INFO;
11948 }
11949 return SQL_SUCCESS;
11950 }
11951
11952 #ifndef WINTERFACE
11953 /**
11954 * Set option on HDBC.
11955 * @param dbc database connection handle
11956 * @param opt option to be set
11957 * @param param option value
11958 * @result ODBC error code
11959 */
11960
11961 SQLRETURN SQL_API
SQLSetConnectOption(SQLHDBC dbc,SQLUSMALLINT opt,SQLULEN param)11962 SQLSetConnectOption(SQLHDBC dbc, SQLUSMALLINT opt, SQLULEN param)
11963 {
11964 SQLRETURN ret;
11965
11966 HDBC_LOCK(dbc);
11967 ret = drvsetconnectoption(dbc, opt, param);
11968 HDBC_UNLOCK(dbc);
11969 return ret;
11970 }
11971 #endif
11972
11973 #ifdef WINTERFACE
11974 /**
11975 * Set option on HDBC (UNICODE version).
11976 * @param dbc database connection handle
11977 * @param opt option to be set
11978 * @param param option value
11979 * @result ODBC error code
11980 */
11981
11982 SQLRETURN SQL_API
SQLSetConnectOptionW(SQLHDBC dbc,SQLUSMALLINT opt,SQLULEN param)11983 SQLSetConnectOptionW(SQLHDBC dbc, SQLUSMALLINT opt, SQLULEN param)
11984 {
11985 SQLRETURN ret;
11986
11987 HDBC_LOCK(dbc);
11988 ret = drvsetconnectoption(dbc, opt, param);
11989 HDBC_UNLOCK(dbc);
11990 return ret;
11991 }
11992 #endif
11993
11994 #if defined(WITHOUT_DRIVERMGR) || (!defined(_WIN32) && !defined(_WIN64))
11995
11996 /**
11997 * Handling of SQLConnect() connection attributes
11998 * for standalone operation without driver manager.
11999 * @param dsn DSN/driver connection string
12000 * @param attr attribute string to be retrieved
12001 * @param out output buffer
12002 * @param outLen length of output buffer
12003 * @result true or false
12004 */
12005
12006 static int
getdsnattr(char * dsn,char * attr,char * out,int outLen)12007 getdsnattr(char *dsn, char *attr, char *out, int outLen)
12008 {
12009 char *str = dsn, *start;
12010 int len = strlen(attr);
12011
12012 while (*str) {
12013 while (*str && *str == ';') {
12014 ++str;
12015 }
12016 start = str;
12017 if ((str = strchr(str, '=')) == NULL) {
12018 return 0;
12019 }
12020 if (str - start == len && strncasecmp(start, attr, len) == 0) {
12021 start = ++str;
12022 while (*str && *str != ';') {
12023 ++str;
12024 }
12025 len = min(outLen - 1, str - start);
12026 strncpy(out, start, len);
12027 out[len] = '\0';
12028 return 1;
12029 }
12030 while (*str && *str != ';') {
12031 ++str;
12032 }
12033 }
12034 return 0;
12035 }
12036 #endif
12037
12038 /**
12039 * Internal connect to SQLite database.
12040 * @param dbc database connection handle
12041 * @param dsn DSN string
12042 * @param dsnLen length of DSN string or SQL_NTS
12043 * @param pwd password or NULL
12044 * @param pwdLen length of password or SQL_NTS
12045 * @param isu true/false: file name is UTF8 encoded
12046 * @result ODBC error code
12047 */
12048
12049 static SQLRETURN
drvconnect(SQLHDBC dbc,SQLCHAR * dsn,SQLSMALLINT dsnLen,char * pwd,int pwdLen,int isu)12050 drvconnect(SQLHDBC dbc, SQLCHAR *dsn, SQLSMALLINT dsnLen, char *pwd,
12051 int pwdLen, int isu)
12052 {
12053 DBC *d;
12054 int len;
12055 SQLRETURN ret;
12056 char buf[SQL_MAX_MESSAGE_LENGTH * 6], dbname[SQL_MAX_MESSAGE_LENGTH];
12057 char busy[SQL_MAX_MESSAGE_LENGTH / 4], tracef[SQL_MAX_MESSAGE_LENGTH];
12058 char loadext[SQL_MAX_MESSAGE_LENGTH];
12059 char sflag[32], spflag[32], ntflag[32], nwflag[32], biflag[32];
12060 char snflag[32], lnflag[32], ncflag[32], fkflag[32], jmode[32];
12061 #if defined(_WIN32) || defined(_WIN64)
12062 char oemcp[32];
12063 #endif
12064
12065 if (dbc == SQL_NULL_HDBC) {
12066 return SQL_INVALID_HANDLE;
12067 }
12068 d = (DBC *) dbc;
12069 if (d->magic != DBC_MAGIC) {
12070 return SQL_INVALID_HANDLE;
12071 }
12072 if (d->sqlite != NULL) {
12073 setstatd(d, -1, "connection already established", "08002");
12074 return SQL_ERROR;
12075 }
12076 buf[0] = '\0';
12077 if (dsnLen == SQL_NTS) {
12078 len = sizeof (buf) - 1;
12079 } else {
12080 len = min(sizeof (buf) - 1, dsnLen);
12081 }
12082 if (dsn != NULL) {
12083 strncpy(buf, (char *) dsn, len);
12084 }
12085 buf[len] = '\0';
12086 if (buf[0] == '\0') {
12087 setstatd(d, -1, "invalid DSN", (*d->ov3) ? "HY090" : "S1090");
12088 return SQL_ERROR;
12089 }
12090 #if defined(_WIN32) || defined(_WIN64)
12091 /*
12092 * When DSN is in UTF it must be converted to ANSI
12093 * here for ANSI SQLGetPrivateProfileString()
12094 */
12095 if (isu) {
12096 char *cdsn = utf_to_wmb(buf, len);
12097
12098 if (!cdsn) {
12099 setstatd(d, -1, "out of memory", (*d->ov3) ? "HY000" : "S1000");
12100 return SQL_ERROR;
12101 }
12102 strcpy(buf, cdsn);
12103 uc_free(cdsn);
12104 }
12105 #endif
12106 busy[0] = '\0';
12107 dbname[0] = '\0';
12108 #ifdef WITHOUT_DRIVERMGR
12109 getdsnattr(buf, "database", dbname, sizeof (dbname));
12110 if (dbname[0] == '\0') {
12111 strncpy(dbname, buf, sizeof (dbname));
12112 dbname[sizeof (dbname) - 1] = '\0';
12113 }
12114 getdsnattr(buf, "timeout", busy, sizeof (busy));
12115 sflag[0] = '\0';
12116 getdsnattr(buf, "stepapi", sflag, sizeof (sflag));
12117 spflag[0] = '\0';
12118 getdsnattr(buf, "syncpragma", spflag, sizeof (spflag));
12119 ntflag[0] = '\0';
12120 getdsnattr(buf, "notxn", ntflag, sizeof (ntflag));
12121 nwflag[0] = '\0';
12122 getdsnattr(buf, "nowchar", nwflag, sizeof (nwflag));
12123 snflag[0] = '\0';
12124 getdsnattr(buf, "shortnames", snflag, sizeof (snflag));
12125 lnflag[0] = '\0';
12126 getdsnattr(buf, "longnames", lnflag, sizeof (lnflag));
12127 ncflag[0] = '\0';
12128 getdsnattr(buf, "nocreat", ncflag, sizeof (ncflag));
12129 fkflag[0] = '\0';
12130 getdsnattr(buf, "fksupport", fkflag, sizeof (fkflag));
12131 loadext[0] = '\0';
12132 getdsnattr(buf, "loadext", loadext, sizeof (loadext));
12133 jmode[0] = '\0';
12134 getdsnattr(buf, "journalmode", jmode, sizeof (jmode));
12135 #if defined(_WIN32) || defined(_WIN64)
12136 oemcp[0] = '\0';
12137 getdsnattr(buf, "oemcp", oemcp, sizeof (oemcp));
12138 #endif
12139 biflag[0] = '\0';
12140 getdsnattr(buf, "bigint", biflag, sizeof (biflag));
12141 #else
12142 SQLGetPrivateProfileString(buf, "timeout", "100000",
12143 busy, sizeof (busy), ODBC_INI);
12144 SQLGetPrivateProfileString(buf, "database", "",
12145 dbname, sizeof (dbname), ODBC_INI);
12146 #if defined(_WIN32) || defined(_WIN64)
12147 /* database name read from registry is not UTF8 !!! */
12148 isu = 0;
12149 #endif
12150 SQLGetPrivateProfileString(buf, "stepapi", "",
12151 sflag, sizeof (sflag), ODBC_INI);
12152 SQLGetPrivateProfileString(buf, "syncpragma", "NORMAL",
12153 spflag, sizeof (spflag), ODBC_INI);
12154 SQLGetPrivateProfileString(buf, "notxn", "",
12155 ntflag, sizeof (ntflag), ODBC_INI);
12156 SQLGetPrivateProfileString(buf, "nowchar", "",
12157 nwflag, sizeof (nwflag), ODBC_INI);
12158 SQLGetPrivateProfileString(buf, "shortnames", "",
12159 snflag, sizeof (snflag), ODBC_INI);
12160 SQLGetPrivateProfileString(buf, "longnames", "",
12161 lnflag, sizeof (lnflag), ODBC_INI);
12162 SQLGetPrivateProfileString(buf, "nocreat", "",
12163 ncflag, sizeof (ncflag), ODBC_INI);
12164 SQLGetPrivateProfileString(buf, "fksupport", "",
12165 fkflag, sizeof (fkflag), ODBC_INI);
12166 SQLGetPrivateProfileString(buf, "loadext", "",
12167 loadext, sizeof (loadext), ODBC_INI);
12168 SQLGetPrivateProfileString(buf, "journalmode", "",
12169 jmode, sizeof (jmode), ODBC_INI);
12170 #if defined(_WIN32) || defined(_WIN64)
12171 SQLGetPrivateProfileString(buf, "oemcp", "1",
12172 oemcp, sizeof (oemcp), ODBC_INI);
12173 #endif
12174 SQLGetPrivateProfileString(buf, "bigint", "",
12175 biflag, sizeof (biflag), ODBC_INI);
12176 #endif
12177 tracef[0] = '\0';
12178 #ifdef WITHOUT_DRIVERMGR
12179 getdsnattr(buf, "tracefile", tracef, sizeof (tracef));
12180 #else
12181 SQLGetPrivateProfileString(buf, "tracefile", "",
12182 tracef, sizeof (tracef), ODBC_INI);
12183 #endif
12184 if (tracef[0] != '\0') {
12185 d->trace = fopen(tracef, "a");
12186 }
12187 d->nowchar = getbool(nwflag);
12188 d->shortnames = getbool(snflag);
12189 d->longnames = getbool(lnflag);
12190 d->nocreat = getbool(ncflag);
12191 d->fksupport = getbool(fkflag);
12192 #if defined(_WIN32) || defined(_WIN64)
12193 d->oemcp = getbool(oemcp);
12194 #else
12195 d->oemcp = 0;
12196 #endif
12197 d->dobigint = getbool(biflag);
12198 d->pwd = pwd;
12199 d->pwdLen = 0;
12200 if (d->pwd) {
12201 d->pwdLen = (pwdLen == SQL_NTS) ? strlen(d->pwd) : pwdLen;
12202 }
12203 ret = dbopen(d, dbname, isu, (char *) dsn, sflag, spflag, ntflag,
12204 jmode, busy);
12205 if (ret == SQL_SUCCESS) {
12206 dbloadext(d, loadext);
12207 }
12208 return ret;
12209 }
12210
12211 #ifndef WINTERFACE
12212 /**
12213 * Connect to SQLite database.
12214 * @param dbc database connection handle
12215 * @param dsn DSN string
12216 * @param dsnLen length of DSN string or SQL_NTS
12217 * @param uid user id string or NULL
12218 * @param uidLen length of user id string or SQL_NTS
12219 * @param pwd password string or NULL
12220 * @param pwdLen length of password string or SQL_NTS
12221 * @result ODBC error code
12222 */
12223
12224 SQLRETURN SQL_API
SQLConnect(SQLHDBC dbc,SQLCHAR * dsn,SQLSMALLINT dsnLen,SQLCHAR * uid,SQLSMALLINT uidLen,SQLCHAR * pwd,SQLSMALLINT pwdLen)12225 SQLConnect(SQLHDBC dbc, SQLCHAR *dsn, SQLSMALLINT dsnLen,
12226 SQLCHAR *uid, SQLSMALLINT uidLen,
12227 SQLCHAR *pwd, SQLSMALLINT pwdLen)
12228 {
12229 SQLRETURN ret;
12230
12231 HDBC_LOCK(dbc);
12232 ret = drvconnect(dbc, dsn, dsnLen, (char *) pwd, pwdLen, 0);
12233 HDBC_UNLOCK(dbc);
12234 return ret;
12235 }
12236 #endif
12237
12238 #ifdef WINTERFACE
12239 /**
12240 * Connect to SQLite database.
12241 * @param dbc database connection handle
12242 * @param dsn DSN string
12243 * @param dsnLen length of DSN string or SQL_NTS
12244 * @param uid user id string or NULL
12245 * @param uidLen length of user id string or SQL_NTS
12246 * @param pwd password string or NULL
12247 * @param pwdLen length of password string or SQL_NTS
12248 * @result ODBC error code
12249 */
12250
12251 SQLRETURN SQL_API
SQLConnectW(SQLHDBC dbc,SQLWCHAR * dsn,SQLSMALLINT dsnLen,SQLWCHAR * uid,SQLSMALLINT uidLen,SQLWCHAR * pwd,SQLSMALLINT pwdLen)12252 SQLConnectW(SQLHDBC dbc, SQLWCHAR *dsn, SQLSMALLINT dsnLen,
12253 SQLWCHAR *uid, SQLSMALLINT uidLen,
12254 SQLWCHAR *pwd, SQLSMALLINT pwdLen)
12255 {
12256 char *dsna = NULL;
12257 char *pwda = NULL;
12258 SQLRETURN ret;
12259
12260 HDBC_LOCK(dbc);
12261 if (dsn) {
12262 dsna = uc_to_utf_c(dsn, dsnLen);
12263 if (!dsna) {
12264 DBC *d = (DBC *) dbc;
12265
12266 setstatd(d, -1, "out of memory", (*d->ov3) ? "HY000" : "S1000");
12267 ret = SQL_ERROR;
12268 goto done;
12269 }
12270 }
12271 if (pwd) {
12272 pwda = uc_to_utf_c(pwd, pwdLen);
12273 if (!pwda) {
12274 DBC *d = (DBC *) dbc;
12275
12276 setstatd(d, -1, "out of memory", (*d->ov3) ? "HY000" : "S1000");
12277 ret = SQL_ERROR;
12278 goto done;
12279 }
12280 }
12281 ret = drvconnect(dbc, (SQLCHAR *) dsna, SQL_NTS, pwda, SQL_NTS, 1);
12282 done:
12283 HDBC_UNLOCK(dbc);
12284 uc_free(dsna);
12285 uc_free(pwda);
12286 return ret;
12287 }
12288 #endif
12289
12290 /**
12291 * Internal disconnect given HDBC.
12292 * @param dbc database connection handle
12293 * @result ODBC error code
12294 */
12295
12296 static SQLRETURN
drvdisconnect(SQLHDBC dbc)12297 drvdisconnect(SQLHDBC dbc)
12298 {
12299 DBC *d;
12300
12301 if (dbc == SQL_NULL_HDBC) {
12302 return SQL_INVALID_HANDLE;
12303 }
12304 d = (DBC *) dbc;
12305 if (d->magic != DBC_MAGIC) {
12306 return SQL_INVALID_HANDLE;
12307 }
12308 if (d->intrans) {
12309 setstatd(d, -1, "incomplete transaction", "25000");
12310 return SQL_ERROR;
12311 }
12312 if (d->cur_s4stmt) {
12313 s4stmt_end(d->cur_s4stmt);
12314 }
12315 if (d->sqlite) {
12316 if (d->trace) {
12317 fprintf(d->trace, "-- sqlite4_close: '%s'\n",
12318 d->dbname);
12319 fflush(d->trace);
12320 }
12321 sqlite4_close(d->sqlite, 0);
12322 d->sqlite = NULL;
12323 }
12324 freep(&d->dbname);
12325 freep(&d->dsn);
12326 return SQL_SUCCESS;
12327 }
12328
12329 /**
12330 * Disconnect given HDBC.
12331 * @param dbc database connection handle
12332 * @result ODBC error code
12333 */
12334
12335 SQLRETURN SQL_API
SQLDisconnect(SQLHDBC dbc)12336 SQLDisconnect(SQLHDBC dbc)
12337 {
12338 SQLRETURN ret;
12339
12340 HDBC_LOCK(dbc);
12341 ret = drvdisconnect(dbc);
12342 HDBC_UNLOCK(dbc);
12343 return ret;
12344 }
12345
12346 #if defined(WITHOUT_DRIVERMGR) || (!defined(_WIN32) && !defined(_WIN64))
12347
12348 /**
12349 * Internal standalone (w/o driver manager) database connect.
12350 * @param dbc database connection handle
12351 * @param hwnd dummy window handle or NULL
12352 * @param connIn driver connect input string
12353 * @param connInLen length of driver connect input string or SQL_NTS
12354 * @param connOut driver connect output string
12355 * @param connOutMax length of driver connect output string
12356 * @param connOutLen output length of driver connect output string
12357 * @param drvcompl completion type
12358 * @result ODBC error code
12359 */
12360
12361 static SQLRETURN
drvdriverconnect(SQLHDBC dbc,SQLHWND hwnd,SQLCHAR * connIn,SQLSMALLINT connInLen,SQLCHAR * connOut,SQLSMALLINT connOutMax,SQLSMALLINT * connOutLen,SQLUSMALLINT drvcompl)12362 drvdriverconnect(SQLHDBC dbc, SQLHWND hwnd,
12363 SQLCHAR *connIn, SQLSMALLINT connInLen,
12364 SQLCHAR *connOut, SQLSMALLINT connOutMax,
12365 SQLSMALLINT *connOutLen, SQLUSMALLINT drvcompl)
12366 {
12367 DBC *d;
12368 int len;
12369 SQLRETURN ret;
12370 char buf[SQL_MAX_MESSAGE_LENGTH * 6], dbname[SQL_MAX_MESSAGE_LENGTH];
12371 char dsn[SQL_MAX_MESSAGE_LENGTH], busy[SQL_MAX_MESSAGE_LENGTH / 4];
12372 char tracef[SQL_MAX_MESSAGE_LENGTH], loadext[SQL_MAX_MESSAGE_LENGTH];
12373 char pwd[SQL_MAX_MESSAGE_LENGTH];
12374 char sflag[32], spflag[32], ntflag[32], snflag[32], lnflag[32];
12375 char ncflag[32], nwflag[32], fkflag[32], jmode[32], biflag[32];
12376
12377 if (dbc == SQL_NULL_HDBC) {
12378 return SQL_INVALID_HANDLE;
12379 }
12380 if (drvcompl != SQL_DRIVER_COMPLETE &&
12381 drvcompl != SQL_DRIVER_COMPLETE_REQUIRED &&
12382 drvcompl != SQL_DRIVER_PROMPT &&
12383 drvcompl != SQL_DRIVER_NOPROMPT) {
12384 return SQL_NO_DATA;
12385 }
12386 d = (DBC *) dbc;
12387 if (d->sqlite) {
12388 setstatd(d, -1, "connection already established", "08002");
12389 return SQL_ERROR;
12390 }
12391 buf[0] = '\0';
12392 if (connInLen == SQL_NTS) {
12393 len = sizeof (buf) - 1;
12394 } else {
12395 len = min(connInLen, sizeof (buf) - 1);
12396 }
12397 if (connIn != NULL) {
12398 strncpy(buf, (char *) connIn, len);
12399 }
12400 buf[len] = '\0';
12401 if (!buf[0]) {
12402 setstatd(d, -1, "invalid connect attributes",
12403 (*d->ov3) ? "HY090" : "S1090");
12404 return SQL_ERROR;
12405 }
12406 dsn[0] = '\0';
12407 getdsnattr(buf, "DSN", dsn, sizeof (dsn));
12408
12409 /* special case: connIn is sole DSN value without keywords */
12410 if (!dsn[0] && !strchr(buf, ';') && !strchr(buf, '=')) {
12411 strncpy(dsn, buf, sizeof (dsn) - 1);
12412 dsn[sizeof (dsn) - 1] = '\0';
12413 }
12414
12415 busy[0] = '\0';
12416 getdsnattr(buf, "timeout", busy, sizeof (busy));
12417 #ifndef WITHOUT_DRIVERMGR
12418 if (dsn[0] && !busy[0]) {
12419 SQLGetPrivateProfileString(dsn, "timeout", "100000",
12420 busy, sizeof (busy), ODBC_INI);
12421 }
12422 #endif
12423 dbname[0] = '\0';
12424 getdsnattr(buf, "database", dbname, sizeof (dbname));
12425 #ifndef WITHOUT_DRIVERMGR
12426 if (dsn[0] && !dbname[0]) {
12427 SQLGetPrivateProfileString(dsn, "database", "",
12428 dbname, sizeof (dbname), ODBC_INI);
12429 }
12430 #endif
12431 sflag[0] = '\0';
12432 getdsnattr(buf, "stepapi", sflag, sizeof (sflag));
12433 #ifndef WITHOUT_DRIVERMGR
12434 if (dsn[0] && !sflag[0]) {
12435 SQLGetPrivateProfileString(dsn, "stepapi", "",
12436 sflag, sizeof (sflag), ODBC_INI);
12437 }
12438 #endif
12439 spflag[0] = '\0';
12440 getdsnattr(buf, "syncpragma", spflag, sizeof (spflag));
12441 #ifndef WITHOUT_DRIVERMGR
12442 if (dsn[0] && !spflag[0]) {
12443 SQLGetPrivateProfileString(dsn, "syncpragma", "NORMAL",
12444 spflag, sizeof (spflag), ODBC_INI);
12445 }
12446 #endif
12447 ntflag[0] = '\0';
12448 getdsnattr(buf, "notxn", ntflag, sizeof (ntflag));
12449 #ifndef WITHOUT_DRIVERMGR
12450 if (dsn[0] && !ntflag[0]) {
12451 SQLGetPrivateProfileString(dsn, "notxn", "",
12452 ntflag, sizeof (ntflag), ODBC_INI);
12453 }
12454 #endif
12455 snflag[0] = '\0';
12456 getdsnattr(buf, "shortnames", snflag, sizeof (snflag));
12457 #ifndef WITHOUT_DRIVERMGR
12458 if (dsn[0] && !snflag[0]) {
12459 SQLGetPrivateProfileString(dsn, "shortnames", "",
12460 snflag, sizeof (snflag), ODBC_INI);
12461 }
12462 #endif
12463 lnflag[0] = '\0';
12464 getdsnattr(buf, "longnames", lnflag, sizeof (lnflag));
12465 #ifndef WITHOUT_DRIVERMGR
12466 if (dsn[0] && !lnflag[0]) {
12467 SQLGetPrivateProfileString(dsn, "longnames", "",
12468 lnflag, sizeof (lnflag), ODBC_INI);
12469 }
12470 #endif
12471 ncflag[0] = '\0';
12472 getdsnattr(buf, "nocreat", ncflag, sizeof (ncflag));
12473 #ifndef WITHOUT_DRIVERMGR
12474 if (dsn[0] && !ncflag[0]) {
12475 SQLGetPrivateProfileString(dsn, "nocreat", "",
12476 ncflag, sizeof (ncflag), ODBC_INI);
12477 }
12478 #endif
12479 nwflag[0] = '\0';
12480 getdsnattr(buf, "nowchar", nwflag, sizeof (nwflag));
12481 #ifndef WITHOUT_DRIVERMGR
12482 if (dsn[0] && !nwflag[0]) {
12483 SQLGetPrivateProfileString(dsn, "nowchar", "",
12484 nwflag, sizeof (nwflag), ODBC_INI);
12485 }
12486 #endif
12487 fkflag[0] = '\0';
12488 getdsnattr(buf, "fksupport", fkflag, sizeof (fkflag));
12489 #ifndef WITHOUT_DRIVERMGR
12490 if (dsn[0] && !fkflag[0]) {
12491 SQLGetPrivateProfileString(dsn, "fksupport", "",
12492 fkflag, sizeof (fkflag), ODBC_INI);
12493 }
12494 #endif
12495 loadext[0] = '\0';
12496 getdsnattr(buf, "loadext", loadext, sizeof (loadext));
12497 #ifndef WITHOUT_DRIVERMGR
12498 if (dsn[0] && !loadext[0]) {
12499 SQLGetPrivateProfileString(dsn, "loadext", "",
12500 loadext, sizeof (loadext), ODBC_INI);
12501 }
12502 #endif
12503 jmode[0] = '\0';
12504 getdsnattr(buf, "journalmode", jmode, sizeof (jmode));
12505 #ifndef WITHOUT_DRIVERMGR
12506 if (dsn[0] && !jmode[0]) {
12507 SQLGetPrivateProfileString(dsn, "journalmode", "",
12508 jmode, sizeof (jmode), ODBC_INI);
12509 }
12510 #endif
12511 biflag[0] = '\0';
12512 getdsnattr(buf, "bigint", biflag, sizeof (biflag));
12513 #ifndef WITHOUT_DRIVERMGR
12514 if (dsn[0] && !biflag[0]) {
12515 SQLGetPrivateProfileString(dsn, "bigint", "",
12516 biflag, sizeof (biflag), ODBC_INI);
12517 }
12518 #endif
12519 pwd[0] = '\0';
12520 getdsnattr(buf, "pwd", pwd, sizeof (pwd));
12521 #ifndef WITHOUT_DRIVERMGR
12522 if (dsn[0] && !pwd[0]) {
12523 SQLGetPrivateProfileString(dsn, "pwd", "",
12524 pwd, sizeof (pwd), ODBC_INI);
12525 }
12526 #endif
12527
12528 if (!dbname[0] && !dsn[0]) {
12529 strcpy(dsn, "SQLite");
12530 strncpy(dbname, buf, sizeof (dbname));
12531 dbname[sizeof (dbname) - 1] = '\0';
12532 }
12533 tracef[0] = '\0';
12534 getdsnattr(buf, "tracefile", tracef, sizeof (tracef));
12535 #ifndef WITHOUT_DRIVERMGR
12536 if (dsn[0] && !tracef[0]) {
12537 SQLGetPrivateProfileString(dsn, "tracefile", "",
12538 tracef, sizeof (tracef), ODBC_INI);
12539 }
12540 #endif
12541 if (connOut || connOutLen) {
12542 int count;
12543
12544 buf[0] = '\0';
12545 count = snprintf(buf, sizeof (buf),
12546 "DSN=%s;Database=%s;StepAPI=%s;Timeout=%s;"
12547 "SyncPragma=%s;NoTXN=%s;ShortNames=%s;LongNames=%s;"
12548 "NoCreat=%s;NoWCHAR=%s;FKSupport=%s;Tracefile=%s;"
12549 "JournalMode=%s;LoadExt=%s;BigInt=%s;PWD=%s",
12550 dsn, dbname, sflag, busy, spflag, ntflag,
12551 snflag, lnflag, ncflag, nwflag, fkflag, tracef,
12552 jmode, loadext, biflag,pwd);
12553 if (count < 0) {
12554 buf[sizeof (buf) - 1] = '\0';
12555 }
12556 len = min(connOutMax - 1, strlen(buf));
12557 if (connOut) {
12558 strncpy((char *) connOut, buf, len);
12559 connOut[len] = '\0';
12560 }
12561 if (connOutLen) {
12562 *connOutLen = len;
12563 }
12564 }
12565 if (tracef[0] != '\0') {
12566 d->trace = fopen(tracef, "a");
12567 }
12568 d->shortnames = getbool(snflag);
12569 d->longnames = getbool(lnflag);
12570 d->nocreat = getbool(ncflag);
12571 d->nowchar = getbool(nwflag);
12572 d->fksupport = getbool(fkflag);
12573 d->dobigint = getbool(biflag);
12574 d->oemcp = 0;
12575 d->pwdLen = strlen(pwd);
12576 d->pwd = (d->pwdLen > 0) ? pwd : NULL;
12577 ret = dbopen(d, dbname, 0, dsn, sflag, spflag, ntflag, jmode, busy);
12578 memset(pwd, 0, sizeof (pwd));
12579 if (ret == SQL_SUCCESS) {
12580 dbloadext(d, loadext);
12581 }
12582 return ret;
12583 }
12584 #endif
12585
12586 /**
12587 * Internal free function for HSTMT.
12588 * @param stmt statement handle
12589 * @result ODBC error code
12590 */
12591
12592 static SQLRETURN
freestmt(SQLHSTMT stmt)12593 freestmt(SQLHSTMT stmt)
12594 {
12595 STMT *s;
12596 DBC *d;
12597
12598 if (stmt == SQL_NULL_HSTMT) {
12599 return SQL_INVALID_HANDLE;
12600 }
12601 s = (STMT *) stmt;
12602 s4stmt_drop(s);
12603 freeresult(s, 1);
12604 freep(&s->query);
12605 d = (DBC *) s->dbc;
12606 if (d && d->magic == DBC_MAGIC) {
12607 STMT *p, *n;
12608
12609 p = NULL;
12610 n = d->stmt;
12611 while (n) {
12612 if (n == s) {
12613 break;
12614 }
12615 p = n;
12616 n = n->next;
12617 }
12618 if (n) {
12619 if (p) {
12620 p->next = s->next;
12621 } else {
12622 d->stmt = s->next;
12623 }
12624 }
12625 }
12626 freeparams(s);
12627 freep(&s->bindparms);
12628 if (s->row_status0 != &s->row_status1) {
12629 freep(&s->row_status0);
12630 s->rowset_size = 1;
12631 s->row_status0 = &s->row_status1;
12632 }
12633 xfree(s);
12634 return SQL_SUCCESS;
12635 }
12636
12637 /**
12638 * Allocate HSTMT given HDBC (driver internal version).
12639 * @param dbc database connection handle
12640 * @param stmt pointer to statement handle
12641 * @result ODBC error code
12642 */
12643
12644 static SQLRETURN
drvallocstmt(SQLHDBC dbc,SQLHSTMT * stmt)12645 drvallocstmt(SQLHDBC dbc, SQLHSTMT *stmt)
12646 {
12647 DBC *d;
12648 STMT *s, *sl, *pl;
12649
12650 if (dbc == SQL_NULL_HDBC) {
12651 return SQL_INVALID_HANDLE;
12652 }
12653 d = (DBC *) dbc;
12654 if (d->magic != DBC_MAGIC || stmt == NULL) {
12655 return SQL_INVALID_HANDLE;
12656 }
12657 s = (STMT *) xmalloc(sizeof (STMT));
12658 if (s == NULL) {
12659 *stmt = SQL_NULL_HSTMT;
12660 return SQL_ERROR;
12661 }
12662 *stmt = (SQLHSTMT) s;
12663 memset(s, 0, sizeof (STMT));
12664 s->dbc = dbc;
12665 s->ov3 = d->ov3;
12666 s->bkmrk = SQL_UB_OFF;
12667 s->bkmrkptr = 0;
12668 s->oemcp = &d->oemcp;
12669 s->nowchar[0] = d->nowchar;
12670 s->nowchar[1] = 0;
12671 s->dobigint = d->dobigint;
12672 s->curtype = d->curtype;
12673 s->row_status0 = &s->row_status1;
12674 s->rowset_size = 1;
12675 s->longnames = d->longnames;
12676 s->retr_data = SQL_RD_ON;
12677 s->max_rows = 0;
12678 s->bind_type = SQL_BIND_BY_COLUMN;
12679 s->bind_offs = NULL;
12680 s->paramset_size = 1;
12681 s->parm_bind_type = SQL_PARAM_BIND_BY_COLUMN;
12682 s->one_tbl = -1;
12683 s->has_pk = -1;
12684 s->has_rowid = -1;
12685 #ifdef _WIN64
12686 sprintf((char *) s->cursorname, "CUR_%I64X", (SQLUBIGINT) *stmt);
12687 #else
12688 sprintf((char *) s->cursorname, "CUR_%016lX", (long) *stmt);
12689 #endif
12690 sl = d->stmt;
12691 pl = NULL;
12692 while (sl) {
12693 pl = sl;
12694 sl = sl->next;
12695 }
12696 if (pl) {
12697 pl->next = s;
12698 } else {
12699 d->stmt = s;
12700 }
12701 return SQL_SUCCESS;
12702 }
12703
12704 /**
12705 * Allocate HSTMT given HDBC.
12706 * @param dbc database connection handle
12707 * @param stmt pointer to statement handle
12708 * @result ODBC error code
12709 */
12710
12711 SQLRETURN SQL_API
SQLAllocStmt(SQLHDBC dbc,SQLHSTMT * stmt)12712 SQLAllocStmt(SQLHDBC dbc, SQLHSTMT *stmt)
12713 {
12714 SQLRETURN ret;
12715
12716 HDBC_LOCK(dbc);
12717 ret = drvallocstmt(dbc, stmt);
12718 HDBC_UNLOCK(dbc);
12719 return ret;
12720 }
12721
12722 /**
12723 * Internal function to perform certain kinds of free/close on STMT.
12724 * @param stmt statement handle
12725 * @param opt SQL_RESET_PARAMS, SQL_UNBIND, SQL_CLOSE, or SQL_DROP
12726 * @result ODBC error code
12727 */
12728
12729 static SQLRETURN
drvfreestmt(SQLHSTMT stmt,SQLUSMALLINT opt)12730 drvfreestmt(SQLHSTMT stmt, SQLUSMALLINT opt)
12731 {
12732 STMT *s;
12733 SQLRETURN ret = SQL_SUCCESS;
12734 SQLHDBC dbc;
12735
12736 if (stmt == SQL_NULL_HSTMT) {
12737 return SQL_INVALID_HANDLE;
12738 }
12739 HSTMT_LOCK(stmt);
12740 s = (STMT *) stmt;
12741 dbc = s->dbc;
12742 switch (opt) {
12743 case SQL_RESET_PARAMS:
12744 freeparams(s);
12745 break;
12746 case SQL_UNBIND:
12747 unbindcols(s);
12748 break;
12749 case SQL_CLOSE:
12750 s4stmt_end_if(s);
12751 freeresult(s, 0);
12752 break;
12753 case SQL_DROP:
12754 s4stmt_end_if(s);
12755 ret = freestmt(stmt);
12756 break;
12757 default:
12758 setstat(s, -1, "unsupported option", (*s->ov3) ? "HYC00" : "S1C00");
12759 ret = SQL_ERROR;
12760 break;
12761 }
12762 HDBC_UNLOCK(dbc);
12763 return ret;
12764 }
12765
12766 /**
12767 * Free HSTMT.
12768 * @param stmt statement handle
12769 * @param opt SQL_RESET_PARAMS, SQL_UNBIND, SQL_CLOSE, or SQL_DROP
12770 * @result ODBC error code
12771 */
12772
12773 SQLRETURN SQL_API
SQLFreeStmt(SQLHSTMT stmt,SQLUSMALLINT opt)12774 SQLFreeStmt(SQLHSTMT stmt, SQLUSMALLINT opt)
12775 {
12776 return drvfreestmt(stmt, opt);
12777 }
12778
12779 /**
12780 * Cancel HSTMT closing cursor.
12781 * @param stmt statement handle
12782 * @result ODBC error code
12783 */
12784
12785 SQLRETURN SQL_API
SQLCancel(SQLHSTMT stmt)12786 SQLCancel(SQLHSTMT stmt)
12787 {
12788 if (stmt != SQL_NULL_HSTMT) {
12789 DBC *d = (DBC *) ((STMT *) stmt)->dbc;
12790 #if defined(_WIN32) || defined(_WIN64)
12791 /* interrupt when other thread owns critical section */
12792 if (d->magic == DBC_MAGIC && d->owner != GetCurrentThreadId() &&
12793 d->owner != 0) {
12794 d->busyint = 1;
12795 sqlite4_interrupt(d->sqlite);
12796 return SQL_SUCCESS;
12797 }
12798 #else
12799 if (d->magic == DBC_MAGIC) {
12800 d->busyint = 1;
12801 sqlite4_interrupt(d->sqlite);
12802 }
12803 #endif
12804 }
12805 return drvfreestmt(stmt, SQL_CLOSE);
12806 }
12807
12808 /**
12809 * Internal function to get cursor name of STMT.
12810 * @param stmt statement handle
12811 * @param cursor output buffer
12812 * @param buflen length of output buffer
12813 * @param lenp output length
12814 * @result ODBC error code
12815 */
12816
12817 static SQLRETURN
drvgetcursorname(SQLHSTMT stmt,SQLCHAR * cursor,SQLSMALLINT buflen,SQLSMALLINT * lenp)12818 drvgetcursorname(SQLHSTMT stmt, SQLCHAR *cursor, SQLSMALLINT buflen,
12819 SQLSMALLINT *lenp)
12820 {
12821 STMT *s;
12822
12823 if (stmt == SQL_NULL_HSTMT) {
12824 return SQL_INVALID_HANDLE;
12825 }
12826 s = (STMT *) stmt;
12827 if (lenp && !cursor) {
12828 *lenp = strlen((char *) s->cursorname);
12829 return SQL_SUCCESS;
12830 }
12831 if (cursor) {
12832 if (buflen > 0) {
12833 strncpy((char *) cursor, (char *) s->cursorname, buflen - 1);
12834 cursor[buflen - 1] = '\0';
12835 }
12836 if (lenp) {
12837 *lenp = min(strlen((char *) s->cursorname), buflen - 1);
12838 }
12839 }
12840 return SQL_SUCCESS;
12841 }
12842
12843 #ifndef WINTERFACE
12844 /**
12845 * Get cursor name of STMT.
12846 * @param stmt statement handle
12847 * @param cursor output buffer
12848 * @param buflen length of output buffer
12849 * @param lenp output length
12850 * @result ODBC error code
12851 */
12852
12853 SQLRETURN SQL_API
SQLGetCursorName(SQLHSTMT stmt,SQLCHAR * cursor,SQLSMALLINT buflen,SQLSMALLINT * lenp)12854 SQLGetCursorName(SQLHSTMT stmt, SQLCHAR *cursor, SQLSMALLINT buflen,
12855 SQLSMALLINT *lenp)
12856 {
12857 SQLRETURN ret;
12858 #if defined(_WIN32) || defined(_WIN64)
12859 SQLSMALLINT len = 0;
12860 #endif
12861
12862 HSTMT_LOCK(stmt);
12863 #if defined(_WIN32) || defined(_WIN64)
12864 if (!((STMT *) stmt)->oemcp[0]) {
12865 ret = drvgetcursorname(stmt, cursor, buflen, lenp);
12866 goto done;
12867 }
12868 ret = drvgetcursorname(stmt, cursor, buflen, &len);
12869 if (ret == SQL_SUCCESS) {
12870 char *c = NULL;
12871
12872 if (cursor) {
12873 c = utf_to_wmb((char *) cursor, len);
12874 if (!c) {
12875 ret = nomem((STMT *) stmt);
12876 goto done;
12877 }
12878 c[len] = 0;
12879 len = strlen(c);
12880 if (buflen > 0) {
12881 strncpy((char *) cursor, c, buflen - 1);
12882 cursor[buflen - 1] = 0;
12883 }
12884 uc_free(c);
12885 }
12886 if (lenp) {
12887 *lenp = min(len, buflen - 1);
12888 }
12889 }
12890 done:
12891 ;
12892 #else
12893 ret = drvgetcursorname(stmt, cursor, buflen, lenp);
12894 #endif
12895 HSTMT_UNLOCK(stmt);
12896 return ret;
12897 }
12898 #endif
12899
12900 #ifdef WINTERFACE
12901 /**
12902 * Get cursor name of STMT (UNICODE version).
12903 * @param stmt statement handle
12904 * @param cursor output buffer
12905 * @param buflen length of output buffer
12906 * @param lenp output length
12907 * @result ODBC error code
12908 */
12909
12910 SQLRETURN SQL_API
SQLGetCursorNameW(SQLHSTMT stmt,SQLWCHAR * cursor,SQLSMALLINT buflen,SQLSMALLINT * lenp)12911 SQLGetCursorNameW(SQLHSTMT stmt, SQLWCHAR *cursor, SQLSMALLINT buflen,
12912 SQLSMALLINT *lenp)
12913 {
12914 SQLRETURN ret;
12915 SQLSMALLINT len = 0;
12916
12917 HSTMT_LOCK(stmt);
12918 ret = drvgetcursorname(stmt, (SQLCHAR *) cursor, buflen, &len);
12919 if (ret == SQL_SUCCESS) {
12920 SQLWCHAR *c = NULL;
12921
12922 if (cursor) {
12923 c = uc_from_utf((SQLCHAR *) cursor, len);
12924 if (!c) {
12925 ret = nomem((STMT *) stmt);
12926 goto done;
12927 }
12928 c[len] = 0;
12929 len = uc_strlen(c);
12930 if (buflen > 0) {
12931 uc_strncpy(cursor, c, buflen - 1);
12932 cursor[buflen - 1] = 0;
12933 }
12934 uc_free(c);
12935 }
12936 if (lenp) {
12937 *lenp = min(len, buflen - 1);
12938 }
12939 }
12940 done:
12941 HSTMT_UNLOCK(stmt);
12942 return ret;
12943 }
12944 #endif
12945
12946 /**
12947 * Internal function to set cursor name on STMT.
12948 * @param stmt statement handle
12949 * @param cursor new cursor name
12950 * @param len length of cursor name or SQL_NTS
12951 * @result ODBC error code
12952 */
12953
12954 static SQLRETURN
drvsetcursorname(SQLHSTMT stmt,SQLCHAR * cursor,SQLSMALLINT len)12955 drvsetcursorname(SQLHSTMT stmt, SQLCHAR *cursor, SQLSMALLINT len)
12956 {
12957 STMT *s;
12958
12959 if (stmt == SQL_NULL_HSTMT) {
12960 return SQL_INVALID_HANDLE;
12961 }
12962 s = (STMT *) stmt;
12963 if (!cursor ||
12964 !((cursor[0] >= 'A' && cursor[0] <= 'Z') ||
12965 (cursor[0] >= 'a' && cursor[0] <= 'z'))) {
12966 setstat(s, -1, "invalid cursor name", (*s->ov3) ? "HYC00" : "S1C00");
12967 return SQL_ERROR;
12968 }
12969 if (len == SQL_NTS) {
12970 len = sizeof (s->cursorname) - 1;
12971 } else {
12972 len = min(sizeof (s->cursorname) - 1, len);
12973 }
12974 strncpy((char *) s->cursorname, (char *) cursor, len);
12975 s->cursorname[len] = '\0';
12976 return SQL_SUCCESS;
12977 }
12978
12979 #ifndef WINTERFACE
12980 /**
12981 * Set cursor name on STMT.
12982 * @param stmt statement handle
12983 * @param cursor new cursor name
12984 * @param len length of cursor name or SQL_NTS
12985 * @result ODBC error code
12986 */
12987
12988 SQLRETURN SQL_API
SQLSetCursorName(SQLHSTMT stmt,SQLCHAR * cursor,SQLSMALLINT len)12989 SQLSetCursorName(SQLHSTMT stmt, SQLCHAR *cursor, SQLSMALLINT len)
12990 {
12991 #if defined(_WIN32) || defined(_WIN64)
12992 char *c = NULL;
12993 #endif
12994 SQLRETURN ret;
12995
12996 HSTMT_LOCK(stmt);
12997 #if defined(_WIN32) || defined(_WIN64)
12998 if (!((STMT *) stmt)->oemcp[0]) {
12999 ret = drvsetcursorname(stmt, cursor, len);
13000 goto done2;
13001 }
13002 if (cursor) {
13003 c = wmb_to_utf_c((char *) cursor, len);
13004 if (!c) {
13005 ret = nomem((STMT *) stmt);
13006 goto done;
13007 }
13008 }
13009 ret = drvsetcursorname(stmt, (SQLCHAR *) c, SQL_NTS);
13010 #else
13011 ret = drvsetcursorname(stmt, cursor, len);
13012 #endif
13013 #if defined(_WIN32) || defined(_WIN64)
13014 done:
13015 uc_free(c);
13016 done2:
13017 ;
13018 #endif
13019 HSTMT_UNLOCK(stmt);
13020 return ret;
13021 }
13022 #endif
13023
13024 #ifdef WINTERFACE
13025 /**
13026 * Set cursor name on STMT (UNICODE version).
13027 * @param stmt statement handle
13028 * @param cursor new cursor name
13029 * @param len length of cursor name or SQL_NTS
13030 * @result ODBC error code
13031 */
13032
13033 SQLRETURN SQL_API
SQLSetCursorNameW(SQLHSTMT stmt,SQLWCHAR * cursor,SQLSMALLINT len)13034 SQLSetCursorNameW(SQLHSTMT stmt, SQLWCHAR *cursor, SQLSMALLINT len)
13035 {
13036 char *c = NULL;
13037 SQLRETURN ret;
13038
13039 HSTMT_LOCK(stmt);
13040 if (cursor) {
13041 c = uc_to_utf_c(cursor, len);
13042 if (!c) {
13043 ret = nomem((STMT *) stmt);
13044 goto done;
13045 }
13046 }
13047 ret = drvsetcursorname(stmt, (SQLCHAR *) c, SQL_NTS);
13048 done:
13049 uc_free(c);
13050 HSTMT_UNLOCK(stmt);
13051 return ret;
13052 }
13053 #endif
13054
13055 /**
13056 * Close open cursor.
13057 * @param stmt statement handle
13058 * @return ODBC error code
13059 */
13060
13061 SQLRETURN SQL_API
SQLCloseCursor(SQLHSTMT stmt)13062 SQLCloseCursor(SQLHSTMT stmt)
13063 {
13064 return drvfreestmt(stmt, SQL_CLOSE);
13065 }
13066
13067 /**
13068 * Allocate a HENV, HDBC, or HSTMT handle.
13069 * @param type handle type
13070 * @param input input handle (HENV, HDBC)
13071 * @param output pointer to output handle (HENV, HDBC, HSTMT)
13072 * @result ODBC error code
13073 */
13074
13075 SQLRETURN SQL_API
SQLAllocHandle(SQLSMALLINT type,SQLHANDLE input,SQLHANDLE * output)13076 SQLAllocHandle(SQLSMALLINT type, SQLHANDLE input, SQLHANDLE *output)
13077 {
13078 SQLRETURN ret;
13079
13080 switch (type) {
13081 case SQL_HANDLE_ENV:
13082 ret = drvallocenv((SQLHENV *) output);
13083 if (ret == SQL_SUCCESS) {
13084 ENV *e = (ENV *) *output;
13085
13086 if (e && e->magic == ENV_MAGIC) {
13087 e->ov3 = 1;
13088 }
13089 }
13090 return ret;
13091 case SQL_HANDLE_DBC:
13092 return drvallocconnect((SQLHENV) input, (SQLHDBC *) output);
13093 case SQL_HANDLE_STMT:
13094 HDBC_LOCK((SQLHDBC) input);
13095 ret = drvallocstmt((SQLHDBC) input, (SQLHSTMT *) output);
13096 HDBC_UNLOCK((SQLHDBC) input);
13097 return ret;
13098 }
13099 return SQL_ERROR;
13100 }
13101
13102 /**
13103 * Free a HENV, HDBC, or HSTMT handle.
13104 * @param type handle type
13105 * @param h handle (HENV, HDBC, or HSTMT)
13106 * @result ODBC error code
13107 */
13108
13109 SQLRETURN SQL_API
SQLFreeHandle(SQLSMALLINT type,SQLHANDLE h)13110 SQLFreeHandle(SQLSMALLINT type, SQLHANDLE h)
13111 {
13112 switch (type) {
13113 case SQL_HANDLE_ENV:
13114 return drvfreeenv((SQLHENV) h);
13115 case SQL_HANDLE_DBC:
13116 return drvfreeconnect((SQLHDBC) h);
13117 case SQL_HANDLE_STMT:
13118 return drvfreestmt((SQLHSTMT) h, SQL_DROP);
13119 }
13120 return SQL_ERROR;
13121 }
13122
13123 /**
13124 * Free dynamically allocated column descriptions of STMT.
13125 * @param s statement pointer
13126 */
13127
13128 static void
freedyncols(STMT * s)13129 freedyncols(STMT *s)
13130 {
13131 if (s->dyncols) {
13132 int i;
13133
13134 for (i = 0; i < s->dcols; i++) {
13135 freep(&s->dyncols[i].typename);
13136 }
13137 if (s->cols == s->dyncols) {
13138 s->cols = NULL;
13139 s->ncols = 0;
13140 s->one_tbl = -1;
13141 s->has_pk = -1;
13142 }
13143 freep(&s->dyncols);
13144 }
13145 s->dcols = 0;
13146 }
13147
13148 /**
13149 * Free statement's result.
13150 * @param s statement pointer
13151 * @param clrcols flag to clear column information
13152 *
13153 * The result rows are free'd using the rowfree function pointer.
13154 * If clrcols is greater than zero, then column bindings and dynamic column
13155 * descriptions are free'd.
13156 * If clrcols is less than zero, then dynamic column descriptions are free'd.
13157 */
13158
13159 static void
freeresult(STMT * s,int clrcols)13160 freeresult(STMT *s, int clrcols)
13161 {
13162 freep(&s->bincache);
13163 s->bincell = NULL;
13164 s->binlen = 0;
13165 if (s->rows) {
13166 if (s->rowfree) {
13167 s->rowfree(s->rows);
13168 s->rowfree = NULL;
13169 }
13170 s->rows = NULL;
13171 }
13172 s->nrows = -1;
13173 if (clrcols > 0) {
13174 freep(&s->bindcols);
13175 s->nbindcols = 0;
13176 }
13177 if (clrcols) {
13178 freedyncols(s);
13179 s->cols = NULL;
13180 s->ncols = 0;
13181 s->nowchar[1] = 0;
13182 s->one_tbl = -1;
13183 s->has_pk = -1;
13184 s->has_rowid = -1;
13185 }
13186 }
13187
13188 /**
13189 * Reset bound columns to unbound state.
13190 * @param s statement pointer
13191 */
13192
13193 static void
unbindcols(STMT * s)13194 unbindcols(STMT *s)
13195 {
13196 int i;
13197
13198 for (i = 0; s->bindcols && i < s->nbindcols; i++) {
13199 s->bindcols[i].type = SQL_UNKNOWN_TYPE;
13200 s->bindcols[i].max = 0;
13201 s->bindcols[i].lenp = NULL;
13202 s->bindcols[i].valp = NULL;
13203 s->bindcols[i].index = i;
13204 s->bindcols[i].offs = 0;
13205 }
13206 }
13207
13208 /**
13209 * Reallocate space for bound columns.
13210 * @param s statement pointer
13211 * @param ncols number of columns
13212 * @result ODBC error code
13213 */
13214
13215 static SQLRETURN
mkbindcols(STMT * s,int ncols)13216 mkbindcols(STMT *s, int ncols)
13217 {
13218 if (s->bindcols) {
13219 if (s->nbindcols < ncols) {
13220 int i;
13221 BINDCOL *bindcols =
13222 xrealloc(s->bindcols, ncols * sizeof (BINDCOL));
13223
13224 if (!bindcols) {
13225 return nomem(s);
13226 }
13227 for (i = s->nbindcols; i < ncols; i++) {
13228 bindcols[i].type = SQL_UNKNOWN_TYPE;
13229 bindcols[i].max = 0;
13230 bindcols[i].lenp = NULL;
13231 bindcols[i].valp = NULL;
13232 bindcols[i].index = i;
13233 bindcols[i].offs = 0;
13234 }
13235 s->bindcols = bindcols;
13236 s->nbindcols = ncols;
13237 }
13238 } else if (ncols > 0) {
13239 s->bindcols = (BINDCOL *) xmalloc(ncols * sizeof (BINDCOL));
13240 if (!s->bindcols) {
13241 return nomem(s);
13242 }
13243 s->nbindcols = ncols;
13244 unbindcols(s);
13245 }
13246 return SQL_SUCCESS;
13247 }
13248
13249 /**
13250 * Internal function to retrieve row data, used by SQLFetch() and
13251 * friends and SQLGetData().
13252 * @param s statement pointer
13253 * @param col column number, 0 based
13254 * @param otype output data type
13255 * @param val output buffer
13256 * @param len length of output buffer
13257 * @param lenp output length
13258 * @param partial flag for partial data retrieval
13259 * @result ODBC error code
13260 */
13261
13262 static SQLRETURN
getrowdata(STMT * s,SQLUSMALLINT col,SQLSMALLINT otype,SQLPOINTER val,SQLINTEGER len,SQLLEN * lenp,int partial)13263 getrowdata(STMT *s, SQLUSMALLINT col, SQLSMALLINT otype,
13264 SQLPOINTER val, SQLINTEGER len, SQLLEN *lenp, int partial)
13265 {
13266 char **data, valdummy[16];
13267 SQLLEN dummy;
13268 SQLINTEGER *ilenp = NULL;
13269 int valnull = 0;
13270 int type = otype;
13271 SQLRETURN sret = SQL_NO_DATA;
13272
13273 if (!lenp) {
13274 lenp = &dummy;
13275 }
13276 /* workaround for JDK 1.7.0 on x86_64 */
13277 if (((SQLINTEGER *) lenp) + 1 == (SQLINTEGER *) val) {
13278 ilenp = (SQLINTEGER *) lenp;
13279 lenp = &dummy;
13280 }
13281 if (col >= s->ncols) {
13282 setstat(s, -1, "invalid column", (*s->ov3) ? "07009" : "S1002");
13283 return SQL_ERROR;
13284 }
13285 if (s->retr_data != SQL_RD_ON) {
13286 return SQL_SUCCESS;
13287 }
13288 if (!s->rows) {
13289 *lenp = SQL_NULL_DATA;
13290 goto done;
13291 }
13292 if (s->rowp < 0 || s->rowp >= s->nrows) {
13293 *lenp = SQL_NULL_DATA;
13294 goto done;
13295 }
13296 type = mapdeftype(type, s->cols[col].type, s->cols[col].nosign ? 1 : 0,
13297 s->nowchar[0]);
13298 #if (defined(_WIN32) || defined(_WIN64)) && defined(WINTERFACE)
13299 /* MS Access hack part 3 (map SQL_C_DEFAULT to SQL_C_CHAR) */
13300 if (type == SQL_C_WCHAR && otype == SQL_C_DEFAULT) {
13301 type = SQL_C_CHAR;
13302 }
13303 #endif
13304 data = s->rows + s->ncols + (s->rowp * s->ncols) + col;
13305 if (!val) {
13306 valnull = 1;
13307 val = (SQLPOINTER) valdummy;
13308 }
13309 if (*data == NULL) {
13310 *lenp = SQL_NULL_DATA;
13311 switch (type) {
13312 case SQL_C_UTINYINT:
13313 case SQL_C_TINYINT:
13314 case SQL_C_STINYINT:
13315 #ifdef SQL_BIT
13316 case SQL_C_BIT:
13317 #endif
13318 *((SQLCHAR *) val) = 0;
13319 break;
13320 case SQL_C_USHORT:
13321 case SQL_C_SHORT:
13322 case SQL_C_SSHORT:
13323 *((SQLSMALLINT *) val) = 0;
13324 break;
13325 case SQL_C_ULONG:
13326 case SQL_C_LONG:
13327 case SQL_C_SLONG:
13328 *((SQLINTEGER *) val) = 0;
13329 break;
13330 #ifdef SQL_BIGINT
13331 case SQL_C_SBIGINT:
13332 case SQL_C_UBIGINT:
13333 *((SQLBIGINT *) val) = 0;
13334 break;
13335 #endif
13336 case SQL_C_FLOAT:
13337 *((float *) val) = 0;
13338 break;
13339 case SQL_C_DOUBLE:
13340 *((double *) val) = 0;
13341 break;
13342 case SQL_C_BINARY:
13343 case SQL_C_CHAR:
13344 if (len > 0) {
13345 *((SQLCHAR *) val) = '\0';
13346 }
13347 break;
13348 #ifdef WCHARSUPPORT
13349 case SQL_C_WCHAR:
13350 if (len > 0) {
13351 *((SQLWCHAR *) val) = '\0';
13352 }
13353 break;
13354 #endif
13355 #ifdef SQL_C_TYPE_DATE
13356 case SQL_C_TYPE_DATE:
13357 #endif
13358 case SQL_C_DATE:
13359 memset((DATE_STRUCT *) val, 0, sizeof (DATE_STRUCT));
13360 break;
13361 #ifdef SQL_C_TYPE_TIME
13362 case SQL_C_TYPE_TIME:
13363 #endif
13364 case SQL_C_TIME:
13365 memset((TIME_STRUCT *) val, 0, sizeof (TIME_STRUCT));
13366 break;
13367 #ifdef SQL_C_TYPE_TIMESTAMP
13368 case SQL_C_TYPE_TIMESTAMP:
13369 #endif
13370 case SQL_C_TIMESTAMP:
13371 memset((TIMESTAMP_STRUCT *) val, 0, sizeof (TIMESTAMP_STRUCT));
13372 break;
13373 default:
13374 return SQL_ERROR;
13375 }
13376 } else {
13377 char *endp = NULL;
13378 #if defined(_WIN32) || defined(_WIN64)
13379 #ifdef SQL_BIGINT
13380 char endc;
13381 #endif
13382 #endif
13383
13384 switch (type) {
13385 case SQL_C_UTINYINT:
13386 case SQL_C_TINYINT:
13387 case SQL_C_STINYINT:
13388 *((SQLCHAR *) val) = strtol(*data, &endp, 0);
13389 if (endp && endp == *data) {
13390 *lenp = SQL_NULL_DATA;
13391 } else {
13392 *lenp = sizeof (SQLCHAR);
13393 }
13394 break;
13395 #ifdef SQL_BIT
13396 case SQL_C_BIT:
13397 *((SQLCHAR *) val) = getbool(*data);
13398 *lenp = sizeof (SQLCHAR);
13399 break;
13400 #endif
13401 case SQL_C_USHORT:
13402 case SQL_C_SHORT:
13403 case SQL_C_SSHORT:
13404 *((SQLSMALLINT *) val) = strtol(*data, &endp, 0);
13405 if (endp && endp == *data) {
13406 *lenp = SQL_NULL_DATA;
13407 } else {
13408 *lenp = sizeof (SQLSMALLINT);
13409 }
13410 break;
13411 case SQL_C_ULONG:
13412 case SQL_C_LONG:
13413 case SQL_C_SLONG:
13414 *((SQLINTEGER *) val) = strtol(*data, &endp, 0);
13415 if (endp && endp == *data) {
13416 *lenp = SQL_NULL_DATA;
13417 } else {
13418 *lenp = sizeof (SQLINTEGER);
13419 }
13420 break;
13421 #ifdef SQL_BIGINT
13422 case SQL_C_UBIGINT:
13423 #if defined(_WIN32) || defined(_WIN64)
13424 if (sscanf(*data, "%I64u%c", (SQLUBIGINT *) val, &endc) != 1) {
13425 *lenp = SQL_NULL_DATA;
13426 } else {
13427 *lenp = sizeof (SQLUBIGINT);
13428 }
13429 #else
13430 #ifdef __osf__
13431 *((SQLUBIGINT *) val) = strtoul(*data, &endp, 0);
13432 #else
13433 *((SQLUBIGINT *) val) = strtoull(*data, &endp, 0);
13434 #endif
13435 if (endp && endp == *data) {
13436 *lenp = SQL_NULL_DATA;
13437 } else {
13438 *lenp = sizeof (SQLUBIGINT);
13439 }
13440 #endif
13441 break;
13442 case SQL_C_SBIGINT:
13443 #if defined(_WIN32) || defined(_WIN64)
13444 if (sscanf(*data, "%I64d%c", (SQLBIGINT *) val, &endc) != 1) {
13445 *lenp = SQL_NULL_DATA;
13446 } else {
13447 *lenp = sizeof (SQLBIGINT);
13448 }
13449 #else
13450 #ifdef __osf__
13451 *((SQLBIGINT *) val) = strtol(*data, &endp, 0);
13452 #else
13453 *((SQLBIGINT *) val) = strtoll(*data, &endp, 0);
13454 #endif
13455 if (endp && endp == *data) {
13456 *lenp = SQL_NULL_DATA;
13457 } else {
13458 *lenp = sizeof (SQLBIGINT);
13459 }
13460 #endif
13461 break;
13462 #endif
13463 case SQL_C_FLOAT:
13464 *((float *) val) = ln_strtod(*data, &endp);
13465 if (endp && endp == *data) {
13466 *lenp = SQL_NULL_DATA;
13467 } else {
13468 *lenp = sizeof (float);
13469 }
13470 break;
13471 case SQL_C_DOUBLE:
13472 *((double *) val) = ln_strtod(*data, &endp);
13473 if (endp && endp == *data) {
13474 *lenp = SQL_NULL_DATA;
13475 } else {
13476 *lenp = sizeof (double);
13477 }
13478 break;
13479 case SQL_C_BINARY: {
13480 int dlen, offs = 0;
13481 char *bin;
13482
13483 if (valnull) {
13484 freep(&s->bincache);
13485 s->binlen = 0;
13486 goto doCHAR;
13487 }
13488 if (*data == s->bincell) {
13489 if (s->bincache) {
13490 bin = s->bincache;
13491 dlen = s->binlen;
13492 } else {
13493 goto doCHAR;
13494 }
13495 } else {
13496 char *dp;
13497 int i;
13498
13499 freep(&s->bincache);
13500 dp = *data;
13501 dlen = strlen(dp);
13502 s->bincell = dp;
13503 s->binlen = 0;
13504 if (!(dp[0] == 'x' || dp[0] == 'X') || dp[1] != '\'' ||
13505 dp[dlen - 1] != '\'') {
13506 goto doCHAR;
13507 }
13508 dlen -= 2;
13509 dp += 2;
13510 dlen = dlen / 2;
13511 s->bincache = bin = xmalloc(dlen + 1);
13512 if (!bin) {
13513 return nomem(s);
13514 }
13515 s->binlen = dlen;
13516 memset(bin, 0, dlen);
13517 bin[dlen] = '\0'; /* terminator, just in case */
13518 for (i = 0; i < dlen; i++) {
13519 char *x;
13520 int v;
13521
13522 if (!*dp || !(x = strchr(xdigits, *dp))) {
13523 goto converr;
13524 }
13525 v = x - xdigits;
13526 bin[i] = (v >= 16) ? ((v - 6) << 4) : (v << 4);
13527 ++dp;
13528 if (!*dp || !(x = strchr(xdigits, *dp))) {
13529 converr:
13530 freep(&s->bincache);
13531 s->binlen = 0;
13532 setstat(s, -1, "conversion error",
13533 (*s->ov3) ? "HY000" : "S1000");
13534 return SQL_ERROR;
13535 }
13536 v = x - xdigits;
13537 bin[i] |= (v >= 16) ? (v - 6) : v;
13538 ++dp;
13539 }
13540 bin = s->bincache;
13541 }
13542 if (partial && len && s->bindcols) {
13543 if (s->bindcols[col].offs >= dlen) {
13544 *lenp = 0;
13545 if (!dlen && s->bindcols[col].offs == dlen) {
13546 s->bindcols[col].offs = 1;
13547 sret = SQL_SUCCESS;
13548 goto done;
13549 }
13550 s->bindcols[col].offs = 0;
13551 sret = SQL_NO_DATA;
13552 goto done;
13553 }
13554 offs = s->bindcols[col].offs;
13555 dlen -= offs;
13556 }
13557 if (val && len) {
13558 memcpy(val, bin + offs, min(len, dlen));
13559 }
13560 if (len < 1) {
13561 *lenp = dlen;
13562 } else {
13563 *lenp = min(len, dlen);
13564 if (*lenp == len && *lenp != dlen) {
13565 *lenp = SQL_NO_TOTAL;
13566 }
13567 }
13568 if (partial && len && s->bindcols) {
13569 if (*lenp == SQL_NO_TOTAL) {
13570 *lenp = dlen;
13571 s->bindcols[col].offs += len;
13572 setstat(s, -1, "data right truncated", "01004");
13573 if (s->bindcols[col].lenp) {
13574 *s->bindcols[col].lenp = dlen;
13575 }
13576 sret = SQL_SUCCESS_WITH_INFO;
13577 goto done;
13578 }
13579 s->bindcols[col].offs += *lenp;
13580 }
13581 if (*lenp == SQL_NO_TOTAL) {
13582 *lenp = dlen;
13583 setstat(s, -1, "data right truncated", "01004");
13584 sret = SQL_SUCCESS_WITH_INFO;
13585 goto done;
13586 }
13587 break;
13588 }
13589 doCHAR:
13590 #ifdef WCHARSUPPORT
13591 case SQL_C_WCHAR:
13592 #endif
13593 case SQL_C_CHAR: {
13594 int doz, zlen = len - 1;
13595 int dlen = strlen(*data);
13596 int offs = 0;
13597 #ifdef WCHARSUPPORT
13598 SQLWCHAR *ucdata = NULL;
13599 SQLCHAR *cdata = (SQLCHAR *) *data;
13600 #endif
13601
13602 #if (defined(_WIN32) || defined(_WIN64)) && defined(WINTERFACE)
13603 /* MS Access hack part 2 (reserved error -7748) */
13604 if (!valnull &&
13605 (s->cols == statSpec2P || s->cols == statSpec3P) &&
13606 type == SQL_C_WCHAR) {
13607 if (len > 0 && len <= sizeof (SQLWCHAR)) {
13608 ((char *) val)[0] = data[0][0];
13609 memset((char *) val + 1, 0, len - 1);
13610 *lenp = 1;
13611 sret = SQL_SUCCESS;
13612 goto done;
13613 }
13614 }
13615 #endif
13616
13617 #ifdef WCHARSUPPORT
13618 switch (type) {
13619 case SQL_C_CHAR:
13620 doz = 1;
13621 break;
13622 case SQL_C_WCHAR:
13623 doz = sizeof (SQLWCHAR);
13624 break;
13625 default:
13626 doz = 0;
13627 break;
13628 }
13629 if (type == SQL_C_WCHAR) {
13630 ucdata = uc_from_utf(cdata, dlen);
13631 if (!ucdata) {
13632 return nomem(s);
13633 }
13634 dlen = uc_strlen(ucdata) * sizeof (SQLWCHAR);
13635 }
13636 #if defined(_WIN32) || defined(_WIN64)
13637 else if (*s->oemcp && type == SQL_C_CHAR) {
13638 ucdata = (SQLWCHAR *) utf_to_wmb((char *) cdata, dlen);
13639 if (!ucdata) {
13640 return nomem(s);
13641 }
13642 cdata = (SQLCHAR *) ucdata;
13643 dlen = strlen((char *) cdata);
13644 }
13645 #endif
13646 #else
13647 doz = (type == SQL_C_CHAR) ? 1 : 0;
13648 #endif
13649 if (partial && len && s->bindcols) {
13650 if (s->bindcols[col].offs >= dlen) {
13651 #ifdef WCHARSUPPORT
13652 uc_free(ucdata);
13653 #endif
13654 *lenp = 0;
13655 if (doz && val) {
13656 #ifdef WCHARSUPPORT
13657 if (type == SQL_C_WCHAR) {
13658 ((SQLWCHAR *) val)[0] = 0;
13659 } else {
13660 ((char *) val)[0] = '\0';
13661 }
13662 #else
13663 ((char *) val)[0] = '\0';
13664 #endif
13665 }
13666 if (!dlen && s->bindcols[col].offs == dlen) {
13667 s->bindcols[col].offs = 1;
13668 sret = SQL_SUCCESS;
13669 goto done;
13670 }
13671 s->bindcols[col].offs = 0;
13672 sret = SQL_NO_DATA;
13673 goto done;
13674 }
13675 offs = s->bindcols[col].offs;
13676 dlen -= offs;
13677 }
13678 if (val && !valnull && len) {
13679 #ifdef WCHARSUPPORT
13680 if (type == SQL_C_WCHAR) {
13681 uc_strncpy(val, ucdata + offs / sizeof (SQLWCHAR),
13682 (len - doz) / sizeof (SQLWCHAR));
13683 } else {
13684 strncpy(val, (char *) cdata + offs, len - doz);
13685 }
13686 #else
13687 strncpy(val, *data + offs, len - doz);
13688 #endif
13689 }
13690 if (valnull || len < 1) {
13691 *lenp = dlen;
13692 } else {
13693 *lenp = min(len - doz, dlen);
13694 if (*lenp == len - doz && *lenp != dlen) {
13695 *lenp = SQL_NO_TOTAL;
13696 } else if (*lenp < zlen) {
13697 zlen = *lenp;
13698 }
13699 }
13700 if (len && !valnull && doz) {
13701 #ifdef WCHARSUPPORT
13702 if (type == SQL_C_WCHAR) {
13703 ((SQLWCHAR *) val)[zlen / sizeof (SQLWCHAR)] = 0;
13704 } else {
13705 ((char *) val)[zlen] = '\0';
13706 }
13707 #else
13708 ((char *) val)[zlen] = '\0';
13709 #endif
13710 }
13711 #ifdef WCHARSUPPORT
13712 uc_free(ucdata);
13713 #endif
13714 if (partial && len && s->bindcols) {
13715 if (*lenp == SQL_NO_TOTAL) {
13716 *lenp = dlen;
13717 s->bindcols[col].offs += len - doz;
13718 setstat(s, -1, "data right truncated", "01004");
13719 if (s->bindcols[col].lenp) {
13720 *s->bindcols[col].lenp = dlen;
13721 }
13722 sret = SQL_SUCCESS_WITH_INFO;
13723 goto done;
13724 }
13725 s->bindcols[col].offs += *lenp;
13726 }
13727 if (*lenp == SQL_NO_TOTAL) {
13728 *lenp = dlen;
13729 setstat(s, -1, "data right truncated", "01004");
13730 sret = SQL_SUCCESS_WITH_INFO;
13731 goto done;
13732 }
13733 break;
13734 }
13735 #ifdef SQL_C_TYPE_DATE
13736 case SQL_C_TYPE_DATE:
13737 #endif
13738 case SQL_C_DATE:
13739 if (str2date(*data, (DATE_STRUCT *) val) < 0) {
13740 *lenp = SQL_NULL_DATA;
13741 } else {
13742 *lenp = sizeof (DATE_STRUCT);
13743 }
13744 break;
13745 #ifdef SQL_C_TYPE_TIME
13746 case SQL_C_TYPE_TIME:
13747 #endif
13748 case SQL_C_TIME:
13749 if (str2time(*data, (TIME_STRUCT *) val) < 0) {
13750 *lenp = SQL_NULL_DATA;
13751 } else {
13752 *lenp = sizeof (TIME_STRUCT);
13753 }
13754 break;
13755 #ifdef SQL_C_TYPE_TIMESTAMP
13756 case SQL_C_TYPE_TIMESTAMP:
13757 #endif
13758 case SQL_C_TIMESTAMP:
13759 if (str2timestamp(*data, (TIMESTAMP_STRUCT *) val) < 0) {
13760 *lenp = SQL_NULL_DATA;
13761 } else {
13762 *lenp = sizeof (TIMESTAMP_STRUCT);
13763 }
13764 switch (s->cols[col].prec) {
13765 case 0:
13766 ((TIMESTAMP_STRUCT *) val)->fraction = 0;
13767 break;
13768 case 1:
13769 ((TIMESTAMP_STRUCT *) val)->fraction /= 100000000;
13770 ((TIMESTAMP_STRUCT *) val)->fraction *= 100000000;
13771 break;
13772 case 2:
13773 ((TIMESTAMP_STRUCT *) val)->fraction /= 10000000;
13774 ((TIMESTAMP_STRUCT *) val)->fraction *= 10000000;
13775 break;
13776 }
13777 break;
13778 default:
13779 return SQL_ERROR;
13780 }
13781 }
13782 sret = SQL_SUCCESS;
13783 done:
13784 if (ilenp) {
13785 *ilenp = *lenp;
13786 }
13787 return sret;
13788 }
13789
13790 /**
13791 * Interal bind C variable to column of result set.
13792 * @param stmt statement handle
13793 * @param col column number, starting at 1
13794 * @param type output type
13795 * @param val output buffer
13796 * @param max length of output buffer
13797 * @param lenp output length pointer
13798 * @result ODBC error code
13799 */
13800
13801 static SQLRETURN
drvbindcol(SQLHSTMT stmt,SQLUSMALLINT col,SQLSMALLINT type,SQLPOINTER val,SQLLEN max,SQLLEN * lenp)13802 drvbindcol(SQLHSTMT stmt, SQLUSMALLINT col, SQLSMALLINT type,
13803 SQLPOINTER val, SQLLEN max, SQLLEN *lenp)
13804 {
13805 STMT *s;
13806 int sz = 0;
13807
13808 if (stmt == SQL_NULL_HSTMT) {
13809 return SQL_INVALID_HANDLE;
13810 }
13811 s = (STMT *) stmt;
13812 if (col < 1) {
13813 if (col == 0 && s->bkmrk == SQL_UB_ON &&
13814 type == SQL_C_BOOKMARK) {
13815 s->bkmrkcol.type = val ? type : SQL_UNKNOWN_TYPE;
13816 s->bkmrkcol.max = val ? sizeof (SQLINTEGER) : 0;
13817 s->bkmrkcol.lenp = val ? lenp : 0;
13818 s->bkmrkcol.valp = val;
13819 s->bkmrkcol.offs = 0;
13820 if (val && lenp) {
13821 *lenp = 0;
13822 }
13823 return SQL_SUCCESS;
13824 } else if (col == 0 && s->bkmrk == SQL_UB_VARIABLE &&
13825 type == SQL_C_VARBOOKMARK &&
13826 max >= sizeof (sqlite4_int64)) {
13827 s->bkmrkcol.type = val ? type : SQL_UNKNOWN_TYPE;
13828 s->bkmrkcol.max = val ? max : 0;
13829 s->bkmrkcol.lenp = val ? lenp : 0;
13830 s->bkmrkcol.valp = val;
13831 s->bkmrkcol.offs = 0;
13832 if (val && lenp) {
13833 *lenp = 0;
13834 }
13835 return SQL_SUCCESS;
13836 }
13837 setstat(s, -1, "invalid column", (*s->ov3) ? "07009" : "S1002");
13838 return SQL_ERROR;
13839 }
13840 if (mkbindcols(s, col) != SQL_SUCCESS) {
13841 return SQL_ERROR;
13842 }
13843 --col;
13844 if (type == SQL_C_DEFAULT) {
13845 type = mapdeftype(type, s->cols[col].type, 0,
13846 s->nowchar[0] || s->nowchar[1]);
13847 }
13848 switch (type) {
13849 case SQL_C_LONG:
13850 case SQL_C_ULONG:
13851 case SQL_C_SLONG:
13852 sz = sizeof (SQLINTEGER);
13853 break;
13854 case SQL_C_TINYINT:
13855 case SQL_C_UTINYINT:
13856 case SQL_C_STINYINT:
13857 sz = sizeof (SQLCHAR);
13858 break;
13859 case SQL_C_SHORT:
13860 case SQL_C_USHORT:
13861 case SQL_C_SSHORT:
13862 sz = sizeof (SQLSMALLINT);
13863 break;
13864 case SQL_C_FLOAT:
13865 sz = sizeof (SQLFLOAT);
13866 break;
13867 case SQL_C_DOUBLE:
13868 sz = sizeof (SQLDOUBLE);
13869 break;
13870 case SQL_C_TIMESTAMP:
13871 sz = sizeof (SQL_TIMESTAMP_STRUCT);
13872 break;
13873 case SQL_C_TIME:
13874 sz = sizeof (SQL_TIME_STRUCT);
13875 break;
13876 case SQL_C_DATE:
13877 sz = sizeof (SQL_DATE_STRUCT);
13878 break;
13879 case SQL_C_CHAR:
13880 break;
13881 #ifdef WCHARSUPPORT
13882 case SQL_C_WCHAR:
13883 break;
13884 #endif
13885 #ifdef SQL_C_TYPE_DATE
13886 case SQL_C_TYPE_DATE:
13887 sz = sizeof (SQL_DATE_STRUCT);
13888 break;
13889 #endif
13890 #ifdef SQL_C_TYPE_TIME
13891 case SQL_C_TYPE_TIME:
13892 sz = sizeof (SQL_TIME_STRUCT);
13893 break;
13894 #endif
13895 #ifdef SQL_C_TYPE_TIMESTAMP
13896 case SQL_C_TYPE_TIMESTAMP:
13897 sz = sizeof (SQL_TIMESTAMP_STRUCT);
13898 break;
13899 #endif
13900 #ifdef SQL_BIT
13901 case SQL_C_BIT:
13902 sz = sizeof (SQLCHAR);
13903 break;
13904 #endif
13905 case SQL_C_BINARY:
13906 break;
13907 #ifdef SQL_BIGINT
13908 case SQL_C_SBIGINT:
13909 case SQL_C_UBIGINT:
13910 sz = sizeof (SQLBIGINT);
13911 break;
13912 #endif
13913 default:
13914 if (val == NULL) {
13915 /* fall through, unbinding column */
13916 break;
13917 }
13918 setstat(s, -1, "invalid type %d", "HY003", type);
13919 return SQL_ERROR;
13920 }
13921 if (val == NULL) {
13922 /* unbind column */
13923 s->bindcols[col].type = SQL_UNKNOWN_TYPE;
13924 s->bindcols[col].max = 0;
13925 s->bindcols[col].lenp = NULL;
13926 s->bindcols[col].valp = NULL;
13927 s->bindcols[col].offs = 0;
13928 } else {
13929 if (sz == 0 && max < 0) {
13930 setstat(s, -1, "invalid length", "HY090");
13931 return SQL_ERROR;
13932 }
13933 s->bindcols[col].type = type;
13934 s->bindcols[col].max = (sz == 0) ? max : sz;
13935 s->bindcols[col].lenp = lenp;
13936 s->bindcols[col].valp = val;
13937 s->bindcols[col].offs = 0;
13938 if (lenp) {
13939 *lenp = 0;
13940 }
13941 }
13942 return SQL_SUCCESS;
13943 }
13944
13945 /**
13946 * Bind C variable to column of result set.
13947 * @param stmt statement handle
13948 * @param col column number, starting at 1
13949 * @param type output type
13950 * @param val output buffer
13951 * @param max length of output buffer
13952 * @param lenp output length pointer
13953 * @result ODBC error code
13954 */
13955
13956 SQLRETURN SQL_API
SQLBindCol(SQLHSTMT stmt,SQLUSMALLINT col,SQLSMALLINT type,SQLPOINTER val,SQLLEN max,SQLLEN * lenp)13957 SQLBindCol(SQLHSTMT stmt, SQLUSMALLINT col, SQLSMALLINT type,
13958 SQLPOINTER val, SQLLEN max, SQLLEN *lenp)
13959 {
13960 SQLRETURN ret;
13961
13962 HSTMT_LOCK(stmt);
13963 ret = drvbindcol(stmt, col, type, val, max, lenp);
13964 HSTMT_UNLOCK(stmt);
13965 return ret;
13966 }
13967
13968 /**
13969 * Columns for result set of SQLTables().
13970 */
13971
13972 static COL tableSpec2[] = {
13973 { "SYSTEM", "COLUMN", "TABLE_QUALIFIER", SCOL_VARCHAR, 50 },
13974 { "SYSTEM", "COLUMN", "TABLE_OWNER", SCOL_VARCHAR, 50 },
13975 { "SYSTEM", "COLUMN", "TABLE_NAME", SCOL_VARCHAR, 255 },
13976 { "SYSTEM", "COLUMN", "TABLE_TYPE", SCOL_VARCHAR, 50 },
13977 { "SYSTEM", "COLUMN", "REMARKS", SCOL_VARCHAR, 50 }
13978 };
13979
13980 static COL tableSpec3[] = {
13981 { "SYSTEM", "COLUMN", "TABLE_CAT", SCOL_VARCHAR, 50 },
13982 { "SYSTEM", "COLUMN", "TABLE_SCHEM", SCOL_VARCHAR, 50 },
13983 { "SYSTEM", "COLUMN", "TABLE_NAME", SCOL_VARCHAR, 255 },
13984 { "SYSTEM", "COLUMN", "TABLE_TYPE", SCOL_VARCHAR, 50 },
13985 { "SYSTEM", "COLUMN", "REMARKS", SCOL_VARCHAR, 50 }
13986 };
13987
13988 /**
13989 * Retrieve information on tables and/or views.
13990 * @param stmt statement handle
13991 * @param cat catalog name/pattern or NULL
13992 * @param catLen length of catalog name/pattern or SQL_NTS
13993 * @param schema schema name/pattern or NULL
13994 * @param schemaLen length of schema name/pattern or SQL_NTS
13995 * @param table table name/pattern or NULL
13996 * @param tableLen length of table name/pattern or SQL_NTS
13997 * @param type types of tables string or NULL
13998 * @param typeLen length of types of tables string or SQL_NTS
13999 * @result ODBC error code
14000 */
14001
14002 static SQLRETURN
drvtables(SQLHSTMT stmt,SQLCHAR * cat,SQLSMALLINT catLen,SQLCHAR * schema,SQLSMALLINT schemaLen,SQLCHAR * table,SQLSMALLINT tableLen,SQLCHAR * type,SQLSMALLINT typeLen)14003 drvtables(SQLHSTMT stmt,
14004 SQLCHAR *cat, SQLSMALLINT catLen,
14005 SQLCHAR *schema, SQLSMALLINT schemaLen,
14006 SQLCHAR *table, SQLSMALLINT tableLen,
14007 SQLCHAR *type, SQLSMALLINT typeLen)
14008 {
14009 SQLRETURN ret;
14010 STMT *s;
14011 DBC *d;
14012 int ncols, asize, rc, size, npatt;
14013 char *errp = NULL, *sql, tname[512];
14014 char *where = "(type = 'table' or type = 'view')";
14015
14016 ret = mkresultset(stmt, tableSpec2, array_size(tableSpec2),
14017 tableSpec3, array_size(tableSpec3), &asize);
14018 if (ret != SQL_SUCCESS) {
14019 return ret;
14020 }
14021 s = (STMT *) stmt;
14022 d = (DBC *) s->dbc;
14023 if (type && (typeLen > 0 || typeLen == SQL_NTS) && type[0] == '%') {
14024 int size = 3 * asize;
14025
14026 s->rows = xmalloc(size * sizeof (char *));
14027 if (!s->rows) {
14028 s->nrows = 0;
14029 return nomem(s);
14030 }
14031 memset(s->rows, 0, sizeof (char *) * size);
14032 s->ncols = asize;
14033 s->rows[s->ncols + 0] = "";
14034 s->rows[s->ncols + 1] = "";
14035 s->rows[s->ncols + 2] = "";
14036 s->rows[s->ncols + 3] = "TABLE";
14037 s->rows[s->ncols + 5] = "";
14038 s->rows[s->ncols + 6] = "";
14039 s->rows[s->ncols + 7] = "";
14040 s->rows[s->ncols + 8] = "VIEW";
14041 #ifdef MEMORY_DEBUG
14042 s->rowfree = xfree__;
14043 #else
14044 s->rowfree = sqlite4_free;
14045 #endif
14046 s->nrows = 2;
14047 s->rowp = s->rowprs = -1;
14048 return SQL_SUCCESS;
14049 }
14050 if (cat && (catLen > 0 || catLen == SQL_NTS) && cat[0] == '%') {
14051 table = NULL;
14052 goto doit;
14053 }
14054 if (schema && (schemaLen > 0 || schemaLen == SQL_NTS) &&
14055 schema[0] == '%') {
14056 if ((!cat || catLen == 0 || !cat[0]) &&
14057 (!table || tableLen == 0 || !table[0])) {
14058 table = NULL;
14059 goto doit;
14060 }
14061 }
14062 if (type && (typeLen > 0 || typeLen == SQL_NTS) && type[0] != '\0') {
14063 char tmp[256], *t;
14064 int with_view = 0, with_table = 0;
14065
14066 if (typeLen == SQL_NTS) {
14067 strncpy(tmp, (char *) type, sizeof (tmp));
14068 tmp[sizeof (tmp) - 1] = '\0';
14069 } else {
14070 int len = min(sizeof (tmp) - 1, typeLen);
14071
14072 strncpy(tmp, (char *) type, len);
14073 tmp[len] = '\0';
14074 }
14075 t = tmp;
14076 while (*t) {
14077 *t = TOLOWER(*t);
14078 t++;
14079 }
14080 t = tmp;
14081 unescpat(t);
14082 while (t) {
14083 if (t[0] == '\'') {
14084 ++t;
14085 }
14086 if (strncmp(t, "table", 5) == 0) {
14087 with_table++;
14088 } else if (strncmp(t, "view", 4) == 0) {
14089 with_view++;
14090 }
14091 t = strchr(t, ',');
14092 if (t) {
14093 ++t;
14094 }
14095 }
14096 if (with_view && with_table) {
14097 /* where is already preset */
14098 } else if (with_view && !with_table) {
14099 where = "type = 'view'";
14100 } else if (!with_view && with_table) {
14101 where = "type = 'table'";
14102 } else {
14103 return SQL_SUCCESS;
14104 }
14105 }
14106 doit:
14107 if (!table) {
14108 size = 1;
14109 tname[0] = '%';
14110 } else {
14111 if (tableLen == SQL_NTS) {
14112 size = sizeof (tname) - 1;
14113 } else {
14114 size = min(sizeof (tname) - 1, tableLen);
14115 }
14116 strncpy(tname, (char *) table, size);
14117 }
14118 tname[size] = '\0';
14119 npatt = unescpat(tname);
14120 #if defined(_WIN32) || defined(_WIN64)
14121 if (npatt) {
14122 sql = sqlite4_mprintf(0, "select %s as 'TABLE_QUALIFIER', "
14123 "%s as 'TABLE_OWNER', "
14124 "tbl_name as 'TABLE_NAME', "
14125 "upper(type) as 'TABLE_TYPE', "
14126 "NULL as 'REMARKS' "
14127 "from sqlite_master where %s "
14128 "and tbl_name like %Q",
14129 d->xcelqrx ? "'main'" : "NULL",
14130 d->xcelqrx ? "''" : "NULL",
14131 where, tname);
14132 } else {
14133 sql = sqlite4_mprintf(0, "select %s as 'TABLE_QUALIFIER', "
14134 "%s as 'TABLE_OWNER', "
14135 "tbl_name as 'TABLE_NAME', "
14136 "upper(type) as 'TABLE_TYPE', "
14137 "NULL as 'REMARKS' "
14138 "from sqlite_master where %s "
14139 "and lower(tbl_name) = lower(%Q)",
14140 d->xcelqrx ? "'main'" : "NULL",
14141 d->xcelqrx ? "''" : "NULL",
14142 where, tname);
14143 }
14144 #else
14145 if (npatt) {
14146 sql = sqlite4_mprintf(0, "select NULL as 'TABLE_QUALIFIER', "
14147 "NULL as 'TABLE_OWNER', "
14148 "tbl_name as 'TABLE_NAME', "
14149 "upper(type) as 'TABLE_TYPE', "
14150 "NULL as 'REMARKS' "
14151 "from sqlite_master where %s "
14152 "and tbl_name like %Q", where, tname);
14153 } else {
14154 sql = sqlite4_mprintf(0, "select NULL as 'TABLE_QUALIFIER', "
14155 "NULL as 'TABLE_OWNER', "
14156 "tbl_name as 'TABLE_NAME', "
14157 "upper(type) as 'TABLE_TYPE', "
14158 "NULL as 'REMARKS' "
14159 "from sqlite_master where %s "
14160 "and lower(tbl_name) = lower(%Q)", where, tname);
14161 }
14162 #endif
14163 if (!sql) {
14164 return nomem(s);
14165 }
14166 ret = starttran(s);
14167 if (ret != SQL_SUCCESS) {
14168 sqlite4_free(0, sql);
14169 return ret;
14170 }
14171 dbtraceapi(d, "sqlite4_get_table", sql);
14172 rc = sqlite4_get_table(d->sqlite, sql, &s->rows, &s->nrows, &ncols, &errp);
14173 sqlite4_free(0, sql);
14174 if (rc == SQLITE4_OK) {
14175 if (ncols != s->ncols) {
14176 freeresult(s, 0);
14177 s->nrows = 0;
14178 } else {
14179 s->rowfree = freerows;
14180 }
14181 } else {
14182 s->nrows = 0;
14183 s->rows = NULL;
14184 s->rowfree = NULL;
14185 }
14186 if (errp) {
14187 sqlite4_free(0, errp);
14188 errp = NULL;
14189 }
14190 s->rowp = s->rowprs = -1;
14191 return SQL_SUCCESS;
14192 }
14193
14194 #ifndef WINTERFACE
14195 /**
14196 * Retrieve information on tables and/or views.
14197 * @param stmt statement handle
14198 * @param cat catalog name/pattern or NULL
14199 * @param catLen length of catalog name/pattern or SQL_NTS
14200 * @param schema schema name/pattern or NULL
14201 * @param schemaLen length of schema name/pattern or SQL_NTS
14202 * @param table table name/pattern or NULL
14203 * @param tableLen length of table name/pattern or SQL_NTS
14204 * @param type types of tables string or NULL
14205 * @param typeLen length of types of tables string or SQL_NTS
14206 * @result ODBC error code
14207 */
14208
14209 SQLRETURN SQL_API
SQLTables(SQLHSTMT stmt,SQLCHAR * cat,SQLSMALLINT catLen,SQLCHAR * schema,SQLSMALLINT schemaLen,SQLCHAR * table,SQLSMALLINT tableLen,SQLCHAR * type,SQLSMALLINT typeLen)14210 SQLTables(SQLHSTMT stmt,
14211 SQLCHAR *cat, SQLSMALLINT catLen,
14212 SQLCHAR *schema, SQLSMALLINT schemaLen,
14213 SQLCHAR *table, SQLSMALLINT tableLen,
14214 SQLCHAR *type, SQLSMALLINT typeLen)
14215 {
14216 #if defined(_WIN32) || defined(_WIN64)
14217 char *c = NULL, *s = NULL, *t = NULL, *y = NULL;
14218 #endif
14219 SQLRETURN ret;
14220
14221 HSTMT_LOCK(stmt);
14222 #if defined(_WIN32) || defined(_WIN64)
14223 if (!((STMT *) stmt)->oemcp[0]) {
14224 ret = drvtables(stmt, cat, catLen, schema, schemaLen,
14225 table, tableLen, type, typeLen);
14226 goto done2;
14227 }
14228 if (cat) {
14229 c = wmb_to_utf_c((char *) cat, catLen);
14230 if (!c) {
14231 ret = nomem((STMT *) stmt);
14232 goto done;
14233 }
14234 }
14235 if (schema) {
14236 s = wmb_to_utf_c((char *) schema, schemaLen);
14237 if (!s) {
14238 ret = nomem((STMT *) stmt);
14239 goto done;
14240 }
14241 }
14242 if (table) {
14243 t = wmb_to_utf_c((char *) table, tableLen);
14244 if (!t) {
14245 ret = nomem((STMT *) stmt);
14246 goto done;
14247 }
14248 }
14249 if (type) {
14250 y = wmb_to_utf_c((char *) type, typeLen);
14251 if (!y) {
14252 ret = nomem((STMT *) stmt);
14253 goto done;
14254 }
14255 }
14256 ret = drvtables(stmt, (SQLCHAR *) c, SQL_NTS, (SQLCHAR *) s, SQL_NTS,
14257 (SQLCHAR *) t, SQL_NTS, (SQLCHAR *) y, SQL_NTS);
14258 #else
14259 ret = drvtables(stmt, cat, catLen, schema, schemaLen,
14260 table, tableLen, type, typeLen);
14261 #endif
14262 #if defined(_WIN32) || defined(_WIN64)
14263 done:
14264 uc_free(y);
14265 uc_free(t);
14266 uc_free(s);
14267 uc_free(c);
14268 done2:
14269 ;
14270 #endif
14271 HSTMT_UNLOCK(stmt);
14272 return ret;
14273 }
14274 #endif
14275
14276 #ifdef WINTERFACE
14277 /**
14278 * Retrieve information on tables and/or views.
14279 * @param stmt statement handle
14280 * @param cat catalog name/pattern or NULL
14281 * @param catLen length of catalog name/pattern or SQL_NTS
14282 * @param schema schema name/pattern or NULL
14283 * @param schemaLen length of schema name/pattern or SQL_NTS
14284 * @param table table name/pattern or NULL
14285 * @param tableLen length of table name/pattern or SQL_NTS
14286 * @param type types of tables string or NULL
14287 * @param typeLen length of types of tables string or SQL_NTS
14288 * @result ODBC error code
14289 */
14290
14291 SQLRETURN SQL_API
SQLTablesW(SQLHSTMT stmt,SQLWCHAR * cat,SQLSMALLINT catLen,SQLWCHAR * schema,SQLSMALLINT schemaLen,SQLWCHAR * table,SQLSMALLINT tableLen,SQLWCHAR * type,SQLSMALLINT typeLen)14292 SQLTablesW(SQLHSTMT stmt,
14293 SQLWCHAR *cat, SQLSMALLINT catLen,
14294 SQLWCHAR *schema, SQLSMALLINT schemaLen,
14295 SQLWCHAR *table, SQLSMALLINT tableLen,
14296 SQLWCHAR *type, SQLSMALLINT typeLen)
14297 {
14298 char *c = NULL, *s = NULL, *t = NULL, *y = NULL;
14299 SQLRETURN ret;
14300
14301 HSTMT_LOCK(stmt);
14302 if (cat) {
14303 c = uc_to_utf_c(cat, catLen);
14304 if (!c) {
14305 ret = nomem((STMT *) stmt);
14306 goto done;
14307 }
14308 }
14309 if (schema) {
14310 s = uc_to_utf_c(schema, schemaLen);
14311 if (!s) {
14312 ret = nomem((STMT *) stmt);
14313 goto done;
14314 }
14315 }
14316 if (table) {
14317 t = uc_to_utf_c(table, tableLen);
14318 if (!t) {
14319 ret = nomem((STMT *) stmt);
14320 goto done;
14321 }
14322 }
14323 if (type) {
14324 y = uc_to_utf_c(type, typeLen);
14325 if (!y) {
14326 ret = nomem((STMT *) stmt);
14327 goto done;
14328 }
14329 }
14330 ret = drvtables(stmt, (SQLCHAR *) c, SQL_NTS, (SQLCHAR *) s, SQL_NTS,
14331 (SQLCHAR *) t, SQL_NTS, (SQLCHAR *) y, SQL_NTS);
14332 done:
14333 uc_free(y);
14334 uc_free(t);
14335 uc_free(s);
14336 uc_free(c);
14337 HSTMT_UNLOCK(stmt);
14338 return ret;
14339 }
14340 #endif
14341
14342 /**
14343 * Columns for result set of SQLColumns().
14344 */
14345
14346 static COL colSpec2[] = {
14347 { "SYSTEM", "COLUMN", "TABLE_QUALIFIER", SCOL_VARCHAR, 50 },
14348 { "SYSTEM", "COLUMN", "TABLE_OWNER", SCOL_VARCHAR, 50 },
14349 { "SYSTEM", "COLUMN", "TABLE_NAME", SCOL_VARCHAR, 255 },
14350 { "SYSTEM", "COLUMN", "COLUMN_NAME", SCOL_VARCHAR, 255 },
14351 { "SYSTEM", "COLUMN", "DATA_TYPE", SQL_SMALLINT, 50 },
14352 { "SYSTEM", "COLUMN", "TYPE_NAME", SCOL_VARCHAR, 50 },
14353 { "SYSTEM", "COLUMN", "PRECISION", SQL_INTEGER, 50 },
14354 { "SYSTEM", "COLUMN", "LENGTH", SQL_INTEGER, 50 },
14355 { "SYSTEM", "COLUMN", "SCALE", SQL_SMALLINT, 50 },
14356 { "SYSTEM", "COLUMN", "RADIX", SQL_SMALLINT, 50 },
14357 { "SYSTEM", "COLUMN", "NULLABLE", SQL_SMALLINT, 50 },
14358 { "SYSTEM", "COLUMN", "REMARKS", SCOL_VARCHAR, 50 },
14359 { "SYSTEM", "COLUMN", "COLUMN_DEF", SCOL_VARCHAR, 50 },
14360 { "SYSTEM", "COLUMN", "SQL_DATA_TYPE", SQL_SMALLINT, 50 },
14361 { "SYSTEM", "COLUMN", "SQL_DATETIME_SUB", SQL_SMALLINT, 50 },
14362 { "SYSTEM", "COLUMN", "CHAR_OCTET_LENGTH", SQL_SMALLINT, 50 },
14363 { "SYSTEM", "COLUMN", "ORDINAL_POSITION", SQL_SMALLINT, 50 },
14364 { "SYSTEM", "COLUMN", "IS_NULLABLE", SCOL_VARCHAR, 50 }
14365 };
14366
14367 static COL colSpec3[] = {
14368 { "SYSTEM", "COLUMN", "TABLE_CAT", SCOL_VARCHAR, 50 },
14369 { "SYSTEM", "COLUMN", "TABLE_SCHEM", SCOL_VARCHAR, 50 },
14370 { "SYSTEM", "COLUMN", "TABLE_NAME", SCOL_VARCHAR, 255 },
14371 { "SYSTEM", "COLUMN", "COLUMN_NAME", SCOL_VARCHAR, 255 },
14372 { "SYSTEM", "COLUMN", "DATA_TYPE", SQL_SMALLINT, 50 },
14373 { "SYSTEM", "COLUMN", "TYPE_NAME", SCOL_VARCHAR, 50 },
14374 { "SYSTEM", "COLUMN", "COLUMN_SIZE", SQL_INTEGER, 50 },
14375 { "SYSTEM", "COLUMN", "BUFFER_LENGTH", SQL_INTEGER, 50 },
14376 { "SYSTEM", "COLUMN", "DECIMAL_DIGITS", SQL_SMALLINT, 50 },
14377 { "SYSTEM", "COLUMN", "NUM_PREC_RADIX", SQL_SMALLINT, 50 },
14378 { "SYSTEM", "COLUMN", "NULLABLE", SQL_SMALLINT, 50 },
14379 { "SYSTEM", "COLUMN", "REMARKS", SCOL_VARCHAR, 50 },
14380 { "SYSTEM", "COLUMN", "COLUMN_DEF", SCOL_VARCHAR, 50 },
14381 { "SYSTEM", "COLUMN", "SQL_DATA_TYPE", SQL_SMALLINT, 50 },
14382 { "SYSTEM", "COLUMN", "SQL_DATETIME_SUB", SQL_SMALLINT, 50 },
14383 { "SYSTEM", "COLUMN", "CHAR_OCTET_LENGTH", SQL_SMALLINT, 50 },
14384 { "SYSTEM", "COLUMN", "ORDINAL_POSITION", SQL_SMALLINT, 50 },
14385 { "SYSTEM", "COLUMN", "IS_NULLABLE", SCOL_VARCHAR, 50 }
14386 };
14387
14388 /**
14389 * Internal retrieve column information on table.
14390 * @param stmt statement handle
14391 * @param cat catalog name/pattern or NULL
14392 * @param catLen length of catalog name/pattern or SQL_NTS
14393 * @param schema schema name/pattern or NULL
14394 * @param schemaLen length of schema name/pattern or SQL_NTS
14395 * @param table table name/pattern or NULL
14396 * @param tableLen length of table name/pattern or SQL_NTS
14397 * @param col column name/pattern or NULL
14398 * @param colLen length of column name/pattern or SQL_NTS
14399 * @result ODBC error code
14400 */
14401
14402 static SQLRETURN
drvcolumns(SQLHSTMT stmt,SQLCHAR * cat,SQLSMALLINT catLen,SQLCHAR * schema,SQLSMALLINT schemaLen,SQLCHAR * table,SQLSMALLINT tableLen,SQLCHAR * col,SQLSMALLINT colLen)14403 drvcolumns(SQLHSTMT stmt,
14404 SQLCHAR *cat, SQLSMALLINT catLen,
14405 SQLCHAR *schema, SQLSMALLINT schemaLen,
14406 SQLCHAR *table, SQLSMALLINT tableLen,
14407 SQLCHAR *col, SQLSMALLINT colLen)
14408 {
14409 SQLRETURN sret;
14410 STMT *s;
14411 DBC *d;
14412 int ret, nrows, ncols, asize, i, k, roffs, namec;
14413 int tnrows, tncols, npatt;
14414 PTRDIFF_T size;
14415 char *errp = NULL, *sql, tname[512], cname[512], **rowp, **trows;
14416
14417 sret = mkresultset(stmt, colSpec2, array_size(colSpec2),
14418 colSpec3, array_size(colSpec3), &asize);
14419 if (sret != SQL_SUCCESS) {
14420 return sret;
14421 }
14422 s = (STMT *) stmt;
14423 d = (DBC *) s->dbc;
14424 if (!table) {
14425 size = 1;
14426 tname[0] = '%';
14427 } else {
14428 if (tableLen == SQL_NTS) {
14429 size = sizeof (tname) - 1;
14430 } else {
14431 size = min(sizeof (tname) - 1, tableLen);
14432 }
14433 strncpy(tname, (char *) table, size);
14434 }
14435 tname[size] = '\0';
14436 npatt = unescpat(tname);
14437 size = 0;
14438 if (col) {
14439 if (colLen == SQL_NTS) {
14440 size = sizeof (cname) - 1;
14441 } else {
14442 size = min(sizeof (cname) - 1, colLen);
14443 }
14444 strncpy(cname, (char *) col, size);
14445 }
14446 cname[size] = '\0';
14447 if (!strcmp(cname, "%")) {
14448 cname[0] = '\0';
14449 }
14450 if (npatt) {
14451 sql = sqlite4_mprintf(0, "select tbl_name from sqlite_master where "
14452 "(type = 'table' or type = 'view') "
14453 "and tbl_name like %Q", tname);
14454 } else {
14455 sql = sqlite4_mprintf(0, "select tbl_name from sqlite_master where "
14456 "(type = 'table' or type = 'view') "
14457 "and lower(tbl_name) = lower(%Q)", tname);
14458 }
14459 if (!sql) {
14460 return nomem(s);
14461 }
14462 sret = starttran(s);
14463 if (sret != SQL_SUCCESS) {
14464 sqlite4_free(0, sql);
14465 return sret;
14466 }
14467 dbtraceapi(d, "sqlite4_get_table", sql);
14468 ret = sqlite4_get_table(d->sqlite, sql, &trows, &tnrows, &tncols, &errp);
14469 sqlite4_free(0, sql);
14470 if (ret != SQLITE4_OK) {
14471 setstat(s, ret, "%s (%d)", (*s->ov3) ? "HY000" : "S1000",
14472 errp ? errp : "unknown error", ret);
14473 if (errp) {
14474 sqlite4_free(0, errp);
14475 errp = NULL;
14476 }
14477 return SQL_ERROR;
14478 }
14479 if (errp) {
14480 sqlite4_free(0, errp);
14481 errp = NULL;
14482 }
14483 /* pass 1: compute number of rows of result set */
14484 if (tncols * tnrows <= 0) {
14485 freerows(trows);
14486 return SQL_SUCCESS;
14487 }
14488 size = 0;
14489 for (i = 1; i <= tnrows; i++) {
14490 sql = sqlite4_mprintf(0, "PRAGMA table_info(%Q)", trows[i]);
14491 if (!sql) {
14492 freerows(trows);
14493 return nomem(s);
14494 }
14495 dbtraceapi(d, "sqlite4_get_table", sql);
14496 ret = sqlite4_get_table(d->sqlite, sql, &rowp, &nrows, &ncols, &errp);
14497 sqlite4_free(0, sql);
14498 if (ret != SQLITE4_OK) {
14499 setstat(s, ret, "%s (%d)", (*s->ov3) ? "HY000" : "S1000",
14500 errp ? errp : "unknown error", ret);
14501 if (errp) {
14502 sqlite4_free(0, errp);
14503 errp = NULL;
14504 }
14505 freerows(trows);
14506 return SQL_ERROR;
14507 }
14508 if (errp) {
14509 sqlite4_free(0, errp);
14510 errp = NULL;
14511 }
14512 if (ncols * nrows > 0) {
14513 namec = -1;
14514 for (k = 0; k < ncols; k++) {
14515 if (strcmp(rowp[k], "name") == 0) {
14516 namec = k;
14517 break;
14518 }
14519 }
14520 if (cname[0]) {
14521 if (namec >= 0) {
14522 for (k = 1; k <= nrows; k++) {
14523 if (namematch(rowp[k * ncols + namec], cname, 1)) {
14524 size++;
14525 }
14526 }
14527 }
14528 } else {
14529 size += nrows;
14530 }
14531 }
14532 freerows(rowp);
14533 }
14534 /* pass 2: fill result set */
14535 if (size <= 0) {
14536 freerows(trows);
14537 return SQL_SUCCESS;
14538 }
14539 s->nrows = size;
14540 size = (size + 1) * asize;
14541 s->rows = xmalloc((size + 1) * sizeof (char *));
14542 if (!s->rows) {
14543 s->nrows = 0;
14544 freerows(trows);
14545 return nomem(s);
14546 }
14547 s->rows[0] = (char *) size;
14548 s->rows += 1;
14549 memset(s->rows, 0, sizeof (char *) * size);
14550 s->rowfree = freerows;
14551 roffs = 1;
14552 for (i = 1; i <= tnrows; i++) {
14553 sql = sqlite4_mprintf(0, "PRAGMA table_info(%Q)", trows[i]);
14554 if (!sql) {
14555 freerows(trows);
14556 return nomem(s);
14557 }
14558 dbtraceapi(d, "sqlite4_get_table", sql);
14559 ret = sqlite4_get_table(d->sqlite, sql, &rowp, &nrows, &ncols, &errp);
14560 sqlite4_free(0, sql);
14561 if (ret != SQLITE4_OK) {
14562 setstat(s, ret, "%s (%d)", (*s->ov3) ? "HY000" : "S1000",
14563 errp ? errp : "unknown error", ret);
14564 if (errp) {
14565 sqlite4_free(0, errp);
14566 errp = NULL;
14567 }
14568 freerows(trows);
14569 return SQL_ERROR;
14570 }
14571 if (errp) {
14572 sqlite4_free(0, errp);
14573 errp = NULL;
14574 }
14575 if (ncols * nrows > 0) {
14576 int m, mr, nr = nrows;
14577
14578 namec = -1;
14579 for (k = 0; k < ncols; k++) {
14580 if (strcmp(rowp[k], "name") == 0) {
14581 namec = k;
14582 break;
14583 }
14584 }
14585 if (cname[0]) {
14586 nr = 0;
14587 if (namec >= 0) {
14588 for (k = 1; k <= nrows; k++) {
14589 if (namematch(rowp[k * ncols + namec], cname, 1)) {
14590 nr++;
14591 }
14592 }
14593 }
14594 }
14595 for (k = 0; k < nr; k++) {
14596 m = asize * (roffs + k);
14597 #if defined(_WIN32) || defined(_WIN64)
14598 s->rows[m + 0] = xstrdup(d->xcelqrx ? "main" : "");
14599 s->rows[m + 1] = xstrdup("");
14600 #else
14601 s->rows[m + 0] = xstrdup("");
14602 s->rows[m + 1] = xstrdup("");
14603 #endif
14604 s->rows[m + 2] = xstrdup(trows[i]);
14605 s->rows[m + 8] = xstrdup("10");
14606 s->rows[m + 9] = xstrdup("0");
14607 s->rows[m + 15] = xstrdup("16384");
14608 }
14609 for (k = 0; nr && k < ncols; k++) {
14610 if (strcmp(rowp[k], "cid") == 0) {
14611 for (mr = 0, m = 1; m <= nrows; m++) {
14612 char buf[256];
14613 int ir, coln = k;
14614
14615 if (cname[0] &&
14616 !namematch(rowp[m * ncols + namec], cname, 1)) {
14617 continue;
14618 }
14619 ir = asize * (roffs + mr);
14620 sscanf(rowp[m * ncols + k], "%d", &coln);
14621 sprintf(buf, "%d", coln + 1);
14622 s->rows[ir + 16] = xstrdup(buf);
14623 ++mr;
14624 }
14625 } else if (k == namec) {
14626 for (mr = 0, m = 1; m <= nrows; m++) {
14627 int ir;
14628
14629 if (cname[0] &&
14630 !namematch(rowp[m * ncols + namec], cname, 1)) {
14631 continue;
14632 }
14633 ir = asize * (roffs + mr);
14634 s->rows[ir + 3] = xstrdup(rowp[m * ncols + k]);
14635 ++mr;
14636 }
14637 } else if (strcmp(rowp[k], "notnull") == 0) {
14638 for (mr = 0, m = 1; m <= nrows; m++) {
14639 int ir;
14640
14641 if (cname[0] &&
14642 !namematch(rowp[m * ncols + namec], cname, 1)) {
14643 continue;
14644 }
14645 ir = asize * (roffs + mr);
14646 if (*rowp[m * ncols + k] != '0') {
14647 s->rows[ir + 10] = xstrdup(stringify(SQL_FALSE));
14648 } else {
14649 s->rows[ir + 10] = xstrdup(stringify(SQL_TRUE));
14650 }
14651 s->rows[ir + 17] =
14652 xstrdup((*rowp[m * ncols + k] != '0') ?
14653 "NO" : "YES");
14654 ++mr;
14655 }
14656 } else if (strcmp(rowp[k], "dflt_value") == 0) {
14657 for (mr = 0, m = 1; m <= nrows; m++) {
14658 char *dflt = unquote(rowp[m * ncols + k]);
14659 int ir;
14660
14661 if (cname[0] &&
14662 !namematch(rowp[m * ncols + namec], cname, 1)) {
14663 continue;
14664 }
14665 ir = asize * (roffs + mr);
14666 s->rows[ir + 12] = xstrdup(dflt ? dflt : "NULL");
14667 ++mr;
14668 }
14669 } else if (strcmp(rowp[k], "type") == 0) {
14670 for (mr = 0, m = 1; m <= nrows; m++) {
14671 char *typename = rowp[m * ncols + k];
14672 int sqltype, mm, dd, ir;
14673 char buf[256];
14674
14675 if (cname[0] &&
14676 !namematch(rowp[m * ncols + namec], cname, 1)) {
14677 continue;
14678 }
14679 ir = asize * (roffs + mr);
14680 s->rows[ir + 5] = xstrdup(typename);
14681 sqltype = mapsqltype(typename, NULL, *s->ov3,
14682 s->nowchar[0], s->dobigint);
14683 getmd(typename, sqltype, &mm, &dd);
14684 #ifdef SQL_LONGVARCHAR
14685 if (sqltype == SQL_VARCHAR && mm > 255) {
14686 sqltype = SQL_LONGVARCHAR;
14687 }
14688 #endif
14689 #ifdef WINTERFACE
14690 #ifdef SQL_WLONGVARCHAR
14691 if (sqltype == SQL_WVARCHAR && mm > 255) {
14692 sqltype = SQL_WLONGVARCHAR;
14693 }
14694 #endif
14695 #endif
14696 if (sqltype == SQL_VARBINARY && mm > 255) {
14697 sqltype = SQL_LONGVARBINARY;
14698 }
14699 sprintf(buf, "%d", sqltype);
14700 s->rows[ir + 4] = xstrdup(buf);
14701 s->rows[ir + 13] = xstrdup(buf);
14702 sprintf(buf, "%d", mm);
14703 s->rows[ir + 7] = xstrdup(buf);
14704 sprintf(buf, "%d", dd);
14705 s->rows[ir + 6] = xstrdup(buf);
14706 ++mr;
14707 }
14708 }
14709 }
14710 roffs += nr;
14711 }
14712 freerows(rowp);
14713 }
14714 freerows(trows);
14715 return SQL_SUCCESS;
14716 }
14717
14718 #ifndef WINTERFACE
14719 /**
14720 * Retrieve column information on table.
14721 * @param stmt statement handle
14722 * @param cat catalog name/pattern or NULL
14723 * @param catLen length of catalog name/pattern or SQL_NTS
14724 * @param schema schema name/pattern or NULL
14725 * @param schemaLen length of schema name/pattern or SQL_NTS
14726 * @param table table name/pattern or NULL
14727 * @param tableLen length of table name/pattern or SQL_NTS
14728 * @param col column name/pattern or NULL
14729 * @param colLen length of column name/pattern or SQL_NTS
14730 * @result ODBC error code
14731 */
14732
14733 SQLRETURN SQL_API
SQLColumns(SQLHSTMT stmt,SQLCHAR * cat,SQLSMALLINT catLen,SQLCHAR * schema,SQLSMALLINT schemaLen,SQLCHAR * table,SQLSMALLINT tableLen,SQLCHAR * col,SQLSMALLINT colLen)14734 SQLColumns(SQLHSTMT stmt,
14735 SQLCHAR *cat, SQLSMALLINT catLen,
14736 SQLCHAR *schema, SQLSMALLINT schemaLen,
14737 SQLCHAR *table, SQLSMALLINT tableLen,
14738 SQLCHAR *col, SQLSMALLINT colLen)
14739 {
14740 #if defined(_WIN32) || defined(_WIN64)
14741 char *c = NULL, *s = NULL, *t = NULL, *k = NULL;
14742 #endif
14743 SQLRETURN ret;
14744
14745 HSTMT_LOCK(stmt);
14746 #if defined(_WIN32) || defined(_WIN64)
14747 if (!((STMT *) stmt)->oemcp[0]) {
14748 ret = drvcolumns(stmt, cat, catLen, schema, schemaLen,
14749 table, tableLen, col, colLen);
14750 goto done2;
14751 }
14752 if (cat) {
14753 c = wmb_to_utf_c((char *) cat, catLen);
14754 if (!c) {
14755 ret = nomem((STMT *) stmt);
14756 goto done;
14757 }
14758 }
14759 if (schema) {
14760 s = wmb_to_utf_c((char *) schema, schemaLen);
14761 if (!s) {
14762 ret = nomem((STMT *) stmt);
14763 goto done;
14764 }
14765 }
14766 if (table) {
14767 t = wmb_to_utf_c((char *) table, tableLen);
14768 if (!t) {
14769 ret = nomem((STMT *) stmt);
14770 goto done;
14771 }
14772 }
14773 if (col) {
14774 k = wmb_to_utf_c((char *) col, colLen);
14775 if (!k) {
14776 ret = nomem((STMT *) stmt);
14777 goto done;
14778 }
14779 }
14780 ret = drvcolumns(stmt, (SQLCHAR *) c, SQL_NTS, (SQLCHAR *) s, SQL_NTS,
14781 (SQLCHAR *) t, SQL_NTS, (SQLCHAR *) k, SQL_NTS);
14782 #else
14783 ret = drvcolumns(stmt, cat, catLen, schema, schemaLen,
14784 table, tableLen, col, colLen);
14785 #endif
14786 #if defined(_WIN32) || defined(_WIN64)
14787 done:
14788 uc_free(k);
14789 uc_free(t);
14790 uc_free(s);
14791 uc_free(c);
14792 done2:
14793 ;
14794 #endif
14795 HSTMT_UNLOCK(stmt);
14796 return ret;
14797 }
14798 #endif
14799
14800 #ifdef WINTERFACE
14801 /**
14802 * Retrieve column information on table (UNICODE version).
14803 * @param stmt statement handle
14804 * @param cat catalog name/pattern or NULL
14805 * @param catLen length of catalog name/pattern or SQL_NTS
14806 * @param schema schema name/pattern or NULL
14807 * @param schemaLen length of schema name/pattern or SQL_NTS
14808 * @param table table name/pattern or NULL
14809 * @param tableLen length of table name/pattern or SQL_NTS
14810 * @param col column name/pattern or NULL
14811 * @param colLen length of column name/pattern or SQL_NTS
14812 * @result ODBC error code
14813 */
14814
14815 SQLRETURN SQL_API
SQLColumnsW(SQLHSTMT stmt,SQLWCHAR * cat,SQLSMALLINT catLen,SQLWCHAR * schema,SQLSMALLINT schemaLen,SQLWCHAR * table,SQLSMALLINT tableLen,SQLWCHAR * col,SQLSMALLINT colLen)14816 SQLColumnsW(SQLHSTMT stmt,
14817 SQLWCHAR *cat, SQLSMALLINT catLen,
14818 SQLWCHAR *schema, SQLSMALLINT schemaLen,
14819 SQLWCHAR *table, SQLSMALLINT tableLen,
14820 SQLWCHAR *col, SQLSMALLINT colLen)
14821 {
14822 char *c = NULL, *s = NULL, *t = NULL, *k = NULL;
14823 SQLRETURN ret;
14824
14825 HSTMT_LOCK(stmt);
14826 if (cat) {
14827 c = uc_to_utf_c(cat, catLen);
14828 if (!c) {
14829 ret = nomem((STMT *) stmt);
14830 goto done;
14831 }
14832 }
14833 if (schema) {
14834 s = uc_to_utf_c(schema, schemaLen);
14835 if (!s) {
14836 ret = nomem((STMT *) stmt);
14837 goto done;
14838 }
14839 }
14840 if (table) {
14841 t = uc_to_utf_c(table, tableLen);
14842 if (!t) {
14843 ret = nomem((STMT *) stmt);
14844 goto done;
14845 }
14846 }
14847 if (col) {
14848 k = uc_to_utf_c(col, colLen);
14849 if (!k) {
14850 ret = nomem((STMT *) stmt);
14851 goto done;
14852 }
14853 }
14854 ret = drvcolumns(stmt, (SQLCHAR *) c, SQL_NTS, (SQLCHAR *) s, SQL_NTS,
14855 (SQLCHAR *) t, SQL_NTS, (SQLCHAR *) k, SQL_NTS);
14856 done:
14857 uc_free(k);
14858 uc_free(t);
14859 uc_free(s);
14860 uc_free(c);
14861 HSTMT_UNLOCK(stmt);
14862 return ret;
14863
14864 }
14865 #endif
14866
14867 /**
14868 * Columns for result set of SQLGetTypeInfo().
14869 */
14870
14871 static COL typeSpec2[] = {
14872 { "SYSTEM", "TYPE", "TYPE_NAME", SCOL_VARCHAR, 50 },
14873 { "SYSTEM", "TYPE", "DATA_TYPE", SQL_SMALLINT, 2 },
14874 { "SYSTEM", "TYPE", "PRECISION", SQL_INTEGER, 9 },
14875 { "SYSTEM", "TYPE", "LITERAL_PREFIX", SCOL_VARCHAR, 50 },
14876 { "SYSTEM", "TYPE", "LITERAL_SUFFIX", SCOL_VARCHAR, 50 },
14877 { "SYSTEM", "TYPE", "CREATE_PARAMS", SCOL_VARCHAR, 50 },
14878 { "SYSTEM", "TYPE", "NULLABLE", SQL_SMALLINT, 2 },
14879 { "SYSTEM", "TYPE", "CASE_SENSITIVE", SQL_SMALLINT, 2 },
14880 { "SYSTEM", "TYPE", "SEARCHABLE", SQL_SMALLINT, 2 },
14881 { "SYSTEM", "TYPE", "UNSIGNED_ATTRIBUTE", SQL_SMALLINT, 2 },
14882 { "SYSTEM", "TYPE", "MONEY", SQL_SMALLINT, 2 },
14883 { "SYSTEM", "TYPE", "AUTO_INCREMENT", SQL_SMALLINT, 2 },
14884 { "SYSTEM", "TYPE", "LOCAL_TYPE_NAME", SCOL_VARCHAR, 50 },
14885 { "SYSTEM", "TYPE", "MINIMUM_SCALE", SQL_SMALLINT, 2 },
14886 { "SYSTEM", "TYPE", "MAXIMUM_SCALE", SQL_SMALLINT, 2 }
14887 };
14888
14889 static COL typeSpec3[] = {
14890 { "SYSTEM", "TYPE", "TYPE_NAME", SCOL_VARCHAR, 50 },
14891 { "SYSTEM", "TYPE", "DATA_TYPE", SQL_SMALLINT, 2 },
14892 { "SYSTEM", "TYPE", "COLUMN_SIZE", SQL_INTEGER, 9 },
14893 { "SYSTEM", "TYPE", "LITERAL_PREFIX", SCOL_VARCHAR, 50 },
14894 { "SYSTEM", "TYPE", "LITERAL_SUFFIX", SCOL_VARCHAR, 50 },
14895 { "SYSTEM", "TYPE", "CREATE_PARAMS", SCOL_VARCHAR, 50 },
14896 { "SYSTEM", "TYPE", "NULLABLE", SQL_SMALLINT, 2 },
14897 { "SYSTEM", "TYPE", "CASE_SENSITIVE", SQL_SMALLINT, 2 },
14898 { "SYSTEM", "TYPE", "SEARCHABLE", SQL_SMALLINT, 2 },
14899 { "SYSTEM", "TYPE", "UNSIGNED_ATTRIBUTE", SQL_SMALLINT, 2 },
14900 { "SYSTEM", "TYPE", "FIXED_PREC_SCALE", SQL_SMALLINT, 2 },
14901 { "SYSTEM", "TYPE", "AUTO_UNIQUE_VALUE", SQL_SMALLINT, 2 },
14902 { "SYSTEM", "TYPE", "LOCAL_TYPE_NAME", SCOL_VARCHAR, 50 },
14903 { "SYSTEM", "TYPE", "MINIMUM_SCALE", SQL_SMALLINT, 2 },
14904 { "SYSTEM", "TYPE", "MAXIMUM_SCALE", SQL_SMALLINT, 2 },
14905 { "SYSTEM", "TYPE", "SQL_DATA_TYPE", SQL_SMALLINT, 2 },
14906 { "SYSTEM", "TYPE", "SQL_DATETIME_SUB", SQL_SMALLINT, 2 },
14907 { "SYSTEM", "TYPE", "NUM_PREC_RADIX", SQL_INTEGER, 4 },
14908 { "SYSTEM", "TYPE", "INTERVAL_PRECISION", SQL_SMALLINT, 2 }
14909 };
14910
14911 /**
14912 * Internal function to build up data type information as row in result set.
14913 * @param s statement pointer
14914 * @param row row number
14915 * @param asize number of items in a row
14916 * @param typename name of type
14917 * @param type integer SQL type
14918 * @param tind type index
14919 */
14920
14921 static void
mktypeinfo(STMT * s,int row,int asize,char * typename,int type,int tind)14922 mktypeinfo(STMT *s, int row, int asize, char *typename, int type, int tind)
14923 {
14924 int offs = row * asize;
14925 char *tcode, *crpar = NULL, *sign = stringify(SQL_FALSE);
14926 char *quote[2] = { NULL, NULL };
14927 static char tcodes[32 * 32];
14928
14929 if (tind <= 0) {
14930 tind = row;
14931 }
14932 tcode = tcodes + tind * 32;
14933 sprintf(tcode, "%d", type);
14934 s->rows[offs + 0] = typename;
14935 s->rows[offs + 1] = tcode;
14936 if (asize >= 17) {
14937 s->rows[offs + 15] = tcode;
14938 s->rows[offs + 16] = "0";
14939 }
14940 switch (type) {
14941 default:
14942 #ifdef SQL_LONGVARCHAR
14943 case SQL_LONGVARCHAR:
14944 #ifdef WINTERFACE
14945 case SQL_WLONGVARCHAR:
14946 #endif
14947 crpar = "length";
14948 quote[0] = quote[1] = "'";
14949 sign = NULL;
14950 s->rows[offs + 2] = "65536";
14951 break;
14952 #endif
14953 #ifdef SQL_BIT
14954 case SQL_BIT:
14955 sign = NULL;
14956 s->rows[offs + 2] = "1";
14957 break;
14958 #endif
14959 case SQL_CHAR:
14960 case SQL_VARCHAR:
14961 #ifdef WINTERFACE
14962 case SQL_WCHAR:
14963 case SQL_WVARCHAR:
14964 #endif
14965 s->rows[offs + 2] = "255";
14966 crpar = "length";
14967 quote[0] = quote[1] = "'";
14968 sign = NULL;
14969 break;
14970 case SQL_TINYINT:
14971 s->rows[offs + 2] = "3";
14972 break;
14973 case SQL_SMALLINT:
14974 s->rows[offs + 2] = "5";
14975 break;
14976 case SQL_INTEGER:
14977 s->rows[offs + 2] = "9";
14978 break;
14979 #ifdef SQL_BIGINT
14980 case SQL_BIGINT:
14981 s->rows[offs + 2] = "19";
14982 break;
14983 #endif
14984 case SQL_FLOAT:
14985 s->rows[offs + 2] = "7";
14986 break;
14987 case SQL_DOUBLE:
14988 s->rows[offs + 2] = "15";
14989 break;
14990 #ifdef SQL_TYPE_DATE
14991 case SQL_TYPE_DATE:
14992 #endif
14993 case SQL_DATE:
14994 s->rows[offs + 2] = "10";
14995 quote[0] = quote[1] = "'";
14996 sign = NULL;
14997 break;
14998 #ifdef SQL_TYPE_TIME
14999 case SQL_TYPE_TIME:
15000 #endif
15001 case SQL_TIME:
15002 s->rows[offs + 2] = "8";
15003 quote[0] = quote[1] = "'";
15004 sign = NULL;
15005 break;
15006 #ifdef SQL_TYPE_TIMESTAMP
15007 case SQL_TYPE_TIMESTAMP:
15008 #endif
15009 case SQL_TIMESTAMP:
15010 s->rows[offs + 2] = "32";
15011 quote[0] = quote[1] = "'";
15012 sign = NULL;
15013 break;
15014 case SQL_VARBINARY:
15015 quote[0] = "0x";
15016 sign = NULL;
15017 s->rows[offs + 2] = "255";
15018 break;
15019 case SQL_LONGVARBINARY:
15020 quote[0] = "0x";
15021 sign = NULL;
15022 s->rows[offs + 2] = "65536";
15023 break;
15024 }
15025 s->rows[offs + 3] = quote[0];
15026 s->rows[offs + 4] = quote[1];
15027 s->rows[offs + 5] = crpar;
15028 s->rows[offs + 6] = stringify(SQL_NULLABLE);
15029 s->rows[offs + 7] = stringify(SQL_FALSE);
15030 s->rows[offs + 8] = stringify(SQL_SEARCHABLE);
15031 s->rows[offs + 9] = sign;
15032 s->rows[offs + 10] = stringify(SQL_FALSE);
15033 s->rows[offs + 11] = stringify(SQL_FALSE);
15034 s->rows[offs + 12] = typename;
15035 switch (type) {
15036 case SQL_DATE:
15037 case SQL_TIME:
15038 s->rows[offs + 13] = "0";
15039 s->rows[offs + 14] = "0";
15040 break;
15041 #ifdef SQL_TYPE_TIMESTAMP
15042 case SQL_TYPE_TIMESTAMP:
15043 #endif
15044 case SQL_TIMESTAMP:
15045 s->rows[offs + 13] = "0";
15046 s->rows[offs + 14] = "3";
15047 break;
15048 default:
15049 s->rows[offs + 13] = NULL;
15050 s->rows[offs + 14] = NULL;
15051 break;
15052 }
15053 }
15054
15055 /**
15056 * Helper function to sort type information.
15057 * Callback for qsort().
15058 * @param a first item to compare
15059 * @param b second item to compare
15060 * @result ==0, <0, >0 according to data type number
15061 */
15062
15063 static int
typeinfosort(const void * a,const void * b)15064 typeinfosort(const void *a, const void *b)
15065 {
15066 char **pa = (char **) a;
15067 char **pb = (char **) b;
15068 int na, nb;
15069
15070 na = strtol(pa[1], NULL, 0);
15071 nb = strtol(pb[1], NULL, 0);
15072 return na - nb;
15073 }
15074
15075 /**
15076 * Internal return data type information.
15077 * @param stmt statement handle
15078 * @param sqltype which type to retrieve
15079 * @result ODBC error code
15080 */
15081
15082 static SQLRETURN
drvgettypeinfo(SQLHSTMT stmt,SQLSMALLINT sqltype)15083 drvgettypeinfo(SQLHSTMT stmt, SQLSMALLINT sqltype)
15084 {
15085 SQLRETURN ret;
15086 STMT *s;
15087 int asize;
15088
15089 ret = mkresultset(stmt, typeSpec2, array_size(typeSpec2),
15090 typeSpec3, array_size(typeSpec3), &asize);
15091 if (ret != SQL_SUCCESS) {
15092 return ret;
15093 }
15094 s = (STMT *) stmt;
15095 #ifdef SQL_LONGVARCHAR
15096 s->nrows = (sqltype == SQL_ALL_TYPES) ? 13 : 1;
15097 #else
15098 s->nrows = (sqltype == SQL_ALL_TYPES) ? 12 : 1;
15099 #endif
15100 if (sqltype == SQL_ALL_TYPES) {
15101 #ifdef WINTERFACE
15102 s->nrows += 2;
15103 #ifdef SQL_WLONGVARCHAR
15104 s->nrows += 2;
15105 #endif
15106 #endif
15107 }
15108 if (sqltype == SQL_ALL_TYPES) {
15109 s->nrows += 2;
15110 #ifdef SQL_BIT
15111 s->nrows += 1;
15112 #endif
15113 #ifdef SQL_BIGINT
15114 s->nrows += 1;
15115 #endif
15116 }
15117 s->rows = (char **) xmalloc(sizeof (char *) * (s->nrows + 1) * asize);
15118 if (!s->rows) {
15119 s->nrows = 0;
15120 return nomem(s);
15121 }
15122 #ifdef MEMORY_DEBUG
15123 s->rowfree = xfree__;
15124 #else
15125 s->rowfree = sqlite4_free;
15126 #endif
15127 memset(s->rows, 0, sizeof (char *) * (s->nrows + 1) * asize);
15128 if (sqltype == SQL_ALL_TYPES) {
15129 int cc = 1;
15130
15131 mktypeinfo(s, cc++, asize, "varchar", SQL_VARCHAR, 0);
15132 mktypeinfo(s, cc++, asize, "tinyint", SQL_TINYINT, 0);
15133 mktypeinfo(s, cc++, asize, "smallint", SQL_SMALLINT, 0);
15134 mktypeinfo(s, cc++, asize, "integer", SQL_INTEGER, 0);
15135 mktypeinfo(s, cc++, asize, "float", SQL_FLOAT, 0);
15136 mktypeinfo(s, cc++, asize, "double", SQL_DOUBLE, 0);
15137 #ifdef SQL_TYPE_DATE
15138 mktypeinfo(s, cc++, asize, "date",
15139 (*s->ov3) ? SQL_TYPE_DATE : SQL_DATE, 0);
15140 #else
15141 mktypeinfo(s, cc++, asize, "date", SQL_DATE, 0);
15142 #endif
15143 #ifdef SQL_TYPE_TIME
15144 mktypeinfo(s, cc++, asize, "time",
15145 (*s->ov3) ? SQL_TYPE_TIME : SQL_TIME, 0);
15146 #else
15147 mktypeinfo(s, cc++, asize, "time", SQL_TIME, 0);
15148 #endif
15149 #ifdef SQL_TYPE_TIMESTAMP
15150 mktypeinfo(s, cc++, asize, "timestamp",
15151 (*s->ov3) ? SQL_TYPE_TIMESTAMP : SQL_TIMESTAMP, 0);
15152 #else
15153 mktypeinfo(s, cc++, asize, "timestamp", SQL_TIMESTAMP, 0);
15154 #endif
15155 mktypeinfo(s, cc++, asize, "char", SQL_CHAR, 0);
15156 mktypeinfo(s, cc++, asize, "numeric", SQL_DOUBLE, 0);
15157 #ifdef SQL_LONGVARCHAR
15158 mktypeinfo(s, cc++, asize, "text", SQL_LONGVARCHAR, 0);
15159 mktypeinfo(s, cc++, asize, "longvarchar", SQL_LONGVARCHAR, 0);
15160 #else
15161 mktypeinfo(s, cc++, asize, "text", SQL_VARCHAR, 0);
15162 #endif
15163 mktypeinfo(s, cc++, asize, "varbinary", SQL_VARBINARY, 0);
15164 mktypeinfo(s, cc++, asize, "longvarbinary", SQL_LONGVARBINARY, 0);
15165 #ifdef SQL_BIT
15166 mktypeinfo(s, cc++, asize, "bit", SQL_BIT, 0);
15167 #endif
15168 #ifdef SQL_BIGINT
15169 mktypeinfo(s, cc++, asize, "bigint", SQL_BIGINT, 0);
15170 #endif
15171 #ifdef WINTERFACE
15172 mktypeinfo(s, cc++, asize, "wvarchar", SQL_WVARCHAR, 0);
15173 mktypeinfo(s, cc++, asize, "wchar", SQL_WCHAR, 0);
15174 #ifdef SQL_WLONGVARCHAR
15175 mktypeinfo(s, cc++, asize, "wtext", SQL_WLONGVARCHAR, 0);
15176 mktypeinfo(s, cc++, asize, "longwvarchar", SQL_WLONGVARCHAR, 0);
15177 #endif
15178 #endif
15179 qsort(s->rows + asize, s->nrows, sizeof (char *) * asize,
15180 typeinfosort);
15181 } else {
15182 switch (sqltype) {
15183 case SQL_CHAR:
15184 mktypeinfo(s, 1, asize, "char", SQL_CHAR, 10);
15185 break;
15186 case SQL_VARCHAR:
15187 mktypeinfo(s, 1, asize, "varchar", SQL_VARCHAR, 1);
15188 break;
15189 case SQL_TINYINT:
15190 mktypeinfo(s, 1, asize, "tinyint", SQL_TINYINT, 2);
15191 break;
15192 case SQL_SMALLINT:
15193 mktypeinfo(s, 1, asize, "smallint", SQL_SMALLINT, 3);
15194 break;
15195 case SQL_INTEGER:
15196 mktypeinfo(s, 1, asize, "integer", SQL_INTEGER, 4);
15197 break;
15198 case SQL_FLOAT:
15199 mktypeinfo(s, 1, asize, "float", SQL_FLOAT, 5);
15200 break;
15201 case SQL_DOUBLE:
15202 mktypeinfo(s, 1, asize, "double", SQL_DOUBLE, 6);
15203 break;
15204 #ifdef SQL_TYPE_DATE
15205 case SQL_TYPE_DATE:
15206 mktypeinfo(s, 1, asize, "date", SQL_TYPE_DATE, 25);
15207 break;
15208 #endif
15209 case SQL_DATE:
15210 mktypeinfo(s, 1, asize, "date", SQL_DATE, 7);
15211 break;
15212 #ifdef SQL_TYPE_TIME
15213 case SQL_TYPE_TIME:
15214 mktypeinfo(s, 1, asize, "time", SQL_TYPE_TIME, 26);
15215 break;
15216 #endif
15217 case SQL_TIME:
15218 mktypeinfo(s, 1, asize, "time", SQL_TIME, 8);
15219 break;
15220 #ifdef SQL_TYPE_TIMESTAMP
15221 case SQL_TYPE_TIMESTAMP:
15222 mktypeinfo(s, 1, asize, "timestamp", SQL_TYPE_TIMESTAMP, 27);
15223 break;
15224 #endif
15225 case SQL_TIMESTAMP:
15226 mktypeinfo(s, 1, asize, "timestamp", SQL_TIMESTAMP, 9);
15227 break;
15228 #ifdef SQL_LONGVARCHAR
15229 case SQL_LONGVARCHAR:
15230 mktypeinfo(s, 1, asize, "longvarchar", SQL_LONGVARCHAR, 12);
15231 break;
15232 #endif
15233 case SQL_VARBINARY:
15234 mktypeinfo(s, 1, asize, "varbinary", SQL_VARBINARY, 30);
15235 break;
15236 case SQL_LONGVARBINARY:
15237 mktypeinfo(s, 1, asize, "longvarbinary", SQL_LONGVARBINARY, 31);
15238 break;
15239 #ifdef SQL_BIT
15240 case SQL_BIT:
15241 mktypeinfo(s, 1, asize, "bit", SQL_BIT, 29);
15242 break;
15243 #endif
15244 #ifdef SQL_BIGINT
15245 case SQL_BIGINT:
15246 mktypeinfo(s, 1, asize, "bigint", SQL_BIGINT, 28);
15247 break;
15248 #endif
15249 #ifdef WINTERFACE
15250 #ifdef SQL_WCHAR
15251 case SQL_WCHAR:
15252 mktypeinfo(s, 1, asize, "wchar", SQL_WCHAR, 18);
15253 break;
15254 #endif
15255 #ifdef SQL_WVARCHAR
15256 case SQL_WVARCHAR:
15257 mktypeinfo(s, 1, asize, "wvarchar", SQL_WVARCHAR, 19);
15258 break;
15259 #endif
15260 #ifdef SQL_WLONGVARCHAR
15261 case SQL_WLONGVARCHAR:
15262 mktypeinfo(s, 1, asize, "longwvarchar", SQL_WLONGVARCHAR, 20);
15263 break;
15264 #endif
15265 #endif
15266 default:
15267 s->nrows = 0;
15268 }
15269 }
15270 return SQL_SUCCESS;
15271 }
15272
15273 #ifndef WINTERFACE
15274 /**
15275 * Return data type information.
15276 * @param stmt statement handle
15277 * @param sqltype which type to retrieve
15278 * @result ODBC error code
15279 */
15280
15281 SQLRETURN SQL_API
SQLGetTypeInfo(SQLHSTMT stmt,SQLSMALLINT sqltype)15282 SQLGetTypeInfo(SQLHSTMT stmt, SQLSMALLINT sqltype)
15283 {
15284 SQLRETURN ret;
15285
15286 HSTMT_LOCK(stmt);
15287 ret = drvgettypeinfo(stmt, sqltype);
15288 HSTMT_UNLOCK(stmt);
15289 return ret;
15290 }
15291 #endif
15292
15293 #ifdef WINTERFACE
15294 /**
15295 * Return data type information (UNICODE version).
15296 * @param stmt statement handle
15297 * @param sqltype which type to retrieve
15298 * @result ODBC error code
15299 */
15300
15301 SQLRETURN SQL_API
SQLGetTypeInfoW(SQLHSTMT stmt,SQLSMALLINT sqltype)15302 SQLGetTypeInfoW(SQLHSTMT stmt, SQLSMALLINT sqltype)
15303 {
15304 SQLRETURN ret;
15305
15306 HSTMT_LOCK(stmt);
15307 ret = drvgettypeinfo(stmt, sqltype);
15308 HSTMT_UNLOCK(stmt);
15309 return ret;
15310 }
15311 #endif
15312
15313 /**
15314 * Columns for result set of SQLStatistics().
15315 */
15316
15317 static COL statSpec2[] = {
15318 { "SYSTEM", "STATISTICS", "TABLE_QUALIFIER", SCOL_VARCHAR, 50 },
15319 { "SYSTEM", "STATISTICS", "TABLE_OWNER", SCOL_VARCHAR, 50 },
15320 { "SYSTEM", "STATISTICS", "TABLE_NAME", SCOL_VARCHAR, 255 },
15321 { "SYSTEM", "STATISTICS", "NON_UNIQUE", SQL_SMALLINT, 50 },
15322 { "SYSTEM", "STATISTICS", "INDEX_QUALIFIER", SCOL_VARCHAR, 255 },
15323 { "SYSTEM", "STATISTICS", "INDEX_NAME", SCOL_VARCHAR, 255 },
15324 { "SYSTEM", "STATISTICS", "TYPE", SQL_SMALLINT, 50 },
15325 { "SYSTEM", "STATISTICS", "SEQ_IN_INDEX", SQL_SMALLINT, 50 },
15326 { "SYSTEM", "STATISTICS", "COLUMN_NAME", SCOL_VARCHAR, 255 },
15327 { "SYSTEM", "STATISTICS", "COLLATION", SCOL_CHAR, 1 },
15328 { "SYSTEM", "STATISTICS", "CARDINALITY", SQL_INTEGER, 50 },
15329 { "SYSTEM", "STATISTICS", "PAGES", SQL_INTEGER, 50 },
15330 { "SYSTEM", "STATISTICS", "FILTER_CONDITION", SCOL_VARCHAR, 255 }
15331 };
15332
15333 static COL statSpec3[] = {
15334 { "SYSTEM", "STATISTICS", "TABLE_CAT", SCOL_VARCHAR, 50 },
15335 { "SYSTEM", "STATISTICS", "TABLE_SCHEM", SCOL_VARCHAR, 50 },
15336 { "SYSTEM", "STATISTICS", "TABLE_NAME", SCOL_VARCHAR, 255 },
15337 { "SYSTEM", "STATISTICS", "NON_UNIQUE", SQL_SMALLINT, 50 },
15338 { "SYSTEM", "STATISTICS", "INDEX_QUALIFIER", SCOL_VARCHAR, 255 },
15339 { "SYSTEM", "STATISTICS", "INDEX_NAME", SCOL_VARCHAR, 255 },
15340 { "SYSTEM", "STATISTICS", "TYPE", SQL_SMALLINT, 50 },
15341 { "SYSTEM", "STATISTICS", "ORDINAL_POSITION", SQL_SMALLINT, 50 },
15342 { "SYSTEM", "STATISTICS", "COLUMN_NAME", SCOL_VARCHAR, 255 },
15343 { "SYSTEM", "STATISTICS", "ASC_OR_DESC", SCOL_CHAR, 1 },
15344 { "SYSTEM", "STATISTICS", "CARDINALITY", SQL_INTEGER, 50 },
15345 { "SYSTEM", "STATISTICS", "PAGES", SQL_INTEGER, 50 },
15346 { "SYSTEM", "STATISTICS", "FILTER_CONDITION", SCOL_VARCHAR, 255 }
15347 };
15348
15349 /**
15350 * Internal return statistic information on table indices.
15351 * @param stmt statement handle
15352 * @param cat catalog name/pattern or NULL
15353 * @param catLen length of catalog name/pattern or SQL_NTS
15354 * @param schema schema name/pattern or NULL
15355 * @param schemaLen length of schema name/pattern or SQL_NTS
15356 * @param table table name/pattern or NULL
15357 * @param tableLen length of table name/pattern or SQL_NTS
15358 * @param itype type of index information
15359 * @param resv reserved
15360 * @result ODBC error code
15361 */
15362
15363 static SQLRETURN
drvstatistics(SQLHSTMT stmt,SQLCHAR * cat,SQLSMALLINT catLen,SQLCHAR * schema,SQLSMALLINT schemaLen,SQLCHAR * table,SQLSMALLINT tableLen,SQLUSMALLINT itype,SQLUSMALLINT resv)15364 drvstatistics(SQLHSTMT stmt, SQLCHAR *cat, SQLSMALLINT catLen,
15365 SQLCHAR *schema, SQLSMALLINT schemaLen,
15366 SQLCHAR *table, SQLSMALLINT tableLen,
15367 SQLUSMALLINT itype, SQLUSMALLINT resv)
15368 {
15369 SQLRETURN sret;
15370 STMT *s;
15371 DBC *d;
15372 int i, asize, ret, nrows, ncols, offs, namec, uniquec, addipk = 0;
15373 PTRDIFF_T size;
15374 char **rowp, *errp = NULL, *sql, tname[512];
15375
15376 sret = mkresultset(stmt, statSpec2, array_size(statSpec2),
15377 statSpec3, array_size(statSpec3), &asize);
15378 if (sret != SQL_SUCCESS) {
15379 return sret;
15380 }
15381 s = (STMT *) stmt;
15382 d = (DBC *) s->dbc;
15383 if (!table || table[0] == '\0' || table[0] == '%') {
15384 setstat(s, -1, "need table name", (*s->ov3) ? "HY000" : "S1000");
15385 return SQL_ERROR;
15386 }
15387 if (tableLen == SQL_NTS) {
15388 size = sizeof (tname) - 1;
15389 } else {
15390 size = min(sizeof (tname) - 1, tableLen);
15391 }
15392 strncpy(tname, (char *) table, size);
15393 tname[size] = '\0';
15394 unescpat(tname);
15395 sret = starttran(s);
15396 if (sret != SQL_SUCCESS) {
15397 return sret;
15398 }
15399 /*
15400 * Try integer primary key (autoincrement) first
15401 */
15402 if (itype == SQL_INDEX_UNIQUE || itype == SQL_INDEX_ALL) {
15403 rowp = 0;
15404 ret = SQLITE4_ERROR;
15405 sql = sqlite4_mprintf(0, "PRAGMA table_info(%Q)", tname);
15406 if (sql) {
15407 dbtraceapi(d, "sqlite4_get_table", sql);
15408 ret = sqlite4_get_table(d->sqlite, sql, &rowp,
15409 &nrows, &ncols, NULL);
15410 sqlite4_free(0, sql);
15411 }
15412 if (ret == SQLITE4_OK) {
15413 int colid, typec, npk = 0, npkint = 0;
15414
15415 namec = findcol(rowp, ncols, "name");
15416 uniquec = findcol(rowp, ncols, "pk");
15417 typec = findcol(rowp, ncols, "type");
15418 colid = findcol(rowp, ncols, "cid");
15419 if (namec < 0 || uniquec < 0 || typec < 0 || colid < 0) {
15420 goto noipk;
15421 }
15422 for (i = 1; i <= nrows; i++) {
15423 if (*rowp[i * ncols + uniquec] != '0') {
15424 npk++;
15425 if (strlen(rowp[i * ncols + typec]) == 7 &&
15426 strncasecmp(rowp[i * ncols + typec], "integer", 7)
15427 == 0) {
15428 npkint++;
15429 }
15430 }
15431 }
15432 if (npkint == 1 && npk == nkpint) {
15433 addipk = 1;
15434 }
15435 }
15436 noipk:
15437 freerows(rowp);
15438 }
15439 sql = sqlite4_mprintf(0, "PRAGMA index_list(%Q)", tname);
15440 if (!sql) {
15441 return nomem(s);
15442 }
15443 dbtraceapi(d, "sqlite4_get_table", sql);
15444 ret = sqlite4_get_table(d->sqlite, sql, &rowp, &nrows, &ncols, &errp);
15445 sqlite4_free(0, sql);
15446 if (ret != SQLITE4_OK) {
15447 setstat(s, ret, "%s (%d)", (*s->ov3) ? "HY000" : "S1000",
15448 errp ? errp : "unknown error", ret);
15449 if (errp) {
15450 sqlite4_free(0, errp);
15451 errp = NULL;
15452 }
15453 return SQL_ERROR;
15454 }
15455 if (errp) {
15456 sqlite4_free(0, errp);
15457 errp = NULL;
15458 }
15459 size = 0;
15460 namec = findcol(rowp, ncols, "name");
15461 uniquec = findcol(rowp, ncols, "unique");
15462 if (namec < 0 || uniquec < 0) {
15463 goto nodata;
15464 }
15465 for (i = 1; i <= nrows; i++) {
15466 int nnrows, nncols;
15467 char **rowpp;
15468 int isuniq;
15469
15470 isuniq = *rowp[i * ncols + uniquec] != '0';
15471 if (isuniq || itype == SQL_INDEX_ALL) {
15472 ret = SQLITE4_ERROR;
15473 sql = sqlite4_mprintf(0, "PRAGMA index_info(%Q)",
15474 rowp[i * ncols + namec]);
15475 if (sql) {
15476 dbtraceapi(d, "sqlite4_get_table", sql);
15477 ret = sqlite4_get_table(d->sqlite, sql, &rowpp,
15478 &nnrows, &nncols, NULL);
15479 sqlite4_free(0, sql);
15480 }
15481 if (ret == SQLITE4_OK) {
15482 size += nnrows;
15483 freerows(rowpp);
15484 }
15485 }
15486 }
15487 nodata:
15488 if (addipk) {
15489 size++;
15490 }
15491 if (size == 0) {
15492 freerows(rowp);
15493 return SQL_SUCCESS;
15494 }
15495 s->nrows = size;
15496 size = (size + 1) * asize;
15497 s->rows = xmalloc((size + 1) * sizeof (char *));
15498 if (!s->rows) {
15499 s->nrows = 0;
15500 return nomem(s);
15501 }
15502 s->rows[0] = (char *) size;
15503 s->rows += 1;
15504 memset(s->rows, 0, sizeof (char *) * size);
15505 s->rowfree = freerows;
15506 offs = 0;
15507 if (addipk) {
15508 char **rowpp = 0;
15509 int nrows2, ncols2;
15510
15511 sql = sqlite4_mprintf(0, "PRAGMA table_info(%Q)", tname);
15512 if (sql) {
15513 dbtraceapi(d, "sqlite4_get_table", sql);
15514 ret = sqlite4_get_table(d->sqlite, sql, &rowpp,
15515 &nrows2, &ncols2, NULL);
15516 sqlite4_free(0, sql);
15517 }
15518 if (ret == SQLITE4_OK) {
15519 int colid, typec, roffs, namecc, uniquecc;
15520
15521 namecc = findcol(rowpp, ncols2, "name");
15522 uniquecc = findcol(rowpp, ncols2, "pk");
15523 typec = findcol(rowpp, ncols2, "type");
15524 colid = findcol(rowpp, ncols2, "cid");
15525 if (namecc < 0 || uniquecc < 0 || typec < 0 || colid < 0) {
15526 addipk = 0;
15527 s->nrows--;
15528 goto nodata2;
15529 }
15530 for (i = 1; i <= nrows2; i++) {
15531 if (*rowpp[i * ncols2 + uniquecc] != '0' &&
15532 strlen(rowpp[i * ncols2 + typec]) == 7 &&
15533 strncasecmp(rowpp[i * ncols2 + typec], "integer", 7)
15534 == 0) {
15535 break;
15536 }
15537 }
15538 if (i > nrows2) {
15539 addipk = 0;
15540 s->nrows--;
15541 goto nodata2;
15542 }
15543 roffs = s->ncols;
15544 #if defined(_WIN32) || defined(_WIN64)
15545 s->rows[roffs + 0] = xstrdup(d->xcelqrx ? "main" : "");
15546 s->rows[roffs + 1] = xstrdup("");
15547 #else
15548 s->rows[roffs + 0] = xstrdup("");
15549 s->rows[roffs + 1] = xstrdup("");
15550 #endif
15551 s->rows[roffs + 2] = xstrdup(tname);
15552 s->rows[roffs + 3] = xstrdup(stringify(SQL_FALSE));
15553 s->rows[roffs + 5] = xstrdup("sqlite_autoindex_0");
15554 s->rows[roffs + 6] = xstrdup(stringify(SQL_INDEX_OTHER));
15555 s->rows[roffs + 7] = xstrdup("1");
15556 s->rows[roffs + 8] = xstrdup(rowpp[i * ncols2 + namecc]);
15557 s->rows[roffs + 9] = xstrdup("A");
15558 }
15559 nodata2:
15560 freerows(rowpp);
15561 }
15562 for (i = 1; i <= nrows; i++) {
15563 int nnrows, nncols;
15564 char **rowpp = 0;
15565
15566 if (*rowp[i * ncols + uniquec] != '0' || itype == SQL_INDEX_ALL) {
15567 int k;
15568
15569 ret = SQLITE4_ERROR;
15570 sql = sqlite4_mprintf(0, "PRAGMA index_info(%Q)",
15571 rowp[i * ncols + namec]);
15572 if (sql) {
15573 dbtraceapi(d, "sqlite4_get_table", sql);
15574 ret = sqlite4_get_table(d->sqlite, sql, &rowpp,
15575 &nnrows, &nncols, NULL);
15576 sqlite4_free(0, sql);
15577 }
15578 if (ret != SQLITE4_OK) {
15579 continue;
15580 }
15581 for (k = 0; nnrows && k < nncols; k++) {
15582 if (strcmp(rowpp[k], "name") == 0) {
15583 int m;
15584
15585 for (m = 1; m <= nnrows; m++) {
15586 int roffs = (offs + addipk + m) * s->ncols;
15587 int isuniq;
15588
15589 isuniq = *rowp[i * ncols + uniquec] != '0';
15590 s->rows[roffs + 0] = xstrdup("");
15591 s->rows[roffs + 1] = xstrdup("");
15592 s->rows[roffs + 2] = xstrdup(tname);
15593 if (isuniq) {
15594 s->rows[roffs + 3] = xstrdup(stringify(SQL_FALSE));
15595 } else {
15596 s->rows[roffs + 3] = xstrdup(stringify(SQL_TRUE));
15597 }
15598 s->rows[roffs + 5] = xstrdup(rowp[i * ncols + namec]);
15599 s->rows[roffs + 6] =
15600 xstrdup(stringify(SQL_INDEX_OTHER));
15601 s->rows[roffs + 8] = xstrdup(rowpp[m * nncols + k]);
15602 s->rows[roffs + 9] = xstrdup("A");
15603 }
15604 } else if (strcmp(rowpp[k], "seqno") == 0) {
15605 int m;
15606
15607 for (m = 1; m <= nnrows; m++) {
15608 int roffs = (offs + addipk + m) * s->ncols;
15609 int pos = m - 1;
15610 char buf[32];
15611
15612 sscanf(rowpp[m * nncols + k], "%d", &pos);
15613 sprintf(buf, "%d", pos + 1);
15614 s->rows[roffs + 7] = xstrdup(buf);
15615 }
15616 }
15617 }
15618 offs += nnrows;
15619 freerows(rowpp);
15620 }
15621 }
15622 freerows(rowp);
15623 return SQL_SUCCESS;
15624 }
15625
15626 #ifndef WINTERFACE
15627 /**
15628 * Return statistic information on table indices.
15629 * @param stmt statement handle
15630 * @param cat catalog name/pattern or NULL
15631 * @param catLen length of catalog name/pattern or SQL_NTS
15632 * @param schema schema name/pattern or NULL
15633 * @param schemaLen length of schema name/pattern or SQL_NTS
15634 * @param table table name/pattern or NULL
15635 * @param tableLen length of table name/pattern or SQL_NTS
15636 * @param itype type of index information
15637 * @param resv reserved
15638 * @result ODBC error code
15639 */
15640
15641 SQLRETURN SQL_API
SQLStatistics(SQLHSTMT stmt,SQLCHAR * cat,SQLSMALLINT catLen,SQLCHAR * schema,SQLSMALLINT schemaLen,SQLCHAR * table,SQLSMALLINT tableLen,SQLUSMALLINT itype,SQLUSMALLINT resv)15642 SQLStatistics(SQLHSTMT stmt, SQLCHAR *cat, SQLSMALLINT catLen,
15643 SQLCHAR *schema, SQLSMALLINT schemaLen,
15644 SQLCHAR *table, SQLSMALLINT tableLen,
15645 SQLUSMALLINT itype, SQLUSMALLINT resv)
15646 {
15647 #if defined(_WIN32) || defined(_WIN64)
15648 char *c = NULL, *s = NULL, *t = NULL;
15649 #endif
15650 SQLRETURN ret;
15651
15652 HSTMT_LOCK(stmt);
15653 #if defined(_WIN32) || defined(_WIN64)
15654 if (!((STMT *) stmt)->oemcp[0]) {
15655 ret = drvstatistics(stmt, cat, catLen, schema, schemaLen,
15656 table, tableLen, itype, resv);
15657 goto done2;
15658 }
15659 if (cat) {
15660 c = wmb_to_utf_c((char *) cat, catLen);
15661 if (!c) {
15662 ret = nomem((STMT *) stmt);
15663 goto done;
15664 }
15665 }
15666 if (schema) {
15667 s = wmb_to_utf_c((char *) schema, schemaLen);
15668 if (!s) {
15669 ret = nomem((STMT *) stmt);
15670 goto done;
15671 }
15672 }
15673 if (table) {
15674 t = wmb_to_utf_c((char *) table, tableLen);
15675 if (!t) {
15676 ret = nomem((STMT *) stmt);
15677 goto done;
15678 }
15679 }
15680 ret = drvstatistics(stmt, (SQLCHAR *) c, SQL_NTS, (SQLCHAR *) s, SQL_NTS,
15681 (SQLCHAR *) t, SQL_NTS, itype, resv);
15682 #else
15683 ret = drvstatistics(stmt, cat, catLen, schema, schemaLen,
15684 table, tableLen, itype, resv);
15685 #endif
15686 #if defined(_WIN32) || defined(_WIN64)
15687 done:
15688 uc_free(t);
15689 uc_free(s);
15690 uc_free(c);
15691 done2:
15692 ;
15693 #endif
15694 HSTMT_UNLOCK(stmt);
15695 return ret;
15696 }
15697 #endif
15698
15699 #ifdef WINTERFACE
15700 /**
15701 * Return statistic information on table indices (UNICODE version).
15702 * @param stmt statement handle
15703 * @param cat catalog name/pattern or NULL
15704 * @param catLen length of catalog name/pattern or SQL_NTS
15705 * @param schema schema name/pattern or NULL
15706 * @param schemaLen length of schema name/pattern or SQL_NTS
15707 * @param table table name/pattern or NULL
15708 * @param tableLen length of table name/pattern or SQL_NTS
15709 * @param itype type of index information
15710 * @param resv reserved
15711 * @result ODBC error code
15712 */
15713
15714 SQLRETURN SQL_API
SQLStatisticsW(SQLHSTMT stmt,SQLWCHAR * cat,SQLSMALLINT catLen,SQLWCHAR * schema,SQLSMALLINT schemaLen,SQLWCHAR * table,SQLSMALLINT tableLen,SQLUSMALLINT itype,SQLUSMALLINT resv)15715 SQLStatisticsW(SQLHSTMT stmt, SQLWCHAR *cat, SQLSMALLINT catLen,
15716 SQLWCHAR *schema, SQLSMALLINT schemaLen,
15717 SQLWCHAR *table, SQLSMALLINT tableLen,
15718 SQLUSMALLINT itype, SQLUSMALLINT resv)
15719 {
15720 char *c = NULL, *s = NULL, *t = NULL;
15721 SQLRETURN ret;
15722
15723 HSTMT_LOCK(stmt);
15724 if (cat) {
15725 c = uc_to_utf_c(cat, catLen);
15726 if (!c) {
15727 ret = nomem((STMT *) stmt);
15728 goto done;
15729 }
15730 }
15731 if (schema) {
15732 s = uc_to_utf_c(schema, schemaLen);
15733 if (!s) {
15734 ret = nomem((STMT *) stmt);
15735 goto done;
15736 }
15737 }
15738 if (table) {
15739 t = uc_to_utf_c(table, tableLen);
15740 if (!t) {
15741 ret = nomem((STMT *) stmt);
15742 goto done;
15743 }
15744 }
15745 ret = drvstatistics(stmt, (SQLCHAR *) c, SQL_NTS, (SQLCHAR *) s, SQL_NTS,
15746 (SQLCHAR *) t, SQL_NTS, itype, resv);
15747 done:
15748 uc_free(t);
15749 uc_free(s);
15750 uc_free(c);
15751 HSTMT_UNLOCK(stmt);
15752 return ret;
15753 }
15754 #endif
15755
15756 /**
15757 * Retrieve row data after fetch.
15758 * @param stmt statement handle
15759 * @param col column number, starting at 1
15760 * @param type output type
15761 * @param val output buffer
15762 * @param len length of output buffer
15763 * @param lenp output length
15764 * @result ODBC error code
15765 */
15766
15767 SQLRETURN SQL_API
SQLGetData(SQLHSTMT stmt,SQLUSMALLINT col,SQLSMALLINT type,SQLPOINTER val,SQLLEN len,SQLLEN * lenp)15768 SQLGetData(SQLHSTMT stmt, SQLUSMALLINT col, SQLSMALLINT type,
15769 SQLPOINTER val, SQLLEN len, SQLLEN *lenp)
15770 {
15771 STMT *s;
15772 SQLRETURN ret = SQL_ERROR;
15773
15774 HSTMT_LOCK(stmt);
15775 if (stmt == SQL_NULL_HSTMT) {
15776 return SQL_INVALID_HANDLE;
15777 }
15778 s = (STMT *) stmt;
15779 if (col == 0 && s->bkmrk != SQL_UB_OFF) {
15780 if (s->bkmrk == SQL_UB_ON && type == SQL_C_BOOKMARK) {
15781 *((SQLINTEGER *) val) = s->rowp;
15782 if (lenp) {
15783 *lenp = sizeof (SQLINTEGER);
15784 }
15785 ret = SQL_SUCCESS;
15786 goto done;
15787 } else if (s->bkmrk == SQL_UB_VARIABLE && type == SQL_C_VARBOOKMARK) {
15788 if (s->has_rowid >= 0) {
15789 char **data, *endp = 0;
15790
15791 data = s->rows + s->ncols + (s->rowp * s->ncols)
15792 + s->has_rowid;
15793 #ifdef __osf__
15794 *((sqlite4_int64 *) val) = strtol(*data, &endp, 0);
15795 #else
15796 *((sqlite4_int64 *) val) = strtoll(*data, &endp, 0);
15797 #endif
15798 } else {
15799 *((sqlite4_int64 *) val) = s->rowp;
15800 }
15801 if (lenp) {
15802 *lenp = sizeof (sqlite4_int64);
15803 }
15804 ret = SQL_SUCCESS;
15805 goto done;
15806 }
15807 }
15808 if (col < 1 || col > s->ncols) {
15809 setstat(s, -1, "invalid column", (*s->ov3) ? "07009" : "S1002");
15810 goto done;
15811 }
15812 --col;
15813 ret = getrowdata(s, col, type, val, len, lenp, 1);
15814 done:
15815 HSTMT_UNLOCK(stmt);
15816 return ret;
15817 }
15818
15819 /**
15820 * Internal: fetch and bind from statement's current row
15821 * @param s statement pointer
15822 * @param rsi rowset index
15823 * @result ODBC error code
15824 */
15825
15826 static SQLRETURN
dofetchbind(STMT * s,int rsi)15827 dofetchbind(STMT *s, int rsi)
15828 {
15829 int ret, i, withinfo = 0;
15830
15831 s->row_status0[rsi] = SQL_ROW_SUCCESS;
15832 if (s->bkmrk != SQL_UB_OFF && s->bkmrkcol.valp) {
15833 int bsize = sizeof (SQLINTEGER);
15834
15835 if (s->bkmrkcol.type == SQL_C_VARBOOKMARK) {
15836 SQLPOINTER *val;
15837
15838 if (s->bind_type != SQL_BIND_BY_COLUMN) {
15839 val = (SQLPOINTER)
15840 ((char *) s->bkmrkcol.valp + s->bind_type * rsi);
15841 } else {
15842 val = (SQLPOINTER)
15843 ((char *) s->bkmrkcol.valp + s->bkmrkcol.max * rsi);
15844 }
15845 if (s->bind_offs) {
15846 val = (SQLPOINTER) ((char *) val + *s->bind_offs);
15847 }
15848 if (s->has_rowid >= 0) {
15849 char **data, *endp = 0;
15850
15851 data = s->rows + s->ncols + (s->rowp * s->ncols)
15852 + s->has_rowid;
15853 #ifdef __osf__
15854 *(sqlite4_int64 *) val = strtol(*data, &endp, 0);
15855 #else
15856 *(sqlite4_int64 *) val = strtoll(*data, &endp, 0);
15857 #endif
15858 } else {
15859 *(sqlite4_int64 *) val = s->rowp;
15860 }
15861 bsize = sizeof (sqlite4_int64);
15862 } else {
15863 SQLINTEGER *val;
15864
15865 if (s->bind_type != SQL_BIND_BY_COLUMN) {
15866 val = (SQLINTEGER *)
15867 ((char *) s->bkmrkcol.valp + s->bind_type * rsi);
15868 } else {
15869 val = (SQLINTEGER *) s->bkmrkcol.valp + rsi;
15870 }
15871 if (s->bind_offs) {
15872 val = (SQLINTEGER *) ((char *) val + *s->bind_offs);
15873 }
15874 *val = s->rowp;
15875 }
15876 if (s->bkmrkcol.lenp) {
15877 SQLLEN *ival;
15878
15879 if (s->bind_type != SQL_BIND_BY_COLUMN) {
15880 ival = (SQLLEN *)
15881 ((char *) s->bkmrkcol.lenp + s->bind_type * rsi);
15882 } else {
15883 ival = &s->bkmrkcol.lenp[rsi];
15884 }
15885 if (s->bind_offs) {
15886 ival = (SQLLEN *) ((char *) ival + *s->bind_offs);
15887 }
15888 *ival = bsize;
15889 }
15890 }
15891 ret = SQL_SUCCESS;
15892 for (i = 0; s->bindcols && i < s->ncols; i++) {
15893 BINDCOL *b = &s->bindcols[i];
15894 SQLPOINTER dp = 0;
15895 SQLLEN *lp = 0;
15896
15897 b->offs = 0;
15898 if (b->valp) {
15899 if (s->bind_type != SQL_BIND_BY_COLUMN) {
15900 dp = (SQLPOINTER) ((char *) b->valp + s->bind_type * rsi);
15901 } else {
15902 dp = (SQLPOINTER) ((char *) b->valp + b->max * rsi);
15903 }
15904 if (s->bind_offs) {
15905 dp = (SQLPOINTER) ((char *) dp + *s->bind_offs);
15906 }
15907 }
15908 if (b->lenp) {
15909 if (s->bind_type != SQL_BIND_BY_COLUMN) {
15910 lp = (SQLLEN *) ((char *) b->lenp + s->bind_type * rsi);
15911 } else {
15912 lp = b->lenp + rsi;
15913 }
15914 if (s->bind_offs) {
15915 lp = (SQLLEN *) ((char *) lp + *s->bind_offs);
15916 }
15917 }
15918 if (dp || lp) {
15919 ret = getrowdata(s, (SQLUSMALLINT) i, b->type, dp, b->max, lp, 0);
15920 if (!SQL_SUCCEEDED(ret)) {
15921 s->row_status0[rsi] = SQL_ROW_ERROR;
15922 break;
15923 }
15924 if (ret != SQL_SUCCESS) {
15925 withinfo = 1;
15926 #ifdef SQL_ROW_SUCCESS_WITH_INFO
15927 s->row_status0[rsi] = SQL_ROW_SUCCESS_WITH_INFO;
15928 #endif
15929 }
15930 }
15931 }
15932 if (SQL_SUCCEEDED(ret)) {
15933 ret = withinfo ? SQL_SUCCESS_WITH_INFO : SQL_SUCCESS;
15934 }
15935 return ret;
15936 }
15937
15938 /**
15939 * Internal fetch function for SQLFetchScroll() and SQLExtendedFetch().
15940 * @param stmt statement handle
15941 * @param orient fetch direction
15942 * @param offset offset for fetch direction
15943 * @result ODBC error code
15944 */
15945
15946 static SQLRETURN
drvfetchscroll(SQLHSTMT stmt,SQLSMALLINT orient,SQLINTEGER offset)15947 drvfetchscroll(SQLHSTMT stmt, SQLSMALLINT orient, SQLINTEGER offset)
15948 {
15949 STMT *s;
15950 int i, withinfo = 0;
15951 SQLRETURN ret;
15952
15953 if (stmt == SQL_NULL_HSTMT) {
15954 return SQL_INVALID_HANDLE;
15955 }
15956 s = (STMT *) stmt;
15957 for (i = 0; i < s->rowset_size; i++) {
15958 s->row_status0[i] = SQL_ROW_NOROW;
15959 }
15960 if (s->row_status) {
15961 memcpy(s->row_status, s->row_status0,
15962 sizeof (SQLUSMALLINT) * s->rowset_size);
15963 }
15964 s->row_count0 = 0;
15965 if (s->row_count) {
15966 *s->row_count = s->row_count0;
15967 }
15968 if (!s->bindcols) {
15969 for (i = 0; i < s->rowset_size; i++) {
15970 s->row_status0[i] = SQL_ROW_ERROR;
15971 }
15972 ret = SQL_ERROR;
15973 i = 0;
15974 goto done2;
15975 }
15976 if (s->isselect != 1 && s->isselect != -1) {
15977 setstat(s, -1, "no result set available", "24000");
15978 ret = SQL_ERROR;
15979 i = s->nrows;
15980 goto done2;
15981 }
15982 if (s->curtype == SQL_CURSOR_FORWARD_ONLY && orient != SQL_FETCH_NEXT) {
15983 setstat(s, -1, "wrong fetch direction", "01000");
15984 ret = SQL_ERROR;
15985 i = 0;
15986 goto done2;
15987 }
15988 ret = SQL_SUCCESS;
15989 i = 0;
15990 if (((DBC *) (s->dbc))->cur_s4stmt == s && s->s4stmt) {
15991 s->rowp = s->rowprs = 0;
15992 for (; i < s->rowset_size; i++) {
15993 if (s->max_rows && s->s4stmt_rownum + 1 >= s->max_rows) {
15994 ret = (i == 0) ? SQL_NO_DATA : SQL_SUCCESS;
15995 break;
15996 }
15997 ret = s4stmt_step(s);
15998 if (ret != SQL_SUCCESS) {
15999 s->row_status0[i] = SQL_ROW_ERROR;
16000 break;
16001 }
16002 if (s->nrows < 1) {
16003 break;
16004 }
16005 ret = dofetchbind(s, i);
16006 if (!SQL_SUCCEEDED(ret)) {
16007 break;
16008 } else if (ret == SQL_SUCCESS_WITH_INFO) {
16009 withinfo = 1;
16010 }
16011 }
16012 } else if (s->rows) {
16013 switch (orient) {
16014 case SQL_FETCH_NEXT:
16015 if (s->nrows < 1) {
16016 return SQL_NO_DATA;
16017 }
16018 if (s->rowp < 0) {
16019 s->rowp = -1;
16020 }
16021 if (s->rowp >= s->nrows) {
16022 s->rowp = s->rowprs = s->nrows;
16023 return SQL_NO_DATA;
16024 }
16025 break;
16026 case SQL_FETCH_PRIOR:
16027 if (s->nrows < 1 || s->rowp <= 0) {
16028 s->rowp = s->rowprs = -1;
16029 return SQL_NO_DATA;
16030 }
16031 s->rowp -= s->rowset_size + 1;
16032 if (s->rowp < -1) {
16033 s->rowp = s->rowprs = -1;
16034 return SQL_NO_DATA;
16035 }
16036 break;
16037 case SQL_FETCH_FIRST:
16038 if (s->nrows < 1) {
16039 return SQL_NO_DATA;
16040 }
16041 s->rowp = -1;
16042 break;
16043 case SQL_FETCH_LAST:
16044 if (s->nrows < 1) {
16045 return SQL_NO_DATA;
16046 }
16047 s->rowp = s->nrows - s->rowset_size;
16048 if (--s->rowp < -1) {
16049 s->rowp = -1;
16050 }
16051 break;
16052 case SQL_FETCH_ABSOLUTE:
16053 if (offset == 0) {
16054 s->rowp = s->rowprs = -1;
16055 return SQL_NO_DATA;
16056 } else if (offset < 0) {
16057 if (0 - offset <= s->nrows) {
16058 s->rowp = s->nrows + offset - 1;
16059 break;
16060 }
16061 s->rowp = s->rowprs = -1;
16062 return SQL_NO_DATA;
16063 } else if (offset > s->nrows) {
16064 s->rowp = s->rowprs = s->nrows;
16065 return SQL_NO_DATA;
16066 }
16067 s->rowp = offset - 1 - 1;
16068 break;
16069 case SQL_FETCH_RELATIVE:
16070 if (offset >= 0) {
16071 s->rowp += offset * s->rowset_size - 1;
16072 if (s->rowp >= s->nrows) {
16073 s->rowp = s->rowprs = s->nrows;
16074 return SQL_NO_DATA;
16075 }
16076 } else {
16077 s->rowp += offset * s->rowset_size - 1;
16078 if (s->rowp < -1) {
16079 s->rowp = s->rowprs = -1;
16080 return SQL_NO_DATA;
16081 }
16082 }
16083 break;
16084 case SQL_FETCH_BOOKMARK:
16085 if (s->bkmrk == SQL_UB_ON && !s->bkmrkptr) {
16086 if (offset < 0 || offset >= s->nrows) {
16087 return SQL_NO_DATA;
16088 }
16089 s->rowp = offset - 1;
16090 break;
16091 }
16092 if (s->bkmrk != SQL_UB_OFF && s->bkmrkptr) {
16093 int rowp;
16094
16095 if (s->bkmrk == SQL_UB_VARIABLE) {
16096 if (s->has_rowid >= 0) {
16097 sqlite4_int64 bkmrk, rowid;
16098
16099 bkmrk = *(sqlite4_int64 *) s->bkmrkptr;
16100 for (rowp = 0; rowp < s->nrows; rowp++) {
16101 char **data, *endp = 0;
16102
16103 data = s->rows + s->ncols + (rowp * s->ncols)
16104 + s->has_rowid;
16105 #ifdef __osf__
16106 rowid = strtol(*data, &endp, 0);
16107 #else
16108 rowid = strtoll(*data, &endp, 0);
16109 #endif
16110 if (rowid == bkmrk) {
16111 break;
16112 }
16113 }
16114 } else {
16115 rowp = *(sqlite4_int64 *) s->bkmrkptr;
16116 }
16117 } else {
16118 rowp = *(int *) s->bkmrkptr;
16119 }
16120 if (rowp + offset < 0 || rowp + offset >= s->nrows) {
16121 return SQL_NO_DATA;
16122 }
16123 s->rowp = rowp + offset - 1;
16124 break;
16125 }
16126 /* fall through */
16127 default:
16128 s->row_status0[0] = SQL_ROW_ERROR;
16129 ret = SQL_ERROR;
16130 goto done;
16131 }
16132 s->rowprs = s->rowp + 1;
16133 for (; i < s->rowset_size; i++) {
16134 ++s->rowp;
16135 if (s->rowp < 0 || s->rowp >= s->nrows) {
16136 break;
16137 }
16138 ret = dofetchbind(s, i);
16139 if (!SQL_SUCCEEDED(ret)) {
16140 break;
16141 } else if (ret == SQL_SUCCESS_WITH_INFO) {
16142 withinfo = 1;
16143 }
16144 }
16145 }
16146 done:
16147 if (i == 0) {
16148 if (SQL_SUCCEEDED(ret)) {
16149 return SQL_NO_DATA;
16150 }
16151 return ret;
16152 }
16153 if (SQL_SUCCEEDED(ret)) {
16154 ret = withinfo ? SQL_SUCCESS_WITH_INFO : SQL_SUCCESS;
16155 }
16156 done2:
16157 if (s->row_status) {
16158 memcpy(s->row_status, s->row_status0,
16159 sizeof (SQLUSMALLINT) * s->rowset_size);
16160 }
16161 s->row_count0 = i;
16162 if (s->row_count) {
16163 *s->row_count = s->row_count0;
16164 }
16165 return ret;
16166 }
16167
16168 /**
16169 * Fetch next result row.
16170 * @param stmt statement handle
16171 * @result ODBC error code
16172 */
16173
16174 SQLRETURN SQL_API
SQLFetch(SQLHSTMT stmt)16175 SQLFetch(SQLHSTMT stmt)
16176 {
16177 SQLRETURN ret;
16178
16179 HSTMT_LOCK(stmt);
16180 ret = drvfetchscroll(stmt, SQL_FETCH_NEXT, 0);
16181 HSTMT_UNLOCK(stmt);
16182 return ret;
16183 }
16184
16185 /**
16186 * Fetch result row with scrolling.
16187 * @param stmt statement handle
16188 * @param orient fetch direction
16189 * @param offset offset for fetch direction
16190 * @result ODBC error code
16191 */
16192
16193 SQLRETURN SQL_API
SQLFetchScroll(SQLHSTMT stmt,SQLSMALLINT orient,SQLLEN offset)16194 SQLFetchScroll(SQLHSTMT stmt, SQLSMALLINT orient, SQLLEN offset)
16195 {
16196 SQLRETURN ret;
16197
16198 HSTMT_LOCK(stmt);
16199 ret = drvfetchscroll(stmt, orient, offset);
16200 HSTMT_UNLOCK(stmt);
16201 return ret;
16202 }
16203
16204 /**
16205 * Fetch result row with scrolling and row status.
16206 * @param stmt statement handle
16207 * @param orient fetch direction
16208 * @param offset offset for fetch direction
16209 * @param rowcount output number of fetched rows
16210 * @param rowstatus array for row stati
16211 * @result ODBC error code
16212 */
16213
16214 SQLRETURN SQL_API
SQLExtendedFetch(SQLHSTMT stmt,SQLUSMALLINT orient,SQLROWOFFSET offset,SQLROWSETSIZE * rowcount,SQLUSMALLINT * rowstatus)16215 SQLExtendedFetch(SQLHSTMT stmt, SQLUSMALLINT orient, SQLROWOFFSET offset,
16216 SQLROWSETSIZE *rowcount, SQLUSMALLINT *rowstatus)
16217 {
16218 STMT *s;
16219 SQLRETURN ret;
16220 SQLUSMALLINT *rst;
16221 SQLINTEGER *bkmrkptr;
16222
16223 HSTMT_LOCK(stmt);
16224 if (stmt == SQL_NULL_HSTMT) {
16225 return SQL_INVALID_HANDLE;
16226 }
16227 s = (STMT *) stmt;
16228 /* temporarily turn off SQL_ATTR_ROW_STATUS_PTR */
16229 rst = s->row_status;
16230 s->row_status = 0;
16231 bkmrkptr = s->bkmrkptr;
16232 s->bkmrkptr = 0;
16233 ret = drvfetchscroll(stmt, orient, offset);
16234 s->row_status = rst;
16235 s->bkmrkptr = bkmrkptr;
16236 if (rowstatus) {
16237 memcpy(rowstatus, s->row_status0,
16238 sizeof (SQLUSMALLINT) * s->rowset_size);
16239 }
16240 if (rowcount) {
16241 *rowcount = s->row_count0;
16242 }
16243 HSTMT_UNLOCK(stmt);
16244 return ret;
16245 }
16246
16247 /**
16248 * Return number of affected rows of HSTMT.
16249 * @param stmt statement handle
16250 * @param nrows output number of rows
16251 * @result ODBC error code
16252 */
16253
16254 SQLRETURN SQL_API
SQLRowCount(SQLHSTMT stmt,SQLLEN * nrows)16255 SQLRowCount(SQLHSTMT stmt, SQLLEN *nrows)
16256 {
16257 STMT *s;
16258
16259 HSTMT_LOCK(stmt);
16260 if (stmt == SQL_NULL_HSTMT) {
16261 return SQL_INVALID_HANDLE;
16262 }
16263 s = (STMT *) stmt;
16264 if (nrows) {
16265 *nrows = s->isselect ? 0 : s->nrows;
16266 }
16267 HSTMT_UNLOCK(stmt);
16268 return SQL_SUCCESS;
16269 }
16270
16271 /**
16272 * Return number of columns of result set given HSTMT.
16273 * @param stmt statement handle
16274 * @param ncols output number of columns
16275 * @result ODBC error code
16276 */
16277
16278 SQLRETURN SQL_API
SQLNumResultCols(SQLHSTMT stmt,SQLSMALLINT * ncols)16279 SQLNumResultCols(SQLHSTMT stmt, SQLSMALLINT *ncols)
16280 {
16281 STMT *s;
16282
16283 HSTMT_LOCK(stmt);
16284 if (stmt == SQL_NULL_HSTMT) {
16285 return SQL_INVALID_HANDLE;
16286 }
16287 s = (STMT *) stmt;
16288 if (ncols) {
16289 *ncols = s->ncols;
16290 }
16291 HSTMT_UNLOCK(stmt);
16292 return SQL_SUCCESS;
16293 }
16294
16295 /**
16296 * Internal describe column information.
16297 * @param stmt statement handle
16298 * @param col column number, starting at 1
16299 * @param name buffer for column name
16300 * @param nameMax length of name buffer
16301 * @param nameLen output length of column name
16302 * @param type output SQL type
16303 * @param size output column size
16304 * @param digits output number of digits
16305 * @param nullable output NULL allowed indicator
16306 * @result ODBC error code
16307 */
16308
16309 static SQLRETURN
drvdescribecol(SQLHSTMT stmt,SQLUSMALLINT col,SQLCHAR * name,SQLSMALLINT nameMax,SQLSMALLINT * nameLen,SQLSMALLINT * type,SQLULEN * size,SQLSMALLINT * digits,SQLSMALLINT * nullable)16310 drvdescribecol(SQLHSTMT stmt, SQLUSMALLINT col, SQLCHAR *name,
16311 SQLSMALLINT nameMax, SQLSMALLINT *nameLen,
16312 SQLSMALLINT *type, SQLULEN *size,
16313 SQLSMALLINT *digits, SQLSMALLINT *nullable)
16314 {
16315 STMT *s;
16316 COL *c;
16317 int didname = 0;
16318
16319 if (stmt == SQL_NULL_HSTMT) {
16320 return SQL_INVALID_HANDLE;
16321 }
16322 s = (STMT *) stmt;
16323 if (!s->cols) {
16324 setstat(s, -1, "no columns", (*s->ov3) ? "07009" : "S1002");
16325 return SQL_ERROR;
16326 }
16327 if (col < 1 || col > s->ncols) {
16328 setstat(s, -1, "invalid column", (*s->ov3) ? "07009" : "S1002");
16329 return SQL_ERROR;
16330 }
16331 c = s->cols + col - 1;
16332 if (name && nameMax > 0) {
16333 strncpy((char *) name, c->column, nameMax);
16334 name[nameMax - 1] = '\0';
16335 didname = 1;
16336 }
16337 if (nameLen) {
16338 if (didname) {
16339 *nameLen = strlen((char *) name);
16340 } else {
16341 *nameLen = strlen(c->column);
16342 }
16343 }
16344 if (type) {
16345 *type = c->type;
16346 #ifdef WINTERFACE
16347 if (s->nowchar[0] || s->nowchar[1]) {
16348 switch (c->type) {
16349 case SQL_WCHAR:
16350 *type = SQL_CHAR;
16351 break;
16352 case SQL_WVARCHAR:
16353 *type = SQL_VARCHAR;
16354 break;
16355 #ifdef SQL_LONGVARCHAR
16356 case SQL_WLONGVARCHAR:
16357 *type = SQL_LONGVARCHAR;
16358 break;
16359 #endif
16360 }
16361 }
16362 #endif
16363 }
16364 if (size) {
16365 *size = c->size;
16366 }
16367 if (digits) {
16368 *digits = 0;
16369 }
16370 if (nullable) {
16371 *nullable = 1;
16372 }
16373 return SQL_SUCCESS;
16374 }
16375
16376 #ifndef WINTERFACE
16377 /**
16378 * Describe column information.
16379 * @param stmt statement handle
16380 * @param col column number, starting at 1
16381 * @param name buffer for column name
16382 * @param nameMax length of name buffer
16383 * @param nameLen output length of column name
16384 * @param type output SQL type
16385 * @param size output column size
16386 * @param digits output number of digits
16387 * @param nullable output NULL allowed indicator
16388 * @result ODBC error code
16389 */
16390
16391 SQLRETURN SQL_API
SQLDescribeCol(SQLHSTMT stmt,SQLUSMALLINT col,SQLCHAR * name,SQLSMALLINT nameMax,SQLSMALLINT * nameLen,SQLSMALLINT * type,SQLULEN * size,SQLSMALLINT * digits,SQLSMALLINT * nullable)16392 SQLDescribeCol(SQLHSTMT stmt, SQLUSMALLINT col, SQLCHAR *name,
16393 SQLSMALLINT nameMax, SQLSMALLINT *nameLen,
16394 SQLSMALLINT *type, SQLULEN *size,
16395 SQLSMALLINT *digits, SQLSMALLINT *nullable)
16396 {
16397 #if defined(_WIN32) || defined(_WIN64)
16398 SQLSMALLINT len = 0;
16399 #endif
16400 SQLRETURN ret;
16401
16402 HSTMT_LOCK(stmt);
16403 #if defined(_WIN32) || defined(_WIN64)
16404 if (!((STMT *) stmt)->oemcp[0]) {
16405 ret = drvdescribecol(stmt, col, name, nameMax, nameLen,
16406 type, size, digits, nullable);
16407 goto done;
16408 }
16409 ret = drvdescribecol(stmt, col, name, nameMax,
16410 &len, type, size, digits, nullable);
16411 if (ret == SQL_SUCCESS) {
16412 if (name) {
16413 if (len > 0) {
16414 SQLCHAR *n = NULL;
16415
16416 n = (SQLCHAR *) utf_to_wmb((char *) name, len);
16417 if (n) {
16418 strncpy((char *) name, (char *) n, nameMax);
16419 n[len] = 0;
16420 len = min(nameMax, strlen((char *) n));
16421 uc_free(n);
16422 } else {
16423 len = 0;
16424 }
16425 }
16426 if (len <= 0) {
16427 len = 0;
16428 if (nameMax > 0) {
16429 name[0] = 0;
16430 }
16431 }
16432 } else {
16433 STMT *s = (STMT *) stmt;
16434 COL *c = s->cols + col - 1;
16435
16436 len = 0;
16437 if (c->column) {
16438 len = strlen(c->column);
16439 }
16440 }
16441 if (nameLen) {
16442 *nameLen = len;
16443 }
16444 }
16445 done:
16446 ;
16447 #else
16448 ret = drvdescribecol(stmt, col, name, nameMax, nameLen,
16449 type, size, digits, nullable);
16450 #endif
16451 HSTMT_UNLOCK(stmt);
16452 return ret;
16453 }
16454 #endif
16455
16456 #ifdef WINTERFACE
16457 /**
16458 * Describe column information (UNICODE version).
16459 * @param stmt statement handle
16460 * @param col column number, starting at 1
16461 * @param name buffer for column name
16462 * @param nameMax length of name buffer
16463 * @param nameLen output length of column name
16464 * @param type output SQL type
16465 * @param size output column size
16466 * @param digits output number of digits
16467 * @param nullable output NULL allowed indicator
16468 * @result ODBC error code
16469 */
16470
16471 SQLRETURN SQL_API
SQLDescribeColW(SQLHSTMT stmt,SQLUSMALLINT col,SQLWCHAR * name,SQLSMALLINT nameMax,SQLSMALLINT * nameLen,SQLSMALLINT * type,SQLULEN * size,SQLSMALLINT * digits,SQLSMALLINT * nullable)16472 SQLDescribeColW(SQLHSTMT stmt, SQLUSMALLINT col, SQLWCHAR *name,
16473 SQLSMALLINT nameMax, SQLSMALLINT *nameLen,
16474 SQLSMALLINT *type, SQLULEN *size,
16475 SQLSMALLINT *digits, SQLSMALLINT *nullable)
16476 {
16477 SQLRETURN ret;
16478 SQLSMALLINT len = 0;
16479
16480 HSTMT_LOCK(stmt);
16481 ret = drvdescribecol(stmt, col, (SQLCHAR *) name,
16482 (SQLSMALLINT) (nameMax * sizeof (SQLWCHAR)),
16483 &len, type, size, digits, nullable);
16484 if (ret == SQL_SUCCESS) {
16485 if (name) {
16486 if (len > 0) {
16487 SQLWCHAR *n = NULL;
16488
16489 n = uc_from_utf((SQLCHAR *) name, len);
16490 if (n) {
16491 uc_strncpy(name, n, nameMax);
16492 n[len] = 0;
16493 len = min(nameMax, uc_strlen(n));
16494 uc_free(n);
16495 } else {
16496 len = 0;
16497 }
16498 }
16499 if (len <= 0) {
16500 len = 0;
16501 if (nameMax > 0) {
16502 name[0] = 0;
16503 }
16504 }
16505 } else {
16506 STMT *s = (STMT *) stmt;
16507 COL *c = s->cols + col - 1;
16508
16509 len = 0;
16510 if (c->column) {
16511 len = strlen(c->column);
16512 }
16513 }
16514 if (nameLen) {
16515 *nameLen = len;
16516 }
16517 }
16518 HSTMT_UNLOCK(stmt);
16519 return ret;
16520 }
16521 #endif
16522
16523 /**
16524 * Internal retrieve column attributes.
16525 * @param stmt statement handle
16526 * @param col column number, starting at 1
16527 * @param id attribute id
16528 * @param val output buffer
16529 * @param valMax length of output buffer
16530 * @param valLen output length
16531 * @param val2 integer output buffer
16532 * @result ODBC error code
16533 */
16534
16535 static SQLRETURN
drvcolattributes(SQLHSTMT stmt,SQLUSMALLINT col,SQLUSMALLINT id,SQLPOINTER val,SQLSMALLINT valMax,SQLSMALLINT * valLen,SQLLEN * val2)16536 drvcolattributes(SQLHSTMT stmt, SQLUSMALLINT col, SQLUSMALLINT id,
16537 SQLPOINTER val, SQLSMALLINT valMax, SQLSMALLINT *valLen,
16538 SQLLEN *val2)
16539 {
16540 STMT *s;
16541 COL *c;
16542 SQLSMALLINT dummy;
16543 char *valc = (char *) val;
16544
16545 if (stmt == SQL_NULL_HSTMT) {
16546 return SQL_INVALID_HANDLE;
16547 }
16548 s = (STMT *) stmt;
16549 if (!s->cols) {
16550 return SQL_ERROR;
16551 }
16552 if (!valLen) {
16553 valLen = &dummy;
16554 }
16555 if (id == SQL_COLUMN_COUNT) {
16556 if (val2) {
16557 *val2 = s->ncols;
16558 }
16559 *valLen = sizeof (int);
16560 return SQL_SUCCESS;
16561 }
16562 if (id == SQL_COLUMN_TYPE && col == 0) {
16563 if (val2) {
16564 *val2 = SQL_INTEGER;
16565 }
16566 *valLen = sizeof (int);
16567 return SQL_SUCCESS;
16568 }
16569 #ifdef SQL_DESC_OCTET_LENGTH
16570 if (id == SQL_DESC_OCTET_LENGTH && col == 0) {
16571 if (val2) {
16572 *val2 = 4;
16573 }
16574 *valLen = sizeof (int);
16575 return SQL_SUCCESS;
16576 }
16577 #endif
16578 if (col < 1 || col > s->ncols) {
16579 setstat(s, -1, "invalid column", (*s->ov3) ? "07009": "S1002");
16580 return SQL_ERROR;
16581 }
16582 c = s->cols + col - 1;
16583
16584 switch (id) {
16585 case SQL_COLUMN_LABEL:
16586 if (c->label) {
16587 if (valc && valMax > 0) {
16588 strncpy(valc, c->label, valMax);
16589 valc[valMax - 1] = '\0';
16590 }
16591 *valLen = strlen(c->label);
16592 goto checkLen;
16593 }
16594 /* fall through */
16595 case SQL_COLUMN_NAME:
16596 case SQL_DESC_NAME:
16597 if (valc && valMax > 0) {
16598 strncpy(valc, c->column, valMax);
16599 valc[valMax - 1] = '\0';
16600 }
16601 *valLen = strlen(c->column);
16602 checkLen:
16603 if (*valLen >= valMax) {
16604 setstat(s, -1, "data right truncated", "01004");
16605 return SQL_SUCCESS_WITH_INFO;
16606 }
16607 return SQL_SUCCESS;
16608 #ifdef SQL_DESC_BASE_COLUMN_NAME
16609 case SQL_DESC_BASE_COLUMN_NAME:
16610 if (strchr(c->column, '(') || strchr(c->column, ')')) {
16611 if (valc && valMax > 0) {
16612 valc[0] = '\0';
16613 }
16614 *valLen = 0;
16615 } else if (valc && valMax > 0) {
16616 strncpy(valc, c->column, valMax);
16617 valc[valMax - 1] = '\0';
16618 *valLen = strlen(c->column);
16619 }
16620 goto checkLen;
16621 #endif
16622 case SQL_COLUMN_TYPE:
16623 case SQL_DESC_TYPE:
16624 #ifdef WINTERFACE
16625 {
16626 int type = c->type;
16627
16628 if (s->nowchar[0] || s->nowchar[1]) {
16629 switch (type) {
16630 case SQL_WCHAR:
16631 type = SQL_CHAR;
16632 break;
16633 case SQL_WVARCHAR:
16634 type = SQL_VARCHAR;
16635 break;
16636 #ifdef SQL_LONGVARCHAR
16637 case SQL_WLONGVARCHAR:
16638 type = SQL_LONGVARCHAR;
16639 break;
16640 }
16641 }
16642 if (val2) {
16643 *val2 = type;
16644 }
16645 #endif
16646 }
16647 #else
16648 if (val2) {
16649 *val2 = c->type;
16650 }
16651 #endif
16652 *valLen = sizeof (int);
16653 return SQL_SUCCESS;
16654 case SQL_COLUMN_DISPLAY_SIZE:
16655 if (val2) {
16656 *val2 = c->size;
16657 }
16658 *valLen = sizeof (int);
16659 return SQL_SUCCESS;
16660 case SQL_COLUMN_UNSIGNED:
16661 if (val2) {
16662 *val2 = c->nosign ? SQL_TRUE : SQL_FALSE;
16663 }
16664 *valLen = sizeof (int);
16665 return SQL_SUCCESS;
16666 case SQL_COLUMN_SCALE:
16667 case SQL_DESC_SCALE:
16668 if (val2) {
16669 *val2 = c->scale;
16670 }
16671 *valLen = sizeof (int);
16672 return SQL_SUCCESS;
16673 case SQL_COLUMN_PRECISION:
16674 case SQL_DESC_PRECISION:
16675 if (val2) {
16676 switch (c->type) {
16677 case SQL_SMALLINT:
16678 *val2 = 5;
16679 break;
16680 case SQL_INTEGER:
16681 *val2 = 10;
16682 break;
16683 case SQL_FLOAT:
16684 case SQL_REAL:
16685 case SQL_DOUBLE:
16686 *val2 = 15;
16687 break;
16688 case SQL_DATE:
16689 *val2 = 0;
16690 break;
16691 case SQL_TIME:
16692 *val2 = 0;
16693 break;
16694 #ifdef SQL_TYPE_TIMESTAMP
16695 case SQL_TYPE_TIMESTAMP:
16696 #endif
16697 case SQL_TIMESTAMP:
16698 *val2 = (c->prec >= 0 && c->prec <= 3) ? c->prec : 3;
16699 break;
16700 default:
16701 *val2 = c->prec;
16702 break;
16703 }
16704 }
16705 *valLen = sizeof (int);
16706 return SQL_SUCCESS;
16707 case SQL_COLUMN_MONEY:
16708 if (val2) {
16709 *val2 = SQL_FALSE;
16710 }
16711 *valLen = sizeof (int);
16712 return SQL_SUCCESS;
16713 case SQL_COLUMN_AUTO_INCREMENT:
16714 if (val2) {
16715 *val2 = c->autoinc;
16716 }
16717 *valLen = sizeof (int);
16718 return SQL_SUCCESS;
16719 case SQL_COLUMN_LENGTH:
16720 case SQL_DESC_LENGTH:
16721 if (val2) {
16722 *val2 = c->size;
16723 }
16724 *valLen = sizeof (int);
16725 return SQL_SUCCESS;
16726 case SQL_COLUMN_NULLABLE:
16727 case SQL_DESC_NULLABLE:
16728 if (val2) {
16729 *val2 = c->notnull;
16730 }
16731 *valLen = sizeof (int);
16732 return SQL_SUCCESS;
16733 case SQL_COLUMN_SEARCHABLE:
16734 if (val2) {
16735 *val2 = SQL_SEARCHABLE;
16736 }
16737 *valLen = sizeof (int);
16738 return SQL_SUCCESS;
16739 case SQL_COLUMN_CASE_SENSITIVE:
16740 if (val2) {
16741 *val2 = SQL_TRUE;
16742 }
16743 *valLen = sizeof (int);
16744 return SQL_SUCCESS;
16745 case SQL_COLUMN_UPDATABLE:
16746 if (val2) {
16747 *val2 = SQL_TRUE;
16748 }
16749 *valLen = sizeof (int);
16750 return SQL_SUCCESS;
16751 case SQL_DESC_COUNT:
16752 if (val2) {
16753 *val2 = s->ncols;
16754 }
16755 *valLen = sizeof (int);
16756 return SQL_SUCCESS;
16757 case SQL_COLUMN_TYPE_NAME: {
16758 char *p = NULL, *tn = c->typename ? c->typename : "varchar";
16759
16760 #ifdef WINTERFACE
16761 if (c->type == SQL_WCHAR ||
16762 c->type == SQL_WVARCHAR ||
16763 c->type == SQL_WLONGVARCHAR) {
16764 if (!(s->nowchar[0] || s->nowchar[1])) {
16765 if (strcasecmp(tn, "varchar") == 0) {
16766 tn = "wvarchar";
16767 }
16768 }
16769 }
16770 #endif
16771 if (valc && valMax > 0) {
16772 strncpy(valc, tn, valMax);
16773 valc[valMax - 1] = '\0';
16774 p = strchr(valc, '(');
16775 if (p) {
16776 *p = '\0';
16777 while (p > valc && ISSPACE(p[-1])) {
16778 --p;
16779 *p = '\0';
16780 }
16781 }
16782 *valLen = strlen(valc);
16783 } else {
16784 *valLen = strlen(tn);
16785 p = strchr(tn, '(');
16786 if (p) {
16787 *valLen = p - tn;
16788 while (p > tn && ISSPACE(p[-1])) {
16789 --p;
16790 *valLen -= 1;
16791 }
16792 }
16793 }
16794 goto checkLen;
16795 }
16796 case SQL_COLUMN_OWNER_NAME:
16797 case SQL_COLUMN_QUALIFIER_NAME: {
16798 char *z = "";
16799
16800 if (valc && valMax > 0) {
16801 strncpy(valc, z, valMax);
16802 valc[valMax - 1] = '\0';
16803 }
16804 *valLen = strlen(z);
16805 goto checkLen;
16806 }
16807 case SQL_COLUMN_TABLE_NAME:
16808 #if (SQL_COLUMN_TABLE_NAME != SQL_DESC_TABLE_NAME)
16809 case SQL_DESC_TABLE_NAME:
16810 #endif
16811 #ifdef SQL_DESC_BASE_TABLE_NAME
16812 case SQL_DESC_BASE_TABLE_NAME:
16813 #endif
16814 if (valc && valMax > 0) {
16815 strncpy(valc, c->table, valMax);
16816 valc[valMax - 1] = '\0';
16817 }
16818 *valLen = strlen(c->table);
16819 goto checkLen;
16820 #ifdef SQL_DESC_NUM_PREC_RADIX
16821 case SQL_DESC_NUM_PREC_RADIX:
16822 if (val2) {
16823 switch (c->type) {
16824 #ifdef WINTERFACE
16825 case SQL_WCHAR:
16826 case SQL_WVARCHAR:
16827 #ifdef SQL_LONGVARCHAR
16828 case SQL_WLONGVARCHAR:
16829 #endif
16830 #endif
16831 case SQL_CHAR:
16832 case SQL_VARCHAR:
16833 #ifdef SQL_LONGVARCHAR
16834 case SQL_LONGVARCHAR:
16835 #endif
16836 case SQL_BINARY:
16837 case SQL_VARBINARY:
16838 case SQL_LONGVARBINARY:
16839 *val2 = 0;
16840 break;
16841 default:
16842 *val2 = 2;
16843 }
16844 }
16845 *valLen = sizeof (int);
16846 return SQL_SUCCESS;
16847 #endif
16848 }
16849 setstat(s, -1, "unsupported column attributes %d", "HY091", id);
16850 return SQL_ERROR;
16851 }
16852
16853 #ifndef WINTERFACE
16854 /**
16855 * Retrieve column attributes.
16856 * @param stmt statement handle
16857 * @param col column number, starting at 1
16858 * @param id attribute id
16859 * @param val output buffer
16860 * @param valMax length of output buffer
16861 * @param valLen output length
16862 * @param val2 integer output buffer
16863 * @result ODBC error code
16864 */
16865
16866 SQLRETURN SQL_API
SQLColAttributes(SQLHSTMT stmt,SQLUSMALLINT col,SQLUSMALLINT id,SQLPOINTER val,SQLSMALLINT valMax,SQLSMALLINT * valLen,SQLLEN * val2)16867 SQLColAttributes(SQLHSTMT stmt, SQLUSMALLINT col, SQLUSMALLINT id,
16868 SQLPOINTER val, SQLSMALLINT valMax, SQLSMALLINT *valLen,
16869 SQLLEN *val2)
16870 {
16871 #if defined(_WIN32) || defined(_WIN64)
16872 SQLSMALLINT len = 0;
16873 #endif
16874 SQLRETURN ret;
16875
16876 HSTMT_LOCK(stmt);
16877 #if defined(_WIN32) || defined(_WIN64)
16878 if (!((STMT *) stmt)->oemcp[0]) {
16879 ret = drvcolattributes(stmt, col, id, val, valMax, valLen, val2);
16880 goto done;
16881 }
16882 ret = drvcolattributes(stmt, col, id, val, valMax, &len, val2);
16883 if (SQL_SUCCEEDED(ret)) {
16884 char *v = NULL;
16885
16886 switch (id) {
16887 case SQL_COLUMN_LABEL:
16888 case SQL_COLUMN_NAME:
16889 case SQL_DESC_NAME:
16890 case SQL_COLUMN_TYPE_NAME:
16891 case SQL_COLUMN_OWNER_NAME:
16892 case SQL_COLUMN_QUALIFIER_NAME:
16893 case SQL_COLUMN_TABLE_NAME:
16894 #if (SQL_COLUMN_TABLE_NAME != SQL_DESC_TABLE_NAME)
16895 case SQL_DESC_TABLE_NAME:
16896 #endif
16897 #ifdef SQL_DESC_BASE_COLUMN_NAME
16898 case SQL_DESC_BASE_COLUMN_NAME:
16899 #endif
16900 #ifdef SQL_DESC_BASE_TABLE_NAME
16901 case SQL_DESC_BASE_TABLE_NAME:
16902 #endif
16903 if (val && valMax > 0) {
16904 int vmax = valMax;
16905
16906 v = utf_to_wmb((char *) val, SQL_NTS);
16907 if (v) {
16908 strncpy(val, v, vmax);
16909 len = min(vmax, strlen(v));
16910 uc_free(v);
16911 }
16912 if (vmax > 0) {
16913 v = (char *) val;
16914 v[vmax - 1] = '\0';
16915 }
16916 }
16917 if (len <= 0) {
16918 len = 0;
16919 }
16920 break;
16921 }
16922 if (valLen) {
16923 *valLen = len;
16924 }
16925 }
16926 done:
16927 ;
16928 #else
16929 ret = drvcolattributes(stmt, col, id, val, valMax, valLen, val2);
16930 #endif
16931 HSTMT_UNLOCK(stmt);
16932 return ret;
16933 }
16934 #endif
16935
16936 #ifdef WINTERFACE
16937 /**
16938 * Retrieve column attributes (UNICODE version).
16939 * @param stmt statement handle
16940 * @param col column number, starting at 1
16941 * @param id attribute id
16942 * @param val output buffer
16943 * @param valMax length of output buffer
16944 * @param valLen output length
16945 * @param val2 integer output buffer
16946 * @result ODBC error code
16947 */
16948
16949 SQLRETURN SQL_API
SQLColAttributesW(SQLHSTMT stmt,SQLUSMALLINT col,SQLUSMALLINT id,SQLPOINTER val,SQLSMALLINT valMax,SQLSMALLINT * valLen,SQLLEN * val2)16950 SQLColAttributesW(SQLHSTMT stmt, SQLUSMALLINT col, SQLUSMALLINT id,
16951 SQLPOINTER val, SQLSMALLINT valMax, SQLSMALLINT *valLen,
16952 SQLLEN *val2)
16953 {
16954 SQLRETURN ret;
16955 SQLSMALLINT len = 0;
16956
16957 HSTMT_LOCK(stmt);
16958 ret = drvcolattributes(stmt, col, id, val, valMax, &len, val2);
16959 if (SQL_SUCCEEDED(ret)) {
16960 SQLWCHAR *v = NULL;
16961
16962 switch (id) {
16963 case SQL_COLUMN_LABEL:
16964 case SQL_COLUMN_NAME:
16965 case SQL_DESC_NAME:
16966 case SQL_COLUMN_TYPE_NAME:
16967 case SQL_COLUMN_OWNER_NAME:
16968 case SQL_COLUMN_QUALIFIER_NAME:
16969 case SQL_COLUMN_TABLE_NAME:
16970 #if (SQL_COLUMN_TABLE_NAME != SQL_DESC_TABLE_NAME)
16971 case SQL_DESC_TABLE_NAME:
16972 #endif
16973 #ifdef SQL_DESC_BASE_COLUMN_NAME
16974 case SQL_DESC_BASE_COLUMN_NAME:
16975 #endif
16976 #ifdef SQL_DESC_BASE_TABLE_NAME
16977 case SQL_DESC_BASE_TABLE_NAME:
16978 #endif
16979 if (val && valMax > 0) {
16980 int vmax = valMax / sizeof (SQLWCHAR);
16981
16982 v = uc_from_utf((SQLCHAR *) val, SQL_NTS);
16983 if (v) {
16984 uc_strncpy(val, v, vmax);
16985 len = min(vmax, uc_strlen(v));
16986 uc_free(v);
16987 len *= sizeof (SQLWCHAR);
16988 }
16989 if (vmax > 0) {
16990 v = (SQLWCHAR *) val;
16991 v[vmax - 1] = '\0';
16992 }
16993 }
16994 if (len <= 0) {
16995 len = 0;
16996 }
16997 break;
16998 }
16999 if (valLen) {
17000 *valLen = len;
17001 }
17002 }
17003 HSTMT_UNLOCK(stmt);
17004 return ret;
17005 }
17006 #endif
17007
17008 /**
17009 * Internal retrieve column attributes.
17010 * @param stmt statement handle
17011 * @param col column number, starting at 1
17012 * @param id attribute id
17013 * @param val output buffer
17014 * @param valMax length of output buffer
17015 * @param valLen output length
17016 * @param val2 integer output buffer
17017 * @result ODBC error code
17018 */
17019
17020 static SQLRETURN
drvcolattribute(SQLHSTMT stmt,SQLUSMALLINT col,SQLUSMALLINT id,SQLPOINTER val,SQLSMALLINT valMax,SQLSMALLINT * valLen,SQLPOINTER val2)17021 drvcolattribute(SQLHSTMT stmt, SQLUSMALLINT col, SQLUSMALLINT id,
17022 SQLPOINTER val, SQLSMALLINT valMax, SQLSMALLINT *valLen,
17023 SQLPOINTER val2)
17024 {
17025 STMT *s;
17026 COL *c;
17027 int v = 0;
17028 char *valc = (char *) val;
17029 SQLSMALLINT dummy;
17030
17031 if (stmt == SQL_NULL_HSTMT) {
17032 return SQL_INVALID_HANDLE;
17033 }
17034 s = (STMT *) stmt;
17035 if (!s->cols) {
17036 return SQL_ERROR;
17037 }
17038 if (col < 1 || col > s->ncols) {
17039 setstat(s, -1, "invalid column", (*s->ov3) ? "07009" : "S1002");
17040 return SQL_ERROR;
17041 }
17042 if (!valLen) {
17043 valLen = &dummy;
17044 }
17045 c = s->cols + col - 1;
17046 switch (id) {
17047 case SQL_DESC_COUNT:
17048 v = s->ncols;
17049 break;
17050 case SQL_DESC_CATALOG_NAME:
17051 if (valc && valMax > 0) {
17052 strncpy(valc, c->db, valMax);
17053 valc[valMax - 1] = '\0';
17054 }
17055 *valLen = strlen(c->db);
17056 checkLen:
17057 if (*valLen >= valMax) {
17058 setstat(s, -1, "data right truncated", "01004");
17059 return SQL_SUCCESS_WITH_INFO;
17060 }
17061 break;
17062 case SQL_COLUMN_LENGTH:
17063 case SQL_DESC_LENGTH:
17064 v = c->size;
17065 break;
17066 case SQL_COLUMN_LABEL:
17067 if (c->label) {
17068 if (valc && valMax > 0) {
17069 strncpy(valc, c->label, valMax);
17070 valc[valMax - 1] = '\0';
17071 }
17072 *valLen = strlen(c->label);
17073 goto checkLen;
17074 }
17075 /* fall through */
17076 case SQL_COLUMN_NAME:
17077 case SQL_DESC_NAME:
17078 if (valc && valMax > 0) {
17079 strncpy(valc, c->column, valMax);
17080 valc[valMax - 1] = '\0';
17081 }
17082 *valLen = strlen(c->column);
17083 goto checkLen;
17084 case SQL_DESC_SCHEMA_NAME: {
17085 char *z = "";
17086
17087 if (valc && valMax > 0) {
17088 strncpy(valc, z, valMax);
17089 valc[valMax - 1] = '\0';
17090 }
17091 *valLen = strlen(z);
17092 goto checkLen;
17093 }
17094 #ifdef SQL_DESC_BASE_COLUMN_NAME
17095 case SQL_DESC_BASE_COLUMN_NAME:
17096 if (strchr(c->column, '(') || strchr(c->column, ')')) {
17097 valc[0] = '\0';
17098 *valLen = 0;
17099 } else if (valc && valMax > 0) {
17100 strncpy(valc, c->column, valMax);
17101 valc[valMax - 1] = '\0';
17102 *valLen = strlen(c->column);
17103 }
17104 goto checkLen;
17105 #endif
17106 case SQL_DESC_TYPE_NAME: {
17107 char *p = NULL, *tn = c->typename ? c->typename : "varchar";
17108
17109 #ifdef WINTERFACE
17110 if (c->type == SQL_WCHAR ||
17111 c->type == SQL_WVARCHAR ||
17112 c->type == SQL_WLONGVARCHAR) {
17113 if (!(s->nowchar[0] || s->nowchar[1])) {
17114 if (strcasecmp(tn, "varchar") == 0) {
17115 tn = "wvarchar";
17116 }
17117 }
17118 }
17119 #endif
17120 if (valc && valMax > 0) {
17121 strncpy(valc, tn, valMax);
17122 valc[valMax - 1] = '\0';
17123 p = strchr(valc, '(');
17124 if (p) {
17125 *p = '\0';
17126 while (p > valc && ISSPACE(p[-1])) {
17127 --p;
17128 *p = '\0';
17129 }
17130 }
17131 *valLen = strlen(valc);
17132 } else {
17133 *valLen = strlen(tn);
17134 p = strchr(tn, '(');
17135 if (p) {
17136 *valLen = p - tn;
17137 while (p > tn && ISSPACE(p[-1])) {
17138 --p;
17139 *valLen -= 1;
17140 }
17141 }
17142 }
17143 goto checkLen;
17144 }
17145 case SQL_DESC_OCTET_LENGTH:
17146 v = c->size;
17147 #ifdef WINTERFACE
17148 if (c->type == SQL_WCHAR ||
17149 c->type == SQL_WVARCHAR ||
17150 c->type == SQL_WLONGVARCHAR) {
17151 if (!(s->nowchar[0] || s->nowchar[1])) {
17152 v *= sizeof (SQLWCHAR);
17153 }
17154 }
17155 #endif
17156 break;
17157 #if (SQL_COLUMN_TABLE_NAME != SQL_DESC_TABLE_NAME)
17158 case SQL_COLUMN_TABLE_NAME:
17159 #endif
17160 #ifdef SQL_DESC_BASE_TABLE_NAME
17161 case SQL_DESC_BASE_TABLE_NAME:
17162 #endif
17163 case SQL_DESC_TABLE_NAME:
17164 if (valc && valMax > 0) {
17165 strncpy(valc, c->table, valMax);
17166 valc[valMax - 1] = '\0';
17167 }
17168 *valLen = strlen(c->table);
17169 goto checkLen;
17170 case SQL_DESC_TYPE:
17171 v = c->type;
17172 #ifdef WINTERFACE
17173 if (s->nowchar[0] || s->nowchar[1]) {
17174 switch (v) {
17175 case SQL_WCHAR:
17176 v = SQL_CHAR;
17177 break;
17178 case SQL_WVARCHAR:
17179 v = SQL_VARCHAR;
17180 break;
17181 #ifdef SQL_LONGVARCHAR
17182 case SQL_WLONGVARCHAR:
17183 v = SQL_LONGVARCHAR;
17184 break;
17185 #endif
17186 }
17187 }
17188 #endif
17189 break;
17190 case SQL_DESC_CONCISE_TYPE:
17191 switch (c->type) {
17192 case SQL_INTEGER:
17193 v = SQL_C_LONG;
17194 break;
17195 case SQL_TINYINT:
17196 v = SQL_C_TINYINT;
17197 break;
17198 case SQL_SMALLINT:
17199 v = SQL_C_SHORT;
17200 break;
17201 case SQL_FLOAT:
17202 v = SQL_C_FLOAT;
17203 break;
17204 case SQL_DOUBLE:
17205 v = SQL_C_DOUBLE;
17206 break;
17207 case SQL_TIMESTAMP:
17208 v = SQL_C_TIMESTAMP;
17209 break;
17210 case SQL_TIME:
17211 v = SQL_C_TIME;
17212 break;
17213 case SQL_DATE:
17214 v = SQL_C_DATE;
17215 break;
17216 #ifdef SQL_C_TYPE_TIMESTAMP
17217 case SQL_TYPE_TIMESTAMP:
17218 v = SQL_C_TYPE_TIMESTAMP;
17219 break;
17220 #endif
17221 #ifdef SQL_C_TYPE_TIME
17222 case SQL_TYPE_TIME:
17223 v = SQL_C_TYPE_TIME;
17224 break;
17225 #endif
17226 #ifdef SQL_C_TYPE_DATE
17227 case SQL_TYPE_DATE:
17228 v = SQL_C_TYPE_DATE;
17229 break;
17230 #endif
17231 #ifdef SQL_BIT
17232 case SQL_BIT:
17233 v = SQL_C_BIT;
17234 break;
17235 #endif
17236 #ifdef SQL_BIGINT
17237 case SQL_BIGINT:
17238 v = SQL_C_SBIGINT;
17239 break;
17240 #endif
17241 default:
17242 #ifdef WINTERFACE
17243 v = (s->nowchar[0] || s->nowchar[1]) ? SQL_C_CHAR : SQL_C_WCHAR;
17244 #else
17245 v = SQL_C_CHAR;
17246 #endif
17247 break;
17248 }
17249 break;
17250 case SQL_DESC_UPDATABLE:
17251 v = SQL_TRUE;
17252 break;
17253 case SQL_COLUMN_DISPLAY_SIZE:
17254 v = c->size;
17255 break;
17256 case SQL_COLUMN_UNSIGNED:
17257 v = c->nosign ? SQL_TRUE : SQL_FALSE;
17258 break;
17259 case SQL_COLUMN_SEARCHABLE:
17260 v = SQL_SEARCHABLE;
17261 break;
17262 case SQL_COLUMN_SCALE:
17263 case SQL_DESC_SCALE:
17264 v = c->scale;
17265 break;
17266 case SQL_COLUMN_PRECISION:
17267 case SQL_DESC_PRECISION:
17268 switch (c->type) {
17269 case SQL_SMALLINT:
17270 v = 5;
17271 break;
17272 case SQL_INTEGER:
17273 v = 10;
17274 break;
17275 case SQL_FLOAT:
17276 case SQL_REAL:
17277 case SQL_DOUBLE:
17278 v = 15;
17279 break;
17280 case SQL_DATE:
17281 v = 0;
17282 break;
17283 case SQL_TIME:
17284 v = 0;
17285 break;
17286 #ifdef SQL_TYPE_TIMESTAMP
17287 case SQL_TYPE_TIMESTAMP:
17288 #endif
17289 case SQL_TIMESTAMP:
17290 v = (c->prec >= 0 && c->prec <= 3) ? c->prec : 3;
17291 break;
17292 default:
17293 v = c->prec;
17294 break;
17295 }
17296 break;
17297 case SQL_COLUMN_MONEY:
17298 v = SQL_FALSE;
17299 break;
17300 case SQL_COLUMN_AUTO_INCREMENT:
17301 v = c->autoinc;
17302 break;
17303 case SQL_DESC_NULLABLE:
17304 v = c->notnull;
17305 break;
17306 #ifdef SQL_DESC_NUM_PREC_RADIX
17307 case SQL_DESC_NUM_PREC_RADIX:
17308 switch (c->type) {
17309 #ifdef WINTERFACE
17310 case SQL_WCHAR:
17311 case SQL_WVARCHAR:
17312 #ifdef SQL_LONGVARCHAR
17313 case SQL_WLONGVARCHAR:
17314 #endif
17315 #endif
17316 case SQL_CHAR:
17317 case SQL_VARCHAR:
17318 #ifdef SQL_LONGVARCHAR
17319 case SQL_LONGVARCHAR:
17320 #endif
17321 case SQL_BINARY:
17322 case SQL_VARBINARY:
17323 case SQL_LONGVARBINARY:
17324 v = 0;
17325 break;
17326 default:
17327 v = 2;
17328 }
17329 break;
17330 #endif
17331 default:
17332 setstat(s, -1, "unsupported column attribute %d", "HY091", id);
17333 return SQL_ERROR;
17334 }
17335 if (val2) {
17336 *(SQLLEN *) val2 = v;
17337 }
17338 return SQL_SUCCESS;
17339 }
17340
17341 #ifndef WINTERFACE
17342 /**
17343 * Retrieve column attributes.
17344 * @param stmt statement handle
17345 * @param col column number, starting at 1
17346 * @param id attribute id
17347 * @param val output buffer
17348 * @param valMax length of output buffer
17349 * @param valLen output length
17350 * @param val2 integer output buffer
17351 * @result ODBC error code
17352 */
17353
17354 SQLRETURN SQL_API
SQLColAttribute(SQLHSTMT stmt,SQLUSMALLINT col,SQLUSMALLINT id,SQLPOINTER val,SQLSMALLINT valMax,SQLSMALLINT * valLen,COLATTRIBUTE_LAST_ARG_TYPE val2)17355 SQLColAttribute(SQLHSTMT stmt, SQLUSMALLINT col, SQLUSMALLINT id,
17356 SQLPOINTER val, SQLSMALLINT valMax, SQLSMALLINT *valLen,
17357 COLATTRIBUTE_LAST_ARG_TYPE val2)
17358 {
17359 #if defined(_WIN32) || defined(_WIN64)
17360 SQLSMALLINT len = 0;
17361 #endif
17362 SQLRETURN ret;
17363
17364 HSTMT_LOCK(stmt);
17365 #if defined(_WIN32) || defined(_WIN64)
17366 if (!((STMT *) stmt)->oemcp[0]) {
17367 ret = drvcolattribute(stmt, col, id, val, valMax, valLen,
17368 (SQLPOINTER) val2);
17369 goto done;
17370 }
17371 ret = drvcolattribute(stmt, col, id, val, valMax, &len,
17372 (SQLPOINTER) val2);
17373 if (SQL_SUCCEEDED(ret)) {
17374 char *v = NULL;
17375
17376 switch (id) {
17377 case SQL_DESC_SCHEMA_NAME:
17378 case SQL_DESC_CATALOG_NAME:
17379 case SQL_COLUMN_LABEL:
17380 case SQL_DESC_NAME:
17381 case SQL_DESC_TABLE_NAME:
17382 #ifdef SQL_DESC_BASE_TABLE_NAME
17383 case SQL_DESC_BASE_TABLE_NAME:
17384 #endif
17385 #ifdef SQL_DESC_BASE_COLUMN_NAME
17386 case SQL_DESC_BASE_COLUMN_NAME:
17387 #endif
17388 case SQL_DESC_TYPE_NAME:
17389 if (val && valMax > 0) {
17390 int vmax = valMax;
17391
17392 v = utf_to_wmb((char *) val, SQL_NTS);
17393 if (v) {
17394 strncpy(val, v, vmax);
17395 len = min(vmax, strlen(v));
17396 uc_free(v);
17397 }
17398 if (vmax > 0) {
17399 v = (char *) val;
17400 v[vmax - 1] = '\0';
17401 }
17402 }
17403 if (len <= 0) {
17404 len = 0;
17405 }
17406 break;
17407 }
17408 if (valLen) {
17409 *valLen = len;
17410 }
17411 }
17412 done:
17413 ;
17414 #else
17415 ret = drvcolattribute(stmt, col, id, val, valMax, valLen,
17416 (SQLPOINTER) val2);
17417 #endif
17418 HSTMT_UNLOCK(stmt);
17419 return ret;
17420 }
17421 #endif
17422
17423 #ifdef WINTERFACE
17424 /**
17425 * Retrieve column attributes (UNICODE version).
17426 * @param stmt statement handle
17427 * @param col column number, starting at 1
17428 * @param id attribute id
17429 * @param val output buffer
17430 * @param valMax length of output buffer
17431 * @param valLen output length
17432 * @param val2 integer output buffer
17433 * @result ODBC error code
17434 */
17435
17436 SQLRETURN SQL_API
SQLColAttributeW(SQLHSTMT stmt,SQLUSMALLINT col,SQLUSMALLINT id,SQLPOINTER val,SQLSMALLINT valMax,SQLSMALLINT * valLen,COLATTRIBUTE_LAST_ARG_TYPE val2)17437 SQLColAttributeW(SQLHSTMT stmt, SQLUSMALLINT col, SQLUSMALLINT id,
17438 SQLPOINTER val, SQLSMALLINT valMax, SQLSMALLINT *valLen,
17439 COLATTRIBUTE_LAST_ARG_TYPE val2)
17440 {
17441 SQLRETURN ret;
17442 SQLSMALLINT len = 0;
17443
17444 HSTMT_LOCK(stmt);
17445 ret = drvcolattribute(stmt, col, id, val, valMax, &len,
17446 (SQLPOINTER) val2);
17447 if (SQL_SUCCEEDED(ret)) {
17448 SQLWCHAR *v = NULL;
17449
17450 switch (id) {
17451 case SQL_DESC_SCHEMA_NAME:
17452 case SQL_DESC_CATALOG_NAME:
17453 case SQL_COLUMN_LABEL:
17454 case SQL_DESC_NAME:
17455 case SQL_DESC_TABLE_NAME:
17456 #ifdef SQL_DESC_BASE_TABLE_NAME
17457 case SQL_DESC_BASE_TABLE_NAME:
17458 #endif
17459 #ifdef SQL_DESC_BASE_COLUMN_NAME
17460 case SQL_DESC_BASE_COLUMN_NAME:
17461 #endif
17462 case SQL_DESC_TYPE_NAME:
17463 if (val && valMax > 0) {
17464 int vmax = valMax / sizeof (SQLWCHAR);
17465
17466 v = uc_from_utf((SQLCHAR *) val, SQL_NTS);
17467 if (v) {
17468 uc_strncpy(val, v, vmax);
17469 len = min(vmax, uc_strlen(v));
17470 uc_free(v);
17471 len *= sizeof (SQLWCHAR);
17472 }
17473 if (vmax > 0) {
17474 v = (SQLWCHAR *) val;
17475 v[vmax - 1] = '\0';
17476 }
17477 }
17478 if (len <= 0) {
17479 len = 0;
17480 }
17481 break;
17482 }
17483 if (valLen) {
17484 *valLen = len;
17485 }
17486 }
17487 HSTMT_UNLOCK(stmt);
17488 return ret;
17489 }
17490 #endif
17491
17492 /**
17493 * Internal return last HDBC or HSTMT error message.
17494 * @param env environment handle or NULL
17495 * @param dbc database connection handle or NULL
17496 * @param stmt statement handle or NULL
17497 * @param sqlState output buffer for SQL state
17498 * @param nativeErr output buffer for native error code
17499 * @param errmsg output buffer for error message
17500 * @param errmax length of output buffer for error message
17501 * @param errlen output length of error message
17502 * @result ODBC error code
17503 */
17504
17505 static SQLRETURN
drverror(SQLHENV env,SQLHDBC dbc,SQLHSTMT stmt,SQLCHAR * sqlState,SQLINTEGER * nativeErr,SQLCHAR * errmsg,SQLSMALLINT errmax,SQLSMALLINT * errlen)17506 drverror(SQLHENV env, SQLHDBC dbc, SQLHSTMT stmt,
17507 SQLCHAR *sqlState, SQLINTEGER *nativeErr,
17508 SQLCHAR *errmsg, SQLSMALLINT errmax, SQLSMALLINT *errlen)
17509 {
17510 SQLCHAR dummy0[6];
17511 SQLINTEGER dummy1;
17512 SQLSMALLINT dummy2;
17513
17514 if (env == SQL_NULL_HENV &&
17515 dbc == SQL_NULL_HDBC &&
17516 stmt == SQL_NULL_HSTMT) {
17517 return SQL_INVALID_HANDLE;
17518 }
17519 if (sqlState) {
17520 sqlState[0] = '\0';
17521 } else {
17522 sqlState = dummy0;
17523 }
17524 if (!nativeErr) {
17525 nativeErr = &dummy1;
17526 }
17527 *nativeErr = 0;
17528 if (!errlen) {
17529 errlen = &dummy2;
17530 }
17531 *errlen = 0;
17532 if (errmsg) {
17533 if (errmax > 0) {
17534 errmsg[0] = '\0';
17535 }
17536 } else {
17537 errmsg = dummy0;
17538 errmax = 0;
17539 }
17540 if (stmt) {
17541 STMT *s = (STMT *) stmt;
17542
17543 HSTMT_LOCK(stmt);
17544 if (s->logmsg[0] == '\0') {
17545 HSTMT_UNLOCK(stmt);
17546 goto noerr;
17547 }
17548 *nativeErr = s->naterr;
17549 strcpy((char *) sqlState, s->sqlstate);
17550 if (errmax == SQL_NTS) {
17551 strcpy((char *) errmsg, "[SQLite]");
17552 strcat((char *) errmsg, (char *) s->logmsg);
17553 *errlen = strlen((char *) errmsg);
17554 } else {
17555 strncpy((char *) errmsg, "[SQLite]", errmax);
17556 if (errmax - 8 > 0) {
17557 strncpy((char *) errmsg + 8, (char *) s->logmsg, errmax - 8);
17558 }
17559 *errlen = min(strlen((char *) s->logmsg) + 8, errmax);
17560 }
17561 s->logmsg[0] = '\0';
17562 HSTMT_UNLOCK(stmt);
17563 return SQL_SUCCESS;
17564 }
17565 if (dbc) {
17566 DBC *d = (DBC *) dbc;
17567
17568 HDBC_LOCK(dbc);
17569 if (d->magic != DBC_MAGIC || d->logmsg[0] == '\0') {
17570 HDBC_UNLOCK(dbc);
17571 goto noerr;
17572 }
17573 *nativeErr = d->naterr;
17574 strcpy((char *) sqlState, d->sqlstate);
17575 if (errmax == SQL_NTS) {
17576 strcpy((char *) errmsg, "[SQLite]");
17577 strcat((char *) errmsg, (char *) d->logmsg);
17578 *errlen = strlen((char *) errmsg);
17579 } else {
17580 strncpy((char *) errmsg, "[SQLite]", errmax);
17581 if (errmax - 8 > 0) {
17582 strncpy((char *) errmsg + 8, (char *) d->logmsg, errmax - 8);
17583 }
17584 *errlen = min(strlen((char *) d->logmsg) + 8, errmax);
17585 }
17586 d->logmsg[0] = '\0';
17587 HDBC_UNLOCK(dbc);
17588 return SQL_SUCCESS;
17589 }
17590 noerr:
17591 sqlState[0] = '\0';
17592 errmsg[0] = '\0';
17593 *nativeErr = 0;
17594 *errlen = 0;
17595 return SQL_NO_DATA;
17596 }
17597
17598 #ifndef WINTERFACE
17599 /**
17600 * Return last HDBC or HSTMT error message.
17601 * @param env environment handle or NULL
17602 * @param dbc database connection handle or NULL
17603 * @param stmt statement handle or NULL
17604 * @param sqlState output buffer for SQL state
17605 * @param nativeErr output buffer for native error code
17606 * @param errmsg output buffer for error message
17607 * @param errmax length of output buffer for error message
17608 * @param errlen output length of error message
17609 * @result ODBC error code
17610 */
17611
17612 SQLRETURN SQL_API
SQLError(SQLHENV env,SQLHDBC dbc,SQLHSTMT stmt,SQLCHAR * sqlState,SQLINTEGER * nativeErr,SQLCHAR * errmsg,SQLSMALLINT errmax,SQLSMALLINT * errlen)17613 SQLError(SQLHENV env, SQLHDBC dbc, SQLHSTMT stmt,
17614 SQLCHAR *sqlState, SQLINTEGER *nativeErr,
17615 SQLCHAR *errmsg, SQLSMALLINT errmax, SQLSMALLINT *errlen)
17616 {
17617 return drverror(env, dbc, stmt, sqlState, nativeErr,
17618 errmsg, errmax, errlen);
17619 }
17620 #endif
17621
17622 #ifdef WINTERFACE
17623 /**
17624 * Return last HDBC or HSTMT error message (UNICODE version).
17625 * @param env environment handle or NULL
17626 * @param dbc database connection handle or NULL
17627 * @param stmt statement handle or NULL
17628 * @param sqlState output buffer for SQL state
17629 * @param nativeErr output buffer for native error code
17630 * @param errmsg output buffer for error message
17631 * @param errmax length of output buffer for error message
17632 * @param errlen output length of error message
17633 * @result ODBC error code
17634 */
17635
17636 SQLRETURN SQL_API
SQLErrorW(SQLHENV env,SQLHDBC dbc,SQLHSTMT stmt,SQLWCHAR * sqlState,SQLINTEGER * nativeErr,SQLWCHAR * errmsg,SQLSMALLINT errmax,SQLSMALLINT * errlen)17637 SQLErrorW(SQLHENV env, SQLHDBC dbc, SQLHSTMT stmt,
17638 SQLWCHAR *sqlState, SQLINTEGER *nativeErr,
17639 SQLWCHAR *errmsg, SQLSMALLINT errmax, SQLSMALLINT *errlen)
17640 {
17641 char state[16];
17642 SQLSMALLINT len = 0;
17643 SQLRETURN ret;
17644
17645 ret = drverror(env, dbc, stmt, (SQLCHAR *) state, nativeErr,
17646 (SQLCHAR *) errmsg, errmax, &len);
17647 if (ret == SQL_SUCCESS) {
17648 if (sqlState) {
17649 uc_from_utf_buf((SQLCHAR *) state, -1, sqlState,
17650 6 * sizeof (SQLWCHAR));
17651 }
17652 if (errmsg) {
17653 if (len > 0) {
17654 SQLWCHAR *e = NULL;
17655
17656 e = uc_from_utf((SQLCHAR *) errmsg, len);
17657 if (e) {
17658 if (errmax > 0) {
17659 uc_strncpy(errmsg, e, errmax);
17660 e[len] = 0;
17661 len = min(errmax, uc_strlen(e));
17662 } else {
17663 len = uc_strlen(e);
17664 }
17665 uc_free(e);
17666 } else {
17667 len = 0;
17668 }
17669 }
17670 if (len <= 0) {
17671 len = 0;
17672 if (errmax > 0) {
17673 errmsg[0] = 0;
17674 }
17675 }
17676 } else {
17677 len = 0;
17678 }
17679 if (errlen) {
17680 *errlen = len;
17681 }
17682 } else if (ret == SQL_NO_DATA) {
17683 if (sqlState) {
17684 sqlState[0] = 0;
17685 }
17686 if (errmsg) {
17687 if (errmax > 0) {
17688 errmsg[0] = 0;
17689 }
17690 }
17691 if (errlen) {
17692 *errlen = 0;
17693 }
17694 }
17695 return ret;
17696 }
17697 #endif
17698
17699 /**
17700 * Return information for more result sets.
17701 * @param stmt statement handle
17702 * @result ODBC error code
17703 */
17704
17705 SQLRETURN SQL_API
SQLMoreResults(SQLHSTMT stmt)17706 SQLMoreResults(SQLHSTMT stmt)
17707 {
17708 HSTMT_LOCK(stmt);
17709 if (stmt == SQL_NULL_HSTMT) {
17710 return SQL_INVALID_HANDLE;
17711 }
17712 HSTMT_UNLOCK(stmt);
17713 return SQL_NO_DATA;
17714 }
17715
17716 /**
17717 * Internal function to setup column name/type information
17718 * @param s statement poiner
17719 * @param s4stmt sqlite4 statement pointer
17720 * @param ncolsp pointer to preinitialized number of columns
17721 * @result ODBC error code
17722 */
17723
17724 static SQLRETURN
setupdyncols(STMT * s,sqlite4_stmt * s4stmt,int * ncolsp)17725 setupdyncols(STMT *s, sqlite4_stmt *s4stmt, int *ncolsp)
17726 {
17727 int ncols = *ncolsp, guessed_types = 0;
17728 SQLRETURN ret = SQL_SUCCESS;
17729
17730 if (ncols > 0) {
17731 int i;
17732 PTRDIFF_T size;
17733 char *p;
17734 COL *dyncols;
17735 DBC *d = (DBC *) s->dbc;
17736 const char *colname, *typename;
17737 char *tblname, *dbname;
17738
17739 for (i = size = 0; i < ncols; i++) {
17740 colname = sqlite4_column_name(s4stmt, i);
17741 size += 3 + 3 * strlen(colname);
17742 }
17743 tblname = (char *) size;
17744 for (i = 0; i < ncols; i++) {
17745 p = (char *) sqlite4_column_table_name(s4stmt, i);
17746 size += 2 + (p ? strlen(p) : 0);
17747 }
17748 dbname = (char *) size;
17749 for (i = 0; i < ncols; i++) {
17750 p = (char *) sqlite4_column_database_name(s4stmt, i);
17751 size += 2 + (p ? strlen(p) : 0);
17752 }
17753 dyncols = xmalloc(ncols * sizeof (COL) + size);
17754 if (!dyncols) {
17755 freedyncols(s);
17756 *ncolsp = 0;
17757 ret = SQL_ERROR;
17758 } else {
17759 p = (char *) (dyncols + ncols);
17760 tblname = p + (PTRDIFF_T) tblname;
17761 dbname = p + (PTRDIFF_T) dbname;
17762 for (i = 0; i < ncols; i++) {
17763 char *q;
17764
17765 colname = sqlite4_column_name(s4stmt, i);
17766 if (d->trace) {
17767 fprintf(d->trace, "-- column %d name: '%s'\n",
17768 i + 1, colname);
17769 fflush(d->trace);
17770 }
17771 q = (char *) sqlite4_column_table_name(s4stmt, i);
17772 strcpy(tblname, q ? q : "");
17773 if (d->trace) {
17774 fprintf(d->trace, "-- table %d name: '%s'\n",
17775 i + 1, tblname);
17776 fflush(d->trace);
17777 }
17778 dyncols[i].table = tblname;
17779 q = (char *) sqlite4_column_database_name(s4stmt, i);
17780 strcpy(dbname, q ? q : "");
17781 if (d->trace) {
17782 fprintf(d->trace, "-- database %d name: '%s'\n",
17783 i + 1, dbname);
17784 fflush(d->trace);
17785 }
17786 dyncols[i].db = dbname;
17787 dbname += strlen(dbname) + 1;
17788 typename = s4stmt_coltype(s4stmt, i, d, &guessed_types);
17789 strcpy(p, colname);
17790 dyncols[i].label = p;
17791 p += strlen(p) + 1;
17792 q = strchr(colname, '.');
17793 if (q) {
17794 char *q2 = strchr(q + 1, '.');
17795
17796 /* SQLite 3.3.4 produces view.table.column sometimes */
17797 if (q2) {
17798 q = q2;
17799 }
17800 }
17801 if (q) {
17802 dyncols[i].table = p;
17803 strncpy(p, colname, q - colname);
17804 p[q - colname] = '\0';
17805 p += strlen(p) + 1;
17806 strcpy(p, q + 1);
17807 dyncols[i].column = p;
17808 p += strlen(p) + 1;
17809 } else {
17810 strcpy(p, colname);
17811 dyncols[i].column = p;
17812 p += strlen(p) + 1;
17813 }
17814 if (s->longnames) {
17815 dyncols[i].column = dyncols[i].label;
17816 }
17817 #ifdef SQL_LONGVARCHAR
17818 dyncols[i].type = SQL_LONGVARCHAR;
17819 dyncols[i].size = 65535;
17820 #else
17821 dyncols[i].type = SQL_VARCHAR;
17822 dyncols[i].size = 255;
17823 #endif
17824 dyncols[i].index = i;
17825 dyncols[i].scale = 0;
17826 dyncols[i].prec = 0;
17827 dyncols[i].nosign = 1;
17828 s4stmt_addmeta(s4stmt, i, d, &dyncols[i]);
17829 dyncols[i].typename = xstrdup(typename);
17830 }
17831 freedyncols(s);
17832 s->dyncols = s->cols = dyncols;
17833 s->dcols = ncols;
17834 fixupdyncols(s, d);
17835 s->guessed_types = guessed_types;
17836 }
17837 }
17838 return ret;
17839 }
17840
17841 /**
17842 * Internal query preparation used by SQLPrepare() and SQLExecDirect().
17843 * @param stmt statement handle
17844 * @param query query string
17845 * @param queryLen length of query string or SQL_NTS
17846 * @result ODBC error code
17847 */
17848
17849 static SQLRETURN
drvprepare(SQLHSTMT stmt,SQLCHAR * query,SQLINTEGER queryLen)17850 drvprepare(SQLHSTMT stmt, SQLCHAR *query, SQLINTEGER queryLen)
17851 {
17852 STMT *s;
17853 DBC *d;
17854 char *errp = NULL;
17855 SQLRETURN sret;
17856
17857 if (stmt == SQL_NULL_HSTMT) {
17858 return SQL_INVALID_HANDLE;
17859 }
17860 s = (STMT *) stmt;
17861 if (s->dbc == SQL_NULL_HDBC) {
17862 noconn:
17863 return noconn(s);
17864 }
17865 d = s->dbc;
17866 if (!d->sqlite) {
17867 goto noconn;
17868 }
17869 s4stmt_end(s);
17870 s4stmt_drop(s);
17871 sret = starttran(s);
17872 if (sret != SQL_SUCCESS) {
17873 return sret;
17874 }
17875 freep(&s->query);
17876 s->query = (SQLCHAR *) fixupsql((char *) query, queryLen,
17877 &s->nparams, &s->isselect, &errp);
17878 if (!s->query) {
17879 if (errp) {
17880 setstat(s, -1, "%s", (*s->ov3) ? "HY000" : "S1000", errp);
17881 return SQL_ERROR;
17882 }
17883 return nomem(s);
17884 }
17885 errp = NULL;
17886 freeresult(s, -1);
17887 if (s->isselect == 1) {
17888 int ret, ncols, nretry = 0;
17889 int sqlleft;
17890 sqlite4_stmt *s4stmt = NULL;
17891
17892 dbtraceapi(d, "sqlite4_prepare", (char *) s->query);
17893 do {
17894 s4stmt = NULL;
17895 ret = sqlite4_prepare(d->sqlite, (char *) s->query, -1,
17896 &s4stmt, &sqlleft);
17897 if (ret != SQLITE4_OK) {
17898 if (s4stmt) {
17899 sqlite4_finalize(s4stmt);
17900 s4stmt = NULL;
17901 }
17902 }
17903 } while (ret == SQLITE4_SCHEMA && (++nretry) < 2);
17904 dbtracerc(d, ret, NULL);
17905 if (ret != SQLITE4_OK) {
17906 if (s4stmt) {
17907 dbtraceapi(d, "sqlite4_finalize", 0);
17908 sqlite4_finalize(s4stmt);
17909 }
17910 setstat(s, ret, "%s (%d)", (*s->ov3) ? "HY000" : "S1000",
17911 sqlite4_errmsg(d->sqlite), ret);
17912 return SQL_ERROR;
17913 }
17914 if (sqlite4_bind_parameter_count(s4stmt) != s->nparams) {
17915 dbtraceapi(d, "sqlite4_finalize", 0);
17916 sqlite4_finalize(s4stmt);
17917 setstat(s, SQLITE4_ERROR, "parameter marker count incorrect",
17918 (*s->ov3) ? "HY000" : "S1000");
17919 return SQL_ERROR;
17920 }
17921 ncols = sqlite4_column_count(s4stmt);
17922 s->guessed_types = 0;
17923 setupdyncols(s, s4stmt, &ncols);
17924 s->ncols = ncols;
17925 s->s4stmt = s4stmt;
17926 }
17927 mkbindcols(s, s->ncols);
17928 s->paramset_count = 0;
17929 return SQL_SUCCESS;
17930 }
17931
17932 /**
17933 * Internal query execution used by SQLExecute() and SQLExecDirect().
17934 * @param stmt statement handle
17935 * @param initial false when called from SQLPutData()
17936 * @result ODBC error code
17937 */
17938
17939 static SQLRETURN
drvexecute(SQLHSTMT stmt,int initial)17940 drvexecute(SQLHSTMT stmt, int initial)
17941 {
17942 STMT *s;
17943 DBC *d;
17944 char *errp = NULL;
17945 int rc, i, ncols = 0, nrows = 0;
17946 SQLRETURN ret;
17947
17948 if (stmt == SQL_NULL_HSTMT) {
17949 return SQL_INVALID_HANDLE;
17950 }
17951 s = (STMT *) stmt;
17952 if (s->dbc == SQL_NULL_HDBC) {
17953 noconn:
17954 return noconn(s);
17955 }
17956 d = (DBC *) s->dbc;
17957 if (!d->sqlite) {
17958 goto noconn;
17959 }
17960 if (!s->query) {
17961 setstat(s, -1, "no query prepared", (*s->ov3) ? "HY000" : "S1000");
17962 return SQL_ERROR;
17963 }
17964 if (s->nbindparms < s->nparams) {
17965 unbound:
17966 setstat(s, -1, "unbound parameters in query",
17967 (*s->ov3) ? "HY000" : "S1000");
17968 return SQL_ERROR;
17969 }
17970 for (i = 0; i < s->nparams; i++) {
17971 BINDPARM *p = &s->bindparms[i];
17972
17973 if (!p->bound) {
17974 goto unbound;
17975 }
17976 if (initial) {
17977 SQLLEN *lenp = p->lenp;
17978
17979 if (lenp && *lenp < 0 && *lenp > SQL_LEN_DATA_AT_EXEC_OFFSET &&
17980 *lenp != SQL_NTS && *lenp != SQL_NULL_DATA &&
17981 *lenp != SQL_DATA_AT_EXEC) {
17982 setstat(s, -1, "invalid length reference", "HY009");
17983 return SQL_ERROR;
17984 }
17985 if (lenp && (*lenp <= SQL_LEN_DATA_AT_EXEC_OFFSET ||
17986 *lenp == SQL_DATA_AT_EXEC)) {
17987 p->need = 1;
17988 p->offs = 0;
17989 p->len = 0;
17990 }
17991 }
17992 }
17993 ret = starttran(s);
17994 if (ret != SQL_SUCCESS) {
17995 goto cleanup;
17996 }
17997 again:
17998 s4stmt_end(s);
17999 if (initial) {
18000 /* fixup data-at-execution parameters and alloc'ed blobs */
18001 s->pdcount = -1;
18002 for (i = 0; i < s->nparams; i++) {
18003 BINDPARM *p = &s->bindparms[i];
18004
18005 if (p->param == p->parbuf) {
18006 p->param = NULL;
18007 }
18008 freep(&p->parbuf);
18009 if (p->need <= 0 &&
18010 p->lenp && (*p->lenp <= SQL_LEN_DATA_AT_EXEC_OFFSET ||
18011 *p->lenp == SQL_DATA_AT_EXEC)) {
18012 p->need = 1;
18013 p->offs = 0;
18014 p->len = 0;
18015 }
18016 }
18017 }
18018 if (s->nparams) {
18019 for (i = 0; i < s->nparams; i++) {
18020 ret = setupparam(s, (char *) s->query, i);
18021 if (ret != SQL_SUCCESS) {
18022 goto cleanup;
18023 }
18024 }
18025 }
18026 freeresult(s, 0);
18027 if (s->isselect == 1 && !d->intrans &&
18028 s->curtype == SQL_CURSOR_FORWARD_ONLY &&
18029 d->step_enable && s->nparams == 0 && d->cur_s4stmt == NULL) {
18030 s->nrows = -1;
18031 ret = s4stmt_start(s);
18032 if (ret == SQL_SUCCESS) {
18033 goto done2;
18034 }
18035 }
18036 rc = drvgettable(s, s->s4stmt ? NULL : (char *) s->query, &s->rows,
18037 &s->nrows, &ncols, &errp, s->nparams, s->bindparms);
18038 dbtracerc(d, rc, errp);
18039 if (rc != SQLITE4_OK) {
18040 setstat(s, rc, "%s (%d)", (*s->ov3) ? "HY000" : "S1000",
18041 errp ? errp : "unknown error", rc);
18042 if (errp) {
18043 sqlite4_free(0, errp);
18044 errp = NULL;
18045 }
18046 ret = SQL_ERROR;
18047 goto cleanup;
18048 }
18049 if (errp) {
18050 sqlite4_free(0, errp);
18051 errp = NULL;
18052 }
18053 s->rowfree = freerows;
18054 if (s->isselect <= 0 || s->isselect > 1) {
18055 /*
18056 * INSERT/UPDATE/DELETE or DDL results are immediately released.
18057 */
18058 freeresult(s, -1);
18059 nrows += sqlite4_changes(d->sqlite);
18060 s->nrows = nrows;
18061 goto done;
18062 }
18063 if (s->ncols != ncols) {
18064 /*
18065 * Weird result.
18066 */
18067 setstat(s, -1, "broken result set %d/%d",
18068 (*s->ov3) ? "HY000" : "S1000", s->ncols, ncols);
18069 ret = SQL_ERROR;
18070 goto cleanup;
18071 }
18072 done:
18073 mkbindcols(s, s->ncols);
18074 done2:
18075 ret = SQL_SUCCESS;
18076 s->rowp = s->rowprs = -1;
18077 s->paramset_count++;
18078 s->paramset_nrows = s->nrows;
18079 if (s->paramset_count < s->paramset_size) {
18080 for (i = 0; i < s->nparams; i++) {
18081 BINDPARM *p = &s->bindparms[i];
18082
18083 if (p->param == p->parbuf) {
18084 p->param = NULL;
18085 }
18086 freep(&p->parbuf);
18087 if (p->lenp0 &&
18088 s->parm_bind_type != SQL_PARAM_BIND_BY_COLUMN) {
18089 p->lenp = (SQLLEN *) ((char *) p->lenp0 +
18090 s->paramset_count * s->parm_bind_type);
18091 } else if (p->lenp0 && p->inc > 0) {
18092 p->lenp = p->lenp0 + s->paramset_count;
18093 }
18094 if (!p->lenp || (*p->lenp > SQL_LEN_DATA_AT_EXEC_OFFSET &&
18095 *p->lenp != SQL_DATA_AT_EXEC)) {
18096 if (p->param0 &&
18097 s->parm_bind_type != SQL_PARAM_BIND_BY_COLUMN) {
18098 p->param = (char *) p->param0 +
18099 s->paramset_count * s->parm_bind_type;
18100 } else if (p->param0 && p->inc > 0) {
18101 p->param = (char *) p->param0 +
18102 s->paramset_count * p->inc;
18103 }
18104 } else if (p->lenp && (*p->lenp <= SQL_LEN_DATA_AT_EXEC_OFFSET ||
18105 *p->lenp == SQL_DATA_AT_EXEC)) {
18106 p->need = 1;
18107 p->offs = 0;
18108 p->len = 0;
18109 }
18110 }
18111 goto again;
18112 }
18113 cleanup:
18114 if (ret != SQL_NEED_DATA) {
18115 for (i = 0; i < s->nparams; i++) {
18116 BINDPARM *p = &s->bindparms[i];
18117
18118 if (p->param == p->parbuf) {
18119 p->param = NULL;
18120 }
18121 freep(&p->parbuf);
18122 if (!p->lenp || (*p->lenp > SQL_LEN_DATA_AT_EXEC_OFFSET &&
18123 *p->lenp != SQL_DATA_AT_EXEC)) {
18124 p->param = p->param0;
18125 }
18126 p->lenp = p->lenp0;
18127 }
18128 s->nrows = s->paramset_nrows;
18129 if (s->parm_proc) {
18130 *s->parm_proc = s->paramset_count;
18131 }
18132 s->paramset_count = 0;
18133 s->paramset_nrows = 0;
18134 }
18135 /*
18136 * For INSERT/UPDATE/DELETE statements change the return code
18137 * to SQL_NO_DATA if the number of rows affected was 0.
18138 */
18139 if (*s->ov3 && s->isselect == 0 &&
18140 ret == SQL_SUCCESS && nrows == 0) {
18141 ret = SQL_NO_DATA;
18142 }
18143 return ret;
18144 }
18145
18146 #ifndef WINTERFACE
18147 /**
18148 * Prepare HSTMT.
18149 * @param stmt statement handle
18150 * @param query query string
18151 * @param queryLen length of query string or SQL_NTS
18152 * @result ODBC error code
18153 */
18154
18155 SQLRETURN SQL_API
SQLPrepare(SQLHSTMT stmt,SQLCHAR * query,SQLINTEGER queryLen)18156 SQLPrepare(SQLHSTMT stmt, SQLCHAR *query, SQLINTEGER queryLen)
18157 {
18158 SQLRETURN ret;
18159 #if defined(_WIN32) || defined(_WIN64)
18160 char *q;
18161 #endif
18162
18163 HSTMT_LOCK(stmt);
18164 #if defined(_WIN32) || defined(_WIN64)
18165 if (!((STMT *) stmt)->oemcp[0]) {
18166 ret = drvprepare(stmt, query, queryLen);
18167 goto done;
18168 }
18169 q = wmb_to_utf_c((char *) query, queryLen);
18170 if (!q) {
18171 ret = nomem((STMT *) stmt);
18172 goto done;
18173 }
18174 query = (SQLCHAR *) q;
18175 queryLen = SQL_NTS;
18176 #endif
18177 ret = drvprepare(stmt, query, queryLen);
18178 #if defined(_WIN32) || defined(_WIN64)
18179 uc_free(q);
18180 done:
18181 ;
18182 #endif
18183 HSTMT_UNLOCK(stmt);
18184 return ret;
18185 }
18186 #endif
18187
18188 #ifdef WINTERFACE
18189 /**
18190 * Prepare HSTMT (UNICODE version).
18191 * @param stmt statement handle
18192 * @param query query string
18193 * @param queryLen length of query string or SQL_NTS
18194 * @result ODBC error code
18195 */
18196
18197 SQLRETURN SQL_API
SQLPrepareW(SQLHSTMT stmt,SQLWCHAR * query,SQLINTEGER queryLen)18198 SQLPrepareW(SQLHSTMT stmt, SQLWCHAR *query, SQLINTEGER queryLen)
18199 {
18200 SQLRETURN ret;
18201 char *q = uc_to_utf_c(query, queryLen);
18202
18203 HSTMT_LOCK(stmt);
18204 if (!q) {
18205 ret = nomem((STMT *) stmt);
18206 goto done;
18207 }
18208 ret = drvprepare(stmt, (SQLCHAR *) q, SQL_NTS);
18209 uc_free(q);
18210 done:
18211 HSTMT_UNLOCK(stmt);
18212 return ret;
18213 }
18214 #endif
18215
18216 /**
18217 * Execute query.
18218 * @param stmt statement handle
18219 * @result ODBC error code
18220 */
18221
18222 SQLRETURN SQL_API
SQLExecute(SQLHSTMT stmt)18223 SQLExecute(SQLHSTMT stmt)
18224 {
18225 SQLRETURN ret;
18226
18227 HSTMT_LOCK(stmt);
18228 ret = drvexecute(stmt, 1);
18229 HSTMT_UNLOCK(stmt);
18230 return ret;
18231 }
18232
18233 #ifndef WINTERFACE
18234 /**
18235 * Execute query directly.
18236 * @param stmt statement handle
18237 * @param query query string
18238 * @param queryLen length of query string or SQL_NTS
18239 * @result ODBC error code
18240 */
18241
18242 SQLRETURN SQL_API
SQLExecDirect(SQLHSTMT stmt,SQLCHAR * query,SQLINTEGER queryLen)18243 SQLExecDirect(SQLHSTMT stmt, SQLCHAR *query, SQLINTEGER queryLen)
18244 {
18245 SQLRETURN ret;
18246 #if defined(_WIN32) || defined(_WIN64)
18247 char *q;
18248 #endif
18249
18250 HSTMT_LOCK(stmt);
18251 #if defined(_WIN32) || defined(_WIN64)
18252 if (!((STMT *) stmt)->oemcp[0]) {
18253 ret = drvprepare(stmt, query, queryLen);
18254 if (ret == SQL_SUCCESS) {
18255 ret = drvexecute(stmt, 1);
18256 }
18257 goto done;
18258 }
18259 q = wmb_to_utf_c((char *) query, queryLen);
18260 if (!q) {
18261 ret = nomem((STMT *) stmt);
18262 goto done;
18263 }
18264 query = (SQLCHAR *) q;
18265 queryLen = SQL_NTS;
18266 #endif
18267 ret = drvprepare(stmt, query, queryLen);
18268 if (ret == SQL_SUCCESS) {
18269 ret = drvexecute(stmt, 1);
18270 }
18271 #if defined(_WIN32) || defined(_WIN64)
18272 uc_free(q);
18273 done:
18274 ;
18275 #endif
18276 HSTMT_UNLOCK(stmt);
18277 return ret;
18278 }
18279 #endif
18280
18281 #ifdef WINTERFACE
18282 /**
18283 * Execute query directly (UNICODE version).
18284 * @param stmt statement handle
18285 * @param query query string
18286 * @param queryLen length of query string or SQL_NTS
18287 * @result ODBC error code
18288 */
18289
18290 SQLRETURN SQL_API
SQLExecDirectW(SQLHSTMT stmt,SQLWCHAR * query,SQLINTEGER queryLen)18291 SQLExecDirectW(SQLHSTMT stmt, SQLWCHAR *query, SQLINTEGER queryLen)
18292 {
18293 SQLRETURN ret;
18294 char *q = uc_to_utf_c(query, queryLen);
18295
18296 HSTMT_LOCK(stmt);
18297 if (!q) {
18298 ret = nomem((STMT *) stmt);
18299 goto done;
18300 }
18301 ret = drvprepare(stmt, (SQLCHAR *) q, SQL_NTS);
18302 uc_free(q);
18303 if (ret == SQL_SUCCESS) {
18304 ret = drvexecute(stmt, 1);
18305 }
18306 done:
18307 HSTMT_UNLOCK(stmt);
18308 return ret;
18309 }
18310 #endif
18311
18312
18313 #if defined(_WIN32) || defined(_WIN64)
18314 #ifndef WITHOUT_DRIVERMGR
18315
18316 /*
18317 * Windows configuration dialog stuff.
18318 */
18319
18320 #include <windowsx.h>
18321 #include <winuser.h>
18322
18323 #define MAXPATHLEN (259+1) /* Max path length */
18324 #define MAXKEYLEN (15+1) /* Max keyword length */
18325 #define MAXDESC (255+1) /* Max description length */
18326 #define MAXDSNAME (255+1) /* Max data source name length */
18327 #define MAXTONAME (32+1) /* Max timeout length */
18328 #define MAXDBNAME MAXPATHLEN
18329
18330 /* Attribute key indexes into an array of Attr structs, see below */
18331
18332 #define KEY_DSN 0
18333 #define KEY_DESC 1
18334 #define KEY_DBNAME 2
18335 #define KEY_BUSY 3
18336 #define KEY_DRIVER 4
18337 #define KEY_STEPAPI 5
18338 #define KEY_SYNCP 6
18339 #define KEY_NOTXN 7
18340 #define KEY_SHORTNAM 8
18341 #define KEY_LONGNAM 9
18342 #define KEY_NOCREAT 10
18343 #define KEY_NOWCHAR 11
18344 #define KEY_LOADEXT 12
18345 #define KEY_JMODE 13
18346 #define KEY_FKSUPPORT 14
18347 #define KEY_OEMCP 15
18348 #define KEY_BIGINT 16
18349 #define KEY_PASSWD 17
18350 #define NUMOFKEYS 18
18351
18352 typedef struct {
18353 BOOL supplied;
18354 char attr[MAXPATHLEN*4];
18355 } ATTR;
18356
18357 typedef struct {
18358 SQLHWND parent;
18359 LPCSTR driver;
18360 ATTR attr[NUMOFKEYS];
18361 char DSN[MAXDSNAME];
18362 BOOL newDSN;
18363 BOOL defDSN;
18364 } SETUPDLG;
18365
18366 static struct {
18367 char *key;
18368 int ikey;
18369 } attrLookup[] = {
18370 { "DSN", KEY_DSN },
18371 { "DESC", KEY_DESC },
18372 { "Description", KEY_DESC},
18373 { "Database", KEY_DBNAME },
18374 { "Timeout", KEY_BUSY },
18375 { "Driver", KEY_DRIVER },
18376 { "StepAPI", KEY_STEPAPI },
18377 { "SyncPragma", KEY_SYNCP },
18378 { "NoTXN", KEY_NOTXN },
18379 { "ShortNames", KEY_SHORTNAM },
18380 { "LongNames", KEY_LONGNAM },
18381 { "NoCreat", KEY_NOCREAT },
18382 { "NoWCHAR", KEY_NOWCHAR },
18383 { "LoadExt", KEY_LOADEXT },
18384 { "JournalMode", KEY_JMODE },
18385 { "FKSupport", KEY_FKSUPPORT },
18386 { "OEMCP", KEY_OEMCP },
18387 { "BigInt", KEY_BIGINT },
18388 { "PWD", KEY_PASSWD },
18389 { NULL, 0 }
18390 };
18391
18392 /**
18393 * Setup dialog data from datasource attributes.
18394 * @param attribs attribute string
18395 * @param setupdlg pointer to dialog data
18396 */
18397
18398 static void
ParseAttributes(LPCSTR attribs,SETUPDLG * setupdlg)18399 ParseAttributes(LPCSTR attribs, SETUPDLG *setupdlg)
18400 {
18401 char *str = (char *) attribs, *start, key[MAXKEYLEN];
18402 int elem, nkey;
18403
18404 while (*str) {
18405 start = str;
18406 if ((str = strchr(str, '=')) == NULL) {
18407 return;
18408 }
18409 elem = -1;
18410 nkey = str - start;
18411 if (nkey < sizeof (key)) {
18412 int i;
18413
18414 memcpy(key, start, nkey);
18415 key[nkey] = '\0';
18416 for (i = 0; attrLookup[i].key; i++) {
18417 if (strcasecmp(attrLookup[i].key, key) == 0) {
18418 elem = attrLookup[i].ikey;
18419 break;
18420 }
18421 }
18422 }
18423 start = ++str;
18424 while (*str && *str != ';') {
18425 ++str;
18426 }
18427 if (elem >= 0) {
18428 int end = min(str - start, sizeof (setupdlg->attr[elem].attr) - 1);
18429
18430 setupdlg->attr[elem].supplied = TRUE;
18431 memcpy(setupdlg->attr[elem].attr, start, end);
18432 setupdlg->attr[elem].attr[end] = '\0';
18433 }
18434 ++str;
18435 }
18436 }
18437
18438 /**
18439 * Set datasource attributes in registry.
18440 * @param parent handle of parent window
18441 * @param setupdlg pointer to dialog data
18442 * @result true or false
18443 */
18444
18445 static BOOL
SetDSNAttributes(HWND parent,SETUPDLG * setupdlg)18446 SetDSNAttributes(HWND parent, SETUPDLG *setupdlg)
18447 {
18448 char *dsn = setupdlg->attr[KEY_DSN].attr;
18449
18450 if (setupdlg->newDSN && strlen(dsn) == 0) {
18451 return FALSE;
18452 }
18453 if (!SQLWriteDSNToIni(dsn, setupdlg->driver)) {
18454 if (parent) {
18455 char buf[MAXPATHLEN], msg[MAXPATHLEN];
18456
18457 LoadString(hModule, IDS_BADDSN, buf, sizeof (buf));
18458 wsprintf(msg, buf, dsn);
18459 LoadString(hModule, IDS_MSGTITLE, buf, sizeof (buf));
18460 MessageBox(parent, msg, buf,
18461 MB_ICONEXCLAMATION | MB_OK | MB_TASKMODAL |
18462 MB_SETFOREGROUND);
18463 }
18464 return FALSE;
18465 }
18466 if (parent || setupdlg->attr[KEY_DESC].supplied) {
18467 SQLWritePrivateProfileString(dsn, "Description",
18468 setupdlg->attr[KEY_DESC].attr,
18469 ODBC_INI);
18470 }
18471 if (parent || setupdlg->attr[KEY_DBNAME].supplied) {
18472 SQLWritePrivateProfileString(dsn, "Database",
18473 setupdlg->attr[KEY_DBNAME].attr,
18474 ODBC_INI);
18475 }
18476 if (parent || setupdlg->attr[KEY_BUSY].supplied) {
18477 SQLWritePrivateProfileString(dsn, "Timeout",
18478 setupdlg->attr[KEY_BUSY].attr,
18479 ODBC_INI);
18480 }
18481 if (parent || setupdlg->attr[KEY_STEPAPI].supplied) {
18482 SQLWritePrivateProfileString(dsn, "StepAPI",
18483 setupdlg->attr[KEY_STEPAPI].attr,
18484 ODBC_INI);
18485 }
18486 if (parent || setupdlg->attr[KEY_SYNCP].supplied) {
18487 SQLWritePrivateProfileString(dsn, "SyncPragma",
18488 setupdlg->attr[KEY_SYNCP].attr,
18489 ODBC_INI);
18490 }
18491 if (parent || setupdlg->attr[KEY_NOTXN].supplied) {
18492 SQLWritePrivateProfileString(dsn, "NoTXN",
18493 setupdlg->attr[KEY_NOTXN].attr,
18494 ODBC_INI);
18495 }
18496 if (parent || setupdlg->attr[KEY_SHORTNAM].supplied) {
18497 SQLWritePrivateProfileString(dsn, "ShortNames",
18498 setupdlg->attr[KEY_SHORTNAM].attr,
18499 ODBC_INI);
18500 }
18501 if (parent || setupdlg->attr[KEY_LONGNAM].supplied) {
18502 SQLWritePrivateProfileString(dsn, "LongNames",
18503 setupdlg->attr[KEY_LONGNAM].attr,
18504 ODBC_INI);
18505 }
18506 if (parent || setupdlg->attr[KEY_NOCREAT].supplied) {
18507 SQLWritePrivateProfileString(dsn, "NoCreat",
18508 setupdlg->attr[KEY_NOCREAT].attr,
18509 ODBC_INI);
18510 }
18511 if (parent || setupdlg->attr[KEY_NOWCHAR].supplied) {
18512 SQLWritePrivateProfileString(dsn, "NoWCHAR",
18513 setupdlg->attr[KEY_NOWCHAR].attr,
18514 ODBC_INI);
18515 }
18516 if (parent || setupdlg->attr[KEY_FKSUPPORT].supplied) {
18517 SQLWritePrivateProfileString(dsn, "FKSupport",
18518 setupdlg->attr[KEY_FKSUPPORT].attr,
18519 ODBC_INI);
18520 }
18521 if (parent || setupdlg->attr[KEY_OEMCP].supplied) {
18522 SQLWritePrivateProfileString(dsn, "OEMCP",
18523 setupdlg->attr[KEY_OEMCP].attr,
18524 ODBC_INI);
18525 }
18526 if (parent || setupdlg->attr[KEY_LOADEXT].supplied) {
18527 SQLWritePrivateProfileString(dsn, "LoadExt",
18528 setupdlg->attr[KEY_LOADEXT].attr,
18529 ODBC_INI);
18530 }
18531 if (parent || setupdlg->attr[KEY_BIGINT].supplied) {
18532 SQLWritePrivateProfileString(dsn, "BigInt",
18533 setupdlg->attr[KEY_BIGINT].attr,
18534 ODBC_INI);
18535 }
18536 if (parent || setupdlg->attr[KEY_PASSWD].supplied) {
18537 SQLWritePrivateProfileString(dsn, "PWD",
18538 setupdlg->attr[KEY_PASSWD].attr,
18539 ODBC_INI);
18540 }
18541 if (setupdlg->attr[KEY_DSN].supplied &&
18542 strcasecmp(setupdlg->DSN, setupdlg->attr[KEY_DSN].attr)) {
18543 SQLRemoveDSNFromIni(setupdlg->DSN);
18544 }
18545 return TRUE;
18546 }
18547
18548 /**
18549 * Get datasource attributes from registry.
18550 * @param setupdlg pointer to dialog data
18551 */
18552
18553 static void
GetAttributes(SETUPDLG * setupdlg)18554 GetAttributes(SETUPDLG *setupdlg)
18555 {
18556 char *dsn = setupdlg->attr[KEY_DSN].attr;
18557
18558 if (!setupdlg->attr[KEY_DESC].supplied) {
18559 SQLGetPrivateProfileString(dsn, "Description", "",
18560 setupdlg->attr[KEY_DESC].attr,
18561 sizeof (setupdlg->attr[KEY_DESC].attr),
18562 ODBC_INI);
18563 }
18564 if (!setupdlg->attr[KEY_DBNAME].supplied) {
18565 SQLGetPrivateProfileString(dsn, "Database", "",
18566 setupdlg->attr[KEY_DBNAME].attr,
18567 sizeof (setupdlg->attr[KEY_DBNAME].attr),
18568 ODBC_INI);
18569 }
18570 if (!setupdlg->attr[KEY_BUSY].supplied) {
18571 SQLGetPrivateProfileString(dsn, "Timeout", "100000",
18572 setupdlg->attr[KEY_BUSY].attr,
18573 sizeof (setupdlg->attr[KEY_BUSY].attr),
18574 ODBC_INI);
18575 }
18576 if (!setupdlg->attr[KEY_STEPAPI].supplied) {
18577 SQLGetPrivateProfileString(dsn, "StepAPI", "0",
18578 setupdlg->attr[KEY_STEPAPI].attr,
18579 sizeof (setupdlg->attr[KEY_STEPAPI].attr),
18580 ODBC_INI);
18581 }
18582 if (!setupdlg->attr[KEY_SYNCP].supplied) {
18583 SQLGetPrivateProfileString(dsn, "SyncPragma", "NORMAL",
18584 setupdlg->attr[KEY_SYNCP].attr,
18585 sizeof (setupdlg->attr[KEY_SYNCP].attr),
18586 ODBC_INI);
18587 }
18588 if (!setupdlg->attr[KEY_NOTXN].supplied) {
18589 SQLGetPrivateProfileString(dsn, "NoTXN", "",
18590 setupdlg->attr[KEY_NOTXN].attr,
18591 sizeof (setupdlg->attr[KEY_NOTXN].attr),
18592 ODBC_INI);
18593 }
18594 if (!setupdlg->attr[KEY_SHORTNAM].supplied) {
18595 SQLGetPrivateProfileString(dsn, "ShortNames", "",
18596 setupdlg->attr[KEY_SHORTNAM].attr,
18597 sizeof (setupdlg->attr[KEY_SHORTNAM].attr),
18598 ODBC_INI);
18599 }
18600 if (!setupdlg->attr[KEY_LONGNAM].supplied) {
18601 SQLGetPrivateProfileString(dsn, "LongNames", "",
18602 setupdlg->attr[KEY_LONGNAM].attr,
18603 sizeof (setupdlg->attr[KEY_LONGNAM].attr),
18604 ODBC_INI);
18605 }
18606 if (!setupdlg->attr[KEY_NOCREAT].supplied) {
18607 SQLGetPrivateProfileString(dsn, "NoCreat", "",
18608 setupdlg->attr[KEY_NOCREAT].attr,
18609 sizeof (setupdlg->attr[KEY_NOCREAT].attr),
18610 ODBC_INI);
18611 }
18612 if (!setupdlg->attr[KEY_NOWCHAR].supplied) {
18613 SQLGetPrivateProfileString(dsn, "NoWCHAR", "",
18614 setupdlg->attr[KEY_NOWCHAR].attr,
18615 sizeof (setupdlg->attr[KEY_NOWCHAR].attr),
18616 ODBC_INI);
18617 }
18618 if (!setupdlg->attr[KEY_FKSUPPORT].supplied) {
18619 SQLGetPrivateProfileString(dsn, "FKSupport", "",
18620 setupdlg->attr[KEY_FKSUPPORT].attr,
18621 sizeof (setupdlg->attr[KEY_FKSUPPORT].attr),
18622 ODBC_INI);
18623 }
18624 if (!setupdlg->attr[KEY_OEMCP].supplied) {
18625 SQLGetPrivateProfileString(dsn, "OEMCP", "",
18626 setupdlg->attr[KEY_OEMCP].attr,
18627 sizeof (setupdlg->attr[KEY_OEMCP].attr),
18628 ODBC_INI);
18629 }
18630 if (!setupdlg->attr[KEY_LOADEXT].supplied) {
18631 SQLGetPrivateProfileString(dsn, "LoadExt", "",
18632 setupdlg->attr[KEY_LOADEXT].attr,
18633 sizeof (setupdlg->attr[KEY_LOADEXT].attr),
18634 ODBC_INI);
18635 }
18636 if (!setupdlg->attr[KEY_JMODE].supplied) {
18637 SQLGetPrivateProfileString(dsn, "JournalMode", "",
18638 setupdlg->attr[KEY_JMODE].attr,
18639 sizeof (setupdlg->attr[KEY_JMODE].attr),
18640 ODBC_INI);
18641 }
18642 if (!setupdlg->attr[KEY_BIGINT].supplied) {
18643 SQLGetPrivateProfileString(dsn, "BigInt", "",
18644 setupdlg->attr[KEY_BIGINT].attr,
18645 sizeof (setupdlg->attr[KEY_BIGINT].attr),
18646 ODBC_INI);
18647 }
18648 if (!setupdlg->attr[KEY_PASSWD].supplied) {
18649 SQLGetPrivateProfileString(dsn, "PWD", "",
18650 setupdlg->attr[KEY_PASSWD].attr,
18651 sizeof (setupdlg->attr[KEY_PASSWD].attr),
18652 ODBC_INI);
18653 }
18654 }
18655
18656 /**
18657 * Open file dialog for selection of SQLite database file.
18658 * @param hdlg handle of originating dialog window
18659 */
18660
18661 static void
GetDBFile(HWND hdlg)18662 GetDBFile(HWND hdlg)
18663 {
18664 #ifdef _WIN64
18665 SETUPDLG *setupdlg = (SETUPDLG *) GetWindowLongPtr(hdlg, DWLP_USER);
18666 #else
18667 SETUPDLG *setupdlg = (SETUPDLG *) GetWindowLong(hdlg, DWL_USER);
18668 #endif
18669 OPENFILENAME ofn;
18670
18671 memset(&ofn, 0, sizeof (ofn));
18672 ofn.lStructSize = sizeof (ofn);
18673 ofn.hwndOwner = hdlg;
18674 #ifdef _WIN64
18675 ofn.hInstance = (HINSTANCE) GetWindowLongPtr(hdlg, GWLP_HINSTANCE);
18676 #else
18677 ofn.hInstance = (HINSTANCE) GetWindowLong(hdlg, GWL_HINSTANCE);
18678 #endif
18679 ofn.lpstrFile = (LPTSTR) setupdlg->attr[KEY_DBNAME].attr;
18680 ofn.nMaxFile = MAXPATHLEN;
18681 ofn.Flags = OFN_HIDEREADONLY | OFN_PATHMUSTEXIST |
18682 OFN_NOCHANGEDIR | OFN_EXPLORER | OFN_FILEMUSTEXIST;
18683 if (GetOpenFileName(&ofn)) {
18684 SetDlgItemText(hdlg, IDC_DBNAME, setupdlg->attr[KEY_DBNAME].attr);
18685 setupdlg->attr[KEY_DBNAME].supplied = TRUE;
18686 }
18687 }
18688
18689 /**
18690 * Dialog procedure for ConfigDSN().
18691 * @param hdlg handle of dialog window
18692 * @param wmsg type of message
18693 * @param wparam wparam of message
18694 * @param lparam lparam of message
18695 * @result true or false
18696 */
18697
18698 static BOOL CALLBACK
ConfigDlgProc(HWND hdlg,WORD wmsg,WPARAM wparam,LPARAM lparam)18699 ConfigDlgProc(HWND hdlg, WORD wmsg, WPARAM wparam, LPARAM lparam)
18700 {
18701 SETUPDLG *setupdlg = NULL;
18702 WORD index;
18703
18704 switch (wmsg) {
18705 case WM_INITDIALOG:
18706 #ifdef _WIN64
18707 SetWindowLong(hdlg, DWLP_USER, lparam);
18708 #else
18709 SetWindowLong(hdlg, DWL_USER, lparam);
18710 #endif
18711 setupdlg = (SETUPDLG *) lparam;
18712 GetAttributes(setupdlg);
18713 SetDlgItemText(hdlg, IDC_DSNAME, setupdlg->attr[KEY_DSN].attr);
18714 SetDlgItemText(hdlg, IDC_DESC, setupdlg->attr[KEY_DESC].attr);
18715 SetDlgItemText(hdlg, IDC_DBNAME, setupdlg->attr[KEY_DBNAME].attr);
18716 SetDlgItemText(hdlg, IDC_TONAME, setupdlg->attr[KEY_BUSY].attr);
18717 SetDlgItemText(hdlg, IDC_LOADEXT, setupdlg->attr[KEY_LOADEXT].attr);
18718 SendDlgItemMessage(hdlg, IDC_DSNAME, EM_LIMITTEXT,
18719 (WPARAM) (MAXDSNAME - 1), (LPARAM) 0);
18720 SendDlgItemMessage(hdlg, IDC_DESC, EM_LIMITTEXT,
18721 (WPARAM) (MAXDESC - 1), (LPARAM) 0);
18722 SendDlgItemMessage(hdlg, IDC_DBNAME, EM_LIMITTEXT,
18723 (WPARAM) (MAXDBNAME - 1), (LPARAM) 0);
18724 SendDlgItemMessage(hdlg, IDC_TONAME, EM_LIMITTEXT,
18725 (WPARAM) (MAXTONAME - 1), (LPARAM) 0);
18726 SendDlgItemMessage(hdlg, IDC_LOADEXT, EM_LIMITTEXT,
18727 (WPARAM) (MAXPATHLEN*4 - 1), (LPARAM) 0);
18728 CheckDlgButton(hdlg, IDC_STEPAPI,
18729 getbool(setupdlg->attr[KEY_STEPAPI].attr) ?
18730 BST_CHECKED : BST_UNCHECKED);
18731 CheckDlgButton(hdlg, IDC_NOTXN,
18732 getbool(setupdlg->attr[KEY_NOTXN].attr) ?
18733 BST_CHECKED : BST_UNCHECKED);
18734 CheckDlgButton(hdlg, IDC_SHORTNAM,
18735 getbool(setupdlg->attr[KEY_SHORTNAM].attr) ?
18736 BST_CHECKED : BST_UNCHECKED);
18737 CheckDlgButton(hdlg, IDC_LONGNAM,
18738 getbool(setupdlg->attr[KEY_LONGNAM].attr) ?
18739 BST_CHECKED : BST_UNCHECKED);
18740 CheckDlgButton(hdlg, IDC_NOCREAT,
18741 getbool(setupdlg->attr[KEY_NOCREAT].attr) ?
18742 BST_CHECKED : BST_UNCHECKED);
18743 CheckDlgButton(hdlg, IDC_NOWCHAR,
18744 getbool(setupdlg->attr[KEY_NOWCHAR].attr) ?
18745 BST_CHECKED : BST_UNCHECKED);
18746 CheckDlgButton(hdlg, IDC_FKSUPPORT,
18747 getbool(setupdlg->attr[KEY_FKSUPPORT].attr) ?
18748 BST_CHECKED : BST_UNCHECKED);
18749 CheckDlgButton(hdlg, IDC_OEMCP,
18750 getbool(setupdlg->attr[KEY_OEMCP].attr) ?
18751 BST_CHECKED : BST_UNCHECKED);
18752 CheckDlgButton(hdlg, IDC_BIGINT,
18753 getbool(setupdlg->attr[KEY_BIGINT].attr) ?
18754 BST_CHECKED : BST_UNCHECKED);
18755 SendDlgItemMessage(hdlg, IDC_SYNCP,
18756 CB_LIMITTEXT, (WPARAM) 10, (LPARAM) 0);
18757 SendDlgItemMessage(hdlg, IDC_SYNCP,
18758 CB_ADDSTRING, 0, (LPARAM) "NORMAL");
18759 SendDlgItemMessage(hdlg, IDC_SYNCP,
18760 CB_ADDSTRING, 0, (LPARAM) "OFF");
18761 SendDlgItemMessage(hdlg, IDC_SYNCP,
18762 CB_ADDSTRING, 0, (LPARAM) "FULL");
18763 SendDlgItemMessage(hdlg, IDC_SYNCP,
18764 CB_SELECTSTRING, (WPARAM) -1,
18765 (LPARAM) setupdlg->attr[KEY_SYNCP].attr);
18766 if (setupdlg->defDSN) {
18767 EnableWindow(GetDlgItem(hdlg, IDC_DSNAME), FALSE);
18768 EnableWindow(GetDlgItem(hdlg, IDC_DSNAMETEXT), FALSE);
18769 }
18770 return TRUE;
18771 case WM_COMMAND:
18772 switch (GET_WM_COMMAND_ID(wparam, lparam)) {
18773 case IDC_DSNAME:
18774 if (GET_WM_COMMAND_CMD(wparam, lparam) == EN_CHANGE) {
18775 char item[MAXDSNAME];
18776
18777 EnableWindow(GetDlgItem(hdlg, IDOK),
18778 GetDlgItemText(hdlg, IDC_DSNAME,
18779 item, sizeof (item)));
18780 return TRUE;
18781 }
18782 break;
18783 case IDC_BROWSE:
18784 GetDBFile(hdlg);
18785 break;
18786 case IDOK:
18787 #ifdef _WIN64
18788 setupdlg = (SETUPDLG *) GetWindowLongPtr(hdlg, DWLP_USER);
18789 #else
18790 setupdlg = (SETUPDLG *) GetWindowLong(hdlg, DWL_USER);
18791 #endif
18792 if (!setupdlg->defDSN) {
18793 GetDlgItemText(hdlg, IDC_DSNAME,
18794 setupdlg->attr[KEY_DSN].attr,
18795 sizeof (setupdlg->attr[KEY_DSN].attr));
18796 }
18797 GetDlgItemText(hdlg, IDC_DESC,
18798 setupdlg->attr[KEY_DESC].attr,
18799 sizeof (setupdlg->attr[KEY_DESC].attr));
18800 GetDlgItemText(hdlg, IDC_DBNAME,
18801 setupdlg->attr[KEY_DBNAME].attr,
18802 sizeof (setupdlg->attr[KEY_DBNAME].attr));
18803 GetDlgItemText(hdlg, IDC_TONAME,
18804 setupdlg->attr[KEY_BUSY].attr,
18805 sizeof (setupdlg->attr[KEY_BUSY].attr));
18806 GetDlgItemText(hdlg, IDC_LOADEXT,
18807 setupdlg->attr[KEY_LOADEXT].attr,
18808 sizeof (setupdlg->attr[KEY_LOADEXT].attr));
18809 index = SendDlgItemMessage(hdlg, IDC_SYNCP,
18810 CB_GETCURSEL, (WPARAM) 0, (LPARAM) 0);
18811 if (index != (WORD) CB_ERR) {
18812 SendDlgItemMessage(hdlg, IDC_SYNCP,
18813 CB_GETLBTEXT, index,
18814 (LPARAM) setupdlg->attr[KEY_SYNCP].attr);
18815 }
18816 strcpy(setupdlg->attr[KEY_STEPAPI].attr,
18817 (IsDlgButtonChecked(hdlg, IDC_STEPAPI) == BST_CHECKED) ?
18818 "1" : "0");
18819 strcpy(setupdlg->attr[KEY_NOTXN].attr,
18820 (IsDlgButtonChecked(hdlg, IDC_NOTXN) == BST_CHECKED) ?
18821 "1" : "0");
18822 strcpy(setupdlg->attr[KEY_SHORTNAM].attr,
18823 (IsDlgButtonChecked(hdlg, IDC_SHORTNAM) == BST_CHECKED) ?
18824 "1" : "0");
18825 strcpy(setupdlg->attr[KEY_LONGNAM].attr,
18826 (IsDlgButtonChecked(hdlg, IDC_LONGNAM) == BST_CHECKED) ?
18827 "1" : "0");
18828 strcpy(setupdlg->attr[KEY_NOCREAT].attr,
18829 (IsDlgButtonChecked(hdlg, IDC_NOCREAT) == BST_CHECKED) ?
18830 "1" : "0");
18831 strcpy(setupdlg->attr[KEY_NOWCHAR].attr,
18832 (IsDlgButtonChecked(hdlg, IDC_NOWCHAR) == BST_CHECKED) ?
18833 "1" : "0");
18834 strcpy(setupdlg->attr[KEY_FKSUPPORT].attr,
18835 (IsDlgButtonChecked(hdlg, IDC_FKSUPPORT) == BST_CHECKED) ?
18836 "1" : "0");
18837 strcpy(setupdlg->attr[KEY_OEMCP].attr,
18838 (IsDlgButtonChecked(hdlg, IDC_OEMCP) == BST_CHECKED) ?
18839 "1" : "0");
18840 strcpy(setupdlg->attr[KEY_BIGINT].attr,
18841 (IsDlgButtonChecked(hdlg, IDC_BIGINT) == BST_CHECKED) ?
18842 "1" : "0");
18843 SetDSNAttributes(hdlg, setupdlg);
18844 /* FALL THROUGH */
18845 case IDCANCEL:
18846 EndDialog(hdlg, wparam);
18847 return TRUE;
18848 }
18849 break;
18850 }
18851 return FALSE;
18852 }
18853
18854 /**
18855 * ODBC INSTAPI procedure for DSN configuration.
18856 * @param hwnd parent window handle
18857 * @param request type of request
18858 * @param driver driver name
18859 * @param attribs attribute string of DSN
18860 * @result true or false
18861 */
18862
18863 BOOL INSTAPI
ConfigDSN(HWND hwnd,WORD request,LPCSTR driver,LPCSTR attribs)18864 ConfigDSN(HWND hwnd, WORD request, LPCSTR driver, LPCSTR attribs)
18865 {
18866 BOOL success;
18867 SETUPDLG *setupdlg;
18868
18869 setupdlg = (SETUPDLG *) xmalloc(sizeof (SETUPDLG));
18870 if (setupdlg == NULL) {
18871 return FALSE;
18872 }
18873 memset(setupdlg, 0, sizeof (SETUPDLG));
18874 if (attribs) {
18875 ParseAttributes(attribs, setupdlg);
18876 }
18877 if (setupdlg->attr[KEY_DSN].supplied) {
18878 strcpy(setupdlg->DSN, setupdlg->attr[KEY_DSN].attr);
18879 } else {
18880 setupdlg->DSN[0] = '\0';
18881 }
18882 if (request == ODBC_REMOVE_DSN) {
18883 if (!setupdlg->attr[KEY_DSN].supplied) {
18884 success = FALSE;
18885 } else {
18886 success = SQLRemoveDSNFromIni(setupdlg->attr[KEY_DSN].attr);
18887 }
18888 } else {
18889 setupdlg->parent = hwnd;
18890 setupdlg->driver = driver;
18891 setupdlg->newDSN = request == ODBC_ADD_DSN;
18892 setupdlg->defDSN = strcasecmp(setupdlg->attr[KEY_DSN].attr,
18893 "Default") == 0;
18894 if (hwnd) {
18895 success = DialogBoxParam(hModule, MAKEINTRESOURCE(CONFIGDSN),
18896 hwnd, (DLGPROC) ConfigDlgProc,
18897 (LPARAM) setupdlg) == IDOK;
18898 } else if (setupdlg->attr[KEY_DSN].supplied) {
18899 success = SetDSNAttributes(hwnd, setupdlg);
18900 } else {
18901 success = FALSE;
18902 }
18903 }
18904 xfree(setupdlg);
18905 return success;
18906 }
18907
18908 /**
18909 * Dialog procedure for SQLDriverConnect().
18910 * @param hdlg handle of dialog window
18911 * @param wmsg type of message
18912 * @param wparam wparam of message
18913 * @param lparam lparam of message
18914 * @result true or false
18915 */
18916
18917 static BOOL CALLBACK
DriverConnectProc(HWND hdlg,WORD wmsg,WPARAM wparam,LPARAM lparam)18918 DriverConnectProc(HWND hdlg, WORD wmsg, WPARAM wparam, LPARAM lparam)
18919 {
18920 SETUPDLG *setupdlg;
18921 WORD index;
18922
18923 switch (wmsg) {
18924 case WM_INITDIALOG:
18925 #ifdef _WIN64
18926 SetWindowLong(hdlg, DWLP_USER, lparam);
18927 #else
18928 SetWindowLong(hdlg, DWL_USER, lparam);
18929 #endif
18930 setupdlg = (SETUPDLG *) lparam;
18931 SetDlgItemText(hdlg, IDC_DSNAME, setupdlg->attr[KEY_DSN].attr);
18932 SetDlgItemText(hdlg, IDC_DESC, setupdlg->attr[KEY_DESC].attr);
18933 SetDlgItemText(hdlg, IDC_DBNAME, setupdlg->attr[KEY_DBNAME].attr);
18934 SetDlgItemText(hdlg, IDC_TONAME, setupdlg->attr[KEY_BUSY].attr);
18935 SetDlgItemText(hdlg, IDC_LOADEXT, setupdlg->attr[KEY_LOADEXT].attr);
18936 SendDlgItemMessage(hdlg, IDC_DSNAME, EM_LIMITTEXT,
18937 (WPARAM) (MAXDSNAME - 1), (LPARAM) 0);
18938 SendDlgItemMessage(hdlg, IDC_DESC, EM_LIMITTEXT,
18939 (WPARAM) (MAXDESC - 1), (LPARAM) 0);
18940 SendDlgItemMessage(hdlg, IDC_DBNAME, EM_LIMITTEXT,
18941 (WPARAM) (MAXDBNAME - 1), (LPARAM) 0);
18942 SendDlgItemMessage(hdlg, IDC_TONAME, EM_LIMITTEXT,
18943 (WPARAM) (MAXTONAME - 1), (LPARAM) 0);
18944 SendDlgItemMessage(hdlg, IDC_LOADEXT, EM_LIMITTEXT,
18945 (WPARAM) (MAXPATHLEN*4 - 1), (LPARAM) 0);
18946 CheckDlgButton(hdlg, IDC_STEPAPI,
18947 getbool(setupdlg->attr[KEY_STEPAPI].attr) ?
18948 BST_CHECKED : BST_UNCHECKED);
18949 CheckDlgButton(hdlg, IDC_NOTXN,
18950 getbool(setupdlg->attr[KEY_NOTXN].attr) ?
18951 BST_CHECKED : BST_UNCHECKED);
18952 CheckDlgButton(hdlg, IDC_SHORTNAM,
18953 getbool(setupdlg->attr[KEY_SHORTNAM].attr) ?
18954 BST_CHECKED : BST_UNCHECKED);
18955 CheckDlgButton(hdlg, IDC_LONGNAM,
18956 getbool(setupdlg->attr[KEY_LONGNAM].attr) ?
18957 BST_CHECKED : BST_UNCHECKED);
18958 CheckDlgButton(hdlg, IDC_NOCREAT,
18959 getbool(setupdlg->attr[KEY_NOCREAT].attr) ?
18960 BST_CHECKED : BST_UNCHECKED);
18961 CheckDlgButton(hdlg, IDC_NOWCHAR,
18962 getbool(setupdlg->attr[KEY_NOWCHAR].attr) ?
18963 BST_CHECKED : BST_UNCHECKED);
18964 CheckDlgButton(hdlg, IDC_FKSUPPORT,
18965 getbool(setupdlg->attr[KEY_FKSUPPORT].attr) ?
18966 BST_CHECKED : BST_UNCHECKED);
18967 CheckDlgButton(hdlg, IDC_OEMCP,
18968 getbool(setupdlg->attr[KEY_OEMCP].attr) ?
18969 BST_CHECKED : BST_UNCHECKED);
18970 CheckDlgButton(hdlg, IDC_BIGINT,
18971 getbool(setupdlg->attr[KEY_BIGINT].attr) ?
18972 BST_CHECKED : BST_UNCHECKED);
18973 SendDlgItemMessage(hdlg, IDC_SYNCP,
18974 CB_LIMITTEXT, (WPARAM) 10, (LPARAM) 0);
18975 SendDlgItemMessage(hdlg, IDC_SYNCP,
18976 CB_ADDSTRING, 0, (LPARAM) "NORMAL");
18977 SendDlgItemMessage(hdlg, IDC_SYNCP,
18978 CB_ADDSTRING, 0, (LPARAM) "OFF");
18979 SendDlgItemMessage(hdlg, IDC_SYNCP,
18980 CB_ADDSTRING, 0, (LPARAM) "FULL");
18981 SendDlgItemMessage(hdlg, IDC_SYNCP,
18982 CB_SELECTSTRING, (WORD) -1,
18983 (LPARAM) setupdlg->attr[KEY_SYNCP].attr);
18984 if (setupdlg->defDSN) {
18985 EnableWindow(GetDlgItem(hdlg, IDC_DSNAME), FALSE);
18986 EnableWindow(GetDlgItem(hdlg, IDC_DSNAMETEXT), FALSE);
18987 }
18988 return TRUE;
18989 case WM_COMMAND:
18990 switch (GET_WM_COMMAND_ID(wparam, lparam)) {
18991 case IDC_BROWSE:
18992 GetDBFile(hdlg);
18993 break;
18994 case IDOK:
18995 #ifdef _WIN64
18996 setupdlg = (SETUPDLG *) GetWindowLongPtr(hdlg, DWLP_USER);
18997 #else
18998 setupdlg = (SETUPDLG *) GetWindowLong(hdlg, DWL_USER);
18999 #endif
19000 GetDlgItemText(hdlg, IDC_DSNAME,
19001 setupdlg->attr[KEY_DSN].attr,
19002 sizeof (setupdlg->attr[KEY_DSN].attr));
19003 GetDlgItemText(hdlg, IDC_DBNAME,
19004 setupdlg->attr[KEY_DBNAME].attr,
19005 sizeof (setupdlg->attr[KEY_DBNAME].attr));
19006 GetDlgItemText(hdlg, IDC_TONAME,
19007 setupdlg->attr[KEY_BUSY].attr,
19008 sizeof (setupdlg->attr[KEY_BUSY].attr));
19009 GetDlgItemText(hdlg, IDC_LOADEXT,
19010 setupdlg->attr[KEY_LOADEXT].attr,
19011 sizeof (setupdlg->attr[KEY_LOADEXT].attr));
19012 index = SendDlgItemMessage(hdlg, IDC_SYNCP,
19013 CB_GETCURSEL, (WPARAM) 0, (LPARAM) 0);
19014 if (index != (WORD) CB_ERR) {
19015 SendDlgItemMessage(hdlg, IDC_SYNCP,
19016 CB_GETLBTEXT, index,
19017 (LPARAM) setupdlg->attr[KEY_SYNCP].attr);
19018 }
19019 strcpy(setupdlg->attr[KEY_STEPAPI].attr,
19020 (IsDlgButtonChecked(hdlg, IDC_STEPAPI) == BST_CHECKED) ?
19021 "1" : "0");
19022 strcpy(setupdlg->attr[KEY_NOTXN].attr,
19023 (IsDlgButtonChecked(hdlg, IDC_NOTXN) == BST_CHECKED) ?
19024 "1" : "0");
19025 strcpy(setupdlg->attr[KEY_SHORTNAM].attr,
19026 (IsDlgButtonChecked(hdlg, IDC_SHORTNAM) == BST_CHECKED) ?
19027 "1" : "0");
19028 strcpy(setupdlg->attr[KEY_LONGNAM].attr,
19029 (IsDlgButtonChecked(hdlg, IDC_LONGNAM) == BST_CHECKED) ?
19030 "1" : "0");
19031 strcpy(setupdlg->attr[KEY_NOCREAT].attr,
19032 (IsDlgButtonChecked(hdlg, IDC_NOCREAT) == BST_CHECKED) ?
19033 "1" : "0");
19034 strcpy(setupdlg->attr[KEY_NOWCHAR].attr,
19035 (IsDlgButtonChecked(hdlg, IDC_NOWCHAR) == BST_CHECKED) ?
19036 "1" : "0");
19037 strcpy(setupdlg->attr[KEY_FKSUPPORT].attr,
19038 (IsDlgButtonChecked(hdlg, IDC_FKSUPPORT) == BST_CHECKED) ?
19039 "1" : "0");
19040 strcpy(setupdlg->attr[KEY_OEMCP].attr,
19041 (IsDlgButtonChecked(hdlg, IDC_OEMCP) == BST_CHECKED) ?
19042 "1" : "0");
19043 strcpy(setupdlg->attr[KEY_BIGINT].attr,
19044 (IsDlgButtonChecked(hdlg, IDC_BIGINT) == BST_CHECKED) ?
19045 "1" : "0");
19046 /* FALL THROUGH */
19047 case IDCANCEL:
19048 EndDialog(hdlg, GET_WM_COMMAND_ID(wparam, lparam) == IDOK);
19049 return TRUE;
19050 }
19051 }
19052 return FALSE;
19053 }
19054
19055 /**
19056 * Internal connect using a driver connection string.
19057 * @param dbc database connection handle
19058 * @param hwnd parent window handle
19059 * @param connIn driver connect input string
19060 * @param connInLen length of driver connect input string or SQL_NTS
19061 * @param connOut driver connect output string
19062 * @param connOutMax length of driver connect output string
19063 * @param connOutLen output length of driver connect output string
19064 * @param drvcompl completion type
19065 * @result ODBC error code
19066 */
19067
19068 static SQLRETURN
drvdriverconnect(SQLHDBC dbc,SQLHWND hwnd,SQLCHAR * connIn,SQLSMALLINT connInLen,SQLCHAR * connOut,SQLSMALLINT connOutMax,SQLSMALLINT * connOutLen,SQLUSMALLINT drvcompl)19069 drvdriverconnect(SQLHDBC dbc, SQLHWND hwnd,
19070 SQLCHAR *connIn, SQLSMALLINT connInLen,
19071 SQLCHAR *connOut, SQLSMALLINT connOutMax,
19072 SQLSMALLINT *connOutLen, SQLUSMALLINT drvcompl)
19073 {
19074 BOOL maybeprompt, prompt = FALSE, defaultdsn = FALSE;
19075 DBC *d;
19076 SETUPDLG *setupdlg;
19077 SQLRETURN ret;
19078 char *dsn = NULL, *driver = NULL, *dbname = NULL;
19079
19080 if (dbc == SQL_NULL_HDBC) {
19081 return SQL_INVALID_HANDLE;
19082 }
19083 d = (DBC *) dbc;
19084 if (d->sqlite) {
19085 setstatd(d, -1, "connection already established", "08002");
19086 return SQL_ERROR;
19087 }
19088 setupdlg = (SETUPDLG *) xmalloc(sizeof (SETUPDLG));
19089 if (setupdlg == NULL) {
19090 return SQL_ERROR;
19091 }
19092 memset(setupdlg, 0, sizeof (SETUPDLG));
19093 maybeprompt = drvcompl == SQL_DRIVER_COMPLETE ||
19094 drvcompl == SQL_DRIVER_COMPLETE_REQUIRED;
19095 if (connIn == NULL || !connInLen ||
19096 (connInLen == SQL_NTS && !connIn[0])) {
19097 prompt = TRUE;
19098 } else {
19099 ParseAttributes((LPCSTR) connIn, setupdlg);
19100 if (!setupdlg->attr[KEY_DSN].attr[0] &&
19101 drvcompl == SQL_DRIVER_COMPLETE_REQUIRED) {
19102 strcpy(setupdlg->attr[KEY_DSN].attr, "DEFAULT");
19103 defaultdsn = TRUE;
19104 }
19105 GetAttributes(setupdlg);
19106 if (drvcompl == SQL_DRIVER_PROMPT ||
19107 (maybeprompt &&
19108 !setupdlg->attr[KEY_DBNAME].attr[0])) {
19109 prompt = TRUE;
19110 }
19111 }
19112 retry:
19113 if (prompt) {
19114 short dlgret;
19115
19116 setupdlg->defDSN = setupdlg->attr[KEY_DRIVER].attr[0] != '\0';
19117 dlgret = DialogBoxParam(hModule, MAKEINTRESOURCE(DRIVERCONNECT),
19118 hwnd, (DLGPROC) DriverConnectProc,
19119 (LPARAM) setupdlg);
19120
19121 if (!dlgret || dlgret == -1) {
19122 xfree(setupdlg);
19123 return SQL_NO_DATA;
19124 }
19125 }
19126 dsn = setupdlg->attr[KEY_DSN].attr;
19127 driver = setupdlg->attr[KEY_DRIVER].attr;
19128 dbname = setupdlg->attr[KEY_DBNAME].attr;
19129 if (connOut || connOutLen) {
19130 char buf[SQL_MAX_MESSAGE_LENGTH * 8];
19131 int len, count;
19132 char dsn_0 = (dsn && !defaultdsn) ? dsn[0] : '\0';
19133 char drv_0 = driver ? driver[0] : '\0';
19134
19135 buf[0] = '\0';
19136 count = snprintf(buf, sizeof (buf),
19137 "%s%s%s%s%s%sDatabase=%s;StepAPI=%s;"
19138 "SyncPragma=%s;NoTXN=%s;Timeout=%s;"
19139 "ShortNames=%s;LongNames=%s;"
19140 "NoCreat=%s;NoWCHAR=%s;"
19141 "FKSupport=%s;JournalMode=%s;OEMCP=%s;LoadExt=%s;"
19142 "BigInt=%s;PWD=%s",
19143 dsn_0 ? "DSN=" : "",
19144 dsn_0 ? dsn : "",
19145 dsn_0 ? ";" : "",
19146 drv_0 ? "Driver=" : "",
19147 drv_0 ? driver : "",
19148 drv_0 ? ";" : "",
19149 dbname ? dbname : "",
19150 setupdlg->attr[KEY_STEPAPI].attr,
19151 setupdlg->attr[KEY_SYNCP].attr,
19152 setupdlg->attr[KEY_NOTXN].attr,
19153 setupdlg->attr[KEY_BUSY].attr,
19154 setupdlg->attr[KEY_SHORTNAM].attr,
19155 setupdlg->attr[KEY_LONGNAM].attr,
19156 setupdlg->attr[KEY_NOCREAT].attr,
19157 setupdlg->attr[KEY_NOWCHAR].attr,
19158 setupdlg->attr[KEY_FKSUPPORT].attr,
19159 setupdlg->attr[KEY_JMODE].attr,
19160 setupdlg->attr[KEY_OEMCP].attr,
19161 setupdlg->attr[KEY_LOADEXT].attr,
19162 setupdlg->attr[KEY_BIGINT].attr,
19163 setupdlg->attr[KEY_PASSWD].attr);
19164 if (count < 0) {
19165 buf[sizeof (buf) - 1] = '\0';
19166 }
19167 len = min(connOutMax - 1, strlen(buf));
19168 if (connOut) {
19169 strncpy((char *) connOut, buf, len);
19170 connOut[len] = '\0';
19171 }
19172 if (connOutLen) {
19173 *connOutLen = len;
19174 }
19175 }
19176 if (dsn[0]) {
19177 char tracef[SQL_MAX_MESSAGE_LENGTH];
19178
19179 tracef[0] = '\0';
19180 SQLGetPrivateProfileString(setupdlg->attr[KEY_DSN].attr,
19181 "tracefile", "", tracef,
19182 sizeof (tracef), ODBC_INI);
19183 if (tracef[0] != '\0') {
19184 d->trace = fopen(tracef, "a");
19185 }
19186 }
19187 d->nowchar = getbool(setupdlg->attr[KEY_NOWCHAR].attr);
19188 d->shortnames = getbool(setupdlg->attr[KEY_SHORTNAM].attr);
19189 d->longnames = getbool(setupdlg->attr[KEY_LONGNAM].attr);
19190 d->nocreat = getbool(setupdlg->attr[KEY_NOCREAT].attr);
19191 d->fksupport = getbool(setupdlg->attr[KEY_FKSUPPORT].attr);
19192 d->oemcp = getbool(setupdlg->attr[KEY_OEMCP].attr);
19193 d->dobigint = getbool(setupdlg->attr[KEY_BIGINT].attr);
19194 d->pwdLen = strlen(setupdlg->attr[KEY_PASSWD].attr);
19195 d->pwd = (d->pwdLen > 0) ? setupdlg->attr[KEY_PASSWD].attr : NULL;
19196 ret = dbopen(d, dbname ? dbname : "", 0,
19197 dsn ? dsn : "",
19198 setupdlg->attr[KEY_STEPAPI].attr,
19199 setupdlg->attr[KEY_SYNCP].attr,
19200 setupdlg->attr[KEY_NOTXN].attr,
19201 setupdlg->attr[KEY_JMODE].attr,
19202 setupdlg->attr[KEY_BUSY].attr);
19203 if (ret != SQL_SUCCESS) {
19204 if (maybeprompt && !prompt) {
19205 prompt = TRUE;
19206 goto retry;
19207 }
19208 }
19209 memset(setupdlg->attr[KEY_PASSWD].attr, 0,
19210 sizeof (setupdlg->attr[KEY_PASSWD].attr));
19211 if (ret == SQL_SUCCESS) {
19212 dbloadext(d, setupdlg->attr[KEY_LOADEXT].attr);
19213 }
19214 xfree(setupdlg);
19215 return ret;
19216 }
19217
19218 #endif /* WITHOUT_DRIVERMGR */
19219 #endif /* _WIN32 || _WIN64 */
19220
19221 #ifndef WINTERFACE
19222 /**
19223 * Connect using a driver connection string.
19224 * @param dbc database connection handle
19225 * @param hwnd parent window handle
19226 * @param connIn driver connect input string
19227 * @param connInLen length of driver connect input string or SQL_NTS
19228 * @param connOut driver connect output string
19229 * @param connOutMax length of driver connect output string
19230 * @param connOutLen output length of driver connect output string
19231 * @param drvcompl completion type
19232 * @result ODBC error code
19233 */
19234
19235 SQLRETURN SQL_API
SQLDriverConnect(SQLHDBC dbc,SQLHWND hwnd,SQLCHAR * connIn,SQLSMALLINT connInLen,SQLCHAR * connOut,SQLSMALLINT connOutMax,SQLSMALLINT * connOutLen,SQLUSMALLINT drvcompl)19236 SQLDriverConnect(SQLHDBC dbc, SQLHWND hwnd,
19237 SQLCHAR *connIn, SQLSMALLINT connInLen,
19238 SQLCHAR *connOut, SQLSMALLINT connOutMax,
19239 SQLSMALLINT *connOutLen, SQLUSMALLINT drvcompl)
19240 {
19241 SQLRETURN ret;
19242
19243 HDBC_LOCK(dbc);
19244 ret = drvdriverconnect(dbc, hwnd, connIn, connInLen,
19245 connOut, connOutMax, connOutLen, drvcompl);
19246 HDBC_UNLOCK(dbc);
19247 return ret;
19248 }
19249 #endif
19250
19251 #ifdef WINTERFACE
19252 /**
19253 * Connect using a driver connection string (UNICODE version).
19254 * @param dbc database connection handle
19255 * @param hwnd parent window handle
19256 * @param connIn driver connect input string
19257 * @param connInLen length of driver connect input string or SQL_NTS
19258 * @param connOut driver connect output string
19259 * @param connOutMax length of driver connect output string
19260 * @param connOutLen output length of driver connect output string
19261 * @param drvcompl completion type
19262 * @result ODBC error code
19263 */
19264
19265 SQLRETURN SQL_API
SQLDriverConnectW(SQLHDBC dbc,SQLHWND hwnd,SQLWCHAR * connIn,SQLSMALLINT connInLen,SQLWCHAR * connOut,SQLSMALLINT connOutMax,SQLSMALLINT * connOutLen,SQLUSMALLINT drvcompl)19266 SQLDriverConnectW(SQLHDBC dbc, SQLHWND hwnd,
19267 SQLWCHAR *connIn, SQLSMALLINT connInLen,
19268 SQLWCHAR *connOut, SQLSMALLINT connOutMax,
19269 SQLSMALLINT *connOutLen, SQLUSMALLINT drvcompl)
19270 {
19271 SQLRETURN ret;
19272 char *ci = NULL;
19273 SQLSMALLINT len = 0;
19274
19275 HDBC_LOCK(dbc);
19276 if (connIn) {
19277 #if defined(_WIN32) || defined(_WIN64)
19278 if (connInLen == SQL_NTS) {
19279 connInLen = -1;
19280 }
19281 ci = uc_to_wmb(connIn, connInLen);
19282 #else
19283 ci = uc_to_utf(connIn, connInLen);
19284 #endif
19285 if (!ci) {
19286 DBC *d = (DBC *) dbc;
19287
19288 setstatd(d, -1, "out of memory", (*d->ov3) ? "HY000" : "S1000");
19289 HDBC_UNLOCK(dbc);
19290 return SQL_ERROR;
19291 }
19292 }
19293 ret = drvdriverconnect(dbc, hwnd, (SQLCHAR *) ci, SQL_NTS,
19294 (SQLCHAR *) connOut, connOutMax, &len, drvcompl);
19295 HDBC_UNLOCK(dbc);
19296 uc_free(ci);
19297 if (ret == SQL_SUCCESS) {
19298 SQLWCHAR *co = NULL;
19299
19300 if (connOut) {
19301 if (len > 0) {
19302 #if defined(_WIN32) || defined(_WIN64)
19303 co = wmb_to_uc((char *) connOut, len);
19304 #else
19305 co = uc_from_utf((SQLCHAR *) connOut, len);
19306 #endif
19307 if (co) {
19308 uc_strncpy(connOut, co, connOutMax / sizeof (SQLWCHAR));
19309 len = min(connOutMax / sizeof (SQLWCHAR), uc_strlen(co));
19310 uc_free(co);
19311 } else {
19312 len = 0;
19313 }
19314 }
19315 if (len <= 0) {
19316 len = 0;
19317 connOut[0] = 0;
19318 }
19319 } else {
19320 len = 0;
19321 }
19322 if (connOutLen) {
19323 *connOutLen = len;
19324 }
19325 }
19326 return ret;
19327 }
19328 #endif
19329
19330 #if defined(_WIN32) || defined(_WIN64)
19331
19332 /**
19333 * DLL initializer for WIN32.
19334 * @param hinst instance handle
19335 * @param reason reason code for entry point
19336 * @param reserved
19337 * @result always true
19338 */
19339
19340 BOOL APIENTRY
LibMain(HANDLE hinst,DWORD reason,LPVOID reserved)19341 LibMain(HANDLE hinst, DWORD reason, LPVOID reserved)
19342 {
19343 static int initialized = 0;
19344
19345 switch (reason) {
19346 case DLL_PROCESS_ATTACH:
19347 if (!initialized++) {
19348 hModule = hinst;
19349 #ifdef WINTERFACE
19350 /* MS Access hack part 1 (reserved error -7748) */
19351 statSpec2P = statSpec2;
19352 statSpec3P = statSpec3;
19353 #endif
19354 #ifdef SQLITE_DYNLOAD
19355 dls_init();
19356 #endif
19357 }
19358 break;
19359 case DLL_THREAD_ATTACH:
19360 break;
19361 case DLL_PROCESS_DETACH:
19362 if (--initialized <= 0) {
19363 #ifdef SQLITE_DYNLOAD
19364 dls_fini();
19365 #endif
19366 }
19367 break;
19368 case DLL_THREAD_DETACH:
19369 break;
19370 default:
19371 break;
19372 }
19373 return TRUE;
19374 }
19375
19376 /**
19377 * DLL entry point for WIN32.
19378 * @param hinst instance handle
19379 * @param reason reason code for entry point
19380 * @param reserved
19381 * @result always true
19382 */
19383
19384 int __stdcall
DllMain(HANDLE hinst,DWORD reason,LPVOID reserved)19385 DllMain(HANDLE hinst, DWORD reason, LPVOID reserved)
19386 {
19387 return LibMain(hinst, reason, reserved);
19388 }
19389
19390 #ifndef WITHOUT_INSTALLER
19391
19392 /**
19393 * Handler for driver installer/uninstaller error messages.
19394 * @param name name of API function for which to show error messages
19395 * @result true when error message retrieved
19396 */
19397
19398 static BOOL
InUnError(char * name)19399 InUnError(char *name)
19400 {
19401 WORD err = 1;
19402 DWORD code;
19403 char errmsg[301];
19404 WORD errlen, errmax = sizeof (errmsg) - 1;
19405 int sqlret;
19406 BOOL ret = FALSE;
19407
19408 do {
19409 errmsg[0] = '\0';
19410 sqlret = SQLInstallerError(err, &code, errmsg, errmax, &errlen);
19411 if (SQL_SUCCEEDED(sqlret)) {
19412 MessageBox(NULL, errmsg, name,
19413 MB_ICONSTOP | MB_OK | MB_TASKMODAL | MB_SETFOREGROUND);
19414 ret = TRUE;
19415 }
19416 err++;
19417 } while (sqlret != SQL_NO_DATA);
19418 return ret;
19419 }
19420
19421 /**
19422 * Built in driver installer/uninstaller.
19423 * @param remove true for uninstall
19424 * @param cmdline command line string of rundll32
19425 */
19426
19427 static BOOL
InUn(int remove,char * cmdline)19428 InUn(int remove, char *cmdline)
19429 {
19430 #ifdef SQLITE_HAS_CODEC
19431 static char *drivername = "SQLite4 ODBC Driver (SEE)";
19432 static char *dsname = "SQLite4 SEE Datasource";
19433 #else
19434 static char *drivername = "SQLite4 ODBC Driver";
19435 static char *dsname = "SQLite4 Datasource";
19436 #endif
19437 char *dllname, *p;
19438 char dllbuf[301], path[301], driver[300], attr[300], inst[400];
19439 WORD pathmax = sizeof (path) - 1, pathlen;
19440 DWORD usecnt, mincnt;
19441 int quiet = 0;
19442
19443 dllbuf[0] = '\0';
19444 GetModuleFileName(hModule, dllbuf, sizeof (dllbuf));
19445 p = strrchr(dllbuf, '\\');
19446 dllname = p ? (p + 1) : dllbuf;
19447 quiet = cmdline && strstr(cmdline, "quiet");
19448 if (SQLInstallDriverManager(path, pathmax, &pathlen)) {
19449 sprintf(driver, "%s;Driver=%s;Setup=%s;",
19450 drivername, dllname, dllname);
19451 p = driver;
19452 while (*p) {
19453 if (*p == ';') {
19454 *p = '\0';
19455 }
19456 ++p;
19457 }
19458 usecnt = 0;
19459 path[0] = '\0';
19460 SQLInstallDriverEx(driver, NULL, path, pathmax, NULL,
19461 ODBC_INSTALL_INQUIRY, &usecnt);
19462 pathlen = strlen(path);
19463 while (pathlen > 0 && path[pathlen - 1] == '\\') {
19464 --pathlen;
19465 path[pathlen] = '\0';
19466 }
19467 sprintf(driver, "%s;Driver=%s\\%s;Setup=%s\\%s;",
19468 drivername, path, dllname, path, dllname);
19469 p = driver;
19470 while (*p) {
19471 if (*p == ';') {
19472 *p = '\0';
19473 }
19474 ++p;
19475 }
19476 sprintf(inst, "%s\\%s", path, dllname);
19477 if (!remove && usecnt > 0) {
19478 /* first install try: copy over driver dll, keeping DSNs */
19479 if (GetFileAttributesA(dllbuf) != INVALID_FILE_ATTRIBUTES &&
19480 CopyFile(dllbuf, inst, 0)) {
19481 if (!quiet) {
19482 char buf[512];
19483
19484 sprintf(buf, "%s replaced.", drivername);
19485 MessageBox(NULL, buf, "Info",
19486 MB_ICONINFORMATION | MB_OK | MB_TASKMODAL |
19487 MB_SETFOREGROUND);
19488 }
19489 return TRUE;
19490 }
19491 }
19492 mincnt = remove ? 1 : 0;
19493 while (usecnt != mincnt) {
19494 if (!SQLRemoveDriver(driver, TRUE, &usecnt)) {
19495 break;
19496 }
19497 }
19498 if (remove) {
19499 if (usecnt && !SQLRemoveDriver(driver, TRUE, &usecnt)) {
19500 InUnError("SQLRemoveDriver");
19501 return FALSE;
19502 }
19503 if (!usecnt) {
19504 char buf[512];
19505
19506 DeleteFile(inst);
19507 if (!quiet) {
19508 sprintf(buf, "%s uninstalled.", drivername);
19509 MessageBox(NULL, buf, "Info",
19510 MB_ICONINFORMATION |MB_OK | MB_TASKMODAL |
19511 MB_SETFOREGROUND);
19512 }
19513 }
19514 sprintf(attr, "DSN=%s;Database=;", dsname);
19515 p = attr;
19516 while (*p) {
19517 if (*p == ';') {
19518 *p = '\0';
19519 }
19520 ++p;
19521 }
19522 SQLConfigDataSource(NULL, ODBC_REMOVE_SYS_DSN, drivername, attr);
19523 return TRUE;
19524 }
19525 if (GetFileAttributesA(dllbuf) == INVALID_FILE_ATTRIBUTES) {
19526 return FALSE;
19527 }
19528 if (strcasecmp(dllbuf, inst) != 0 && !CopyFile(dllbuf, inst, 0)) {
19529 char buf[512];
19530
19531 sprintf(buf, "Copy %s to %s failed.", dllbuf, inst);
19532 MessageBox(NULL, buf, "CopyFile",
19533 MB_ICONSTOP |MB_OK | MB_TASKMODAL | MB_SETFOREGROUND);
19534 return FALSE;
19535 }
19536 if (!SQLInstallDriverEx(driver, path, path, pathmax, &pathlen,
19537 ODBC_INSTALL_COMPLETE, &usecnt)) {
19538 InUnError("SQLInstallDriverEx");
19539 return FALSE;
19540 }
19541 sprintf(attr, "DSN=%s;Database=;", dsname);
19542 p = attr;
19543 while (*p) {
19544 if (*p == ';') {
19545 *p = '\0';
19546 }
19547 ++p;
19548 }
19549 SQLConfigDataSource(NULL, ODBC_REMOVE_SYS_DSN, drivername, attr);
19550 if (!SQLConfigDataSource(NULL, ODBC_ADD_SYS_DSN, drivername, attr)) {
19551 InUnError("SQLConfigDataSource");
19552 return FALSE;
19553 }
19554 if (!quiet) {
19555 char buf[512];
19556
19557 sprintf(buf, "%s installed.", drivername);
19558 MessageBox(NULL, buf, "Info",
19559 MB_ICONINFORMATION | MB_OK | MB_TASKMODAL |
19560 MB_SETFOREGROUND);
19561 }
19562 } else {
19563 InUnError("SQLInstallDriverManager");
19564 return FALSE;
19565 }
19566 return TRUE;
19567 }
19568
19569 /**
19570 * RunDLL32 entry point for driver installation.
19571 * @param hwnd window handle of caller
19572 * @param hinst of this DLL
19573 * @param lpszCmdLine rundll32 command line tail
19574 * @param nCmdShow ignored
19575 */
19576
19577 void CALLBACK
install(HWND hwnd,HINSTANCE hinst,LPSTR lpszCmdLine,int nCmdShow)19578 install(HWND hwnd, HINSTANCE hinst, LPSTR lpszCmdLine, int nCmdShow)
19579 {
19580 InUn(0, lpszCmdLine);
19581 }
19582
19583 /**
19584 * RunDLL32 entry point for driver uninstallation.
19585 * @param hwnd window handle of caller
19586 * @param hinst of this DLL
19587 * @param lpszCmdLine rundll32 command line tail
19588 * @param nCmdShow ignored
19589 */
19590
19591 void CALLBACK
uninstall(HWND hwnd,HINSTANCE hinst,LPSTR lpszCmdLine,int nCmdShow)19592 uninstall(HWND hwnd, HINSTANCE hinst, LPSTR lpszCmdLine, int nCmdShow)
19593 {
19594 InUn(1, lpszCmdLine);
19595 }
19596
19597 #endif /* WITHOUT_INSTALLER */
19598
19599 #ifndef WITHOUT_SHELL
19600
19601 /**
19602 * Setup argv vector from string
19603 * @param argcp pointer to argc
19604 * @param argvp pointer to argv
19605 * @param cmdline command line string
19606 * @param argv0 0th element for argv or NULL, must be static
19607 */
19608
19609 static void
setargv(int * argcp,char *** argvp,char * cmdline,char * argv0)19610 setargv(int *argcp, char ***argvp, char *cmdline, char *argv0)
19611 {
19612 char *p, *arg, *argspace, **argv;
19613 int argc, size, inquote, copy, slashes;
19614
19615 size = 2 + (argv0 ? 1 : 0);
19616 for (p = cmdline; *p != '\0'; p++) {
19617 if (ISSPACE(*p)) {
19618 size++;
19619 while (ISSPACE(*p)) {
19620 p++;
19621 }
19622 if (*p == '\0') {
19623 break;
19624 }
19625 }
19626 }
19627 argspace = malloc(size * sizeof (char *) + strlen(cmdline) + 1);
19628 argv = (char **) argspace;
19629 argspace += size * sizeof (char *);
19630 size--;
19631 argc = 0;
19632 if (argv0) {
19633 argv[argc++] = argv0;
19634 }
19635 p = cmdline;
19636 for (; argc < size; argc++) {
19637 argv[argc] = arg = argspace;
19638 while (ISSPACE(*p)) {
19639 p++;
19640 }
19641 if (*p == '\0') {
19642 break;
19643 }
19644 inquote = 0;
19645 slashes = 0;
19646 while (1) {
19647 copy = 1;
19648 while (*p == '\\') {
19649 slashes++;
19650 p++;
19651 }
19652 if (*p == '"') {
19653 if ((slashes & 1) == 0) {
19654 copy = 0;
19655 if (inquote && p[1] == '"') {
19656 p++;
19657 copy = 1;
19658 } else {
19659 inquote = !inquote;
19660 }
19661 }
19662 slashes >>= 1;
19663 }
19664 while (slashes) {
19665 *arg = '\\';
19666 arg++;
19667 slashes--;
19668 }
19669 if (*p == '\0' || (!inquote && ISSPACE(*p))) {
19670 break;
19671 }
19672 if (copy != 0) {
19673 *arg = *p;
19674 arg++;
19675 }
19676 p++;
19677 }
19678 *arg = '\0';
19679 argspace = arg + 1;
19680 }
19681 argv[argc] = 0;
19682 *argcp = argc;
19683 *argvp = argv;
19684 }
19685
19686 /**
19687 * RunDLL32 entry point for SQLite shell
19688 * @param hwnd window handle of caller
19689 * @param hinst of this DLL
19690 * @param lpszCmdLine rundll32 command line tail
19691 * @param nCmdShow ignored
19692 */
19693
19694 void CALLBACK
shell(HWND hwnd,HINSTANCE hinst,LPSTR lpszCmdLine,int nCmdShow)19695 shell(HWND hwnd, HINSTANCE hinst, LPSTR lpszCmdLine, int nCmdShow)
19696 {
19697 int argc, needcon = 0;
19698 char **argv;
19699 extern int sqlite4_main(int, char **);
19700 static const char *name = "SQLite4 Shell";
19701 DWORD ftype0, ftype1, ftype2;
19702
19703 ftype0 = GetFileType(GetStdHandle(STD_INPUT_HANDLE));
19704 ftype1 = GetFileType(GetStdHandle(STD_OUTPUT_HANDLE));
19705 ftype2 = GetFileType(GetStdHandle(STD_ERROR_HANDLE));
19706 if (ftype0 != FILE_TYPE_DISK && ftype0 != FILE_TYPE_CHAR &&
19707 ftype0 != FILE_TYPE_PIPE) {
19708 fclose(stdin);
19709 ++needcon;
19710 ftype0 = FILE_TYPE_UNKNOWN;
19711 }
19712 if (ftype1 != FILE_TYPE_DISK && ftype1 != FILE_TYPE_CHAR &&
19713 ftype1 != FILE_TYPE_PIPE) {
19714 fclose(stdout);
19715 ++needcon;
19716 ftype1 = FILE_TYPE_UNKNOWN;
19717 }
19718 if (ftype2 != FILE_TYPE_DISK && ftype2 != FILE_TYPE_CHAR &&
19719 ftype2 != FILE_TYPE_PIPE) {
19720 fclose(stderr);
19721 ++needcon;
19722 ftype2 = FILE_TYPE_UNKNOWN;
19723 }
19724 if (needcon > 0) {
19725 AllocConsole();
19726 SetConsoleTitle(name);
19727 }
19728 if (ftype0 == FILE_TYPE_UNKNOWN) {
19729 freopen("CONIN$", "r", stdin);
19730 }
19731 if (ftype1 == FILE_TYPE_UNKNOWN) {
19732 freopen("CONOUT$", "w", stdout);
19733 }
19734 if (ftype2 == FILE_TYPE_UNKNOWN) {
19735 freopen("CONOUT$", "w", stderr);
19736 }
19737 setargv(&argc, &argv, lpszCmdLine, (char *) name);
19738 sqlite4_main(argc, argv);
19739 }
19740
19741 #endif /* WITHOUT_SHELL */
19742
19743 #endif /* _WIN32 || _WIN64 */
19744
19745 #if defined(HAVE_ODBCINSTEXT_H) && (HAVE_ODBCINSTEXT_H)
19746
19747 /*
19748 * unixODBC property page for this driver,
19749 * may or may not work depending on unixODBC version.
19750 */
19751
19752 #include <odbcinstext.h>
19753
19754 int
ODBCINSTGetProperties(HODBCINSTPROPERTY prop)19755 ODBCINSTGetProperties(HODBCINSTPROPERTY prop)
19756 {
19757 static const char *instYN[] = { "No", "Yes", NULL };
19758 static const char *syncPragma[] = { "NORMAL", "OFF", "FULL", NULL };
19759 static const char *jmPragma[] = {
19760 "DELETE", "PERSIST", "OFF", "TRUNCATE", "MEMORY", "WAL", NULL
19761 };
19762
19763 prop->pNext = (HODBCINSTPROPERTY) malloc(sizeof (ODBCINSTPROPERTY));
19764 prop = prop->pNext;
19765 memset(prop, 0, sizeof (ODBCINSTPROPERTY));
19766 prop->nPromptType = ODBCINST_PROMPTTYPE_FILENAME;
19767 strncpy(prop->szName, "Database", INI_MAX_PROPERTY_NAME);
19768 strncpy(prop->szValue, "", INI_MAX_PROPERTY_VALUE);
19769 prop->pNext = (HODBCINSTPROPERTY) malloc(sizeof (ODBCINSTPROPERTY));
19770 prop = prop->pNext;
19771 memset(prop, 0, sizeof (ODBCINSTPROPERTY));
19772 prop->nPromptType = ODBCINST_PROMPTTYPE_TEXTEDIT;
19773 strncpy(prop->szName, "Timeout", INI_MAX_PROPERTY_NAME);
19774 strncpy(prop->szValue, "100000", INI_MAX_PROPERTY_VALUE);
19775 prop->pNext = (HODBCINSTPROPERTY) malloc(sizeof (ODBCINSTPROPERTY));
19776 prop = prop->pNext;
19777 memset(prop, 0, sizeof (ODBCINSTPROPERTY));
19778 prop->nPromptType = ODBCINST_PROMPTTYPE_COMBOBOX;
19779 prop->aPromptData = malloc(sizeof (instYN));
19780 memcpy(prop->aPromptData, instYN, sizeof (instYN));
19781 strncpy(prop->szName, "StepAPI", INI_MAX_PROPERTY_NAME);
19782 strncpy(prop->szValue, "No", INI_MAX_PROPERTY_VALUE);
19783 prop->pNext = (HODBCINSTPROPERTY) malloc(sizeof (ODBCINSTPROPERTY));
19784 prop = prop->pNext;
19785 memset(prop, 0, sizeof (ODBCINSTPROPERTY));
19786 prop->nPromptType = ODBCINST_PROMPTTYPE_COMBOBOX;
19787 prop->aPromptData = malloc(sizeof (instYN));
19788 memcpy(prop->aPromptData, instYN, sizeof (instYN));
19789 strncpy(prop->szName, "ShortNames", INI_MAX_PROPERTY_NAME);
19790 strncpy(prop->szValue, "No", INI_MAX_PROPERTY_VALUE);
19791 prop->pNext = (HODBCINSTPROPERTY) malloc(sizeof (ODBCINSTPROPERTY));
19792 prop = prop->pNext;
19793 memset(prop, 0, sizeof (ODBCINSTPROPERTY));
19794 prop->nPromptType = ODBCINST_PROMPTTYPE_COMBOBOX;
19795 prop->aPromptData = malloc(sizeof (instYN));
19796 memcpy(prop->aPromptData, instYN, sizeof (instYN));
19797 strncpy(prop->szName, "LongNames", INI_MAX_PROPERTY_NAME);
19798 strncpy(prop->szValue, "No", INI_MAX_PROPERTY_VALUE);
19799 prop->pNext = (HODBCINSTPROPERTY) malloc(sizeof (ODBCINSTPROPERTY));
19800 memset(prop, 0, sizeof (ODBCINSTPROPERTY));
19801 prop->nPromptType = ODBCINST_PROMPTTYPE_COMBOBOX;
19802 prop->aPromptData = malloc(sizeof (instYN));
19803 memcpy(prop->aPromptData, instYN, sizeof (instYN));
19804 strncpy(prop->szName, "NoCreat", INI_MAX_PROPERTY_NAME);
19805 strncpy(prop->szValue, "No", INI_MAX_PROPERTY_VALUE);
19806 #ifdef WINTERFACE
19807 prop->pNext = (HODBCINSTPROPERTY) malloc(sizeof (ODBCINSTPROPERTY));
19808 memset(prop, 0, sizeof (ODBCINSTPROPERTY));
19809 prop->nPromptType = ODBCINST_PROMPTTYPE_COMBOBOX;
19810 prop->aPromptData = malloc(sizeof (instYN));
19811 memcpy(prop->aPromptData, instYN, sizeof (instYN));
19812 strncpy(prop->szName, "NoWCHAR", INI_MAX_PROPERTY_NAME);
19813 strncpy(prop->szValue, "No", INI_MAX_PROPERTY_VALUE);
19814 #endif
19815 prop->pNext = (HODBCINSTPROPERTY) malloc(sizeof (ODBCINSTPROPERTY));
19816 memset(prop, 0, sizeof (ODBCINSTPROPERTY));
19817 prop->nPromptType = ODBCINST_PROMPTTYPE_COMBOBOX;
19818 prop->aPromptData = malloc(sizeof (instYN));
19819 memcpy(prop->aPromptData, instYN, sizeof (instYN));
19820 strncpy(prop->szName, "FKSupport", INI_MAX_PROPERTY_NAME);
19821 strncpy(prop->szValue, "No", INI_MAX_PROPERTY_VALUE);
19822 prop->pNext = (HODBCINSTPROPERTY) malloc(sizeof (ODBCINSTPROPERTY));
19823 prop = prop->pNext;
19824 memset(prop, 0, sizeof (ODBCINSTPROPERTY));
19825 prop->nPromptType = ODBCINST_PROMPTTYPE_COMBOBOX;
19826 prop->aPromptData = malloc(sizeof (syncPragma));
19827 memcpy(prop->aPromptData, syncPragma, sizeof (syncPragma));
19828 strncpy(prop->szName, "SyncPragma", INI_MAX_PROPERTY_NAME);
19829 strncpy(prop->szValue, "NORMAL", INI_MAX_PROPERTY_VALUE);
19830 prop->pNext = (HODBCINSTPROPERTY) malloc(sizeof (ODBCINSTPROPERTY));
19831 prop = prop->pNext;
19832 memset(prop, 0, sizeof (ODBCINSTPROPERTY));
19833 prop->nPromptType = ODBCINST_PROMPTTYPE_COMBOBOX;
19834 prop->aPromptData = malloc(sizeof (jmPragma));
19835 memcpy(prop->aPromptData, jmPragma, sizeof (jmPragma));
19836 strncpy(prop->szName, "JournalMode", INI_MAX_PROPERTY_NAME);
19837 strncpy(prop->szValue, "DELETE", INI_MAX_PROPERTY_VALUE);
19838 prop->pNext = (HODBCINSTPROPERTY) malloc(sizeof (ODBCINSTPROPERTY));
19839 prop = prop->pNext;
19840 memset(prop, 0, sizeof (ODBCINSTPROPERTY));
19841 prop->nPromptType = ODBCINST_PROMPTTYPE_TEXTEDIT;
19842 strncpy(prop->szName, "LoadExt", INI_MAX_PROPERTY_NAME);
19843 strncpy(prop->szValue, "", INI_MAX_PROPERTY_VALUE);
19844 prop->pNext = (HODBCINSTPROPERTY) malloc(sizeof (ODBCINSTPROPERTY));
19845 memset(prop, 0, sizeof (ODBCINSTPROPERTY));
19846 prop->nPromptType = ODBCINST_PROMPTTYPE_COMBOBOX;
19847 prop->aPromptData = malloc(sizeof (instYN));
19848 memcpy(prop->aPromptData, instYN, sizeof (instYN));
19849 strncpy(prop->szName, "BigInt", INI_MAX_PROPERTY_NAME);
19850 strncpy(prop->szValue, "No", INI_MAX_PROPERTY_VALUE);
19851 return 1;
19852 }
19853
19854 #endif /* HAVE_ODBCINSTEXT_H */
19855
19856 #ifdef SQLITE_DYNLOAD
19857
19858 /*
19859 * SQLite4 shared library/DLL stubs.
19860 */
19861
19862 static void
dls_void(void)19863 dls_void(void)
19864 {
19865 }
19866
19867 static int
dls_error(void)19868 dls_error(void)
19869 {
19870 return SQLITE4_ERROR;
19871 }
19872
19873 static int
dls_0(void)19874 dls_0(void)
19875 {
19876 return 0;
19877 }
19878
19879 #if 0
19880 static sqlite4_int64
19881 dls_0LL(void)
19882 {
19883 return 0;
19884 }
19885 #endif
19886
19887 static double
dls_00(void)19888 dls_00(void)
19889 {
19890 return 0;
19891 }
19892
19893 static void *
dls_null(void)19894 dls_null(void)
19895 {
19896 return NULL;
19897 }
19898
19899 static const char *
dls_empty(void)19900 dls_empty(void)
19901 {
19902 return "";
19903 }
19904
19905 static int
dls_snull(void)19906 dls_snull(void)
19907 {
19908 return SQLITE4_NULL;
19909 }
19910
19911 #define DLS_ENT(name, func) \
19912 { "sqlite4_" #name, offsetof(struct dl_sqlite4_funcs, name), \
19913 (void *) func }
19914
19915 #define DLS_ENT3(name, off, func) \
19916 { "sqlite4_" #name, offsetof(struct dl_sqlite4_funcs, off), \
19917 (void *) func }
19918
19919 #define DLS_END { NULL, 0, NULL }
19920
19921 static struct {
19922 const char *name;
19923 int offset;
19924 void *func;
19925 } dls_nametab[] = {
19926 DLS_ENT(bind_blob, dls_error),
19927 DLS_ENT(bind_double, dls_error),
19928 DLS_ENT(bind_int, dls_error),
19929 DLS_ENT(bind_int64, dls_error),
19930 DLS_ENT(bind_null, dls_error),
19931 DLS_ENT(bind_parameter_count, dls_0),
19932 DLS_ENT(bind_text, dls_error),
19933 DLS_ENT(changes, dls_0),
19934 DLS_ENT(close, dls_error),
19935 DLS_ENT(column_blob, dls_null),
19936 DLS_ENT(column_bytes, dls_0),
19937 DLS_ENT(column_count, dls_0),
19938 DLS_ENT(column_database_name, dls_empty),
19939 DLS_ENT(column_decltype, dls_empty),
19940 DLS_ENT(column_double, dls_00),
19941 DLS_ENT(column_name, dls_empty),
19942 DLS_ENT(column_origin_name, dls_null),
19943 DLS_ENT(column_table_name, dls_null),
19944 DLS_ENT(column_text, dls_null),
19945 DLS_ENT(column_type, dls_snull),
19946 DLS_ENT(create_function, dls_error),
19947 DLS_ENT(errcode, dls_error),
19948 DLS_ENT(errmsg, dls_empty),
19949 DLS_ENT(exec, dls_error),
19950 DLS_ENT(finalize, dls_error),
19951 DLS_ENT(free, free),
19952 DLS_ENT(interrupt, dls_void),
19953 #if 0
19954 DLS_ENT(last_insert_rowid, dls_0LL),
19955 #endif
19956 DLS_ENT(libversion, dls_empty),
19957 #if 0
19958 DLS_ENT(load_extension, dls_error),
19959 #endif
19960 DLS_ENT(malloc, malloc),
19961 DLS_ENT(mprintf, dls_null),
19962 DLS_ENT(open, dls_error),
19963 DLS_ENT(prepare, dls_error),
19964 DLS_ENT(profile, dls_null),
19965 DLS_ENT(realloc, realloc),
19966 DLS_ENT(reset, dls_error),
19967 DLS_ENT(result_blob, dls_void),
19968 DLS_ENT(result_error, dls_void),
19969 DLS_ENT(result_int, dls_void),
19970 DLS_ENT(result_null, dls_void),
19971 DLS_ENT(step, dls_error),
19972 #if defined(_WIN32) || defined(_WIN64)
19973 DLS_ENT3(strnicmp, xstrnicmp, _strnicmp),
19974 #else
19975 DLS_ENT3(strnicmp, xstrnicmp, strncasecmp),
19976 #endif
19977 #if 0
19978 DLS_ENT(table_column_metadata, dls_error),
19979 #endif
19980 DLS_ENT(trace, dls_null),
19981 DLS_ENT(user_data, dls_null),
19982 DLS_ENT(value_blob, dls_null),
19983 DLS_ENT(value_bytes, dls_0),
19984 DLS_ENT(value_text, dls_empty),
19985 DLS_ENT(value_type, dls_snull),
19986 DLS_END
19987 };
19988
19989 #if defined(_WIN32) || defined(_WIN64)
19990
19991 static HMODULE sqlite4_dll = 0;
19992
19993 static void
dls_init(void)19994 dls_init(void)
19995 {
19996 int i;
19997 static const char *dll_names[] = {
19998 "System.Data.SQLite.dll",
19999 "sqlite4.dll",
20000 NULL,
20001 };
20002
20003 i = 0;
20004 while (dll_names[i]) {
20005 sqlite4_dll = LoadLibrary(dll_names[i]);
20006 if (sqlite4_dll) {
20007 break;
20008 }
20009 ++i;
20010 }
20011 i = 0;
20012 while (dls_nametab[i].name) {
20013 void *func = 0, **loc;
20014
20015 if (sqlite4_dll) {
20016 func = (void *) GetProcAddress(sqlite4_dll, dls_nametab[i].name);
20017 }
20018 if (!func) {
20019 func = dls_nametab[i].func;
20020 }
20021 loc = (void **) ((char *) &dls_funcs + dls_nametab[i].offset);
20022 *loc = func;
20023 ++i;
20024 }
20025 if (!sqlite4_dll) {
20026 char buf[MAXPATHLEN], msg[MAXPATHLEN];
20027
20028 LoadString(hModule, IDS_DRVTITLE, buf, sizeof (buf));
20029 LoadString(hModule, IDS_DLLERR, msg, sizeof (msg));
20030 MessageBox(NULL, msg, buf,
20031 MB_ICONEXCLAMATION | MB_OK | MB_TASKMODAL |
20032 MB_SETFOREGROUND);
20033 }
20034 }
20035
20036 static void
dls_fini(void)20037 dls_fini(void)
20038 {
20039 if (sqlite4_dll) {
20040 FreeLibrary(sqlite4_dll);
20041 sqlite4_dll = 0;
20042 }
20043 }
20044
20045 #else
20046
20047 #include <dlfcn.h>
20048
20049 static void *libsqlite4_so = 0;
20050
20051 void
dls_init(void)20052 dls_init(void)
20053 {
20054 int i;
20055
20056 libsqlite4_so = dlopen("libsqlite4.so.0", RTLD_NOW | RTLD_GLOBAL);
20057 i = 0;
20058 while (dls_nametab[i].name) {
20059 void *func = 0, **loc;
20060
20061 if (libsqlite4_so) {
20062 func = dlsym(libsqlite4_so, dls_nametab[i].name);
20063 }
20064 if (!func) {
20065 func = dls_nametab[i].func;
20066 }
20067 loc = (void **) ((char *) &dls_funcs + dls_nametab[i].offset);
20068 *loc = func;
20069 ++i;
20070 }
20071 if (!libsqlite4_so) {
20072 const char errmsg[] = "sqlite4 shared library not found.\n";
20073
20074 write(2, errmsg, sizeof (errmsg) - 1);
20075 }
20076 }
20077
20078 void
dls_fini(void)20079 dls_fini(void)
20080 {
20081 if (libsqlite4_so) {
20082 dlclose(libsqlite4_so);
20083 libsqlite4_so = 0;
20084 }
20085 }
20086
20087 #endif
20088
20089 #endif
20090
20091 /*
20092 * Local Variables:
20093 * mode: c
20094 * c-basic-offset: 4
20095 * fill-column: 78
20096 * tab-width: 8
20097 * End:
20098 */
20099