1 /**
2 * @file sqlite3odbc.c
3 * SQLite3 ODBC Driver main module.
4 *
5 * $Id: sqlite3odbc.c,v 1.136 2011/11/12 04:35:40 chw Exp chw $
6 *
7 * Copyright (c) 2004-2011 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 #endif
23
24 #include "sqlite3odbc.h"
25
26 #ifdef SQLITE_DYNLOAD
27
28 #undef MEMORY_DEBUG
29
30 #if defined(_WIN32) || defined(_WIN64)
31 static void dls_init(void);
32 static void dls_fini(void);
33 #else
34 void dls_init(void);
35 void dls_fini(void);
36 #endif
37
38 static struct dl_sqlite3_funcs {
39 void (*activate_see)(const char *p0);
40 int (*bind_blob)(sqlite3_stmt *p0, int p1, const void *p2, int p3,
41 void (*p4)(void *));
42 int (*bind_double)(sqlite3_stmt *p0, int p1, double p2);
43 int (*bind_int)(sqlite3_stmt *p0, int p1, int p2);
44 int (*bind_int64)(sqlite3_stmt *p0, int p1, sqlite3_int64 p2);
45 int (*bind_null)(sqlite3_stmt *p0, int p1);
46 int (*bind_parameter_count)(sqlite3_stmt *p0);
47 int (*bind_text)(sqlite3_stmt *p0, int p1, const char *p2, int p3,
48 void (*p4)(void *));
49 int (*busy_handler)(sqlite3 *p0, int (*p2)(void *, int), void *p3);
50 int (*changes)(sqlite3 *p0);
51 int (*close)(sqlite3 *p0);
52 const void * (*column_blob)(sqlite3_stmt *p0, int p1);
53 int (*column_bytes)(sqlite3_stmt *p0, int p1);
54 int (*column_count)(sqlite3_stmt *p0);
55 const char * (*column_database_name)(sqlite3_stmt *p0, int p1);
56 const char * (*column_decltype)(sqlite3_stmt *p0, int p1);
57 const char * (*column_name)(sqlite3_stmt *p0, int p1);
58 const char * (*column_origin_name)(sqlite3_stmt *p0, int p1);
59 const char * (*column_table_name)(sqlite3_stmt *p0, int p1);
60 const unsigned char * (*column_text)(sqlite3_stmt *p0, int p1);
61 int (*column_type)(sqlite3_stmt *p0, int p1);
62 int (*create_function)(sqlite3 *p0, const char *p1, int p2, int p3,
63 void *p4,
64 void (*p5)(sqlite3_context *, int, sqlite3_value **),
65 void (*p6)(sqlite3_context *, int, sqlite3_value **),
66 void (*p7)(sqlite3_context *));
67 int (*enable_load_extension)(sqlite3 *p0, int p1);
68 int (*errcode)(sqlite3 *p0);
69 const char * (*errmsg)(sqlite3 *p0);
70 int (*exec)(sqlite3 *p0, const char *p1,
71 int (*p2)(void *, int, char **, char **),
72 void *p3, char **p4);
73 int (*finalize)(sqlite3_stmt *p0);
74 void (*free)(void *p0);
75 void (*free_table)(char **p0);
76 int (*get_table)(sqlite3 *p0, const char *p1, char ***p2,
77 int *p3, int *p4, char **p5);
78 void (*interrupt)(sqlite3 *p0);
79 int (*key)(sqlite3 *p0, const void *p1, int p2);
80 const char * (*libversion)(void);
81 int (*load_extension)(sqlite3 *p0, const char *p1, const char *p2,
82 char **p3);
83 void * (*malloc)(int p0);
84 char * (*mprintf)(const char *p0, ...);
85 int (*open)(const char *p0, sqlite3 **p1);
86 int (*open16)(const void *p0, sqlite3 **p1);
87 int (*open_v2)(const char *p0, sqlite3 **p1, int p2, const char *p3);
88 int (*prepare)(sqlite3 *p0, const char *p1, int p2, sqlite3_stmt **p3,
89 const char **p4);
90 int (*prepare_v2)(sqlite3 *p0, const char *p1, int p2, sqlite3_stmt **p3,
91 const char **p4);
92 void * (*profile)(sqlite3 *p0,
93 void (*p1)(void *, const char *, sqlite3_uint64),
94 void *p2);
95 void * (*realloc)(void *p0, int p1);
96 int (*rekey)(sqlite3 *p0, const void *p1, int p2);
97 int (*reset)(sqlite3_stmt *p0);
98 void (*result_blob)(sqlite3_context *p0, const void *p1,
99 int p2, void (*p3)(void *));
100 void (*result_error)(sqlite3_context *p0, const char *p1, int p2);
101 void (*result_int)(sqlite3_context *p0, int p1);
102 void (*result_null)(sqlite3_context *p0);
103 int (*step)(sqlite3_stmt *p0);
104 int (*xstrnicmp)(const char *p0, const char *p1, int p2);
105 int (*table_column_metadata)(sqlite3 *p0, const char *p1,
106 const char *p2, const char *p3,
107 char const **p4, char const **p5,
108 int *p6, int *p7, int *p8);
109 void * (*trace)(sqlite3 *p0, void (*p1)(void *, const char *), void *p2);
110 void * (*user_data)(sqlite3_context *p0);
111 const void * (*value_blob)(sqlite3_value *p0);
112 int (*value_bytes)(sqlite3_value *p0);
113 const unsigned char * (*value_text)(sqlite3_value *p0);
114 int (*value_type)(sqlite3_value *p0);
115 } dls_funcs;
116
117 #define sqlite3_activate_see dls_funcs.activate_see
118 #define sqlite3_bind_blob dls_funcs.bind_blob
119 #define sqlite3_bind_double dls_funcs.bind_double
120 #define sqlite3_bind_int dls_funcs.bind_int
121 #define sqlite3_bind_int64 dls_funcs.bind_int64
122 #define sqlite3_bind_null dls_funcs.bind_null
123 #define sqlite3_bind_parameter_count dls_funcs.bind_parameter_count
124 #define sqlite3_bind_text dls_funcs.bind_text
125 #define sqlite3_busy_handler dls_funcs.busy_handler
126 #define sqlite3_changes dls_funcs.changes
127 #define sqlite3_close dls_funcs.close
128 #define sqlite3_column_blob dls_funcs.column_blob
129 #define sqlite3_column_bytes dls_funcs.column_bytes
130 #define sqlite3_column_count dls_funcs.column_count
131 #define sqlite3_column_database_name dls_funcs.column_database_name
132 #define sqlite3_column_decltype dls_funcs.column_decltype
133 #define sqlite3_column_name dls_funcs.column_name
134 #define sqlite3_column_origin_name dls_funcs.column_origin_name
135 #define sqlite3_column_table_name dls_funcs.column_table_name
136 #define sqlite3_column_text dls_funcs.column_text
137 #define sqlite3_column_type dls_funcs.column_type
138 #define sqlite3_create_function dls_funcs.create_function
139 #define sqlite3_enable_load_extension dls_funcs.enable_load_extension
140 #define sqlite3_errcode dls_funcs.errcode
141 #define sqlite3_errmsg dls_funcs.errmsg
142 #define sqlite3_exec dls_funcs.exec
143 #define sqlite3_finalize dls_funcs.finalize
144 #define sqlite3_free dls_funcs.free
145 #define sqlite3_free_table dls_funcs.free_table
146 #define sqlite3_get_table dls_funcs.get_table
147 #define sqlite3_interrupt dls_funcs.interrupt
148 #define sqlite3_key dls_funcs.key
149 #define sqlite3_libversion dls_funcs.libversion
150 #define sqlite3_load_extension dls_funcs.load_extension
151 #define sqlite3_malloc dls_funcs.malloc
152 #define sqlite3_mprintf dls_funcs.mprintf
153 #define sqlite3_open dls_funcs.open
154 #define sqlite3_open16 dls_funcs.open16
155 #define sqlite3_open_v2 dls_funcs.open_v2
156 #define sqlite3_prepare dls_funcs.prepare
157 #define sqlite3_prepare_v2 dls_funcs.prepare_v2
158 #define sqlite3_profile dls_funcs.profile
159 #define sqlite3_realloc dls_funcs.realloc
160 #define sqlite3_rekey dls_funcs.rekey
161 #define sqlite3_reset dls_funcs.reset
162 #define sqlite3_result_blob dls_funcs.result_blob
163 #define sqlite3_result_error dls_funcs.result_error
164 #define sqlite3_result_int dls_funcs.result_int
165 #define sqlite3_result_null dls_funcs.result_null
166 #define sqlite3_step dls_funcs.step
167 #define sqlite3_strnicmp dls_funcs.xstrnicmp
168 #define sqlite3_table_column_metadata dls_funcs.table_column_metadata
169 #define sqlite3_trace dls_funcs.trace
170 #define sqlite3_user_data dls_funcs.user_data
171 #define sqlite3_value_blob dls_funcs.value_blob
172 #define sqlite3_value_bytes dls_funcs.value_bytes
173 #define sqlite3_value_text dls_funcs.value_text
174 #define sqlite3_value_type dls_funcs.value_type
175
176 #endif
177
178 #ifndef WITHOUT_WINTERFACE
179 #define WINTERFACE
180 #define WCHARSUPPORT
181 #endif
182
183 #if !defined(_WIN32) && !defined(_WIN64)
184 #if !defined(WCHARSUPPORT) && defined(HAVE_SQLWCHAR) && (HAVE_SQLWCHAR)
185 #define WCHARSUPPORT
186 #endif
187 #endif
188
189 #if defined(WINTERFACE)
190 #include <sqlucode.h>
191 #endif
192
193 #if defined(_WIN32) || defined(_WIN64)
194 #include "resource3.h"
195 #define ODBC_INI "ODBC.INI"
196 #ifndef DRIVER_VER_INFO
197 #define DRIVER_VER_INFO VERSION
198 #endif
199 #else
200 #define ODBC_INI ".odbc.ini"
201 #endif
202
203 #ifndef DRIVER_VER_INFO
204 #define DRIVER_VER_INFO "0.0"
205 #endif
206
207 #ifndef COLATTRIBUTE_LAST_ARG_TYPE
208 #ifdef _WIN64
209 #define COLATTRIBUTE_LAST_ARG_TYPE SQLLEN *
210 #else
211 #define COLATTRIBUTE_LAST_ARG_TYPE SQLPOINTER
212 #endif
213 #endif
214
215 #ifndef SETSTMTOPTION_LAST_ARG_TYPE
216 #define SETSTMTOPTION_LAST_ARG_TYPE SQLROWCOUNT
217 #endif
218
219 #undef min
220 #define min(a, b) ((a) < (b) ? (a) : (b))
221 #undef max
222 #define max(a, b) ((a) < (b) ? (b) : (a))
223
224 #ifndef PTRDIFF_T
225 #define PTRDIFF_T int
226 #endif
227
228 #define array_size(x) (sizeof (x) / sizeof (x[0]))
229
230 #define stringify1(s) #s
231 #define stringify(s) stringify1(s)
232
233 #define verinfo(maj, min, lev) ((maj) << 16 | (min) << 8 | (lev))
234
235 /* Column types for static string column descriptions (SQLTables etc.) */
236
237 #if defined(WINTERFACE) && !defined(_WIN32) && !defined(_WIN64)
238 #define SCOL_VARCHAR SQL_WVARCHAR
239 #define SCOL_CHAR SQL_WCHAR
240 #else
241 #define SCOL_VARCHAR SQL_VARCHAR
242 #define SCOL_CHAR SQL_CHAR
243 #endif
244
245 #define ENV_MAGIC 0x53544145
246 #define DBC_MAGIC 0x53544144
247 #define DEAD_MAGIC 0xdeadbeef
248
249 static const char *xdigits = "0123456789ABCDEFabcdef";
250
251 #ifdef MEMORY_DEBUG
252
253 static void *
xmalloc_(int n,char * file,int line)254 xmalloc_(int n, char *file, int line)
255 {
256 int nn = n + 4 * sizeof (long);
257 long *p;
258
259 p = malloc(nn);
260 if (!p) {
261 #if (MEMORY_DEBUG > 1)
262 fprintf(stderr, "malloc\t%d\tNULL\t%s:%d\n", n, file, line);
263 #endif
264 return NULL;
265 }
266 p[0] = 0xdead1234;
267 nn = nn / sizeof (long) - 1;
268 p[1] = n;
269 p[nn] = 0xdead5678;
270 #if (MEMORY_DEBUG > 1)
271 fprintf(stderr, "malloc\t%d\t%p\t%s:%d\n", n, &p[2], file, line);
272 #endif
273 return (void *) &p[2];
274 }
275
276 static void *
xrealloc_(void * old,int n,char * file,int line)277 xrealloc_(void *old, int n, char *file, int line)
278 {
279 int nn = n + 4 * sizeof (long), nnn;
280 long *p, *pp;
281
282 if (n == 0 || !old) {
283 return xmalloc_(n, file, line);
284 }
285 p = &((long *) old)[-2];
286 if (p[0] != 0xdead1234) {
287 fprintf(stderr, "*** low end corruption @ %p\n", old);
288 abort();
289 }
290 nnn = p[1] + 4 * sizeof (long);
291 nnn = nnn / sizeof (long) - 1;
292 if (p[nnn] != 0xdead5678) {
293 fprintf(stderr, "*** high end corruption @ %p\n", old);
294 abort();
295 }
296 pp = realloc(p, nn);
297 if (!pp) {
298 #if (MEMORY_DEBUG > 1)
299 fprintf(stderr, "realloc\t%p,%d\tNULL\t%s:%d\n", old, n, file, line);
300 #endif
301 return NULL;
302 }
303 #if (MEMORY_DEBUG > 1)
304 fprintf(stderr, "realloc\t%p,%d\t%p\t%s:%d\n", old, n, &pp[2], file, line);
305 #endif
306 p = pp;
307 p[1] = n;
308 nn = nn / sizeof (long) - 1;
309 p[nn] = 0xdead5678;
310 return (void *) &p[2];
311 }
312
313 static void
xfree_(void * x,char * file,int line)314 xfree_(void *x, char *file, int line)
315 {
316 long *p;
317 int n;
318
319 if (!x) {
320 return;
321 }
322 p = &((long *) x)[-2];
323 if (p[0] != 0xdead1234) {
324 fprintf(stderr, "*** low end corruption @ %p\n", x);
325 abort();
326 }
327 n = p[1] + 4 * sizeof (long);
328 n = n / sizeof (long) - 1;
329 if (p[n] != 0xdead5678) {
330 fprintf(stderr, "*** high end corruption @ %p\n", x);
331 abort();
332 }
333 #if (MEMORY_DEBUG > 1)
334 fprintf(stderr, "free\t%p\t\t%s:%d\n", x, file, line);
335 #endif
336 free(p);
337 }
338
339 static void
xfree__(void * x)340 xfree__(void *x)
341 {
342 xfree_(x, "unknown location", 0);
343 }
344
345 static char *
xstrdup_(const char * str,char * file,int line)346 xstrdup_(const char *str, char *file, int line)
347 {
348 char *p;
349
350 if (!str) {
351 #if (MEMORY_DEBUG > 1)
352 fprintf(stderr, "strdup\tNULL\tNULL\t%s:%d\n", file, line);
353 #endif
354 return NULL;
355 }
356 p = xmalloc_(strlen(str) + 1, file, line);
357 if (p) {
358 strcpy(p, str);
359 }
360 #if (MEMORY_DEBUG > 1)
361 fprintf(stderr, "strdup\t%p\t%p\t%s:%d\n", str, p, file, line);
362 #endif
363 return p;
364 }
365
366 #define xmalloc(x) xmalloc_(x, __FILE__, __LINE__)
367 #define xrealloc(x,y) xrealloc_(x, y, __FILE__, __LINE__)
368 #define xfree(x) xfree_(x, __FILE__, __LINE__)
369 #define xstrdup(x) xstrdup_(x, __FILE__, __LINE__)
370
371 #else
372
373 #define xmalloc(x) sqlite3_malloc(x)
374 #define xrealloc(x,y) sqlite3_realloc(x, y)
375 #define xfree(x) sqlite3_free(x)
376 #define xstrdup(x) strdup_(x)
377
378 #endif
379
380 #if defined(_WIN32) || defined(_WIN64)
381
382 #define vsnprintf _vsnprintf
383 #define snprintf _snprintf
384 #define strcasecmp _stricmp
385 #define strncasecmp _strnicmp
386
387 static HINSTANCE NEAR hModule; /* Saved module handle for resources */
388
389 #endif
390
391 #ifdef HAVE_SQLITE3STRNICMP
392 #undef strncasecmp
393 #define strncasecmp(A,B,C) sqlite3_strnicmp(A,B,C)
394 #undef strcasecmp
395 #define strcasecmp(A,B) strcasecmp_(A,B)
396
397 #if defined(__GNUC__) && (__GNUC__ >= 2)
398 static int strcasecmp_(const char *a, const char *b)
399 __attribute__((__unused__));
400 #endif
401
strcasecmp_(const char * a,const char * b)402 static int strcasecmp_(const char *a, const char *b)
403 {
404 int c = strlen(a), d = strlen(b);
405
406 if (c > d) {
407 return strncasecmp(a, b, c);
408 }
409 return strncasecmp(a, b, d);
410 }
411 #endif
412
413 #if defined(_WIN32) || defined(_WIN64)
414
415 /*
416 * SQLHENV, SQLHDBC, and SQLHSTMT synchronization
417 * is done using a critical section in ENV structure.
418 */
419
420 #define HDBC_LOCK(hdbc) \
421 { \
422 DBC *d; \
423 \
424 if ((hdbc) == SQL_NULL_HDBC) { \
425 return SQL_INVALID_HANDLE; \
426 } \
427 d = (DBC *) (hdbc); \
428 if (d->magic != DBC_MAGIC || !d->env) { \
429 return SQL_INVALID_HANDLE; \
430 } \
431 if (d->env->magic != ENV_MAGIC) { \
432 return SQL_INVALID_HANDLE; \
433 } \
434 EnterCriticalSection(&d->env->cs); \
435 d->env->owner = GetCurrentThreadId(); \
436 }
437
438 #define HDBC_UNLOCK(hdbc) \
439 if ((hdbc) != SQL_NULL_HDBC) { \
440 DBC *d; \
441 \
442 d = (DBC *) (hdbc); \
443 if (d->magic == DBC_MAGIC && d->env && \
444 d->env->magic == ENV_MAGIC) { \
445 d->env->owner = 0; \
446 LeaveCriticalSection(&d->env->cs); \
447 } \
448 }
449
450 #define HSTMT_LOCK(hstmt) \
451 { \
452 DBC *d; \
453 \
454 if ((hstmt) == SQL_NULL_HSTMT) { \
455 return SQL_INVALID_HANDLE; \
456 } \
457 d = (DBC *) ((STMT *) (hstmt))->dbc; \
458 if (d->magic != DBC_MAGIC || !d->env) { \
459 return SQL_INVALID_HANDLE; \
460 } \
461 if (d->env->magic != ENV_MAGIC) { \
462 return SQL_INVALID_HANDLE; \
463 } \
464 EnterCriticalSection(&d->env->cs); \
465 d->env->owner = GetCurrentThreadId(); \
466 }
467
468 #define HSTMT_UNLOCK(hstmt) \
469 if ((hstmt) != SQL_NULL_HSTMT) { \
470 DBC *d; \
471 \
472 d = (DBC *) ((STMT *) (hstmt))->dbc; \
473 if (d->magic == DBC_MAGIC && d->env && \
474 d->env->magic == ENV_MAGIC) { \
475 d->env->owner = 0; \
476 LeaveCriticalSection(&d->env->cs); \
477 } \
478 }
479
480 #else
481
482 /*
483 * On UN*X assume that we are single-threaded or
484 * the driver manager provides serialization for us.
485 *
486 * In iODBC (3.52.x) serialization can be turned
487 * on using the DSN property "ThreadManager=yes".
488 *
489 * In unixODBC that property is named
490 * "Threading=0-3" and takes one of these values:
491 *
492 * 0 - no protection
493 * 1 - statement level protection
494 * 2 - connection level protection
495 * 3 - environment level protection
496 *
497 * unixODBC 2.2.11 uses environment level protection
498 * by default when it has been built with pthread
499 * support.
500 */
501
502 #define HDBC_LOCK(hdbc)
503 #define HDBC_UNLOCK(hdbc)
504 #define HSTMT_LOCK(hdbc)
505 #define HSTMT_UNLOCK(hdbc)
506
507 #endif
508
509 #if defined(ENABLE_NVFS) && (ENABLE_NVFS)
510 extern void nvfs_init(void);
511 extern const char *nvfs_makevfs(const char *);
512 #endif
513
514 /*
515 * tolower() replacement w/o locale
516 */
517
518 static const char upper_chars[] = "ABCDEFGHIJKLMNOPQRSTUVWXYZ";
519 static const char lower_chars[] = "abcdefghijklmnopqrstuvwxyz";
520
521 static int
TOLOWER(int c)522 TOLOWER(int c)
523 {
524 if (c) {
525 char *p = strchr(upper_chars, c);
526
527 if (p) {
528 c = lower_chars[p - upper_chars];
529 }
530 }
531 return c;
532 }
533
534 /*
535 * isdigit() replacement w/o ctype.h
536 */
537
538 static const char digit_chars[] = "0123456789";
539
540 #define ISDIGIT(c) \
541 ((c) && strchr(digit_chars, (c)) != NULL)
542
543 /*
544 * isspace() replacement w/o ctype.h
545 */
546
547 static const char space_chars[] = " \f\n\r\t\v";
548
549 #define ISSPACE(c) \
550 ((c) && strchr(space_chars, (c)) != NULL)
551
552
553 /*
554 * Forward declarations of static functions.
555 */
556
557 static void dbtraceapi(DBC *d, char *fn, const char *sql);
558 static void freedyncols(STMT *s);
559 static void freeresult(STMT *s, int clrcols);
560 static void freerows(char **rowp);
561 static void unbindcols(STMT *s);
562 static void s3stmt_drop(STMT *s);
563
564 static SQLRETURN drvexecute(SQLHSTMT stmt, int initial);
565 static SQLRETURN freestmt(HSTMT stmt);
566 static SQLRETURN mkbindcols(STMT *s, int ncols);
567 static SQLRETURN setupdyncols(STMT *s, sqlite3_stmt *s3stmt, int *ncolsp);
568 static SQLRETURN setupparbuf(STMT *s, BINDPARM *p);
569 static SQLRETURN starttran(STMT *s);
570 static SQLRETURN setupparam(STMT *s, char *sql, int pnum);
571
572 #if (defined(_WIN32) || defined(_WIN64)) && defined(WINTERFACE)
573 /* MS Access hack part 1 (reserved error -7748) */
574 static COL *statSpec2P, *statSpec3P;
575 #endif
576
577 #if (MEMORY_DEBUG < 1)
578 /**
579 * Duplicate string using xmalloc().
580 * @param str string to be duplicated
581 * @result pointer to new string or NULL
582 */
583
584 static char *
strdup_(const char * str)585 strdup_(const char *str)
586 {
587 char *p = NULL;
588
589 if (str) {
590 p = xmalloc(strlen(str) + 1);
591 if (p) {
592 strcpy(p, str);
593 }
594 }
595 return p;
596 }
597 #endif
598
599 #ifdef WCHARSUPPORT
600
601 /**
602 * Return length of UNICODE string.
603 * @param str UNICODE string
604 * @result length of string
605 */
606
607 static int
uc_strlen(SQLWCHAR * str)608 uc_strlen(SQLWCHAR *str)
609 {
610 int len = 0;
611
612 if (str) {
613 while (*str) {
614 ++len;
615 ++str;
616 }
617 }
618 return len;
619 }
620
621 /**
622 * Copy UNICODE string like strncpy().
623 * @param dest destination area
624 * @param src source area
625 * @param len length of source area
626 * @return pointer to destination area
627 */
628
629 static SQLWCHAR *
uc_strncpy(SQLWCHAR * dest,SQLWCHAR * src,int len)630 uc_strncpy(SQLWCHAR *dest, SQLWCHAR *src, int len)
631 {
632 int i = 0;
633
634 while (i < len) {
635 if (!src[i]) {
636 break;
637 }
638 dest[i] = src[i];
639 ++i;
640 }
641 if (i < len) {
642 dest[i] = 0;
643 }
644 return dest;
645 }
646
647 /**
648 * Make UNICODE string from UTF8 string into buffer.
649 * @param str UTF8 string to be converted
650 * @param len length of str or -1
651 * @param uc destination area to receive UNICODE string
652 * @param ucLen byte length of destination area
653 */
654
655 static void
uc_from_utf_buf(unsigned char * str,int len,SQLWCHAR * uc,int ucLen)656 uc_from_utf_buf(unsigned char *str, int len, SQLWCHAR *uc, int ucLen)
657 {
658 ucLen = ucLen / sizeof (SQLWCHAR);
659 if (!uc || ucLen < 0) {
660 return;
661 }
662 if (len < 0) {
663 len = ucLen * 5;
664 }
665 uc[0] = 0;
666 if (str) {
667 int i = 0;
668
669 while (i < len && *str && i < ucLen) {
670 unsigned char c = str[0];
671
672 if (c < 0x80) {
673 uc[i++] = c;
674 ++str;
675 } else if (c <= 0xc1 || c >= 0xf5) {
676 /* illegal, ignored */
677 ++str;
678 } else if (c < 0xe0) {
679 if ((str[1] & 0xc0) == 0x80) {
680 unsigned long t = ((c & 0x1f) << 6) | (str[1] & 0x3f);
681
682 uc[i++] = t;
683 str += 2;
684 } else {
685 uc[i++] = c;
686 ++str;
687 }
688 } else if (c < 0xf0) {
689 if ((str[1] & 0xc0) == 0x80 && (str[2] & 0xc0) == 0x80) {
690 unsigned long t = ((c & 0x0f) << 12) |
691 ((str[1] & 0x3f) << 6) | (str[2] & 0x3f);
692
693 uc[i++] = t;
694 str += 3;
695 } else {
696 uc[i++] = c;
697 ++str;
698 }
699 } else if (c < 0xf8) {
700 if ((str[1] & 0xc0) == 0x80 && (str[2] & 0xc0) == 0x80 &&
701 (str[3] & 0xc0) == 0x80) {
702 unsigned long t = ((c & 0x03) << 18) |
703 ((str[1] & 0x3f) << 12) | ((str[2] & 0x3f) << 6) |
704 (str[4] & 0x3f);
705
706 if (sizeof (SQLWCHAR) == 2 * sizeof (char) &&
707 t >= 0x10000) {
708 t -= 0x10000;
709 uc[i++] = 0xd800 | (t & 0x3ff);
710 if (i >= ucLen) {
711 break;
712 }
713 t = 0xdc00 | ((t >> 10) & 0x3ff);
714 }
715 uc[i++] = t;
716 str += 4;
717 } else {
718 uc[i++] = c;
719 ++str;
720 }
721 } else if (c < 0xfc) {
722 if ((str[1] & 0xc0) == 0x80 && (str[2] & 0xc0) == 0x80 &&
723 (str[3] & 0xc0) == 0x80 && (str[4] & 0xc0) == 0x80) {
724 unsigned long t = ((c & 0x01) << 24) |
725 ((str[1] & 0x3f) << 18) | ((str[2] & 0x3f) << 12) |
726 ((str[4] & 0x3f) << 6) | (str[5] & 0x3f);
727
728 if (sizeof (SQLWCHAR) == 2 * sizeof (char) &&
729 t >= 0x10000) {
730 t -= 0x10000;
731 uc[i++] = 0xd800 | (t & 0x3ff);
732 if (i >= ucLen) {
733 break;
734 }
735 t = 0xdc00 | ((t >> 10) & 0x3ff);
736 }
737 uc[i++] = t;
738 str += 5;
739 } else {
740 uc[i++] = c;
741 ++str;
742 }
743 } else {
744 /* ignore */
745 ++str;
746 }
747 }
748 if (i < ucLen) {
749 uc[i] = 0;
750 }
751 }
752 }
753
754 /**
755 * Make UNICODE string from UTF8 string.
756 * @param str UTF8 string to be converted
757 * @param len length of UTF8 string
758 * @return alloc'ed UNICODE string to be free'd by uc_free()
759 */
760
761 static SQLWCHAR *
uc_from_utf(unsigned char * str,int len)762 uc_from_utf(unsigned char *str, int len)
763 {
764 SQLWCHAR *uc = NULL;
765 int ucLen;
766
767 if (str) {
768 if (len == SQL_NTS) {
769 len = strlen((char *) str);
770 }
771 ucLen = sizeof (SQLWCHAR) * (len + 1);
772 uc = xmalloc(ucLen);
773 if (uc) {
774 uc_from_utf_buf(str, len, uc, ucLen);
775 }
776 }
777 return uc;
778 }
779
780 /**
781 * Make UTF8 string from UNICODE string.
782 * @param str UNICODE string to be converted
783 * @param len length of UNICODE string in bytes
784 * @return alloc'ed UTF8 string to be free'd by uc_free()
785 */
786
787 static char *
uc_to_utf(SQLWCHAR * str,int len)788 uc_to_utf(SQLWCHAR *str, int len)
789 {
790 int i;
791 char *cp, *ret = NULL;
792
793 if (!str) {
794 return ret;
795 }
796 if (len == SQL_NTS) {
797 len = uc_strlen(str);
798 } else {
799 len = len / sizeof (SQLWCHAR);
800 }
801 cp = xmalloc(len * 6 + 1);
802 if (!cp) {
803 return ret;
804 }
805 ret = cp;
806 for (i = 0; i < len; i++) {
807 unsigned long c = str[i];
808
809 if (sizeof (SQLWCHAR) == 2 * sizeof (char)) {
810 c &= 0xffff;
811 }
812 if (c < 0x80) {
813 *cp++ = c;
814 } else if (c < 0x800) {
815 *cp++ = 0xc0 | ((c >> 6) & 0x1f);
816 *cp++ = 0x80 | (c & 0x3f);
817 } else if (c < 0x10000) {
818 if (sizeof (SQLWCHAR) == 2 * sizeof (char) &&
819 c >= 0xd800 && c <= 0xdbff && i + 1 < len) {
820 unsigned long c2 = str[i + 1] & 0xffff;
821
822 if (c2 >= 0xdc00 && c <= 0xdfff) {
823 c = ((c & 0x3ff) | ((c2 & 0x3ff) << 10)) + 0x10000;
824 *cp++ = 0xf0 | ((c >> 18) & 0x07);
825 *cp++ = 0x80 | ((c >> 12) & 0x3f);
826 *cp++ = 0x80 | ((c >> 6) & 0x3f);
827 *cp++ = 0x80 | (c & 0x3f);
828 ++i;
829 continue;
830 }
831 }
832 *cp++ = 0xe0 | ((c >> 12) & 0x0f);
833 *cp++ = 0x80 | ((c >> 6) & 0x3f);
834 *cp++ = 0x80 | (c & 0x3f);
835 } else if (c < 0x200000) {
836 *cp++ = 0xf0 | ((c >> 18) & 0x07);
837 *cp++ = 0x80 | ((c >> 12) & 0x3f);
838 *cp++ = 0x80 | ((c >> 6) & 0x3f);
839 *cp++ = 0x80 | (c & 0x3f);
840 } else if (c < 0x4000000) {
841 *cp++ = 0xf8 | ((c >> 24) & 0x03);
842 *cp++ = 0x80 | ((c >> 18) & 0x3f);
843 *cp++ = 0x80 | ((c >> 12) & 0x3f);
844 *cp++ = 0x80 | ((c >> 6) & 0x3f);
845 *cp++ = 0x80 | (c & 0x3f);
846 } else if (c < 0x80000000) {
847 *cp++ = 0xfc | ((c >> 31) & 0x01);
848 *cp++ = 0x80 | ((c >> 24) & 0x3f);
849 *cp++ = 0x80 | ((c >> 18) & 0x3f);
850 *cp++ = 0x80 | ((c >> 12) & 0x3f);
851 *cp++ = 0x80 | ((c >> 6) & 0x3f);
852 *cp++ = 0x80 | (c & 0x3f);
853 }
854 }
855 *cp = '\0';
856 return ret;
857 }
858
859 #endif
860
861 #ifdef WINTERFACE
862
863 /**
864 * Make UTF8 string from UNICODE string.
865 * @param str UNICODE string to be converted
866 * @param len length of UNICODE string in characters
867 * @return alloc'ed UTF8 string to be free'd by uc_free()
868 */
869
870 static char *
uc_to_utf_c(SQLWCHAR * str,int len)871 uc_to_utf_c(SQLWCHAR *str, int len)
872 {
873 if (len != SQL_NTS) {
874 len = len * sizeof (SQLWCHAR);
875 }
876 return uc_to_utf(str, len);
877 }
878
879 #endif
880
881 #if defined(WCHARSUPPORT) || defined(_WIN32) || defined(_WIN64)
882
883 /**
884 * Free converted UTF8 or UNICODE string.
885 * @param str string to be free'd
886 */
887
888 static void
uc_free(void * str)889 uc_free(void *str)
890 {
891 if (str) {
892 xfree(str);
893 }
894 }
895
896 #endif
897
898 #if defined(_WIN32) || defined(_WIN64)
899
900 /**
901 * Convert multibyte, current code page string to UTF8 string,
902 * @param str multibyte string to be converted
903 * @param len length of multibyte string
904 * @return alloc'ed UTF8 string to be free'd by uc_free()
905 */
906
907 static char *
wmb_to_utf(char * str,int len)908 wmb_to_utf(char *str, int len)
909 {
910 WCHAR *wstr;
911 OSVERSIONINFO ovi;
912 int nchar, is2k, cp = CP_OEMCP;
913
914 ovi.dwOSVersionInfoSize = sizeof (ovi);
915 GetVersionEx(&ovi);
916 is2k = ovi.dwPlatformId == VER_PLATFORM_WIN32_NT && ovi.dwMajorVersion > 4;
917 if (AreFileApisANSI()) {
918 cp = is2k ? CP_THREAD_ACP : CP_ACP;
919 }
920 nchar = MultiByteToWideChar(cp, 0, str, len, NULL, 0);
921 wstr = xmalloc((nchar + 1) * sizeof (WCHAR));
922 if (!wstr) {
923 return NULL;
924 }
925 wstr[0] = 0;
926 nchar = MultiByteToWideChar(cp, 0, str, len, wstr, nchar);
927 wstr[nchar] = 0;
928 str = xmalloc((nchar + 1) * 7);
929 if (!str) {
930 xfree(wstr);
931 return NULL;
932 }
933 str[0] = '\0';
934 nchar = WideCharToMultiByte(CP_UTF8, 0, wstr, -1, str, nchar * 7, 0, 0);
935 str[nchar] = '\0';
936 xfree(wstr);
937 return str;
938 }
939
940 #ifndef WINTERFACE
941
942 /**
943 * Convert multibyte, current code page string to UTF8 string,
944 * @param str multibyte string to be converted
945 * @param len length of multibyte string
946 * @return alloc'ed UTF8 string to be free'd by uc_free()
947 */
948
949 static char *
wmb_to_utf_c(char * str,int len)950 wmb_to_utf_c(char *str, int len)
951 {
952 if (len == SQL_NTS) {
953 len = strlen(str);
954 }
955 return wmb_to_utf(str, len);
956 }
957
958 #endif
959
960 /**
961 * Convert UTF8 string to multibyte, current code page string,
962 * @param str UTF8 string to be converted
963 * @param len length of UTF8 string
964 * @return alloc'ed multibyte string to be free'd by uc_free()
965 */
966
967 static char *
utf_to_wmb(char * str,int len)968 utf_to_wmb(char *str, int len)
969 {
970 WCHAR *wstr;
971 OSVERSIONINFO ovi;
972 int nchar, is2k, cp = CP_OEMCP;
973
974 ovi.dwOSVersionInfoSize = sizeof (ovi);
975 GetVersionEx(&ovi);
976 is2k = ovi.dwPlatformId == VER_PLATFORM_WIN32_NT && ovi.dwMajorVersion > 4;
977 if (AreFileApisANSI()) {
978 cp = is2k ? CP_THREAD_ACP : CP_ACP;
979 }
980 nchar = MultiByteToWideChar(CP_UTF8, 0, str, len, NULL, 0);
981 wstr = xmalloc((nchar + 1) * sizeof (WCHAR));
982 if (!wstr) {
983 return NULL;
984 }
985 wstr[0] = 0;
986 nchar = MultiByteToWideChar(CP_UTF8, 0, str, len, wstr, nchar);
987 wstr[nchar] = 0;
988 str = xmalloc((nchar + 1) * 7);
989 if (!str) {
990 xfree(wstr);
991 return NULL;
992 }
993 str[0] = '\0';
994 nchar = WideCharToMultiByte(cp, 0, wstr, -1, str, nchar * 7, 0, 0);
995 str[nchar] = '\0';
996 xfree(wstr);
997 return str;
998 }
999
1000 #ifdef WINTERFACE
1001
1002 /**
1003 * Convert multibyte, current code page string to UNICODE string,
1004 * @param str multibyte string to be converted
1005 * @param len length of multibyte string
1006 * @return alloc'ed UNICODE string to be free'd by uc_free()
1007 */
1008
1009 static WCHAR *
wmb_to_uc(char * str,int len)1010 wmb_to_uc(char *str, int len)
1011 {
1012 WCHAR *wstr;
1013 OSVERSIONINFO ovi;
1014 int nchar, is2k, cp = CP_OEMCP;
1015
1016 ovi.dwOSVersionInfoSize = sizeof (ovi);
1017 GetVersionEx(&ovi);
1018 is2k = ovi.dwPlatformId == VER_PLATFORM_WIN32_NT && ovi.dwMajorVersion > 4;
1019 if (AreFileApisANSI()) {
1020 cp = is2k ? CP_THREAD_ACP : CP_ACP;
1021 }
1022 nchar = MultiByteToWideChar(cp, 0, str, len, NULL, 0);
1023 wstr = xmalloc((nchar + 1) * sizeof (WCHAR));
1024 if (!wstr) {
1025 return NULL;
1026 }
1027 wstr[0] = 0;
1028 nchar = MultiByteToWideChar(cp, 0, str, len, wstr, nchar);
1029 wstr[nchar] = 0;
1030 return wstr;
1031 }
1032
1033 /**
1034 * Convert UNICODE string to multibyte, current code page string,
1035 * @param str UNICODE string to be converted
1036 * @param len length of UNICODE string
1037 * @return alloc'ed multibyte string to be free'd by uc_free()
1038 */
1039
1040 static char *
uc_to_wmb(WCHAR * wstr,int len)1041 uc_to_wmb(WCHAR *wstr, int len)
1042 {
1043 char *str;
1044 OSVERSIONINFO ovi;
1045 int nchar, is2k, cp = CP_OEMCP;
1046
1047 ovi.dwOSVersionInfoSize = sizeof (ovi);
1048 GetVersionEx(&ovi);
1049 is2k = ovi.dwPlatformId == VER_PLATFORM_WIN32_NT && ovi.dwMajorVersion > 4;
1050 if (AreFileApisANSI()) {
1051 cp = is2k ? CP_THREAD_ACP : CP_ACP;
1052 }
1053 nchar = WideCharToMultiByte(cp, 0, wstr, len, NULL, 0, 0, 0);
1054 str = xmalloc((nchar + 1) * 2);
1055 if (!str) {
1056 return NULL;
1057 }
1058 str[0] = '\0';
1059 nchar = WideCharToMultiByte(cp, 0, wstr, len, str, nchar * 2, 0, 0);
1060 str[nchar] = '\0';
1061 return str;
1062 }
1063
1064 #endif /* WINTERFACE */
1065
1066 #endif /* _WIN32 || _WIN64 */
1067
1068
1069 #ifdef USE_DLOPEN_FOR_GPPS
1070
1071 #include <dlfcn.h>
1072
1073 #define SQLGetPrivateProfileString(A,B,C,D,E,F) drvgpps(d,A,B,C,D,E,F)
1074
1075 /*
1076 * EXPERIMENTAL: SQLGetPrivateProfileString infrastructure using
1077 * dlopen(), in theory this makes the driver independent from the
1078 * driver manager, i.e. the same driver binary can run with iODBC
1079 * and unixODBC.
1080 */
1081
1082 static void
drvgetgpps(DBC * d)1083 drvgetgpps(DBC *d)
1084 {
1085 void *lib;
1086 int (*gpps)();
1087
1088 lib = dlopen("libodbcinst.so.1", RTLD_LAZY);
1089 if (!lib) {
1090 lib = dlopen("libodbcinst.so", RTLD_LAZY);
1091 }
1092 if (!lib) {
1093 lib = dlopen("libiodbcinst.so.2", RTLD_LAZY);
1094 }
1095 if (!lib) {
1096 lib = dlopen("libiodbcinst.so", RTLD_LAZY);
1097 }
1098 if (lib) {
1099 gpps = (int (*)()) dlsym(lib, "SQLGetPrivateProfileString");
1100 if (!gpps) {
1101 dlclose(lib);
1102 return;
1103 }
1104 d->instlib = lib;
1105 d->gpps = gpps;
1106 }
1107 }
1108
1109 static void
drvrelgpps(DBC * d)1110 drvrelgpps(DBC *d)
1111 {
1112 if (d->instlib) {
1113 dlclose(d->instlib);
1114 d->instlib = 0;
1115 }
1116 }
1117
1118 static int
drvgpps(DBC * d,char * sect,char * ent,char * def,char * buf,int bufsiz,char * fname)1119 drvgpps(DBC *d, char *sect, char *ent, char *def, char *buf,
1120 int bufsiz, char *fname)
1121 {
1122 if (d->gpps) {
1123 return d->gpps(sect, ent, def, buf, bufsiz, fname);
1124 }
1125 strncpy(buf, def, bufsiz);
1126 buf[bufsiz - 1] = '\0';
1127 return 1;
1128 }
1129 #else
1130 #include <odbcinst.h>
1131 #define drvgetgpps(d)
1132 #define drvrelgpps(d)
1133 #endif
1134
1135 /*
1136 * Internal function to bind SQLite3 parameters.
1137 */
1138
1139 static void
s3bind(DBC * d,sqlite3_stmt * stmt,int nparams,BINDPARM * p)1140 s3bind(DBC *d, sqlite3_stmt *stmt, int nparams, BINDPARM *p)
1141 {
1142 int i;
1143
1144 if (stmt && p && nparams > 0) {
1145 for (i = 0; i < nparams; i++, p++) {
1146 switch (p->s3type) {
1147 default:
1148 case SQLITE_NULL:
1149 sqlite3_bind_null(stmt, i + 1);
1150 if (d->trace) {
1151 fprintf(d->trace, "-- parameter %d: NULL\n", i + 1);
1152 fflush(d->trace);
1153 }
1154 break;
1155 case SQLITE_TEXT:
1156 sqlite3_bind_text(stmt, i + 1, p->s3val, p->s3size,
1157 SQLITE_STATIC);
1158 if (d->trace) {
1159 fprintf(d->trace, "-- parameter %d: '%*s'\n", i + 1,
1160 p->s3size, (char *) p->s3val);
1161 fflush(d->trace);
1162 }
1163 break;
1164 case SQLITE_BLOB:
1165 sqlite3_bind_blob(stmt, i + 1, p->s3val, p->s3size,
1166 SQLITE_STATIC);
1167 if (d->trace) {
1168 fprintf(d->trace, "-- parameter %d: [BLOB]'\n", i + 1);
1169 fflush(d->trace);
1170 }
1171 break;
1172 case SQLITE_FLOAT:
1173 sqlite3_bind_double(stmt, i + 1, p->s3dval);
1174 if (d->trace) {
1175 fprintf(d->trace, "-- parameter %d: %g\n",
1176 i + 1, p->s3dval);
1177 fflush(d->trace);
1178 }
1179 break;
1180 case SQLITE_INTEGER:
1181 if (p->s3size > sizeof (int)) {
1182 sqlite3_bind_int64(stmt, i + 1, p->s3lival);
1183 if (d->trace) {
1184 fprintf(d->trace,
1185 #ifdef _WIN32
1186 "-- parameter %d: %I64d\n",
1187 #else
1188 "-- parameter %d: %lld\n",
1189 #endif
1190 i + 1, p->s3lival);
1191 fflush(d->trace);
1192 }
1193 } else {
1194 sqlite3_bind_int(stmt, i + 1, p->s3ival);
1195 if (d->trace) {
1196 fprintf(d->trace, "-- parameter %d: %d\n",
1197 i + 1, p->s3ival);
1198 fflush(d->trace);
1199 }
1200 }
1201 break;
1202 }
1203 }
1204 }
1205 }
1206
1207 /*
1208 * Internal structure for managing driver's
1209 * sqlite3_get_table() implementation.
1210 */
1211
1212 typedef struct tblres {
1213 char **resarr;
1214 char *errmsg;
1215 sqlite3_stmt *stmt;
1216 STMT *s;
1217 int nres;
1218 int nalloc;
1219 int nrow;
1220 int ncol;
1221 PTRDIFF_T ndata;
1222 int rc;
1223 } TBLRES;
1224
1225 /*
1226 * Driver's version of sqlite3_get_table() and friends which are
1227 * capable of dealing with blobs.
1228 */
1229
1230 static int
drvgettable_row(TBLRES * t,int ncol,int rc)1231 drvgettable_row(TBLRES *t, int ncol, int rc)
1232 {
1233 int need;
1234 int i;
1235 char *p;
1236
1237 if (t->nrow == 0 && rc == SQLITE_ROW) {
1238 need = ncol * 2;
1239 } else {
1240 need = ncol;
1241 }
1242 if (t->ndata + need >= t->nalloc) {
1243 char **resnew;
1244 int nalloc = t->nalloc * 2 + need + 1;
1245
1246 resnew = xrealloc(t->resarr, sizeof (char *) * nalloc);
1247 if (!resnew) {
1248 nomem:
1249 t->rc = SQLITE_NOMEM;
1250 return 1;
1251 }
1252 t->nalloc = nalloc;
1253 t->resarr = resnew;
1254 }
1255 /* column names when first row */
1256 if (t->nrow == 0) {
1257 t->ncol = ncol;
1258 for (i = 0; i < ncol; i++) {
1259 p = (char *) sqlite3_column_name(t->stmt, i);
1260 if (p) {
1261 char *q = xmalloc(strlen(p) + 1);
1262
1263 if (!q) {
1264 goto nomem;
1265 }
1266 strcpy(q, p);
1267 p = q;
1268 }
1269 t->resarr[t->ndata++] = p;
1270 }
1271 if (t->s && t->s->guessed_types) {
1272 int ncol2 = ncol;
1273
1274 setupdyncols(t->s, t->stmt, &ncol2);
1275 t->s->guessed_types = 0;
1276 t->s->ncols = ncol;
1277 }
1278 } else if (t->ncol != ncol) {
1279 t->errmsg = sqlite3_mprintf("drvgettable() called with two or"
1280 " more incompatible queries");
1281 t->rc = SQLITE_ERROR;
1282 return 1;
1283 }
1284 /* copy row data */
1285 if (rc == SQLITE_ROW) {
1286 for (i = 0; i < ncol; i++) {
1287 int coltype = sqlite3_column_type(t->stmt, i);
1288
1289 p = NULL;
1290 if (coltype == SQLITE_BLOB) {
1291 int k, nbytes = sqlite3_column_bytes(t->stmt, i);
1292 char *qp;
1293 unsigned const char *bp;
1294
1295 bp = sqlite3_column_blob(t->stmt, i);
1296 qp = xmalloc(nbytes * 2 + 4);
1297 if (!qp) {
1298 goto nomem;
1299 }
1300 p = qp;
1301 *qp++ = 'X';
1302 *qp++ = '\'';
1303 for (k = 0; k < nbytes; k++) {
1304 *qp++ = xdigits[(bp[k] >> 4)];
1305 *qp++ = xdigits[(bp[k] & 0xF)];
1306 }
1307 *qp++ = '\'';
1308 *qp = '\0';
1309 } else if (coltype != SQLITE_NULL) {
1310 p = xstrdup((char *) sqlite3_column_text(t->stmt, i));
1311 if (!p) {
1312 goto nomem;
1313 }
1314 }
1315 t->resarr[t->ndata++] = p;
1316 }
1317 t->nrow++;
1318 }
1319 return 0;
1320 }
1321
1322 static int
drvgettable(STMT * s,const char * sql,char *** resp,int * nrowp,int * ncolp,char ** errp,int nparam,BINDPARM * p)1323 drvgettable(STMT *s, const char *sql, char ***resp, int *nrowp,
1324 int *ncolp, char **errp, int nparam, BINDPARM *p)
1325 {
1326 DBC *d = (DBC *) s->dbc;
1327 int rc = SQLITE_OK, keep = sql == NULL;
1328 TBLRES tres;
1329 const char *sqlleft = 0;
1330 int nretry = 0, haveerr = 0;
1331
1332 if (!resp) {
1333 return SQLITE_ERROR;
1334 }
1335 *resp = NULL;
1336 if (nrowp) {
1337 *nrowp = 0;
1338 }
1339 if (ncolp) {
1340 *ncolp = 0;
1341 }
1342 tres.errmsg = NULL;
1343 tres.nres = 0;
1344 tres.nrow = 0;
1345 tres.ncol = 0;
1346 tres.ndata = 1;
1347 tres.nalloc = 20;
1348 tres.rc = SQLITE_OK;
1349 tres.resarr = xmalloc(sizeof (char *) * tres.nalloc);
1350 tres.stmt = NULL;
1351 tres.s = s;
1352 if (!tres.resarr) {
1353 return SQLITE_NOMEM;
1354 }
1355 tres.resarr[0] = 0;
1356 if (sql == NULL) {
1357 tres.stmt = s->s3stmt;
1358 if (tres.stmt == NULL) {
1359 return SQLITE_NOMEM;
1360 }
1361 goto retrieve;
1362 }
1363 while (sql && *sql && (rc == SQLITE_OK ||
1364 (rc == SQLITE_SCHEMA && (++nretry) < 2))) {
1365 int ncol;
1366
1367 tres.stmt = NULL;
1368 #if defined(HAVE_SQLITE3PREPAREV2) && (HAVE_SQLITE3PREPAREV2)
1369 dbtraceapi(d, "sqlite3_prepare_v2", sql);
1370 rc = sqlite3_prepare_v2(d->sqlite, sql, -1, &tres.stmt, &sqlleft);
1371 #else
1372 dbtraceapi(d, "sqlite3_prepare", sql);
1373 rc = sqlite3_prepare(d->sqlite, sql, -1, &tres.stmt, &sqlleft);
1374 #endif
1375 if (rc != SQLITE_OK) {
1376 if (tres.stmt) {
1377 dbtraceapi(d, "sqlite3_finalize", 0);
1378 sqlite3_finalize(tres.stmt);
1379 tres.stmt = NULL;
1380 }
1381 continue;
1382 }
1383 if (!tres.stmt) {
1384 /* this happens for a comment or white-space */
1385 sql = sqlleft;
1386 continue;
1387 }
1388 retrieve:
1389 if (sqlite3_bind_parameter_count(tres.stmt) != nparam) {
1390 if (errp) {
1391 *errp =
1392 sqlite3_mprintf("%s", "parameter marker count incorrect");
1393 }
1394 haveerr = 1;
1395 rc = SQLITE_ERROR;
1396 goto tbldone;
1397 }
1398 s3bind(d, tres.stmt, nparam, p);
1399 ncol = sqlite3_column_count(tres.stmt);
1400 while (1) {
1401 if (s->max_rows && tres.nrow >= s->max_rows) {
1402 rc = SQLITE_OK;
1403 break;
1404 }
1405 rc = sqlite3_step(tres.stmt);
1406 if (rc == SQLITE_ROW || rc == SQLITE_DONE) {
1407 if (drvgettable_row(&tres, ncol, rc)) {
1408 rc = SQLITE_ABORT;
1409 goto tbldone;
1410 }
1411 }
1412 if (rc != SQLITE_ROW) {
1413 if (keep) {
1414 dbtraceapi(d, "sqlite3_reset", 0);
1415 rc = sqlite3_reset(tres.stmt);
1416 s->s3stmt_noreset = 1;
1417 } else {
1418 dbtraceapi(d, "sqlite3_finalize", 0);
1419 rc = sqlite3_finalize(tres.stmt);
1420 }
1421 tres.stmt = 0;
1422 if (rc != SQLITE_SCHEMA) {
1423 nretry = 0;
1424 sql = sqlleft;
1425 while (sql && ISSPACE(*sql)) {
1426 sql++;
1427 }
1428 }
1429 if (rc == SQLITE_DONE) {
1430 rc = SQLITE_OK;
1431 }
1432 break;
1433 }
1434 }
1435 }
1436 tbldone:
1437 if (tres.stmt) {
1438 if (keep) {
1439 if (!s->s3stmt_noreset) {
1440 dbtraceapi(d, "sqlite3_reset", 0);
1441 sqlite3_reset(tres.stmt);
1442 s->s3stmt_noreset = 1;
1443 }
1444 } else {
1445 dbtraceapi(d, "sqlite3_finalize", 0);
1446 sqlite3_finalize(tres.stmt);
1447 }
1448 }
1449 if (haveerr) {
1450 /* message already in *errp if any */
1451 } else if (rc != SQLITE_OK && rc == sqlite3_errcode(d->sqlite) && errp) {
1452 *errp = sqlite3_mprintf("%s", sqlite3_errmsg(d->sqlite));
1453 } else if (errp) {
1454 *errp = NULL;
1455 }
1456 if (tres.resarr) {
1457 tres.resarr[0] = (char *) (tres.ndata - 1);
1458 }
1459 if (rc == SQLITE_ABORT) {
1460 freerows(&tres.resarr[1]);
1461 if (tres.errmsg) {
1462 if (errp) {
1463 if (*errp) {
1464 sqlite3_free(*errp);
1465 }
1466 *errp = tres.errmsg;
1467 } else {
1468 sqlite3_free(tres.errmsg);
1469 }
1470 }
1471 return tres.rc;
1472 }
1473 sqlite3_free(tres.errmsg);
1474 if (rc != SQLITE_OK) {
1475 freerows(&tres.resarr[1]);
1476 return rc;
1477 }
1478 *resp = &tres.resarr[1];
1479 if (ncolp) {
1480 *ncolp = tres.ncol;
1481 }
1482 if (nrowp) {
1483 *nrowp = tres.nrow;
1484 }
1485 return rc;
1486 }
1487
1488 /**
1489 * Set error message and SQL state on DBC
1490 * @param d database connection pointer
1491 * @param naterr native error code
1492 * @param msg error message
1493 * @param st SQL state
1494 */
1495
1496 #if defined(__GNUC__) && (__GNUC__ >= 2)
1497 static void setstatd(DBC *, int, char *, char *, ...)
1498 __attribute__((format (printf, 3, 5)));
1499 #endif
1500
1501 static void
setstatd(DBC * d,int naterr,char * msg,char * st,...)1502 setstatd(DBC *d, int naterr, char *msg, char *st, ...)
1503 {
1504 va_list ap;
1505
1506 if (!d) {
1507 return;
1508 }
1509 d->naterr = naterr;
1510 d->logmsg[0] = '\0';
1511 if (msg) {
1512 int count;
1513
1514 va_start(ap, st);
1515 count = vsnprintf((char *) d->logmsg, sizeof (d->logmsg), msg, ap);
1516 va_end(ap);
1517 if (count < 0) {
1518 d->logmsg[sizeof (d->logmsg) - 1] = '\0';
1519 }
1520 }
1521 if (!st) {
1522 st = "?????";
1523 }
1524 strncpy(d->sqlstate, st, 5);
1525 d->sqlstate[5] = '\0';
1526 }
1527
1528 /**
1529 * Set error message and SQL state on statement
1530 * @param s statement pointer
1531 * @param naterr native error code
1532 * @param msg error message
1533 * @param st SQL state
1534 */
1535
1536 #if defined(__GNUC__) && (__GNUC__ >= 2)
1537 static void setstat(STMT *, int, char *, char *, ...)
1538 __attribute__((format (printf, 3, 5)));
1539 #endif
1540
1541 static void
setstat(STMT * s,int naterr,char * msg,char * st,...)1542 setstat(STMT *s, int naterr, char *msg, char *st, ...)
1543 {
1544 va_list ap;
1545
1546 if (!s) {
1547 return;
1548 }
1549 s->naterr = naterr;
1550 s->logmsg[0] = '\0';
1551 if (msg) {
1552 int count;
1553
1554 va_start(ap, st);
1555 count = vsnprintf((char *) s->logmsg, sizeof (s->logmsg), msg, ap);
1556 va_end(ap);
1557 if (count < 0) {
1558 s->logmsg[sizeof (s->logmsg) - 1] = '\0';
1559 }
1560 }
1561 if (!st) {
1562 st = "?????";
1563 }
1564 strncpy(s->sqlstate, st, 5);
1565 s->sqlstate[5] = '\0';
1566 }
1567
1568 /**
1569 * Report IM001 (not implemented) SQL error code for HDBC.
1570 * @param dbc database connection handle
1571 * @result ODBC error code
1572 */
1573
1574 static SQLRETURN
drvunimpldbc(HDBC dbc)1575 drvunimpldbc(HDBC dbc)
1576 {
1577 DBC *d;
1578
1579 if (dbc == SQL_NULL_HDBC) {
1580 return SQL_INVALID_HANDLE;
1581 }
1582 d = (DBC *) dbc;
1583 setstatd(d, -1, "not supported", "IM001");
1584 return SQL_ERROR;
1585 }
1586
1587 /**
1588 * Report IM001 (not implemented) SQL error code for HSTMT.
1589 * @param stmt statement handle
1590 * @result ODBC error code
1591 */
1592
1593 static SQLRETURN
drvunimplstmt(HSTMT stmt)1594 drvunimplstmt(HSTMT stmt)
1595 {
1596 STMT *s;
1597
1598 if (stmt == SQL_NULL_HSTMT) {
1599 return SQL_INVALID_HANDLE;
1600 }
1601 s = (STMT *) stmt;
1602 setstat(s, -1, "not supported", "IM001");
1603 return SQL_ERROR;
1604 }
1605
1606 /**
1607 * Free memory given pointer to memory pointer.
1608 * @param x pointer to pointer to memory to be free'd
1609 */
1610
1611 static void
freep(void * x)1612 freep(void *x)
1613 {
1614 if (x && ((char **) x)[0]) {
1615 xfree(((char **) x)[0]);
1616 ((char **) x)[0] = NULL;
1617 }
1618 }
1619
1620 /**
1621 * Report S1000 (out of memory) SQL error given STMT.
1622 * @param s statement pointer
1623 * @result ODBC error code
1624 */
1625
1626 static SQLRETURN
nomem(STMT * s)1627 nomem(STMT *s)
1628 {
1629 setstat(s, -1, "out of memory", (*s->ov3) ? "HY000" : "S1000");
1630 return SQL_ERROR;
1631 }
1632
1633 /**
1634 * Report S1000 (not connected) SQL error given STMT.
1635 * @param s statement pointer
1636 * @result ODBC error code
1637 */
1638
1639 static SQLRETURN
noconn(STMT * s)1640 noconn(STMT *s)
1641 {
1642 setstat(s, -1, "not connected", (*s->ov3) ? "HY000" : "S1000");
1643 return SQL_ERROR;
1644 }
1645
1646 /**
1647 * Internal locale neutral strtod function.
1648 * @param data pointer to string
1649 * @param endp pointer for ending character
1650 * @result double value
1651 */
1652
1653 #if defined(HAVE_LOCALECONV) || defined(_WIN32) || defined(_WIN64)
1654
1655 static double
ln_strtod(const char * data,char ** endp)1656 ln_strtod(const char *data, char **endp)
1657 {
1658 struct lconv *lc;
1659 char buf[128], *p, *end;
1660 double value;
1661
1662 lc = localeconv();
1663 if (lc && lc->decimal_point && lc->decimal_point[0] &&
1664 lc->decimal_point[0] != '.') {
1665 strncpy(buf, data, sizeof (buf) - 1);
1666 buf[sizeof (buf) - 1] = '\0';
1667 p = strchr(buf, '.');
1668 if (p) {
1669 *p = lc->decimal_point[0];
1670 }
1671 p = buf;
1672 } else {
1673 p = (char *) data;
1674 }
1675 value = strtod(p, &end);
1676 end = (char *) data + (end - p);
1677 if (endp) {
1678 *endp = end;
1679 }
1680 return value;
1681 }
1682
1683 #else
1684
1685 #define ln_strtod(A,B) strtod(A,B)
1686
1687 #endif
1688
1689 /**
1690 * Strip quotes from quoted string in-place.
1691 * @param str string
1692 */
1693
1694 static char *
unquote(char * str)1695 unquote(char *str)
1696 {
1697 if (str) {
1698 int len = strlen(str);
1699
1700 if (len > 1) {
1701 if ((str[0] == '\'' && str[len - 1] == '\'') ||
1702 (str[0] == '"' && str[len - 1] == '"') ||
1703 (str[0] == '[' && str[len - 1] == ']')) {
1704 str[len - 1] = '\0';
1705 strcpy(str, str + 1);
1706 }
1707 }
1708 }
1709 return str;
1710 }
1711
1712 /**
1713 * Unescape search pattern for e.g. table name in
1714 * catalog functions. Replacements in string are done in-place.
1715 * @param str string
1716 * @result number of pattern characters in string or 0
1717 */
1718
1719 static int
unescpat(char * str)1720 unescpat(char *str)
1721 {
1722 char *p, *q;
1723 int count = 0;
1724
1725 p = str;
1726 while ((q = strchr(p, '_')) != NULL) {
1727 if (q == str || q[-1] != '\\') {
1728 count++;
1729 }
1730 p = q + 1;
1731 }
1732 p = str;
1733 while ((q = strchr(p, '%')) != NULL) {
1734 if (q == str || q[-1] != '\\') {
1735 count++;
1736 }
1737 p = q + 1;
1738 }
1739 p = str;
1740 while ((q = strchr(p, '\\')) != NULL) {
1741 if (q[1] == '\\' || q[1] == '_' || q[1] == '%') {
1742 strcpy(q, q + 1);
1743 }
1744 p = q + 1;
1745 }
1746 return count;
1747 }
1748
1749 /**
1750 * SQL LIKE string match with optional backslash escape handling.
1751 * @param str string
1752 * @param pat pattern
1753 * @param esc when true, treat literally "\\" as "\", "\?" as "?", "\_" as "_"
1754 * @result true when pattern matched
1755 */
1756
1757 static int
namematch(char * str,char * pat,int esc)1758 namematch(char *str, char *pat, int esc)
1759 {
1760 int cp, ch;
1761
1762 while (1) {
1763 cp = TOLOWER(*pat);
1764 if (cp == '\0') {
1765 if (*str != '\0') {
1766 goto nomatch;
1767 }
1768 break;
1769 }
1770 if (*str == '\0' && cp != '%') {
1771 goto nomatch;
1772 }
1773 if (cp == '%') {
1774 while (*pat == '%') {
1775 ++pat;
1776 }
1777 cp = TOLOWER(*pat);
1778 if (cp == '\0') {
1779 break;
1780 }
1781 while (1) {
1782 if (cp != '_' && cp != '\\') {
1783 while (*str) {
1784 ch = TOLOWER(*str);
1785 if (ch == cp) {
1786 break;
1787 }
1788 ++str;
1789 }
1790 }
1791 if (namematch(str, pat, esc)) {
1792 goto match;
1793 }
1794 if (*str == '\0') {
1795 goto nomatch;
1796 }
1797 ch = TOLOWER(*str);
1798 ++str;
1799 }
1800 }
1801 if (cp == '_') {
1802 pat++;
1803 str++;
1804 continue;
1805 }
1806 if (esc && cp == '\\' &&
1807 (pat[1] == '\\' || pat[1] == '%' || pat[1] == '_')) {
1808 ++pat;
1809 cp = TOLOWER(*pat);
1810 }
1811 ch = TOLOWER(*str++);
1812 ++pat;
1813 if (ch != cp) {
1814 goto nomatch;
1815 }
1816 }
1817 match:
1818 return 1;
1819 nomatch:
1820 return 0;
1821 }
1822
1823 /**
1824 * Busy callback for SQLite.
1825 * @param udata user data, pointer to DBC
1826 * @param count count of subsequenct calls
1827 * @result true or false
1828 */
1829
1830 static int
busy_handler(void * udata,int count)1831 busy_handler(void *udata, int count)
1832 {
1833 DBC *d = (DBC *) udata;
1834 long t1;
1835 int ret = 0;
1836 #if !defined(_WIN32) && !defined(_WIN64)
1837 struct timeval tv;
1838 #ifdef HAVE_NANOSLEEP
1839 struct timespec ts;
1840 #endif
1841 #endif
1842
1843 if (d->busyint) {
1844 d->busyint = 0;
1845 return ret;
1846 }
1847 if (d->timeout <= 0) {
1848 return ret;
1849 }
1850 if (count <= 1) {
1851 #if defined(_WIN32) || defined(_WIN64)
1852 d->t0 = GetTickCount();
1853 #else
1854 gettimeofday(&tv, NULL);
1855 d->t0 = tv.tv_sec * 1000 + tv.tv_usec / 1000;
1856 #endif
1857 }
1858 #if defined(_WIN32) || defined(_WIN64)
1859 t1 = GetTickCount();
1860 #else
1861 gettimeofday(&tv, NULL);
1862 t1 = tv.tv_sec * 1000 + tv.tv_usec / 1000;
1863 #endif
1864 if (t1 - d->t0 > d->timeout) {
1865 goto done;
1866 }
1867 #if defined(_WIN32) || defined(_WIN64)
1868 Sleep(10);
1869 #else
1870 #ifdef HAVE_NANOSLEEP
1871 ts.tv_sec = 0;
1872 ts.tv_nsec = 10000000;
1873 do {
1874 ret = nanosleep(&ts, &ts);
1875 if (ret < 0 && errno != EINTR) {
1876 ret = 0;
1877 }
1878 } while (ret);
1879 #else
1880 #ifdef HAVE_USLEEP
1881 usleep(10000);
1882 #else
1883 tv.tv_sec = 0;
1884 tv.tv_usec = 10000;
1885 select(0, NULL, NULL, NULL, &tv);
1886 #endif
1887 #endif
1888 #endif
1889 ret = 1;
1890 done:
1891 return ret;
1892 }
1893
1894 /**
1895 * Set SQLite options (PRAGMAs) given SQLite handle.
1896 * @param x SQLite database handle
1897 * @param d DBC pointer
1898 * @result SQLite error code
1899 *
1900 * SQLite < 3.3.x and not shortnames DSN option:
1901 * "full_column_names" is always turned on and "short_column_names"
1902 * is always turned off, to get the table names in column labels.
1903 */
1904
1905 static int
setsqliteopts(sqlite3 * x,DBC * d)1906 setsqliteopts(sqlite3 *x, DBC *d)
1907 {
1908 int count = 0, step = 0, max, rc = SQLITE_ERROR;
1909
1910 #if defined(HAVE_SQLITE3COLUMNTABLENAME) && (HAVE_SQLITE3COLUMNTABLENAME)
1911 max = d->longnames ? 3 : 1;
1912 #else
1913 max = 3;
1914 #endif
1915 if (d->shortnames) {
1916 max = 3;
1917 }
1918 while (step < max) {
1919 if (step < 1) {
1920 rc = sqlite3_exec(x, "PRAGMA empty_result_callbacks = on;",
1921 NULL, NULL, NULL);
1922 if (rc == SQLITE_OK) {
1923 rc = sqlite3_exec(x, d->fksupport ?
1924 "PRAGMA foreign_keys = on;" :
1925 "PRAGMA foreign_keys = off;",
1926 NULL, NULL, NULL);
1927 }
1928 } else if (step < 2) {
1929 rc = sqlite3_exec(x, d->shortnames ?
1930 "PRAGMA full_column_names = off;" :
1931 "PRAGMA full_column_names = on;",
1932 NULL, NULL, NULL);
1933 } else if (step < 3) {
1934 rc = sqlite3_exec(x, d->shortnames ?
1935 "PRAGMA short_column_names = on;" :
1936 "PRAGMA short_column_names = off;",
1937 NULL, NULL, NULL);
1938 }
1939 if (rc != SQLITE_OK) {
1940 if (rc != SQLITE_BUSY ||
1941 !busy_handler((void *) d, ++count)) {
1942 return rc;
1943 }
1944 continue;
1945 }
1946 count = 0;
1947 ++step;
1948 }
1949 sqlite3_busy_handler(x, busy_handler, (void *) d);
1950 return SQLITE_OK;
1951 }
1952
1953 /**
1954 * Free counted array of char pointers.
1955 * @param rowp pointer to char pointer array
1956 *
1957 * The -1-th element of the array holds the array size.
1958 * All non-NULL pointers of the array and then the array
1959 * itself are free'd.
1960 */
1961
1962 static void
freerows(char ** rowp)1963 freerows(char **rowp)
1964 {
1965 PTRDIFF_T size, i;
1966
1967 if (!rowp) {
1968 return;
1969 }
1970 --rowp;
1971 size = (PTRDIFF_T) rowp[0];
1972 for (i = 1; i <= size; i++) {
1973 freep(&rowp[i]);
1974 }
1975 freep(&rowp);
1976 }
1977
1978 /**
1979 * Map SQL field type from string to ODBC integer type code.
1980 * @param typename field type string
1981 * @param nosign pointer to indicator for unsigned field or NULL
1982 * @param ov3 boolean, true for SQL_OV_ODBC3
1983 * @param nowchar boolean, for WINTERFACE don't use WCHAR
1984 * @param dobigint boolean, force SQL_BIGINT on INTEGER columns
1985 * @result SQL data type
1986 */
1987
1988 static int
mapsqltype(const char * typename,int * nosign,int ov3,int nowchar,int dobigint)1989 mapsqltype(const char *typename, int *nosign, int ov3, int nowchar,
1990 int dobigint)
1991 {
1992 char *p, *q;
1993 int testsign = 0, result;
1994
1995 #ifdef WINTERFACE
1996 result = nowchar ? SQL_VARCHAR : SQL_WVARCHAR;
1997 #else
1998 result = SQL_VARCHAR;
1999 #endif
2000 if (!typename) {
2001 return result;
2002 }
2003 q = p = xmalloc(strlen(typename) + 1);
2004 if (!p) {
2005 return result;
2006 }
2007 strcpy(p, typename);
2008 while (*q) {
2009 *q = TOLOWER(*q);
2010 ++q;
2011 }
2012 if (strncmp(p, "inter", 5) == 0) {
2013 } else if (strncmp(p, "int", 3) == 0 ||
2014 strncmp(p, "mediumint", 9) == 0) {
2015 testsign = 1;
2016 result = SQL_INTEGER;
2017 } else if (strncmp(p, "numeric", 7) == 0) {
2018 result = SQL_DOUBLE;
2019 } else if (strncmp(p, "tinyint", 7) == 0) {
2020 testsign = 1;
2021 result = SQL_TINYINT;
2022 } else if (strncmp(p, "smallint", 8) == 0) {
2023 testsign = 1;
2024 result = SQL_SMALLINT;
2025 } else if (strncmp(p, "float", 5) == 0) {
2026 result = SQL_DOUBLE;
2027 } else if (strncmp(p, "double", 6) == 0 ||
2028 strncmp(p, "real", 4) == 0) {
2029 result = SQL_DOUBLE;
2030 } else if (strncmp(p, "timestamp", 9) == 0) {
2031 #ifdef SQL_TYPE_TIMESTAMP
2032 result = ov3 ? SQL_TYPE_TIMESTAMP : SQL_TIMESTAMP;
2033 #else
2034 result = SQL_TIMESTAMP;
2035 #endif
2036 } else if (strncmp(p, "datetime", 8) == 0) {
2037 #ifdef SQL_TYPE_TIMESTAMP
2038 result = ov3 ? SQL_TYPE_TIMESTAMP : SQL_TIMESTAMP;
2039 #else
2040 result = SQL_TIMESTAMP;
2041 #endif
2042 } else if (strncmp(p, "time", 4) == 0) {
2043 #ifdef SQL_TYPE_TIME
2044 result = ov3 ? SQL_TYPE_TIME : SQL_TIME;
2045 #else
2046 result = SQL_TIME;
2047 #endif
2048 } else if (strncmp(p, "date", 4) == 0) {
2049 #ifdef SQL_TYPE_DATE
2050 result = ov3 ? SQL_TYPE_DATE : SQL_DATE;
2051 #else
2052 result = SQL_DATE;
2053 #endif
2054 #ifdef SQL_LONGVARCHAR
2055 } else if (strncmp(p, "text", 4) == 0 ||
2056 strncmp(p, "memo", 4) == 0 ||
2057 strncmp(p, "longvarchar", 11) == 0) {
2058 #ifdef WINTERFACE
2059 result = nowchar ? SQL_LONGVARCHAR : SQL_WLONGVARCHAR;
2060 #else
2061 result = SQL_LONGVARCHAR;
2062 #endif
2063 #ifdef WINTERFACE
2064 } else if (strncmp(p, "wtext", 5) == 0 ||
2065 strncmp(p, "wvarchar", 8) == 0 ||
2066 strncmp(p, "longwvarchar", 12) == 0) {
2067 result = SQL_WLONGVARCHAR;
2068 #endif
2069 #endif
2070 #ifdef SQL_BIT
2071 } else if (strncmp(p, "bool", 4) == 0 ||
2072 strncmp(p, "bit", 3) == 0) {
2073 result = SQL_BIT;
2074 #endif
2075 #ifdef SQL_BIGINT
2076 } else if (strncmp(p, "bigint", 6) == 0) {
2077 testsign = 1;
2078 result = SQL_BIGINT;
2079 #endif
2080 } else if (strncmp(p, "blob", 4) == 0) {
2081 result = SQL_BINARY;
2082 } else if (strncmp(p, "varbinary", 9) == 0) {
2083 result = SQL_VARBINARY;
2084 } else if (strncmp(p, "longvarbinary", 13) == 0) {
2085 result = SQL_LONGVARBINARY;
2086 }
2087 if (nosign) {
2088 if (testsign) {
2089 *nosign = strstr(p, "unsigned") != NULL;
2090 } else {
2091 *nosign = 1;
2092 }
2093 }
2094 #ifdef SQL_BIGINT
2095 if (dobigint && result == SQL_INTEGER) {
2096 result = SQL_BIGINT;
2097 }
2098 #endif
2099 xfree(p);
2100 return result;
2101 }
2102
2103 /**
2104 * Get maximum display size and number of digits after decimal point
2105 * from field type specification.
2106 * @param typename field type specification
2107 * @param sqltype target SQL data type
2108 * @param mp pointer to maximum display size or NULL
2109 * @param dp pointer to number of digits after decimal point or NULL
2110 */
2111
2112 static void
getmd(const char * typename,int sqltype,int * mp,int * dp)2113 getmd(const char *typename, int sqltype, int *mp, int *dp)
2114 {
2115 int m = 0, d = 0;
2116
2117 switch (sqltype) {
2118 case SQL_INTEGER: m = 10; d = 9; break;
2119 case SQL_TINYINT: m = 4; d = 3; break;
2120 case SQL_SMALLINT: m = 6; d = 5; break;
2121 case SQL_FLOAT: m = 25; d = 24; break;
2122 case SQL_DOUBLE: m = 54; d = 53; break;
2123 case SQL_VARCHAR: m = 255; d = 0; break;
2124 #ifdef WINTERFACE
2125 #ifdef SQL_WVARCHAR
2126 case SQL_WVARCHAR: m = 255; d = 0; break;
2127 #endif
2128 #endif
2129 #ifdef SQL_TYPE_DATE
2130 case SQL_TYPE_DATE:
2131 #endif
2132 case SQL_DATE: m = 10; d = 0; break;
2133 #ifdef SQL_TYPE_TIME
2134 case SQL_TYPE_TIME:
2135 #endif
2136 case SQL_TIME: m = 8; d = 0; break;
2137 #ifdef SQL_TYPE_TIMESTAMP
2138 case SQL_TYPE_TIMESTAMP:
2139 #endif
2140 case SQL_TIMESTAMP: m = 32; d = 3; break;
2141 #ifdef SQL_LONGVARCHAR
2142 case SQL_LONGVARCHAR : m = 65536; d = 0; break;
2143 #endif
2144 #ifdef WINTERFACE
2145 #ifdef SQL_WLONGVARCHAR
2146 case SQL_WLONGVARCHAR: m = 65536; d = 0; break;
2147 #endif
2148 #endif
2149 case SQL_VARBINARY: m = 255; d = 0; break;
2150 case SQL_LONGVARBINARY: m = 65536; d = 0; break;
2151 #ifdef SQL_BIGINT
2152 case SQL_BIGINT: m = 20; d = 19; break;
2153 #endif
2154 #ifdef SQL_BIT
2155 case SQL_BIT: m = 1; d = 1; break;
2156 #endif
2157 }
2158 if (m && typename) {
2159 int mm, dd;
2160
2161 if (sscanf(typename, "%*[^(](%d)", &mm) == 1) {
2162 if (sqltype == SQL_TIMESTAMP) {
2163 d = mm;
2164 }
2165 #ifdef SQL_TYPE_TIMESTAMP
2166 else if (sqltype == SQL_TYPE_TIMESTAMP) {
2167 d = mm;
2168 }
2169 #endif
2170 else {
2171 m = d = mm;
2172 }
2173 } else if (sscanf(typename, "%*[^(](%d,%d)", &mm, &dd) == 2) {
2174 m = mm;
2175 d = dd;
2176 }
2177 }
2178 if (mp) {
2179 *mp = m;
2180 }
2181 if (dp) {
2182 *dp = d;
2183 }
2184 }
2185
2186 /**
2187 * Map SQL_C_DEFAULT to proper C type.
2188 * @param type input C type
2189 * @param stype input SQL type
2190 * @param nosign 0=signed, 0>unsigned, 0<undefined
2191 * @param nowchar when compiled with WINTERFACE don't use WCHAR
2192 * @result C type
2193 */
2194
2195 static int
mapdeftype(int type,int stype,int nosign,int nowchar)2196 mapdeftype(int type, int stype, int nosign, int nowchar)
2197 {
2198 if (type == SQL_C_DEFAULT) {
2199 switch (stype) {
2200 case SQL_INTEGER:
2201 type = (nosign > 0) ? SQL_C_ULONG : SQL_C_LONG;
2202 break;
2203 case SQL_TINYINT:
2204 type = (nosign > 0) ? SQL_C_UTINYINT : SQL_C_TINYINT;
2205 break;
2206 case SQL_SMALLINT:
2207 type = (nosign > 0) ? SQL_C_USHORT : SQL_C_SHORT;
2208 break;
2209 case SQL_FLOAT:
2210 type = SQL_C_FLOAT;
2211 break;
2212 case SQL_DOUBLE:
2213 type = SQL_C_DOUBLE;
2214 break;
2215 case SQL_TIMESTAMP:
2216 type = SQL_C_TIMESTAMP;
2217 break;
2218 case SQL_TIME:
2219 type = SQL_C_TIME;
2220 break;
2221 case SQL_DATE:
2222 type = SQL_C_DATE;
2223 break;
2224 #ifdef SQL_C_TYPE_TIMESTAMP
2225 case SQL_TYPE_TIMESTAMP:
2226 type = SQL_C_TYPE_TIMESTAMP;
2227 break;
2228 #endif
2229 #ifdef SQL_C_TYPE_TIME
2230 case SQL_TYPE_TIME:
2231 type = SQL_C_TYPE_TIME;
2232 break;
2233 #endif
2234 #ifdef SQL_C_TYPE_DATE
2235 case SQL_TYPE_DATE:
2236 type = SQL_C_TYPE_DATE;
2237 break;
2238 #endif
2239 #ifdef WINTERFACE
2240 case SQL_WVARCHAR:
2241 case SQL_WCHAR:
2242 #ifdef SQL_WLONGVARCHAR
2243 case SQL_WLONGVARCHAR:
2244 #endif
2245 type = nowchar ? SQL_C_CHAR : SQL_C_WCHAR;
2246 break;
2247 #endif
2248 case SQL_BINARY:
2249 case SQL_VARBINARY:
2250 case SQL_LONGVARBINARY:
2251 type = SQL_C_BINARY;
2252 break;
2253 #ifdef SQL_BIT
2254 case SQL_BIT:
2255 type = SQL_C_BIT;
2256 break;
2257 #endif
2258 #ifdef SQL_BIGINT
2259 case SQL_BIGINT:
2260 type = SQL_C_CHAR;
2261 break;
2262 #endif
2263 default:
2264 #ifdef WINTERFACE
2265 type = nowchar ? SQL_C_CHAR : SQL_C_WCHAR;
2266 #else
2267 type = SQL_C_CHAR;
2268 #endif
2269 break;
2270 }
2271 }
2272 return type;
2273 }
2274
2275 /**
2276 * Fixup query string with optional parameter markers.
2277 * @param sql original query string
2278 * @param sqlLen length of query string or SQL_NTS
2279 * @param nparam output number of parameters
2280 * @param isselect output indicator for SELECT statement
2281 * @param errmsg output error message
2282 * @result newly allocated string containing query string for SQLite or NULL
2283 */
2284
2285 static char *
fixupsql(char * sql,int sqlLen,int * nparam,int * isselect,char ** errmsg)2286 fixupsql(char *sql, int sqlLen, int *nparam, int *isselect, char **errmsg)
2287 {
2288 char *q = sql, *qz = NULL, *p, *inq = NULL, *out;
2289 int np = 0, isddl = -1, size;
2290
2291 *errmsg = NULL;
2292 if (sqlLen != SQL_NTS) {
2293 qz = q = xmalloc(sqlLen + 1);
2294 if (!qz) {
2295 return NULL;
2296 }
2297 memcpy(q, sql, sqlLen);
2298 q[sqlLen] = '\0';
2299 size = sqlLen * 4;
2300 } else {
2301 size = strlen(sql) * 4;
2302 }
2303 size += sizeof (char *) - 1;
2304 size &= ~(sizeof (char *) - 1);
2305 p = xmalloc(size);
2306 if (!p) {
2307 errout:
2308 freep(&qz);
2309 return NULL;
2310 }
2311 memset(p, 0, size);
2312 out = p;
2313 while (*q) {
2314 switch (*q) {
2315 case '\'':
2316 case '\"':
2317 if (q == inq) {
2318 inq = NULL;
2319 } else if (!inq) {
2320 inq = q + 1;
2321
2322 while (*inq) {
2323 if (*inq == *q) {
2324 if (inq[1] == *q) {
2325 inq++;
2326 } else {
2327 break;
2328 }
2329 }
2330 inq++;
2331 }
2332 }
2333 *p++ = *q;
2334 break;
2335 case '?':
2336 *p++ = *q;
2337 if (!inq) {
2338 np++;
2339 }
2340 break;
2341 case ';':
2342 if (!inq) {
2343 if (isddl < 0) {
2344 char *qq = out;
2345
2346 while (*qq && ISSPACE(*qq)) {
2347 ++qq;
2348 }
2349 if (*qq && *qq != ';') {
2350 size = strlen(qq);
2351 if ((size >= 5) &&
2352 (strncasecmp(qq, "create", 5) == 0)) {
2353 isddl = 1;
2354 } else if ((size >= 4) &&
2355 (strncasecmp(qq, "drop", 4) == 0)) {
2356 isddl = 1;
2357 } else {
2358 isddl = 0;
2359 }
2360 }
2361 }
2362 if (isddl == 0) {
2363 char *qq = q;
2364
2365 do {
2366 ++qq;
2367 } while (*qq && ISSPACE(*qq));
2368 if (*qq && *qq != ';') {
2369 freep(&out);
2370 *errmsg = "only one SQL statement allowed";
2371 goto errout;
2372 }
2373 }
2374 }
2375 *p++ = *q;
2376 break;
2377 case '{':
2378 /* deal with {d 'YYYY-MM-DD'}, {t ...}, and {ts ...} */
2379 if (!inq) {
2380 char *end = q + 1;
2381
2382 while (*end && *end != '}') {
2383 ++end;
2384 }
2385 if (*end == '}') {
2386 char *start = q + 1;
2387 char *end2 = end - 1;
2388
2389 while (start < end2 && *start != '\'') {
2390 ++start;
2391 }
2392 while (end2 > start && *end2 != '\'') {
2393 --end2;
2394 }
2395 if (*start == '\'' && *end2 == '\'') {
2396 while (start <= end2) {
2397 *p++ = *start;
2398 ++start;
2399 }
2400 q = end;
2401 break;
2402 }
2403 }
2404 }
2405 /* FALL THROUGH */
2406 default:
2407 *p++ = *q;
2408 }
2409 ++q;
2410 }
2411 freep(&qz);
2412 *p = '\0';
2413 if (nparam) {
2414 *nparam = np;
2415 }
2416 if (isselect) {
2417 if (isddl > 0) {
2418 *isselect = 0;
2419 } else {
2420 int incom = 0;
2421
2422 p = out;
2423 while (*p) {
2424 switch (*p) {
2425 case '-':
2426 if (!incom && p[1] == '-') {
2427 incom = -1;
2428 }
2429 break;
2430 case '\n':
2431 if (incom < 0) {
2432 incom = 0;
2433 }
2434 break;
2435 case '/':
2436 if (incom > 0 && p[-1] == '*') {
2437 incom = 0;
2438 p++;
2439 continue;
2440 } else if (!incom && p[1] == '*') {
2441 incom = 1;
2442 }
2443 break;
2444 }
2445 if (!incom && !ISSPACE(*p)) {
2446 break;
2447 }
2448 p++;
2449 }
2450 size = strlen(p);
2451 *isselect = (size >= 6) && (strncasecmp(p, "select", 6) == 0);
2452 }
2453 }
2454 return out;
2455 }
2456
2457 /**
2458 * Find column given name in string array.
2459 * @param cols string array
2460 * @param ncols number of strings
2461 * @param name column name
2462 * @result >= 0 on success, -1 on error
2463 */
2464
2465 static int
findcol(char ** cols,int ncols,char * name)2466 findcol(char **cols, int ncols, char *name)
2467 {
2468 int i;
2469
2470 if (cols) {
2471 for (i = 0; i < ncols; i++) {
2472 if (strcmp(cols[i], name) == 0) {
2473 return i;
2474 }
2475 }
2476 }
2477 return -1;
2478 }
2479
2480 /**
2481 * Fixup column information for a running statement.
2482 * @param s statement to get fresh column information
2483 * @param d DBC pointer
2484 *
2485 * The column labels get the table names stripped
2486 * when there's more than one column and all table
2487 * names are identical.
2488 *
2489 * The "dyncols" field of STMT is filled with column
2490 * information obtained by SQLite "PRAGMA table_info"
2491 * for each column whose table name is known. If the
2492 * types are already present as with SQLite 2.5.7
2493 * this information is used instead.
2494 */
2495
2496 static void
fixupdyncols(STMT * s,DBC * d)2497 fixupdyncols(STMT *s, DBC *d)
2498 {
2499 int i;
2500 #if !defined(HAVE_SQLITE3TABLECOLUMNMETADATA) || !(HAVE_SQLITE3TABLECOLUMNMETADATA)
2501 int k, pk, nn, t, r, nrows, ncols;
2502 char **rowp, *flagp, flags[128];
2503 #endif
2504
2505 if (!s->dyncols) {
2506 return;
2507 }
2508 /* fixup labels */
2509 if (!s->longnames) {
2510 if (s->dcols > 1) {
2511 char *table = s->dyncols[0].table;
2512
2513 for (i = 1; table[0] && i < s->dcols; i++) {
2514 if (strcmp(s->dyncols[i].table, table)) {
2515 break;
2516 }
2517 }
2518 if (i >= s->dcols) {
2519 for (i = 0; i < s->dcols; i++) {
2520 s->dyncols[i].label = s->dyncols[i].column;
2521 }
2522 }
2523 } else if (s->dcols == 1) {
2524 s->dyncols[0].label = s->dyncols[0].column;
2525 }
2526 }
2527 for (i = 0; i < s->dcols; i++) {
2528 s->dyncols[i].type =
2529 mapsqltype(s->dyncols[i].typename, &s->dyncols[i].nosign, *s->ov3,
2530 s->nowchar[0] || s->nowchar[1], s->dobigint);
2531 getmd(s->dyncols[i].typename, s->dyncols[i].type,
2532 &s->dyncols[i].size, &s->dyncols[i].prec);
2533 #ifdef SQL_LONGVARCHAR
2534 if (s->dyncols[i].type == SQL_VARCHAR &&
2535 s->dyncols[i].size > 255) {
2536 s->dyncols[i].type = SQL_LONGVARCHAR;
2537 }
2538 #endif
2539 #ifdef WINTERFACE
2540 #ifdef SQL_WLONGVARCHAR
2541 if (s->dyncols[i].type == SQL_WVARCHAR &&
2542 s->dyncols[i].size > 255) {
2543 s->dyncols[i].type = SQL_WLONGVARCHAR;
2544 }
2545 #endif
2546 #endif
2547 if (s->dyncols[i].type == SQL_VARBINARY &&
2548 s->dyncols[i].size > 255) {
2549 s->dyncols[i].type = SQL_LONGVARBINARY;
2550 }
2551 }
2552 #if !defined(HAVE_SQLITE3TABLECOLUMNMETADATA) || !(HAVE_SQLITE3TABLECOLUMNMETADATA)
2553 if (s->dcols > array_size(flags)) {
2554 flagp = xmalloc(sizeof (flags[0]) * s->dcols);
2555 if (flagp == NULL) {
2556 return;
2557 }
2558 } else {
2559 flagp = flags;
2560 }
2561 memset(flagp, 0, sizeof (flags[0]) * s->dcols);
2562 for (i = 0; i < s->dcols; i++) {
2563 s->dyncols[i].autoinc = SQL_FALSE;
2564 s->dyncols[i].notnull = SQL_NULLABLE;
2565 }
2566 for (i = 0; i < s->dcols; i++) {
2567 int ret, lastpk = -1, autoinccount = 0;
2568 char *sql;
2569
2570 if (!s->dyncols[i].table[0]) {
2571 continue;
2572 }
2573 if (flagp[i]) {
2574 continue;
2575 }
2576 sql = sqlite3_mprintf("PRAGMA table_info(%Q)", s->dyncols[i].table);
2577 if (!sql) {
2578 continue;
2579 }
2580 dbtraceapi(d, "sqlite3_get_table", sql);
2581 ret = sqlite3_get_table(d->sqlite, sql, &rowp, &nrows, &ncols, NULL);
2582 sqlite3_free(sql);
2583 if (ret != SQLITE_OK) {
2584 continue;
2585 }
2586 k = findcol(rowp, ncols, "name");
2587 t = findcol(rowp, ncols, "type");
2588 pk = findcol(rowp, ncols, "pk");
2589 nn = findcol(rowp, ncols, "notnull");
2590 if (k < 0 || t < 0) {
2591 goto freet;
2592 }
2593 for (r = 1; r <= nrows; r++) {
2594 int m;
2595
2596 for (m = i; m < s->dcols; m++) {
2597 char *colname = s->dyncols[m].column;
2598
2599 if (s->longnames) {
2600 char *dotp = strchr(colname, '.');
2601
2602 if (dotp) {
2603 colname = dotp + 1;
2604 }
2605 }
2606 if (!flagp[m] &&
2607 strcmp(colname, rowp[r * ncols + k]) == 0 &&
2608 strcmp(s->dyncols[m].table, s->dyncols[i].table) == 0) {
2609 char *typename = rowp[r * ncols + t];
2610
2611 flagp[m] = 1;
2612 freep(&s->dyncols[m].typename);
2613 s->dyncols[m].typename = xstrdup(typename);
2614 s->dyncols[m].type =
2615 mapsqltype(typename, &s->dyncols[m].nosign, *s->ov3,
2616 s->nowchar[0] || s->nowchar[1],
2617 s->dobigint);
2618 getmd(typename, s->dyncols[m].type, &s->dyncols[m].size,
2619 &s->dyncols[m].prec);
2620 #ifdef SQL_LONGVARCHAR
2621 if (s->dyncols[m].type == SQL_VARCHAR &&
2622 s->dyncols[m].size > 255) {
2623 s->dyncols[m].type = SQL_LONGVARCHAR;
2624 }
2625 #endif
2626 #ifdef WINTERFACE
2627 #ifdef SQL_WLONGVARCHAR
2628 if (s->dyncols[i].type == SQL_WVARCHAR &&
2629 s->dyncols[i].size > 255) {
2630 s->dyncols[i].type = SQL_WLONGVARCHAR;
2631 }
2632 #endif
2633 #endif
2634 if (s->dyncols[i].type == SQL_VARBINARY &&
2635 s->dyncols[i].size > 255) {
2636 s->dyncols[i].type = SQL_LONGVARBINARY;
2637 }
2638 if (pk >= 0 && strcmp(rowp[r * ncols + pk], "1") == 0) {
2639 if (++autoinccount > 1) {
2640 if (lastpk >= 0) {
2641 s->dyncols[lastpk].autoinc = SQL_FALSE;
2642 lastpk = -1;
2643 }
2644 } else {
2645 lastpk = m;
2646 if (strlen(typename) == 7 &&
2647 strncasecmp(typename, "integer", 7) == 0) {
2648 s->dyncols[m].autoinc = SQL_TRUE;
2649 }
2650 }
2651 }
2652 if (nn >= 0 && rowp[r * ncols + nn][0] != '0') {
2653 s->dyncols[m].notnull = SQL_NO_NULLS;
2654 }
2655 }
2656 }
2657 }
2658 freet:
2659 sqlite3_free_table(rowp);
2660 }
2661 if (flagp != flags) {
2662 freep(&flagp);
2663 }
2664 #endif
2665 }
2666
2667 /**
2668 * Return number of month days.
2669 * @param year
2670 * @param month 1..12
2671 * @result number of month days or 0
2672 */
2673
2674 static int
getmdays(int year,int month)2675 getmdays(int year, int month)
2676 {
2677 static const int mdays[] = {
2678 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31
2679 };
2680 int mday;
2681
2682 if (month < 1) {
2683 return 0;
2684 }
2685 mday = mdays[(month - 1) % 12];
2686 if (mday == 28 && year % 4 == 0 &&
2687 (!(year % 100 == 0) || year % 400 == 0)) {
2688 mday++;
2689 }
2690 return mday;
2691 }
2692
2693 /**
2694 * Convert string to ODBC DATE_STRUCT.
2695 * @param str string to be converted
2696 * @param ds output DATE_STRUCT
2697 * @result 0 on success, -1 on error
2698 *
2699 * Strings of the format 'YYYYMMDD' or 'YYYY-MM-DD' or
2700 * 'YYYY/MM/DD' or 'MM/DD/YYYY' are converted to a
2701 * DATE_STRUCT.
2702 */
2703
2704 static int
str2date(char * str,DATE_STRUCT * ds)2705 str2date(char *str, DATE_STRUCT *ds)
2706 {
2707 int i, err = 0;
2708 char *p, *q, sepc = '\0';
2709
2710 ds->year = ds->month = ds->day = 0;
2711 p = str;
2712 while (*p && !ISDIGIT(*p)) {
2713 ++p;
2714 }
2715 q = p;
2716 i = 0;
2717 while (*q && !ISDIGIT(*q)) {
2718 ++i;
2719 ++q;
2720 }
2721 if (i >= 8) {
2722 char buf[8];
2723
2724 strncpy(buf, p + 0, 4); buf[4] = '\0';
2725 ds->year = strtol(buf, NULL, 10);
2726 strncpy(buf, p + 4, 2); buf[2] = '\0';
2727 ds->month = strtol(buf, NULL, 10);
2728 strncpy(buf, p + 6, 2); buf[2] = '\0';
2729 ds->day = strtol(buf, NULL, 10);
2730 goto done;
2731 }
2732 i = 0;
2733 while (i < 3) {
2734 int n;
2735
2736 q = NULL;
2737 n = strtol(p, &q, 10);
2738 if (!q || q == p) {
2739 if (*q == '\0') {
2740 if (i == 0) {
2741 err = 1;
2742 }
2743 goto done;
2744 }
2745 }
2746 if (!sepc) {
2747 sepc = *q;
2748 }
2749 if (*q == '-' || *q == '/' || *q == '\0' || i == 2) {
2750 switch (i) {
2751 case 0: ds->year = n; break;
2752 case 1: ds->month = n; break;
2753 case 2: ds->day = n; break;
2754 }
2755 ++i;
2756 if (*q) {
2757 ++q;
2758 }
2759 } else {
2760 i = 0;
2761 while (*q && !ISDIGIT(*q)) {
2762 ++q;
2763 }
2764 }
2765 p = q;
2766 }
2767 done:
2768 /* final check for overflow */
2769 if (err ||
2770 ds->month < 1 || ds->month > 12 ||
2771 ds->day < 1 || ds->day > getmdays(ds->year, ds->month)) {
2772 if (sepc == '/') {
2773 /* Try MM/DD/YYYY format */
2774 int t[3];
2775
2776 t[0] = ds->year;
2777 t[1] = ds->month;
2778 t[2] = ds->day;
2779 ds->year = t[2];
2780 ds->day = t[1];
2781 ds->month = t[0];
2782 if (ds->month >= 1 && ds->month <= 12 &&
2783 (ds->day >= 1 || ds->day <= getmdays(ds->year, ds->month))) {
2784 return 0;
2785 }
2786 }
2787 return -1;
2788 }
2789 return 0;
2790 }
2791
2792 /**
2793 * Convert string to ODBC TIME_STRUCT.
2794 * @param str string to be converted
2795 * @param ts output TIME_STRUCT
2796 * @result 0 on success, -1 on error
2797 *
2798 * Strings of the format 'HHMMSS' or 'HH:MM:SS'
2799 * are converted to a TIME_STRUCT.
2800 */
2801
2802 static int
str2time(char * str,TIME_STRUCT * ts)2803 str2time(char *str, TIME_STRUCT *ts)
2804 {
2805 int i, err = 0, ampm = -1;
2806 char *p, *q;
2807
2808 ts->hour = ts->minute = ts->second = 0;
2809 p = str;
2810 while (*p && !ISDIGIT(*p)) {
2811 ++p;
2812 }
2813 q = p;
2814 i = 0;
2815 while (*q && ISDIGIT(*q)) {
2816 ++i;
2817 ++q;
2818 }
2819 if (i >= 6) {
2820 char buf[4];
2821
2822 strncpy(buf, p + 0, 2); buf[2] = '\0';
2823 ts->hour = strtol(buf, NULL, 10);
2824 strncpy(buf, p + 2, 2); buf[2] = '\0';
2825 ts->minute = strtol(buf, NULL, 10);
2826 strncpy(buf, p + 4, 2); buf[2] = '\0';
2827 ts->second = strtol(buf, NULL, 10);
2828 goto done;
2829 }
2830 i = 0;
2831 while (i < 3) {
2832 int n;
2833
2834 q = NULL;
2835 n = strtol(p, &q, 10);
2836 if (!q || q == p) {
2837 if (*q == '\0') {
2838 if (i == 0) {
2839 err = 1;
2840 }
2841 goto done;
2842 }
2843 }
2844 if (*q == ':' || *q == '\0' || i == 2) {
2845 switch (i) {
2846 case 0: ts->hour = n; break;
2847 case 1: ts->minute = n; break;
2848 case 2: ts->second = n; break;
2849 }
2850 ++i;
2851 if (*q) {
2852 ++q;
2853 }
2854 } else {
2855 i = 0;
2856 while (*q && !ISDIGIT(*q)) {
2857 ++q;
2858 }
2859 }
2860 p = q;
2861 }
2862 if (!err) {
2863 while (*p) {
2864 if ((p[0] == 'p' || p[0] == 'P') &&
2865 (p[1] == 'm' || p[1] == 'M')) {
2866 ampm = 1;
2867 } else if ((p[0] == 'a' || p[0] == 'A') &&
2868 (p[1] == 'm' || p[1] == 'M')) {
2869 ampm = 0;
2870 }
2871 ++p;
2872 }
2873 if (ampm > 0) {
2874 if (ts->hour < 12) {
2875 ts->hour += 12;
2876 }
2877 } else if (ampm == 0) {
2878 if (ts->hour == 12) {
2879 ts->hour = 0;
2880 }
2881 }
2882 }
2883 done:
2884 /* final check for overflow */
2885 if (err || ts->hour > 23 || ts->minute > 59 || ts->second > 59) {
2886 return -1;
2887 }
2888 return 0;
2889 }
2890
2891 /**
2892 * Convert string to ODBC TIMESTAMP_STRUCT.
2893 * @param str string to be converted
2894 * @param tss output TIMESTAMP_STRUCT
2895 * @result 0 on success, -1 on error
2896 *
2897 * Strings of the format 'YYYYMMDDhhmmssff' or 'YYYY-MM-DD hh:mm:ss ff'
2898 * or 'YYYY/MM/DD hh:mm:ss ff' or 'hh:mm:ss ff YYYY-MM-DD' are
2899 * converted to a TIMESTAMP_STRUCT. The ISO8601 formats
2900 * YYYY-MM-DDThh:mm:ss[.f]Z
2901 * YYYY-MM-DDThh:mm:ss[.f]shh:mm
2902 * are also supported. In case a time zone field is present,
2903 * the resulting TIMESTAMP_STRUCT is expressed in UTC.
2904 */
2905
2906 static int
str2timestamp(char * str,TIMESTAMP_STRUCT * tss)2907 str2timestamp(char *str, TIMESTAMP_STRUCT *tss)
2908 {
2909 int i, m, n, err = 0, ampm = -1;
2910 char *p, *q, in = '\0', sepc = '\0';
2911
2912 tss->year = tss->month = tss->day = 0;
2913 tss->hour = tss->minute = tss->second = 0;
2914 tss->fraction = 0;
2915 p = str;
2916 while (*p && !ISDIGIT(*p)) {
2917 ++p;
2918 }
2919 q = p;
2920 i = 0;
2921 while (*q && ISDIGIT(*q)) {
2922 ++i;
2923 ++q;
2924 }
2925 if (i >= 14) {
2926 char buf[16];
2927
2928 strncpy(buf, p + 0, 4); buf[4] = '\0';
2929 tss->year = strtol(buf, NULL, 10);
2930 strncpy(buf, p + 4, 2); buf[2] = '\0';
2931 tss->month = strtol(buf, NULL, 10);
2932 strncpy(buf, p + 6, 2); buf[2] = '\0';
2933 tss->day = strtol(buf, NULL, 10);
2934 strncpy(buf, p + 8, 2); buf[2] = '\0';
2935 tss->hour = strtol(buf, NULL, 10);
2936 strncpy(buf, p + 10, 2); buf[2] = '\0';
2937 tss->minute = strtol(buf, NULL, 10);
2938 strncpy(buf, p + 12, 2); buf[2] = '\0';
2939 tss->second = strtol(buf, NULL, 10);
2940 if (i > 14) {
2941 m = i - 14;
2942 strncpy(buf, p + 14, m);
2943 while (m < 9) {
2944 buf[m] = '0';
2945 ++m;
2946 }
2947 buf[m] = '\0';
2948 tss->fraction = strtol(buf, NULL, 0);
2949 }
2950 m = 7;
2951 goto done;
2952 }
2953 m = i = 0;
2954 while ((m & 7) != 7) {
2955 q = NULL;
2956 n = strtol(p, &q, 10);
2957 if (!q || q == p) {
2958 if (*q == '\0') {
2959 if (m < 1) {
2960 err = 1;
2961 }
2962 goto done;
2963 }
2964 }
2965 if (in == '\0') {
2966 switch (*q) {
2967 case '-':
2968 case '/':
2969 if ((m & 1) == 0) {
2970 in = *q;
2971 i = 0;
2972 }
2973 break;
2974 case ':':
2975 if ((m & 2) == 0) {
2976 in = *q;
2977 i = 0;
2978 }
2979 break;
2980 case ' ':
2981 case '.':
2982 break;
2983 default:
2984 in = '\0';
2985 i = 0;
2986 break;
2987 }
2988 }
2989 switch (in) {
2990 case '-':
2991 case '/':
2992 if (!sepc) {
2993 sepc = in;
2994 }
2995 switch (i) {
2996 case 0: tss->year = n; break;
2997 case 1: tss->month = n; break;
2998 case 2: tss->day = n; break;
2999 }
3000 if (++i >= 3) {
3001 i = 0;
3002 m |= 1;
3003 if (!(m & 2)) {
3004 m |= 8;
3005 }
3006 goto skip;
3007 } else {
3008 ++q;
3009 }
3010 break;
3011 case ':':
3012 switch (i) {
3013 case 0: tss->hour = n; break;
3014 case 1: tss->minute = n; break;
3015 case 2: tss->second = n; break;
3016 }
3017 if (++i >= 3) {
3018 i = 0;
3019 m |= 2;
3020 if (*q == '.') {
3021 in = '.';
3022 goto skip2;
3023 }
3024 if (*q == ' ') {
3025 if ((m & 1) == 0) {
3026 char *e = NULL;
3027 int dummy;
3028
3029 dummy = strtol(q + 1, &e, 10);
3030 if (e && *e == '-') {
3031 goto skip;
3032 }
3033 }
3034 in = '.';
3035 goto skip2;
3036 }
3037 goto skip;
3038 } else {
3039 ++q;
3040 }
3041 break;
3042 case '.':
3043 if (++i >= 1) {
3044 int ndig = q - p;
3045
3046 if (p[0] == '+' || p[0] == '-') {
3047 ndig--;
3048 }
3049 while (ndig < 9) {
3050 n = n * 10;
3051 ++ndig;
3052 }
3053 tss->fraction = n;
3054 m |= 4;
3055 i = 0;
3056 }
3057 default:
3058 skip:
3059 in = '\0';
3060 skip2:
3061 while (*q && !ISDIGIT(*q)) {
3062 if ((q[0] == 'a' || q[0] == 'A') &&
3063 (q[1] == 'm' || q[1] == 'M')) {
3064 ampm = 0;
3065 ++q;
3066 } else if ((q[0] == 'p' || q[0] == 'P') &&
3067 (q[1] == 'm' || q[1] == 'M')) {
3068 ampm = 1;
3069 ++q;
3070 }
3071 ++q;
3072 }
3073 }
3074 p = q;
3075 }
3076 if ((m & 7) > 1 && (m & 8)) {
3077 /* ISO8601 timezone */
3078 if (p > str && ISDIGIT(*p)) {
3079 int nn, sign;
3080
3081 q = p - 1;
3082 if (*q != '+' && *q != '-') {
3083 goto done;
3084 }
3085 sign = (*q == '+') ? -1 : 1;
3086 q = NULL;
3087 n = strtol(p, &q, 10);
3088 if (!q || *q++ != ':' || !ISDIGIT(*q)) {
3089 goto done;
3090 }
3091 p = q;
3092 q = NULL;
3093 nn = strtol(p, &q, 0);
3094 tss->minute += nn * sign;
3095 if ((SQLSMALLINT) tss->minute < 0) {
3096 tss->hour -= 1;
3097 tss->minute += 60;
3098 } else if (tss->minute >= 60) {
3099 tss->hour += 1;
3100 tss->minute -= 60;
3101 }
3102 tss->hour += n * sign;
3103 if ((SQLSMALLINT) tss->hour < 0) {
3104 tss->day -= 1;
3105 tss->hour += 24;
3106 } else if (tss->hour >= 24) {
3107 tss->day += 1;
3108 tss->hour -= 24;
3109 }
3110 if ((short) tss->day < 1 || tss->day >= 28) {
3111 int mday, pday, pmon;
3112
3113 mday = getmdays(tss->year, tss->month);
3114 pmon = tss->month - 1;
3115 if (pmon < 1) {
3116 pmon = 12;
3117 }
3118 pday = getmdays(tss->year, pmon);
3119 if ((SQLSMALLINT) tss->day < 1) {
3120 tss->month -= 1;
3121 tss->day = pday;
3122 } else if (tss->day > mday) {
3123 tss->month += 1;
3124 tss->day = 1;
3125 }
3126 if ((SQLSMALLINT) tss->month < 1) {
3127 tss->year -= 1;
3128 tss->month = 12;
3129 } else if (tss->month > 12) {
3130 tss->year += 1;
3131 tss->month = 1;
3132 }
3133 }
3134 }
3135 }
3136 done:
3137 if ((m & 1) &&
3138 (tss->month < 1 || tss->month > 12 ||
3139 tss->day < 1 || tss->day > getmdays(tss->year, tss->month))) {
3140 if (sepc == '/') {
3141 /* Try MM/DD/YYYY format */
3142 int t[3];
3143
3144 t[0] = tss->year;
3145 t[1] = tss->month;
3146 t[2] = tss->day;
3147 tss->year = t[2];
3148 tss->day = t[1];
3149 tss->month = t[0];
3150 }
3151 }
3152 /* Replace missing year/month/day with current date */
3153 if (!err && (m & 1) == 0) {
3154 #ifdef _WIN32
3155 SYSTEMTIME t;
3156
3157 GetLocalTime(&t);
3158 tss->year = t.wYear;
3159 tss->month = t.wMonth;
3160 tss->day = t.wDay;
3161 #else
3162 struct timeval tv;
3163 struct tm tm;
3164
3165 gettimeofday(&tv, NULL);
3166 tm = *localtime(&tv.tv_sec);
3167 tss->year = tm.tm_year + 1900;
3168 tss->month = tm.tm_mon + 1;
3169 tss->day = tm.tm_mday;
3170 #endif
3171 }
3172 /* Normalize fraction */
3173 if (tss->fraction < 0) {
3174 tss->fraction = 0;
3175 }
3176 /* Final check for overflow */
3177 if (err ||
3178 tss->month < 1 || tss->month > 12 ||
3179 tss->day < 1 || tss->day > getmdays(tss->year, tss->month) ||
3180 tss->hour > 23 || tss->minute > 59 || tss->second > 59) {
3181 return -1;
3182 }
3183 if ((m & 7) > 1) {
3184 if (ampm > 0) {
3185 if (tss->hour < 12) {
3186 tss->hour += 12;
3187 }
3188 } else if (ampm == 0) {
3189 if (tss->hour == 12) {
3190 tss->hour = 0;
3191 }
3192 }
3193 }
3194 return ((m & 7) < 1) ? -1 : 0;
3195 }
3196
3197 /**
3198 * Get boolean flag from string.
3199 * @param string string to be inspected
3200 * @result true or false
3201 */
3202
3203 static int
getbool(char * string)3204 getbool(char *string)
3205 {
3206 if (string) {
3207 return string[0] && strchr("Yy123456789Tt", string[0]) != NULL;
3208 }
3209 return 0;
3210 }
3211
3212 /**
3213 * SQLite function to import a BLOB from a file
3214 * @param ctx function context
3215 * @param nargs number arguments
3216 * @param args arguments
3217 */
3218
3219 static void
blob_import(sqlite3_context * ctx,int nargs,sqlite3_value ** args)3220 blob_import(sqlite3_context *ctx, int nargs, sqlite3_value **args)
3221 {
3222 #if 0
3223 DBC *d = (DBC *) sqlite3_user_data(ctx);
3224 #endif
3225 char *filename = 0;
3226
3227 if (nargs > 0) {
3228 if (sqlite3_value_type(args[0]) != SQLITE_NULL) {
3229 filename = (char *) sqlite3_value_text(args[0]);
3230 }
3231 }
3232 if (filename) {
3233 #ifdef _WIN32
3234 char *wname = utf_to_wmb(filename, -1);
3235 FILE *f;
3236 #else
3237 FILE *f = fopen(filename, "r");
3238 #endif
3239 char *p;
3240 long n, nn;
3241
3242 #ifdef _WIN32
3243 if (wname) {
3244 f = fopen(wname, "rb");
3245 } else {
3246 sqlite3_result_error(ctx, "out of memory", -1);
3247 return;
3248 }
3249 uc_free(wname);
3250 #endif
3251 if (f) {
3252 if (fseek(f, 0, SEEK_END) == 0) {
3253 n = ftell(f);
3254 if (fseek(f, 0, SEEK_SET) == 0) {
3255 p = sqlite3_malloc(n);
3256 if (p) {
3257 nn = fread(p, 1, n, f);
3258 if (nn != n) {
3259 sqlite3_result_error(ctx, "read error", -1);
3260 sqlite3_free(p);
3261 } else {
3262 sqlite3_result_blob(ctx, p, n, sqlite3_free);
3263 }
3264 } else {
3265 sqlite3_result_error(ctx, "out of memory", -1);
3266 }
3267 } else {
3268 sqlite3_result_error(ctx, "seek error", -1);
3269 }
3270 } else {
3271 sqlite3_result_error(ctx, "seek error", -1);
3272 }
3273 fclose(f);
3274 } else {
3275 sqlite3_result_error(ctx, "cannot open file", -1);
3276 }
3277 } else {
3278 sqlite3_result_error(ctx, "no filename given", -1);
3279 }
3280 }
3281
3282 /**
3283 * SQLite function to export a BLOB to a file
3284 * @param ctx function context
3285 * @param nargs number arguments
3286 * @param args arguments
3287 */
3288
3289 static void
blob_export(sqlite3_context * ctx,int nargs,sqlite3_value ** args)3290 blob_export(sqlite3_context *ctx, int nargs, sqlite3_value **args)
3291 {
3292 #if 0
3293 DBC *d = (DBC *) sqlite3_user_data(ctx);
3294 #endif
3295 char *filename = 0;
3296 char *p = 0;
3297 int n = 0;
3298
3299 if (nargs > 0) {
3300 p = (char *) sqlite3_value_blob(args[0]);
3301 n = sqlite3_value_bytes(args[0]);
3302 }
3303 if (nargs > 1) {
3304 if (sqlite3_value_type(args[1]) != SQLITE_NULL) {
3305 filename = (char *) sqlite3_value_text(args[1]);
3306 }
3307 }
3308 if (p) {
3309 if (filename) {
3310 #ifdef _WIN32
3311 char *wname = utf_to_wmb(filename, -1);
3312 FILE *f;
3313 #else
3314 FILE *f = fopen(filename, "w");
3315 #endif
3316 int nn;
3317
3318 #ifdef _WIN32
3319 if (wname) {
3320 f = fopen(wname, "wb");
3321 } else {
3322 sqlite3_result_error(ctx, "out of memory", -1);
3323 return;
3324 }
3325 uc_free(wname);
3326 #endif
3327 if (f) {
3328 nn = fwrite(p, 1, n, f);
3329 if (nn != n) {
3330 sqlite3_result_error(ctx, "write error", -1);
3331 } else {
3332 sqlite3_result_int(ctx, nn);
3333 }
3334 } else {
3335 sqlite3_result_error(ctx, "cannot open file", -1);
3336 }
3337 } else {
3338 sqlite3_result_error(ctx, "no filename given", -1);
3339 }
3340 } else {
3341 sqlite3_result_null(ctx);
3342 }
3343 }
3344
3345 /**
3346 * SQLite trace or profile callback
3347 * @param arg DBC pointer
3348 * @param msg log message, SQL text
3349 * @param et elapsed time
3350 */
3351
3352 static void
3353 #if defined(HAVE_SQLITE3PROFILE) && (HAVE_SQLITE3PROFILE)
dbtrace(void * arg,const char * msg,sqlite_uint64 et)3354 dbtrace(void *arg, const char *msg, sqlite_uint64 et)
3355 #else
3356 dbtrace(void *arg, const char *msg)
3357 #endif
3358 {
3359 DBC *d = (DBC *) arg;
3360
3361 if (msg && d->trace) {
3362 int len = strlen(msg);
3363 #if defined(HAVE_SQLITE3PROFILE) && (HAVE_SQLITE3PROFILE)
3364 unsigned long s, f;
3365 #endif
3366
3367 if (len > 0) {
3368 char *end = "\n";
3369
3370 if (msg[len - 1] != ';') {
3371 end = ";\n";
3372 }
3373 fprintf(d->trace, "%s%s", msg, end);
3374 #if defined(HAVE_SQLITE3PROFILE) && (HAVE_SQLITE3PROFILE)
3375 s = et / 1000000000LL;
3376 f = et % 1000000000LL;
3377 fprintf(d->trace, "-- took %lu.%09lu seconds\n", s, f);
3378 #endif
3379 fflush(d->trace);
3380 }
3381 }
3382 }
3383
3384 /**
3385 * Trace function for SQLite API calls
3386 * @param d pointer to database connection handle
3387 * @param fn SQLite function name
3388 * @param sql SQL string
3389 */
3390
3391 static void
dbtraceapi(DBC * d,char * fn,const char * sql)3392 dbtraceapi(DBC *d, char *fn, const char *sql)
3393 {
3394 if (fn && d->trace) {
3395 if (sql) {
3396 fprintf(d->trace, "-- %s: %s\n", fn, sql);
3397 } else {
3398 fprintf(d->trace, "-- %s\n", fn);
3399 }
3400 fflush(d->trace);
3401 }
3402 }
3403
3404 /**
3405 * Trace function for SQLite return codes
3406 * @param d pointer to database connection handle
3407 * @param rc SQLite return code
3408 * @param err error string or NULL
3409 */
3410
3411 static void
dbtracerc(DBC * d,int rc,char * err)3412 dbtracerc(DBC *d, int rc, char *err)
3413 {
3414 if (rc != SQLITE_OK && d->trace) {
3415 fprintf(d->trace, "-- SQLITE ERROR CODE %d", rc);
3416 fprintf(d->trace, err ? ": %s\n" : "\n", err);
3417 fflush(d->trace);
3418 }
3419 }
3420
3421 /**
3422 * Open SQLite database file given file name and flags.
3423 * @param d DBC pointer
3424 * @param name file name
3425 * @param isu true/false: file name is UTF8 encoded
3426 * @param dsn data source name
3427 * @param sflag STEPAPI flag
3428 * @param spflag SyncPragma string
3429 * @param ntflag NoTransaction string
3430 * @param jmode JournalMode string
3431 * @param busy busy/lock timeout
3432 * @result ODBC error code
3433 */
3434
3435 static SQLRETURN
dbopen(DBC * d,char * name,int isu,char * dsn,char * sflag,char * spflag,char * ntflag,char * jmode,char * busy)3436 dbopen(DBC *d, char *name, int isu, char *dsn, char *sflag,
3437 char *spflag, char *ntflag, char *jmode, char *busy)
3438 {
3439 char *endp = NULL;
3440 int rc, tmp, busyto = 100000;
3441 #if defined(HAVE_SQLITE3VFS) && (HAVE_SQLITE3VFS)
3442 int flags = SQLITE_OPEN_READWRITE | SQLITE_OPEN_CREATE;
3443 char *uname = name;
3444 const char *vfs_name = NULL;
3445 #endif
3446
3447 if (d->sqlite) {
3448 if (d->trace) {
3449 fprintf(d->trace, "-- sqlite3_close (deferred): '%s'\n",
3450 d->dbname);
3451 fflush(d->trace);
3452 }
3453 sqlite3_close(d->sqlite);
3454 d->sqlite = NULL;
3455 }
3456 #if defined(HAVE_SQLITE3VFS) && (HAVE_SQLITE3VFS)
3457 if (d->nocreat) {
3458 flags &= ~ SQLITE_OPEN_CREATE;
3459 }
3460 #if defined(_WIN32) || defined(_WIN64)
3461 if (!isu) {
3462 uname = wmb_to_utf(name, -1);
3463 if (!uname) {
3464 rc = SQLITE_NOMEM;
3465 setstatd(d, rc, "out of memory", (*d->ov3) ? "HY000" : "S1000");
3466 return SQL_ERROR;
3467 }
3468 }
3469 #endif
3470 #if defined(ENABLE_NVFS) && (ENABLE_NVFS)
3471 vfs_name = nvfs_makevfs(uname);
3472 #endif
3473 #ifdef SQLITE_OPEN_URI
3474 flags |= SQLITE_OPEN_URI;
3475 #endif
3476 rc = sqlite3_open_v2(uname, &d->sqlite, flags, vfs_name);
3477 #if defined(WINTERFACE) || defined(_WIN32) || defined(_WIN64)
3478 if (uname != name) {
3479 uc_free(uname);
3480 }
3481 #endif
3482 #else
3483 #if defined(_WIN32) || defined(_WIN64)
3484 if (d->nocreat) {
3485 char *cname = NULL;
3486
3487 if (isu) {
3488 cname = utf_to_wmb(name, -1);
3489 }
3490 if (GetFileAttributesA(cname ? cname : name) ==
3491 INVALID_FILE_ATTRIBUTES) {
3492 uc_free(cname);
3493 rc = SQLITE_CANTOPEN;
3494 setstatd(d, rc, "cannot open database",
3495 (*d->ov3) ? "HY000" : "S1000");
3496 return SQL_ERROR;
3497 }
3498 uc_free(cname);
3499 }
3500 #else
3501 if (d->nocreat && access(name, 004) < 0) {
3502 rc = SQLITE_CANTOPEN;
3503 setstatd(d, rc, "cannot open database", (*d->ov3) ? "HY000" : "S1000");
3504 return SQL_ERROR;
3505 }
3506 #endif
3507 #if defined(_WIN32) || defined(_WIN64)
3508 if (!isu) {
3509 WCHAR *wname = wmb_to_uc(name, -1);
3510
3511 if (!wname) {
3512 rc = SQLITE_NOMEM;
3513 setstatd(d, rc, "out of memory", (*d->ov3) ? "HY000" : "S1000");
3514 return SQL_ERROR;
3515 }
3516 rc = sqlite3_open16(wname, &d->sqlite);
3517 uc_free(wname);
3518 } else
3519 #endif
3520 rc = sqlite3_open(name, &d->sqlite);
3521 #endif /* !HAVE_SQLITE3VFS */
3522 if (rc != SQLITE_OK) {
3523 connfail:
3524 setstatd(d, rc, "connect failed", (*d->ov3) ? "HY000" : "S1000");
3525 if (d->sqlite) {
3526 sqlite3_close(d->sqlite);
3527 d->sqlite = NULL;
3528 }
3529 return SQL_ERROR;
3530 }
3531 #if defined(SQLITE_DYNLOAD) || defined(SQLITE_HAS_CODEC)
3532 if (d->pwd) {
3533 sqlite3_key(d->sqlite, d->pwd, d->pwdLen);
3534 }
3535 #endif
3536 d->pwd = NULL;
3537 d->pwdLen = 0;
3538 if (d->trace) {
3539 #if defined(HAVE_SQLITE3PROFILE) && (HAVE_SQLITE3PROFILE)
3540 sqlite3_profile(d->sqlite, dbtrace, d);
3541 #else
3542 sqlite3_trace(d->sqlite, dbtrace, d);
3543 #endif
3544 }
3545 d->step_enable = getbool(sflag);
3546 d->trans_disable = getbool(ntflag);
3547 d->curtype = d->step_enable ?
3548 SQL_CURSOR_FORWARD_ONLY : SQL_CURSOR_STATIC;
3549 tmp = strtol(busy, &endp, 0);
3550 if (endp && *endp == '\0' && endp != busy) {
3551 busyto = tmp;
3552 }
3553 if (busyto < 1 || busyto > 1000000) {
3554 busyto = 1000000;
3555 }
3556 d->timeout = busyto;
3557 if ((rc = setsqliteopts(d->sqlite, d)) != SQLITE_OK) {
3558 if (d->trace) {
3559 fprintf(d->trace, "-- sqlite3_close: '%s'\n",
3560 d->dbname);
3561 fflush(d->trace);
3562 }
3563 sqlite3_close(d->sqlite);
3564 d->sqlite = NULL;
3565 goto connfail;
3566 }
3567 if (!spflag || spflag[0] == '\0') {
3568 spflag = "NORMAL";
3569 }
3570 if (spflag[0] != '\0') {
3571 char syncp[128];
3572
3573 sprintf(syncp, "PRAGMA synchronous = %8.8s;", spflag);
3574 sqlite3_exec(d->sqlite, syncp, NULL, NULL, NULL);
3575 }
3576 if (jmode[0] != '\0') {
3577 char jourp[128];
3578
3579 sprintf(jourp, "PRAGMA journal_mode = %16.16s;", jmode);
3580 sqlite3_exec(d->sqlite, jourp, NULL, NULL, NULL);
3581 }
3582 freep(&d->dbname);
3583 d->dbname = xstrdup(name);
3584 freep(&d->dsn);
3585 d->dsn = xstrdup(dsn);
3586 if (d->trace) {
3587 fprintf(d->trace, "-- sqlite3_open: '%s'\n", d->dbname);
3588 fflush(d->trace);
3589 }
3590 #if defined(_WIN32) || defined(_WIN64)
3591 {
3592 char pname[MAX_PATH];
3593 HANDLE h = OpenProcess(PROCESS_QUERY_INFORMATION | PROCESS_VM_READ,
3594 FALSE, GetCurrentProcessId());
3595
3596 pname[0] = '\0';
3597 if (h) {
3598 HMODULE m = NULL, l = LoadLibrary("psapi.dll");
3599 DWORD need;
3600 typedef BOOL (WINAPI *epmfunc)(HANDLE, HMODULE *, DWORD, LPDWORD);
3601 typedef BOOL (WINAPI *gmbfunc)(HANDLE, HMODULE, LPSTR, DWORD);
3602 epmfunc epm;
3603 gmbfunc gmb;
3604
3605 if (l) {
3606 epm = (epmfunc) GetProcAddress(l, "EnumProcessModules");
3607 gmb = (gmbfunc) GetProcAddress(l, "GetModuleBaseNameA");
3608 if (epm && gmb && epm(h, &m, sizeof (m), &need)) {
3609 gmb(h, m, pname, sizeof (pname));
3610 }
3611 FreeLibrary(l);
3612 }
3613 CloseHandle(h);
3614 }
3615 d->xcelqrx = strncasecmp(pname, "EXCEL", 5) == 0 ||
3616 strncasecmp(pname, "MSQRY", 5) == 0;
3617 if (d->trace && d->xcelqrx) {
3618 fprintf(d->trace, "-- enabled EXCEL quirks\n");
3619 fflush(d->trace);
3620 }
3621 }
3622 #endif
3623 sqlite3_create_function(d->sqlite, "blob_import", 1, SQLITE_UTF8,
3624 d, blob_import, 0, 0);
3625 sqlite3_create_function(d->sqlite, "blob_export", 2, SQLITE_UTF8,
3626 d, blob_export, 0, 0);
3627 return SQL_SUCCESS;
3628 }
3629
3630 /**
3631 * Load SQLite extension modules, if any
3632 * @param d DBC pointer
3633 * @param exts string, comma separated extension names
3634 */
3635
3636 static void
dbloadext(DBC * d,char * exts)3637 dbloadext(DBC *d, char *exts)
3638 {
3639 #if defined(HAVE_SQLITE3LOADEXTENSION) && (HAVE_SQLITE3LOADEXTENSION)
3640 char *p;
3641 char path[SQL_MAX_MESSAGE_LENGTH];
3642 int plen = 0;
3643
3644 if (!d->sqlite) {
3645 return;
3646 }
3647 sqlite3_enable_load_extension(d->sqlite, 1);
3648 #if defined(_WIN32) || defined(_WIN64)
3649 GetModuleFileName(hModule, path, sizeof (path));
3650 p = strrchr(path, '\\');
3651 plen = p ? ((p + 1) - path) : 0;
3652 #endif
3653 do {
3654 p = strchr(exts, ',');
3655 if (p) {
3656 strncpy(path + plen, exts, p - exts);
3657 path[plen + (p - exts)] = '\0';
3658 } else {
3659 strcpy(path + plen, exts);
3660 }
3661 if (exts[0]) {
3662 char *errmsg = NULL;
3663 int rc;
3664 #if defined(_WIN32) || defined(_WIN64)
3665 char *q;
3666
3667 q = path + plen;
3668 if (!(q[0] &&
3669 ((q[1] == ':' && (q[2] == '\\' || q[2] == '/')) ||
3670 q[0] == '\\' || q[0] == '/' || q[0] == '.'))) {
3671 q = path;
3672 }
3673 rc = sqlite3_load_extension(d->sqlite, q, 0, &errmsg);
3674 #else
3675 rc = sqlite3_load_extension(d->sqlite, path, 0, &errmsg);
3676 #endif
3677 if (rc != SQLITE_OK) {
3678 #if defined(_WIN32) || defined(_WIN64)
3679 char buf[512], msg[512];
3680
3681 LoadString(hModule, IDS_EXTERR, buf, sizeof (buf));
3682 wsprintf(msg, buf, q, errmsg ?
3683 errmsg : "no error info available");
3684 LoadString(hModule, IDS_EXTTITLE, buf, sizeof (buf));
3685 MessageBox(NULL, msg, buf,
3686 MB_ICONEXCLAMATION | MB_OK | MB_TASKMODAL |
3687 MB_SETFOREGROUND);
3688 #else
3689 fprintf(stderr, "extension '%s' did not load%s%s\n",
3690 path, errmsg ? ": " : "", errmsg ? errmsg : "");
3691 #endif
3692 }
3693 }
3694 if (p) {
3695 exts = p + 1;
3696 }
3697 } while (p);
3698 #endif /* HAVE_SQLITE3LOADEXTENSION */
3699 }
3700
3701 /**
3702 * Find out column type
3703 * @param s3stmt SQLite statement pointer
3704 * @param col column number
3705 * @param d DBC pointer (for tracing only)
3706 * @param guessed_types flag array
3707 * @result type name as string
3708 */
3709
3710 static char *
s3stmt_coltype(sqlite3_stmt * s3stmt,int col,DBC * d,int * guessed_types)3711 s3stmt_coltype(sqlite3_stmt *s3stmt, int col, DBC *d, int *guessed_types)
3712 {
3713 char *typename = (char *) sqlite3_column_decltype(s3stmt, col);
3714 char guess[64];
3715
3716 guess[0] = '\0';
3717 if (!typename) {
3718 int coltype = sqlite3_column_type(s3stmt, col);
3719
3720 if (guessed_types) {
3721 guessed_types[0]++;
3722 }
3723 if (d->trace) {
3724 sprintf(guess, " (guessed from %d)", coltype);
3725 }
3726 switch (coltype) {
3727 case SQLITE_INTEGER: typename = "integer"; break;
3728 case SQLITE_FLOAT: typename = "double"; break;
3729 default:
3730 case SQLITE_TEXT: typename = "varchar"; break;
3731 case SQLITE_BLOB: typename = "blob"; break;
3732 #if 0
3733 case SQLITE_NULL: typename = "null"; break;
3734 #endif
3735 }
3736 }
3737 if (d->trace) {
3738 fprintf(d->trace, "-- column %d type%s: '%s'\n", col + 1,
3739 guess, typename);
3740 fflush(d->trace);
3741 }
3742 return typename;
3743 }
3744
3745 #if defined(HAVE_SQLITE3TABLECOLUMNMETADATA) && (HAVE_SQLITE3TABLECOLUMNMETADATA)
3746
3747 /**
3748 * Add meta data for column
3749 * @param s3stmt SQLite statement pointer
3750 * @param col column number
3751 * @param d DBC pointer (for tracing only)
3752 * @param ci pointer to COL
3753 */
3754
3755 static void
s3stmt_addmeta(sqlite3_stmt * s3stmt,int col,DBC * d,COL * ci)3756 s3stmt_addmeta(sqlite3_stmt *s3stmt, int col, DBC *d, COL *ci)
3757 {
3758 int nn = 0, pk = 0, ai = 0;
3759 const char *dn, *tn, *cn, *dummy1, *dummy2;
3760
3761 dn = sqlite3_column_database_name(s3stmt, col);
3762 tn = sqlite3_column_table_name(s3stmt, col);
3763 cn = sqlite3_column_origin_name(s3stmt, col);
3764 sqlite3_table_column_metadata(d->sqlite, dn, tn, cn,
3765 &dummy1, &dummy2,
3766 &nn, &pk, &ai);
3767 ci->autoinc = ai ? SQL_TRUE: SQL_FALSE;
3768 ci->notnull = nn ? SQL_NO_NULLS : SQL_NULLABLE;
3769 if (d->trace) {
3770 fprintf(d->trace, "-- column %d %s\n",
3771 col + 1, nn ? "notnull" : "nullable");
3772 if (ai) {
3773 fprintf(d->trace, "-- column %d autoincrement\n", col + 1);
3774 }
3775 fflush(d->trace);
3776 }
3777 }
3778
3779 #endif
3780
3781 /**
3782 * Do one sqlite statement step gathering one result row
3783 * @param s statement pointer
3784 * @result ODBC error code
3785 */
3786
3787 static int
s3stmt_step(STMT * s)3788 s3stmt_step(STMT *s)
3789 {
3790 DBC *d = (DBC *) s->dbc;
3791 char **rowd = NULL;
3792 const char *errp = NULL;
3793 int i, ncols, rc;
3794
3795 if (s != d->cur_s3stmt || !s->s3stmt) {
3796 setstat(s, -1, "stale statement", (*s->ov3) ? "HY000" : "S1000");
3797 return SQL_ERROR;
3798 }
3799 rc = sqlite3_step(s->s3stmt);
3800 if (rc == SQLITE_ROW || rc == SQLITE_DONE) {
3801 ++s->s3stmt_rownum;
3802 ncols = sqlite3_column_count(s->s3stmt);
3803 if (d->s3stmt_needmeta && s->s3stmt_rownum == 0 && ncols > 0) {
3804 PTRDIFF_T size;
3805 char *p;
3806 COL *dyncols;
3807 const char *colname, *typename;
3808 #if defined(HAVE_SQLITE3COLUMNTABLENAME) && (HAVE_SQLITE3COLUMNTABLENAME)
3809 char *tblname;
3810 #endif
3811
3812 for (i = size = 0; i < ncols; i++) {
3813 colname = sqlite3_column_name(s->s3stmt, i);
3814 size += 3 + 3 * strlen(colname);
3815 }
3816 #if defined(HAVE_SQLITE3COLUMNTABLENAME) && (HAVE_SQLITE3COLUMNTABLENAME)
3817 tblname = (char *) size;
3818 for (i = 0; i < ncols; i++) {
3819 p = (char *) sqlite3_column_table_name(s->s3stmt, i);
3820 size += 2 + (p ? strlen(p) : 0);
3821 }
3822 #endif
3823 dyncols = xmalloc(ncols * sizeof (COL) + size);
3824 if (!dyncols) {
3825 freedyncols(s);
3826 s->ncols = 0;
3827 dbtraceapi(d, "sqlite3_finalize", 0);
3828 sqlite3_finalize(s->s3stmt);
3829 s->s3stmt = NULL;
3830 d->cur_s3stmt = NULL;
3831 return nomem(s);
3832 }
3833 p = (char *) (dyncols + ncols);
3834 #if defined(HAVE_SQLITE3COLUMNTABLENAME) && (HAVE_SQLITE3COLUMNTABLENAME)
3835 tblname = p + (PTRDIFF_T) tblname;
3836 #endif
3837 for (i = 0; i < ncols; i++) {
3838 char *q;
3839
3840 colname = sqlite3_column_name(s->s3stmt, i);
3841 if (d->trace) {
3842 fprintf(d->trace, "-- column %d name: '%s'\n",
3843 i + 1, colname);
3844 fflush(d->trace);
3845 }
3846 #if defined(HAVE_SQLITE3COLUMNTABLENAME) && (HAVE_SQLITE3COLUMNTABLENAME)
3847 q = (char *) sqlite3_column_table_name(s->s3stmt, i);
3848 strcpy(tblname, q ? q : "");
3849 if (d->trace) {
3850 fprintf(d->trace, "-- table %d name: '%s'\n",
3851 i + 1, tblname);
3852 fflush(d->trace);
3853 }
3854 dyncols[i].table = tblname;
3855 tblname += strlen(tblname) + 1;
3856 #endif
3857 typename = s3stmt_coltype(s->s3stmt, i, d, 0);
3858 dyncols[i].db = ((DBC *) (s->dbc))->dbname;
3859 strcpy(p, colname);
3860 dyncols[i].label = p;
3861 p += strlen(p) + 1;
3862 q = strchr(colname, '.');
3863 if (q) {
3864 char *q2 = strchr(q + 1, '.');
3865
3866 /* SQLite 3.3.4 produces view.table.column sometimes */
3867 if (q2) {
3868 q = q2;
3869 }
3870 }
3871 if (q) {
3872 #if !defined(HAVE_SQLITE3COLUMNTABLENAME) || !(HAVE_SQLITE3COLUMNTABLENAME)
3873 dyncols[i].table = p;
3874 #endif
3875 strncpy(p, colname, q - colname);
3876 p[q - colname] = '\0';
3877 p += strlen(p) + 1;
3878 strcpy(p, q + 1);
3879 dyncols[i].column = p;
3880 p += strlen(p) + 1;
3881 } else {
3882 #if !defined(HAVE_SQLITE3COLUMNTABLENAME) || !(HAVE_SQLITE3COLUMNTABLENAME)
3883 dyncols[i].table = "";
3884 #endif
3885 strcpy(p, colname);
3886 dyncols[i].column = p;
3887 p += strlen(p) + 1;
3888 }
3889 if (s->longnames) {
3890 dyncols[i].column = dyncols[i].label;
3891 }
3892 #ifdef SQL_LONGVARCHAR
3893 dyncols[i].type = SQL_LONGVARCHAR;
3894 dyncols[i].size = 65535;
3895 #else
3896 dyncols[i].type = SQL_VARCHAR;
3897 dyncols[i].size = 255;
3898 #endif
3899 dyncols[i].index = i;
3900 dyncols[i].scale = 0;
3901 dyncols[i].prec = 0;
3902 dyncols[i].nosign = 1;
3903 #if defined(HAVE_SQLITE3TABLECOLUMNMETADATA) && (HAVE_SQLITE3TABLECOLUMNMETADATA)
3904 s3stmt_addmeta(s->s3stmt, i, d, &dyncols[i]);
3905 #else
3906 dyncols[i].autoinc = SQL_FALSE;
3907 dyncols[i].notnull = SQL_NULLABLE;
3908 #endif
3909 dyncols[i].typename = xstrdup(typename);
3910 }
3911 freedyncols(s);
3912 s->ncols = s->dcols = ncols;
3913 s->dyncols = s->cols = dyncols;
3914 fixupdyncols(s, d);
3915 mkbindcols(s, s->ncols);
3916 d->s3stmt_needmeta = 0;
3917 }
3918 if (ncols <= 0) {
3919 goto killstmt;
3920 }
3921 if (rc == SQLITE_DONE) {
3922 freeresult(s, 0);
3923 s->nrows = 0;
3924 dbtraceapi(d, "sqlite3_finalize", 0);
3925 sqlite3_finalize(s->s3stmt);
3926 s->s3stmt = NULL;
3927 d->cur_s3stmt = NULL;
3928 return SQL_SUCCESS;
3929 }
3930 rowd = xmalloc((1 + 2 * ncols) * sizeof (char *));
3931 if (rowd) {
3932 const unsigned char *value;
3933
3934 rowd[0] = (char *) ((PTRDIFF_T) (ncols * 2));
3935 ++rowd;
3936 for (i = 0; i < ncols; i++) {
3937 int coltype = sqlite3_column_type(s->s3stmt, i);
3938
3939 rowd[i] = rowd[i + ncols] = NULL;
3940 if (coltype == SQLITE_BLOB) {
3941 int k, nbytes = sqlite3_column_bytes(s->s3stmt, i);
3942 char *qp;
3943 unsigned const char *bp;
3944
3945 bp = sqlite3_column_blob(s->s3stmt, i);
3946 qp = xmalloc(nbytes * 2 + 4);
3947 if (qp) {
3948 rowd[i + ncols] = qp;
3949 *qp++ = 'X';
3950 *qp++ = '\'';
3951 for (k = 0; k < nbytes; k++) {
3952 *qp++ = xdigits[(bp[k] >> 4)];
3953 *qp++ = xdigits[(bp[k] & 0xF)];
3954 }
3955 *qp++ = '\'';
3956 *qp = '\0';
3957 }
3958 } else if (coltype != SQLITE_NULL) {
3959 value = sqlite3_column_text(s->s3stmt, i);
3960 rowd[i + ncols] = xstrdup((char *) value);
3961 }
3962 }
3963 for (i = 0; i < ncols; i++) {
3964 int coltype = sqlite3_column_type(s->s3stmt, i);
3965
3966 value = NULL;
3967 if (coltype == SQLITE_BLOB) {
3968 value = sqlite3_column_blob(s->s3stmt, i);
3969 } else if (coltype != SQLITE_NULL) {
3970 value = sqlite3_column_text(s->s3stmt, i);
3971 }
3972 if (value && !rowd[i + ncols]) {
3973 freerows(rowd);
3974 rowd = 0;
3975 break;
3976 }
3977 }
3978 }
3979 if (rowd) {
3980 freeresult(s, 0);
3981 s->nrows = 1;
3982 s->rows = rowd;
3983 s->rowfree = freerows;
3984 if (rc == SQLITE_DONE) {
3985 dbtraceapi(d, "sqlite3_finalize", 0);
3986 sqlite3_finalize(s->s3stmt);
3987 s->s3stmt = NULL;
3988 d->cur_s3stmt = NULL;
3989 }
3990 return SQL_SUCCESS;
3991 }
3992 }
3993 killstmt:
3994 dbtraceapi(d, "sqlite3_reset", 0);
3995 rc = sqlite3_reset(s->s3stmt);
3996 s->s3stmt_noreset = 1;
3997 errp = sqlite3_errmsg(d->sqlite);
3998 if (d->cur_s3stmt == s) {
3999 d->cur_s3stmt = NULL;
4000 }
4001 setstat(s, rc, "%s (%d)", (*s->ov3) ? "HY000" : "S1000",
4002 errp ? errp : "unknown error", rc);
4003 return SQL_ERROR;
4004 }
4005
4006 /**
4007 * Stop running sqlite statement
4008 * @param s statement pointer
4009 */
4010
4011 static void
s3stmt_end(STMT * s)4012 s3stmt_end(STMT *s)
4013 {
4014 DBC *d;
4015
4016 if (!s || !s->s3stmt) {
4017 return;
4018 }
4019 d = (DBC *) s->dbc;
4020 if (d) {
4021 d->busyint = 0;
4022 }
4023 if (!s->s3stmt_noreset) {
4024 dbtraceapi(d, "sqlite3_reset", 0);
4025 sqlite3_reset(s->s3stmt);
4026 s->s3stmt_noreset = 1;
4027 s->s3stmt_rownum = -1;
4028 }
4029 if (d->cur_s3stmt == s) {
4030 d->cur_s3stmt = NULL;
4031 }
4032 }
4033
4034 /**
4035 * Conditionally stop running sqlite statement
4036 * @param s statement pointer
4037 */
4038
4039 static void
s3stmt_end_if(STMT * s)4040 s3stmt_end_if(STMT *s)
4041 {
4042 DBC *d = (DBC *) s->dbc;
4043
4044 if (d) {
4045 d->busyint = 0;
4046 }
4047 if (d && d->cur_s3stmt == s) {
4048 s3stmt_end(s);
4049 }
4050 }
4051
4052 /**
4053 * Drop running sqlite statement in STMT
4054 * @param s statement pointer
4055 */
4056
4057 static void
s3stmt_drop(STMT * s)4058 s3stmt_drop(STMT *s)
4059 {
4060 if (s->s3stmt) {
4061 DBC *d = (DBC *) s->dbc;
4062
4063 if (d) {
4064 dbtraceapi(d, "sqlite3_finalize", 0);
4065 }
4066 sqlite3_finalize(s->s3stmt);
4067 s->s3stmt = NULL;
4068 s->s3stmt_rownum = 0;
4069 }
4070 }
4071
4072 /**
4073 * Start sqlite statement for execution of SELECT statement.
4074 * @param s statement pointer
4075 * @result ODBC error code
4076 */
4077
4078 static SQLRETURN
s3stmt_start(STMT * s)4079 s3stmt_start(STMT *s)
4080 {
4081 DBC *d = (DBC *) s->dbc;
4082 const char *endp;
4083 sqlite3_stmt *s3stmt = NULL;
4084 int rc, nretry = 0;
4085
4086 d->s3stmt_needmeta = 0;
4087 if (!s->s3stmt) {
4088 #if defined(HAVE_SQLITE3PREPAREV2) && (HAVE_SQLITE3PREPAREV2)
4089 dbtraceapi(d, "sqlite3_prepare_v2", (char *) s->query);
4090 #else
4091 dbtraceapi(d, "sqlite3_prepare", (char *) s->query);
4092 #endif
4093 do {
4094 s3stmt = NULL;
4095 #if defined(HAVE_SQLITE3PREPAREV2) && (HAVE_SQLITE3PREPAREV2)
4096 rc = sqlite3_prepare_v2(d->sqlite, (char *) s->query, -1,
4097 &s3stmt, &endp);
4098 #else
4099 rc = sqlite3_prepare(d->sqlite, (char *) s->query, -1,
4100 &s3stmt, &endp);
4101 #endif
4102 if (rc != SQLITE_OK) {
4103 if (s3stmt) {
4104 sqlite3_finalize(s3stmt);
4105 s3stmt = NULL;
4106 }
4107 }
4108 } while (rc == SQLITE_SCHEMA && (++nretry) < 2);
4109 dbtracerc(d, rc, NULL);
4110 if (rc != SQLITE_OK) {
4111 if (s3stmt) {
4112 dbtraceapi(d, "sqlite3_finalize", NULL);
4113 sqlite3_finalize(s3stmt);
4114 }
4115 setstat(s, rc, "%s (%d)", (*s->ov3) ? "HY000" : "S1000",
4116 sqlite3_errmsg(d->sqlite), rc);
4117 return SQL_ERROR;
4118 }
4119 if (sqlite3_bind_parameter_count(s3stmt) != s->nparams) {
4120 dbtraceapi(d, "sqlite3_finalize", 0);
4121 sqlite3_finalize(s3stmt);
4122 setstat(s, SQLITE_ERROR, "parameter marker count incorrect",
4123 (*s->ov3) ? "HY000" : "S1000");
4124 return SQL_ERROR;
4125 }
4126 s->s3stmt = s3stmt;
4127 s->s3stmt_noreset = 1;
4128 d->s3stmt_needmeta = 1;
4129 }
4130 d->cur_s3stmt = s;
4131 s->s3stmt_rownum = -1;
4132 s3bind(d, s->s3stmt, s->nparams, s->bindparms);
4133 return SQL_SUCCESS;
4134 }
4135
4136 /**
4137 * Function not implemented.
4138 */
4139
4140 SQLRETURN SQL_API
SQLBulkOperations(SQLHSTMT stmt,SQLSMALLINT oper)4141 SQLBulkOperations(SQLHSTMT stmt, SQLSMALLINT oper)
4142 {
4143 SQLRETURN ret;
4144
4145 HSTMT_LOCK(stmt);
4146 ret = drvunimplstmt(stmt);
4147 HSTMT_UNLOCK(stmt);
4148 return ret;
4149 }
4150
4151 #ifndef WINTERFACE
4152 /**
4153 * Function not implemented.
4154 */
4155
4156 SQLRETURN SQL_API
SQLDataSources(SQLHENV env,SQLUSMALLINT dir,SQLCHAR * srvname,SQLSMALLINT buflen1,SQLSMALLINT * lenp1,SQLCHAR * desc,SQLSMALLINT buflen2,SQLSMALLINT * lenp2)4157 SQLDataSources(SQLHENV env, SQLUSMALLINT dir, SQLCHAR *srvname,
4158 SQLSMALLINT buflen1, SQLSMALLINT *lenp1,
4159 SQLCHAR *desc, SQLSMALLINT buflen2, SQLSMALLINT *lenp2)
4160 {
4161 if (env == SQL_NULL_HENV) {
4162 return SQL_INVALID_HANDLE;
4163 }
4164 return SQL_ERROR;
4165 }
4166 #endif
4167
4168 #ifdef WINTERFACE
4169 /**
4170 * Function not implemented.
4171 */
4172
4173 SQLRETURN SQL_API
SQLDataSourcesW(SQLHENV env,SQLUSMALLINT dir,SQLWCHAR * srvname,SQLSMALLINT buflen1,SQLSMALLINT * lenp1,SQLWCHAR * desc,SQLSMALLINT buflen2,SQLSMALLINT * lenp2)4174 SQLDataSourcesW(SQLHENV env, SQLUSMALLINT dir, SQLWCHAR *srvname,
4175 SQLSMALLINT buflen1, SQLSMALLINT *lenp1,
4176 SQLWCHAR *desc, SQLSMALLINT buflen2, SQLSMALLINT *lenp2)
4177 {
4178 if (env == SQL_NULL_HENV) {
4179 return SQL_INVALID_HANDLE;
4180 }
4181 return SQL_ERROR;
4182 }
4183 #endif
4184
4185 #ifndef WINTERFACE
4186 /**
4187 * Function not implemented.
4188 */
4189
4190 SQLRETURN SQL_API
SQLDrivers(SQLHENV env,SQLUSMALLINT dir,SQLCHAR * drvdesc,SQLSMALLINT descmax,SQLSMALLINT * desclenp,SQLCHAR * drvattr,SQLSMALLINT attrmax,SQLSMALLINT * attrlenp)4191 SQLDrivers(SQLHENV env, SQLUSMALLINT dir, SQLCHAR *drvdesc,
4192 SQLSMALLINT descmax, SQLSMALLINT *desclenp,
4193 SQLCHAR *drvattr, SQLSMALLINT attrmax, SQLSMALLINT *attrlenp)
4194 {
4195 if (env == SQL_NULL_HENV) {
4196 return SQL_INVALID_HANDLE;
4197 }
4198 return SQL_ERROR;
4199 }
4200 #endif
4201
4202 #ifdef WINTERFACE
4203 /**
4204 * Function not implemented.
4205 */
4206
4207 SQLRETURN SQL_API
SQLDriversW(SQLHENV env,SQLUSMALLINT dir,SQLWCHAR * drvdesc,SQLSMALLINT descmax,SQLSMALLINT * desclenp,SQLWCHAR * drvattr,SQLSMALLINT attrmax,SQLSMALLINT * attrlenp)4208 SQLDriversW(SQLHENV env, SQLUSMALLINT dir, SQLWCHAR *drvdesc,
4209 SQLSMALLINT descmax, SQLSMALLINT *desclenp,
4210 SQLWCHAR *drvattr, SQLSMALLINT attrmax, SQLSMALLINT *attrlenp)
4211 {
4212 if (env == SQL_NULL_HENV) {
4213 return SQL_INVALID_HANDLE;
4214 }
4215 return SQL_ERROR;
4216 }
4217 #endif
4218
4219 #ifndef WINTERFACE
4220 /**
4221 * Function not implemented.
4222 */
4223
4224 SQLRETURN SQL_API
SQLBrowseConnect(SQLHDBC dbc,SQLCHAR * connin,SQLSMALLINT conninLen,SQLCHAR * connout,SQLSMALLINT connoutMax,SQLSMALLINT * connoutLen)4225 SQLBrowseConnect(SQLHDBC dbc, SQLCHAR *connin, SQLSMALLINT conninLen,
4226 SQLCHAR *connout, SQLSMALLINT connoutMax,
4227 SQLSMALLINT *connoutLen)
4228 {
4229 SQLRETURN ret;
4230
4231 HDBC_LOCK(dbc);
4232 ret = drvunimpldbc(dbc);
4233 HDBC_UNLOCK(dbc);
4234 return ret;
4235 }
4236 #endif
4237
4238 #ifdef WINTERFACE
4239 /**
4240 * Function not implemented.
4241 */
4242
4243 SQLRETURN SQL_API
SQLBrowseConnectW(SQLHDBC dbc,SQLWCHAR * connin,SQLSMALLINT conninLen,SQLWCHAR * connout,SQLSMALLINT connoutMax,SQLSMALLINT * connoutLen)4244 SQLBrowseConnectW(SQLHDBC dbc, SQLWCHAR *connin, SQLSMALLINT conninLen,
4245 SQLWCHAR *connout, SQLSMALLINT connoutMax,
4246 SQLSMALLINT *connoutLen)
4247 {
4248 SQLRETURN ret;
4249
4250 HDBC_LOCK(dbc);
4251 ret = drvunimpldbc(dbc);
4252 HDBC_UNLOCK(dbc);
4253 return ret;
4254 }
4255 #endif
4256
4257 /**
4258 * Internal put (partial) parameter data into executing statement.
4259 * @param stmt statement handle
4260 * @param data pointer to data
4261 * @param len length of data
4262 * @result ODBC error code
4263 */
4264
4265 static SQLRETURN
drvputdata(SQLHSTMT stmt,SQLPOINTER data,SQLLEN len)4266 drvputdata(SQLHSTMT stmt, SQLPOINTER data, SQLLEN len)
4267 {
4268 STMT *s;
4269 int i, dlen, done = 0;
4270 BINDPARM *p;
4271
4272 if (stmt == SQL_NULL_HSTMT) {
4273 return SQL_INVALID_HANDLE;
4274 }
4275 s = (STMT *) stmt;
4276 if (!s->query || s->nparams <= 0) {
4277 seqerr:
4278 setstat(s, -1, "sequence error", "HY010");
4279 return SQL_ERROR;
4280 }
4281 for (i = 0; i < s->nparams; i++) {
4282 p = &s->bindparms[i];
4283 if (p->need > 0) {
4284 int type = mapdeftype(p->type, p->stype, -1, s->nowchar[0]);
4285
4286 if (len == SQL_NULL_DATA) {
4287 freep(&p->parbuf);
4288 p->param = NULL;
4289 p->len = SQL_NULL_DATA;
4290 p->need = -1;
4291 } else if (type != SQL_C_CHAR
4292 #ifdef WCHARSUPPORT
4293 && type != SQL_C_WCHAR
4294 #endif
4295 && type != SQL_C_BINARY) {
4296 int size = 0;
4297
4298 switch (type) {
4299 case SQL_C_TINYINT:
4300 case SQL_C_UTINYINT:
4301 case SQL_C_STINYINT:
4302 #ifdef SQL_BIT
4303 case SQL_C_BIT:
4304 #endif
4305 size = sizeof (char);
4306 break;
4307 case SQL_C_SHORT:
4308 case SQL_C_USHORT:
4309 case SQL_C_SSHORT:
4310 size = sizeof (short);
4311 break;
4312 case SQL_C_LONG:
4313 case SQL_C_ULONG:
4314 case SQL_C_SLONG:
4315 size = sizeof (long);
4316 break;
4317 #ifdef SQL_BIGINT
4318 case SQL_C_UBIGINT:
4319 case SQL_C_SBIGINT:
4320 size = sizeof (SQLBIGINT);
4321 break;
4322 #endif
4323 case SQL_C_FLOAT:
4324 size = sizeof (float);
4325 break;
4326 case SQL_C_DOUBLE:
4327 size = sizeof (double);
4328 break;
4329 #ifdef SQL_C_TYPE_DATE
4330 case SQL_C_TYPE_DATE:
4331 #endif
4332 case SQL_C_DATE:
4333 size = sizeof (DATE_STRUCT);
4334 break;
4335 #ifdef SQL_C_TYPE_DATE
4336 case SQL_C_TYPE_TIME:
4337 #endif
4338 case SQL_C_TIME:
4339 size = sizeof (TIME_STRUCT);
4340 break;
4341 #ifdef SQL_C_TYPE_DATE
4342 case SQL_C_TYPE_TIMESTAMP:
4343 #endif
4344 case SQL_C_TIMESTAMP:
4345 size = sizeof (TIMESTAMP_STRUCT);
4346 break;
4347 }
4348 freep(&p->parbuf);
4349 p->parbuf = xmalloc(size);
4350 if (!p->parbuf) {
4351 return nomem(s);
4352 }
4353 p->param = p->parbuf;
4354 memcpy(p->param, data, size);
4355 p->len = size;
4356 p->need = -1;
4357 } else if (len == SQL_NTS && (
4358 type == SQL_C_CHAR
4359 #ifdef WCHARSUPPORT
4360 || type == SQL_C_WCHAR
4361 #endif
4362 )) {
4363 char *dp = data;
4364
4365 #ifdef WCHARSUPPORT
4366 if (type == SQL_C_WCHAR) {
4367 dp = uc_to_utf(data, len);
4368 if (!dp) {
4369 return nomem(s);
4370 }
4371 }
4372 #endif
4373 #if defined(_WIN32) || defined(_WIN64)
4374 if (*s->oemcp) {
4375 dp = wmb_to_utf(data, strlen (data));
4376 if (!dp) {
4377 return nomem(s);
4378 }
4379 }
4380 #endif
4381 dlen = strlen(dp);
4382 freep(&p->parbuf);
4383 p->parbuf = xmalloc(dlen + 1);
4384 if (!p->parbuf) {
4385 if (dp != data) {
4386 uc_free(dp);
4387 }
4388 return nomem(s);
4389 }
4390 p->param = p->parbuf;
4391 strcpy(p->param, dp);
4392 if (dp != data) {
4393 uc_free(dp);
4394 }
4395 p->len = dlen;
4396 p->need = -1;
4397 } else if (len < 0) {
4398 setstat(s, -1, "invalid length", "HY090");
4399 return SQL_ERROR;
4400 } else {
4401 dlen = min(p->len - p->offs, len);
4402 if (!p->param) {
4403 setstat(s, -1, "no memory for parameter", "HY013");
4404 return SQL_ERROR;
4405 }
4406 memcpy((char *) p->param + p->offs, data, dlen);
4407 p->offs += dlen;
4408 if (p->offs >= p->len) {
4409 #ifdef WCHARSUPPORT
4410 if (type == SQL_C_WCHAR) {
4411 char *dp = uc_to_utf(p->param, p->len);
4412 char *np;
4413 int nlen;
4414
4415 if (!dp) {
4416 return nomem(s);
4417 }
4418 nlen = strlen(dp);
4419 np = xmalloc(nlen + 1);
4420 if (!np) {
4421 uc_free(dp);
4422 return nomem(s);
4423 }
4424 strcpy(np, dp);
4425 uc_free(dp);
4426 if (p->param == p->parbuf) {
4427 freep(&p->parbuf);
4428 }
4429 p->parbuf = p->param = np;
4430 p->len = nlen;
4431 } else {
4432 *((char *) p->param + p->len) = '\0';
4433 }
4434 p->need = (type == SQL_C_CHAR || type == SQL_C_WCHAR)
4435 ? -1 : 0;
4436 #else
4437 *((char *) p->param + p->len) = '\0';
4438 p->need = (type == SQL_C_CHAR) ? -1 : 0;
4439 #endif
4440 #if defined(_WIN32) || defined(_WIN64)
4441 if (type == SQL_C_CHAR && *s->oemcp) {
4442 char *dp = wmb_to_utf(p->param, p->len);
4443
4444 if (!dp) {
4445 return nomem(s);
4446 }
4447 if (p->param == p->parbuf) {
4448 freep(&p->parbuf);
4449 }
4450 p->parbuf = p->param = dp;
4451 p->len = strlen(dp);
4452 }
4453 if (p->type == SQL_C_WCHAR &&
4454 (p->stype == SQL_VARCHAR ||
4455 p->stype == SQL_LONGVARCHAR) &&
4456 p->len == p->coldef * sizeof (SQLWCHAR)) {
4457 /* fix for MS-Access */
4458 p->len = p->coldef;
4459 }
4460 #endif
4461 }
4462 }
4463 done = 1;
4464 break;
4465 }
4466 }
4467 if (!done) {
4468 goto seqerr;
4469 }
4470 return SQL_SUCCESS;
4471 }
4472
4473 /**
4474 * Put (partial) parameter data into executing statement.
4475 * @param stmt statement handle
4476 * @param data pointer to data
4477 * @param len length of data
4478 * @result ODBC error code
4479 */
4480
4481 SQLRETURN SQL_API
SQLPutData(SQLHSTMT stmt,SQLPOINTER data,SQLLEN len)4482 SQLPutData(SQLHSTMT stmt, SQLPOINTER data, SQLLEN len)
4483 {
4484 SQLRETURN ret;
4485
4486 HSTMT_LOCK(stmt);
4487 ret = drvputdata(stmt, data, len);
4488 HSTMT_UNLOCK(stmt);
4489 return ret;
4490 }
4491
4492 /**
4493 * Clear out parameter bindings, if any.
4494 * @param s statement pointer
4495 */
4496
4497 static SQLRETURN
freeparams(STMT * s)4498 freeparams(STMT *s)
4499 {
4500 if (s->bindparms) {
4501 int n;
4502
4503 for (n = 0; n < s->nbindparms; n++) {
4504 freep(&s->bindparms[n].parbuf);
4505 memset(&s->bindparms[n], 0, sizeof (BINDPARM));
4506 }
4507 }
4508 return SQL_SUCCESS;
4509 }
4510
4511 /**
4512 * Setup SQLite3 parameter for statement parameter.
4513 * @param s statement pointer
4514 * @param sql sql string
4515 * @param pnum parameter number
4516 * @result ODBC error code
4517 *
4518 * The parameter is converted within BINDPARM in order to
4519 * be presented to sqlite3_bind_*() functions.
4520 */
4521
4522 static SQLRETURN
setupparam(STMT * s,char * sql,int pnum)4523 setupparam(STMT *s, char *sql, int pnum)
4524 {
4525 int type, len = 0, needalloc = 0;
4526 BINDPARM *p;
4527
4528 if (!s->bindparms || pnum < 0 || pnum >= s->nbindparms) {
4529 goto error;
4530 }
4531 p = &s->bindparms[pnum];
4532 type = mapdeftype(p->type, p->stype, -1, s->nowchar[0]);
4533 #if (defined(_WIN32) || defined(_WIN64)) && defined(WINTERFACE)
4534 /* MS Access hack part 4 (map SQL_C_DEFAULT to SQL_C_CHAR) */
4535 if (type == SQL_C_WCHAR && p->type == SQL_C_DEFAULT) {
4536 type = SQL_C_CHAR;
4537 }
4538 #endif
4539 if (p->need > 0) {
4540 return setupparbuf(s, p);
4541 }
4542 p->strbuf[0] = '\0';
4543 if (!p->param || (p->lenp && *p->lenp == SQL_NULL_DATA)) {
4544 p->s3type = SQLITE_NULL;
4545 p->s3size = 0;
4546 return SQL_SUCCESS;
4547 }
4548 switch (type) {
4549 case SQL_C_BINARY:
4550 p->s3type = SQLITE_BLOB;
4551 p->s3size = p->len;
4552 p->s3val = p->param;
4553 if (p->need < 0) {
4554 break;
4555 }
4556 if (!p->lenp) {
4557 len = p->len;
4558 } else {
4559 len = *p->lenp;
4560 if (len <= SQL_LEN_DATA_AT_EXEC_OFFSET) {
4561 len = SQL_LEN_DATA_AT_EXEC(len);
4562 }
4563 }
4564 if (len < 0) {
4565 setstat(s, -1, "invalid length", "HY009");
4566 return SQL_ERROR;
4567 }
4568 p->len = len;
4569 p->max = p->len;
4570 p->need = -1;
4571 p->s3size = len;
4572 break;
4573 #ifdef WCHARSUPPORT
4574 case SQL_C_WCHAR:
4575 #endif
4576 case SQL_C_CHAR:
4577 p->s3type = SQLITE_TEXT;
4578 p->s3size = -1;
4579 p->s3val = p->param;
4580 if (!p->parbuf && p->lenp) {
4581 #ifdef WCHARSUPPORT
4582 if (type == SQL_C_WCHAR) {
4583 if (*p->lenp == SQL_NTS) {
4584 p->max = uc_strlen(p->param) * sizeof (SQLWCHAR);
4585 } else if (*p->lenp >= 0) {
4586 p->max = *p->lenp;
4587 }
4588 } else
4589 #endif
4590 if (type == SQL_C_CHAR) {
4591 if (*p->lenp == SQL_NTS) {
4592 p->len = p->max = strlen(p->param);
4593 #if defined(_WIN32) || defined(_WIN64)
4594 needalloc = 1;
4595 #endif
4596 } else if (*p->lenp >= 0) {
4597 p->len = p->max = *p->lenp;
4598 needalloc = 1;
4599 }
4600 }
4601 }
4602 if (p->need < 0 && p->parbuf == p->param) {
4603 break;
4604 }
4605 #ifdef WCHARSUPPORT
4606 if (type == SQL_C_WCHAR) {
4607 char *dp = uc_to_utf(p->param, p->max);
4608
4609 if (!dp) {
4610 return nomem(s);
4611 }
4612 if (p->param == p->parbuf) {
4613 freep(&p->parbuf);
4614 }
4615 p->parbuf = p->param = dp;
4616 p->need = -1;
4617 p->len = strlen(p->param);
4618 p->s3val = p->param;
4619 p->s3size = p->len;
4620 } else
4621 #endif
4622 if (type == SQL_C_CHAR) {
4623 p->s3val = p->param;
4624 if (needalloc) {
4625 char *dp;
4626
4627 #if defined(_WIN32) || defined(_WIN64)
4628 if (*s->oemcp) {
4629 dp = wmb_to_utf(p->param, p->len);
4630 } else {
4631 dp = xmalloc(p->len + 1);
4632 }
4633 #else
4634 dp = xmalloc(p->len + 1);
4635 #endif
4636 if (!dp) {
4637 return nomem(s);
4638 }
4639 #if defined(_WIN32) || defined(_WIN64)
4640 if (*s->oemcp) {
4641 p->len = strlen(dp);
4642 } else {
4643 memcpy(dp, p->param, p->len);
4644 dp[p->len] = '\0';
4645 }
4646 #else
4647 memcpy(dp, p->param, p->len);
4648 dp[p->len] = '\0';
4649 #endif
4650 if (p->param == p->parbuf) {
4651 freep(&p->parbuf);
4652 }
4653 p->parbuf = p->param = dp;
4654 p->need = -1;
4655 p->s3val = p->param;
4656 p->s3size = p->len;
4657 }
4658 }
4659 break;
4660 case SQL_C_UTINYINT:
4661 p->s3type = SQLITE_INTEGER;
4662 p->s3size = sizeof (int);
4663 p->s3ival = *((unsigned char *) p->param);
4664 break;
4665 case SQL_C_TINYINT:
4666 case SQL_C_STINYINT:
4667 p->s3type = SQLITE_INTEGER;
4668 p->s3size = sizeof (int);
4669 p->s3ival = *((char *) p->param);
4670 break;
4671 case SQL_C_USHORT:
4672 p->s3type = SQLITE_INTEGER;
4673 p->s3size = sizeof (int);
4674 p->s3ival = *((unsigned short *) p->param);
4675 break;
4676 case SQL_C_SHORT:
4677 case SQL_C_SSHORT:
4678 p->s3type = SQLITE_INTEGER;
4679 p->s3size = sizeof (int);
4680 p->s3ival = *((short *) p->param);
4681 break;
4682 case SQL_C_ULONG:
4683 p->s3type = SQLITE_INTEGER;
4684 p->s3size = sizeof (int);
4685 p->s3ival = *((unsigned int *) p->param);
4686 break;
4687 case SQL_C_LONG:
4688 case SQL_C_SLONG:
4689 p->s3type = SQLITE_INTEGER;
4690 p->s3size = sizeof (int);
4691 p->s3ival = *((int *) p->param);
4692 break;
4693 #ifdef SQL_BIT
4694 case SQL_C_BIT:
4695 p->s3type = SQLITE_INTEGER;
4696 p->s3size = sizeof (int);
4697 p->s3ival = (*((unsigned char *) p->param)) ? 1 : 0;
4698 break;
4699 #endif
4700 #ifdef SQL_BIGINT
4701 case SQL_C_SBIGINT:
4702 p->s3type = SQLITE_INTEGER;
4703 p->s3size = sizeof (sqlite_int64);
4704 p->s3lival = *((sqlite_int64 *) p->param);
4705 break;
4706 case SQL_C_UBIGINT:
4707 p->s3type = SQLITE_INTEGER;
4708 p->s3size = sizeof (sqlite_int64);
4709 p->s3lival = *((sqlite_uint64 *) p->param);
4710 break;
4711 #endif
4712 case SQL_C_FLOAT:
4713 p->s3type = SQLITE_FLOAT;
4714 p->s3size = sizeof (double);
4715 p->s3dval = *((float *) p->param);
4716 break;
4717 case SQL_C_DOUBLE:
4718 p->s3type = SQLITE_FLOAT;
4719 p->s3size = sizeof (double);
4720 p->s3dval = *((double *) p->param);
4721 break;
4722 #ifdef SQL_C_TYPE_DATE
4723 case SQL_C_TYPE_DATE:
4724 #endif
4725 case SQL_C_DATE:
4726 sprintf(p->strbuf, "%04d-%02d-%02d",
4727 ((DATE_STRUCT *) p->param)->year,
4728 ((DATE_STRUCT *) p->param)->month,
4729 ((DATE_STRUCT *) p->param)->day);
4730 p->s3type = SQLITE_TEXT;
4731 p->s3size = -1;
4732 p->s3val = p->strbuf;
4733 break;
4734 #ifdef SQL_C_TYPE_TIME
4735 case SQL_C_TYPE_TIME:
4736 #endif
4737 case SQL_C_TIME:
4738 sprintf(p->strbuf, "%02d:%02d:%02d",
4739 ((TIME_STRUCT *) p->param)->hour,
4740 ((TIME_STRUCT *) p->param)->minute,
4741 ((TIME_STRUCT *) p->param)->second);
4742 p->s3type = SQLITE_TEXT;
4743 p->s3size = -1;
4744 p->s3val = p->strbuf;
4745 break;
4746 #ifdef SQL_C_TYPE_TIMESTAMP
4747 case SQL_C_TYPE_TIMESTAMP:
4748 #endif
4749 case SQL_C_TIMESTAMP:
4750 len = (int) ((TIMESTAMP_STRUCT *) p->param)->fraction;
4751 len /= 1000000;
4752 len = len % 1000;
4753 if (len < 0) {
4754 len = 0;
4755 }
4756 if (p->coldef && p->coldef <= 16) {
4757 sprintf(p->strbuf, "%04d-%02d-%02d %02d:%02d:00.000",
4758 ((TIMESTAMP_STRUCT *) p->param)->year,
4759 ((TIMESTAMP_STRUCT *) p->param)->month,
4760 ((TIMESTAMP_STRUCT *) p->param)->day,
4761 ((TIMESTAMP_STRUCT *) p->param)->hour,
4762 ((TIMESTAMP_STRUCT *) p->param)->minute);
4763 } else if (p->coldef && p->coldef <= 19) {
4764 sprintf(p->strbuf, "%04d-%02d-%02d %02d:%02d:%02d.000",
4765 ((TIMESTAMP_STRUCT *) p->param)->year,
4766 ((TIMESTAMP_STRUCT *) p->param)->month,
4767 ((TIMESTAMP_STRUCT *) p->param)->day,
4768 ((TIMESTAMP_STRUCT *) p->param)->hour,
4769 ((TIMESTAMP_STRUCT *) p->param)->minute,
4770 ((TIMESTAMP_STRUCT *) p->param)->second);
4771 } else {
4772 sprintf(p->strbuf, "%04d-%02d-%02d %02d:%02d:%02d.%03d",
4773 ((TIMESTAMP_STRUCT *) p->param)->year,
4774 ((TIMESTAMP_STRUCT *) p->param)->month,
4775 ((TIMESTAMP_STRUCT *) p->param)->day,
4776 ((TIMESTAMP_STRUCT *) p->param)->hour,
4777 ((TIMESTAMP_STRUCT *) p->param)->minute,
4778 ((TIMESTAMP_STRUCT *) p->param)->second,
4779 len);
4780 }
4781 p->s3type = SQLITE_TEXT;
4782 p->s3size = -1;
4783 p->s3val = p->strbuf;
4784 break;
4785 default:
4786 error:
4787 setstat(s, -1, "unsupported parameter type",
4788 (*s->ov3) ? "07009" : "S1093");
4789 return SQL_ERROR;
4790 }
4791 return SQL_SUCCESS;
4792 }
4793
4794 /**
4795 * Internal bind parameter on HSTMT.
4796 * @param stmt statement handle
4797 * @param pnum parameter number, starting at 1
4798 * @param iotype input/output type of parameter
4799 * @param buftype type of host variable
4800 * @param ptype
4801 * @param coldef
4802 * @param scale
4803 * @param data pointer to host variable
4804 * @param buflen length of host variable
4805 * @param len output length pointer
4806 * @result ODBC error code
4807 */
4808
4809 static SQLRETURN
drvbindparam(SQLHSTMT stmt,SQLUSMALLINT pnum,SQLSMALLINT iotype,SQLSMALLINT buftype,SQLSMALLINT ptype,SQLUINTEGER coldef,SQLSMALLINT scale,SQLPOINTER data,SQLINTEGER buflen,SQLLEN * len)4810 drvbindparam(SQLHSTMT stmt, SQLUSMALLINT pnum, SQLSMALLINT iotype,
4811 SQLSMALLINT buftype, SQLSMALLINT ptype, SQLUINTEGER coldef,
4812 SQLSMALLINT scale,
4813 SQLPOINTER data, SQLINTEGER buflen, SQLLEN *len)
4814 {
4815 STMT *s;
4816 BINDPARM *p;
4817
4818 if (stmt == SQL_NULL_HSTMT) {
4819 return SQL_INVALID_HANDLE;
4820 }
4821 s = (STMT *) stmt;
4822 if (pnum == 0) {
4823 setstat(s, -1, "invalid parameter", (*s->ov3) ? "07009" : "S1093");
4824 return SQL_ERROR;
4825 }
4826 if (!data && !len) {
4827 setstat(s, -1, "invalid buffer", "HY003");
4828 return SQL_ERROR;
4829 }
4830 --pnum;
4831 if (s->bindparms) {
4832 if (pnum >= s->nbindparms) {
4833 BINDPARM *newparms;
4834
4835 newparms = xrealloc(s->bindparms,
4836 (pnum + 1) * sizeof (BINDPARM));
4837 if (!newparms) {
4838 outofmem:
4839 return nomem(s);
4840 }
4841 s->bindparms = newparms;
4842 memset(&s->bindparms[s->nbindparms], 0,
4843 (pnum + 1 - s->nbindparms) * sizeof (BINDPARM));
4844 s->nbindparms = pnum + 1;
4845 }
4846 } else {
4847 int npar = max(10, pnum + 1);
4848
4849 s->bindparms = xmalloc(npar * sizeof (BINDPARM));
4850 if (!s->bindparms) {
4851 goto outofmem;
4852 }
4853 memset(s->bindparms, 0, npar * sizeof (BINDPARM));
4854 s->nbindparms = npar;
4855 }
4856 switch (buftype) {
4857 case SQL_C_STINYINT:
4858 case SQL_C_UTINYINT:
4859 case SQL_C_TINYINT:
4860 #ifdef SQL_C_BIT
4861 case SQL_C_BIT:
4862 #endif
4863 buflen = sizeof (char);
4864 break;
4865 case SQL_C_SHORT:
4866 case SQL_C_USHORT:
4867 case SQL_C_SSHORT:
4868 buflen = sizeof (short);
4869 break;
4870 case SQL_C_SLONG:
4871 case SQL_C_ULONG:
4872 case SQL_C_LONG:
4873 buflen = sizeof (long);
4874 break;
4875 case SQL_C_FLOAT:
4876 buflen = sizeof (float);
4877 break;
4878 case SQL_C_DOUBLE:
4879 buflen = sizeof (double);
4880 break;
4881 case SQL_C_TIMESTAMP:
4882 #ifdef SQL_C_TYPE_TIMESTAMP
4883 case SQL_C_TYPE_TIMESTAMP:
4884 #endif
4885 buflen = sizeof (TIMESTAMP_STRUCT);
4886 break;
4887 case SQL_C_TIME:
4888 #ifdef SQL_C_TYPE_TIME
4889 case SQL_C_TYPE_TIME:
4890 #endif
4891 buflen = sizeof (TIME_STRUCT);
4892 break;
4893 case SQL_C_DATE:
4894 #ifdef SQL_C_TYPE_DATE
4895 case SQL_C_TYPE_DATE:
4896 #endif
4897 buflen = sizeof (DATE_STRUCT);
4898 break;
4899 #ifdef SQL_C_UBIGINT
4900 case SQL_C_UBIGINT:
4901 buflen = sizeof (SQLBIGINT);
4902 break;
4903 #endif
4904 #ifdef SQL_C_SBIGINT
4905 case SQL_C_SBIGINT:
4906 buflen = sizeof (SQLBIGINT);
4907 break;
4908 #endif
4909 #ifdef SQL_C_BIGINT
4910 case SQL_C_BIGINT:
4911 buflen = sizeof (SQLBIGINT);
4912 break;
4913 #endif
4914 }
4915 p = &s->bindparms[pnum];
4916 p->type = buftype;
4917 p->stype = ptype;
4918 p->coldef = coldef;
4919 p->scale = scale;
4920 p->max = buflen;
4921 p->inc = buflen;
4922 p->lenp = p->lenp0 = len;
4923 p->offs = 0;
4924 p->len = 0;
4925 p->param0 = data;
4926 freep(&p->parbuf);
4927 p->param = p->param0;
4928 p->bound = 1;
4929 p->need = 0;
4930 return SQL_SUCCESS;
4931 }
4932
4933 /**
4934 * Bind parameter on HSTMT.
4935 * @param stmt statement handle
4936 * @param pnum parameter number, starting at 1
4937 * @param iotype input/output type of parameter
4938 * @param buftype type of host variable
4939 * @param ptype
4940 * @param coldef
4941 * @param scale
4942 * @param data pointer to host variable
4943 * @param buflen length of host variable
4944 * @param len output length pointer
4945 * @result ODBC error code
4946 */
4947
4948 SQLRETURN SQL_API
SQLBindParameter(SQLHSTMT stmt,SQLUSMALLINT pnum,SQLSMALLINT iotype,SQLSMALLINT buftype,SQLSMALLINT ptype,SQLULEN coldef,SQLSMALLINT scale,SQLPOINTER data,SQLLEN buflen,SQLLEN * len)4949 SQLBindParameter(SQLHSTMT stmt, SQLUSMALLINT pnum, SQLSMALLINT iotype,
4950 SQLSMALLINT buftype, SQLSMALLINT ptype, SQLULEN coldef,
4951 SQLSMALLINT scale,
4952 SQLPOINTER data, SQLLEN buflen, SQLLEN *len)
4953 {
4954 SQLRETURN ret;
4955
4956 HSTMT_LOCK(stmt);
4957 ret = drvbindparam(stmt, pnum, iotype, buftype, ptype, coldef,
4958 scale, data, buflen, len);
4959 HSTMT_UNLOCK(stmt);
4960 return ret;
4961 }
4962
4963 #ifndef HAVE_IODBC
4964 /**
4965 * Bind parameter on HSTMT.
4966 * @param stmt statement handle
4967 * @param pnum parameter number, starting at 1
4968 * @param vtype input/output type of parameter
4969 * @param ptype
4970 * @param lenprec
4971 * @param scale
4972 * @param val pointer to host variable
4973 * @param lenp output length pointer
4974 * @result ODBC error code
4975 */
4976
4977 SQLRETURN SQL_API
SQLBindParam(SQLHSTMT stmt,SQLUSMALLINT pnum,SQLSMALLINT vtype,SQLSMALLINT ptype,SQLULEN lenprec,SQLSMALLINT scale,SQLPOINTER val,SQLLEN * lenp)4978 SQLBindParam(SQLHSTMT stmt, SQLUSMALLINT pnum, SQLSMALLINT vtype,
4979 SQLSMALLINT ptype, SQLULEN lenprec,
4980 SQLSMALLINT scale, SQLPOINTER val,
4981 SQLLEN *lenp)
4982 {
4983 SQLRETURN ret;
4984
4985 HSTMT_LOCK(stmt);
4986 ret = drvbindparam(stmt, pnum, SQL_PARAM_INPUT, vtype, ptype,
4987 lenprec, scale, val, 0, lenp);
4988 HSTMT_UNLOCK(stmt);
4989 return ret;
4990 }
4991 #endif
4992
4993 /**
4994 * Return number of parameters.
4995 * @param stmt statement handle
4996 * @param nparam output parameter count
4997 * @result ODBC error code
4998 */
4999
5000 SQLRETURN SQL_API
SQLNumParams(SQLHSTMT stmt,SQLSMALLINT * nparam)5001 SQLNumParams(SQLHSTMT stmt, SQLSMALLINT *nparam)
5002 {
5003 STMT *s;
5004 SQLSMALLINT dummy;
5005
5006 HSTMT_LOCK(stmt);
5007 if (stmt == SQL_NULL_HSTMT) {
5008 return SQL_INVALID_HANDLE;
5009 }
5010 s = (STMT *) stmt;
5011 if (!nparam) {
5012 nparam = &dummy;
5013 }
5014 *nparam = s->nparams;
5015 HSTMT_UNLOCK(stmt);
5016 return SQL_SUCCESS;
5017 }
5018
5019 /**
5020 * Setup parameter buffer for deferred parameter.
5021 * @param s pointer to STMT
5022 * @param p pointer to BINDPARM
5023 * @result ODBC error code (success indicated by SQL_NEED_DATA)
5024 */
5025
5026 static SQLRETURN
setupparbuf(STMT * s,BINDPARM * p)5027 setupparbuf(STMT *s, BINDPARM *p)
5028 {
5029 if (!p->parbuf) {
5030 p->len = SQL_LEN_DATA_AT_EXEC(*p->lenp);
5031 if (p->len < 0 && p->len != SQL_NTS &&
5032 p->len != SQL_NULL_DATA) {
5033 setstat(s, -1, "invalid length", "HY009");
5034 return SQL_ERROR;
5035 }
5036 if (p->len >= 0) {
5037 p->parbuf = xmalloc(p->len + 1);
5038 if (!p->parbuf) {
5039 return nomem(s);
5040 }
5041 p->param = p->parbuf;
5042 } else {
5043 p->param = NULL;
5044 }
5045 }
5046 return SQL_NEED_DATA;
5047 }
5048
5049 /**
5050 * Retrieve next parameter for sending data to executing query.
5051 * @param stmt statement handle
5052 * @param pind pointer to output parameter indicator
5053 * @result ODBC error code
5054 */
5055
5056 SQLRETURN SQL_API
SQLParamData(SQLHSTMT stmt,SQLPOINTER * pind)5057 SQLParamData(SQLHSTMT stmt, SQLPOINTER *pind)
5058 {
5059 STMT *s;
5060 int i;
5061 SQLPOINTER dummy;
5062 SQLRETURN ret;
5063
5064 HSTMT_LOCK(stmt);
5065 if (stmt == SQL_NULL_HSTMT) {
5066 return SQL_INVALID_HANDLE;
5067 }
5068 s = (STMT *) stmt;
5069 if (!pind) {
5070 pind = &dummy;
5071 }
5072 for (i = 0; i < s->nparams; i++) {
5073 BINDPARM *p = &s->bindparms[i];
5074
5075 if (p->need > 0) {
5076 *pind = (SQLPOINTER) p->param0;
5077 ret = setupparbuf(s, p);
5078 goto done;
5079 }
5080 }
5081 ret = drvexecute(stmt, 0);
5082 done:
5083 HSTMT_UNLOCK(stmt);
5084 return ret;
5085 }
5086
5087 /**
5088 * Return information about parameter.
5089 * @param stmt statement handle
5090 * @param pnum parameter number, starting at 1
5091 * @param dtype output type indicator
5092 * @param size output size indicator
5093 * @param decdigits output number of digits
5094 * @param nullable output NULL allowed indicator
5095 * @result ODBC error code
5096 */
5097
5098 SQLRETURN SQL_API
SQLDescribeParam(SQLHSTMT stmt,SQLUSMALLINT pnum,SQLSMALLINT * dtype,SQLULEN * size,SQLSMALLINT * decdigits,SQLSMALLINT * nullable)5099 SQLDescribeParam(SQLHSTMT stmt, SQLUSMALLINT pnum, SQLSMALLINT *dtype,
5100 SQLULEN *size, SQLSMALLINT *decdigits, SQLSMALLINT *nullable)
5101 {
5102 STMT *s;
5103 SQLRETURN ret = SQL_ERROR;
5104
5105 HSTMT_LOCK(stmt);
5106 if (stmt == SQL_NULL_HSTMT) {
5107 return SQL_INVALID_HANDLE;
5108 }
5109 s = (STMT *) stmt;
5110 --pnum;
5111 if (pnum >= s->nparams) {
5112 setstat(s, -1, "invalid parameter index",
5113 (*s->ov3) ? "HY000" : "S1000");
5114 goto done;
5115 }
5116 if (dtype) {
5117 #ifdef SQL_LONGVARCHAR
5118 #ifdef WINTERFACE
5119 *dtype = s->nowchar[0] ? SQL_LONGVARCHAR : SQL_WLONGVARCHAR;
5120 #else
5121 *dtype = SQL_LONGVARCHAR;
5122 #endif
5123 #else
5124 #ifdef WINTERFACE
5125 *dtype = s->nowchar[0] ? SQL_VARCHAR : SQL_WVARCHAR;
5126 #else
5127 *dtype = SQL_VARCHAR;
5128 #endif
5129 #endif
5130 }
5131 if (size) {
5132 #ifdef SQL_LONGVARCHAR
5133 *size = 65536;
5134 #else
5135 *size = 255;
5136 #endif
5137 }
5138 if (decdigits) {
5139 *decdigits = 0;
5140 }
5141 if (nullable) {
5142 *nullable = SQL_NULLABLE;
5143 }
5144 ret = SQL_SUCCESS;
5145 done:
5146 HSTMT_UNLOCK(stmt);
5147 return ret;
5148 }
5149
5150 /**
5151 * Set information on parameter.
5152 * @param stmt statement handle
5153 * @param par parameter number, starting at 1
5154 * @param type type of host variable
5155 * @param sqltype
5156 * @param coldef
5157 * @param scale
5158 * @param val pointer to host variable
5159 * @param nval output length pointer
5160 * @result ODBC error code
5161 */
5162
5163 SQLRETURN SQL_API
SQLSetParam(SQLHSTMT stmt,SQLUSMALLINT par,SQLSMALLINT type,SQLSMALLINT sqltype,SQLULEN coldef,SQLSMALLINT scale,SQLPOINTER val,SQLLEN * nval)5164 SQLSetParam(SQLHSTMT stmt, SQLUSMALLINT par, SQLSMALLINT type,
5165 SQLSMALLINT sqltype, SQLULEN coldef,
5166 SQLSMALLINT scale, SQLPOINTER val, SQLLEN *nval)
5167 {
5168 SQLRETURN ret;
5169
5170 HSTMT_LOCK(stmt);
5171 ret = drvbindparam(stmt, par, SQL_PARAM_INPUT,
5172 type, sqltype, coldef, scale, val,
5173 SQL_SETPARAM_VALUE_MAX, nval);
5174 HSTMT_UNLOCK(stmt);
5175 return ret;
5176 }
5177
5178 /**
5179 * Function not implemented.
5180 */
5181
5182 SQLRETURN SQL_API
SQLParamOptions(SQLHSTMT stmt,SQLULEN rows,SQLULEN * rowp)5183 SQLParamOptions(SQLHSTMT stmt, SQLULEN rows, SQLULEN *rowp)
5184 {
5185 SQLRETURN ret;
5186
5187 HSTMT_LOCK(stmt);
5188 ret = drvunimplstmt(stmt);
5189 HSTMT_UNLOCK(stmt);
5190 return ret;
5191 }
5192
5193 #ifndef WINTERFACE
5194 /**
5195 * Function not implemented.
5196 */
5197
5198 SQLRETURN SQL_API
SQLGetDescField(SQLHDESC handle,SQLSMALLINT recno,SQLSMALLINT fieldid,SQLPOINTER value,SQLINTEGER buflen,SQLINTEGER * strlen)5199 SQLGetDescField(SQLHDESC handle, SQLSMALLINT recno,
5200 SQLSMALLINT fieldid, SQLPOINTER value,
5201 SQLINTEGER buflen, SQLINTEGER *strlen)
5202 {
5203 return SQL_ERROR;
5204 }
5205 #endif
5206
5207 #ifdef WINTERFACE
5208 /**
5209 * Function not implemented.
5210 */
5211
5212 SQLRETURN SQL_API
SQLGetDescFieldW(SQLHDESC handle,SQLSMALLINT recno,SQLSMALLINT fieldid,SQLPOINTER value,SQLINTEGER buflen,SQLINTEGER * strlen)5213 SQLGetDescFieldW(SQLHDESC handle, SQLSMALLINT recno,
5214 SQLSMALLINT fieldid, SQLPOINTER value,
5215 SQLINTEGER buflen, SQLINTEGER *strlen)
5216 {
5217 return SQL_ERROR;
5218 }
5219 #endif
5220
5221 #ifndef WINTERFACE
5222 /**
5223 * Function not implemented.
5224 */
5225
5226 SQLRETURN SQL_API
SQLSetDescField(SQLHDESC handle,SQLSMALLINT recno,SQLSMALLINT fieldid,SQLPOINTER value,SQLINTEGER buflen)5227 SQLSetDescField(SQLHDESC handle, SQLSMALLINT recno,
5228 SQLSMALLINT fieldid, SQLPOINTER value,
5229 SQLINTEGER buflen)
5230 {
5231 return SQL_ERROR;
5232 }
5233 #endif
5234
5235 #ifdef WINTERFACE
5236 /**
5237 * Function not implemented.
5238 */
5239
5240 SQLRETURN SQL_API
SQLSetDescFieldW(SQLHDESC handle,SQLSMALLINT recno,SQLSMALLINT fieldid,SQLPOINTER value,SQLINTEGER buflen)5241 SQLSetDescFieldW(SQLHDESC handle, SQLSMALLINT recno,
5242 SQLSMALLINT fieldid, SQLPOINTER value,
5243 SQLINTEGER buflen)
5244 {
5245 return SQL_ERROR;
5246 }
5247 #endif
5248
5249 #ifndef WINTERFACE
5250 /**
5251 * Function not implemented.
5252 */
5253
5254 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)5255 SQLGetDescRec(SQLHDESC handle, SQLSMALLINT recno,
5256 SQLCHAR *name, SQLSMALLINT buflen,
5257 SQLSMALLINT *strlen, SQLSMALLINT *type,
5258 SQLSMALLINT *subtype, SQLLEN *len,
5259 SQLSMALLINT *prec, SQLSMALLINT *scale,
5260 SQLSMALLINT *nullable)
5261 {
5262 return SQL_ERROR;
5263 }
5264 #endif
5265
5266 #ifdef WINTERFACE
5267 /**
5268 * Function not implemented.
5269 */
5270
5271 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)5272 SQLGetDescRecW(SQLHDESC handle, SQLSMALLINT recno,
5273 SQLWCHAR *name, SQLSMALLINT buflen,
5274 SQLSMALLINT *strlen, SQLSMALLINT *type,
5275 SQLSMALLINT *subtype, SQLLEN *len,
5276 SQLSMALLINT *prec, SQLSMALLINT *scale,
5277 SQLSMALLINT *nullable)
5278 {
5279 return SQL_ERROR;
5280 }
5281 #endif
5282
5283 /**
5284 * Function not implemented.
5285 */
5286
5287 SQLRETURN SQL_API
SQLSetDescRec(SQLHDESC handle,SQLSMALLINT recno,SQLSMALLINT type,SQLSMALLINT subtype,SQLLEN len,SQLSMALLINT prec,SQLSMALLINT scale,SQLPOINTER data,SQLLEN * strlen,SQLLEN * indicator)5288 SQLSetDescRec(SQLHDESC handle, SQLSMALLINT recno,
5289 SQLSMALLINT type, SQLSMALLINT subtype,
5290 SQLLEN len, SQLSMALLINT prec,
5291 SQLSMALLINT scale, SQLPOINTER data,
5292 SQLLEN *strlen, SQLLEN *indicator)
5293 {
5294 return SQL_ERROR;
5295 }
5296
5297 /**
5298 * Setup empty result set from constant column specification.
5299 * @param stmt statement handle
5300 * @param colspec column specification array (default, ODBC2)
5301 * @param ncols number of columns (default, ODBC2)
5302 * @param colspec3 column specification array (ODBC3)
5303 * @param ncols3 number of columns (ODBC3)
5304 * @param nret returns number of columns
5305 * @result ODBC error code
5306 */
5307
5308 static SQLRETURN
mkresultset(HSTMT stmt,COL * colspec,int ncols,COL * colspec3,int ncols3,int * nret)5309 mkresultset(HSTMT stmt, COL *colspec, int ncols, COL *colspec3,
5310 int ncols3, int *nret)
5311 {
5312 STMT *s;
5313 DBC *d;
5314
5315 if (stmt == SQL_NULL_HSTMT) {
5316 return SQL_INVALID_HANDLE;
5317 }
5318 s = (STMT *) stmt;
5319 if (s->dbc == SQL_NULL_HDBC) {
5320 noconn:
5321 return noconn(s);
5322 }
5323 d = (DBC *) s->dbc;
5324 if (!d->sqlite) {
5325 goto noconn;
5326 }
5327 s3stmt_end_if(s);
5328 freeresult(s, 0);
5329 if (colspec3 && *s->ov3) {
5330 s->ncols = ncols3;
5331 s->cols = colspec3;
5332 } else {
5333 s->ncols = ncols;
5334 s->cols = colspec;
5335 }
5336 mkbindcols(s, s->ncols);
5337 s->nowchar[1] = 1;
5338 s->nrows = 0;
5339 s->rowp = -1;
5340 s->isselect = -1;
5341 if (nret) {
5342 *nret = s->ncols;
5343 }
5344 return SQL_SUCCESS;
5345 }
5346
5347 /**
5348 * Columns for result set of SQLTablePrivileges().
5349 */
5350
5351 static COL tablePrivSpec2[] = {
5352 { "SYSTEM", "TABLEPRIV", "TABLE_QUALIFIER", SCOL_VARCHAR, 50 },
5353 { "SYSTEM", "TABLEPRIV", "TABLE_OWNER", SCOL_VARCHAR, 50 },
5354 { "SYSTEM", "TABLEPRIV", "TABLE_NAME", SCOL_VARCHAR, 255 },
5355 { "SYSTEM", "TABLEPRIV", "GRANTOR", SCOL_VARCHAR, 50 },
5356 { "SYSTEM", "TABLEPRIV", "GRANTEE", SCOL_VARCHAR, 50 },
5357 { "SYSTEM", "TABLEPRIV", "PRIVILEGE", SCOL_VARCHAR, 50 },
5358 { "SYSTEM", "TABLEPRIV", "IS_GRANTABLE", SCOL_VARCHAR, 50 }
5359 };
5360
5361 static COL tablePrivSpec3[] = {
5362 { "SYSTEM", "TABLEPRIV", "TABLE_CAT", SCOL_VARCHAR, 50 },
5363 { "SYSTEM", "TABLEPRIV", "TABLE_SCHEM", SCOL_VARCHAR, 50 },
5364 { "SYSTEM", "TABLEPRIV", "TABLE_NAME", SCOL_VARCHAR, 255 },
5365 { "SYSTEM", "TABLEPRIV", "GRANTOR", SCOL_VARCHAR, 50 },
5366 { "SYSTEM", "TABLEPRIV", "GRANTEE", SCOL_VARCHAR, 50 },
5367 { "SYSTEM", "TABLEPRIV", "PRIVILEGE", SCOL_VARCHAR, 50 },
5368 { "SYSTEM", "TABLEPRIV", "IS_GRANTABLE", SCOL_VARCHAR, 50 }
5369 };
5370
5371 /**
5372 * Retrieve privileges on tables and/or views.
5373 * @param stmt statement handle
5374 * @param cat catalog name/pattern or NULL
5375 * @param catLen length of catalog name/pattern or SQL_NTS
5376 * @param schema schema name/pattern or NULL
5377 * @param schemaLen length of schema name/pattern or SQL_NTS
5378 * @param table table name/pattern or NULL
5379 * @param tableLen length of table name/pattern or SQL_NTS
5380 * @result ODBC error code
5381 */
5382
5383 static SQLRETURN
drvtableprivileges(SQLHSTMT stmt,SQLCHAR * cat,SQLSMALLINT catLen,SQLCHAR * schema,SQLSMALLINT schemaLen,SQLCHAR * table,SQLSMALLINT tableLen)5384 drvtableprivileges(SQLHSTMT stmt,
5385 SQLCHAR *cat, SQLSMALLINT catLen,
5386 SQLCHAR *schema, SQLSMALLINT schemaLen,
5387 SQLCHAR *table, SQLSMALLINT tableLen)
5388 {
5389 SQLRETURN ret;
5390 STMT *s;
5391 DBC *d;
5392 int ncols, rc, size, npatt;
5393 char *errp = NULL, *sql, tname[512];
5394
5395 ret = mkresultset(stmt, tablePrivSpec2, array_size(tablePrivSpec2),
5396 tablePrivSpec3, array_size(tablePrivSpec3), NULL);
5397 if (ret != SQL_SUCCESS) {
5398 return ret;
5399 }
5400 s = (STMT *) stmt;
5401 d = (DBC *) s->dbc;
5402 if (cat && (catLen > 0 || catLen == SQL_NTS) && cat[0] == '%') {
5403 table = NULL;
5404 goto doit;
5405 }
5406 if (schema && (schemaLen > 0 || schemaLen == SQL_NTS) &&
5407 schema[0] == '%') {
5408 if ((!cat || catLen == 0 || !cat[0]) &&
5409 (!table || tableLen == 0 || !table[0])) {
5410 table = NULL;
5411 goto doit;
5412 }
5413 }
5414 doit:
5415 if (!table) {
5416 size = 1;
5417 tname[0] = '%';
5418 } else {
5419 if (tableLen == SQL_NTS) {
5420 size = sizeof (tname) - 1;
5421 } else {
5422 size = min(sizeof (tname) - 1, tableLen);
5423 }
5424 strncpy(tname, (char *) table, size);
5425 }
5426 tname[size] = '\0';
5427 npatt = unescpat(tname);
5428 #if defined(_WIN32) || defined(_WIN64)
5429 sql = sqlite3_mprintf("select %s as 'TABLE_QUALIFIER', "
5430 "%s as 'TABLE_OWNER', "
5431 "tbl_name as 'TABLE_NAME', "
5432 "'' as 'GRANTOR', "
5433 "'' as 'GRANTEE', "
5434 "'SELECT' AS 'PRIVILEGE', "
5435 "NULL as 'IS_GRANTABLE' "
5436 "from sqlite_master where "
5437 "(type = 'table' or type = 'view') "
5438 "and tbl_name %s %Q "
5439 "UNION "
5440 "select %s as 'TABLE_QUALIFIER', "
5441 "%s as 'TABLE_OWNER', "
5442 "tbl_name as 'TABLE_NAME', "
5443 "'' as 'GRANTOR', "
5444 "'' as 'GRANTEE', "
5445 "'UPDATE' AS 'PRIVILEGE', "
5446 "NULL as 'IS_GRANTABLE' "
5447 "from sqlite_master where "
5448 "(type = 'table' or type = 'view') "
5449 "and tbl_name %s %Q "
5450 "UNION "
5451 "select %s as 'TABLE_QUALIFIER', "
5452 "%s as 'TABLE_OWNER', "
5453 "tbl_name as 'TABLE_NAME', "
5454 "'' as 'GRANTOR', "
5455 "'' as 'GRANTEE', "
5456 "'DELETE' AS 'PRIVILEGE', "
5457 "NULL as 'IS_GRANTABLE' "
5458 "from sqlite_master where "
5459 "(type = 'table' or type = 'view') "
5460 "and tbl_name %s %Q "
5461 "UNION "
5462 "select %s as 'TABLE_QUALIFIER', "
5463 "%s as 'TABLE_OWNER', "
5464 "tbl_name as 'TABLE_NAME', "
5465 "'' as 'GRANTOR', "
5466 "'' as 'GRANTEE', "
5467 "'INSERT' AS 'PRIVILEGE', "
5468 "NULL as 'IS_GRANTABLE' "
5469 "from sqlite_master where "
5470 "(type = 'table' or type = 'view') "
5471 "and tbl_name %s %Q "
5472 "UNION "
5473 "select %s as 'TABLE_QUALIFIER', "
5474 "%s as 'TABLE_OWNER', "
5475 "tbl_name as 'TABLE_NAME', "
5476 "'' as 'GRANTOR', "
5477 "'' as 'GRANTEE', "
5478 "'REFERENCES' AS 'PRIVILEGE', "
5479 "NULL as 'IS_GRANTABLE' "
5480 "from sqlite_master where "
5481 "(type = 'table' or type = 'view') "
5482 "and tbl_name %s %Q",
5483 d->xcelqrx ? "''" : "NULL",
5484 d->xcelqrx ? "'main'" : "NULL",
5485 npatt ? "like" : "=", tname,
5486 d->xcelqrx ? "''" : "NULL",
5487 d->xcelqrx ? "'main'" : "NULL",
5488 npatt ? "like" : "=", tname,
5489 d->xcelqrx ? "''" : "NULL",
5490 d->xcelqrx ? "'main'" : "NULL",
5491 npatt ? "like" : "=", tname,
5492 d->xcelqrx ? "''" : "NULL",
5493 d->xcelqrx ? "'main'" : "NULL",
5494 npatt ? "like" : "=", tname,
5495 d->xcelqrx ? "''" : "NULL",
5496 d->xcelqrx ? "'main'" : "NULL",
5497 npatt ? "like" : "=", tname);
5498 #else
5499 sql = sqlite3_mprintf("select NULL as 'TABLE_QUALIFIER', "
5500 "NULL as 'TABLE_OWNER', "
5501 "tbl_name as 'TABLE_NAME', "
5502 "'' as 'GRANTOR', "
5503 "'' as 'GRANTEE', "
5504 "'SELECT' AS 'PRIVILEGE', "
5505 "NULL as 'IS_GRANTABLE' "
5506 "from sqlite_master where "
5507 "(type = 'table' or type = 'view') "
5508 "and tbl_name %s %Q "
5509 "UNION "
5510 "select NULL as 'TABLE_QUALIFIER', "
5511 "NULL as 'TABLE_OWNER', "
5512 "tbl_name as 'TABLE_NAME', "
5513 "'' as 'GRANTOR', "
5514 "'' as 'GRANTEE', "
5515 "'UPDATE' AS 'PRIVILEGE', "
5516 "NULL as 'IS_GRANTABLE' "
5517 "from sqlite_master where "
5518 "(type = 'table' or type = 'view') "
5519 "and tbl_name %s %Q "
5520 "UNION "
5521 "select NULL as 'TABLE_QUALIFIER', "
5522 "NULL as 'TABLE_OWNER', "
5523 "tbl_name as 'TABLE_NAME', "
5524 "'' as 'GRANTOR', "
5525 "'' as 'GRANTEE', "
5526 "'DELETE' AS 'PRIVILEGE', "
5527 "NULL as 'IS_GRANTABLE' "
5528 "from sqlite_master where "
5529 "(type = 'table' or type = 'view') "
5530 "and tbl_name %s %Q "
5531 "UNION "
5532 "select NULL as 'TABLE_QUALIFIER', "
5533 "NULL as 'TABLE_OWNER', "
5534 "tbl_name as 'TABLE_NAME', "
5535 "'' as 'GRANTOR', "
5536 "'' as 'GRANTEE', "
5537 "'INSERT' AS 'PRIVILEGE', "
5538 "NULL as 'IS_GRANTABLE' "
5539 "from sqlite_master where "
5540 "(type = 'table' or type = 'view') "
5541 "and tbl_name %s %Q "
5542 "UNION "
5543 "select NULL as 'TABLE_QUALIFIER', "
5544 "NULL as 'TABLE_OWNER', "
5545 "tbl_name as 'TABLE_NAME', "
5546 "'' as 'GRANTOR', "
5547 "'' as 'GRANTEE', "
5548 "'REFERENCES' AS 'PRIVILEGE', "
5549 "NULL as 'IS_GRANTABLE' "
5550 "from sqlite_master where "
5551 "(type = 'table' or type = 'view') "
5552 "and tbl_name %s %Q",
5553 npatt ? "like" : "=", tname,
5554 npatt ? "like" : "=", tname,
5555 npatt ? "like" : "=", tname,
5556 npatt ? "like" : "=", tname,
5557 npatt ? "like" : "=", tname);
5558 #endif
5559 if (!sql) {
5560 return nomem(s);
5561 }
5562 ret = starttran(s);
5563 if (ret != SQL_SUCCESS) {
5564 sqlite3_free(sql);
5565 return ret;
5566 }
5567 dbtraceapi(d, "sqlite3_get_table", sql);
5568 rc = sqlite3_get_table(d->sqlite, sql, &s->rows, &s->nrows, &ncols, &errp);
5569 sqlite3_free(sql);
5570 if (rc == SQLITE_OK) {
5571 if (ncols != s->ncols) {
5572 freeresult(s, 0);
5573 s->nrows = 0;
5574 } else {
5575 s->rowfree = sqlite3_free_table;
5576 }
5577 } else {
5578 s->nrows = 0;
5579 s->rows = NULL;
5580 s->rowfree = NULL;
5581 }
5582 if (errp) {
5583 sqlite3_free(errp);
5584 errp = NULL;
5585 }
5586 s->rowp = -1;
5587 return SQL_SUCCESS;
5588 }
5589
5590
5591 #if !defined(WINTERFACE) || (defined(HAVE_UNIXODBC) && (HAVE_UNIXODBC))
5592 /**
5593 * Retrieve privileges on tables and/or views.
5594 * @param stmt statement handle
5595 * @param catalog catalog name/pattern or NULL
5596 * @param catalogLen length of catalog name/pattern or SQL_NTS
5597 * @param schema schema name/pattern or NULL
5598 * @param schemaLen length of schema name/pattern or SQL_NTS
5599 * @param table table name/pattern or NULL
5600 * @param tableLen length of table name/pattern or SQL_NTS
5601 * @result ODBC error code
5602 */
5603
5604 SQLRETURN SQL_API
SQLTablePrivileges(SQLHSTMT stmt,SQLCHAR * catalog,SQLSMALLINT catalogLen,SQLCHAR * schema,SQLSMALLINT schemaLen,SQLCHAR * table,SQLSMALLINT tableLen)5605 SQLTablePrivileges(SQLHSTMT stmt,
5606 SQLCHAR *catalog, SQLSMALLINT catalogLen,
5607 SQLCHAR *schema, SQLSMALLINT schemaLen,
5608 SQLCHAR *table, SQLSMALLINT tableLen)
5609 {
5610 #if defined(_WIN32) || defined(_WIN64)
5611 char *c = NULL, *s = NULL, *t = NULL;
5612 #endif
5613 SQLRETURN ret;
5614
5615 HSTMT_LOCK(stmt);
5616 #if defined(_WIN32) || defined(_WIN64)
5617 if (!((STMT *) stmt)->oemcp[0]) {
5618 ret = drvtableprivileges(stmt, catalog, catalogLen, schema, schemaLen,
5619 table, tableLen);
5620 goto done2;
5621 }
5622 if (catalog) {
5623 c = wmb_to_utf_c((char *) catalog, catalogLen);
5624 if (!c) {
5625 ret = nomem((STMT *) stmt);
5626 goto done;
5627 }
5628 }
5629 if (schema) {
5630 s = wmb_to_utf_c((char *) schema, schemaLen);
5631 if (!s) {
5632 ret = nomem((STMT *) stmt);
5633 goto done;
5634 }
5635 }
5636 if (table) {
5637 t = wmb_to_utf_c((char *) table, tableLen);
5638 if (!t) {
5639 ret = nomem((STMT *) stmt);
5640 goto done;
5641 }
5642 }
5643 ret = drvtableprivileges(stmt, (SQLCHAR *) c, SQL_NTS,
5644 (SQLCHAR *) s, SQL_NTS,
5645 (SQLCHAR *) t, SQL_NTS);
5646 #else
5647 ret = drvtableprivileges(stmt, catalog, catalogLen, schema, schemaLen,
5648 table, tableLen);
5649 #endif
5650 #if defined(_WIN32) || defined(_WIN64)
5651 done:
5652 uc_free(t);
5653 uc_free(s);
5654 uc_free(c);
5655 done2:
5656 ;
5657 #endif
5658 HSTMT_UNLOCK(stmt);
5659 return ret;
5660 }
5661 #endif
5662
5663 #if !defined(HAVE_UNIXODBC) || !(HAVE_UNIXODBC)
5664 #ifdef WINTERFACE
5665 /**
5666 * Retrieve privileges on tables and/or views (UNICODE version).
5667 * @param stmt statement handle
5668 * @param catalog catalog name/pattern or NULL
5669 * @param catalogLen length of catalog name/pattern or SQL_NTS
5670 * @param schema schema name/pattern or NULL
5671 * @param schemaLen length of schema name/pattern or SQL_NTS
5672 * @param table table name/pattern or NULL
5673 * @param tableLen length of table name/pattern or SQL_NTS
5674 * @result ODBC error code
5675 */
5676
5677 SQLRETURN SQL_API
SQLTablePrivilegesW(SQLHSTMT stmt,SQLWCHAR * catalog,SQLSMALLINT catalogLen,SQLWCHAR * schema,SQLSMALLINT schemaLen,SQLWCHAR * table,SQLSMALLINT tableLen)5678 SQLTablePrivilegesW(SQLHSTMT stmt,
5679 SQLWCHAR *catalog, SQLSMALLINT catalogLen,
5680 SQLWCHAR *schema, SQLSMALLINT schemaLen,
5681 SQLWCHAR *table, SQLSMALLINT tableLen)
5682 {
5683 char *c = NULL, *s = NULL, *t = NULL;
5684 SQLRETURN ret;
5685
5686 HSTMT_LOCK(stmt);
5687 if (catalog) {
5688 c = uc_to_utf_c(catalog, catalogLen);
5689 if (!c) {
5690 ret = nomem((STMT *) stmt);
5691 goto done;
5692 }
5693 }
5694 if (schema) {
5695 s = uc_to_utf_c(schema, schemaLen);
5696 if (!s) {
5697 ret = nomem((STMT *) stmt);
5698 goto done;
5699 }
5700 }
5701 if (table) {
5702 t = uc_to_utf_c(table, tableLen);
5703 if (!t) {
5704 ret = nomem((STMT *) stmt);
5705 goto done;
5706 }
5707 }
5708 ret = drvtableprivileges(stmt, (SQLCHAR *) c, SQL_NTS,
5709 (SQLCHAR *) s, SQL_NTS,
5710 (SQLCHAR *) t, SQL_NTS);
5711 done:
5712 uc_free(t);
5713 uc_free(s);
5714 uc_free(c);
5715 HSTMT_UNLOCK(stmt);
5716 return ret;
5717 }
5718 #endif
5719 #endif
5720
5721 /**
5722 * Columns for result set of SQLColumnPrivileges().
5723 */
5724
5725 static COL colPrivSpec2[] = {
5726 { "SYSTEM", "COLPRIV", "TABLE_QUALIFIER", SCOL_VARCHAR, 50 },
5727 { "SYSTEM", "COLPRIV", "TABLE_OWNER", SCOL_VARCHAR, 50 },
5728 { "SYSTEM", "COLPRIV", "TABLE_NAME", SCOL_VARCHAR, 255 },
5729 { "SYSTEM", "COLPRIV", "COLUMN_NAME", SCOL_VARCHAR, 255 },
5730 { "SYSTEM", "COLPRIV", "GRANTOR", SCOL_VARCHAR, 50 },
5731 { "SYSTEM", "COLPRIV", "GRANTEE", SCOL_VARCHAR, 50 },
5732 { "SYSTEM", "COLPRIV", "PRIVILEGE", SCOL_VARCHAR, 50 }
5733 };
5734
5735 static COL colPrivSpec3[] = {
5736 { "SYSTEM", "COLPRIV", "TABLE_CAT", SCOL_VARCHAR, 50 },
5737 { "SYSTEM", "COLPRIV", "TABLE_SCHEM", SCOL_VARCHAR, 50 },
5738 { "SYSTEM", "COLPRIV", "TABLE_NAME", SCOL_VARCHAR, 255 },
5739 { "SYSTEM", "COLPRIV", "COLUMN_NAME", SCOL_VARCHAR, 255 },
5740 { "SYSTEM", "COLPRIV", "GRANTOR", SCOL_VARCHAR, 50 },
5741 { "SYSTEM", "COLPRIV", "GRANTEE", SCOL_VARCHAR, 50 },
5742 { "SYSTEM", "COLPRIV", "PRIVILEGE", SCOL_VARCHAR, 50 }
5743 };
5744
5745 #if !defined(WINTERFACE) || (defined(HAVE_UNIXODBC) && (HAVE_UNIXODBC))
5746 /**
5747 * Retrieve privileges on columns.
5748 * @param stmt statement handle
5749 * @param catalog catalog name/pattern or NULL
5750 * @param catalogLen length of catalog name/pattern or SQL_NTS
5751 * @param schema schema name/pattern or NULL
5752 * @param schemaLen length of schema name/pattern or SQL_NTS
5753 * @param table table name/pattern or NULL
5754 * @param tableLen length of table name/pattern or SQL_NTS
5755 * @param column column name or NULL
5756 * @param columnLen length of column name or SQL_NTS
5757 * @result ODBC error code
5758 */
5759
5760 SQLRETURN SQL_API
SQLColumnPrivileges(SQLHSTMT stmt,SQLCHAR * catalog,SQLSMALLINT catalogLen,SQLCHAR * schema,SQLSMALLINT schemaLen,SQLCHAR * table,SQLSMALLINT tableLen,SQLCHAR * column,SQLSMALLINT columnLen)5761 SQLColumnPrivileges(SQLHSTMT stmt,
5762 SQLCHAR *catalog, SQLSMALLINT catalogLen,
5763 SQLCHAR *schema, SQLSMALLINT schemaLen,
5764 SQLCHAR *table, SQLSMALLINT tableLen,
5765 SQLCHAR *column, SQLSMALLINT columnLen)
5766 {
5767 SQLRETURN ret;
5768
5769 HSTMT_LOCK(stmt);
5770 ret = mkresultset(stmt, colPrivSpec2, array_size(colPrivSpec2),
5771 colPrivSpec3, array_size(colPrivSpec3), NULL);
5772 HSTMT_UNLOCK(stmt);
5773 return ret;
5774 }
5775 #endif
5776
5777 #if !defined(HAVE_UNIXODBC) || !(HAVE_UNIXODBC)
5778 #ifdef WINTERFACE
5779 /**
5780 * Retrieve privileges on columns (UNICODE version).
5781 * @param stmt statement handle
5782 * @param catalog catalog name/pattern or NULL
5783 * @param catalogLen length of catalog name/pattern or SQL_NTS
5784 * @param schema schema name/pattern or NULL
5785 * @param schemaLen length of schema name/pattern or SQL_NTS
5786 * @param table table name/pattern or NULL
5787 * @param tableLen length of table name/pattern or SQL_NTS
5788 * @param column column name or NULL
5789 * @param columnLen length of column name or SQL_NTS
5790 * @result ODBC error code
5791 */
5792
5793 SQLRETURN SQL_API
SQLColumnPrivilegesW(SQLHSTMT stmt,SQLWCHAR * catalog,SQLSMALLINT catalogLen,SQLWCHAR * schema,SQLSMALLINT schemaLen,SQLWCHAR * table,SQLSMALLINT tableLen,SQLWCHAR * column,SQLSMALLINT columnLen)5794 SQLColumnPrivilegesW(SQLHSTMT stmt,
5795 SQLWCHAR *catalog, SQLSMALLINT catalogLen,
5796 SQLWCHAR *schema, SQLSMALLINT schemaLen,
5797 SQLWCHAR *table, SQLSMALLINT tableLen,
5798 SQLWCHAR *column, SQLSMALLINT columnLen)
5799 {
5800 SQLRETURN ret;
5801
5802 HSTMT_LOCK(stmt);
5803 ret = mkresultset(stmt, colPrivSpec2, array_size(colPrivSpec2),
5804 colPrivSpec3, array_size(colPrivSpec3), NULL);
5805 HSTMT_UNLOCK(stmt);
5806 return ret;
5807 }
5808 #endif
5809 #endif
5810
5811 /**
5812 * Columns for result set of SQLPrimaryKeys().
5813 */
5814
5815 static COL pkeySpec2[] = {
5816 { "SYSTEM", "PRIMARYKEY", "TABLE_QUALIFIER", SCOL_VARCHAR, 50 },
5817 { "SYSTEM", "PRIMARYKEY", "TABLE_OWNER", SCOL_VARCHAR, 50 },
5818 { "SYSTEM", "PRIMARYKEY", "TABLE_NAME", SCOL_VARCHAR, 255 },
5819 { "SYSTEM", "PRIMARYKEY", "COLUMN_NAME", SCOL_VARCHAR, 255 },
5820 { "SYSTEM", "PRIMARYKEY", "KEY_SEQ", SQL_SMALLINT, 50 },
5821 { "SYSTEM", "PRIMARYKEY", "PK_NAME", SCOL_VARCHAR, 50 }
5822 };
5823
5824 static COL pkeySpec3[] = {
5825 { "SYSTEM", "PRIMARYKEY", "TABLE_CAT", SCOL_VARCHAR, 50 },
5826 { "SYSTEM", "PRIMARYKEY", "TABLE_SCHEM", SCOL_VARCHAR, 50 },
5827 { "SYSTEM", "PRIMARYKEY", "TABLE_NAME", SCOL_VARCHAR, 255 },
5828 { "SYSTEM", "PRIMARYKEY", "COLUMN_NAME", SCOL_VARCHAR, 255 },
5829 { "SYSTEM", "PRIMARYKEY", "KEY_SEQ", SQL_SMALLINT, 50 },
5830 { "SYSTEM", "PRIMARYKEY", "PK_NAME", SCOL_VARCHAR, 50 }
5831 };
5832
5833 /**
5834 * Internal retrieve information about indexed columns.
5835 * @param stmt statement handle
5836 * @param cat catalog name/pattern or NULL
5837 * @param catLen length of catalog name/pattern or SQL_NTS
5838 * @param schema schema name/pattern or NULL
5839 * @param schemaLen length of schema name/pattern or SQL_NTS
5840 * @param table table name/pattern or NULL
5841 * @param tableLen length of table name/pattern or SQL_NTS
5842 * @result ODBC error code
5843 */
5844
5845 static SQLRETURN
drvprimarykeys(SQLHSTMT stmt,SQLCHAR * cat,SQLSMALLINT catLen,SQLCHAR * schema,SQLSMALLINT schemaLen,SQLCHAR * table,SQLSMALLINT tableLen)5846 drvprimarykeys(SQLHSTMT stmt,
5847 SQLCHAR *cat, SQLSMALLINT catLen,
5848 SQLCHAR *schema, SQLSMALLINT schemaLen,
5849 SQLCHAR *table, SQLSMALLINT tableLen)
5850 {
5851 STMT *s;
5852 DBC *d;
5853 SQLRETURN sret;
5854 int i, asize, ret, nrows, ncols, nrows2 = 0, ncols2 = 0;
5855 int namec = -1, uniquec = -1, namec2 = -1, uniquec2 = -1, offs, seq = 1;
5856 PTRDIFF_T size;
5857 char **rowp = NULL, **rowp2 = NULL, *errp = NULL, *sql, tname[512];
5858
5859 sret = mkresultset(stmt, pkeySpec2, array_size(pkeySpec2),
5860 pkeySpec3, array_size(pkeySpec3), &asize);
5861 if (sret != SQL_SUCCESS) {
5862 return sret;
5863 }
5864 s = (STMT *) stmt;
5865 d = (DBC *) s->dbc;
5866 if (!table || table[0] == '\0' || table[0] == '%') {
5867 setstat(s, -1, "need table name", (*s->ov3) ? "HY000" : "S1000");
5868 return SQL_ERROR;
5869 }
5870 if (tableLen == SQL_NTS) {
5871 size = sizeof (tname) - 1;
5872 } else {
5873 size = min(sizeof (tname) - 1, tableLen);
5874 }
5875 strncpy(tname, (char *) table, size);
5876 tname[size] = '\0';
5877 unescpat(tname);
5878 sql = sqlite3_mprintf("PRAGMA table_info(%Q)", tname);
5879 if (!sql) {
5880 return nomem(s);
5881 }
5882 sret = starttran(s);
5883 if (sret != SQL_SUCCESS) {
5884 sqlite3_free(sql);
5885 return sret;
5886 }
5887 dbtraceapi(d, "sqlite3_get_table", sql);
5888 ret = sqlite3_get_table(d->sqlite, sql, &rowp, &nrows, &ncols, &errp);
5889 sqlite3_free(sql);
5890 if (ret != SQLITE_OK) {
5891 setstat(s, ret, "%s (%d)", (*s->ov3) ? "HY000" : "S1000",
5892 errp ? errp : "unknown error", ret);
5893 if (errp) {
5894 sqlite3_free(errp);
5895 errp = NULL;
5896 }
5897 return SQL_ERROR;
5898 }
5899 if (errp) {
5900 sqlite3_free(errp);
5901 errp = NULL;
5902 }
5903 size = 0;
5904 if (ncols * nrows > 0) {
5905 int typec;
5906
5907 namec = findcol(rowp, ncols, "name");
5908 uniquec = findcol(rowp, ncols, "pk");
5909 typec = findcol(rowp, ncols, "type");
5910 if (namec >= 0 && uniquec >= 0 && typec >= 0) {
5911 for (i = 1; i <= nrows; i++) {
5912 if (*rowp[i * ncols + uniquec] != '0') {
5913 size++;
5914 }
5915 }
5916 }
5917 }
5918 if (size == 0) {
5919 sql = sqlite3_mprintf("PRAGMA index_list(%Q)", tname);
5920 if (!sql) {
5921 sqlite3_free_table(rowp);
5922 return nomem(s);
5923 }
5924 dbtraceapi(d, "sqlite3_get_table", sql);
5925 ret = sqlite3_get_table(d->sqlite, sql, &rowp2, &nrows2, &ncols2,
5926 &errp);
5927 sqlite3_free(sql);
5928 if (ret != SQLITE_OK) {
5929 sqlite3_free_table(rowp);
5930 sqlite3_free_table(rowp2);
5931 setstat(s, ret, "%s (%d)", (*s->ov3) ? "HY000" : "S1000",
5932 errp ? errp : "unknown error", ret);
5933 if (errp) {
5934 sqlite3_free(errp);
5935 errp = NULL;
5936 }
5937 return SQL_ERROR;
5938 }
5939 if (errp) {
5940 sqlite3_free(errp);
5941 errp = NULL;
5942 }
5943 }
5944 if (ncols2 * nrows2 > 0) {
5945 namec2 = findcol(rowp2, ncols2, "name");
5946 uniquec2 = findcol(rowp2, ncols2, "unique");
5947 if (namec2 >= 0 && uniquec2 >= 0) {
5948 for (i = 1; i <= nrows2; i++) {
5949 int nnrows, nncols, nlen = 0;
5950 char **rowpp;
5951
5952 if (rowp2[i * ncols2 + namec2]) {
5953 nlen = strlen(rowp2[i * ncols2 + namec2]);
5954 }
5955 if (nlen < 17 ||
5956 strncmp(rowp2[i * ncols2 + namec2],
5957 "sqlite_autoindex_", 17)) {
5958 continue;
5959 }
5960 if (*rowp2[i * ncols2 + uniquec2] != '0') {
5961 ret = SQLITE_ERROR;
5962 sql = sqlite3_mprintf("PRAGMA index_info(%Q)",
5963 rowp2[i * ncols2 + namec2]);
5964 if (sql) {
5965 dbtraceapi(d, "sqlite3_get_table", sql);
5966 ret = sqlite3_get_table(d->sqlite, sql, &rowpp,
5967 &nnrows, &nncols, NULL);
5968 sqlite3_free(sql);
5969 }
5970 if (ret == SQLITE_OK) {
5971 size += nnrows;
5972 sqlite3_free_table(rowpp);
5973 }
5974 }
5975 }
5976 }
5977 }
5978 if (size == 0) {
5979 sqlite3_free_table(rowp);
5980 sqlite3_free_table(rowp2);
5981 return SQL_SUCCESS;
5982 }
5983 s->nrows = size;
5984 size = (size + 1) * asize;
5985 s->rows = xmalloc((size + 1) * sizeof (char *));
5986 if (!s->rows) {
5987 s->nrows = 0;
5988 sqlite3_free_table(rowp);
5989 sqlite3_free_table(rowp2);
5990 return nomem(s);
5991 }
5992 s->rows[0] = (char *) size;
5993 s->rows += 1;
5994 memset(s->rows, 0, sizeof (char *) * size);
5995 s->rowfree = freerows;
5996 offs = s->ncols;
5997 if (rowp) {
5998 for (i = 1; i <= nrows; i++) {
5999 if (*rowp[i * ncols + uniquec] != '0') {
6000 char buf[32];
6001
6002 s->rows[offs + 0] = xstrdup("");
6003 #if defined(_WIN32) || defined(_WIN64)
6004 s->rows[offs + 1] = xstrdup(d->xcelqrx ? "main" : "");
6005 #else
6006 s->rows[offs + 1] = xstrdup("");
6007 #endif
6008 s->rows[offs + 2] = xstrdup(tname);
6009 s->rows[offs + 3] = xstrdup(rowp[i * ncols + namec]);
6010 sprintf(buf, "%d", seq++);
6011 s->rows[offs + 4] = xstrdup(buf);
6012 offs += s->ncols;
6013 }
6014 }
6015 }
6016 if (rowp2) {
6017 for (i = 1; i <= nrows2; i++) {
6018 int nnrows, nncols, nlen = 0;
6019 char **rowpp;
6020
6021 if (rowp2[i * ncols2 + namec2]) {
6022 nlen = strlen(rowp2[i * ncols2 + namec2]);
6023 }
6024 if (nlen < 17 ||
6025 strncmp(rowp2[i * ncols2 + namec2], "sqlite_autoindex_", 17)) {
6026 continue;
6027 }
6028 if (*rowp2[i * ncols2 + uniquec2] != '0') {
6029 int k;
6030
6031 ret = SQLITE_ERROR;
6032 sql = sqlite3_mprintf("PRAGMA index_info(%Q)",
6033 rowp2[i * ncols2 + namec2]);
6034 if (sql) {
6035 dbtraceapi(d, "sqlite3_get_table", sql);
6036 ret = sqlite3_get_table(d->sqlite, sql, &rowpp,
6037 &nnrows, &nncols, NULL);
6038 sqlite3_free(sql);
6039 }
6040 if (ret != SQLITE_OK) {
6041 continue;
6042 }
6043 for (k = 0; nnrows && k < nncols; k++) {
6044 if (strcmp(rowpp[k], "name") == 0) {
6045 int m;
6046
6047 for (m = 1; m <= nnrows; m++) {
6048 int roffs = offs + (m - 1) * s->ncols;
6049
6050 s->rows[roffs + 0] = xstrdup("");
6051 #if defined(_WIN32) || defined(_WIN64)
6052 s->rows[roffs + 1] =
6053 xstrdup(d->xcelqrx ? "main" : "");
6054 #else
6055 s->rows[roffs + 1] = xstrdup("");
6056 #endif
6057 s->rows[roffs + 2] = xstrdup(tname);
6058 s->rows[roffs + 3] =
6059 xstrdup(rowpp[m * nncols + k]);
6060 s->rows[roffs + 5] =
6061 xstrdup(rowp2[i * ncols2 + namec2]);
6062 }
6063 } else if (strcmp(rowpp[k], "seqno") == 0) {
6064 int m;
6065
6066 for (m = 1; m <= nnrows; m++) {
6067 int roffs = offs + (m - 1) * s->ncols;
6068 int pos = m - 1;
6069 char buf[32];
6070
6071 sscanf(rowpp[m * nncols + k], "%d", &pos);
6072 sprintf(buf, "%d", pos + 1);
6073 s->rows[roffs + 4] = xstrdup(buf);
6074 }
6075 }
6076 }
6077 offs += nnrows * s->ncols;
6078 sqlite3_free_table(rowpp);
6079 }
6080 }
6081 }
6082 sqlite3_free_table(rowp);
6083 sqlite3_free_table(rowp2);
6084 return SQL_SUCCESS;
6085 }
6086
6087 #ifndef WINTERFACE
6088 /**
6089 * Retrieve information about indexed columns.
6090 * @param stmt statement handle
6091 * @param cat catalog name/pattern or NULL
6092 * @param catLen length of catalog name/pattern or SQL_NTS
6093 * @param schema schema name/pattern or NULL
6094 * @param schemaLen length of schema name/pattern or SQL_NTS
6095 * @param table table name/pattern or NULL
6096 * @param tableLen length of table name/pattern or SQL_NTS
6097 * @result ODBC error code
6098 */
6099
6100 SQLRETURN SQL_API
SQLPrimaryKeys(SQLHSTMT stmt,SQLCHAR * cat,SQLSMALLINT catLen,SQLCHAR * schema,SQLSMALLINT schemaLen,SQLCHAR * table,SQLSMALLINT tableLen)6101 SQLPrimaryKeys(SQLHSTMT stmt,
6102 SQLCHAR *cat, SQLSMALLINT catLen,
6103 SQLCHAR *schema, SQLSMALLINT schemaLen,
6104 SQLCHAR *table, SQLSMALLINT tableLen)
6105 {
6106 #if defined(_WIN32) || defined(_WIN64)
6107 char *c = NULL, *s = NULL, *t = NULL;
6108 #endif
6109 SQLRETURN ret;
6110
6111 HSTMT_LOCK(stmt);
6112 #if defined(_WIN32) || defined(_WIN64)
6113 if (!((STMT *) stmt)->oemcp[0]) {
6114 ret = drvprimarykeys(stmt, cat, catLen, schema, schemaLen,
6115 table, tableLen);
6116 goto done2;
6117 }
6118 if (cat) {
6119 c = wmb_to_utf_c((char *) cat, catLen);
6120 if (!c) {
6121 ret = nomem((STMT *) stmt);
6122 goto done;
6123 }
6124 }
6125 if (schema) {
6126 s = wmb_to_utf_c((char *) schema, schemaLen);
6127 if (!s) {
6128 ret = nomem((STMT *) stmt);
6129 goto done;
6130 }
6131 }
6132 if (table) {
6133 t = wmb_to_utf_c((char *) table, tableLen);
6134 if (!t) {
6135 ret = nomem((STMT *) stmt);
6136 goto done;
6137 }
6138 }
6139 ret = drvprimarykeys(stmt, (SQLCHAR *) c, SQL_NTS,
6140 (SQLCHAR *) s, SQL_NTS, (SQLCHAR *) t, SQL_NTS);
6141 #else
6142 ret = drvprimarykeys(stmt, cat, catLen, schema, schemaLen,
6143 table, tableLen);
6144 #endif
6145 #if defined(_WIN32) || defined(_WIN64)
6146 done:
6147 uc_free(t);
6148 uc_free(s);
6149 uc_free(c);
6150 done2:
6151 ;
6152 #endif
6153 HSTMT_UNLOCK(stmt);
6154 return ret;
6155 }
6156 #endif
6157
6158 #ifdef WINTERFACE
6159 /**
6160 * Retrieve information about indexed columns (UNICODE version).
6161 * @param stmt statement handle
6162 * @param cat catalog name/pattern or NULL
6163 * @param catLen length of catalog name/pattern or SQL_NTS
6164 * @param schema schema name/pattern or NULL
6165 * @param schemaLen length of schema name/pattern or SQL_NTS
6166 * @param table table name/pattern or NULL
6167 * @param tableLen length of table name/pattern or SQL_NTS
6168 * @result ODBC error code
6169 */
6170
6171 SQLRETURN SQL_API
SQLPrimaryKeysW(SQLHSTMT stmt,SQLWCHAR * cat,SQLSMALLINT catLen,SQLWCHAR * schema,SQLSMALLINT schemaLen,SQLWCHAR * table,SQLSMALLINT tableLen)6172 SQLPrimaryKeysW(SQLHSTMT stmt,
6173 SQLWCHAR *cat, SQLSMALLINT catLen,
6174 SQLWCHAR *schema, SQLSMALLINT schemaLen,
6175 SQLWCHAR *table, SQLSMALLINT tableLen)
6176 {
6177 char *c = NULL, *s = NULL, *t = NULL;
6178 SQLRETURN ret;
6179
6180 HSTMT_LOCK(stmt);
6181 if (cat) {
6182 c = uc_to_utf_c(cat, catLen);
6183 if (!c) {
6184 ret = nomem((STMT *) stmt);
6185 goto done;
6186 }
6187 }
6188 if (schema) {
6189 s = uc_to_utf_c(schema, schemaLen);
6190 if (!s) {
6191 ret = nomem((STMT *) stmt);
6192 goto done;
6193 }
6194 }
6195 if (table) {
6196 t = uc_to_utf_c(table, tableLen);
6197 if (!t) {
6198 ret = nomem((STMT *) stmt);
6199 goto done;
6200 }
6201 }
6202 ret = drvprimarykeys(stmt, (SQLCHAR *) c, SQL_NTS,
6203 (SQLCHAR *) s, SQL_NTS, (SQLCHAR *) t, SQL_NTS);
6204 done:
6205 uc_free(t);
6206 uc_free(s);
6207 uc_free(c);
6208 HSTMT_UNLOCK(stmt);
6209 return ret;
6210 }
6211 #endif
6212
6213 /**
6214 * Columns for result set of SQLSpecialColumns().
6215 */
6216
6217 static COL scolSpec2[] = {
6218 { "SYSTEM", "COLUMN", "SCOPE", SQL_SMALLINT, 1 },
6219 { "SYSTEM", "COLUMN", "COLUMN_NAME", SCOL_VARCHAR, 255 },
6220 { "SYSTEM", "COLUMN", "DATA_TYPE", SQL_SMALLINT, 50 },
6221 { "SYSTEM", "COLUMN", "TYPE_NAME", SCOL_VARCHAR, 50 },
6222 { "SYSTEM", "COLUMN", "PRECISION", SQL_INTEGER, 50 },
6223 { "SYSTEM", "COLUMN", "LENGTH", SQL_INTEGER, 50 },
6224 { "SYSTEM", "COLUMN", "DECIMAL_DIGITS", SQL_INTEGER, 50 },
6225 { "SYSTEM", "COLUMN", "PSEUDO_COLUMN", SQL_SMALLINT, 1 },
6226 { "SYSTEM", "COLUMN", "NULLABLE", SQL_SMALLINT, 1 }
6227 };
6228
6229 static COL scolSpec3[] = {
6230 { "SYSTEM", "COLUMN", "SCOPE", SQL_SMALLINT, 1 },
6231 { "SYSTEM", "COLUMN", "COLUMN_NAME", SCOL_VARCHAR, 255 },
6232 { "SYSTEM", "COLUMN", "DATA_TYPE", SQL_SMALLINT, 50 },
6233 { "SYSTEM", "COLUMN", "TYPE_NAME", SCOL_VARCHAR, 50 },
6234 { "SYSTEM", "COLUMN", "COLUMN_SIZE", SQL_INTEGER, 50 },
6235 { "SYSTEM", "COLUMN", "BUFFER_LENGTH", SQL_INTEGER, 50 },
6236 { "SYSTEM", "COLUMN", "DECIMAL_DIGITS", SQL_INTEGER, 50 },
6237 { "SYSTEM", "COLUMN", "PSEUDO_COLUMN", SQL_SMALLINT, 1 },
6238 { "SYSTEM", "COLUMN", "NULLABLE", SQL_SMALLINT, 1 }
6239 };
6240
6241 /**
6242 * Internal retrieve information about indexed columns.
6243 * @param stmt statement handle
6244 * @param id type of information, e.g. best row id
6245 * @param cat catalog name/pattern or NULL
6246 * @param catLen length of catalog name/pattern or SQL_NTS
6247 * @param schema schema name/pattern or NULL
6248 * @param schemaLen length of schema name/pattern or SQL_NTS
6249 * @param table table name/pattern or NULL
6250 * @param tableLen length of table name/pattern or SQL_NTS
6251 * @param scope
6252 * @param nullable
6253 * @result ODBC error code
6254 */
6255
6256 static SQLRETURN
drvspecialcolumns(SQLHSTMT stmt,SQLUSMALLINT id,SQLCHAR * cat,SQLSMALLINT catLen,SQLCHAR * schema,SQLSMALLINT schemaLen,SQLCHAR * table,SQLSMALLINT tableLen,SQLUSMALLINT scope,SQLUSMALLINT nullable)6257 drvspecialcolumns(SQLHSTMT stmt, SQLUSMALLINT id,
6258 SQLCHAR *cat, SQLSMALLINT catLen,
6259 SQLCHAR *schema, SQLSMALLINT schemaLen,
6260 SQLCHAR *table, SQLSMALLINT tableLen,
6261 SQLUSMALLINT scope, SQLUSMALLINT nullable)
6262 {
6263 STMT *s;
6264 DBC *d;
6265 SQLRETURN sret;
6266 int i, asize, ret, nrows, ncols, nnnrows, nnncols, offs;
6267 PTRDIFF_T size;
6268 int namec = -1, uniquec = -1, namecc = -1, typecc = -1;
6269 int notnullcc = -1, mkrowid = 0;
6270 char *errp = NULL, *sql, tname[512];
6271 char **rowp = NULL, **rowppp = NULL;
6272
6273 sret = mkresultset(stmt, scolSpec2, array_size(scolSpec2),
6274 scolSpec3, array_size(scolSpec3), &asize);
6275 if (sret != SQL_SUCCESS) {
6276 return sret;
6277 }
6278 s = (STMT *) stmt;
6279 d = (DBC *) s->dbc;
6280 if (!table || table[0] == '\0' || table[0] == '%') {
6281 setstat(s, -1, "need table name", (*s->ov3) ? "HY000" : "S1000");
6282 return SQL_ERROR;
6283 }
6284 if (tableLen == SQL_NTS) {
6285 size = sizeof (tname) - 1;
6286 } else {
6287 size = min(sizeof (tname) - 1, tableLen);
6288 }
6289 strncpy(tname, (char *) table, size);
6290 tname[size] = '\0';
6291 unescpat(tname);
6292 if (id != SQL_BEST_ROWID) {
6293 return SQL_SUCCESS;
6294 }
6295 sql = sqlite3_mprintf("PRAGMA index_list(%Q)", tname);
6296 if (!sql) {
6297 return nomem(s);
6298 }
6299 sret = starttran(s);
6300 if (sret != SQL_SUCCESS) {
6301 sqlite3_free(sql);
6302 return sret;
6303 }
6304 dbtraceapi(d, "sqlite3_get_table", sql);
6305 ret = sqlite3_get_table(d->sqlite, sql, &rowp, &nrows, &ncols, &errp);
6306 sqlite3_free(sql);
6307 if (ret != SQLITE_OK) {
6308 doerr:
6309 setstat(s, ret, "%s (%d)", (*s->ov3) ? "HY000" : "S1000",
6310 errp ? errp : "unknown error", ret);
6311 if (errp) {
6312 sqlite3_free(errp);
6313 errp = NULL;
6314 }
6315 return SQL_ERROR;
6316 }
6317 if (errp) {
6318 sqlite3_free(errp);
6319 errp = NULL;
6320 }
6321 size = 0; /* number result rows */
6322 if (ncols * nrows <= 0) {
6323 goto nodata_but_rowid;
6324 }
6325 sql = sqlite3_mprintf("PRAGMA table_info(%Q)", tname);
6326 if (!sql) {
6327 return nomem(s);
6328 }
6329 dbtraceapi(d, "sqlite3_get_table", sql);
6330 ret = sqlite3_get_table(d->sqlite, sql, &rowppp, &nnnrows, &nnncols,
6331 &errp);
6332 sqlite3_free(sql);
6333 if (ret != SQLITE_OK) {
6334 sqlite3_free_table(rowp);
6335 goto doerr;
6336 }
6337 if (errp) {
6338 sqlite3_free(errp);
6339 errp = NULL;
6340 }
6341 namec = findcol(rowp, ncols, "name");
6342 uniquec = findcol(rowp, ncols, "unique");
6343 if (namec < 0 || uniquec < 0) {
6344 goto nodata_but_rowid;
6345 }
6346 namecc = findcol(rowppp, nnncols, "name");
6347 typecc = findcol(rowppp, nnncols, "type");
6348 notnullcc = findcol(rowppp, nnncols, "notnull");
6349 for (i = 1; i <= nrows; i++) {
6350 int nnrows, nncols;
6351 char **rowpp = NULL;
6352
6353 if (*rowp[i * ncols + uniquec] != '0') {
6354 ret = SQLITE_ERROR;
6355 sql = sqlite3_mprintf("PRAGMA index_info(%Q)",
6356 rowp[i * ncols + namec]);
6357 if (sql) {
6358 dbtraceapi(d, "sqlite3_get_table", sql);
6359 ret = sqlite3_get_table(d->sqlite, sql, &rowpp,
6360 &nnrows, &nncols, NULL);
6361 sqlite3_free(sql);
6362 }
6363 if (ret == SQLITE_OK) {
6364 size += nnrows;
6365 sqlite3_free_table(rowpp);
6366 }
6367 }
6368 }
6369 nodata_but_rowid:
6370 if (size == 0) {
6371 size = 1;
6372 mkrowid = 1;
6373 }
6374 s->nrows = size;
6375 size = (size + 1) * asize;
6376 s->rows = xmalloc((size + 1) * sizeof (char *));
6377 if (!s->rows) {
6378 s->nrows = 0;
6379 sqlite3_free_table(rowp);
6380 sqlite3_free_table(rowppp);
6381 return nomem(s);
6382 }
6383 s->rows[0] = (char *) size;
6384 s->rows += 1;
6385 memset(s->rows, 0, sizeof (char *) * size);
6386 s->rowfree = freerows;
6387 if (mkrowid) {
6388 s->nrows = 0;
6389 goto mkrowid;
6390 }
6391 offs = 0;
6392 for (i = 1; i <= nrows; i++) {
6393 int nnrows, nncols;
6394 char **rowpp = NULL;
6395
6396 if (*rowp[i * ncols + uniquec] != '0') {
6397 int k;
6398
6399 ret = SQLITE_ERROR;
6400 sql = sqlite3_mprintf("PRAGMA index_info(%Q)",
6401 rowp[i * ncols + namec]);
6402 if (sql) {
6403 dbtraceapi(d, "sqlite3_get_table", sql);
6404 ret = sqlite3_get_table(d->sqlite, sql, &rowpp,
6405 &nnrows, &nncols, NULL);
6406 sqlite3_free(sql);
6407 }
6408 if (ret != SQLITE_OK) {
6409 continue;
6410 }
6411 for (k = 0; nnrows && k < nncols; k++) {
6412 if (strcmp(rowpp[k], "name") == 0) {
6413 int m;
6414
6415 for (m = 1; m <= nnrows; m++) {
6416 int roffs = (offs + m) * s->ncols;
6417
6418 s->rows[roffs + 0] =
6419 xstrdup(stringify(SQL_SCOPE_SESSION));
6420 s->rows[roffs + 1] = xstrdup(rowpp[m * nncols + k]);
6421 s->rows[roffs + 4] = xstrdup("0");
6422 s->rows[roffs + 7] =
6423 xstrdup(stringify(SQL_PC_NOT_PSEUDO));
6424 if (namecc >= 0 && typecc >= 0) {
6425 int ii;
6426
6427 for (ii = 1; ii <= nnnrows; ii++) {
6428 if (strcmp(rowppp[ii * nnncols + namecc],
6429 rowpp[m * nncols + k]) == 0) {
6430 char *typen = rowppp[ii * nnncols + typecc];
6431 int sqltype, mm, dd, isnullable = 0;
6432 char buf[32];
6433
6434 s->rows[roffs + 3] = xstrdup(typen);
6435 sqltype = mapsqltype(typen, NULL, *s->ov3,
6436 s->nowchar[0],
6437 s->dobigint);
6438 getmd(typen, sqltype, &mm, &dd);
6439 #ifdef SQL_LONGVARCHAR
6440 if (sqltype == SQL_VARCHAR && mm > 255) {
6441 sqltype = SQL_LONGVARCHAR;
6442 }
6443 #endif
6444 #ifdef WINTERFACE
6445 #ifdef SQL_WLONGVARCHAR
6446 if (sqltype == SQL_WVARCHAR && mm > 255) {
6447 sqltype = SQL_WLONGVARCHAR;
6448 }
6449 #endif
6450 #endif
6451 if (sqltype == SQL_VARBINARY && mm > 255) {
6452 sqltype = SQL_LONGVARBINARY;
6453 }
6454 sprintf(buf, "%d", sqltype);
6455 s->rows[roffs + 2] = xstrdup(buf);
6456 sprintf(buf, "%d", mm);
6457 s->rows[roffs + 5] = xstrdup(buf);
6458 sprintf(buf, "%d", dd);
6459 s->rows[roffs + 6] = xstrdup(buf);
6460 if (notnullcc >= 0) {
6461 char *inp =
6462 rowppp[ii * nnncols + notnullcc];
6463
6464 isnullable = inp[0] != '0';
6465 }
6466 sprintf(buf, "%d", isnullable);
6467 s->rows[roffs + 8] = xstrdup(buf);
6468 }
6469 }
6470 }
6471 }
6472 }
6473 }
6474 offs += nnrows;
6475 sqlite3_free_table(rowpp);
6476 }
6477 }
6478 if (nullable == SQL_NO_NULLS) {
6479 for (i = 1; i < s->nrows; i++) {
6480 if (s->rows[i * s->ncols + 8][0] == '0') {
6481 int m, i1 = i + 1;
6482
6483 for (m = 0; m < s->ncols; m++) {
6484 freep(&s->rows[i * s->ncols + m]);
6485 }
6486 size = s->ncols * sizeof (char *) * (s->nrows - i1);
6487 if (size > 0) {
6488 memmove(s->rows + i * s->ncols,
6489 s->rows + i1 * s->ncols,
6490 size);
6491 memset(s->rows + s->nrows * s->ncols, 0,
6492 s->ncols * sizeof (char *));
6493 }
6494 s->nrows--;
6495 --i;
6496 }
6497 }
6498 }
6499 mkrowid:
6500 sqlite3_free_table(rowp);
6501 sqlite3_free_table(rowppp);
6502 if (s->nrows == 0) {
6503 s->rows[s->ncols + 0] = xstrdup(stringify(SQL_SCOPE_SESSION));
6504 s->rows[s->ncols + 1] = xstrdup("_ROWID_");
6505 s->rows[s->ncols + 2] = xstrdup(stringify(SQL_INTEGER));
6506 s->rows[s->ncols + 3] = xstrdup("integer");
6507 s->rows[s->ncols + 4] = xstrdup("0");
6508 s->rows[s->ncols + 5] = xstrdup("10");
6509 s->rows[s->ncols + 6] = xstrdup("9");
6510 s->rows[s->ncols + 7] = xstrdup(stringify(SQL_PC_PSEUDO));
6511 s->rows[s->ncols + 8] = xstrdup(stringify(SQL_FALSE));
6512 s->nrows = 1;
6513 }
6514 return SQL_SUCCESS;
6515 }
6516
6517 #ifndef WINTERFACE
6518 /**
6519 * Retrieve information about indexed columns.
6520 * @param stmt statement handle
6521 * @param id type of information, e.g. best row id
6522 * @param cat catalog name/pattern or NULL
6523 * @param catLen length of catalog name/pattern or SQL_NTS
6524 * @param schema schema name/pattern or NULL
6525 * @param schemaLen length of schema name/pattern or SQL_NTS
6526 * @param table table name/pattern or NULL
6527 * @param tableLen length of table name/pattern or SQL_NTS
6528 * @param scope
6529 * @param nullable
6530 * @result ODBC error code
6531 */
6532
6533 SQLRETURN SQL_API
SQLSpecialColumns(SQLHSTMT stmt,SQLUSMALLINT id,SQLCHAR * cat,SQLSMALLINT catLen,SQLCHAR * schema,SQLSMALLINT schemaLen,SQLCHAR * table,SQLSMALLINT tableLen,SQLUSMALLINT scope,SQLUSMALLINT nullable)6534 SQLSpecialColumns(SQLHSTMT stmt, SQLUSMALLINT id,
6535 SQLCHAR *cat, SQLSMALLINT catLen,
6536 SQLCHAR *schema, SQLSMALLINT schemaLen,
6537 SQLCHAR *table, SQLSMALLINT tableLen,
6538 SQLUSMALLINT scope, SQLUSMALLINT nullable)
6539 {
6540 #if defined(_WIN32) || defined(_WIN64)
6541 char *c = NULL, *s = NULL, *t = NULL;
6542 #endif
6543 SQLRETURN ret;
6544
6545 HSTMT_LOCK(stmt);
6546 #if defined(_WIN32) || defined(_WIN64)
6547 if (!((STMT *) stmt)->oemcp[0]) {
6548 ret = drvspecialcolumns(stmt, id, cat, catLen, schema, schemaLen,
6549 table, tableLen, scope, nullable);
6550 goto done2;
6551 }
6552 if (cat) {
6553 c = wmb_to_utf_c((char *) cat, catLen);
6554 if (!c) {
6555 ret = nomem((STMT *) stmt);
6556 goto done;
6557 }
6558 }
6559 if (schema) {
6560 s = wmb_to_utf_c((char *) schema, schemaLen);
6561 if (!s) {
6562 ret = nomem((STMT *) stmt);
6563 goto done;
6564 }
6565 }
6566 if (table) {
6567 t = wmb_to_utf_c((char *) table, tableLen);
6568 if (!t) {
6569 ret = nomem((STMT *) stmt);
6570 goto done;
6571 }
6572 }
6573 ret = drvspecialcolumns(stmt, id, (SQLCHAR *) c, SQL_NTS,
6574 (SQLCHAR *) s, SQL_NTS, (SQLCHAR *) t, SQL_NTS,
6575 scope, nullable);
6576 #else
6577 ret = drvspecialcolumns(stmt, id, cat, catLen, schema, schemaLen,
6578 table, tableLen, scope, nullable);
6579 #endif
6580 #if defined(_WIN32) || defined(_WIN64)
6581 done:
6582 uc_free(t);
6583 uc_free(s);
6584 uc_free(c);
6585 done2:
6586 ;
6587 #endif
6588 HSTMT_UNLOCK(stmt);
6589 return ret;
6590 }
6591 #endif
6592
6593 #ifdef WINTERFACE
6594 /**
6595 * Retrieve information about indexed columns (UNICODE version).
6596 * @param stmt statement handle
6597 * @param id type of information, e.g. best row id
6598 * @param cat catalog name/pattern or NULL
6599 * @param catLen length of catalog name/pattern or SQL_NTS
6600 * @param schema schema name/pattern or NULL
6601 * @param schemaLen length of schema name/pattern or SQL_NTS
6602 * @param table table name/pattern or NULL
6603 * @param tableLen length of table name/pattern or SQL_NTS
6604 * @param scope
6605 * @param nullable
6606 * @result ODBC error code
6607 */
6608
6609 SQLRETURN SQL_API
SQLSpecialColumnsW(SQLHSTMT stmt,SQLUSMALLINT id,SQLWCHAR * cat,SQLSMALLINT catLen,SQLWCHAR * schema,SQLSMALLINT schemaLen,SQLWCHAR * table,SQLSMALLINT tableLen,SQLUSMALLINT scope,SQLUSMALLINT nullable)6610 SQLSpecialColumnsW(SQLHSTMT stmt, SQLUSMALLINT id,
6611 SQLWCHAR *cat, SQLSMALLINT catLen,
6612 SQLWCHAR *schema, SQLSMALLINT schemaLen,
6613 SQLWCHAR *table, SQLSMALLINT tableLen,
6614 SQLUSMALLINT scope, SQLUSMALLINT nullable)
6615 {
6616 char *c = NULL, *s = NULL, *t = NULL;
6617 SQLRETURN ret;
6618
6619 HSTMT_LOCK(stmt);
6620 if (cat) {
6621 c = uc_to_utf_c(cat, catLen);
6622 if (!c) {
6623 ret = nomem((STMT *) stmt);
6624 goto done;
6625 }
6626 }
6627 if (schema) {
6628 s = uc_to_utf_c(schema, schemaLen);
6629 if (!s) {
6630 ret = nomem((STMT *) stmt);
6631 goto done;
6632 }
6633 }
6634 if (table) {
6635 t = uc_to_utf_c(table, tableLen);
6636 if (!t) {
6637 ret = nomem((STMT *) stmt);
6638 goto done;
6639 }
6640 }
6641 ret = drvspecialcolumns(stmt, id, (SQLCHAR *) c, SQL_NTS,
6642 (SQLCHAR *) s, SQL_NTS, (SQLCHAR *) t, SQL_NTS,
6643 scope, nullable);
6644 done:
6645 uc_free(t);
6646 uc_free(s);
6647 uc_free(c);
6648 HSTMT_UNLOCK(stmt);
6649 return ret;
6650 }
6651 #endif
6652
6653 /**
6654 * Columns for result set of SQLForeignKeys().
6655 */
6656
6657 static COL fkeySpec2[] = {
6658 { "SYSTEM", "FOREIGNKEY", "PKTABLE_QUALIFIER", SCOL_VARCHAR, 50 },
6659 { "SYSTEM", "FOREIGNKEY", "PKTABLE_OWNER", SCOL_VARCHAR, 50 },
6660 { "SYSTEM", "FOREIGNKEY", "PKTABLE_NAME", SCOL_VARCHAR, 255 },
6661 { "SYSTEM", "FOREIGNKEY", "PKCOLUMN_NAME", SCOL_VARCHAR, 255 },
6662 { "SYSTEM", "FOREIGNKEY", "FKTABLE_QUALIFIER", SCOL_VARCHAR, 50 },
6663 { "SYSTEM", "FOREIGNKEY", "FKTABLE_OWNER", SCOL_VARCHAR, 50 },
6664 { "SYSTEM", "FOREIGNKEY", "FKTABLE_NAME", SCOL_VARCHAR, 255 },
6665 { "SYSTEM", "FOREIGNKEY", "FKCOLUMN_NAME", SCOL_VARCHAR, 255 },
6666 { "SYSTEM", "FOREIGNKEY", "KEY_SEQ", SQL_SMALLINT, 5 },
6667 { "SYSTEM", "FOREIGNKEY", "UPDATE_RULE", SQL_SMALLINT, 5 },
6668 { "SYSTEM", "FOREIGNKEY", "DELETE_RULE", SQL_SMALLINT, 5 },
6669 { "SYSTEM", "FOREIGNKEY", "FK_NAME", SCOL_VARCHAR, 255 },
6670 { "SYSTEM", "FOREIGNKEY", "PK_NAME", SCOL_VARCHAR, 255 },
6671 { "SYSTEM", "FOREIGNKEY", "DEFERRABILITY", SQL_SMALLINT, 5 }
6672 };
6673
6674 static COL fkeySpec3[] = {
6675 { "SYSTEM", "FOREIGNKEY", "PKTABLE_CAT", SCOL_VARCHAR, 50 },
6676 { "SYSTEM", "FOREIGNKEY", "PKTABLE_SCHEM", SCOL_VARCHAR, 50 },
6677 { "SYSTEM", "FOREIGNKEY", "PKTABLE_NAME", SCOL_VARCHAR, 255 },
6678 { "SYSTEM", "FOREIGNKEY", "PKCOLUMN_NAME", SCOL_VARCHAR, 255 },
6679 { "SYSTEM", "FOREIGNKEY", "FKTABLE_CAT", SCOL_VARCHAR, 50 },
6680 { "SYSTEM", "FOREIGNKEY", "FKTABLE_SCHEM", SCOL_VARCHAR, 50 },
6681 { "SYSTEM", "FOREIGNKEY", "FKTABLE_NAME", SCOL_VARCHAR, 255 },
6682 { "SYSTEM", "FOREIGNKEY", "FKCOLUMN_NAME", SCOL_VARCHAR, 255 },
6683 { "SYSTEM", "FOREIGNKEY", "KEY_SEQ", SQL_SMALLINT, 5 },
6684 { "SYSTEM", "FOREIGNKEY", "UPDATE_RULE", SQL_SMALLINT, 5 },
6685 { "SYSTEM", "FOREIGNKEY", "DELETE_RULE", SQL_SMALLINT, 5 },
6686 { "SYSTEM", "FOREIGNKEY", "FK_NAME", SCOL_VARCHAR, 255 },
6687 { "SYSTEM", "FOREIGNKEY", "PK_NAME", SCOL_VARCHAR, 255 },
6688 { "SYSTEM", "FOREIGNKEY", "DEFERRABILITY", SQL_SMALLINT, 5 }
6689 };
6690
6691 /**
6692 * Internal retrieve information about primary/foreign keys.
6693 * @param stmt statement handle
6694 * @param PKcatalog primary key catalog name/pattern or NULL
6695 * @param PKcatalogLen length of PKcatalog or SQL_NTS
6696 * @param PKschema primary key schema name/pattern or NULL
6697 * @param PKschemaLen length of PKschema or SQL_NTS
6698 * @param PKtable primary key table name/pattern or NULL
6699 * @param PKtableLen length of PKtable or SQL_NTS
6700 * @param FKcatalog foreign key catalog name/pattern or NULL
6701 * @param FKcatalogLen length of FKcatalog or SQL_NTS
6702 * @param FKschema foreign key schema name/pattern or NULL
6703 * @param FKschemaLen length of FKschema or SQL_NTS
6704 * @param FKtable foreign key table name/pattern or NULL
6705 * @param FKtableLen length of FKtable or SQL_NTS
6706 * @result ODBC error code
6707 */
6708
6709 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)6710 drvforeignkeys(SQLHSTMT stmt,
6711 SQLCHAR *PKcatalog, SQLSMALLINT PKcatalogLen,
6712 SQLCHAR *PKschema, SQLSMALLINT PKschemaLen,
6713 SQLCHAR *PKtable, SQLSMALLINT PKtableLen,
6714 SQLCHAR *FKcatalog, SQLSMALLINT FKcatalogLen,
6715 SQLCHAR *FKschema, SQLSMALLINT FKschemaLen,
6716 SQLCHAR *FKtable, SQLSMALLINT FKtableLen)
6717 {
6718 STMT *s;
6719 DBC *d;
6720 SQLRETURN sret;
6721 int i, asize, ret, nrows, ncols, offs, namec, seqc, fromc, toc;
6722 int onu, ond;
6723 PTRDIFF_T size;
6724 char **rowp, *errp = NULL, *sql, pname[512], fname[512];
6725
6726 sret = mkresultset(stmt, fkeySpec2, array_size(fkeySpec2),
6727 fkeySpec3, array_size(fkeySpec3), &asize);
6728 if (sret != SQL_SUCCESS) {
6729 return sret;
6730 }
6731 s = (STMT *) stmt;
6732 sret = starttran(s);
6733 if (sret != SQL_SUCCESS) {
6734 return sret;
6735 }
6736 d = (DBC *) s->dbc;
6737 if ((!PKtable || PKtable[0] == '\0' || PKtable[0] == '%') &&
6738 (!FKtable || FKtable[0] == '\0' || FKtable[0] == '%')) {
6739 setstat(s, -1, "need table name", (*s->ov3) ? "HY000" : "S1000");
6740 return SQL_ERROR;
6741 }
6742 size = 0;
6743 if (PKtable) {
6744 if (PKtableLen == SQL_NTS) {
6745 size = sizeof (pname) - 1;
6746 } else {
6747 size = min(sizeof (pname) - 1, PKtableLen);
6748 }
6749 strncpy(pname, (char *) PKtable, size);
6750 }
6751 pname[size] = '\0';
6752 size = 0;
6753 if (FKtable) {
6754
6755 if (FKtableLen == SQL_NTS) {
6756 size = sizeof (fname) - 1;
6757 } else {
6758 size = min(sizeof (fname) - 1, FKtableLen);
6759 }
6760 strncpy(fname, (char *) FKtable, size);
6761 }
6762 fname[size] = '\0';
6763 if (fname[0] != '\0') {
6764 int plen;
6765
6766 ret = SQLITE_ERROR;
6767 sql = sqlite3_mprintf("PRAGMA foreign_key_list(%Q)", fname);
6768 if (sql) {
6769 dbtraceapi(d, "sqlite3_get_table", sql);
6770 ret = sqlite3_get_table(d->sqlite, sql, &rowp,
6771 &nrows, &ncols, &errp);
6772 sqlite3_free(sql);
6773 }
6774 if (ret != SQLITE_OK) {
6775 setstat(s, ret, "%s (%d)", (*s->ov3) ? "HY000" : "S1000",
6776 errp ? errp : "unknown error", ret);
6777 if (errp) {
6778 sqlite3_free(errp);
6779 errp = NULL;
6780 }
6781 return SQL_ERROR;
6782 }
6783 if (errp) {
6784 sqlite3_free(errp);
6785 errp = NULL;
6786 }
6787 if (ncols * nrows <= 0) {
6788 nodata:
6789 sqlite3_free_table(rowp);
6790 return SQL_SUCCESS;
6791 }
6792 size = 0;
6793 namec = findcol(rowp, ncols, "table");
6794 seqc = findcol(rowp, ncols, "seq");
6795 fromc = findcol(rowp, ncols, "from");
6796 toc = findcol(rowp, ncols, "to");
6797 onu = findcol(rowp, ncols, "on_update");
6798 ond = findcol(rowp, ncols, "on_delete");
6799 if (namec < 0 || seqc < 0 || fromc < 0 || toc < 0) {
6800 goto nodata;
6801 }
6802 plen = strlen(pname);
6803 for (i = 1; i <= nrows; i++) {
6804 char *ptab = unquote(rowp[i * ncols + namec]);
6805
6806 if (plen && ptab) {
6807 int len = strlen(ptab);
6808
6809 if (plen != len || strncasecmp(pname, ptab, plen) != 0) {
6810 continue;
6811 }
6812 }
6813 size++;
6814 }
6815 if (size == 0) {
6816 goto nodata;
6817 }
6818 s->nrows = size;
6819 size = (size + 1) * asize;
6820 s->rows = xmalloc((size + 1) * sizeof (char *));
6821 if (!s->rows) {
6822 s->nrows = 0;
6823 return nomem(s);
6824 }
6825 s->rows[0] = (char *) size;
6826 s->rows += 1;
6827 memset(s->rows, 0, sizeof (char *) * size);
6828 s->rowfree = freerows;
6829 offs = 0;
6830 for (i = 1; i <= nrows; i++) {
6831 int pos = 0, roffs = (offs + 1) * s->ncols;
6832 char *ptab = rowp[i * ncols + namec];
6833 char buf[32];
6834
6835 if (plen && ptab) {
6836 int len = strlen(ptab);
6837
6838 if (plen != len || strncasecmp(pname, ptab, plen) != 0) {
6839 continue;
6840 }
6841 }
6842 s->rows[roffs + 0] = xstrdup("");
6843 #if defined(_WIN32) || defined(_WIN64)
6844 s->rows[roffs + 1] = xstrdup(d->xcelqrx ? "main" : "");
6845 #else
6846 s->rows[roffs + 1] = xstrdup("");
6847 #endif
6848 s->rows[roffs + 2] = xstrdup(ptab);
6849 s->rows[roffs + 3] = xstrdup(rowp[i * ncols + toc]);
6850 s->rows[roffs + 4] = xstrdup("");
6851 s->rows[roffs + 5] = xstrdup("");
6852 s->rows[roffs + 6] = xstrdup(fname);
6853 s->rows[roffs + 7] = xstrdup(rowp[i * ncols + fromc]);
6854 sscanf(rowp[i * ncols + seqc], "%d", &pos);
6855 sprintf(buf, "%d", pos + 1);
6856 s->rows[roffs + 8] = xstrdup(buf);
6857 if (onu < 0) {
6858 s->rows[roffs + 9] = xstrdup(stringify(SQL_NO_ACTION));
6859 } else {
6860 if (strcmp(rowp[i * ncols + onu], "SET NULL") == 0) {
6861 s->rows[roffs + 9] = xstrdup(stringify(SQL_SET_NULL));
6862 } else if (strcmp(rowp[i * ncols + onu], "SET DEFAULT") == 0) {
6863 s->rows[roffs + 9] = xstrdup(stringify(SQL_SET_DEFAULT));
6864 } else if (strcmp(rowp[i * ncols + onu], "CASCADE") == 0) {
6865 s->rows[roffs + 9] = xstrdup(stringify(SQL_CASCADE));
6866 } else if (strcmp(rowp[i * ncols + onu], "RESTRICT") == 0) {
6867 s->rows[roffs + 9] = xstrdup(stringify(SQL_RESTRICT));
6868 } else {
6869 s->rows[roffs + 9] = xstrdup(stringify(SQL_NO_ACTION));
6870 }
6871 }
6872 if (ond < 0) {
6873 s->rows[roffs + 10] = xstrdup(stringify(SQL_NO_ACTION));
6874 } else {
6875 if (strcmp(rowp[i * ncols + ond], "SET NULL") == 0) {
6876 s->rows[roffs + 10] = xstrdup(stringify(SQL_SET_NULL));
6877 } else if (strcmp(rowp[i * ncols + ond], "SET DEFAULT") == 0) {
6878 s->rows[roffs + 10] = xstrdup(stringify(SQL_SET_DEFAULT));
6879 } else if (strcmp(rowp[i * ncols + ond], "CASCADE") == 0) {
6880 s->rows[roffs + 10] = xstrdup(stringify(SQL_CASCADE));
6881 } else if (strcmp(rowp[i * ncols + ond], "RESTRICT") == 0) {
6882 s->rows[roffs + 10] = xstrdup(stringify(SQL_RESTRICT));
6883 } else {
6884 s->rows[roffs + 10] = xstrdup(stringify(SQL_NO_ACTION));
6885 }
6886 }
6887 s->rows[roffs + 11] = NULL;
6888 s->rows[roffs + 12] = NULL;
6889 s->rows[roffs + 13] = xstrdup(stringify(SQL_NOT_DEFERRABLE));
6890 offs++;
6891 }
6892 sqlite3_free_table(rowp);
6893 } else {
6894 int nnrows, nncols, plen = strlen(pname);
6895 char **rowpp;
6896
6897 sql = "select name from sqlite_master where type='table'";
6898 dbtraceapi(d, "sqlite3_get_table", sql);
6899 ret = sqlite3_get_table(d->sqlite, sql, &rowp, &nrows, &ncols, &errp);
6900 if (ret != SQLITE_OK) {
6901 setstat(s, ret, "%s (%d)", (*s->ov3) ? "HY000" : "S1000",
6902 errp ? errp : "unknown error", ret);
6903 if (errp) {
6904 sqlite3_free(errp);
6905 errp = NULL;
6906 }
6907 return SQL_ERROR;
6908 }
6909 if (errp) {
6910 sqlite3_free(errp);
6911 errp = NULL;
6912 }
6913 if (ncols * nrows <= 0) {
6914 goto nodata;
6915 }
6916 size = 0;
6917 for (i = 1; i <= nrows; i++) {
6918 int k;
6919
6920 if (!rowp[i]) {
6921 continue;
6922 }
6923 rowpp = NULL;
6924 ret = SQLITE_ERROR;
6925 sql = sqlite3_mprintf("PRAGMA foreign_key_list(%Q)", rowp[i]);
6926 if (sql) {
6927 dbtraceapi(d, "sqlite3_get_table", sql);
6928 ret = sqlite3_get_table(d->sqlite, sql, &rowpp,
6929 &nnrows, &nncols, NULL);
6930 sqlite3_free(sql);
6931 }
6932 if (ret != SQLITE_OK || nncols * nnrows <= 0) {
6933 sqlite3_free_table(rowpp);
6934 continue;
6935 }
6936 namec = findcol(rowpp, nncols, "table");
6937 seqc = findcol(rowpp, nncols, "seq");
6938 fromc = findcol(rowpp, nncols, "from");
6939 toc = findcol(rowpp, nncols, "to");
6940 if (namec < 0 || seqc < 0 || fromc < 0 || toc < 0) {
6941 sqlite3_free_table(rowpp);
6942 continue;
6943 }
6944 for (k = 1; k <= nnrows; k++) {
6945 char *ptab = unquote(rowpp[k * nncols + namec]);
6946
6947 if (plen && ptab) {
6948 int len = strlen(ptab);
6949
6950 if (len != plen || strncasecmp(pname, ptab, plen) != 0) {
6951 continue;
6952 }
6953 }
6954 size++;
6955 }
6956 sqlite3_free_table(rowpp);
6957 }
6958 if (size == 0) {
6959 goto nodata;
6960 }
6961 s->nrows = size;
6962 size = (size + 1) * asize;
6963 s->rows = xmalloc((size + 1) * sizeof (char *));
6964 if (!s->rows) {
6965 s->nrows = 0;
6966 return nomem(s);
6967 }
6968 s->rows[0] = (char *) size;
6969 s->rows += 1;
6970 memset(s->rows, 0, sizeof (char *) * size);
6971 s->rowfree = freerows;
6972 offs = 0;
6973 for (i = 1; i <= nrows; i++) {
6974 int k;
6975
6976 if (!rowp[i]) {
6977 continue;
6978 }
6979 rowpp = NULL;
6980 ret = SQLITE_ERROR;
6981 sql = sqlite3_mprintf("PRAGMA foreign_key_list(%Q)", rowp[i]);
6982 if (sql) {
6983 dbtraceapi(d, "sqlite3_get_table", sql);
6984 ret = sqlite3_get_table(d->sqlite, sql, &rowpp,
6985 &nnrows, &nncols, NULL);
6986 sqlite3_free(sql);
6987 }
6988 if (ret != SQLITE_OK || nncols * nnrows <= 0) {
6989 sqlite3_free_table(rowpp);
6990 continue;
6991 }
6992 namec = findcol(rowpp, nncols, "table");
6993 seqc = findcol(rowpp, nncols, "seq");
6994 fromc = findcol(rowpp, nncols, "from");
6995 toc = findcol(rowpp, nncols, "to");
6996 onu = findcol(rowpp, nncols, "on_update");
6997 ond = findcol(rowpp, nncols, "on_delete");
6998 if (namec < 0 || seqc < 0 || fromc < 0 || toc < 0) {
6999 sqlite3_free_table(rowpp);
7000 continue;
7001 }
7002 for (k = 1; k <= nnrows; k++) {
7003 int pos = 0, roffs = (offs + 1) * s->ncols;
7004 char *ptab = unquote(rowpp[k * nncols + namec]);
7005 char buf[32];
7006
7007 if (plen && ptab) {
7008 int len = strlen(ptab);
7009
7010 if (len != plen || strncasecmp(pname, ptab, plen) != 0) {
7011 continue;
7012 }
7013 }
7014 s->rows[roffs + 0] = xstrdup("");
7015 #if defined(_WIN32) || defined(_WIN64)
7016 s->rows[roffs + 1] = xstrdup(d->xcelqrx ? "main" : "");
7017 #else
7018 s->rows[roffs + 1] = xstrdup("");
7019 #endif
7020 s->rows[roffs + 2] = xstrdup(ptab);
7021 s->rows[roffs + 3] = xstrdup(rowpp[k * nncols + toc]);
7022 s->rows[roffs + 4] = xstrdup("");
7023 s->rows[roffs + 5] = xstrdup("");
7024 s->rows[roffs + 6] = xstrdup(rowp[i]);
7025 s->rows[roffs + 7] = xstrdup(rowpp[k * nncols + fromc]);
7026 sscanf(rowpp[k * nncols + seqc], "%d", &pos);
7027 sprintf(buf, "%d", pos + 1);
7028 s->rows[roffs + 8] = xstrdup(buf);
7029 if (onu < 0) {
7030 s->rows[roffs + 9] = xstrdup(stringify(SQL_NO_ACTION));
7031 } else {
7032 if (strcmp(rowpp[k * nncols + onu], "SET NULL") == 0) {
7033 s->rows[roffs + 9] = xstrdup(stringify(SQL_SET_NULL));
7034 } else if (strcmp(rowpp[k * nncols + onu], "SET DEFAULT")
7035 == 0) {
7036 s->rows[roffs + 9] =
7037 xstrdup(stringify(SQL_SET_DEFAULT));
7038 } else if (strcmp(rowpp[k * nncols + onu], "CASCADE")
7039 == 0) {
7040 s->rows[roffs + 9] = xstrdup(stringify(SQL_CASCADE));
7041 } else if (strcmp(rowpp[k * nncols + onu], "RESTRICT")
7042 == 0) {
7043 s->rows[roffs + 9] = xstrdup(stringify(SQL_RESTRICT));
7044 } else {
7045 s->rows[roffs + 9] =
7046 xstrdup(stringify(SQL_NO_ACTION));
7047 }
7048 }
7049 if (ond < 0) {
7050 s->rows[roffs + 10] = xstrdup(stringify(SQL_NO_ACTION));
7051 } else {
7052 if (strcmp(rowpp[k * nncols + ond], "SET NULL") == 0) {
7053 s->rows[roffs + 10] = xstrdup(stringify(SQL_SET_NULL));
7054 } else if (strcmp(rowpp[k * nncols + ond], "SET DEFAULT")
7055 == 0) {
7056 s->rows[roffs + 10] =
7057 xstrdup(stringify(SQL_SET_DEFAULT));
7058 } else if (strcmp(rowpp[k * nncols + ond], "CASCADE")
7059 == 0) {
7060 s->rows[roffs + 10] = xstrdup(stringify(SQL_CASCADE));
7061 } else if (strcmp(rowpp[k * nncols + ond], "RESTRICT")
7062 == 0) {
7063 s->rows[roffs + 10] = xstrdup(stringify(SQL_RESTRICT));
7064 } else {
7065 s->rows[roffs + 10] =
7066 xstrdup(stringify(SQL_NO_ACTION));
7067 }
7068 }
7069 s->rows[roffs + 11] = NULL;
7070 s->rows[roffs + 12] = NULL;
7071 s->rows[roffs + 13] = xstrdup(stringify(SQL_NOT_DEFERRABLE));
7072 offs++;
7073 }
7074 sqlite3_free_table(rowpp);
7075 }
7076 sqlite3_free_table(rowp);
7077 }
7078 return SQL_SUCCESS;
7079 }
7080
7081 #ifndef WINTERFACE
7082 /**
7083 * Retrieve information about primary/foreign keys.
7084 * @param stmt statement handle
7085 * @param PKcatalog primary key catalog name/pattern or NULL
7086 * @param PKcatalogLen length of PKcatalog or SQL_NTS
7087 * @param PKschema primary key schema name/pattern or NULL
7088 * @param PKschemaLen length of PKschema or SQL_NTS
7089 * @param PKtable primary key table name/pattern or NULL
7090 * @param PKtableLen length of PKtable or SQL_NTS
7091 * @param FKcatalog foreign key catalog name/pattern or NULL
7092 * @param FKcatalogLen length of FKcatalog or SQL_NTS
7093 * @param FKschema foreign key schema name/pattern or NULL
7094 * @param FKschemaLen length of FKschema or SQL_NTS
7095 * @param FKtable foreign key table name/pattern or NULL
7096 * @param FKtableLen length of FKtable or SQL_NTS
7097 * @result ODBC error code
7098 */
7099
7100 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)7101 SQLForeignKeys(SQLHSTMT stmt,
7102 SQLCHAR *PKcatalog, SQLSMALLINT PKcatalogLen,
7103 SQLCHAR *PKschema, SQLSMALLINT PKschemaLen,
7104 SQLCHAR *PKtable, SQLSMALLINT PKtableLen,
7105 SQLCHAR *FKcatalog, SQLSMALLINT FKcatalogLen,
7106 SQLCHAR *FKschema, SQLSMALLINT FKschemaLen,
7107 SQLCHAR *FKtable, SQLSMALLINT FKtableLen)
7108 {
7109 #if defined(_WIN32) || defined(_WIN64)
7110 char *pc = NULL, *ps = NULL, *pt = NULL;
7111 char *fc = NULL, *fs = NULL, *ft = NULL;
7112 #endif
7113 SQLRETURN ret;
7114
7115 HSTMT_LOCK(stmt);
7116 #if defined(_WIN32) || defined(_WIN64)
7117 if (!((STMT *) stmt)->oemcp[0]) {
7118 ret = drvforeignkeys(stmt,
7119 PKcatalog, PKcatalogLen,
7120 PKschema, PKschemaLen, PKtable, PKtableLen,
7121 FKcatalog, FKcatalogLen,
7122 FKschema, FKschemaLen,
7123 FKtable, FKtableLen);
7124 goto done2;
7125 }
7126 if (PKcatalog) {
7127 pc = wmb_to_utf_c((char *) PKcatalog, PKcatalogLen);
7128 if (!pc) {
7129 ret = nomem((STMT *) stmt);
7130 goto done;
7131 }
7132 }
7133 if (PKschema) {
7134 ps = wmb_to_utf_c((char *) PKschema, PKschemaLen);
7135 if (!ps) {
7136 ret = nomem((STMT *) stmt);
7137 goto done;
7138 }
7139 }
7140 if (PKtable) {
7141 pt = wmb_to_utf_c((char *) PKtable, PKtableLen);
7142 if (!pt) {
7143 ret = nomem((STMT *) stmt);
7144 goto done;
7145 }
7146 }
7147 if (FKcatalog) {
7148 fc = wmb_to_utf_c((char *) FKcatalog, FKcatalogLen);
7149 if (!fc) {
7150 ret = nomem((STMT *) stmt);
7151 goto done;
7152 }
7153 }
7154 if (FKschema) {
7155 fs = wmb_to_utf_c((char *) FKschema, FKschemaLen);
7156 if (!fs) {
7157 ret = nomem((STMT *) stmt);
7158 goto done;
7159 }
7160 }
7161 if (FKtable) {
7162 ft = wmb_to_utf_c((char *) FKtable, FKtableLen);
7163 if (!ft) {
7164 ret = nomem((STMT *) stmt);
7165 goto done;
7166 }
7167 }
7168 ret = drvforeignkeys(stmt, (SQLCHAR *) pc, SQL_NTS,
7169 (SQLCHAR *) ps, SQL_NTS, (SQLCHAR *) pt, SQL_NTS,
7170 (SQLCHAR *) fc, SQL_NTS, (SQLCHAR *) fs, SQL_NTS,
7171 (SQLCHAR *) ft, SQL_NTS);
7172 #else
7173 ret = drvforeignkeys(stmt,
7174 PKcatalog, PKcatalogLen,
7175 PKschema, PKschemaLen, PKtable, PKtableLen,
7176 FKcatalog, FKcatalogLen,
7177 FKschema, FKschemaLen,
7178 FKtable, FKtableLen);
7179 #endif
7180 #if defined(_WIN32) || defined(_WIN64)
7181 done:
7182 uc_free(ft);
7183 uc_free(fs);
7184 uc_free(fc);
7185 uc_free(pt);
7186 uc_free(ps);
7187 uc_free(pc);
7188 done2:
7189 ;
7190 #endif
7191 HSTMT_UNLOCK(stmt);
7192 return ret;
7193 }
7194 #endif
7195
7196 #ifdef WINTERFACE
7197 /**
7198 * Retrieve information about primary/foreign keys (UNICODE version).
7199 * @param stmt statement handle
7200 * @param PKcatalog primary key catalog name/pattern or NULL
7201 * @param PKcatalogLen length of PKcatalog or SQL_NTS
7202 * @param PKschema primary key schema name/pattern or NULL
7203 * @param PKschemaLen length of PKschema or SQL_NTS
7204 * @param PKtable primary key table name/pattern or NULL
7205 * @param PKtableLen length of PKtable or SQL_NTS
7206 * @param FKcatalog foreign key catalog name/pattern or NULL
7207 * @param FKcatalogLen length of FKcatalog or SQL_NTS
7208 * @param FKschema foreign key schema name/pattern or NULL
7209 * @param FKschemaLen length of FKschema or SQL_NTS
7210 * @param FKtable foreign key table name/pattern or NULL
7211 * @param FKtableLen length of FKtable or SQL_NTS
7212 * @result ODBC error code
7213 */
7214
7215 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)7216 SQLForeignKeysW(SQLHSTMT stmt,
7217 SQLWCHAR *PKcatalog, SQLSMALLINT PKcatalogLen,
7218 SQLWCHAR *PKschema, SQLSMALLINT PKschemaLen,
7219 SQLWCHAR *PKtable, SQLSMALLINT PKtableLen,
7220 SQLWCHAR *FKcatalog, SQLSMALLINT FKcatalogLen,
7221 SQLWCHAR *FKschema, SQLSMALLINT FKschemaLen,
7222 SQLWCHAR *FKtable, SQLSMALLINT FKtableLen)
7223 {
7224 char *pc = NULL, *ps = NULL, *pt = NULL;
7225 char *fc = NULL, *fs = NULL, *ft = NULL;
7226 SQLRETURN ret;
7227
7228 HSTMT_LOCK(stmt);
7229 if (PKcatalog) {
7230 pc = uc_to_utf_c(PKcatalog, PKcatalogLen);
7231 if (!pc) {
7232 ret = nomem((STMT *) stmt);
7233 goto done;
7234 }
7235 }
7236 if (PKschema) {
7237 ps = uc_to_utf_c(PKschema, PKschemaLen);
7238 if (!ps) {
7239 ret = nomem((STMT *) stmt);
7240 goto done;
7241 }
7242 }
7243 if (PKtable) {
7244 pt = uc_to_utf_c(PKtable, PKtableLen);
7245 if (!pt) {
7246 ret = nomem((STMT *) stmt);
7247 goto done;
7248 }
7249 }
7250 if (FKcatalog) {
7251 fc = uc_to_utf_c(FKcatalog, FKcatalogLen);
7252 if (!fc) {
7253 ret = nomem((STMT *) stmt);
7254 goto done;
7255 }
7256 }
7257 if (FKschema) {
7258 fs = uc_to_utf_c(FKschema, FKschemaLen);
7259 if (!fs) {
7260 ret = nomem((STMT *) stmt);
7261 goto done;
7262 }
7263 }
7264 if (FKtable) {
7265 ft = uc_to_utf_c(FKtable, FKtableLen);
7266 if (!ft) {
7267 ret = nomem((STMT *) stmt);
7268 goto done;
7269 }
7270 }
7271 ret = drvforeignkeys(stmt, (SQLCHAR *) pc, SQL_NTS,
7272 (SQLCHAR *) ps, SQL_NTS, (SQLCHAR *) pt, SQL_NTS,
7273 (SQLCHAR *) fc, SQL_NTS, (SQLCHAR *) fs, SQL_NTS,
7274 (SQLCHAR *) ft, SQL_NTS);
7275 done:
7276 uc_free(ft);
7277 uc_free(fs);
7278 uc_free(fc);
7279 uc_free(pt);
7280 uc_free(ps);
7281 uc_free(pc);
7282 HSTMT_UNLOCK(stmt);
7283 return ret;
7284 }
7285 #endif
7286
7287 /**
7288 * Start transaction when autocommit off
7289 * @param s statement pointer
7290 * @result ODBC error code
7291 */
7292
7293 static SQLRETURN
starttran(STMT * s)7294 starttran(STMT *s)
7295 {
7296 int ret = SQL_SUCCESS, rc, busy_count = 0;
7297 char *errp = NULL;
7298 DBC *d = (DBC *) s->dbc;
7299
7300 if (!d->autocommit && !d->intrans && !d->trans_disable) {
7301 begin_again:
7302 rc = sqlite3_exec(d->sqlite, "BEGIN TRANSACTION", NULL, NULL, &errp);
7303 if (rc == SQLITE_BUSY) {
7304 if (busy_handler((void *) d, ++busy_count)) {
7305 if (errp) {
7306 sqlite3_free(errp);
7307 errp = NULL;
7308 }
7309 goto begin_again;
7310 }
7311 }
7312 dbtracerc(d, rc, errp);
7313 if (rc != SQLITE_OK) {
7314 setstat(s, rc, "%s (%d)", (*s->ov3) ? "HY000" : "S1000",
7315 errp ? errp : "unknown error", rc);
7316 ret = SQL_ERROR;
7317 } else {
7318 d->intrans = 1;
7319 }
7320 if (errp) {
7321 sqlite3_free(errp);
7322 errp = NULL;
7323 }
7324 }
7325 return ret;
7326 }
7327
7328 /**
7329 * Internal commit or rollback transaction.
7330 * @param d database connection pointer
7331 * @param comptype type of transaction's end, SQL_COMMIT or SQL_ROLLBACK
7332 * @param force force action regardless of DBC's autocommit state
7333 * @result ODBC error code
7334 */
7335
7336 static SQLRETURN
endtran(DBC * d,SQLSMALLINT comptype,int force)7337 endtran(DBC *d, SQLSMALLINT comptype, int force)
7338 {
7339 int ret, busy_count = 0;
7340 char *sql, *errp = NULL;
7341
7342 if (!d->sqlite) {
7343 setstatd(d, -1, "not connected", (*d->ov3) ? "HY000" : "S1000");
7344 return SQL_ERROR;
7345 }
7346 if ((!force && d->autocommit) || !d->intrans) {
7347 return SQL_SUCCESS;
7348 }
7349 switch (comptype) {
7350 case SQL_COMMIT:
7351 sql = "COMMIT TRANSACTION";
7352 goto doit;
7353 case SQL_ROLLBACK:
7354 sql = "ROLLBACK TRANSACTION";
7355 doit:
7356 ret = sqlite3_exec(d->sqlite, sql, NULL, NULL, &errp);
7357 dbtracerc(d, ret, errp);
7358 if (ret == SQLITE_BUSY && busy_count < 10) {
7359 if (busy_handler((void *) d, ++busy_count)) {
7360 if (errp) {
7361 sqlite3_free(errp);
7362 errp = NULL;
7363 }
7364 goto doit;
7365 }
7366 }
7367 d->intrans = 0;
7368 if (ret != SQLITE_OK) {
7369 setstatd(d, ret, "%s", (*d->ov3) ? "HY000" : "S1000",
7370 errp ? errp : "transaction failed");
7371 if (errp) {
7372 sqlite3_free(errp);
7373 errp = NULL;
7374 }
7375 return SQL_ERROR;
7376 }
7377 if (errp) {
7378 sqlite3_free(errp);
7379 errp = NULL;
7380 }
7381 return SQL_SUCCESS;
7382 }
7383 setstatd(d, -1, "invalid completion type", (*d->ov3) ? "HY000" : "S1000");
7384 return SQL_ERROR;
7385 }
7386
7387 /**
7388 * Internal commit or rollback transaction.
7389 * @param type type of handle
7390 * @param handle HDBC, HENV, or HSTMT handle
7391 * @param comptype SQL_COMMIT or SQL_ROLLBACK
7392 * @result ODBC error code
7393 */
7394
7395 static SQLRETURN
drvendtran(SQLSMALLINT type,SQLHANDLE handle,SQLSMALLINT comptype)7396 drvendtran(SQLSMALLINT type, SQLHANDLE handle, SQLSMALLINT comptype)
7397 {
7398 DBC *d;
7399 int fail = 0;
7400 SQLRETURN ret;
7401 #if defined(_WIN32) || defined(_WIN64)
7402 ENV *e;
7403 #endif
7404
7405 switch (type) {
7406 case SQL_HANDLE_DBC:
7407 HDBC_LOCK((SQLHDBC) handle);
7408 if (handle == SQL_NULL_HDBC) {
7409 return SQL_INVALID_HANDLE;
7410 }
7411 d = (DBC *) handle;
7412 ret = endtran(d, comptype, 0);
7413 HDBC_UNLOCK((SQLHDBC) handle);
7414 return ret;
7415 case SQL_HANDLE_ENV:
7416 if (handle == SQL_NULL_HENV) {
7417 return SQL_INVALID_HANDLE;
7418 }
7419 #if defined(_WIN32) || defined(_WIN64)
7420 e = (ENV *) handle;
7421 if (e->magic != ENV_MAGIC) {
7422 return SQL_INVALID_HANDLE;
7423 }
7424 EnterCriticalSection(&e->cs);
7425 e->owner = GetCurrentThreadId();
7426 #endif
7427 d = ((ENV *) handle)->dbcs;
7428 while (d) {
7429 ret = endtran(d, comptype, 0);
7430 if (ret != SQL_SUCCESS) {
7431 fail++;
7432 }
7433 d = d->next;
7434 }
7435 #if defined(_WIN32) || defined(_WIN64)
7436 e->owner = 0;
7437 LeaveCriticalSection(&e->cs);
7438 #endif
7439 return fail ? SQL_ERROR : SQL_SUCCESS;
7440 }
7441 return SQL_INVALID_HANDLE;
7442 }
7443
7444 /**
7445 * Commit or rollback transaction.
7446 * @param type type of handle
7447 * @param handle HDBC, HENV, or HSTMT handle
7448 * @param comptype SQL_COMMIT or SQL_ROLLBACK
7449 * @result ODBC error code
7450 */
7451
7452 SQLRETURN SQL_API
SQLEndTran(SQLSMALLINT type,SQLHANDLE handle,SQLSMALLINT comptype)7453 SQLEndTran(SQLSMALLINT type, SQLHANDLE handle, SQLSMALLINT comptype)
7454 {
7455 return drvendtran(type, handle, comptype);
7456 }
7457
7458 /**
7459 * Commit or rollback transaction.
7460 * @param env environment handle or NULL
7461 * @param dbc database connection handle or NULL
7462 * @param type SQL_COMMIT or SQL_ROLLBACK
7463 * @result ODBC error code
7464 */
7465
7466 SQLRETURN SQL_API
SQLTransact(SQLHENV env,SQLHDBC dbc,SQLUSMALLINT type)7467 SQLTransact(SQLHENV env, SQLHDBC dbc, SQLUSMALLINT type)
7468 {
7469 if (env != SQL_NULL_HENV) {
7470 return drvendtran(SQL_HANDLE_ENV, (SQLHANDLE) env, type);
7471 }
7472 return drvendtran(SQL_HANDLE_DBC, (SQLHANDLE) dbc, type);
7473 }
7474
7475 /**
7476 * Function not implemented.
7477 */
7478
7479 SQLRETURN SQL_API
SQLCopyDesc(SQLHDESC source,SQLHDESC target)7480 SQLCopyDesc(SQLHDESC source, SQLHDESC target)
7481 {
7482 return SQL_ERROR;
7483 }
7484
7485 #ifndef WINTERFACE
7486 /**
7487 * Translate SQL string.
7488 * @param stmt statement handle
7489 * @param sqlin input string
7490 * @param sqlinLen length of input string
7491 * @param sql output string
7492 * @param sqlMax max space in output string
7493 * @param sqlLen value return for length of output string
7494 * @result ODBC error code
7495 */
7496
7497 SQLRETURN SQL_API
SQLNativeSql(SQLHSTMT stmt,SQLCHAR * sqlin,SQLINTEGER sqlinLen,SQLCHAR * sql,SQLINTEGER sqlMax,SQLINTEGER * sqlLen)7498 SQLNativeSql(SQLHSTMT stmt, SQLCHAR *sqlin, SQLINTEGER sqlinLen,
7499 SQLCHAR *sql, SQLINTEGER sqlMax, SQLINTEGER *sqlLen)
7500 {
7501 int outLen = 0;
7502 SQLRETURN ret = SQL_SUCCESS;
7503
7504 HSTMT_LOCK(stmt);
7505 if (sqlinLen == SQL_NTS) {
7506 sqlinLen = strlen((char *) sqlin);
7507 }
7508 if (sql) {
7509 if (sqlMax > 0) {
7510 strncpy((char *) sql, (char *) sqlin, sqlMax - 1);
7511 sqlin[sqlMax - 1] = '\0';
7512 outLen = min(sqlMax - 1, sqlinLen);
7513 }
7514 } else {
7515 outLen = sqlinLen;
7516 }
7517 if (sqlLen) {
7518 *sqlLen = outLen;
7519 }
7520 if (sql && outLen < sqlinLen) {
7521 setstat((STMT *) stmt, -1, "data right truncated", "01004");
7522 ret = SQL_SUCCESS_WITH_INFO;
7523 }
7524 HSTMT_UNLOCK(stmt);
7525 return ret;
7526 }
7527 #endif
7528
7529 #ifdef WINTERFACE
7530 /**
7531 * Translate SQL string (UNICODE version).
7532 * @param stmt statement handle
7533 * @param sqlin input string
7534 * @param sqlinLen length of input string
7535 * @param sql output string
7536 * @param sqlMax max space in output string
7537 * @param sqlLen value return for length of output string
7538 * @result ODBC error code
7539 */
7540
7541 SQLRETURN SQL_API
SQLNativeSqlW(SQLHSTMT stmt,SQLWCHAR * sqlin,SQLINTEGER sqlinLen,SQLWCHAR * sql,SQLINTEGER sqlMax,SQLINTEGER * sqlLen)7542 SQLNativeSqlW(SQLHSTMT stmt, SQLWCHAR *sqlin, SQLINTEGER sqlinLen,
7543 SQLWCHAR *sql, SQLINTEGER sqlMax, SQLINTEGER *sqlLen)
7544 {
7545 int outLen = 0;
7546 SQLRETURN ret = SQL_SUCCESS;
7547
7548 HSTMT_LOCK(stmt);
7549 if (sqlinLen == SQL_NTS) {
7550 sqlinLen = uc_strlen(sqlin);
7551 }
7552 if (sql) {
7553 if (sqlMax > 0) {
7554 uc_strncpy(sql, sqlin, sqlMax - 1);
7555 sqlin[sqlMax - 1] = 0;
7556 outLen = min(sqlMax - 1, sqlinLen);
7557 }
7558 } else {
7559 outLen = sqlinLen;
7560 }
7561 if (sqlLen) {
7562 *sqlLen = outLen;
7563 }
7564 if (sql && outLen < sqlinLen) {
7565 setstat((STMT *) stmt, -1, "data right truncated", "01004");
7566 ret = SQL_SUCCESS_WITH_INFO;
7567 }
7568 HSTMT_UNLOCK(stmt);
7569 return ret;
7570 }
7571 #endif
7572
7573 /**
7574 * Columns for result set of SQLProcedures().
7575 */
7576
7577 static COL procSpec2[] = {
7578 { "SYSTEM", "PROCEDURE", "PROCEDURE_QUALIFIER", SCOL_VARCHAR, 50 },
7579 { "SYSTEM", "PROCEDURE", "PROCEDURE_OWNER", SCOL_VARCHAR, 50 },
7580 { "SYSTEM", "PROCEDURE", "PROCEDURE_NAME", SCOL_VARCHAR, 255 },
7581 { "SYSTEM", "PROCEDURE", "NUM_INPUT_PARAMS", SQL_SMALLINT, 5 },
7582 { "SYSTEM", "PROCEDURE", "NUM_OUTPUT_PARAMS", SQL_SMALLINT, 5 },
7583 { "SYSTEM", "PROCEDURE", "NUM_RESULT_SETS", SQL_SMALLINT, 5 },
7584 { "SYSTEM", "PROCEDURE", "REMARKS", SCOL_VARCHAR, 255 },
7585 { "SYSTEM", "PROCEDURE", "PROCEDURE_TYPE", SQL_SMALLINT, 5 }
7586 };
7587
7588 static COL procSpec3[] = {
7589 { "SYSTEM", "PROCEDURE", "PROCEDURE_CAT", SCOL_VARCHAR, 50 },
7590 { "SYSTEM", "PROCEDURE", "PROCEDURE_SCHEM", SCOL_VARCHAR, 50 },
7591 { "SYSTEM", "PROCEDURE", "PROCEDURE_NAME", SCOL_VARCHAR, 255 },
7592 { "SYSTEM", "PROCEDURE", "NUM_INPUT_PARAMS", SQL_SMALLINT, 5 },
7593 { "SYSTEM", "PROCEDURE", "NUM_OUTPUT_PARAMS", SQL_SMALLINT, 5 },
7594 { "SYSTEM", "PROCEDURE", "NUM_RESULT_SETS", SQL_SMALLINT, 5 },
7595 { "SYSTEM", "PROCEDURE", "REMARKS", SCOL_VARCHAR, 255 },
7596 { "SYSTEM", "PROCEDURE", "PROCEDURE_TYPE", SQL_SMALLINT, 5 }
7597 };
7598
7599 #ifndef WINTERFACE
7600 /**
7601 * Retrieve information about stored procedures.
7602 * @param stmt statement handle
7603 * @param catalog catalog name/pattern or NULL
7604 * @param catalogLen length of catalog or SQL_NTS
7605 * @param schema schema name/pattern or NULL
7606 * @param schemaLen length of schema or SQL_NTS
7607 * @param proc procedure name/pattern or NULL
7608 * @param procLen length of proc or SQL_NTS
7609 * @result ODBC error code
7610 */
7611
7612 SQLRETURN SQL_API
SQLProcedures(SQLHSTMT stmt,SQLCHAR * catalog,SQLSMALLINT catalogLen,SQLCHAR * schema,SQLSMALLINT schemaLen,SQLCHAR * proc,SQLSMALLINT procLen)7613 SQLProcedures(SQLHSTMT stmt,
7614 SQLCHAR *catalog, SQLSMALLINT catalogLen,
7615 SQLCHAR *schema, SQLSMALLINT schemaLen,
7616 SQLCHAR *proc, SQLSMALLINT procLen)
7617 {
7618 SQLRETURN ret;
7619
7620 HSTMT_LOCK(stmt);
7621 ret = mkresultset(stmt, procSpec2, array_size(procSpec2),
7622 procSpec3, array_size(procSpec3), NULL);
7623 HSTMT_UNLOCK(stmt);
7624 return ret;
7625 }
7626 #endif
7627
7628 #ifdef WINTERFACE
7629 /**
7630 * Retrieve information about stored procedures (UNICODE version).
7631 * @param stmt statement handle
7632 * @param catalog catalog name/pattern or NULL
7633 * @param catalogLen length of catalog or SQL_NTS
7634 * @param schema schema name/pattern or NULL
7635 * @param schemaLen length of schema or SQL_NTS
7636 * @param proc procedure name/pattern or NULL
7637 * @param procLen length of proc or SQL_NTS
7638 * @result ODBC error code
7639 */
7640
7641 SQLRETURN SQL_API
SQLProceduresW(SQLHSTMT stmt,SQLWCHAR * catalog,SQLSMALLINT catalogLen,SQLWCHAR * schema,SQLSMALLINT schemaLen,SQLWCHAR * proc,SQLSMALLINT procLen)7642 SQLProceduresW(SQLHSTMT stmt,
7643 SQLWCHAR *catalog, SQLSMALLINT catalogLen,
7644 SQLWCHAR *schema, SQLSMALLINT schemaLen,
7645 SQLWCHAR *proc, SQLSMALLINT procLen)
7646 {
7647 SQLRETURN ret;
7648
7649 HSTMT_LOCK(stmt);
7650 ret = mkresultset(stmt, procSpec2, array_size(procSpec2),
7651 procSpec3, array_size(procSpec3), NULL);
7652 HSTMT_UNLOCK(stmt);
7653 return ret;
7654 }
7655 #endif
7656
7657 /**
7658 * Columns for result set of SQLProcedureColumns().
7659 */
7660
7661 static COL procColSpec2[] = {
7662 { "SYSTEM", "PROCCOL", "PROCEDURE_QUALIFIER", SCOL_VARCHAR, 50 },
7663 { "SYSTEM", "PROCCOL", "PROCEDURE_OWNER", SCOL_VARCHAR, 50 },
7664 { "SYSTEM", "PROCCOL", "PROCEDURE_NAME", SCOL_VARCHAR, 255 },
7665 { "SYSTEM", "PROCCOL", "COLUMN_NAME", SCOL_VARCHAR, 255 },
7666 { "SYSTEM", "PROCCOL", "COLUMN_TYPE", SQL_SMALLINT, 5 },
7667 { "SYSTEM", "PROCCOL", "DATA_TYPE", SQL_SMALLINT, 5 },
7668 { "SYSTEM", "PROCCOL", "TYPE_NAME", SCOL_VARCHAR, 50 },
7669 { "SYSTEM", "PROCCOL", "PRECISION", SQL_INTEGER, 10 },
7670 { "SYSTEM", "PROCCOL", "LENGTH", SQL_INTEGER, 10 },
7671 { "SYSTEM", "PROCCOL", "SCALE", SQL_SMALLINT, 5 },
7672 { "SYSTEM", "PROCCOL", "RADIX", SQL_SMALLINT, 5 },
7673 { "SYSTEM", "PROCCOL", "NULLABLE", SQL_SMALLINT, 5 },
7674 { "SYSTEM", "PROCCOL", "REMARKS", SCOL_VARCHAR, 50 },
7675 { "SYSTEM", "PROCCOL", "COLUMN_DEF", SCOL_VARCHAR, 50 },
7676 { "SYSTEM", "PROCCOL", "SQL_DATA_TYPE", SQL_SMALLINT, 5 },
7677 { "SYSTEM", "PROCCOL", "SQL_DATETIME_SUB", SQL_SMALLINT, 5 },
7678 { "SYSTEM", "PROCCOL", "CHAR_OCTET_LENGTH", SQL_SMALLINT, 5 },
7679 { "SYSTEM", "PROCCOL", "ORDINAL_POSITION", SQL_SMALLINT, 5 },
7680 { "SYSTEM", "PROCCOL", "IS_NULLABLE", SCOL_VARCHAR, 50 }
7681 };
7682
7683 static COL procColSpec3[] = {
7684 { "SYSTEM", "PROCCOL", "PROCEDURE_CAT", SCOL_VARCHAR, 50 },
7685 { "SYSTEM", "PROCCOL", "PROCEDURE_SCHEM", SCOL_VARCHAR, 50 },
7686 { "SYSTEM", "PROCCOL", "PROCEDURE_NAME", SCOL_VARCHAR, 255 },
7687 { "SYSTEM", "PROCCOL", "COLUMN_NAME", SCOL_VARCHAR, 255 },
7688 { "SYSTEM", "PROCCOL", "COLUMN_TYPE", SQL_SMALLINT, 5 },
7689 { "SYSTEM", "PROCCOL", "DATA_TYPE", SQL_SMALLINT, 5 },
7690 { "SYSTEM", "PROCCOL", "TYPE_NAME", SCOL_VARCHAR, 50 },
7691 { "SYSTEM", "PROCCOL", "COLUMN_SIZE", SQL_INTEGER, 10 },
7692 { "SYSTEM", "PROCCOL", "BUFFER_LENGTH", SQL_INTEGER, 10 },
7693 { "SYSTEM", "PROCCOL", "DECIMAL_DIGITS", SQL_SMALLINT, 5 },
7694 { "SYSTEM", "PROCCOL", "NUM_PREC_RADIX", SQL_SMALLINT, 5 },
7695 { "SYSTEM", "PROCCOL", "NULLABLE", SQL_SMALLINT, 5 },
7696 { "SYSTEM", "PROCCOL", "REMARKS", SCOL_VARCHAR, 50 },
7697 { "SYSTEM", "PROCCOL", "COLUMN_DEF", SCOL_VARCHAR, 50 },
7698 { "SYSTEM", "PROCCOL", "SQL_DATA_TYPE", SQL_SMALLINT, 5 },
7699 { "SYSTEM", "PROCCOL", "SQL_DATETIME_SUB", SQL_SMALLINT, 5 },
7700 { "SYSTEM", "PROCCOL", "CHAR_OCTET_LENGTH", SQL_SMALLINT, 5 },
7701 { "SYSTEM", "PROCCOL", "ORDINAL_POSITION", SQL_SMALLINT, 5 },
7702 { "SYSTEM", "PROCCOL", "IS_NULLABLE", SCOL_VARCHAR, 50 }
7703 };
7704
7705 #ifndef WINTERFACE
7706 /**
7707 * Retrieve information about columns in result set of stored procedures.
7708 * @param stmt statement handle
7709 * @param catalog catalog name/pattern or NULL
7710 * @param catalogLen length of catalog or SQL_NTS
7711 * @param schema schema name/pattern or NULL
7712 * @param schemaLen length of schema or SQL_NTS
7713 * @param proc procedure name/pattern or NULL
7714 * @param procLen length of proc or SQL_NTS
7715 * @param column column name/pattern or NULL
7716 * @param columnLen length of column or SQL_NTS
7717 * @result ODBC error code
7718 */
7719
7720 SQLRETURN SQL_API
SQLProcedureColumns(SQLHSTMT stmt,SQLCHAR * catalog,SQLSMALLINT catalogLen,SQLCHAR * schema,SQLSMALLINT schemaLen,SQLCHAR * proc,SQLSMALLINT procLen,SQLCHAR * column,SQLSMALLINT columnLen)7721 SQLProcedureColumns(SQLHSTMT stmt,
7722 SQLCHAR *catalog, SQLSMALLINT catalogLen,
7723 SQLCHAR *schema, SQLSMALLINT schemaLen,
7724 SQLCHAR *proc, SQLSMALLINT procLen,
7725 SQLCHAR *column, SQLSMALLINT columnLen)
7726 {
7727 SQLRETURN ret;
7728
7729 HSTMT_LOCK(stmt);
7730 ret = mkresultset(stmt, procColSpec2, array_size(procColSpec2),
7731 procColSpec3, array_size(procColSpec3), NULL);
7732 HSTMT_UNLOCK(stmt);
7733 return ret;
7734 }
7735 #endif
7736
7737 #ifdef WINTERFACE
7738 /**
7739 * Retrieve information about columns in result
7740 * set of stored procedures (UNICODE version).
7741 * @param stmt statement handle
7742 * @param catalog catalog name/pattern or NULL
7743 * @param catalogLen length of catalog or SQL_NTS
7744 * @param schema schema name/pattern or NULL
7745 * @param schemaLen length of schema or SQL_NTS
7746 * @param proc procedure name/pattern or NULL
7747 * @param procLen length of proc or SQL_NTS
7748 * @param column column name/pattern or NULL
7749 * @param columnLen length of column or SQL_NTS
7750 * @result ODBC error code
7751 */
7752
7753 SQLRETURN SQL_API
SQLProcedureColumnsW(SQLHSTMT stmt,SQLWCHAR * catalog,SQLSMALLINT catalogLen,SQLWCHAR * schema,SQLSMALLINT schemaLen,SQLWCHAR * proc,SQLSMALLINT procLen,SQLWCHAR * column,SQLSMALLINT columnLen)7754 SQLProcedureColumnsW(SQLHSTMT stmt,
7755 SQLWCHAR *catalog, SQLSMALLINT catalogLen,
7756 SQLWCHAR *schema, SQLSMALLINT schemaLen,
7757 SQLWCHAR *proc, SQLSMALLINT procLen,
7758 SQLWCHAR *column, SQLSMALLINT columnLen)
7759 {
7760 SQLRETURN ret;
7761
7762 HSTMT_LOCK(stmt);
7763 ret = mkresultset(stmt, procColSpec2, array_size(procColSpec2),
7764 procColSpec3, array_size(procColSpec3), NULL);
7765 HSTMT_UNLOCK(stmt);
7766 return ret;
7767 }
7768 #endif
7769
7770 /**
7771 * Get information of HENV.
7772 * @param env environment handle
7773 * @param attr attribute to be retrieved
7774 * @param val output buffer
7775 * @param len length of output buffer
7776 * @param lenp output length
7777 * @result ODBC error code
7778 */
7779
7780 SQLRETURN SQL_API
SQLGetEnvAttr(SQLHENV env,SQLINTEGER attr,SQLPOINTER val,SQLINTEGER len,SQLINTEGER * lenp)7781 SQLGetEnvAttr(SQLHENV env, SQLINTEGER attr, SQLPOINTER val,
7782 SQLINTEGER len, SQLINTEGER *lenp)
7783 {
7784 ENV *e;
7785 SQLRETURN ret = SQL_ERROR;
7786
7787 if (env == SQL_NULL_HENV) {
7788 return SQL_INVALID_HANDLE;
7789 }
7790 e = (ENV *) env;
7791 if (!e || e->magic != ENV_MAGIC) {
7792 return SQL_INVALID_HANDLE;
7793 }
7794 #if defined(_WIN32) || defined(_WIN64)
7795 EnterCriticalSection(&e->cs);
7796 e->owner = GetCurrentThreadId();
7797 #endif
7798 switch (attr) {
7799 case SQL_ATTR_CONNECTION_POOLING:
7800 ret = SQL_ERROR;
7801 break;
7802 case SQL_ATTR_CP_MATCH:
7803 ret = SQL_NO_DATA;
7804 break;
7805 case SQL_ATTR_OUTPUT_NTS:
7806 if (val) {
7807 *((SQLINTEGER *) val) = SQL_TRUE;
7808 }
7809 if (lenp) {
7810 *lenp = sizeof (SQLINTEGER);
7811 }
7812 ret = SQL_SUCCESS;
7813 break;
7814 case SQL_ATTR_ODBC_VERSION:
7815 if (val) {
7816 *((SQLINTEGER *) val) = e->ov3 ? SQL_OV_ODBC3 : SQL_OV_ODBC2;
7817 }
7818 if (lenp) {
7819 *lenp = sizeof (SQLINTEGER);
7820 }
7821 ret = SQL_SUCCESS;
7822 break;
7823 }
7824 #if defined(_WIN32) || defined(_WIN64)
7825 e->owner = 0;
7826 LeaveCriticalSection(&e->cs);
7827 #endif
7828 return ret;
7829 }
7830
7831 /**
7832 * Set information in HENV.
7833 * @param env environment handle
7834 * @param attr attribute to be retrieved
7835 * @param val parameter buffer
7836 * @param len length of parameter
7837 * @result ODBC error code
7838 */
7839
7840 SQLRETURN SQL_API
SQLSetEnvAttr(SQLHENV env,SQLINTEGER attr,SQLPOINTER val,SQLINTEGER len)7841 SQLSetEnvAttr(SQLHENV env, SQLINTEGER attr, SQLPOINTER val, SQLINTEGER len)
7842 {
7843 ENV *e;
7844 SQLRETURN ret = SQL_ERROR;
7845
7846 if (env == SQL_NULL_HENV) {
7847 return SQL_INVALID_HANDLE;
7848 }
7849 e = (ENV *) env;
7850 if (!e || e->magic != ENV_MAGIC) {
7851 return SQL_INVALID_HANDLE;
7852 }
7853 #if defined(_WIN32) || defined(_WIN64)
7854 EnterCriticalSection(&e->cs);
7855 e->owner = GetCurrentThreadId();
7856 #endif
7857 switch (attr) {
7858 case SQL_ATTR_CONNECTION_POOLING:
7859 ret = SQL_SUCCESS;
7860 break;
7861 case SQL_ATTR_CP_MATCH:
7862 ret = SQL_NO_DATA;
7863 break;
7864 case SQL_ATTR_OUTPUT_NTS:
7865 if (val == (SQLPOINTER) SQL_TRUE) {
7866 ret = SQL_SUCCESS;
7867 }
7868 break;
7869 case SQL_ATTR_ODBC_VERSION:
7870 if (!val) {
7871 break;
7872 }
7873 if (val == (SQLPOINTER) SQL_OV_ODBC2) {
7874 e->ov3 = 0;
7875 ret = SQL_SUCCESS;
7876 }
7877 if (val == (SQLPOINTER) SQL_OV_ODBC3) {
7878 e->ov3 = 1;
7879 ret = SQL_SUCCESS;
7880 }
7881 break;
7882 }
7883 #if defined(_WIN32) || defined(_WIN64)
7884 e->owner = 0;
7885 LeaveCriticalSection(&e->cs);
7886 #endif
7887 return ret;
7888 }
7889
7890 /**
7891 * Internal get error message given handle (HENV, HDBC, or HSTMT).
7892 * @param htype handle type
7893 * @param handle HENV, HDBC, or HSTMT
7894 * @param recno
7895 * @param sqlstate output buffer for SQL state
7896 * @param nativeerr output buffer of native error code
7897 * @param msg output buffer for error message
7898 * @param buflen length of output buffer
7899 * @param msglen output length
7900 * @result ODBC error code
7901 */
7902
7903 static SQLRETURN
drvgetdiagrec(SQLSMALLINT htype,SQLHANDLE handle,SQLSMALLINT recno,SQLCHAR * sqlstate,SQLINTEGER * nativeerr,SQLCHAR * msg,SQLSMALLINT buflen,SQLSMALLINT * msglen)7904 drvgetdiagrec(SQLSMALLINT htype, SQLHANDLE handle, SQLSMALLINT recno,
7905 SQLCHAR *sqlstate, SQLINTEGER *nativeerr, SQLCHAR *msg,
7906 SQLSMALLINT buflen, SQLSMALLINT *msglen)
7907 {
7908 DBC *d = NULL;
7909 STMT *s = NULL;
7910 int len, naterr;
7911 char *logmsg, *sqlst;
7912 SQLRETURN ret = SQL_ERROR;
7913
7914 if (handle == SQL_NULL_HANDLE) {
7915 return SQL_INVALID_HANDLE;
7916 }
7917 if (sqlstate) {
7918 sqlstate[0] = '\0';
7919 }
7920 if (msg && buflen > 0) {
7921 msg[0] = '\0';
7922 }
7923 if (msglen) {
7924 *msglen = 0;
7925 }
7926 if (nativeerr) {
7927 *nativeerr = 0;
7928 }
7929 switch (htype) {
7930 case SQL_HANDLE_ENV:
7931 case SQL_HANDLE_DESC:
7932 return SQL_NO_DATA;
7933 case SQL_HANDLE_DBC:
7934 HDBC_LOCK((SQLHDBC) handle);
7935 d = (DBC *) handle;
7936 logmsg = (char *) d->logmsg;
7937 sqlst = d->sqlstate;
7938 naterr = d->naterr;
7939 break;
7940 case SQL_HANDLE_STMT:
7941 HSTMT_LOCK((SQLHSTMT) handle);
7942 s = (STMT *) handle;
7943 logmsg = (char *) s->logmsg;
7944 sqlst = s->sqlstate;
7945 naterr = s->naterr;
7946 break;
7947 default:
7948 return SQL_INVALID_HANDLE;
7949 }
7950 if (buflen < 0) {
7951 goto done;
7952 }
7953 if (recno > 1) {
7954 ret = SQL_NO_DATA;
7955 goto done;
7956 }
7957 len = strlen(logmsg);
7958 if (len == 0) {
7959 ret = SQL_NO_DATA;
7960 goto done;
7961 }
7962 if (nativeerr) {
7963 *nativeerr = naterr;
7964 }
7965 if (sqlstate) {
7966 strcpy((char *) sqlstate, sqlst);
7967 }
7968 if (msglen) {
7969 *msglen = len;
7970 }
7971 if (len >= buflen) {
7972 if (msg && buflen > 0) {
7973 strncpy((char *) msg, logmsg, buflen);
7974 msg[buflen - 1] = '\0';
7975 logmsg[0] = '\0';
7976 }
7977 } else if (msg) {
7978 strcpy((char *) msg, logmsg);
7979 logmsg[0] = '\0';
7980 }
7981 ret = SQL_SUCCESS;
7982 done:
7983 switch (htype) {
7984 case SQL_HANDLE_DBC:
7985 HDBC_UNLOCK((SQLHDBC) handle);
7986 break;
7987 case SQL_HANDLE_STMT:
7988 HSTMT_UNLOCK((SQLHSTMT) handle);
7989 break;
7990 }
7991 return ret;
7992 }
7993
7994 #if !defined(WINTERFACE) || (defined(HAVE_UNIXODBC) && (HAVE_UNIXODBC))
7995 /**
7996 * Get error message given handle (HENV, HDBC, or HSTMT).
7997 * @param htype handle type
7998 * @param handle HENV, HDBC, or HSTMT
7999 * @param recno
8000 * @param sqlstate output buffer for SQL state
8001 * @param nativeerr output buffer of native error code
8002 * @param msg output buffer for error message
8003 * @param buflen length of output buffer
8004 * @param msglen output length
8005 * @result ODBC error code
8006 */
8007
8008 SQLRETURN SQL_API
SQLGetDiagRec(SQLSMALLINT htype,SQLHANDLE handle,SQLSMALLINT recno,SQLCHAR * sqlstate,SQLINTEGER * nativeerr,SQLCHAR * msg,SQLSMALLINT buflen,SQLSMALLINT * msglen)8009 SQLGetDiagRec(SQLSMALLINT htype, SQLHANDLE handle, SQLSMALLINT recno,
8010 SQLCHAR *sqlstate, SQLINTEGER *nativeerr, SQLCHAR *msg,
8011 SQLSMALLINT buflen, SQLSMALLINT *msglen)
8012 {
8013 return drvgetdiagrec(htype, handle, recno, sqlstate,
8014 nativeerr, msg, buflen, msglen);
8015 }
8016 #endif
8017
8018 #if !defined(HAVE_UNIXODBC) || !(HAVE_UNIXODBC)
8019 #ifdef WINTERFACE
8020 /**
8021 * Get error message given handle (HENV, HDBC, or HSTMT)
8022 * (UNICODE version).
8023 * @param htype handle type
8024 * @param handle HENV, HDBC, or HSTMT
8025 * @param recno
8026 * @param sqlstate output buffer for SQL state
8027 * @param nativeerr output buffer of native error code
8028 * @param msg output buffer for error message
8029 * @param buflen length of output buffer
8030 * @param msglen output length
8031 * @result ODBC error code
8032 */
8033
8034 SQLRETURN SQL_API
SQLGetDiagRecW(SQLSMALLINT htype,SQLHANDLE handle,SQLSMALLINT recno,SQLWCHAR * sqlstate,SQLINTEGER * nativeerr,SQLWCHAR * msg,SQLSMALLINT buflen,SQLSMALLINT * msglen)8035 SQLGetDiagRecW(SQLSMALLINT htype, SQLHANDLE handle, SQLSMALLINT recno,
8036 SQLWCHAR *sqlstate, SQLINTEGER *nativeerr, SQLWCHAR *msg,
8037 SQLSMALLINT buflen, SQLSMALLINT *msglen)
8038 {
8039 char state[16];
8040 SQLSMALLINT len;
8041 SQLRETURN ret;
8042
8043 ret = drvgetdiagrec(htype, handle, recno, (SQLCHAR *) state,
8044 nativeerr, (SQLCHAR *) msg, buflen, &len);
8045 if (ret == SQL_SUCCESS) {
8046 if (sqlstate) {
8047 uc_from_utf_buf((SQLCHAR *) state, -1, sqlstate,
8048 6 * sizeof (SQLWCHAR));
8049 }
8050 if (msg) {
8051 if (len > 0) {
8052 SQLWCHAR *m = NULL;
8053
8054 m = uc_from_utf((unsigned char *) msg, len);
8055 if (m) {
8056 if (buflen) {
8057 buflen /= sizeof (SQLWCHAR);
8058 uc_strncpy(msg, m, buflen);
8059 m[len] = 0;
8060 len = min(buflen, uc_strlen(m));
8061 } else {
8062 len = uc_strlen(m);
8063 }
8064 uc_free(m);
8065 } else {
8066 len = 0;
8067 }
8068 }
8069 if (len <= 0) {
8070 len = 0;
8071 if (buflen > 0) {
8072 msg[0] = 0;
8073 }
8074 }
8075 } else {
8076 /* estimated length !!! */
8077 len *= sizeof (SQLWCHAR);
8078 }
8079 if (msglen) {
8080 *msglen = len;
8081 }
8082 } else if (ret == SQL_NO_DATA) {
8083 if (sqlstate) {
8084 sqlstate[0] = 0;
8085 }
8086 if (msg) {
8087 if (buflen > 0) {
8088 msg[0] = 0;
8089 }
8090 }
8091 if (msglen) {
8092 *msglen = 0;
8093 }
8094 }
8095 return ret;
8096 }
8097 #endif
8098 #endif
8099
8100 /**
8101 * Get error record given handle (HDBC or HSTMT).
8102 * @param htype handle type
8103 * @param handle HDBC or HSTMT
8104 * @param recno diag record number for which info to be retrieved
8105 * @param id diag id for which info to be retrieved
8106 * @param info output buffer for error message
8107 * @param buflen length of output buffer
8108 * @param stringlen output length
8109 * @result ODBC error code
8110 */
8111
8112 static SQLRETURN
drvgetdiagfield(SQLSMALLINT htype,SQLHANDLE handle,SQLSMALLINT recno,SQLSMALLINT id,SQLPOINTER info,SQLSMALLINT buflen,SQLSMALLINT * stringlen)8113 drvgetdiagfield(SQLSMALLINT htype, SQLHANDLE handle, SQLSMALLINT recno,
8114 SQLSMALLINT id, SQLPOINTER info,
8115 SQLSMALLINT buflen, SQLSMALLINT *stringlen)
8116 {
8117 DBC *d = NULL;
8118 STMT *s = NULL;
8119 int len, naterr;
8120 char *logmsg, *sqlst, *clrmsg = NULL;
8121 SQLRETURN ret = SQL_ERROR;
8122
8123 if (handle == SQL_NULL_HANDLE) {
8124 return SQL_INVALID_HANDLE;
8125 }
8126 if (stringlen) {
8127 *stringlen = 0;
8128 }
8129 switch (htype) {
8130 case SQL_HANDLE_ENV:
8131 case SQL_HANDLE_DESC:
8132 return SQL_NO_DATA;
8133 case SQL_HANDLE_DBC:
8134 HDBC_LOCK((SQLHDBC) handle);
8135 d = (DBC *) handle;
8136 logmsg = (char *) d->logmsg;
8137 sqlst = d->sqlstate;
8138 naterr = d->naterr;
8139 break;
8140 case SQL_HANDLE_STMT:
8141 HSTMT_LOCK((SQLHSTMT) handle);
8142 s = (STMT *) handle;
8143 d = (DBC *) s->dbc;
8144 logmsg = (char *) s->logmsg;
8145 sqlst = s->sqlstate;
8146 naterr = s->naterr;
8147 break;
8148 default:
8149 return SQL_INVALID_HANDLE;
8150 }
8151 if (buflen < 0) {
8152 goto done;
8153 }
8154 if (recno > 1) {
8155 ret = SQL_NO_DATA;
8156 goto done;
8157 }
8158 switch (id) {
8159 case SQL_DIAG_CLASS_ORIGIN:
8160 logmsg = "ISO 9075";
8161 if (sqlst[0] == 'I' && sqlst[1] == 'M') {
8162 logmsg = "ODBC 3.0";
8163 }
8164 break;
8165 case SQL_DIAG_SUBCLASS_ORIGIN:
8166 logmsg = "ISO 9075";
8167 if (sqlst[0] == 'I' && sqlst[1] == 'M') {
8168 logmsg = "ODBC 3.0";
8169 } else if (sqlst[0] == 'H' && sqlst[1] == 'Y') {
8170 logmsg = "ODBC 3.0";
8171 } else if (sqlst[0] == '2' || sqlst[0] == '0' || sqlst[0] == '4') {
8172 logmsg = "ODBC 3.0";
8173 }
8174 break;
8175 case SQL_DIAG_CONNECTION_NAME:
8176 case SQL_DIAG_SERVER_NAME:
8177 logmsg = d->dsn ? d->dsn : "No DSN";
8178 break;
8179 case SQL_DIAG_SQLSTATE:
8180 logmsg = sqlst;
8181 break;
8182 case SQL_DIAG_MESSAGE_TEXT:
8183 clrmsg = logmsg;
8184 break;
8185 case SQL_DIAG_NUMBER:
8186 naterr = 1;
8187 /* fall through */
8188 case SQL_DIAG_NATIVE:
8189 len = strlen(logmsg);
8190 if (len == 0) {
8191 ret = SQL_NO_DATA;
8192 goto done;
8193 }
8194 if (info) {
8195 *((SQLINTEGER *) info) = naterr;
8196 }
8197 ret = SQL_SUCCESS;
8198 goto done;
8199 default:
8200 goto done;
8201 }
8202 if (info && buflen > 0) {
8203 ((char *) info)[0] = '\0';
8204 }
8205 len = strlen(logmsg);
8206 if (len == 0) {
8207 ret = SQL_NO_DATA;
8208 goto done;
8209 }
8210 if (stringlen) {
8211 *stringlen = len;
8212 }
8213 if (len >= buflen) {
8214 if (info && buflen > 0) {
8215 if (stringlen) {
8216 *stringlen = buflen - 1;
8217 }
8218 strncpy((char *) info, logmsg, buflen);
8219 ((char *) info)[buflen - 1] = '\0';
8220 }
8221 } else if (info) {
8222 strcpy((char *) info, logmsg);
8223 }
8224 if (clrmsg) {
8225 *clrmsg = '\0';
8226 }
8227 ret = SQL_SUCCESS;
8228 done:
8229 switch (htype) {
8230 case SQL_HANDLE_DBC:
8231 HDBC_UNLOCK((SQLHDBC) handle);
8232 break;
8233 case SQL_HANDLE_STMT:
8234 HSTMT_UNLOCK((SQLHSTMT) handle);
8235 break;
8236 }
8237 return ret;
8238 }
8239
8240 #ifndef WINTERFACE
8241 /**
8242 * Get error record given handle (HDBC or HSTMT).
8243 * @param htype handle type
8244 * @param handle HDBC or HSTMT
8245 * @param recno diag record number for which info to be retrieved
8246 * @param id diag id for which info to be retrieved
8247 * @param info output buffer for error message
8248 * @param buflen length of output buffer
8249 * @param stringlen output length
8250 * @result ODBC error code
8251 */
8252
8253 SQLRETURN SQL_API
SQLGetDiagField(SQLSMALLINT htype,SQLHANDLE handle,SQLSMALLINT recno,SQLSMALLINT id,SQLPOINTER info,SQLSMALLINT buflen,SQLSMALLINT * stringlen)8254 SQLGetDiagField(SQLSMALLINT htype, SQLHANDLE handle, SQLSMALLINT recno,
8255 SQLSMALLINT id, SQLPOINTER info,
8256 SQLSMALLINT buflen, SQLSMALLINT *stringlen)
8257 {
8258 return drvgetdiagfield(htype, handle, recno, id, info, buflen, stringlen);
8259 }
8260 #endif
8261
8262 #ifdef WINTERFACE
8263 /**
8264 * Get error record given handle (HDBC or HSTMT).
8265 * @param htype handle type
8266 * @param handle HDBC or HSTMT
8267 * @param recno diag record number for which info to be retrieved
8268 * @param id diag id for which info to be retrieved
8269 * @param info output buffer for error message
8270 * @param buflen length of output buffer
8271 * @param stringlen output length
8272 * @result ODBC error code
8273 */
8274
8275 SQLRETURN SQL_API
SQLGetDiagFieldW(SQLSMALLINT htype,SQLHANDLE handle,SQLSMALLINT recno,SQLSMALLINT id,SQLPOINTER info,SQLSMALLINT buflen,SQLSMALLINT * stringlen)8276 SQLGetDiagFieldW(SQLSMALLINT htype, SQLHANDLE handle, SQLSMALLINT recno,
8277 SQLSMALLINT id, SQLPOINTER info,
8278 SQLSMALLINT buflen, SQLSMALLINT *stringlen)
8279 {
8280 SQLSMALLINT len;
8281 SQLRETURN ret;
8282
8283 ret = drvgetdiagfield(htype, handle, recno, id, info, buflen, &len);
8284 if (ret == SQL_SUCCESS) {
8285 if (info) {
8286 switch (id) {
8287 case SQL_DIAG_CLASS_ORIGIN:
8288 case SQL_DIAG_SUBCLASS_ORIGIN:
8289 case SQL_DIAG_CONNECTION_NAME:
8290 case SQL_DIAG_SERVER_NAME:
8291 case SQL_DIAG_SQLSTATE:
8292 case SQL_DIAG_MESSAGE_TEXT:
8293 if (len > 0) {
8294 SQLWCHAR *m = NULL;
8295
8296 m = uc_from_utf((unsigned char *) info, len);
8297 if (m) {
8298 if (buflen) {
8299 buflen /= sizeof (SQLWCHAR);
8300 uc_strncpy(info, m, buflen);
8301 m[len] = 0;
8302 len = min(buflen, uc_strlen(m));
8303 } else {
8304 len = uc_strlen(m);
8305 }
8306 uc_free(m);
8307 len *= sizeof (SQLWCHAR);
8308 } else {
8309 len = 0;
8310 }
8311 }
8312 if (len <= 0) {
8313 len = 0;
8314 if (buflen > 0) {
8315 ((SQLWCHAR *) info)[0] = 0;
8316 }
8317 }
8318 }
8319 } else {
8320 switch (id) {
8321 case SQL_DIAG_CLASS_ORIGIN:
8322 case SQL_DIAG_SUBCLASS_ORIGIN:
8323 case SQL_DIAG_CONNECTION_NAME:
8324 case SQL_DIAG_SERVER_NAME:
8325 case SQL_DIAG_SQLSTATE:
8326 case SQL_DIAG_MESSAGE_TEXT:
8327 len *= sizeof (SQLWCHAR);
8328 break;
8329 }
8330 }
8331 if (stringlen) {
8332 *stringlen = len;
8333 }
8334 }
8335 return ret;
8336 }
8337 #endif
8338
8339 /**
8340 * Internal get option of HSTMT.
8341 * @param stmt statement handle
8342 * @param attr attribute to be retrieved
8343 * @param val output buffer
8344 * @param bufmax length of output buffer
8345 * @param buflen output length
8346 * @result ODBC error code
8347 */
8348
8349 static SQLRETURN
drvgetstmtattr(SQLHSTMT stmt,SQLINTEGER attr,SQLPOINTER val,SQLINTEGER bufmax,SQLINTEGER * buflen)8350 drvgetstmtattr(SQLHSTMT stmt, SQLINTEGER attr, SQLPOINTER val,
8351 SQLINTEGER bufmax, SQLINTEGER *buflen)
8352 {
8353 STMT *s = (STMT *) stmt;
8354 SQLULEN *uval = (SQLULEN *) val;
8355
8356 switch (attr) {
8357 case SQL_QUERY_TIMEOUT:
8358 *uval = 0;
8359 return SQL_SUCCESS;
8360 case SQL_ATTR_CURSOR_TYPE:
8361 *uval = s->curtype;
8362 return SQL_SUCCESS;
8363 case SQL_ATTR_CURSOR_SCROLLABLE:
8364 *uval = (s->curtype != SQL_CURSOR_FORWARD_ONLY) ?
8365 SQL_SCROLLABLE : SQL_NONSCROLLABLE;
8366 return SQL_SUCCESS;
8367 #ifdef SQL_ATTR_CURSOR_SENSITIVITY
8368 case SQL_ATTR_CURSOR_SENSITIVITY:
8369 *uval = SQL_UNSPECIFIED;
8370 return SQL_SUCCESS;
8371 #endif
8372 case SQL_ATTR_ROW_NUMBER:
8373 if (s->s3stmt) {
8374 *uval = (s->s3stmt_rownum < 0) ?
8375 SQL_ROW_NUMBER_UNKNOWN : (s->s3stmt_rownum + 1);
8376 } else {
8377 *uval = (s->rowp < 0) ? SQL_ROW_NUMBER_UNKNOWN : (s->rowp + 1);
8378 }
8379 return SQL_SUCCESS;
8380 case SQL_ATTR_ASYNC_ENABLE:
8381 *uval = SQL_ASYNC_ENABLE_OFF;
8382 return SQL_SUCCESS;
8383 case SQL_CONCURRENCY:
8384 *uval = SQL_CONCUR_LOCK;
8385 return SQL_SUCCESS;
8386 case SQL_ATTR_RETRIEVE_DATA:
8387 *uval = s->retr_data;
8388 return SQL_SUCCESS;
8389 case SQL_ROWSET_SIZE:
8390 case SQL_ATTR_ROW_ARRAY_SIZE:
8391 *uval = s->rowset_size;
8392 return SQL_SUCCESS;
8393 /* Needed for some driver managers, but dummies for now */
8394 case SQL_ATTR_IMP_ROW_DESC:
8395 case SQL_ATTR_APP_ROW_DESC:
8396 case SQL_ATTR_IMP_PARAM_DESC:
8397 case SQL_ATTR_APP_PARAM_DESC:
8398 *((SQLHDESC *) val) = (SQLHDESC) DEAD_MAGIC;
8399 return SQL_SUCCESS;
8400 case SQL_ATTR_ROW_STATUS_PTR:
8401 *((SQLUSMALLINT **) val) = s->row_status;
8402 return SQL_SUCCESS;
8403 case SQL_ATTR_ROWS_FETCHED_PTR:
8404 *((SQLULEN **) val) = s->row_count;
8405 return SQL_SUCCESS;
8406 case SQL_ATTR_USE_BOOKMARKS: {
8407 STMT *s = (STMT *) stmt;
8408
8409 *(SQLUINTEGER *) val = s->bkmrk ? SQL_UB_ON : SQL_UB_OFF;
8410 return SQL_SUCCESS;
8411 }
8412 case SQL_ATTR_PARAM_BIND_OFFSET_PTR:
8413 *((SQLULEN **) val) = s->parm_bind_offs;
8414 return SQL_SUCCESS;
8415 case SQL_ATTR_PARAM_BIND_TYPE:
8416 *((SQLULEN *) val) = s->parm_bind_type;
8417 return SQL_SUCCESS;
8418 case SQL_ATTR_PARAM_OPERATION_PTR:
8419 *((SQLUSMALLINT **) val) = s->parm_oper;
8420 return SQL_SUCCESS;
8421 case SQL_ATTR_PARAM_STATUS_PTR:
8422 *((SQLUSMALLINT **) val) = s->parm_status;
8423 return SQL_SUCCESS;
8424 case SQL_ATTR_PARAMS_PROCESSED_PTR:
8425 *((SQLULEN **) val) = s->parm_proc;
8426 return SQL_SUCCESS;
8427 case SQL_ATTR_PARAMSET_SIZE:
8428 *((SQLULEN *) val) = s->paramset_size;
8429 return SQL_SUCCESS;
8430 case SQL_ATTR_ROW_BIND_TYPE:
8431 *(SQLULEN *) val = s->bind_type;
8432 return SQL_SUCCESS;
8433 case SQL_ATTR_ROW_BIND_OFFSET_PTR:
8434 *((SQLULEN **) val) = s->bind_offs;
8435 return SQL_SUCCESS;
8436 case SQL_ATTR_MAX_ROWS:
8437 *((SQLULEN *) val) = s->max_rows;
8438 case SQL_ATTR_MAX_LENGTH:
8439 *((SQLINTEGER *) val) = 1000000000;
8440 return SQL_SUCCESS;
8441 #ifdef SQL_ATTR_METADATA_ID
8442 case SQL_ATTR_METADATA_ID:
8443 *((SQLULEN *) val) = SQL_FALSE;
8444 return SQL_SUCCESS;
8445 #endif
8446 }
8447 return drvunimplstmt(stmt);
8448 }
8449
8450 #if (defined(HAVE_UNIXODBC) && (HAVE_UNIXODBC)) || !defined(WINTERFACE)
8451 /**
8452 * Get option of HSTMT.
8453 * @param stmt statement handle
8454 * @param attr attribute to be retrieved
8455 * @param val output buffer
8456 * @param bufmax length of output buffer
8457 * @param buflen output length
8458 * @result ODBC error code
8459 */
8460
8461 SQLRETURN SQL_API
SQLGetStmtAttr(SQLHSTMT stmt,SQLINTEGER attr,SQLPOINTER val,SQLINTEGER bufmax,SQLINTEGER * buflen)8462 SQLGetStmtAttr(SQLHSTMT stmt, SQLINTEGER attr, SQLPOINTER val,
8463 SQLINTEGER bufmax, SQLINTEGER *buflen)
8464 {
8465 SQLRETURN ret;
8466
8467 HSTMT_LOCK(stmt);
8468 ret = drvgetstmtattr(stmt, attr, val, bufmax, buflen);
8469 HSTMT_UNLOCK(stmt);
8470 return ret;
8471 }
8472 #endif
8473
8474 #ifdef WINTERFACE
8475 /**
8476 * Get option of HSTMT (UNICODE version).
8477 * @param stmt statement handle
8478 * @param attr attribute to be retrieved
8479 * @param val output buffer
8480 * @param bufmax length of output buffer
8481 * @param buflen output length
8482 * @result ODBC error code
8483 */
8484
8485 SQLRETURN SQL_API
SQLGetStmtAttrW(SQLHSTMT stmt,SQLINTEGER attr,SQLPOINTER val,SQLINTEGER bufmax,SQLINTEGER * buflen)8486 SQLGetStmtAttrW(SQLHSTMT stmt, SQLINTEGER attr, SQLPOINTER val,
8487 SQLINTEGER bufmax, SQLINTEGER *buflen)
8488 {
8489 SQLRETURN ret;
8490
8491 HSTMT_LOCK(stmt);
8492 ret = drvgetstmtattr(stmt, attr, val, bufmax, buflen);
8493 HSTMT_UNLOCK(stmt);
8494 return ret;
8495 }
8496 #endif
8497
8498 /**
8499 * Internal set option on HSTMT.
8500 * @param stmt statement handle
8501 * @param attr attribute to be set
8502 * @param val input buffer (attribute value)
8503 * @param buflen length of input buffer
8504 * @result ODBC error code
8505 */
8506
8507 static SQLRETURN
drvsetstmtattr(SQLHSTMT stmt,SQLINTEGER attr,SQLPOINTER val,SQLINTEGER buflen)8508 drvsetstmtattr(SQLHSTMT stmt, SQLINTEGER attr, SQLPOINTER val,
8509 SQLINTEGER buflen)
8510 {
8511 STMT *s = (STMT *) stmt;
8512 #if defined(SQL_BIGINT) && defined(__WORDSIZE) && (__WORDSIZE == 64)
8513 SQLBIGINT uval;
8514
8515 uval = (SQLBIGINT) val;
8516 #else
8517 SQLULEN uval;
8518
8519 uval = (SQLULEN) val;
8520 #endif
8521 switch (attr) {
8522 case SQL_ATTR_CURSOR_TYPE:
8523 if (val == (SQLPOINTER) SQL_CURSOR_FORWARD_ONLY) {
8524 s->curtype = SQL_CURSOR_FORWARD_ONLY;
8525 } else {
8526 s->curtype = SQL_CURSOR_STATIC;
8527 }
8528 if (val != (SQLPOINTER) SQL_CURSOR_FORWARD_ONLY &&
8529 val != (SQLPOINTER) SQL_CURSOR_STATIC) {
8530 goto e01s02;
8531 }
8532 return SQL_SUCCESS;
8533 case SQL_ATTR_CURSOR_SCROLLABLE:
8534 if (val == (SQLPOINTER) SQL_NONSCROLLABLE) {
8535 s->curtype = SQL_CURSOR_FORWARD_ONLY;
8536 } else {
8537 s->curtype = SQL_CURSOR_STATIC;
8538 }
8539 return SQL_SUCCESS;
8540 case SQL_ATTR_ASYNC_ENABLE:
8541 if (val != (SQLPOINTER) SQL_ASYNC_ENABLE_OFF) {
8542 e01s02:
8543 setstat(s, -1, "option value changed", "01S02");
8544 return SQL_SUCCESS_WITH_INFO;
8545 }
8546 return SQL_SUCCESS;
8547 case SQL_CONCURRENCY:
8548 if (val != (SQLPOINTER) SQL_CONCUR_LOCK) {
8549 goto e01s02;
8550 }
8551 return SQL_SUCCESS;
8552 #ifdef SQL_ATTR_CURSOR_SENSITIVITY
8553 case SQL_ATTR_CURSOR_SENSITIVITY:
8554 if (val != (SQLPOINTER) SQL_UNSPECIFIED) {
8555 goto e01s02;
8556 }
8557 return SQL_SUCCESS;
8558 #endif
8559 case SQL_ATTR_QUERY_TIMEOUT:
8560 return SQL_SUCCESS;
8561 case SQL_ATTR_RETRIEVE_DATA:
8562 if (val != (SQLPOINTER) SQL_RD_ON &&
8563 val != (SQLPOINTER) SQL_RD_OFF) {
8564 goto e01s02;
8565 }
8566 s->retr_data = uval;
8567 return SQL_SUCCESS;
8568 case SQL_ROWSET_SIZE:
8569 case SQL_ATTR_ROW_ARRAY_SIZE:
8570 if (uval < 1) {
8571 setstat(s, -1, "invalid rowset size", "HY000");
8572 return SQL_ERROR;
8573 } else {
8574 SQLUSMALLINT *rst = &s->row_status1;
8575
8576 if (uval > 1) {
8577 rst = xmalloc(sizeof (SQLUSMALLINT) * uval);
8578 if (!rst) {
8579 return nomem(s);
8580 }
8581 }
8582 if (s->row_status0 != &s->row_status1) {
8583 freep(&s->row_status0);
8584 }
8585 s->row_status0 = rst;
8586 s->rowset_size = uval;
8587 }
8588 return SQL_SUCCESS;
8589 case SQL_ATTR_ROW_STATUS_PTR:
8590 s->row_status = (SQLUSMALLINT *) val;
8591 return SQL_SUCCESS;
8592 case SQL_ATTR_ROWS_FETCHED_PTR:
8593 s->row_count = (SQLULEN *) val;
8594 return SQL_SUCCESS;
8595 case SQL_ATTR_PARAM_BIND_OFFSET_PTR:
8596 s->parm_bind_offs = (SQLULEN *) val;
8597 return SQL_SUCCESS;
8598 case SQL_ATTR_PARAM_BIND_TYPE:
8599 s->parm_bind_type = uval;
8600 return SQL_SUCCESS;
8601 case SQL_ATTR_PARAM_OPERATION_PTR:
8602 s->parm_oper = (SQLUSMALLINT *) val;
8603 return SQL_SUCCESS;
8604 case SQL_ATTR_PARAM_STATUS_PTR:
8605 s->parm_status = (SQLUSMALLINT *) val;
8606 return SQL_SUCCESS;
8607 case SQL_ATTR_PARAMS_PROCESSED_PTR:
8608 s->parm_proc = (SQLULEN *) val;
8609 return SQL_SUCCESS;
8610 case SQL_ATTR_PARAMSET_SIZE:
8611 if (uval < 1) {
8612 goto e01s02;
8613 }
8614 s->paramset_size = uval;
8615 s->paramset_count = 0;
8616 return SQL_SUCCESS;
8617 case SQL_ATTR_ROW_BIND_TYPE:
8618 s->bind_type = uval;
8619 return SQL_SUCCESS;
8620 case SQL_ATTR_ROW_BIND_OFFSET_PTR:
8621 s->bind_offs = (SQLULEN *) val;
8622 return SQL_SUCCESS;
8623 case SQL_ATTR_USE_BOOKMARKS:
8624 if (val != (SQLPOINTER) SQL_UB_OFF &&
8625 val != (SQLPOINTER) SQL_UB_ON) {
8626 goto e01s02;
8627 }
8628 s->bkmrk = val == (SQLPOINTER) SQL_UB_ON;
8629 return SQL_SUCCESS;
8630 case SQL_ATTR_MAX_ROWS:
8631 s->max_rows = uval;
8632 return SQL_SUCCESS;
8633 case SQL_ATTR_MAX_LENGTH:
8634 if (val != (SQLPOINTER) 1000000000) {
8635 goto e01s02;
8636 }
8637 return SQL_SUCCESS;
8638 #ifdef SQL_ATTR_METADATA_ID
8639 case SQL_ATTR_METADATA_ID:
8640 if (val != (SQLPOINTER) SQL_FALSE) {
8641 goto e01s02;
8642 }
8643 return SQL_SUCCESS;
8644 #endif
8645 }
8646 return drvunimplstmt(stmt);
8647 }
8648
8649 #if (defined(HAVE_UNIXODBC) && (HAVE_UNIXODBC)) || !defined(WINTERFACE)
8650 /**
8651 * Set option on HSTMT.
8652 * @param stmt statement handle
8653 * @param attr attribute to be set
8654 * @param val input buffer (attribute value)
8655 * @param buflen length of input buffer
8656 * @result ODBC error code
8657 */
8658
8659 SQLRETURN SQL_API
SQLSetStmtAttr(SQLHSTMT stmt,SQLINTEGER attr,SQLPOINTER val,SQLINTEGER buflen)8660 SQLSetStmtAttr(SQLHSTMT stmt, SQLINTEGER attr, SQLPOINTER val,
8661 SQLINTEGER buflen)
8662 {
8663 SQLRETURN ret;
8664
8665 HSTMT_LOCK(stmt);
8666 ret = drvsetstmtattr(stmt, attr, val, buflen);
8667 HSTMT_UNLOCK(stmt);
8668 return ret;
8669 }
8670 #endif
8671
8672 #ifdef WINTERFACE
8673 /**
8674 * Set option on HSTMT (UNICODE version).
8675 * @param stmt statement handle
8676 * @param attr attribute to be set
8677 * @param val input buffer (attribute value)
8678 * @param buflen length of input buffer
8679 * @result ODBC error code
8680 */
8681
8682 SQLRETURN SQL_API
SQLSetStmtAttrW(SQLHSTMT stmt,SQLINTEGER attr,SQLPOINTER val,SQLINTEGER buflen)8683 SQLSetStmtAttrW(SQLHSTMT stmt, SQLINTEGER attr, SQLPOINTER val,
8684 SQLINTEGER buflen)
8685 {
8686 SQLRETURN ret;
8687
8688 HSTMT_LOCK(stmt);
8689 ret = drvsetstmtattr(stmt, attr, val, buflen);
8690 HSTMT_UNLOCK(stmt);
8691 return ret;
8692 }
8693 #endif
8694
8695 /**
8696 * Internal get option of HSTMT.
8697 * @param stmt statement handle
8698 * @param opt option to be retrieved
8699 * @param param output buffer
8700 * @result ODBC error code
8701 */
8702
8703 static SQLRETURN
drvgetstmtoption(SQLHSTMT stmt,SQLUSMALLINT opt,SQLPOINTER param)8704 drvgetstmtoption(SQLHSTMT stmt, SQLUSMALLINT opt, SQLPOINTER param)
8705 {
8706 STMT *s = (STMT *) stmt;
8707 SQLUINTEGER *ret = (SQLUINTEGER *) param;
8708
8709 switch (opt) {
8710 case SQL_QUERY_TIMEOUT:
8711 *ret = 0;
8712 return SQL_SUCCESS;
8713 case SQL_CURSOR_TYPE:
8714 *ret = s->curtype;
8715 return SQL_SUCCESS;
8716 case SQL_ROW_NUMBER:
8717 if (s->s3stmt) {
8718 *ret = (s->s3stmt_rownum < 0) ?
8719 SQL_ROW_NUMBER_UNKNOWN : (s->s3stmt_rownum + 1);
8720 } else {
8721 *ret = (s->rowp < 0) ? SQL_ROW_NUMBER_UNKNOWN : (s->rowp + 1);
8722 }
8723 return SQL_SUCCESS;
8724 case SQL_ASYNC_ENABLE:
8725 *ret = SQL_ASYNC_ENABLE_OFF;
8726 return SQL_SUCCESS;
8727 case SQL_CONCURRENCY:
8728 *ret = SQL_CONCUR_LOCK;
8729 return SQL_SUCCESS;
8730 case SQL_ATTR_RETRIEVE_DATA:
8731 *ret = s->retr_data;
8732 return SQL_SUCCESS;
8733 case SQL_ROWSET_SIZE:
8734 case SQL_ATTR_ROW_ARRAY_SIZE:
8735 *ret = s->rowset_size;
8736 return SQL_SUCCESS;
8737 case SQL_ATTR_MAX_ROWS:
8738 *ret = s->max_rows;
8739 return SQL_SUCCESS;
8740 case SQL_ATTR_MAX_LENGTH:
8741 *ret = 1000000000;
8742 return SQL_SUCCESS;
8743 }
8744 return drvunimplstmt(stmt);
8745 }
8746
8747 /**
8748 * Get option of HSTMT.
8749 * @param stmt statement handle
8750 * @param opt option to be retrieved
8751 * @param param output buffer
8752 * @result ODBC error code
8753 */
8754
8755 SQLRETURN SQL_API
SQLGetStmtOption(SQLHSTMT stmt,SQLUSMALLINT opt,SQLPOINTER param)8756 SQLGetStmtOption(SQLHSTMT stmt, SQLUSMALLINT opt, SQLPOINTER param)
8757 {
8758 SQLRETURN ret;
8759
8760 HSTMT_LOCK(stmt);
8761 ret = drvgetstmtoption(stmt, opt, param);
8762 HSTMT_UNLOCK(stmt);
8763 return ret;
8764 }
8765
8766 #ifdef WINTERFACE
8767 /**
8768 * Get option of HSTMT (UNICODE version).
8769 * @param stmt statement handle
8770 * @param opt option to be retrieved
8771 * @param param output buffer
8772 * @result ODBC error code
8773 */
8774
8775 SQLRETURN SQL_API
SQLGetStmtOptionW(SQLHSTMT stmt,SQLUSMALLINT opt,SQLPOINTER param)8776 SQLGetStmtOptionW(SQLHSTMT stmt, SQLUSMALLINT opt, SQLPOINTER param)
8777 {
8778 SQLRETURN ret;
8779
8780 HSTMT_LOCK(stmt);
8781 ret = drvgetstmtoption(stmt, opt, param);
8782 HSTMT_UNLOCK(stmt);
8783 return ret;
8784 }
8785 #endif
8786
8787 /**
8788 * Internal set option on HSTMT.
8789 * @param stmt statement handle
8790 * @param opt option to be set
8791 * @param param input buffer (option value)
8792 * @result ODBC error code
8793 */
8794
8795 static SQLRETURN
drvsetstmtoption(SQLHSTMT stmt,SQLUSMALLINT opt,SQLUINTEGER param)8796 drvsetstmtoption(SQLHSTMT stmt, SQLUSMALLINT opt, SQLUINTEGER param)
8797 {
8798 STMT *s = (STMT *) stmt;
8799
8800 switch (opt) {
8801 case SQL_CURSOR_TYPE:
8802 if (param == SQL_CURSOR_FORWARD_ONLY) {
8803 s->curtype = param;
8804 } else {
8805 s->curtype = SQL_CURSOR_STATIC;
8806 }
8807 if (param != SQL_CURSOR_FORWARD_ONLY &&
8808 param != SQL_CURSOR_STATIC) {
8809 goto e01s02;
8810 }
8811 return SQL_SUCCESS;
8812 case SQL_ASYNC_ENABLE:
8813 if (param != SQL_ASYNC_ENABLE_OFF) {
8814 goto e01s02;
8815 }
8816 return SQL_SUCCESS;
8817 case SQL_CONCURRENCY:
8818 if (param != SQL_CONCUR_LOCK) {
8819 goto e01s02;
8820 }
8821 return SQL_SUCCESS;
8822 case SQL_QUERY_TIMEOUT:
8823 return SQL_SUCCESS;
8824 case SQL_RETRIEVE_DATA:
8825 if (param != SQL_RD_ON && param != SQL_RD_OFF) {
8826 e01s02:
8827 setstat(s, -1, "option value changed", "01S02");
8828 return SQL_SUCCESS_WITH_INFO;
8829 }
8830 s->retr_data = (int) param;
8831 return SQL_SUCCESS;
8832 case SQL_ROWSET_SIZE:
8833 case SQL_ATTR_ROW_ARRAY_SIZE:
8834 if (param < 1) {
8835 setstat(s, -1, "invalid rowset size", "HY000");
8836 return SQL_ERROR;
8837 } else {
8838 SQLUSMALLINT *rst = &s->row_status1;
8839
8840 if (param > 1) {
8841 rst = xmalloc(sizeof (SQLUSMALLINT) * param);
8842 if (!rst) {
8843 return nomem(s);
8844 }
8845 }
8846 if (s->row_status0 != &s->row_status1) {
8847 freep(&s->row_status0);
8848 }
8849 s->row_status0 = rst;
8850 s->rowset_size = param;
8851 }
8852 return SQL_SUCCESS;
8853 case SQL_ATTR_MAX_ROWS:
8854 s->max_rows = param;
8855 return SQL_SUCCESS;
8856 case SQL_ATTR_MAX_LENGTH:
8857 if (param != 1000000000) {
8858 goto e01s02;
8859 }
8860 return SQL_SUCCESS;
8861 }
8862 return drvunimplstmt(stmt);
8863 }
8864
8865 /**
8866 * Set option on HSTMT.
8867 * @param stmt statement handle
8868 * @param opt option to be set
8869 * @param param input buffer (option value)
8870 * @result ODBC error code
8871 */
8872
8873 SQLRETURN SQL_API
SQLSetStmtOption(SQLHSTMT stmt,SQLUSMALLINT opt,SETSTMTOPTION_LAST_ARG_TYPE param)8874 SQLSetStmtOption(SQLHSTMT stmt, SQLUSMALLINT opt,
8875 SETSTMTOPTION_LAST_ARG_TYPE param)
8876 {
8877 SQLRETURN ret;
8878
8879 HSTMT_LOCK(stmt);
8880 ret = drvsetstmtoption(stmt, opt, (SQLUINTEGER) param);
8881 HSTMT_UNLOCK(stmt);
8882 return ret;
8883 }
8884
8885 #ifdef WINTERFACE
8886 /**
8887 * Set option on HSTMT (UNICODE version).
8888 * @param stmt statement handle
8889 * @param opt option to be set
8890 * @param param input buffer (option value)
8891 * @result ODBC error code
8892 */
8893
8894 SQLRETURN SQL_API
SQLSetStmtOptionW(SQLHSTMT stmt,SQLUSMALLINT opt,SETSTMTOPTION_LAST_ARG_TYPE param)8895 SQLSetStmtOptionW(SQLHSTMT stmt, SQLUSMALLINT opt,
8896 SETSTMTOPTION_LAST_ARG_TYPE param)
8897 {
8898 SQLRETURN ret;
8899
8900 HSTMT_LOCK(stmt);
8901 ret = drvsetstmtoption(stmt, opt, (SQLUINTEGER) param);
8902 HSTMT_UNLOCK(stmt);
8903 return ret;
8904 }
8905 #endif
8906
8907 /**
8908 * Internal set position on result in HSTMT.
8909 * @param stmt statement handle
8910 * @param row row to be positioned
8911 * @param op operation code
8912 * @param lock locking type
8913 * @result ODBC error code
8914 */
8915
8916 static SQLRETURN
drvsetpos(SQLHSTMT stmt,SQLSETPOSIROW row,SQLUSMALLINT op,SQLUSMALLINT lock)8917 drvsetpos(SQLHSTMT stmt, SQLSETPOSIROW row, SQLUSMALLINT op, SQLUSMALLINT lock)
8918 {
8919 STMT *s = (STMT *) stmt;
8920 int rowp;
8921
8922 if (op != SQL_POSITION) {
8923 return drvunimplstmt(stmt);
8924 }
8925 rowp = s->rowp + row - 1;
8926 if (!s->rows || row <= 0 || rowp < -1 || rowp >= s->nrows) {
8927 setstat(s, -1, "row out of range", (*s->ov3) ? "HY107" : "S1107");
8928 return SQL_ERROR;
8929 }
8930 s->rowp = rowp;
8931 return SQL_SUCCESS;
8932 }
8933
8934 /**
8935 * Set position on result in HSTMT.
8936 * @param stmt statement handle
8937 * @param row row to be positioned
8938 * @param op operation code
8939 * @param lock locking type
8940 * @result ODBC error code
8941 */
8942
8943 SQLRETURN SQL_API
SQLSetPos(SQLHSTMT stmt,SQLSETPOSIROW row,SQLUSMALLINT op,SQLUSMALLINT lock)8944 SQLSetPos(SQLHSTMT stmt, SQLSETPOSIROW row, SQLUSMALLINT op, SQLUSMALLINT lock)
8945 {
8946 SQLRETURN ret;
8947
8948 HSTMT_LOCK(stmt);
8949 ret = drvsetpos(stmt, row, op, lock);
8950 HSTMT_UNLOCK(stmt);
8951 return ret;
8952 }
8953
8954 /**
8955 * Function not implemented.
8956 */
8957
8958 SQLRETURN SQL_API
SQLSetScrollOptions(SQLHSTMT stmt,SQLUSMALLINT concur,SQLLEN rowkeyset,SQLUSMALLINT rowset)8959 SQLSetScrollOptions(SQLHSTMT stmt, SQLUSMALLINT concur, SQLLEN rowkeyset,
8960 SQLUSMALLINT rowset)
8961 {
8962 SQLRETURN ret;
8963
8964 HSTMT_LOCK(stmt);
8965 ret = drvunimplstmt(stmt);
8966 HSTMT_UNLOCK(stmt);
8967 return ret;
8968 }
8969
8970 #define strmak(dst, src, max, lenp) { \
8971 int len = strlen(src); \
8972 int cnt = min(len + 1, max); \
8973 strncpy(dst, src, cnt); \
8974 *lenp = (cnt > len) ? len : cnt; \
8975 }
8976
8977 /**
8978 * Internal return information about what this ODBC driver supports.
8979 * @param dbc database connection handle
8980 * @param type type of information to be retrieved
8981 * @param val output buffer
8982 * @param valMax length of output buffer
8983 * @param valLen output length
8984 * @result ODBC error code
8985 */
8986
8987 static SQLRETURN
drvgetinfo(SQLHDBC dbc,SQLUSMALLINT type,SQLPOINTER val,SQLSMALLINT valMax,SQLSMALLINT * valLen)8988 drvgetinfo(SQLHDBC dbc, SQLUSMALLINT type, SQLPOINTER val, SQLSMALLINT valMax,
8989 SQLSMALLINT *valLen)
8990 {
8991 DBC *d;
8992 char dummyc[16];
8993 SQLSMALLINT dummy;
8994 #if defined(_WIN32) || defined(_WIN64)
8995 char drvname[301];
8996 #else
8997 static char drvname[] = "sqlite3odbc.so";
8998 #endif
8999
9000 if (dbc == SQL_NULL_HDBC) {
9001 return SQL_INVALID_HANDLE;
9002 }
9003 d = (DBC *) dbc;
9004 if (valMax) {
9005 valMax--;
9006 }
9007 if (!valLen) {
9008 valLen = &dummy;
9009 }
9010 if (!val) {
9011 val = dummyc;
9012 valMax = sizeof (dummyc) - 1;
9013 }
9014 switch (type) {
9015 case SQL_MAX_USER_NAME_LEN:
9016 *((SQLSMALLINT *) val) = 16;
9017 *valLen = sizeof (SQLSMALLINT);
9018 break;
9019 case SQL_USER_NAME:
9020 strmak(val, "", valMax, valLen);
9021 break;
9022 case SQL_DRIVER_ODBC_VER:
9023 #if 0
9024 strmak(val, (*d->ov3) ? "03.00" : "02.50", valMax, valLen);
9025 #else
9026 strmak(val, "03.00", valMax, valLen);
9027 #endif
9028 break;
9029 case SQL_ACTIVE_CONNECTIONS:
9030 case SQL_ACTIVE_STATEMENTS:
9031 *((SQLSMALLINT *) val) = 0;
9032 *valLen = sizeof (SQLSMALLINT);
9033 break;
9034 #ifdef SQL_ASYNC_MODE
9035 case SQL_ASYNC_MODE:
9036 *((SQLUINTEGER *) val) = SQL_AM_NONE;
9037 *valLen = sizeof (SQLUINTEGER);
9038 break;
9039 #endif
9040 #ifdef SQL_CREATE_TABLE
9041 case SQL_CREATE_TABLE:
9042 *((SQLUINTEGER *) val) = SQL_CT_CREATE_TABLE |
9043 SQL_CT_COLUMN_DEFAULT |
9044 SQL_CT_COLUMN_CONSTRAINT |
9045 SQL_CT_CONSTRAINT_NON_DEFERRABLE;
9046 *valLen = sizeof (SQLUINTEGER);
9047 break;
9048 #endif
9049 #ifdef SQL_CREATE_VIEW
9050 case SQL_CREATE_VIEW:
9051 *((SQLUINTEGER *) val) = SQL_CV_CREATE_VIEW;
9052 *valLen = sizeof (SQLUINTEGER);
9053 break;
9054 #endif
9055 #ifdef SQL_DDL_INDEX
9056 case SQL_DDL_INDEX:
9057 *((SQLUINTEGER *) val) = SQL_DI_CREATE_INDEX | SQL_DI_DROP_INDEX;
9058 *valLen = sizeof (SQLUINTEGER);
9059 break;
9060 #endif
9061 #ifdef SQL_DROP_TABLE
9062 case SQL_DROP_TABLE:
9063 *((SQLUINTEGER *) val) = SQL_DT_DROP_TABLE;
9064 *valLen = sizeof (SQLUINTEGER);
9065 break;
9066 #endif
9067 #ifdef SQL_DROP_VIEW
9068 case SQL_DROP_VIEW:
9069 *((SQLUINTEGER *) val) = SQL_DV_DROP_VIEW;
9070 *valLen = sizeof (SQLUINTEGER);
9071 break;
9072 #endif
9073 #ifdef SQL_INDEX_KEYWORDS
9074 case SQL_INDEX_KEYWORDS:
9075 *((SQLUINTEGER *) val) = SQL_IK_ALL;
9076 *valLen = sizeof (SQLUINTEGER);
9077 break;
9078 #endif
9079 case SQL_DATA_SOURCE_NAME:
9080 strmak(val, d->dsn ? d->dsn : "", valMax, valLen);
9081 break;
9082 case SQL_DRIVER_NAME:
9083 #if defined(_WIN32) || defined(_WIN64)
9084 GetModuleFileName(hModule, drvname, sizeof (drvname));
9085 #endif
9086 strmak(val, drvname, valMax, valLen);
9087 break;
9088 case SQL_DRIVER_VER:
9089 strmak(val, DRIVER_VER_INFO, valMax, valLen);
9090 break;
9091 case SQL_FETCH_DIRECTION:
9092 *((SQLUINTEGER *) val) = SQL_FD_FETCH_NEXT | SQL_FD_FETCH_FIRST |
9093 SQL_FD_FETCH_LAST | SQL_FD_FETCH_PRIOR | SQL_FD_FETCH_ABSOLUTE;
9094 *valLen = sizeof (SQLUINTEGER);
9095 break;
9096 case SQL_ODBC_VER:
9097 strmak(val, (*d->ov3) ? "03.00" : "02.50", valMax, valLen);
9098 break;
9099 case SQL_ODBC_SAG_CLI_CONFORMANCE:
9100 *((SQLSMALLINT *) val) = SQL_OSCC_NOT_COMPLIANT;
9101 *valLen = sizeof (SQLSMALLINT);
9102 break;
9103 case SQL_STANDARD_CLI_CONFORMANCE:
9104 *((SQLUINTEGER *) val) = SQL_SCC_XOPEN_CLI_VERSION1;
9105 *valLen = sizeof (SQLUINTEGER);
9106 break;
9107 case SQL_SERVER_NAME:
9108 case SQL_DATABASE_NAME:
9109 strmak(val, d->dbname ? d->dbname : "", valMax, valLen);
9110 break;
9111 case SQL_SEARCH_PATTERN_ESCAPE:
9112 strmak(val, "\\", valMax, valLen);
9113 break;
9114 case SQL_ODBC_SQL_CONFORMANCE:
9115 *((SQLSMALLINT *) val) = SQL_OSC_MINIMUM;
9116 *valLen = sizeof (SQLSMALLINT);
9117 break;
9118 case SQL_ODBC_API_CONFORMANCE:
9119 *((SQLSMALLINT *) val) = SQL_OAC_LEVEL1;
9120 *valLen = sizeof (SQLSMALLINT);
9121 break;
9122 case SQL_DBMS_NAME:
9123 strmak(val, "SQLite", valMax, valLen);
9124 break;
9125 case SQL_DBMS_VER:
9126 strmak(val, SQLITE_VERSION, valMax, valLen);
9127 break;
9128 case SQL_COLUMN_ALIAS:
9129 case SQL_NEED_LONG_DATA_LEN:
9130 strmak(val, "Y", valMax, valLen);
9131 break;
9132 case SQL_ROW_UPDATES:
9133 case SQL_ACCESSIBLE_PROCEDURES:
9134 case SQL_PROCEDURES:
9135 case SQL_EXPRESSIONS_IN_ORDERBY:
9136 case SQL_ODBC_SQL_OPT_IEF:
9137 case SQL_LIKE_ESCAPE_CLAUSE:
9138 case SQL_ORDER_BY_COLUMNS_IN_SELECT:
9139 case SQL_OUTER_JOINS:
9140 case SQL_ACCESSIBLE_TABLES:
9141 case SQL_MULT_RESULT_SETS:
9142 case SQL_MULTIPLE_ACTIVE_TXN:
9143 case SQL_MAX_ROW_SIZE_INCLUDES_LONG:
9144 strmak(val, "N", valMax, valLen);
9145 break;
9146 #ifdef SQL_CATALOG_NAME
9147 case SQL_CATALOG_NAME:
9148 #if defined(_WIN32) || defined(_WIN64)
9149 strmak(val, d->xcelqrx ? "Y" : "N", valMax, valLen);
9150 #else
9151 strmak(val, "N", valMax, valLen);
9152 #endif
9153 break;
9154 #endif
9155 case SQL_DATA_SOURCE_READ_ONLY:
9156 strmak(val, "N", valMax, valLen);
9157 break;
9158 #ifdef SQL_OJ_CAPABILITIES
9159 case SQL_OJ_CAPABILITIES:
9160 *((SQLUINTEGER *) val) = 0;
9161 *valLen = sizeof (SQLUINTEGER);
9162 break;
9163 #endif
9164 #ifdef SQL_MAX_IDENTIFIER_LEN
9165 case SQL_MAX_IDENTIFIER_LEN:
9166 *((SQLUSMALLINT *) val) = 255;
9167 *valLen = sizeof (SQLUSMALLINT);
9168 break;
9169 #endif
9170 case SQL_CONCAT_NULL_BEHAVIOR:
9171 *((SQLSMALLINT *) val) = SQL_CB_NULL;
9172 *valLen = sizeof (SQLSMALLINT);
9173 break;
9174 case SQL_CURSOR_COMMIT_BEHAVIOR:
9175 case SQL_CURSOR_ROLLBACK_BEHAVIOR:
9176 *((SQLSMALLINT *) val) = SQL_CB_PRESERVE;
9177 *valLen = sizeof (SQLSMALLINT);
9178 break;
9179 #ifdef SQL_CURSOR_SENSITIVITY
9180 case SQL_CURSOR_SENSITIVITY:
9181 *((SQLUINTEGER *) val) = SQL_UNSPECIFIED;
9182 *valLen = sizeof (SQLUINTEGER);
9183 break;
9184 #endif
9185 case SQL_DEFAULT_TXN_ISOLATION:
9186 *((SQLUINTEGER *) val) = SQL_TXN_SERIALIZABLE;
9187 *valLen = sizeof (SQLUINTEGER);
9188 break;
9189 #ifdef SQL_DESCRIBE_PARAMETER
9190 case SQL_DESCRIBE_PARAMETER:
9191 strmak(val, "Y", valMax, valLen);
9192 break;
9193 #endif
9194 case SQL_TXN_ISOLATION_OPTION:
9195 *((SQLUINTEGER *) val) = SQL_TXN_SERIALIZABLE;
9196 *valLen = sizeof (SQLUINTEGER);
9197 break;
9198 case SQL_IDENTIFIER_CASE:
9199 *((SQLSMALLINT *) val) = SQL_IC_SENSITIVE;
9200 *valLen = sizeof (SQLSMALLINT);
9201 break;
9202 case SQL_IDENTIFIER_QUOTE_CHAR:
9203 strmak(val, "\"", valMax, valLen);
9204 break;
9205 case SQL_MAX_TABLE_NAME_LEN:
9206 case SQL_MAX_COLUMN_NAME_LEN:
9207 *((SQLSMALLINT *) val) = 255;
9208 *valLen = sizeof (SQLSMALLINT);
9209 break;
9210 case SQL_MAX_CURSOR_NAME_LEN:
9211 *((SQLSMALLINT *) val) = 255;
9212 *valLen = sizeof (SQLSMALLINT);
9213 break;
9214 case SQL_MAX_PROCEDURE_NAME_LEN:
9215 *((SQLSMALLINT *) val) = 0;
9216 break;
9217 case SQL_MAX_QUALIFIER_NAME_LEN:
9218 case SQL_MAX_OWNER_NAME_LEN:
9219 *((SQLSMALLINT *) val) = 255;
9220 break;
9221 case SQL_OWNER_TERM:
9222 strmak(val, "", valMax, valLen);
9223 break;
9224 case SQL_PROCEDURE_TERM:
9225 strmak(val, "PROCEDURE", valMax, valLen);
9226 break;
9227 case SQL_QUALIFIER_NAME_SEPARATOR:
9228 strmak(val, ".", valMax, valLen);
9229 break;
9230 case SQL_QUALIFIER_TERM:
9231 #if defined(_WIN32) || defined(_WIN64)
9232 strmak(val, d->xcelqrx ? "catalog" : "", valMax, valLen);
9233 #else
9234 strmak(val, "", valMax, valLen);
9235 #endif
9236 break;
9237 case SQL_QUALIFIER_USAGE:
9238 #if defined(_WIN32) || defined(_WIN64)
9239 *((SQLUINTEGER *) val) = d->xcelqrx ?
9240 (SQL_CU_DML_STATEMENTS | SQL_CU_INDEX_DEFINITION |
9241 SQL_CU_TABLE_DEFINITION) : 0;
9242 #else
9243 *((SQLUINTEGER *) val) = 0;
9244 #endif
9245 *valLen = sizeof (SQLUINTEGER);
9246 break;
9247 case SQL_SCROLL_CONCURRENCY:
9248 *((SQLUINTEGER *) val) = SQL_SCCO_LOCK;
9249 *valLen = sizeof (SQLUINTEGER);
9250 break;
9251 case SQL_SCROLL_OPTIONS:
9252 *((SQLUINTEGER *) val) = SQL_SO_STATIC | SQL_SO_FORWARD_ONLY;
9253 *valLen = sizeof (SQLUINTEGER);
9254 break;
9255 case SQL_TABLE_TERM:
9256 strmak(val, "TABLE", valMax, valLen);
9257 break;
9258 case SQL_TXN_CAPABLE:
9259 *((SQLSMALLINT *) val) = SQL_TC_ALL;
9260 *valLen = sizeof (SQLSMALLINT);
9261 break;
9262 case SQL_CONVERT_FUNCTIONS:
9263 *((SQLUINTEGER *) val) = 0;
9264 *valLen = sizeof (SQLUINTEGER);
9265 break;
9266 case SQL_SYSTEM_FUNCTIONS:
9267 case SQL_NUMERIC_FUNCTIONS:
9268 case SQL_STRING_FUNCTIONS:
9269 case SQL_TIMEDATE_FUNCTIONS:
9270 *((SQLUINTEGER *) val) = 0;
9271 *valLen = sizeof (SQLUINTEGER);
9272 break;
9273 case SQL_CONVERT_BIGINT:
9274 case SQL_CONVERT_BIT:
9275 case SQL_CONVERT_CHAR:
9276 case SQL_CONVERT_DATE:
9277 case SQL_CONVERT_DECIMAL:
9278 case SQL_CONVERT_DOUBLE:
9279 case SQL_CONVERT_FLOAT:
9280 case SQL_CONVERT_INTEGER:
9281 case SQL_CONVERT_LONGVARCHAR:
9282 case SQL_CONVERT_NUMERIC:
9283 case SQL_CONVERT_REAL:
9284 case SQL_CONVERT_SMALLINT:
9285 case SQL_CONVERT_TIME:
9286 case SQL_CONVERT_TIMESTAMP:
9287 case SQL_CONVERT_TINYINT:
9288 case SQL_CONVERT_VARCHAR:
9289 *((SQLUINTEGER *) val) =
9290 SQL_CVT_CHAR | SQL_CVT_NUMERIC | SQL_CVT_DECIMAL |
9291 SQL_CVT_INTEGER | SQL_CVT_SMALLINT | SQL_CVT_FLOAT | SQL_CVT_REAL |
9292 SQL_CVT_DOUBLE | SQL_CVT_VARCHAR | SQL_CVT_LONGVARCHAR |
9293 SQL_CVT_BIT | SQL_CVT_TINYINT | SQL_CVT_BIGINT |
9294 SQL_CVT_DATE | SQL_CVT_TIME | SQL_CVT_TIMESTAMP;
9295 *valLen = sizeof (SQLUINTEGER);
9296 break;
9297 case SQL_CONVERT_BINARY:
9298 case SQL_CONVERT_VARBINARY:
9299 case SQL_CONVERT_LONGVARBINARY:
9300 *((SQLUINTEGER *) val) = 0;
9301 *valLen = sizeof (SQLUINTEGER);
9302 break;
9303 case SQL_POSITIONED_STATEMENTS:
9304 case SQL_LOCK_TYPES:
9305 *((SQLUINTEGER *) val) = 0;
9306 *valLen = sizeof (SQLUINTEGER);
9307 break;
9308 case SQL_BOOKMARK_PERSISTENCE:
9309 *((SQLUINTEGER *) val) = SQL_BP_SCROLL;
9310 *valLen = sizeof (SQLUINTEGER);
9311 break;
9312 case SQL_UNION:
9313 *((SQLUINTEGER *) val) = SQL_U_UNION | SQL_U_UNION_ALL;
9314 *valLen = sizeof (SQLUINTEGER);
9315 break;
9316 case SQL_OWNER_USAGE:
9317 case SQL_SUBQUERIES:
9318 case SQL_TIMEDATE_ADD_INTERVALS:
9319 case SQL_TIMEDATE_DIFF_INTERVALS:
9320 *((SQLUINTEGER *) val) = 0;
9321 *valLen = sizeof (SQLUINTEGER);
9322 break;
9323 case SQL_QUOTED_IDENTIFIER_CASE:
9324 *((SQLUSMALLINT *) val) = SQL_IC_SENSITIVE;
9325 *valLen = sizeof (SQLUSMALLINT);
9326 break;
9327 case SQL_POS_OPERATIONS:
9328 *((SQLUINTEGER *) val) = 0;
9329 *valLen = sizeof (SQLUINTEGER);
9330 break;
9331 case SQL_ALTER_TABLE:
9332 *((SQLUINTEGER *) val) = 0;
9333 *valLen = sizeof (SQLUINTEGER);
9334 break;
9335 case SQL_CORRELATION_NAME:
9336 *((SQLSMALLINT *) val) = SQL_CN_DIFFERENT;
9337 *valLen = sizeof (SQLSMALLINT);
9338 break;
9339 case SQL_NON_NULLABLE_COLUMNS:
9340 *((SQLSMALLINT *) val) = SQL_NNC_NON_NULL;
9341 *valLen = sizeof (SQLSMALLINT);
9342 break;
9343 case SQL_NULL_COLLATION:
9344 *((SQLSMALLINT *) val) = SQL_NC_START;
9345 *valLen = sizeof (SQLSMALLINT);
9346 break;
9347 case SQL_MAX_COLUMNS_IN_GROUP_BY:
9348 case SQL_MAX_COLUMNS_IN_ORDER_BY:
9349 case SQL_MAX_COLUMNS_IN_SELECT:
9350 case SQL_MAX_COLUMNS_IN_TABLE:
9351 case SQL_MAX_ROW_SIZE:
9352 case SQL_MAX_TABLES_IN_SELECT:
9353 *((SQLSMALLINT *) val) = 0;
9354 *valLen = sizeof (SQLSMALLINT);
9355 break;
9356 case SQL_MAX_BINARY_LITERAL_LEN:
9357 case SQL_MAX_CHAR_LITERAL_LEN:
9358 *((SQLUINTEGER *) val) = 0;
9359 *valLen = sizeof (SQLUINTEGER);
9360 break;
9361 case SQL_MAX_COLUMNS_IN_INDEX:
9362 *((SQLSMALLINT *) val) = 0;
9363 *valLen = sizeof (SQLSMALLINT);
9364 break;
9365 case SQL_MAX_INDEX_SIZE:
9366 *((SQLUINTEGER *) val) = 0;
9367 *valLen = sizeof (SQLUINTEGER);
9368 break;
9369 #ifdef SQL_MAX_IDENTIFIER_LENGTH
9370 case SQL_MAX_IDENTIFIER_LENGTH:
9371 *((SQLUINTEGER *) val) = 255;
9372 *valLen = sizeof (SQLUINTEGER);
9373 break;
9374 #endif
9375 case SQL_MAX_STATEMENT_LEN:
9376 *((SQLUINTEGER *) val) = 16384;
9377 *valLen = sizeof (SQLUINTEGER);
9378 break;
9379 case SQL_QUALIFIER_LOCATION:
9380 *((SQLSMALLINT *) val) = SQL_QL_START;
9381 *valLen = sizeof (SQLSMALLINT);
9382 break;
9383 case SQL_GETDATA_EXTENSIONS:
9384 *((SQLUINTEGER *) val) =
9385 SQL_GD_ANY_COLUMN | SQL_GD_ANY_ORDER | SQL_GD_BOUND;
9386 *valLen = sizeof (SQLUINTEGER);
9387 break;
9388 case SQL_STATIC_SENSITIVITY:
9389 *((SQLUINTEGER *) val) = 0;
9390 *valLen = sizeof (SQLUINTEGER);
9391 break;
9392 case SQL_FILE_USAGE:
9393 #if defined(_WIN32) || defined(_WIN64)
9394 *((SQLSMALLINT *) val) =
9395 d->xcelqrx ? SQL_FILE_CATALOG : SQL_FILE_NOT_SUPPORTED;
9396 #else
9397 *((SQLSMALLINT *) val) = SQL_FILE_NOT_SUPPORTED;
9398 #endif
9399 *valLen = sizeof (SQLSMALLINT);
9400 break;
9401 case SQL_GROUP_BY:
9402 *((SQLSMALLINT *) val) = 0;
9403 *valLen = sizeof (SQLSMALLINT);
9404 break;
9405 case SQL_KEYWORDS:
9406 strmak(val, "CREATE,SELECT,DROP,DELETE,UPDATE,INSERT,"
9407 "INTO,VALUES,TABLE,INDEX,FROM,SET,WHERE,AND,CURRENT,OF",
9408 valMax, valLen);
9409 break;
9410 case SQL_SPECIAL_CHARACTERS:
9411 #ifdef SQL_COLLATION_SEQ
9412 case SQL_COLLATION_SEQ:
9413 #endif
9414 strmak(val, "", valMax, valLen);
9415 break;
9416 case SQL_BATCH_SUPPORT:
9417 case SQL_BATCH_ROW_COUNT:
9418 case SQL_PARAM_ARRAY_ROW_COUNTS:
9419 *((SQLUINTEGER *) val) = 0;
9420 *valLen = sizeof (SQLUINTEGER);
9421 break;
9422 case SQL_FORWARD_ONLY_CURSOR_ATTRIBUTES1:
9423 *((SQLUINTEGER *) val) = SQL_CA1_NEXT | SQL_CA1_BOOKMARK;
9424 *valLen = sizeof (SQLUINTEGER);
9425 break;
9426 case SQL_STATIC_CURSOR_ATTRIBUTES1:
9427 *((SQLUINTEGER *) val) = SQL_CA1_NEXT | SQL_CA1_ABSOLUTE |
9428 SQL_CA1_RELATIVE | SQL_CA1_BOOKMARK;
9429 *valLen = sizeof (SQLUINTEGER);
9430 break;
9431 case SQL_FORWARD_ONLY_CURSOR_ATTRIBUTES2:
9432 case SQL_STATIC_CURSOR_ATTRIBUTES2:
9433 *((SQLUINTEGER *) val) = SQL_CA2_READ_ONLY_CONCURRENCY |
9434 SQL_CA2_LOCK_CONCURRENCY;
9435 *valLen = sizeof (SQLUINTEGER);
9436 break;
9437 case SQL_KEYSET_CURSOR_ATTRIBUTES1:
9438 case SQL_KEYSET_CURSOR_ATTRIBUTES2:
9439 case SQL_DYNAMIC_CURSOR_ATTRIBUTES1:
9440 case SQL_DYNAMIC_CURSOR_ATTRIBUTES2:
9441 *((SQLUINTEGER *) val) = 0;
9442 *valLen = sizeof (SQLUINTEGER);
9443 break;
9444 case SQL_ODBC_INTERFACE_CONFORMANCE:
9445 *((SQLUINTEGER *) val) = SQL_OIC_CORE;
9446 *valLen = sizeof (SQLUINTEGER);
9447 break;
9448 default:
9449 setstatd(d, -1, "unsupported info option %d",
9450 (*d->ov3) ? "HYC00" : "S1C00", type);
9451 return SQL_ERROR;
9452 }
9453 return SQL_SUCCESS;
9454 }
9455
9456 #if (defined(HAVE_UNIXODBC) && (HAVE_UNIXODBC)) || !defined(WINTERFACE)
9457 /**
9458 * Return information about what this ODBC driver supports.
9459 * @param dbc database connection handle
9460 * @param type type of information to be retrieved
9461 * @param val output buffer
9462 * @param valMax length of output buffer
9463 * @param valLen output length
9464 * @result ODBC error code
9465 */
9466
9467 SQLRETURN SQL_API
SQLGetInfo(SQLHDBC dbc,SQLUSMALLINT type,SQLPOINTER val,SQLSMALLINT valMax,SQLSMALLINT * valLen)9468 SQLGetInfo(SQLHDBC dbc, SQLUSMALLINT type, SQLPOINTER val, SQLSMALLINT valMax,
9469 SQLSMALLINT *valLen)
9470 {
9471 SQLRETURN ret;
9472
9473 HDBC_LOCK(dbc);
9474 ret = drvgetinfo(dbc, type, val, valMax, valLen);
9475 HDBC_UNLOCK(dbc);
9476 return ret;
9477 }
9478 #endif
9479
9480 #ifdef WINTERFACE
9481 /**
9482 * Return information about what this ODBC driver supports.
9483 * @param dbc database connection handle
9484 * @param type type of information to be retrieved
9485 * @param val output buffer
9486 * @param valMax length of output buffer
9487 * @param valLen output length
9488 * @result ODBC error code
9489 */
9490
9491 SQLRETURN SQL_API
SQLGetInfoW(SQLHDBC dbc,SQLUSMALLINT type,SQLPOINTER val,SQLSMALLINT valMax,SQLSMALLINT * valLen)9492 SQLGetInfoW(SQLHDBC dbc, SQLUSMALLINT type, SQLPOINTER val, SQLSMALLINT valMax,
9493 SQLSMALLINT *valLen)
9494 {
9495 SQLRETURN ret;
9496 SQLSMALLINT len = 0;
9497
9498 HDBC_LOCK(dbc);
9499 ret = drvgetinfo(dbc, type, val, valMax, &len);
9500 HDBC_UNLOCK(dbc);
9501 if (ret == SQL_SUCCESS) {
9502 SQLWCHAR *v = NULL;
9503
9504 switch (type) {
9505 case SQL_USER_NAME:
9506 case SQL_DRIVER_ODBC_VER:
9507 case SQL_DATA_SOURCE_NAME:
9508 case SQL_DRIVER_NAME:
9509 case SQL_DRIVER_VER:
9510 case SQL_ODBC_VER:
9511 case SQL_SERVER_NAME:
9512 case SQL_DATABASE_NAME:
9513 case SQL_SEARCH_PATTERN_ESCAPE:
9514 case SQL_DBMS_NAME:
9515 case SQL_DBMS_VER:
9516 case SQL_NEED_LONG_DATA_LEN:
9517 case SQL_ROW_UPDATES:
9518 case SQL_ACCESSIBLE_PROCEDURES:
9519 case SQL_PROCEDURES:
9520 case SQL_EXPRESSIONS_IN_ORDERBY:
9521 case SQL_ODBC_SQL_OPT_IEF:
9522 case SQL_LIKE_ESCAPE_CLAUSE:
9523 case SQL_ORDER_BY_COLUMNS_IN_SELECT:
9524 case SQL_OUTER_JOINS:
9525 case SQL_COLUMN_ALIAS:
9526 case SQL_ACCESSIBLE_TABLES:
9527 case SQL_MULT_RESULT_SETS:
9528 case SQL_MULTIPLE_ACTIVE_TXN:
9529 case SQL_MAX_ROW_SIZE_INCLUDES_LONG:
9530 case SQL_DATA_SOURCE_READ_ONLY:
9531 #ifdef SQL_DESCRIBE_PARAMETER
9532 case SQL_DESCRIBE_PARAMETER:
9533 #endif
9534 case SQL_IDENTIFIER_QUOTE_CHAR:
9535 case SQL_OWNER_TERM:
9536 case SQL_PROCEDURE_TERM:
9537 case SQL_QUALIFIER_NAME_SEPARATOR:
9538 case SQL_QUALIFIER_TERM:
9539 case SQL_TABLE_TERM:
9540 case SQL_KEYWORDS:
9541 case SQL_SPECIAL_CHARACTERS:
9542 #ifdef SQL_CATALOG_NAME
9543 case SQL_CATALOG_NAME:
9544 #endif
9545 #ifdef SQL_COLLATION_SEQ
9546 case SQL_COLLATION_SEQ:
9547 #endif
9548 if (val) {
9549 if (len > 0) {
9550 v = uc_from_utf((SQLCHAR *) val, len);
9551 if (v) {
9552 int vmax = valMax / sizeof (SQLWCHAR);
9553
9554 uc_strncpy(val, v, vmax);
9555 v[len] = 0;
9556 len = min(vmax, uc_strlen(v));
9557 uc_free(v);
9558 len *= sizeof (SQLWCHAR);
9559 } else {
9560 len = 0;
9561 }
9562 }
9563 if (len <= 0) {
9564 len = 0;
9565 if (valMax >= sizeof (SQLWCHAR)) {
9566 *((SQLWCHAR *)val) = 0;
9567 }
9568 }
9569 } else {
9570 len = 0;
9571 }
9572 break;
9573 }
9574 if (valLen) {
9575 *valLen = len;
9576 }
9577 }
9578 return ret;
9579 }
9580 #endif
9581
9582 /**
9583 * Return information about supported ODBC API functions.
9584 * @param dbc database connection handle
9585 * @param func function code to be retrieved
9586 * @param flags output indicator
9587 * @result ODBC error code
9588 */
9589
9590 SQLRETURN SQL_API
SQLGetFunctions(SQLHDBC dbc,SQLUSMALLINT func,SQLUSMALLINT * flags)9591 SQLGetFunctions(SQLHDBC dbc, SQLUSMALLINT func,
9592 SQLUSMALLINT *flags)
9593 {
9594 DBC *d;
9595 int i;
9596 SQLUSMALLINT exists[100];
9597
9598 if (dbc == SQL_NULL_HDBC) {
9599 return SQL_INVALID_HANDLE;
9600 }
9601 d = (DBC *) dbc;
9602 for (i = 0; i < array_size(exists); i++) {
9603 exists[i] = SQL_FALSE;
9604 }
9605 exists[SQL_API_SQLALLOCCONNECT] = SQL_TRUE;
9606 exists[SQL_API_SQLFETCH] = SQL_TRUE;
9607 exists[SQL_API_SQLALLOCENV] = SQL_TRUE;
9608 exists[SQL_API_SQLFREECONNECT] = SQL_TRUE;
9609 exists[SQL_API_SQLALLOCSTMT] = SQL_TRUE;
9610 exists[SQL_API_SQLFREEENV] = SQL_TRUE;
9611 exists[SQL_API_SQLBINDCOL] = SQL_TRUE;
9612 exists[SQL_API_SQLFREESTMT] = SQL_TRUE;
9613 exists[SQL_API_SQLCANCEL] = SQL_TRUE;
9614 exists[SQL_API_SQLGETCURSORNAME] = SQL_TRUE;
9615 exists[SQL_API_SQLCOLATTRIBUTES] = SQL_TRUE;
9616 exists[SQL_API_SQLNUMRESULTCOLS] = SQL_TRUE;
9617 exists[SQL_API_SQLCONNECT] = SQL_TRUE;
9618 exists[SQL_API_SQLPREPARE] = SQL_TRUE;
9619 exists[SQL_API_SQLDESCRIBECOL] = SQL_TRUE;
9620 exists[SQL_API_SQLROWCOUNT] = SQL_TRUE;
9621 exists[SQL_API_SQLDISCONNECT] = SQL_TRUE;
9622 exists[SQL_API_SQLSETCURSORNAME] = SQL_FALSE;
9623 exists[SQL_API_SQLERROR] = SQL_TRUE;
9624 exists[SQL_API_SQLSETPARAM] = SQL_TRUE;
9625 exists[SQL_API_SQLEXECDIRECT] = SQL_TRUE;
9626 exists[SQL_API_SQLTRANSACT] = SQL_TRUE;
9627 exists[SQL_API_SQLEXECUTE] = SQL_TRUE;
9628 exists[SQL_API_SQLBINDPARAMETER] = SQL_TRUE;
9629 exists[SQL_API_SQLGETTYPEINFO] = SQL_TRUE;
9630 exists[SQL_API_SQLCOLUMNS] = SQL_TRUE;
9631 exists[SQL_API_SQLPARAMDATA] = SQL_TRUE;
9632 exists[SQL_API_SQLDRIVERCONNECT] = SQL_TRUE;
9633 exists[SQL_API_SQLPUTDATA] = SQL_TRUE;
9634 exists[SQL_API_SQLGETCONNECTOPTION] = SQL_TRUE;
9635 exists[SQL_API_SQLSETCONNECTOPTION] = SQL_TRUE;
9636 exists[SQL_API_SQLGETDATA] = SQL_TRUE;
9637 exists[SQL_API_SQLSETSTMTOPTION] = SQL_TRUE;
9638 exists[SQL_API_SQLGETFUNCTIONS] = SQL_TRUE;
9639 exists[SQL_API_SQLSPECIALCOLUMNS] = SQL_TRUE;
9640 exists[SQL_API_SQLGETINFO] = SQL_TRUE;
9641 exists[SQL_API_SQLSTATISTICS] = SQL_TRUE;
9642 exists[SQL_API_SQLGETSTMTOPTION] = SQL_TRUE;
9643 exists[SQL_API_SQLTABLES] = SQL_TRUE;
9644 exists[SQL_API_SQLBROWSECONNECT] = SQL_FALSE;
9645 exists[SQL_API_SQLNUMPARAMS] = SQL_TRUE;
9646 exists[SQL_API_SQLCOLUMNPRIVILEGES] = SQL_FALSE;
9647 exists[SQL_API_SQLPARAMOPTIONS] = SQL_FALSE;
9648 exists[SQL_API_SQLDATASOURCES] = SQL_TRUE;
9649 exists[SQL_API_SQLPRIMARYKEYS] = SQL_TRUE;
9650 exists[SQL_API_SQLDESCRIBEPARAM] = SQL_TRUE;
9651 exists[SQL_API_SQLPROCEDURECOLUMNS] = SQL_TRUE;
9652 exists[SQL_API_SQLDRIVERS] = SQL_FALSE;
9653 exists[SQL_API_SQLPROCEDURES] = SQL_TRUE;
9654 exists[SQL_API_SQLEXTENDEDFETCH] = SQL_TRUE;
9655 exists[SQL_API_SQLSETPOS] = SQL_TRUE;
9656 exists[SQL_API_SQLFOREIGNKEYS] = SQL_TRUE;
9657 exists[SQL_API_SQLSETSCROLLOPTIONS] = SQL_TRUE;
9658 exists[SQL_API_SQLMORERESULTS] = SQL_TRUE;
9659 exists[SQL_API_SQLTABLEPRIVILEGES] = SQL_TRUE;
9660 exists[SQL_API_SQLNATIVESQL] = SQL_TRUE;
9661 if (func == SQL_API_ALL_FUNCTIONS) {
9662 memcpy(flags, exists, sizeof (exists));
9663 } else if (func == SQL_API_ODBC3_ALL_FUNCTIONS) {
9664 int i;
9665 #define SET_EXISTS(x) \
9666 flags[(x) >> 4] |= (1 << ((x) & 0xF))
9667 #define CLR_EXISTS(x) \
9668 flags[(x) >> 4] &= ~(1 << ((x) & 0xF))
9669
9670 memset(flags, 0,
9671 sizeof (SQLUSMALLINT) * SQL_API_ODBC3_ALL_FUNCTIONS_SIZE);
9672 for (i = 0; i < array_size(exists); i++) {
9673 if (exists[i]) {
9674 flags[i >> 4] |= (1 << (i & 0xF));
9675 }
9676 }
9677 SET_EXISTS(SQL_API_SQLALLOCHANDLE);
9678 SET_EXISTS(SQL_API_SQLFREEHANDLE);
9679 SET_EXISTS(SQL_API_SQLGETSTMTATTR);
9680 SET_EXISTS(SQL_API_SQLSETSTMTATTR);
9681 SET_EXISTS(SQL_API_SQLGETCONNECTATTR);
9682 SET_EXISTS(SQL_API_SQLSETCONNECTATTR);
9683 SET_EXISTS(SQL_API_SQLGETENVATTR);
9684 SET_EXISTS(SQL_API_SQLSETENVATTR);
9685 SET_EXISTS(SQL_API_SQLCLOSECURSOR);
9686 SET_EXISTS(SQL_API_SQLBINDPARAM);
9687 #if !defined(HAVE_UNIXODBC) || !(HAVE_UNIXODBC)
9688 /*
9689 * Some unixODBC versions have problems with
9690 * SQLError() vs. SQLGetDiagRec() with loss
9691 * of error/warning messages.
9692 */
9693 SET_EXISTS(SQL_API_SQLGETDIAGREC);
9694 #endif
9695 SET_EXISTS(SQL_API_SQLGETDIAGFIELD);
9696 SET_EXISTS(SQL_API_SQLFETCHSCROLL);
9697 SET_EXISTS(SQL_API_SQLENDTRAN);
9698 } else {
9699 if (func < array_size(exists)) {
9700 *flags = exists[func];
9701 } else {
9702 switch (func) {
9703 case SQL_API_SQLALLOCHANDLE:
9704 case SQL_API_SQLFREEHANDLE:
9705 case SQL_API_SQLGETSTMTATTR:
9706 case SQL_API_SQLSETSTMTATTR:
9707 case SQL_API_SQLGETCONNECTATTR:
9708 case SQL_API_SQLSETCONNECTATTR:
9709 case SQL_API_SQLGETENVATTR:
9710 case SQL_API_SQLSETENVATTR:
9711 case SQL_API_SQLCLOSECURSOR:
9712 case SQL_API_SQLBINDPARAM:
9713 #if !defined(HAVE_UNIXODBC) || !(HAVE_UNIXODBC)
9714 /*
9715 * Some unixODBC versions have problems with
9716 * SQLError() vs. SQLGetDiagRec() with loss
9717 * of error/warning messages.
9718 */
9719 case SQL_API_SQLGETDIAGREC:
9720 #endif
9721 case SQL_API_SQLGETDIAGFIELD:
9722 case SQL_API_SQLFETCHSCROLL:
9723 case SQL_API_SQLENDTRAN:
9724 *flags = SQL_TRUE;
9725 break;
9726 default:
9727 *flags = SQL_FALSE;
9728 }
9729 }
9730 }
9731 return SQL_SUCCESS;
9732 }
9733
9734 /**
9735 * Internal allocate HENV.
9736 * @param env pointer to environment handle
9737 * @result ODBC error code
9738 */
9739
9740 static SQLRETURN
drvallocenv(SQLHENV * env)9741 drvallocenv(SQLHENV *env)
9742 {
9743 ENV *e;
9744
9745 if (env == NULL) {
9746 return SQL_INVALID_HANDLE;
9747 }
9748 e = (ENV *) xmalloc(sizeof (ENV));
9749 if (e == NULL) {
9750 *env = SQL_NULL_HENV;
9751 return SQL_ERROR;
9752 }
9753 e->magic = ENV_MAGIC;
9754 e->ov3 = 0;
9755 #if defined(_WIN32) || defined(_WIN64)
9756 InitializeCriticalSection(&e->cs);
9757 e->owner = 0;
9758 #else
9759 #if defined(ENABLE_NVFS) && (ENABLE_NVFS)
9760 nvfs_init();
9761 #endif
9762 #endif
9763 e->dbcs = NULL;
9764 *env = (SQLHENV) e;
9765 return SQL_SUCCESS;
9766 }
9767
9768 /**
9769 * Allocate HENV.
9770 * @param env pointer to environment handle
9771 * @result ODBC error code
9772 */
9773
9774 SQLRETURN SQL_API
SQLAllocEnv(SQLHENV * env)9775 SQLAllocEnv(SQLHENV *env)
9776 {
9777 return drvallocenv(env);
9778 }
9779
9780 /**
9781 * Internal free HENV.
9782 * @param env environment handle
9783 * @result ODBC error code
9784 */
9785
9786 static SQLRETURN
drvfreeenv(SQLHENV env)9787 drvfreeenv(SQLHENV env)
9788 {
9789 ENV *e;
9790
9791 if (env == SQL_NULL_HENV) {
9792 return SQL_INVALID_HANDLE;
9793 }
9794 e = (ENV *) env;
9795 if (e->magic != ENV_MAGIC) {
9796 return SQL_SUCCESS;
9797 }
9798 #if defined(_WIN32) || defined(_WIN64)
9799 EnterCriticalSection(&e->cs);
9800 e->owner = GetCurrentThreadId();
9801 #endif
9802 if (e->dbcs) {
9803 #if defined(_WIN32) || defined(_WIN64)
9804 LeaveCriticalSection(&e->cs);
9805 e->owner = 0;
9806 #endif
9807 return SQL_ERROR;
9808 }
9809 e->magic = DEAD_MAGIC;
9810 #if defined(_WIN32) || defined(_WIN64)
9811 e->owner = 0;
9812 LeaveCriticalSection(&e->cs);
9813 DeleteCriticalSection(&e->cs);
9814 #endif
9815 xfree(e);
9816 return SQL_SUCCESS;
9817 }
9818
9819 /**
9820 * Free HENV.
9821 * @param env environment handle
9822 * @result ODBC error code
9823 */
9824
9825 SQLRETURN SQL_API
SQLFreeEnv(SQLHENV env)9826 SQLFreeEnv(SQLHENV env)
9827 {
9828 return drvfreeenv(env);
9829 }
9830
9831 /**
9832 * Internal allocate HDBC.
9833 * @param env environment handle
9834 * @param dbc pointer to database connection handle
9835 * @result ODBC error code
9836 */
9837
9838 static SQLRETURN
drvallocconnect(SQLHENV env,SQLHDBC * dbc)9839 drvallocconnect(SQLHENV env, SQLHDBC *dbc)
9840 {
9841 DBC *d;
9842 ENV *e;
9843 const char *verstr;
9844 int maj = 0, min = 0, lev = 0;
9845
9846 if (dbc == NULL) {
9847 return SQL_ERROR;
9848 }
9849 d = (DBC *) xmalloc(sizeof (DBC));
9850 if (d == NULL) {
9851 *dbc = SQL_NULL_HDBC;
9852 return SQL_ERROR;
9853 }
9854 memset(d, 0, sizeof (DBC));
9855 d->curtype = SQL_CURSOR_STATIC;
9856 d->ov3 = &d->ov3val;
9857 verstr = sqlite3_libversion();
9858 sscanf(verstr, "%d.%d.%d", &maj, &min, &lev);
9859 d->version = verinfo(maj & 0xFF, min & 0xFF, lev & 0xFF);
9860 e = (ENV *) env;
9861 #if defined(_WIN32) || defined(_WIN64)
9862 if (e->magic == ENV_MAGIC) {
9863 EnterCriticalSection(&e->cs);
9864 e->owner = GetCurrentThreadId();
9865 }
9866 #endif
9867 if (e->magic == ENV_MAGIC) {
9868 DBC *n, *p;
9869
9870 d->env = e;
9871 d->ov3 = &e->ov3;
9872 p = NULL;
9873 n = e->dbcs;
9874 while (n) {
9875 p = n;
9876 n = n->next;
9877 }
9878 if (p) {
9879 p->next = d;
9880 } else {
9881 e->dbcs = d;
9882 }
9883 }
9884 #if defined(_WIN32) || defined(_WIN64)
9885 if (e->magic == ENV_MAGIC) {
9886 e->owner = 0;
9887 LeaveCriticalSection(&e->cs);
9888 }
9889 d->oemcp = 1;
9890 #endif
9891 d->autocommit = 1;
9892 d->magic = DBC_MAGIC;
9893 *dbc = (SQLHDBC) d;
9894 drvgetgpps(d);
9895 return SQL_SUCCESS;
9896 }
9897
9898 /**
9899 * Allocate HDBC.
9900 * @param env environment handle
9901 * @param dbc pointer to database connection handle
9902 * @result ODBC error code
9903 */
9904
9905 SQLRETURN SQL_API
SQLAllocConnect(SQLHENV env,SQLHDBC * dbc)9906 SQLAllocConnect(SQLHENV env, SQLHDBC *dbc)
9907 {
9908 return drvallocconnect(env, dbc);
9909 }
9910
9911 /**
9912 * Internal free connection (HDBC).
9913 * @param dbc database connection handle
9914 * @result ODBC error code
9915 */
9916
9917 static SQLRETURN
drvfreeconnect(SQLHDBC dbc)9918 drvfreeconnect(SQLHDBC dbc)
9919 {
9920 DBC *d;
9921 ENV *e;
9922 SQLRETURN ret = SQL_ERROR;
9923
9924 if (dbc == SQL_NULL_HDBC) {
9925 return SQL_INVALID_HANDLE;
9926 }
9927 d = (DBC *) dbc;
9928 if (d->magic != DBC_MAGIC) {
9929 return SQL_INVALID_HANDLE;
9930 }
9931 e = d->env;
9932 if (e && e->magic == ENV_MAGIC) {
9933 #if defined(_WIN32) || defined(_WIN64)
9934 EnterCriticalSection(&e->cs);
9935 e->owner = GetCurrentThreadId();
9936 #endif
9937 } else {
9938 e = NULL;
9939 }
9940 if (d->sqlite) {
9941 setstatd(d, -1, "not disconnected", (*d->ov3) ? "HY000" : "S1000");
9942 goto done;
9943 }
9944 while (d->stmt) {
9945 freestmt((HSTMT) d->stmt);
9946 }
9947 if (e && e->magic == ENV_MAGIC) {
9948 DBC *n, *p;
9949
9950 p = NULL;
9951 n = e->dbcs;
9952 while (n) {
9953 if (n == d) {
9954 break;
9955 }
9956 p = n;
9957 n = n->next;
9958 }
9959 if (n) {
9960 if (p) {
9961 p->next = d->next;
9962 } else {
9963 e->dbcs = d->next;
9964 }
9965 }
9966 }
9967 drvrelgpps(d);
9968 d->magic = DEAD_MAGIC;
9969 if (d->trace) {
9970 fclose(d->trace);
9971 }
9972 xfree(d);
9973 ret = SQL_SUCCESS;
9974 done:
9975 #if defined(_WIN32) || defined(_WIN64)
9976 if (e) {
9977 e->owner = 0;
9978 LeaveCriticalSection(&e->cs);
9979 }
9980 #endif
9981 return ret;
9982 }
9983
9984 /**
9985 * Free connection (HDBC).
9986 * @param dbc database connection handle
9987 * @result ODBC error code
9988 */
9989
9990 SQLRETURN SQL_API
SQLFreeConnect(SQLHDBC dbc)9991 SQLFreeConnect(SQLHDBC dbc)
9992 {
9993 return drvfreeconnect(dbc);
9994 }
9995
9996 /**
9997 * Internal get connect attribute of HDBC.
9998 * @param dbc database connection handle
9999 * @param attr option to be retrieved
10000 * @param val output buffer
10001 * @param bufmax size of output buffer
10002 * @param buflen output length
10003 * @result ODBC error code
10004 */
10005
10006 static SQLRETURN
drvgetconnectattr(SQLHDBC dbc,SQLINTEGER attr,SQLPOINTER val,SQLINTEGER bufmax,SQLINTEGER * buflen)10007 drvgetconnectattr(SQLHDBC dbc, SQLINTEGER attr, SQLPOINTER val,
10008 SQLINTEGER bufmax, SQLINTEGER *buflen)
10009 {
10010 DBC *d;
10011 SQLINTEGER dummy;
10012
10013 if (dbc == SQL_NULL_HDBC) {
10014 return SQL_INVALID_HANDLE;
10015 }
10016 d = (DBC *) dbc;
10017 if (!val) {
10018 val = (SQLPOINTER) &dummy;
10019 }
10020 if (!buflen) {
10021 buflen = &dummy;
10022 }
10023 switch (attr) {
10024 case SQL_ATTR_CONNECTION_DEAD:
10025 *((SQLINTEGER *) val) = d->sqlite ? SQL_CD_FALSE : SQL_CD_TRUE;
10026 *buflen = sizeof (SQLINTEGER);
10027 break;
10028 case SQL_ATTR_ACCESS_MODE:
10029 *((SQLINTEGER *) val) = SQL_MODE_READ_WRITE;
10030 *buflen = sizeof (SQLINTEGER);
10031 break;
10032 case SQL_ATTR_AUTOCOMMIT:
10033 *((SQLINTEGER *) val) =
10034 d->autocommit ? SQL_AUTOCOMMIT_ON : SQL_AUTOCOMMIT_OFF;
10035 *buflen = sizeof (SQLINTEGER);
10036 break;
10037 case SQL_ATTR_LOGIN_TIMEOUT:
10038 *((SQLINTEGER *) val) = 100;
10039 *buflen = sizeof (SQLINTEGER);
10040 break;
10041 case SQL_ATTR_ODBC_CURSORS:
10042 *((SQLINTEGER *) val) = SQL_CUR_USE_DRIVER;
10043 *buflen = sizeof (SQLINTEGER);
10044 break;
10045 case SQL_ATTR_PACKET_SIZE:
10046 *((SQLINTEGER *) val) = 16384;
10047 *buflen = sizeof (SQLINTEGER);
10048 break;
10049 case SQL_ATTR_TXN_ISOLATION:
10050 *((SQLINTEGER *) val) = SQL_TXN_SERIALIZABLE;
10051 *buflen = sizeof (SQLINTEGER);
10052 break;
10053 case SQL_ATTR_TRACEFILE:
10054 case SQL_ATTR_TRANSLATE_LIB:
10055 case SQL_ATTR_CURRENT_CATALOG:
10056 *((SQLCHAR *) val) = 0;
10057 *buflen = 0;
10058 break;
10059 case SQL_ATTR_TRACE:
10060 case SQL_ATTR_QUIET_MODE:
10061 case SQL_ATTR_TRANSLATE_OPTION:
10062 case SQL_ATTR_KEYSET_SIZE:
10063 case SQL_ATTR_QUERY_TIMEOUT:
10064 *((SQLINTEGER *) val) = 0;
10065 *buflen = sizeof (SQLINTEGER);
10066 break;
10067 case SQL_ATTR_PARAM_BIND_TYPE:
10068 *((SQLULEN *) val) = SQL_PARAM_BIND_BY_COLUMN;
10069 *buflen = sizeof (SQLUINTEGER);
10070 break;
10071 case SQL_ATTR_ROW_BIND_TYPE:
10072 *((SQLULEN *) val) = SQL_BIND_BY_COLUMN;
10073 *buflen = sizeof (SQLULEN);
10074 break;
10075 case SQL_ATTR_USE_BOOKMARKS:
10076 *((SQLINTEGER *) val) = SQL_UB_OFF;
10077 *buflen = sizeof (SQLINTEGER);
10078 break;
10079 case SQL_ATTR_ASYNC_ENABLE:
10080 *((SQLINTEGER *) val) = SQL_ASYNC_ENABLE_OFF;
10081 *buflen = sizeof (SQLINTEGER);
10082 break;
10083 case SQL_ATTR_NOSCAN:
10084 *((SQLINTEGER *) val) = SQL_NOSCAN_ON;
10085 *buflen = sizeof (SQLINTEGER);
10086 break;
10087 case SQL_ATTR_CONCURRENCY:
10088 *((SQLINTEGER *) val) = SQL_CONCUR_LOCK;
10089 *buflen = sizeof (SQLINTEGER);
10090 break;
10091 #ifdef SQL_ATTR_CURSOR_SENSITIVITY
10092 case SQL_ATTR_CURSOR_SENSITIVITY:
10093 *((SQLINTEGER *) val) = SQL_UNSPECIFIED;
10094 *buflen = sizeof (SQLINTEGER);
10095 break;
10096 #endif
10097 case SQL_ATTR_SIMULATE_CURSOR:
10098 *((SQLINTEGER *) val) = SQL_SC_NON_UNIQUE;
10099 *buflen = sizeof (SQLINTEGER);
10100 break;
10101 case SQL_ATTR_MAX_ROWS:
10102 *((SQLINTEGER *) val) = 0;
10103 *buflen = sizeof (SQLINTEGER);
10104 case SQL_ATTR_MAX_LENGTH:
10105 *((SQLINTEGER *) val) = 1000000000;
10106 *buflen = sizeof (SQLINTEGER);
10107 break;
10108 case SQL_ATTR_CURSOR_TYPE:
10109 *((SQLINTEGER *) val) = d->curtype;
10110 *buflen = sizeof (SQLINTEGER);
10111 break;
10112 case SQL_ATTR_RETRIEVE_DATA:
10113 *((SQLINTEGER *) val) = SQL_RD_ON;
10114 *buflen = sizeof (SQLINTEGER);
10115 break;
10116 #ifdef SQL_ATTR_METADATA_ID
10117 case SQL_ATTR_METADATA_ID:
10118 *((SQLULEN *) val) = SQL_FALSE;
10119 return SQL_SUCCESS;
10120 #endif
10121 default:
10122 *((SQLINTEGER *) val) = 0;
10123 *buflen = sizeof (SQLINTEGER);
10124 setstatd(d, -1, "unsupported connect attribute %d",
10125 (*d->ov3) ? "HYC00" : "S1C00", (int) attr);
10126 return SQL_ERROR;
10127 }
10128 return SQL_SUCCESS;
10129 }
10130
10131 #ifndef WINTERFACE
10132 /**
10133 * Get connect attribute of HDBC.
10134 * @param dbc database connection handle
10135 * @param attr option to be retrieved
10136 * @param val output buffer
10137 * @param bufmax size of output buffer
10138 * @param buflen output length
10139 * @result ODBC error code
10140 */
10141
10142 SQLRETURN SQL_API
SQLGetConnectAttr(SQLHDBC dbc,SQLINTEGER attr,SQLPOINTER val,SQLINTEGER bufmax,SQLINTEGER * buflen)10143 SQLGetConnectAttr(SQLHDBC dbc, SQLINTEGER attr, SQLPOINTER val,
10144 SQLINTEGER bufmax, SQLINTEGER *buflen)
10145 {
10146 SQLRETURN ret;
10147
10148 HDBC_LOCK(dbc);
10149 ret = drvgetconnectattr(dbc, attr, val, bufmax, buflen);
10150 HDBC_UNLOCK(dbc);
10151 return ret;
10152 }
10153 #endif
10154
10155 #ifdef WINTERFACE
10156 /**
10157 * Get connect attribute of HDBC (UNICODE version).
10158 * @param dbc database connection handle
10159 * @param attr option to be retrieved
10160 * @param val output buffer
10161 * @param bufmax size of output buffer
10162 * @param buflen output length
10163 * @result ODBC error code
10164 */
10165
10166 SQLRETURN SQL_API
SQLGetConnectAttrW(SQLHDBC dbc,SQLINTEGER attr,SQLPOINTER val,SQLINTEGER bufmax,SQLINTEGER * buflen)10167 SQLGetConnectAttrW(SQLHDBC dbc, SQLINTEGER attr, SQLPOINTER val,
10168 SQLINTEGER bufmax, SQLINTEGER *buflen)
10169 {
10170 SQLRETURN ret;
10171
10172 HDBC_LOCK(dbc);
10173 ret = drvgetconnectattr(dbc, attr, val, bufmax, buflen);
10174 if (SQL_SUCCEEDED(ret)) {
10175 switch (attr) {
10176 case SQL_ATTR_TRACEFILE:
10177 case SQL_ATTR_CURRENT_CATALOG:
10178 case SQL_ATTR_TRANSLATE_LIB:
10179 if (val && bufmax >= sizeof (SQLWCHAR)) {
10180 *(SQLWCHAR *) val = 0;
10181 }
10182 break;
10183 }
10184 }
10185 HDBC_UNLOCK(dbc);
10186 return ret;
10187 }
10188 #endif
10189
10190 /**
10191 * Internal set connect attribute of HDBC.
10192 * @param dbc database connection handle
10193 * @param attr option to be set
10194 * @param val option value
10195 * @param len size of option
10196 * @result ODBC error code
10197 */
10198
10199 static SQLRETURN
drvsetconnectattr(SQLHDBC dbc,SQLINTEGER attr,SQLPOINTER val,SQLINTEGER len)10200 drvsetconnectattr(SQLHDBC dbc, SQLINTEGER attr, SQLPOINTER val,
10201 SQLINTEGER len)
10202 {
10203 DBC *d;
10204
10205 if (dbc == SQL_NULL_HDBC) {
10206 return SQL_INVALID_HANDLE;
10207 }
10208 d = (DBC *) dbc;
10209 switch (attr) {
10210 case SQL_AUTOCOMMIT:
10211 d->autocommit = val == (SQLPOINTER) SQL_AUTOCOMMIT_ON;
10212 if (d->autocommit && d->intrans) {
10213 return endtran(d, SQL_COMMIT, 1);
10214 } else if (!d->autocommit) {
10215 s3stmt_end(d->cur_s3stmt);
10216 }
10217 return SQL_SUCCESS;
10218 #ifdef SQL_ATTR_METADATA_ID
10219 case SQL_ATTR_METADATA_ID:
10220 if (val == (SQLPOINTER) SQL_FALSE) {
10221 return SQL_SUCCESS;
10222 }
10223 /* fall through */
10224 #endif
10225 default:
10226 setstatd(d, -1, "option value changed", "01S02");
10227 return SQL_SUCCESS_WITH_INFO;
10228 }
10229 return SQL_SUCCESS;
10230 }
10231
10232 #ifndef WINTERFACE
10233 /**
10234 * Set connect attribute of HDBC.
10235 * @param dbc database connection handle
10236 * @param attr option to be set
10237 * @param val option value
10238 * @param len size of option
10239 * @result ODBC error code
10240 */
10241
10242 SQLRETURN SQL_API
SQLSetConnectAttr(SQLHDBC dbc,SQLINTEGER attr,SQLPOINTER val,SQLINTEGER len)10243 SQLSetConnectAttr(SQLHDBC dbc, SQLINTEGER attr, SQLPOINTER val,
10244 SQLINTEGER len)
10245 {
10246 SQLRETURN ret;
10247
10248 HDBC_LOCK(dbc);
10249 ret = drvsetconnectattr(dbc, attr, val, len);
10250 HDBC_UNLOCK(dbc);
10251 return ret;
10252 }
10253 #endif
10254
10255 #ifdef WINTERFACE
10256 /**
10257 * Set connect attribute of HDBC (UNICODE version).
10258 * @param dbc database connection handle
10259 * @param attr option to be set
10260 * @param val option value
10261 * @param len size of option
10262 * @result ODBC error code
10263 */
10264
10265 SQLRETURN SQL_API
SQLSetConnectAttrW(SQLHDBC dbc,SQLINTEGER attr,SQLPOINTER val,SQLINTEGER len)10266 SQLSetConnectAttrW(SQLHDBC dbc, SQLINTEGER attr, SQLPOINTER val,
10267 SQLINTEGER len)
10268 {
10269 SQLRETURN ret;
10270
10271 HDBC_LOCK(dbc);
10272 ret = drvsetconnectattr(dbc, attr, val, len);
10273 HDBC_UNLOCK(dbc);
10274 return ret;
10275 }
10276 #endif
10277
10278 /**
10279 * Internal get connect option of HDBC.
10280 * @param dbc database connection handle
10281 * @param opt option to be retrieved
10282 * @param param output buffer
10283 * @result ODBC error code
10284 */
10285
10286 static SQLRETURN
drvgetconnectoption(SQLHDBC dbc,SQLUSMALLINT opt,SQLPOINTER param)10287 drvgetconnectoption(SQLHDBC dbc, SQLUSMALLINT opt, SQLPOINTER param)
10288 {
10289 DBC *d;
10290 SQLINTEGER dummy;
10291
10292 if (dbc == SQL_NULL_HDBC) {
10293 return SQL_INVALID_HANDLE;
10294 }
10295 d = (DBC *) dbc;
10296 if (!param) {
10297 param = (SQLPOINTER) &dummy;
10298 }
10299 switch (opt) {
10300 case SQL_ACCESS_MODE:
10301 *((SQLINTEGER *) param) = SQL_MODE_READ_WRITE;
10302 break;
10303 case SQL_AUTOCOMMIT:
10304 *((SQLINTEGER *) param) =
10305 d->autocommit ? SQL_AUTOCOMMIT_ON : SQL_AUTOCOMMIT_OFF;
10306 break;
10307 case SQL_LOGIN_TIMEOUT:
10308 *((SQLINTEGER *) param) = 100;
10309 break;
10310 case SQL_ODBC_CURSORS:
10311 *((SQLINTEGER *) param) = SQL_CUR_USE_DRIVER;
10312 break;
10313 case SQL_PACKET_SIZE:
10314 *((SQLINTEGER *) param) = 16384;
10315 break;
10316 case SQL_TXN_ISOLATION:
10317 *((SQLINTEGER *) param) = SQL_TXN_SERIALIZABLE;
10318 break;
10319 case SQL_OPT_TRACE:
10320 case SQL_OPT_TRACEFILE:
10321 case SQL_QUIET_MODE:
10322 case SQL_TRANSLATE_DLL:
10323 case SQL_TRANSLATE_OPTION:
10324 case SQL_KEYSET_SIZE:
10325 case SQL_QUERY_TIMEOUT:
10326 case SQL_BIND_TYPE:
10327 case SQL_CURRENT_QUALIFIER:
10328 *((SQLINTEGER *) param) = 0;
10329 break;
10330 case SQL_USE_BOOKMARKS:
10331 *((SQLINTEGER *) param) = SQL_UB_OFF;
10332 break;
10333 case SQL_ASYNC_ENABLE:
10334 *((SQLINTEGER *) param) = SQL_ASYNC_ENABLE_OFF;
10335 break;
10336 case SQL_NOSCAN:
10337 *((SQLINTEGER *) param) = SQL_NOSCAN_ON;
10338 break;
10339 case SQL_CONCURRENCY:
10340 *((SQLINTEGER *) param) = SQL_CONCUR_LOCK;
10341 break;
10342 case SQL_SIMULATE_CURSOR:
10343 *((SQLINTEGER *) param) = SQL_SC_NON_UNIQUE;
10344 break;
10345 case SQL_MAX_ROWS:
10346 *((SQLINTEGER *) param) = 0;
10347 break;
10348 case SQL_ROWSET_SIZE:
10349 case SQL_MAX_LENGTH:
10350 *((SQLINTEGER *) param) = 1000000000;
10351 break;
10352 case SQL_CURSOR_TYPE:
10353 *((SQLINTEGER *) param) = d->curtype;
10354 break;
10355 case SQL_RETRIEVE_DATA:
10356 *((SQLINTEGER *) param) = SQL_RD_ON;
10357 break;
10358 default:
10359 *((SQLINTEGER *) param) = 0;
10360 setstatd(d, -1, "unsupported connect option %d",
10361 (*d->ov3) ? "HYC00" : "S1C00", opt);
10362 return SQL_ERROR;
10363 }
10364 return SQL_SUCCESS;
10365 }
10366
10367 #ifndef WINTERFACE
10368 /**
10369 * Get connect option of HDBC.
10370 * @param dbc database connection handle
10371 * @param opt option to be retrieved
10372 * @param param output buffer
10373 * @result ODBC error code
10374 */
10375
10376 SQLRETURN SQL_API
SQLGetConnectOption(SQLHDBC dbc,SQLUSMALLINT opt,SQLPOINTER param)10377 SQLGetConnectOption(SQLHDBC dbc, SQLUSMALLINT opt, SQLPOINTER param)
10378 {
10379 SQLRETURN ret;
10380
10381 HDBC_LOCK(dbc);
10382 ret = drvgetconnectoption(dbc, opt, param);
10383 HDBC_UNLOCK(dbc);
10384 return ret;
10385 }
10386 #endif
10387
10388 #ifdef WINTERFACE
10389 /**
10390 * Get connect option of HDBC (UNICODE version).
10391 * @param dbc database connection handle
10392 * @param opt option to be retrieved
10393 * @param param output buffer
10394 * @result ODBC error code
10395 */
10396
10397 SQLRETURN SQL_API
SQLGetConnectOptionW(SQLHDBC dbc,SQLUSMALLINT opt,SQLPOINTER param)10398 SQLGetConnectOptionW(SQLHDBC dbc, SQLUSMALLINT opt, SQLPOINTER param)
10399 {
10400 SQLRETURN ret;
10401
10402 HDBC_LOCK(dbc);
10403 ret = drvgetconnectoption(dbc, opt, param);
10404 if (SQL_SUCCEEDED(ret)) {
10405 switch (opt) {
10406 case SQL_OPT_TRACEFILE:
10407 case SQL_CURRENT_QUALIFIER:
10408 case SQL_TRANSLATE_DLL:
10409 if (param) {
10410 *(SQLWCHAR *) param = 0;
10411 }
10412 break;
10413 }
10414 }
10415 HDBC_UNLOCK(dbc);
10416 return ret;
10417 }
10418 #endif
10419
10420 /**
10421 * Internal set option on HDBC.
10422 * @param dbc database connection handle
10423 * @param opt option to be set
10424 * @param param option value
10425 * @result ODBC error code
10426 */
10427
10428 static SQLRETURN
drvsetconnectoption(SQLHDBC dbc,SQLUSMALLINT opt,SQLUINTEGER param)10429 drvsetconnectoption(SQLHDBC dbc, SQLUSMALLINT opt, SQLUINTEGER param)
10430 {
10431 DBC *d;
10432
10433 if (dbc == SQL_NULL_HDBC) {
10434 return SQL_INVALID_HANDLE;
10435 }
10436 d = (DBC *) dbc;
10437 switch (opt) {
10438 case SQL_AUTOCOMMIT:
10439 d->autocommit = param == SQL_AUTOCOMMIT_ON;
10440 if (d->autocommit && d->intrans) {
10441 return endtran(d, SQL_COMMIT, 1);
10442 } else if (!d->autocommit) {
10443 s3stmt_end(d->cur_s3stmt);
10444 }
10445 break;
10446 default:
10447 setstatd(d, -1, "option value changed", "01S02");
10448 return SQL_SUCCESS_WITH_INFO;
10449 }
10450 return SQL_SUCCESS;
10451 }
10452
10453 #ifndef WINTERFACE
10454 /**
10455 * Set option on HDBC.
10456 * @param dbc database connection handle
10457 * @param opt option to be set
10458 * @param param option value
10459 * @result ODBC error code
10460 */
10461
10462 SQLRETURN SQL_API
SQLSetConnectOption(SQLHDBC dbc,SQLUSMALLINT opt,SQLULEN param)10463 SQLSetConnectOption(SQLHDBC dbc, SQLUSMALLINT opt, SQLULEN param)
10464 {
10465 SQLRETURN ret;
10466
10467 HDBC_LOCK(dbc);
10468 ret = drvsetconnectoption(dbc, opt, param);
10469 HDBC_UNLOCK(dbc);
10470 return ret;
10471 }
10472 #endif
10473
10474 #ifdef WINTERFACE
10475 /**
10476 * Set option on HDBC (UNICODE version).
10477 * @param dbc database connection handle
10478 * @param opt option to be set
10479 * @param param option value
10480 * @result ODBC error code
10481 */
10482
10483 SQLRETURN SQL_API
SQLSetConnectOptionW(SQLHDBC dbc,SQLUSMALLINT opt,SQLULEN param)10484 SQLSetConnectOptionW(SQLHDBC dbc, SQLUSMALLINT opt, SQLULEN param)
10485 {
10486 SQLRETURN ret;
10487
10488 HDBC_LOCK(dbc);
10489 ret = drvsetconnectoption(dbc, opt, param);
10490 HDBC_UNLOCK(dbc);
10491 return ret;
10492 }
10493 #endif
10494
10495 #if defined(WITHOUT_DRIVERMGR) || (!defined(_WIN32) && !defined(_WIN64))
10496
10497 /**
10498 * Handling of SQLConnect() connection attributes
10499 * for standalone operation without driver manager.
10500 * @param dsn DSN/driver connection string
10501 * @param attr attribute string to be retrieved
10502 * @param out output buffer
10503 * @param outLen length of output buffer
10504 * @result true or false
10505 */
10506
10507 static int
getdsnattr(char * dsn,char * attr,char * out,int outLen)10508 getdsnattr(char *dsn, char *attr, char *out, int outLen)
10509 {
10510 char *str = dsn, *start;
10511 int len = strlen(attr);
10512
10513 while (*str) {
10514 while (*str && *str == ';') {
10515 ++str;
10516 }
10517 start = str;
10518 if ((str = strchr(str, '=')) == NULL) {
10519 return 0;
10520 }
10521 if (str - start == len && strncasecmp(start, attr, len) == 0) {
10522 start = ++str;
10523 while (*str && *str != ';') {
10524 ++str;
10525 }
10526 len = min(outLen - 1, str - start);
10527 strncpy(out, start, len);
10528 out[len] = '\0';
10529 return 1;
10530 }
10531 while (*str && *str != ';') {
10532 ++str;
10533 }
10534 }
10535 return 0;
10536 }
10537 #endif
10538
10539 /**
10540 * Internal connect to SQLite database.
10541 * @param dbc database connection handle
10542 * @param dsn DSN string
10543 * @param dsnLen length of DSN string or SQL_NTS
10544 * @param pwd password or NULL
10545 * @param pwdLen length of password or SQL_NTS
10546 * @param isu true/false: file name is UTF8 encoded
10547 * @result ODBC error code
10548 */
10549
10550 static SQLRETURN
drvconnect(SQLHDBC dbc,SQLCHAR * dsn,SQLSMALLINT dsnLen,char * pwd,int pwdLen,int isu)10551 drvconnect(SQLHDBC dbc, SQLCHAR *dsn, SQLSMALLINT dsnLen, char *pwd,
10552 int pwdLen, int isu)
10553 {
10554 DBC *d;
10555 int len;
10556 SQLRETURN ret;
10557 char buf[SQL_MAX_MESSAGE_LENGTH], dbname[SQL_MAX_MESSAGE_LENGTH / 4];
10558 char busy[SQL_MAX_MESSAGE_LENGTH / 4], tracef[SQL_MAX_MESSAGE_LENGTH];
10559 char loadext[SQL_MAX_MESSAGE_LENGTH];
10560 char sflag[32], spflag[32], ntflag[32], nwflag[32], biflag[32];
10561 char snflag[32], lnflag[32], ncflag[32], fkflag[32], jmode[32];
10562 #if defined(_WIN32) || defined(_WIN64)
10563 char oemcp[32];
10564 #endif
10565
10566 if (dbc == SQL_NULL_HDBC) {
10567 return SQL_INVALID_HANDLE;
10568 }
10569 d = (DBC *) dbc;
10570 if (d->magic != DBC_MAGIC) {
10571 return SQL_INVALID_HANDLE;
10572 }
10573 if (d->sqlite != NULL) {
10574 setstatd(d, -1, "connection already established", "08002");
10575 return SQL_ERROR;
10576 }
10577 buf[0] = '\0';
10578 if (dsnLen == SQL_NTS) {
10579 len = sizeof (buf) - 1;
10580 } else {
10581 len = min(sizeof (buf) - 1, dsnLen);
10582 }
10583 if (dsn != NULL) {
10584 strncpy(buf, (char *) dsn, len);
10585 }
10586 buf[len] = '\0';
10587 if (buf[0] == '\0') {
10588 setstatd(d, -1, "invalid DSN", (*d->ov3) ? "HY090" : "S1090");
10589 return SQL_ERROR;
10590 }
10591 #if defined(_WIN32) || defined(_WIN64)
10592 /*
10593 * When DSN is in UTF it must be converted to ANSI
10594 * here for ANSI SQLGetPrivateProfileString()
10595 */
10596 if (isu) {
10597 char *cdsn = utf_to_wmb(buf, len);
10598
10599 if (!cdsn) {
10600 setstatd(d, -1, "out of memory", (*d->ov3) ? "HY000" : "S1000");
10601 return SQL_ERROR;
10602 }
10603 strcpy(buf, cdsn);
10604 uc_free(cdsn);
10605 }
10606 #endif
10607 busy[0] = '\0';
10608 dbname[0] = '\0';
10609 #ifdef WITHOUT_DRIVERMGR
10610 getdsnattr(buf, "database", dbname, sizeof (dbname));
10611 if (dbname[0] == '\0') {
10612 strncpy(dbname, buf, sizeof (dbname));
10613 dbname[sizeof (dbname) - 1] = '\0';
10614 }
10615 getdsnattr(buf, "timeout", busy, sizeof (busy));
10616 sflag[0] = '\0';
10617 getdsnattr(buf, "stepapi", sflag, sizeof (sflag));
10618 spflag[0] = '\0';
10619 getdsnattr(buf, "syncpragma", spflag, sizeof (spflag));
10620 ntflag[0] = '\0';
10621 getdsnattr(buf, "notxn", ntflag, sizeof (ntflag));
10622 nwflag[0] = '\0';
10623 getdsnattr(buf, "nowchar", nwflag, sizeof (nwflag));
10624 snflag[0] = '\0';
10625 getdsnattr(buf, "shortnames", snflag, sizeof (snflag));
10626 lnflag[0] = '\0';
10627 getdsnattr(buf, "longnames", lnflag, sizeof (lnflag));
10628 ncflag[0] = '\0';
10629 getdsnattr(buf, "nocreat", ncflag, sizeof (ncflag));
10630 fkflag[0] = '\0';
10631 getdsnattr(buf, "fksupport", fkflag, sizeof (fkflag));
10632 loadext[0] = '\0';
10633 getdsnattr(buf, "loadext", loadext, sizeof (loadext));
10634 jmode[0] = '\0';
10635 getdsnattr(buf, "journalmode", jmode, sizeof (jmode));
10636 #if defined(_WIN32) || defined(_WIN64)
10637 oemcp[0] = '\0';
10638 getdsnattr(buf, "oemcp", oemcp, sizeof (oemcp));
10639 #endif
10640 biflag[0] = '\0';
10641 getdsnattr(buf, "bigint", biflag, sizeof (biflag));
10642 #else
10643 SQLGetPrivateProfileString(buf, "timeout", "100000",
10644 busy, sizeof (busy), ODBC_INI);
10645 SQLGetPrivateProfileString(buf, "database", "",
10646 dbname, sizeof (dbname), ODBC_INI);
10647 #if defined(_WIN32) || defined(_WIN64)
10648 /* database name read from registry is not UTF8 !!! */
10649 isu = 0;
10650 #endif
10651 SQLGetPrivateProfileString(buf, "stepapi", "",
10652 sflag, sizeof (sflag), ODBC_INI);
10653 SQLGetPrivateProfileString(buf, "syncpragma", "NORMAL",
10654 spflag, sizeof (spflag), ODBC_INI);
10655 SQLGetPrivateProfileString(buf, "notxn", "",
10656 ntflag, sizeof (ntflag), ODBC_INI);
10657 SQLGetPrivateProfileString(buf, "nowchar", "",
10658 nwflag, sizeof (nwflag), ODBC_INI);
10659 SQLGetPrivateProfileString(buf, "shortnames", "",
10660 snflag, sizeof (snflag), ODBC_INI);
10661 SQLGetPrivateProfileString(buf, "longnames", "",
10662 lnflag, sizeof (lnflag), ODBC_INI);
10663 SQLGetPrivateProfileString(buf, "nocreat", "",
10664 ncflag, sizeof (ncflag), ODBC_INI);
10665 SQLGetPrivateProfileString(buf, "fksupport", "",
10666 fkflag, sizeof (fkflag), ODBC_INI);
10667 SQLGetPrivateProfileString(buf, "loadext", "",
10668 loadext, sizeof (loadext), ODBC_INI);
10669 SQLGetPrivateProfileString(buf, "journalmode", "",
10670 jmode, sizeof (jmode), ODBC_INI);
10671 #if defined(_WIN32) || defined(_WIN64)
10672 SQLGetPrivateProfileString(buf, "oemcp", "1",
10673 oemcp, sizeof (oemcp), ODBC_INI);
10674 #endif
10675 SQLGetPrivateProfileString(buf, "bigint", "",
10676 biflag, sizeof (biflag), ODBC_INI);
10677 #endif
10678 tracef[0] = '\0';
10679 #ifdef WITHOUT_DRIVERMGR
10680 getdsnattr(buf, "tracefile", tracef, sizeof (tracef));
10681 #else
10682 SQLGetPrivateProfileString(buf, "tracefile", "",
10683 tracef, sizeof (tracef), ODBC_INI);
10684 #endif
10685 if (tracef[0] != '\0') {
10686 d->trace = fopen(tracef, "a");
10687 }
10688 d->nowchar = getbool(nwflag);
10689 d->shortnames = getbool(snflag);
10690 d->longnames = getbool(lnflag);
10691 d->nocreat = getbool(ncflag);
10692 d->fksupport = getbool(fkflag);
10693 #if defined(_WIN32) || defined(_WIN64)
10694 d->oemcp = getbool(oemcp);
10695 #else
10696 d->oemcp = 0;
10697 #endif
10698 d->dobigint = getbool(biflag);
10699 d->pwd = pwd;
10700 d->pwdLen = 0;
10701 if (d->pwd) {
10702 d->pwdLen = (pwdLen == SQL_NTS) ? strlen(d->pwd) : pwdLen;
10703 }
10704 ret = dbopen(d, dbname, isu, (char *) dsn, sflag, spflag, ntflag,
10705 jmode, busy);
10706 if (ret == SQL_SUCCESS) {
10707 dbloadext(d, loadext);
10708 }
10709 return ret;
10710 }
10711
10712 #ifndef WINTERFACE
10713 /**
10714 * Connect to SQLite database.
10715 * @param dbc database connection handle
10716 * @param dsn DSN string
10717 * @param dsnLen length of DSN string or SQL_NTS
10718 * @param uid user id string or NULL
10719 * @param uidLen length of user id string or SQL_NTS
10720 * @param pwd password string or NULL
10721 * @param pwdLen length of password string or SQL_NTS
10722 * @result ODBC error code
10723 */
10724
10725 SQLRETURN SQL_API
SQLConnect(SQLHDBC dbc,SQLCHAR * dsn,SQLSMALLINT dsnLen,SQLCHAR * uid,SQLSMALLINT uidLen,SQLCHAR * pwd,SQLSMALLINT pwdLen)10726 SQLConnect(SQLHDBC dbc, SQLCHAR *dsn, SQLSMALLINT dsnLen,
10727 SQLCHAR *uid, SQLSMALLINT uidLen,
10728 SQLCHAR *pwd, SQLSMALLINT pwdLen)
10729 {
10730 SQLRETURN ret;
10731
10732 HDBC_LOCK(dbc);
10733 ret = drvconnect(dbc, dsn, dsnLen, (char *) pwd, pwdLen, 0);
10734 HDBC_UNLOCK(dbc);
10735 return ret;
10736 }
10737 #endif
10738
10739 #ifdef WINTERFACE
10740 /**
10741 * Connect to SQLite database.
10742 * @param dbc database connection handle
10743 * @param dsn DSN string
10744 * @param dsnLen length of DSN string or SQL_NTS
10745 * @param uid user id string or NULL
10746 * @param uidLen length of user id string or SQL_NTS
10747 * @param pwd password string or NULL
10748 * @param pwdLen length of password string or SQL_NTS
10749 * @result ODBC error code
10750 */
10751
10752 SQLRETURN SQL_API
SQLConnectW(SQLHDBC dbc,SQLWCHAR * dsn,SQLSMALLINT dsnLen,SQLWCHAR * uid,SQLSMALLINT uidLen,SQLWCHAR * pwd,SQLSMALLINT pwdLen)10753 SQLConnectW(SQLHDBC dbc, SQLWCHAR *dsn, SQLSMALLINT dsnLen,
10754 SQLWCHAR *uid, SQLSMALLINT uidLen,
10755 SQLWCHAR *pwd, SQLSMALLINT pwdLen)
10756 {
10757 char *dsna = NULL;
10758 char *pwda = NULL;
10759 SQLRETURN ret;
10760
10761 HDBC_LOCK(dbc);
10762 if (dsn) {
10763 dsna = uc_to_utf_c(dsn, dsnLen);
10764 if (!dsna) {
10765 DBC *d = (DBC *) dbc;
10766
10767 setstatd(d, -1, "out of memory", (*d->ov3) ? "HY000" : "S1000");
10768 ret = SQL_ERROR;
10769 goto done;
10770 }
10771 }
10772 if (pwd) {
10773 pwda = uc_to_utf_c(pwd, pwdLen);
10774 if (!pwda) {
10775 DBC *d = (DBC *) dbc;
10776
10777 setstatd(d, -1, "out of memory", (*d->ov3) ? "HY000" : "S1000");
10778 ret = SQL_ERROR;
10779 goto done;
10780 }
10781 }
10782 ret = drvconnect(dbc, (SQLCHAR *) dsna, SQL_NTS, pwda, SQL_NTS, 1);
10783 done:
10784 HDBC_UNLOCK(dbc);
10785 uc_free(dsna);
10786 uc_free(pwda);
10787 return ret;
10788 }
10789 #endif
10790
10791 /**
10792 * Internal disconnect given HDBC.
10793 * @param dbc database connection handle
10794 * @result ODBC error code
10795 */
10796
10797 static SQLRETURN
drvdisconnect(SQLHDBC dbc)10798 drvdisconnect(SQLHDBC dbc)
10799 {
10800 DBC *d;
10801
10802 if (dbc == SQL_NULL_HDBC) {
10803 return SQL_INVALID_HANDLE;
10804 }
10805 d = (DBC *) dbc;
10806 if (d->magic != DBC_MAGIC) {
10807 return SQL_INVALID_HANDLE;
10808 }
10809 if (d->intrans) {
10810 setstatd(d, -1, "incomplete transaction", "25000");
10811 return SQL_ERROR;
10812 }
10813 if (d->cur_s3stmt) {
10814 s3stmt_end(d->cur_s3stmt);
10815 }
10816 if (d->sqlite) {
10817 if (d->trace) {
10818 fprintf(d->trace, "-- sqlite3_close: '%s'\n",
10819 d->dbname);
10820 fflush(d->trace);
10821 }
10822 sqlite3_close(d->sqlite);
10823 d->sqlite = NULL;
10824 }
10825 freep(&d->dbname);
10826 freep(&d->dsn);
10827 return SQL_SUCCESS;
10828 }
10829
10830 /**
10831 * Disconnect given HDBC.
10832 * @param dbc database connection handle
10833 * @result ODBC error code
10834 */
10835
10836 SQLRETURN SQL_API
SQLDisconnect(SQLHDBC dbc)10837 SQLDisconnect(SQLHDBC dbc)
10838 {
10839 SQLRETURN ret;
10840
10841 HDBC_LOCK(dbc);
10842 ret = drvdisconnect(dbc);
10843 HDBC_UNLOCK(dbc);
10844 return ret;
10845 }
10846
10847 #if defined(WITHOUT_DRIVERMGR) || (!defined(_WIN32) && !defined(_WIN64))
10848
10849 /**
10850 * Internal standalone (w/o driver manager) database connect.
10851 * @param dbc database connection handle
10852 * @param hwnd dummy window handle or NULL
10853 * @param connIn driver connect input string
10854 * @param connInLen length of driver connect input string or SQL_NTS
10855 * @param connOut driver connect output string
10856 * @param connOutMax length of driver connect output string
10857 * @param connOutLen output length of driver connect output string
10858 * @param drvcompl completion type
10859 * @result ODBC error code
10860 */
10861
10862 static SQLRETURN
drvdriverconnect(SQLHDBC dbc,SQLHWND hwnd,SQLCHAR * connIn,SQLSMALLINT connInLen,SQLCHAR * connOut,SQLSMALLINT connOutMax,SQLSMALLINT * connOutLen,SQLUSMALLINT drvcompl)10863 drvdriverconnect(SQLHDBC dbc, SQLHWND hwnd,
10864 SQLCHAR *connIn, SQLSMALLINT connInLen,
10865 SQLCHAR *connOut, SQLSMALLINT connOutMax,
10866 SQLSMALLINT *connOutLen, SQLUSMALLINT drvcompl)
10867 {
10868 DBC *d;
10869 int len;
10870 SQLRETURN ret;
10871 char buf[SQL_MAX_MESSAGE_LENGTH * 2], dbname[SQL_MAX_MESSAGE_LENGTH / 4];
10872 char dsn[SQL_MAX_MESSAGE_LENGTH / 4], busy[SQL_MAX_MESSAGE_LENGTH / 4];
10873 char tracef[SQL_MAX_MESSAGE_LENGTH], loadext[SQL_MAX_MESSAGE_LENGTH];
10874 char pwd[SQL_MAX_MESSAGE_LENGTH];
10875 char sflag[32], spflag[32], ntflag[32], snflag[32], lnflag[32];
10876 char ncflag[32], nwflag[32], fkflag[32], jmode[32], biflag[32];
10877
10878 if (dbc == SQL_NULL_HDBC) {
10879 return SQL_INVALID_HANDLE;
10880 }
10881 if (drvcompl != SQL_DRIVER_COMPLETE &&
10882 drvcompl != SQL_DRIVER_COMPLETE_REQUIRED &&
10883 drvcompl != SQL_DRIVER_PROMPT &&
10884 drvcompl != SQL_DRIVER_NOPROMPT) {
10885 return SQL_NO_DATA;
10886 }
10887 d = (DBC *) dbc;
10888 if (d->sqlite) {
10889 setstatd(d, -1, "connection already established", "08002");
10890 return SQL_ERROR;
10891 }
10892 buf[0] = '\0';
10893 if (connInLen == SQL_NTS) {
10894 len = sizeof (buf) - 1;
10895 } else {
10896 len = min(connInLen, sizeof (buf) - 1);
10897 }
10898 if (connIn != NULL) {
10899 strncpy(buf, (char *) connIn, len);
10900 }
10901 buf[len] = '\0';
10902 if (!buf[0]) {
10903 setstatd(d, -1, "invalid connect attributes",
10904 (*d->ov3) ? "HY090" : "S1090");
10905 return SQL_ERROR;
10906 }
10907 dsn[0] = '\0';
10908 getdsnattr(buf, "DSN", dsn, sizeof (dsn));
10909
10910 /* special case: connIn is sole DSN value without keywords */
10911 if (!dsn[0] && !strchr(buf, ';') && !strchr(buf, '=')) {
10912 strncpy(dsn, buf, sizeof (dsn) - 1);
10913 dsn[sizeof (dsn) - 1] = '\0';
10914 }
10915
10916 busy[0] = '\0';
10917 getdsnattr(buf, "timeout", busy, sizeof (busy));
10918 #ifndef WITHOUT_DRIVERMGR
10919 if (dsn[0] && !busy[0]) {
10920 SQLGetPrivateProfileString(dsn, "timeout", "100000",
10921 busy, sizeof (busy), ODBC_INI);
10922 }
10923 #endif
10924 dbname[0] = '\0';
10925 getdsnattr(buf, "database", dbname, sizeof (dbname));
10926 #ifndef WITHOUT_DRIVERMGR
10927 if (dsn[0] && !dbname[0]) {
10928 SQLGetPrivateProfileString(dsn, "database", "",
10929 dbname, sizeof (dbname), ODBC_INI);
10930 }
10931 #endif
10932 sflag[0] = '\0';
10933 getdsnattr(buf, "stepapi", sflag, sizeof (sflag));
10934 #ifndef WITHOUT_DRIVERMGR
10935 if (dsn[0] && !sflag[0]) {
10936 SQLGetPrivateProfileString(dsn, "stepapi", "",
10937 sflag, sizeof (sflag), ODBC_INI);
10938 }
10939 #endif
10940 spflag[0] = '\0';
10941 getdsnattr(buf, "syncpragma", spflag, sizeof (spflag));
10942 #ifndef WITHOUT_DRIVERMGR
10943 if (dsn[0] && !spflag[0]) {
10944 SQLGetPrivateProfileString(dsn, "syncpragma", "NORMAL",
10945 spflag, sizeof (spflag), ODBC_INI);
10946 }
10947 #endif
10948 ntflag[0] = '\0';
10949 getdsnattr(buf, "notxn", ntflag, sizeof (ntflag));
10950 #ifndef WITHOUT_DRIVERMGR
10951 if (dsn[0] && !ntflag[0]) {
10952 SQLGetPrivateProfileString(dsn, "notxn", "",
10953 ntflag, sizeof (ntflag), ODBC_INI);
10954 }
10955 #endif
10956 snflag[0] = '\0';
10957 getdsnattr(buf, "shortnames", snflag, sizeof (snflag));
10958 #ifndef WITHOUT_DRIVERMGR
10959 if (dsn[0] && !snflag[0]) {
10960 SQLGetPrivateProfileString(dsn, "shortnames", "",
10961 snflag, sizeof (snflag), ODBC_INI);
10962 }
10963 #endif
10964 lnflag[0] = '\0';
10965 getdsnattr(buf, "longnames", lnflag, sizeof (lnflag));
10966 #ifndef WITHOUT_DRIVERMGR
10967 if (dsn[0] && !lnflag[0]) {
10968 SQLGetPrivateProfileString(dsn, "longnames", "",
10969 lnflag, sizeof (lnflag), ODBC_INI);
10970 }
10971 #endif
10972 ncflag[0] = '\0';
10973 getdsnattr(buf, "nocreat", ncflag, sizeof (ncflag));
10974 #ifndef WITHOUT_DRIVERMGR
10975 if (dsn[0] && !ncflag[0]) {
10976 SQLGetPrivateProfileString(dsn, "nocreat", "",
10977 ncflag, sizeof (ncflag), ODBC_INI);
10978 }
10979 #endif
10980 nwflag[0] = '\0';
10981 getdsnattr(buf, "nowchar", nwflag, sizeof (nwflag));
10982 #ifndef WITHOUT_DRIVERMGR
10983 if (dsn[0] && !nwflag[0]) {
10984 SQLGetPrivateProfileString(dsn, "nowchar", "",
10985 nwflag, sizeof (nwflag), ODBC_INI);
10986 }
10987 #endif
10988 fkflag[0] = '\0';
10989 getdsnattr(buf, "fksupport", fkflag, sizeof (fkflag));
10990 #ifndef WITHOUT_DRIVERMGR
10991 if (dsn[0] && !fkflag[0]) {
10992 SQLGetPrivateProfileString(dsn, "fksupport", "",
10993 fkflag, sizeof (fkflag), ODBC_INI);
10994 }
10995 #endif
10996 loadext[0] = '\0';
10997 getdsnattr(buf, "loadext", loadext, sizeof (loadext));
10998 #ifndef WITHOUT_DRIVERMGR
10999 if (dsn[0] && !loadext[0]) {
11000 SQLGetPrivateProfileString(dsn, "loadext", "",
11001 loadext, sizeof (loadext), ODBC_INI);
11002 }
11003 #endif
11004 jmode[0] = '\0';
11005 getdsnattr(buf, "journalmode", jmode, sizeof (jmode));
11006 #ifndef WITHOUT_DRIVERMGR
11007 if (dsn[0] && !jmode[0]) {
11008 SQLGetPrivateProfileString(dsn, "journalmode", "",
11009 jmode, sizeof (jmode), ODBC_INI);
11010 }
11011 #endif
11012 biflag[0] = '\0';
11013 getdsnattr(buf, "bigint", biflag, sizeof (biflag));
11014 #ifndef WITHOUT_DRIVERMGR
11015 if (dsn[0] && !biflag[0]) {
11016 SQLGetPrivateProfileString(dsn, "bigint", "",
11017 biflag, sizeof (biflag), ODBC_INI);
11018 }
11019 #endif
11020 pwd[0] = '\0';
11021 getdsnattr(buf, "pwd", pwd, sizeof (pwd));
11022 #ifndef WITHOUT_DRIVERMGR
11023 if (dsn[0] && !pwd[0]) {
11024 SQLGetPrivateProfileString(dsn, "pwd", "",
11025 pwd, sizeof (pwd), ODBC_INI);
11026 }
11027 #endif
11028
11029 if (!dbname[0] && !dsn[0]) {
11030 strcpy(dsn, "SQLite");
11031 strncpy(dbname, buf, sizeof (dbname));
11032 dbname[sizeof (dbname) - 1] = '\0';
11033 }
11034 tracef[0] = '\0';
11035 getdsnattr(buf, "tracefile", tracef, sizeof (tracef));
11036 #ifndef WITHOUT_DRIVERMGR
11037 if (dsn[0] && !tracef[0]) {
11038 SQLGetPrivateProfileString(dsn, "tracefile", "",
11039 tracef, sizeof (tracef), ODBC_INI);
11040 }
11041 #endif
11042 if (connOut || connOutLen) {
11043 int count;
11044
11045 buf[0] = '\0';
11046 count = snprintf(buf, sizeof (buf),
11047 "DSN=%s;Database=%s;StepAPI=%s;Timeout=%s;"
11048 "SyncPragma=%s;NoTXN=%s;ShortNames=%s;LongNames=%s;"
11049 "NoCreat=%s;NoWCHAR=%s;FKSupport=%s;Tracefile=%s;"
11050 "JournalMode=%s;LoadExt=%s;BigInt=%s;PWD=%s",
11051 dsn, dbname, sflag, busy, spflag, ntflag,
11052 snflag, lnflag, ncflag, nwflag, fkflag, tracef,
11053 jmode, loadext, biflag,pwd);
11054 if (count < 0) {
11055 buf[sizeof (buf) - 1] = '\0';
11056 }
11057 len = min(connOutMax - 1, strlen(buf));
11058 if (connOut) {
11059 strncpy((char *) connOut, buf, len);
11060 connOut[len] = '\0';
11061 }
11062 if (connOutLen) {
11063 *connOutLen = len;
11064 }
11065 }
11066 if (tracef[0] != '\0') {
11067 d->trace = fopen(tracef, "a");
11068 }
11069 d->shortnames = getbool(snflag);
11070 d->longnames = getbool(lnflag);
11071 d->nocreat = getbool(ncflag);
11072 d->nowchar = getbool(nwflag);
11073 d->fksupport = getbool(fkflag);
11074 d->dobigint = getbool(biflag);
11075 d->oemcp = 0;
11076 d->pwdLen = strlen(pwd);
11077 d->pwd = (d->pwdLen > 0) ? pwd : NULL;
11078 ret = dbopen(d, dbname, 0, dsn, sflag, spflag, ntflag, jmode, busy);
11079 memset(pwd, 0, sizeof (pwd));
11080 if (ret == SQL_SUCCESS) {
11081 dbloadext(d, loadext);
11082 }
11083 return ret;
11084 }
11085 #endif
11086
11087 /**
11088 * Internal free function for HSTMT.
11089 * @param stmt statement handle
11090 * @result ODBC error code
11091 */
11092
11093 static SQLRETURN
freestmt(SQLHSTMT stmt)11094 freestmt(SQLHSTMT stmt)
11095 {
11096 STMT *s;
11097 DBC *d;
11098
11099 if (stmt == SQL_NULL_HSTMT) {
11100 return SQL_INVALID_HANDLE;
11101 }
11102 s = (STMT *) stmt;
11103 s3stmt_drop(s);
11104 freeresult(s, 1);
11105 freep(&s->query);
11106 d = (DBC *) s->dbc;
11107 if (d && d->magic == DBC_MAGIC) {
11108 STMT *p, *n;
11109
11110 p = NULL;
11111 n = d->stmt;
11112 while (n) {
11113 if (n == s) {
11114 break;
11115 }
11116 p = n;
11117 n = n->next;
11118 }
11119 if (n) {
11120 if (p) {
11121 p->next = s->next;
11122 } else {
11123 d->stmt = s->next;
11124 }
11125 }
11126 }
11127 freeparams(s);
11128 freep(&s->bindparms);
11129 if (s->row_status0 != &s->row_status1) {
11130 freep(&s->row_status0);
11131 s->rowset_size = 1;
11132 s->row_status0 = &s->row_status1;
11133 }
11134 xfree(s);
11135 return SQL_SUCCESS;
11136 }
11137
11138 /**
11139 * Allocate HSTMT given HDBC (driver internal version).
11140 * @param dbc database connection handle
11141 * @param stmt pointer to statement handle
11142 * @result ODBC error code
11143 */
11144
11145 static SQLRETURN
drvallocstmt(SQLHDBC dbc,SQLHSTMT * stmt)11146 drvallocstmt(SQLHDBC dbc, SQLHSTMT *stmt)
11147 {
11148 DBC *d;
11149 STMT *s, *sl, *pl;
11150
11151 if (dbc == SQL_NULL_HDBC) {
11152 return SQL_INVALID_HANDLE;
11153 }
11154 d = (DBC *) dbc;
11155 if (d->magic != DBC_MAGIC || stmt == NULL) {
11156 return SQL_INVALID_HANDLE;
11157 }
11158 s = (STMT *) xmalloc(sizeof (STMT));
11159 if (s == NULL) {
11160 *stmt = SQL_NULL_HSTMT;
11161 return SQL_ERROR;
11162 }
11163 *stmt = (SQLHSTMT) s;
11164 memset(s, 0, sizeof (STMT));
11165 s->dbc = dbc;
11166 s->ov3 = d->ov3;
11167 s->oemcp = &d->oemcp;
11168 s->nowchar[0] = d->nowchar;
11169 s->nowchar[1] = 0;
11170 s->dobigint = d->dobigint;
11171 s->curtype = d->curtype;
11172 s->row_status0 = &s->row_status1;
11173 s->rowset_size = 1;
11174 s->longnames = d->longnames;
11175 s->retr_data = SQL_RD_ON;
11176 s->max_rows = 0;
11177 s->bind_type = SQL_BIND_BY_COLUMN;
11178 s->bind_offs = NULL;
11179 s->paramset_size = 1;
11180 s->parm_bind_type = SQL_PARAM_BIND_BY_COLUMN;
11181 #ifdef _WIN64
11182 sprintf((char *) s->cursorname, "CUR_%I64X", (SQLUBIGINT) *stmt);
11183 #else
11184 sprintf((char *) s->cursorname, "CUR_%016lX", (long) *stmt);
11185 #endif
11186 sl = d->stmt;
11187 pl = NULL;
11188 while (sl) {
11189 pl = sl;
11190 sl = sl->next;
11191 }
11192 if (pl) {
11193 pl->next = s;
11194 } else {
11195 d->stmt = s;
11196 }
11197 return SQL_SUCCESS;
11198 }
11199
11200 /**
11201 * Allocate HSTMT given HDBC.
11202 * @param dbc database connection handle
11203 * @param stmt pointer to statement handle
11204 * @result ODBC error code
11205 */
11206
11207 SQLRETURN SQL_API
SQLAllocStmt(SQLHDBC dbc,SQLHSTMT * stmt)11208 SQLAllocStmt(SQLHDBC dbc, SQLHSTMT *stmt)
11209 {
11210 SQLRETURN ret;
11211
11212 HDBC_LOCK(dbc);
11213 ret = drvallocstmt(dbc, stmt);
11214 HDBC_UNLOCK(dbc);
11215 return ret;
11216 }
11217
11218 /**
11219 * Internal function to perform certain kinds of free/close on STMT.
11220 * @param stmt statement handle
11221 * @param opt SQL_RESET_PARAMS, SQL_UNBIND, SQL_CLOSE, or SQL_DROP
11222 * @result ODBC error code
11223 */
11224
11225 static SQLRETURN
drvfreestmt(SQLHSTMT stmt,SQLUSMALLINT opt)11226 drvfreestmt(SQLHSTMT stmt, SQLUSMALLINT opt)
11227 {
11228 STMT *s;
11229 SQLRETURN ret = SQL_SUCCESS;
11230 SQLHDBC dbc;
11231
11232 if (stmt == SQL_NULL_HSTMT) {
11233 return SQL_INVALID_HANDLE;
11234 }
11235 HSTMT_LOCK(stmt);
11236 s = (STMT *) stmt;
11237 dbc = s->dbc;
11238 switch (opt) {
11239 case SQL_RESET_PARAMS:
11240 freeparams(s);
11241 break;
11242 case SQL_UNBIND:
11243 unbindcols(s);
11244 break;
11245 case SQL_CLOSE:
11246 s3stmt_end_if(s);
11247 freeresult(s, 0);
11248 break;
11249 case SQL_DROP:
11250 s3stmt_end_if(s);
11251 ret = freestmt(stmt);
11252 break;
11253 default:
11254 setstat(s, -1, "unsupported option", (*s->ov3) ? "HYC00" : "S1C00");
11255 ret = SQL_ERROR;
11256 break;
11257 }
11258 HDBC_UNLOCK(dbc);
11259 return ret;
11260 }
11261
11262 /**
11263 * Free HSTMT.
11264 * @param stmt statement handle
11265 * @param opt SQL_RESET_PARAMS, SQL_UNBIND, SQL_CLOSE, or SQL_DROP
11266 * @result ODBC error code
11267 */
11268
11269 SQLRETURN SQL_API
SQLFreeStmt(SQLHSTMT stmt,SQLUSMALLINT opt)11270 SQLFreeStmt(SQLHSTMT stmt, SQLUSMALLINT opt)
11271 {
11272 return drvfreestmt(stmt, opt);
11273 }
11274
11275 /**
11276 * Cancel HSTMT closing cursor.
11277 * @param stmt statement handle
11278 * @result ODBC error code
11279 */
11280
11281 SQLRETURN SQL_API
SQLCancel(SQLHSTMT stmt)11282 SQLCancel(SQLHSTMT stmt)
11283 {
11284 if (stmt != SQL_NULL_HSTMT) {
11285 DBC *d = (DBC *) ((STMT *) stmt)->dbc;
11286 #if defined(_WIN32) || defined(_WIN64)
11287 /* interrupt when other thread owns critical section */
11288 int i;
11289
11290 for (i = 0; i < 2; i++) {
11291 if (d->magic == DBC_MAGIC && d->env &&
11292 d->env->magic == ENV_MAGIC &&
11293 d->env->owner != GetCurrentThreadId() &&
11294 d->env->owner != 0) {
11295 d->busyint = 1;
11296 sqlite3_interrupt(d->sqlite);
11297 }
11298 Sleep(1);
11299 }
11300
11301 #else
11302 if (d->magic == DBC_MAGIC) {
11303 d->busyint = 1;
11304 sqlite3_interrupt(d->sqlite);
11305 }
11306 #endif
11307 }
11308 return drvfreestmt(stmt, SQL_CLOSE);
11309 }
11310
11311 /**
11312 * Internal function to get cursor name of STMT.
11313 * @param stmt statement handle
11314 * @param cursor output buffer
11315 * @param buflen length of output buffer
11316 * @param lenp output length
11317 * @result ODBC error code
11318 */
11319
11320 static SQLRETURN
drvgetcursorname(SQLHSTMT stmt,SQLCHAR * cursor,SQLSMALLINT buflen,SQLSMALLINT * lenp)11321 drvgetcursorname(SQLHSTMT stmt, SQLCHAR *cursor, SQLSMALLINT buflen,
11322 SQLSMALLINT *lenp)
11323 {
11324 STMT *s;
11325
11326 if (stmt == SQL_NULL_HSTMT) {
11327 return SQL_INVALID_HANDLE;
11328 }
11329 s = (STMT *) stmt;
11330 if (lenp && !cursor) {
11331 *lenp = strlen((char *) s->cursorname);
11332 return SQL_SUCCESS;
11333 }
11334 if (cursor) {
11335 if (buflen > 0) {
11336 strncpy((char *) cursor, (char *) s->cursorname, buflen - 1);
11337 cursor[buflen - 1] = '\0';
11338 }
11339 if (lenp) {
11340 *lenp = min(strlen((char *) s->cursorname), buflen - 1);
11341 }
11342 }
11343 return SQL_SUCCESS;
11344 }
11345
11346 #ifndef WINTERFACE
11347 /**
11348 * Get cursor name of STMT.
11349 * @param stmt statement handle
11350 * @param cursor output buffer
11351 * @param buflen length of output buffer
11352 * @param lenp output length
11353 * @result ODBC error code
11354 */
11355
11356 SQLRETURN SQL_API
SQLGetCursorName(SQLHSTMT stmt,SQLCHAR * cursor,SQLSMALLINT buflen,SQLSMALLINT * lenp)11357 SQLGetCursorName(SQLHSTMT stmt, SQLCHAR *cursor, SQLSMALLINT buflen,
11358 SQLSMALLINT *lenp)
11359 {
11360 SQLRETURN ret;
11361 #if defined(_WIN32) || defined(_WIN64)
11362 SQLSMALLINT len = 0;
11363 #endif
11364
11365 HSTMT_LOCK(stmt);
11366 #if defined(_WIN32) || defined(_WIN64)
11367 if (!((STMT *) stmt)->oemcp[0]) {
11368 ret = drvgetcursorname(stmt, cursor, buflen, lenp);
11369 goto done;
11370 }
11371 ret = drvgetcursorname(stmt, cursor, buflen, &len);
11372 if (ret == SQL_SUCCESS) {
11373 char *c = NULL;
11374
11375 if (cursor) {
11376 c = utf_to_wmb((char *) cursor, len);
11377 if (!c) {
11378 ret = nomem((STMT *) stmt);
11379 goto done;
11380 }
11381 c[len] = 0;
11382 len = strlen(c);
11383 if (buflen > 0) {
11384 strncpy((char *) cursor, c, buflen - 1);
11385 cursor[buflen - 1] = 0;
11386 }
11387 uc_free(c);
11388 }
11389 if (lenp) {
11390 *lenp = min(len, buflen - 1);
11391 }
11392 }
11393 done:
11394 ;
11395 #else
11396 ret = drvgetcursorname(stmt, cursor, buflen, lenp);
11397 #endif
11398 HSTMT_UNLOCK(stmt);
11399 return ret;
11400 }
11401 #endif
11402
11403 #ifdef WINTERFACE
11404 /**
11405 * Get cursor name of STMT (UNICODE version).
11406 * @param stmt statement handle
11407 * @param cursor output buffer
11408 * @param buflen length of output buffer
11409 * @param lenp output length
11410 * @result ODBC error code
11411 */
11412
11413 SQLRETURN SQL_API
SQLGetCursorNameW(SQLHSTMT stmt,SQLWCHAR * cursor,SQLSMALLINT buflen,SQLSMALLINT * lenp)11414 SQLGetCursorNameW(SQLHSTMT stmt, SQLWCHAR *cursor, SQLSMALLINT buflen,
11415 SQLSMALLINT *lenp)
11416 {
11417 SQLRETURN ret;
11418 SQLSMALLINT len = 0;
11419
11420 HSTMT_LOCK(stmt);
11421 ret = drvgetcursorname(stmt, (SQLCHAR *) cursor, buflen, &len);
11422 if (ret == SQL_SUCCESS) {
11423 SQLWCHAR *c = NULL;
11424
11425 if (cursor) {
11426 c = uc_from_utf((SQLCHAR *) cursor, len);
11427 if (!c) {
11428 ret = nomem((STMT *) stmt);
11429 goto done;
11430 }
11431 c[len] = 0;
11432 len = uc_strlen(c);
11433 if (buflen > 0) {
11434 uc_strncpy(cursor, c, buflen - 1);
11435 cursor[buflen - 1] = 0;
11436 }
11437 uc_free(c);
11438 }
11439 if (lenp) {
11440 *lenp = min(len, buflen - 1);
11441 }
11442 }
11443 done:
11444 HSTMT_UNLOCK(stmt);
11445 return ret;
11446 }
11447 #endif
11448
11449 /**
11450 * Internal function to set cursor name on STMT.
11451 * @param stmt statement handle
11452 * @param cursor new cursor name
11453 * @param len length of cursor name or SQL_NTS
11454 * @result ODBC error code
11455 */
11456
11457 static SQLRETURN
drvsetcursorname(SQLHSTMT stmt,SQLCHAR * cursor,SQLSMALLINT len)11458 drvsetcursorname(SQLHSTMT stmt, SQLCHAR *cursor, SQLSMALLINT len)
11459 {
11460 STMT *s;
11461
11462 if (stmt == SQL_NULL_HSTMT) {
11463 return SQL_INVALID_HANDLE;
11464 }
11465 s = (STMT *) stmt;
11466 if (!cursor ||
11467 !((cursor[0] >= 'A' && cursor[0] <= 'Z') ||
11468 (cursor[0] >= 'a' && cursor[0] <= 'z'))) {
11469 setstat(s, -1, "invalid cursor name", (*s->ov3) ? "HYC00" : "S1C00");
11470 return SQL_ERROR;
11471 }
11472 if (len == SQL_NTS) {
11473 len = sizeof (s->cursorname) - 1;
11474 } else {
11475 len = min(sizeof (s->cursorname) - 1, len);
11476 }
11477 strncpy((char *) s->cursorname, (char *) cursor, len);
11478 s->cursorname[len] = '\0';
11479 return SQL_SUCCESS;
11480 }
11481
11482 #ifndef WINTERFACE
11483 /**
11484 * Set cursor name on STMT.
11485 * @param stmt statement handle
11486 * @param cursor new cursor name
11487 * @param len length of cursor name or SQL_NTS
11488 * @result ODBC error code
11489 */
11490
11491 SQLRETURN SQL_API
SQLSetCursorName(SQLHSTMT stmt,SQLCHAR * cursor,SQLSMALLINT len)11492 SQLSetCursorName(SQLHSTMT stmt, SQLCHAR *cursor, SQLSMALLINT len)
11493 {
11494 #if defined(_WIN32) || defined(_WIN64)
11495 char *c = NULL;
11496 #endif
11497 SQLRETURN ret;
11498
11499 HSTMT_LOCK(stmt);
11500 #if defined(_WIN32) || defined(_WIN64)
11501 if (!((STMT *) stmt)->oemcp[0]) {
11502 ret = drvsetcursorname(stmt, cursor, len);
11503 goto done2;
11504 }
11505 if (cursor) {
11506 c = wmb_to_utf_c((char *) cursor, len);
11507 if (!c) {
11508 ret = nomem((STMT *) stmt);
11509 goto done;
11510 }
11511 }
11512 ret = drvsetcursorname(stmt, (SQLCHAR *) c, SQL_NTS);
11513 #else
11514 ret = drvsetcursorname(stmt, cursor, len);
11515 #endif
11516 #if defined(_WIN32) || defined(_WIN64)
11517 done:
11518 uc_free(c);
11519 done2:
11520 ;
11521 #endif
11522 HSTMT_UNLOCK(stmt);
11523 return ret;
11524 }
11525 #endif
11526
11527 #ifdef WINTERFACE
11528 /**
11529 * Set cursor name on STMT (UNICODE version).
11530 * @param stmt statement handle
11531 * @param cursor new cursor name
11532 * @param len length of cursor name or SQL_NTS
11533 * @result ODBC error code
11534 */
11535
11536 SQLRETURN SQL_API
SQLSetCursorNameW(SQLHSTMT stmt,SQLWCHAR * cursor,SQLSMALLINT len)11537 SQLSetCursorNameW(SQLHSTMT stmt, SQLWCHAR *cursor, SQLSMALLINT len)
11538 {
11539 char *c = NULL;
11540 SQLRETURN ret;
11541
11542 HSTMT_LOCK(stmt);
11543 if (cursor) {
11544 c = uc_to_utf_c(cursor, len);
11545 if (!c) {
11546 ret = nomem((STMT *) stmt);
11547 goto done;
11548 }
11549 }
11550 ret = drvsetcursorname(stmt, (SQLCHAR *) c, SQL_NTS);
11551 done:
11552 uc_free(c);
11553 HSTMT_UNLOCK(stmt);
11554 return ret;
11555 }
11556 #endif
11557
11558 /**
11559 * Close open cursor.
11560 * @param stmt statement handle
11561 * @return ODBC error code
11562 */
11563
11564 SQLRETURN SQL_API
SQLCloseCursor(SQLHSTMT stmt)11565 SQLCloseCursor(SQLHSTMT stmt)
11566 {
11567 return drvfreestmt(stmt, SQL_CLOSE);
11568 }
11569
11570 /**
11571 * Allocate a HENV, HDBC, or HSTMT handle.
11572 * @param type handle type
11573 * @param input input handle (HENV, HDBC)
11574 * @param output pointer to output handle (HENV, HDBC, HSTMT)
11575 * @result ODBC error code
11576 */
11577
11578 SQLRETURN SQL_API
SQLAllocHandle(SQLSMALLINT type,SQLHANDLE input,SQLHANDLE * output)11579 SQLAllocHandle(SQLSMALLINT type, SQLHANDLE input, SQLHANDLE *output)
11580 {
11581 SQLRETURN ret;
11582
11583 switch (type) {
11584 case SQL_HANDLE_ENV:
11585 ret = drvallocenv((SQLHENV *) output);
11586 if (ret == SQL_SUCCESS) {
11587 ENV *e = (ENV *) *output;
11588
11589 if (e && e->magic == ENV_MAGIC) {
11590 e->ov3 = 1;
11591 }
11592 }
11593 return ret;
11594 case SQL_HANDLE_DBC:
11595 return drvallocconnect((SQLHENV) input, (SQLHDBC *) output);
11596 case SQL_HANDLE_STMT:
11597 HDBC_LOCK((SQLHDBC) input);
11598 ret = drvallocstmt((SQLHDBC) input, (SQLHSTMT *) output);
11599 HDBC_UNLOCK((SQLHDBC) input);
11600 return ret;
11601 }
11602 return SQL_ERROR;
11603 }
11604
11605 /**
11606 * Free a HENV, HDBC, or HSTMT handle.
11607 * @param type handle type
11608 * @param h handle (HENV, HDBC, or HSTMT)
11609 * @result ODBC error code
11610 */
11611
11612 SQLRETURN SQL_API
SQLFreeHandle(SQLSMALLINT type,SQLHANDLE h)11613 SQLFreeHandle(SQLSMALLINT type, SQLHANDLE h)
11614 {
11615 switch (type) {
11616 case SQL_HANDLE_ENV:
11617 return drvfreeenv((SQLHENV) h);
11618 case SQL_HANDLE_DBC:
11619 return drvfreeconnect((SQLHDBC) h);
11620 case SQL_HANDLE_STMT:
11621 return drvfreestmt((SQLHSTMT) h, SQL_DROP);
11622 }
11623 return SQL_ERROR;
11624 }
11625
11626 /**
11627 * Free dynamically allocated column descriptions of STMT.
11628 * @param s statement pointer
11629 */
11630
11631 static void
freedyncols(STMT * s)11632 freedyncols(STMT *s)
11633 {
11634 if (s->dyncols) {
11635 int i;
11636
11637 for (i = 0; i < s->dcols; i++) {
11638 freep(&s->dyncols[i].typename);
11639 }
11640 if (s->cols == s->dyncols) {
11641 s->cols = NULL;
11642 s->ncols = 0;
11643 }
11644 freep(&s->dyncols);
11645 }
11646 s->dcols = 0;
11647 }
11648
11649 /**
11650 * Free statement's result.
11651 * @param s statement pointer
11652 * @param clrcols flag to clear column information
11653 *
11654 * The result rows are free'd using the rowfree function pointer.
11655 * If clrcols is greater than zero, then column bindings and dynamic column
11656 * descriptions are free'd.
11657 * If clrcols is less than zero, then dynamic column descriptions are free'd.
11658 */
11659
11660 static void
freeresult(STMT * s,int clrcols)11661 freeresult(STMT *s, int clrcols)
11662 {
11663 freep(&s->bincache);
11664 s->bincell = NULL;
11665 s->binlen = 0;
11666 if (s->rows) {
11667 if (s->rowfree) {
11668 s->rowfree(s->rows);
11669 s->rowfree = NULL;
11670 }
11671 s->rows = NULL;
11672 }
11673 s->nrows = -1;
11674 if (clrcols > 0) {
11675 freep(&s->bindcols);
11676 s->nbindcols = 0;
11677 }
11678 if (clrcols) {
11679 freedyncols(s);
11680 s->cols = NULL;
11681 s->ncols = 0;
11682 s->nowchar[1] = 0;
11683 }
11684 }
11685
11686 /**
11687 * Reset bound columns to unbound state.
11688 * @param s statement pointer
11689 */
11690
11691 static void
unbindcols(STMT * s)11692 unbindcols(STMT *s)
11693 {
11694 int i;
11695
11696 s->bkmrkcol.type = -1;
11697 s->bkmrkcol.max = 0;
11698 s->bkmrkcol.lenp = NULL;
11699 s->bkmrkcol.valp = NULL;
11700 s->bkmrkcol.index = 0;
11701 s->bkmrkcol.offs = 0;
11702 for (i = 0; s->bindcols && i < s->nbindcols; i++) {
11703 s->bindcols[i].type = -1;
11704 s->bindcols[i].max = 0;
11705 s->bindcols[i].lenp = NULL;
11706 s->bindcols[i].valp = NULL;
11707 s->bindcols[i].index = i;
11708 s->bindcols[i].offs = 0;
11709 }
11710 }
11711
11712 /**
11713 * Reallocate space for bound columns.
11714 * @param s statement pointer
11715 * @param ncols number of columns
11716 * @result ODBC error code
11717 */
11718
11719 static SQLRETURN
mkbindcols(STMT * s,int ncols)11720 mkbindcols(STMT *s, int ncols)
11721 {
11722 if (s->bindcols) {
11723 if (s->nbindcols < ncols) {
11724 int i;
11725 BINDCOL *bindcols =
11726 xrealloc(s->bindcols, ncols * sizeof (BINDCOL));
11727
11728 if (!bindcols) {
11729 return nomem(s);
11730 }
11731 for (i = s->nbindcols; i < ncols; i++) {
11732 bindcols[i].type = -1;
11733 bindcols[i].max = 0;
11734 bindcols[i].lenp = NULL;
11735 bindcols[i].valp = NULL;
11736 bindcols[i].index = i;
11737 bindcols[i].offs = 0;
11738 }
11739 s->bindcols = bindcols;
11740 s->nbindcols = ncols;
11741 }
11742 } else if (ncols > 0) {
11743 s->bindcols = (BINDCOL *) xmalloc(ncols * sizeof (BINDCOL));
11744 if (!s->bindcols) {
11745 return nomem(s);
11746 }
11747 s->nbindcols = ncols;
11748 unbindcols(s);
11749 }
11750 return SQL_SUCCESS;
11751 }
11752
11753 /**
11754 * Internal function to retrieve row data, used by SQLFetch() and
11755 * friends and SQLGetData().
11756 * @param s statement pointer
11757 * @param col column number, 0 based
11758 * @param otype output data type
11759 * @param val output buffer
11760 * @param len length of output buffer
11761 * @param lenp output length
11762 * @param partial flag for partial data retrieval
11763 * @result ODBC error code
11764 */
11765
11766 static SQLRETURN
getrowdata(STMT * s,SQLUSMALLINT col,SQLSMALLINT otype,SQLPOINTER val,SQLINTEGER len,SQLLEN * lenp,int partial)11767 getrowdata(STMT *s, SQLUSMALLINT col, SQLSMALLINT otype,
11768 SQLPOINTER val, SQLINTEGER len, SQLLEN *lenp, int partial)
11769 {
11770 char **data, valdummy[16];
11771 SQLLEN dummy;
11772 int valnull = 0;
11773 int type = otype;
11774
11775 if (!lenp) {
11776 lenp = &dummy;
11777 }
11778 if (!s->rows) {
11779 *lenp = SQL_NULL_DATA;
11780 return SQL_NO_DATA;
11781 }
11782 if (col >= s->ncols) {
11783 setstat(s, -1, "invalid column", (*s->ov3) ? "07009" : "S1002");
11784 return SQL_ERROR;
11785 }
11786 if (s->rowp < 0 || s->rowp >= s->nrows) {
11787 *lenp = SQL_NULL_DATA;
11788 return SQL_NO_DATA;
11789 }
11790 if (s->retr_data != SQL_RD_ON) {
11791 return SQL_SUCCESS;
11792 }
11793 type = mapdeftype(type, s->cols[col].type, s->cols[col].nosign ? 1 : 0,
11794 s->nowchar[0]);
11795 #if (defined(_WIN32) || defined(_WIN64)) && defined(WINTERFACE)
11796 /* MS Access hack part 3 (map SQL_C_DEFAULT to SQL_C_CHAR) */
11797 if (type == SQL_C_WCHAR && otype == SQL_C_DEFAULT) {
11798 type = SQL_C_CHAR;
11799 }
11800 #endif
11801 data = s->rows + s->ncols + (s->rowp * s->ncols) + col;
11802 if (!val) {
11803 valnull = 1;
11804 val = (SQLPOINTER) valdummy;
11805 }
11806 if (*data == NULL) {
11807 *lenp = SQL_NULL_DATA;
11808 switch (type) {
11809 case SQL_C_UTINYINT:
11810 case SQL_C_TINYINT:
11811 case SQL_C_STINYINT:
11812 #ifdef SQL_BIT
11813 case SQL_C_BIT:
11814 #endif
11815 *((char *) val) = 0;
11816 break;
11817 case SQL_C_USHORT:
11818 case SQL_C_SHORT:
11819 case SQL_C_SSHORT:
11820 *((short *) val) = 0;
11821 break;
11822 case SQL_C_ULONG:
11823 case SQL_C_LONG:
11824 case SQL_C_SLONG:
11825 *((SQLINTEGER *) val) = 0;
11826 break;
11827 #ifdef SQL_BIGINT
11828 case SQL_C_SBIGINT:
11829 case SQL_C_UBIGINT:
11830 *((SQLBIGINT *) val) = 0;
11831 break;
11832 #endif
11833 case SQL_C_FLOAT:
11834 *((float *) val) = 0;
11835 break;
11836 case SQL_C_DOUBLE:
11837 *((double *) val) = 0;
11838 break;
11839 case SQL_C_BINARY:
11840 case SQL_C_CHAR:
11841 *((char *) val) = '\0';
11842 break;
11843 #ifdef WCHARSUPPORT
11844 case SQL_C_WCHAR:
11845 *((SQLWCHAR *) val) = '\0';
11846 break;
11847 #endif
11848 #ifdef SQL_C_TYPE_DATE
11849 case SQL_C_TYPE_DATE:
11850 #endif
11851 case SQL_C_DATE:
11852 memset((DATE_STRUCT *) val, 0, sizeof (DATE_STRUCT));
11853 break;
11854 #ifdef SQL_C_TYPE_TIME
11855 case SQL_C_TYPE_TIME:
11856 #endif
11857 case SQL_C_TIME:
11858 memset((TIME_STRUCT *) val, 0, sizeof (TIME_STRUCT));
11859 break;
11860 #ifdef SQL_C_TYPE_TIMESTAMP
11861 case SQL_C_TYPE_TIMESTAMP:
11862 #endif
11863 case SQL_C_TIMESTAMP:
11864 memset((TIMESTAMP_STRUCT *) val, 0, sizeof (TIMESTAMP_STRUCT));
11865 break;
11866 default:
11867 return SQL_ERROR;
11868 }
11869 } else {
11870 char *endp = NULL;
11871 #if defined(_WIN32) || defined(_WIN64)
11872 #ifdef SQL_BIGINT
11873 char endc;
11874 #endif
11875 #endif
11876
11877 switch (type) {
11878 case SQL_C_UTINYINT:
11879 case SQL_C_TINYINT:
11880 case SQL_C_STINYINT:
11881 *((char *) val) = strtol(*data, &endp, 0);
11882 if (endp && endp == *data) {
11883 *lenp = SQL_NULL_DATA;
11884 } else {
11885 *lenp = sizeof (char);
11886 }
11887 break;
11888 #ifdef SQL_BIT
11889 case SQL_C_BIT:
11890 *((char *) val) = getbool(*data);
11891 *lenp = sizeof (char);
11892 break;
11893 #endif
11894 case SQL_C_USHORT:
11895 case SQL_C_SHORT:
11896 case SQL_C_SSHORT:
11897 *((short *) val) = strtol(*data, &endp, 0);
11898 if (endp && endp == *data) {
11899 *lenp = SQL_NULL_DATA;
11900 } else {
11901 *lenp = sizeof (short);
11902 }
11903 break;
11904 case SQL_C_ULONG:
11905 case SQL_C_LONG:
11906 case SQL_C_SLONG:
11907 *((SQLINTEGER *) val) = strtol(*data, &endp, 0);
11908 if (endp && endp == *data) {
11909 *lenp = SQL_NULL_DATA;
11910 } else {
11911 *lenp = sizeof (SQLINTEGER);
11912 }
11913 break;
11914 #ifdef SQL_BIGINT
11915 case SQL_C_UBIGINT:
11916 #if defined(_WIN32) || defined(_WIN64)
11917 if (sscanf(*data, "%I64u%c", (SQLUBIGINT *) val, &endc) != 1) {
11918 *lenp = SQL_NULL_DATA;
11919 } else {
11920 *lenp = sizeof (SQLUBIGINT);
11921 }
11922 #else
11923 #ifdef __osf__
11924 *((SQLUBIGINT *) val) = strtoul(*data, &endp, 0);
11925 #else
11926 *((SQLUBIGINT *) val) = strtoull(*data, &endp, 0);
11927 #endif
11928 if (endp && endp == *data) {
11929 *lenp = SQL_NULL_DATA;
11930 } else {
11931 *lenp = sizeof (SQLUBIGINT);
11932 }
11933 #endif
11934 break;
11935 case SQL_C_SBIGINT:
11936 #if defined(_WIN32) || defined(_WIN64)
11937 if (sscanf(*data, "%I64d%c", (SQLBIGINT *) val, &endc) != 1) {
11938 *lenp = SQL_NULL_DATA;
11939 } else {
11940 *lenp = sizeof (SQLBIGINT);
11941 }
11942 #else
11943 #ifdef __osf__
11944 *((SQLBIGINT *) val) = strtol(*data, &endp, 0);
11945 #else
11946 *((SQLBIGINT *) val) = strtoll(*data, &endp, 0);
11947 #endif
11948 if (endp && endp == *data) {
11949 *lenp = SQL_NULL_DATA;
11950 } else {
11951 *lenp = sizeof (int);
11952 }
11953 #endif
11954 break;
11955 #endif
11956 case SQL_C_FLOAT:
11957 *((float *) val) = ln_strtod(*data, &endp);
11958 if (endp && endp == *data) {
11959 *lenp = SQL_NULL_DATA;
11960 } else {
11961 *lenp = sizeof (float);
11962 }
11963 break;
11964 case SQL_C_DOUBLE:
11965 *((double *) val) = ln_strtod(*data, &endp);
11966 if (endp && endp == *data) {
11967 *lenp = SQL_NULL_DATA;
11968 } else {
11969 *lenp = sizeof (double);
11970 }
11971 break;
11972 case SQL_C_BINARY: {
11973 int dlen, offs = 0;
11974 char *bin;
11975
11976 if (valnull) {
11977 freep(&s->bincache);
11978 s->binlen = 0;
11979 goto doCHAR;
11980 }
11981 if (*data == s->bincell) {
11982 if (s->bincache) {
11983 bin = s->bincache;
11984 dlen = s->binlen;
11985 } else {
11986 goto doCHAR;
11987 }
11988 } else {
11989 char *dp;
11990 int i;
11991
11992 freep(&s->bincache);
11993 dp = *data;
11994 dlen = strlen(dp);
11995 s->bincell = dp;
11996 s->binlen = 0;
11997 if (!(dp[0] == 'x' || dp[0] == 'X') || dp[1] != '\'' ||
11998 dp[dlen - 1] != '\'') {
11999 goto doCHAR;
12000 }
12001 dlen -= 2;
12002 dp += 2;
12003 dlen = dlen / 2;
12004 s->bincache = bin = xmalloc(dlen);
12005 if (!bin) {
12006 return nomem(s);
12007 }
12008 s->binlen = dlen;
12009 memset(s->bincache, 0, dlen);
12010 for (i = 0; i < dlen; i++) {
12011 char *x;
12012 int v;
12013
12014 if (!*dp || !(x = strchr(xdigits, *dp))) {
12015 goto converr;
12016 }
12017 v = x - xdigits;
12018 bin[i] = (v >= 16) ? ((v - 6) << 4) : (v << 4);
12019 ++dp;
12020 if (!*dp || !(x = strchr(xdigits, *dp))) {
12021 converr:
12022 freep(&s->bincache);
12023 s->binlen = 0;
12024 setstat(s, -1, "conversion error",
12025 (*s->ov3) ? "HY000" : "S1000");
12026 return SQL_ERROR;
12027 }
12028 v = x - xdigits;
12029 bin[i] |= (v >= 16) ? (v - 6) : v;
12030 ++dp;
12031 }
12032 bin = s->bincache;
12033 }
12034 if (partial && len && s->bindcols) {
12035 if (s->bindcols[col].offs >= dlen) {
12036 *lenp = 0;
12037 if (!dlen && s->bindcols[col].offs == dlen) {
12038 s->bindcols[col].offs = 1;
12039 return SQL_SUCCESS;
12040 }
12041 s->bindcols[col].offs = 0;
12042 return SQL_NO_DATA;
12043 }
12044 offs = s->bindcols[col].offs;
12045 dlen -= offs;
12046 }
12047 if (val && len) {
12048 memcpy(val, bin + offs, min(len, dlen));
12049 }
12050 if (len < 1) {
12051 *lenp = dlen;
12052 } else {
12053 *lenp = min(len, dlen);
12054 if (*lenp == len && *lenp != dlen) {
12055 *lenp = SQL_NO_TOTAL;
12056 }
12057 }
12058 if (partial && len && s->bindcols) {
12059 if (*lenp == SQL_NO_TOTAL) {
12060 *lenp = dlen;
12061 s->bindcols[col].offs += len;
12062 setstat(s, -1, "data right truncated", "01004");
12063 if (s->bindcols[col].lenp) {
12064 *s->bindcols[col].lenp = dlen;
12065 }
12066 return SQL_SUCCESS_WITH_INFO;
12067 }
12068 s->bindcols[col].offs += *lenp;
12069 }
12070 if (*lenp == SQL_NO_TOTAL) {
12071 *lenp = dlen;
12072 setstat(s, -1, "data right truncated", "01004");
12073 return SQL_SUCCESS_WITH_INFO;
12074 }
12075 break;
12076 }
12077 doCHAR:
12078 #ifdef WCHARSUPPORT
12079 case SQL_C_WCHAR:
12080 #endif
12081 case SQL_C_CHAR: {
12082 int doz, zlen = len - 1;
12083 int dlen = strlen(*data);
12084 int offs = 0;
12085 #ifdef WCHARSUPPORT
12086 SQLWCHAR *ucdata = NULL;
12087 SQLCHAR *cdata = (SQLCHAR *) *data;
12088 #endif
12089
12090 #if (defined(_WIN32) || defined(_WIN64)) && defined(WINTERFACE)
12091 /* MS Access hack part 2 (reserved error -7748) */
12092 if (!valnull &&
12093 (s->cols == statSpec2P || s->cols == statSpec3P) &&
12094 type == SQL_C_WCHAR) {
12095 if (len > 0 && len <= sizeof (SQLWCHAR)) {
12096 ((char *) val)[0] = data[0][0];
12097 memset((char *) val + 1, 0, len - 1);
12098 *lenp = 1;
12099 return SQL_SUCCESS;
12100 }
12101 }
12102 #endif
12103
12104 #ifdef WCHARSUPPORT
12105 switch (type) {
12106 case SQL_C_CHAR:
12107 doz = 1;
12108 break;
12109 case SQL_C_WCHAR:
12110 doz = sizeof (SQLWCHAR);
12111 break;
12112 default:
12113 doz = 0;
12114 break;
12115 }
12116 if (type == SQL_C_WCHAR) {
12117 ucdata = uc_from_utf(cdata, dlen);
12118 if (!ucdata) {
12119 return nomem(s);
12120 }
12121 dlen = uc_strlen(ucdata) * sizeof (SQLWCHAR);
12122 }
12123 #if defined(_WIN32) || defined(_WIN64)
12124 else if (*s->oemcp && type == SQL_C_CHAR) {
12125 ucdata = (SQLWCHAR *) utf_to_wmb((char *) cdata, dlen);
12126 if (!ucdata) {
12127 return nomem(s);
12128 }
12129 cdata = (SQLCHAR *) ucdata;
12130 dlen = strlen((char *) cdata);
12131 }
12132 #endif
12133 #else
12134 doz = (type == SQL_C_CHAR) ? 1 : 0;
12135 #endif
12136 if (partial && len && s->bindcols) {
12137 if (s->bindcols[col].offs >= dlen) {
12138 #ifdef WCHARSUPPORT
12139 uc_free(ucdata);
12140 #endif
12141 *lenp = 0;
12142 if (doz && val) {
12143 #ifdef WCHARSUPPORT
12144 if (type == SQL_C_WCHAR) {
12145 ((SQLWCHAR *) val)[0] = 0;
12146 } else {
12147 ((char *) val)[0] = '\0';
12148 }
12149 #else
12150 ((char *) val)[0] = '\0';
12151 #endif
12152 }
12153 if (!dlen && s->bindcols[col].offs == dlen) {
12154 s->bindcols[col].offs = 1;
12155 return SQL_SUCCESS;
12156 }
12157 s->bindcols[col].offs = 0;
12158 return SQL_NO_DATA;
12159 }
12160 offs = s->bindcols[col].offs;
12161 dlen -= offs;
12162 }
12163 if (val && !valnull && len) {
12164 #ifdef WCHARSUPPORT
12165 if (type == SQL_C_WCHAR) {
12166 uc_strncpy(val, ucdata + offs / sizeof (SQLWCHAR),
12167 (len - doz) / sizeof (SQLWCHAR));
12168 } else {
12169 strncpy(val, (char *) cdata + offs, len - doz);
12170 }
12171 #else
12172 strncpy(val, *data + offs, len - doz);
12173 #endif
12174 }
12175 if (valnull || len < 1) {
12176 *lenp = dlen;
12177 } else {
12178 *lenp = min(len - doz, dlen);
12179 if (*lenp == len - doz && *lenp != dlen) {
12180 *lenp = SQL_NO_TOTAL;
12181 } else if (*lenp < zlen) {
12182 zlen = *lenp;
12183 }
12184 }
12185 if (len && !valnull && doz) {
12186 #ifdef WCHARSUPPORT
12187 if (type == SQL_C_WCHAR) {
12188 ((SQLWCHAR *) val)[zlen / sizeof (SQLWCHAR)] = 0;
12189 } else {
12190 ((char *) val)[zlen] = '\0';
12191 }
12192 #else
12193 ((char *) val)[zlen] = '\0';
12194 #endif
12195 }
12196 #ifdef WCHARSUPPORT
12197 uc_free(ucdata);
12198 #endif
12199 if (partial && len && s->bindcols) {
12200 if (*lenp == SQL_NO_TOTAL) {
12201 *lenp = dlen;
12202 s->bindcols[col].offs += len - doz;
12203 setstat(s, -1, "data right truncated", "01004");
12204 if (s->bindcols[col].lenp) {
12205 *s->bindcols[col].lenp = dlen;
12206 }
12207 return SQL_SUCCESS_WITH_INFO;
12208 }
12209 s->bindcols[col].offs += *lenp;
12210 }
12211 if (*lenp == SQL_NO_TOTAL) {
12212 *lenp = dlen;
12213 setstat(s, -1, "data right truncated", "01004");
12214 return SQL_SUCCESS_WITH_INFO;
12215 }
12216 break;
12217 }
12218 #ifdef SQL_C_TYPE_DATE
12219 case SQL_C_TYPE_DATE:
12220 #endif
12221 case SQL_C_DATE:
12222 if (str2date(*data, (DATE_STRUCT *) val) < 0) {
12223 *lenp = SQL_NULL_DATA;
12224 } else {
12225 *lenp = sizeof (DATE_STRUCT);
12226 }
12227 break;
12228 #ifdef SQL_C_TYPE_TIME
12229 case SQL_C_TYPE_TIME:
12230 #endif
12231 case SQL_C_TIME:
12232 if (str2time(*data, (TIME_STRUCT *) val) < 0) {
12233 *lenp = SQL_NULL_DATA;
12234 } else {
12235 *lenp = sizeof (TIME_STRUCT);
12236 }
12237 break;
12238 #ifdef SQL_C_TYPE_TIMESTAMP
12239 case SQL_C_TYPE_TIMESTAMP:
12240 #endif
12241 case SQL_C_TIMESTAMP:
12242 if (str2timestamp(*data, (TIMESTAMP_STRUCT *) val) < 0) {
12243 *lenp = SQL_NULL_DATA;
12244 } else {
12245 *lenp = sizeof (TIMESTAMP_STRUCT);
12246 }
12247 switch (s->cols[col].prec) {
12248 case 0:
12249 ((TIMESTAMP_STRUCT *) val)->fraction = 0;
12250 break;
12251 case 1:
12252 ((TIMESTAMP_STRUCT *) val)->fraction /= 100000000;
12253 ((TIMESTAMP_STRUCT *) val)->fraction *= 100000000;
12254 break;
12255 case 2:
12256 ((TIMESTAMP_STRUCT *) val)->fraction /= 10000000;
12257 ((TIMESTAMP_STRUCT *) val)->fraction *= 10000000;
12258 break;
12259 }
12260 break;
12261 default:
12262 return SQL_ERROR;
12263 }
12264 }
12265 return SQL_SUCCESS;
12266 }
12267
12268 /**
12269 * Interal bind C variable to column of result set.
12270 * @param stmt statement handle
12271 * @param col column number, starting at 1
12272 * @param type output type
12273 * @param val output buffer
12274 * @param max length of output buffer
12275 * @param lenp output length pointer
12276 * @result ODBC error code
12277 */
12278
12279 static SQLRETURN
drvbindcol(SQLHSTMT stmt,SQLUSMALLINT col,SQLSMALLINT type,SQLPOINTER val,SQLLEN max,SQLLEN * lenp)12280 drvbindcol(SQLHSTMT stmt, SQLUSMALLINT col, SQLSMALLINT type,
12281 SQLPOINTER val, SQLLEN max, SQLLEN *lenp)
12282 {
12283 STMT *s;
12284 int sz = 0;
12285
12286 if (stmt == SQL_NULL_HSTMT) {
12287 return SQL_INVALID_HANDLE;
12288 }
12289 s = (STMT *) stmt;
12290 if (col < 1) {
12291 if (col == 0 && s->bkmrk && type == SQL_C_BOOKMARK) {
12292 s->bkmrkcol.type = type;
12293 s->bkmrkcol.max = sizeof (SQLINTEGER);
12294 s->bkmrkcol.lenp = lenp;
12295 s->bkmrkcol.valp = val;
12296 s->bkmrkcol.offs = 0;
12297 if (lenp) {
12298 *lenp = 0;
12299 }
12300 return SQL_SUCCESS;
12301 }
12302 setstat(s, -1, "invalid column", (*s->ov3) ? "07009" : "S1002");
12303 return SQL_ERROR;
12304 }
12305 if (mkbindcols(s, col) != SQL_SUCCESS) {
12306 return SQL_ERROR;
12307 }
12308 --col;
12309 if (type == SQL_C_DEFAULT) {
12310 type = mapdeftype(type, s->cols[col].type, 0,
12311 s->nowchar[0] || s->nowchar[1]);
12312 }
12313 switch (type) {
12314 case SQL_C_LONG:
12315 case SQL_C_ULONG:
12316 case SQL_C_SLONG:
12317 sz = sizeof (SQLINTEGER);
12318 break;
12319 case SQL_C_TINYINT:
12320 case SQL_C_UTINYINT:
12321 case SQL_C_STINYINT:
12322 sz = sizeof (SQLCHAR);
12323 break;
12324 case SQL_C_SHORT:
12325 case SQL_C_USHORT:
12326 case SQL_C_SSHORT:
12327 sz = sizeof (short);
12328 break;
12329 case SQL_C_FLOAT:
12330 sz = sizeof (SQLFLOAT);
12331 break;
12332 case SQL_C_DOUBLE:
12333 sz = sizeof (SQLDOUBLE);
12334 break;
12335 case SQL_C_TIMESTAMP:
12336 sz = sizeof (SQL_TIMESTAMP_STRUCT);
12337 break;
12338 case SQL_C_TIME:
12339 sz = sizeof (SQL_TIME_STRUCT);
12340 break;
12341 case SQL_C_DATE:
12342 sz = sizeof (SQL_DATE_STRUCT);
12343 break;
12344 case SQL_C_CHAR:
12345 break;
12346 #ifdef WINTERFACE
12347 case SQL_C_WCHAR:
12348 break;
12349 #endif
12350 #ifdef SQL_C_TYPE_DATE
12351 case SQL_C_TYPE_DATE:
12352 sz = sizeof (SQL_DATE_STRUCT);
12353 break;
12354 #endif
12355 #ifdef SQL_C_TYPE_TIME
12356 case SQL_C_TYPE_TIME:
12357 sz = sizeof (SQL_TIME_STRUCT);
12358 break;
12359 #endif
12360 #ifdef SQL_C_TYPE_TIMESTAMP
12361 case SQL_C_TYPE_TIMESTAMP:
12362 sz = sizeof (SQL_TIMESTAMP_STRUCT);
12363 break;
12364 #endif
12365 #ifdef SQL_BIT
12366 case SQL_C_BIT:
12367 sz = sizeof (SQLCHAR);
12368 break;
12369 #endif
12370 case SQL_C_BINARY:
12371 break;
12372 #ifdef SQL_BIGINT
12373 case SQL_C_SBIGINT:
12374 case SQL_C_UBIGINT:
12375 sz = sizeof (SQLBIGINT);
12376 break;
12377 #endif
12378 default:
12379 if (val == NULL) {
12380 /* fall through, unbinding column */
12381 break;
12382 }
12383 setstat(s, -1, "invalid type %d", "HY003", type);
12384 return SQL_ERROR;
12385 }
12386 if (val == NULL) {
12387 /* unbind column */
12388 s->bindcols[col].type = -1;
12389 s->bindcols[col].max = 0;
12390 s->bindcols[col].lenp = NULL;
12391 s->bindcols[col].valp = NULL;
12392 s->bindcols[col].offs = 0;
12393 } else {
12394 if (sz == 0 && max < 0) {
12395 setstat(s, -1, "invalid length", "HY090");
12396 return SQL_ERROR;
12397 }
12398 s->bindcols[col].type = type;
12399 s->bindcols[col].max = (sz == 0) ? max : sz;
12400 s->bindcols[col].lenp = lenp;
12401 s->bindcols[col].valp = val;
12402 s->bindcols[col].offs = 0;
12403 if (lenp) {
12404 *lenp = 0;
12405 }
12406 }
12407 return SQL_SUCCESS;
12408 }
12409
12410 /**
12411 * Bind C variable to column of result set.
12412 * @param stmt statement handle
12413 * @param col column number, starting at 1
12414 * @param type output type
12415 * @param val output buffer
12416 * @param max length of output buffer
12417 * @param lenp output length pointer
12418 * @result ODBC error code
12419 */
12420
12421 SQLRETURN SQL_API
SQLBindCol(SQLHSTMT stmt,SQLUSMALLINT col,SQLSMALLINT type,SQLPOINTER val,SQLLEN max,SQLLEN * lenp)12422 SQLBindCol(SQLHSTMT stmt, SQLUSMALLINT col, SQLSMALLINT type,
12423 SQLPOINTER val, SQLLEN max, SQLLEN *lenp)
12424 {
12425 SQLRETURN ret;
12426
12427 HSTMT_LOCK(stmt);
12428 ret = drvbindcol(stmt, col, type, val, max, lenp);
12429 HSTMT_UNLOCK(stmt);
12430 return ret;
12431 }
12432
12433 /**
12434 * Columns for result set of SQLTables().
12435 */
12436
12437 static COL tableSpec2[] = {
12438 { "SYSTEM", "COLUMN", "TABLE_QUALIFIER", SCOL_VARCHAR, 50 },
12439 { "SYSTEM", "COLUMN", "TABLE_OWNER", SCOL_VARCHAR, 50 },
12440 { "SYSTEM", "COLUMN", "TABLE_NAME", SCOL_VARCHAR, 255 },
12441 { "SYSTEM", "COLUMN", "TABLE_TYPE", SCOL_VARCHAR, 50 },
12442 { "SYSTEM", "COLUMN", "REMARKS", SCOL_VARCHAR, 50 }
12443 };
12444
12445 static COL tableSpec3[] = {
12446 { "SYSTEM", "COLUMN", "TABLE_CAT", SCOL_VARCHAR, 50 },
12447 { "SYSTEM", "COLUMN", "TABLE_SCHEM", SCOL_VARCHAR, 50 },
12448 { "SYSTEM", "COLUMN", "TABLE_NAME", SCOL_VARCHAR, 255 },
12449 { "SYSTEM", "COLUMN", "TABLE_TYPE", SCOL_VARCHAR, 50 },
12450 { "SYSTEM", "COLUMN", "REMARKS", SCOL_VARCHAR, 50 }
12451 };
12452
12453 /**
12454 * Retrieve information on tables and/or views.
12455 * @param stmt statement handle
12456 * @param cat catalog name/pattern or NULL
12457 * @param catLen length of catalog name/pattern or SQL_NTS
12458 * @param schema schema name/pattern or NULL
12459 * @param schemaLen length of schema name/pattern or SQL_NTS
12460 * @param table table name/pattern or NULL
12461 * @param tableLen length of table name/pattern or SQL_NTS
12462 * @param type types of tables string or NULL
12463 * @param typeLen length of types of tables string or SQL_NTS
12464 * @result ODBC error code
12465 */
12466
12467 static SQLRETURN
drvtables(SQLHSTMT stmt,SQLCHAR * cat,SQLSMALLINT catLen,SQLCHAR * schema,SQLSMALLINT schemaLen,SQLCHAR * table,SQLSMALLINT tableLen,SQLCHAR * type,SQLSMALLINT typeLen)12468 drvtables(SQLHSTMT stmt,
12469 SQLCHAR *cat, SQLSMALLINT catLen,
12470 SQLCHAR *schema, SQLSMALLINT schemaLen,
12471 SQLCHAR *table, SQLSMALLINT tableLen,
12472 SQLCHAR *type, SQLSMALLINT typeLen)
12473 {
12474 SQLRETURN ret;
12475 STMT *s;
12476 DBC *d;
12477 int ncols, asize, rc, size, npatt;
12478 char *errp = NULL, *sql, tname[512];
12479 char *where = "(type = 'table' or type = 'view')";
12480
12481 ret = mkresultset(stmt, tableSpec2, array_size(tableSpec2),
12482 tableSpec3, array_size(tableSpec3), &asize);
12483 if (ret != SQL_SUCCESS) {
12484 return ret;
12485 }
12486 s = (STMT *) stmt;
12487 d = (DBC *) s->dbc;
12488 if (type && (typeLen > 0 || typeLen == SQL_NTS) && type[0] == '%') {
12489 int size = 3 * asize;
12490
12491 s->rows = xmalloc(size * sizeof (char *));
12492 if (!s->rows) {
12493 s->nrows = 0;
12494 return nomem(s);
12495 }
12496 memset(s->rows, 0, sizeof (char *) * size);
12497 s->ncols = asize;
12498 s->rows[s->ncols + 0] = "";
12499 s->rows[s->ncols + 1] = "";
12500 s->rows[s->ncols + 2] = "";
12501 s->rows[s->ncols + 3] = "TABLE";
12502 s->rows[s->ncols + 5] = "";
12503 s->rows[s->ncols + 6] = "";
12504 s->rows[s->ncols + 7] = "";
12505 s->rows[s->ncols + 8] = "VIEW";
12506 #ifdef MEMORY_DEBUG
12507 s->rowfree = xfree__;
12508 #else
12509 s->rowfree = sqlite3_free;
12510 #endif
12511 s->nrows = 2;
12512 s->rowp = -1;
12513 return SQL_SUCCESS;
12514 }
12515 if (cat && (catLen > 0 || catLen == SQL_NTS) && cat[0] == '%') {
12516 table = NULL;
12517 goto doit;
12518 }
12519 if (schema && (schemaLen > 0 || schemaLen == SQL_NTS) &&
12520 schema[0] == '%') {
12521 if ((!cat || catLen == 0 || !cat[0]) &&
12522 (!table || tableLen == 0 || !table[0])) {
12523 table = NULL;
12524 goto doit;
12525 }
12526 }
12527 if (type && (typeLen > 0 || typeLen == SQL_NTS) && type[0] != '\0') {
12528 char tmp[256], *t;
12529 int with_view = 0, with_table = 0;
12530
12531 if (typeLen == SQL_NTS) {
12532 strncpy(tmp, (char *) type, sizeof (tmp));
12533 tmp[sizeof (tmp) - 1] = '\0';
12534 } else {
12535 int len = min(sizeof (tmp) - 1, typeLen);
12536
12537 strncpy(tmp, (char *) type, len);
12538 tmp[len] = '\0';
12539 }
12540 t = tmp;
12541 while (*t) {
12542 *t = TOLOWER(*t);
12543 t++;
12544 }
12545 t = tmp;
12546 unescpat(t);
12547 while (t) {
12548 if (t[0] == '\'') {
12549 ++t;
12550 }
12551 if (strncmp(t, "table", 5) == 0) {
12552 with_table++;
12553 } else if (strncmp(t, "view", 4) == 0) {
12554 with_view++;
12555 }
12556 t = strchr(t, ',');
12557 if (t) {
12558 ++t;
12559 }
12560 }
12561 if (with_view && with_table) {
12562 /* where is already preset */
12563 } else if (with_view && !with_table) {
12564 where = "type = 'view'";
12565 } else if (!with_view && with_table) {
12566 where = "type = 'table'";
12567 } else {
12568 return SQL_SUCCESS;
12569 }
12570 }
12571 doit:
12572 if (!table) {
12573 size = 1;
12574 tname[0] = '%';
12575 } else {
12576 if (tableLen == SQL_NTS) {
12577 size = sizeof (tname) - 1;
12578 } else {
12579 size = min(sizeof (tname) - 1, tableLen);
12580 }
12581 strncpy(tname, (char *) table, size);
12582 }
12583 tname[size] = '\0';
12584 npatt = unescpat(tname);
12585 #if defined(_WIN32) || defined(_WIN64)
12586 sql = sqlite3_mprintf("select %s as 'TABLE_QUALIFIER', "
12587 "%s as 'TABLE_OWNER', "
12588 "tbl_name as 'TABLE_NAME', "
12589 "upper(type) as 'TABLE_TYPE', "
12590 "NULL as 'REMARKS' "
12591 "from sqlite_master where %s "
12592 "and tbl_name %s %Q",
12593 d->xcelqrx ? "''" : "NULL",
12594 d->xcelqrx ? "'main'" : "NULL",
12595 where,
12596 npatt ? "like" : "=", tname);
12597 #else
12598 sql = sqlite3_mprintf("select NULL as 'TABLE_QUALIFIER', "
12599 "NULL as 'TABLE_OWNER', "
12600 "tbl_name as 'TABLE_NAME', "
12601 "upper(type) as 'TABLE_TYPE', "
12602 "NULL as 'REMARKS' "
12603 "from sqlite_master where %s "
12604 "and tbl_name %s %Q", where,
12605 npatt ? "like" : "=", tname);
12606 #endif
12607 if (!sql) {
12608 return nomem(s);
12609 }
12610 ret = starttran(s);
12611 if (ret != SQL_SUCCESS) {
12612 sqlite3_free(sql);
12613 return ret;
12614 }
12615 dbtraceapi(d, "sqlite3_get_table", sql);
12616 rc = sqlite3_get_table(d->sqlite, sql, &s->rows, &s->nrows, &ncols, &errp);
12617 sqlite3_free(sql);
12618 if (rc == SQLITE_OK) {
12619 if (ncols != s->ncols) {
12620 freeresult(s, 0);
12621 s->nrows = 0;
12622 } else {
12623 s->rowfree = sqlite3_free_table;
12624 }
12625 } else {
12626 s->nrows = 0;
12627 s->rows = NULL;
12628 s->rowfree = NULL;
12629 }
12630 if (errp) {
12631 sqlite3_free(errp);
12632 errp = NULL;
12633 }
12634 s->rowp = -1;
12635 return SQL_SUCCESS;
12636 }
12637
12638 #ifndef WINTERFACE
12639 /**
12640 * Retrieve information on tables and/or views.
12641 * @param stmt statement handle
12642 * @param cat catalog name/pattern or NULL
12643 * @param catLen length of catalog name/pattern or SQL_NTS
12644 * @param schema schema name/pattern or NULL
12645 * @param schemaLen length of schema name/pattern or SQL_NTS
12646 * @param table table name/pattern or NULL
12647 * @param tableLen length of table name/pattern or SQL_NTS
12648 * @param type types of tables string or NULL
12649 * @param typeLen length of types of tables string or SQL_NTS
12650 * @result ODBC error code
12651 */
12652
12653 SQLRETURN SQL_API
SQLTables(SQLHSTMT stmt,SQLCHAR * cat,SQLSMALLINT catLen,SQLCHAR * schema,SQLSMALLINT schemaLen,SQLCHAR * table,SQLSMALLINT tableLen,SQLCHAR * type,SQLSMALLINT typeLen)12654 SQLTables(SQLHSTMT stmt,
12655 SQLCHAR *cat, SQLSMALLINT catLen,
12656 SQLCHAR *schema, SQLSMALLINT schemaLen,
12657 SQLCHAR *table, SQLSMALLINT tableLen,
12658 SQLCHAR *type, SQLSMALLINT typeLen)
12659 {
12660 #if defined(_WIN32) || defined(_WIN64)
12661 char *c = NULL, *s = NULL, *t = NULL, *y = NULL;
12662 #endif
12663 SQLRETURN ret;
12664
12665 HSTMT_LOCK(stmt);
12666 #if defined(_WIN32) || defined(_WIN64)
12667 if (!((STMT *) stmt)->oemcp[0]) {
12668 ret = drvtables(stmt, cat, catLen, schema, schemaLen,
12669 table, tableLen, type, typeLen);
12670 goto done2;
12671 }
12672 if (cat) {
12673 c = wmb_to_utf_c((char *) cat, catLen);
12674 if (!c) {
12675 ret = nomem((STMT *) stmt);
12676 goto done;
12677 }
12678 }
12679 if (schema) {
12680 s = wmb_to_utf_c((char *) schema, schemaLen);
12681 if (!s) {
12682 ret = nomem((STMT *) stmt);
12683 goto done;
12684 }
12685 }
12686 if (table) {
12687 t = wmb_to_utf_c((char *) table, tableLen);
12688 if (!t) {
12689 ret = nomem((STMT *) stmt);
12690 goto done;
12691 }
12692 }
12693 if (type) {
12694 y = wmb_to_utf_c((char *) type, typeLen);
12695 if (!y) {
12696 ret = nomem((STMT *) stmt);
12697 goto done;
12698 }
12699 }
12700 ret = drvtables(stmt, (SQLCHAR *) c, SQL_NTS, (SQLCHAR *) s, SQL_NTS,
12701 (SQLCHAR *) t, SQL_NTS, (SQLCHAR *) y, SQL_NTS);
12702 #else
12703 ret = drvtables(stmt, cat, catLen, schema, schemaLen,
12704 table, tableLen, type, typeLen);
12705 #endif
12706 #if defined(_WIN32) || defined(_WIN64)
12707 done:
12708 uc_free(y);
12709 uc_free(t);
12710 uc_free(s);
12711 uc_free(c);
12712 done2:
12713 ;
12714 #endif
12715 HSTMT_UNLOCK(stmt);
12716 return ret;
12717 }
12718 #endif
12719
12720 #ifdef WINTERFACE
12721 /**
12722 * Retrieve information on tables and/or views.
12723 * @param stmt statement handle
12724 * @param cat catalog name/pattern or NULL
12725 * @param catLen length of catalog name/pattern or SQL_NTS
12726 * @param schema schema name/pattern or NULL
12727 * @param schemaLen length of schema name/pattern or SQL_NTS
12728 * @param table table name/pattern or NULL
12729 * @param tableLen length of table name/pattern or SQL_NTS
12730 * @param type types of tables string or NULL
12731 * @param typeLen length of types of tables string or SQL_NTS
12732 * @result ODBC error code
12733 */
12734
12735 SQLRETURN SQL_API
SQLTablesW(SQLHSTMT stmt,SQLWCHAR * cat,SQLSMALLINT catLen,SQLWCHAR * schema,SQLSMALLINT schemaLen,SQLWCHAR * table,SQLSMALLINT tableLen,SQLWCHAR * type,SQLSMALLINT typeLen)12736 SQLTablesW(SQLHSTMT stmt,
12737 SQLWCHAR *cat, SQLSMALLINT catLen,
12738 SQLWCHAR *schema, SQLSMALLINT schemaLen,
12739 SQLWCHAR *table, SQLSMALLINT tableLen,
12740 SQLWCHAR *type, SQLSMALLINT typeLen)
12741 {
12742 char *c = NULL, *s = NULL, *t = NULL, *y = NULL;
12743 SQLRETURN ret;
12744
12745 HSTMT_LOCK(stmt);
12746 if (cat) {
12747 c = uc_to_utf_c(cat, catLen);
12748 if (!c) {
12749 ret = nomem((STMT *) stmt);
12750 goto done;
12751 }
12752 }
12753 if (schema) {
12754 s = uc_to_utf_c(schema, schemaLen);
12755 if (!s) {
12756 ret = nomem((STMT *) stmt);
12757 goto done;
12758 }
12759 }
12760 if (table) {
12761 t = uc_to_utf_c(table, tableLen);
12762 if (!t) {
12763 ret = nomem((STMT *) stmt);
12764 goto done;
12765 }
12766 }
12767 if (type) {
12768 y = uc_to_utf_c(type, typeLen);
12769 if (!y) {
12770 ret = nomem((STMT *) stmt);
12771 goto done;
12772 }
12773 }
12774 ret = drvtables(stmt, (SQLCHAR *) c, SQL_NTS, (SQLCHAR *) s, SQL_NTS,
12775 (SQLCHAR *) t, SQL_NTS, (SQLCHAR *) y, SQL_NTS);
12776 done:
12777 uc_free(y);
12778 uc_free(t);
12779 uc_free(s);
12780 uc_free(c);
12781 HSTMT_UNLOCK(stmt);
12782 return ret;
12783 }
12784 #endif
12785
12786 /**
12787 * Columns for result set of SQLColumns().
12788 */
12789
12790 static COL colSpec2[] = {
12791 { "SYSTEM", "COLUMN", "TABLE_QUALIFIER", SCOL_VARCHAR, 50 },
12792 { "SYSTEM", "COLUMN", "TABLE_OWNER", SCOL_VARCHAR, 50 },
12793 { "SYSTEM", "COLUMN", "TABLE_NAME", SCOL_VARCHAR, 255 },
12794 { "SYSTEM", "COLUMN", "COLUMN_NAME", SCOL_VARCHAR, 255 },
12795 { "SYSTEM", "COLUMN", "DATA_TYPE", SQL_SMALLINT, 50 },
12796 { "SYSTEM", "COLUMN", "TYPE_NAME", SCOL_VARCHAR, 50 },
12797 { "SYSTEM", "COLUMN", "PRECISION", SQL_INTEGER, 50 },
12798 { "SYSTEM", "COLUMN", "LENGTH", SQL_INTEGER, 50 },
12799 { "SYSTEM", "COLUMN", "SCALE", SQL_SMALLINT, 50 },
12800 { "SYSTEM", "COLUMN", "RADIX", SQL_SMALLINT, 50 },
12801 { "SYSTEM", "COLUMN", "NULLABLE", SQL_SMALLINT, 50 },
12802 { "SYSTEM", "COLUMN", "REMARKS", SCOL_VARCHAR, 50 },
12803 { "SYSTEM", "COLUMN", "COLUMN_DEF", SCOL_VARCHAR, 50 },
12804 { "SYSTEM", "COLUMN", "SQL_DATA_TYPE", SQL_SMALLINT, 50 },
12805 { "SYSTEM", "COLUMN", "SQL_DATETIME_SUB", SQL_SMALLINT, 50 },
12806 { "SYSTEM", "COLUMN", "CHAR_OCTET_LENGTH", SQL_SMALLINT, 50 },
12807 { "SYSTEM", "COLUMN", "ORDINAL_POSITION", SQL_SMALLINT, 50 },
12808 { "SYSTEM", "COLUMN", "IS_NULLABLE", SCOL_VARCHAR, 50 }
12809 };
12810
12811 static COL colSpec3[] = {
12812 { "SYSTEM", "COLUMN", "TABLE_CAT", SCOL_VARCHAR, 50 },
12813 { "SYSTEM", "COLUMN", "TABLE_SCHEM", SCOL_VARCHAR, 50 },
12814 { "SYSTEM", "COLUMN", "TABLE_NAME", SCOL_VARCHAR, 255 },
12815 { "SYSTEM", "COLUMN", "COLUMN_NAME", SCOL_VARCHAR, 255 },
12816 { "SYSTEM", "COLUMN", "DATA_TYPE", SQL_SMALLINT, 50 },
12817 { "SYSTEM", "COLUMN", "TYPE_NAME", SCOL_VARCHAR, 50 },
12818 { "SYSTEM", "COLUMN", "COLUMN_SIZE", SQL_INTEGER, 50 },
12819 { "SYSTEM", "COLUMN", "BUFFER_LENGTH", SQL_INTEGER, 50 },
12820 { "SYSTEM", "COLUMN", "DECIMAL_DIGITS", SQL_SMALLINT, 50 },
12821 { "SYSTEM", "COLUMN", "NUM_PREC_RADIX", SQL_SMALLINT, 50 },
12822 { "SYSTEM", "COLUMN", "NULLABLE", SQL_SMALLINT, 50 },
12823 { "SYSTEM", "COLUMN", "REMARKS", SCOL_VARCHAR, 50 },
12824 { "SYSTEM", "COLUMN", "COLUMN_DEF", SCOL_VARCHAR, 50 },
12825 { "SYSTEM", "COLUMN", "SQL_DATA_TYPE", SQL_SMALLINT, 50 },
12826 { "SYSTEM", "COLUMN", "SQL_DATETIME_SUB", SQL_SMALLINT, 50 },
12827 { "SYSTEM", "COLUMN", "CHAR_OCTET_LENGTH", SQL_SMALLINT, 50 },
12828 { "SYSTEM", "COLUMN", "ORDINAL_POSITION", SQL_SMALLINT, 50 },
12829 { "SYSTEM", "COLUMN", "IS_NULLABLE", SCOL_VARCHAR, 50 }
12830 };
12831
12832 /**
12833 * Internal retrieve column information on table.
12834 * @param stmt statement handle
12835 * @param cat catalog name/pattern or NULL
12836 * @param catLen length of catalog name/pattern or SQL_NTS
12837 * @param schema schema name/pattern or NULL
12838 * @param schemaLen length of schema name/pattern or SQL_NTS
12839 * @param table table name/pattern or NULL
12840 * @param tableLen length of table name/pattern or SQL_NTS
12841 * @param col column name/pattern or NULL
12842 * @param colLen length of column name/pattern or SQL_NTS
12843 * @result ODBC error code
12844 */
12845
12846 static SQLRETURN
drvcolumns(SQLHSTMT stmt,SQLCHAR * cat,SQLSMALLINT catLen,SQLCHAR * schema,SQLSMALLINT schemaLen,SQLCHAR * table,SQLSMALLINT tableLen,SQLCHAR * col,SQLSMALLINT colLen)12847 drvcolumns(SQLHSTMT stmt,
12848 SQLCHAR *cat, SQLSMALLINT catLen,
12849 SQLCHAR *schema, SQLSMALLINT schemaLen,
12850 SQLCHAR *table, SQLSMALLINT tableLen,
12851 SQLCHAR *col, SQLSMALLINT colLen)
12852 {
12853 SQLRETURN sret;
12854 STMT *s;
12855 DBC *d;
12856 int ret, nrows, ncols, asize, i, k, roffs, namec;
12857 int tnrows, tncols, npatt;
12858 PTRDIFF_T size;
12859 char *errp = NULL, *sql, tname[512], cname[512], **rowp, **trows;
12860
12861 sret = mkresultset(stmt, colSpec2, array_size(colSpec2),
12862 colSpec3, array_size(colSpec3), &asize);
12863 if (sret != SQL_SUCCESS) {
12864 return sret;
12865 }
12866 s = (STMT *) stmt;
12867 d = (DBC *) s->dbc;
12868 if (!table) {
12869 size = 1;
12870 tname[0] = '%';
12871 } else {
12872 if (tableLen == SQL_NTS) {
12873 size = sizeof (tname) - 1;
12874 } else {
12875 size = min(sizeof (tname) - 1, tableLen);
12876 }
12877 strncpy(tname, (char *) table, size);
12878 }
12879 tname[size] = '\0';
12880 npatt = unescpat(tname);
12881 size = 0;
12882 if (col) {
12883 if (colLen == SQL_NTS) {
12884 size = sizeof (cname) - 1;
12885 } else {
12886 size = min(sizeof (cname) - 1, colLen);
12887 }
12888 strncpy(cname, (char *) col, size);
12889 }
12890 cname[size] = '\0';
12891 if (!strcmp(cname, "%")) {
12892 cname[0] = '\0';
12893 }
12894 sql = sqlite3_mprintf("select tbl_name from sqlite_master where "
12895 "(type = 'table' or type = 'view') "
12896 "and tbl_name %s %Q", npatt ? "like" : "=", tname);
12897 if (!sql) {
12898 return nomem(s);
12899 }
12900 sret = starttran(s);
12901 if (sret != SQL_SUCCESS) {
12902 sqlite3_free(sql);
12903 return sret;
12904 }
12905 dbtraceapi(d, "sqlite3_get_table", sql);
12906 ret = sqlite3_get_table(d->sqlite, sql, &trows, &tnrows, &tncols, &errp);
12907 sqlite3_free(sql);
12908 if (ret != SQLITE_OK) {
12909 setstat(s, ret, "%s (%d)", (*s->ov3) ? "HY000" : "S1000",
12910 errp ? errp : "unknown error", ret);
12911 if (errp) {
12912 sqlite3_free(errp);
12913 errp = NULL;
12914 }
12915 return SQL_ERROR;
12916 }
12917 if (errp) {
12918 sqlite3_free(errp);
12919 errp = NULL;
12920 }
12921 /* pass 1: compute number of rows of result set */
12922 if (tncols * tnrows <= 0) {
12923 sqlite3_free_table(trows);
12924 return SQL_SUCCESS;
12925 }
12926 size = 0;
12927 for (i = 1; i <= tnrows; i++) {
12928 sql = sqlite3_mprintf("PRAGMA table_info(%Q)", trows[i]);
12929 if (!sql) {
12930 sqlite3_free_table(trows);
12931 return nomem(s);
12932 }
12933 dbtraceapi(d, "sqlite3_get_table", sql);
12934 ret = sqlite3_get_table(d->sqlite, sql, &rowp, &nrows, &ncols, &errp);
12935 sqlite3_free(sql);
12936 if (ret != SQLITE_OK) {
12937 setstat(s, ret, "%s (%d)", (*s->ov3) ? "HY000" : "S1000",
12938 errp ? errp : "unknown error", ret);
12939 if (errp) {
12940 sqlite3_free(errp);
12941 errp = NULL;
12942 }
12943 sqlite3_free_table(trows);
12944 return SQL_ERROR;
12945 }
12946 if (errp) {
12947 sqlite3_free(errp);
12948 errp = NULL;
12949 }
12950 if (ncols * nrows > 0) {
12951 namec = -1;
12952 for (k = 0; k < ncols; k++) {
12953 if (strcmp(rowp[k], "name") == 0) {
12954 namec = k;
12955 break;
12956 }
12957 }
12958 if (cname[0]) {
12959 if (namec >= 0) {
12960 for (k = 1; k <= nrows; k++) {
12961 if (namematch(rowp[k * ncols + namec], cname, 1)) {
12962 size++;
12963 }
12964 }
12965 }
12966 } else {
12967 size += nrows;
12968 }
12969 }
12970 sqlite3_free_table(rowp);
12971 }
12972 /* pass 2: fill result set */
12973 if (size <= 0) {
12974 sqlite3_free_table(trows);
12975 return SQL_SUCCESS;
12976 }
12977 s->nrows = size;
12978 size = (size + 1) * asize;
12979 s->rows = xmalloc((size + 1) * sizeof (char *));
12980 if (!s->rows) {
12981 s->nrows = 0;
12982 sqlite3_free_table(trows);
12983 return nomem(s);
12984 }
12985 s->rows[0] = (char *) size;
12986 s->rows += 1;
12987 memset(s->rows, 0, sizeof (char *) * size);
12988 s->rowfree = freerows;
12989 roffs = 1;
12990 for (i = 1; i <= tnrows; i++) {
12991 sql = sqlite3_mprintf("PRAGMA table_info(%Q)", trows[i]);
12992 if (!sql) {
12993 sqlite3_free_table(trows);
12994 return nomem(s);
12995 }
12996 dbtraceapi(d, "sqlite3_get_table", sql);
12997 ret = sqlite3_get_table(d->sqlite, sql, &rowp, &nrows, &ncols, &errp);
12998 sqlite3_free(sql);
12999 if (ret != SQLITE_OK) {
13000 setstat(s, ret, "%s (%d)", (*s->ov3) ? "HY000" : "S1000",
13001 errp ? errp : "unknown error", ret);
13002 if (errp) {
13003 sqlite3_free(errp);
13004 errp = NULL;
13005 }
13006 sqlite3_free_table(trows);
13007 return SQL_ERROR;
13008 }
13009 if (errp) {
13010 sqlite3_free(errp);
13011 errp = NULL;
13012 }
13013 if (ncols * nrows > 0) {
13014 int m, mr, nr = nrows;
13015
13016 namec = -1;
13017 for (k = 0; k < ncols; k++) {
13018 if (strcmp(rowp[k], "name") == 0) {
13019 namec = k;
13020 break;
13021 }
13022 }
13023 if (cname[0]) {
13024 nr = 0;
13025 if (namec >= 0) {
13026 for (k = 1; k <= nrows; k++) {
13027 if (namematch(rowp[k * ncols + namec], cname, 1)) {
13028 nr++;
13029 }
13030 }
13031 }
13032 }
13033 for (k = 0; k < nr; k++) {
13034 m = asize * (roffs + k);
13035 s->rows[m + 0] = xstrdup("");
13036 #if defined(_WIN32) || defined(_WIN64)
13037 s->rows[m + 1] = xstrdup(d->xcelqrx ? "main" : "");
13038 #else
13039 s->rows[m + 1] = xstrdup("");
13040 #endif
13041 s->rows[m + 2] = xstrdup(trows[i]);
13042 s->rows[m + 8] = xstrdup("10");
13043 s->rows[m + 9] = xstrdup("0");
13044 s->rows[m + 15] = xstrdup("16384");
13045 }
13046 for (k = 0; nr && k < ncols; k++) {
13047 if (strcmp(rowp[k], "cid") == 0) {
13048 for (mr = 0, m = 1; m <= nrows; m++) {
13049 char buf[256];
13050 int ir, coln = k;
13051
13052 if (cname[0] &&
13053 !namematch(rowp[m * ncols + namec], cname, 1)) {
13054 continue;
13055 }
13056 ir = asize * (roffs + mr);
13057 sscanf(rowp[m * ncols + k], "%d", &coln);
13058 sprintf(buf, "%d", coln + 1);
13059 s->rows[ir + 16] = xstrdup(buf);
13060 ++mr;
13061 }
13062 } else if (k == namec) {
13063 for (mr = 0, m = 1; m <= nrows; m++) {
13064 int ir;
13065
13066 if (cname[0] &&
13067 !namematch(rowp[m * ncols + namec], cname, 1)) {
13068 continue;
13069 }
13070 ir = asize * (roffs + mr);
13071 s->rows[ir + 3] = xstrdup(rowp[m * ncols + k]);
13072 ++mr;
13073 }
13074 } else if (strcmp(rowp[k], "notnull") == 0) {
13075 for (mr = 0, m = 1; m <= nrows; m++) {
13076 int ir;
13077
13078 if (cname[0] &&
13079 !namematch(rowp[m * ncols + namec], cname, 1)) {
13080 continue;
13081 }
13082 ir = asize * (roffs + mr);
13083 if (*rowp[m * ncols + k] != '0') {
13084 s->rows[ir + 10] = xstrdup(stringify(SQL_FALSE));
13085 } else {
13086 s->rows[ir + 10] = xstrdup(stringify(SQL_TRUE));
13087 }
13088 s->rows[ir + 17] =
13089 xstrdup((*rowp[m * ncols + k] != '0') ?
13090 "NO" : "YES");
13091 ++mr;
13092 }
13093 } else if (strcmp(rowp[k], "dflt_value") == 0) {
13094 for (mr = 0, m = 1; m <= nrows; m++) {
13095 char *dflt = unquote(rowp[m * ncols + k]);
13096 int ir;
13097
13098 if (cname[0] &&
13099 !namematch(rowp[m * ncols + namec], cname, 1)) {
13100 continue;
13101 }
13102 ir = asize * (roffs + mr);
13103 s->rows[ir + 12] = xstrdup(dflt ? dflt : "NULL");
13104 ++mr;
13105 }
13106 } else if (strcmp(rowp[k], "type") == 0) {
13107 for (mr = 0, m = 1; m <= nrows; m++) {
13108 char *typename = rowp[m * ncols + k];
13109 int sqltype, mm, dd, ir;
13110 char buf[256];
13111
13112 if (cname[0] &&
13113 !namematch(rowp[m * ncols + namec], cname, 1)) {
13114 continue;
13115 }
13116 ir = asize * (roffs + mr);
13117 s->rows[ir + 5] = xstrdup(typename);
13118 sqltype = mapsqltype(typename, NULL, *s->ov3,
13119 s->nowchar[0], s->dobigint);
13120 getmd(typename, sqltype, &mm, &dd);
13121 #ifdef SQL_LONGVARCHAR
13122 if (sqltype == SQL_VARCHAR && mm > 255) {
13123 sqltype = SQL_LONGVARCHAR;
13124 }
13125 #endif
13126 #ifdef WINTERFACE
13127 #ifdef SQL_WLONGVARCHAR
13128 if (sqltype == SQL_WVARCHAR && mm > 255) {
13129 sqltype = SQL_WLONGVARCHAR;
13130 }
13131 #endif
13132 #endif
13133 if (sqltype == SQL_VARBINARY && mm > 255) {
13134 sqltype = SQL_LONGVARBINARY;
13135 }
13136 sprintf(buf, "%d", sqltype);
13137 s->rows[ir + 4] = xstrdup(buf);
13138 s->rows[ir + 13] = xstrdup(buf);
13139 sprintf(buf, "%d", mm);
13140 s->rows[ir + 7] = xstrdup(buf);
13141 sprintf(buf, "%d", dd);
13142 s->rows[ir + 6] = xstrdup(buf);
13143 ++mr;
13144 }
13145 }
13146 }
13147 roffs += nr;
13148 }
13149 sqlite3_free_table(rowp);
13150 }
13151 sqlite3_free_table(trows);
13152 return SQL_SUCCESS;
13153 }
13154
13155 #ifndef WINTERFACE
13156 /**
13157 * Retrieve column information on table.
13158 * @param stmt statement handle
13159 * @param cat catalog name/pattern or NULL
13160 * @param catLen length of catalog name/pattern or SQL_NTS
13161 * @param schema schema name/pattern or NULL
13162 * @param schemaLen length of schema name/pattern or SQL_NTS
13163 * @param table table name/pattern or NULL
13164 * @param tableLen length of table name/pattern or SQL_NTS
13165 * @param col column name/pattern or NULL
13166 * @param colLen length of column name/pattern or SQL_NTS
13167 * @result ODBC error code
13168 */
13169
13170 SQLRETURN SQL_API
SQLColumns(SQLHSTMT stmt,SQLCHAR * cat,SQLSMALLINT catLen,SQLCHAR * schema,SQLSMALLINT schemaLen,SQLCHAR * table,SQLSMALLINT tableLen,SQLCHAR * col,SQLSMALLINT colLen)13171 SQLColumns(SQLHSTMT stmt,
13172 SQLCHAR *cat, SQLSMALLINT catLen,
13173 SQLCHAR *schema, SQLSMALLINT schemaLen,
13174 SQLCHAR *table, SQLSMALLINT tableLen,
13175 SQLCHAR *col, SQLSMALLINT colLen)
13176 {
13177 #if defined(_WIN32) || defined(_WIN64)
13178 char *c = NULL, *s = NULL, *t = NULL, *k = NULL;
13179 #endif
13180 SQLRETURN ret;
13181
13182 HSTMT_LOCK(stmt);
13183 #if defined(_WIN32) || defined(_WIN64)
13184 if (!((STMT *) stmt)->oemcp[0]) {
13185 ret = drvcolumns(stmt, cat, catLen, schema, schemaLen,
13186 table, tableLen, col, colLen);
13187 goto done2;
13188 }
13189 if (cat) {
13190 c = wmb_to_utf_c((char *) cat, catLen);
13191 if (!c) {
13192 ret = nomem((STMT *) stmt);
13193 goto done;
13194 }
13195 }
13196 if (schema) {
13197 s = wmb_to_utf_c((char *) schema, schemaLen);
13198 if (!s) {
13199 ret = nomem((STMT *) stmt);
13200 goto done;
13201 }
13202 }
13203 if (table) {
13204 t = wmb_to_utf_c((char *) table, tableLen);
13205 if (!t) {
13206 ret = nomem((STMT *) stmt);
13207 goto done;
13208 }
13209 }
13210 if (col) {
13211 k = wmb_to_utf_c((char *) col, colLen);
13212 if (!k) {
13213 ret = nomem((STMT *) stmt);
13214 goto done;
13215 }
13216 }
13217 ret = drvcolumns(stmt, (SQLCHAR *) c, SQL_NTS, (SQLCHAR *) s, SQL_NTS,
13218 (SQLCHAR *) t, SQL_NTS, (SQLCHAR *) k, SQL_NTS);
13219 #else
13220 ret = drvcolumns(stmt, cat, catLen, schema, schemaLen,
13221 table, tableLen, col, colLen);
13222 #endif
13223 #if defined(_WIN32) || defined(_WIN64)
13224 done:
13225 uc_free(k);
13226 uc_free(t);
13227 uc_free(s);
13228 uc_free(c);
13229 done2:
13230 ;
13231 #endif
13232 HSTMT_UNLOCK(stmt);
13233 return ret;
13234 }
13235 #endif
13236
13237 #ifdef WINTERFACE
13238 /**
13239 * Retrieve column information on table (UNICODE version).
13240 * @param stmt statement handle
13241 * @param cat catalog name/pattern or NULL
13242 * @param catLen length of catalog name/pattern or SQL_NTS
13243 * @param schema schema name/pattern or NULL
13244 * @param schemaLen length of schema name/pattern or SQL_NTS
13245 * @param table table name/pattern or NULL
13246 * @param tableLen length of table name/pattern or SQL_NTS
13247 * @param col column name/pattern or NULL
13248 * @param colLen length of column name/pattern or SQL_NTS
13249 * @result ODBC error code
13250 */
13251
13252 SQLRETURN SQL_API
SQLColumnsW(SQLHSTMT stmt,SQLWCHAR * cat,SQLSMALLINT catLen,SQLWCHAR * schema,SQLSMALLINT schemaLen,SQLWCHAR * table,SQLSMALLINT tableLen,SQLWCHAR * col,SQLSMALLINT colLen)13253 SQLColumnsW(SQLHSTMT stmt,
13254 SQLWCHAR *cat, SQLSMALLINT catLen,
13255 SQLWCHAR *schema, SQLSMALLINT schemaLen,
13256 SQLWCHAR *table, SQLSMALLINT tableLen,
13257 SQLWCHAR *col, SQLSMALLINT colLen)
13258 {
13259 char *c = NULL, *s = NULL, *t = NULL, *k = NULL;
13260 SQLRETURN ret;
13261
13262 HSTMT_LOCK(stmt);
13263 if (cat) {
13264 c = uc_to_utf_c(cat, catLen);
13265 if (!c) {
13266 ret = nomem((STMT *) stmt);
13267 goto done;
13268 }
13269 }
13270 if (schema) {
13271 s = uc_to_utf_c(schema, schemaLen);
13272 if (!s) {
13273 ret = nomem((STMT *) stmt);
13274 goto done;
13275 }
13276 }
13277 if (table) {
13278 t = uc_to_utf_c(table, tableLen);
13279 if (!t) {
13280 ret = nomem((STMT *) stmt);
13281 goto done;
13282 }
13283 }
13284 if (col) {
13285 k = uc_to_utf_c(col, colLen);
13286 if (!k) {
13287 ret = nomem((STMT *) stmt);
13288 goto done;
13289 }
13290 }
13291 ret = drvcolumns(stmt, (SQLCHAR *) c, SQL_NTS, (SQLCHAR *) s, SQL_NTS,
13292 (SQLCHAR *) t, SQL_NTS, (SQLCHAR *) k, SQL_NTS);
13293 done:
13294 uc_free(k);
13295 uc_free(t);
13296 uc_free(s);
13297 uc_free(c);
13298 HSTMT_UNLOCK(stmt);
13299 return ret;
13300
13301 }
13302 #endif
13303
13304 /**
13305 * Columns for result set of SQLGetTypeInfo().
13306 */
13307
13308 static COL typeSpec2[] = {
13309 { "SYSTEM", "TYPE", "TYPE_NAME", SCOL_VARCHAR, 50 },
13310 { "SYSTEM", "TYPE", "DATA_TYPE", SQL_SMALLINT, 2 },
13311 { "SYSTEM", "TYPE", "PRECISION", SQL_INTEGER, 9 },
13312 { "SYSTEM", "TYPE", "LITERAL_PREFIX", SCOL_VARCHAR, 50 },
13313 { "SYSTEM", "TYPE", "LITERAL_SUFFIX", SCOL_VARCHAR, 50 },
13314 { "SYSTEM", "TYPE", "CREATE_PARAMS", SCOL_VARCHAR, 50 },
13315 { "SYSTEM", "TYPE", "NULLABLE", SQL_SMALLINT, 2 },
13316 { "SYSTEM", "TYPE", "CASE_SENSITIVE", SQL_SMALLINT, 2 },
13317 { "SYSTEM", "TYPE", "SEARCHABLE", SQL_SMALLINT, 2 },
13318 { "SYSTEM", "TYPE", "UNSIGNED_ATTRIBUTE", SQL_SMALLINT, 2 },
13319 { "SYSTEM", "TYPE", "MONEY", SQL_SMALLINT, 2 },
13320 { "SYSTEM", "TYPE", "AUTO_INCREMENT", SQL_SMALLINT, 2 },
13321 { "SYSTEM", "TYPE", "LOCAL_TYPE_NAME", SCOL_VARCHAR, 50 },
13322 { "SYSTEM", "TYPE", "MINIMUM_SCALE", SQL_SMALLINT, 2 },
13323 { "SYSTEM", "TYPE", "MAXIMUM_SCALE", SQL_SMALLINT, 2 }
13324 };
13325
13326 static COL typeSpec3[] = {
13327 { "SYSTEM", "TYPE", "TYPE_NAME", SCOL_VARCHAR, 50 },
13328 { "SYSTEM", "TYPE", "DATA_TYPE", SQL_SMALLINT, 2 },
13329 { "SYSTEM", "TYPE", "COLUMN_SIZE", SQL_INTEGER, 9 },
13330 { "SYSTEM", "TYPE", "LITERAL_PREFIX", SCOL_VARCHAR, 50 },
13331 { "SYSTEM", "TYPE", "LITERAL_SUFFIX", SCOL_VARCHAR, 50 },
13332 { "SYSTEM", "TYPE", "CREATE_PARAMS", SCOL_VARCHAR, 50 },
13333 { "SYSTEM", "TYPE", "NULLABLE", SQL_SMALLINT, 2 },
13334 { "SYSTEM", "TYPE", "CASE_SENSITIVE", SQL_SMALLINT, 2 },
13335 { "SYSTEM", "TYPE", "SEARCHABLE", SQL_SMALLINT, 2 },
13336 { "SYSTEM", "TYPE", "UNSIGNED_ATTRIBUTE", SQL_SMALLINT, 2 },
13337 { "SYSTEM", "TYPE", "FIXED_PREC_SCALE", SQL_SMALLINT, 2 },
13338 { "SYSTEM", "TYPE", "AUTO_UNIQUE_VALUE", SQL_SMALLINT, 2 },
13339 { "SYSTEM", "TYPE", "LOCAL_TYPE_NAME", SCOL_VARCHAR, 50 },
13340 { "SYSTEM", "TYPE", "MINIMUM_SCALE", SQL_SMALLINT, 2 },
13341 { "SYSTEM", "TYPE", "MAXIMUM_SCALE", SQL_SMALLINT, 2 },
13342 { "SYSTEM", "TYPE", "SQL_DATA_TYPE", SQL_SMALLINT, 2 },
13343 { "SYSTEM", "TYPE", "SQL_DATETIME_SUB", SQL_SMALLINT, 2 },
13344 { "SYSTEM", "TYPE", "NUM_PREC_RADIX", SQL_INTEGER, 4 },
13345 { "SYSTEM", "TYPE", "INTERVAL_PRECISION", SQL_SMALLINT, 2 }
13346 };
13347
13348 /**
13349 * Internal function to build up data type information as row in result set.
13350 * @param s statement pointer
13351 * @param row row number
13352 * @param asize number of items in a row
13353 * @param typename name of type
13354 * @param type integer SQL type
13355 * @param tind type index
13356 */
13357
13358 static void
mktypeinfo(STMT * s,int row,int asize,char * typename,int type,int tind)13359 mktypeinfo(STMT *s, int row, int asize, char *typename, int type, int tind)
13360 {
13361 int offs = row * asize;
13362 char *tcode, *crpar = NULL, *quote = NULL, *sign = stringify(SQL_FALSE);
13363 static char tcodes[32 * 32];
13364
13365 if (tind <= 0) {
13366 tind = row;
13367 }
13368 tcode = tcodes + tind * 32;
13369 sprintf(tcode, "%d", type);
13370 s->rows[offs + 0] = typename;
13371 s->rows[offs + 1] = tcode;
13372 if (asize >= 17) {
13373 s->rows[offs + 15] = tcode;
13374 s->rows[offs + 16] = "0";
13375 }
13376 switch (type) {
13377 default:
13378 #ifdef SQL_LONGVARCHAR
13379 case SQL_LONGVARCHAR:
13380 #ifdef WINTERFACE
13381 case SQL_WLONGVARCHAR:
13382 #endif
13383 crpar = "length";
13384 quote = "'";
13385 sign = NULL;
13386 s->rows[offs + 2] = "65536";
13387 break;
13388 #endif
13389 #ifdef SQL_BIT
13390 case SQL_BIT:
13391 sign = NULL;
13392 s->rows[offs + 2] = "1";
13393 break;
13394 #endif
13395 case SQL_CHAR:
13396 case SQL_VARCHAR:
13397 #ifdef WINTERFACE
13398 case SQL_WCHAR:
13399 case SQL_WVARCHAR:
13400 #endif
13401 s->rows[offs + 2] = "255";
13402 crpar = "length";
13403 quote = "'";
13404 sign = NULL;
13405 break;
13406 case SQL_TINYINT:
13407 s->rows[offs + 2] = "3";
13408 break;
13409 case SQL_SMALLINT:
13410 s->rows[offs + 2] = "5";
13411 break;
13412 case SQL_INTEGER:
13413 s->rows[offs + 2] = "9";
13414 break;
13415 #ifdef SQL_BIGINT
13416 case SQL_BIGINT:
13417 s->rows[offs + 2] = "19";
13418 break;
13419 #endif
13420 case SQL_FLOAT:
13421 s->rows[offs + 2] = "7";
13422 break;
13423 case SQL_DOUBLE:
13424 s->rows[offs + 2] = "15";
13425 break;
13426 #ifdef SQL_TYPE_DATE
13427 case SQL_TYPE_DATE:
13428 #endif
13429 case SQL_DATE:
13430 s->rows[offs + 2] = "10";
13431 quote = "'";
13432 sign = NULL;
13433 break;
13434 #ifdef SQL_TYPE_TIME
13435 case SQL_TYPE_TIME:
13436 #endif
13437 case SQL_TIME:
13438 s->rows[offs + 2] = "8";
13439 quote = "'";
13440 sign = NULL;
13441 break;
13442 #ifdef SQL_TYPE_TIMESTAMP
13443 case SQL_TYPE_TIMESTAMP:
13444 #endif
13445 case SQL_TIMESTAMP:
13446 s->rows[offs + 2] = "32";
13447 quote = "'";
13448 sign = NULL;
13449 break;
13450 case SQL_VARBINARY:
13451 sign = NULL;
13452 s->rows[offs + 2] = "255";
13453 break;
13454 case SQL_LONGVARBINARY:
13455 sign = NULL;
13456 s->rows[offs + 2] = "65536";
13457 break;
13458 }
13459 s->rows[offs + 3] = s->rows[offs + 4] = quote;
13460 s->rows[offs + 5] = crpar;
13461 s->rows[offs + 6] = stringify(SQL_NULLABLE);
13462 s->rows[offs + 7] = stringify(SQL_FALSE);
13463 s->rows[offs + 8] = stringify(SQL_SEARCHABLE);
13464 s->rows[offs + 9] = sign;
13465 s->rows[offs + 10] = stringify(SQL_FALSE);
13466 s->rows[offs + 11] = stringify(SQL_FALSE);
13467 s->rows[offs + 12] = typename;
13468 switch (type) {
13469 case SQL_DATE:
13470 case SQL_TIME:
13471 s->rows[offs + 13] = "0";
13472 s->rows[offs + 14] = "0";
13473 break;
13474 #ifdef SQL_TYPE_TIMESTAMP
13475 case SQL_TYPE_TIMESTAMP:
13476 #endif
13477 case SQL_TIMESTAMP:
13478 s->rows[offs + 13] = "0";
13479 s->rows[offs + 14] = "3";
13480 break;
13481 default:
13482 s->rows[offs + 13] = NULL;
13483 s->rows[offs + 14] = NULL;
13484 break;
13485 }
13486 }
13487
13488 /**
13489 * Helper function to sort type information.
13490 * Callback for qsort().
13491 * @param a first item to compare
13492 * @param b second item to compare
13493 * @result ==0, <0, >0 according to data type number
13494 */
13495
13496 static int
typeinfosort(const void * a,const void * b)13497 typeinfosort(const void *a, const void *b)
13498 {
13499 char **pa = (char **) a;
13500 char **pb = (char **) b;
13501 int na, nb;
13502
13503 na = strtol(pa[1], NULL, 0);
13504 nb = strtol(pb[1], NULL, 0);
13505 return na - nb;
13506 }
13507
13508 /**
13509 * Internal return data type information.
13510 * @param stmt statement handle
13511 * @param sqltype which type to retrieve
13512 * @result ODBC error code
13513 */
13514
13515 static SQLRETURN
drvgettypeinfo(SQLHSTMT stmt,SQLSMALLINT sqltype)13516 drvgettypeinfo(SQLHSTMT stmt, SQLSMALLINT sqltype)
13517 {
13518 SQLRETURN ret;
13519 STMT *s;
13520 DBC *d;
13521 int asize;
13522
13523 ret = mkresultset(stmt, typeSpec2, array_size(typeSpec2),
13524 typeSpec3, array_size(typeSpec3), &asize);
13525 if (ret != SQL_SUCCESS) {
13526 return ret;
13527 }
13528 s = (STMT *) stmt;
13529 d = (DBC *) s->dbc;
13530 #ifdef SQL_LONGVARCHAR
13531 s->nrows = (sqltype == SQL_ALL_TYPES) ? 13 : 1;
13532 #else
13533 s->nrows = (sqltype == SQL_ALL_TYPES) ? 12 : 1;
13534 #endif
13535 if (sqltype == SQL_ALL_TYPES) {
13536 #ifdef WINTERFACE
13537 s->nrows += 2;
13538 #ifdef SQL_WLONGVARCHAR
13539 s->nrows += 2;
13540 #endif
13541 #endif
13542 }
13543 if (sqltype == SQL_ALL_TYPES) {
13544 s->nrows += 2;
13545 #ifdef SQL_BIT
13546 s->nrows += 1;
13547 #endif
13548 #ifdef SQL_BIGINT
13549 s->nrows += 1;
13550 #endif
13551 }
13552 s->rows = (char **) xmalloc(sizeof (char *) * (s->nrows + 1) * asize);
13553 if (!s->rows) {
13554 s->nrows = 0;
13555 return nomem(s);
13556 }
13557 #ifdef MEMORY_DEBUG
13558 s->rowfree = xfree__;
13559 #else
13560 s->rowfree = sqlite3_free;
13561 #endif
13562 memset(s->rows, 0, sizeof (char *) * (s->nrows + 1) * asize);
13563 if (sqltype == SQL_ALL_TYPES) {
13564 int cc = 1;
13565
13566 mktypeinfo(s, cc++, asize, "varchar", SQL_VARCHAR, 0);
13567 mktypeinfo(s, cc++, asize, "tinyint", SQL_TINYINT, 0);
13568 mktypeinfo(s, cc++, asize, "smallint", SQL_SMALLINT, 0);
13569 mktypeinfo(s, cc++, asize, "integer", SQL_INTEGER, 0);
13570 mktypeinfo(s, cc++, asize, "float", SQL_FLOAT, 0);
13571 mktypeinfo(s, cc++, asize, "double", SQL_DOUBLE, 0);
13572 #ifdef SQL_TYPE_DATE
13573 mktypeinfo(s, cc++, asize, "date",
13574 (*s->ov3) ? SQL_TYPE_DATE : SQL_DATE, 0);
13575 #else
13576 mktypeinfo(s, cc++, asize, "date", SQL_DATE, 0);
13577 #endif
13578 #ifdef SQL_TYPE_TIME
13579 mktypeinfo(s, cc++, asize, "time",
13580 (*s->ov3) ? SQL_TYPE_TIME : SQL_TIME, 0);
13581 #else
13582 mktypeinfo(s, cc++, asize, "time", SQL_TIME, 0);
13583 #endif
13584 #ifdef SQL_TYPE_TIMESTAMP
13585 mktypeinfo(s, cc++, asize, "timestamp",
13586 (*s->ov3) ? SQL_TYPE_TIMESTAMP : SQL_TIMESTAMP, 0);
13587 #else
13588 mktypeinfo(s, cc++, asize, "timestamp", SQL_TIMESTAMP, 0);
13589 #endif
13590 mktypeinfo(s, cc++, asize, "char", SQL_CHAR, 0);
13591 mktypeinfo(s, cc++, asize, "numeric", SQL_DOUBLE, 0);
13592 #ifdef SQL_LONGVARCHAR
13593 mktypeinfo(s, cc++, asize, "text", SQL_LONGVARCHAR, 0);
13594 mktypeinfo(s, cc++, asize, "longvarchar", SQL_LONGVARCHAR, 0);
13595 #else
13596 mktypeinfo(s, cc++, asize, "text", SQL_VARCHAR, 0);
13597 #endif
13598 mktypeinfo(s, cc++, asize, "varbinary", SQL_VARBINARY, 0);
13599 mktypeinfo(s, cc++, asize, "longvarbinary", SQL_LONGVARBINARY, 0);
13600 #ifdef SQL_BIT
13601 mktypeinfo(s, cc++, asize, "bit", SQL_BIT, 0);
13602 #endif
13603 #ifdef SQL_BIGINT
13604 mktypeinfo(s, cc++, asize, "bigint", SQL_BIGINT, 0);
13605 #endif
13606 #ifdef WINTERFACE
13607 mktypeinfo(s, cc++, asize, "wvarchar", SQL_WVARCHAR, 0);
13608 mktypeinfo(s, cc++, asize, "wchar", SQL_WCHAR, 0);
13609 #ifdef SQL_WLONGVARCHAR
13610 mktypeinfo(s, cc++, asize, "wtext", SQL_WLONGVARCHAR, 0);
13611 mktypeinfo(s, cc++, asize, "longwvarchar", SQL_WLONGVARCHAR, 0);
13612 #endif
13613 #endif
13614 qsort(s->rows + asize, s->nrows, sizeof (char *) * asize,
13615 typeinfosort);
13616 } else {
13617 switch (sqltype) {
13618 case SQL_CHAR:
13619 mktypeinfo(s, 1, asize, "char", SQL_CHAR, 10);
13620 break;
13621 case SQL_VARCHAR:
13622 mktypeinfo(s, 1, asize, "varchar", SQL_VARCHAR, 1);
13623 break;
13624 case SQL_TINYINT:
13625 mktypeinfo(s, 1, asize, "tinyint", SQL_TINYINT, 2);
13626 break;
13627 case SQL_SMALLINT:
13628 mktypeinfo(s, 1, asize, "smallint", SQL_SMALLINT, 3);
13629 break;
13630 case SQL_INTEGER:
13631 mktypeinfo(s, 1, asize, "integer", SQL_INTEGER, 4);
13632 break;
13633 case SQL_FLOAT:
13634 mktypeinfo(s, 1, asize, "float", SQL_FLOAT, 5);
13635 break;
13636 case SQL_DOUBLE:
13637 mktypeinfo(s, 1, asize, "double", SQL_DOUBLE, 6);
13638 break;
13639 #ifdef SQL_TYPE_DATE
13640 case SQL_TYPE_DATE:
13641 mktypeinfo(s, 1, asize, "date", SQL_TYPE_DATE, 25);
13642 break;
13643 #endif
13644 case SQL_DATE:
13645 mktypeinfo(s, 1, asize, "date", SQL_DATE, 7);
13646 break;
13647 #ifdef SQL_TYPE_TIME
13648 case SQL_TYPE_TIME:
13649 mktypeinfo(s, 1, asize, "time", SQL_TYPE_TIME, 26);
13650 break;
13651 #endif
13652 case SQL_TIME:
13653 mktypeinfo(s, 1, asize, "time", SQL_TIME, 8);
13654 break;
13655 #ifdef SQL_TYPE_TIMESTAMP
13656 case SQL_TYPE_TIMESTAMP:
13657 mktypeinfo(s, 1, asize, "timestamp", SQL_TYPE_TIMESTAMP, 27);
13658 break;
13659 #endif
13660 case SQL_TIMESTAMP:
13661 mktypeinfo(s, 1, asize, "timestamp", SQL_TIMESTAMP, 9);
13662 break;
13663 #ifdef SQL_LONGVARCHAR
13664 case SQL_LONGVARCHAR:
13665 mktypeinfo(s, 1, asize, "longvarchar", SQL_LONGVARCHAR, 12);
13666 break;
13667 #endif
13668 case SQL_VARBINARY:
13669 mktypeinfo(s, 1, asize, "varbinary", SQL_VARBINARY, 30);
13670 break;
13671 case SQL_LONGVARBINARY:
13672 mktypeinfo(s, 1, asize, "longvarbinary", SQL_LONGVARBINARY, 31);
13673 break;
13674 #ifdef SQL_BIT
13675 case SQL_BIT:
13676 mktypeinfo(s, 1, asize, "bit", SQL_BIT, 29);
13677 break;
13678 #endif
13679 #ifdef SQL_BIGINT
13680 case SQL_BIGINT:
13681 mktypeinfo(s, 1, asize, "bigint", SQL_BIGINT, 28);
13682 break;
13683 #endif
13684 #ifdef WINTERFACE
13685 #ifdef SQL_WCHAR
13686 case SQL_WCHAR:
13687 mktypeinfo(s, 1, asize, "wchar", SQL_WCHAR, 18);
13688 break;
13689 #endif
13690 #ifdef SQL_WVARCHAR
13691 case SQL_WVARCHAR:
13692 mktypeinfo(s, 1, asize, "wvarchar", SQL_WVARCHAR, 19);
13693 break;
13694 #endif
13695 #ifdef SQL_WLONGVARCHAR
13696 case SQL_WLONGVARCHAR:
13697 mktypeinfo(s, 1, asize, "longwvarchar", SQL_WLONGVARCHAR, 20);
13698 break;
13699 #endif
13700 #endif
13701 default:
13702 s->nrows = 0;
13703 }
13704 }
13705 return SQL_SUCCESS;
13706 }
13707
13708 #ifndef WINTERFACE
13709 /**
13710 * Return data type information.
13711 * @param stmt statement handle
13712 * @param sqltype which type to retrieve
13713 * @result ODBC error code
13714 */
13715
13716 SQLRETURN SQL_API
SQLGetTypeInfo(SQLHSTMT stmt,SQLSMALLINT sqltype)13717 SQLGetTypeInfo(SQLHSTMT stmt, SQLSMALLINT sqltype)
13718 {
13719 SQLRETURN ret;
13720
13721 HSTMT_LOCK(stmt);
13722 ret = drvgettypeinfo(stmt, sqltype);
13723 HSTMT_UNLOCK(stmt);
13724 return ret;
13725 }
13726 #endif
13727
13728 #ifdef WINTERFACE
13729 /**
13730 * Return data type information (UNICODE version).
13731 * @param stmt statement handle
13732 * @param sqltype which type to retrieve
13733 * @result ODBC error code
13734 */
13735
13736 SQLRETURN SQL_API
SQLGetTypeInfoW(SQLHSTMT stmt,SQLSMALLINT sqltype)13737 SQLGetTypeInfoW(SQLHSTMT stmt, SQLSMALLINT sqltype)
13738 {
13739 SQLRETURN ret;
13740
13741 HSTMT_LOCK(stmt);
13742 ret = drvgettypeinfo(stmt, sqltype);
13743 HSTMT_UNLOCK(stmt);
13744 return ret;
13745 }
13746 #endif
13747
13748 /**
13749 * Columns for result set of SQLStatistics().
13750 */
13751
13752 static COL statSpec2[] = {
13753 { "SYSTEM", "STATISTICS", "TABLE_QUALIFIER", SCOL_VARCHAR, 50 },
13754 { "SYSTEM", "STATISTICS", "TABLE_OWNER", SCOL_VARCHAR, 50 },
13755 { "SYSTEM", "STATISTICS", "TABLE_NAME", SCOL_VARCHAR, 255 },
13756 { "SYSTEM", "STATISTICS", "NON_UNIQUE", SQL_SMALLINT, 50 },
13757 { "SYSTEM", "STATISTICS", "INDEX_QUALIFIER", SCOL_VARCHAR, 255 },
13758 { "SYSTEM", "STATISTICS", "INDEX_NAME", SCOL_VARCHAR, 255 },
13759 { "SYSTEM", "STATISTICS", "TYPE", SQL_SMALLINT, 50 },
13760 { "SYSTEM", "STATISTICS", "SEQ_IN_INDEX", SQL_SMALLINT, 50 },
13761 { "SYSTEM", "STATISTICS", "COLUMN_NAME", SCOL_VARCHAR, 255 },
13762 { "SYSTEM", "STATISTICS", "COLLATION", SCOL_CHAR, 1 },
13763 { "SYSTEM", "STATISTICS", "CARDINALITY", SQL_INTEGER, 50 },
13764 { "SYSTEM", "STATISTICS", "PAGES", SQL_INTEGER, 50 },
13765 { "SYSTEM", "STATISTICS", "FILTER_CONDITION", SCOL_VARCHAR, 255 }
13766 };
13767
13768 static COL statSpec3[] = {
13769 { "SYSTEM", "STATISTICS", "TABLE_CAT", SCOL_VARCHAR, 50 },
13770 { "SYSTEM", "STATISTICS", "TABLE_SCHEM", SCOL_VARCHAR, 50 },
13771 { "SYSTEM", "STATISTICS", "TABLE_NAME", SCOL_VARCHAR, 255 },
13772 { "SYSTEM", "STATISTICS", "NON_UNIQUE", SQL_SMALLINT, 50 },
13773 { "SYSTEM", "STATISTICS", "INDEX_QUALIFIER", SCOL_VARCHAR, 255 },
13774 { "SYSTEM", "STATISTICS", "INDEX_NAME", SCOL_VARCHAR, 255 },
13775 { "SYSTEM", "STATISTICS", "TYPE", SQL_SMALLINT, 50 },
13776 { "SYSTEM", "STATISTICS", "ORDINAL_POSITION", SQL_SMALLINT, 50 },
13777 { "SYSTEM", "STATISTICS", "COLUMN_NAME", SCOL_VARCHAR, 255 },
13778 { "SYSTEM", "STATISTICS", "ASC_OR_DESC", SCOL_CHAR, 1 },
13779 { "SYSTEM", "STATISTICS", "CARDINALITY", SQL_INTEGER, 50 },
13780 { "SYSTEM", "STATISTICS", "PAGES", SQL_INTEGER, 50 },
13781 { "SYSTEM", "STATISTICS", "FILTER_CONDITION", SCOL_VARCHAR, 255 }
13782 };
13783
13784 /**
13785 * Internal return statistic information on table indices.
13786 * @param stmt statement handle
13787 * @param cat catalog name/pattern or NULL
13788 * @param catLen length of catalog name/pattern or SQL_NTS
13789 * @param schema schema name/pattern or NULL
13790 * @param schemaLen length of schema name/pattern or SQL_NTS
13791 * @param table table name/pattern or NULL
13792 * @param tableLen length of table name/pattern or SQL_NTS
13793 * @param itype type of index information
13794 * @param resv reserved
13795 * @result ODBC error code
13796 */
13797
13798 static SQLRETURN
drvstatistics(SQLHSTMT stmt,SQLCHAR * cat,SQLSMALLINT catLen,SQLCHAR * schema,SQLSMALLINT schemaLen,SQLCHAR * table,SQLSMALLINT tableLen,SQLUSMALLINT itype,SQLUSMALLINT resv)13799 drvstatistics(SQLHSTMT stmt, SQLCHAR *cat, SQLSMALLINT catLen,
13800 SQLCHAR *schema, SQLSMALLINT schemaLen,
13801 SQLCHAR *table, SQLSMALLINT tableLen,
13802 SQLUSMALLINT itype, SQLUSMALLINT resv)
13803 {
13804 SQLRETURN sret;
13805 STMT *s;
13806 DBC *d;
13807 int i, asize, ret, nrows, ncols, offs, namec, uniquec, addipk = 0;
13808 PTRDIFF_T size;
13809 char **rowp, *errp = NULL, *sql, tname[512];
13810
13811 sret = mkresultset(stmt, statSpec2, array_size(statSpec2),
13812 statSpec3, array_size(statSpec3), &asize);
13813 if (sret != SQL_SUCCESS) {
13814 return sret;
13815 }
13816 s = (STMT *) stmt;
13817 d = (DBC *) s->dbc;
13818 if (!table || table[0] == '\0' || table[0] == '%') {
13819 setstat(s, -1, "need table name", (*s->ov3) ? "HY000" : "S1000");
13820 return SQL_ERROR;
13821 }
13822 if (tableLen == SQL_NTS) {
13823 size = sizeof (tname) - 1;
13824 } else {
13825 size = min(sizeof (tname) - 1, tableLen);
13826 }
13827 strncpy(tname, (char *) table, size);
13828 tname[size] = '\0';
13829 unescpat(tname);
13830 sret = starttran(s);
13831 if (sret != SQL_SUCCESS) {
13832 return sret;
13833 }
13834 /*
13835 * Try integer primary key (autoincrement) first
13836 */
13837 if (itype == SQL_INDEX_UNIQUE || itype == SQL_INDEX_ALL) {
13838 rowp = 0;
13839 ret = SQLITE_ERROR;
13840 sql = sqlite3_mprintf("PRAGMA table_info(%Q)", tname);
13841 if (sql) {
13842 dbtraceapi(d, "sqlite3_get_table", sql);
13843 ret = sqlite3_get_table(d->sqlite, sql, &rowp,
13844 &nrows, &ncols, NULL);
13845 sqlite3_free(sql);
13846 }
13847 if (ret == SQLITE_OK) {
13848 int colid, typec, npk = 0;
13849
13850 namec = findcol(rowp, ncols, "name");
13851 uniquec = findcol(rowp, ncols, "pk");
13852 typec = findcol(rowp, ncols, "type");
13853 colid = findcol(rowp, ncols, "cid");
13854 if (namec < 0 || uniquec < 0 || typec < 0 || colid < 0) {
13855 goto noipk;
13856 }
13857 for (i = 1; i <= nrows; i++) {
13858 if (*rowp[i * ncols + uniquec] != '0' &&
13859 strlen(rowp[i * ncols + typec]) == 7 &&
13860 strncasecmp(rowp[i * ncols + typec], "integer", 7)
13861 == 0) {
13862 npk++;
13863 }
13864 }
13865 if (npk == 1) {
13866 addipk = 1;
13867 }
13868 }
13869 noipk:
13870 sqlite3_free_table(rowp);
13871 }
13872 sql = sqlite3_mprintf("PRAGMA index_list(%Q)", tname);
13873 if (!sql) {
13874 return nomem(s);
13875 }
13876 dbtraceapi(d, "sqlite3_get_table", sql);
13877 ret = sqlite3_get_table(d->sqlite, sql, &rowp, &nrows, &ncols, &errp);
13878 sqlite3_free(sql);
13879 if (ret != SQLITE_OK) {
13880 setstat(s, ret, "%s (%d)", (*s->ov3) ? "HY000" : "S1000",
13881 errp ? errp : "unknown error", ret);
13882 if (errp) {
13883 sqlite3_free(errp);
13884 errp = NULL;
13885 }
13886 return SQL_ERROR;
13887 }
13888 if (errp) {
13889 sqlite3_free(errp);
13890 errp = NULL;
13891 }
13892 size = 0;
13893 namec = findcol(rowp, ncols, "name");
13894 uniquec = findcol(rowp, ncols, "unique");
13895 if (namec < 0 || uniquec < 0) {
13896 goto nodata;
13897 }
13898 for (i = 1; i <= nrows; i++) {
13899 int nnrows, nncols;
13900 char **rowpp;
13901 int isuniq;
13902
13903 isuniq = *rowp[i * ncols + uniquec] != '0';
13904 if (isuniq || itype == SQL_INDEX_ALL) {
13905 ret = SQLITE_ERROR;
13906 sql = sqlite3_mprintf("PRAGMA index_info(%Q)",
13907 rowp[i * ncols + namec]);
13908 if (sql) {
13909 dbtraceapi(d, "sqlite3_get_table", sql);
13910 ret = sqlite3_get_table(d->sqlite, sql, &rowpp,
13911 &nnrows, &nncols, NULL);
13912 sqlite3_free(sql);
13913 }
13914 if (ret == SQLITE_OK) {
13915 size += nnrows;
13916 sqlite3_free_table(rowpp);
13917 }
13918 }
13919 }
13920 nodata:
13921 if (addipk) {
13922 size++;
13923 }
13924 if (size == 0) {
13925 sqlite3_free_table(rowp);
13926 return SQL_SUCCESS;
13927 }
13928 s->nrows = size;
13929 size = (size + 1) * asize;
13930 s->rows = xmalloc((size + 1) * sizeof (char *));
13931 if (!s->rows) {
13932 s->nrows = 0;
13933 return nomem(s);
13934 }
13935 s->rows[0] = (char *) size;
13936 s->rows += 1;
13937 memset(s->rows, 0, sizeof (char *) * size);
13938 s->rowfree = freerows;
13939 offs = 0;
13940 if (addipk) {
13941 char **rowpp = 0;
13942 int nrows2, ncols2;
13943
13944 sql = sqlite3_mprintf("PRAGMA table_info(%Q)", tname);
13945 if (sql) {
13946 dbtraceapi(d, "sqlite3_get_table", sql);
13947 ret = sqlite3_get_table(d->sqlite, sql, &rowpp,
13948 &nrows2, &ncols2, NULL);
13949 sqlite3_free(sql);
13950 }
13951 if (ret == SQLITE_OK) {
13952 int colid, typec, roffs, namecc, uniquecc;
13953
13954 namecc = findcol(rowpp, ncols2, "name");
13955 uniquecc = findcol(rowpp, ncols2, "pk");
13956 typec = findcol(rowpp, ncols2, "type");
13957 colid = findcol(rowpp, ncols2, "cid");
13958 if (namecc < 0 || uniquecc < 0 || typec < 0 || colid < 0) {
13959 addipk = 0;
13960 s->nrows--;
13961 goto nodata2;
13962 }
13963 for (i = 1; i <= nrows2; i++) {
13964 if (*rowpp[i * ncols2 + uniquecc] != '0' &&
13965 strlen(rowpp[i * ncols2 + typec]) == 7 &&
13966 strncasecmp(rowpp[i * ncols2 + typec], "integer", 7)
13967 == 0) {
13968 break;
13969 }
13970 }
13971 if (i > nrows2) {
13972 addipk = 0;
13973 s->nrows--;
13974 goto nodata2;
13975 }
13976 roffs = s->ncols;
13977 s->rows[roffs + 0] = xstrdup("");
13978 #if defined(_WIN32) || defined(_WIN64)
13979 s->rows[roffs + 1] = xstrdup(d->xcelqrx ? "main" : "");
13980 #else
13981 s->rows[roffs + 1] = xstrdup("");
13982 #endif
13983 s->rows[roffs + 2] = xstrdup(tname);
13984 s->rows[roffs + 3] = xstrdup(stringify(SQL_FALSE));
13985 s->rows[roffs + 5] = xstrdup("sqlite_autoindex_0");
13986 s->rows[roffs + 6] = xstrdup(stringify(SQL_INDEX_OTHER));
13987 s->rows[roffs + 7] = xstrdup("1");
13988 s->rows[roffs + 8] = xstrdup(rowpp[i * ncols2 + namecc]);
13989 s->rows[roffs + 9] = xstrdup("A");
13990 }
13991 nodata2:
13992 sqlite3_free_table(rowpp);
13993 }
13994 for (i = 1; i <= nrows; i++) {
13995 int nnrows, nncols;
13996 char **rowpp = 0;
13997
13998 if (*rowp[i * ncols + uniquec] != '0' || itype == SQL_INDEX_ALL) {
13999 int k;
14000
14001 ret = SQLITE_ERROR;
14002 sql = sqlite3_mprintf("PRAGMA index_info(%Q)",
14003 rowp[i * ncols + namec]);
14004 if (sql) {
14005 dbtraceapi(d, "sqlite3_get_table", sql);
14006 ret = sqlite3_get_table(d->sqlite, sql, &rowpp,
14007 &nnrows, &nncols, NULL);
14008 sqlite3_free(sql);
14009 }
14010 if (ret != SQLITE_OK) {
14011 continue;
14012 }
14013 for (k = 0; nnrows && k < nncols; k++) {
14014 if (strcmp(rowpp[k], "name") == 0) {
14015 int m;
14016
14017 for (m = 1; m <= nnrows; m++) {
14018 int roffs = (offs + addipk + m) * s->ncols;
14019 int isuniq;
14020
14021 isuniq = *rowp[i * ncols + uniquec] != '0';
14022 s->rows[roffs + 0] = xstrdup("");
14023 s->rows[roffs + 1] = xstrdup("");
14024 s->rows[roffs + 2] = xstrdup(tname);
14025 if (isuniq) {
14026 s->rows[roffs + 3] = xstrdup(stringify(SQL_FALSE));
14027 } else {
14028 s->rows[roffs + 3] = xstrdup(stringify(SQL_TRUE));
14029 }
14030 s->rows[roffs + 5] = xstrdup(rowp[i * ncols + namec]);
14031 s->rows[roffs + 6] =
14032 xstrdup(stringify(SQL_INDEX_OTHER));
14033 s->rows[roffs + 8] = xstrdup(rowpp[m * nncols + k]);
14034 s->rows[roffs + 9] = xstrdup("A");
14035 }
14036 } else if (strcmp(rowpp[k], "seqno") == 0) {
14037 int m;
14038
14039 for (m = 1; m <= nnrows; m++) {
14040 int roffs = (offs + addipk + m) * s->ncols;
14041 int pos = m - 1;
14042 char buf[32];
14043
14044 sscanf(rowpp[m * nncols + k], "%d", &pos);
14045 sprintf(buf, "%d", pos + 1);
14046 s->rows[roffs + 7] = xstrdup(buf);
14047 }
14048 }
14049 }
14050 offs += nnrows;
14051 sqlite3_free_table(rowpp);
14052 }
14053 }
14054 sqlite3_free_table(rowp);
14055 return SQL_SUCCESS;
14056 }
14057
14058 #ifndef WINTERFACE
14059 /**
14060 * Return statistic information on table indices.
14061 * @param stmt statement handle
14062 * @param cat catalog name/pattern or NULL
14063 * @param catLen length of catalog name/pattern or SQL_NTS
14064 * @param schema schema name/pattern or NULL
14065 * @param schemaLen length of schema name/pattern or SQL_NTS
14066 * @param table table name/pattern or NULL
14067 * @param tableLen length of table name/pattern or SQL_NTS
14068 * @param itype type of index information
14069 * @param resv reserved
14070 * @result ODBC error code
14071 */
14072
14073 SQLRETURN SQL_API
SQLStatistics(SQLHSTMT stmt,SQLCHAR * cat,SQLSMALLINT catLen,SQLCHAR * schema,SQLSMALLINT schemaLen,SQLCHAR * table,SQLSMALLINT tableLen,SQLUSMALLINT itype,SQLUSMALLINT resv)14074 SQLStatistics(SQLHSTMT stmt, SQLCHAR *cat, SQLSMALLINT catLen,
14075 SQLCHAR *schema, SQLSMALLINT schemaLen,
14076 SQLCHAR *table, SQLSMALLINT tableLen,
14077 SQLUSMALLINT itype, SQLUSMALLINT resv)
14078 {
14079 #if defined(_WIN32) || defined(_WIN64)
14080 char *c = NULL, *s = NULL, *t = NULL;
14081 #endif
14082 SQLRETURN ret;
14083
14084 HSTMT_LOCK(stmt);
14085 #if defined(_WIN32) || defined(_WIN64)
14086 if (!((STMT *) stmt)->oemcp[0]) {
14087 ret = drvstatistics(stmt, cat, catLen, schema, schemaLen,
14088 table, tableLen, itype, resv);
14089 goto done2;
14090 }
14091 if (cat) {
14092 c = wmb_to_utf_c((char *) cat, catLen);
14093 if (!c) {
14094 ret = nomem((STMT *) stmt);
14095 goto done;
14096 }
14097 }
14098 if (schema) {
14099 s = wmb_to_utf_c((char *) schema, schemaLen);
14100 if (!s) {
14101 ret = nomem((STMT *) stmt);
14102 goto done;
14103 }
14104 }
14105 if (table) {
14106 t = wmb_to_utf_c((char *) table, tableLen);
14107 if (!t) {
14108 ret = nomem((STMT *) stmt);
14109 goto done;
14110 }
14111 }
14112 ret = drvstatistics(stmt, (SQLCHAR *) c, SQL_NTS, (SQLCHAR *) s, SQL_NTS,
14113 (SQLCHAR *) t, SQL_NTS, itype, resv);
14114 #else
14115 ret = drvstatistics(stmt, cat, catLen, schema, schemaLen,
14116 table, tableLen, itype, resv);
14117 #endif
14118 #if defined(_WIN32) || defined(_WIN64)
14119 done:
14120 uc_free(t);
14121 uc_free(s);
14122 uc_free(c);
14123 done2:
14124 ;
14125 #endif
14126 HSTMT_UNLOCK(stmt);
14127 return ret;
14128 }
14129 #endif
14130
14131 #ifdef WINTERFACE
14132 /**
14133 * Return statistic information on table indices (UNICODE version).
14134 * @param stmt statement handle
14135 * @param cat catalog name/pattern or NULL
14136 * @param catLen length of catalog name/pattern or SQL_NTS
14137 * @param schema schema name/pattern or NULL
14138 * @param schemaLen length of schema name/pattern or SQL_NTS
14139 * @param table table name/pattern or NULL
14140 * @param tableLen length of table name/pattern or SQL_NTS
14141 * @param itype type of index information
14142 * @param resv reserved
14143 * @result ODBC error code
14144 */
14145
14146 SQLRETURN SQL_API
SQLStatisticsW(SQLHSTMT stmt,SQLWCHAR * cat,SQLSMALLINT catLen,SQLWCHAR * schema,SQLSMALLINT schemaLen,SQLWCHAR * table,SQLSMALLINT tableLen,SQLUSMALLINT itype,SQLUSMALLINT resv)14147 SQLStatisticsW(SQLHSTMT stmt, SQLWCHAR *cat, SQLSMALLINT catLen,
14148 SQLWCHAR *schema, SQLSMALLINT schemaLen,
14149 SQLWCHAR *table, SQLSMALLINT tableLen,
14150 SQLUSMALLINT itype, SQLUSMALLINT resv)
14151 {
14152 char *c = NULL, *s = NULL, *t = NULL;
14153 SQLRETURN ret;
14154
14155 HSTMT_LOCK(stmt);
14156 if (cat) {
14157 c = uc_to_utf_c(cat, catLen);
14158 if (!c) {
14159 ret = nomem((STMT *) stmt);
14160 goto done;
14161 }
14162 }
14163 if (schema) {
14164 s = uc_to_utf_c(schema, schemaLen);
14165 if (!s) {
14166 ret = nomem((STMT *) stmt);
14167 goto done;
14168 }
14169 }
14170 if (table) {
14171 t = uc_to_utf_c(table, tableLen);
14172 if (!t) {
14173 ret = nomem((STMT *) stmt);
14174 goto done;
14175 }
14176 }
14177 ret = drvstatistics(stmt, (SQLCHAR *) c, SQL_NTS, (SQLCHAR *) s, SQL_NTS,
14178 (SQLCHAR *) t, SQL_NTS, itype, resv);
14179 done:
14180 uc_free(t);
14181 uc_free(s);
14182 uc_free(c);
14183 HSTMT_UNLOCK(stmt);
14184 return ret;
14185 }
14186 #endif
14187
14188 /**
14189 * Retrieve row data after fetch.
14190 * @param stmt statement handle
14191 * @param col column number, starting at 1
14192 * @param type output type
14193 * @param val output buffer
14194 * @param len length of output buffer
14195 * @param lenp output length
14196 * @result ODBC error code
14197 */
14198
14199 SQLRETURN SQL_API
SQLGetData(SQLHSTMT stmt,SQLUSMALLINT col,SQLSMALLINT type,SQLPOINTER val,SQLLEN len,SQLLEN * lenp)14200 SQLGetData(SQLHSTMT stmt, SQLUSMALLINT col, SQLSMALLINT type,
14201 SQLPOINTER val, SQLLEN len, SQLLEN *lenp)
14202 {
14203 STMT *s;
14204 SQLRETURN ret = SQL_ERROR;
14205
14206 HSTMT_LOCK(stmt);
14207 if (stmt == SQL_NULL_HSTMT) {
14208 return SQL_INVALID_HANDLE;
14209 }
14210 s = (STMT *) stmt;
14211 if (col == 0 && s->bkmrk && type == SQL_C_BOOKMARK) {
14212 *((long *) val) = s->rowp;
14213 if (lenp) {
14214 *lenp = sizeof (long);
14215 }
14216 ret = SQL_SUCCESS;
14217 goto done;
14218 }
14219 if (col < 1 || col > s->ncols) {
14220 setstat(s, -1, "invalid column", (*s->ov3) ? "07009" : "S1002");
14221 goto done;
14222 }
14223 --col;
14224 ret = getrowdata(s, col, type, val, len, lenp, 1);
14225 done:
14226 HSTMT_UNLOCK(stmt);
14227 return ret;
14228 }
14229
14230 /**
14231 * Internal: fetch and bind from statement's current row
14232 * @param s statement pointer
14233 * @param rsi rowset index
14234 * @result ODBC error code
14235 */
14236
14237 static SQLRETURN
dofetchbind(STMT * s,int rsi)14238 dofetchbind(STMT *s, int rsi)
14239 {
14240 int ret, i, withinfo = 0;
14241
14242 s->row_status0[rsi] = SQL_ROW_SUCCESS;
14243 if (s->bkmrk && s->bkmrkcol.valp) {
14244 long *val;
14245
14246 if (s->bind_type != SQL_BIND_BY_COLUMN) {
14247 val = (long *) ((char *) s->bkmrkcol.valp + s->bind_type * rsi);
14248 } else {
14249 val = (long *) s->bkmrkcol.valp + rsi;
14250 }
14251 if (s->bind_offs) {
14252 val = (long *) ((char *) val + *s->bind_offs);
14253 }
14254 *val = s->rowp;
14255 if (s->bkmrkcol.lenp) {
14256 SQLLEN *ival;
14257
14258 if (s->bind_type != SQL_BIND_BY_COLUMN) {
14259 ival = (SQLLEN *)
14260 ((char *) s->bkmrkcol.lenp + s->bind_type * rsi);
14261 } else {
14262 ival = &s->bkmrkcol.lenp[rsi];
14263 }
14264 if (s->bind_offs) {
14265 ival = (SQLLEN *) ((char *) ival + *s->bind_offs);
14266 }
14267 *ival = sizeof (long);
14268 }
14269 }
14270 ret = SQL_SUCCESS;
14271 for (i = 0; s->bindcols && i < s->ncols; i++) {
14272 BINDCOL *b = &s->bindcols[i];
14273 SQLPOINTER dp = 0;
14274 SQLLEN *lp = 0;
14275
14276 b->offs = 0;
14277 if (b->valp) {
14278 if (s->bind_type != SQL_BIND_BY_COLUMN) {
14279 dp = (SQLPOINTER) ((char *) b->valp + s->bind_type * rsi);
14280 } else {
14281 dp = (SQLPOINTER) ((char *) b->valp + b->max * rsi);
14282 }
14283 if (s->bind_offs) {
14284 dp = (SQLPOINTER) ((char *) dp + *s->bind_offs);
14285 }
14286 }
14287 if (b->lenp) {
14288 if (s->bind_type != SQL_BIND_BY_COLUMN) {
14289 lp = (SQLLEN *) ((char *) b->lenp + s->bind_type * rsi);
14290 } else {
14291 lp = b->lenp + rsi;
14292 }
14293 if (s->bind_offs) {
14294 lp = (SQLLEN *) ((char *) lp + *s->bind_offs);
14295 }
14296 }
14297 if (dp || lp) {
14298 ret = getrowdata(s, (SQLUSMALLINT) i, b->type, dp, b->max, lp, 0);
14299 if (!SQL_SUCCEEDED(ret)) {
14300 s->row_status0[rsi] = SQL_ROW_ERROR;
14301 break;
14302 }
14303 if (ret != SQL_SUCCESS) {
14304 withinfo = 1;
14305 #ifdef SQL_ROW_SUCCESS_WITH_INFO
14306 s->row_status0[rsi] = SQL_ROW_SUCCESS_WITH_INFO;
14307 #endif
14308 }
14309 }
14310 }
14311 if (SQL_SUCCEEDED(ret)) {
14312 ret = withinfo ? SQL_SUCCESS_WITH_INFO : SQL_SUCCESS;
14313 }
14314 return ret;
14315 }
14316
14317 /**
14318 * Internal fetch function for SQLFetchScroll() and SQLExtendedFetch().
14319 * @param stmt statement handle
14320 * @param orient fetch direction
14321 * @param offset offset for fetch direction
14322 * @result ODBC error code
14323 */
14324
14325 static SQLRETURN
drvfetchscroll(SQLHSTMT stmt,SQLSMALLINT orient,SQLINTEGER offset)14326 drvfetchscroll(SQLHSTMT stmt, SQLSMALLINT orient, SQLINTEGER offset)
14327 {
14328 STMT *s;
14329 int i, withinfo = 0;
14330 SQLRETURN ret;
14331
14332 if (stmt == SQL_NULL_HSTMT) {
14333 return SQL_INVALID_HANDLE;
14334 }
14335 s = (STMT *) stmt;
14336 for (i = 0; i < s->rowset_size; i++) {
14337 s->row_status0[i] = SQL_ROW_NOROW;
14338 }
14339 if (s->row_status) {
14340 memcpy(s->row_status, s->row_status0,
14341 sizeof (SQLUSMALLINT) * s->rowset_size);
14342 }
14343 s->row_count0 = 0;
14344 if (s->row_count) {
14345 *s->row_count = s->row_count0;
14346 }
14347 if (!s->bindcols) {
14348 for (i = 0; i < s->rowset_size; i++) {
14349 s->row_status0[i] = SQL_ROW_ERROR;
14350 }
14351 ret = SQL_ERROR;
14352 i = 0;
14353 goto done2;
14354 }
14355 if (!s->isselect) {
14356 setstat(s, -1, "no result set available", "24000");
14357 ret = SQL_ERROR;
14358 i = s->nrows;
14359 goto done2;
14360 }
14361 if (s->curtype == SQL_CURSOR_FORWARD_ONLY && orient != SQL_FETCH_NEXT) {
14362 setstat(s, -1, "wrong fetch direction", "01000");
14363 ret = SQL_ERROR;
14364 i = 0;
14365 goto done2;
14366 }
14367 ret = SQL_SUCCESS;
14368 i = 0;
14369 if (((DBC *) (s->dbc))->cur_s3stmt == s && s->s3stmt) {
14370 s->rowp = 0;
14371 for (; i < s->rowset_size; i++) {
14372 if (s->max_rows && s->s3stmt_rownum + 1 >= s->max_rows) {
14373 ret = (i == 0) ? SQL_NO_DATA : SQL_SUCCESS;
14374 break;
14375 }
14376 ret = s3stmt_step(s);
14377 if (ret != SQL_SUCCESS) {
14378 s->row_status0[i] = SQL_ROW_ERROR;
14379 break;
14380 }
14381 if (s->nrows < 1) {
14382 break;
14383 }
14384 ret = dofetchbind(s, i);
14385 if (!SQL_SUCCEEDED(ret)) {
14386 break;
14387 } else if (ret == SQL_SUCCESS_WITH_INFO) {
14388 withinfo = 1;
14389 }
14390 }
14391 } else if (s->rows) {
14392 switch (orient) {
14393 case SQL_FETCH_NEXT:
14394 if (s->nrows < 1) {
14395 return SQL_NO_DATA;
14396 }
14397 if (s->rowp < 0) {
14398 s->rowp = -1;
14399 }
14400 if (s->rowp >= s->nrows) {
14401 s->rowp = s->nrows;
14402 return SQL_NO_DATA;
14403 }
14404 break;
14405 case SQL_FETCH_PRIOR:
14406 if (s->nrows < 1) {
14407 s->rowp = -1;
14408 return SQL_NO_DATA;
14409 }
14410 s->rowp -= s->rowset_size + 1;
14411 if (s->rowp < -1) {
14412 s->rowp = -1;
14413 return SQL_NO_DATA;
14414 }
14415 break;
14416 case SQL_FETCH_FIRST:
14417 if (s->nrows < 1) {
14418 return SQL_NO_DATA;
14419 }
14420 s->rowp = -1;
14421 break;
14422 case SQL_FETCH_LAST:
14423 if (s->nrows < 1) {
14424 return SQL_NO_DATA;
14425 }
14426 s->rowp = s->nrows - s->rowset_size;
14427 if (--s->rowp < -1) {
14428 s->rowp = -1;
14429 }
14430 break;
14431 case SQL_FETCH_ABSOLUTE:
14432 if (offset == 0) {
14433 s->rowp = -1;
14434 return SQL_NO_DATA;
14435 } else if (offset < 0) {
14436 if (0 - offset <= s->nrows) {
14437 s->rowp = s->nrows + offset - 1;
14438 break;
14439 }
14440 s->rowp = -1;
14441 return SQL_NO_DATA;
14442 } else if (offset > s->nrows) {
14443 s->rowp = s->nrows;
14444 return SQL_NO_DATA;
14445 }
14446 s->rowp = offset - 1 - 1;
14447 break;
14448 case SQL_FETCH_RELATIVE:
14449 if (offset >= 0) {
14450 s->rowp += offset * s->rowset_size - 1;
14451 if (s->rowp >= s->nrows) {
14452 s->rowp = s->nrows;
14453 return SQL_NO_DATA;
14454 }
14455 } else {
14456 s->rowp += offset * s->rowset_size - 1;
14457 if (s->rowp < -1) {
14458 s->rowp = -1;
14459 return SQL_NO_DATA;
14460 }
14461 }
14462 break;
14463 case SQL_FETCH_BOOKMARK:
14464 if (s->bkmrk) {
14465 if (offset < 0 || offset >= s->nrows) {
14466 return SQL_NO_DATA;
14467 }
14468 s->rowp = offset - 1;
14469 break;
14470 }
14471 /* fall through */
14472 default:
14473 s->row_status0[0] = SQL_ROW_ERROR;
14474 ret = SQL_ERROR;
14475 goto done;
14476 }
14477 for (; i < s->rowset_size; i++) {
14478 ++s->rowp;
14479 if (s->rowp < 0 || s->rowp >= s->nrows) {
14480 break;
14481 }
14482 ret = dofetchbind(s, i);
14483 if (!SQL_SUCCEEDED(ret)) {
14484 break;
14485 } else if (ret == SQL_SUCCESS_WITH_INFO) {
14486 withinfo = 1;
14487 }
14488 }
14489 }
14490 done:
14491 if (i == 0) {
14492 if (SQL_SUCCEEDED(ret)) {
14493 return SQL_NO_DATA;
14494 }
14495 return ret;
14496 }
14497 if (SQL_SUCCEEDED(ret)) {
14498 ret = withinfo ? SQL_SUCCESS_WITH_INFO : SQL_SUCCESS;
14499 }
14500 done2:
14501 if (s->row_status) {
14502 memcpy(s->row_status, s->row_status0,
14503 sizeof (SQLUSMALLINT) * s->rowset_size);
14504 }
14505 s->row_count0 = i;
14506 if (s->row_count) {
14507 *s->row_count = s->row_count0;
14508 }
14509 return ret;
14510 }
14511
14512 /**
14513 * Fetch next result row.
14514 * @param stmt statement handle
14515 * @result ODBC error code
14516 */
14517
14518 SQLRETURN SQL_API
SQLFetch(SQLHSTMT stmt)14519 SQLFetch(SQLHSTMT stmt)
14520 {
14521 SQLRETURN ret;
14522
14523 HSTMT_LOCK(stmt);
14524 ret = drvfetchscroll(stmt, SQL_FETCH_NEXT, 0);
14525 HSTMT_UNLOCK(stmt);
14526 return ret;
14527 }
14528
14529 /**
14530 * Fetch result row with scrolling.
14531 * @param stmt statement handle
14532 * @param orient fetch direction
14533 * @param offset offset for fetch direction
14534 * @result ODBC error code
14535 */
14536
14537 SQLRETURN SQL_API
SQLFetchScroll(SQLHSTMT stmt,SQLSMALLINT orient,SQLLEN offset)14538 SQLFetchScroll(SQLHSTMT stmt, SQLSMALLINT orient, SQLLEN offset)
14539 {
14540 SQLRETURN ret;
14541
14542 HSTMT_LOCK(stmt);
14543 ret = drvfetchscroll(stmt, orient, offset);
14544 HSTMT_UNLOCK(stmt);
14545 return ret;
14546 }
14547
14548 /**
14549 * Fetch result row with scrolling and row status.
14550 * @param stmt statement handle
14551 * @param orient fetch direction
14552 * @param offset offset for fetch direction
14553 * @param rowcount output number of fetched rows
14554 * @param rowstatus array for row stati
14555 * @result ODBC error code
14556 */
14557
14558 SQLRETURN SQL_API
SQLExtendedFetch(SQLHSTMT stmt,SQLUSMALLINT orient,SQLROWOFFSET offset,SQLROWSETSIZE * rowcount,SQLUSMALLINT * rowstatus)14559 SQLExtendedFetch(SQLHSTMT stmt, SQLUSMALLINT orient, SQLROWOFFSET offset,
14560 SQLROWSETSIZE *rowcount, SQLUSMALLINT *rowstatus)
14561 {
14562 STMT *s;
14563 SQLRETURN ret;
14564 SQLUSMALLINT *rst;
14565
14566 HSTMT_LOCK(stmt);
14567 if (stmt == SQL_NULL_HSTMT) {
14568 return SQL_INVALID_HANDLE;
14569 }
14570 s = (STMT *) stmt;
14571 /* temporarily turn off SQL_ATTR_ROW_STATUS_PTR */
14572 rst = s->row_status;
14573 s->row_status = 0;
14574 ret = drvfetchscroll(stmt, orient, offset);
14575 s->row_status = rst;
14576 if (rowstatus) {
14577 memcpy(rowstatus, s->row_status0,
14578 sizeof (SQLUSMALLINT) * s->rowset_size);
14579 }
14580 if (rowcount) {
14581 *rowcount = s->row_count0;
14582 }
14583 HSTMT_UNLOCK(stmt);
14584 return ret;
14585 }
14586
14587 /**
14588 * Return number of affected rows of HSTMT.
14589 * @param stmt statement handle
14590 * @param nrows output number of rows
14591 * @result ODBC error code
14592 */
14593
14594 SQLRETURN SQL_API
SQLRowCount(SQLHSTMT stmt,SQLLEN * nrows)14595 SQLRowCount(SQLHSTMT stmt, SQLLEN *nrows)
14596 {
14597 STMT *s;
14598
14599 HSTMT_LOCK(stmt);
14600 if (stmt == SQL_NULL_HSTMT) {
14601 return SQL_INVALID_HANDLE;
14602 }
14603 s = (STMT *) stmt;
14604 if (nrows) {
14605 *nrows = s->nrows;
14606 }
14607 HSTMT_UNLOCK(stmt);
14608 return SQL_SUCCESS;
14609 }
14610
14611 /**
14612 * Return number of columns of result set given HSTMT.
14613 * @param stmt statement handle
14614 * @param ncols output number of columns
14615 * @result ODBC error code
14616 */
14617
14618 SQLRETURN SQL_API
SQLNumResultCols(SQLHSTMT stmt,SQLSMALLINT * ncols)14619 SQLNumResultCols(SQLHSTMT stmt, SQLSMALLINT *ncols)
14620 {
14621 STMT *s;
14622
14623 HSTMT_LOCK(stmt);
14624 if (stmt == SQL_NULL_HSTMT) {
14625 return SQL_INVALID_HANDLE;
14626 }
14627 s = (STMT *) stmt;
14628 if (ncols) {
14629 *ncols = s->ncols;
14630 }
14631 HSTMT_UNLOCK(stmt);
14632 return SQL_SUCCESS;
14633 }
14634
14635 /**
14636 * Internal describe column information.
14637 * @param stmt statement handle
14638 * @param col column number, starting at 1
14639 * @param name buffer for column name
14640 * @param nameMax length of name buffer
14641 * @param nameLen output length of column name
14642 * @param type output SQL type
14643 * @param size output column size
14644 * @param digits output number of digits
14645 * @param nullable output NULL allowed indicator
14646 * @result ODBC error code
14647 */
14648
14649 static SQLRETURN
drvdescribecol(SQLHSTMT stmt,SQLUSMALLINT col,SQLCHAR * name,SQLSMALLINT nameMax,SQLSMALLINT * nameLen,SQLSMALLINT * type,SQLULEN * size,SQLSMALLINT * digits,SQLSMALLINT * nullable)14650 drvdescribecol(SQLHSTMT stmt, SQLUSMALLINT col, SQLCHAR *name,
14651 SQLSMALLINT nameMax, SQLSMALLINT *nameLen,
14652 SQLSMALLINT *type, SQLULEN *size,
14653 SQLSMALLINT *digits, SQLSMALLINT *nullable)
14654 {
14655 STMT *s;
14656 COL *c;
14657 int didname = 0;
14658
14659 if (stmt == SQL_NULL_HSTMT) {
14660 return SQL_INVALID_HANDLE;
14661 }
14662 s = (STMT *) stmt;
14663 if (!s->cols) {
14664 setstat(s, -1, "no columns", (*s->ov3) ? "07009" : "S1002");
14665 return SQL_ERROR;
14666 }
14667 if (col < 1 || col > s->ncols) {
14668 setstat(s, -1, "invalid column", (*s->ov3) ? "07009" : "S1002");
14669 return SQL_ERROR;
14670 }
14671 c = s->cols + col - 1;
14672 if (name && nameMax > 0) {
14673 strncpy((char *) name, c->column, nameMax);
14674 name[nameMax - 1] = '\0';
14675 didname = 1;
14676 }
14677 if (nameLen) {
14678 if (didname) {
14679 *nameLen = strlen((char *) name);
14680 } else {
14681 *nameLen = strlen(c->column);
14682 }
14683 }
14684 if (type) {
14685 *type = c->type;
14686 #ifdef WINTERFACE
14687 if (s->nowchar[0] || s->nowchar[1]) {
14688 switch (c->type) {
14689 case SQL_WCHAR:
14690 *type = SQL_CHAR;
14691 break;
14692 case SQL_WVARCHAR:
14693 *type = SQL_VARCHAR;
14694 break;
14695 #ifdef SQL_LONGVARCHAR
14696 case SQL_WLONGVARCHAR:
14697 *type = SQL_LONGVARCHAR;
14698 break;
14699 #endif
14700 }
14701 }
14702 #endif
14703 }
14704 if (size) {
14705 *size = c->size;
14706 }
14707 if (digits) {
14708 *digits = 0;
14709 }
14710 if (nullable) {
14711 *nullable = 1;
14712 }
14713 return SQL_SUCCESS;
14714 }
14715
14716 #ifndef WINTERFACE
14717 /**
14718 * Describe column information.
14719 * @param stmt statement handle
14720 * @param col column number, starting at 1
14721 * @param name buffer for column name
14722 * @param nameMax length of name buffer
14723 * @param nameLen output length of column name
14724 * @param type output SQL type
14725 * @param size output column size
14726 * @param digits output number of digits
14727 * @param nullable output NULL allowed indicator
14728 * @result ODBC error code
14729 */
14730
14731 SQLRETURN SQL_API
SQLDescribeCol(SQLHSTMT stmt,SQLUSMALLINT col,SQLCHAR * name,SQLSMALLINT nameMax,SQLSMALLINT * nameLen,SQLSMALLINT * type,SQLULEN * size,SQLSMALLINT * digits,SQLSMALLINT * nullable)14732 SQLDescribeCol(SQLHSTMT stmt, SQLUSMALLINT col, SQLCHAR *name,
14733 SQLSMALLINT nameMax, SQLSMALLINT *nameLen,
14734 SQLSMALLINT *type, SQLULEN *size,
14735 SQLSMALLINT *digits, SQLSMALLINT *nullable)
14736 {
14737 #if defined(_WIN32) || defined(_WIN64)
14738 SQLSMALLINT len = 0;
14739 #endif
14740 SQLRETURN ret;
14741
14742 HSTMT_LOCK(stmt);
14743 #if defined(_WIN32) || defined(_WIN64)
14744 if (!((STMT *) stmt)->oemcp[0]) {
14745 ret = drvdescribecol(stmt, col, name, nameMax, nameLen,
14746 type, size, digits, nullable);
14747 goto done;
14748 }
14749 ret = drvdescribecol(stmt, col, name, nameMax,
14750 &len, type, size, digits, nullable);
14751 if (ret == SQL_SUCCESS) {
14752 if (name) {
14753 if (len > 0) {
14754 SQLCHAR *n = NULL;
14755
14756 n = (SQLCHAR *) utf_to_wmb((char *) name, len);
14757 if (n) {
14758 strncpy((char *) name, (char *) n, nameMax);
14759 n[len] = 0;
14760 len = min(nameMax, strlen((char *) n));
14761 uc_free(n);
14762 } else {
14763 len = 0;
14764 }
14765 }
14766 if (len <= 0) {
14767 len = 0;
14768 if (nameMax > 0) {
14769 name[0] = 0;
14770 }
14771 }
14772 } else {
14773 STMT *s = (STMT *) stmt;
14774 COL *c = s->cols + col - 1;
14775
14776 len = 0;
14777 if (c->column) {
14778 len = strlen(c->column);
14779 }
14780 }
14781 if (nameLen) {
14782 *nameLen = len;
14783 }
14784 }
14785 done:
14786 ;
14787 #else
14788 ret = drvdescribecol(stmt, col, name, nameMax, nameLen,
14789 type, size, digits, nullable);
14790 #endif
14791 HSTMT_UNLOCK(stmt);
14792 return ret;
14793 }
14794 #endif
14795
14796 #ifdef WINTERFACE
14797 /**
14798 * Describe column information (UNICODE version).
14799 * @param stmt statement handle
14800 * @param col column number, starting at 1
14801 * @param name buffer for column name
14802 * @param nameMax length of name buffer
14803 * @param nameLen output length of column name
14804 * @param type output SQL type
14805 * @param size output column size
14806 * @param digits output number of digits
14807 * @param nullable output NULL allowed indicator
14808 * @result ODBC error code
14809 */
14810
14811 SQLRETURN SQL_API
SQLDescribeColW(SQLHSTMT stmt,SQLUSMALLINT col,SQLWCHAR * name,SQLSMALLINT nameMax,SQLSMALLINT * nameLen,SQLSMALLINT * type,SQLULEN * size,SQLSMALLINT * digits,SQLSMALLINT * nullable)14812 SQLDescribeColW(SQLHSTMT stmt, SQLUSMALLINT col, SQLWCHAR *name,
14813 SQLSMALLINT nameMax, SQLSMALLINT *nameLen,
14814 SQLSMALLINT *type, SQLULEN *size,
14815 SQLSMALLINT *digits, SQLSMALLINT *nullable)
14816 {
14817 SQLRETURN ret;
14818 SQLSMALLINT len = 0;
14819
14820 HSTMT_LOCK(stmt);
14821 ret = drvdescribecol(stmt, col, (SQLCHAR *) name,
14822 (SQLSMALLINT) (nameMax * sizeof (SQLWCHAR)),
14823 &len, type, size, digits, nullable);
14824 if (ret == SQL_SUCCESS) {
14825 if (name) {
14826 if (len > 0) {
14827 SQLWCHAR *n = NULL;
14828
14829 n = uc_from_utf((SQLCHAR *) name, len);
14830 if (n) {
14831 uc_strncpy(name, n, nameMax);
14832 n[len] = 0;
14833 len = min(nameMax, uc_strlen(n));
14834 uc_free(n);
14835 } else {
14836 len = 0;
14837 }
14838 }
14839 if (len <= 0) {
14840 len = 0;
14841 if (nameMax > 0) {
14842 name[0] = 0;
14843 }
14844 }
14845 } else {
14846 STMT *s = (STMT *) stmt;
14847 COL *c = s->cols + col - 1;
14848
14849 len = 0;
14850 if (c->column) {
14851 len = strlen(c->column);
14852 }
14853 }
14854 if (nameLen) {
14855 *nameLen = len;
14856 }
14857 }
14858 HSTMT_UNLOCK(stmt);
14859 return ret;
14860 }
14861 #endif
14862
14863 /**
14864 * Internal retrieve column attributes.
14865 * @param stmt statement handle
14866 * @param col column number, starting at 1
14867 * @param id attribute id
14868 * @param val output buffer
14869 * @param valMax length of output buffer
14870 * @param valLen output length
14871 * @param val2 integer output buffer
14872 * @result ODBC error code
14873 */
14874
14875 static SQLRETURN
drvcolattributes(SQLHSTMT stmt,SQLUSMALLINT col,SQLUSMALLINT id,SQLPOINTER val,SQLSMALLINT valMax,SQLSMALLINT * valLen,SQLLEN * val2)14876 drvcolattributes(SQLHSTMT stmt, SQLUSMALLINT col, SQLUSMALLINT id,
14877 SQLPOINTER val, SQLSMALLINT valMax, SQLSMALLINT *valLen,
14878 SQLLEN *val2)
14879 {
14880 STMT *s;
14881 COL *c;
14882 SQLSMALLINT dummy;
14883 char *valc = (char *) val;
14884
14885 if (stmt == SQL_NULL_HSTMT) {
14886 return SQL_INVALID_HANDLE;
14887 }
14888 s = (STMT *) stmt;
14889 if (!s->cols) {
14890 return SQL_ERROR;
14891 }
14892 if (!valLen) {
14893 valLen = &dummy;
14894 }
14895 if (id == SQL_COLUMN_COUNT) {
14896 if (val2) {
14897 *val2 = s->ncols;
14898 }
14899 *valLen = sizeof (int);
14900 return SQL_SUCCESS;
14901 }
14902 if (id == SQL_COLUMN_TYPE && col == 0) {
14903 if (val2) {
14904 *val2 = SQL_INTEGER;
14905 }
14906 *valLen = sizeof (int);
14907 return SQL_SUCCESS;
14908 }
14909 #ifdef SQL_DESC_OCTET_LENGTH
14910 if (id == SQL_DESC_OCTET_LENGTH && col == 0) {
14911 if (val2) {
14912 *val2 = 4;
14913 }
14914 *valLen = sizeof (int);
14915 return SQL_SUCCESS;
14916 }
14917 #endif
14918 if (col < 1 || col > s->ncols) {
14919 setstat(s, -1, "invalid column", (*s->ov3) ? "07009": "S1002");
14920 return SQL_ERROR;
14921 }
14922 c = s->cols + col - 1;
14923
14924 switch (id) {
14925 case SQL_COLUMN_LABEL:
14926 if (c->label) {
14927 if (valc && valMax > 0) {
14928 strncpy(valc, c->label, valMax);
14929 valc[valMax - 1] = '\0';
14930 }
14931 *valLen = strlen(c->label);
14932 goto checkLen;
14933 }
14934 /* fall through */
14935 case SQL_COLUMN_NAME:
14936 case SQL_DESC_NAME:
14937 if (valc && valMax > 0) {
14938 strncpy(valc, c->column, valMax);
14939 valc[valMax - 1] = '\0';
14940 }
14941 *valLen = strlen(c->column);
14942 checkLen:
14943 if (*valLen >= valMax) {
14944 setstat(s, -1, "data right truncated", "01004");
14945 return SQL_SUCCESS_WITH_INFO;
14946 }
14947 return SQL_SUCCESS;
14948 #ifdef SQL_DESC_BASE_COLUMN_NAME
14949 if (strchr(c->column, '(') || strchr(c->column, ')')) {
14950 valc[0] = '\0';
14951 *valLen = 0;
14952 } else if (valc && valMax > 0) {
14953 strncpy(valc, c->column, valMax);
14954 valc[valMax - 1] = '\0';
14955 *valLen = strlen(c->column);
14956 }
14957 goto checkLen;
14958 #endif
14959 case SQL_COLUMN_TYPE:
14960 case SQL_DESC_TYPE:
14961 #ifdef WINTERFACE
14962 {
14963 int type = c->type;
14964
14965 if (s->nowchar[0] || s->nowchar[1]) {
14966 switch (type) {
14967 case SQL_WCHAR:
14968 type = SQL_CHAR;
14969 break;
14970 case SQL_WVARCHAR:
14971 type = SQL_VARCHAR;
14972 break;
14973 #ifdef SQL_LONGVARCHAR
14974 case SQL_WLONGVARCHAR:
14975 type = SQL_LONGVARCHAR;
14976 break;
14977 }
14978 }
14979 if (val2) {
14980 *val2 = type;
14981 }
14982 #endif
14983 }
14984 #else
14985 if (val2) {
14986 *val2 = c->type;
14987 }
14988 #endif
14989 *valLen = sizeof (int);
14990 return SQL_SUCCESS;
14991 case SQL_COLUMN_DISPLAY_SIZE:
14992 if (val2) {
14993 *val2 = c->size;
14994 }
14995 *valLen = sizeof (int);
14996 return SQL_SUCCESS;
14997 case SQL_COLUMN_UNSIGNED:
14998 if (val2) {
14999 *val2 = c->nosign ? SQL_TRUE : SQL_FALSE;
15000 }
15001 *valLen = sizeof (int);
15002 return SQL_SUCCESS;
15003 case SQL_COLUMN_SCALE:
15004 case SQL_DESC_SCALE:
15005 if (val2) {
15006 *val2 = c->scale;
15007 }
15008 *valLen = sizeof (int);
15009 return SQL_SUCCESS;
15010 case SQL_COLUMN_PRECISION:
15011 case SQL_DESC_PRECISION:
15012 if (val2) {
15013 switch (c->type) {
15014 case SQL_SMALLINT:
15015 *val2 = 5;
15016 break;
15017 case SQL_INTEGER:
15018 *val2 = 10;
15019 break;
15020 case SQL_FLOAT:
15021 case SQL_REAL:
15022 case SQL_DOUBLE:
15023 *val2 = 15;
15024 break;
15025 case SQL_DATE:
15026 *val2 = 0;
15027 break;
15028 case SQL_TIME:
15029 *val2 = 0;
15030 break;
15031 #ifdef SQL_TYPE_TIMESTAMP
15032 case SQL_TYPE_TIMESTAMP:
15033 #endif
15034 case SQL_TIMESTAMP:
15035 *val2 = (c->prec >= 0 && c->prec <= 3) ? c->prec : 3;
15036 break;
15037 default:
15038 *val2 = c->prec;
15039 break;
15040 }
15041 }
15042 *valLen = sizeof (int);
15043 return SQL_SUCCESS;
15044 case SQL_COLUMN_MONEY:
15045 if (val2) {
15046 *val2 = SQL_FALSE;
15047 }
15048 *valLen = sizeof (int);
15049 return SQL_SUCCESS;
15050 case SQL_COLUMN_AUTO_INCREMENT:
15051 if (val2) {
15052 *val2 = c->autoinc;
15053 }
15054 *valLen = sizeof (int);
15055 return SQL_SUCCESS;
15056 case SQL_COLUMN_LENGTH:
15057 case SQL_DESC_LENGTH:
15058 if (val2) {
15059 *val2 = c->size;
15060 }
15061 *valLen = sizeof (int);
15062 return SQL_SUCCESS;
15063 case SQL_COLUMN_NULLABLE:
15064 case SQL_DESC_NULLABLE:
15065 if (val2) {
15066 *val2 = c->notnull;
15067 }
15068 *valLen = sizeof (int);
15069 return SQL_SUCCESS;
15070 case SQL_COLUMN_SEARCHABLE:
15071 if (val2) {
15072 *val2 = SQL_SEARCHABLE;
15073 }
15074 *valLen = sizeof (int);
15075 return SQL_SUCCESS;
15076 case SQL_COLUMN_CASE_SENSITIVE:
15077 if (val2) {
15078 *val2 = SQL_TRUE;
15079 }
15080 *valLen = sizeof (int);
15081 return SQL_SUCCESS;
15082 case SQL_COLUMN_UPDATABLE:
15083 if (val2) {
15084 *val2 = SQL_TRUE;
15085 }
15086 *valLen = sizeof (int);
15087 return SQL_SUCCESS;
15088 case SQL_DESC_COUNT:
15089 if (val2) {
15090 *val2 = s->ncols;
15091 }
15092 *valLen = sizeof (int);
15093 return SQL_SUCCESS;
15094 case SQL_COLUMN_TYPE_NAME: {
15095 char *p = NULL, *tn = c->typename ? c->typename : "varchar";
15096
15097 #ifdef WINTERFACE
15098 if (c->type == SQL_WCHAR ||
15099 c->type == SQL_WVARCHAR ||
15100 c->type == SQL_WLONGVARCHAR) {
15101 if (!(s->nowchar[0] || s->nowchar[1])) {
15102 if (strcasecmp(tn, "varchar") == 0) {
15103 tn = "wvarchar";
15104 }
15105 }
15106 }
15107 #endif
15108 if (valc && valMax > 0) {
15109 strncpy(valc, tn, valMax);
15110 valc[valMax - 1] = '\0';
15111 p = strchr(valc, '(');
15112 if (p) {
15113 *p = '\0';
15114 while (p > valc && ISSPACE(p[-1])) {
15115 --p;
15116 *p = '\0';
15117 }
15118 }
15119 *valLen = strlen(valc);
15120 } else {
15121 *valLen = strlen(tn);
15122 p = strchr(tn, '(');
15123 if (p) {
15124 *valLen = p - tn;
15125 while (p > tn && ISSPACE(p[-1])) {
15126 --p;
15127 *valLen -= 1;
15128 }
15129 }
15130 }
15131 goto checkLen;
15132 }
15133 case SQL_COLUMN_OWNER_NAME:
15134 case SQL_COLUMN_QUALIFIER_NAME: {
15135 char *z = "";
15136
15137 if (valc && valMax > 0) {
15138 strncpy(valc, z, valMax);
15139 valc[valMax - 1] = '\0';
15140 }
15141 *valLen = strlen(z);
15142 goto checkLen;
15143 }
15144 case SQL_COLUMN_TABLE_NAME:
15145 #if (SQL_COLUMN_TABLE_NAME != SQL_DESC_TABLE_NAME)
15146 case SQL_DESC_TABLE_NAME:
15147 #endif
15148 #ifdef SQL_DESC_BASE_TABLE_NAME
15149 case SQL_DESC_BASE_TABLE_NAME:
15150 #endif
15151 if (valc && valMax > 0) {
15152 strncpy(valc, c->table, valMax);
15153 valc[valMax - 1] = '\0';
15154 }
15155 *valLen = strlen(c->table);
15156 goto checkLen;
15157 #ifdef SQL_DESC_NUM_PREC_RADIX
15158 case SQL_DESC_NUM_PREC_RADIX:
15159 if (val2) {
15160 switch (c->type) {
15161 #ifdef WINTERFACE
15162 case SQL_WCHAR:
15163 case SQL_WVARCHAR:
15164 #ifdef SQL_LONGVARCHAR
15165 case SQL_WLONGVARCHAR:
15166 #endif
15167 #endif
15168 case SQL_CHAR:
15169 case SQL_VARCHAR:
15170 #ifdef SQL_LONGVARCHAR
15171 case SQL_LONGVARCHAR:
15172 #endif
15173 case SQL_BINARY:
15174 case SQL_VARBINARY:
15175 case SQL_LONGVARBINARY:
15176 *val2 = 0;
15177 break;
15178 default:
15179 *val2 = 2;
15180 }
15181 }
15182 *valLen = sizeof (int);
15183 return SQL_SUCCESS;
15184 #endif
15185 }
15186 setstat(s, -1, "unsupported column attributes %d", "HY091", id);
15187 return SQL_ERROR;
15188 }
15189
15190 #ifndef WINTERFACE
15191 /**
15192 * Retrieve column attributes.
15193 * @param stmt statement handle
15194 * @param col column number, starting at 1
15195 * @param id attribute id
15196 * @param val output buffer
15197 * @param valMax length of output buffer
15198 * @param valLen output length
15199 * @param val2 integer output buffer
15200 * @result ODBC error code
15201 */
15202
15203 SQLRETURN SQL_API
SQLColAttributes(SQLHSTMT stmt,SQLUSMALLINT col,SQLUSMALLINT id,SQLPOINTER val,SQLSMALLINT valMax,SQLSMALLINT * valLen,SQLLEN * val2)15204 SQLColAttributes(SQLHSTMT stmt, SQLUSMALLINT col, SQLUSMALLINT id,
15205 SQLPOINTER val, SQLSMALLINT valMax, SQLSMALLINT *valLen,
15206 SQLLEN *val2)
15207 {
15208 #if defined(_WIN32) || defined(_WIN64)
15209 SQLSMALLINT len = 0;
15210 #endif
15211 SQLRETURN ret;
15212
15213 HSTMT_LOCK(stmt);
15214 #if defined(_WIN32) || defined(_WIN64)
15215 if (!((STMT *) stmt)->oemcp[0]) {
15216 ret = drvcolattributes(stmt, col, id, val, valMax, valLen, val2);
15217 goto done;
15218 }
15219 ret = drvcolattributes(stmt, col, id, val, valMax, &len, val2);
15220 if (SQL_SUCCEEDED(ret)) {
15221 char *v = NULL;
15222
15223 switch (id) {
15224 case SQL_COLUMN_LABEL:
15225 case SQL_COLUMN_NAME:
15226 case SQL_DESC_NAME:
15227 case SQL_COLUMN_TYPE_NAME:
15228 case SQL_COLUMN_OWNER_NAME:
15229 case SQL_COLUMN_QUALIFIER_NAME:
15230 case SQL_COLUMN_TABLE_NAME:
15231 #if (SQL_COLUMN_TABLE_NAME != SQL_DESC_TABLE_NAME)
15232 case SQL_DESC_TABLE_NAME:
15233 #endif
15234 #ifdef SQL_DESC_BASE_COLUMN_NAME
15235 case SQL_DESC_BASE_COLUMN_NAME:
15236 #endif
15237 #ifdef SQL_DESC_BASE_TABLE_NAME
15238 case SQL_DESC_BASE_TABLE_NAME:
15239 #endif
15240 if (val && valMax > 0) {
15241 int vmax = valMax;
15242
15243 v = utf_to_wmb((char *) val, SQL_NTS);
15244 if (v) {
15245 strncpy(val, v, vmax);
15246 len = min(vmax, strlen(v));
15247 uc_free(v);
15248 }
15249 if (vmax > 0) {
15250 v = (char *) val;
15251 v[vmax - 1] = '\0';
15252 }
15253 }
15254 if (len <= 0) {
15255 len = 0;
15256 }
15257 break;
15258 }
15259 if (valLen) {
15260 *valLen = len;
15261 }
15262 }
15263 done:
15264 ;
15265 #else
15266 ret = drvcolattributes(stmt, col, id, val, valMax, valLen, val2);
15267 #endif
15268 HSTMT_UNLOCK(stmt);
15269 return ret;
15270 }
15271 #endif
15272
15273 #ifdef WINTERFACE
15274 /**
15275 * Retrieve column attributes (UNICODE version).
15276 * @param stmt statement handle
15277 * @param col column number, starting at 1
15278 * @param id attribute id
15279 * @param val output buffer
15280 * @param valMax length of output buffer
15281 * @param valLen output length
15282 * @param val2 integer output buffer
15283 * @result ODBC error code
15284 */
15285
15286 SQLRETURN SQL_API
SQLColAttributesW(SQLHSTMT stmt,SQLUSMALLINT col,SQLUSMALLINT id,SQLPOINTER val,SQLSMALLINT valMax,SQLSMALLINT * valLen,SQLLEN * val2)15287 SQLColAttributesW(SQLHSTMT stmt, SQLUSMALLINT col, SQLUSMALLINT id,
15288 SQLPOINTER val, SQLSMALLINT valMax, SQLSMALLINT *valLen,
15289 SQLLEN *val2)
15290 {
15291 SQLRETURN ret;
15292 SQLSMALLINT len = 0;
15293
15294 HSTMT_LOCK(stmt);
15295 ret = drvcolattributes(stmt, col, id, val, valMax, &len, val2);
15296 if (SQL_SUCCEEDED(ret)) {
15297 SQLWCHAR *v = NULL;
15298
15299 switch (id) {
15300 case SQL_COLUMN_LABEL:
15301 case SQL_COLUMN_NAME:
15302 case SQL_DESC_NAME:
15303 case SQL_COLUMN_TYPE_NAME:
15304 case SQL_COLUMN_OWNER_NAME:
15305 case SQL_COLUMN_QUALIFIER_NAME:
15306 case SQL_COLUMN_TABLE_NAME:
15307 #if (SQL_COLUMN_TABLE_NAME != SQL_DESC_TABLE_NAME)
15308 case SQL_DESC_TABLE_NAME:
15309 #endif
15310 #ifdef SQL_DESC_BASE_COLUMN_NAME
15311 case SQL_DESC_BASE_COLUMN_NAME:
15312 #endif
15313 #ifdef SQL_DESC_BASE_TABLE_NAME
15314 case SQL_DESC_BASE_TABLE_NAME:
15315 #endif
15316 if (val && valMax > 0) {
15317 int vmax = valMax / sizeof (SQLWCHAR);
15318
15319 v = uc_from_utf((SQLCHAR *) val, SQL_NTS);
15320 if (v) {
15321 uc_strncpy(val, v, vmax);
15322 len = min(vmax, uc_strlen(v));
15323 uc_free(v);
15324 len *= sizeof (SQLWCHAR);
15325 }
15326 if (vmax > 0) {
15327 v = (SQLWCHAR *) val;
15328 v[vmax - 1] = '\0';
15329 }
15330 }
15331 if (len <= 0) {
15332 len = 0;
15333 }
15334 break;
15335 }
15336 if (valLen) {
15337 *valLen = len;
15338 }
15339 }
15340 HSTMT_UNLOCK(stmt);
15341 return ret;
15342 }
15343 #endif
15344
15345 /**
15346 * Internal retrieve column attributes.
15347 * @param stmt statement handle
15348 * @param col column number, starting at 1
15349 * @param id attribute id
15350 * @param val output buffer
15351 * @param valMax length of output buffer
15352 * @param valLen output length
15353 * @param val2 integer output buffer
15354 * @result ODBC error code
15355 */
15356
15357 static SQLRETURN
drvcolattribute(SQLHSTMT stmt,SQLUSMALLINT col,SQLUSMALLINT id,SQLPOINTER val,SQLSMALLINT valMax,SQLSMALLINT * valLen,SQLPOINTER val2)15358 drvcolattribute(SQLHSTMT stmt, SQLUSMALLINT col, SQLUSMALLINT id,
15359 SQLPOINTER val, SQLSMALLINT valMax, SQLSMALLINT *valLen,
15360 SQLPOINTER val2)
15361 {
15362 STMT *s;
15363 COL *c;
15364 int v = 0;
15365 char *valc = (char *) val;
15366 SQLSMALLINT dummy;
15367
15368 if (stmt == SQL_NULL_HSTMT) {
15369 return SQL_INVALID_HANDLE;
15370 }
15371 s = (STMT *) stmt;
15372 if (!s->cols) {
15373 return SQL_ERROR;
15374 }
15375 if (col < 1 || col > s->ncols) {
15376 setstat(s, -1, "invalid column", (*s->ov3) ? "07009" : "S1002");
15377 return SQL_ERROR;
15378 }
15379 if (!valLen) {
15380 valLen = &dummy;
15381 }
15382 c = s->cols + col - 1;
15383 switch (id) {
15384 case SQL_DESC_COUNT:
15385 v = s->ncols;
15386 break;
15387 case SQL_DESC_CATALOG_NAME:
15388 if (valc && valMax > 0) {
15389 strncpy(valc, c->db, valMax);
15390 valc[valMax - 1] = '\0';
15391 }
15392 *valLen = strlen(c->db);
15393 checkLen:
15394 if (*valLen >= valMax) {
15395 setstat(s, -1, "data right truncated", "01004");
15396 return SQL_SUCCESS_WITH_INFO;
15397 }
15398 break;
15399 case SQL_COLUMN_LENGTH:
15400 case SQL_DESC_LENGTH:
15401 v = c->size;
15402 break;
15403 case SQL_COLUMN_LABEL:
15404 if (c->label) {
15405 if (valc && valMax > 0) {
15406 strncpy(valc, c->label, valMax);
15407 valc[valMax - 1] = '\0';
15408 }
15409 *valLen = strlen(c->label);
15410 goto checkLen;
15411 }
15412 /* fall through */
15413 case SQL_COLUMN_NAME:
15414 case SQL_DESC_NAME:
15415 if (valc && valMax > 0) {
15416 strncpy(valc, c->column, valMax);
15417 valc[valMax - 1] = '\0';
15418 }
15419 *valLen = strlen(c->column);
15420 goto checkLen;
15421 case SQL_DESC_SCHEMA_NAME: {
15422 char *z = "";
15423
15424 if (valc && valMax > 0) {
15425 strncpy(valc, z, valMax);
15426 valc[valMax - 1] = '\0';
15427 }
15428 *valLen = strlen(z);
15429 goto checkLen;
15430 }
15431 #ifdef SQL_DESC_BASE_COLUMN_NAME
15432 case SQL_DESC_BASE_COLUMN_NAME:
15433 if (strchr(c->column, '(') || strchr(c->column, ')')) {
15434 valc[0] = '\0';
15435 *valLen = 0;
15436 } else if (valc && valMax > 0) {
15437 strncpy(valc, c->column, valMax);
15438 valc[valMax - 1] = '\0';
15439 *valLen = strlen(c->column);
15440 }
15441 goto checkLen;
15442 #endif
15443 case SQL_DESC_TYPE_NAME: {
15444 char *p = NULL, *tn = c->typename ? c->typename : "varchar";
15445
15446 #ifdef WINTERFACE
15447 if (c->type == SQL_WCHAR ||
15448 c->type == SQL_WVARCHAR ||
15449 c->type == SQL_WLONGVARCHAR) {
15450 if (!(s->nowchar[0] || s->nowchar[1])) {
15451 if (strcasecmp(tn, "varchar") == 0) {
15452 tn = "wvarchar";
15453 }
15454 }
15455 }
15456 #endif
15457 if (valc && valMax > 0) {
15458 strncpy(valc, tn, valMax);
15459 valc[valMax - 1] = '\0';
15460 p = strchr(valc, '(');
15461 if (p) {
15462 *p = '\0';
15463 while (p > valc && ISSPACE(p[-1])) {
15464 --p;
15465 *p = '\0';
15466 }
15467 }
15468 *valLen = strlen(valc);
15469 } else {
15470 *valLen = strlen(tn);
15471 p = strchr(tn, '(');
15472 if (p) {
15473 *valLen = p - tn;
15474 while (p > tn && ISSPACE(p[-1])) {
15475 --p;
15476 *valLen -= 1;
15477 }
15478 }
15479 }
15480 goto checkLen;
15481 }
15482 case SQL_DESC_OCTET_LENGTH:
15483 v = c->size;
15484 #ifdef WINTERFACE
15485 if (c->type == SQL_WCHAR ||
15486 c->type == SQL_WVARCHAR ||
15487 c->type == SQL_WLONGVARCHAR) {
15488 if (!(s->nowchar[0] || s->nowchar[1])) {
15489 v *= sizeof (SQLWCHAR);
15490 }
15491 }
15492 #endif
15493 break;
15494 #if (SQL_COLUMN_TABLE_NAME != SQL_DESC_TABLE_NAME)
15495 case SQL_COLUMN_TABLE_NAME:
15496 #endif
15497 #ifdef SQL_DESC_BASE_TABLE_NAME
15498 case SQL_DESC_BASE_TABLE_NAME:
15499 #endif
15500 case SQL_DESC_TABLE_NAME:
15501 if (valc && valMax > 0) {
15502 strncpy(valc, c->table, valMax);
15503 valc[valMax - 1] = '\0';
15504 }
15505 *valLen = strlen(c->table);
15506 goto checkLen;
15507 case SQL_DESC_TYPE:
15508 v = c->type;
15509 #ifdef WINTERFACE
15510 if (s->nowchar[0] || s->nowchar[1]) {
15511 switch (v) {
15512 case SQL_WCHAR:
15513 v = SQL_CHAR;
15514 break;
15515 case SQL_WVARCHAR:
15516 v = SQL_VARCHAR;
15517 break;
15518 #ifdef SQL_LONGVARCHAR
15519 case SQL_WLONGVARCHAR:
15520 v = SQL_LONGVARCHAR;
15521 break;
15522 #endif
15523 }
15524 }
15525 #endif
15526 break;
15527 case SQL_DESC_CONCISE_TYPE:
15528 switch (c->type) {
15529 case SQL_INTEGER:
15530 v = SQL_C_LONG;
15531 break;
15532 case SQL_TINYINT:
15533 v = SQL_C_TINYINT;
15534 break;
15535 case SQL_SMALLINT:
15536 v = SQL_C_SHORT;
15537 break;
15538 case SQL_FLOAT:
15539 v = SQL_C_FLOAT;
15540 break;
15541 case SQL_DOUBLE:
15542 v = SQL_C_DOUBLE;
15543 break;
15544 case SQL_TIMESTAMP:
15545 v = SQL_C_TIMESTAMP;
15546 break;
15547 case SQL_TIME:
15548 v = SQL_C_TIME;
15549 break;
15550 case SQL_DATE:
15551 v = SQL_C_DATE;
15552 break;
15553 #ifdef SQL_C_TYPE_TIMESTAMP
15554 case SQL_TYPE_TIMESTAMP:
15555 v = SQL_C_TYPE_TIMESTAMP;
15556 break;
15557 #endif
15558 #ifdef SQL_C_TYPE_TIME
15559 case SQL_TYPE_TIME:
15560 v = SQL_C_TYPE_TIME;
15561 break;
15562 #endif
15563 #ifdef SQL_C_TYPE_DATE
15564 case SQL_TYPE_DATE:
15565 v = SQL_C_TYPE_DATE;
15566 break;
15567 #endif
15568 #ifdef SQL_BIT
15569 case SQL_BIT:
15570 v = SQL_C_BIT;
15571 break;
15572 #endif
15573 #ifdef SQL_BIGINT
15574 case SQL_BIGINT:
15575 v = SQL_C_SBIGINT;
15576 break;
15577 #endif
15578 default:
15579 #ifdef WINTERFACE
15580 v = (s->nowchar[0] || s->nowchar[1]) ? SQL_C_CHAR : SQL_C_WCHAR;
15581 #else
15582 v = SQL_C_CHAR;
15583 #endif
15584 break;
15585 }
15586 break;
15587 case SQL_DESC_UPDATABLE:
15588 v = SQL_TRUE;
15589 break;
15590 case SQL_COLUMN_DISPLAY_SIZE:
15591 v = c->size;
15592 break;
15593 case SQL_COLUMN_UNSIGNED:
15594 v = c->nosign ? SQL_TRUE : SQL_FALSE;
15595 break;
15596 case SQL_COLUMN_SEARCHABLE:
15597 v = SQL_SEARCHABLE;
15598 break;
15599 case SQL_COLUMN_SCALE:
15600 case SQL_DESC_SCALE:
15601 v = c->scale;
15602 break;
15603 case SQL_COLUMN_PRECISION:
15604 case SQL_DESC_PRECISION:
15605 switch (c->type) {
15606 case SQL_SMALLINT:
15607 v = 5;
15608 break;
15609 case SQL_INTEGER:
15610 v = 10;
15611 break;
15612 case SQL_FLOAT:
15613 case SQL_REAL:
15614 case SQL_DOUBLE:
15615 v = 15;
15616 break;
15617 case SQL_DATE:
15618 v = 0;
15619 break;
15620 case SQL_TIME:
15621 v = 0;
15622 break;
15623 #ifdef SQL_TYPE_TIMESTAMP
15624 case SQL_TYPE_TIMESTAMP:
15625 #endif
15626 case SQL_TIMESTAMP:
15627 v = (c->prec >= 0 && c->prec <= 3) ? c->prec : 3;
15628 break;
15629 default:
15630 v = c->prec;
15631 break;
15632 }
15633 break;
15634 case SQL_COLUMN_MONEY:
15635 v = SQL_FALSE;
15636 break;
15637 case SQL_COLUMN_AUTO_INCREMENT:
15638 v = c->autoinc;
15639 break;
15640 case SQL_DESC_NULLABLE:
15641 v = c->notnull;
15642 break;
15643 #ifdef SQL_DESC_NUM_PREC_RADIX
15644 case SQL_DESC_NUM_PREC_RADIX:
15645 switch (c->type) {
15646 #ifdef WINTERFACE
15647 case SQL_WCHAR:
15648 case SQL_WVARCHAR:
15649 #ifdef SQL_LONGVARCHAR
15650 case SQL_WLONGVARCHAR:
15651 #endif
15652 #endif
15653 case SQL_CHAR:
15654 case SQL_VARCHAR:
15655 #ifdef SQL_LONGVARCHAR
15656 case SQL_LONGVARCHAR:
15657 #endif
15658 case SQL_BINARY:
15659 case SQL_VARBINARY:
15660 case SQL_LONGVARBINARY:
15661 v = 0;
15662 break;
15663 default:
15664 v = 2;
15665 }
15666 break;
15667 #endif
15668 default:
15669 setstat(s, -1, "unsupported column attribute %d", "HY091", id);
15670 return SQL_ERROR;
15671 }
15672 if (val2) {
15673 *(SQLLEN *) val2 = v;
15674 }
15675 return SQL_SUCCESS;
15676 }
15677
15678 #ifndef WINTERFACE
15679 /**
15680 * Retrieve column attributes.
15681 * @param stmt statement handle
15682 * @param col column number, starting at 1
15683 * @param id attribute id
15684 * @param val output buffer
15685 * @param valMax length of output buffer
15686 * @param valLen output length
15687 * @param val2 integer output buffer
15688 * @result ODBC error code
15689 */
15690
15691 SQLRETURN SQL_API
SQLColAttribute(SQLHSTMT stmt,SQLUSMALLINT col,SQLUSMALLINT id,SQLPOINTER val,SQLSMALLINT valMax,SQLSMALLINT * valLen,COLATTRIBUTE_LAST_ARG_TYPE val2)15692 SQLColAttribute(SQLHSTMT stmt, SQLUSMALLINT col, SQLUSMALLINT id,
15693 SQLPOINTER val, SQLSMALLINT valMax, SQLSMALLINT *valLen,
15694 COLATTRIBUTE_LAST_ARG_TYPE val2)
15695 {
15696 #if defined(_WIN32) || defined(_WIN64)
15697 SQLSMALLINT len = 0;
15698 #endif
15699 SQLRETURN ret;
15700
15701 HSTMT_LOCK(stmt);
15702 #if defined(_WIN32) || defined(_WIN64)
15703 if (!((STMT *) stmt)->oemcp[0]) {
15704 ret = drvcolattribute(stmt, col, id, val, valMax, valLen,
15705 (SQLPOINTER) val2);
15706 goto done;
15707 }
15708 ret = drvcolattribute(stmt, col, id, val, valMax, &len,
15709 (SQLPOINTER) val2);
15710 if (SQL_SUCCEEDED(ret)) {
15711 char *v = NULL;
15712
15713 switch (id) {
15714 case SQL_DESC_SCHEMA_NAME:
15715 case SQL_DESC_CATALOG_NAME:
15716 case SQL_COLUMN_LABEL:
15717 case SQL_DESC_NAME:
15718 case SQL_DESC_TABLE_NAME:
15719 #ifdef SQL_DESC_BASE_TABLE_NAME
15720 case SQL_DESC_BASE_TABLE_NAME:
15721 #endif
15722 #ifdef SQL_DESC_BASE_COLUMN_NAME
15723 case SQL_DESC_BASE_COLUMN_NAME:
15724 #endif
15725 case SQL_DESC_TYPE_NAME:
15726 if (val && valMax > 0) {
15727 int vmax = valMax;
15728
15729 v = utf_to_wmb((char *) val, SQL_NTS);
15730 if (v) {
15731 strncpy(val, v, vmax);
15732 len = min(vmax, strlen(v));
15733 uc_free(v);
15734 }
15735 if (vmax > 0) {
15736 v = (char *) val;
15737 v[vmax - 1] = '\0';
15738 }
15739 }
15740 if (len <= 0) {
15741 len = 0;
15742 }
15743 break;
15744 }
15745 if (valLen) {
15746 *valLen = len;
15747 }
15748 }
15749 done:
15750 ;
15751 #else
15752 ret = drvcolattribute(stmt, col, id, val, valMax, valLen,
15753 (SQLPOINTER) val2);
15754 #endif
15755 HSTMT_UNLOCK(stmt);
15756 return ret;
15757 }
15758 #endif
15759
15760 #ifdef WINTERFACE
15761 /**
15762 * Retrieve column attributes (UNICODE version).
15763 * @param stmt statement handle
15764 * @param col column number, starting at 1
15765 * @param id attribute id
15766 * @param val output buffer
15767 * @param valMax length of output buffer
15768 * @param valLen output length
15769 * @param val2 integer output buffer
15770 * @result ODBC error code
15771 */
15772
15773 SQLRETURN SQL_API
SQLColAttributeW(SQLHSTMT stmt,SQLUSMALLINT col,SQLUSMALLINT id,SQLPOINTER val,SQLSMALLINT valMax,SQLSMALLINT * valLen,COLATTRIBUTE_LAST_ARG_TYPE val2)15774 SQLColAttributeW(SQLHSTMT stmt, SQLUSMALLINT col, SQLUSMALLINT id,
15775 SQLPOINTER val, SQLSMALLINT valMax, SQLSMALLINT *valLen,
15776 COLATTRIBUTE_LAST_ARG_TYPE val2)
15777 {
15778 SQLRETURN ret;
15779 SQLSMALLINT len = 0;
15780
15781 HSTMT_LOCK(stmt);
15782 ret = drvcolattribute(stmt, col, id, val, valMax, &len,
15783 (SQLPOINTER) val2);
15784 if (SQL_SUCCEEDED(ret)) {
15785 SQLWCHAR *v = NULL;
15786
15787 switch (id) {
15788 case SQL_DESC_SCHEMA_NAME:
15789 case SQL_DESC_CATALOG_NAME:
15790 case SQL_COLUMN_LABEL:
15791 case SQL_DESC_NAME:
15792 case SQL_DESC_TABLE_NAME:
15793 #ifdef SQL_DESC_BASE_TABLE_NAME
15794 case SQL_DESC_BASE_TABLE_NAME:
15795 #endif
15796 #ifdef SQL_DESC_BASE_COLUMN_NAME
15797 case SQL_DESC_BASE_COLUMN_NAME:
15798 #endif
15799 case SQL_DESC_TYPE_NAME:
15800 if (val && valMax > 0) {
15801 int vmax = valMax / sizeof (SQLWCHAR);
15802
15803 v = uc_from_utf((SQLCHAR *) val, SQL_NTS);
15804 if (v) {
15805 uc_strncpy(val, v, vmax);
15806 len = min(vmax, uc_strlen(v));
15807 uc_free(v);
15808 len *= sizeof (SQLWCHAR);
15809 }
15810 if (vmax > 0) {
15811 v = (SQLWCHAR *) val;
15812 v[vmax - 1] = '\0';
15813 }
15814 }
15815 if (len <= 0) {
15816 len = 0;
15817 }
15818 break;
15819 }
15820 if (valLen) {
15821 *valLen = len;
15822 }
15823 }
15824 HSTMT_UNLOCK(stmt);
15825 return ret;
15826 }
15827 #endif
15828
15829 /**
15830 * Internal return last HDBC or HSTMT error message.
15831 * @param env environment handle or NULL
15832 * @param dbc database connection handle or NULL
15833 * @param stmt statement handle or NULL
15834 * @param sqlState output buffer for SQL state
15835 * @param nativeErr output buffer for native error code
15836 * @param errmsg output buffer for error message
15837 * @param errmax length of output buffer for error message
15838 * @param errlen output length of error message
15839 * @result ODBC error code
15840 */
15841
15842 static SQLRETURN
drverror(SQLHENV env,SQLHDBC dbc,SQLHSTMT stmt,SQLCHAR * sqlState,SQLINTEGER * nativeErr,SQLCHAR * errmsg,SQLSMALLINT errmax,SQLSMALLINT * errlen)15843 drverror(SQLHENV env, SQLHDBC dbc, SQLHSTMT stmt,
15844 SQLCHAR *sqlState, SQLINTEGER *nativeErr,
15845 SQLCHAR *errmsg, SQLSMALLINT errmax, SQLSMALLINT *errlen)
15846 {
15847 SQLCHAR dummy0[6];
15848 SQLINTEGER dummy1;
15849 SQLSMALLINT dummy2;
15850
15851 if (env == SQL_NULL_HENV &&
15852 dbc == SQL_NULL_HDBC &&
15853 stmt == SQL_NULL_HSTMT) {
15854 return SQL_INVALID_HANDLE;
15855 }
15856 if (sqlState) {
15857 sqlState[0] = '\0';
15858 } else {
15859 sqlState = dummy0;
15860 }
15861 if (!nativeErr) {
15862 nativeErr = &dummy1;
15863 }
15864 *nativeErr = 0;
15865 if (!errlen) {
15866 errlen = &dummy2;
15867 }
15868 *errlen = 0;
15869 if (errmsg) {
15870 if (errmax > 0) {
15871 errmsg[0] = '\0';
15872 }
15873 } else {
15874 errmsg = dummy0;
15875 errmax = 0;
15876 }
15877 if (stmt) {
15878 STMT *s = (STMT *) stmt;
15879
15880 HSTMT_LOCK(stmt);
15881 if (s->logmsg[0] == '\0') {
15882 HSTMT_UNLOCK(stmt);
15883 goto noerr;
15884 }
15885 *nativeErr = s->naterr;
15886 strcpy((char *) sqlState, s->sqlstate);
15887 if (errmax == SQL_NTS) {
15888 strcpy((char *) errmsg, "[SQLite]");
15889 strcat((char *) errmsg, (char *) s->logmsg);
15890 *errlen = strlen((char *) errmsg);
15891 } else {
15892 strncpy((char *) errmsg, "[SQLite]", errmax);
15893 if (errmax - 8 > 0) {
15894 strncpy((char *) errmsg + 8, (char *) s->logmsg, errmax - 8);
15895 }
15896 *errlen = min(strlen((char *) s->logmsg) + 8, errmax);
15897 }
15898 s->logmsg[0] = '\0';
15899 HSTMT_UNLOCK(stmt);
15900 return SQL_SUCCESS;
15901 }
15902 if (dbc) {
15903 DBC *d = (DBC *) dbc;
15904
15905 HDBC_LOCK(dbc);
15906 if (d->magic != DBC_MAGIC || d->logmsg[0] == '\0') {
15907 HDBC_UNLOCK(dbc);
15908 goto noerr;
15909 }
15910 *nativeErr = d->naterr;
15911 strcpy((char *) sqlState, d->sqlstate);
15912 if (errmax == SQL_NTS) {
15913 strcpy((char *) errmsg, "[SQLite]");
15914 strcat((char *) errmsg, (char *) d->logmsg);
15915 *errlen = strlen((char *) errmsg);
15916 } else {
15917 strncpy((char *) errmsg, "[SQLite]", errmax);
15918 if (errmax - 8 > 0) {
15919 strncpy((char *) errmsg + 8, (char *) d->logmsg, errmax - 8);
15920 }
15921 *errlen = min(strlen((char *) d->logmsg) + 8, errmax);
15922 }
15923 d->logmsg[0] = '\0';
15924 HDBC_UNLOCK(dbc);
15925 return SQL_SUCCESS;
15926 }
15927 noerr:
15928 sqlState[0] = '\0';
15929 errmsg[0] = '\0';
15930 *nativeErr = 0;
15931 *errlen = 0;
15932 return SQL_NO_DATA;
15933 }
15934
15935 #ifndef WINTERFACE
15936 /**
15937 * Return last HDBC or HSTMT error message.
15938 * @param env environment handle or NULL
15939 * @param dbc database connection handle or NULL
15940 * @param stmt statement handle or NULL
15941 * @param sqlState output buffer for SQL state
15942 * @param nativeErr output buffer for native error code
15943 * @param errmsg output buffer for error message
15944 * @param errmax length of output buffer for error message
15945 * @param errlen output length of error message
15946 * @result ODBC error code
15947 */
15948
15949 SQLRETURN SQL_API
SQLError(SQLHENV env,SQLHDBC dbc,SQLHSTMT stmt,SQLCHAR * sqlState,SQLINTEGER * nativeErr,SQLCHAR * errmsg,SQLSMALLINT errmax,SQLSMALLINT * errlen)15950 SQLError(SQLHENV env, SQLHDBC dbc, SQLHSTMT stmt,
15951 SQLCHAR *sqlState, SQLINTEGER *nativeErr,
15952 SQLCHAR *errmsg, SQLSMALLINT errmax, SQLSMALLINT *errlen)
15953 {
15954 return drverror(env, dbc, stmt, sqlState, nativeErr,
15955 errmsg, errmax, errlen);
15956 }
15957 #endif
15958
15959 #ifdef WINTERFACE
15960 /**
15961 * Return last HDBC or HSTMT error message (UNICODE version).
15962 * @param env environment handle or NULL
15963 * @param dbc database connection handle or NULL
15964 * @param stmt statement handle or NULL
15965 * @param sqlState output buffer for SQL state
15966 * @param nativeErr output buffer for native error code
15967 * @param errmsg output buffer for error message
15968 * @param errmax length of output buffer for error message
15969 * @param errlen output length of error message
15970 * @result ODBC error code
15971 */
15972
15973 SQLRETURN SQL_API
SQLErrorW(SQLHENV env,SQLHDBC dbc,SQLHSTMT stmt,SQLWCHAR * sqlState,SQLINTEGER * nativeErr,SQLWCHAR * errmsg,SQLSMALLINT errmax,SQLSMALLINT * errlen)15974 SQLErrorW(SQLHENV env, SQLHDBC dbc, SQLHSTMT stmt,
15975 SQLWCHAR *sqlState, SQLINTEGER *nativeErr,
15976 SQLWCHAR *errmsg, SQLSMALLINT errmax, SQLSMALLINT *errlen)
15977 {
15978 char state[16];
15979 SQLSMALLINT len = 0;
15980 SQLRETURN ret;
15981
15982 ret = drverror(env, dbc, stmt, (SQLCHAR *) state, nativeErr,
15983 (SQLCHAR *) errmsg, errmax, &len);
15984 if (ret == SQL_SUCCESS) {
15985 if (sqlState) {
15986 uc_from_utf_buf((SQLCHAR *) state, -1, sqlState,
15987 6 * sizeof (SQLWCHAR));
15988 }
15989 if (errmsg) {
15990 if (len > 0) {
15991 SQLWCHAR *e = NULL;
15992
15993 e = uc_from_utf((SQLCHAR *) errmsg, len);
15994 if (e) {
15995 if (errmax > 0) {
15996 uc_strncpy(errmsg, e, errmax);
15997 e[len] = 0;
15998 len = min(errmax, uc_strlen(e));
15999 } else {
16000 len = uc_strlen(e);
16001 }
16002 uc_free(e);
16003 } else {
16004 len = 0;
16005 }
16006 }
16007 if (len <= 0) {
16008 len = 0;
16009 if (errmax > 0) {
16010 errmsg[0] = 0;
16011 }
16012 }
16013 } else {
16014 len = 0;
16015 }
16016 if (errlen) {
16017 *errlen = len;
16018 }
16019 } else if (ret == SQL_NO_DATA) {
16020 if (sqlState) {
16021 sqlState[0] = 0;
16022 }
16023 if (errmsg) {
16024 if (errmax > 0) {
16025 errmsg[0] = 0;
16026 }
16027 }
16028 if (errlen) {
16029 *errlen = 0;
16030 }
16031 }
16032 return ret;
16033 }
16034 #endif
16035
16036 /**
16037 * Return information for more result sets.
16038 * @param stmt statement handle
16039 * @result ODBC error code
16040 */
16041
16042 SQLRETURN SQL_API
SQLMoreResults(SQLHSTMT stmt)16043 SQLMoreResults(SQLHSTMT stmt)
16044 {
16045 HSTMT_LOCK(stmt);
16046 if (stmt == SQL_NULL_HSTMT) {
16047 return SQL_INVALID_HANDLE;
16048 }
16049 HSTMT_UNLOCK(stmt);
16050 return SQL_NO_DATA;
16051 }
16052
16053 /**
16054 * Internal function to setup column name/type information
16055 * @param s statement poiner
16056 * @param s3stmt SQLite3 statement pointer
16057 * @param ncolsp pointer to preinitialized number of colums
16058 * @result ODBC error code
16059 */
16060
16061 static SQLRETURN
setupdyncols(STMT * s,sqlite3_stmt * s3stmt,int * ncolsp)16062 setupdyncols(STMT *s, sqlite3_stmt *s3stmt, int *ncolsp)
16063 {
16064 int ncols = *ncolsp, guessed_types = 0;
16065 SQLRETURN ret = SQL_SUCCESS;
16066
16067 if (ncols > 0) {
16068 int i;
16069 PTRDIFF_T size;
16070 char *p;
16071 COL *dyncols;
16072 DBC *d = (DBC *) s->dbc;
16073 const char *colname, *typename;
16074 #if defined(HAVE_SQLITE3COLUMNTABLENAME) && (HAVE_SQLITE3COLUMNTABLENAME)
16075 char *tblname;
16076 #endif
16077
16078 for (i = size = 0; i < ncols; i++) {
16079 colname = sqlite3_column_name(s3stmt, i);
16080 size += 3 + 3 * strlen(colname);
16081 }
16082 #if defined(HAVE_SQLITE3COLUMNTABLENAME) && (HAVE_SQLITE3COLUMNTABLENAME)
16083 tblname = (char *) size;
16084 for (i = 0; i < ncols; i++) {
16085 p = (char *) sqlite3_column_table_name(s3stmt, i);
16086 size += 2 + (p ? strlen(p) : 0);
16087 }
16088 #endif
16089 dyncols = xmalloc(ncols * sizeof (COL) + size);
16090 if (!dyncols) {
16091 freedyncols(s);
16092 *ncolsp = 0;
16093 ret = SQL_ERROR;
16094 } else {
16095 p = (char *) (dyncols + ncols);
16096 #if defined(HAVE_SQLITE3COLUMNTABLENAME) && (HAVE_SQLITE3COLUMNTABLENAME)
16097 tblname = p + (PTRDIFF_T) tblname;
16098 #endif
16099 for (i = 0; i < ncols; i++) {
16100 char *q;
16101
16102 colname = sqlite3_column_name(s3stmt, i);
16103 if (d->trace) {
16104 fprintf(d->trace, "-- column %d name: '%s'\n",
16105 i + 1, colname);
16106 fflush(d->trace);
16107 }
16108 #if defined(HAVE_SQLITE3COLUMNTABLENAME) && (HAVE_SQLITE3COLUMNTABLENAME)
16109 q = (char *) sqlite3_column_table_name(s3stmt, i);
16110 strcpy(tblname, q ? q : "");
16111 if (d->trace) {
16112 fprintf(d->trace, "-- table %d name: '%s'\n",
16113 i + 1, tblname);
16114 fflush(d->trace);
16115 }
16116 dyncols[i].table = tblname;
16117 tblname += strlen(tblname) + 1;
16118 #endif
16119 typename = s3stmt_coltype(s3stmt, i, d, &guessed_types);
16120 dyncols[i].db = ((DBC *) (s->dbc))->dbname;
16121 strcpy(p, colname);
16122 dyncols[i].label = p;
16123 p += strlen(p) + 1;
16124 q = strchr(colname, '.');
16125 if (q) {
16126 char *q2 = strchr(q + 1, '.');
16127
16128 /* SQLite 3.3.4 produces view.table.column sometimes */
16129 if (q2) {
16130 q = q2;
16131 }
16132 }
16133 if (q) {
16134 #if !defined(HAVE_SQLITE3COLUMNTABLENAME) || !(HAVE_SQLITE3COLUMNTABLENAME)
16135 dyncols[i].table = p;
16136 #endif
16137 strncpy(p, colname, q - colname);
16138 p[q - colname] = '\0';
16139 p += strlen(p) + 1;
16140 strcpy(p, q + 1);
16141 dyncols[i].column = p;
16142 p += strlen(p) + 1;
16143 } else {
16144 #if !defined(HAVE_SQLITE3COLUMNTABLENAME) || !(HAVE_SQLITE3COLUMNTABLENAME)
16145 dyncols[i].table = "";
16146 #endif
16147 strcpy(p, colname);
16148 dyncols[i].column = p;
16149 p += strlen(p) + 1;
16150 }
16151 if (s->longnames) {
16152 dyncols[i].column = dyncols[i].label;
16153 }
16154 #ifdef SQL_LONGVARCHAR
16155 dyncols[i].type = SQL_LONGVARCHAR;
16156 dyncols[i].size = 65535;
16157 #else
16158 dyncols[i].type = SQL_VARCHAR;
16159 dyncols[i].size = 255;
16160 #endif
16161 dyncols[i].index = i;
16162 dyncols[i].scale = 0;
16163 dyncols[i].prec = 0;
16164 dyncols[i].nosign = 1;
16165 #if defined(HAVE_SQLITE3TABLECOLUMNMETADATA) && (HAVE_SQLITE3TABLECOLUMNMETADATA)
16166 s3stmt_addmeta(s3stmt, i, d, &dyncols[i]);
16167 #else
16168 dyncols[i].autoinc = SQL_FALSE;
16169 dyncols[i].notnull = SQL_NULLABLE;
16170 #endif
16171 dyncols[i].typename = xstrdup(typename);
16172 }
16173 freedyncols(s);
16174 s->dyncols = s->cols = dyncols;
16175 s->dcols = ncols;
16176 fixupdyncols(s, d);
16177 s->guessed_types = guessed_types;
16178 }
16179 }
16180 return ret;
16181 }
16182
16183 /**
16184 * Internal query preparation used by SQLPrepare() and SQLExecDirect().
16185 * @param stmt statement handle
16186 * @param query query string
16187 * @param queryLen length of query string or SQL_NTS
16188 * @result ODBC error code
16189 */
16190
16191 static SQLRETURN
drvprepare(SQLHSTMT stmt,SQLCHAR * query,SQLINTEGER queryLen)16192 drvprepare(SQLHSTMT stmt, SQLCHAR *query, SQLINTEGER queryLen)
16193 {
16194 STMT *s;
16195 DBC *d;
16196 char *errp = NULL;
16197 SQLRETURN sret;
16198
16199 if (stmt == SQL_NULL_HSTMT) {
16200 return SQL_INVALID_HANDLE;
16201 }
16202 s = (STMT *) stmt;
16203 if (s->dbc == SQL_NULL_HDBC) {
16204 noconn:
16205 return noconn(s);
16206 }
16207 d = s->dbc;
16208 if (!d->sqlite) {
16209 goto noconn;
16210 }
16211 s3stmt_end(s);
16212 s3stmt_drop(s);
16213 sret = starttran(s);
16214 if (sret != SQL_SUCCESS) {
16215 return sret;
16216 }
16217 freep(&s->query);
16218 s->query = (SQLCHAR *) fixupsql((char *) query, queryLen,
16219 &s->nparams, &s->isselect, &errp);
16220 if (!s->query) {
16221 if (errp) {
16222 setstat(s, -1, "%s", (*s->ov3) ? "HY000" : "S1000", errp);
16223 return SQL_ERROR;
16224 }
16225 return nomem(s);
16226 }
16227 errp = NULL;
16228 freeresult(s, -1);
16229 if (s->isselect > 0) {
16230 int ret, ncols, nretry = 0;
16231 const char *rest;
16232 sqlite3_stmt *s3stmt = NULL;
16233
16234 #if defined(HAVE_SQLITE3PREPAREV2) && (HAVE_SQLITE3PREPAREV2)
16235 dbtraceapi(d, "sqlite3_prepare_v2", (char *) s->query);
16236 #else
16237 dbtraceapi(d, "sqlite3_prepare", (char *) s->query);
16238 #endif
16239 do {
16240 s3stmt = NULL;
16241 #if defined(HAVE_SQLITE3PREPAREV2) && (HAVE_SQLITE3PREPAREV2)
16242 ret = sqlite3_prepare_v2(d->sqlite, (char *) s->query, -1,
16243 &s3stmt, &rest);
16244 #else
16245 ret = sqlite3_prepare(d->sqlite, (char *) s->query, -1,
16246 &s3stmt, &rest);
16247 #endif
16248 if (ret != SQLITE_OK) {
16249 if (s3stmt) {
16250 sqlite3_finalize(s3stmt);
16251 s3stmt = NULL;
16252 }
16253 }
16254 } while (ret == SQLITE_SCHEMA && (++nretry) < 2);
16255 dbtracerc(d, ret, NULL);
16256 if (ret != SQLITE_OK) {
16257 if (s3stmt) {
16258 dbtraceapi(d, "sqlite3_finalize", 0);
16259 sqlite3_finalize(s3stmt);
16260 }
16261 setstat(s, ret, "%s (%d)", (*s->ov3) ? "HY000" : "S1000",
16262 sqlite3_errmsg(d->sqlite), ret);
16263 return SQL_ERROR;
16264 }
16265 if (sqlite3_bind_parameter_count(s3stmt) != s->nparams) {
16266 dbtraceapi(d, "sqlite3_finalize", 0);
16267 sqlite3_finalize(s3stmt);
16268 setstat(s, SQLITE_ERROR, "parameter marker count incorrect",
16269 (*s->ov3) ? "HY000" : "S1000");
16270 return SQL_ERROR;
16271 }
16272 ncols = sqlite3_column_count(s3stmt);
16273 s->guessed_types = 0;
16274 setupdyncols(s, s3stmt, &ncols);
16275 s->ncols = ncols;
16276 s->s3stmt = s3stmt;
16277 }
16278 mkbindcols(s, s->ncols);
16279 s->paramset_count = 0;
16280 return SQL_SUCCESS;
16281 }
16282
16283 /**
16284 * Internal query execution used by SQLExecute() and SQLExecDirect().
16285 * @param stmt statement handle
16286 * @param initial false when called from SQLPutData()
16287 * @result ODBC error code
16288 */
16289
16290 static SQLRETURN
drvexecute(SQLHSTMT stmt,int initial)16291 drvexecute(SQLHSTMT stmt, int initial)
16292 {
16293 STMT *s;
16294 DBC *d;
16295 char *errp = NULL;
16296 int rc, i, ncols = 0, nrows = 0, busy_count;
16297 SQLRETURN ret;
16298
16299 if (stmt == SQL_NULL_HSTMT) {
16300 return SQL_INVALID_HANDLE;
16301 }
16302 s = (STMT *) stmt;
16303 if (s->dbc == SQL_NULL_HDBC) {
16304 noconn:
16305 return noconn(s);
16306 }
16307 d = (DBC *) s->dbc;
16308 if (!d->sqlite) {
16309 goto noconn;
16310 }
16311 if (!s->query) {
16312 setstat(s, -1, "no query prepared", (*s->ov3) ? "HY000" : "S1000");
16313 return SQL_ERROR;
16314 }
16315 if (s->nbindparms < s->nparams) {
16316 unbound:
16317 setstat(s, -1, "unbound parameters in query",
16318 (*s->ov3) ? "HY000" : "S1000");
16319 return SQL_ERROR;
16320 }
16321 for (i = 0; i < s->nparams; i++) {
16322 BINDPARM *p = &s->bindparms[i];
16323
16324 if (!p->bound) {
16325 goto unbound;
16326 }
16327 if (initial) {
16328 SQLLEN *lenp = p->lenp;
16329
16330 if (lenp && *lenp < 0 && *lenp > SQL_LEN_DATA_AT_EXEC_OFFSET &&
16331 *lenp != SQL_NTS && *lenp != SQL_NULL_DATA) {
16332 setstat(s, -1, "invalid length reference", "HY009");
16333 return SQL_ERROR;
16334 }
16335 if (lenp && *lenp <= SQL_LEN_DATA_AT_EXEC_OFFSET) {
16336 p->need = 1;
16337 p->offs = 0;
16338 p->len = 0;
16339 }
16340 }
16341 }
16342 ret = starttran(s);
16343 if (ret != SQL_SUCCESS) {
16344 goto cleanup;
16345 }
16346 busy_count = 0;
16347 again:
16348 s3stmt_end(s);
16349 if (initial) {
16350 /* fixup data-at-execution parameters and alloc'ed blobs */
16351 for (i = 0; i < s->nparams; i++) {
16352 BINDPARM *p = &s->bindparms[i];
16353
16354 if (p->param == p->parbuf) {
16355 p->param = NULL;
16356 }
16357 freep(&p->parbuf);
16358 if (p->need <= 0 &&
16359 p->lenp && *p->lenp <= SQL_LEN_DATA_AT_EXEC_OFFSET) {
16360 p->need = 1;
16361 p->offs = 0;
16362 p->len = 0;
16363 }
16364 }
16365 }
16366 if (s->nparams) {
16367 for (i = 0; i < s->nparams; i++) {
16368 ret = setupparam(s, (char *) s->query, i);
16369 if (ret != SQL_SUCCESS) {
16370 goto cleanup;
16371 }
16372 }
16373 }
16374 freeresult(s, 0);
16375 if (s->isselect > 0 && !d->intrans &&
16376 s->curtype == SQL_CURSOR_FORWARD_ONLY &&
16377 d->step_enable && s->nparams == 0 && d->cur_s3stmt == NULL) {
16378 s->nrows = -1;
16379 ret = s3stmt_start(s);
16380 if (ret == SQL_SUCCESS) {
16381 goto done2;
16382 }
16383 }
16384 rc = drvgettable(s, s->s3stmt ? NULL : (char *) s->query, &s->rows,
16385 &s->nrows, &ncols, &errp, s->nparams, s->bindparms);
16386 dbtracerc(d, rc, errp);
16387 if (rc == SQLITE_BUSY) {
16388 if (busy_handler((void *) d, ++busy_count)) {
16389 if (errp) {
16390 sqlite3_free(errp);
16391 errp = NULL;
16392 }
16393 for (i = 0; i < s->nparams; i++) {
16394 BINDPARM *p = &s->bindparms[i];
16395
16396 if (p->param == p->parbuf) {
16397 p->param = NULL;
16398 }
16399 freep(&p->parbuf);
16400 if (!p->lenp || *p->lenp > SQL_LEN_DATA_AT_EXEC_OFFSET) {
16401 p->param = p->param0;
16402 }
16403 p->lenp = p->lenp0;
16404 }
16405 s->nrows = 0;
16406 goto again;
16407 }
16408 }
16409 if (rc != SQLITE_OK) {
16410 setstat(s, rc, "%s (%d)", (*s->ov3) ? "HY000" : "S1000",
16411 errp ? errp : "unknown error", rc);
16412 if (errp) {
16413 sqlite3_free(errp);
16414 errp = NULL;
16415 }
16416 ret = SQL_ERROR;
16417 goto cleanup;
16418 }
16419 if (errp) {
16420 sqlite3_free(errp);
16421 errp = NULL;
16422 }
16423 s->rowfree = freerows;
16424 if (!s->isselect) {
16425 /*
16426 * INSERT/UPDATE/DELETE results are immediately released.
16427 */
16428 freeresult(s, -1);
16429 nrows += sqlite3_changes(d->sqlite);
16430 s->nrows = nrows;
16431 goto done;
16432 }
16433 if (s->ncols != ncols) {
16434 /*
16435 * Weird result.
16436 */
16437 setstat(s, -1, "broken result set %d/%d",
16438 (*s->ov3) ? "HY000" : "S1000", s->ncols, ncols);
16439 ret = SQL_ERROR;
16440 goto cleanup;
16441 }
16442 done:
16443 mkbindcols(s, s->ncols);
16444 done2:
16445 ret = SQL_SUCCESS;
16446 s->rowp = -1;
16447 s->paramset_count++;
16448 s->paramset_nrows = s->nrows;
16449 if (s->paramset_count < s->paramset_size) {
16450 for (i = 0; i < s->nparams; i++) {
16451 BINDPARM *p = &s->bindparms[i];
16452
16453 if (p->param == p->parbuf) {
16454 p->param = NULL;
16455 }
16456 freep(&p->parbuf);
16457 if (p->lenp0 &&
16458 s->parm_bind_type != SQL_PARAM_BIND_BY_COLUMN) {
16459 p->lenp = (SQLLEN *) ((char *) p->lenp0 +
16460 s->paramset_count * s->parm_bind_type);
16461 } else if (p->lenp0 && p->inc > 0) {
16462 p->lenp = p->lenp0 + s->paramset_count;
16463 }
16464 if (!p->lenp || *p->lenp > SQL_LEN_DATA_AT_EXEC_OFFSET) {
16465 if (p->param0 &&
16466 s->parm_bind_type != SQL_PARAM_BIND_BY_COLUMN) {
16467 p->param = (char *) p->param0 +
16468 s->paramset_count * s->parm_bind_type;
16469 } else if (p->param0 && p->inc > 0) {
16470 p->param = (char *) p->param0 +
16471 s->paramset_count * p->inc;
16472 }
16473 } else if (p->lenp && *p->lenp <= SQL_LEN_DATA_AT_EXEC_OFFSET) {
16474 p->need = 1;
16475 p->offs = 0;
16476 p->len = 0;
16477 }
16478 }
16479 goto again;
16480 }
16481 cleanup:
16482 if (ret != SQL_NEED_DATA) {
16483 for (i = 0; i < s->nparams; i++) {
16484 BINDPARM *p = &s->bindparms[i];
16485
16486 if (p->param == p->parbuf) {
16487 p->param = NULL;
16488 }
16489 freep(&p->parbuf);
16490 if (!p->lenp || *p->lenp > SQL_LEN_DATA_AT_EXEC_OFFSET) {
16491 p->param = p->param0;
16492 }
16493 p->lenp = p->lenp0;
16494 }
16495 s->nrows = s->paramset_nrows;
16496 if (s->parm_proc) {
16497 *s->parm_proc = s->paramset_count;
16498 }
16499 s->paramset_count = 0;
16500 s->paramset_nrows = 0;
16501 }
16502 if (*s->ov3 && !s->isselect && ret == SQL_SUCCESS && nrows == 0) {
16503 ret = SQL_NO_DATA;
16504 }
16505 return ret;
16506 }
16507
16508 #ifndef WINTERFACE
16509 /**
16510 * Prepare HSTMT.
16511 * @param stmt statement handle
16512 * @param query query string
16513 * @param queryLen length of query string or SQL_NTS
16514 * @result ODBC error code
16515 */
16516
16517 SQLRETURN SQL_API
SQLPrepare(SQLHSTMT stmt,SQLCHAR * query,SQLINTEGER queryLen)16518 SQLPrepare(SQLHSTMT stmt, SQLCHAR *query, SQLINTEGER queryLen)
16519 {
16520 SQLRETURN ret;
16521 #if defined(_WIN32) || defined(_WIN64)
16522 char *q;
16523 #endif
16524
16525 HSTMT_LOCK(stmt);
16526 #if defined(_WIN32) || defined(_WIN64)
16527 if (!((STMT *) stmt)->oemcp[0]) {
16528 ret = drvprepare(stmt, query, queryLen);
16529 goto done;
16530 }
16531 q = wmb_to_utf_c((char *) query, queryLen);
16532 if (!q) {
16533 ret = nomem((STMT *) stmt);
16534 goto done;
16535 }
16536 query = (SQLCHAR *) q;
16537 queryLen = SQL_NTS;
16538 #endif
16539 ret = drvprepare(stmt, query, queryLen);
16540 #if defined(_WIN32) || defined(_WIN64)
16541 uc_free(q);
16542 done:
16543 ;
16544 #endif
16545 HSTMT_UNLOCK(stmt);
16546 return ret;
16547 }
16548 #endif
16549
16550 #ifdef WINTERFACE
16551 /**
16552 * Prepare HSTMT (UNICODE version).
16553 * @param stmt statement handle
16554 * @param query query string
16555 * @param queryLen length of query string or SQL_NTS
16556 * @result ODBC error code
16557 */
16558
16559 SQLRETURN SQL_API
SQLPrepareW(SQLHSTMT stmt,SQLWCHAR * query,SQLINTEGER queryLen)16560 SQLPrepareW(SQLHSTMT stmt, SQLWCHAR *query, SQLINTEGER queryLen)
16561 {
16562 SQLRETURN ret;
16563 char *q = uc_to_utf_c(query, queryLen);
16564
16565 HSTMT_LOCK(stmt);
16566 if (!q) {
16567 ret = nomem((STMT *) stmt);
16568 goto done;
16569 }
16570 ret = drvprepare(stmt, (SQLCHAR *) q, SQL_NTS);
16571 uc_free(q);
16572 done:
16573 HSTMT_UNLOCK(stmt);
16574 return ret;
16575 }
16576 #endif
16577
16578 /**
16579 * Execute query.
16580 * @param stmt statement handle
16581 * @result ODBC error code
16582 */
16583
16584 SQLRETURN SQL_API
SQLExecute(SQLHSTMT stmt)16585 SQLExecute(SQLHSTMT stmt)
16586 {
16587 SQLRETURN ret;
16588
16589 HSTMT_LOCK(stmt);
16590 ret = drvexecute(stmt, 1);
16591 HSTMT_UNLOCK(stmt);
16592 return ret;
16593 }
16594
16595 #ifndef WINTERFACE
16596 /**
16597 * Execute query directly.
16598 * @param stmt statement handle
16599 * @param query query string
16600 * @param queryLen length of query string or SQL_NTS
16601 * @result ODBC error code
16602 */
16603
16604 SQLRETURN SQL_API
SQLExecDirect(SQLHSTMT stmt,SQLCHAR * query,SQLINTEGER queryLen)16605 SQLExecDirect(SQLHSTMT stmt, SQLCHAR *query, SQLINTEGER queryLen)
16606 {
16607 SQLRETURN ret;
16608 #if defined(_WIN32) || defined(_WIN64)
16609 char *q;
16610 #endif
16611
16612 HSTMT_LOCK(stmt);
16613 #if defined(_WIN32) || defined(_WIN64)
16614 if (!((STMT *) stmt)->oemcp[0]) {
16615 ret = drvprepare(stmt, query, queryLen);
16616 if (ret == SQL_SUCCESS) {
16617 ret = drvexecute(stmt, 1);
16618 }
16619 goto done;
16620 }
16621 q = wmb_to_utf_c((char *) query, queryLen);
16622 if (!q) {
16623 ret = nomem((STMT *) stmt);
16624 goto done;
16625 }
16626 query = (SQLCHAR *) q;
16627 queryLen = SQL_NTS;
16628 #endif
16629 ret = drvprepare(stmt, query, queryLen);
16630 if (ret == SQL_SUCCESS) {
16631 ret = drvexecute(stmt, 1);
16632 }
16633 #if defined(_WIN32) || defined(_WIN64)
16634 uc_free(q);
16635 done:
16636 ;
16637 #endif
16638 HSTMT_UNLOCK(stmt);
16639 return ret;
16640 }
16641 #endif
16642
16643 #ifdef WINTERFACE
16644 /**
16645 * Execute query directly (UNICODE version).
16646 * @param stmt statement handle
16647 * @param query query string
16648 * @param queryLen length of query string or SQL_NTS
16649 * @result ODBC error code
16650 */
16651
16652 SQLRETURN SQL_API
SQLExecDirectW(SQLHSTMT stmt,SQLWCHAR * query,SQLINTEGER queryLen)16653 SQLExecDirectW(SQLHSTMT stmt, SQLWCHAR *query, SQLINTEGER queryLen)
16654 {
16655 SQLRETURN ret;
16656 char *q = uc_to_utf_c(query, queryLen);
16657
16658 HSTMT_LOCK(stmt);
16659 if (!q) {
16660 ret = nomem((STMT *) stmt);
16661 goto done;
16662 }
16663 ret = drvprepare(stmt, (SQLCHAR *) q, SQL_NTS);
16664 uc_free(q);
16665 if (ret == SQL_SUCCESS) {
16666 ret = drvexecute(stmt, 1);
16667 }
16668 done:
16669 HSTMT_UNLOCK(stmt);
16670 return ret;
16671 }
16672 #endif
16673
16674
16675 #if defined(_WIN32) || defined(_WIN64)
16676 #ifndef WITHOUT_DRIVERMGR
16677
16678 /*
16679 * Windows configuration dialog stuff.
16680 */
16681
16682 #include <windowsx.h>
16683 #include <winuser.h>
16684
16685 #define MAXPATHLEN (255+1) /* Max path length */
16686 #define MAXKEYLEN (15+1) /* Max keyword length */
16687 #define MAXDESC (255+1) /* Max description length */
16688 #define MAXDSNAME (32+1) /* Max data source name length */
16689 #define MAXTONAME (32+1) /* Max timeout length */
16690 #define MAXDBNAME (255+1)
16691
16692 /* Attribute key indexes into an array of Attr structs, see below */
16693
16694 #define KEY_DSN 0
16695 #define KEY_DESC 1
16696 #define KEY_DBNAME 2
16697 #define KEY_BUSY 3
16698 #define KEY_DRIVER 4
16699 #define KEY_STEPAPI 5
16700 #define KEY_SYNCP 6
16701 #define KEY_NOTXN 7
16702 #define KEY_SHORTNAM 8
16703 #define KEY_LONGNAM 9
16704 #define KEY_NOCREAT 10
16705 #define KEY_NOWCHAR 11
16706 #define KEY_LOADEXT 12
16707 #define KEY_JMODE 13
16708 #define KEY_FKSUPPORT 14
16709 #define KEY_OEMCP 15
16710 #define KEY_BIGINT 16
16711 #define KEY_PASSWD 17
16712 #define NUMOFKEYS 18
16713
16714 typedef struct {
16715 BOOL supplied;
16716 char attr[MAXPATHLEN*4];
16717 } ATTR;
16718
16719 typedef struct {
16720 SQLHWND parent;
16721 LPCSTR driver;
16722 ATTR attr[NUMOFKEYS];
16723 char DSN[MAXDSNAME];
16724 BOOL newDSN;
16725 BOOL defDSN;
16726 } SETUPDLG;
16727
16728 static struct {
16729 char *key;
16730 int ikey;
16731 } attrLookup[] = {
16732 { "DSN", KEY_DSN },
16733 { "DESC", KEY_DESC },
16734 { "Description", KEY_DESC},
16735 { "Database", KEY_DBNAME },
16736 { "Timeout", KEY_BUSY },
16737 { "Driver", KEY_DRIVER },
16738 { "StepAPI", KEY_STEPAPI },
16739 { "SyncPragma", KEY_SYNCP },
16740 { "NoTXN", KEY_NOTXN },
16741 { "ShortNames", KEY_SHORTNAM },
16742 { "LongNames", KEY_LONGNAM },
16743 { "NoCreat", KEY_NOCREAT },
16744 { "NoWCHAR", KEY_NOWCHAR },
16745 { "LoadExt", KEY_LOADEXT },
16746 { "JournalMode", KEY_JMODE },
16747 { "FKSupport", KEY_FKSUPPORT },
16748 { "OEMCP", KEY_OEMCP },
16749 { "BigInt", KEY_BIGINT },
16750 { "PWD", KEY_PASSWD },
16751 { NULL, 0 }
16752 };
16753
16754 /**
16755 * Setup dialog data from datasource attributes.
16756 * @param attribs attribute string
16757 * @param setupdlg pointer to dialog data
16758 */
16759
16760 static void
ParseAttributes(LPCSTR attribs,SETUPDLG * setupdlg)16761 ParseAttributes(LPCSTR attribs, SETUPDLG *setupdlg)
16762 {
16763 char *str = (char *) attribs, *start, key[MAXKEYLEN];
16764 int elem, nkey;
16765
16766 while (*str) {
16767 start = str;
16768 if ((str = strchr(str, '=')) == NULL) {
16769 return;
16770 }
16771 elem = -1;
16772 nkey = str - start;
16773 if (nkey < sizeof (key)) {
16774 int i;
16775
16776 memcpy(key, start, nkey);
16777 key[nkey] = '\0';
16778 for (i = 0; attrLookup[i].key; i++) {
16779 if (strcasecmp(attrLookup[i].key, key) == 0) {
16780 elem = attrLookup[i].ikey;
16781 break;
16782 }
16783 }
16784 }
16785 start = ++str;
16786 while (*str && *str != ';') {
16787 ++str;
16788 }
16789 if (elem >= 0) {
16790 int end = min(str - start, sizeof (setupdlg->attr[elem].attr) - 1);
16791
16792 setupdlg->attr[elem].supplied = TRUE;
16793 memcpy(setupdlg->attr[elem].attr, start, end);
16794 setupdlg->attr[elem].attr[end] = '\0';
16795 }
16796 ++str;
16797 }
16798 }
16799
16800 /**
16801 * Set datasource attributes in registry.
16802 * @param parent handle of parent window
16803 * @param setupdlg pointer to dialog data
16804 * @result true or false
16805 */
16806
16807 static BOOL
SetDSNAttributes(HWND parent,SETUPDLG * setupdlg)16808 SetDSNAttributes(HWND parent, SETUPDLG *setupdlg)
16809 {
16810 char *dsn = setupdlg->attr[KEY_DSN].attr;
16811
16812 if (setupdlg->newDSN && strlen(dsn) == 0) {
16813 return FALSE;
16814 }
16815 if (!SQLWriteDSNToIni(dsn, setupdlg->driver)) {
16816 if (parent) {
16817 char buf[MAXPATHLEN], msg[MAXPATHLEN];
16818
16819 LoadString(hModule, IDS_BADDSN, buf, sizeof (buf));
16820 wsprintf(msg, buf, dsn);
16821 LoadString(hModule, IDS_MSGTITLE, buf, sizeof (buf));
16822 MessageBox(parent, msg, buf,
16823 MB_ICONEXCLAMATION | MB_OK | MB_TASKMODAL |
16824 MB_SETFOREGROUND);
16825 }
16826 return FALSE;
16827 }
16828 if (parent || setupdlg->attr[KEY_DESC].supplied) {
16829 SQLWritePrivateProfileString(dsn, "Description",
16830 setupdlg->attr[KEY_DESC].attr,
16831 ODBC_INI);
16832 }
16833 if (parent || setupdlg->attr[KEY_DBNAME].supplied) {
16834 SQLWritePrivateProfileString(dsn, "Database",
16835 setupdlg->attr[KEY_DBNAME].attr,
16836 ODBC_INI);
16837 }
16838 if (parent || setupdlg->attr[KEY_BUSY].supplied) {
16839 SQLWritePrivateProfileString(dsn, "Timeout",
16840 setupdlg->attr[KEY_BUSY].attr,
16841 ODBC_INI);
16842 }
16843 if (parent || setupdlg->attr[KEY_STEPAPI].supplied) {
16844 SQLWritePrivateProfileString(dsn, "StepAPI",
16845 setupdlg->attr[KEY_STEPAPI].attr,
16846 ODBC_INI);
16847 }
16848 if (parent || setupdlg->attr[KEY_SYNCP].supplied) {
16849 SQLWritePrivateProfileString(dsn, "SyncPragma",
16850 setupdlg->attr[KEY_SYNCP].attr,
16851 ODBC_INI);
16852 }
16853 if (parent || setupdlg->attr[KEY_NOTXN].supplied) {
16854 SQLWritePrivateProfileString(dsn, "NoTXN",
16855 setupdlg->attr[KEY_NOTXN].attr,
16856 ODBC_INI);
16857 }
16858 if (parent || setupdlg->attr[KEY_SHORTNAM].supplied) {
16859 SQLWritePrivateProfileString(dsn, "ShortNames",
16860 setupdlg->attr[KEY_SHORTNAM].attr,
16861 ODBC_INI);
16862 }
16863 if (parent || setupdlg->attr[KEY_LONGNAM].supplied) {
16864 SQLWritePrivateProfileString(dsn, "LongNames",
16865 setupdlg->attr[KEY_LONGNAM].attr,
16866 ODBC_INI);
16867 }
16868 if (parent || setupdlg->attr[KEY_NOCREAT].supplied) {
16869 SQLWritePrivateProfileString(dsn, "NoCreat",
16870 setupdlg->attr[KEY_NOCREAT].attr,
16871 ODBC_INI);
16872 }
16873 if (parent || setupdlg->attr[KEY_NOWCHAR].supplied) {
16874 SQLWritePrivateProfileString(dsn, "NoWCHAR",
16875 setupdlg->attr[KEY_NOWCHAR].attr,
16876 ODBC_INI);
16877 }
16878 if (parent || setupdlg->attr[KEY_FKSUPPORT].supplied) {
16879 SQLWritePrivateProfileString(dsn, "FKSupport",
16880 setupdlg->attr[KEY_FKSUPPORT].attr,
16881 ODBC_INI);
16882 }
16883 if (parent || setupdlg->attr[KEY_OEMCP].supplied) {
16884 SQLWritePrivateProfileString(dsn, "OEMCP",
16885 setupdlg->attr[KEY_OEMCP].attr,
16886 ODBC_INI);
16887 }
16888 if (parent || setupdlg->attr[KEY_LOADEXT].supplied) {
16889 SQLWritePrivateProfileString(dsn, "LoadExt",
16890 setupdlg->attr[KEY_LOADEXT].attr,
16891 ODBC_INI);
16892 }
16893 if (parent || setupdlg->attr[KEY_BIGINT].supplied) {
16894 SQLWritePrivateProfileString(dsn, "BigInt",
16895 setupdlg->attr[KEY_BIGINT].attr,
16896 ODBC_INI);
16897 }
16898 if (parent || setupdlg->attr[KEY_PASSWD].supplied) {
16899 SQLWritePrivateProfileString(dsn, "PWD",
16900 setupdlg->attr[KEY_PASSWD].attr,
16901 ODBC_INI);
16902 }
16903 if (setupdlg->attr[KEY_DSN].supplied &&
16904 strcasecmp(setupdlg->DSN, setupdlg->attr[KEY_DSN].attr)) {
16905 SQLRemoveDSNFromIni(setupdlg->DSN);
16906 }
16907 return TRUE;
16908 }
16909
16910 /**
16911 * Get datasource attributes from registry.
16912 * @param setupdlg pointer to dialog data
16913 */
16914
16915 static void
GetAttributes(SETUPDLG * setupdlg)16916 GetAttributes(SETUPDLG *setupdlg)
16917 {
16918 char *dsn = setupdlg->attr[KEY_DSN].attr;
16919
16920 if (!setupdlg->attr[KEY_DESC].supplied) {
16921 SQLGetPrivateProfileString(dsn, "Description", "",
16922 setupdlg->attr[KEY_DESC].attr,
16923 sizeof (setupdlg->attr[KEY_DESC].attr),
16924 ODBC_INI);
16925 }
16926 if (!setupdlg->attr[KEY_DBNAME].supplied) {
16927 SQLGetPrivateProfileString(dsn, "Database", "",
16928 setupdlg->attr[KEY_DBNAME].attr,
16929 sizeof (setupdlg->attr[KEY_DBNAME].attr),
16930 ODBC_INI);
16931 }
16932 if (!setupdlg->attr[KEY_BUSY].supplied) {
16933 SQLGetPrivateProfileString(dsn, "Timeout", "100000",
16934 setupdlg->attr[KEY_BUSY].attr,
16935 sizeof (setupdlg->attr[KEY_BUSY].attr),
16936 ODBC_INI);
16937 }
16938 if (!setupdlg->attr[KEY_STEPAPI].supplied) {
16939 SQLGetPrivateProfileString(dsn, "StepAPI", "0",
16940 setupdlg->attr[KEY_STEPAPI].attr,
16941 sizeof (setupdlg->attr[KEY_STEPAPI].attr),
16942 ODBC_INI);
16943 }
16944 if (!setupdlg->attr[KEY_SYNCP].supplied) {
16945 SQLGetPrivateProfileString(dsn, "SyncPragma", "NORMAL",
16946 setupdlg->attr[KEY_SYNCP].attr,
16947 sizeof (setupdlg->attr[KEY_SYNCP].attr),
16948 ODBC_INI);
16949 }
16950 if (!setupdlg->attr[KEY_NOTXN].supplied) {
16951 SQLGetPrivateProfileString(dsn, "NoTXN", "",
16952 setupdlg->attr[KEY_NOTXN].attr,
16953 sizeof (setupdlg->attr[KEY_NOTXN].attr),
16954 ODBC_INI);
16955 }
16956 if (!setupdlg->attr[KEY_SHORTNAM].supplied) {
16957 SQLGetPrivateProfileString(dsn, "ShortNames", "",
16958 setupdlg->attr[KEY_SHORTNAM].attr,
16959 sizeof (setupdlg->attr[KEY_SHORTNAM].attr),
16960 ODBC_INI);
16961 }
16962 if (!setupdlg->attr[KEY_LONGNAM].supplied) {
16963 SQLGetPrivateProfileString(dsn, "LongNames", "",
16964 setupdlg->attr[KEY_LONGNAM].attr,
16965 sizeof (setupdlg->attr[KEY_LONGNAM].attr),
16966 ODBC_INI);
16967 }
16968 if (!setupdlg->attr[KEY_NOCREAT].supplied) {
16969 SQLGetPrivateProfileString(dsn, "NoCreat", "",
16970 setupdlg->attr[KEY_NOCREAT].attr,
16971 sizeof (setupdlg->attr[KEY_NOCREAT].attr),
16972 ODBC_INI);
16973 }
16974 if (!setupdlg->attr[KEY_NOWCHAR].supplied) {
16975 SQLGetPrivateProfileString(dsn, "NoWCHAR", "",
16976 setupdlg->attr[KEY_NOWCHAR].attr,
16977 sizeof (setupdlg->attr[KEY_NOWCHAR].attr),
16978 ODBC_INI);
16979 }
16980 if (!setupdlg->attr[KEY_FKSUPPORT].supplied) {
16981 SQLGetPrivateProfileString(dsn, "FKSupport", "",
16982 setupdlg->attr[KEY_FKSUPPORT].attr,
16983 sizeof (setupdlg->attr[KEY_FKSUPPORT].attr),
16984 ODBC_INI);
16985 }
16986 if (!setupdlg->attr[KEY_OEMCP].supplied) {
16987 SQLGetPrivateProfileString(dsn, "OEMCP", "",
16988 setupdlg->attr[KEY_OEMCP].attr,
16989 sizeof (setupdlg->attr[KEY_OEMCP].attr),
16990 ODBC_INI);
16991 }
16992 if (!setupdlg->attr[KEY_LOADEXT].supplied) {
16993 SQLGetPrivateProfileString(dsn, "LoadExt", "",
16994 setupdlg->attr[KEY_LOADEXT].attr,
16995 sizeof (setupdlg->attr[KEY_LOADEXT].attr),
16996 ODBC_INI);
16997 }
16998 if (!setupdlg->attr[KEY_JMODE].supplied) {
16999 SQLGetPrivateProfileString(dsn, "JournalMode", "",
17000 setupdlg->attr[KEY_JMODE].attr,
17001 sizeof (setupdlg->attr[KEY_JMODE].attr),
17002 ODBC_INI);
17003 }
17004 if (!setupdlg->attr[KEY_BIGINT].supplied) {
17005 SQLGetPrivateProfileString(dsn, "BigInt", "",
17006 setupdlg->attr[KEY_BIGINT].attr,
17007 sizeof (setupdlg->attr[KEY_BIGINT].attr),
17008 ODBC_INI);
17009 }
17010 if (!setupdlg->attr[KEY_PASSWD].supplied) {
17011 SQLGetPrivateProfileString(dsn, "PWD", "",
17012 setupdlg->attr[KEY_PASSWD].attr,
17013 sizeof (setupdlg->attr[KEY_PASSWD].attr),
17014 ODBC_INI);
17015 }
17016 }
17017
17018 /**
17019 * Open file dialog for selection of SQLite database file.
17020 * @param hdlg handle of originating dialog window
17021 */
17022
17023 static void
GetDBFile(HWND hdlg)17024 GetDBFile(HWND hdlg)
17025 {
17026 #ifdef _WIN64
17027 SETUPDLG *setupdlg = (SETUPDLG *) GetWindowLongPtr(hdlg, DWLP_USER);
17028 #else
17029 SETUPDLG *setupdlg = (SETUPDLG *) GetWindowLong(hdlg, DWL_USER);
17030 #endif
17031 OPENFILENAME ofn;
17032
17033 memset(&ofn, 0, sizeof (ofn));
17034 ofn.lStructSize = sizeof (ofn);
17035 ofn.hwndOwner = hdlg;
17036 #ifdef _WIN64
17037 ofn.hInstance = (HINSTANCE) GetWindowLongPtr(hdlg, GWLP_HINSTANCE);
17038 #else
17039 ofn.hInstance = (HINSTANCE) GetWindowLong(hdlg, GWL_HINSTANCE);
17040 #endif
17041 ofn.lpstrFile = (LPTSTR) setupdlg->attr[KEY_DBNAME].attr;
17042 ofn.nMaxFile = MAXPATHLEN;
17043 ofn.Flags = OFN_HIDEREADONLY | OFN_PATHMUSTEXIST |
17044 OFN_NOCHANGEDIR | OFN_EXPLORER | OFN_FILEMUSTEXIST;
17045 if (GetOpenFileName(&ofn)) {
17046 SetDlgItemText(hdlg, IDC_DBNAME, setupdlg->attr[KEY_DBNAME].attr);
17047 setupdlg->attr[KEY_DBNAME].supplied = TRUE;
17048 }
17049 }
17050
17051 /**
17052 * Dialog procedure for ConfigDSN().
17053 * @param hdlg handle of dialog window
17054 * @param wmsg type of message
17055 * @param wparam wparam of message
17056 * @param lparam lparam of message
17057 * @result true or false
17058 */
17059
17060 static BOOL CALLBACK
ConfigDlgProc(HWND hdlg,WORD wmsg,WPARAM wparam,LPARAM lparam)17061 ConfigDlgProc(HWND hdlg, WORD wmsg, WPARAM wparam, LPARAM lparam)
17062 {
17063 SETUPDLG *setupdlg = NULL;
17064 WORD index;
17065
17066 switch (wmsg) {
17067 case WM_INITDIALOG:
17068 #ifdef _WIN64
17069 SetWindowLong(hdlg, DWLP_USER, lparam);
17070 #else
17071 SetWindowLong(hdlg, DWL_USER, lparam);
17072 #endif
17073 setupdlg = (SETUPDLG *) lparam;
17074 GetAttributes(setupdlg);
17075 SetDlgItemText(hdlg, IDC_DSNAME, setupdlg->attr[KEY_DSN].attr);
17076 SetDlgItemText(hdlg, IDC_DESC, setupdlg->attr[KEY_DESC].attr);
17077 SetDlgItemText(hdlg, IDC_DBNAME, setupdlg->attr[KEY_DBNAME].attr);
17078 SetDlgItemText(hdlg, IDC_TONAME, setupdlg->attr[KEY_BUSY].attr);
17079 SetDlgItemText(hdlg, IDC_LOADEXT, setupdlg->attr[KEY_LOADEXT].attr);
17080 SendDlgItemMessage(hdlg, IDC_DSNAME, EM_LIMITTEXT,
17081 (WPARAM) (MAXDSNAME - 1), (LPARAM) 0);
17082 SendDlgItemMessage(hdlg, IDC_DESC, EM_LIMITTEXT,
17083 (WPARAM) (MAXDESC - 1), (LPARAM) 0);
17084 SendDlgItemMessage(hdlg, IDC_DBNAME, EM_LIMITTEXT,
17085 (WPARAM) (MAXDBNAME - 1), (LPARAM) 0);
17086 SendDlgItemMessage(hdlg, IDC_TONAME, EM_LIMITTEXT,
17087 (WPARAM) (MAXTONAME - 1), (LPARAM) 0);
17088 SendDlgItemMessage(hdlg, IDC_LOADEXT, EM_LIMITTEXT,
17089 (WPARAM) (MAXPATHLEN*4 - 1), (LPARAM) 0);
17090 CheckDlgButton(hdlg, IDC_STEPAPI,
17091 getbool(setupdlg->attr[KEY_STEPAPI].attr) ?
17092 BST_CHECKED : BST_UNCHECKED);
17093 CheckDlgButton(hdlg, IDC_NOTXN,
17094 getbool(setupdlg->attr[KEY_NOTXN].attr) ?
17095 BST_CHECKED : BST_UNCHECKED);
17096 CheckDlgButton(hdlg, IDC_SHORTNAM,
17097 getbool(setupdlg->attr[KEY_SHORTNAM].attr) ?
17098 BST_CHECKED : BST_UNCHECKED);
17099 CheckDlgButton(hdlg, IDC_LONGNAM,
17100 getbool(setupdlg->attr[KEY_LONGNAM].attr) ?
17101 BST_CHECKED : BST_UNCHECKED);
17102 CheckDlgButton(hdlg, IDC_NOCREAT,
17103 getbool(setupdlg->attr[KEY_NOCREAT].attr) ?
17104 BST_CHECKED : BST_UNCHECKED);
17105 CheckDlgButton(hdlg, IDC_NOWCHAR,
17106 getbool(setupdlg->attr[KEY_NOWCHAR].attr) ?
17107 BST_CHECKED : BST_UNCHECKED);
17108 CheckDlgButton(hdlg, IDC_FKSUPPORT,
17109 getbool(setupdlg->attr[KEY_FKSUPPORT].attr) ?
17110 BST_CHECKED : BST_UNCHECKED);
17111 CheckDlgButton(hdlg, IDC_OEMCP,
17112 getbool(setupdlg->attr[KEY_OEMCP].attr) ?
17113 BST_CHECKED : BST_UNCHECKED);
17114 CheckDlgButton(hdlg, IDC_BIGINT,
17115 getbool(setupdlg->attr[KEY_BIGINT].attr) ?
17116 BST_CHECKED : BST_UNCHECKED);
17117 SendDlgItemMessage(hdlg, IDC_SYNCP,
17118 CB_LIMITTEXT, (WPARAM) 10, (LPARAM) 0);
17119 SendDlgItemMessage(hdlg, IDC_SYNCP,
17120 CB_ADDSTRING, 0, (LPARAM) "NORMAL");
17121 SendDlgItemMessage(hdlg, IDC_SYNCP,
17122 CB_ADDSTRING, 0, (LPARAM) "OFF");
17123 SendDlgItemMessage(hdlg, IDC_SYNCP,
17124 CB_ADDSTRING, 0, (LPARAM) "FULL");
17125 SendDlgItemMessage(hdlg, IDC_SYNCP,
17126 CB_SELECTSTRING, (WPARAM) -1,
17127 (LPARAM) setupdlg->attr[KEY_SYNCP].attr);
17128 if (setupdlg->defDSN) {
17129 EnableWindow(GetDlgItem(hdlg, IDC_DSNAME), FALSE);
17130 EnableWindow(GetDlgItem(hdlg, IDC_DSNAMETEXT), FALSE);
17131 }
17132 return TRUE;
17133 case WM_COMMAND:
17134 switch (GET_WM_COMMAND_ID(wparam, lparam)) {
17135 case IDC_DSNAME:
17136 if (GET_WM_COMMAND_CMD(wparam, lparam) == EN_CHANGE) {
17137 char item[MAXDSNAME];
17138
17139 EnableWindow(GetDlgItem(hdlg, IDOK),
17140 GetDlgItemText(hdlg, IDC_DSNAME,
17141 item, sizeof (item)));
17142 return TRUE;
17143 }
17144 break;
17145 case IDC_BROWSE:
17146 GetDBFile(hdlg);
17147 break;
17148 case IDOK:
17149 #ifdef _WIN64
17150 setupdlg = (SETUPDLG *) GetWindowLongPtr(hdlg, DWLP_USER);
17151 #else
17152 setupdlg = (SETUPDLG *) GetWindowLong(hdlg, DWL_USER);
17153 #endif
17154 if (!setupdlg->defDSN) {
17155 GetDlgItemText(hdlg, IDC_DSNAME,
17156 setupdlg->attr[KEY_DSN].attr,
17157 sizeof (setupdlg->attr[KEY_DSN].attr));
17158 }
17159 GetDlgItemText(hdlg, IDC_DESC,
17160 setupdlg->attr[KEY_DESC].attr,
17161 sizeof (setupdlg->attr[KEY_DESC].attr));
17162 GetDlgItemText(hdlg, IDC_DBNAME,
17163 setupdlg->attr[KEY_DBNAME].attr,
17164 sizeof (setupdlg->attr[KEY_DBNAME].attr));
17165 GetDlgItemText(hdlg, IDC_TONAME,
17166 setupdlg->attr[KEY_BUSY].attr,
17167 sizeof (setupdlg->attr[KEY_BUSY].attr));
17168 GetDlgItemText(hdlg, IDC_LOADEXT,
17169 setupdlg->attr[KEY_LOADEXT].attr,
17170 sizeof (setupdlg->attr[KEY_LOADEXT].attr));
17171 index = SendDlgItemMessage(hdlg, IDC_SYNCP,
17172 CB_GETCURSEL, (WPARAM) 0, (LPARAM) 0);
17173 if (index != (WORD) CB_ERR) {
17174 SendDlgItemMessage(hdlg, IDC_SYNCP,
17175 CB_GETLBTEXT, index,
17176 (LPARAM) setupdlg->attr[KEY_SYNCP].attr);
17177 }
17178 strcpy(setupdlg->attr[KEY_STEPAPI].attr,
17179 (IsDlgButtonChecked(hdlg, IDC_STEPAPI) == BST_CHECKED) ?
17180 "1" : "0");
17181 strcpy(setupdlg->attr[KEY_NOTXN].attr,
17182 (IsDlgButtonChecked(hdlg, IDC_NOTXN) == BST_CHECKED) ?
17183 "1" : "0");
17184 strcpy(setupdlg->attr[KEY_SHORTNAM].attr,
17185 (IsDlgButtonChecked(hdlg, IDC_SHORTNAM) == BST_CHECKED) ?
17186 "1" : "0");
17187 strcpy(setupdlg->attr[KEY_LONGNAM].attr,
17188 (IsDlgButtonChecked(hdlg, IDC_LONGNAM) == BST_CHECKED) ?
17189 "1" : "0");
17190 strcpy(setupdlg->attr[KEY_NOCREAT].attr,
17191 (IsDlgButtonChecked(hdlg, IDC_NOCREAT) == BST_CHECKED) ?
17192 "1" : "0");
17193 strcpy(setupdlg->attr[KEY_NOWCHAR].attr,
17194 (IsDlgButtonChecked(hdlg, IDC_NOWCHAR) == BST_CHECKED) ?
17195 "1" : "0");
17196 strcpy(setupdlg->attr[KEY_FKSUPPORT].attr,
17197 (IsDlgButtonChecked(hdlg, IDC_FKSUPPORT) == BST_CHECKED) ?
17198 "1" : "0");
17199 strcpy(setupdlg->attr[KEY_OEMCP].attr,
17200 (IsDlgButtonChecked(hdlg, IDC_OEMCP) == BST_CHECKED) ?
17201 "1" : "0");
17202 strcpy(setupdlg->attr[KEY_BIGINT].attr,
17203 (IsDlgButtonChecked(hdlg, IDC_BIGINT) == BST_CHECKED) ?
17204 "1" : "0");
17205 SetDSNAttributes(hdlg, setupdlg);
17206 /* FALL THROUGH */
17207 case IDCANCEL:
17208 EndDialog(hdlg, wparam);
17209 return TRUE;
17210 }
17211 break;
17212 }
17213 return FALSE;
17214 }
17215
17216 /**
17217 * ODBC INSTAPI procedure for DSN configuration.
17218 * @param hwnd parent window handle
17219 * @param request type of request
17220 * @param driver driver name
17221 * @param attribs attribute string of DSN
17222 * @result true or false
17223 */
17224
17225 BOOL INSTAPI
ConfigDSN(HWND hwnd,WORD request,LPCSTR driver,LPCSTR attribs)17226 ConfigDSN(HWND hwnd, WORD request, LPCSTR driver, LPCSTR attribs)
17227 {
17228 BOOL success;
17229 SETUPDLG *setupdlg;
17230
17231 setupdlg = (SETUPDLG *) xmalloc(sizeof (SETUPDLG));
17232 if (setupdlg == NULL) {
17233 return FALSE;
17234 }
17235 memset(setupdlg, 0, sizeof (SETUPDLG));
17236 if (attribs) {
17237 ParseAttributes(attribs, setupdlg);
17238 }
17239 if (setupdlg->attr[KEY_DSN].supplied) {
17240 strcpy(setupdlg->DSN, setupdlg->attr[KEY_DSN].attr);
17241 } else {
17242 setupdlg->DSN[0] = '\0';
17243 }
17244 if (request == ODBC_REMOVE_DSN) {
17245 if (!setupdlg->attr[KEY_DSN].supplied) {
17246 success = FALSE;
17247 } else {
17248 success = SQLRemoveDSNFromIni(setupdlg->attr[KEY_DSN].attr);
17249 }
17250 } else {
17251 setupdlg->parent = hwnd;
17252 setupdlg->driver = driver;
17253 setupdlg->newDSN = request == ODBC_ADD_DSN;
17254 setupdlg->defDSN = strcasecmp(setupdlg->attr[KEY_DSN].attr,
17255 "Default") == 0;
17256 if (hwnd) {
17257 success = DialogBoxParam(hModule, MAKEINTRESOURCE(CONFIGDSN),
17258 hwnd, (DLGPROC) ConfigDlgProc,
17259 (LPARAM) setupdlg) == IDOK;
17260 } else if (setupdlg->attr[KEY_DSN].supplied) {
17261 success = SetDSNAttributes(hwnd, setupdlg);
17262 } else {
17263 success = FALSE;
17264 }
17265 }
17266 xfree(setupdlg);
17267 return success;
17268 }
17269
17270 /**
17271 * Dialog procedure for SQLDriverConnect().
17272 * @param hdlg handle of dialog window
17273 * @param wmsg type of message
17274 * @param wparam wparam of message
17275 * @param lparam lparam of message
17276 * @result true or false
17277 */
17278
17279 static BOOL CALLBACK
DriverConnectProc(HWND hdlg,WORD wmsg,WPARAM wparam,LPARAM lparam)17280 DriverConnectProc(HWND hdlg, WORD wmsg, WPARAM wparam, LPARAM lparam)
17281 {
17282 SETUPDLG *setupdlg;
17283 WORD index;
17284
17285 switch (wmsg) {
17286 case WM_INITDIALOG:
17287 #ifdef _WIN64
17288 SetWindowLong(hdlg, DWLP_USER, lparam);
17289 #else
17290 SetWindowLong(hdlg, DWL_USER, lparam);
17291 #endif
17292 setupdlg = (SETUPDLG *) lparam;
17293 SetDlgItemText(hdlg, IDC_DSNAME, setupdlg->attr[KEY_DSN].attr);
17294 SetDlgItemText(hdlg, IDC_DESC, setupdlg->attr[KEY_DESC].attr);
17295 SetDlgItemText(hdlg, IDC_DBNAME, setupdlg->attr[KEY_DBNAME].attr);
17296 SetDlgItemText(hdlg, IDC_TONAME, setupdlg->attr[KEY_BUSY].attr);
17297 SetDlgItemText(hdlg, IDC_LOADEXT, setupdlg->attr[KEY_LOADEXT].attr);
17298 SendDlgItemMessage(hdlg, IDC_DSNAME, EM_LIMITTEXT,
17299 (WPARAM) (MAXDSNAME - 1), (LPARAM) 0);
17300 SendDlgItemMessage(hdlg, IDC_DESC, EM_LIMITTEXT,
17301 (WPARAM) (MAXDESC - 1), (LPARAM) 0);
17302 SendDlgItemMessage(hdlg, IDC_DBNAME, EM_LIMITTEXT,
17303 (WPARAM) (MAXDBNAME - 1), (LPARAM) 0);
17304 SendDlgItemMessage(hdlg, IDC_TONAME, EM_LIMITTEXT,
17305 (WPARAM) (MAXTONAME - 1), (LPARAM) 0);
17306 SendDlgItemMessage(hdlg, IDC_LOADEXT, EM_LIMITTEXT,
17307 (WPARAM) (MAXPATHLEN*4 - 1), (LPARAM) 0);
17308 CheckDlgButton(hdlg, IDC_STEPAPI,
17309 getbool(setupdlg->attr[KEY_STEPAPI].attr) ?
17310 BST_CHECKED : BST_UNCHECKED);
17311 CheckDlgButton(hdlg, IDC_NOTXN,
17312 getbool(setupdlg->attr[KEY_NOTXN].attr) ?
17313 BST_CHECKED : BST_UNCHECKED);
17314 CheckDlgButton(hdlg, IDC_SHORTNAM,
17315 getbool(setupdlg->attr[KEY_SHORTNAM].attr) ?
17316 BST_CHECKED : BST_UNCHECKED);
17317 CheckDlgButton(hdlg, IDC_LONGNAM,
17318 getbool(setupdlg->attr[KEY_LONGNAM].attr) ?
17319 BST_CHECKED : BST_UNCHECKED);
17320 CheckDlgButton(hdlg, IDC_NOCREAT,
17321 getbool(setupdlg->attr[KEY_NOCREAT].attr) ?
17322 BST_CHECKED : BST_UNCHECKED);
17323 CheckDlgButton(hdlg, IDC_NOWCHAR,
17324 getbool(setupdlg->attr[KEY_NOWCHAR].attr) ?
17325 BST_CHECKED : BST_UNCHECKED);
17326 CheckDlgButton(hdlg, IDC_FKSUPPORT,
17327 getbool(setupdlg->attr[KEY_FKSUPPORT].attr) ?
17328 BST_CHECKED : BST_UNCHECKED);
17329 CheckDlgButton(hdlg, IDC_OEMCP,
17330 getbool(setupdlg->attr[KEY_OEMCP].attr) ?
17331 BST_CHECKED : BST_UNCHECKED);
17332 CheckDlgButton(hdlg, IDC_BIGINT,
17333 getbool(setupdlg->attr[KEY_BIGINT].attr) ?
17334 BST_CHECKED : BST_UNCHECKED);
17335 SendDlgItemMessage(hdlg, IDC_SYNCP,
17336 CB_LIMITTEXT, (WPARAM) 10, (LPARAM) 0);
17337 SendDlgItemMessage(hdlg, IDC_SYNCP,
17338 CB_ADDSTRING, 0, (LPARAM) "NORMAL");
17339 SendDlgItemMessage(hdlg, IDC_SYNCP,
17340 CB_ADDSTRING, 0, (LPARAM) "OFF");
17341 SendDlgItemMessage(hdlg, IDC_SYNCP,
17342 CB_ADDSTRING, 0, (LPARAM) "FULL");
17343 SendDlgItemMessage(hdlg, IDC_SYNCP,
17344 CB_SELECTSTRING, (WORD) -1,
17345 (LPARAM) setupdlg->attr[KEY_SYNCP].attr);
17346 if (setupdlg->defDSN) {
17347 EnableWindow(GetDlgItem(hdlg, IDC_DSNAME), FALSE);
17348 EnableWindow(GetDlgItem(hdlg, IDC_DSNAMETEXT), FALSE);
17349 }
17350 return TRUE;
17351 case WM_COMMAND:
17352 switch (GET_WM_COMMAND_ID(wparam, lparam)) {
17353 case IDC_BROWSE:
17354 GetDBFile(hdlg);
17355 break;
17356 case IDOK:
17357 #ifdef _WIN64
17358 setupdlg = (SETUPDLG *) GetWindowLongPtr(hdlg, DWLP_USER);
17359 #else
17360 setupdlg = (SETUPDLG *) GetWindowLong(hdlg, DWL_USER);
17361 #endif
17362 GetDlgItemText(hdlg, IDC_DSNAME,
17363 setupdlg->attr[KEY_DSN].attr,
17364 sizeof (setupdlg->attr[KEY_DSN].attr));
17365 GetDlgItemText(hdlg, IDC_DBNAME,
17366 setupdlg->attr[KEY_DBNAME].attr,
17367 sizeof (setupdlg->attr[KEY_DBNAME].attr));
17368 GetDlgItemText(hdlg, IDC_TONAME,
17369 setupdlg->attr[KEY_BUSY].attr,
17370 sizeof (setupdlg->attr[KEY_BUSY].attr));
17371 GetDlgItemText(hdlg, IDC_LOADEXT,
17372 setupdlg->attr[KEY_LOADEXT].attr,
17373 sizeof (setupdlg->attr[KEY_LOADEXT].attr));
17374 index = SendDlgItemMessage(hdlg, IDC_SYNCP,
17375 CB_GETCURSEL, (WPARAM) 0, (LPARAM) 0);
17376 if (index != (WORD) CB_ERR) {
17377 SendDlgItemMessage(hdlg, IDC_SYNCP,
17378 CB_GETLBTEXT, index,
17379 (LPARAM) setupdlg->attr[KEY_SYNCP].attr);
17380 }
17381 strcpy(setupdlg->attr[KEY_STEPAPI].attr,
17382 (IsDlgButtonChecked(hdlg, IDC_STEPAPI) == BST_CHECKED) ?
17383 "1" : "0");
17384 strcpy(setupdlg->attr[KEY_NOTXN].attr,
17385 (IsDlgButtonChecked(hdlg, IDC_NOTXN) == BST_CHECKED) ?
17386 "1" : "0");
17387 strcpy(setupdlg->attr[KEY_SHORTNAM].attr,
17388 (IsDlgButtonChecked(hdlg, IDC_SHORTNAM) == BST_CHECKED) ?
17389 "1" : "0");
17390 strcpy(setupdlg->attr[KEY_LONGNAM].attr,
17391 (IsDlgButtonChecked(hdlg, IDC_LONGNAM) == BST_CHECKED) ?
17392 "1" : "0");
17393 strcpy(setupdlg->attr[KEY_NOCREAT].attr,
17394 (IsDlgButtonChecked(hdlg, IDC_NOCREAT) == BST_CHECKED) ?
17395 "1" : "0");
17396 strcpy(setupdlg->attr[KEY_NOWCHAR].attr,
17397 (IsDlgButtonChecked(hdlg, IDC_NOWCHAR) == BST_CHECKED) ?
17398 "1" : "0");
17399 strcpy(setupdlg->attr[KEY_FKSUPPORT].attr,
17400 (IsDlgButtonChecked(hdlg, IDC_FKSUPPORT) == BST_CHECKED) ?
17401 "1" : "0");
17402 strcpy(setupdlg->attr[KEY_OEMCP].attr,
17403 (IsDlgButtonChecked(hdlg, IDC_OEMCP) == BST_CHECKED) ?
17404 "1" : "0");
17405 strcpy(setupdlg->attr[KEY_BIGINT].attr,
17406 (IsDlgButtonChecked(hdlg, IDC_BIGINT) == BST_CHECKED) ?
17407 "1" : "0");
17408 /* FALL THROUGH */
17409 case IDCANCEL:
17410 EndDialog(hdlg, GET_WM_COMMAND_ID(wparam, lparam) == IDOK);
17411 return TRUE;
17412 }
17413 }
17414 return FALSE;
17415 }
17416
17417 /**
17418 * Internal connect using a driver connection string.
17419 * @param dbc database connection handle
17420 * @param hwnd parent window handle
17421 * @param connIn driver connect input string
17422 * @param connInLen length of driver connect input string or SQL_NTS
17423 * @param connOut driver connect output string
17424 * @param connOutMax length of driver connect output string
17425 * @param connOutLen output length of driver connect output string
17426 * @param drvcompl completion type
17427 * @result ODBC error code
17428 */
17429
17430 static SQLRETURN
drvdriverconnect(SQLHDBC dbc,SQLHWND hwnd,SQLCHAR * connIn,SQLSMALLINT connInLen,SQLCHAR * connOut,SQLSMALLINT connOutMax,SQLSMALLINT * connOutLen,SQLUSMALLINT drvcompl)17431 drvdriverconnect(SQLHDBC dbc, SQLHWND hwnd,
17432 SQLCHAR *connIn, SQLSMALLINT connInLen,
17433 SQLCHAR *connOut, SQLSMALLINT connOutMax,
17434 SQLSMALLINT *connOutLen, SQLUSMALLINT drvcompl)
17435 {
17436 BOOL maybeprompt, prompt = FALSE;
17437 DBC *d;
17438 SETUPDLG *setupdlg;
17439 SQLRETURN ret;
17440 char *dsn = NULL, *driver = NULL, *dbname = NULL;
17441
17442 if (dbc == SQL_NULL_HDBC) {
17443 return SQL_INVALID_HANDLE;
17444 }
17445 d = (DBC *) dbc;
17446 if (d->sqlite) {
17447 setstatd(d, -1, "connection already established", "08002");
17448 return SQL_ERROR;
17449 }
17450 setupdlg = (SETUPDLG *) xmalloc(sizeof (SETUPDLG));
17451 if (setupdlg == NULL) {
17452 return SQL_ERROR;
17453 }
17454 memset(setupdlg, 0, sizeof (SETUPDLG));
17455 maybeprompt = drvcompl == SQL_DRIVER_COMPLETE ||
17456 drvcompl == SQL_DRIVER_COMPLETE_REQUIRED;
17457 if (connIn == NULL || !connInLen ||
17458 (connInLen == SQL_NTS && !connIn[0])) {
17459 prompt = TRUE;
17460 } else {
17461 ParseAttributes((LPCSTR) connIn, setupdlg);
17462 if (!setupdlg->attr[KEY_DSN].attr[0] &&
17463 drvcompl == SQL_DRIVER_COMPLETE_REQUIRED) {
17464 strcpy(setupdlg->attr[KEY_DSN].attr, "DEFAULT");
17465 }
17466 GetAttributes(setupdlg);
17467 if (drvcompl == SQL_DRIVER_PROMPT ||
17468 (maybeprompt &&
17469 !setupdlg->attr[KEY_DBNAME].attr[0])) {
17470 prompt = TRUE;
17471 }
17472 }
17473 retry:
17474 if (prompt) {
17475 short dlgret;
17476
17477 setupdlg->defDSN = setupdlg->attr[KEY_DRIVER].attr[0] != '\0';
17478 dlgret = DialogBoxParam(hModule, MAKEINTRESOURCE(DRIVERCONNECT),
17479 hwnd, (DLGPROC) DriverConnectProc,
17480 (LPARAM) setupdlg);
17481
17482 if (!dlgret || dlgret == -1) {
17483 xfree(setupdlg);
17484 return SQL_NO_DATA;
17485 }
17486 }
17487 dsn = setupdlg->attr[KEY_DSN].attr;
17488 driver = setupdlg->attr[KEY_DRIVER].attr;
17489 dbname = setupdlg->attr[KEY_DBNAME].attr;
17490 if (connOut || connOutLen) {
17491 char buf[2048];
17492 int len, count;
17493 char dsn_0 = dsn ? dsn[0] : '\0';
17494 char drv_0 = driver ? driver[0] : '\0';
17495
17496 buf[0] = '\0';
17497 count = snprintf(buf, sizeof (buf),
17498 "%s%s%s%s%s%sDatabase=%s;StepAPI=%s;"
17499 "SyncPragma=%s;NoTXN=%s;Timeout=%s;"
17500 "ShortNames=%s;LongNames=%s;"
17501 "NoCreat=%s;NoWCHAR=%s;"
17502 "FKSupport=%s;JournalMode=%s;OEMCP=%s;LoadExt=%s;"
17503 "BigInt=%s;PWD=%s",
17504 dsn_0 ? "DSN=" : "",
17505 dsn_0 ? dsn : "",
17506 dsn_0 ? ";" : "",
17507 drv_0 ? "Driver=" : "",
17508 drv_0 ? driver : "",
17509 drv_0 ? ";" : "",
17510 dbname ? dbname : "",
17511 setupdlg->attr[KEY_STEPAPI].attr,
17512 setupdlg->attr[KEY_SYNCP].attr,
17513 setupdlg->attr[KEY_NOTXN].attr,
17514 setupdlg->attr[KEY_BUSY].attr,
17515 setupdlg->attr[KEY_SHORTNAM].attr,
17516 setupdlg->attr[KEY_LONGNAM].attr,
17517 setupdlg->attr[KEY_NOCREAT].attr,
17518 setupdlg->attr[KEY_NOWCHAR].attr,
17519 setupdlg->attr[KEY_FKSUPPORT].attr,
17520 setupdlg->attr[KEY_JMODE].attr,
17521 setupdlg->attr[KEY_OEMCP].attr,
17522 setupdlg->attr[KEY_LOADEXT].attr,
17523 setupdlg->attr[KEY_BIGINT].attr,
17524 setupdlg->attr[KEY_PASSWD].attr);
17525 if (count < 0) {
17526 buf[sizeof (buf) - 1] = '\0';
17527 }
17528 len = min(connOutMax - 1, strlen(buf));
17529 if (connOut) {
17530 strncpy((char *) connOut, buf, len);
17531 connOut[len] = '\0';
17532 }
17533 if (connOutLen) {
17534 *connOutLen = len;
17535 }
17536 }
17537 if (dsn[0]) {
17538 char tracef[SQL_MAX_MESSAGE_LENGTH];
17539
17540 tracef[0] = '\0';
17541 SQLGetPrivateProfileString(setupdlg->attr[KEY_DSN].attr,
17542 "tracefile", "", tracef,
17543 sizeof (tracef), ODBC_INI);
17544 if (tracef[0] != '\0') {
17545 d->trace = fopen(tracef, "a");
17546 }
17547 }
17548 d->nowchar = getbool(setupdlg->attr[KEY_NOWCHAR].attr);
17549 d->shortnames = getbool(setupdlg->attr[KEY_SHORTNAM].attr);
17550 d->longnames = getbool(setupdlg->attr[KEY_LONGNAM].attr);
17551 d->nocreat = getbool(setupdlg->attr[KEY_NOCREAT].attr);
17552 d->fksupport = getbool(setupdlg->attr[KEY_FKSUPPORT].attr);
17553 d->oemcp = getbool(setupdlg->attr[KEY_OEMCP].attr);
17554 d->dobigint = getbool(setupdlg->attr[KEY_BIGINT].attr);
17555 d->pwdLen = strlen(setupdlg->attr[KEY_PASSWD].attr);
17556 d->pwd = (d->pwdLen > 0) ? setupdlg->attr[KEY_PASSWD].attr : NULL;
17557 ret = dbopen(d, dbname ? dbname : "", 0,
17558 dsn ? dsn : "",
17559 setupdlg->attr[KEY_STEPAPI].attr,
17560 setupdlg->attr[KEY_SYNCP].attr,
17561 setupdlg->attr[KEY_NOTXN].attr,
17562 setupdlg->attr[KEY_JMODE].attr,
17563 setupdlg->attr[KEY_BUSY].attr);
17564 if (ret != SQL_SUCCESS) {
17565 if (maybeprompt && !prompt) {
17566 prompt = TRUE;
17567 goto retry;
17568 }
17569 }
17570 memset(setupdlg->attr[KEY_PASSWD].attr, 0,
17571 sizeof (setupdlg->attr[KEY_PASSWD].attr));
17572 if (ret == SQL_SUCCESS) {
17573 dbloadext(d, setupdlg->attr[KEY_LOADEXT].attr);
17574 }
17575 xfree(setupdlg);
17576 return ret;
17577 }
17578
17579 #endif /* WITHOUT_DRIVERMGR */
17580 #endif /* _WIN32 || _WIN64 */
17581
17582 #ifndef WINTERFACE
17583 /**
17584 * Connect using a driver connection string.
17585 * @param dbc database connection handle
17586 * @param hwnd parent window handle
17587 * @param connIn driver connect input string
17588 * @param connInLen length of driver connect input string or SQL_NTS
17589 * @param connOut driver connect output string
17590 * @param connOutMax length of driver connect output string
17591 * @param connOutLen output length of driver connect output string
17592 * @param drvcompl completion type
17593 * @result ODBC error code
17594 */
17595
17596 SQLRETURN SQL_API
SQLDriverConnect(SQLHDBC dbc,SQLHWND hwnd,SQLCHAR * connIn,SQLSMALLINT connInLen,SQLCHAR * connOut,SQLSMALLINT connOutMax,SQLSMALLINT * connOutLen,SQLUSMALLINT drvcompl)17597 SQLDriverConnect(SQLHDBC dbc, SQLHWND hwnd,
17598 SQLCHAR *connIn, SQLSMALLINT connInLen,
17599 SQLCHAR *connOut, SQLSMALLINT connOutMax,
17600 SQLSMALLINT *connOutLen, SQLUSMALLINT drvcompl)
17601 {
17602 SQLRETURN ret;
17603
17604 HDBC_LOCK(dbc);
17605 ret = drvdriverconnect(dbc, hwnd, connIn, connInLen,
17606 connOut, connOutMax, connOutLen, drvcompl);
17607 HDBC_UNLOCK(dbc);
17608 return ret;
17609 }
17610 #endif
17611
17612 #ifdef WINTERFACE
17613 /**
17614 * Connect using a driver connection string (UNICODE version).
17615 * @param dbc database connection handle
17616 * @param hwnd parent window handle
17617 * @param connIn driver connect input string
17618 * @param connInLen length of driver connect input string or SQL_NTS
17619 * @param connOut driver connect output string
17620 * @param connOutMax length of driver connect output string
17621 * @param connOutLen output length of driver connect output string
17622 * @param drvcompl completion type
17623 * @result ODBC error code
17624 */
17625
17626 SQLRETURN SQL_API
SQLDriverConnectW(SQLHDBC dbc,SQLHWND hwnd,SQLWCHAR * connIn,SQLSMALLINT connInLen,SQLWCHAR * connOut,SQLSMALLINT connOutMax,SQLSMALLINT * connOutLen,SQLUSMALLINT drvcompl)17627 SQLDriverConnectW(SQLHDBC dbc, SQLHWND hwnd,
17628 SQLWCHAR *connIn, SQLSMALLINT connInLen,
17629 SQLWCHAR *connOut, SQLSMALLINT connOutMax,
17630 SQLSMALLINT *connOutLen, SQLUSMALLINT drvcompl)
17631 {
17632 SQLRETURN ret;
17633 char *ci = NULL;
17634 SQLSMALLINT len = 0;
17635
17636 HDBC_LOCK(dbc);
17637 if (connIn) {
17638 #if defined(_WIN32) || defined(_WIN64)
17639 ci = uc_to_wmb(connIn, connInLen);
17640 #else
17641 ci = uc_to_utf(connIn, connInLen);
17642 #endif
17643 if (!ci) {
17644 DBC *d = (DBC *) dbc;
17645
17646 setstatd(d, -1, "out of memory", (*d->ov3) ? "HY000" : "S1000");
17647 HDBC_UNLOCK(dbc);
17648 return SQL_ERROR;
17649 }
17650 }
17651 ret = drvdriverconnect(dbc, hwnd, (SQLCHAR *) ci, SQL_NTS,
17652 (SQLCHAR *) connOut, connOutMax, &len, drvcompl);
17653 HDBC_UNLOCK(dbc);
17654 uc_free(ci);
17655 if (ret == SQL_SUCCESS) {
17656 SQLWCHAR *co = NULL;
17657
17658 if (connOut) {
17659 if (len > 0) {
17660 #if defined(_WIN32) || defined(_WIN64)
17661 co = wmb_to_uc((char *) connOut, len);
17662 #else
17663 co = uc_from_utf((SQLCHAR *) connOut, len);
17664 #endif
17665 if (co) {
17666 uc_strncpy(connOut, co, connOutMax);
17667 co[len] = 0;
17668 len = min(connOutMax, uc_strlen(co));
17669 uc_free(co);
17670 } else {
17671 len = 0;
17672 }
17673 }
17674 if (len <= 0) {
17675 len = 0;
17676 connOut[0] = 0;
17677 }
17678 } else {
17679 len = 0;
17680 }
17681 if (connOutLen) {
17682 *connOutLen = len;
17683 }
17684 }
17685 return ret;
17686 }
17687 #endif
17688
17689 #if defined(_WIN32) || defined(_WIN64)
17690
17691 /**
17692 * DLL initializer for WIN32.
17693 * @param hinst instance handle
17694 * @param reason reason code for entry point
17695 * @param reserved
17696 * @result always true
17697 */
17698
17699 BOOL APIENTRY
LibMain(HANDLE hinst,DWORD reason,LPVOID reserved)17700 LibMain(HANDLE hinst, DWORD reason, LPVOID reserved)
17701 {
17702 static int initialized = 0;
17703
17704 switch (reason) {
17705 case DLL_PROCESS_ATTACH:
17706 if (!initialized++) {
17707 hModule = hinst;
17708 #ifdef WINTERFACE
17709 /* MS Access hack part 1 (reserved error -7748) */
17710 statSpec2P = statSpec2;
17711 statSpec3P = statSpec3;
17712 #endif
17713 #ifdef SQLITE_DYNLOAD
17714 dls_init();
17715 #endif
17716 #ifdef SQLITE_HAS_CODEC
17717 sqlite3_activate_see(SQLITE_ACTIVATION_KEY);
17718 #endif
17719 }
17720 #if defined(ENABLE_NVFS) && (ENABLE_NVFS)
17721 nvfs_init();
17722 #endif
17723 break;
17724 case DLL_THREAD_ATTACH:
17725 break;
17726 case DLL_PROCESS_DETACH:
17727 if (--initialized <= 0) {
17728 #ifdef SQLITE_DYNLOAD
17729 dls_fini();
17730 #endif
17731 }
17732 break;
17733 case DLL_THREAD_DETACH:
17734 break;
17735 default:
17736 break;
17737 }
17738 return TRUE;
17739 }
17740
17741 /**
17742 * DLL entry point for WIN32.
17743 * @param hinst instance handle
17744 * @param reason reason code for entry point
17745 * @param reserved
17746 * @result always true
17747 */
17748
17749 int __stdcall
DllMain(HANDLE hinst,DWORD reason,LPVOID reserved)17750 DllMain(HANDLE hinst, DWORD reason, LPVOID reserved)
17751 {
17752 return LibMain(hinst, reason, reserved);
17753 }
17754
17755 #ifndef WITHOUT_INSTALLER
17756
17757 /**
17758 * Handler for driver installer/uninstaller error messages.
17759 * @param name name of API function for which to show error messages
17760 * @result true when error message retrieved
17761 */
17762
17763 static BOOL
InUnError(char * name)17764 InUnError(char *name)
17765 {
17766 WORD err = 1;
17767 DWORD code;
17768 char errmsg[301];
17769 WORD errlen, errmax = sizeof (errmsg) - 1;
17770 int sqlret;
17771 BOOL ret = FALSE;
17772
17773 do {
17774 errmsg[0] = '\0';
17775 sqlret = SQLInstallerError(err, &code, errmsg, errmax, &errlen);
17776 if (SQL_SUCCEEDED(sqlret)) {
17777 MessageBox(NULL, errmsg, name,
17778 MB_ICONSTOP | MB_OK | MB_TASKMODAL | MB_SETFOREGROUND);
17779 ret = TRUE;
17780 }
17781 err++;
17782 } while (sqlret != SQL_NO_DATA);
17783 return ret;
17784 }
17785
17786 /**
17787 * Built in driver installer/uninstaller.
17788 * @param remove true for uninstall
17789 * @param cmdline command line string of rundll32
17790 */
17791
17792 static BOOL
InUn(int remove,char * cmdline)17793 InUn(int remove, char *cmdline)
17794 {
17795 #ifdef SQLITE_HAS_CODEC
17796 static char *drivername = "SQLite3 ODBC Driver (SEE)";
17797 static char *dsname = "SQLite3 SEE Datasource";
17798 #else
17799 static char *drivername = "SQLite3 ODBC Driver";
17800 static char *dsname = "SQLite3 Datasource";
17801 #endif
17802 char *dllname, *p;
17803 char dllbuf[301], path[301], driver[300], attr[300], inst[400];
17804 WORD pathmax = sizeof (path) - 1, pathlen;
17805 DWORD usecnt, mincnt;
17806 int quiet = 0;
17807
17808 dllbuf[0] = '\0';
17809 GetModuleFileName(hModule, dllbuf, sizeof (dllbuf));
17810 p = strrchr(dllbuf, '\\');
17811 dllname = p ? (p + 1) : dllbuf;
17812 quiet = cmdline && strstr(cmdline, "quiet");
17813 if (SQLInstallDriverManager(path, pathmax, &pathlen)) {
17814 sprintf(driver, "%s;Driver=%s;Setup=%s;",
17815 drivername, dllname, dllname);
17816 p = driver;
17817 while (*p) {
17818 if (*p == ';') {
17819 *p = '\0';
17820 }
17821 ++p;
17822 }
17823 usecnt = 0;
17824 path[0] = '\0';
17825 SQLInstallDriverEx(driver, NULL, path, pathmax, NULL,
17826 ODBC_INSTALL_INQUIRY, &usecnt);
17827 pathlen = strlen(path);
17828 while (pathlen > 0 && path[pathlen - 1] == '\\') {
17829 --pathlen;
17830 path[pathlen] = '\0';
17831 }
17832 sprintf(driver, "%s;Driver=%s\\%s;Setup=%s\\%s;",
17833 drivername, path, dllname, path, dllname);
17834 p = driver;
17835 while (*p) {
17836 if (*p == ';') {
17837 *p = '\0';
17838 }
17839 ++p;
17840 }
17841 sprintf(inst, "%s\\%s", path, dllname);
17842 if (!remove && usecnt > 0) {
17843 /* first install try: copy over driver dll, keeping DSNs */
17844 if (GetFileAttributesA(dllbuf) != INVALID_FILE_ATTRIBUTES &&
17845 CopyFile(dllbuf, inst, 0)) {
17846 if (!quiet) {
17847 char buf[512];
17848
17849 sprintf(buf, "%s replaced.", drivername);
17850 MessageBox(NULL, buf, "Info",
17851 MB_ICONINFORMATION | MB_OK | MB_TASKMODAL |
17852 MB_SETFOREGROUND);
17853 }
17854 return TRUE;
17855 }
17856 }
17857 mincnt = remove ? 1 : 0;
17858 while (usecnt != mincnt) {
17859 if (!SQLRemoveDriver(driver, TRUE, &usecnt)) {
17860 break;
17861 }
17862 }
17863 if (remove) {
17864 if (usecnt && !SQLRemoveDriver(driver, TRUE, &usecnt)) {
17865 InUnError("SQLRemoveDriver");
17866 return FALSE;
17867 }
17868 if (!usecnt) {
17869 char buf[512];
17870
17871 DeleteFile(inst);
17872 if (!quiet) {
17873 sprintf(buf, "%s uninstalled.", drivername);
17874 MessageBox(NULL, buf, "Info",
17875 MB_ICONINFORMATION |MB_OK | MB_TASKMODAL |
17876 MB_SETFOREGROUND);
17877 }
17878 }
17879 sprintf(attr, "DSN=%s;Database=sqlite.db;", dsname);
17880 p = attr;
17881 while (*p) {
17882 if (*p == ';') {
17883 *p = '\0';
17884 }
17885 ++p;
17886 }
17887 SQLConfigDataSource(NULL, ODBC_REMOVE_SYS_DSN, drivername, attr);
17888 return TRUE;
17889 }
17890 if (GetFileAttributesA(dllbuf) == INVALID_FILE_ATTRIBUTES) {
17891 return FALSE;
17892 }
17893 if (strcmp(dllbuf, inst) != 0 && !CopyFile(dllbuf, inst, 0)) {
17894 char buf[512];
17895
17896 sprintf(buf, "Copy %s to %s failed.", dllbuf, inst);
17897 MessageBox(NULL, buf, "CopyFile",
17898 MB_ICONSTOP |MB_OK | MB_TASKMODAL | MB_SETFOREGROUND);
17899 return FALSE;
17900 }
17901 if (!SQLInstallDriverEx(driver, path, path, pathmax, &pathlen,
17902 ODBC_INSTALL_COMPLETE, &usecnt)) {
17903 InUnError("SQLInstallDriverEx");
17904 return FALSE;
17905 }
17906 sprintf(attr, "DSN=%s;Database=sqlite.db;", dsname);
17907 p = attr;
17908 while (*p) {
17909 if (*p == ';') {
17910 *p = '\0';
17911 }
17912 ++p;
17913 }
17914 SQLConfigDataSource(NULL, ODBC_REMOVE_SYS_DSN, drivername, attr);
17915 if (!SQLConfigDataSource(NULL, ODBC_ADD_SYS_DSN, drivername, attr)) {
17916 InUnError("SQLConfigDataSource");
17917 return FALSE;
17918 }
17919 if (!quiet) {
17920 char buf[512];
17921
17922 sprintf(buf, "%s installed.", drivername);
17923 MessageBox(NULL, buf, "Info",
17924 MB_ICONINFORMATION | MB_OK | MB_TASKMODAL |
17925 MB_SETFOREGROUND);
17926 }
17927 } else {
17928 InUnError("SQLInstallDriverManager");
17929 return FALSE;
17930 }
17931 return TRUE;
17932 }
17933
17934 /**
17935 * RunDLL32 entry point for driver installation.
17936 * @param hwnd window handle of caller
17937 * @param hinst of this DLL
17938 * @param lpszCmdLine rundll32 command line tail
17939 * @param nCmdShow ignored
17940 */
17941
17942 void CALLBACK
install(HWND hwnd,HINSTANCE hinst,LPSTR lpszCmdLine,int nCmdShow)17943 install(HWND hwnd, HINSTANCE hinst, LPSTR lpszCmdLine, int nCmdShow)
17944 {
17945 InUn(0, lpszCmdLine);
17946 }
17947
17948 /**
17949 * RunDLL32 entry point for driver uninstallation.
17950 * @param hwnd window handle of caller
17951 * @param hinst of this DLL
17952 * @param lpszCmdLine rundll32 command line tail
17953 * @param nCmdShow ignored
17954 */
17955
17956 void CALLBACK
uninstall(HWND hwnd,HINSTANCE hinst,LPSTR lpszCmdLine,int nCmdShow)17957 uninstall(HWND hwnd, HINSTANCE hinst, LPSTR lpszCmdLine, int nCmdShow)
17958 {
17959 InUn(1, lpszCmdLine);
17960 }
17961
17962 #endif /* WITHOUT_INSTALLER */
17963
17964 #ifndef WITHOUT_SHELL
17965
17966 /**
17967 * Setup argv vector from string
17968 * @param argcp pointer to argc
17969 * @param argvp pointer to argv
17970 * @param cmdline command line string
17971 * @param argv0 0th element for argv or NULL, must be static
17972 */
17973
17974 static void
setargv(int * argcp,char *** argvp,char * cmdline,char * argv0)17975 setargv(int *argcp, char ***argvp, char *cmdline, char *argv0)
17976 {
17977 char *p, *arg, *argspace, **argv;
17978 int argc, size, inquote, copy, slashes;
17979
17980 size = 2 + (argv0 ? 1 : 0);
17981 for (p = cmdline; *p != '\0'; p++) {
17982 if (ISSPACE(*p)) {
17983 size++;
17984 while (ISSPACE(*p)) {
17985 p++;
17986 }
17987 if (*p == '\0') {
17988 break;
17989 }
17990 }
17991 }
17992 argspace = malloc(size * sizeof (char *) + strlen(cmdline) + 1);
17993 argv = (char **) argspace;
17994 argspace += size * sizeof (char *);
17995 size--;
17996 argc = 0;
17997 if (argv0) {
17998 argv[argc++] = argv0;
17999 }
18000 p = cmdline;
18001 for (; argc < size; argc++) {
18002 argv[argc] = arg = argspace;
18003 while (ISSPACE(*p)) {
18004 p++;
18005 }
18006 if (*p == '\0') {
18007 break;
18008 }
18009 inquote = 0;
18010 slashes = 0;
18011 while (1) {
18012 copy = 1;
18013 while (*p == '\\') {
18014 slashes++;
18015 p++;
18016 }
18017 if (*p == '"') {
18018 if ((slashes & 1) == 0) {
18019 copy = 0;
18020 if (inquote && p[1] == '"') {
18021 p++;
18022 copy = 1;
18023 } else {
18024 inquote = !inquote;
18025 }
18026 }
18027 slashes >>= 1;
18028 }
18029 while (slashes) {
18030 *arg = '\\';
18031 arg++;
18032 slashes--;
18033 }
18034 if (*p == '\0' || (!inquote && ISSPACE(*p))) {
18035 break;
18036 }
18037 if (copy != 0) {
18038 *arg = *p;
18039 arg++;
18040 }
18041 p++;
18042 }
18043 *arg = '\0';
18044 argspace = arg + 1;
18045 }
18046 argv[argc] = 0;
18047 *argcp = argc;
18048 *argvp = argv;
18049 }
18050
18051 /**
18052 * RunDLL32 entry point for SQLite shell
18053 * @param hwnd window handle of caller
18054 * @param hinst of this DLL
18055 * @param lpszCmdLine rundll32 command line tail
18056 * @param nCmdShow ignored
18057 */
18058
18059 void CALLBACK
shell(HWND hwnd,HINSTANCE hinst,LPSTR lpszCmdLine,int nCmdShow)18060 shell(HWND hwnd, HINSTANCE hinst, LPSTR lpszCmdLine, int nCmdShow)
18061 {
18062 int argc, needcon = 0;
18063 char **argv;
18064 extern int sqlite3_main(int, char **);
18065 static const char *name = "SQLite3 Shell";
18066 DWORD ftype0, ftype1, ftype2;
18067
18068 ftype0 = GetFileType(GetStdHandle(STD_INPUT_HANDLE));
18069 ftype1 = GetFileType(GetStdHandle(STD_OUTPUT_HANDLE));
18070 ftype2 = GetFileType(GetStdHandle(STD_ERROR_HANDLE));
18071 if (ftype0 != FILE_TYPE_DISK && ftype0 != FILE_TYPE_CHAR &&
18072 ftype0 != FILE_TYPE_PIPE) {
18073 fclose(stdin);
18074 ++needcon;
18075 ftype0 = FILE_TYPE_UNKNOWN;
18076 }
18077 if (ftype1 != FILE_TYPE_DISK && ftype1 != FILE_TYPE_CHAR &&
18078 ftype1 != FILE_TYPE_PIPE) {
18079 fclose(stdout);
18080 ++needcon;
18081 ftype1 = FILE_TYPE_UNKNOWN;
18082 }
18083 if (ftype2 != FILE_TYPE_DISK && ftype2 != FILE_TYPE_CHAR &&
18084 ftype2 != FILE_TYPE_PIPE) {
18085 fclose(stderr);
18086 ++needcon;
18087 ftype2 = FILE_TYPE_UNKNOWN;
18088 }
18089 if (needcon > 0) {
18090 AllocConsole();
18091 SetConsoleTitle(name);
18092 }
18093 if (ftype0 == FILE_TYPE_UNKNOWN) {
18094 freopen("CONIN$", "r", stdin);
18095 }
18096 if (ftype1 == FILE_TYPE_UNKNOWN) {
18097 freopen("CONOUT$", "w", stdout);
18098 }
18099 if (ftype2 == FILE_TYPE_UNKNOWN) {
18100 freopen("CONOUT$", "w", stderr);
18101 }
18102 setargv(&argc, &argv, lpszCmdLine, (char *) name);
18103 #if defined(ENABLE_NVFS) && (ENABLE_NVFS)
18104 nvfs_init();
18105 #endif
18106 sqlite3_main(argc, argv);
18107 }
18108
18109 #endif /* WITHOUT_SHELL */
18110
18111 #endif /* _WIN32 || _WIN64 */
18112
18113 #if defined(HAVE_ODBCINSTEXT_H) && (HAVE_ODBCINSTEXT_H)
18114
18115 /*
18116 * unixODBC property page for this driver,
18117 * may or may not work depending on unixODBC version.
18118 */
18119
18120 #include <odbcinstext.h>
18121
18122 int
ODBCINSTGetProperties(HODBCINSTPROPERTY prop)18123 ODBCINSTGetProperties(HODBCINSTPROPERTY prop)
18124 {
18125 static const char *instYN[] = { "No", "Yes", NULL };
18126 static const char *syncPragma[] = { "NORMAL", "OFF", "FULL", NULL };
18127 static const char *jmPragma[] = {
18128 "DELETE", "PERSIST", "OFF", "TRUNCATE", "MEMORY", "WAL", NULL
18129 };
18130
18131 prop->pNext = (HODBCINSTPROPERTY) malloc(sizeof (ODBCINSTPROPERTY));
18132 prop = prop->pNext;
18133 memset(prop, 0, sizeof (ODBCINSTPROPERTY));
18134 prop->nPromptType = ODBCINST_PROMPTTYPE_FILENAME;
18135 strncpy(prop->szName, "Database", INI_MAX_PROPERTY_NAME);
18136 strncpy(prop->szValue, "", INI_MAX_PROPERTY_VALUE);
18137 prop->pNext = (HODBCINSTPROPERTY) malloc(sizeof (ODBCINSTPROPERTY));
18138 prop = prop->pNext;
18139 memset(prop, 0, sizeof (ODBCINSTPROPERTY));
18140 prop->nPromptType = ODBCINST_PROMPTTYPE_TEXTEDIT;
18141 strncpy(prop->szName, "Timeout", INI_MAX_PROPERTY_NAME);
18142 strncpy(prop->szValue, "100000", INI_MAX_PROPERTY_VALUE);
18143 prop->pNext = (HODBCINSTPROPERTY) malloc(sizeof (ODBCINSTPROPERTY));
18144 prop = prop->pNext;
18145 memset(prop, 0, sizeof (ODBCINSTPROPERTY));
18146 prop->nPromptType = ODBCINST_PROMPTTYPE_COMBOBOX;
18147 prop->aPromptData = malloc(sizeof (instYN));
18148 memcpy(prop->aPromptData, instYN, sizeof (instYN));
18149 strncpy(prop->szName, "StepAPI", INI_MAX_PROPERTY_NAME);
18150 strncpy(prop->szValue, "No", INI_MAX_PROPERTY_VALUE);
18151 prop->pNext = (HODBCINSTPROPERTY) malloc(sizeof (ODBCINSTPROPERTY));
18152 prop = prop->pNext;
18153 memset(prop, 0, sizeof (ODBCINSTPROPERTY));
18154 prop->nPromptType = ODBCINST_PROMPTTYPE_COMBOBOX;
18155 prop->aPromptData = malloc(sizeof (instYN));
18156 memcpy(prop->aPromptData, instYN, sizeof (instYN));
18157 strncpy(prop->szName, "ShortNames", INI_MAX_PROPERTY_NAME);
18158 strncpy(prop->szValue, "No", INI_MAX_PROPERTY_VALUE);
18159 prop->pNext = (HODBCINSTPROPERTY) malloc(sizeof (ODBCINSTPROPERTY));
18160 prop = prop->pNext;
18161 memset(prop, 0, sizeof (ODBCINSTPROPERTY));
18162 prop->nPromptType = ODBCINST_PROMPTTYPE_COMBOBOX;
18163 prop->aPromptData = malloc(sizeof (instYN));
18164 memcpy(prop->aPromptData, instYN, sizeof (instYN));
18165 strncpy(prop->szName, "LongNames", INI_MAX_PROPERTY_NAME);
18166 strncpy(prop->szValue, "No", INI_MAX_PROPERTY_VALUE);
18167 prop->pNext = (HODBCINSTPROPERTY) malloc(sizeof (ODBCINSTPROPERTY));
18168 memset(prop, 0, sizeof (ODBCINSTPROPERTY));
18169 prop->nPromptType = ODBCINST_PROMPTTYPE_COMBOBOX;
18170 prop->aPromptData = malloc(sizeof (instYN));
18171 memcpy(prop->aPromptData, instYN, sizeof (instYN));
18172 strncpy(prop->szName, "NoCreat", INI_MAX_PROPERTY_NAME);
18173 strncpy(prop->szValue, "No", INI_MAX_PROPERTY_VALUE);
18174 #ifdef WINTERFACE
18175 prop->pNext = (HODBCINSTPROPERTY) malloc(sizeof (ODBCINSTPROPERTY));
18176 memset(prop, 0, sizeof (ODBCINSTPROPERTY));
18177 prop->nPromptType = ODBCINST_PROMPTTYPE_COMBOBOX;
18178 prop->aPromptData = malloc(sizeof (instYN));
18179 memcpy(prop->aPromptData, instYN, sizeof (instYN));
18180 strncpy(prop->szName, "NoWCHAR", INI_MAX_PROPERTY_NAME);
18181 strncpy(prop->szValue, "No", INI_MAX_PROPERTY_VALUE);
18182 #endif
18183 prop->pNext = (HODBCINSTPROPERTY) malloc(sizeof (ODBCINSTPROPERTY));
18184 memset(prop, 0, sizeof (ODBCINSTPROPERTY));
18185 prop->nPromptType = ODBCINST_PROMPTTYPE_COMBOBOX;
18186 prop->aPromptData = malloc(sizeof (instYN));
18187 memcpy(prop->aPromptData, instYN, sizeof (instYN));
18188 strncpy(prop->szName, "FKSupport", INI_MAX_PROPERTY_NAME);
18189 strncpy(prop->szValue, "No", INI_MAX_PROPERTY_VALUE);
18190 prop->pNext = (HODBCINSTPROPERTY) malloc(sizeof (ODBCINSTPROPERTY));
18191 prop = prop->pNext;
18192 memset(prop, 0, sizeof (ODBCINSTPROPERTY));
18193 prop->nPromptType = ODBCINST_PROMPTTYPE_COMBOBOX;
18194 prop->aPromptData = malloc(sizeof (syncPragma));
18195 memcpy(prop->aPromptData, syncPragma, sizeof (syncPragma));
18196 strncpy(prop->szName, "SyncPragma", INI_MAX_PROPERTY_NAME);
18197 strncpy(prop->szValue, "NORMAL", INI_MAX_PROPERTY_VALUE);
18198 prop->pNext = (HODBCINSTPROPERTY) malloc(sizeof (ODBCINSTPROPERTY));
18199 prop = prop->pNext;
18200 memset(prop, 0, sizeof (ODBCINSTPROPERTY));
18201 prop->nPromptType = ODBCINST_PROMPTTYPE_COMBOBOX;
18202 prop->aPromptData = malloc(sizeof (jmPragma));
18203 memcpy(prop->aPromptData, jmPragma, sizeof (jmPragma));
18204 strncpy(prop->szName, "JournalMode", INI_MAX_PROPERTY_NAME);
18205 strncpy(prop->szValue, "DELETE", INI_MAX_PROPERTY_VALUE);
18206 prop->pNext = (HODBCINSTPROPERTY) malloc(sizeof (ODBCINSTPROPERTY));
18207 prop = prop->pNext;
18208 memset(prop, 0, sizeof (ODBCINSTPROPERTY));
18209 prop->nPromptType = ODBCINST_PROMPTTYPE_TEXTEDIT;
18210 strncpy(prop->szName, "LoadExt", INI_MAX_PROPERTY_NAME);
18211 strncpy(prop->szValue, "", INI_MAX_PROPERTY_VALUE);
18212 prop->pNext = (HODBCINSTPROPERTY) malloc(sizeof (ODBCINSTPROPERTY));
18213 memset(prop, 0, sizeof (ODBCINSTPROPERTY));
18214 prop->nPromptType = ODBCINST_PROMPTTYPE_COMBOBOX;
18215 prop->aPromptData = malloc(sizeof (instYN));
18216 memcpy(prop->aPromptData, instYN, sizeof (instYN));
18217 strncpy(prop->szName, "BigInt", INI_MAX_PROPERTY_NAME);
18218 strncpy(prop->szValue, "No", INI_MAX_PROPERTY_VALUE);
18219 return 1;
18220 }
18221
18222 #endif /* HAVE_ODBCINSTEXT_H */
18223
18224 #ifdef SQLITE_DYNLOAD
18225
18226 /*
18227 * SQLite3 shared library/DLL stubs.
18228 */
18229
18230 static void
dls_void(void)18231 dls_void(void)
18232 {
18233 }
18234
18235 static int
dls_error(void)18236 dls_error(void)
18237 {
18238 return SQLITE_ERROR;
18239 }
18240
18241 static int
dls_0(void)18242 dls_0(void)
18243 {
18244 return 0;
18245 }
18246
18247 static void *
dls_null(void)18248 dls_null(void)
18249 {
18250 return NULL;
18251 }
18252
18253 static const char *
dls_empty(void)18254 dls_empty(void)
18255 {
18256 return "";
18257 }
18258
18259 static int
dls_snull(void)18260 dls_snull(void)
18261 {
18262 return SQLITE_NULL;
18263 }
18264
18265 #define DLS_ENT(name, func) \
18266 { "sqlite3_" #name, offsetof(struct dl_sqlite3_funcs, name), \
18267 (void *) func }
18268
18269 #define DLS_ENT3(name, off, func) \
18270 { "sqlite3_" #name, offsetof(struct dl_sqlite3_funcs, off), \
18271 (void *) func }
18272
18273 #define DLS_END { NULL, 0, NULL }
18274
18275 static struct {
18276 const char *name;
18277 int offset;
18278 void *func;
18279 } dls_nametab[] = {
18280 DLS_ENT(activate_see, dls_void),
18281 DLS_ENT(bind_blob, dls_error),
18282 DLS_ENT(bind_double, dls_error),
18283 DLS_ENT(bind_int, dls_error),
18284 DLS_ENT(bind_int64, dls_error),
18285 DLS_ENT(bind_null, dls_error),
18286 DLS_ENT(bind_parameter_count, dls_0),
18287 DLS_ENT(bind_text, dls_error),
18288 DLS_ENT(busy_handler, dls_error),
18289 DLS_ENT(changes, dls_0),
18290 DLS_ENT(close, dls_error),
18291 DLS_ENT(column_blob, dls_null),
18292 DLS_ENT(column_bytes, dls_0),
18293 DLS_ENT(column_count, dls_0),
18294 DLS_ENT(column_database_name, dls_empty),
18295 DLS_ENT(column_decltype, dls_empty),
18296 DLS_ENT(column_name, dls_empty),
18297 DLS_ENT(column_origin_name, dls_null),
18298 DLS_ENT(column_table_name, dls_null),
18299 DLS_ENT(column_text, dls_null),
18300 DLS_ENT(column_type, dls_snull),
18301 DLS_ENT(create_function, dls_error),
18302 DLS_ENT(enable_load_extension, dls_error),
18303 DLS_ENT(errcode, dls_error),
18304 DLS_ENT(errmsg, dls_empty),
18305 DLS_ENT(exec, dls_error),
18306 DLS_ENT(finalize, dls_error),
18307 DLS_ENT(free, free),
18308 DLS_ENT(free_table, dls_void),
18309 DLS_ENT(get_table, dls_error),
18310 DLS_ENT(interrupt, dls_void),
18311 DLS_ENT(key, dls_error),
18312 DLS_ENT(libversion, dls_empty),
18313 DLS_ENT(load_extension, dls_error),
18314 DLS_ENT(malloc, malloc),
18315 DLS_ENT(mprintf, dls_null),
18316 DLS_ENT(open, dls_error),
18317 DLS_ENT(open16, dls_error),
18318 DLS_ENT(open_v2, dls_error),
18319 DLS_ENT(prepare, dls_error),
18320 DLS_ENT(prepare_v2, dls_error),
18321 DLS_ENT(profile, dls_null),
18322 DLS_ENT(realloc, realloc),
18323 DLS_ENT(rekey, dls_error),
18324 DLS_ENT(reset, dls_error),
18325 DLS_ENT(result_blob, dls_void),
18326 DLS_ENT(result_error, dls_void),
18327 DLS_ENT(result_int, dls_void),
18328 DLS_ENT(result_null, dls_void),
18329 DLS_ENT(step, dls_error),
18330 #if defined(_WIN32) || defined(_WIN64)
18331 DLS_ENT3(strnicmp, xstrnicmp, _strnicmp),
18332 #else
18333 DLS_ENT3(strnicmp, xstrnicmp, strncasecmp),
18334 #endif
18335 DLS_ENT(table_column_metadata, dls_error),
18336 DLS_ENT(trace, dls_null),
18337 DLS_ENT(user_data, dls_null),
18338 DLS_ENT(value_blob, dls_null),
18339 DLS_ENT(value_bytes, dls_0),
18340 DLS_ENT(value_text, dls_empty),
18341 DLS_ENT(value_type, dls_snull),
18342 DLS_END
18343 };
18344
18345 #if defined(_WIN32) || defined(_WIN64)
18346
18347 static HMODULE sqlite3_dll = 0;
18348
18349 static void
dls_init(void)18350 dls_init(void)
18351 {
18352 int i;
18353 static const char *dll_names[] = {
18354 "System.Data.SQLite.dll",
18355 "sqlite3.dll",
18356 NULL,
18357 };
18358
18359 i = 0;
18360 while (dll_names[i]) {
18361 sqlite3_dll = LoadLibrary(dll_names[i]);
18362 if (sqlite3_dll) {
18363 break;
18364 }
18365 ++i;
18366 }
18367 i = 0;
18368 while (dls_nametab[i].name) {
18369 void *func = 0, **loc;
18370
18371 if (sqlite3_dll) {
18372 func = (void *) GetProcAddress(sqlite3_dll, dls_nametab[i].name);
18373 }
18374 if (!func) {
18375 func = dls_nametab[i].func;
18376 }
18377 loc = (void **) ((char *) &dls_funcs + dls_nametab[i].offset);
18378 *loc = func;
18379 ++i;
18380 }
18381 if (!sqlite3_dll) {
18382 char buf[MAXPATHLEN], msg[MAXPATHLEN];
18383
18384 LoadString(hModule, IDS_DRVTITLE, buf, sizeof (buf));
18385 LoadString(hModule, IDS_DLLERR, msg, sizeof (msg));
18386 MessageBox(NULL, msg, buf,
18387 MB_ICONEXCLAMATION | MB_OK | MB_TASKMODAL |
18388 MB_SETFOREGROUND);
18389 }
18390 }
18391
18392 static void
dls_fini(void)18393 dls_fini(void)
18394 {
18395 if (sqlite3_dll) {
18396 FreeLibrary(sqlite3_dll);
18397 sqlite3_dll = 0;
18398 }
18399 }
18400
18401 #else
18402
18403 #include <dlfcn.h>
18404
18405 static void *libsqlite3_so = 0;
18406
18407 void
dls_init(void)18408 dls_init(void)
18409 {
18410 int i;
18411
18412 libsqlite3_so = dlopen("libsqlite3.so.0", RTLD_NOW | RTLD_GLOBAL);
18413 i = 0;
18414 while (dls_nametab[i].name) {
18415 void *func = 0, **loc;
18416
18417 if (libsqlite3_so) {
18418 func = dlsym(libsqlite3_so, dls_nametab[i].name);
18419 }
18420 if (!func) {
18421 func = dls_nametab[i].func;
18422 }
18423 loc = (void **) ((char *) &dls_funcs + dls_nametab[i].offset);
18424 *loc = func;
18425 ++i;
18426 }
18427 if (!libsqlite3_so) {
18428 const char errmsg[] = "SQLite3 shared library not found.\n";
18429
18430 write(2, errmsg, sizeof (errmsg) - 1);
18431 }
18432 }
18433
18434 void
dls_fini(void)18435 dls_fini(void)
18436 {
18437 if (libsqlite3_so) {
18438 dlclose(libsqlite3_so);
18439 libsqlite3_so = 0;
18440 }
18441 }
18442
18443 #endif
18444
18445 #endif
18446