sqlite3odbc.c
Go to the documentation of this file.
1
14#if defined(SQLITE_HAS_CODEC) && defined(SQLITE_API)
15#undef WITH_SQLITE_DLLS
16#undef SQLITE_DYNLOAD
17#include "sqlite3.c"
18#endif
19
20#if defined(WITH_SQLITE_DLLS) && (WITH_SQLITE_DLLS > 1)
21#define SQLITE_DYNLOAD 1
22#undef HAVE_SQLITE3CLOSEV2
23#endif
24
25#include "sqlite3odbc.h"
26
27#ifdef SQLITE_DYNLOAD
28
29#undef MEMORY_DEBUG
30
31#if defined(_WIN32) || defined(_WIN64)
32static void dls_init(void);
33static void dls_fini(void);
34#else
35void dls_init(void);
36void dls_fini(void);
37#endif
38
39static struct dl_sqlite3_funcs {
40 void (*activate_see)(const char *p0);
41 int (*bind_blob)(sqlite3_stmt *p0, int p1, const void *p2, int p3,
42 void (*p4)(void *));
43 int (*bind_double)(sqlite3_stmt *p0, int p1, double p2);
44 int (*bind_int)(sqlite3_stmt *p0, int p1, int p2);
45 int (*bind_int64)(sqlite3_stmt *p0, int p1, sqlite_int64 p2);
46 int (*bind_null)(sqlite3_stmt *p0, int p1);
47 int (*bind_parameter_count)(sqlite3_stmt *p0);
48 int (*bind_text)(sqlite3_stmt *p0, int p1, const char *p2, int p3,
49 void (*p4)(void *));
50 int (*busy_handler)(sqlite3 *p0, int (*p2)(void *, int), void *p3);
51 int (*changes)(sqlite3 *p0);
52 int (*close)(sqlite3 *p0);
53 const void * (*column_blob)(sqlite3_stmt *p0, int p1);
54 int (*column_bytes)(sqlite3_stmt *p0, int p1);
55 int (*column_count)(sqlite3_stmt *p0);
56 const char * (*column_database_name)(sqlite3_stmt *p0, int p1);
57 const char * (*column_decltype)(sqlite3_stmt *p0, int p1);
58 double (*column_double)(sqlite3_stmt *p0, int p1);
59 const char * (*column_name)(sqlite3_stmt *p0, int p1);
60 const char * (*column_origin_name)(sqlite3_stmt *p0, int p1);
61 const char * (*column_table_name)(sqlite3_stmt *p0, int p1);
62 const unsigned char * (*column_text)(sqlite3_stmt *p0, int p1);
63 int (*column_type)(sqlite3_stmt *p0, int p1);
64 int (*create_function)(sqlite3 *p0, const char *p1, int p2, int p3,
65 void *p4,
66 void (*p5)(sqlite3_context *, int, sqlite3_value **),
67 void (*p6)(sqlite3_context *, int, sqlite3_value **),
68 void (*p7)(sqlite3_context *));
69 int (*enable_load_extension)(sqlite3 *p0, int p1);
70 int (*errcode)(sqlite3 *p0);
71 const char * (*errmsg)(sqlite3 *p0);
72 int (*exec)(sqlite3 *p0, const char *p1,
73 int (*p2)(void *, int, char **, char **),
74 void *p3, char **p4);
75 int (*finalize)(sqlite3_stmt *p0);
76 void (*free)(void *p0);
77 void (*free_table)(char **p0);
78 int (*get_table)(sqlite3 *p0, const char *p1, char ***p2,
79 int *p3, int *p4, char **p5);
80 void (*interrupt)(sqlite3 *p0);
81 int (*key)(sqlite3 *p0, const void *p1, int p2);
82 sqlite_int64 (*last_insert_rowid)(sqlite3 *p0);
83 const char * (*libversion)(void);
84 int (*load_extension)(sqlite3 *p0, const char *p1, const char *p2,
85 char **p3);
86 void * (*malloc)(int p0);
87 char * (*mprintf)(const char *p0, ...);
88 int (*open)(const char *p0, sqlite3 **p1);
89 int (*open16)(const void *p0, sqlite3 **p1);
90 int (*open_v2)(const char *p0, sqlite3 **p1, int p2, const char *p3);
91 int (*prepare)(sqlite3 *p0, const char *p1, int p2, sqlite3_stmt **p3,
92 const char **p4);
93 int (*prepare_v2)(sqlite3 *p0, const char *p1, int p2, sqlite3_stmt **p3,
94 const char **p4);
95 void * (*profile)(sqlite3 *p0,
96 void (*p1)(void *, const char *, sqlite3_uint64),
97 void *p2);
98 void * (*realloc)(void *p0, int p1);
99 int (*rekey)(sqlite3 *p0, const void *p1, int p2);
100 int (*reset)(sqlite3_stmt *p0);
101 void (*result_blob)(sqlite3_context *p0, const void *p1,
102 int p2, void (*p3)(void *));
103 void (*result_error)(sqlite3_context *p0, const char *p1, int p2);
104 void (*result_int)(sqlite3_context *p0, int p1);
105 void (*result_null)(sqlite3_context *p0);
106 int (*step)(sqlite3_stmt *p0);
107 int (*xstrnicmp)(const char *p0, const char *p1, int p2);
108 int (*table_column_metadata)(sqlite3 *p0, const char *p1,
109 const char *p2, const char *p3,
110 char const **p4, char const **p5,
111 int *p6, int *p7, int *p8);
112 void * (*trace)(sqlite3 *p0, void (*p1)(void *, const char *), void *p2);
113 void * (*user_data)(sqlite3_context *p0);
114 const void * (*value_blob)(sqlite3_value *p0);
115 int (*value_bytes)(sqlite3_value *p0);
116 const unsigned char * (*value_text)(sqlite3_value *p0);
117 int (*value_type)(sqlite3_value *p0);
118} dls_funcs;
119
120#define sqlite3_activate_see dls_funcs.activate_see
121#define sqlite3_bind_blob dls_funcs.bind_blob
122#define sqlite3_bind_double dls_funcs.bind_double
123#define sqlite3_bind_int dls_funcs.bind_int
124#define sqlite3_bind_int64 dls_funcs.bind_int64
125#define sqlite3_bind_null dls_funcs.bind_null
126#define sqlite3_bind_parameter_count dls_funcs.bind_parameter_count
127#define sqlite3_bind_text dls_funcs.bind_text
128#define sqlite3_busy_handler dls_funcs.busy_handler
129#define sqlite3_changes dls_funcs.changes
130#define sqlite3_close dls_funcs.close
131#define sqlite3_column_blob dls_funcs.column_blob
132#define sqlite3_column_bytes dls_funcs.column_bytes
133#define sqlite3_column_count dls_funcs.column_count
134#define sqlite3_column_database_name dls_funcs.column_database_name
135#define sqlite3_column_decltype dls_funcs.column_decltype
136#define sqlite3_column_double dls_funcs.column_double
137#define sqlite3_column_name dls_funcs.column_name
138#define sqlite3_column_origin_name dls_funcs.column_origin_name
139#define sqlite3_column_table_name dls_funcs.column_table_name
140#define sqlite3_column_text dls_funcs.column_text
141#define sqlite3_column_type dls_funcs.column_type
142#define sqlite3_create_function dls_funcs.create_function
143#define sqlite3_enable_load_extension dls_funcs.enable_load_extension
144#define sqlite3_errcode dls_funcs.errcode
145#define sqlite3_errmsg dls_funcs.errmsg
146#define sqlite3_exec dls_funcs.exec
147#define sqlite3_finalize dls_funcs.finalize
148#define sqlite3_free dls_funcs.free
149#define sqlite3_free_table dls_funcs.free_table
150#define sqlite3_get_table dls_funcs.get_table
151#define sqlite3_interrupt dls_funcs.interrupt
152#define sqlite3_key dls_funcs.key
153#define sqlite3_last_insert_rowid dls_funcs.last_insert_rowid
154#define sqlite3_libversion dls_funcs.libversion
155#define sqlite3_load_extension dls_funcs.load_extension
156#define sqlite3_malloc dls_funcs.malloc
157#define sqlite3_mprintf dls_funcs.mprintf
158#define sqlite3_open dls_funcs.open
159#define sqlite3_open16 dls_funcs.open16
160#define sqlite3_open_v2 dls_funcs.open_v2
161#define sqlite3_prepare dls_funcs.prepare
162#define sqlite3_prepare_v2 dls_funcs.prepare_v2
163#define sqlite3_profile dls_funcs.profile
164#define sqlite3_realloc dls_funcs.realloc
165#define sqlite3_rekey dls_funcs.rekey
166#define sqlite3_reset dls_funcs.reset
167#define sqlite3_result_blob dls_funcs.result_blob
168#define sqlite3_result_error dls_funcs.result_error
169#define sqlite3_result_int dls_funcs.result_int
170#define sqlite3_result_null dls_funcs.result_null
171#define sqlite3_step dls_funcs.step
172#define sqlite3_strnicmp dls_funcs.xstrnicmp
173#define sqlite3_table_column_metadata dls_funcs.table_column_metadata
174#define sqlite3_trace dls_funcs.trace
175#define sqlite3_user_data dls_funcs.user_data
176#define sqlite3_value_blob dls_funcs.value_blob
177#define sqlite3_value_bytes dls_funcs.value_bytes
178#define sqlite3_value_text dls_funcs.value_text
179#define sqlite3_value_type dls_funcs.value_type
180
181#endif
182
183#ifndef WITHOUT_WINTERFACE
184#define WINTERFACE
185#define WCHARSUPPORT
186#endif
187
188#if !defined(_WIN32) && !defined(_WIN64)
189#if !defined(WCHARSUPPORT) && defined(HAVE_SQLWCHAR) && (HAVE_SQLWCHAR)
190#define WCHARSUPPORT
191#endif
192#endif
193
194#if defined(WINTERFACE)
195#include <sqlucode.h>
196#endif
197
198#if defined(_WIN32) || defined(_WIN64)
199#include "resource3.h"
200#define ODBC_INI "ODBC.INI"
201#ifndef DRIVER_VER_INFO
202#define DRIVER_VER_INFO VERSION
203#endif
204#else
205#define ODBC_INI ".odbc.ini"
206#endif
207
208#ifndef DRIVER_VER_INFO
209#define DRIVER_VER_INFO "0.0"
210#endif
211
212#ifndef COLATTRIBUTE_LAST_ARG_TYPE
213#ifdef _WIN64
214#define COLATTRIBUTE_LAST_ARG_TYPE SQLLEN *
215#else
216#define COLATTRIBUTE_LAST_ARG_TYPE SQLPOINTER
217#endif
218#endif
219
220#ifndef SETSTMTOPTION_LAST_ARG_TYPE
221#define SETSTMTOPTION_LAST_ARG_TYPE SQLROWCOUNT
222#endif
223
224#undef min
225#define min(a, b) ((a) < (b) ? (a) : (b))
226#undef max
227#define max(a, b) ((a) < (b) ? (b) : (a))
228
229#ifndef PTRDIFF_T
230#define PTRDIFF_T int
231#endif
232
233#define array_size(x) (sizeof (x) / sizeof (x[0]))
234
235#define stringify1(s) #s
236#define stringify(s) stringify1(s)
237
238#define verinfo(maj, min, lev) ((maj) << 16 | (min) << 8 | (lev))
239
240/* Column meta data from SQLite support */
241#undef FULL_METADATA
242#if defined(HAVE_SQLITE3TABLECOLUMNMETADATA) && (HAVE_SQLITE3TABLECOLUMNMETADATA)
243#if defined(HAVE_SQLITE3COLUMNDATABASENAME) && (HAVE_SQLITE3COLUMNDATABASENAME)
244#if defined(HAVE_SQLITE3COLUMNTABLENAME) && (HAVE_SQLITE3COLUMNTABLENAME)
245#if defined(HAVE_SQLITE3COLUMNORIGINNAME) && (HAVE_SQLITE3COLUMNORIGINNAME)
246#define FULL_METADATA 1
247#endif
248#endif
249#endif
250#endif
251
252/* Column types for static string column descriptions (SQLTables etc.) */
253
254#if defined(WINTERFACE) && !defined(_WIN32) && !defined(_WIN64)
255#define SCOL_VARCHAR SQL_WVARCHAR
256#define SCOL_CHAR SQL_WCHAR
257#else
258#define SCOL_VARCHAR SQL_VARCHAR
259#define SCOL_CHAR SQL_CHAR
260#endif
261
262#define ENV_MAGIC 0x53544145
263#define DBC_MAGIC 0x53544144
264#define DEAD_MAGIC 0xdeadbeef
265
272typedef struct dstr {
273 int len;
274 int max;
275 int oom;
276 char buffer[1];
278
279static const char *xdigits = "0123456789ABCDEFabcdef";
280
281#ifdef MEMORY_DEBUG
282
283static void *
284xmalloc_(int n, char *file, int line)
285{
286 int nn = n + 4 * sizeof (long);
287 long *p;
288
289 p = malloc(nn);
290 if (!p) {
291#if (MEMORY_DEBUG > 1)
292 fprintf(stderr, "malloc\t%d\tNULL\t%s:%d\n", n, file, line);
293#endif
294 return NULL;
295 }
296 p[0] = 0xdead1234;
297 nn = nn / sizeof (long) - 1;
298 p[1] = n;
299 p[nn] = 0xdead5678;
300#if (MEMORY_DEBUG > 1)
301 fprintf(stderr, "malloc\t%d\t%p\t%s:%d\n", n, &p[2], file, line);
302#endif
303 return (void *) &p[2];
304}
305
306static void *
307xrealloc_(void *old, int n, char *file, int line)
308{
309 int nn = n + 4 * sizeof (long), nnn;
310 long *p, *pp;
311
312 if (n == 0 || !old) {
313 return xmalloc_(n, file, line);
314 }
315 p = &((long *) old)[-2];
316 if (p[0] != 0xdead1234) {
317 fprintf(stderr, "*** low end corruption @ %p\n", old);
318 abort();
319 }
320 nnn = p[1] + 4 * sizeof (long);
321 nnn = nnn / sizeof (long) - 1;
322 if (p[nnn] != 0xdead5678) {
323 fprintf(stderr, "*** high end corruption @ %p\n", old);
324 abort();
325 }
326 pp = realloc(p, nn);
327 if (!pp) {
328#if (MEMORY_DEBUG > 1)
329 fprintf(stderr, "realloc\t%p,%d\tNULL\t%s:%d\n", old, n, file, line);
330#endif
331 return NULL;
332 }
333#if (MEMORY_DEBUG > 1)
334 fprintf(stderr, "realloc\t%p,%d\t%p\t%s:%d\n", old, n, &pp[2], file, line);
335#endif
336 p = pp;
337 p[1] = n;
338 nn = nn / sizeof (long) - 1;
339 p[nn] = 0xdead5678;
340 return (void *) &p[2];
341}
342
343static void
344xfree_(void *x, char *file, int line)
345{
346 long *p;
347 int n;
348
349 if (!x) {
350 return;
351 }
352 p = &((long *) x)[-2];
353 if (p[0] != 0xdead1234) {
354 fprintf(stderr, "*** low end corruption @ %p\n", x);
355 abort();
356 }
357 n = p[1] + 4 * sizeof (long);
358 n = n / sizeof (long) - 1;
359 if (p[n] != 0xdead5678) {
360 fprintf(stderr, "*** high end corruption @ %p\n", x);
361 abort();
362 }
363#if (MEMORY_DEBUG > 1)
364 fprintf(stderr, "free\t%p\t\t%s:%d\n", x, file, line);
365#endif
366 free(p);
367}
368
369static void
370xfree__(void *x)
371{
372 xfree_(x, "unknown location", 0);
373}
374
375static char *
376xstrdup_(const char *str, char *file, int line)
377{
378 char *p;
379
380 if (!str) {
381#if (MEMORY_DEBUG > 1)
382 fprintf(stderr, "strdup\tNULL\tNULL\t%s:%d\n", file, line);
383#endif
384 return NULL;
385 }
386 p = xmalloc_(strlen(str) + 1, file, line);
387 if (p) {
388 strcpy(p, str);
389 }
390#if (MEMORY_DEBUG > 1)
391 fprintf(stderr, "strdup\t%p\t%p\t%s:%d\n", str, p, file, line);
392#endif
393 return p;
394}
395
396#define xmalloc(x) xmalloc_(x, __FILE__, __LINE__)
397#define xrealloc(x,y) xrealloc_(x, y, __FILE__, __LINE__)
398#define xfree(x) xfree_(x, __FILE__, __LINE__)
399#define xstrdup(x) xstrdup_(x, __FILE__, __LINE__)
400
401#else
402
403#define xmalloc(x) sqlite3_malloc(x)
404#define xrealloc(x,y) sqlite3_realloc(x, y)
405#define xfree(x) sqlite3_free(x)
406#define xstrdup(x) strdup_(x)
407
408#endif
409
410#if defined(_WIN32) || defined(_WIN64)
411
412#define vsnprintf _vsnprintf
413#define snprintf _snprintf
414#define strcasecmp _stricmp
415#define strncasecmp _strnicmp
416
417#ifdef _MSC_VER
418#define strtoll _strtoi64
419#define strtoull _strtoui64
420#endif
421
422static HINSTANCE NEAR hModule; /* Saved module handle for resources */
423
424#endif
425
426#ifdef HAVE_SQLITE3STRNICMP
427#undef strncasecmp
428#define strncasecmp(A,B,C) sqlite3_strnicmp(A,B,C)
429#undef strcasecmp
430#define strcasecmp(A,B) strcasecmp_(A,B)
431
432#if defined(__GNUC__) && (__GNUC__ >= 2)
433static int strcasecmp_(const char *a, const char *b)
434 __attribute__((__unused__));
435#endif
436
437static int strcasecmp_(const char *a, const char *b)
438{
439 int c = strlen(a), d = strlen(b);
440
441 if (c > d) {
442 return strncasecmp(a, b, c);
443 }
444 return strncasecmp(a, b, d);
445}
446#endif
447
448#if defined(_WIN32) || defined(_WIN64)
449
450/*
451 * SQLHENV, SQLHDBC, and SQLHSTMT synchronization
452 * is done using a critical section in ENV and DBC
453 * structures.
454 */
455
456#define HDBC_LOCK(hdbc) \
457{ \
458 DBC *d; \
459 \
460 if ((hdbc) == SQL_NULL_HDBC) { \
461 return SQL_INVALID_HANDLE; \
462 } \
463 d = (DBC *) (hdbc); \
464 if (d->magic != DBC_MAGIC) { \
465 return SQL_INVALID_HANDLE; \
466 } \
467 EnterCriticalSection(&d->cs); \
468 d->owner = GetCurrentThreadId(); \
469}
470
471#define HDBC_UNLOCK(hdbc) \
472 if ((hdbc) != SQL_NULL_HDBC) { \
473 DBC *d; \
474 \
475 d = (DBC *) (hdbc); \
476 if (d->magic == DBC_MAGIC) { \
477 d->owner = 0; \
478 LeaveCriticalSection(&d->cs); \
479 } \
480 }
481
482#define HSTMT_LOCK(hstmt) \
483{ \
484 DBC *d; \
485 \
486 if ((hstmt) == SQL_NULL_HSTMT) { \
487 return SQL_INVALID_HANDLE; \
488 } \
489 d = (DBC *) ((STMT *) (hstmt))->dbc; \
490 if (d->magic != DBC_MAGIC) { \
491 return SQL_INVALID_HANDLE; \
492 } \
493 EnterCriticalSection(&d->cs); \
494 d->owner = GetCurrentThreadId(); \
495}
496
497#define HSTMT_UNLOCK(hstmt) \
498 if ((hstmt) != SQL_NULL_HSTMT) { \
499 DBC *d; \
500 \
501 d = (DBC *) ((STMT *) (hstmt))->dbc; \
502 if (d->magic == DBC_MAGIC) { \
503 d->owner = 0; \
504 LeaveCriticalSection(&d->cs); \
505 } \
506 }
507
508#else
509
510/*
511 * On UN*X assume that we are single-threaded or
512 * the driver manager provides serialization for us.
513 *
514 * In iODBC (3.52.x) serialization can be turned
515 * on using the DSN property "ThreadManager=yes".
516 *
517 * In unixODBC that property is named
518 * "Threading=0-3" and takes one of these values:
519 *
520 * 0 - no protection
521 * 1 - statement level protection
522 * 2 - connection level protection
523 * 3 - environment level protection
524 *
525 * unixODBC 2.2.11 uses environment level protection
526 * by default when it has been built with pthread
527 * support.
528 */
529
530#define HDBC_LOCK(hdbc)
531#define HDBC_UNLOCK(hdbc)
532#define HSTMT_LOCK(hdbc)
533#define HSTMT_UNLOCK(hdbc)
534
535#endif
536
537#if defined(ENABLE_NVFS) && (ENABLE_NVFS)
538extern void nvfs_init(void);
539extern const char *nvfs_makevfs(const char *);
540#endif
541
542/*
543 * tolower() replacement w/o locale
544 */
545
546static const char upper_chars[] = "ABCDEFGHIJKLMNOPQRSTUVWXYZ";
547static const char lower_chars[] = "abcdefghijklmnopqrstuvwxyz";
548
549static int
551{
552 if (c) {
553 char *p = strchr(upper_chars, c);
554
555 if (p) {
556 c = lower_chars[p - upper_chars];
557 }
558 }
559 return c;
560}
561
562/*
563 * isdigit() replacement w/o ctype.h
564 */
565
566static const char digit_chars[] = "0123456789";
567
568#define ISDIGIT(c) \
569 ((c) && strchr(digit_chars, (c)) != NULL)
570
571/*
572 * isspace() replacement w/o ctype.h
573 */
574
575static const char space_chars[] = " \f\n\r\t\v";
576
577#define ISSPACE(c) \
578 ((c) && strchr(space_chars, (c)) != NULL)
579
580
581/*
582 * Forward declarations of static functions.
583 */
584
585static void dbtraceapi(DBC *d, char *fn, const char *sql);
586static void freedyncols(STMT *s);
587static void freeresult(STMT *s, int clrcols);
588static void freerows(char **rowp);
589static void unbindcols(STMT *s);
590static void s3stmt_drop(STMT *s);
591
592static SQLRETURN drvexecute(SQLHSTMT stmt, int initial);
593static SQLRETURN freestmt(HSTMT stmt);
594static SQLRETURN mkbindcols(STMT *s, int ncols);
595static SQLRETURN setupdyncols(STMT *s, sqlite3_stmt *s3stmt, int *ncolsp);
596static SQLRETURN setupparbuf(STMT *s, BINDPARM *p);
597static SQLRETURN starttran(STMT *s);
598static SQLRETURN setupparam(STMT *s, char *sql, int pnum);
599static SQLRETURN getrowdata(STMT *s, SQLUSMALLINT col, SQLSMALLINT otype,
600 SQLPOINTER val, SQLINTEGER len, SQLLEN *lenp,
601 int partial);
602
603#if (defined(_WIN32) || defined(_WIN64)) && defined(WINTERFACE)
604/* MS Access hack part 1 (reserved error -7748) */
605static COL *statSpec2P, *statSpec3P;
606#endif
607
608#if (MEMORY_DEBUG < 1)
615static char *
616strdup_(const char *str)
617{
618 char *p = NULL;
619
620 if (str) {
621 p = xmalloc(strlen(str) + 1);
622 if (p) {
623 strcpy(p, str);
624 }
625 }
626 return p;
627}
628#endif
629
637static dstr *
638dsappend(dstr *dsp, const char *str)
639{
640 int len;
641
642 if (!str) {
643 return dsp;
644 }
645 len = strlen(str);
646 if (!dsp) {
647 int max = 256;
648
649 if (max < len) {
650 max += len;
651 }
652 dsp = xmalloc(max + sizeof (*dsp));
653 if (dsp) {
654 dsp->max = max;
655 dsp->len = dsp->oom = 0;
656 goto copy;
657 }
658 return dsp;
659 }
660 if (dsp->oom) {
661 return dsp;
662 }
663 if (dsp->len + len > dsp->max) {
664 int max = dsp->max + len + 256;
665 dstr *ndsp = xrealloc(dsp, max + sizeof (*dsp));
666
667 if (!ndsp) {
668 strcpy(dsp->buffer, "OUT OF MEMORY");
669 dsp->max = dsp->len = 13;
670 dsp->oom = 1;
671 return dsp;
672 }
673 dsp = ndsp;
674 dsp->max = max;
675 }
676copy:
677 strcpy(dsp->buffer + dsp->len, str);
678 dsp->len += len;
679 return dsp;
680}
681
689static dstr *
690dsappendq(dstr *dsp, const char *str)
691{
692 int len;
693 const char *p;
694 char *q;
695
696 if (!str) {
697 return dsp;
698 }
699 len = strlen(str);
700 for (p = str; *p; ++p) {
701 if (p[0] == '"') {
702 ++len;
703 }
704 }
705 len += 2;
706 if (!dsp) {
707 int max = 256;
708
709 if (max < len) {
710 max += len;
711 }
712 dsp = xmalloc(max + sizeof (*dsp));
713 if (dsp) {
714 dsp->max = max;
715 dsp->len = dsp->oom = 0;
716 goto copy;
717 }
718 return dsp;
719 }
720 if (dsp->oom) {
721 return dsp;
722 }
723 if (dsp->len + len > dsp->max) {
724 int max = dsp->max + len + 256;
725 dstr *ndsp = xrealloc(dsp, max + sizeof (*dsp));
726
727 if (!ndsp) {
728 strcpy(dsp->buffer, "OUT OF MEMORY");
729 dsp->max = dsp->len = 13;
730 dsp->oom = 1;
731 return dsp;
732 }
733 dsp = ndsp;
734 dsp->max = max;
735 }
736copy:
737 q = dsp->buffer + dsp->len;
738 *q++ = '"';
739 for (p = str; *p; ++p) {
740 *q++ = *p;
741 if (p[0] == '"') {
742 *q++ = '"';
743 }
744 }
745 *q++ = '"';
746 *q = '\0';
747 dsp->len += len;
748 return dsp;
749}
750
757static const char *
759{
760 if (dsp) {
761 return (const char *) dsp->buffer;
762 }
763 return "ERROR";
764}
765
772static int
774{
775 return !dsp || dsp->oom;
776}
777
783static void
785{
786 if (dsp) {
787 xfree(dsp);
788 }
789}
790
791#ifdef WCHARSUPPORT
792
799static int
800uc_strlen(SQLWCHAR *str)
801{
802 int len = 0;
803
804 if (str) {
805 while (*str) {
806 ++len;
807 ++str;
808 }
809 }
810 return len;
811}
812
821static SQLWCHAR *
822uc_strncpy(SQLWCHAR *dest, SQLWCHAR *src, int len)
823{
824 int i = 0;
825
826 while (i < len) {
827 if (!src[i]) {
828 break;
829 }
830 dest[i] = src[i];
831 ++i;
832 }
833 if (i < len) {
834 dest[i] = 0;
835 }
836 return dest;
837}
838
847static void
848uc_from_utf_buf(unsigned char *str, int len, SQLWCHAR *uc, int ucLen)
849{
850 ucLen = ucLen / sizeof (SQLWCHAR);
851 if (!uc || ucLen < 0) {
852 return;
853 }
854 if (len < 0) {
855 len = ucLen * 5;
856 }
857 uc[0] = 0;
858 if (str) {
859 int i = 0;
860
861 while (i < len && *str && i < ucLen) {
862 unsigned char c = str[0];
863
864 if (c < 0x80) {
865 uc[i++] = c;
866 ++str;
867 } else if (c <= 0xc1 || c >= 0xf5) {
868 /* illegal, ignored */
869 ++str;
870 } else if (c < 0xe0) {
871 if ((str[1] & 0xc0) == 0x80) {
872 unsigned long t = ((c & 0x1f) << 6) | (str[1] & 0x3f);
873
874 uc[i++] = t;
875 str += 2;
876 } else {
877 uc[i++] = c;
878 ++str;
879 }
880 } else if (c < 0xf0) {
881 if ((str[1] & 0xc0) == 0x80 && (str[2] & 0xc0) == 0x80) {
882 unsigned long t = ((c & 0x0f) << 12) |
883 ((str[1] & 0x3f) << 6) | (str[2] & 0x3f);
884
885 uc[i++] = t;
886 str += 3;
887 } else {
888 uc[i++] = c;
889 ++str;
890 }
891 } else if (c < 0xf8) {
892 if ((str[1] & 0xc0) == 0x80 && (str[2] & 0xc0) == 0x80 &&
893 (str[3] & 0xc0) == 0x80) {
894 unsigned long t = ((c & 0x03) << 18) |
895 ((str[1] & 0x3f) << 12) | ((str[2] & 0x3f) << 6) |
896 (str[3] & 0x3f);
897
898 if (sizeof (SQLWCHAR) == 2 * sizeof (char) &&
899 t >= 0x10000) {
900 t -= 0x10000;
901 uc[i++] = 0xd800 | ((t >> 10) & 0x3ff);
902 if (i >= ucLen) {
903 break;
904 }
905 t = 0xdc00 | (t & 0x3ff);
906 }
907 uc[i++] = t;
908 str += 4;
909 } else {
910 uc[i++] = c;
911 ++str;
912 }
913 } else {
914 /* ignore */
915 ++str;
916 }
917 }
918 if (i < ucLen) {
919 uc[i] = 0;
920 }
921 }
922}
923
931static SQLWCHAR *
932uc_from_utf(unsigned char *str, int len)
933{
934 SQLWCHAR *uc = NULL;
935 int ucLen;
936
937 if (str) {
938 if (len == SQL_NTS) {
939 len = strlen((char *) str);
940 }
941 ucLen = sizeof (SQLWCHAR) * (len + 1);
942 uc = xmalloc(ucLen);
943 if (uc) {
944 uc_from_utf_buf(str, len, uc, ucLen);
945 }
946 }
947 return uc;
948}
949
957static char *
958uc_to_utf(SQLWCHAR *str, int len)
959{
960 int i;
961 char *cp, *ret = NULL;
962
963 if (!str) {
964 return ret;
965 }
966 if (len == SQL_NTS) {
967 len = uc_strlen(str);
968 } else {
969 len = len / sizeof (SQLWCHAR);
970 }
971 cp = xmalloc(len * 6 + 1);
972 if (!cp) {
973 return ret;
974 }
975 ret = cp;
976 for (i = 0; i < len; i++) {
977 unsigned long c = str[i];
978
979 if (sizeof (SQLWCHAR) == 2 * sizeof (char)) {
980 c &= 0xffff;
981 }
982 if (c < 0x80) {
983 *cp++ = c;
984 } else if (c < 0x800) {
985 *cp++ = 0xc0 | ((c >> 6) & 0x1f);
986 *cp++ = 0x80 | (c & 0x3f);
987 } else if (c < 0x10000) {
988 if (sizeof (SQLWCHAR) == 2 * sizeof (char) &&
989 c >= 0xd800 && c <= 0xdbff && i + 1 < len) {
990 unsigned long c2 = str[i + 1] & 0xffff;
991
992 if (c2 >= 0xdc00 && c2 <= 0xdfff) {
993 c = (((c & 0x3ff) << 10) | (c2 & 0x3ff)) + 0x10000;
994 *cp++ = 0xf0 | ((c >> 18) & 0x07);
995 *cp++ = 0x80 | ((c >> 12) & 0x3f);
996 *cp++ = 0x80 | ((c >> 6) & 0x3f);
997 *cp++ = 0x80 | (c & 0x3f);
998 ++i;
999 continue;
1000 }
1001 }
1002 *cp++ = 0xe0 | ((c >> 12) & 0x0f);
1003 *cp++ = 0x80 | ((c >> 6) & 0x3f);
1004 *cp++ = 0x80 | (c & 0x3f);
1005 } else if (c <= 0x10ffff) {
1006 *cp++ = 0xf0 | ((c >> 18) & 0x07);
1007 *cp++ = 0x80 | ((c >> 12) & 0x3f);
1008 *cp++ = 0x80 | ((c >> 6) & 0x3f);
1009 *cp++ = 0x80 | (c & 0x3f);
1010 }
1011 }
1012 *cp = '\0';
1013 return ret;
1014}
1015
1016#endif
1017
1018#ifdef WINTERFACE
1019
1027static char *
1028uc_to_utf_c(SQLWCHAR *str, int len)
1029{
1030 if (len != SQL_NTS) {
1031 len = len * sizeof (SQLWCHAR);
1032 }
1033 return uc_to_utf(str, len);
1034}
1035
1036#endif
1037
1038#if defined(WCHARSUPPORT) || defined(_WIN32) || defined(_WIN64)
1039
1045static void
1046uc_free(void *str)
1047{
1048 if (str) {
1049 xfree(str);
1050 }
1051}
1052
1053#endif
1054
1055#if defined(_WIN32) || defined(_WIN64)
1056
1064static char *
1065wmb_to_utf(char *str, int len)
1066{
1067 WCHAR *wstr;
1068 OSVERSIONINFO ovi;
1069 int nchar, is2k, cp = CP_OEMCP;
1070
1071 ovi.dwOSVersionInfoSize = sizeof (ovi);
1072 GetVersionEx(&ovi);
1073 is2k = ovi.dwPlatformId == VER_PLATFORM_WIN32_NT && ovi.dwMajorVersion > 4;
1074 if (AreFileApisANSI()) {
1075 cp = is2k ? CP_THREAD_ACP : CP_ACP;
1076 }
1077 nchar = MultiByteToWideChar(cp, 0, str, len, NULL, 0);
1078 wstr = xmalloc((nchar + 1) * sizeof (WCHAR));
1079 if (!wstr) {
1080 return NULL;
1081 }
1082 wstr[0] = 0;
1083 nchar = MultiByteToWideChar(cp, 0, str, len, wstr, nchar);
1084 wstr[nchar] = 0;
1085 str = xmalloc((nchar + 1) * 7);
1086 if (!str) {
1087 xfree(wstr);
1088 return NULL;
1089 }
1090 str[0] = '\0';
1091 nchar = WideCharToMultiByte(CP_UTF8, 0, wstr, -1, str, nchar * 7, 0, 0);
1092 str[nchar] = '\0';
1093 xfree(wstr);
1094 return str;
1095}
1096
1097#ifndef WINTERFACE
1098
1106static char *
1107wmb_to_utf_c(char *str, int len)
1108{
1109 if (len == SQL_NTS) {
1110 len = strlen(str);
1111 }
1112 return wmb_to_utf(str, len);
1113}
1114
1115#endif
1116
1124static char *
1125utf_to_wmb(char *str, int len)
1126{
1127 WCHAR *wstr;
1128 OSVERSIONINFO ovi;
1129 int nchar, is2k, cp = CP_OEMCP;
1130
1131 ovi.dwOSVersionInfoSize = sizeof (ovi);
1132 GetVersionEx(&ovi);
1133 is2k = ovi.dwPlatformId == VER_PLATFORM_WIN32_NT && ovi.dwMajorVersion > 4;
1134 if (AreFileApisANSI()) {
1135 cp = is2k ? CP_THREAD_ACP : CP_ACP;
1136 }
1137 nchar = MultiByteToWideChar(CP_UTF8, 0, str, len, NULL, 0);
1138 wstr = xmalloc((nchar + 1) * sizeof (WCHAR));
1139 if (!wstr) {
1140 return NULL;
1141 }
1142 wstr[0] = 0;
1143 nchar = MultiByteToWideChar(CP_UTF8, 0, str, len, wstr, nchar);
1144 wstr[nchar] = 0;
1145 str = xmalloc((nchar + 1) * 7);
1146 if (!str) {
1147 xfree(wstr);
1148 return NULL;
1149 }
1150 str[0] = '\0';
1151 nchar = WideCharToMultiByte(cp, 0, wstr, -1, str, nchar * 7, 0, 0);
1152 str[nchar] = '\0';
1153 xfree(wstr);
1154 return str;
1155}
1156
1157#ifdef WINTERFACE
1158
1166static WCHAR *
1167wmb_to_uc(char *str, int len)
1168{
1169 WCHAR *wstr;
1170 OSVERSIONINFO ovi;
1171 int nchar, is2k, cp = CP_OEMCP;
1172
1173 ovi.dwOSVersionInfoSize = sizeof (ovi);
1174 GetVersionEx(&ovi);
1175 is2k = ovi.dwPlatformId == VER_PLATFORM_WIN32_NT && ovi.dwMajorVersion > 4;
1176 if (AreFileApisANSI()) {
1177 cp = is2k ? CP_THREAD_ACP : CP_ACP;
1178 }
1179 nchar = MultiByteToWideChar(cp, 0, str, len, NULL, 0);
1180 wstr = xmalloc((nchar + 1) * sizeof (WCHAR));
1181 if (!wstr) {
1182 return NULL;
1183 }
1184 wstr[0] = 0;
1185 nchar = MultiByteToWideChar(cp, 0, str, len, wstr, nchar);
1186 wstr[nchar] = 0;
1187 return wstr;
1188}
1189
1197static char *
1198uc_to_wmb(WCHAR *wstr, int len)
1199{
1200 char *str;
1201 OSVERSIONINFO ovi;
1202 int nchar, is2k, cp = CP_OEMCP;
1203
1204 ovi.dwOSVersionInfoSize = sizeof (ovi);
1205 GetVersionEx(&ovi);
1206 is2k = ovi.dwPlatformId == VER_PLATFORM_WIN32_NT && ovi.dwMajorVersion > 4;
1207 if (AreFileApisANSI()) {
1208 cp = is2k ? CP_THREAD_ACP : CP_ACP;
1209 }
1210 nchar = WideCharToMultiByte(cp, 0, wstr, len, NULL, 0, 0, 0);
1211 str = xmalloc((nchar + 1) * 2);
1212 if (!str) {
1213 return NULL;
1214 }
1215 str[0] = '\0';
1216 nchar = WideCharToMultiByte(cp, 0, wstr, len, str, nchar * 2, 0, 0);
1217 str[nchar] = '\0';
1218 return str;
1219}
1220
1221#endif /* WINTERFACE */
1222
1223#endif /* _WIN32 || _WIN64 */
1224
1225
1226#ifdef USE_DLOPEN_FOR_GPPS
1227
1228#include <dlfcn.h>
1229
1230#define SQLGetPrivateProfileString(A,B,C,D,E,F) drvgpps(d,A,B,C,D,E,F)
1231
1232/*
1233 * EXPERIMENTAL: SQLGetPrivateProfileString infrastructure using
1234 * dlopen(), in theory this makes the driver independent from the
1235 * driver manager, i.e. the same driver binary can run with iODBC
1236 * and unixODBC.
1237 */
1238
1239static void
1240drvgetgpps(DBC *d)
1241{
1242 void *lib;
1243 int (*gpps)();
1244
1245 lib = dlopen("libodbcinst.so.2", RTLD_LAZY);
1246 if (!lib) {
1247 lib = dlopen("libodbcinst.so.1", RTLD_LAZY);
1248 }
1249 if (!lib) {
1250 lib = dlopen("libodbcinst.so", RTLD_LAZY);
1251 }
1252 if (!lib) {
1253 lib = dlopen("libiodbcinst.so.2", RTLD_LAZY);
1254 }
1255 if (!lib) {
1256 lib = dlopen("libiodbcinst.so", RTLD_LAZY);
1257 }
1258 if (lib) {
1259 gpps = (int (*)()) dlsym(lib, "SQLGetPrivateProfileString");
1260 if (!gpps) {
1261 dlclose(lib);
1262 return;
1263 }
1264 d->instlib = lib;
1265 d->gpps = gpps;
1266 }
1267}
1268
1269static void
1270drvrelgpps(DBC *d)
1271{
1272 if (d->instlib) {
1273 dlclose(d->instlib);
1274 d->instlib = 0;
1275 }
1276}
1277
1278static int
1279drvgpps(DBC *d, char *sect, char *ent, char *def, char *buf,
1280 int bufsiz, char *fname)
1281{
1282 if (d->gpps) {
1283 return d->gpps(sect, ent, def, buf, bufsiz, fname);
1284 }
1285 strncpy(buf, def, bufsiz);
1286 buf[bufsiz - 1] = '\0';
1287 return 1;
1288}
1289#else
1290#include <odbcinst.h>
1291#define drvgetgpps(d)
1292#define drvrelgpps(d)
1293#endif
1294
1295/*
1296 * Internal function to bind SQLite3 parameters.
1297 */
1298
1299static void
1300s3bind(DBC *d, sqlite3_stmt *stmt, int nparams, BINDPARM *p)
1301{
1302 int i;
1303
1304 if (stmt && p && nparams > 0) {
1305 for (i = 0; i < nparams; i++, p++) {
1306 switch (p->s3type) {
1307 default:
1308 case SQLITE_NULL:
1309 sqlite3_bind_null(stmt, i + 1);
1310 if (d->trace) {
1311 fprintf(d->trace, "-- parameter %d: NULL\n", i + 1);
1312 fflush(d->trace);
1313 }
1314 break;
1315 case SQLITE_TEXT:
1316 sqlite3_bind_text(stmt, i + 1, p->s3val, p->s3size,
1317 SQLITE_STATIC);
1318 if (d->trace) {
1319 fprintf(d->trace, "-- parameter %d: '%*s'\n", i + 1,
1320 p->s3size, (char *) p->s3val);
1321 fflush(d->trace);
1322 }
1323 break;
1324 case SQLITE_BLOB:
1325 sqlite3_bind_blob(stmt, i + 1, p->s3val, p->s3size,
1326 SQLITE_STATIC);
1327 if (d->trace) {
1328 fprintf(d->trace, "-- parameter %d: [BLOB]'\n", i + 1);
1329 fflush(d->trace);
1330 }
1331 break;
1332 case SQLITE_FLOAT:
1333 sqlite3_bind_double(stmt, i + 1, p->s3dval);
1334 if (d->trace) {
1335 fprintf(d->trace, "-- parameter %d: %g\n",
1336 i + 1, p->s3dval);
1337 fflush(d->trace);
1338 }
1339 break;
1340 case SQLITE_INTEGER:
1341 if (p->s3size > sizeof (int)) {
1342 sqlite3_bind_int64(stmt, i + 1, p->s3lival);
1343 if (d->trace) {
1344 fprintf(d->trace,
1345#ifdef _WIN32
1346 "-- parameter %d: %I64d\n",
1347#else
1348 "-- parameter %d: %lld\n",
1349#endif
1350 i + 1, p->s3lival);
1351 fflush(d->trace);
1352 }
1353 } else {
1354 sqlite3_bind_int(stmt, i + 1, p->s3ival);
1355 if (d->trace) {
1356 fprintf(d->trace, "-- parameter %d: %d\n",
1357 i + 1, p->s3ival);
1358 fflush(d->trace);
1359 }
1360 }
1361 break;
1362 }
1363 }
1364 }
1365}
1366
1374typedef struct tblres {
1375 char **resarr;
1376 char *errmsg;
1377 sqlite3_stmt *stmt;
1380 int nrow;
1381 int ncol;
1383 int rc;
1385
1386/*
1387 * Driver's version of sqlite3_get_table() and friends which are
1388 * capable of dealing with blobs.
1389 */
1390
1391static int
1392drvgettable_row(TBLRES *t, int ncol, int rc)
1393{
1394 int need;
1395 int i;
1396 char *p;
1397
1398 if (t->nrow == 0 && rc == SQLITE_ROW) {
1399 need = ncol * 2;
1400 } else {
1401 need = ncol;
1402 }
1403 if (t->ndata + need >= t->nalloc) {
1404 char **resnew;
1405 int nalloc = t->nalloc * 2 + need + 1;
1406
1407 if (nalloc < t->nalloc) {
1408 goto nomem;
1409 }
1410 resnew = xrealloc(t->resarr, sizeof (char *) * nalloc);
1411 if (!resnew) {
1412nomem:
1413 t->rc = SQLITE_NOMEM;
1414 return 1;
1415 }
1416 t->nalloc = nalloc;
1417 t->resarr = resnew;
1418 }
1419 /* column names when first row */
1420 if (t->nrow == 0) {
1421 t->ncol = ncol;
1422 for (i = 0; i < ncol; i++) {
1423 p = (char *) sqlite3_column_name(t->stmt, i);
1424 if (p) {
1425 char *q = xmalloc(strlen(p) + 1);
1426
1427 if (!q) {
1428 goto nomem;
1429 }
1430 strcpy(q, p);
1431 p = q;
1432 }
1433 t->resarr[t->ndata++] = p;
1434 }
1435 if (t->s && t->s->guessed_types) {
1436 int ncol2 = ncol;
1437
1438 setupdyncols(t->s, t->stmt, &ncol2);
1439 t->s->guessed_types = 0;
1440 t->s->ncols = ncol;
1441 }
1442 } else if (t->ncol != ncol) {
1443 t->errmsg = sqlite3_mprintf("drvgettable() called with two or"
1444 " more incompatible queries");
1445 t->rc = SQLITE_ERROR;
1446 return 1;
1447 }
1448 /* copy row data */
1449 if (rc == SQLITE_ROW) {
1450 for (i = 0; i < ncol; i++) {
1451 int coltype = sqlite3_column_type(t->stmt, i);
1452
1453 p = NULL;
1454 if (coltype == SQLITE_BLOB) {
1455 int k, nbytes = sqlite3_column_bytes(t->stmt, i);
1456 char *qp;
1457 unsigned const char *bp;
1458
1459 bp = sqlite3_column_blob(t->stmt, i);
1460 qp = xmalloc(nbytes * 2 + 4);
1461 if (!qp) {
1462 goto nomem;
1463 }
1464 p = qp;
1465 *qp++ = 'X';
1466 *qp++ = '\'';
1467 for (k = 0; k < nbytes; k++) {
1468 *qp++ = xdigits[(bp[k] >> 4)];
1469 *qp++ = xdigits[(bp[k] & 0xF)];
1470 }
1471 *qp++ = '\'';
1472 *qp = '\0';
1473#ifdef _MSC_VER
1474 } else if (coltype == SQLITE_FLOAT) {
1475 struct lconv *lc = 0;
1476 double val = sqlite3_column_double(t->stmt, i);
1477 char buffer[128];
1478
1479 /*
1480 * This avoids floating point rounding
1481 * and formatting problems of some SQLite
1482 * versions in conjunction with MSVC 2010.
1483 */
1484 snprintf(buffer, sizeof (buffer), "%.15g", val);
1485 lc = localeconv();
1486 if (lc && lc->decimal_point && lc->decimal_point[0] &&
1487 lc->decimal_point[0] != '.') {
1488 p = strchr(buffer, lc->decimal_point[0]);
1489 if (p) {
1490 *p = '.';
1491 }
1492 }
1493 p = xstrdup(buffer);
1494 if (!p) {
1495 goto nomem;
1496 }
1497#endif
1498 } else if (coltype != SQLITE_NULL) {
1499 p = xstrdup((char *) sqlite3_column_text(t->stmt, i));
1500 if (!p) {
1501 goto nomem;
1502 }
1503 }
1504 t->resarr[t->ndata++] = p;
1505 }
1506 t->nrow++;
1507 }
1508 return 0;
1509}
1510
1511static int
1512drvgettable(STMT *s, const char *sql, char ***resp, int *nrowp,
1513 int *ncolp, char **errp, int nparam, BINDPARM *p)
1514{
1515 DBC *d = (DBC *) s->dbc;
1516 int rc = SQLITE_OK, keep = sql == NULL;
1517 TBLRES tres;
1518 const char *sqlleft = 0;
1519 int nretry = 0, haveerr = 0;
1520
1521 if (!resp) {
1522 return SQLITE_ERROR;
1523 }
1524 *resp = NULL;
1525 if (nrowp) {
1526 *nrowp = 0;
1527 }
1528 if (ncolp) {
1529 *ncolp = 0;
1530 }
1531 tres.errmsg = NULL;
1532 tres.nrow = 0;
1533 tres.ncol = 0;
1534 tres.ndata = 1;
1535 tres.nalloc = 20;
1536 tres.rc = SQLITE_OK;
1537 tres.resarr = xmalloc(sizeof (char *) * tres.nalloc);
1538 tres.stmt = NULL;
1539 tres.s = s;
1540 if (!tres.resarr) {
1541 return SQLITE_NOMEM;
1542 }
1543 tres.resarr[0] = 0;
1544 if (sql == NULL) {
1545 tres.stmt = s->s3stmt;
1546 if (tres.stmt == NULL) {
1547 return SQLITE_NOMEM;
1548 }
1549 goto retrieve;
1550 }
1551 while (sql && *sql && (rc == SQLITE_OK ||
1552 (rc == SQLITE_SCHEMA && (++nretry) < 2))) {
1553 int ncol;
1554
1555 tres.stmt = NULL;
1556#if defined(HAVE_SQLITE3PREPAREV2) && (HAVE_SQLITE3PREPAREV2)
1557 dbtraceapi(d, "sqlite3_prepare_v2", sql);
1558 rc = sqlite3_prepare_v2(d->sqlite, sql, -1, &tres.stmt, &sqlleft);
1559#else
1560 dbtraceapi(d, "sqlite3_prepare", sql);
1561 rc = sqlite3_prepare(d->sqlite, sql, -1, &tres.stmt, &sqlleft);
1562#endif
1563 if (rc != SQLITE_OK) {
1564 if (tres.stmt) {
1565 dbtraceapi(d, "sqlite3_finalize", 0);
1566 sqlite3_finalize(tres.stmt);
1567 tres.stmt = NULL;
1568 }
1569 continue;
1570 }
1571 if (!tres.stmt) {
1572 /* this happens for a comment or white-space */
1573 sql = sqlleft;
1574 continue;
1575 }
1576retrieve:
1577 if (sqlite3_bind_parameter_count(tres.stmt) != nparam) {
1578 if (errp) {
1579 *errp =
1580 sqlite3_mprintf("%s", "parameter marker count incorrect");
1581 }
1582 haveerr = 1;
1583 rc = SQLITE_ERROR;
1584 goto tbldone;
1585 }
1586 s3bind(d, tres.stmt, nparam, p);
1587 ncol = sqlite3_column_count(tres.stmt);
1588 while (1) {
1589 if (s->max_rows && tres.nrow >= s->max_rows) {
1590 rc = SQLITE_OK;
1591 break;
1592 }
1593 rc = sqlite3_step(tres.stmt);
1594 if (rc == SQLITE_ROW || rc == SQLITE_DONE) {
1595 if (drvgettable_row(&tres, ncol, rc)) {
1596 rc = SQLITE_ABORT;
1597 goto tbldone;
1598 }
1599 }
1600 if (rc != SQLITE_ROW) {
1601 if (keep) {
1602 dbtraceapi(d, "sqlite3_reset", 0);
1603 rc = sqlite3_reset(tres.stmt);
1604 s->s3stmt_noreset = 1;
1605 } else {
1606 dbtraceapi(d, "sqlite3_finalize", 0);
1607 rc = sqlite3_finalize(tres.stmt);
1608 }
1609 tres.stmt = 0;
1610 if (rc != SQLITE_SCHEMA) {
1611 nretry = 0;
1612 sql = sqlleft;
1613 while (sql && ISSPACE(*sql)) {
1614 sql++;
1615 }
1616 }
1617 if (rc == SQLITE_DONE) {
1618 rc = SQLITE_OK;
1619 }
1620 break;
1621 }
1622 }
1623 }
1624tbldone:
1625 if (tres.stmt) {
1626 if (keep) {
1627 if (!s->s3stmt_noreset) {
1628 dbtraceapi(d, "sqlite3_reset", 0);
1629 sqlite3_reset(tres.stmt);
1630 s->s3stmt_noreset = 1;
1631 }
1632 } else {
1633 dbtraceapi(d, "sqlite3_finalize", 0);
1634 sqlite3_finalize(tres.stmt);
1635 }
1636 }
1637 if (haveerr) {
1638 /* message already in *errp if any */
1639 } else if (rc != SQLITE_OK && rc == sqlite3_errcode(d->sqlite) && errp) {
1640 *errp = sqlite3_mprintf("%s", sqlite3_errmsg(d->sqlite));
1641 } else if (errp) {
1642 *errp = NULL;
1643 }
1644 if (tres.resarr) {
1645 tres.resarr[0] = (char *) (tres.ndata - 1);
1646 }
1647 if (rc == SQLITE_ABORT) {
1648 freerows(&tres.resarr[1]);
1649 if (tres.errmsg) {
1650 if (errp) {
1651 if (*errp) {
1652 sqlite3_free(*errp);
1653 }
1654 *errp = tres.errmsg;
1655 } else {
1656 sqlite3_free(tres.errmsg);
1657 }
1658 }
1659 return tres.rc;
1660 }
1661 sqlite3_free(tres.errmsg);
1662 if (rc != SQLITE_OK) {
1663 freerows(&tres.resarr[1]);
1664 return rc;
1665 }
1666 *resp = &tres.resarr[1];
1667 if (ncolp) {
1668 *ncolp = tres.ncol;
1669 }
1670 if (nrowp) {
1671 *nrowp = tres.nrow;
1672 }
1673 return rc;
1674}
1675
1684#if defined(__GNUC__) && (__GNUC__ >= 2)
1685static void setstatd(DBC *, int, char *, char *, ...)
1686 __attribute__((format (printf, 3, 5)));
1687#endif
1688
1689static void
1690setstatd(DBC *d, int naterr, char *msg, char *st, ...)
1691{
1692 va_list ap;
1693
1694 if (!d) {
1695 return;
1696 }
1697 d->naterr = naterr;
1698 d->logmsg[0] = '\0';
1699 if (msg) {
1700 int count;
1701
1702 va_start(ap, st);
1703 count = vsnprintf((char *) d->logmsg, sizeof (d->logmsg), msg, ap);
1704 va_end(ap);
1705 if (count < 0) {
1706 d->logmsg[sizeof (d->logmsg) - 1] = '\0';
1707 }
1708 }
1709 if (!st) {
1710 st = "?????";
1711 }
1712 strncpy(d->sqlstate, st, 5);
1713 d->sqlstate[5] = '\0';
1714}
1715
1724#if defined(__GNUC__) && (__GNUC__ >= 2)
1725static void setstat(STMT *, int, char *, char *, ...)
1726 __attribute__((format (printf, 3, 5)));
1727#endif
1728
1729static void
1730setstat(STMT *s, int naterr, char *msg, char *st, ...)
1731{
1732 va_list ap;
1733
1734 if (!s) {
1735 return;
1736 }
1737 s->naterr = naterr;
1738 s->logmsg[0] = '\0';
1739 if (msg) {
1740 int count;
1741
1742 va_start(ap, st);
1743 count = vsnprintf((char *) s->logmsg, sizeof (s->logmsg), msg, ap);
1744 va_end(ap);
1745 if (count < 0) {
1746 s->logmsg[sizeof (s->logmsg) - 1] = '\0';
1747 }
1748 }
1749 if (!st) {
1750 st = "?????";
1751 }
1752 strncpy(s->sqlstate, st, 5);
1753 s->sqlstate[5] = '\0';
1754}
1755
1762static SQLRETURN
1764{
1765 DBC *d;
1766
1767 if (dbc == SQL_NULL_HDBC) {
1768 return SQL_INVALID_HANDLE;
1769 }
1770 d = (DBC *) dbc;
1771 setstatd(d, -1, "not supported", "IM001");
1772 return SQL_ERROR;
1773}
1774
1781static SQLRETURN
1783{
1784 STMT *s;
1785
1786 if (stmt == SQL_NULL_HSTMT) {
1787 return SQL_INVALID_HANDLE;
1788 }
1789 s = (STMT *) stmt;
1790 setstat(s, -1, "not supported", "IM001");
1791 return SQL_ERROR;
1792}
1793
1799static void
1800freep(void *x)
1801{
1802 if (x && ((char **) x)[0]) {
1803 xfree(((char **) x)[0]);
1804 ((char **) x)[0] = NULL;
1805 }
1806}
1807
1814static SQLRETURN
1816{
1817 setstat(s, -1, "out of memory", (*s->ov3) ? "HY000" : "S1000");
1818 return SQL_ERROR;
1819}
1820
1827static SQLRETURN
1829{
1830 setstat(s, -1, "not connected", (*s->ov3) ? "HY000" : "S1000");
1831 return SQL_ERROR;
1832}
1833
1841#if defined(HAVE_LOCALECONV) || defined(_WIN32) || defined(_WIN64)
1842
1843static double
1844ln_strtod(const char *data, char **endp)
1845{
1846 struct lconv *lc = 0;
1847 char buf[128], *p, *end;
1848 double value;
1849
1850 lc = localeconv();
1851 if (lc && lc->decimal_point && lc->decimal_point[0] &&
1852 lc->decimal_point[0] != '.') {
1853 strncpy(buf, data, sizeof (buf) - 1);
1854 buf[sizeof (buf) - 1] = '\0';
1855 p = strchr(buf, '.');
1856 if (p) {
1857 *p = lc->decimal_point[0];
1858 }
1859 p = buf;
1860 } else {
1861 p = (char *) data;
1862 }
1863 value = strtod(p, &end);
1864 end = (char *) data + (end - p);
1865 if (endp) {
1866 *endp = end;
1867 }
1868 return value;
1869}
1870
1871#else
1872
1873#define ln_strtod(A,B) strtod(A,B)
1874
1875#endif
1876
1882static char *
1883unquote(char *str)
1884{
1885 if (str) {
1886 int len = strlen(str);
1887
1888 if (len > 1) {
1889 int end = len - 1;
1890
1891 if ((str[0] == '\'' && str[end] == '\'') ||
1892 (str[0] == '"' && str[end] == '"') ||
1893 (str[0] == '[' && str[end] == ']')) {
1894 memmove(str, str + 1, end - 1);
1895 str[end - 1] = '\0';
1896 }
1897 }
1898 }
1899 return str;
1900}
1901
1909static int
1910unescpat(char *str)
1911{
1912 char *p, *q;
1913 int count = 0;
1914
1915 p = str;
1916 while ((q = strchr(p, '_')) != NULL) {
1917 if (q == str || q[-1] != '\\') {
1918 count++;
1919 }
1920 p = q + 1;
1921 }
1922 p = str;
1923 while ((q = strchr(p, '%')) != NULL) {
1924 if (q == str || q[-1] != '\\') {
1925 count++;
1926 }
1927 p = q + 1;
1928 }
1929 p = str;
1930 while ((q = strchr(p, '\\')) != NULL) {
1931 if (q[1] == '\\' || q[1] == '_' || q[1] == '%') {
1932 memmove(q, q + 1, strlen(q));
1933 }
1934 p = q + 1;
1935 }
1936 return count;
1937}
1938
1947static int
1948namematch(char *str, char *pat, int esc)
1949{
1950 int cp, ch;
1951
1952 while (1) {
1953 cp = TOLOWER(*pat);
1954 if (cp == '\0') {
1955 if (*str != '\0') {
1956 goto nomatch;
1957 }
1958 break;
1959 }
1960 if (*str == '\0' && cp != '%') {
1961 goto nomatch;
1962 }
1963 if (cp == '%') {
1964 while (*pat == '%') {
1965 ++pat;
1966 }
1967 cp = TOLOWER(*pat);
1968 if (cp == '\0') {
1969 break;
1970 }
1971 while (1) {
1972 if (cp != '_' && cp != '\\') {
1973 while (*str) {
1974 ch = TOLOWER(*str);
1975 if (ch == cp) {
1976 break;
1977 }
1978 ++str;
1979 }
1980 }
1981 if (namematch(str, pat, esc)) {
1982 goto match;
1983 }
1984 if (*str == '\0') {
1985 goto nomatch;
1986 }
1987 ch = TOLOWER(*str);
1988 ++str;
1989 }
1990 }
1991 if (cp == '_') {
1992 pat++;
1993 str++;
1994 continue;
1995 }
1996 if (esc && cp == '\\' &&
1997 (pat[1] == '\\' || pat[1] == '%' || pat[1] == '_')) {
1998 ++pat;
1999 cp = TOLOWER(*pat);
2000 }
2001 ch = TOLOWER(*str++);
2002 ++pat;
2003 if (ch != cp) {
2004 goto nomatch;
2005 }
2006 }
2007match:
2008 return 1;
2009nomatch:
2010 return 0;
2011}
2012
2020static int
2021busy_handler(void *udata, int count)
2022{
2023 DBC *d = (DBC *) udata;
2024 long t1;
2025 int ret = 0;
2026#if !defined(_WIN32) && !defined(_WIN64)
2027 struct timeval tv;
2028#ifdef HAVE_NANOSLEEP
2029 struct timespec ts;
2030#endif
2031#endif
2032
2033 if (d->busyint) {
2034 d->busyint = 0;
2035 return ret;
2036 }
2037 if (d->timeout <= 0) {
2038 return ret;
2039 }
2040 if (count <= 1) {
2041#if defined(_WIN32) || defined(_WIN64)
2042 d->t0 = GetTickCount();
2043#else
2044 gettimeofday(&tv, NULL);
2045 d->t0 = tv.tv_sec * 1000 + tv.tv_usec / 1000;
2046#endif
2047 }
2048#if defined(_WIN32) || defined(_WIN64)
2049 t1 = GetTickCount();
2050#else
2051 gettimeofday(&tv, NULL);
2052 t1 = tv.tv_sec * 1000 + tv.tv_usec / 1000;
2053#endif
2054 if (t1 - d->t0 > d->timeout) {
2055 goto done;
2056 }
2057#if defined(_WIN32) || defined(_WIN64)
2058 Sleep(10);
2059#else
2060#ifdef HAVE_NANOSLEEP
2061 ts.tv_sec = 0;
2062 ts.tv_nsec = 10000000;
2063 do {
2064 ret = nanosleep(&ts, &ts);
2065 if (ret < 0 && errno != EINTR) {
2066 ret = 0;
2067 }
2068 } while (ret);
2069#else
2070#ifdef HAVE_USLEEP
2071 usleep(10000);
2072#else
2073 tv.tv_sec = 0;
2074 tv.tv_usec = 10000;
2075 select(0, NULL, NULL, NULL, &tv);
2076#endif
2077#endif
2078#endif
2079 ret = 1;
2080done:
2081 return ret;
2082}
2083
2095static int
2096setsqliteopts(sqlite3 *x, DBC *d)
2097{
2098 int count = 0, step = 0, max, rc = SQLITE_ERROR;
2099
2100#if defined(HAVE_SQLITE3COLUMNTABLENAME) && (HAVE_SQLITE3COLUMNTABLENAME)
2101 max = d->longnames ? 3 : 1;
2102#else
2103 max = 3;
2104#endif
2105 if (d->shortnames) {
2106 max = 3;
2107 }
2108 while (step < max) {
2109 if (step < 1) {
2110 rc = sqlite3_exec(x, "PRAGMA empty_result_callbacks = on;",
2111 NULL, NULL, NULL);
2112 if (rc == SQLITE_OK) {
2113 rc = sqlite3_exec(x, d->fksupport ?
2114 "PRAGMA foreign_keys = on;" :
2115 "PRAGMA foreign_keys = off;",
2116 NULL, NULL, NULL);
2117 }
2118 } else if (step < 2) {
2119 rc = sqlite3_exec(x, d->shortnames ?
2120 "PRAGMA full_column_names = off;" :
2121 "PRAGMA full_column_names = on;",
2122 NULL, NULL, NULL);
2123 } else if (step < 3) {
2124 rc = sqlite3_exec(x, d->shortnames ?
2125 "PRAGMA short_column_names = on;" :
2126 "PRAGMA short_column_names = off;",
2127 NULL, NULL, NULL);
2128 }
2129 if (rc != SQLITE_OK) {
2130 if (rc != SQLITE_BUSY ||
2131 !busy_handler((void *) d, ++count)) {
2132 return rc;
2133 }
2134 continue;
2135 }
2136 count = 0;
2137 ++step;
2138 }
2139 sqlite3_busy_handler(x, busy_handler, (void *) d);
2140 return SQLITE_OK;
2141}
2142
2152static void
2153freerows(char **rowp)
2154{
2155 PTRDIFF_T size, i;
2156
2157 if (!rowp) {
2158 return;
2159 }
2160 --rowp;
2161 size = (PTRDIFF_T) rowp[0];
2162 for (i = 1; i <= size; i++) {
2163 freep(&rowp[i]);
2164 }
2165 freep(&rowp);
2166}
2167
2178static int
2179mapsqltype(const char *typename, int *nosign, int ov3, int nowchar,
2180 int dobigint)
2181{
2182 char *p, *q;
2183 int testsign = 0, result;
2184
2185#ifdef WINTERFACE
2186 result = nowchar ? SQL_VARCHAR : SQL_WVARCHAR;
2187#else
2188 result = SQL_VARCHAR;
2189#endif
2190 if (!typename) {
2191 return result;
2192 }
2193 q = p = xmalloc(strlen(typename) + 1);
2194 if (!p) {
2195 return result;
2196 }
2197 strcpy(p, typename);
2198 while (*q) {
2199 *q = TOLOWER(*q);
2200 ++q;
2201 }
2202 if (strncmp(p, "inter", 5) == 0) {
2203 } else if (strncmp(p, "int", 3) == 0 ||
2204 strncmp(p, "mediumint", 9) == 0) {
2205 testsign = 1;
2206 result = SQL_INTEGER;
2207 } else if (strncmp(p, "numeric", 7) == 0) {
2208 result = SQL_DOUBLE;
2209 } else if (strncmp(p, "tinyint", 7) == 0) {
2210 testsign = 1;
2211 result = SQL_TINYINT;
2212 } else if (strncmp(p, "smallint", 8) == 0) {
2213 testsign = 1;
2214 result = SQL_SMALLINT;
2215 } else if (strncmp(p, "float", 5) == 0) {
2216 result = SQL_DOUBLE;
2217 } else if (strncmp(p, "double", 6) == 0 ||
2218 strncmp(p, "real", 4) == 0) {
2219 result = SQL_DOUBLE;
2220 } else if (strncmp(p, "timestamp", 9) == 0) {
2221#ifdef SQL_TYPE_TIMESTAMP
2222 result = ov3 ? SQL_TYPE_TIMESTAMP : SQL_TIMESTAMP;
2223#else
2224 result = SQL_TIMESTAMP;
2225#endif
2226 } else if (strncmp(p, "datetime", 8) == 0) {
2227#ifdef SQL_TYPE_TIMESTAMP
2228 result = ov3 ? SQL_TYPE_TIMESTAMP : SQL_TIMESTAMP;
2229#else
2230 result = SQL_TIMESTAMP;
2231#endif
2232 } else if (strncmp(p, "time", 4) == 0) {
2233#ifdef SQL_TYPE_TIME
2234 result = ov3 ? SQL_TYPE_TIME : SQL_TIME;
2235#else
2236 result = SQL_TIME;
2237#endif
2238 } else if (strncmp(p, "date", 4) == 0) {
2239#ifdef SQL_TYPE_DATE
2240 result = ov3 ? SQL_TYPE_DATE : SQL_DATE;
2241#else
2242 result = SQL_DATE;
2243#endif
2244#ifdef SQL_LONGVARCHAR
2245 } else if (strncmp(p, "text", 4) == 0 ||
2246 strncmp(p, "memo", 4) == 0 ||
2247 strncmp(p, "longvarchar", 11) == 0) {
2248#ifdef WINTERFACE
2249 result = nowchar ? SQL_LONGVARCHAR : SQL_WLONGVARCHAR;
2250#else
2251 result = SQL_LONGVARCHAR;
2252#endif
2253#ifdef WINTERFACE
2254 } else if (strncmp(p, "wtext", 5) == 0 ||
2255 strncmp(p, "wvarchar", 8) == 0 ||
2256 strncmp(p, "longwvarchar", 12) == 0) {
2257 result = SQL_WLONGVARCHAR;
2258#endif
2259#endif
2260#ifdef SQL_BIT
2261 } else if (strncmp(p, "bool", 4) == 0 ||
2262 strncmp(p, "bit", 3) == 0) {
2263 result = SQL_BIT;
2264#endif
2265#ifdef SQL_BIGINT
2266 } else if (strncmp(p, "bigint", 6) == 0) {
2267 testsign = 1;
2268 result = SQL_BIGINT;
2269#endif
2270 } else if (strncmp(p, "blob", 4) == 0) {
2271 result = SQL_BINARY;
2272 } else if (strncmp(p, "varbinary", 9) == 0) {
2273 result = SQL_VARBINARY;
2274 } else if (strncmp(p, "longvarbinary", 13) == 0) {
2275 result = SQL_LONGVARBINARY;
2276 }
2277 if (nosign) {
2278 if (testsign) {
2279 *nosign = strstr(p, "unsigned") != NULL;
2280 } else {
2281 *nosign = 1;
2282 }
2283 }
2284#ifdef SQL_BIGINT
2285 if (dobigint && result == SQL_INTEGER) {
2286 result = SQL_BIGINT;
2287 }
2288#endif
2289 xfree(p);
2290 return result;
2291}
2292
2302static void
2303getmd(const char *typename, int sqltype, int *mp, int *dp)
2304{
2305 int m = 0, d = 0;
2306
2307 switch (sqltype) {
2308 case SQL_INTEGER: m = 10; d = 9; break;
2309 case SQL_TINYINT: m = 4; d = 3; break;
2310 case SQL_SMALLINT: m = 6; d = 5; break;
2311 case SQL_FLOAT: m = 25; d = 24; break;
2312 case SQL_DOUBLE: m = 54; d = 53; break;
2313 case SQL_VARCHAR: m = 255; d = 0; break;
2314#ifdef WINTERFACE
2315#ifdef SQL_WVARCHAR
2316 case SQL_WVARCHAR: m = 255; d = 0; break;
2317#endif
2318#endif
2319#ifdef SQL_TYPE_DATE
2320 case SQL_TYPE_DATE:
2321#endif
2322 case SQL_DATE: m = 10; d = 0; break;
2323#ifdef SQL_TYPE_TIME
2324 case SQL_TYPE_TIME:
2325#endif
2326 case SQL_TIME: m = 8; d = 0; break;
2327#ifdef SQL_TYPE_TIMESTAMP
2328 case SQL_TYPE_TIMESTAMP:
2329#endif
2330 case SQL_TIMESTAMP: m = 32; d = 3; break;
2331#ifdef SQL_LONGVARCHAR
2332 case SQL_LONGVARCHAR : m = 65536; d = 0; break;
2333#endif
2334#ifdef WINTERFACE
2335#ifdef SQL_WLONGVARCHAR
2336 case SQL_WLONGVARCHAR: m = 65536; d = 0; break;
2337#endif
2338#endif
2339 case SQL_BINARY:
2340 case SQL_VARBINARY: m = 255; d = 0; break;
2341 case SQL_LONGVARBINARY: m = 65536; d = 0; break;
2342#ifdef SQL_BIGINT
2343 case SQL_BIGINT: m = 20; d = 19; break;
2344#endif
2345#ifdef SQL_BIT
2346 case SQL_BIT: m = 1; d = 1; break;
2347#endif
2348 }
2349 if (m && typename) {
2350 int mm, dd;
2351 char clbr[4];
2352
2353 if (sscanf(typename, "%*[^(](%d,%d %1[)]", &mm, &dd, clbr) == 3) {
2354 m = mm;
2355 d = dd;
2356 } else if (sscanf(typename, "%*[^(](%d %1[)]", &mm, clbr) == 2) {
2357 if (sqltype == SQL_TIMESTAMP) {
2358 d = mm;
2359 }
2360#ifdef SQL_TYPE_TIMESTAMP
2361 else if (sqltype == SQL_TYPE_TIMESTAMP) {
2362 d = mm;
2363 }
2364#endif
2365 else {
2366 m = d = mm;
2367 }
2368 }
2369 }
2370 if (mp) {
2371 *mp = m;
2372 }
2373 if (dp) {
2374 *dp = d;
2375 }
2376}
2377
2387static int
2388mapdeftype(int type, int stype, int nosign, int nowchar)
2389{
2390 if (type == SQL_C_DEFAULT) {
2391 switch (stype) {
2392 case SQL_INTEGER:
2393 type = (nosign > 0) ? SQL_C_ULONG : SQL_C_LONG;
2394 break;
2395 case SQL_TINYINT:
2396 type = (nosign > 0) ? SQL_C_UTINYINT : SQL_C_TINYINT;
2397 break;
2398 case SQL_SMALLINT:
2399 type = (nosign > 0) ? SQL_C_USHORT : SQL_C_SHORT;
2400 break;
2401 case SQL_FLOAT:
2402 type = SQL_C_FLOAT;
2403 break;
2404 case SQL_DOUBLE:
2405 type = SQL_C_DOUBLE;
2406 break;
2407 case SQL_TIMESTAMP:
2408 type = SQL_C_TIMESTAMP;
2409 break;
2410 case SQL_TIME:
2411 type = SQL_C_TIME;
2412 break;
2413 case SQL_DATE:
2414 type = SQL_C_DATE;
2415 break;
2416#ifdef SQL_C_TYPE_TIMESTAMP
2417 case SQL_TYPE_TIMESTAMP:
2418 type = SQL_C_TYPE_TIMESTAMP;
2419 break;
2420#endif
2421#ifdef SQL_C_TYPE_TIME
2422 case SQL_TYPE_TIME:
2423 type = SQL_C_TYPE_TIME;
2424 break;
2425#endif
2426#ifdef SQL_C_TYPE_DATE
2427 case SQL_TYPE_DATE:
2428 type = SQL_C_TYPE_DATE;
2429 break;
2430#endif
2431#ifdef WINTERFACE
2432 case SQL_WVARCHAR:
2433 case SQL_WCHAR:
2434#ifdef SQL_WLONGVARCHAR
2435 case SQL_WLONGVARCHAR:
2436#endif
2437 type = nowchar ? SQL_C_CHAR : SQL_C_WCHAR;
2438 break;
2439#endif
2440 case SQL_BINARY:
2441 case SQL_VARBINARY:
2442 case SQL_LONGVARBINARY:
2443 type = SQL_C_BINARY;
2444 break;
2445#ifdef SQL_BIT
2446 case SQL_BIT:
2447 type = SQL_C_BIT;
2448 break;
2449#endif
2450#ifdef SQL_BIGINT
2451 case SQL_BIGINT:
2452 type = SQL_C_CHAR;
2453 break;
2454#endif
2455 default:
2456#ifdef WINTERFACE
2457 type = nowchar ? SQL_C_CHAR : SQL_C_WCHAR;
2458#else
2459 type = SQL_C_CHAR;
2460#endif
2461 break;
2462 }
2463 }
2464 return type;
2465}
2466
2473static int
2474checkddl(char *sql)
2475{
2476 int isddl = 0;
2477
2478 while (*sql && ISSPACE(*sql)) {
2479 ++sql;
2480 }
2481 if (*sql && *sql != ';') {
2482 int i, size;
2483 static const struct {
2484 int len;
2485 const char *str;
2486 } ddlstr[] = {
2487 { 5, "alter" },
2488 { 7, "analyze" },
2489 { 6, "attach" },
2490 { 5, "begin" },
2491 { 6, "commit" },
2492 { 6, "create" },
2493 { 6, "detach" },
2494 { 4, "drop" },
2495 { 3, "end" },
2496 { 7, "reindex" },
2497 { 7, "release" },
2498 { 8, "rollback" },
2499 { 9, "savepoint" },
2500 { 6, "vacuum" }
2501 };
2502
2503 size = strlen(sql);
2504 for (i = 0; i < array_size(ddlstr); i++) {
2505 if (size >= ddlstr[i].len &&
2506 strncasecmp(sql, ddlstr[i].str, ddlstr[i].len) == 0) {
2507 isddl = 1;
2508 break;
2509 }
2510 }
2511 }
2512 return isddl;
2513}
2514
2526static char *
2527fixupsql(char *sql, int sqlLen, int cte, int *nparam, int *isselect,
2528 char **errmsg)
2529{
2530 char *q = sql, *qz = NULL, *p, *inq = NULL, *out;
2531 int np = 0, isddl = -1, size;
2532
2533 if (errmsg) {
2534 *errmsg = NULL;
2535 }
2536 if (sqlLen != SQL_NTS) {
2537 qz = q = xmalloc(sqlLen + 1);
2538 if (!qz) {
2539 return NULL;
2540 }
2541 memcpy(q, sql, sqlLen);
2542 q[sqlLen] = '\0';
2543 size = sqlLen * 4;
2544 } else {
2545 size = strlen(sql) * 4;
2546 }
2547 size += sizeof (char *) - 1;
2548 size &= ~(sizeof (char *) - 1);
2549 p = xmalloc(size);
2550 if (!p) {
2551errout:
2552 freep(&qz);
2553 return NULL;
2554 }
2555 memset(p, 0, size);
2556 out = p;
2557 while (*q) {
2558 switch (*q) {
2559 case '\'':
2560 case '\"':
2561 if (q == inq) {
2562 inq = NULL;
2563 } else if (!inq) {
2564 inq = q + 1;
2565
2566 while (*inq) {
2567 if (*inq == *q) {
2568 if (inq[1] == *q) {
2569 inq++;
2570 } else {
2571 break;
2572 }
2573 }
2574 inq++;
2575 }
2576 }
2577 *p++ = *q;
2578 break;
2579 case '-':
2580 *p++ = *q;
2581 if (!inq && q[1] == '-') {
2582 ++q;
2583 while (*q) {
2584 *p++ = *q++;
2585 if (*q == '\n') {
2586 break;
2587 }
2588 }
2589 }
2590 break;
2591 case '?':
2592 *p++ = *q;
2593 if (!inq) {
2594 np++;
2595 }
2596 break;
2597 case ';':
2598 if (!inq) {
2599 if (isddl < 0) {
2600 isddl = checkddl(out);
2601 }
2602 if (isddl == 0) {
2603 char *qq = q;
2604
2605 do {
2606 ++qq;
2607 } while (*qq && ISSPACE(*qq));
2608 if (*qq && *qq != ';') {
2609 freep(&out);
2610 if (errmsg) {
2611 *errmsg = "only one SQL statement allowed";
2612 }
2613 goto errout;
2614 }
2615 }
2616 }
2617 *p++ = *q;
2618 break;
2619 case '{':
2620 /*
2621 * Deal with escape sequences:
2622 * {d 'YYYY-MM-DD'}, {t ...}, {ts ...}
2623 * {oj ...}, {fn ...} etc.
2624 */
2625 if (!inq) {
2626 int ojfn = 0, brc = 0;
2627 char *inq2 = NULL, *end = q + 1, *start;
2628
2629 while (*end && ISSPACE(*end)) {
2630 ++end;
2631 }
2632 if (*end != 'd' && *end != 'D' &&
2633 *end != 't' && *end != 'T') {
2634 ojfn = 1;
2635 }
2636 start = end;
2637 while (*end) {
2638 if (inq2 && *end == *inq2) {
2639 inq2 = NULL;
2640 } else if (inq2 == NULL && *end == '{') {
2641 char *nerr = 0, *nsql;
2642
2643 nsql = fixupsql(end, SQL_NTS, cte, 0, 0, &nerr);
2644 if (nsql && !nerr) {
2645 strcpy(end, nsql);
2646 } else {
2647 brc++;
2648 }
2649 freep(&nsql);
2650 } else if (inq2 == NULL && *end == '}') {
2651 if (brc-- <= 0) {
2652 break;
2653 }
2654 } else if (inq2 == NULL && (*end == '\'' || *end == '"')) {
2655 inq2 = end;
2656 } else if (inq2 == NULL && *end == '?') {
2657 np++;
2658 }
2659 ++end;
2660 }
2661 if (*end == '}') {
2662 char *end2 = end - 1;
2663
2664 if (ojfn) {
2665 while (start < end) {
2666 if (ISSPACE(*start)) {
2667 break;
2668 }
2669 ++start;
2670 }
2671 while (start < end) {
2672 *p++ = *start;
2673 ++start;
2674 }
2675 q = end;
2676 break;
2677 } else {
2678 while (start < end2 && *start != '\'') {
2679 ++start;
2680 }
2681 while (end2 > start && *end2 != '\'') {
2682 --end2;
2683 }
2684 if (*start == '\'' && *end2 == '\'') {
2685 while (start <= end2) {
2686 *p++ = *start;
2687 ++start;
2688 }
2689 q = end;
2690 break;
2691 }
2692 }
2693 }
2694 }
2695 /* FALL THROUGH */
2696 default:
2697 *p++ = *q;
2698 }
2699 ++q;
2700 }
2701 freep(&qz);
2702 *p = '\0';
2703 if (nparam) {
2704 *nparam = np;
2705 }
2706 if (isselect) {
2707 if (isddl < 0) {
2708 isddl = checkddl(out);
2709 }
2710 if (isddl > 0) {
2711 *isselect = 2;
2712 } else {
2713 int incom = 0;
2714
2715 p = out;
2716 while (*p) {
2717 switch (*p) {
2718 case '-':
2719 if (!incom && p[1] == '-') {
2720 incom = -1;
2721 }
2722 break;
2723 case '\n':
2724 if (incom < 0) {
2725 incom = 0;
2726 }
2727 break;
2728 case '/':
2729 if (incom > 0 && p[-1] == '*') {
2730 incom = 0;
2731 p++;
2732 continue;
2733 } else if (!incom && p[1] == '*') {
2734 incom = 1;
2735 }
2736 break;
2737 }
2738 if (!incom && !ISSPACE(*p)) {
2739 break;
2740 }
2741 p++;
2742 }
2743 size = strlen(p);
2744 if (size >= 6 &&
2745 (strncasecmp(p, "select", 6) == 0 ||
2746 strncasecmp(p, "pragma", 6) == 0)) {
2747 *isselect = 1;
2748 } else if (cte && size >= 4 && strncasecmp(p, "with", 4) == 0) {
2749 *isselect = 1;
2750 } else if (size >= 7 && strncasecmp(p, "explain", 7) == 0) {
2751 *isselect = 1;
2752 } else {
2753 *isselect = 0;
2754 }
2755 }
2756 }
2757 return out;
2758}
2759
2765static void
2766replilike(char *sql)
2767{
2768 char *q = sql, *inq = NULL;
2769
2770 while (*q) {
2771 switch (*q) {
2772 case '\'':
2773 case '\"':
2774 if (q == inq) {
2775 inq = NULL;
2776 } else if (!inq) {
2777 inq = q + 1;
2778
2779 while (*inq) {
2780 if (*inq == *q) {
2781 if (inq[1] == *q) {
2782 inq++;
2783 } else {
2784 break;
2785 }
2786 }
2787 inq++;
2788 }
2789 }
2790 break;
2791 case '-':
2792 if (!inq && q[1] == '-') {
2793 ++q;
2794 while (*q) {
2795 if (*q == '\n') {
2796 break;
2797 }
2798 }
2799 }
2800 break;
2801 default:
2802 if (!inq && ISSPACE(*q) && q[1]) {
2803 if (strncasecmp(q + 1, "ilike", 5) == 0) {
2804 if ((q[2] != '\0') && (q[3] != '\0') &&
2805 (q[4] != '\0') && (q[5] != '\0') &&
2806 ((q[6] == '\0') || ISSPACE(q[6]))) {
2807 q++;
2808 memmove(q, q + 1, strlen(q));
2809 q += 3;
2810 }
2811 }
2812 }
2813 break;
2814 }
2815 ++q;
2816 }
2817}
2818
2827static int
2828findcol(char **cols, int ncols, char *name)
2829{
2830 int i;
2831
2832 if (cols) {
2833 for (i = 0; i < ncols; i++) {
2834 if (strcmp(cols[i], name) == 0) {
2835 return i;
2836 }
2837 }
2838 }
2839 return -1;
2840}
2841
2858static void
2860{
2861 int i, k;
2862#ifndef FULL_METADATA
2863 int pk, nn, t, r, nrows, ncols;
2864 char **rowp, *flagp, flags[128];
2865#endif
2866
2867 if (!s->dyncols) {
2868 return;
2869 }
2870 /* fixup labels */
2871 if (!s->longnames) {
2872 if (s->dcols > 1) {
2873 char *table = s->dyncols[0].table;
2874
2875 for (i = 1; table[0] && i < s->dcols; i++) {
2876 if (strcmp(s->dyncols[i].table, table)) {
2877 break;
2878 }
2879 }
2880 if (i >= s->dcols) {
2881 for (i = 0; i < s->dcols; i++) {
2882 s->dyncols[i].label = s->dyncols[i].column;
2883 }
2884 }
2885 } else if (s->dcols == 1) {
2886 s->dyncols[0].label = s->dyncols[0].column;
2887 }
2888 }
2889 for (i = 0; i < s->dcols; i++) {
2890 s->dyncols[i].type =
2891 mapsqltype(s->dyncols[i].typename, &s->dyncols[i].nosign, *s->ov3,
2892 s->nowchar[0] || s->nowchar[1], s->dobigint);
2893 getmd(s->dyncols[i].typename, s->dyncols[i].type,
2894 &s->dyncols[i].size, &s->dyncols[i].prec);
2895#ifdef SQL_LONGVARCHAR
2896 if (s->dyncols[i].type == SQL_VARCHAR &&
2897 s->dyncols[i].size > 255) {
2898 s->dyncols[i].type = SQL_LONGVARCHAR;
2899 }
2900#endif
2901#ifdef WINTERFACE
2902#ifdef SQL_WLONGVARCHAR
2903 if (s->dyncols[i].type == SQL_WVARCHAR &&
2904 s->dyncols[i].size > 255) {
2905 s->dyncols[i].type = SQL_WLONGVARCHAR;
2906 }
2907#endif
2908#endif
2909 if (s->dyncols[i].type == SQL_VARBINARY &&
2910 s->dyncols[i].size > 255) {
2911 s->dyncols[i].type = SQL_LONGVARBINARY;
2912 }
2913 }
2914#ifndef FULL_METADATA
2915 if (s->dcols > array_size(flags)) {
2916 flagp = xmalloc(sizeof (flags[0]) * s->dcols);
2917 if (flagp == NULL) {
2918 return;
2919 }
2920 } else {
2921 flagp = flags;
2922 }
2923 memset(flagp, 0, sizeof (flags[0]) * s->dcols);
2924 for (i = 0; i < s->dcols; i++) {
2925 s->dyncols[i].autoinc = SQL_FALSE;
2926 s->dyncols[i].notnull = SQL_NULLABLE;
2927 }
2928 for (i = 0; i < s->dcols; i++) {
2929 int ret, lastpk = -1, autoinccount = 0;
2930 char *sql;
2931
2932 if (!s->dyncols[i].table[0]) {
2933 continue;
2934 }
2935 if (flagp[i]) {
2936 continue;
2937 }
2938 sql = sqlite3_mprintf("PRAGMA table_info(%Q)", s->dyncols[i].table);
2939 if (!sql) {
2940 continue;
2941 }
2942 dbtraceapi(d, "sqlite3_get_table", sql);
2943 ret = sqlite3_get_table(d->sqlite, sql, &rowp, &nrows, &ncols, NULL);
2944 sqlite3_free(sql);
2945 if (ret != SQLITE_OK) {
2946 continue;
2947 }
2948 k = findcol(rowp, ncols, "name");
2949 t = findcol(rowp, ncols, "type");
2950 pk = findcol(rowp, ncols, "pk");
2951 nn = findcol(rowp, ncols, "notnull");
2952 if (k < 0 || t < 0) {
2953 goto freet;
2954 }
2955 for (r = 1; r <= nrows; r++) {
2956 int m;
2957
2958 for (m = i; m < s->dcols; m++) {
2959 char *colname = s->dyncols[m].column;
2960
2961 if (s->longnames) {
2962 char *dotp = strchr(colname, '.');
2963
2964 if (dotp) {
2965 colname = dotp + 1;
2966 }
2967 }
2968 if (!flagp[m] &&
2969 strcmp(colname, rowp[r * ncols + k]) == 0 &&
2970 strcmp(s->dyncols[m].table, s->dyncols[i].table) == 0) {
2971 char *typename = rowp[r * ncols + t];
2972
2973 flagp[m] = i + 1;
2974 freep(&s->dyncols[m].typename);
2975 s->dyncols[m].typename = xstrdup(typename);
2976 s->dyncols[m].type =
2977 mapsqltype(typename, &s->dyncols[m].nosign, *s->ov3,
2978 s->nowchar[0] || s->nowchar[1],
2979 s->dobigint);
2980 getmd(typename, s->dyncols[m].type, &s->dyncols[m].size,
2981 &s->dyncols[m].prec);
2982#ifdef SQL_LONGVARCHAR
2983 if (s->dyncols[m].type == SQL_VARCHAR &&
2984 s->dyncols[m].size > 255) {
2985 s->dyncols[m].type = SQL_LONGVARCHAR;
2986 }
2987#endif
2988#ifdef WINTERFACE
2989#ifdef SQL_WLONGVARCHAR
2990 if (s->dyncols[i].type == SQL_WVARCHAR &&
2991 s->dyncols[i].size > 255) {
2992 s->dyncols[i].type = SQL_WLONGVARCHAR;
2993 }
2994#endif
2995#endif
2996 if (s->dyncols[i].type == SQL_VARBINARY &&
2997 s->dyncols[i].size > 255) {
2998 s->dyncols[i].type = SQL_LONGVARBINARY;
2999 }
3000 if (pk >= 0 && strcmp(rowp[r * ncols + pk], "1") == 0) {
3001 s->dyncols[m].ispk = 1;
3002 if (++autoinccount > 1) {
3003 if (lastpk >= 0) {
3004 s->dyncols[lastpk].autoinc = SQL_FALSE;
3005 lastpk = -1;
3006 }
3007 } else {
3008 lastpk = m;
3009 if (strlen(typename) == 7 &&
3010 strncasecmp(typename, "integer", 7) == 0) {
3011 s->dyncols[m].autoinc = SQL_TRUE;
3012 }
3013 }
3014 } else {
3015 s->dyncols[m].ispk = 0;
3016 }
3017 if (nn >= 0 && rowp[r * ncols + nn][0] != '0') {
3018 s->dyncols[m].notnull = SQL_NO_NULLS;
3019 }
3020 }
3021 }
3022 }
3023freet:
3024 sqlite3_free_table(rowp);
3025 }
3026 for (i = k = 0; i < s->dcols; i++) {
3027 if (flagp[i] == 0) {
3028 break;
3029 }
3030 if (k == 0) {
3031 k = flagp[i];
3032 } else if (flagp[i] != k) {
3033 k = 0;
3034 break;
3035 }
3036 }
3037 s->one_tbl = k ? 1 : 0;
3038 k = 0;
3039 if (s->one_tbl) {
3040 for (i = 0; i < s->dcols; i++) {
3041 if (s->dyncols[i].ispk > 0) {
3042 ++k;
3043 }
3044 }
3045 }
3046 s->has_pk = k;
3047 if (flagp != flags) {
3048 freep(&flagp);
3049 }
3050#else
3051 for (i = 1, k = 0; i < s->dcols; i++) {
3052 if (strcmp(s->dyncols[i].table, s->dyncols[0].table) == 0) {
3053 k++;
3054 }
3055 }
3056 s->one_tbl = (k && k + 1 == s->dcols) ? 1 : 0;
3057 k = 0;
3058 if (s->one_tbl) {
3059 for (i = 0; i < s->dcols; i++) {
3060 if (s->dyncols[i].ispk > 0) {
3061 ++k;
3062 if (s->has_rowid < 0 && s->dyncols[i].isrowid > 0) {
3063 s->has_rowid = i;
3064 }
3065 }
3066 }
3067 }
3068 s->has_pk = k;
3069#endif
3070}
3071
3078static void
3079convJD2YMD(double jd, DATE_STRUCT *ds)
3080{
3081 int z, a, b, c, d, e, x1;
3082 sqlite_int64 ijd;
3083
3084 ijd = jd * 86400000.0 + 0.5;
3085 z = (int) ((ijd + 43200000) / 86400000);
3086 a = (int) ((z - 1867216.25) / 36524.25);
3087 a = z + 1 + a - (a / 4);
3088 b = a + 1524;
3089 c = (int) ((b - 122.1) / 365.25);
3090 d = (36525 * c) / 100;
3091 e = (int) ((b - d) / 30.6001);
3092 x1 = (int) (30.6001 * e);
3093 ds->day = b - d - x1;
3094 ds->month = (e < 14) ? (e - 1) : (e - 13);
3095 ds->year = (ds->month > 2) ? (c - 4716) : (c - 4715);
3096}
3097
3098
3106static void
3107convJD2HMS(double jd, TIME_STRUCT *ts, int *fp)
3108{
3109 int s;
3110 double ds;
3111 sqlite_int64 ijd;
3112
3113 ijd = jd * 86400000.0 + 0.5;
3114 s = (int)((ijd + 43200000) % 86400000);
3115 ds = s / 1000.0;
3116 if (fp) {
3117 *fp = (s % 1000) * 1000000;
3118 }
3119 s = (int) ds;
3120 ds -= s;
3121 ts->hour = s / 3600;
3122 s -= ts->hour * 3600;
3123 ts->minute = s / 60;
3124 ds += s - ts->minute *60;
3125 ts->second = (int) ds;
3126}
3127
3135static int
3136getmdays(int year, int month)
3137{
3138 static const int mdays[] = {
3139 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31
3140 };
3141 int mday;
3142
3143 if (month < 1) {
3144 return 0;
3145 }
3146 mday = mdays[(month - 1) % 12];
3147 if (mday == 28 && year % 4 == 0 &&
3148 (!(year % 100 == 0) || year % 400 == 0)) {
3149 mday++;
3150 }
3151 return mday;
3152}
3153
3169static int
3170str2date(int jdconv, char *str, DATE_STRUCT *ds)
3171{
3172 int i, err = 0;
3173 double jd;
3174 char *p, *q, sepc = '\0';
3175
3176 ds->year = ds->month = ds->day = 0;
3177 if (jdconv) {
3178 p = strchr(str, '.');
3179 if (p) {
3180 /* julian day format */
3181 p = 0;
3182 jd = ln_strtod(str, &p);
3183 if (p && p > str) {
3184 convJD2YMD(jd, ds);
3185 return 0;
3186 }
3187 }
3188 }
3189 p = str;
3190 while (*p && !ISDIGIT(*p)) {
3191 ++p;
3192 }
3193 q = p;
3194 i = 0;
3195 while (*q && !ISDIGIT(*q)) {
3196 ++i;
3197 ++q;
3198 }
3199 if (i >= 8) {
3200 char buf[8];
3201
3202 strncpy(buf, p + 0, 4); buf[4] = '\0';
3203 ds->year = strtol(buf, NULL, 10);
3204 strncpy(buf, p + 4, 2); buf[2] = '\0';
3205 ds->month = strtol(buf, NULL, 10);
3206 strncpy(buf, p + 6, 2); buf[2] = '\0';
3207 ds->day = strtol(buf, NULL, 10);
3208 goto done;
3209 }
3210 i = 0;
3211 while (i < 3) {
3212 int n;
3213
3214 q = NULL;
3215 n = strtol(p, &q, 10);
3216 if (!q || q == p) {
3217 if (*q == '\0') {
3218 if (i == 0) {
3219 err = 1;
3220 }
3221 goto done;
3222 }
3223 }
3224 if (!sepc) {
3225 sepc = *q;
3226 }
3227 if (*q == '-' || *q == '/' || *q == '\0' || i == 2) {
3228 switch (i) {
3229 case 0: ds->year = n; break;
3230 case 1: ds->month = n; break;
3231 case 2: ds->day = n; break;
3232 }
3233 ++i;
3234 if (*q) {
3235 ++q;
3236 }
3237 } else {
3238 i = 0;
3239 while (*q && !ISDIGIT(*q)) {
3240 ++q;
3241 }
3242 }
3243 p = q;
3244 }
3245done:
3246 /* final check for overflow */
3247 if (err ||
3248 ds->month < 1 || ds->month > 12 ||
3249 ds->day < 1 || ds->day > getmdays(ds->year, ds->month)) {
3250 if (sepc == '/') {
3251 /* Try MM/DD/YYYY format */
3252 int t[3];
3253
3254 t[0] = ds->year;
3255 t[1] = ds->month;
3256 t[2] = ds->day;
3257 ds->year = t[2];
3258 ds->day = t[1];
3259 ds->month = t[0];
3260 if (ds->month >= 1 && ds->month <= 12 &&
3261 (ds->day >= 1 || ds->day <= getmdays(ds->year, ds->month))) {
3262 return 0;
3263 }
3264 }
3265 return -1;
3266 }
3267 return 0;
3268}
3269
3284static int
3285str2time(int jdconv, char *str, TIME_STRUCT *ts)
3286{
3287 int i, err = 0, ampm = -1;
3288 double jd;
3289 char *p, *q;
3290
3291 ts->hour = ts->minute = ts->second = 0;
3292 if (jdconv) {
3293 p = strchr(str, '.');
3294 if (p) {
3295 /* julian day format */
3296 p = 0;
3297 jd = ln_strtod(str, &p);
3298 if (p && p > str) {
3299 convJD2HMS(jd, ts, 0);
3300 return 0;
3301 }
3302 }
3303 }
3304 p = str;
3305 while (*p && !ISDIGIT(*p)) {
3306 ++p;
3307 }
3308 q = p;
3309 i = 0;
3310 while (*q && ISDIGIT(*q)) {
3311 ++i;
3312 ++q;
3313 }
3314 if (i >= 6) {
3315 char buf[4];
3316
3317 strncpy(buf, p + 0, 2); buf[2] = '\0';
3318 ts->hour = strtol(buf, NULL, 10);
3319 strncpy(buf, p + 2, 2); buf[2] = '\0';
3320 ts->minute = strtol(buf, NULL, 10);
3321 strncpy(buf, p + 4, 2); buf[2] = '\0';
3322 ts->second = strtol(buf, NULL, 10);
3323 goto done;
3324 }
3325 i = 0;
3326 while (i < 3) {
3327 int n;
3328
3329 q = NULL;
3330 n = strtol(p, &q, 10);
3331 if (!q || q == p) {
3332 if (*q == '\0') {
3333 if (i == 0) {
3334 err = 1;
3335 }
3336 goto done;
3337 }
3338 }
3339 if (*q == ':' || *q == '\0' || i == 2) {
3340 switch (i) {
3341 case 0: ts->hour = n; break;
3342 case 1: ts->minute = n; break;
3343 case 2: ts->second = n; break;
3344 }
3345 ++i;
3346 if (*q) {
3347 ++q;
3348 }
3349 } else {
3350 i = 0;
3351 while (*q && !ISDIGIT(*q)) {
3352 ++q;
3353 }
3354 }
3355 p = q;
3356 }
3357 if (!err) {
3358 while (*p) {
3359 if ((p[0] == 'p' || p[0] == 'P') &&
3360 (p[1] == 'm' || p[1] == 'M')) {
3361 ampm = 1;
3362 } else if ((p[0] == 'a' || p[0] == 'A') &&
3363 (p[1] == 'm' || p[1] == 'M')) {
3364 ampm = 0;
3365 }
3366 ++p;
3367 }
3368 if (ampm > 0) {
3369 if (ts->hour < 12) {
3370 ts->hour += 12;
3371 }
3372 } else if (ampm == 0) {
3373 if (ts->hour == 12) {
3374 ts->hour = 0;
3375 }
3376 }
3377 }
3378done:
3379 /* final check for overflow */
3380 if (err || ts->hour > 23 || ts->minute > 59 || ts->second > 59) {
3381 return -1;
3382 }
3383 return 0;
3384}
3385
3405static int
3406str2timestamp(int jdconv, char *str, TIMESTAMP_STRUCT *tss)
3407{
3408 int i, m, n, err = 0, ampm = -1;
3409 double jd;
3410 char *p, *q, in = '\0', sepc = '\0';
3411
3412 tss->year = tss->month = tss->day = 0;
3413 tss->hour = tss->minute = tss->second = 0;
3414 tss->fraction = 0;
3415 if (jdconv) {
3416 p = strchr(str, '.');
3417 if (p) {
3418 q = strchr(str, '-');
3419 if (q == str) {
3420 q = 0;
3421 }
3422 if (!q) {
3423 q = strchr(str, '/');
3424 if (!q) {
3425 q = strchr(str, ':');
3426 }
3427 }
3428 if (!q || q > p) {
3429 /* julian day format */
3430 p = 0;
3431 jd = ln_strtod(str, &p);
3432 if (p && p > str) {
3433 DATE_STRUCT ds;
3434 TIME_STRUCT ts;
3435
3436 convJD2YMD(jd, &ds);
3437 convJD2HMS(jd, &ts, &n);
3438 tss->year = ds.year;
3439 tss->month = ds.month;
3440 tss->day = ds.day;
3441 tss->hour = ts.hour;
3442 tss->minute = ts.minute;
3443 tss->second = ts.second;
3444 tss->fraction = n;
3445 return 0;
3446 }
3447 }
3448 }
3449 }
3450 p = str;
3451 while (*p && !ISDIGIT(*p)) {
3452 ++p;
3453 }
3454 q = p;
3455 i = 0;
3456 while (*q && ISDIGIT(*q)) {
3457 ++i;
3458 ++q;
3459 }
3460 if (i >= 14) {
3461 char buf[16];
3462
3463 strncpy(buf, p + 0, 4); buf[4] = '\0';
3464 tss->year = strtol(buf, NULL, 10);
3465 strncpy(buf, p + 4, 2); buf[2] = '\0';
3466 tss->month = strtol(buf, NULL, 10);
3467 strncpy(buf, p + 6, 2); buf[2] = '\0';
3468 tss->day = strtol(buf, NULL, 10);
3469 strncpy(buf, p + 8, 2); buf[2] = '\0';
3470 tss->hour = strtol(buf, NULL, 10);
3471 strncpy(buf, p + 10, 2); buf[2] = '\0';
3472 tss->minute = strtol(buf, NULL, 10);
3473 strncpy(buf, p + 12, 2); buf[2] = '\0';
3474 tss->second = strtol(buf, NULL, 10);
3475 if (i > 14) {
3476 m = i - 14;
3477 strncpy(buf, p + 14, m);
3478 while (m < 9) {
3479 buf[m] = '0';
3480 ++m;
3481 }
3482 buf[m] = '\0';
3483 tss->fraction = strtol(buf, NULL, 10);
3484 }
3485 m = 7;
3486 goto done;
3487 }
3488 m = i = 0;
3489 while ((m & 7) != 7) {
3490 q = NULL;
3491 n = strtol(p, &q, 10);
3492 if (!q || q == p) {
3493 if (*q == '\0') {
3494 if (m < 1) {
3495 err = 1;
3496 }
3497 goto done;
3498 }
3499 }
3500 if (in == '\0') {
3501 switch (*q) {
3502 case '-':
3503 case '/':
3504 if ((m & 1) == 0) {
3505 in = *q;
3506 i = 0;
3507 }
3508 break;
3509 case ':':
3510 if ((m & 2) == 0) {
3511 in = *q;
3512 i = 0;
3513 }
3514 break;
3515 case ' ':
3516 case '.':
3517 break;
3518 default:
3519 in = '\0';
3520 i = 0;
3521 break;
3522 }
3523 }
3524 switch (in) {
3525 case '-':
3526 case '/':
3527 if (!sepc) {
3528 sepc = in;
3529 }
3530 switch (i) {
3531 case 0: tss->year = n; break;
3532 case 1: tss->month = n; break;
3533 case 2: tss->day = n; break;
3534 }
3535 if (++i >= 3) {
3536 i = 0;
3537 m |= 1;
3538 if (!(m & 2)) {
3539 m |= 8;
3540 }
3541 goto skip;
3542 } else {
3543 ++q;
3544 }
3545 break;
3546 case ':':
3547 switch (i) {
3548 case 0: tss->hour = n; break;
3549 case 1: tss->minute = n; break;
3550 case 2: tss->second = n; break;
3551 }
3552 if (++i >= 3) {
3553 i = 0;
3554 m |= 2;
3555 if (*q == '.') {
3556 in = '.';
3557 goto skip2;
3558 }
3559 if (*q == ' ') {
3560 if ((m & 1) == 0) {
3561 char *e = NULL;
3562
3563 (void) strtol(q + 1, &e, 10);
3564 if (e && *e == '-') {
3565 goto skip;
3566 }
3567 }
3568 in = '.';
3569 goto skip2;
3570 }
3571 goto skip;
3572 } else {
3573 ++q;
3574 }
3575 break;
3576 case '.':
3577 if (++i >= 1) {
3578 int ndig = q - p;
3579
3580 if (p[0] == '+' || p[0] == '-') {
3581 ndig--;
3582 }
3583 while (ndig < 9) {
3584 n = n * 10;
3585 ++ndig;
3586 }
3587 tss->fraction = n;
3588 m |= 4;
3589 i = 0;
3590 }
3591 default:
3592 skip:
3593 in = '\0';
3594 skip2:
3595 while (*q && !ISDIGIT(*q)) {
3596 if ((q[0] == 'a' || q[0] == 'A') &&
3597 (q[1] == 'm' || q[1] == 'M')) {
3598 ampm = 0;
3599 ++q;
3600 } else if ((q[0] == 'p' || q[0] == 'P') &&
3601 (q[1] == 'm' || q[1] == 'M')) {
3602 ampm = 1;
3603 ++q;
3604 }
3605 ++q;
3606 }
3607 }
3608 p = q;
3609 }
3610 if ((m & 7) > 1 && (m & 8)) {
3611 /* ISO8601 timezone */
3612 if (p > str && ISDIGIT(*p)) {
3613 int nn, sign;
3614
3615 q = p - 1;
3616 if (*q != '+' && *q != '-') {
3617 goto done;
3618 }
3619 sign = (*q == '+') ? -1 : 1;
3620 q = NULL;
3621 n = strtol(p, &q, 10);
3622 if (!q || *q++ != ':' || !ISDIGIT(*q)) {
3623 goto done;
3624 }
3625 p = q;
3626 q = NULL;
3627 nn = strtol(p, &q, 10);
3628 tss->minute += nn * sign;
3629 if ((SQLSMALLINT) tss->minute < 0) {
3630 tss->hour -= 1;
3631 tss->minute += 60;
3632 } else if (tss->minute >= 60) {
3633 tss->hour += 1;
3634 tss->minute -= 60;
3635 }
3636 tss->hour += n * sign;
3637 if ((SQLSMALLINT) tss->hour < 0) {
3638 tss->day -= 1;
3639 tss->hour += 24;
3640 } else if (tss->hour >= 24) {
3641 tss->day += 1;
3642 tss->hour -= 24;
3643 }
3644 if ((short) tss->day < 1 || tss->day >= 28) {
3645 int mday, pday, pmon;
3646
3647 mday = getmdays(tss->year, tss->month);
3648 pmon = tss->month - 1;
3649 if (pmon < 1) {
3650 pmon = 12;
3651 }
3652 pday = getmdays(tss->year, pmon);
3653 if ((SQLSMALLINT) tss->day < 1) {
3654 tss->month -= 1;
3655 tss->day = pday;
3656 } else if (tss->day > mday) {
3657 tss->month += 1;
3658 tss->day = 1;
3659 }
3660 if ((SQLSMALLINT) tss->month < 1) {
3661 tss->year -= 1;
3662 tss->month = 12;
3663 } else if (tss->month > 12) {
3664 tss->year += 1;
3665 tss->month = 1;
3666 }
3667 }
3668 }
3669 }
3670done:
3671 if ((m & 1) &&
3672 (tss->month < 1 || tss->month > 12 ||
3673 tss->day < 1 || tss->day > getmdays(tss->year, tss->month))) {
3674 if (sepc == '/') {
3675 /* Try MM/DD/YYYY format */
3676 int t[3];
3677
3678 t[0] = tss->year;
3679 t[1] = tss->month;
3680 t[2] = tss->day;
3681 tss->year = t[2];
3682 tss->day = t[1];
3683 tss->month = t[0];
3684 }
3685 }
3686 /* Replace missing year/month/day with current date */
3687 if (!err && (m & 1) == 0) {
3688#ifdef _WIN32
3689 SYSTEMTIME t;
3690
3691 GetLocalTime(&t);
3692 tss->year = t.wYear;
3693 tss->month = t.wMonth;
3694 tss->day = t.wDay;
3695#else
3696 struct timeval tv;
3697 struct tm tm;
3698
3699 gettimeofday(&tv, NULL);
3700 tm = *localtime(&tv.tv_sec);
3701 tss->year = tm.tm_year + 1900;
3702 tss->month = tm.tm_mon + 1;
3703 tss->day = tm.tm_mday;
3704#endif
3705 }
3706 /* Normalize fraction */
3707 if (tss->fraction < 0) {
3708 tss->fraction = 0;
3709 }
3710 /* Final check for overflow */
3711 if (err ||
3712 tss->month < 1 || tss->month > 12 ||
3713 tss->day < 1 || tss->day > getmdays(tss->year, tss->month) ||
3714 tss->hour > 23 || tss->minute > 59 || tss->second > 59) {
3715 return -1;
3716 }
3717 if ((m & 7) > 1) {
3718 if (ampm > 0) {
3719 if (tss->hour < 12) {
3720 tss->hour += 12;
3721 }
3722 } else if (ampm == 0) {
3723 if (tss->hour == 12) {
3724 tss->hour = 0;
3725 }
3726 }
3727 }
3728 return ((m & 7) < 1) ? -1 : 0;
3729}
3730
3737static int
3738getbool(char *string)
3739{
3740 if (string) {
3741 return string[0] && strchr("Yy123456789Tt", string[0]) != NULL;
3742 }
3743 return 0;
3744}
3745
3753static void
3754blob_import(sqlite3_context *ctx, int nargs, sqlite3_value **args)
3755{
3756#if 0
3757 DBC *d = (DBC *) sqlite3_user_data(ctx);
3758#endif
3759 char *filename = 0;
3760
3761 if (nargs > 0) {
3762 if (sqlite3_value_type(args[0]) != SQLITE_NULL) {
3763 filename = (char *) sqlite3_value_text(args[0]);
3764 }
3765 }
3766 if (filename) {
3767#ifdef _WIN32
3768 char *wname = utf_to_wmb(filename, -1);
3769 FILE *f;
3770#else
3771 FILE *f = fopen(filename, "r");
3772#endif
3773 char *p;
3774 long n, nn;
3775
3776#ifdef _WIN32
3777 if (wname) {
3778 f = fopen(wname, "rb");
3779 } else {
3780 sqlite3_result_error(ctx, "out of memory", -1);
3781 return;
3782 }
3783 uc_free(wname);
3784#endif
3785 if (f) {
3786 if (fseek(f, 0, SEEK_END) == 0) {
3787 n = ftell(f);
3788 if (fseek(f, 0, SEEK_SET) == 0) {
3789 p = sqlite3_malloc(n);
3790 if (p) {
3791 nn = fread(p, 1, n, f);
3792 if (nn != n) {
3793 sqlite3_result_error(ctx, "read error", -1);
3794 sqlite3_free(p);
3795 } else {
3796 sqlite3_result_blob(ctx, p, n, sqlite3_free);
3797 }
3798 } else {
3799 sqlite3_result_error(ctx, "out of memory", -1);
3800 }
3801 } else {
3802 sqlite3_result_error(ctx, "seek error", -1);
3803 }
3804 } else {
3805 sqlite3_result_error(ctx, "seek error", -1);
3806 }
3807 fclose(f);
3808 } else {
3809 sqlite3_result_error(ctx, "cannot open file", -1);
3810 }
3811 } else {
3812 sqlite3_result_error(ctx, "no filename given", -1);
3813 }
3814}
3815
3823static void
3824blob_export(sqlite3_context *ctx, int nargs, sqlite3_value **args)
3825{
3826#if 0
3827 DBC *d = (DBC *) sqlite3_user_data(ctx);
3828#endif
3829 char *filename = 0;
3830 char *p = 0;
3831 int n = 0;
3832
3833 if (nargs > 0) {
3834 p = (char *) sqlite3_value_blob(args[0]);
3835 n = sqlite3_value_bytes(args[0]);
3836 }
3837 if (nargs > 1) {
3838 if (sqlite3_value_type(args[1]) != SQLITE_NULL) {
3839 filename = (char *) sqlite3_value_text(args[1]);
3840 }
3841 }
3842 if (p) {
3843 if (filename) {
3844#ifdef _WIN32
3845 char *wname = utf_to_wmb(filename, -1);
3846 FILE *f;
3847#else
3848 FILE *f = fopen(filename, "w");
3849#endif
3850 int nn;
3851
3852#ifdef _WIN32
3853 if (wname) {
3854 f = fopen(wname, "wb");
3855 } else {
3856 sqlite3_result_error(ctx, "out of memory", -1);
3857 return;
3858 }
3859 uc_free(wname);
3860#endif
3861 if (f) {
3862 nn = fwrite(p, 1, n, f);
3863 fclose(f);
3864 if (nn != n) {
3865 sqlite3_result_error(ctx, "write error", -1);
3866 } else {
3867 sqlite3_result_int(ctx, nn);
3868 }
3869 } else {
3870 sqlite3_result_error(ctx, "cannot open file", -1);
3871 }
3872 } else {
3873 sqlite3_result_error(ctx, "no filename given", -1);
3874 }
3875 } else {
3876 sqlite3_result_null(ctx);
3877 }
3878}
3879
3887static void
3888#if defined(HAVE_SQLITE3PROFILE) && (HAVE_SQLITE3PROFILE)
3889dbtrace(void *arg, const char *msg, sqlite_uint64 et)
3890#else
3891dbtrace(void *arg, const char *msg)
3892#endif
3893{
3894 DBC *d = (DBC *) arg;
3895
3896 if (msg && d->trace) {
3897 int len = strlen(msg);
3898#if defined(HAVE_SQLITE3PROFILE) && (HAVE_SQLITE3PROFILE)
3899 unsigned long s, f;
3900#endif
3901
3902 if (len > 0) {
3903 char *end = "\n";
3904
3905 if (msg[len - 1] != ';') {
3906 end = ";\n";
3907 }
3908 fprintf(d->trace, "%s%s", msg, end);
3909#if defined(HAVE_SQLITE3PROFILE) && (HAVE_SQLITE3PROFILE)
3910 s = et / 1000000000LL;
3911 f = et % 1000000000LL;
3912 fprintf(d->trace, "-- took %lu.%09lu seconds\n", s, f);
3913#endif
3914 fflush(d->trace);
3915 }
3916 }
3917}
3918
3926static void
3927dbtraceapi(DBC *d, char *fn, const char *sql)
3928{
3929 if (fn && d->trace) {
3930 if (sql) {
3931 fprintf(d->trace, "-- %s: %s\n", fn, sql);
3932 } else {
3933 fprintf(d->trace, "-- %s\n", fn);
3934 }
3935 fflush(d->trace);
3936 }
3937}
3938
3946static void
3947dbtracerc(DBC *d, int rc, char *err)
3948{
3949 if (rc != SQLITE_OK && d->trace) {
3950 fprintf(d->trace, "-- SQLITE ERROR CODE %d", rc);
3951 fprintf(d->trace, err ? ": %s\n" : "\n", err);
3952 fflush(d->trace);
3953 }
3954}
3955
3970static SQLRETURN
3971dbopen(DBC *d, char *name, int isu, char *dsn, char *sflag,
3972 char *spflag, char *ntflag, char *jmode, char *busy)
3973{
3974 char *endp = NULL;
3975 int rc, tmp, busyto = 100000;
3976#if defined(HAVE_SQLITE3VFS) && (HAVE_SQLITE3VFS)
3977 int flags = SQLITE_OPEN_READWRITE | SQLITE_OPEN_CREATE;
3978 char *uname = name;
3979 const char *vfs_name = NULL;
3980#endif
3981
3982 if (d->sqlite) {
3983 if (d->trace) {
3984 fprintf(d->trace, "-- sqlite3_close (deferred): '%s'\n",
3985 d->dbname);
3986 fflush(d->trace);
3987 }
3988#if defined(HAVE_SQLITE3CLOSEV2) && (HAVE_SQLITE3CLOSEV2)
3989 sqlite3_close_v2(d->sqlite);
3990#else
3991 sqlite3_close(d->sqlite);
3992#endif
3993 d->sqlite = NULL;
3994 }
3995#if defined(HAVE_SQLITE3VFS) && (HAVE_SQLITE3VFS)
3996 if (d->nocreat) {
3997 flags &= ~ SQLITE_OPEN_CREATE;
3998 }
3999#if defined(_WIN32) || defined(_WIN64)
4000 if (!isu) {
4001 char expname[SQL_MAX_MESSAGE_LENGTH * 2];
4002
4003 expname[0] = '\0';
4004 rc = ExpandEnvironmentStrings(name, expname, sizeof (expname));
4005 if (rc <= sizeof (expname)) {
4006 uname = wmb_to_utf(expname, rc - 1);
4007 } else {
4008 uname = wmb_to_utf(name, -1);
4009 }
4010 if (!uname) {
4011 rc = SQLITE_NOMEM;
4012 setstatd(d, rc, "out of memory", (*d->ov3) ? "HY000" : "S1000");
4013 return SQL_ERROR;
4014 }
4015 }
4016#endif
4017#if defined(ENABLE_NVFS) && (ENABLE_NVFS)
4018 vfs_name = nvfs_makevfs(uname);
4019#endif
4020#ifdef SQLITE_OPEN_URI
4021 flags |= SQLITE_OPEN_URI;
4022#endif
4023 rc = sqlite3_open_v2(uname, &d->sqlite, flags, vfs_name);
4024#if defined(WINTERFACE) || defined(_WIN32) || defined(_WIN64)
4025 if (uname != name) {
4026 uc_free(uname);
4027 }
4028#endif
4029#else
4030#if defined(_WIN32) || defined(_WIN64)
4031 if (d->nocreat) {
4032 char *cname = NULL;
4033
4034 if (isu) {
4035 cname = utf_to_wmb(name, -1);
4036 }
4037 if (GetFileAttributesA(cname ? cname : name) ==
4038 INVALID_FILE_ATTRIBUTES) {
4039 uc_free(cname);
4040 rc = SQLITE_CANTOPEN;
4041 setstatd(d, rc, "cannot open database",
4042 (*d->ov3) ? "HY000" : "S1000");
4043 return SQL_ERROR;
4044 }
4045 uc_free(cname);
4046 }
4047#else
4048 if (d->nocreat && access(name, 004) < 0) {
4049 rc = SQLITE_CANTOPEN;
4050 setstatd(d, rc, "cannot open database", (*d->ov3) ? "HY000" : "S1000");
4051 return SQL_ERROR;
4052 }
4053#endif
4054#if defined(_WIN32) || defined(_WIN64)
4055 if (!isu) {
4056 WCHAR *wname = wmb_to_uc(name, -1);
4057
4058 if (!wname) {
4059 rc = SQLITE_NOMEM;
4060 setstatd(d, rc, "out of memory", (*d->ov3) ? "HY000" : "S1000");
4061 return SQL_ERROR;
4062 }
4063 rc = sqlite3_open16(wname, &d->sqlite);
4064 uc_free(wname);
4065 } else
4066#endif
4067 rc = sqlite3_open(name, &d->sqlite);
4068#endif /* !HAVE_SQLITE3VFS */
4069 if (rc != SQLITE_OK) {
4070connfail:
4071 setstatd(d, rc, "connect failed", (*d->ov3) ? "HY000" : "S1000");
4072 if (d->sqlite) {
4073 sqlite3_close(d->sqlite);
4074 d->sqlite = NULL;
4075 }
4076 return SQL_ERROR;
4077 }
4078#if defined(SQLITE_DYNLOAD) || defined(SQLITE_HAS_CODEC)
4079 if (d->pwd) {
4080 sqlite3_key(d->sqlite, d->pwd, d->pwdLen);
4081 }
4082#endif
4083 d->pwd = NULL;
4084 d->pwdLen = 0;
4085 if (d->trace) {
4086#if defined(HAVE_SQLITE3PROFILE) && (HAVE_SQLITE3PROFILE)
4087 sqlite3_profile(d->sqlite, dbtrace, d);
4088#else
4089 sqlite3_trace(d->sqlite, dbtrace, d);
4090#endif
4091 }
4092 d->step_enable = getbool(sflag);
4093 d->trans_disable = getbool(ntflag);
4094 d->curtype = d->step_enable ?
4095 SQL_CURSOR_FORWARD_ONLY : SQL_CURSOR_STATIC;
4096 tmp = strtol(busy, &endp, 0);
4097 if (endp && *endp == '\0' && endp != busy) {
4098 busyto = tmp;
4099 }
4100 if (busyto < 1 || busyto > 1000000) {
4101 busyto = 1000000;
4102 }
4103 d->timeout = busyto;
4104 freep(&d->dbname);
4105 d->dbname = xstrdup(name);
4106 freep(&d->dsn);
4107 d->dsn = xstrdup(dsn);
4108 if ((rc = setsqliteopts(d->sqlite, d)) != SQLITE_OK) {
4109 if (d->trace) {
4110 fprintf(d->trace, "-- sqlite3_close: '%s'\n",
4111 d->dbname);
4112 fflush(d->trace);
4113 }
4114 sqlite3_close(d->sqlite);
4115 d->sqlite = NULL;
4116 goto connfail;
4117 }
4118 if (!spflag || spflag[0] == '\0') {
4119 spflag = "NORMAL";
4120 }
4121 if (spflag[0] != '\0') {
4122 char syncp[128];
4123
4124 sprintf(syncp, "PRAGMA synchronous = %8.8s;", spflag);
4125 sqlite3_exec(d->sqlite, syncp, NULL, NULL, NULL);
4126 }
4127 if (jmode[0] != '\0') {
4128 char jourp[128];
4129
4130 sprintf(jourp, "PRAGMA journal_mode = %16.16s;", jmode);
4131 sqlite3_exec(d->sqlite, jourp, NULL, NULL, NULL);
4132 }
4133 if (d->trace) {
4134 fprintf(d->trace, "-- sqlite3_open: '%s'\n", d->dbname);
4135 fflush(d->trace);
4136 }
4137#if defined(_WIN32) || defined(_WIN64)
4138 {
4139 char pname[MAX_PATH];
4140 HANDLE h = OpenProcess(PROCESS_QUERY_INFORMATION | PROCESS_VM_READ,
4141 FALSE, GetCurrentProcessId());
4142
4143 pname[0] = '\0';
4144 if (h) {
4145 HMODULE m = NULL, l = LoadLibrary("psapi.dll");
4146 DWORD need;
4147 typedef BOOL (WINAPI *epmfunc)(HANDLE, HMODULE *, DWORD, LPDWORD);
4148 typedef BOOL (WINAPI *gmbfunc)(HANDLE, HMODULE, LPSTR, DWORD);
4149 epmfunc epm;
4150 gmbfunc gmb;
4151
4152 if (l) {
4153 epm = (epmfunc) GetProcAddress(l, "EnumProcessModules");
4154 gmb = (gmbfunc) GetProcAddress(l, "GetModuleBaseNameA");
4155 if (epm && gmb && epm(h, &m, sizeof (m), &need)) {
4156 gmb(h, m, pname, sizeof (pname));
4157 }
4158 FreeLibrary(l);
4159 }
4160 CloseHandle(h);
4161 }
4162 d->xcelqrx = strncasecmp(pname, "EXCEL", 5) == 0 ||
4163 strncasecmp(pname, "MSQRY", 5) == 0;
4164 if (d->trace && d->xcelqrx) {
4165
4166 fprintf(d->trace, "-- enabled EXCEL quirks\n");
4167 fflush(d->trace);
4168 }
4169 }
4170#endif
4171 sqlite3_create_function(d->sqlite, "blob_import", 1, SQLITE_UTF8,
4172 d, blob_import, 0, 0);
4173 sqlite3_create_function(d->sqlite, "blob_export", 2, SQLITE_UTF8,
4174 d, blob_export, 0, 0);
4175 return SQL_SUCCESS;
4176}
4177
4184static void
4185dbloadext(DBC *d, char *exts)
4186{
4187#if defined(HAVE_SQLITE3LOADEXTENSION) && (HAVE_SQLITE3LOADEXTENSION)
4188 char *p;
4189 char path[SQL_MAX_MESSAGE_LENGTH];
4190 int plen = 0;
4191
4192 if (!d->sqlite) {
4193 return;
4194 }
4195 sqlite3_enable_load_extension(d->sqlite, 1);
4196#if defined(_WIN32) || defined(_WIN64)
4197 GetModuleFileName(hModule, path, sizeof (path));
4198 p = strrchr(path, '\\');
4199 plen = p ? ((p + 1) - path) : 0;
4200#endif
4201 do {
4202 p = strchr(exts, ',');
4203 if (p) {
4204 strncpy(path + plen, exts, p - exts);
4205 path[plen + (p - exts)] = '\0';
4206 } else {
4207 strcpy(path + plen, exts);
4208 }
4209 if (exts[0]) {
4210 char *errmsg = NULL;
4211 int rc;
4212#if defined(_WIN32) || defined(_WIN64)
4213 int i;
4214 char *q;
4215
4216 q = path + plen;
4217 if (!(q[0] &&
4218 ((q[1] == ':' && (q[2] == '\\' || q[2] == '/')) ||
4219 q[0] == '\\' || q[0] == '/' || q[0] == '.'))) {
4220 q = path;
4221 }
4222 /* sqlite3_load_extension() dislikes backslashes */
4223 for (i = 0; q[i] != '\0'; i++) {
4224 if (q[i] == '\\') {
4225 q[i] = '/';
4226 }
4227 }
4228 rc = sqlite3_load_extension(d->sqlite, q, 0, &errmsg);
4229#else
4230 rc = sqlite3_load_extension(d->sqlite, path, 0, &errmsg);
4231#endif
4232 if (rc != SQLITE_OK) {
4233#if defined(_WIN32) || defined(_WIN64)
4234 char buf[512], msg[512];
4235
4236 LoadString(hModule, IDS_EXTERR, buf, sizeof (buf));
4237 wsprintf(msg, buf, q, errmsg ?
4238 errmsg : "no error info available");
4239 LoadString(hModule, IDS_EXTTITLE, buf, sizeof (buf));
4240 MessageBox(NULL, msg, buf,
4241 MB_ICONEXCLAMATION | MB_OK | MB_TASKMODAL |
4242 MB_SETFOREGROUND);
4243#else
4244 fprintf(stderr, "extension '%s' did not load%s%s\n",
4245 path, errmsg ? ": " : "", errmsg ? errmsg : "");
4246#endif
4247 }
4248 }
4249 if (p) {
4250 exts = p + 1;
4251 }
4252 } while (p);
4253#endif /* HAVE_SQLITE3LOADEXTENSION */
4254}
4255
4262static void
4263dbattas(DBC *d, char *attas)
4264{
4265 char *p;
4266 char as[SQL_MAX_MESSAGE_LENGTH];
4267
4268 if (!d->sqlite) {
4269 return;
4270 }
4271 do {
4272 p = strchr(attas, ',');
4273 if (p) {
4274 strncpy(as, attas, p - attas);
4275 as[p - attas] = '\0';
4276 } else {
4277 strcpy(as, attas);
4278 }
4279 if (attas[0]) {
4280 char *sql;
4281
4282 sql = sqlite3_mprintf("ATTACH %Q AS %s", d->dbname, as);
4283 if (sql != NULL) {
4284 sqlite3_exec(d->sqlite, sql, NULL, NULL, NULL);
4285 sqlite3_free(sql);
4286 }
4287 }
4288 if (p) {
4289 attas = p + 1;
4290 }
4291 } while (p);
4292}
4293
4303static char *
4304s3stmt_coltype(sqlite3_stmt *s3stmt, int col, DBC *d, int *guessed_types)
4305{
4306 char *typename = (char *) sqlite3_column_decltype(s3stmt, col);
4307 char guess[64];
4308
4309 guess[0] = '\0';
4310 if (!typename) {
4311 int coltype = sqlite3_column_type(s3stmt, col);
4312
4313 if (guessed_types) {
4314 guessed_types[0]++;
4315 }
4316 if (d->trace) {
4317 sprintf(guess, " (guessed from %d)", coltype);
4318 }
4319 switch (coltype) {
4320 case SQLITE_INTEGER: typename = "integer"; break;
4321 case SQLITE_FLOAT: typename = "double"; break;
4322 default:
4323 case SQLITE_TEXT: typename = "varchar"; break;
4324 case SQLITE_BLOB: typename = "blob"; break;
4325#if 0
4326 case SQLITE_NULL: typename = "null"; break;
4327#endif
4328 }
4329 }
4330 if (d->trace) {
4331 fprintf(d->trace, "-- column %d type%s: '%s'\n", col + 1,
4332 guess, typename);
4333 fflush(d->trace);
4334 }
4335 return typename;
4336}
4337
4338#ifdef FULL_METADATA
4339
4348static void
4349s3stmt_addmeta(sqlite3_stmt *s3stmt, int col, DBC *d, COL *ci)
4350{
4351 int nn = 0, pk = 0, ai = 0;
4352 const char *dn = NULL, *tn = NULL, *cn = NULL, *dummy[4];
4353
4354 dn = sqlite3_column_database_name(s3stmt, col);
4355 tn = sqlite3_column_table_name(s3stmt, col);
4356 cn = sqlite3_column_origin_name(s3stmt, col);
4357 dummy[0] = dummy[1] = 0;
4358 if (tn && cn) {
4359 sqlite3_table_column_metadata(d->sqlite, dn, tn, cn,
4360 dummy, dummy + 1,
4361 &nn, &pk, &ai);
4362 }
4363 ci->autoinc = ai ? SQL_TRUE: SQL_FALSE;
4364 ci->notnull = nn ? SQL_NO_NULLS : SQL_NULLABLE;
4365 ci->ispk = pk ? 1 : 0;
4366 if (d->trace) {
4367 fprintf(d->trace, "-- column %d %s\n",
4368 col + 1, nn ? "notnull" : "nullable");
4369 if (ai) {
4370 fprintf(d->trace, "-- column %d autoincrement\n", col + 1);
4371 }
4372 fflush(d->trace);
4373 }
4374 ci->isrowid = 0;
4375 if (ci->ispk && tn) {
4376 nn = pk = ai = 0;
4377 dummy[2] = dummy[3] = 0;
4378
4379 sqlite3_table_column_metadata(d->sqlite, dn, tn, "rowid",
4380 dummy + 2, dummy + 3,
4381 &nn, &pk, &ai);
4382 if (pk && dummy[0] && dummy[0] == dummy[2]) {
4383 ci->isrowid = 1;
4384 }
4385 }
4386}
4387
4388#endif
4389
4396static int
4398{
4399 DBC *d = (DBC *) s->dbc;
4400 char **rowd = NULL;
4401 const char *errp = NULL;
4402 int i, ncols, rc;
4403
4404 if (s != d->cur_s3stmt || !s->s3stmt) {
4405 setstat(s, -1, "stale statement", (*s->ov3) ? "HY000" : "S1000");
4406 return SQL_ERROR;
4407 }
4408 rc = sqlite3_step(s->s3stmt);
4409 if (rc == SQLITE_ROW || rc == SQLITE_DONE) {
4410 ++s->s3stmt_rownum;
4411 ncols = sqlite3_column_count(s->s3stmt);
4412 if (d->s3stmt_needmeta && s->s3stmt_rownum == 0 && ncols > 0) {
4413 PTRDIFF_T size;
4414 char *p;
4415 COL *dyncols;
4416 const char *colname, *typename;
4417#if defined(HAVE_SQLITE3COLUMNTABLENAME) && (HAVE_SQLITE3COLUMNTABLENAME)
4418 char *tblname;
4419#endif
4420#if defined(HAVE_SQLITE3COLUMNDATABASENAME) && (HAVE_SQLITE3COLUMNDATABASENAME)
4421 char *dbname;
4422#endif
4423
4424 for (i = size = 0; i < ncols; i++) {
4425 colname = sqlite3_column_name(s->s3stmt, i);
4426 size += 3 + 3 * strlen(colname);
4427 }
4428#if defined(HAVE_SQLITE3COLUMNTABLENAME) && (HAVE_SQLITE3COLUMNTABLENAME)
4429 tblname = (char *) size;
4430 for (i = 0; i < ncols; i++) {
4431 p = (char *) sqlite3_column_table_name(s->s3stmt, i);
4432 size += 2 + (p ? strlen(p) : 0);
4433 }
4434#endif
4435#if defined(HAVE_SQLITE3COLUMNDATABASENAME) && (HAVE_SQLITE3COLUMNDATABASENAME)
4436 dbname = (char *) size;
4437 for (i = 0; i < ncols; i++) {
4438 p = (char *) sqlite3_column_database_name(s->s3stmt, i);
4439 size += 2 + (p ? strlen(p) : 0);
4440 }
4441#endif
4442 dyncols = xmalloc(ncols * sizeof (COL) + size);
4443 if (!dyncols) {
4444 freedyncols(s);
4445 s->ncols = 0;
4446 dbtraceapi(d, "sqlite3_finalize", 0);
4447 sqlite3_finalize(s->s3stmt);
4448 s->s3stmt = NULL;
4449 d->cur_s3stmt = NULL;
4450 return nomem(s);
4451 }
4452 p = (char *) (dyncols + ncols);
4453#if defined(HAVE_SQLITE3COLUMNTABLENAME) && (HAVE_SQLITE3COLUMNTABLENAME)
4454 tblname = p + (PTRDIFF_T) tblname;
4455#endif
4456#if defined(HAVE_SQLITE3COLUMNDATABASENAME) && (HAVE_SQLITE3COLUMNDATABASENAME)
4457 dbname = p + (PTRDIFF_T) dbname;
4458#endif
4459 for (i = 0; i < ncols; i++) {
4460 char *q;
4461
4462 colname = sqlite3_column_name(s->s3stmt, i);
4463 if (d->trace) {
4464 fprintf(d->trace, "-- column %d name: '%s'\n",
4465 i + 1, colname);
4466 fflush(d->trace);
4467 }
4468#if defined(HAVE_SQLITE3COLUMNTABLENAME) && (HAVE_SQLITE3COLUMNTABLENAME)
4469 q = (char *) sqlite3_column_table_name(s->s3stmt, i);
4470 strcpy(tblname, q ? q : "");
4471 if (d->trace) {
4472 fprintf(d->trace, "-- table %d name: '%s'\n",
4473 i + 1, tblname);
4474 fflush(d->trace);
4475 }
4476 dyncols[i].table = tblname;
4477 tblname += strlen(tblname) + 1;
4478#endif
4479#if defined(HAVE_SQLITE3COLUMNDATABASENAME) && (HAVE_SQLITE3COLUMNDATABASENAME)
4480 q = (char *) sqlite3_column_database_name(s->s3stmt, i);
4481 strcpy(dbname, q ? q : "");
4482 if (d->trace) {
4483 fprintf(d->trace, "-- database %d name: '%s'\n",
4484 i + 1, dbname);
4485 fflush(d->trace);
4486 }
4487 dyncols[i].db = dbname;
4488 dbname += strlen(dbname) + 1;
4489#else
4490 dyncols[i].db = ((DBC *) (s->dbc))->dbname;
4491#endif
4492 typename = s3stmt_coltype(s->s3stmt, i, d, 0);
4493 strcpy(p, colname);
4494 dyncols[i].label = p;
4495 p += strlen(p) + 1;
4496 q = strchr(colname, '.');
4497 if (q) {
4498 char *q2 = strchr(q + 1, '.');
4499
4500 /* SQLite 3.3.4 produces view.table.column sometimes */
4501 if (q2) {
4502 q = q2;
4503 }
4504 }
4505 if (q) {
4506#if !defined(HAVE_SQLITE3COLUMNTABLENAME) || !(HAVE_SQLITE3COLUMNTABLENAME)
4507 dyncols[i].table = p;
4508#endif
4509 strncpy(p, colname, q - colname);
4510 p[q - colname] = '\0';
4511 p += strlen(p) + 1;
4512 strcpy(p, q + 1);
4513 dyncols[i].column = p;
4514 p += strlen(p) + 1;
4515 } else {
4516#if !defined(HAVE_SQLITE3COLUMNTABLENAME) || !(HAVE_SQLITE3COLUMNTABLENAME)
4517 dyncols[i].table = "";
4518#endif
4519 strcpy(p, colname);
4520 dyncols[i].column = p;
4521 p += strlen(p) + 1;
4522 }
4523 if (s->longnames) {
4524 dyncols[i].column = dyncols[i].label;
4525 }
4526#ifdef SQL_LONGVARCHAR
4527 dyncols[i].type = SQL_LONGVARCHAR;
4528 dyncols[i].size = 65535;
4529#else
4530 dyncols[i].type = SQL_VARCHAR;
4531 dyncols[i].size = 255;
4532#endif
4533 dyncols[i].index = i;
4534 dyncols[i].scale = 0;
4535 dyncols[i].prec = 0;
4536 dyncols[i].nosign = 1;
4537 dyncols[i].autoinc = SQL_FALSE;
4538 dyncols[i].notnull = SQL_NULLABLE;
4539 dyncols[i].ispk = -1;
4540 dyncols[i].isrowid = -1;
4541#ifdef FULL_METADATA
4542 s3stmt_addmeta(s->s3stmt, i, d, &dyncols[i]);
4543#endif
4544 dyncols[i].typename = xstrdup(typename);
4545 }
4546 freedyncols(s);
4547 s->ncols = s->dcols = ncols;
4548 s->dyncols = s->cols = dyncols;
4549 fixupdyncols(s, d);
4550 mkbindcols(s, s->ncols);
4551 d->s3stmt_needmeta = 0;
4552 }
4553 if (ncols <= 0) {
4554 goto killstmt;
4555 }
4556 if (rc == SQLITE_DONE) {
4557 freeresult(s, 0);
4558 s->nrows = 0;
4559 dbtraceapi(d, "sqlite3_finalize", 0);
4560 sqlite3_finalize(s->s3stmt);
4561 s->s3stmt = NULL;
4562 d->cur_s3stmt = NULL;
4563 return SQL_SUCCESS;
4564 }
4565 rowd = xmalloc((1 + 2 * ncols) * sizeof (char *));
4566 if (rowd) {
4567 const unsigned char *value;
4568
4569 rowd[0] = (char *) ((PTRDIFF_T) (ncols * 2));
4570 ++rowd;
4571 for (i = 0; i < ncols; i++) {
4572 int coltype = sqlite3_column_type(s->s3stmt, i);
4573
4574 rowd[i] = rowd[i + ncols] = NULL;
4575 if (coltype == SQLITE_BLOB) {
4576 int k, nbytes = sqlite3_column_bytes(s->s3stmt, i);
4577 char *qp;
4578 unsigned const char *bp;
4579
4580 bp = sqlite3_column_blob(s->s3stmt, i);
4581 qp = xmalloc(nbytes * 2 + 4);
4582 if (qp) {
4583 rowd[i + ncols] = qp;
4584 *qp++ = 'X';
4585 *qp++ = '\'';
4586 for (k = 0; k < nbytes; k++) {
4587 *qp++ = xdigits[(bp[k] >> 4)];
4588 *qp++ = xdigits[(bp[k] & 0xF)];
4589 }
4590 *qp++ = '\'';
4591 *qp = '\0';
4592 }
4593#ifdef _MSC_VER
4594 } else if (coltype == SQLITE_FLOAT) {
4595 struct lconv *lc = 0;
4596 double d = sqlite3_column_double(s->s3stmt, i);
4597 char *p, buffer[128];
4598
4599 /*
4600 * This avoids floating point rounding
4601 * and formatting problems of some SQLite
4602 * versions in conjunction with MSVC 2010.
4603 */
4604 snprintf(buffer, sizeof (buffer), "%.15g", d);
4605 lc = localeconv();
4606 if (lc && lc->decimal_point && lc->decimal_point[0] &&
4607 lc->decimal_point[0] != '.') {
4608 p = strchr(buffer, lc->decimal_point[0]);
4609 if (p) {
4610 *p = '.';
4611 }
4612 }
4613 rowd[i + ncols] = xstrdup(buffer);
4614#endif
4615 } else if (coltype != SQLITE_NULL) {
4616 value = sqlite3_column_text(s->s3stmt, i);
4617 rowd[i + ncols] = xstrdup((char *) value);
4618 }
4619 }
4620 for (i = 0; i < ncols; i++) {
4621 int coltype = sqlite3_column_type(s->s3stmt, i);
4622
4623 value = NULL;
4624 if (coltype == SQLITE_BLOB) {
4625 value = sqlite3_column_blob(s->s3stmt, i);
4626 } else if (coltype != SQLITE_NULL) {
4627 value = sqlite3_column_text(s->s3stmt, i);
4628 }
4629 if (value && !rowd[i + ncols]) {
4630 freerows(rowd);
4631 rowd = 0;
4632 break;
4633 }
4634 }
4635 }
4636 if (rowd) {
4637 freeresult(s, 0);
4638 s->nrows = 1;
4639 s->rows = rowd;
4640 s->rowfree = freerows;
4641 if (rc == SQLITE_DONE) {
4642 dbtraceapi(d, "sqlite3_finalize", 0);
4643 sqlite3_finalize(s->s3stmt);
4644 s->s3stmt = NULL;
4645 d->cur_s3stmt = NULL;
4646 }
4647 return SQL_SUCCESS;
4648 }
4649 }
4650killstmt:
4651 dbtraceapi(d, "sqlite3_reset", 0);
4652 rc = sqlite3_reset(s->s3stmt);
4653 s->s3stmt_noreset = 1;
4654 errp = sqlite3_errmsg(d->sqlite);
4655 if (d->cur_s3stmt == s) {
4656 d->cur_s3stmt = NULL;
4657 }
4658 setstat(s, rc, "%s (%d)", (*s->ov3) ? "HY000" : "S1000",
4659 errp ? errp : "unknown error", rc);
4660 return SQL_ERROR;
4661}
4662
4668static void
4670{
4671 DBC *d;
4672
4673 if (!s || !s->s3stmt) {
4674 return;
4675 }
4676 d = (DBC *) s->dbc;
4677 if (d) {
4678 d->busyint = 0;
4679 }
4680 if (!s->s3stmt_noreset) {
4681 dbtraceapi(d, "sqlite3_reset", 0);
4682 sqlite3_reset(s->s3stmt);
4683 s->s3stmt_noreset = 1;
4684 s->s3stmt_rownum = -1;
4685 }
4686 if (d->cur_s3stmt == s) {
4687 d->cur_s3stmt = NULL;
4688 }
4689}
4690
4696static void
4698{
4699 DBC *d = (DBC *) s->dbc;
4700
4701 if (d) {
4702 d->busyint = 0;
4703 }
4704 if (d && d->cur_s3stmt == s) {
4705 s3stmt_end(s);
4706 }
4707}
4708
4714static void
4716{
4717 if (s->s3stmt) {
4718 DBC *d = (DBC *) s->dbc;
4719
4720 if (d) {
4721 dbtraceapi(d, "sqlite3_finalize", 0);
4722 }
4723 sqlite3_finalize(s->s3stmt);
4724 s->s3stmt = NULL;
4725 s->s3stmt_rownum = 0;
4726 }
4727}
4728
4735static SQLRETURN
4737{
4738 DBC *d = (DBC *) s->dbc;
4739 const char *endp;
4740 sqlite3_stmt *s3stmt = NULL;
4741 int rc, nretry = 0;
4742
4743 d->s3stmt_needmeta = 0;
4744 if (!s->s3stmt) {
4745#if defined(HAVE_SQLITE3PREPAREV2) && (HAVE_SQLITE3PREPAREV2)
4746 dbtraceapi(d, "sqlite3_prepare_v2", (char *) s->query);
4747#else
4748 dbtraceapi(d, "sqlite3_prepare", (char *) s->query);
4749#endif
4750 do {
4751 s3stmt = NULL;
4752#if defined(HAVE_SQLITE3PREPAREV2) && (HAVE_SQLITE3PREPAREV2)
4753 rc = sqlite3_prepare_v2(d->sqlite, (char *) s->query, -1,
4754 &s3stmt, &endp);
4755#else
4756 rc = sqlite3_prepare(d->sqlite, (char *) s->query, -1,
4757 &s3stmt, &endp);
4758#endif
4759 if (rc != SQLITE_OK) {
4760 if (s3stmt) {
4761 sqlite3_finalize(s3stmt);
4762 s3stmt = NULL;
4763 }
4764 }
4765 } while (rc == SQLITE_SCHEMA && (++nretry) < 2);
4766 dbtracerc(d, rc, NULL);
4767 if (rc != SQLITE_OK) {
4768 if (s3stmt) {
4769 dbtraceapi(d, "sqlite3_finalize", NULL);
4770 sqlite3_finalize(s3stmt);
4771 }
4772 setstat(s, rc, "%s (%d)", (*s->ov3) ? "HY000" : "S1000",
4773 sqlite3_errmsg(d->sqlite), rc);
4774 return SQL_ERROR;
4775 }
4776 if (sqlite3_bind_parameter_count(s3stmt) != s->nparams) {
4777 dbtraceapi(d, "sqlite3_finalize", 0);
4778 sqlite3_finalize(s3stmt);
4779 setstat(s, SQLITE_ERROR, "parameter marker count incorrect",
4780 (*s->ov3) ? "HY000" : "S1000");
4781 return SQL_ERROR;
4782 }
4783 s->s3stmt = s3stmt;
4784 s->s3stmt_noreset = 1;
4785 d->s3stmt_needmeta = 1;
4786 }
4787 d->cur_s3stmt = s;
4788 s->s3stmt_rownum = -1;
4789 s3bind(d, s->s3stmt, s->nparams, s->bindparms);
4790 return SQL_SUCCESS;
4791}
4792
4793#ifndef WINTERFACE
4798SQLRETURN SQL_API
4799SQLDataSources(SQLHENV env, SQLUSMALLINT dir, SQLCHAR *srvname,
4800 SQLSMALLINT buflen1, SQLSMALLINT *lenp1,
4801 SQLCHAR *desc, SQLSMALLINT buflen2, SQLSMALLINT *lenp2)
4802{
4803 if (env == SQL_NULL_HENV) {
4804 return SQL_INVALID_HANDLE;
4805 }
4806 return SQL_ERROR;
4807}
4808#endif
4809
4810#ifdef WINTERFACE
4815SQLRETURN SQL_API
4816SQLDataSourcesW(SQLHENV env, SQLUSMALLINT dir, SQLWCHAR *srvname,
4817 SQLSMALLINT buflen1, SQLSMALLINT *lenp1,
4818 SQLWCHAR *desc, SQLSMALLINT buflen2, SQLSMALLINT *lenp2)
4819{
4820 if (env == SQL_NULL_HENV) {
4821 return SQL_INVALID_HANDLE;
4822 }
4823 return SQL_ERROR;
4824}
4825#endif
4826
4827#ifndef WINTERFACE
4832SQLRETURN SQL_API
4833SQLDrivers(SQLHENV env, SQLUSMALLINT dir, SQLCHAR *drvdesc,
4834 SQLSMALLINT descmax, SQLSMALLINT *desclenp,
4835 SQLCHAR *drvattr, SQLSMALLINT attrmax, SQLSMALLINT *attrlenp)
4836{
4837 if (env == SQL_NULL_HENV) {
4838 return SQL_INVALID_HANDLE;
4839 }
4840 return SQL_ERROR;
4841}
4842#endif
4843
4844#ifdef WINTERFACE
4849SQLRETURN SQL_API
4850SQLDriversW(SQLHENV env, SQLUSMALLINT dir, SQLWCHAR *drvdesc,
4851 SQLSMALLINT descmax, SQLSMALLINT *desclenp,
4852 SQLWCHAR *drvattr, SQLSMALLINT attrmax, SQLSMALLINT *attrlenp)
4853{
4854 if (env == SQL_NULL_HENV) {
4855 return SQL_INVALID_HANDLE;
4856 }
4857 return SQL_ERROR;
4858}
4859#endif
4860
4861#ifndef WINTERFACE
4866SQLRETURN SQL_API
4867SQLBrowseConnect(SQLHDBC dbc, SQLCHAR *connin, SQLSMALLINT conninLen,
4868 SQLCHAR *connout, SQLSMALLINT connoutMax,
4869 SQLSMALLINT *connoutLen)
4870{
4871 SQLRETURN ret;
4872
4873 HDBC_LOCK(dbc);
4874 ret = drvunimpldbc(dbc);
4876 return ret;
4877}
4878#endif
4879
4880#ifdef WINTERFACE
4885SQLRETURN SQL_API
4886SQLBrowseConnectW(SQLHDBC dbc, SQLWCHAR *connin, SQLSMALLINT conninLen,
4887 SQLWCHAR *connout, SQLSMALLINT connoutMax,
4888 SQLSMALLINT *connoutLen)
4889{
4890 SQLRETURN ret;
4891
4892 HDBC_LOCK(dbc);
4893 ret = drvunimpldbc(dbc);
4895 return ret;
4896}
4897#endif
4898
4907static SQLRETURN
4908drvputdata(SQLHSTMT stmt, SQLPOINTER data, SQLLEN len)
4909{
4910 STMT *s;
4911 int i, dlen, done = 0;
4912 BINDPARM *p;
4913
4914 if (stmt == SQL_NULL_HSTMT) {
4915 return SQL_INVALID_HANDLE;
4916 }
4917 s = (STMT *) stmt;
4918 if (!s->query || s->nparams <= 0) {
4919seqerr:
4920 setstat(s, -1, "sequence error", "HY010");
4921 return SQL_ERROR;
4922 }
4923 for (i = (s->pdcount < 0) ? 0 : s->pdcount; i < s->nparams; i++) {
4924 p = &s->bindparms[i];
4925 if (p->need > 0) {
4926 int type = mapdeftype(p->type, p->stype, -1, s->nowchar[0]);
4927
4928 if (len == SQL_NULL_DATA) {
4929 freep(&p->parbuf);
4930 p->param = NULL;
4931 p->len = SQL_NULL_DATA;
4932 p->need = -1;
4933 } else if (type != SQL_C_CHAR
4934#ifdef WCHARSUPPORT
4935 && type != SQL_C_WCHAR
4936#endif
4937 && type != SQL_C_BINARY) {
4938 int size = 0;
4939
4940 switch (type) {
4941 case SQL_C_TINYINT:
4942 case SQL_C_UTINYINT:
4943 case SQL_C_STINYINT:
4944#ifdef SQL_BIT
4945 case SQL_C_BIT:
4946#endif
4947 size = sizeof (SQLCHAR);
4948 break;
4949 case SQL_C_SHORT:
4950 case SQL_C_USHORT:
4951 case SQL_C_SSHORT:
4952 size = sizeof (SQLSMALLINT);
4953 break;
4954 case SQL_C_LONG:
4955 case SQL_C_ULONG:
4956 case SQL_C_SLONG:
4957 size = sizeof (SQLINTEGER);
4958 break;
4959#ifdef SQL_BIGINT
4960 case SQL_C_UBIGINT:
4961 case SQL_C_SBIGINT:
4962 size = sizeof (SQLBIGINT);
4963 break;
4964#endif
4965 case SQL_C_FLOAT:
4966 size = sizeof (float);
4967 break;
4968 case SQL_C_DOUBLE:
4969 size = sizeof (double);
4970 break;
4971#ifdef SQL_C_TYPE_DATE
4972 case SQL_C_TYPE_DATE:
4973#endif
4974 case SQL_C_DATE:
4975 size = sizeof (DATE_STRUCT);
4976 break;
4977#ifdef SQL_C_TYPE_DATE
4978 case SQL_C_TYPE_TIME:
4979#endif
4980 case SQL_C_TIME:
4981 size = sizeof (TIME_STRUCT);
4982 break;
4983#ifdef SQL_C_TYPE_DATE
4984 case SQL_C_TYPE_TIMESTAMP:
4985#endif
4986 case SQL_C_TIMESTAMP:
4987 size = sizeof (TIMESTAMP_STRUCT);
4988 break;
4989 }
4990 freep(&p->parbuf);
4991 p->parbuf = xmalloc(size);
4992 if (!p->parbuf) {
4993 return nomem(s);
4994 }
4995 p->param = p->parbuf;
4996 memcpy(p->param, data, size);
4997 p->len = size;
4998 p->need = -1;
4999 } else if (len == SQL_NTS && (
5000 type == SQL_C_CHAR
5001#ifdef WCHARSUPPORT
5002 || type == SQL_C_WCHAR
5003#endif
5004 )) {
5005 char *dp = data;
5006
5007#ifdef WCHARSUPPORT
5008 if (type == SQL_C_WCHAR) {
5009 dp = uc_to_utf(data, len);
5010 if (!dp) {
5011 return nomem(s);
5012 }
5013 }
5014#endif
5015#if defined(_WIN32) || defined(_WIN64)
5016 if (*s->oemcp) {
5017 dp = wmb_to_utf(data, strlen (data));
5018 if (!dp) {
5019 return nomem(s);
5020 }
5021 }
5022#endif
5023 dlen = strlen(dp);
5024 freep(&p->parbuf);
5025 p->parbuf = xmalloc(dlen + 1);
5026 if (!p->parbuf) {
5027 if (dp != data) {
5028 uc_free(dp);
5029 }
5030 return nomem(s);
5031 }
5032 p->param = p->parbuf;
5033 strcpy(p->param, dp);
5034 if (dp != data) {
5035 uc_free(dp);
5036 }
5037 p->len = dlen;
5038 p->need = -1;
5039 } else if (len < 0) {
5040 setstat(s, -1, "invalid length", "HY090");
5041 return SQL_ERROR;
5042 } else {
5043 dlen = min(p->len - p->offs, len);
5044 if (!p->param) {
5045 setstat(s, -1, "no memory for parameter", "HY013");
5046 return SQL_ERROR;
5047 }
5048 memcpy((char *) p->param + p->offs, data, dlen);
5049 p->offs += dlen;
5050 if (p->offs >= p->len) {
5051#ifdef WCHARSUPPORT
5052 if (type == SQL_C_WCHAR) {
5053 char *dp = uc_to_utf(p->param, p->len);
5054 char *np;
5055 int nlen;
5056
5057 if (!dp) {
5058 return nomem(s);
5059 }
5060 nlen = strlen(dp);
5061 np = xmalloc(nlen + 1);
5062 if (!np) {
5063 uc_free(dp);
5064 return nomem(s);
5065 }
5066 strcpy(np, dp);
5067 uc_free(dp);
5068 if (p->param == p->parbuf) {
5069 freep(&p->parbuf);
5070 }
5071 p->parbuf = p->param = np;
5072 p->len = nlen;
5073 } else {
5074 *((char *) p->param + p->len) = '\0';
5075 }
5076 p->need = (type == SQL_C_CHAR || type == SQL_C_WCHAR)
5077 ? -1 : 0;
5078#else
5079 *((char *) p->param + p->len) = '\0';
5080 p->need = (type == SQL_C_CHAR) ? -1 : 0;
5081#endif
5082#if defined(_WIN32) || defined(_WIN64)
5083 if (type == SQL_C_CHAR && *s->oemcp &&
5084 !(p->stype == SQL_BINARY ||
5085 p->stype == SQL_VARBINARY ||
5086 p->stype == SQL_LONGVARBINARY)) {
5087 char *dp = wmb_to_utf(p->param, p->len);
5088
5089 if (!dp) {
5090 return nomem(s);
5091 }
5092 if (p->param == p->parbuf) {
5093 freep(&p->parbuf);
5094 }
5095 p->parbuf = p->param = dp;
5096 p->len = strlen(dp);
5097 }
5098 if (p->type == SQL_C_WCHAR &&
5099 (p->stype == SQL_VARCHAR ||
5100 p->stype == SQL_LONGVARCHAR) &&
5101 p->len == p->coldef * sizeof (SQLWCHAR)) {
5102 /* fix for MS-Access */
5103 p->len = p->coldef;
5104 }
5105#endif
5106 }
5107 }
5108 done = 1;
5109 break;
5110 }
5111 }
5112 if (!done) {
5113 goto seqerr;
5114 }
5115 return SQL_SUCCESS;
5116}
5117
5126SQLRETURN SQL_API
5127SQLPutData(SQLHSTMT stmt, SQLPOINTER data, SQLLEN len)
5128{
5129 SQLRETURN ret;
5130
5132 ret = drvputdata(stmt, data, len);
5134 return ret;
5135}
5136
5142static SQLRETURN
5144{
5145 if (s->bindparms) {
5146 int n;
5147
5148 for (n = 0; n < s->nbindparms; n++) {
5149 freep(&s->bindparms[n].parbuf);
5150 memset(&s->bindparms[n], 0, sizeof (BINDPARM));
5151 }
5152 }
5153 return SQL_SUCCESS;
5154}
5155
5167static SQLRETURN
5168setupparam(STMT *s, char *sql, int pnum)
5169{
5170 int type, len = 0, needalloc = 0;
5171 BINDPARM *p;
5172
5173 if (!s->bindparms || pnum < 0 || pnum >= s->nbindparms) {
5174 goto error;
5175 }
5176 p = &s->bindparms[pnum];
5177 type = mapdeftype(p->type, p->stype, -1, s->nowchar[0]);
5178#if (defined(_WIN32) || defined(_WIN64)) && defined(WINTERFACE)
5179 /* MS Access hack part 4 (map SQL_C_DEFAULT to SQL_C_CHAR) */
5180 if (type == SQL_C_WCHAR && p->type == SQL_C_DEFAULT) {
5181 type = SQL_C_CHAR;
5182 }
5183#endif
5184 if (p->need > 0) {
5185 return setupparbuf(s, p);
5186 }
5187 p->strbuf[0] = '\0';
5188 if (!p->param || (p->lenp && *p->lenp == SQL_NULL_DATA)) {
5189 p->s3type = SQLITE_NULL;
5190 p->s3size = 0;
5191 return SQL_SUCCESS;
5192 }
5193 if (type == SQL_C_CHAR &&
5194 (p->stype == SQL_BINARY ||
5195 p->stype == SQL_VARBINARY ||
5196 p->stype == SQL_LONGVARBINARY)) {
5197 type = SQL_C_BINARY;
5198 }
5199 switch (type) {
5200 case SQL_C_BINARY:
5201 p->s3type = SQLITE_BLOB;
5202 p->s3val = p->param;
5203 if (!p->lenp) {
5204 len = p->len;
5205 } else if (*p->lenp == SQL_DATA_AT_EXEC) {
5206 len = p->len;
5207 } else {
5208 len = *p->lenp;
5209 if (len <= SQL_LEN_DATA_AT_EXEC_OFFSET) {
5210 len = SQL_LEN_DATA_AT_EXEC(len);
5211 }
5212 }
5213 if (len < 0) {
5214 setstat(s, -1, "invalid length", "HY009");
5215 return SQL_ERROR;
5216 }
5217 p->len = len;
5218 p->max = p->len;
5219 p->s3size = len;
5220 break;
5221#ifdef WCHARSUPPORT
5222 case SQL_C_WCHAR:
5223#endif
5224 case SQL_C_CHAR:
5225 p->s3type = SQLITE_TEXT;
5226 p->s3size = -1;
5227 p->s3val = p->param;
5228 if (!p->parbuf) {
5229#ifdef WCHARSUPPORT
5230 if (type == SQL_C_WCHAR) {
5231 if (!p->lenp || *p->lenp == SQL_NTS) {
5232 p->max = uc_strlen(p->param) * sizeof (SQLWCHAR);
5233 } else if (*p->lenp >= 0) {
5234 p->max = *p->lenp;
5235 }
5236 } else
5237#endif
5238 if (type == SQL_C_CHAR) {
5239 if (!p->lenp || *p->lenp == SQL_NTS) {
5240 p->len = p->max = strlen(p->param);
5241#if defined(_WIN32) || defined(_WIN64)
5242 needalloc = 1;
5243#endif
5244 } else if (*p->lenp >= 0) {
5245 p->len = p->max = *p->lenp;
5246 needalloc = 1;
5247 }
5248 }
5249 }
5250 if (p->need < 0 && p->parbuf == p->param) {
5251 break;
5252 }
5253#ifdef WCHARSUPPORT
5254 if (type == SQL_C_WCHAR) {
5255 char *dp = uc_to_utf(p->param, p->max);
5256
5257 if (!dp) {
5258 return nomem(s);
5259 }
5260 if (p->param == p->parbuf) {
5261 freep(&p->parbuf);
5262 }
5263 p->parbuf = p->param = dp;
5264 p->need = -1;
5265 p->len = strlen(p->param);
5266 p->s3val = p->param;
5267 p->s3size = p->len;
5268 } else
5269#endif
5270 if (type == SQL_C_CHAR) {
5271 p->s3val = p->param;
5272 if (needalloc) {
5273 char *dp;
5274
5275#if defined(_WIN32) || defined(_WIN64)
5276 if (*s->oemcp) {
5277 dp = wmb_to_utf(p->param, p->len);
5278 } else {
5279 dp = xmalloc(p->len + 1);
5280 }
5281#else
5282 dp = xmalloc(p->len + 1);
5283#endif
5284 if (!dp) {
5285 return nomem(s);
5286 }
5287#if defined(_WIN32) || defined(_WIN64)
5288 if (*s->oemcp) {
5289 p->len = strlen(dp);
5290 } else {
5291 memcpy(dp, p->param, p->len);
5292 dp[p->len] = '\0';
5293 }
5294#else
5295 memcpy(dp, p->param, p->len);
5296 dp[p->len] = '\0';
5297#endif
5298 if (p->param == p->parbuf) {
5299 freep(&p->parbuf);
5300 }
5301 p->parbuf = p->param = dp;
5302 p->need = -1;
5303 p->s3val = p->param;
5304 p->s3size = p->len;
5305 }
5306 }
5307 break;
5308 case SQL_C_UTINYINT:
5309 case SQL_C_TINYINT:
5310 case SQL_C_STINYINT:
5311 p->s3type = SQLITE_INTEGER;
5312 p->s3size = sizeof (int);
5313 p->s3ival = *((SQLCHAR *) p->param);
5314 break;
5315 case SQL_C_USHORT:
5316 p->s3type = SQLITE_INTEGER;
5317 p->s3size = sizeof (int);
5318 p->s3ival = *((SQLUSMALLINT *) p->param);
5319 break;
5320 case SQL_C_SHORT:
5321 case SQL_C_SSHORT:
5322 p->s3type = SQLITE_INTEGER;
5323 p->s3size = sizeof (int);
5324 p->s3ival = *((SQLSMALLINT *) p->param);
5325 break;
5326 case SQL_C_ULONG:
5327 p->s3type = SQLITE_INTEGER;
5328 p->s3size = sizeof (int);
5329 p->s3ival = *((SQLUINTEGER *) p->param);
5330 break;
5331 case SQL_C_LONG:
5332 case SQL_C_SLONG:
5333 p->s3type = SQLITE_INTEGER;
5334 p->s3size = sizeof (int);
5335 p->s3ival = *((SQLINTEGER *) p->param);
5336 break;
5337#ifdef SQL_BIT
5338 case SQL_C_BIT:
5339 p->s3type = SQLITE_INTEGER;
5340 p->s3size = sizeof (int);
5341 p->s3ival = (*((SQLCHAR *) p->param)) ? 1 : 0;
5342 break;
5343#endif
5344#ifdef SQL_BIGINT
5345 case SQL_C_SBIGINT:
5346 p->s3type = SQLITE_INTEGER;
5347 p->s3size = sizeof (sqlite_int64);
5348 p->s3lival = *((sqlite_int64 *) p->param);
5349 break;
5350 case SQL_C_UBIGINT:
5351 p->s3type = SQLITE_INTEGER;
5352 p->s3size = sizeof (sqlite_int64);
5353 p->s3lival = *((sqlite_uint64 *) p->param);
5354 break;
5355#endif
5356 case SQL_C_FLOAT:
5357 p->s3type = SQLITE_FLOAT;
5358 p->s3size = sizeof (double);
5359 p->s3dval = *((float *) p->param);
5360 break;
5361 case SQL_C_DOUBLE:
5362 p->s3type = SQLITE_FLOAT;
5363 p->s3size = sizeof (double);
5364 p->s3dval = *((double *) p->param);
5365 break;
5366#ifdef SQL_C_TYPE_DATE
5367 case SQL_C_TYPE_DATE:
5368#endif
5369 case SQL_C_DATE:
5370 if (*s->jdconv) {
5371 int a, b, x1, x2, y, m, d;
5372
5373 p->s3type = SQLITE_FLOAT;
5374 p->s3size = sizeof (double);
5375 y = ((DATE_STRUCT *) p->param)->year;
5376 m = ((DATE_STRUCT *) p->param)->month;
5377 d = ((DATE_STRUCT *) p->param)->day;
5378 if (m <= 2) {
5379 y--;
5380 m += 12;
5381 }
5382 a = y / 100;
5383 b = 2 - a + (a / 4);
5384 x1 = 36525 * (y + 4716) / 100;
5385 x2 = 306001 * (m + 1) / 10000;
5386 p->s3dval = x1 + x2 + d + b - 1524.5;
5387 break;
5388 }
5389 sprintf(p->strbuf, "%04d-%02d-%02d",
5390 ((DATE_STRUCT *) p->param)->year,
5391 ((DATE_STRUCT *) p->param)->month,
5392 ((DATE_STRUCT *) p->param)->day);
5393 p->s3type = SQLITE_TEXT;
5394 p->s3size = -1;
5395 p->s3val = p->strbuf;
5396 break;
5397#ifdef SQL_C_TYPE_TIME
5398 case SQL_C_TYPE_TIME:
5399#endif
5400 case SQL_C_TIME:
5401 if (*s->jdconv) {
5402 p->s3type = SQLITE_FLOAT;
5403 p->s3size = sizeof (double);
5404 p->s3dval = 2451544.5 +
5405 (((TIME_STRUCT *) p->param)->hour * 3600000.0 +
5406 ((TIME_STRUCT *) p->param)->minute * 60000.0 +
5407 ((TIME_STRUCT *) p->param)->second * 1000.0) / 86400000.0;
5408 break;
5409 }
5410 sprintf(p->strbuf, "%02d:%02d:%02d",
5411 ((TIME_STRUCT *) p->param)->hour,
5412 ((TIME_STRUCT *) p->param)->minute,
5413 ((TIME_STRUCT *) p->param)->second);
5414 p->s3type = SQLITE_TEXT;
5415 p->s3size = -1;
5416 p->s3val = p->strbuf;
5417 break;
5418#ifdef SQL_C_TYPE_TIMESTAMP
5419 case SQL_C_TYPE_TIMESTAMP:
5420#endif
5421 case SQL_C_TIMESTAMP:
5422 if (*s->jdconv) {
5423 int a, b, x1, x2, y, m, d;
5424
5425 p->s3type = SQLITE_FLOAT;
5426 p->s3size = sizeof (double);
5427 y = ((TIMESTAMP_STRUCT *) p->param)->year;
5428 m = ((TIMESTAMP_STRUCT *) p->param)->month;
5429 d = ((TIMESTAMP_STRUCT *) p->param)->day;
5430 if (m <= 2) {
5431 y--;
5432 m += 12;
5433 }
5434 a = y / 100;
5435 b = 2 - a + (a / 4);
5436 x1 = 36525 * (y + 4716) / 100;
5437 x2 = 306001 * (m + 1) / 10000;
5438 p->s3dval = x1 + x2 + d + b - 1524.5 +
5439 (((TIMESTAMP_STRUCT *) p->param)->hour * 3600000.0 +
5440 ((TIMESTAMP_STRUCT *) p->param)->minute * 60000.0 +
5441 ((TIMESTAMP_STRUCT *) p->param)->second * 1000.0 +
5442 ((TIMESTAMP_STRUCT *) p->param)->fraction / 1.0E6)
5443 / 86400000.0;
5444 break;
5445 }
5446 len = (int) ((TIMESTAMP_STRUCT *) p->param)->fraction;
5447 len /= 1000000;
5448 len = len % 1000;
5449 if (len < 0) {
5450 len = 0;
5451 }
5452 if (p->coldef && p->coldef <= 16) {
5453 sprintf(p->strbuf, "%04d-%02d-%02d %02d:%02d:00.000",
5454 ((TIMESTAMP_STRUCT *) p->param)->year,
5455 ((TIMESTAMP_STRUCT *) p->param)->month,
5456 ((TIMESTAMP_STRUCT *) p->param)->day,
5457 ((TIMESTAMP_STRUCT *) p->param)->hour,
5458 ((TIMESTAMP_STRUCT *) p->param)->minute);
5459 } else if (p->coldef && p->coldef <= 19) {
5460 sprintf(p->strbuf, "%04d-%02d-%02d %02d:%02d:%02d.000",
5461 ((TIMESTAMP_STRUCT *) p->param)->year,
5462 ((TIMESTAMP_STRUCT *) p->param)->month,
5463 ((TIMESTAMP_STRUCT *) p->param)->day,
5464 ((TIMESTAMP_STRUCT *) p->param)->hour,
5465 ((TIMESTAMP_STRUCT *) p->param)->minute,
5466 ((TIMESTAMP_STRUCT *) p->param)->second);
5467 } else {
5468 sprintf(p->strbuf, "%04d-%02d-%02d %02d:%02d:%02d.%03d",
5469 ((TIMESTAMP_STRUCT *) p->param)->year,
5470 ((TIMESTAMP_STRUCT *) p->param)->month,
5471 ((TIMESTAMP_STRUCT *) p->param)->day,
5472 ((TIMESTAMP_STRUCT *) p->param)->hour,
5473 ((TIMESTAMP_STRUCT *) p->param)->minute,
5474 ((TIMESTAMP_STRUCT *) p->param)->second,
5475 len);
5476 }
5477 p->s3type = SQLITE_TEXT;
5478 p->s3size = -1;
5479 p->s3val = p->strbuf;
5480 break;
5481 default:
5482 error:
5483 setstat(s, -1, "unsupported parameter type",
5484 (*s->ov3) ? "07009" : "S1093");
5485 return SQL_ERROR;
5486 }
5487 return SQL_SUCCESS;
5488}
5489
5505static SQLRETURN
5506drvbindparam(SQLHSTMT stmt, SQLUSMALLINT pnum, SQLSMALLINT iotype,
5507 SQLSMALLINT buftype, SQLSMALLINT ptype, SQLUINTEGER coldef,
5508 SQLSMALLINT scale,
5509 SQLPOINTER data, SQLINTEGER buflen, SQLLEN *len)
5510{
5511 STMT *s;
5512 BINDPARM *p;
5513
5514 if (stmt == SQL_NULL_HSTMT) {
5515 return SQL_INVALID_HANDLE;
5516 }
5517 s = (STMT *) stmt;
5518 if (pnum == 0) {
5519 setstat(s, -1, "invalid parameter", (*s->ov3) ? "07009" : "S1093");
5520 return SQL_ERROR;
5521 }
5522 if (!data && !len) {
5523 setstat(s, -1, "invalid buffer", "HY003");
5524 return SQL_ERROR;
5525 }
5526 --pnum;
5527 if (s->bindparms) {
5528 if (pnum >= s->nbindparms) {
5529 BINDPARM *newparms;
5530
5531 newparms = xrealloc(s->bindparms,
5532 (pnum + 1) * sizeof (BINDPARM));
5533 if (!newparms) {
5534outofmem:
5535 return nomem(s);
5536 }
5537 s->bindparms = newparms;
5538 memset(&s->bindparms[s->nbindparms], 0,
5539 (pnum + 1 - s->nbindparms) * sizeof (BINDPARM));
5540 s->nbindparms = pnum + 1;
5541 }
5542 } else {
5543 int npar = max(10, pnum + 1);
5544
5545 s->bindparms = xmalloc(npar * sizeof (BINDPARM));
5546 if (!s->bindparms) {
5547 goto outofmem;
5548 }
5549 memset(s->bindparms, 0, npar * sizeof (BINDPARM));
5550 s->nbindparms = npar;
5551 }
5552 switch (buftype) {
5553 case SQL_C_STINYINT:
5554 case SQL_C_UTINYINT:
5555 case SQL_C_TINYINT:
5556#ifdef SQL_C_BIT
5557 case SQL_C_BIT:
5558#endif
5559 buflen = sizeof (SQLCHAR);
5560 break;
5561 case SQL_C_SHORT:
5562 case SQL_C_USHORT:
5563 case SQL_C_SSHORT:
5564 buflen = sizeof (SQLSMALLINT);
5565 break;
5566 case SQL_C_SLONG:
5567 case SQL_C_ULONG:
5568 case SQL_C_LONG:
5569 buflen = sizeof (SQLINTEGER);
5570 break;
5571 case SQL_C_FLOAT:
5572 buflen = sizeof (float);
5573 break;
5574 case SQL_C_DOUBLE:
5575 buflen = sizeof (double);
5576 break;
5577 case SQL_C_TIMESTAMP:
5578#ifdef SQL_C_TYPE_TIMESTAMP
5579 case SQL_C_TYPE_TIMESTAMP:
5580#endif
5581 buflen = sizeof (TIMESTAMP_STRUCT);
5582 break;
5583 case SQL_C_TIME:
5584#ifdef SQL_C_TYPE_TIME
5585 case SQL_C_TYPE_TIME:
5586#endif
5587 buflen = sizeof (TIME_STRUCT);
5588 break;
5589 case SQL_C_DATE:
5590#ifdef SQL_C_TYPE_DATE
5591 case SQL_C_TYPE_DATE:
5592#endif
5593 buflen = sizeof (DATE_STRUCT);
5594 break;
5595#ifdef SQL_C_UBIGINT
5596 case SQL_C_UBIGINT:
5597 buflen = sizeof (SQLBIGINT);
5598 break;
5599#endif
5600#ifdef SQL_C_SBIGINT
5601 case SQL_C_SBIGINT:
5602 buflen = sizeof (SQLBIGINT);
5603 break;
5604#endif
5605#ifdef SQL_C_BIGINT
5606 case SQL_C_BIGINT:
5607 buflen = sizeof (SQLBIGINT);
5608 break;
5609#endif
5610 }
5611 p = &s->bindparms[pnum];
5612 p->type = buftype;
5613 p->stype = ptype;
5614 p->coldef = coldef;
5615 p->scale = scale;
5616 p->max = buflen;
5617 p->inc = buflen;
5618 p->lenp = p->lenp0 = len;
5619 p->offs = 0;
5620 p->len = 0;
5621 p->param0 = data;
5622 freep(&p->parbuf);
5623 p->param = p->param0;
5624 p->bound = 1;
5625 p->need = 0;
5626 return SQL_SUCCESS;
5627}
5628
5644SQLRETURN SQL_API
5645SQLBindParameter(SQLHSTMT stmt, SQLUSMALLINT pnum, SQLSMALLINT iotype,
5646 SQLSMALLINT buftype, SQLSMALLINT ptype, SQLULEN coldef,
5647 SQLSMALLINT scale,
5648 SQLPOINTER data, SQLLEN buflen, SQLLEN *len)
5649{
5650 SQLRETURN ret;
5651
5653 ret = drvbindparam(stmt, pnum, iotype, buftype, ptype, coldef,
5654 scale, data, buflen, len);
5656 return ret;
5657}
5658
5659#ifndef HAVE_IODBC
5673SQLRETURN SQL_API
5674SQLBindParam(SQLHSTMT stmt, SQLUSMALLINT pnum, SQLSMALLINT vtype,
5675 SQLSMALLINT ptype, SQLULEN lenprec,
5676 SQLSMALLINT scale, SQLPOINTER val,
5677 SQLLEN *lenp)
5678{
5679 SQLRETURN ret;
5680
5682 ret = drvbindparam(stmt, pnum, SQL_PARAM_INPUT, vtype, ptype,
5683 lenprec, scale, val, 0, lenp);
5685 return ret;
5686}
5687#endif
5688
5696SQLRETURN SQL_API
5697SQLNumParams(SQLHSTMT stmt, SQLSMALLINT *nparam)
5698{
5699 STMT *s;
5700 SQLSMALLINT dummy;
5701
5703 if (stmt == SQL_NULL_HSTMT) {
5704 return SQL_INVALID_HANDLE;
5705 }
5706 s = (STMT *) stmt;
5707 if (!nparam) {
5708 nparam = &dummy;
5709 }
5710 *nparam = s->nparams;
5712 return SQL_SUCCESS;
5713}
5714
5722static SQLRETURN
5724{
5725 if (!p->parbuf) {
5726 if (*p->lenp == SQL_DATA_AT_EXEC) {
5727 p->len = p->max;
5728 } else {
5729 p->len = SQL_LEN_DATA_AT_EXEC(*p->lenp);
5730 }
5731 if (p->len < 0 && p->len != SQL_NTS &&
5732 p->len != SQL_NULL_DATA) {
5733 setstat(s, -1, "invalid length", "HY009");
5734 return SQL_ERROR;
5735 }
5736 if (p->len >= 0) {
5737 p->parbuf = xmalloc(p->len + 2);
5738 if (!p->parbuf) {
5739 return nomem(s);
5740 }
5741 p->param = p->parbuf;
5742 } else {
5743 p->param = NULL;
5744 }
5745 }
5746 return SQL_NEED_DATA;
5747}
5748
5756SQLRETURN SQL_API
5757SQLParamData(SQLHSTMT stmt, SQLPOINTER *pind)
5758{
5759 STMT *s;
5760 int i;
5761 SQLPOINTER dummy;
5762 SQLRETURN ret;
5763 BINDPARM *p;
5764
5766 if (stmt == SQL_NULL_HSTMT) {
5767 return SQL_INVALID_HANDLE;
5768 }
5769 s = (STMT *) stmt;
5770 if (!pind) {
5771 pind = &dummy;
5772 }
5773 if (s->pdcount < s->nparams) {
5774 s->pdcount++;
5775 }
5776 for (i = 0; i < s->pdcount; i++) {
5777 p = &s->bindparms[i];
5778 if (p->need > 0) {
5779 int type = mapdeftype(p->type, p->stype, -1, s->nowchar[0]);
5780
5781 p->need = (type == SQL_C_CHAR || type == SQL_C_WCHAR) ? -1 : 0;
5782 }
5783 }
5784 for (; i < s->nparams; i++) {
5785 p = &s->bindparms[i];
5786 if (p->need > 0) {
5787 *pind = (SQLPOINTER) p->param0;
5788 ret = setupparbuf(s, p);
5789 s->pdcount = i;
5790 goto done;
5791 }
5792 }
5793 ret = drvexecute(stmt, 0);
5794done:
5796 return ret;
5797}
5798
5810SQLRETURN SQL_API
5811SQLDescribeParam(SQLHSTMT stmt, SQLUSMALLINT pnum, SQLSMALLINT *dtype,
5812 SQLULEN *size, SQLSMALLINT *decdigits, SQLSMALLINT *nullable)
5813{
5814 STMT *s;
5815 SQLRETURN ret = SQL_ERROR;
5816
5818 if (stmt == SQL_NULL_HSTMT) {
5819 return SQL_INVALID_HANDLE;
5820 }
5821 s = (STMT *) stmt;
5822 --pnum;
5823 if (pnum >= s->nparams) {
5824 setstat(s, -1, "invalid parameter index",
5825 (*s->ov3) ? "HY000" : "S1000");
5826 goto done;
5827 }
5828 if (dtype) {
5829#ifdef SQL_LONGVARCHAR
5830#ifdef WINTERFACE
5831 *dtype = s->nowchar[0] ? SQL_LONGVARCHAR : SQL_WLONGVARCHAR;
5832#else
5833 *dtype = SQL_LONGVARCHAR;
5834#endif
5835#else
5836#ifdef WINTERFACE
5837 *dtype = s->nowchar[0] ? SQL_VARCHAR : SQL_WVARCHAR;
5838#else
5839 *dtype = SQL_VARCHAR;
5840#endif
5841#endif
5842 }
5843 if (size) {
5844#ifdef SQL_LONGVARCHAR
5845 *size = 65536;
5846#else
5847 *size = 255;
5848#endif
5849 }
5850 if (decdigits) {
5851 *decdigits = 0;
5852 }
5853 if (nullable) {
5854 *nullable = SQL_NULLABLE;
5855 }
5856 ret = SQL_SUCCESS;
5857done:
5859 return ret;
5860}
5861
5875SQLRETURN SQL_API
5876SQLSetParam(SQLHSTMT stmt, SQLUSMALLINT par, SQLSMALLINT type,
5877 SQLSMALLINT sqltype, SQLULEN coldef,
5878 SQLSMALLINT scale, SQLPOINTER val, SQLLEN *nval)
5879{
5880 SQLRETURN ret;
5881
5883 ret = drvbindparam(stmt, par, SQL_PARAM_INPUT,
5884 type, sqltype, coldef, scale, val,
5885 SQL_SETPARAM_VALUE_MAX, nval);
5887 return ret;
5888}
5889
5894SQLRETURN SQL_API
5895SQLParamOptions(SQLHSTMT stmt, SQLULEN rows, SQLULEN *rowp)
5896{
5897 SQLRETURN ret;
5898
5900 ret = drvunimplstmt(stmt);
5902 return ret;
5903}
5904
5905#ifndef WINTERFACE
5910SQLRETURN SQL_API
5911SQLGetDescField(SQLHDESC handle, SQLSMALLINT recno,
5912 SQLSMALLINT fieldid, SQLPOINTER value,
5913 SQLINTEGER buflen, SQLINTEGER *strlen)
5914{
5915 return SQL_ERROR;
5916}
5917#endif
5918
5919#ifdef WINTERFACE
5924SQLRETURN SQL_API
5925SQLGetDescFieldW(SQLHDESC handle, SQLSMALLINT recno,
5926 SQLSMALLINT fieldid, SQLPOINTER value,
5927 SQLINTEGER buflen, SQLINTEGER *strlen)
5928{
5929 return SQL_ERROR;
5930}
5931#endif
5932
5933#ifndef WINTERFACE
5938SQLRETURN SQL_API
5939SQLSetDescField(SQLHDESC handle, SQLSMALLINT recno,
5940 SQLSMALLINT fieldid, SQLPOINTER value,
5941 SQLINTEGER buflen)
5942{
5943 return SQL_ERROR;
5944}
5945#endif
5946
5947#ifdef WINTERFACE
5952SQLRETURN SQL_API
5953SQLSetDescFieldW(SQLHDESC handle, SQLSMALLINT recno,
5954 SQLSMALLINT fieldid, SQLPOINTER value,
5955 SQLINTEGER buflen)
5956{
5957 return SQL_ERROR;
5958}
5959#endif
5960
5961#ifndef WINTERFACE
5966SQLRETURN SQL_API
5967SQLGetDescRec(SQLHDESC handle, SQLSMALLINT recno,
5968 SQLCHAR *name, SQLSMALLINT buflen,
5969 SQLSMALLINT *strlen, SQLSMALLINT *type,
5970 SQLSMALLINT *subtype, SQLLEN *len,
5971 SQLSMALLINT *prec, SQLSMALLINT *scale,
5972 SQLSMALLINT *nullable)
5973{
5974 return SQL_ERROR;
5975}
5976#endif
5977
5978#ifdef WINTERFACE
5983SQLRETURN SQL_API
5984SQLGetDescRecW(SQLHDESC handle, SQLSMALLINT recno,
5985 SQLWCHAR *name, SQLSMALLINT buflen,
5986 SQLSMALLINT *strlen, SQLSMALLINT *type,
5987 SQLSMALLINT *subtype, SQLLEN *len,
5988 SQLSMALLINT *prec, SQLSMALLINT *scale,
5989 SQLSMALLINT *nullable)
5990{
5991 return SQL_ERROR;
5992}
5993#endif
5994
5999SQLRETURN SQL_API
6000SQLSetDescRec(SQLHDESC handle, SQLSMALLINT recno,
6001 SQLSMALLINT type, SQLSMALLINT subtype,
6002 SQLLEN len, SQLSMALLINT prec,
6003 SQLSMALLINT scale, SQLPOINTER data,
6004 SQLLEN *strlen, SQLLEN *indicator)
6005{
6006 return SQL_ERROR;
6007}
6008
6020static SQLRETURN
6021mkresultset(HSTMT stmt, COL *colspec, int ncols, COL *colspec3,
6022 int ncols3, int *nret)
6023{
6024 STMT *s;
6025 DBC *d;
6026
6027 if (stmt == SQL_NULL_HSTMT) {
6028 return SQL_INVALID_HANDLE;
6029 }
6030 s = (STMT *) stmt;
6031 if (s->dbc == SQL_NULL_HDBC) {
6032noconn:
6033 return noconn(s);
6034 }
6035 d = (DBC *) s->dbc;
6036 if (!d->sqlite) {
6037 goto noconn;
6038 }
6039 s3stmt_end_if(s);
6040 freeresult(s, 0);
6041 if (colspec3 && *s->ov3) {
6042 s->ncols = ncols3;
6043 s->cols = colspec3;
6044 } else {
6045 s->ncols = ncols;
6046 s->cols = colspec;
6047 }
6048 mkbindcols(s, s->ncols);
6049 s->nowchar[1] = 1;
6050 s->nrows = 0;
6051 s->rowp = s->rowprs = -1;
6052 s->isselect = -1;
6053 if (nret) {
6054 *nret = s->ncols;
6055 }
6056 return SQL_SUCCESS;
6057}
6058
6064 { "SYSTEM", "TABLEPRIV", "TABLE_QUALIFIER", SCOL_VARCHAR, 50 },
6065 { "SYSTEM", "TABLEPRIV", "TABLE_OWNER", SCOL_VARCHAR, 50 },
6066 { "SYSTEM", "TABLEPRIV", "TABLE_NAME", SCOL_VARCHAR, 255 },
6067 { "SYSTEM", "TABLEPRIV", "GRANTOR", SCOL_VARCHAR, 50 },
6068 { "SYSTEM", "TABLEPRIV", "GRANTEE", SCOL_VARCHAR, 50 },
6069 { "SYSTEM", "TABLEPRIV", "PRIVILEGE", SCOL_VARCHAR, 50 },
6070 { "SYSTEM", "TABLEPRIV", "IS_GRANTABLE", SCOL_VARCHAR, 50 }
6071};
6072
6074 { "SYSTEM", "TABLEPRIV", "TABLE_CAT", SCOL_VARCHAR, 50 },
6075 { "SYSTEM", "TABLEPRIV", "TABLE_SCHEM", SCOL_VARCHAR, 50 },
6076 { "SYSTEM", "TABLEPRIV", "TABLE_NAME", SCOL_VARCHAR, 255 },
6077 { "SYSTEM", "TABLEPRIV", "GRANTOR", SCOL_VARCHAR, 50 },
6078 { "SYSTEM", "TABLEPRIV", "GRANTEE", SCOL_VARCHAR, 50 },
6079 { "SYSTEM", "TABLEPRIV", "PRIVILEGE", SCOL_VARCHAR, 50 },
6080 { "SYSTEM", "TABLEPRIV", "IS_GRANTABLE", SCOL_VARCHAR, 50 }
6081};
6082
6095static SQLRETURN
6097 SQLCHAR *cat, SQLSMALLINT catLen,
6098 SQLCHAR *schema, SQLSMALLINT schemaLen,
6099 SQLCHAR *table, SQLSMALLINT tableLen)
6100{
6101 SQLRETURN ret;
6102 STMT *s;
6103 DBC *d;
6104 int ncols, rc, size, npatt;
6105 char *errp = NULL, *sql, tname[512];
6106
6109 if (ret != SQL_SUCCESS) {
6110 return ret;
6111 }
6112 s = (STMT *) stmt;
6113 d = (DBC *) s->dbc;
6114 if (cat && (catLen > 0 || catLen == SQL_NTS) && cat[0] == '%') {
6115 table = NULL;
6116 goto doit;
6117 }
6118 if (schema && (schemaLen > 0 || schemaLen == SQL_NTS) &&
6119 schema[0] == '%') {
6120 if ((!cat || catLen == 0 || !cat[0]) &&
6121 (!table || tableLen == 0 || !table[0])) {
6122 table = NULL;
6123 goto doit;
6124 }
6125 }
6126doit:
6127 if (!table) {
6128 size = 1;
6129 tname[0] = '%';
6130 } else {
6131 if (tableLen == SQL_NTS) {
6132 size = sizeof (tname) - 1;
6133 } else {
6134 size = min(sizeof (tname) - 1, tableLen);
6135 }
6136 strncpy(tname, (char *) table, size);
6137 }
6138 tname[size] = '\0';
6139 npatt = unescpat(tname);
6140#if defined(_WIN32) || defined(_WIN64)
6141 if (npatt) {
6142 sql = sqlite3_mprintf("select %s as 'TABLE_QUALIFIER', "
6143 "%s as 'TABLE_OWNER', "
6144 "tbl_name as 'TABLE_NAME', "
6145 "'' as 'GRANTOR', "
6146 "'' as 'GRANTEE', "
6147 "'SELECT' AS 'PRIVILEGE', "
6148 "NULL as 'IS_GRANTABLE' "
6149 "from sqlite_master where "
6150 "(type = 'table' or type = 'view') "
6151 "and tbl_name like %Q "
6152 "UNION "
6153 "select %s as 'TABLE_QUALIFIER', "
6154 "%s as 'TABLE_OWNER', "
6155 "tbl_name as 'TABLE_NAME', "
6156 "'' as 'GRANTOR', "
6157 "'' as 'GRANTEE', "
6158 "'UPDATE' AS 'PRIVILEGE', "
6159 "NULL as 'IS_GRANTABLE' "
6160 "from sqlite_master where "
6161 "(type = 'table' or type = 'view') "
6162 "and tbl_name like %Q "
6163 "UNION "
6164 "select %s as 'TABLE_QUALIFIER', "
6165 "%s as 'TABLE_OWNER', "
6166 "tbl_name as 'TABLE_NAME', "
6167 "'' as 'GRANTOR', "
6168 "'' as 'GRANTEE', "
6169 "'DELETE' AS 'PRIVILEGE', "
6170 "NULL as 'IS_GRANTABLE' "
6171 "from sqlite_master where "
6172 "(type = 'table' or type = 'view') "
6173 "and tbl_name like %Q "
6174 "UNION "
6175 "select %s as 'TABLE_QUALIFIER', "
6176 "%s as 'TABLE_OWNER', "
6177 "tbl_name as 'TABLE_NAME', "
6178 "'' as 'GRANTOR', "
6179 "'' as 'GRANTEE', "
6180 "'INSERT' AS 'PRIVILEGE', "
6181 "NULL as 'IS_GRANTABLE' "
6182 "from sqlite_master where "
6183 "(type = 'table' or type = 'view') "
6184 "and tbl_name like %Q "
6185 "UNION "
6186 "select %s as 'TABLE_QUALIFIER', "
6187 "%s as 'TABLE_OWNER', "
6188 "tbl_name as 'TABLE_NAME', "
6189 "'' as 'GRANTOR', "
6190 "'' as 'GRANTEE', "
6191 "'REFERENCES' AS 'PRIVILEGE', "
6192 "NULL as 'IS_GRANTABLE' "
6193 "from sqlite_master where "
6194 "(type = 'table' or type = 'view') "
6195 "and tbl_name like %Q",
6196 d->xcelqrx ? "'main'" : "NULL",
6197 d->xcelqrx ? "''" : "NULL",
6198 tname,
6199 d->xcelqrx ? "'main'" : "NULL",
6200 d->xcelqrx ? "''" : "NULL",
6201 tname,
6202 d->xcelqrx ? "'main'" : "NULL",
6203 d->xcelqrx ? "''" : "NULL",
6204 tname,
6205 d->xcelqrx ? "'main'" : "NULL",
6206 d->xcelqrx ? "''" : "NULL",
6207 tname,
6208 d->xcelqrx ? "'main'" : "NULL",
6209 d->xcelqrx ? "''" : "NULL",
6210 tname);
6211 } else {
6212 sql = sqlite3_mprintf("select %s as 'TABLE_QUALIFIER', "
6213 "%s as 'TABLE_OWNER', "
6214 "tbl_name as 'TABLE_NAME', "
6215 "'' as 'GRANTOR', "
6216 "'' as 'GRANTEE', "
6217 "'SELECT' AS 'PRIVILEGE', "
6218 "NULL as 'IS_GRANTABLE' "
6219 "from sqlite_master where "
6220 "(type = 'table' or type = 'view') "
6221 "and lower(tbl_name) = lower(%Q) "
6222 "UNION "
6223 "select %s as 'TABLE_QUALIFIER', "
6224 "%s as 'TABLE_OWNER', "
6225 "tbl_name as 'TABLE_NAME', "
6226 "'' as 'GRANTOR', "
6227 "'' as 'GRANTEE', "
6228 "'UPDATE' AS 'PRIVILEGE', "
6229 "NULL as 'IS_GRANTABLE' "
6230 "from sqlite_master where "
6231 "(type = 'table' or type = 'view') "
6232 "and lower(tbl_name) = lower(%Q) "
6233 "UNION "
6234 "select %s as 'TABLE_QUALIFIER', "
6235 "%s as 'TABLE_OWNER', "
6236 "tbl_name as 'TABLE_NAME', "
6237 "'' as 'GRANTOR', "
6238 "'' as 'GRANTEE', "
6239 "'DELETE' AS 'PRIVILEGE', "
6240 "NULL as 'IS_GRANTABLE' "
6241 "from sqlite_master where "
6242 "(type = 'table' or type = 'view') "
6243 "and lower(tbl_name) = lower(%Q) "
6244 "UNION "
6245 "select %s as 'TABLE_QUALIFIER', "
6246 "%s as 'TABLE_OWNER', "
6247 "tbl_name as 'TABLE_NAME', "
6248 "'' as 'GRANTOR', "
6249 "'' as 'GRANTEE', "
6250 "'INSERT' AS 'PRIVILEGE', "
6251 "NULL as 'IS_GRANTABLE' "
6252 "from sqlite_master where "
6253 "(type = 'table' or type = 'view') "
6254 "and lower(tbl_name) = lower(%Q) "
6255 "UNION "
6256 "select %s as 'TABLE_QUALIFIER', "
6257 "%s as 'TABLE_OWNER', "
6258 "tbl_name as 'TABLE_NAME', "
6259 "'' as 'GRANTOR', "
6260 "'' as 'GRANTEE', "
6261 "'REFERENCES' AS 'PRIVILEGE', "
6262 "NULL as 'IS_GRANTABLE' "
6263 "from sqlite_master where "
6264 "(type = 'table' or type = 'view') "
6265 "and lower(tbl_name) = lower(%Q)",
6266 d->xcelqrx ? "'main'" : "NULL",
6267 d->xcelqrx ? "''" : "NULL",
6268 tname,
6269 d->xcelqrx ? "'main'" : "NULL",
6270 d->xcelqrx ? "''" : "NULL",
6271 tname,
6272 d->xcelqrx ? "'main'" : "NULL",
6273 d->xcelqrx ? "''" : "NULL",
6274 tname,
6275 d->xcelqrx ? "'main'" : "NULL",
6276 d->xcelqrx ? "''" : "NULL",
6277 tname,
6278 d->xcelqrx ? "'main'" : "NULL",
6279 d->xcelqrx ? "''" : "NULL",
6280 tname);
6281 }
6282#else
6283 if (npatt) {
6284 sql = sqlite3_mprintf("select NULL as 'TABLE_QUALIFIER', "
6285 "NULL as 'TABLE_OWNER', "
6286 "tbl_name as 'TABLE_NAME', "
6287 "'' as 'GRANTOR', "
6288 "'' as 'GRANTEE', "
6289 "'SELECT' AS 'PRIVILEGE', "
6290 "NULL as 'IS_GRANTABLE' "
6291 "from sqlite_master where "
6292 "(type = 'table' or type = 'view') "
6293 "and tbl_name like %Q "
6294 "UNION "
6295 "select NULL as 'TABLE_QUALIFIER', "
6296 "NULL as 'TABLE_OWNER', "
6297 "tbl_name as 'TABLE_NAME', "
6298 "'' as 'GRANTOR', "
6299 "'' as 'GRANTEE', "
6300 "'UPDATE' AS 'PRIVILEGE', "
6301 "NULL as 'IS_GRANTABLE' "
6302 "from sqlite_master where "
6303 "(type = 'table' or type = 'view') "
6304 "and tbl_name like %Q "
6305 "UNION "
6306 "select NULL as 'TABLE_QUALIFIER', "
6307 "NULL as 'TABLE_OWNER', "
6308 "tbl_name as 'TABLE_NAME', "
6309 "'' as 'GRANTOR', "
6310 "'' as 'GRANTEE', "
6311 "'DELETE' AS 'PRIVILEGE', "
6312 "NULL as 'IS_GRANTABLE' "
6313 "from sqlite_master where "
6314 "(type = 'table' or type = 'view') "
6315 "and tbl_name like %Q "
6316 "UNION "
6317 "select NULL as 'TABLE_QUALIFIER', "
6318 "NULL as 'TABLE_OWNER', "
6319 "tbl_name as 'TABLE_NAME', "
6320 "'' as 'GRANTOR', "
6321 "'' as 'GRANTEE', "
6322 "'INSERT' AS 'PRIVILEGE', "
6323 "NULL as 'IS_GRANTABLE' "
6324 "from sqlite_master where "
6325 "(type = 'table' or type = 'view') "
6326 "and tbl_name like %Q "
6327 "UNION "
6328 "select NULL as 'TABLE_QUALIFIER', "
6329 "NULL as 'TABLE_OWNER', "
6330 "tbl_name as 'TABLE_NAME', "
6331 "'' as 'GRANTOR', "
6332 "'' as 'GRANTEE', "
6333 "'REFERENCES' AS 'PRIVILEGE', "
6334 "NULL as 'IS_GRANTABLE' "
6335 "from sqlite_master where "
6336 "(type = 'table' or type = 'view') "
6337 "and tbl_name like %Q",
6338 tname, tname, tname, tname, tname);
6339 } else {
6340 sql = sqlite3_mprintf("select NULL as 'TABLE_QUALIFIER', "
6341 "NULL as 'TABLE_OWNER', "
6342 "tbl_name as 'TABLE_NAME', "
6343 "'' as 'GRANTOR', "
6344 "'' as 'GRANTEE', "
6345 "'SELECT' AS 'PRIVILEGE', "
6346 "NULL as 'IS_GRANTABLE' "
6347 "from sqlite_master where "
6348 "(type = 'table' or type = 'view') "
6349 "and lower(tbl_name) = lower(%Q) "
6350 "UNION "
6351 "select NULL as 'TABLE_QUALIFIER', "
6352 "NULL as 'TABLE_OWNER', "
6353 "tbl_name as 'TABLE_NAME', "
6354 "'' as 'GRANTOR', "
6355 "'' as 'GRANTEE', "
6356 "'UPDATE' AS 'PRIVILEGE', "
6357 "NULL as 'IS_GRANTABLE' "
6358 "from sqlite_master where "
6359 "(type = 'table' or type = 'view') "
6360 "and lower(tbl_name) = lower(%Q) "
6361 "UNION "
6362 "select NULL as 'TABLE_QUALIFIER', "
6363 "NULL as 'TABLE_OWNER', "
6364 "tbl_name as 'TABLE_NAME', "
6365 "'' as 'GRANTOR', "
6366 "'' as 'GRANTEE', "
6367 "'DELETE' AS 'PRIVILEGE', "
6368 "NULL as 'IS_GRANTABLE' "
6369 "from sqlite_master where "
6370 "(type = 'table' or type = 'view') "
6371 "and lower(tbl_name) = lower(%Q) "
6372 "UNION "
6373 "select NULL as 'TABLE_QUALIFIER', "
6374 "NULL as 'TABLE_OWNER', "
6375 "tbl_name as 'TABLE_NAME', "
6376 "'' as 'GRANTOR', "
6377 "'' as 'GRANTEE', "
6378 "'INSERT' AS 'PRIVILEGE', "
6379 "NULL as 'IS_GRANTABLE' "
6380 "from sqlite_master where "
6381 "(type = 'table' or type = 'view') "
6382 "and lower(tbl_name) = lower(%Q) "
6383 "UNION "
6384 "select NULL as 'TABLE_QUALIFIER', "
6385 "NULL as 'TABLE_OWNER', "
6386 "tbl_name as 'TABLE_NAME', "
6387 "'' as 'GRANTOR', "
6388 "'' as 'GRANTEE', "
6389 "'REFERENCES' AS 'PRIVILEGE', "
6390 "NULL as 'IS_GRANTABLE' "
6391 "from sqlite_master where "
6392 "(type = 'table' or type = 'view') "
6393 "and lower(tbl_name) = lower(%Q)",
6394 tname, tname, tname, tname, tname);
6395 }
6396#endif
6397 if (!sql) {
6398 return nomem(s);
6399 }
6400 ret = starttran(s);
6401 if (ret != SQL_SUCCESS) {
6402 sqlite3_free(sql);
6403 return ret;
6404 }
6405 dbtraceapi(d, "sqlite3_get_table", sql);
6406 rc = sqlite3_get_table(d->sqlite, sql, &s->rows, &s->nrows, &ncols, &errp);
6407 sqlite3_free(sql);
6408 if (rc == SQLITE_OK) {
6409 if (ncols != s->ncols) {
6410 freeresult(s, 0);
6411 s->nrows = 0;
6412 } else {
6413 s->rowfree = sqlite3_free_table;
6414 }
6415 } else {
6416 s->nrows = 0;
6417 s->rows = NULL;
6418 s->rowfree = NULL;
6419 }
6420 if (errp) {
6421 sqlite3_free(errp);
6422 errp = NULL;
6423 }
6424 s->rowp = s->rowprs = -1;
6425 return SQL_SUCCESS;
6426}
6427
6428
6429#if !defined(WINTERFACE) || (defined(HAVE_UNIXODBC) && (HAVE_UNIXODBC))
6442SQLRETURN SQL_API
6443SQLTablePrivileges(SQLHSTMT stmt,
6444 SQLCHAR *catalog, SQLSMALLINT catalogLen,
6445 SQLCHAR *schema, SQLSMALLINT schemaLen,
6446 SQLCHAR *table, SQLSMALLINT tableLen)
6447{
6448#if defined(_WIN32) || defined(_WIN64)
6449 char *c = NULL, *s = NULL, *t = NULL;
6450#endif
6451 SQLRETURN ret;
6452
6454#if defined(_WIN32) || defined(_WIN64)
6455 if (!((STMT *) stmt)->oemcp[0]) {
6456 ret = drvtableprivileges(stmt, catalog, catalogLen, schema, schemaLen,
6457 table, tableLen);
6458 goto done2;
6459 }
6460 if (catalog) {
6461 c = wmb_to_utf_c((char *) catalog, catalogLen);
6462 if (!c) {
6463 ret = nomem((STMT *) stmt);
6464 goto done;
6465 }
6466 }
6467 if (schema) {
6468 s = wmb_to_utf_c((char *) schema, schemaLen);
6469 if (!s) {
6470 ret = nomem((STMT *) stmt);
6471 goto done;
6472 }
6473 }
6474 if (table) {
6475 t = wmb_to_utf_c((char *) table, tableLen);
6476 if (!t) {
6477 ret = nomem((STMT *) stmt);
6478 goto done;
6479 }
6480 }
6481 ret = drvtableprivileges(stmt, (SQLCHAR *) c, SQL_NTS,
6482 (SQLCHAR *) s, SQL_NTS,
6483 (SQLCHAR *) t, SQL_NTS);
6484#else
6485 ret = drvtableprivileges(stmt, catalog, catalogLen, schema, schemaLen,
6486 table, tableLen);
6487#endif
6488#if defined(_WIN32) || defined(_WIN64)
6489done:
6490 uc_free(t);
6491 uc_free(s);
6492 uc_free(c);
6493done2:
6494 ;
6495#endif
6497 return ret;
6498}
6499#endif
6500
6501#if !defined(HAVE_UNIXODBC) || !(HAVE_UNIXODBC)
6502#ifdef WINTERFACE
6515SQLRETURN SQL_API
6517 SQLWCHAR *catalog, SQLSMALLINT catalogLen,
6518 SQLWCHAR *schema, SQLSMALLINT schemaLen,
6519 SQLWCHAR *table, SQLSMALLINT tableLen)
6520{
6521 char *c = NULL, *s = NULL, *t = NULL;
6522 SQLRETURN ret;
6523
6525 if (catalog) {
6526 c = uc_to_utf_c(catalog, catalogLen);
6527 if (!c) {
6528 ret = nomem((STMT *) stmt);
6529 goto done;
6530 }
6531 }
6532 if (schema) {
6533 s = uc_to_utf_c(schema, schemaLen);
6534 if (!s) {
6535 ret = nomem((STMT *) stmt);
6536 goto done;
6537 }
6538 }
6539 if (table) {
6540 t = uc_to_utf_c(table, tableLen);
6541 if (!t) {
6542 ret = nomem((STMT *) stmt);
6543 goto done;
6544 }
6545 }
6546 ret = drvtableprivileges(stmt, (SQLCHAR *) c, SQL_NTS,
6547 (SQLCHAR *) s, SQL_NTS,
6548 (SQLCHAR *) t, SQL_NTS);
6549done:
6550 uc_free(t);
6551 uc_free(s);
6552 uc_free(c);
6554 return ret;
6555}
6556#endif
6557#endif
6558
6563static COL colPrivSpec2[] = {
6564 { "SYSTEM", "COLPRIV", "TABLE_QUALIFIER", SCOL_VARCHAR, 50 },
6565 { "SYSTEM", "COLPRIV", "TABLE_OWNER", SCOL_VARCHAR, 50 },
6566 { "SYSTEM", "COLPRIV", "TABLE_NAME", SCOL_VARCHAR, 255 },
6567 { "SYSTEM", "COLPRIV", "COLUMN_NAME", SCOL_VARCHAR, 255 },
6568 { "SYSTEM", "COLPRIV", "GRANTOR", SCOL_VARCHAR, 50 },
6569 { "SYSTEM", "COLPRIV", "GRANTEE", SCOL_VARCHAR, 50 },
6570 { "SYSTEM", "COLPRIV", "PRIVILEGE", SCOL_VARCHAR, 50 }
6571};
6572
6573static COL colPrivSpec3[] = {
6574 { "SYSTEM", "COLPRIV", "TABLE_CAT", SCOL_VARCHAR, 50 },
6575 { "SYSTEM", "COLPRIV", "TABLE_SCHEM", SCOL_VARCHAR, 50 },
6576 { "SYSTEM", "COLPRIV", "TABLE_NAME", SCOL_VARCHAR, 255 },
6577 { "SYSTEM", "COLPRIV", "COLUMN_NAME", SCOL_VARCHAR, 255 },
6578 { "SYSTEM", "COLPRIV", "GRANTOR", SCOL_VARCHAR, 50 },
6579 { "SYSTEM", "COLPRIV", "GRANTEE", SCOL_VARCHAR, 50 },
6580 { "SYSTEM", "COLPRIV", "PRIVILEGE", SCOL_VARCHAR, 50 }
6581};
6582
6583#if !defined(WINTERFACE) || (defined(HAVE_UNIXODBC) && (HAVE_UNIXODBC))
6598SQLRETURN SQL_API
6599SQLColumnPrivileges(SQLHSTMT stmt,
6600 SQLCHAR *catalog, SQLSMALLINT catalogLen,
6601 SQLCHAR *schema, SQLSMALLINT schemaLen,
6602 SQLCHAR *table, SQLSMALLINT tableLen,
6603 SQLCHAR *column, SQLSMALLINT columnLen)
6604{
6605 SQLRETURN ret;
6606
6611 return ret;
6612}
6613#endif
6614
6615#if !defined(HAVE_UNIXODBC) || !(HAVE_UNIXODBC)
6616#ifdef WINTERFACE
6631SQLRETURN SQL_API
6633 SQLWCHAR *catalog, SQLSMALLINT catalogLen,
6634 SQLWCHAR *schema, SQLSMALLINT schemaLen,
6635 SQLWCHAR *table, SQLSMALLINT tableLen,
6636 SQLWCHAR *column, SQLSMALLINT columnLen)
6637{
6638 SQLRETURN ret;
6639
6644 return ret;
6645}
6646#endif
6647#endif
6648
6653static COL pkeySpec2[] = {
6654 { "SYSTEM", "PRIMARYKEY", "TABLE_QUALIFIER", SCOL_VARCHAR, 50 },
6655 { "SYSTEM", "PRIMARYKEY", "TABLE_OWNER", SCOL_VARCHAR, 50 },
6656 { "SYSTEM", "PRIMARYKEY", "TABLE_NAME", SCOL_VARCHAR, 255 },
6657 { "SYSTEM", "PRIMARYKEY", "COLUMN_NAME", SCOL_VARCHAR, 255 },
6658 { "SYSTEM", "PRIMARYKEY", "KEY_SEQ", SQL_SMALLINT, 50 },
6659 { "SYSTEM", "PRIMARYKEY", "PK_NAME", SCOL_VARCHAR, 50 }
6660};
6661
6662static COL pkeySpec3[] = {
6663 { "SYSTEM", "PRIMARYKEY", "TABLE_CAT", SCOL_VARCHAR, 50 },
6664 { "SYSTEM", "PRIMARYKEY", "TABLE_SCHEM", SCOL_VARCHAR, 50 },
6665 { "SYSTEM", "PRIMARYKEY", "TABLE_NAME", SCOL_VARCHAR, 255 },
6666 { "SYSTEM", "PRIMARYKEY", "COLUMN_NAME", SCOL_VARCHAR, 255 },
6667 { "SYSTEM", "PRIMARYKEY", "KEY_SEQ", SQL_SMALLINT, 50 },
6668 { "SYSTEM", "PRIMARYKEY", "PK_NAME", SCOL_VARCHAR, 50 }
6669};
6670
6683static SQLRETURN
6685 SQLCHAR *cat, SQLSMALLINT catLen,
6686 SQLCHAR *schema, SQLSMALLINT schemaLen,
6687 SQLCHAR *table, SQLSMALLINT tableLen)
6688{
6689 STMT *s;
6690 DBC *d;
6691 SQLRETURN sret;
6692 int i, asize, ret, nrows, ncols, nrows2 = 0, ncols2 = 0;
6693 int namec = -1, uniquec = -1, namec2 = -1, uniquec2 = -1, offs, seq = 1;
6694 PTRDIFF_T size;
6695 char **rowp = NULL, **rowp2 = NULL, *errp = NULL, *sql, tname[512];
6696
6698 pkeySpec3, array_size(pkeySpec3), &asize);
6699 if (sret != SQL_SUCCESS) {
6700 return sret;
6701 }
6702 s = (STMT *) stmt;
6703 d = (DBC *) s->dbc;
6704 if (!table || table[0] == '\0' || table[0] == '%') {
6705 setstat(s, -1, "need table name", (*s->ov3) ? "HY000" : "S1000");
6706 return SQL_ERROR;
6707 }
6708 if (tableLen == SQL_NTS) {
6709 size = sizeof (tname) - 1;
6710 } else {
6711 size = min(sizeof (tname) - 1, tableLen);
6712 }
6713 strncpy(tname, (char *) table, size);
6714 tname[size] = '\0';
6715 unescpat(tname);
6716 sql = sqlite3_mprintf("PRAGMA table_info(%Q)", tname);
6717 if (!sql) {
6718 return nomem(s);
6719 }
6720 sret = starttran(s);
6721 if (sret != SQL_SUCCESS) {
6722 sqlite3_free(sql);
6723 return sret;
6724 }
6725 dbtraceapi(d, "sqlite3_get_table", sql);
6726 ret = sqlite3_get_table(d->sqlite, sql, &rowp, &nrows, &ncols, &errp);
6727 sqlite3_free(sql);
6728 if (ret != SQLITE_OK) {
6729 setstat(s, ret, "%s (%d)", (*s->ov3) ? "HY000" : "S1000",
6730 errp ? errp : "unknown error", ret);
6731 if (errp) {
6732 sqlite3_free(errp);
6733 errp = NULL;
6734 }
6735 return SQL_ERROR;
6736 }
6737 if (errp) {
6738 sqlite3_free(errp);
6739 errp = NULL;
6740 }
6741 size = 0;
6742 if (ncols * nrows > 0) {
6743 int typec;
6744
6745 namec = findcol(rowp, ncols, "name");
6746 uniquec = findcol(rowp, ncols, "pk");
6747 typec = findcol(rowp, ncols, "type");
6748 if (namec >= 0 && uniquec >= 0 && typec >= 0) {
6749 for (i = 1; i <= nrows; i++) {
6750 if (*rowp[i * ncols + uniquec] != '0') {
6751 size++;
6752 }
6753 }
6754 }
6755 }
6756 if (size == 0) {
6757 sql = sqlite3_mprintf("PRAGMA index_list(%Q)", tname);
6758 if (!sql) {
6759 sqlite3_free_table(rowp);
6760 return nomem(s);
6761 }
6762 dbtraceapi(d, "sqlite3_get_table", sql);
6763 ret = sqlite3_get_table(d->sqlite, sql, &rowp2, &nrows2, &ncols2,
6764 &errp);
6765 sqlite3_free(sql);
6766 if (ret != SQLITE_OK) {
6767 sqlite3_free_table(rowp);
6768 sqlite3_free_table(rowp2);
6769 setstat(s, ret, "%s (%d)", (*s->ov3) ? "HY000" : "S1000",
6770 errp ? errp : "unknown error", ret);
6771 if (errp) {
6772 sqlite3_free(errp);
6773 errp = NULL;
6774 }
6775 return SQL_ERROR;
6776 }
6777 if (errp) {
6778 sqlite3_free(errp);
6779 errp = NULL;
6780 }
6781 }
6782 if (ncols2 * nrows2 > 0) {
6783 namec2 = findcol(rowp2, ncols2, "name");
6784 uniquec2 = findcol(rowp2, ncols2, "unique");
6785 if (namec2 >= 0 && uniquec2 >= 0) {
6786 for (i = 1; i <= nrows2; i++) {
6787 int nnrows, nncols, nlen = 0;
6788 char **rowpp;
6789
6790 if (rowp2[i * ncols2 + namec2]) {
6791 nlen = strlen(rowp2[i * ncols2 + namec2]);
6792 }
6793 if (nlen < 17 ||
6794 strncmp(rowp2[i * ncols2 + namec2],
6795 "sqlite_autoindex_", 17)) {
6796 continue;
6797 }
6798 if (*rowp2[i * ncols2 + uniquec2] != '0') {
6799 ret = SQLITE_ERROR;
6800 sql = sqlite3_mprintf("PRAGMA index_info(%Q)",
6801 rowp2[i * ncols2 + namec2]);
6802 if (sql) {
6803 dbtraceapi(d, "sqlite3_get_table", sql);
6804 ret = sqlite3_get_table(d->sqlite, sql, &rowpp,
6805 &nnrows, &nncols, NULL);
6806 sqlite3_free(sql);
6807 }
6808 if (ret == SQLITE_OK) {
6809 size += nnrows;
6810 sqlite3_free_table(rowpp);
6811 }
6812 }
6813 }
6814 }
6815 }
6816 if (size == 0) {
6817 sqlite3_free_table(rowp);
6818 sqlite3_free_table(rowp2);
6819 return SQL_SUCCESS;
6820 }
6821 s->nrows = size;
6822 size = (size + 1) * asize;
6823 s->rows = xmalloc((size + 1) * sizeof (char *));
6824 if (!s->rows) {
6825 s->nrows = 0;
6826 sqlite3_free_table(rowp);
6827 sqlite3_free_table(rowp2);
6828 return nomem(s);
6829 }
6830 s->rows[0] = (char *) size;
6831 s->rows += 1;
6832 memset(s->rows, 0, sizeof (char *) * size);
6833 s->rowfree = freerows;
6834 offs = s->ncols;
6835 if (rowp) {
6836 for (i = 1; i <= nrows; i++) {
6837 if (*rowp[i * ncols + uniquec] != '0') {
6838 char buf[32];
6839
6840#if defined(_WIN32) || defined(_WIN64)
6841 s->rows[offs + 0] = xstrdup(d->xcelqrx ? "main" : "");
6842 s->rows[offs + 1] = xstrdup("");
6843#else
6844 s->rows[offs + 0] = xstrdup("");
6845 s->rows[offs + 1] = xstrdup("");
6846#endif
6847 s->rows[offs + 2] = xstrdup(tname);
6848 s->rows[offs + 3] = xstrdup(rowp[i * ncols + namec]);
6849 sprintf(buf, "%d", seq++);
6850 s->rows[offs + 4] = xstrdup(buf);
6851 offs += s->ncols;
6852 }
6853 }
6854 }
6855 if (rowp2) {
6856 for (i = 1; i <= nrows2; i++) {
6857 int nnrows, nncols, nlen = 0;
6858 char **rowpp;
6859
6860 if (rowp2[i * ncols2 + namec2]) {
6861 nlen = strlen(rowp2[i * ncols2 + namec2]);
6862 }
6863 if (nlen < 17 ||
6864 strncmp(rowp2[i * ncols2 + namec2], "sqlite_autoindex_", 17)) {
6865 continue;
6866 }
6867 if (*rowp2[i * ncols2 + uniquec2] != '0') {
6868 int k;
6869
6870 ret = SQLITE_ERROR;
6871 sql = sqlite3_mprintf("PRAGMA index_info(%Q)",
6872 rowp2[i * ncols2 + namec2]);
6873 if (sql) {
6874 dbtraceapi(d, "sqlite3_get_table", sql);
6875 ret = sqlite3_get_table(d->sqlite, sql, &rowpp,
6876 &nnrows, &nncols, NULL);
6877 sqlite3_free(sql);
6878 }
6879 if (ret != SQLITE_OK) {
6880 continue;
6881 }
6882 for (k = 0; nnrows && k < nncols; k++) {
6883 if (strcmp(rowpp[k], "name") == 0) {
6884 int m;
6885
6886 for (m = 1; m <= nnrows; m++) {
6887 int roffs = offs + (m - 1) * s->ncols;
6888
6889#if defined(_WIN32) || defined(_WIN64)
6890 s->rows[roffs + 0] =
6891 xstrdup(d->xcelqrx ? "main" : "");
6892 s->rows[roffs + 1] = xstrdup("");
6893#else
6894 s->rows[roffs + 0] = xstrdup("");
6895 s->rows[roffs + 1] = xstrdup("");
6896#endif
6897 s->rows[roffs + 2] = xstrdup(tname);
6898 s->rows[roffs + 3] =
6899 xstrdup(rowpp[m * nncols + k]);
6900 s->rows[roffs + 5] =
6901 xstrdup(rowp2[i * ncols2 + namec2]);
6902 }
6903 } else if (strcmp(rowpp[k], "seqno") == 0) {
6904 int m;
6905
6906 for (m = 1; m <= nnrows; m++) {
6907 int roffs = offs + (m - 1) * s->ncols;
6908 int pos = m - 1;
6909 char buf[32];
6910
6911 sscanf(rowpp[m * nncols + k], "%d", &pos);
6912 sprintf(buf, "%d", pos + 1);
6913 s->rows[roffs + 4] = xstrdup(buf);
6914 }
6915 }
6916 }
6917 offs += nnrows * s->ncols;
6918 sqlite3_free_table(rowpp);
6919 }
6920 }
6921 }
6922 sqlite3_free_table(rowp);
6923 sqlite3_free_table(rowp2);
6924 return SQL_SUCCESS;
6925}
6926
6927#ifndef WINTERFACE
6940SQLRETURN SQL_API
6941SQLPrimaryKeys(SQLHSTMT stmt,
6942 SQLCHAR *cat, SQLSMALLINT catLen,
6943 SQLCHAR *schema, SQLSMALLINT schemaLen,
6944 SQLCHAR *table, SQLSMALLINT tableLen)
6945{
6946#if defined(_WIN32) || defined(_WIN64)
6947 char *c = NULL, *s = NULL, *t = NULL;
6948#endif
6949 SQLRETURN ret;
6950
6952#if defined(_WIN32) || defined(_WIN64)
6953 if (!((STMT *) stmt)->oemcp[0]) {
6954 ret = drvprimarykeys(stmt, cat, catLen, schema, schemaLen,
6955 table, tableLen);
6956 goto done2;
6957 }
6958 if (cat) {
6959 c = wmb_to_utf_c((char *) cat, catLen);
6960 if (!c) {
6961 ret = nomem((STMT *) stmt);
6962 goto done;
6963 }
6964 }
6965 if (schema) {
6966 s = wmb_to_utf_c((char *) schema, schemaLen);
6967 if (!s) {
6968 ret = nomem((STMT *) stmt);
6969 goto done;
6970 }
6971 }
6972 if (table) {
6973 t = wmb_to_utf_c((char *) table, tableLen);
6974 if (!t) {
6975 ret = nomem((STMT *) stmt);
6976 goto done;
6977 }
6978 }
6979 ret = drvprimarykeys(stmt, (SQLCHAR *) c, SQL_NTS,
6980 (SQLCHAR *) s, SQL_NTS, (SQLCHAR *) t, SQL_NTS);
6981#else
6982 ret = drvprimarykeys(stmt, cat, catLen, schema, schemaLen,
6983 table, tableLen);
6984#endif
6985#if defined(_WIN32) || defined(_WIN64)
6986done:
6987 uc_free(t);
6988 uc_free(s);
6989 uc_free(c);
6990done2:
6991 ;
6992#endif
6994 return ret;
6995}
6996#endif
6997
6998#ifdef WINTERFACE
7011SQLRETURN SQL_API
7013 SQLWCHAR *cat, SQLSMALLINT catLen,
7014 SQLWCHAR *schema, SQLSMALLINT schemaLen,
7015 SQLWCHAR *table, SQLSMALLINT tableLen)
7016{
7017 char *c = NULL, *s = NULL, *t = NULL;
7018 SQLRETURN ret;
7019
7021 if (cat) {
7022 c = uc_to_utf_c(cat, catLen);
7023 if (!c) {
7024 ret = nomem((STMT *) stmt);
7025 goto done;
7026 }
7027 }
7028 if (schema) {
7029 s = uc_to_utf_c(schema, schemaLen);
7030 if (!s) {
7031 ret = nomem((STMT *) stmt);
7032 goto done;
7033 }
7034 }
7035 if (table) {
7036 t = uc_to_utf_c(table, tableLen);
7037 if (!t) {
7038 ret = nomem((STMT *) stmt);
7039 goto done;
7040 }
7041 }
7042 ret = drvprimarykeys(stmt, (SQLCHAR *) c, SQL_NTS,
7043 (SQLCHAR *) s, SQL_NTS, (SQLCHAR *) t, SQL_NTS);
7044done:
7045 uc_free(t);
7046 uc_free(s);
7047 uc_free(c);
7049 return ret;
7050}
7051#endif
7052
7057static COL scolSpec2[] = {
7058 { "SYSTEM", "COLUMN", "SCOPE", SQL_SMALLINT, 1 },
7059 { "SYSTEM", "COLUMN", "COLUMN_NAME", SCOL_VARCHAR, 255 },
7060 { "SYSTEM", "COLUMN", "DATA_TYPE", SQL_SMALLINT, 50 },
7061 { "SYSTEM", "COLUMN", "TYPE_NAME", SCOL_VARCHAR, 50 },
7062 { "SYSTEM", "COLUMN", "PRECISION", SQL_INTEGER, 50 },
7063 { "SYSTEM", "COLUMN", "LENGTH", SQL_INTEGER, 50 },
7064 { "SYSTEM", "COLUMN", "DECIMAL_DIGITS", SQL_INTEGER, 50 },
7065 { "SYSTEM", "COLUMN", "PSEUDO_COLUMN", SQL_SMALLINT, 1 },
7066 { "SYSTEM", "COLUMN", "NULLABLE", SQL_SMALLINT, 1 }
7067};
7068
7069static COL scolSpec3[] = {
7070 { "SYSTEM", "COLUMN", "SCOPE", SQL_SMALLINT, 1 },
7071 { "SYSTEM", "COLUMN", "COLUMN_NAME", SCOL_VARCHAR, 255 },
7072 { "SYSTEM", "COLUMN", "DATA_TYPE", SQL_SMALLINT, 50 },
7073 { "SYSTEM", "COLUMN", "TYPE_NAME", SCOL_VARCHAR, 50 },
7074 { "SYSTEM", "COLUMN", "COLUMN_SIZE", SQL_INTEGER, 50 },
7075 { "SYSTEM", "COLUMN", "BUFFER_LENGTH", SQL_INTEGER, 50 },
7076 { "SYSTEM", "COLUMN", "DECIMAL_DIGITS", SQL_INTEGER, 50 },
7077 { "SYSTEM", "COLUMN", "PSEUDO_COLUMN", SQL_SMALLINT, 1 },
7078 { "SYSTEM", "COLUMN", "NULLABLE", SQL_SMALLINT, 1 }
7079};
7080
7096static SQLRETURN
7097drvspecialcolumns(SQLHSTMT stmt, SQLUSMALLINT id,
7098 SQLCHAR *cat, SQLSMALLINT catLen,
7099 SQLCHAR *schema, SQLSMALLINT schemaLen,
7100 SQLCHAR *table, SQLSMALLINT tableLen,
7101 SQLUSMALLINT scope, SQLUSMALLINT nullable)
7102{
7103 STMT *s;
7104 DBC *d;
7105 SQLRETURN sret;
7106 int i, asize, ret, nrows, ncols, nnnrows, nnncols, offs;
7107 PTRDIFF_T size;
7108 int namec = -1, uniquec = -1, namecc = -1, typecc = -1;
7109 int notnullcc = -1, mkrowid = 0;
7110 char *errp = NULL, *sql, tname[512];
7111 char **rowp = NULL, **rowppp = NULL;
7112
7114 scolSpec3, array_size(scolSpec3), &asize);
7115 if (sret != SQL_SUCCESS) {
7116 return sret;
7117 }
7118 s = (STMT *) stmt;
7119 d = (DBC *) s->dbc;
7120 if (!table || table[0] == '\0' || table[0] == '%') {
7121 setstat(s, -1, "need table name", (*s->ov3) ? "HY000" : "S1000");
7122 return SQL_ERROR;
7123 }
7124 if (tableLen == SQL_NTS) {
7125 size = sizeof (tname) - 1;
7126 } else {
7127 size = min(sizeof (tname) - 1, tableLen);
7128 }
7129 strncpy(tname, (char *) table, size);
7130 tname[size] = '\0';
7131 unescpat(tname);
7132 if (id != SQL_BEST_ROWID) {
7133 return SQL_SUCCESS;
7134 }
7135 sql = sqlite3_mprintf("PRAGMA index_list(%Q)", tname);
7136 if (!sql) {
7137 return nomem(s);
7138 }
7139 sret = starttran(s);
7140 if (sret != SQL_SUCCESS) {
7141 sqlite3_free(sql);
7142 return sret;
7143 }
7144 dbtraceapi(d, "sqlite3_get_table", sql);
7145 ret = sqlite3_get_table(d->sqlite, sql, &rowp, &nrows, &ncols, &errp);
7146 sqlite3_free(sql);
7147 if (ret != SQLITE_OK) {
7148doerr:
7149 setstat(s, ret, "%s (%d)", (*s->ov3) ? "HY000" : "S1000",
7150 errp ? errp : "unknown error", ret);
7151 if (errp) {
7152 sqlite3_free(errp);
7153 errp = NULL;
7154 }
7155 return SQL_ERROR;
7156 }
7157 if (errp) {
7158 sqlite3_free(errp);
7159 errp = NULL;
7160 }
7161 size = 0; /* number result rows */
7162 if (ncols * nrows <= 0) {
7163 goto nodata_but_rowid;
7164 }
7165 sql = sqlite3_mprintf("PRAGMA table_info(%Q)", tname);
7166 if (!sql) {
7167 return nomem(s);
7168 }
7169 dbtraceapi(d, "sqlite3_get_table", sql);
7170 ret = sqlite3_get_table(d->sqlite, sql, &rowppp, &nnnrows, &nnncols,
7171 &errp);
7172 sqlite3_free(sql);
7173 if (ret != SQLITE_OK) {
7174 sqlite3_free_table(rowp);
7175 goto doerr;
7176 }
7177 if (errp) {
7178 sqlite3_free(errp);
7179 errp = NULL;
7180 }
7181 namec = findcol(rowp, ncols, "name");
7182 uniquec = findcol(rowp, ncols, "unique");
7183 if (namec < 0 || uniquec < 0) {
7184 goto nodata_but_rowid;
7185 }
7186 namecc = findcol(rowppp, nnncols, "name");
7187 typecc = findcol(rowppp, nnncols, "type");
7188 notnullcc = findcol(rowppp, nnncols, "notnull");
7189 for (i = 1; i <= nrows; i++) {
7190 int nnrows, nncols;
7191 char **rowpp = NULL;
7192
7193 if (*rowp[i * ncols + uniquec] != '0') {
7194 ret = SQLITE_ERROR;
7195 sql = sqlite3_mprintf("PRAGMA index_info(%Q)",
7196 rowp[i * ncols + namec]);
7197 if (sql) {
7198 dbtraceapi(d, "sqlite3_get_table", sql);
7199 ret = sqlite3_get_table(d->sqlite, sql, &rowpp,
7200 &nnrows, &nncols, NULL);
7201 sqlite3_free(sql);
7202 }
7203 if (ret == SQLITE_OK) {
7204 size += nnrows;
7205 sqlite3_free_table(rowpp);
7206 }
7207 }
7208 }
7209nodata_but_rowid:
7210 if (size == 0) {
7211 size = 1;
7212 mkrowid = 1;
7213 }
7214 s->nrows = size;
7215 size = (size + 1) * asize;
7216 s->rows = xmalloc((size + 1) * sizeof (char *));
7217 if (!s->rows) {
7218 s->nrows = 0;
7219 sqlite3_free_table(rowp);
7220 sqlite3_free_table(rowppp);
7221 return nomem(s);
7222 }
7223 s->rows[0] = (char *) size;
7224 s->rows += 1;
7225 memset(s->rows, 0, sizeof (char *) * size);
7226 s->rowfree = freerows;
7227 if (mkrowid) {
7228 s->nrows = 0;
7229 goto mkrowid;
7230 }
7231 offs = 0;
7232 for (i = 1; i <= nrows; i++) {
7233 int nnrows, nncols;
7234 char **rowpp = NULL;
7235
7236 if (*rowp[i * ncols + uniquec] != '0') {
7237 int k;
7238
7239 ret = SQLITE_ERROR;
7240 sql = sqlite3_mprintf("PRAGMA index_info(%Q)",
7241 rowp[i * ncols + namec]);
7242 if (sql) {
7243 dbtraceapi(d, "sqlite3_get_table", sql);
7244 ret = sqlite3_get_table(d->sqlite, sql, &rowpp,
7245 &nnrows, &nncols, NULL);
7246 sqlite3_free(sql);
7247 }
7248 if (ret != SQLITE_OK) {
7249 continue;
7250 }
7251 for (k = 0; nnrows && k < nncols; k++) {
7252 if (strcmp(rowpp[k], "name") == 0) {
7253 int m;
7254
7255 for (m = 1; m <= nnrows; m++) {
7256 int roffs = (offs + m) * s->ncols;
7257
7258 s->rows[roffs + 0] =
7259 xstrdup(stringify(SQL_SCOPE_SESSION));
7260 s->rows[roffs + 1] = xstrdup(rowpp[m * nncols + k]);
7261 s->rows[roffs + 4] = xstrdup("0");
7262 s->rows[roffs + 7] =
7263 xstrdup(stringify(SQL_PC_NOT_PSEUDO));
7264 if (namecc >= 0 && typecc >= 0) {
7265 int ii;
7266
7267 for (ii = 1; ii <= nnnrows; ii++) {
7268 if (strcmp(rowppp[ii * nnncols + namecc],
7269 rowpp[m * nncols + k]) == 0) {
7270 char *typen = rowppp[ii * nnncols + typecc];
7271 int sqltype, mm, dd, isnullable = 0;
7272 char buf[32];
7273
7274 s->rows[roffs + 3] = xstrdup(typen);
7275 sqltype = mapsqltype(typen, NULL, *s->ov3,
7276 s->nowchar[0],
7277 s->dobigint);
7278 getmd(typen, sqltype, &mm, &dd);
7279#ifdef SQL_LONGVARCHAR
7280 if (sqltype == SQL_VARCHAR && mm > 255) {
7281 sqltype = SQL_LONGVARCHAR;
7282 }
7283#endif
7284#ifdef WINTERFACE
7285#ifdef SQL_WLONGVARCHAR
7286 if (sqltype == SQL_WVARCHAR && mm > 255) {
7287 sqltype = SQL_WLONGVARCHAR;
7288 }
7289#endif
7290#endif
7291 if (sqltype == SQL_VARBINARY && mm > 255) {
7292 sqltype = SQL_LONGVARBINARY;
7293 }
7294 sprintf(buf, "%d", sqltype);
7295 s->rows[roffs + 2] = xstrdup(buf);
7296 sprintf(buf, "%d", mm);
7297 s->rows[roffs + 5] = xstrdup(buf);
7298 sprintf(buf, "%d", dd);
7299 s->rows[roffs + 6] = xstrdup(buf);
7300 if (notnullcc >= 0) {
7301 char *inp =
7302 rowppp[ii * nnncols + notnullcc];
7303
7304 isnullable = inp[0] != '0';
7305 }
7306 sprintf(buf, "%d", isnullable);
7307 s->rows[roffs + 8] = xstrdup(buf);
7308 }
7309 }
7310 }
7311 }
7312 }
7313 }
7314 offs += nnrows;
7315 sqlite3_free_table(rowpp);
7316 }
7317 }
7318 if (nullable == SQL_NO_NULLS) {
7319 for (i = 1; i < s->nrows; i++) {
7320 if (s->rows[i * s->ncols + 8][0] == '0') {
7321 int m, i1 = i + 1;
7322
7323 for (m = 0; m < s->ncols; m++) {
7324 freep(&s->rows[i * s->ncols + m]);
7325 }
7326 size = s->ncols * sizeof (char *) * (s->nrows - i1);
7327 if (size > 0) {
7328 memmove(s->rows + i * s->ncols,
7329 s->rows + i1 * s->ncols,
7330 size);
7331 memset(s->rows + s->nrows * s->ncols, 0,
7332 s->ncols * sizeof (char *));
7333 }
7334 s->nrows--;
7335 --i;
7336 }
7337 }
7338 }
7339mkrowid:
7340 sqlite3_free_table(rowp);
7341 sqlite3_free_table(rowppp);
7342 if (s->nrows == 0) {
7343 s->rows[s->ncols + 0] = xstrdup(stringify(SQL_SCOPE_SESSION));
7344 s->rows[s->ncols + 1] = xstrdup("_ROWID_");
7345 s->rows[s->ncols + 2] = xstrdup(stringify(SQL_INTEGER));
7346 s->rows[s->ncols + 3] = xstrdup("integer");
7347 s->rows[s->ncols + 4] = xstrdup("0");
7348 s->rows[s->ncols + 5] = xstrdup("10");
7349 s->rows[s->ncols + 6] = xstrdup("9");
7350 s->rows[s->ncols + 7] = xstrdup(stringify(SQL_PC_PSEUDO));
7351 s->rows[s->ncols + 8] = xstrdup(stringify(SQL_FALSE));
7352 s->nrows = 1;
7353 }
7354 return SQL_SUCCESS;
7355}
7356
7357#ifndef WINTERFACE
7373SQLRETURN SQL_API
7374SQLSpecialColumns(SQLHSTMT stmt, SQLUSMALLINT id,
7375 SQLCHAR *cat, SQLSMALLINT catLen,
7376 SQLCHAR *schema, SQLSMALLINT schemaLen,
7377 SQLCHAR *table, SQLSMALLINT tableLen,
7378 SQLUSMALLINT scope, SQLUSMALLINT nullable)
7379{
7380#if defined(_WIN32) || defined(_WIN64)
7381 char *c = NULL, *s = NULL, *t = NULL;
7382#endif
7383 SQLRETURN ret;
7384
7386#if defined(_WIN32) || defined(_WIN64)
7387 if (!((STMT *) stmt)->oemcp[0]) {
7388 ret = drvspecialcolumns(stmt, id, cat, catLen, schema, schemaLen,
7389 table, tableLen, scope, nullable);
7390 goto done2;
7391 }
7392 if (cat) {
7393 c = wmb_to_utf_c((char *) cat, catLen);
7394 if (!c) {
7395 ret = nomem((STMT *) stmt);
7396 goto done;
7397 }
7398 }
7399 if (schema) {
7400 s = wmb_to_utf_c((char *) schema, schemaLen);
7401 if (!s) {
7402 ret = nomem((STMT *) stmt);
7403 goto done;
7404 }
7405 }
7406 if (table) {
7407 t = wmb_to_utf_c((char *) table, tableLen);
7408 if (!t) {
7409 ret = nomem((STMT *) stmt);
7410 goto done;
7411 }
7412 }
7413 ret = drvspecialcolumns(stmt, id, (SQLCHAR *) c, SQL_NTS,
7414 (SQLCHAR *) s, SQL_NTS, (SQLCHAR *) t, SQL_NTS,
7415 scope, nullable);
7416#else
7417 ret = drvspecialcolumns(stmt, id, cat, catLen, schema, schemaLen,
7418 table, tableLen, scope, nullable);
7419#endif
7420#if defined(_WIN32) || defined(_WIN64)
7421done:
7422 uc_free(t);
7423 uc_free(s);
7424 uc_free(c);
7425done2:
7426 ;
7427#endif
7429 return ret;
7430}
7431#endif
7432
7433#ifdef WINTERFACE
7449SQLRETURN SQL_API
7450SQLSpecialColumnsW(SQLHSTMT stmt, SQLUSMALLINT id,
7451 SQLWCHAR *cat, SQLSMALLINT catLen,
7452 SQLWCHAR *schema, SQLSMALLINT schemaLen,
7453 SQLWCHAR *table, SQLSMALLINT tableLen,
7454 SQLUSMALLINT scope, SQLUSMALLINT nullable)
7455{
7456 char *c = NULL, *s = NULL, *t = NULL;
7457 SQLRETURN ret;
7458
7460 if (cat) {
7461 c = uc_to_utf_c(cat, catLen);
7462 if (!c) {
7463 ret = nomem((STMT *) stmt);
7464 goto done;
7465 }
7466 }
7467 if (schema) {
7468 s = uc_to_utf_c(schema, schemaLen);
7469 if (!s) {
7470 ret = nomem((STMT *) stmt);
7471 goto done;
7472 }
7473 }
7474 if (table) {
7475 t = uc_to_utf_c(table, tableLen);
7476 if (!t) {
7477 ret = nomem((STMT *) stmt);
7478 goto done;
7479 }
7480 }
7481 ret = drvspecialcolumns(stmt, id, (SQLCHAR *) c, SQL_NTS,
7482 (SQLCHAR *) s, SQL_NTS, (SQLCHAR *) t, SQL_NTS,
7483 scope, nullable);
7484done:
7485 uc_free(t);
7486 uc_free(s);
7487 uc_free(c);
7489 return ret;
7490}
7491#endif
7492
7497static COL fkeySpec2[] = {
7498 { "SYSTEM", "FOREIGNKEY", "PKTABLE_QUALIFIER", SCOL_VARCHAR, 50 },
7499 { "SYSTEM", "FOREIGNKEY", "PKTABLE_OWNER", SCOL_VARCHAR, 50 },
7500 { "SYSTEM", "FOREIGNKEY", "PKTABLE_NAME", SCOL_VARCHAR, 255 },
7501 { "SYSTEM", "FOREIGNKEY", "PKCOLUMN_NAME", SCOL_VARCHAR, 255 },
7502 { "SYSTEM", "FOREIGNKEY", "FKTABLE_QUALIFIER", SCOL_VARCHAR, 50 },
7503 { "SYSTEM", "FOREIGNKEY", "FKTABLE_OWNER", SCOL_VARCHAR, 50 },
7504 { "SYSTEM", "FOREIGNKEY", "FKTABLE_NAME", SCOL_VARCHAR, 255 },
7505 { "SYSTEM", "FOREIGNKEY", "FKCOLUMN_NAME", SCOL_VARCHAR, 255 },
7506 { "SYSTEM", "FOREIGNKEY", "KEY_SEQ", SQL_SMALLINT, 5 },
7507 { "SYSTEM", "FOREIGNKEY", "UPDATE_RULE", SQL_SMALLINT, 5 },
7508 { "SYSTEM", "FOREIGNKEY", "DELETE_RULE", SQL_SMALLINT, 5 },
7509 { "SYSTEM", "FOREIGNKEY", "FK_NAME", SCOL_VARCHAR, 255 },
7510 { "SYSTEM", "FOREIGNKEY", "PK_NAME", SCOL_VARCHAR, 255 },
7511 { "SYSTEM", "FOREIGNKEY", "DEFERRABILITY", SQL_SMALLINT, 5 }
7512};
7513
7514static COL fkeySpec3[] = {
7515 { "SYSTEM", "FOREIGNKEY", "PKTABLE_CAT", SCOL_VARCHAR, 50 },
7516 { "SYSTEM", "FOREIGNKEY", "PKTABLE_SCHEM", SCOL_VARCHAR, 50 },
7517 { "SYSTEM", "FOREIGNKEY", "PKTABLE_NAME", SCOL_VARCHAR, 255 },
7518 { "SYSTEM", "FOREIGNKEY", "PKCOLUMN_NAME", SCOL_VARCHAR, 255 },
7519 { "SYSTEM", "FOREIGNKEY", "FKTABLE_CAT", SCOL_VARCHAR, 50 },
7520 { "SYSTEM", "FOREIGNKEY", "FKTABLE_SCHEM", SCOL_VARCHAR, 50 },
7521 { "SYSTEM", "FOREIGNKEY", "FKTABLE_NAME", SCOL_VARCHAR, 255 },
7522 { "SYSTEM", "FOREIGNKEY", "FKCOLUMN_NAME", SCOL_VARCHAR, 255 },
7523 { "SYSTEM", "FOREIGNKEY", "KEY_SEQ", SQL_SMALLINT, 5 },
7524 { "SYSTEM", "FOREIGNKEY", "UPDATE_RULE", SQL_SMALLINT, 5 },
7525 { "SYSTEM", "FOREIGNKEY", "DELETE_RULE", SQL_SMALLINT, 5 },
7526 { "SYSTEM", "FOREIGNKEY", "FK_NAME", SCOL_VARCHAR, 255 },
7527 { "SYSTEM", "FOREIGNKEY", "PK_NAME", SCOL_VARCHAR, 255 },
7528 { "SYSTEM", "FOREIGNKEY", "DEFERRABILITY", SQL_SMALLINT, 5 }
7529};
7530
7549static SQLRETURN SQL_API
7551 SQLCHAR *PKcatalog, SQLSMALLINT PKcatalogLen,
7552 SQLCHAR *PKschema, SQLSMALLINT PKschemaLen,
7553 SQLCHAR *PKtable, SQLSMALLINT PKtableLen,
7554 SQLCHAR *FKcatalog, SQLSMALLINT FKcatalogLen,
7555 SQLCHAR *FKschema, SQLSMALLINT FKschemaLen,
7556 SQLCHAR *FKtable, SQLSMALLINT FKtableLen)
7557{
7558 STMT *s;
7559 DBC *d;
7560 SQLRETURN sret;
7561 int i, asize, ret, nrows, ncols, offs, namec, seqc, fromc, toc;
7562 int onu, ond;
7563 PTRDIFF_T size;
7564 char **rowp, *errp = NULL, *sql, pname[512], fname[512];
7565
7567 fkeySpec3, array_size(fkeySpec3), &asize);
7568 if (sret != SQL_SUCCESS) {
7569 return sret;
7570 }
7571 s = (STMT *) stmt;
7572 sret = starttran(s);
7573 if (sret != SQL_SUCCESS) {
7574 return sret;
7575 }
7576 d = (DBC *) s->dbc;
7577 if ((!PKtable || PKtable[0] == '\0' || PKtable[0] == '%') &&
7578 (!FKtable || FKtable[0] == '\0' || FKtable[0] == '%')) {
7579 setstat(s, -1, "need table name", (*s->ov3) ? "HY000" : "S1000");
7580 return SQL_ERROR;
7581 }
7582 size = 0;
7583 if (PKtable) {
7584 if (PKtableLen == SQL_NTS) {
7585 size = sizeof (pname) - 1;
7586 } else {
7587 size = min(sizeof (pname) - 1, PKtableLen);
7588 }
7589 strncpy(pname, (char *) PKtable, size);
7590 }
7591 pname[size] = '\0';
7592 size = 0;
7593 if (FKtable) {
7594
7595 if (FKtableLen == SQL_NTS) {
7596 size = sizeof (fname) - 1;
7597 } else {
7598 size = min(sizeof (fname) - 1, FKtableLen);
7599 }
7600 strncpy(fname, (char *) FKtable, size);
7601 }
7602 fname[size] = '\0';
7603 if (fname[0] != '\0') {
7604 int plen;
7605
7606 ret = SQLITE_ERROR;
7607 sql = sqlite3_mprintf("PRAGMA foreign_key_list(%Q)", fname);
7608 if (sql) {
7609 dbtraceapi(d, "sqlite3_get_table", sql);
7610 ret = sqlite3_get_table(d->sqlite, sql, &rowp,
7611 &nrows, &ncols, &errp);
7612 sqlite3_free(sql);
7613 }
7614 if (ret != SQLITE_OK) {
7615 setstat(s, ret, "%s (%d)", (*s->ov3) ? "HY000" : "S1000",
7616 errp ? errp : "unknown error", ret);
7617 if (errp) {
7618 sqlite3_free(errp);
7619 errp = NULL;
7620 }
7621 return SQL_ERROR;
7622 }
7623 if (errp) {
7624 sqlite3_free(errp);
7625 errp = NULL;
7626 }
7627 if (ncols * nrows <= 0) {
7628nodata:
7629 sqlite3_free_table(rowp);
7630 return SQL_SUCCESS;
7631 }
7632 size = 0;
7633 namec = findcol(rowp, ncols, "table");
7634 seqc = findcol(rowp, ncols, "seq");
7635 fromc = findcol(rowp, ncols, "from");
7636 toc = findcol(rowp, ncols, "to");
7637 onu = findcol(rowp, ncols, "on_update");
7638 ond = findcol(rowp, ncols, "on_delete");
7639 if (namec < 0 || seqc < 0 || fromc < 0 || toc < 0) {
7640 goto nodata;
7641 }
7642 plen = strlen(pname);
7643 for (i = 1; i <= nrows; i++) {
7644 char *ptab = unquote(rowp[i * ncols + namec]);
7645
7646 if (plen && ptab) {
7647 int len = strlen(ptab);
7648
7649 if (plen != len || strncasecmp(pname, ptab, plen) != 0) {
7650 continue;
7651 }
7652 }
7653 size++;
7654 }
7655 if (size == 0) {
7656 goto nodata;
7657 }
7658 s->nrows = size;
7659 size = (size + 1) * asize;
7660 s->rows = xmalloc((size + 1) * sizeof (char *));
7661 if (!s->rows) {
7662 s->nrows = 0;
7663 return nomem(s);
7664 }
7665 s->rows[0] = (char *) size;
7666 s->rows += 1;
7667 memset(s->rows, 0, sizeof (char *) * size);
7668 s->rowfree = freerows;
7669 offs = 0;
7670 for (i = 1; i <= nrows; i++) {
7671 int pos = 0, roffs = (offs + 1) * s->ncols;
7672 char *ptab = rowp[i * ncols + namec];
7673 char buf[32];
7674
7675 if (plen && ptab) {
7676 int len = strlen(ptab);
7677
7678 if (plen != len || strncasecmp(pname, ptab, plen) != 0) {
7679 continue;
7680 }
7681 }
7682#if defined(_WIN32) || defined(_WIN64)
7683 s->rows[roffs + 0] = xstrdup(d->xcelqrx ? "main" : "");
7684 s->rows[roffs + 1] = xstrdup("");
7685#else
7686 s->rows[roffs + 0] = xstrdup("");
7687 s->rows[roffs + 1] = xstrdup("");
7688#endif
7689 s->rows[roffs + 2] = xstrdup(ptab);
7690 s->rows[roffs + 3] = xstrdup(rowp[i * ncols + toc]);
7691 s->rows[roffs + 4] = xstrdup("");
7692 s->rows[roffs + 5] = xstrdup("");
7693 s->rows[roffs + 6] = xstrdup(fname);
7694 s->rows[roffs + 7] = xstrdup(rowp[i * ncols + fromc]);
7695 sscanf(rowp[i * ncols + seqc], "%d", &pos);
7696 sprintf(buf, "%d", pos + 1);
7697 s->rows[roffs + 8] = xstrdup(buf);
7698 if (onu < 0) {
7699 s->rows[roffs + 9] = xstrdup(stringify(SQL_NO_ACTION));
7700 } else {
7701 if (strcmp(rowp[i * ncols + onu], "SET NULL") == 0) {
7702 s->rows[roffs + 9] = xstrdup(stringify(SQL_SET_NULL));
7703 } else if (strcmp(rowp[i * ncols + onu], "SET DEFAULT") == 0) {
7704 s->rows[roffs + 9] = xstrdup(stringify(SQL_SET_DEFAULT));
7705 } else if (strcmp(rowp[i * ncols + onu], "CASCADE") == 0) {
7706 s->rows[roffs + 9] = xstrdup(stringify(SQL_CASCADE));
7707 } else if (strcmp(rowp[i * ncols + onu], "RESTRICT") == 0) {
7708 s->rows[roffs + 9] = xstrdup(stringify(SQL_RESTRICT));
7709 } else {
7710 s->rows[roffs + 9] = xstrdup(stringify(SQL_NO_ACTION));
7711 }
7712 }
7713 if (ond < 0) {
7714 s->rows[roffs + 10] = xstrdup(stringify(SQL_NO_ACTION));
7715 } else {
7716 if (strcmp(rowp[i * ncols + ond], "SET NULL") == 0) {
7717 s->rows[roffs + 10] = xstrdup(stringify(SQL_SET_NULL));
7718 } else if (strcmp(rowp[i * ncols + ond], "SET DEFAULT") == 0) {
7719 s->rows[roffs + 10] = xstrdup(stringify(SQL_SET_DEFAULT));
7720 } else if (strcmp(rowp[i * ncols + ond], "CASCADE") == 0) {
7721 s->rows[roffs + 10] = xstrdup(stringify(SQL_CASCADE));
7722 } else if (strcmp(rowp[i * ncols + ond], "RESTRICT") == 0) {
7723 s->rows[roffs + 10] = xstrdup(stringify(SQL_RESTRICT));
7724 } else {
7725 s->rows[roffs + 10] = xstrdup(stringify(SQL_NO_ACTION));
7726 }
7727 }
7728 s->rows[roffs + 11] = NULL;
7729 s->rows[roffs + 12] = NULL;
7730 s->rows[roffs + 13] = xstrdup(stringify(SQL_NOT_DEFERRABLE));
7731 offs++;
7732 }
7733 sqlite3_free_table(rowp);
7734 } else {
7735 int nnrows, nncols, plen = strlen(pname);
7736 char **rowpp;
7737
7738 sql = "select name from sqlite_master where type='table'";
7739 dbtraceapi(d, "sqlite3_get_table", sql);
7740 ret = sqlite3_get_table(d->sqlite, sql, &rowp, &nrows, &ncols, &errp);
7741 if (ret != SQLITE_OK) {
7742 setstat(s, ret, "%s (%d)", (*s->ov3) ? "HY000" : "S1000",
7743 errp ? errp : "unknown error", ret);
7744 if (errp) {
7745 sqlite3_free(errp);
7746 errp = NULL;
7747 }
7748 return SQL_ERROR;
7749 }
7750 if (errp) {
7751 sqlite3_free(errp);
7752 errp = NULL;
7753 }
7754 if (ncols * nrows <= 0) {
7755 goto nodata;
7756 }
7757 size = 0;
7758 for (i = 1; i <= nrows; i++) {
7759 int k;
7760
7761 if (!rowp[i]) {
7762 continue;
7763 }
7764 rowpp = NULL;
7765 ret = SQLITE_ERROR;
7766 sql = sqlite3_mprintf("PRAGMA foreign_key_list(%Q)", rowp[i]);
7767 if (sql) {
7768 dbtraceapi(d, "sqlite3_get_table", sql);
7769 ret = sqlite3_get_table(d->sqlite, sql, &rowpp,
7770 &nnrows, &nncols, NULL);
7771 sqlite3_free(sql);
7772 }
7773 if (ret != SQLITE_OK || nncols * nnrows <= 0) {
7774 sqlite3_free_table(rowpp);
7775 continue;
7776 }
7777 namec = findcol(rowpp, nncols, "table");
7778 seqc = findcol(rowpp, nncols, "seq");
7779 fromc = findcol(rowpp, nncols, "from");
7780 toc = findcol(rowpp, nncols, "to");
7781 if (namec < 0 || seqc < 0 || fromc < 0 || toc < 0) {
7782 sqlite3_free_table(rowpp);
7783 continue;
7784 }
7785 for (k = 1; k <= nnrows; k++) {
7786 char *ptab = unquote(rowpp[k * nncols + namec]);
7787
7788 if (plen && ptab) {
7789 int len = strlen(ptab);
7790
7791 if (len != plen || strncasecmp(pname, ptab, plen) != 0) {
7792 continue;
7793 }
7794 }
7795 size++;
7796 }
7797 sqlite3_free_table(rowpp);
7798 }
7799 if (size == 0) {
7800 goto nodata;
7801 }
7802 s->nrows = size;
7803 size = (size + 1) * asize;
7804 s->rows = xmalloc((size + 1) * sizeof (char *));
7805 if (!s->rows) {
7806 s->nrows = 0;
7807 return nomem(s);
7808 }
7809 s->rows[0] = (char *) size;
7810 s->rows += 1;
7811 memset(s->rows, 0, sizeof (char *) * size);
7812 s->rowfree = freerows;
7813 offs = 0;
7814 for (i = 1; i <= nrows; i++) {
7815 int k;
7816
7817 if (!rowp[i]) {
7818 continue;
7819 }
7820 rowpp = NULL;
7821 ret = SQLITE_ERROR;
7822 sql = sqlite3_mprintf("PRAGMA foreign_key_list(%Q)", rowp[i]);
7823 if (sql) {
7824 dbtraceapi(d, "sqlite3_get_table", sql);
7825 ret = sqlite3_get_table(d->sqlite, sql, &rowpp,
7826 &nnrows, &nncols, NULL);
7827 sqlite3_free(sql);
7828 }
7829 if (ret != SQLITE_OK || nncols * nnrows <= 0) {
7830 sqlite3_free_table(rowpp);
7831 continue;
7832 }
7833 namec = findcol(rowpp, nncols, "table");
7834 seqc = findcol(rowpp, nncols, "seq");
7835 fromc = findcol(rowpp, nncols, "from");
7836 toc = findcol(rowpp, nncols, "to");
7837 onu = findcol(rowpp, nncols, "on_update");
7838 ond = findcol(rowpp, nncols, "on_delete");
7839 if (namec < 0 || seqc < 0 || fromc < 0 || toc < 0) {
7840 sqlite3_free_table(rowpp);
7841 continue;
7842 }
7843 for (k = 1; k <= nnrows; k++) {
7844 int pos = 0, roffs = (offs + 1) * s->ncols;
7845 char *ptab = unquote(rowpp[k * nncols + namec]);
7846 char buf[32];
7847
7848 if (plen && ptab) {
7849 int len = strlen(ptab);
7850
7851 if (len != plen || strncasecmp(pname, ptab, plen) != 0) {
7852 continue;
7853 }
7854 }
7855#if defined(_WIN32) || defined(_WIN64)
7856 s->rows[roffs + 0] = xstrdup(d->xcelqrx ? "main" : "");
7857 s->rows[roffs + 1] = xstrdup("");
7858#else
7859 s->rows[roffs + 0] = xstrdup("");
7860 s->rows[roffs + 1] = xstrdup("");
7861#endif
7862 s->rows[roffs + 2] = xstrdup(ptab);
7863 s->rows[roffs + 3] = xstrdup(rowpp[k * nncols + toc]);
7864 s->rows[roffs + 4] = xstrdup("");
7865 s->rows[roffs + 5] = xstrdup("");
7866 s->rows[roffs + 6] = xstrdup(rowp[i]);
7867 s->rows[roffs + 7] = xstrdup(rowpp[k * nncols + fromc]);
7868 sscanf(rowpp[k * nncols + seqc], "%d", &pos);
7869 sprintf(buf, "%d", pos + 1);
7870 s->rows[roffs + 8] = xstrdup(buf);
7871 if (onu < 0) {
7872 s->rows[roffs + 9] = xstrdup(stringify(SQL_NO_ACTION));
7873 } else {
7874 if (strcmp(rowpp[k * nncols + onu], "SET NULL") == 0) {
7875 s->rows[roffs + 9] = xstrdup(stringify(SQL_SET_NULL));
7876 } else if (strcmp(rowpp[k * nncols + onu], "SET DEFAULT")
7877 == 0) {
7878 s->rows[roffs + 9] =
7879 xstrdup(stringify(SQL_SET_DEFAULT));
7880 } else if (strcmp(rowpp[k * nncols + onu], "CASCADE")
7881 == 0) {
7882 s->rows[roffs + 9] = xstrdup(stringify(SQL_CASCADE));
7883 } else if (strcmp(rowpp[k * nncols + onu], "RESTRICT")
7884 == 0) {
7885 s->rows[roffs + 9] = xstrdup(stringify(SQL_RESTRICT));
7886 } else {
7887 s->rows[roffs + 9] =
7888 xstrdup(stringify(SQL_NO_ACTION));
7889 }
7890 }
7891 if (ond < 0) {
7892 s->rows[roffs + 10] = xstrdup(stringify(SQL_NO_ACTION));
7893 } else {
7894 if (strcmp(rowpp[k * nncols + ond], "SET NULL") == 0) {
7895 s->rows[roffs + 10] = xstrdup(stringify(SQL_SET_NULL));
7896 } else if (strcmp(rowpp[k * nncols + ond], "SET DEFAULT")
7897 == 0) {
7898 s->rows[roffs + 10] =
7899 xstrdup(stringify(SQL_SET_DEFAULT));
7900 } else if (strcmp(rowpp[k * nncols + ond], "CASCADE")
7901 == 0) {
7902 s->rows[roffs + 10] = xstrdup(stringify(SQL_CASCADE));
7903 } else if (strcmp(rowpp[k * nncols + ond], "RESTRICT")
7904 == 0) {
7905 s->rows[roffs + 10] = xstrdup(stringify(SQL_RESTRICT));
7906 } else {
7907 s->rows[roffs + 10] =
7908 xstrdup(stringify(SQL_NO_ACTION));
7909 }
7910 }
7911 s->rows[roffs + 11] = NULL;
7912 s->rows[roffs + 12] = NULL;
7913 s->rows[roffs + 13] = xstrdup(stringify(SQL_NOT_DEFERRABLE));
7914 offs++;
7915 }
7916 sqlite3_free_table(rowpp);
7917 }
7918 sqlite3_free_table(rowp);
7919 }
7920 return SQL_SUCCESS;
7921}
7922
7923#ifndef WINTERFACE
7942SQLRETURN SQL_API
7943SQLForeignKeys(SQLHSTMT stmt,
7944 SQLCHAR *PKcatalog, SQLSMALLINT PKcatalogLen,
7945 SQLCHAR *PKschema, SQLSMALLINT PKschemaLen,
7946 SQLCHAR *PKtable, SQLSMALLINT PKtableLen,
7947 SQLCHAR *FKcatalog, SQLSMALLINT FKcatalogLen,
7948 SQLCHAR *FKschema, SQLSMALLINT FKschemaLen,
7949 SQLCHAR *FKtable, SQLSMALLINT FKtableLen)
7950{
7951#if defined(_WIN32) || defined(_WIN64)
7952 char *pc = NULL, *ps = NULL, *pt = NULL;
7953 char *fc = NULL, *fs = NULL, *ft = NULL;
7954#endif
7955 SQLRETURN ret;
7956
7958#if defined(_WIN32) || defined(_WIN64)
7959 if (!((STMT *) stmt)->oemcp[0]) {
7960 ret = drvforeignkeys(stmt,
7961 PKcatalog, PKcatalogLen,
7962 PKschema, PKschemaLen, PKtable, PKtableLen,
7963 FKcatalog, FKcatalogLen,
7964 FKschema, FKschemaLen,
7965 FKtable, FKtableLen);
7966 goto done2;
7967 }
7968 if (PKcatalog) {
7969 pc = wmb_to_utf_c((char *) PKcatalog, PKcatalogLen);
7970 if (!pc) {
7971 ret = nomem((STMT *) stmt);
7972 goto done;
7973 }
7974 }
7975 if (PKschema) {
7976 ps = wmb_to_utf_c((char *) PKschema, PKschemaLen);
7977 if (!ps) {
7978 ret = nomem((STMT *) stmt);
7979 goto done;
7980 }
7981 }
7982 if (PKtable) {
7983 pt = wmb_to_utf_c((char *) PKtable, PKtableLen);
7984 if (!pt) {
7985 ret = nomem((STMT *) stmt);
7986 goto done;
7987 }
7988 }
7989 if (FKcatalog) {
7990 fc = wmb_to_utf_c((char *) FKcatalog, FKcatalogLen);
7991 if (!fc) {
7992 ret = nomem((STMT *) stmt);
7993 goto done;
7994 }
7995 }
7996 if (FKschema) {
7997 fs = wmb_to_utf_c((char *) FKschema, FKschemaLen);
7998 if (!fs) {
7999 ret = nomem((STMT *) stmt);
8000 goto done;
8001 }
8002 }
8003 if (FKtable) {
8004 ft = wmb_to_utf_c((char *) FKtable, FKtableLen);
8005 if (!ft) {
8006 ret = nomem((STMT *) stmt);
8007 goto done;
8008 }
8009 }
8010 ret = drvforeignkeys(stmt, (SQLCHAR *) pc, SQL_NTS,
8011 (SQLCHAR *) ps, SQL_NTS, (SQLCHAR *) pt, SQL_NTS,
8012 (SQLCHAR *) fc, SQL_NTS, (SQLCHAR *) fs, SQL_NTS,
8013 (SQLCHAR *) ft, SQL_NTS);
8014#else
8015 ret = drvforeignkeys(stmt,
8016 PKcatalog, PKcatalogLen,
8017 PKschema, PKschemaLen, PKtable, PKtableLen,
8018 FKcatalog, FKcatalogLen,
8019 FKschema, FKschemaLen,
8020 FKtable, FKtableLen);
8021#endif
8022#if defined(_WIN32) || defined(_WIN64)
8023done:
8024 uc_free(ft);
8025 uc_free(fs);
8026 uc_free(fc);
8027 uc_free(pt);
8028 uc_free(ps);
8029 uc_free(pc);
8030done2:
8031 ;
8032#endif
8034 return ret;
8035}
8036#endif
8037
8038#ifdef WINTERFACE
8057SQLRETURN SQL_API
8059 SQLWCHAR *PKcatalog, SQLSMALLINT PKcatalogLen,
8060 SQLWCHAR *PKschema, SQLSMALLINT PKschemaLen,
8061 SQLWCHAR *PKtable, SQLSMALLINT PKtableLen,
8062 SQLWCHAR *FKcatalog, SQLSMALLINT FKcatalogLen,
8063 SQLWCHAR *FKschema, SQLSMALLINT FKschemaLen,
8064 SQLWCHAR *FKtable, SQLSMALLINT FKtableLen)
8065{
8066 char *pc = NULL, *ps = NULL, *pt = NULL;
8067 char *fc = NULL, *fs = NULL, *ft = NULL;
8068 SQLRETURN ret;
8069
8071 if (PKcatalog) {
8072 pc = uc_to_utf_c(PKcatalog, PKcatalogLen);
8073 if (!pc) {
8074 ret = nomem((STMT *) stmt);
8075 goto done;
8076 }
8077 }
8078 if (PKschema) {
8079 ps = uc_to_utf_c(PKschema, PKschemaLen);
8080 if (!ps) {
8081 ret = nomem((STMT *) stmt);
8082 goto done;
8083 }
8084 }
8085 if (PKtable) {
8086 pt = uc_to_utf_c(PKtable, PKtableLen);
8087 if (!pt) {
8088 ret = nomem((STMT *) stmt);
8089 goto done;
8090 }
8091 }
8092 if (FKcatalog) {
8093 fc = uc_to_utf_c(FKcatalog, FKcatalogLen);
8094 if (!fc) {
8095 ret = nomem((STMT *) stmt);
8096 goto done;
8097 }
8098 }
8099 if (FKschema) {
8100 fs = uc_to_utf_c(FKschema, FKschemaLen);
8101 if (!fs) {
8102 ret = nomem((STMT *) stmt);
8103 goto done;
8104 }
8105 }
8106 if (FKtable) {
8107 ft = uc_to_utf_c(FKtable, FKtableLen);
8108 if (!ft) {
8109 ret = nomem((STMT *) stmt);
8110 goto done;
8111 }
8112 }
8113 ret = drvforeignkeys(stmt, (SQLCHAR *) pc, SQL_NTS,
8114 (SQLCHAR *) ps, SQL_NTS, (SQLCHAR *) pt, SQL_NTS,
8115 (SQLCHAR *) fc, SQL_NTS, (SQLCHAR *) fs, SQL_NTS,
8116 (SQLCHAR *) ft, SQL_NTS);
8117done:
8118 uc_free(ft);
8119 uc_free(fs);
8120 uc_free(fc);
8121 uc_free(pt);
8122 uc_free(ps);
8123 uc_free(pc);
8125 return ret;
8126}
8127#endif
8128
8135static SQLRETURN
8137{
8138 int ret = SQL_SUCCESS, rc, busy_count = 0;
8139 char *errp = NULL;
8140 DBC *d = (DBC *) s->dbc;
8141
8142 if (!d->autocommit && !d->intrans && !d->trans_disable) {
8143begin_again:
8144 rc = sqlite3_exec(d->sqlite, "BEGIN TRANSACTION", NULL, NULL, &errp);
8145 if (rc == SQLITE_BUSY) {
8146 if (busy_handler((void *) d, ++busy_count)) {
8147 if (errp) {
8148 sqlite3_free(errp);
8149 errp = NULL;
8150 }
8151 goto begin_again;
8152 }
8153 }
8154 dbtracerc(d, rc, errp);
8155 if (rc != SQLITE_OK) {
8156 setstat(s, rc, "%s (%d)", (*s->ov3) ? "HY000" : "S1000",
8157 errp ? errp : "unknown error", rc);
8158 ret = SQL_ERROR;
8159 } else {
8160 d->intrans = 1;
8161 }
8162 if (errp) {
8163 sqlite3_free(errp);
8164 errp = NULL;
8165 }
8166 }
8167 return ret;
8168}
8169
8178static SQLRETURN
8179endtran(DBC *d, SQLSMALLINT comptype, int force)
8180{
8181 int ret, busy_count = 0;
8182 char *sql, *errp = NULL;
8183
8184 if (!d->sqlite) {
8185 setstatd(d, -1, "not connected", (*d->ov3) ? "HY000" : "S1000");
8186 return SQL_ERROR;
8187 }
8188 if ((!force && d->autocommit) || !d->intrans) {
8189 return SQL_SUCCESS;
8190 }
8191 switch (comptype) {
8192 case SQL_COMMIT:
8193 sql = "COMMIT TRANSACTION";
8194 goto doit;
8195 case SQL_ROLLBACK:
8196 sql = "ROLLBACK TRANSACTION";
8197 doit:
8198 ret = sqlite3_exec(d->sqlite, sql, NULL, NULL, &errp);
8199 dbtracerc(d, ret, errp);
8200 if (ret == SQLITE_BUSY && busy_count < 10) {
8201 if (busy_handler((void *) d, ++busy_count)) {
8202 if (errp) {
8203 sqlite3_free(errp);
8204 errp = NULL;
8205 }
8206 goto doit;
8207 }
8208 }
8209 if (ret != SQLITE_OK) {
8210 setstatd(d, ret, "%s", (*d->ov3) ? "HY000" : "S1000",
8211 errp ? errp : "transaction failed");
8212 if (errp) {
8213 sqlite3_free(errp);
8214 errp = NULL;
8215 }
8216 return SQL_ERROR;
8217 }
8218 if (errp) {
8219 sqlite3_free(errp);
8220 errp = NULL;
8221 }
8222 d->intrans = 0;
8223 return SQL_SUCCESS;
8224 }
8225 setstatd(d, -1, "invalid completion type", (*d->ov3) ? "HY000" : "S1000");
8226 return SQL_ERROR;
8227}
8228
8237static SQLRETURN
8238drvendtran(SQLSMALLINT type, SQLHANDLE handle, SQLSMALLINT comptype)
8239{
8240 DBC *dbc = NULL;
8241 int fail = 0;
8242 SQLRETURN ret;
8243#if defined(_WIN32) || defined(_WIN64)
8244 ENV *env;
8245#endif
8246
8247 switch (type) {
8248 case SQL_HANDLE_DBC:
8249 HDBC_LOCK((SQLHDBC) handle);
8250 if (handle == SQL_NULL_HDBC) {
8251 return SQL_INVALID_HANDLE;
8252 }
8253 dbc = (DBC *) handle;
8254 ret = endtran(dbc, comptype, 0);
8255 HDBC_UNLOCK((SQLHDBC) handle);
8256 return ret;
8257 case SQL_HANDLE_ENV:
8258 if (handle == SQL_NULL_HENV) {
8259 return SQL_INVALID_HANDLE;
8260 }
8261#if defined(_WIN32) || defined(_WIN64)
8262 env = (ENV *) handle;
8263 if (env->magic != ENV_MAGIC) {
8264 return SQL_INVALID_HANDLE;
8265 }
8266 EnterCriticalSection(&env->cs);
8267#endif
8268 dbc = ((ENV *) handle)->dbcs;
8269 while (dbc) {
8270 HDBC_LOCK((SQLHDBC) dbc);
8271 ret = endtran(dbc, comptype, 0);
8272 HDBC_UNLOCK((SQLHDBC) dbc);
8273 if (ret != SQL_SUCCESS) {
8274 fail++;
8275 }
8276 dbc = dbc->next;
8277 }
8278#if defined(_WIN32) || defined(_WIN64)
8279 LeaveCriticalSection(&env->cs);
8280#endif
8281 return fail ? SQL_ERROR : SQL_SUCCESS;
8282 }
8283 return SQL_INVALID_HANDLE;
8284}
8285
8294SQLRETURN SQL_API
8295SQLEndTran(SQLSMALLINT type, SQLHANDLE handle, SQLSMALLINT comptype)
8296{
8297 return drvendtran(type, handle, comptype);
8298}
8299
8308SQLRETURN SQL_API
8309SQLTransact(SQLHENV env, SQLHDBC dbc, SQLUSMALLINT type)
8310{
8311 if (dbc != SQL_NULL_HDBC) {
8312 return drvendtran(SQL_HANDLE_DBC, (SQLHANDLE) dbc, type);
8313 }
8314 return drvendtran(SQL_HANDLE_ENV, (SQLHANDLE) env, type);
8315}
8316
8321SQLRETURN SQL_API
8322SQLCopyDesc(SQLHDESC source, SQLHDESC target)
8323{
8324 return SQL_ERROR;
8325}
8326
8327#ifndef WINTERFACE
8339SQLRETURN SQL_API
8340SQLNativeSql(SQLHSTMT stmt, SQLCHAR *sqlin, SQLINTEGER sqlinLen,
8341 SQLCHAR *sql, SQLINTEGER sqlMax, SQLINTEGER *sqlLen)
8342{
8343 int outLen = 0;
8344 SQLRETURN ret = SQL_SUCCESS;
8345
8347 if (sqlinLen == SQL_NTS) {
8348 sqlinLen = strlen((char *) sqlin);
8349 }
8350 if (sql) {
8351 if (sqlMax > 0) {
8352 strncpy((char *) sql, (char *) sqlin, sqlMax - 1);
8353 sqlin[sqlMax - 1] = '\0';
8354 outLen = min(sqlMax - 1, sqlinLen);
8355 }
8356 } else {
8357 outLen = sqlinLen;
8358 }
8359 if (sqlLen) {
8360 *sqlLen = outLen;
8361 }
8362 if (sql && outLen < sqlinLen) {
8363 setstat((STMT *) stmt, -1, "data right truncated", "01004");
8364 ret = SQL_SUCCESS_WITH_INFO;
8365 }
8367 return ret;
8368}
8369#endif
8370
8371#ifdef WINTERFACE
8383SQLRETURN SQL_API
8384SQLNativeSqlW(SQLHSTMT stmt, SQLWCHAR *sqlin, SQLINTEGER sqlinLen,
8385 SQLWCHAR *sql, SQLINTEGER sqlMax, SQLINTEGER *sqlLen)
8386{
8387 int outLen = 0;
8388 SQLRETURN ret = SQL_SUCCESS;
8389
8391 if (sqlinLen == SQL_NTS) {
8392 sqlinLen = uc_strlen(sqlin);
8393 }
8394 if (sql) {
8395 if (sqlMax > 0) {
8396 uc_strncpy(sql, sqlin, sqlMax - 1);
8397 sqlin[sqlMax - 1] = 0;
8398 outLen = min(sqlMax - 1, sqlinLen);
8399 }
8400 } else {
8401 outLen = sqlinLen;
8402 }
8403 if (sqlLen) {
8404 *sqlLen = outLen;
8405 }
8406 if (sql && outLen < sqlinLen) {
8407 setstat((STMT *) stmt, -1, "data right truncated", "01004");
8408 ret = SQL_SUCCESS_WITH_INFO;
8409 }
8411 return ret;
8412}
8413#endif
8414
8419static COL procSpec2[] = {
8420 { "SYSTEM", "PROCEDURE", "PROCEDURE_QUALIFIER", SCOL_VARCHAR, 50 },
8421 { "SYSTEM", "PROCEDURE", "PROCEDURE_OWNER", SCOL_VARCHAR, 50 },
8422 { "SYSTEM", "PROCEDURE", "PROCEDURE_NAME", SCOL_VARCHAR, 255 },
8423 { "SYSTEM", "PROCEDURE", "NUM_INPUT_PARAMS", SQL_SMALLINT, 5 },
8424 { "SYSTEM", "PROCEDURE", "NUM_OUTPUT_PARAMS", SQL_SMALLINT, 5 },
8425 { "SYSTEM", "PROCEDURE", "NUM_RESULT_SETS", SQL_SMALLINT, 5 },
8426 { "SYSTEM", "PROCEDURE", "REMARKS", SCOL_VARCHAR, 255 },
8427 { "SYSTEM", "PROCEDURE", "PROCEDURE_TYPE", SQL_SMALLINT, 5 }
8428};
8429
8430static COL procSpec3[] = {
8431 { "SYSTEM", "PROCEDURE", "PROCEDURE_CAT", SCOL_VARCHAR, 50 },
8432 { "SYSTEM", "PROCEDURE", "PROCEDURE_SCHEM", SCOL_VARCHAR, 50 },
8433 { "SYSTEM", "PROCEDURE", "PROCEDURE_NAME", SCOL_VARCHAR, 255 },
8434 { "SYSTEM", "PROCEDURE", "NUM_INPUT_PARAMS", SQL_SMALLINT, 5 },
8435 { "SYSTEM", "PROCEDURE", "NUM_OUTPUT_PARAMS", SQL_SMALLINT, 5 },
8436 { "SYSTEM", "PROCEDURE", "NUM_RESULT_SETS", SQL_SMALLINT, 5 },
8437 { "SYSTEM", "PROCEDURE", "REMARKS", SCOL_VARCHAR, 255 },
8438 { "SYSTEM", "PROCEDURE", "PROCEDURE_TYPE", SQL_SMALLINT, 5 }
8439};
8440
8441#ifndef WINTERFACE
8454SQLRETURN SQL_API
8455SQLProcedures(SQLHSTMT stmt,
8456 SQLCHAR *catalog, SQLSMALLINT catalogLen,
8457 SQLCHAR *schema, SQLSMALLINT schemaLen,
8458 SQLCHAR *proc, SQLSMALLINT procLen)
8459{
8460 SQLRETURN ret;
8461
8466 return ret;
8467}
8468#endif
8469
8470#ifdef WINTERFACE
8483SQLRETURN SQL_API
8485 SQLWCHAR *catalog, SQLSMALLINT catalogLen,
8486 SQLWCHAR *schema, SQLSMALLINT schemaLen,
8487 SQLWCHAR *proc, SQLSMALLINT procLen)
8488{
8489 SQLRETURN ret;
8490
8495 return ret;
8496}
8497#endif
8498
8503static COL procColSpec2[] = {
8504 { "SYSTEM", "PROCCOL", "PROCEDURE_QUALIFIER", SCOL_VARCHAR, 50 },
8505 { "SYSTEM", "PROCCOL", "PROCEDURE_OWNER", SCOL_VARCHAR, 50 },
8506 { "SYSTEM", "PROCCOL", "PROCEDURE_NAME", SCOL_VARCHAR, 255 },
8507 { "SYSTEM", "PROCCOL", "COLUMN_NAME", SCOL_VARCHAR, 255 },
8508 { "SYSTEM", "PROCCOL", "COLUMN_TYPE", SQL_SMALLINT, 5 },
8509 { "SYSTEM", "PROCCOL", "DATA_TYPE", SQL_SMALLINT, 5 },
8510 { "SYSTEM", "PROCCOL", "TYPE_NAME", SCOL_VARCHAR, 50 },
8511 { "SYSTEM", "PROCCOL", "PRECISION", SQL_INTEGER, 10 },
8512 { "SYSTEM", "PROCCOL", "LENGTH", SQL_INTEGER, 10 },
8513 { "SYSTEM", "PROCCOL", "SCALE", SQL_SMALLINT, 5 },
8514 { "SYSTEM", "PROCCOL", "RADIX", SQL_SMALLINT, 5 },
8515 { "SYSTEM", "PROCCOL", "NULLABLE", SQL_SMALLINT, 5 },
8516 { "SYSTEM", "PROCCOL", "REMARKS", SCOL_VARCHAR, 50 },
8517 { "SYSTEM", "PROCCOL", "COLUMN_DEF", SCOL_VARCHAR, 50 },
8518 { "SYSTEM", "PROCCOL", "SQL_DATA_TYPE", SQL_SMALLINT, 5 },
8519 { "SYSTEM", "PROCCOL", "SQL_DATETIME_SUB", SQL_SMALLINT, 5 },
8520 { "SYSTEM", "PROCCOL", "CHAR_OCTET_LENGTH", SQL_SMALLINT, 5 },
8521 { "SYSTEM", "PROCCOL", "ORDINAL_POSITION", SQL_SMALLINT, 5 },
8522 { "SYSTEM", "PROCCOL", "IS_NULLABLE", SCOL_VARCHAR, 50 }
8523};
8524
8525static COL procColSpec3[] = {
8526 { "SYSTEM", "PROCCOL", "PROCEDURE_CAT", SCOL_VARCHAR, 50 },
8527 { "SYSTEM", "PROCCOL", "PROCEDURE_SCHEM", SCOL_VARCHAR, 50 },
8528 { "SYSTEM", "PROCCOL", "PROCEDURE_NAME", SCOL_VARCHAR, 255 },
8529 { "SYSTEM", "PROCCOL", "COLUMN_NAME", SCOL_VARCHAR, 255 },
8530 { "SYSTEM", "PROCCOL", "COLUMN_TYPE", SQL_SMALLINT, 5 },
8531 { "SYSTEM", "PROCCOL", "DATA_TYPE", SQL_SMALLINT, 5 },
8532 { "SYSTEM", "PROCCOL", "TYPE_NAME", SCOL_VARCHAR, 50 },
8533 { "SYSTEM", "PROCCOL", "COLUMN_SIZE", SQL_INTEGER, 10 },
8534 { "SYSTEM", "PROCCOL", "BUFFER_LENGTH", SQL_INTEGER, 10 },
8535 { "SYSTEM", "PROCCOL", "DECIMAL_DIGITS", SQL_SMALLINT, 5 },
8536 { "SYSTEM", "PROCCOL", "NUM_PREC_RADIX", SQL_SMALLINT, 5 },
8537 { "SYSTEM", "PROCCOL", "NULLABLE", SQL_SMALLINT, 5 },
8538 { "SYSTEM", "PROCCOL", "REMARKS", SCOL_VARCHAR, 50 },
8539 { "SYSTEM", "PROCCOL", "COLUMN_DEF", SCOL_VARCHAR, 50 },
8540 { "SYSTEM", "PROCCOL", "SQL_DATA_TYPE", SQL_SMALLINT, 5 },
8541 { "SYSTEM", "PROCCOL", "SQL_DATETIME_SUB", SQL_SMALLINT, 5 },
8542 { "SYSTEM", "PROCCOL", "CHAR_OCTET_LENGTH", SQL_SMALLINT, 5 },
8543 { "SYSTEM", "PROCCOL", "ORDINAL_POSITION", SQL_SMALLINT, 5 },
8544 { "SYSTEM", "PROCCOL", "IS_NULLABLE", SCOL_VARCHAR, 50 }
8545};
8546
8547#ifndef WINTERFACE
8562SQLRETURN SQL_API
8563SQLProcedureColumns(SQLHSTMT stmt,
8564 SQLCHAR *catalog, SQLSMALLINT catalogLen,
8565 SQLCHAR *schema, SQLSMALLINT schemaLen,
8566 SQLCHAR *proc, SQLSMALLINT procLen,
8567 SQLCHAR *column, SQLSMALLINT columnLen)
8568{
8569 SQLRETURN ret;
8570
8575 return ret;
8576}
8577#endif
8578
8579#ifdef WINTERFACE
8595SQLRETURN SQL_API
8597 SQLWCHAR *catalog, SQLSMALLINT catalogLen,
8598 SQLWCHAR *schema, SQLSMALLINT schemaLen,
8599 SQLWCHAR *proc, SQLSMALLINT procLen,
8600 SQLWCHAR *column, SQLSMALLINT columnLen)
8601{
8602 SQLRETURN ret;
8603
8608 return ret;
8609}
8610#endif
8611
8622SQLRETURN SQL_API
8623SQLGetEnvAttr(SQLHENV env, SQLINTEGER attr, SQLPOINTER val,
8624 SQLINTEGER len, SQLINTEGER *lenp)
8625{
8626 ENV *e;
8627 SQLRETURN ret = SQL_ERROR;
8628
8629 if (env == SQL_NULL_HENV) {
8630 return SQL_INVALID_HANDLE;
8631 }
8632 e = (ENV *) env;
8633 if (!e || e->magic != ENV_MAGIC) {
8634 return SQL_INVALID_HANDLE;
8635 }
8636#if defined(_WIN32) || defined(_WIN64)
8637 EnterCriticalSection(&e->cs);
8638#endif
8639 switch (attr) {
8640 case SQL_ATTR_CONNECTION_POOLING:
8641 if (val) {
8642 *((SQLINTEGER *) val) = e->pool ?
8643 SQL_CP_ONE_PER_DRIVER : SQL_CP_OFF;
8644 }
8645 if (lenp) {
8646 *lenp = sizeof (SQLINTEGER);
8647 }
8648 ret = SQL_SUCCESS;
8649 break;
8650 case SQL_ATTR_CP_MATCH:
8651 *((SQLINTEGER *) val) = SQL_CP_RELAXED_MATCH;
8652 if (lenp) {
8653 *lenp = sizeof (SQLINTEGER);
8654 }
8655 ret = SQL_SUCCESS;
8656 break;
8657 case SQL_ATTR_OUTPUT_NTS:
8658 if (val) {
8659 *((SQLINTEGER *) val) = SQL_TRUE;
8660 }
8661 if (lenp) {
8662 *lenp = sizeof (SQLINTEGER);
8663 }
8664 ret = SQL_SUCCESS;
8665 break;
8666 case SQL_ATTR_ODBC_VERSION:
8667 if (val) {
8668 *((SQLINTEGER *) val) = e->ov3 ? SQL_OV_ODBC3 : SQL_OV_ODBC2;
8669 }
8670 if (lenp) {
8671 *lenp = sizeof (SQLINTEGER);
8672 }
8673 ret = SQL_SUCCESS;
8674 break;
8675 }
8676#if defined(_WIN32) || defined(_WIN64)
8677 LeaveCriticalSection(&e->cs);
8678#endif
8679 return ret;
8680}
8681
8691SQLRETURN SQL_API
8692SQLSetEnvAttr(SQLHENV env, SQLINTEGER attr, SQLPOINTER val, SQLINTEGER len)
8693{
8694 ENV *e;
8695 SQLRETURN ret = SQL_ERROR;
8696
8697 if (env == SQL_NULL_HENV) {
8698 return SQL_INVALID_HANDLE;
8699 }
8700 e = (ENV *) env;
8701 if (!e || e->magic != ENV_MAGIC) {
8702 return SQL_INVALID_HANDLE;
8703 }
8704#if defined(_WIN32) || defined(_WIN64)
8705 EnterCriticalSection(&e->cs);
8706#endif
8707 switch (attr) {
8708 case SQL_ATTR_CONNECTION_POOLING:
8709 if (val == (SQLPOINTER) SQL_CP_ONE_PER_DRIVER) {
8710 e->pool = 1;
8711 ret = SQL_SUCCESS;
8712 } else if (val == (SQLPOINTER) SQL_CP_OFF) {
8713 e->pool = 0;
8714 ret = SQL_SUCCESS;
8715 }
8716 break;
8717 case SQL_ATTR_CP_MATCH:
8718 ret = SQL_SUCCESS;
8719 break;
8720 case SQL_ATTR_OUTPUT_NTS:
8721 if (val == (SQLPOINTER) SQL_TRUE) {
8722 ret = SQL_SUCCESS;
8723 }
8724 break;
8725 case SQL_ATTR_ODBC_VERSION:
8726 if (!val) {
8727 break;
8728 }
8729 if (val == (SQLPOINTER) SQL_OV_ODBC2) {
8730 e->ov3 = 0;
8731 ret = SQL_SUCCESS;
8732 } else if (val == (SQLPOINTER) SQL_OV_ODBC3) {
8733 e->ov3 = 1;
8734 ret = SQL_SUCCESS;
8735 }
8736 break;
8737 }
8738#if defined(_WIN32) || defined(_WIN64)
8739 LeaveCriticalSection(&e->cs);
8740#endif
8741 return ret;
8742}
8743
8757static SQLRETURN
8758drvgetdiagrec(SQLSMALLINT htype, SQLHANDLE handle, SQLSMALLINT recno,
8759 SQLCHAR *sqlstate, SQLINTEGER *nativeerr, SQLCHAR *msg,
8760 SQLSMALLINT buflen, SQLSMALLINT *msglen)
8761{
8762 DBC *d = NULL;
8763 STMT *s = NULL;
8764 int len, naterr;
8765 char *logmsg, *sqlst;
8766 SQLRETURN ret = SQL_ERROR;
8767
8768 if (handle == SQL_NULL_HANDLE) {
8769 return SQL_INVALID_HANDLE;
8770 }
8771 if (sqlstate) {
8772 sqlstate[0] = '\0';
8773 }
8774 if (msg && buflen > 0) {
8775 msg[0] = '\0';
8776 }
8777 if (msglen) {
8778 *msglen = 0;
8779 }
8780 if (nativeerr) {
8781 *nativeerr = 0;
8782 }
8783 switch (htype) {
8784 case SQL_HANDLE_ENV:
8785 case SQL_HANDLE_DESC:
8786 return SQL_NO_DATA;
8787 case SQL_HANDLE_DBC:
8788 HDBC_LOCK((SQLHDBC) handle);
8789 d = (DBC *) handle;
8790 logmsg = (char *) d->logmsg;
8791 sqlst = d->sqlstate;
8792 naterr = d->naterr;
8793 break;
8794 case SQL_HANDLE_STMT:
8795 HSTMT_LOCK((SQLHSTMT) handle);
8796 s = (STMT *) handle;
8797 logmsg = (char *) s->logmsg;
8798 sqlst = s->sqlstate;
8799 naterr = s->naterr;
8800 break;
8801 default:
8802 return SQL_INVALID_HANDLE;
8803 }
8804 if (buflen < 0) {
8805 goto done;
8806 }
8807 if (recno > 1) {
8808 ret = SQL_NO_DATA;
8809 goto done;
8810 }
8811 len = strlen(logmsg);
8812 if (len == 0) {
8813 ret = SQL_NO_DATA;
8814 goto done;
8815 }
8816 if (nativeerr) {
8817 *nativeerr = naterr;
8818 }
8819 if (sqlstate) {
8820 strcpy((char *) sqlstate, sqlst);
8821 }
8822 if (msglen) {
8823 *msglen = len;
8824 }
8825 if (len >= buflen) {
8826 if (msg && buflen > 0) {
8827 strncpy((char *) msg, logmsg, buflen);
8828 msg[buflen - 1] = '\0';
8829 logmsg[0] = '\0';
8830 }
8831 } else if (msg) {
8832 strcpy((char *) msg, logmsg);
8833 logmsg[0] = '\0';
8834 }
8835 ret = SQL_SUCCESS;
8836done:
8837 switch (htype) {
8838 case SQL_HANDLE_DBC:
8839 HDBC_UNLOCK((SQLHDBC) handle);
8840 break;
8841 case SQL_HANDLE_STMT:
8842 HSTMT_UNLOCK((SQLHSTMT) handle);
8843 break;
8844 }
8845 return ret;
8846}
8847
8848#if !defined(WINTERFACE) || (defined(HAVE_UNIXODBC) && (HAVE_UNIXODBC))
8862SQLRETURN SQL_API
8863SQLGetDiagRec(SQLSMALLINT htype, SQLHANDLE handle, SQLSMALLINT recno,
8864 SQLCHAR *sqlstate, SQLINTEGER *nativeerr, SQLCHAR *msg,
8865 SQLSMALLINT buflen, SQLSMALLINT *msglen)
8866{
8867 return drvgetdiagrec(htype, handle, recno, sqlstate,
8868 nativeerr, msg, buflen, msglen);
8869}
8870#endif
8871
8872#if !defined(HAVE_UNIXODBC) || !(HAVE_UNIXODBC)
8873#ifdef WINTERFACE
8888SQLRETURN SQL_API
8889SQLGetDiagRecW(SQLSMALLINT htype, SQLHANDLE handle, SQLSMALLINT recno,
8890 SQLWCHAR *sqlstate, SQLINTEGER *nativeerr, SQLWCHAR *msg,
8891 SQLSMALLINT buflen, SQLSMALLINT *msglen)
8892{
8893 char state[16];
8894 SQLSMALLINT len;
8895 SQLRETURN ret;
8896
8897 ret = drvgetdiagrec(htype, handle, recno, (SQLCHAR *) state,
8898 nativeerr, (SQLCHAR *) msg, buflen, &len);
8899 if (ret == SQL_SUCCESS) {
8900 if (sqlstate) {
8901 uc_from_utf_buf((SQLCHAR *) state, -1, sqlstate,
8902 6 * sizeof (SQLWCHAR));
8903 }
8904 if (msg) {
8905 if (len > 0) {
8906 SQLWCHAR *m = NULL;
8907
8908 m = uc_from_utf((unsigned char *) msg, len);
8909 if (m) {
8910 if (buflen) {
8911 buflen /= sizeof (SQLWCHAR);
8912 uc_strncpy(msg, m, buflen);
8913 m[len] = 0;
8914 len = min(buflen, uc_strlen(m));
8915 } else {
8916 len = uc_strlen(m);
8917 }
8918 uc_free(m);
8919 } else {
8920 len = 0;
8921 }
8922 }
8923 if (len <= 0) {
8924 len = 0;
8925 if (buflen > 0) {
8926 msg[0] = 0;
8927 }
8928 }
8929 } else {
8930 /* estimated length !!! */
8931 len *= sizeof (SQLWCHAR);
8932 }
8933 if (msglen) {
8934 *msglen = len;
8935 }
8936 } else if (ret == SQL_NO_DATA) {
8937 if (sqlstate) {
8938 sqlstate[0] = 0;
8939 }
8940 if (msg) {
8941 if (buflen > 0) {
8942 msg[0] = 0;
8943 }
8944 }
8945 if (msglen) {
8946 *msglen = 0;
8947 }
8948 }
8949 return ret;
8950}
8951#endif
8952#endif
8953
8966static SQLRETURN
8967drvgetdiagfield(SQLSMALLINT htype, SQLHANDLE handle, SQLSMALLINT recno,
8968 SQLSMALLINT id, SQLPOINTER info,
8969 SQLSMALLINT buflen, SQLSMALLINT *stringlen)
8970{
8971 DBC *d = NULL;
8972 STMT *s = NULL;
8973 int len, naterr, strbuf = 1;
8974 char *logmsg, *sqlst, *clrmsg = NULL;
8975 SQLRETURN ret = SQL_ERROR;
8976
8977 if (handle == SQL_NULL_HANDLE) {
8978 return SQL_INVALID_HANDLE;
8979 }
8980 if (stringlen) {
8981 *stringlen = 0;
8982 }
8983 switch (htype) {
8984 case SQL_HANDLE_ENV:
8985 case SQL_HANDLE_DESC:
8986 return SQL_NO_DATA;
8987 case SQL_HANDLE_DBC:
8988 HDBC_LOCK((SQLHDBC) handle);
8989 d = (DBC *) handle;
8990 logmsg = (char *) d->logmsg;
8991 sqlst = d->sqlstate;
8992 naterr = d->naterr;
8993 break;
8994 case SQL_HANDLE_STMT:
8995 HSTMT_LOCK((SQLHSTMT) handle);
8996 s = (STMT *) handle;
8997 d = (DBC *) s->dbc;
8998 logmsg = (char *) s->logmsg;
8999 sqlst = s->sqlstate;
9000 naterr = s->naterr;
9001 break;
9002 default:
9003 return SQL_INVALID_HANDLE;
9004 }
9005 if (buflen < 0) {
9006 switch (buflen) {
9007 case SQL_IS_POINTER:
9008 case SQL_IS_UINTEGER:
9009 case SQL_IS_INTEGER:
9010 case SQL_IS_USMALLINT:
9011 case SQL_IS_SMALLINT:
9012 strbuf = 0;
9013 break;
9014 default:
9015 ret = SQL_ERROR;
9016 goto done;
9017 }
9018 }
9019 if (recno > 1) {
9020 ret = SQL_NO_DATA;
9021 goto done;
9022 }
9023 switch (id) {
9024 case SQL_DIAG_CLASS_ORIGIN:
9025 logmsg = "ISO 9075";
9026 if (sqlst[0] == 'I' && sqlst[1] == 'M') {
9027 logmsg = "ODBC 3.0";
9028 }
9029 break;
9030 case SQL_DIAG_SUBCLASS_ORIGIN:
9031 logmsg = "ISO 9075";
9032 if (sqlst[0] == 'I' && sqlst[1] == 'M') {
9033 logmsg = "ODBC 3.0";
9034 } else if (sqlst[0] == 'H' && sqlst[1] == 'Y') {
9035 logmsg = "ODBC 3.0";
9036 } else if (sqlst[0] == '2' || sqlst[0] == '0' || sqlst[0] == '4') {
9037 logmsg = "ODBC 3.0";
9038 }
9039 break;
9040 case SQL_DIAG_CONNECTION_NAME:
9041 case SQL_DIAG_SERVER_NAME:
9042 logmsg = d->dsn ? d->dsn : "No DSN";
9043 break;
9044 case SQL_DIAG_SQLSTATE:
9045 logmsg = sqlst;
9046 break;
9047 case SQL_DIAG_MESSAGE_TEXT:
9048 if (info) {
9049 clrmsg = logmsg;
9050 }
9051 break;
9052 case SQL_DIAG_NUMBER:
9053 naterr = 1;
9054 /* fall through */
9055 case SQL_DIAG_NATIVE:
9056 len = strlen(logmsg);
9057 if (len == 0) {
9058 ret = SQL_NO_DATA;
9059 goto done;
9060 }
9061 if (info) {
9062 *((SQLINTEGER *) info) = naterr;
9063 }
9064 ret = SQL_SUCCESS;
9065 goto done;
9066 case SQL_DIAG_DYNAMIC_FUNCTION:
9067 logmsg = "";
9068 break;
9069 case SQL_DIAG_CURSOR_ROW_COUNT:
9070 if (htype == SQL_HANDLE_STMT) {
9071 SQLULEN count;
9072
9073 count = (s->isselect == 1 || s->isselect == -1) ? s->nrows : 0;
9074 *((SQLULEN *) info) = count;
9075 ret = SQL_SUCCESS;
9076 }
9077 goto done;
9078 case SQL_DIAG_ROW_COUNT:
9079 if (htype == SQL_HANDLE_STMT) {
9080 SQLULEN count;
9081
9082 count = s->isselect ? 0 : s->nrows;
9083 *((SQLULEN *) info) = count;
9084 ret = SQL_SUCCESS;
9085 }
9086 goto done;
9087 default:
9088 goto done;
9089 }
9090 if (info && buflen > 0) {
9091 ((char *) info)[0] = '\0';
9092 }
9093 len = strlen(logmsg);
9094 if (len == 0) {
9095 ret = SQL_NO_DATA;
9096 goto done;
9097 }
9098 if (stringlen) {
9099 *stringlen = len;
9100 }
9101 if (strbuf) {
9102 if (len >= buflen) {
9103 if (info && buflen > 0) {
9104 if (stringlen) {
9105 *stringlen = buflen - 1;
9106 }
9107 strncpy((char *) info, logmsg, buflen);
9108 ((char *) info)[buflen - 1] = '\0';
9109 }
9110 } else if (info) {
9111 strcpy((char *) info, logmsg);
9112 }
9113 }
9114 if (clrmsg) {
9115 *clrmsg = '\0';
9116 }
9117 ret = SQL_SUCCESS;
9118done:
9119 switch (htype) {
9120 case SQL_HANDLE_DBC:
9121 HDBC_UNLOCK((SQLHDBC) handle);
9122 break;
9123 case SQL_HANDLE_STMT:
9124 HSTMT_UNLOCK((SQLHSTMT) handle);
9125 break;
9126 }
9127 return ret;
9128}
9129
9130#ifndef WINTERFACE
9143SQLRETURN SQL_API
9144SQLGetDiagField(SQLSMALLINT htype, SQLHANDLE handle, SQLSMALLINT recno,
9145 SQLSMALLINT id, SQLPOINTER info,
9146 SQLSMALLINT buflen, SQLSMALLINT *stringlen)
9147{
9148 return drvgetdiagfield(htype, handle, recno, id, info, buflen, stringlen);
9149}
9150#endif
9151
9152#ifdef WINTERFACE
9165SQLRETURN SQL_API
9166SQLGetDiagFieldW(SQLSMALLINT htype, SQLHANDLE handle, SQLSMALLINT recno,
9167 SQLSMALLINT id, SQLPOINTER info,
9168 SQLSMALLINT buflen, SQLSMALLINT *stringlen)
9169{
9170 SQLSMALLINT len;
9171 SQLRETURN ret;
9172
9173 ret = drvgetdiagfield(htype, handle, recno, id, info, buflen, &len);
9174 if (ret == SQL_SUCCESS) {
9175 if (info) {
9176 switch (id) {
9177 case SQL_DIAG_CLASS_ORIGIN:
9178 case SQL_DIAG_SUBCLASS_ORIGIN:
9179 case SQL_DIAG_CONNECTION_NAME:
9180 case SQL_DIAG_SERVER_NAME:
9181 case SQL_DIAG_SQLSTATE:
9182 case SQL_DIAG_MESSAGE_TEXT:
9183 case SQL_DIAG_DYNAMIC_FUNCTION:
9184 if (len > 0) {
9185 SQLWCHAR *m = NULL;
9186
9187 m = uc_from_utf((unsigned char *) info, len);
9188 if (m) {
9189 if (buflen) {
9190 buflen /= sizeof (SQLWCHAR);
9191 uc_strncpy(info, m, buflen);
9192 m[len] = 0;
9193 len = min(buflen, uc_strlen(m));
9194 } else {
9195 len = uc_strlen(m);
9196 }
9197 uc_free(m);
9198 len *= sizeof (SQLWCHAR);
9199 } else {
9200 len = 0;
9201 }
9202 }
9203 if (len <= 0) {
9204 len = 0;
9205 if (buflen > 0) {
9206 ((SQLWCHAR *) info)[0] = 0;
9207 }
9208 }
9209 }
9210 } else {
9211 switch (id) {
9212 case SQL_DIAG_CLASS_ORIGIN:
9213 case SQL_DIAG_SUBCLASS_ORIGIN:
9214 case SQL_DIAG_CONNECTION_NAME:
9215 case SQL_DIAG_SERVER_NAME:
9216 case SQL_DIAG_SQLSTATE:
9217 case SQL_DIAG_MESSAGE_TEXT:
9218 case SQL_DIAG_DYNAMIC_FUNCTION:
9219 len *= sizeof (SQLWCHAR);
9220 break;
9221 }
9222 }
9223 if (stringlen) {
9224 *stringlen = len;
9225 }
9226 }
9227 return ret;
9228}
9229#endif
9230
9241static SQLRETURN
9242drvgetstmtattr(SQLHSTMT stmt, SQLINTEGER attr, SQLPOINTER val,
9243 SQLINTEGER bufmax, SQLINTEGER *buflen)
9244{
9245 STMT *s = (STMT *) stmt;
9246 SQLULEN *uval = (SQLULEN *) val;
9247 SQLINTEGER dummy;
9248 char dummybuf[16];
9249
9250 if (!buflen) {
9251 buflen = &dummy;
9252 }
9253 if (!uval) {
9254 uval = (SQLPOINTER) dummybuf;
9255 }
9256 switch (attr) {
9257 case SQL_QUERY_TIMEOUT:
9258 *uval = 0;
9259 *buflen = sizeof (SQLULEN);
9260 return SQL_SUCCESS;
9261 case SQL_ATTR_CURSOR_TYPE:
9262 *uval = s->curtype;
9263 *buflen = sizeof (SQLULEN);
9264 return SQL_SUCCESS;
9265 case SQL_ATTR_CURSOR_SCROLLABLE:
9266 *uval = (s->curtype != SQL_CURSOR_FORWARD_ONLY) ?
9267 SQL_SCROLLABLE : SQL_NONSCROLLABLE;
9268 *buflen = sizeof (SQLULEN);
9269 return SQL_SUCCESS;
9270#ifdef SQL_ATTR_CURSOR_SENSITIVITY
9271 case SQL_ATTR_CURSOR_SENSITIVITY:
9272 *uval = SQL_UNSPECIFIED;
9273 *buflen = sizeof (SQLULEN);
9274 return SQL_SUCCESS;
9275#endif
9276 case SQL_ATTR_ROW_NUMBER:
9277 if (s->s3stmt) {
9278 *uval = (s->s3stmt_rownum < 0) ?
9279 SQL_ROW_NUMBER_UNKNOWN : (s->s3stmt_rownum + 1);
9280 } else {
9281 *uval = (s->rowp < 0) ? SQL_ROW_NUMBER_UNKNOWN : (s->rowp + 1);
9282 }
9283 *buflen = sizeof (SQLULEN);
9284 return SQL_SUCCESS;
9285 case SQL_ATTR_ASYNC_ENABLE:
9286 *uval = SQL_ASYNC_ENABLE_OFF;
9287 *buflen = sizeof (SQLULEN);
9288 return SQL_SUCCESS;
9289 case SQL_CONCURRENCY:
9290 *uval = SQL_CONCUR_LOCK;
9291 *buflen = sizeof (SQLULEN);
9292 return SQL_SUCCESS;
9293 case SQL_ATTR_RETRIEVE_DATA:
9294 *uval = s->retr_data;
9295 *buflen = sizeof (SQLULEN);
9296 return SQL_SUCCESS;
9297 case SQL_ROWSET_SIZE:
9298 case SQL_ATTR_ROW_ARRAY_SIZE:
9299 *uval = s->rowset_size;
9300 *buflen = sizeof (SQLULEN);
9301 return SQL_SUCCESS;
9302 /* Needed for some driver managers, but dummies for now */
9303 case SQL_ATTR_IMP_ROW_DESC:
9304 case SQL_ATTR_APP_ROW_DESC:
9305 case SQL_ATTR_IMP_PARAM_DESC:
9306 case SQL_ATTR_APP_PARAM_DESC:
9307 *((SQLHDESC *) uval) = (SQLHDESC) DEAD_MAGIC;
9308 *buflen = sizeof (SQLHDESC);
9309 return SQL_SUCCESS;
9310 case SQL_ATTR_ROW_STATUS_PTR:
9311 *((SQLUSMALLINT **) uval) = s->row_status;
9312 *buflen = sizeof (SQLUSMALLINT *);
9313 return SQL_SUCCESS;
9314 case SQL_ATTR_ROWS_FETCHED_PTR:
9315 *((SQLULEN **) uval) = s->row_count;
9316 *buflen = sizeof (SQLULEN *);
9317 return SQL_SUCCESS;
9318 case SQL_ATTR_USE_BOOKMARKS: {
9319 STMT *s = (STMT *) stmt;
9320
9321 *(SQLUINTEGER *) uval = s->bkmrk;
9322 *buflen = sizeof (SQLUINTEGER);
9323 return SQL_SUCCESS;
9324 }
9325 case SQL_ATTR_FETCH_BOOKMARK_PTR:
9326 *(SQLPOINTER *) uval = s->bkmrkptr;
9327 *buflen = sizeof (SQLPOINTER);
9328 return SQL_SUCCESS;
9329 case SQL_ATTR_PARAM_BIND_OFFSET_PTR:
9330 *((SQLULEN **) uval) = s->parm_bind_offs;
9331 *buflen = sizeof (SQLULEN *);
9332 return SQL_SUCCESS;
9333 case SQL_ATTR_PARAM_BIND_TYPE:
9334 *((SQLULEN *) uval) = s->parm_bind_type;
9335 *buflen = sizeof (SQLULEN);
9336 return SQL_SUCCESS;
9337 case SQL_ATTR_PARAM_OPERATION_PTR:
9338 *((SQLUSMALLINT **) uval) = s->parm_oper;
9339 *buflen = sizeof (SQLUSMALLINT *);
9340 return SQL_SUCCESS;
9341 case SQL_ATTR_PARAM_STATUS_PTR:
9342 *((SQLUSMALLINT **) uval) = s->parm_status;
9343 *buflen = sizeof (SQLUSMALLINT *);
9344 return SQL_SUCCESS;
9345 case SQL_ATTR_PARAMS_PROCESSED_PTR:
9346 *((SQLULEN **) uval) = s->parm_proc;
9347 *buflen = sizeof (SQLULEN *);
9348 return SQL_SUCCESS;
9349 case SQL_ATTR_PARAMSET_SIZE:
9350 *((SQLULEN *) uval) = s->paramset_size;
9351 *buflen = sizeof (SQLULEN);
9352 return SQL_SUCCESS;
9353 case SQL_ATTR_ROW_BIND_TYPE:
9354 *(SQLULEN *) uval = s->bind_type;
9355 *buflen = sizeof (SQLULEN);
9356 return SQL_SUCCESS;
9357 case SQL_ATTR_ROW_BIND_OFFSET_PTR:
9358 *((SQLULEN **) uval) = s->bind_offs;
9359 *buflen = sizeof (SQLULEN *);
9360 return SQL_SUCCESS;
9361 case SQL_ATTR_MAX_ROWS:
9362 *((SQLULEN *) uval) = s->max_rows;
9363 *buflen = sizeof (SQLULEN);
9364 return SQL_SUCCESS;
9365 case SQL_ATTR_MAX_LENGTH:
9366 *((SQLULEN *) uval) = 1000000000;
9367 *buflen = sizeof (SQLULEN);
9368 return SQL_SUCCESS;
9369#ifdef SQL_ATTR_METADATA_ID
9370 case SQL_ATTR_METADATA_ID:
9371 *((SQLULEN *) uval) = SQL_FALSE;
9372 *buflen = sizeof (SQLULEN);
9373 return SQL_SUCCESS;
9374#endif
9375 }
9376 return drvunimplstmt(stmt);
9377}
9378
9379#if (defined(HAVE_UNIXODBC) && (HAVE_UNIXODBC)) || !defined(WINTERFACE)
9390SQLRETURN SQL_API
9391SQLGetStmtAttr(SQLHSTMT stmt, SQLINTEGER attr, SQLPOINTER val,
9392 SQLINTEGER bufmax, SQLINTEGER *buflen)
9393{
9394 SQLRETURN ret;
9395
9397 ret = drvgetstmtattr(stmt, attr, val, bufmax, buflen);
9399 return ret;
9400}
9401#endif
9402
9403#ifdef WINTERFACE
9414SQLRETURN SQL_API
9415SQLGetStmtAttrW(SQLHSTMT stmt, SQLINTEGER attr, SQLPOINTER val,
9416 SQLINTEGER bufmax, SQLINTEGER *buflen)
9417{
9418 SQLRETURN ret;
9419
9421 ret = drvgetstmtattr(stmt, attr, val, bufmax, buflen);
9423 return ret;
9424}
9425#endif
9426
9436static SQLRETURN
9437drvsetstmtattr(SQLHSTMT stmt, SQLINTEGER attr, SQLPOINTER val,
9438 SQLINTEGER buflen)
9439{
9440 STMT *s = (STMT *) stmt;
9441#if defined(SQL_BIGINT) && defined(__WORDSIZE) && (__WORDSIZE == 64)
9442 SQLBIGINT uval;
9443
9444 uval = (SQLBIGINT) val;
9445#else
9446 SQLULEN uval;
9447
9448 uval = (SQLULEN) val;
9449#endif
9450 switch (attr) {
9451 case SQL_ATTR_CURSOR_TYPE:
9452 if (val == (SQLPOINTER) SQL_CURSOR_FORWARD_ONLY) {
9453 s->curtype = SQL_CURSOR_FORWARD_ONLY;
9454 } else {
9455 s->curtype = SQL_CURSOR_STATIC;
9456 }
9457 if (val != (SQLPOINTER) SQL_CURSOR_FORWARD_ONLY &&
9458 val != (SQLPOINTER) SQL_CURSOR_STATIC) {
9459 goto e01s02;
9460 }
9461 return SQL_SUCCESS;
9462 case SQL_ATTR_CURSOR_SCROLLABLE:
9463 if (val == (SQLPOINTER) SQL_NONSCROLLABLE) {
9464 s->curtype = SQL_CURSOR_FORWARD_ONLY;
9465 } else {
9466 s->curtype = SQL_CURSOR_STATIC;
9467 }
9468 return SQL_SUCCESS;
9469 case SQL_ATTR_ASYNC_ENABLE:
9470 if (val != (SQLPOINTER) SQL_ASYNC_ENABLE_OFF) {
9471 e01s02:
9472 setstat(s, -1, "option value changed", "01S02");
9473 return SQL_SUCCESS_WITH_INFO;
9474 }
9475 return SQL_SUCCESS;
9476 case SQL_CONCURRENCY:
9477 if (val != (SQLPOINTER) SQL_CONCUR_LOCK) {
9478 goto e01s02;
9479 }
9480 return SQL_SUCCESS;
9481#ifdef SQL_ATTR_CURSOR_SENSITIVITY
9482 case SQL_ATTR_CURSOR_SENSITIVITY:
9483 if (val != (SQLPOINTER) SQL_UNSPECIFIED) {
9484 goto e01s02;
9485 }
9486 return SQL_SUCCESS;
9487#endif
9488 case SQL_ATTR_QUERY_TIMEOUT:
9489 return SQL_SUCCESS;
9490 case SQL_ATTR_RETRIEVE_DATA:
9491 if (val != (SQLPOINTER) SQL_RD_ON &&
9492 val != (SQLPOINTER) SQL_RD_OFF) {
9493 goto e01s02;
9494 }
9495 s->retr_data = uval;
9496 return SQL_SUCCESS;
9497 case SQL_ROWSET_SIZE:
9498 case SQL_ATTR_ROW_ARRAY_SIZE:
9499 if (uval < 1) {
9500 setstat(s, -1, "invalid rowset size", "HY000");
9501 return SQL_ERROR;
9502 } else {
9503 SQLUSMALLINT *rst = &s->row_status1;
9504
9505 if (uval > 1) {
9506 rst = xmalloc(sizeof (SQLUSMALLINT) * uval);
9507 if (!rst) {
9508 return nomem(s);
9509 }
9510 }
9511 if (s->row_status0 != &s->row_status1) {
9512 freep(&s->row_status0);
9513 }
9514 s->row_status0 = rst;
9515 s->rowset_size = uval;
9516 }
9517 return SQL_SUCCESS;
9518 case SQL_ATTR_ROW_STATUS_PTR:
9519 s->row_status = (SQLUSMALLINT *) val;
9520 return SQL_SUCCESS;
9521 case SQL_ATTR_ROWS_FETCHED_PTR:
9522 s->row_count = (SQLULEN *) val;
9523 return SQL_SUCCESS;
9524 case SQL_ATTR_PARAM_BIND_OFFSET_PTR:
9525 s->parm_bind_offs = (SQLULEN *) val;
9526 return SQL_SUCCESS;
9527 case SQL_ATTR_PARAM_BIND_TYPE:
9528 s->parm_bind_type = uval;
9529 return SQL_SUCCESS;
9530 case SQL_ATTR_PARAM_OPERATION_PTR:
9531 s->parm_oper = (SQLUSMALLINT *) val;
9532 return SQL_SUCCESS;
9533 case SQL_ATTR_PARAM_STATUS_PTR:
9534 s->parm_status = (SQLUSMALLINT *) val;
9535 return SQL_SUCCESS;
9536 case SQL_ATTR_PARAMS_PROCESSED_PTR:
9537 s->parm_proc = (SQLULEN *) val;
9538 return SQL_SUCCESS;
9539 case SQL_ATTR_PARAMSET_SIZE:
9540 if (uval < 1) {
9541 goto e01s02;
9542 }
9543 s->paramset_size = uval;
9544 s->paramset_count = 0;
9545 return SQL_SUCCESS;
9546 case SQL_ATTR_ROW_BIND_TYPE:
9547 s->bind_type = uval;
9548 return SQL_SUCCESS;
9549 case SQL_ATTR_ROW_BIND_OFFSET_PTR:
9550 s->bind_offs = (SQLULEN *) val;
9551 return SQL_SUCCESS;
9552 case SQL_ATTR_USE_BOOKMARKS:
9553 if (val != (SQLPOINTER) SQL_UB_OFF &&
9554 val != (SQLPOINTER) SQL_UB_ON &&
9555 val != (SQLPOINTER) SQL_UB_VARIABLE) {
9556 goto e01s02;
9557 }
9558 if (*s->ov3 && val == (SQLPOINTER) SQL_UB_VARIABLE) {
9559 s->bkmrk = SQL_UB_VARIABLE;
9560 return SQL_SUCCESS;
9561 }
9562 if (val == (SQLPOINTER) SQL_UB_VARIABLE) {
9563 s->bkmrk = SQL_UB_ON;
9564 goto e01s02;
9565 }
9566 s->bkmrk = (val == (SQLPOINTER) SQL_UB_ON) ? SQL_UB_ON : SQL_UB_OFF;
9567 return SQL_SUCCESS;
9568 case SQL_ATTR_FETCH_BOOKMARK_PTR:
9569 s->bkmrkptr = (SQLINTEGER *) val;
9570 return SQL_SUCCESS;
9571 case SQL_ATTR_MAX_ROWS:
9572 s->max_rows = uval;
9573 return SQL_SUCCESS;
9574 case SQL_ATTR_MAX_LENGTH:
9575 if (val != (SQLPOINTER) 1000000000) {
9576 goto e01s02;
9577 }
9578 return SQL_SUCCESS;
9579#ifdef SQL_ATTR_METADATA_ID
9580 case SQL_ATTR_METADATA_ID:
9581 if (val != (SQLPOINTER) SQL_FALSE) {
9582 goto e01s02;
9583 }
9584 return SQL_SUCCESS;
9585#endif
9586 }
9587 return drvunimplstmt(stmt);
9588}
9589
9590#if (defined(HAVE_UNIXODBC) && (HAVE_UNIXODBC)) || !defined(WINTERFACE)
9600SQLRETURN SQL_API
9601SQLSetStmtAttr(SQLHSTMT stmt, SQLINTEGER attr, SQLPOINTER val,
9602 SQLINTEGER buflen)
9603{
9604 SQLRETURN ret;
9605
9607 ret = drvsetstmtattr(stmt, attr, val, buflen);
9609 return ret;
9610}
9611#endif
9612
9613#ifdef WINTERFACE
9623SQLRETURN SQL_API
9624SQLSetStmtAttrW(SQLHSTMT stmt, SQLINTEGER attr, SQLPOINTER val,
9625 SQLINTEGER buflen)
9626{
9627 SQLRETURN ret;
9628
9630 ret = drvsetstmtattr(stmt, attr, val, buflen);
9632 return ret;
9633}
9634#endif
9635
9644static SQLRETURN
9645drvgetstmtoption(SQLHSTMT stmt, SQLUSMALLINT opt, SQLPOINTER param)
9646{
9647 STMT *s = (STMT *) stmt;
9648 SQLUINTEGER *ret = (SQLUINTEGER *) param;
9649
9650 switch (opt) {
9651 case SQL_QUERY_TIMEOUT:
9652 *ret = 0;
9653 return SQL_SUCCESS;
9654 case SQL_CURSOR_TYPE:
9655 *ret = s->curtype;
9656 return SQL_SUCCESS;
9657 case SQL_ROW_NUMBER:
9658 if (s->s3stmt) {
9659 *ret = (s->s3stmt_rownum < 0) ?
9660 SQL_ROW_NUMBER_UNKNOWN : (s->s3stmt_rownum + 1);
9661 } else {
9662 *ret = (s->rowp < 0) ? SQL_ROW_NUMBER_UNKNOWN : (s->rowp + 1);
9663 }
9664 return SQL_SUCCESS;
9665 case SQL_ASYNC_ENABLE:
9666 *ret = SQL_ASYNC_ENABLE_OFF;
9667 return SQL_SUCCESS;
9668 case SQL_CONCURRENCY:
9669 *ret = SQL_CONCUR_LOCK;
9670 return SQL_SUCCESS;
9671 case SQL_ATTR_RETRIEVE_DATA:
9672 *ret = s->retr_data;
9673 return SQL_SUCCESS;
9674 case SQL_ROWSET_SIZE:
9675 case SQL_ATTR_ROW_ARRAY_SIZE:
9676 *ret = s->rowset_size;
9677 return SQL_SUCCESS;
9678 case SQL_ATTR_MAX_ROWS:
9679 *ret = s->max_rows;
9680 return SQL_SUCCESS;
9681 case SQL_ATTR_MAX_LENGTH:
9682 *ret = 1000000000;
9683 return SQL_SUCCESS;
9684 }
9685 return drvunimplstmt(stmt);
9686}
9687
9696SQLRETURN SQL_API
9697SQLGetStmtOption(SQLHSTMT stmt, SQLUSMALLINT opt, SQLPOINTER param)
9698{
9699 SQLRETURN ret;
9700
9702 ret = drvgetstmtoption(stmt, opt, param);
9704 return ret;
9705}
9706
9707#ifdef WINTERFACE
9716SQLRETURN SQL_API
9717SQLGetStmtOptionW(SQLHSTMT stmt, SQLUSMALLINT opt, SQLPOINTER param)
9718{
9719 SQLRETURN ret;
9720
9722 ret = drvgetstmtoption(stmt, opt, param);
9724 return ret;
9725}
9726#endif
9727
9736static SQLRETURN
9737drvsetstmtoption(SQLHSTMT stmt, SQLUSMALLINT opt, SQLUINTEGER param)
9738{
9739 STMT *s = (STMT *) stmt;
9740
9741 switch (opt) {
9742 case SQL_CURSOR_TYPE:
9743 if (param == SQL_CURSOR_FORWARD_ONLY) {
9744 s->curtype = param;
9745 } else {
9746 s->curtype = SQL_CURSOR_STATIC;
9747 }
9748 if (param != SQL_CURSOR_FORWARD_ONLY &&
9749 param != SQL_CURSOR_STATIC) {
9750 goto e01s02;
9751 }
9752 return SQL_SUCCESS;
9753 case SQL_ASYNC_ENABLE:
9754 if (param != SQL_ASYNC_ENABLE_OFF) {
9755 goto e01s02;
9756 }
9757 return SQL_SUCCESS;
9758 case SQL_CONCURRENCY:
9759 if (param != SQL_CONCUR_LOCK) {
9760 goto e01s02;
9761 }
9762 return SQL_SUCCESS;
9763 case SQL_QUERY_TIMEOUT:
9764 return SQL_SUCCESS;
9765 case SQL_RETRIEVE_DATA:
9766 if (param != SQL_RD_ON && param != SQL_RD_OFF) {
9767 e01s02:
9768 setstat(s, -1, "option value changed", "01S02");
9769 return SQL_SUCCESS_WITH_INFO;
9770 }
9771 s->retr_data = (int) param;
9772 return SQL_SUCCESS;
9773 case SQL_ROWSET_SIZE:
9774 case SQL_ATTR_ROW_ARRAY_SIZE:
9775 if (param < 1) {
9776 setstat(s, -1, "invalid rowset size", "HY000");
9777 return SQL_ERROR;
9778 } else {
9779 SQLUSMALLINT *rst = &s->row_status1;
9780
9781 if (param > 1) {
9782 rst = xmalloc(sizeof (SQLUSMALLINT) * param);
9783 if (!rst) {
9784 return nomem(s);
9785 }
9786 }
9787 if (s->row_status0 != &s->row_status1) {
9788 freep(&s->row_status0);
9789 }
9790 s->row_status0 = rst;
9791 s->rowset_size = param;
9792 }
9793 return SQL_SUCCESS;
9794 case SQL_ATTR_MAX_ROWS:
9795 s->max_rows = param;
9796 return SQL_SUCCESS;
9797 case SQL_ATTR_MAX_LENGTH:
9798 if (param != 1000000000) {
9799 goto e01s02;
9800 }
9801 return SQL_SUCCESS;
9802 }
9803 return drvunimplstmt(stmt);
9804}
9805
9814SQLRETURN SQL_API
9815SQLSetStmtOption(SQLHSTMT stmt, SQLUSMALLINT opt,
9817{
9818 SQLRETURN ret;
9819
9821 ret = drvsetstmtoption(stmt, opt, (SQLUINTEGER) param);
9823 return ret;
9824}
9825
9826#ifdef WINTERFACE
9835SQLRETURN SQL_API
9836SQLSetStmtOptionW(SQLHSTMT stmt, SQLUSMALLINT opt,
9838{
9839 SQLRETURN ret;
9840
9842 ret = drvsetstmtoption(stmt, opt, (SQLUINTEGER) param);
9844 return ret;
9845}
9846#endif
9847
9854static SQLRETURN
9856{
9857 int i;
9858
9859 if (!s->bindcols || s->nbindcols < s->ncols) {
9860unbound:
9861 setstat(s, -1, "unbound columns", (*s->ov3) ? "HY000" : "S1000");
9862 return SQL_ERROR;
9863 }
9864 for (i = 0; i < s->ncols; i++) {
9865 BINDCOL *b = &s->bindcols[i];
9866
9867 if (b->type == SQL_UNKNOWN_TYPE || !b->valp) {
9868 goto unbound;
9869 }
9870 }
9871 return SQL_SUCCESS;
9872}
9873
9885static SQLRETURN
9886setposbind(STMT *s, sqlite3_stmt *stmt, int i, int si, int rsi)
9887{
9888 DBC *d = (DBC *) s->dbc;
9889 SQLPOINTER dp = 0;
9890 SQLLEN *lp = 0;
9891 BINDCOL *b = &s->bindcols[i];
9892 COL *c = &s->cols[i];
9893 char strbuf[128], *cp;
9894
9895 if (b->valp) {
9896 if (s->bind_type != SQL_BIND_BY_COLUMN) {
9897 dp = (SQLPOINTER) ((char *) b->valp + s->bind_type * rsi);
9898 } else {
9899 dp = (SQLPOINTER) ((char *) b->valp + b->max * rsi);
9900 }
9901 if (s->bind_offs) {
9902 dp = (SQLPOINTER) ((char *) dp + *s->bind_offs);
9903 }
9904 }
9905 if (b->lenp) {
9906 if (s->bind_type != SQL_BIND_BY_COLUMN) {
9907 lp = (SQLLEN *) ((char *) b->lenp + s->bind_type * rsi);
9908 } else {
9909 lp = b->lenp + rsi;
9910 }
9911 if (s->bind_offs) {
9912 lp = (SQLLEN *) ((char *) lp + *s->bind_offs);
9913 }
9914 }
9915 if (!dp || !lp) {
9916 setstat(s, -1, "unbound column in positional update",
9917 (*s->ov3) ? "HY000" : "S1000");
9918 return SQL_ERROR;
9919 }
9920 if (*lp == SQL_NULL_DATA) {
9921 sqlite3_bind_null(stmt, si);
9922 if (d->trace) {
9923 fprintf(d->trace, "-- parameter %d: NULL\n", si);
9924 fflush(d->trace);
9925 }
9926 return SQL_SUCCESS;
9927 }
9928 switch (b->type) {
9929 case SQL_C_UTINYINT:
9930 case SQL_C_TINYINT:
9931 case SQL_C_STINYINT:
9932 sqlite3_bind_int(stmt, si, *(SQLCHAR *) dp);
9933 if (d->trace) {
9934 fprintf(d->trace, "-- parameter %d: %d\n", si, *(SQLCHAR *) dp);
9935 fflush(d->trace);
9936 }
9937 break;
9938#ifdef SQL_BIT
9939 case SQL_C_BIT:
9940 sqlite3_bind_int(stmt, si, (*(SQLCHAR *) dp) ? 1 : 0);
9941 if (d->trace) {
9942 fprintf(d->trace, "-- parameter %d: %d\n", si,
9943 (*(SQLCHAR *) dp) ? 1 : 0);
9944 fflush(d->trace);
9945 }
9946 break;
9947#endif
9948 case SQL_C_USHORT:
9949 sqlite3_bind_int(stmt, si, *(SQLUSMALLINT *) dp);
9950 if (d->trace) {
9951 fprintf(d->trace, "-- parameter %d: %d\n", si,
9952 *(SQLUSMALLINT *) dp);
9953 fflush(d->trace);
9954 }
9955 break;
9956 case SQL_C_SHORT:
9957 case SQL_C_SSHORT:
9958 sqlite3_bind_int(stmt, si, *(SQLSMALLINT *) dp);
9959 if (d->trace) {
9960 fprintf(d->trace, "-- parameter %d: %d\n", si,
9961 *(SQLSMALLINT *) dp);
9962 fflush(d->trace);
9963 }
9964 break;
9965 case SQL_C_ULONG:
9966 sqlite3_bind_int(stmt, si, *(SQLUINTEGER *) dp);
9967 if (d->trace) {
9968 fprintf(d->trace, "-- parameter %d: %ld\n", si,
9969 (long) *(SQLUINTEGER *) dp);
9970 fflush(d->trace);
9971 }
9972 break;
9973 case SQL_C_LONG:
9974 case SQL_C_SLONG:
9975 sqlite3_bind_int(stmt, si, *(SQLINTEGER *) dp);
9976 if (d->trace) {
9977 fprintf(d->trace, "-- parameter %d: %ld\n", si,
9978 (long) *(SQLINTEGER *) dp);
9979 fflush(d->trace);
9980 }
9981 break;
9982#ifdef SQL_BIGINT
9983 case SQL_C_UBIGINT:
9984 case SQL_C_SBIGINT:
9985 sqlite3_bind_int64(stmt, si, *(SQLBIGINT *) dp);
9986 if (d->trace) {
9987 fprintf(d->trace,
9988#ifdef _WIN32
9989 "-- parameter %d: %I64d\n",
9990#else
9991 "-- parameter %d: %lld\n",
9992#endif
9993 si, (sqlite_int64) *(SQLBIGINT *) dp);
9994 fflush(d->trace);
9995 }
9996 break;
9997#endif
9998 case SQL_C_FLOAT:
9999 sqlite3_bind_double(stmt, si, *(float *) dp);
10000 if (d->trace) {
10001 fprintf(d->trace, "-- parameter %d: %g\n", si,
10002 *(float *) dp);
10003 fflush(d->trace);
10004 }
10005 break;
10006 case SQL_C_DOUBLE:
10007 sqlite3_bind_double(stmt, si, *(double *) dp);
10008 if (d->trace) {
10009 fprintf(d->trace, "-- parameter %d: %g\n", si,
10010 *(double *) dp);
10011 fflush(d->trace);
10012 }
10013 break;
10014 case SQL_C_BINARY:
10015 sqlite3_bind_blob(stmt, si, (char *) dp, *lp, SQLITE_STATIC);
10016 if (d->trace) {
10017 fprintf(d->trace, "-- parameter %d: [BLOB]\n", si);
10018 fflush(d->trace);
10019 }
10020 break;
10021#ifdef WCHARSUPPORT
10022 case SQL_C_WCHAR:
10023 cp = uc_to_utf((SQLWCHAR *) dp, *lp);
10024 if (!cp) {
10025 return nomem(s);
10026 }
10027 sqlite3_bind_text(stmt, si, cp, -1, SQLITE_TRANSIENT);
10028 if (d->trace) {
10029 fprintf(d->trace, "-- parameter %d: '%s'\n", si, cp);
10030 fflush(d->trace);
10031 }
10032 uc_free(cp);
10033 break;
10034#endif
10035 case SQL_C_CHAR:
10036#if defined(_WIN32) || defined(_WIN64)
10037 if (*s->oemcp) {
10038 cp = wmb_to_utf((char *) dp, *lp);
10039 if (!cp) {
10040 return nomem(s);
10041 }
10042 sqlite3_bind_text(stmt, si, cp, -1, SQLITE_TRANSIENT);
10043 if (d->trace) {
10044 fprintf(d->trace, "-- parameter %d: '%s'\n", si, cp);
10045 fflush(d->trace);
10046 }
10047 uc_free(cp);
10048 } else
10049#endif
10050 {
10051 if (*lp == SQL_NTS) {
10052 sqlite3_bind_text(stmt, si, (char *) dp, -1,
10053 SQLITE_STATIC);
10054 if (d->trace) {
10055 fprintf(d->trace, "-- parameter %d: '%s'\n", si,
10056 (char *) dp);
10057 fflush(d->trace);
10058 }
10059 } else {
10060 sqlite3_bind_text(stmt, si, (char *) dp, *lp,
10061 SQLITE_STATIC);
10062 if (d->trace) {
10063 fprintf(d->trace, "-- parameter %d: '%*s'\n", si,
10064 (int) *lp, (char *) dp);
10065 fflush(d->trace);
10066 }
10067 }
10068 }
10069 break;
10070#ifdef SQL_C_TYPE_DATE
10071 case SQL_C_TYPE_DATE:
10072#endif
10073 case SQL_C_DATE:
10074 if (*s->jdconv) {
10075 int a, b, x1, x2, y, m, dd;
10076 double v;
10077
10078 y = ((DATE_STRUCT *) dp)->year;
10079 m = ((DATE_STRUCT *) dp)->month;
10080 dd = ((DATE_STRUCT *) dp)->day;
10081 if (m <= 2) {
10082 y--;
10083 m += 12;
10084 }
10085 a = y / 100;
10086 b = 2 - a + (a / 4);
10087 x1 = 36525 * (y + 4716) / 100;
10088 x2 = 306001 * (m + 1) / 10000;
10089 v = x1 + x2 + dd + b - 1524.5;
10090 sqlite3_bind_double(stmt, si, v);
10091 if (d->trace) {
10092 fprintf(d->trace, "-- parameter %d: %g\n", si, v);
10093 fflush(d->trace);
10094 }
10095 } else {
10096 sprintf(strbuf, "%04d-%02d-%02d",
10097 ((DATE_STRUCT *) dp)->year,
10098 ((DATE_STRUCT *) dp)->month,
10099 ((DATE_STRUCT *) dp)->day);
10100 sqlite3_bind_text(stmt, si, strbuf, -1, SQLITE_TRANSIENT);
10101 if (d->trace) {
10102 fprintf(d->trace, "-- parameter %d: '%s'\n", si, strbuf);
10103 fflush(d->trace);
10104 }
10105 }
10106 break;
10107#ifdef SQL_C_TYPE_TIME
10108 case SQL_C_TYPE_TIME:
10109#endif
10110 case SQL_C_TIME:
10111 if (*s->jdconv) {
10112 double v;
10113
10114 v = 2451544.5 +
10115 (((TIME_STRUCT *) dp)->hour * 3600000.0 +
10116 ((TIME_STRUCT *) dp)->minute * 60000.0 +
10117 ((TIME_STRUCT *) dp)->second * 1000.0) / 86400000.0;
10118 sqlite3_bind_double(stmt, si, v);
10119 if (d->trace) {
10120 fprintf(d->trace, "-- parameter %d: %g\n", si, v);
10121 fflush(d->trace);
10122 }
10123 } else {
10124 sprintf(strbuf, "%02d:%02d:%02d",
10125 ((TIME_STRUCT *) dp)->hour,
10126 ((TIME_STRUCT *) dp)->minute,
10127 ((TIME_STRUCT *) dp)->second);
10128 sqlite3_bind_text(stmt, si, strbuf, -1, SQLITE_TRANSIENT);
10129 if (d->trace) {
10130 fprintf(d->trace, "-- parameter %d: '%s'\n", si, strbuf);
10131 fflush(d->trace);
10132 }
10133 }
10134 break;
10135#ifdef SQL_C_TYPE_TIMESTAMP
10136 case SQL_C_TYPE_TIMESTAMP:
10137#endif
10138 case SQL_C_TIMESTAMP:
10139 if (*s->jdconv) {
10140 int a, b, x1, x2, y, m, dd;
10141 double v;
10142
10143 y = ((TIMESTAMP_STRUCT *) dp)->year;
10144 m = ((TIMESTAMP_STRUCT *) dp)->month;
10145 dd = ((TIMESTAMP_STRUCT *) dp)->day;
10146 if (m <= 2) {
10147 y--;
10148 m += 12;
10149 }
10150 a = y / 100;
10151 b = 2 - a + (a / 4);
10152 x1 = 36525 * (y + 4716) / 100;
10153 x2 = 306001 * (m + 1) / 10000;
10154 v = x1 + x2 + dd + b - 1524.5 +
10155 (((TIMESTAMP_STRUCT *) dp)->hour * 3600000.0 +
10156 ((TIMESTAMP_STRUCT *) dp)->minute * 60000.0 +
10157 ((TIMESTAMP_STRUCT *) dp)->second * 1000.0 +
10158 ((TIMESTAMP_STRUCT *) dp)->fraction / 1.0E6)
10159 / 86400000.0;
10160 sqlite3_bind_double(stmt, si, v);
10161 if (d->trace) {
10162 fprintf(d->trace, "-- parameter %d: %g\n", si, v);
10163 fflush(d->trace);
10164 }
10165 } else {
10166 int frac;
10167
10168 frac = (int) ((TIMESTAMP_STRUCT *) dp)->fraction;
10169 frac /= 1000000;
10170 frac = frac % 1000;
10171 if (frac < 0) {
10172 frac = 0;
10173 }
10174 if (c->prec && c->prec <= 16) {
10175 sprintf(strbuf, "%04d-%02d-%02d %02d:%02d:00.000",
10176 ((TIMESTAMP_STRUCT *) dp)->year,
10177 ((TIMESTAMP_STRUCT *) dp)->month,
10178 ((TIMESTAMP_STRUCT *) dp)->day,
10179 ((TIMESTAMP_STRUCT *) dp)->hour,
10180 ((TIMESTAMP_STRUCT *) dp)->minute);
10181 } else if (c->prec && c->prec <= 19) {
10182 sprintf(strbuf, "%04d-%02d-%02d %02d:%02d:%02d.000",
10183 ((TIMESTAMP_STRUCT *) dp)->year,
10184 ((TIMESTAMP_STRUCT *) dp)->month,
10185 ((TIMESTAMP_STRUCT *) dp)->day,
10186 ((TIMESTAMP_STRUCT *) dp)->hour,
10187 ((TIMESTAMP_STRUCT *) dp)->minute,
10188 ((TIMESTAMP_STRUCT *) dp)->second);
10189 } else {
10190 sprintf(strbuf, "%04d-%02d-%02d %02d:%02d:%02d.%03d",
10191 ((TIMESTAMP_STRUCT *) dp)->year,
10192 ((TIMESTAMP_STRUCT *) dp)->month,
10193 ((TIMESTAMP_STRUCT *) dp)->day,
10194 ((TIMESTAMP_STRUCT *) dp)->hour,
10195 ((TIMESTAMP_STRUCT *) dp)->minute,
10196 ((TIMESTAMP_STRUCT *) dp)->second,
10197 frac);
10198 }
10199 sqlite3_bind_text(stmt, si, strbuf, -1, SQLITE_TRANSIENT);
10200 if (d->trace) {
10201 fprintf(d->trace, "-- parameter %d: '%s'\n", si, strbuf);
10202 fflush(d->trace);
10203 }
10204 }
10205 break;
10206 default:
10207 setstat(s, -1, "unsupported column type in positional update",
10208 (*s->ov3) ? "HY000" : "S1000");
10209 return SQL_ERROR;
10210 }
10211 return SQL_SUCCESS;
10212}
10213
10225static SQLRETURN
10226setposibind(STMT *s, sqlite3_stmt *stmt, int i, int si, int rsi)
10227{
10228 DBC *d = (DBC *) s->dbc;
10229 char **data;
10230 int pos;
10231
10232 pos = s->rowprs;
10233 if (pos < 0) {
10234 setstat(s, -1, "row out of range", (*s->ov3) ? "HY107" : "S1107");
10235 return SQL_ERROR;
10236 }
10237 pos += rsi;
10238 data = s->rows + s->ncols + (pos * s->ncols) + i;
10239 if (*data == NULL) {
10240 sqlite3_bind_null(stmt, si);
10241 if (d->trace) {
10242 fprintf(d->trace, "-- parameter %d: NULL\n", si);
10243 fflush(d->trace);
10244 }
10245 } else {
10246 sqlite3_bind_text(stmt, si, *data, -1, SQLITE_STATIC);
10247 if (d->trace) {
10248 fprintf(d->trace, "-- parameter %d: '%s'\n", si, *data);
10249 fflush(d->trace);
10250 }
10251 }
10252 return SQL_SUCCESS;
10253}
10254
10262static SQLRETURN
10263setposrefr(STMT *s, int rsi)
10264{
10265 int i, withinfo = 0;
10266 SQLRETURN ret = SQL_SUCCESS;
10267
10268 for (i = 0; s->bindcols && i < s->ncols; i++) {
10269 BINDCOL *b = &s->bindcols[i];
10270 SQLPOINTER dp = 0;
10271 SQLLEN *lp = 0;
10272
10273 b->offs = 0;
10274 if (b->valp) {
10275 if (s->bind_type != SQL_BIND_BY_COLUMN) {
10276 dp = (SQLPOINTER) ((char *) b->valp + s->bind_type * rsi);
10277 } else {
10278 dp = (SQLPOINTER) ((char *) b->valp + b->max * rsi);
10279 }
10280 if (s->bind_offs) {
10281 dp = (SQLPOINTER) ((char *) dp + *s->bind_offs);
10282 }
10283 }
10284 if (b->lenp) {
10285 if (s->bind_type != SQL_BIND_BY_COLUMN) {
10286 lp = (SQLLEN *) ((char *) b->lenp + s->bind_type * rsi);
10287 } else {
10288 lp = b->lenp + rsi;
10289 }
10290 if (s->bind_offs) {
10291 lp = (SQLLEN *) ((char *) lp + *s->bind_offs);
10292 }
10293 }
10294 if (dp || lp) {
10295 int rowp = s->rowp;
10296
10297 s->rowp = s->rowprs + rsi;
10298 ret = getrowdata(s, (SQLUSMALLINT) i, b->type, dp,
10299 b->max, lp, 0);
10300 s->rowp = rowp;
10301 if (!SQL_SUCCEEDED(ret)) {
10302 s->row_status0[rsi] = SQL_ROW_ERROR;
10303 break;
10304 }
10305 if (ret != SQL_SUCCESS) {
10306 withinfo = 1;
10307#ifdef SQL_ROW_SUCCESS_WITH_INFO
10308 s->row_status0[rsi] = SQL_ROW_SUCCESS_WITH_INFO;
10309#endif
10310 }
10311 }
10312 }
10313 if (SQL_SUCCEEDED(ret)) {
10314 ret = withinfo ? SQL_SUCCESS_WITH_INFO : SQL_SUCCESS;
10315 }
10316 return ret;
10317}
10318
10328static SQLRETURN
10329drvsetpos(SQLHSTMT stmt, SQLSETPOSIROW row, SQLUSMALLINT op, SQLUSMALLINT lock)
10330{
10331 STMT *s = (STMT *) stmt;
10332 DBC *d = (DBC *) s->dbc;
10333 int rowp, i, k, rc, nretry = 0;
10334 dstr *sql = 0;
10335 const char *endp;
10336 sqlite3_stmt *s3stmt = NULL;
10337 SQLRETURN ret;
10338
10339 if (lock != SQL_LOCK_NO_CHANGE) {
10340 setstat(s, -1, "unsupported locking mode",
10341 (*s->ov3) ? "HY000" : "S1000");
10342 return SQL_ERROR;
10343 }
10344 if (s->isselect != 1 || s->curtype != SQL_CURSOR_STATIC) {
10345 setstat(s, -1, "incompatible statement",
10346 (*s->ov3) ? "HY000" : "S1000");
10347 return SQL_ERROR;
10348 }
10349 if (op == SQL_ADD) {
10350 if (s->one_tbl <= 0) {
10351 setstat(s, -1, "incompatible rowset",
10352 (*s->ov3) ? "HY000" : "S1000");
10353 return SQL_ERROR;
10354 }
10355 if (row == 0 || row > s->rowset_size + 1) {
10356 goto rowoor;
10357 }
10358 ret = chkunbound(s);
10359 if (ret != SQL_SUCCESS) {
10360 return ret;
10361 }
10362 sql = dsappend(sql, "INSERT INTO ");
10363 if (s->dyncols[0].db && s->dyncols[0].db[0]) {
10364 sql = dsappendq(sql, s->dyncols[0].db);
10365 sql = dsappend(sql, ".");
10366 }
10367 sql = dsappendq(sql, s->dyncols[0].table);
10368 for (i = 0; i < s->ncols; i++) {
10369 sql = dsappend(sql, (i > 0) ? "," : "(");
10370 sql = dsappendq(sql, s->dyncols[i].column);
10371 }
10372 sql = dsappend(sql, ") VALUES ");
10373 for (i = 0; i < s->ncols; i++) {
10374 sql = dsappend(sql, (i > 0) ? ",?" : "(?");
10375 }
10376 sql = dsappend(sql, ")");
10377 if (dserr(sql)) {
10378 dsfree(sql);
10379 return nomem(s);
10380 }
10381#if defined(HAVE_SQLITE3PREPAREV2) && (HAVE_SQLITE3PREPAREV2)
10382 dbtraceapi(d, "sqlite3_prepare_v2", dsval(sql));
10383#else
10384 dbtraceapi(d, "sqlite3_prepare", dsval(sql));
10385#endif
10386 do {
10387 s3stmt = NULL;
10388#if defined(HAVE_SQLITE3PREPAREV2) && (HAVE_SQLITE3PREPAREV2)
10389 rc = sqlite3_prepare_v2(d->sqlite, dsval(sql), -1,
10390 &s3stmt, &endp);
10391#else
10392 rc = sqlite3_prepare(d->sqlite, dsval(sql), -1,
10393 &s3stmt, &endp);
10394#endif
10395 if (rc != SQLITE_OK) {
10396 if (s3stmt) {
10397 sqlite3_finalize(s3stmt);
10398 s3stmt = NULL;
10399 }
10400 }
10401 } while (rc == SQLITE_SCHEMA && (++nretry) < 2);
10402 dbtracerc(d, rc, NULL);
10403 dsfree(sql);
10404 if (rc != SQLITE_OK) {
10405istmterr:
10406 setstat(s, rc, "%s (%d)", (*s->ov3) ? "HY000" : "S1000",
10407 sqlite3_errmsg(d->sqlite), rc);
10408 if (s3stmt) {
10409 dbtraceapi(d, "sqlite3_finalize", NULL);
10410 sqlite3_finalize(s3stmt);
10411 }
10412 return SQL_ERROR;
10413 }
10414 for (i = 0, k = 1; s->bindcols && i < s->ncols; i++) {
10415 ret = setposbind(s, s3stmt, i, k, row - 1);
10416 if (ret != SQL_SUCCESS) {
10417 dbtraceapi(d, "sqlite3_finalize", NULL);
10418 sqlite3_finalize(s3stmt);
10419 return ret;
10420 }
10421 k++;
10422 }
10423 rc = sqlite3_step(s3stmt);
10424 if (rc != SQLITE_DONE) {
10425 goto istmterr;
10426 }
10427 sqlite3_finalize(s3stmt);
10428 if (sqlite3_changes(d->sqlite) > 0 && row <= s->rowset_size) {
10429 if (s->row_status0) {
10430 s->row_status0[row - 1] = SQL_ROW_ADDED;
10431 }
10432 if (s->row_status) {
10433 s->row_status[row - 1] = SQL_ROW_ADDED;
10434 }
10435 }
10436 return SQL_SUCCESS;
10437 } else if (op == SQL_UPDATE || op == SQL_DELETE) {
10438 if (s->one_tbl <= 0 || s->has_pk <= 0) {
10439 setstat(s, -1, "incompatible rowset",
10440 (*s->ov3) ? "HY000" : "S1000");
10441 return SQL_ERROR;
10442 }
10443 if (row == 0) {
10444 ret = SQL_SUCCESS;
10445 for (i = 1; i <= s->rowset_size; i++) {
10446 ret = drvsetpos(stmt, i, op, lock);
10447 if (!SQL_SUCCEEDED(ret)) {
10448 break;
10449 }
10450 }
10451 return ret;
10452 }
10453 if (row > s->rowset_size) {
10454 goto rowoor;
10455 }
10456 }
10457 if (op != SQL_POSITION && op != SQL_REFRESH &&
10458 op != SQL_DELETE && op != SQL_UPDATE) {
10459 return drvunimplstmt(stmt);
10460 }
10461 if (op == SQL_POSITION) {
10462 rowp = s->rowp + row - 1;
10463 if (!s->rows || row == 0 || rowp < -1 || rowp >= s->nrows) {
10464rowoor:
10465 setstat(s, -1, "row out of range", (*s->ov3) ? "HY107" : "S1107");
10466 return SQL_ERROR;
10467 }
10468 s->rowp = rowp;
10469 } else if (op == SQL_REFRESH) {
10470 if (row > s->rowset_size) {
10471 goto rowoor;
10472 }
10473 if (row == 0) {
10474 ret = SQL_SUCCESS;
10475 for (i = 0; i < s->rowset_size; i++) {
10476 ret = setposrefr(s, i);
10477 if (!SQL_SUCCEEDED(ret)) {
10478 break;
10479 }
10480 }
10481 return ret;
10482 }
10483 return setposrefr(s, row - 1);
10484 } else if (op == SQL_DELETE) {
10485 sql = dsappend(sql, "DELETE FROM ");
10486 if (s->dyncols[0].db && s->dyncols[0].db[0]) {
10487 sql = dsappendq(sql, s->dyncols[0].db);
10488 sql = dsappend(sql, ".");
10489 }
10490 sql = dsappendq(sql, s->dyncols[0].table);
10491 for (i = k = 0; i < s->ncols; i++) {
10492 if (s->dyncols[i].ispk <= 0) {
10493 continue;
10494 }
10495 sql = dsappend(sql, (k > 0) ? " AND " : " WHERE ");
10496 sql = dsappendq(sql, s->dyncols[i].column);
10497 sql = dsappend(sql, " = ?");
10498 k++;
10499 }
10500 if (dserr(sql)) {
10501 dsfree(sql);
10502 return nomem(s);
10503 }
10504#if defined(HAVE_SQLITE3PREPAREV2) && (HAVE_SQLITE3PREPAREV2)
10505 dbtraceapi(d, "sqlite3_prepare_v2", dsval(sql));
10506#else
10507 dbtraceapi(d, "sqlite3_prepare", dsval(sql));
10508#endif
10509 do {
10510 s3stmt = NULL;
10511#if defined(HAVE_SQLITE3PREPAREV2) && (HAVE_SQLITE3PREPAREV2)
10512 rc = sqlite3_prepare_v2(d->sqlite, dsval(sql), -1,
10513 &s3stmt, &endp);
10514#else
10515 rc = sqlite3_prepare(d->sqlite, dsval(sql), -1,
10516 &s3stmt, &endp);
10517#endif
10518 if (rc != SQLITE_OK) {
10519 if (s3stmt) {
10520 sqlite3_finalize(s3stmt);
10521 s3stmt = NULL;
10522 }
10523 }
10524 } while (rc == SQLITE_SCHEMA && (++nretry) < 2);
10525 dbtracerc(d, rc, NULL);
10526 dsfree(sql);
10527 if (rc != SQLITE_OK) {
10528dstmterr:
10529 setstat(s, rc, "%s (%d)", (*s->ov3) ? "HY000" : "S1000",
10530 sqlite3_errmsg(d->sqlite), rc);
10531 if (s3stmt) {
10532 dbtraceapi(d, "sqlite3_finalize", NULL);
10533 sqlite3_finalize(s3stmt);
10534 }
10535 return SQL_ERROR;
10536 }
10537 for (i = 0, k = 1; s->bindcols && i < s->ncols; i++) {
10538 if (s->dyncols[i].ispk <= 0) {
10539 continue;
10540 }
10541 ret = setposibind(s, s3stmt, i, k, row - 1);
10542 if (ret != SQL_SUCCESS) {
10543 dbtraceapi(d, "sqlite3_finalize", NULL);
10544 sqlite3_finalize(s3stmt);
10545 return ret;
10546 }
10547 k++;
10548 }
10549 rc = sqlite3_step(s3stmt);
10550 if (rc != SQLITE_DONE) {
10551 goto dstmterr;
10552 }
10553 sqlite3_finalize(s3stmt);
10554 if (sqlite3_changes(d->sqlite) > 0) {
10555 if (s->row_status0) {
10556 s->row_status0[row - 1] = SQL_ROW_DELETED;
10557 }
10558 if (s->row_status) {
10559 s->row_status[row - 1] = SQL_ROW_DELETED;
10560 }
10561 }
10562 return SQL_SUCCESS;
10563 } else if (op == SQL_UPDATE) {
10564 ret = chkunbound(s);
10565 if (ret != SQL_SUCCESS) {
10566 return ret;
10567 }
10568 sql = dsappend(sql, "UPDATE ");
10569 if (s->dyncols[0].db && s->dyncols[0].db[0]) {
10570 sql = dsappendq(sql, s->dyncols[0].db);
10571 sql = dsappend(sql, ".");
10572 }
10573 sql = dsappendq(sql, s->dyncols[0].table);
10574 for (i = 0; i < s->ncols; i++) {
10575 sql = dsappend(sql, (i > 0) ? ", " : " SET ");
10576 sql = dsappendq(sql, s->dyncols[i].column);
10577 sql = dsappend(sql, " = ?");
10578 }
10579 for (i = k = 0; i < s->ncols; i++) {
10580 if (s->dyncols[i].ispk <= 0) {
10581 continue;
10582 }
10583 sql = dsappend(sql, (k > 0) ? " AND " : " WHERE ");
10584 sql = dsappendq(sql, s->dyncols[i].column);
10585 sql = dsappend(sql, " = ?");
10586 k++;
10587 }
10588 if (dserr(sql)) {
10589 dsfree(sql);
10590 return nomem(s);
10591 }
10592#if defined(HAVE_SQLITE3PREPAREV2) && (HAVE_SQLITE3PREPAREV2)
10593 dbtraceapi(d, "sqlite3_prepare_v2", dsval(sql));
10594#else
10595 dbtraceapi(d, "sqlite3_prepare", dsval(sql));
10596#endif
10597 do {
10598 s3stmt = NULL;
10599#if defined(HAVE_SQLITE3PREPAREV2) && (HAVE_SQLITE3PREPAREV2)
10600 rc = sqlite3_prepare_v2(d->sqlite, dsval(sql), -1,
10601 &s3stmt, &endp);
10602#else
10603 rc = sqlite3_prepare(d->sqlite, dsval(sql), -1,
10604 &s3stmt, &endp);
10605#endif
10606 if (rc != SQLITE_OK) {
10607 if (s3stmt) {
10608 sqlite3_finalize(s3stmt);
10609 s3stmt = NULL;
10610 }
10611 }
10612 } while (rc == SQLITE_SCHEMA && (++nretry) < 2);
10613 dbtracerc(d, rc, NULL);
10614 dsfree(sql);
10615 if (rc != SQLITE_OK) {
10616ustmterr:
10617 setstat(s, rc, "%s (%d)", (*s->ov3) ? "HY000" : "S1000",
10618 sqlite3_errmsg(d->sqlite), rc);
10619 if (s3stmt) {
10620 dbtraceapi(d, "sqlite3_finalize", NULL);
10621 sqlite3_finalize(s3stmt);
10622 }
10623 return SQL_ERROR;
10624 }
10625 for (i = 0, k = 1; s->bindcols && i < s->ncols; i++) {
10626 ret = setposbind(s, s3stmt, i, k, row - 1);
10627 if (ret != SQL_SUCCESS) {
10628 dbtraceapi(d, "sqlite3_finalize", NULL);
10629 sqlite3_finalize(s3stmt);
10630 return ret;
10631 }
10632 k++;
10633 }
10634 for (i = 0; s->bindcols && i < s->ncols; i++) {
10635 if (s->dyncols[i].ispk <= 0) {
10636 continue;
10637 }
10638 ret = setposibind(s, s3stmt, i, k, row - 1);
10639 if (ret != SQL_SUCCESS) {
10640 dbtraceapi(d, "sqlite3_finalize", NULL);
10641 sqlite3_finalize(s3stmt);
10642 return ret;
10643 }
10644 k++;
10645 }
10646 rc = sqlite3_step(s3stmt);
10647 if (rc != SQLITE_DONE) {
10648 goto ustmterr;
10649 }
10650 sqlite3_finalize(s3stmt);
10651 if (sqlite3_changes(d->sqlite) > 0) {
10652 if (s->row_status0) {
10653 s->row_status0[row - 1] = SQL_ROW_UPDATED;
10654 }
10655 if (s->row_status) {
10656 s->row_status[row - 1] = SQL_ROW_UPDATED;
10657 }
10658 }
10659 return SQL_SUCCESS;
10660 }
10661 return SQL_SUCCESS;
10662}
10663
10673SQLRETURN SQL_API
10674SQLSetPos(SQLHSTMT stmt, SQLSETPOSIROW row, SQLUSMALLINT op, SQLUSMALLINT lock)
10675{
10676 SQLRETURN ret;
10677
10679 ret = drvsetpos(stmt, row, op, lock);
10681 return ret;
10682}
10683
10691static SQLRETURN
10692drvbulkoperations(SQLHSTMT stmt, SQLSMALLINT op)
10693{
10694 STMT *s = (STMT *) stmt;
10695 DBC *d = (DBC *) s->dbc;
10696 int row, i, k, rc, nretry = 0;
10697 dstr *sql = 0;
10698 const char *endp;
10699 sqlite3_stmt *s3stmt = NULL;
10700 SQLRETURN ret;
10701
10702 if (s->isselect != 1 || s->curtype != SQL_CURSOR_STATIC) {
10703 setstat(s, -1, "incompatible statement",
10704 (*s->ov3) ? "HY000" : "S1000");
10705 return SQL_ERROR;
10706 }
10707 if (op == SQL_ADD) {
10708 if (s->one_tbl <= 0) {
10709 setstat(s, -1, "incompatible rowset",
10710 (*s->ov3) ? "HY000" : "S1000");
10711 return SQL_ERROR;
10712 }
10713 ret = chkunbound(s);
10714 if (ret != SQL_SUCCESS) {
10715 return ret;
10716 }
10717 sql = dsappend(sql, "INSERT INTO ");
10718 if (s->dyncols[0].db && s->dyncols[0].db[0]) {
10719 sql = dsappendq(sql, s->dyncols[0].db);
10720 sql = dsappend(sql, ".");
10721 }
10722 sql = dsappendq(sql, s->dyncols[0].table);
10723 for (i = 0; i < s->ncols; i++) {
10724 sql = dsappend(sql, (i > 0) ? "," : "(");
10725 sql = dsappendq(sql, s->dyncols[i].column);
10726 }
10727 sql = dsappend(sql, ") VALUES ");
10728 for (i = 0; i < s->ncols; i++) {
10729 sql = dsappend(sql, (i > 0) ? ",?" : "(?");
10730 }
10731 sql = dsappend(sql, ")");
10732 if (dserr(sql)) {
10733 dsfree(sql);
10734 return nomem(s);
10735 }
10736#if defined(HAVE_SQLITE3PREPAREV2) && (HAVE_SQLITE3PREPAREV2)
10737 dbtraceapi(d, "sqlite3_prepare_v2", dsval(sql));
10738#else
10739 dbtraceapi(d, "sqlite3_prepare", dsval(sql));
10740#endif
10741 do {
10742 s3stmt = NULL;
10743#if defined(HAVE_SQLITE3PREPAREV2) && (HAVE_SQLITE3PREPAREV2)
10744 rc = sqlite3_prepare_v2(d->sqlite, dsval(sql), -1,
10745 &s3stmt, &endp);
10746#else
10747 rc = sqlite3_prepare(d->sqlite, dsval(sql), -1,
10748 &s3stmt, &endp);
10749#endif
10750 if (rc != SQLITE_OK) {
10751 if (s3stmt) {
10752 sqlite3_finalize(s3stmt);
10753 s3stmt = NULL;
10754 }
10755 }
10756 } while (rc == SQLITE_SCHEMA && (++nretry) < 2);
10757 dbtracerc(d, rc, NULL);
10758 dsfree(sql);
10759 if (rc != SQLITE_OK) {
10760 setstat(s, rc, "%s (%d)", (*s->ov3) ? "HY000" : "S1000",
10761 sqlite3_errmsg(d->sqlite), rc);
10762 if (s3stmt) {
10763 dbtraceapi(d, "sqlite3_finalize", NULL);
10764 sqlite3_finalize(s3stmt);
10765 }
10766 return SQL_ERROR;
10767 }
10768 for (row = 0; row < s->rowset_size; row++) {
10769 for (i = 0, k = 1; s->bindcols && i < s->ncols; i++) {
10770 ret = setposbind(s, s3stmt, i, k, row);
10771 if (ret != SQL_SUCCESS) {
10772istmterr:
10773 if (s->row_status0) {
10774 s->row_status0[row] = SQL_ROW_ERROR;
10775 }
10776 if (s->row_status) {
10777 s->row_status[row] = SQL_ROW_ERROR;
10778 }
10779 dbtraceapi(d, "sqlite3_finalize", NULL);
10780 sqlite3_finalize(s3stmt);
10781 return ret;
10782 }
10783 k++;
10784 }
10785 rc = sqlite3_step(s3stmt);
10786 if (rc != SQLITE_DONE) {
10787 setstat(s, rc, "%s (%d)", (*s->ov3) ? "HY000" : "S1000",
10788 sqlite3_errmsg(d->sqlite), rc);
10789 ret = SQL_ERROR;
10790 goto istmterr;
10791 }
10792 if (sqlite3_changes(d->sqlite) > 0) {
10793 if (s->row_status0) {
10794 s->row_status0[row] = SQL_ROW_ADDED;
10795 }
10796 if (s->row_status) {
10797 s->row_status[row] = SQL_ROW_ADDED;
10798 }
10799 }
10800 if (s->bkmrk == SQL_UB_VARIABLE &&
10801 s->bkmrkcol.type == SQL_C_VARBOOKMARK &&
10802 s->bkmrkcol.valp) {
10803 SQLPOINTER *val;
10804
10805 if (s->bind_type != SQL_BIND_BY_COLUMN) {
10806 val = (SQLPOINTER)
10807 ((char *) s->bkmrkcol.valp + s->bind_type * row);
10808 } else {
10809 val = (SQLPOINTER)
10810 ((char *) s->bkmrkcol.valp + s->bkmrkcol.max * row);
10811 }
10812 if (s->bind_offs) {
10813 val = (SQLPOINTER) ((char *) val + *s->bind_offs);
10814 }
10815 *(sqlite_int64 *) val = sqlite3_last_insert_rowid(d->sqlite);
10816 if (s->bkmrkcol.lenp) {
10817 SQLLEN *ival;
10818
10819 if (s->bind_type != SQL_BIND_BY_COLUMN) {
10820 ival = (SQLLEN *)
10821 ((char *) s->bkmrkcol.lenp + s->bind_type * row);
10822 } else {
10823 ival = &s->bkmrkcol.lenp[row];
10824 }
10825 if (s->bind_offs) {
10826 ival = (SQLLEN *) ((char *) ival + *s->bind_offs);
10827 }
10828 *ival = sizeof (sqlite_int64);
10829 }
10830 }
10831 dbtraceapi(d, "sqlite3_reset", NULL);
10832 sqlite3_reset(s3stmt);
10833 }
10834 dbtraceapi(d, "sqlite3_finalize", NULL);
10835 sqlite3_finalize(s3stmt);
10836 return SQL_SUCCESS;
10837 } else if (op == SQL_DELETE_BY_BOOKMARK) {
10838 if (s->has_rowid < 0 ||
10839 s->bkmrk != SQL_UB_VARIABLE ||
10840 s->bkmrkcol.type != SQL_C_VARBOOKMARK ||
10841 !s->bkmrkcol.valp) {
10842 setstat(s, -1, "incompatible rowset",
10843 (*s->ov3) ? "HY000" : "S1000");
10844 return SQL_ERROR;
10845 }
10846 sql = dsappend(sql, "DELETE FROM ");
10847 if (s->dyncols[0].db && s->dyncols[0].db[0]) {
10848 sql = dsappendq(sql, s->dyncols[0].db);
10849 sql = dsappend(sql, ".");
10850 }
10851 sql = dsappendq(sql, s->dyncols[0].table);
10852 sql = dsappend(sql, " WHERE ");
10853 sql = dsappendq(sql, s->dyncols[0].column);
10854 sql = dsappend(sql, " = ?");
10855 if (dserr(sql)) {
10856 dsfree(sql);
10857 return nomem(s);
10858 }
10859#if defined(HAVE_SQLITE3PREPAREV2) && (HAVE_SQLITE3PREPAREV2)
10860 dbtraceapi(d, "sqlite3_prepare_v2", dsval(sql));
10861#else
10862 dbtraceapi(d, "sqlite3_prepare", dsval(sql));
10863#endif
10864 do {
10865 s3stmt = NULL;
10866#if defined(HAVE_SQLITE3PREPAREV2) && (HAVE_SQLITE3PREPAREV2)
10867 rc = sqlite3_prepare_v2(d->sqlite, dsval(sql), -1,
10868 &s3stmt, &endp);
10869#else
10870 rc = sqlite3_prepare(d->sqlite, dsval(sql), -1,
10871 &s3stmt, &endp);
10872#endif
10873 if (rc != SQLITE_OK) {
10874 if (s3stmt) {
10875 sqlite3_finalize(s3stmt);
10876 s3stmt = NULL;
10877 }
10878 }
10879 } while (rc == SQLITE_SCHEMA && (++nretry) < 2);
10880 dbtracerc(d, rc, NULL);
10881 dsfree(sql);
10882 if (rc != SQLITE_OK) {
10883 setstat(s, rc, "%s (%d)", (*s->ov3) ? "HY000" : "S1000",
10884 sqlite3_errmsg(d->sqlite), rc);
10885 if (s3stmt) {
10886 dbtraceapi(d, "sqlite3_finalize", NULL);
10887 sqlite3_finalize(s3stmt);
10888 }
10889 return SQL_ERROR;
10890 }
10891 for (row = 0; row < s->rowset_size; row++) {
10892 SQLPOINTER *val;
10893 sqlite_int64 rowid;
10894
10895 if (s->bind_type != SQL_BIND_BY_COLUMN) {
10896 val = (SQLPOINTER)
10897 ((char *) s->bkmrkcol.valp + s->bind_type * row);
10898 } else {
10899 val = (SQLPOINTER)
10900 ((char *) s->bkmrkcol.valp + s->bkmrkcol.max * row);
10901 }
10902 if (s->bind_offs) {
10903 val = (SQLPOINTER) ((char *) val + *s->bind_offs);
10904 }
10905 if (s->bkmrkcol.lenp) {
10906 SQLLEN *ival;
10907
10908 if (s->bind_type != SQL_BIND_BY_COLUMN) {
10909 ival = (SQLLEN *)
10910 ((char *) s->bkmrkcol.lenp + s->bind_type * row);
10911 } else {
10912 ival = &s->bkmrkcol.lenp[row];
10913 }
10914 if (s->bind_offs) {
10915 ival = (SQLLEN *) ((char *) ival + *s->bind_offs);
10916 }
10917 if (*ival != sizeof (sqlite_int64)) {
10918 continue;
10919 }
10920 }
10921 rowid = *(sqlite_int64 *) val;
10922 sqlite3_bind_int64(s3stmt, 1, rowid);
10923 if (d->trace) {
10924 fprintf(d->trace,
10925#ifdef _WIN32
10926 "-- parameter 1: %I64d\n",
10927#else
10928 "-- parameter 1: %lld\n",
10929#endif
10930 rowid);
10931 fflush(d->trace);
10932 }
10933 rc = sqlite3_step(s3stmt);
10934 if (rc != SQLITE_DONE) {
10935 setstat(s, rc, "%s (%d)", (*s->ov3) ? "HY000" : "S1000",
10936 sqlite3_errmsg(d->sqlite), rc);
10937 if (s->row_status0) {
10938 s->row_status0[row] = SQL_ROW_ERROR;
10939 }
10940 if (s->row_status) {
10941 s->row_status[row] = SQL_ROW_ERROR;
10942 }
10943 dbtraceapi(d, "sqlite3_finalize", NULL);
10944 sqlite3_finalize(s3stmt);
10945 return SQL_ERROR;
10946 }
10947 if (sqlite3_changes(d->sqlite) > 0) {
10948 if (s->row_status0) {
10949 s->row_status0[row] = SQL_ROW_DELETED;
10950 }
10951 if (s->row_status) {
10952 s->row_status[row] = SQL_ROW_DELETED;
10953 }
10954 }
10955 dbtraceapi(d, "sqlite3_reset", NULL);
10956 sqlite3_reset(s3stmt);
10957 }
10958 dbtraceapi(d, "sqlite3_finalize", NULL);
10959 sqlite3_finalize(s3stmt);
10960 return SQL_SUCCESS;
10961 } else if (op == SQL_UPDATE_BY_BOOKMARK) {
10962 if (s->has_rowid < 0 ||
10963 s->bkmrk != SQL_UB_VARIABLE ||
10964 s->bkmrkcol.type != SQL_C_VARBOOKMARK ||
10965 !s->bkmrkcol.valp) {
10966 setstat(s, -1, "incompatible rowset",
10967 (*s->ov3) ? "HY000" : "S1000");
10968 return SQL_ERROR;
10969 }
10970 ret = chkunbound(s);
10971 if (ret != SQL_SUCCESS) {
10972 return ret;
10973 }
10974 sql = dsappend(sql, "UPDATE ");
10975 if (s->dyncols[0].db && s->dyncols[0].db[0]) {
10976 sql = dsappendq(sql, s->dyncols[0].db);
10977 sql = dsappend(sql, ".");
10978 }
10979 sql = dsappendq(sql, s->dyncols[0].table);
10980 for (i = 0, k = 0; i < s->ncols; i++) {
10981 sql = dsappend(sql, (k > 0) ? ", " : " SET ");
10982 sql = dsappendq(sql, s->dyncols[i].column);
10983 sql = dsappend(sql, " = ?");
10984 k++;
10985 }
10986 sql = dsappend(sql, " WHERE ");
10987 sql = dsappendq(sql, s->dyncols[s->has_rowid].column);
10988 sql = dsappend(sql, " = ?");
10989 if (dserr(sql)) {
10990 dsfree(sql);
10991 return nomem(s);
10992 }
10993#if defined(HAVE_SQLITE3PREPAREV2) && (HAVE_SQLITE3PREPAREV2)
10994 dbtraceapi(d, "sqlite3_prepare_v2", dsval(sql));
10995#else
10996 dbtraceapi(d, "sqlite3_prepare", dsval(sql));
10997#endif
10998 do {
10999 s3stmt = NULL;
11000#if defined(HAVE_SQLITE3PREPAREV2) && (HAVE_SQLITE3PREPAREV2)
11001 rc = sqlite3_prepare_v2(d->sqlite, dsval(sql), -1,
11002 &s3stmt, &endp);
11003#else
11004 rc = sqlite3_prepare(d->sqlite, dsval(sql), -1,
11005 &s3stmt, &endp);
11006#endif
11007 if (rc != SQLITE_OK) {
11008 if (s3stmt) {
11009 sqlite3_finalize(s3stmt);
11010 s3stmt = NULL;
11011 }
11012 }
11013 } while (rc == SQLITE_SCHEMA && (++nretry) < 2);
11014 dbtracerc(d, rc, NULL);
11015 dsfree(sql);
11016 if (rc != SQLITE_OK) {
11017 setstat(s, rc, "%s (%d)", (*s->ov3) ? "HY000" : "S1000",
11018 sqlite3_errmsg(d->sqlite), rc);
11019 if (s3stmt) {
11020 dbtraceapi(d, "sqlite3_finalize", NULL);
11021 sqlite3_finalize(s3stmt);
11022 }
11023 return SQL_ERROR;
11024 }
11025 for (row = 0; row < s->rowset_size; row++) {
11026 SQLPOINTER *val;
11027 sqlite_int64 rowid;
11028
11029 if (s->bind_type != SQL_BIND_BY_COLUMN) {
11030 val = (SQLPOINTER)
11031 ((char *) s->bkmrkcol.valp + s->bind_type * row);
11032 } else {
11033 val = (SQLPOINTER)
11034 ((char *) s->bkmrkcol.valp + s->bkmrkcol.max * row);
11035 }
11036 if (s->bind_offs) {
11037 val = (SQLPOINTER) ((char *) val + *s->bind_offs);
11038 }
11039 if (s->bkmrkcol.lenp) {
11040 SQLLEN *ival;
11041
11042 if (s->bind_type != SQL_BIND_BY_COLUMN) {
11043 ival = (SQLLEN *)
11044 ((char *) s->bkmrkcol.lenp + s->bind_type * row);
11045 } else {
11046 ival = &s->bkmrkcol.lenp[row];
11047 }
11048 if (s->bind_offs) {
11049 ival = (SQLLEN *) ((char *) ival + *s->bind_offs);
11050 }
11051 if (*ival != sizeof (sqlite_int64)) {
11052 continue;
11053 }
11054 }
11055 for (i = 0, k = 1; s->bindcols && i < s->ncols; i++) {
11056 ret = setposbind(s, s3stmt, i, k, row);
11057 if (ret != SQL_SUCCESS) {
11058ustmterr:
11059 if (s->row_status0) {
11060 s->row_status0[row] = SQL_ROW_ERROR;
11061 }
11062 if (s->row_status) {
11063 s->row_status[row] = SQL_ROW_ERROR;
11064 }
11065 dbtraceapi(d, "sqlite3_finalize", NULL);
11066 sqlite3_finalize(s3stmt);
11067 return ret;
11068 }
11069 k++;
11070 }
11071 rowid = *(sqlite_int64 *) val;
11072 sqlite3_bind_int64(s3stmt, k, rowid);
11073 if (d->trace) {
11074 fprintf(d->trace,
11075#ifdef _WIN32
11076 "-- parameter %d: %I64d\n",
11077#else
11078 "-- parameter %d: %lld\n",
11079#endif
11080 k, rowid);
11081 fflush(d->trace);
11082 }
11083 rc = sqlite3_step(s3stmt);
11084 if (rc != SQLITE_DONE) {
11085 setstat(s, rc, "%s (%d)", (*s->ov3) ? "HY000" : "S1000",
11086 sqlite3_errmsg(d->sqlite), rc);
11087 ret = SQL_ERROR;
11088 goto ustmterr;
11089 }
11090 if (sqlite3_changes(d->sqlite) > 0) {
11091 if (s->row_status0) {
11092 s->row_status0[row] = SQL_ROW_UPDATED;
11093 }
11094 if (s->row_status) {
11095 s->row_status[row] = SQL_ROW_UPDATED;
11096 }
11097 }
11098 dbtraceapi(d, "sqlite3_reset", NULL);
11099 sqlite3_reset(s3stmt);
11100 }
11101 dbtraceapi(d, "sqlite3_finalize", NULL);
11102 sqlite3_finalize(s3stmt);
11103 return SQL_SUCCESS;
11104 }
11105 setstat(s, -1, "unsupported operation", (*s->ov3) ? "HY000" : "S1000");
11106 return SQL_ERROR;
11107}
11108
11116SQLRETURN SQL_API
11117SQLBulkOperations(SQLHSTMT stmt, SQLSMALLINT oper)
11118{
11119 SQLRETURN ret;
11120
11122 ret = drvbulkoperations(stmt, oper);
11124 return ret;
11125}
11126
11127
11132SQLRETURN SQL_API
11133SQLSetScrollOptions(SQLHSTMT stmt, SQLUSMALLINT concur, SQLLEN rowkeyset,
11134 SQLUSMALLINT rowset)
11135{
11136 SQLRETURN ret;
11137
11139 ret = drvunimplstmt(stmt);
11141 return ret;
11142}
11143
11144#define strmak(dst, src, max, lenp) { \
11145 int len = strlen(src); \
11146 int cnt = min(len + 1, max); \
11147 strncpy(dst, src, cnt); \
11148 *lenp = (cnt > len) ? len : cnt; \
11149}
11150
11161static SQLRETURN
11162drvgetinfo(SQLHDBC dbc, SQLUSMALLINT type, SQLPOINTER val, SQLSMALLINT valMax,
11163 SQLSMALLINT *valLen)
11164{
11165 DBC *d;
11166 char dummyc[301];
11167 SQLSMALLINT dummy;
11168#if defined(_WIN32) || defined(_WIN64)
11169 char pathbuf[301], *drvname;
11170#else
11171 static char drvname[] = "sqlite3odbc.so";
11172#endif
11173
11174 if (dbc == SQL_NULL_HDBC) {
11175 return SQL_INVALID_HANDLE;
11176 }
11177 d = (DBC *) dbc;
11178 if (valMax) {
11179 valMax--;
11180 }
11181 if (!valLen) {
11182 valLen = &dummy;
11183 }
11184 if (!val) {
11185 val = dummyc;
11186 valMax = sizeof (dummyc) - 1;
11187 }
11188 switch (type) {
11189 case SQL_MAX_USER_NAME_LEN:
11190 *((SQLSMALLINT *) val) = 16;
11191 *valLen = sizeof (SQLSMALLINT);
11192 break;
11193 case SQL_USER_NAME:
11194 strmak(val, "", valMax, valLen);
11195 break;
11196 case SQL_DRIVER_ODBC_VER:
11197#if 0
11198 strmak(val, (*d->ov3) ? "03.00" : "02.50", valMax, valLen);
11199#else
11200 strmak(val, "03.00", valMax, valLen);
11201#endif
11202 break;
11203 case SQL_ACTIVE_CONNECTIONS:
11204 case SQL_ACTIVE_STATEMENTS:
11205 *((SQLSMALLINT *) val) = 0;
11206 *valLen = sizeof (SQLSMALLINT);
11207 break;
11208#ifdef SQL_ASYNC_MODE
11209 case SQL_ASYNC_MODE:
11210 *((SQLUINTEGER *) val) = SQL_AM_NONE;
11211 *valLen = sizeof (SQLUINTEGER);
11212 break;
11213#endif
11214#ifdef SQL_CREATE_TABLE
11215 case SQL_CREATE_TABLE:
11216 *((SQLUINTEGER *) val) = SQL_CT_CREATE_TABLE |
11217 SQL_CT_COLUMN_DEFAULT |
11218 SQL_CT_COLUMN_CONSTRAINT |
11219 SQL_CT_CONSTRAINT_NON_DEFERRABLE;
11220 *valLen = sizeof (SQLUINTEGER);
11221 break;
11222#endif
11223#ifdef SQL_CREATE_VIEW
11224 case SQL_CREATE_VIEW:
11225 *((SQLUINTEGER *) val) = SQL_CV_CREATE_VIEW;
11226 *valLen = sizeof (SQLUINTEGER);
11227 break;
11228#endif
11229#ifdef SQL_DDL_INDEX
11230 case SQL_DDL_INDEX:
11231 *((SQLUINTEGER *) val) = SQL_DI_CREATE_INDEX | SQL_DI_DROP_INDEX;
11232 *valLen = sizeof (SQLUINTEGER);
11233 break;
11234#endif
11235#ifdef SQL_DROP_TABLE
11236 case SQL_DROP_TABLE:
11237 *((SQLUINTEGER *) val) = SQL_DT_DROP_TABLE;
11238 *valLen = sizeof (SQLUINTEGER);
11239 break;
11240#endif
11241#ifdef SQL_DROP_VIEW
11242 case SQL_DROP_VIEW:
11243 *((SQLUINTEGER *) val) = SQL_DV_DROP_VIEW;
11244 *valLen = sizeof (SQLUINTEGER);
11245 break;
11246#endif
11247#ifdef SQL_INDEX_KEYWORDS
11248 case SQL_INDEX_KEYWORDS:
11249 *((SQLUINTEGER *) val) = SQL_IK_ALL;
11250 *valLen = sizeof (SQLUINTEGER);
11251 break;
11252#endif
11253 case SQL_DATA_SOURCE_NAME:
11254 strmak(val, d->dsn ? d->dsn : "", valMax, valLen);
11255 break;
11256 case SQL_DRIVER_NAME:
11257#if defined(_WIN32) || defined(_WIN64)
11258 GetModuleFileName(hModule, pathbuf, sizeof (pathbuf));
11259 drvname = strrchr(pathbuf, '\\');
11260 if (drvname == NULL) {
11261 drvname = strrchr(pathbuf, '/');
11262 }
11263 if (drvname == NULL) {
11264 drvname = pathbuf;
11265 } else {
11266 drvname++;
11267 }
11268#endif
11269 strmak(val, drvname, valMax, valLen);
11270 break;
11271 case SQL_DRIVER_VER:
11272 strmak(val, DRIVER_VER_INFO, valMax, valLen);
11273 break;
11274 case SQL_FETCH_DIRECTION:
11275 *((SQLUINTEGER *) val) = SQL_FD_FETCH_NEXT | SQL_FD_FETCH_FIRST |
11276 SQL_FD_FETCH_LAST | SQL_FD_FETCH_PRIOR | SQL_FD_FETCH_ABSOLUTE;
11277 *valLen = sizeof (SQLUINTEGER);
11278 break;
11279 case SQL_ODBC_VER:
11280 strmak(val, (*d->ov3) ? "03.00" : "02.50", valMax, valLen);
11281 break;
11282 case SQL_ODBC_SAG_CLI_CONFORMANCE:
11283 *((SQLSMALLINT *) val) = SQL_OSCC_NOT_COMPLIANT;
11284 *valLen = sizeof (SQLSMALLINT);
11285 break;
11286 case SQL_STANDARD_CLI_CONFORMANCE:
11287 *((SQLUINTEGER *) val) = SQL_SCC_XOPEN_CLI_VERSION1;
11288 *valLen = sizeof (SQLUINTEGER);
11289 break;
11290 case SQL_SQL_CONFORMANCE:
11291 *((SQLUINTEGER *) val) = SQL_SC_SQL92_ENTRY;
11292 *valLen = sizeof (SQLUINTEGER);
11293 break;
11294 case SQL_SERVER_NAME:
11295 case SQL_DATABASE_NAME:
11296 strmak(val, d->dbname ? d->dbname : "", valMax, valLen);
11297 break;
11298 case SQL_SEARCH_PATTERN_ESCAPE:
11299 strmak(val, "\\", valMax, valLen);
11300 break;
11301 case SQL_ODBC_SQL_CONFORMANCE:
11302 *((SQLSMALLINT *) val) = SQL_OSC_MINIMUM;
11303 *valLen = sizeof (SQLSMALLINT);
11304 break;
11305 case SQL_ODBC_API_CONFORMANCE:
11306 *((SQLSMALLINT *) val) = SQL_OAC_LEVEL1;
11307 *valLen = sizeof (SQLSMALLINT);
11308 break;
11309 case SQL_DBMS_NAME:
11310 strmak(val, "SQLite", valMax, valLen);
11311 break;
11312 case SQL_DBMS_VER:
11313 strmak(val, SQLITE_VERSION, valMax, valLen);
11314 break;
11315 case SQL_COLUMN_ALIAS:
11316 case SQL_NEED_LONG_DATA_LEN:
11317 case SQL_OUTER_JOINS:
11318 strmak(val, "Y", valMax, valLen);
11319 break;
11320 case SQL_ROW_UPDATES:
11321 case SQL_ACCESSIBLE_PROCEDURES:
11322 case SQL_PROCEDURES:
11323 case SQL_EXPRESSIONS_IN_ORDERBY:
11324 case SQL_ODBC_SQL_OPT_IEF:
11325 case SQL_LIKE_ESCAPE_CLAUSE:
11326 case SQL_ORDER_BY_COLUMNS_IN_SELECT:
11327 case SQL_ACCESSIBLE_TABLES:
11328 case SQL_MULT_RESULT_SETS:
11329 case SQL_MULTIPLE_ACTIVE_TXN:
11330 case SQL_MAX_ROW_SIZE_INCLUDES_LONG:
11331 strmak(val, "N", valMax, valLen);
11332 break;
11333#ifdef SQL_CATALOG_NAME
11334 case SQL_CATALOG_NAME:
11335#if defined(_WIN32) || defined(_WIN64)
11336 strmak(val, d->xcelqrx ? "Y" : "N", valMax, valLen);
11337#else
11338 strmak(val, "N", valMax, valLen);
11339#endif
11340 break;
11341#endif
11342 case SQL_DATA_SOURCE_READ_ONLY:
11343 strmak(val, "N", valMax, valLen);
11344 break;
11345#ifdef SQL_OJ_CAPABILITIES
11346 case SQL_OJ_CAPABILITIES:
11347 *((SQLUINTEGER *) val) = SQL_OJ_LEFT;
11348 *valLen = sizeof (SQLUINTEGER);
11349 break;
11350#endif
11351#ifdef SQL_MAX_IDENTIFIER_LEN
11352 case SQL_MAX_IDENTIFIER_LEN:
11353 *((SQLUSMALLINT *) val) = 255;
11354 *valLen = sizeof (SQLUSMALLINT);
11355 break;
11356#endif
11357 case SQL_CONCAT_NULL_BEHAVIOR:
11358 *((SQLSMALLINT *) val) = SQL_CB_NULL;
11359 *valLen = sizeof (SQLSMALLINT);
11360 break;
11361 case SQL_CURSOR_COMMIT_BEHAVIOR:
11362 case SQL_CURSOR_ROLLBACK_BEHAVIOR:
11363 *((SQLSMALLINT *) val) = SQL_CB_PRESERVE;
11364 *valLen = sizeof (SQLSMALLINT);
11365 break;
11366#ifdef SQL_CURSOR_SENSITIVITY
11367 case SQL_CURSOR_SENSITIVITY:
11368 *((SQLUINTEGER *) val) = SQL_UNSPECIFIED;
11369 *valLen = sizeof (SQLUINTEGER);
11370 break;
11371#endif
11372 case SQL_DEFAULT_TXN_ISOLATION:
11373 *((SQLUINTEGER *) val) = SQL_TXN_SERIALIZABLE;
11374 *valLen = sizeof (SQLUINTEGER);
11375 break;
11376#ifdef SQL_DESCRIBE_PARAMETER
11377 case SQL_DESCRIBE_PARAMETER:
11378 strmak(val, "Y", valMax, valLen);
11379 break;
11380#endif
11381 case SQL_TXN_ISOLATION_OPTION:
11382 *((SQLUINTEGER *) val) = SQL_TXN_SERIALIZABLE;
11383 *valLen = sizeof (SQLUINTEGER);
11384 break;
11385 case SQL_IDENTIFIER_CASE:
11386 *((SQLSMALLINT *) val) = SQL_IC_SENSITIVE;
11387 *valLen = sizeof (SQLSMALLINT);
11388 break;
11389 case SQL_IDENTIFIER_QUOTE_CHAR:
11390 strmak(val, "\"", valMax, valLen);
11391 break;
11392 case SQL_MAX_TABLE_NAME_LEN:
11393 case SQL_MAX_COLUMN_NAME_LEN:
11394 *((SQLSMALLINT *) val) = 255;
11395 *valLen = sizeof (SQLSMALLINT);
11396 break;
11397 case SQL_MAX_CURSOR_NAME_LEN:
11398 *((SQLSMALLINT *) val) = 255;
11399 *valLen = sizeof (SQLSMALLINT);
11400 break;
11401 case SQL_MAX_PROCEDURE_NAME_LEN:
11402 *((SQLSMALLINT *) val) = 0;
11403 break;
11404 case SQL_MAX_QUALIFIER_NAME_LEN:
11405 case SQL_MAX_OWNER_NAME_LEN:
11406 *((SQLSMALLINT *) val) = 255;
11407 break;
11408 case SQL_OWNER_TERM:
11409 strmak(val, "", valMax, valLen);
11410 break;
11411 case SQL_PROCEDURE_TERM:
11412 strmak(val, "PROCEDURE", valMax, valLen);
11413 break;
11414 case SQL_QUALIFIER_NAME_SEPARATOR:
11415 strmak(val, ".", valMax, valLen);
11416 break;
11417 case SQL_QUALIFIER_TERM:
11418#if defined(_WIN32) || defined(_WIN64)
11419 strmak(val, d->xcelqrx ? "catalog" : "", valMax, valLen);
11420#else
11421 strmak(val, "", valMax, valLen);
11422#endif
11423 break;
11424 case SQL_QUALIFIER_USAGE:
11425#if defined(_WIN32) || defined(_WIN64)
11426 *((SQLUINTEGER *) val) = d->xcelqrx ?
11427 (SQL_CU_DML_STATEMENTS | SQL_CU_INDEX_DEFINITION |
11428 SQL_CU_TABLE_DEFINITION) : 0;
11429#else
11430 *((SQLUINTEGER *) val) = 0;
11431#endif
11432 *valLen = sizeof (SQLUINTEGER);
11433 break;
11434 case SQL_SCROLL_CONCURRENCY:
11435 *((SQLUINTEGER *) val) = SQL_SCCO_LOCK;
11436 *valLen = sizeof (SQLUINTEGER);
11437 break;
11438 case SQL_SCROLL_OPTIONS:
11439 *((SQLUINTEGER *) val) = SQL_SO_STATIC | SQL_SO_FORWARD_ONLY;
11440 *valLen = sizeof (SQLUINTEGER);
11441 break;
11442 case SQL_TABLE_TERM:
11443 strmak(val, "TABLE", valMax, valLen);
11444 break;
11445 case SQL_TXN_CAPABLE:
11446 *((SQLSMALLINT *) val) = SQL_TC_ALL;
11447 *valLen = sizeof (SQLSMALLINT);
11448 break;
11449 case SQL_CONVERT_FUNCTIONS:
11450 *((SQLUINTEGER *) val) = 0;
11451 *valLen = sizeof (SQLUINTEGER);
11452 break;
11453 case SQL_SYSTEM_FUNCTIONS:
11454 case SQL_NUMERIC_FUNCTIONS:
11455 case SQL_STRING_FUNCTIONS:
11456 case SQL_TIMEDATE_FUNCTIONS:
11457 *((SQLUINTEGER *) val) = 0;
11458 *valLen = sizeof (SQLUINTEGER);
11459 break;
11460 case SQL_CONVERT_BIGINT:
11461 case SQL_CONVERT_BIT:
11462 case SQL_CONVERT_CHAR:
11463 case SQL_CONVERT_DATE:
11464 case SQL_CONVERT_DECIMAL:
11465 case SQL_CONVERT_DOUBLE:
11466 case SQL_CONVERT_FLOAT:
11467 case SQL_CONVERT_INTEGER:
11468 case SQL_CONVERT_LONGVARCHAR:
11469 case SQL_CONVERT_NUMERIC:
11470 case SQL_CONVERT_REAL:
11471 case SQL_CONVERT_SMALLINT:
11472 case SQL_CONVERT_TIME:
11473 case SQL_CONVERT_TIMESTAMP:
11474 case SQL_CONVERT_TINYINT:
11475 case SQL_CONVERT_VARCHAR:
11476 *((SQLUINTEGER *) val) =
11477 SQL_CVT_CHAR | SQL_CVT_NUMERIC | SQL_CVT_DECIMAL |
11478 SQL_CVT_INTEGER | SQL_CVT_SMALLINT | SQL_CVT_FLOAT | SQL_CVT_REAL |
11479 SQL_CVT_DOUBLE | SQL_CVT_VARCHAR | SQL_CVT_LONGVARCHAR |
11480 SQL_CVT_BIT | SQL_CVT_TINYINT | SQL_CVT_BIGINT |
11481 SQL_CVT_DATE | SQL_CVT_TIME | SQL_CVT_TIMESTAMP;
11482 *valLen = sizeof (SQLUINTEGER);
11483 break;
11484 case SQL_CONVERT_BINARY:
11485 case SQL_CONVERT_VARBINARY:
11486 case SQL_CONVERT_LONGVARBINARY:
11487 *((SQLUINTEGER *) val) = 0;
11488 *valLen = sizeof (SQLUINTEGER);
11489 break;
11490 case SQL_POSITIONED_STATEMENTS:
11491 *((SQLUINTEGER *) val) = 0;
11492 *valLen = sizeof (SQLUINTEGER);
11493 break;
11494 case SQL_LOCK_TYPES:
11495 *((SQLUINTEGER *) val) = SQL_LCK_NO_CHANGE;
11496 *valLen = sizeof (SQLUINTEGER);
11497 break;
11498 case SQL_BOOKMARK_PERSISTENCE:
11499 *((SQLUINTEGER *) val) = SQL_BP_SCROLL;
11500 *valLen = sizeof (SQLUINTEGER);
11501 break;
11502 case SQL_UNION:
11503 *((SQLUINTEGER *) val) = SQL_U_UNION | SQL_U_UNION_ALL;
11504 *valLen = sizeof (SQLUINTEGER);
11505 break;
11506 case SQL_OWNER_USAGE:
11507 case SQL_SUBQUERIES:
11508 case SQL_TIMEDATE_ADD_INTERVALS:
11509 case SQL_TIMEDATE_DIFF_INTERVALS:
11510 *((SQLUINTEGER *) val) = 0;
11511 *valLen = sizeof (SQLUINTEGER);
11512 break;
11513 case SQL_QUOTED_IDENTIFIER_CASE:
11514 *((SQLUSMALLINT *) val) = SQL_IC_SENSITIVE;
11515 *valLen = sizeof (SQLUSMALLINT);
11516 break;
11517 case SQL_POS_OPERATIONS:
11518 *((SQLUINTEGER *) val) = SQL_POS_POSITION | SQL_POS_UPDATE |
11519 SQL_POS_DELETE | SQL_POS_ADD | SQL_POS_REFRESH;
11520 *valLen = sizeof (SQLUINTEGER);
11521 break;
11522 case SQL_ALTER_TABLE:
11523 *((SQLUINTEGER *) val) = 0;
11524 *valLen = sizeof (SQLUINTEGER);
11525 break;
11526 case SQL_CORRELATION_NAME:
11527 *((SQLSMALLINT *) val) = SQL_CN_ANY;
11528 *valLen = sizeof (SQLSMALLINT);
11529 break;
11530 case SQL_NON_NULLABLE_COLUMNS:
11531 *((SQLSMALLINT *) val) = SQL_NNC_NON_NULL;
11532 *valLen = sizeof (SQLSMALLINT);
11533 break;
11534 case SQL_NULL_COLLATION:
11535 *((SQLSMALLINT *) val) = SQL_NC_START;
11536 *valLen = sizeof (SQLSMALLINT);
11537 break;
11538 case SQL_MAX_COLUMNS_IN_GROUP_BY:
11539 case SQL_MAX_COLUMNS_IN_ORDER_BY:
11540 case SQL_MAX_COLUMNS_IN_SELECT:
11541 case SQL_MAX_COLUMNS_IN_TABLE:
11542 case SQL_MAX_ROW_SIZE:
11543 case SQL_MAX_TABLES_IN_SELECT:
11544 *((SQLSMALLINT *) val) = 0;
11545 *valLen = sizeof (SQLSMALLINT);
11546 break;
11547 case SQL_MAX_BINARY_LITERAL_LEN:
11548 case SQL_MAX_CHAR_LITERAL_LEN:
11549 *((SQLUINTEGER *) val) = 0;
11550 *valLen = sizeof (SQLUINTEGER);
11551 break;
11552 case SQL_MAX_COLUMNS_IN_INDEX:
11553 *((SQLSMALLINT *) val) = 0;
11554 *valLen = sizeof (SQLSMALLINT);
11555 break;
11556 case SQL_MAX_INDEX_SIZE:
11557 *((SQLUINTEGER *) val) = 0;
11558 *valLen = sizeof (SQLUINTEGER);
11559 break;
11560#ifdef SQL_MAX_IDENTIFIER_LENGTH
11561 case SQL_MAX_IDENTIFIER_LENGTH:
11562 *((SQLUINTEGER *) val) = 255;
11563 *valLen = sizeof (SQLUINTEGER);
11564 break;
11565#endif
11566 case SQL_MAX_STATEMENT_LEN:
11567 *((SQLUINTEGER *) val) = 16384;
11568 *valLen = sizeof (SQLUINTEGER);
11569 break;
11570 case SQL_QUALIFIER_LOCATION:
11571 *((SQLSMALLINT *) val) = SQL_QL_START;
11572 *valLen = sizeof (SQLSMALLINT);
11573 break;
11574 case SQL_GETDATA_EXTENSIONS:
11575 *((SQLUINTEGER *) val) =
11576 SQL_GD_ANY_COLUMN | SQL_GD_ANY_ORDER | SQL_GD_BOUND;
11577 *valLen = sizeof (SQLUINTEGER);
11578 break;
11579 case SQL_STATIC_SENSITIVITY:
11580 *((SQLUINTEGER *) val) = 0;
11581 *valLen = sizeof (SQLUINTEGER);
11582 break;
11583 case SQL_FILE_USAGE:
11584#if defined(_WIN32) || defined(_WIN64)
11585 *((SQLSMALLINT *) val) =
11586 d->xcelqrx ? SQL_FILE_CATALOG : SQL_FILE_NOT_SUPPORTED;
11587#else
11588 *((SQLSMALLINT *) val) = SQL_FILE_NOT_SUPPORTED;
11589#endif
11590 *valLen = sizeof (SQLSMALLINT);
11591 break;
11592 case SQL_GROUP_BY:
11593 *((SQLSMALLINT *) val) = SQL_GB_GROUP_BY_EQUALS_SELECT;
11594 *valLen = sizeof (SQLSMALLINT);
11595 break;
11596 case SQL_KEYWORDS:
11597 strmak(val, "CREATE,SELECT,DROP,DELETE,UPDATE,INSERT,"
11598 "INTO,VALUES,TABLE,INDEX,FROM,SET,WHERE,AND,CURRENT,OF",
11599 valMax, valLen);
11600 break;
11601 case SQL_SPECIAL_CHARACTERS:
11602#ifdef SQL_COLLATION_SEQ
11603 case SQL_COLLATION_SEQ:
11604#endif
11605 strmak(val, "", valMax, valLen);
11606 break;
11607 case SQL_BATCH_SUPPORT:
11608 case SQL_BATCH_ROW_COUNT:
11609 case SQL_PARAM_ARRAY_ROW_COUNTS:
11610 *((SQLUINTEGER *) val) = 0;
11611 *valLen = sizeof (SQLUINTEGER);
11612 break;
11613 case SQL_FORWARD_ONLY_CURSOR_ATTRIBUTES1:
11614 *((SQLUINTEGER *) val) = SQL_CA1_NEXT | SQL_CA1_BOOKMARK;
11615 *valLen = sizeof (SQLUINTEGER);
11616 break;
11617 case SQL_STATIC_CURSOR_ATTRIBUTES1:
11618 *((SQLUINTEGER *) val) = SQL_CA1_NEXT | SQL_CA1_ABSOLUTE |
11619 SQL_CA1_RELATIVE | SQL_CA1_BOOKMARK | SQL_CA1_POS_POSITION |
11620 SQL_CA1_POS_DELETE | SQL_CA1_POS_UPDATE | SQL_CA1_POS_REFRESH |
11621 SQL_CA1_LOCK_NO_CHANGE | SQL_CA1_BULK_ADD |
11622 SQL_CA1_BULK_UPDATE_BY_BOOKMARK | SQL_CA1_BULK_DELETE_BY_BOOKMARK;
11623 *valLen = sizeof (SQLUINTEGER);
11624 break;
11625 case SQL_FORWARD_ONLY_CURSOR_ATTRIBUTES2:
11626 case SQL_STATIC_CURSOR_ATTRIBUTES2:
11627 *((SQLUINTEGER *) val) = SQL_CA2_READ_ONLY_CONCURRENCY |
11628 SQL_CA2_LOCK_CONCURRENCY;
11629 *valLen = sizeof (SQLUINTEGER);
11630 break;
11631 case SQL_KEYSET_CURSOR_ATTRIBUTES1:
11632 case SQL_KEYSET_CURSOR_ATTRIBUTES2:
11633 case SQL_DYNAMIC_CURSOR_ATTRIBUTES1:
11634 case SQL_DYNAMIC_CURSOR_ATTRIBUTES2:
11635 *((SQLUINTEGER *) val) = 0;
11636 *valLen = sizeof (SQLUINTEGER);
11637 break;
11638 case SQL_ODBC_INTERFACE_CONFORMANCE:
11639 *((SQLUINTEGER *) val) = SQL_OIC_CORE;
11640 *valLen = sizeof (SQLUINTEGER);
11641 break;
11642 default:
11643 setstatd(d, -1, "unsupported info option %d",
11644 (*d->ov3) ? "HYC00" : "S1C00", type);
11645 return SQL_ERROR;
11646 }
11647 return SQL_SUCCESS;
11648}
11649
11650#if (defined(HAVE_UNIXODBC) && (HAVE_UNIXODBC)) || !defined(WINTERFACE)
11661SQLRETURN SQL_API
11662SQLGetInfo(SQLHDBC dbc, SQLUSMALLINT type, SQLPOINTER val, SQLSMALLINT valMax,
11663 SQLSMALLINT *valLen)
11664{
11665 SQLRETURN ret;
11666
11667 HDBC_LOCK(dbc);
11668 ret = drvgetinfo(dbc, type, val, valMax, valLen);
11670 return ret;
11671}
11672#endif
11673
11674#ifdef WINTERFACE
11685SQLRETURN SQL_API
11686SQLGetInfoW(SQLHDBC dbc, SQLUSMALLINT type, SQLPOINTER val, SQLSMALLINT valMax,
11687 SQLSMALLINT *valLen)
11688{
11689 SQLRETURN ret;
11690 SQLSMALLINT len = 0;
11691
11692 HDBC_LOCK(dbc);
11693 ret = drvgetinfo(dbc, type, val, valMax, &len);
11695 if (ret == SQL_SUCCESS) {
11696 SQLWCHAR *v = NULL;
11697
11698 switch (type) {
11699 case SQL_USER_NAME:
11700 case SQL_DRIVER_ODBC_VER:
11701 case SQL_DATA_SOURCE_NAME:
11702 case SQL_DRIVER_NAME:
11703 case SQL_DRIVER_VER:
11704 case SQL_ODBC_VER:
11705 case SQL_SERVER_NAME:
11706 case SQL_DATABASE_NAME:
11707 case SQL_SEARCH_PATTERN_ESCAPE:
11708 case SQL_DBMS_NAME:
11709 case SQL_DBMS_VER:
11710 case SQL_NEED_LONG_DATA_LEN:
11711 case SQL_ROW_UPDATES:
11712 case SQL_ACCESSIBLE_PROCEDURES:
11713 case SQL_PROCEDURES:
11714 case SQL_EXPRESSIONS_IN_ORDERBY:
11715 case SQL_ODBC_SQL_OPT_IEF:
11716 case SQL_LIKE_ESCAPE_CLAUSE:
11717 case SQL_ORDER_BY_COLUMNS_IN_SELECT:
11718 case SQL_OUTER_JOINS:
11719 case SQL_COLUMN_ALIAS:
11720 case SQL_ACCESSIBLE_TABLES:
11721 case SQL_MULT_RESULT_SETS:
11722 case SQL_MULTIPLE_ACTIVE_TXN:
11723 case SQL_MAX_ROW_SIZE_INCLUDES_LONG:
11724 case SQL_DATA_SOURCE_READ_ONLY:
11725#ifdef SQL_DESCRIBE_PARAMETER
11726 case SQL_DESCRIBE_PARAMETER:
11727#endif
11728 case SQL_IDENTIFIER_QUOTE_CHAR:
11729 case SQL_OWNER_TERM:
11730 case SQL_PROCEDURE_TERM:
11731 case SQL_QUALIFIER_NAME_SEPARATOR:
11732 case SQL_QUALIFIER_TERM:
11733 case SQL_TABLE_TERM:
11734 case SQL_KEYWORDS:
11735 case SQL_SPECIAL_CHARACTERS:
11736#ifdef SQL_CATALOG_NAME
11737 case SQL_CATALOG_NAME:
11738#endif
11739#ifdef SQL_COLLATION_SEQ
11740 case SQL_COLLATION_SEQ:
11741#endif
11742 if (val) {
11743 if (len > 0) {
11744 v = uc_from_utf((SQLCHAR *) val, len);
11745 if (v) {
11746 int vmax = valMax / sizeof (SQLWCHAR);
11747
11748 uc_strncpy(val, v, vmax);
11749 if (len < vmax) {
11750 len = min(vmax, uc_strlen(v));
11751 v[len] = 0;
11752 } else {
11753 len = vmax;
11754 }
11755 uc_free(v);
11756 len *= sizeof (SQLWCHAR);
11757 } else {
11758 len = 0;
11759 }
11760 }
11761 if (len <= 0) {
11762 len = 0;
11763 if (valMax >= sizeof (SQLWCHAR)) {
11764 *((SQLWCHAR *)val) = 0;
11765 }
11766 }
11767 } else {
11768 len *= sizeof (SQLWCHAR);
11769 }
11770 break;
11771 }
11772 if (valLen) {
11773 *valLen = len;
11774 }
11775 }
11776 return ret;
11777}
11778#endif
11779
11788SQLRETURN SQL_API
11789SQLGetFunctions(SQLHDBC dbc, SQLUSMALLINT func,
11790 SQLUSMALLINT *flags)
11791{
11792 int i;
11793 SQLUSMALLINT exists[100];
11794
11795 if (dbc == SQL_NULL_HDBC) {
11796 return SQL_INVALID_HANDLE;
11797 }
11798 for (i = 0; i < array_size(exists); i++) {
11799 exists[i] = SQL_FALSE;
11800 }
11801 exists[SQL_API_SQLALLOCCONNECT] = SQL_TRUE;
11802 exists[SQL_API_SQLFETCH] = SQL_TRUE;
11803 exists[SQL_API_SQLALLOCENV] = SQL_TRUE;
11804 exists[SQL_API_SQLFREECONNECT] = SQL_TRUE;
11805 exists[SQL_API_SQLALLOCSTMT] = SQL_TRUE;
11806 exists[SQL_API_SQLFREEENV] = SQL_TRUE;
11807 exists[SQL_API_SQLBINDCOL] = SQL_TRUE;
11808 exists[SQL_API_SQLFREESTMT] = SQL_TRUE;
11809 exists[SQL_API_SQLCANCEL] = SQL_TRUE;
11810 exists[SQL_API_SQLGETCURSORNAME] = SQL_TRUE;
11811 exists[SQL_API_SQLCOLATTRIBUTES] = SQL_TRUE;
11812 exists[SQL_API_SQLNUMRESULTCOLS] = SQL_TRUE;
11813 exists[SQL_API_SQLCONNECT] = SQL_TRUE;
11814 exists[SQL_API_SQLPREPARE] = SQL_TRUE;
11815 exists[SQL_API_SQLDESCRIBECOL] = SQL_TRUE;
11816 exists[SQL_API_SQLROWCOUNT] = SQL_TRUE;
11817 exists[SQL_API_SQLDISCONNECT] = SQL_TRUE;
11818 exists[SQL_API_SQLSETCURSORNAME] = SQL_FALSE;
11819 exists[SQL_API_SQLERROR] = SQL_TRUE;
11820 exists[SQL_API_SQLSETPARAM] = SQL_TRUE;
11821 exists[SQL_API_SQLEXECDIRECT] = SQL_TRUE;
11822 exists[SQL_API_SQLTRANSACT] = SQL_TRUE;
11823 exists[SQL_API_SQLBULKOPERATIONS] = SQL_TRUE;
11824 exists[SQL_API_SQLEXECUTE] = SQL_TRUE;
11825 exists[SQL_API_SQLBINDPARAMETER] = SQL_TRUE;
11826 exists[SQL_API_SQLGETTYPEINFO] = SQL_TRUE;
11827 exists[SQL_API_SQLCOLUMNS] = SQL_TRUE;
11828 exists[SQL_API_SQLPARAMDATA] = SQL_TRUE;
11829 exists[SQL_API_SQLDRIVERCONNECT] = SQL_TRUE;
11830 exists[SQL_API_SQLPUTDATA] = SQL_TRUE;
11831 exists[SQL_API_SQLGETCONNECTOPTION] = SQL_TRUE;
11832 exists[SQL_API_SQLSETCONNECTOPTION] = SQL_TRUE;
11833 exists[SQL_API_SQLGETDATA] = SQL_TRUE;
11834 exists[SQL_API_SQLSETSTMTOPTION] = SQL_TRUE;
11835 exists[SQL_API_SQLGETFUNCTIONS] = SQL_TRUE;
11836 exists[SQL_API_SQLSPECIALCOLUMNS] = SQL_TRUE;
11837 exists[SQL_API_SQLGETINFO] = SQL_TRUE;
11838 exists[SQL_API_SQLSTATISTICS] = SQL_TRUE;
11839 exists[SQL_API_SQLGETSTMTOPTION] = SQL_TRUE;
11840 exists[SQL_API_SQLTABLES] = SQL_TRUE;
11841 exists[SQL_API_SQLBROWSECONNECT] = SQL_FALSE;
11842 exists[SQL_API_SQLNUMPARAMS] = SQL_TRUE;
11843 exists[SQL_API_SQLCOLUMNPRIVILEGES] = SQL_FALSE;
11844 exists[SQL_API_SQLPARAMOPTIONS] = SQL_FALSE;
11845 exists[SQL_API_SQLDATASOURCES] = SQL_TRUE;
11846 exists[SQL_API_SQLPRIMARYKEYS] = SQL_TRUE;
11847 exists[SQL_API_SQLDESCRIBEPARAM] = SQL_TRUE;
11848 exists[SQL_API_SQLPROCEDURECOLUMNS] = SQL_TRUE;
11849 exists[SQL_API_SQLDRIVERS] = SQL_FALSE;
11850 exists[SQL_API_SQLPROCEDURES] = SQL_TRUE;
11851 exists[SQL_API_SQLEXTENDEDFETCH] = SQL_TRUE;
11852 exists[SQL_API_SQLSETPOS] = SQL_TRUE;
11853 exists[SQL_API_SQLFOREIGNKEYS] = SQL_TRUE;
11854 exists[SQL_API_SQLSETSCROLLOPTIONS] = SQL_TRUE;
11855 exists[SQL_API_SQLMORERESULTS] = SQL_TRUE;
11856 exists[SQL_API_SQLTABLEPRIVILEGES] = SQL_TRUE;
11857 exists[SQL_API_SQLNATIVESQL] = SQL_TRUE;
11858 if (func == SQL_API_ALL_FUNCTIONS) {
11859 memcpy(flags, exists, sizeof (exists));
11860 } else if (func == SQL_API_ODBC3_ALL_FUNCTIONS) {
11861 int i;
11862#define SET_EXISTS(x) \
11863 flags[(x) >> 4] |= (1 << ((x) & 0xF))
11864#define CLR_EXISTS(x) \
11865 flags[(x) >> 4] &= ~(1 << ((x) & 0xF))
11866
11867 memset(flags, 0,
11868 sizeof (SQLUSMALLINT) * SQL_API_ODBC3_ALL_FUNCTIONS_SIZE);
11869 for (i = 0; i < array_size(exists); i++) {
11870 if (exists[i]) {
11871 flags[i >> 4] |= (1 << (i & 0xF));
11872 }
11873 }
11874 SET_EXISTS(SQL_API_SQLALLOCHANDLE);
11875 SET_EXISTS(SQL_API_SQLFREEHANDLE);
11876 SET_EXISTS(SQL_API_SQLGETSTMTATTR);
11877 SET_EXISTS(SQL_API_SQLSETSTMTATTR);
11878 SET_EXISTS(SQL_API_SQLGETCONNECTATTR);
11879 SET_EXISTS(SQL_API_SQLSETCONNECTATTR);
11880 SET_EXISTS(SQL_API_SQLGETENVATTR);
11881 SET_EXISTS(SQL_API_SQLSETENVATTR);
11882 SET_EXISTS(SQL_API_SQLCLOSECURSOR);
11883 SET_EXISTS(SQL_API_SQLBINDPARAM);
11884#if !defined(HAVE_UNIXODBC) || !(HAVE_UNIXODBC)
11885 /*
11886 * Some unixODBC versions have problems with
11887 * SQLError() vs. SQLGetDiagRec() with loss
11888 * of error/warning messages.
11889 */
11890 SET_EXISTS(SQL_API_SQLGETDIAGREC);
11891#endif
11892 SET_EXISTS(SQL_API_SQLGETDIAGFIELD);
11893 SET_EXISTS(SQL_API_SQLFETCHSCROLL);
11894 SET_EXISTS(SQL_API_SQLENDTRAN);
11895 } else {
11896 if (func < array_size(exists)) {
11897 *flags = exists[func];
11898 } else {
11899 switch (func) {
11900 case SQL_API_SQLALLOCHANDLE:
11901 case SQL_API_SQLFREEHANDLE:
11902 case SQL_API_SQLGETSTMTATTR:
11903 case SQL_API_SQLSETSTMTATTR:
11904 case SQL_API_SQLGETCONNECTATTR:
11905 case SQL_API_SQLSETCONNECTATTR:
11906 case SQL_API_SQLGETENVATTR:
11907 case SQL_API_SQLSETENVATTR:
11908 case SQL_API_SQLCLOSECURSOR:
11909 case SQL_API_SQLBINDPARAM:
11910#if !defined(HAVE_UNIXODBC) || !(HAVE_UNIXODBC)
11911 /*
11912 * Some unixODBC versions have problems with
11913 * SQLError() vs. SQLGetDiagRec() with loss
11914 * of error/warning messages.
11915 */
11916 case SQL_API_SQLGETDIAGREC:
11917#endif
11918 case SQL_API_SQLGETDIAGFIELD:
11919 case SQL_API_SQLFETCHSCROLL:
11920 case SQL_API_SQLENDTRAN:
11921 *flags = SQL_TRUE;
11922 break;
11923 default:
11924 *flags = SQL_FALSE;
11925 }
11926 }
11927 }
11928 return SQL_SUCCESS;
11929}
11930
11937static SQLRETURN
11938drvallocenv(SQLHENV *env)
11939{
11940 ENV *e;
11941
11942 if (env == NULL) {
11943 return SQL_INVALID_HANDLE;
11944 }
11945 e = (ENV *) xmalloc(sizeof (ENV));
11946 if (e == NULL) {
11947 *env = SQL_NULL_HENV;
11948 return SQL_ERROR;
11949 }
11950 e->magic = ENV_MAGIC;
11951 e->ov3 = 0;
11952 e->pool = 0;
11953#if defined(_WIN32) || defined(_WIN64)
11954 InitializeCriticalSection(&e->cs);
11955#else
11956#if defined(ENABLE_NVFS) && (ENABLE_NVFS)
11957 nvfs_init();
11958#endif
11959#endif
11960 e->dbcs = NULL;
11961 *env = (SQLHENV) e;
11962 return SQL_SUCCESS;
11963}
11964
11971SQLRETURN SQL_API
11972SQLAllocEnv(SQLHENV *env)
11973{
11974 return drvallocenv(env);
11975}
11976
11983static SQLRETURN
11984drvfreeenv(SQLHENV env)
11985{
11986 ENV *e;
11987
11988 if (env == SQL_NULL_HENV) {
11989 return SQL_INVALID_HANDLE;
11990 }
11991 e = (ENV *) env;
11992 if (e->magic != ENV_MAGIC) {
11993 return SQL_SUCCESS;
11994 }
11995#if defined(_WIN32) || defined(_WIN64)
11996 EnterCriticalSection(&e->cs);
11997#endif
11998 if (e->dbcs) {
11999#if defined(_WIN32) || defined(_WIN64)
12000 LeaveCriticalSection(&e->cs);
12001#endif
12002 return SQL_ERROR;
12003 }
12004 e->magic = DEAD_MAGIC;
12005#if defined(_WIN32) || defined(_WIN64)
12006 LeaveCriticalSection(&e->cs);
12007 DeleteCriticalSection(&e->cs);
12008#endif
12009 xfree(e);
12010 return SQL_SUCCESS;
12011}
12012
12019SQLRETURN SQL_API
12020SQLFreeEnv(SQLHENV env)
12021{
12022 return drvfreeenv(env);
12023}
12024
12032static SQLRETURN
12033drvallocconnect(SQLHENV env, SQLHDBC *dbc)
12034{
12035 DBC *d;
12036 ENV *e;
12037 const char *verstr;
12038 int maj = 0, min = 0, lev = 0;
12039
12040 if (dbc == NULL) {
12041 return SQL_ERROR;
12042 }
12043 d = (DBC *) xmalloc(sizeof (DBC));
12044 if (d == NULL) {
12045 *dbc = SQL_NULL_HDBC;
12046 return SQL_ERROR;
12047 }
12048 memset(d, 0, sizeof (DBC));
12049 d->curtype = SQL_CURSOR_STATIC;
12050 d->ov3 = &d->ov3val;
12051 verstr = sqlite3_libversion();
12052 sscanf(verstr, "%d.%d.%d", &maj, &min, &lev);
12053 d->version = verinfo(maj & 0xFF, min & 0xFF, lev & 0xFF);
12054 e = (ENV *) env;
12055#if defined(_WIN32) || defined(_WIN64)
12056 if (e->magic == ENV_MAGIC) {
12057 EnterCriticalSection(&e->cs);
12058 }
12059#endif
12060 if (e->magic == ENV_MAGIC) {
12061 DBC *n, *p;
12062
12063 d->env = e;
12064 d->ov3 = &e->ov3;
12065 p = NULL;
12066 n = e->dbcs;
12067 while (n) {
12068 p = n;
12069 n = n->next;
12070 }
12071 if (p) {
12072 p->next = d;
12073 } else {
12074 e->dbcs = d;
12075 }
12076 }
12077#if defined(_WIN32) || defined(_WIN64)
12078 InitializeCriticalSection(&d->cs);
12079 d->owner = 0;
12080 if (e->magic == ENV_MAGIC) {
12081 LeaveCriticalSection(&e->cs);
12082 }
12083 d->oemcp = 1;
12084#endif
12085 d->autocommit = 1;
12086 d->magic = DBC_MAGIC;
12087 *dbc = (SQLHDBC) d;
12088 drvgetgpps(d);
12089 return SQL_SUCCESS;
12090}
12091
12099SQLRETURN SQL_API
12100SQLAllocConnect(SQLHENV env, SQLHDBC *dbc)
12101{
12102 return drvallocconnect(env, dbc);
12103}
12104
12111static SQLRETURN
12113{
12114 DBC *d;
12115 ENV *e;
12116 SQLRETURN ret = SQL_ERROR;
12117
12118 if (dbc == SQL_NULL_HDBC) {
12119 return SQL_INVALID_HANDLE;
12120 }
12121 d = (DBC *) dbc;
12122 if (d->magic != DBC_MAGIC) {
12123 return SQL_INVALID_HANDLE;
12124 }
12125 e = d->env;
12126 if (e && e->magic == ENV_MAGIC) {
12127#if defined(_WIN32) || defined(_WIN64)
12128 EnterCriticalSection(&e->cs);
12129#endif
12130 } else {
12131 e = NULL;
12132 }
12133 HDBC_LOCK(dbc);
12134 if (d->sqlite) {
12135 setstatd(d, -1, "not disconnected", (*d->ov3) ? "HY000" : "S1000");
12137 goto done;
12138 }
12139 while (d->stmt) {
12140 freestmt((HSTMT) d->stmt);
12141 }
12142 if (e && e->magic == ENV_MAGIC) {
12143 DBC *n, *p;
12144
12145 p = NULL;
12146 n = e->dbcs;
12147 while (n) {
12148 if (n == d) {
12149 break;
12150 }
12151 p = n;
12152 n = n->next;
12153 }
12154 if (n) {
12155 if (p) {
12156 p->next = d->next;
12157 } else {
12158 e->dbcs = d->next;
12159 }
12160 }
12161 }
12162 drvrelgpps(d);
12163 d->magic = DEAD_MAGIC;
12164 if (d->trace) {
12165 fclose(d->trace);
12166 }
12167#if defined(_WIN32) || defined(_WIN64)
12168 d->owner = 0;
12169 LeaveCriticalSection(&d->cs);
12170 DeleteCriticalSection(&d->cs);
12171#endif
12172 xfree(d);
12173 ret = SQL_SUCCESS;
12174done:
12175#if defined(_WIN32) || defined(_WIN64)
12176 if (e) {
12177 LeaveCriticalSection(&e->cs);
12178 }
12179#endif
12180 return ret;
12181}
12182
12189SQLRETURN SQL_API
12191{
12192 return drvfreeconnect(dbc);
12193}
12194
12205static SQLRETURN
12206drvgetconnectattr(SQLHDBC dbc, SQLINTEGER attr, SQLPOINTER val,
12207 SQLINTEGER bufmax, SQLINTEGER *buflen)
12208{
12209 DBC *d;
12210 SQLINTEGER dummy;
12211
12212 if (dbc == SQL_NULL_HDBC) {
12213 return SQL_INVALID_HANDLE;
12214 }
12215 d = (DBC *) dbc;
12216 if (!val) {
12217 val = (SQLPOINTER) &dummy;
12218 }
12219 if (!buflen) {
12220 buflen = &dummy;
12221 }
12222 switch (attr) {
12223 case SQL_ATTR_CONNECTION_DEAD:
12224 *((SQLINTEGER *) val) = d->sqlite ? SQL_CD_FALSE : SQL_CD_TRUE;
12225 *buflen = sizeof (SQLINTEGER);
12226 break;
12227 case SQL_ATTR_ACCESS_MODE:
12228 *((SQLINTEGER *) val) = SQL_MODE_READ_WRITE;
12229 *buflen = sizeof (SQLINTEGER);
12230 break;
12231 case SQL_ATTR_AUTOCOMMIT:
12232 *((SQLINTEGER *) val) =
12233 d->autocommit ? SQL_AUTOCOMMIT_ON : SQL_AUTOCOMMIT_OFF;
12234 *buflen = sizeof (SQLINTEGER);
12235 break;
12236 case SQL_ATTR_LOGIN_TIMEOUT:
12237 *((SQLINTEGER *) val) = 100;
12238 *buflen = sizeof (SQLINTEGER);
12239 break;
12240 case SQL_ATTR_ODBC_CURSORS:
12241 *((SQLINTEGER *) val) = SQL_CUR_USE_DRIVER;
12242 *buflen = sizeof (SQLINTEGER);
12243 break;
12244 case SQL_ATTR_PACKET_SIZE:
12245 *((SQLINTEGER *) val) = 16384;
12246 *buflen = sizeof (SQLINTEGER);
12247 break;
12248 case SQL_ATTR_TXN_ISOLATION:
12249 *((SQLINTEGER *) val) = SQL_TXN_SERIALIZABLE;
12250 *buflen = sizeof (SQLINTEGER);
12251 break;
12252 case SQL_ATTR_TRACEFILE:
12253 case SQL_ATTR_TRANSLATE_LIB:
12254 *((SQLCHAR *) val) = 0;
12255 *buflen = 0;
12256 break;
12257 case SQL_ATTR_CURRENT_CATALOG:
12258#if defined(_WIN32) || defined(_WIN64)
12259 if (d->xcelqrx) {
12260 if ((bufmax > 4) && (val != (SQLPOINTER) &dummy)) {
12261 strcpy((char *) val, "main");
12262 *buflen = 4;
12263 break;
12264 }
12265 }
12266#endif
12267 *((SQLCHAR *) val) = 0;
12268 *buflen = 0;
12269 break;
12270 case SQL_ATTR_TRACE:
12271 case SQL_ATTR_QUIET_MODE:
12272 case SQL_ATTR_TRANSLATE_OPTION:
12273 case SQL_ATTR_KEYSET_SIZE:
12274 case SQL_ATTR_QUERY_TIMEOUT:
12275 *((SQLINTEGER *) val) = 0;
12276 *buflen = sizeof (SQLINTEGER);
12277 break;
12278 case SQL_ATTR_PARAM_BIND_TYPE:
12279 *((SQLULEN *) val) = SQL_PARAM_BIND_BY_COLUMN;
12280 *buflen = sizeof (SQLUINTEGER);
12281 break;
12282 case SQL_ATTR_ROW_BIND_TYPE:
12283 *((SQLULEN *) val) = SQL_BIND_BY_COLUMN;
12284 *buflen = sizeof (SQLULEN);
12285 break;
12286 case SQL_ATTR_USE_BOOKMARKS:
12287 *((SQLINTEGER *) val) = SQL_UB_OFF;
12288 *buflen = sizeof (SQLINTEGER);
12289 break;
12290 case SQL_ATTR_ASYNC_ENABLE:
12291 *((SQLINTEGER *) val) = SQL_ASYNC_ENABLE_OFF;
12292 *buflen = sizeof (SQLINTEGER);
12293 break;
12294 case SQL_ATTR_NOSCAN:
12295 *((SQLINTEGER *) val) = SQL_NOSCAN_ON;
12296 *buflen = sizeof (SQLINTEGER);
12297 break;
12298 case SQL_ATTR_CONCURRENCY:
12299 *((SQLINTEGER *) val) = SQL_CONCUR_LOCK;
12300 *buflen = sizeof (SQLINTEGER);
12301 break;
12302#ifdef SQL_ATTR_CURSOR_SENSITIVITY
12303 case SQL_ATTR_CURSOR_SENSITIVITY:
12304 *((SQLINTEGER *) val) = SQL_UNSPECIFIED;
12305 *buflen = sizeof (SQLINTEGER);
12306 break;
12307#endif
12308 case SQL_ATTR_SIMULATE_CURSOR:
12309 *((SQLINTEGER *) val) = SQL_SC_NON_UNIQUE;
12310 *buflen = sizeof (SQLINTEGER);
12311 break;
12312 case SQL_ATTR_MAX_ROWS:
12313 *((SQLINTEGER *) val) = 0;
12314 *buflen = sizeof (SQLINTEGER);
12315 case SQL_ATTR_MAX_LENGTH:
12316 *((SQLINTEGER *) val) = 1000000000;
12317 *buflen = sizeof (SQLINTEGER);
12318 break;
12319 case SQL_ATTR_CURSOR_TYPE:
12320 *((SQLINTEGER *) val) = d->curtype;
12321 *buflen = sizeof (SQLINTEGER);
12322 break;
12323 case SQL_ATTR_RETRIEVE_DATA:
12324 *((SQLINTEGER *) val) = SQL_RD_ON;
12325 *buflen = sizeof (SQLINTEGER);
12326 break;
12327#ifdef SQL_ATTR_METADATA_ID
12328 case SQL_ATTR_METADATA_ID:
12329 *((SQLULEN *) val) = SQL_FALSE;
12330 return SQL_SUCCESS;
12331#endif
12332 default:
12333 *((SQLINTEGER *) val) = 0;
12334 *buflen = sizeof (SQLINTEGER);
12335 setstatd(d, -1, "unsupported connect attribute %d",
12336 (*d->ov3) ? "HYC00" : "S1C00", (int) attr);
12337 return SQL_ERROR;
12338 }
12339 return SQL_SUCCESS;
12340}
12341
12342#ifndef WINTERFACE
12353SQLRETURN SQL_API
12354SQLGetConnectAttr(SQLHDBC dbc, SQLINTEGER attr, SQLPOINTER val,
12355 SQLINTEGER bufmax, SQLINTEGER *buflen)
12356{
12357 SQLRETURN ret;
12358
12359 HDBC_LOCK(dbc);
12360 ret = drvgetconnectattr(dbc, attr, val, bufmax, buflen);
12362 return ret;
12363}
12364#endif
12365
12366#ifdef WINTERFACE
12377SQLRETURN SQL_API
12378SQLGetConnectAttrW(SQLHDBC dbc, SQLINTEGER attr, SQLPOINTER val,
12379 SQLINTEGER bufmax, SQLINTEGER *buflen)
12380{
12381 SQLRETURN ret;
12382 SQLINTEGER len = 0;
12383
12384 HDBC_LOCK(dbc);
12385 ret = drvgetconnectattr(dbc, attr, val, bufmax, &len);
12386 if (ret == SQL_SUCCESS) {
12387 SQLWCHAR *v = NULL;
12388
12389 switch (attr) {
12390 case SQL_ATTR_TRACEFILE:
12391 case SQL_ATTR_CURRENT_CATALOG:
12392 case SQL_ATTR_TRANSLATE_LIB:
12393 if (val) {
12394 if (len > 0) {
12395 v = uc_from_utf((SQLCHAR *) val, len);
12396 if (v) {
12397 int vmax = bufmax / sizeof (SQLWCHAR);
12398
12399 uc_strncpy(val, v, vmax);
12400 if (len < vmax) {
12401 len = min(vmax, uc_strlen(v));
12402 v[len] = 0;
12403 } else {
12404 len = vmax;
12405 }
12406 uc_free(v);
12407 len *= sizeof (SQLWCHAR);
12408 } else {
12409 len = 0;
12410 }
12411 }
12412 if (len <= 0) {
12413 len = 0;
12414 if (bufmax >= sizeof (SQLWCHAR)) {
12415 *((SQLWCHAR *)val) = 0;
12416 }
12417 }
12418 } else {
12419 len *= sizeof (SQLWCHAR);
12420 }
12421 break;
12422 }
12423 if (buflen) {
12424 *buflen = len;
12425 }
12426 }
12428 return ret;
12429}
12430#endif
12431
12441static SQLRETURN
12442drvsetconnectattr(SQLHDBC dbc, SQLINTEGER attr, SQLPOINTER val,
12443 SQLINTEGER len)
12444{
12445 DBC *d;
12446
12447 if (dbc == SQL_NULL_HDBC) {
12448 return SQL_INVALID_HANDLE;
12449 }
12450 d = (DBC *) dbc;
12451 switch (attr) {
12452 case SQL_AUTOCOMMIT:
12453 d->autocommit = val == (SQLPOINTER) SQL_AUTOCOMMIT_ON;
12454 if (d->autocommit && d->intrans) {
12455 return endtran(d, SQL_COMMIT, 1);
12456 } else if (!d->autocommit) {
12458 }
12459 break;
12460#ifdef SQL_ATTR_METADATA_ID
12461 case SQL_ATTR_METADATA_ID:
12462 if (val == (SQLPOINTER) SQL_FALSE) {
12463 break;
12464 }
12465 /* fall through */
12466#endif
12467 default:
12468 setstatd(d, -1, "option value changed", "01S02");
12469 return SQL_SUCCESS_WITH_INFO;
12470 }
12471 return SQL_SUCCESS;
12472}
12473
12474#ifndef WINTERFACE
12484SQLRETURN SQL_API
12485SQLSetConnectAttr(SQLHDBC dbc, SQLINTEGER attr, SQLPOINTER val,
12486 SQLINTEGER len)
12487{
12488 SQLRETURN ret;
12489
12490 HDBC_LOCK(dbc);
12491 ret = drvsetconnectattr(dbc, attr, val, len);
12493 return ret;
12494}
12495#endif
12496
12497#ifdef WINTERFACE
12507SQLRETURN SQL_API
12508SQLSetConnectAttrW(SQLHDBC dbc, SQLINTEGER attr, SQLPOINTER val,
12509 SQLINTEGER len)
12510{
12511 SQLRETURN ret;
12512
12513 HDBC_LOCK(dbc);
12514 ret = drvsetconnectattr(dbc, attr, val, len);
12516 return ret;
12517}
12518#endif
12519
12528static SQLRETURN
12529drvgetconnectoption(SQLHDBC dbc, SQLUSMALLINT opt, SQLPOINTER param)
12530{
12531 DBC *d;
12532 SQLINTEGER dummy;
12533
12534 if (dbc == SQL_NULL_HDBC) {
12535 return SQL_INVALID_HANDLE;
12536 }
12537 d = (DBC *) dbc;
12538 if (!param) {
12539 param = (SQLPOINTER) &dummy;
12540 }
12541 switch (opt) {
12542 case SQL_ACCESS_MODE:
12543 *((SQLINTEGER *) param) = SQL_MODE_READ_WRITE;
12544 break;
12545 case SQL_AUTOCOMMIT:
12546 *((SQLINTEGER *) param) =
12547 d->autocommit ? SQL_AUTOCOMMIT_ON : SQL_AUTOCOMMIT_OFF;
12548 break;
12549 case SQL_LOGIN_TIMEOUT:
12550 *((SQLINTEGER *) param) = 100;
12551 break;
12552 case SQL_ODBC_CURSORS:
12553 *((SQLINTEGER *) param) = SQL_CUR_USE_DRIVER;
12554 break;
12555 case SQL_PACKET_SIZE:
12556 *((SQLINTEGER *) param) = 16384;
12557 break;
12558 case SQL_TXN_ISOLATION:
12559 *((SQLINTEGER *) param) = SQL_TXN_SERIALIZABLE;
12560 break;
12561 case SQL_OPT_TRACE:
12562 case SQL_OPT_TRACEFILE:
12563 case SQL_QUIET_MODE:
12564 case SQL_TRANSLATE_DLL:
12565 case SQL_TRANSLATE_OPTION:
12566 case SQL_KEYSET_SIZE:
12567 case SQL_QUERY_TIMEOUT:
12568 case SQL_BIND_TYPE:
12569 case SQL_CURRENT_QUALIFIER:
12570 *((SQLINTEGER *) param) = 0;
12571 break;
12572 case SQL_USE_BOOKMARKS:
12573 *((SQLINTEGER *) param) = SQL_UB_OFF;
12574 break;
12575 case SQL_ASYNC_ENABLE:
12576 *((SQLINTEGER *) param) = SQL_ASYNC_ENABLE_OFF;
12577 break;
12578 case SQL_NOSCAN:
12579 *((SQLINTEGER *) param) = SQL_NOSCAN_ON;
12580 break;
12581 case SQL_CONCURRENCY:
12582 *((SQLINTEGER *) param) = SQL_CONCUR_LOCK;
12583 break;
12584 case SQL_SIMULATE_CURSOR:
12585 *((SQLINTEGER *) param) = SQL_SC_NON_UNIQUE;
12586 break;
12587 case SQL_MAX_ROWS:
12588 *((SQLINTEGER *) param) = 0;
12589 break;
12590 case SQL_ROWSET_SIZE:
12591 case SQL_MAX_LENGTH:
12592 *((SQLINTEGER *) param) = 1000000000;
12593 break;
12594 case SQL_CURSOR_TYPE:
12595 *((SQLINTEGER *) param) = d->curtype;
12596 break;
12597 case SQL_RETRIEVE_DATA:
12598 *((SQLINTEGER *) param) = SQL_RD_ON;
12599 break;
12600 default:
12601 *((SQLINTEGER *) param) = 0;
12602 setstatd(d, -1, "unsupported connect option %d",
12603 (*d->ov3) ? "HYC00" : "S1C00", opt);
12604 return SQL_ERROR;
12605 }
12606 return SQL_SUCCESS;
12607}
12608
12609#ifndef WINTERFACE
12618SQLRETURN SQL_API
12619SQLGetConnectOption(SQLHDBC dbc, SQLUSMALLINT opt, SQLPOINTER param)
12620{
12621 SQLRETURN ret;
12622
12623 HDBC_LOCK(dbc);
12624 ret = drvgetconnectoption(dbc, opt, param);
12626 return ret;
12627}
12628#endif
12629
12630#ifdef WINTERFACE
12639SQLRETURN SQL_API
12640SQLGetConnectOptionW(SQLHDBC dbc, SQLUSMALLINT opt, SQLPOINTER param)
12641{
12642 SQLRETURN ret;
12643
12644 HDBC_LOCK(dbc);
12645 ret = drvgetconnectoption(dbc, opt, param);
12646 if (SQL_SUCCEEDED(ret)) {
12647 switch (opt) {
12648 case SQL_OPT_TRACEFILE:
12649 case SQL_CURRENT_QUALIFIER:
12650 case SQL_TRANSLATE_DLL:
12651 if (param) {
12652 *(SQLWCHAR *) param = 0;
12653 }
12654 break;
12655 }
12656 }
12658 return ret;
12659}
12660#endif
12661
12670static SQLRETURN
12671drvsetconnectoption(SQLHDBC dbc, SQLUSMALLINT opt, SQLUINTEGER param)
12672{
12673 DBC *d;
12674
12675 if (dbc == SQL_NULL_HDBC) {
12676 return SQL_INVALID_HANDLE;
12677 }
12678 d = (DBC *) dbc;
12679 switch (opt) {
12680 case SQL_AUTOCOMMIT:
12681 d->autocommit = param == SQL_AUTOCOMMIT_ON;
12682 if (d->autocommit && d->intrans) {
12683 return endtran(d, SQL_COMMIT, 1);
12684 } else if (!d->autocommit) {
12686 }
12687 break;
12688 default:
12689 setstatd(d, -1, "option value changed", "01S02");
12690 return SQL_SUCCESS_WITH_INFO;
12691 }
12692 return SQL_SUCCESS;
12693}
12694
12695#ifndef WINTERFACE
12704SQLRETURN SQL_API
12705SQLSetConnectOption(SQLHDBC dbc, SQLUSMALLINT opt, SQLULEN param)
12706{
12707 SQLRETURN ret;
12708
12709 HDBC_LOCK(dbc);
12710 ret = drvsetconnectoption(dbc, opt, param);
12712 return ret;
12713}
12714#endif
12715
12716#ifdef WINTERFACE
12725SQLRETURN SQL_API
12726SQLSetConnectOptionW(SQLHDBC dbc, SQLUSMALLINT opt, SQLULEN param)
12727{
12728 SQLRETURN ret;
12729
12730 HDBC_LOCK(dbc);
12731 ret = drvsetconnectoption(dbc, opt, param);
12733 return ret;
12734}
12735#endif
12736
12737#if defined(WITHOUT_DRIVERMGR) || (!defined(_WIN32) && !defined(_WIN64))
12738
12749static int
12750getdsnattr(char *dsn, char *attr, char *out, int outLen)
12751{
12752 char *str = dsn, *start;
12753 int len = strlen(attr);
12754
12755 while (*str) {
12756 while (*str && *str == ';') {
12757 ++str;
12758 }
12759 start = str;
12760 if ((str = strchr(str, '=')) == NULL) {
12761 return 0;
12762 }
12763 if (str - start == len && strncasecmp(start, attr, len) == 0) {
12764 start = ++str;
12765 while (*str && *str != ';') {
12766 ++str;
12767 }
12768 len = min(outLen - 1, str - start);
12769 strncpy(out, start, len);
12770 out[len] = '\0';
12771 return 1;
12772 }
12773 while (*str && *str != ';') {
12774 ++str;
12775 }
12776 }
12777 return 0;
12778}
12779#endif
12780
12792static SQLRETURN
12793drvconnect(SQLHDBC dbc, SQLCHAR *dsn, SQLSMALLINT dsnLen, char *pwd,
12794 int pwdLen, int isu)
12795{
12796 DBC *d;
12797 int len;
12798 SQLRETURN ret;
12799 char buf[SQL_MAX_MESSAGE_LENGTH * 6], dbname[SQL_MAX_MESSAGE_LENGTH];
12800 char busy[SQL_MAX_MESSAGE_LENGTH / 4], tracef[SQL_MAX_MESSAGE_LENGTH];
12801 char loadext[SQL_MAX_MESSAGE_LENGTH], attas[SQL_MAX_MESSAGE_LENGTH];
12802 char sflag[32], spflag[32], ntflag[32], nwflag[32], biflag[32];
12803 char snflag[32], lnflag[32], ncflag[32], fkflag[32], jmode[32];
12804 char jdflag[32], ilflag[32];
12805#if defined(_WIN32) || defined(_WIN64)
12806 char oemcp[32];
12807#endif
12808
12809 if (dbc == SQL_NULL_HDBC) {
12810 return SQL_INVALID_HANDLE;
12811 }
12812 d = (DBC *) dbc;
12813 if (d->magic != DBC_MAGIC) {
12814 return SQL_INVALID_HANDLE;
12815 }
12816 if (d->sqlite != NULL) {
12817 setstatd(d, -1, "connection already established", "08002");
12818 return SQL_ERROR;
12819 }
12820 buf[0] = '\0';
12821 if (dsnLen == SQL_NTS) {
12822 len = sizeof (buf) - 1;
12823 } else {
12824 len = min(sizeof (buf) - 1, dsnLen);
12825 }
12826 if (dsn != NULL) {
12827 strncpy(buf, (char *) dsn, len);
12828 }
12829 buf[len] = '\0';
12830 if (buf[0] == '\0') {
12831 setstatd(d, -1, "invalid DSN", (*d->ov3) ? "HY090" : "S1090");
12832 return SQL_ERROR;
12833 }
12834#if defined(_WIN32) || defined(_WIN64)
12835 /*
12836 * When DSN is in UTF it must be converted to ANSI
12837 * here for ANSI SQLGetPrivateProfileString()
12838 */
12839 if (isu) {
12840 char *cdsn = utf_to_wmb(buf, len);
12841
12842 if (!cdsn) {
12843 setstatd(d, -1, "out of memory", (*d->ov3) ? "HY000" : "S1000");
12844 return SQL_ERROR;
12845 }
12846 strcpy(buf, cdsn);
12847 uc_free(cdsn);
12848 }
12849#endif
12850 busy[0] = '\0';
12851 dbname[0] = '\0';
12852#ifdef WITHOUT_DRIVERMGR
12853 getdsnattr(buf, "database", dbname, sizeof (dbname));
12854 if (dbname[0] == '\0') {
12855 strncpy(dbname, buf, sizeof (dbname));
12856 dbname[sizeof (dbname) - 1] = '\0';
12857 }
12858 getdsnattr(buf, "timeout", busy, sizeof (busy));
12859 sflag[0] = '\0';
12860 getdsnattr(buf, "stepapi", sflag, sizeof (sflag));
12861 spflag[0] = '\0';
12862 getdsnattr(buf, "syncpragma", spflag, sizeof (spflag));
12863 ntflag[0] = '\0';
12864 getdsnattr(buf, "notxn", ntflag, sizeof (ntflag));
12865 nwflag[0] = '\0';
12866 getdsnattr(buf, "nowchar", nwflag, sizeof (nwflag));
12867 snflag[0] = '\0';
12868 getdsnattr(buf, "shortnames", snflag, sizeof (snflag));
12869 lnflag[0] = '\0';
12870 getdsnattr(buf, "longnames", lnflag, sizeof (lnflag));
12871 ncflag[0] = '\0';
12872 getdsnattr(buf, "nocreat", ncflag, sizeof (ncflag));
12873 fkflag[0] = '\0';
12874 getdsnattr(buf, "fksupport", fkflag, sizeof (fkflag));
12875 loadext[0] = '\0';
12876 getdsnattr(buf, "loadext", loadext, sizeof (loadext));
12877 jmode[0] = '\0';
12878 getdsnattr(buf, "journalmode", jmode, sizeof (jmode));
12879 jdflag[0] = '\0';
12880 getdsnattr(buf, "jdconv", jdflag, sizeof (jdflag));
12881#if defined(_WIN32) || defined(_WIN64)
12882 oemcp[0] = '\0';
12883 getdsnattr(buf, "oemcp", oemcp, sizeof (oemcp));
12884#endif
12885 biflag[0] = '\0';
12886 getdsnattr(buf, "bigint", biflag, sizeof (biflag));
12887 attas[0] = '\0';
12888 getdsnattr(buf, "attachas", attas, sizeof (attas));
12889 ilflag[0] = '\0';
12890 getdsnattr(buf, "ilike", ilflag, sizeof (ilflag));
12891#else
12892 SQLGetPrivateProfileString(buf, "timeout", "100000",
12893 busy, sizeof (busy), ODBC_INI);
12894 SQLGetPrivateProfileString(buf, "database", "",
12895 dbname, sizeof (dbname), ODBC_INI);
12896#if defined(_WIN32) || defined(_WIN64)
12897 /* database name read from registry is not UTF8 !!! */
12898 isu = 0;
12899#endif
12900 SQLGetPrivateProfileString(buf, "stepapi", "",
12901 sflag, sizeof (sflag), ODBC_INI);
12902 SQLGetPrivateProfileString(buf, "syncpragma", "NORMAL",
12903 spflag, sizeof (spflag), ODBC_INI);
12904 SQLGetPrivateProfileString(buf, "notxn", "",
12905 ntflag, sizeof (ntflag), ODBC_INI);
12906 SQLGetPrivateProfileString(buf, "nowchar", "",
12907 nwflag, sizeof (nwflag), ODBC_INI);
12908 SQLGetPrivateProfileString(buf, "shortnames", "",
12909 snflag, sizeof (snflag), ODBC_INI);
12910 SQLGetPrivateProfileString(buf, "longnames", "",
12911 lnflag, sizeof (lnflag), ODBC_INI);
12912 SQLGetPrivateProfileString(buf, "nocreat", "",
12913 ncflag, sizeof (ncflag), ODBC_INI);
12914 SQLGetPrivateProfileString(buf, "fksupport", "",
12915 fkflag, sizeof (fkflag), ODBC_INI);
12916 SQLGetPrivateProfileString(buf, "loadext", "",
12917 loadext, sizeof (loadext), ODBC_INI);
12918 SQLGetPrivateProfileString(buf, "journalmode", "",
12919 jmode, sizeof (jmode), ODBC_INI);
12920 SQLGetPrivateProfileString(buf, "jdconv", "",
12921 jdflag, sizeof (jdflag), ODBC_INI);
12922#if defined(_WIN32) || defined(_WIN64)
12923 SQLGetPrivateProfileString(buf, "oemcp", "1",
12924 oemcp, sizeof (oemcp), ODBC_INI);
12925#endif
12926 SQLGetPrivateProfileString(buf, "bigint", "",
12927 biflag, sizeof (biflag), ODBC_INI);
12928 SQLGetPrivateProfileString(buf, "attachas", "",
12929 attas, sizeof (attas), ODBC_INI);
12930 SQLGetPrivateProfileString(buf, "ilike", "",
12931 ilflag, sizeof (ilflag), ODBC_INI);
12932#endif
12933 tracef[0] = '\0';
12934#ifdef WITHOUT_DRIVERMGR
12935 getdsnattr(buf, "tracefile", tracef, sizeof (tracef));
12936#else
12937 SQLGetPrivateProfileString(buf, "tracefile", "",
12938 tracef, sizeof (tracef), ODBC_INI);
12939#endif
12940 if (tracef[0] != '\0') {
12941 d->trace = fopen(tracef, "a");
12942 }
12943 d->nowchar = getbool(nwflag);
12944 d->shortnames = getbool(snflag);
12945 d->longnames = getbool(lnflag);
12946 d->nocreat = getbool(ncflag);
12947 d->fksupport = getbool(fkflag);
12948 d->jdconv = getbool(jdflag);
12949 d->ilike = getbool(ilflag);
12950#if defined(_WIN32) || defined(_WIN64)
12951 d->oemcp = getbool(oemcp);
12952#else
12953 d->oemcp = 0;
12954#endif
12955 d->dobigint = getbool(biflag);
12956 d->pwd = pwd;
12957 d->pwdLen = 0;
12958 if (d->pwd) {
12959 d->pwdLen = (pwdLen == SQL_NTS) ? strlen(d->pwd) : pwdLen;
12960 }
12961 ret = dbopen(d, dbname, isu, (char *) dsn, sflag, spflag, ntflag,
12962 jmode, busy);
12963 if (ret == SQL_SUCCESS) {
12964 dbloadext(d, loadext);
12965 dbattas(d, attas);
12966 }
12967 return ret;
12968}
12969
12970#ifndef WINTERFACE
12983SQLRETURN SQL_API
12984SQLConnect(SQLHDBC dbc, SQLCHAR *dsn, SQLSMALLINT dsnLen,
12985 SQLCHAR *uid, SQLSMALLINT uidLen,
12986 SQLCHAR *pwd, SQLSMALLINT pwdLen)
12987{
12988 SQLRETURN ret;
12989
12990 HDBC_LOCK(dbc);
12991 ret = drvconnect(dbc, dsn, dsnLen, (char *) pwd, pwdLen, 0);
12993 return ret;
12994}
12995#endif
12996
12997#ifdef WINTERFACE
13010SQLRETURN SQL_API
13011SQLConnectW(SQLHDBC dbc, SQLWCHAR *dsn, SQLSMALLINT dsnLen,
13012 SQLWCHAR *uid, SQLSMALLINT uidLen,
13013 SQLWCHAR *pwd, SQLSMALLINT pwdLen)
13014{
13015 char *dsna = NULL;
13016 char *pwda = NULL;
13017 SQLRETURN ret;
13018
13019 HDBC_LOCK(dbc);
13020 if (dsn) {
13021 dsna = uc_to_utf_c(dsn, dsnLen);
13022 if (!dsna) {
13023 DBC *d = (DBC *) dbc;
13024
13025 setstatd(d, -1, "out of memory", (*d->ov3) ? "HY000" : "S1000");
13026 ret = SQL_ERROR;
13027 goto done;
13028 }
13029 }
13030 if (pwd) {
13031 pwda = uc_to_utf_c(pwd, pwdLen);
13032 if (!pwda) {
13033 DBC *d = (DBC *) dbc;
13034
13035 setstatd(d, -1, "out of memory", (*d->ov3) ? "HY000" : "S1000");
13036 ret = SQL_ERROR;
13037 goto done;
13038 }
13039 }
13040 ret = drvconnect(dbc, (SQLCHAR *) dsna, SQL_NTS, pwda, SQL_NTS, 1);
13041done:
13043 uc_free(dsna);
13044 uc_free(pwda);
13045 return ret;
13046}
13047#endif
13048
13055static SQLRETURN
13057{
13058 DBC *d;
13059 int rc;
13060
13061 if (dbc == SQL_NULL_HDBC) {
13062 return SQL_INVALID_HANDLE;
13063 }
13064 d = (DBC *) dbc;
13065 if (d->magic != DBC_MAGIC) {
13066 return SQL_INVALID_HANDLE;
13067 }
13068 if (d->intrans) {
13069 setstatd(d, -1, "incomplete transaction", "25000");
13070 return SQL_ERROR;
13071 }
13072 if (d->cur_s3stmt) {
13074 }
13075 if (d->sqlite) {
13076 if (d->trace) {
13077 fprintf(d->trace, "-- sqlite3_close: '%s'\n",
13078 d->dbname);
13079 fflush(d->trace);
13080 }
13081 rc = sqlite3_close(d->sqlite);
13082 if (rc == SQLITE_BUSY) {
13083 setstatd(d, -1, "unfinished statements", "25000");
13084 return SQL_ERROR;
13085 }
13086 d->sqlite = NULL;
13087 }
13088 freep(&d->dbname);
13089 freep(&d->dsn);
13090 return SQL_SUCCESS;
13091}
13092
13099SQLRETURN SQL_API
13101{
13102 SQLRETURN ret;
13103
13104 HDBC_LOCK(dbc);
13105 ret = drvdisconnect(dbc);
13107 return ret;
13108}
13109
13110#if defined(WITHOUT_DRIVERMGR) || (!defined(_WIN32) && !defined(_WIN64))
13111
13125static SQLRETURN
13126drvdriverconnect(SQLHDBC dbc, SQLHWND hwnd,
13127 SQLCHAR *connIn, SQLSMALLINT connInLen,
13128 SQLCHAR *connOut, SQLSMALLINT connOutMax,
13129 SQLSMALLINT *connOutLen, SQLUSMALLINT drvcompl)
13130{
13131 DBC *d;
13132 int len;
13133 SQLRETURN ret;
13134 char buf[SQL_MAX_MESSAGE_LENGTH * 8], dbname[SQL_MAX_MESSAGE_LENGTH];
13135 char dsn[SQL_MAX_MESSAGE_LENGTH], busy[SQL_MAX_MESSAGE_LENGTH / 4];
13136 char tracef[SQL_MAX_MESSAGE_LENGTH], loadext[SQL_MAX_MESSAGE_LENGTH];
13137 char pwd[SQL_MAX_MESSAGE_LENGTH], attas[SQL_MAX_MESSAGE_LENGTH];
13138 char sflag[32], spflag[32], ntflag[32], snflag[32], lnflag[32];
13139 char ncflag[32], nwflag[32], fkflag[32], jmode[32], biflag[32];
13140 char jdflag[32], ilflag[32];
13141
13142 if (dbc == SQL_NULL_HDBC) {
13143 return SQL_INVALID_HANDLE;
13144 }
13145 if (drvcompl != SQL_DRIVER_COMPLETE &&
13146 drvcompl != SQL_DRIVER_COMPLETE_REQUIRED &&
13147 drvcompl != SQL_DRIVER_PROMPT &&
13148 drvcompl != SQL_DRIVER_NOPROMPT) {
13149 return SQL_NO_DATA;
13150 }
13151 d = (DBC *) dbc;
13152 if (d->sqlite) {
13153 setstatd(d, -1, "connection already established", "08002");
13154 return SQL_ERROR;
13155 }
13156 buf[0] = '\0';
13157 if (connInLen == SQL_NTS) {
13158 len = sizeof (buf) - 1;
13159 } else {
13160 len = min(connInLen, sizeof (buf) - 1);
13161 }
13162 if (connIn != NULL) {
13163 strncpy(buf, (char *) connIn, len);
13164 }
13165 buf[len] = '\0';
13166 if (!buf[0]) {
13167 setstatd(d, -1, "invalid connect attributes",
13168 (*d->ov3) ? "HY090" : "S1090");
13169 return SQL_ERROR;
13170 }
13171 dsn[0] = '\0';
13172 getdsnattr(buf, "DSN", dsn, sizeof (dsn));
13173
13174 /* special case: connIn is sole DSN value without keywords */
13175 if (!dsn[0] && !strchr(buf, ';') && !strchr(buf, '=')) {
13176 strncpy(dsn, buf, sizeof (dsn) - 1);
13177 dsn[sizeof (dsn) - 1] = '\0';
13178 }
13179
13180 busy[0] = '\0';
13181 getdsnattr(buf, "timeout", busy, sizeof (busy));
13182#ifndef WITHOUT_DRIVERMGR
13183 if (dsn[0] && !busy[0]) {
13184 SQLGetPrivateProfileString(dsn, "timeout", "100000",
13185 busy, sizeof (busy), ODBC_INI);
13186 }
13187#endif
13188 dbname[0] = '\0';
13189 getdsnattr(buf, "database", dbname, sizeof (dbname));
13190#ifndef WITHOUT_DRIVERMGR
13191 if (dsn[0] && !dbname[0]) {
13192 SQLGetPrivateProfileString(dsn, "database", "",
13193 dbname, sizeof (dbname), ODBC_INI);
13194 }
13195#endif
13196 sflag[0] = '\0';
13197 getdsnattr(buf, "stepapi", sflag, sizeof (sflag));
13198#ifndef WITHOUT_DRIVERMGR
13199 if (dsn[0] && !sflag[0]) {
13200 SQLGetPrivateProfileString(dsn, "stepapi", "",
13201 sflag, sizeof (sflag), ODBC_INI);
13202 }
13203#endif
13204 spflag[0] = '\0';
13205 getdsnattr(buf, "syncpragma", spflag, sizeof (spflag));
13206#ifndef WITHOUT_DRIVERMGR
13207 if (dsn[0] && !spflag[0]) {
13208 SQLGetPrivateProfileString(dsn, "syncpragma", "NORMAL",
13209 spflag, sizeof (spflag), ODBC_INI);
13210 }
13211#endif
13212 ntflag[0] = '\0';
13213 getdsnattr(buf, "notxn", ntflag, sizeof (ntflag));
13214#ifndef WITHOUT_DRIVERMGR
13215 if (dsn[0] && !ntflag[0]) {
13216 SQLGetPrivateProfileString(dsn, "notxn", "",
13217 ntflag, sizeof (ntflag), ODBC_INI);
13218 }
13219#endif
13220 snflag[0] = '\0';
13221 getdsnattr(buf, "shortnames", snflag, sizeof (snflag));
13222#ifndef WITHOUT_DRIVERMGR
13223 if (dsn[0] && !snflag[0]) {
13224 SQLGetPrivateProfileString(dsn, "shortnames", "",
13225 snflag, sizeof (snflag), ODBC_INI);
13226 }
13227#endif
13228 lnflag[0] = '\0';
13229 getdsnattr(buf, "longnames", lnflag, sizeof (lnflag));
13230#ifndef WITHOUT_DRIVERMGR
13231 if (dsn[0] && !lnflag[0]) {
13232 SQLGetPrivateProfileString(dsn, "longnames", "",
13233 lnflag, sizeof (lnflag), ODBC_INI);
13234 }
13235#endif
13236 ncflag[0] = '\0';
13237 getdsnattr(buf, "nocreat", ncflag, sizeof (ncflag));
13238#ifndef WITHOUT_DRIVERMGR
13239 if (dsn[0] && !ncflag[0]) {
13240 SQLGetPrivateProfileString(dsn, "nocreat", "",
13241 ncflag, sizeof (ncflag), ODBC_INI);
13242 }
13243#endif
13244 nwflag[0] = '\0';
13245 getdsnattr(buf, "nowchar", nwflag, sizeof (nwflag));
13246#ifndef WITHOUT_DRIVERMGR
13247 if (dsn[0] && !nwflag[0]) {
13248 SQLGetPrivateProfileString(dsn, "nowchar", "",
13249 nwflag, sizeof (nwflag), ODBC_INI);
13250 }
13251#endif
13252 fkflag[0] = '\0';
13253 getdsnattr(buf, "fksupport", fkflag, sizeof (fkflag));
13254#ifndef WITHOUT_DRIVERMGR
13255 if (dsn[0] && !fkflag[0]) {
13256 SQLGetPrivateProfileString(dsn, "fksupport", "",
13257 fkflag, sizeof (fkflag), ODBC_INI);
13258 }
13259#endif
13260 loadext[0] = '\0';
13261 getdsnattr(buf, "loadext", loadext, sizeof (loadext));
13262#ifndef WITHOUT_DRIVERMGR
13263 if (dsn[0] && !loadext[0]) {
13264 SQLGetPrivateProfileString(dsn, "loadext", "",
13265 loadext, sizeof (loadext), ODBC_INI);
13266 }
13267#endif
13268 jmode[0] = '\0';
13269 getdsnattr(buf, "journalmode", jmode, sizeof (jmode));
13270#ifndef WITHOUT_DRIVERMGR
13271 if (dsn[0] && !jmode[0]) {
13272 SQLGetPrivateProfileString(dsn, "journalmode", "",
13273 jmode, sizeof (jmode), ODBC_INI);
13274 }
13275#endif
13276 biflag[0] = '\0';
13277 getdsnattr(buf, "bigint", biflag, sizeof (biflag));
13278#ifndef WITHOUT_DRIVERMGR
13279 if (dsn[0] && !biflag[0]) {
13280 SQLGetPrivateProfileString(dsn, "bigint", "",
13281 biflag, sizeof (biflag), ODBC_INI);
13282 }
13283#endif
13284 jdflag[0] = '\0';
13285 getdsnattr(buf, "jdconv", jdflag, sizeof (jdflag));
13286#ifndef WITHOUT_DRIVERMGR
13287 if (dsn[0] && !jdflag[0]) {
13288 SQLGetPrivateProfileString(dsn, "jdconv", "",
13289 jdflag, sizeof (jdflag), ODBC_INI);
13290 }
13291#endif
13292 pwd[0] = '\0';
13293 getdsnattr(buf, "pwd", pwd, sizeof (pwd));
13294#ifndef WITHOUT_DRIVERMGR
13295 if (dsn[0] && !pwd[0]) {
13296 SQLGetPrivateProfileString(dsn, "pwd", "",
13297 pwd, sizeof (pwd), ODBC_INI);
13298 }
13299#endif
13300 attas[0] = '\0';
13301 getdsnattr(buf, "attachas", attas, sizeof (attas));
13302#ifndef WITHOUT_DRIVERMGR
13303 if (dsn[0] && !attas[0]) {
13304 SQLGetPrivateProfileString(dsn, "attachas", "",
13305 attas, sizeof (attas), ODBC_INI);
13306 }
13307#endif
13308 ilflag[0] = '\0';
13309 getdsnattr(buf, "ilike", ilflag, sizeof (ilflag));
13310#ifndef WITHOUT_DRIVERMGR
13311 if (dsn[0] && !ilflag[0]) {
13312 SQLGetPrivateProfileString(dsn, "ilike", "",
13313 ilflag, sizeof (ilflag), ODBC_INI);
13314 }
13315#endif
13316
13317 if (!dbname[0] && !dsn[0]) {
13318 strcpy(dsn, "SQLite");
13319 strncpy(dbname, buf, sizeof (dbname));
13320 dbname[sizeof (dbname) - 1] = '\0';
13321 }
13322 tracef[0] = '\0';
13323 getdsnattr(buf, "tracefile", tracef, sizeof (tracef));
13324#ifndef WITHOUT_DRIVERMGR
13325 if (dsn[0] && !tracef[0]) {
13326 SQLGetPrivateProfileString(dsn, "tracefile", "",
13327 tracef, sizeof (tracef), ODBC_INI);
13328 }
13329#endif
13330 if (connOut || connOutLen) {
13331 int count;
13332
13333 buf[0] = '\0';
13334 count = snprintf(buf, sizeof (buf),
13335 "DSN=%s;Database=%s;StepAPI=%s;Timeout=%s;"
13336 "SyncPragma=%s;NoTXN=%s;ShortNames=%s;LongNames=%s;"
13337 "NoCreat=%s;NoWCHAR=%s;FKSupport=%s;Tracefile=%s;"
13338 "JournalMode=%s;LoadExt=%s;BigInt=%s;JDConv=%s;"
13339 "PWD=%s;AttachAs=%s;ILike=%s",
13340 dsn, dbname, sflag, busy, spflag, ntflag,
13341 snflag, lnflag, ncflag, nwflag, fkflag, tracef,
13342 jmode, loadext, biflag, jdflag, pwd, attas, ilflag);
13343 if (count < 0) {
13344 buf[sizeof (buf) - 1] = '\0';
13345 }
13346 len = min(connOutMax - 1, strlen(buf));
13347 if (connOut) {
13348 strncpy((char *) connOut, buf, len);
13349 connOut[len] = '\0';
13350 }
13351 if (connOutLen) {
13352 *connOutLen = len;
13353 }
13354 }
13355 if (tracef[0] != '\0') {
13356 d->trace = fopen(tracef, "a");
13357 }
13358 d->shortnames = getbool(snflag);
13359 d->longnames = getbool(lnflag);
13360 d->nocreat = getbool(ncflag);
13361 d->nowchar = getbool(nwflag);
13362 d->fksupport = getbool(fkflag);
13363 d->dobigint = getbool(biflag);
13364 d->jdconv = getbool(jdflag);
13365 d->ilike = getbool(ilflag);
13366 d->oemcp = 0;
13367 d->pwdLen = strlen(pwd);
13368 d->pwd = (d->pwdLen > 0) ? pwd : NULL;
13369 ret = dbopen(d, dbname, 0, dsn, sflag, spflag, ntflag, jmode, busy);
13370 memset(pwd, 0, sizeof (pwd));
13371 if (ret == SQL_SUCCESS) {
13372 dbloadext(d, loadext);
13373 dbattas(d, attas);
13374 }
13375 return ret;
13376}
13377#endif
13378
13385static SQLRETURN
13387{
13388 STMT *s;
13389 DBC *d;
13390
13391 if (stmt == SQL_NULL_HSTMT) {
13392 return SQL_INVALID_HANDLE;
13393 }
13394 s = (STMT *) stmt;
13395 s3stmt_drop(s);
13396 freeresult(s, 1);
13397 freep(&s->query);
13398 d = (DBC *) s->dbc;
13399 if (d && d->magic == DBC_MAGIC) {
13400 STMT *p, *n;
13401
13402 p = NULL;
13403 n = d->stmt;
13404 while (n) {
13405 if (n == s) {
13406 break;
13407 }
13408 p = n;
13409 n = n->next;
13410 }
13411 if (n) {
13412 if (p) {
13413 p->next = s->next;
13414 } else {
13415 d->stmt = s->next;
13416 }
13417 }
13418 }
13419 freeparams(s);
13420 freep(&s->bindparms);
13421 if (s->row_status0 != &s->row_status1) {
13422 freep(&s->row_status0);
13423 s->rowset_size = 1;
13424 s->row_status0 = &s->row_status1;
13425 }
13426 xfree(s);
13427 return SQL_SUCCESS;
13428}
13429
13437static SQLRETURN
13438drvallocstmt(SQLHDBC dbc, SQLHSTMT *stmt)
13439{
13440 DBC *d;
13441 STMT *s, *sl, *pl;
13442
13443 if (dbc == SQL_NULL_HDBC) {
13444 return SQL_INVALID_HANDLE;
13445 }
13446 d = (DBC *) dbc;
13447 if (d->magic != DBC_MAGIC || stmt == NULL) {
13448 return SQL_INVALID_HANDLE;
13449 }
13450 s = (STMT *) xmalloc(sizeof (STMT));
13451 if (s == NULL) {
13452 *stmt = SQL_NULL_HSTMT;
13453 return SQL_ERROR;
13454 }
13455 *stmt = (SQLHSTMT) s;
13456 memset(s, 0, sizeof (STMT));
13457 s->dbc = dbc;
13458 s->ov3 = d->ov3;
13459 s->bkmrk = SQL_UB_OFF;
13460 s->bkmrkptr = 0;
13461 s->oemcp = &d->oemcp;
13462 s->jdconv = &d->jdconv;
13463 s->ilike = &d->ilike;
13464 s->nowchar[0] = d->nowchar;
13465 s->nowchar[1] = 0;
13466 s->dobigint = d->dobigint;
13467 s->curtype = d->curtype;
13468 s->row_status0 = &s->row_status1;
13469 s->rowset_size = 1;
13470 s->longnames = d->longnames;
13471 s->retr_data = SQL_RD_ON;
13472 s->max_rows = 0;
13473 s->bind_type = SQL_BIND_BY_COLUMN;
13474 s->bind_offs = NULL;
13475 s->paramset_size = 1;
13476 s->parm_bind_type = SQL_PARAM_BIND_BY_COLUMN;
13477 s->one_tbl = -1;
13478 s->has_pk = -1;
13479 s->has_rowid = -1;
13480#ifdef _WIN64
13481 sprintf((char *) s->cursorname, "CUR_%I64X", (SQLUBIGINT) *stmt);
13482#else
13483 sprintf((char *) s->cursorname, "CUR_%016lX", (long) *stmt);
13484#endif
13485 sl = d->stmt;
13486 pl = NULL;
13487 while (sl) {
13488 pl = sl;
13489 sl = sl->next;
13490 }
13491 if (pl) {
13492 pl->next = s;
13493 } else {
13494 d->stmt = s;
13495 }
13496 return SQL_SUCCESS;
13497}
13498
13506SQLRETURN SQL_API
13507SQLAllocStmt(SQLHDBC dbc, SQLHSTMT *stmt)
13508{
13509 SQLRETURN ret;
13510
13511 HDBC_LOCK(dbc);
13512 ret = drvallocstmt(dbc, stmt);
13514 return ret;
13515}
13516
13524static SQLRETURN
13525drvfreestmt(SQLHSTMT stmt, SQLUSMALLINT opt)
13526{
13527 STMT *s;
13528 SQLRETURN ret = SQL_SUCCESS;
13529 SQLHDBC dbc;
13530
13531 if (stmt == SQL_NULL_HSTMT) {
13532 return SQL_INVALID_HANDLE;
13533 }
13535 s = (STMT *) stmt;
13536 dbc = s->dbc;
13537 switch (opt) {
13538 case SQL_RESET_PARAMS:
13539 freeparams(s);
13540 break;
13541 case SQL_UNBIND:
13542 unbindcols(s);
13543 break;
13544 case SQL_CLOSE:
13545 s3stmt_end_if(s);
13546 freeresult(s, 0);
13547 break;
13548 case SQL_DROP:
13549 s3stmt_end_if(s);
13550 ret = freestmt(stmt);
13551 break;
13552 default:
13553 setstat(s, -1, "unsupported option", (*s->ov3) ? "HYC00" : "S1C00");
13554 ret = SQL_ERROR;
13555 break;
13556 }
13558 return ret;
13559}
13560
13568SQLRETURN SQL_API
13569SQLFreeStmt(SQLHSTMT stmt, SQLUSMALLINT opt)
13570{
13571 return drvfreestmt(stmt, opt);
13572}
13573
13580SQLRETURN SQL_API
13582{
13583 if (stmt != SQL_NULL_HSTMT) {
13584 DBC *d = (DBC *) ((STMT *) stmt)->dbc;
13585#if defined(_WIN32) || defined(_WIN64)
13586 /* interrupt when other thread owns critical section */
13587 if (d->magic == DBC_MAGIC && d->owner != GetCurrentThreadId() &&
13588 d->owner != 0) {
13589 d->busyint = 1;
13590 sqlite3_interrupt(d->sqlite);
13591 return SQL_SUCCESS;
13592 }
13593#else
13594 if (d->magic == DBC_MAGIC) {
13595 d->busyint = 1;
13596 sqlite3_interrupt(d->sqlite);
13597 }
13598#endif
13599 }
13600 return drvfreestmt(stmt, SQL_CLOSE);
13601}
13602
13612static SQLRETURN
13613drvgetcursorname(SQLHSTMT stmt, SQLCHAR *cursor, SQLSMALLINT buflen,
13614 SQLSMALLINT *lenp)
13615{
13616 STMT *s;
13617
13618 if (stmt == SQL_NULL_HSTMT) {
13619 return SQL_INVALID_HANDLE;
13620 }
13621 s = (STMT *) stmt;
13622 if (lenp && !cursor) {
13623 *lenp = strlen((char *) s->cursorname);
13624 return SQL_SUCCESS;
13625 }
13626 if (cursor) {
13627 if (buflen > 0) {
13628 strncpy((char *) cursor, (char *) s->cursorname, buflen - 1);
13629 cursor[buflen - 1] = '\0';
13630 }
13631 if (lenp) {
13632 *lenp = min(strlen((char *) s->cursorname), buflen - 1);
13633 }
13634 }
13635 return SQL_SUCCESS;
13636}
13637
13638#ifndef WINTERFACE
13648SQLRETURN SQL_API
13649SQLGetCursorName(SQLHSTMT stmt, SQLCHAR *cursor, SQLSMALLINT buflen,
13650 SQLSMALLINT *lenp)
13651{
13652 SQLRETURN ret;
13653#if defined(_WIN32) || defined(_WIN64)
13654 SQLSMALLINT len = 0;
13655#endif
13656
13658#if defined(_WIN32) || defined(_WIN64)
13659 if (!((STMT *) stmt)->oemcp[0]) {
13660 ret = drvgetcursorname(stmt, cursor, buflen, lenp);
13661 goto done;
13662 }
13663 ret = drvgetcursorname(stmt, cursor, buflen, &len);
13664 if (ret == SQL_SUCCESS) {
13665 char *c = NULL;
13666
13667 if (cursor) {
13668 c = utf_to_wmb((char *) cursor, len);
13669 if (!c) {
13670 ret = nomem((STMT *) stmt);
13671 goto done;
13672 }
13673 c[len] = 0;
13674 len = strlen(c);
13675 if (buflen > 0) {
13676 strncpy((char *) cursor, c, buflen - 1);
13677 cursor[buflen - 1] = 0;
13678 }
13679 uc_free(c);
13680 }
13681 if (lenp) {
13682 *lenp = min(len, buflen - 1);
13683 }
13684 }
13685done:
13686 ;
13687#else
13688 ret = drvgetcursorname(stmt, cursor, buflen, lenp);
13689#endif
13691 return ret;
13692}
13693#endif
13694
13695#ifdef WINTERFACE
13705SQLRETURN SQL_API
13706SQLGetCursorNameW(SQLHSTMT stmt, SQLWCHAR *cursor, SQLSMALLINT buflen,
13707 SQLSMALLINT *lenp)
13708{
13709 SQLRETURN ret;
13710 SQLSMALLINT len = 0;
13711
13713 ret = drvgetcursorname(stmt, (SQLCHAR *) cursor, buflen, &len);
13714 if (ret == SQL_SUCCESS) {
13715 SQLWCHAR *c = NULL;
13716
13717 if (cursor) {
13718 c = uc_from_utf((SQLCHAR *) cursor, len);
13719 if (!c) {
13720 ret = nomem((STMT *) stmt);
13721 goto done;
13722 }
13723 c[len] = 0;
13724 len = uc_strlen(c);
13725 if (buflen > 0) {
13726 uc_strncpy(cursor, c, buflen - 1);
13727 cursor[buflen - 1] = 0;
13728 }
13729 uc_free(c);
13730 }
13731 if (lenp) {
13732 *lenp = min(len, buflen - 1);
13733 }
13734 }
13735done:
13737 return ret;
13738}
13739#endif
13740
13749static SQLRETURN
13750drvsetcursorname(SQLHSTMT stmt, SQLCHAR *cursor, SQLSMALLINT len)
13751{
13752 STMT *s;
13753
13754 if (stmt == SQL_NULL_HSTMT) {
13755 return SQL_INVALID_HANDLE;
13756 }
13757 s = (STMT *) stmt;
13758 if (!cursor ||
13759 !((cursor[0] >= 'A' && cursor[0] <= 'Z') ||
13760 (cursor[0] >= 'a' && cursor[0] <= 'z'))) {
13761 setstat(s, -1, "invalid cursor name", (*s->ov3) ? "HYC00" : "S1C00");
13762 return SQL_ERROR;
13763 }
13764 if (len == SQL_NTS) {
13765 len = sizeof (s->cursorname) - 1;
13766 } else {
13767 len = min(sizeof (s->cursorname) - 1, len);
13768 }
13769 strncpy((char *) s->cursorname, (char *) cursor, len);
13770 s->cursorname[len] = '\0';
13771 return SQL_SUCCESS;
13772}
13773
13774#ifndef WINTERFACE
13783SQLRETURN SQL_API
13784SQLSetCursorName(SQLHSTMT stmt, SQLCHAR *cursor, SQLSMALLINT len)
13785{
13786#if defined(_WIN32) || defined(_WIN64)
13787 char *c = NULL;
13788#endif
13789 SQLRETURN ret;
13790
13792#if defined(_WIN32) || defined(_WIN64)
13793 if (!((STMT *) stmt)->oemcp[0]) {
13794 ret = drvsetcursorname(stmt, cursor, len);
13795 goto done2;
13796 }
13797 if (cursor) {
13798 c = wmb_to_utf_c((char *) cursor, len);
13799 if (!c) {
13800 ret = nomem((STMT *) stmt);
13801 goto done;
13802 }
13803 }
13804 ret = drvsetcursorname(stmt, (SQLCHAR *) c, SQL_NTS);
13805#else
13806 ret = drvsetcursorname(stmt, cursor, len);
13807#endif
13808#if defined(_WIN32) || defined(_WIN64)
13809done:
13810 uc_free(c);
13811done2:
13812 ;
13813#endif
13815 return ret;
13816}
13817#endif
13818
13819#ifdef WINTERFACE
13828SQLRETURN SQL_API
13829SQLSetCursorNameW(SQLHSTMT stmt, SQLWCHAR *cursor, SQLSMALLINT len)
13830{
13831 char *c = NULL;
13832 SQLRETURN ret;
13833
13835 if (cursor) {
13836 c = uc_to_utf_c(cursor, len);
13837 if (!c) {
13838 ret = nomem((STMT *) stmt);
13839 goto done;
13840 }
13841 }
13842 ret = drvsetcursorname(stmt, (SQLCHAR *) c, SQL_NTS);
13843done:
13844 uc_free(c);
13846 return ret;
13847}
13848#endif
13849
13856SQLRETURN SQL_API
13858{
13859 return drvfreestmt(stmt, SQL_CLOSE);
13860}
13861
13870SQLRETURN SQL_API
13871SQLAllocHandle(SQLSMALLINT type, SQLHANDLE input, SQLHANDLE *output)
13872{
13873 SQLRETURN ret;
13874
13875 switch (type) {
13876 case SQL_HANDLE_ENV:
13877 ret = drvallocenv((SQLHENV *) output);
13878 if (ret == SQL_SUCCESS) {
13879 ENV *e = (ENV *) *output;
13880
13881 if (e && e->magic == ENV_MAGIC) {
13882 e->ov3 = 1;
13883 }
13884 }
13885 return ret;
13886 case SQL_HANDLE_DBC:
13887 return drvallocconnect((SQLHENV) input, (SQLHDBC *) output);
13888 case SQL_HANDLE_STMT:
13889 HDBC_LOCK((SQLHDBC) input);
13890 ret = drvallocstmt((SQLHDBC) input, (SQLHSTMT *) output);
13891 HDBC_UNLOCK((SQLHDBC) input);
13892 return ret;
13893 }
13894 return SQL_ERROR;
13895}
13896
13904SQLRETURN SQL_API
13905SQLFreeHandle(SQLSMALLINT type, SQLHANDLE h)
13906{
13907 switch (type) {
13908 case SQL_HANDLE_ENV:
13909 return drvfreeenv((SQLHENV) h);
13910 case SQL_HANDLE_DBC:
13911 return drvfreeconnect((SQLHDBC) h);
13912 case SQL_HANDLE_STMT:
13913 return drvfreestmt((SQLHSTMT) h, SQL_DROP);
13914 }
13915 return SQL_ERROR;
13916}
13917
13923static void
13925{
13926 if (s->dyncols) {
13927 int i;
13928
13929 for (i = 0; i < s->dcols; i++) {
13930 freep(&s->dyncols[i].typename);
13931 }
13932 if (s->cols == s->dyncols) {
13933 s->cols = NULL;
13934 s->ncols = 0;
13935 }
13936 freep(&s->dyncols);
13937 }
13938 s->dcols = 0;
13939}
13940
13952static void
13953freeresult(STMT *s, int clrcols)
13954{
13955 freep(&s->bincache);
13956 s->bincell = NULL;
13957 s->binlen = 0;
13958 if (s->rows) {
13959 if (s->rowfree) {
13960 s->rowfree(s->rows);
13961 s->rowfree = NULL;
13962 }
13963 s->rows = NULL;
13964 }
13965 s->nrows = -1;
13966 if (clrcols > 0) {
13967 freep(&s->bindcols);
13968 s->nbindcols = 0;
13969 }
13970 if (clrcols) {
13971 freedyncols(s);
13972 s->cols = NULL;
13973 s->ncols = 0;
13974 s->nowchar[1] = 0;
13975 s->one_tbl = -1;
13976 s->has_pk = -1;
13977 s->has_rowid = -1;
13978 }
13979}
13980
13986static void
13988{
13989 int i;
13990
13991 for (i = 0; s->bindcols && i < s->nbindcols; i++) {
13992 s->bindcols[i].type = SQL_UNKNOWN_TYPE;
13993 s->bindcols[i].max = 0;
13994 s->bindcols[i].lenp = NULL;
13995 s->bindcols[i].valp = NULL;
13996 s->bindcols[i].index = i;
13997 s->bindcols[i].offs = 0;
13998 }
13999}
14000
14008static SQLRETURN
14009mkbindcols(STMT *s, int ncols)
14010{
14011 if (s->bindcols) {
14012 if (s->nbindcols < ncols) {
14013 int i;
14014 BINDCOL *bindcols =
14015 xrealloc(s->bindcols, ncols * sizeof (BINDCOL));
14016
14017 if (!bindcols) {
14018 return nomem(s);
14019 }
14020 for (i = s->nbindcols; i < ncols; i++) {
14021 bindcols[i].type = SQL_UNKNOWN_TYPE;
14022 bindcols[i].max = 0;
14023 bindcols[i].lenp = NULL;
14024 bindcols[i].valp = NULL;
14025 bindcols[i].index = i;
14026 bindcols[i].offs = 0;
14027 }
14028 s->bindcols = bindcols;
14029 s->nbindcols = ncols;
14030 }
14031 } else if (ncols > 0) {
14032 s->bindcols = (BINDCOL *) xmalloc(ncols * sizeof (BINDCOL));
14033 if (!s->bindcols) {
14034 return nomem(s);
14035 }
14036 s->nbindcols = ncols;
14037 unbindcols(s);
14038 }
14039 return SQL_SUCCESS;
14040}
14041
14055static SQLRETURN
14056getrowdata(STMT *s, SQLUSMALLINT col, SQLSMALLINT otype,
14057 SQLPOINTER val, SQLINTEGER len, SQLLEN *lenp, int partial)
14058{
14059 char **data, valdummy[16];
14060 SQLLEN dummy;
14061 SQLINTEGER *ilenp = NULL;
14062 int valnull = 0;
14063 int type = otype;
14064 SQLRETURN sret = SQL_NO_DATA;
14065
14066 if (!lenp) {
14067 lenp = &dummy;
14068 }
14069 /* workaround for JDK 1.7.0 on x86_64 */
14070 if (((SQLINTEGER *) lenp) + 1 == (SQLINTEGER *) val) {
14071 ilenp = (SQLINTEGER *) lenp;
14072 lenp = &dummy;
14073 }
14074 if (col >= s->ncols) {
14075 setstat(s, -1, "invalid column", (*s->ov3) ? "07009" : "S1002");
14076 return SQL_ERROR;
14077 }
14078 if (s->retr_data != SQL_RD_ON) {
14079 return SQL_SUCCESS;
14080 }
14081 if (!s->rows) {
14082 *lenp = SQL_NULL_DATA;
14083 goto done;
14084 }
14085 if (s->rowp < 0 || s->rowp >= s->nrows) {
14086 *lenp = SQL_NULL_DATA;
14087 goto done;
14088 }
14089 type = mapdeftype(type, s->cols[col].type, s->cols[col].nosign ? 1 : 0,
14090 s->nowchar[0]);
14091#if (defined(_WIN32) || defined(_WIN64)) && defined(WINTERFACE)
14092 /* MS Access hack part 3 (map SQL_C_DEFAULT to SQL_C_CHAR) */
14093 if (type == SQL_C_WCHAR && otype == SQL_C_DEFAULT) {
14094 type = SQL_C_CHAR;
14095 }
14096#endif
14097 data = s->rows + s->ncols + (s->rowp * s->ncols) + col;
14098 if (!val) {
14099 valnull = 1;
14100 val = (SQLPOINTER) valdummy;
14101 }
14102 if (*data == NULL) {
14103 *lenp = SQL_NULL_DATA;
14104 switch (type) {
14105 case SQL_C_UTINYINT:
14106 case SQL_C_TINYINT:
14107 case SQL_C_STINYINT:
14108#ifdef SQL_BIT
14109 case SQL_C_BIT:
14110#endif
14111 *((SQLCHAR *) val) = 0;
14112 break;
14113 case SQL_C_USHORT:
14114 case SQL_C_SHORT:
14115 case SQL_C_SSHORT:
14116 *((SQLSMALLINT *) val) = 0;
14117 break;
14118 case SQL_C_ULONG:
14119 case SQL_C_LONG:
14120 case SQL_C_SLONG:
14121 *((SQLINTEGER *) val) = 0;
14122 break;
14123#ifdef SQL_BIGINT
14124 case SQL_C_SBIGINT:
14125 case SQL_C_UBIGINT:
14126 *((SQLBIGINT *) val) = 0;
14127 break;
14128#endif
14129 case SQL_C_FLOAT:
14130 *((float *) val) = 0;
14131 break;
14132 case SQL_C_DOUBLE:
14133 *((double *) val) = 0;
14134 break;
14135 case SQL_C_BINARY:
14136 case SQL_C_CHAR:
14137 if (len > 0) {
14138 *((SQLCHAR *) val) = '\0';
14139 }
14140 break;
14141#ifdef WCHARSUPPORT
14142 case SQL_C_WCHAR:
14143 if (len > 0) {
14144 *((SQLWCHAR *) val) = '\0';
14145 }
14146 break;
14147#endif
14148#ifdef SQL_C_TYPE_DATE
14149 case SQL_C_TYPE_DATE:
14150#endif
14151 case SQL_C_DATE:
14152 memset((DATE_STRUCT *) val, 0, sizeof (DATE_STRUCT));
14153 break;
14154#ifdef SQL_C_TYPE_TIME
14155 case SQL_C_TYPE_TIME:
14156#endif
14157 case SQL_C_TIME:
14158 memset((TIME_STRUCT *) val, 0, sizeof (TIME_STRUCT));
14159 break;
14160#ifdef SQL_C_TYPE_TIMESTAMP
14161 case SQL_C_TYPE_TIMESTAMP:
14162#endif
14163 case SQL_C_TIMESTAMP:
14164 memset((TIMESTAMP_STRUCT *) val, 0, sizeof (TIMESTAMP_STRUCT));
14165 break;
14166 default:
14167 return SQL_ERROR;
14168 }
14169 } else {
14170 char *endp = NULL;
14171#if defined(_WIN32) || defined(_WIN64)
14172#ifdef SQL_BIGINT
14173 char endc;
14174#endif
14175#endif
14176
14177 switch (type) {
14178 case SQL_C_UTINYINT:
14179 case SQL_C_TINYINT:
14180 case SQL_C_STINYINT:
14181 *((SQLCHAR *) val) = strtol(*data, &endp, 0);
14182 if (endp && endp == *data) {
14183 *lenp = SQL_NULL_DATA;
14184 } else {
14185 *lenp = sizeof (SQLCHAR);
14186 }
14187 break;
14188#ifdef SQL_BIT
14189 case SQL_C_BIT:
14190 *((SQLCHAR *) val) = getbool(*data);
14191 *lenp = sizeof (SQLCHAR);
14192 break;
14193#endif
14194 case SQL_C_USHORT:
14195 case SQL_C_SHORT:
14196 case SQL_C_SSHORT:
14197 *((SQLSMALLINT *) val) = strtol(*data, &endp, 0);
14198 if (endp && endp == *data) {
14199 *lenp = SQL_NULL_DATA;
14200 } else {
14201 *lenp = sizeof (SQLSMALLINT);
14202 }
14203 break;
14204 case SQL_C_ULONG:
14205 case SQL_C_LONG:
14206 case SQL_C_SLONG:
14207 *((SQLINTEGER *) val) = strtol(*data, &endp, 0);
14208 if (endp && endp == *data) {
14209 *lenp = SQL_NULL_DATA;
14210 } else {
14211 *lenp = sizeof (SQLINTEGER);
14212 }
14213 break;
14214#ifdef SQL_BIGINT
14215 case SQL_C_UBIGINT:
14216#if defined(_WIN32) || defined(_WIN64)
14217 if (sscanf(*data, "%I64u%c", (SQLUBIGINT *) val, &endc) != 1) {
14218 *lenp = SQL_NULL_DATA;
14219 } else {
14220 *lenp = sizeof (SQLUBIGINT);
14221 }
14222#else
14223#ifdef __osf__
14224 *((SQLUBIGINT *) val) = strtoul(*data, &endp, 0);
14225#else
14226 *((SQLUBIGINT *) val) = strtoull(*data, &endp, 0);
14227#endif
14228 if (endp && endp == *data) {
14229 *lenp = SQL_NULL_DATA;
14230 } else {
14231 *lenp = sizeof (SQLUBIGINT);
14232 }
14233#endif
14234 break;
14235 case SQL_C_SBIGINT:
14236#if defined(_WIN32) || defined(_WIN64)
14237 if (sscanf(*data, "%I64d%c", (SQLBIGINT *) val, &endc) != 1) {
14238 *lenp = SQL_NULL_DATA;
14239 } else {
14240 *lenp = sizeof (SQLBIGINT);
14241 }
14242#else
14243#ifdef __osf__
14244 *((SQLBIGINT *) val) = strtol(*data, &endp, 0);
14245#else
14246 *((SQLBIGINT *) val) = strtoll(*data, &endp, 0);
14247#endif
14248 if (endp && endp == *data) {
14249 *lenp = SQL_NULL_DATA;
14250 } else {
14251 *lenp = sizeof (SQLBIGINT);
14252 }
14253#endif
14254 break;
14255#endif
14256 case SQL_C_FLOAT:
14257 *((float *) val) = ln_strtod(*data, &endp);
14258 if (endp && endp == *data) {
14259 *lenp = SQL_NULL_DATA;
14260 } else {
14261 *lenp = sizeof (float);
14262 }
14263 break;
14264 case SQL_C_DOUBLE:
14265 *((double *) val) = ln_strtod(*data, &endp);
14266 if (endp && endp == *data) {
14267 *lenp = SQL_NULL_DATA;
14268 } else {
14269 *lenp = sizeof (double);
14270 }
14271 break;
14272 case SQL_C_BINARY: {
14273 int dlen, offs = 0;
14274 char *bin;
14275
14276 if (valnull) {
14277 freep(&s->bincache);
14278 s->binlen = 0;
14279 goto doCHAR;
14280 }
14281 if (*data == s->bincell) {
14282 if (s->bincache) {
14283 bin = s->bincache;
14284 dlen = s->binlen;
14285 } else {
14286 goto doCHAR;
14287 }
14288 } else {
14289 char *dp;
14290 int i;
14291
14292 freep(&s->bincache);
14293 dp = *data;
14294 dlen = strlen(dp);
14295 s->bincell = dp;
14296 s->binlen = 0;
14297 if (!(dp[0] == 'x' || dp[0] == 'X') || dp[1] != '\'' ||
14298 dp[dlen - 1] != '\'') {
14299 goto doCHAR;
14300 }
14301 dlen -= 2;
14302 dp += 2;
14303 dlen = dlen / 2;
14304 s->bincache = bin = xmalloc(dlen + 1);
14305 if (!bin) {
14306 return nomem(s);
14307 }
14308 s->binlen = dlen;
14309 memset(bin, 0, dlen);
14310 bin[dlen] = '\0'; /* terminator, just in case */
14311 for (i = 0; i < dlen; i++) {
14312 char *x;
14313 int v;
14314
14315 if (!*dp || !(x = strchr(xdigits, *dp))) {
14316 goto converr;
14317 }
14318 v = x - xdigits;
14319 bin[i] = (v >= 16) ? ((v - 6) << 4) : (v << 4);
14320 ++dp;
14321 if (!*dp || !(x = strchr(xdigits, *dp))) {
14322converr:
14323 freep(&s->bincache);
14324 s->binlen = 0;
14325 setstat(s, -1, "conversion error",
14326 (*s->ov3) ? "HY000" : "S1000");
14327 return SQL_ERROR;
14328 }
14329 v = x - xdigits;
14330 bin[i] |= (v >= 16) ? (v - 6) : v;
14331 ++dp;
14332 }
14333 bin = s->bincache;
14334 }
14335 if (partial && len && s->bindcols) {
14336 if (s->bindcols[col].offs >= dlen) {
14337 *lenp = 0;
14338 if (!dlen && s->bindcols[col].offs == dlen) {
14339 s->bindcols[col].offs = 1;
14340 sret = SQL_SUCCESS;
14341 goto done;
14342 }
14343 s->bindcols[col].offs = 0;
14344 sret = SQL_NO_DATA;
14345 goto done;
14346 }
14347 offs = s->bindcols[col].offs;
14348 dlen -= offs;
14349 }
14350 if (val && len) {
14351 memcpy(val, bin + offs, min(len, dlen));
14352 }
14353 if (len < 1) {
14354 *lenp = dlen;
14355 } else {
14356 *lenp = min(len, dlen);
14357 if (*lenp == len && *lenp != dlen) {
14358 *lenp = SQL_NO_TOTAL;
14359 }
14360 }
14361 if (partial && len && s->bindcols) {
14362 if (*lenp == SQL_NO_TOTAL) {
14363 *lenp = dlen;
14364 s->bindcols[col].offs += len;
14365 setstat(s, -1, "data right truncated", "01004");
14366 if (s->bindcols[col].lenp) {
14367 *s->bindcols[col].lenp = dlen;
14368 }
14369 sret = SQL_SUCCESS_WITH_INFO;
14370 goto done;
14371 }
14372 s->bindcols[col].offs += *lenp;
14373 }
14374 if (*lenp == SQL_NO_TOTAL) {
14375 *lenp = dlen;
14376 setstat(s, -1, "data right truncated", "01004");
14377 sret = SQL_SUCCESS_WITH_INFO;
14378 goto done;
14379 }
14380 break;
14381 }
14382 doCHAR:
14383#ifdef WCHARSUPPORT
14384 case SQL_C_WCHAR:
14385#endif
14386 case SQL_C_CHAR: {
14387 int doz, zlen = len - 1;
14388 int dlen = strlen(*data);
14389 int offs = 0;
14390#ifdef WCHARSUPPORT
14391 SQLWCHAR *ucdata = NULL;
14392 SQLCHAR *cdata = (SQLCHAR *) *data;
14393#endif
14394
14395#if (defined(_WIN32) || defined(_WIN64)) && defined(WINTERFACE)
14396 /* MS Access hack part 2 (reserved error -7748) */
14397 if (!valnull &&
14398 (s->cols == statSpec2P || s->cols == statSpec3P) &&
14399 type == SQL_C_WCHAR) {
14400 if (len > 0 && len <= sizeof (SQLWCHAR)) {
14401 ((char *) val)[0] = data[0][0];
14402 memset((char *) val + 1, 0, len - 1);
14403 *lenp = 1;
14404 sret = SQL_SUCCESS;
14405 goto done;
14406 }
14407 }
14408#endif
14409
14410#ifdef WCHARSUPPORT
14411 switch (type) {
14412 case SQL_C_CHAR:
14413 doz = 1;
14414 break;
14415 case SQL_C_WCHAR:
14416 doz = sizeof (SQLWCHAR);
14417 break;
14418 default:
14419 doz = 0;
14420 break;
14421 }
14422 if (type == SQL_C_WCHAR) {
14423 ucdata = uc_from_utf(cdata, dlen);
14424 if (!ucdata) {
14425 return nomem(s);
14426 }
14427 dlen = uc_strlen(ucdata) * sizeof (SQLWCHAR);
14428 }
14429#if defined(_WIN32) || defined(_WIN64)
14430 else if (*s->oemcp && type == SQL_C_CHAR) {
14431 ucdata = (SQLWCHAR *) utf_to_wmb((char *) cdata, dlen);
14432 if (!ucdata) {
14433 return nomem(s);
14434 }
14435 cdata = (SQLCHAR *) ucdata;
14436 dlen = strlen((char *) cdata);
14437 }
14438#endif
14439#else
14440 doz = (type == SQL_C_CHAR) ? 1 : 0;
14441#endif
14442 if (partial && len && s->bindcols) {
14443 if (s->bindcols[col].offs >= dlen) {
14444#ifdef WCHARSUPPORT
14445 uc_free(ucdata);
14446#endif
14447 *lenp = 0;
14448 if (doz && val) {
14449#ifdef WCHARSUPPORT
14450 if (type == SQL_C_WCHAR) {
14451 ((SQLWCHAR *) val)[0] = 0;
14452 } else {
14453 ((char *) val)[0] = '\0';
14454 }
14455#else
14456 ((char *) val)[0] = '\0';
14457#endif
14458 }
14459 if (!dlen && s->bindcols[col].offs == dlen) {
14460 s->bindcols[col].offs = 1;
14461 sret = SQL_SUCCESS;
14462 goto done;
14463 }
14464 s->bindcols[col].offs = 0;
14465 sret = SQL_NO_DATA;
14466 goto done;
14467 }
14468 offs = s->bindcols[col].offs;
14469 dlen -= offs;
14470 }
14471 if (val && !valnull && len) {
14472#ifdef WCHARSUPPORT
14473 if (type == SQL_C_WCHAR) {
14474 uc_strncpy(val, ucdata + offs / sizeof (SQLWCHAR),
14475 (len - doz) / sizeof (SQLWCHAR));
14476 } else {
14477 strncpy(val, (char *) cdata + offs, len - doz);
14478 }
14479#else
14480 strncpy(val, *data + offs, len - doz);
14481#endif
14482 }
14483 if (valnull || len < 1) {
14484 *lenp = dlen;
14485 } else {
14486 *lenp = min(len - doz, dlen);
14487 if (*lenp == len - doz && *lenp != dlen) {
14488 *lenp = SQL_NO_TOTAL;
14489 } else if (*lenp < zlen) {
14490 zlen = *lenp;
14491 }
14492 }
14493 if (len && !valnull && doz) {
14494#ifdef WCHARSUPPORT
14495 if (type == SQL_C_WCHAR) {
14496 ((SQLWCHAR *) val)[zlen / sizeof (SQLWCHAR)] = 0;
14497 } else {
14498 ((char *) val)[zlen] = '\0';
14499 }
14500#else
14501 ((char *) val)[zlen] = '\0';
14502#endif
14503 }
14504#ifdef WCHARSUPPORT
14505 uc_free(ucdata);
14506#endif
14507 if (partial && len && s->bindcols) {
14508 if (*lenp == SQL_NO_TOTAL) {
14509 *lenp = dlen;
14510 s->bindcols[col].offs += len - doz;
14511 setstat(s, -1, "data right truncated", "01004");
14512 if (s->bindcols[col].lenp) {
14513 *s->bindcols[col].lenp = dlen;
14514 }
14515 sret = SQL_SUCCESS_WITH_INFO;
14516 goto done;
14517 }
14518 s->bindcols[col].offs += *lenp;
14519 }
14520 if (*lenp == SQL_NO_TOTAL) {
14521 *lenp = dlen;
14522 setstat(s, -1, "data right truncated", "01004");
14523 sret = SQL_SUCCESS_WITH_INFO;
14524 goto done;
14525 }
14526 break;
14527 }
14528#ifdef SQL_C_TYPE_DATE
14529 case SQL_C_TYPE_DATE:
14530#endif
14531 case SQL_C_DATE:
14532 if (str2date(*s->jdconv, *data, (DATE_STRUCT *) val) < 0) {
14533 *lenp = SQL_NULL_DATA;
14534 } else {
14535 *lenp = sizeof (DATE_STRUCT);
14536 }
14537 break;
14538#ifdef SQL_C_TYPE_TIME
14539 case SQL_C_TYPE_TIME:
14540#endif
14541 case SQL_C_TIME:
14542 if (str2time(*s->jdconv, *data, (TIME_STRUCT *) val) < 0) {
14543 *lenp = SQL_NULL_DATA;
14544 } else {
14545 *lenp = sizeof (TIME_STRUCT);
14546 }
14547 break;
14548#ifdef SQL_C_TYPE_TIMESTAMP
14549 case SQL_C_TYPE_TIMESTAMP:
14550#endif
14551 case SQL_C_TIMESTAMP:
14552 if (str2timestamp(*s->jdconv, *data,
14553 (TIMESTAMP_STRUCT *) val) < 0) {
14554 *lenp = SQL_NULL_DATA;
14555 } else {
14556 *lenp = sizeof (TIMESTAMP_STRUCT);
14557 }
14558 switch (s->cols[col].prec) {
14559 case 0:
14560 ((TIMESTAMP_STRUCT *) val)->fraction = 0;
14561 break;
14562 case 1:
14563 ((TIMESTAMP_STRUCT *) val)->fraction /= 100000000;
14564 ((TIMESTAMP_STRUCT *) val)->fraction *= 100000000;
14565 break;
14566 case 2:
14567 ((TIMESTAMP_STRUCT *) val)->fraction /= 10000000;
14568 ((TIMESTAMP_STRUCT *) val)->fraction *= 10000000;
14569 break;
14570 }
14571 break;
14572 default:
14573 return SQL_ERROR;
14574 }
14575 }
14576 sret = SQL_SUCCESS;
14577done:
14578 if (ilenp) {
14579 *ilenp = *lenp;
14580 }
14581 return sret;
14582}
14583
14595static SQLRETURN
14596drvbindcol(SQLHSTMT stmt, SQLUSMALLINT col, SQLSMALLINT type,
14597 SQLPOINTER val, SQLLEN max, SQLLEN *lenp)
14598{
14599 STMT *s;
14600 int sz = 0;
14601
14602 if (stmt == SQL_NULL_HSTMT) {
14603 return SQL_INVALID_HANDLE;
14604 }
14605 s = (STMT *) stmt;
14606 if (col < 1) {
14607 if (col == 0 && s->bkmrk == SQL_UB_ON &&
14608 type == SQL_C_BOOKMARK) {
14609 s->bkmrkcol.type = val ? type : SQL_UNKNOWN_TYPE;
14610 s->bkmrkcol.max = val ? sizeof (SQLINTEGER) : 0;
14611 s->bkmrkcol.lenp = val ? lenp : 0;
14612 s->bkmrkcol.valp = val;
14613 s->bkmrkcol.offs = 0;
14614 if (val && lenp) {
14615 *lenp = 0;
14616 }
14617 return SQL_SUCCESS;
14618 } else if (col == 0 && s->bkmrk == SQL_UB_VARIABLE &&
14619 type == SQL_C_VARBOOKMARK &&
14620 max >= sizeof (sqlite_int64)) {
14621 s->bkmrkcol.type = val ? type : SQL_UNKNOWN_TYPE;
14622 s->bkmrkcol.max = val ? max : 0;
14623 s->bkmrkcol.lenp = val ? lenp : 0;
14624 s->bkmrkcol.valp = val;
14625 s->bkmrkcol.offs = 0;
14626 if (val && lenp) {
14627 *lenp = 0;
14628 }
14629 return SQL_SUCCESS;
14630 }
14631 setstat(s, -1, "invalid column", (*s->ov3) ? "07009" : "S1002");
14632 return SQL_ERROR;
14633 }
14634 if (mkbindcols(s, col) != SQL_SUCCESS) {
14635 return SQL_ERROR;
14636 }
14637 --col;
14638 if (type == SQL_C_DEFAULT) {
14639 type = mapdeftype(type, s->cols[col].type, 0,
14640 s->nowchar[0] || s->nowchar[1]);
14641 }
14642 switch (type) {
14643 case SQL_C_LONG:
14644 case SQL_C_ULONG:
14645 case SQL_C_SLONG:
14646 sz = sizeof (SQLINTEGER);
14647 break;
14648 case SQL_C_TINYINT:
14649 case SQL_C_UTINYINT:
14650 case SQL_C_STINYINT:
14651 sz = sizeof (SQLCHAR);
14652 break;
14653 case SQL_C_SHORT:
14654 case SQL_C_USHORT:
14655 case SQL_C_SSHORT:
14656 sz = sizeof (SQLSMALLINT);
14657 break;
14658 case SQL_C_FLOAT:
14659 sz = sizeof (SQLFLOAT);
14660 break;
14661 case SQL_C_DOUBLE:
14662 sz = sizeof (SQLDOUBLE);
14663 break;
14664 case SQL_C_TIMESTAMP:
14665 sz = sizeof (SQL_TIMESTAMP_STRUCT);
14666 break;
14667 case SQL_C_TIME:
14668 sz = sizeof (SQL_TIME_STRUCT);
14669 break;
14670 case SQL_C_DATE:
14671 sz = sizeof (SQL_DATE_STRUCT);
14672 break;
14673 case SQL_C_CHAR:
14674 break;
14675#ifdef WCHARSUPPORT
14676 case SQL_C_WCHAR:
14677 break;
14678#endif
14679#ifdef SQL_C_TYPE_DATE
14680 case SQL_C_TYPE_DATE:
14681 sz = sizeof (SQL_DATE_STRUCT);
14682 break;
14683#endif
14684#ifdef SQL_C_TYPE_TIME
14685 case SQL_C_TYPE_TIME:
14686 sz = sizeof (SQL_TIME_STRUCT);
14687 break;
14688#endif
14689#ifdef SQL_C_TYPE_TIMESTAMP
14690 case SQL_C_TYPE_TIMESTAMP:
14691 sz = sizeof (SQL_TIMESTAMP_STRUCT);
14692 break;
14693#endif
14694#ifdef SQL_BIT
14695 case SQL_C_BIT:
14696 sz = sizeof (SQLCHAR);
14697 break;
14698#endif
14699 case SQL_C_BINARY:
14700 break;
14701#ifdef SQL_BIGINT
14702 case SQL_C_SBIGINT:
14703 case SQL_C_UBIGINT:
14704 sz = sizeof (SQLBIGINT);
14705 break;
14706#endif
14707 default:
14708 if (val == NULL) {
14709 /* fall through, unbinding column */
14710 break;
14711 }
14712 setstat(s, -1, "invalid type %d", "HY003", type);
14713 return SQL_ERROR;
14714 }
14715 if (val == NULL) {
14716 /* unbind column */
14717 s->bindcols[col].type = SQL_UNKNOWN_TYPE;
14718 s->bindcols[col].max = 0;
14719 s->bindcols[col].lenp = NULL;
14720 s->bindcols[col].valp = NULL;
14721 s->bindcols[col].offs = 0;
14722 } else {
14723 if (sz == 0 && max < 0) {
14724 setstat(s, -1, "invalid length", "HY090");
14725 return SQL_ERROR;
14726 }
14727 s->bindcols[col].type = type;
14728 s->bindcols[col].max = (sz == 0) ? max : sz;
14729 s->bindcols[col].lenp = lenp;
14730 s->bindcols[col].valp = val;
14731 s->bindcols[col].offs = 0;
14732 if (lenp) {
14733 *lenp = 0;
14734 }
14735 }
14736 return SQL_SUCCESS;
14737}
14738
14750SQLRETURN SQL_API
14751SQLBindCol(SQLHSTMT stmt, SQLUSMALLINT col, SQLSMALLINT type,
14752 SQLPOINTER val, SQLLEN max, SQLLEN *lenp)
14753{
14754 SQLRETURN ret;
14755
14757 ret = drvbindcol(stmt, col, type, val, max, lenp);
14759 return ret;
14760}
14761
14766static COL tableSpec2[] = {
14767 { "SYSTEM", "COLUMN", "TABLE_QUALIFIER", SCOL_VARCHAR, 50 },
14768 { "SYSTEM", "COLUMN", "TABLE_OWNER", SCOL_VARCHAR, 50 },
14769 { "SYSTEM", "COLUMN", "TABLE_NAME", SCOL_VARCHAR, 255 },
14770 { "SYSTEM", "COLUMN", "TABLE_TYPE", SCOL_VARCHAR, 50 },
14771 { "SYSTEM", "COLUMN", "REMARKS", SCOL_VARCHAR, 50 }
14772};
14773
14774static COL tableSpec3[] = {
14775 { "SYSTEM", "COLUMN", "TABLE_CAT", SCOL_VARCHAR, 50 },
14776 { "SYSTEM", "COLUMN", "TABLE_SCHEM", SCOL_VARCHAR, 50 },
14777 { "SYSTEM", "COLUMN", "TABLE_NAME", SCOL_VARCHAR, 255 },
14778 { "SYSTEM", "COLUMN", "TABLE_TYPE", SCOL_VARCHAR, 50 },
14779 { "SYSTEM", "COLUMN", "REMARKS", SCOL_VARCHAR, 50 }
14780};
14781
14796static SQLRETURN
14798 SQLCHAR *cat, SQLSMALLINT catLen,
14799 SQLCHAR *schema, SQLSMALLINT schemaLen,
14800 SQLCHAR *table, SQLSMALLINT tableLen,
14801 SQLCHAR *type, SQLSMALLINT typeLen)
14802{
14803 SQLRETURN ret;
14804 STMT *s;
14805 DBC *d;
14806 int ncols, asize, rc, size, npatt;
14807 char *errp = NULL, *sql, tname[512];
14808 char *where = "(type = 'table' or type = 'view')";
14809
14811 tableSpec3, array_size(tableSpec3), &asize);
14812 if (ret != SQL_SUCCESS) {
14813 return ret;
14814 }
14815 s = (STMT *) stmt;
14816 d = (DBC *) s->dbc;
14817 if (type && (typeLen > 0 || typeLen == SQL_NTS) && type[0] == '%') {
14818 int size = 3 * asize;
14819
14820 s->rows = xmalloc(size * sizeof (char *));
14821 if (!s->rows) {
14822 s->nrows = 0;
14823 return nomem(s);
14824 }
14825 memset(s->rows, 0, sizeof (char *) * size);
14826 s->ncols = asize;
14827 s->rows[s->ncols + 0] = "";
14828 s->rows[s->ncols + 1] = "";
14829 s->rows[s->ncols + 2] = "";
14830 s->rows[s->ncols + 3] = "TABLE";
14831 s->rows[s->ncols + 5] = "";
14832 s->rows[s->ncols + 6] = "";
14833 s->rows[s->ncols + 7] = "";
14834 s->rows[s->ncols + 8] = "VIEW";
14835#ifdef MEMORY_DEBUG
14836 s->rowfree = xfree__;
14837#else
14838 s->rowfree = sqlite3_free;
14839#endif
14840 s->nrows = 2;
14841 s->rowp = s->rowprs = -1;
14842 return SQL_SUCCESS;
14843 }
14844 if (cat && (catLen > 0 || catLen == SQL_NTS) && cat[0] == '%') {
14845 table = NULL;
14846 goto doit;
14847 }
14848 if (schema && (schemaLen > 0 || schemaLen == SQL_NTS) &&
14849 schema[0] == '%') {
14850 if ((!cat || catLen == 0 || !cat[0]) &&
14851 (!table || tableLen == 0 || !table[0])) {
14852 table = NULL;
14853 goto doit;
14854 }
14855 }
14856 if (type && (typeLen > 0 || typeLen == SQL_NTS) && type[0] != '\0') {
14857 char tmp[256], *t;
14858 int with_view = 0, with_table = 0;
14859
14860 if (typeLen == SQL_NTS) {
14861 strncpy(tmp, (char *) type, sizeof (tmp));
14862 tmp[sizeof (tmp) - 1] = '\0';
14863 } else {
14864 int len = min(sizeof (tmp) - 1, typeLen);
14865
14866 strncpy(tmp, (char *) type, len);
14867 tmp[len] = '\0';
14868 }
14869 t = tmp;
14870 while (*t) {
14871 *t = TOLOWER(*t);
14872 t++;
14873 }
14874 t = tmp;
14875 unescpat(t);
14876 while (t) {
14877 if (t[0] == '\'') {
14878 ++t;
14879 }
14880 if (strncmp(t, "table", 5) == 0) {
14881 with_table++;
14882 } else if (strncmp(t, "view", 4) == 0) {
14883 with_view++;
14884 }
14885 t = strchr(t, ',');
14886 if (t) {
14887 ++t;
14888 }
14889 }
14890 if (with_view && with_table) {
14891 /* where is already preset */
14892 } else if (with_view && !with_table) {
14893 where = "type = 'view'";
14894 } else if (!with_view && with_table) {
14895 where = "type = 'table'";
14896 } else {
14897 return SQL_SUCCESS;
14898 }
14899 }
14900doit:
14901 if (!table) {
14902 size = 1;
14903 tname[0] = '%';
14904 } else {
14905 if (tableLen == SQL_NTS) {
14906 size = sizeof (tname) - 1;
14907 } else {
14908 size = min(sizeof (tname) - 1, tableLen);
14909 }
14910 strncpy(tname, (char *) table, size);
14911 }
14912 tname[size] = '\0';
14913 npatt = unescpat(tname);
14914#if defined(_WIN32) || defined(_WIN64)
14915 if (npatt) {
14916 sql = sqlite3_mprintf("select %s as 'TABLE_CAT', "
14917 "%s as 'TABLE_SCHEM', "
14918 "tbl_name as 'TABLE_NAME', "
14919 "upper(type) as 'TABLE_TYPE', "
14920 "NULL as 'REMARKS' "
14921 "from sqlite_master where %s "
14922 "and tbl_name like %Q",
14923 d->xcelqrx ? "'main'" : "NULL",
14924 d->xcelqrx ? "''" : "NULL",
14925 where, tname);
14926 } else {
14927 sql = sqlite3_mprintf("select %s as 'TABLE_CAT', "
14928 "%s as 'TABLE_SCHEM', "
14929 "tbl_name as 'TABLE_NAME', "
14930 "upper(type) as 'TABLE_TYPE', "
14931 "NULL as 'REMARKS' "
14932 "from sqlite_master where %s "
14933 "and lower(tbl_name) = lower(%Q)",
14934 d->xcelqrx ? "'main'" : "NULL",
14935 d->xcelqrx ? "''" : "NULL",
14936 where, tname);
14937 }
14938#else
14939 if (npatt) {
14940 sql = sqlite3_mprintf("select NULL as 'TABLE_QUALIFIER', "
14941 "NULL as 'TABLE_OWNER', "
14942 "tbl_name as 'TABLE_NAME', "
14943 "upper(type) as 'TABLE_TYPE', "
14944 "NULL as 'REMARKS' "
14945 "from sqlite_master where %s "
14946 "and tbl_name like %Q",
14947 where, tname);
14948 } else {
14949 sql = sqlite3_mprintf("select NULL as 'TABLE_QUALIFIER', "
14950 "NULL as 'TABLE_OWNER', "
14951 "tbl_name as 'TABLE_NAME', "
14952 "upper(type) as 'TABLE_TYPE', "
14953 "NULL as 'REMARKS' "
14954 "from sqlite_master where %s "
14955 "and lower(tbl_name) = lower(%Q)",
14956 where, tname);
14957 }
14958#endif
14959 if (!sql) {
14960 return nomem(s);
14961 }
14962 ret = starttran(s);
14963 if (ret != SQL_SUCCESS) {
14964 sqlite3_free(sql);
14965 return ret;
14966 }
14967 dbtraceapi(d, "sqlite3_get_table", sql);
14968 rc = sqlite3_get_table(d->sqlite, sql, &s->rows, &s->nrows, &ncols, &errp);
14969 sqlite3_free(sql);
14970 if (rc == SQLITE_OK) {
14971 if (ncols != s->ncols) {
14972 freeresult(s, 0);
14973 s->nrows = 0;
14974 } else {
14975 s->rowfree = sqlite3_free_table;
14976 }
14977 } else {
14978 s->nrows = 0;
14979 s->rows = NULL;
14980 s->rowfree = NULL;
14981 }
14982 if (errp) {
14983 sqlite3_free(errp);
14984 errp = NULL;
14985 }
14986 s->rowp = s->rowprs = -1;
14987 return SQL_SUCCESS;
14988}
14989
14990#ifndef WINTERFACE
15005SQLRETURN SQL_API
15006SQLTables(SQLHSTMT stmt,
15007 SQLCHAR *cat, SQLSMALLINT catLen,
15008 SQLCHAR *schema, SQLSMALLINT schemaLen,
15009 SQLCHAR *table, SQLSMALLINT tableLen,
15010 SQLCHAR *type, SQLSMALLINT typeLen)
15011{
15012#if defined(_WIN32) || defined(_WIN64)
15013 char *c = NULL, *s = NULL, *t = NULL, *y = NULL;
15014#endif
15015 SQLRETURN ret;
15016
15018#if defined(_WIN32) || defined(_WIN64)
15019 if (!((STMT *) stmt)->oemcp[0]) {
15020 ret = drvtables(stmt, cat, catLen, schema, schemaLen,
15021 table, tableLen, type, typeLen);
15022 goto done2;
15023 }
15024 if (cat) {
15025 c = wmb_to_utf_c((char *) cat, catLen);
15026 if (!c) {
15027 ret = nomem((STMT *) stmt);
15028 goto done;
15029 }
15030 }
15031 if (schema) {
15032 s = wmb_to_utf_c((char *) schema, schemaLen);
15033 if (!s) {
15034 ret = nomem((STMT *) stmt);
15035 goto done;
15036 }
15037 }
15038 if (table) {
15039 t = wmb_to_utf_c((char *) table, tableLen);
15040 if (!t) {
15041 ret = nomem((STMT *) stmt);
15042 goto done;
15043 }
15044 }
15045 if (type) {
15046 y = wmb_to_utf_c((char *) type, typeLen);
15047 if (!y) {
15048 ret = nomem((STMT *) stmt);
15049 goto done;
15050 }
15051 }
15052 ret = drvtables(stmt, (SQLCHAR *) c, SQL_NTS, (SQLCHAR *) s, SQL_NTS,
15053 (SQLCHAR *) t, SQL_NTS, (SQLCHAR *) y, SQL_NTS);
15054#else
15055 ret = drvtables(stmt, cat, catLen, schema, schemaLen,
15056 table, tableLen, type, typeLen);
15057#endif
15058#if defined(_WIN32) || defined(_WIN64)
15059done:
15060 uc_free(y);
15061 uc_free(t);
15062 uc_free(s);
15063 uc_free(c);
15064done2:
15065 ;
15066#endif
15068 return ret;
15069}
15070#endif
15071
15072#ifdef WINTERFACE
15087SQLRETURN SQL_API
15089 SQLWCHAR *cat, SQLSMALLINT catLen,
15090 SQLWCHAR *schema, SQLSMALLINT schemaLen,
15091 SQLWCHAR *table, SQLSMALLINT tableLen,
15092 SQLWCHAR *type, SQLSMALLINT typeLen)
15093{
15094 char *c = NULL, *s = NULL, *t = NULL, *y = NULL;
15095 SQLRETURN ret;
15096
15098 if (cat) {
15099 c = uc_to_utf_c(cat, catLen);
15100 if (!c) {
15101 ret = nomem((STMT *) stmt);
15102 goto done;
15103 }
15104 }
15105 if (schema) {
15106 s = uc_to_utf_c(schema, schemaLen);
15107 if (!s) {
15108 ret = nomem((STMT *) stmt);
15109 goto done;
15110 }
15111 }
15112 if (table) {
15113 t = uc_to_utf_c(table, tableLen);
15114 if (!t) {
15115 ret = nomem((STMT *) stmt);
15116 goto done;
15117 }
15118 }
15119 if (type) {
15120 y = uc_to_utf_c(type, typeLen);
15121 if (!y) {
15122 ret = nomem((STMT *) stmt);
15123 goto done;
15124 }
15125 }
15126 ret = drvtables(stmt, (SQLCHAR *) c, SQL_NTS, (SQLCHAR *) s, SQL_NTS,
15127 (SQLCHAR *) t, SQL_NTS, (SQLCHAR *) y, SQL_NTS);
15128done:
15129 uc_free(y);
15130 uc_free(t);
15131 uc_free(s);
15132 uc_free(c);
15134 return ret;
15135}
15136#endif
15137
15142static COL colSpec2[] = {
15143 { "SYSTEM", "COLUMN", "TABLE_QUALIFIER", SCOL_VARCHAR, 50 },
15144 { "SYSTEM", "COLUMN", "TABLE_OWNER", SCOL_VARCHAR, 50 },
15145 { "SYSTEM", "COLUMN", "TABLE_NAME", SCOL_VARCHAR, 255 },
15146 { "SYSTEM", "COLUMN", "COLUMN_NAME", SCOL_VARCHAR, 255 },
15147 { "SYSTEM", "COLUMN", "DATA_TYPE", SQL_SMALLINT, 50 },
15148 { "SYSTEM", "COLUMN", "TYPE_NAME", SCOL_VARCHAR, 50 },
15149 { "SYSTEM", "COLUMN", "PRECISION", SQL_INTEGER, 50 },
15150 { "SYSTEM", "COLUMN", "LENGTH", SQL_INTEGER, 50 },
15151 { "SYSTEM", "COLUMN", "SCALE", SQL_SMALLINT, 50 },
15152 { "SYSTEM", "COLUMN", "RADIX", SQL_SMALLINT, 50 },
15153 { "SYSTEM", "COLUMN", "NULLABLE", SQL_SMALLINT, 50 },
15154 { "SYSTEM", "COLUMN", "REMARKS", SCOL_VARCHAR, 50 },
15155 { "SYSTEM", "COLUMN", "COLUMN_DEF", SCOL_VARCHAR, 50 },
15156 { "SYSTEM", "COLUMN", "SQL_DATA_TYPE", SQL_SMALLINT, 50 },
15157 { "SYSTEM", "COLUMN", "SQL_DATETIME_SUB", SQL_SMALLINT, 50 },
15158 { "SYSTEM", "COLUMN", "CHAR_OCTET_LENGTH", SQL_SMALLINT, 50 },
15159 { "SYSTEM", "COLUMN", "ORDINAL_POSITION", SQL_SMALLINT, 50 },
15160 { "SYSTEM", "COLUMN", "IS_NULLABLE", SCOL_VARCHAR, 50 }
15161};
15162
15163static COL colSpec3[] = {
15164 { "SYSTEM", "COLUMN", "TABLE_CAT", SCOL_VARCHAR, 50 },
15165 { "SYSTEM", "COLUMN", "TABLE_SCHEM", SCOL_VARCHAR, 50 },
15166 { "SYSTEM", "COLUMN", "TABLE_NAME", SCOL_VARCHAR, 255 },
15167 { "SYSTEM", "COLUMN", "COLUMN_NAME", SCOL_VARCHAR, 255 },
15168 { "SYSTEM", "COLUMN", "DATA_TYPE", SQL_SMALLINT, 50 },
15169 { "SYSTEM", "COLUMN", "TYPE_NAME", SCOL_VARCHAR, 50 },
15170 { "SYSTEM", "COLUMN", "COLUMN_SIZE", SQL_INTEGER, 50 },
15171 { "SYSTEM", "COLUMN", "BUFFER_LENGTH", SQL_INTEGER, 50 },
15172 { "SYSTEM", "COLUMN", "DECIMAL_DIGITS", SQL_SMALLINT, 50 },
15173 { "SYSTEM", "COLUMN", "NUM_PREC_RADIX", SQL_SMALLINT, 50 },
15174 { "SYSTEM", "COLUMN", "NULLABLE", SQL_SMALLINT, 50 },
15175 { "SYSTEM", "COLUMN", "REMARKS", SCOL_VARCHAR, 50 },
15176 { "SYSTEM", "COLUMN", "COLUMN_DEF", SCOL_VARCHAR, 50 },
15177 { "SYSTEM", "COLUMN", "SQL_DATA_TYPE", SQL_SMALLINT, 50 },
15178 { "SYSTEM", "COLUMN", "SQL_DATETIME_SUB", SQL_SMALLINT, 50 },
15179 { "SYSTEM", "COLUMN", "CHAR_OCTET_LENGTH", SQL_SMALLINT, 50 },
15180 { "SYSTEM", "COLUMN", "ORDINAL_POSITION", SQL_SMALLINT, 50 },
15181 { "SYSTEM", "COLUMN", "IS_NULLABLE", SCOL_VARCHAR, 50 }
15182};
15183
15198static SQLRETURN
15200 SQLCHAR *cat, SQLSMALLINT catLen,
15201 SQLCHAR *schema, SQLSMALLINT schemaLen,
15202 SQLCHAR *table, SQLSMALLINT tableLen,
15203 SQLCHAR *col, SQLSMALLINT colLen)
15204{
15205 SQLRETURN sret;
15206 STMT *s;
15207 DBC *d;
15208 int ret, nrows, ncols, asize, i, k, roffs, namec;
15209 int tnrows, tncols, npatt;
15210 PTRDIFF_T size;
15211 char *errp = NULL, *sql, tname[512], cname[512], **rowp, **trows;
15212
15214 colSpec3, array_size(colSpec3), &asize);
15215 if (sret != SQL_SUCCESS) {
15216 return sret;
15217 }
15218 s = (STMT *) stmt;
15219 d = (DBC *) s->dbc;
15220 if (!table) {
15221 size = 1;
15222 tname[0] = '%';
15223 } else {
15224 if (tableLen == SQL_NTS) {
15225 size = sizeof (tname) - 1;
15226 } else {
15227 size = min(sizeof (tname) - 1, tableLen);
15228 }
15229 strncpy(tname, (char *) table, size);
15230 }
15231 tname[size] = '\0';
15232 npatt = unescpat(tname);
15233 size = 0;
15234 if (col) {
15235 if (colLen == SQL_NTS) {
15236 size = sizeof (cname) - 1;
15237 } else {
15238 size = min(sizeof (cname) - 1, colLen);
15239 }
15240 strncpy(cname, (char *) col, size);
15241 }
15242 cname[size] = '\0';
15243 if (!strcmp(cname, "%")) {
15244 cname[0] = '\0';
15245 }
15246 if (npatt) {
15247 sql = sqlite3_mprintf("select tbl_name from sqlite_master where "
15248 "(type = 'table' or type = 'view') "
15249 "and tbl_name like %Q", tname);
15250 } else {
15251 sql = sqlite3_mprintf("select tbl_name from sqlite_master where "
15252 "(type = 'table' or type = 'view') "
15253 "and lower(tbl_name) = lower(%Q)", tname);
15254 }
15255 if (!sql) {
15256 return nomem(s);
15257 }
15258 sret = starttran(s);
15259 if (sret != SQL_SUCCESS) {
15260 sqlite3_free(sql);
15261 return sret;
15262 }
15263 dbtraceapi(d, "sqlite3_get_table", sql);
15264 ret = sqlite3_get_table(d->sqlite, sql, &trows, &tnrows, &tncols, &errp);
15265 sqlite3_free(sql);
15266 if (ret != SQLITE_OK) {
15267 setstat(s, ret, "%s (%d)", (*s->ov3) ? "HY000" : "S1000",
15268 errp ? errp : "unknown error", ret);
15269 if (errp) {
15270 sqlite3_free(errp);
15271 errp = NULL;
15272 }
15273 return SQL_ERROR;
15274 }
15275 if (errp) {
15276 sqlite3_free(errp);
15277 errp = NULL;
15278 }
15279 /* pass 1: compute number of rows of result set */
15280 if (tncols * tnrows <= 0) {
15281 sqlite3_free_table(trows);
15282 return SQL_SUCCESS;
15283 }
15284 size = 0;
15285 for (i = 1; i <= tnrows; i++) {
15286 sql = sqlite3_mprintf("PRAGMA table_info(%Q)", trows[i]);
15287 if (!sql) {
15288 sqlite3_free_table(trows);
15289 return nomem(s);
15290 }
15291 dbtraceapi(d, "sqlite3_get_table", sql);
15292 ret = sqlite3_get_table(d->sqlite, sql, &rowp, &nrows, &ncols, &errp);
15293 sqlite3_free(sql);
15294 if (ret != SQLITE_OK) {
15295 setstat(s, ret, "%s (%d)", (*s->ov3) ? "HY000" : "S1000",
15296 errp ? errp : "unknown error", ret);
15297 if (errp) {
15298 sqlite3_free(errp);
15299 errp = NULL;
15300 }
15301 sqlite3_free_table(trows);
15302 return SQL_ERROR;
15303 }
15304 if (errp) {
15305 sqlite3_free(errp);
15306 errp = NULL;
15307 }
15308 if (ncols * nrows > 0) {
15309 namec = -1;
15310 for (k = 0; k < ncols; k++) {
15311 if (strcmp(rowp[k], "name") == 0) {
15312 namec = k;
15313 break;
15314 }
15315 }
15316 if (cname[0]) {
15317 if (namec >= 0) {
15318 for (k = 1; k <= nrows; k++) {
15319 if (namematch(rowp[k * ncols + namec], cname, 1)) {
15320 size++;
15321 }
15322 }
15323 }
15324 } else {
15325 size += nrows;
15326 }
15327 }
15328 sqlite3_free_table(rowp);
15329 }
15330 /* pass 2: fill result set */
15331 if (size <= 0) {
15332 sqlite3_free_table(trows);
15333 return SQL_SUCCESS;
15334 }
15335 s->nrows = size;
15336 size = (size + 1) * asize;
15337 s->rows = xmalloc((size + 1) * sizeof (char *));
15338 if (!s->rows) {
15339 s->nrows = 0;
15340 sqlite3_free_table(trows);
15341 return nomem(s);
15342 }
15343 s->rows[0] = (char *) size;
15344 s->rows += 1;
15345 memset(s->rows, 0, sizeof (char *) * size);
15346 s->rowfree = freerows;
15347 roffs = 1;
15348 for (i = 1; i <= tnrows; i++) {
15349 sql = sqlite3_mprintf("PRAGMA table_info(%Q)", trows[i]);
15350 if (!sql) {
15351 sqlite3_free_table(trows);
15352 return nomem(s);
15353 }
15354 dbtraceapi(d, "sqlite3_get_table", sql);
15355 ret = sqlite3_get_table(d->sqlite, sql, &rowp, &nrows, &ncols, &errp);
15356 sqlite3_free(sql);
15357 if (ret != SQLITE_OK) {
15358 setstat(s, ret, "%s (%d)", (*s->ov3) ? "HY000" : "S1000",
15359 errp ? errp : "unknown error", ret);
15360 if (errp) {
15361 sqlite3_free(errp);
15362 errp = NULL;
15363 }
15364 sqlite3_free_table(trows);
15365 return SQL_ERROR;
15366 }
15367 if (errp) {
15368 sqlite3_free(errp);
15369 errp = NULL;
15370 }
15371 if (ncols * nrows > 0) {
15372 int m, mr, nr = nrows;
15373
15374 namec = -1;
15375 for (k = 0; k < ncols; k++) {
15376 if (strcmp(rowp[k], "name") == 0) {
15377 namec = k;
15378 break;
15379 }
15380 }
15381 if (cname[0]) {
15382 nr = 0;
15383 if (namec >= 0) {
15384 for (k = 1; k <= nrows; k++) {
15385 if (namematch(rowp[k * ncols + namec], cname, 1)) {
15386 nr++;
15387 }
15388 }
15389 }
15390 }
15391 for (k = 0; k < nr; k++) {
15392 m = asize * (roffs + k);
15393#if defined(_WIN32) || defined(_WIN64)
15394 s->rows[m + 0] = xstrdup(d->xcelqrx ? "main" : "");
15395 s->rows[m + 1] = xstrdup("");
15396#else
15397 s->rows[m + 0] = xstrdup("");
15398 s->rows[m + 1] = xstrdup("");
15399#endif
15400 s->rows[m + 2] = xstrdup(trows[i]);
15401 s->rows[m + 8] = xstrdup("10");
15402 s->rows[m + 9] = xstrdup("0");
15403 s->rows[m + 15] = xstrdup("16384");
15404 }
15405 for (k = 0; nr && k < ncols; k++) {
15406 if (strcmp(rowp[k], "cid") == 0) {
15407 for (mr = 0, m = 1; m <= nrows; m++) {
15408 char buf[256];
15409 int ir, coln = k;
15410
15411 if (cname[0] &&
15412 !namematch(rowp[m * ncols + namec], cname, 1)) {
15413 continue;
15414 }
15415 ir = asize * (roffs + mr);
15416 sscanf(rowp[m * ncols + k], "%d", &coln);
15417 sprintf(buf, "%d", coln + 1);
15418 s->rows[ir + 16] = xstrdup(buf);
15419 ++mr;
15420 }
15421 } else if (k == namec) {
15422 for (mr = 0, m = 1; m <= nrows; m++) {
15423 int ir;
15424
15425 if (cname[0] &&
15426 !namematch(rowp[m * ncols + namec], cname, 1)) {
15427 continue;
15428 }
15429 ir = asize * (roffs + mr);
15430 s->rows[ir + 3] = xstrdup(rowp[m * ncols + k]);
15431 ++mr;
15432 }
15433 } else if (strcmp(rowp[k], "notnull") == 0) {
15434 for (mr = 0, m = 1; m <= nrows; m++) {
15435 int ir;
15436
15437 if (cname[0] &&
15438 !namematch(rowp[m * ncols + namec], cname, 1)) {
15439 continue;
15440 }
15441 ir = asize * (roffs + mr);
15442 if (*rowp[m * ncols + k] != '0') {
15443 s->rows[ir + 10] = xstrdup(stringify(SQL_FALSE));
15444 } else {
15445 s->rows[ir + 10] = xstrdup(stringify(SQL_TRUE));
15446 }
15447 s->rows[ir + 17] =
15448 xstrdup((*rowp[m * ncols + k] != '0') ?
15449 "NO" : "YES");
15450 ++mr;
15451 }
15452 } else if (strcmp(rowp[k], "dflt_value") == 0) {
15453 for (mr = 0, m = 1; m <= nrows; m++) {
15454 char *dflt = unquote(rowp[m * ncols + k]);
15455 int ir;
15456
15457 if (cname[0] &&
15458 !namematch(rowp[m * ncols + namec], cname, 1)) {
15459 continue;
15460 }
15461 ir = asize * (roffs + mr);
15462 s->rows[ir + 12] = xstrdup(dflt ? dflt : "NULL");
15463 ++mr;
15464 }
15465 } else if (strcmp(rowp[k], "type") == 0) {
15466 for (mr = 0, m = 1; m <= nrows; m++) {
15467 char *typename = rowp[m * ncols + k];
15468 int sqltype, mm, dd, ir;
15469 char buf[256];
15470
15471 if (cname[0] &&
15472 !namematch(rowp[m * ncols + namec], cname, 1)) {
15473 continue;
15474 }
15475 ir = asize * (roffs + mr);
15476 s->rows[ir + 5] = xstrdup(typename);
15477 sqltype = mapsqltype(typename, NULL, *s->ov3,
15478 s->nowchar[0], s->dobigint);
15479 getmd(typename, sqltype, &mm, &dd);
15480#ifdef SQL_LONGVARCHAR
15481 if (sqltype == SQL_VARCHAR && mm > 255) {
15482 sqltype = SQL_LONGVARCHAR;
15483 }
15484#endif
15485#ifdef WINTERFACE
15486#ifdef SQL_WLONGVARCHAR
15487 if (sqltype == SQL_WVARCHAR && mm > 255) {
15488 sqltype = SQL_WLONGVARCHAR;
15489 }
15490#endif
15491#endif
15492 if (sqltype == SQL_VARBINARY && mm > 255) {
15493 sqltype = SQL_LONGVARBINARY;
15494 }
15495 sprintf(buf, "%d", sqltype);
15496 s->rows[ir + 4] = xstrdup(buf);
15497 s->rows[ir + 13] = xstrdup(buf);
15498 sprintf(buf, "%d", mm);
15499 s->rows[ir + 7] = xstrdup(buf);
15500 sprintf(buf, "%d", dd);
15501 s->rows[ir + 6] = xstrdup(buf);
15502 ++mr;
15503 }
15504 }
15505 }
15506 roffs += nr;
15507 }
15508 sqlite3_free_table(rowp);
15509 }
15510 sqlite3_free_table(trows);
15511 return SQL_SUCCESS;
15512}
15513
15514#ifndef WINTERFACE
15529SQLRETURN SQL_API
15530SQLColumns(SQLHSTMT stmt,
15531 SQLCHAR *cat, SQLSMALLINT catLen,
15532 SQLCHAR *schema, SQLSMALLINT schemaLen,
15533 SQLCHAR *table, SQLSMALLINT tableLen,
15534 SQLCHAR *col, SQLSMALLINT colLen)
15535{
15536#if defined(_WIN32) || defined(_WIN64)
15537 char *c = NULL, *s = NULL, *t = NULL, *k = NULL;
15538#endif
15539 SQLRETURN ret;
15540
15542#if defined(_WIN32) || defined(_WIN64)
15543 if (!((STMT *) stmt)->oemcp[0]) {
15544 ret = drvcolumns(stmt, cat, catLen, schema, schemaLen,
15545 table, tableLen, col, colLen);
15546 goto done2;
15547 }
15548 if (cat) {
15549 c = wmb_to_utf_c((char *) cat, catLen);
15550 if (!c) {
15551 ret = nomem((STMT *) stmt);
15552 goto done;
15553 }
15554 }
15555 if (schema) {
15556 s = wmb_to_utf_c((char *) schema, schemaLen);
15557 if (!s) {
15558 ret = nomem((STMT *) stmt);
15559 goto done;
15560 }
15561 }
15562 if (table) {
15563 t = wmb_to_utf_c((char *) table, tableLen);
15564 if (!t) {
15565 ret = nomem((STMT *) stmt);
15566 goto done;
15567 }
15568 }
15569 if (col) {
15570 k = wmb_to_utf_c((char *) col, colLen);
15571 if (!k) {
15572 ret = nomem((STMT *) stmt);
15573 goto done;
15574 }
15575 }
15576 ret = drvcolumns(stmt, (SQLCHAR *) c, SQL_NTS, (SQLCHAR *) s, SQL_NTS,
15577 (SQLCHAR *) t, SQL_NTS, (SQLCHAR *) k, SQL_NTS);
15578#else
15579 ret = drvcolumns(stmt, cat, catLen, schema, schemaLen,
15580 table, tableLen, col, colLen);
15581#endif
15582#if defined(_WIN32) || defined(_WIN64)
15583done:
15584 uc_free(k);
15585 uc_free(t);
15586 uc_free(s);
15587 uc_free(c);
15588done2:
15589 ;
15590#endif
15592 return ret;
15593}
15594#endif
15595
15596#ifdef WINTERFACE
15611SQLRETURN SQL_API
15613 SQLWCHAR *cat, SQLSMALLINT catLen,
15614 SQLWCHAR *schema, SQLSMALLINT schemaLen,
15615 SQLWCHAR *table, SQLSMALLINT tableLen,
15616 SQLWCHAR *col, SQLSMALLINT colLen)
15617{
15618 char *c = NULL, *s = NULL, *t = NULL, *k = NULL;
15619 SQLRETURN ret;
15620
15622 if (cat) {
15623 c = uc_to_utf_c(cat, catLen);
15624 if (!c) {
15625 ret = nomem((STMT *) stmt);
15626 goto done;
15627 }
15628 }
15629 if (schema) {
15630 s = uc_to_utf_c(schema, schemaLen);
15631 if (!s) {
15632 ret = nomem((STMT *) stmt);
15633 goto done;
15634 }
15635 }
15636 if (table) {
15637 t = uc_to_utf_c(table, tableLen);
15638 if (!t) {
15639 ret = nomem((STMT *) stmt);
15640 goto done;
15641 }
15642 }
15643 if (col) {
15644 k = uc_to_utf_c(col, colLen);
15645 if (!k) {
15646 ret = nomem((STMT *) stmt);
15647 goto done;
15648 }
15649 }
15650 ret = drvcolumns(stmt, (SQLCHAR *) c, SQL_NTS, (SQLCHAR *) s, SQL_NTS,
15651 (SQLCHAR *) t, SQL_NTS, (SQLCHAR *) k, SQL_NTS);
15652done:
15653 uc_free(k);
15654 uc_free(t);
15655 uc_free(s);
15656 uc_free(c);
15658 return ret;
15659
15660}
15661#endif
15662
15667static COL typeSpec2[] = {
15668 { "SYSTEM", "TYPE", "TYPE_NAME", SCOL_VARCHAR, 50 },
15669 { "SYSTEM", "TYPE", "DATA_TYPE", SQL_SMALLINT, 2 },
15670 { "SYSTEM", "TYPE", "PRECISION", SQL_INTEGER, 9 },
15671 { "SYSTEM", "TYPE", "LITERAL_PREFIX", SCOL_VARCHAR, 50 },
15672 { "SYSTEM", "TYPE", "LITERAL_SUFFIX", SCOL_VARCHAR, 50 },
15673 { "SYSTEM", "TYPE", "CREATE_PARAMS", SCOL_VARCHAR, 50 },
15674 { "SYSTEM", "TYPE", "NULLABLE", SQL_SMALLINT, 2 },
15675 { "SYSTEM", "TYPE", "CASE_SENSITIVE", SQL_SMALLINT, 2 },
15676 { "SYSTEM", "TYPE", "SEARCHABLE", SQL_SMALLINT, 2 },
15677 { "SYSTEM", "TYPE", "UNSIGNED_ATTRIBUTE", SQL_SMALLINT, 2 },
15678 { "SYSTEM", "TYPE", "MONEY", SQL_SMALLINT, 2 },
15679 { "SYSTEM", "TYPE", "AUTO_INCREMENT", SQL_SMALLINT, 2 },
15680 { "SYSTEM", "TYPE", "LOCAL_TYPE_NAME", SCOL_VARCHAR, 50 },
15681 { "SYSTEM", "TYPE", "MINIMUM_SCALE", SQL_SMALLINT, 2 },
15682 { "SYSTEM", "TYPE", "MAXIMUM_SCALE", SQL_SMALLINT, 2 }
15683};
15684
15685static COL typeSpec3[] = {
15686 { "SYSTEM", "TYPE", "TYPE_NAME", SCOL_VARCHAR, 50 },
15687 { "SYSTEM", "TYPE", "DATA_TYPE", SQL_SMALLINT, 2 },
15688 { "SYSTEM", "TYPE", "COLUMN_SIZE", SQL_INTEGER, 9 },
15689 { "SYSTEM", "TYPE", "LITERAL_PREFIX", SCOL_VARCHAR, 50 },
15690 { "SYSTEM", "TYPE", "LITERAL_SUFFIX", SCOL_VARCHAR, 50 },
15691 { "SYSTEM", "TYPE", "CREATE_PARAMS", SCOL_VARCHAR, 50 },
15692 { "SYSTEM", "TYPE", "NULLABLE", SQL_SMALLINT, 2 },
15693 { "SYSTEM", "TYPE", "CASE_SENSITIVE", SQL_SMALLINT, 2 },
15694 { "SYSTEM", "TYPE", "SEARCHABLE", SQL_SMALLINT, 2 },
15695 { "SYSTEM", "TYPE", "UNSIGNED_ATTRIBUTE", SQL_SMALLINT, 2 },
15696 { "SYSTEM", "TYPE", "FIXED_PREC_SCALE", SQL_SMALLINT, 2 },
15697 { "SYSTEM", "TYPE", "AUTO_UNIQUE_VALUE", SQL_SMALLINT, 2 },
15698 { "SYSTEM", "TYPE", "LOCAL_TYPE_NAME", SCOL_VARCHAR, 50 },
15699 { "SYSTEM", "TYPE", "MINIMUM_SCALE", SQL_SMALLINT, 2 },
15700 { "SYSTEM", "TYPE", "MAXIMUM_SCALE", SQL_SMALLINT, 2 },
15701 { "SYSTEM", "TYPE", "SQL_DATA_TYPE", SQL_SMALLINT, 2 },
15702 { "SYSTEM", "TYPE", "SQL_DATETIME_SUB", SQL_SMALLINT, 2 },
15703 { "SYSTEM", "TYPE", "NUM_PREC_RADIX", SQL_INTEGER, 4 },
15704 { "SYSTEM", "TYPE", "INTERVAL_PRECISION", SQL_SMALLINT, 2 }
15705};
15706
15717static void
15718mktypeinfo(STMT *s, int row, int asize, char *typename, int type, int tind)
15719{
15720 int offs = row * asize;
15721 char *tcode, *crpar = NULL, *sign = stringify(SQL_FALSE);
15722 char *quote[2] = { NULL, NULL };
15723 static char tcodes[32 * 32];
15724
15725 if (tind <= 0) {
15726 tind = row;
15727 }
15728 tcode = tcodes + tind * 32;
15729 sprintf(tcode, "%d", type);
15730 s->rows[offs + 0] = typename;
15731 s->rows[offs + 1] = tcode;
15732 if (asize >= 17) {
15733 s->rows[offs + 15] = tcode;
15734 s->rows[offs + 16] = "0";
15735 }
15736 switch (type) {
15737 default:
15738#ifdef SQL_LONGVARCHAR
15739 case SQL_LONGVARCHAR:
15740#ifdef WINTERFACE
15741 case SQL_WLONGVARCHAR:
15742#endif
15743 crpar = "length";
15744 quote[0] = quote[1] = "'";
15745 sign = NULL;
15746 s->rows[offs + 2] = "65536";
15747 break;
15748#endif
15749#ifdef SQL_BIT
15750 case SQL_BIT:
15751 sign = NULL;
15752 s->rows[offs + 2] = "1";
15753 break;
15754#endif
15755 case SQL_CHAR:
15756 case SQL_VARCHAR:
15757#ifdef WINTERFACE
15758 case SQL_WCHAR:
15759 case SQL_WVARCHAR:
15760#endif
15761 s->rows[offs + 2] = "255";
15762 crpar = "length";
15763 quote[0] = quote[1] = "'";
15764 sign = NULL;
15765 break;
15766 case SQL_TINYINT:
15767 s->rows[offs + 2] = "3";
15768 break;
15769 case SQL_SMALLINT:
15770 s->rows[offs + 2] = "5";
15771 break;
15772 case SQL_INTEGER:
15773 s->rows[offs + 2] = "9";
15774 break;
15775#ifdef SQL_BIGINT
15776 case SQL_BIGINT:
15777 s->rows[offs + 2] = "19";
15778 break;
15779#endif
15780 case SQL_FLOAT:
15781 s->rows[offs + 2] = "7";
15782 break;
15783 case SQL_DOUBLE:
15784 s->rows[offs + 2] = "15";
15785 break;
15786#ifdef SQL_TYPE_DATE
15787 case SQL_TYPE_DATE:
15788#endif
15789 case SQL_DATE:
15790 s->rows[offs + 2] = "10";
15791 quote[0] = quote[1] = "'";
15792 sign = NULL;
15793 break;
15794#ifdef SQL_TYPE_TIME
15795 case SQL_TYPE_TIME:
15796#endif
15797 case SQL_TIME:
15798 s->rows[offs + 2] = "8";
15799 quote[0] = quote[1] = "'";
15800 sign = NULL;
15801 break;
15802#ifdef SQL_TYPE_TIMESTAMP
15803 case SQL_TYPE_TIMESTAMP:
15804#endif
15805 case SQL_TIMESTAMP:
15806 s->rows[offs + 2] = "32";
15807 quote[0] = quote[1] = "'";
15808 sign = NULL;
15809 break;
15810 case SQL_VARBINARY:
15811 quote[0] = "0x";
15812 sign = NULL;
15813 s->rows[offs + 2] = "255";
15814 break;
15815 case SQL_LONGVARBINARY:
15816 quote[0] = "0x";
15817 sign = NULL;
15818 s->rows[offs + 2] = "65536";
15819 break;
15820 }
15821 s->rows[offs + 3] = quote[0];
15822 s->rows[offs + 4] = quote[1];
15823 s->rows[offs + 5] = crpar;
15824 s->rows[offs + 6] = stringify(SQL_NULLABLE);
15825 s->rows[offs + 7] = stringify(SQL_FALSE);
15826 s->rows[offs + 8] = stringify(SQL_SEARCHABLE);
15827 s->rows[offs + 9] = sign;
15828 s->rows[offs + 10] = stringify(SQL_FALSE);
15829 s->rows[offs + 11] = stringify(SQL_FALSE);
15830 s->rows[offs + 12] = typename;
15831 switch (type) {
15832 case SQL_DATE:
15833 case SQL_TIME:
15834 s->rows[offs + 13] = "0";
15835 s->rows[offs + 14] = "0";
15836 break;
15837#ifdef SQL_TYPE_TIMESTAMP
15838 case SQL_TYPE_TIMESTAMP:
15839#endif
15840 case SQL_TIMESTAMP:
15841 s->rows[offs + 13] = "0";
15842 s->rows[offs + 14] = "3";
15843 break;
15844 default:
15845 s->rows[offs + 13] = NULL;
15846 s->rows[offs + 14] = NULL;
15847 break;
15848 }
15849}
15850
15859static int
15860typeinfosort(const void *a, const void *b)
15861{
15862 char **pa = (char **) a;
15863 char **pb = (char **) b;
15864 int na, nb;
15865
15866 na = strtol(pa[1], NULL, 0);
15867 nb = strtol(pb[1], NULL, 0);
15868 return na - nb;
15869}
15870
15878static SQLRETURN
15879drvgettypeinfo(SQLHSTMT stmt, SQLSMALLINT sqltype)
15880{
15881 SQLRETURN ret;
15882 STMT *s;
15883 int asize;
15884
15886 typeSpec3, array_size(typeSpec3), &asize);
15887 if (ret != SQL_SUCCESS) {
15888 return ret;
15889 }
15890 s = (STMT *) stmt;
15891#ifdef SQL_LONGVARCHAR
15892 s->nrows = (sqltype == SQL_ALL_TYPES) ? 13 : 1;
15893#else
15894 s->nrows = (sqltype == SQL_ALL_TYPES) ? 12 : 1;
15895#endif
15896 if (sqltype == SQL_ALL_TYPES) {
15897#ifdef WINTERFACE
15898 s->nrows += 2;
15899#ifdef SQL_WLONGVARCHAR
15900 s->nrows += 2;
15901#endif
15902#endif
15903 }
15904 if (sqltype == SQL_ALL_TYPES) {
15905 s->nrows += 2;
15906#ifdef SQL_BIT
15907 s->nrows += 1;
15908#endif
15909#ifdef SQL_BIGINT
15910 s->nrows += 1;
15911#endif
15912 }
15913 s->rows = (char **) xmalloc(sizeof (char *) * (s->nrows + 1) * asize);
15914 if (!s->rows) {
15915 s->nrows = 0;
15916 return nomem(s);
15917 }
15918#ifdef MEMORY_DEBUG
15919 s->rowfree = xfree__;
15920#else
15921 s->rowfree = sqlite3_free;
15922#endif
15923 memset(s->rows, 0, sizeof (char *) * (s->nrows + 1) * asize);
15924 if (sqltype == SQL_ALL_TYPES) {
15925 int cc = 1;
15926
15927 mktypeinfo(s, cc++, asize, "varchar", SQL_VARCHAR, 0);
15928 mktypeinfo(s, cc++, asize, "tinyint", SQL_TINYINT, 0);
15929 mktypeinfo(s, cc++, asize, "smallint", SQL_SMALLINT, 0);
15930 mktypeinfo(s, cc++, asize, "integer", SQL_INTEGER, 0);
15931 mktypeinfo(s, cc++, asize, "float", SQL_FLOAT, 0);
15932 mktypeinfo(s, cc++, asize, "double", SQL_DOUBLE, 0);
15933#ifdef SQL_TYPE_DATE
15934 mktypeinfo(s, cc++, asize, "date",
15935 (*s->ov3) ? SQL_TYPE_DATE : SQL_DATE, 0);
15936#else
15937 mktypeinfo(s, cc++, asize, "date", SQL_DATE, 0);
15938#endif
15939#ifdef SQL_TYPE_TIME
15940 mktypeinfo(s, cc++, asize, "time",
15941 (*s->ov3) ? SQL_TYPE_TIME : SQL_TIME, 0);
15942#else
15943 mktypeinfo(s, cc++, asize, "time", SQL_TIME, 0);
15944#endif
15945#ifdef SQL_TYPE_TIMESTAMP
15946 mktypeinfo(s, cc++, asize, "timestamp",
15947 (*s->ov3) ? SQL_TYPE_TIMESTAMP : SQL_TIMESTAMP, 0);
15948#else
15949 mktypeinfo(s, cc++, asize, "timestamp", SQL_TIMESTAMP, 0);
15950#endif
15951 mktypeinfo(s, cc++, asize, "char", SQL_CHAR, 0);
15952 mktypeinfo(s, cc++, asize, "numeric", SQL_DOUBLE, 0);
15953#ifdef SQL_LONGVARCHAR
15954 mktypeinfo(s, cc++, asize, "text", SQL_LONGVARCHAR, 0);
15955 mktypeinfo(s, cc++, asize, "longvarchar", SQL_LONGVARCHAR, 0);
15956#else
15957 mktypeinfo(s, cc++, asize, "text", SQL_VARCHAR, 0);
15958#endif
15959 mktypeinfo(s, cc++, asize, "varbinary", SQL_VARBINARY, 0);
15960 mktypeinfo(s, cc++, asize, "longvarbinary", SQL_LONGVARBINARY, 0);
15961#ifdef SQL_BIT
15962 mktypeinfo(s, cc++, asize, "bit", SQL_BIT, 0);
15963#endif
15964#ifdef SQL_BIGINT
15965 mktypeinfo(s, cc++, asize, "bigint", SQL_BIGINT, 0);
15966#endif
15967#ifdef WINTERFACE
15968 mktypeinfo(s, cc++, asize, "wvarchar", SQL_WVARCHAR, 0);
15969 mktypeinfo(s, cc++, asize, "wchar", SQL_WCHAR, 0);
15970#ifdef SQL_WLONGVARCHAR
15971 mktypeinfo(s, cc++, asize, "wtext", SQL_WLONGVARCHAR, 0);
15972 mktypeinfo(s, cc++, asize, "longwvarchar", SQL_WLONGVARCHAR, 0);
15973#endif
15974#endif
15975 qsort(s->rows + asize, s->nrows, sizeof (char *) * asize,
15976 typeinfosort);
15977 } else {
15978 switch (sqltype) {
15979 case SQL_CHAR:
15980 mktypeinfo(s, 1, asize, "char", SQL_CHAR, 10);
15981 break;
15982 case SQL_VARCHAR:
15983 mktypeinfo(s, 1, asize, "varchar", SQL_VARCHAR, 1);
15984 break;
15985 case SQL_TINYINT:
15986 mktypeinfo(s, 1, asize, "tinyint", SQL_TINYINT, 2);
15987 break;
15988 case SQL_SMALLINT:
15989 mktypeinfo(s, 1, asize, "smallint", SQL_SMALLINT, 3);
15990 break;
15991 case SQL_INTEGER:
15992 mktypeinfo(s, 1, asize, "integer", SQL_INTEGER, 4);
15993 break;
15994 case SQL_FLOAT:
15995 mktypeinfo(s, 1, asize, "float", SQL_FLOAT, 5);
15996 break;
15997 case SQL_DOUBLE:
15998 mktypeinfo(s, 1, asize, "double", SQL_DOUBLE, 6);
15999 break;
16000#ifdef SQL_TYPE_DATE
16001 case SQL_TYPE_DATE:
16002 mktypeinfo(s, 1, asize, "date", SQL_TYPE_DATE, 25);
16003 break;
16004#endif
16005 case SQL_DATE:
16006 mktypeinfo(s, 1, asize, "date", SQL_DATE, 7);
16007 break;
16008#ifdef SQL_TYPE_TIME
16009 case SQL_TYPE_TIME:
16010 mktypeinfo(s, 1, asize, "time", SQL_TYPE_TIME, 26);
16011 break;
16012#endif
16013 case SQL_TIME:
16014 mktypeinfo(s, 1, asize, "time", SQL_TIME, 8);
16015 break;
16016#ifdef SQL_TYPE_TIMESTAMP
16017 case SQL_TYPE_TIMESTAMP:
16018 mktypeinfo(s, 1, asize, "timestamp", SQL_TYPE_TIMESTAMP, 27);
16019 break;
16020#endif
16021 case SQL_TIMESTAMP:
16022 mktypeinfo(s, 1, asize, "timestamp", SQL_TIMESTAMP, 9);
16023 break;
16024#ifdef SQL_LONGVARCHAR
16025 case SQL_LONGVARCHAR:
16026 mktypeinfo(s, 1, asize, "longvarchar", SQL_LONGVARCHAR, 12);
16027 break;
16028#endif
16029 case SQL_VARBINARY:
16030 mktypeinfo(s, 1, asize, "varbinary", SQL_VARBINARY, 30);
16031 break;
16032 case SQL_LONGVARBINARY:
16033 mktypeinfo(s, 1, asize, "longvarbinary", SQL_LONGVARBINARY, 31);
16034 break;
16035#ifdef SQL_BIT
16036 case SQL_BIT:
16037 mktypeinfo(s, 1, asize, "bit", SQL_BIT, 29);
16038 break;
16039#endif
16040#ifdef SQL_BIGINT
16041 case SQL_BIGINT:
16042 mktypeinfo(s, 1, asize, "bigint", SQL_BIGINT, 28);
16043 break;
16044#endif
16045#ifdef WINTERFACE
16046#ifdef SQL_WCHAR
16047 case SQL_WCHAR:
16048 mktypeinfo(s, 1, asize, "wchar", SQL_WCHAR, 18);
16049 break;
16050#endif
16051#ifdef SQL_WVARCHAR
16052 case SQL_WVARCHAR:
16053 mktypeinfo(s, 1, asize, "wvarchar", SQL_WVARCHAR, 19);
16054 break;
16055#endif
16056#ifdef SQL_WLONGVARCHAR
16057 case SQL_WLONGVARCHAR:
16058 mktypeinfo(s, 1, asize, "longwvarchar", SQL_WLONGVARCHAR, 20);
16059 break;
16060#endif
16061#endif
16062 default:
16063 s->nrows = 0;
16064 }
16065 }
16066 return SQL_SUCCESS;
16067}
16068
16069#ifndef WINTERFACE
16077SQLRETURN SQL_API
16078SQLGetTypeInfo(SQLHSTMT stmt, SQLSMALLINT sqltype)
16079{
16080 SQLRETURN ret;
16081
16083 ret = drvgettypeinfo(stmt, sqltype);
16085 return ret;
16086}
16087#endif
16088
16089#ifdef WINTERFACE
16097SQLRETURN SQL_API
16098SQLGetTypeInfoW(SQLHSTMT stmt, SQLSMALLINT sqltype)
16099{
16100 SQLRETURN ret;
16101
16103 ret = drvgettypeinfo(stmt, sqltype);
16105 return ret;
16106}
16107#endif
16108
16113static COL statSpec2[] = {
16114 { "SYSTEM", "STATISTICS", "TABLE_QUALIFIER", SCOL_VARCHAR, 50 },
16115 { "SYSTEM", "STATISTICS", "TABLE_OWNER", SCOL_VARCHAR, 50 },
16116 { "SYSTEM", "STATISTICS", "TABLE_NAME", SCOL_VARCHAR, 255 },
16117 { "SYSTEM", "STATISTICS", "NON_UNIQUE", SQL_SMALLINT, 50 },
16118 { "SYSTEM", "STATISTICS", "INDEX_QUALIFIER", SCOL_VARCHAR, 255 },
16119 { "SYSTEM", "STATISTICS", "INDEX_NAME", SCOL_VARCHAR, 255 },
16120 { "SYSTEM", "STATISTICS", "TYPE", SQL_SMALLINT, 50 },
16121 { "SYSTEM", "STATISTICS", "SEQ_IN_INDEX", SQL_SMALLINT, 50 },
16122 { "SYSTEM", "STATISTICS", "COLUMN_NAME", SCOL_VARCHAR, 255 },
16123 { "SYSTEM", "STATISTICS", "COLLATION", SCOL_CHAR, 1 },
16124 { "SYSTEM", "STATISTICS", "CARDINALITY", SQL_INTEGER, 50 },
16125 { "SYSTEM", "STATISTICS", "PAGES", SQL_INTEGER, 50 },
16126 { "SYSTEM", "STATISTICS", "FILTER_CONDITION", SCOL_VARCHAR, 255 }
16127};
16128
16129static COL statSpec3[] = {
16130 { "SYSTEM", "STATISTICS", "TABLE_CAT", SCOL_VARCHAR, 50 },
16131 { "SYSTEM", "STATISTICS", "TABLE_SCHEM", SCOL_VARCHAR, 50 },
16132 { "SYSTEM", "STATISTICS", "TABLE_NAME", SCOL_VARCHAR, 255 },
16133 { "SYSTEM", "STATISTICS", "NON_UNIQUE", SQL_SMALLINT, 50 },
16134 { "SYSTEM", "STATISTICS", "INDEX_QUALIFIER", SCOL_VARCHAR, 255 },
16135 { "SYSTEM", "STATISTICS", "INDEX_NAME", SCOL_VARCHAR, 255 },
16136 { "SYSTEM", "STATISTICS", "TYPE", SQL_SMALLINT, 50 },
16137 { "SYSTEM", "STATISTICS", "ORDINAL_POSITION", SQL_SMALLINT, 50 },
16138 { "SYSTEM", "STATISTICS", "COLUMN_NAME", SCOL_VARCHAR, 255 },
16139 { "SYSTEM", "STATISTICS", "ASC_OR_DESC", SCOL_CHAR, 1 },
16140 { "SYSTEM", "STATISTICS", "CARDINALITY", SQL_INTEGER, 50 },
16141 { "SYSTEM", "STATISTICS", "PAGES", SQL_INTEGER, 50 },
16142 { "SYSTEM", "STATISTICS", "FILTER_CONDITION", SCOL_VARCHAR, 255 }
16143};
16144
16159static SQLRETURN
16160drvstatistics(SQLHSTMT stmt, SQLCHAR *cat, SQLSMALLINT catLen,
16161 SQLCHAR *schema, SQLSMALLINT schemaLen,
16162 SQLCHAR *table, SQLSMALLINT tableLen,
16163 SQLUSMALLINT itype, SQLUSMALLINT resv)
16164{
16165 SQLRETURN sret;
16166 STMT *s;
16167 DBC *d;
16168 int i, asize, ret, nrows, ncols, offs, namec, uniquec, addipk = 0;
16169 PTRDIFF_T size;
16170 char **rowp, *errp = NULL, *sql, tname[512];
16171
16173 statSpec3, array_size(statSpec3), &asize);
16174 if (sret != SQL_SUCCESS) {
16175 return sret;
16176 }
16177 s = (STMT *) stmt;
16178 d = (DBC *) s->dbc;
16179 if (!table || table[0] == '\0' || table[0] == '%') {
16180 setstat(s, -1, "need table name", (*s->ov3) ? "HY000" : "S1000");
16181 return SQL_ERROR;
16182 }
16183 if (tableLen == SQL_NTS) {
16184 size = sizeof (tname) - 1;
16185 } else {
16186 size = min(sizeof (tname) - 1, tableLen);
16187 }
16188 strncpy(tname, (char *) table, size);
16189 tname[size] = '\0';
16190 unescpat(tname);
16191 sret = starttran(s);
16192 if (sret != SQL_SUCCESS) {
16193 return sret;
16194 }
16195 /*
16196 * Try integer primary key (autoincrement) first
16197 */
16198 if (itype == SQL_INDEX_UNIQUE || itype == SQL_INDEX_ALL) {
16199 rowp = 0;
16200 ret = SQLITE_ERROR;
16201 sql = sqlite3_mprintf("PRAGMA table_info(%Q)", tname);
16202 if (sql) {
16203 dbtraceapi(d, "sqlite3_get_table", sql);
16204 ret = sqlite3_get_table(d->sqlite, sql, &rowp,
16205 &nrows, &ncols, NULL);
16206 sqlite3_free(sql);
16207 }
16208 if (ret == SQLITE_OK) {
16209 int colid, typec, npk = 0, npkint = 0;
16210
16211 namec = findcol(rowp, ncols, "name");
16212 uniquec = findcol(rowp, ncols, "pk");
16213 typec = findcol(rowp, ncols, "type");
16214 colid = findcol(rowp, ncols, "cid");
16215 if (namec < 0 || uniquec < 0 || typec < 0 || colid < 0) {
16216 goto noipk;
16217 }
16218 for (i = 1; i <= nrows; i++) {
16219 if (*rowp[i * ncols + uniquec] != '0') {
16220 npk++;
16221 if (strlen(rowp[i * ncols + typec]) == 7 &&
16222 strncasecmp(rowp[i * ncols + typec], "integer", 7)
16223 == 0) {
16224 npkint++;
16225 }
16226 }
16227 }
16228 if (npkint == 1 && npk == npkint) {
16229 addipk = 1;
16230 }
16231 }
16232noipk:
16233 sqlite3_free_table(rowp);
16234 }
16235 sql = sqlite3_mprintf("PRAGMA index_list(%Q)", tname);
16236 if (!sql) {
16237 return nomem(s);
16238 }
16239 dbtraceapi(d, "sqlite3_get_table", sql);
16240 ret = sqlite3_get_table(d->sqlite, sql, &rowp, &nrows, &ncols, &errp);
16241 sqlite3_free(sql);
16242 if (ret != SQLITE_OK) {
16243 setstat(s, ret, "%s (%d)", (*s->ov3) ? "HY000" : "S1000",
16244 errp ? errp : "unknown error", ret);
16245 if (errp) {
16246 sqlite3_free(errp);
16247 errp = NULL;
16248 }
16249 return SQL_ERROR;
16250 }
16251 if (errp) {
16252 sqlite3_free(errp);
16253 errp = NULL;
16254 }
16255 size = 0;
16256 namec = findcol(rowp, ncols, "name");
16257 uniquec = findcol(rowp, ncols, "unique");
16258 if (namec < 0 || uniquec < 0) {
16259 goto nodata;
16260 }
16261 for (i = 1; i <= nrows; i++) {
16262 int nnrows, nncols;
16263 char **rowpp;
16264 int isuniq;
16265
16266 isuniq = *rowp[i * ncols + uniquec] != '0';
16267 if (isuniq || itype == SQL_INDEX_ALL) {
16268 ret = SQLITE_ERROR;
16269 sql = sqlite3_mprintf("PRAGMA index_info(%Q)",
16270 rowp[i * ncols + namec]);
16271 if (sql) {
16272 dbtraceapi(d, "sqlite3_get_table", sql);
16273 ret = sqlite3_get_table(d->sqlite, sql, &rowpp,
16274 &nnrows, &nncols, NULL);
16275 sqlite3_free(sql);
16276 }
16277 if (ret == SQLITE_OK) {
16278 size += nnrows;
16279 sqlite3_free_table(rowpp);
16280 }
16281 }
16282 }
16283nodata:
16284 if (addipk) {
16285 size++;
16286 }
16287 if (size == 0) {
16288 sqlite3_free_table(rowp);
16289 return SQL_SUCCESS;
16290 }
16291 s->nrows = size;
16292 size = (size + 1) * asize;
16293 s->rows = xmalloc((size + 1) * sizeof (char *));
16294 if (!s->rows) {
16295 s->nrows = 0;
16296 return nomem(s);
16297 }
16298 s->rows[0] = (char *) size;
16299 s->rows += 1;
16300 memset(s->rows, 0, sizeof (char *) * size);
16301 s->rowfree = freerows;
16302 offs = 0;
16303 if (addipk) {
16304 char **rowpp = 0;
16305 int nrows2, ncols2;
16306
16307 sql = sqlite3_mprintf("PRAGMA table_info(%Q)", tname);
16308 if (sql) {
16309 dbtraceapi(d, "sqlite3_get_table", sql);
16310 ret = sqlite3_get_table(d->sqlite, sql, &rowpp,
16311 &nrows2, &ncols2, NULL);
16312 sqlite3_free(sql);
16313 }
16314 if (ret == SQLITE_OK) {
16315 int colid, typec, roffs, namecc, uniquecc;
16316
16317 namecc = findcol(rowpp, ncols2, "name");
16318 uniquecc = findcol(rowpp, ncols2, "pk");
16319 typec = findcol(rowpp, ncols2, "type");
16320 colid = findcol(rowpp, ncols2, "cid");
16321 if (namecc < 0 || uniquecc < 0 || typec < 0 || colid < 0) {
16322 addipk = 0;
16323 s->nrows--;
16324 goto nodata2;
16325 }
16326 for (i = 1; i <= nrows2; i++) {
16327 if (*rowpp[i * ncols2 + uniquecc] != '0' &&
16328 strlen(rowpp[i * ncols2 + typec]) == 7 &&
16329 strncasecmp(rowpp[i * ncols2 + typec], "integer", 7)
16330 == 0) {
16331 break;
16332 }
16333 }
16334 if (i > nrows2) {
16335 addipk = 0;
16336 s->nrows--;
16337 goto nodata2;
16338 }
16339 roffs = s->ncols;
16340#if defined(_WIN32) || defined(_WIN64)
16341 s->rows[roffs + 0] = xstrdup(d->xcelqrx ? "main" : "");
16342 s->rows[roffs + 1] = xstrdup("");
16343#else
16344 s->rows[roffs + 0] = xstrdup("");
16345 s->rows[roffs + 1] = xstrdup("");
16346#endif
16347 s->rows[roffs + 2] = xstrdup(tname);
16348 s->rows[roffs + 3] = xstrdup(stringify(SQL_FALSE));
16349 s->rows[roffs + 5] = xstrdup("sqlite_autoindex_0");
16350 s->rows[roffs + 6] = xstrdup(stringify(SQL_INDEX_OTHER));
16351 s->rows[roffs + 7] = xstrdup("1");
16352 s->rows[roffs + 8] = xstrdup(rowpp[i * ncols2 + namecc]);
16353 s->rows[roffs + 9] = xstrdup("A");
16354 }
16355nodata2:
16356 sqlite3_free_table(rowpp);
16357 }
16358 for (i = 1; i <= nrows; i++) {
16359 int nnrows, nncols;
16360 char **rowpp = 0;
16361
16362 if (*rowp[i * ncols + uniquec] != '0' || itype == SQL_INDEX_ALL) {
16363 int k;
16364
16365 ret = SQLITE_ERROR;
16366 sql = sqlite3_mprintf("PRAGMA index_info(%Q)",
16367 rowp[i * ncols + namec]);
16368 if (sql) {
16369 dbtraceapi(d, "sqlite3_get_table", sql);
16370 ret = sqlite3_get_table(d->sqlite, sql, &rowpp,
16371 &nnrows, &nncols, NULL);
16372 sqlite3_free(sql);
16373 }
16374 if (ret != SQLITE_OK) {
16375 continue;
16376 }
16377 for (k = 0; nnrows && k < nncols; k++) {
16378 if (strcmp(rowpp[k], "name") == 0) {
16379 int m;
16380
16381 for (m = 1; m <= nnrows; m++) {
16382 int roffs = (offs + addipk + m) * s->ncols;
16383 int isuniq;
16384
16385 isuniq = *rowp[i * ncols + uniquec] != '0';
16386 s->rows[roffs + 0] = xstrdup("");
16387 s->rows[roffs + 1] = xstrdup("");
16388 s->rows[roffs + 2] = xstrdup(tname);
16389 if (isuniq) {
16390 s->rows[roffs + 3] = xstrdup(stringify(SQL_FALSE));
16391 } else {
16392 s->rows[roffs + 3] = xstrdup(stringify(SQL_TRUE));
16393 }
16394 s->rows[roffs + 5] = xstrdup(rowp[i * ncols + namec]);
16395 s->rows[roffs + 6] =
16396 xstrdup(stringify(SQL_INDEX_OTHER));
16397 s->rows[roffs + 8] = xstrdup(rowpp[m * nncols + k]);
16398 s->rows[roffs + 9] = xstrdup("A");
16399 }
16400 } else if (strcmp(rowpp[k], "seqno") == 0) {
16401 int m;
16402
16403 for (m = 1; m <= nnrows; m++) {
16404 int roffs = (offs + addipk + m) * s->ncols;
16405 int pos = m - 1;
16406 char buf[32];
16407
16408 sscanf(rowpp[m * nncols + k], "%d", &pos);
16409 sprintf(buf, "%d", pos + 1);
16410 s->rows[roffs + 7] = xstrdup(buf);
16411 }
16412 }
16413 }
16414 offs += nnrows;
16415 sqlite3_free_table(rowpp);
16416 }
16417 }
16418 sqlite3_free_table(rowp);
16419 return SQL_SUCCESS;
16420}
16421
16422#ifndef WINTERFACE
16437SQLRETURN SQL_API
16438SQLStatistics(SQLHSTMT stmt, SQLCHAR *cat, SQLSMALLINT catLen,
16439 SQLCHAR *schema, SQLSMALLINT schemaLen,
16440 SQLCHAR *table, SQLSMALLINT tableLen,
16441 SQLUSMALLINT itype, SQLUSMALLINT resv)
16442{
16443#if defined(_WIN32) || defined(_WIN64)
16444 char *c = NULL, *s = NULL, *t = NULL;
16445#endif
16446 SQLRETURN ret;
16447
16449#if defined(_WIN32) || defined(_WIN64)
16450 if (!((STMT *) stmt)->oemcp[0]) {
16451 ret = drvstatistics(stmt, cat, catLen, schema, schemaLen,
16452 table, tableLen, itype, resv);
16453 goto done2;
16454 }
16455 if (cat) {
16456 c = wmb_to_utf_c((char *) cat, catLen);
16457 if (!c) {
16458 ret = nomem((STMT *) stmt);
16459 goto done;
16460 }
16461 }
16462 if (schema) {
16463 s = wmb_to_utf_c((char *) schema, schemaLen);
16464 if (!s) {
16465 ret = nomem((STMT *) stmt);
16466 goto done;
16467 }
16468 }
16469 if (table) {
16470 t = wmb_to_utf_c((char *) table, tableLen);
16471 if (!t) {
16472 ret = nomem((STMT *) stmt);
16473 goto done;
16474 }
16475 }
16476 ret = drvstatistics(stmt, (SQLCHAR *) c, SQL_NTS, (SQLCHAR *) s, SQL_NTS,
16477 (SQLCHAR *) t, SQL_NTS, itype, resv);
16478#else
16479 ret = drvstatistics(stmt, cat, catLen, schema, schemaLen,
16480 table, tableLen, itype, resv);
16481#endif
16482#if defined(_WIN32) || defined(_WIN64)
16483done:
16484 uc_free(t);
16485 uc_free(s);
16486 uc_free(c);
16487done2:
16488 ;
16489#endif
16491 return ret;
16492}
16493#endif
16494
16495#ifdef WINTERFACE
16510SQLRETURN SQL_API
16511SQLStatisticsW(SQLHSTMT stmt, SQLWCHAR *cat, SQLSMALLINT catLen,
16512 SQLWCHAR *schema, SQLSMALLINT schemaLen,
16513 SQLWCHAR *table, SQLSMALLINT tableLen,
16514 SQLUSMALLINT itype, SQLUSMALLINT resv)
16515{
16516 char *c = NULL, *s = NULL, *t = NULL;
16517 SQLRETURN ret;
16518
16520 if (cat) {
16521 c = uc_to_utf_c(cat, catLen);
16522 if (!c) {
16523 ret = nomem((STMT *) stmt);
16524 goto done;
16525 }
16526 }
16527 if (schema) {
16528 s = uc_to_utf_c(schema, schemaLen);
16529 if (!s) {
16530 ret = nomem((STMT *) stmt);
16531 goto done;
16532 }
16533 }
16534 if (table) {
16535 t = uc_to_utf_c(table, tableLen);
16536 if (!t) {
16537 ret = nomem((STMT *) stmt);
16538 goto done;
16539 }
16540 }
16541 ret = drvstatistics(stmt, (SQLCHAR *) c, SQL_NTS, (SQLCHAR *) s, SQL_NTS,
16542 (SQLCHAR *) t, SQL_NTS, itype, resv);
16543done:
16544 uc_free(t);
16545 uc_free(s);
16546 uc_free(c);
16548 return ret;
16549}
16550#endif
16551
16563SQLRETURN SQL_API
16564SQLGetData(SQLHSTMT stmt, SQLUSMALLINT col, SQLSMALLINT type,
16565 SQLPOINTER val, SQLLEN len, SQLLEN *lenp)
16566{
16567 STMT *s;
16568 SQLRETURN ret = SQL_ERROR;
16569
16571 if (stmt == SQL_NULL_HSTMT) {
16572 return SQL_INVALID_HANDLE;
16573 }
16574 s = (STMT *) stmt;
16575 if (col == 0 && s->bkmrk != SQL_UB_OFF) {
16576 if (s->bkmrk == SQL_UB_ON && type == SQL_C_BOOKMARK) {
16577 *((SQLINTEGER *) val) = s->rowp;
16578 if (lenp) {
16579 *lenp = sizeof (SQLINTEGER);
16580 }
16581 ret = SQL_SUCCESS;
16582 goto done;
16583 } else if (s->bkmrk == SQL_UB_VARIABLE && type == SQL_C_VARBOOKMARK) {
16584 if (s->has_rowid >= 0) {
16585 char **data, *endp = 0;
16586
16587 data = s->rows + s->ncols + (s->rowp * s->ncols)
16588 + s->has_rowid;
16589#ifdef __osf__
16590 *((sqlite_int64 *) val) = strtol(*data, &endp, 0);
16591#else
16592 *((sqlite_int64 *) val) = strtoll(*data, &endp, 0);
16593#endif
16594 } else {
16595 *((sqlite_int64 *) val) = s->rowp;
16596 }
16597 if (lenp) {
16598 *lenp = sizeof (sqlite_int64);
16599 }
16600 ret = SQL_SUCCESS;
16601 goto done;
16602 }
16603 }
16604 if (col < 1 || col > s->ncols) {
16605 setstat(s, -1, "invalid column", (*s->ov3) ? "07009" : "S1002");
16606 goto done;
16607 }
16608 --col;
16609 ret = getrowdata(s, col, type, val, len, lenp, 1);
16610done:
16612 return ret;
16613}
16614
16622static SQLRETURN
16623dofetchbind(STMT *s, int rsi)
16624{
16625 int ret, i, withinfo = 0;
16626
16627 s->row_status0[rsi] = SQL_ROW_SUCCESS;
16628 if (s->bkmrk != SQL_UB_OFF && s->bkmrkcol.valp) {
16629 int bsize = sizeof (SQLINTEGER);
16630
16631 if (s->bkmrkcol.type == SQL_C_VARBOOKMARK) {
16632 SQLPOINTER *val;
16633
16634 if (s->bind_type != SQL_BIND_BY_COLUMN) {
16635 val = (SQLPOINTER)
16636 ((char *) s->bkmrkcol.valp + s->bind_type * rsi);
16637 } else {
16638 val = (SQLPOINTER)
16639 ((char *) s->bkmrkcol.valp + s->bkmrkcol.max * rsi);
16640 }
16641 if (s->bind_offs) {
16642 val = (SQLPOINTER) ((char *) val + *s->bind_offs);
16643 }
16644 if (s->has_rowid >= 0) {
16645 char **data, *endp = 0;
16646
16647 data = s->rows + s->ncols + (s->rowp * s->ncols)
16648 + s->has_rowid;
16649#ifdef __osf__
16650 *(sqlite_int64 *) val = strtol(*data, &endp, 0);
16651#else
16652 *(sqlite_int64 *) val = strtoll(*data, &endp, 0);
16653#endif
16654 } else {
16655 *(sqlite_int64 *) val = s->rowp;
16656 }
16657 bsize = sizeof (sqlite_int64);
16658 } else {
16659 SQLINTEGER *val;
16660
16661 if (s->bind_type != SQL_BIND_BY_COLUMN) {
16662 val = (SQLINTEGER *)
16663 ((char *) s->bkmrkcol.valp + s->bind_type * rsi);
16664 } else {
16665 val = (SQLINTEGER *) s->bkmrkcol.valp + rsi;
16666 }
16667 if (s->bind_offs) {
16668 val = (SQLINTEGER *) ((char *) val + *s->bind_offs);
16669 }
16670 *val = s->rowp;
16671 }
16672 if (s->bkmrkcol.lenp) {
16673 SQLLEN *ival;
16674
16675 if (s->bind_type != SQL_BIND_BY_COLUMN) {
16676 ival = (SQLLEN *)
16677 ((char *) s->bkmrkcol.lenp + s->bind_type * rsi);
16678 } else {
16679 ival = &s->bkmrkcol.lenp[rsi];
16680 }
16681 if (s->bind_offs) {
16682 ival = (SQLLEN *) ((char *) ival + *s->bind_offs);
16683 }
16684 *ival = bsize;
16685 }
16686 }
16687 ret = SQL_SUCCESS;
16688 for (i = 0; s->bindcols && i < s->ncols; i++) {
16689 BINDCOL *b = &s->bindcols[i];
16690 SQLPOINTER dp = 0;
16691 SQLLEN *lp = 0;
16692
16693 b->offs = 0;
16694 if (b->valp) {
16695 if (s->bind_type != SQL_BIND_BY_COLUMN) {
16696 dp = (SQLPOINTER) ((char *) b->valp + s->bind_type * rsi);
16697 } else {
16698 dp = (SQLPOINTER) ((char *) b->valp + b->max * rsi);
16699 }
16700 if (s->bind_offs) {
16701 dp = (SQLPOINTER) ((char *) dp + *s->bind_offs);
16702 }
16703 }
16704 if (b->lenp) {
16705 if (s->bind_type != SQL_BIND_BY_COLUMN) {
16706 lp = (SQLLEN *) ((char *) b->lenp + s->bind_type * rsi);
16707 } else {
16708 lp = b->lenp + rsi;
16709 }
16710 if (s->bind_offs) {
16711 lp = (SQLLEN *) ((char *) lp + *s->bind_offs);
16712 }
16713 }
16714 if (dp || lp) {
16715 ret = getrowdata(s, (SQLUSMALLINT) i, b->type, dp, b->max, lp, 0);
16716 if (!SQL_SUCCEEDED(ret)) {
16717 s->row_status0[rsi] = SQL_ROW_ERROR;
16718 break;
16719 }
16720 if (ret != SQL_SUCCESS) {
16721 withinfo = 1;
16722#ifdef SQL_ROW_SUCCESS_WITH_INFO
16723 s->row_status0[rsi] = SQL_ROW_SUCCESS_WITH_INFO;
16724#endif
16725 }
16726 }
16727 }
16728 if (SQL_SUCCEEDED(ret)) {
16729 ret = withinfo ? SQL_SUCCESS_WITH_INFO : SQL_SUCCESS;
16730 }
16731 return ret;
16732}
16733
16742static SQLRETURN
16743drvfetchscroll(SQLHSTMT stmt, SQLSMALLINT orient, SQLINTEGER offset)
16744{
16745 STMT *s;
16746 int i, withinfo = 0;
16747 SQLRETURN ret;
16748
16749 if (stmt == SQL_NULL_HSTMT) {
16750 return SQL_INVALID_HANDLE;
16751 }
16752 s = (STMT *) stmt;
16753 for (i = 0; i < s->rowset_size; i++) {
16754 s->row_status0[i] = SQL_ROW_NOROW;
16755 }
16756 if (s->row_status) {
16757 memcpy(s->row_status, s->row_status0,
16758 sizeof (SQLUSMALLINT) * s->rowset_size);
16759 }
16760 s->row_count0 = 0;
16761 if (s->row_count) {
16762 *s->row_count = s->row_count0;
16763 }
16764 if (!s->bindcols) {
16765 for (i = 0; i < s->rowset_size; i++) {
16766 s->row_status0[i] = SQL_ROW_ERROR;
16767 }
16768 ret = SQL_ERROR;
16769 i = 0;
16770 goto done2;
16771 }
16772 if (s->isselect != 1 && s->isselect != -1) {
16773 if (s->isselect != 0 || s->ncols <= 0) {
16774 setstat(s, -1, "no result set available", "24000");
16775 ret = SQL_ERROR;
16776 i = s->nrows;
16777 goto done2;
16778 } else {
16779 /* INSERT/UPDATE/DELETE ... RETURNING ... has columns */
16780 }
16781 }
16782 if (s->curtype == SQL_CURSOR_FORWARD_ONLY && orient != SQL_FETCH_NEXT) {
16783 setstat(s, -1, "wrong fetch direction", "01000");
16784 ret = SQL_ERROR;
16785 i = 0;
16786 goto done2;
16787 }
16788 ret = SQL_SUCCESS;
16789 i = 0;
16790 if (((DBC *) (s->dbc))->cur_s3stmt == s && s->s3stmt) {
16791 s->rowp = s->rowprs = 0;
16792 for (; i < s->rowset_size; i++) {
16793 if (s->max_rows && s->s3stmt_rownum + 1 >= s->max_rows) {
16794 ret = (i == 0) ? SQL_NO_DATA : SQL_SUCCESS;
16795 break;
16796 }
16797 ret = s3stmt_step(s);
16798 if (ret != SQL_SUCCESS) {
16799 s->row_status0[i] = SQL_ROW_ERROR;
16800 break;
16801 }
16802 if (s->nrows < 1) {
16803 break;
16804 }
16805 ret = dofetchbind(s, i);
16806 if (!SQL_SUCCEEDED(ret)) {
16807 break;
16808 } else if (ret == SQL_SUCCESS_WITH_INFO) {
16809 withinfo = 1;
16810 }
16811 }
16812 } else if (s->rows) {
16813 switch (orient) {
16814 case SQL_FETCH_NEXT:
16815 if (s->nrows < 1) {
16816 return SQL_NO_DATA;
16817 }
16818 if (s->rowp < 0) {
16819 s->rowp = -1;
16820 }
16821 if (s->rowp >= s->nrows) {
16822 s->rowp = s->rowprs = s->nrows;
16823 return SQL_NO_DATA;
16824 }
16825 break;
16826 case SQL_FETCH_PRIOR:
16827 if (s->nrows < 1 || s->rowp <= 0) {
16828 s->rowp = s->rowprs = -1;
16829 return SQL_NO_DATA;
16830 }
16831 s->rowp -= s->rowset_size + 1;
16832 if (s->rowp < -1) {
16833 s->rowp = s->rowprs = -1;
16834 return SQL_NO_DATA;
16835 }
16836 break;
16837 case SQL_FETCH_FIRST:
16838 if (s->nrows < 1) {
16839 return SQL_NO_DATA;
16840 }
16841 s->rowp = -1;
16842 break;
16843 case SQL_FETCH_LAST:
16844 if (s->nrows < 1) {
16845 return SQL_NO_DATA;
16846 }
16847 s->rowp = s->nrows - s->rowset_size;
16848 if (--s->rowp < -1) {
16849 s->rowp = -1;
16850 }
16851 break;
16852 case SQL_FETCH_ABSOLUTE:
16853 if (offset == 0) {
16854 s->rowp = s->rowprs = -1;
16855 return SQL_NO_DATA;
16856 } else if (offset < 0) {
16857 if (0 - offset <= s->nrows) {
16858 s->rowp = s->nrows + offset - 1;
16859 break;
16860 }
16861 s->rowp = s->rowprs = -1;
16862 return SQL_NO_DATA;
16863 } else if (offset > s->nrows) {
16864 s->rowp = s->rowprs = s->nrows;
16865 return SQL_NO_DATA;
16866 }
16867 s->rowp = offset - 1 - 1;
16868 break;
16869 case SQL_FETCH_RELATIVE:
16870 if (offset >= 0) {
16871 s->rowp += offset * s->rowset_size - 1;
16872 if (s->rowp >= s->nrows) {
16873 s->rowp = s->rowprs = s->nrows;
16874 return SQL_NO_DATA;
16875 }
16876 } else {
16877 s->rowp += offset * s->rowset_size - 1;
16878 if (s->rowp < -1) {
16879 s->rowp = s->rowprs = -1;
16880 return SQL_NO_DATA;
16881 }
16882 }
16883 break;
16884 case SQL_FETCH_BOOKMARK:
16885 if (s->bkmrk == SQL_UB_ON && !s->bkmrkptr) {
16886 if (offset < 0 || offset >= s->nrows) {
16887 return SQL_NO_DATA;
16888 }
16889 s->rowp = offset - 1;
16890 break;
16891 }
16892 if (s->bkmrk != SQL_UB_OFF && s->bkmrkptr) {
16893 int rowp;
16894
16895 if (s->bkmrk == SQL_UB_VARIABLE) {
16896 if (s->has_rowid >= 0) {
16897 sqlite_int64 bkmrk, rowid;
16898
16899 bkmrk = *(sqlite_int64 *) s->bkmrkptr;
16900 for (rowp = 0; rowp < s->nrows; rowp++) {
16901 char **data, *endp = 0;
16902
16903 data = s->rows + s->ncols + (rowp * s->ncols)
16904 + s->has_rowid;
16905#ifdef __osf__
16906 rowid = strtol(*data, &endp, 0);
16907#else
16908 rowid = strtoll(*data, &endp, 0);
16909#endif
16910 if (rowid == bkmrk) {
16911 break;
16912 }
16913 }
16914 } else {
16915 rowp = *(sqlite_int64 *) s->bkmrkptr;
16916 }
16917 } else {
16918 rowp = *(int *) s->bkmrkptr;
16919 }
16920 if (rowp + offset < 0 || rowp + offset >= s->nrows) {
16921 return SQL_NO_DATA;
16922 }
16923 s->rowp = rowp + offset - 1;
16924 break;
16925 }
16926 /* fall through */
16927 default:
16928 s->row_status0[0] = SQL_ROW_ERROR;
16929 ret = SQL_ERROR;
16930 goto done;
16931 }
16932 s->rowprs = s->rowp + 1;
16933 for (; i < s->rowset_size; i++) {
16934 ++s->rowp;
16935 if (s->rowp < 0 || s->rowp >= s->nrows) {
16936 break;
16937 }
16938 ret = dofetchbind(s, i);
16939 if (!SQL_SUCCEEDED(ret)) {
16940 break;
16941 } else if (ret == SQL_SUCCESS_WITH_INFO) {
16942 withinfo = 1;
16943 }
16944 }
16945 }
16946done:
16947 if (i == 0) {
16948 if (SQL_SUCCEEDED(ret)) {
16949 return SQL_NO_DATA;
16950 }
16951 return ret;
16952 }
16953 if (SQL_SUCCEEDED(ret)) {
16954 ret = withinfo ? SQL_SUCCESS_WITH_INFO : SQL_SUCCESS;
16955 }
16956done2:
16957 if (s->row_status) {
16958 memcpy(s->row_status, s->row_status0,
16959 sizeof (SQLUSMALLINT) * s->rowset_size);
16960 }
16961 s->row_count0 = i;
16962 if (s->row_count) {
16963 *s->row_count = s->row_count0;
16964 }
16965 return ret;
16966}
16967
16974SQLRETURN SQL_API
16976{
16977 SQLRETURN ret;
16978
16980 ret = drvfetchscroll(stmt, SQL_FETCH_NEXT, 0);
16982 return ret;
16983}
16984
16993SQLRETURN SQL_API
16994SQLFetchScroll(SQLHSTMT stmt, SQLSMALLINT orient, SQLLEN offset)
16995{
16996 SQLRETURN ret;
16997
16999 ret = drvfetchscroll(stmt, orient, offset);
17001 return ret;
17002}
17003
17014SQLRETURN SQL_API
17015SQLExtendedFetch(SQLHSTMT stmt, SQLUSMALLINT orient, SQLROWOFFSET offset,
17016 SQLROWSETSIZE *rowcount, SQLUSMALLINT *rowstatus)
17017{
17018 STMT *s;
17019 SQLRETURN ret;
17020 SQLUSMALLINT *rst;
17021 SQLINTEGER *bkmrkptr;
17022
17024 if (stmt == SQL_NULL_HSTMT) {
17025 return SQL_INVALID_HANDLE;
17026 }
17027 s = (STMT *) stmt;
17028 /* temporarily turn off SQL_ATTR_ROW_STATUS_PTR */
17029 rst = s->row_status;
17030 s->row_status = 0;
17031 bkmrkptr = s->bkmrkptr;
17032 s->bkmrkptr = 0;
17033 ret = drvfetchscroll(stmt, orient, offset);
17034 s->row_status = rst;
17035 s->bkmrkptr = bkmrkptr;
17036 if (rowstatus) {
17037 memcpy(rowstatus, s->row_status0,
17038 sizeof (SQLUSMALLINT) * s->rowset_size);
17039 }
17040 if (rowcount) {
17041 *rowcount = s->row_count0;
17042 }
17044 return ret;
17045}
17046
17054SQLRETURN SQL_API
17055SQLRowCount(SQLHSTMT stmt, SQLLEN *nrows)
17056{
17057 STMT *s;
17058
17060 if (stmt == SQL_NULL_HSTMT) {
17061 return SQL_INVALID_HANDLE;
17062 }
17063 s = (STMT *) stmt;
17064 if (nrows) {
17065 *nrows = s->isselect ? 0 : s->nrows;
17066 }
17068 return SQL_SUCCESS;
17069}
17070
17078SQLRETURN SQL_API
17079SQLNumResultCols(SQLHSTMT stmt, SQLSMALLINT *ncols)
17080{
17081 STMT *s;
17082
17084 if (stmt == SQL_NULL_HSTMT) {
17085 return SQL_INVALID_HANDLE;
17086 }
17087 s = (STMT *) stmt;
17088 if (ncols) {
17089 *ncols = s->ncols;
17090 }
17092 return SQL_SUCCESS;
17093}
17094
17109static SQLRETURN
17110drvdescribecol(SQLHSTMT stmt, SQLUSMALLINT col, SQLCHAR *name,
17111 SQLSMALLINT nameMax, SQLSMALLINT *nameLen,
17112 SQLSMALLINT *type, SQLULEN *size,
17113 SQLSMALLINT *digits, SQLSMALLINT *nullable)
17114{
17115 STMT *s;
17116 COL *c;
17117 int didname = 0;
17118
17119 if (stmt == SQL_NULL_HSTMT) {
17120 return SQL_INVALID_HANDLE;
17121 }
17122 s = (STMT *) stmt;
17123 if (!s->cols) {
17124 setstat(s, -1, "no columns", (*s->ov3) ? "07009" : "S1002");
17125 return SQL_ERROR;
17126 }
17127 if (col < 1 || col > s->ncols) {
17128 setstat(s, -1, "invalid column", (*s->ov3) ? "07009" : "S1002");
17129 return SQL_ERROR;
17130 }
17131 c = s->cols + col - 1;
17132 if (name && nameMax > 0) {
17133 strncpy((char *) name, c->column, nameMax);
17134 name[nameMax - 1] = '\0';
17135 didname = 1;
17136 }
17137 if (nameLen) {
17138 if (didname) {
17139 *nameLen = strlen((char *) name);
17140 } else {
17141 *nameLen = strlen(c->column);
17142 }
17143 }
17144 if (type) {
17145 *type = c->type;
17146#ifdef WINTERFACE
17147 if (s->nowchar[0] || s->nowchar[1]) {
17148 switch (c->type) {
17149 case SQL_WCHAR:
17150 *type = SQL_CHAR;
17151 break;
17152 case SQL_WVARCHAR:
17153 *type = SQL_VARCHAR;
17154 break;
17155#ifdef SQL_LONGVARCHAR
17156 case SQL_WLONGVARCHAR:
17157 *type = SQL_LONGVARCHAR;
17158 break;
17159#endif
17160 }
17161 }
17162#endif
17163 }
17164 if (size) {
17165 *size = c->size;
17166 }
17167 if (digits) {
17168 *digits = 0;
17169 }
17170 if (nullable) {
17171 *nullable = 1;
17172 }
17173 return SQL_SUCCESS;
17174}
17175
17176#ifndef WINTERFACE
17191SQLRETURN SQL_API
17192SQLDescribeCol(SQLHSTMT stmt, SQLUSMALLINT col, SQLCHAR *name,
17193 SQLSMALLINT nameMax, SQLSMALLINT *nameLen,
17194 SQLSMALLINT *type, SQLULEN *size,
17195 SQLSMALLINT *digits, SQLSMALLINT *nullable)
17196{
17197#if defined(_WIN32) || defined(_WIN64)
17198 SQLSMALLINT len = 0;
17199#endif
17200 SQLRETURN ret;
17201
17203#if defined(_WIN32) || defined(_WIN64)
17204 if (!((STMT *) stmt)->oemcp[0]) {
17205 ret = drvdescribecol(stmt, col, name, nameMax, nameLen,
17206 type, size, digits, nullable);
17207 goto done;
17208 }
17209 ret = drvdescribecol(stmt, col, name, nameMax,
17210 &len, type, size, digits, nullable);
17211 if (ret == SQL_SUCCESS) {
17212 if (name) {
17213 if (len > 0) {
17214 SQLCHAR *n = NULL;
17215
17216 n = (SQLCHAR *) utf_to_wmb((char *) name, len);
17217 if (n) {
17218 strncpy((char *) name, (char *) n, nameMax);
17219 n[len] = 0;
17220 len = min(nameMax, strlen((char *) n));
17221 uc_free(n);
17222 } else {
17223 len = 0;
17224 }
17225 }
17226 if (len <= 0) {
17227 len = 0;
17228 if (nameMax > 0) {
17229 name[0] = 0;
17230 }
17231 }
17232 } else {
17233 STMT *s = (STMT *) stmt;
17234 COL *c = s->cols + col - 1;
17235
17236 len = 0;
17237 if (c->column) {
17238 len = strlen(c->column);
17239 }
17240 }
17241 if (nameLen) {
17242 *nameLen = len;
17243 }
17244 }
17245done:
17246 ;
17247#else
17248 ret = drvdescribecol(stmt, col, name, nameMax, nameLen,
17249 type, size, digits, nullable);
17250#endif
17252 return ret;
17253}
17254#endif
17255
17256#ifdef WINTERFACE
17271SQLRETURN SQL_API
17272SQLDescribeColW(SQLHSTMT stmt, SQLUSMALLINT col, SQLWCHAR *name,
17273 SQLSMALLINT nameMax, SQLSMALLINT *nameLen,
17274 SQLSMALLINT *type, SQLULEN *size,
17275 SQLSMALLINT *digits, SQLSMALLINT *nullable)
17276{
17277 SQLRETURN ret;
17278 SQLSMALLINT len = 0;
17279
17281 ret = drvdescribecol(stmt, col, (SQLCHAR *) name,
17282 (SQLSMALLINT) (nameMax * sizeof (SQLWCHAR)),
17283 &len, type, size, digits, nullable);
17284 if (ret == SQL_SUCCESS) {
17285 if (name) {
17286 if (len > 0) {
17287 SQLWCHAR *n = NULL;
17288
17289 n = uc_from_utf((SQLCHAR *) name, len);
17290 if (n) {
17291 uc_strncpy(name, n, nameMax);
17292 n[len] = 0;
17293 len = min(nameMax, uc_strlen(n));
17294 uc_free(n);
17295 } else {
17296 len = 0;
17297 }
17298 }
17299 if (len <= 0) {
17300 len = 0;
17301 if (nameMax > 0) {
17302 name[0] = 0;
17303 }
17304 }
17305 } else {
17306 STMT *s = (STMT *) stmt;
17307 COL *c = s->cols + col - 1;
17308
17309 len = 0;
17310 if (c->column) {
17311 len = strlen(c->column);
17312 }
17313 }
17314 if (nameLen) {
17315 *nameLen = len;
17316 }
17317 }
17319 return ret;
17320}
17321#endif
17322
17335static SQLRETURN
17336drvcolattributes(SQLHSTMT stmt, SQLUSMALLINT col, SQLUSMALLINT id,
17337 SQLPOINTER val, SQLSMALLINT valMax, SQLSMALLINT *valLen,
17338 SQLLEN *val2)
17339{
17340 STMT *s;
17341 COL *c;
17342 SQLSMALLINT dummy;
17343 char *valc = (char *) val;
17344
17345 if (stmt == SQL_NULL_HSTMT) {
17346 return SQL_INVALID_HANDLE;
17347 }
17348 s = (STMT *) stmt;
17349 if (!s->cols) {
17350 return SQL_ERROR;
17351 }
17352 if (!valLen) {
17353 valLen = &dummy;
17354 }
17355 if (id == SQL_COLUMN_COUNT) {
17356 if (val2) {
17357 *val2 = s->ncols;
17358 }
17359 *valLen = sizeof (int);
17360 return SQL_SUCCESS;
17361 }
17362 if (id == SQL_COLUMN_TYPE && col == 0) {
17363 if (val2) {
17364 *val2 = SQL_INTEGER;
17365 }
17366 *valLen = sizeof (int);
17367 return SQL_SUCCESS;
17368 }
17369#ifdef SQL_DESC_OCTET_LENGTH
17370 if (id == SQL_DESC_OCTET_LENGTH && col == 0) {
17371 if (val2) {
17372 *val2 = 4;
17373 }
17374 *valLen = sizeof (int);
17375 return SQL_SUCCESS;
17376 }
17377#endif
17378 if (col < 1 || col > s->ncols) {
17379 setstat(s, -1, "invalid column", (*s->ov3) ? "07009": "S1002");
17380 return SQL_ERROR;
17381 }
17382 c = s->cols + col - 1;
17383
17384 switch (id) {
17385 case SQL_COLUMN_LABEL:
17386 if (c->label) {
17387 if (valc && valMax > 0) {
17388 strncpy(valc, c->label, valMax);
17389 valc[valMax - 1] = '\0';
17390 }
17391 *valLen = strlen(c->label);
17392 goto checkLen;
17393 }
17394 /* fall through */
17395 case SQL_COLUMN_NAME:
17396 case SQL_DESC_NAME:
17397 if (valc && valMax > 0) {
17398 strncpy(valc, c->column, valMax);
17399 valc[valMax - 1] = '\0';
17400 }
17401 *valLen = strlen(c->column);
17402checkLen:
17403 if (*valLen >= valMax) {
17404 setstat(s, -1, "data right truncated", "01004");
17405 return SQL_SUCCESS_WITH_INFO;
17406 }
17407 return SQL_SUCCESS;
17408#ifdef SQL_DESC_BASE_COLUMN_NAME
17409 case SQL_DESC_BASE_COLUMN_NAME:
17410 if (strchr(c->column, '(') || strchr(c->column, ')')) {
17411 if (valc && valMax > 0) {
17412 valc[0] = '\0';
17413 }
17414 *valLen = 0;
17415 } else if (valc && valMax > 0) {
17416 strncpy(valc, c->column, valMax);
17417 valc[valMax - 1] = '\0';
17418 *valLen = strlen(c->column);
17419 }
17420 goto checkLen;
17421#endif
17422 case SQL_COLUMN_TYPE:
17423 case SQL_DESC_TYPE:
17424#ifdef WINTERFACE
17425 {
17426 int type = c->type;
17427
17428 if (s->nowchar[0] || s->nowchar[1]) {
17429 switch (type) {
17430 case SQL_WCHAR:
17431 type = SQL_CHAR;
17432 break;
17433 case SQL_WVARCHAR:
17434 type = SQL_VARCHAR;
17435 break;
17436#ifdef SQL_LONGVARCHAR
17437 case SQL_WLONGVARCHAR:
17438 type = SQL_LONGVARCHAR;
17439 break;
17440 }
17441 }
17442 if (val2) {
17443 *val2 = type;
17444 }
17445#endif
17446 }
17447#else
17448 if (val2) {
17449 *val2 = c->type;
17450 }
17451#endif
17452 *valLen = sizeof (int);
17453 return SQL_SUCCESS;
17454 case SQL_COLUMN_DISPLAY_SIZE:
17455 if (val2) {
17456 *val2 = c->size;
17457 }
17458 *valLen = sizeof (int);
17459 return SQL_SUCCESS;
17460 case SQL_COLUMN_UNSIGNED:
17461 if (val2) {
17462 *val2 = c->nosign ? SQL_TRUE : SQL_FALSE;
17463 }
17464 *valLen = sizeof (int);
17465 return SQL_SUCCESS;
17466 case SQL_COLUMN_SCALE:
17467 case SQL_DESC_SCALE:
17468 if (val2) {
17469 *val2 = c->scale;
17470 }
17471 *valLen = sizeof (int);
17472 return SQL_SUCCESS;
17473 case SQL_COLUMN_PRECISION:
17474 case SQL_DESC_PRECISION:
17475 if (val2) {
17476 switch (c->type) {
17477 case SQL_SMALLINT:
17478 *val2 = 5;
17479 break;
17480 case SQL_INTEGER:
17481 *val2 = 10;
17482 break;
17483 case SQL_FLOAT:
17484 case SQL_REAL:
17485 case SQL_DOUBLE:
17486 *val2 = 15;
17487 break;
17488 case SQL_DATE:
17489 *val2 = 0;
17490 break;
17491 case SQL_TIME:
17492 *val2 = 0;
17493 break;
17494#ifdef SQL_TYPE_TIMESTAMP
17495 case SQL_TYPE_TIMESTAMP:
17496#endif
17497 case SQL_TIMESTAMP:
17498 *val2 = (c->prec >= 0 && c->prec <= 3) ? c->prec : 3;
17499 break;
17500 default:
17501 *val2 = c->prec;
17502 break;
17503 }
17504 }
17505 *valLen = sizeof (int);
17506 return SQL_SUCCESS;
17507 case SQL_COLUMN_MONEY:
17508 if (val2) {
17509 *val2 = SQL_FALSE;
17510 }
17511 *valLen = sizeof (int);
17512 return SQL_SUCCESS;
17513 case SQL_COLUMN_AUTO_INCREMENT:
17514 if (val2) {
17515 *val2 = c->autoinc;
17516 }
17517 *valLen = sizeof (int);
17518 return SQL_SUCCESS;
17519 case SQL_COLUMN_LENGTH:
17520 case SQL_DESC_LENGTH:
17521 if (val2) {
17522 *val2 = c->size;
17523 }
17524 *valLen = sizeof (int);
17525 return SQL_SUCCESS;
17526 case SQL_COLUMN_NULLABLE:
17527 case SQL_DESC_NULLABLE:
17528 if (val2) {
17529 *val2 = c->notnull;
17530 }
17531 *valLen = sizeof (int);
17532 return SQL_SUCCESS;
17533 case SQL_COLUMN_SEARCHABLE:
17534 if (val2) {
17535 *val2 = SQL_SEARCHABLE;
17536 }
17537 *valLen = sizeof (int);
17538 return SQL_SUCCESS;
17539 case SQL_COLUMN_CASE_SENSITIVE:
17540 if (val2) {
17541 *val2 = SQL_TRUE;
17542 }
17543 *valLen = sizeof (int);
17544 return SQL_SUCCESS;
17545 case SQL_COLUMN_UPDATABLE:
17546 if (val2) {
17547 *val2 = SQL_TRUE;
17548 }
17549 *valLen = sizeof (int);
17550 return SQL_SUCCESS;
17551 case SQL_DESC_COUNT:
17552 if (val2) {
17553 *val2 = s->ncols;
17554 }
17555 *valLen = sizeof (int);
17556 return SQL_SUCCESS;
17557 case SQL_COLUMN_TYPE_NAME: {
17558 char *p = NULL, *tn = c->typename ? c->typename : "varchar";
17559
17560#ifdef WINTERFACE
17561 if (c->type == SQL_WCHAR ||
17562 c->type == SQL_WVARCHAR ||
17563 c->type == SQL_WLONGVARCHAR) {
17564 if (!(s->nowchar[0] || s->nowchar[1])) {
17565 if (strcasecmp(tn, "varchar") == 0) {
17566 tn = "wvarchar";
17567 }
17568 }
17569 }
17570#endif
17571 if (valc && valMax > 0) {
17572 strncpy(valc, tn, valMax);
17573 valc[valMax - 1] = '\0';
17574 p = strchr(valc, '(');
17575 if (p) {
17576 *p = '\0';
17577 while (p > valc && ISSPACE(p[-1])) {
17578 --p;
17579 *p = '\0';
17580 }
17581 }
17582 *valLen = strlen(valc);
17583 } else {
17584 *valLen = strlen(tn);
17585 p = strchr(tn, '(');
17586 if (p) {
17587 *valLen = p - tn;
17588 while (p > tn && ISSPACE(p[-1])) {
17589 --p;
17590 *valLen -= 1;
17591 }
17592 }
17593 }
17594 goto checkLen;
17595 }
17596 case SQL_COLUMN_OWNER_NAME:
17597 case SQL_COLUMN_QUALIFIER_NAME: {
17598 char *z = "";
17599
17600 if (valc && valMax > 0) {
17601 strncpy(valc, z, valMax);
17602 valc[valMax - 1] = '\0';
17603 }
17604 *valLen = strlen(z);
17605 goto checkLen;
17606 }
17607 case SQL_COLUMN_TABLE_NAME:
17608#if (SQL_COLUMN_TABLE_NAME != SQL_DESC_TABLE_NAME)
17609 case SQL_DESC_TABLE_NAME:
17610#endif
17611#ifdef SQL_DESC_BASE_TABLE_NAME
17612 case SQL_DESC_BASE_TABLE_NAME:
17613#endif
17614 if (valc && valMax > 0) {
17615 strncpy(valc, c->table, valMax);
17616 valc[valMax - 1] = '\0';
17617 }
17618 *valLen = strlen(c->table);
17619 goto checkLen;
17620#ifdef SQL_DESC_NUM_PREC_RADIX
17621 case SQL_DESC_NUM_PREC_RADIX:
17622 if (val2) {
17623 switch (c->type) {
17624#ifdef WINTERFACE
17625 case SQL_WCHAR:
17626 case SQL_WVARCHAR:
17627#ifdef SQL_LONGVARCHAR
17628 case SQL_WLONGVARCHAR:
17629#endif
17630#endif
17631 case SQL_CHAR:
17632 case SQL_VARCHAR:
17633#ifdef SQL_LONGVARCHAR
17634 case SQL_LONGVARCHAR:
17635#endif
17636 case SQL_BINARY:
17637 case SQL_VARBINARY:
17638 case SQL_LONGVARBINARY:
17639 *val2 = 0;
17640 break;
17641 default:
17642 *val2 = 2;
17643 }
17644 }
17645 *valLen = sizeof (int);
17646 return SQL_SUCCESS;
17647#endif
17648 }
17649 setstat(s, -1, "unsupported column attributes %d", "HY091", id);
17650 return SQL_ERROR;
17651}
17652
17653#ifndef WINTERFACE
17666SQLRETURN SQL_API
17667SQLColAttributes(SQLHSTMT stmt, SQLUSMALLINT col, SQLUSMALLINT id,
17668 SQLPOINTER val, SQLSMALLINT valMax, SQLSMALLINT *valLen,
17669 SQLLEN *val2)
17670{
17671#if defined(_WIN32) || defined(_WIN64)
17672 SQLSMALLINT len = 0;
17673#endif
17674 SQLRETURN ret;
17675
17677#if defined(_WIN32) || defined(_WIN64)
17678 if (!((STMT *) stmt)->oemcp[0]) {
17679 ret = drvcolattributes(stmt, col, id, val, valMax, valLen, val2);
17680 goto done;
17681 }
17682 ret = drvcolattributes(stmt, col, id, val, valMax, &len, val2);
17683 if (SQL_SUCCEEDED(ret)) {
17684 char *v = NULL;
17685
17686 switch (id) {
17687 case SQL_COLUMN_LABEL:
17688 case SQL_COLUMN_NAME:
17689 case SQL_DESC_NAME:
17690 case SQL_COLUMN_TYPE_NAME:
17691 case SQL_COLUMN_OWNER_NAME:
17692 case SQL_COLUMN_QUALIFIER_NAME:
17693 case SQL_COLUMN_TABLE_NAME:
17694#if (SQL_COLUMN_TABLE_NAME != SQL_DESC_TABLE_NAME)
17695 case SQL_DESC_TABLE_NAME:
17696#endif
17697#ifdef SQL_DESC_BASE_COLUMN_NAME
17698 case SQL_DESC_BASE_COLUMN_NAME:
17699#endif
17700#ifdef SQL_DESC_BASE_TABLE_NAME
17701 case SQL_DESC_BASE_TABLE_NAME:
17702#endif
17703 if (val && valMax > 0) {
17704 int vmax = valMax;
17705
17706 v = utf_to_wmb((char *) val, SQL_NTS);
17707 if (v) {
17708 strncpy(val, v, vmax);
17709 len = min(vmax, strlen(v));
17710 uc_free(v);
17711 }
17712 if (vmax > 0) {
17713 v = (char *) val;
17714 v[vmax - 1] = '\0';
17715 }
17716 }
17717 if (len <= 0) {
17718 len = 0;
17719 }
17720 break;
17721 }
17722 if (valLen) {
17723 *valLen = len;
17724 }
17725 }
17726done:
17727 ;
17728#else
17729 ret = drvcolattributes(stmt, col, id, val, valMax, valLen, val2);
17730#endif
17732 return ret;
17733}
17734#endif
17735
17736#ifdef WINTERFACE
17749SQLRETURN SQL_API
17750SQLColAttributesW(SQLHSTMT stmt, SQLUSMALLINT col, SQLUSMALLINT id,
17751 SQLPOINTER val, SQLSMALLINT valMax, SQLSMALLINT *valLen,
17752 SQLLEN *val2)
17753{
17754 SQLRETURN ret;
17755 SQLSMALLINT len = 0;
17756
17758 ret = drvcolattributes(stmt, col, id, val, valMax, &len, val2);
17759 if (SQL_SUCCEEDED(ret)) {
17760 SQLWCHAR *v = NULL;
17761
17762 switch (id) {
17763 case SQL_COLUMN_LABEL:
17764 case SQL_COLUMN_NAME:
17765 case SQL_DESC_NAME:
17766 case SQL_COLUMN_TYPE_NAME:
17767 case SQL_COLUMN_OWNER_NAME:
17768 case SQL_COLUMN_QUALIFIER_NAME:
17769 case SQL_COLUMN_TABLE_NAME:
17770#if (SQL_COLUMN_TABLE_NAME != SQL_DESC_TABLE_NAME)
17771 case SQL_DESC_TABLE_NAME:
17772#endif
17773#ifdef SQL_DESC_BASE_COLUMN_NAME
17774 case SQL_DESC_BASE_COLUMN_NAME:
17775#endif
17776#ifdef SQL_DESC_BASE_TABLE_NAME
17777 case SQL_DESC_BASE_TABLE_NAME:
17778#endif
17779 if (val && valMax > 0) {
17780 int vmax = valMax / sizeof (SQLWCHAR);
17781
17782 v = uc_from_utf((SQLCHAR *) val, SQL_NTS);
17783 if (v) {
17784 uc_strncpy(val, v, vmax);
17785 len = min(vmax, uc_strlen(v));
17786 uc_free(v);
17787 len *= sizeof (SQLWCHAR);
17788 }
17789 if (vmax > 0) {
17790 v = (SQLWCHAR *) val;
17791 v[vmax - 1] = '\0';
17792 }
17793 }
17794 if (len <= 0) {
17795 len = 0;
17796 }
17797 break;
17798 }
17799 if (valLen) {
17800 *valLen = len;
17801 }
17802 }
17804 return ret;
17805}
17806#endif
17807
17820static SQLRETURN
17821drvcolattribute(SQLHSTMT stmt, SQLUSMALLINT col, SQLUSMALLINT id,
17822 SQLPOINTER val, SQLSMALLINT valMax, SQLSMALLINT *valLen,
17823 SQLPOINTER val2)
17824{
17825 STMT *s;
17826 COL *c;
17827 int v = 0;
17828 char *valc = (char *) val;
17829 SQLSMALLINT dummy;
17830
17831 if (stmt == SQL_NULL_HSTMT) {
17832 return SQL_INVALID_HANDLE;
17833 }
17834 s = (STMT *) stmt;
17835 if (!s->cols) {
17836 return SQL_ERROR;
17837 }
17838 if (col < 1 || col > s->ncols) {
17839 setstat(s, -1, "invalid column", (*s->ov3) ? "07009" : "S1002");
17840 return SQL_ERROR;
17841 }
17842 if (!valLen) {
17843 valLen = &dummy;
17844 }
17845 c = s->cols + col - 1;
17846 switch (id) {
17847 case SQL_DESC_COUNT:
17848 v = s->ncols;
17849 break;
17850 case SQL_DESC_CATALOG_NAME:
17851 if (valc && valMax > 0) {
17852 strncpy(valc, c->db, valMax);
17853 valc[valMax - 1] = '\0';
17854 }
17855 *valLen = strlen(c->db);
17856checkLen:
17857 if (*valLen >= valMax) {
17858 setstat(s, -1, "data right truncated", "01004");
17859 return SQL_SUCCESS_WITH_INFO;
17860 }
17861 break;
17862 case SQL_COLUMN_LENGTH:
17863 case SQL_DESC_LENGTH:
17864 v = c->size;
17865 break;
17866 case SQL_COLUMN_LABEL:
17867 if (c->label) {
17868 if (valc && valMax > 0) {
17869 strncpy(valc, c->label, valMax);
17870 valc[valMax - 1] = '\0';
17871 }
17872 *valLen = strlen(c->label);
17873 goto checkLen;
17874 }
17875 /* fall through */
17876 case SQL_COLUMN_NAME:
17877 case SQL_DESC_NAME:
17878 if (valc && valMax > 0) {
17879 strncpy(valc, c->column, valMax);
17880 valc[valMax - 1] = '\0';
17881 }
17882 *valLen = strlen(c->column);
17883 goto checkLen;
17884 case SQL_DESC_SCHEMA_NAME: {
17885 char *z = "";
17886
17887 if (valc && valMax > 0) {
17888 strncpy(valc, z, valMax);
17889 valc[valMax - 1] = '\0';
17890 }
17891 *valLen = strlen(z);
17892 goto checkLen;
17893 }
17894#ifdef SQL_DESC_BASE_COLUMN_NAME
17895 case SQL_DESC_BASE_COLUMN_NAME:
17896 if (strchr(c->column, '(') || strchr(c->column, ')')) {
17897 valc[0] = '\0';
17898 *valLen = 0;
17899 } else if (valc && valMax > 0) {
17900 strncpy(valc, c->column, valMax);
17901 valc[valMax - 1] = '\0';
17902 *valLen = strlen(c->column);
17903 }
17904 goto checkLen;
17905#endif
17906 case SQL_DESC_TYPE_NAME: {
17907 char *p = NULL, *tn = c->typename ? c->typename : "varchar";
17908
17909#ifdef WINTERFACE
17910 if (c->type == SQL_WCHAR ||
17911 c->type == SQL_WVARCHAR ||
17912 c->type == SQL_WLONGVARCHAR) {
17913 if (!(s->nowchar[0] || s->nowchar[1])) {
17914 if (strcasecmp(tn, "varchar") == 0) {
17915 tn = "wvarchar";
17916 }
17917 }
17918 }
17919#endif
17920 if (valc && valMax > 0) {
17921 strncpy(valc, tn, valMax);
17922 valc[valMax - 1] = '\0';
17923 p = strchr(valc, '(');
17924 if (p) {
17925 *p = '\0';
17926 while (p > valc && ISSPACE(p[-1])) {
17927 --p;
17928 *p = '\0';
17929 }
17930 }
17931 *valLen = strlen(valc);
17932 } else {
17933 *valLen = strlen(tn);
17934 p = strchr(tn, '(');
17935 if (p) {
17936 *valLen = p - tn;
17937 while (p > tn && ISSPACE(p[-1])) {
17938 --p;
17939 *valLen -= 1;
17940 }
17941 }
17942 }
17943 goto checkLen;
17944 }
17945 case SQL_DESC_OCTET_LENGTH:
17946 v = c->size;
17947#ifdef WINTERFACE
17948 if (c->type == SQL_WCHAR ||
17949 c->type == SQL_WVARCHAR ||
17950 c->type == SQL_WLONGVARCHAR) {
17951 if (!(s->nowchar[0] || s->nowchar[1])) {
17952 v *= sizeof (SQLWCHAR);
17953 }
17954 }
17955#endif
17956 break;
17957#if (SQL_COLUMN_TABLE_NAME != SQL_DESC_TABLE_NAME)
17958 case SQL_COLUMN_TABLE_NAME:
17959#endif
17960#ifdef SQL_DESC_BASE_TABLE_NAME
17961 case SQL_DESC_BASE_TABLE_NAME:
17962#endif
17963 case SQL_DESC_TABLE_NAME:
17964 if (valc && valMax > 0) {
17965 strncpy(valc, c->table, valMax);
17966 valc[valMax - 1] = '\0';
17967 }
17968 *valLen = strlen(c->table);
17969 goto checkLen;
17970 case SQL_DESC_TYPE:
17971 v = c->type;
17972#ifdef WINTERFACE
17973 if (s->nowchar[0] || s->nowchar[1]) {
17974 switch (v) {
17975 case SQL_WCHAR:
17976 v = SQL_CHAR;
17977 break;
17978 case SQL_WVARCHAR:
17979 v = SQL_VARCHAR;
17980 break;
17981#ifdef SQL_LONGVARCHAR
17982 case SQL_WLONGVARCHAR:
17983 v = SQL_LONGVARCHAR;
17984 break;
17985#endif
17986 }
17987 }
17988#endif
17989 break;
17990 case SQL_DESC_CONCISE_TYPE:
17991 switch (c->type) {
17992 case SQL_INTEGER:
17993 v = SQL_C_LONG;
17994 break;
17995 case SQL_TINYINT:
17996 v = SQL_C_TINYINT;
17997 break;
17998 case SQL_SMALLINT:
17999 v = SQL_C_SHORT;
18000 break;
18001 case SQL_FLOAT:
18002 v = SQL_C_FLOAT;
18003 break;
18004 case SQL_DOUBLE:
18005 v = SQL_C_DOUBLE;
18006 break;
18007 case SQL_TIMESTAMP:
18008 v = SQL_C_TIMESTAMP;
18009 break;
18010 case SQL_TIME:
18011 v = SQL_C_TIME;
18012 break;
18013 case SQL_DATE:
18014 v = SQL_C_DATE;
18015 break;
18016#ifdef SQL_C_TYPE_TIMESTAMP
18017 case SQL_TYPE_TIMESTAMP:
18018 v = SQL_C_TYPE_TIMESTAMP;
18019 break;
18020#endif
18021#ifdef SQL_C_TYPE_TIME
18022 case SQL_TYPE_TIME:
18023 v = SQL_C_TYPE_TIME;
18024 break;
18025#endif
18026#ifdef SQL_C_TYPE_DATE
18027 case SQL_TYPE_DATE:
18028 v = SQL_C_TYPE_DATE;
18029 break;
18030#endif
18031#ifdef SQL_BIT
18032 case SQL_BIT:
18033 v = SQL_C_BIT;
18034 break;
18035#endif
18036#ifdef SQL_BIGINT
18037 case SQL_BIGINT:
18038 v = SQL_C_SBIGINT;
18039 break;
18040#endif
18041 default:
18042#ifdef WINTERFACE
18043 v = (s->nowchar[0] || s->nowchar[1]) ? SQL_C_CHAR : SQL_C_WCHAR;
18044#else
18045 v = SQL_C_CHAR;
18046#endif
18047 break;
18048 }
18049 break;
18050 case SQL_DESC_UPDATABLE:
18051 v = SQL_TRUE;
18052 break;
18053 case SQL_COLUMN_DISPLAY_SIZE:
18054 v = c->size;
18055 break;
18056 case SQL_COLUMN_UNSIGNED:
18057 v = c->nosign ? SQL_TRUE : SQL_FALSE;
18058 break;
18059 case SQL_COLUMN_SEARCHABLE:
18060 v = SQL_SEARCHABLE;
18061 break;
18062 case SQL_COLUMN_SCALE:
18063 case SQL_DESC_SCALE:
18064 v = c->scale;
18065 break;
18066 case SQL_COLUMN_PRECISION:
18067 case SQL_DESC_PRECISION:
18068 switch (c->type) {
18069 case SQL_SMALLINT:
18070 v = 5;
18071 break;
18072 case SQL_INTEGER:
18073 v = 10;
18074 break;
18075 case SQL_FLOAT:
18076 case SQL_REAL:
18077 case SQL_DOUBLE:
18078 v = 15;
18079 break;
18080 case SQL_DATE:
18081 v = 0;
18082 break;
18083 case SQL_TIME:
18084 v = 0;
18085 break;
18086#ifdef SQL_TYPE_TIMESTAMP
18087 case SQL_TYPE_TIMESTAMP:
18088#endif
18089 case SQL_TIMESTAMP:
18090 v = (c->prec >= 0 && c->prec <= 3) ? c->prec : 3;
18091 break;
18092 default:
18093 v = c->prec;
18094 break;
18095 }
18096 break;
18097 case SQL_COLUMN_MONEY:
18098 v = SQL_FALSE;
18099 break;
18100 case SQL_COLUMN_AUTO_INCREMENT:
18101 v = c->autoinc;
18102 break;
18103 case SQL_DESC_NULLABLE:
18104 v = c->notnull;
18105 break;
18106#ifdef SQL_DESC_NUM_PREC_RADIX
18107 case SQL_DESC_NUM_PREC_RADIX:
18108 switch (c->type) {
18109#ifdef WINTERFACE
18110 case SQL_WCHAR:
18111 case SQL_WVARCHAR:
18112#ifdef SQL_LONGVARCHAR
18113 case SQL_WLONGVARCHAR:
18114#endif
18115#endif
18116 case SQL_CHAR:
18117 case SQL_VARCHAR:
18118#ifdef SQL_LONGVARCHAR
18119 case SQL_LONGVARCHAR:
18120#endif
18121 case SQL_BINARY:
18122 case SQL_VARBINARY:
18123 case SQL_LONGVARBINARY:
18124 v = 0;
18125 break;
18126 default:
18127 v = 2;
18128 }
18129 break;
18130#endif
18131 default:
18132 setstat(s, -1, "unsupported column attribute %d", "HY091", id);
18133 return SQL_ERROR;
18134 }
18135 if (val2) {
18136 *(SQLLEN *) val2 = v;
18137 }
18138 return SQL_SUCCESS;
18139}
18140
18141#ifndef WINTERFACE
18154SQLRETURN SQL_API
18155SQLColAttribute(SQLHSTMT stmt, SQLUSMALLINT col, SQLUSMALLINT id,
18156 SQLPOINTER val, SQLSMALLINT valMax, SQLSMALLINT *valLen,
18158{
18159#if defined(_WIN32) || defined(_WIN64)
18160 SQLSMALLINT len = 0;
18161#endif
18162 SQLRETURN ret;
18163
18165#if defined(_WIN32) || defined(_WIN64)
18166 if (!((STMT *) stmt)->oemcp[0]) {
18167 ret = drvcolattribute(stmt, col, id, val, valMax, valLen,
18168 (SQLPOINTER) val2);
18169 goto done;
18170 }
18171 ret = drvcolattribute(stmt, col, id, val, valMax, &len,
18172 (SQLPOINTER) val2);
18173 if (SQL_SUCCEEDED(ret)) {
18174 char *v = NULL;
18175
18176 switch (id) {
18177 case SQL_DESC_SCHEMA_NAME:
18178 case SQL_DESC_CATALOG_NAME:
18179 case SQL_COLUMN_LABEL:
18180 case SQL_DESC_NAME:
18181 case SQL_DESC_TABLE_NAME:
18182#ifdef SQL_DESC_BASE_TABLE_NAME
18183 case SQL_DESC_BASE_TABLE_NAME:
18184#endif
18185#ifdef SQL_DESC_BASE_COLUMN_NAME
18186 case SQL_DESC_BASE_COLUMN_NAME:
18187#endif
18188 case SQL_DESC_TYPE_NAME:
18189 if (val && valMax > 0) {
18190 int vmax = valMax;
18191
18192 v = utf_to_wmb((char *) val, SQL_NTS);
18193 if (v) {
18194 strncpy(val, v, vmax);
18195 len = min(vmax, strlen(v));
18196 uc_free(v);
18197 }
18198 if (vmax > 0) {
18199 v = (char *) val;
18200 v[vmax - 1] = '\0';
18201 }
18202 }
18203 if (len <= 0) {
18204 len = 0;
18205 }
18206 break;
18207 }
18208 if (valLen) {
18209 *valLen = len;
18210 }
18211 }
18212done:
18213 ;
18214#else
18215 ret = drvcolattribute(stmt, col, id, val, valMax, valLen,
18216 (SQLPOINTER) val2);
18217#endif
18219 return ret;
18220}
18221#endif
18222
18223#ifdef WINTERFACE
18236SQLRETURN SQL_API
18237SQLColAttributeW(SQLHSTMT stmt, SQLUSMALLINT col, SQLUSMALLINT id,
18238 SQLPOINTER val, SQLSMALLINT valMax, SQLSMALLINT *valLen,
18240{
18241 SQLRETURN ret;
18242 SQLSMALLINT len = 0;
18243
18245 ret = drvcolattribute(stmt, col, id, val, valMax, &len,
18246 (SQLPOINTER) val2);
18247 if (SQL_SUCCEEDED(ret)) {
18248 SQLWCHAR *v = NULL;
18249
18250 switch (id) {
18251 case SQL_DESC_SCHEMA_NAME:
18252 case SQL_DESC_CATALOG_NAME:
18253 case SQL_COLUMN_LABEL:
18254 case SQL_DESC_NAME:
18255 case SQL_DESC_TABLE_NAME:
18256#ifdef SQL_DESC_BASE_TABLE_NAME
18257 case SQL_DESC_BASE_TABLE_NAME:
18258#endif
18259#ifdef SQL_DESC_BASE_COLUMN_NAME
18260 case SQL_DESC_BASE_COLUMN_NAME:
18261#endif
18262 case SQL_DESC_TYPE_NAME:
18263 if (val && valMax > 0) {
18264 int vmax = valMax / sizeof (SQLWCHAR);
18265
18266 v = uc_from_utf((SQLCHAR *) val, SQL_NTS);
18267 if (v) {
18268 uc_strncpy(val, v, vmax);
18269 len = min(vmax, uc_strlen(v));
18270 uc_free(v);
18271 len *= sizeof (SQLWCHAR);
18272 }
18273 if (vmax > 0) {
18274 v = (SQLWCHAR *) val;
18275 v[vmax - 1] = '\0';
18276 }
18277 }
18278 if (len <= 0) {
18279 len = 0;
18280 }
18281 break;
18282 }
18283 if (valLen) {
18284 *valLen = len;
18285 }
18286 }
18288 return ret;
18289}
18290#endif
18291
18305static SQLRETURN
18306drverror(SQLHENV env, SQLHDBC dbc, SQLHSTMT stmt,
18307 SQLCHAR *sqlState, SQLINTEGER *nativeErr,
18308 SQLCHAR *errmsg, SQLSMALLINT errmax, SQLSMALLINT *errlen)
18309{
18310 SQLCHAR dummy0[6];
18311 SQLINTEGER dummy1;
18312 SQLSMALLINT dummy2;
18313
18314 if (env == SQL_NULL_HENV &&
18315 dbc == SQL_NULL_HDBC &&
18316 stmt == SQL_NULL_HSTMT) {
18317 return SQL_INVALID_HANDLE;
18318 }
18319 if (sqlState) {
18320 sqlState[0] = '\0';
18321 } else {
18322 sqlState = dummy0;
18323 }
18324 if (!nativeErr) {
18325 nativeErr = &dummy1;
18326 }
18327 *nativeErr = 0;
18328 if (!errlen) {
18329 errlen = &dummy2;
18330 }
18331 *errlen = 0;
18332 if (errmsg) {
18333 if (errmax > 0) {
18334 errmsg[0] = '\0';
18335 }
18336 } else {
18337 errmsg = dummy0;
18338 errmax = 0;
18339 }
18340 if (stmt) {
18341 STMT *s = (STMT *) stmt;
18342
18344 if (s->logmsg[0] == '\0') {
18346 goto noerr;
18347 }
18348 *nativeErr = s->naterr;
18349 strcpy((char *) sqlState, s->sqlstate);
18350 if (errmax == SQL_NTS) {
18351 strcpy((char *) errmsg, "[SQLite]");
18352 strcat((char *) errmsg, (char *) s->logmsg);
18353 *errlen = strlen((char *) errmsg);
18354 } else {
18355 strncpy((char *) errmsg, "[SQLite]", errmax);
18356 if (errmax - 8 > 0) {
18357 strncpy((char *) errmsg + 8, (char *) s->logmsg, errmax - 8);
18358 }
18359 *errlen = min(strlen((char *) s->logmsg) + 8, errmax);
18360 }
18361 s->logmsg[0] = '\0';
18363 return SQL_SUCCESS;
18364 }
18365 if (dbc) {
18366 DBC *d = (DBC *) dbc;
18367
18368 HDBC_LOCK(dbc);
18369 if (d->magic != DBC_MAGIC || d->logmsg[0] == '\0') {
18371 goto noerr;
18372 }
18373 *nativeErr = d->naterr;
18374 strcpy((char *) sqlState, d->sqlstate);
18375 if (errmax == SQL_NTS) {
18376 strcpy((char *) errmsg, "[SQLite]");
18377 strcat((char *) errmsg, (char *) d->logmsg);
18378 *errlen = strlen((char *) errmsg);
18379 } else {
18380 strncpy((char *) errmsg, "[SQLite]", errmax);
18381 if (errmax - 8 > 0) {
18382 strncpy((char *) errmsg + 8, (char *) d->logmsg, errmax - 8);
18383 }
18384 *errlen = min(strlen((char *) d->logmsg) + 8, errmax);
18385 }
18386 d->logmsg[0] = '\0';
18388 return SQL_SUCCESS;
18389 }
18390noerr:
18391 sqlState[0] = '\0';
18392 errmsg[0] = '\0';
18393 *nativeErr = 0;
18394 *errlen = 0;
18395 return SQL_NO_DATA;
18396}
18397
18398#ifndef WINTERFACE
18412SQLRETURN SQL_API
18413SQLError(SQLHENV env, SQLHDBC dbc, SQLHSTMT stmt,
18414 SQLCHAR *sqlState, SQLINTEGER *nativeErr,
18415 SQLCHAR *errmsg, SQLSMALLINT errmax, SQLSMALLINT *errlen)
18416{
18417 return drverror(env, dbc, stmt, sqlState, nativeErr,
18418 errmsg, errmax, errlen);
18419}
18420#endif
18421
18422#ifdef WINTERFACE
18436SQLRETURN SQL_API
18437SQLErrorW(SQLHENV env, SQLHDBC dbc, SQLHSTMT stmt,
18438 SQLWCHAR *sqlState, SQLINTEGER *nativeErr,
18439 SQLWCHAR *errmsg, SQLSMALLINT errmax, SQLSMALLINT *errlen)
18440{
18441 char state[16];
18442 SQLSMALLINT len = 0;
18443 SQLRETURN ret;
18444
18445 ret = drverror(env, dbc, stmt, (SQLCHAR *) state, nativeErr,
18446 (SQLCHAR *) errmsg, errmax, &len);
18447 if (ret == SQL_SUCCESS) {
18448 if (sqlState) {
18449 uc_from_utf_buf((SQLCHAR *) state, -1, sqlState,
18450 6 * sizeof (SQLWCHAR));
18451 }
18452 if (errmsg) {
18453 if (len > 0) {
18454 SQLWCHAR *e = NULL;
18455
18456 e = uc_from_utf((SQLCHAR *) errmsg, len);
18457 if (e) {
18458 if (errmax > 0) {
18459 uc_strncpy(errmsg, e, errmax);
18460 e[len] = 0;
18461 len = min(errmax, uc_strlen(e));
18462 } else {
18463 len = uc_strlen(e);
18464 }
18465 uc_free(e);
18466 } else {
18467 len = 0;
18468 }
18469 }
18470 if (len <= 0) {
18471 len = 0;
18472 if (errmax > 0) {
18473 errmsg[0] = 0;
18474 }
18475 }
18476 } else {
18477 len = 0;
18478 }
18479 if (errlen) {
18480 *errlen = len;
18481 }
18482 } else if (ret == SQL_NO_DATA) {
18483 if (sqlState) {
18484 sqlState[0] = 0;
18485 }
18486 if (errmsg) {
18487 if (errmax > 0) {
18488 errmsg[0] = 0;
18489 }
18490 }
18491 if (errlen) {
18492 *errlen = 0;
18493 }
18494 }
18495 return ret;
18496}
18497#endif
18498
18505SQLRETURN SQL_API
18506SQLMoreResults(SQLHSTMT stmt)
18507{
18509 if (stmt == SQL_NULL_HSTMT) {
18510 return SQL_INVALID_HANDLE;
18511 }
18513 return SQL_NO_DATA;
18514}
18515
18524static SQLRETURN
18525setupdyncols(STMT *s, sqlite3_stmt *s3stmt, int *ncolsp)
18526{
18527 int ncols = *ncolsp, guessed_types = 0;
18528 SQLRETURN ret = SQL_SUCCESS;
18529
18530 if (ncols > 0) {
18531 int i;
18532 PTRDIFF_T size;
18533 char *p;
18534 COL *dyncols;
18535 DBC *d = (DBC *) s->dbc;
18536 const char *colname, *typename;
18537#if defined(HAVE_SQLITE3COLUMNTABLENAME) && (HAVE_SQLITE3COLUMNTABLENAME)
18538 char *tblname;
18539#endif
18540#if defined(HAVE_SQLITE3COLUMNDATABASENAME) && (HAVE_SQLITE3COLUMNDATABASENAME)
18541 char *dbname;
18542#endif
18543
18544 for (i = size = 0; i < ncols; i++) {
18545 colname = sqlite3_column_name(s3stmt, i);
18546 size += 3 + 3 * strlen(colname);
18547 }
18548#if defined(HAVE_SQLITE3COLUMNTABLENAME) && (HAVE_SQLITE3COLUMNTABLENAME)
18549 tblname = (char *) size;
18550 for (i = 0; i < ncols; i++) {
18551 p = (char *) sqlite3_column_table_name(s3stmt, i);
18552 size += 2 + (p ? strlen(p) : 0);
18553 }
18554#endif
18555#if defined(HAVE_SQLITE3COLUMNDATABASENAME) && (HAVE_SQLITE3COLUMNDATABASENAME)
18556 dbname = (char *) size;
18557 for (i = 0; i < ncols; i++) {
18558 p = (char *) sqlite3_column_database_name(s3stmt, i);
18559 size += 2 + (p ? strlen(p) : 0);
18560 }
18561#endif
18562 dyncols = xmalloc(ncols * sizeof (COL) + size);
18563 if (!dyncols) {
18564 freedyncols(s);
18565 *ncolsp = 0;
18566 ret = SQL_ERROR;
18567 } else {
18568 p = (char *) (dyncols + ncols);
18569#if defined(HAVE_SQLITE3COLUMNTABLENAME) && (HAVE_SQLITE3COLUMNTABLENAME)
18570 tblname = p + (PTRDIFF_T) tblname;
18571#endif
18572#if defined(HAVE_SQLITE3COLUMNDATABASENAME) && (HAVE_SQLITE3COLUMNDATABASENAME)
18573 dbname = p + (PTRDIFF_T) dbname;
18574#endif
18575 for (i = 0; i < ncols; i++) {
18576 char *q;
18577
18578 colname = sqlite3_column_name(s3stmt, i);
18579 if (d->trace) {
18580 fprintf(d->trace, "-- column %d name: '%s'\n",
18581 i + 1, colname);
18582 fflush(d->trace);
18583 }
18584#if defined(HAVE_SQLITE3COLUMNTABLENAME) && (HAVE_SQLITE3COLUMNTABLENAME)
18585 q = (char *) sqlite3_column_table_name(s3stmt, i);
18586 strcpy(tblname, q ? q : "");
18587 if (d->trace) {
18588 fprintf(d->trace, "-- table %d name: '%s'\n",
18589 i + 1, tblname);
18590 fflush(d->trace);
18591 }
18592 dyncols[i].table = tblname;
18593 tblname += strlen(tblname) + 1;
18594#endif
18595#if defined(HAVE_SQLITE3COLUMNDATABASENAME) && (HAVE_SQLITE3COLUMNDATABASENAME)
18596 q = (char *) sqlite3_column_database_name(s3stmt, i);
18597 strcpy(dbname, q ? q : "");
18598 if (d->trace) {
18599 fprintf(d->trace, "-- database %d name: '%s'\n",
18600 i + 1, dbname);
18601 fflush(d->trace);
18602 }
18603 dyncols[i].db = dbname;
18604 dbname += strlen(dbname) + 1;
18605#else
18606 dyncols[i].db = ((DBC *) (s->dbc))->dbname;
18607#endif
18608 typename = s3stmt_coltype(s3stmt, i, d, &guessed_types);
18609 strcpy(p, colname);
18610 dyncols[i].label = p;
18611 p += strlen(p) + 1;
18612 q = strchr(colname, '.');
18613 if (q) {
18614 char *q2 = strchr(q + 1, '.');
18615
18616 /* SQLite 3.3.4 produces view.table.column sometimes */
18617 if (q2) {
18618 q = q2;
18619 }
18620 }
18621 if (q) {
18622#if !defined(HAVE_SQLITE3COLUMNTABLENAME) || !(HAVE_SQLITE3COLUMNTABLENAME)
18623 dyncols[i].table = p;
18624#endif
18625 strncpy(p, colname, q - colname);
18626 p[q - colname] = '\0';
18627 p += strlen(p) + 1;
18628 strcpy(p, q + 1);
18629 dyncols[i].column = p;
18630 p += strlen(p) + 1;
18631 } else {
18632#if !defined(HAVE_SQLITE3COLUMNTABLENAME) || !(HAVE_SQLITE3COLUMNTABLENAME)
18633 dyncols[i].table = "";
18634#endif
18635 strcpy(p, colname);
18636 dyncols[i].column = p;
18637 p += strlen(p) + 1;
18638 }
18639 if (s->longnames) {
18640 dyncols[i].column = dyncols[i].label;
18641 }
18642#ifdef SQL_LONGVARCHAR
18643 dyncols[i].type = SQL_LONGVARCHAR;
18644 dyncols[i].size = 65535;
18645#else
18646 dyncols[i].type = SQL_VARCHAR;
18647 dyncols[i].size = 255;
18648#endif
18649 dyncols[i].index = i;
18650 dyncols[i].scale = 0;
18651 dyncols[i].prec = 0;
18652 dyncols[i].nosign = 1;
18653 dyncols[i].autoinc = SQL_FALSE;
18654 dyncols[i].notnull = SQL_NULLABLE;
18655 dyncols[i].ispk = -1;
18656 dyncols[i].isrowid = -1;
18657#ifdef FULL_METADATA
18658 s3stmt_addmeta(s3stmt, i, d, &dyncols[i]);
18659#endif
18660 dyncols[i].typename = xstrdup(typename);
18661 }
18662 freedyncols(s);
18663 s->dyncols = s->cols = dyncols;
18664 s->dcols = ncols;
18665 fixupdyncols(s, d);
18666 s->guessed_types = guessed_types;
18667 }
18668 }
18669 return ret;
18670}
18671
18680static SQLRETURN
18681drvprepare(SQLHSTMT stmt, SQLCHAR *query, SQLINTEGER queryLen)
18682{
18683 STMT *s;
18684 DBC *d;
18685 char *errp = NULL;
18686 SQLRETURN sret;
18687
18688 if (stmt == SQL_NULL_HSTMT) {
18689 return SQL_INVALID_HANDLE;
18690 }
18691 s = (STMT *) stmt;
18692 if (s->dbc == SQL_NULL_HDBC) {
18693noconn:
18694 return noconn(s);
18695 }
18696 d = s->dbc;
18697 if (!d->sqlite) {
18698 goto noconn;
18699 }
18700 s3stmt_end(s);
18701 s3stmt_drop(s);
18702 sret = starttran(s);
18703 if (sret != SQL_SUCCESS) {
18704 return sret;
18705 }
18706 freep(&s->query);
18707 s->query = (SQLCHAR *) fixupsql((char *) query, queryLen,
18708 (d->version >= 0x030805),
18709 &s->nparams, &s->isselect, &errp);
18710 if (!s->query) {
18711 if (errp) {
18712 setstat(s, -1, "%s", (*s->ov3) ? "HY000" : "S1000", errp);
18713 return SQL_ERROR;
18714 }
18715 return nomem(s);
18716 }
18717 if (*s->ilike) {
18718 replilike((char *) s->query);
18719 }
18720 errp = NULL;
18721 freeresult(s, -1);
18722 if (s->isselect == 1) {
18723 int ret, ncols, nretry = 0;
18724 const char *rest;
18725 sqlite3_stmt *s3stmt = NULL;
18726
18727#if defined(HAVE_SQLITE3PREPAREV2) && (HAVE_SQLITE3PREPAREV2)
18728 dbtraceapi(d, "sqlite3_prepare_v2", (char *) s->query);
18729#else
18730 dbtraceapi(d, "sqlite3_prepare", (char *) s->query);
18731#endif
18732 do {
18733 s3stmt = NULL;
18734#if defined(HAVE_SQLITE3PREPAREV2) && (HAVE_SQLITE3PREPAREV2)
18735 ret = sqlite3_prepare_v2(d->sqlite, (char *) s->query, -1,
18736 &s3stmt, &rest);
18737#else
18738 ret = sqlite3_prepare(d->sqlite, (char *) s->query, -1,
18739 &s3stmt, &rest);
18740#endif
18741 if (ret != SQLITE_OK) {
18742 if (s3stmt) {
18743 sqlite3_finalize(s3stmt);
18744 s3stmt = NULL;
18745 }
18746 }
18747 } while (ret == SQLITE_SCHEMA && (++nretry) < 2);
18748 dbtracerc(d, ret, NULL);
18749 if (ret != SQLITE_OK) {
18750 if (s3stmt) {
18751 dbtraceapi(d, "sqlite3_finalize", 0);
18752 sqlite3_finalize(s3stmt);
18753 }
18754 setstat(s, ret, "%s (%d)", (*s->ov3) ? "HY000" : "S1000",
18755 sqlite3_errmsg(d->sqlite), ret);
18756 return SQL_ERROR;
18757 }
18758 if (sqlite3_bind_parameter_count(s3stmt) != s->nparams) {
18759 dbtraceapi(d, "sqlite3_finalize", 0);
18760 sqlite3_finalize(s3stmt);
18761 setstat(s, SQLITE_ERROR, "parameter marker count incorrect",
18762 (*s->ov3) ? "HY000" : "S1000");
18763 return SQL_ERROR;
18764 }
18765 ncols = sqlite3_column_count(s3stmt);
18766 s->guessed_types = 0;
18767 setupdyncols(s, s3stmt, &ncols);
18768 s->ncols = ncols;
18769 s->s3stmt = s3stmt;
18770 } else {
18771 s->guessed_types = 1;
18772 }
18773 mkbindcols(s, s->ncols);
18774 s->paramset_count = 0;
18775 return SQL_SUCCESS;
18776}
18777
18785static SQLRETURN
18786drvexecute(SQLHSTMT stmt, int initial)
18787{
18788 STMT *s;
18789 DBC *d;
18790 char *errp = NULL;
18791 int rc, i, ncols = 0, nrows = 0, busy_count;
18792 SQLRETURN ret;
18793
18794 if (stmt == SQL_NULL_HSTMT) {
18795 return SQL_INVALID_HANDLE;
18796 }
18797 s = (STMT *) stmt;
18798 if (s->dbc == SQL_NULL_HDBC) {
18799noconn:
18800 return noconn(s);
18801 }
18802 d = (DBC *) s->dbc;
18803 if (!d->sqlite) {
18804 goto noconn;
18805 }
18806 if (!s->query) {
18807 setstat(s, -1, "no query prepared", (*s->ov3) ? "HY000" : "S1000");
18808 return SQL_ERROR;
18809 }
18810 if (s->nbindparms < s->nparams) {
18811unbound:
18812 setstat(s, -1, "unbound parameters in query",
18813 (*s->ov3) ? "HY000" : "S1000");
18814 return SQL_ERROR;
18815 }
18816 for (i = 0; i < s->nparams; i++) {
18817 BINDPARM *p = &s->bindparms[i];
18818
18819 if (!p->bound) {
18820 goto unbound;
18821 }
18822 if (initial) {
18823 SQLLEN *lenp = p->lenp;
18824
18825 if (lenp && *lenp < 0 && *lenp > SQL_LEN_DATA_AT_EXEC_OFFSET &&
18826 *lenp != SQL_NTS && *lenp != SQL_NULL_DATA &&
18827 *lenp != SQL_DATA_AT_EXEC) {
18828 setstat(s, -1, "invalid length reference", "HY009");
18829 return SQL_ERROR;
18830 }
18831 if (lenp && (*lenp <= SQL_LEN_DATA_AT_EXEC_OFFSET ||
18832 *lenp == SQL_DATA_AT_EXEC)) {
18833 p->need = 1;
18834 p->offs = 0;
18835 p->len = 0;
18836 }
18837 }
18838 }
18839 ret = starttran(s);
18840 if (ret != SQL_SUCCESS) {
18841 goto cleanup;
18842 }
18843 busy_count = 0;
18844again:
18845 s3stmt_end(s);
18846 if (initial) {
18847 /* fixup data-at-execution parameters and alloc'ed blobs */
18848 s->pdcount = -1;
18849 for (i = 0; i < s->nparams; i++) {
18850 BINDPARM *p = &s->bindparms[i];
18851
18852 if (p->param == p->parbuf) {
18853 p->param = NULL;
18854 }
18855 freep(&p->parbuf);
18856 if (p->need <= 0 &&
18857 p->lenp && (*p->lenp <= SQL_LEN_DATA_AT_EXEC_OFFSET ||
18858 *p->lenp == SQL_DATA_AT_EXEC)) {
18859 p->need = 1;
18860 p->offs = 0;
18861 p->len = 0;
18862 }
18863 }
18864 }
18865 if (s->nparams) {
18866 for (i = 0; i < s->nparams; i++) {
18867 ret = setupparam(s, (char *) s->query, i);
18868 if (ret != SQL_SUCCESS) {
18869 goto cleanup;
18870 }
18871 }
18872 }
18873 freeresult(s, 0);
18874 if (s->isselect == 1 && !d->intrans &&
18875 s->curtype == SQL_CURSOR_FORWARD_ONLY &&
18876 d->step_enable && s->nparams == 0 && d->cur_s3stmt == NULL) {
18877 s->nrows = -1;
18878 ret = s3stmt_start(s);
18879 if (ret == SQL_SUCCESS) {
18880 goto done2;
18881 }
18882 }
18883 rc = drvgettable(s, s->s3stmt ? NULL : (char *) s->query, &s->rows,
18884 &s->nrows, &ncols, &errp, s->nparams, s->bindparms);
18885 dbtracerc(d, rc, errp);
18886 if (rc == SQLITE_BUSY) {
18887 if (busy_handler((void *) d, ++busy_count)) {
18888 if (errp) {
18889 sqlite3_free(errp);
18890 errp = NULL;
18891 }
18892 for (i = 0; i < s->nparams; i++) {
18893 BINDPARM *p = &s->bindparms[i];
18894
18895 if (p->param == p->parbuf) {
18896 p->param = NULL;
18897 }
18898 freep(&p->parbuf);
18899 if (!p->lenp || (*p->lenp > SQL_LEN_DATA_AT_EXEC_OFFSET &&
18900 *p->lenp != SQL_DATA_AT_EXEC)) {
18901 p->param = p->param0;
18902 }
18903 p->lenp = p->lenp0;
18904 }
18905 s->nrows = 0;
18906 goto again;
18907 }
18908 }
18909 if (rc != SQLITE_OK) {
18910 setstat(s, rc, "%s (%d)", (*s->ov3) ? "HY000" : "S1000",
18911 errp ? errp : "unknown error", rc);
18912 if (errp) {
18913 sqlite3_free(errp);
18914 errp = NULL;
18915 }
18916 ret = SQL_ERROR;
18917 goto cleanup;
18918 }
18919 if (errp) {
18920 sqlite3_free(errp);
18921 errp = NULL;
18922 }
18923 s->rowfree = freerows;
18924 if (s->isselect <= 0 || s->isselect > 1) {
18925 /*
18926 * DDL results are immediately released.
18927 * INSERT/UPDATE/DELETE depends on number of columns in
18928 * result set, if zero, result is immediately released.
18929 */
18930 if (s->isselect != 0 || ncols == 0) {
18931 freeresult(s, -1);
18932 nrows += sqlite3_changes(d->sqlite);
18933 s->nrows = nrows;
18934 } else {
18935 s->ncols = ncols;
18936 }
18937 goto done;
18938 }
18939 if (s->ncols != ncols) {
18940 /*
18941 * Weird result.
18942 */
18943 setstat(s, -1, "broken result set %d/%d",
18944 (*s->ov3) ? "HY000" : "S1000", s->ncols, ncols);
18945 ret = SQL_ERROR;
18946 goto cleanup;
18947 }
18948done:
18949 mkbindcols(s, s->ncols);
18950done2:
18951 ret = SQL_SUCCESS;
18952 s->rowp = s->rowprs = -1;
18953 s->paramset_count++;
18954 s->paramset_nrows = s->nrows;
18955 if (s->paramset_count < s->paramset_size) {
18956 for (i = 0; i < s->nparams; i++) {
18957 BINDPARM *p = &s->bindparms[i];
18958
18959 if (p->param == p->parbuf) {
18960 p->param = NULL;
18961 }
18962 freep(&p->parbuf);
18963 if (p->lenp0 &&
18964 s->parm_bind_type != SQL_PARAM_BIND_BY_COLUMN) {
18965 p->lenp = (SQLLEN *) ((char *) p->lenp0 +
18967 } else if (p->lenp0 && p->inc > 0) {
18968 p->lenp = p->lenp0 + s->paramset_count;
18969 }
18970 if (!p->lenp || (*p->lenp > SQL_LEN_DATA_AT_EXEC_OFFSET &&
18971 *p->lenp != SQL_DATA_AT_EXEC)) {
18972 if (p->param0 &&
18973 s->parm_bind_type != SQL_PARAM_BIND_BY_COLUMN) {
18974 p->param = (char *) p->param0 +
18976 } else if (p->param0 && p->inc > 0) {
18977 p->param = (char *) p->param0 +
18978 s->paramset_count * p->inc;
18979 }
18980 } else if (p->lenp && (*p->lenp <= SQL_LEN_DATA_AT_EXEC_OFFSET ||
18981 *p->lenp == SQL_DATA_AT_EXEC)) {
18982 p->need = 1;
18983 p->offs = 0;
18984 p->len = 0;
18985 }
18986 }
18987 goto again;
18988 }
18989cleanup:
18990 if (ret != SQL_NEED_DATA) {
18991 for (i = 0; i < s->nparams; i++) {
18992 BINDPARM *p = &s->bindparms[i];
18993
18994 if (p->param == p->parbuf) {
18995 p->param = NULL;
18996 }
18997 freep(&p->parbuf);
18998 if (!p->lenp || (*p->lenp > SQL_LEN_DATA_AT_EXEC_OFFSET &&
18999 *p->lenp != SQL_DATA_AT_EXEC)) {
19000 p->param = p->param0;
19001 }
19002 p->lenp = p->lenp0;
19003 }
19004 s->nrows = s->paramset_nrows;
19005 if (s->parm_proc) {
19006 *s->parm_proc = s->paramset_count;
19007 }
19008 s->paramset_count = 0;
19009 s->paramset_nrows = 0;
19010 }
19011 /*
19012 * For INSERT/UPDATE/DELETE statements change the return code
19013 * to SQL_NO_DATA if the number of rows affected was 0.
19014 */
19015 if (*s->ov3 && s->isselect == 0 &&
19016 ret == SQL_SUCCESS && nrows == 0) {
19017 ret = SQL_NO_DATA;
19018 }
19019 return ret;
19020}
19021
19022#ifndef WINTERFACE
19031SQLRETURN SQL_API
19032SQLPrepare(SQLHSTMT stmt, SQLCHAR *query, SQLINTEGER queryLen)
19033{
19034 SQLRETURN ret;
19035#if defined(_WIN32) || defined(_WIN64)
19036 char *q;
19037#endif
19038
19040#if defined(_WIN32) || defined(_WIN64)
19041 if (!((STMT *) stmt)->oemcp[0]) {
19042 ret = drvprepare(stmt, query, queryLen);
19043 goto done;
19044 }
19045 q = wmb_to_utf_c((char *) query, queryLen);
19046 if (!q) {
19047 ret = nomem((STMT *) stmt);
19048 goto done;
19049 }
19050 query = (SQLCHAR *) q;
19051 queryLen = SQL_NTS;
19052#endif
19053 ret = drvprepare(stmt, query, queryLen);
19054#if defined(_WIN32) || defined(_WIN64)
19055 uc_free(q);
19056done:
19057 ;
19058#endif
19060 return ret;
19061}
19062#endif
19063
19064#ifdef WINTERFACE
19073SQLRETURN SQL_API
19074SQLPrepareW(SQLHSTMT stmt, SQLWCHAR *query, SQLINTEGER queryLen)
19075{
19076 SQLRETURN ret;
19077 char *q = uc_to_utf_c(query, queryLen);
19078
19080 if (!q) {
19081 ret = nomem((STMT *) stmt);
19082 goto done;
19083 }
19084 ret = drvprepare(stmt, (SQLCHAR *) q, SQL_NTS);
19085 uc_free(q);
19086done:
19088 return ret;
19089}
19090#endif
19091
19098SQLRETURN SQL_API
19099SQLExecute(SQLHSTMT stmt)
19100{
19101 SQLRETURN ret;
19102
19104 ret = drvexecute(stmt, 1);
19106 return ret;
19107}
19108
19109#ifndef WINTERFACE
19118SQLRETURN SQL_API
19119SQLExecDirect(SQLHSTMT stmt, SQLCHAR *query, SQLINTEGER queryLen)
19120{
19121 SQLRETURN ret;
19122#if defined(_WIN32) || defined(_WIN64)
19123 char *q;
19124#endif
19125
19127#if defined(_WIN32) || defined(_WIN64)
19128 if (!((STMT *) stmt)->oemcp[0]) {
19129 ret = drvprepare(stmt, query, queryLen);
19130 if (ret == SQL_SUCCESS) {
19131 ret = drvexecute(stmt, 1);
19132 }
19133 goto done;
19134 }
19135 q = wmb_to_utf_c((char *) query, queryLen);
19136 if (!q) {
19137 ret = nomem((STMT *) stmt);
19138 goto done;
19139 }
19140 query = (SQLCHAR *) q;
19141 queryLen = SQL_NTS;
19142#endif
19143 ret = drvprepare(stmt, query, queryLen);
19144 if (ret == SQL_SUCCESS) {
19145 ret = drvexecute(stmt, 1);
19146 }
19147#if defined(_WIN32) || defined(_WIN64)
19148 uc_free(q);
19149done:
19150 ;
19151#endif
19153 return ret;
19154}
19155#endif
19156
19157#ifdef WINTERFACE
19166SQLRETURN SQL_API
19167SQLExecDirectW(SQLHSTMT stmt, SQLWCHAR *query, SQLINTEGER queryLen)
19168{
19169 SQLRETURN ret;
19170 char *q = uc_to_utf_c(query, queryLen);
19171
19173 if (!q) {
19174 ret = nomem((STMT *) stmt);
19175 goto done;
19176 }
19177 ret = drvprepare(stmt, (SQLCHAR *) q, SQL_NTS);
19178 uc_free(q);
19179 if (ret == SQL_SUCCESS) {
19180 ret = drvexecute(stmt, 1);
19181 }
19182done:
19184 return ret;
19185}
19186#endif
19187
19188
19189#if defined(_WIN32) || defined(_WIN64)
19190#ifndef WITHOUT_DRIVERMGR
19191
19192/*
19193 * Windows configuration dialog stuff.
19194 */
19195
19196#include <windowsx.h>
19197#include <winuser.h>
19198
19199#define MAXPATHLEN (259+1) /* Max path length */
19200#define MAXKEYLEN (15+1) /* Max keyword length */
19201#define MAXDESC (255+1) /* Max description length */
19202#define MAXDSNAME (255+1) /* Max data source name length */
19203#define MAXTONAME (32+1) /* Max timeout length */
19204#define MAXDBNAME MAXPATHLEN
19205
19206/* Attribute key indexes into an array of Attr structs, see below */
19207
19208#define KEY_DSN 0
19209#define KEY_DESC 1
19210#define KEY_DBNAME 2
19211#define KEY_BUSY 3
19212#define KEY_DRIVER 4
19213#define KEY_STEPAPI 5
19214#define KEY_SYNCP 6
19215#define KEY_NOTXN 7
19216#define KEY_SHORTNAM 8
19217#define KEY_LONGNAM 9
19218#define KEY_NOCREAT 10
19219#define KEY_NOWCHAR 11
19220#define KEY_LOADEXT 12
19221#define KEY_JMODE 13
19222#define KEY_FKSUPPORT 14
19223#define KEY_OEMCP 15
19224#define KEY_BIGINT 16
19225#define KEY_PASSWD 17
19226#define KEY_JDCONV 18
19227#define KEY_ATTAS 19
19228#define KEY_ILIKE 20
19229#define NUMOFKEYS 21
19230
19231typedef struct {
19232 BOOL supplied;
19233 char attr[MAXPATHLEN*4];
19234} ATTR;
19235
19236typedef struct {
19237 SQLHWND parent;
19238 LPCSTR driver;
19239 ATTR attr[NUMOFKEYS];
19240 char DSN[MAXDSNAME];
19241 BOOL newDSN;
19242 BOOL defDSN;
19243} SETUPDLG;
19244
19245static struct {
19246 char *key;
19247 int ikey;
19248} attrLookup[] = {
19249 { "DSN", KEY_DSN },
19250 { "DESC", KEY_DESC },
19251 { "Description", KEY_DESC},
19252 { "Database", KEY_DBNAME },
19253 { "Timeout", KEY_BUSY },
19254 { "Driver", KEY_DRIVER },
19255 { "StepAPI", KEY_STEPAPI },
19256 { "SyncPragma", KEY_SYNCP },
19257 { "NoTXN", KEY_NOTXN },
19258 { "ShortNames", KEY_SHORTNAM },
19259 { "LongNames", KEY_LONGNAM },
19260 { "NoCreat", KEY_NOCREAT },
19261 { "NoWCHAR", KEY_NOWCHAR },
19262 { "LoadExt", KEY_LOADEXT },
19263 { "JournalMode", KEY_JMODE },
19264 { "FKSupport", KEY_FKSUPPORT },
19265 { "OEMCP", KEY_OEMCP },
19266 { "BigInt", KEY_BIGINT },
19267 { "PWD", KEY_PASSWD },
19268 { "JDConv", KEY_JDCONV },
19269 { "AttachAs", KEY_ATTAS },
19270 { "ILike", KEY_ILIKE },
19271 { NULL, 0 }
19272};
19273
19280static void
19281ParseAttributes(LPCSTR attribs, SETUPDLG *setupdlg)
19282{
19283 char *str = (char *) attribs, *start, key[MAXKEYLEN];
19284 int elem, nkey;
19285
19286 while (*str) {
19287 start = str;
19288 if ((str = strchr(str, '=')) == NULL) {
19289 return;
19290 }
19291 elem = -1;
19292 nkey = str - start;
19293 if (nkey < sizeof (key)) {
19294 int i;
19295
19296 memcpy(key, start, nkey);
19297 key[nkey] = '\0';
19298 for (i = 0; attrLookup[i].key; i++) {
19299 if (strcasecmp(attrLookup[i].key, key) == 0) {
19300 elem = attrLookup[i].ikey;
19301 break;
19302 }
19303 }
19304 }
19305 start = ++str;
19306 while (*str && *str != ';') {
19307 ++str;
19308 }
19309 if (elem >= 0) {
19310 int end = min(str - start, sizeof (setupdlg->attr[elem].attr) - 1);
19311
19312 setupdlg->attr[elem].supplied = TRUE;
19313 memcpy(setupdlg->attr[elem].attr, start, end);
19314 setupdlg->attr[elem].attr[end] = '\0';
19315 }
19316 ++str;
19317 }
19318}
19319
19327static BOOL
19328SetDSNAttributes(HWND parent, SETUPDLG *setupdlg)
19329{
19330 char *dsn = setupdlg->attr[KEY_DSN].attr;
19331
19332 if (setupdlg->newDSN && strlen(dsn) == 0) {
19333 return FALSE;
19334 }
19335 if (!SQLWriteDSNToIni(dsn, setupdlg->driver)) {
19336 if (parent) {
19337 char buf[MAXPATHLEN], msg[MAXPATHLEN];
19338
19339 LoadString(hModule, IDS_BADDSN, buf, sizeof (buf));
19340 wsprintf(msg, buf, dsn);
19341 LoadString(hModule, IDS_MSGTITLE, buf, sizeof (buf));
19342 MessageBox(parent, msg, buf,
19343 MB_ICONEXCLAMATION | MB_OK | MB_TASKMODAL |
19344 MB_SETFOREGROUND);
19345 }
19346 return FALSE;
19347 }
19348 if (parent || setupdlg->attr[KEY_DESC].supplied) {
19349 SQLWritePrivateProfileString(dsn, "Description",
19350 setupdlg->attr[KEY_DESC].attr,
19351 ODBC_INI);
19352 }
19353 if (parent || setupdlg->attr[KEY_DBNAME].supplied) {
19354 SQLWritePrivateProfileString(dsn, "Database",
19355 setupdlg->attr[KEY_DBNAME].attr,
19356 ODBC_INI);
19357 }
19358 if (parent || setupdlg->attr[KEY_BUSY].supplied) {
19359 SQLWritePrivateProfileString(dsn, "Timeout",
19360 setupdlg->attr[KEY_BUSY].attr,
19361 ODBC_INI);
19362 }
19363 if (parent || setupdlg->attr[KEY_STEPAPI].supplied) {
19364 SQLWritePrivateProfileString(dsn, "StepAPI",
19365 setupdlg->attr[KEY_STEPAPI].attr,
19366 ODBC_INI);
19367 }
19368 if (parent || setupdlg->attr[KEY_SYNCP].supplied) {
19369 SQLWritePrivateProfileString(dsn, "SyncPragma",
19370 setupdlg->attr[KEY_SYNCP].attr,
19371 ODBC_INI);
19372 }
19373 if (parent || setupdlg->attr[KEY_NOTXN].supplied) {
19374 SQLWritePrivateProfileString(dsn, "NoTXN",
19375 setupdlg->attr[KEY_NOTXN].attr,
19376 ODBC_INI);
19377 }
19378 if (parent || setupdlg->attr[KEY_SHORTNAM].supplied) {
19379 SQLWritePrivateProfileString(dsn, "ShortNames",
19380 setupdlg->attr[KEY_SHORTNAM].attr,
19381 ODBC_INI);
19382 }
19383 if (parent || setupdlg->attr[KEY_LONGNAM].supplied) {
19384 SQLWritePrivateProfileString(dsn, "LongNames",
19385 setupdlg->attr[KEY_LONGNAM].attr,
19386 ODBC_INI);
19387 }
19388 if (parent || setupdlg->attr[KEY_NOCREAT].supplied) {
19389 SQLWritePrivateProfileString(dsn, "NoCreat",
19390 setupdlg->attr[KEY_NOCREAT].attr,
19391 ODBC_INI);
19392 }
19393 if (parent || setupdlg->attr[KEY_NOWCHAR].supplied) {
19394 SQLWritePrivateProfileString(dsn, "NoWCHAR",
19395 setupdlg->attr[KEY_NOWCHAR].attr,
19396 ODBC_INI);
19397 }
19398 if (parent || setupdlg->attr[KEY_FKSUPPORT].supplied) {
19399 SQLWritePrivateProfileString(dsn, "FKSupport",
19400 setupdlg->attr[KEY_FKSUPPORT].attr,
19401 ODBC_INI);
19402 }
19403 if (parent || setupdlg->attr[KEY_OEMCP].supplied) {
19404 SQLWritePrivateProfileString(dsn, "OEMCP",
19405 setupdlg->attr[KEY_OEMCP].attr,
19406 ODBC_INI);
19407 }
19408 if (parent || setupdlg->attr[KEY_LOADEXT].supplied) {
19409 SQLWritePrivateProfileString(dsn, "LoadExt",
19410 setupdlg->attr[KEY_LOADEXT].attr,
19411 ODBC_INI);
19412 }
19413 if (parent || setupdlg->attr[KEY_BIGINT].supplied) {
19414 SQLWritePrivateProfileString(dsn, "BigInt",
19415 setupdlg->attr[KEY_BIGINT].attr,
19416 ODBC_INI);
19417 }
19418 if (parent || setupdlg->attr[KEY_JDCONV].supplied) {
19419 SQLWritePrivateProfileString(dsn, "JDConv",
19420 setupdlg->attr[KEY_JDCONV].attr,
19421 ODBC_INI);
19422 }
19423 if (parent || setupdlg->attr[KEY_ATTAS].supplied) {
19424 SQLWritePrivateProfileString(dsn, "AttachAs",
19425 setupdlg->attr[KEY_ATTAS].attr,
19426 ODBC_INI);
19427 }
19428 if (parent || setupdlg->attr[KEY_ILIKE].supplied) {
19429 SQLWritePrivateProfileString(dsn, "ILike",
19430 setupdlg->attr[KEY_ILIKE].attr,
19431 ODBC_INI);
19432 }
19433 if (parent || setupdlg->attr[KEY_PASSWD].supplied) {
19434 SQLWritePrivateProfileString(dsn, "PWD",
19435 setupdlg->attr[KEY_PASSWD].attr,
19436 ODBC_INI);
19437 }
19438 if (setupdlg->attr[KEY_DSN].supplied &&
19439 strcasecmp(setupdlg->DSN, setupdlg->attr[KEY_DSN].attr)) {
19440 SQLRemoveDSNFromIni(setupdlg->DSN);
19441 }
19442 return TRUE;
19443}
19444
19450static void
19451GetAttributes(SETUPDLG *setupdlg)
19452{
19453 char *dsn = setupdlg->attr[KEY_DSN].attr;
19454
19455 if (!setupdlg->attr[KEY_DESC].supplied) {
19456 SQLGetPrivateProfileString(dsn, "Description", "",
19457 setupdlg->attr[KEY_DESC].attr,
19458 sizeof (setupdlg->attr[KEY_DESC].attr),
19459 ODBC_INI);
19460 }
19461 if (!setupdlg->attr[KEY_DBNAME].supplied) {
19462 SQLGetPrivateProfileString(dsn, "Database", "",
19463 setupdlg->attr[KEY_DBNAME].attr,
19464 sizeof (setupdlg->attr[KEY_DBNAME].attr),
19465 ODBC_INI);
19466 }
19467 if (!setupdlg->attr[KEY_BUSY].supplied) {
19468 SQLGetPrivateProfileString(dsn, "Timeout", "100000",
19469 setupdlg->attr[KEY_BUSY].attr,
19470 sizeof (setupdlg->attr[KEY_BUSY].attr),
19471 ODBC_INI);
19472 }
19473 if (!setupdlg->attr[KEY_STEPAPI].supplied) {
19474 SQLGetPrivateProfileString(dsn, "StepAPI", "0",
19475 setupdlg->attr[KEY_STEPAPI].attr,
19476 sizeof (setupdlg->attr[KEY_STEPAPI].attr),
19477 ODBC_INI);
19478 }
19479 if (!setupdlg->attr[KEY_SYNCP].supplied) {
19480 SQLGetPrivateProfileString(dsn, "SyncPragma", "NORMAL",
19481 setupdlg->attr[KEY_SYNCP].attr,
19482 sizeof (setupdlg->attr[KEY_SYNCP].attr),
19483 ODBC_INI);
19484 }
19485 if (!setupdlg->attr[KEY_NOTXN].supplied) {
19486 SQLGetPrivateProfileString(dsn, "NoTXN", "",
19487 setupdlg->attr[KEY_NOTXN].attr,
19488 sizeof (setupdlg->attr[KEY_NOTXN].attr),
19489 ODBC_INI);
19490 }
19491 if (!setupdlg->attr[KEY_SHORTNAM].supplied) {
19492 SQLGetPrivateProfileString(dsn, "ShortNames", "",
19493 setupdlg->attr[KEY_SHORTNAM].attr,
19494 sizeof (setupdlg->attr[KEY_SHORTNAM].attr),
19495 ODBC_INI);
19496 }
19497 if (!setupdlg->attr[KEY_LONGNAM].supplied) {
19498 SQLGetPrivateProfileString(dsn, "LongNames", "",
19499 setupdlg->attr[KEY_LONGNAM].attr,
19500 sizeof (setupdlg->attr[KEY_LONGNAM].attr),
19501 ODBC_INI);
19502 }
19503 if (!setupdlg->attr[KEY_NOCREAT].supplied) {
19504 SQLGetPrivateProfileString(dsn, "NoCreat", "",
19505 setupdlg->attr[KEY_NOCREAT].attr,
19506 sizeof (setupdlg->attr[KEY_NOCREAT].attr),
19507 ODBC_INI);
19508 }
19509 if (!setupdlg->attr[KEY_NOWCHAR].supplied) {
19510 SQLGetPrivateProfileString(dsn, "NoWCHAR", "",
19511 setupdlg->attr[KEY_NOWCHAR].attr,
19512 sizeof (setupdlg->attr[KEY_NOWCHAR].attr),
19513 ODBC_INI);
19514 }
19515 if (!setupdlg->attr[KEY_FKSUPPORT].supplied) {
19516 SQLGetPrivateProfileString(dsn, "FKSupport", "",
19517 setupdlg->attr[KEY_FKSUPPORT].attr,
19518 sizeof (setupdlg->attr[KEY_FKSUPPORT].attr),
19519 ODBC_INI);
19520 }
19521 if (!setupdlg->attr[KEY_OEMCP].supplied) {
19522 SQLGetPrivateProfileString(dsn, "OEMCP", "",
19523 setupdlg->attr[KEY_OEMCP].attr,
19524 sizeof (setupdlg->attr[KEY_OEMCP].attr),
19525 ODBC_INI);
19526 }
19527 if (!setupdlg->attr[KEY_LOADEXT].supplied) {
19528 SQLGetPrivateProfileString(dsn, "LoadExt", "",
19529 setupdlg->attr[KEY_LOADEXT].attr,
19530 sizeof (setupdlg->attr[KEY_LOADEXT].attr),
19531 ODBC_INI);
19532 }
19533 if (!setupdlg->attr[KEY_JMODE].supplied) {
19534 SQLGetPrivateProfileString(dsn, "JournalMode", "",
19535 setupdlg->attr[KEY_JMODE].attr,
19536 sizeof (setupdlg->attr[KEY_JMODE].attr),
19537 ODBC_INI);
19538 }
19539 if (!setupdlg->attr[KEY_BIGINT].supplied) {
19540 SQLGetPrivateProfileString(dsn, "BigInt", "",
19541 setupdlg->attr[KEY_BIGINT].attr,
19542 sizeof (setupdlg->attr[KEY_BIGINT].attr),
19543 ODBC_INI);
19544 }
19545 if (!setupdlg->attr[KEY_PASSWD].supplied) {
19546 SQLGetPrivateProfileString(dsn, "PWD", "",
19547 setupdlg->attr[KEY_PASSWD].attr,
19548 sizeof (setupdlg->attr[KEY_PASSWD].attr),
19549 ODBC_INI);
19550 }
19551 if (!setupdlg->attr[KEY_JDCONV].supplied) {
19552 SQLGetPrivateProfileString(dsn, "JDConv", "",
19553 setupdlg->attr[KEY_JDCONV].attr,
19554 sizeof (setupdlg->attr[KEY_JDCONV].attr),
19555 ODBC_INI);
19556 }
19557 if (!setupdlg->attr[KEY_ATTAS].supplied) {
19558 SQLGetPrivateProfileString(dsn, "AttachAs", "",
19559 setupdlg->attr[KEY_ATTAS].attr,
19560 sizeof (setupdlg->attr[KEY_ATTAS].attr),
19561 ODBC_INI);
19562 }
19563 if (!setupdlg->attr[KEY_ILIKE].supplied) {
19564 SQLGetPrivateProfileString(dsn, "ILike", "",
19565 setupdlg->attr[KEY_ILIKE].attr,
19566 sizeof (setupdlg->attr[KEY_ILIKE].attr),
19567 ODBC_INI);
19568 }
19569}
19570
19576static void
19577GetDBFile(HWND hdlg)
19578{
19579#ifdef _WIN64
19580 SETUPDLG *setupdlg = (SETUPDLG *) GetWindowLongPtr(hdlg, DWLP_USER);
19581#else
19582 SETUPDLG *setupdlg = (SETUPDLG *) GetWindowLong(hdlg, DWL_USER);
19583#endif
19584 OPENFILENAME ofn;
19585
19586 memset(&ofn, 0, sizeof (ofn));
19587 ofn.lStructSize = sizeof (ofn);
19588 ofn.hwndOwner = hdlg;
19589#ifdef _WIN64
19590 ofn.hInstance = (HINSTANCE) GetWindowLongPtr(hdlg, GWLP_HINSTANCE);
19591#else
19592 ofn.hInstance = (HINSTANCE) GetWindowLong(hdlg, GWL_HINSTANCE);
19593#endif
19594 ofn.lpstrFile = (LPTSTR) setupdlg->attr[KEY_DBNAME].attr;
19595 ofn.nMaxFile = MAXPATHLEN;
19596 ofn.Flags = OFN_HIDEREADONLY | OFN_PATHMUSTEXIST |
19597 OFN_NOCHANGEDIR | OFN_EXPLORER | OFN_FILEMUSTEXIST;
19598 if (GetOpenFileName(&ofn)) {
19599 SetDlgItemText(hdlg, IDC_DBNAME, setupdlg->attr[KEY_DBNAME].attr);
19600 setupdlg->attr[KEY_DBNAME].supplied = TRUE;
19601 }
19602}
19603
19613static BOOL CALLBACK
19614ConfigDlgProc(HWND hdlg, WORD wmsg, WPARAM wparam, LPARAM lparam)
19615{
19616 SETUPDLG *setupdlg = NULL;
19617 WORD index;
19618
19619 switch (wmsg) {
19620 case WM_INITDIALOG:
19621#ifdef _WIN64
19622 SetWindowLongPtr(hdlg, DWLP_USER, lparam);
19623#else
19624 SetWindowLong(hdlg, DWL_USER, lparam);
19625#endif
19626 setupdlg = (SETUPDLG *) lparam;
19627 GetAttributes(setupdlg);
19628 SetDlgItemText(hdlg, IDC_DSNAME, setupdlg->attr[KEY_DSN].attr);
19629 SetDlgItemText(hdlg, IDC_DESC, setupdlg->attr[KEY_DESC].attr);
19630 SetDlgItemText(hdlg, IDC_DBNAME, setupdlg->attr[KEY_DBNAME].attr);
19631 SetDlgItemText(hdlg, IDC_TONAME, setupdlg->attr[KEY_BUSY].attr);
19632 SetDlgItemText(hdlg, IDC_LOADEXT, setupdlg->attr[KEY_LOADEXT].attr);
19633 SendDlgItemMessage(hdlg, IDC_DSNAME, EM_LIMITTEXT,
19634 (WPARAM) (MAXDSNAME - 1), (LPARAM) 0);
19635 SendDlgItemMessage(hdlg, IDC_DESC, EM_LIMITTEXT,
19636 (WPARAM) (MAXDESC - 1), (LPARAM) 0);
19637 SendDlgItemMessage(hdlg, IDC_DBNAME, EM_LIMITTEXT,
19638 (WPARAM) (MAXDBNAME - 1), (LPARAM) 0);
19639 SendDlgItemMessage(hdlg, IDC_TONAME, EM_LIMITTEXT,
19640 (WPARAM) (MAXTONAME - 1), (LPARAM) 0);
19641 SendDlgItemMessage(hdlg, IDC_LOADEXT, EM_LIMITTEXT,
19642 (WPARAM) (MAXPATHLEN*4 - 1), (LPARAM) 0);
19643 CheckDlgButton(hdlg, IDC_STEPAPI,
19644 getbool(setupdlg->attr[KEY_STEPAPI].attr) ?
19645 BST_CHECKED : BST_UNCHECKED);
19646 CheckDlgButton(hdlg, IDC_NOTXN,
19647 getbool(setupdlg->attr[KEY_NOTXN].attr) ?
19648 BST_CHECKED : BST_UNCHECKED);
19649 CheckDlgButton(hdlg, IDC_SHORTNAM,
19650 getbool(setupdlg->attr[KEY_SHORTNAM].attr) ?
19651 BST_CHECKED : BST_UNCHECKED);
19652 CheckDlgButton(hdlg, IDC_LONGNAM,
19653 getbool(setupdlg->attr[KEY_LONGNAM].attr) ?
19654 BST_CHECKED : BST_UNCHECKED);
19655 CheckDlgButton(hdlg, IDC_NOCREAT,
19656 getbool(setupdlg->attr[KEY_NOCREAT].attr) ?
19657 BST_CHECKED : BST_UNCHECKED);
19658 CheckDlgButton(hdlg, IDC_NOWCHAR,
19659 getbool(setupdlg->attr[KEY_NOWCHAR].attr) ?
19660 BST_CHECKED : BST_UNCHECKED);
19661 CheckDlgButton(hdlg, IDC_FKSUPPORT,
19662 getbool(setupdlg->attr[KEY_FKSUPPORT].attr) ?
19663 BST_CHECKED : BST_UNCHECKED);
19664 CheckDlgButton(hdlg, IDC_OEMCP,
19665 getbool(setupdlg->attr[KEY_OEMCP].attr) ?
19666 BST_CHECKED : BST_UNCHECKED);
19667 CheckDlgButton(hdlg, IDC_BIGINT,
19668 getbool(setupdlg->attr[KEY_BIGINT].attr) ?
19669 BST_CHECKED : BST_UNCHECKED);
19670 CheckDlgButton(hdlg, IDC_JDCONV,
19671 getbool(setupdlg->attr[KEY_JDCONV].attr) ?
19672 BST_CHECKED : BST_UNCHECKED);
19673 SetDlgItemText(hdlg, IDC_ATTAS, setupdlg->attr[KEY_ATTAS].attr);
19674 CheckDlgButton(hdlg, IDC_ILIKE,
19675 getbool(setupdlg->attr[KEY_ILIKE].attr) ?
19676 BST_CHECKED : BST_UNCHECKED);
19677 SendDlgItemMessage(hdlg, IDC_SYNCP,
19678 CB_LIMITTEXT, (WPARAM) 10, (LPARAM) 0);
19679 SendDlgItemMessage(hdlg, IDC_SYNCP,
19680 CB_ADDSTRING, 0, (LPARAM) "NORMAL");
19681 SendDlgItemMessage(hdlg, IDC_SYNCP,
19682 CB_ADDSTRING, 0, (LPARAM) "OFF");
19683 SendDlgItemMessage(hdlg, IDC_SYNCP,
19684 CB_ADDSTRING, 0, (LPARAM) "FULL");
19685 SendDlgItemMessage(hdlg, IDC_SYNCP,
19686 CB_SELECTSTRING, (WPARAM) -1,
19687 (LPARAM) setupdlg->attr[KEY_SYNCP].attr);
19688 if (setupdlg->defDSN) {
19689 EnableWindow(GetDlgItem(hdlg, IDC_DSNAME), FALSE);
19690 EnableWindow(GetDlgItem(hdlg, IDC_DSNAMETEXT), FALSE);
19691 }
19692 return TRUE;
19693 case WM_COMMAND:
19694 switch (GET_WM_COMMAND_ID(wparam, lparam)) {
19695 case IDC_DSNAME:
19696 if (GET_WM_COMMAND_CMD(wparam, lparam) == EN_CHANGE) {
19697 char item[MAXDSNAME];
19698
19699 EnableWindow(GetDlgItem(hdlg, IDOK),
19700 GetDlgItemText(hdlg, IDC_DSNAME,
19701 item, sizeof (item)));
19702 return TRUE;
19703 }
19704 break;
19705 case IDC_BROWSE:
19706 GetDBFile(hdlg);
19707 break;
19708 case IDOK:
19709#ifdef _WIN64
19710 setupdlg = (SETUPDLG *) GetWindowLongPtr(hdlg, DWLP_USER);
19711#else
19712 setupdlg = (SETUPDLG *) GetWindowLong(hdlg, DWL_USER);
19713#endif
19714 if (!setupdlg->defDSN) {
19715 GetDlgItemText(hdlg, IDC_DSNAME,
19716 setupdlg->attr[KEY_DSN].attr,
19717 sizeof (setupdlg->attr[KEY_DSN].attr));
19718 }
19719 GetDlgItemText(hdlg, IDC_DESC,
19720 setupdlg->attr[KEY_DESC].attr,
19721 sizeof (setupdlg->attr[KEY_DESC].attr));
19722 GetDlgItemText(hdlg, IDC_DBNAME,
19723 setupdlg->attr[KEY_DBNAME].attr,
19724 sizeof (setupdlg->attr[KEY_DBNAME].attr));
19725 GetDlgItemText(hdlg, IDC_TONAME,
19726 setupdlg->attr[KEY_BUSY].attr,
19727 sizeof (setupdlg->attr[KEY_BUSY].attr));
19728 GetDlgItemText(hdlg, IDC_LOADEXT,
19729 setupdlg->attr[KEY_LOADEXT].attr,
19730 sizeof (setupdlg->attr[KEY_LOADEXT].attr));
19731 index = SendDlgItemMessage(hdlg, IDC_SYNCP,
19732 CB_GETCURSEL, (WPARAM) 0, (LPARAM) 0);
19733 if (index != (WORD) CB_ERR) {
19734 SendDlgItemMessage(hdlg, IDC_SYNCP,
19735 CB_GETLBTEXT, index,
19736 (LPARAM) setupdlg->attr[KEY_SYNCP].attr);
19737 }
19738 strcpy(setupdlg->attr[KEY_STEPAPI].attr,
19739 (IsDlgButtonChecked(hdlg, IDC_STEPAPI) == BST_CHECKED) ?
19740 "1" : "0");
19741 strcpy(setupdlg->attr[KEY_NOTXN].attr,
19742 (IsDlgButtonChecked(hdlg, IDC_NOTXN) == BST_CHECKED) ?
19743 "1" : "0");
19744 strcpy(setupdlg->attr[KEY_SHORTNAM].attr,
19745 (IsDlgButtonChecked(hdlg, IDC_SHORTNAM) == BST_CHECKED) ?
19746 "1" : "0");
19747 strcpy(setupdlg->attr[KEY_LONGNAM].attr,
19748 (IsDlgButtonChecked(hdlg, IDC_LONGNAM) == BST_CHECKED) ?
19749 "1" : "0");
19750 strcpy(setupdlg->attr[KEY_NOCREAT].attr,
19751 (IsDlgButtonChecked(hdlg, IDC_NOCREAT) == BST_CHECKED) ?
19752 "1" : "0");
19753 strcpy(setupdlg->attr[KEY_NOWCHAR].attr,
19754 (IsDlgButtonChecked(hdlg, IDC_NOWCHAR) == BST_CHECKED) ?
19755 "1" : "0");
19756 strcpy(setupdlg->attr[KEY_FKSUPPORT].attr,
19757 (IsDlgButtonChecked(hdlg, IDC_FKSUPPORT) == BST_CHECKED) ?
19758 "1" : "0");
19759 strcpy(setupdlg->attr[KEY_OEMCP].attr,
19760 (IsDlgButtonChecked(hdlg, IDC_OEMCP) == BST_CHECKED) ?
19761 "1" : "0");
19762 strcpy(setupdlg->attr[KEY_BIGINT].attr,
19763 (IsDlgButtonChecked(hdlg, IDC_BIGINT) == BST_CHECKED) ?
19764 "1" : "0");
19765 strcpy(setupdlg->attr[KEY_JDCONV].attr,
19766 (IsDlgButtonChecked(hdlg, IDC_JDCONV) == BST_CHECKED) ?
19767 "1" : "0");
19768 GetDlgItemText(hdlg, IDC_ATTAS,
19769 setupdlg->attr[KEY_ATTAS].attr,
19770 sizeof (setupdlg->attr[KEY_ATTAS].attr));
19771 strcpy(setupdlg->attr[KEY_ILIKE].attr,
19772 (IsDlgButtonChecked(hdlg, IDC_ILIKE) == BST_CHECKED) ?
19773 "1" : "0");
19774 SetDSNAttributes(hdlg, setupdlg);
19775 /* FALL THROUGH */
19776 case IDCANCEL:
19777 EndDialog(hdlg, wparam);
19778 return TRUE;
19779 }
19780 break;
19781 }
19782 return FALSE;
19783}
19784
19794BOOL INSTAPI
19795ConfigDSN(HWND hwnd, WORD request, LPCSTR driver, LPCSTR attribs)
19796{
19797 BOOL success;
19798 SETUPDLG *setupdlg;
19799
19800 setupdlg = (SETUPDLG *) xmalloc(sizeof (SETUPDLG));
19801 if (setupdlg == NULL) {
19802 return FALSE;
19803 }
19804 memset(setupdlg, 0, sizeof (SETUPDLG));
19805 if (attribs) {
19806 ParseAttributes(attribs, setupdlg);
19807 }
19808 if (setupdlg->attr[KEY_DSN].supplied) {
19809 strcpy(setupdlg->DSN, setupdlg->attr[KEY_DSN].attr);
19810 } else {
19811 setupdlg->DSN[0] = '\0';
19812 }
19813 if (request == ODBC_REMOVE_DSN) {
19814 if (!setupdlg->attr[KEY_DSN].supplied) {
19815 success = FALSE;
19816 } else {
19817 success = SQLRemoveDSNFromIni(setupdlg->attr[KEY_DSN].attr);
19818 }
19819 } else {
19820 setupdlg->parent = hwnd;
19821 setupdlg->driver = driver;
19822 setupdlg->newDSN = request == ODBC_ADD_DSN;
19823 setupdlg->defDSN = strcasecmp(setupdlg->attr[KEY_DSN].attr,
19824 "Default") == 0;
19825 if (hwnd) {
19826 success = DialogBoxParam(hModule, MAKEINTRESOURCE(CONFIGDSN),
19827 hwnd, (DLGPROC) ConfigDlgProc,
19828 (LPARAM) setupdlg) == IDOK;
19829 } else if (setupdlg->attr[KEY_DSN].supplied) {
19830 success = SetDSNAttributes(hwnd, setupdlg);
19831 } else {
19832 success = FALSE;
19833 }
19834 }
19835 xfree(setupdlg);
19836 return success;
19837}
19838
19848static BOOL CALLBACK
19849DriverConnectProc(HWND hdlg, WORD wmsg, WPARAM wparam, LPARAM lparam)
19850{
19851 SETUPDLG *setupdlg;
19852 WORD index;
19853
19854 switch (wmsg) {
19855 case WM_INITDIALOG:
19856#ifdef _WIN64
19857 SetWindowLongPtr(hdlg, DWLP_USER, lparam);
19858#else
19859 SetWindowLong(hdlg, DWL_USER, lparam);
19860#endif
19861 setupdlg = (SETUPDLG *) lparam;
19862 SetDlgItemText(hdlg, IDC_DSNAME, setupdlg->attr[KEY_DSN].attr);
19863 SetDlgItemText(hdlg, IDC_DESC, setupdlg->attr[KEY_DESC].attr);
19864 SetDlgItemText(hdlg, IDC_DBNAME, setupdlg->attr[KEY_DBNAME].attr);
19865 SetDlgItemText(hdlg, IDC_TONAME, setupdlg->attr[KEY_BUSY].attr);
19866 SetDlgItemText(hdlg, IDC_LOADEXT, setupdlg->attr[KEY_LOADEXT].attr);
19867 SendDlgItemMessage(hdlg, IDC_DSNAME, EM_LIMITTEXT,
19868 (WPARAM) (MAXDSNAME - 1), (LPARAM) 0);
19869 SendDlgItemMessage(hdlg, IDC_DESC, EM_LIMITTEXT,
19870 (WPARAM) (MAXDESC - 1), (LPARAM) 0);
19871 SendDlgItemMessage(hdlg, IDC_DBNAME, EM_LIMITTEXT,
19872 (WPARAM) (MAXDBNAME - 1), (LPARAM) 0);
19873 SendDlgItemMessage(hdlg, IDC_TONAME, EM_LIMITTEXT,
19874 (WPARAM) (MAXTONAME - 1), (LPARAM) 0);
19875 SendDlgItemMessage(hdlg, IDC_LOADEXT, EM_LIMITTEXT,
19876 (WPARAM) (MAXPATHLEN*4 - 1), (LPARAM) 0);
19877 CheckDlgButton(hdlg, IDC_STEPAPI,
19878 getbool(setupdlg->attr[KEY_STEPAPI].attr) ?
19879 BST_CHECKED : BST_UNCHECKED);
19880 CheckDlgButton(hdlg, IDC_NOTXN,
19881 getbool(setupdlg->attr[KEY_NOTXN].attr) ?
19882 BST_CHECKED : BST_UNCHECKED);
19883 CheckDlgButton(hdlg, IDC_SHORTNAM,
19884 getbool(setupdlg->attr[KEY_SHORTNAM].attr) ?
19885 BST_CHECKED : BST_UNCHECKED);
19886 CheckDlgButton(hdlg, IDC_LONGNAM,
19887 getbool(setupdlg->attr[KEY_LONGNAM].attr) ?
19888 BST_CHECKED : BST_UNCHECKED);
19889 CheckDlgButton(hdlg, IDC_NOCREAT,
19890 getbool(setupdlg->attr[KEY_NOCREAT].attr) ?
19891 BST_CHECKED : BST_UNCHECKED);
19892 CheckDlgButton(hdlg, IDC_NOWCHAR,
19893 getbool(setupdlg->attr[KEY_NOWCHAR].attr) ?
19894 BST_CHECKED : BST_UNCHECKED);
19895 CheckDlgButton(hdlg, IDC_FKSUPPORT,
19896 getbool(setupdlg->attr[KEY_FKSUPPORT].attr) ?
19897 BST_CHECKED : BST_UNCHECKED);
19898 CheckDlgButton(hdlg, IDC_OEMCP,
19899 getbool(setupdlg->attr[KEY_OEMCP].attr) ?
19900 BST_CHECKED : BST_UNCHECKED);
19901 CheckDlgButton(hdlg, IDC_BIGINT,
19902 getbool(setupdlg->attr[KEY_BIGINT].attr) ?
19903 BST_CHECKED : BST_UNCHECKED);
19904 CheckDlgButton(hdlg, IDC_JDCONV,
19905 getbool(setupdlg->attr[KEY_JDCONV].attr) ?
19906 BST_CHECKED : BST_UNCHECKED);
19907 SendDlgItemMessage(hdlg, IDC_SYNCP,
19908 CB_LIMITTEXT, (WPARAM) 10, (LPARAM) 0);
19909 SendDlgItemMessage(hdlg, IDC_SYNCP,
19910 CB_ADDSTRING, 0, (LPARAM) "NORMAL");
19911 SendDlgItemMessage(hdlg, IDC_SYNCP,
19912 CB_ADDSTRING, 0, (LPARAM) "OFF");
19913 SendDlgItemMessage(hdlg, IDC_SYNCP,
19914 CB_ADDSTRING, 0, (LPARAM) "FULL");
19915 SendDlgItemMessage(hdlg, IDC_SYNCP,
19916 CB_SELECTSTRING, (WORD) -1,
19917 (LPARAM) setupdlg->attr[KEY_SYNCP].attr);
19918 if (setupdlg->defDSN) {
19919 EnableWindow(GetDlgItem(hdlg, IDC_DSNAME), FALSE);
19920 EnableWindow(GetDlgItem(hdlg, IDC_DSNAMETEXT), FALSE);
19921 }
19922 SetDlgItemText(hdlg, IDC_ATTAS, setupdlg->attr[KEY_ATTAS].attr);
19923 CheckDlgButton(hdlg, IDC_ILIKE,
19924 getbool(setupdlg->attr[KEY_ILIKE].attr) ?
19925 BST_CHECKED : BST_UNCHECKED);
19926 return TRUE;
19927 case WM_COMMAND:
19928 switch (GET_WM_COMMAND_ID(wparam, lparam)) {
19929 case IDC_BROWSE:
19930 GetDBFile(hdlg);
19931 break;
19932 case IDOK:
19933#ifdef _WIN64
19934 setupdlg = (SETUPDLG *) GetWindowLongPtr(hdlg, DWLP_USER);
19935#else
19936 setupdlg = (SETUPDLG *) GetWindowLong(hdlg, DWL_USER);
19937#endif
19938 GetDlgItemText(hdlg, IDC_DSNAME,
19939 setupdlg->attr[KEY_DSN].attr,
19940 sizeof (setupdlg->attr[KEY_DSN].attr));
19941 GetDlgItemText(hdlg, IDC_DBNAME,
19942 setupdlg->attr[KEY_DBNAME].attr,
19943 sizeof (setupdlg->attr[KEY_DBNAME].attr));
19944 GetDlgItemText(hdlg, IDC_TONAME,
19945 setupdlg->attr[KEY_BUSY].attr,
19946 sizeof (setupdlg->attr[KEY_BUSY].attr));
19947 GetDlgItemText(hdlg, IDC_LOADEXT,
19948 setupdlg->attr[KEY_LOADEXT].attr,
19949 sizeof (setupdlg->attr[KEY_LOADEXT].attr));
19950 index = SendDlgItemMessage(hdlg, IDC_SYNCP,
19951 CB_GETCURSEL, (WPARAM) 0, (LPARAM) 0);
19952 if (index != (WORD) CB_ERR) {
19953 SendDlgItemMessage(hdlg, IDC_SYNCP,
19954 CB_GETLBTEXT, index,
19955 (LPARAM) setupdlg->attr[KEY_SYNCP].attr);
19956 }
19957 strcpy(setupdlg->attr[KEY_STEPAPI].attr,
19958 (IsDlgButtonChecked(hdlg, IDC_STEPAPI) == BST_CHECKED) ?
19959 "1" : "0");
19960 strcpy(setupdlg->attr[KEY_NOTXN].attr,
19961 (IsDlgButtonChecked(hdlg, IDC_NOTXN) == BST_CHECKED) ?
19962 "1" : "0");
19963 strcpy(setupdlg->attr[KEY_SHORTNAM].attr,
19964 (IsDlgButtonChecked(hdlg, IDC_SHORTNAM) == BST_CHECKED) ?
19965 "1" : "0");
19966 strcpy(setupdlg->attr[KEY_LONGNAM].attr,
19967 (IsDlgButtonChecked(hdlg, IDC_LONGNAM) == BST_CHECKED) ?
19968 "1" : "0");
19969 strcpy(setupdlg->attr[KEY_NOCREAT].attr,
19970 (IsDlgButtonChecked(hdlg, IDC_NOCREAT) == BST_CHECKED) ?
19971 "1" : "0");
19972 strcpy(setupdlg->attr[KEY_NOWCHAR].attr,
19973 (IsDlgButtonChecked(hdlg, IDC_NOWCHAR) == BST_CHECKED) ?
19974 "1" : "0");
19975 strcpy(setupdlg->attr[KEY_FKSUPPORT].attr,
19976 (IsDlgButtonChecked(hdlg, IDC_FKSUPPORT) == BST_CHECKED) ?
19977 "1" : "0");
19978 strcpy(setupdlg->attr[KEY_OEMCP].attr,
19979 (IsDlgButtonChecked(hdlg, IDC_OEMCP) == BST_CHECKED) ?
19980 "1" : "0");
19981 strcpy(setupdlg->attr[KEY_BIGINT].attr,
19982 (IsDlgButtonChecked(hdlg, IDC_BIGINT) == BST_CHECKED) ?
19983 "1" : "0");
19984 strcpy(setupdlg->attr[KEY_JDCONV].attr,
19985 (IsDlgButtonChecked(hdlg, IDC_JDCONV) == BST_CHECKED) ?
19986 "1" : "0");
19987 GetDlgItemText(hdlg, IDC_ATTAS,
19988 setupdlg->attr[KEY_ATTAS].attr,
19989 sizeof (setupdlg->attr[KEY_ATTAS].attr));
19990 strcpy(setupdlg->attr[KEY_ILIKE].attr,
19991 (IsDlgButtonChecked(hdlg, IDC_ILIKE) == BST_CHECKED) ?
19992 "1" : "0");
19993 /* FALL THROUGH */
19994 case IDCANCEL:
19995 EndDialog(hdlg, GET_WM_COMMAND_ID(wparam, lparam) == IDOK);
19996 return TRUE;
19997 }
19998 }
19999 return FALSE;
20000}
20001
20015static SQLRETURN
20016drvdriverconnect(SQLHDBC dbc, SQLHWND hwnd,
20017 SQLCHAR *connIn, SQLSMALLINT connInLen,
20018 SQLCHAR *connOut, SQLSMALLINT connOutMax,
20019 SQLSMALLINT *connOutLen, SQLUSMALLINT drvcompl)
20020{
20021 BOOL maybeprompt, prompt = FALSE, defaultdsn = FALSE;
20022 DBC *d;
20023 SETUPDLG *setupdlg;
20024 SQLRETURN ret;
20025 char *dsn = NULL, *driver = NULL, *dbname = NULL;
20026
20027 if (dbc == SQL_NULL_HDBC) {
20028 return SQL_INVALID_HANDLE;
20029 }
20030 d = (DBC *) dbc;
20031 if (d->sqlite) {
20032 setstatd(d, -1, "connection already established", "08002");
20033 return SQL_ERROR;
20034 }
20035 setupdlg = (SETUPDLG *) xmalloc(sizeof (SETUPDLG));
20036 if (setupdlg == NULL) {
20037 return SQL_ERROR;
20038 }
20039 memset(setupdlg, 0, sizeof (SETUPDLG));
20040 maybeprompt = drvcompl == SQL_DRIVER_COMPLETE ||
20041 drvcompl == SQL_DRIVER_COMPLETE_REQUIRED;
20042 if (connIn == NULL || !connInLen ||
20043 (connInLen == SQL_NTS && !connIn[0])) {
20044 prompt = TRUE;
20045 } else {
20046 ParseAttributes((LPCSTR) connIn, setupdlg);
20047 if (!setupdlg->attr[KEY_DSN].attr[0] &&
20048 drvcompl == SQL_DRIVER_COMPLETE_REQUIRED) {
20049 strcpy(setupdlg->attr[KEY_DSN].attr, "DEFAULT");
20050 defaultdsn = TRUE;
20051 }
20052 GetAttributes(setupdlg);
20053 if (drvcompl == SQL_DRIVER_PROMPT ||
20054 (maybeprompt &&
20055 !setupdlg->attr[KEY_DBNAME].attr[0])) {
20056 prompt = TRUE;
20057 }
20058 }
20059retry:
20060 if (prompt) {
20061 short dlgret;
20062
20063 setupdlg->defDSN = setupdlg->attr[KEY_DRIVER].attr[0] != '\0';
20064 dlgret = DialogBoxParam(hModule, MAKEINTRESOURCE(DRIVERCONNECT),
20065 hwnd, (DLGPROC) DriverConnectProc,
20066 (LPARAM) setupdlg);
20067
20068 if (!dlgret || dlgret == -1) {
20069 xfree(setupdlg);
20070 return SQL_NO_DATA;
20071 }
20072 }
20073 dsn = setupdlg->attr[KEY_DSN].attr;
20074 driver = setupdlg->attr[KEY_DRIVER].attr;
20075 dbname = setupdlg->attr[KEY_DBNAME].attr;
20076 if (connOut || connOutLen) {
20077 char buf[SQL_MAX_MESSAGE_LENGTH * 8];
20078 int len, count;
20079 char dsn_0 = (dsn && !defaultdsn) ? dsn[0] : '\0';
20080 char drv_0 = driver ? driver[0] : '\0';
20081
20082 buf[0] = '\0';
20083 count = snprintf(buf, sizeof (buf),
20084 "%s%s%s%s%s%sDatabase=%s;StepAPI=%s;"
20085 "SyncPragma=%s;NoTXN=%s;Timeout=%s;"
20086 "ShortNames=%s;LongNames=%s;"
20087 "NoCreat=%s;NoWCHAR=%s;"
20088 "FKSupport=%s;JournalMode=%s;OEMCP=%s;LoadExt=%s;"
20089 "BigInt=%s;JDConv=%s;PWD=%s;AttachAs=%s;ILike=%s",
20090 dsn_0 ? "DSN=" : "",
20091 dsn_0 ? dsn : "",
20092 dsn_0 ? ";" : "",
20093 drv_0 ? "Driver=" : "",
20094 drv_0 ? driver : "",
20095 drv_0 ? ";" : "",
20096 dbname ? dbname : "",
20097 setupdlg->attr[KEY_STEPAPI].attr,
20098 setupdlg->attr[KEY_SYNCP].attr,
20099 setupdlg->attr[KEY_NOTXN].attr,
20100 setupdlg->attr[KEY_BUSY].attr,
20101 setupdlg->attr[KEY_SHORTNAM].attr,
20102 setupdlg->attr[KEY_LONGNAM].attr,
20103 setupdlg->attr[KEY_NOCREAT].attr,
20104 setupdlg->attr[KEY_NOWCHAR].attr,
20105 setupdlg->attr[KEY_FKSUPPORT].attr,
20106 setupdlg->attr[KEY_JMODE].attr,
20107 setupdlg->attr[KEY_OEMCP].attr,
20108 setupdlg->attr[KEY_LOADEXT].attr,
20109 setupdlg->attr[KEY_BIGINT].attr,
20110 setupdlg->attr[KEY_JDCONV].attr,
20111 setupdlg->attr[KEY_PASSWD].attr,
20112 setupdlg->attr[KEY_ATTAS].attr,
20113 setupdlg->attr[KEY_ILIKE].attr);
20114 if (count < 0) {
20115 buf[sizeof (buf) - 1] = '\0';
20116 }
20117 len = min(connOutMax - 1, strlen(buf));
20118 if (connOut) {
20119 strncpy((char *) connOut, buf, len);
20120 connOut[len] = '\0';
20121 }
20122 if (connOutLen) {
20123 *connOutLen = len;
20124 }
20125 }
20126 if (dsn[0]) {
20127 char tracef[SQL_MAX_MESSAGE_LENGTH];
20128
20129 tracef[0] = '\0';
20130 SQLGetPrivateProfileString(setupdlg->attr[KEY_DSN].attr,
20131 "tracefile", "", tracef,
20132 sizeof (tracef), ODBC_INI);
20133 if (tracef[0] != '\0') {
20134 d->trace = fopen(tracef, "a");
20135 }
20136 }
20137 d->nowchar = getbool(setupdlg->attr[KEY_NOWCHAR].attr);
20138 d->shortnames = getbool(setupdlg->attr[KEY_SHORTNAM].attr);
20139 d->longnames = getbool(setupdlg->attr[KEY_LONGNAM].attr);
20140 d->nocreat = getbool(setupdlg->attr[KEY_NOCREAT].attr);
20141 d->fksupport = getbool(setupdlg->attr[KEY_FKSUPPORT].attr);
20142 d->oemcp = getbool(setupdlg->attr[KEY_OEMCP].attr);
20143 d->dobigint = getbool(setupdlg->attr[KEY_BIGINT].attr);
20144 d->jdconv = getbool(setupdlg->attr[KEY_JDCONV].attr);
20145 d->ilike = getbool(setupdlg->attr[KEY_ILIKE].attr);
20146 d->pwdLen = strlen(setupdlg->attr[KEY_PASSWD].attr);
20147 d->pwd = (d->pwdLen > 0) ? setupdlg->attr[KEY_PASSWD].attr : NULL;
20148 ret = dbopen(d, dbname ? dbname : "", 0,
20149 dsn ? dsn : "",
20150 setupdlg->attr[KEY_STEPAPI].attr,
20151 setupdlg->attr[KEY_SYNCP].attr,
20152 setupdlg->attr[KEY_NOTXN].attr,
20153 setupdlg->attr[KEY_JMODE].attr,
20154 setupdlg->attr[KEY_BUSY].attr);
20155 if (ret != SQL_SUCCESS) {
20156 if (maybeprompt && !prompt) {
20157 prompt = TRUE;
20158 goto retry;
20159 }
20160 }
20161 memset(setupdlg->attr[KEY_PASSWD].attr, 0,
20162 sizeof (setupdlg->attr[KEY_PASSWD].attr));
20163 if (ret == SQL_SUCCESS) {
20164 dbloadext(d, setupdlg->attr[KEY_LOADEXT].attr);
20165 dbattas(d, setupdlg->attr[KEY_ATTAS].attr);
20166 }
20167 xfree(setupdlg);
20168 return ret;
20169}
20170
20171#endif /* WITHOUT_DRIVERMGR */
20172#endif /* _WIN32 || _WIN64 */
20173
20174#ifndef WINTERFACE
20188SQLRETURN SQL_API
20189SQLDriverConnect(SQLHDBC dbc, SQLHWND hwnd,
20190 SQLCHAR *connIn, SQLSMALLINT connInLen,
20191 SQLCHAR *connOut, SQLSMALLINT connOutMax,
20192 SQLSMALLINT *connOutLen, SQLUSMALLINT drvcompl)
20193{
20194 SQLRETURN ret;
20195
20196 HDBC_LOCK(dbc);
20197 ret = drvdriverconnect(dbc, hwnd, connIn, connInLen,
20198 connOut, connOutMax, connOutLen, drvcompl);
20200 return ret;
20201}
20202#endif
20203
20204#ifdef WINTERFACE
20218SQLRETURN SQL_API
20219SQLDriverConnectW(SQLHDBC dbc, SQLHWND hwnd,
20220 SQLWCHAR *connIn, SQLSMALLINT connInLen,
20221 SQLWCHAR *connOut, SQLSMALLINT connOutMax,
20222 SQLSMALLINT *connOutLen, SQLUSMALLINT drvcompl)
20223{
20224 SQLRETURN ret;
20225 char *ci = NULL;
20226 SQLSMALLINT len = 0;
20227
20228 HDBC_LOCK(dbc);
20229 if (connIn) {
20230#if defined(_WIN32) || defined(_WIN64)
20231 if (connInLen == SQL_NTS) {
20232 connInLen = -1;
20233 }
20234 ci = uc_to_wmb(connIn, connInLen);
20235#else
20236 ci = uc_to_utf(connIn, connInLen);
20237#endif
20238 if (!ci) {
20239 DBC *d = (DBC *) dbc;
20240
20241 setstatd(d, -1, "out of memory", (*d->ov3) ? "HY000" : "S1000");
20243 return SQL_ERROR;
20244 }
20245 }
20246 ret = drvdriverconnect(dbc, hwnd, (SQLCHAR *) ci, SQL_NTS,
20247 (SQLCHAR *) connOut, connOutMax, &len, drvcompl);
20249 uc_free(ci);
20250 if (ret == SQL_SUCCESS) {
20251 SQLWCHAR *co = NULL;
20252
20253 if (connOut) {
20254 if (len > 0) {
20255#if defined(_WIN32) || defined(_WIN64)
20256 co = wmb_to_uc((char *) connOut, len);
20257#else
20258 co = uc_from_utf((SQLCHAR *) connOut, len);
20259#endif
20260 if (co) {
20261 uc_strncpy(connOut, co, connOutMax / sizeof (SQLWCHAR));
20262 len = min(connOutMax / sizeof (SQLWCHAR), uc_strlen(co));
20263 uc_free(co);
20264 } else {
20265 len = 0;
20266 }
20267 }
20268 if (len <= 0) {
20269 len = 0;
20270 connOut[0] = 0;
20271 }
20272 } else {
20273 len = 0;
20274 }
20275 if (connOutLen) {
20276 *connOutLen = len;
20277 }
20278 }
20279 return ret;
20280}
20281#endif
20282
20283#if defined(_WIN32) || defined(_WIN64)
20284
20293BOOL APIENTRY
20294LibMain(HANDLE hinst, DWORD reason, LPVOID reserved)
20295{
20296 static int initialized = 0;
20297
20298 switch (reason) {
20299 case DLL_PROCESS_ATTACH:
20300 if (!initialized++) {
20301 hModule = hinst;
20302#ifdef WINTERFACE
20303 /* MS Access hack part 1 (reserved error -7748) */
20304 statSpec2P = statSpec2;
20305 statSpec3P = statSpec3;
20306#endif
20307#ifdef SQLITE_DYNLOAD
20308 dls_init();
20309#endif
20310#ifdef SQLITE_HAS_CODEC
20311 sqlite3_activate_see(SQLITE_ACTIVATION_KEY);
20312#endif
20313 }
20314#if defined(ENABLE_NVFS) && (ENABLE_NVFS)
20315 nvfs_init();
20316#endif
20317 break;
20318 case DLL_THREAD_ATTACH:
20319 break;
20320 case DLL_PROCESS_DETACH:
20321 if (--initialized <= 0) {
20322#ifdef SQLITE_DYNLOAD
20323 dls_fini();
20324#endif
20325 }
20326 break;
20327 case DLL_THREAD_DETACH:
20328 break;
20329 default:
20330 break;
20331 }
20332 return TRUE;
20333}
20334
20343int __stdcall
20344DllMain(HANDLE hinst, DWORD reason, LPVOID reserved)
20345{
20346 return LibMain(hinst, reason, reserved);
20347}
20348
20349#ifndef WITHOUT_INSTALLER
20350
20357static BOOL
20358InUnError(char *name)
20359{
20360 WORD err = 1;
20361 DWORD code;
20362 char errmsg[301];
20363 WORD errlen, errmax = sizeof (errmsg) - 1;
20364 int sqlret;
20365 BOOL ret = FALSE;
20366
20367 do {
20368 errmsg[0] = '\0';
20369 sqlret = SQLInstallerError(err, &code, errmsg, errmax, &errlen);
20370 if (SQL_SUCCEEDED(sqlret)) {
20371 MessageBox(NULL, errmsg, name,
20372 MB_ICONSTOP | MB_OK | MB_TASKMODAL | MB_SETFOREGROUND);
20373 ret = TRUE;
20374 }
20375 err++;
20376 } while (sqlret != SQL_NO_DATA);
20377 return ret;
20378}
20379
20386static BOOL
20387InUn(int remove, char *cmdline)
20388{
20389#ifdef SQLITE_HAS_CODEC
20390 static char *drivername = "SQLite3 ODBC Driver (SEE)";
20391 static char *dsname = "SQLite3 SEE Datasource";
20392#else
20393 static char *drivername = "SQLite3 ODBC Driver";
20394 static char *dsname = "SQLite3 Datasource";
20395#endif
20396 char *dllname, *p;
20397 char dllbuf[301], path[301], driver[300], attr[300], inst[400];
20398 WORD pathmax = sizeof (path) - 1, pathlen;
20399 DWORD usecnt, mincnt;
20400 int quiet = 0;
20401
20402 dllbuf[0] = '\0';
20403 GetModuleFileName(hModule, dllbuf, sizeof (dllbuf));
20404 p = strrchr(dllbuf, '\\');
20405 dllname = p ? (p + 1) : dllbuf;
20406 quiet = cmdline && strstr(cmdline, "quiet");
20407 if (SQLInstallDriverManager(path, pathmax, &pathlen)) {
20408 sprintf(driver, "%s;Driver=%s;Setup=%s;",
20409 drivername, dllname, dllname);
20410 p = driver;
20411 while (*p) {
20412 if (*p == ';') {
20413 *p = '\0';
20414 }
20415 ++p;
20416 }
20417 usecnt = 0;
20418 path[0] = '\0';
20419 SQLInstallDriverEx(driver, NULL, path, pathmax, NULL,
20420 ODBC_INSTALL_INQUIRY, &usecnt);
20421 pathlen = strlen(path);
20422 while (pathlen > 0 && path[pathlen - 1] == '\\') {
20423 --pathlen;
20424 path[pathlen] = '\0';
20425 }
20426 sprintf(driver, "%s;Driver=%s\\%s;Setup=%s\\%s;",
20427 drivername, path, dllname, path, dllname);
20428 p = driver;
20429 while (*p) {
20430 if (*p == ';') {
20431 *p = '\0';
20432 }
20433 ++p;
20434 }
20435 sprintf(inst, "%s\\%s", path, dllname);
20436 if (!remove && usecnt > 0) {
20437 /* first install try: copy over driver dll, keeping DSNs */
20438 if (GetFileAttributesA(dllbuf) != INVALID_FILE_ATTRIBUTES &&
20439 CopyFile(dllbuf, inst, 0)) {
20440 if (!quiet) {
20441 char buf[512];
20442
20443 sprintf(buf, "%s replaced.", drivername);
20444 MessageBox(NULL, buf, "Info",
20445 MB_ICONINFORMATION | MB_OK | MB_TASKMODAL |
20446 MB_SETFOREGROUND);
20447 }
20448 return TRUE;
20449 }
20450 }
20451 mincnt = remove ? 1 : 0;
20452 while (usecnt != mincnt) {
20453 if (!SQLRemoveDriver(driver, TRUE, &usecnt)) {
20454 break;
20455 }
20456 }
20457 if (remove) {
20458 if (usecnt && !SQLRemoveDriver(driver, TRUE, &usecnt)) {
20459 InUnError("SQLRemoveDriver");
20460 return FALSE;
20461 }
20462 if (!usecnt) {
20463 char buf[512];
20464
20465 DeleteFile(inst);
20466 if (!quiet) {
20467 sprintf(buf, "%s uninstalled.", drivername);
20468 MessageBox(NULL, buf, "Info",
20469 MB_ICONINFORMATION |MB_OK | MB_TASKMODAL |
20470 MB_SETFOREGROUND);
20471 }
20472 }
20473 sprintf(attr, "DSN=%s;Database=;", dsname);
20474 p = attr;
20475 while (*p) {
20476 if (*p == ';') {
20477 *p = '\0';
20478 }
20479 ++p;
20480 }
20481 SQLConfigDataSource(NULL, ODBC_REMOVE_SYS_DSN, drivername, attr);
20482 return TRUE;
20483 }
20484 if (GetFileAttributesA(dllbuf) == INVALID_FILE_ATTRIBUTES) {
20485 return FALSE;
20486 }
20487 if (strcasecmp(dllbuf, inst) != 0 && !CopyFile(dllbuf, inst, 0)) {
20488 char buf[512];
20489
20490 sprintf(buf, "Copy %s to %s failed.", dllbuf, inst);
20491 MessageBox(NULL, buf, "CopyFile",
20492 MB_ICONSTOP |MB_OK | MB_TASKMODAL | MB_SETFOREGROUND);
20493 return FALSE;
20494 }
20495 if (!SQLInstallDriverEx(driver, path, path, pathmax, &pathlen,
20496 ODBC_INSTALL_COMPLETE, &usecnt)) {
20497 InUnError("SQLInstallDriverEx");
20498 return FALSE;
20499 }
20500 sprintf(attr, "DSN=%s;Database=;", dsname);
20501 p = attr;
20502 while (*p) {
20503 if (*p == ';') {
20504 *p = '\0';
20505 }
20506 ++p;
20507 }
20508 SQLConfigDataSource(NULL, ODBC_REMOVE_SYS_DSN, drivername, attr);
20509 if (!SQLConfigDataSource(NULL, ODBC_ADD_SYS_DSN, drivername, attr)) {
20510 InUnError("SQLConfigDataSource");
20511 return FALSE;
20512 }
20513 if (!quiet) {
20514 char buf[512];
20515
20516 sprintf(buf, "%s installed.", drivername);
20517 MessageBox(NULL, buf, "Info",
20518 MB_ICONINFORMATION | MB_OK | MB_TASKMODAL |
20519 MB_SETFOREGROUND);
20520 }
20521 } else {
20522 InUnError("SQLInstallDriverManager");
20523 return FALSE;
20524 }
20525 return TRUE;
20526}
20527
20536void CALLBACK
20537install(HWND hwnd, HINSTANCE hinst, LPSTR lpszCmdLine, int nCmdShow)
20538{
20539 InUn(0, lpszCmdLine);
20540}
20541
20550void CALLBACK
20551uninstall(HWND hwnd, HINSTANCE hinst, LPSTR lpszCmdLine, int nCmdShow)
20552{
20553 InUn(1, lpszCmdLine);
20554}
20555
20556#endif /* WITHOUT_INSTALLER */
20557
20558#ifndef WITHOUT_SHELL
20559
20568static void
20569setargv(int *argcp, char ***argvp, char *cmdline, char *argv0)
20570{
20571 char *p, *arg, *argspace, **argv;
20572 int argc, size, inquote, copy, slashes;
20573
20574 size = 2 + (argv0 ? 1 : 0);
20575 for (p = cmdline; *p != '\0'; p++) {
20576 if (ISSPACE(*p)) {
20577 size++;
20578 while (ISSPACE(*p)) {
20579 p++;
20580 }
20581 if (*p == '\0') {
20582 break;
20583 }
20584 }
20585 }
20586 argspace = malloc(size * sizeof (char *) + strlen(cmdline) + 1);
20587 argv = (char **) argspace;
20588 argspace += size * sizeof (char *);
20589 size--;
20590 argc = 0;
20591 if (argv0) {
20592 argv[argc++] = argv0;
20593 }
20594 p = cmdline;
20595 for (; argc < size; argc++) {
20596 argv[argc] = arg = argspace;
20597 while (ISSPACE(*p)) {
20598 p++;
20599 }
20600 if (*p == '\0') {
20601 break;
20602 }
20603 inquote = 0;
20604 slashes = 0;
20605 while (1) {
20606 copy = 1;
20607 while (*p == '\\') {
20608 slashes++;
20609 p++;
20610 }
20611 if (*p == '"') {
20612 if ((slashes & 1) == 0) {
20613 copy = 0;
20614 if (inquote && p[1] == '"') {
20615 p++;
20616 copy = 1;
20617 } else {
20618 inquote = !inquote;
20619 }
20620 }
20621 slashes >>= 1;
20622 }
20623 while (slashes) {
20624 *arg = '\\';
20625 arg++;
20626 slashes--;
20627 }
20628 if (*p == '\0' || (!inquote && ISSPACE(*p))) {
20629 break;
20630 }
20631 if (copy != 0) {
20632 *arg = *p;
20633 arg++;
20634 }
20635 p++;
20636 }
20637 *arg = '\0';
20638 argspace = arg + 1;
20639 }
20640 argv[argc] = 0;
20641 *argcp = argc;
20642 *argvp = argv;
20643}
20644
20653void CALLBACK
20654shell(HWND hwnd, HINSTANCE hinst, LPSTR lpszCmdLine, int nCmdShow)
20655{
20656 int argc, needcon = 0;
20657 char **argv;
20658 extern int sqlite3_main(int, char **);
20659 static const char *name = "SQLite3 Shell";
20660 DWORD ftype0, ftype1, ftype2;
20661
20662 ftype0 = GetFileType(GetStdHandle(STD_INPUT_HANDLE));
20663 ftype1 = GetFileType(GetStdHandle(STD_OUTPUT_HANDLE));
20664 ftype2 = GetFileType(GetStdHandle(STD_ERROR_HANDLE));
20665 if (ftype0 != FILE_TYPE_DISK && ftype0 != FILE_TYPE_CHAR &&
20666 ftype0 != FILE_TYPE_PIPE) {
20667 fclose(stdin);
20668 ++needcon;
20669 ftype0 = FILE_TYPE_UNKNOWN;
20670 }
20671 if (ftype1 != FILE_TYPE_DISK && ftype1 != FILE_TYPE_CHAR &&
20672 ftype1 != FILE_TYPE_PIPE) {
20673 fclose(stdout);
20674 ++needcon;
20675 ftype1 = FILE_TYPE_UNKNOWN;
20676 }
20677 if (ftype2 != FILE_TYPE_DISK && ftype2 != FILE_TYPE_CHAR &&
20678 ftype2 != FILE_TYPE_PIPE) {
20679 fclose(stderr);
20680 ++needcon;
20681 ftype2 = FILE_TYPE_UNKNOWN;
20682 }
20683 if (needcon > 0) {
20684 AllocConsole();
20685 SetConsoleTitle(name);
20686 }
20687 if (ftype0 == FILE_TYPE_UNKNOWN) {
20688 freopen("CONIN$", "r", stdin);
20689 }
20690 if (ftype1 == FILE_TYPE_UNKNOWN) {
20691 freopen("CONOUT$", "w", stdout);
20692 }
20693 if (ftype2 == FILE_TYPE_UNKNOWN) {
20694 freopen("CONOUT$", "w", stderr);
20695 }
20696 setargv(&argc, &argv, lpszCmdLine, (char *) name);
20697#if defined(ENABLE_NVFS) && (ENABLE_NVFS)
20698 nvfs_init();
20699#endif
20700 sqlite3_main(argc, argv);
20701}
20702
20703#endif /* WITHOUT_SHELL */
20704
20705#endif /* _WIN32 || _WIN64 */
20706
20707#if defined(HAVE_ODBCINSTEXT_H) && (HAVE_ODBCINSTEXT_H)
20708
20709/*
20710 * unixODBC property page for this driver,
20711 * may or may not work depending on unixODBC version.
20712 */
20713
20714#include <odbcinstext.h>
20715
20716int
20717ODBCINSTGetProperties(HODBCINSTPROPERTY prop)
20718{
20719 static const char *instYN[] = { "No", "Yes", NULL };
20720 static const char *syncPragma[] = { "NORMAL", "OFF", "FULL", NULL };
20721 static const char *jmPragma[] = {
20722 "DELETE", "PERSIST", "OFF", "TRUNCATE", "MEMORY", "WAL", NULL
20723 };
20724
20725 prop->pNext = (HODBCINSTPROPERTY) malloc(sizeof (ODBCINSTPROPERTY));
20726 prop = prop->pNext;
20727 memset(prop, 0, sizeof (ODBCINSTPROPERTY));
20728 prop->nPromptType = ODBCINST_PROMPTTYPE_FILENAME;
20729 strncpy(prop->szName, "Database", INI_MAX_PROPERTY_NAME);
20730 strncpy(prop->szValue, "", INI_MAX_PROPERTY_VALUE);
20731 prop->pNext = (HODBCINSTPROPERTY) malloc(sizeof (ODBCINSTPROPERTY));
20732 prop = prop->pNext;
20733 memset(prop, 0, sizeof (ODBCINSTPROPERTY));
20734 prop->nPromptType = ODBCINST_PROMPTTYPE_TEXTEDIT;
20735 strncpy(prop->szName, "Timeout", INI_MAX_PROPERTY_NAME);
20736 strncpy(prop->szValue, "100000", INI_MAX_PROPERTY_VALUE);
20737 prop->pNext = (HODBCINSTPROPERTY) malloc(sizeof (ODBCINSTPROPERTY));
20738 prop = prop->pNext;
20739 memset(prop, 0, sizeof (ODBCINSTPROPERTY));
20740 prop->nPromptType = ODBCINST_PROMPTTYPE_COMBOBOX;
20741 prop->aPromptData = malloc(sizeof (instYN));
20742 memcpy(prop->aPromptData, instYN, sizeof (instYN));
20743 strncpy(prop->szName, "StepAPI", INI_MAX_PROPERTY_NAME);
20744 strncpy(prop->szValue, "No", INI_MAX_PROPERTY_VALUE);
20745 prop->pNext = (HODBCINSTPROPERTY) malloc(sizeof (ODBCINSTPROPERTY));
20746 prop = prop->pNext;
20747 memset(prop, 0, sizeof (ODBCINSTPROPERTY));
20748 prop->nPromptType = ODBCINST_PROMPTTYPE_COMBOBOX;
20749 prop->aPromptData = malloc(sizeof (instYN));
20750 memcpy(prop->aPromptData, instYN, sizeof (instYN));
20751 strncpy(prop->szName, "ShortNames", INI_MAX_PROPERTY_NAME);
20752 strncpy(prop->szValue, "No", INI_MAX_PROPERTY_VALUE);
20753 prop->pNext = (HODBCINSTPROPERTY) malloc(sizeof (ODBCINSTPROPERTY));
20754 prop = prop->pNext;
20755 memset(prop, 0, sizeof (ODBCINSTPROPERTY));
20756 prop->nPromptType = ODBCINST_PROMPTTYPE_COMBOBOX;
20757 prop->aPromptData = malloc(sizeof (instYN));
20758 memcpy(prop->aPromptData, instYN, sizeof (instYN));
20759 strncpy(prop->szName, "LongNames", INI_MAX_PROPERTY_NAME);
20760 strncpy(prop->szValue, "No", INI_MAX_PROPERTY_VALUE);
20761 prop->pNext = (HODBCINSTPROPERTY) malloc(sizeof (ODBCINSTPROPERTY));
20762 memset(prop, 0, sizeof (ODBCINSTPROPERTY));
20763 prop->nPromptType = ODBCINST_PROMPTTYPE_COMBOBOX;
20764 prop->aPromptData = malloc(sizeof (instYN));
20765 memcpy(prop->aPromptData, instYN, sizeof (instYN));
20766 strncpy(prop->szName, "NoCreat", INI_MAX_PROPERTY_NAME);
20767 strncpy(prop->szValue, "No", INI_MAX_PROPERTY_VALUE);
20768#ifdef WINTERFACE
20769 prop->pNext = (HODBCINSTPROPERTY) malloc(sizeof (ODBCINSTPROPERTY));
20770 memset(prop, 0, sizeof (ODBCINSTPROPERTY));
20771 prop->nPromptType = ODBCINST_PROMPTTYPE_COMBOBOX;
20772 prop->aPromptData = malloc(sizeof (instYN));
20773 memcpy(prop->aPromptData, instYN, sizeof (instYN));
20774 strncpy(prop->szName, "NoWCHAR", INI_MAX_PROPERTY_NAME);
20775 strncpy(prop->szValue, "No", INI_MAX_PROPERTY_VALUE);
20776#endif
20777 prop->pNext = (HODBCINSTPROPERTY) malloc(sizeof (ODBCINSTPROPERTY));
20778 memset(prop, 0, sizeof (ODBCINSTPROPERTY));
20779 prop->nPromptType = ODBCINST_PROMPTTYPE_COMBOBOX;
20780 prop->aPromptData = malloc(sizeof (instYN));
20781 memcpy(prop->aPromptData, instYN, sizeof (instYN));
20782 strncpy(prop->szName, "FKSupport", INI_MAX_PROPERTY_NAME);
20783 strncpy(prop->szValue, "No", INI_MAX_PROPERTY_VALUE);
20784 prop->pNext = (HODBCINSTPROPERTY) malloc(sizeof (ODBCINSTPROPERTY));
20785 prop = prop->pNext;
20786 memset(prop, 0, sizeof (ODBCINSTPROPERTY));
20787 prop->nPromptType = ODBCINST_PROMPTTYPE_COMBOBOX;
20788 prop->aPromptData = malloc(sizeof (syncPragma));
20789 memcpy(prop->aPromptData, syncPragma, sizeof (syncPragma));
20790 strncpy(prop->szName, "SyncPragma", INI_MAX_PROPERTY_NAME);
20791 strncpy(prop->szValue, "NORMAL", INI_MAX_PROPERTY_VALUE);
20792 prop->pNext = (HODBCINSTPROPERTY) malloc(sizeof (ODBCINSTPROPERTY));
20793 prop = prop->pNext;
20794 memset(prop, 0, sizeof (ODBCINSTPROPERTY));
20795 prop->nPromptType = ODBCINST_PROMPTTYPE_COMBOBOX;
20796 prop->aPromptData = malloc(sizeof (jmPragma));
20797 memcpy(prop->aPromptData, jmPragma, sizeof (jmPragma));
20798 strncpy(prop->szName, "JournalMode", INI_MAX_PROPERTY_NAME);
20799 strncpy(prop->szValue, "DELETE", INI_MAX_PROPERTY_VALUE);
20800 prop->pNext = (HODBCINSTPROPERTY) malloc(sizeof (ODBCINSTPROPERTY));
20801 prop = prop->pNext;
20802 memset(prop, 0, sizeof (ODBCINSTPROPERTY));
20803 prop->nPromptType = ODBCINST_PROMPTTYPE_TEXTEDIT;
20804 strncpy(prop->szName, "LoadExt", INI_MAX_PROPERTY_NAME);
20805 strncpy(prop->szValue, "", INI_MAX_PROPERTY_VALUE);
20806 prop->pNext = (HODBCINSTPROPERTY) malloc(sizeof (ODBCINSTPROPERTY));
20807 memset(prop, 0, sizeof (ODBCINSTPROPERTY));
20808 prop->nPromptType = ODBCINST_PROMPTTYPE_COMBOBOX;
20809 prop->aPromptData = malloc(sizeof (instYN));
20810 memcpy(prop->aPromptData, instYN, sizeof (instYN));
20811 strncpy(prop->szName, "BigInt", INI_MAX_PROPERTY_NAME);
20812 strncpy(prop->szValue, "No", INI_MAX_PROPERTY_VALUE);
20813 return 1;
20814}
20815
20816#endif /* HAVE_ODBCINSTEXT_H */
20817
20818#ifdef SQLITE_DYNLOAD
20819
20820/*
20821 * SQLite3 shared library/DLL stubs.
20822 */
20823
20824static void
20825dls_void(void)
20826{
20827}
20828
20829static int
20830dls_error(void)
20831{
20832 return SQLITE_ERROR;
20833}
20834
20835static int
20836dls_0(void)
20837{
20838 return 0;
20839}
20840
20841static sqlite_int64
20842dls_0LL(void)
20843{
20844 return 0;
20845}
20846
20847static double
20848dls_00(void)
20849{
20850 return 0;
20851}
20852
20853static void *
20854dls_null(void)
20855{
20856 return NULL;
20857}
20858
20859static const char *
20860dls_empty(void)
20861{
20862 return "";
20863}
20864
20865static int
20866dls_snull(void)
20867{
20868 return SQLITE_NULL;
20869}
20870
20871#define DLS_ENT(name, func) \
20872 { "sqlite3_" #name, offsetof(struct dl_sqlite3_funcs, name), \
20873 (void *) func }
20874
20875#define DLS_ENT3(name, off, func) \
20876 { "sqlite3_" #name, offsetof(struct dl_sqlite3_funcs, off), \
20877 (void *) func }
20878
20879#define DLS_END { NULL, 0, NULL }
20880
20881static struct {
20882 const char *name;
20883 int offset;
20884 void *func;
20885} dls_nametab[] = {
20886 DLS_ENT(activate_see, dls_void),
20887 DLS_ENT(bind_blob, dls_error),
20888 DLS_ENT(bind_double, dls_error),
20889 DLS_ENT(bind_int, dls_error),
20890 DLS_ENT(bind_int64, dls_error),
20891 DLS_ENT(bind_null, dls_error),
20892 DLS_ENT(bind_parameter_count, dls_0),
20893 DLS_ENT(bind_text, dls_error),
20894 DLS_ENT(busy_handler, dls_error),
20895 DLS_ENT(changes, dls_0),
20896 DLS_ENT(close, dls_error),
20897 DLS_ENT(column_blob, dls_null),
20898 DLS_ENT(column_bytes, dls_0),
20899 DLS_ENT(column_count, dls_0),
20900 DLS_ENT(column_database_name, dls_empty),
20901 DLS_ENT(column_decltype, dls_empty),
20902 DLS_ENT(column_double, dls_00),
20903 DLS_ENT(column_name, dls_empty),
20904 DLS_ENT(column_origin_name, dls_null),
20905 DLS_ENT(column_table_name, dls_null),
20906 DLS_ENT(column_text, dls_null),
20907 DLS_ENT(column_type, dls_snull),
20908 DLS_ENT(create_function, dls_error),
20909 DLS_ENT(enable_load_extension, dls_error),
20910 DLS_ENT(errcode, dls_error),
20911 DLS_ENT(errmsg, dls_empty),
20912 DLS_ENT(exec, dls_error),
20913 DLS_ENT(finalize, dls_error),
20914 DLS_ENT(free, free),
20915 DLS_ENT(free_table, dls_void),
20916 DLS_ENT(get_table, dls_error),
20917 DLS_ENT(interrupt, dls_void),
20918 DLS_ENT(key, dls_error),
20919 DLS_ENT(last_insert_rowid, dls_0LL),
20920 DLS_ENT(libversion, dls_empty),
20921 DLS_ENT(load_extension, dls_error),
20922 DLS_ENT(malloc, malloc),
20923 DLS_ENT(mprintf, dls_null),
20924 DLS_ENT(open, dls_error),
20925 DLS_ENT(open16, dls_error),
20926 DLS_ENT(open_v2, dls_error),
20927 DLS_ENT(prepare, dls_error),
20928 DLS_ENT(prepare_v2, dls_error),
20929 DLS_ENT(profile, dls_null),
20930 DLS_ENT(realloc, realloc),
20931 DLS_ENT(rekey, dls_error),
20932 DLS_ENT(reset, dls_error),
20933 DLS_ENT(result_blob, dls_void),
20934 DLS_ENT(result_error, dls_void),
20935 DLS_ENT(result_int, dls_void),
20936 DLS_ENT(result_null, dls_void),
20937 DLS_ENT(step, dls_error),
20938#if defined(_WIN32) || defined(_WIN64)
20939 DLS_ENT3(strnicmp, xstrnicmp, _strnicmp),
20940#else
20941 DLS_ENT3(strnicmp, xstrnicmp, strncasecmp),
20942#endif
20943 DLS_ENT(table_column_metadata, dls_error),
20944 DLS_ENT(trace, dls_null),
20945 DLS_ENT(user_data, dls_null),
20946 DLS_ENT(value_blob, dls_null),
20947 DLS_ENT(value_bytes, dls_0),
20948 DLS_ENT(value_text, dls_empty),
20949 DLS_ENT(value_type, dls_snull),
20950 DLS_END
20951};
20952
20953#if defined(_WIN32) || defined(_WIN64)
20954
20955static HMODULE sqlite3_dll = 0;
20956
20957static void
20958dls_init(void)
20959{
20960 int i;
20961 static const char *dll_names[] = {
20962 "System.Data.SQLite.dll",
20963 "sqlite3.dll",
20964 NULL,
20965 };
20966
20967 i = 0;
20968 while (dll_names[i]) {
20969 sqlite3_dll = LoadLibrary(dll_names[i]);
20970 if (sqlite3_dll) {
20971 break;
20972 }
20973 ++i;
20974 }
20975 i = 0;
20976 while (dls_nametab[i].name) {
20977 void *func = 0, **loc;
20978
20979 if (sqlite3_dll) {
20980 func = (void *) GetProcAddress(sqlite3_dll, dls_nametab[i].name);
20981 }
20982 if (!func) {
20983 func = dls_nametab[i].func;
20984 }
20985 loc = (void **) ((char *) &dls_funcs + dls_nametab[i].offset);
20986 *loc = func;
20987 ++i;
20988 }
20989 if (!sqlite3_dll) {
20990 char buf[MAXPATHLEN], msg[MAXPATHLEN];
20991
20992 LoadString(hModule, IDS_DRVTITLE, buf, sizeof (buf));
20993 LoadString(hModule, IDS_DLLERR, msg, sizeof (msg));
20994 MessageBox(NULL, msg, buf,
20995 MB_ICONEXCLAMATION | MB_OK | MB_TASKMODAL |
20996 MB_SETFOREGROUND);
20997 }
20998}
20999
21000static void
21001dls_fini(void)
21002{
21003 if (sqlite3_dll) {
21004 FreeLibrary(sqlite3_dll);
21005 sqlite3_dll = 0;
21006 }
21007}
21008
21009#else
21010
21011#include <dlfcn.h>
21012
21013static void *libsqlite3_so = 0;
21014
21015void
21016dls_init(void)
21017{
21018 int i;
21019
21020 libsqlite3_so = dlopen("libsqlite3.so.0", RTLD_NOW | RTLD_GLOBAL);
21021 i = 0;
21022 while (dls_nametab[i].name) {
21023 void *func = 0, **loc;
21024
21025 if (libsqlite3_so) {
21026 func = dlsym(libsqlite3_so, dls_nametab[i].name);
21027 }
21028 if (!func) {
21029 func = dls_nametab[i].func;
21030 }
21031 loc = (void **) ((char *) &dls_funcs + dls_nametab[i].offset);
21032 *loc = func;
21033 ++i;
21034 }
21035 if (!libsqlite3_so) {
21036 const char errmsg[] = "SQLite3 shared library not found.\n";
21037
21038 write(2, errmsg, sizeof (errmsg) - 1);
21039 }
21040}
21041
21042void
21043dls_fini(void)
21044{
21045 if (libsqlite3_so) {
21046 dlclose(libsqlite3_so);
21047 libsqlite3_so = 0;
21048 }
21049}
21050
21051#endif
21052
21053#endif
21054
21055/*
21056 * Local Variables:
21057 * mode: c
21058 * c-basic-offset: 4
21059 * fill-column: 78
21060 * tab-width: 8
21061 * End:
21062 */
static int quiet
Definition inst.c:60
static BOOL InUn(int remove, char *drivername, char *dllname, char *dll2name, char *dsname)
Driver installer/uninstaller.
Definition inst.c:153
#define SCOL_VARCHAR
static int getmdays(int year, int month)
Return number of month days.
static COL procColSpec3[]
static SQLRETURN drvgetstmtattr(SQLHSTMT stmt, SQLINTEGER attr, SQLPOINTER val, SQLINTEGER bufmax, SQLINTEGER *buflen)
Internal get option of HSTMT.
SQLRETURN SQL_API SQLCloseCursor(SQLHSTMT stmt)
Close open cursor.
SQLRETURN SQL_API SQLFreeConnect(SQLHDBC dbc)
Free connection (HDBC).
static SQLRETURN drvfreeenv(SQLHENV env)
Internal free HENV.
SQLRETURN SQL_API SQLSetPos(SQLHSTMT stmt, SQLSETPOSIROW row, SQLUSMALLINT op, SQLUSMALLINT lock)
Set position on result in HSTMT.
SQLRETURN SQL_API SQLSpecialColumnsW(SQLHSTMT stmt, SQLUSMALLINT id, SQLWCHAR *cat, SQLSMALLINT catLen, SQLWCHAR *schema, SQLSMALLINT schemaLen, SQLWCHAR *table, SQLSMALLINT tableLen, SQLUSMALLINT scope, SQLUSMALLINT nullable)
Retrieve information about indexed columns (UNICODE version).
static SQLRETURN drvprimarykeys(SQLHSTMT stmt, SQLCHAR *cat, SQLSMALLINT catLen, SQLCHAR *schema, SQLSMALLINT schemaLen, SQLCHAR *table, SQLSMALLINT tableLen)
Internal retrieve information about indexed columns.
static SQLRETURN nomem(STMT *s)
Report S1000 (out of memory) SQL error given STMT.
SQLRETURN SQL_API SQLSetStmtAttrW(SQLHSTMT stmt, SQLINTEGER attr, SQLPOINTER val, SQLINTEGER buflen)
Set option on HSTMT (UNICODE version).
static SQLRETURN setupparbuf(STMT *s, BINDPARM *p)
Setup parameter buffer for deferred parameter.
SQLRETURN SQL_API SQLGetEnvAttr(SQLHENV env, SQLINTEGER attr, SQLPOINTER val, SQLINTEGER len, SQLINTEGER *lenp)
Get information of HENV.
SQLRETURN SQL_API SQLSetStmtOptionW(SQLHSTMT stmt, SQLUSMALLINT opt, SETSTMTOPTION_LAST_ARG_TYPE param)
Set option on HSTMT (UNICODE version).
#define xfree(x)
static SQLRETURN setposbind(STMT *s, sqlite3_stmt *stmt, int i, int si, int rsi)
Internal handler to setup parameters for positional updates from bound user buffers.
#define SETSTMTOPTION_LAST_ARG_TYPE
static SQLWCHAR * uc_strncpy(SQLWCHAR *dest, SQLWCHAR *src, int len)
Copy UNICODE string like strncpy().
static void dbtrace(void *arg, const char *msg, sqlite_uint64 et)
SQLite trace or profile callback.
#define HSTMT_LOCK(hdbc)
SQLRETURN SQL_API SQLSetDescRec(SQLHDESC handle, SQLSMALLINT recno, SQLSMALLINT type, SQLSMALLINT subtype, SQLLEN len, SQLSMALLINT prec, SQLSMALLINT scale, SQLPOINTER data, SQLLEN *strlen, SQLLEN *indicator)
Function not implemented.
static SQLRETURN drvendtran(SQLSMALLINT type, SQLHANDLE handle, SQLSMALLINT comptype)
Internal commit or rollback transaction.
static void freeresult(STMT *s, int clrcols)
Free statement's result.
#define ENV_MAGIC
SQLRETURN SQL_API SQLConnectW(SQLHDBC dbc, SQLWCHAR *dsn, SQLSMALLINT dsnLen, SQLWCHAR *uid, SQLSMALLINT uidLen, SQLWCHAR *pwd, SQLSMALLINT pwdLen)
Connect to SQLite database.
static void getmd(const char *typename, int sqltype, int *mp, int *dp)
Get maximum display size and number of digits after decimal point from field type specification.
static SQLRETURN drvdriverconnect(SQLHDBC dbc, SQLHWND hwnd, SQLCHAR *connIn, SQLSMALLINT connInLen, SQLCHAR *connOut, SQLSMALLINT connOutMax, SQLSMALLINT *connOutLen, SQLUSMALLINT drvcompl)
Internal standalone (w/o driver manager) database connect.
static char * s3stmt_coltype(sqlite3_stmt *s3stmt, int col, DBC *d, int *guessed_types)
Find out column type.
#define DRIVER_VER_INFO
static const char digit_chars[]
SQLRETURN SQL_API SQLGetStmtOption(SQLHSTMT stmt, SQLUSMALLINT opt, SQLPOINTER param)
Get option of HSTMT.
SQLRETURN SQL_API SQLGetConnectAttrW(SQLHDBC dbc, SQLINTEGER attr, SQLPOINTER val, SQLINTEGER bufmax, SQLINTEGER *buflen)
Get connect attribute of HDBC (UNICODE version).
SQLRETURN SQL_API SQLAllocConnect(SQLHENV env, SQLHDBC *dbc)
Allocate HDBC.
static SQLRETURN drvspecialcolumns(SQLHSTMT stmt, SQLUSMALLINT id, SQLCHAR *cat, SQLSMALLINT catLen, SQLCHAR *schema, SQLSMALLINT schemaLen, SQLCHAR *table, SQLSMALLINT tableLen, SQLUSMALLINT scope, SQLUSMALLINT nullable)
Internal retrieve information about indexed columns.
static SQLRETURN drvgetinfo(SQLHDBC dbc, SQLUSMALLINT type, SQLPOINTER val, SQLSMALLINT valMax, SQLSMALLINT *valLen)
Internal return information about what this ODBC driver supports.
static COL fkeySpec3[]
static SQLRETURN mkbindcols(STMT *s, int ncols)
Reallocate space for bound columns.
#define xstrdup(x)
static void freedyncols(STMT *s)
Free dynamically allocated column descriptions of STMT.
static SQLRETURN setupparam(STMT *s, char *sql, int pnum)
Setup SQLite3 parameter for statement parameter.
static COL colSpec3[]
SQLRETURN SQL_API SQLGetDescFieldW(SQLHDESC handle, SQLSMALLINT recno, SQLSMALLINT fieldid, SQLPOINTER value, SQLINTEGER buflen, SQLINTEGER *strlen)
Function not implemented.
static void convJD2HMS(double jd, TIME_STRUCT *ts, int *fp)
Convert julian day to hour/minute/second.
SQLRETURN SQL_API SQLProceduresW(SQLHSTMT stmt, SQLWCHAR *catalog, SQLSMALLINT catalogLen, SQLWCHAR *schema, SQLSMALLINT schemaLen, SQLWCHAR *proc, SQLSMALLINT procLen)
Retrieve information about stored procedures (UNICODE version).
static void mktypeinfo(STMT *s, int row, int asize, char *typename, int type, int tind)
Internal function to build up data type information as row in result set.
SQLRETURN SQL_API SQLDescribeParam(SQLHSTMT stmt, SQLUSMALLINT pnum, SQLSMALLINT *dtype, SQLULEN *size, SQLSMALLINT *decdigits, SQLSMALLINT *nullable)
Return information about parameter.
static SQLRETURN drvgetconnectoption(SQLHDBC dbc, SQLUSMALLINT opt, SQLPOINTER param)
Internal get connect option of HDBC.
static int namematch(char *str, char *pat, int esc)
SQL LIKE string match with optional backslash escape handling.
#define drvgetgpps(d)
static SQLRETURN mkresultset(HSTMT stmt, COL *colspec, int ncols, COL *colspec3, int ncols3, int *nret)
Setup empty result set from constant column specification.
static COL statSpec3[]
SQLRETURN SQL_API SQLTablesW(SQLHSTMT stmt, SQLWCHAR *cat, SQLSMALLINT catLen, SQLWCHAR *schema, SQLSMALLINT schemaLen, SQLWCHAR *table, SQLSMALLINT tableLen, SQLWCHAR *type, SQLSMALLINT typeLen)
Retrieve information on tables and/or views.
SQLRETURN SQL_API SQLTransact(SQLHENV env, SQLHDBC dbc, SQLUSMALLINT type)
Commit or rollback transaction.
SQLRETURN SQL_API SQLNumParams(SQLHSTMT stmt, SQLSMALLINT *nparam)
Return number of parameters.
static const char * xdigits
static COL scolSpec2[]
Columns for result set of SQLSpecialColumns().
SQLRETURN SQL_API SQLGetTypeInfoW(SQLHSTMT stmt, SQLSMALLINT sqltype)
Return data type information (UNICODE version).
static int drvgettable(STMT *s, const char *sql, char ***resp, int *nrowp, int *ncolp, char **errp, int nparam, BINDPARM *p)
static int TOLOWER(int c)
SQLRETURN SQL_API SQLGetDiagFieldW(SQLSMALLINT htype, SQLHANDLE handle, SQLSMALLINT recno, SQLSMALLINT id, SQLPOINTER info, SQLSMALLINT buflen, SQLSMALLINT *stringlen)
Get error record given handle (HDBC or HSTMT).
SQLRETURN SQL_API SQLSetConnectAttrW(SQLHDBC dbc, SQLINTEGER attr, SQLPOINTER val, SQLINTEGER len)
Set connect attribute of HDBC (UNICODE version).
static void s3bind(DBC *d, sqlite3_stmt *stmt, int nparams, BINDPARM *p)
struct tblres TBLRES
static SQLRETURN drvunimpldbc(HDBC dbc)
Report IM001 (not implemented) SQL error code for HDBC.
#define SET_EXISTS(x)
static COL procColSpec2[]
Columns for result set of SQLProcedureColumns().
static SQLRETURN drvsetstmtoption(SQLHSTMT stmt, SQLUSMALLINT opt, SQLUINTEGER param)
Internal set option on HSTMT.
static SQLRETURN drvgetdiagfield(SQLSMALLINT htype, SQLHANDLE handle, SQLSMALLINT recno, SQLSMALLINT id, SQLPOINTER info, SQLSMALLINT buflen, SQLSMALLINT *stringlen)
Get error record given handle (HDBC or HSTMT).
static SQLRETURN drvfreeconnect(SQLHDBC dbc)
Internal free connection (HDBC).
static SQLRETURN drvallocconnect(SQLHENV env, SQLHDBC *dbc)
Internal allocate HDBC.
static void fixupdyncols(STMT *s, DBC *d)
Fixup column information for a running statement.
static SQLRETURN getrowdata(STMT *s, SQLUSMALLINT col, SQLSMALLINT otype, SQLPOINTER val, SQLINTEGER len, SQLLEN *lenp, int partial)
Internal function to retrieve row data, used by SQLFetch() and friends and SQLGetData().
SQLRETURN SQL_API SQLAllocStmt(SQLHDBC dbc, SQLHSTMT *stmt)
Allocate HSTMT given HDBC.
static COL scolSpec3[]
static void uc_free(void *str)
Free converted UTF8 or UNICODE string.
static SQLWCHAR * uc_from_utf(unsigned char *str, int len)
Make UNICODE string from UTF8 string.
SQLRETURN SQL_API SQLGetFunctions(SQLHDBC dbc, SQLUSMALLINT func, SQLUSMALLINT *flags)
Return information about supported ODBC API functions.
SQLRETURN SQL_API SQLNativeSqlW(SQLHSTMT stmt, SQLWCHAR *sqlin, SQLINTEGER sqlinLen, SQLWCHAR *sql, SQLINTEGER sqlMax, SQLINTEGER *sqlLen)
Translate SQL string (UNICODE version).
static SQLRETURN drvtables(SQLHSTMT stmt, SQLCHAR *cat, SQLSMALLINT catLen, SQLCHAR *schema, SQLSMALLINT schemaLen, SQLCHAR *table, SQLSMALLINT tableLen, SQLCHAR *type, SQLSMALLINT typeLen)
Retrieve information on tables and/or views.
#define COLATTRIBUTE_LAST_ARG_TYPE
SQLRETURN SQL_API SQLSetStmtOption(SQLHSTMT stmt, SQLUSMALLINT opt, SETSTMTOPTION_LAST_ARG_TYPE param)
Set option on HSTMT.
static int str2timestamp(int jdconv, char *str, TIMESTAMP_STRUCT *tss)
Convert string to ODBC TIMESTAMP_STRUCT.
SQLRETURN SQL_API SQLFreeHandle(SQLSMALLINT type, SQLHANDLE h)
Free a HENV, HDBC, or HSTMT handle.
static int setsqliteopts(sqlite3 *x, DBC *d)
Set SQLite options (PRAGMAs) given SQLite handle.
#define DEAD_MAGIC
SQLRETURN SQL_API SQLNumResultCols(SQLHSTMT stmt, SQLSMALLINT *ncols)
Return number of columns of result set given HSTMT.
SQLRETURN SQL_API SQLGetStmtAttrW(SQLHSTMT stmt, SQLINTEGER attr, SQLPOINTER val, SQLINTEGER bufmax, SQLINTEGER *buflen)
Get option of HSTMT (UNICODE version).
static SQLRETURN drvgetcursorname(SQLHSTMT stmt, SQLCHAR *cursor, SQLSMALLINT buflen, SQLSMALLINT *lenp)
Internal function to get cursor name of STMT.
static SQLRETURN drvgetstmtoption(SQLHSTMT stmt, SQLUSMALLINT opt, SQLPOINTER param)
Internal get option of HSTMT.
static SQLRETURN drvstatistics(SQLHSTMT stmt, SQLCHAR *cat, SQLSMALLINT catLen, SQLCHAR *schema, SQLSMALLINT schemaLen, SQLCHAR *table, SQLSMALLINT tableLen, SQLUSMALLINT itype, SQLUSMALLINT resv)
Internal return statistic information on table indices.
SQLRETURN SQL_API SQLGetData(SQLHSTMT stmt, SQLUSMALLINT col, SQLSMALLINT type, SQLPOINTER val, SQLLEN len, SQLLEN *lenp)
Retrieve row data after fetch.
static SQLRETURN s3stmt_start(STMT *s)
Start sqlite statement for execution of SELECT statement.
static char * strdup_(const char *str)
Duplicate string using xmalloc().
static SQLRETURN setposibind(STMT *s, sqlite3_stmt *stmt, int i, int si, int rsi)
Internal handler to setup parameters for positional updates from driver side result set.
static void uc_from_utf_buf(unsigned char *str, int len, SQLWCHAR *uc, int ucLen)
Make UNICODE string from UTF8 string into buffer.
static COL colSpec2[]
Columns for result set of SQLColumns().
static void dbattas(DBC *d, char *attas)
Perform ATTACH commands to same database file.
#define WCHARSUPPORT
static SQLRETURN noconn(STMT *s)
Report S1000 (not connected) SQL error given STMT.
static int drvgettable_row(TBLRES *t, int ncol, int rc)
SQLRETURN SQL_API SQLTablePrivilegesW(SQLHSTMT stmt, SQLWCHAR *catalog, SQLSMALLINT catalogLen, SQLWCHAR *schema, SQLSMALLINT schemaLen, SQLWCHAR *table, SQLSMALLINT tableLen)
Retrieve privileges on tables and/or views (UNICODE version).
static SQLRETURN drvsetconnectoption(SQLHDBC dbc, SQLUSMALLINT opt, SQLUINTEGER param)
Internal set option on HDBC.
static SQLRETURN freeparams(STMT *s)
Clear out parameter bindings, if any.
SQLRETURN SQL_API SQLSetScrollOptions(SQLHSTMT stmt, SQLUSMALLINT concur, SQLLEN rowkeyset, SQLUSMALLINT rowset)
Function not implemented.
static SQLRETURN endtran(DBC *d, SQLSMALLINT comptype, int force)
Internal commit or rollback transaction.
static SQLRETURN drvallocenv(SQLHENV *env)
Internal allocate HENV.
SQLRETURN SQL_API SQLAllocHandle(SQLSMALLINT type, SQLHANDLE input, SQLHANDLE *output)
Allocate a HENV, HDBC, or HSTMT handle.
static COL statSpec2[]
Columns for result set of SQLStatistics().
#define PTRDIFF_T
static int unescpat(char *str)
Unescape search pattern for e.g.
static SQLRETURN drvconnect(SQLHDBC dbc, SQLCHAR *dsn, SQLSMALLINT dsnLen, char *pwd, int pwdLen, int isu)
Internal connect to SQLite database.
SQLRETURN SQL_API SQLCopyDesc(SQLHDESC source, SQLHDESC target)
Function not implemented.
SQLRETURN SQL_API SQLSetParam(SQLHSTMT stmt, SQLUSMALLINT par, SQLSMALLINT type, SQLSMALLINT sqltype, SQLULEN coldef, SQLSMALLINT scale, SQLPOINTER val, SQLLEN *nval)
Set information on parameter.
static SQLRETURN drvgetconnectattr(SQLHDBC dbc, SQLINTEGER attr, SQLPOINTER val, SQLINTEGER bufmax, SQLINTEGER *buflen)
Internal get connect attribute of HDBC.
static COL colPrivSpec3[]
SQLRETURN SQL_API SQLDriversW(SQLHENV env, SQLUSMALLINT dir, SQLWCHAR *drvdesc, SQLSMALLINT descmax, SQLSMALLINT *desclenp, SQLWCHAR *drvattr, SQLSMALLINT attrmax, SQLSMALLINT *attrlenp)
Function not implemented.
SQLRETURN SQL_API SQLDescribeColW(SQLHSTMT stmt, SQLUSMALLINT col, SQLWCHAR *name, SQLSMALLINT nameMax, SQLSMALLINT *nameLen, SQLSMALLINT *type, SQLULEN *size, SQLSMALLINT *digits, SQLSMALLINT *nullable)
Describe column information (UNICODE version).
static SQLRETURN drvbindcol(SQLHSTMT stmt, SQLUSMALLINT col, SQLSMALLINT type, SQLPOINTER val, SQLLEN max, SQLLEN *lenp)
Internal bind C variable to column of result set.
static SQLRETURN drvsetstmtattr(SQLHSTMT stmt, SQLINTEGER attr, SQLPOINTER val, SQLINTEGER buflen)
Internal set option on HSTMT.
SQLRETURN SQL_API SQLFreeStmt(SQLHSTMT stmt, SQLUSMALLINT opt)
Free HSTMT.
static const char upper_chars[]
static SQLRETURN drvgettypeinfo(SQLHSTMT stmt, SQLSMALLINT sqltype)
Internal return data type information.
SQLRETURN SQL_API SQLFetchScroll(SQLHSTMT stmt, SQLSMALLINT orient, SQLLEN offset)
Fetch result row with scrolling.
SQLRETURN SQL_API SQLParamData(SQLHSTMT stmt, SQLPOINTER *pind)
Retrieve next parameter for sending data to executing query.
SQLRETURN SQL_API SQLPutData(SQLHSTMT stmt, SQLPOINTER data, SQLLEN len)
Put (partial) parameter data into executing statement.
static const char lower_chars[]
SQLRETURN SQL_API SQLGetStmtOptionW(SQLHSTMT stmt, SQLUSMALLINT opt, SQLPOINTER param)
Get option of HSTMT (UNICODE version).
static int getdsnattr(char *dsn, char *attr, char *out, int outLen)
Handling of SQLConnect() connection attributes for standalone operation without driver manager.
static COL tableSpec2[]
Columns for result set of SQLTables().
#define array_size(x)
SQLRETURN SQL_API SQLExtendedFetch(SQLHSTMT stmt, SQLUSMALLINT orient, SQLROWOFFSET offset, SQLROWSETSIZE *rowcount, SQLUSMALLINT *rowstatus)
Fetch result row with scrolling and row status.
static void dbtraceapi(DBC *d, char *fn, const char *sql)
Trace function for SQLite API calls.
SQLRETURN SQL_API SQLBrowseConnectW(SQLHDBC dbc, SQLWCHAR *connin, SQLSMALLINT conninLen, SQLWCHAR *connout, SQLSMALLINT connoutMax, SQLSMALLINT *connoutLen)
Function not implemented.
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)
Retrieve information about primary/foreign keys (UNICODE version).
static int s3stmt_step(STMT *s)
Do one sqlite statement step gathering one result row.
static int dserr(dstr *dsp)
Check error on dynamic string.
static SQLRETURN drvfreestmt(SQLHSTMT stmt, SQLUSMALLINT opt)
Internal function to perform certain kinds of free/close on STMT.
static SQLRETURN drvdescribecol(SQLHSTMT stmt, SQLUSMALLINT col, SQLCHAR *name, SQLSMALLINT nameMax, SQLSMALLINT *nameLen, SQLSMALLINT *type, SQLULEN *size, SQLSMALLINT *digits, SQLSMALLINT *nullable)
Internal describe column information.
static double ln_strtod(const char *data, char **endp)
Internal locale neutral strtod function.
static void s3stmt_drop(STMT *s)
Drop running sqlite statement in STMT.
static char * uc_to_utf_c(SQLWCHAR *str, int len)
Make UTF8 string from UNICODE string.
SQLRETURN SQL_API SQLGetCursorNameW(SQLHSTMT stmt, SQLWCHAR *cursor, SQLSMALLINT buflen, SQLSMALLINT *lenp)
Get cursor name of STMT (UNICODE version).
static const char * dsval(dstr *dsp)
Return dynamic string's value.
SQLRETURN SQL_API SQLEndTran(SQLSMALLINT type, SQLHANDLE handle, SQLSMALLINT comptype)
Commit or rollback transaction.
static char * unquote(char *str)
Strip quotes from quoted string in-place.
#define strmak(dst, src, max, lenp)
static int uc_strlen(SQLWCHAR *str)
Return length of UNICODE string.
SQLRETURN SQL_API SQLSetCursorNameW(SQLHSTMT stmt, SQLWCHAR *cursor, SQLSMALLINT len)
Set cursor name on STMT (UNICODE version).
static COL pkeySpec3[]
SQLRETURN SQL_API SQLGetDiagRecW(SQLSMALLINT htype, SQLHANDLE handle, SQLSMALLINT recno, SQLWCHAR *sqlstate, SQLINTEGER *nativeerr, SQLWCHAR *msg, SQLSMALLINT buflen, SQLSMALLINT *msglen)
Get error message given handle (HENV, HDBC, or HSTMT) (UNICODE version).
static void dsfree(dstr *dsp)
Free dynamic string.
SQLRETURN SQL_API SQLBindParam(SQLHSTMT stmt, SQLUSMALLINT pnum, SQLSMALLINT vtype, SQLSMALLINT ptype, SQLULEN lenprec, SQLSMALLINT scale, SQLPOINTER val, SQLLEN *lenp)
Bind parameter on HSTMT.
static void setstat(STMT *s, int naterr, char *msg, char *st,...)
Set error message and SQL state on statement.
#define HDBC_LOCK(hdbc)
static SQLRETURN drvallocstmt(SQLHDBC dbc, SQLHSTMT *stmt)
Allocate HSTMT given HDBC (driver internal version).
static SQLRETURN drvsetconnectattr(SQLHDBC dbc, SQLINTEGER attr, SQLPOINTER val, SQLINTEGER len)
Internal set connect attribute of HDBC.
static int mapsqltype(const char *typename, int *nosign, int ov3, int nowchar, int dobigint)
Map SQL field type from string to ODBC integer type code.
#define DBC_MAGIC
static SQLRETURN drvputdata(SQLHSTMT stmt, SQLPOINTER data, SQLLEN len)
Internal put (partial) parameter data into executing statement.
SQLRETURN SQL_API SQLGetConnectOptionW(SQLHDBC dbc, SQLUSMALLINT opt, SQLPOINTER param)
Get connect option of HDBC (UNICODE version).
static void replilike(char *sql)
Replace ILIKE with LIKE in-place given query string.
static SQLRETURN dofetchbind(STMT *s, int rsi)
Internal: fetch and bind from statement's current row.
static SQLRETURN drvsetcursorname(SQLHSTMT stmt, SQLCHAR *cursor, SQLSMALLINT len)
Internal function to set cursor name on STMT.
struct dstr dstr
SQLRETURN SQL_API SQLParamOptions(SQLHSTMT stmt, SQLULEN rows, SQLULEN *rowp)
Function not implemented.
SQLRETURN SQL_API SQLColumnPrivilegesW(SQLHSTMT stmt, SQLWCHAR *catalog, SQLSMALLINT catalogLen, SQLWCHAR *schema, SQLSMALLINT schemaLen, SQLWCHAR *table, SQLSMALLINT tableLen, SQLWCHAR *column, SQLSMALLINT columnLen)
Retrieve privileges on columns (UNICODE version).
static SQLRETURN setupdyncols(STMT *s, sqlite3_stmt *s3stmt, int *ncolsp)
SQLRETURN SQL_API SQLFetch(SQLHSTMT stmt)
Fetch next result row.
SQLRETURN SQL_API SQLCancel(SQLHSTMT stmt)
Cancel HSTMT closing cursor.
static COL pkeySpec2[]
Columns for result set of SQLPrimaryKeys().
static COL typeSpec3[]
static SQLRETURN drvbindparam(SQLHSTMT stmt, SQLUSMALLINT pnum, SQLSMALLINT iotype, SQLSMALLINT buftype, SQLSMALLINT ptype, SQLUINTEGER coldef, SQLSMALLINT scale, SQLPOINTER data, SQLINTEGER buflen, SQLLEN *len)
Internal bind parameter on HSTMT.
static void dbloadext(DBC *d, char *exts)
Load SQLite extension modules, if any.
static void blob_import(sqlite3_context *ctx, int nargs, sqlite3_value **args)
SQLite function to import a BLOB from a file.
SQLRETURN SQL_API SQLBulkOperations(SQLHSTMT stmt, SQLSMALLINT oper)
Perform bulk operation on HSTMT.
static int str2time(int jdconv, char *str, TIME_STRUCT *ts)
Convert string to ODBC TIME_STRUCT.
static int getbool(char *string)
Get boolean flag from string.
static dstr * dsappendq(dstr *dsp, const char *str)
Append a string double quoted to dynamic string.
SQLRETURN SQL_API SQLSetEnvAttr(SQLHENV env, SQLINTEGER attr, SQLPOINTER val, SQLINTEGER len)
Set information in HENV.
#define xrealloc(x, y)
static int typeinfosort(const void *a, const void *b)
Helper function to sort type information.
#define ISDIGIT(c)
static SQLRETURN chkunbound(STMT *s)
Check for unbound result columns.
static int mapdeftype(int type, int stype, int nosign, int nowchar)
Map SQL_C_DEFAULT to proper C type.
static COL tableSpec3[]
static void freep(void *x)
Free memory given pointer to memory pointer.
static void blob_export(sqlite3_context *ctx, int nargs, sqlite3_value **args)
SQLite function to export a BLOB to a file.
SQLRETURN SQL_API SQLFreeEnv(SQLHENV env)
Free HENV.
static int busy_handler(void *udata, int count)
Busy callback for SQLite.
SQLRETURN SQL_API SQLSetDescFieldW(SQLHDESC handle, SQLSMALLINT recno, SQLSMALLINT fieldid, SQLPOINTER value, SQLINTEGER buflen)
Function not implemented.
#define xmalloc(x)
#define drvrelgpps(d)
#define HDBC_UNLOCK(hdbc)
static SQLRETURN starttran(STMT *s)
Start transaction when autocommit off.
#define verinfo(maj, min, lev)
static SQLRETURN setposrefr(STMT *s, int rsi)
Internal handler to refresh user buffers from driver side result set.
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)
Function not implemented.
#define min(a, b)
SQLRETURN SQL_API SQLAllocEnv(SQLHENV *env)
Allocate HENV.
static void freerows(char **rowp)
Free counted array of char pointers.
static COL tablePrivSpec3[]
static SQLRETURN drvexecute(SQLHSTMT stmt, int initial)
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)
Internal retrieve information about primary/foreign keys.
static void s3stmt_end_if(STMT *s)
Conditionally stop running sqlite statement.
static SQLRETURN drvcolattributes(SQLHSTMT stmt, SQLUSMALLINT col, SQLUSMALLINT id, SQLPOINTER val, SQLSMALLINT valMax, SQLSMALLINT *valLen, SQLLEN *val2)
Internal retrieve column attributes.
SQLRETURN SQL_API SQLGetInfoW(SQLHDBC dbc, SQLUSMALLINT type, SQLPOINTER val, SQLSMALLINT valMax, SQLSMALLINT *valLen)
Return information about what this ODBC driver supports.
SQLRETURN SQL_API SQLBindCol(SQLHSTMT stmt, SQLUSMALLINT col, SQLSMALLINT type, SQLPOINTER val, SQLLEN max, SQLLEN *lenp)
Bind C variable to column of result set.
static SQLRETURN drvbulkoperations(SQLHSTMT stmt, SQLSMALLINT op)
Internal perform bulk operation on HSTMT.
static SQLRETURN drvgetdiagrec(SQLSMALLINT htype, SQLHANDLE handle, SQLSMALLINT recno, SQLCHAR *sqlstate, SQLINTEGER *nativeerr, SQLCHAR *msg, SQLSMALLINT buflen, SQLSMALLINT *msglen)
Internal get error message given handle (HENV, HDBC, or HSTMT).
#define stringify(s)
static void s3stmt_end(STMT *s)
Stop running sqlite statement.
static SQLRETURN drvtableprivileges(SQLHSTMT stmt, SQLCHAR *cat, SQLSMALLINT catLen, SQLCHAR *schema, SQLSMALLINT schemaLen, SQLCHAR *table, SQLSMALLINT tableLen)
Retrieve privileges on tables and/or views.
static COL tablePrivSpec2[]
Columns for result set of SQLTablePrivileges().
static COL typeSpec2[]
Columns for result set of SQLGetTypeInfo().
static SQLRETURN dbopen(DBC *d, char *name, int isu, char *dsn, char *sflag, char *spflag, char *ntflag, char *jmode, char *busy)
Open SQLite database file given file name and flags.
#define ODBC_INI
SQLRETURN SQL_API SQLBindParameter(SQLHSTMT stmt, SQLUSMALLINT pnum, SQLSMALLINT iotype, SQLSMALLINT buftype, SQLSMALLINT ptype, SQLULEN coldef, SQLSMALLINT scale, SQLPOINTER data, SQLLEN buflen, SQLLEN *len)
Bind parameter on HSTMT.
static void dbtracerc(DBC *d, int rc, char *err)
Trace function for SQLite return codes.
static void convJD2YMD(double jd, DATE_STRUCT *ds)
Convert julian day to year/month/day.
static SQLRETURN drvsetpos(SQLHSTMT stmt, SQLSETPOSIROW row, SQLUSMALLINT op, SQLUSMALLINT lock)
Internal set position on result in HSTMT.
static dstr * dsappend(dstr *dsp, const char *str)
Append string to dynamic string.
SQLRETURN SQL_API SQLDisconnect(SQLHDBC dbc)
Disconnect given HDBC.
SQLRETURN SQL_API SQLSetConnectOptionW(SQLHDBC dbc, SQLUSMALLINT opt, SQLULEN param)
Set option on HDBC (UNICODE version).
SQLRETURN SQL_API SQLPrimaryKeysW(SQLHSTMT stmt, SQLWCHAR *cat, SQLSMALLINT catLen, SQLWCHAR *schema, SQLSMALLINT schemaLen, SQLWCHAR *table, SQLSMALLINT tableLen)
Retrieve information about indexed columns (UNICODE version).
static char * fixupsql(char *sql, int sqlLen, int cte, int *nparam, int *isselect, char **errmsg)
Fixup query string with optional parameter markers.
static void unbindcols(STMT *s)
Reset bound columns to unbound state.
static SQLRETURN drvdisconnect(SQLHDBC dbc)
Internal disconnect given HDBC.
static int checkddl(char *sql)
Check if query is a DDL statement.
static SQLRETURN drvfetchscroll(SQLHSTMT stmt, SQLSMALLINT orient, SQLINTEGER offset)
Internal fetch function for SQLFetchScroll() and SQLExtendedFetch().
static SQLRETURN drvunimplstmt(HSTMT stmt)
Report IM001 (not implemented) SQL error code for HSTMT.
static void setstatd(DBC *d, int naterr, char *msg, char *st,...)
Set error message and SQL state on DBC.
static COL colPrivSpec2[]
Columns for result set of SQLColumnPrivileges().
SQLRETURN SQL_API SQLProcedureColumnsW(SQLHSTMT stmt, SQLWCHAR *catalog, SQLSMALLINT catalogLen, SQLWCHAR *schema, SQLSMALLINT schemaLen, SQLWCHAR *proc, SQLSMALLINT procLen, SQLWCHAR *column, SQLSMALLINT columnLen)
Retrieve information about columns in result set of stored procedures (UNICODE version).
#define ISSPACE(c)
static SQLRETURN drvcolumns(SQLHSTMT stmt, SQLCHAR *cat, SQLSMALLINT catLen, SQLCHAR *schema, SQLSMALLINT schemaLen, SQLCHAR *table, SQLSMALLINT tableLen, SQLCHAR *col, SQLSMALLINT colLen)
Internal retrieve column information on table.
static COL procSpec2[]
Columns for result set of SQLProcedures().
SQLRETURN SQL_API SQLColumnsW(SQLHSTMT stmt, SQLWCHAR *cat, SQLSMALLINT catLen, SQLWCHAR *schema, SQLSMALLINT schemaLen, SQLWCHAR *table, SQLSMALLINT tableLen, SQLWCHAR *col, SQLSMALLINT colLen)
Retrieve column information on table (UNICODE version).
#define HSTMT_UNLOCK(hdbc)
SQLRETURN SQL_API SQLDataSourcesW(SQLHENV env, SQLUSMALLINT dir, SQLWCHAR *srvname, SQLSMALLINT buflen1, SQLSMALLINT *lenp1, SQLWCHAR *desc, SQLSMALLINT buflen2, SQLSMALLINT *lenp2)
Function not implemented.
static char * uc_to_utf(SQLWCHAR *str, int len)
Make UTF8 string from UNICODE string.
static const char space_chars[]
#define SCOL_CHAR
SQLRETURN SQL_API SQLStatisticsW(SQLHSTMT stmt, SQLWCHAR *cat, SQLSMALLINT catLen, SQLWCHAR *schema, SQLSMALLINT schemaLen, SQLWCHAR *table, SQLSMALLINT tableLen, SQLUSMALLINT itype, SQLUSMALLINT resv)
Return statistic information on table indices (UNICODE version).
static COL fkeySpec2[]
Columns for result set of SQLForeignKeys().
SQLRETURN SQL_API SQLRowCount(SQLHSTMT stmt, SQLLEN *nrows)
Return number of affected rows of HSTMT.
static SQLRETURN freestmt(HSTMT stmt)
static int findcol(char **cols, int ncols, char *name)
Find column given name in string array.
static int str2date(int jdconv, char *str, DATE_STRUCT *ds)
Convert string to ODBC DATE_STRUCT.
static COL procSpec3[]
#define max(a, b)
Header file for SQLite3 ODBC driver.
#define SQLULEN
Definition sqlite3odbc.h:68
#define SQLROWOFFSET
Definition sqlite3odbc.h:80
#define SQLLEN
Definition sqlite3odbc.h:62
#define SQLROWSETSIZE
Definition sqlite3odbc.h:84
#define SQL_API
Definition sqlite3odbc.h:58
#define SQLSETPOSIROW
Definition sqlite3odbc.h:76
Internal structure for bound column (SQLBindCol).
SQLINTEGER max
Max.
SQLLEN * lenp
Value return, actual size of value buffer.
SQLPOINTER valp
Value buffer.
int offs
Byte offset for SQLGetData()
SQLSMALLINT type
ODBC type.
int index
Index of column in result.
Internal structure for bound parameter (SQLBindParameter).
double s3dval
SQLite3 float value.
void * param0
Parameter buffer, initial value.
int need
True when SQL_LEN_DATA_AT_EXEC.
int s3type
SQLite3 type.
int scale
from SQLBindParameter()
int len
Offset/length for SQLParamData()/SQLPutData()
void * param
Parameter buffer.
void * parbuf
Buffer for SQL_LEN_DATA_AT_EXEC etc.
int inc
Increment for paramset size > 1.
SQLLEN * lenp0
Actual size of parameter buffer, initial value.
void * s3val
SQLite3 value buffer.
int stype
ODBC and SQL types.
SQLLEN max
Max.
char strbuf[64]
String buffer for scalar data.
int bound
True when SQLBindParameter() called.
sqlite_int64 s3lival
SQLite3 64bit integer value.
int s3ival
SQLite3 integer value.
SQLLEN * lenp
Actual size of parameter buffer.
int s3size
SQLite3 size.
Internal structure to describe a column in a result set.
char * column
Column name.
char * label
Column label or NULL.
int nosign
Unsigned type.
char * typename
Column type name or NULL.
int notnull
NOT NULL constraint on column.
int ispk
Flag for primary key (> 0)
int prec
Precision of column.
char * table
Table name.
char * db
Database name.
int type
Data type of column.
int isrowid
Flag for ROWID column (> 0)
int scale
Scale of column.
int autoinc
AUTO_INCREMENT column.
int size
Size of column.
int index
Index of column in result.
Driver internal structure for environment (HENV).
Definition sqlite3odbc.h:96
int pool
True for SQL_CP_ONE_PER_DRIVER.
Definition sqlite3odbc.h:99
int ov3
True for SQL_OV_ODBC3.
Definition sqlite3odbc.h:98
int magic
Magic cookie.
Definition sqlite3odbc.h:97
struct dbc * dbcs
Pointer to first DBC.
Driver internal structure for database connection (HDBC).
int busyint
Interrupt busy handler from SQLCancel()
char * pwd
Password or NULL.
int s3stmt_needmeta
True to get meta data in s3stmt_step().
int nowchar
Don't try to use WCHAR.
struct stmt * cur_s3stmt
Current STMT executing sqlite statement.
long t0
Start time for SQLITE busy handler.
int curtype
Default cursor type.
int step_enable
True for sqlite_compile/step/finalize.
int intrans
True when transaction started.
char * dsn
ODBC data source name.
struct stmt * stmt
STMT list of this DBC.
int pwdLen
Length of password.
int * ov3
True for SQL_OV_ODBC3.
int magic
Magic cookie.
FILE * trace
sqlite3_trace() file pointer or NULL
int oemcp
True for Win32 OEM CP translation.
int longnames
Don't shorten column names.
int trans_disable
True for no transaction support.
ENV * env
Pointer to environment.
int dobigint
Force SQL_BIGINT for INTEGER columns.
int fksupport
Foreign keys on or off.
int ilike
True for ILIKE fixup.
int naterr
Native error code.
char sqlstate[6]
SQL state for SQLError()
int version
SQLITE version number.
int autocommit
Auto commit state.
int jdconv
True for julian day conversion.
struct dbc * next
Pointer to next DBC.
char * dbname
SQLITE database name.
int shortnames
Always use short column names.
SQLCHAR logmsg[1024]
Message for SQLError()
int ov3val
True for SQL_OV_ODBC3.
int nocreat
Don't auto create database file.
sqlite3 * sqlite
SQLITE database handle.
int timeout
Lock timeout value.
Internal structure representing dynamic strings.
int oom
True when out of memory.
int len
Current length.
int max
Maximum length of buffer.
char buffer[1]
String buffer.
Driver internal structure representing SQL statement (HSTMT).
SQLUSMALLINT * row_status0
Internal status array.
int * ov3
True for SQL_OV_ODBC3.
SQLUSMALLINT row_status1
Internal status array for 1 row rowsets.
BINDCOL * bindcols
Array of bound columns.
int naterr
Native error code.
SQLULEN * parm_bind_offs
SQL_ATTR_PARAM_BIND_OFFSET_PTR.
int dcols
Number of entries in dyncols.
SQLULEN bind_type
SQL_ATTR_ROW_BIND_TYPE.
BINDCOL bkmrkcol
Bookmark bound column.
int nbindparms
Number bound parameters.
COL * dyncols
Column array, but malloc()ed.
COL * cols
Result column array.
int dobigint
Force SQL_BIGINT for INTEGER columns.
int s3stmt_rownum
Current row number.
SQLCHAR logmsg[1024]
Message for SQLError()
int ncols
Number of result columns.
SQLULEN * row_count
Row count pointer.
SQLULEN paramset_count
Internal for paramset.
SQLUSMALLINT * parm_oper
SQL_ATTR_PARAM_OPERATION_PTR.
int nowchar[2]
Don't try to use WCHAR.
int binlen
Length of blob data.
int longnames
Don't shorten column names.
SQLULEN parm_bind_type
SQL_ATTR_PARAM_BIND_TYPE.
int guessed_types
Flag for drvprepare()/drvexecute()
char * bincell
Cache for blob data.
SQLCHAR cursorname[32]
Cursor name.
int nrows
Number of result rows.
SQLULEN paramset_size
SQL_ATTR_PARAMSET_SIZE.
int bkmrk
True when bookmarks used.
int * jdconv
True for julian day conversion.
SQLULEN * parm_proc
SQL_ATTR_PARAMS_PROCESSED_PTR.
sqlite3_stmt * s3stmt
SQLite statement handle or NULL.
SQLULEN * bind_offs
SQL_ATTR_ROW_BIND_OFFSET_PTR.
SQLULEN retr_data
SQL_ATTR_RETRIEVE_DATA.
SQLULEN max_rows
SQL_ATTR_MAX_ROWS.
HDBC dbc
Pointer to DBC.
BINDPARM * bindparms
Array of bound parameters.
int has_rowid
Flag for ROWID (>= 0 or -1)
SQLUSMALLINT * parm_status
SQL_ATTR_PARAMS_STATUS_PTR.
int one_tbl
Flag for single table (> 0)
int curtype
Cursor type.
int rowprs
Current start row of rowset.
char ** rows
2-dim array, result set
int isselect
int s3stmt_noreset
False when sqlite3_reset() needed.
SQLULEN rowset_size
Size of rowset.
int nparams
Number of parameters in query.
SQLUINTEGER paramset_nrows
Row count for paramset handling.
int nbindcols
Number of entries in bindcols.
SQLCHAR * query
Current query, raw string.
int * oemcp
True for Win32 OEM CP translation.
int rowp
Current result row.
char * bincache
Cache for blob data.
int pdcount
SQLParamData() counter.
SQLUSMALLINT * row_status
Row status pointer.
int has_pk
Flag for primary key (> 0)
char sqlstate[6]
SQL state for SQLError()
struct stmt * next
Linkage for STMT list in DBC.
int * ilike
True for ILIKE fixup.
SQLULEN row_count0
Row count.
void(* rowfree)()
Free function for rows.
SQLINTEGER * bkmrkptr
SQL_ATTR_FETCH_BOOKMARK_PTR.
Internal dynamic string buffer.
Definition blobtoxy.c:1212
Internal structure for managing driver's sqlite3_get_table() implementation.
sqlite3_stmt * stmt
SQLite3 statement pointer.
int rc
SQLite return code.
int ncol
number of columns in result array
char ** resarr
result array
int nrow
number of rows in result array
PTRDIFF_T ndata
index into result array
int nalloc
alloc'ed size of result array
STMT * s
Driver statement pointer.
char * errmsg
error message or NULL
static int initialized
Definition xpath.c:66

Generated on Sun Nov 26 2023 by doxygen.
Contact: chw@ch-werner.de