1 /**
2 * @file sqlite3odbc.c
3 * SQLite3 ODBC Driver main module.
4 *
5 * $Id: sqlite3odbc.c,v 1.179 2020/06/20 11:56:09 chw Exp chw $
6 *
7 * Copyright (c) 2004-2020 Christian Werner <chw@ch-werner.de>
8 *
9 * See the file "license.terms" for information on usage
10 * and redistribution of this file and for a
11 * DISCLAIMER OF ALL WARRANTIES.
12 */
13
14 #if defined(SQLITE_HAS_CODEC) && defined(SQLITE_API)
15 #undef WITH_SQLITE_DLLS
16 #undef SQLITE_DYNLOAD
17 #include "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)
32 static void dls_init(void);
33 static void dls_fini(void);
34 #else
35 void dls_init(void);
36 void dls_fini(void);
37 #endif
38
39 static 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
266 /**
267 * @typedef dstr
268 * @struct dstr
269 * Internal structure representing dynamic strings.
270 */
271
272 typedef struct dstr {
273 int len; /**< Current length. */
274 int max; /**< Maximum length of buffer. */
275 int oom; /**< True when out of memory. */
276 char buffer[1]; /**< String buffer. */
277 } dstr;
278
279 static const char *xdigits = "0123456789ABCDEFabcdef";
280
281 #ifdef MEMORY_DEBUG
282
283 static void *
xmalloc_(int n,char * file,int line)284 xmalloc_(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
306 static void *
xrealloc_(void * old,int n,char * file,int line)307 xrealloc_(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
343 static void
xfree_(void * x,char * file,int line)344 xfree_(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
369 static void
xfree__(void * x)370 xfree__(void *x)
371 {
372 xfree_(x, "unknown location", 0);
373 }
374
375 static char *
xstrdup_(const char * str,char * file,int line)376 xstrdup_(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
422 static 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)
433 static int strcasecmp_(const char *a, const char *b)
434 __attribute__((__unused__));
435 #endif
436
strcasecmp_(const char * a,const char * b)437 static 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)
538 extern void nvfs_init(void);
539 extern const char *nvfs_makevfs(const char *);
540 #endif
541
542 /*
543 * tolower() replacement w/o locale
544 */
545
546 static const char upper_chars[] = "ABCDEFGHIJKLMNOPQRSTUVWXYZ";
547 static const char lower_chars[] = "abcdefghijklmnopqrstuvwxyz";
548
549 static int
TOLOWER(int c)550 TOLOWER(int c)
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
566 static 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
575 static 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
585 static void dbtraceapi(DBC *d, char *fn, const char *sql);
586 static void freedyncols(STMT *s);
587 static void freeresult(STMT *s, int clrcols);
588 static void freerows(char **rowp);
589 static void unbindcols(STMT *s);
590 static void s3stmt_drop(STMT *s);
591
592 static SQLRETURN drvexecute(SQLHSTMT stmt, int initial);
593 static SQLRETURN freestmt(HSTMT stmt);
594 static SQLRETURN mkbindcols(STMT *s, int ncols);
595 static SQLRETURN setupdyncols(STMT *s, sqlite3_stmt *s3stmt, int *ncolsp);
596 static SQLRETURN setupparbuf(STMT *s, BINDPARM *p);
597 static SQLRETURN starttran(STMT *s);
598 static SQLRETURN setupparam(STMT *s, char *sql, int pnum);
599 static 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) */
605 static COL *statSpec2P, *statSpec3P;
606 #endif
607
608 #if (MEMORY_DEBUG < 1)
609 /**
610 * Duplicate string using xmalloc().
611 * @param str string to be duplicated
612 * @result pointer to new string or NULL
613 */
614
615 static char *
strdup_(const char * str)616 strdup_(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
630 /**
631 * Append string to dynamic string.
632 * @param dsp dstr pointer
633 * @param str string to append
634 * @result dsp result dstr pointer or NULL.
635 */
636
637 static dstr *
dsappend(dstr * dsp,const char * str)638 dsappend(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);
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);
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 }
676 copy:
677 strcpy(dsp->buffer + dsp->len, str);
678 dsp->len += len;
679 return dsp;
680 }
681
682 /**
683 * Append a string double quoted to dynamic string.
684 * @param dsp dstr pointer
685 * @param str string to append
686 * @result dsp result dstr pointer or NULL.
687 */
688
689 static dstr *
dsappendq(dstr * dsp,const char * str)690 dsappendq(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);
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);
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 }
736 copy:
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
751 /**
752 * Return dynamic string's value.
753 * @param dsp dstr pointer
754 * @result string value
755 */
756
757 static const char *
dsval(dstr * dsp)758 dsval(dstr *dsp)
759 {
760 if (dsp) {
761 return (const char *) dsp->buffer;
762 }
763 return "ERROR";
764 }
765
766 /**
767 * Check error on dynamic string.
768 * @param dsp dstr pointer
769 * @result true when error pending
770 */
771
772 static int
dserr(dstr * dsp)773 dserr(dstr *dsp)
774 {
775 return !dsp || dsp->oom;
776 }
777
778 /**
779 * Free dynamic string.
780 * @param dsp dstr pointer
781 */
782
783 static void
dsfree(dstr * dsp)784 dsfree(dstr *dsp)
785 {
786 if (dsp) {
787 xfree(dsp);
788 }
789 }
790
791 #ifdef WCHARSUPPORT
792
793 /**
794 * Return length of UNICODE string.
795 * @param str UNICODE string
796 * @result length of string in characters
797 */
798
799 static int
uc_strlen(SQLWCHAR * str)800 uc_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
813 /**
814 * Copy UNICODE string like strncpy().
815 * @param dest destination area
816 * @param src source area
817 * @param len length of source area in characters
818 * @return pointer to destination area
819 */
820
821 static SQLWCHAR *
uc_strncpy(SQLWCHAR * dest,SQLWCHAR * src,int len)822 uc_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
839 /**
840 * Make UNICODE string from UTF8 string into buffer.
841 * @param str UTF8 string to be converted
842 * @param len length in characters of str or -1
843 * @param uc destination area to receive UNICODE string
844 * @param ucLen byte length of destination area
845 */
846
847 static void
uc_from_utf_buf(unsigned char * str,int len,SQLWCHAR * uc,int ucLen)848 uc_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
924 /**
925 * Make UNICODE string from UTF8 string.
926 * @param str UTF8 string to be converted
927 * @param len length of UTF8 string
928 * @return alloc'ed UNICODE string to be free'd by uc_free()
929 */
930
931 static SQLWCHAR *
uc_from_utf(unsigned char * str,int len)932 uc_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
950 /**
951 * Make UTF8 string from UNICODE string.
952 * @param str UNICODE string to be converted
953 * @param len length of UNICODE string in bytes
954 * @return alloc'ed UTF8 string to be free'd by uc_free()
955 */
956
957 static char *
uc_to_utf(SQLWCHAR * str,int len)958 uc_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
1020 /**
1021 * Make UTF8 string from UNICODE string.
1022 * @param str UNICODE string to be converted
1023 * @param len length of UNICODE string in characters
1024 * @return alloc'ed UTF8 string to be free'd by uc_free()
1025 */
1026
1027 static char *
uc_to_utf_c(SQLWCHAR * str,int len)1028 uc_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
1040 /**
1041 * Free converted UTF8 or UNICODE string.
1042 * @param str string to be free'd
1043 */
1044
1045 static void
uc_free(void * str)1046 uc_free(void *str)
1047 {
1048 if (str) {
1049 xfree(str);
1050 }
1051 }
1052
1053 #endif
1054
1055 #if defined(_WIN32) || defined(_WIN64)
1056
1057 /**
1058 * Convert multibyte, current code page string to UTF8 string,
1059 * @param str multibyte string to be converted
1060 * @param len length of multibyte string
1061 * @return alloc'ed UTF8 string to be free'd by uc_free()
1062 */
1063
1064 static char *
wmb_to_utf(char * str,int len)1065 wmb_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
1099 /**
1100 * Convert multibyte, current code page string to UTF8 string,
1101 * @param str multibyte string to be converted
1102 * @param len length of multibyte string
1103 * @return alloc'ed UTF8 string to be free'd by uc_free()
1104 */
1105
1106 static char *
wmb_to_utf_c(char * str,int len)1107 wmb_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
1117 /**
1118 * Convert UTF8 string to multibyte, current code page string,
1119 * @param str UTF8 string to be converted
1120 * @param len length of UTF8 string
1121 * @return alloc'ed multibyte string to be free'd by uc_free()
1122 */
1123
1124 static char *
utf_to_wmb(char * str,int len)1125 utf_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
1159 /**
1160 * Convert multibyte, current code page string to UNICODE string,
1161 * @param str multibyte string to be converted
1162 * @param len length of multibyte string
1163 * @return alloc'ed UNICODE string to be free'd by uc_free()
1164 */
1165
1166 static WCHAR *
wmb_to_uc(char * str,int len)1167 wmb_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
1190 /**
1191 * Convert UNICODE string to multibyte, current code page string,
1192 * @param str UNICODE string to be converted
1193 * @param len length of UNICODE string
1194 * @return alloc'ed multibyte string to be free'd by uc_free()
1195 */
1196
1197 static char *
uc_to_wmb(WCHAR * wstr,int len)1198 uc_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
1239 static void
drvgetgpps(DBC * d)1240 drvgetgpps(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
1269 static void
drvrelgpps(DBC * d)1270 drvrelgpps(DBC *d)
1271 {
1272 if (d->instlib) {
1273 dlclose(d->instlib);
1274 d->instlib = 0;
1275 }
1276 }
1277
1278 static int
drvgpps(DBC * d,char * sect,char * ent,char * def,char * buf,int bufsiz,char * fname)1279 drvgpps(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
1299 static void
s3bind(DBC * d,sqlite3_stmt * stmt,int nparams,BINDPARM * p)1300 s3bind(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
1367 /**
1368 * @typedef TBLRES
1369 * @struct tblres
1370 * Internal structure for managing driver's
1371 * sqlite3_get_table() implementation.
1372 */
1373
1374 typedef struct tblres {
1375 char **resarr; /**< result array */
1376 char *errmsg; /**< error message or NULL */
1377 sqlite3_stmt *stmt; /**< SQLite3 statement pointer */
1378 STMT *s; /**< Driver statement pointer */
1379 int nalloc; /**< alloc'ed size of result array */
1380 int nrow; /**< number of rows in result array */
1381 int ncol; /**< number of columns in result array */
1382 PTRDIFF_T ndata; /**< index into result array */
1383 int rc; /**< SQLite return code */
1384 } TBLRES;
1385
1386 /*
1387 * Driver's version of sqlite3_get_table() and friends which are
1388 * capable of dealing with blobs.
1389 */
1390
1391 static int
drvgettable_row(TBLRES * t,int ncol,int rc)1392 drvgettable_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 resnew = xrealloc(t->resarr, sizeof (char *) * nalloc);
1408 if (!resnew) {
1409 nomem:
1410 t->rc = SQLITE_NOMEM;
1411 return 1;
1412 }
1413 t->nalloc = nalloc;
1414 t->resarr = resnew;
1415 }
1416 /* column names when first row */
1417 if (t->nrow == 0) {
1418 t->ncol = ncol;
1419 for (i = 0; i < ncol; i++) {
1420 p = (char *) sqlite3_column_name(t->stmt, i);
1421 if (p) {
1422 char *q = xmalloc(strlen(p) + 1);
1423
1424 if (!q) {
1425 goto nomem;
1426 }
1427 strcpy(q, p);
1428 p = q;
1429 }
1430 t->resarr[t->ndata++] = p;
1431 }
1432 if (t->s && t->s->guessed_types) {
1433 int ncol2 = ncol;
1434
1435 setupdyncols(t->s, t->stmt, &ncol2);
1436 t->s->guessed_types = 0;
1437 t->s->ncols = ncol;
1438 }
1439 } else if (t->ncol != ncol) {
1440 t->errmsg = sqlite3_mprintf("drvgettable() called with two or"
1441 " more incompatible queries");
1442 t->rc = SQLITE_ERROR;
1443 return 1;
1444 }
1445 /* copy row data */
1446 if (rc == SQLITE_ROW) {
1447 for (i = 0; i < ncol; i++) {
1448 int coltype = sqlite3_column_type(t->stmt, i);
1449
1450 p = NULL;
1451 if (coltype == SQLITE_BLOB) {
1452 int k, nbytes = sqlite3_column_bytes(t->stmt, i);
1453 char *qp;
1454 unsigned const char *bp;
1455
1456 bp = sqlite3_column_blob(t->stmt, i);
1457 qp = xmalloc(nbytes * 2 + 4);
1458 if (!qp) {
1459 goto nomem;
1460 }
1461 p = qp;
1462 *qp++ = 'X';
1463 *qp++ = '\'';
1464 for (k = 0; k < nbytes; k++) {
1465 *qp++ = xdigits[(bp[k] >> 4)];
1466 *qp++ = xdigits[(bp[k] & 0xF)];
1467 }
1468 *qp++ = '\'';
1469 *qp = '\0';
1470 #ifdef _MSC_VER
1471 } else if (coltype == SQLITE_FLOAT) {
1472 struct lconv *lc = 0;
1473 double val = sqlite3_column_double(t->stmt, i);
1474 char buffer[128];
1475
1476 /*
1477 * This avoids floating point rounding
1478 * and formatting problems of some SQLite
1479 * versions in conjunction with MSVC 2010.
1480 */
1481 snprintf(buffer, sizeof (buffer), "%.15g", val);
1482 lc = localeconv();
1483 if (lc && lc->decimal_point && lc->decimal_point[0] &&
1484 lc->decimal_point[0] != '.') {
1485 p = strchr(buffer, lc->decimal_point[0]);
1486 if (p) {
1487 *p = '.';
1488 }
1489 }
1490 p = xstrdup(buffer);
1491 if (!p) {
1492 goto nomem;
1493 }
1494 #endif
1495 } else if (coltype != SQLITE_NULL) {
1496 p = xstrdup((char *) sqlite3_column_text(t->stmt, i));
1497 if (!p) {
1498 goto nomem;
1499 }
1500 }
1501 t->resarr[t->ndata++] = p;
1502 }
1503 t->nrow++;
1504 }
1505 return 0;
1506 }
1507
1508 static int
drvgettable(STMT * s,const char * sql,char *** resp,int * nrowp,int * ncolp,char ** errp,int nparam,BINDPARM * p)1509 drvgettable(STMT *s, const char *sql, char ***resp, int *nrowp,
1510 int *ncolp, char **errp, int nparam, BINDPARM *p)
1511 {
1512 DBC *d = (DBC *) s->dbc;
1513 int rc = SQLITE_OK, keep = sql == NULL;
1514 TBLRES tres;
1515 const char *sqlleft = 0;
1516 int nretry = 0, haveerr = 0;
1517
1518 if (!resp) {
1519 return SQLITE_ERROR;
1520 }
1521 *resp = NULL;
1522 if (nrowp) {
1523 *nrowp = 0;
1524 }
1525 if (ncolp) {
1526 *ncolp = 0;
1527 }
1528 tres.errmsg = NULL;
1529 tres.nrow = 0;
1530 tres.ncol = 0;
1531 tres.ndata = 1;
1532 tres.nalloc = 20;
1533 tres.rc = SQLITE_OK;
1534 tres.resarr = xmalloc(sizeof (char *) * tres.nalloc);
1535 tres.stmt = NULL;
1536 tres.s = s;
1537 if (!tres.resarr) {
1538 return SQLITE_NOMEM;
1539 }
1540 tres.resarr[0] = 0;
1541 if (sql == NULL) {
1542 tres.stmt = s->s3stmt;
1543 if (tres.stmt == NULL) {
1544 return SQLITE_NOMEM;
1545 }
1546 goto retrieve;
1547 }
1548 while (sql && *sql && (rc == SQLITE_OK ||
1549 (rc == SQLITE_SCHEMA && (++nretry) < 2))) {
1550 int ncol;
1551
1552 tres.stmt = NULL;
1553 #if defined(HAVE_SQLITE3PREPAREV2) && (HAVE_SQLITE3PREPAREV2)
1554 dbtraceapi(d, "sqlite3_prepare_v2", sql);
1555 rc = sqlite3_prepare_v2(d->sqlite, sql, -1, &tres.stmt, &sqlleft);
1556 #else
1557 dbtraceapi(d, "sqlite3_prepare", sql);
1558 rc = sqlite3_prepare(d->sqlite, sql, -1, &tres.stmt, &sqlleft);
1559 #endif
1560 if (rc != SQLITE_OK) {
1561 if (tres.stmt) {
1562 dbtraceapi(d, "sqlite3_finalize", 0);
1563 sqlite3_finalize(tres.stmt);
1564 tres.stmt = NULL;
1565 }
1566 continue;
1567 }
1568 if (!tres.stmt) {
1569 /* this happens for a comment or white-space */
1570 sql = sqlleft;
1571 continue;
1572 }
1573 retrieve:
1574 if (sqlite3_bind_parameter_count(tres.stmt) != nparam) {
1575 if (errp) {
1576 *errp =
1577 sqlite3_mprintf("%s", "parameter marker count incorrect");
1578 }
1579 haveerr = 1;
1580 rc = SQLITE_ERROR;
1581 goto tbldone;
1582 }
1583 s3bind(d, tres.stmt, nparam, p);
1584 ncol = sqlite3_column_count(tres.stmt);
1585 while (1) {
1586 if (s->max_rows && tres.nrow >= s->max_rows) {
1587 rc = SQLITE_OK;
1588 break;
1589 }
1590 rc = sqlite3_step(tres.stmt);
1591 if (rc == SQLITE_ROW || rc == SQLITE_DONE) {
1592 if (drvgettable_row(&tres, ncol, rc)) {
1593 rc = SQLITE_ABORT;
1594 goto tbldone;
1595 }
1596 }
1597 if (rc != SQLITE_ROW) {
1598 if (keep) {
1599 dbtraceapi(d, "sqlite3_reset", 0);
1600 rc = sqlite3_reset(tres.stmt);
1601 s->s3stmt_noreset = 1;
1602 } else {
1603 dbtraceapi(d, "sqlite3_finalize", 0);
1604 rc = sqlite3_finalize(tres.stmt);
1605 }
1606 tres.stmt = 0;
1607 if (rc != SQLITE_SCHEMA) {
1608 nretry = 0;
1609 sql = sqlleft;
1610 while (sql && ISSPACE(*sql)) {
1611 sql++;
1612 }
1613 }
1614 if (rc == SQLITE_DONE) {
1615 rc = SQLITE_OK;
1616 }
1617 break;
1618 }
1619 }
1620 }
1621 tbldone:
1622 if (tres.stmt) {
1623 if (keep) {
1624 if (!s->s3stmt_noreset) {
1625 dbtraceapi(d, "sqlite3_reset", 0);
1626 sqlite3_reset(tres.stmt);
1627 s->s3stmt_noreset = 1;
1628 }
1629 } else {
1630 dbtraceapi(d, "sqlite3_finalize", 0);
1631 sqlite3_finalize(tres.stmt);
1632 }
1633 }
1634 if (haveerr) {
1635 /* message already in *errp if any */
1636 } else if (rc != SQLITE_OK && rc == sqlite3_errcode(d->sqlite) && errp) {
1637 *errp = sqlite3_mprintf("%s", sqlite3_errmsg(d->sqlite));
1638 } else if (errp) {
1639 *errp = NULL;
1640 }
1641 if (tres.resarr) {
1642 tres.resarr[0] = (char *) (tres.ndata - 1);
1643 }
1644 if (rc == SQLITE_ABORT) {
1645 freerows(&tres.resarr[1]);
1646 if (tres.errmsg) {
1647 if (errp) {
1648 if (*errp) {
1649 sqlite3_free(*errp);
1650 }
1651 *errp = tres.errmsg;
1652 } else {
1653 sqlite3_free(tres.errmsg);
1654 }
1655 }
1656 return tres.rc;
1657 }
1658 sqlite3_free(tres.errmsg);
1659 if (rc != SQLITE_OK) {
1660 freerows(&tres.resarr[1]);
1661 return rc;
1662 }
1663 *resp = &tres.resarr[1];
1664 if (ncolp) {
1665 *ncolp = tres.ncol;
1666 }
1667 if (nrowp) {
1668 *nrowp = tres.nrow;
1669 }
1670 return rc;
1671 }
1672
1673 /**
1674 * Set error message and SQL state on DBC
1675 * @param d database connection pointer
1676 * @param naterr native error code
1677 * @param msg error message
1678 * @param st SQL state
1679 */
1680
1681 #if defined(__GNUC__) && (__GNUC__ >= 2)
1682 static void setstatd(DBC *, int, char *, char *, ...)
1683 __attribute__((format (printf, 3, 5)));
1684 #endif
1685
1686 static void
setstatd(DBC * d,int naterr,char * msg,char * st,...)1687 setstatd(DBC *d, int naterr, char *msg, char *st, ...)
1688 {
1689 va_list ap;
1690
1691 if (!d) {
1692 return;
1693 }
1694 d->naterr = naterr;
1695 d->logmsg[0] = '\0';
1696 if (msg) {
1697 int count;
1698
1699 va_start(ap, st);
1700 count = vsnprintf((char *) d->logmsg, sizeof (d->logmsg), msg, ap);
1701 va_end(ap);
1702 if (count < 0) {
1703 d->logmsg[sizeof (d->logmsg) - 1] = '\0';
1704 }
1705 }
1706 if (!st) {
1707 st = "?????";
1708 }
1709 strncpy(d->sqlstate, st, 5);
1710 d->sqlstate[5] = '\0';
1711 }
1712
1713 /**
1714 * Set error message and SQL state on statement
1715 * @param s statement pointer
1716 * @param naterr native error code
1717 * @param msg error message
1718 * @param st SQL state
1719 */
1720
1721 #if defined(__GNUC__) && (__GNUC__ >= 2)
1722 static void setstat(STMT *, int, char *, char *, ...)
1723 __attribute__((format (printf, 3, 5)));
1724 #endif
1725
1726 static void
setstat(STMT * s,int naterr,char * msg,char * st,...)1727 setstat(STMT *s, int naterr, char *msg, char *st, ...)
1728 {
1729 va_list ap;
1730
1731 if (!s) {
1732 return;
1733 }
1734 s->naterr = naterr;
1735 s->logmsg[0] = '\0';
1736 if (msg) {
1737 int count;
1738
1739 va_start(ap, st);
1740 count = vsnprintf((char *) s->logmsg, sizeof (s->logmsg), msg, ap);
1741 va_end(ap);
1742 if (count < 0) {
1743 s->logmsg[sizeof (s->logmsg) - 1] = '\0';
1744 }
1745 }
1746 if (!st) {
1747 st = "?????";
1748 }
1749 strncpy(s->sqlstate, st, 5);
1750 s->sqlstate[5] = '\0';
1751 }
1752
1753 /**
1754 * Report IM001 (not implemented) SQL error code for HDBC.
1755 * @param dbc database connection handle
1756 * @result ODBC error code
1757 */
1758
1759 static SQLRETURN
drvunimpldbc(HDBC dbc)1760 drvunimpldbc(HDBC dbc)
1761 {
1762 DBC *d;
1763
1764 if (dbc == SQL_NULL_HDBC) {
1765 return SQL_INVALID_HANDLE;
1766 }
1767 d = (DBC *) dbc;
1768 setstatd(d, -1, "not supported", "IM001");
1769 return SQL_ERROR;
1770 }
1771
1772 /**
1773 * Report IM001 (not implemented) SQL error code for HSTMT.
1774 * @param stmt statement handle
1775 * @result ODBC error code
1776 */
1777
1778 static SQLRETURN
drvunimplstmt(HSTMT stmt)1779 drvunimplstmt(HSTMT stmt)
1780 {
1781 STMT *s;
1782
1783 if (stmt == SQL_NULL_HSTMT) {
1784 return SQL_INVALID_HANDLE;
1785 }
1786 s = (STMT *) stmt;
1787 setstat(s, -1, "not supported", "IM001");
1788 return SQL_ERROR;
1789 }
1790
1791 /**
1792 * Free memory given pointer to memory pointer.
1793 * @param x pointer to pointer to memory to be free'd
1794 */
1795
1796 static void
freep(void * x)1797 freep(void *x)
1798 {
1799 if (x && ((char **) x)[0]) {
1800 xfree(((char **) x)[0]);
1801 ((char **) x)[0] = NULL;
1802 }
1803 }
1804
1805 /**
1806 * Report S1000 (out of memory) SQL error given STMT.
1807 * @param s statement pointer
1808 * @result ODBC error code
1809 */
1810
1811 static SQLRETURN
nomem(STMT * s)1812 nomem(STMT *s)
1813 {
1814 setstat(s, -1, "out of memory", (*s->ov3) ? "HY000" : "S1000");
1815 return SQL_ERROR;
1816 }
1817
1818 /**
1819 * Report S1000 (not connected) SQL error given STMT.
1820 * @param s statement pointer
1821 * @result ODBC error code
1822 */
1823
1824 static SQLRETURN
noconn(STMT * s)1825 noconn(STMT *s)
1826 {
1827 setstat(s, -1, "not connected", (*s->ov3) ? "HY000" : "S1000");
1828 return SQL_ERROR;
1829 }
1830
1831 /**
1832 * Internal locale neutral strtod function.
1833 * @param data pointer to string
1834 * @param endp pointer for ending character
1835 * @result double value
1836 */
1837
1838 #if defined(HAVE_LOCALECONV) || defined(_WIN32) || defined(_WIN64)
1839
1840 static double
ln_strtod(const char * data,char ** endp)1841 ln_strtod(const char *data, char **endp)
1842 {
1843 struct lconv *lc = 0;
1844 char buf[128], *p, *end;
1845 double value;
1846
1847 lc = localeconv();
1848 if (lc && lc->decimal_point && lc->decimal_point[0] &&
1849 lc->decimal_point[0] != '.') {
1850 strncpy(buf, data, sizeof (buf) - 1);
1851 buf[sizeof (buf) - 1] = '\0';
1852 p = strchr(buf, '.');
1853 if (p) {
1854 *p = lc->decimal_point[0];
1855 }
1856 p = buf;
1857 } else {
1858 p = (char *) data;
1859 }
1860 value = strtod(p, &end);
1861 end = (char *) data + (end - p);
1862 if (endp) {
1863 *endp = end;
1864 }
1865 return value;
1866 }
1867
1868 #else
1869
1870 #define ln_strtod(A,B) strtod(A,B)
1871
1872 #endif
1873
1874 /**
1875 * Strip quotes from quoted string in-place.
1876 * @param str string
1877 */
1878
1879 static char *
unquote(char * str)1880 unquote(char *str)
1881 {
1882 if (str) {
1883 int len = strlen(str);
1884
1885 if (len > 1) {
1886 int end = len - 1;
1887
1888 if ((str[0] == '\'' && str[end] == '\'') ||
1889 (str[0] == '"' && str[end] == '"') ||
1890 (str[0] == '[' && str[end] == ']')) {
1891 memmove(str, str + 1, end - 1);
1892 str[end - 1] = '\0';
1893 }
1894 }
1895 }
1896 return str;
1897 }
1898
1899 /**
1900 * Unescape search pattern for e.g. table name in
1901 * catalog functions. Replacements in string are done in-place.
1902 * @param str string
1903 * @result number of pattern characters in string or 0
1904 */
1905
1906 static int
unescpat(char * str)1907 unescpat(char *str)
1908 {
1909 char *p, *q;
1910 int count = 0;
1911
1912 p = str;
1913 while ((q = strchr(p, '_')) != NULL) {
1914 if (q == str || q[-1] != '\\') {
1915 count++;
1916 }
1917 p = q + 1;
1918 }
1919 p = str;
1920 while ((q = strchr(p, '%')) != NULL) {
1921 if (q == str || q[-1] != '\\') {
1922 count++;
1923 }
1924 p = q + 1;
1925 }
1926 p = str;
1927 while ((q = strchr(p, '\\')) != NULL) {
1928 if (q[1] == '\\' || q[1] == '_' || q[1] == '%') {
1929 memmove(q, q + 1, strlen(q));
1930 }
1931 p = q + 1;
1932 }
1933 return count;
1934 }
1935
1936 /**
1937 * SQL LIKE string match with optional backslash escape handling.
1938 * @param str string
1939 * @param pat pattern
1940 * @param esc when true, treat literally "\\" as "\", "\%" as "%", "\_" as "_"
1941 * @result true when pattern matched
1942 */
1943
1944 static int
namematch(char * str,char * pat,int esc)1945 namematch(char *str, char *pat, int esc)
1946 {
1947 int cp, ch;
1948
1949 while (1) {
1950 cp = TOLOWER(*pat);
1951 if (cp == '\0') {
1952 if (*str != '\0') {
1953 goto nomatch;
1954 }
1955 break;
1956 }
1957 if (*str == '\0' && cp != '%') {
1958 goto nomatch;
1959 }
1960 if (cp == '%') {
1961 while (*pat == '%') {
1962 ++pat;
1963 }
1964 cp = TOLOWER(*pat);
1965 if (cp == '\0') {
1966 break;
1967 }
1968 while (1) {
1969 if (cp != '_' && cp != '\\') {
1970 while (*str) {
1971 ch = TOLOWER(*str);
1972 if (ch == cp) {
1973 break;
1974 }
1975 ++str;
1976 }
1977 }
1978 if (namematch(str, pat, esc)) {
1979 goto match;
1980 }
1981 if (*str == '\0') {
1982 goto nomatch;
1983 }
1984 ch = TOLOWER(*str);
1985 ++str;
1986 }
1987 }
1988 if (cp == '_') {
1989 pat++;
1990 str++;
1991 continue;
1992 }
1993 if (esc && cp == '\\' &&
1994 (pat[1] == '\\' || pat[1] == '%' || pat[1] == '_')) {
1995 ++pat;
1996 cp = TOLOWER(*pat);
1997 }
1998 ch = TOLOWER(*str++);
1999 ++pat;
2000 if (ch != cp) {
2001 goto nomatch;
2002 }
2003 }
2004 match:
2005 return 1;
2006 nomatch:
2007 return 0;
2008 }
2009
2010 /**
2011 * Busy callback for SQLite.
2012 * @param udata user data, pointer to DBC
2013 * @param count count of subsequenct calls
2014 * @result true or false
2015 */
2016
2017 static int
busy_handler(void * udata,int count)2018 busy_handler(void *udata, int count)
2019 {
2020 DBC *d = (DBC *) udata;
2021 long t1;
2022 int ret = 0;
2023 #if !defined(_WIN32) && !defined(_WIN64)
2024 struct timeval tv;
2025 #ifdef HAVE_NANOSLEEP
2026 struct timespec ts;
2027 #endif
2028 #endif
2029
2030 if (d->busyint) {
2031 d->busyint = 0;
2032 return ret;
2033 }
2034 if (d->timeout <= 0) {
2035 return ret;
2036 }
2037 if (count <= 1) {
2038 #if defined(_WIN32) || defined(_WIN64)
2039 d->t0 = GetTickCount();
2040 #else
2041 gettimeofday(&tv, NULL);
2042 d->t0 = tv.tv_sec * 1000 + tv.tv_usec / 1000;
2043 #endif
2044 }
2045 #if defined(_WIN32) || defined(_WIN64)
2046 t1 = GetTickCount();
2047 #else
2048 gettimeofday(&tv, NULL);
2049 t1 = tv.tv_sec * 1000 + tv.tv_usec / 1000;
2050 #endif
2051 if (t1 - d->t0 > d->timeout) {
2052 goto done;
2053 }
2054 #if defined(_WIN32) || defined(_WIN64)
2055 Sleep(10);
2056 #else
2057 #ifdef HAVE_NANOSLEEP
2058 ts.tv_sec = 0;
2059 ts.tv_nsec = 10000000;
2060 do {
2061 ret = nanosleep(&ts, &ts);
2062 if (ret < 0 && errno != EINTR) {
2063 ret = 0;
2064 }
2065 } while (ret);
2066 #else
2067 #ifdef HAVE_USLEEP
2068 usleep(10000);
2069 #else
2070 tv.tv_sec = 0;
2071 tv.tv_usec = 10000;
2072 select(0, NULL, NULL, NULL, &tv);
2073 #endif
2074 #endif
2075 #endif
2076 ret = 1;
2077 done:
2078 return ret;
2079 }
2080
2081 /**
2082 * Set SQLite options (PRAGMAs) given SQLite handle.
2083 * @param x SQLite database handle
2084 * @param d DBC pointer
2085 * @result SQLite error code
2086 *
2087 * SQLite < 3.3.x and not shortnames DSN option:
2088 * "full_column_names" is always turned on and "short_column_names"
2089 * is always turned off, to get the table names in column labels.
2090 */
2091
2092 static int
setsqliteopts(sqlite3 * x,DBC * d)2093 setsqliteopts(sqlite3 *x, DBC *d)
2094 {
2095 int count = 0, step = 0, max, rc = SQLITE_ERROR;
2096
2097 #if defined(HAVE_SQLITE3COLUMNTABLENAME) && (HAVE_SQLITE3COLUMNTABLENAME)
2098 max = d->longnames ? 3 : 1;
2099 #else
2100 max = 3;
2101 #endif
2102 if (d->shortnames) {
2103 max = 3;
2104 }
2105 while (step < max) {
2106 if (step < 1) {
2107 rc = sqlite3_exec(x, "PRAGMA empty_result_callbacks = on;",
2108 NULL, NULL, NULL);
2109 if (rc == SQLITE_OK) {
2110 rc = sqlite3_exec(x, d->fksupport ?
2111 "PRAGMA foreign_keys = on;" :
2112 "PRAGMA foreign_keys = off;",
2113 NULL, NULL, NULL);
2114 }
2115 } else if (step < 2) {
2116 rc = sqlite3_exec(x, d->shortnames ?
2117 "PRAGMA full_column_names = off;" :
2118 "PRAGMA full_column_names = on;",
2119 NULL, NULL, NULL);
2120 } else if (step < 3) {
2121 rc = sqlite3_exec(x, d->shortnames ?
2122 "PRAGMA short_column_names = on;" :
2123 "PRAGMA short_column_names = off;",
2124 NULL, NULL, NULL);
2125 }
2126 if (rc != SQLITE_OK) {
2127 if (rc != SQLITE_BUSY ||
2128 !busy_handler((void *) d, ++count)) {
2129 return rc;
2130 }
2131 continue;
2132 }
2133 count = 0;
2134 ++step;
2135 }
2136 sqlite3_busy_handler(x, busy_handler, (void *) d);
2137 return SQLITE_OK;
2138 }
2139
2140 /**
2141 * Free counted array of char pointers.
2142 * @param rowp pointer to char pointer array
2143 *
2144 * The -1-th element of the array holds the array size.
2145 * All non-NULL pointers of the array and then the array
2146 * itself are free'd.
2147 */
2148
2149 static void
freerows(char ** rowp)2150 freerows(char **rowp)
2151 {
2152 PTRDIFF_T size, i;
2153
2154 if (!rowp) {
2155 return;
2156 }
2157 --rowp;
2158 size = (PTRDIFF_T) rowp[0];
2159 for (i = 1; i <= size; i++) {
2160 freep(&rowp[i]);
2161 }
2162 freep(&rowp);
2163 }
2164
2165 /**
2166 * Map SQL field type from string to ODBC integer type code.
2167 * @param typename field type string
2168 * @param nosign pointer to indicator for unsigned field or NULL
2169 * @param ov3 boolean, true for SQL_OV_ODBC3
2170 * @param nowchar boolean, for WINTERFACE don't use WCHAR
2171 * @param dobigint boolean, force SQL_BIGINT on INTEGER columns
2172 * @result SQL data type
2173 */
2174
2175 static int
mapsqltype(const char * typename,int * nosign,int ov3,int nowchar,int dobigint)2176 mapsqltype(const char *typename, int *nosign, int ov3, int nowchar,
2177 int dobigint)
2178 {
2179 char *p, *q;
2180 int testsign = 0, result;
2181
2182 #ifdef WINTERFACE
2183 result = nowchar ? SQL_VARCHAR : SQL_WVARCHAR;
2184 #else
2185 result = SQL_VARCHAR;
2186 #endif
2187 if (!typename) {
2188 return result;
2189 }
2190 q = p = xmalloc(strlen(typename) + 1);
2191 if (!p) {
2192 return result;
2193 }
2194 strcpy(p, typename);
2195 while (*q) {
2196 *q = TOLOWER(*q);
2197 ++q;
2198 }
2199 if (strncmp(p, "inter", 5) == 0) {
2200 } else if (strncmp(p, "int", 3) == 0 ||
2201 strncmp(p, "mediumint", 9) == 0) {
2202 testsign = 1;
2203 result = SQL_INTEGER;
2204 } else if (strncmp(p, "numeric", 7) == 0) {
2205 result = SQL_DOUBLE;
2206 } else if (strncmp(p, "tinyint", 7) == 0) {
2207 testsign = 1;
2208 result = SQL_TINYINT;
2209 } else if (strncmp(p, "smallint", 8) == 0) {
2210 testsign = 1;
2211 result = SQL_SMALLINT;
2212 } else if (strncmp(p, "float", 5) == 0) {
2213 result = SQL_DOUBLE;
2214 } else if (strncmp(p, "double", 6) == 0 ||
2215 strncmp(p, "real", 4) == 0) {
2216 result = SQL_DOUBLE;
2217 } else if (strncmp(p, "timestamp", 9) == 0) {
2218 #ifdef SQL_TYPE_TIMESTAMP
2219 result = ov3 ? SQL_TYPE_TIMESTAMP : SQL_TIMESTAMP;
2220 #else
2221 result = SQL_TIMESTAMP;
2222 #endif
2223 } else if (strncmp(p, "datetime", 8) == 0) {
2224 #ifdef SQL_TYPE_TIMESTAMP
2225 result = ov3 ? SQL_TYPE_TIMESTAMP : SQL_TIMESTAMP;
2226 #else
2227 result = SQL_TIMESTAMP;
2228 #endif
2229 } else if (strncmp(p, "time", 4) == 0) {
2230 #ifdef SQL_TYPE_TIME
2231 result = ov3 ? SQL_TYPE_TIME : SQL_TIME;
2232 #else
2233 result = SQL_TIME;
2234 #endif
2235 } else if (strncmp(p, "date", 4) == 0) {
2236 #ifdef SQL_TYPE_DATE
2237 result = ov3 ? SQL_TYPE_DATE : SQL_DATE;
2238 #else
2239 result = SQL_DATE;
2240 #endif
2241 #ifdef SQL_LONGVARCHAR
2242 } else if (strncmp(p, "text", 4) == 0 ||
2243 strncmp(p, "memo", 4) == 0 ||
2244 strncmp(p, "longvarchar", 11) == 0) {
2245 #ifdef WINTERFACE
2246 result = nowchar ? SQL_LONGVARCHAR : SQL_WLONGVARCHAR;
2247 #else
2248 result = SQL_LONGVARCHAR;
2249 #endif
2250 #ifdef WINTERFACE
2251 } else if (strncmp(p, "wtext", 5) == 0 ||
2252 strncmp(p, "wvarchar", 8) == 0 ||
2253 strncmp(p, "longwvarchar", 12) == 0) {
2254 result = SQL_WLONGVARCHAR;
2255 #endif
2256 #endif
2257 #ifdef SQL_BIT
2258 } else if (strncmp(p, "bool", 4) == 0 ||
2259 strncmp(p, "bit", 3) == 0) {
2260 result = SQL_BIT;
2261 #endif
2262 #ifdef SQL_BIGINT
2263 } else if (strncmp(p, "bigint", 6) == 0) {
2264 testsign = 1;
2265 result = SQL_BIGINT;
2266 #endif
2267 } else if (strncmp(p, "blob", 4) == 0) {
2268 result = SQL_BINARY;
2269 } else if (strncmp(p, "varbinary", 9) == 0) {
2270 result = SQL_VARBINARY;
2271 } else if (strncmp(p, "longvarbinary", 13) == 0) {
2272 result = SQL_LONGVARBINARY;
2273 }
2274 if (nosign) {
2275 if (testsign) {
2276 *nosign = strstr(p, "unsigned") != NULL;
2277 } else {
2278 *nosign = 1;
2279 }
2280 }
2281 #ifdef SQL_BIGINT
2282 if (dobigint && result == SQL_INTEGER) {
2283 result = SQL_BIGINT;
2284 }
2285 #endif
2286 xfree(p);
2287 return result;
2288 }
2289
2290 /**
2291 * Get maximum display size and number of digits after decimal point
2292 * from field type specification.
2293 * @param typename field type specification
2294 * @param sqltype target SQL data type
2295 * @param mp pointer to maximum display size or NULL
2296 * @param dp pointer to number of digits after decimal point or NULL
2297 */
2298
2299 static void
getmd(const char * typename,int sqltype,int * mp,int * dp)2300 getmd(const char *typename, int sqltype, int *mp, int *dp)
2301 {
2302 int m = 0, d = 0;
2303
2304 switch (sqltype) {
2305 case SQL_INTEGER: m = 10; d = 9; break;
2306 case SQL_TINYINT: m = 4; d = 3; break;
2307 case SQL_SMALLINT: m = 6; d = 5; break;
2308 case SQL_FLOAT: m = 25; d = 24; break;
2309 case SQL_DOUBLE: m = 54; d = 53; break;
2310 case SQL_VARCHAR: m = 255; d = 0; break;
2311 #ifdef WINTERFACE
2312 #ifdef SQL_WVARCHAR
2313 case SQL_WVARCHAR: m = 255; d = 0; break;
2314 #endif
2315 #endif
2316 #ifdef SQL_TYPE_DATE
2317 case SQL_TYPE_DATE:
2318 #endif
2319 case SQL_DATE: m = 10; d = 0; break;
2320 #ifdef SQL_TYPE_TIME
2321 case SQL_TYPE_TIME:
2322 #endif
2323 case SQL_TIME: m = 8; d = 0; break;
2324 #ifdef SQL_TYPE_TIMESTAMP
2325 case SQL_TYPE_TIMESTAMP:
2326 #endif
2327 case SQL_TIMESTAMP: m = 32; d = 3; break;
2328 #ifdef SQL_LONGVARCHAR
2329 case SQL_LONGVARCHAR : m = 65536; d = 0; break;
2330 #endif
2331 #ifdef WINTERFACE
2332 #ifdef SQL_WLONGVARCHAR
2333 case SQL_WLONGVARCHAR: m = 65536; d = 0; break;
2334 #endif
2335 #endif
2336 case SQL_BINARY:
2337 case SQL_VARBINARY: m = 255; d = 0; break;
2338 case SQL_LONGVARBINARY: m = 65536; d = 0; break;
2339 #ifdef SQL_BIGINT
2340 case SQL_BIGINT: m = 20; d = 19; break;
2341 #endif
2342 #ifdef SQL_BIT
2343 case SQL_BIT: m = 1; d = 1; break;
2344 #endif
2345 }
2346 if (m && typename) {
2347 int mm, dd;
2348 char clbr[4];
2349
2350 if (sscanf(typename, "%*[^(](%d,%d %1[)]", &mm, &dd, clbr) == 3) {
2351 m = mm;
2352 d = dd;
2353 } else if (sscanf(typename, "%*[^(](%d %1[)]", &mm, clbr) == 2) {
2354 if (sqltype == SQL_TIMESTAMP) {
2355 d = mm;
2356 }
2357 #ifdef SQL_TYPE_TIMESTAMP
2358 else if (sqltype == SQL_TYPE_TIMESTAMP) {
2359 d = mm;
2360 }
2361 #endif
2362 else {
2363 m = d = mm;
2364 }
2365 }
2366 }
2367 if (mp) {
2368 *mp = m;
2369 }
2370 if (dp) {
2371 *dp = d;
2372 }
2373 }
2374
2375 /**
2376 * Map SQL_C_DEFAULT to proper C type.
2377 * @param type input C type
2378 * @param stype input SQL type
2379 * @param nosign 0=signed, 0>unsigned, 0<undefined
2380 * @param nowchar when compiled with WINTERFACE don't use WCHAR
2381 * @result C type
2382 */
2383
2384 static int
mapdeftype(int type,int stype,int nosign,int nowchar)2385 mapdeftype(int type, int stype, int nosign, int nowchar)
2386 {
2387 if (type == SQL_C_DEFAULT) {
2388 switch (stype) {
2389 case SQL_INTEGER:
2390 type = (nosign > 0) ? SQL_C_ULONG : SQL_C_LONG;
2391 break;
2392 case SQL_TINYINT:
2393 type = (nosign > 0) ? SQL_C_UTINYINT : SQL_C_TINYINT;
2394 break;
2395 case SQL_SMALLINT:
2396 type = (nosign > 0) ? SQL_C_USHORT : SQL_C_SHORT;
2397 break;
2398 case SQL_FLOAT:
2399 type = SQL_C_FLOAT;
2400 break;
2401 case SQL_DOUBLE:
2402 type = SQL_C_DOUBLE;
2403 break;
2404 case SQL_TIMESTAMP:
2405 type = SQL_C_TIMESTAMP;
2406 break;
2407 case SQL_TIME:
2408 type = SQL_C_TIME;
2409 break;
2410 case SQL_DATE:
2411 type = SQL_C_DATE;
2412 break;
2413 #ifdef SQL_C_TYPE_TIMESTAMP
2414 case SQL_TYPE_TIMESTAMP:
2415 type = SQL_C_TYPE_TIMESTAMP;
2416 break;
2417 #endif
2418 #ifdef SQL_C_TYPE_TIME
2419 case SQL_TYPE_TIME:
2420 type = SQL_C_TYPE_TIME;
2421 break;
2422 #endif
2423 #ifdef SQL_C_TYPE_DATE
2424 case SQL_TYPE_DATE:
2425 type = SQL_C_TYPE_DATE;
2426 break;
2427 #endif
2428 #ifdef WINTERFACE
2429 case SQL_WVARCHAR:
2430 case SQL_WCHAR:
2431 #ifdef SQL_WLONGVARCHAR
2432 case SQL_WLONGVARCHAR:
2433 #endif
2434 type = nowchar ? SQL_C_CHAR : SQL_C_WCHAR;
2435 break;
2436 #endif
2437 case SQL_BINARY:
2438 case SQL_VARBINARY:
2439 case SQL_LONGVARBINARY:
2440 type = SQL_C_BINARY;
2441 break;
2442 #ifdef SQL_BIT
2443 case SQL_BIT:
2444 type = SQL_C_BIT;
2445 break;
2446 #endif
2447 #ifdef SQL_BIGINT
2448 case SQL_BIGINT:
2449 type = SQL_C_CHAR;
2450 break;
2451 #endif
2452 default:
2453 #ifdef WINTERFACE
2454 type = nowchar ? SQL_C_CHAR : SQL_C_WCHAR;
2455 #else
2456 type = SQL_C_CHAR;
2457 #endif
2458 break;
2459 }
2460 }
2461 return type;
2462 }
2463
2464 /**
2465 * Check if query is a DDL statement.
2466 * @param sql query string
2467 * @result true or false
2468 */
2469
2470 static int
checkddl(char * sql)2471 checkddl(char *sql)
2472 {
2473 int isddl = 0;
2474
2475 while (*sql && ISSPACE(*sql)) {
2476 ++sql;
2477 }
2478 if (*sql && *sql != ';') {
2479 int i, size;
2480 static const struct {
2481 int len;
2482 const char *str;
2483 } ddlstr[] = {
2484 { 5, "alter" },
2485 { 7, "analyze" },
2486 { 6, "attach" },
2487 { 5, "begin" },
2488 { 6, "commit" },
2489 { 6, "create" },
2490 { 6, "detach" },
2491 { 4, "drop" },
2492 { 3, "end" },
2493 { 7, "reindex" },
2494 { 7, "release" },
2495 { 8, "rollback" },
2496 { 9, "savepoint" },
2497 { 6, "vacuum" }
2498 };
2499
2500 size = strlen(sql);
2501 for (i = 0; i < array_size(ddlstr); i++) {
2502 if (size >= ddlstr[i].len &&
2503 strncasecmp(sql, ddlstr[i].str, ddlstr[i].len) == 0) {
2504 isddl = 1;
2505 break;
2506 }
2507 }
2508 }
2509 return isddl;
2510 }
2511
2512 /**
2513 * Fixup query string with optional parameter markers.
2514 * @param sql original query string
2515 * @param sqlLen length of query string or SQL_NTS
2516 * @param cte when true, WITH is treated as SELECT
2517 * @param nparam output number of parameters
2518 * @param isselect output indicator for SELECT (1) or DDL statement (2)
2519 * @param errmsg output error message
2520 * @result newly allocated string containing query string for SQLite or NULL
2521 */
2522
2523 static char *
fixupsql(char * sql,int sqlLen,int cte,int * nparam,int * isselect,char ** errmsg)2524 fixupsql(char *sql, int sqlLen, int cte, int *nparam, int *isselect,
2525 char **errmsg)
2526 {
2527 char *q = sql, *qz = NULL, *p, *inq = NULL, *out;
2528 int np = 0, isddl = -1, size;
2529
2530 if (errmsg) {
2531 *errmsg = NULL;
2532 }
2533 if (sqlLen != SQL_NTS) {
2534 qz = q = xmalloc(sqlLen + 1);
2535 if (!qz) {
2536 return NULL;
2537 }
2538 memcpy(q, sql, sqlLen);
2539 q[sqlLen] = '\0';
2540 size = sqlLen * 4;
2541 } else {
2542 size = strlen(sql) * 4;
2543 }
2544 size += sizeof (char *) - 1;
2545 size &= ~(sizeof (char *) - 1);
2546 p = xmalloc(size);
2547 if (!p) {
2548 errout:
2549 freep(&qz);
2550 return NULL;
2551 }
2552 memset(p, 0, size);
2553 out = p;
2554 while (*q) {
2555 switch (*q) {
2556 case '\'':
2557 case '\"':
2558 if (q == inq) {
2559 inq = NULL;
2560 } else if (!inq) {
2561 inq = q + 1;
2562
2563 while (*inq) {
2564 if (*inq == *q) {
2565 if (inq[1] == *q) {
2566 inq++;
2567 } else {
2568 break;
2569 }
2570 }
2571 inq++;
2572 }
2573 }
2574 *p++ = *q;
2575 break;
2576 case '?':
2577 *p++ = *q;
2578 if (!inq) {
2579 np++;
2580 }
2581 break;
2582 case ';':
2583 if (!inq) {
2584 if (isddl < 0) {
2585 isddl = checkddl(out);
2586 }
2587 if (isddl == 0) {
2588 char *qq = q;
2589
2590 do {
2591 ++qq;
2592 } while (*qq && ISSPACE(*qq));
2593 if (*qq && *qq != ';') {
2594 freep(&out);
2595 if (errmsg) {
2596 *errmsg = "only one SQL statement allowed";
2597 }
2598 goto errout;
2599 }
2600 }
2601 }
2602 *p++ = *q;
2603 break;
2604 case '{':
2605 /*
2606 * Deal with escape sequences:
2607 * {d 'YYYY-MM-DD'}, {t ...}, {ts ...}
2608 * {oj ...}, {fn ...} etc.
2609 */
2610 if (!inq) {
2611 int ojfn = 0, brc = 0;
2612 char *inq2 = NULL, *end = q + 1, *start;
2613
2614 while (*end && ISSPACE(*end)) {
2615 ++end;
2616 }
2617 if (*end != 'd' && *end != 'D' &&
2618 *end != 't' && *end != 'T') {
2619 ojfn = 1;
2620 }
2621 start = end;
2622 while (*end) {
2623 if (inq2 && *end == *inq2) {
2624 inq2 = NULL;
2625 } else if (inq2 == NULL && *end == '{') {
2626 char *nerr = 0, *nsql;
2627
2628 nsql = fixupsql(end, SQL_NTS, cte, 0, 0, &nerr);
2629 if (nsql && !nerr) {
2630 strcpy(end, nsql);
2631 } else {
2632 brc++;
2633 }
2634 freep(&nsql);
2635 } else if (inq2 == NULL && *end == '}') {
2636 if (brc-- <= 0) {
2637 break;
2638 }
2639 } else if (inq2 == NULL && (*end == '\'' || *end == '"')) {
2640 inq2 = end;
2641 } else if (inq2 == NULL && *end == '?') {
2642 np++;
2643 }
2644 ++end;
2645 }
2646 if (*end == '}') {
2647 char *end2 = end - 1;
2648
2649 if (ojfn) {
2650 while (start < end) {
2651 if (ISSPACE(*start)) {
2652 break;
2653 }
2654 ++start;
2655 }
2656 while (start < end) {
2657 *p++ = *start;
2658 ++start;
2659 }
2660 q = end;
2661 break;
2662 } else {
2663 while (start < end2 && *start != '\'') {
2664 ++start;
2665 }
2666 while (end2 > start && *end2 != '\'') {
2667 --end2;
2668 }
2669 if (*start == '\'' && *end2 == '\'') {
2670 while (start <= end2) {
2671 *p++ = *start;
2672 ++start;
2673 }
2674 q = end;
2675 break;
2676 }
2677 }
2678 }
2679 }
2680 /* FALL THROUGH */
2681 default:
2682 *p++ = *q;
2683 }
2684 ++q;
2685 }
2686 freep(&qz);
2687 *p = '\0';
2688 if (nparam) {
2689 *nparam = np;
2690 }
2691 if (isselect) {
2692 if (isddl < 0) {
2693 isddl = checkddl(out);
2694 }
2695 if (isddl > 0) {
2696 *isselect = 2;
2697 } else {
2698 int incom = 0;
2699
2700 p = out;
2701 while (*p) {
2702 switch (*p) {
2703 case '-':
2704 if (!incom && p[1] == '-') {
2705 incom = -1;
2706 }
2707 break;
2708 case '\n':
2709 if (incom < 0) {
2710 incom = 0;
2711 }
2712 break;
2713 case '/':
2714 if (incom > 0 && p[-1] == '*') {
2715 incom = 0;
2716 p++;
2717 continue;
2718 } else if (!incom && p[1] == '*') {
2719 incom = 1;
2720 }
2721 break;
2722 }
2723 if (!incom && !ISSPACE(*p)) {
2724 break;
2725 }
2726 p++;
2727 }
2728 size = strlen(p);
2729 if (size >= 6 &&
2730 (strncasecmp(p, "select", 6) == 0 ||
2731 strncasecmp(p, "pragma", 6) == 0)) {
2732 *isselect = 1;
2733 } else if (cte && size >= 4 && strncasecmp(p, "with", 4) == 0) {
2734 *isselect = 1;
2735 } else if (size >= 7 && strncasecmp(p, "explain", 7) == 0) {
2736 *isselect = 1;
2737 } else {
2738 *isselect = 0;
2739 }
2740 }
2741 }
2742 return out;
2743 }
2744
2745 /**
2746 * Find column given name in string array.
2747 * @param cols string array
2748 * @param ncols number of strings
2749 * @param name column name
2750 * @result >= 0 on success, -1 on error
2751 */
2752
2753 static int
findcol(char ** cols,int ncols,char * name)2754 findcol(char **cols, int ncols, char *name)
2755 {
2756 int i;
2757
2758 if (cols) {
2759 for (i = 0; i < ncols; i++) {
2760 if (strcmp(cols[i], name) == 0) {
2761 return i;
2762 }
2763 }
2764 }
2765 return -1;
2766 }
2767
2768 /**
2769 * Fixup column information for a running statement.
2770 * @param s statement to get fresh column information
2771 * @param d DBC pointer
2772 *
2773 * The column labels get the table names stripped
2774 * when there's more than one column and all table
2775 * names are identical.
2776 *
2777 * The "dyncols" field of STMT is filled with column
2778 * information obtained by SQLite "PRAGMA table_info"
2779 * for each column whose table name is known. If the
2780 * types are already present as with SQLite 2.5.7
2781 * this information is used instead.
2782 */
2783
2784 static void
fixupdyncols(STMT * s,DBC * d)2785 fixupdyncols(STMT *s, DBC *d)
2786 {
2787 int i, k;
2788 #ifndef FULL_METADATA
2789 int pk, nn, t, r, nrows, ncols;
2790 char **rowp, *flagp, flags[128];
2791 #endif
2792
2793 if (!s->dyncols) {
2794 return;
2795 }
2796 /* fixup labels */
2797 if (!s->longnames) {
2798 if (s->dcols > 1) {
2799 char *table = s->dyncols[0].table;
2800
2801 for (i = 1; table[0] && i < s->dcols; i++) {
2802 if (strcmp(s->dyncols[i].table, table)) {
2803 break;
2804 }
2805 }
2806 if (i >= s->dcols) {
2807 for (i = 0; i < s->dcols; i++) {
2808 s->dyncols[i].label = s->dyncols[i].column;
2809 }
2810 }
2811 } else if (s->dcols == 1) {
2812 s->dyncols[0].label = s->dyncols[0].column;
2813 }
2814 }
2815 for (i = 0; i < s->dcols; i++) {
2816 s->dyncols[i].type =
2817 mapsqltype(s->dyncols[i].typename, &s->dyncols[i].nosign, *s->ov3,
2818 s->nowchar[0] || s->nowchar[1], s->dobigint);
2819 getmd(s->dyncols[i].typename, s->dyncols[i].type,
2820 &s->dyncols[i].size, &s->dyncols[i].prec);
2821 #ifdef SQL_LONGVARCHAR
2822 if (s->dyncols[i].type == SQL_VARCHAR &&
2823 s->dyncols[i].size > 255) {
2824 s->dyncols[i].type = SQL_LONGVARCHAR;
2825 }
2826 #endif
2827 #ifdef WINTERFACE
2828 #ifdef SQL_WLONGVARCHAR
2829 if (s->dyncols[i].type == SQL_WVARCHAR &&
2830 s->dyncols[i].size > 255) {
2831 s->dyncols[i].type = SQL_WLONGVARCHAR;
2832 }
2833 #endif
2834 #endif
2835 if (s->dyncols[i].type == SQL_VARBINARY &&
2836 s->dyncols[i].size > 255) {
2837 s->dyncols[i].type = SQL_LONGVARBINARY;
2838 }
2839 }
2840 #ifndef FULL_METADATA
2841 if (s->dcols > array_size(flags)) {
2842 flagp = xmalloc(sizeof (flags[0]) * s->dcols);
2843 if (flagp == NULL) {
2844 return;
2845 }
2846 } else {
2847 flagp = flags;
2848 }
2849 memset(flagp, 0, sizeof (flags[0]) * s->dcols);
2850 for (i = 0; i < s->dcols; i++) {
2851 s->dyncols[i].autoinc = SQL_FALSE;
2852 s->dyncols[i].notnull = SQL_NULLABLE;
2853 }
2854 for (i = 0; i < s->dcols; i++) {
2855 int ret, lastpk = -1, autoinccount = 0;
2856 char *sql;
2857
2858 if (!s->dyncols[i].table[0]) {
2859 continue;
2860 }
2861 if (flagp[i]) {
2862 continue;
2863 }
2864 sql = sqlite3_mprintf("PRAGMA table_info(%Q)", s->dyncols[i].table);
2865 if (!sql) {
2866 continue;
2867 }
2868 dbtraceapi(d, "sqlite3_get_table", sql);
2869 ret = sqlite3_get_table(d->sqlite, sql, &rowp, &nrows, &ncols, NULL);
2870 sqlite3_free(sql);
2871 if (ret != SQLITE_OK) {
2872 continue;
2873 }
2874 k = findcol(rowp, ncols, "name");
2875 t = findcol(rowp, ncols, "type");
2876 pk = findcol(rowp, ncols, "pk");
2877 nn = findcol(rowp, ncols, "notnull");
2878 if (k < 0 || t < 0) {
2879 goto freet;
2880 }
2881 for (r = 1; r <= nrows; r++) {
2882 int m;
2883
2884 for (m = i; m < s->dcols; m++) {
2885 char *colname = s->dyncols[m].column;
2886
2887 if (s->longnames) {
2888 char *dotp = strchr(colname, '.');
2889
2890 if (dotp) {
2891 colname = dotp + 1;
2892 }
2893 }
2894 if (!flagp[m] &&
2895 strcmp(colname, rowp[r * ncols + k]) == 0 &&
2896 strcmp(s->dyncols[m].table, s->dyncols[i].table) == 0) {
2897 char *typename = rowp[r * ncols + t];
2898
2899 flagp[m] = i + 1;
2900 freep(&s->dyncols[m].typename);
2901 s->dyncols[m].typename = xstrdup(typename);
2902 s->dyncols[m].type =
2903 mapsqltype(typename, &s->dyncols[m].nosign, *s->ov3,
2904 s->nowchar[0] || s->nowchar[1],
2905 s->dobigint);
2906 getmd(typename, s->dyncols[m].type, &s->dyncols[m].size,
2907 &s->dyncols[m].prec);
2908 #ifdef SQL_LONGVARCHAR
2909 if (s->dyncols[m].type == SQL_VARCHAR &&
2910 s->dyncols[m].size > 255) {
2911 s->dyncols[m].type = SQL_LONGVARCHAR;
2912 }
2913 #endif
2914 #ifdef WINTERFACE
2915 #ifdef SQL_WLONGVARCHAR
2916 if (s->dyncols[i].type == SQL_WVARCHAR &&
2917 s->dyncols[i].size > 255) {
2918 s->dyncols[i].type = SQL_WLONGVARCHAR;
2919 }
2920 #endif
2921 #endif
2922 if (s->dyncols[i].type == SQL_VARBINARY &&
2923 s->dyncols[i].size > 255) {
2924 s->dyncols[i].type = SQL_LONGVARBINARY;
2925 }
2926 if (pk >= 0 && strcmp(rowp[r * ncols + pk], "1") == 0) {
2927 s->dyncols[m].ispk = 1;
2928 if (++autoinccount > 1) {
2929 if (lastpk >= 0) {
2930 s->dyncols[lastpk].autoinc = SQL_FALSE;
2931 lastpk = -1;
2932 }
2933 } else {
2934 lastpk = m;
2935 if (strlen(typename) == 7 &&
2936 strncasecmp(typename, "integer", 7) == 0) {
2937 s->dyncols[m].autoinc = SQL_TRUE;
2938 }
2939 }
2940 } else {
2941 s->dyncols[m].ispk = 0;
2942 }
2943 if (nn >= 0 && rowp[r * ncols + nn][0] != '0') {
2944 s->dyncols[m].notnull = SQL_NO_NULLS;
2945 }
2946 }
2947 }
2948 }
2949 freet:
2950 sqlite3_free_table(rowp);
2951 }
2952 for (i = k = 0; i < s->dcols; i++) {
2953 if (flagp[i] == 0) {
2954 break;
2955 }
2956 if (k == 0) {
2957 k = flagp[i];
2958 } else if (flagp[i] != k) {
2959 k = 0;
2960 break;
2961 }
2962 }
2963 s->one_tbl = k ? 1 : 0;
2964 k = 0;
2965 if (s->one_tbl) {
2966 for (i = 0; i < s->dcols; i++) {
2967 if (s->dyncols[i].ispk > 0) {
2968 ++k;
2969 }
2970 }
2971 }
2972 s->has_pk = k;
2973 if (flagp != flags) {
2974 freep(&flagp);
2975 }
2976 #else
2977 for (i = 1, k = 0; i < s->dcols; i++) {
2978 if (strcmp(s->dyncols[i].table, s->dyncols[0].table) == 0) {
2979 k++;
2980 }
2981 }
2982 s->one_tbl = (k && k + 1 == s->dcols) ? 1 : 0;
2983 k = 0;
2984 if (s->one_tbl) {
2985 for (i = 0; i < s->dcols; i++) {
2986 if (s->dyncols[i].ispk > 0) {
2987 ++k;
2988 if (s->has_rowid < 0 && s->dyncols[i].isrowid > 0) {
2989 s->has_rowid = i;
2990 }
2991 }
2992 }
2993 }
2994 s->has_pk = k;
2995 #endif
2996 }
2997
2998 /**
2999 * Convert julian day to year/month/day.
3000 * @param jd julian day as stored in database
3001 * @param ds output DATE_STRUCT
3002 */
3003
3004 static void
convJD2YMD(double jd,DATE_STRUCT * ds)3005 convJD2YMD(double jd, DATE_STRUCT *ds)
3006 {
3007 int z, a, b, c, d, e, x1;
3008 sqlite_int64 ijd;
3009
3010 ijd = jd * 86400000.0 + 0.5;
3011 z = (int) ((ijd + 43200000) / 86400000);
3012 a = (int) ((z - 1867216.25) / 36524.25);
3013 a = z + 1 + a - (a / 4);
3014 b = a + 1524;
3015 c = (int) ((b - 122.1) / 365.25);
3016 d = (36525 * c) / 100;
3017 e = (int) ((b - d) / 30.6001);
3018 x1 = (int) (30.6001 * e);
3019 ds->day = b - d - x1;
3020 ds->month = (e < 14) ? (e - 1) : (e - 13);
3021 ds->year = (ds->month > 2) ? (c - 4716) : (c - 4715);
3022 }
3023
3024
3025 /**
3026 * Convert julian day to hour/minute/second.
3027 * @param jd julian day as stored in database
3028 * @param ts output TIME_STRUCT
3029 * @param fp optional fractional part output
3030 */
3031
3032 static void
convJD2HMS(double jd,TIME_STRUCT * ts,int * fp)3033 convJD2HMS(double jd, TIME_STRUCT *ts, int *fp)
3034 {
3035 int s;
3036 double ds;
3037 sqlite_int64 ijd;
3038
3039 ijd = jd * 86400000.0 + 0.5;
3040 s = (int)((ijd + 43200000) % 86400000);
3041 ds = s / 1000.0;
3042 if (fp) {
3043 *fp = (s % 1000) * 1000000;
3044 }
3045 s = (int) ds;
3046 ds -= s;
3047 ts->hour = s / 3600;
3048 s -= ts->hour * 3600;
3049 ts->minute = s / 60;
3050 ds += s - ts->minute *60;
3051 ts->second = (int) ds;
3052 }
3053
3054 /**
3055 * Return number of month days.
3056 * @param year
3057 * @param month 1..12
3058 * @result number of month days or 0
3059 */
3060
3061 static int
getmdays(int year,int month)3062 getmdays(int year, int month)
3063 {
3064 static const int mdays[] = {
3065 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31
3066 };
3067 int mday;
3068
3069 if (month < 1) {
3070 return 0;
3071 }
3072 mday = mdays[(month - 1) % 12];
3073 if (mday == 28 && year % 4 == 0 &&
3074 (!(year % 100 == 0) || year % 400 == 0)) {
3075 mday++;
3076 }
3077 return mday;
3078 }
3079
3080 /**
3081 * Convert string to ODBC DATE_STRUCT.
3082 * @param jdconv when true, allow julian day format
3083 * @param str string to be converted
3084 * @param ds output DATE_STRUCT
3085 * @result 0 on success, -1 on error
3086 *
3087 * Strings of the format 'YYYYMMDD' or 'YYYY-MM-DD' or
3088 * 'YYYY/MM/DD' or 'MM/DD/YYYY' are converted to a
3089 * DATE_STRUCT.
3090 *
3091 * If the string looks like a floating point number,
3092 * SQLite3's julian day format is assumed.
3093 */
3094
3095 static int
str2date(int jdconv,char * str,DATE_STRUCT * ds)3096 str2date(int jdconv, char *str, DATE_STRUCT *ds)
3097 {
3098 int i, err = 0;
3099 double jd;
3100 char *p, *q, sepc = '\0';
3101
3102 ds->year = ds->month = ds->day = 0;
3103 if (jdconv) {
3104 p = strchr(str, '.');
3105 if (p) {
3106 /* julian day format */
3107 p = 0;
3108 jd = ln_strtod(str, &p);
3109 if (p && p > str) {
3110 convJD2YMD(jd, ds);
3111 return 0;
3112 }
3113 }
3114 }
3115 p = str;
3116 while (*p && !ISDIGIT(*p)) {
3117 ++p;
3118 }
3119 q = p;
3120 i = 0;
3121 while (*q && !ISDIGIT(*q)) {
3122 ++i;
3123 ++q;
3124 }
3125 if (i >= 8) {
3126 char buf[8];
3127
3128 strncpy(buf, p + 0, 4); buf[4] = '\0';
3129 ds->year = strtol(buf, NULL, 10);
3130 strncpy(buf, p + 4, 2); buf[2] = '\0';
3131 ds->month = strtol(buf, NULL, 10);
3132 strncpy(buf, p + 6, 2); buf[2] = '\0';
3133 ds->day = strtol(buf, NULL, 10);
3134 goto done;
3135 }
3136 i = 0;
3137 while (i < 3) {
3138 int n;
3139
3140 q = NULL;
3141 n = strtol(p, &q, 10);
3142 if (!q || q == p) {
3143 if (*q == '\0') {
3144 if (i == 0) {
3145 err = 1;
3146 }
3147 goto done;
3148 }
3149 }
3150 if (!sepc) {
3151 sepc = *q;
3152 }
3153 if (*q == '-' || *q == '/' || *q == '\0' || i == 2) {
3154 switch (i) {
3155 case 0: ds->year = n; break;
3156 case 1: ds->month = n; break;
3157 case 2: ds->day = n; break;
3158 }
3159 ++i;
3160 if (*q) {
3161 ++q;
3162 }
3163 } else {
3164 i = 0;
3165 while (*q && !ISDIGIT(*q)) {
3166 ++q;
3167 }
3168 }
3169 p = q;
3170 }
3171 done:
3172 /* final check for overflow */
3173 if (err ||
3174 ds->month < 1 || ds->month > 12 ||
3175 ds->day < 1 || ds->day > getmdays(ds->year, ds->month)) {
3176 if (sepc == '/') {
3177 /* Try MM/DD/YYYY format */
3178 int t[3];
3179
3180 t[0] = ds->year;
3181 t[1] = ds->month;
3182 t[2] = ds->day;
3183 ds->year = t[2];
3184 ds->day = t[1];
3185 ds->month = t[0];
3186 if (ds->month >= 1 && ds->month <= 12 &&
3187 (ds->day >= 1 || ds->day <= getmdays(ds->year, ds->month))) {
3188 return 0;
3189 }
3190 }
3191 return -1;
3192 }
3193 return 0;
3194 }
3195
3196 /**
3197 * Convert string to ODBC TIME_STRUCT.
3198 * @param jdconv when true, allow julian day format
3199 * @param str string to be converted
3200 * @param ts output TIME_STRUCT
3201 * @result 0 on success, -1 on error
3202 *
3203 * Strings of the format 'HHMMSS' or 'HH:MM:SS'
3204 * are converted to a TIME_STRUCT.
3205 *
3206 * If the string looks like a floating point number,
3207 * SQLite3's julian day format is assumed.
3208 */
3209
3210 static int
str2time(int jdconv,char * str,TIME_STRUCT * ts)3211 str2time(int jdconv, char *str, TIME_STRUCT *ts)
3212 {
3213 int i, err = 0, ampm = -1;
3214 double jd;
3215 char *p, *q;
3216
3217 ts->hour = ts->minute = ts->second = 0;
3218 if (jdconv) {
3219 p = strchr(str, '.');
3220 if (p) {
3221 /* julian day format */
3222 p = 0;
3223 jd = ln_strtod(str, &p);
3224 if (p && p > str) {
3225 convJD2HMS(jd, ts, 0);
3226 return 0;
3227 }
3228 }
3229 }
3230 p = str;
3231 while (*p && !ISDIGIT(*p)) {
3232 ++p;
3233 }
3234 q = p;
3235 i = 0;
3236 while (*q && ISDIGIT(*q)) {
3237 ++i;
3238 ++q;
3239 }
3240 if (i >= 6) {
3241 char buf[4];
3242
3243 strncpy(buf, p + 0, 2); buf[2] = '\0';
3244 ts->hour = strtol(buf, NULL, 10);
3245 strncpy(buf, p + 2, 2); buf[2] = '\0';
3246 ts->minute = strtol(buf, NULL, 10);
3247 strncpy(buf, p + 4, 2); buf[2] = '\0';
3248 ts->second = strtol(buf, NULL, 10);
3249 goto done;
3250 }
3251 i = 0;
3252 while (i < 3) {
3253 int n;
3254
3255 q = NULL;
3256 n = strtol(p, &q, 10);
3257 if (!q || q == p) {
3258 if (*q == '\0') {
3259 if (i == 0) {
3260 err = 1;
3261 }
3262 goto done;
3263 }
3264 }
3265 if (*q == ':' || *q == '\0' || i == 2) {
3266 switch (i) {
3267 case 0: ts->hour = n; break;
3268 case 1: ts->minute = n; break;
3269 case 2: ts->second = n; break;
3270 }
3271 ++i;
3272 if (*q) {
3273 ++q;
3274 }
3275 } else {
3276 i = 0;
3277 while (*q && !ISDIGIT(*q)) {
3278 ++q;
3279 }
3280 }
3281 p = q;
3282 }
3283 if (!err) {
3284 while (*p) {
3285 if ((p[0] == 'p' || p[0] == 'P') &&
3286 (p[1] == 'm' || p[1] == 'M')) {
3287 ampm = 1;
3288 } else if ((p[0] == 'a' || p[0] == 'A') &&
3289 (p[1] == 'm' || p[1] == 'M')) {
3290 ampm = 0;
3291 }
3292 ++p;
3293 }
3294 if (ampm > 0) {
3295 if (ts->hour < 12) {
3296 ts->hour += 12;
3297 }
3298 } else if (ampm == 0) {
3299 if (ts->hour == 12) {
3300 ts->hour = 0;
3301 }
3302 }
3303 }
3304 done:
3305 /* final check for overflow */
3306 if (err || ts->hour > 23 || ts->minute > 59 || ts->second > 59) {
3307 return -1;
3308 }
3309 return 0;
3310 }
3311
3312 /**
3313 * Convert string to ODBC TIMESTAMP_STRUCT.
3314 * @param jdconv when true, allow julian day format
3315 * @param str string to be converted
3316 * @param tss output TIMESTAMP_STRUCT
3317 * @result 0 on success, -1 on error
3318 *
3319 * Strings of the format 'YYYYMMDDhhmmssff' or 'YYYY-MM-DD hh:mm:ss ff'
3320 * or 'YYYY/MM/DD hh:mm:ss ff' or 'hh:mm:ss ff YYYY-MM-DD' are
3321 * converted to a TIMESTAMP_STRUCT. The ISO8601 formats
3322 * YYYY-MM-DDThh:mm:ss[.f]Z
3323 * YYYY-MM-DDThh:mm:ss[.f]shh:mm
3324 * are also supported. In case a time zone field is present,
3325 * the resulting TIMESTAMP_STRUCT is expressed in UTC.
3326 *
3327 * If the string looks like a floating point number,
3328 * SQLite3's julian day format is assumed.
3329 */
3330
3331 static int
str2timestamp(int jdconv,char * str,TIMESTAMP_STRUCT * tss)3332 str2timestamp(int jdconv, char *str, TIMESTAMP_STRUCT *tss)
3333 {
3334 int i, m, n, err = 0, ampm = -1;
3335 double jd;
3336 char *p, *q, in = '\0', sepc = '\0';
3337
3338 tss->year = tss->month = tss->day = 0;
3339 tss->hour = tss->minute = tss->second = 0;
3340 tss->fraction = 0;
3341 if (jdconv) {
3342 p = strchr(str, '.');
3343 if (p) {
3344 q = strchr(str, '-');
3345 if (q == str) {
3346 q = 0;
3347 }
3348 if (!q) {
3349 q = strchr(str, '/');
3350 if (!q) {
3351 q = strchr(str, ':');
3352 }
3353 }
3354 if (!q || q > p) {
3355 /* julian day format */
3356 p = 0;
3357 jd = ln_strtod(str, &p);
3358 if (p && p > str) {
3359 DATE_STRUCT ds;
3360 TIME_STRUCT ts;
3361
3362 convJD2YMD(jd, &ds);
3363 convJD2HMS(jd, &ts, &n);
3364 tss->year = ds.year;
3365 tss->month = ds.month;
3366 tss->day = ds.day;
3367 tss->hour = ts.hour;
3368 tss->minute = ts.minute;
3369 tss->second = ts.second;
3370 tss->fraction = n;
3371 return 0;
3372 }
3373 }
3374 }
3375 }
3376 p = str;
3377 while (*p && !ISDIGIT(*p)) {
3378 ++p;
3379 }
3380 q = p;
3381 i = 0;
3382 while (*q && ISDIGIT(*q)) {
3383 ++i;
3384 ++q;
3385 }
3386 if (i >= 14) {
3387 char buf[16];
3388
3389 strncpy(buf, p + 0, 4); buf[4] = '\0';
3390 tss->year = strtol(buf, NULL, 10);
3391 strncpy(buf, p + 4, 2); buf[2] = '\0';
3392 tss->month = strtol(buf, NULL, 10);
3393 strncpy(buf, p + 6, 2); buf[2] = '\0';
3394 tss->day = strtol(buf, NULL, 10);
3395 strncpy(buf, p + 8, 2); buf[2] = '\0';
3396 tss->hour = strtol(buf, NULL, 10);
3397 strncpy(buf, p + 10, 2); buf[2] = '\0';
3398 tss->minute = strtol(buf, NULL, 10);
3399 strncpy(buf, p + 12, 2); buf[2] = '\0';
3400 tss->second = strtol(buf, NULL, 10);
3401 if (i > 14) {
3402 m = i - 14;
3403 strncpy(buf, p + 14, m);
3404 while (m < 9) {
3405 buf[m] = '0';
3406 ++m;
3407 }
3408 buf[m] = '\0';
3409 tss->fraction = strtol(buf, NULL, 10);
3410 }
3411 m = 7;
3412 goto done;
3413 }
3414 m = i = 0;
3415 while ((m & 7) != 7) {
3416 q = NULL;
3417 n = strtol(p, &q, 10);
3418 if (!q || q == p) {
3419 if (*q == '\0') {
3420 if (m < 1) {
3421 err = 1;
3422 }
3423 goto done;
3424 }
3425 }
3426 if (in == '\0') {
3427 switch (*q) {
3428 case '-':
3429 case '/':
3430 if ((m & 1) == 0) {
3431 in = *q;
3432 i = 0;
3433 }
3434 break;
3435 case ':':
3436 if ((m & 2) == 0) {
3437 in = *q;
3438 i = 0;
3439 }
3440 break;
3441 case ' ':
3442 case '.':
3443 break;
3444 default:
3445 in = '\0';
3446 i = 0;
3447 break;
3448 }
3449 }
3450 switch (in) {
3451 case '-':
3452 case '/':
3453 if (!sepc) {
3454 sepc = in;
3455 }
3456 switch (i) {
3457 case 0: tss->year = n; break;
3458 case 1: tss->month = n; break;
3459 case 2: tss->day = n; break;
3460 }
3461 if (++i >= 3) {
3462 i = 0;
3463 m |= 1;
3464 if (!(m & 2)) {
3465 m |= 8;
3466 }
3467 goto skip;
3468 } else {
3469 ++q;
3470 }
3471 break;
3472 case ':':
3473 switch (i) {
3474 case 0: tss->hour = n; break;
3475 case 1: tss->minute = n; break;
3476 case 2: tss->second = n; break;
3477 }
3478 if (++i >= 3) {
3479 i = 0;
3480 m |= 2;
3481 if (*q == '.') {
3482 in = '.';
3483 goto skip2;
3484 }
3485 if (*q == ' ') {
3486 if ((m & 1) == 0) {
3487 char *e = NULL;
3488
3489 (void) strtol(q + 1, &e, 10);
3490 if (e && *e == '-') {
3491 goto skip;
3492 }
3493 }
3494 in = '.';
3495 goto skip2;
3496 }
3497 goto skip;
3498 } else {
3499 ++q;
3500 }
3501 break;
3502 case '.':
3503 if (++i >= 1) {
3504 int ndig = q - p;
3505
3506 if (p[0] == '+' || p[0] == '-') {
3507 ndig--;
3508 }
3509 while (ndig < 9) {
3510 n = n * 10;
3511 ++ndig;
3512 }
3513 tss->fraction = n;
3514 m |= 4;
3515 i = 0;
3516 }
3517 default:
3518 skip:
3519 in = '\0';
3520 skip2:
3521 while (*q && !ISDIGIT(*q)) {
3522 if ((q[0] == 'a' || q[0] == 'A') &&
3523 (q[1] == 'm' || q[1] == 'M')) {
3524 ampm = 0;
3525 ++q;
3526 } else if ((q[0] == 'p' || q[0] == 'P') &&
3527 (q[1] == 'm' || q[1] == 'M')) {
3528 ampm = 1;
3529 ++q;
3530 }
3531 ++q;
3532 }
3533 }
3534 p = q;
3535 }
3536 if ((m & 7) > 1 && (m & 8)) {
3537 /* ISO8601 timezone */
3538 if (p > str && ISDIGIT(*p)) {
3539 int nn, sign;
3540
3541 q = p - 1;
3542 if (*q != '+' && *q != '-') {
3543 goto done;
3544 }
3545 sign = (*q == '+') ? -1 : 1;
3546 q = NULL;
3547 n = strtol(p, &q, 10);
3548 if (!q || *q++ != ':' || !ISDIGIT(*q)) {
3549 goto done;
3550 }
3551 p = q;
3552 q = NULL;
3553 nn = strtol(p, &q, 10);
3554 tss->minute += nn * sign;
3555 if ((SQLSMALLINT) tss->minute < 0) {
3556 tss->hour -= 1;
3557 tss->minute += 60;
3558 } else if (tss->minute >= 60) {
3559 tss->hour += 1;
3560 tss->minute -= 60;
3561 }
3562 tss->hour += n * sign;
3563 if ((SQLSMALLINT) tss->hour < 0) {
3564 tss->day -= 1;
3565 tss->hour += 24;
3566 } else if (tss->hour >= 24) {
3567 tss->day += 1;
3568 tss->hour -= 24;
3569 }
3570 if ((short) tss->day < 1 || tss->day >= 28) {
3571 int mday, pday, pmon;
3572
3573 mday = getmdays(tss->year, tss->month);
3574 pmon = tss->month - 1;
3575 if (pmon < 1) {
3576 pmon = 12;
3577 }
3578 pday = getmdays(tss->year, pmon);
3579 if ((SQLSMALLINT) tss->day < 1) {
3580 tss->month -= 1;
3581 tss->day = pday;
3582 } else if (tss->day > mday) {
3583 tss->month += 1;
3584 tss->day = 1;
3585 }
3586 if ((SQLSMALLINT) tss->month < 1) {
3587 tss->year -= 1;
3588 tss->month = 12;
3589 } else if (tss->month > 12) {
3590 tss->year += 1;
3591 tss->month = 1;
3592 }
3593 }
3594 }
3595 }
3596 done:
3597 if ((m & 1) &&
3598 (tss->month < 1 || tss->month > 12 ||
3599 tss->day < 1 || tss->day > getmdays(tss->year, tss->month))) {
3600 if (sepc == '/') {
3601 /* Try MM/DD/YYYY format */
3602 int t[3];
3603
3604 t[0] = tss->year;
3605 t[1] = tss->month;
3606 t[2] = tss->day;
3607 tss->year = t[2];
3608 tss->day = t[1];
3609 tss->month = t[0];
3610 }
3611 }
3612 /* Replace missing year/month/day with current date */
3613 if (!err && (m & 1) == 0) {
3614 #ifdef _WIN32
3615 SYSTEMTIME t;
3616
3617 GetLocalTime(&t);
3618 tss->year = t.wYear;
3619 tss->month = t.wMonth;
3620 tss->day = t.wDay;
3621 #else
3622 struct timeval tv;
3623 struct tm tm;
3624
3625 gettimeofday(&tv, NULL);
3626 tm = *localtime(&tv.tv_sec);
3627 tss->year = tm.tm_year + 1900;
3628 tss->month = tm.tm_mon + 1;
3629 tss->day = tm.tm_mday;
3630 #endif
3631 }
3632 /* Normalize fraction */
3633 if (tss->fraction < 0) {
3634 tss->fraction = 0;
3635 }
3636 /* Final check for overflow */
3637 if (err ||
3638 tss->month < 1 || tss->month > 12 ||
3639 tss->day < 1 || tss->day > getmdays(tss->year, tss->month) ||
3640 tss->hour > 23 || tss->minute > 59 || tss->second > 59) {
3641 return -1;
3642 }
3643 if ((m & 7) > 1) {
3644 if (ampm > 0) {
3645 if (tss->hour < 12) {
3646 tss->hour += 12;
3647 }
3648 } else if (ampm == 0) {
3649 if (tss->hour == 12) {
3650 tss->hour = 0;
3651 }
3652 }
3653 }
3654 return ((m & 7) < 1) ? -1 : 0;
3655 }
3656
3657 /**
3658 * Get boolean flag from string.
3659 * @param string string to be inspected
3660 * @result true or false
3661 */
3662
3663 static int
getbool(char * string)3664 getbool(char *string)
3665 {
3666 if (string) {
3667 return string[0] && strchr("Yy123456789Tt", string[0]) != NULL;
3668 }
3669 return 0;
3670 }
3671
3672 /**
3673 * SQLite function to import a BLOB from a file
3674 * @param ctx function context
3675 * @param nargs number arguments
3676 * @param args arguments
3677 */
3678
3679 static void
blob_import(sqlite3_context * ctx,int nargs,sqlite3_value ** args)3680 blob_import(sqlite3_context *ctx, int nargs, sqlite3_value **args)
3681 {
3682 #if 0
3683 DBC *d = (DBC *) sqlite3_user_data(ctx);
3684 #endif
3685 char *filename = 0;
3686
3687 if (nargs > 0) {
3688 if (sqlite3_value_type(args[0]) != SQLITE_NULL) {
3689 filename = (char *) sqlite3_value_text(args[0]);
3690 }
3691 }
3692 if (filename) {
3693 #ifdef _WIN32
3694 char *wname = utf_to_wmb(filename, -1);
3695 FILE *f;
3696 #else
3697 FILE *f = fopen(filename, "r");
3698 #endif
3699 char *p;
3700 long n, nn;
3701
3702 #ifdef _WIN32
3703 if (wname) {
3704 f = fopen(wname, "rb");
3705 } else {
3706 sqlite3_result_error(ctx, "out of memory", -1);
3707 return;
3708 }
3709 uc_free(wname);
3710 #endif
3711 if (f) {
3712 if (fseek(f, 0, SEEK_END) == 0) {
3713 n = ftell(f);
3714 if (fseek(f, 0, SEEK_SET) == 0) {
3715 p = sqlite3_malloc(n);
3716 if (p) {
3717 nn = fread(p, 1, n, f);
3718 if (nn != n) {
3719 sqlite3_result_error(ctx, "read error", -1);
3720 sqlite3_free(p);
3721 } else {
3722 sqlite3_result_blob(ctx, p, n, sqlite3_free);
3723 }
3724 } else {
3725 sqlite3_result_error(ctx, "out of memory", -1);
3726 }
3727 } else {
3728 sqlite3_result_error(ctx, "seek error", -1);
3729 }
3730 } else {
3731 sqlite3_result_error(ctx, "seek error", -1);
3732 }
3733 fclose(f);
3734 } else {
3735 sqlite3_result_error(ctx, "cannot open file", -1);
3736 }
3737 } else {
3738 sqlite3_result_error(ctx, "no filename given", -1);
3739 }
3740 }
3741
3742 /**
3743 * SQLite function to export a BLOB to a file
3744 * @param ctx function context
3745 * @param nargs number arguments
3746 * @param args arguments
3747 */
3748
3749 static void
blob_export(sqlite3_context * ctx,int nargs,sqlite3_value ** args)3750 blob_export(sqlite3_context *ctx, int nargs, sqlite3_value **args)
3751 {
3752 #if 0
3753 DBC *d = (DBC *) sqlite3_user_data(ctx);
3754 #endif
3755 char *filename = 0;
3756 char *p = 0;
3757 int n = 0;
3758
3759 if (nargs > 0) {
3760 p = (char *) sqlite3_value_blob(args[0]);
3761 n = sqlite3_value_bytes(args[0]);
3762 }
3763 if (nargs > 1) {
3764 if (sqlite3_value_type(args[1]) != SQLITE_NULL) {
3765 filename = (char *) sqlite3_value_text(args[1]);
3766 }
3767 }
3768 if (p) {
3769 if (filename) {
3770 #ifdef _WIN32
3771 char *wname = utf_to_wmb(filename, -1);
3772 FILE *f;
3773 #else
3774 FILE *f = fopen(filename, "w");
3775 #endif
3776 int nn;
3777
3778 #ifdef _WIN32
3779 if (wname) {
3780 f = fopen(wname, "wb");
3781 } else {
3782 sqlite3_result_error(ctx, "out of memory", -1);
3783 return;
3784 }
3785 uc_free(wname);
3786 #endif
3787 if (f) {
3788 nn = fwrite(p, 1, n, f);
3789 fclose(f);
3790 if (nn != n) {
3791 sqlite3_result_error(ctx, "write error", -1);
3792 } else {
3793 sqlite3_result_int(ctx, nn);
3794 }
3795 } else {
3796 sqlite3_result_error(ctx, "cannot open file", -1);
3797 }
3798 } else {
3799 sqlite3_result_error(ctx, "no filename given", -1);
3800 }
3801 } else {
3802 sqlite3_result_null(ctx);
3803 }
3804 }
3805
3806 /**
3807 * SQLite trace or profile callback
3808 * @param arg DBC pointer
3809 * @param msg log message, SQL text
3810 * @param et elapsed time
3811 */
3812
3813 static void
3814 #if defined(HAVE_SQLITE3PROFILE) && (HAVE_SQLITE3PROFILE)
dbtrace(void * arg,const char * msg,sqlite_uint64 et)3815 dbtrace(void *arg, const char *msg, sqlite_uint64 et)
3816 #else
3817 dbtrace(void *arg, const char *msg)
3818 #endif
3819 {
3820 DBC *d = (DBC *) arg;
3821
3822 if (msg && d->trace) {
3823 int len = strlen(msg);
3824 #if defined(HAVE_SQLITE3PROFILE) && (HAVE_SQLITE3PROFILE)
3825 unsigned long s, f;
3826 #endif
3827
3828 if (len > 0) {
3829 char *end = "\n";
3830
3831 if (msg[len - 1] != ';') {
3832 end = ";\n";
3833 }
3834 fprintf(d->trace, "%s%s", msg, end);
3835 #if defined(HAVE_SQLITE3PROFILE) && (HAVE_SQLITE3PROFILE)
3836 s = et / 1000000000LL;
3837 f = et % 1000000000LL;
3838 fprintf(d->trace, "-- took %lu.%09lu seconds\n", s, f);
3839 #endif
3840 fflush(d->trace);
3841 }
3842 }
3843 }
3844
3845 /**
3846 * Trace function for SQLite API calls
3847 * @param d pointer to database connection handle
3848 * @param fn SQLite function name
3849 * @param sql SQL string
3850 */
3851
3852 static void
dbtraceapi(DBC * d,char * fn,const char * sql)3853 dbtraceapi(DBC *d, char *fn, const char *sql)
3854 {
3855 if (fn && d->trace) {
3856 if (sql) {
3857 fprintf(d->trace, "-- %s: %s\n", fn, sql);
3858 } else {
3859 fprintf(d->trace, "-- %s\n", fn);
3860 }
3861 fflush(d->trace);
3862 }
3863 }
3864
3865 /**
3866 * Trace function for SQLite return codes
3867 * @param d pointer to database connection handle
3868 * @param rc SQLite return code
3869 * @param err error string or NULL
3870 */
3871
3872 static void
dbtracerc(DBC * d,int rc,char * err)3873 dbtracerc(DBC *d, int rc, char *err)
3874 {
3875 if (rc != SQLITE_OK && d->trace) {
3876 fprintf(d->trace, "-- SQLITE ERROR CODE %d", rc);
3877 fprintf(d->trace, err ? ": %s\n" : "\n", err);
3878 fflush(d->trace);
3879 }
3880 }
3881
3882 /**
3883 * Open SQLite database file given file name and flags.
3884 * @param d DBC pointer
3885 * @param name file name
3886 * @param isu true/false: file name is UTF8 encoded
3887 * @param dsn data source name
3888 * @param sflag STEPAPI flag
3889 * @param spflag SyncPragma string
3890 * @param ntflag NoTransaction string
3891 * @param jmode JournalMode string
3892 * @param busy busy/lock timeout
3893 * @result ODBC error code
3894 */
3895
3896 static SQLRETURN
dbopen(DBC * d,char * name,int isu,char * dsn,char * sflag,char * spflag,char * ntflag,char * jmode,char * busy)3897 dbopen(DBC *d, char *name, int isu, char *dsn, char *sflag,
3898 char *spflag, char *ntflag, char *jmode, char *busy)
3899 {
3900 char *endp = NULL;
3901 int rc, tmp, busyto = 100000;
3902 #if defined(HAVE_SQLITE3VFS) && (HAVE_SQLITE3VFS)
3903 int flags = SQLITE_OPEN_READWRITE | SQLITE_OPEN_CREATE;
3904 char *uname = name;
3905 const char *vfs_name = NULL;
3906 #endif
3907
3908 if (d->sqlite) {
3909 if (d->trace) {
3910 fprintf(d->trace, "-- sqlite3_close (deferred): '%s'\n",
3911 d->dbname);
3912 fflush(d->trace);
3913 }
3914 #if defined(HAVE_SQLITE3CLOSEV2) && (HAVE_SQLITE3CLOSEV2)
3915 sqlite3_close_v2(d->sqlite);
3916 #else
3917 sqlite3_close(d->sqlite);
3918 #endif
3919 d->sqlite = NULL;
3920 }
3921 #if defined(HAVE_SQLITE3VFS) && (HAVE_SQLITE3VFS)
3922 if (d->nocreat) {
3923 flags &= ~ SQLITE_OPEN_CREATE;
3924 }
3925 #if defined(_WIN32) || defined(_WIN64)
3926 if (!isu) {
3927 char expname[SQL_MAX_MESSAGE_LENGTH * 2];
3928
3929 expname[0] = '\0';
3930 rc = ExpandEnvironmentStrings(name, expname, sizeof (expname));
3931 if (rc <= sizeof (expname)) {
3932 uname = wmb_to_utf(expname, rc - 1);
3933 } else {
3934 uname = wmb_to_utf(name, -1);
3935 }
3936 if (!uname) {
3937 rc = SQLITE_NOMEM;
3938 setstatd(d, rc, "out of memory", (*d->ov3) ? "HY000" : "S1000");
3939 return SQL_ERROR;
3940 }
3941 }
3942 #endif
3943 #if defined(ENABLE_NVFS) && (ENABLE_NVFS)
3944 vfs_name = nvfs_makevfs(uname);
3945 #endif
3946 #ifdef SQLITE_OPEN_URI
3947 flags |= SQLITE_OPEN_URI;
3948 #endif
3949 rc = sqlite3_open_v2(uname, &d->sqlite, flags, vfs_name);
3950 #if defined(WINTERFACE) || defined(_WIN32) || defined(_WIN64)
3951 if (uname != name) {
3952 uc_free(uname);
3953 }
3954 #endif
3955 #else
3956 #if defined(_WIN32) || defined(_WIN64)
3957 if (d->nocreat) {
3958 char *cname = NULL;
3959
3960 if (isu) {
3961 cname = utf_to_wmb(name, -1);
3962 }
3963 if (GetFileAttributesA(cname ? cname : name) ==
3964 INVALID_FILE_ATTRIBUTES) {
3965 uc_free(cname);
3966 rc = SQLITE_CANTOPEN;
3967 setstatd(d, rc, "cannot open database",
3968 (*d->ov3) ? "HY000" : "S1000");
3969 return SQL_ERROR;
3970 }
3971 uc_free(cname);
3972 }
3973 #else
3974 if (d->nocreat && access(name, 004) < 0) {
3975 rc = SQLITE_CANTOPEN;
3976 setstatd(d, rc, "cannot open database", (*d->ov3) ? "HY000" : "S1000");
3977 return SQL_ERROR;
3978 }
3979 #endif
3980 #if defined(_WIN32) || defined(_WIN64)
3981 if (!isu) {
3982 WCHAR *wname = wmb_to_uc(name, -1);
3983
3984 if (!wname) {
3985 rc = SQLITE_NOMEM;
3986 setstatd(d, rc, "out of memory", (*d->ov3) ? "HY000" : "S1000");
3987 return SQL_ERROR;
3988 }
3989 rc = sqlite3_open16(wname, &d->sqlite);
3990 uc_free(wname);
3991 } else
3992 #endif
3993 rc = sqlite3_open(name, &d->sqlite);
3994 #endif /* !HAVE_SQLITE3VFS */
3995 if (rc != SQLITE_OK) {
3996 connfail:
3997 setstatd(d, rc, "connect failed", (*d->ov3) ? "HY000" : "S1000");
3998 if (d->sqlite) {
3999 sqlite3_close(d->sqlite);
4000 d->sqlite = NULL;
4001 }
4002 return SQL_ERROR;
4003 }
4004 #if defined(SQLITE_DYNLOAD) || defined(SQLITE_HAS_CODEC)
4005 if (d->pwd) {
4006 sqlite3_key(d->sqlite, d->pwd, d->pwdLen);
4007 }
4008 #endif
4009 d->pwd = NULL;
4010 d->pwdLen = 0;
4011 if (d->trace) {
4012 #if defined(HAVE_SQLITE3PROFILE) && (HAVE_SQLITE3PROFILE)
4013 sqlite3_profile(d->sqlite, dbtrace, d);
4014 #else
4015 sqlite3_trace(d->sqlite, dbtrace, d);
4016 #endif
4017 }
4018 d->step_enable = getbool(sflag);
4019 d->trans_disable = getbool(ntflag);
4020 d->curtype = d->step_enable ?
4021 SQL_CURSOR_FORWARD_ONLY : SQL_CURSOR_STATIC;
4022 tmp = strtol(busy, &endp, 0);
4023 if (endp && *endp == '\0' && endp != busy) {
4024 busyto = tmp;
4025 }
4026 if (busyto < 1 || busyto > 1000000) {
4027 busyto = 1000000;
4028 }
4029 d->timeout = busyto;
4030 freep(&d->dbname);
4031 d->dbname = xstrdup(name);
4032 freep(&d->dsn);
4033 d->dsn = xstrdup(dsn);
4034 if ((rc = setsqliteopts(d->sqlite, d)) != SQLITE_OK) {
4035 if (d->trace) {
4036 fprintf(d->trace, "-- sqlite3_close: '%s'\n",
4037 d->dbname);
4038 fflush(d->trace);
4039 }
4040 sqlite3_close(d->sqlite);
4041 d->sqlite = NULL;
4042 goto connfail;
4043 }
4044 if (!spflag || spflag[0] == '\0') {
4045 spflag = "NORMAL";
4046 }
4047 if (spflag[0] != '\0') {
4048 char syncp[128];
4049
4050 sprintf(syncp, "PRAGMA synchronous = %8.8s;", spflag);
4051 sqlite3_exec(d->sqlite, syncp, NULL, NULL, NULL);
4052 }
4053 if (jmode[0] != '\0') {
4054 char jourp[128];
4055
4056 sprintf(jourp, "PRAGMA journal_mode = %16.16s;", jmode);
4057 sqlite3_exec(d->sqlite, jourp, NULL, NULL, NULL);
4058 }
4059 if (d->trace) {
4060 fprintf(d->trace, "-- sqlite3_open: '%s'\n", d->dbname);
4061 fflush(d->trace);
4062 }
4063 #if defined(_WIN32) || defined(_WIN64)
4064 {
4065 char pname[MAX_PATH];
4066 HANDLE h = OpenProcess(PROCESS_QUERY_INFORMATION | PROCESS_VM_READ,
4067 FALSE, GetCurrentProcessId());
4068
4069 pname[0] = '\0';
4070 if (h) {
4071 HMODULE m = NULL, l = LoadLibrary("psapi.dll");
4072 DWORD need;
4073 typedef BOOL (WINAPI *epmfunc)(HANDLE, HMODULE *, DWORD, LPDWORD);
4074 typedef BOOL (WINAPI *gmbfunc)(HANDLE, HMODULE, LPSTR, DWORD);
4075 epmfunc epm;
4076 gmbfunc gmb;
4077
4078 if (l) {
4079 epm = (epmfunc) GetProcAddress(l, "EnumProcessModules");
4080 gmb = (gmbfunc) GetProcAddress(l, "GetModuleBaseNameA");
4081 if (epm && gmb && epm(h, &m, sizeof (m), &need)) {
4082 gmb(h, m, pname, sizeof (pname));
4083 }
4084 FreeLibrary(l);
4085 }
4086 CloseHandle(h);
4087 }
4088 d->xcelqrx = strncasecmp(pname, "EXCEL", 5) == 0 ||
4089 strncasecmp(pname, "MSQRY", 5) == 0;
4090 if (d->trace && d->xcelqrx) {
4091
4092 fprintf(d->trace, "-- enabled EXCEL quirks\n");
4093 fflush(d->trace);
4094 }
4095 }
4096 #endif
4097 sqlite3_create_function(d->sqlite, "blob_import", 1, SQLITE_UTF8,
4098 d, blob_import, 0, 0);
4099 sqlite3_create_function(d->sqlite, "blob_export", 2, SQLITE_UTF8,
4100 d, blob_export, 0, 0);
4101 return SQL_SUCCESS;
4102 }
4103
4104 /**
4105 * Load SQLite extension modules, if any
4106 * @param d DBC pointer
4107 * @param exts string, comma separated extension names
4108 */
4109
4110 static void
dbloadext(DBC * d,char * exts)4111 dbloadext(DBC *d, char *exts)
4112 {
4113 #if defined(HAVE_SQLITE3LOADEXTENSION) && (HAVE_SQLITE3LOADEXTENSION)
4114 char *p;
4115 char path[SQL_MAX_MESSAGE_LENGTH];
4116 int plen = 0;
4117
4118 if (!d->sqlite) {
4119 return;
4120 }
4121 sqlite3_enable_load_extension(d->sqlite, 1);
4122 #if defined(_WIN32) || defined(_WIN64)
4123 GetModuleFileName(hModule, path, sizeof (path));
4124 p = strrchr(path, '\\');
4125 plen = p ? ((p + 1) - path) : 0;
4126 #endif
4127 do {
4128 p = strchr(exts, ',');
4129 if (p) {
4130 strncpy(path + plen, exts, p - exts);
4131 path[plen + (p - exts)] = '\0';
4132 } else {
4133 strcpy(path + plen, exts);
4134 }
4135 if (exts[0]) {
4136 char *errmsg = NULL;
4137 int rc;
4138 #if defined(_WIN32) || defined(_WIN64)
4139 int i;
4140 char *q;
4141
4142 q = path + plen;
4143 if (!(q[0] &&
4144 ((q[1] == ':' && (q[2] == '\\' || q[2] == '/')) ||
4145 q[0] == '\\' || q[0] == '/' || q[0] == '.'))) {
4146 q = path;
4147 }
4148 /* sqlite3_load_extension() dislikes backslashes */
4149 for (i = 0; q[i] != '\0'; i++) {
4150 if (q[i] == '\\') {
4151 q[i] = '/';
4152 }
4153 }
4154 rc = sqlite3_load_extension(d->sqlite, q, 0, &errmsg);
4155 #else
4156 rc = sqlite3_load_extension(d->sqlite, path, 0, &errmsg);
4157 #endif
4158 if (rc != SQLITE_OK) {
4159 #if defined(_WIN32) || defined(_WIN64)
4160 char buf[512], msg[512];
4161
4162 LoadString(hModule, IDS_EXTERR, buf, sizeof (buf));
4163 wsprintf(msg, buf, q, errmsg ?
4164 errmsg : "no error info available");
4165 LoadString(hModule, IDS_EXTTITLE, buf, sizeof (buf));
4166 MessageBox(NULL, msg, buf,
4167 MB_ICONEXCLAMATION | MB_OK | MB_TASKMODAL |
4168 MB_SETFOREGROUND);
4169 #else
4170 fprintf(stderr, "extension '%s' did not load%s%s\n",
4171 path, errmsg ? ": " : "", errmsg ? errmsg : "");
4172 #endif
4173 }
4174 }
4175 if (p) {
4176 exts = p + 1;
4177 }
4178 } while (p);
4179 #endif /* HAVE_SQLITE3LOADEXTENSION */
4180 }
4181
4182 /**
4183 * Find out column type
4184 * @param s3stmt SQLite statement pointer
4185 * @param col column number
4186 * @param d DBC pointer (for tracing only)
4187 * @param guessed_types flag array
4188 * @result type name as string
4189 */
4190
4191 static char *
s3stmt_coltype(sqlite3_stmt * s3stmt,int col,DBC * d,int * guessed_types)4192 s3stmt_coltype(sqlite3_stmt *s3stmt, int col, DBC *d, int *guessed_types)
4193 {
4194 char *typename = (char *) sqlite3_column_decltype(s3stmt, col);
4195 char guess[64];
4196
4197 guess[0] = '\0';
4198 if (!typename) {
4199 int coltype = sqlite3_column_type(s3stmt, col);
4200
4201 if (guessed_types) {
4202 guessed_types[0]++;
4203 }
4204 if (d->trace) {
4205 sprintf(guess, " (guessed from %d)", coltype);
4206 }
4207 switch (coltype) {
4208 case SQLITE_INTEGER: typename = "integer"; break;
4209 case SQLITE_FLOAT: typename = "double"; break;
4210 default:
4211 case SQLITE_TEXT: typename = "varchar"; break;
4212 case SQLITE_BLOB: typename = "blob"; break;
4213 #if 0
4214 case SQLITE_NULL: typename = "null"; break;
4215 #endif
4216 }
4217 }
4218 if (d->trace) {
4219 fprintf(d->trace, "-- column %d type%s: '%s'\n", col + 1,
4220 guess, typename);
4221 fflush(d->trace);
4222 }
4223 return typename;
4224 }
4225
4226 #ifdef FULL_METADATA
4227
4228 /**
4229 * Add meta data for column
4230 * @param s3stmt SQLite statement pointer
4231 * @param col column number
4232 * @param d DBC pointer (for tracing only)
4233 * @param ci pointer to COL
4234 */
4235
4236 static void
s3stmt_addmeta(sqlite3_stmt * s3stmt,int col,DBC * d,COL * ci)4237 s3stmt_addmeta(sqlite3_stmt *s3stmt, int col, DBC *d, COL *ci)
4238 {
4239 int nn = 0, pk = 0, ai = 0;
4240 const char *dn = NULL, *tn = NULL, *cn = NULL, *dummy[4];
4241
4242 dn = sqlite3_column_database_name(s3stmt, col);
4243 tn = sqlite3_column_table_name(s3stmt, col);
4244 cn = sqlite3_column_origin_name(s3stmt, col);
4245 dummy[0] = dummy[1] = 0;
4246 if (tn && cn) {
4247 sqlite3_table_column_metadata(d->sqlite, dn, tn, cn,
4248 dummy, dummy + 1,
4249 &nn, &pk, &ai);
4250 }
4251 ci->autoinc = ai ? SQL_TRUE: SQL_FALSE;
4252 ci->notnull = nn ? SQL_NO_NULLS : SQL_NULLABLE;
4253 ci->ispk = pk ? 1 : 0;
4254 if (d->trace) {
4255 fprintf(d->trace, "-- column %d %s\n",
4256 col + 1, nn ? "notnull" : "nullable");
4257 if (ai) {
4258 fprintf(d->trace, "-- column %d autoincrement\n", col + 1);
4259 }
4260 fflush(d->trace);
4261 }
4262 ci->isrowid = 0;
4263 if (ci->ispk && tn) {
4264 nn = pk = ai = 0;
4265 dummy[2] = dummy[3] = 0;
4266
4267 sqlite3_table_column_metadata(d->sqlite, dn, tn, "rowid",
4268 dummy + 2, dummy + 3,
4269 &nn, &pk, &ai);
4270 if (pk && dummy[0] && dummy[0] == dummy[2]) {
4271 ci->isrowid = 1;
4272 }
4273 }
4274 }
4275
4276 #endif
4277
4278 /**
4279 * Do one sqlite statement step gathering one result row
4280 * @param s statement pointer
4281 * @result ODBC error code
4282 */
4283
4284 static int
s3stmt_step(STMT * s)4285 s3stmt_step(STMT *s)
4286 {
4287 DBC *d = (DBC *) s->dbc;
4288 char **rowd = NULL;
4289 const char *errp = NULL;
4290 int i, ncols, rc;
4291
4292 if (s != d->cur_s3stmt || !s->s3stmt) {
4293 setstat(s, -1, "stale statement", (*s->ov3) ? "HY000" : "S1000");
4294 return SQL_ERROR;
4295 }
4296 rc = sqlite3_step(s->s3stmt);
4297 if (rc == SQLITE_ROW || rc == SQLITE_DONE) {
4298 ++s->s3stmt_rownum;
4299 ncols = sqlite3_column_count(s->s3stmt);
4300 if (d->s3stmt_needmeta && s->s3stmt_rownum == 0 && ncols > 0) {
4301 PTRDIFF_T size;
4302 char *p;
4303 COL *dyncols;
4304 const char *colname, *typename;
4305 #if defined(HAVE_SQLITE3COLUMNTABLENAME) && (HAVE_SQLITE3COLUMNTABLENAME)
4306 char *tblname;
4307 #endif
4308 #if defined(HAVE_SQLITE3COLUMNDATABASENAME) && (HAVE_SQLITE3COLUMNDATABASENAME)
4309 char *dbname;
4310 #endif
4311
4312 for (i = size = 0; i < ncols; i++) {
4313 colname = sqlite3_column_name(s->s3stmt, i);
4314 size += 3 + 3 * strlen(colname);
4315 }
4316 #if defined(HAVE_SQLITE3COLUMNTABLENAME) && (HAVE_SQLITE3COLUMNTABLENAME)
4317 tblname = (char *) size;
4318 for (i = 0; i < ncols; i++) {
4319 p = (char *) sqlite3_column_table_name(s->s3stmt, i);
4320 size += 2 + (p ? strlen(p) : 0);
4321 }
4322 #endif
4323 #if defined(HAVE_SQLITE3COLUMNDATABASENAME) && (HAVE_SQLITE3COLUMNDATABASENAME)
4324 dbname = (char *) size;
4325 for (i = 0; i < ncols; i++) {
4326 p = (char *) sqlite3_column_database_name(s->s3stmt, i);
4327 size += 2 + (p ? strlen(p) : 0);
4328 }
4329 #endif
4330 dyncols = xmalloc(ncols * sizeof (COL) + size);
4331 if (!dyncols) {
4332 freedyncols(s);
4333 s->ncols = 0;
4334 dbtraceapi(d, "sqlite3_finalize", 0);
4335 sqlite3_finalize(s->s3stmt);
4336 s->s3stmt = NULL;
4337 d->cur_s3stmt = NULL;
4338 return nomem(s);
4339 }
4340 p = (char *) (dyncols + ncols);
4341 #if defined(HAVE_SQLITE3COLUMNTABLENAME) && (HAVE_SQLITE3COLUMNTABLENAME)
4342 tblname = p + (PTRDIFF_T) tblname;
4343 #endif
4344 #if defined(HAVE_SQLITE3COLUMNDATABASENAME) && (HAVE_SQLITE3COLUMNDATABASENAME)
4345 dbname = p + (PTRDIFF_T) dbname;
4346 #endif
4347 for (i = 0; i < ncols; i++) {
4348 char *q;
4349
4350 colname = sqlite3_column_name(s->s3stmt, i);
4351 if (d->trace) {
4352 fprintf(d->trace, "-- column %d name: '%s'\n",
4353 i + 1, colname);
4354 fflush(d->trace);
4355 }
4356 #if defined(HAVE_SQLITE3COLUMNTABLENAME) && (HAVE_SQLITE3COLUMNTABLENAME)
4357 q = (char *) sqlite3_column_table_name(s->s3stmt, i);
4358 strcpy(tblname, q ? q : "");
4359 if (d->trace) {
4360 fprintf(d->trace, "-- table %d name: '%s'\n",
4361 i + 1, tblname);
4362 fflush(d->trace);
4363 }
4364 dyncols[i].table = tblname;
4365 tblname += strlen(tblname) + 1;
4366 #endif
4367 #if defined(HAVE_SQLITE3COLUMNDATABASENAME) && (HAVE_SQLITE3COLUMNDATABASENAME)
4368 q = (char *) sqlite3_column_database_name(s->s3stmt, i);
4369 strcpy(dbname, q ? q : "");
4370 if (d->trace) {
4371 fprintf(d->trace, "-- database %d name: '%s'\n",
4372 i + 1, dbname);
4373 fflush(d->trace);
4374 }
4375 dyncols[i].db = dbname;
4376 dbname += strlen(dbname) + 1;
4377 #else
4378 dyncols[i].db = ((DBC *) (s->dbc))->dbname;
4379 #endif
4380 typename = s3stmt_coltype(s->s3stmt, i, d, 0);
4381 strcpy(p, colname);
4382 dyncols[i].label = p;
4383 p += strlen(p) + 1;
4384 q = strchr(colname, '.');
4385 if (q) {
4386 char *q2 = strchr(q + 1, '.');
4387
4388 /* SQLite 3.3.4 produces view.table.column sometimes */
4389 if (q2) {
4390 q = q2;
4391 }
4392 }
4393 if (q) {
4394 #if !defined(HAVE_SQLITE3COLUMNTABLENAME) || !(HAVE_SQLITE3COLUMNTABLENAME)
4395 dyncols[i].table = p;
4396 #endif
4397 strncpy(p, colname, q - colname);
4398 p[q - colname] = '\0';
4399 p += strlen(p) + 1;
4400 strcpy(p, q + 1);
4401 dyncols[i].column = p;
4402 p += strlen(p) + 1;
4403 } else {
4404 #if !defined(HAVE_SQLITE3COLUMNTABLENAME) || !(HAVE_SQLITE3COLUMNTABLENAME)
4405 dyncols[i].table = "";
4406 #endif
4407 strcpy(p, colname);
4408 dyncols[i].column = p;
4409 p += strlen(p) + 1;
4410 }
4411 if (s->longnames) {
4412 dyncols[i].column = dyncols[i].label;
4413 }
4414 #ifdef SQL_LONGVARCHAR
4415 dyncols[i].type = SQL_LONGVARCHAR;
4416 dyncols[i].size = 65535;
4417 #else
4418 dyncols[i].type = SQL_VARCHAR;
4419 dyncols[i].size = 255;
4420 #endif
4421 dyncols[i].index = i;
4422 dyncols[i].scale = 0;
4423 dyncols[i].prec = 0;
4424 dyncols[i].nosign = 1;
4425 dyncols[i].autoinc = SQL_FALSE;
4426 dyncols[i].notnull = SQL_NULLABLE;
4427 dyncols[i].ispk = -1;
4428 dyncols[i].isrowid = -1;
4429 #ifdef FULL_METADATA
4430 s3stmt_addmeta(s->s3stmt, i, d, &dyncols[i]);
4431 #endif
4432 dyncols[i].typename = xstrdup(typename);
4433 }
4434 freedyncols(s);
4435 s->ncols = s->dcols = ncols;
4436 s->dyncols = s->cols = dyncols;
4437 fixupdyncols(s, d);
4438 mkbindcols(s, s->ncols);
4439 d->s3stmt_needmeta = 0;
4440 }
4441 if (ncols <= 0) {
4442 goto killstmt;
4443 }
4444 if (rc == SQLITE_DONE) {
4445 freeresult(s, 0);
4446 s->nrows = 0;
4447 dbtraceapi(d, "sqlite3_finalize", 0);
4448 sqlite3_finalize(s->s3stmt);
4449 s->s3stmt = NULL;
4450 d->cur_s3stmt = NULL;
4451 return SQL_SUCCESS;
4452 }
4453 rowd = xmalloc((1 + 2 * ncols) * sizeof (char *));
4454 if (rowd) {
4455 const unsigned char *value;
4456
4457 rowd[0] = (char *) ((PTRDIFF_T) (ncols * 2));
4458 ++rowd;
4459 for (i = 0; i < ncols; i++) {
4460 int coltype = sqlite3_column_type(s->s3stmt, i);
4461
4462 rowd[i] = rowd[i + ncols] = NULL;
4463 if (coltype == SQLITE_BLOB) {
4464 int k, nbytes = sqlite3_column_bytes(s->s3stmt, i);
4465 char *qp;
4466 unsigned const char *bp;
4467
4468 bp = sqlite3_column_blob(s->s3stmt, i);
4469 qp = xmalloc(nbytes * 2 + 4);
4470 if (qp) {
4471 rowd[i + ncols] = qp;
4472 *qp++ = 'X';
4473 *qp++ = '\'';
4474 for (k = 0; k < nbytes; k++) {
4475 *qp++ = xdigits[(bp[k] >> 4)];
4476 *qp++ = xdigits[(bp[k] & 0xF)];
4477 }
4478 *qp++ = '\'';
4479 *qp = '\0';
4480 }
4481 #ifdef _MSC_VER
4482 } else if (coltype == SQLITE_FLOAT) {
4483 struct lconv *lc = 0;
4484 double d = sqlite3_column_double(s->s3stmt, i);
4485 char *p, buffer[128];
4486
4487 /*
4488 * This avoids floating point rounding
4489 * and formatting problems of some SQLite
4490 * versions in conjunction with MSVC 2010.
4491 */
4492 snprintf(buffer, sizeof (buffer), "%.15g", d);
4493 lc = localeconv();
4494 if (lc && lc->decimal_point && lc->decimal_point[0] &&
4495 lc->decimal_point[0] != '.') {
4496 p = strchr(buffer, lc->decimal_point[0]);
4497 if (p) {
4498 *p = '.';
4499 }
4500 }
4501 rowd[i + ncols] = xstrdup(buffer);
4502 #endif
4503 } else if (coltype != SQLITE_NULL) {
4504 value = sqlite3_column_text(s->s3stmt, i);
4505 rowd[i + ncols] = xstrdup((char *) value);
4506 }
4507 }
4508 for (i = 0; i < ncols; i++) {
4509 int coltype = sqlite3_column_type(s->s3stmt, i);
4510
4511 value = NULL;
4512 if (coltype == SQLITE_BLOB) {
4513 value = sqlite3_column_blob(s->s3stmt, i);
4514 } else if (coltype != SQLITE_NULL) {
4515 value = sqlite3_column_text(s->s3stmt, i);
4516 }
4517 if (value && !rowd[i + ncols]) {
4518 freerows(rowd);
4519 rowd = 0;
4520 break;
4521 }
4522 }
4523 }
4524 if (rowd) {
4525 freeresult(s, 0);
4526 s->nrows = 1;
4527 s->rows = rowd;
4528 s->rowfree = freerows;
4529 if (rc == SQLITE_DONE) {
4530 dbtraceapi(d, "sqlite3_finalize", 0);
4531 sqlite3_finalize(s->s3stmt);
4532 s->s3stmt = NULL;
4533 d->cur_s3stmt = NULL;
4534 }
4535 return SQL_SUCCESS;
4536 }
4537 }
4538 killstmt:
4539 dbtraceapi(d, "sqlite3_reset", 0);
4540 rc = sqlite3_reset(s->s3stmt);
4541 s->s3stmt_noreset = 1;
4542 errp = sqlite3_errmsg(d->sqlite);
4543 if (d->cur_s3stmt == s) {
4544 d->cur_s3stmt = NULL;
4545 }
4546 setstat(s, rc, "%s (%d)", (*s->ov3) ? "HY000" : "S1000",
4547 errp ? errp : "unknown error", rc);
4548 return SQL_ERROR;
4549 }
4550
4551 /**
4552 * Stop running sqlite statement
4553 * @param s statement pointer
4554 */
4555
4556 static void
s3stmt_end(STMT * s)4557 s3stmt_end(STMT *s)
4558 {
4559 DBC *d;
4560
4561 if (!s || !s->s3stmt) {
4562 return;
4563 }
4564 d = (DBC *) s->dbc;
4565 if (d) {
4566 d->busyint = 0;
4567 }
4568 if (!s->s3stmt_noreset) {
4569 dbtraceapi(d, "sqlite3_reset", 0);
4570 sqlite3_reset(s->s3stmt);
4571 s->s3stmt_noreset = 1;
4572 s->s3stmt_rownum = -1;
4573 }
4574 if (d->cur_s3stmt == s) {
4575 d->cur_s3stmt = NULL;
4576 }
4577 }
4578
4579 /**
4580 * Conditionally stop running sqlite statement
4581 * @param s statement pointer
4582 */
4583
4584 static void
s3stmt_end_if(STMT * s)4585 s3stmt_end_if(STMT *s)
4586 {
4587 DBC *d = (DBC *) s->dbc;
4588
4589 if (d) {
4590 d->busyint = 0;
4591 }
4592 if (d && d->cur_s3stmt == s) {
4593 s3stmt_end(s);
4594 }
4595 }
4596
4597 /**
4598 * Drop running sqlite statement in STMT
4599 * @param s statement pointer
4600 */
4601
4602 static void
s3stmt_drop(STMT * s)4603 s3stmt_drop(STMT *s)
4604 {
4605 if (s->s3stmt) {
4606 DBC *d = (DBC *) s->dbc;
4607
4608 if (d) {
4609 dbtraceapi(d, "sqlite3_finalize", 0);
4610 }
4611 sqlite3_finalize(s->s3stmt);
4612 s->s3stmt = NULL;
4613 s->s3stmt_rownum = 0;
4614 }
4615 }
4616
4617 /**
4618 * Start sqlite statement for execution of SELECT statement.
4619 * @param s statement pointer
4620 * @result ODBC error code
4621 */
4622
4623 static SQLRETURN
s3stmt_start(STMT * s)4624 s3stmt_start(STMT *s)
4625 {
4626 DBC *d = (DBC *) s->dbc;
4627 const char *endp;
4628 sqlite3_stmt *s3stmt = NULL;
4629 int rc, nretry = 0;
4630
4631 d->s3stmt_needmeta = 0;
4632 if (!s->s3stmt) {
4633 #if defined(HAVE_SQLITE3PREPAREV2) && (HAVE_SQLITE3PREPAREV2)
4634 dbtraceapi(d, "sqlite3_prepare_v2", (char *) s->query);
4635 #else
4636 dbtraceapi(d, "sqlite3_prepare", (char *) s->query);
4637 #endif
4638 do {
4639 s3stmt = NULL;
4640 #if defined(HAVE_SQLITE3PREPAREV2) && (HAVE_SQLITE3PREPAREV2)
4641 rc = sqlite3_prepare_v2(d->sqlite, (char *) s->query, -1,
4642 &s3stmt, &endp);
4643 #else
4644 rc = sqlite3_prepare(d->sqlite, (char *) s->query, -1,
4645 &s3stmt, &endp);
4646 #endif
4647 if (rc != SQLITE_OK) {
4648 if (s3stmt) {
4649 sqlite3_finalize(s3stmt);
4650 s3stmt = NULL;
4651 }
4652 }
4653 } while (rc == SQLITE_SCHEMA && (++nretry) < 2);
4654 dbtracerc(d, rc, NULL);
4655 if (rc != SQLITE_OK) {
4656 if (s3stmt) {
4657 dbtraceapi(d, "sqlite3_finalize", NULL);
4658 sqlite3_finalize(s3stmt);
4659 }
4660 setstat(s, rc, "%s (%d)", (*s->ov3) ? "HY000" : "S1000",
4661 sqlite3_errmsg(d->sqlite), rc);
4662 return SQL_ERROR;
4663 }
4664 if (sqlite3_bind_parameter_count(s3stmt) != s->nparams) {
4665 dbtraceapi(d, "sqlite3_finalize", 0);
4666 sqlite3_finalize(s3stmt);
4667 setstat(s, SQLITE_ERROR, "parameter marker count incorrect",
4668 (*s->ov3) ? "HY000" : "S1000");
4669 return SQL_ERROR;
4670 }
4671 s->s3stmt = s3stmt;
4672 s->s3stmt_noreset = 1;
4673 d->s3stmt_needmeta = 1;
4674 }
4675 d->cur_s3stmt = s;
4676 s->s3stmt_rownum = -1;
4677 s3bind(d, s->s3stmt, s->nparams, s->bindparms);
4678 return SQL_SUCCESS;
4679 }
4680
4681 #ifndef WINTERFACE
4682 /**
4683 * Function not implemented.
4684 */
4685
4686 SQLRETURN SQL_API
SQLDataSources(SQLHENV env,SQLUSMALLINT dir,SQLCHAR * srvname,SQLSMALLINT buflen1,SQLSMALLINT * lenp1,SQLCHAR * desc,SQLSMALLINT buflen2,SQLSMALLINT * lenp2)4687 SQLDataSources(SQLHENV env, SQLUSMALLINT dir, SQLCHAR *srvname,
4688 SQLSMALLINT buflen1, SQLSMALLINT *lenp1,
4689 SQLCHAR *desc, SQLSMALLINT buflen2, SQLSMALLINT *lenp2)
4690 {
4691 if (env == SQL_NULL_HENV) {
4692 return SQL_INVALID_HANDLE;
4693 }
4694 return SQL_ERROR;
4695 }
4696 #endif
4697
4698 #ifdef WINTERFACE
4699 /**
4700 * Function not implemented.
4701 */
4702
4703 SQLRETURN SQL_API
SQLDataSourcesW(SQLHENV env,SQLUSMALLINT dir,SQLWCHAR * srvname,SQLSMALLINT buflen1,SQLSMALLINT * lenp1,SQLWCHAR * desc,SQLSMALLINT buflen2,SQLSMALLINT * lenp2)4704 SQLDataSourcesW(SQLHENV env, SQLUSMALLINT dir, SQLWCHAR *srvname,
4705 SQLSMALLINT buflen1, SQLSMALLINT *lenp1,
4706 SQLWCHAR *desc, SQLSMALLINT buflen2, SQLSMALLINT *lenp2)
4707 {
4708 if (env == SQL_NULL_HENV) {
4709 return SQL_INVALID_HANDLE;
4710 }
4711 return SQL_ERROR;
4712 }
4713 #endif
4714
4715 #ifndef WINTERFACE
4716 /**
4717 * Function not implemented.
4718 */
4719
4720 SQLRETURN SQL_API
SQLDrivers(SQLHENV env,SQLUSMALLINT dir,SQLCHAR * drvdesc,SQLSMALLINT descmax,SQLSMALLINT * desclenp,SQLCHAR * drvattr,SQLSMALLINT attrmax,SQLSMALLINT * attrlenp)4721 SQLDrivers(SQLHENV env, SQLUSMALLINT dir, SQLCHAR *drvdesc,
4722 SQLSMALLINT descmax, SQLSMALLINT *desclenp,
4723 SQLCHAR *drvattr, SQLSMALLINT attrmax, SQLSMALLINT *attrlenp)
4724 {
4725 if (env == SQL_NULL_HENV) {
4726 return SQL_INVALID_HANDLE;
4727 }
4728 return SQL_ERROR;
4729 }
4730 #endif
4731
4732 #ifdef WINTERFACE
4733 /**
4734 * Function not implemented.
4735 */
4736
4737 SQLRETURN SQL_API
SQLDriversW(SQLHENV env,SQLUSMALLINT dir,SQLWCHAR * drvdesc,SQLSMALLINT descmax,SQLSMALLINT * desclenp,SQLWCHAR * drvattr,SQLSMALLINT attrmax,SQLSMALLINT * attrlenp)4738 SQLDriversW(SQLHENV env, SQLUSMALLINT dir, SQLWCHAR *drvdesc,
4739 SQLSMALLINT descmax, SQLSMALLINT *desclenp,
4740 SQLWCHAR *drvattr, SQLSMALLINT attrmax, SQLSMALLINT *attrlenp)
4741 {
4742 if (env == SQL_NULL_HENV) {
4743 return SQL_INVALID_HANDLE;
4744 }
4745 return SQL_ERROR;
4746 }
4747 #endif
4748
4749 #ifndef WINTERFACE
4750 /**
4751 * Function not implemented.
4752 */
4753
4754 SQLRETURN SQL_API
SQLBrowseConnect(SQLHDBC dbc,SQLCHAR * connin,SQLSMALLINT conninLen,SQLCHAR * connout,SQLSMALLINT connoutMax,SQLSMALLINT * connoutLen)4755 SQLBrowseConnect(SQLHDBC dbc, SQLCHAR *connin, SQLSMALLINT conninLen,
4756 SQLCHAR *connout, SQLSMALLINT connoutMax,
4757 SQLSMALLINT *connoutLen)
4758 {
4759 SQLRETURN ret;
4760
4761 HDBC_LOCK(dbc);
4762 ret = drvunimpldbc(dbc);
4763 HDBC_UNLOCK(dbc);
4764 return ret;
4765 }
4766 #endif
4767
4768 #ifdef WINTERFACE
4769 /**
4770 * Function not implemented.
4771 */
4772
4773 SQLRETURN SQL_API
SQLBrowseConnectW(SQLHDBC dbc,SQLWCHAR * connin,SQLSMALLINT conninLen,SQLWCHAR * connout,SQLSMALLINT connoutMax,SQLSMALLINT * connoutLen)4774 SQLBrowseConnectW(SQLHDBC dbc, SQLWCHAR *connin, SQLSMALLINT conninLen,
4775 SQLWCHAR *connout, SQLSMALLINT connoutMax,
4776 SQLSMALLINT *connoutLen)
4777 {
4778 SQLRETURN ret;
4779
4780 HDBC_LOCK(dbc);
4781 ret = drvunimpldbc(dbc);
4782 HDBC_UNLOCK(dbc);
4783 return ret;
4784 }
4785 #endif
4786
4787 /**
4788 * Internal put (partial) parameter data into executing statement.
4789 * @param stmt statement handle
4790 * @param data pointer to data
4791 * @param len length of data
4792 * @result ODBC error code
4793 */
4794
4795 static SQLRETURN
drvputdata(SQLHSTMT stmt,SQLPOINTER data,SQLLEN len)4796 drvputdata(SQLHSTMT stmt, SQLPOINTER data, SQLLEN len)
4797 {
4798 STMT *s;
4799 int i, dlen, done = 0;
4800 BINDPARM *p;
4801
4802 if (stmt == SQL_NULL_HSTMT) {
4803 return SQL_INVALID_HANDLE;
4804 }
4805 s = (STMT *) stmt;
4806 if (!s->query || s->nparams <= 0) {
4807 seqerr:
4808 setstat(s, -1, "sequence error", "HY010");
4809 return SQL_ERROR;
4810 }
4811 for (i = (s->pdcount < 0) ? 0 : s->pdcount; i < s->nparams; i++) {
4812 p = &s->bindparms[i];
4813 if (p->need > 0) {
4814 int type = mapdeftype(p->type, p->stype, -1, s->nowchar[0]);
4815
4816 if (len == SQL_NULL_DATA) {
4817 freep(&p->parbuf);
4818 p->param = NULL;
4819 p->len = SQL_NULL_DATA;
4820 p->need = -1;
4821 } else if (type != SQL_C_CHAR
4822 #ifdef WCHARSUPPORT
4823 && type != SQL_C_WCHAR
4824 #endif
4825 && type != SQL_C_BINARY) {
4826 int size = 0;
4827
4828 switch (type) {
4829 case SQL_C_TINYINT:
4830 case SQL_C_UTINYINT:
4831 case SQL_C_STINYINT:
4832 #ifdef SQL_BIT
4833 case SQL_C_BIT:
4834 #endif
4835 size = sizeof (SQLCHAR);
4836 break;
4837 case SQL_C_SHORT:
4838 case SQL_C_USHORT:
4839 case SQL_C_SSHORT:
4840 size = sizeof (SQLSMALLINT);
4841 break;
4842 case SQL_C_LONG:
4843 case SQL_C_ULONG:
4844 case SQL_C_SLONG:
4845 size = sizeof (SQLINTEGER);
4846 break;
4847 #ifdef SQL_BIGINT
4848 case SQL_C_UBIGINT:
4849 case SQL_C_SBIGINT:
4850 size = sizeof (SQLBIGINT);
4851 break;
4852 #endif
4853 case SQL_C_FLOAT:
4854 size = sizeof (float);
4855 break;
4856 case SQL_C_DOUBLE:
4857 size = sizeof (double);
4858 break;
4859 #ifdef SQL_C_TYPE_DATE
4860 case SQL_C_TYPE_DATE:
4861 #endif
4862 case SQL_C_DATE:
4863 size = sizeof (DATE_STRUCT);
4864 break;
4865 #ifdef SQL_C_TYPE_DATE
4866 case SQL_C_TYPE_TIME:
4867 #endif
4868 case SQL_C_TIME:
4869 size = sizeof (TIME_STRUCT);
4870 break;
4871 #ifdef SQL_C_TYPE_DATE
4872 case SQL_C_TYPE_TIMESTAMP:
4873 #endif
4874 case SQL_C_TIMESTAMP:
4875 size = sizeof (TIMESTAMP_STRUCT);
4876 break;
4877 }
4878 freep(&p->parbuf);
4879 p->parbuf = xmalloc(size);
4880 if (!p->parbuf) {
4881 return nomem(s);
4882 }
4883 p->param = p->parbuf;
4884 memcpy(p->param, data, size);
4885 p->len = size;
4886 p->need = -1;
4887 } else if (len == SQL_NTS && (
4888 type == SQL_C_CHAR
4889 #ifdef WCHARSUPPORT
4890 || type == SQL_C_WCHAR
4891 #endif
4892 )) {
4893 char *dp = data;
4894
4895 #ifdef WCHARSUPPORT
4896 if (type == SQL_C_WCHAR) {
4897 dp = uc_to_utf(data, len);
4898 if (!dp) {
4899 return nomem(s);
4900 }
4901 }
4902 #endif
4903 #if defined(_WIN32) || defined(_WIN64)
4904 if (*s->oemcp) {
4905 dp = wmb_to_utf(data, strlen (data));
4906 if (!dp) {
4907 return nomem(s);
4908 }
4909 }
4910 #endif
4911 dlen = strlen(dp);
4912 freep(&p->parbuf);
4913 p->parbuf = xmalloc(dlen + 1);
4914 if (!p->parbuf) {
4915 if (dp != data) {
4916 uc_free(dp);
4917 }
4918 return nomem(s);
4919 }
4920 p->param = p->parbuf;
4921 strcpy(p->param, dp);
4922 if (dp != data) {
4923 uc_free(dp);
4924 }
4925 p->len = dlen;
4926 p->need = -1;
4927 } else if (len < 0) {
4928 setstat(s, -1, "invalid length", "HY090");
4929 return SQL_ERROR;
4930 } else {
4931 dlen = min(p->len - p->offs, len);
4932 if (!p->param) {
4933 setstat(s, -1, "no memory for parameter", "HY013");
4934 return SQL_ERROR;
4935 }
4936 memcpy((char *) p->param + p->offs, data, dlen);
4937 p->offs += dlen;
4938 if (p->offs >= p->len) {
4939 #ifdef WCHARSUPPORT
4940 if (type == SQL_C_WCHAR) {
4941 char *dp = uc_to_utf(p->param, p->len);
4942 char *np;
4943 int nlen;
4944
4945 if (!dp) {
4946 return nomem(s);
4947 }
4948 nlen = strlen(dp);
4949 np = xmalloc(nlen + 1);
4950 if (!np) {
4951 uc_free(dp);
4952 return nomem(s);
4953 }
4954 strcpy(np, dp);
4955 uc_free(dp);
4956 if (p->param == p->parbuf) {
4957 freep(&p->parbuf);
4958 }
4959 p->parbuf = p->param = np;
4960 p->len = nlen;
4961 } else {
4962 *((char *) p->param + p->len) = '\0';
4963 }
4964 p->need = (type == SQL_C_CHAR || type == SQL_C_WCHAR)
4965 ? -1 : 0;
4966 #else
4967 *((char *) p->param + p->len) = '\0';
4968 p->need = (type == SQL_C_CHAR) ? -1 : 0;
4969 #endif
4970 #if defined(_WIN32) || defined(_WIN64)
4971 if (type == SQL_C_CHAR && *s->oemcp &&
4972 !(p->stype == SQL_BINARY ||
4973 p->stype == SQL_VARBINARY ||
4974 p->stype == SQL_LONGVARBINARY)) {
4975 char *dp = wmb_to_utf(p->param, p->len);
4976
4977 if (!dp) {
4978 return nomem(s);
4979 }
4980 if (p->param == p->parbuf) {
4981 freep(&p->parbuf);
4982 }
4983 p->parbuf = p->param = dp;
4984 p->len = strlen(dp);
4985 }
4986 if (p->type == SQL_C_WCHAR &&
4987 (p->stype == SQL_VARCHAR ||
4988 p->stype == SQL_LONGVARCHAR) &&
4989 p->len == p->coldef * sizeof (SQLWCHAR)) {
4990 /* fix for MS-Access */
4991 p->len = p->coldef;
4992 }
4993 #endif
4994 }
4995 }
4996 done = 1;
4997 break;
4998 }
4999 }
5000 if (!done) {
5001 goto seqerr;
5002 }
5003 return SQL_SUCCESS;
5004 }
5005
5006 /**
5007 * Put (partial) parameter data into executing statement.
5008 * @param stmt statement handle
5009 * @param data pointer to data
5010 * @param len length of data
5011 * @result ODBC error code
5012 */
5013
5014 SQLRETURN SQL_API
SQLPutData(SQLHSTMT stmt,SQLPOINTER data,SQLLEN len)5015 SQLPutData(SQLHSTMT stmt, SQLPOINTER data, SQLLEN len)
5016 {
5017 SQLRETURN ret;
5018
5019 HSTMT_LOCK(stmt);
5020 ret = drvputdata(stmt, data, len);
5021 HSTMT_UNLOCK(stmt);
5022 return ret;
5023 }
5024
5025 /**
5026 * Clear out parameter bindings, if any.
5027 * @param s statement pointer
5028 */
5029
5030 static SQLRETURN
freeparams(STMT * s)5031 freeparams(STMT *s)
5032 {
5033 if (s->bindparms) {
5034 int n;
5035
5036 for (n = 0; n < s->nbindparms; n++) {
5037 freep(&s->bindparms[n].parbuf);
5038 memset(&s->bindparms[n], 0, sizeof (BINDPARM));
5039 }
5040 }
5041 return SQL_SUCCESS;
5042 }
5043
5044 /**
5045 * Setup SQLite3 parameter for statement parameter.
5046 * @param s statement pointer
5047 * @param sql sql string
5048 * @param pnum parameter number
5049 * @result ODBC error code
5050 *
5051 * The parameter is converted within BINDPARM in order to
5052 * be presented to sqlite3_bind_*() functions.
5053 */
5054
5055 static SQLRETURN
setupparam(STMT * s,char * sql,int pnum)5056 setupparam(STMT *s, char *sql, int pnum)
5057 {
5058 int type, len = 0, needalloc = 0;
5059 BINDPARM *p;
5060
5061 if (!s->bindparms || pnum < 0 || pnum >= s->nbindparms) {
5062 goto error;
5063 }
5064 p = &s->bindparms[pnum];
5065 type = mapdeftype(p->type, p->stype, -1, s->nowchar[0]);
5066 #if (defined(_WIN32) || defined(_WIN64)) && defined(WINTERFACE)
5067 /* MS Access hack part 4 (map SQL_C_DEFAULT to SQL_C_CHAR) */
5068 if (type == SQL_C_WCHAR && p->type == SQL_C_DEFAULT) {
5069 type = SQL_C_CHAR;
5070 }
5071 #endif
5072 if (p->need > 0) {
5073 return setupparbuf(s, p);
5074 }
5075 p->strbuf[0] = '\0';
5076 if (!p->param || (p->lenp && *p->lenp == SQL_NULL_DATA)) {
5077 p->s3type = SQLITE_NULL;
5078 p->s3size = 0;
5079 return SQL_SUCCESS;
5080 }
5081 if (type == SQL_C_CHAR &&
5082 (p->stype == SQL_BINARY ||
5083 p->stype == SQL_VARBINARY ||
5084 p->stype == SQL_LONGVARBINARY)) {
5085 type = SQL_C_BINARY;
5086 }
5087 switch (type) {
5088 case SQL_C_BINARY:
5089 p->s3type = SQLITE_BLOB;
5090 p->s3size = p->len;
5091 p->s3val = p->param;
5092 if (p->need < 0) {
5093 break;
5094 }
5095 if (!p->lenp) {
5096 len = p->len;
5097 } else if (*p->lenp == SQL_DATA_AT_EXEC) {
5098 len = p->len;
5099 } else {
5100 len = *p->lenp;
5101 if (len <= SQL_LEN_DATA_AT_EXEC_OFFSET) {
5102 len = SQL_LEN_DATA_AT_EXEC(len);
5103 }
5104 }
5105 if (len < 0) {
5106 setstat(s, -1, "invalid length", "HY009");
5107 return SQL_ERROR;
5108 }
5109 p->len = len;
5110 p->max = p->len;
5111 p->need = -1;
5112 p->s3size = len;
5113 break;
5114 #ifdef WCHARSUPPORT
5115 case SQL_C_WCHAR:
5116 #endif
5117 case SQL_C_CHAR:
5118 p->s3type = SQLITE_TEXT;
5119 p->s3size = -1;
5120 p->s3val = p->param;
5121 if (!p->parbuf) {
5122 #ifdef WCHARSUPPORT
5123 if (type == SQL_C_WCHAR) {
5124 if (!p->lenp || *p->lenp == SQL_NTS) {
5125 p->max = uc_strlen(p->param) * sizeof (SQLWCHAR);
5126 } else if (*p->lenp >= 0) {
5127 p->max = *p->lenp;
5128 }
5129 } else
5130 #endif
5131 if (type == SQL_C_CHAR) {
5132 if (!p->lenp || *p->lenp == SQL_NTS) {
5133 p->len = p->max = strlen(p->param);
5134 #if defined(_WIN32) || defined(_WIN64)
5135 needalloc = 1;
5136 #endif
5137 } else if (*p->lenp >= 0) {
5138 p->len = p->max = *p->lenp;
5139 needalloc = 1;
5140 }
5141 }
5142 }
5143 if (p->need < 0 && p->parbuf == p->param) {
5144 break;
5145 }
5146 #ifdef WCHARSUPPORT
5147 if (type == SQL_C_WCHAR) {
5148 char *dp = uc_to_utf(p->param, p->max);
5149
5150 if (!dp) {
5151 return nomem(s);
5152 }
5153 if (p->param == p->parbuf) {
5154 freep(&p->parbuf);
5155 }
5156 p->parbuf = p->param = dp;
5157 p->need = -1;
5158 p->len = strlen(p->param);
5159 p->s3val = p->param;
5160 p->s3size = p->len;
5161 } else
5162 #endif
5163 if (type == SQL_C_CHAR) {
5164 p->s3val = p->param;
5165 if (needalloc) {
5166 char *dp;
5167
5168 #if defined(_WIN32) || defined(_WIN64)
5169 if (*s->oemcp) {
5170 dp = wmb_to_utf(p->param, p->len);
5171 } else {
5172 dp = xmalloc(p->len + 1);
5173 }
5174 #else
5175 dp = xmalloc(p->len + 1);
5176 #endif
5177 if (!dp) {
5178 return nomem(s);
5179 }
5180 #if defined(_WIN32) || defined(_WIN64)
5181 if (*s->oemcp) {
5182 p->len = strlen(dp);
5183 } else {
5184 memcpy(dp, p->param, p->len);
5185 dp[p->len] = '\0';
5186 }
5187 #else
5188 memcpy(dp, p->param, p->len);
5189 dp[p->len] = '\0';
5190 #endif
5191 if (p->param == p->parbuf) {
5192 freep(&p->parbuf);
5193 }
5194 p->parbuf = p->param = dp;
5195 p->need = -1;
5196 p->s3val = p->param;
5197 p->s3size = p->len;
5198 }
5199 }
5200 break;
5201 case SQL_C_UTINYINT:
5202 case SQL_C_TINYINT:
5203 case SQL_C_STINYINT:
5204 p->s3type = SQLITE_INTEGER;
5205 p->s3size = sizeof (int);
5206 p->s3ival = *((SQLCHAR *) p->param);
5207 break;
5208 case SQL_C_USHORT:
5209 p->s3type = SQLITE_INTEGER;
5210 p->s3size = sizeof (int);
5211 p->s3ival = *((SQLUSMALLINT *) p->param);
5212 break;
5213 case SQL_C_SHORT:
5214 case SQL_C_SSHORT:
5215 p->s3type = SQLITE_INTEGER;
5216 p->s3size = sizeof (int);
5217 p->s3ival = *((SQLSMALLINT *) p->param);
5218 break;
5219 case SQL_C_ULONG:
5220 p->s3type = SQLITE_INTEGER;
5221 p->s3size = sizeof (int);
5222 p->s3ival = *((SQLUINTEGER *) p->param);
5223 break;
5224 case SQL_C_LONG:
5225 case SQL_C_SLONG:
5226 p->s3type = SQLITE_INTEGER;
5227 p->s3size = sizeof (int);
5228 p->s3ival = *((SQLINTEGER *) p->param);
5229 break;
5230 #ifdef SQL_BIT
5231 case SQL_C_BIT:
5232 p->s3type = SQLITE_INTEGER;
5233 p->s3size = sizeof (int);
5234 p->s3ival = (*((SQLCHAR *) p->param)) ? 1 : 0;
5235 break;
5236 #endif
5237 #ifdef SQL_BIGINT
5238 case SQL_C_SBIGINT:
5239 p->s3type = SQLITE_INTEGER;
5240 p->s3size = sizeof (sqlite_int64);
5241 p->s3lival = *((sqlite_int64 *) p->param);
5242 break;
5243 case SQL_C_UBIGINT:
5244 p->s3type = SQLITE_INTEGER;
5245 p->s3size = sizeof (sqlite_int64);
5246 p->s3lival = *((sqlite_uint64 *) p->param);
5247 break;
5248 #endif
5249 case SQL_C_FLOAT:
5250 p->s3type = SQLITE_FLOAT;
5251 p->s3size = sizeof (double);
5252 p->s3dval = *((float *) p->param);
5253 break;
5254 case SQL_C_DOUBLE:
5255 p->s3type = SQLITE_FLOAT;
5256 p->s3size = sizeof (double);
5257 p->s3dval = *((double *) p->param);
5258 break;
5259 #ifdef SQL_C_TYPE_DATE
5260 case SQL_C_TYPE_DATE:
5261 #endif
5262 case SQL_C_DATE:
5263 if (*s->jdconv) {
5264 int a, b, x1, x2, y, m, d;
5265
5266 p->s3type = SQLITE_FLOAT;
5267 p->s3size = sizeof (double);
5268 y = ((DATE_STRUCT *) p->param)->year;
5269 m = ((DATE_STRUCT *) p->param)->month;
5270 d = ((DATE_STRUCT *) p->param)->day;
5271 if (m <= 2) {
5272 y--;
5273 m += 12;
5274 }
5275 a = y / 100;
5276 b = 2 - a + (a / 4);
5277 x1 = 36525 * (y + 4716) / 100;
5278 x2 = 306001 * (m + 1) / 10000;
5279 p->s3dval = x1 + x2 + d + b - 1524.5;
5280 break;
5281 }
5282 sprintf(p->strbuf, "%04d-%02d-%02d",
5283 ((DATE_STRUCT *) p->param)->year,
5284 ((DATE_STRUCT *) p->param)->month,
5285 ((DATE_STRUCT *) p->param)->day);
5286 p->s3type = SQLITE_TEXT;
5287 p->s3size = -1;
5288 p->s3val = p->strbuf;
5289 break;
5290 #ifdef SQL_C_TYPE_TIME
5291 case SQL_C_TYPE_TIME:
5292 #endif
5293 case SQL_C_TIME:
5294 if (*s->jdconv) {
5295 p->s3type = SQLITE_FLOAT;
5296 p->s3size = sizeof (double);
5297 p->s3dval = 2451544.5 +
5298 (((TIME_STRUCT *) p->param)->hour * 3600000.0 +
5299 ((TIME_STRUCT *) p->param)->minute * 60000.0 +
5300 ((TIME_STRUCT *) p->param)->second * 1000.0) / 86400000.0;
5301 break;
5302 }
5303 sprintf(p->strbuf, "%02d:%02d:%02d",
5304 ((TIME_STRUCT *) p->param)->hour,
5305 ((TIME_STRUCT *) p->param)->minute,
5306 ((TIME_STRUCT *) p->param)->second);
5307 p->s3type = SQLITE_TEXT;
5308 p->s3size = -1;
5309 p->s3val = p->strbuf;
5310 break;
5311 #ifdef SQL_C_TYPE_TIMESTAMP
5312 case SQL_C_TYPE_TIMESTAMP:
5313 #endif
5314 case SQL_C_TIMESTAMP:
5315 if (*s->jdconv) {
5316 int a, b, x1, x2, y, m, d;
5317
5318 p->s3type = SQLITE_FLOAT;
5319 p->s3size = sizeof (double);
5320 y = ((TIMESTAMP_STRUCT *) p->param)->year;
5321 m = ((TIMESTAMP_STRUCT *) p->param)->month;
5322 d = ((TIMESTAMP_STRUCT *) p->param)->day;
5323 if (m <= 2) {
5324 y--;
5325 m += 12;
5326 }
5327 a = y / 100;
5328 b = 2 - a + (a / 4);
5329 x1 = 36525 * (y + 4716) / 100;
5330 x2 = 306001 * (m + 1) / 10000;
5331 p->s3dval = x1 + x2 + d + b - 1524.5 +
5332 (((TIMESTAMP_STRUCT *) p->param)->hour * 3600000.0 +
5333 ((TIMESTAMP_STRUCT *) p->param)->minute * 60000.0 +
5334 ((TIMESTAMP_STRUCT *) p->param)->second * 1000.0 +
5335 ((TIMESTAMP_STRUCT *) p->param)->fraction / 1.0E6)
5336 / 86400000.0;
5337 break;
5338 }
5339 len = (int) ((TIMESTAMP_STRUCT *) p->param)->fraction;
5340 len /= 1000000;
5341 len = len % 1000;
5342 if (len < 0) {
5343 len = 0;
5344 }
5345 if (p->coldef && p->coldef <= 16) {
5346 sprintf(p->strbuf, "%04d-%02d-%02d %02d:%02d:00.000",
5347 ((TIMESTAMP_STRUCT *) p->param)->year,
5348 ((TIMESTAMP_STRUCT *) p->param)->month,
5349 ((TIMESTAMP_STRUCT *) p->param)->day,
5350 ((TIMESTAMP_STRUCT *) p->param)->hour,
5351 ((TIMESTAMP_STRUCT *) p->param)->minute);
5352 } else if (p->coldef && p->coldef <= 19) {
5353 sprintf(p->strbuf, "%04d-%02d-%02d %02d:%02d:%02d.000",
5354 ((TIMESTAMP_STRUCT *) p->param)->year,
5355 ((TIMESTAMP_STRUCT *) p->param)->month,
5356 ((TIMESTAMP_STRUCT *) p->param)->day,
5357 ((TIMESTAMP_STRUCT *) p->param)->hour,
5358 ((TIMESTAMP_STRUCT *) p->param)->minute,
5359 ((TIMESTAMP_STRUCT *) p->param)->second);
5360 } else {
5361 sprintf(p->strbuf, "%04d-%02d-%02d %02d:%02d:%02d.%03d",
5362 ((TIMESTAMP_STRUCT *) p->param)->year,
5363 ((TIMESTAMP_STRUCT *) p->param)->month,
5364 ((TIMESTAMP_STRUCT *) p->param)->day,
5365 ((TIMESTAMP_STRUCT *) p->param)->hour,
5366 ((TIMESTAMP_STRUCT *) p->param)->minute,
5367 ((TIMESTAMP_STRUCT *) p->param)->second,
5368 len);
5369 }
5370 p->s3type = SQLITE_TEXT;
5371 p->s3size = -1;
5372 p->s3val = p->strbuf;
5373 break;
5374 default:
5375 error:
5376 setstat(s, -1, "unsupported parameter type",
5377 (*s->ov3) ? "07009" : "S1093");
5378 return SQL_ERROR;
5379 }
5380 return SQL_SUCCESS;
5381 }
5382
5383 /**
5384 * Internal bind parameter on HSTMT.
5385 * @param stmt statement handle
5386 * @param pnum parameter number, starting at 1
5387 * @param iotype input/output type of parameter
5388 * @param buftype type of host variable
5389 * @param ptype
5390 * @param coldef
5391 * @param scale
5392 * @param data pointer to host variable
5393 * @param buflen length of host variable
5394 * @param len output length pointer
5395 * @result ODBC error code
5396 */
5397
5398 static SQLRETURN
drvbindparam(SQLHSTMT stmt,SQLUSMALLINT pnum,SQLSMALLINT iotype,SQLSMALLINT buftype,SQLSMALLINT ptype,SQLUINTEGER coldef,SQLSMALLINT scale,SQLPOINTER data,SQLINTEGER buflen,SQLLEN * len)5399 drvbindparam(SQLHSTMT stmt, SQLUSMALLINT pnum, SQLSMALLINT iotype,
5400 SQLSMALLINT buftype, SQLSMALLINT ptype, SQLUINTEGER coldef,
5401 SQLSMALLINT scale,
5402 SQLPOINTER data, SQLINTEGER buflen, SQLLEN *len)
5403 {
5404 STMT *s;
5405 BINDPARM *p;
5406
5407 if (stmt == SQL_NULL_HSTMT) {
5408 return SQL_INVALID_HANDLE;
5409 }
5410 s = (STMT *) stmt;
5411 if (pnum == 0) {
5412 setstat(s, -1, "invalid parameter", (*s->ov3) ? "07009" : "S1093");
5413 return SQL_ERROR;
5414 }
5415 if (!data && !len) {
5416 setstat(s, -1, "invalid buffer", "HY003");
5417 return SQL_ERROR;
5418 }
5419 --pnum;
5420 if (s->bindparms) {
5421 if (pnum >= s->nbindparms) {
5422 BINDPARM *newparms;
5423
5424 newparms = xrealloc(s->bindparms,
5425 (pnum + 1) * sizeof (BINDPARM));
5426 if (!newparms) {
5427 outofmem:
5428 return nomem(s);
5429 }
5430 s->bindparms = newparms;
5431 memset(&s->bindparms[s->nbindparms], 0,
5432 (pnum + 1 - s->nbindparms) * sizeof (BINDPARM));
5433 s->nbindparms = pnum + 1;
5434 }
5435 } else {
5436 int npar = max(10, pnum + 1);
5437
5438 s->bindparms = xmalloc(npar * sizeof (BINDPARM));
5439 if (!s->bindparms) {
5440 goto outofmem;
5441 }
5442 memset(s->bindparms, 0, npar * sizeof (BINDPARM));
5443 s->nbindparms = npar;
5444 }
5445 switch (buftype) {
5446 case SQL_C_STINYINT:
5447 case SQL_C_UTINYINT:
5448 case SQL_C_TINYINT:
5449 #ifdef SQL_C_BIT
5450 case SQL_C_BIT:
5451 #endif
5452 buflen = sizeof (SQLCHAR);
5453 break;
5454 case SQL_C_SHORT:
5455 case SQL_C_USHORT:
5456 case SQL_C_SSHORT:
5457 buflen = sizeof (SQLSMALLINT);
5458 break;
5459 case SQL_C_SLONG:
5460 case SQL_C_ULONG:
5461 case SQL_C_LONG:
5462 buflen = sizeof (SQLINTEGER);
5463 break;
5464 case SQL_C_FLOAT:
5465 buflen = sizeof (float);
5466 break;
5467 case SQL_C_DOUBLE:
5468 buflen = sizeof (double);
5469 break;
5470 case SQL_C_TIMESTAMP:
5471 #ifdef SQL_C_TYPE_TIMESTAMP
5472 case SQL_C_TYPE_TIMESTAMP:
5473 #endif
5474 buflen = sizeof (TIMESTAMP_STRUCT);
5475 break;
5476 case SQL_C_TIME:
5477 #ifdef SQL_C_TYPE_TIME
5478 case SQL_C_TYPE_TIME:
5479 #endif
5480 buflen = sizeof (TIME_STRUCT);
5481 break;
5482 case SQL_C_DATE:
5483 #ifdef SQL_C_TYPE_DATE
5484 case SQL_C_TYPE_DATE:
5485 #endif
5486 buflen = sizeof (DATE_STRUCT);
5487 break;
5488 #ifdef SQL_C_UBIGINT
5489 case SQL_C_UBIGINT:
5490 buflen = sizeof (SQLBIGINT);
5491 break;
5492 #endif
5493 #ifdef SQL_C_SBIGINT
5494 case SQL_C_SBIGINT:
5495 buflen = sizeof (SQLBIGINT);
5496 break;
5497 #endif
5498 #ifdef SQL_C_BIGINT
5499 case SQL_C_BIGINT:
5500 buflen = sizeof (SQLBIGINT);
5501 break;
5502 #endif
5503 }
5504 p = &s->bindparms[pnum];
5505 p->type = buftype;
5506 p->stype = ptype;
5507 p->coldef = coldef;
5508 p->scale = scale;
5509 p->max = buflen;
5510 p->inc = buflen;
5511 p->lenp = p->lenp0 = len;
5512 p->offs = 0;
5513 p->len = 0;
5514 p->param0 = data;
5515 freep(&p->parbuf);
5516 p->param = p->param0;
5517 p->bound = 1;
5518 p->need = 0;
5519 return SQL_SUCCESS;
5520 }
5521
5522 /**
5523 * Bind parameter on HSTMT.
5524 * @param stmt statement handle
5525 * @param pnum parameter number, starting at 1
5526 * @param iotype input/output type of parameter
5527 * @param buftype type of host variable
5528 * @param ptype
5529 * @param coldef
5530 * @param scale
5531 * @param data pointer to host variable
5532 * @param buflen length of host variable
5533 * @param len output length pointer
5534 * @result ODBC error code
5535 */
5536
5537 SQLRETURN SQL_API
SQLBindParameter(SQLHSTMT stmt,SQLUSMALLINT pnum,SQLSMALLINT iotype,SQLSMALLINT buftype,SQLSMALLINT ptype,SQLULEN coldef,SQLSMALLINT scale,SQLPOINTER data,SQLLEN buflen,SQLLEN * len)5538 SQLBindParameter(SQLHSTMT stmt, SQLUSMALLINT pnum, SQLSMALLINT iotype,
5539 SQLSMALLINT buftype, SQLSMALLINT ptype, SQLULEN coldef,
5540 SQLSMALLINT scale,
5541 SQLPOINTER data, SQLLEN buflen, SQLLEN *len)
5542 {
5543 SQLRETURN ret;
5544
5545 HSTMT_LOCK(stmt);
5546 ret = drvbindparam(stmt, pnum, iotype, buftype, ptype, coldef,
5547 scale, data, buflen, len);
5548 HSTMT_UNLOCK(stmt);
5549 return ret;
5550 }
5551
5552 #ifndef HAVE_IODBC
5553 /**
5554 * Bind parameter on HSTMT.
5555 * @param stmt statement handle
5556 * @param pnum parameter number, starting at 1
5557 * @param vtype input/output type of parameter
5558 * @param ptype
5559 * @param lenprec
5560 * @param scale
5561 * @param val pointer to host variable
5562 * @param lenp output length pointer
5563 * @result ODBC error code
5564 */
5565
5566 SQLRETURN SQL_API
SQLBindParam(SQLHSTMT stmt,SQLUSMALLINT pnum,SQLSMALLINT vtype,SQLSMALLINT ptype,SQLULEN lenprec,SQLSMALLINT scale,SQLPOINTER val,SQLLEN * lenp)5567 SQLBindParam(SQLHSTMT stmt, SQLUSMALLINT pnum, SQLSMALLINT vtype,
5568 SQLSMALLINT ptype, SQLULEN lenprec,
5569 SQLSMALLINT scale, SQLPOINTER val,
5570 SQLLEN *lenp)
5571 {
5572 SQLRETURN ret;
5573
5574 HSTMT_LOCK(stmt);
5575 ret = drvbindparam(stmt, pnum, SQL_PARAM_INPUT, vtype, ptype,
5576 lenprec, scale, val, 0, lenp);
5577 HSTMT_UNLOCK(stmt);
5578 return ret;
5579 }
5580 #endif
5581
5582 /**
5583 * Return number of parameters.
5584 * @param stmt statement handle
5585 * @param nparam output parameter count
5586 * @result ODBC error code
5587 */
5588
5589 SQLRETURN SQL_API
SQLNumParams(SQLHSTMT stmt,SQLSMALLINT * nparam)5590 SQLNumParams(SQLHSTMT stmt, SQLSMALLINT *nparam)
5591 {
5592 STMT *s;
5593 SQLSMALLINT dummy;
5594
5595 HSTMT_LOCK(stmt);
5596 if (stmt == SQL_NULL_HSTMT) {
5597 return SQL_INVALID_HANDLE;
5598 }
5599 s = (STMT *) stmt;
5600 if (!nparam) {
5601 nparam = &dummy;
5602 }
5603 *nparam = s->nparams;
5604 HSTMT_UNLOCK(stmt);
5605 return SQL_SUCCESS;
5606 }
5607
5608 /**
5609 * Setup parameter buffer for deferred parameter.
5610 * @param s pointer to STMT
5611 * @param p pointer to BINDPARM
5612 * @result ODBC error code (success indicated by SQL_NEED_DATA)
5613 */
5614
5615 static SQLRETURN
setupparbuf(STMT * s,BINDPARM * p)5616 setupparbuf(STMT *s, BINDPARM *p)
5617 {
5618 if (!p->parbuf) {
5619 if (*p->lenp == SQL_DATA_AT_EXEC) {
5620 p->len = p->max;
5621 } else {
5622 p->len = SQL_LEN_DATA_AT_EXEC(*p->lenp);
5623 }
5624 if (p->len < 0 && p->len != SQL_NTS &&
5625 p->len != SQL_NULL_DATA) {
5626 setstat(s, -1, "invalid length", "HY009");
5627 return SQL_ERROR;
5628 }
5629 if (p->len >= 0) {
5630 p->parbuf = xmalloc(p->len + 2);
5631 if (!p->parbuf) {
5632 return nomem(s);
5633 }
5634 p->param = p->parbuf;
5635 } else {
5636 p->param = NULL;
5637 }
5638 }
5639 return SQL_NEED_DATA;
5640 }
5641
5642 /**
5643 * Retrieve next parameter for sending data to executing query.
5644 * @param stmt statement handle
5645 * @param pind pointer to output parameter indicator
5646 * @result ODBC error code
5647 */
5648
5649 SQLRETURN SQL_API
SQLParamData(SQLHSTMT stmt,SQLPOINTER * pind)5650 SQLParamData(SQLHSTMT stmt, SQLPOINTER *pind)
5651 {
5652 STMT *s;
5653 int i;
5654 SQLPOINTER dummy;
5655 SQLRETURN ret;
5656 BINDPARM *p;
5657
5658 HSTMT_LOCK(stmt);
5659 if (stmt == SQL_NULL_HSTMT) {
5660 return SQL_INVALID_HANDLE;
5661 }
5662 s = (STMT *) stmt;
5663 if (!pind) {
5664 pind = &dummy;
5665 }
5666 if (s->pdcount < s->nparams) {
5667 s->pdcount++;
5668 }
5669 for (i = 0; i < s->pdcount; i++) {
5670 p = &s->bindparms[i];
5671 if (p->need > 0) {
5672 int type = mapdeftype(p->type, p->stype, -1, s->nowchar[0]);
5673
5674 p->need = (type == SQL_C_CHAR || type == SQL_C_WCHAR) ? -1 : 0;
5675 }
5676 }
5677 for (; i < s->nparams; i++) {
5678 p = &s->bindparms[i];
5679 if (p->need > 0) {
5680 *pind = (SQLPOINTER) p->param0;
5681 ret = setupparbuf(s, p);
5682 s->pdcount = i;
5683 goto done;
5684 }
5685 }
5686 ret = drvexecute(stmt, 0);
5687 done:
5688 HSTMT_UNLOCK(stmt);
5689 return ret;
5690 }
5691
5692 /**
5693 * Return information about parameter.
5694 * @param stmt statement handle
5695 * @param pnum parameter number, starting at 1
5696 * @param dtype output type indicator
5697 * @param size output size indicator
5698 * @param decdigits output number of digits
5699 * @param nullable output NULL allowed indicator
5700 * @result ODBC error code
5701 */
5702
5703 SQLRETURN SQL_API
SQLDescribeParam(SQLHSTMT stmt,SQLUSMALLINT pnum,SQLSMALLINT * dtype,SQLULEN * size,SQLSMALLINT * decdigits,SQLSMALLINT * nullable)5704 SQLDescribeParam(SQLHSTMT stmt, SQLUSMALLINT pnum, SQLSMALLINT *dtype,
5705 SQLULEN *size, SQLSMALLINT *decdigits, SQLSMALLINT *nullable)
5706 {
5707 STMT *s;
5708 SQLRETURN ret = SQL_ERROR;
5709
5710 HSTMT_LOCK(stmt);
5711 if (stmt == SQL_NULL_HSTMT) {
5712 return SQL_INVALID_HANDLE;
5713 }
5714 s = (STMT *) stmt;
5715 --pnum;
5716 if (pnum >= s->nparams) {
5717 setstat(s, -1, "invalid parameter index",
5718 (*s->ov3) ? "HY000" : "S1000");
5719 goto done;
5720 }
5721 if (dtype) {
5722 #ifdef SQL_LONGVARCHAR
5723 #ifdef WINTERFACE
5724 *dtype = s->nowchar[0] ? SQL_LONGVARCHAR : SQL_WLONGVARCHAR;
5725 #else
5726 *dtype = SQL_LONGVARCHAR;
5727 #endif
5728 #else
5729 #ifdef WINTERFACE
5730 *dtype = s->nowchar[0] ? SQL_VARCHAR : SQL_WVARCHAR;
5731 #else
5732 *dtype = SQL_VARCHAR;
5733 #endif
5734 #endif
5735 }
5736 if (size) {
5737 #ifdef SQL_LONGVARCHAR
5738 *size = 65536;
5739 #else
5740 *size = 255;
5741 #endif
5742 }
5743 if (decdigits) {
5744 *decdigits = 0;
5745 }
5746 if (nullable) {
5747 *nullable = SQL_NULLABLE;
5748 }
5749 ret = SQL_SUCCESS;
5750 done:
5751 HSTMT_UNLOCK(stmt);
5752 return ret;
5753 }
5754
5755 /**
5756 * Set information on parameter.
5757 * @param stmt statement handle
5758 * @param par parameter number, starting at 1
5759 * @param type type of host variable
5760 * @param sqltype
5761 * @param coldef
5762 * @param scale
5763 * @param val pointer to host variable
5764 * @param nval output length pointer
5765 * @result ODBC error code
5766 */
5767
5768 SQLRETURN SQL_API
SQLSetParam(SQLHSTMT stmt,SQLUSMALLINT par,SQLSMALLINT type,SQLSMALLINT sqltype,SQLULEN coldef,SQLSMALLINT scale,SQLPOINTER val,SQLLEN * nval)5769 SQLSetParam(SQLHSTMT stmt, SQLUSMALLINT par, SQLSMALLINT type,
5770 SQLSMALLINT sqltype, SQLULEN coldef,
5771 SQLSMALLINT scale, SQLPOINTER val, SQLLEN *nval)
5772 {
5773 SQLRETURN ret;
5774
5775 HSTMT_LOCK(stmt);
5776 ret = drvbindparam(stmt, par, SQL_PARAM_INPUT,
5777 type, sqltype, coldef, scale, val,
5778 SQL_SETPARAM_VALUE_MAX, nval);
5779 HSTMT_UNLOCK(stmt);
5780 return ret;
5781 }
5782
5783 /**
5784 * Function not implemented.
5785 */
5786
5787 SQLRETURN SQL_API
SQLParamOptions(SQLHSTMT stmt,SQLULEN rows,SQLULEN * rowp)5788 SQLParamOptions(SQLHSTMT stmt, SQLULEN rows, SQLULEN *rowp)
5789 {
5790 SQLRETURN ret;
5791
5792 HSTMT_LOCK(stmt);
5793 ret = drvunimplstmt(stmt);
5794 HSTMT_UNLOCK(stmt);
5795 return ret;
5796 }
5797
5798 #ifndef WINTERFACE
5799 /**
5800 * Function not implemented.
5801 */
5802
5803 SQLRETURN SQL_API
SQLGetDescField(SQLHDESC handle,SQLSMALLINT recno,SQLSMALLINT fieldid,SQLPOINTER value,SQLINTEGER buflen,SQLINTEGER * strlen)5804 SQLGetDescField(SQLHDESC handle, SQLSMALLINT recno,
5805 SQLSMALLINT fieldid, SQLPOINTER value,
5806 SQLINTEGER buflen, SQLINTEGER *strlen)
5807 {
5808 return SQL_ERROR;
5809 }
5810 #endif
5811
5812 #ifdef WINTERFACE
5813 /**
5814 * Function not implemented.
5815 */
5816
5817 SQLRETURN SQL_API
SQLGetDescFieldW(SQLHDESC handle,SQLSMALLINT recno,SQLSMALLINT fieldid,SQLPOINTER value,SQLINTEGER buflen,SQLINTEGER * strlen)5818 SQLGetDescFieldW(SQLHDESC handle, SQLSMALLINT recno,
5819 SQLSMALLINT fieldid, SQLPOINTER value,
5820 SQLINTEGER buflen, SQLINTEGER *strlen)
5821 {
5822 return SQL_ERROR;
5823 }
5824 #endif
5825
5826 #ifndef WINTERFACE
5827 /**
5828 * Function not implemented.
5829 */
5830
5831 SQLRETURN SQL_API
SQLSetDescField(SQLHDESC handle,SQLSMALLINT recno,SQLSMALLINT fieldid,SQLPOINTER value,SQLINTEGER buflen)5832 SQLSetDescField(SQLHDESC handle, SQLSMALLINT recno,
5833 SQLSMALLINT fieldid, SQLPOINTER value,
5834 SQLINTEGER buflen)
5835 {
5836 return SQL_ERROR;
5837 }
5838 #endif
5839
5840 #ifdef WINTERFACE
5841 /**
5842 * Function not implemented.
5843 */
5844
5845 SQLRETURN SQL_API
SQLSetDescFieldW(SQLHDESC handle,SQLSMALLINT recno,SQLSMALLINT fieldid,SQLPOINTER value,SQLINTEGER buflen)5846 SQLSetDescFieldW(SQLHDESC handle, SQLSMALLINT recno,
5847 SQLSMALLINT fieldid, SQLPOINTER value,
5848 SQLINTEGER buflen)
5849 {
5850 return SQL_ERROR;
5851 }
5852 #endif
5853
5854 #ifndef WINTERFACE
5855 /**
5856 * Function not implemented.
5857 */
5858
5859 SQLRETURN SQL_API
SQLGetDescRec(SQLHDESC handle,SQLSMALLINT recno,SQLCHAR * name,SQLSMALLINT buflen,SQLSMALLINT * strlen,SQLSMALLINT * type,SQLSMALLINT * subtype,SQLLEN * len,SQLSMALLINT * prec,SQLSMALLINT * scale,SQLSMALLINT * nullable)5860 SQLGetDescRec(SQLHDESC handle, SQLSMALLINT recno,
5861 SQLCHAR *name, SQLSMALLINT buflen,
5862 SQLSMALLINT *strlen, SQLSMALLINT *type,
5863 SQLSMALLINT *subtype, SQLLEN *len,
5864 SQLSMALLINT *prec, SQLSMALLINT *scale,
5865 SQLSMALLINT *nullable)
5866 {
5867 return SQL_ERROR;
5868 }
5869 #endif
5870
5871 #ifdef WINTERFACE
5872 /**
5873 * Function not implemented.
5874 */
5875
5876 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)5877 SQLGetDescRecW(SQLHDESC handle, SQLSMALLINT recno,
5878 SQLWCHAR *name, SQLSMALLINT buflen,
5879 SQLSMALLINT *strlen, SQLSMALLINT *type,
5880 SQLSMALLINT *subtype, SQLLEN *len,
5881 SQLSMALLINT *prec, SQLSMALLINT *scale,
5882 SQLSMALLINT *nullable)
5883 {
5884 return SQL_ERROR;
5885 }
5886 #endif
5887
5888 /**
5889 * Function not implemented.
5890 */
5891
5892 SQLRETURN SQL_API
SQLSetDescRec(SQLHDESC handle,SQLSMALLINT recno,SQLSMALLINT type,SQLSMALLINT subtype,SQLLEN len,SQLSMALLINT prec,SQLSMALLINT scale,SQLPOINTER data,SQLLEN * strlen,SQLLEN * indicator)5893 SQLSetDescRec(SQLHDESC handle, SQLSMALLINT recno,
5894 SQLSMALLINT type, SQLSMALLINT subtype,
5895 SQLLEN len, SQLSMALLINT prec,
5896 SQLSMALLINT scale, SQLPOINTER data,
5897 SQLLEN *strlen, SQLLEN *indicator)
5898 {
5899 return SQL_ERROR;
5900 }
5901
5902 /**
5903 * Setup empty result set from constant column specification.
5904 * @param stmt statement handle
5905 * @param colspec column specification array (default, ODBC2)
5906 * @param ncols number of columns (default, ODBC2)
5907 * @param colspec3 column specification array (ODBC3)
5908 * @param ncols3 number of columns (ODBC3)
5909 * @param nret returns number of columns
5910 * @result ODBC error code
5911 */
5912
5913 static SQLRETURN
mkresultset(HSTMT stmt,COL * colspec,int ncols,COL * colspec3,int ncols3,int * nret)5914 mkresultset(HSTMT stmt, COL *colspec, int ncols, COL *colspec3,
5915 int ncols3, int *nret)
5916 {
5917 STMT *s;
5918 DBC *d;
5919
5920 if (stmt == SQL_NULL_HSTMT) {
5921 return SQL_INVALID_HANDLE;
5922 }
5923 s = (STMT *) stmt;
5924 if (s->dbc == SQL_NULL_HDBC) {
5925 noconn:
5926 return noconn(s);
5927 }
5928 d = (DBC *) s->dbc;
5929 if (!d->sqlite) {
5930 goto noconn;
5931 }
5932 s3stmt_end_if(s);
5933 freeresult(s, 0);
5934 if (colspec3 && *s->ov3) {
5935 s->ncols = ncols3;
5936 s->cols = colspec3;
5937 } else {
5938 s->ncols = ncols;
5939 s->cols = colspec;
5940 }
5941 mkbindcols(s, s->ncols);
5942 s->nowchar[1] = 1;
5943 s->nrows = 0;
5944 s->rowp = s->rowprs = -1;
5945 s->isselect = -1;
5946 if (nret) {
5947 *nret = s->ncols;
5948 }
5949 return SQL_SUCCESS;
5950 }
5951
5952 /**
5953 * Columns for result set of SQLTablePrivileges().
5954 */
5955
5956 static COL tablePrivSpec2[] = {
5957 { "SYSTEM", "TABLEPRIV", "TABLE_QUALIFIER", SCOL_VARCHAR, 50 },
5958 { "SYSTEM", "TABLEPRIV", "TABLE_OWNER", SCOL_VARCHAR, 50 },
5959 { "SYSTEM", "TABLEPRIV", "TABLE_NAME", SCOL_VARCHAR, 255 },
5960 { "SYSTEM", "TABLEPRIV", "GRANTOR", SCOL_VARCHAR, 50 },
5961 { "SYSTEM", "TABLEPRIV", "GRANTEE", SCOL_VARCHAR, 50 },
5962 { "SYSTEM", "TABLEPRIV", "PRIVILEGE", SCOL_VARCHAR, 50 },
5963 { "SYSTEM", "TABLEPRIV", "IS_GRANTABLE", SCOL_VARCHAR, 50 }
5964 };
5965
5966 static COL tablePrivSpec3[] = {
5967 { "SYSTEM", "TABLEPRIV", "TABLE_CAT", SCOL_VARCHAR, 50 },
5968 { "SYSTEM", "TABLEPRIV", "TABLE_SCHEM", SCOL_VARCHAR, 50 },
5969 { "SYSTEM", "TABLEPRIV", "TABLE_NAME", SCOL_VARCHAR, 255 },
5970 { "SYSTEM", "TABLEPRIV", "GRANTOR", SCOL_VARCHAR, 50 },
5971 { "SYSTEM", "TABLEPRIV", "GRANTEE", SCOL_VARCHAR, 50 },
5972 { "SYSTEM", "TABLEPRIV", "PRIVILEGE", SCOL_VARCHAR, 50 },
5973 { "SYSTEM", "TABLEPRIV", "IS_GRANTABLE", SCOL_VARCHAR, 50 }
5974 };
5975
5976 /**
5977 * Retrieve privileges on tables and/or views.
5978 * @param stmt statement handle
5979 * @param cat catalog name/pattern or NULL
5980 * @param catLen length of catalog name/pattern or SQL_NTS
5981 * @param schema schema name/pattern or NULL
5982 * @param schemaLen length of schema name/pattern or SQL_NTS
5983 * @param table table name/pattern or NULL
5984 * @param tableLen length of table name/pattern or SQL_NTS
5985 * @result ODBC error code
5986 */
5987
5988 static SQLRETURN
drvtableprivileges(SQLHSTMT stmt,SQLCHAR * cat,SQLSMALLINT catLen,SQLCHAR * schema,SQLSMALLINT schemaLen,SQLCHAR * table,SQLSMALLINT tableLen)5989 drvtableprivileges(SQLHSTMT stmt,
5990 SQLCHAR *cat, SQLSMALLINT catLen,
5991 SQLCHAR *schema, SQLSMALLINT schemaLen,
5992 SQLCHAR *table, SQLSMALLINT tableLen)
5993 {
5994 SQLRETURN ret;
5995 STMT *s;
5996 DBC *d;
5997 int ncols, rc, size, npatt;
5998 char *errp = NULL, *sql, tname[512];
5999
6000 ret = mkresultset(stmt, tablePrivSpec2, array_size(tablePrivSpec2),
6001 tablePrivSpec3, array_size(tablePrivSpec3), NULL);
6002 if (ret != SQL_SUCCESS) {
6003 return ret;
6004 }
6005 s = (STMT *) stmt;
6006 d = (DBC *) s->dbc;
6007 if (cat && (catLen > 0 || catLen == SQL_NTS) && cat[0] == '%') {
6008 table = NULL;
6009 goto doit;
6010 }
6011 if (schema && (schemaLen > 0 || schemaLen == SQL_NTS) &&
6012 schema[0] == '%') {
6013 if ((!cat || catLen == 0 || !cat[0]) &&
6014 (!table || tableLen == 0 || !table[0])) {
6015 table = NULL;
6016 goto doit;
6017 }
6018 }
6019 doit:
6020 if (!table) {
6021 size = 1;
6022 tname[0] = '%';
6023 } else {
6024 if (tableLen == SQL_NTS) {
6025 size = sizeof (tname) - 1;
6026 } else {
6027 size = min(sizeof (tname) - 1, tableLen);
6028 }
6029 strncpy(tname, (char *) table, size);
6030 }
6031 tname[size] = '\0';
6032 npatt = unescpat(tname);
6033 #if defined(_WIN32) || defined(_WIN64)
6034 if (npatt) {
6035 sql = sqlite3_mprintf("select %s as 'TABLE_QUALIFIER', "
6036 "%s as 'TABLE_OWNER', "
6037 "tbl_name as 'TABLE_NAME', "
6038 "'' as 'GRANTOR', "
6039 "'' as 'GRANTEE', "
6040 "'SELECT' AS 'PRIVILEGE', "
6041 "NULL as 'IS_GRANTABLE' "
6042 "from sqlite_master where "
6043 "(type = 'table' or type = 'view') "
6044 "and tbl_name like %Q "
6045 "UNION "
6046 "select %s as 'TABLE_QUALIFIER', "
6047 "%s as 'TABLE_OWNER', "
6048 "tbl_name as 'TABLE_NAME', "
6049 "'' as 'GRANTOR', "
6050 "'' as 'GRANTEE', "
6051 "'UPDATE' AS 'PRIVILEGE', "
6052 "NULL as 'IS_GRANTABLE' "
6053 "from sqlite_master where "
6054 "(type = 'table' or type = 'view') "
6055 "and tbl_name like %Q "
6056 "UNION "
6057 "select %s as 'TABLE_QUALIFIER', "
6058 "%s as 'TABLE_OWNER', "
6059 "tbl_name as 'TABLE_NAME', "
6060 "'' as 'GRANTOR', "
6061 "'' as 'GRANTEE', "
6062 "'DELETE' AS 'PRIVILEGE', "
6063 "NULL as 'IS_GRANTABLE' "
6064 "from sqlite_master where "
6065 "(type = 'table' or type = 'view') "
6066 "and tbl_name like %Q "
6067 "UNION "
6068 "select %s as 'TABLE_QUALIFIER', "
6069 "%s as 'TABLE_OWNER', "
6070 "tbl_name as 'TABLE_NAME', "
6071 "'' as 'GRANTOR', "
6072 "'' as 'GRANTEE', "
6073 "'INSERT' AS 'PRIVILEGE', "
6074 "NULL as 'IS_GRANTABLE' "
6075 "from sqlite_master where "
6076 "(type = 'table' or type = 'view') "
6077 "and tbl_name like %Q "
6078 "UNION "
6079 "select %s as 'TABLE_QUALIFIER', "
6080 "%s as 'TABLE_OWNER', "
6081 "tbl_name as 'TABLE_NAME', "
6082 "'' as 'GRANTOR', "
6083 "'' as 'GRANTEE', "
6084 "'REFERENCES' AS 'PRIVILEGE', "
6085 "NULL as 'IS_GRANTABLE' "
6086 "from sqlite_master where "
6087 "(type = 'table' or type = 'view') "
6088 "and tbl_name like %Q",
6089 d->xcelqrx ? "'main'" : "NULL",
6090 d->xcelqrx ? "''" : "NULL",
6091 tname,
6092 d->xcelqrx ? "'main'" : "NULL",
6093 d->xcelqrx ? "''" : "NULL",
6094 tname,
6095 d->xcelqrx ? "'main'" : "NULL",
6096 d->xcelqrx ? "''" : "NULL",
6097 tname,
6098 d->xcelqrx ? "'main'" : "NULL",
6099 d->xcelqrx ? "''" : "NULL",
6100 tname,
6101 d->xcelqrx ? "'main'" : "NULL",
6102 d->xcelqrx ? "''" : "NULL",
6103 tname);
6104 } else {
6105 sql = sqlite3_mprintf("select %s as 'TABLE_QUALIFIER', "
6106 "%s as 'TABLE_OWNER', "
6107 "tbl_name as 'TABLE_NAME', "
6108 "'' as 'GRANTOR', "
6109 "'' as 'GRANTEE', "
6110 "'SELECT' AS 'PRIVILEGE', "
6111 "NULL as 'IS_GRANTABLE' "
6112 "from sqlite_master where "
6113 "(type = 'table' or type = 'view') "
6114 "and lower(tbl_name) = lower(%Q) "
6115 "UNION "
6116 "select %s as 'TABLE_QUALIFIER', "
6117 "%s as 'TABLE_OWNER', "
6118 "tbl_name as 'TABLE_NAME', "
6119 "'' as 'GRANTOR', "
6120 "'' as 'GRANTEE', "
6121 "'UPDATE' AS 'PRIVILEGE', "
6122 "NULL as 'IS_GRANTABLE' "
6123 "from sqlite_master where "
6124 "(type = 'table' or type = 'view') "
6125 "and lower(tbl_name) = lower(%Q) "
6126 "UNION "
6127 "select %s as 'TABLE_QUALIFIER', "
6128 "%s as 'TABLE_OWNER', "
6129 "tbl_name as 'TABLE_NAME', "
6130 "'' as 'GRANTOR', "
6131 "'' as 'GRANTEE', "
6132 "'DELETE' AS 'PRIVILEGE', "
6133 "NULL as 'IS_GRANTABLE' "
6134 "from sqlite_master where "
6135 "(type = 'table' or type = 'view') "
6136 "and lower(tbl_name) = lower(%Q) "
6137 "UNION "
6138 "select %s as 'TABLE_QUALIFIER', "
6139 "%s as 'TABLE_OWNER', "
6140 "tbl_name as 'TABLE_NAME', "
6141 "'' as 'GRANTOR', "
6142 "'' as 'GRANTEE', "
6143 "'INSERT' AS 'PRIVILEGE', "
6144 "NULL as 'IS_GRANTABLE' "
6145 "from sqlite_master where "
6146 "(type = 'table' or type = 'view') "
6147 "and lower(tbl_name) = lower(%Q) "
6148 "UNION "
6149 "select %s as 'TABLE_QUALIFIER', "
6150 "%s as 'TABLE_OWNER', "
6151 "tbl_name as 'TABLE_NAME', "
6152 "'' as 'GRANTOR', "
6153 "'' as 'GRANTEE', "
6154 "'REFERENCES' AS 'PRIVILEGE', "
6155 "NULL as 'IS_GRANTABLE' "
6156 "from sqlite_master where "
6157 "(type = 'table' or type = 'view') "
6158 "and lower(tbl_name) = lower(%Q)",
6159 d->xcelqrx ? "'main'" : "NULL",
6160 d->xcelqrx ? "''" : "NULL",
6161 tname,
6162 d->xcelqrx ? "'main'" : "NULL",
6163 d->xcelqrx ? "''" : "NULL",
6164 tname,
6165 d->xcelqrx ? "'main'" : "NULL",
6166 d->xcelqrx ? "''" : "NULL",
6167 tname,
6168 d->xcelqrx ? "'main'" : "NULL",
6169 d->xcelqrx ? "''" : "NULL",
6170 tname,
6171 d->xcelqrx ? "'main'" : "NULL",
6172 d->xcelqrx ? "''" : "NULL",
6173 tname);
6174 }
6175 #else
6176 if (npatt) {
6177 sql = sqlite3_mprintf("select NULL as 'TABLE_QUALIFIER', "
6178 "NULL as 'TABLE_OWNER', "
6179 "tbl_name as 'TABLE_NAME', "
6180 "'' as 'GRANTOR', "
6181 "'' as 'GRANTEE', "
6182 "'SELECT' AS 'PRIVILEGE', "
6183 "NULL as 'IS_GRANTABLE' "
6184 "from sqlite_master where "
6185 "(type = 'table' or type = 'view') "
6186 "and tbl_name like %Q "
6187 "UNION "
6188 "select NULL as 'TABLE_QUALIFIER', "
6189 "NULL as 'TABLE_OWNER', "
6190 "tbl_name as 'TABLE_NAME', "
6191 "'' as 'GRANTOR', "
6192 "'' as 'GRANTEE', "
6193 "'UPDATE' AS 'PRIVILEGE', "
6194 "NULL as 'IS_GRANTABLE' "
6195 "from sqlite_master where "
6196 "(type = 'table' or type = 'view') "
6197 "and tbl_name like %Q "
6198 "UNION "
6199 "select NULL as 'TABLE_QUALIFIER', "
6200 "NULL as 'TABLE_OWNER', "
6201 "tbl_name as 'TABLE_NAME', "
6202 "'' as 'GRANTOR', "
6203 "'' as 'GRANTEE', "
6204 "'DELETE' AS 'PRIVILEGE', "
6205 "NULL as 'IS_GRANTABLE' "
6206 "from sqlite_master where "
6207 "(type = 'table' or type = 'view') "
6208 "and tbl_name like %Q "
6209 "UNION "
6210 "select NULL as 'TABLE_QUALIFIER', "
6211 "NULL as 'TABLE_OWNER', "
6212 "tbl_name as 'TABLE_NAME', "
6213 "'' as 'GRANTOR', "
6214 "'' as 'GRANTEE', "
6215 "'INSERT' AS 'PRIVILEGE', "
6216 "NULL as 'IS_GRANTABLE' "
6217 "from sqlite_master where "
6218 "(type = 'table' or type = 'view') "
6219 "and tbl_name like %Q "
6220 "UNION "
6221 "select NULL as 'TABLE_QUALIFIER', "
6222 "NULL as 'TABLE_OWNER', "
6223 "tbl_name as 'TABLE_NAME', "
6224 "'' as 'GRANTOR', "
6225 "'' as 'GRANTEE', "
6226 "'REFERENCES' AS 'PRIVILEGE', "
6227 "NULL as 'IS_GRANTABLE' "
6228 "from sqlite_master where "
6229 "(type = 'table' or type = 'view') "
6230 "and tbl_name like %Q",
6231 tname, tname, tname, tname, tname);
6232 } else {
6233 sql = sqlite3_mprintf("select NULL as 'TABLE_QUALIFIER', "
6234 "NULL as 'TABLE_OWNER', "
6235 "tbl_name as 'TABLE_NAME', "
6236 "'' as 'GRANTOR', "
6237 "'' as 'GRANTEE', "
6238 "'SELECT' AS 'PRIVILEGE', "
6239 "NULL as 'IS_GRANTABLE' "
6240 "from sqlite_master where "
6241 "(type = 'table' or type = 'view') "
6242 "and lower(tbl_name) = lower(%Q) "
6243 "UNION "
6244 "select NULL as 'TABLE_QUALIFIER', "
6245 "NULL as 'TABLE_OWNER', "
6246 "tbl_name as 'TABLE_NAME', "
6247 "'' as 'GRANTOR', "
6248 "'' as 'GRANTEE', "
6249 "'UPDATE' AS 'PRIVILEGE', "
6250 "NULL as 'IS_GRANTABLE' "
6251 "from sqlite_master where "
6252 "(type = 'table' or type = 'view') "
6253 "and lower(tbl_name) = lower(%Q) "
6254 "UNION "
6255 "select NULL as 'TABLE_QUALIFIER', "
6256 "NULL as 'TABLE_OWNER', "
6257 "tbl_name as 'TABLE_NAME', "
6258 "'' as 'GRANTOR', "
6259 "'' as 'GRANTEE', "
6260 "'DELETE' AS 'PRIVILEGE', "
6261 "NULL as 'IS_GRANTABLE' "
6262 "from sqlite_master where "
6263 "(type = 'table' or type = 'view') "
6264 "and lower(tbl_name) = lower(%Q) "
6265 "UNION "
6266 "select NULL as 'TABLE_QUALIFIER', "
6267 "NULL as 'TABLE_OWNER', "
6268 "tbl_name as 'TABLE_NAME', "
6269 "'' as 'GRANTOR', "
6270 "'' as 'GRANTEE', "
6271 "'INSERT' AS 'PRIVILEGE', "
6272 "NULL as 'IS_GRANTABLE' "
6273 "from sqlite_master where "
6274 "(type = 'table' or type = 'view') "
6275 "and lower(tbl_name) = lower(%Q) "
6276 "UNION "
6277 "select NULL as 'TABLE_QUALIFIER', "
6278 "NULL as 'TABLE_OWNER', "
6279 "tbl_name as 'TABLE_NAME', "
6280 "'' as 'GRANTOR', "
6281 "'' as 'GRANTEE', "
6282 "'REFERENCES' AS 'PRIVILEGE', "
6283 "NULL as 'IS_GRANTABLE' "
6284 "from sqlite_master where "
6285 "(type = 'table' or type = 'view') "
6286 "and lower(tbl_name) = lower(%Q)",
6287 tname, tname, tname, tname, tname);
6288 }
6289 #endif
6290 if (!sql) {
6291 return nomem(s);
6292 }
6293 ret = starttran(s);
6294 if (ret != SQL_SUCCESS) {
6295 sqlite3_free(sql);
6296 return ret;
6297 }
6298 dbtraceapi(d, "sqlite3_get_table", sql);
6299 rc = sqlite3_get_table(d->sqlite, sql, &s->rows, &s->nrows, &ncols, &errp);
6300 sqlite3_free(sql);
6301 if (rc == SQLITE_OK) {
6302 if (ncols != s->ncols) {
6303 freeresult(s, 0);
6304 s->nrows = 0;
6305 } else {
6306 s->rowfree = sqlite3_free_table;
6307 }
6308 } else {
6309 s->nrows = 0;
6310 s->rows = NULL;
6311 s->rowfree = NULL;
6312 }
6313 if (errp) {
6314 sqlite3_free(errp);
6315 errp = NULL;
6316 }
6317 s->rowp = s->rowprs = -1;
6318 return SQL_SUCCESS;
6319 }
6320
6321
6322 #if !defined(WINTERFACE) || (defined(HAVE_UNIXODBC) && (HAVE_UNIXODBC))
6323 /**
6324 * Retrieve privileges on tables and/or views.
6325 * @param stmt statement handle
6326 * @param catalog catalog name/pattern or NULL
6327 * @param catalogLen length of catalog name/pattern or SQL_NTS
6328 * @param schema schema name/pattern or NULL
6329 * @param schemaLen length of schema name/pattern or SQL_NTS
6330 * @param table table name/pattern or NULL
6331 * @param tableLen length of table name/pattern or SQL_NTS
6332 * @result ODBC error code
6333 */
6334
6335 SQLRETURN SQL_API
SQLTablePrivileges(SQLHSTMT stmt,SQLCHAR * catalog,SQLSMALLINT catalogLen,SQLCHAR * schema,SQLSMALLINT schemaLen,SQLCHAR * table,SQLSMALLINT tableLen)6336 SQLTablePrivileges(SQLHSTMT stmt,
6337 SQLCHAR *catalog, SQLSMALLINT catalogLen,
6338 SQLCHAR *schema, SQLSMALLINT schemaLen,
6339 SQLCHAR *table, SQLSMALLINT tableLen)
6340 {
6341 #if defined(_WIN32) || defined(_WIN64)
6342 char *c = NULL, *s = NULL, *t = NULL;
6343 #endif
6344 SQLRETURN ret;
6345
6346 HSTMT_LOCK(stmt);
6347 #if defined(_WIN32) || defined(_WIN64)
6348 if (!((STMT *) stmt)->oemcp[0]) {
6349 ret = drvtableprivileges(stmt, catalog, catalogLen, schema, schemaLen,
6350 table, tableLen);
6351 goto done2;
6352 }
6353 if (catalog) {
6354 c = wmb_to_utf_c((char *) catalog, catalogLen);
6355 if (!c) {
6356 ret = nomem((STMT *) stmt);
6357 goto done;
6358 }
6359 }
6360 if (schema) {
6361 s = wmb_to_utf_c((char *) schema, schemaLen);
6362 if (!s) {
6363 ret = nomem((STMT *) stmt);
6364 goto done;
6365 }
6366 }
6367 if (table) {
6368 t = wmb_to_utf_c((char *) table, tableLen);
6369 if (!t) {
6370 ret = nomem((STMT *) stmt);
6371 goto done;
6372 }
6373 }
6374 ret = drvtableprivileges(stmt, (SQLCHAR *) c, SQL_NTS,
6375 (SQLCHAR *) s, SQL_NTS,
6376 (SQLCHAR *) t, SQL_NTS);
6377 #else
6378 ret = drvtableprivileges(stmt, catalog, catalogLen, schema, schemaLen,
6379 table, tableLen);
6380 #endif
6381 #if defined(_WIN32) || defined(_WIN64)
6382 done:
6383 uc_free(t);
6384 uc_free(s);
6385 uc_free(c);
6386 done2:
6387 ;
6388 #endif
6389 HSTMT_UNLOCK(stmt);
6390 return ret;
6391 }
6392 #endif
6393
6394 #if !defined(HAVE_UNIXODBC) || !(HAVE_UNIXODBC)
6395 #ifdef WINTERFACE
6396 /**
6397 * Retrieve privileges on tables and/or views (UNICODE version).
6398 * @param stmt statement handle
6399 * @param catalog catalog name/pattern or NULL
6400 * @param catalogLen length of catalog name/pattern or SQL_NTS
6401 * @param schema schema name/pattern or NULL
6402 * @param schemaLen length of schema name/pattern or SQL_NTS
6403 * @param table table name/pattern or NULL
6404 * @param tableLen length of table name/pattern or SQL_NTS
6405 * @result ODBC error code
6406 */
6407
6408 SQLRETURN SQL_API
SQLTablePrivilegesW(SQLHSTMT stmt,SQLWCHAR * catalog,SQLSMALLINT catalogLen,SQLWCHAR * schema,SQLSMALLINT schemaLen,SQLWCHAR * table,SQLSMALLINT tableLen)6409 SQLTablePrivilegesW(SQLHSTMT stmt,
6410 SQLWCHAR *catalog, SQLSMALLINT catalogLen,
6411 SQLWCHAR *schema, SQLSMALLINT schemaLen,
6412 SQLWCHAR *table, SQLSMALLINT tableLen)
6413 {
6414 char *c = NULL, *s = NULL, *t = NULL;
6415 SQLRETURN ret;
6416
6417 HSTMT_LOCK(stmt);
6418 if (catalog) {
6419 c = uc_to_utf_c(catalog, catalogLen);
6420 if (!c) {
6421 ret = nomem((STMT *) stmt);
6422 goto done;
6423 }
6424 }
6425 if (schema) {
6426 s = uc_to_utf_c(schema, schemaLen);
6427 if (!s) {
6428 ret = nomem((STMT *) stmt);
6429 goto done;
6430 }
6431 }
6432 if (table) {
6433 t = uc_to_utf_c(table, tableLen);
6434 if (!t) {
6435 ret = nomem((STMT *) stmt);
6436 goto done;
6437 }
6438 }
6439 ret = drvtableprivileges(stmt, (SQLCHAR *) c, SQL_NTS,
6440 (SQLCHAR *) s, SQL_NTS,
6441 (SQLCHAR *) t, SQL_NTS);
6442 done:
6443 uc_free(t);
6444 uc_free(s);
6445 uc_free(c);
6446 HSTMT_UNLOCK(stmt);
6447 return ret;
6448 }
6449 #endif
6450 #endif
6451
6452 /**
6453 * Columns for result set of SQLColumnPrivileges().
6454 */
6455
6456 static COL colPrivSpec2[] = {
6457 { "SYSTEM", "COLPRIV", "TABLE_QUALIFIER", SCOL_VARCHAR, 50 },
6458 { "SYSTEM", "COLPRIV", "TABLE_OWNER", SCOL_VARCHAR, 50 },
6459 { "SYSTEM", "COLPRIV", "TABLE_NAME", SCOL_VARCHAR, 255 },
6460 { "SYSTEM", "COLPRIV", "COLUMN_NAME", SCOL_VARCHAR, 255 },
6461 { "SYSTEM", "COLPRIV", "GRANTOR", SCOL_VARCHAR, 50 },
6462 { "SYSTEM", "COLPRIV", "GRANTEE", SCOL_VARCHAR, 50 },
6463 { "SYSTEM", "COLPRIV", "PRIVILEGE", SCOL_VARCHAR, 50 }
6464 };
6465
6466 static COL colPrivSpec3[] = {
6467 { "SYSTEM", "COLPRIV", "TABLE_CAT", SCOL_VARCHAR, 50 },
6468 { "SYSTEM", "COLPRIV", "TABLE_SCHEM", SCOL_VARCHAR, 50 },
6469 { "SYSTEM", "COLPRIV", "TABLE_NAME", SCOL_VARCHAR, 255 },
6470 { "SYSTEM", "COLPRIV", "COLUMN_NAME", SCOL_VARCHAR, 255 },
6471 { "SYSTEM", "COLPRIV", "GRANTOR", SCOL_VARCHAR, 50 },
6472 { "SYSTEM", "COLPRIV", "GRANTEE", SCOL_VARCHAR, 50 },
6473 { "SYSTEM", "COLPRIV", "PRIVILEGE", SCOL_VARCHAR, 50 }
6474 };
6475
6476 #if !defined(WINTERFACE) || (defined(HAVE_UNIXODBC) && (HAVE_UNIXODBC))
6477 /**
6478 * Retrieve privileges on columns.
6479 * @param stmt statement handle
6480 * @param catalog catalog name/pattern or NULL
6481 * @param catalogLen length of catalog name/pattern or SQL_NTS
6482 * @param schema schema name/pattern or NULL
6483 * @param schemaLen length of schema name/pattern or SQL_NTS
6484 * @param table table name/pattern or NULL
6485 * @param tableLen length of table name/pattern or SQL_NTS
6486 * @param column column name or NULL
6487 * @param columnLen length of column name or SQL_NTS
6488 * @result ODBC error code
6489 */
6490
6491 SQLRETURN SQL_API
SQLColumnPrivileges(SQLHSTMT stmt,SQLCHAR * catalog,SQLSMALLINT catalogLen,SQLCHAR * schema,SQLSMALLINT schemaLen,SQLCHAR * table,SQLSMALLINT tableLen,SQLCHAR * column,SQLSMALLINT columnLen)6492 SQLColumnPrivileges(SQLHSTMT stmt,
6493 SQLCHAR *catalog, SQLSMALLINT catalogLen,
6494 SQLCHAR *schema, SQLSMALLINT schemaLen,
6495 SQLCHAR *table, SQLSMALLINT tableLen,
6496 SQLCHAR *column, SQLSMALLINT columnLen)
6497 {
6498 SQLRETURN ret;
6499
6500 HSTMT_LOCK(stmt);
6501 ret = mkresultset(stmt, colPrivSpec2, array_size(colPrivSpec2),
6502 colPrivSpec3, array_size(colPrivSpec3), NULL);
6503 HSTMT_UNLOCK(stmt);
6504 return ret;
6505 }
6506 #endif
6507
6508 #if !defined(HAVE_UNIXODBC) || !(HAVE_UNIXODBC)
6509 #ifdef WINTERFACE
6510 /**
6511 * Retrieve privileges on columns (UNICODE version).
6512 * @param stmt statement handle
6513 * @param catalog catalog name/pattern or NULL
6514 * @param catalogLen length of catalog name/pattern or SQL_NTS
6515 * @param schema schema name/pattern or NULL
6516 * @param schemaLen length of schema name/pattern or SQL_NTS
6517 * @param table table name/pattern or NULL
6518 * @param tableLen length of table name/pattern or SQL_NTS
6519 * @param column column name or NULL
6520 * @param columnLen length of column name or SQL_NTS
6521 * @result ODBC error code
6522 */
6523
6524 SQLRETURN SQL_API
SQLColumnPrivilegesW(SQLHSTMT stmt,SQLWCHAR * catalog,SQLSMALLINT catalogLen,SQLWCHAR * schema,SQLSMALLINT schemaLen,SQLWCHAR * table,SQLSMALLINT tableLen,SQLWCHAR * column,SQLSMALLINT columnLen)6525 SQLColumnPrivilegesW(SQLHSTMT stmt,
6526 SQLWCHAR *catalog, SQLSMALLINT catalogLen,
6527 SQLWCHAR *schema, SQLSMALLINT schemaLen,
6528 SQLWCHAR *table, SQLSMALLINT tableLen,
6529 SQLWCHAR *column, SQLSMALLINT columnLen)
6530 {
6531 SQLRETURN ret;
6532
6533 HSTMT_LOCK(stmt);
6534 ret = mkresultset(stmt, colPrivSpec2, array_size(colPrivSpec2),
6535 colPrivSpec3, array_size(colPrivSpec3), NULL);
6536 HSTMT_UNLOCK(stmt);
6537 return ret;
6538 }
6539 #endif
6540 #endif
6541
6542 /**
6543 * Columns for result set of SQLPrimaryKeys().
6544 */
6545
6546 static COL pkeySpec2[] = {
6547 { "SYSTEM", "PRIMARYKEY", "TABLE_QUALIFIER", SCOL_VARCHAR, 50 },
6548 { "SYSTEM", "PRIMARYKEY", "TABLE_OWNER", SCOL_VARCHAR, 50 },
6549 { "SYSTEM", "PRIMARYKEY", "TABLE_NAME", SCOL_VARCHAR, 255 },
6550 { "SYSTEM", "PRIMARYKEY", "COLUMN_NAME", SCOL_VARCHAR, 255 },
6551 { "SYSTEM", "PRIMARYKEY", "KEY_SEQ", SQL_SMALLINT, 50 },
6552 { "SYSTEM", "PRIMARYKEY", "PK_NAME", SCOL_VARCHAR, 50 }
6553 };
6554
6555 static COL pkeySpec3[] = {
6556 { "SYSTEM", "PRIMARYKEY", "TABLE_CAT", SCOL_VARCHAR, 50 },
6557 { "SYSTEM", "PRIMARYKEY", "TABLE_SCHEM", SCOL_VARCHAR, 50 },
6558 { "SYSTEM", "PRIMARYKEY", "TABLE_NAME", SCOL_VARCHAR, 255 },
6559 { "SYSTEM", "PRIMARYKEY", "COLUMN_NAME", SCOL_VARCHAR, 255 },
6560 { "SYSTEM", "PRIMARYKEY", "KEY_SEQ", SQL_SMALLINT, 50 },
6561 { "SYSTEM", "PRIMARYKEY", "PK_NAME", SCOL_VARCHAR, 50 }
6562 };
6563
6564 /**
6565 * Internal retrieve information about indexed columns.
6566 * @param stmt statement handle
6567 * @param cat catalog name/pattern or NULL
6568 * @param catLen length of catalog name/pattern or SQL_NTS
6569 * @param schema schema name/pattern or NULL
6570 * @param schemaLen length of schema name/pattern or SQL_NTS
6571 * @param table table name/pattern or NULL
6572 * @param tableLen length of table name/pattern or SQL_NTS
6573 * @result ODBC error code
6574 */
6575
6576 static SQLRETURN
drvprimarykeys(SQLHSTMT stmt,SQLCHAR * cat,SQLSMALLINT catLen,SQLCHAR * schema,SQLSMALLINT schemaLen,SQLCHAR * table,SQLSMALLINT tableLen)6577 drvprimarykeys(SQLHSTMT stmt,
6578 SQLCHAR *cat, SQLSMALLINT catLen,
6579 SQLCHAR *schema, SQLSMALLINT schemaLen,
6580 SQLCHAR *table, SQLSMALLINT tableLen)
6581 {
6582 STMT *s;
6583 DBC *d;
6584 SQLRETURN sret;
6585 int i, asize, ret, nrows, ncols, nrows2 = 0, ncols2 = 0;
6586 int namec = -1, uniquec = -1, namec2 = -1, uniquec2 = -1, offs, seq = 1;
6587 PTRDIFF_T size;
6588 char **rowp = NULL, **rowp2 = NULL, *errp = NULL, *sql, tname[512];
6589
6590 sret = mkresultset(stmt, pkeySpec2, array_size(pkeySpec2),
6591 pkeySpec3, array_size(pkeySpec3), &asize);
6592 if (sret != SQL_SUCCESS) {
6593 return sret;
6594 }
6595 s = (STMT *) stmt;
6596 d = (DBC *) s->dbc;
6597 if (!table || table[0] == '\0' || table[0] == '%') {
6598 setstat(s, -1, "need table name", (*s->ov3) ? "HY000" : "S1000");
6599 return SQL_ERROR;
6600 }
6601 if (tableLen == SQL_NTS) {
6602 size = sizeof (tname) - 1;
6603 } else {
6604 size = min(sizeof (tname) - 1, tableLen);
6605 }
6606 strncpy(tname, (char *) table, size);
6607 tname[size] = '\0';
6608 unescpat(tname);
6609 sql = sqlite3_mprintf("PRAGMA table_info(%Q)", tname);
6610 if (!sql) {
6611 return nomem(s);
6612 }
6613 sret = starttran(s);
6614 if (sret != SQL_SUCCESS) {
6615 sqlite3_free(sql);
6616 return sret;
6617 }
6618 dbtraceapi(d, "sqlite3_get_table", sql);
6619 ret = sqlite3_get_table(d->sqlite, sql, &rowp, &nrows, &ncols, &errp);
6620 sqlite3_free(sql);
6621 if (ret != SQLITE_OK) {
6622 setstat(s, ret, "%s (%d)", (*s->ov3) ? "HY000" : "S1000",
6623 errp ? errp : "unknown error", ret);
6624 if (errp) {
6625 sqlite3_free(errp);
6626 errp = NULL;
6627 }
6628 return SQL_ERROR;
6629 }
6630 if (errp) {
6631 sqlite3_free(errp);
6632 errp = NULL;
6633 }
6634 size = 0;
6635 if (ncols * nrows > 0) {
6636 int typec;
6637
6638 namec = findcol(rowp, ncols, "name");
6639 uniquec = findcol(rowp, ncols, "pk");
6640 typec = findcol(rowp, ncols, "type");
6641 if (namec >= 0 && uniquec >= 0 && typec >= 0) {
6642 for (i = 1; i <= nrows; i++) {
6643 if (*rowp[i * ncols + uniquec] != '0') {
6644 size++;
6645 }
6646 }
6647 }
6648 }
6649 if (size == 0) {
6650 sql = sqlite3_mprintf("PRAGMA index_list(%Q)", tname);
6651 if (!sql) {
6652 sqlite3_free_table(rowp);
6653 return nomem(s);
6654 }
6655 dbtraceapi(d, "sqlite3_get_table", sql);
6656 ret = sqlite3_get_table(d->sqlite, sql, &rowp2, &nrows2, &ncols2,
6657 &errp);
6658 sqlite3_free(sql);
6659 if (ret != SQLITE_OK) {
6660 sqlite3_free_table(rowp);
6661 sqlite3_free_table(rowp2);
6662 setstat(s, ret, "%s (%d)", (*s->ov3) ? "HY000" : "S1000",
6663 errp ? errp : "unknown error", ret);
6664 if (errp) {
6665 sqlite3_free(errp);
6666 errp = NULL;
6667 }
6668 return SQL_ERROR;
6669 }
6670 if (errp) {
6671 sqlite3_free(errp);
6672 errp = NULL;
6673 }
6674 }
6675 if (ncols2 * nrows2 > 0) {
6676 namec2 = findcol(rowp2, ncols2, "name");
6677 uniquec2 = findcol(rowp2, ncols2, "unique");
6678 if (namec2 >= 0 && uniquec2 >= 0) {
6679 for (i = 1; i <= nrows2; i++) {
6680 int nnrows, nncols, nlen = 0;
6681 char **rowpp;
6682
6683 if (rowp2[i * ncols2 + namec2]) {
6684 nlen = strlen(rowp2[i * ncols2 + namec2]);
6685 }
6686 if (nlen < 17 ||
6687 strncmp(rowp2[i * ncols2 + namec2],
6688 "sqlite_autoindex_", 17)) {
6689 continue;
6690 }
6691 if (*rowp2[i * ncols2 + uniquec2] != '0') {
6692 ret = SQLITE_ERROR;
6693 sql = sqlite3_mprintf("PRAGMA index_info(%Q)",
6694 rowp2[i * ncols2 + namec2]);
6695 if (sql) {
6696 dbtraceapi(d, "sqlite3_get_table", sql);
6697 ret = sqlite3_get_table(d->sqlite, sql, &rowpp,
6698 &nnrows, &nncols, NULL);
6699 sqlite3_free(sql);
6700 }
6701 if (ret == SQLITE_OK) {
6702 size += nnrows;
6703 sqlite3_free_table(rowpp);
6704 }
6705 }
6706 }
6707 }
6708 }
6709 if (size == 0) {
6710 sqlite3_free_table(rowp);
6711 sqlite3_free_table(rowp2);
6712 return SQL_SUCCESS;
6713 }
6714 s->nrows = size;
6715 size = (size + 1) * asize;
6716 s->rows = xmalloc((size + 1) * sizeof (char *));
6717 if (!s->rows) {
6718 s->nrows = 0;
6719 sqlite3_free_table(rowp);
6720 sqlite3_free_table(rowp2);
6721 return nomem(s);
6722 }
6723 s->rows[0] = (char *) size;
6724 s->rows += 1;
6725 memset(s->rows, 0, sizeof (char *) * size);
6726 s->rowfree = freerows;
6727 offs = s->ncols;
6728 if (rowp) {
6729 for (i = 1; i <= nrows; i++) {
6730 if (*rowp[i * ncols + uniquec] != '0') {
6731 char buf[32];
6732
6733 #if defined(_WIN32) || defined(_WIN64)
6734 s->rows[offs + 0] = xstrdup(d->xcelqrx ? "main" : "");
6735 s->rows[offs + 1] = xstrdup("");
6736 #else
6737 s->rows[offs + 0] = xstrdup("");
6738 s->rows[offs + 1] = xstrdup("");
6739 #endif
6740 s->rows[offs + 2] = xstrdup(tname);
6741 s->rows[offs + 3] = xstrdup(rowp[i * ncols + namec]);
6742 sprintf(buf, "%d", seq++);
6743 s->rows[offs + 4] = xstrdup(buf);
6744 offs += s->ncols;
6745 }
6746 }
6747 }
6748 if (rowp2) {
6749 for (i = 1; i <= nrows2; i++) {
6750 int nnrows, nncols, nlen = 0;
6751 char **rowpp;
6752
6753 if (rowp2[i * ncols2 + namec2]) {
6754 nlen = strlen(rowp2[i * ncols2 + namec2]);
6755 }
6756 if (nlen < 17 ||
6757 strncmp(rowp2[i * ncols2 + namec2], "sqlite_autoindex_", 17)) {
6758 continue;
6759 }
6760 if (*rowp2[i * ncols2 + uniquec2] != '0') {
6761 int k;
6762
6763 ret = SQLITE_ERROR;
6764 sql = sqlite3_mprintf("PRAGMA index_info(%Q)",
6765 rowp2[i * ncols2 + namec2]);
6766 if (sql) {
6767 dbtraceapi(d, "sqlite3_get_table", sql);
6768 ret = sqlite3_get_table(d->sqlite, sql, &rowpp,
6769 &nnrows, &nncols, NULL);
6770 sqlite3_free(sql);
6771 }
6772 if (ret != SQLITE_OK) {
6773 continue;
6774 }
6775 for (k = 0; nnrows && k < nncols; k++) {
6776 if (strcmp(rowpp[k], "name") == 0) {
6777 int m;
6778
6779 for (m = 1; m <= nnrows; m++) {
6780 int roffs = offs + (m - 1) * s->ncols;
6781
6782 #if defined(_WIN32) || defined(_WIN64)
6783 s->rows[roffs + 0] =
6784 xstrdup(d->xcelqrx ? "main" : "");
6785 s->rows[roffs + 1] = xstrdup("");
6786 #else
6787 s->rows[roffs + 0] = xstrdup("");
6788 s->rows[roffs + 1] = xstrdup("");
6789 #endif
6790 s->rows[roffs + 2] = xstrdup(tname);
6791 s->rows[roffs + 3] =
6792 xstrdup(rowpp[m * nncols + k]);
6793 s->rows[roffs + 5] =
6794 xstrdup(rowp2[i * ncols2 + namec2]);
6795 }
6796 } else if (strcmp(rowpp[k], "seqno") == 0) {
6797 int m;
6798
6799 for (m = 1; m <= nnrows; m++) {
6800 int roffs = offs + (m - 1) * s->ncols;
6801 int pos = m - 1;
6802 char buf[32];
6803
6804 sscanf(rowpp[m * nncols + k], "%d", &pos);
6805 sprintf(buf, "%d", pos + 1);
6806 s->rows[roffs + 4] = xstrdup(buf);
6807 }
6808 }
6809 }
6810 offs += nnrows * s->ncols;
6811 sqlite3_free_table(rowpp);
6812 }
6813 }
6814 }
6815 sqlite3_free_table(rowp);
6816 sqlite3_free_table(rowp2);
6817 return SQL_SUCCESS;
6818 }
6819
6820 #ifndef WINTERFACE
6821 /**
6822 * Retrieve information about indexed columns.
6823 * @param stmt statement handle
6824 * @param cat catalog name/pattern or NULL
6825 * @param catLen length of catalog name/pattern or SQL_NTS
6826 * @param schema schema name/pattern or NULL
6827 * @param schemaLen length of schema name/pattern or SQL_NTS
6828 * @param table table name/pattern or NULL
6829 * @param tableLen length of table name/pattern or SQL_NTS
6830 * @result ODBC error code
6831 */
6832
6833 SQLRETURN SQL_API
SQLPrimaryKeys(SQLHSTMT stmt,SQLCHAR * cat,SQLSMALLINT catLen,SQLCHAR * schema,SQLSMALLINT schemaLen,SQLCHAR * table,SQLSMALLINT tableLen)6834 SQLPrimaryKeys(SQLHSTMT stmt,
6835 SQLCHAR *cat, SQLSMALLINT catLen,
6836 SQLCHAR *schema, SQLSMALLINT schemaLen,
6837 SQLCHAR *table, SQLSMALLINT tableLen)
6838 {
6839 #if defined(_WIN32) || defined(_WIN64)
6840 char *c = NULL, *s = NULL, *t = NULL;
6841 #endif
6842 SQLRETURN ret;
6843
6844 HSTMT_LOCK(stmt);
6845 #if defined(_WIN32) || defined(_WIN64)
6846 if (!((STMT *) stmt)->oemcp[0]) {
6847 ret = drvprimarykeys(stmt, cat, catLen, schema, schemaLen,
6848 table, tableLen);
6849 goto done2;
6850 }
6851 if (cat) {
6852 c = wmb_to_utf_c((char *) cat, catLen);
6853 if (!c) {
6854 ret = nomem((STMT *) stmt);
6855 goto done;
6856 }
6857 }
6858 if (schema) {
6859 s = wmb_to_utf_c((char *) schema, schemaLen);
6860 if (!s) {
6861 ret = nomem((STMT *) stmt);
6862 goto done;
6863 }
6864 }
6865 if (table) {
6866 t = wmb_to_utf_c((char *) table, tableLen);
6867 if (!t) {
6868 ret = nomem((STMT *) stmt);
6869 goto done;
6870 }
6871 }
6872 ret = drvprimarykeys(stmt, (SQLCHAR *) c, SQL_NTS,
6873 (SQLCHAR *) s, SQL_NTS, (SQLCHAR *) t, SQL_NTS);
6874 #else
6875 ret = drvprimarykeys(stmt, cat, catLen, schema, schemaLen,
6876 table, tableLen);
6877 #endif
6878 #if defined(_WIN32) || defined(_WIN64)
6879 done:
6880 uc_free(t);
6881 uc_free(s);
6882 uc_free(c);
6883 done2:
6884 ;
6885 #endif
6886 HSTMT_UNLOCK(stmt);
6887 return ret;
6888 }
6889 #endif
6890
6891 #ifdef WINTERFACE
6892 /**
6893 * Retrieve information about indexed columns (UNICODE version).
6894 * @param stmt statement handle
6895 * @param cat catalog name/pattern or NULL
6896 * @param catLen length of catalog name/pattern or SQL_NTS
6897 * @param schema schema name/pattern or NULL
6898 * @param schemaLen length of schema name/pattern or SQL_NTS
6899 * @param table table name/pattern or NULL
6900 * @param tableLen length of table name/pattern or SQL_NTS
6901 * @result ODBC error code
6902 */
6903
6904 SQLRETURN SQL_API
SQLPrimaryKeysW(SQLHSTMT stmt,SQLWCHAR * cat,SQLSMALLINT catLen,SQLWCHAR * schema,SQLSMALLINT schemaLen,SQLWCHAR * table,SQLSMALLINT tableLen)6905 SQLPrimaryKeysW(SQLHSTMT stmt,
6906 SQLWCHAR *cat, SQLSMALLINT catLen,
6907 SQLWCHAR *schema, SQLSMALLINT schemaLen,
6908 SQLWCHAR *table, SQLSMALLINT tableLen)
6909 {
6910 char *c = NULL, *s = NULL, *t = NULL;
6911 SQLRETURN ret;
6912
6913 HSTMT_LOCK(stmt);
6914 if (cat) {
6915 c = uc_to_utf_c(cat, catLen);
6916 if (!c) {
6917 ret = nomem((STMT *) stmt);
6918 goto done;
6919 }
6920 }
6921 if (schema) {
6922 s = uc_to_utf_c(schema, schemaLen);
6923 if (!s) {
6924 ret = nomem((STMT *) stmt);
6925 goto done;
6926 }
6927 }
6928 if (table) {
6929 t = uc_to_utf_c(table, tableLen);
6930 if (!t) {
6931 ret = nomem((STMT *) stmt);
6932 goto done;
6933 }
6934 }
6935 ret = drvprimarykeys(stmt, (SQLCHAR *) c, SQL_NTS,
6936 (SQLCHAR *) s, SQL_NTS, (SQLCHAR *) t, SQL_NTS);
6937 done:
6938 uc_free(t);
6939 uc_free(s);
6940 uc_free(c);
6941 HSTMT_UNLOCK(stmt);
6942 return ret;
6943 }
6944 #endif
6945
6946 /**
6947 * Columns for result set of SQLSpecialColumns().
6948 */
6949
6950 static COL scolSpec2[] = {
6951 { "SYSTEM", "COLUMN", "SCOPE", SQL_SMALLINT, 1 },
6952 { "SYSTEM", "COLUMN", "COLUMN_NAME", SCOL_VARCHAR, 255 },
6953 { "SYSTEM", "COLUMN", "DATA_TYPE", SQL_SMALLINT, 50 },
6954 { "SYSTEM", "COLUMN", "TYPE_NAME", SCOL_VARCHAR, 50 },
6955 { "SYSTEM", "COLUMN", "PRECISION", SQL_INTEGER, 50 },
6956 { "SYSTEM", "COLUMN", "LENGTH", SQL_INTEGER, 50 },
6957 { "SYSTEM", "COLUMN", "DECIMAL_DIGITS", SQL_INTEGER, 50 },
6958 { "SYSTEM", "COLUMN", "PSEUDO_COLUMN", SQL_SMALLINT, 1 },
6959 { "SYSTEM", "COLUMN", "NULLABLE", SQL_SMALLINT, 1 }
6960 };
6961
6962 static COL scolSpec3[] = {
6963 { "SYSTEM", "COLUMN", "SCOPE", SQL_SMALLINT, 1 },
6964 { "SYSTEM", "COLUMN", "COLUMN_NAME", SCOL_VARCHAR, 255 },
6965 { "SYSTEM", "COLUMN", "DATA_TYPE", SQL_SMALLINT, 50 },
6966 { "SYSTEM", "COLUMN", "TYPE_NAME", SCOL_VARCHAR, 50 },
6967 { "SYSTEM", "COLUMN", "COLUMN_SIZE", SQL_INTEGER, 50 },
6968 { "SYSTEM", "COLUMN", "BUFFER_LENGTH", SQL_INTEGER, 50 },
6969 { "SYSTEM", "COLUMN", "DECIMAL_DIGITS", SQL_INTEGER, 50 },
6970 { "SYSTEM", "COLUMN", "PSEUDO_COLUMN", SQL_SMALLINT, 1 },
6971 { "SYSTEM", "COLUMN", "NULLABLE", SQL_SMALLINT, 1 }
6972 };
6973
6974 /**
6975 * Internal retrieve information about indexed columns.
6976 * @param stmt statement handle
6977 * @param id type of information, e.g. best row id
6978 * @param cat catalog name/pattern or NULL
6979 * @param catLen length of catalog name/pattern or SQL_NTS
6980 * @param schema schema name/pattern or NULL
6981 * @param schemaLen length of schema name/pattern or SQL_NTS
6982 * @param table table name/pattern or NULL
6983 * @param tableLen length of table name/pattern or SQL_NTS
6984 * @param scope
6985 * @param nullable
6986 * @result ODBC error code
6987 */
6988
6989 static SQLRETURN
drvspecialcolumns(SQLHSTMT stmt,SQLUSMALLINT id,SQLCHAR * cat,SQLSMALLINT catLen,SQLCHAR * schema,SQLSMALLINT schemaLen,SQLCHAR * table,SQLSMALLINT tableLen,SQLUSMALLINT scope,SQLUSMALLINT nullable)6990 drvspecialcolumns(SQLHSTMT stmt, SQLUSMALLINT id,
6991 SQLCHAR *cat, SQLSMALLINT catLen,
6992 SQLCHAR *schema, SQLSMALLINT schemaLen,
6993 SQLCHAR *table, SQLSMALLINT tableLen,
6994 SQLUSMALLINT scope, SQLUSMALLINT nullable)
6995 {
6996 STMT *s;
6997 DBC *d;
6998 SQLRETURN sret;
6999 int i, asize, ret, nrows, ncols, nnnrows, nnncols, offs;
7000 PTRDIFF_T size;
7001 int namec = -1, uniquec = -1, namecc = -1, typecc = -1;
7002 int notnullcc = -1, mkrowid = 0;
7003 char *errp = NULL, *sql, tname[512];
7004 char **rowp = NULL, **rowppp = NULL;
7005
7006 sret = mkresultset(stmt, scolSpec2, array_size(scolSpec2),
7007 scolSpec3, array_size(scolSpec3), &asize);
7008 if (sret != SQL_SUCCESS) {
7009 return sret;
7010 }
7011 s = (STMT *) stmt;
7012 d = (DBC *) s->dbc;
7013 if (!table || table[0] == '\0' || table[0] == '%') {
7014 setstat(s, -1, "need table name", (*s->ov3) ? "HY000" : "S1000");
7015 return SQL_ERROR;
7016 }
7017 if (tableLen == SQL_NTS) {
7018 size = sizeof (tname) - 1;
7019 } else {
7020 size = min(sizeof (tname) - 1, tableLen);
7021 }
7022 strncpy(tname, (char *) table, size);
7023 tname[size] = '\0';
7024 unescpat(tname);
7025 if (id != SQL_BEST_ROWID) {
7026 return SQL_SUCCESS;
7027 }
7028 sql = sqlite3_mprintf("PRAGMA index_list(%Q)", tname);
7029 if (!sql) {
7030 return nomem(s);
7031 }
7032 sret = starttran(s);
7033 if (sret != SQL_SUCCESS) {
7034 sqlite3_free(sql);
7035 return sret;
7036 }
7037 dbtraceapi(d, "sqlite3_get_table", sql);
7038 ret = sqlite3_get_table(d->sqlite, sql, &rowp, &nrows, &ncols, &errp);
7039 sqlite3_free(sql);
7040 if (ret != SQLITE_OK) {
7041 doerr:
7042 setstat(s, ret, "%s (%d)", (*s->ov3) ? "HY000" : "S1000",
7043 errp ? errp : "unknown error", ret);
7044 if (errp) {
7045 sqlite3_free(errp);
7046 errp = NULL;
7047 }
7048 return SQL_ERROR;
7049 }
7050 if (errp) {
7051 sqlite3_free(errp);
7052 errp = NULL;
7053 }
7054 size = 0; /* number result rows */
7055 if (ncols * nrows <= 0) {
7056 goto nodata_but_rowid;
7057 }
7058 sql = sqlite3_mprintf("PRAGMA table_info(%Q)", tname);
7059 if (!sql) {
7060 return nomem(s);
7061 }
7062 dbtraceapi(d, "sqlite3_get_table", sql);
7063 ret = sqlite3_get_table(d->sqlite, sql, &rowppp, &nnnrows, &nnncols,
7064 &errp);
7065 sqlite3_free(sql);
7066 if (ret != SQLITE_OK) {
7067 sqlite3_free_table(rowp);
7068 goto doerr;
7069 }
7070 if (errp) {
7071 sqlite3_free(errp);
7072 errp = NULL;
7073 }
7074 namec = findcol(rowp, ncols, "name");
7075 uniquec = findcol(rowp, ncols, "unique");
7076 if (namec < 0 || uniquec < 0) {
7077 goto nodata_but_rowid;
7078 }
7079 namecc = findcol(rowppp, nnncols, "name");
7080 typecc = findcol(rowppp, nnncols, "type");
7081 notnullcc = findcol(rowppp, nnncols, "notnull");
7082 for (i = 1; i <= nrows; i++) {
7083 int nnrows, nncols;
7084 char **rowpp = NULL;
7085
7086 if (*rowp[i * ncols + uniquec] != '0') {
7087 ret = SQLITE_ERROR;
7088 sql = sqlite3_mprintf("PRAGMA index_info(%Q)",
7089 rowp[i * ncols + namec]);
7090 if (sql) {
7091 dbtraceapi(d, "sqlite3_get_table", sql);
7092 ret = sqlite3_get_table(d->sqlite, sql, &rowpp,
7093 &nnrows, &nncols, NULL);
7094 sqlite3_free(sql);
7095 }
7096 if (ret == SQLITE_OK) {
7097 size += nnrows;
7098 sqlite3_free_table(rowpp);
7099 }
7100 }
7101 }
7102 nodata_but_rowid:
7103 if (size == 0) {
7104 size = 1;
7105 mkrowid = 1;
7106 }
7107 s->nrows = size;
7108 size = (size + 1) * asize;
7109 s->rows = xmalloc((size + 1) * sizeof (char *));
7110 if (!s->rows) {
7111 s->nrows = 0;
7112 sqlite3_free_table(rowp);
7113 sqlite3_free_table(rowppp);
7114 return nomem(s);
7115 }
7116 s->rows[0] = (char *) size;
7117 s->rows += 1;
7118 memset(s->rows, 0, sizeof (char *) * size);
7119 s->rowfree = freerows;
7120 if (mkrowid) {
7121 s->nrows = 0;
7122 goto mkrowid;
7123 }
7124 offs = 0;
7125 for (i = 1; i <= nrows; i++) {
7126 int nnrows, nncols;
7127 char **rowpp = NULL;
7128
7129 if (*rowp[i * ncols + uniquec] != '0') {
7130 int k;
7131
7132 ret = SQLITE_ERROR;
7133 sql = sqlite3_mprintf("PRAGMA index_info(%Q)",
7134 rowp[i * ncols + namec]);
7135 if (sql) {
7136 dbtraceapi(d, "sqlite3_get_table", sql);
7137 ret = sqlite3_get_table(d->sqlite, sql, &rowpp,
7138 &nnrows, &nncols, NULL);
7139 sqlite3_free(sql);
7140 }
7141 if (ret != SQLITE_OK) {
7142 continue;
7143 }
7144 for (k = 0; nnrows && k < nncols; k++) {
7145 if (strcmp(rowpp[k], "name") == 0) {
7146 int m;
7147
7148 for (m = 1; m <= nnrows; m++) {
7149 int roffs = (offs + m) * s->ncols;
7150
7151 s->rows[roffs + 0] =
7152 xstrdup(stringify(SQL_SCOPE_SESSION));
7153 s->rows[roffs + 1] = xstrdup(rowpp[m * nncols + k]);
7154 s->rows[roffs + 4] = xstrdup("0");
7155 s->rows[roffs + 7] =
7156 xstrdup(stringify(SQL_PC_NOT_PSEUDO));
7157 if (namecc >= 0 && typecc >= 0) {
7158 int ii;
7159
7160 for (ii = 1; ii <= nnnrows; ii++) {
7161 if (strcmp(rowppp[ii * nnncols + namecc],
7162 rowpp[m * nncols + k]) == 0) {
7163 char *typen = rowppp[ii * nnncols + typecc];
7164 int sqltype, mm, dd, isnullable = 0;
7165 char buf[32];
7166
7167 s->rows[roffs + 3] = xstrdup(typen);
7168 sqltype = mapsqltype(typen, NULL, *s->ov3,
7169 s->nowchar[0],
7170 s->dobigint);
7171 getmd(typen, sqltype, &mm, &dd);
7172 #ifdef SQL_LONGVARCHAR
7173 if (sqltype == SQL_VARCHAR && mm > 255) {
7174 sqltype = SQL_LONGVARCHAR;
7175 }
7176 #endif
7177 #ifdef WINTERFACE
7178 #ifdef SQL_WLONGVARCHAR
7179 if (sqltype == SQL_WVARCHAR && mm > 255) {
7180 sqltype = SQL_WLONGVARCHAR;
7181 }
7182 #endif
7183 #endif
7184 if (sqltype == SQL_VARBINARY && mm > 255) {
7185 sqltype = SQL_LONGVARBINARY;
7186 }
7187 sprintf(buf, "%d", sqltype);
7188 s->rows[roffs + 2] = xstrdup(buf);
7189 sprintf(buf, "%d", mm);
7190 s->rows[roffs + 5] = xstrdup(buf);
7191 sprintf(buf, "%d", dd);
7192 s->rows[roffs + 6] = xstrdup(buf);
7193 if (notnullcc >= 0) {
7194 char *inp =
7195 rowppp[ii * nnncols + notnullcc];
7196
7197 isnullable = inp[0] != '0';
7198 }
7199 sprintf(buf, "%d", isnullable);
7200 s->rows[roffs + 8] = xstrdup(buf);
7201 }
7202 }
7203 }
7204 }
7205 }
7206 }
7207 offs += nnrows;
7208 sqlite3_free_table(rowpp);
7209 }
7210 }
7211 if (nullable == SQL_NO_NULLS) {
7212 for (i = 1; i < s->nrows; i++) {
7213 if (s->rows[i * s->ncols + 8][0] == '0') {
7214 int m, i1 = i + 1;
7215
7216 for (m = 0; m < s->ncols; m++) {
7217 freep(&s->rows[i * s->ncols + m]);
7218 }
7219 size = s->ncols * sizeof (char *) * (s->nrows - i1);
7220 if (size > 0) {
7221 memmove(s->rows + i * s->ncols,
7222 s->rows + i1 * s->ncols,
7223 size);
7224 memset(s->rows + s->nrows * s->ncols, 0,
7225 s->ncols * sizeof (char *));
7226 }
7227 s->nrows--;
7228 --i;
7229 }
7230 }
7231 }
7232 mkrowid:
7233 sqlite3_free_table(rowp);
7234 sqlite3_free_table(rowppp);
7235 if (s->nrows == 0) {
7236 s->rows[s->ncols + 0] = xstrdup(stringify(SQL_SCOPE_SESSION));
7237 s->rows[s->ncols + 1] = xstrdup("_ROWID_");
7238 s->rows[s->ncols + 2] = xstrdup(stringify(SQL_INTEGER));
7239 s->rows[s->ncols + 3] = xstrdup("integer");
7240 s->rows[s->ncols + 4] = xstrdup("0");
7241 s->rows[s->ncols + 5] = xstrdup("10");
7242 s->rows[s->ncols + 6] = xstrdup("9");
7243 s->rows[s->ncols + 7] = xstrdup(stringify(SQL_PC_PSEUDO));
7244 s->rows[s->ncols + 8] = xstrdup(stringify(SQL_FALSE));
7245 s->nrows = 1;
7246 }
7247 return SQL_SUCCESS;
7248 }
7249
7250 #ifndef WINTERFACE
7251 /**
7252 * Retrieve information about indexed columns.
7253 * @param stmt statement handle
7254 * @param id type of information, e.g. best row id
7255 * @param cat catalog name/pattern or NULL
7256 * @param catLen length of catalog name/pattern or SQL_NTS
7257 * @param schema schema name/pattern or NULL
7258 * @param schemaLen length of schema name/pattern or SQL_NTS
7259 * @param table table name/pattern or NULL
7260 * @param tableLen length of table name/pattern or SQL_NTS
7261 * @param scope
7262 * @param nullable
7263 * @result ODBC error code
7264 */
7265
7266 SQLRETURN SQL_API
SQLSpecialColumns(SQLHSTMT stmt,SQLUSMALLINT id,SQLCHAR * cat,SQLSMALLINT catLen,SQLCHAR * schema,SQLSMALLINT schemaLen,SQLCHAR * table,SQLSMALLINT tableLen,SQLUSMALLINT scope,SQLUSMALLINT nullable)7267 SQLSpecialColumns(SQLHSTMT stmt, SQLUSMALLINT id,
7268 SQLCHAR *cat, SQLSMALLINT catLen,
7269 SQLCHAR *schema, SQLSMALLINT schemaLen,
7270 SQLCHAR *table, SQLSMALLINT tableLen,
7271 SQLUSMALLINT scope, SQLUSMALLINT nullable)
7272 {
7273 #if defined(_WIN32) || defined(_WIN64)
7274 char *c = NULL, *s = NULL, *t = NULL;
7275 #endif
7276 SQLRETURN ret;
7277
7278 HSTMT_LOCK(stmt);
7279 #if defined(_WIN32) || defined(_WIN64)
7280 if (!((STMT *) stmt)->oemcp[0]) {
7281 ret = drvspecialcolumns(stmt, id, cat, catLen, schema, schemaLen,
7282 table, tableLen, scope, nullable);
7283 goto done2;
7284 }
7285 if (cat) {
7286 c = wmb_to_utf_c((char *) cat, catLen);
7287 if (!c) {
7288 ret = nomem((STMT *) stmt);
7289 goto done;
7290 }
7291 }
7292 if (schema) {
7293 s = wmb_to_utf_c((char *) schema, schemaLen);
7294 if (!s) {
7295 ret = nomem((STMT *) stmt);
7296 goto done;
7297 }
7298 }
7299 if (table) {
7300 t = wmb_to_utf_c((char *) table, tableLen);
7301 if (!t) {
7302 ret = nomem((STMT *) stmt);
7303 goto done;
7304 }
7305 }
7306 ret = drvspecialcolumns(stmt, id, (SQLCHAR *) c, SQL_NTS,
7307 (SQLCHAR *) s, SQL_NTS, (SQLCHAR *) t, SQL_NTS,
7308 scope, nullable);
7309 #else
7310 ret = drvspecialcolumns(stmt, id, cat, catLen, schema, schemaLen,
7311 table, tableLen, scope, nullable);
7312 #endif
7313 #if defined(_WIN32) || defined(_WIN64)
7314 done:
7315 uc_free(t);
7316 uc_free(s);
7317 uc_free(c);
7318 done2:
7319 ;
7320 #endif
7321 HSTMT_UNLOCK(stmt);
7322 return ret;
7323 }
7324 #endif
7325
7326 #ifdef WINTERFACE
7327 /**
7328 * Retrieve information about indexed columns (UNICODE version).
7329 * @param stmt statement handle
7330 * @param id type of information, e.g. best row id
7331 * @param cat catalog name/pattern or NULL
7332 * @param catLen length of catalog name/pattern or SQL_NTS
7333 * @param schema schema name/pattern or NULL
7334 * @param schemaLen length of schema name/pattern or SQL_NTS
7335 * @param table table name/pattern or NULL
7336 * @param tableLen length of table name/pattern or SQL_NTS
7337 * @param scope
7338 * @param nullable
7339 * @result ODBC error code
7340 */
7341
7342 SQLRETURN SQL_API
SQLSpecialColumnsW(SQLHSTMT stmt,SQLUSMALLINT id,SQLWCHAR * cat,SQLSMALLINT catLen,SQLWCHAR * schema,SQLSMALLINT schemaLen,SQLWCHAR * table,SQLSMALLINT tableLen,SQLUSMALLINT scope,SQLUSMALLINT nullable)7343 SQLSpecialColumnsW(SQLHSTMT stmt, SQLUSMALLINT id,
7344 SQLWCHAR *cat, SQLSMALLINT catLen,
7345 SQLWCHAR *schema, SQLSMALLINT schemaLen,
7346 SQLWCHAR *table, SQLSMALLINT tableLen,
7347 SQLUSMALLINT scope, SQLUSMALLINT nullable)
7348 {
7349 char *c = NULL, *s = NULL, *t = NULL;
7350 SQLRETURN ret;
7351
7352 HSTMT_LOCK(stmt);
7353 if (cat) {
7354 c = uc_to_utf_c(cat, catLen);
7355 if (!c) {
7356 ret = nomem((STMT *) stmt);
7357 goto done;
7358 }
7359 }
7360 if (schema) {
7361 s = uc_to_utf_c(schema, schemaLen);
7362 if (!s) {
7363 ret = nomem((STMT *) stmt);
7364 goto done;
7365 }
7366 }
7367 if (table) {
7368 t = uc_to_utf_c(table, tableLen);
7369 if (!t) {
7370 ret = nomem((STMT *) stmt);
7371 goto done;
7372 }
7373 }
7374 ret = drvspecialcolumns(stmt, id, (SQLCHAR *) c, SQL_NTS,
7375 (SQLCHAR *) s, SQL_NTS, (SQLCHAR *) t, SQL_NTS,
7376 scope, nullable);
7377 done:
7378 uc_free(t);
7379 uc_free(s);
7380 uc_free(c);
7381 HSTMT_UNLOCK(stmt);
7382 return ret;
7383 }
7384 #endif
7385
7386 /**
7387 * Columns for result set of SQLForeignKeys().
7388 */
7389
7390 static COL fkeySpec2[] = {
7391 { "SYSTEM", "FOREIGNKEY", "PKTABLE_QUALIFIER", SCOL_VARCHAR, 50 },
7392 { "SYSTEM", "FOREIGNKEY", "PKTABLE_OWNER", SCOL_VARCHAR, 50 },
7393 { "SYSTEM", "FOREIGNKEY", "PKTABLE_NAME", SCOL_VARCHAR, 255 },
7394 { "SYSTEM", "FOREIGNKEY", "PKCOLUMN_NAME", SCOL_VARCHAR, 255 },
7395 { "SYSTEM", "FOREIGNKEY", "FKTABLE_QUALIFIER", SCOL_VARCHAR, 50 },
7396 { "SYSTEM", "FOREIGNKEY", "FKTABLE_OWNER", SCOL_VARCHAR, 50 },
7397 { "SYSTEM", "FOREIGNKEY", "FKTABLE_NAME", SCOL_VARCHAR, 255 },
7398 { "SYSTEM", "FOREIGNKEY", "FKCOLUMN_NAME", SCOL_VARCHAR, 255 },
7399 { "SYSTEM", "FOREIGNKEY", "KEY_SEQ", SQL_SMALLINT, 5 },
7400 { "SYSTEM", "FOREIGNKEY", "UPDATE_RULE", SQL_SMALLINT, 5 },
7401 { "SYSTEM", "FOREIGNKEY", "DELETE_RULE", SQL_SMALLINT, 5 },
7402 { "SYSTEM", "FOREIGNKEY", "FK_NAME", SCOL_VARCHAR, 255 },
7403 { "SYSTEM", "FOREIGNKEY", "PK_NAME", SCOL_VARCHAR, 255 },
7404 { "SYSTEM", "FOREIGNKEY", "DEFERRABILITY", SQL_SMALLINT, 5 }
7405 };
7406
7407 static COL fkeySpec3[] = {
7408 { "SYSTEM", "FOREIGNKEY", "PKTABLE_CAT", SCOL_VARCHAR, 50 },
7409 { "SYSTEM", "FOREIGNKEY", "PKTABLE_SCHEM", SCOL_VARCHAR, 50 },
7410 { "SYSTEM", "FOREIGNKEY", "PKTABLE_NAME", SCOL_VARCHAR, 255 },
7411 { "SYSTEM", "FOREIGNKEY", "PKCOLUMN_NAME", SCOL_VARCHAR, 255 },
7412 { "SYSTEM", "FOREIGNKEY", "FKTABLE_CAT", SCOL_VARCHAR, 50 },
7413 { "SYSTEM", "FOREIGNKEY", "FKTABLE_SCHEM", SCOL_VARCHAR, 50 },
7414 { "SYSTEM", "FOREIGNKEY", "FKTABLE_NAME", SCOL_VARCHAR, 255 },
7415 { "SYSTEM", "FOREIGNKEY", "FKCOLUMN_NAME", SCOL_VARCHAR, 255 },
7416 { "SYSTEM", "FOREIGNKEY", "KEY_SEQ", SQL_SMALLINT, 5 },
7417 { "SYSTEM", "FOREIGNKEY", "UPDATE_RULE", SQL_SMALLINT, 5 },
7418 { "SYSTEM", "FOREIGNKEY", "DELETE_RULE", SQL_SMALLINT, 5 },
7419 { "SYSTEM", "FOREIGNKEY", "FK_NAME", SCOL_VARCHAR, 255 },
7420 { "SYSTEM", "FOREIGNKEY", "PK_NAME", SCOL_VARCHAR, 255 },
7421 { "SYSTEM", "FOREIGNKEY", "DEFERRABILITY", SQL_SMALLINT, 5 }
7422 };
7423
7424 /**
7425 * Internal retrieve information about primary/foreign keys.
7426 * @param stmt statement handle
7427 * @param PKcatalog primary key catalog name/pattern or NULL
7428 * @param PKcatalogLen length of PKcatalog or SQL_NTS
7429 * @param PKschema primary key schema name/pattern or NULL
7430 * @param PKschemaLen length of PKschema or SQL_NTS
7431 * @param PKtable primary key table name/pattern or NULL
7432 * @param PKtableLen length of PKtable or SQL_NTS
7433 * @param FKcatalog foreign key catalog name/pattern or NULL
7434 * @param FKcatalogLen length of FKcatalog or SQL_NTS
7435 * @param FKschema foreign key schema name/pattern or NULL
7436 * @param FKschemaLen length of FKschema or SQL_NTS
7437 * @param FKtable foreign key table name/pattern or NULL
7438 * @param FKtableLen length of FKtable or SQL_NTS
7439 * @result ODBC error code
7440 */
7441
7442 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)7443 drvforeignkeys(SQLHSTMT stmt,
7444 SQLCHAR *PKcatalog, SQLSMALLINT PKcatalogLen,
7445 SQLCHAR *PKschema, SQLSMALLINT PKschemaLen,
7446 SQLCHAR *PKtable, SQLSMALLINT PKtableLen,
7447 SQLCHAR *FKcatalog, SQLSMALLINT FKcatalogLen,
7448 SQLCHAR *FKschema, SQLSMALLINT FKschemaLen,
7449 SQLCHAR *FKtable, SQLSMALLINT FKtableLen)
7450 {
7451 STMT *s;
7452 DBC *d;
7453 SQLRETURN sret;
7454 int i, asize, ret, nrows, ncols, offs, namec, seqc, fromc, toc;
7455 int onu, ond;
7456 PTRDIFF_T size;
7457 char **rowp, *errp = NULL, *sql, pname[512], fname[512];
7458
7459 sret = mkresultset(stmt, fkeySpec2, array_size(fkeySpec2),
7460 fkeySpec3, array_size(fkeySpec3), &asize);
7461 if (sret != SQL_SUCCESS) {
7462 return sret;
7463 }
7464 s = (STMT *) stmt;
7465 sret = starttran(s);
7466 if (sret != SQL_SUCCESS) {
7467 return sret;
7468 }
7469 d = (DBC *) s->dbc;
7470 if ((!PKtable || PKtable[0] == '\0' || PKtable[0] == '%') &&
7471 (!FKtable || FKtable[0] == '\0' || FKtable[0] == '%')) {
7472 setstat(s, -1, "need table name", (*s->ov3) ? "HY000" : "S1000");
7473 return SQL_ERROR;
7474 }
7475 size = 0;
7476 if (PKtable) {
7477 if (PKtableLen == SQL_NTS) {
7478 size = sizeof (pname) - 1;
7479 } else {
7480 size = min(sizeof (pname) - 1, PKtableLen);
7481 }
7482 strncpy(pname, (char *) PKtable, size);
7483 }
7484 pname[size] = '\0';
7485 size = 0;
7486 if (FKtable) {
7487
7488 if (FKtableLen == SQL_NTS) {
7489 size = sizeof (fname) - 1;
7490 } else {
7491 size = min(sizeof (fname) - 1, FKtableLen);
7492 }
7493 strncpy(fname, (char *) FKtable, size);
7494 }
7495 fname[size] = '\0';
7496 if (fname[0] != '\0') {
7497 int plen;
7498
7499 ret = SQLITE_ERROR;
7500 sql = sqlite3_mprintf("PRAGMA foreign_key_list(%Q)", fname);
7501 if (sql) {
7502 dbtraceapi(d, "sqlite3_get_table", sql);
7503 ret = sqlite3_get_table(d->sqlite, sql, &rowp,
7504 &nrows, &ncols, &errp);
7505 sqlite3_free(sql);
7506 }
7507 if (ret != SQLITE_OK) {
7508 setstat(s, ret, "%s (%d)", (*s->ov3) ? "HY000" : "S1000",
7509 errp ? errp : "unknown error", ret);
7510 if (errp) {
7511 sqlite3_free(errp);
7512 errp = NULL;
7513 }
7514 return SQL_ERROR;
7515 }
7516 if (errp) {
7517 sqlite3_free(errp);
7518 errp = NULL;
7519 }
7520 if (ncols * nrows <= 0) {
7521 nodata:
7522 sqlite3_free_table(rowp);
7523 return SQL_SUCCESS;
7524 }
7525 size = 0;
7526 namec = findcol(rowp, ncols, "table");
7527 seqc = findcol(rowp, ncols, "seq");
7528 fromc = findcol(rowp, ncols, "from");
7529 toc = findcol(rowp, ncols, "to");
7530 onu = findcol(rowp, ncols, "on_update");
7531 ond = findcol(rowp, ncols, "on_delete");
7532 if (namec < 0 || seqc < 0 || fromc < 0 || toc < 0) {
7533 goto nodata;
7534 }
7535 plen = strlen(pname);
7536 for (i = 1; i <= nrows; i++) {
7537 char *ptab = unquote(rowp[i * ncols + namec]);
7538
7539 if (plen && ptab) {
7540 int len = strlen(ptab);
7541
7542 if (plen != len || strncasecmp(pname, ptab, plen) != 0) {
7543 continue;
7544 }
7545 }
7546 size++;
7547 }
7548 if (size == 0) {
7549 goto nodata;
7550 }
7551 s->nrows = size;
7552 size = (size + 1) * asize;
7553 s->rows = xmalloc((size + 1) * sizeof (char *));
7554 if (!s->rows) {
7555 s->nrows = 0;
7556 return nomem(s);
7557 }
7558 s->rows[0] = (char *) size;
7559 s->rows += 1;
7560 memset(s->rows, 0, sizeof (char *) * size);
7561 s->rowfree = freerows;
7562 offs = 0;
7563 for (i = 1; i <= nrows; i++) {
7564 int pos = 0, roffs = (offs + 1) * s->ncols;
7565 char *ptab = rowp[i * ncols + namec];
7566 char buf[32];
7567
7568 if (plen && ptab) {
7569 int len = strlen(ptab);
7570
7571 if (plen != len || strncasecmp(pname, ptab, plen) != 0) {
7572 continue;
7573 }
7574 }
7575 #if defined(_WIN32) || defined(_WIN64)
7576 s->rows[roffs + 0] = xstrdup(d->xcelqrx ? "main" : "");
7577 s->rows[roffs + 1] = xstrdup("");
7578 #else
7579 s->rows[roffs + 0] = xstrdup("");
7580 s->rows[roffs + 1] = xstrdup("");
7581 #endif
7582 s->rows[roffs + 2] = xstrdup(ptab);
7583 s->rows[roffs + 3] = xstrdup(rowp[i * ncols + toc]);
7584 s->rows[roffs + 4] = xstrdup("");
7585 s->rows[roffs + 5] = xstrdup("");
7586 s->rows[roffs + 6] = xstrdup(fname);
7587 s->rows[roffs + 7] = xstrdup(rowp[i * ncols + fromc]);
7588 sscanf(rowp[i * ncols + seqc], "%d", &pos);
7589 sprintf(buf, "%d", pos + 1);
7590 s->rows[roffs + 8] = xstrdup(buf);
7591 if (onu < 0) {
7592 s->rows[roffs + 9] = xstrdup(stringify(SQL_NO_ACTION));
7593 } else {
7594 if (strcmp(rowp[i * ncols + onu], "SET NULL") == 0) {
7595 s->rows[roffs + 9] = xstrdup(stringify(SQL_SET_NULL));
7596 } else if (strcmp(rowp[i * ncols + onu], "SET DEFAULT") == 0) {
7597 s->rows[roffs + 9] = xstrdup(stringify(SQL_SET_DEFAULT));
7598 } else if (strcmp(rowp[i * ncols + onu], "CASCADE") == 0) {
7599 s->rows[roffs + 9] = xstrdup(stringify(SQL_CASCADE));
7600 } else if (strcmp(rowp[i * ncols + onu], "RESTRICT") == 0) {
7601 s->rows[roffs + 9] = xstrdup(stringify(SQL_RESTRICT));
7602 } else {
7603 s->rows[roffs + 9] = xstrdup(stringify(SQL_NO_ACTION));
7604 }
7605 }
7606 if (ond < 0) {
7607 s->rows[roffs + 10] = xstrdup(stringify(SQL_NO_ACTION));
7608 } else {
7609 if (strcmp(rowp[i * ncols + ond], "SET NULL") == 0) {
7610 s->rows[roffs + 10] = xstrdup(stringify(SQL_SET_NULL));
7611 } else if (strcmp(rowp[i * ncols + ond], "SET DEFAULT") == 0) {
7612 s->rows[roffs + 10] = xstrdup(stringify(SQL_SET_DEFAULT));
7613 } else if (strcmp(rowp[i * ncols + ond], "CASCADE") == 0) {
7614 s->rows[roffs + 10] = xstrdup(stringify(SQL_CASCADE));
7615 } else if (strcmp(rowp[i * ncols + ond], "RESTRICT") == 0) {
7616 s->rows[roffs + 10] = xstrdup(stringify(SQL_RESTRICT));
7617 } else {
7618 s->rows[roffs + 10] = xstrdup(stringify(SQL_NO_ACTION));
7619 }
7620 }
7621 s->rows[roffs + 11] = NULL;
7622 s->rows[roffs + 12] = NULL;
7623 s->rows[roffs + 13] = xstrdup(stringify(SQL_NOT_DEFERRABLE));
7624 offs++;
7625 }
7626 sqlite3_free_table(rowp);
7627 } else {
7628 int nnrows, nncols, plen = strlen(pname);
7629 char **rowpp;
7630
7631 sql = "select name from sqlite_master where type='table'";
7632 dbtraceapi(d, "sqlite3_get_table", sql);
7633 ret = sqlite3_get_table(d->sqlite, sql, &rowp, &nrows, &ncols, &errp);
7634 if (ret != SQLITE_OK) {
7635 setstat(s, ret, "%s (%d)", (*s->ov3) ? "HY000" : "S1000",
7636 errp ? errp : "unknown error", ret);
7637 if (errp) {
7638 sqlite3_free(errp);
7639 errp = NULL;
7640 }
7641 return SQL_ERROR;
7642 }
7643 if (errp) {
7644 sqlite3_free(errp);
7645 errp = NULL;
7646 }
7647 if (ncols * nrows <= 0) {
7648 goto nodata;
7649 }
7650 size = 0;
7651 for (i = 1; i <= nrows; i++) {
7652 int k;
7653
7654 if (!rowp[i]) {
7655 continue;
7656 }
7657 rowpp = NULL;
7658 ret = SQLITE_ERROR;
7659 sql = sqlite3_mprintf("PRAGMA foreign_key_list(%Q)", rowp[i]);
7660 if (sql) {
7661 dbtraceapi(d, "sqlite3_get_table", sql);
7662 ret = sqlite3_get_table(d->sqlite, sql, &rowpp,
7663 &nnrows, &nncols, NULL);
7664 sqlite3_free(sql);
7665 }
7666 if (ret != SQLITE_OK || nncols * nnrows <= 0) {
7667 sqlite3_free_table(rowpp);
7668 continue;
7669 }
7670 namec = findcol(rowpp, nncols, "table");
7671 seqc = findcol(rowpp, nncols, "seq");
7672 fromc = findcol(rowpp, nncols, "from");
7673 toc = findcol(rowpp, nncols, "to");
7674 if (namec < 0 || seqc < 0 || fromc < 0 || toc < 0) {
7675 sqlite3_free_table(rowpp);
7676 continue;
7677 }
7678 for (k = 1; k <= nnrows; k++) {
7679 char *ptab = unquote(rowpp[k * nncols + namec]);
7680
7681 if (plen && ptab) {
7682 int len = strlen(ptab);
7683
7684 if (len != plen || strncasecmp(pname, ptab, plen) != 0) {
7685 continue;
7686 }
7687 }
7688 size++;
7689 }
7690 sqlite3_free_table(rowpp);
7691 }
7692 if (size == 0) {
7693 goto nodata;
7694 }
7695 s->nrows = size;
7696 size = (size + 1) * asize;
7697 s->rows = xmalloc((size + 1) * sizeof (char *));
7698 if (!s->rows) {
7699 s->nrows = 0;
7700 return nomem(s);
7701 }
7702 s->rows[0] = (char *) size;
7703 s->rows += 1;
7704 memset(s->rows, 0, sizeof (char *) * size);
7705 s->rowfree = freerows;
7706 offs = 0;
7707 for (i = 1; i <= nrows; i++) {
7708 int k;
7709
7710 if (!rowp[i]) {
7711 continue;
7712 }
7713 rowpp = NULL;
7714 ret = SQLITE_ERROR;
7715 sql = sqlite3_mprintf("PRAGMA foreign_key_list(%Q)", rowp[i]);
7716 if (sql) {
7717 dbtraceapi(d, "sqlite3_get_table", sql);
7718 ret = sqlite3_get_table(d->sqlite, sql, &rowpp,
7719 &nnrows, &nncols, NULL);
7720 sqlite3_free(sql);
7721 }
7722 if (ret != SQLITE_OK || nncols * nnrows <= 0) {
7723 sqlite3_free_table(rowpp);
7724 continue;
7725 }
7726 namec = findcol(rowpp, nncols, "table");
7727 seqc = findcol(rowpp, nncols, "seq");
7728 fromc = findcol(rowpp, nncols, "from");
7729 toc = findcol(rowpp, nncols, "to");
7730 onu = findcol(rowpp, nncols, "on_update");
7731 ond = findcol(rowpp, nncols, "on_delete");
7732 if (namec < 0 || seqc < 0 || fromc < 0 || toc < 0) {
7733 sqlite3_free_table(rowpp);
7734 continue;
7735 }
7736 for (k = 1; k <= nnrows; k++) {
7737 int pos = 0, roffs = (offs + 1) * s->ncols;
7738 char *ptab = unquote(rowpp[k * nncols + namec]);
7739 char buf[32];
7740
7741 if (plen && ptab) {
7742 int len = strlen(ptab);
7743
7744 if (len != plen || strncasecmp(pname, ptab, plen) != 0) {
7745 continue;
7746 }
7747 }
7748 #if defined(_WIN32) || defined(_WIN64)
7749 s->rows[roffs + 0] = xstrdup(d->xcelqrx ? "main" : "");
7750 s->rows[roffs + 1] = xstrdup("");
7751 #else
7752 s->rows[roffs + 0] = xstrdup("");
7753 s->rows[roffs + 1] = xstrdup("");
7754 #endif
7755 s->rows[roffs + 2] = xstrdup(ptab);
7756 s->rows[roffs + 3] = xstrdup(rowpp[k * nncols + toc]);
7757 s->rows[roffs + 4] = xstrdup("");
7758 s->rows[roffs + 5] = xstrdup("");
7759 s->rows[roffs + 6] = xstrdup(rowp[i]);
7760 s->rows[roffs + 7] = xstrdup(rowpp[k * nncols + fromc]);
7761 sscanf(rowpp[k * nncols + seqc], "%d", &pos);
7762 sprintf(buf, "%d", pos + 1);
7763 s->rows[roffs + 8] = xstrdup(buf);
7764 if (onu < 0) {
7765 s->rows[roffs + 9] = xstrdup(stringify(SQL_NO_ACTION));
7766 } else {
7767 if (strcmp(rowpp[k * nncols + onu], "SET NULL") == 0) {
7768 s->rows[roffs + 9] = xstrdup(stringify(SQL_SET_NULL));
7769 } else if (strcmp(rowpp[k * nncols + onu], "SET DEFAULT")
7770 == 0) {
7771 s->rows[roffs + 9] =
7772 xstrdup(stringify(SQL_SET_DEFAULT));
7773 } else if (strcmp(rowpp[k * nncols + onu], "CASCADE")
7774 == 0) {
7775 s->rows[roffs + 9] = xstrdup(stringify(SQL_CASCADE));
7776 } else if (strcmp(rowpp[k * nncols + onu], "RESTRICT")
7777 == 0) {
7778 s->rows[roffs + 9] = xstrdup(stringify(SQL_RESTRICT));
7779 } else {
7780 s->rows[roffs + 9] =
7781 xstrdup(stringify(SQL_NO_ACTION));
7782 }
7783 }
7784 if (ond < 0) {
7785 s->rows[roffs + 10] = xstrdup(stringify(SQL_NO_ACTION));
7786 } else {
7787 if (strcmp(rowpp[k * nncols + ond], "SET NULL") == 0) {
7788 s->rows[roffs + 10] = xstrdup(stringify(SQL_SET_NULL));
7789 } else if (strcmp(rowpp[k * nncols + ond], "SET DEFAULT")
7790 == 0) {
7791 s->rows[roffs + 10] =
7792 xstrdup(stringify(SQL_SET_DEFAULT));
7793 } else if (strcmp(rowpp[k * nncols + ond], "CASCADE")
7794 == 0) {
7795 s->rows[roffs + 10] = xstrdup(stringify(SQL_CASCADE));
7796 } else if (strcmp(rowpp[k * nncols + ond], "RESTRICT")
7797 == 0) {
7798 s->rows[roffs + 10] = xstrdup(stringify(SQL_RESTRICT));
7799 } else {
7800 s->rows[roffs + 10] =
7801 xstrdup(stringify(SQL_NO_ACTION));
7802 }
7803 }
7804 s->rows[roffs + 11] = NULL;
7805 s->rows[roffs + 12] = NULL;
7806 s->rows[roffs + 13] = xstrdup(stringify(SQL_NOT_DEFERRABLE));
7807 offs++;
7808 }
7809 sqlite3_free_table(rowpp);
7810 }
7811 sqlite3_free_table(rowp);
7812 }
7813 return SQL_SUCCESS;
7814 }
7815
7816 #ifndef WINTERFACE
7817 /**
7818 * Retrieve information about primary/foreign keys.
7819 * @param stmt statement handle
7820 * @param PKcatalog primary key catalog name/pattern or NULL
7821 * @param PKcatalogLen length of PKcatalog or SQL_NTS
7822 * @param PKschema primary key schema name/pattern or NULL
7823 * @param PKschemaLen length of PKschema or SQL_NTS
7824 * @param PKtable primary key table name/pattern or NULL
7825 * @param PKtableLen length of PKtable or SQL_NTS
7826 * @param FKcatalog foreign key catalog name/pattern or NULL
7827 * @param FKcatalogLen length of FKcatalog or SQL_NTS
7828 * @param FKschema foreign key schema name/pattern or NULL
7829 * @param FKschemaLen length of FKschema or SQL_NTS
7830 * @param FKtable foreign key table name/pattern or NULL
7831 * @param FKtableLen length of FKtable or SQL_NTS
7832 * @result ODBC error code
7833 */
7834
7835 SQLRETURN SQL_API
SQLForeignKeys(SQLHSTMT stmt,SQLCHAR * PKcatalog,SQLSMALLINT PKcatalogLen,SQLCHAR * PKschema,SQLSMALLINT PKschemaLen,SQLCHAR * PKtable,SQLSMALLINT PKtableLen,SQLCHAR * FKcatalog,SQLSMALLINT FKcatalogLen,SQLCHAR * FKschema,SQLSMALLINT FKschemaLen,SQLCHAR * FKtable,SQLSMALLINT FKtableLen)7836 SQLForeignKeys(SQLHSTMT stmt,
7837 SQLCHAR *PKcatalog, SQLSMALLINT PKcatalogLen,
7838 SQLCHAR *PKschema, SQLSMALLINT PKschemaLen,
7839 SQLCHAR *PKtable, SQLSMALLINT PKtableLen,
7840 SQLCHAR *FKcatalog, SQLSMALLINT FKcatalogLen,
7841 SQLCHAR *FKschema, SQLSMALLINT FKschemaLen,
7842 SQLCHAR *FKtable, SQLSMALLINT FKtableLen)
7843 {
7844 #if defined(_WIN32) || defined(_WIN64)
7845 char *pc = NULL, *ps = NULL, *pt = NULL;
7846 char *fc = NULL, *fs = NULL, *ft = NULL;
7847 #endif
7848 SQLRETURN ret;
7849
7850 HSTMT_LOCK(stmt);
7851 #if defined(_WIN32) || defined(_WIN64)
7852 if (!((STMT *) stmt)->oemcp[0]) {
7853 ret = drvforeignkeys(stmt,
7854 PKcatalog, PKcatalogLen,
7855 PKschema, PKschemaLen, PKtable, PKtableLen,
7856 FKcatalog, FKcatalogLen,
7857 FKschema, FKschemaLen,
7858 FKtable, FKtableLen);
7859 goto done2;
7860 }
7861 if (PKcatalog) {
7862 pc = wmb_to_utf_c((char *) PKcatalog, PKcatalogLen);
7863 if (!pc) {
7864 ret = nomem((STMT *) stmt);
7865 goto done;
7866 }
7867 }
7868 if (PKschema) {
7869 ps = wmb_to_utf_c((char *) PKschema, PKschemaLen);
7870 if (!ps) {
7871 ret = nomem((STMT *) stmt);
7872 goto done;
7873 }
7874 }
7875 if (PKtable) {
7876 pt = wmb_to_utf_c((char *) PKtable, PKtableLen);
7877 if (!pt) {
7878 ret = nomem((STMT *) stmt);
7879 goto done;
7880 }
7881 }
7882 if (FKcatalog) {
7883 fc = wmb_to_utf_c((char *) FKcatalog, FKcatalogLen);
7884 if (!fc) {
7885 ret = nomem((STMT *) stmt);
7886 goto done;
7887 }
7888 }
7889 if (FKschema) {
7890 fs = wmb_to_utf_c((char *) FKschema, FKschemaLen);
7891 if (!fs) {
7892 ret = nomem((STMT *) stmt);
7893 goto done;
7894 }
7895 }
7896 if (FKtable) {
7897 ft = wmb_to_utf_c((char *) FKtable, FKtableLen);
7898 if (!ft) {
7899 ret = nomem((STMT *) stmt);
7900 goto done;
7901 }
7902 }
7903 ret = drvforeignkeys(stmt, (SQLCHAR *) pc, SQL_NTS,
7904 (SQLCHAR *) ps, SQL_NTS, (SQLCHAR *) pt, SQL_NTS,
7905 (SQLCHAR *) fc, SQL_NTS, (SQLCHAR *) fs, SQL_NTS,
7906 (SQLCHAR *) ft, SQL_NTS);
7907 #else
7908 ret = drvforeignkeys(stmt,
7909 PKcatalog, PKcatalogLen,
7910 PKschema, PKschemaLen, PKtable, PKtableLen,
7911 FKcatalog, FKcatalogLen,
7912 FKschema, FKschemaLen,
7913 FKtable, FKtableLen);
7914 #endif
7915 #if defined(_WIN32) || defined(_WIN64)
7916 done:
7917 uc_free(ft);
7918 uc_free(fs);
7919 uc_free(fc);
7920 uc_free(pt);
7921 uc_free(ps);
7922 uc_free(pc);
7923 done2:
7924 ;
7925 #endif
7926 HSTMT_UNLOCK(stmt);
7927 return ret;
7928 }
7929 #endif
7930
7931 #ifdef WINTERFACE
7932 /**
7933 * Retrieve information about primary/foreign keys (UNICODE version).
7934 * @param stmt statement handle
7935 * @param PKcatalog primary key catalog name/pattern or NULL
7936 * @param PKcatalogLen length of PKcatalog or SQL_NTS
7937 * @param PKschema primary key schema name/pattern or NULL
7938 * @param PKschemaLen length of PKschema or SQL_NTS
7939 * @param PKtable primary key table name/pattern or NULL
7940 * @param PKtableLen length of PKtable or SQL_NTS
7941 * @param FKcatalog foreign key catalog name/pattern or NULL
7942 * @param FKcatalogLen length of FKcatalog or SQL_NTS
7943 * @param FKschema foreign key schema name/pattern or NULL
7944 * @param FKschemaLen length of FKschema or SQL_NTS
7945 * @param FKtable foreign key table name/pattern or NULL
7946 * @param FKtableLen length of FKtable or SQL_NTS
7947 * @result ODBC error code
7948 */
7949
7950 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)7951 SQLForeignKeysW(SQLHSTMT stmt,
7952 SQLWCHAR *PKcatalog, SQLSMALLINT PKcatalogLen,
7953 SQLWCHAR *PKschema, SQLSMALLINT PKschemaLen,
7954 SQLWCHAR *PKtable, SQLSMALLINT PKtableLen,
7955 SQLWCHAR *FKcatalog, SQLSMALLINT FKcatalogLen,
7956 SQLWCHAR *FKschema, SQLSMALLINT FKschemaLen,
7957 SQLWCHAR *FKtable, SQLSMALLINT FKtableLen)
7958 {
7959 char *pc = NULL, *ps = NULL, *pt = NULL;
7960 char *fc = NULL, *fs = NULL, *ft = NULL;
7961 SQLRETURN ret;
7962
7963 HSTMT_LOCK(stmt);
7964 if (PKcatalog) {
7965 pc = uc_to_utf_c(PKcatalog, PKcatalogLen);
7966 if (!pc) {
7967 ret = nomem((STMT *) stmt);
7968 goto done;
7969 }
7970 }
7971 if (PKschema) {
7972 ps = uc_to_utf_c(PKschema, PKschemaLen);
7973 if (!ps) {
7974 ret = nomem((STMT *) stmt);
7975 goto done;
7976 }
7977 }
7978 if (PKtable) {
7979 pt = uc_to_utf_c(PKtable, PKtableLen);
7980 if (!pt) {
7981 ret = nomem((STMT *) stmt);
7982 goto done;
7983 }
7984 }
7985 if (FKcatalog) {
7986 fc = uc_to_utf_c(FKcatalog, FKcatalogLen);
7987 if (!fc) {
7988 ret = nomem((STMT *) stmt);
7989 goto done;
7990 }
7991 }
7992 if (FKschema) {
7993 fs = uc_to_utf_c(FKschema, FKschemaLen);
7994 if (!fs) {
7995 ret = nomem((STMT *) stmt);
7996 goto done;
7997 }
7998 }
7999 if (FKtable) {
8000 ft = uc_to_utf_c(FKtable, FKtableLen);
8001 if (!ft) {
8002 ret = nomem((STMT *) stmt);
8003 goto done;
8004 }
8005 }
8006 ret = drvforeignkeys(stmt, (SQLCHAR *) pc, SQL_NTS,
8007 (SQLCHAR *) ps, SQL_NTS, (SQLCHAR *) pt, SQL_NTS,
8008 (SQLCHAR *) fc, SQL_NTS, (SQLCHAR *) fs, SQL_NTS,
8009 (SQLCHAR *) ft, SQL_NTS);
8010 done:
8011 uc_free(ft);
8012 uc_free(fs);
8013 uc_free(fc);
8014 uc_free(pt);
8015 uc_free(ps);
8016 uc_free(pc);
8017 HSTMT_UNLOCK(stmt);
8018 return ret;
8019 }
8020 #endif
8021
8022 /**
8023 * Start transaction when autocommit off
8024 * @param s statement pointer
8025 * @result ODBC error code
8026 */
8027
8028 static SQLRETURN
starttran(STMT * s)8029 starttran(STMT *s)
8030 {
8031 int ret = SQL_SUCCESS, rc, busy_count = 0;
8032 char *errp = NULL;
8033 DBC *d = (DBC *) s->dbc;
8034
8035 if (!d->autocommit && !d->intrans && !d->trans_disable) {
8036 begin_again:
8037 rc = sqlite3_exec(d->sqlite, "BEGIN TRANSACTION", NULL, NULL, &errp);
8038 if (rc == SQLITE_BUSY) {
8039 if (busy_handler((void *) d, ++busy_count)) {
8040 if (errp) {
8041 sqlite3_free(errp);
8042 errp = NULL;
8043 }
8044 goto begin_again;
8045 }
8046 }
8047 dbtracerc(d, rc, errp);
8048 if (rc != SQLITE_OK) {
8049 setstat(s, rc, "%s (%d)", (*s->ov3) ? "HY000" : "S1000",
8050 errp ? errp : "unknown error", rc);
8051 ret = SQL_ERROR;
8052 } else {
8053 d->intrans = 1;
8054 }
8055 if (errp) {
8056 sqlite3_free(errp);
8057 errp = NULL;
8058 }
8059 }
8060 return ret;
8061 }
8062
8063 /**
8064 * Internal commit or rollback transaction.
8065 * @param d database connection pointer
8066 * @param comptype type of transaction's end, SQL_COMMIT or SQL_ROLLBACK
8067 * @param force force action regardless of DBC's autocommit state
8068 * @result ODBC error code
8069 */
8070
8071 static SQLRETURN
endtran(DBC * d,SQLSMALLINT comptype,int force)8072 endtran(DBC *d, SQLSMALLINT comptype, int force)
8073 {
8074 int ret, busy_count = 0;
8075 char *sql, *errp = NULL;
8076
8077 if (!d->sqlite) {
8078 setstatd(d, -1, "not connected", (*d->ov3) ? "HY000" : "S1000");
8079 return SQL_ERROR;
8080 }
8081 if ((!force && d->autocommit) || !d->intrans) {
8082 return SQL_SUCCESS;
8083 }
8084 switch (comptype) {
8085 case SQL_COMMIT:
8086 sql = "COMMIT TRANSACTION";
8087 goto doit;
8088 case SQL_ROLLBACK:
8089 sql = "ROLLBACK TRANSACTION";
8090 doit:
8091 ret = sqlite3_exec(d->sqlite, sql, NULL, NULL, &errp);
8092 dbtracerc(d, ret, errp);
8093 if (ret == SQLITE_BUSY && busy_count < 10) {
8094 if (busy_handler((void *) d, ++busy_count)) {
8095 if (errp) {
8096 sqlite3_free(errp);
8097 errp = NULL;
8098 }
8099 goto doit;
8100 }
8101 }
8102 if (ret != SQLITE_OK) {
8103 setstatd(d, ret, "%s", (*d->ov3) ? "HY000" : "S1000",
8104 errp ? errp : "transaction failed");
8105 if (errp) {
8106 sqlite3_free(errp);
8107 errp = NULL;
8108 }
8109 return SQL_ERROR;
8110 }
8111 if (errp) {
8112 sqlite3_free(errp);
8113 errp = NULL;
8114 }
8115 d->intrans = 0;
8116 return SQL_SUCCESS;
8117 }
8118 setstatd(d, -1, "invalid completion type", (*d->ov3) ? "HY000" : "S1000");
8119 return SQL_ERROR;
8120 }
8121
8122 /**
8123 * Internal commit or rollback transaction.
8124 * @param type type of handle
8125 * @param handle HDBC, HENV, or HSTMT handle
8126 * @param comptype SQL_COMMIT or SQL_ROLLBACK
8127 * @result ODBC error code
8128 */
8129
8130 static SQLRETURN
drvendtran(SQLSMALLINT type,SQLHANDLE handle,SQLSMALLINT comptype)8131 drvendtran(SQLSMALLINT type, SQLHANDLE handle, SQLSMALLINT comptype)
8132 {
8133 DBC *dbc = NULL;
8134 int fail = 0;
8135 SQLRETURN ret;
8136 #if defined(_WIN32) || defined(_WIN64)
8137 ENV *env;
8138 #endif
8139
8140 switch (type) {
8141 case SQL_HANDLE_DBC:
8142 HDBC_LOCK((SQLHDBC) handle);
8143 if (handle == SQL_NULL_HDBC) {
8144 return SQL_INVALID_HANDLE;
8145 }
8146 dbc = (DBC *) handle;
8147 ret = endtran(dbc, comptype, 0);
8148 HDBC_UNLOCK((SQLHDBC) handle);
8149 return ret;
8150 case SQL_HANDLE_ENV:
8151 if (handle == SQL_NULL_HENV) {
8152 return SQL_INVALID_HANDLE;
8153 }
8154 #if defined(_WIN32) || defined(_WIN64)
8155 env = (ENV *) handle;
8156 if (env->magic != ENV_MAGIC) {
8157 return SQL_INVALID_HANDLE;
8158 }
8159 EnterCriticalSection(&env->cs);
8160 #endif
8161 dbc = ((ENV *) handle)->dbcs;
8162 while (dbc) {
8163 HDBC_LOCK((SQLHDBC) dbc);
8164 ret = endtran(dbc, comptype, 0);
8165 HDBC_UNLOCK((SQLHDBC) dbc);
8166 if (ret != SQL_SUCCESS) {
8167 fail++;
8168 }
8169 dbc = dbc->next;
8170 }
8171 #if defined(_WIN32) || defined(_WIN64)
8172 LeaveCriticalSection(&env->cs);
8173 #endif
8174 return fail ? SQL_ERROR : SQL_SUCCESS;
8175 }
8176 return SQL_INVALID_HANDLE;
8177 }
8178
8179 /**
8180 * Commit or rollback transaction.
8181 * @param type type of handle
8182 * @param handle HDBC, HENV, or HSTMT handle
8183 * @param comptype SQL_COMMIT or SQL_ROLLBACK
8184 * @result ODBC error code
8185 */
8186
8187 SQLRETURN SQL_API
SQLEndTran(SQLSMALLINT type,SQLHANDLE handle,SQLSMALLINT comptype)8188 SQLEndTran(SQLSMALLINT type, SQLHANDLE handle, SQLSMALLINT comptype)
8189 {
8190 return drvendtran(type, handle, comptype);
8191 }
8192
8193 /**
8194 * Commit or rollback transaction.
8195 * @param env environment handle or NULL
8196 * @param dbc database connection handle or NULL
8197 * @param type SQL_COMMIT or SQL_ROLLBACK
8198 * @result ODBC error code
8199 */
8200
8201 SQLRETURN SQL_API
SQLTransact(SQLHENV env,SQLHDBC dbc,SQLUSMALLINT type)8202 SQLTransact(SQLHENV env, SQLHDBC dbc, SQLUSMALLINT type)
8203 {
8204 if (dbc != SQL_NULL_HDBC) {
8205 return drvendtran(SQL_HANDLE_DBC, (SQLHANDLE) dbc, type);
8206 }
8207 return drvendtran(SQL_HANDLE_ENV, (SQLHANDLE) env, type);
8208 }
8209
8210 /**
8211 * Function not implemented.
8212 */
8213
8214 SQLRETURN SQL_API
SQLCopyDesc(SQLHDESC source,SQLHDESC target)8215 SQLCopyDesc(SQLHDESC source, SQLHDESC target)
8216 {
8217 return SQL_ERROR;
8218 }
8219
8220 #ifndef WINTERFACE
8221 /**
8222 * Translate SQL string.
8223 * @param stmt statement handle
8224 * @param sqlin input string
8225 * @param sqlinLen length of input string
8226 * @param sql output string
8227 * @param sqlMax max space in output string
8228 * @param sqlLen value return for length of output string
8229 * @result ODBC error code
8230 */
8231
8232 SQLRETURN SQL_API
SQLNativeSql(SQLHSTMT stmt,SQLCHAR * sqlin,SQLINTEGER sqlinLen,SQLCHAR * sql,SQLINTEGER sqlMax,SQLINTEGER * sqlLen)8233 SQLNativeSql(SQLHSTMT stmt, SQLCHAR *sqlin, SQLINTEGER sqlinLen,
8234 SQLCHAR *sql, SQLINTEGER sqlMax, SQLINTEGER *sqlLen)
8235 {
8236 int outLen = 0;
8237 SQLRETURN ret = SQL_SUCCESS;
8238
8239 HSTMT_LOCK(stmt);
8240 if (sqlinLen == SQL_NTS) {
8241 sqlinLen = strlen((char *) sqlin);
8242 }
8243 if (sql) {
8244 if (sqlMax > 0) {
8245 strncpy((char *) sql, (char *) sqlin, sqlMax - 1);
8246 sqlin[sqlMax - 1] = '\0';
8247 outLen = min(sqlMax - 1, sqlinLen);
8248 }
8249 } else {
8250 outLen = sqlinLen;
8251 }
8252 if (sqlLen) {
8253 *sqlLen = outLen;
8254 }
8255 if (sql && outLen < sqlinLen) {
8256 setstat((STMT *) stmt, -1, "data right truncated", "01004");
8257 ret = SQL_SUCCESS_WITH_INFO;
8258 }
8259 HSTMT_UNLOCK(stmt);
8260 return ret;
8261 }
8262 #endif
8263
8264 #ifdef WINTERFACE
8265 /**
8266 * Translate SQL string (UNICODE version).
8267 * @param stmt statement handle
8268 * @param sqlin input string
8269 * @param sqlinLen length of input string
8270 * @param sql output string
8271 * @param sqlMax max space in output string
8272 * @param sqlLen value return for length of output string
8273 * @result ODBC error code
8274 */
8275
8276 SQLRETURN SQL_API
SQLNativeSqlW(SQLHSTMT stmt,SQLWCHAR * sqlin,SQLINTEGER sqlinLen,SQLWCHAR * sql,SQLINTEGER sqlMax,SQLINTEGER * sqlLen)8277 SQLNativeSqlW(SQLHSTMT stmt, SQLWCHAR *sqlin, SQLINTEGER sqlinLen,
8278 SQLWCHAR *sql, SQLINTEGER sqlMax, SQLINTEGER *sqlLen)
8279 {
8280 int outLen = 0;
8281 SQLRETURN ret = SQL_SUCCESS;
8282
8283 HSTMT_LOCK(stmt);
8284 if (sqlinLen == SQL_NTS) {
8285 sqlinLen = uc_strlen(sqlin);
8286 }
8287 if (sql) {
8288 if (sqlMax > 0) {
8289 uc_strncpy(sql, sqlin, sqlMax - 1);
8290 sqlin[sqlMax - 1] = 0;
8291 outLen = min(sqlMax - 1, sqlinLen);
8292 }
8293 } else {
8294 outLen = sqlinLen;
8295 }
8296 if (sqlLen) {
8297 *sqlLen = outLen;
8298 }
8299 if (sql && outLen < sqlinLen) {
8300 setstat((STMT *) stmt, -1, "data right truncated", "01004");
8301 ret = SQL_SUCCESS_WITH_INFO;
8302 }
8303 HSTMT_UNLOCK(stmt);
8304 return ret;
8305 }
8306 #endif
8307
8308 /**
8309 * Columns for result set of SQLProcedures().
8310 */
8311
8312 static COL procSpec2[] = {
8313 { "SYSTEM", "PROCEDURE", "PROCEDURE_QUALIFIER", SCOL_VARCHAR, 50 },
8314 { "SYSTEM", "PROCEDURE", "PROCEDURE_OWNER", SCOL_VARCHAR, 50 },
8315 { "SYSTEM", "PROCEDURE", "PROCEDURE_NAME", SCOL_VARCHAR, 255 },
8316 { "SYSTEM", "PROCEDURE", "NUM_INPUT_PARAMS", SQL_SMALLINT, 5 },
8317 { "SYSTEM", "PROCEDURE", "NUM_OUTPUT_PARAMS", SQL_SMALLINT, 5 },
8318 { "SYSTEM", "PROCEDURE", "NUM_RESULT_SETS", SQL_SMALLINT, 5 },
8319 { "SYSTEM", "PROCEDURE", "REMARKS", SCOL_VARCHAR, 255 },
8320 { "SYSTEM", "PROCEDURE", "PROCEDURE_TYPE", SQL_SMALLINT, 5 }
8321 };
8322
8323 static COL procSpec3[] = {
8324 { "SYSTEM", "PROCEDURE", "PROCEDURE_CAT", SCOL_VARCHAR, 50 },
8325 { "SYSTEM", "PROCEDURE", "PROCEDURE_SCHEM", SCOL_VARCHAR, 50 },
8326 { "SYSTEM", "PROCEDURE", "PROCEDURE_NAME", SCOL_VARCHAR, 255 },
8327 { "SYSTEM", "PROCEDURE", "NUM_INPUT_PARAMS", SQL_SMALLINT, 5 },
8328 { "SYSTEM", "PROCEDURE", "NUM_OUTPUT_PARAMS", SQL_SMALLINT, 5 },
8329 { "SYSTEM", "PROCEDURE", "NUM_RESULT_SETS", SQL_SMALLINT, 5 },
8330 { "SYSTEM", "PROCEDURE", "REMARKS", SCOL_VARCHAR, 255 },
8331 { "SYSTEM", "PROCEDURE", "PROCEDURE_TYPE", SQL_SMALLINT, 5 }
8332 };
8333
8334 #ifndef WINTERFACE
8335 /**
8336 * Retrieve information about stored procedures.
8337 * @param stmt statement handle
8338 * @param catalog catalog name/pattern or NULL
8339 * @param catalogLen length of catalog or SQL_NTS
8340 * @param schema schema name/pattern or NULL
8341 * @param schemaLen length of schema or SQL_NTS
8342 * @param proc procedure name/pattern or NULL
8343 * @param procLen length of proc or SQL_NTS
8344 * @result ODBC error code
8345 */
8346
8347 SQLRETURN SQL_API
SQLProcedures(SQLHSTMT stmt,SQLCHAR * catalog,SQLSMALLINT catalogLen,SQLCHAR * schema,SQLSMALLINT schemaLen,SQLCHAR * proc,SQLSMALLINT procLen)8348 SQLProcedures(SQLHSTMT stmt,
8349 SQLCHAR *catalog, SQLSMALLINT catalogLen,
8350 SQLCHAR *schema, SQLSMALLINT schemaLen,
8351 SQLCHAR *proc, SQLSMALLINT procLen)
8352 {
8353 SQLRETURN ret;
8354
8355 HSTMT_LOCK(stmt);
8356 ret = mkresultset(stmt, procSpec2, array_size(procSpec2),
8357 procSpec3, array_size(procSpec3), NULL);
8358 HSTMT_UNLOCK(stmt);
8359 return ret;
8360 }
8361 #endif
8362
8363 #ifdef WINTERFACE
8364 /**
8365 * Retrieve information about stored procedures (UNICODE version).
8366 * @param stmt statement handle
8367 * @param catalog catalog name/pattern or NULL
8368 * @param catalogLen length of catalog or SQL_NTS
8369 * @param schema schema name/pattern or NULL
8370 * @param schemaLen length of schema or SQL_NTS
8371 * @param proc procedure name/pattern or NULL
8372 * @param procLen length of proc or SQL_NTS
8373 * @result ODBC error code
8374 */
8375
8376 SQLRETURN SQL_API
SQLProceduresW(SQLHSTMT stmt,SQLWCHAR * catalog,SQLSMALLINT catalogLen,SQLWCHAR * schema,SQLSMALLINT schemaLen,SQLWCHAR * proc,SQLSMALLINT procLen)8377 SQLProceduresW(SQLHSTMT stmt,
8378 SQLWCHAR *catalog, SQLSMALLINT catalogLen,
8379 SQLWCHAR *schema, SQLSMALLINT schemaLen,
8380 SQLWCHAR *proc, SQLSMALLINT procLen)
8381 {
8382 SQLRETURN ret;
8383
8384 HSTMT_LOCK(stmt);
8385 ret = mkresultset(stmt, procSpec2, array_size(procSpec2),
8386 procSpec3, array_size(procSpec3), NULL);
8387 HSTMT_UNLOCK(stmt);
8388 return ret;
8389 }
8390 #endif
8391
8392 /**
8393 * Columns for result set of SQLProcedureColumns().
8394 */
8395
8396 static COL procColSpec2[] = {
8397 { "SYSTEM", "PROCCOL", "PROCEDURE_QUALIFIER", SCOL_VARCHAR, 50 },
8398 { "SYSTEM", "PROCCOL", "PROCEDURE_OWNER", SCOL_VARCHAR, 50 },
8399 { "SYSTEM", "PROCCOL", "PROCEDURE_NAME", SCOL_VARCHAR, 255 },
8400 { "SYSTEM", "PROCCOL", "COLUMN_NAME", SCOL_VARCHAR, 255 },
8401 { "SYSTEM", "PROCCOL", "COLUMN_TYPE", SQL_SMALLINT, 5 },
8402 { "SYSTEM", "PROCCOL", "DATA_TYPE", SQL_SMALLINT, 5 },
8403 { "SYSTEM", "PROCCOL", "TYPE_NAME", SCOL_VARCHAR, 50 },
8404 { "SYSTEM", "PROCCOL", "PRECISION", SQL_INTEGER, 10 },
8405 { "SYSTEM", "PROCCOL", "LENGTH", SQL_INTEGER, 10 },
8406 { "SYSTEM", "PROCCOL", "SCALE", SQL_SMALLINT, 5 },
8407 { "SYSTEM", "PROCCOL", "RADIX", SQL_SMALLINT, 5 },
8408 { "SYSTEM", "PROCCOL", "NULLABLE", SQL_SMALLINT, 5 },
8409 { "SYSTEM", "PROCCOL", "REMARKS", SCOL_VARCHAR, 50 },
8410 { "SYSTEM", "PROCCOL", "COLUMN_DEF", SCOL_VARCHAR, 50 },
8411 { "SYSTEM", "PROCCOL", "SQL_DATA_TYPE", SQL_SMALLINT, 5 },
8412 { "SYSTEM", "PROCCOL", "SQL_DATETIME_SUB", SQL_SMALLINT, 5 },
8413 { "SYSTEM", "PROCCOL", "CHAR_OCTET_LENGTH", SQL_SMALLINT, 5 },
8414 { "SYSTEM", "PROCCOL", "ORDINAL_POSITION", SQL_SMALLINT, 5 },
8415 { "SYSTEM", "PROCCOL", "IS_NULLABLE", SCOL_VARCHAR, 50 }
8416 };
8417
8418 static COL procColSpec3[] = {
8419 { "SYSTEM", "PROCCOL", "PROCEDURE_CAT", SCOL_VARCHAR, 50 },
8420 { "SYSTEM", "PROCCOL", "PROCEDURE_SCHEM", SCOL_VARCHAR, 50 },
8421 { "SYSTEM", "PROCCOL", "PROCEDURE_NAME", SCOL_VARCHAR, 255 },
8422 { "SYSTEM", "PROCCOL", "COLUMN_NAME", SCOL_VARCHAR, 255 },
8423 { "SYSTEM", "PROCCOL", "COLUMN_TYPE", SQL_SMALLINT, 5 },
8424 { "SYSTEM", "PROCCOL", "DATA_TYPE", SQL_SMALLINT, 5 },
8425 { "SYSTEM", "PROCCOL", "TYPE_NAME", SCOL_VARCHAR, 50 },
8426 { "SYSTEM", "PROCCOL", "COLUMN_SIZE", SQL_INTEGER, 10 },
8427 { "SYSTEM", "PROCCOL", "BUFFER_LENGTH", SQL_INTEGER, 10 },
8428 { "SYSTEM", "PROCCOL", "DECIMAL_DIGITS", SQL_SMALLINT, 5 },
8429 { "SYSTEM", "PROCCOL", "NUM_PREC_RADIX", SQL_SMALLINT, 5 },
8430 { "SYSTEM", "PROCCOL", "NULLABLE", SQL_SMALLINT, 5 },
8431 { "SYSTEM", "PROCCOL", "REMARKS", SCOL_VARCHAR, 50 },
8432 { "SYSTEM", "PROCCOL", "COLUMN_DEF", SCOL_VARCHAR, 50 },
8433 { "SYSTEM", "PROCCOL", "SQL_DATA_TYPE", SQL_SMALLINT, 5 },
8434 { "SYSTEM", "PROCCOL", "SQL_DATETIME_SUB", SQL_SMALLINT, 5 },
8435 { "SYSTEM", "PROCCOL", "CHAR_OCTET_LENGTH", SQL_SMALLINT, 5 },
8436 { "SYSTEM", "PROCCOL", "ORDINAL_POSITION", SQL_SMALLINT, 5 },
8437 { "SYSTEM", "PROCCOL", "IS_NULLABLE", SCOL_VARCHAR, 50 }
8438 };
8439
8440 #ifndef WINTERFACE
8441 /**
8442 * Retrieve information about columns in result set of stored procedures.
8443 * @param stmt statement handle
8444 * @param catalog catalog name/pattern or NULL
8445 * @param catalogLen length of catalog or SQL_NTS
8446 * @param schema schema name/pattern or NULL
8447 * @param schemaLen length of schema or SQL_NTS
8448 * @param proc procedure name/pattern or NULL
8449 * @param procLen length of proc or SQL_NTS
8450 * @param column column name/pattern or NULL
8451 * @param columnLen length of column or SQL_NTS
8452 * @result ODBC error code
8453 */
8454
8455 SQLRETURN SQL_API
SQLProcedureColumns(SQLHSTMT stmt,SQLCHAR * catalog,SQLSMALLINT catalogLen,SQLCHAR * schema,SQLSMALLINT schemaLen,SQLCHAR * proc,SQLSMALLINT procLen,SQLCHAR * column,SQLSMALLINT columnLen)8456 SQLProcedureColumns(SQLHSTMT stmt,
8457 SQLCHAR *catalog, SQLSMALLINT catalogLen,
8458 SQLCHAR *schema, SQLSMALLINT schemaLen,
8459 SQLCHAR *proc, SQLSMALLINT procLen,
8460 SQLCHAR *column, SQLSMALLINT columnLen)
8461 {
8462 SQLRETURN ret;
8463
8464 HSTMT_LOCK(stmt);
8465 ret = mkresultset(stmt, procColSpec2, array_size(procColSpec2),
8466 procColSpec3, array_size(procColSpec3), NULL);
8467 HSTMT_UNLOCK(stmt);
8468 return ret;
8469 }
8470 #endif
8471
8472 #ifdef WINTERFACE
8473 /**
8474 * Retrieve information about columns in result
8475 * set of stored procedures (UNICODE version).
8476 * @param stmt statement handle
8477 * @param catalog catalog name/pattern or NULL
8478 * @param catalogLen length of catalog or SQL_NTS
8479 * @param schema schema name/pattern or NULL
8480 * @param schemaLen length of schema or SQL_NTS
8481 * @param proc procedure name/pattern or NULL
8482 * @param procLen length of proc or SQL_NTS
8483 * @param column column name/pattern or NULL
8484 * @param columnLen length of column or SQL_NTS
8485 * @result ODBC error code
8486 */
8487
8488 SQLRETURN SQL_API
SQLProcedureColumnsW(SQLHSTMT stmt,SQLWCHAR * catalog,SQLSMALLINT catalogLen,SQLWCHAR * schema,SQLSMALLINT schemaLen,SQLWCHAR * proc,SQLSMALLINT procLen,SQLWCHAR * column,SQLSMALLINT columnLen)8489 SQLProcedureColumnsW(SQLHSTMT stmt,
8490 SQLWCHAR *catalog, SQLSMALLINT catalogLen,
8491 SQLWCHAR *schema, SQLSMALLINT schemaLen,
8492 SQLWCHAR *proc, SQLSMALLINT procLen,
8493 SQLWCHAR *column, SQLSMALLINT columnLen)
8494 {
8495 SQLRETURN ret;
8496
8497 HSTMT_LOCK(stmt);
8498 ret = mkresultset(stmt, procColSpec2, array_size(procColSpec2),
8499 procColSpec3, array_size(procColSpec3), NULL);
8500 HSTMT_UNLOCK(stmt);
8501 return ret;
8502 }
8503 #endif
8504
8505 /**
8506 * Get information of HENV.
8507 * @param env environment handle
8508 * @param attr attribute to be retrieved
8509 * @param val output buffer
8510 * @param len length of output buffer
8511 * @param lenp output length
8512 * @result ODBC error code
8513 */
8514
8515 SQLRETURN SQL_API
SQLGetEnvAttr(SQLHENV env,SQLINTEGER attr,SQLPOINTER val,SQLINTEGER len,SQLINTEGER * lenp)8516 SQLGetEnvAttr(SQLHENV env, SQLINTEGER attr, SQLPOINTER val,
8517 SQLINTEGER len, SQLINTEGER *lenp)
8518 {
8519 ENV *e;
8520 SQLRETURN ret = SQL_ERROR;
8521
8522 if (env == SQL_NULL_HENV) {
8523 return SQL_INVALID_HANDLE;
8524 }
8525 e = (ENV *) env;
8526 if (!e || e->magic != ENV_MAGIC) {
8527 return SQL_INVALID_HANDLE;
8528 }
8529 #if defined(_WIN32) || defined(_WIN64)
8530 EnterCriticalSection(&e->cs);
8531 #endif
8532 switch (attr) {
8533 case SQL_ATTR_CONNECTION_POOLING:
8534 if (val) {
8535 *((SQLINTEGER *) val) = e->pool ?
8536 SQL_CP_ONE_PER_DRIVER : SQL_CP_OFF;
8537 }
8538 if (lenp) {
8539 *lenp = sizeof (SQLINTEGER);
8540 }
8541 ret = SQL_SUCCESS;
8542 break;
8543 case SQL_ATTR_CP_MATCH:
8544 *((SQLINTEGER *) val) = SQL_CP_RELAXED_MATCH;
8545 if (lenp) {
8546 *lenp = sizeof (SQLINTEGER);
8547 }
8548 ret = SQL_SUCCESS;
8549 break;
8550 case SQL_ATTR_OUTPUT_NTS:
8551 if (val) {
8552 *((SQLINTEGER *) val) = SQL_TRUE;
8553 }
8554 if (lenp) {
8555 *lenp = sizeof (SQLINTEGER);
8556 }
8557 ret = SQL_SUCCESS;
8558 break;
8559 case SQL_ATTR_ODBC_VERSION:
8560 if (val) {
8561 *((SQLINTEGER *) val) = e->ov3 ? SQL_OV_ODBC3 : SQL_OV_ODBC2;
8562 }
8563 if (lenp) {
8564 *lenp = sizeof (SQLINTEGER);
8565 }
8566 ret = SQL_SUCCESS;
8567 break;
8568 }
8569 #if defined(_WIN32) || defined(_WIN64)
8570 LeaveCriticalSection(&e->cs);
8571 #endif
8572 return ret;
8573 }
8574
8575 /**
8576 * Set information in HENV.
8577 * @param env environment handle
8578 * @param attr attribute to be retrieved
8579 * @param val parameter buffer
8580 * @param len length of parameter
8581 * @result ODBC error code
8582 */
8583
8584 SQLRETURN SQL_API
SQLSetEnvAttr(SQLHENV env,SQLINTEGER attr,SQLPOINTER val,SQLINTEGER len)8585 SQLSetEnvAttr(SQLHENV env, SQLINTEGER attr, SQLPOINTER val, SQLINTEGER len)
8586 {
8587 ENV *e;
8588 SQLRETURN ret = SQL_ERROR;
8589
8590 if (env == SQL_NULL_HENV) {
8591 return SQL_INVALID_HANDLE;
8592 }
8593 e = (ENV *) env;
8594 if (!e || e->magic != ENV_MAGIC) {
8595 return SQL_INVALID_HANDLE;
8596 }
8597 #if defined(_WIN32) || defined(_WIN64)
8598 EnterCriticalSection(&e->cs);
8599 #endif
8600 switch (attr) {
8601 case SQL_ATTR_CONNECTION_POOLING:
8602 if (val == (SQLPOINTER) SQL_CP_ONE_PER_DRIVER) {
8603 e->pool = 1;
8604 ret = SQL_SUCCESS;
8605 } else if (val == (SQLPOINTER) SQL_CP_OFF) {
8606 e->pool = 0;
8607 ret = SQL_SUCCESS;
8608 }
8609 break;
8610 case SQL_ATTR_CP_MATCH:
8611 ret = SQL_SUCCESS;
8612 break;
8613 case SQL_ATTR_OUTPUT_NTS:
8614 if (val == (SQLPOINTER) SQL_TRUE) {
8615 ret = SQL_SUCCESS;
8616 }
8617 break;
8618 case SQL_ATTR_ODBC_VERSION:
8619 if (!val) {
8620 break;
8621 }
8622 if (val == (SQLPOINTER) SQL_OV_ODBC2) {
8623 e->ov3 = 0;
8624 ret = SQL_SUCCESS;
8625 } else if (val == (SQLPOINTER) SQL_OV_ODBC3) {
8626 e->ov3 = 1;
8627 ret = SQL_SUCCESS;
8628 }
8629 break;
8630 }
8631 #if defined(_WIN32) || defined(_WIN64)
8632 LeaveCriticalSection(&e->cs);
8633 #endif
8634 return ret;
8635 }
8636
8637 /**
8638 * Internal get error message given handle (HENV, HDBC, or HSTMT).
8639 * @param htype handle type
8640 * @param handle HENV, HDBC, or HSTMT
8641 * @param recno
8642 * @param sqlstate output buffer for SQL state
8643 * @param nativeerr output buffer of native error code
8644 * @param msg output buffer for error message
8645 * @param buflen length of output buffer
8646 * @param msglen output length
8647 * @result ODBC error code
8648 */
8649
8650 static SQLRETURN
drvgetdiagrec(SQLSMALLINT htype,SQLHANDLE handle,SQLSMALLINT recno,SQLCHAR * sqlstate,SQLINTEGER * nativeerr,SQLCHAR * msg,SQLSMALLINT buflen,SQLSMALLINT * msglen)8651 drvgetdiagrec(SQLSMALLINT htype, SQLHANDLE handle, SQLSMALLINT recno,
8652 SQLCHAR *sqlstate, SQLINTEGER *nativeerr, SQLCHAR *msg,
8653 SQLSMALLINT buflen, SQLSMALLINT *msglen)
8654 {
8655 DBC *d = NULL;
8656 STMT *s = NULL;
8657 int len, naterr;
8658 char *logmsg, *sqlst;
8659 SQLRETURN ret = SQL_ERROR;
8660
8661 if (handle == SQL_NULL_HANDLE) {
8662 return SQL_INVALID_HANDLE;
8663 }
8664 if (sqlstate) {
8665 sqlstate[0] = '\0';
8666 }
8667 if (msg && buflen > 0) {
8668 msg[0] = '\0';
8669 }
8670 if (msglen) {
8671 *msglen = 0;
8672 }
8673 if (nativeerr) {
8674 *nativeerr = 0;
8675 }
8676 switch (htype) {
8677 case SQL_HANDLE_ENV:
8678 case SQL_HANDLE_DESC:
8679 return SQL_NO_DATA;
8680 case SQL_HANDLE_DBC:
8681 HDBC_LOCK((SQLHDBC) handle);
8682 d = (DBC *) handle;
8683 logmsg = (char *) d->logmsg;
8684 sqlst = d->sqlstate;
8685 naterr = d->naterr;
8686 break;
8687 case SQL_HANDLE_STMT:
8688 HSTMT_LOCK((SQLHSTMT) handle);
8689 s = (STMT *) handle;
8690 logmsg = (char *) s->logmsg;
8691 sqlst = s->sqlstate;
8692 naterr = s->naterr;
8693 break;
8694 default:
8695 return SQL_INVALID_HANDLE;
8696 }
8697 if (buflen < 0) {
8698 goto done;
8699 }
8700 if (recno > 1) {
8701 ret = SQL_NO_DATA;
8702 goto done;
8703 }
8704 len = strlen(logmsg);
8705 if (len == 0) {
8706 ret = SQL_NO_DATA;
8707 goto done;
8708 }
8709 if (nativeerr) {
8710 *nativeerr = naterr;
8711 }
8712 if (sqlstate) {
8713 strcpy((char *) sqlstate, sqlst);
8714 }
8715 if (msglen) {
8716 *msglen = len;
8717 }
8718 if (len >= buflen) {
8719 if (msg && buflen > 0) {
8720 strncpy((char *) msg, logmsg, buflen);
8721 msg[buflen - 1] = '\0';
8722 logmsg[0] = '\0';
8723 }
8724 } else if (msg) {
8725 strcpy((char *) msg, logmsg);
8726 logmsg[0] = '\0';
8727 }
8728 ret = SQL_SUCCESS;
8729 done:
8730 switch (htype) {
8731 case SQL_HANDLE_DBC:
8732 HDBC_UNLOCK((SQLHDBC) handle);
8733 break;
8734 case SQL_HANDLE_STMT:
8735 HSTMT_UNLOCK((SQLHSTMT) handle);
8736 break;
8737 }
8738 return ret;
8739 }
8740
8741 #if !defined(WINTERFACE) || (defined(HAVE_UNIXODBC) && (HAVE_UNIXODBC))
8742 /**
8743 * Get error message given handle (HENV, HDBC, or HSTMT).
8744 * @param htype handle type
8745 * @param handle HENV, HDBC, or HSTMT
8746 * @param recno
8747 * @param sqlstate output buffer for SQL state
8748 * @param nativeerr output buffer of native error code
8749 * @param msg output buffer for error message
8750 * @param buflen length of output buffer
8751 * @param msglen output length
8752 * @result ODBC error code
8753 */
8754
8755 SQLRETURN SQL_API
SQLGetDiagRec(SQLSMALLINT htype,SQLHANDLE handle,SQLSMALLINT recno,SQLCHAR * sqlstate,SQLINTEGER * nativeerr,SQLCHAR * msg,SQLSMALLINT buflen,SQLSMALLINT * msglen)8756 SQLGetDiagRec(SQLSMALLINT htype, SQLHANDLE handle, SQLSMALLINT recno,
8757 SQLCHAR *sqlstate, SQLINTEGER *nativeerr, SQLCHAR *msg,
8758 SQLSMALLINT buflen, SQLSMALLINT *msglen)
8759 {
8760 return drvgetdiagrec(htype, handle, recno, sqlstate,
8761 nativeerr, msg, buflen, msglen);
8762 }
8763 #endif
8764
8765 #if !defined(HAVE_UNIXODBC) || !(HAVE_UNIXODBC)
8766 #ifdef WINTERFACE
8767 /**
8768 * Get error message given handle (HENV, HDBC, or HSTMT)
8769 * (UNICODE version).
8770 * @param htype handle type
8771 * @param handle HENV, HDBC, or HSTMT
8772 * @param recno
8773 * @param sqlstate output buffer for SQL state
8774 * @param nativeerr output buffer of native error code
8775 * @param msg output buffer for error message
8776 * @param buflen length of output buffer
8777 * @param msglen output length
8778 * @result ODBC error code
8779 */
8780
8781 SQLRETURN SQL_API
SQLGetDiagRecW(SQLSMALLINT htype,SQLHANDLE handle,SQLSMALLINT recno,SQLWCHAR * sqlstate,SQLINTEGER * nativeerr,SQLWCHAR * msg,SQLSMALLINT buflen,SQLSMALLINT * msglen)8782 SQLGetDiagRecW(SQLSMALLINT htype, SQLHANDLE handle, SQLSMALLINT recno,
8783 SQLWCHAR *sqlstate, SQLINTEGER *nativeerr, SQLWCHAR *msg,
8784 SQLSMALLINT buflen, SQLSMALLINT *msglen)
8785 {
8786 char state[16];
8787 SQLSMALLINT len;
8788 SQLRETURN ret;
8789
8790 ret = drvgetdiagrec(htype, handle, recno, (SQLCHAR *) state,
8791 nativeerr, (SQLCHAR *) msg, buflen, &len);
8792 if (ret == SQL_SUCCESS) {
8793 if (sqlstate) {
8794 uc_from_utf_buf((SQLCHAR *) state, -1, sqlstate,
8795 6 * sizeof (SQLWCHAR));
8796 }
8797 if (msg) {
8798 if (len > 0) {
8799 SQLWCHAR *m = NULL;
8800
8801 m = uc_from_utf((unsigned char *) msg, len);
8802 if (m) {
8803 if (buflen) {
8804 buflen /= sizeof (SQLWCHAR);
8805 uc_strncpy(msg, m, buflen);
8806 m[len] = 0;
8807 len = min(buflen, uc_strlen(m));
8808 } else {
8809 len = uc_strlen(m);
8810 }
8811 uc_free(m);
8812 } else {
8813 len = 0;
8814 }
8815 }
8816 if (len <= 0) {
8817 len = 0;
8818 if (buflen > 0) {
8819 msg[0] = 0;
8820 }
8821 }
8822 } else {
8823 /* estimated length !!! */
8824 len *= sizeof (SQLWCHAR);
8825 }
8826 if (msglen) {
8827 *msglen = len;
8828 }
8829 } else if (ret == SQL_NO_DATA) {
8830 if (sqlstate) {
8831 sqlstate[0] = 0;
8832 }
8833 if (msg) {
8834 if (buflen > 0) {
8835 msg[0] = 0;
8836 }
8837 }
8838 if (msglen) {
8839 *msglen = 0;
8840 }
8841 }
8842 return ret;
8843 }
8844 #endif
8845 #endif
8846
8847 /**
8848 * Get error record given handle (HDBC or HSTMT).
8849 * @param htype handle type
8850 * @param handle HDBC or HSTMT
8851 * @param recno diag record number for which info to be retrieved
8852 * @param id diag id for which info to be retrieved
8853 * @param info output buffer for error message
8854 * @param buflen length of output buffer
8855 * @param stringlen output length
8856 * @result ODBC error code
8857 */
8858
8859 static SQLRETURN
drvgetdiagfield(SQLSMALLINT htype,SQLHANDLE handle,SQLSMALLINT recno,SQLSMALLINT id,SQLPOINTER info,SQLSMALLINT buflen,SQLSMALLINT * stringlen)8860 drvgetdiagfield(SQLSMALLINT htype, SQLHANDLE handle, SQLSMALLINT recno,
8861 SQLSMALLINT id, SQLPOINTER info,
8862 SQLSMALLINT buflen, SQLSMALLINT *stringlen)
8863 {
8864 DBC *d = NULL;
8865 STMT *s = NULL;
8866 int len, naterr, strbuf = 1;
8867 char *logmsg, *sqlst, *clrmsg = NULL;
8868 SQLRETURN ret = SQL_ERROR;
8869
8870 if (handle == SQL_NULL_HANDLE) {
8871 return SQL_INVALID_HANDLE;
8872 }
8873 if (stringlen) {
8874 *stringlen = 0;
8875 }
8876 switch (htype) {
8877 case SQL_HANDLE_ENV:
8878 case SQL_HANDLE_DESC:
8879 return SQL_NO_DATA;
8880 case SQL_HANDLE_DBC:
8881 HDBC_LOCK((SQLHDBC) handle);
8882 d = (DBC *) handle;
8883 logmsg = (char *) d->logmsg;
8884 sqlst = d->sqlstate;
8885 naterr = d->naterr;
8886 break;
8887 case SQL_HANDLE_STMT:
8888 HSTMT_LOCK((SQLHSTMT) handle);
8889 s = (STMT *) handle;
8890 d = (DBC *) s->dbc;
8891 logmsg = (char *) s->logmsg;
8892 sqlst = s->sqlstate;
8893 naterr = s->naterr;
8894 break;
8895 default:
8896 return SQL_INVALID_HANDLE;
8897 }
8898 if (buflen < 0) {
8899 switch (buflen) {
8900 case SQL_IS_POINTER:
8901 case SQL_IS_UINTEGER:
8902 case SQL_IS_INTEGER:
8903 case SQL_IS_USMALLINT:
8904 case SQL_IS_SMALLINT:
8905 strbuf = 0;
8906 break;
8907 default:
8908 ret = SQL_ERROR;
8909 goto done;
8910 }
8911 }
8912 if (recno > 1) {
8913 ret = SQL_NO_DATA;
8914 goto done;
8915 }
8916 switch (id) {
8917 case SQL_DIAG_CLASS_ORIGIN:
8918 logmsg = "ISO 9075";
8919 if (sqlst[0] == 'I' && sqlst[1] == 'M') {
8920 logmsg = "ODBC 3.0";
8921 }
8922 break;
8923 case SQL_DIAG_SUBCLASS_ORIGIN:
8924 logmsg = "ISO 9075";
8925 if (sqlst[0] == 'I' && sqlst[1] == 'M') {
8926 logmsg = "ODBC 3.0";
8927 } else if (sqlst[0] == 'H' && sqlst[1] == 'Y') {
8928 logmsg = "ODBC 3.0";
8929 } else if (sqlst[0] == '2' || sqlst[0] == '0' || sqlst[0] == '4') {
8930 logmsg = "ODBC 3.0";
8931 }
8932 break;
8933 case SQL_DIAG_CONNECTION_NAME:
8934 case SQL_DIAG_SERVER_NAME:
8935 logmsg = d->dsn ? d->dsn : "No DSN";
8936 break;
8937 case SQL_DIAG_SQLSTATE:
8938 logmsg = sqlst;
8939 break;
8940 case SQL_DIAG_MESSAGE_TEXT:
8941 if (info) {
8942 clrmsg = logmsg;
8943 }
8944 break;
8945 case SQL_DIAG_NUMBER:
8946 naterr = 1;
8947 /* fall through */
8948 case SQL_DIAG_NATIVE:
8949 len = strlen(logmsg);
8950 if (len == 0) {
8951 ret = SQL_NO_DATA;
8952 goto done;
8953 }
8954 if (info) {
8955 *((SQLINTEGER *) info) = naterr;
8956 }
8957 ret = SQL_SUCCESS;
8958 goto done;
8959 case SQL_DIAG_DYNAMIC_FUNCTION:
8960 logmsg = "";
8961 break;
8962 case SQL_DIAG_CURSOR_ROW_COUNT:
8963 if (htype == SQL_HANDLE_STMT) {
8964 SQLULEN count;
8965
8966 count = (s->isselect == 1 || s->isselect == -1) ? s->nrows : 0;
8967 *((SQLULEN *) info) = count;
8968 ret = SQL_SUCCESS;
8969 }
8970 goto done;
8971 case SQL_DIAG_ROW_COUNT:
8972 if (htype == SQL_HANDLE_STMT) {
8973 SQLULEN count;
8974
8975 count = s->isselect ? 0 : s->nrows;
8976 *((SQLULEN *) info) = count;
8977 ret = SQL_SUCCESS;
8978 }
8979 goto done;
8980 default:
8981 goto done;
8982 }
8983 if (info && buflen > 0) {
8984 ((char *) info)[0] = '\0';
8985 }
8986 len = strlen(logmsg);
8987 if (len == 0) {
8988 ret = SQL_NO_DATA;
8989 goto done;
8990 }
8991 if (stringlen) {
8992 *stringlen = len;
8993 }
8994 if (strbuf) {
8995 if (len >= buflen) {
8996 if (info && buflen > 0) {
8997 if (stringlen) {
8998 *stringlen = buflen - 1;
8999 }
9000 strncpy((char *) info, logmsg, buflen);
9001 ((char *) info)[buflen - 1] = '\0';
9002 }
9003 } else if (info) {
9004 strcpy((char *) info, logmsg);
9005 }
9006 }
9007 if (clrmsg) {
9008 *clrmsg = '\0';
9009 }
9010 ret = SQL_SUCCESS;
9011 done:
9012 switch (htype) {
9013 case SQL_HANDLE_DBC:
9014 HDBC_UNLOCK((SQLHDBC) handle);
9015 break;
9016 case SQL_HANDLE_STMT:
9017 HSTMT_UNLOCK((SQLHSTMT) handle);
9018 break;
9019 }
9020 return ret;
9021 }
9022
9023 #ifndef WINTERFACE
9024 /**
9025 * Get error record given handle (HDBC or HSTMT).
9026 * @param htype handle type
9027 * @param handle HDBC or HSTMT
9028 * @param recno diag record number for which info to be retrieved
9029 * @param id diag id for which info to be retrieved
9030 * @param info output buffer for error message
9031 * @param buflen length of output buffer
9032 * @param stringlen output length
9033 * @result ODBC error code
9034 */
9035
9036 SQLRETURN SQL_API
SQLGetDiagField(SQLSMALLINT htype,SQLHANDLE handle,SQLSMALLINT recno,SQLSMALLINT id,SQLPOINTER info,SQLSMALLINT buflen,SQLSMALLINT * stringlen)9037 SQLGetDiagField(SQLSMALLINT htype, SQLHANDLE handle, SQLSMALLINT recno,
9038 SQLSMALLINT id, SQLPOINTER info,
9039 SQLSMALLINT buflen, SQLSMALLINT *stringlen)
9040 {
9041 return drvgetdiagfield(htype, handle, recno, id, info, buflen, stringlen);
9042 }
9043 #endif
9044
9045 #ifdef WINTERFACE
9046 /**
9047 * Get error record given handle (HDBC or HSTMT).
9048 * @param htype handle type
9049 * @param handle HDBC or HSTMT
9050 * @param recno diag record number for which info to be retrieved
9051 * @param id diag id for which info to be retrieved
9052 * @param info output buffer for error message
9053 * @param buflen length of output buffer
9054 * @param stringlen output length
9055 * @result ODBC error code
9056 */
9057
9058 SQLRETURN SQL_API
SQLGetDiagFieldW(SQLSMALLINT htype,SQLHANDLE handle,SQLSMALLINT recno,SQLSMALLINT id,SQLPOINTER info,SQLSMALLINT buflen,SQLSMALLINT * stringlen)9059 SQLGetDiagFieldW(SQLSMALLINT htype, SQLHANDLE handle, SQLSMALLINT recno,
9060 SQLSMALLINT id, SQLPOINTER info,
9061 SQLSMALLINT buflen, SQLSMALLINT *stringlen)
9062 {
9063 SQLSMALLINT len;
9064 SQLRETURN ret;
9065
9066 ret = drvgetdiagfield(htype, handle, recno, id, info, buflen, &len);
9067 if (ret == SQL_SUCCESS) {
9068 if (info) {
9069 switch (id) {
9070 case SQL_DIAG_CLASS_ORIGIN:
9071 case SQL_DIAG_SUBCLASS_ORIGIN:
9072 case SQL_DIAG_CONNECTION_NAME:
9073 case SQL_DIAG_SERVER_NAME:
9074 case SQL_DIAG_SQLSTATE:
9075 case SQL_DIAG_MESSAGE_TEXT:
9076 case SQL_DIAG_DYNAMIC_FUNCTION:
9077 if (len > 0) {
9078 SQLWCHAR *m = NULL;
9079
9080 m = uc_from_utf((unsigned char *) info, len);
9081 if (m) {
9082 if (buflen) {
9083 buflen /= sizeof (SQLWCHAR);
9084 uc_strncpy(info, m, buflen);
9085 m[len] = 0;
9086 len = min(buflen, uc_strlen(m));
9087 } else {
9088 len = uc_strlen(m);
9089 }
9090 uc_free(m);
9091 len *= sizeof (SQLWCHAR);
9092 } else {
9093 len = 0;
9094 }
9095 }
9096 if (len <= 0) {
9097 len = 0;
9098 if (buflen > 0) {
9099 ((SQLWCHAR *) info)[0] = 0;
9100 }
9101 }
9102 }
9103 } else {
9104 switch (id) {
9105 case SQL_DIAG_CLASS_ORIGIN:
9106 case SQL_DIAG_SUBCLASS_ORIGIN:
9107 case SQL_DIAG_CONNECTION_NAME:
9108 case SQL_DIAG_SERVER_NAME:
9109 case SQL_DIAG_SQLSTATE:
9110 case SQL_DIAG_MESSAGE_TEXT:
9111 case SQL_DIAG_DYNAMIC_FUNCTION:
9112 len *= sizeof (SQLWCHAR);
9113 break;
9114 }
9115 }
9116 if (stringlen) {
9117 *stringlen = len;
9118 }
9119 }
9120 return ret;
9121 }
9122 #endif
9123
9124 /**
9125 * Internal get option of HSTMT.
9126 * @param stmt statement handle
9127 * @param attr attribute to be retrieved
9128 * @param val output buffer
9129 * @param bufmax length of output buffer
9130 * @param buflen output length
9131 * @result ODBC error code
9132 */
9133
9134 static SQLRETURN
drvgetstmtattr(SQLHSTMT stmt,SQLINTEGER attr,SQLPOINTER val,SQLINTEGER bufmax,SQLINTEGER * buflen)9135 drvgetstmtattr(SQLHSTMT stmt, SQLINTEGER attr, SQLPOINTER val,
9136 SQLINTEGER bufmax, SQLINTEGER *buflen)
9137 {
9138 STMT *s = (STMT *) stmt;
9139 SQLULEN *uval = (SQLULEN *) val;
9140 SQLINTEGER dummy;
9141 char dummybuf[16];
9142
9143 if (!buflen) {
9144 buflen = &dummy;
9145 }
9146 if (!uval) {
9147 uval = (SQLPOINTER) dummybuf;
9148 }
9149 switch (attr) {
9150 case SQL_QUERY_TIMEOUT:
9151 *uval = 0;
9152 *buflen = sizeof (SQLULEN);
9153 return SQL_SUCCESS;
9154 case SQL_ATTR_CURSOR_TYPE:
9155 *uval = s->curtype;
9156 *buflen = sizeof (SQLULEN);
9157 return SQL_SUCCESS;
9158 case SQL_ATTR_CURSOR_SCROLLABLE:
9159 *uval = (s->curtype != SQL_CURSOR_FORWARD_ONLY) ?
9160 SQL_SCROLLABLE : SQL_NONSCROLLABLE;
9161 *buflen = sizeof (SQLULEN);
9162 return SQL_SUCCESS;
9163 #ifdef SQL_ATTR_CURSOR_SENSITIVITY
9164 case SQL_ATTR_CURSOR_SENSITIVITY:
9165 *uval = SQL_UNSPECIFIED;
9166 *buflen = sizeof (SQLULEN);
9167 return SQL_SUCCESS;
9168 #endif
9169 case SQL_ATTR_ROW_NUMBER:
9170 if (s->s3stmt) {
9171 *uval = (s->s3stmt_rownum < 0) ?
9172 SQL_ROW_NUMBER_UNKNOWN : (s->s3stmt_rownum + 1);
9173 } else {
9174 *uval = (s->rowp < 0) ? SQL_ROW_NUMBER_UNKNOWN : (s->rowp + 1);
9175 }
9176 *buflen = sizeof (SQLULEN);
9177 return SQL_SUCCESS;
9178 case SQL_ATTR_ASYNC_ENABLE:
9179 *uval = SQL_ASYNC_ENABLE_OFF;
9180 *buflen = sizeof (SQLULEN);
9181 return SQL_SUCCESS;
9182 case SQL_CONCURRENCY:
9183 *uval = SQL_CONCUR_LOCK;
9184 *buflen = sizeof (SQLULEN);
9185 return SQL_SUCCESS;
9186 case SQL_ATTR_RETRIEVE_DATA:
9187 *uval = s->retr_data;
9188 *buflen = sizeof (SQLULEN);
9189 return SQL_SUCCESS;
9190 case SQL_ROWSET_SIZE:
9191 case SQL_ATTR_ROW_ARRAY_SIZE:
9192 *uval = s->rowset_size;
9193 *buflen = sizeof (SQLULEN);
9194 return SQL_SUCCESS;
9195 /* Needed for some driver managers, but dummies for now */
9196 case SQL_ATTR_IMP_ROW_DESC:
9197 case SQL_ATTR_APP_ROW_DESC:
9198 case SQL_ATTR_IMP_PARAM_DESC:
9199 case SQL_ATTR_APP_PARAM_DESC:
9200 *((SQLHDESC *) uval) = (SQLHDESC) DEAD_MAGIC;
9201 *buflen = sizeof (SQLHDESC);
9202 return SQL_SUCCESS;
9203 case SQL_ATTR_ROW_STATUS_PTR:
9204 *((SQLUSMALLINT **) uval) = s->row_status;
9205 *buflen = sizeof (SQLUSMALLINT *);
9206 return SQL_SUCCESS;
9207 case SQL_ATTR_ROWS_FETCHED_PTR:
9208 *((SQLULEN **) uval) = s->row_count;
9209 *buflen = sizeof (SQLULEN *);
9210 return SQL_SUCCESS;
9211 case SQL_ATTR_USE_BOOKMARKS: {
9212 STMT *s = (STMT *) stmt;
9213
9214 *(SQLUINTEGER *) uval = s->bkmrk;
9215 *buflen = sizeof (SQLUINTEGER);
9216 return SQL_SUCCESS;
9217 }
9218 case SQL_ATTR_FETCH_BOOKMARK_PTR:
9219 *(SQLPOINTER *) uval = s->bkmrkptr;
9220 *buflen = sizeof (SQLPOINTER);
9221 return SQL_SUCCESS;
9222 case SQL_ATTR_PARAM_BIND_OFFSET_PTR:
9223 *((SQLULEN **) uval) = s->parm_bind_offs;
9224 *buflen = sizeof (SQLULEN *);
9225 return SQL_SUCCESS;
9226 case SQL_ATTR_PARAM_BIND_TYPE:
9227 *((SQLULEN *) uval) = s->parm_bind_type;
9228 *buflen = sizeof (SQLULEN);
9229 return SQL_SUCCESS;
9230 case SQL_ATTR_PARAM_OPERATION_PTR:
9231 *((SQLUSMALLINT **) uval) = s->parm_oper;
9232 *buflen = sizeof (SQLUSMALLINT *);
9233 return SQL_SUCCESS;
9234 case SQL_ATTR_PARAM_STATUS_PTR:
9235 *((SQLUSMALLINT **) uval) = s->parm_status;
9236 *buflen = sizeof (SQLUSMALLINT *);
9237 return SQL_SUCCESS;
9238 case SQL_ATTR_PARAMS_PROCESSED_PTR:
9239 *((SQLULEN **) uval) = s->parm_proc;
9240 *buflen = sizeof (SQLULEN *);
9241 return SQL_SUCCESS;
9242 case SQL_ATTR_PARAMSET_SIZE:
9243 *((SQLULEN *) uval) = s->paramset_size;
9244 *buflen = sizeof (SQLULEN);
9245 return SQL_SUCCESS;
9246 case SQL_ATTR_ROW_BIND_TYPE:
9247 *(SQLULEN *) uval = s->bind_type;
9248 *buflen = sizeof (SQLULEN);
9249 return SQL_SUCCESS;
9250 case SQL_ATTR_ROW_BIND_OFFSET_PTR:
9251 *((SQLULEN **) uval) = s->bind_offs;
9252 *buflen = sizeof (SQLULEN *);
9253 return SQL_SUCCESS;
9254 case SQL_ATTR_MAX_ROWS:
9255 *((SQLULEN *) uval) = s->max_rows;
9256 *buflen = sizeof (SQLULEN);
9257 return SQL_SUCCESS;
9258 case SQL_ATTR_MAX_LENGTH:
9259 *((SQLULEN *) uval) = 1000000000;
9260 *buflen = sizeof (SQLULEN);
9261 return SQL_SUCCESS;
9262 #ifdef SQL_ATTR_METADATA_ID
9263 case SQL_ATTR_METADATA_ID:
9264 *((SQLULEN *) uval) = SQL_FALSE;
9265 *buflen = sizeof (SQLULEN);
9266 return SQL_SUCCESS;
9267 #endif
9268 }
9269 return drvunimplstmt(stmt);
9270 }
9271
9272 #if (defined(HAVE_UNIXODBC) && (HAVE_UNIXODBC)) || !defined(WINTERFACE)
9273 /**
9274 * Get option of HSTMT.
9275 * @param stmt statement handle
9276 * @param attr attribute to be retrieved
9277 * @param val output buffer
9278 * @param bufmax length of output buffer
9279 * @param buflen output length
9280 * @result ODBC error code
9281 */
9282
9283 SQLRETURN SQL_API
SQLGetStmtAttr(SQLHSTMT stmt,SQLINTEGER attr,SQLPOINTER val,SQLINTEGER bufmax,SQLINTEGER * buflen)9284 SQLGetStmtAttr(SQLHSTMT stmt, SQLINTEGER attr, SQLPOINTER val,
9285 SQLINTEGER bufmax, SQLINTEGER *buflen)
9286 {
9287 SQLRETURN ret;
9288
9289 HSTMT_LOCK(stmt);
9290 ret = drvgetstmtattr(stmt, attr, val, bufmax, buflen);
9291 HSTMT_UNLOCK(stmt);
9292 return ret;
9293 }
9294 #endif
9295
9296 #ifdef WINTERFACE
9297 /**
9298 * Get option of HSTMT (UNICODE version).
9299 * @param stmt statement handle
9300 * @param attr attribute to be retrieved
9301 * @param val output buffer
9302 * @param bufmax length of output buffer
9303 * @param buflen output length
9304 * @result ODBC error code
9305 */
9306
9307 SQLRETURN SQL_API
SQLGetStmtAttrW(SQLHSTMT stmt,SQLINTEGER attr,SQLPOINTER val,SQLINTEGER bufmax,SQLINTEGER * buflen)9308 SQLGetStmtAttrW(SQLHSTMT stmt, SQLINTEGER attr, SQLPOINTER val,
9309 SQLINTEGER bufmax, SQLINTEGER *buflen)
9310 {
9311 SQLRETURN ret;
9312
9313 HSTMT_LOCK(stmt);
9314 ret = drvgetstmtattr(stmt, attr, val, bufmax, buflen);
9315 HSTMT_UNLOCK(stmt);
9316 return ret;
9317 }
9318 #endif
9319
9320 /**
9321 * Internal set option on HSTMT.
9322 * @param stmt statement handle
9323 * @param attr attribute to be set
9324 * @param val input buffer (attribute value)
9325 * @param buflen length of input buffer
9326 * @result ODBC error code
9327 */
9328
9329 static SQLRETURN
drvsetstmtattr(SQLHSTMT stmt,SQLINTEGER attr,SQLPOINTER val,SQLINTEGER buflen)9330 drvsetstmtattr(SQLHSTMT stmt, SQLINTEGER attr, SQLPOINTER val,
9331 SQLINTEGER buflen)
9332 {
9333 STMT *s = (STMT *) stmt;
9334 #if defined(SQL_BIGINT) && defined(__WORDSIZE) && (__WORDSIZE == 64)
9335 SQLBIGINT uval;
9336
9337 uval = (SQLBIGINT) val;
9338 #else
9339 SQLULEN uval;
9340
9341 uval = (SQLULEN) val;
9342 #endif
9343 switch (attr) {
9344 case SQL_ATTR_CURSOR_TYPE:
9345 if (val == (SQLPOINTER) SQL_CURSOR_FORWARD_ONLY) {
9346 s->curtype = SQL_CURSOR_FORWARD_ONLY;
9347 } else {
9348 s->curtype = SQL_CURSOR_STATIC;
9349 }
9350 if (val != (SQLPOINTER) SQL_CURSOR_FORWARD_ONLY &&
9351 val != (SQLPOINTER) SQL_CURSOR_STATIC) {
9352 goto e01s02;
9353 }
9354 return SQL_SUCCESS;
9355 case SQL_ATTR_CURSOR_SCROLLABLE:
9356 if (val == (SQLPOINTER) SQL_NONSCROLLABLE) {
9357 s->curtype = SQL_CURSOR_FORWARD_ONLY;
9358 } else {
9359 s->curtype = SQL_CURSOR_STATIC;
9360 }
9361 return SQL_SUCCESS;
9362 case SQL_ATTR_ASYNC_ENABLE:
9363 if (val != (SQLPOINTER) SQL_ASYNC_ENABLE_OFF) {
9364 e01s02:
9365 setstat(s, -1, "option value changed", "01S02");
9366 return SQL_SUCCESS_WITH_INFO;
9367 }
9368 return SQL_SUCCESS;
9369 case SQL_CONCURRENCY:
9370 if (val != (SQLPOINTER) SQL_CONCUR_LOCK) {
9371 goto e01s02;
9372 }
9373 return SQL_SUCCESS;
9374 #ifdef SQL_ATTR_CURSOR_SENSITIVITY
9375 case SQL_ATTR_CURSOR_SENSITIVITY:
9376 if (val != (SQLPOINTER) SQL_UNSPECIFIED) {
9377 goto e01s02;
9378 }
9379 return SQL_SUCCESS;
9380 #endif
9381 case SQL_ATTR_QUERY_TIMEOUT:
9382 return SQL_SUCCESS;
9383 case SQL_ATTR_RETRIEVE_DATA:
9384 if (val != (SQLPOINTER) SQL_RD_ON &&
9385 val != (SQLPOINTER) SQL_RD_OFF) {
9386 goto e01s02;
9387 }
9388 s->retr_data = uval;
9389 return SQL_SUCCESS;
9390 case SQL_ROWSET_SIZE:
9391 case SQL_ATTR_ROW_ARRAY_SIZE:
9392 if (uval < 1) {
9393 setstat(s, -1, "invalid rowset size", "HY000");
9394 return SQL_ERROR;
9395 } else {
9396 SQLUSMALLINT *rst = &s->row_status1;
9397
9398 if (uval > 1) {
9399 rst = xmalloc(sizeof (SQLUSMALLINT) * uval);
9400 if (!rst) {
9401 return nomem(s);
9402 }
9403 }
9404 if (s->row_status0 != &s->row_status1) {
9405 freep(&s->row_status0);
9406 }
9407 s->row_status0 = rst;
9408 s->rowset_size = uval;
9409 }
9410 return SQL_SUCCESS;
9411 case SQL_ATTR_ROW_STATUS_PTR:
9412 s->row_status = (SQLUSMALLINT *) val;
9413 return SQL_SUCCESS;
9414 case SQL_ATTR_ROWS_FETCHED_PTR:
9415 s->row_count = (SQLULEN *) val;
9416 return SQL_SUCCESS;
9417 case SQL_ATTR_PARAM_BIND_OFFSET_PTR:
9418 s->parm_bind_offs = (SQLULEN *) val;
9419 return SQL_SUCCESS;
9420 case SQL_ATTR_PARAM_BIND_TYPE:
9421 s->parm_bind_type = uval;
9422 return SQL_SUCCESS;
9423 case SQL_ATTR_PARAM_OPERATION_PTR:
9424 s->parm_oper = (SQLUSMALLINT *) val;
9425 return SQL_SUCCESS;
9426 case SQL_ATTR_PARAM_STATUS_PTR:
9427 s->parm_status = (SQLUSMALLINT *) val;
9428 return SQL_SUCCESS;
9429 case SQL_ATTR_PARAMS_PROCESSED_PTR:
9430 s->parm_proc = (SQLULEN *) val;
9431 return SQL_SUCCESS;
9432 case SQL_ATTR_PARAMSET_SIZE:
9433 if (uval < 1) {
9434 goto e01s02;
9435 }
9436 s->paramset_size = uval;
9437 s->paramset_count = 0;
9438 return SQL_SUCCESS;
9439 case SQL_ATTR_ROW_BIND_TYPE:
9440 s->bind_type = uval;
9441 return SQL_SUCCESS;
9442 case SQL_ATTR_ROW_BIND_OFFSET_PTR:
9443 s->bind_offs = (SQLULEN *) val;
9444 return SQL_SUCCESS;
9445 case SQL_ATTR_USE_BOOKMARKS:
9446 if (val != (SQLPOINTER) SQL_UB_OFF &&
9447 val != (SQLPOINTER) SQL_UB_ON &&
9448 val != (SQLPOINTER) SQL_UB_VARIABLE) {
9449 goto e01s02;
9450 }
9451 if (*s->ov3 && val == (SQLPOINTER) SQL_UB_VARIABLE) {
9452 s->bkmrk = SQL_UB_VARIABLE;
9453 return SQL_SUCCESS;
9454 }
9455 if (val == (SQLPOINTER) SQL_UB_VARIABLE) {
9456 s->bkmrk = SQL_UB_ON;
9457 goto e01s02;
9458 }
9459 s->bkmrk = (val == (SQLPOINTER) SQL_UB_ON) ? SQL_UB_ON : SQL_UB_OFF;
9460 return SQL_SUCCESS;
9461 case SQL_ATTR_FETCH_BOOKMARK_PTR:
9462 s->bkmrkptr = (SQLINTEGER *) val;
9463 return SQL_SUCCESS;
9464 case SQL_ATTR_MAX_ROWS:
9465 s->max_rows = uval;
9466 return SQL_SUCCESS;
9467 case SQL_ATTR_MAX_LENGTH:
9468 if (val != (SQLPOINTER) 1000000000) {
9469 goto e01s02;
9470 }
9471 return SQL_SUCCESS;
9472 #ifdef SQL_ATTR_METADATA_ID
9473 case SQL_ATTR_METADATA_ID:
9474 if (val != (SQLPOINTER) SQL_FALSE) {
9475 goto e01s02;
9476 }
9477 return SQL_SUCCESS;
9478 #endif
9479 }
9480 return drvunimplstmt(stmt);
9481 }
9482
9483 #if (defined(HAVE_UNIXODBC) && (HAVE_UNIXODBC)) || !defined(WINTERFACE)
9484 /**
9485 * Set option on HSTMT.
9486 * @param stmt statement handle
9487 * @param attr attribute to be set
9488 * @param val input buffer (attribute value)
9489 * @param buflen length of input buffer
9490 * @result ODBC error code
9491 */
9492
9493 SQLRETURN SQL_API
SQLSetStmtAttr(SQLHSTMT stmt,SQLINTEGER attr,SQLPOINTER val,SQLINTEGER buflen)9494 SQLSetStmtAttr(SQLHSTMT stmt, SQLINTEGER attr, SQLPOINTER val,
9495 SQLINTEGER buflen)
9496 {
9497 SQLRETURN ret;
9498
9499 HSTMT_LOCK(stmt);
9500 ret = drvsetstmtattr(stmt, attr, val, buflen);
9501 HSTMT_UNLOCK(stmt);
9502 return ret;
9503 }
9504 #endif
9505
9506 #ifdef WINTERFACE
9507 /**
9508 * Set option on HSTMT (UNICODE version).
9509 * @param stmt statement handle
9510 * @param attr attribute to be set
9511 * @param val input buffer (attribute value)
9512 * @param buflen length of input buffer
9513 * @result ODBC error code
9514 */
9515
9516 SQLRETURN SQL_API
SQLSetStmtAttrW(SQLHSTMT stmt,SQLINTEGER attr,SQLPOINTER val,SQLINTEGER buflen)9517 SQLSetStmtAttrW(SQLHSTMT stmt, SQLINTEGER attr, SQLPOINTER val,
9518 SQLINTEGER buflen)
9519 {
9520 SQLRETURN ret;
9521
9522 HSTMT_LOCK(stmt);
9523 ret = drvsetstmtattr(stmt, attr, val, buflen);
9524 HSTMT_UNLOCK(stmt);
9525 return ret;
9526 }
9527 #endif
9528
9529 /**
9530 * Internal get option of HSTMT.
9531 * @param stmt statement handle
9532 * @param opt option to be retrieved
9533 * @param param output buffer
9534 * @result ODBC error code
9535 */
9536
9537 static SQLRETURN
drvgetstmtoption(SQLHSTMT stmt,SQLUSMALLINT opt,SQLPOINTER param)9538 drvgetstmtoption(SQLHSTMT stmt, SQLUSMALLINT opt, SQLPOINTER param)
9539 {
9540 STMT *s = (STMT *) stmt;
9541 SQLUINTEGER *ret = (SQLUINTEGER *) param;
9542
9543 switch (opt) {
9544 case SQL_QUERY_TIMEOUT:
9545 *ret = 0;
9546 return SQL_SUCCESS;
9547 case SQL_CURSOR_TYPE:
9548 *ret = s->curtype;
9549 return SQL_SUCCESS;
9550 case SQL_ROW_NUMBER:
9551 if (s->s3stmt) {
9552 *ret = (s->s3stmt_rownum < 0) ?
9553 SQL_ROW_NUMBER_UNKNOWN : (s->s3stmt_rownum + 1);
9554 } else {
9555 *ret = (s->rowp < 0) ? SQL_ROW_NUMBER_UNKNOWN : (s->rowp + 1);
9556 }
9557 return SQL_SUCCESS;
9558 case SQL_ASYNC_ENABLE:
9559 *ret = SQL_ASYNC_ENABLE_OFF;
9560 return SQL_SUCCESS;
9561 case SQL_CONCURRENCY:
9562 *ret = SQL_CONCUR_LOCK;
9563 return SQL_SUCCESS;
9564 case SQL_ATTR_RETRIEVE_DATA:
9565 *ret = s->retr_data;
9566 return SQL_SUCCESS;
9567 case SQL_ROWSET_SIZE:
9568 case SQL_ATTR_ROW_ARRAY_SIZE:
9569 *ret = s->rowset_size;
9570 return SQL_SUCCESS;
9571 case SQL_ATTR_MAX_ROWS:
9572 *ret = s->max_rows;
9573 return SQL_SUCCESS;
9574 case SQL_ATTR_MAX_LENGTH:
9575 *ret = 1000000000;
9576 return SQL_SUCCESS;
9577 }
9578 return drvunimplstmt(stmt);
9579 }
9580
9581 /**
9582 * Get option of HSTMT.
9583 * @param stmt statement handle
9584 * @param opt option to be retrieved
9585 * @param param output buffer
9586 * @result ODBC error code
9587 */
9588
9589 SQLRETURN SQL_API
SQLGetStmtOption(SQLHSTMT stmt,SQLUSMALLINT opt,SQLPOINTER param)9590 SQLGetStmtOption(SQLHSTMT stmt, SQLUSMALLINT opt, SQLPOINTER param)
9591 {
9592 SQLRETURN ret;
9593
9594 HSTMT_LOCK(stmt);
9595 ret = drvgetstmtoption(stmt, opt, param);
9596 HSTMT_UNLOCK(stmt);
9597 return ret;
9598 }
9599
9600 #ifdef WINTERFACE
9601 /**
9602 * Get option of HSTMT (UNICODE version).
9603 * @param stmt statement handle
9604 * @param opt option to be retrieved
9605 * @param param output buffer
9606 * @result ODBC error code
9607 */
9608
9609 SQLRETURN SQL_API
SQLGetStmtOptionW(SQLHSTMT stmt,SQLUSMALLINT opt,SQLPOINTER param)9610 SQLGetStmtOptionW(SQLHSTMT stmt, SQLUSMALLINT opt, SQLPOINTER param)
9611 {
9612 SQLRETURN ret;
9613
9614 HSTMT_LOCK(stmt);
9615 ret = drvgetstmtoption(stmt, opt, param);
9616 HSTMT_UNLOCK(stmt);
9617 return ret;
9618 }
9619 #endif
9620
9621 /**
9622 * Internal set option on HSTMT.
9623 * @param stmt statement handle
9624 * @param opt option to be set
9625 * @param param input buffer (option value)
9626 * @result ODBC error code
9627 */
9628
9629 static SQLRETURN
drvsetstmtoption(SQLHSTMT stmt,SQLUSMALLINT opt,SQLUINTEGER param)9630 drvsetstmtoption(SQLHSTMT stmt, SQLUSMALLINT opt, SQLUINTEGER param)
9631 {
9632 STMT *s = (STMT *) stmt;
9633
9634 switch (opt) {
9635 case SQL_CURSOR_TYPE:
9636 if (param == SQL_CURSOR_FORWARD_ONLY) {
9637 s->curtype = param;
9638 } else {
9639 s->curtype = SQL_CURSOR_STATIC;
9640 }
9641 if (param != SQL_CURSOR_FORWARD_ONLY &&
9642 param != SQL_CURSOR_STATIC) {
9643 goto e01s02;
9644 }
9645 return SQL_SUCCESS;
9646 case SQL_ASYNC_ENABLE:
9647 if (param != SQL_ASYNC_ENABLE_OFF) {
9648 goto e01s02;
9649 }
9650 return SQL_SUCCESS;
9651 case SQL_CONCURRENCY:
9652 if (param != SQL_CONCUR_LOCK) {
9653 goto e01s02;
9654 }
9655 return SQL_SUCCESS;
9656 case SQL_QUERY_TIMEOUT:
9657 return SQL_SUCCESS;
9658 case SQL_RETRIEVE_DATA:
9659 if (param != SQL_RD_ON && param != SQL_RD_OFF) {
9660 e01s02:
9661 setstat(s, -1, "option value changed", "01S02");
9662 return SQL_SUCCESS_WITH_INFO;
9663 }
9664 s->retr_data = (int) param;
9665 return SQL_SUCCESS;
9666 case SQL_ROWSET_SIZE:
9667 case SQL_ATTR_ROW_ARRAY_SIZE:
9668 if (param < 1) {
9669 setstat(s, -1, "invalid rowset size", "HY000");
9670 return SQL_ERROR;
9671 } else {
9672 SQLUSMALLINT *rst = &s->row_status1;
9673
9674 if (param > 1) {
9675 rst = xmalloc(sizeof (SQLUSMALLINT) * param);
9676 if (!rst) {
9677 return nomem(s);
9678 }
9679 }
9680 if (s->row_status0 != &s->row_status1) {
9681 freep(&s->row_status0);
9682 }
9683 s->row_status0 = rst;
9684 s->rowset_size = param;
9685 }
9686 return SQL_SUCCESS;
9687 case SQL_ATTR_MAX_ROWS:
9688 s->max_rows = param;
9689 return SQL_SUCCESS;
9690 case SQL_ATTR_MAX_LENGTH:
9691 if (param != 1000000000) {
9692 goto e01s02;
9693 }
9694 return SQL_SUCCESS;
9695 }
9696 return drvunimplstmt(stmt);
9697 }
9698
9699 /**
9700 * Set option on HSTMT.
9701 * @param stmt statement handle
9702 * @param opt option to be set
9703 * @param param input buffer (option value)
9704 * @result ODBC error code
9705 */
9706
9707 SQLRETURN SQL_API
SQLSetStmtOption(SQLHSTMT stmt,SQLUSMALLINT opt,SETSTMTOPTION_LAST_ARG_TYPE param)9708 SQLSetStmtOption(SQLHSTMT stmt, SQLUSMALLINT opt,
9709 SETSTMTOPTION_LAST_ARG_TYPE param)
9710 {
9711 SQLRETURN ret;
9712
9713 HSTMT_LOCK(stmt);
9714 ret = drvsetstmtoption(stmt, opt, (SQLUINTEGER) param);
9715 HSTMT_UNLOCK(stmt);
9716 return ret;
9717 }
9718
9719 #ifdef WINTERFACE
9720 /**
9721 * Set option on HSTMT (UNICODE version).
9722 * @param stmt statement handle
9723 * @param opt option to be set
9724 * @param param input buffer (option value)
9725 * @result ODBC error code
9726 */
9727
9728 SQLRETURN SQL_API
SQLSetStmtOptionW(SQLHSTMT stmt,SQLUSMALLINT opt,SETSTMTOPTION_LAST_ARG_TYPE param)9729 SQLSetStmtOptionW(SQLHSTMT stmt, SQLUSMALLINT opt,
9730 SETSTMTOPTION_LAST_ARG_TYPE param)
9731 {
9732 SQLRETURN ret;
9733
9734 HSTMT_LOCK(stmt);
9735 ret = drvsetstmtoption(stmt, opt, (SQLUINTEGER) param);
9736 HSTMT_UNLOCK(stmt);
9737 return ret;
9738 }
9739 #endif
9740
9741 /**
9742 * Check for unbound result columns.
9743 * @param s statement handle
9744 * @result ODBC error code
9745 */
9746
9747 static SQLRETURN
chkunbound(STMT * s)9748 chkunbound(STMT *s)
9749 {
9750 int i;
9751
9752 if (!s->bindcols || s->nbindcols < s->ncols) {
9753 unbound:
9754 setstat(s, -1, "unbound columns", (*s->ov3) ? "HY000" : "S1000");
9755 return SQL_ERROR;
9756 }
9757 for (i = 0; i < s->ncols; i++) {
9758 BINDCOL *b = &s->bindcols[i];
9759
9760 if (b->type == SQL_UNKNOWN_TYPE || !b->valp) {
9761 goto unbound;
9762 }
9763 }
9764 return SQL_SUCCESS;
9765 }
9766
9767 /**
9768 * Internal handler to setup parameters for positional updates
9769 * from bound user buffers.
9770 * @param s statement handle
9771 * @param stmt SQLite3 statement pointer
9772 * @param i result set column index
9773 * @param si SQLite3 parameter index
9774 * @param rsi result set row index
9775 * @result ODBC error code
9776 */
9777
9778 static SQLRETURN
setposbind(STMT * s,sqlite3_stmt * stmt,int i,int si,int rsi)9779 setposbind(STMT *s, sqlite3_stmt *stmt, int i, int si, int rsi)
9780 {
9781 DBC *d = (DBC *) s->dbc;
9782 SQLPOINTER dp = 0;
9783 SQLLEN *lp = 0;
9784 BINDCOL *b = &s->bindcols[i];
9785 COL *c = &s->cols[i];
9786 char strbuf[128], *cp;
9787
9788 if (b->valp) {
9789 if (s->bind_type != SQL_BIND_BY_COLUMN) {
9790 dp = (SQLPOINTER) ((char *) b->valp + s->bind_type * rsi);
9791 } else {
9792 dp = (SQLPOINTER) ((char *) b->valp + b->max * rsi);
9793 }
9794 if (s->bind_offs) {
9795 dp = (SQLPOINTER) ((char *) dp + *s->bind_offs);
9796 }
9797 }
9798 if (b->lenp) {
9799 if (s->bind_type != SQL_BIND_BY_COLUMN) {
9800 lp = (SQLLEN *) ((char *) b->lenp + s->bind_type * rsi);
9801 } else {
9802 lp = b->lenp + rsi;
9803 }
9804 if (s->bind_offs) {
9805 lp = (SQLLEN *) ((char *) lp + *s->bind_offs);
9806 }
9807 }
9808 if (!dp || !lp) {
9809 setstat(s, -1, "unbound column in positional update",
9810 (*s->ov3) ? "HY000" : "S1000");
9811 return SQL_ERROR;
9812 }
9813 if (*lp == SQL_NULL_DATA) {
9814 sqlite3_bind_null(stmt, si);
9815 if (d->trace) {
9816 fprintf(d->trace, "-- parameter %d: NULL\n", si);
9817 fflush(d->trace);
9818 }
9819 return SQL_SUCCESS;
9820 }
9821 switch (b->type) {
9822 case SQL_C_UTINYINT:
9823 case SQL_C_TINYINT:
9824 case SQL_C_STINYINT:
9825 sqlite3_bind_int(stmt, si, *(SQLCHAR *) dp);
9826 if (d->trace) {
9827 fprintf(d->trace, "-- parameter %d: %d\n", si, *(SQLCHAR *) dp);
9828 fflush(d->trace);
9829 }
9830 break;
9831 #ifdef SQL_BIT
9832 case SQL_C_BIT:
9833 sqlite3_bind_int(stmt, si, (*(SQLCHAR *) dp) ? 1 : 0);
9834 if (d->trace) {
9835 fprintf(d->trace, "-- parameter %d: %d\n", si,
9836 (*(SQLCHAR *) dp) ? 1 : 0);
9837 fflush(d->trace);
9838 }
9839 break;
9840 #endif
9841 case SQL_C_USHORT:
9842 sqlite3_bind_int(stmt, si, *(SQLUSMALLINT *) dp);
9843 if (d->trace) {
9844 fprintf(d->trace, "-- parameter %d: %d\n", si,
9845 *(SQLUSMALLINT *) dp);
9846 fflush(d->trace);
9847 }
9848 break;
9849 case SQL_C_SHORT:
9850 case SQL_C_SSHORT:
9851 sqlite3_bind_int(stmt, si, *(SQLSMALLINT *) dp);
9852 if (d->trace) {
9853 fprintf(d->trace, "-- parameter %d: %d\n", si,
9854 *(SQLSMALLINT *) dp);
9855 fflush(d->trace);
9856 }
9857 break;
9858 case SQL_C_ULONG:
9859 sqlite3_bind_int(stmt, si, *(SQLUINTEGER *) dp);
9860 if (d->trace) {
9861 fprintf(d->trace, "-- parameter %d: %ld\n", si,
9862 (long) *(SQLUINTEGER *) dp);
9863 fflush(d->trace);
9864 }
9865 break;
9866 case SQL_C_LONG:
9867 case SQL_C_SLONG:
9868 sqlite3_bind_int(stmt, si, *(SQLINTEGER *) dp);
9869 if (d->trace) {
9870 fprintf(d->trace, "-- parameter %d: %ld\n", si,
9871 (long) *(SQLINTEGER *) dp);
9872 fflush(d->trace);
9873 }
9874 break;
9875 #ifdef SQL_BIGINT
9876 case SQL_C_UBIGINT:
9877 case SQL_C_SBIGINT:
9878 sqlite3_bind_int64(stmt, si, *(SQLBIGINT *) dp);
9879 if (d->trace) {
9880 fprintf(d->trace,
9881 #ifdef _WIN32
9882 "-- parameter %d: %I64d\n",
9883 #else
9884 "-- parameter %d: %lld\n",
9885 #endif
9886 si, (sqlite_int64) *(SQLBIGINT *) dp);
9887 fflush(d->trace);
9888 }
9889 break;
9890 #endif
9891 case SQL_C_FLOAT:
9892 sqlite3_bind_double(stmt, si, *(float *) dp);
9893 if (d->trace) {
9894 fprintf(d->trace, "-- parameter %d: %g\n", si,
9895 *(float *) dp);
9896 fflush(d->trace);
9897 }
9898 break;
9899 case SQL_C_DOUBLE:
9900 sqlite3_bind_double(stmt, si, *(double *) dp);
9901 if (d->trace) {
9902 fprintf(d->trace, "-- parameter %d: %g\n", si,
9903 *(double *) dp);
9904 fflush(d->trace);
9905 }
9906 break;
9907 case SQL_C_BINARY:
9908 sqlite3_bind_blob(stmt, si, (char *) dp, *lp, SQLITE_STATIC);
9909 if (d->trace) {
9910 fprintf(d->trace, "-- parameter %d: [BLOB]\n", si);
9911 fflush(d->trace);
9912 }
9913 break;
9914 #ifdef WCHARSUPPORT
9915 case SQL_C_WCHAR:
9916 cp = uc_to_utf((SQLWCHAR *) dp, *lp);
9917 if (!cp) {
9918 return nomem(s);
9919 }
9920 sqlite3_bind_text(stmt, si, cp, -1, SQLITE_TRANSIENT);
9921 if (d->trace) {
9922 fprintf(d->trace, "-- parameter %d: '%s'\n", si, cp);
9923 fflush(d->trace);
9924 }
9925 uc_free(cp);
9926 break;
9927 #endif
9928 case SQL_C_CHAR:
9929 #if defined(_WIN32) || defined(_WIN64)
9930 if (*s->oemcp) {
9931 cp = wmb_to_utf((char *) dp, *lp);
9932 if (!cp) {
9933 return nomem(s);
9934 }
9935 sqlite3_bind_text(stmt, si, cp, -1, SQLITE_TRANSIENT);
9936 if (d->trace) {
9937 fprintf(d->trace, "-- parameter %d: '%s'\n", si, cp);
9938 fflush(d->trace);
9939 }
9940 uc_free(cp);
9941 } else
9942 #endif
9943 {
9944 if (*lp == SQL_NTS) {
9945 sqlite3_bind_text(stmt, si, (char *) dp, -1,
9946 SQLITE_STATIC);
9947 if (d->trace) {
9948 fprintf(d->trace, "-- parameter %d: '%s'\n", si,
9949 (char *) dp);
9950 fflush(d->trace);
9951 }
9952 } else {
9953 sqlite3_bind_text(stmt, si, (char *) dp, *lp,
9954 SQLITE_STATIC);
9955 if (d->trace) {
9956 fprintf(d->trace, "-- parameter %d: '%*s'\n", si,
9957 (int) *lp, (char *) dp);
9958 fflush(d->trace);
9959 }
9960 }
9961 }
9962 break;
9963 #ifdef SQL_C_TYPE_DATE
9964 case SQL_C_TYPE_DATE:
9965 #endif
9966 case SQL_C_DATE:
9967 if (*s->jdconv) {
9968 int a, b, x1, x2, y, m, dd;
9969 double v;
9970
9971 y = ((DATE_STRUCT *) dp)->year;
9972 m = ((DATE_STRUCT *) dp)->month;
9973 dd = ((DATE_STRUCT *) dp)->day;
9974 if (m <= 2) {
9975 y--;
9976 m += 12;
9977 }
9978 a = y / 100;
9979 b = 2 - a + (a / 4);
9980 x1 = 36525 * (y + 4716) / 100;
9981 x2 = 306001 * (m + 1) / 10000;
9982 v = x1 + x2 + dd + b - 1524.5;
9983 sqlite3_bind_double(stmt, si, v);
9984 if (d->trace) {
9985 fprintf(d->trace, "-- parameter %d: %g\n", si, v);
9986 fflush(d->trace);
9987 }
9988 } else {
9989 sprintf(strbuf, "%04d-%02d-%02d",
9990 ((DATE_STRUCT *) dp)->year,
9991 ((DATE_STRUCT *) dp)->month,
9992 ((DATE_STRUCT *) dp)->day);
9993 sqlite3_bind_text(stmt, si, strbuf, -1, SQLITE_TRANSIENT);
9994 if (d->trace) {
9995 fprintf(d->trace, "-- parameter %d: '%s'\n", si, strbuf);
9996 fflush(d->trace);
9997 }
9998 }
9999 break;
10000 #ifdef SQL_C_TYPE_TIME
10001 case SQL_C_TYPE_TIME:
10002 #endif
10003 case SQL_C_TIME:
10004 if (*s->jdconv) {
10005 double v;
10006
10007 v = 2451544.5 +
10008 (((TIME_STRUCT *) dp)->hour * 3600000.0 +
10009 ((TIME_STRUCT *) dp)->minute * 60000.0 +
10010 ((TIME_STRUCT *) dp)->second * 1000.0) / 86400000.0;
10011 sqlite3_bind_double(stmt, si, v);
10012 if (d->trace) {
10013 fprintf(d->trace, "-- parameter %d: %g\n", si, v);
10014 fflush(d->trace);
10015 }
10016 } else {
10017 sprintf(strbuf, "%02d:%02d:%02d",
10018 ((TIME_STRUCT *) dp)->hour,
10019 ((TIME_STRUCT *) dp)->minute,
10020 ((TIME_STRUCT *) dp)->second);
10021 sqlite3_bind_text(stmt, si, strbuf, -1, SQLITE_TRANSIENT);
10022 if (d->trace) {
10023 fprintf(d->trace, "-- parameter %d: '%s'\n", si, strbuf);
10024 fflush(d->trace);
10025 }
10026 }
10027 break;
10028 #ifdef SQL_C_TYPE_TIMESTAMP
10029 case SQL_C_TYPE_TIMESTAMP:
10030 #endif
10031 case SQL_C_TIMESTAMP:
10032 if (*s->jdconv) {
10033 int a, b, x1, x2, y, m, dd;
10034 double v;
10035
10036 y = ((TIMESTAMP_STRUCT *) dp)->year;
10037 m = ((TIMESTAMP_STRUCT *) dp)->month;
10038 dd = ((TIMESTAMP_STRUCT *) dp)->day;
10039 if (m <= 2) {
10040 y--;
10041 m += 12;
10042 }
10043 a = y / 100;
10044 b = 2 - a + (a / 4);
10045 x1 = 36525 * (y + 4716) / 100;
10046 x2 = 306001 * (m + 1) / 10000;
10047 v = x1 + x2 + dd + b - 1524.5 +
10048 (((TIMESTAMP_STRUCT *) dp)->hour * 3600000.0 +
10049 ((TIMESTAMP_STRUCT *) dp)->minute * 60000.0 +
10050 ((TIMESTAMP_STRUCT *) dp)->second * 1000.0 +
10051 ((TIMESTAMP_STRUCT *) dp)->fraction / 1.0E6)
10052 / 86400000.0;
10053 sqlite3_bind_double(stmt, si, v);
10054 if (d->trace) {
10055 fprintf(d->trace, "-- parameter %d: %g\n", si, v);
10056 fflush(d->trace);
10057 }
10058 } else {
10059 int frac;
10060
10061 frac = (int) ((TIMESTAMP_STRUCT *) dp)->fraction;
10062 frac /= 1000000;
10063 frac = frac % 1000;
10064 if (frac < 0) {
10065 frac = 0;
10066 }
10067 if (c->prec && c->prec <= 16) {
10068 sprintf(strbuf, "%04d-%02d-%02d %02d:%02d:00.000",
10069 ((TIMESTAMP_STRUCT *) dp)->year,
10070 ((TIMESTAMP_STRUCT *) dp)->month,
10071 ((TIMESTAMP_STRUCT *) dp)->day,
10072 ((TIMESTAMP_STRUCT *) dp)->hour,
10073 ((TIMESTAMP_STRUCT *) dp)->minute);
10074 } else if (c->prec && c->prec <= 19) {
10075 sprintf(strbuf, "%04d-%02d-%02d %02d:%02d:%02d.000",
10076 ((TIMESTAMP_STRUCT *) dp)->year,
10077 ((TIMESTAMP_STRUCT *) dp)->month,
10078 ((TIMESTAMP_STRUCT *) dp)->day,
10079 ((TIMESTAMP_STRUCT *) dp)->hour,
10080 ((TIMESTAMP_STRUCT *) dp)->minute,
10081 ((TIMESTAMP_STRUCT *) dp)->second);
10082 } else {
10083 sprintf(strbuf, "%04d-%02d-%02d %02d:%02d:%02d.%03d",
10084 ((TIMESTAMP_STRUCT *) dp)->year,
10085 ((TIMESTAMP_STRUCT *) dp)->month,
10086 ((TIMESTAMP_STRUCT *) dp)->day,
10087 ((TIMESTAMP_STRUCT *) dp)->hour,
10088 ((TIMESTAMP_STRUCT *) dp)->minute,
10089 ((TIMESTAMP_STRUCT *) dp)->second,
10090 frac);
10091 }
10092 sqlite3_bind_text(stmt, si, strbuf, -1, SQLITE_TRANSIENT);
10093 if (d->trace) {
10094 fprintf(d->trace, "-- parameter %d: '%s'\n", si, strbuf);
10095 fflush(d->trace);
10096 }
10097 }
10098 break;
10099 default:
10100 setstat(s, -1, "unsupported column type in positional update",
10101 (*s->ov3) ? "HY000" : "S1000");
10102 return SQL_ERROR;
10103 }
10104 return SQL_SUCCESS;
10105 }
10106
10107 /**
10108 * Internal handler to setup parameters for positional updates
10109 * from driver side result set.
10110 * @param s statement handle
10111 * @param stmt SQLite3 statement pointer
10112 * @param i result set column index
10113 * @param si SQLite3 parameter index
10114 * @param rsi result set row index
10115 * @result ODBC error code
10116 */
10117
10118 static SQLRETURN
setposibind(STMT * s,sqlite3_stmt * stmt,int i,int si,int rsi)10119 setposibind(STMT *s, sqlite3_stmt *stmt, int i, int si, int rsi)
10120 {
10121 DBC *d = (DBC *) s->dbc;
10122 char **data;
10123 int pos;
10124
10125 pos = s->rowprs;
10126 if (pos < 0) {
10127 setstat(s, -1, "row out of range", (*s->ov3) ? "HY107" : "S1107");
10128 return SQL_ERROR;
10129 }
10130 pos += rsi;
10131 data = s->rows + s->ncols + (pos * s->ncols) + i;
10132 if (*data == NULL) {
10133 sqlite3_bind_null(stmt, si);
10134 if (d->trace) {
10135 fprintf(d->trace, "-- parameter %d: NULL\n", si);
10136 fflush(d->trace);
10137 }
10138 } else {
10139 sqlite3_bind_text(stmt, si, *data, -1, SQLITE_STATIC);
10140 if (d->trace) {
10141 fprintf(d->trace, "-- parameter %d: '%s'\n", si, *data);
10142 fflush(d->trace);
10143 }
10144 }
10145 return SQL_SUCCESS;
10146 }
10147
10148 /**
10149 * Internal handler to refresh user buffers from driver side result set.
10150 * @param s statement handle
10151 * @param rsi result set row index
10152 * @result ODBC error code
10153 */
10154
10155 static SQLRETURN
setposrefr(STMT * s,int rsi)10156 setposrefr(STMT *s, int rsi)
10157 {
10158 int i, withinfo = 0;
10159 SQLRETURN ret = SQL_SUCCESS;
10160
10161 for (i = 0; s->bindcols && i < s->ncols; i++) {
10162 BINDCOL *b = &s->bindcols[i];
10163 SQLPOINTER dp = 0;
10164 SQLLEN *lp = 0;
10165
10166 b->offs = 0;
10167 if (b->valp) {
10168 if (s->bind_type != SQL_BIND_BY_COLUMN) {
10169 dp = (SQLPOINTER) ((char *) b->valp + s->bind_type * rsi);
10170 } else {
10171 dp = (SQLPOINTER) ((char *) b->valp + b->max * rsi);
10172 }
10173 if (s->bind_offs) {
10174 dp = (SQLPOINTER) ((char *) dp + *s->bind_offs);
10175 }
10176 }
10177 if (b->lenp) {
10178 if (s->bind_type != SQL_BIND_BY_COLUMN) {
10179 lp = (SQLLEN *) ((char *) b->lenp + s->bind_type * rsi);
10180 } else {
10181 lp = b->lenp + rsi;
10182 }
10183 if (s->bind_offs) {
10184 lp = (SQLLEN *) ((char *) lp + *s->bind_offs);
10185 }
10186 }
10187 if (dp || lp) {
10188 int rowp = s->rowp;
10189
10190 s->rowp = s->rowprs + rsi;
10191 ret = getrowdata(s, (SQLUSMALLINT) i, b->type, dp,
10192 b->max, lp, 0);
10193 s->rowp = rowp;
10194 if (!SQL_SUCCEEDED(ret)) {
10195 s->row_status0[rsi] = SQL_ROW_ERROR;
10196 break;
10197 }
10198 if (ret != SQL_SUCCESS) {
10199 withinfo = 1;
10200 #ifdef SQL_ROW_SUCCESS_WITH_INFO
10201 s->row_status0[rsi] = SQL_ROW_SUCCESS_WITH_INFO;
10202 #endif
10203 }
10204 }
10205 }
10206 if (SQL_SUCCEEDED(ret)) {
10207 ret = withinfo ? SQL_SUCCESS_WITH_INFO : SQL_SUCCESS;
10208 }
10209 return ret;
10210 }
10211
10212 /**
10213 * Internal set position on result in HSTMT.
10214 * @param stmt statement handle
10215 * @param row row to be positioned
10216 * @param op operation code
10217 * @param lock locking type
10218 * @result ODBC error code
10219 */
10220
10221 static SQLRETURN
drvsetpos(SQLHSTMT stmt,SQLSETPOSIROW row,SQLUSMALLINT op,SQLUSMALLINT lock)10222 drvsetpos(SQLHSTMT stmt, SQLSETPOSIROW row, SQLUSMALLINT op, SQLUSMALLINT lock)
10223 {
10224 STMT *s = (STMT *) stmt;
10225 DBC *d = (DBC *) s->dbc;
10226 int rowp, i, k, rc, nretry = 0;
10227 dstr *sql = 0;
10228 const char *endp;
10229 sqlite3_stmt *s3stmt = NULL;
10230 SQLRETURN ret;
10231
10232 if (lock != SQL_LOCK_NO_CHANGE) {
10233 setstat(s, -1, "unsupported locking mode",
10234 (*s->ov3) ? "HY000" : "S1000");
10235 return SQL_ERROR;
10236 }
10237 if (s->isselect != 1 || s->curtype != SQL_CURSOR_STATIC) {
10238 setstat(s, -1, "incompatible statement",
10239 (*s->ov3) ? "HY000" : "S1000");
10240 return SQL_ERROR;
10241 }
10242 if (op == SQL_ADD) {
10243 if (s->one_tbl <= 0) {
10244 setstat(s, -1, "incompatible rowset",
10245 (*s->ov3) ? "HY000" : "S1000");
10246 return SQL_ERROR;
10247 }
10248 if (row == 0 || row > s->rowset_size + 1) {
10249 goto rowoor;
10250 }
10251 ret = chkunbound(s);
10252 if (ret != SQL_SUCCESS) {
10253 return ret;
10254 }
10255 sql = dsappend(sql, "INSERT INTO ");
10256 if (s->dyncols[0].db && s->dyncols[0].db[0]) {
10257 sql = dsappendq(sql, s->dyncols[0].db);
10258 sql = dsappend(sql, ".");
10259 }
10260 sql = dsappendq(sql, s->dyncols[0].table);
10261 for (i = 0; i < s->ncols; i++) {
10262 sql = dsappend(sql, (i > 0) ? "," : "(");
10263 sql = dsappendq(sql, s->dyncols[i].column);
10264 }
10265 sql = dsappend(sql, ") VALUES ");
10266 for (i = 0; i < s->ncols; i++) {
10267 sql = dsappend(sql, (i > 0) ? ",?" : "(?");
10268 }
10269 sql = dsappend(sql, ")");
10270 if (dserr(sql)) {
10271 dsfree(sql);
10272 return nomem(s);
10273 }
10274 #if defined(HAVE_SQLITE3PREPAREV2) && (HAVE_SQLITE3PREPAREV2)
10275 dbtraceapi(d, "sqlite3_prepare_v2", dsval(sql));
10276 #else
10277 dbtraceapi(d, "sqlite3_prepare", dsval(sql));
10278 #endif
10279 do {
10280 s3stmt = NULL;
10281 #if defined(HAVE_SQLITE3PREPAREV2) && (HAVE_SQLITE3PREPAREV2)
10282 rc = sqlite3_prepare_v2(d->sqlite, dsval(sql), -1,
10283 &s3stmt, &endp);
10284 #else
10285 rc = sqlite3_prepare(d->sqlite, dsval(sql), -1,
10286 &s3stmt, &endp);
10287 #endif
10288 if (rc != SQLITE_OK) {
10289 if (s3stmt) {
10290 sqlite3_finalize(s3stmt);
10291 s3stmt = NULL;
10292 }
10293 }
10294 } while (rc == SQLITE_SCHEMA && (++nretry) < 2);
10295 dbtracerc(d, rc, NULL);
10296 dsfree(sql);
10297 if (rc != SQLITE_OK) {
10298 istmterr:
10299 setstat(s, rc, "%s (%d)", (*s->ov3) ? "HY000" : "S1000",
10300 sqlite3_errmsg(d->sqlite), rc);
10301 if (s3stmt) {
10302 dbtraceapi(d, "sqlite3_finalize", NULL);
10303 sqlite3_finalize(s3stmt);
10304 }
10305 return SQL_ERROR;
10306 }
10307 for (i = 0, k = 1; s->bindcols && i < s->ncols; i++) {
10308 ret = setposbind(s, s3stmt, i, k, row - 1);
10309 if (ret != SQL_SUCCESS) {
10310 dbtraceapi(d, "sqlite3_finalize", NULL);
10311 sqlite3_finalize(s3stmt);
10312 return ret;
10313 }
10314 k++;
10315 }
10316 rc = sqlite3_step(s3stmt);
10317 if (rc != SQLITE_DONE) {
10318 goto istmterr;
10319 }
10320 sqlite3_finalize(s3stmt);
10321 if (sqlite3_changes(d->sqlite) > 0 && row <= s->rowset_size) {
10322 if (s->row_status0) {
10323 s->row_status0[row - 1] = SQL_ROW_ADDED;
10324 }
10325 if (s->row_status) {
10326 s->row_status[row - 1] = SQL_ROW_ADDED;
10327 }
10328 }
10329 return SQL_SUCCESS;
10330 } else if (op == SQL_UPDATE || op == SQL_DELETE) {
10331 if (s->one_tbl <= 0 || s->has_pk <= 0) {
10332 setstat(s, -1, "incompatible rowset",
10333 (*s->ov3) ? "HY000" : "S1000");
10334 return SQL_ERROR;
10335 }
10336 if (row == 0) {
10337 ret = SQL_SUCCESS;
10338 for (i = 1; i <= s->rowset_size; i++) {
10339 ret = drvsetpos(stmt, i, op, lock);
10340 if (!SQL_SUCCEEDED(ret)) {
10341 break;
10342 }
10343 }
10344 return ret;
10345 }
10346 if (row > s->rowset_size) {
10347 goto rowoor;
10348 }
10349 }
10350 if (op != SQL_POSITION && op != SQL_REFRESH &&
10351 op != SQL_DELETE && op != SQL_UPDATE) {
10352 return drvunimplstmt(stmt);
10353 }
10354 if (op == SQL_POSITION) {
10355 rowp = s->rowp + row - 1;
10356 if (!s->rows || row == 0 || rowp < -1 || rowp >= s->nrows) {
10357 rowoor:
10358 setstat(s, -1, "row out of range", (*s->ov3) ? "HY107" : "S1107");
10359 return SQL_ERROR;
10360 }
10361 s->rowp = rowp;
10362 } else if (op == SQL_REFRESH) {
10363 if (row > s->rowset_size) {
10364 goto rowoor;
10365 }
10366 if (row == 0) {
10367 ret = SQL_SUCCESS;
10368 for (i = 0; i < s->rowset_size; i++) {
10369 ret = setposrefr(s, i);
10370 if (!SQL_SUCCEEDED(ret)) {
10371 break;
10372 }
10373 }
10374 return ret;
10375 }
10376 return setposrefr(s, row - 1);
10377 } else if (op == SQL_DELETE) {
10378 sql = dsappend(sql, "DELETE FROM ");
10379 if (s->dyncols[0].db && s->dyncols[0].db[0]) {
10380 sql = dsappendq(sql, s->dyncols[0].db);
10381 sql = dsappend(sql, ".");
10382 }
10383 sql = dsappendq(sql, s->dyncols[0].table);
10384 for (i = k = 0; i < s->ncols; i++) {
10385 if (s->dyncols[i].ispk <= 0) {
10386 continue;
10387 }
10388 sql = dsappend(sql, (k > 0) ? " AND " : " WHERE ");
10389 sql = dsappendq(sql, s->dyncols[i].column);
10390 sql = dsappend(sql, " = ?");
10391 k++;
10392 }
10393 if (dserr(sql)) {
10394 dsfree(sql);
10395 return nomem(s);
10396 }
10397 #if defined(HAVE_SQLITE3PREPAREV2) && (HAVE_SQLITE3PREPAREV2)
10398 dbtraceapi(d, "sqlite3_prepare_v2", dsval(sql));
10399 #else
10400 dbtraceapi(d, "sqlite3_prepare", dsval(sql));
10401 #endif
10402 do {
10403 s3stmt = NULL;
10404 #if defined(HAVE_SQLITE3PREPAREV2) && (HAVE_SQLITE3PREPAREV2)
10405 rc = sqlite3_prepare_v2(d->sqlite, dsval(sql), -1,
10406 &s3stmt, &endp);
10407 #else
10408 rc = sqlite3_prepare(d->sqlite, dsval(sql), -1,
10409 &s3stmt, &endp);
10410 #endif
10411 if (rc != SQLITE_OK) {
10412 if (s3stmt) {
10413 sqlite3_finalize(s3stmt);
10414 s3stmt = NULL;
10415 }
10416 }
10417 } while (rc == SQLITE_SCHEMA && (++nretry) < 2);
10418 dbtracerc(d, rc, NULL);
10419 dsfree(sql);
10420 if (rc != SQLITE_OK) {
10421 dstmterr:
10422 setstat(s, rc, "%s (%d)", (*s->ov3) ? "HY000" : "S1000",
10423 sqlite3_errmsg(d->sqlite), rc);
10424 if (s3stmt) {
10425 dbtraceapi(d, "sqlite3_finalize", NULL);
10426 sqlite3_finalize(s3stmt);
10427 }
10428 return SQL_ERROR;
10429 }
10430 for (i = 0, k = 1; s->bindcols && i < s->ncols; i++) {
10431 if (s->dyncols[i].ispk <= 0) {
10432 continue;
10433 }
10434 ret = setposibind(s, s3stmt, i, k, row - 1);
10435 if (ret != SQL_SUCCESS) {
10436 dbtraceapi(d, "sqlite3_finalize", NULL);
10437 sqlite3_finalize(s3stmt);
10438 return ret;
10439 }
10440 k++;
10441 }
10442 rc = sqlite3_step(s3stmt);
10443 if (rc != SQLITE_DONE) {
10444 goto dstmterr;
10445 }
10446 sqlite3_finalize(s3stmt);
10447 if (sqlite3_changes(d->sqlite) > 0) {
10448 if (s->row_status0) {
10449 s->row_status0[row - 1] = SQL_ROW_DELETED;
10450 }
10451 if (s->row_status) {
10452 s->row_status[row - 1] = SQL_ROW_DELETED;
10453 }
10454 }
10455 return SQL_SUCCESS;
10456 } else if (op == SQL_UPDATE) {
10457 ret = chkunbound(s);
10458 if (ret != SQL_SUCCESS) {
10459 return ret;
10460 }
10461 sql = dsappend(sql, "UPDATE ");
10462 if (s->dyncols[0].db && s->dyncols[0].db[0]) {
10463 sql = dsappendq(sql, s->dyncols[0].db);
10464 sql = dsappend(sql, ".");
10465 }
10466 sql = dsappendq(sql, s->dyncols[0].table);
10467 for (i = 0; i < s->ncols; i++) {
10468 sql = dsappend(sql, (i > 0) ? ", " : " SET ");
10469 sql = dsappendq(sql, s->dyncols[i].column);
10470 sql = dsappend(sql, " = ?");
10471 }
10472 for (i = k = 0; i < s->ncols; i++) {
10473 if (s->dyncols[i].ispk <= 0) {
10474 continue;
10475 }
10476 sql = dsappend(sql, (k > 0) ? " AND " : " WHERE ");
10477 sql = dsappendq(sql, s->dyncols[i].column);
10478 sql = dsappend(sql, " = ?");
10479 k++;
10480 }
10481 if (dserr(sql)) {
10482 dsfree(sql);
10483 return nomem(s);
10484 }
10485 #if defined(HAVE_SQLITE3PREPAREV2) && (HAVE_SQLITE3PREPAREV2)
10486 dbtraceapi(d, "sqlite3_prepare_v2", dsval(sql));
10487 #else
10488 dbtraceapi(d, "sqlite3_prepare", dsval(sql));
10489 #endif
10490 do {
10491 s3stmt = NULL;
10492 #if defined(HAVE_SQLITE3PREPAREV2) && (HAVE_SQLITE3PREPAREV2)
10493 rc = sqlite3_prepare_v2(d->sqlite, dsval(sql), -1,
10494 &s3stmt, &endp);
10495 #else
10496 rc = sqlite3_prepare(d->sqlite, dsval(sql), -1,
10497 &s3stmt, &endp);
10498 #endif
10499 if (rc != SQLITE_OK) {
10500 if (s3stmt) {
10501 sqlite3_finalize(s3stmt);
10502 s3stmt = NULL;
10503 }
10504 }
10505 } while (rc == SQLITE_SCHEMA && (++nretry) < 2);
10506 dbtracerc(d, rc, NULL);
10507 dsfree(sql);
10508 if (rc != SQLITE_OK) {
10509 ustmterr:
10510 setstat(s, rc, "%s (%d)", (*s->ov3) ? "HY000" : "S1000",
10511 sqlite3_errmsg(d->sqlite), rc);
10512 if (s3stmt) {
10513 dbtraceapi(d, "sqlite3_finalize", NULL);
10514 sqlite3_finalize(s3stmt);
10515 }
10516 return SQL_ERROR;
10517 }
10518 for (i = 0, k = 1; s->bindcols && i < s->ncols; i++) {
10519 ret = setposbind(s, s3stmt, i, k, row - 1);
10520 if (ret != SQL_SUCCESS) {
10521 dbtraceapi(d, "sqlite3_finalize", NULL);
10522 sqlite3_finalize(s3stmt);
10523 return ret;
10524 }
10525 k++;
10526 }
10527 for (i = 0; s->bindcols && i < s->ncols; i++) {
10528 if (s->dyncols[i].ispk <= 0) {
10529 continue;
10530 }
10531 ret = setposibind(s, s3stmt, i, k, row - 1);
10532 if (ret != SQL_SUCCESS) {
10533 dbtraceapi(d, "sqlite3_finalize", NULL);
10534 sqlite3_finalize(s3stmt);
10535 return ret;
10536 }
10537 k++;
10538 }
10539 rc = sqlite3_step(s3stmt);
10540 if (rc != SQLITE_DONE) {
10541 goto ustmterr;
10542 }
10543 sqlite3_finalize(s3stmt);
10544 if (sqlite3_changes(d->sqlite) > 0) {
10545 if (s->row_status0) {
10546 s->row_status0[row - 1] = SQL_ROW_UPDATED;
10547 }
10548 if (s->row_status) {
10549 s->row_status[row - 1] = SQL_ROW_UPDATED;
10550 }
10551 }
10552 return SQL_SUCCESS;
10553 }
10554 return SQL_SUCCESS;
10555 }
10556
10557 /**
10558 * Set position on result in HSTMT.
10559 * @param stmt statement handle
10560 * @param row row to be positioned
10561 * @param op operation code
10562 * @param lock locking type
10563 * @result ODBC error code
10564 */
10565
10566 SQLRETURN SQL_API
SQLSetPos(SQLHSTMT stmt,SQLSETPOSIROW row,SQLUSMALLINT op,SQLUSMALLINT lock)10567 SQLSetPos(SQLHSTMT stmt, SQLSETPOSIROW row, SQLUSMALLINT op, SQLUSMALLINT lock)
10568 {
10569 SQLRETURN ret;
10570
10571 HSTMT_LOCK(stmt);
10572 ret = drvsetpos(stmt, row, op, lock);
10573 HSTMT_UNLOCK(stmt);
10574 return ret;
10575 }
10576
10577 /**
10578 * Internal perform bulk operation on HSTMT.
10579 * @param stmt statement handle
10580 * @param op operation to be performed
10581 * @result ODBC error code
10582 */
10583
10584 static SQLRETURN
drvbulkoperations(SQLHSTMT stmt,SQLSMALLINT op)10585 drvbulkoperations(SQLHSTMT stmt, SQLSMALLINT op)
10586 {
10587 STMT *s = (STMT *) stmt;
10588 DBC *d = (DBC *) s->dbc;
10589 int row, i, k, rc, nretry = 0;
10590 dstr *sql = 0;
10591 const char *endp;
10592 sqlite3_stmt *s3stmt = NULL;
10593 SQLRETURN ret;
10594
10595 if (s->isselect != 1 || s->curtype != SQL_CURSOR_STATIC) {
10596 setstat(s, -1, "incompatible statement",
10597 (*s->ov3) ? "HY000" : "S1000");
10598 return SQL_ERROR;
10599 }
10600 if (op == SQL_ADD) {
10601 if (s->one_tbl <= 0) {
10602 setstat(s, -1, "incompatible rowset",
10603 (*s->ov3) ? "HY000" : "S1000");
10604 return SQL_ERROR;
10605 }
10606 ret = chkunbound(s);
10607 if (ret != SQL_SUCCESS) {
10608 return ret;
10609 }
10610 sql = dsappend(sql, "INSERT INTO ");
10611 if (s->dyncols[0].db && s->dyncols[0].db[0]) {
10612 sql = dsappendq(sql, s->dyncols[0].db);
10613 sql = dsappend(sql, ".");
10614 }
10615 sql = dsappendq(sql, s->dyncols[0].table);
10616 for (i = 0; i < s->ncols; i++) {
10617 sql = dsappend(sql, (i > 0) ? "," : "(");
10618 sql = dsappendq(sql, s->dyncols[i].column);
10619 }
10620 sql = dsappend(sql, ") VALUES ");
10621 for (i = 0; i < s->ncols; i++) {
10622 sql = dsappend(sql, (i > 0) ? ",?" : "(?");
10623 }
10624 sql = dsappend(sql, ")");
10625 if (dserr(sql)) {
10626 dsfree(sql);
10627 return nomem(s);
10628 }
10629 #if defined(HAVE_SQLITE3PREPAREV2) && (HAVE_SQLITE3PREPAREV2)
10630 dbtraceapi(d, "sqlite3_prepare_v2", dsval(sql));
10631 #else
10632 dbtraceapi(d, "sqlite3_prepare", dsval(sql));
10633 #endif
10634 do {
10635 s3stmt = NULL;
10636 #if defined(HAVE_SQLITE3PREPAREV2) && (HAVE_SQLITE3PREPAREV2)
10637 rc = sqlite3_prepare_v2(d->sqlite, dsval(sql), -1,
10638 &s3stmt, &endp);
10639 #else
10640 rc = sqlite3_prepare(d->sqlite, dsval(sql), -1,
10641 &s3stmt, &endp);
10642 #endif
10643 if (rc != SQLITE_OK) {
10644 if (s3stmt) {
10645 sqlite3_finalize(s3stmt);
10646 s3stmt = NULL;
10647 }
10648 }
10649 } while (rc == SQLITE_SCHEMA && (++nretry) < 2);
10650 dbtracerc(d, rc, NULL);
10651 dsfree(sql);
10652 if (rc != SQLITE_OK) {
10653 setstat(s, rc, "%s (%d)", (*s->ov3) ? "HY000" : "S1000",
10654 sqlite3_errmsg(d->sqlite), rc);
10655 if (s3stmt) {
10656 dbtraceapi(d, "sqlite3_finalize", NULL);
10657 sqlite3_finalize(s3stmt);
10658 }
10659 return SQL_ERROR;
10660 }
10661 for (row = 0; row < s->rowset_size; row++) {
10662 for (i = 0, k = 1; s->bindcols && i < s->ncols; i++) {
10663 ret = setposbind(s, s3stmt, i, k, row);
10664 if (ret != SQL_SUCCESS) {
10665 istmterr:
10666 if (s->row_status0) {
10667 s->row_status0[row] = SQL_ROW_ERROR;
10668 }
10669 if (s->row_status) {
10670 s->row_status[row] = SQL_ROW_ERROR;
10671 }
10672 dbtraceapi(d, "sqlite3_finalize", NULL);
10673 sqlite3_finalize(s3stmt);
10674 return ret;
10675 }
10676 k++;
10677 }
10678 rc = sqlite3_step(s3stmt);
10679 if (rc != SQLITE_DONE) {
10680 setstat(s, rc, "%s (%d)", (*s->ov3) ? "HY000" : "S1000",
10681 sqlite3_errmsg(d->sqlite), rc);
10682 ret = SQL_ERROR;
10683 goto istmterr;
10684 }
10685 if (sqlite3_changes(d->sqlite) > 0) {
10686 if (s->row_status0) {
10687 s->row_status0[row] = SQL_ROW_ADDED;
10688 }
10689 if (s->row_status) {
10690 s->row_status[row] = SQL_ROW_ADDED;
10691 }
10692 }
10693 if (s->bkmrk == SQL_UB_VARIABLE &&
10694 s->bkmrkcol.type == SQL_C_VARBOOKMARK &&
10695 s->bkmrkcol.valp) {
10696 SQLPOINTER *val;
10697
10698 if (s->bind_type != SQL_BIND_BY_COLUMN) {
10699 val = (SQLPOINTER)
10700 ((char *) s->bkmrkcol.valp + s->bind_type * row);
10701 } else {
10702 val = (SQLPOINTER)
10703 ((char *) s->bkmrkcol.valp + s->bkmrkcol.max * row);
10704 }
10705 if (s->bind_offs) {
10706 val = (SQLPOINTER) ((char *) val + *s->bind_offs);
10707 }
10708 *(sqlite_int64 *) val = sqlite3_last_insert_rowid(d->sqlite);
10709 if (s->bkmrkcol.lenp) {
10710 SQLLEN *ival;
10711
10712 if (s->bind_type != SQL_BIND_BY_COLUMN) {
10713 ival = (SQLLEN *)
10714 ((char *) s->bkmrkcol.lenp + s->bind_type * row);
10715 } else {
10716 ival = &s->bkmrkcol.lenp[row];
10717 }
10718 if (s->bind_offs) {
10719 ival = (SQLLEN *) ((char *) ival + *s->bind_offs);
10720 }
10721 *ival = sizeof (sqlite_int64);
10722 }
10723 }
10724 dbtraceapi(d, "sqlite3_reset", NULL);
10725 sqlite3_reset(s3stmt);
10726 }
10727 dbtraceapi(d, "sqlite3_finalize", NULL);
10728 sqlite3_finalize(s3stmt);
10729 return SQL_SUCCESS;
10730 } else if (op == SQL_DELETE_BY_BOOKMARK) {
10731 if (s->has_rowid < 0 ||
10732 s->bkmrk != SQL_UB_VARIABLE ||
10733 s->bkmrkcol.type != SQL_C_VARBOOKMARK ||
10734 !s->bkmrkcol.valp) {
10735 setstat(s, -1, "incompatible rowset",
10736 (*s->ov3) ? "HY000" : "S1000");
10737 return SQL_ERROR;
10738 }
10739 sql = dsappend(sql, "DELETE FROM ");
10740 if (s->dyncols[0].db && s->dyncols[0].db[0]) {
10741 sql = dsappendq(sql, s->dyncols[0].db);
10742 sql = dsappend(sql, ".");
10743 }
10744 sql = dsappendq(sql, s->dyncols[0].table);
10745 sql = dsappend(sql, " WHERE ");
10746 sql = dsappendq(sql, s->dyncols[0].column);
10747 sql = dsappend(sql, " = ?");
10748 if (dserr(sql)) {
10749 dsfree(sql);
10750 return nomem(s);
10751 }
10752 #if defined(HAVE_SQLITE3PREPAREV2) && (HAVE_SQLITE3PREPAREV2)
10753 dbtraceapi(d, "sqlite3_prepare_v2", dsval(sql));
10754 #else
10755 dbtraceapi(d, "sqlite3_prepare", dsval(sql));
10756 #endif
10757 do {
10758 s3stmt = NULL;
10759 #if defined(HAVE_SQLITE3PREPAREV2) && (HAVE_SQLITE3PREPAREV2)
10760 rc = sqlite3_prepare_v2(d->sqlite, dsval(sql), -1,
10761 &s3stmt, &endp);
10762 #else
10763 rc = sqlite3_prepare(d->sqlite, dsval(sql), -1,
10764 &s3stmt, &endp);
10765 #endif
10766 if (rc != SQLITE_OK) {
10767 if (s3stmt) {
10768 sqlite3_finalize(s3stmt);
10769 s3stmt = NULL;
10770 }
10771 }
10772 } while (rc == SQLITE_SCHEMA && (++nretry) < 2);
10773 dbtracerc(d, rc, NULL);
10774 dsfree(sql);
10775 if (rc != SQLITE_OK) {
10776 setstat(s, rc, "%s (%d)", (*s->ov3) ? "HY000" : "S1000",
10777 sqlite3_errmsg(d->sqlite), rc);
10778 if (s3stmt) {
10779 dbtraceapi(d, "sqlite3_finalize", NULL);
10780 sqlite3_finalize(s3stmt);
10781 }
10782 return SQL_ERROR;
10783 }
10784 for (row = 0; row < s->rowset_size; row++) {
10785 SQLPOINTER *val;
10786 sqlite_int64 rowid;
10787
10788 if (s->bind_type != SQL_BIND_BY_COLUMN) {
10789 val = (SQLPOINTER)
10790 ((char *) s->bkmrkcol.valp + s->bind_type * row);
10791 } else {
10792 val = (SQLPOINTER)
10793 ((char *) s->bkmrkcol.valp + s->bkmrkcol.max * row);
10794 }
10795 if (s->bind_offs) {
10796 val = (SQLPOINTER) ((char *) val + *s->bind_offs);
10797 }
10798 if (s->bkmrkcol.lenp) {
10799 SQLLEN *ival;
10800
10801 if (s->bind_type != SQL_BIND_BY_COLUMN) {
10802 ival = (SQLLEN *)
10803 ((char *) s->bkmrkcol.lenp + s->bind_type * row);
10804 } else {
10805 ival = &s->bkmrkcol.lenp[row];
10806 }
10807 if (s->bind_offs) {
10808 ival = (SQLLEN *) ((char *) ival + *s->bind_offs);
10809 }
10810 if (*ival != sizeof (sqlite_int64)) {
10811 continue;
10812 }
10813 }
10814 rowid = *(sqlite_int64 *) val;
10815 sqlite3_bind_int64(s3stmt, 1, rowid);
10816 if (d->trace) {
10817 fprintf(d->trace,
10818 #ifdef _WIN32
10819 "-- parameter 1: %I64d\n",
10820 #else
10821 "-- parameter 1: %lld\n",
10822 #endif
10823 rowid);
10824 fflush(d->trace);
10825 }
10826 rc = sqlite3_step(s3stmt);
10827 if (rc != SQLITE_DONE) {
10828 setstat(s, rc, "%s (%d)", (*s->ov3) ? "HY000" : "S1000",
10829 sqlite3_errmsg(d->sqlite), rc);
10830 if (s->row_status0) {
10831 s->row_status0[row] = SQL_ROW_ERROR;
10832 }
10833 if (s->row_status) {
10834 s->row_status[row] = SQL_ROW_ERROR;
10835 }
10836 dbtraceapi(d, "sqlite3_finalize", NULL);
10837 sqlite3_finalize(s3stmt);
10838 return SQL_ERROR;
10839 }
10840 if (sqlite3_changes(d->sqlite) > 0) {
10841 if (s->row_status0) {
10842 s->row_status0[row] = SQL_ROW_DELETED;
10843 }
10844 if (s->row_status) {
10845 s->row_status[row] = SQL_ROW_DELETED;
10846 }
10847 }
10848 dbtraceapi(d, "sqlite3_reset", NULL);
10849 sqlite3_reset(s3stmt);
10850 }
10851 dbtraceapi(d, "sqlite3_finalize", NULL);
10852 sqlite3_finalize(s3stmt);
10853 return SQL_SUCCESS;
10854 } else if (op == SQL_UPDATE_BY_BOOKMARK) {
10855 if (s->has_rowid < 0 ||
10856 s->bkmrk != SQL_UB_VARIABLE ||
10857 s->bkmrkcol.type != SQL_C_VARBOOKMARK ||
10858 !s->bkmrkcol.valp) {
10859 setstat(s, -1, "incompatible rowset",
10860 (*s->ov3) ? "HY000" : "S1000");
10861 return SQL_ERROR;
10862 }
10863 ret = chkunbound(s);
10864 if (ret != SQL_SUCCESS) {
10865 return ret;
10866 }
10867 sql = dsappend(sql, "UPDATE ");
10868 if (s->dyncols[0].db && s->dyncols[0].db[0]) {
10869 sql = dsappendq(sql, s->dyncols[0].db);
10870 sql = dsappend(sql, ".");
10871 }
10872 sql = dsappendq(sql, s->dyncols[0].table);
10873 for (i = 0, k = 0; i < s->ncols; i++) {
10874 sql = dsappend(sql, (k > 0) ? ", " : " SET ");
10875 sql = dsappendq(sql, s->dyncols[i].column);
10876 sql = dsappend(sql, " = ?");
10877 k++;
10878 }
10879 sql = dsappend(sql, " WHERE ");
10880 sql = dsappendq(sql, s->dyncols[s->has_rowid].column);
10881 sql = dsappend(sql, " = ?");
10882 if (dserr(sql)) {
10883 dsfree(sql);
10884 return nomem(s);
10885 }
10886 #if defined(HAVE_SQLITE3PREPAREV2) && (HAVE_SQLITE3PREPAREV2)
10887 dbtraceapi(d, "sqlite3_prepare_v2", dsval(sql));
10888 #else
10889 dbtraceapi(d, "sqlite3_prepare", dsval(sql));
10890 #endif
10891 do {
10892 s3stmt = NULL;
10893 #if defined(HAVE_SQLITE3PREPAREV2) && (HAVE_SQLITE3PREPAREV2)
10894 rc = sqlite3_prepare_v2(d->sqlite, dsval(sql), -1,
10895 &s3stmt, &endp);
10896 #else
10897 rc = sqlite3_prepare(d->sqlite, dsval(sql), -1,
10898 &s3stmt, &endp);
10899 #endif
10900 if (rc != SQLITE_OK) {
10901 if (s3stmt) {
10902 sqlite3_finalize(s3stmt);
10903 s3stmt = NULL;
10904 }
10905 }
10906 } while (rc == SQLITE_SCHEMA && (++nretry) < 2);
10907 dbtracerc(d, rc, NULL);
10908 dsfree(sql);
10909 if (rc != SQLITE_OK) {
10910 setstat(s, rc, "%s (%d)", (*s->ov3) ? "HY000" : "S1000",
10911 sqlite3_errmsg(d->sqlite), rc);
10912 if (s3stmt) {
10913 dbtraceapi(d, "sqlite3_finalize", NULL);
10914 sqlite3_finalize(s3stmt);
10915 }
10916 return SQL_ERROR;
10917 }
10918 for (row = 0; row < s->rowset_size; row++) {
10919 SQLPOINTER *val;
10920 sqlite_int64 rowid;
10921
10922 if (s->bind_type != SQL_BIND_BY_COLUMN) {
10923 val = (SQLPOINTER)
10924 ((char *) s->bkmrkcol.valp + s->bind_type * row);
10925 } else {
10926 val = (SQLPOINTER)
10927 ((char *) s->bkmrkcol.valp + s->bkmrkcol.max * row);
10928 }
10929 if (s->bind_offs) {
10930 val = (SQLPOINTER) ((char *) val + *s->bind_offs);
10931 }
10932 if (s->bkmrkcol.lenp) {
10933 SQLLEN *ival;
10934
10935 if (s->bind_type != SQL_BIND_BY_COLUMN) {
10936 ival = (SQLLEN *)
10937 ((char *) s->bkmrkcol.lenp + s->bind_type * row);
10938 } else {
10939 ival = &s->bkmrkcol.lenp[row];
10940 }
10941 if (s->bind_offs) {
10942 ival = (SQLLEN *) ((char *) ival + *s->bind_offs);
10943 }
10944 if (*ival != sizeof (sqlite_int64)) {
10945 continue;
10946 }
10947 }
10948 for (i = 0, k = 1; s->bindcols && i < s->ncols; i++) {
10949 ret = setposbind(s, s3stmt, i, k, row);
10950 if (ret != SQL_SUCCESS) {
10951 ustmterr:
10952 if (s->row_status0) {
10953 s->row_status0[row] = SQL_ROW_ERROR;
10954 }
10955 if (s->row_status) {
10956 s->row_status[row] = SQL_ROW_ERROR;
10957 }
10958 dbtraceapi(d, "sqlite3_finalize", NULL);
10959 sqlite3_finalize(s3stmt);
10960 return ret;
10961 }
10962 k++;
10963 }
10964 rowid = *(sqlite_int64 *) val;
10965 sqlite3_bind_int64(s3stmt, k, rowid);
10966 if (d->trace) {
10967 fprintf(d->trace,
10968 #ifdef _WIN32
10969 "-- parameter %d: %I64d\n",
10970 #else
10971 "-- parameter %d: %lld\n",
10972 #endif
10973 k, rowid);
10974 fflush(d->trace);
10975 }
10976 rc = sqlite3_step(s3stmt);
10977 if (rc != SQLITE_DONE) {
10978 setstat(s, rc, "%s (%d)", (*s->ov3) ? "HY000" : "S1000",
10979 sqlite3_errmsg(d->sqlite), rc);
10980 ret = SQL_ERROR;
10981 goto ustmterr;
10982 }
10983 if (sqlite3_changes(d->sqlite) > 0) {
10984 if (s->row_status0) {
10985 s->row_status0[row] = SQL_ROW_UPDATED;
10986 }
10987 if (s->row_status) {
10988 s->row_status[row] = SQL_ROW_UPDATED;
10989 }
10990 }
10991 dbtraceapi(d, "sqlite3_reset", NULL);
10992 sqlite3_reset(s3stmt);
10993 }
10994 dbtraceapi(d, "sqlite3_finalize", NULL);
10995 sqlite3_finalize(s3stmt);
10996 return SQL_SUCCESS;
10997 }
10998 setstat(s, -1, "unsupported operation", (*s->ov3) ? "HY000" : "S1000");
10999 return SQL_ERROR;
11000 }
11001
11002 /**
11003 * Perform bulk operation on HSTMT.
11004 * @param stmt statement handle
11005 * @param oper operation to be performed
11006 * @result ODBC error code
11007 */
11008
11009 SQLRETURN SQL_API
SQLBulkOperations(SQLHSTMT stmt,SQLSMALLINT oper)11010 SQLBulkOperations(SQLHSTMT stmt, SQLSMALLINT oper)
11011 {
11012 SQLRETURN ret;
11013
11014 HSTMT_LOCK(stmt);
11015 ret = drvbulkoperations(stmt, oper);
11016 HSTMT_UNLOCK(stmt);
11017 return ret;
11018 }
11019
11020
11021 /**
11022 * Function not implemented.
11023 */
11024
11025 SQLRETURN SQL_API
SQLSetScrollOptions(SQLHSTMT stmt,SQLUSMALLINT concur,SQLLEN rowkeyset,SQLUSMALLINT rowset)11026 SQLSetScrollOptions(SQLHSTMT stmt, SQLUSMALLINT concur, SQLLEN rowkeyset,
11027 SQLUSMALLINT rowset)
11028 {
11029 SQLRETURN ret;
11030
11031 HSTMT_LOCK(stmt);
11032 ret = drvunimplstmt(stmt);
11033 HSTMT_UNLOCK(stmt);
11034 return ret;
11035 }
11036
11037 #define strmak(dst, src, max, lenp) { \
11038 int len = strlen(src); \
11039 int cnt = min(len + 1, max); \
11040 strncpy(dst, src, cnt); \
11041 *lenp = (cnt > len) ? len : cnt; \
11042 }
11043
11044 /**
11045 * Internal return information about what this ODBC driver supports.
11046 * @param dbc database connection handle
11047 * @param type type of information to be retrieved
11048 * @param val output buffer
11049 * @param valMax length of output buffer
11050 * @param valLen output length
11051 * @result ODBC error code
11052 */
11053
11054 static SQLRETURN
drvgetinfo(SQLHDBC dbc,SQLUSMALLINT type,SQLPOINTER val,SQLSMALLINT valMax,SQLSMALLINT * valLen)11055 drvgetinfo(SQLHDBC dbc, SQLUSMALLINT type, SQLPOINTER val, SQLSMALLINT valMax,
11056 SQLSMALLINT *valLen)
11057 {
11058 DBC *d;
11059 char dummyc[301];
11060 SQLSMALLINT dummy;
11061 #if defined(_WIN32) || defined(_WIN64)
11062 char pathbuf[301], *drvname;
11063 #else
11064 static char drvname[] = "sqlite3odbc.so";
11065 #endif
11066
11067 if (dbc == SQL_NULL_HDBC) {
11068 return SQL_INVALID_HANDLE;
11069 }
11070 d = (DBC *) dbc;
11071 if (valMax) {
11072 valMax--;
11073 }
11074 if (!valLen) {
11075 valLen = &dummy;
11076 }
11077 if (!val) {
11078 val = dummyc;
11079 valMax = sizeof (dummyc) - 1;
11080 }
11081 switch (type) {
11082 case SQL_MAX_USER_NAME_LEN:
11083 *((SQLSMALLINT *) val) = 16;
11084 *valLen = sizeof (SQLSMALLINT);
11085 break;
11086 case SQL_USER_NAME:
11087 strmak(val, "", valMax, valLen);
11088 break;
11089 case SQL_DRIVER_ODBC_VER:
11090 #if 0
11091 strmak(val, (*d->ov3) ? "03.00" : "02.50", valMax, valLen);
11092 #else
11093 strmak(val, "03.00", valMax, valLen);
11094 #endif
11095 break;
11096 case SQL_ACTIVE_CONNECTIONS:
11097 case SQL_ACTIVE_STATEMENTS:
11098 *((SQLSMALLINT *) val) = 0;
11099 *valLen = sizeof (SQLSMALLINT);
11100 break;
11101 #ifdef SQL_ASYNC_MODE
11102 case SQL_ASYNC_MODE:
11103 *((SQLUINTEGER *) val) = SQL_AM_NONE;
11104 *valLen = sizeof (SQLUINTEGER);
11105 break;
11106 #endif
11107 #ifdef SQL_CREATE_TABLE
11108 case SQL_CREATE_TABLE:
11109 *((SQLUINTEGER *) val) = SQL_CT_CREATE_TABLE |
11110 SQL_CT_COLUMN_DEFAULT |
11111 SQL_CT_COLUMN_CONSTRAINT |
11112 SQL_CT_CONSTRAINT_NON_DEFERRABLE;
11113 *valLen = sizeof (SQLUINTEGER);
11114 break;
11115 #endif
11116 #ifdef SQL_CREATE_VIEW
11117 case SQL_CREATE_VIEW:
11118 *((SQLUINTEGER *) val) = SQL_CV_CREATE_VIEW;
11119 *valLen = sizeof (SQLUINTEGER);
11120 break;
11121 #endif
11122 #ifdef SQL_DDL_INDEX
11123 case SQL_DDL_INDEX:
11124 *((SQLUINTEGER *) val) = SQL_DI_CREATE_INDEX | SQL_DI_DROP_INDEX;
11125 *valLen = sizeof (SQLUINTEGER);
11126 break;
11127 #endif
11128 #ifdef SQL_DROP_TABLE
11129 case SQL_DROP_TABLE:
11130 *((SQLUINTEGER *) val) = SQL_DT_DROP_TABLE;
11131 *valLen = sizeof (SQLUINTEGER);
11132 break;
11133 #endif
11134 #ifdef SQL_DROP_VIEW
11135 case SQL_DROP_VIEW:
11136 *((SQLUINTEGER *) val) = SQL_DV_DROP_VIEW;
11137 *valLen = sizeof (SQLUINTEGER);
11138 break;
11139 #endif
11140 #ifdef SQL_INDEX_KEYWORDS
11141 case SQL_INDEX_KEYWORDS:
11142 *((SQLUINTEGER *) val) = SQL_IK_ALL;
11143 *valLen = sizeof (SQLUINTEGER);
11144 break;
11145 #endif
11146 case SQL_DATA_SOURCE_NAME:
11147 strmak(val, d->dsn ? d->dsn : "", valMax, valLen);
11148 break;
11149 case SQL_DRIVER_NAME:
11150 #if defined(_WIN32) || defined(_WIN64)
11151 GetModuleFileName(hModule, pathbuf, sizeof (pathbuf));
11152 drvname = strrchr(pathbuf, '\\');
11153 if (drvname == NULL) {
11154 drvname = strrchr(pathbuf, '/');
11155 }
11156 if (drvname == NULL) {
11157 drvname = pathbuf;
11158 } else {
11159 drvname++;
11160 }
11161 #endif
11162 strmak(val, drvname, valMax, valLen);
11163 break;
11164 case SQL_DRIVER_VER:
11165 strmak(val, DRIVER_VER_INFO, valMax, valLen);
11166 break;
11167 case SQL_FETCH_DIRECTION:
11168 *((SQLUINTEGER *) val) = SQL_FD_FETCH_NEXT | SQL_FD_FETCH_FIRST |
11169 SQL_FD_FETCH_LAST | SQL_FD_FETCH_PRIOR | SQL_FD_FETCH_ABSOLUTE;
11170 *valLen = sizeof (SQLUINTEGER);
11171 break;
11172 case SQL_ODBC_VER:
11173 strmak(val, (*d->ov3) ? "03.00" : "02.50", valMax, valLen);
11174 break;
11175 case SQL_ODBC_SAG_CLI_CONFORMANCE:
11176 *((SQLSMALLINT *) val) = SQL_OSCC_NOT_COMPLIANT;
11177 *valLen = sizeof (SQLSMALLINT);
11178 break;
11179 case SQL_STANDARD_CLI_CONFORMANCE:
11180 *((SQLUINTEGER *) val) = SQL_SCC_XOPEN_CLI_VERSION1;
11181 *valLen = sizeof (SQLUINTEGER);
11182 break;
11183 case SQL_SQL_CONFORMANCE:
11184 *((SQLUINTEGER *) val) = SQL_SC_SQL92_ENTRY;
11185 *valLen = sizeof (SQLUINTEGER);
11186 break;
11187 case SQL_SERVER_NAME:
11188 case SQL_DATABASE_NAME:
11189 strmak(val, d->dbname ? d->dbname : "", valMax, valLen);
11190 break;
11191 case SQL_SEARCH_PATTERN_ESCAPE:
11192 strmak(val, "\\", valMax, valLen);
11193 break;
11194 case SQL_ODBC_SQL_CONFORMANCE:
11195 *((SQLSMALLINT *) val) = SQL_OSC_MINIMUM;
11196 *valLen = sizeof (SQLSMALLINT);
11197 break;
11198 case SQL_ODBC_API_CONFORMANCE:
11199 *((SQLSMALLINT *) val) = SQL_OAC_LEVEL1;
11200 *valLen = sizeof (SQLSMALLINT);
11201 break;
11202 case SQL_DBMS_NAME:
11203 strmak(val, "SQLite", valMax, valLen);
11204 break;
11205 case SQL_DBMS_VER:
11206 strmak(val, SQLITE_VERSION, valMax, valLen);
11207 break;
11208 case SQL_COLUMN_ALIAS:
11209 case SQL_NEED_LONG_DATA_LEN:
11210 case SQL_OUTER_JOINS:
11211 strmak(val, "Y", valMax, valLen);
11212 break;
11213 case SQL_ROW_UPDATES:
11214 case SQL_ACCESSIBLE_PROCEDURES:
11215 case SQL_PROCEDURES:
11216 case SQL_EXPRESSIONS_IN_ORDERBY:
11217 case SQL_ODBC_SQL_OPT_IEF:
11218 case SQL_LIKE_ESCAPE_CLAUSE:
11219 case SQL_ORDER_BY_COLUMNS_IN_SELECT:
11220 case SQL_ACCESSIBLE_TABLES:
11221 case SQL_MULT_RESULT_SETS:
11222 case SQL_MULTIPLE_ACTIVE_TXN:
11223 case SQL_MAX_ROW_SIZE_INCLUDES_LONG:
11224 strmak(val, "N", valMax, valLen);
11225 break;
11226 #ifdef SQL_CATALOG_NAME
11227 case SQL_CATALOG_NAME:
11228 #if defined(_WIN32) || defined(_WIN64)
11229 strmak(val, d->xcelqrx ? "Y" : "N", valMax, valLen);
11230 #else
11231 strmak(val, "N", valMax, valLen);
11232 #endif
11233 break;
11234 #endif
11235 case SQL_DATA_SOURCE_READ_ONLY:
11236 strmak(val, "N", valMax, valLen);
11237 break;
11238 #ifdef SQL_OJ_CAPABILITIES
11239 case SQL_OJ_CAPABILITIES:
11240 *((SQLUINTEGER *) val) = SQL_OJ_LEFT;
11241 *valLen = sizeof (SQLUINTEGER);
11242 break;
11243 #endif
11244 #ifdef SQL_MAX_IDENTIFIER_LEN
11245 case SQL_MAX_IDENTIFIER_LEN:
11246 *((SQLUSMALLINT *) val) = 255;
11247 *valLen = sizeof (SQLUSMALLINT);
11248 break;
11249 #endif
11250 case SQL_CONCAT_NULL_BEHAVIOR:
11251 *((SQLSMALLINT *) val) = SQL_CB_NULL;
11252 *valLen = sizeof (SQLSMALLINT);
11253 break;
11254 case SQL_CURSOR_COMMIT_BEHAVIOR:
11255 case SQL_CURSOR_ROLLBACK_BEHAVIOR:
11256 *((SQLSMALLINT *) val) = SQL_CB_PRESERVE;
11257 *valLen = sizeof (SQLSMALLINT);
11258 break;
11259 #ifdef SQL_CURSOR_SENSITIVITY
11260 case SQL_CURSOR_SENSITIVITY:
11261 *((SQLUINTEGER *) val) = SQL_UNSPECIFIED;
11262 *valLen = sizeof (SQLUINTEGER);
11263 break;
11264 #endif
11265 case SQL_DEFAULT_TXN_ISOLATION:
11266 *((SQLUINTEGER *) val) = SQL_TXN_SERIALIZABLE;
11267 *valLen = sizeof (SQLUINTEGER);
11268 break;
11269 #ifdef SQL_DESCRIBE_PARAMETER
11270 case SQL_DESCRIBE_PARAMETER:
11271 strmak(val, "Y", valMax, valLen);
11272 break;
11273 #endif
11274 case SQL_TXN_ISOLATION_OPTION:
11275 *((SQLUINTEGER *) val) = SQL_TXN_SERIALIZABLE;
11276 *valLen = sizeof (SQLUINTEGER);
11277 break;
11278 case SQL_IDENTIFIER_CASE:
11279 *((SQLSMALLINT *) val) = SQL_IC_SENSITIVE;
11280 *valLen = sizeof (SQLSMALLINT);
11281 break;
11282 case SQL_IDENTIFIER_QUOTE_CHAR:
11283 strmak(val, "\"", valMax, valLen);
11284 break;
11285 case SQL_MAX_TABLE_NAME_LEN:
11286 case SQL_MAX_COLUMN_NAME_LEN:
11287 *((SQLSMALLINT *) val) = 255;
11288 *valLen = sizeof (SQLSMALLINT);
11289 break;
11290 case SQL_MAX_CURSOR_NAME_LEN:
11291 *((SQLSMALLINT *) val) = 255;
11292 *valLen = sizeof (SQLSMALLINT);
11293 break;
11294 case SQL_MAX_PROCEDURE_NAME_LEN:
11295 *((SQLSMALLINT *) val) = 0;
11296 break;
11297 case SQL_MAX_QUALIFIER_NAME_LEN:
11298 case SQL_MAX_OWNER_NAME_LEN:
11299 *((SQLSMALLINT *) val) = 255;
11300 break;
11301 case SQL_OWNER_TERM:
11302 strmak(val, "", valMax, valLen);
11303 break;
11304 case SQL_PROCEDURE_TERM:
11305 strmak(val, "PROCEDURE", valMax, valLen);
11306 break;
11307 case SQL_QUALIFIER_NAME_SEPARATOR:
11308 strmak(val, ".", valMax, valLen);
11309 break;
11310 case SQL_QUALIFIER_TERM:
11311 #if defined(_WIN32) || defined(_WIN64)
11312 strmak(val, d->xcelqrx ? "catalog" : "", valMax, valLen);
11313 #else
11314 strmak(val, "", valMax, valLen);
11315 #endif
11316 break;
11317 case SQL_QUALIFIER_USAGE:
11318 #if defined(_WIN32) || defined(_WIN64)
11319 *((SQLUINTEGER *) val) = d->xcelqrx ?
11320 (SQL_CU_DML_STATEMENTS | SQL_CU_INDEX_DEFINITION |
11321 SQL_CU_TABLE_DEFINITION) : 0;
11322 #else
11323 *((SQLUINTEGER *) val) = 0;
11324 #endif
11325 *valLen = sizeof (SQLUINTEGER);
11326 break;
11327 case SQL_SCROLL_CONCURRENCY:
11328 *((SQLUINTEGER *) val) = SQL_SCCO_LOCK;
11329 *valLen = sizeof (SQLUINTEGER);
11330 break;
11331 case SQL_SCROLL_OPTIONS:
11332 *((SQLUINTEGER *) val) = SQL_SO_STATIC | SQL_SO_FORWARD_ONLY;
11333 *valLen = sizeof (SQLUINTEGER);
11334 break;
11335 case SQL_TABLE_TERM:
11336 strmak(val, "TABLE", valMax, valLen);
11337 break;
11338 case SQL_TXN_CAPABLE:
11339 *((SQLSMALLINT *) val) = SQL_TC_ALL;
11340 *valLen = sizeof (SQLSMALLINT);
11341 break;
11342 case SQL_CONVERT_FUNCTIONS:
11343 *((SQLUINTEGER *) val) = 0;
11344 *valLen = sizeof (SQLUINTEGER);
11345 break;
11346 case SQL_SYSTEM_FUNCTIONS:
11347 case SQL_NUMERIC_FUNCTIONS:
11348 case SQL_STRING_FUNCTIONS:
11349 case SQL_TIMEDATE_FUNCTIONS:
11350 *((SQLUINTEGER *) val) = 0;
11351 *valLen = sizeof (SQLUINTEGER);
11352 break;
11353 case SQL_CONVERT_BIGINT:
11354 case SQL_CONVERT_BIT:
11355 case SQL_CONVERT_CHAR:
11356 case SQL_CONVERT_DATE:
11357 case SQL_CONVERT_DECIMAL:
11358 case SQL_CONVERT_DOUBLE:
11359 case SQL_CONVERT_FLOAT:
11360 case SQL_CONVERT_INTEGER:
11361 case SQL_CONVERT_LONGVARCHAR:
11362 case SQL_CONVERT_NUMERIC:
11363 case SQL_CONVERT_REAL:
11364 case SQL_CONVERT_SMALLINT:
11365 case SQL_CONVERT_TIME:
11366 case SQL_CONVERT_TIMESTAMP:
11367 case SQL_CONVERT_TINYINT:
11368 case SQL_CONVERT_VARCHAR:
11369 *((SQLUINTEGER *) val) =
11370 SQL_CVT_CHAR | SQL_CVT_NUMERIC | SQL_CVT_DECIMAL |
11371 SQL_CVT_INTEGER | SQL_CVT_SMALLINT | SQL_CVT_FLOAT | SQL_CVT_REAL |
11372 SQL_CVT_DOUBLE | SQL_CVT_VARCHAR | SQL_CVT_LONGVARCHAR |
11373 SQL_CVT_BIT | SQL_CVT_TINYINT | SQL_CVT_BIGINT |
11374 SQL_CVT_DATE | SQL_CVT_TIME | SQL_CVT_TIMESTAMP;
11375 *valLen = sizeof (SQLUINTEGER);
11376 break;
11377 case SQL_CONVERT_BINARY:
11378 case SQL_CONVERT_VARBINARY:
11379 case SQL_CONVERT_LONGVARBINARY:
11380 *((SQLUINTEGER *) val) = 0;
11381 *valLen = sizeof (SQLUINTEGER);
11382 break;
11383 case SQL_POSITIONED_STATEMENTS:
11384 *((SQLUINTEGER *) val) = 0;
11385 *valLen = sizeof (SQLUINTEGER);
11386 break;
11387 case SQL_LOCK_TYPES:
11388 *((SQLUINTEGER *) val) = SQL_LCK_NO_CHANGE;
11389 *valLen = sizeof (SQLUINTEGER);
11390 break;
11391 case SQL_BOOKMARK_PERSISTENCE:
11392 *((SQLUINTEGER *) val) = SQL_BP_SCROLL;
11393 *valLen = sizeof (SQLUINTEGER);
11394 break;
11395 case SQL_UNION:
11396 *((SQLUINTEGER *) val) = SQL_U_UNION | SQL_U_UNION_ALL;
11397 *valLen = sizeof (SQLUINTEGER);
11398 break;
11399 case SQL_OWNER_USAGE:
11400 case SQL_SUBQUERIES:
11401 case SQL_TIMEDATE_ADD_INTERVALS:
11402 case SQL_TIMEDATE_DIFF_INTERVALS:
11403 *((SQLUINTEGER *) val) = 0;
11404 *valLen = sizeof (SQLUINTEGER);
11405 break;
11406 case SQL_QUOTED_IDENTIFIER_CASE:
11407 *((SQLUSMALLINT *) val) = SQL_IC_SENSITIVE;
11408 *valLen = sizeof (SQLUSMALLINT);
11409 break;
11410 case SQL_POS_OPERATIONS:
11411 *((SQLUINTEGER *) val) = SQL_POS_POSITION | SQL_POS_UPDATE |
11412 SQL_POS_DELETE | SQL_POS_ADD | SQL_POS_REFRESH;
11413 *valLen = sizeof (SQLUINTEGER);
11414 break;
11415 case SQL_ALTER_TABLE:
11416 *((SQLUINTEGER *) val) = 0;
11417 *valLen = sizeof (SQLUINTEGER);
11418 break;
11419 case SQL_CORRELATION_NAME:
11420 *((SQLSMALLINT *) val) = SQL_CN_DIFFERENT;
11421 *valLen = sizeof (SQLSMALLINT);
11422 break;
11423 case SQL_NON_NULLABLE_COLUMNS:
11424 *((SQLSMALLINT *) val) = SQL_NNC_NON_NULL;
11425 *valLen = sizeof (SQLSMALLINT);
11426 break;
11427 case SQL_NULL_COLLATION:
11428 *((SQLSMALLINT *) val) = SQL_NC_START;
11429 *valLen = sizeof (SQLSMALLINT);
11430 break;
11431 case SQL_MAX_COLUMNS_IN_GROUP_BY:
11432 case SQL_MAX_COLUMNS_IN_ORDER_BY:
11433 case SQL_MAX_COLUMNS_IN_SELECT:
11434 case SQL_MAX_COLUMNS_IN_TABLE:
11435 case SQL_MAX_ROW_SIZE:
11436 case SQL_MAX_TABLES_IN_SELECT:
11437 *((SQLSMALLINT *) val) = 0;
11438 *valLen = sizeof (SQLSMALLINT);
11439 break;
11440 case SQL_MAX_BINARY_LITERAL_LEN:
11441 case SQL_MAX_CHAR_LITERAL_LEN:
11442 *((SQLUINTEGER *) val) = 0;
11443 *valLen = sizeof (SQLUINTEGER);
11444 break;
11445 case SQL_MAX_COLUMNS_IN_INDEX:
11446 *((SQLSMALLINT *) val) = 0;
11447 *valLen = sizeof (SQLSMALLINT);
11448 break;
11449 case SQL_MAX_INDEX_SIZE:
11450 *((SQLUINTEGER *) val) = 0;
11451 *valLen = sizeof (SQLUINTEGER);
11452 break;
11453 #ifdef SQL_MAX_IDENTIFIER_LENGTH
11454 case SQL_MAX_IDENTIFIER_LENGTH:
11455 *((SQLUINTEGER *) val) = 255;
11456 *valLen = sizeof (SQLUINTEGER);
11457 break;
11458 #endif
11459 case SQL_MAX_STATEMENT_LEN:
11460 *((SQLUINTEGER *) val) = 16384;
11461 *valLen = sizeof (SQLUINTEGER);
11462 break;
11463 case SQL_QUALIFIER_LOCATION:
11464 *((SQLSMALLINT *) val) = SQL_QL_START;
11465 *valLen = sizeof (SQLSMALLINT);
11466 break;
11467 case SQL_GETDATA_EXTENSIONS:
11468 *((SQLUINTEGER *) val) =
11469 SQL_GD_ANY_COLUMN | SQL_GD_ANY_ORDER | SQL_GD_BOUND;
11470 *valLen = sizeof (SQLUINTEGER);
11471 break;
11472 case SQL_STATIC_SENSITIVITY:
11473 *((SQLUINTEGER *) val) = 0;
11474 *valLen = sizeof (SQLUINTEGER);
11475 break;
11476 case SQL_FILE_USAGE:
11477 #if defined(_WIN32) || defined(_WIN64)
11478 *((SQLSMALLINT *) val) =
11479 d->xcelqrx ? SQL_FILE_CATALOG : SQL_FILE_NOT_SUPPORTED;
11480 #else
11481 *((SQLSMALLINT *) val) = SQL_FILE_NOT_SUPPORTED;
11482 #endif
11483 *valLen = sizeof (SQLSMALLINT);
11484 break;
11485 case SQL_GROUP_BY:
11486 *((SQLSMALLINT *) val) = SQL_GB_GROUP_BY_EQUALS_SELECT;
11487 *valLen = sizeof (SQLSMALLINT);
11488 break;
11489 case SQL_KEYWORDS:
11490 strmak(val, "CREATE,SELECT,DROP,DELETE,UPDATE,INSERT,"
11491 "INTO,VALUES,TABLE,INDEX,FROM,SET,WHERE,AND,CURRENT,OF",
11492 valMax, valLen);
11493 break;
11494 case SQL_SPECIAL_CHARACTERS:
11495 #ifdef SQL_COLLATION_SEQ
11496 case SQL_COLLATION_SEQ:
11497 #endif
11498 strmak(val, "", valMax, valLen);
11499 break;
11500 case SQL_BATCH_SUPPORT:
11501 case SQL_BATCH_ROW_COUNT:
11502 case SQL_PARAM_ARRAY_ROW_COUNTS:
11503 *((SQLUINTEGER *) val) = 0;
11504 *valLen = sizeof (SQLUINTEGER);
11505 break;
11506 case SQL_FORWARD_ONLY_CURSOR_ATTRIBUTES1:
11507 *((SQLUINTEGER *) val) = SQL_CA1_NEXT | SQL_CA1_BOOKMARK;
11508 *valLen = sizeof (SQLUINTEGER);
11509 break;
11510 case SQL_STATIC_CURSOR_ATTRIBUTES1:
11511 *((SQLUINTEGER *) val) = SQL_CA1_NEXT | SQL_CA1_ABSOLUTE |
11512 SQL_CA1_RELATIVE | SQL_CA1_BOOKMARK | SQL_CA1_POS_POSITION |
11513 SQL_CA1_POS_DELETE | SQL_CA1_POS_UPDATE | SQL_CA1_POS_REFRESH |
11514 SQL_CA1_LOCK_NO_CHANGE | SQL_CA1_BULK_ADD |
11515 SQL_CA1_BULK_UPDATE_BY_BOOKMARK | SQL_CA1_BULK_DELETE_BY_BOOKMARK;
11516 *valLen = sizeof (SQLUINTEGER);
11517 break;
11518 case SQL_FORWARD_ONLY_CURSOR_ATTRIBUTES2:
11519 case SQL_STATIC_CURSOR_ATTRIBUTES2:
11520 *((SQLUINTEGER *) val) = SQL_CA2_READ_ONLY_CONCURRENCY |
11521 SQL_CA2_LOCK_CONCURRENCY;
11522 *valLen = sizeof (SQLUINTEGER);
11523 break;
11524 case SQL_KEYSET_CURSOR_ATTRIBUTES1:
11525 case SQL_KEYSET_CURSOR_ATTRIBUTES2:
11526 case SQL_DYNAMIC_CURSOR_ATTRIBUTES1:
11527 case SQL_DYNAMIC_CURSOR_ATTRIBUTES2:
11528 *((SQLUINTEGER *) val) = 0;
11529 *valLen = sizeof (SQLUINTEGER);
11530 break;
11531 case SQL_ODBC_INTERFACE_CONFORMANCE:
11532 *((SQLUINTEGER *) val) = SQL_OIC_CORE;
11533 *valLen = sizeof (SQLUINTEGER);
11534 break;
11535 default:
11536 setstatd(d, -1, "unsupported info option %d",
11537 (*d->ov3) ? "HYC00" : "S1C00", type);
11538 return SQL_ERROR;
11539 }
11540 return SQL_SUCCESS;
11541 }
11542
11543 #if (defined(HAVE_UNIXODBC) && (HAVE_UNIXODBC)) || !defined(WINTERFACE)
11544 /**
11545 * Return information about what this ODBC driver supports.
11546 * @param dbc database connection handle
11547 * @param type type of information to be retrieved
11548 * @param val output buffer
11549 * @param valMax length of output buffer
11550 * @param valLen output length
11551 * @result ODBC error code
11552 */
11553
11554 SQLRETURN SQL_API
SQLGetInfo(SQLHDBC dbc,SQLUSMALLINT type,SQLPOINTER val,SQLSMALLINT valMax,SQLSMALLINT * valLen)11555 SQLGetInfo(SQLHDBC dbc, SQLUSMALLINT type, SQLPOINTER val, SQLSMALLINT valMax,
11556 SQLSMALLINT *valLen)
11557 {
11558 SQLRETURN ret;
11559
11560 HDBC_LOCK(dbc);
11561 ret = drvgetinfo(dbc, type, val, valMax, valLen);
11562 HDBC_UNLOCK(dbc);
11563 return ret;
11564 }
11565 #endif
11566
11567 #ifdef WINTERFACE
11568 /**
11569 * Return information about what this ODBC driver supports.
11570 * @param dbc database connection handle
11571 * @param type type of information to be retrieved
11572 * @param val output buffer
11573 * @param valMax length of output buffer
11574 * @param valLen output length
11575 * @result ODBC error code
11576 */
11577
11578 SQLRETURN SQL_API
SQLGetInfoW(SQLHDBC dbc,SQLUSMALLINT type,SQLPOINTER val,SQLSMALLINT valMax,SQLSMALLINT * valLen)11579 SQLGetInfoW(SQLHDBC dbc, SQLUSMALLINT type, SQLPOINTER val, SQLSMALLINT valMax,
11580 SQLSMALLINT *valLen)
11581 {
11582 SQLRETURN ret;
11583 SQLSMALLINT len = 0;
11584
11585 HDBC_LOCK(dbc);
11586 ret = drvgetinfo(dbc, type, val, valMax, &len);
11587 HDBC_UNLOCK(dbc);
11588 if (ret == SQL_SUCCESS) {
11589 SQLWCHAR *v = NULL;
11590
11591 switch (type) {
11592 case SQL_USER_NAME:
11593 case SQL_DRIVER_ODBC_VER:
11594 case SQL_DATA_SOURCE_NAME:
11595 case SQL_DRIVER_NAME:
11596 case SQL_DRIVER_VER:
11597 case SQL_ODBC_VER:
11598 case SQL_SERVER_NAME:
11599 case SQL_DATABASE_NAME:
11600 case SQL_SEARCH_PATTERN_ESCAPE:
11601 case SQL_DBMS_NAME:
11602 case SQL_DBMS_VER:
11603 case SQL_NEED_LONG_DATA_LEN:
11604 case SQL_ROW_UPDATES:
11605 case SQL_ACCESSIBLE_PROCEDURES:
11606 case SQL_PROCEDURES:
11607 case SQL_EXPRESSIONS_IN_ORDERBY:
11608 case SQL_ODBC_SQL_OPT_IEF:
11609 case SQL_LIKE_ESCAPE_CLAUSE:
11610 case SQL_ORDER_BY_COLUMNS_IN_SELECT:
11611 case SQL_OUTER_JOINS:
11612 case SQL_COLUMN_ALIAS:
11613 case SQL_ACCESSIBLE_TABLES:
11614 case SQL_MULT_RESULT_SETS:
11615 case SQL_MULTIPLE_ACTIVE_TXN:
11616 case SQL_MAX_ROW_SIZE_INCLUDES_LONG:
11617 case SQL_DATA_SOURCE_READ_ONLY:
11618 #ifdef SQL_DESCRIBE_PARAMETER
11619 case SQL_DESCRIBE_PARAMETER:
11620 #endif
11621 case SQL_IDENTIFIER_QUOTE_CHAR:
11622 case SQL_OWNER_TERM:
11623 case SQL_PROCEDURE_TERM:
11624 case SQL_QUALIFIER_NAME_SEPARATOR:
11625 case SQL_QUALIFIER_TERM:
11626 case SQL_TABLE_TERM:
11627 case SQL_KEYWORDS:
11628 case SQL_SPECIAL_CHARACTERS:
11629 #ifdef SQL_CATALOG_NAME
11630 case SQL_CATALOG_NAME:
11631 #endif
11632 #ifdef SQL_COLLATION_SEQ
11633 case SQL_COLLATION_SEQ:
11634 #endif
11635 if (val) {
11636 if (len > 0) {
11637 v = uc_from_utf((SQLCHAR *) val, len);
11638 if (v) {
11639 int vmax = valMax / sizeof (SQLWCHAR);
11640
11641 uc_strncpy(val, v, vmax);
11642 if (len < vmax) {
11643 len = min(vmax, uc_strlen(v));
11644 v[len] = 0;
11645 } else {
11646 len = vmax;
11647 }
11648 uc_free(v);
11649 len *= sizeof (SQLWCHAR);
11650 } else {
11651 len = 0;
11652 }
11653 }
11654 if (len <= 0) {
11655 len = 0;
11656 if (valMax >= sizeof (SQLWCHAR)) {
11657 *((SQLWCHAR *)val) = 0;
11658 }
11659 }
11660 } else {
11661 len *= sizeof (SQLWCHAR);
11662 }
11663 break;
11664 }
11665 if (valLen) {
11666 *valLen = len;
11667 }
11668 }
11669 return ret;
11670 }
11671 #endif
11672
11673 /**
11674 * Return information about supported ODBC API functions.
11675 * @param dbc database connection handle
11676 * @param func function code to be retrieved
11677 * @param flags output indicator
11678 * @result ODBC error code
11679 */
11680
11681 SQLRETURN SQL_API
SQLGetFunctions(SQLHDBC dbc,SQLUSMALLINT func,SQLUSMALLINT * flags)11682 SQLGetFunctions(SQLHDBC dbc, SQLUSMALLINT func,
11683 SQLUSMALLINT *flags)
11684 {
11685 int i;
11686 SQLUSMALLINT exists[100];
11687
11688 if (dbc == SQL_NULL_HDBC) {
11689 return SQL_INVALID_HANDLE;
11690 }
11691 for (i = 0; i < array_size(exists); i++) {
11692 exists[i] = SQL_FALSE;
11693 }
11694 exists[SQL_API_SQLALLOCCONNECT] = SQL_TRUE;
11695 exists[SQL_API_SQLFETCH] = SQL_TRUE;
11696 exists[SQL_API_SQLALLOCENV] = SQL_TRUE;
11697 exists[SQL_API_SQLFREECONNECT] = SQL_TRUE;
11698 exists[SQL_API_SQLALLOCSTMT] = SQL_TRUE;
11699 exists[SQL_API_SQLFREEENV] = SQL_TRUE;
11700 exists[SQL_API_SQLBINDCOL] = SQL_TRUE;
11701 exists[SQL_API_SQLFREESTMT] = SQL_TRUE;
11702 exists[SQL_API_SQLCANCEL] = SQL_TRUE;
11703 exists[SQL_API_SQLGETCURSORNAME] = SQL_TRUE;
11704 exists[SQL_API_SQLCOLATTRIBUTES] = SQL_TRUE;
11705 exists[SQL_API_SQLNUMRESULTCOLS] = SQL_TRUE;
11706 exists[SQL_API_SQLCONNECT] = SQL_TRUE;
11707 exists[SQL_API_SQLPREPARE] = SQL_TRUE;
11708 exists[SQL_API_SQLDESCRIBECOL] = SQL_TRUE;
11709 exists[SQL_API_SQLROWCOUNT] = SQL_TRUE;
11710 exists[SQL_API_SQLDISCONNECT] = SQL_TRUE;
11711 exists[SQL_API_SQLSETCURSORNAME] = SQL_FALSE;
11712 exists[SQL_API_SQLERROR] = SQL_TRUE;
11713 exists[SQL_API_SQLSETPARAM] = SQL_TRUE;
11714 exists[SQL_API_SQLEXECDIRECT] = SQL_TRUE;
11715 exists[SQL_API_SQLTRANSACT] = SQL_TRUE;
11716 exists[SQL_API_SQLBULKOPERATIONS] = SQL_TRUE;
11717 exists[SQL_API_SQLEXECUTE] = SQL_TRUE;
11718 exists[SQL_API_SQLBINDPARAMETER] = SQL_TRUE;
11719 exists[SQL_API_SQLGETTYPEINFO] = SQL_TRUE;
11720 exists[SQL_API_SQLCOLUMNS] = SQL_TRUE;
11721 exists[SQL_API_SQLPARAMDATA] = SQL_TRUE;
11722 exists[SQL_API_SQLDRIVERCONNECT] = SQL_TRUE;
11723 exists[SQL_API_SQLPUTDATA] = SQL_TRUE;
11724 exists[SQL_API_SQLGETCONNECTOPTION] = SQL_TRUE;
11725 exists[SQL_API_SQLSETCONNECTOPTION] = SQL_TRUE;
11726 exists[SQL_API_SQLGETDATA] = SQL_TRUE;
11727 exists[SQL_API_SQLSETSTMTOPTION] = SQL_TRUE;
11728 exists[SQL_API_SQLGETFUNCTIONS] = SQL_TRUE;
11729 exists[SQL_API_SQLSPECIALCOLUMNS] = SQL_TRUE;
11730 exists[SQL_API_SQLGETINFO] = SQL_TRUE;
11731 exists[SQL_API_SQLSTATISTICS] = SQL_TRUE;
11732 exists[SQL_API_SQLGETSTMTOPTION] = SQL_TRUE;
11733 exists[SQL_API_SQLTABLES] = SQL_TRUE;
11734 exists[SQL_API_SQLBROWSECONNECT] = SQL_FALSE;
11735 exists[SQL_API_SQLNUMPARAMS] = SQL_TRUE;
11736 exists[SQL_API_SQLCOLUMNPRIVILEGES] = SQL_FALSE;
11737 exists[SQL_API_SQLPARAMOPTIONS] = SQL_FALSE;
11738 exists[SQL_API_SQLDATASOURCES] = SQL_TRUE;
11739 exists[SQL_API_SQLPRIMARYKEYS] = SQL_TRUE;
11740 exists[SQL_API_SQLDESCRIBEPARAM] = SQL_TRUE;
11741 exists[SQL_API_SQLPROCEDURECOLUMNS] = SQL_TRUE;
11742 exists[SQL_API_SQLDRIVERS] = SQL_FALSE;
11743 exists[SQL_API_SQLPROCEDURES] = SQL_TRUE;
11744 exists[SQL_API_SQLEXTENDEDFETCH] = SQL_TRUE;
11745 exists[SQL_API_SQLSETPOS] = SQL_TRUE;
11746 exists[SQL_API_SQLFOREIGNKEYS] = SQL_TRUE;
11747 exists[SQL_API_SQLSETSCROLLOPTIONS] = SQL_TRUE;
11748 exists[SQL_API_SQLMORERESULTS] = SQL_TRUE;
11749 exists[SQL_API_SQLTABLEPRIVILEGES] = SQL_TRUE;
11750 exists[SQL_API_SQLNATIVESQL] = SQL_TRUE;
11751 if (func == SQL_API_ALL_FUNCTIONS) {
11752 memcpy(flags, exists, sizeof (exists));
11753 } else if (func == SQL_API_ODBC3_ALL_FUNCTIONS) {
11754 int i;
11755 #define SET_EXISTS(x) \
11756 flags[(x) >> 4] |= (1 << ((x) & 0xF))
11757 #define CLR_EXISTS(x) \
11758 flags[(x) >> 4] &= ~(1 << ((x) & 0xF))
11759
11760 memset(flags, 0,
11761 sizeof (SQLUSMALLINT) * SQL_API_ODBC3_ALL_FUNCTIONS_SIZE);
11762 for (i = 0; i < array_size(exists); i++) {
11763 if (exists[i]) {
11764 flags[i >> 4] |= (1 << (i & 0xF));
11765 }
11766 }
11767 SET_EXISTS(SQL_API_SQLALLOCHANDLE);
11768 SET_EXISTS(SQL_API_SQLFREEHANDLE);
11769 SET_EXISTS(SQL_API_SQLGETSTMTATTR);
11770 SET_EXISTS(SQL_API_SQLSETSTMTATTR);
11771 SET_EXISTS(SQL_API_SQLGETCONNECTATTR);
11772 SET_EXISTS(SQL_API_SQLSETCONNECTATTR);
11773 SET_EXISTS(SQL_API_SQLGETENVATTR);
11774 SET_EXISTS(SQL_API_SQLSETENVATTR);
11775 SET_EXISTS(SQL_API_SQLCLOSECURSOR);
11776 SET_EXISTS(SQL_API_SQLBINDPARAM);
11777 #if !defined(HAVE_UNIXODBC) || !(HAVE_UNIXODBC)
11778 /*
11779 * Some unixODBC versions have problems with
11780 * SQLError() vs. SQLGetDiagRec() with loss
11781 * of error/warning messages.
11782 */
11783 SET_EXISTS(SQL_API_SQLGETDIAGREC);
11784 #endif
11785 SET_EXISTS(SQL_API_SQLGETDIAGFIELD);
11786 SET_EXISTS(SQL_API_SQLFETCHSCROLL);
11787 SET_EXISTS(SQL_API_SQLENDTRAN);
11788 } else {
11789 if (func < array_size(exists)) {
11790 *flags = exists[func];
11791 } else {
11792 switch (func) {
11793 case SQL_API_SQLALLOCHANDLE:
11794 case SQL_API_SQLFREEHANDLE:
11795 case SQL_API_SQLGETSTMTATTR:
11796 case SQL_API_SQLSETSTMTATTR:
11797 case SQL_API_SQLGETCONNECTATTR:
11798 case SQL_API_SQLSETCONNECTATTR:
11799 case SQL_API_SQLGETENVATTR:
11800 case SQL_API_SQLSETENVATTR:
11801 case SQL_API_SQLCLOSECURSOR:
11802 case SQL_API_SQLBINDPARAM:
11803 #if !defined(HAVE_UNIXODBC) || !(HAVE_UNIXODBC)
11804 /*
11805 * Some unixODBC versions have problems with
11806 * SQLError() vs. SQLGetDiagRec() with loss
11807 * of error/warning messages.
11808 */
11809 case SQL_API_SQLGETDIAGREC:
11810 #endif
11811 case SQL_API_SQLGETDIAGFIELD:
11812 case SQL_API_SQLFETCHSCROLL:
11813 case SQL_API_SQLENDTRAN:
11814 *flags = SQL_TRUE;
11815 break;
11816 default:
11817 *flags = SQL_FALSE;
11818 }
11819 }
11820 }
11821 return SQL_SUCCESS;
11822 }
11823
11824 /**
11825 * Internal allocate HENV.
11826 * @param env pointer to environment handle
11827 * @result ODBC error code
11828 */
11829
11830 static SQLRETURN
drvallocenv(SQLHENV * env)11831 drvallocenv(SQLHENV *env)
11832 {
11833 ENV *e;
11834
11835 if (env == NULL) {
11836 return SQL_INVALID_HANDLE;
11837 }
11838 e = (ENV *) xmalloc(sizeof (ENV));
11839 if (e == NULL) {
11840 *env = SQL_NULL_HENV;
11841 return SQL_ERROR;
11842 }
11843 e->magic = ENV_MAGIC;
11844 e->ov3 = 0;
11845 e->pool = 0;
11846 #if defined(_WIN32) || defined(_WIN64)
11847 InitializeCriticalSection(&e->cs);
11848 #else
11849 #if defined(ENABLE_NVFS) && (ENABLE_NVFS)
11850 nvfs_init();
11851 #endif
11852 #endif
11853 e->dbcs = NULL;
11854 *env = (SQLHENV) e;
11855 return SQL_SUCCESS;
11856 }
11857
11858 /**
11859 * Allocate HENV.
11860 * @param env pointer to environment handle
11861 * @result ODBC error code
11862 */
11863
11864 SQLRETURN SQL_API
SQLAllocEnv(SQLHENV * env)11865 SQLAllocEnv(SQLHENV *env)
11866 {
11867 return drvallocenv(env);
11868 }
11869
11870 /**
11871 * Internal free HENV.
11872 * @param env environment handle
11873 * @result ODBC error code
11874 */
11875
11876 static SQLRETURN
drvfreeenv(SQLHENV env)11877 drvfreeenv(SQLHENV env)
11878 {
11879 ENV *e;
11880
11881 if (env == SQL_NULL_HENV) {
11882 return SQL_INVALID_HANDLE;
11883 }
11884 e = (ENV *) env;
11885 if (e->magic != ENV_MAGIC) {
11886 return SQL_SUCCESS;
11887 }
11888 #if defined(_WIN32) || defined(_WIN64)
11889 EnterCriticalSection(&e->cs);
11890 #endif
11891 if (e->dbcs) {
11892 #if defined(_WIN32) || defined(_WIN64)
11893 LeaveCriticalSection(&e->cs);
11894 #endif
11895 return SQL_ERROR;
11896 }
11897 e->magic = DEAD_MAGIC;
11898 #if defined(_WIN32) || defined(_WIN64)
11899 LeaveCriticalSection(&e->cs);
11900 DeleteCriticalSection(&e->cs);
11901 #endif
11902 xfree(e);
11903 return SQL_SUCCESS;
11904 }
11905
11906 /**
11907 * Free HENV.
11908 * @param env environment handle
11909 * @result ODBC error code
11910 */
11911
11912 SQLRETURN SQL_API
SQLFreeEnv(SQLHENV env)11913 SQLFreeEnv(SQLHENV env)
11914 {
11915 return drvfreeenv(env);
11916 }
11917
11918 /**
11919 * Internal allocate HDBC.
11920 * @param env environment handle
11921 * @param dbc pointer to database connection handle
11922 * @result ODBC error code
11923 */
11924
11925 static SQLRETURN
drvallocconnect(SQLHENV env,SQLHDBC * dbc)11926 drvallocconnect(SQLHENV env, SQLHDBC *dbc)
11927 {
11928 DBC *d;
11929 ENV *e;
11930 const char *verstr;
11931 int maj = 0, min = 0, lev = 0;
11932
11933 if (dbc == NULL) {
11934 return SQL_ERROR;
11935 }
11936 d = (DBC *) xmalloc(sizeof (DBC));
11937 if (d == NULL) {
11938 *dbc = SQL_NULL_HDBC;
11939 return SQL_ERROR;
11940 }
11941 memset(d, 0, sizeof (DBC));
11942 d->curtype = SQL_CURSOR_STATIC;
11943 d->ov3 = &d->ov3val;
11944 verstr = sqlite3_libversion();
11945 sscanf(verstr, "%d.%d.%d", &maj, &min, &lev);
11946 d->version = verinfo(maj & 0xFF, min & 0xFF, lev & 0xFF);
11947 e = (ENV *) env;
11948 #if defined(_WIN32) || defined(_WIN64)
11949 if (e->magic == ENV_MAGIC) {
11950 EnterCriticalSection(&e->cs);
11951 }
11952 #endif
11953 if (e->magic == ENV_MAGIC) {
11954 DBC *n, *p;
11955
11956 d->env = e;
11957 d->ov3 = &e->ov3;
11958 p = NULL;
11959 n = e->dbcs;
11960 while (n) {
11961 p = n;
11962 n = n->next;
11963 }
11964 if (p) {
11965 p->next = d;
11966 } else {
11967 e->dbcs = d;
11968 }
11969 }
11970 #if defined(_WIN32) || defined(_WIN64)
11971 InitializeCriticalSection(&d->cs);
11972 d->owner = 0;
11973 if (e->magic == ENV_MAGIC) {
11974 LeaveCriticalSection(&e->cs);
11975 }
11976 d->oemcp = 1;
11977 #endif
11978 d->autocommit = 1;
11979 d->magic = DBC_MAGIC;
11980 *dbc = (SQLHDBC) d;
11981 drvgetgpps(d);
11982 return SQL_SUCCESS;
11983 }
11984
11985 /**
11986 * Allocate HDBC.
11987 * @param env environment handle
11988 * @param dbc pointer to database connection handle
11989 * @result ODBC error code
11990 */
11991
11992 SQLRETURN SQL_API
SQLAllocConnect(SQLHENV env,SQLHDBC * dbc)11993 SQLAllocConnect(SQLHENV env, SQLHDBC *dbc)
11994 {
11995 return drvallocconnect(env, dbc);
11996 }
11997
11998 /**
11999 * Internal free connection (HDBC).
12000 * @param dbc database connection handle
12001 * @result ODBC error code
12002 */
12003
12004 static SQLRETURN
drvfreeconnect(SQLHDBC dbc)12005 drvfreeconnect(SQLHDBC dbc)
12006 {
12007 DBC *d;
12008 ENV *e;
12009 SQLRETURN ret = SQL_ERROR;
12010
12011 if (dbc == SQL_NULL_HDBC) {
12012 return SQL_INVALID_HANDLE;
12013 }
12014 d = (DBC *) dbc;
12015 if (d->magic != DBC_MAGIC) {
12016 return SQL_INVALID_HANDLE;
12017 }
12018 e = d->env;
12019 if (e && e->magic == ENV_MAGIC) {
12020 #if defined(_WIN32) || defined(_WIN64)
12021 EnterCriticalSection(&e->cs);
12022 #endif
12023 } else {
12024 e = NULL;
12025 }
12026 HDBC_LOCK(dbc);
12027 if (d->sqlite) {
12028 setstatd(d, -1, "not disconnected", (*d->ov3) ? "HY000" : "S1000");
12029 HDBC_UNLOCK(dbc);
12030 goto done;
12031 }
12032 while (d->stmt) {
12033 freestmt((HSTMT) d->stmt);
12034 }
12035 if (e && e->magic == ENV_MAGIC) {
12036 DBC *n, *p;
12037
12038 p = NULL;
12039 n = e->dbcs;
12040 while (n) {
12041 if (n == d) {
12042 break;
12043 }
12044 p = n;
12045 n = n->next;
12046 }
12047 if (n) {
12048 if (p) {
12049 p->next = d->next;
12050 } else {
12051 e->dbcs = d->next;
12052 }
12053 }
12054 }
12055 drvrelgpps(d);
12056 d->magic = DEAD_MAGIC;
12057 if (d->trace) {
12058 fclose(d->trace);
12059 }
12060 #if defined(_WIN32) || defined(_WIN64)
12061 d->owner = 0;
12062 LeaveCriticalSection(&d->cs);
12063 DeleteCriticalSection(&d->cs);
12064 #endif
12065 xfree(d);
12066 ret = SQL_SUCCESS;
12067 done:
12068 #if defined(_WIN32) || defined(_WIN64)
12069 if (e) {
12070 LeaveCriticalSection(&e->cs);
12071 }
12072 #endif
12073 return ret;
12074 }
12075
12076 /**
12077 * Free connection (HDBC).
12078 * @param dbc database connection handle
12079 * @result ODBC error code
12080 */
12081
12082 SQLRETURN SQL_API
SQLFreeConnect(SQLHDBC dbc)12083 SQLFreeConnect(SQLHDBC dbc)
12084 {
12085 return drvfreeconnect(dbc);
12086 }
12087
12088 /**
12089 * Internal get connect attribute of HDBC.
12090 * @param dbc database connection handle
12091 * @param attr option to be retrieved
12092 * @param val output buffer
12093 * @param bufmax size of output buffer
12094 * @param buflen output length
12095 * @result ODBC error code
12096 */
12097
12098 static SQLRETURN
drvgetconnectattr(SQLHDBC dbc,SQLINTEGER attr,SQLPOINTER val,SQLINTEGER bufmax,SQLINTEGER * buflen)12099 drvgetconnectattr(SQLHDBC dbc, SQLINTEGER attr, SQLPOINTER val,
12100 SQLINTEGER bufmax, SQLINTEGER *buflen)
12101 {
12102 DBC *d;
12103 SQLINTEGER dummy;
12104
12105 if (dbc == SQL_NULL_HDBC) {
12106 return SQL_INVALID_HANDLE;
12107 }
12108 d = (DBC *) dbc;
12109 if (!val) {
12110 val = (SQLPOINTER) &dummy;
12111 }
12112 if (!buflen) {
12113 buflen = &dummy;
12114 }
12115 switch (attr) {
12116 case SQL_ATTR_CONNECTION_DEAD:
12117 *((SQLINTEGER *) val) = d->sqlite ? SQL_CD_FALSE : SQL_CD_TRUE;
12118 *buflen = sizeof (SQLINTEGER);
12119 break;
12120 case SQL_ATTR_ACCESS_MODE:
12121 *((SQLINTEGER *) val) = SQL_MODE_READ_WRITE;
12122 *buflen = sizeof (SQLINTEGER);
12123 break;
12124 case SQL_ATTR_AUTOCOMMIT:
12125 *((SQLINTEGER *) val) =
12126 d->autocommit ? SQL_AUTOCOMMIT_ON : SQL_AUTOCOMMIT_OFF;
12127 *buflen = sizeof (SQLINTEGER);
12128 break;
12129 case SQL_ATTR_LOGIN_TIMEOUT:
12130 *((SQLINTEGER *) val) = 100;
12131 *buflen = sizeof (SQLINTEGER);
12132 break;
12133 case SQL_ATTR_ODBC_CURSORS:
12134 *((SQLINTEGER *) val) = SQL_CUR_USE_DRIVER;
12135 *buflen = sizeof (SQLINTEGER);
12136 break;
12137 case SQL_ATTR_PACKET_SIZE:
12138 *((SQLINTEGER *) val) = 16384;
12139 *buflen = sizeof (SQLINTEGER);
12140 break;
12141 case SQL_ATTR_TXN_ISOLATION:
12142 *((SQLINTEGER *) val) = SQL_TXN_SERIALIZABLE;
12143 *buflen = sizeof (SQLINTEGER);
12144 break;
12145 case SQL_ATTR_TRACEFILE:
12146 case SQL_ATTR_TRANSLATE_LIB:
12147 *((SQLCHAR *) val) = 0;
12148 *buflen = 0;
12149 break;
12150 case SQL_ATTR_CURRENT_CATALOG:
12151 #if defined(_WIN32) || defined(_WIN64)
12152 if (d->xcelqrx) {
12153 if ((bufmax > 4) && (val != (SQLPOINTER) &dummy)) {
12154 strcpy((char *) val, "main");
12155 *buflen = 4;
12156 break;
12157 }
12158 }
12159 #endif
12160 *((SQLCHAR *) val) = 0;
12161 *buflen = 0;
12162 break;
12163 case SQL_ATTR_TRACE:
12164 case SQL_ATTR_QUIET_MODE:
12165 case SQL_ATTR_TRANSLATE_OPTION:
12166 case SQL_ATTR_KEYSET_SIZE:
12167 case SQL_ATTR_QUERY_TIMEOUT:
12168 *((SQLINTEGER *) val) = 0;
12169 *buflen = sizeof (SQLINTEGER);
12170 break;
12171 case SQL_ATTR_PARAM_BIND_TYPE:
12172 *((SQLULEN *) val) = SQL_PARAM_BIND_BY_COLUMN;
12173 *buflen = sizeof (SQLUINTEGER);
12174 break;
12175 case SQL_ATTR_ROW_BIND_TYPE:
12176 *((SQLULEN *) val) = SQL_BIND_BY_COLUMN;
12177 *buflen = sizeof (SQLULEN);
12178 break;
12179 case SQL_ATTR_USE_BOOKMARKS:
12180 *((SQLINTEGER *) val) = SQL_UB_OFF;
12181 *buflen = sizeof (SQLINTEGER);
12182 break;
12183 case SQL_ATTR_ASYNC_ENABLE:
12184 *((SQLINTEGER *) val) = SQL_ASYNC_ENABLE_OFF;
12185 *buflen = sizeof (SQLINTEGER);
12186 break;
12187 case SQL_ATTR_NOSCAN:
12188 *((SQLINTEGER *) val) = SQL_NOSCAN_ON;
12189 *buflen = sizeof (SQLINTEGER);
12190 break;
12191 case SQL_ATTR_CONCURRENCY:
12192 *((SQLINTEGER *) val) = SQL_CONCUR_LOCK;
12193 *buflen = sizeof (SQLINTEGER);
12194 break;
12195 #ifdef SQL_ATTR_CURSOR_SENSITIVITY
12196 case SQL_ATTR_CURSOR_SENSITIVITY:
12197 *((SQLINTEGER *) val) = SQL_UNSPECIFIED;
12198 *buflen = sizeof (SQLINTEGER);
12199 break;
12200 #endif
12201 case SQL_ATTR_SIMULATE_CURSOR:
12202 *((SQLINTEGER *) val) = SQL_SC_NON_UNIQUE;
12203 *buflen = sizeof (SQLINTEGER);
12204 break;
12205 case SQL_ATTR_MAX_ROWS:
12206 *((SQLINTEGER *) val) = 0;
12207 *buflen = sizeof (SQLINTEGER);
12208 case SQL_ATTR_MAX_LENGTH:
12209 *((SQLINTEGER *) val) = 1000000000;
12210 *buflen = sizeof (SQLINTEGER);
12211 break;
12212 case SQL_ATTR_CURSOR_TYPE:
12213 *((SQLINTEGER *) val) = d->curtype;
12214 *buflen = sizeof (SQLINTEGER);
12215 break;
12216 case SQL_ATTR_RETRIEVE_DATA:
12217 *((SQLINTEGER *) val) = SQL_RD_ON;
12218 *buflen = sizeof (SQLINTEGER);
12219 break;
12220 #ifdef SQL_ATTR_METADATA_ID
12221 case SQL_ATTR_METADATA_ID:
12222 *((SQLULEN *) val) = SQL_FALSE;
12223 return SQL_SUCCESS;
12224 #endif
12225 default:
12226 *((SQLINTEGER *) val) = 0;
12227 *buflen = sizeof (SQLINTEGER);
12228 setstatd(d, -1, "unsupported connect attribute %d",
12229 (*d->ov3) ? "HYC00" : "S1C00", (int) attr);
12230 return SQL_ERROR;
12231 }
12232 return SQL_SUCCESS;
12233 }
12234
12235 #ifndef WINTERFACE
12236 /**
12237 * Get connect attribute of HDBC.
12238 * @param dbc database connection handle
12239 * @param attr option to be retrieved
12240 * @param val output buffer
12241 * @param bufmax size of output buffer
12242 * @param buflen output length
12243 * @result ODBC error code
12244 */
12245
12246 SQLRETURN SQL_API
SQLGetConnectAttr(SQLHDBC dbc,SQLINTEGER attr,SQLPOINTER val,SQLINTEGER bufmax,SQLINTEGER * buflen)12247 SQLGetConnectAttr(SQLHDBC dbc, SQLINTEGER attr, SQLPOINTER val,
12248 SQLINTEGER bufmax, SQLINTEGER *buflen)
12249 {
12250 SQLRETURN ret;
12251
12252 HDBC_LOCK(dbc);
12253 ret = drvgetconnectattr(dbc, attr, val, bufmax, buflen);
12254 HDBC_UNLOCK(dbc);
12255 return ret;
12256 }
12257 #endif
12258
12259 #ifdef WINTERFACE
12260 /**
12261 * Get connect attribute of HDBC (UNICODE version).
12262 * @param dbc database connection handle
12263 * @param attr option to be retrieved
12264 * @param val output buffer
12265 * @param bufmax size of output buffer
12266 * @param buflen output length
12267 * @result ODBC error code
12268 */
12269
12270 SQLRETURN SQL_API
SQLGetConnectAttrW(SQLHDBC dbc,SQLINTEGER attr,SQLPOINTER val,SQLINTEGER bufmax,SQLINTEGER * buflen)12271 SQLGetConnectAttrW(SQLHDBC dbc, SQLINTEGER attr, SQLPOINTER val,
12272 SQLINTEGER bufmax, SQLINTEGER *buflen)
12273 {
12274 SQLRETURN ret;
12275 SQLINTEGER len = 0;
12276
12277 HDBC_LOCK(dbc);
12278 ret = drvgetconnectattr(dbc, attr, val, bufmax, &len);
12279 if (ret == SQL_SUCCESS) {
12280 SQLWCHAR *v = NULL;
12281
12282 switch (attr) {
12283 case SQL_ATTR_TRACEFILE:
12284 case SQL_ATTR_CURRENT_CATALOG:
12285 case SQL_ATTR_TRANSLATE_LIB:
12286 if (val) {
12287 if (len > 0) {
12288 v = uc_from_utf((SQLCHAR *) val, len);
12289 if (v) {
12290 int vmax = bufmax / sizeof (SQLWCHAR);
12291
12292 uc_strncpy(val, v, vmax);
12293 if (len < vmax) {
12294 len = min(vmax, uc_strlen(v));
12295 v[len] = 0;
12296 } else {
12297 len = vmax;
12298 }
12299 uc_free(v);
12300 len *= sizeof (SQLWCHAR);
12301 } else {
12302 len = 0;
12303 }
12304 }
12305 if (len <= 0) {
12306 len = 0;
12307 if (bufmax >= sizeof (SQLWCHAR)) {
12308 *((SQLWCHAR *)val) = 0;
12309 }
12310 }
12311 } else {
12312 len *= sizeof (SQLWCHAR);
12313 }
12314 break;
12315 }
12316 if (buflen) {
12317 *buflen = len;
12318 }
12319 }
12320 HDBC_UNLOCK(dbc);
12321 return ret;
12322 }
12323 #endif
12324
12325 /**
12326 * Internal set connect attribute of HDBC.
12327 * @param dbc database connection handle
12328 * @param attr option to be set
12329 * @param val option value
12330 * @param len size of option
12331 * @result ODBC error code
12332 */
12333
12334 static SQLRETURN
drvsetconnectattr(SQLHDBC dbc,SQLINTEGER attr,SQLPOINTER val,SQLINTEGER len)12335 drvsetconnectattr(SQLHDBC dbc, SQLINTEGER attr, SQLPOINTER val,
12336 SQLINTEGER len)
12337 {
12338 DBC *d;
12339
12340 if (dbc == SQL_NULL_HDBC) {
12341 return SQL_INVALID_HANDLE;
12342 }
12343 d = (DBC *) dbc;
12344 switch (attr) {
12345 case SQL_AUTOCOMMIT:
12346 d->autocommit = val == (SQLPOINTER) SQL_AUTOCOMMIT_ON;
12347 if (d->autocommit && d->intrans) {
12348 return endtran(d, SQL_COMMIT, 1);
12349 } else if (!d->autocommit) {
12350 s3stmt_end(d->cur_s3stmt);
12351 }
12352 break;
12353 return SQL_SUCCESS;
12354 #ifdef SQL_ATTR_METADATA_ID
12355 case SQL_ATTR_METADATA_ID:
12356 if (val == (SQLPOINTER) SQL_FALSE) {
12357 break;
12358 }
12359 /* fall through */
12360 #endif
12361 default:
12362 setstatd(d, -1, "option value changed", "01S02");
12363 return SQL_SUCCESS_WITH_INFO;
12364 }
12365 return SQL_SUCCESS;
12366 }
12367
12368 #ifndef WINTERFACE
12369 /**
12370 * Set connect attribute of HDBC.
12371 * @param dbc database connection handle
12372 * @param attr option to be set
12373 * @param val option value
12374 * @param len size of option
12375 * @result ODBC error code
12376 */
12377
12378 SQLRETURN SQL_API
SQLSetConnectAttr(SQLHDBC dbc,SQLINTEGER attr,SQLPOINTER val,SQLINTEGER len)12379 SQLSetConnectAttr(SQLHDBC dbc, SQLINTEGER attr, SQLPOINTER val,
12380 SQLINTEGER len)
12381 {
12382 SQLRETURN ret;
12383
12384 HDBC_LOCK(dbc);
12385 ret = drvsetconnectattr(dbc, attr, val, len);
12386 HDBC_UNLOCK(dbc);
12387 return ret;
12388 }
12389 #endif
12390
12391 #ifdef WINTERFACE
12392 /**
12393 * Set connect attribute of HDBC (UNICODE version).
12394 * @param dbc database connection handle
12395 * @param attr option to be set
12396 * @param val option value
12397 * @param len size of option
12398 * @result ODBC error code
12399 */
12400
12401 SQLRETURN SQL_API
SQLSetConnectAttrW(SQLHDBC dbc,SQLINTEGER attr,SQLPOINTER val,SQLINTEGER len)12402 SQLSetConnectAttrW(SQLHDBC dbc, SQLINTEGER attr, SQLPOINTER val,
12403 SQLINTEGER len)
12404 {
12405 SQLRETURN ret;
12406
12407 HDBC_LOCK(dbc);
12408 ret = drvsetconnectattr(dbc, attr, val, len);
12409 HDBC_UNLOCK(dbc);
12410 return ret;
12411 }
12412 #endif
12413
12414 /**
12415 * Internal get connect option of HDBC.
12416 * @param dbc database connection handle
12417 * @param opt option to be retrieved
12418 * @param param output buffer
12419 * @result ODBC error code
12420 */
12421
12422 static SQLRETURN
drvgetconnectoption(SQLHDBC dbc,SQLUSMALLINT opt,SQLPOINTER param)12423 drvgetconnectoption(SQLHDBC dbc, SQLUSMALLINT opt, SQLPOINTER param)
12424 {
12425 DBC *d;
12426 SQLINTEGER dummy;
12427
12428 if (dbc == SQL_NULL_HDBC) {
12429 return SQL_INVALID_HANDLE;
12430 }
12431 d = (DBC *) dbc;
12432 if (!param) {
12433 param = (SQLPOINTER) &dummy;
12434 }
12435 switch (opt) {
12436 case SQL_ACCESS_MODE:
12437 *((SQLINTEGER *) param) = SQL_MODE_READ_WRITE;
12438 break;
12439 case SQL_AUTOCOMMIT:
12440 *((SQLINTEGER *) param) =
12441 d->autocommit ? SQL_AUTOCOMMIT_ON : SQL_AUTOCOMMIT_OFF;
12442 break;
12443 case SQL_LOGIN_TIMEOUT:
12444 *((SQLINTEGER *) param) = 100;
12445 break;
12446 case SQL_ODBC_CURSORS:
12447 *((SQLINTEGER *) param) = SQL_CUR_USE_DRIVER;
12448 break;
12449 case SQL_PACKET_SIZE:
12450 *((SQLINTEGER *) param) = 16384;
12451 break;
12452 case SQL_TXN_ISOLATION:
12453 *((SQLINTEGER *) param) = SQL_TXN_SERIALIZABLE;
12454 break;
12455 case SQL_OPT_TRACE:
12456 case SQL_OPT_TRACEFILE:
12457 case SQL_QUIET_MODE:
12458 case SQL_TRANSLATE_DLL:
12459 case SQL_TRANSLATE_OPTION:
12460 case SQL_KEYSET_SIZE:
12461 case SQL_QUERY_TIMEOUT:
12462 case SQL_BIND_TYPE:
12463 case SQL_CURRENT_QUALIFIER:
12464 *((SQLINTEGER *) param) = 0;
12465 break;
12466 case SQL_USE_BOOKMARKS:
12467 *((SQLINTEGER *) param) = SQL_UB_OFF;
12468 break;
12469 case SQL_ASYNC_ENABLE:
12470 *((SQLINTEGER *) param) = SQL_ASYNC_ENABLE_OFF;
12471 break;
12472 case SQL_NOSCAN:
12473 *((SQLINTEGER *) param) = SQL_NOSCAN_ON;
12474 break;
12475 case SQL_CONCURRENCY:
12476 *((SQLINTEGER *) param) = SQL_CONCUR_LOCK;
12477 break;
12478 case SQL_SIMULATE_CURSOR:
12479 *((SQLINTEGER *) param) = SQL_SC_NON_UNIQUE;
12480 break;
12481 case SQL_MAX_ROWS:
12482 *((SQLINTEGER *) param) = 0;
12483 break;
12484 case SQL_ROWSET_SIZE:
12485 case SQL_MAX_LENGTH:
12486 *((SQLINTEGER *) param) = 1000000000;
12487 break;
12488 case SQL_CURSOR_TYPE:
12489 *((SQLINTEGER *) param) = d->curtype;
12490 break;
12491 case SQL_RETRIEVE_DATA:
12492 *((SQLINTEGER *) param) = SQL_RD_ON;
12493 break;
12494 default:
12495 *((SQLINTEGER *) param) = 0;
12496 setstatd(d, -1, "unsupported connect option %d",
12497 (*d->ov3) ? "HYC00" : "S1C00", opt);
12498 return SQL_ERROR;
12499 }
12500 return SQL_SUCCESS;
12501 }
12502
12503 #ifndef WINTERFACE
12504 /**
12505 * Get connect option of HDBC.
12506 * @param dbc database connection handle
12507 * @param opt option to be retrieved
12508 * @param param output buffer
12509 * @result ODBC error code
12510 */
12511
12512 SQLRETURN SQL_API
SQLGetConnectOption(SQLHDBC dbc,SQLUSMALLINT opt,SQLPOINTER param)12513 SQLGetConnectOption(SQLHDBC dbc, SQLUSMALLINT opt, SQLPOINTER param)
12514 {
12515 SQLRETURN ret;
12516
12517 HDBC_LOCK(dbc);
12518 ret = drvgetconnectoption(dbc, opt, param);
12519 HDBC_UNLOCK(dbc);
12520 return ret;
12521 }
12522 #endif
12523
12524 #ifdef WINTERFACE
12525 /**
12526 * Get connect option of HDBC (UNICODE version).
12527 * @param dbc database connection handle
12528 * @param opt option to be retrieved
12529 * @param param output buffer
12530 * @result ODBC error code
12531 */
12532
12533 SQLRETURN SQL_API
SQLGetConnectOptionW(SQLHDBC dbc,SQLUSMALLINT opt,SQLPOINTER param)12534 SQLGetConnectOptionW(SQLHDBC dbc, SQLUSMALLINT opt, SQLPOINTER param)
12535 {
12536 SQLRETURN ret;
12537
12538 HDBC_LOCK(dbc);
12539 ret = drvgetconnectoption(dbc, opt, param);
12540 if (SQL_SUCCEEDED(ret)) {
12541 switch (opt) {
12542 case SQL_OPT_TRACEFILE:
12543 case SQL_CURRENT_QUALIFIER:
12544 case SQL_TRANSLATE_DLL:
12545 if (param) {
12546 *(SQLWCHAR *) param = 0;
12547 }
12548 break;
12549 }
12550 }
12551 HDBC_UNLOCK(dbc);
12552 return ret;
12553 }
12554 #endif
12555
12556 /**
12557 * Internal set option on HDBC.
12558 * @param dbc database connection handle
12559 * @param opt option to be set
12560 * @param param option value
12561 * @result ODBC error code
12562 */
12563
12564 static SQLRETURN
drvsetconnectoption(SQLHDBC dbc,SQLUSMALLINT opt,SQLUINTEGER param)12565 drvsetconnectoption(SQLHDBC dbc, SQLUSMALLINT opt, SQLUINTEGER param)
12566 {
12567 DBC *d;
12568
12569 if (dbc == SQL_NULL_HDBC) {
12570 return SQL_INVALID_HANDLE;
12571 }
12572 d = (DBC *) dbc;
12573 switch (opt) {
12574 case SQL_AUTOCOMMIT:
12575 d->autocommit = param == SQL_AUTOCOMMIT_ON;
12576 if (d->autocommit && d->intrans) {
12577 return endtran(d, SQL_COMMIT, 1);
12578 } else if (!d->autocommit) {
12579 s3stmt_end(d->cur_s3stmt);
12580 }
12581 break;
12582 default:
12583 setstatd(d, -1, "option value changed", "01S02");
12584 return SQL_SUCCESS_WITH_INFO;
12585 }
12586 return SQL_SUCCESS;
12587 }
12588
12589 #ifndef WINTERFACE
12590 /**
12591 * Set option on HDBC.
12592 * @param dbc database connection handle
12593 * @param opt option to be set
12594 * @param param option value
12595 * @result ODBC error code
12596 */
12597
12598 SQLRETURN SQL_API
SQLSetConnectOption(SQLHDBC dbc,SQLUSMALLINT opt,SQLULEN param)12599 SQLSetConnectOption(SQLHDBC dbc, SQLUSMALLINT opt, SQLULEN param)
12600 {
12601 SQLRETURN ret;
12602
12603 HDBC_LOCK(dbc);
12604 ret = drvsetconnectoption(dbc, opt, param);
12605 HDBC_UNLOCK(dbc);
12606 return ret;
12607 }
12608 #endif
12609
12610 #ifdef WINTERFACE
12611 /**
12612 * Set option on HDBC (UNICODE version).
12613 * @param dbc database connection handle
12614 * @param opt option to be set
12615 * @param param option value
12616 * @result ODBC error code
12617 */
12618
12619 SQLRETURN SQL_API
SQLSetConnectOptionW(SQLHDBC dbc,SQLUSMALLINT opt,SQLULEN param)12620 SQLSetConnectOptionW(SQLHDBC dbc, SQLUSMALLINT opt, SQLULEN param)
12621 {
12622 SQLRETURN ret;
12623
12624 HDBC_LOCK(dbc);
12625 ret = drvsetconnectoption(dbc, opt, param);
12626 HDBC_UNLOCK(dbc);
12627 return ret;
12628 }
12629 #endif
12630
12631 #if defined(WITHOUT_DRIVERMGR) || (!defined(_WIN32) && !defined(_WIN64))
12632
12633 /**
12634 * Handling of SQLConnect() connection attributes
12635 * for standalone operation without driver manager.
12636 * @param dsn DSN/driver connection string
12637 * @param attr attribute string to be retrieved
12638 * @param out output buffer
12639 * @param outLen length of output buffer
12640 * @result true or false
12641 */
12642
12643 static int
getdsnattr(char * dsn,char * attr,char * out,int outLen)12644 getdsnattr(char *dsn, char *attr, char *out, int outLen)
12645 {
12646 char *str = dsn, *start;
12647 int len = strlen(attr);
12648
12649 while (*str) {
12650 while (*str && *str == ';') {
12651 ++str;
12652 }
12653 start = str;
12654 if ((str = strchr(str, '=')) == NULL) {
12655 return 0;
12656 }
12657 if (str - start == len && strncasecmp(start, attr, len) == 0) {
12658 start = ++str;
12659 while (*str && *str != ';') {
12660 ++str;
12661 }
12662 len = min(outLen - 1, str - start);
12663 strncpy(out, start, len);
12664 out[len] = '\0';
12665 return 1;
12666 }
12667 while (*str && *str != ';') {
12668 ++str;
12669 }
12670 }
12671 return 0;
12672 }
12673 #endif
12674
12675 /**
12676 * Internal connect to SQLite database.
12677 * @param dbc database connection handle
12678 * @param dsn DSN string
12679 * @param dsnLen length of DSN string or SQL_NTS
12680 * @param pwd password or NULL
12681 * @param pwdLen length of password or SQL_NTS
12682 * @param isu true/false: file name is UTF8 encoded
12683 * @result ODBC error code
12684 */
12685
12686 static SQLRETURN
drvconnect(SQLHDBC dbc,SQLCHAR * dsn,SQLSMALLINT dsnLen,char * pwd,int pwdLen,int isu)12687 drvconnect(SQLHDBC dbc, SQLCHAR *dsn, SQLSMALLINT dsnLen, char *pwd,
12688 int pwdLen, int isu)
12689 {
12690 DBC *d;
12691 int len;
12692 SQLRETURN ret;
12693 char buf[SQL_MAX_MESSAGE_LENGTH * 6], dbname[SQL_MAX_MESSAGE_LENGTH];
12694 char busy[SQL_MAX_MESSAGE_LENGTH / 4], tracef[SQL_MAX_MESSAGE_LENGTH];
12695 char loadext[SQL_MAX_MESSAGE_LENGTH];
12696 char sflag[32], spflag[32], ntflag[32], nwflag[32], biflag[32];
12697 char snflag[32], lnflag[32], ncflag[32], fkflag[32], jmode[32];
12698 char jdflag[32];
12699 #if defined(_WIN32) || defined(_WIN64)
12700 char oemcp[32];
12701 #endif
12702
12703 if (dbc == SQL_NULL_HDBC) {
12704 return SQL_INVALID_HANDLE;
12705 }
12706 d = (DBC *) dbc;
12707 if (d->magic != DBC_MAGIC) {
12708 return SQL_INVALID_HANDLE;
12709 }
12710 if (d->sqlite != NULL) {
12711 setstatd(d, -1, "connection already established", "08002");
12712 return SQL_ERROR;
12713 }
12714 buf[0] = '\0';
12715 if (dsnLen == SQL_NTS) {
12716 len = sizeof (buf) - 1;
12717 } else {
12718 len = min(sizeof (buf) - 1, dsnLen);
12719 }
12720 if (dsn != NULL) {
12721 strncpy(buf, (char *) dsn, len);
12722 }
12723 buf[len] = '\0';
12724 if (buf[0] == '\0') {
12725 setstatd(d, -1, "invalid DSN", (*d->ov3) ? "HY090" : "S1090");
12726 return SQL_ERROR;
12727 }
12728 #if defined(_WIN32) || defined(_WIN64)
12729 /*
12730 * When DSN is in UTF it must be converted to ANSI
12731 * here for ANSI SQLGetPrivateProfileString()
12732 */
12733 if (isu) {
12734 char *cdsn = utf_to_wmb(buf, len);
12735
12736 if (!cdsn) {
12737 setstatd(d, -1, "out of memory", (*d->ov3) ? "HY000" : "S1000");
12738 return SQL_ERROR;
12739 }
12740 strcpy(buf, cdsn);
12741 uc_free(cdsn);
12742 }
12743 #endif
12744 busy[0] = '\0';
12745 dbname[0] = '\0';
12746 #ifdef WITHOUT_DRIVERMGR
12747 getdsnattr(buf, "database", dbname, sizeof (dbname));
12748 if (dbname[0] == '\0') {
12749 strncpy(dbname, buf, sizeof (dbname));
12750 dbname[sizeof (dbname) - 1] = '\0';
12751 }
12752 getdsnattr(buf, "timeout", busy, sizeof (busy));
12753 sflag[0] = '\0';
12754 getdsnattr(buf, "stepapi", sflag, sizeof (sflag));
12755 spflag[0] = '\0';
12756 getdsnattr(buf, "syncpragma", spflag, sizeof (spflag));
12757 ntflag[0] = '\0';
12758 getdsnattr(buf, "notxn", ntflag, sizeof (ntflag));
12759 nwflag[0] = '\0';
12760 getdsnattr(buf, "nowchar", nwflag, sizeof (nwflag));
12761 snflag[0] = '\0';
12762 getdsnattr(buf, "shortnames", snflag, sizeof (snflag));
12763 lnflag[0] = '\0';
12764 getdsnattr(buf, "longnames", lnflag, sizeof (lnflag));
12765 ncflag[0] = '\0';
12766 getdsnattr(buf, "nocreat", ncflag, sizeof (ncflag));
12767 fkflag[0] = '\0';
12768 getdsnattr(buf, "fksupport", fkflag, sizeof (fkflag));
12769 loadext[0] = '\0';
12770 getdsnattr(buf, "loadext", loadext, sizeof (loadext));
12771 jmode[0] = '\0';
12772 getdsnattr(buf, "journalmode", jmode, sizeof (jmode));
12773 jdflag[0] = '\0';
12774 getdsnattr(buf, "jdconv", jdflag, sizeof (jdflag));
12775 #if defined(_WIN32) || defined(_WIN64)
12776 oemcp[0] = '\0';
12777 getdsnattr(buf, "oemcp", oemcp, sizeof (oemcp));
12778 #endif
12779 biflag[0] = '\0';
12780 getdsnattr(buf, "bigint", biflag, sizeof (biflag));
12781 #else
12782 SQLGetPrivateProfileString(buf, "timeout", "100000",
12783 busy, sizeof (busy), ODBC_INI);
12784 SQLGetPrivateProfileString(buf, "database", "",
12785 dbname, sizeof (dbname), ODBC_INI);
12786 #if defined(_WIN32) || defined(_WIN64)
12787 /* database name read from registry is not UTF8 !!! */
12788 isu = 0;
12789 #endif
12790 SQLGetPrivateProfileString(buf, "stepapi", "",
12791 sflag, sizeof (sflag), ODBC_INI);
12792 SQLGetPrivateProfileString(buf, "syncpragma", "NORMAL",
12793 spflag, sizeof (spflag), ODBC_INI);
12794 SQLGetPrivateProfileString(buf, "notxn", "",
12795 ntflag, sizeof (ntflag), ODBC_INI);
12796 SQLGetPrivateProfileString(buf, "nowchar", "",
12797 nwflag, sizeof (nwflag), ODBC_INI);
12798 SQLGetPrivateProfileString(buf, "shortnames", "",
12799 snflag, sizeof (snflag), ODBC_INI);
12800 SQLGetPrivateProfileString(buf, "longnames", "",
12801 lnflag, sizeof (lnflag), ODBC_INI);
12802 SQLGetPrivateProfileString(buf, "nocreat", "",
12803 ncflag, sizeof (ncflag), ODBC_INI);
12804 SQLGetPrivateProfileString(buf, "fksupport", "",
12805 fkflag, sizeof (fkflag), ODBC_INI);
12806 SQLGetPrivateProfileString(buf, "loadext", "",
12807 loadext, sizeof (loadext), ODBC_INI);
12808 SQLGetPrivateProfileString(buf, "journalmode", "",
12809 jmode, sizeof (jmode), ODBC_INI);
12810 SQLGetPrivateProfileString(buf, "jdconv", "",
12811 jdflag, sizeof (jdflag), ODBC_INI);
12812 #if defined(_WIN32) || defined(_WIN64)
12813 SQLGetPrivateProfileString(buf, "oemcp", "1",
12814 oemcp, sizeof (oemcp), ODBC_INI);
12815 #endif
12816 SQLGetPrivateProfileString(buf, "bigint", "",
12817 biflag, sizeof (biflag), ODBC_INI);
12818 #endif
12819 tracef[0] = '\0';
12820 #ifdef WITHOUT_DRIVERMGR
12821 getdsnattr(buf, "tracefile", tracef, sizeof (tracef));
12822 #else
12823 SQLGetPrivateProfileString(buf, "tracefile", "",
12824 tracef, sizeof (tracef), ODBC_INI);
12825 #endif
12826 if (tracef[0] != '\0') {
12827 d->trace = fopen(tracef, "a");
12828 }
12829 d->nowchar = getbool(nwflag);
12830 d->shortnames = getbool(snflag);
12831 d->longnames = getbool(lnflag);
12832 d->nocreat = getbool(ncflag);
12833 d->fksupport = getbool(fkflag);
12834 d->jdconv = getbool(jdflag);
12835 #if defined(_WIN32) || defined(_WIN64)
12836 d->oemcp = getbool(oemcp);
12837 #else
12838 d->oemcp = 0;
12839 #endif
12840 d->dobigint = getbool(biflag);
12841 d->pwd = pwd;
12842 d->pwdLen = 0;
12843 if (d->pwd) {
12844 d->pwdLen = (pwdLen == SQL_NTS) ? strlen(d->pwd) : pwdLen;
12845 }
12846 ret = dbopen(d, dbname, isu, (char *) dsn, sflag, spflag, ntflag,
12847 jmode, busy);
12848 if (ret == SQL_SUCCESS) {
12849 dbloadext(d, loadext);
12850 }
12851 return ret;
12852 }
12853
12854 #ifndef WINTERFACE
12855 /**
12856 * Connect to SQLite database.
12857 * @param dbc database connection handle
12858 * @param dsn DSN string
12859 * @param dsnLen length of DSN string or SQL_NTS
12860 * @param uid user id string or NULL
12861 * @param uidLen length of user id string or SQL_NTS
12862 * @param pwd password string or NULL
12863 * @param pwdLen length of password string or SQL_NTS
12864 * @result ODBC error code
12865 */
12866
12867 SQLRETURN SQL_API
SQLConnect(SQLHDBC dbc,SQLCHAR * dsn,SQLSMALLINT dsnLen,SQLCHAR * uid,SQLSMALLINT uidLen,SQLCHAR * pwd,SQLSMALLINT pwdLen)12868 SQLConnect(SQLHDBC dbc, SQLCHAR *dsn, SQLSMALLINT dsnLen,
12869 SQLCHAR *uid, SQLSMALLINT uidLen,
12870 SQLCHAR *pwd, SQLSMALLINT pwdLen)
12871 {
12872 SQLRETURN ret;
12873
12874 HDBC_LOCK(dbc);
12875 ret = drvconnect(dbc, dsn, dsnLen, (char *) pwd, pwdLen, 0);
12876 HDBC_UNLOCK(dbc);
12877 return ret;
12878 }
12879 #endif
12880
12881 #ifdef WINTERFACE
12882 /**
12883 * Connect to SQLite database.
12884 * @param dbc database connection handle
12885 * @param dsn DSN string
12886 * @param dsnLen length of DSN string or SQL_NTS
12887 * @param uid user id string or NULL
12888 * @param uidLen length of user id string or SQL_NTS
12889 * @param pwd password string or NULL
12890 * @param pwdLen length of password string or SQL_NTS
12891 * @result ODBC error code
12892 */
12893
12894 SQLRETURN SQL_API
SQLConnectW(SQLHDBC dbc,SQLWCHAR * dsn,SQLSMALLINT dsnLen,SQLWCHAR * uid,SQLSMALLINT uidLen,SQLWCHAR * pwd,SQLSMALLINT pwdLen)12895 SQLConnectW(SQLHDBC dbc, SQLWCHAR *dsn, SQLSMALLINT dsnLen,
12896 SQLWCHAR *uid, SQLSMALLINT uidLen,
12897 SQLWCHAR *pwd, SQLSMALLINT pwdLen)
12898 {
12899 char *dsna = NULL;
12900 char *pwda = NULL;
12901 SQLRETURN ret;
12902
12903 HDBC_LOCK(dbc);
12904 if (dsn) {
12905 dsna = uc_to_utf_c(dsn, dsnLen);
12906 if (!dsna) {
12907 DBC *d = (DBC *) dbc;
12908
12909 setstatd(d, -1, "out of memory", (*d->ov3) ? "HY000" : "S1000");
12910 ret = SQL_ERROR;
12911 goto done;
12912 }
12913 }
12914 if (pwd) {
12915 pwda = uc_to_utf_c(pwd, pwdLen);
12916 if (!pwda) {
12917 DBC *d = (DBC *) dbc;
12918
12919 setstatd(d, -1, "out of memory", (*d->ov3) ? "HY000" : "S1000");
12920 ret = SQL_ERROR;
12921 goto done;
12922 }
12923 }
12924 ret = drvconnect(dbc, (SQLCHAR *) dsna, SQL_NTS, pwda, SQL_NTS, 1);
12925 done:
12926 HDBC_UNLOCK(dbc);
12927 uc_free(dsna);
12928 uc_free(pwda);
12929 return ret;
12930 }
12931 #endif
12932
12933 /**
12934 * Internal disconnect given HDBC.
12935 * @param dbc database connection handle
12936 * @result ODBC error code
12937 */
12938
12939 static SQLRETURN
drvdisconnect(SQLHDBC dbc)12940 drvdisconnect(SQLHDBC dbc)
12941 {
12942 DBC *d;
12943 int rc;
12944
12945 if (dbc == SQL_NULL_HDBC) {
12946 return SQL_INVALID_HANDLE;
12947 }
12948 d = (DBC *) dbc;
12949 if (d->magic != DBC_MAGIC) {
12950 return SQL_INVALID_HANDLE;
12951 }
12952 if (d->intrans) {
12953 setstatd(d, -1, "incomplete transaction", "25000");
12954 return SQL_ERROR;
12955 }
12956 if (d->cur_s3stmt) {
12957 s3stmt_end(d->cur_s3stmt);
12958 }
12959 if (d->sqlite) {
12960 if (d->trace) {
12961 fprintf(d->trace, "-- sqlite3_close: '%s'\n",
12962 d->dbname);
12963 fflush(d->trace);
12964 }
12965 rc = sqlite3_close(d->sqlite);
12966 if (rc == SQLITE_BUSY) {
12967 setstatd(d, -1, "unfinished statements", "25000");
12968 return SQL_ERROR;
12969 }
12970 d->sqlite = NULL;
12971 }
12972 freep(&d->dbname);
12973 freep(&d->dsn);
12974 return SQL_SUCCESS;
12975 }
12976
12977 /**
12978 * Disconnect given HDBC.
12979 * @param dbc database connection handle
12980 * @result ODBC error code
12981 */
12982
12983 SQLRETURN SQL_API
SQLDisconnect(SQLHDBC dbc)12984 SQLDisconnect(SQLHDBC dbc)
12985 {
12986 SQLRETURN ret;
12987
12988 HDBC_LOCK(dbc);
12989 ret = drvdisconnect(dbc);
12990 HDBC_UNLOCK(dbc);
12991 return ret;
12992 }
12993
12994 #if defined(WITHOUT_DRIVERMGR) || (!defined(_WIN32) && !defined(_WIN64))
12995
12996 /**
12997 * Internal standalone (w/o driver manager) database connect.
12998 * @param dbc database connection handle
12999 * @param hwnd dummy window handle or NULL
13000 * @param connIn driver connect input string
13001 * @param connInLen length of driver connect input string or SQL_NTS
13002 * @param connOut driver connect output string
13003 * @param connOutMax length of driver connect output string
13004 * @param connOutLen output length of driver connect output string
13005 * @param drvcompl completion type
13006 * @result ODBC error code
13007 */
13008
13009 static SQLRETURN
drvdriverconnect(SQLHDBC dbc,SQLHWND hwnd,SQLCHAR * connIn,SQLSMALLINT connInLen,SQLCHAR * connOut,SQLSMALLINT connOutMax,SQLSMALLINT * connOutLen,SQLUSMALLINT drvcompl)13010 drvdriverconnect(SQLHDBC dbc, SQLHWND hwnd,
13011 SQLCHAR *connIn, SQLSMALLINT connInLen,
13012 SQLCHAR *connOut, SQLSMALLINT connOutMax,
13013 SQLSMALLINT *connOutLen, SQLUSMALLINT drvcompl)
13014 {
13015 DBC *d;
13016 int len;
13017 SQLRETURN ret;
13018 char buf[SQL_MAX_MESSAGE_LENGTH * 8], dbname[SQL_MAX_MESSAGE_LENGTH];
13019 char dsn[SQL_MAX_MESSAGE_LENGTH], busy[SQL_MAX_MESSAGE_LENGTH / 4];
13020 char tracef[SQL_MAX_MESSAGE_LENGTH], loadext[SQL_MAX_MESSAGE_LENGTH];
13021 char pwd[SQL_MAX_MESSAGE_LENGTH];
13022 char sflag[32], spflag[32], ntflag[32], snflag[32], lnflag[32];
13023 char ncflag[32], nwflag[32], fkflag[32], jmode[32], biflag[32];
13024 char jdflag[32];
13025
13026 if (dbc == SQL_NULL_HDBC) {
13027 return SQL_INVALID_HANDLE;
13028 }
13029 if (drvcompl != SQL_DRIVER_COMPLETE &&
13030 drvcompl != SQL_DRIVER_COMPLETE_REQUIRED &&
13031 drvcompl != SQL_DRIVER_PROMPT &&
13032 drvcompl != SQL_DRIVER_NOPROMPT) {
13033 return SQL_NO_DATA;
13034 }
13035 d = (DBC *) dbc;
13036 if (d->sqlite) {
13037 setstatd(d, -1, "connection already established", "08002");
13038 return SQL_ERROR;
13039 }
13040 buf[0] = '\0';
13041 if (connInLen == SQL_NTS) {
13042 len = sizeof (buf) - 1;
13043 } else {
13044 len = min(connInLen, sizeof (buf) - 1);
13045 }
13046 if (connIn != NULL) {
13047 strncpy(buf, (char *) connIn, len);
13048 }
13049 buf[len] = '\0';
13050 if (!buf[0]) {
13051 setstatd(d, -1, "invalid connect attributes",
13052 (*d->ov3) ? "HY090" : "S1090");
13053 return SQL_ERROR;
13054 }
13055 dsn[0] = '\0';
13056 getdsnattr(buf, "DSN", dsn, sizeof (dsn));
13057
13058 /* special case: connIn is sole DSN value without keywords */
13059 if (!dsn[0] && !strchr(buf, ';') && !strchr(buf, '=')) {
13060 strncpy(dsn, buf, sizeof (dsn) - 1);
13061 dsn[sizeof (dsn) - 1] = '\0';
13062 }
13063
13064 busy[0] = '\0';
13065 getdsnattr(buf, "timeout", busy, sizeof (busy));
13066 #ifndef WITHOUT_DRIVERMGR
13067 if (dsn[0] && !busy[0]) {
13068 SQLGetPrivateProfileString(dsn, "timeout", "100000",
13069 busy, sizeof (busy), ODBC_INI);
13070 }
13071 #endif
13072 dbname[0] = '\0';
13073 getdsnattr(buf, "database", dbname, sizeof (dbname));
13074 #ifndef WITHOUT_DRIVERMGR
13075 if (dsn[0] && !dbname[0]) {
13076 SQLGetPrivateProfileString(dsn, "database", "",
13077 dbname, sizeof (dbname), ODBC_INI);
13078 }
13079 #endif
13080 sflag[0] = '\0';
13081 getdsnattr(buf, "stepapi", sflag, sizeof (sflag));
13082 #ifndef WITHOUT_DRIVERMGR
13083 if (dsn[0] && !sflag[0]) {
13084 SQLGetPrivateProfileString(dsn, "stepapi", "",
13085 sflag, sizeof (sflag), ODBC_INI);
13086 }
13087 #endif
13088 spflag[0] = '\0';
13089 getdsnattr(buf, "syncpragma", spflag, sizeof (spflag));
13090 #ifndef WITHOUT_DRIVERMGR
13091 if (dsn[0] && !spflag[0]) {
13092 SQLGetPrivateProfileString(dsn, "syncpragma", "NORMAL",
13093 spflag, sizeof (spflag), ODBC_INI);
13094 }
13095 #endif
13096 ntflag[0] = '\0';
13097 getdsnattr(buf, "notxn", ntflag, sizeof (ntflag));
13098 #ifndef WITHOUT_DRIVERMGR
13099 if (dsn[0] && !ntflag[0]) {
13100 SQLGetPrivateProfileString(dsn, "notxn", "",
13101 ntflag, sizeof (ntflag), ODBC_INI);
13102 }
13103 #endif
13104 snflag[0] = '\0';
13105 getdsnattr(buf, "shortnames", snflag, sizeof (snflag));
13106 #ifndef WITHOUT_DRIVERMGR
13107 if (dsn[0] && !snflag[0]) {
13108 SQLGetPrivateProfileString(dsn, "shortnames", "",
13109 snflag, sizeof (snflag), ODBC_INI);
13110 }
13111 #endif
13112 lnflag[0] = '\0';
13113 getdsnattr(buf, "longnames", lnflag, sizeof (lnflag));
13114 #ifndef WITHOUT_DRIVERMGR
13115 if (dsn[0] && !lnflag[0]) {
13116 SQLGetPrivateProfileString(dsn, "longnames", "",
13117 lnflag, sizeof (lnflag), ODBC_INI);
13118 }
13119 #endif
13120 ncflag[0] = '\0';
13121 getdsnattr(buf, "nocreat", ncflag, sizeof (ncflag));
13122 #ifndef WITHOUT_DRIVERMGR
13123 if (dsn[0] && !ncflag[0]) {
13124 SQLGetPrivateProfileString(dsn, "nocreat", "",
13125 ncflag, sizeof (ncflag), ODBC_INI);
13126 }
13127 #endif
13128 nwflag[0] = '\0';
13129 getdsnattr(buf, "nowchar", nwflag, sizeof (nwflag));
13130 #ifndef WITHOUT_DRIVERMGR
13131 if (dsn[0] && !nwflag[0]) {
13132 SQLGetPrivateProfileString(dsn, "nowchar", "",
13133 nwflag, sizeof (nwflag), ODBC_INI);
13134 }
13135 #endif
13136 fkflag[0] = '\0';
13137 getdsnattr(buf, "fksupport", fkflag, sizeof (fkflag));
13138 #ifndef WITHOUT_DRIVERMGR
13139 if (dsn[0] && !fkflag[0]) {
13140 SQLGetPrivateProfileString(dsn, "fksupport", "",
13141 fkflag, sizeof (fkflag), ODBC_INI);
13142 }
13143 #endif
13144 loadext[0] = '\0';
13145 getdsnattr(buf, "loadext", loadext, sizeof (loadext));
13146 #ifndef WITHOUT_DRIVERMGR
13147 if (dsn[0] && !loadext[0]) {
13148 SQLGetPrivateProfileString(dsn, "loadext", "",
13149 loadext, sizeof (loadext), ODBC_INI);
13150 }
13151 #endif
13152 jmode[0] = '\0';
13153 getdsnattr(buf, "journalmode", jmode, sizeof (jmode));
13154 #ifndef WITHOUT_DRIVERMGR
13155 if (dsn[0] && !jmode[0]) {
13156 SQLGetPrivateProfileString(dsn, "journalmode", "",
13157 jmode, sizeof (jmode), ODBC_INI);
13158 }
13159 #endif
13160 biflag[0] = '\0';
13161 getdsnattr(buf, "bigint", biflag, sizeof (biflag));
13162 #ifndef WITHOUT_DRIVERMGR
13163 if (dsn[0] && !biflag[0]) {
13164 SQLGetPrivateProfileString(dsn, "bigint", "",
13165 biflag, sizeof (biflag), ODBC_INI);
13166 }
13167 #endif
13168 jdflag[0] = '\0';
13169 getdsnattr(buf, "jdconv", jdflag, sizeof (jdflag));
13170 #ifndef WITHOUT_DRIVERMGR
13171 if (dsn[0] && !jdflag[0]) {
13172 SQLGetPrivateProfileString(dsn, "jdconv", "",
13173 jdflag, sizeof (jdflag), ODBC_INI);
13174 }
13175 #endif
13176 pwd[0] = '\0';
13177 getdsnattr(buf, "pwd", pwd, sizeof (pwd));
13178 #ifndef WITHOUT_DRIVERMGR
13179 if (dsn[0] && !pwd[0]) {
13180 SQLGetPrivateProfileString(dsn, "pwd", "",
13181 pwd, sizeof (pwd), ODBC_INI);
13182 }
13183 #endif
13184
13185 if (!dbname[0] && !dsn[0]) {
13186 strcpy(dsn, "SQLite");
13187 strncpy(dbname, buf, sizeof (dbname));
13188 dbname[sizeof (dbname) - 1] = '\0';
13189 }
13190 tracef[0] = '\0';
13191 getdsnattr(buf, "tracefile", tracef, sizeof (tracef));
13192 #ifndef WITHOUT_DRIVERMGR
13193 if (dsn[0] && !tracef[0]) {
13194 SQLGetPrivateProfileString(dsn, "tracefile", "",
13195 tracef, sizeof (tracef), ODBC_INI);
13196 }
13197 #endif
13198 if (connOut || connOutLen) {
13199 int count;
13200
13201 buf[0] = '\0';
13202 count = snprintf(buf, sizeof (buf),
13203 "DSN=%s;Database=%s;StepAPI=%s;Timeout=%s;"
13204 "SyncPragma=%s;NoTXN=%s;ShortNames=%s;LongNames=%s;"
13205 "NoCreat=%s;NoWCHAR=%s;FKSupport=%s;Tracefile=%s;"
13206 "JournalMode=%s;LoadExt=%s;BigInt=%s;JDConv=%s;"
13207 "PWD=%s",
13208 dsn, dbname, sflag, busy, spflag, ntflag,
13209 snflag, lnflag, ncflag, nwflag, fkflag, tracef,
13210 jmode, loadext, biflag, jdflag, pwd);
13211 if (count < 0) {
13212 buf[sizeof (buf) - 1] = '\0';
13213 }
13214 len = min(connOutMax - 1, strlen(buf));
13215 if (connOut) {
13216 strncpy((char *) connOut, buf, len);
13217 connOut[len] = '\0';
13218 }
13219 if (connOutLen) {
13220 *connOutLen = len;
13221 }
13222 }
13223 if (tracef[0] != '\0') {
13224 d->trace = fopen(tracef, "a");
13225 }
13226 d->shortnames = getbool(snflag);
13227 d->longnames = getbool(lnflag);
13228 d->nocreat = getbool(ncflag);
13229 d->nowchar = getbool(nwflag);
13230 d->fksupport = getbool(fkflag);
13231 d->dobigint = getbool(biflag);
13232 d->jdconv = getbool(jdflag);
13233 d->oemcp = 0;
13234 d->pwdLen = strlen(pwd);
13235 d->pwd = (d->pwdLen > 0) ? pwd : NULL;
13236 ret = dbopen(d, dbname, 0, dsn, sflag, spflag, ntflag, jmode, busy);
13237 memset(pwd, 0, sizeof (pwd));
13238 if (ret == SQL_SUCCESS) {
13239 dbloadext(d, loadext);
13240 }
13241 return ret;
13242 }
13243 #endif
13244
13245 /**
13246 * Internal free function for HSTMT.
13247 * @param stmt statement handle
13248 * @result ODBC error code
13249 */
13250
13251 static SQLRETURN
freestmt(SQLHSTMT stmt)13252 freestmt(SQLHSTMT stmt)
13253 {
13254 STMT *s;
13255 DBC *d;
13256
13257 if (stmt == SQL_NULL_HSTMT) {
13258 return SQL_INVALID_HANDLE;
13259 }
13260 s = (STMT *) stmt;
13261 s3stmt_drop(s);
13262 freeresult(s, 1);
13263 freep(&s->query);
13264 d = (DBC *) s->dbc;
13265 if (d && d->magic == DBC_MAGIC) {
13266 STMT *p, *n;
13267
13268 p = NULL;
13269 n = d->stmt;
13270 while (n) {
13271 if (n == s) {
13272 break;
13273 }
13274 p = n;
13275 n = n->next;
13276 }
13277 if (n) {
13278 if (p) {
13279 p->next = s->next;
13280 } else {
13281 d->stmt = s->next;
13282 }
13283 }
13284 }
13285 freeparams(s);
13286 freep(&s->bindparms);
13287 if (s->row_status0 != &s->row_status1) {
13288 freep(&s->row_status0);
13289 s->rowset_size = 1;
13290 s->row_status0 = &s->row_status1;
13291 }
13292 xfree(s);
13293 return SQL_SUCCESS;
13294 }
13295
13296 /**
13297 * Allocate HSTMT given HDBC (driver internal version).
13298 * @param dbc database connection handle
13299 * @param stmt pointer to statement handle
13300 * @result ODBC error code
13301 */
13302
13303 static SQLRETURN
drvallocstmt(SQLHDBC dbc,SQLHSTMT * stmt)13304 drvallocstmt(SQLHDBC dbc, SQLHSTMT *stmt)
13305 {
13306 DBC *d;
13307 STMT *s, *sl, *pl;
13308
13309 if (dbc == SQL_NULL_HDBC) {
13310 return SQL_INVALID_HANDLE;
13311 }
13312 d = (DBC *) dbc;
13313 if (d->magic != DBC_MAGIC || stmt == NULL) {
13314 return SQL_INVALID_HANDLE;
13315 }
13316 s = (STMT *) xmalloc(sizeof (STMT));
13317 if (s == NULL) {
13318 *stmt = SQL_NULL_HSTMT;
13319 return SQL_ERROR;
13320 }
13321 *stmt = (SQLHSTMT) s;
13322 memset(s, 0, sizeof (STMT));
13323 s->dbc = dbc;
13324 s->ov3 = d->ov3;
13325 s->bkmrk = SQL_UB_OFF;
13326 s->bkmrkptr = 0;
13327 s->oemcp = &d->oemcp;
13328 s->jdconv = &d->jdconv;
13329 s->nowchar[0] = d->nowchar;
13330 s->nowchar[1] = 0;
13331 s->dobigint = d->dobigint;
13332 s->curtype = d->curtype;
13333 s->row_status0 = &s->row_status1;
13334 s->rowset_size = 1;
13335 s->longnames = d->longnames;
13336 s->retr_data = SQL_RD_ON;
13337 s->max_rows = 0;
13338 s->bind_type = SQL_BIND_BY_COLUMN;
13339 s->bind_offs = NULL;
13340 s->paramset_size = 1;
13341 s->parm_bind_type = SQL_PARAM_BIND_BY_COLUMN;
13342 s->one_tbl = -1;
13343 s->has_pk = -1;
13344 s->has_rowid = -1;
13345 #ifdef _WIN64
13346 sprintf((char *) s->cursorname, "CUR_%I64X", (SQLUBIGINT) *stmt);
13347 #else
13348 sprintf((char *) s->cursorname, "CUR_%016lX", (long) *stmt);
13349 #endif
13350 sl = d->stmt;
13351 pl = NULL;
13352 while (sl) {
13353 pl = sl;
13354 sl = sl->next;
13355 }
13356 if (pl) {
13357 pl->next = s;
13358 } else {
13359 d->stmt = s;
13360 }
13361 return SQL_SUCCESS;
13362 }
13363
13364 /**
13365 * Allocate HSTMT given HDBC.
13366 * @param dbc database connection handle
13367 * @param stmt pointer to statement handle
13368 * @result ODBC error code
13369 */
13370
13371 SQLRETURN SQL_API
SQLAllocStmt(SQLHDBC dbc,SQLHSTMT * stmt)13372 SQLAllocStmt(SQLHDBC dbc, SQLHSTMT *stmt)
13373 {
13374 SQLRETURN ret;
13375
13376 HDBC_LOCK(dbc);
13377 ret = drvallocstmt(dbc, stmt);
13378 HDBC_UNLOCK(dbc);
13379 return ret;
13380 }
13381
13382 /**
13383 * Internal function to perform certain kinds of free/close on STMT.
13384 * @param stmt statement handle
13385 * @param opt SQL_RESET_PARAMS, SQL_UNBIND, SQL_CLOSE, or SQL_DROP
13386 * @result ODBC error code
13387 */
13388
13389 static SQLRETURN
drvfreestmt(SQLHSTMT stmt,SQLUSMALLINT opt)13390 drvfreestmt(SQLHSTMT stmt, SQLUSMALLINT opt)
13391 {
13392 STMT *s;
13393 SQLRETURN ret = SQL_SUCCESS;
13394 SQLHDBC dbc;
13395
13396 if (stmt == SQL_NULL_HSTMT) {
13397 return SQL_INVALID_HANDLE;
13398 }
13399 HSTMT_LOCK(stmt);
13400 s = (STMT *) stmt;
13401 dbc = s->dbc;
13402 switch (opt) {
13403 case SQL_RESET_PARAMS:
13404 freeparams(s);
13405 break;
13406 case SQL_UNBIND:
13407 unbindcols(s);
13408 break;
13409 case SQL_CLOSE:
13410 s3stmt_end_if(s);
13411 freeresult(s, 0);
13412 break;
13413 case SQL_DROP:
13414 s3stmt_end_if(s);
13415 ret = freestmt(stmt);
13416 break;
13417 default:
13418 setstat(s, -1, "unsupported option", (*s->ov3) ? "HYC00" : "S1C00");
13419 ret = SQL_ERROR;
13420 break;
13421 }
13422 HDBC_UNLOCK(dbc);
13423 return ret;
13424 }
13425
13426 /**
13427 * Free HSTMT.
13428 * @param stmt statement handle
13429 * @param opt SQL_RESET_PARAMS, SQL_UNBIND, SQL_CLOSE, or SQL_DROP
13430 * @result ODBC error code
13431 */
13432
13433 SQLRETURN SQL_API
SQLFreeStmt(SQLHSTMT stmt,SQLUSMALLINT opt)13434 SQLFreeStmt(SQLHSTMT stmt, SQLUSMALLINT opt)
13435 {
13436 return drvfreestmt(stmt, opt);
13437 }
13438
13439 /**
13440 * Cancel HSTMT closing cursor.
13441 * @param stmt statement handle
13442 * @result ODBC error code
13443 */
13444
13445 SQLRETURN SQL_API
SQLCancel(SQLHSTMT stmt)13446 SQLCancel(SQLHSTMT stmt)
13447 {
13448 if (stmt != SQL_NULL_HSTMT) {
13449 DBC *d = (DBC *) ((STMT *) stmt)->dbc;
13450 #if defined(_WIN32) || defined(_WIN64)
13451 /* interrupt when other thread owns critical section */
13452 if (d->magic == DBC_MAGIC && d->owner != GetCurrentThreadId() &&
13453 d->owner != 0) {
13454 d->busyint = 1;
13455 sqlite3_interrupt(d->sqlite);
13456 return SQL_SUCCESS;
13457 }
13458 #else
13459 if (d->magic == DBC_MAGIC) {
13460 d->busyint = 1;
13461 sqlite3_interrupt(d->sqlite);
13462 }
13463 #endif
13464 }
13465 return drvfreestmt(stmt, SQL_CLOSE);
13466 }
13467
13468 /**
13469 * Internal function to get cursor name of STMT.
13470 * @param stmt statement handle
13471 * @param cursor output buffer
13472 * @param buflen length of output buffer
13473 * @param lenp output length
13474 * @result ODBC error code
13475 */
13476
13477 static SQLRETURN
drvgetcursorname(SQLHSTMT stmt,SQLCHAR * cursor,SQLSMALLINT buflen,SQLSMALLINT * lenp)13478 drvgetcursorname(SQLHSTMT stmt, SQLCHAR *cursor, SQLSMALLINT buflen,
13479 SQLSMALLINT *lenp)
13480 {
13481 STMT *s;
13482
13483 if (stmt == SQL_NULL_HSTMT) {
13484 return SQL_INVALID_HANDLE;
13485 }
13486 s = (STMT *) stmt;
13487 if (lenp && !cursor) {
13488 *lenp = strlen((char *) s->cursorname);
13489 return SQL_SUCCESS;
13490 }
13491 if (cursor) {
13492 if (buflen > 0) {
13493 strncpy((char *) cursor, (char *) s->cursorname, buflen - 1);
13494 cursor[buflen - 1] = '\0';
13495 }
13496 if (lenp) {
13497 *lenp = min(strlen((char *) s->cursorname), buflen - 1);
13498 }
13499 }
13500 return SQL_SUCCESS;
13501 }
13502
13503 #ifndef WINTERFACE
13504 /**
13505 * Get cursor name of STMT.
13506 * @param stmt statement handle
13507 * @param cursor output buffer
13508 * @param buflen length of output buffer
13509 * @param lenp output length
13510 * @result ODBC error code
13511 */
13512
13513 SQLRETURN SQL_API
SQLGetCursorName(SQLHSTMT stmt,SQLCHAR * cursor,SQLSMALLINT buflen,SQLSMALLINT * lenp)13514 SQLGetCursorName(SQLHSTMT stmt, SQLCHAR *cursor, SQLSMALLINT buflen,
13515 SQLSMALLINT *lenp)
13516 {
13517 SQLRETURN ret;
13518 #if defined(_WIN32) || defined(_WIN64)
13519 SQLSMALLINT len = 0;
13520 #endif
13521
13522 HSTMT_LOCK(stmt);
13523 #if defined(_WIN32) || defined(_WIN64)
13524 if (!((STMT *) stmt)->oemcp[0]) {
13525 ret = drvgetcursorname(stmt, cursor, buflen, lenp);
13526 goto done;
13527 }
13528 ret = drvgetcursorname(stmt, cursor, buflen, &len);
13529 if (ret == SQL_SUCCESS) {
13530 char *c = NULL;
13531
13532 if (cursor) {
13533 c = utf_to_wmb((char *) cursor, len);
13534 if (!c) {
13535 ret = nomem((STMT *) stmt);
13536 goto done;
13537 }
13538 c[len] = 0;
13539 len = strlen(c);
13540 if (buflen > 0) {
13541 strncpy((char *) cursor, c, buflen - 1);
13542 cursor[buflen - 1] = 0;
13543 }
13544 uc_free(c);
13545 }
13546 if (lenp) {
13547 *lenp = min(len, buflen - 1);
13548 }
13549 }
13550 done:
13551 ;
13552 #else
13553 ret = drvgetcursorname(stmt, cursor, buflen, lenp);
13554 #endif
13555 HSTMT_UNLOCK(stmt);
13556 return ret;
13557 }
13558 #endif
13559
13560 #ifdef WINTERFACE
13561 /**
13562 * Get cursor name of STMT (UNICODE version).
13563 * @param stmt statement handle
13564 * @param cursor output buffer
13565 * @param buflen length of output buffer
13566 * @param lenp output length
13567 * @result ODBC error code
13568 */
13569
13570 SQLRETURN SQL_API
SQLGetCursorNameW(SQLHSTMT stmt,SQLWCHAR * cursor,SQLSMALLINT buflen,SQLSMALLINT * lenp)13571 SQLGetCursorNameW(SQLHSTMT stmt, SQLWCHAR *cursor, SQLSMALLINT buflen,
13572 SQLSMALLINT *lenp)
13573 {
13574 SQLRETURN ret;
13575 SQLSMALLINT len = 0;
13576
13577 HSTMT_LOCK(stmt);
13578 ret = drvgetcursorname(stmt, (SQLCHAR *) cursor, buflen, &len);
13579 if (ret == SQL_SUCCESS) {
13580 SQLWCHAR *c = NULL;
13581
13582 if (cursor) {
13583 c = uc_from_utf((SQLCHAR *) cursor, len);
13584 if (!c) {
13585 ret = nomem((STMT *) stmt);
13586 goto done;
13587 }
13588 c[len] = 0;
13589 len = uc_strlen(c);
13590 if (buflen > 0) {
13591 uc_strncpy(cursor, c, buflen - 1);
13592 cursor[buflen - 1] = 0;
13593 }
13594 uc_free(c);
13595 }
13596 if (lenp) {
13597 *lenp = min(len, buflen - 1);
13598 }
13599 }
13600 done:
13601 HSTMT_UNLOCK(stmt);
13602 return ret;
13603 }
13604 #endif
13605
13606 /**
13607 * Internal function to set cursor name on STMT.
13608 * @param stmt statement handle
13609 * @param cursor new cursor name
13610 * @param len length of cursor name or SQL_NTS
13611 * @result ODBC error code
13612 */
13613
13614 static SQLRETURN
drvsetcursorname(SQLHSTMT stmt,SQLCHAR * cursor,SQLSMALLINT len)13615 drvsetcursorname(SQLHSTMT stmt, SQLCHAR *cursor, SQLSMALLINT len)
13616 {
13617 STMT *s;
13618
13619 if (stmt == SQL_NULL_HSTMT) {
13620 return SQL_INVALID_HANDLE;
13621 }
13622 s = (STMT *) stmt;
13623 if (!cursor ||
13624 !((cursor[0] >= 'A' && cursor[0] <= 'Z') ||
13625 (cursor[0] >= 'a' && cursor[0] <= 'z'))) {
13626 setstat(s, -1, "invalid cursor name", (*s->ov3) ? "HYC00" : "S1C00");
13627 return SQL_ERROR;
13628 }
13629 if (len == SQL_NTS) {
13630 len = sizeof (s->cursorname) - 1;
13631 } else {
13632 len = min(sizeof (s->cursorname) - 1, len);
13633 }
13634 strncpy((char *) s->cursorname, (char *) cursor, len);
13635 s->cursorname[len] = '\0';
13636 return SQL_SUCCESS;
13637 }
13638
13639 #ifndef WINTERFACE
13640 /**
13641 * Set cursor name on STMT.
13642 * @param stmt statement handle
13643 * @param cursor new cursor name
13644 * @param len length of cursor name or SQL_NTS
13645 * @result ODBC error code
13646 */
13647
13648 SQLRETURN SQL_API
SQLSetCursorName(SQLHSTMT stmt,SQLCHAR * cursor,SQLSMALLINT len)13649 SQLSetCursorName(SQLHSTMT stmt, SQLCHAR *cursor, SQLSMALLINT len)
13650 {
13651 #if defined(_WIN32) || defined(_WIN64)
13652 char *c = NULL;
13653 #endif
13654 SQLRETURN ret;
13655
13656 HSTMT_LOCK(stmt);
13657 #if defined(_WIN32) || defined(_WIN64)
13658 if (!((STMT *) stmt)->oemcp[0]) {
13659 ret = drvsetcursorname(stmt, cursor, len);
13660 goto done2;
13661 }
13662 if (cursor) {
13663 c = wmb_to_utf_c((char *) cursor, len);
13664 if (!c) {
13665 ret = nomem((STMT *) stmt);
13666 goto done;
13667 }
13668 }
13669 ret = drvsetcursorname(stmt, (SQLCHAR *) c, SQL_NTS);
13670 #else
13671 ret = drvsetcursorname(stmt, cursor, len);
13672 #endif
13673 #if defined(_WIN32) || defined(_WIN64)
13674 done:
13675 uc_free(c);
13676 done2:
13677 ;
13678 #endif
13679 HSTMT_UNLOCK(stmt);
13680 return ret;
13681 }
13682 #endif
13683
13684 #ifdef WINTERFACE
13685 /**
13686 * Set cursor name on STMT (UNICODE version).
13687 * @param stmt statement handle
13688 * @param cursor new cursor name
13689 * @param len length of cursor name or SQL_NTS
13690 * @result ODBC error code
13691 */
13692
13693 SQLRETURN SQL_API
SQLSetCursorNameW(SQLHSTMT stmt,SQLWCHAR * cursor,SQLSMALLINT len)13694 SQLSetCursorNameW(SQLHSTMT stmt, SQLWCHAR *cursor, SQLSMALLINT len)
13695 {
13696 char *c = NULL;
13697 SQLRETURN ret;
13698
13699 HSTMT_LOCK(stmt);
13700 if (cursor) {
13701 c = uc_to_utf_c(cursor, len);
13702 if (!c) {
13703 ret = nomem((STMT *) stmt);
13704 goto done;
13705 }
13706 }
13707 ret = drvsetcursorname(stmt, (SQLCHAR *) c, SQL_NTS);
13708 done:
13709 uc_free(c);
13710 HSTMT_UNLOCK(stmt);
13711 return ret;
13712 }
13713 #endif
13714
13715 /**
13716 * Close open cursor.
13717 * @param stmt statement handle
13718 * @return ODBC error code
13719 */
13720
13721 SQLRETURN SQL_API
SQLCloseCursor(SQLHSTMT stmt)13722 SQLCloseCursor(SQLHSTMT stmt)
13723 {
13724 return drvfreestmt(stmt, SQL_CLOSE);
13725 }
13726
13727 /**
13728 * Allocate a HENV, HDBC, or HSTMT handle.
13729 * @param type handle type
13730 * @param input input handle (HENV, HDBC)
13731 * @param output pointer to output handle (HENV, HDBC, HSTMT)
13732 * @result ODBC error code
13733 */
13734
13735 SQLRETURN SQL_API
SQLAllocHandle(SQLSMALLINT type,SQLHANDLE input,SQLHANDLE * output)13736 SQLAllocHandle(SQLSMALLINT type, SQLHANDLE input, SQLHANDLE *output)
13737 {
13738 SQLRETURN ret;
13739
13740 switch (type) {
13741 case SQL_HANDLE_ENV:
13742 ret = drvallocenv((SQLHENV *) output);
13743 if (ret == SQL_SUCCESS) {
13744 ENV *e = (ENV *) *output;
13745
13746 if (e && e->magic == ENV_MAGIC) {
13747 e->ov3 = 1;
13748 }
13749 }
13750 return ret;
13751 case SQL_HANDLE_DBC:
13752 return drvallocconnect((SQLHENV) input, (SQLHDBC *) output);
13753 case SQL_HANDLE_STMT:
13754 HDBC_LOCK((SQLHDBC) input);
13755 ret = drvallocstmt((SQLHDBC) input, (SQLHSTMT *) output);
13756 HDBC_UNLOCK((SQLHDBC) input);
13757 return ret;
13758 }
13759 return SQL_ERROR;
13760 }
13761
13762 /**
13763 * Free a HENV, HDBC, or HSTMT handle.
13764 * @param type handle type
13765 * @param h handle (HENV, HDBC, or HSTMT)
13766 * @result ODBC error code
13767 */
13768
13769 SQLRETURN SQL_API
SQLFreeHandle(SQLSMALLINT type,SQLHANDLE h)13770 SQLFreeHandle(SQLSMALLINT type, SQLHANDLE h)
13771 {
13772 switch (type) {
13773 case SQL_HANDLE_ENV:
13774 return drvfreeenv((SQLHENV) h);
13775 case SQL_HANDLE_DBC:
13776 return drvfreeconnect((SQLHDBC) h);
13777 case SQL_HANDLE_STMT:
13778 return drvfreestmt((SQLHSTMT) h, SQL_DROP);
13779 }
13780 return SQL_ERROR;
13781 }
13782
13783 /**
13784 * Free dynamically allocated column descriptions of STMT.
13785 * @param s statement pointer
13786 */
13787
13788 static void
freedyncols(STMT * s)13789 freedyncols(STMT *s)
13790 {
13791 if (s->dyncols) {
13792 int i;
13793
13794 for (i = 0; i < s->dcols; i++) {
13795 freep(&s->dyncols[i].typename);
13796 }
13797 if (s->cols == s->dyncols) {
13798 s->cols = NULL;
13799 s->ncols = 0;
13800 }
13801 freep(&s->dyncols);
13802 }
13803 s->dcols = 0;
13804 }
13805
13806 /**
13807 * Free statement's result.
13808 * @param s statement pointer
13809 * @param clrcols flag to clear column information
13810 *
13811 * The result rows are free'd using the rowfree function pointer.
13812 * If clrcols is greater than zero, then column bindings and dynamic column
13813 * descriptions are free'd.
13814 * If clrcols is less than zero, then dynamic column descriptions are free'd.
13815 */
13816
13817 static void
freeresult(STMT * s,int clrcols)13818 freeresult(STMT *s, int clrcols)
13819 {
13820 freep(&s->bincache);
13821 s->bincell = NULL;
13822 s->binlen = 0;
13823 if (s->rows) {
13824 if (s->rowfree) {
13825 s->rowfree(s->rows);
13826 s->rowfree = NULL;
13827 }
13828 s->rows = NULL;
13829 }
13830 s->nrows = -1;
13831 if (clrcols > 0) {
13832 freep(&s->bindcols);
13833 s->nbindcols = 0;
13834 }
13835 if (clrcols) {
13836 freedyncols(s);
13837 s->cols = NULL;
13838 s->ncols = 0;
13839 s->nowchar[1] = 0;
13840 s->one_tbl = -1;
13841 s->has_pk = -1;
13842 s->has_rowid = -1;
13843 }
13844 }
13845
13846 /**
13847 * Reset bound columns to unbound state.
13848 * @param s statement pointer
13849 */
13850
13851 static void
unbindcols(STMT * s)13852 unbindcols(STMT *s)
13853 {
13854 int i;
13855
13856 for (i = 0; s->bindcols && i < s->nbindcols; i++) {
13857 s->bindcols[i].type = SQL_UNKNOWN_TYPE;
13858 s->bindcols[i].max = 0;
13859 s->bindcols[i].lenp = NULL;
13860 s->bindcols[i].valp = NULL;
13861 s->bindcols[i].index = i;
13862 s->bindcols[i].offs = 0;
13863 }
13864 }
13865
13866 /**
13867 * Reallocate space for bound columns.
13868 * @param s statement pointer
13869 * @param ncols number of columns
13870 * @result ODBC error code
13871 */
13872
13873 static SQLRETURN
mkbindcols(STMT * s,int ncols)13874 mkbindcols(STMT *s, int ncols)
13875 {
13876 if (s->bindcols) {
13877 if (s->nbindcols < ncols) {
13878 int i;
13879 BINDCOL *bindcols =
13880 xrealloc(s->bindcols, ncols * sizeof (BINDCOL));
13881
13882 if (!bindcols) {
13883 return nomem(s);
13884 }
13885 for (i = s->nbindcols; i < ncols; i++) {
13886 bindcols[i].type = SQL_UNKNOWN_TYPE;
13887 bindcols[i].max = 0;
13888 bindcols[i].lenp = NULL;
13889 bindcols[i].valp = NULL;
13890 bindcols[i].index = i;
13891 bindcols[i].offs = 0;
13892 }
13893 s->bindcols = bindcols;
13894 s->nbindcols = ncols;
13895 }
13896 } else if (ncols > 0) {
13897 s->bindcols = (BINDCOL *) xmalloc(ncols * sizeof (BINDCOL));
13898 if (!s->bindcols) {
13899 return nomem(s);
13900 }
13901 s->nbindcols = ncols;
13902 unbindcols(s);
13903 }
13904 return SQL_SUCCESS;
13905 }
13906
13907 /**
13908 * Internal function to retrieve row data, used by SQLFetch() and
13909 * friends and SQLGetData().
13910 * @param s statement pointer
13911 * @param col column number, 0 based
13912 * @param otype output data type
13913 * @param val output buffer
13914 * @param len length of output buffer
13915 * @param lenp output length
13916 * @param partial flag for partial data retrieval
13917 * @result ODBC error code
13918 */
13919
13920 static SQLRETURN
getrowdata(STMT * s,SQLUSMALLINT col,SQLSMALLINT otype,SQLPOINTER val,SQLINTEGER len,SQLLEN * lenp,int partial)13921 getrowdata(STMT *s, SQLUSMALLINT col, SQLSMALLINT otype,
13922 SQLPOINTER val, SQLINTEGER len, SQLLEN *lenp, int partial)
13923 {
13924 char **data, valdummy[16];
13925 SQLLEN dummy;
13926 SQLINTEGER *ilenp = NULL;
13927 int valnull = 0;
13928 int type = otype;
13929 SQLRETURN sret = SQL_NO_DATA;
13930
13931 if (!lenp) {
13932 lenp = &dummy;
13933 }
13934 /* workaround for JDK 1.7.0 on x86_64 */
13935 if (((SQLINTEGER *) lenp) + 1 == (SQLINTEGER *) val) {
13936 ilenp = (SQLINTEGER *) lenp;
13937 lenp = &dummy;
13938 }
13939 if (col >= s->ncols) {
13940 setstat(s, -1, "invalid column", (*s->ov3) ? "07009" : "S1002");
13941 return SQL_ERROR;
13942 }
13943 if (s->retr_data != SQL_RD_ON) {
13944 return SQL_SUCCESS;
13945 }
13946 if (!s->rows) {
13947 *lenp = SQL_NULL_DATA;
13948 goto done;
13949 }
13950 if (s->rowp < 0 || s->rowp >= s->nrows) {
13951 *lenp = SQL_NULL_DATA;
13952 goto done;
13953 }
13954 type = mapdeftype(type, s->cols[col].type, s->cols[col].nosign ? 1 : 0,
13955 s->nowchar[0]);
13956 #if (defined(_WIN32) || defined(_WIN64)) && defined(WINTERFACE)
13957 /* MS Access hack part 3 (map SQL_C_DEFAULT to SQL_C_CHAR) */
13958 if (type == SQL_C_WCHAR && otype == SQL_C_DEFAULT) {
13959 type = SQL_C_CHAR;
13960 }
13961 #endif
13962 data = s->rows + s->ncols + (s->rowp * s->ncols) + col;
13963 if (!val) {
13964 valnull = 1;
13965 val = (SQLPOINTER) valdummy;
13966 }
13967 if (*data == NULL) {
13968 *lenp = SQL_NULL_DATA;
13969 switch (type) {
13970 case SQL_C_UTINYINT:
13971 case SQL_C_TINYINT:
13972 case SQL_C_STINYINT:
13973 #ifdef SQL_BIT
13974 case SQL_C_BIT:
13975 #endif
13976 *((SQLCHAR *) val) = 0;
13977 break;
13978 case SQL_C_USHORT:
13979 case SQL_C_SHORT:
13980 case SQL_C_SSHORT:
13981 *((SQLSMALLINT *) val) = 0;
13982 break;
13983 case SQL_C_ULONG:
13984 case SQL_C_LONG:
13985 case SQL_C_SLONG:
13986 *((SQLINTEGER *) val) = 0;
13987 break;
13988 #ifdef SQL_BIGINT
13989 case SQL_C_SBIGINT:
13990 case SQL_C_UBIGINT:
13991 *((SQLBIGINT *) val) = 0;
13992 break;
13993 #endif
13994 case SQL_C_FLOAT:
13995 *((float *) val) = 0;
13996 break;
13997 case SQL_C_DOUBLE:
13998 *((double *) val) = 0;
13999 break;
14000 case SQL_C_BINARY:
14001 case SQL_C_CHAR:
14002 if (len > 0) {
14003 *((SQLCHAR *) val) = '\0';
14004 }
14005 break;
14006 #ifdef WCHARSUPPORT
14007 case SQL_C_WCHAR:
14008 if (len > 0) {
14009 *((SQLWCHAR *) val) = '\0';
14010 }
14011 break;
14012 #endif
14013 #ifdef SQL_C_TYPE_DATE
14014 case SQL_C_TYPE_DATE:
14015 #endif
14016 case SQL_C_DATE:
14017 memset((DATE_STRUCT *) val, 0, sizeof (DATE_STRUCT));
14018 break;
14019 #ifdef SQL_C_TYPE_TIME
14020 case SQL_C_TYPE_TIME:
14021 #endif
14022 case SQL_C_TIME:
14023 memset((TIME_STRUCT *) val, 0, sizeof (TIME_STRUCT));
14024 break;
14025 #ifdef SQL_C_TYPE_TIMESTAMP
14026 case SQL_C_TYPE_TIMESTAMP:
14027 #endif
14028 case SQL_C_TIMESTAMP:
14029 memset((TIMESTAMP_STRUCT *) val, 0, sizeof (TIMESTAMP_STRUCT));
14030 break;
14031 default:
14032 return SQL_ERROR;
14033 }
14034 } else {
14035 char *endp = NULL;
14036 #if defined(_WIN32) || defined(_WIN64)
14037 #ifdef SQL_BIGINT
14038 char endc;
14039 #endif
14040 #endif
14041
14042 switch (type) {
14043 case SQL_C_UTINYINT:
14044 case SQL_C_TINYINT:
14045 case SQL_C_STINYINT:
14046 *((SQLCHAR *) val) = strtol(*data, &endp, 0);
14047 if (endp && endp == *data) {
14048 *lenp = SQL_NULL_DATA;
14049 } else {
14050 *lenp = sizeof (SQLCHAR);
14051 }
14052 break;
14053 #ifdef SQL_BIT
14054 case SQL_C_BIT:
14055 *((SQLCHAR *) val) = getbool(*data);
14056 *lenp = sizeof (SQLCHAR);
14057 break;
14058 #endif
14059 case SQL_C_USHORT:
14060 case SQL_C_SHORT:
14061 case SQL_C_SSHORT:
14062 *((SQLSMALLINT *) val) = strtol(*data, &endp, 0);
14063 if (endp && endp == *data) {
14064 *lenp = SQL_NULL_DATA;
14065 } else {
14066 *lenp = sizeof (SQLSMALLINT);
14067 }
14068 break;
14069 case SQL_C_ULONG:
14070 case SQL_C_LONG:
14071 case SQL_C_SLONG:
14072 *((SQLINTEGER *) val) = strtol(*data, &endp, 0);
14073 if (endp && endp == *data) {
14074 *lenp = SQL_NULL_DATA;
14075 } else {
14076 *lenp = sizeof (SQLINTEGER);
14077 }
14078 break;
14079 #ifdef SQL_BIGINT
14080 case SQL_C_UBIGINT:
14081 #if defined(_WIN32) || defined(_WIN64)
14082 if (sscanf(*data, "%I64u%c", (SQLUBIGINT *) val, &endc) != 1) {
14083 *lenp = SQL_NULL_DATA;
14084 } else {
14085 *lenp = sizeof (SQLUBIGINT);
14086 }
14087 #else
14088 #ifdef __osf__
14089 *((SQLUBIGINT *) val) = strtoul(*data, &endp, 0);
14090 #else
14091 *((SQLUBIGINT *) val) = strtoull(*data, &endp, 0);
14092 #endif
14093 if (endp && endp == *data) {
14094 *lenp = SQL_NULL_DATA;
14095 } else {
14096 *lenp = sizeof (SQLUBIGINT);
14097 }
14098 #endif
14099 break;
14100 case SQL_C_SBIGINT:
14101 #if defined(_WIN32) || defined(_WIN64)
14102 if (sscanf(*data, "%I64d%c", (SQLBIGINT *) val, &endc) != 1) {
14103 *lenp = SQL_NULL_DATA;
14104 } else {
14105 *lenp = sizeof (SQLBIGINT);
14106 }
14107 #else
14108 #ifdef __osf__
14109 *((SQLBIGINT *) val) = strtol(*data, &endp, 0);
14110 #else
14111 *((SQLBIGINT *) val) = strtoll(*data, &endp, 0);
14112 #endif
14113 if (endp && endp == *data) {
14114 *lenp = SQL_NULL_DATA;
14115 } else {
14116 *lenp = sizeof (SQLBIGINT);
14117 }
14118 #endif
14119 break;
14120 #endif
14121 case SQL_C_FLOAT:
14122 *((float *) val) = ln_strtod(*data, &endp);
14123 if (endp && endp == *data) {
14124 *lenp = SQL_NULL_DATA;
14125 } else {
14126 *lenp = sizeof (float);
14127 }
14128 break;
14129 case SQL_C_DOUBLE:
14130 *((double *) val) = ln_strtod(*data, &endp);
14131 if (endp && endp == *data) {
14132 *lenp = SQL_NULL_DATA;
14133 } else {
14134 *lenp = sizeof (double);
14135 }
14136 break;
14137 case SQL_C_BINARY: {
14138 int dlen, offs = 0;
14139 char *bin;
14140
14141 if (valnull) {
14142 freep(&s->bincache);
14143 s->binlen = 0;
14144 goto doCHAR;
14145 }
14146 if (*data == s->bincell) {
14147 if (s->bincache) {
14148 bin = s->bincache;
14149 dlen = s->binlen;
14150 } else {
14151 goto doCHAR;
14152 }
14153 } else {
14154 char *dp;
14155 int i;
14156
14157 freep(&s->bincache);
14158 dp = *data;
14159 dlen = strlen(dp);
14160 s->bincell = dp;
14161 s->binlen = 0;
14162 if (!(dp[0] == 'x' || dp[0] == 'X') || dp[1] != '\'' ||
14163 dp[dlen - 1] != '\'') {
14164 goto doCHAR;
14165 }
14166 dlen -= 2;
14167 dp += 2;
14168 dlen = dlen / 2;
14169 s->bincache = bin = xmalloc(dlen + 1);
14170 if (!bin) {
14171 return nomem(s);
14172 }
14173 s->binlen = dlen;
14174 memset(bin, 0, dlen);
14175 bin[dlen] = '\0'; /* terminator, just in case */
14176 for (i = 0; i < dlen; i++) {
14177 char *x;
14178 int v;
14179
14180 if (!*dp || !(x = strchr(xdigits, *dp))) {
14181 goto converr;
14182 }
14183 v = x - xdigits;
14184 bin[i] = (v >= 16) ? ((v - 6) << 4) : (v << 4);
14185 ++dp;
14186 if (!*dp || !(x = strchr(xdigits, *dp))) {
14187 converr:
14188 freep(&s->bincache);
14189 s->binlen = 0;
14190 setstat(s, -1, "conversion error",
14191 (*s->ov3) ? "HY000" : "S1000");
14192 return SQL_ERROR;
14193 }
14194 v = x - xdigits;
14195 bin[i] |= (v >= 16) ? (v - 6) : v;
14196 ++dp;
14197 }
14198 bin = s->bincache;
14199 }
14200 if (partial && len && s->bindcols) {
14201 if (s->bindcols[col].offs >= dlen) {
14202 *lenp = 0;
14203 if (!dlen && s->bindcols[col].offs == dlen) {
14204 s->bindcols[col].offs = 1;
14205 sret = SQL_SUCCESS;
14206 goto done;
14207 }
14208 s->bindcols[col].offs = 0;
14209 sret = SQL_NO_DATA;
14210 goto done;
14211 }
14212 offs = s->bindcols[col].offs;
14213 dlen -= offs;
14214 }
14215 if (val && len) {
14216 memcpy(val, bin + offs, min(len, dlen));
14217 }
14218 if (len < 1) {
14219 *lenp = dlen;
14220 } else {
14221 *lenp = min(len, dlen);
14222 if (*lenp == len && *lenp != dlen) {
14223 *lenp = SQL_NO_TOTAL;
14224 }
14225 }
14226 if (partial && len && s->bindcols) {
14227 if (*lenp == SQL_NO_TOTAL) {
14228 *lenp = dlen;
14229 s->bindcols[col].offs += len;
14230 setstat(s, -1, "data right truncated", "01004");
14231 if (s->bindcols[col].lenp) {
14232 *s->bindcols[col].lenp = dlen;
14233 }
14234 sret = SQL_SUCCESS_WITH_INFO;
14235 goto done;
14236 }
14237 s->bindcols[col].offs += *lenp;
14238 }
14239 if (*lenp == SQL_NO_TOTAL) {
14240 *lenp = dlen;
14241 setstat(s, -1, "data right truncated", "01004");
14242 sret = SQL_SUCCESS_WITH_INFO;
14243 goto done;
14244 }
14245 break;
14246 }
14247 doCHAR:
14248 #ifdef WCHARSUPPORT
14249 case SQL_C_WCHAR:
14250 #endif
14251 case SQL_C_CHAR: {
14252 int doz, zlen = len - 1;
14253 int dlen = strlen(*data);
14254 int offs = 0;
14255 #ifdef WCHARSUPPORT
14256 SQLWCHAR *ucdata = NULL;
14257 SQLCHAR *cdata = (SQLCHAR *) *data;
14258 #endif
14259
14260 #if (defined(_WIN32) || defined(_WIN64)) && defined(WINTERFACE)
14261 /* MS Access hack part 2 (reserved error -7748) */
14262 if (!valnull &&
14263 (s->cols == statSpec2P || s->cols == statSpec3P) &&
14264 type == SQL_C_WCHAR) {
14265 if (len > 0 && len <= sizeof (SQLWCHAR)) {
14266 ((char *) val)[0] = data[0][0];
14267 memset((char *) val + 1, 0, len - 1);
14268 *lenp = 1;
14269 sret = SQL_SUCCESS;
14270 goto done;
14271 }
14272 }
14273 #endif
14274
14275 #ifdef WCHARSUPPORT
14276 switch (type) {
14277 case SQL_C_CHAR:
14278 doz = 1;
14279 break;
14280 case SQL_C_WCHAR:
14281 doz = sizeof (SQLWCHAR);
14282 break;
14283 default:
14284 doz = 0;
14285 break;
14286 }
14287 if (type == SQL_C_WCHAR) {
14288 ucdata = uc_from_utf(cdata, dlen);
14289 if (!ucdata) {
14290 return nomem(s);
14291 }
14292 dlen = uc_strlen(ucdata) * sizeof (SQLWCHAR);
14293 }
14294 #if defined(_WIN32) || defined(_WIN64)
14295 else if (*s->oemcp && type == SQL_C_CHAR) {
14296 ucdata = (SQLWCHAR *) utf_to_wmb((char *) cdata, dlen);
14297 if (!ucdata) {
14298 return nomem(s);
14299 }
14300 cdata = (SQLCHAR *) ucdata;
14301 dlen = strlen((char *) cdata);
14302 }
14303 #endif
14304 #else
14305 doz = (type == SQL_C_CHAR) ? 1 : 0;
14306 #endif
14307 if (partial && len && s->bindcols) {
14308 if (s->bindcols[col].offs >= dlen) {
14309 #ifdef WCHARSUPPORT
14310 uc_free(ucdata);
14311 #endif
14312 *lenp = 0;
14313 if (doz && val) {
14314 #ifdef WCHARSUPPORT
14315 if (type == SQL_C_WCHAR) {
14316 ((SQLWCHAR *) val)[0] = 0;
14317 } else {
14318 ((char *) val)[0] = '\0';
14319 }
14320 #else
14321 ((char *) val)[0] = '\0';
14322 #endif
14323 }
14324 if (!dlen && s->bindcols[col].offs == dlen) {
14325 s->bindcols[col].offs = 1;
14326 sret = SQL_SUCCESS;
14327 goto done;
14328 }
14329 s->bindcols[col].offs = 0;
14330 sret = SQL_NO_DATA;
14331 goto done;
14332 }
14333 offs = s->bindcols[col].offs;
14334 dlen -= offs;
14335 }
14336 if (val && !valnull && len) {
14337 #ifdef WCHARSUPPORT
14338 if (type == SQL_C_WCHAR) {
14339 uc_strncpy(val, ucdata + offs / sizeof (SQLWCHAR),
14340 (len - doz) / sizeof (SQLWCHAR));
14341 } else {
14342 strncpy(val, (char *) cdata + offs, len - doz);
14343 }
14344 #else
14345 strncpy(val, *data + offs, len - doz);
14346 #endif
14347 }
14348 if (valnull || len < 1) {
14349 *lenp = dlen;
14350 } else {
14351 *lenp = min(len - doz, dlen);
14352 if (*lenp == len - doz && *lenp != dlen) {
14353 *lenp = SQL_NO_TOTAL;
14354 } else if (*lenp < zlen) {
14355 zlen = *lenp;
14356 }
14357 }
14358 if (len && !valnull && doz) {
14359 #ifdef WCHARSUPPORT
14360 if (type == SQL_C_WCHAR) {
14361 ((SQLWCHAR *) val)[zlen / sizeof (SQLWCHAR)] = 0;
14362 } else {
14363 ((char *) val)[zlen] = '\0';
14364 }
14365 #else
14366 ((char *) val)[zlen] = '\0';
14367 #endif
14368 }
14369 #ifdef WCHARSUPPORT
14370 uc_free(ucdata);
14371 #endif
14372 if (partial && len && s->bindcols) {
14373 if (*lenp == SQL_NO_TOTAL) {
14374 *lenp = dlen;
14375 s->bindcols[col].offs += len - doz;
14376 setstat(s, -1, "data right truncated", "01004");
14377 if (s->bindcols[col].lenp) {
14378 *s->bindcols[col].lenp = dlen;
14379 }
14380 sret = SQL_SUCCESS_WITH_INFO;
14381 goto done;
14382 }
14383 s->bindcols[col].offs += *lenp;
14384 }
14385 if (*lenp == SQL_NO_TOTAL) {
14386 *lenp = dlen;
14387 setstat(s, -1, "data right truncated", "01004");
14388 sret = SQL_SUCCESS_WITH_INFO;
14389 goto done;
14390 }
14391 break;
14392 }
14393 #ifdef SQL_C_TYPE_DATE
14394 case SQL_C_TYPE_DATE:
14395 #endif
14396 case SQL_C_DATE:
14397 if (str2date(*s->jdconv, *data, (DATE_STRUCT *) val) < 0) {
14398 *lenp = SQL_NULL_DATA;
14399 } else {
14400 *lenp = sizeof (DATE_STRUCT);
14401 }
14402 break;
14403 #ifdef SQL_C_TYPE_TIME
14404 case SQL_C_TYPE_TIME:
14405 #endif
14406 case SQL_C_TIME:
14407 if (str2time(*s->jdconv, *data, (TIME_STRUCT *) val) < 0) {
14408 *lenp = SQL_NULL_DATA;
14409 } else {
14410 *lenp = sizeof (TIME_STRUCT);
14411 }
14412 break;
14413 #ifdef SQL_C_TYPE_TIMESTAMP
14414 case SQL_C_TYPE_TIMESTAMP:
14415 #endif
14416 case SQL_C_TIMESTAMP:
14417 if (str2timestamp(*s->jdconv, *data,
14418 (TIMESTAMP_STRUCT *) val) < 0) {
14419 *lenp = SQL_NULL_DATA;
14420 } else {
14421 *lenp = sizeof (TIMESTAMP_STRUCT);
14422 }
14423 switch (s->cols[col].prec) {
14424 case 0:
14425 ((TIMESTAMP_STRUCT *) val)->fraction = 0;
14426 break;
14427 case 1:
14428 ((TIMESTAMP_STRUCT *) val)->fraction /= 100000000;
14429 ((TIMESTAMP_STRUCT *) val)->fraction *= 100000000;
14430 break;
14431 case 2:
14432 ((TIMESTAMP_STRUCT *) val)->fraction /= 10000000;
14433 ((TIMESTAMP_STRUCT *) val)->fraction *= 10000000;
14434 break;
14435 }
14436 break;
14437 default:
14438 return SQL_ERROR;
14439 }
14440 }
14441 sret = SQL_SUCCESS;
14442 done:
14443 if (ilenp) {
14444 *ilenp = *lenp;
14445 }
14446 return sret;
14447 }
14448
14449 /**
14450 * Internal bind C variable to column of result set.
14451 * @param stmt statement handle
14452 * @param col column number, starting at 1
14453 * @param type output type
14454 * @param val output buffer
14455 * @param max length of output buffer
14456 * @param lenp output length pointer
14457 * @result ODBC error code
14458 */
14459
14460 static SQLRETURN
drvbindcol(SQLHSTMT stmt,SQLUSMALLINT col,SQLSMALLINT type,SQLPOINTER val,SQLLEN max,SQLLEN * lenp)14461 drvbindcol(SQLHSTMT stmt, SQLUSMALLINT col, SQLSMALLINT type,
14462 SQLPOINTER val, SQLLEN max, SQLLEN *lenp)
14463 {
14464 STMT *s;
14465 int sz = 0;
14466
14467 if (stmt == SQL_NULL_HSTMT) {
14468 return SQL_INVALID_HANDLE;
14469 }
14470 s = (STMT *) stmt;
14471 if (col < 1) {
14472 if (col == 0 && s->bkmrk == SQL_UB_ON &&
14473 type == SQL_C_BOOKMARK) {
14474 s->bkmrkcol.type = val ? type : SQL_UNKNOWN_TYPE;
14475 s->bkmrkcol.max = val ? sizeof (SQLINTEGER) : 0;
14476 s->bkmrkcol.lenp = val ? lenp : 0;
14477 s->bkmrkcol.valp = val;
14478 s->bkmrkcol.offs = 0;
14479 if (val && lenp) {
14480 *lenp = 0;
14481 }
14482 return SQL_SUCCESS;
14483 } else if (col == 0 && s->bkmrk == SQL_UB_VARIABLE &&
14484 type == SQL_C_VARBOOKMARK &&
14485 max >= sizeof (sqlite_int64)) {
14486 s->bkmrkcol.type = val ? type : SQL_UNKNOWN_TYPE;
14487 s->bkmrkcol.max = val ? max : 0;
14488 s->bkmrkcol.lenp = val ? lenp : 0;
14489 s->bkmrkcol.valp = val;
14490 s->bkmrkcol.offs = 0;
14491 if (val && lenp) {
14492 *lenp = 0;
14493 }
14494 return SQL_SUCCESS;
14495 }
14496 setstat(s, -1, "invalid column", (*s->ov3) ? "07009" : "S1002");
14497 return SQL_ERROR;
14498 }
14499 if (mkbindcols(s, col) != SQL_SUCCESS) {
14500 return SQL_ERROR;
14501 }
14502 --col;
14503 if (type == SQL_C_DEFAULT) {
14504 type = mapdeftype(type, s->cols[col].type, 0,
14505 s->nowchar[0] || s->nowchar[1]);
14506 }
14507 switch (type) {
14508 case SQL_C_LONG:
14509 case SQL_C_ULONG:
14510 case SQL_C_SLONG:
14511 sz = sizeof (SQLINTEGER);
14512 break;
14513 case SQL_C_TINYINT:
14514 case SQL_C_UTINYINT:
14515 case SQL_C_STINYINT:
14516 sz = sizeof (SQLCHAR);
14517 break;
14518 case SQL_C_SHORT:
14519 case SQL_C_USHORT:
14520 case SQL_C_SSHORT:
14521 sz = sizeof (SQLSMALLINT);
14522 break;
14523 case SQL_C_FLOAT:
14524 sz = sizeof (SQLFLOAT);
14525 break;
14526 case SQL_C_DOUBLE:
14527 sz = sizeof (SQLDOUBLE);
14528 break;
14529 case SQL_C_TIMESTAMP:
14530 sz = sizeof (SQL_TIMESTAMP_STRUCT);
14531 break;
14532 case SQL_C_TIME:
14533 sz = sizeof (SQL_TIME_STRUCT);
14534 break;
14535 case SQL_C_DATE:
14536 sz = sizeof (SQL_DATE_STRUCT);
14537 break;
14538 case SQL_C_CHAR:
14539 break;
14540 #ifdef WCHARSUPPORT
14541 case SQL_C_WCHAR:
14542 break;
14543 #endif
14544 #ifdef SQL_C_TYPE_DATE
14545 case SQL_C_TYPE_DATE:
14546 sz = sizeof (SQL_DATE_STRUCT);
14547 break;
14548 #endif
14549 #ifdef SQL_C_TYPE_TIME
14550 case SQL_C_TYPE_TIME:
14551 sz = sizeof (SQL_TIME_STRUCT);
14552 break;
14553 #endif
14554 #ifdef SQL_C_TYPE_TIMESTAMP
14555 case SQL_C_TYPE_TIMESTAMP:
14556 sz = sizeof (SQL_TIMESTAMP_STRUCT);
14557 break;
14558 #endif
14559 #ifdef SQL_BIT
14560 case SQL_C_BIT:
14561 sz = sizeof (SQLCHAR);
14562 break;
14563 #endif
14564 case SQL_C_BINARY:
14565 break;
14566 #ifdef SQL_BIGINT
14567 case SQL_C_SBIGINT:
14568 case SQL_C_UBIGINT:
14569 sz = sizeof (SQLBIGINT);
14570 break;
14571 #endif
14572 default:
14573 if (val == NULL) {
14574 /* fall through, unbinding column */
14575 break;
14576 }
14577 setstat(s, -1, "invalid type %d", "HY003", type);
14578 return SQL_ERROR;
14579 }
14580 if (val == NULL) {
14581 /* unbind column */
14582 s->bindcols[col].type = SQL_UNKNOWN_TYPE;
14583 s->bindcols[col].max = 0;
14584 s->bindcols[col].lenp = NULL;
14585 s->bindcols[col].valp = NULL;
14586 s->bindcols[col].offs = 0;
14587 } else {
14588 if (sz == 0 && max < 0) {
14589 setstat(s, -1, "invalid length", "HY090");
14590 return SQL_ERROR;
14591 }
14592 s->bindcols[col].type = type;
14593 s->bindcols[col].max = (sz == 0) ? max : sz;
14594 s->bindcols[col].lenp = lenp;
14595 s->bindcols[col].valp = val;
14596 s->bindcols[col].offs = 0;
14597 if (lenp) {
14598 *lenp = 0;
14599 }
14600 }
14601 return SQL_SUCCESS;
14602 }
14603
14604 /**
14605 * Bind C variable to column of result set.
14606 * @param stmt statement handle
14607 * @param col column number, starting at 1
14608 * @param type output type
14609 * @param val output buffer
14610 * @param max length of output buffer
14611 * @param lenp output length pointer
14612 * @result ODBC error code
14613 */
14614
14615 SQLRETURN SQL_API
SQLBindCol(SQLHSTMT stmt,SQLUSMALLINT col,SQLSMALLINT type,SQLPOINTER val,SQLLEN max,SQLLEN * lenp)14616 SQLBindCol(SQLHSTMT stmt, SQLUSMALLINT col, SQLSMALLINT type,
14617 SQLPOINTER val, SQLLEN max, SQLLEN *lenp)
14618 {
14619 SQLRETURN ret;
14620
14621 HSTMT_LOCK(stmt);
14622 ret = drvbindcol(stmt, col, type, val, max, lenp);
14623 HSTMT_UNLOCK(stmt);
14624 return ret;
14625 }
14626
14627 /**
14628 * Columns for result set of SQLTables().
14629 */
14630
14631 static COL tableSpec2[] = {
14632 { "SYSTEM", "COLUMN", "TABLE_QUALIFIER", SCOL_VARCHAR, 50 },
14633 { "SYSTEM", "COLUMN", "TABLE_OWNER", SCOL_VARCHAR, 50 },
14634 { "SYSTEM", "COLUMN", "TABLE_NAME", SCOL_VARCHAR, 255 },
14635 { "SYSTEM", "COLUMN", "TABLE_TYPE", SCOL_VARCHAR, 50 },
14636 { "SYSTEM", "COLUMN", "REMARKS", SCOL_VARCHAR, 50 }
14637 };
14638
14639 static COL tableSpec3[] = {
14640 { "SYSTEM", "COLUMN", "TABLE_CAT", SCOL_VARCHAR, 50 },
14641 { "SYSTEM", "COLUMN", "TABLE_SCHEM", SCOL_VARCHAR, 50 },
14642 { "SYSTEM", "COLUMN", "TABLE_NAME", SCOL_VARCHAR, 255 },
14643 { "SYSTEM", "COLUMN", "TABLE_TYPE", SCOL_VARCHAR, 50 },
14644 { "SYSTEM", "COLUMN", "REMARKS", SCOL_VARCHAR, 50 }
14645 };
14646
14647 /**
14648 * Retrieve information on tables and/or views.
14649 * @param stmt statement handle
14650 * @param cat catalog name/pattern or NULL
14651 * @param catLen length of catalog name/pattern or SQL_NTS
14652 * @param schema schema name/pattern or NULL
14653 * @param schemaLen length of schema name/pattern or SQL_NTS
14654 * @param table table name/pattern or NULL
14655 * @param tableLen length of table name/pattern or SQL_NTS
14656 * @param type types of tables string or NULL
14657 * @param typeLen length of types of tables string or SQL_NTS
14658 * @result ODBC error code
14659 */
14660
14661 static SQLRETURN
drvtables(SQLHSTMT stmt,SQLCHAR * cat,SQLSMALLINT catLen,SQLCHAR * schema,SQLSMALLINT schemaLen,SQLCHAR * table,SQLSMALLINT tableLen,SQLCHAR * type,SQLSMALLINT typeLen)14662 drvtables(SQLHSTMT stmt,
14663 SQLCHAR *cat, SQLSMALLINT catLen,
14664 SQLCHAR *schema, SQLSMALLINT schemaLen,
14665 SQLCHAR *table, SQLSMALLINT tableLen,
14666 SQLCHAR *type, SQLSMALLINT typeLen)
14667 {
14668 SQLRETURN ret;
14669 STMT *s;
14670 DBC *d;
14671 int ncols, asize, rc, size, npatt;
14672 char *errp = NULL, *sql, tname[512];
14673 char *where = "(type = 'table' or type = 'view')";
14674
14675 ret = mkresultset(stmt, tableSpec2, array_size(tableSpec2),
14676 tableSpec3, array_size(tableSpec3), &asize);
14677 if (ret != SQL_SUCCESS) {
14678 return ret;
14679 }
14680 s = (STMT *) stmt;
14681 d = (DBC *) s->dbc;
14682 if (type && (typeLen > 0 || typeLen == SQL_NTS) && type[0] == '%') {
14683 int size = 3 * asize;
14684
14685 s->rows = xmalloc(size * sizeof (char *));
14686 if (!s->rows) {
14687 s->nrows = 0;
14688 return nomem(s);
14689 }
14690 memset(s->rows, 0, sizeof (char *) * size);
14691 s->ncols = asize;
14692 s->rows[s->ncols + 0] = "";
14693 s->rows[s->ncols + 1] = "";
14694 s->rows[s->ncols + 2] = "";
14695 s->rows[s->ncols + 3] = "TABLE";
14696 s->rows[s->ncols + 5] = "";
14697 s->rows[s->ncols + 6] = "";
14698 s->rows[s->ncols + 7] = "";
14699 s->rows[s->ncols + 8] = "VIEW";
14700 #ifdef MEMORY_DEBUG
14701 s->rowfree = xfree__;
14702 #else
14703 s->rowfree = sqlite3_free;
14704 #endif
14705 s->nrows = 2;
14706 s->rowp = s->rowprs = -1;
14707 return SQL_SUCCESS;
14708 }
14709 if (cat && (catLen > 0 || catLen == SQL_NTS) && cat[0] == '%') {
14710 table = NULL;
14711 goto doit;
14712 }
14713 if (schema && (schemaLen > 0 || schemaLen == SQL_NTS) &&
14714 schema[0] == '%') {
14715 if ((!cat || catLen == 0 || !cat[0]) &&
14716 (!table || tableLen == 0 || !table[0])) {
14717 table = NULL;
14718 goto doit;
14719 }
14720 }
14721 if (type && (typeLen > 0 || typeLen == SQL_NTS) && type[0] != '\0') {
14722 char tmp[256], *t;
14723 int with_view = 0, with_table = 0;
14724
14725 if (typeLen == SQL_NTS) {
14726 strncpy(tmp, (char *) type, sizeof (tmp));
14727 tmp[sizeof (tmp) - 1] = '\0';
14728 } else {
14729 int len = min(sizeof (tmp) - 1, typeLen);
14730
14731 strncpy(tmp, (char *) type, len);
14732 tmp[len] = '\0';
14733 }
14734 t = tmp;
14735 while (*t) {
14736 *t = TOLOWER(*t);
14737 t++;
14738 }
14739 t = tmp;
14740 unescpat(t);
14741 while (t) {
14742 if (t[0] == '\'') {
14743 ++t;
14744 }
14745 if (strncmp(t, "table", 5) == 0) {
14746 with_table++;
14747 } else if (strncmp(t, "view", 4) == 0) {
14748 with_view++;
14749 }
14750 t = strchr(t, ',');
14751 if (t) {
14752 ++t;
14753 }
14754 }
14755 if (with_view && with_table) {
14756 /* where is already preset */
14757 } else if (with_view && !with_table) {
14758 where = "type = 'view'";
14759 } else if (!with_view && with_table) {
14760 where = "type = 'table'";
14761 } else {
14762 return SQL_SUCCESS;
14763 }
14764 }
14765 doit:
14766 if (!table) {
14767 size = 1;
14768 tname[0] = '%';
14769 } else {
14770 if (tableLen == SQL_NTS) {
14771 size = sizeof (tname) - 1;
14772 } else {
14773 size = min(sizeof (tname) - 1, tableLen);
14774 }
14775 strncpy(tname, (char *) table, size);
14776 }
14777 tname[size] = '\0';
14778 npatt = unescpat(tname);
14779 #if defined(_WIN32) || defined(_WIN64)
14780 if (npatt) {
14781 sql = sqlite3_mprintf("select %s as 'TABLE_CAT', "
14782 "%s as 'TABLE_SCHEM', "
14783 "tbl_name as 'TABLE_NAME', "
14784 "upper(type) as 'TABLE_TYPE', "
14785 "NULL as 'REMARKS' "
14786 "from sqlite_master where %s "
14787 "and tbl_name like %Q",
14788 d->xcelqrx ? "'main'" : "NULL",
14789 d->xcelqrx ? "''" : "NULL",
14790 where, tname);
14791 } else {
14792 sql = sqlite3_mprintf("select %s as 'TABLE_CAT', "
14793 "%s as 'TABLE_SCHEM', "
14794 "tbl_name as 'TABLE_NAME', "
14795 "upper(type) as 'TABLE_TYPE', "
14796 "NULL as 'REMARKS' "
14797 "from sqlite_master where %s "
14798 "and lower(tbl_name) = lower(%Q)",
14799 d->xcelqrx ? "'main'" : "NULL",
14800 d->xcelqrx ? "''" : "NULL",
14801 where, tname);
14802 }
14803 #else
14804 if (npatt) {
14805 sql = sqlite3_mprintf("select NULL as 'TABLE_QUALIFIER', "
14806 "NULL as 'TABLE_OWNER', "
14807 "tbl_name as 'TABLE_NAME', "
14808 "upper(type) as 'TABLE_TYPE', "
14809 "NULL as 'REMARKS' "
14810 "from sqlite_master where %s "
14811 "and tbl_name like %Q",
14812 where, tname);
14813 } else {
14814 sql = sqlite3_mprintf("select NULL as 'TABLE_QUALIFIER', "
14815 "NULL as 'TABLE_OWNER', "
14816 "tbl_name as 'TABLE_NAME', "
14817 "upper(type) as 'TABLE_TYPE', "
14818 "NULL as 'REMARKS' "
14819 "from sqlite_master where %s "
14820 "and lower(tbl_name) = lower(%Q)",
14821 where, tname);
14822 }
14823 #endif
14824 if (!sql) {
14825 return nomem(s);
14826 }
14827 ret = starttran(s);
14828 if (ret != SQL_SUCCESS) {
14829 sqlite3_free(sql);
14830 return ret;
14831 }
14832 dbtraceapi(d, "sqlite3_get_table", sql);
14833 rc = sqlite3_get_table(d->sqlite, sql, &s->rows, &s->nrows, &ncols, &errp);
14834 sqlite3_free(sql);
14835 if (rc == SQLITE_OK) {
14836 if (ncols != s->ncols) {
14837 freeresult(s, 0);
14838 s->nrows = 0;
14839 } else {
14840 s->rowfree = sqlite3_free_table;
14841 }
14842 } else {
14843 s->nrows = 0;
14844 s->rows = NULL;
14845 s->rowfree = NULL;
14846 }
14847 if (errp) {
14848 sqlite3_free(errp);
14849 errp = NULL;
14850 }
14851 s->rowp = s->rowprs = -1;
14852 return SQL_SUCCESS;
14853 }
14854
14855 #ifndef WINTERFACE
14856 /**
14857 * Retrieve information on tables and/or views.
14858 * @param stmt statement handle
14859 * @param cat catalog name/pattern or NULL
14860 * @param catLen length of catalog name/pattern or SQL_NTS
14861 * @param schema schema name/pattern or NULL
14862 * @param schemaLen length of schema name/pattern or SQL_NTS
14863 * @param table table name/pattern or NULL
14864 * @param tableLen length of table name/pattern or SQL_NTS
14865 * @param type types of tables string or NULL
14866 * @param typeLen length of types of tables string or SQL_NTS
14867 * @result ODBC error code
14868 */
14869
14870 SQLRETURN SQL_API
SQLTables(SQLHSTMT stmt,SQLCHAR * cat,SQLSMALLINT catLen,SQLCHAR * schema,SQLSMALLINT schemaLen,SQLCHAR * table,SQLSMALLINT tableLen,SQLCHAR * type,SQLSMALLINT typeLen)14871 SQLTables(SQLHSTMT stmt,
14872 SQLCHAR *cat, SQLSMALLINT catLen,
14873 SQLCHAR *schema, SQLSMALLINT schemaLen,
14874 SQLCHAR *table, SQLSMALLINT tableLen,
14875 SQLCHAR *type, SQLSMALLINT typeLen)
14876 {
14877 #if defined(_WIN32) || defined(_WIN64)
14878 char *c = NULL, *s = NULL, *t = NULL, *y = NULL;
14879 #endif
14880 SQLRETURN ret;
14881
14882 HSTMT_LOCK(stmt);
14883 #if defined(_WIN32) || defined(_WIN64)
14884 if (!((STMT *) stmt)->oemcp[0]) {
14885 ret = drvtables(stmt, cat, catLen, schema, schemaLen,
14886 table, tableLen, type, typeLen);
14887 goto done2;
14888 }
14889 if (cat) {
14890 c = wmb_to_utf_c((char *) cat, catLen);
14891 if (!c) {
14892 ret = nomem((STMT *) stmt);
14893 goto done;
14894 }
14895 }
14896 if (schema) {
14897 s = wmb_to_utf_c((char *) schema, schemaLen);
14898 if (!s) {
14899 ret = nomem((STMT *) stmt);
14900 goto done;
14901 }
14902 }
14903 if (table) {
14904 t = wmb_to_utf_c((char *) table, tableLen);
14905 if (!t) {
14906 ret = nomem((STMT *) stmt);
14907 goto done;
14908 }
14909 }
14910 if (type) {
14911 y = wmb_to_utf_c((char *) type, typeLen);
14912 if (!y) {
14913 ret = nomem((STMT *) stmt);
14914 goto done;
14915 }
14916 }
14917 ret = drvtables(stmt, (SQLCHAR *) c, SQL_NTS, (SQLCHAR *) s, SQL_NTS,
14918 (SQLCHAR *) t, SQL_NTS, (SQLCHAR *) y, SQL_NTS);
14919 #else
14920 ret = drvtables(stmt, cat, catLen, schema, schemaLen,
14921 table, tableLen, type, typeLen);
14922 #endif
14923 #if defined(_WIN32) || defined(_WIN64)
14924 done:
14925 uc_free(y);
14926 uc_free(t);
14927 uc_free(s);
14928 uc_free(c);
14929 done2:
14930 ;
14931 #endif
14932 HSTMT_UNLOCK(stmt);
14933 return ret;
14934 }
14935 #endif
14936
14937 #ifdef WINTERFACE
14938 /**
14939 * Retrieve information on tables and/or views.
14940 * @param stmt statement handle
14941 * @param cat catalog name/pattern or NULL
14942 * @param catLen length of catalog name/pattern or SQL_NTS
14943 * @param schema schema name/pattern or NULL
14944 * @param schemaLen length of schema name/pattern or SQL_NTS
14945 * @param table table name/pattern or NULL
14946 * @param tableLen length of table name/pattern or SQL_NTS
14947 * @param type types of tables string or NULL
14948 * @param typeLen length of types of tables string or SQL_NTS
14949 * @result ODBC error code
14950 */
14951
14952 SQLRETURN SQL_API
SQLTablesW(SQLHSTMT stmt,SQLWCHAR * cat,SQLSMALLINT catLen,SQLWCHAR * schema,SQLSMALLINT schemaLen,SQLWCHAR * table,SQLSMALLINT tableLen,SQLWCHAR * type,SQLSMALLINT typeLen)14953 SQLTablesW(SQLHSTMT stmt,
14954 SQLWCHAR *cat, SQLSMALLINT catLen,
14955 SQLWCHAR *schema, SQLSMALLINT schemaLen,
14956 SQLWCHAR *table, SQLSMALLINT tableLen,
14957 SQLWCHAR *type, SQLSMALLINT typeLen)
14958 {
14959 char *c = NULL, *s = NULL, *t = NULL, *y = NULL;
14960 SQLRETURN ret;
14961
14962 HSTMT_LOCK(stmt);
14963 if (cat) {
14964 c = uc_to_utf_c(cat, catLen);
14965 if (!c) {
14966 ret = nomem((STMT *) stmt);
14967 goto done;
14968 }
14969 }
14970 if (schema) {
14971 s = uc_to_utf_c(schema, schemaLen);
14972 if (!s) {
14973 ret = nomem((STMT *) stmt);
14974 goto done;
14975 }
14976 }
14977 if (table) {
14978 t = uc_to_utf_c(table, tableLen);
14979 if (!t) {
14980 ret = nomem((STMT *) stmt);
14981 goto done;
14982 }
14983 }
14984 if (type) {
14985 y = uc_to_utf_c(type, typeLen);
14986 if (!y) {
14987 ret = nomem((STMT *) stmt);
14988 goto done;
14989 }
14990 }
14991 ret = drvtables(stmt, (SQLCHAR *) c, SQL_NTS, (SQLCHAR *) s, SQL_NTS,
14992 (SQLCHAR *) t, SQL_NTS, (SQLCHAR *) y, SQL_NTS);
14993 done:
14994 uc_free(y);
14995 uc_free(t);
14996 uc_free(s);
14997 uc_free(c);
14998 HSTMT_UNLOCK(stmt);
14999 return ret;
15000 }
15001 #endif
15002
15003 /**
15004 * Columns for result set of SQLColumns().
15005 */
15006
15007 static COL colSpec2[] = {
15008 { "SYSTEM", "COLUMN", "TABLE_QUALIFIER", SCOL_VARCHAR, 50 },
15009 { "SYSTEM", "COLUMN", "TABLE_OWNER", SCOL_VARCHAR, 50 },
15010 { "SYSTEM", "COLUMN", "TABLE_NAME", SCOL_VARCHAR, 255 },
15011 { "SYSTEM", "COLUMN", "COLUMN_NAME", SCOL_VARCHAR, 255 },
15012 { "SYSTEM", "COLUMN", "DATA_TYPE", SQL_SMALLINT, 50 },
15013 { "SYSTEM", "COLUMN", "TYPE_NAME", SCOL_VARCHAR, 50 },
15014 { "SYSTEM", "COLUMN", "PRECISION", SQL_INTEGER, 50 },
15015 { "SYSTEM", "COLUMN", "LENGTH", SQL_INTEGER, 50 },
15016 { "SYSTEM", "COLUMN", "SCALE", SQL_SMALLINT, 50 },
15017 { "SYSTEM", "COLUMN", "RADIX", SQL_SMALLINT, 50 },
15018 { "SYSTEM", "COLUMN", "NULLABLE", SQL_SMALLINT, 50 },
15019 { "SYSTEM", "COLUMN", "REMARKS", SCOL_VARCHAR, 50 },
15020 { "SYSTEM", "COLUMN", "COLUMN_DEF", SCOL_VARCHAR, 50 },
15021 { "SYSTEM", "COLUMN", "SQL_DATA_TYPE", SQL_SMALLINT, 50 },
15022 { "SYSTEM", "COLUMN", "SQL_DATETIME_SUB", SQL_SMALLINT, 50 },
15023 { "SYSTEM", "COLUMN", "CHAR_OCTET_LENGTH", SQL_SMALLINT, 50 },
15024 { "SYSTEM", "COLUMN", "ORDINAL_POSITION", SQL_SMALLINT, 50 },
15025 { "SYSTEM", "COLUMN", "IS_NULLABLE", SCOL_VARCHAR, 50 }
15026 };
15027
15028 static COL colSpec3[] = {
15029 { "SYSTEM", "COLUMN", "TABLE_CAT", SCOL_VARCHAR, 50 },
15030 { "SYSTEM", "COLUMN", "TABLE_SCHEM", SCOL_VARCHAR, 50 },
15031 { "SYSTEM", "COLUMN", "TABLE_NAME", SCOL_VARCHAR, 255 },
15032 { "SYSTEM", "COLUMN", "COLUMN_NAME", SCOL_VARCHAR, 255 },
15033 { "SYSTEM", "COLUMN", "DATA_TYPE", SQL_SMALLINT, 50 },
15034 { "SYSTEM", "COLUMN", "TYPE_NAME", SCOL_VARCHAR, 50 },
15035 { "SYSTEM", "COLUMN", "COLUMN_SIZE", SQL_INTEGER, 50 },
15036 { "SYSTEM", "COLUMN", "BUFFER_LENGTH", SQL_INTEGER, 50 },
15037 { "SYSTEM", "COLUMN", "DECIMAL_DIGITS", SQL_SMALLINT, 50 },
15038 { "SYSTEM", "COLUMN", "NUM_PREC_RADIX", SQL_SMALLINT, 50 },
15039 { "SYSTEM", "COLUMN", "NULLABLE", SQL_SMALLINT, 50 },
15040 { "SYSTEM", "COLUMN", "REMARKS", SCOL_VARCHAR, 50 },
15041 { "SYSTEM", "COLUMN", "COLUMN_DEF", SCOL_VARCHAR, 50 },
15042 { "SYSTEM", "COLUMN", "SQL_DATA_TYPE", SQL_SMALLINT, 50 },
15043 { "SYSTEM", "COLUMN", "SQL_DATETIME_SUB", SQL_SMALLINT, 50 },
15044 { "SYSTEM", "COLUMN", "CHAR_OCTET_LENGTH", SQL_SMALLINT, 50 },
15045 { "SYSTEM", "COLUMN", "ORDINAL_POSITION", SQL_SMALLINT, 50 },
15046 { "SYSTEM", "COLUMN", "IS_NULLABLE", SCOL_VARCHAR, 50 }
15047 };
15048
15049 /**
15050 * Internal retrieve column information on table.
15051 * @param stmt statement handle
15052 * @param cat catalog name/pattern or NULL
15053 * @param catLen length of catalog name/pattern or SQL_NTS
15054 * @param schema schema name/pattern or NULL
15055 * @param schemaLen length of schema name/pattern or SQL_NTS
15056 * @param table table name/pattern or NULL
15057 * @param tableLen length of table name/pattern or SQL_NTS
15058 * @param col column name/pattern or NULL
15059 * @param colLen length of column name/pattern or SQL_NTS
15060 * @result ODBC error code
15061 */
15062
15063 static SQLRETURN
drvcolumns(SQLHSTMT stmt,SQLCHAR * cat,SQLSMALLINT catLen,SQLCHAR * schema,SQLSMALLINT schemaLen,SQLCHAR * table,SQLSMALLINT tableLen,SQLCHAR * col,SQLSMALLINT colLen)15064 drvcolumns(SQLHSTMT stmt,
15065 SQLCHAR *cat, SQLSMALLINT catLen,
15066 SQLCHAR *schema, SQLSMALLINT schemaLen,
15067 SQLCHAR *table, SQLSMALLINT tableLen,
15068 SQLCHAR *col, SQLSMALLINT colLen)
15069 {
15070 SQLRETURN sret;
15071 STMT *s;
15072 DBC *d;
15073 int ret, nrows, ncols, asize, i, k, roffs, namec;
15074 int tnrows, tncols, npatt;
15075 PTRDIFF_T size;
15076 char *errp = NULL, *sql, tname[512], cname[512], **rowp, **trows;
15077
15078 sret = mkresultset(stmt, colSpec2, array_size(colSpec2),
15079 colSpec3, array_size(colSpec3), &asize);
15080 if (sret != SQL_SUCCESS) {
15081 return sret;
15082 }
15083 s = (STMT *) stmt;
15084 d = (DBC *) s->dbc;
15085 if (!table) {
15086 size = 1;
15087 tname[0] = '%';
15088 } else {
15089 if (tableLen == SQL_NTS) {
15090 size = sizeof (tname) - 1;
15091 } else {
15092 size = min(sizeof (tname) - 1, tableLen);
15093 }
15094 strncpy(tname, (char *) table, size);
15095 }
15096 tname[size] = '\0';
15097 npatt = unescpat(tname);
15098 size = 0;
15099 if (col) {
15100 if (colLen == SQL_NTS) {
15101 size = sizeof (cname) - 1;
15102 } else {
15103 size = min(sizeof (cname) - 1, colLen);
15104 }
15105 strncpy(cname, (char *) col, size);
15106 }
15107 cname[size] = '\0';
15108 if (!strcmp(cname, "%")) {
15109 cname[0] = '\0';
15110 }
15111 if (npatt) {
15112 sql = sqlite3_mprintf("select tbl_name from sqlite_master where "
15113 "(type = 'table' or type = 'view') "
15114 "and tbl_name like %Q", tname);
15115 } else {
15116 sql = sqlite3_mprintf("select tbl_name from sqlite_master where "
15117 "(type = 'table' or type = 'view') "
15118 "and lower(tbl_name) = lower(%Q)", tname);
15119 }
15120 if (!sql) {
15121 return nomem(s);
15122 }
15123 sret = starttran(s);
15124 if (sret != SQL_SUCCESS) {
15125 sqlite3_free(sql);
15126 return sret;
15127 }
15128 dbtraceapi(d, "sqlite3_get_table", sql);
15129 ret = sqlite3_get_table(d->sqlite, sql, &trows, &tnrows, &tncols, &errp);
15130 sqlite3_free(sql);
15131 if (ret != SQLITE_OK) {
15132 setstat(s, ret, "%s (%d)", (*s->ov3) ? "HY000" : "S1000",
15133 errp ? errp : "unknown error", ret);
15134 if (errp) {
15135 sqlite3_free(errp);
15136 errp = NULL;
15137 }
15138 return SQL_ERROR;
15139 }
15140 if (errp) {
15141 sqlite3_free(errp);
15142 errp = NULL;
15143 }
15144 /* pass 1: compute number of rows of result set */
15145 if (tncols * tnrows <= 0) {
15146 sqlite3_free_table(trows);
15147 return SQL_SUCCESS;
15148 }
15149 size = 0;
15150 for (i = 1; i <= tnrows; i++) {
15151 sql = sqlite3_mprintf("PRAGMA table_info(%Q)", trows[i]);
15152 if (!sql) {
15153 sqlite3_free_table(trows);
15154 return nomem(s);
15155 }
15156 dbtraceapi(d, "sqlite3_get_table", sql);
15157 ret = sqlite3_get_table(d->sqlite, sql, &rowp, &nrows, &ncols, &errp);
15158 sqlite3_free(sql);
15159 if (ret != SQLITE_OK) {
15160 setstat(s, ret, "%s (%d)", (*s->ov3) ? "HY000" : "S1000",
15161 errp ? errp : "unknown error", ret);
15162 if (errp) {
15163 sqlite3_free(errp);
15164 errp = NULL;
15165 }
15166 sqlite3_free_table(trows);
15167 return SQL_ERROR;
15168 }
15169 if (errp) {
15170 sqlite3_free(errp);
15171 errp = NULL;
15172 }
15173 if (ncols * nrows > 0) {
15174 namec = -1;
15175 for (k = 0; k < ncols; k++) {
15176 if (strcmp(rowp[k], "name") == 0) {
15177 namec = k;
15178 break;
15179 }
15180 }
15181 if (cname[0]) {
15182 if (namec >= 0) {
15183 for (k = 1; k <= nrows; k++) {
15184 if (namematch(rowp[k * ncols + namec], cname, 1)) {
15185 size++;
15186 }
15187 }
15188 }
15189 } else {
15190 size += nrows;
15191 }
15192 }
15193 sqlite3_free_table(rowp);
15194 }
15195 /* pass 2: fill result set */
15196 if (size <= 0) {
15197 sqlite3_free_table(trows);
15198 return SQL_SUCCESS;
15199 }
15200 s->nrows = size;
15201 size = (size + 1) * asize;
15202 s->rows = xmalloc((size + 1) * sizeof (char *));
15203 if (!s->rows) {
15204 s->nrows = 0;
15205 sqlite3_free_table(trows);
15206 return nomem(s);
15207 }
15208 s->rows[0] = (char *) size;
15209 s->rows += 1;
15210 memset(s->rows, 0, sizeof (char *) * size);
15211 s->rowfree = freerows;
15212 roffs = 1;
15213 for (i = 1; i <= tnrows; i++) {
15214 sql = sqlite3_mprintf("PRAGMA table_info(%Q)", trows[i]);
15215 if (!sql) {
15216 sqlite3_free_table(trows);
15217 return nomem(s);
15218 }
15219 dbtraceapi(d, "sqlite3_get_table", sql);
15220 ret = sqlite3_get_table(d->sqlite, sql, &rowp, &nrows, &ncols, &errp);
15221 sqlite3_free(sql);
15222 if (ret != SQLITE_OK) {
15223 setstat(s, ret, "%s (%d)", (*s->ov3) ? "HY000" : "S1000",
15224 errp ? errp : "unknown error", ret);
15225 if (errp) {
15226 sqlite3_free(errp);
15227 errp = NULL;
15228 }
15229 sqlite3_free_table(trows);
15230 return SQL_ERROR;
15231 }
15232 if (errp) {
15233 sqlite3_free(errp);
15234 errp = NULL;
15235 }
15236 if (ncols * nrows > 0) {
15237 int m, mr, nr = nrows;
15238
15239 namec = -1;
15240 for (k = 0; k < ncols; k++) {
15241 if (strcmp(rowp[k], "name") == 0) {
15242 namec = k;
15243 break;
15244 }
15245 }
15246 if (cname[0]) {
15247 nr = 0;
15248 if (namec >= 0) {
15249 for (k = 1; k <= nrows; k++) {
15250 if (namematch(rowp[k * ncols + namec], cname, 1)) {
15251 nr++;
15252 }
15253 }
15254 }
15255 }
15256 for (k = 0; k < nr; k++) {
15257 m = asize * (roffs + k);
15258 #if defined(_WIN32) || defined(_WIN64)
15259 s->rows[m + 0] = xstrdup(d->xcelqrx ? "main" : "");
15260 s->rows[m + 1] = xstrdup("");
15261 #else
15262 s->rows[m + 0] = xstrdup("");
15263 s->rows[m + 1] = xstrdup("");
15264 #endif
15265 s->rows[m + 2] = xstrdup(trows[i]);
15266 s->rows[m + 8] = xstrdup("10");
15267 s->rows[m + 9] = xstrdup("0");
15268 s->rows[m + 15] = xstrdup("16384");
15269 }
15270 for (k = 0; nr && k < ncols; k++) {
15271 if (strcmp(rowp[k], "cid") == 0) {
15272 for (mr = 0, m = 1; m <= nrows; m++) {
15273 char buf[256];
15274 int ir, coln = k;
15275
15276 if (cname[0] &&
15277 !namematch(rowp[m * ncols + namec], cname, 1)) {
15278 continue;
15279 }
15280 ir = asize * (roffs + mr);
15281 sscanf(rowp[m * ncols + k], "%d", &coln);
15282 sprintf(buf, "%d", coln + 1);
15283 s->rows[ir + 16] = xstrdup(buf);
15284 ++mr;
15285 }
15286 } else if (k == namec) {
15287 for (mr = 0, m = 1; m <= nrows; m++) {
15288 int ir;
15289
15290 if (cname[0] &&
15291 !namematch(rowp[m * ncols + namec], cname, 1)) {
15292 continue;
15293 }
15294 ir = asize * (roffs + mr);
15295 s->rows[ir + 3] = xstrdup(rowp[m * ncols + k]);
15296 ++mr;
15297 }
15298 } else if (strcmp(rowp[k], "notnull") == 0) {
15299 for (mr = 0, m = 1; m <= nrows; m++) {
15300 int ir;
15301
15302 if (cname[0] &&
15303 !namematch(rowp[m * ncols + namec], cname, 1)) {
15304 continue;
15305 }
15306 ir = asize * (roffs + mr);
15307 if (*rowp[m * ncols + k] != '0') {
15308 s->rows[ir + 10] = xstrdup(stringify(SQL_FALSE));
15309 } else {
15310 s->rows[ir + 10] = xstrdup(stringify(SQL_TRUE));
15311 }
15312 s->rows[ir + 17] =
15313 xstrdup((*rowp[m * ncols + k] != '0') ?
15314 "NO" : "YES");
15315 ++mr;
15316 }
15317 } else if (strcmp(rowp[k], "dflt_value") == 0) {
15318 for (mr = 0, m = 1; m <= nrows; m++) {
15319 char *dflt = unquote(rowp[m * ncols + k]);
15320 int ir;
15321
15322 if (cname[0] &&
15323 !namematch(rowp[m * ncols + namec], cname, 1)) {
15324 continue;
15325 }
15326 ir = asize * (roffs + mr);
15327 s->rows[ir + 12] = xstrdup(dflt ? dflt : "NULL");
15328 ++mr;
15329 }
15330 } else if (strcmp(rowp[k], "type") == 0) {
15331 for (mr = 0, m = 1; m <= nrows; m++) {
15332 char *typename = rowp[m * ncols + k];
15333 int sqltype, mm, dd, ir;
15334 char buf[256];
15335
15336 if (cname[0] &&
15337 !namematch(rowp[m * ncols + namec], cname, 1)) {
15338 continue;
15339 }
15340 ir = asize * (roffs + mr);
15341 s->rows[ir + 5] = xstrdup(typename);
15342 sqltype = mapsqltype(typename, NULL, *s->ov3,
15343 s->nowchar[0], s->dobigint);
15344 getmd(typename, sqltype, &mm, &dd);
15345 #ifdef SQL_LONGVARCHAR
15346 if (sqltype == SQL_VARCHAR && mm > 255) {
15347 sqltype = SQL_LONGVARCHAR;
15348 }
15349 #endif
15350 #ifdef WINTERFACE
15351 #ifdef SQL_WLONGVARCHAR
15352 if (sqltype == SQL_WVARCHAR && mm > 255) {
15353 sqltype = SQL_WLONGVARCHAR;
15354 }
15355 #endif
15356 #endif
15357 if (sqltype == SQL_VARBINARY && mm > 255) {
15358 sqltype = SQL_LONGVARBINARY;
15359 }
15360 sprintf(buf, "%d", sqltype);
15361 s->rows[ir + 4] = xstrdup(buf);
15362 s->rows[ir + 13] = xstrdup(buf);
15363 sprintf(buf, "%d", mm);
15364 s->rows[ir + 7] = xstrdup(buf);
15365 sprintf(buf, "%d", dd);
15366 s->rows[ir + 6] = xstrdup(buf);
15367 ++mr;
15368 }
15369 }
15370 }
15371 roffs += nr;
15372 }
15373 sqlite3_free_table(rowp);
15374 }
15375 sqlite3_free_table(trows);
15376 return SQL_SUCCESS;
15377 }
15378
15379 #ifndef WINTERFACE
15380 /**
15381 * Retrieve column information on table.
15382 * @param stmt statement handle
15383 * @param cat catalog name/pattern or NULL
15384 * @param catLen length of catalog name/pattern or SQL_NTS
15385 * @param schema schema name/pattern or NULL
15386 * @param schemaLen length of schema name/pattern or SQL_NTS
15387 * @param table table name/pattern or NULL
15388 * @param tableLen length of table name/pattern or SQL_NTS
15389 * @param col column name/pattern or NULL
15390 * @param colLen length of column name/pattern or SQL_NTS
15391 * @result ODBC error code
15392 */
15393
15394 SQLRETURN SQL_API
SQLColumns(SQLHSTMT stmt,SQLCHAR * cat,SQLSMALLINT catLen,SQLCHAR * schema,SQLSMALLINT schemaLen,SQLCHAR * table,SQLSMALLINT tableLen,SQLCHAR * col,SQLSMALLINT colLen)15395 SQLColumns(SQLHSTMT stmt,
15396 SQLCHAR *cat, SQLSMALLINT catLen,
15397 SQLCHAR *schema, SQLSMALLINT schemaLen,
15398 SQLCHAR *table, SQLSMALLINT tableLen,
15399 SQLCHAR *col, SQLSMALLINT colLen)
15400 {
15401 #if defined(_WIN32) || defined(_WIN64)
15402 char *c = NULL, *s = NULL, *t = NULL, *k = NULL;
15403 #endif
15404 SQLRETURN ret;
15405
15406 HSTMT_LOCK(stmt);
15407 #if defined(_WIN32) || defined(_WIN64)
15408 if (!((STMT *) stmt)->oemcp[0]) {
15409 ret = drvcolumns(stmt, cat, catLen, schema, schemaLen,
15410 table, tableLen, col, colLen);
15411 goto done2;
15412 }
15413 if (cat) {
15414 c = wmb_to_utf_c((char *) cat, catLen);
15415 if (!c) {
15416 ret = nomem((STMT *) stmt);
15417 goto done;
15418 }
15419 }
15420 if (schema) {
15421 s = wmb_to_utf_c((char *) schema, schemaLen);
15422 if (!s) {
15423 ret = nomem((STMT *) stmt);
15424 goto done;
15425 }
15426 }
15427 if (table) {
15428 t = wmb_to_utf_c((char *) table, tableLen);
15429 if (!t) {
15430 ret = nomem((STMT *) stmt);
15431 goto done;
15432 }
15433 }
15434 if (col) {
15435 k = wmb_to_utf_c((char *) col, colLen);
15436 if (!k) {
15437 ret = nomem((STMT *) stmt);
15438 goto done;
15439 }
15440 }
15441 ret = drvcolumns(stmt, (SQLCHAR *) c, SQL_NTS, (SQLCHAR *) s, SQL_NTS,
15442 (SQLCHAR *) t, SQL_NTS, (SQLCHAR *) k, SQL_NTS);
15443 #else
15444 ret = drvcolumns(stmt, cat, catLen, schema, schemaLen,
15445 table, tableLen, col, colLen);
15446 #endif
15447 #if defined(_WIN32) || defined(_WIN64)
15448 done:
15449 uc_free(k);
15450 uc_free(t);
15451 uc_free(s);
15452 uc_free(c);
15453 done2:
15454 ;
15455 #endif
15456 HSTMT_UNLOCK(stmt);
15457 return ret;
15458 }
15459 #endif
15460
15461 #ifdef WINTERFACE
15462 /**
15463 * Retrieve column information on table (UNICODE version).
15464 * @param stmt statement handle
15465 * @param cat catalog name/pattern or NULL
15466 * @param catLen length of catalog name/pattern or SQL_NTS
15467 * @param schema schema name/pattern or NULL
15468 * @param schemaLen length of schema name/pattern or SQL_NTS
15469 * @param table table name/pattern or NULL
15470 * @param tableLen length of table name/pattern or SQL_NTS
15471 * @param col column name/pattern or NULL
15472 * @param colLen length of column name/pattern or SQL_NTS
15473 * @result ODBC error code
15474 */
15475
15476 SQLRETURN SQL_API
SQLColumnsW(SQLHSTMT stmt,SQLWCHAR * cat,SQLSMALLINT catLen,SQLWCHAR * schema,SQLSMALLINT schemaLen,SQLWCHAR * table,SQLSMALLINT tableLen,SQLWCHAR * col,SQLSMALLINT colLen)15477 SQLColumnsW(SQLHSTMT stmt,
15478 SQLWCHAR *cat, SQLSMALLINT catLen,
15479 SQLWCHAR *schema, SQLSMALLINT schemaLen,
15480 SQLWCHAR *table, SQLSMALLINT tableLen,
15481 SQLWCHAR *col, SQLSMALLINT colLen)
15482 {
15483 char *c = NULL, *s = NULL, *t = NULL, *k = NULL;
15484 SQLRETURN ret;
15485
15486 HSTMT_LOCK(stmt);
15487 if (cat) {
15488 c = uc_to_utf_c(cat, catLen);
15489 if (!c) {
15490 ret = nomem((STMT *) stmt);
15491 goto done;
15492 }
15493 }
15494 if (schema) {
15495 s = uc_to_utf_c(schema, schemaLen);
15496 if (!s) {
15497 ret = nomem((STMT *) stmt);
15498 goto done;
15499 }
15500 }
15501 if (table) {
15502 t = uc_to_utf_c(table, tableLen);
15503 if (!t) {
15504 ret = nomem((STMT *) stmt);
15505 goto done;
15506 }
15507 }
15508 if (col) {
15509 k = uc_to_utf_c(col, colLen);
15510 if (!k) {
15511 ret = nomem((STMT *) stmt);
15512 goto done;
15513 }
15514 }
15515 ret = drvcolumns(stmt, (SQLCHAR *) c, SQL_NTS, (SQLCHAR *) s, SQL_NTS,
15516 (SQLCHAR *) t, SQL_NTS, (SQLCHAR *) k, SQL_NTS);
15517 done:
15518 uc_free(k);
15519 uc_free(t);
15520 uc_free(s);
15521 uc_free(c);
15522 HSTMT_UNLOCK(stmt);
15523 return ret;
15524
15525 }
15526 #endif
15527
15528 /**
15529 * Columns for result set of SQLGetTypeInfo().
15530 */
15531
15532 static COL typeSpec2[] = {
15533 { "SYSTEM", "TYPE", "TYPE_NAME", SCOL_VARCHAR, 50 },
15534 { "SYSTEM", "TYPE", "DATA_TYPE", SQL_SMALLINT, 2 },
15535 { "SYSTEM", "TYPE", "PRECISION", SQL_INTEGER, 9 },
15536 { "SYSTEM", "TYPE", "LITERAL_PREFIX", SCOL_VARCHAR, 50 },
15537 { "SYSTEM", "TYPE", "LITERAL_SUFFIX", SCOL_VARCHAR, 50 },
15538 { "SYSTEM", "TYPE", "CREATE_PARAMS", SCOL_VARCHAR, 50 },
15539 { "SYSTEM", "TYPE", "NULLABLE", SQL_SMALLINT, 2 },
15540 { "SYSTEM", "TYPE", "CASE_SENSITIVE", SQL_SMALLINT, 2 },
15541 { "SYSTEM", "TYPE", "SEARCHABLE", SQL_SMALLINT, 2 },
15542 { "SYSTEM", "TYPE", "UNSIGNED_ATTRIBUTE", SQL_SMALLINT, 2 },
15543 { "SYSTEM", "TYPE", "MONEY", SQL_SMALLINT, 2 },
15544 { "SYSTEM", "TYPE", "AUTO_INCREMENT", SQL_SMALLINT, 2 },
15545 { "SYSTEM", "TYPE", "LOCAL_TYPE_NAME", SCOL_VARCHAR, 50 },
15546 { "SYSTEM", "TYPE", "MINIMUM_SCALE", SQL_SMALLINT, 2 },
15547 { "SYSTEM", "TYPE", "MAXIMUM_SCALE", SQL_SMALLINT, 2 }
15548 };
15549
15550 static COL typeSpec3[] = {
15551 { "SYSTEM", "TYPE", "TYPE_NAME", SCOL_VARCHAR, 50 },
15552 { "SYSTEM", "TYPE", "DATA_TYPE", SQL_SMALLINT, 2 },
15553 { "SYSTEM", "TYPE", "COLUMN_SIZE", SQL_INTEGER, 9 },
15554 { "SYSTEM", "TYPE", "LITERAL_PREFIX", SCOL_VARCHAR, 50 },
15555 { "SYSTEM", "TYPE", "LITERAL_SUFFIX", SCOL_VARCHAR, 50 },
15556 { "SYSTEM", "TYPE", "CREATE_PARAMS", SCOL_VARCHAR, 50 },
15557 { "SYSTEM", "TYPE", "NULLABLE", SQL_SMALLINT, 2 },
15558 { "SYSTEM", "TYPE", "CASE_SENSITIVE", SQL_SMALLINT, 2 },
15559 { "SYSTEM", "TYPE", "SEARCHABLE", SQL_SMALLINT, 2 },
15560 { "SYSTEM", "TYPE", "UNSIGNED_ATTRIBUTE", SQL_SMALLINT, 2 },
15561 { "SYSTEM", "TYPE", "FIXED_PREC_SCALE", SQL_SMALLINT, 2 },
15562 { "SYSTEM", "TYPE", "AUTO_UNIQUE_VALUE", SQL_SMALLINT, 2 },
15563 { "SYSTEM", "TYPE", "LOCAL_TYPE_NAME", SCOL_VARCHAR, 50 },
15564 { "SYSTEM", "TYPE", "MINIMUM_SCALE", SQL_SMALLINT, 2 },
15565 { "SYSTEM", "TYPE", "MAXIMUM_SCALE", SQL_SMALLINT, 2 },
15566 { "SYSTEM", "TYPE", "SQL_DATA_TYPE", SQL_SMALLINT, 2 },
15567 { "SYSTEM", "TYPE", "SQL_DATETIME_SUB", SQL_SMALLINT, 2 },
15568 { "SYSTEM", "TYPE", "NUM_PREC_RADIX", SQL_INTEGER, 4 },
15569 { "SYSTEM", "TYPE", "INTERVAL_PRECISION", SQL_SMALLINT, 2 }
15570 };
15571
15572 /**
15573 * Internal function to build up data type information as row in result set.
15574 * @param s statement pointer
15575 * @param row row number
15576 * @param asize number of items in a row
15577 * @param typename name of type
15578 * @param type integer SQL type
15579 * @param tind type index
15580 */
15581
15582 static void
mktypeinfo(STMT * s,int row,int asize,char * typename,int type,int tind)15583 mktypeinfo(STMT *s, int row, int asize, char *typename, int type, int tind)
15584 {
15585 int offs = row * asize;
15586 char *tcode, *crpar = NULL, *sign = stringify(SQL_FALSE);
15587 char *quote[2] = { NULL, NULL };
15588 static char tcodes[32 * 32];
15589
15590 if (tind <= 0) {
15591 tind = row;
15592 }
15593 tcode = tcodes + tind * 32;
15594 sprintf(tcode, "%d", type);
15595 s->rows[offs + 0] = typename;
15596 s->rows[offs + 1] = tcode;
15597 if (asize >= 17) {
15598 s->rows[offs + 15] = tcode;
15599 s->rows[offs + 16] = "0";
15600 }
15601 switch (type) {
15602 default:
15603 #ifdef SQL_LONGVARCHAR
15604 case SQL_LONGVARCHAR:
15605 #ifdef WINTERFACE
15606 case SQL_WLONGVARCHAR:
15607 #endif
15608 crpar = "length";
15609 quote[0] = quote[1] = "'";
15610 sign = NULL;
15611 s->rows[offs + 2] = "65536";
15612 break;
15613 #endif
15614 #ifdef SQL_BIT
15615 case SQL_BIT:
15616 sign = NULL;
15617 s->rows[offs + 2] = "1";
15618 break;
15619 #endif
15620 case SQL_CHAR:
15621 case SQL_VARCHAR:
15622 #ifdef WINTERFACE
15623 case SQL_WCHAR:
15624 case SQL_WVARCHAR:
15625 #endif
15626 s->rows[offs + 2] = "255";
15627 crpar = "length";
15628 quote[0] = quote[1] = "'";
15629 sign = NULL;
15630 break;
15631 case SQL_TINYINT:
15632 s->rows[offs + 2] = "3";
15633 break;
15634 case SQL_SMALLINT:
15635 s->rows[offs + 2] = "5";
15636 break;
15637 case SQL_INTEGER:
15638 s->rows[offs + 2] = "9";
15639 break;
15640 #ifdef SQL_BIGINT
15641 case SQL_BIGINT:
15642 s->rows[offs + 2] = "19";
15643 break;
15644 #endif
15645 case SQL_FLOAT:
15646 s->rows[offs + 2] = "7";
15647 break;
15648 case SQL_DOUBLE:
15649 s->rows[offs + 2] = "15";
15650 break;
15651 #ifdef SQL_TYPE_DATE
15652 case SQL_TYPE_DATE:
15653 #endif
15654 case SQL_DATE:
15655 s->rows[offs + 2] = "10";
15656 quote[0] = quote[1] = "'";
15657 sign = NULL;
15658 break;
15659 #ifdef SQL_TYPE_TIME
15660 case SQL_TYPE_TIME:
15661 #endif
15662 case SQL_TIME:
15663 s->rows[offs + 2] = "8";
15664 quote[0] = quote[1] = "'";
15665 sign = NULL;
15666 break;
15667 #ifdef SQL_TYPE_TIMESTAMP
15668 case SQL_TYPE_TIMESTAMP:
15669 #endif
15670 case SQL_TIMESTAMP:
15671 s->rows[offs + 2] = "32";
15672 quote[0] = quote[1] = "'";
15673 sign = NULL;
15674 break;
15675 case SQL_VARBINARY:
15676 quote[0] = "0x";
15677 sign = NULL;
15678 s->rows[offs + 2] = "255";
15679 break;
15680 case SQL_LONGVARBINARY:
15681 quote[0] = "0x";
15682 sign = NULL;
15683 s->rows[offs + 2] = "65536";
15684 break;
15685 }
15686 s->rows[offs + 3] = quote[0];
15687 s->rows[offs + 4] = quote[1];
15688 s->rows[offs + 5] = crpar;
15689 s->rows[offs + 6] = stringify(SQL_NULLABLE);
15690 s->rows[offs + 7] = stringify(SQL_FALSE);
15691 s->rows[offs + 8] = stringify(SQL_SEARCHABLE);
15692 s->rows[offs + 9] = sign;
15693 s->rows[offs + 10] = stringify(SQL_FALSE);
15694 s->rows[offs + 11] = stringify(SQL_FALSE);
15695 s->rows[offs + 12] = typename;
15696 switch (type) {
15697 case SQL_DATE:
15698 case SQL_TIME:
15699 s->rows[offs + 13] = "0";
15700 s->rows[offs + 14] = "0";
15701 break;
15702 #ifdef SQL_TYPE_TIMESTAMP
15703 case SQL_TYPE_TIMESTAMP:
15704 #endif
15705 case SQL_TIMESTAMP:
15706 s->rows[offs + 13] = "0";
15707 s->rows[offs + 14] = "3";
15708 break;
15709 default:
15710 s->rows[offs + 13] = NULL;
15711 s->rows[offs + 14] = NULL;
15712 break;
15713 }
15714 }
15715
15716 /**
15717 * Helper function to sort type information.
15718 * Callback for qsort().
15719 * @param a first item to compare
15720 * @param b second item to compare
15721 * @result ==0, <0, >0 according to data type number
15722 */
15723
15724 static int
typeinfosort(const void * a,const void * b)15725 typeinfosort(const void *a, const void *b)
15726 {
15727 char **pa = (char **) a;
15728 char **pb = (char **) b;
15729 int na, nb;
15730
15731 na = strtol(pa[1], NULL, 0);
15732 nb = strtol(pb[1], NULL, 0);
15733 return na - nb;
15734 }
15735
15736 /**
15737 * Internal return data type information.
15738 * @param stmt statement handle
15739 * @param sqltype which type to retrieve
15740 * @result ODBC error code
15741 */
15742
15743 static SQLRETURN
drvgettypeinfo(SQLHSTMT stmt,SQLSMALLINT sqltype)15744 drvgettypeinfo(SQLHSTMT stmt, SQLSMALLINT sqltype)
15745 {
15746 SQLRETURN ret;
15747 STMT *s;
15748 int asize;
15749
15750 ret = mkresultset(stmt, typeSpec2, array_size(typeSpec2),
15751 typeSpec3, array_size(typeSpec3), &asize);
15752 if (ret != SQL_SUCCESS) {
15753 return ret;
15754 }
15755 s = (STMT *) stmt;
15756 #ifdef SQL_LONGVARCHAR
15757 s->nrows = (sqltype == SQL_ALL_TYPES) ? 13 : 1;
15758 #else
15759 s->nrows = (sqltype == SQL_ALL_TYPES) ? 12 : 1;
15760 #endif
15761 if (sqltype == SQL_ALL_TYPES) {
15762 #ifdef WINTERFACE
15763 s->nrows += 2;
15764 #ifdef SQL_WLONGVARCHAR
15765 s->nrows += 2;
15766 #endif
15767 #endif
15768 }
15769 if (sqltype == SQL_ALL_TYPES) {
15770 s->nrows += 2;
15771 #ifdef SQL_BIT
15772 s->nrows += 1;
15773 #endif
15774 #ifdef SQL_BIGINT
15775 s->nrows += 1;
15776 #endif
15777 }
15778 s->rows = (char **) xmalloc(sizeof (char *) * (s->nrows + 1) * asize);
15779 if (!s->rows) {
15780 s->nrows = 0;
15781 return nomem(s);
15782 }
15783 #ifdef MEMORY_DEBUG
15784 s->rowfree = xfree__;
15785 #else
15786 s->rowfree = sqlite3_free;
15787 #endif
15788 memset(s->rows, 0, sizeof (char *) * (s->nrows + 1) * asize);
15789 if (sqltype == SQL_ALL_TYPES) {
15790 int cc = 1;
15791
15792 mktypeinfo(s, cc++, asize, "varchar", SQL_VARCHAR, 0);
15793 mktypeinfo(s, cc++, asize, "tinyint", SQL_TINYINT, 0);
15794 mktypeinfo(s, cc++, asize, "smallint", SQL_SMALLINT, 0);
15795 mktypeinfo(s, cc++, asize, "integer", SQL_INTEGER, 0);
15796 mktypeinfo(s, cc++, asize, "float", SQL_FLOAT, 0);
15797 mktypeinfo(s, cc++, asize, "double", SQL_DOUBLE, 0);
15798 #ifdef SQL_TYPE_DATE
15799 mktypeinfo(s, cc++, asize, "date",
15800 (*s->ov3) ? SQL_TYPE_DATE : SQL_DATE, 0);
15801 #else
15802 mktypeinfo(s, cc++, asize, "date", SQL_DATE, 0);
15803 #endif
15804 #ifdef SQL_TYPE_TIME
15805 mktypeinfo(s, cc++, asize, "time",
15806 (*s->ov3) ? SQL_TYPE_TIME : SQL_TIME, 0);
15807 #else
15808 mktypeinfo(s, cc++, asize, "time", SQL_TIME, 0);
15809 #endif
15810 #ifdef SQL_TYPE_TIMESTAMP
15811 mktypeinfo(s, cc++, asize, "timestamp",
15812 (*s->ov3) ? SQL_TYPE_TIMESTAMP : SQL_TIMESTAMP, 0);
15813 #else
15814 mktypeinfo(s, cc++, asize, "timestamp", SQL_TIMESTAMP, 0);
15815 #endif
15816 mktypeinfo(s, cc++, asize, "char", SQL_CHAR, 0);
15817 mktypeinfo(s, cc++, asize, "numeric", SQL_DOUBLE, 0);
15818 #ifdef SQL_LONGVARCHAR
15819 mktypeinfo(s, cc++, asize, "text", SQL_LONGVARCHAR, 0);
15820 mktypeinfo(s, cc++, asize, "longvarchar", SQL_LONGVARCHAR, 0);
15821 #else
15822 mktypeinfo(s, cc++, asize, "text", SQL_VARCHAR, 0);
15823 #endif
15824 mktypeinfo(s, cc++, asize, "varbinary", SQL_VARBINARY, 0);
15825 mktypeinfo(s, cc++, asize, "longvarbinary", SQL_LONGVARBINARY, 0);
15826 #ifdef SQL_BIT
15827 mktypeinfo(s, cc++, asize, "bit", SQL_BIT, 0);
15828 #endif
15829 #ifdef SQL_BIGINT
15830 mktypeinfo(s, cc++, asize, "bigint", SQL_BIGINT, 0);
15831 #endif
15832 #ifdef WINTERFACE
15833 mktypeinfo(s, cc++, asize, "wvarchar", SQL_WVARCHAR, 0);
15834 mktypeinfo(s, cc++, asize, "wchar", SQL_WCHAR, 0);
15835 #ifdef SQL_WLONGVARCHAR
15836 mktypeinfo(s, cc++, asize, "wtext", SQL_WLONGVARCHAR, 0);
15837 mktypeinfo(s, cc++, asize, "longwvarchar", SQL_WLONGVARCHAR, 0);
15838 #endif
15839 #endif
15840 qsort(s->rows + asize, s->nrows, sizeof (char *) * asize,
15841 typeinfosort);
15842 } else {
15843 switch (sqltype) {
15844 case SQL_CHAR:
15845 mktypeinfo(s, 1, asize, "char", SQL_CHAR, 10);
15846 break;
15847 case SQL_VARCHAR:
15848 mktypeinfo(s, 1, asize, "varchar", SQL_VARCHAR, 1);
15849 break;
15850 case SQL_TINYINT:
15851 mktypeinfo(s, 1, asize, "tinyint", SQL_TINYINT, 2);
15852 break;
15853 case SQL_SMALLINT:
15854 mktypeinfo(s, 1, asize, "smallint", SQL_SMALLINT, 3);
15855 break;
15856 case SQL_INTEGER:
15857 mktypeinfo(s, 1, asize, "integer", SQL_INTEGER, 4);
15858 break;
15859 case SQL_FLOAT:
15860 mktypeinfo(s, 1, asize, "float", SQL_FLOAT, 5);
15861 break;
15862 case SQL_DOUBLE:
15863 mktypeinfo(s, 1, asize, "double", SQL_DOUBLE, 6);
15864 break;
15865 #ifdef SQL_TYPE_DATE
15866 case SQL_TYPE_DATE:
15867 mktypeinfo(s, 1, asize, "date", SQL_TYPE_DATE, 25);
15868 break;
15869 #endif
15870 case SQL_DATE:
15871 mktypeinfo(s, 1, asize, "date", SQL_DATE, 7);
15872 break;
15873 #ifdef SQL_TYPE_TIME
15874 case SQL_TYPE_TIME:
15875 mktypeinfo(s, 1, asize, "time", SQL_TYPE_TIME, 26);
15876 break;
15877 #endif
15878 case SQL_TIME:
15879 mktypeinfo(s, 1, asize, "time", SQL_TIME, 8);
15880 break;
15881 #ifdef SQL_TYPE_TIMESTAMP
15882 case SQL_TYPE_TIMESTAMP:
15883 mktypeinfo(s, 1, asize, "timestamp", SQL_TYPE_TIMESTAMP, 27);
15884 break;
15885 #endif
15886 case SQL_TIMESTAMP:
15887 mktypeinfo(s, 1, asize, "timestamp", SQL_TIMESTAMP, 9);
15888 break;
15889 #ifdef SQL_LONGVARCHAR
15890 case SQL_LONGVARCHAR:
15891 mktypeinfo(s, 1, asize, "longvarchar", SQL_LONGVARCHAR, 12);
15892 break;
15893 #endif
15894 case SQL_VARBINARY:
15895 mktypeinfo(s, 1, asize, "varbinary", SQL_VARBINARY, 30);
15896 break;
15897 case SQL_LONGVARBINARY:
15898 mktypeinfo(s, 1, asize, "longvarbinary", SQL_LONGVARBINARY, 31);
15899 break;
15900 #ifdef SQL_BIT
15901 case SQL_BIT:
15902 mktypeinfo(s, 1, asize, "bit", SQL_BIT, 29);
15903 break;
15904 #endif
15905 #ifdef SQL_BIGINT
15906 case SQL_BIGINT:
15907 mktypeinfo(s, 1, asize, "bigint", SQL_BIGINT, 28);
15908 break;
15909 #endif
15910 #ifdef WINTERFACE
15911 #ifdef SQL_WCHAR
15912 case SQL_WCHAR:
15913 mktypeinfo(s, 1, asize, "wchar", SQL_WCHAR, 18);
15914 break;
15915 #endif
15916 #ifdef SQL_WVARCHAR
15917 case SQL_WVARCHAR:
15918 mktypeinfo(s, 1, asize, "wvarchar", SQL_WVARCHAR, 19);
15919 break;
15920 #endif
15921 #ifdef SQL_WLONGVARCHAR
15922 case SQL_WLONGVARCHAR:
15923 mktypeinfo(s, 1, asize, "longwvarchar", SQL_WLONGVARCHAR, 20);
15924 break;
15925 #endif
15926 #endif
15927 default:
15928 s->nrows = 0;
15929 }
15930 }
15931 return SQL_SUCCESS;
15932 }
15933
15934 #ifndef WINTERFACE
15935 /**
15936 * Return data type information.
15937 * @param stmt statement handle
15938 * @param sqltype which type to retrieve
15939 * @result ODBC error code
15940 */
15941
15942 SQLRETURN SQL_API
SQLGetTypeInfo(SQLHSTMT stmt,SQLSMALLINT sqltype)15943 SQLGetTypeInfo(SQLHSTMT stmt, SQLSMALLINT sqltype)
15944 {
15945 SQLRETURN ret;
15946
15947 HSTMT_LOCK(stmt);
15948 ret = drvgettypeinfo(stmt, sqltype);
15949 HSTMT_UNLOCK(stmt);
15950 return ret;
15951 }
15952 #endif
15953
15954 #ifdef WINTERFACE
15955 /**
15956 * Return data type information (UNICODE version).
15957 * @param stmt statement handle
15958 * @param sqltype which type to retrieve
15959 * @result ODBC error code
15960 */
15961
15962 SQLRETURN SQL_API
SQLGetTypeInfoW(SQLHSTMT stmt,SQLSMALLINT sqltype)15963 SQLGetTypeInfoW(SQLHSTMT stmt, SQLSMALLINT sqltype)
15964 {
15965 SQLRETURN ret;
15966
15967 HSTMT_LOCK(stmt);
15968 ret = drvgettypeinfo(stmt, sqltype);
15969 HSTMT_UNLOCK(stmt);
15970 return ret;
15971 }
15972 #endif
15973
15974 /**
15975 * Columns for result set of SQLStatistics().
15976 */
15977
15978 static COL statSpec2[] = {
15979 { "SYSTEM", "STATISTICS", "TABLE_QUALIFIER", SCOL_VARCHAR, 50 },
15980 { "SYSTEM", "STATISTICS", "TABLE_OWNER", SCOL_VARCHAR, 50 },
15981 { "SYSTEM", "STATISTICS", "TABLE_NAME", SCOL_VARCHAR, 255 },
15982 { "SYSTEM", "STATISTICS", "NON_UNIQUE", SQL_SMALLINT, 50 },
15983 { "SYSTEM", "STATISTICS", "INDEX_QUALIFIER", SCOL_VARCHAR, 255 },
15984 { "SYSTEM", "STATISTICS", "INDEX_NAME", SCOL_VARCHAR, 255 },
15985 { "SYSTEM", "STATISTICS", "TYPE", SQL_SMALLINT, 50 },
15986 { "SYSTEM", "STATISTICS", "SEQ_IN_INDEX", SQL_SMALLINT, 50 },
15987 { "SYSTEM", "STATISTICS", "COLUMN_NAME", SCOL_VARCHAR, 255 },
15988 { "SYSTEM", "STATISTICS", "COLLATION", SCOL_CHAR, 1 },
15989 { "SYSTEM", "STATISTICS", "CARDINALITY", SQL_INTEGER, 50 },
15990 { "SYSTEM", "STATISTICS", "PAGES", SQL_INTEGER, 50 },
15991 { "SYSTEM", "STATISTICS", "FILTER_CONDITION", SCOL_VARCHAR, 255 }
15992 };
15993
15994 static COL statSpec3[] = {
15995 { "SYSTEM", "STATISTICS", "TABLE_CAT", SCOL_VARCHAR, 50 },
15996 { "SYSTEM", "STATISTICS", "TABLE_SCHEM", SCOL_VARCHAR, 50 },
15997 { "SYSTEM", "STATISTICS", "TABLE_NAME", SCOL_VARCHAR, 255 },
15998 { "SYSTEM", "STATISTICS", "NON_UNIQUE", SQL_SMALLINT, 50 },
15999 { "SYSTEM", "STATISTICS", "INDEX_QUALIFIER", SCOL_VARCHAR, 255 },
16000 { "SYSTEM", "STATISTICS", "INDEX_NAME", SCOL_VARCHAR, 255 },
16001 { "SYSTEM", "STATISTICS", "TYPE", SQL_SMALLINT, 50 },
16002 { "SYSTEM", "STATISTICS", "ORDINAL_POSITION", SQL_SMALLINT, 50 },
16003 { "SYSTEM", "STATISTICS", "COLUMN_NAME", SCOL_VARCHAR, 255 },
16004 { "SYSTEM", "STATISTICS", "ASC_OR_DESC", SCOL_CHAR, 1 },
16005 { "SYSTEM", "STATISTICS", "CARDINALITY", SQL_INTEGER, 50 },
16006 { "SYSTEM", "STATISTICS", "PAGES", SQL_INTEGER, 50 },
16007 { "SYSTEM", "STATISTICS", "FILTER_CONDITION", SCOL_VARCHAR, 255 }
16008 };
16009
16010 /**
16011 * Internal return statistic information on table indices.
16012 * @param stmt statement handle
16013 * @param cat catalog name/pattern or NULL
16014 * @param catLen length of catalog name/pattern or SQL_NTS
16015 * @param schema schema name/pattern or NULL
16016 * @param schemaLen length of schema name/pattern or SQL_NTS
16017 * @param table table name/pattern or NULL
16018 * @param tableLen length of table name/pattern or SQL_NTS
16019 * @param itype type of index information
16020 * @param resv reserved
16021 * @result ODBC error code
16022 */
16023
16024 static SQLRETURN
drvstatistics(SQLHSTMT stmt,SQLCHAR * cat,SQLSMALLINT catLen,SQLCHAR * schema,SQLSMALLINT schemaLen,SQLCHAR * table,SQLSMALLINT tableLen,SQLUSMALLINT itype,SQLUSMALLINT resv)16025 drvstatistics(SQLHSTMT stmt, SQLCHAR *cat, SQLSMALLINT catLen,
16026 SQLCHAR *schema, SQLSMALLINT schemaLen,
16027 SQLCHAR *table, SQLSMALLINT tableLen,
16028 SQLUSMALLINT itype, SQLUSMALLINT resv)
16029 {
16030 SQLRETURN sret;
16031 STMT *s;
16032 DBC *d;
16033 int i, asize, ret, nrows, ncols, offs, namec, uniquec, addipk = 0;
16034 PTRDIFF_T size;
16035 char **rowp, *errp = NULL, *sql, tname[512];
16036
16037 sret = mkresultset(stmt, statSpec2, array_size(statSpec2),
16038 statSpec3, array_size(statSpec3), &asize);
16039 if (sret != SQL_SUCCESS) {
16040 return sret;
16041 }
16042 s = (STMT *) stmt;
16043 d = (DBC *) s->dbc;
16044 if (!table || table[0] == '\0' || table[0] == '%') {
16045 setstat(s, -1, "need table name", (*s->ov3) ? "HY000" : "S1000");
16046 return SQL_ERROR;
16047 }
16048 if (tableLen == SQL_NTS) {
16049 size = sizeof (tname) - 1;
16050 } else {
16051 size = min(sizeof (tname) - 1, tableLen);
16052 }
16053 strncpy(tname, (char *) table, size);
16054 tname[size] = '\0';
16055 unescpat(tname);
16056 sret = starttran(s);
16057 if (sret != SQL_SUCCESS) {
16058 return sret;
16059 }
16060 /*
16061 * Try integer primary key (autoincrement) first
16062 */
16063 if (itype == SQL_INDEX_UNIQUE || itype == SQL_INDEX_ALL) {
16064 rowp = 0;
16065 ret = SQLITE_ERROR;
16066 sql = sqlite3_mprintf("PRAGMA table_info(%Q)", tname);
16067 if (sql) {
16068 dbtraceapi(d, "sqlite3_get_table", sql);
16069 ret = sqlite3_get_table(d->sqlite, sql, &rowp,
16070 &nrows, &ncols, NULL);
16071 sqlite3_free(sql);
16072 }
16073 if (ret == SQLITE_OK) {
16074 int colid, typec, npk = 0, npkint = 0;
16075
16076 namec = findcol(rowp, ncols, "name");
16077 uniquec = findcol(rowp, ncols, "pk");
16078 typec = findcol(rowp, ncols, "type");
16079 colid = findcol(rowp, ncols, "cid");
16080 if (namec < 0 || uniquec < 0 || typec < 0 || colid < 0) {
16081 goto noipk;
16082 }
16083 for (i = 1; i <= nrows; i++) {
16084 if (*rowp[i * ncols + uniquec] != '0') {
16085 npk++;
16086 if (strlen(rowp[i * ncols + typec]) == 7 &&
16087 strncasecmp(rowp[i * ncols + typec], "integer", 7)
16088 == 0) {
16089 npkint++;
16090 }
16091 }
16092 }
16093 if (npkint == 1 && npk == npkint) {
16094 addipk = 1;
16095 }
16096 }
16097 noipk:
16098 sqlite3_free_table(rowp);
16099 }
16100 sql = sqlite3_mprintf("PRAGMA index_list(%Q)", tname);
16101 if (!sql) {
16102 return nomem(s);
16103 }
16104 dbtraceapi(d, "sqlite3_get_table", sql);
16105 ret = sqlite3_get_table(d->sqlite, sql, &rowp, &nrows, &ncols, &errp);
16106 sqlite3_free(sql);
16107 if (ret != SQLITE_OK) {
16108 setstat(s, ret, "%s (%d)", (*s->ov3) ? "HY000" : "S1000",
16109 errp ? errp : "unknown error", ret);
16110 if (errp) {
16111 sqlite3_free(errp);
16112 errp = NULL;
16113 }
16114 return SQL_ERROR;
16115 }
16116 if (errp) {
16117 sqlite3_free(errp);
16118 errp = NULL;
16119 }
16120 size = 0;
16121 namec = findcol(rowp, ncols, "name");
16122 uniquec = findcol(rowp, ncols, "unique");
16123 if (namec < 0 || uniquec < 0) {
16124 goto nodata;
16125 }
16126 for (i = 1; i <= nrows; i++) {
16127 int nnrows, nncols;
16128 char **rowpp;
16129 int isuniq;
16130
16131 isuniq = *rowp[i * ncols + uniquec] != '0';
16132 if (isuniq || itype == SQL_INDEX_ALL) {
16133 ret = SQLITE_ERROR;
16134 sql = sqlite3_mprintf("PRAGMA index_info(%Q)",
16135 rowp[i * ncols + namec]);
16136 if (sql) {
16137 dbtraceapi(d, "sqlite3_get_table", sql);
16138 ret = sqlite3_get_table(d->sqlite, sql, &rowpp,
16139 &nnrows, &nncols, NULL);
16140 sqlite3_free(sql);
16141 }
16142 if (ret == SQLITE_OK) {
16143 size += nnrows;
16144 sqlite3_free_table(rowpp);
16145 }
16146 }
16147 }
16148 nodata:
16149 if (addipk) {
16150 size++;
16151 }
16152 if (size == 0) {
16153 sqlite3_free_table(rowp);
16154 return SQL_SUCCESS;
16155 }
16156 s->nrows = size;
16157 size = (size + 1) * asize;
16158 s->rows = xmalloc((size + 1) * sizeof (char *));
16159 if (!s->rows) {
16160 s->nrows = 0;
16161 return nomem(s);
16162 }
16163 s->rows[0] = (char *) size;
16164 s->rows += 1;
16165 memset(s->rows, 0, sizeof (char *) * size);
16166 s->rowfree = freerows;
16167 offs = 0;
16168 if (addipk) {
16169 char **rowpp = 0;
16170 int nrows2, ncols2;
16171
16172 sql = sqlite3_mprintf("PRAGMA table_info(%Q)", tname);
16173 if (sql) {
16174 dbtraceapi(d, "sqlite3_get_table", sql);
16175 ret = sqlite3_get_table(d->sqlite, sql, &rowpp,
16176 &nrows2, &ncols2, NULL);
16177 sqlite3_free(sql);
16178 }
16179 if (ret == SQLITE_OK) {
16180 int colid, typec, roffs, namecc, uniquecc;
16181
16182 namecc = findcol(rowpp, ncols2, "name");
16183 uniquecc = findcol(rowpp, ncols2, "pk");
16184 typec = findcol(rowpp, ncols2, "type");
16185 colid = findcol(rowpp, ncols2, "cid");
16186 if (namecc < 0 || uniquecc < 0 || typec < 0 || colid < 0) {
16187 addipk = 0;
16188 s->nrows--;
16189 goto nodata2;
16190 }
16191 for (i = 1; i <= nrows2; i++) {
16192 if (*rowpp[i * ncols2 + uniquecc] != '0' &&
16193 strlen(rowpp[i * ncols2 + typec]) == 7 &&
16194 strncasecmp(rowpp[i * ncols2 + typec], "integer", 7)
16195 == 0) {
16196 break;
16197 }
16198 }
16199 if (i > nrows2) {
16200 addipk = 0;
16201 s->nrows--;
16202 goto nodata2;
16203 }
16204 roffs = s->ncols;
16205 #if defined(_WIN32) || defined(_WIN64)
16206 s->rows[roffs + 0] = xstrdup(d->xcelqrx ? "main" : "");
16207 s->rows[roffs + 1] = xstrdup("");
16208 #else
16209 s->rows[roffs + 0] = xstrdup("");
16210 s->rows[roffs + 1] = xstrdup("");
16211 #endif
16212 s->rows[roffs + 2] = xstrdup(tname);
16213 s->rows[roffs + 3] = xstrdup(stringify(SQL_FALSE));
16214 s->rows[roffs + 5] = xstrdup("sqlite_autoindex_0");
16215 s->rows[roffs + 6] = xstrdup(stringify(SQL_INDEX_OTHER));
16216 s->rows[roffs + 7] = xstrdup("1");
16217 s->rows[roffs + 8] = xstrdup(rowpp[i * ncols2 + namecc]);
16218 s->rows[roffs + 9] = xstrdup("A");
16219 }
16220 nodata2:
16221 sqlite3_free_table(rowpp);
16222 }
16223 for (i = 1; i <= nrows; i++) {
16224 int nnrows, nncols;
16225 char **rowpp = 0;
16226
16227 if (*rowp[i * ncols + uniquec] != '0' || itype == SQL_INDEX_ALL) {
16228 int k;
16229
16230 ret = SQLITE_ERROR;
16231 sql = sqlite3_mprintf("PRAGMA index_info(%Q)",
16232 rowp[i * ncols + namec]);
16233 if (sql) {
16234 dbtraceapi(d, "sqlite3_get_table", sql);
16235 ret = sqlite3_get_table(d->sqlite, sql, &rowpp,
16236 &nnrows, &nncols, NULL);
16237 sqlite3_free(sql);
16238 }
16239 if (ret != SQLITE_OK) {
16240 continue;
16241 }
16242 for (k = 0; nnrows && k < nncols; k++) {
16243 if (strcmp(rowpp[k], "name") == 0) {
16244 int m;
16245
16246 for (m = 1; m <= nnrows; m++) {
16247 int roffs = (offs + addipk + m) * s->ncols;
16248 int isuniq;
16249
16250 isuniq = *rowp[i * ncols + uniquec] != '0';
16251 s->rows[roffs + 0] = xstrdup("");
16252 s->rows[roffs + 1] = xstrdup("");
16253 s->rows[roffs + 2] = xstrdup(tname);
16254 if (isuniq) {
16255 s->rows[roffs + 3] = xstrdup(stringify(SQL_FALSE));
16256 } else {
16257 s->rows[roffs + 3] = xstrdup(stringify(SQL_TRUE));
16258 }
16259 s->rows[roffs + 5] = xstrdup(rowp[i * ncols + namec]);
16260 s->rows[roffs + 6] =
16261 xstrdup(stringify(SQL_INDEX_OTHER));
16262 s->rows[roffs + 8] = xstrdup(rowpp[m * nncols + k]);
16263 s->rows[roffs + 9] = xstrdup("A");
16264 }
16265 } else if (strcmp(rowpp[k], "seqno") == 0) {
16266 int m;
16267
16268 for (m = 1; m <= nnrows; m++) {
16269 int roffs = (offs + addipk + m) * s->ncols;
16270 int pos = m - 1;
16271 char buf[32];
16272
16273 sscanf(rowpp[m * nncols + k], "%d", &pos);
16274 sprintf(buf, "%d", pos + 1);
16275 s->rows[roffs + 7] = xstrdup(buf);
16276 }
16277 }
16278 }
16279 offs += nnrows;
16280 sqlite3_free_table(rowpp);
16281 }
16282 }
16283 sqlite3_free_table(rowp);
16284 return SQL_SUCCESS;
16285 }
16286
16287 #ifndef WINTERFACE
16288 /**
16289 * Return statistic information on table indices.
16290 * @param stmt statement handle
16291 * @param cat catalog name/pattern or NULL
16292 * @param catLen length of catalog name/pattern or SQL_NTS
16293 * @param schema schema name/pattern or NULL
16294 * @param schemaLen length of schema name/pattern or SQL_NTS
16295 * @param table table name/pattern or NULL
16296 * @param tableLen length of table name/pattern or SQL_NTS
16297 * @param itype type of index information
16298 * @param resv reserved
16299 * @result ODBC error code
16300 */
16301
16302 SQLRETURN SQL_API
SQLStatistics(SQLHSTMT stmt,SQLCHAR * cat,SQLSMALLINT catLen,SQLCHAR * schema,SQLSMALLINT schemaLen,SQLCHAR * table,SQLSMALLINT tableLen,SQLUSMALLINT itype,SQLUSMALLINT resv)16303 SQLStatistics(SQLHSTMT stmt, SQLCHAR *cat, SQLSMALLINT catLen,
16304 SQLCHAR *schema, SQLSMALLINT schemaLen,
16305 SQLCHAR *table, SQLSMALLINT tableLen,
16306 SQLUSMALLINT itype, SQLUSMALLINT resv)
16307 {
16308 #if defined(_WIN32) || defined(_WIN64)
16309 char *c = NULL, *s = NULL, *t = NULL;
16310 #endif
16311 SQLRETURN ret;
16312
16313 HSTMT_LOCK(stmt);
16314 #if defined(_WIN32) || defined(_WIN64)
16315 if (!((STMT *) stmt)->oemcp[0]) {
16316 ret = drvstatistics(stmt, cat, catLen, schema, schemaLen,
16317 table, tableLen, itype, resv);
16318 goto done2;
16319 }
16320 if (cat) {
16321 c = wmb_to_utf_c((char *) cat, catLen);
16322 if (!c) {
16323 ret = nomem((STMT *) stmt);
16324 goto done;
16325 }
16326 }
16327 if (schema) {
16328 s = wmb_to_utf_c((char *) schema, schemaLen);
16329 if (!s) {
16330 ret = nomem((STMT *) stmt);
16331 goto done;
16332 }
16333 }
16334 if (table) {
16335 t = wmb_to_utf_c((char *) table, tableLen);
16336 if (!t) {
16337 ret = nomem((STMT *) stmt);
16338 goto done;
16339 }
16340 }
16341 ret = drvstatistics(stmt, (SQLCHAR *) c, SQL_NTS, (SQLCHAR *) s, SQL_NTS,
16342 (SQLCHAR *) t, SQL_NTS, itype, resv);
16343 #else
16344 ret = drvstatistics(stmt, cat, catLen, schema, schemaLen,
16345 table, tableLen, itype, resv);
16346 #endif
16347 #if defined(_WIN32) || defined(_WIN64)
16348 done:
16349 uc_free(t);
16350 uc_free(s);
16351 uc_free(c);
16352 done2:
16353 ;
16354 #endif
16355 HSTMT_UNLOCK(stmt);
16356 return ret;
16357 }
16358 #endif
16359
16360 #ifdef WINTERFACE
16361 /**
16362 * Return statistic information on table indices (UNICODE version).
16363 * @param stmt statement handle
16364 * @param cat catalog name/pattern or NULL
16365 * @param catLen length of catalog name/pattern or SQL_NTS
16366 * @param schema schema name/pattern or NULL
16367 * @param schemaLen length of schema name/pattern or SQL_NTS
16368 * @param table table name/pattern or NULL
16369 * @param tableLen length of table name/pattern or SQL_NTS
16370 * @param itype type of index information
16371 * @param resv reserved
16372 * @result ODBC error code
16373 */
16374
16375 SQLRETURN SQL_API
SQLStatisticsW(SQLHSTMT stmt,SQLWCHAR * cat,SQLSMALLINT catLen,SQLWCHAR * schema,SQLSMALLINT schemaLen,SQLWCHAR * table,SQLSMALLINT tableLen,SQLUSMALLINT itype,SQLUSMALLINT resv)16376 SQLStatisticsW(SQLHSTMT stmt, SQLWCHAR *cat, SQLSMALLINT catLen,
16377 SQLWCHAR *schema, SQLSMALLINT schemaLen,
16378 SQLWCHAR *table, SQLSMALLINT tableLen,
16379 SQLUSMALLINT itype, SQLUSMALLINT resv)
16380 {
16381 char *c = NULL, *s = NULL, *t = NULL;
16382 SQLRETURN ret;
16383
16384 HSTMT_LOCK(stmt);
16385 if (cat) {
16386 c = uc_to_utf_c(cat, catLen);
16387 if (!c) {
16388 ret = nomem((STMT *) stmt);
16389 goto done;
16390 }
16391 }
16392 if (schema) {
16393 s = uc_to_utf_c(schema, schemaLen);
16394 if (!s) {
16395 ret = nomem((STMT *) stmt);
16396 goto done;
16397 }
16398 }
16399 if (table) {
16400 t = uc_to_utf_c(table, tableLen);
16401 if (!t) {
16402 ret = nomem((STMT *) stmt);
16403 goto done;
16404 }
16405 }
16406 ret = drvstatistics(stmt, (SQLCHAR *) c, SQL_NTS, (SQLCHAR *) s, SQL_NTS,
16407 (SQLCHAR *) t, SQL_NTS, itype, resv);
16408 done:
16409 uc_free(t);
16410 uc_free(s);
16411 uc_free(c);
16412 HSTMT_UNLOCK(stmt);
16413 return ret;
16414 }
16415 #endif
16416
16417 /**
16418 * Retrieve row data after fetch.
16419 * @param stmt statement handle
16420 * @param col column number, starting at 1
16421 * @param type output type
16422 * @param val output buffer
16423 * @param len length of output buffer
16424 * @param lenp output length
16425 * @result ODBC error code
16426 */
16427
16428 SQLRETURN SQL_API
SQLGetData(SQLHSTMT stmt,SQLUSMALLINT col,SQLSMALLINT type,SQLPOINTER val,SQLLEN len,SQLLEN * lenp)16429 SQLGetData(SQLHSTMT stmt, SQLUSMALLINT col, SQLSMALLINT type,
16430 SQLPOINTER val, SQLLEN len, SQLLEN *lenp)
16431 {
16432 STMT *s;
16433 SQLRETURN ret = SQL_ERROR;
16434
16435 HSTMT_LOCK(stmt);
16436 if (stmt == SQL_NULL_HSTMT) {
16437 return SQL_INVALID_HANDLE;
16438 }
16439 s = (STMT *) stmt;
16440 if (col == 0 && s->bkmrk != SQL_UB_OFF) {
16441 if (s->bkmrk == SQL_UB_ON && type == SQL_C_BOOKMARK) {
16442 *((SQLINTEGER *) val) = s->rowp;
16443 if (lenp) {
16444 *lenp = sizeof (SQLINTEGER);
16445 }
16446 ret = SQL_SUCCESS;
16447 goto done;
16448 } else if (s->bkmrk == SQL_UB_VARIABLE && type == SQL_C_VARBOOKMARK) {
16449 if (s->has_rowid >= 0) {
16450 char **data, *endp = 0;
16451
16452 data = s->rows + s->ncols + (s->rowp * s->ncols)
16453 + s->has_rowid;
16454 #ifdef __osf__
16455 *((sqlite_int64 *) val) = strtol(*data, &endp, 0);
16456 #else
16457 *((sqlite_int64 *) val) = strtoll(*data, &endp, 0);
16458 #endif
16459 } else {
16460 *((sqlite_int64 *) val) = s->rowp;
16461 }
16462 if (lenp) {
16463 *lenp = sizeof (sqlite_int64);
16464 }
16465 ret = SQL_SUCCESS;
16466 goto done;
16467 }
16468 }
16469 if (col < 1 || col > s->ncols) {
16470 setstat(s, -1, "invalid column", (*s->ov3) ? "07009" : "S1002");
16471 goto done;
16472 }
16473 --col;
16474 ret = getrowdata(s, col, type, val, len, lenp, 1);
16475 done:
16476 HSTMT_UNLOCK(stmt);
16477 return ret;
16478 }
16479
16480 /**
16481 * Internal: fetch and bind from statement's current row
16482 * @param s statement pointer
16483 * @param rsi rowset index
16484 * @result ODBC error code
16485 */
16486
16487 static SQLRETURN
dofetchbind(STMT * s,int rsi)16488 dofetchbind(STMT *s, int rsi)
16489 {
16490 int ret, i, withinfo = 0;
16491
16492 s->row_status0[rsi] = SQL_ROW_SUCCESS;
16493 if (s->bkmrk != SQL_UB_OFF && s->bkmrkcol.valp) {
16494 int bsize = sizeof (SQLINTEGER);
16495
16496 if (s->bkmrkcol.type == SQL_C_VARBOOKMARK) {
16497 SQLPOINTER *val;
16498
16499 if (s->bind_type != SQL_BIND_BY_COLUMN) {
16500 val = (SQLPOINTER)
16501 ((char *) s->bkmrkcol.valp + s->bind_type * rsi);
16502 } else {
16503 val = (SQLPOINTER)
16504 ((char *) s->bkmrkcol.valp + s->bkmrkcol.max * rsi);
16505 }
16506 if (s->bind_offs) {
16507 val = (SQLPOINTER) ((char *) val + *s->bind_offs);
16508 }
16509 if (s->has_rowid >= 0) {
16510 char **data, *endp = 0;
16511
16512 data = s->rows + s->ncols + (s->rowp * s->ncols)
16513 + s->has_rowid;
16514 #ifdef __osf__
16515 *(sqlite_int64 *) val = strtol(*data, &endp, 0);
16516 #else
16517 *(sqlite_int64 *) val = strtoll(*data, &endp, 0);
16518 #endif
16519 } else {
16520 *(sqlite_int64 *) val = s->rowp;
16521 }
16522 bsize = sizeof (sqlite_int64);
16523 } else {
16524 SQLINTEGER *val;
16525
16526 if (s->bind_type != SQL_BIND_BY_COLUMN) {
16527 val = (SQLINTEGER *)
16528 ((char *) s->bkmrkcol.valp + s->bind_type * rsi);
16529 } else {
16530 val = (SQLINTEGER *) s->bkmrkcol.valp + rsi;
16531 }
16532 if (s->bind_offs) {
16533 val = (SQLINTEGER *) ((char *) val + *s->bind_offs);
16534 }
16535 *val = s->rowp;
16536 }
16537 if (s->bkmrkcol.lenp) {
16538 SQLLEN *ival;
16539
16540 if (s->bind_type != SQL_BIND_BY_COLUMN) {
16541 ival = (SQLLEN *)
16542 ((char *) s->bkmrkcol.lenp + s->bind_type * rsi);
16543 } else {
16544 ival = &s->bkmrkcol.lenp[rsi];
16545 }
16546 if (s->bind_offs) {
16547 ival = (SQLLEN *) ((char *) ival + *s->bind_offs);
16548 }
16549 *ival = bsize;
16550 }
16551 }
16552 ret = SQL_SUCCESS;
16553 for (i = 0; s->bindcols && i < s->ncols; i++) {
16554 BINDCOL *b = &s->bindcols[i];
16555 SQLPOINTER dp = 0;
16556 SQLLEN *lp = 0;
16557
16558 b->offs = 0;
16559 if (b->valp) {
16560 if (s->bind_type != SQL_BIND_BY_COLUMN) {
16561 dp = (SQLPOINTER) ((char *) b->valp + s->bind_type * rsi);
16562 } else {
16563 dp = (SQLPOINTER) ((char *) b->valp + b->max * rsi);
16564 }
16565 if (s->bind_offs) {
16566 dp = (SQLPOINTER) ((char *) dp + *s->bind_offs);
16567 }
16568 }
16569 if (b->lenp) {
16570 if (s->bind_type != SQL_BIND_BY_COLUMN) {
16571 lp = (SQLLEN *) ((char *) b->lenp + s->bind_type * rsi);
16572 } else {
16573 lp = b->lenp + rsi;
16574 }
16575 if (s->bind_offs) {
16576 lp = (SQLLEN *) ((char *) lp + *s->bind_offs);
16577 }
16578 }
16579 if (dp || lp) {
16580 ret = getrowdata(s, (SQLUSMALLINT) i, b->type, dp, b->max, lp, 0);
16581 if (!SQL_SUCCEEDED(ret)) {
16582 s->row_status0[rsi] = SQL_ROW_ERROR;
16583 break;
16584 }
16585 if (ret != SQL_SUCCESS) {
16586 withinfo = 1;
16587 #ifdef SQL_ROW_SUCCESS_WITH_INFO
16588 s->row_status0[rsi] = SQL_ROW_SUCCESS_WITH_INFO;
16589 #endif
16590 }
16591 }
16592 }
16593 if (SQL_SUCCEEDED(ret)) {
16594 ret = withinfo ? SQL_SUCCESS_WITH_INFO : SQL_SUCCESS;
16595 }
16596 return ret;
16597 }
16598
16599 /**
16600 * Internal fetch function for SQLFetchScroll() and SQLExtendedFetch().
16601 * @param stmt statement handle
16602 * @param orient fetch direction
16603 * @param offset offset for fetch direction
16604 * @result ODBC error code
16605 */
16606
16607 static SQLRETURN
drvfetchscroll(SQLHSTMT stmt,SQLSMALLINT orient,SQLINTEGER offset)16608 drvfetchscroll(SQLHSTMT stmt, SQLSMALLINT orient, SQLINTEGER offset)
16609 {
16610 STMT *s;
16611 int i, withinfo = 0;
16612 SQLRETURN ret;
16613
16614 if (stmt == SQL_NULL_HSTMT) {
16615 return SQL_INVALID_HANDLE;
16616 }
16617 s = (STMT *) stmt;
16618 for (i = 0; i < s->rowset_size; i++) {
16619 s->row_status0[i] = SQL_ROW_NOROW;
16620 }
16621 if (s->row_status) {
16622 memcpy(s->row_status, s->row_status0,
16623 sizeof (SQLUSMALLINT) * s->rowset_size);
16624 }
16625 s->row_count0 = 0;
16626 if (s->row_count) {
16627 *s->row_count = s->row_count0;
16628 }
16629 if (!s->bindcols) {
16630 for (i = 0; i < s->rowset_size; i++) {
16631 s->row_status0[i] = SQL_ROW_ERROR;
16632 }
16633 ret = SQL_ERROR;
16634 i = 0;
16635 goto done2;
16636 }
16637 if (s->isselect != 1 && s->isselect != -1) {
16638 setstat(s, -1, "no result set available", "24000");
16639 ret = SQL_ERROR;
16640 i = s->nrows;
16641 goto done2;
16642 }
16643 if (s->curtype == SQL_CURSOR_FORWARD_ONLY && orient != SQL_FETCH_NEXT) {
16644 setstat(s, -1, "wrong fetch direction", "01000");
16645 ret = SQL_ERROR;
16646 i = 0;
16647 goto done2;
16648 }
16649 ret = SQL_SUCCESS;
16650 i = 0;
16651 if (((DBC *) (s->dbc))->cur_s3stmt == s && s->s3stmt) {
16652 s->rowp = s->rowprs = 0;
16653 for (; i < s->rowset_size; i++) {
16654 if (s->max_rows && s->s3stmt_rownum + 1 >= s->max_rows) {
16655 ret = (i == 0) ? SQL_NO_DATA : SQL_SUCCESS;
16656 break;
16657 }
16658 ret = s3stmt_step(s);
16659 if (ret != SQL_SUCCESS) {
16660 s->row_status0[i] = SQL_ROW_ERROR;
16661 break;
16662 }
16663 if (s->nrows < 1) {
16664 break;
16665 }
16666 ret = dofetchbind(s, i);
16667 if (!SQL_SUCCEEDED(ret)) {
16668 break;
16669 } else if (ret == SQL_SUCCESS_WITH_INFO) {
16670 withinfo = 1;
16671 }
16672 }
16673 } else if (s->rows) {
16674 switch (orient) {
16675 case SQL_FETCH_NEXT:
16676 if (s->nrows < 1) {
16677 return SQL_NO_DATA;
16678 }
16679 if (s->rowp < 0) {
16680 s->rowp = -1;
16681 }
16682 if (s->rowp >= s->nrows) {
16683 s->rowp = s->rowprs = s->nrows;
16684 return SQL_NO_DATA;
16685 }
16686 break;
16687 case SQL_FETCH_PRIOR:
16688 if (s->nrows < 1 || s->rowp <= 0) {
16689 s->rowp = s->rowprs = -1;
16690 return SQL_NO_DATA;
16691 }
16692 s->rowp -= s->rowset_size + 1;
16693 if (s->rowp < -1) {
16694 s->rowp = s->rowprs = -1;
16695 return SQL_NO_DATA;
16696 }
16697 break;
16698 case SQL_FETCH_FIRST:
16699 if (s->nrows < 1) {
16700 return SQL_NO_DATA;
16701 }
16702 s->rowp = -1;
16703 break;
16704 case SQL_FETCH_LAST:
16705 if (s->nrows < 1) {
16706 return SQL_NO_DATA;
16707 }
16708 s->rowp = s->nrows - s->rowset_size;
16709 if (--s->rowp < -1) {
16710 s->rowp = -1;
16711 }
16712 break;
16713 case SQL_FETCH_ABSOLUTE:
16714 if (offset == 0) {
16715 s->rowp = s->rowprs = -1;
16716 return SQL_NO_DATA;
16717 } else if (offset < 0) {
16718 if (0 - offset <= s->nrows) {
16719 s->rowp = s->nrows + offset - 1;
16720 break;
16721 }
16722 s->rowp = s->rowprs = -1;
16723 return SQL_NO_DATA;
16724 } else if (offset > s->nrows) {
16725 s->rowp = s->rowprs = s->nrows;
16726 return SQL_NO_DATA;
16727 }
16728 s->rowp = offset - 1 - 1;
16729 break;
16730 case SQL_FETCH_RELATIVE:
16731 if (offset >= 0) {
16732 s->rowp += offset * s->rowset_size - 1;
16733 if (s->rowp >= s->nrows) {
16734 s->rowp = s->rowprs = s->nrows;
16735 return SQL_NO_DATA;
16736 }
16737 } else {
16738 s->rowp += offset * s->rowset_size - 1;
16739 if (s->rowp < -1) {
16740 s->rowp = s->rowprs = -1;
16741 return SQL_NO_DATA;
16742 }
16743 }
16744 break;
16745 case SQL_FETCH_BOOKMARK:
16746 if (s->bkmrk == SQL_UB_ON && !s->bkmrkptr) {
16747 if (offset < 0 || offset >= s->nrows) {
16748 return SQL_NO_DATA;
16749 }
16750 s->rowp = offset - 1;
16751 break;
16752 }
16753 if (s->bkmrk != SQL_UB_OFF && s->bkmrkptr) {
16754 int rowp;
16755
16756 if (s->bkmrk == SQL_UB_VARIABLE) {
16757 if (s->has_rowid >= 0) {
16758 sqlite_int64 bkmrk, rowid;
16759
16760 bkmrk = *(sqlite_int64 *) s->bkmrkptr;
16761 for (rowp = 0; rowp < s->nrows; rowp++) {
16762 char **data, *endp = 0;
16763
16764 data = s->rows + s->ncols + (rowp * s->ncols)
16765 + s->has_rowid;
16766 #ifdef __osf__
16767 rowid = strtol(*data, &endp, 0);
16768 #else
16769 rowid = strtoll(*data, &endp, 0);
16770 #endif
16771 if (rowid == bkmrk) {
16772 break;
16773 }
16774 }
16775 } else {
16776 rowp = *(sqlite_int64 *) s->bkmrkptr;
16777 }
16778 } else {
16779 rowp = *(int *) s->bkmrkptr;
16780 }
16781 if (rowp + offset < 0 || rowp + offset >= s->nrows) {
16782 return SQL_NO_DATA;
16783 }
16784 s->rowp = rowp + offset - 1;
16785 break;
16786 }
16787 /* fall through */
16788 default:
16789 s->row_status0[0] = SQL_ROW_ERROR;
16790 ret = SQL_ERROR;
16791 goto done;
16792 }
16793 s->rowprs = s->rowp + 1;
16794 for (; i < s->rowset_size; i++) {
16795 ++s->rowp;
16796 if (s->rowp < 0 || s->rowp >= s->nrows) {
16797 break;
16798 }
16799 ret = dofetchbind(s, i);
16800 if (!SQL_SUCCEEDED(ret)) {
16801 break;
16802 } else if (ret == SQL_SUCCESS_WITH_INFO) {
16803 withinfo = 1;
16804 }
16805 }
16806 }
16807 done:
16808 if (i == 0) {
16809 if (SQL_SUCCEEDED(ret)) {
16810 return SQL_NO_DATA;
16811 }
16812 return ret;
16813 }
16814 if (SQL_SUCCEEDED(ret)) {
16815 ret = withinfo ? SQL_SUCCESS_WITH_INFO : SQL_SUCCESS;
16816 }
16817 done2:
16818 if (s->row_status) {
16819 memcpy(s->row_status, s->row_status0,
16820 sizeof (SQLUSMALLINT) * s->rowset_size);
16821 }
16822 s->row_count0 = i;
16823 if (s->row_count) {
16824 *s->row_count = s->row_count0;
16825 }
16826 return ret;
16827 }
16828
16829 /**
16830 * Fetch next result row.
16831 * @param stmt statement handle
16832 * @result ODBC error code
16833 */
16834
16835 SQLRETURN SQL_API
SQLFetch(SQLHSTMT stmt)16836 SQLFetch(SQLHSTMT stmt)
16837 {
16838 SQLRETURN ret;
16839
16840 HSTMT_LOCK(stmt);
16841 ret = drvfetchscroll(stmt, SQL_FETCH_NEXT, 0);
16842 HSTMT_UNLOCK(stmt);
16843 return ret;
16844 }
16845
16846 /**
16847 * Fetch result row with scrolling.
16848 * @param stmt statement handle
16849 * @param orient fetch direction
16850 * @param offset offset for fetch direction
16851 * @result ODBC error code
16852 */
16853
16854 SQLRETURN SQL_API
SQLFetchScroll(SQLHSTMT stmt,SQLSMALLINT orient,SQLLEN offset)16855 SQLFetchScroll(SQLHSTMT stmt, SQLSMALLINT orient, SQLLEN offset)
16856 {
16857 SQLRETURN ret;
16858
16859 HSTMT_LOCK(stmt);
16860 ret = drvfetchscroll(stmt, orient, offset);
16861 HSTMT_UNLOCK(stmt);
16862 return ret;
16863 }
16864
16865 /**
16866 * Fetch result row with scrolling and row status.
16867 * @param stmt statement handle
16868 * @param orient fetch direction
16869 * @param offset offset for fetch direction
16870 * @param rowcount output number of fetched rows
16871 * @param rowstatus array for row stati
16872 * @result ODBC error code
16873 */
16874
16875 SQLRETURN SQL_API
SQLExtendedFetch(SQLHSTMT stmt,SQLUSMALLINT orient,SQLROWOFFSET offset,SQLROWSETSIZE * rowcount,SQLUSMALLINT * rowstatus)16876 SQLExtendedFetch(SQLHSTMT stmt, SQLUSMALLINT orient, SQLROWOFFSET offset,
16877 SQLROWSETSIZE *rowcount, SQLUSMALLINT *rowstatus)
16878 {
16879 STMT *s;
16880 SQLRETURN ret;
16881 SQLUSMALLINT *rst;
16882 SQLINTEGER *bkmrkptr;
16883
16884 HSTMT_LOCK(stmt);
16885 if (stmt == SQL_NULL_HSTMT) {
16886 return SQL_INVALID_HANDLE;
16887 }
16888 s = (STMT *) stmt;
16889 /* temporarily turn off SQL_ATTR_ROW_STATUS_PTR */
16890 rst = s->row_status;
16891 s->row_status = 0;
16892 bkmrkptr = s->bkmrkptr;
16893 s->bkmrkptr = 0;
16894 ret = drvfetchscroll(stmt, orient, offset);
16895 s->row_status = rst;
16896 s->bkmrkptr = bkmrkptr;
16897 if (rowstatus) {
16898 memcpy(rowstatus, s->row_status0,
16899 sizeof (SQLUSMALLINT) * s->rowset_size);
16900 }
16901 if (rowcount) {
16902 *rowcount = s->row_count0;
16903 }
16904 HSTMT_UNLOCK(stmt);
16905 return ret;
16906 }
16907
16908 /**
16909 * Return number of affected rows of HSTMT.
16910 * @param stmt statement handle
16911 * @param nrows output number of rows
16912 * @result ODBC error code
16913 */
16914
16915 SQLRETURN SQL_API
SQLRowCount(SQLHSTMT stmt,SQLLEN * nrows)16916 SQLRowCount(SQLHSTMT stmt, SQLLEN *nrows)
16917 {
16918 STMT *s;
16919
16920 HSTMT_LOCK(stmt);
16921 if (stmt == SQL_NULL_HSTMT) {
16922 return SQL_INVALID_HANDLE;
16923 }
16924 s = (STMT *) stmt;
16925 if (nrows) {
16926 *nrows = s->isselect ? 0 : s->nrows;
16927 }
16928 HSTMT_UNLOCK(stmt);
16929 return SQL_SUCCESS;
16930 }
16931
16932 /**
16933 * Return number of columns of result set given HSTMT.
16934 * @param stmt statement handle
16935 * @param ncols output number of columns
16936 * @result ODBC error code
16937 */
16938
16939 SQLRETURN SQL_API
SQLNumResultCols(SQLHSTMT stmt,SQLSMALLINT * ncols)16940 SQLNumResultCols(SQLHSTMT stmt, SQLSMALLINT *ncols)
16941 {
16942 STMT *s;
16943
16944 HSTMT_LOCK(stmt);
16945 if (stmt == SQL_NULL_HSTMT) {
16946 return SQL_INVALID_HANDLE;
16947 }
16948 s = (STMT *) stmt;
16949 if (ncols) {
16950 *ncols = s->ncols;
16951 }
16952 HSTMT_UNLOCK(stmt);
16953 return SQL_SUCCESS;
16954 }
16955
16956 /**
16957 * Internal describe column information.
16958 * @param stmt statement handle
16959 * @param col column number, starting at 1
16960 * @param name buffer for column name
16961 * @param nameMax length of name buffer
16962 * @param nameLen output length of column name
16963 * @param type output SQL type
16964 * @param size output column size
16965 * @param digits output number of digits
16966 * @param nullable output NULL allowed indicator
16967 * @result ODBC error code
16968 */
16969
16970 static SQLRETURN
drvdescribecol(SQLHSTMT stmt,SQLUSMALLINT col,SQLCHAR * name,SQLSMALLINT nameMax,SQLSMALLINT * nameLen,SQLSMALLINT * type,SQLULEN * size,SQLSMALLINT * digits,SQLSMALLINT * nullable)16971 drvdescribecol(SQLHSTMT stmt, SQLUSMALLINT col, SQLCHAR *name,
16972 SQLSMALLINT nameMax, SQLSMALLINT *nameLen,
16973 SQLSMALLINT *type, SQLULEN *size,
16974 SQLSMALLINT *digits, SQLSMALLINT *nullable)
16975 {
16976 STMT *s;
16977 COL *c;
16978 int didname = 0;
16979
16980 if (stmt == SQL_NULL_HSTMT) {
16981 return SQL_INVALID_HANDLE;
16982 }
16983 s = (STMT *) stmt;
16984 if (!s->cols) {
16985 setstat(s, -1, "no columns", (*s->ov3) ? "07009" : "S1002");
16986 return SQL_ERROR;
16987 }
16988 if (col < 1 || col > s->ncols) {
16989 setstat(s, -1, "invalid column", (*s->ov3) ? "07009" : "S1002");
16990 return SQL_ERROR;
16991 }
16992 c = s->cols + col - 1;
16993 if (name && nameMax > 0) {
16994 strncpy((char *) name, c->column, nameMax);
16995 name[nameMax - 1] = '\0';
16996 didname = 1;
16997 }
16998 if (nameLen) {
16999 if (didname) {
17000 *nameLen = strlen((char *) name);
17001 } else {
17002 *nameLen = strlen(c->column);
17003 }
17004 }
17005 if (type) {
17006 *type = c->type;
17007 #ifdef WINTERFACE
17008 if (s->nowchar[0] || s->nowchar[1]) {
17009 switch (c->type) {
17010 case SQL_WCHAR:
17011 *type = SQL_CHAR;
17012 break;
17013 case SQL_WVARCHAR:
17014 *type = SQL_VARCHAR;
17015 break;
17016 #ifdef SQL_LONGVARCHAR
17017 case SQL_WLONGVARCHAR:
17018 *type = SQL_LONGVARCHAR;
17019 break;
17020 #endif
17021 }
17022 }
17023 #endif
17024 }
17025 if (size) {
17026 *size = c->size;
17027 }
17028 if (digits) {
17029 *digits = 0;
17030 }
17031 if (nullable) {
17032 *nullable = 1;
17033 }
17034 return SQL_SUCCESS;
17035 }
17036
17037 #ifndef WINTERFACE
17038 /**
17039 * Describe column information.
17040 * @param stmt statement handle
17041 * @param col column number, starting at 1
17042 * @param name buffer for column name
17043 * @param nameMax length of name buffer
17044 * @param nameLen output length of column name
17045 * @param type output SQL type
17046 * @param size output column size
17047 * @param digits output number of digits
17048 * @param nullable output NULL allowed indicator
17049 * @result ODBC error code
17050 */
17051
17052 SQLRETURN SQL_API
SQLDescribeCol(SQLHSTMT stmt,SQLUSMALLINT col,SQLCHAR * name,SQLSMALLINT nameMax,SQLSMALLINT * nameLen,SQLSMALLINT * type,SQLULEN * size,SQLSMALLINT * digits,SQLSMALLINT * nullable)17053 SQLDescribeCol(SQLHSTMT stmt, SQLUSMALLINT col, SQLCHAR *name,
17054 SQLSMALLINT nameMax, SQLSMALLINT *nameLen,
17055 SQLSMALLINT *type, SQLULEN *size,
17056 SQLSMALLINT *digits, SQLSMALLINT *nullable)
17057 {
17058 #if defined(_WIN32) || defined(_WIN64)
17059 SQLSMALLINT len = 0;
17060 #endif
17061 SQLRETURN ret;
17062
17063 HSTMT_LOCK(stmt);
17064 #if defined(_WIN32) || defined(_WIN64)
17065 if (!((STMT *) stmt)->oemcp[0]) {
17066 ret = drvdescribecol(stmt, col, name, nameMax, nameLen,
17067 type, size, digits, nullable);
17068 goto done;
17069 }
17070 ret = drvdescribecol(stmt, col, name, nameMax,
17071 &len, type, size, digits, nullable);
17072 if (ret == SQL_SUCCESS) {
17073 if (name) {
17074 if (len > 0) {
17075 SQLCHAR *n = NULL;
17076
17077 n = (SQLCHAR *) utf_to_wmb((char *) name, len);
17078 if (n) {
17079 strncpy((char *) name, (char *) n, nameMax);
17080 n[len] = 0;
17081 len = min(nameMax, strlen((char *) n));
17082 uc_free(n);
17083 } else {
17084 len = 0;
17085 }
17086 }
17087 if (len <= 0) {
17088 len = 0;
17089 if (nameMax > 0) {
17090 name[0] = 0;
17091 }
17092 }
17093 } else {
17094 STMT *s = (STMT *) stmt;
17095 COL *c = s->cols + col - 1;
17096
17097 len = 0;
17098 if (c->column) {
17099 len = strlen(c->column);
17100 }
17101 }
17102 if (nameLen) {
17103 *nameLen = len;
17104 }
17105 }
17106 done:
17107 ;
17108 #else
17109 ret = drvdescribecol(stmt, col, name, nameMax, nameLen,
17110 type, size, digits, nullable);
17111 #endif
17112 HSTMT_UNLOCK(stmt);
17113 return ret;
17114 }
17115 #endif
17116
17117 #ifdef WINTERFACE
17118 /**
17119 * Describe column information (UNICODE version).
17120 * @param stmt statement handle
17121 * @param col column number, starting at 1
17122 * @param name buffer for column name
17123 * @param nameMax length of name buffer
17124 * @param nameLen output length of column name
17125 * @param type output SQL type
17126 * @param size output column size
17127 * @param digits output number of digits
17128 * @param nullable output NULL allowed indicator
17129 * @result ODBC error code
17130 */
17131
17132 SQLRETURN SQL_API
SQLDescribeColW(SQLHSTMT stmt,SQLUSMALLINT col,SQLWCHAR * name,SQLSMALLINT nameMax,SQLSMALLINT * nameLen,SQLSMALLINT * type,SQLULEN * size,SQLSMALLINT * digits,SQLSMALLINT * nullable)17133 SQLDescribeColW(SQLHSTMT stmt, SQLUSMALLINT col, SQLWCHAR *name,
17134 SQLSMALLINT nameMax, SQLSMALLINT *nameLen,
17135 SQLSMALLINT *type, SQLULEN *size,
17136 SQLSMALLINT *digits, SQLSMALLINT *nullable)
17137 {
17138 SQLRETURN ret;
17139 SQLSMALLINT len = 0;
17140
17141 HSTMT_LOCK(stmt);
17142 ret = drvdescribecol(stmt, col, (SQLCHAR *) name,
17143 (SQLSMALLINT) (nameMax * sizeof (SQLWCHAR)),
17144 &len, type, size, digits, nullable);
17145 if (ret == SQL_SUCCESS) {
17146 if (name) {
17147 if (len > 0) {
17148 SQLWCHAR *n = NULL;
17149
17150 n = uc_from_utf((SQLCHAR *) name, len);
17151 if (n) {
17152 uc_strncpy(name, n, nameMax);
17153 n[len] = 0;
17154 len = min(nameMax, uc_strlen(n));
17155 uc_free(n);
17156 } else {
17157 len = 0;
17158 }
17159 }
17160 if (len <= 0) {
17161 len = 0;
17162 if (nameMax > 0) {
17163 name[0] = 0;
17164 }
17165 }
17166 } else {
17167 STMT *s = (STMT *) stmt;
17168 COL *c = s->cols + col - 1;
17169
17170 len = 0;
17171 if (c->column) {
17172 len = strlen(c->column);
17173 }
17174 }
17175 if (nameLen) {
17176 *nameLen = len;
17177 }
17178 }
17179 HSTMT_UNLOCK(stmt);
17180 return ret;
17181 }
17182 #endif
17183
17184 /**
17185 * Internal retrieve column attributes.
17186 * @param stmt statement handle
17187 * @param col column number, starting at 1
17188 * @param id attribute id
17189 * @param val output buffer
17190 * @param valMax length of output buffer
17191 * @param valLen output length
17192 * @param val2 integer output buffer
17193 * @result ODBC error code
17194 */
17195
17196 static SQLRETURN
drvcolattributes(SQLHSTMT stmt,SQLUSMALLINT col,SQLUSMALLINT id,SQLPOINTER val,SQLSMALLINT valMax,SQLSMALLINT * valLen,SQLLEN * val2)17197 drvcolattributes(SQLHSTMT stmt, SQLUSMALLINT col, SQLUSMALLINT id,
17198 SQLPOINTER val, SQLSMALLINT valMax, SQLSMALLINT *valLen,
17199 SQLLEN *val2)
17200 {
17201 STMT *s;
17202 COL *c;
17203 SQLSMALLINT dummy;
17204 char *valc = (char *) val;
17205
17206 if (stmt == SQL_NULL_HSTMT) {
17207 return SQL_INVALID_HANDLE;
17208 }
17209 s = (STMT *) stmt;
17210 if (!s->cols) {
17211 return SQL_ERROR;
17212 }
17213 if (!valLen) {
17214 valLen = &dummy;
17215 }
17216 if (id == SQL_COLUMN_COUNT) {
17217 if (val2) {
17218 *val2 = s->ncols;
17219 }
17220 *valLen = sizeof (int);
17221 return SQL_SUCCESS;
17222 }
17223 if (id == SQL_COLUMN_TYPE && col == 0) {
17224 if (val2) {
17225 *val2 = SQL_INTEGER;
17226 }
17227 *valLen = sizeof (int);
17228 return SQL_SUCCESS;
17229 }
17230 #ifdef SQL_DESC_OCTET_LENGTH
17231 if (id == SQL_DESC_OCTET_LENGTH && col == 0) {
17232 if (val2) {
17233 *val2 = 4;
17234 }
17235 *valLen = sizeof (int);
17236 return SQL_SUCCESS;
17237 }
17238 #endif
17239 if (col < 1 || col > s->ncols) {
17240 setstat(s, -1, "invalid column", (*s->ov3) ? "07009": "S1002");
17241 return SQL_ERROR;
17242 }
17243 c = s->cols + col - 1;
17244
17245 switch (id) {
17246 case SQL_COLUMN_LABEL:
17247 if (c->label) {
17248 if (valc && valMax > 0) {
17249 strncpy(valc, c->label, valMax);
17250 valc[valMax - 1] = '\0';
17251 }
17252 *valLen = strlen(c->label);
17253 goto checkLen;
17254 }
17255 /* fall through */
17256 case SQL_COLUMN_NAME:
17257 case SQL_DESC_NAME:
17258 if (valc && valMax > 0) {
17259 strncpy(valc, c->column, valMax);
17260 valc[valMax - 1] = '\0';
17261 }
17262 *valLen = strlen(c->column);
17263 checkLen:
17264 if (*valLen >= valMax) {
17265 setstat(s, -1, "data right truncated", "01004");
17266 return SQL_SUCCESS_WITH_INFO;
17267 }
17268 return SQL_SUCCESS;
17269 #ifdef SQL_DESC_BASE_COLUMN_NAME
17270 case SQL_DESC_BASE_COLUMN_NAME:
17271 if (strchr(c->column, '(') || strchr(c->column, ')')) {
17272 if (valc && valMax > 0) {
17273 valc[0] = '\0';
17274 }
17275 *valLen = 0;
17276 } else if (valc && valMax > 0) {
17277 strncpy(valc, c->column, valMax);
17278 valc[valMax - 1] = '\0';
17279 *valLen = strlen(c->column);
17280 }
17281 goto checkLen;
17282 #endif
17283 case SQL_COLUMN_TYPE:
17284 case SQL_DESC_TYPE:
17285 #ifdef WINTERFACE
17286 {
17287 int type = c->type;
17288
17289 if (s->nowchar[0] || s->nowchar[1]) {
17290 switch (type) {
17291 case SQL_WCHAR:
17292 type = SQL_CHAR;
17293 break;
17294 case SQL_WVARCHAR:
17295 type = SQL_VARCHAR;
17296 break;
17297 #ifdef SQL_LONGVARCHAR
17298 case SQL_WLONGVARCHAR:
17299 type = SQL_LONGVARCHAR;
17300 break;
17301 }
17302 }
17303 if (val2) {
17304 *val2 = type;
17305 }
17306 #endif
17307 }
17308 #else
17309 if (val2) {
17310 *val2 = c->type;
17311 }
17312 #endif
17313 *valLen = sizeof (int);
17314 return SQL_SUCCESS;
17315 case SQL_COLUMN_DISPLAY_SIZE:
17316 if (val2) {
17317 *val2 = c->size;
17318 }
17319 *valLen = sizeof (int);
17320 return SQL_SUCCESS;
17321 case SQL_COLUMN_UNSIGNED:
17322 if (val2) {
17323 *val2 = c->nosign ? SQL_TRUE : SQL_FALSE;
17324 }
17325 *valLen = sizeof (int);
17326 return SQL_SUCCESS;
17327 case SQL_COLUMN_SCALE:
17328 case SQL_DESC_SCALE:
17329 if (val2) {
17330 *val2 = c->scale;
17331 }
17332 *valLen = sizeof (int);
17333 return SQL_SUCCESS;
17334 case SQL_COLUMN_PRECISION:
17335 case SQL_DESC_PRECISION:
17336 if (val2) {
17337 switch (c->type) {
17338 case SQL_SMALLINT:
17339 *val2 = 5;
17340 break;
17341 case SQL_INTEGER:
17342 *val2 = 10;
17343 break;
17344 case SQL_FLOAT:
17345 case SQL_REAL:
17346 case SQL_DOUBLE:
17347 *val2 = 15;
17348 break;
17349 case SQL_DATE:
17350 *val2 = 0;
17351 break;
17352 case SQL_TIME:
17353 *val2 = 0;
17354 break;
17355 #ifdef SQL_TYPE_TIMESTAMP
17356 case SQL_TYPE_TIMESTAMP:
17357 #endif
17358 case SQL_TIMESTAMP:
17359 *val2 = (c->prec >= 0 && c->prec <= 3) ? c->prec : 3;
17360 break;
17361 default:
17362 *val2 = c->prec;
17363 break;
17364 }
17365 }
17366 *valLen = sizeof (int);
17367 return SQL_SUCCESS;
17368 case SQL_COLUMN_MONEY:
17369 if (val2) {
17370 *val2 = SQL_FALSE;
17371 }
17372 *valLen = sizeof (int);
17373 return SQL_SUCCESS;
17374 case SQL_COLUMN_AUTO_INCREMENT:
17375 if (val2) {
17376 *val2 = c->autoinc;
17377 }
17378 *valLen = sizeof (int);
17379 return SQL_SUCCESS;
17380 case SQL_COLUMN_LENGTH:
17381 case SQL_DESC_LENGTH:
17382 if (val2) {
17383 *val2 = c->size;
17384 }
17385 *valLen = sizeof (int);
17386 return SQL_SUCCESS;
17387 case SQL_COLUMN_NULLABLE:
17388 case SQL_DESC_NULLABLE:
17389 if (val2) {
17390 *val2 = c->notnull;
17391 }
17392 *valLen = sizeof (int);
17393 return SQL_SUCCESS;
17394 case SQL_COLUMN_SEARCHABLE:
17395 if (val2) {
17396 *val2 = SQL_SEARCHABLE;
17397 }
17398 *valLen = sizeof (int);
17399 return SQL_SUCCESS;
17400 case SQL_COLUMN_CASE_SENSITIVE:
17401 if (val2) {
17402 *val2 = SQL_TRUE;
17403 }
17404 *valLen = sizeof (int);
17405 return SQL_SUCCESS;
17406 case SQL_COLUMN_UPDATABLE:
17407 if (val2) {
17408 *val2 = SQL_TRUE;
17409 }
17410 *valLen = sizeof (int);
17411 return SQL_SUCCESS;
17412 case SQL_DESC_COUNT:
17413 if (val2) {
17414 *val2 = s->ncols;
17415 }
17416 *valLen = sizeof (int);
17417 return SQL_SUCCESS;
17418 case SQL_COLUMN_TYPE_NAME: {
17419 char *p = NULL, *tn = c->typename ? c->typename : "varchar";
17420
17421 #ifdef WINTERFACE
17422 if (c->type == SQL_WCHAR ||
17423 c->type == SQL_WVARCHAR ||
17424 c->type == SQL_WLONGVARCHAR) {
17425 if (!(s->nowchar[0] || s->nowchar[1])) {
17426 if (strcasecmp(tn, "varchar") == 0) {
17427 tn = "wvarchar";
17428 }
17429 }
17430 }
17431 #endif
17432 if (valc && valMax > 0) {
17433 strncpy(valc, tn, valMax);
17434 valc[valMax - 1] = '\0';
17435 p = strchr(valc, '(');
17436 if (p) {
17437 *p = '\0';
17438 while (p > valc && ISSPACE(p[-1])) {
17439 --p;
17440 *p = '\0';
17441 }
17442 }
17443 *valLen = strlen(valc);
17444 } else {
17445 *valLen = strlen(tn);
17446 p = strchr(tn, '(');
17447 if (p) {
17448 *valLen = p - tn;
17449 while (p > tn && ISSPACE(p[-1])) {
17450 --p;
17451 *valLen -= 1;
17452 }
17453 }
17454 }
17455 goto checkLen;
17456 }
17457 case SQL_COLUMN_OWNER_NAME:
17458 case SQL_COLUMN_QUALIFIER_NAME: {
17459 char *z = "";
17460
17461 if (valc && valMax > 0) {
17462 strncpy(valc, z, valMax);
17463 valc[valMax - 1] = '\0';
17464 }
17465 *valLen = strlen(z);
17466 goto checkLen;
17467 }
17468 case SQL_COLUMN_TABLE_NAME:
17469 #if (SQL_COLUMN_TABLE_NAME != SQL_DESC_TABLE_NAME)
17470 case SQL_DESC_TABLE_NAME:
17471 #endif
17472 #ifdef SQL_DESC_BASE_TABLE_NAME
17473 case SQL_DESC_BASE_TABLE_NAME:
17474 #endif
17475 if (valc && valMax > 0) {
17476 strncpy(valc, c->table, valMax);
17477 valc[valMax - 1] = '\0';
17478 }
17479 *valLen = strlen(c->table);
17480 goto checkLen;
17481 #ifdef SQL_DESC_NUM_PREC_RADIX
17482 case SQL_DESC_NUM_PREC_RADIX:
17483 if (val2) {
17484 switch (c->type) {
17485 #ifdef WINTERFACE
17486 case SQL_WCHAR:
17487 case SQL_WVARCHAR:
17488 #ifdef SQL_LONGVARCHAR
17489 case SQL_WLONGVARCHAR:
17490 #endif
17491 #endif
17492 case SQL_CHAR:
17493 case SQL_VARCHAR:
17494 #ifdef SQL_LONGVARCHAR
17495 case SQL_LONGVARCHAR:
17496 #endif
17497 case SQL_BINARY:
17498 case SQL_VARBINARY:
17499 case SQL_LONGVARBINARY:
17500 *val2 = 0;
17501 break;
17502 default:
17503 *val2 = 2;
17504 }
17505 }
17506 *valLen = sizeof (int);
17507 return SQL_SUCCESS;
17508 #endif
17509 }
17510 setstat(s, -1, "unsupported column attributes %d", "HY091", id);
17511 return SQL_ERROR;
17512 }
17513
17514 #ifndef WINTERFACE
17515 /**
17516 * Retrieve column attributes.
17517 * @param stmt statement handle
17518 * @param col column number, starting at 1
17519 * @param id attribute id
17520 * @param val output buffer
17521 * @param valMax length of output buffer
17522 * @param valLen output length
17523 * @param val2 integer output buffer
17524 * @result ODBC error code
17525 */
17526
17527 SQLRETURN SQL_API
SQLColAttributes(SQLHSTMT stmt,SQLUSMALLINT col,SQLUSMALLINT id,SQLPOINTER val,SQLSMALLINT valMax,SQLSMALLINT * valLen,SQLLEN * val2)17528 SQLColAttributes(SQLHSTMT stmt, SQLUSMALLINT col, SQLUSMALLINT id,
17529 SQLPOINTER val, SQLSMALLINT valMax, SQLSMALLINT *valLen,
17530 SQLLEN *val2)
17531 {
17532 #if defined(_WIN32) || defined(_WIN64)
17533 SQLSMALLINT len = 0;
17534 #endif
17535 SQLRETURN ret;
17536
17537 HSTMT_LOCK(stmt);
17538 #if defined(_WIN32) || defined(_WIN64)
17539 if (!((STMT *) stmt)->oemcp[0]) {
17540 ret = drvcolattributes(stmt, col, id, val, valMax, valLen, val2);
17541 goto done;
17542 }
17543 ret = drvcolattributes(stmt, col, id, val, valMax, &len, val2);
17544 if (SQL_SUCCEEDED(ret)) {
17545 char *v = NULL;
17546
17547 switch (id) {
17548 case SQL_COLUMN_LABEL:
17549 case SQL_COLUMN_NAME:
17550 case SQL_DESC_NAME:
17551 case SQL_COLUMN_TYPE_NAME:
17552 case SQL_COLUMN_OWNER_NAME:
17553 case SQL_COLUMN_QUALIFIER_NAME:
17554 case SQL_COLUMN_TABLE_NAME:
17555 #if (SQL_COLUMN_TABLE_NAME != SQL_DESC_TABLE_NAME)
17556 case SQL_DESC_TABLE_NAME:
17557 #endif
17558 #ifdef SQL_DESC_BASE_COLUMN_NAME
17559 case SQL_DESC_BASE_COLUMN_NAME:
17560 #endif
17561 #ifdef SQL_DESC_BASE_TABLE_NAME
17562 case SQL_DESC_BASE_TABLE_NAME:
17563 #endif
17564 if (val && valMax > 0) {
17565 int vmax = valMax;
17566
17567 v = utf_to_wmb((char *) val, SQL_NTS);
17568 if (v) {
17569 strncpy(val, v, vmax);
17570 len = min(vmax, strlen(v));
17571 uc_free(v);
17572 }
17573 if (vmax > 0) {
17574 v = (char *) val;
17575 v[vmax - 1] = '\0';
17576 }
17577 }
17578 if (len <= 0) {
17579 len = 0;
17580 }
17581 break;
17582 }
17583 if (valLen) {
17584 *valLen = len;
17585 }
17586 }
17587 done:
17588 ;
17589 #else
17590 ret = drvcolattributes(stmt, col, id, val, valMax, valLen, val2);
17591 #endif
17592 HSTMT_UNLOCK(stmt);
17593 return ret;
17594 }
17595 #endif
17596
17597 #ifdef WINTERFACE
17598 /**
17599 * Retrieve column attributes (UNICODE version).
17600 * @param stmt statement handle
17601 * @param col column number, starting at 1
17602 * @param id attribute id
17603 * @param val output buffer
17604 * @param valMax length of output buffer
17605 * @param valLen output length
17606 * @param val2 integer output buffer
17607 * @result ODBC error code
17608 */
17609
17610 SQLRETURN SQL_API
SQLColAttributesW(SQLHSTMT stmt,SQLUSMALLINT col,SQLUSMALLINT id,SQLPOINTER val,SQLSMALLINT valMax,SQLSMALLINT * valLen,SQLLEN * val2)17611 SQLColAttributesW(SQLHSTMT stmt, SQLUSMALLINT col, SQLUSMALLINT id,
17612 SQLPOINTER val, SQLSMALLINT valMax, SQLSMALLINT *valLen,
17613 SQLLEN *val2)
17614 {
17615 SQLRETURN ret;
17616 SQLSMALLINT len = 0;
17617
17618 HSTMT_LOCK(stmt);
17619 ret = drvcolattributes(stmt, col, id, val, valMax, &len, val2);
17620 if (SQL_SUCCEEDED(ret)) {
17621 SQLWCHAR *v = NULL;
17622
17623 switch (id) {
17624 case SQL_COLUMN_LABEL:
17625 case SQL_COLUMN_NAME:
17626 case SQL_DESC_NAME:
17627 case SQL_COLUMN_TYPE_NAME:
17628 case SQL_COLUMN_OWNER_NAME:
17629 case SQL_COLUMN_QUALIFIER_NAME:
17630 case SQL_COLUMN_TABLE_NAME:
17631 #if (SQL_COLUMN_TABLE_NAME != SQL_DESC_TABLE_NAME)
17632 case SQL_DESC_TABLE_NAME:
17633 #endif
17634 #ifdef SQL_DESC_BASE_COLUMN_NAME
17635 case SQL_DESC_BASE_COLUMN_NAME:
17636 #endif
17637 #ifdef SQL_DESC_BASE_TABLE_NAME
17638 case SQL_DESC_BASE_TABLE_NAME:
17639 #endif
17640 if (val && valMax > 0) {
17641 int vmax = valMax / sizeof (SQLWCHAR);
17642
17643 v = uc_from_utf((SQLCHAR *) val, SQL_NTS);
17644 if (v) {
17645 uc_strncpy(val, v, vmax);
17646 len = min(vmax, uc_strlen(v));
17647 uc_free(v);
17648 len *= sizeof (SQLWCHAR);
17649 }
17650 if (vmax > 0) {
17651 v = (SQLWCHAR *) val;
17652 v[vmax - 1] = '\0';
17653 }
17654 }
17655 if (len <= 0) {
17656 len = 0;
17657 }
17658 break;
17659 }
17660 if (valLen) {
17661 *valLen = len;
17662 }
17663 }
17664 HSTMT_UNLOCK(stmt);
17665 return ret;
17666 }
17667 #endif
17668
17669 /**
17670 * Internal retrieve column attributes.
17671 * @param stmt statement handle
17672 * @param col column number, starting at 1
17673 * @param id attribute id
17674 * @param val output buffer
17675 * @param valMax length of output buffer
17676 * @param valLen output length
17677 * @param val2 integer output buffer
17678 * @result ODBC error code
17679 */
17680
17681 static SQLRETURN
drvcolattribute(SQLHSTMT stmt,SQLUSMALLINT col,SQLUSMALLINT id,SQLPOINTER val,SQLSMALLINT valMax,SQLSMALLINT * valLen,SQLPOINTER val2)17682 drvcolattribute(SQLHSTMT stmt, SQLUSMALLINT col, SQLUSMALLINT id,
17683 SQLPOINTER val, SQLSMALLINT valMax, SQLSMALLINT *valLen,
17684 SQLPOINTER val2)
17685 {
17686 STMT *s;
17687 COL *c;
17688 int v = 0;
17689 char *valc = (char *) val;
17690 SQLSMALLINT dummy;
17691
17692 if (stmt == SQL_NULL_HSTMT) {
17693 return SQL_INVALID_HANDLE;
17694 }
17695 s = (STMT *) stmt;
17696 if (!s->cols) {
17697 return SQL_ERROR;
17698 }
17699 if (col < 1 || col > s->ncols) {
17700 setstat(s, -1, "invalid column", (*s->ov3) ? "07009" : "S1002");
17701 return SQL_ERROR;
17702 }
17703 if (!valLen) {
17704 valLen = &dummy;
17705 }
17706 c = s->cols + col - 1;
17707 switch (id) {
17708 case SQL_DESC_COUNT:
17709 v = s->ncols;
17710 break;
17711 case SQL_DESC_CATALOG_NAME:
17712 if (valc && valMax > 0) {
17713 strncpy(valc, c->db, valMax);
17714 valc[valMax - 1] = '\0';
17715 }
17716 *valLen = strlen(c->db);
17717 checkLen:
17718 if (*valLen >= valMax) {
17719 setstat(s, -1, "data right truncated", "01004");
17720 return SQL_SUCCESS_WITH_INFO;
17721 }
17722 break;
17723 case SQL_COLUMN_LENGTH:
17724 case SQL_DESC_LENGTH:
17725 v = c->size;
17726 break;
17727 case SQL_COLUMN_LABEL:
17728 if (c->label) {
17729 if (valc && valMax > 0) {
17730 strncpy(valc, c->label, valMax);
17731 valc[valMax - 1] = '\0';
17732 }
17733 *valLen = strlen(c->label);
17734 goto checkLen;
17735 }
17736 /* fall through */
17737 case SQL_COLUMN_NAME:
17738 case SQL_DESC_NAME:
17739 if (valc && valMax > 0) {
17740 strncpy(valc, c->column, valMax);
17741 valc[valMax - 1] = '\0';
17742 }
17743 *valLen = strlen(c->column);
17744 goto checkLen;
17745 case SQL_DESC_SCHEMA_NAME: {
17746 char *z = "";
17747
17748 if (valc && valMax > 0) {
17749 strncpy(valc, z, valMax);
17750 valc[valMax - 1] = '\0';
17751 }
17752 *valLen = strlen(z);
17753 goto checkLen;
17754 }
17755 #ifdef SQL_DESC_BASE_COLUMN_NAME
17756 case SQL_DESC_BASE_COLUMN_NAME:
17757 if (strchr(c->column, '(') || strchr(c->column, ')')) {
17758 valc[0] = '\0';
17759 *valLen = 0;
17760 } else if (valc && valMax > 0) {
17761 strncpy(valc, c->column, valMax);
17762 valc[valMax - 1] = '\0';
17763 *valLen = strlen(c->column);
17764 }
17765 goto checkLen;
17766 #endif
17767 case SQL_DESC_TYPE_NAME: {
17768 char *p = NULL, *tn = c->typename ? c->typename : "varchar";
17769
17770 #ifdef WINTERFACE
17771 if (c->type == SQL_WCHAR ||
17772 c->type == SQL_WVARCHAR ||
17773 c->type == SQL_WLONGVARCHAR) {
17774 if (!(s->nowchar[0] || s->nowchar[1])) {
17775 if (strcasecmp(tn, "varchar") == 0) {
17776 tn = "wvarchar";
17777 }
17778 }
17779 }
17780 #endif
17781 if (valc && valMax > 0) {
17782 strncpy(valc, tn, valMax);
17783 valc[valMax - 1] = '\0';
17784 p = strchr(valc, '(');
17785 if (p) {
17786 *p = '\0';
17787 while (p > valc && ISSPACE(p[-1])) {
17788 --p;
17789 *p = '\0';
17790 }
17791 }
17792 *valLen = strlen(valc);
17793 } else {
17794 *valLen = strlen(tn);
17795 p = strchr(tn, '(');
17796 if (p) {
17797 *valLen = p - tn;
17798 while (p > tn && ISSPACE(p[-1])) {
17799 --p;
17800 *valLen -= 1;
17801 }
17802 }
17803 }
17804 goto checkLen;
17805 }
17806 case SQL_DESC_OCTET_LENGTH:
17807 v = c->size;
17808 #ifdef WINTERFACE
17809 if (c->type == SQL_WCHAR ||
17810 c->type == SQL_WVARCHAR ||
17811 c->type == SQL_WLONGVARCHAR) {
17812 if (!(s->nowchar[0] || s->nowchar[1])) {
17813 v *= sizeof (SQLWCHAR);
17814 }
17815 }
17816 #endif
17817 break;
17818 #if (SQL_COLUMN_TABLE_NAME != SQL_DESC_TABLE_NAME)
17819 case SQL_COLUMN_TABLE_NAME:
17820 #endif
17821 #ifdef SQL_DESC_BASE_TABLE_NAME
17822 case SQL_DESC_BASE_TABLE_NAME:
17823 #endif
17824 case SQL_DESC_TABLE_NAME:
17825 if (valc && valMax > 0) {
17826 strncpy(valc, c->table, valMax);
17827 valc[valMax - 1] = '\0';
17828 }
17829 *valLen = strlen(c->table);
17830 goto checkLen;
17831 case SQL_DESC_TYPE:
17832 v = c->type;
17833 #ifdef WINTERFACE
17834 if (s->nowchar[0] || s->nowchar[1]) {
17835 switch (v) {
17836 case SQL_WCHAR:
17837 v = SQL_CHAR;
17838 break;
17839 case SQL_WVARCHAR:
17840 v = SQL_VARCHAR;
17841 break;
17842 #ifdef SQL_LONGVARCHAR
17843 case SQL_WLONGVARCHAR:
17844 v = SQL_LONGVARCHAR;
17845 break;
17846 #endif
17847 }
17848 }
17849 #endif
17850 break;
17851 case SQL_DESC_CONCISE_TYPE:
17852 switch (c->type) {
17853 case SQL_INTEGER:
17854 v = SQL_C_LONG;
17855 break;
17856 case SQL_TINYINT:
17857 v = SQL_C_TINYINT;
17858 break;
17859 case SQL_SMALLINT:
17860 v = SQL_C_SHORT;
17861 break;
17862 case SQL_FLOAT:
17863 v = SQL_C_FLOAT;
17864 break;
17865 case SQL_DOUBLE:
17866 v = SQL_C_DOUBLE;
17867 break;
17868 case SQL_TIMESTAMP:
17869 v = SQL_C_TIMESTAMP;
17870 break;
17871 case SQL_TIME:
17872 v = SQL_C_TIME;
17873 break;
17874 case SQL_DATE:
17875 v = SQL_C_DATE;
17876 break;
17877 #ifdef SQL_C_TYPE_TIMESTAMP
17878 case SQL_TYPE_TIMESTAMP:
17879 v = SQL_C_TYPE_TIMESTAMP;
17880 break;
17881 #endif
17882 #ifdef SQL_C_TYPE_TIME
17883 case SQL_TYPE_TIME:
17884 v = SQL_C_TYPE_TIME;
17885 break;
17886 #endif
17887 #ifdef SQL_C_TYPE_DATE
17888 case SQL_TYPE_DATE:
17889 v = SQL_C_TYPE_DATE;
17890 break;
17891 #endif
17892 #ifdef SQL_BIT
17893 case SQL_BIT:
17894 v = SQL_C_BIT;
17895 break;
17896 #endif
17897 #ifdef SQL_BIGINT
17898 case SQL_BIGINT:
17899 v = SQL_C_SBIGINT;
17900 break;
17901 #endif
17902 default:
17903 #ifdef WINTERFACE
17904 v = (s->nowchar[0] || s->nowchar[1]) ? SQL_C_CHAR : SQL_C_WCHAR;
17905 #else
17906 v = SQL_C_CHAR;
17907 #endif
17908 break;
17909 }
17910 break;
17911 case SQL_DESC_UPDATABLE:
17912 v = SQL_TRUE;
17913 break;
17914 case SQL_COLUMN_DISPLAY_SIZE:
17915 v = c->size;
17916 break;
17917 case SQL_COLUMN_UNSIGNED:
17918 v = c->nosign ? SQL_TRUE : SQL_FALSE;
17919 break;
17920 case SQL_COLUMN_SEARCHABLE:
17921 v = SQL_SEARCHABLE;
17922 break;
17923 case SQL_COLUMN_SCALE:
17924 case SQL_DESC_SCALE:
17925 v = c->scale;
17926 break;
17927 case SQL_COLUMN_PRECISION:
17928 case SQL_DESC_PRECISION:
17929 switch (c->type) {
17930 case SQL_SMALLINT:
17931 v = 5;
17932 break;
17933 case SQL_INTEGER:
17934 v = 10;
17935 break;
17936 case SQL_FLOAT:
17937 case SQL_REAL:
17938 case SQL_DOUBLE:
17939 v = 15;
17940 break;
17941 case SQL_DATE:
17942 v = 0;
17943 break;
17944 case SQL_TIME:
17945 v = 0;
17946 break;
17947 #ifdef SQL_TYPE_TIMESTAMP
17948 case SQL_TYPE_TIMESTAMP:
17949 #endif
17950 case SQL_TIMESTAMP:
17951 v = (c->prec >= 0 && c->prec <= 3) ? c->prec : 3;
17952 break;
17953 default:
17954 v = c->prec;
17955 break;
17956 }
17957 break;
17958 case SQL_COLUMN_MONEY:
17959 v = SQL_FALSE;
17960 break;
17961 case SQL_COLUMN_AUTO_INCREMENT:
17962 v = c->autoinc;
17963 break;
17964 case SQL_DESC_NULLABLE:
17965 v = c->notnull;
17966 break;
17967 #ifdef SQL_DESC_NUM_PREC_RADIX
17968 case SQL_DESC_NUM_PREC_RADIX:
17969 switch (c->type) {
17970 #ifdef WINTERFACE
17971 case SQL_WCHAR:
17972 case SQL_WVARCHAR:
17973 #ifdef SQL_LONGVARCHAR
17974 case SQL_WLONGVARCHAR:
17975 #endif
17976 #endif
17977 case SQL_CHAR:
17978 case SQL_VARCHAR:
17979 #ifdef SQL_LONGVARCHAR
17980 case SQL_LONGVARCHAR:
17981 #endif
17982 case SQL_BINARY:
17983 case SQL_VARBINARY:
17984 case SQL_LONGVARBINARY:
17985 v = 0;
17986 break;
17987 default:
17988 v = 2;
17989 }
17990 break;
17991 #endif
17992 default:
17993 setstat(s, -1, "unsupported column attribute %d", "HY091", id);
17994 return SQL_ERROR;
17995 }
17996 if (val2) {
17997 *(SQLLEN *) val2 = v;
17998 }
17999 return SQL_SUCCESS;
18000 }
18001
18002 #ifndef WINTERFACE
18003 /**
18004 * Retrieve column attributes.
18005 * @param stmt statement handle
18006 * @param col column number, starting at 1
18007 * @param id attribute id
18008 * @param val output buffer
18009 * @param valMax length of output buffer
18010 * @param valLen output length
18011 * @param val2 integer output buffer
18012 * @result ODBC error code
18013 */
18014
18015 SQLRETURN SQL_API
SQLColAttribute(SQLHSTMT stmt,SQLUSMALLINT col,SQLUSMALLINT id,SQLPOINTER val,SQLSMALLINT valMax,SQLSMALLINT * valLen,COLATTRIBUTE_LAST_ARG_TYPE val2)18016 SQLColAttribute(SQLHSTMT stmt, SQLUSMALLINT col, SQLUSMALLINT id,
18017 SQLPOINTER val, SQLSMALLINT valMax, SQLSMALLINT *valLen,
18018 COLATTRIBUTE_LAST_ARG_TYPE val2)
18019 {
18020 #if defined(_WIN32) || defined(_WIN64)
18021 SQLSMALLINT len = 0;
18022 #endif
18023 SQLRETURN ret;
18024
18025 HSTMT_LOCK(stmt);
18026 #if defined(_WIN32) || defined(_WIN64)
18027 if (!((STMT *) stmt)->oemcp[0]) {
18028 ret = drvcolattribute(stmt, col, id, val, valMax, valLen,
18029 (SQLPOINTER) val2);
18030 goto done;
18031 }
18032 ret = drvcolattribute(stmt, col, id, val, valMax, &len,
18033 (SQLPOINTER) val2);
18034 if (SQL_SUCCEEDED(ret)) {
18035 char *v = NULL;
18036
18037 switch (id) {
18038 case SQL_DESC_SCHEMA_NAME:
18039 case SQL_DESC_CATALOG_NAME:
18040 case SQL_COLUMN_LABEL:
18041 case SQL_DESC_NAME:
18042 case SQL_DESC_TABLE_NAME:
18043 #ifdef SQL_DESC_BASE_TABLE_NAME
18044 case SQL_DESC_BASE_TABLE_NAME:
18045 #endif
18046 #ifdef SQL_DESC_BASE_COLUMN_NAME
18047 case SQL_DESC_BASE_COLUMN_NAME:
18048 #endif
18049 case SQL_DESC_TYPE_NAME:
18050 if (val && valMax > 0) {
18051 int vmax = valMax;
18052
18053 v = utf_to_wmb((char *) val, SQL_NTS);
18054 if (v) {
18055 strncpy(val, v, vmax);
18056 len = min(vmax, strlen(v));
18057 uc_free(v);
18058 }
18059 if (vmax > 0) {
18060 v = (char *) val;
18061 v[vmax - 1] = '\0';
18062 }
18063 }
18064 if (len <= 0) {
18065 len = 0;
18066 }
18067 break;
18068 }
18069 if (valLen) {
18070 *valLen = len;
18071 }
18072 }
18073 done:
18074 ;
18075 #else
18076 ret = drvcolattribute(stmt, col, id, val, valMax, valLen,
18077 (SQLPOINTER) val2);
18078 #endif
18079 HSTMT_UNLOCK(stmt);
18080 return ret;
18081 }
18082 #endif
18083
18084 #ifdef WINTERFACE
18085 /**
18086 * Retrieve column attributes (UNICODE version).
18087 * @param stmt statement handle
18088 * @param col column number, starting at 1
18089 * @param id attribute id
18090 * @param val output buffer
18091 * @param valMax length of output buffer
18092 * @param valLen output length
18093 * @param val2 integer output buffer
18094 * @result ODBC error code
18095 */
18096
18097 SQLRETURN SQL_API
SQLColAttributeW(SQLHSTMT stmt,SQLUSMALLINT col,SQLUSMALLINT id,SQLPOINTER val,SQLSMALLINT valMax,SQLSMALLINT * valLen,COLATTRIBUTE_LAST_ARG_TYPE val2)18098 SQLColAttributeW(SQLHSTMT stmt, SQLUSMALLINT col, SQLUSMALLINT id,
18099 SQLPOINTER val, SQLSMALLINT valMax, SQLSMALLINT *valLen,
18100 COLATTRIBUTE_LAST_ARG_TYPE val2)
18101 {
18102 SQLRETURN ret;
18103 SQLSMALLINT len = 0;
18104
18105 HSTMT_LOCK(stmt);
18106 ret = drvcolattribute(stmt, col, id, val, valMax, &len,
18107 (SQLPOINTER) val2);
18108 if (SQL_SUCCEEDED(ret)) {
18109 SQLWCHAR *v = NULL;
18110
18111 switch (id) {
18112 case SQL_DESC_SCHEMA_NAME:
18113 case SQL_DESC_CATALOG_NAME:
18114 case SQL_COLUMN_LABEL:
18115 case SQL_DESC_NAME:
18116 case SQL_DESC_TABLE_NAME:
18117 #ifdef SQL_DESC_BASE_TABLE_NAME
18118 case SQL_DESC_BASE_TABLE_NAME:
18119 #endif
18120 #ifdef SQL_DESC_BASE_COLUMN_NAME
18121 case SQL_DESC_BASE_COLUMN_NAME:
18122 #endif
18123 case SQL_DESC_TYPE_NAME:
18124 if (val && valMax > 0) {
18125 int vmax = valMax / sizeof (SQLWCHAR);
18126
18127 v = uc_from_utf((SQLCHAR *) val, SQL_NTS);
18128 if (v) {
18129 uc_strncpy(val, v, vmax);
18130 len = min(vmax, uc_strlen(v));
18131 uc_free(v);
18132 len *= sizeof (SQLWCHAR);
18133 }
18134 if (vmax > 0) {
18135 v = (SQLWCHAR *) val;
18136 v[vmax - 1] = '\0';
18137 }
18138 }
18139 if (len <= 0) {
18140 len = 0;
18141 }
18142 break;
18143 }
18144 if (valLen) {
18145 *valLen = len;
18146 }
18147 }
18148 HSTMT_UNLOCK(stmt);
18149 return ret;
18150 }
18151 #endif
18152
18153 /**
18154 * Internal return last HDBC or HSTMT error message.
18155 * @param env environment handle or NULL
18156 * @param dbc database connection handle or NULL
18157 * @param stmt statement handle or NULL
18158 * @param sqlState output buffer for SQL state
18159 * @param nativeErr output buffer for native error code
18160 * @param errmsg output buffer for error message
18161 * @param errmax length of output buffer for error message
18162 * @param errlen output length of error message
18163 * @result ODBC error code
18164 */
18165
18166 static SQLRETURN
drverror(SQLHENV env,SQLHDBC dbc,SQLHSTMT stmt,SQLCHAR * sqlState,SQLINTEGER * nativeErr,SQLCHAR * errmsg,SQLSMALLINT errmax,SQLSMALLINT * errlen)18167 drverror(SQLHENV env, SQLHDBC dbc, SQLHSTMT stmt,
18168 SQLCHAR *sqlState, SQLINTEGER *nativeErr,
18169 SQLCHAR *errmsg, SQLSMALLINT errmax, SQLSMALLINT *errlen)
18170 {
18171 SQLCHAR dummy0[6];
18172 SQLINTEGER dummy1;
18173 SQLSMALLINT dummy2;
18174
18175 if (env == SQL_NULL_HENV &&
18176 dbc == SQL_NULL_HDBC &&
18177 stmt == SQL_NULL_HSTMT) {
18178 return SQL_INVALID_HANDLE;
18179 }
18180 if (sqlState) {
18181 sqlState[0] = '\0';
18182 } else {
18183 sqlState = dummy0;
18184 }
18185 if (!nativeErr) {
18186 nativeErr = &dummy1;
18187 }
18188 *nativeErr = 0;
18189 if (!errlen) {
18190 errlen = &dummy2;
18191 }
18192 *errlen = 0;
18193 if (errmsg) {
18194 if (errmax > 0) {
18195 errmsg[0] = '\0';
18196 }
18197 } else {
18198 errmsg = dummy0;
18199 errmax = 0;
18200 }
18201 if (stmt) {
18202 STMT *s = (STMT *) stmt;
18203
18204 HSTMT_LOCK(stmt);
18205 if (s->logmsg[0] == '\0') {
18206 HSTMT_UNLOCK(stmt);
18207 goto noerr;
18208 }
18209 *nativeErr = s->naterr;
18210 strcpy((char *) sqlState, s->sqlstate);
18211 if (errmax == SQL_NTS) {
18212 strcpy((char *) errmsg, "[SQLite]");
18213 strcat((char *) errmsg, (char *) s->logmsg);
18214 *errlen = strlen((char *) errmsg);
18215 } else {
18216 strncpy((char *) errmsg, "[SQLite]", errmax);
18217 if (errmax - 8 > 0) {
18218 strncpy((char *) errmsg + 8, (char *) s->logmsg, errmax - 8);
18219 }
18220 *errlen = min(strlen((char *) s->logmsg) + 8, errmax);
18221 }
18222 s->logmsg[0] = '\0';
18223 HSTMT_UNLOCK(stmt);
18224 return SQL_SUCCESS;
18225 }
18226 if (dbc) {
18227 DBC *d = (DBC *) dbc;
18228
18229 HDBC_LOCK(dbc);
18230 if (d->magic != DBC_MAGIC || d->logmsg[0] == '\0') {
18231 HDBC_UNLOCK(dbc);
18232 goto noerr;
18233 }
18234 *nativeErr = d->naterr;
18235 strcpy((char *) sqlState, d->sqlstate);
18236 if (errmax == SQL_NTS) {
18237 strcpy((char *) errmsg, "[SQLite]");
18238 strcat((char *) errmsg, (char *) d->logmsg);
18239 *errlen = strlen((char *) errmsg);
18240 } else {
18241 strncpy((char *) errmsg, "[SQLite]", errmax);
18242 if (errmax - 8 > 0) {
18243 strncpy((char *) errmsg + 8, (char *) d->logmsg, errmax - 8);
18244 }
18245 *errlen = min(strlen((char *) d->logmsg) + 8, errmax);
18246 }
18247 d->logmsg[0] = '\0';
18248 HDBC_UNLOCK(dbc);
18249 return SQL_SUCCESS;
18250 }
18251 noerr:
18252 sqlState[0] = '\0';
18253 errmsg[0] = '\0';
18254 *nativeErr = 0;
18255 *errlen = 0;
18256 return SQL_NO_DATA;
18257 }
18258
18259 #ifndef WINTERFACE
18260 /**
18261 * Return last HDBC or HSTMT error message.
18262 * @param env environment handle or NULL
18263 * @param dbc database connection handle or NULL
18264 * @param stmt statement handle or NULL
18265 * @param sqlState output buffer for SQL state
18266 * @param nativeErr output buffer for native error code
18267 * @param errmsg output buffer for error message
18268 * @param errmax length of output buffer for error message
18269 * @param errlen output length of error message
18270 * @result ODBC error code
18271 */
18272
18273 SQLRETURN SQL_API
SQLError(SQLHENV env,SQLHDBC dbc,SQLHSTMT stmt,SQLCHAR * sqlState,SQLINTEGER * nativeErr,SQLCHAR * errmsg,SQLSMALLINT errmax,SQLSMALLINT * errlen)18274 SQLError(SQLHENV env, SQLHDBC dbc, SQLHSTMT stmt,
18275 SQLCHAR *sqlState, SQLINTEGER *nativeErr,
18276 SQLCHAR *errmsg, SQLSMALLINT errmax, SQLSMALLINT *errlen)
18277 {
18278 return drverror(env, dbc, stmt, sqlState, nativeErr,
18279 errmsg, errmax, errlen);
18280 }
18281 #endif
18282
18283 #ifdef WINTERFACE
18284 /**
18285 * Return last HDBC or HSTMT error message (UNICODE version).
18286 * @param env environment handle or NULL
18287 * @param dbc database connection handle or NULL
18288 * @param stmt statement handle or NULL
18289 * @param sqlState output buffer for SQL state
18290 * @param nativeErr output buffer for native error code
18291 * @param errmsg output buffer for error message
18292 * @param errmax length of output buffer for error message
18293 * @param errlen output length of error message
18294 * @result ODBC error code
18295 */
18296
18297 SQLRETURN SQL_API
SQLErrorW(SQLHENV env,SQLHDBC dbc,SQLHSTMT stmt,SQLWCHAR * sqlState,SQLINTEGER * nativeErr,SQLWCHAR * errmsg,SQLSMALLINT errmax,SQLSMALLINT * errlen)18298 SQLErrorW(SQLHENV env, SQLHDBC dbc, SQLHSTMT stmt,
18299 SQLWCHAR *sqlState, SQLINTEGER *nativeErr,
18300 SQLWCHAR *errmsg, SQLSMALLINT errmax, SQLSMALLINT *errlen)
18301 {
18302 char state[16];
18303 SQLSMALLINT len = 0;
18304 SQLRETURN ret;
18305
18306 ret = drverror(env, dbc, stmt, (SQLCHAR *) state, nativeErr,
18307 (SQLCHAR *) errmsg, errmax, &len);
18308 if (ret == SQL_SUCCESS) {
18309 if (sqlState) {
18310 uc_from_utf_buf((SQLCHAR *) state, -1, sqlState,
18311 6 * sizeof (SQLWCHAR));
18312 }
18313 if (errmsg) {
18314 if (len > 0) {
18315 SQLWCHAR *e = NULL;
18316
18317 e = uc_from_utf((SQLCHAR *) errmsg, len);
18318 if (e) {
18319 if (errmax > 0) {
18320 uc_strncpy(errmsg, e, errmax);
18321 e[len] = 0;
18322 len = min(errmax, uc_strlen(e));
18323 } else {
18324 len = uc_strlen(e);
18325 }
18326 uc_free(e);
18327 } else {
18328 len = 0;
18329 }
18330 }
18331 if (len <= 0) {
18332 len = 0;
18333 if (errmax > 0) {
18334 errmsg[0] = 0;
18335 }
18336 }
18337 } else {
18338 len = 0;
18339 }
18340 if (errlen) {
18341 *errlen = len;
18342 }
18343 } else if (ret == SQL_NO_DATA) {
18344 if (sqlState) {
18345 sqlState[0] = 0;
18346 }
18347 if (errmsg) {
18348 if (errmax > 0) {
18349 errmsg[0] = 0;
18350 }
18351 }
18352 if (errlen) {
18353 *errlen = 0;
18354 }
18355 }
18356 return ret;
18357 }
18358 #endif
18359
18360 /**
18361 * Return information for more result sets.
18362 * @param stmt statement handle
18363 * @result ODBC error code
18364 */
18365
18366 SQLRETURN SQL_API
SQLMoreResults(SQLHSTMT stmt)18367 SQLMoreResults(SQLHSTMT stmt)
18368 {
18369 HSTMT_LOCK(stmt);
18370 if (stmt == SQL_NULL_HSTMT) {
18371 return SQL_INVALID_HANDLE;
18372 }
18373 HSTMT_UNLOCK(stmt);
18374 return SQL_NO_DATA;
18375 }
18376
18377 /**
18378 * Internal function to setup column name/type information
18379 * @param s statement poiner
18380 * @param s3stmt SQLite3 statement pointer
18381 * @param ncolsp pointer to preinitialized number of columns
18382 * @result ODBC error code
18383 */
18384
18385 static SQLRETURN
setupdyncols(STMT * s,sqlite3_stmt * s3stmt,int * ncolsp)18386 setupdyncols(STMT *s, sqlite3_stmt *s3stmt, int *ncolsp)
18387 {
18388 int ncols = *ncolsp, guessed_types = 0;
18389 SQLRETURN ret = SQL_SUCCESS;
18390
18391 if (ncols > 0) {
18392 int i;
18393 PTRDIFF_T size;
18394 char *p;
18395 COL *dyncols;
18396 DBC *d = (DBC *) s->dbc;
18397 const char *colname, *typename;
18398 #if defined(HAVE_SQLITE3COLUMNTABLENAME) && (HAVE_SQLITE3COLUMNTABLENAME)
18399 char *tblname;
18400 #endif
18401 #if defined(HAVE_SQLITE3COLUMNDATABASENAME) && (HAVE_SQLITE3COLUMNDATABASENAME)
18402 char *dbname;
18403 #endif
18404
18405 for (i = size = 0; i < ncols; i++) {
18406 colname = sqlite3_column_name(s3stmt, i);
18407 size += 3 + 3 * strlen(colname);
18408 }
18409 #if defined(HAVE_SQLITE3COLUMNTABLENAME) && (HAVE_SQLITE3COLUMNTABLENAME)
18410 tblname = (char *) size;
18411 for (i = 0; i < ncols; i++) {
18412 p = (char *) sqlite3_column_table_name(s3stmt, i);
18413 size += 2 + (p ? strlen(p) : 0);
18414 }
18415 #endif
18416 #if defined(HAVE_SQLITE3COLUMNDATABASENAME) && (HAVE_SQLITE3COLUMNDATABASENAME)
18417 dbname = (char *) size;
18418 for (i = 0; i < ncols; i++) {
18419 p = (char *) sqlite3_column_database_name(s3stmt, i);
18420 size += 2 + (p ? strlen(p) : 0);
18421 }
18422 #endif
18423 dyncols = xmalloc(ncols * sizeof (COL) + size);
18424 if (!dyncols) {
18425 freedyncols(s);
18426 *ncolsp = 0;
18427 ret = SQL_ERROR;
18428 } else {
18429 p = (char *) (dyncols + ncols);
18430 #if defined(HAVE_SQLITE3COLUMNTABLENAME) && (HAVE_SQLITE3COLUMNTABLENAME)
18431 tblname = p + (PTRDIFF_T) tblname;
18432 #endif
18433 #if defined(HAVE_SQLITE3COLUMNDATABASENAME) && (HAVE_SQLITE3COLUMNDATABASENAME)
18434 dbname = p + (PTRDIFF_T) dbname;
18435 #endif
18436 for (i = 0; i < ncols; i++) {
18437 char *q;
18438
18439 colname = sqlite3_column_name(s3stmt, i);
18440 if (d->trace) {
18441 fprintf(d->trace, "-- column %d name: '%s'\n",
18442 i + 1, colname);
18443 fflush(d->trace);
18444 }
18445 #if defined(HAVE_SQLITE3COLUMNTABLENAME) && (HAVE_SQLITE3COLUMNTABLENAME)
18446 q = (char *) sqlite3_column_table_name(s3stmt, i);
18447 strcpy(tblname, q ? q : "");
18448 if (d->trace) {
18449 fprintf(d->trace, "-- table %d name: '%s'\n",
18450 i + 1, tblname);
18451 fflush(d->trace);
18452 }
18453 dyncols[i].table = tblname;
18454 tblname += strlen(tblname) + 1;
18455 #endif
18456 #if defined(HAVE_SQLITE3COLUMNDATABASENAME) && (HAVE_SQLITE3COLUMNDATABASENAME)
18457 q = (char *) sqlite3_column_database_name(s3stmt, i);
18458 strcpy(dbname, q ? q : "");
18459 if (d->trace) {
18460 fprintf(d->trace, "-- database %d name: '%s'\n",
18461 i + 1, dbname);
18462 fflush(d->trace);
18463 }
18464 dyncols[i].db = dbname;
18465 dbname += strlen(dbname) + 1;
18466 #else
18467 dyncols[i].db = ((DBC *) (s->dbc))->dbname;
18468 #endif
18469 typename = s3stmt_coltype(s3stmt, i, d, &guessed_types);
18470 strcpy(p, colname);
18471 dyncols[i].label = p;
18472 p += strlen(p) + 1;
18473 q = strchr(colname, '.');
18474 if (q) {
18475 char *q2 = strchr(q + 1, '.');
18476
18477 /* SQLite 3.3.4 produces view.table.column sometimes */
18478 if (q2) {
18479 q = q2;
18480 }
18481 }
18482 if (q) {
18483 #if !defined(HAVE_SQLITE3COLUMNTABLENAME) || !(HAVE_SQLITE3COLUMNTABLENAME)
18484 dyncols[i].table = p;
18485 #endif
18486 strncpy(p, colname, q - colname);
18487 p[q - colname] = '\0';
18488 p += strlen(p) + 1;
18489 strcpy(p, q + 1);
18490 dyncols[i].column = p;
18491 p += strlen(p) + 1;
18492 } else {
18493 #if !defined(HAVE_SQLITE3COLUMNTABLENAME) || !(HAVE_SQLITE3COLUMNTABLENAME)
18494 dyncols[i].table = "";
18495 #endif
18496 strcpy(p, colname);
18497 dyncols[i].column = p;
18498 p += strlen(p) + 1;
18499 }
18500 if (s->longnames) {
18501 dyncols[i].column = dyncols[i].label;
18502 }
18503 #ifdef SQL_LONGVARCHAR
18504 dyncols[i].type = SQL_LONGVARCHAR;
18505 dyncols[i].size = 65535;
18506 #else
18507 dyncols[i].type = SQL_VARCHAR;
18508 dyncols[i].size = 255;
18509 #endif
18510 dyncols[i].index = i;
18511 dyncols[i].scale = 0;
18512 dyncols[i].prec = 0;
18513 dyncols[i].nosign = 1;
18514 dyncols[i].autoinc = SQL_FALSE;
18515 dyncols[i].notnull = SQL_NULLABLE;
18516 dyncols[i].ispk = -1;
18517 dyncols[i].isrowid = -1;
18518 #ifdef FULL_METADATA
18519 s3stmt_addmeta(s3stmt, i, d, &dyncols[i]);
18520 #endif
18521 dyncols[i].typename = xstrdup(typename);
18522 }
18523 freedyncols(s);
18524 s->dyncols = s->cols = dyncols;
18525 s->dcols = ncols;
18526 fixupdyncols(s, d);
18527 s->guessed_types = guessed_types;
18528 }
18529 }
18530 return ret;
18531 }
18532
18533 /**
18534 * Internal query preparation used by SQLPrepare() and SQLExecDirect().
18535 * @param stmt statement handle
18536 * @param query query string
18537 * @param queryLen length of query string or SQL_NTS
18538 * @result ODBC error code
18539 */
18540
18541 static SQLRETURN
drvprepare(SQLHSTMT stmt,SQLCHAR * query,SQLINTEGER queryLen)18542 drvprepare(SQLHSTMT stmt, SQLCHAR *query, SQLINTEGER queryLen)
18543 {
18544 STMT *s;
18545 DBC *d;
18546 char *errp = NULL;
18547 SQLRETURN sret;
18548
18549 if (stmt == SQL_NULL_HSTMT) {
18550 return SQL_INVALID_HANDLE;
18551 }
18552 s = (STMT *) stmt;
18553 if (s->dbc == SQL_NULL_HDBC) {
18554 noconn:
18555 return noconn(s);
18556 }
18557 d = s->dbc;
18558 if (!d->sqlite) {
18559 goto noconn;
18560 }
18561 s3stmt_end(s);
18562 s3stmt_drop(s);
18563 sret = starttran(s);
18564 if (sret != SQL_SUCCESS) {
18565 return sret;
18566 }
18567 freep(&s->query);
18568 s->query = (SQLCHAR *) fixupsql((char *) query, queryLen,
18569 (d->version >= 0x030805),
18570 &s->nparams, &s->isselect, &errp);
18571 if (!s->query) {
18572 if (errp) {
18573 setstat(s, -1, "%s", (*s->ov3) ? "HY000" : "S1000", errp);
18574 return SQL_ERROR;
18575 }
18576 return nomem(s);
18577 }
18578 errp = NULL;
18579 freeresult(s, -1);
18580 if (s->isselect == 1) {
18581 int ret, ncols, nretry = 0;
18582 const char *rest;
18583 sqlite3_stmt *s3stmt = NULL;
18584
18585 #if defined(HAVE_SQLITE3PREPAREV2) && (HAVE_SQLITE3PREPAREV2)
18586 dbtraceapi(d, "sqlite3_prepare_v2", (char *) s->query);
18587 #else
18588 dbtraceapi(d, "sqlite3_prepare", (char *) s->query);
18589 #endif
18590 do {
18591 s3stmt = NULL;
18592 #if defined(HAVE_SQLITE3PREPAREV2) && (HAVE_SQLITE3PREPAREV2)
18593 ret = sqlite3_prepare_v2(d->sqlite, (char *) s->query, -1,
18594 &s3stmt, &rest);
18595 #else
18596 ret = sqlite3_prepare(d->sqlite, (char *) s->query, -1,
18597 &s3stmt, &rest);
18598 #endif
18599 if (ret != SQLITE_OK) {
18600 if (s3stmt) {
18601 sqlite3_finalize(s3stmt);
18602 s3stmt = NULL;
18603 }
18604 }
18605 } while (ret == SQLITE_SCHEMA && (++nretry) < 2);
18606 dbtracerc(d, ret, NULL);
18607 if (ret != SQLITE_OK) {
18608 if (s3stmt) {
18609 dbtraceapi(d, "sqlite3_finalize", 0);
18610 sqlite3_finalize(s3stmt);
18611 }
18612 setstat(s, ret, "%s (%d)", (*s->ov3) ? "HY000" : "S1000",
18613 sqlite3_errmsg(d->sqlite), ret);
18614 return SQL_ERROR;
18615 }
18616 if (sqlite3_bind_parameter_count(s3stmt) != s->nparams) {
18617 dbtraceapi(d, "sqlite3_finalize", 0);
18618 sqlite3_finalize(s3stmt);
18619 setstat(s, SQLITE_ERROR, "parameter marker count incorrect",
18620 (*s->ov3) ? "HY000" : "S1000");
18621 return SQL_ERROR;
18622 }
18623 ncols = sqlite3_column_count(s3stmt);
18624 s->guessed_types = 0;
18625 setupdyncols(s, s3stmt, &ncols);
18626 s->ncols = ncols;
18627 s->s3stmt = s3stmt;
18628 }
18629 mkbindcols(s, s->ncols);
18630 s->paramset_count = 0;
18631 return SQL_SUCCESS;
18632 }
18633
18634 /**
18635 * Internal query execution used by SQLExecute() and SQLExecDirect().
18636 * @param stmt statement handle
18637 * @param initial false when called from SQLPutData()
18638 * @result ODBC error code
18639 */
18640
18641 static SQLRETURN
drvexecute(SQLHSTMT stmt,int initial)18642 drvexecute(SQLHSTMT stmt, int initial)
18643 {
18644 STMT *s;
18645 DBC *d;
18646 char *errp = NULL;
18647 int rc, i, ncols = 0, nrows = 0, busy_count;
18648 SQLRETURN ret;
18649
18650 if (stmt == SQL_NULL_HSTMT) {
18651 return SQL_INVALID_HANDLE;
18652 }
18653 s = (STMT *) stmt;
18654 if (s->dbc == SQL_NULL_HDBC) {
18655 noconn:
18656 return noconn(s);
18657 }
18658 d = (DBC *) s->dbc;
18659 if (!d->sqlite) {
18660 goto noconn;
18661 }
18662 if (!s->query) {
18663 setstat(s, -1, "no query prepared", (*s->ov3) ? "HY000" : "S1000");
18664 return SQL_ERROR;
18665 }
18666 if (s->nbindparms < s->nparams) {
18667 unbound:
18668 setstat(s, -1, "unbound parameters in query",
18669 (*s->ov3) ? "HY000" : "S1000");
18670 return SQL_ERROR;
18671 }
18672 for (i = 0; i < s->nparams; i++) {
18673 BINDPARM *p = &s->bindparms[i];
18674
18675 if (!p->bound) {
18676 goto unbound;
18677 }
18678 if (initial) {
18679 SQLLEN *lenp = p->lenp;
18680
18681 if (lenp && *lenp < 0 && *lenp > SQL_LEN_DATA_AT_EXEC_OFFSET &&
18682 *lenp != SQL_NTS && *lenp != SQL_NULL_DATA &&
18683 *lenp != SQL_DATA_AT_EXEC) {
18684 setstat(s, -1, "invalid length reference", "HY009");
18685 return SQL_ERROR;
18686 }
18687 if (lenp && (*lenp <= SQL_LEN_DATA_AT_EXEC_OFFSET ||
18688 *lenp == SQL_DATA_AT_EXEC)) {
18689 p->need = 1;
18690 p->offs = 0;
18691 p->len = 0;
18692 }
18693 }
18694 }
18695 ret = starttran(s);
18696 if (ret != SQL_SUCCESS) {
18697 goto cleanup;
18698 }
18699 busy_count = 0;
18700 again:
18701 s3stmt_end(s);
18702 if (initial) {
18703 /* fixup data-at-execution parameters and alloc'ed blobs */
18704 s->pdcount = -1;
18705 for (i = 0; i < s->nparams; i++) {
18706 BINDPARM *p = &s->bindparms[i];
18707
18708 if (p->param == p->parbuf) {
18709 p->param = NULL;
18710 }
18711 freep(&p->parbuf);
18712 if (p->need <= 0 &&
18713 p->lenp && (*p->lenp <= SQL_LEN_DATA_AT_EXEC_OFFSET ||
18714 *p->lenp == SQL_DATA_AT_EXEC)) {
18715 p->need = 1;
18716 p->offs = 0;
18717 p->len = 0;
18718 }
18719 }
18720 }
18721 if (s->nparams) {
18722 for (i = 0; i < s->nparams; i++) {
18723 ret = setupparam(s, (char *) s->query, i);
18724 if (ret != SQL_SUCCESS) {
18725 goto cleanup;
18726 }
18727 }
18728 }
18729 freeresult(s, 0);
18730 if (s->isselect == 1 && !d->intrans &&
18731 s->curtype == SQL_CURSOR_FORWARD_ONLY &&
18732 d->step_enable && s->nparams == 0 && d->cur_s3stmt == NULL) {
18733 s->nrows = -1;
18734 ret = s3stmt_start(s);
18735 if (ret == SQL_SUCCESS) {
18736 goto done2;
18737 }
18738 }
18739 rc = drvgettable(s, s->s3stmt ? NULL : (char *) s->query, &s->rows,
18740 &s->nrows, &ncols, &errp, s->nparams, s->bindparms);
18741 dbtracerc(d, rc, errp);
18742 if (rc == SQLITE_BUSY) {
18743 if (busy_handler((void *) d, ++busy_count)) {
18744 if (errp) {
18745 sqlite3_free(errp);
18746 errp = NULL;
18747 }
18748 for (i = 0; i < s->nparams; i++) {
18749 BINDPARM *p = &s->bindparms[i];
18750
18751 if (p->param == p->parbuf) {
18752 p->param = NULL;
18753 }
18754 freep(&p->parbuf);
18755 if (!p->lenp || (*p->lenp > SQL_LEN_DATA_AT_EXEC_OFFSET &&
18756 *p->lenp != SQL_DATA_AT_EXEC)) {
18757 p->param = p->param0;
18758 }
18759 p->lenp = p->lenp0;
18760 }
18761 s->nrows = 0;
18762 goto again;
18763 }
18764 }
18765 if (rc != SQLITE_OK) {
18766 setstat(s, rc, "%s (%d)", (*s->ov3) ? "HY000" : "S1000",
18767 errp ? errp : "unknown error", rc);
18768 if (errp) {
18769 sqlite3_free(errp);
18770 errp = NULL;
18771 }
18772 ret = SQL_ERROR;
18773 goto cleanup;
18774 }
18775 if (errp) {
18776 sqlite3_free(errp);
18777 errp = NULL;
18778 }
18779 s->rowfree = freerows;
18780 if (s->isselect <= 0 || s->isselect > 1) {
18781 /*
18782 * INSERT/UPDATE/DELETE or DDL results are immediately released.
18783 */
18784 freeresult(s, -1);
18785 nrows += sqlite3_changes(d->sqlite);
18786 s->nrows = nrows;
18787 goto done;
18788 }
18789 if (s->ncols != ncols) {
18790 /*
18791 * Weird result.
18792 */
18793 setstat(s, -1, "broken result set %d/%d",
18794 (*s->ov3) ? "HY000" : "S1000", s->ncols, ncols);
18795 ret = SQL_ERROR;
18796 goto cleanup;
18797 }
18798 done:
18799 mkbindcols(s, s->ncols);
18800 done2:
18801 ret = SQL_SUCCESS;
18802 s->rowp = s->rowprs = -1;
18803 s->paramset_count++;
18804 s->paramset_nrows = s->nrows;
18805 if (s->paramset_count < s->paramset_size) {
18806 for (i = 0; i < s->nparams; i++) {
18807 BINDPARM *p = &s->bindparms[i];
18808
18809 if (p->param == p->parbuf) {
18810 p->param = NULL;
18811 }
18812 freep(&p->parbuf);
18813 if (p->lenp0 &&
18814 s->parm_bind_type != SQL_PARAM_BIND_BY_COLUMN) {
18815 p->lenp = (SQLLEN *) ((char *) p->lenp0 +
18816 s->paramset_count * s->parm_bind_type);
18817 } else if (p->lenp0 && p->inc > 0) {
18818 p->lenp = p->lenp0 + s->paramset_count;
18819 }
18820 if (!p->lenp || (*p->lenp > SQL_LEN_DATA_AT_EXEC_OFFSET &&
18821 *p->lenp != SQL_DATA_AT_EXEC)) {
18822 if (p->param0 &&
18823 s->parm_bind_type != SQL_PARAM_BIND_BY_COLUMN) {
18824 p->param = (char *) p->param0 +
18825 s->paramset_count * s->parm_bind_type;
18826 } else if (p->param0 && p->inc > 0) {
18827 p->param = (char *) p->param0 +
18828 s->paramset_count * p->inc;
18829 }
18830 } else if (p->lenp && (*p->lenp <= SQL_LEN_DATA_AT_EXEC_OFFSET ||
18831 *p->lenp == SQL_DATA_AT_EXEC)) {
18832 p->need = 1;
18833 p->offs = 0;
18834 p->len = 0;
18835 }
18836 }
18837 goto again;
18838 }
18839 cleanup:
18840 if (ret != SQL_NEED_DATA) {
18841 for (i = 0; i < s->nparams; i++) {
18842 BINDPARM *p = &s->bindparms[i];
18843
18844 if (p->param == p->parbuf) {
18845 p->param = NULL;
18846 }
18847 freep(&p->parbuf);
18848 if (!p->lenp || (*p->lenp > SQL_LEN_DATA_AT_EXEC_OFFSET &&
18849 *p->lenp != SQL_DATA_AT_EXEC)) {
18850 p->param = p->param0;
18851 }
18852 p->lenp = p->lenp0;
18853 }
18854 s->nrows = s->paramset_nrows;
18855 if (s->parm_proc) {
18856 *s->parm_proc = s->paramset_count;
18857 }
18858 s->paramset_count = 0;
18859 s->paramset_nrows = 0;
18860 }
18861 /*
18862 * For INSERT/UPDATE/DELETE statements change the return code
18863 * to SQL_NO_DATA if the number of rows affected was 0.
18864 */
18865 if (*s->ov3 && s->isselect == 0 &&
18866 ret == SQL_SUCCESS && nrows == 0) {
18867 ret = SQL_NO_DATA;
18868 }
18869 return ret;
18870 }
18871
18872 #ifndef WINTERFACE
18873 /**
18874 * Prepare HSTMT.
18875 * @param stmt statement handle
18876 * @param query query string
18877 * @param queryLen length of query string or SQL_NTS
18878 * @result ODBC error code
18879 */
18880
18881 SQLRETURN SQL_API
SQLPrepare(SQLHSTMT stmt,SQLCHAR * query,SQLINTEGER queryLen)18882 SQLPrepare(SQLHSTMT stmt, SQLCHAR *query, SQLINTEGER queryLen)
18883 {
18884 SQLRETURN ret;
18885 #if defined(_WIN32) || defined(_WIN64)
18886 char *q;
18887 #endif
18888
18889 HSTMT_LOCK(stmt);
18890 #if defined(_WIN32) || defined(_WIN64)
18891 if (!((STMT *) stmt)->oemcp[0]) {
18892 ret = drvprepare(stmt, query, queryLen);
18893 goto done;
18894 }
18895 q = wmb_to_utf_c((char *) query, queryLen);
18896 if (!q) {
18897 ret = nomem((STMT *) stmt);
18898 goto done;
18899 }
18900 query = (SQLCHAR *) q;
18901 queryLen = SQL_NTS;
18902 #endif
18903 ret = drvprepare(stmt, query, queryLen);
18904 #if defined(_WIN32) || defined(_WIN64)
18905 uc_free(q);
18906 done:
18907 ;
18908 #endif
18909 HSTMT_UNLOCK(stmt);
18910 return ret;
18911 }
18912 #endif
18913
18914 #ifdef WINTERFACE
18915 /**
18916 * Prepare HSTMT (UNICODE version).
18917 * @param stmt statement handle
18918 * @param query query string
18919 * @param queryLen length of query string or SQL_NTS
18920 * @result ODBC error code
18921 */
18922
18923 SQLRETURN SQL_API
SQLPrepareW(SQLHSTMT stmt,SQLWCHAR * query,SQLINTEGER queryLen)18924 SQLPrepareW(SQLHSTMT stmt, SQLWCHAR *query, SQLINTEGER queryLen)
18925 {
18926 SQLRETURN ret;
18927 char *q = uc_to_utf_c(query, queryLen);
18928
18929 HSTMT_LOCK(stmt);
18930 if (!q) {
18931 ret = nomem((STMT *) stmt);
18932 goto done;
18933 }
18934 ret = drvprepare(stmt, (SQLCHAR *) q, SQL_NTS);
18935 uc_free(q);
18936 done:
18937 HSTMT_UNLOCK(stmt);
18938 return ret;
18939 }
18940 #endif
18941
18942 /**
18943 * Execute query.
18944 * @param stmt statement handle
18945 * @result ODBC error code
18946 */
18947
18948 SQLRETURN SQL_API
SQLExecute(SQLHSTMT stmt)18949 SQLExecute(SQLHSTMT stmt)
18950 {
18951 SQLRETURN ret;
18952
18953 HSTMT_LOCK(stmt);
18954 ret = drvexecute(stmt, 1);
18955 HSTMT_UNLOCK(stmt);
18956 return ret;
18957 }
18958
18959 #ifndef WINTERFACE
18960 /**
18961 * Execute query directly.
18962 * @param stmt statement handle
18963 * @param query query string
18964 * @param queryLen length of query string or SQL_NTS
18965 * @result ODBC error code
18966 */
18967
18968 SQLRETURN SQL_API
SQLExecDirect(SQLHSTMT stmt,SQLCHAR * query,SQLINTEGER queryLen)18969 SQLExecDirect(SQLHSTMT stmt, SQLCHAR *query, SQLINTEGER queryLen)
18970 {
18971 SQLRETURN ret;
18972 #if defined(_WIN32) || defined(_WIN64)
18973 char *q;
18974 #endif
18975
18976 HSTMT_LOCK(stmt);
18977 #if defined(_WIN32) || defined(_WIN64)
18978 if (!((STMT *) stmt)->oemcp[0]) {
18979 ret = drvprepare(stmt, query, queryLen);
18980 if (ret == SQL_SUCCESS) {
18981 ret = drvexecute(stmt, 1);
18982 }
18983 goto done;
18984 }
18985 q = wmb_to_utf_c((char *) query, queryLen);
18986 if (!q) {
18987 ret = nomem((STMT *) stmt);
18988 goto done;
18989 }
18990 query = (SQLCHAR *) q;
18991 queryLen = SQL_NTS;
18992 #endif
18993 ret = drvprepare(stmt, query, queryLen);
18994 if (ret == SQL_SUCCESS) {
18995 ret = drvexecute(stmt, 1);
18996 }
18997 #if defined(_WIN32) || defined(_WIN64)
18998 uc_free(q);
18999 done:
19000 ;
19001 #endif
19002 HSTMT_UNLOCK(stmt);
19003 return ret;
19004 }
19005 #endif
19006
19007 #ifdef WINTERFACE
19008 /**
19009 * Execute query directly (UNICODE version).
19010 * @param stmt statement handle
19011 * @param query query string
19012 * @param queryLen length of query string or SQL_NTS
19013 * @result ODBC error code
19014 */
19015
19016 SQLRETURN SQL_API
SQLExecDirectW(SQLHSTMT stmt,SQLWCHAR * query,SQLINTEGER queryLen)19017 SQLExecDirectW(SQLHSTMT stmt, SQLWCHAR *query, SQLINTEGER queryLen)
19018 {
19019 SQLRETURN ret;
19020 char *q = uc_to_utf_c(query, queryLen);
19021
19022 HSTMT_LOCK(stmt);
19023 if (!q) {
19024 ret = nomem((STMT *) stmt);
19025 goto done;
19026 }
19027 ret = drvprepare(stmt, (SQLCHAR *) q, SQL_NTS);
19028 uc_free(q);
19029 if (ret == SQL_SUCCESS) {
19030 ret = drvexecute(stmt, 1);
19031 }
19032 done:
19033 HSTMT_UNLOCK(stmt);
19034 return ret;
19035 }
19036 #endif
19037
19038
19039 #if defined(_WIN32) || defined(_WIN64)
19040 #ifndef WITHOUT_DRIVERMGR
19041
19042 /*
19043 * Windows configuration dialog stuff.
19044 */
19045
19046 #include <windowsx.h>
19047 #include <winuser.h>
19048
19049 #define MAXPATHLEN (259+1) /* Max path length */
19050 #define MAXKEYLEN (15+1) /* Max keyword length */
19051 #define MAXDESC (255+1) /* Max description length */
19052 #define MAXDSNAME (255+1) /* Max data source name length */
19053 #define MAXTONAME (32+1) /* Max timeout length */
19054 #define MAXDBNAME MAXPATHLEN
19055
19056 /* Attribute key indexes into an array of Attr structs, see below */
19057
19058 #define KEY_DSN 0
19059 #define KEY_DESC 1
19060 #define KEY_DBNAME 2
19061 #define KEY_BUSY 3
19062 #define KEY_DRIVER 4
19063 #define KEY_STEPAPI 5
19064 #define KEY_SYNCP 6
19065 #define KEY_NOTXN 7
19066 #define KEY_SHORTNAM 8
19067 #define KEY_LONGNAM 9
19068 #define KEY_NOCREAT 10
19069 #define KEY_NOWCHAR 11
19070 #define KEY_LOADEXT 12
19071 #define KEY_JMODE 13
19072 #define KEY_FKSUPPORT 14
19073 #define KEY_OEMCP 15
19074 #define KEY_BIGINT 16
19075 #define KEY_PASSWD 17
19076 #define KEY_JDCONV 18
19077 #define NUMOFKEYS 19
19078
19079 typedef struct {
19080 BOOL supplied;
19081 char attr[MAXPATHLEN*4];
19082 } ATTR;
19083
19084 typedef struct {
19085 SQLHWND parent;
19086 LPCSTR driver;
19087 ATTR attr[NUMOFKEYS];
19088 char DSN[MAXDSNAME];
19089 BOOL newDSN;
19090 BOOL defDSN;
19091 } SETUPDLG;
19092
19093 static struct {
19094 char *key;
19095 int ikey;
19096 } attrLookup[] = {
19097 { "DSN", KEY_DSN },
19098 { "DESC", KEY_DESC },
19099 { "Description", KEY_DESC},
19100 { "Database", KEY_DBNAME },
19101 { "Timeout", KEY_BUSY },
19102 { "Driver", KEY_DRIVER },
19103 { "StepAPI", KEY_STEPAPI },
19104 { "SyncPragma", KEY_SYNCP },
19105 { "NoTXN", KEY_NOTXN },
19106 { "ShortNames", KEY_SHORTNAM },
19107 { "LongNames", KEY_LONGNAM },
19108 { "NoCreat", KEY_NOCREAT },
19109 { "NoWCHAR", KEY_NOWCHAR },
19110 { "LoadExt", KEY_LOADEXT },
19111 { "JournalMode", KEY_JMODE },
19112 { "FKSupport", KEY_FKSUPPORT },
19113 { "OEMCP", KEY_OEMCP },
19114 { "BigInt", KEY_BIGINT },
19115 { "PWD", KEY_PASSWD },
19116 { "JDConv", KEY_JDCONV },
19117 { NULL, 0 }
19118 };
19119
19120 /**
19121 * Setup dialog data from datasource attributes.
19122 * @param attribs attribute string
19123 * @param setupdlg pointer to dialog data
19124 */
19125
19126 static void
ParseAttributes(LPCSTR attribs,SETUPDLG * setupdlg)19127 ParseAttributes(LPCSTR attribs, SETUPDLG *setupdlg)
19128 {
19129 char *str = (char *) attribs, *start, key[MAXKEYLEN];
19130 int elem, nkey;
19131
19132 while (*str) {
19133 start = str;
19134 if ((str = strchr(str, '=')) == NULL) {
19135 return;
19136 }
19137 elem = -1;
19138 nkey = str - start;
19139 if (nkey < sizeof (key)) {
19140 int i;
19141
19142 memcpy(key, start, nkey);
19143 key[nkey] = '\0';
19144 for (i = 0; attrLookup[i].key; i++) {
19145 if (strcasecmp(attrLookup[i].key, key) == 0) {
19146 elem = attrLookup[i].ikey;
19147 break;
19148 }
19149 }
19150 }
19151 start = ++str;
19152 while (*str && *str != ';') {
19153 ++str;
19154 }
19155 if (elem >= 0) {
19156 int end = min(str - start, sizeof (setupdlg->attr[elem].attr) - 1);
19157
19158 setupdlg->attr[elem].supplied = TRUE;
19159 memcpy(setupdlg->attr[elem].attr, start, end);
19160 setupdlg->attr[elem].attr[end] = '\0';
19161 }
19162 ++str;
19163 }
19164 }
19165
19166 /**
19167 * Set datasource attributes in registry.
19168 * @param parent handle of parent window
19169 * @param setupdlg pointer to dialog data
19170 * @result true or false
19171 */
19172
19173 static BOOL
SetDSNAttributes(HWND parent,SETUPDLG * setupdlg)19174 SetDSNAttributes(HWND parent, SETUPDLG *setupdlg)
19175 {
19176 char *dsn = setupdlg->attr[KEY_DSN].attr;
19177
19178 if (setupdlg->newDSN && strlen(dsn) == 0) {
19179 return FALSE;
19180 }
19181 if (!SQLWriteDSNToIni(dsn, setupdlg->driver)) {
19182 if (parent) {
19183 char buf[MAXPATHLEN], msg[MAXPATHLEN];
19184
19185 LoadString(hModule, IDS_BADDSN, buf, sizeof (buf));
19186 wsprintf(msg, buf, dsn);
19187 LoadString(hModule, IDS_MSGTITLE, buf, sizeof (buf));
19188 MessageBox(parent, msg, buf,
19189 MB_ICONEXCLAMATION | MB_OK | MB_TASKMODAL |
19190 MB_SETFOREGROUND);
19191 }
19192 return FALSE;
19193 }
19194 if (parent || setupdlg->attr[KEY_DESC].supplied) {
19195 SQLWritePrivateProfileString(dsn, "Description",
19196 setupdlg->attr[KEY_DESC].attr,
19197 ODBC_INI);
19198 }
19199 if (parent || setupdlg->attr[KEY_DBNAME].supplied) {
19200 SQLWritePrivateProfileString(dsn, "Database",
19201 setupdlg->attr[KEY_DBNAME].attr,
19202 ODBC_INI);
19203 }
19204 if (parent || setupdlg->attr[KEY_BUSY].supplied) {
19205 SQLWritePrivateProfileString(dsn, "Timeout",
19206 setupdlg->attr[KEY_BUSY].attr,
19207 ODBC_INI);
19208 }
19209 if (parent || setupdlg->attr[KEY_STEPAPI].supplied) {
19210 SQLWritePrivateProfileString(dsn, "StepAPI",
19211 setupdlg->attr[KEY_STEPAPI].attr,
19212 ODBC_INI);
19213 }
19214 if (parent || setupdlg->attr[KEY_SYNCP].supplied) {
19215 SQLWritePrivateProfileString(dsn, "SyncPragma",
19216 setupdlg->attr[KEY_SYNCP].attr,
19217 ODBC_INI);
19218 }
19219 if (parent || setupdlg->attr[KEY_NOTXN].supplied) {
19220 SQLWritePrivateProfileString(dsn, "NoTXN",
19221 setupdlg->attr[KEY_NOTXN].attr,
19222 ODBC_INI);
19223 }
19224 if (parent || setupdlg->attr[KEY_SHORTNAM].supplied) {
19225 SQLWritePrivateProfileString(dsn, "ShortNames",
19226 setupdlg->attr[KEY_SHORTNAM].attr,
19227 ODBC_INI);
19228 }
19229 if (parent || setupdlg->attr[KEY_LONGNAM].supplied) {
19230 SQLWritePrivateProfileString(dsn, "LongNames",
19231 setupdlg->attr[KEY_LONGNAM].attr,
19232 ODBC_INI);
19233 }
19234 if (parent || setupdlg->attr[KEY_NOCREAT].supplied) {
19235 SQLWritePrivateProfileString(dsn, "NoCreat",
19236 setupdlg->attr[KEY_NOCREAT].attr,
19237 ODBC_INI);
19238 }
19239 if (parent || setupdlg->attr[KEY_NOWCHAR].supplied) {
19240 SQLWritePrivateProfileString(dsn, "NoWCHAR",
19241 setupdlg->attr[KEY_NOWCHAR].attr,
19242 ODBC_INI);
19243 }
19244 if (parent || setupdlg->attr[KEY_FKSUPPORT].supplied) {
19245 SQLWritePrivateProfileString(dsn, "FKSupport",
19246 setupdlg->attr[KEY_FKSUPPORT].attr,
19247 ODBC_INI);
19248 }
19249 if (parent || setupdlg->attr[KEY_OEMCP].supplied) {
19250 SQLWritePrivateProfileString(dsn, "OEMCP",
19251 setupdlg->attr[KEY_OEMCP].attr,
19252 ODBC_INI);
19253 }
19254 if (parent || setupdlg->attr[KEY_LOADEXT].supplied) {
19255 SQLWritePrivateProfileString(dsn, "LoadExt",
19256 setupdlg->attr[KEY_LOADEXT].attr,
19257 ODBC_INI);
19258 }
19259 if (parent || setupdlg->attr[KEY_BIGINT].supplied) {
19260 SQLWritePrivateProfileString(dsn, "BigInt",
19261 setupdlg->attr[KEY_BIGINT].attr,
19262 ODBC_INI);
19263 }
19264 if (parent || setupdlg->attr[KEY_JDCONV].supplied) {
19265 SQLWritePrivateProfileString(dsn, "JDConv",
19266 setupdlg->attr[KEY_JDCONV].attr,
19267 ODBC_INI);
19268 }
19269 if (parent || setupdlg->attr[KEY_PASSWD].supplied) {
19270 SQLWritePrivateProfileString(dsn, "PWD",
19271 setupdlg->attr[KEY_PASSWD].attr,
19272 ODBC_INI);
19273 }
19274 if (setupdlg->attr[KEY_DSN].supplied &&
19275 strcasecmp(setupdlg->DSN, setupdlg->attr[KEY_DSN].attr)) {
19276 SQLRemoveDSNFromIni(setupdlg->DSN);
19277 }
19278 return TRUE;
19279 }
19280
19281 /**
19282 * Get datasource attributes from registry.
19283 * @param setupdlg pointer to dialog data
19284 */
19285
19286 static void
GetAttributes(SETUPDLG * setupdlg)19287 GetAttributes(SETUPDLG *setupdlg)
19288 {
19289 char *dsn = setupdlg->attr[KEY_DSN].attr;
19290
19291 if (!setupdlg->attr[KEY_DESC].supplied) {
19292 SQLGetPrivateProfileString(dsn, "Description", "",
19293 setupdlg->attr[KEY_DESC].attr,
19294 sizeof (setupdlg->attr[KEY_DESC].attr),
19295 ODBC_INI);
19296 }
19297 if (!setupdlg->attr[KEY_DBNAME].supplied) {
19298 SQLGetPrivateProfileString(dsn, "Database", "",
19299 setupdlg->attr[KEY_DBNAME].attr,
19300 sizeof (setupdlg->attr[KEY_DBNAME].attr),
19301 ODBC_INI);
19302 }
19303 if (!setupdlg->attr[KEY_BUSY].supplied) {
19304 SQLGetPrivateProfileString(dsn, "Timeout", "100000",
19305 setupdlg->attr[KEY_BUSY].attr,
19306 sizeof (setupdlg->attr[KEY_BUSY].attr),
19307 ODBC_INI);
19308 }
19309 if (!setupdlg->attr[KEY_STEPAPI].supplied) {
19310 SQLGetPrivateProfileString(dsn, "StepAPI", "0",
19311 setupdlg->attr[KEY_STEPAPI].attr,
19312 sizeof (setupdlg->attr[KEY_STEPAPI].attr),
19313 ODBC_INI);
19314 }
19315 if (!setupdlg->attr[KEY_SYNCP].supplied) {
19316 SQLGetPrivateProfileString(dsn, "SyncPragma", "NORMAL",
19317 setupdlg->attr[KEY_SYNCP].attr,
19318 sizeof (setupdlg->attr[KEY_SYNCP].attr),
19319 ODBC_INI);
19320 }
19321 if (!setupdlg->attr[KEY_NOTXN].supplied) {
19322 SQLGetPrivateProfileString(dsn, "NoTXN", "",
19323 setupdlg->attr[KEY_NOTXN].attr,
19324 sizeof (setupdlg->attr[KEY_NOTXN].attr),
19325 ODBC_INI);
19326 }
19327 if (!setupdlg->attr[KEY_SHORTNAM].supplied) {
19328 SQLGetPrivateProfileString(dsn, "ShortNames", "",
19329 setupdlg->attr[KEY_SHORTNAM].attr,
19330 sizeof (setupdlg->attr[KEY_SHORTNAM].attr),
19331 ODBC_INI);
19332 }
19333 if (!setupdlg->attr[KEY_LONGNAM].supplied) {
19334 SQLGetPrivateProfileString(dsn, "LongNames", "",
19335 setupdlg->attr[KEY_LONGNAM].attr,
19336 sizeof (setupdlg->attr[KEY_LONGNAM].attr),
19337 ODBC_INI);
19338 }
19339 if (!setupdlg->attr[KEY_NOCREAT].supplied) {
19340 SQLGetPrivateProfileString(dsn, "NoCreat", "",
19341 setupdlg->attr[KEY_NOCREAT].attr,
19342 sizeof (setupdlg->attr[KEY_NOCREAT].attr),
19343 ODBC_INI);
19344 }
19345 if (!setupdlg->attr[KEY_NOWCHAR].supplied) {
19346 SQLGetPrivateProfileString(dsn, "NoWCHAR", "",
19347 setupdlg->attr[KEY_NOWCHAR].attr,
19348 sizeof (setupdlg->attr[KEY_NOWCHAR].attr),
19349 ODBC_INI);
19350 }
19351 if (!setupdlg->attr[KEY_FKSUPPORT].supplied) {
19352 SQLGetPrivateProfileString(dsn, "FKSupport", "",
19353 setupdlg->attr[KEY_FKSUPPORT].attr,
19354 sizeof (setupdlg->attr[KEY_FKSUPPORT].attr),
19355 ODBC_INI);
19356 }
19357 if (!setupdlg->attr[KEY_OEMCP].supplied) {
19358 SQLGetPrivateProfileString(dsn, "OEMCP", "",
19359 setupdlg->attr[KEY_OEMCP].attr,
19360 sizeof (setupdlg->attr[KEY_OEMCP].attr),
19361 ODBC_INI);
19362 }
19363 if (!setupdlg->attr[KEY_LOADEXT].supplied) {
19364 SQLGetPrivateProfileString(dsn, "LoadExt", "",
19365 setupdlg->attr[KEY_LOADEXT].attr,
19366 sizeof (setupdlg->attr[KEY_LOADEXT].attr),
19367 ODBC_INI);
19368 }
19369 if (!setupdlg->attr[KEY_JMODE].supplied) {
19370 SQLGetPrivateProfileString(dsn, "JournalMode", "",
19371 setupdlg->attr[KEY_JMODE].attr,
19372 sizeof (setupdlg->attr[KEY_JMODE].attr),
19373 ODBC_INI);
19374 }
19375 if (!setupdlg->attr[KEY_BIGINT].supplied) {
19376 SQLGetPrivateProfileString(dsn, "BigInt", "",
19377 setupdlg->attr[KEY_BIGINT].attr,
19378 sizeof (setupdlg->attr[KEY_BIGINT].attr),
19379 ODBC_INI);
19380 }
19381 if (!setupdlg->attr[KEY_PASSWD].supplied) {
19382 SQLGetPrivateProfileString(dsn, "PWD", "",
19383 setupdlg->attr[KEY_PASSWD].attr,
19384 sizeof (setupdlg->attr[KEY_PASSWD].attr),
19385 ODBC_INI);
19386 }
19387 if (!setupdlg->attr[KEY_JDCONV].supplied) {
19388 SQLGetPrivateProfileString(dsn, "JDConv", "",
19389 setupdlg->attr[KEY_JDCONV].attr,
19390 sizeof (setupdlg->attr[KEY_JDCONV].attr),
19391 ODBC_INI);
19392 }
19393 }
19394
19395 /**
19396 * Open file dialog for selection of SQLite database file.
19397 * @param hdlg handle of originating dialog window
19398 */
19399
19400 static void
GetDBFile(HWND hdlg)19401 GetDBFile(HWND hdlg)
19402 {
19403 #ifdef _WIN64
19404 SETUPDLG *setupdlg = (SETUPDLG *) GetWindowLongPtr(hdlg, DWLP_USER);
19405 #else
19406 SETUPDLG *setupdlg = (SETUPDLG *) GetWindowLong(hdlg, DWL_USER);
19407 #endif
19408 OPENFILENAME ofn;
19409
19410 memset(&ofn, 0, sizeof (ofn));
19411 ofn.lStructSize = sizeof (ofn);
19412 ofn.hwndOwner = hdlg;
19413 #ifdef _WIN64
19414 ofn.hInstance = (HINSTANCE) GetWindowLongPtr(hdlg, GWLP_HINSTANCE);
19415 #else
19416 ofn.hInstance = (HINSTANCE) GetWindowLong(hdlg, GWL_HINSTANCE);
19417 #endif
19418 ofn.lpstrFile = (LPTSTR) setupdlg->attr[KEY_DBNAME].attr;
19419 ofn.nMaxFile = MAXPATHLEN;
19420 ofn.Flags = OFN_HIDEREADONLY | OFN_PATHMUSTEXIST |
19421 OFN_NOCHANGEDIR | OFN_EXPLORER | OFN_FILEMUSTEXIST;
19422 if (GetOpenFileName(&ofn)) {
19423 SetDlgItemText(hdlg, IDC_DBNAME, setupdlg->attr[KEY_DBNAME].attr);
19424 setupdlg->attr[KEY_DBNAME].supplied = TRUE;
19425 }
19426 }
19427
19428 /**
19429 * Dialog procedure for ConfigDSN().
19430 * @param hdlg handle of dialog window
19431 * @param wmsg type of message
19432 * @param wparam wparam of message
19433 * @param lparam lparam of message
19434 * @result true or false
19435 */
19436
19437 static BOOL CALLBACK
ConfigDlgProc(HWND hdlg,WORD wmsg,WPARAM wparam,LPARAM lparam)19438 ConfigDlgProc(HWND hdlg, WORD wmsg, WPARAM wparam, LPARAM lparam)
19439 {
19440 SETUPDLG *setupdlg = NULL;
19441 WORD index;
19442
19443 switch (wmsg) {
19444 case WM_INITDIALOG:
19445 #ifdef _WIN64
19446 SetWindowLongPtr(hdlg, DWLP_USER, lparam);
19447 #else
19448 SetWindowLong(hdlg, DWL_USER, lparam);
19449 #endif
19450 setupdlg = (SETUPDLG *) lparam;
19451 GetAttributes(setupdlg);
19452 SetDlgItemText(hdlg, IDC_DSNAME, setupdlg->attr[KEY_DSN].attr);
19453 SetDlgItemText(hdlg, IDC_DESC, setupdlg->attr[KEY_DESC].attr);
19454 SetDlgItemText(hdlg, IDC_DBNAME, setupdlg->attr[KEY_DBNAME].attr);
19455 SetDlgItemText(hdlg, IDC_TONAME, setupdlg->attr[KEY_BUSY].attr);
19456 SetDlgItemText(hdlg, IDC_LOADEXT, setupdlg->attr[KEY_LOADEXT].attr);
19457 SendDlgItemMessage(hdlg, IDC_DSNAME, EM_LIMITTEXT,
19458 (WPARAM) (MAXDSNAME - 1), (LPARAM) 0);
19459 SendDlgItemMessage(hdlg, IDC_DESC, EM_LIMITTEXT,
19460 (WPARAM) (MAXDESC - 1), (LPARAM) 0);
19461 SendDlgItemMessage(hdlg, IDC_DBNAME, EM_LIMITTEXT,
19462 (WPARAM) (MAXDBNAME - 1), (LPARAM) 0);
19463 SendDlgItemMessage(hdlg, IDC_TONAME, EM_LIMITTEXT,
19464 (WPARAM) (MAXTONAME - 1), (LPARAM) 0);
19465 SendDlgItemMessage(hdlg, IDC_LOADEXT, EM_LIMITTEXT,
19466 (WPARAM) (MAXPATHLEN*4 - 1), (LPARAM) 0);
19467 CheckDlgButton(hdlg, IDC_STEPAPI,
19468 getbool(setupdlg->attr[KEY_STEPAPI].attr) ?
19469 BST_CHECKED : BST_UNCHECKED);
19470 CheckDlgButton(hdlg, IDC_NOTXN,
19471 getbool(setupdlg->attr[KEY_NOTXN].attr) ?
19472 BST_CHECKED : BST_UNCHECKED);
19473 CheckDlgButton(hdlg, IDC_SHORTNAM,
19474 getbool(setupdlg->attr[KEY_SHORTNAM].attr) ?
19475 BST_CHECKED : BST_UNCHECKED);
19476 CheckDlgButton(hdlg, IDC_LONGNAM,
19477 getbool(setupdlg->attr[KEY_LONGNAM].attr) ?
19478 BST_CHECKED : BST_UNCHECKED);
19479 CheckDlgButton(hdlg, IDC_NOCREAT,
19480 getbool(setupdlg->attr[KEY_NOCREAT].attr) ?
19481 BST_CHECKED : BST_UNCHECKED);
19482 CheckDlgButton(hdlg, IDC_NOWCHAR,
19483 getbool(setupdlg->attr[KEY_NOWCHAR].attr) ?
19484 BST_CHECKED : BST_UNCHECKED);
19485 CheckDlgButton(hdlg, IDC_FKSUPPORT,
19486 getbool(setupdlg->attr[KEY_FKSUPPORT].attr) ?
19487 BST_CHECKED : BST_UNCHECKED);
19488 CheckDlgButton(hdlg, IDC_OEMCP,
19489 getbool(setupdlg->attr[KEY_OEMCP].attr) ?
19490 BST_CHECKED : BST_UNCHECKED);
19491 CheckDlgButton(hdlg, IDC_BIGINT,
19492 getbool(setupdlg->attr[KEY_BIGINT].attr) ?
19493 BST_CHECKED : BST_UNCHECKED);
19494 CheckDlgButton(hdlg, IDC_JDCONV,
19495 getbool(setupdlg->attr[KEY_JDCONV].attr) ?
19496 BST_CHECKED : BST_UNCHECKED);
19497 SendDlgItemMessage(hdlg, IDC_SYNCP,
19498 CB_LIMITTEXT, (WPARAM) 10, (LPARAM) 0);
19499 SendDlgItemMessage(hdlg, IDC_SYNCP,
19500 CB_ADDSTRING, 0, (LPARAM) "NORMAL");
19501 SendDlgItemMessage(hdlg, IDC_SYNCP,
19502 CB_ADDSTRING, 0, (LPARAM) "OFF");
19503 SendDlgItemMessage(hdlg, IDC_SYNCP,
19504 CB_ADDSTRING, 0, (LPARAM) "FULL");
19505 SendDlgItemMessage(hdlg, IDC_SYNCP,
19506 CB_SELECTSTRING, (WPARAM) -1,
19507 (LPARAM) setupdlg->attr[KEY_SYNCP].attr);
19508 if (setupdlg->defDSN) {
19509 EnableWindow(GetDlgItem(hdlg, IDC_DSNAME), FALSE);
19510 EnableWindow(GetDlgItem(hdlg, IDC_DSNAMETEXT), FALSE);
19511 }
19512 return TRUE;
19513 case WM_COMMAND:
19514 switch (GET_WM_COMMAND_ID(wparam, lparam)) {
19515 case IDC_DSNAME:
19516 if (GET_WM_COMMAND_CMD(wparam, lparam) == EN_CHANGE) {
19517 char item[MAXDSNAME];
19518
19519 EnableWindow(GetDlgItem(hdlg, IDOK),
19520 GetDlgItemText(hdlg, IDC_DSNAME,
19521 item, sizeof (item)));
19522 return TRUE;
19523 }
19524 break;
19525 case IDC_BROWSE:
19526 GetDBFile(hdlg);
19527 break;
19528 case IDOK:
19529 #ifdef _WIN64
19530 setupdlg = (SETUPDLG *) GetWindowLongPtr(hdlg, DWLP_USER);
19531 #else
19532 setupdlg = (SETUPDLG *) GetWindowLong(hdlg, DWL_USER);
19533 #endif
19534 if (!setupdlg->defDSN) {
19535 GetDlgItemText(hdlg, IDC_DSNAME,
19536 setupdlg->attr[KEY_DSN].attr,
19537 sizeof (setupdlg->attr[KEY_DSN].attr));
19538 }
19539 GetDlgItemText(hdlg, IDC_DESC,
19540 setupdlg->attr[KEY_DESC].attr,
19541 sizeof (setupdlg->attr[KEY_DESC].attr));
19542 GetDlgItemText(hdlg, IDC_DBNAME,
19543 setupdlg->attr[KEY_DBNAME].attr,
19544 sizeof (setupdlg->attr[KEY_DBNAME].attr));
19545 GetDlgItemText(hdlg, IDC_TONAME,
19546 setupdlg->attr[KEY_BUSY].attr,
19547 sizeof (setupdlg->attr[KEY_BUSY].attr));
19548 GetDlgItemText(hdlg, IDC_LOADEXT,
19549 setupdlg->attr[KEY_LOADEXT].attr,
19550 sizeof (setupdlg->attr[KEY_LOADEXT].attr));
19551 index = SendDlgItemMessage(hdlg, IDC_SYNCP,
19552 CB_GETCURSEL, (WPARAM) 0, (LPARAM) 0);
19553 if (index != (WORD) CB_ERR) {
19554 SendDlgItemMessage(hdlg, IDC_SYNCP,
19555 CB_GETLBTEXT, index,
19556 (LPARAM) setupdlg->attr[KEY_SYNCP].attr);
19557 }
19558 strcpy(setupdlg->attr[KEY_STEPAPI].attr,
19559 (IsDlgButtonChecked(hdlg, IDC_STEPAPI) == BST_CHECKED) ?
19560 "1" : "0");
19561 strcpy(setupdlg->attr[KEY_NOTXN].attr,
19562 (IsDlgButtonChecked(hdlg, IDC_NOTXN) == BST_CHECKED) ?
19563 "1" : "0");
19564 strcpy(setupdlg->attr[KEY_SHORTNAM].attr,
19565 (IsDlgButtonChecked(hdlg, IDC_SHORTNAM) == BST_CHECKED) ?
19566 "1" : "0");
19567 strcpy(setupdlg->attr[KEY_LONGNAM].attr,
19568 (IsDlgButtonChecked(hdlg, IDC_LONGNAM) == BST_CHECKED) ?
19569 "1" : "0");
19570 strcpy(setupdlg->attr[KEY_NOCREAT].attr,
19571 (IsDlgButtonChecked(hdlg, IDC_NOCREAT) == BST_CHECKED) ?
19572 "1" : "0");
19573 strcpy(setupdlg->attr[KEY_NOWCHAR].attr,
19574 (IsDlgButtonChecked(hdlg, IDC_NOWCHAR) == BST_CHECKED) ?
19575 "1" : "0");
19576 strcpy(setupdlg->attr[KEY_FKSUPPORT].attr,
19577 (IsDlgButtonChecked(hdlg, IDC_FKSUPPORT) == BST_CHECKED) ?
19578 "1" : "0");
19579 strcpy(setupdlg->attr[KEY_OEMCP].attr,
19580 (IsDlgButtonChecked(hdlg, IDC_OEMCP) == BST_CHECKED) ?
19581 "1" : "0");
19582 strcpy(setupdlg->attr[KEY_BIGINT].attr,
19583 (IsDlgButtonChecked(hdlg, IDC_BIGINT) == BST_CHECKED) ?
19584 "1" : "0");
19585 strcpy(setupdlg->attr[KEY_JDCONV].attr,
19586 (IsDlgButtonChecked(hdlg, IDC_JDCONV) == BST_CHECKED) ?
19587 "1" : "0");
19588 SetDSNAttributes(hdlg, setupdlg);
19589 /* FALL THROUGH */
19590 case IDCANCEL:
19591 EndDialog(hdlg, wparam);
19592 return TRUE;
19593 }
19594 break;
19595 }
19596 return FALSE;
19597 }
19598
19599 /**
19600 * ODBC INSTAPI procedure for DSN configuration.
19601 * @param hwnd parent window handle
19602 * @param request type of request
19603 * @param driver driver name
19604 * @param attribs attribute string of DSN
19605 * @result true or false
19606 */
19607
19608 BOOL INSTAPI
ConfigDSN(HWND hwnd,WORD request,LPCSTR driver,LPCSTR attribs)19609 ConfigDSN(HWND hwnd, WORD request, LPCSTR driver, LPCSTR attribs)
19610 {
19611 BOOL success;
19612 SETUPDLG *setupdlg;
19613
19614 setupdlg = (SETUPDLG *) xmalloc(sizeof (SETUPDLG));
19615 if (setupdlg == NULL) {
19616 return FALSE;
19617 }
19618 memset(setupdlg, 0, sizeof (SETUPDLG));
19619 if (attribs) {
19620 ParseAttributes(attribs, setupdlg);
19621 }
19622 if (setupdlg->attr[KEY_DSN].supplied) {
19623 strcpy(setupdlg->DSN, setupdlg->attr[KEY_DSN].attr);
19624 } else {
19625 setupdlg->DSN[0] = '\0';
19626 }
19627 if (request == ODBC_REMOVE_DSN) {
19628 if (!setupdlg->attr[KEY_DSN].supplied) {
19629 success = FALSE;
19630 } else {
19631 success = SQLRemoveDSNFromIni(setupdlg->attr[KEY_DSN].attr);
19632 }
19633 } else {
19634 setupdlg->parent = hwnd;
19635 setupdlg->driver = driver;
19636 setupdlg->newDSN = request == ODBC_ADD_DSN;
19637 setupdlg->defDSN = strcasecmp(setupdlg->attr[KEY_DSN].attr,
19638 "Default") == 0;
19639 if (hwnd) {
19640 success = DialogBoxParam(hModule, MAKEINTRESOURCE(CONFIGDSN),
19641 hwnd, (DLGPROC) ConfigDlgProc,
19642 (LPARAM) setupdlg) == IDOK;
19643 } else if (setupdlg->attr[KEY_DSN].supplied) {
19644 success = SetDSNAttributes(hwnd, setupdlg);
19645 } else {
19646 success = FALSE;
19647 }
19648 }
19649 xfree(setupdlg);
19650 return success;
19651 }
19652
19653 /**
19654 * Dialog procedure for SQLDriverConnect().
19655 * @param hdlg handle of dialog window
19656 * @param wmsg type of message
19657 * @param wparam wparam of message
19658 * @param lparam lparam of message
19659 * @result true or false
19660 */
19661
19662 static BOOL CALLBACK
DriverConnectProc(HWND hdlg,WORD wmsg,WPARAM wparam,LPARAM lparam)19663 DriverConnectProc(HWND hdlg, WORD wmsg, WPARAM wparam, LPARAM lparam)
19664 {
19665 SETUPDLG *setupdlg;
19666 WORD index;
19667
19668 switch (wmsg) {
19669 case WM_INITDIALOG:
19670 #ifdef _WIN64
19671 SetWindowLongPtr(hdlg, DWLP_USER, lparam);
19672 #else
19673 SetWindowLong(hdlg, DWL_USER, lparam);
19674 #endif
19675 setupdlg = (SETUPDLG *) lparam;
19676 SetDlgItemText(hdlg, IDC_DSNAME, setupdlg->attr[KEY_DSN].attr);
19677 SetDlgItemText(hdlg, IDC_DESC, setupdlg->attr[KEY_DESC].attr);
19678 SetDlgItemText(hdlg, IDC_DBNAME, setupdlg->attr[KEY_DBNAME].attr);
19679 SetDlgItemText(hdlg, IDC_TONAME, setupdlg->attr[KEY_BUSY].attr);
19680 SetDlgItemText(hdlg, IDC_LOADEXT, setupdlg->attr[KEY_LOADEXT].attr);
19681 SendDlgItemMessage(hdlg, IDC_DSNAME, EM_LIMITTEXT,
19682 (WPARAM) (MAXDSNAME - 1), (LPARAM) 0);
19683 SendDlgItemMessage(hdlg, IDC_DESC, EM_LIMITTEXT,
19684 (WPARAM) (MAXDESC - 1), (LPARAM) 0);
19685 SendDlgItemMessage(hdlg, IDC_DBNAME, EM_LIMITTEXT,
19686 (WPARAM) (MAXDBNAME - 1), (LPARAM) 0);
19687 SendDlgItemMessage(hdlg, IDC_TONAME, EM_LIMITTEXT,
19688 (WPARAM) (MAXTONAME - 1), (LPARAM) 0);
19689 SendDlgItemMessage(hdlg, IDC_LOADEXT, EM_LIMITTEXT,
19690 (WPARAM) (MAXPATHLEN*4 - 1), (LPARAM) 0);
19691 CheckDlgButton(hdlg, IDC_STEPAPI,
19692 getbool(setupdlg->attr[KEY_STEPAPI].attr) ?
19693 BST_CHECKED : BST_UNCHECKED);
19694 CheckDlgButton(hdlg, IDC_NOTXN,
19695 getbool(setupdlg->attr[KEY_NOTXN].attr) ?
19696 BST_CHECKED : BST_UNCHECKED);
19697 CheckDlgButton(hdlg, IDC_SHORTNAM,
19698 getbool(setupdlg->attr[KEY_SHORTNAM].attr) ?
19699 BST_CHECKED : BST_UNCHECKED);
19700 CheckDlgButton(hdlg, IDC_LONGNAM,
19701 getbool(setupdlg->attr[KEY_LONGNAM].attr) ?
19702 BST_CHECKED : BST_UNCHECKED);
19703 CheckDlgButton(hdlg, IDC_NOCREAT,
19704 getbool(setupdlg->attr[KEY_NOCREAT].attr) ?
19705 BST_CHECKED : BST_UNCHECKED);
19706 CheckDlgButton(hdlg, IDC_NOWCHAR,
19707 getbool(setupdlg->attr[KEY_NOWCHAR].attr) ?
19708 BST_CHECKED : BST_UNCHECKED);
19709 CheckDlgButton(hdlg, IDC_FKSUPPORT,
19710 getbool(setupdlg->attr[KEY_FKSUPPORT].attr) ?
19711 BST_CHECKED : BST_UNCHECKED);
19712 CheckDlgButton(hdlg, IDC_OEMCP,
19713 getbool(setupdlg->attr[KEY_OEMCP].attr) ?
19714 BST_CHECKED : BST_UNCHECKED);
19715 CheckDlgButton(hdlg, IDC_BIGINT,
19716 getbool(setupdlg->attr[KEY_BIGINT].attr) ?
19717 BST_CHECKED : BST_UNCHECKED);
19718 CheckDlgButton(hdlg, IDC_JDCONV,
19719 getbool(setupdlg->attr[KEY_JDCONV].attr) ?
19720 BST_CHECKED : BST_UNCHECKED);
19721 SendDlgItemMessage(hdlg, IDC_SYNCP,
19722 CB_LIMITTEXT, (WPARAM) 10, (LPARAM) 0);
19723 SendDlgItemMessage(hdlg, IDC_SYNCP,
19724 CB_ADDSTRING, 0, (LPARAM) "NORMAL");
19725 SendDlgItemMessage(hdlg, IDC_SYNCP,
19726 CB_ADDSTRING, 0, (LPARAM) "OFF");
19727 SendDlgItemMessage(hdlg, IDC_SYNCP,
19728 CB_ADDSTRING, 0, (LPARAM) "FULL");
19729 SendDlgItemMessage(hdlg, IDC_SYNCP,
19730 CB_SELECTSTRING, (WORD) -1,
19731 (LPARAM) setupdlg->attr[KEY_SYNCP].attr);
19732 if (setupdlg->defDSN) {
19733 EnableWindow(GetDlgItem(hdlg, IDC_DSNAME), FALSE);
19734 EnableWindow(GetDlgItem(hdlg, IDC_DSNAMETEXT), FALSE);
19735 }
19736 return TRUE;
19737 case WM_COMMAND:
19738 switch (GET_WM_COMMAND_ID(wparam, lparam)) {
19739 case IDC_BROWSE:
19740 GetDBFile(hdlg);
19741 break;
19742 case IDOK:
19743 #ifdef _WIN64
19744 setupdlg = (SETUPDLG *) GetWindowLongPtr(hdlg, DWLP_USER);
19745 #else
19746 setupdlg = (SETUPDLG *) GetWindowLong(hdlg, DWL_USER);
19747 #endif
19748 GetDlgItemText(hdlg, IDC_DSNAME,
19749 setupdlg->attr[KEY_DSN].attr,
19750 sizeof (setupdlg->attr[KEY_DSN].attr));
19751 GetDlgItemText(hdlg, IDC_DBNAME,
19752 setupdlg->attr[KEY_DBNAME].attr,
19753 sizeof (setupdlg->attr[KEY_DBNAME].attr));
19754 GetDlgItemText(hdlg, IDC_TONAME,
19755 setupdlg->attr[KEY_BUSY].attr,
19756 sizeof (setupdlg->attr[KEY_BUSY].attr));
19757 GetDlgItemText(hdlg, IDC_LOADEXT,
19758 setupdlg->attr[KEY_LOADEXT].attr,
19759 sizeof (setupdlg->attr[KEY_LOADEXT].attr));
19760 index = SendDlgItemMessage(hdlg, IDC_SYNCP,
19761 CB_GETCURSEL, (WPARAM) 0, (LPARAM) 0);
19762 if (index != (WORD) CB_ERR) {
19763 SendDlgItemMessage(hdlg, IDC_SYNCP,
19764 CB_GETLBTEXT, index,
19765 (LPARAM) setupdlg->attr[KEY_SYNCP].attr);
19766 }
19767 strcpy(setupdlg->attr[KEY_STEPAPI].attr,
19768 (IsDlgButtonChecked(hdlg, IDC_STEPAPI) == BST_CHECKED) ?
19769 "1" : "0");
19770 strcpy(setupdlg->attr[KEY_NOTXN].attr,
19771 (IsDlgButtonChecked(hdlg, IDC_NOTXN) == BST_CHECKED) ?
19772 "1" : "0");
19773 strcpy(setupdlg->attr[KEY_SHORTNAM].attr,
19774 (IsDlgButtonChecked(hdlg, IDC_SHORTNAM) == BST_CHECKED) ?
19775 "1" : "0");
19776 strcpy(setupdlg->attr[KEY_LONGNAM].attr,
19777 (IsDlgButtonChecked(hdlg, IDC_LONGNAM) == BST_CHECKED) ?
19778 "1" : "0");
19779 strcpy(setupdlg->attr[KEY_NOCREAT].attr,
19780 (IsDlgButtonChecked(hdlg, IDC_NOCREAT) == BST_CHECKED) ?
19781 "1" : "0");
19782 strcpy(setupdlg->attr[KEY_NOWCHAR].attr,
19783 (IsDlgButtonChecked(hdlg, IDC_NOWCHAR) == BST_CHECKED) ?
19784 "1" : "0");
19785 strcpy(setupdlg->attr[KEY_FKSUPPORT].attr,
19786 (IsDlgButtonChecked(hdlg, IDC_FKSUPPORT) == BST_CHECKED) ?
19787 "1" : "0");
19788 strcpy(setupdlg->attr[KEY_OEMCP].attr,
19789 (IsDlgButtonChecked(hdlg, IDC_OEMCP) == BST_CHECKED) ?
19790 "1" : "0");
19791 strcpy(setupdlg->attr[KEY_BIGINT].attr,
19792 (IsDlgButtonChecked(hdlg, IDC_BIGINT) == BST_CHECKED) ?
19793 "1" : "0");
19794 strcpy(setupdlg->attr[KEY_JDCONV].attr,
19795 (IsDlgButtonChecked(hdlg, IDC_JDCONV) == BST_CHECKED) ?
19796 "1" : "0");
19797 /* FALL THROUGH */
19798 case IDCANCEL:
19799 EndDialog(hdlg, GET_WM_COMMAND_ID(wparam, lparam) == IDOK);
19800 return TRUE;
19801 }
19802 }
19803 return FALSE;
19804 }
19805
19806 /**
19807 * Internal connect using a driver connection string.
19808 * @param dbc database connection handle
19809 * @param hwnd parent window handle
19810 * @param connIn driver connect input string
19811 * @param connInLen length of driver connect input string or SQL_NTS
19812 * @param connOut driver connect output string
19813 * @param connOutMax length of driver connect output string
19814 * @param connOutLen output length of driver connect output string
19815 * @param drvcompl completion type
19816 * @result ODBC error code
19817 */
19818
19819 static SQLRETURN
drvdriverconnect(SQLHDBC dbc,SQLHWND hwnd,SQLCHAR * connIn,SQLSMALLINT connInLen,SQLCHAR * connOut,SQLSMALLINT connOutMax,SQLSMALLINT * connOutLen,SQLUSMALLINT drvcompl)19820 drvdriverconnect(SQLHDBC dbc, SQLHWND hwnd,
19821 SQLCHAR *connIn, SQLSMALLINT connInLen,
19822 SQLCHAR *connOut, SQLSMALLINT connOutMax,
19823 SQLSMALLINT *connOutLen, SQLUSMALLINT drvcompl)
19824 {
19825 BOOL maybeprompt, prompt = FALSE, defaultdsn = FALSE;
19826 DBC *d;
19827 SETUPDLG *setupdlg;
19828 SQLRETURN ret;
19829 char *dsn = NULL, *driver = NULL, *dbname = NULL;
19830
19831 if (dbc == SQL_NULL_HDBC) {
19832 return SQL_INVALID_HANDLE;
19833 }
19834 d = (DBC *) dbc;
19835 if (d->sqlite) {
19836 setstatd(d, -1, "connection already established", "08002");
19837 return SQL_ERROR;
19838 }
19839 setupdlg = (SETUPDLG *) xmalloc(sizeof (SETUPDLG));
19840 if (setupdlg == NULL) {
19841 return SQL_ERROR;
19842 }
19843 memset(setupdlg, 0, sizeof (SETUPDLG));
19844 maybeprompt = drvcompl == SQL_DRIVER_COMPLETE ||
19845 drvcompl == SQL_DRIVER_COMPLETE_REQUIRED;
19846 if (connIn == NULL || !connInLen ||
19847 (connInLen == SQL_NTS && !connIn[0])) {
19848 prompt = TRUE;
19849 } else {
19850 ParseAttributes((LPCSTR) connIn, setupdlg);
19851 if (!setupdlg->attr[KEY_DSN].attr[0] &&
19852 drvcompl == SQL_DRIVER_COMPLETE_REQUIRED) {
19853 strcpy(setupdlg->attr[KEY_DSN].attr, "DEFAULT");
19854 defaultdsn = TRUE;
19855 }
19856 GetAttributes(setupdlg);
19857 if (drvcompl == SQL_DRIVER_PROMPT ||
19858 (maybeprompt &&
19859 !setupdlg->attr[KEY_DBNAME].attr[0])) {
19860 prompt = TRUE;
19861 }
19862 }
19863 retry:
19864 if (prompt) {
19865 short dlgret;
19866
19867 setupdlg->defDSN = setupdlg->attr[KEY_DRIVER].attr[0] != '\0';
19868 dlgret = DialogBoxParam(hModule, MAKEINTRESOURCE(DRIVERCONNECT),
19869 hwnd, (DLGPROC) DriverConnectProc,
19870 (LPARAM) setupdlg);
19871
19872 if (!dlgret || dlgret == -1) {
19873 xfree(setupdlg);
19874 return SQL_NO_DATA;
19875 }
19876 }
19877 dsn = setupdlg->attr[KEY_DSN].attr;
19878 driver = setupdlg->attr[KEY_DRIVER].attr;
19879 dbname = setupdlg->attr[KEY_DBNAME].attr;
19880 if (connOut || connOutLen) {
19881 char buf[SQL_MAX_MESSAGE_LENGTH * 8];
19882 int len, count;
19883 char dsn_0 = (dsn && !defaultdsn) ? dsn[0] : '\0';
19884 char drv_0 = driver ? driver[0] : '\0';
19885
19886 buf[0] = '\0';
19887 count = snprintf(buf, sizeof (buf),
19888 "%s%s%s%s%s%sDatabase=%s;StepAPI=%s;"
19889 "SyncPragma=%s;NoTXN=%s;Timeout=%s;"
19890 "ShortNames=%s;LongNames=%s;"
19891 "NoCreat=%s;NoWCHAR=%s;"
19892 "FKSupport=%s;JournalMode=%s;OEMCP=%s;LoadExt=%s;"
19893 "BigInt=%s;JDConv=%s;PWD=%s",
19894 dsn_0 ? "DSN=" : "",
19895 dsn_0 ? dsn : "",
19896 dsn_0 ? ";" : "",
19897 drv_0 ? "Driver=" : "",
19898 drv_0 ? driver : "",
19899 drv_0 ? ";" : "",
19900 dbname ? dbname : "",
19901 setupdlg->attr[KEY_STEPAPI].attr,
19902 setupdlg->attr[KEY_SYNCP].attr,
19903 setupdlg->attr[KEY_NOTXN].attr,
19904 setupdlg->attr[KEY_BUSY].attr,
19905 setupdlg->attr[KEY_SHORTNAM].attr,
19906 setupdlg->attr[KEY_LONGNAM].attr,
19907 setupdlg->attr[KEY_NOCREAT].attr,
19908 setupdlg->attr[KEY_NOWCHAR].attr,
19909 setupdlg->attr[KEY_FKSUPPORT].attr,
19910 setupdlg->attr[KEY_JMODE].attr,
19911 setupdlg->attr[KEY_OEMCP].attr,
19912 setupdlg->attr[KEY_LOADEXT].attr,
19913 setupdlg->attr[KEY_BIGINT].attr,
19914 setupdlg->attr[KEY_JDCONV].attr,
19915 setupdlg->attr[KEY_PASSWD].attr);
19916 if (count < 0) {
19917 buf[sizeof (buf) - 1] = '\0';
19918 }
19919 len = min(connOutMax - 1, strlen(buf));
19920 if (connOut) {
19921 strncpy((char *) connOut, buf, len);
19922 connOut[len] = '\0';
19923 }
19924 if (connOutLen) {
19925 *connOutLen = len;
19926 }
19927 }
19928 if (dsn[0]) {
19929 char tracef[SQL_MAX_MESSAGE_LENGTH];
19930
19931 tracef[0] = '\0';
19932 SQLGetPrivateProfileString(setupdlg->attr[KEY_DSN].attr,
19933 "tracefile", "", tracef,
19934 sizeof (tracef), ODBC_INI);
19935 if (tracef[0] != '\0') {
19936 d->trace = fopen(tracef, "a");
19937 }
19938 }
19939 d->nowchar = getbool(setupdlg->attr[KEY_NOWCHAR].attr);
19940 d->shortnames = getbool(setupdlg->attr[KEY_SHORTNAM].attr);
19941 d->longnames = getbool(setupdlg->attr[KEY_LONGNAM].attr);
19942 d->nocreat = getbool(setupdlg->attr[KEY_NOCREAT].attr);
19943 d->fksupport = getbool(setupdlg->attr[KEY_FKSUPPORT].attr);
19944 d->oemcp = getbool(setupdlg->attr[KEY_OEMCP].attr);
19945 d->dobigint = getbool(setupdlg->attr[KEY_BIGINT].attr);
19946 d->jdconv = getbool(setupdlg->attr[KEY_JDCONV].attr);
19947 d->pwdLen = strlen(setupdlg->attr[KEY_PASSWD].attr);
19948 d->pwd = (d->pwdLen > 0) ? setupdlg->attr[KEY_PASSWD].attr : NULL;
19949 ret = dbopen(d, dbname ? dbname : "", 0,
19950 dsn ? dsn : "",
19951 setupdlg->attr[KEY_STEPAPI].attr,
19952 setupdlg->attr[KEY_SYNCP].attr,
19953 setupdlg->attr[KEY_NOTXN].attr,
19954 setupdlg->attr[KEY_JMODE].attr,
19955 setupdlg->attr[KEY_BUSY].attr);
19956 if (ret != SQL_SUCCESS) {
19957 if (maybeprompt && !prompt) {
19958 prompt = TRUE;
19959 goto retry;
19960 }
19961 }
19962 memset(setupdlg->attr[KEY_PASSWD].attr, 0,
19963 sizeof (setupdlg->attr[KEY_PASSWD].attr));
19964 if (ret == SQL_SUCCESS) {
19965 dbloadext(d, setupdlg->attr[KEY_LOADEXT].attr);
19966 }
19967 xfree(setupdlg);
19968 return ret;
19969 }
19970
19971 #endif /* WITHOUT_DRIVERMGR */
19972 #endif /* _WIN32 || _WIN64 */
19973
19974 #ifndef WINTERFACE
19975 /**
19976 * Connect using a driver connection string.
19977 * @param dbc database connection handle
19978 * @param hwnd parent window handle
19979 * @param connIn driver connect input string
19980 * @param connInLen length of driver connect input string or SQL_NTS
19981 * @param connOut driver connect output string
19982 * @param connOutMax length of driver connect output string
19983 * @param connOutLen output length of driver connect output string
19984 * @param drvcompl completion type
19985 * @result ODBC error code
19986 */
19987
19988 SQLRETURN SQL_API
SQLDriverConnect(SQLHDBC dbc,SQLHWND hwnd,SQLCHAR * connIn,SQLSMALLINT connInLen,SQLCHAR * connOut,SQLSMALLINT connOutMax,SQLSMALLINT * connOutLen,SQLUSMALLINT drvcompl)19989 SQLDriverConnect(SQLHDBC dbc, SQLHWND hwnd,
19990 SQLCHAR *connIn, SQLSMALLINT connInLen,
19991 SQLCHAR *connOut, SQLSMALLINT connOutMax,
19992 SQLSMALLINT *connOutLen, SQLUSMALLINT drvcompl)
19993 {
19994 SQLRETURN ret;
19995
19996 HDBC_LOCK(dbc);
19997 ret = drvdriverconnect(dbc, hwnd, connIn, connInLen,
19998 connOut, connOutMax, connOutLen, drvcompl);
19999 HDBC_UNLOCK(dbc);
20000 return ret;
20001 }
20002 #endif
20003
20004 #ifdef WINTERFACE
20005 /**
20006 * Connect using a driver connection string (UNICODE version).
20007 * @param dbc database connection handle
20008 * @param hwnd parent window handle
20009 * @param connIn driver connect input string
20010 * @param connInLen length of driver connect input string or SQL_NTS
20011 * @param connOut driver connect output string
20012 * @param connOutMax length of driver connect output string
20013 * @param connOutLen output length of driver connect output string
20014 * @param drvcompl completion type
20015 * @result ODBC error code
20016 */
20017
20018 SQLRETURN SQL_API
SQLDriverConnectW(SQLHDBC dbc,SQLHWND hwnd,SQLWCHAR * connIn,SQLSMALLINT connInLen,SQLWCHAR * connOut,SQLSMALLINT connOutMax,SQLSMALLINT * connOutLen,SQLUSMALLINT drvcompl)20019 SQLDriverConnectW(SQLHDBC dbc, SQLHWND hwnd,
20020 SQLWCHAR *connIn, SQLSMALLINT connInLen,
20021 SQLWCHAR *connOut, SQLSMALLINT connOutMax,
20022 SQLSMALLINT *connOutLen, SQLUSMALLINT drvcompl)
20023 {
20024 SQLRETURN ret;
20025 char *ci = NULL;
20026 SQLSMALLINT len = 0;
20027
20028 HDBC_LOCK(dbc);
20029 if (connIn) {
20030 #if defined(_WIN32) || defined(_WIN64)
20031 if (connInLen == SQL_NTS) {
20032 connInLen = -1;
20033 }
20034 ci = uc_to_wmb(connIn, connInLen);
20035 #else
20036 ci = uc_to_utf(connIn, connInLen);
20037 #endif
20038 if (!ci) {
20039 DBC *d = (DBC *) dbc;
20040
20041 setstatd(d, -1, "out of memory", (*d->ov3) ? "HY000" : "S1000");
20042 HDBC_UNLOCK(dbc);
20043 return SQL_ERROR;
20044 }
20045 }
20046 ret = drvdriverconnect(dbc, hwnd, (SQLCHAR *) ci, SQL_NTS,
20047 (SQLCHAR *) connOut, connOutMax, &len, drvcompl);
20048 HDBC_UNLOCK(dbc);
20049 uc_free(ci);
20050 if (ret == SQL_SUCCESS) {
20051 SQLWCHAR *co = NULL;
20052
20053 if (connOut) {
20054 if (len > 0) {
20055 #if defined(_WIN32) || defined(_WIN64)
20056 co = wmb_to_uc((char *) connOut, len);
20057 #else
20058 co = uc_from_utf((SQLCHAR *) connOut, len);
20059 #endif
20060 if (co) {
20061 uc_strncpy(connOut, co, connOutMax / sizeof (SQLWCHAR));
20062 len = min(connOutMax / sizeof (SQLWCHAR), uc_strlen(co));
20063 uc_free(co);
20064 } else {
20065 len = 0;
20066 }
20067 }
20068 if (len <= 0) {
20069 len = 0;
20070 connOut[0] = 0;
20071 }
20072 } else {
20073 len = 0;
20074 }
20075 if (connOutLen) {
20076 *connOutLen = len;
20077 }
20078 }
20079 return ret;
20080 }
20081 #endif
20082
20083 #if defined(_WIN32) || defined(_WIN64)
20084
20085 /**
20086 * DLL initializer for WIN32.
20087 * @param hinst instance handle
20088 * @param reason reason code for entry point
20089 * @param reserved
20090 * @result always true
20091 */
20092
20093 BOOL APIENTRY
LibMain(HANDLE hinst,DWORD reason,LPVOID reserved)20094 LibMain(HANDLE hinst, DWORD reason, LPVOID reserved)
20095 {
20096 static int initialized = 0;
20097
20098 switch (reason) {
20099 case DLL_PROCESS_ATTACH:
20100 if (!initialized++) {
20101 hModule = hinst;
20102 #ifdef WINTERFACE
20103 /* MS Access hack part 1 (reserved error -7748) */
20104 statSpec2P = statSpec2;
20105 statSpec3P = statSpec3;
20106 #endif
20107 #ifdef SQLITE_DYNLOAD
20108 dls_init();
20109 #endif
20110 #ifdef SQLITE_HAS_CODEC
20111 sqlite3_activate_see(SQLITE_ACTIVATION_KEY);
20112 #endif
20113 }
20114 #if defined(ENABLE_NVFS) && (ENABLE_NVFS)
20115 nvfs_init();
20116 #endif
20117 break;
20118 case DLL_THREAD_ATTACH:
20119 break;
20120 case DLL_PROCESS_DETACH:
20121 if (--initialized <= 0) {
20122 #ifdef SQLITE_DYNLOAD
20123 dls_fini();
20124 #endif
20125 }
20126 break;
20127 case DLL_THREAD_DETACH:
20128 break;
20129 default:
20130 break;
20131 }
20132 return TRUE;
20133 }
20134
20135 /**
20136 * DLL entry point for WIN32.
20137 * @param hinst instance handle
20138 * @param reason reason code for entry point
20139 * @param reserved
20140 * @result always true
20141 */
20142
20143 int __stdcall
DllMain(HANDLE hinst,DWORD reason,LPVOID reserved)20144 DllMain(HANDLE hinst, DWORD reason, LPVOID reserved)
20145 {
20146 return LibMain(hinst, reason, reserved);
20147 }
20148
20149 #ifndef WITHOUT_INSTALLER
20150
20151 /**
20152 * Handler for driver installer/uninstaller error messages.
20153 * @param name name of API function for which to show error messages
20154 * @result true when error message retrieved
20155 */
20156
20157 static BOOL
InUnError(char * name)20158 InUnError(char *name)
20159 {
20160 WORD err = 1;
20161 DWORD code;
20162 char errmsg[301];
20163 WORD errlen, errmax = sizeof (errmsg) - 1;
20164 int sqlret;
20165 BOOL ret = FALSE;
20166
20167 do {
20168 errmsg[0] = '\0';
20169 sqlret = SQLInstallerError(err, &code, errmsg, errmax, &errlen);
20170 if (SQL_SUCCEEDED(sqlret)) {
20171 MessageBox(NULL, errmsg, name,
20172 MB_ICONSTOP | MB_OK | MB_TASKMODAL | MB_SETFOREGROUND);
20173 ret = TRUE;
20174 }
20175 err++;
20176 } while (sqlret != SQL_NO_DATA);
20177 return ret;
20178 }
20179
20180 /**
20181 * Built in driver installer/uninstaller.
20182 * @param remove true for uninstall
20183 * @param cmdline command line string of rundll32
20184 */
20185
20186 static BOOL
InUn(int remove,char * cmdline)20187 InUn(int remove, char *cmdline)
20188 {
20189 #ifdef SQLITE_HAS_CODEC
20190 static char *drivername = "SQLite3 ODBC Driver (SEE)";
20191 static char *dsname = "SQLite3 SEE Datasource";
20192 #else
20193 static char *drivername = "SQLite3 ODBC Driver";
20194 static char *dsname = "SQLite3 Datasource";
20195 #endif
20196 char *dllname, *p;
20197 char dllbuf[301], path[301], driver[300], attr[300], inst[400];
20198 WORD pathmax = sizeof (path) - 1, pathlen;
20199 DWORD usecnt, mincnt;
20200 int quiet = 0;
20201
20202 dllbuf[0] = '\0';
20203 GetModuleFileName(hModule, dllbuf, sizeof (dllbuf));
20204 p = strrchr(dllbuf, '\\');
20205 dllname = p ? (p + 1) : dllbuf;
20206 quiet = cmdline && strstr(cmdline, "quiet");
20207 if (SQLInstallDriverManager(path, pathmax, &pathlen)) {
20208 sprintf(driver, "%s;Driver=%s;Setup=%s;",
20209 drivername, dllname, dllname);
20210 p = driver;
20211 while (*p) {
20212 if (*p == ';') {
20213 *p = '\0';
20214 }
20215 ++p;
20216 }
20217 usecnt = 0;
20218 path[0] = '\0';
20219 SQLInstallDriverEx(driver, NULL, path, pathmax, NULL,
20220 ODBC_INSTALL_INQUIRY, &usecnt);
20221 pathlen = strlen(path);
20222 while (pathlen > 0 && path[pathlen - 1] == '\\') {
20223 --pathlen;
20224 path[pathlen] = '\0';
20225 }
20226 sprintf(driver, "%s;Driver=%s\\%s;Setup=%s\\%s;",
20227 drivername, path, dllname, path, dllname);
20228 p = driver;
20229 while (*p) {
20230 if (*p == ';') {
20231 *p = '\0';
20232 }
20233 ++p;
20234 }
20235 sprintf(inst, "%s\\%s", path, dllname);
20236 if (!remove && usecnt > 0) {
20237 /* first install try: copy over driver dll, keeping DSNs */
20238 if (GetFileAttributesA(dllbuf) != INVALID_FILE_ATTRIBUTES &&
20239 CopyFile(dllbuf, inst, 0)) {
20240 if (!quiet) {
20241 char buf[512];
20242
20243 sprintf(buf, "%s replaced.", drivername);
20244 MessageBox(NULL, buf, "Info",
20245 MB_ICONINFORMATION | MB_OK | MB_TASKMODAL |
20246 MB_SETFOREGROUND);
20247 }
20248 return TRUE;
20249 }
20250 }
20251 mincnt = remove ? 1 : 0;
20252 while (usecnt != mincnt) {
20253 if (!SQLRemoveDriver(driver, TRUE, &usecnt)) {
20254 break;
20255 }
20256 }
20257 if (remove) {
20258 if (usecnt && !SQLRemoveDriver(driver, TRUE, &usecnt)) {
20259 InUnError("SQLRemoveDriver");
20260 return FALSE;
20261 }
20262 if (!usecnt) {
20263 char buf[512];
20264
20265 DeleteFile(inst);
20266 if (!quiet) {
20267 sprintf(buf, "%s uninstalled.", drivername);
20268 MessageBox(NULL, buf, "Info",
20269 MB_ICONINFORMATION |MB_OK | MB_TASKMODAL |
20270 MB_SETFOREGROUND);
20271 }
20272 }
20273 sprintf(attr, "DSN=%s;Database=;", dsname);
20274 p = attr;
20275 while (*p) {
20276 if (*p == ';') {
20277 *p = '\0';
20278 }
20279 ++p;
20280 }
20281 SQLConfigDataSource(NULL, ODBC_REMOVE_SYS_DSN, drivername, attr);
20282 return TRUE;
20283 }
20284 if (GetFileAttributesA(dllbuf) == INVALID_FILE_ATTRIBUTES) {
20285 return FALSE;
20286 }
20287 if (strcasecmp(dllbuf, inst) != 0 && !CopyFile(dllbuf, inst, 0)) {
20288 char buf[512];
20289
20290 sprintf(buf, "Copy %s to %s failed.", dllbuf, inst);
20291 MessageBox(NULL, buf, "CopyFile",
20292 MB_ICONSTOP |MB_OK | MB_TASKMODAL | MB_SETFOREGROUND);
20293 return FALSE;
20294 }
20295 if (!SQLInstallDriverEx(driver, path, path, pathmax, &pathlen,
20296 ODBC_INSTALL_COMPLETE, &usecnt)) {
20297 InUnError("SQLInstallDriverEx");
20298 return FALSE;
20299 }
20300 sprintf(attr, "DSN=%s;Database=;", dsname);
20301 p = attr;
20302 while (*p) {
20303 if (*p == ';') {
20304 *p = '\0';
20305 }
20306 ++p;
20307 }
20308 SQLConfigDataSource(NULL, ODBC_REMOVE_SYS_DSN, drivername, attr);
20309 if (!SQLConfigDataSource(NULL, ODBC_ADD_SYS_DSN, drivername, attr)) {
20310 InUnError("SQLConfigDataSource");
20311 return FALSE;
20312 }
20313 if (!quiet) {
20314 char buf[512];
20315
20316 sprintf(buf, "%s installed.", drivername);
20317 MessageBox(NULL, buf, "Info",
20318 MB_ICONINFORMATION | MB_OK | MB_TASKMODAL |
20319 MB_SETFOREGROUND);
20320 }
20321 } else {
20322 InUnError("SQLInstallDriverManager");
20323 return FALSE;
20324 }
20325 return TRUE;
20326 }
20327
20328 /**
20329 * RunDLL32 entry point for driver installation.
20330 * @param hwnd window handle of caller
20331 * @param hinst of this DLL
20332 * @param lpszCmdLine rundll32 command line tail
20333 * @param nCmdShow ignored
20334 */
20335
20336 void CALLBACK
install(HWND hwnd,HINSTANCE hinst,LPSTR lpszCmdLine,int nCmdShow)20337 install(HWND hwnd, HINSTANCE hinst, LPSTR lpszCmdLine, int nCmdShow)
20338 {
20339 InUn(0, lpszCmdLine);
20340 }
20341
20342 /**
20343 * RunDLL32 entry point for driver uninstallation.
20344 * @param hwnd window handle of caller
20345 * @param hinst of this DLL
20346 * @param lpszCmdLine rundll32 command line tail
20347 * @param nCmdShow ignored
20348 */
20349
20350 void CALLBACK
uninstall(HWND hwnd,HINSTANCE hinst,LPSTR lpszCmdLine,int nCmdShow)20351 uninstall(HWND hwnd, HINSTANCE hinst, LPSTR lpszCmdLine, int nCmdShow)
20352 {
20353 InUn(1, lpszCmdLine);
20354 }
20355
20356 #endif /* WITHOUT_INSTALLER */
20357
20358 #ifndef WITHOUT_SHELL
20359
20360 /**
20361 * Setup argv vector from string
20362 * @param argcp pointer to argc
20363 * @param argvp pointer to argv
20364 * @param cmdline command line string
20365 * @param argv0 0th element for argv or NULL, must be static
20366 */
20367
20368 static void
setargv(int * argcp,char *** argvp,char * cmdline,char * argv0)20369 setargv(int *argcp, char ***argvp, char *cmdline, char *argv0)
20370 {
20371 char *p, *arg, *argspace, **argv;
20372 int argc, size, inquote, copy, slashes;
20373
20374 size = 2 + (argv0 ? 1 : 0);
20375 for (p = cmdline; *p != '\0'; p++) {
20376 if (ISSPACE(*p)) {
20377 size++;
20378 while (ISSPACE(*p)) {
20379 p++;
20380 }
20381 if (*p == '\0') {
20382 break;
20383 }
20384 }
20385 }
20386 argspace = malloc(size * sizeof (char *) + strlen(cmdline) + 1);
20387 argv = (char **) argspace;
20388 argspace += size * sizeof (char *);
20389 size--;
20390 argc = 0;
20391 if (argv0) {
20392 argv[argc++] = argv0;
20393 }
20394 p = cmdline;
20395 for (; argc < size; argc++) {
20396 argv[argc] = arg = argspace;
20397 while (ISSPACE(*p)) {
20398 p++;
20399 }
20400 if (*p == '\0') {
20401 break;
20402 }
20403 inquote = 0;
20404 slashes = 0;
20405 while (1) {
20406 copy = 1;
20407 while (*p == '\\') {
20408 slashes++;
20409 p++;
20410 }
20411 if (*p == '"') {
20412 if ((slashes & 1) == 0) {
20413 copy = 0;
20414 if (inquote && p[1] == '"') {
20415 p++;
20416 copy = 1;
20417 } else {
20418 inquote = !inquote;
20419 }
20420 }
20421 slashes >>= 1;
20422 }
20423 while (slashes) {
20424 *arg = '\\';
20425 arg++;
20426 slashes--;
20427 }
20428 if (*p == '\0' || (!inquote && ISSPACE(*p))) {
20429 break;
20430 }
20431 if (copy != 0) {
20432 *arg = *p;
20433 arg++;
20434 }
20435 p++;
20436 }
20437 *arg = '\0';
20438 argspace = arg + 1;
20439 }
20440 argv[argc] = 0;
20441 *argcp = argc;
20442 *argvp = argv;
20443 }
20444
20445 /**
20446 * RunDLL32 entry point for SQLite shell
20447 * @param hwnd window handle of caller
20448 * @param hinst of this DLL
20449 * @param lpszCmdLine rundll32 command line tail
20450 * @param nCmdShow ignored
20451 */
20452
20453 void CALLBACK
shell(HWND hwnd,HINSTANCE hinst,LPSTR lpszCmdLine,int nCmdShow)20454 shell(HWND hwnd, HINSTANCE hinst, LPSTR lpszCmdLine, int nCmdShow)
20455 {
20456 int argc, needcon = 0;
20457 char **argv;
20458 extern int sqlite3_main(int, char **);
20459 static const char *name = "SQLite3 Shell";
20460 DWORD ftype0, ftype1, ftype2;
20461
20462 ftype0 = GetFileType(GetStdHandle(STD_INPUT_HANDLE));
20463 ftype1 = GetFileType(GetStdHandle(STD_OUTPUT_HANDLE));
20464 ftype2 = GetFileType(GetStdHandle(STD_ERROR_HANDLE));
20465 if (ftype0 != FILE_TYPE_DISK && ftype0 != FILE_TYPE_CHAR &&
20466 ftype0 != FILE_TYPE_PIPE) {
20467 fclose(stdin);
20468 ++needcon;
20469 ftype0 = FILE_TYPE_UNKNOWN;
20470 }
20471 if (ftype1 != FILE_TYPE_DISK && ftype1 != FILE_TYPE_CHAR &&
20472 ftype1 != FILE_TYPE_PIPE) {
20473 fclose(stdout);
20474 ++needcon;
20475 ftype1 = FILE_TYPE_UNKNOWN;
20476 }
20477 if (ftype2 != FILE_TYPE_DISK && ftype2 != FILE_TYPE_CHAR &&
20478 ftype2 != FILE_TYPE_PIPE) {
20479 fclose(stderr);
20480 ++needcon;
20481 ftype2 = FILE_TYPE_UNKNOWN;
20482 }
20483 if (needcon > 0) {
20484 AllocConsole();
20485 SetConsoleTitle(name);
20486 }
20487 if (ftype0 == FILE_TYPE_UNKNOWN) {
20488 freopen("CONIN$", "r", stdin);
20489 }
20490 if (ftype1 == FILE_TYPE_UNKNOWN) {
20491 freopen("CONOUT$", "w", stdout);
20492 }
20493 if (ftype2 == FILE_TYPE_UNKNOWN) {
20494 freopen("CONOUT$", "w", stderr);
20495 }
20496 setargv(&argc, &argv, lpszCmdLine, (char *) name);
20497 #if defined(ENABLE_NVFS) && (ENABLE_NVFS)
20498 nvfs_init();
20499 #endif
20500 sqlite3_main(argc, argv);
20501 }
20502
20503 #endif /* WITHOUT_SHELL */
20504
20505 #endif /* _WIN32 || _WIN64 */
20506
20507 #if defined(HAVE_ODBCINSTEXT_H) && (HAVE_ODBCINSTEXT_H)
20508
20509 /*
20510 * unixODBC property page for this driver,
20511 * may or may not work depending on unixODBC version.
20512 */
20513
20514 #include <odbcinstext.h>
20515
20516 int
ODBCINSTGetProperties(HODBCINSTPROPERTY prop)20517 ODBCINSTGetProperties(HODBCINSTPROPERTY prop)
20518 {
20519 static const char *instYN[] = { "No", "Yes", NULL };
20520 static const char *syncPragma[] = { "NORMAL", "OFF", "FULL", NULL };
20521 static const char *jmPragma[] = {
20522 "DELETE", "PERSIST", "OFF", "TRUNCATE", "MEMORY", "WAL", NULL
20523 };
20524
20525 prop->pNext = (HODBCINSTPROPERTY) malloc(sizeof (ODBCINSTPROPERTY));
20526 prop = prop->pNext;
20527 memset(prop, 0, sizeof (ODBCINSTPROPERTY));
20528 prop->nPromptType = ODBCINST_PROMPTTYPE_FILENAME;
20529 strncpy(prop->szName, "Database", INI_MAX_PROPERTY_NAME);
20530 strncpy(prop->szValue, "", INI_MAX_PROPERTY_VALUE);
20531 prop->pNext = (HODBCINSTPROPERTY) malloc(sizeof (ODBCINSTPROPERTY));
20532 prop = prop->pNext;
20533 memset(prop, 0, sizeof (ODBCINSTPROPERTY));
20534 prop->nPromptType = ODBCINST_PROMPTTYPE_TEXTEDIT;
20535 strncpy(prop->szName, "Timeout", INI_MAX_PROPERTY_NAME);
20536 strncpy(prop->szValue, "100000", INI_MAX_PROPERTY_VALUE);
20537 prop->pNext = (HODBCINSTPROPERTY) malloc(sizeof (ODBCINSTPROPERTY));
20538 prop = prop->pNext;
20539 memset(prop, 0, sizeof (ODBCINSTPROPERTY));
20540 prop->nPromptType = ODBCINST_PROMPTTYPE_COMBOBOX;
20541 prop->aPromptData = malloc(sizeof (instYN));
20542 memcpy(prop->aPromptData, instYN, sizeof (instYN));
20543 strncpy(prop->szName, "StepAPI", INI_MAX_PROPERTY_NAME);
20544 strncpy(prop->szValue, "No", INI_MAX_PROPERTY_VALUE);
20545 prop->pNext = (HODBCINSTPROPERTY) malloc(sizeof (ODBCINSTPROPERTY));
20546 prop = prop->pNext;
20547 memset(prop, 0, sizeof (ODBCINSTPROPERTY));
20548 prop->nPromptType = ODBCINST_PROMPTTYPE_COMBOBOX;
20549 prop->aPromptData = malloc(sizeof (instYN));
20550 memcpy(prop->aPromptData, instYN, sizeof (instYN));
20551 strncpy(prop->szName, "ShortNames", INI_MAX_PROPERTY_NAME);
20552 strncpy(prop->szValue, "No", INI_MAX_PROPERTY_VALUE);
20553 prop->pNext = (HODBCINSTPROPERTY) malloc(sizeof (ODBCINSTPROPERTY));
20554 prop = prop->pNext;
20555 memset(prop, 0, sizeof (ODBCINSTPROPERTY));
20556 prop->nPromptType = ODBCINST_PROMPTTYPE_COMBOBOX;
20557 prop->aPromptData = malloc(sizeof (instYN));
20558 memcpy(prop->aPromptData, instYN, sizeof (instYN));
20559 strncpy(prop->szName, "LongNames", INI_MAX_PROPERTY_NAME);
20560 strncpy(prop->szValue, "No", INI_MAX_PROPERTY_VALUE);
20561 prop->pNext = (HODBCINSTPROPERTY) malloc(sizeof (ODBCINSTPROPERTY));
20562 memset(prop, 0, sizeof (ODBCINSTPROPERTY));
20563 prop->nPromptType = ODBCINST_PROMPTTYPE_COMBOBOX;
20564 prop->aPromptData = malloc(sizeof (instYN));
20565 memcpy(prop->aPromptData, instYN, sizeof (instYN));
20566 strncpy(prop->szName, "NoCreat", INI_MAX_PROPERTY_NAME);
20567 strncpy(prop->szValue, "No", INI_MAX_PROPERTY_VALUE);
20568 #ifdef WINTERFACE
20569 prop->pNext = (HODBCINSTPROPERTY) malloc(sizeof (ODBCINSTPROPERTY));
20570 memset(prop, 0, sizeof (ODBCINSTPROPERTY));
20571 prop->nPromptType = ODBCINST_PROMPTTYPE_COMBOBOX;
20572 prop->aPromptData = malloc(sizeof (instYN));
20573 memcpy(prop->aPromptData, instYN, sizeof (instYN));
20574 strncpy(prop->szName, "NoWCHAR", INI_MAX_PROPERTY_NAME);
20575 strncpy(prop->szValue, "No", INI_MAX_PROPERTY_VALUE);
20576 #endif
20577 prop->pNext = (HODBCINSTPROPERTY) malloc(sizeof (ODBCINSTPROPERTY));
20578 memset(prop, 0, sizeof (ODBCINSTPROPERTY));
20579 prop->nPromptType = ODBCINST_PROMPTTYPE_COMBOBOX;
20580 prop->aPromptData = malloc(sizeof (instYN));
20581 memcpy(prop->aPromptData, instYN, sizeof (instYN));
20582 strncpy(prop->szName, "FKSupport", INI_MAX_PROPERTY_NAME);
20583 strncpy(prop->szValue, "No", INI_MAX_PROPERTY_VALUE);
20584 prop->pNext = (HODBCINSTPROPERTY) malloc(sizeof (ODBCINSTPROPERTY));
20585 prop = prop->pNext;
20586 memset(prop, 0, sizeof (ODBCINSTPROPERTY));
20587 prop->nPromptType = ODBCINST_PROMPTTYPE_COMBOBOX;
20588 prop->aPromptData = malloc(sizeof (syncPragma));
20589 memcpy(prop->aPromptData, syncPragma, sizeof (syncPragma));
20590 strncpy(prop->szName, "SyncPragma", INI_MAX_PROPERTY_NAME);
20591 strncpy(prop->szValue, "NORMAL", INI_MAX_PROPERTY_VALUE);
20592 prop->pNext = (HODBCINSTPROPERTY) malloc(sizeof (ODBCINSTPROPERTY));
20593 prop = prop->pNext;
20594 memset(prop, 0, sizeof (ODBCINSTPROPERTY));
20595 prop->nPromptType = ODBCINST_PROMPTTYPE_COMBOBOX;
20596 prop->aPromptData = malloc(sizeof (jmPragma));
20597 memcpy(prop->aPromptData, jmPragma, sizeof (jmPragma));
20598 strncpy(prop->szName, "JournalMode", INI_MAX_PROPERTY_NAME);
20599 strncpy(prop->szValue, "DELETE", INI_MAX_PROPERTY_VALUE);
20600 prop->pNext = (HODBCINSTPROPERTY) malloc(sizeof (ODBCINSTPROPERTY));
20601 prop = prop->pNext;
20602 memset(prop, 0, sizeof (ODBCINSTPROPERTY));
20603 prop->nPromptType = ODBCINST_PROMPTTYPE_TEXTEDIT;
20604 strncpy(prop->szName, "LoadExt", INI_MAX_PROPERTY_NAME);
20605 strncpy(prop->szValue, "", INI_MAX_PROPERTY_VALUE);
20606 prop->pNext = (HODBCINSTPROPERTY) malloc(sizeof (ODBCINSTPROPERTY));
20607 memset(prop, 0, sizeof (ODBCINSTPROPERTY));
20608 prop->nPromptType = ODBCINST_PROMPTTYPE_COMBOBOX;
20609 prop->aPromptData = malloc(sizeof (instYN));
20610 memcpy(prop->aPromptData, instYN, sizeof (instYN));
20611 strncpy(prop->szName, "BigInt", INI_MAX_PROPERTY_NAME);
20612 strncpy(prop->szValue, "No", INI_MAX_PROPERTY_VALUE);
20613 return 1;
20614 }
20615
20616 #endif /* HAVE_ODBCINSTEXT_H */
20617
20618 #ifdef SQLITE_DYNLOAD
20619
20620 /*
20621 * SQLite3 shared library/DLL stubs.
20622 */
20623
20624 static void
dls_void(void)20625 dls_void(void)
20626 {
20627 }
20628
20629 static int
dls_error(void)20630 dls_error(void)
20631 {
20632 return SQLITE_ERROR;
20633 }
20634
20635 static int
dls_0(void)20636 dls_0(void)
20637 {
20638 return 0;
20639 }
20640
20641 static sqlite_int64
dls_0LL(void)20642 dls_0LL(void)
20643 {
20644 return 0;
20645 }
20646
20647 static double
dls_00(void)20648 dls_00(void)
20649 {
20650 return 0;
20651 }
20652
20653 static void *
dls_null(void)20654 dls_null(void)
20655 {
20656 return NULL;
20657 }
20658
20659 static const char *
dls_empty(void)20660 dls_empty(void)
20661 {
20662 return "";
20663 }
20664
20665 static int
dls_snull(void)20666 dls_snull(void)
20667 {
20668 return SQLITE_NULL;
20669 }
20670
20671 #define DLS_ENT(name, func) \
20672 { "sqlite3_" #name, offsetof(struct dl_sqlite3_funcs, name), \
20673 (void *) func }
20674
20675 #define DLS_ENT3(name, off, func) \
20676 { "sqlite3_" #name, offsetof(struct dl_sqlite3_funcs, off), \
20677 (void *) func }
20678
20679 #define DLS_END { NULL, 0, NULL }
20680
20681 static struct {
20682 const char *name;
20683 int offset;
20684 void *func;
20685 } dls_nametab[] = {
20686 DLS_ENT(activate_see, dls_void),
20687 DLS_ENT(bind_blob, dls_error),
20688 DLS_ENT(bind_double, dls_error),
20689 DLS_ENT(bind_int, dls_error),
20690 DLS_ENT(bind_int64, dls_error),
20691 DLS_ENT(bind_null, dls_error),
20692 DLS_ENT(bind_parameter_count, dls_0),
20693 DLS_ENT(bind_text, dls_error),
20694 DLS_ENT(busy_handler, dls_error),
20695 DLS_ENT(changes, dls_0),
20696 DLS_ENT(close, dls_error),
20697 DLS_ENT(column_blob, dls_null),
20698 DLS_ENT(column_bytes, dls_0),
20699 DLS_ENT(column_count, dls_0),
20700 DLS_ENT(column_database_name, dls_empty),
20701 DLS_ENT(column_decltype, dls_empty),
20702 DLS_ENT(column_double, dls_00),
20703 DLS_ENT(column_name, dls_empty),
20704 DLS_ENT(column_origin_name, dls_null),
20705 DLS_ENT(column_table_name, dls_null),
20706 DLS_ENT(column_text, dls_null),
20707 DLS_ENT(column_type, dls_snull),
20708 DLS_ENT(create_function, dls_error),
20709 DLS_ENT(enable_load_extension, dls_error),
20710 DLS_ENT(errcode, dls_error),
20711 DLS_ENT(errmsg, dls_empty),
20712 DLS_ENT(exec, dls_error),
20713 DLS_ENT(finalize, dls_error),
20714 DLS_ENT(free, free),
20715 DLS_ENT(free_table, dls_void),
20716 DLS_ENT(get_table, dls_error),
20717 DLS_ENT(interrupt, dls_void),
20718 DLS_ENT(key, dls_error),
20719 DLS_ENT(last_insert_rowid, dls_0LL),
20720 DLS_ENT(libversion, dls_empty),
20721 DLS_ENT(load_extension, dls_error),
20722 DLS_ENT(malloc, malloc),
20723 DLS_ENT(mprintf, dls_null),
20724 DLS_ENT(open, dls_error),
20725 DLS_ENT(open16, dls_error),
20726 DLS_ENT(open_v2, dls_error),
20727 DLS_ENT(prepare, dls_error),
20728 DLS_ENT(prepare_v2, dls_error),
20729 DLS_ENT(profile, dls_null),
20730 DLS_ENT(realloc, realloc),
20731 DLS_ENT(rekey, dls_error),
20732 DLS_ENT(reset, dls_error),
20733 DLS_ENT(result_blob, dls_void),
20734 DLS_ENT(result_error, dls_void),
20735 DLS_ENT(result_int, dls_void),
20736 DLS_ENT(result_null, dls_void),
20737 DLS_ENT(step, dls_error),
20738 #if defined(_WIN32) || defined(_WIN64)
20739 DLS_ENT3(strnicmp, xstrnicmp, _strnicmp),
20740 #else
20741 DLS_ENT3(strnicmp, xstrnicmp, strncasecmp),
20742 #endif
20743 DLS_ENT(table_column_metadata, dls_error),
20744 DLS_ENT(trace, dls_null),
20745 DLS_ENT(user_data, dls_null),
20746 DLS_ENT(value_blob, dls_null),
20747 DLS_ENT(value_bytes, dls_0),
20748 DLS_ENT(value_text, dls_empty),
20749 DLS_ENT(value_type, dls_snull),
20750 DLS_END
20751 };
20752
20753 #if defined(_WIN32) || defined(_WIN64)
20754
20755 static HMODULE sqlite3_dll = 0;
20756
20757 static void
dls_init(void)20758 dls_init(void)
20759 {
20760 int i;
20761 static const char *dll_names[] = {
20762 "System.Data.SQLite.dll",
20763 "sqlite3.dll",
20764 NULL,
20765 };
20766
20767 i = 0;
20768 while (dll_names[i]) {
20769 sqlite3_dll = LoadLibrary(dll_names[i]);
20770 if (sqlite3_dll) {
20771 break;
20772 }
20773 ++i;
20774 }
20775 i = 0;
20776 while (dls_nametab[i].name) {
20777 void *func = 0, **loc;
20778
20779 if (sqlite3_dll) {
20780 func = (void *) GetProcAddress(sqlite3_dll, dls_nametab[i].name);
20781 }
20782 if (!func) {
20783 func = dls_nametab[i].func;
20784 }
20785 loc = (void **) ((char *) &dls_funcs + dls_nametab[i].offset);
20786 *loc = func;
20787 ++i;
20788 }
20789 if (!sqlite3_dll) {
20790 char buf[MAXPATHLEN], msg[MAXPATHLEN];
20791
20792 LoadString(hModule, IDS_DRVTITLE, buf, sizeof (buf));
20793 LoadString(hModule, IDS_DLLERR, msg, sizeof (msg));
20794 MessageBox(NULL, msg, buf,
20795 MB_ICONEXCLAMATION | MB_OK | MB_TASKMODAL |
20796 MB_SETFOREGROUND);
20797 }
20798 }
20799
20800 static void
dls_fini(void)20801 dls_fini(void)
20802 {
20803 if (sqlite3_dll) {
20804 FreeLibrary(sqlite3_dll);
20805 sqlite3_dll = 0;
20806 }
20807 }
20808
20809 #else
20810
20811 #include <dlfcn.h>
20812
20813 static void *libsqlite3_so = 0;
20814
20815 void
dls_init(void)20816 dls_init(void)
20817 {
20818 int i;
20819
20820 libsqlite3_so = dlopen("libsqlite3.so.0", RTLD_NOW | RTLD_GLOBAL);
20821 i = 0;
20822 while (dls_nametab[i].name) {
20823 void *func = 0, **loc;
20824
20825 if (libsqlite3_so) {
20826 func = dlsym(libsqlite3_so, dls_nametab[i].name);
20827 }
20828 if (!func) {
20829 func = dls_nametab[i].func;
20830 }
20831 loc = (void **) ((char *) &dls_funcs + dls_nametab[i].offset);
20832 *loc = func;
20833 ++i;
20834 }
20835 if (!libsqlite3_so) {
20836 const char errmsg[] = "SQLite3 shared library not found.\n";
20837
20838 write(2, errmsg, sizeof (errmsg) - 1);
20839 }
20840 }
20841
20842 void
dls_fini(void)20843 dls_fini(void)
20844 {
20845 if (libsqlite3_so) {
20846 dlclose(libsqlite3_so);
20847 libsqlite3_so = 0;
20848 }
20849 }
20850
20851 #endif
20852
20853 #endif
20854
20855 /*
20856 * Local Variables:
20857 * mode: c
20858 * c-basic-offset: 4
20859 * fill-column: 78
20860 * tab-width: 8
20861 * End:
20862 */
20863