00001
00014 #include "sqliteodbc.h"
00015
00016 #ifdef SQLITE_UTF8
00017 #include <sqlucode.h>
00018 #endif
00019
00020 #ifdef _WIN32
00021 #include "resource.h"
00022 #define ODBC_INI "ODBC.INI"
00023 #define DRIVER_VER_INFO VERSION
00024 #else
00025 #define ODBC_INI ".odbc.ini"
00026 #endif
00027
00028 #ifndef DRIVER_VER_INFO
00029 #define DRIVER_VER_INFO "0.0"
00030 #endif
00031
00032 #undef min
00033 #define min(a, b) ((a) < (b) ? (a) : (b))
00034 #undef max
00035 #define max(a, b) ((a) < (b) ? (b) : (a))
00036
00037 #define array_size(x) (sizeof (x) / sizeof (x[0]))
00038
00039 #define stringify1(s) #s
00040 #define stringify(s) stringify1(s)
00041
00042 #define verinfo(maj, min, lev) ((maj) << 16 | (min) << 8 | (lev))
00043
00044
00045
00046 #ifdef SQLITE_UTF8
00047 #define SCOL_VARCHAR SQL_WVARCHAR
00048 #define SCOL_CHAR SQL_WCHAR
00049 #else
00050 #define SCOL_VARCHAR SQL_VARCHAR
00051 #define SCOL_CHAR SQL_CHAR
00052 #endif
00053
00054 #define ENV_MAGIC 0x53544145
00055 #define DBC_MAGIC 0x53544144
00056 #define DEAD_MAGIC 0xdeadbeef
00057
00058 #ifdef MEMORY_DEBUG
00059
00060 static void *
00061 xmalloc_(int n, char *file, int line)
00062 {
00063 int nn = n + 4 * sizeof (long);
00064 long *p;
00065
00066 p = malloc(nn);
00067 if (!p) {
00068 #if (MEMORY_DEBUG > 1)
00069 fprintf(stderr, "malloc\t%d\tNULL\t%s:%d\n", n, file, line);
00070 #endif
00071 return NULL;
00072 }
00073 p[0] = 0xdead1234;
00074 nn = nn / sizeof (long) - 1;
00075 p[1] = n;
00076 p[nn] = 0xdead5678;
00077 #if (MEMORY_DEBUG > 1)
00078 fprintf(stderr, "malloc\t%d\t%p\t%s:%d\n", n, &p[2], file, line);
00079 #endif
00080 return (void *) &p[2];
00081 }
00082
00083 static void *
00084 xrealloc_(void *old, int n, char *file, int line)
00085 {
00086 int nn = n + 4 * sizeof (long), nnn;
00087 long *p, *pp;
00088
00089 if (n == 0) {
00090 return xmalloc_(n, file, line);
00091 }
00092 p = &((long *) old)[-2];
00093 if (p[0] != 0xdead1234) {
00094 fprintf(stderr, "*** low end corruption @ %p\n", old);
00095 abort();
00096 }
00097 nnn = p[1] + 4 * sizeof (long);
00098 nnn = nnn / sizeof (long) - 1;
00099 if (p[nnn] != 0xdead5678) {
00100 fprintf(stderr, "*** high end corruption @ %p\n", old);
00101 abort();
00102 }
00103 pp = realloc(p, nn);
00104 if (!pp) {
00105 #if (MEMORY_DEBUG > 1)
00106 fprintf(stderr, "realloc\t%p,%d\tNULL\t%s:%d\n", old, n, file, line);
00107 #endif
00108 return NULL;
00109 }
00110 #if (MEMORY_DEBUG > 1)
00111 fprintf(stderr, "realloc\t%p,%d\t%p\t%s:%d\n", old, n, &pp[2], file, line);
00112 #endif
00113 p = pp;
00114 if (n > p[1]) {
00115 memset(p + p[1], 0, 3 * sizeof (long));
00116 }
00117 p[1] = n;
00118 nn = nn / sizeof (long) - 1;
00119 p[nn] = 0xdead5678;
00120 return (void *) &p[2];
00121 }
00122
00123 static void
00124 xfree_(void *x, char *file, int line)
00125 {
00126 long *p;
00127 int n;
00128
00129 p = &((long *) x)[-2];
00130 if (p[0] != 0xdead1234) {
00131 fprintf(stderr, "*** low end corruption @ %p\n", x);
00132 abort();
00133 }
00134 n = p[1] + 4 * sizeof (long);
00135 n = n / sizeof (long) - 1;
00136 if (p[n] != 0xdead5678) {
00137 fprintf(stderr, "*** high end corruption @ %p\n", x);
00138 abort();
00139 }
00140 #if (MEMORY_DEBUG > 1)
00141 fprintf(stderr, "free\t%p\t\t%s:%d\n", x, file, line);
00142 #endif
00143 free(p);
00144 }
00145
00146 static void
00147 xfree__(void *x)
00148 {
00149 xfree_(x, "unknown location", 0);
00150 }
00151
00152 static char *
00153 xstrdup_(char *str, char *file, int line)
00154 {
00155 char *p;
00156
00157 if (!str) {
00158 #if (MEMORY_DEBUG > 1)
00159 fprintf(stderr, "strdup\tNULL\tNULL\t%s:%d\n", file, line);
00160 #endif
00161 return NULL;
00162 }
00163 p = xmalloc_(strlen(str) + 1, file, line);
00164 if (p) {
00165 strcpy(p, str);
00166 }
00167 #if (MEMORY_DEBUG > 1)
00168 fprintf(stderr, "strdup\t%p\t%p\t%s:%d\n", str, p, file, line);
00169 #endif
00170 return p;
00171 }
00172
00173 #define xmalloc(x) xmalloc_(x, __FILE__, __LINE__)
00174 #define xrealloc(x,y) xrealloc_(x, y, __FILE__, __LINE__)
00175 #define xfree(x) xfree_(x, __FILE__, __LINE__)
00176 #define xstrdup(x) xstrdup_(x, __FILE__, __LINE__)
00177
00178 #else
00179
00180 #define xmalloc(x) malloc(x)
00181 #define xrealloc(x,y) realloc(x, y)
00182 #define xfree(x) free(x)
00183 #define xstrdup(x) strdup_(x)
00184
00185 #endif
00186
00187 #ifdef _WIN32
00188 #define vsnprintf _vsnprintf
00189 #define snprintf _snprintf
00190 #define strncasecmp _strnicmp
00191 #endif
00192
00193
00194
00195
00196
00197 static const char upper_chars[] = "ABCDEFGHIJKLMNOPQRSTUVWXYZ";
00198 static const char lower_chars[] = "abcdefghijklmnopqrstuvwxyz";
00199
00200 static int
00201 TOLOWER(int c)
00202 {
00203 if (c) {
00204 char *p = strchr(upper_chars, c);
00205
00206 if (p) {
00207 c = lower_chars[p - upper_chars];
00208 }
00209 }
00210 return c;
00211 }
00212
00213
00214
00215
00216
00217 static const char digit_chars[] = "0123456789";
00218
00219 #define ISDIGIT(c) \
00220 ((c) && strchr(digit_chars, (c)) != NULL)
00221
00222
00223
00224
00225
00226 static const char space_chars[] = " \f\n\r\t\v";
00227
00228 #define ISSPACE(c) \
00229 ((c) && strchr(space_chars, (c)) != NULL)
00230
00231
00232
00233
00234
00235 static const char id_chars[] = "ABCDEFGHIJKLMNOPQRSTUVWXYZ"
00236 "abcdefghijklmnopqrstuvwxyz"
00237 "_0123456789";
00238
00239 #define ISIDCHAR(c) \
00240 ((c) && strchr(id_chars, (c)) != NULL)
00241
00247 static void unbindcols(STMT *s);
00248
00256 static SQLRETURN mkbindcols(STMT *s, int ncols);
00257
00269 static void freeresult(STMT *s, int clrcols);
00270
00277 static SQLRETURN freestmt(HSTMT stmt);
00278
00293 static SQLRETURN substparam(STMT *s, int pnum, char **out, int *size);
00294
00300 static void freedyncols(STMT *s);
00301
00308 static SQLRETURN drvexecute(SQLHSTMT stmt);
00309
00310 #if (MEMORY_DEBUG < 1)
00311
00317 static char *
00318 strdup_(const char *str)
00319 {
00320 char *p = NULL;
00321
00322 if (str) {
00323 p = xmalloc(strlen(str) + 1);
00324 if (p) {
00325 strcpy(p, str);
00326 }
00327 }
00328 return p;
00329 }
00330 #endif
00331
00332 #ifdef SQLITE_UTF8
00333
00339 static int
00340 uc_strlen(SQLWCHAR *str)
00341 {
00342 int len = 0;
00343
00344 if (str) {
00345 while (*str) {
00346 ++len;
00347 ++str;
00348 }
00349 }
00350 return len;
00351 }
00352
00361 static SQLWCHAR *
00362 uc_strncpy(SQLWCHAR *dest, SQLWCHAR *src, int len)
00363 {
00364 int i = 0;
00365
00366 while (i < len) {
00367 if (!src[i]) {
00368 break;
00369 }
00370 dest[i] = src[i];
00371 ++i;
00372 }
00373 if (i < len) {
00374 dest[i] = 0;
00375 }
00376 return dest;
00377 }
00378
00386 static void
00387 uc_from_utf_buf(unsigned char *str, SQLWCHAR *uc, int ucLen)
00388 {
00389 ucLen = ucLen / sizeof (SQLWCHAR);
00390 if (!uc || ucLen < 0) {
00391 return;
00392 }
00393 uc[0] = 0;
00394 if (str) {
00395 int i = 0;
00396
00397 while (*str && i < ucLen) {
00398 unsigned char c = str[0];
00399
00400 if (c < 0xc0) {
00401 uc[i++] = c;
00402 ++str;
00403 } else if (c < 0xe0) {
00404 if ((str[1] & 0xc0) == 0x80) {
00405 unsigned long t = ((c & 0x1f) << 6) | (str[1] & 0x3f);
00406
00407 uc[i++] = t;
00408 str += 2;
00409 } else {
00410 uc[i++] = c;
00411 ++str;
00412 }
00413 } else if (c < 0xf0) {
00414 if ((str[1] & 0xc0) == 0x80 && (str[2] & 0xc0) == 0x80) {
00415 unsigned long t = ((c & 0x0f) << 12) |
00416 ((str[1] & 0x3f) << 6) | (str[2] & 0x3f);
00417
00418 uc[i++] = t;
00419 str += 3;
00420 } else {
00421 uc[i++] = c;
00422 ++str;
00423 }
00424 } else if (c < 0xf8) {
00425 if ((str[1] & 0xc0) == 0x80 && (str[2] & 0xc0) == 0x80 &&
00426 (str[3] & 0xc0) == 0x80) {
00427 unsigned long t = ((c & 0x03) << 18) |
00428 ((str[1] & 0x3f) << 12) | ((str[2] & 0x3f) << 6) |
00429 (str[4] & 0x3f);
00430
00431 uc[i++] = t;
00432 str += 4;
00433 } else {
00434 uc[i++] = c;
00435 ++str;
00436 }
00437 } else if (c < 0xfc) {
00438 if ((str[1] & 0xc0) == 0x80 && (str[2] & 0xc0) == 0x80 &&
00439 (str[3] & 0xc0) == 0x80 && (str[4] & 0xc0) == 0x80) {
00440 unsigned long t = ((c & 0x01) << 24) |
00441 ((str[1] & 0x3f) << 18) | ((str[2] & 0x3f) << 12) |
00442 ((str[4] & 0x3f) << 6) | (str[5] & 0x3f);
00443
00444 uc[i++] = t;
00445 str += 5;
00446 } else {
00447 uc[i++] = c;
00448 ++str;
00449 }
00450 } else {
00451
00452 ++str;
00453 }
00454 }
00455 if (i < ucLen) {
00456 uc[i] = 0;
00457 }
00458 }
00459 }
00460
00468 static SQLWCHAR *
00469 uc_from_utf(unsigned char *str, int len)
00470 {
00471 SQLWCHAR *uc = NULL;
00472
00473 if (str) {
00474 if (len == SQL_NTS) {
00475 len = strlen(str);
00476 }
00477 len = sizeof (SQLWCHAR) * (len + 1);
00478 uc = xmalloc(len);
00479 if (uc) {
00480 uc_from_utf_buf(str, uc, len);
00481 }
00482 }
00483 return uc;
00484 }
00485
00493 static char *
00494 uc_to_utf(SQLWCHAR *str, int len)
00495 {
00496 int i;
00497 char *cp, *ret = NULL;
00498
00499 if (!str) {
00500 return ret;
00501 }
00502 if (len == SQL_NTS) {
00503 len = uc_strlen(str);
00504 } else {
00505 len = len / sizeof (SQLWCHAR);
00506 }
00507 cp = xmalloc(len * 6 + 1);
00508 if (!cp) {
00509 return ret;
00510 }
00511 ret = cp;
00512 for (i = 0; i < len; i++) {
00513 unsigned long c = str[i];
00514
00515 if (c < 0xc0) {
00516 *cp++ = c;
00517 } else if (c < 0x800) {
00518 *cp++ = 0xc0 | ((c >> 6) & 0x1f);
00519 *cp++ = 0x80 | (c & 0x3f);
00520 } else if (c < 0x10000) {
00521 *cp++ = 0xe0 | ((c >> 12) & 0x0f);
00522 *cp++ = 0x80 | ((c >> 6) & 0x3f);
00523 *cp++ = 0x80 | (c & 0x3f);
00524 } else if (c < 0x200000) {
00525 *cp++ = 0xf0 | ((c >> 18) & 0x07);
00526 *cp++ = 0x80 | ((c >> 12) & 0x3f);
00527 *cp++ = 0x80 | ((c >> 6) & 0x3f);
00528 *cp++ = 0x80 | (c & 0x3f);
00529 } else if (c < 0x4000000) {
00530 *cp++ = 0xf8 | ((c >> 24) & 0x03);
00531 *cp++ = 0x80 | ((c >> 18) & 0x3f);
00532 *cp++ = 0x80 | ((c >> 12) & 0x3f);
00533 *cp++ = 0x80 | ((c >> 6) & 0x3f);
00534 *cp++ = 0x80 | (c & 0x3f);
00535 } else if (c < 0x80000000) {
00536 *cp++ = 0xfc | ((c >> 31) & 0x01);
00537 *cp++ = 0x80 | ((c >> 24) & 0x3f);
00538 *cp++ = 0x80 | ((c >> 18) & 0x3f);
00539 *cp++ = 0x80 | ((c >> 12) & 0x3f);
00540 *cp++ = 0x80 | ((c >> 6) & 0x3f);
00541 *cp++ = 0x80 | (c & 0x3f);
00542 }
00543 }
00544 *cp = '\0';
00545 return ret;
00546 }
00547
00555 static char *
00556 uc_to_utf_c(SQLWCHAR *str, int len)
00557 {
00558 if (len != SQL_NTS) {
00559 len = len * sizeof (SQLWCHAR);
00560 }
00561 return uc_to_utf(str, len);
00562 }
00563
00568 static void
00569 uc_free(void *str)
00570 {
00571 if (str) {
00572 xfree(str);
00573 }
00574 }
00575 #endif
00576
00577 #ifdef USE_DLOPEN_FOR_GPPS
00578
00579 #include <dlfcn.h>
00580
00581 #define SQLGetPrivateProfileString(A,B,C,D,E,F) drvgpps(d,A,B,C,D,E,F)
00582
00583
00584
00585
00586
00587
00588
00589
00590 static void
00591 drvgetgpps(DBC *d)
00592 {
00593 void *lib;
00594 int (*gpps)();
00595
00596 lib = dlopen("libodbcinst.so", RTLD_LAZY);
00597 if (!lib) {
00598 lib = dlopen("libiodbcinst.so", RTLD_LAZY);
00599 }
00600 if (lib) {
00601 gpps = (int (*)()) dlsym(lib, "SQLGetPrivateProfileString");
00602 if (!gpps) {
00603 dlclose(lib);
00604 return;
00605 }
00606 d->instlib = lib;
00607 d->gpps = gpps;
00608 }
00609 }
00610
00611 static void
00612 drvrelgpps(DBC *d)
00613 {
00614 if (d->instlib) {
00615 dlclose(d->instlib);
00616 d->instlib = 0;
00617 }
00618 }
00619
00620 static int
00621 drvgpps(DBC *d, char *sect, char *ent, char *def, char *buf,
00622 int bufsiz, char *fname)
00623 {
00624 if (d->gpps) {
00625 return d->gpps(sect, ent, def, buf, bufsiz, fname);
00626 }
00627 strncpy(buf, def, bufsiz);
00628 buf[bufsiz - 1] = '\0';
00629 return 1;
00630 }
00631 #else
00632 #define drvgetgpps(d)
00633 #define drvrelgpps(d)
00634 #endif
00635
00644 #if defined(__GNUC__) && (__GNUC__ >= 2)
00645 static void setstatd(DBC *, int, char *, char *, ...)
00646 __attribute__((format (printf, 3, 5)));
00647 #endif
00648
00649 static void
00650 setstatd(DBC *d, int naterr, char *msg, char *st, ...)
00651 {
00652 va_list ap;
00653
00654 if (!d) {
00655 return;
00656 }
00657 d->naterr = naterr;
00658 d->logmsg[0] = '\0';
00659 if (msg) {
00660 int count;
00661
00662 va_start(ap, st);
00663 count = vsnprintf(d->logmsg, sizeof (d->logmsg), msg, ap);
00664 va_end(ap);
00665 if (count < 0) {
00666 d->logmsg[sizeof (d->logmsg) - 1] = '\0';
00667 }
00668 }
00669 if (!st) {
00670 st = "?????";
00671 }
00672 strncpy(d->sqlstate, st, 5);
00673 d->sqlstate[5] = '\0';
00674 }
00675
00684 #if defined(__GNUC__) && (__GNUC__ >= 2)
00685 static void setstat(STMT *, int, char *, char *, ...)
00686 __attribute__((format (printf, 3, 5)));
00687 #endif
00688
00689 static void
00690 setstat(STMT *s, int naterr, char *msg, char *st, ...)
00691 {
00692 va_list ap;
00693
00694 if (!s) {
00695 return;
00696 }
00697 s->naterr = naterr;
00698 s->logmsg[0] = '\0';
00699 if (msg) {
00700 int count;
00701
00702 va_start(ap, st);
00703 count = vsnprintf(s->logmsg, sizeof (s->logmsg), msg, ap);
00704 va_end(ap);
00705 if (count < 0) {
00706 s->logmsg[sizeof (s->logmsg) - 1] = '\0';
00707 }
00708 }
00709 if (!st) {
00710 st = "?????";
00711 }
00712 strncpy(s->sqlstate, st, 5);
00713 s->sqlstate[5] = '\0';
00714 }
00715
00722 static SQLRETURN
00723 drvunimpldbc(HDBC dbc)
00724 {
00725 DBC *d;
00726
00727 if (dbc == SQL_NULL_HDBC) {
00728 return SQL_INVALID_HANDLE;
00729 }
00730 d = (DBC *) dbc;
00731 setstatd(d, -1, "not supported", "IM001");
00732 return SQL_ERROR;
00733 }
00734
00741 static SQLRETURN
00742 drvunimplstmt(HSTMT stmt)
00743 {
00744 STMT *s;
00745
00746 if (stmt == SQL_NULL_HSTMT) {
00747 return SQL_INVALID_HANDLE;
00748 }
00749 s = (STMT *) stmt;
00750 setstat(s, -1, "not supported", "IM001");
00751 return SQL_ERROR;
00752 }
00753
00759 static void
00760 freep(void *x)
00761 {
00762 if (x && ((char **) x)[0]) {
00763 xfree(((char **) x)[0]);
00764 ((char **) x)[0] = NULL;
00765 }
00766 }
00767
00774 static SQLRETURN
00775 nomem(STMT *s)
00776 {
00777 setstat(s, -1, "out of memory", (*s->ov3) ? "HY000" : "S1000");
00778 return SQL_ERROR;
00779 }
00780
00787 static SQLRETURN
00788 noconn(STMT *s)
00789 {
00790 setstat(s, -1, "not connected", (*s->ov3) ? "HY000" : "S1000");
00791 return SQL_ERROR;
00792 }
00793
00801 #if defined(HAVE_SQLITEATOF) && HAVE_SQLITEATOF
00802
00803 extern double sqliteAtoF(char *data, char **endp);
00804
00805 #define ln_strtod sqliteAtoF
00806
00807 #else
00808
00809 static double
00810 ln_strtod(const char *data, char **endp)
00811 {
00812 #if defined(HAVE_LOCALECONV) || defined(_WIN32)
00813 struct lconv *lc;
00814 char buf[128], *p, *end;
00815 double value;
00816
00817 lc = localeconv();
00818 if (lc && lc->decimal_point && lc->decimal_point[0] &&
00819 lc->decimal_point[0] != '.') {
00820 strncpy(buf, data, sizeof (buf) - 1);
00821 buf[sizeof (buf) - 1] = '\0';
00822 p = strchr(buf, '.');
00823 if (p) {
00824 *p = lc->decimal_point[0];
00825 }
00826 p = buf;
00827 } else {
00828 p = (char *) data;
00829 }
00830 value = strtod(p, &end);
00831 end = (char *) data + (end - p);
00832 if (endp) {
00833 *endp = end;
00834 }
00835 return value;
00836 #else
00837 return strtod(data, endp);
00838 #endif
00839 }
00840
00841 #endif
00842
00843 #if !defined(HAVE_SQLITEMPRINTF) || !HAVE_SQLITEMPRINTF
00844
00850 static void
00851 ln_sprintfg(char *buf, double value)
00852 {
00853 #if defined(HAVE_LOCALECONV) || defined(_WIN32)
00854 struct lconv *lc;
00855 char *p;
00856
00857 sprintf(buf, "%.16g", value);
00858 lc = localeconv();
00859 if (lc && lc->decimal_point && lc->decimal_point[0] &&
00860 lc->decimal_point[0] != '.') {
00861 p = strchr(buf, lc->decimal_point[0]);
00862 if (p) {
00863 *p = '.';
00864 }
00865 }
00866 #else
00867 sprintf(buf, "%.16g", value);
00868 #endif
00869 }
00870 #endif
00871
00880 static int
00881 busy_handler(void *udata, const char *table, int count)
00882 {
00883 DBC *d = (DBC *) udata;
00884 long t1;
00885 int ret = 0;
00886 #ifndef _WIN32
00887 struct timeval tv;
00888 #endif
00889
00890 if (d->timeout <= 0) {
00891 return ret;
00892 }
00893 if (count <= 1) {
00894 #ifdef _WIN32
00895 d->t0 = GetTickCount();
00896 #else
00897 gettimeofday(&tv, NULL);
00898 d->t0 = tv.tv_sec * 1000 + tv.tv_usec / 1000;
00899 #endif
00900 }
00901 #ifdef _WIN32
00902 t1 = GetTickCount();
00903 #else
00904 gettimeofday(&tv, NULL);
00905 t1 = tv.tv_sec * 1000 + tv.tv_usec / 1000;
00906 #endif
00907 if (t1 - d->t0 > d->timeout) {
00908 goto done;
00909 return 0;
00910 }
00911 #ifdef _WIN32
00912 Sleep(10);
00913 #else
00914 #ifdef HAVE_USLEEP
00915 usleep(10000);
00916 #else
00917 tv.tv_sec = 0;
00918 tv.tv_usec = 10000;
00919 select(0, NULL, NULL, NULL, &tv);
00920 #endif
00921 #endif
00922 ret = 1;
00923 done:
00924 return ret;
00925 }
00926
00943 static int
00944 setsqliteopts(sqlite *x, DBC *d)
00945 {
00946 int count = 0, step = 0, rc;
00947
00948 while (step < 4) {
00949 if (step < 1) {
00950 rc = sqlite_exec(x, "PRAGMA full_column_names = on;",
00951 NULL, NULL, NULL);
00952 } else if (step < 2) {
00953 rc = sqlite_exec(x, "PRAGMA count_changes = on;",
00954 NULL, NULL, NULL);
00955 } else if (step < 3) {
00956 rc = sqlite_exec(x, "PRAGMA empty_result_callbacks = on;",
00957 NULL, NULL, NULL);
00958 } else {
00959 rc = sqlite_exec(x, "PRAGMA show_datatypes = on;",
00960 NULL, NULL, NULL);
00961 }
00962 if (rc != SQLITE_OK) {
00963 if (rc != SQLITE_BUSY ||
00964 !busy_handler((void *) d, NULL, ++count)) {
00965 return rc;
00966 }
00967 continue;
00968 }
00969 count = 0;
00970 ++step;
00971 }
00972 sqlite_busy_handler(x, busy_handler, (void *) d);
00973 #if HAVE_ENCDEC
00974 {
00975 char *fname;
00976 static void hextobin_func(sqlite_func *context,
00977 int argc, const char **argv);
00978 static void bintohex_func(sqlite_func *context,
00979 int argc, const char **argv);
00980
00981 fname = "hextobin";
00982 sqlite_create_function(x, fname, 1, hextobin_func, 0);
00983 sqlite_function_type(x, fname, SQLITE_TEXT);
00984 fname = "bintohex";
00985 sqlite_create_function(x, fname, 1, bintohex_func, 0);
00986 sqlite_function_type(x, fname, SQLITE_TEXT);
00987 }
00988 #endif
00989 {
00990 char *fname;
00991 static void time_func(sqlite_func *context,
00992 int argc, const char **argv);
00993
00994 fname = "current_time_local";
00995 sqlite_create_function(x, fname, 0, time_func, (void *) 0);
00996 sqlite_function_type(x, fname, SQLITE_TEXT);
00997 fname = "current_time_utc";
00998 sqlite_create_function(x, fname, 0, time_func, (void *) 1);
00999 sqlite_function_type(x, fname, SQLITE_TEXT);
01000 fname = "current_date_local";
01001 sqlite_create_function(x, fname, 0, time_func, (void *) 2);
01002 sqlite_function_type(x, fname, SQLITE_TEXT);
01003 fname = "current_date_utc";
01004 sqlite_create_function(x, fname, 0, time_func, (void *) 3);
01005 sqlite_function_type(x, fname, SQLITE_TEXT);
01006 fname = "current_datetime_local";
01007 sqlite_create_function(x, fname, 0, time_func, (void *) 4);
01008 sqlite_function_type(x, fname, SQLITE_TEXT);
01009 fname = "current_datetime_utc";
01010 sqlite_create_function(x, fname, 0, time_func, (void *) 5);
01011 sqlite_function_type(x, fname, SQLITE_TEXT);
01012 fname = "current_timestamp_local";
01013 sqlite_create_function(x, fname, 0, time_func, (void *) 4);
01014 sqlite_function_type(x, fname, SQLITE_TEXT);
01015 fname = "current_timestamp_utc";
01016 sqlite_create_function(x, fname, 0, time_func, (void *) 5);
01017 sqlite_function_type(x, fname, SQLITE_TEXT);
01018 }
01019 return SQLITE_OK;
01020 }
01021
01031 static void
01032 freerows(char **rowp)
01033 {
01034 int size, i;
01035
01036 if (!rowp) {
01037 return;
01038 }
01039 --rowp;
01040 size = (int) rowp[0];
01041 for (i = 1; i <= size; i++) {
01042 freep(&rowp[i]);
01043 }
01044 freep(&rowp);
01045 }
01046
01056 static int
01057 mapsqltype(const char *typename, int *nosign, int ov3, int nowchar)
01058 {
01059 char *p, *q;
01060 int testsign = 0, result;
01061
01062 #ifdef SQLITE_UTF8
01063 result = nowchar ? SQL_VARCHAR : SQL_WVARCHAR;
01064 #else
01065 result = SQL_VARCHAR;
01066 #endif
01067 if (!typename) {
01068 return result;
01069 }
01070 q = p = xmalloc(strlen(typename) + 1);
01071 if (!p) {
01072 return result;
01073 }
01074 strcpy(p, typename);
01075 while (*q) {
01076 *q = TOLOWER(*q);
01077 ++q;
01078 }
01079 if (strncmp(p, "inter", 5) == 0) {
01080 } else if (strncmp(p, "int", 3) == 0 ||
01081 strncmp(p, "mediumint", 9) == 0) {
01082 testsign = 1;
01083 result = SQL_INTEGER;
01084 } else if (strncmp(p, "numeric", 7) == 0) {
01085 result = SQL_DOUBLE;
01086 } else if (strncmp(p, "tinyint", 7) == 0) {
01087 testsign = 1;
01088 result = SQL_TINYINT;
01089 } else if (strncmp(p, "smallint", 8) == 0) {
01090 testsign = 1;
01091 result = SQL_SMALLINT;
01092 } else if (strncmp(p, "float", 5) == 0) {
01093 result = SQL_DOUBLE;
01094 } else if (strncmp(p, "double", 6) == 0 ||
01095 strncmp(p, "real", 4) == 0) {
01096 result = SQL_DOUBLE;
01097 } else if (strncmp(p, "timestamp", 9) == 0) {
01098 #ifdef SQL_TYPE_TIMESTAMP
01099 result = ov3 ? SQL_TYPE_TIMESTAMP : SQL_TIMESTAMP;
01100 #else
01101 result = SQL_TIMESTAMP;
01102 #endif
01103 } else if (strncmp(p, "datetime", 8) == 0) {
01104 #ifdef SQL_TYPE_TIMESTAMP
01105 result = ov3 ? SQL_TYPE_TIMESTAMP : SQL_TIMESTAMP;
01106 #else
01107 result = SQL_TIMESTAMP;
01108 #endif
01109 } else if (strncmp(p, "time", 4) == 0) {
01110 #ifdef SQL_TYPE_TIME
01111 result = ov3 ? SQL_TYPE_TIME : SQL_TIME;
01112 #else
01113 result = SQL_TIME;
01114 #endif
01115 } else if (strncmp(p, "date", 4) == 0) {
01116 #ifdef SQL_TYPE_DATE
01117 result = ov3 ? SQL_TYPE_DATE : SQL_DATE;
01118 #else
01119 result = SQL_DATE;
01120 #endif
01121 #ifdef SQL_LONGVARCHAR
01122 } else if (strncmp(p, "text", 4) == 0) {
01123 #ifdef SQLITE_UTF8
01124 result = nowchar ? SQL_LONGVARCHAR : SQL_WLONGVARCHAR;
01125 #else
01126 result = SQL_LONGVARCHAR;
01127 #endif
01128 #ifdef SQLITE_UTF8
01129 } else if (strncmp(p, "wtext", 5) == 0 ||
01130 strncmp(p, "wvarchar", 8) == 0 ||
01131 strncmp(p, "longwvarchar", 12) == 0) {
01132 result = SQL_WLONGVARCHAR;
01133 #endif
01134 #endif
01135 #if HAVE_ENCDEC
01136 } else if (strncmp(p, "binary", 6) == 0 ||
01137 strncmp(p, "varbinary", 9) == 0 ||
01138 strncmp(p, "bytea", 5) == 0 ||
01139 strncmp(p, "blob", 4) == 0 ||
01140 strncmp(p, "tinyblob", 8) == 0 ||
01141 strncmp(p, "mediumblob", 10) == 0) {
01142 result = SQL_VARBINARY;
01143 } else if (strncmp(p, "longbinary", 10) == 0 ||
01144 strncmp(p, "longvarbinary", 13) == 0 ||
01145 strncmp(p, "longblob", 8) == 0) {
01146 result = SQL_LONGVARBINARY;
01147 #endif
01148 }
01149 if (nosign) {
01150 if (testsign) {
01151 *nosign = strstr(p, "unsigned") != NULL;
01152 } else {
01153 *nosign = 1;
01154 }
01155 }
01156 xfree(p);
01157 return result;
01158 }
01159
01169 static void
01170 getmd(const char *typename, int sqltype, int *mp, int *dp)
01171 {
01172 int m = 0, d = 0;
01173
01174 switch (sqltype) {
01175 case SQL_INTEGER: m = 10; d = 9; break;
01176 case SQL_TINYINT: m = 4; d = 3; break;
01177 case SQL_SMALLINT: m = 6; d = 5; break;
01178 case SQL_FLOAT: m = 25; d = 24; break;
01179 case SQL_DOUBLE: m = 54; d = 53; break;
01180 case SQL_VARCHAR: m = 255; d = 0; break;
01181 #ifdef SQLITE_UTF8
01182 #ifdef SQL_WVARCHAR
01183 case SQL_WVARCHAR: m = 255; d = 0; break;
01184 #endif
01185 #endif
01186 #ifdef SQL_TYPE_DATE
01187 case SQL_TYPE_DATE:
01188 #endif
01189 case SQL_DATE: m = 10; d = 0; break;
01190 #ifdef SQL_TYPE_TIME
01191 case SQL_TYPE_TIME:
01192 #endif
01193 case SQL_TIME: m = 8; d = 0; break;
01194 #ifdef SQL_TYPE_TIMESTAMP
01195 case SQL_TYPE_TIMESTAMP:
01196 #endif
01197 case SQL_TIMESTAMP: m = 32; d = 0; break;
01198 #ifdef SQL_LONGVARCHAR
01199 case SQL_LONGVARCHAR : m = 65536; d = 0; break;
01200 #endif
01201 #ifdef SQLITE_UTF8
01202 #ifdef SQL_WLONGVARCHAR
01203 case SQL_WLONGVARCHAR: m = 65536; d = 0; break;
01204 #endif
01205 #endif
01206 #if HAVE_ENCDEC
01207 case SQL_VARBINARY: m = 255; d = 0; break;
01208 case SQL_LONGVARBINARY: m = 65536; d = 0; break;
01209 #endif
01210 }
01211 if (m && typename) {
01212 int mm, dd;
01213
01214 if (sscanf(typename, "%*[^(](%d)", &mm) == 1) {
01215 m = d = mm;
01216 } else if (sscanf(typename, "%*[^(](%d,%d)", &mm, &dd) == 2) {
01217 m = mm;
01218 d = dd;
01219 }
01220 }
01221 if (mp) {
01222 *mp = m;
01223 }
01224 if (dp) {
01225 *dp = d;
01226 }
01227 }
01228
01238 static int
01239 mapdeftype(int type, int stype, int nosign, int nowchar)
01240 {
01241 if (type == SQL_C_DEFAULT) {
01242 switch (stype) {
01243 case SQL_INTEGER:
01244 type = nosign > 0 ? SQL_C_ULONG : SQL_C_LONG;
01245 break;
01246 case SQL_TINYINT:
01247 type = nosign > 0 ? SQL_C_UTINYINT : SQL_C_TINYINT;
01248 break;
01249 case SQL_SMALLINT:
01250 type = nosign > 0 ? SQL_C_USHORT : SQL_C_SHORT;
01251 break;
01252 case SQL_FLOAT:
01253 type = SQL_C_FLOAT;
01254 break;
01255 case SQL_DOUBLE:
01256 type = SQL_C_DOUBLE;
01257 break;
01258 case SQL_TIMESTAMP:
01259 type = SQL_C_TIMESTAMP;
01260 break;
01261 case SQL_TIME:
01262 type = SQL_C_TIME;
01263 break;
01264 case SQL_DATE:
01265 type = SQL_C_DATE;
01266 break;
01267 #ifdef SQL_C_TYPE_TIMESTAMP
01268 case SQL_TYPE_TIMESTAMP:
01269 type = SQL_C_TYPE_TIMESTAMP;
01270 break;
01271 #endif
01272 #ifdef SQL_C_TYPE_TIME
01273 case SQL_TYPE_TIME:
01274 type = SQL_C_TYPE_TIME;
01275 break;
01276 #endif
01277 #ifdef SQL_C_TYPE_DATE
01278 case SQL_TYPE_DATE:
01279 type = SQL_C_TYPE_DATE;
01280 break;
01281 #endif
01282 #ifdef SQLITE_UTF8
01283 case SQL_WVARCHAR:
01284 case SQL_WCHAR:
01285 #ifdef SQL_WLONGVARCHAR
01286 case SQL_WLONGVARCHAR:
01287 #endif
01288 type = nowchar ? SQL_C_CHAR : SQL_C_WCHAR;
01289 break;
01290 #endif
01291 #if HAVE_ENCDEC
01292 case SQL_BINARY:
01293 case SQL_VARBINARY:
01294 case SQL_LONGVARBINARY:
01295 type = SQL_C_BINARY;
01296 break;
01297 #endif
01298 default:
01299 type = SQL_C_CHAR;
01300 }
01301 }
01302 #ifdef SQLITE_UTF8
01303 if (nowchar) {
01304 switch (type) {
01305 case SQL_C_WCHAR:
01306 type = SQL_C_CHAR;
01307 break;
01308 }
01309 }
01310 #endif
01311 return type;
01312 }
01313
01326 static char *
01327 fixupsql(char *sql, int sqlLen, int *nparam, int *isselect, char **errmsg,
01328 int version, char ***namepp)
01329 {
01330 char *q = sql, *qz = NULL, *p, *inq = NULL, *out;
01331 int np = 0, size;
01332 char **npp = NULL, *ncp = NULL;
01333
01334 *errmsg = NULL;
01335 if (sqlLen != SQL_NTS) {
01336 qz = q = xmalloc(sqlLen + 1);
01337 if (!qz) {
01338 return NULL;
01339 }
01340 memcpy(q, sql, sqlLen);
01341 q[sqlLen] = '\0';
01342 size = sqlLen * 4;
01343 } else {
01344 size = strlen(sql) * 4;
01345 }
01346 size += sizeof (char *) - 1;
01347 size &= ~(sizeof (char *) - 1);
01348 p = xmalloc(2 * size + size * sizeof (char *) / 2);
01349 if (!p) {
01350 errout:
01351 freep(&qz);
01352 return NULL;
01353 }
01354 out = p;
01355 npp = (char **) (out + size);
01356 ncp = (char *) npp + size * sizeof (char *) / 2;
01357 while (*q) {
01358 switch (*q) {
01359 case '\'':
01360 case '\"':
01361 if (q == inq) {
01362 inq = NULL;
01363 } else if (!inq) {
01364 inq = q + 1;
01365
01366 while (*inq) {
01367 if (*inq == *q) {
01368 if (inq[1] == *q) {
01369 inq++;
01370 } else {
01371 break;
01372 }
01373 }
01374 inq++;
01375 }
01376 }
01377 *p++ = *q;
01378 break;
01379 case '?':
01380 if (inq) {
01381 *p++ = *q;
01382 } else {
01383 *p++ = '%';
01384 *p++ = 'Q';
01385 npp[np] = ncp;
01386 *ncp = '\0';
01387 ++ncp;
01388 np++;
01389 }
01390 break;
01391 case ':':
01392 case '@':
01393 if (inq) {
01394 *p++ = *q;
01395 } else {
01396 int n = -1;
01397
01398 do {
01399 ++q;
01400 ++n;
01401 } while (*q && ISIDCHAR(*q));
01402 if (n > 0) {
01403 *p++ = '%';
01404 *p++ = 'Q';
01405 npp[np] = ncp;
01406 memcpy(ncp, q - n, n);
01407 ncp[n] = '\0';
01408 ncp += n + 1;
01409 np++;
01410 }
01411 --q;
01412 }
01413 break;
01414 case ';':
01415 if (inq) {
01416 *p++ = *q;
01417 } else {
01418 do {
01419 ++q;
01420 } while (*q && ISSPACE(*q));
01421 if (*q) {
01422 freep(&out);
01423 *errmsg = "only one SQL statement allowed";
01424 goto errout;
01425 }
01426 --q;
01427 }
01428 break;
01429 case '%':
01430 *p++ = '%';
01431 *p++ = '%';
01432 break;
01433 case '{':
01434
01435 if (!inq) {
01436 char *end = q + 1;
01437
01438 while (*end && *end != '}') {
01439 ++end;
01440 }
01441 if (*end == '}') {
01442 char *start = q + 1;
01443 char *end2 = end - 1;
01444
01445 while (start < end2 && *start != '\'') {
01446 ++start;
01447 }
01448 while (end2 > start && *end2 != '\'') {
01449 --end2;
01450 }
01451 if (*start == '\'' && *end2 == '\'') {
01452 while (start <= end2) {
01453 *p++ = *start;
01454 ++start;
01455 }
01456 q = end;
01457 break;
01458 }
01459 }
01460 }
01461
01462 default:
01463 *p++ = *q;
01464 }
01465 ++q;
01466 }
01467 freep(&qz);
01468 *p = '\0';
01469 if (nparam) {
01470 *nparam = np;
01471 }
01472 if (isselect) {
01473 p = out;
01474 while (*p && ISSPACE(*q)) {
01475 ++p;
01476 }
01477 *isselect = strncasecmp(p, "select", 6) == 0;
01478 }
01479 if (namepp) {
01480 *namepp = npp;
01481 }
01482 return out;
01483 }
01484
01493 static int
01494 findcol(char **cols, int ncols, char *name)
01495 {
01496 int i;
01497
01498 if (cols) {
01499 for (i = 0; i < ncols; i++) {
01500 if (strcmp(cols[i], name) == 0) {
01501 return i;
01502 }
01503 }
01504 }
01505 return -1;
01506 }
01507
01525 static void
01526 fixupdyncols(STMT *s, sqlite *sqlite, const char **types)
01527 {
01528 int i, k, pk, t, r, nrows, ncols, doautoinc = 0;
01529 char **rowp, *flagp, flags[128];
01530
01531 if (!s->dyncols) {
01532 return;
01533 }
01534
01535 if (s->dcols > 1) {
01536 char *table = s->dyncols[0].table;
01537
01538 for (i = 1; table[0] && i < s->dcols; i++) {
01539 if (strcmp(s->dyncols[i].table, table)) {
01540 break;
01541 }
01542 }
01543 if (i >= s->dcols) {
01544 for (i = 0; i < s->dcols; i++) {
01545 s->dyncols[i].label = s->dyncols[i].column;
01546 }
01547 }
01548 } else if (s->dcols == 1) {
01549 s->dyncols[0].label = s->dyncols[0].column;
01550 }
01551 if (types) {
01552 for (i = 0; i < s->dcols; i++) {
01553 freep(&s->dyncols[i].typename);
01554 s->dyncols[i].typename = xstrdup(types[i] ? types[i] : "text");
01555 s->dyncols[i].type =
01556 mapsqltype(types[i], &s->dyncols[i].nosign, *s->ov3,
01557 s->nowchar);
01558 getmd(types[i], s->dyncols[i].type, &s->dyncols[i].size, NULL);
01559 #ifdef SQL_LONGVARCHAR
01560 if (s->dyncols[i].type == SQL_VARCHAR &&
01561 s->dyncols[i].size > 255) {
01562 s->dyncols[i].type = SQL_LONGVARCHAR;
01563 }
01564 #endif
01565 #ifdef SQLITE_UTF8
01566 #ifdef SQL_WLONGVARCHAR
01567 if (s->dyncols[i].type == SQL_WVARCHAR &&
01568 s->dyncols[i].size > 255) {
01569 s->dyncols[i].type = SQL_WLONGVARCHAR;
01570 }
01571 #endif
01572 #endif
01573 #if HAVE_ENCDEC
01574 if (s->dyncols[i].type == SQL_VARBINARY &&
01575 s->dyncols[i].size > 255) {
01576 s->dyncols[i].type = SQL_LONGVARBINARY;
01577 }
01578 #endif
01579 if (types[i] && strlen(types[i]) == 7 &&
01580 strncasecmp(types[i], "integer", 7) == 0) {
01581 doautoinc++;
01582 s->dyncols[i].autoinc = -1;
01583 } else {
01584 s->dyncols[i].autoinc = 0;
01585 }
01586 }
01587 if (!doautoinc) {
01588 return;
01589 }
01590 }
01591 if (s->dcols > array_size(flags)) {
01592 flagp = xmalloc(sizeof (flags[0]) * s->dcols);
01593 if (flagp == NULL) {
01594 return;
01595 }
01596 } else {
01597 flagp = flags;
01598 }
01599 memset(flagp, 0, sizeof (flags[0]) * s->dcols);
01600 for (i = 0; i < s->dcols; i++) {
01601 s->dyncols[i].autoinc = 0;
01602 }
01603 for (i = 0; i < s->dcols; i++) {
01604 int ret, lastpk = -1, autoinccount = 0;
01605
01606 if (!s->dyncols[i].table[0]) {
01607 continue;
01608 }
01609 if (flagp[i]) {
01610 continue;
01611 }
01612 ret = sqlite_get_table_printf(sqlite,
01613 "PRAGMA table_info('%q')", &rowp,
01614 &nrows, &ncols, NULL,
01615 s->dyncols[i].table);
01616 if (ret != SQLITE_OK) {
01617 continue;
01618 }
01619 k = findcol(rowp, ncols, "name");
01620 t = findcol(rowp, ncols, "type");
01621 pk = findcol(rowp, ncols, "pk");
01622 if (k < 0 || t < 0) {
01623 goto freet;
01624 }
01625 for (r = 1; r <= nrows; r++) {
01626 int m;
01627
01628 for (m = i; m < s->dcols; m++) {
01629 if (!flagp[m] &&
01630 strcmp(s->dyncols[m].column, rowp[r * ncols + k]) == 0 &&
01631 strcmp(s->dyncols[m].table, s->dyncols[i].table) == 0) {
01632 char *typename = rowp[r * ncols + t];
01633
01634 flagp[m] = 1;
01635 freep(&s->dyncols[m].typename);
01636 s->dyncols[m].typename = xstrdup(typename);
01637 s->dyncols[m].type =
01638 mapsqltype(typename, &s->dyncols[m].nosign, *s->ov3,
01639 s->nowchar);
01640 getmd(typename, s->dyncols[m].type, &s->dyncols[m].size,
01641 NULL);
01642 #ifdef SQL_LONGVARCHAR
01643 if (s->dyncols[m].type == SQL_VARCHAR &&
01644 s->dyncols[m].size > 255) {
01645 s->dyncols[m].type = SQL_LONGVARCHAR;
01646 }
01647 #endif
01648 #ifdef SQLITE_UTF8
01649 #ifdef SQL_WLONGVARCHAR
01650 if (s->dyncols[i].type == SQL_WVARCHAR &&
01651 s->dyncols[i].size > 255) {
01652 s->dyncols[i].type = SQL_WLONGVARCHAR;
01653 }
01654 #endif
01655 #endif
01656 #if HAVE_ENCDEC
01657 if (s->dyncols[i].type == SQL_VARBINARY &&
01658 s->dyncols[i].size > 255) {
01659 s->dyncols[i].type = SQL_LONGVARBINARY;
01660 }
01661 #endif
01662 if (pk >= 0 && strcmp(rowp[r * ncols + pk], "1") == 0) {
01663 if (++autoinccount > 1) {
01664 if (lastpk >= 0) {
01665 s->dyncols[lastpk].autoinc = 0;
01666 lastpk = -1;
01667 }
01668 } else {
01669 lastpk = m;
01670 if (strlen(typename) == 7 &&
01671 strncasecmp(typename, "integer", 7) == 0) {
01672 s->dyncols[m].autoinc = 1;
01673 }
01674 }
01675 }
01676 }
01677 }
01678 }
01679 freet:
01680 sqlite_free_table(rowp);
01681 }
01682 if (flagp != flags) {
01683 freep(&flagp);
01684 }
01685 }
01686
01694 static int
01695 getmdays(int year, int month)
01696 {
01697 static const int mdays[] = {
01698 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31
01699 };
01700 int mday;
01701
01702 if (month < 1) {
01703 return 0;
01704 }
01705 mday = mdays[(month - 1) % 12];
01706 if (mday == 28 && year % 4 == 0 &&
01707 (!(year % 100 == 0) || year % 400 == 0)) {
01708 mday++;
01709 }
01710 return mday;
01711 }
01712
01723 static int
01724 str2date(char *str, DATE_STRUCT *ds)
01725 {
01726 int i, err = 0;
01727 char *p, *q;
01728
01729 ds->year = ds->month = ds->day = 0;
01730 p = str;
01731 while (*p && !ISDIGIT(*p)) {
01732 ++p;
01733 }
01734 q = p;
01735 i = 0;
01736 while (*q && !ISDIGIT(*q)) {
01737 ++i;
01738 ++q;
01739 }
01740 if (i >= 8) {
01741 char buf[8];
01742
01743 strncpy(buf, p + 0, 4); buf[4] = '\0';
01744 ds->year = strtol(buf, NULL, 10);
01745 strncpy(buf, p + 4, 2); buf[2] = '\0';
01746 ds->month = strtol(buf, NULL, 10);
01747 strncpy(buf, p + 6, 2); buf[2] = '\0';
01748 ds->day = strtol(buf, NULL, 10);
01749 goto done;
01750 }
01751 i = 0;
01752 while (i < 3) {
01753 int n;
01754
01755 q = NULL;
01756 n = strtol(p, &q, 10);
01757 if (!q || q == p) {
01758 if (*q == '\0') {
01759 if (i == 0) {
01760 err = 1;
01761 }
01762 goto done;
01763 }
01764 }
01765 if (*q == '-' || *q == '/' || *q == '\0' || i == 2) {
01766 switch (i) {
01767 case 0: ds->year = n; break;
01768 case 1: ds->month = n; break;
01769 case 2: ds->day = n; break;
01770 }
01771 ++i;
01772 if (*q) {
01773 ++q;
01774 }
01775 } else {
01776 i = 0;
01777 while (*q && !ISDIGIT(*q)) {
01778 ++q;
01779 }
01780 }
01781 p = q;
01782 }
01783 done:
01784
01785 if (err ||
01786 ds->month < 1 || ds->month > 12 ||
01787 ds->day < 1 || ds->day > getmdays(ds->year, ds->month)) {
01788 return -1;
01789 }
01790 return 0;
01791 }
01792
01803 static int
01804 str2time(char *str, TIME_STRUCT *ts)
01805 {
01806 int i, err = 0;
01807 char *p, *q;
01808
01809 ts->hour = ts->minute = ts->second = 0;
01810 p = str;
01811 while (*p && !ISDIGIT(*p)) {
01812 ++p;
01813 }
01814 q = p;
01815 i = 0;
01816 while (*q && ISDIGIT(*q)) {
01817 ++i;
01818 ++q;
01819 }
01820 if (i >= 6) {
01821 char buf[4];
01822
01823 strncpy(buf, p + 0, 2); buf[2] = '\0';
01824 ts->hour = strtol(buf, NULL, 10);
01825 strncpy(buf, p + 2, 2); buf[2] = '\0';
01826 ts->minute = strtol(buf, NULL, 10);
01827 strncpy(buf, p + 4, 2); buf[2] = '\0';
01828 ts->second = strtol(buf, NULL, 10);
01829 goto done;
01830 }
01831 i = 0;
01832 while (i < 3) {
01833 int n;
01834
01835 q = NULL;
01836 n = strtol(p, &q, 10);
01837 if (!q || q == p) {
01838 if (*q == '\0') {
01839 if (i == 0) {
01840 err = 1;
01841 }
01842 goto done;
01843 }
01844 }
01845 if (*q == ':' || *q == '\0' || i == 2) {
01846 switch (i) {
01847 case 0: ts->hour = n; break;
01848 case 1: ts->minute = n; break;
01849 case 2: ts->second = n; break;
01850 }
01851 ++i;
01852 if (*q) {
01853 ++q;
01854 }
01855 } else {
01856 i = 0;
01857 while (*q && !ISDIGIT(*q)) {
01858 ++q;
01859 }
01860 }
01861 p = q;
01862 }
01863 done:
01864
01865 if (err || ts->hour > 23 || ts->minute > 59 || ts->second > 59) {
01866 return -1;
01867 }
01868 return 0;
01869 }
01870
01886 static int
01887 str2timestamp(char *str, TIMESTAMP_STRUCT *tss)
01888 {
01889 int i, m, n, err = 0;
01890 char *p, *q, in = '\0';
01891
01892 tss->year = tss->month = tss->day = 0;
01893 tss->hour = tss->minute = tss->second = 0;
01894 tss->fraction = 0;
01895 p = str;
01896 while (*p && !ISDIGIT(*p)) {
01897 ++p;
01898 }
01899 q = p;
01900 i = 0;
01901 while (*q && ISDIGIT(*q)) {
01902 ++i;
01903 ++q;
01904 }
01905 if (i >= 14) {
01906 char buf[16];
01907
01908 strncpy(buf, p + 0, 4); buf[4] = '\0';
01909 tss->year = strtol(buf, NULL, 10);
01910 strncpy(buf, p + 4, 2); buf[2] = '\0';
01911 tss->month = strtol(buf, NULL, 10);
01912 strncpy(buf, p + 6, 2); buf[2] = '\0';
01913 tss->day = strtol(buf, NULL, 10);
01914 strncpy(buf, p + 8, 2); buf[2] = '\0';
01915 tss->hour = strtol(buf, NULL, 10);
01916 strncpy(buf, p + 10, 2); buf[2] = '\0';
01917 tss->minute = strtol(buf, NULL, 10);
01918 strncpy(buf, p + 12, 2); buf[2] = '\0';
01919 tss->second = strtol(buf, NULL, 10);
01920 if (i > 14) {
01921 m = i - 14;
01922 strncpy(buf, p + 14, m);
01923 while (m < 9) {
01924 buf[m] = '0';
01925 ++m;
01926 }
01927 buf[m] = '\0';
01928 tss->fraction = strtol(buf, NULL, 0);
01929 }
01930 m = 7;
01931 goto done;
01932 }
01933 m = i = 0;
01934 while ((m & 7) != 7) {
01935 q = NULL;
01936 n = strtol(p, &q, 10);
01937 if (!q || q == p) {
01938 if (*q == '\0') {
01939 if (m < 1) {
01940 err = 1;
01941 }
01942 goto done;
01943 }
01944 }
01945 if (in == '\0') {
01946 switch (*q) {
01947 case '-':
01948 case '/':
01949 if ((m & 1) == 0) {
01950 in = *q;
01951 i = 0;
01952 }
01953 break;
01954 case ':':
01955 if ((m & 2) == 0) {
01956 in = *q;
01957 i = 0;
01958 }
01959 break;
01960 case ' ':
01961 case '.':
01962 break;
01963 default:
01964 in = '\0';
01965 i = 0;
01966 break;
01967 }
01968 }
01969 switch (in) {
01970 case '-':
01971 case '/':
01972 switch (i) {
01973 case 0: tss->year = n; break;
01974 case 1: tss->month = n; break;
01975 case 2: tss->day = n; break;
01976 }
01977 if (++i >= 3) {
01978 i = 0;
01979 m |= 1;
01980 if (!(m & 2)) {
01981 m |= 8;
01982 }
01983 goto skip;
01984 } else {
01985 ++q;
01986 }
01987 break;
01988 case ':':
01989 switch (i) {
01990 case 0: tss->hour = n; break;
01991 case 1: tss->minute = n; break;
01992 case 2: tss->second = n; break;
01993 }
01994 if (++i >= 3) {
01995 i = 0;
01996 m |= 2;
01997 if (*q == '.') {
01998 in = '.';
01999 goto skip2;
02000 }
02001 if (*q == ' ') {
02002 if ((m & 1) == 0) {
02003 char *e = NULL;
02004
02005 strtol(q + 1, &e, 10);
02006 if (e && *e == '-') {
02007 goto skip;
02008 }
02009 }
02010 in = '.';
02011 goto skip2;
02012 }
02013 goto skip;
02014 } else {
02015 ++q;
02016 }
02017 break;
02018 case '.':
02019 if (++i >= 1) {
02020 int ndig = q - p;
02021
02022 if (p[0] == '+' || p[0] == '-') {
02023 ndig--;
02024 }
02025 while (ndig < 9) {
02026 n = n * 10;
02027 ++ndig;
02028 }
02029 tss->fraction = n;
02030 m |= 4;
02031 i = 0;
02032 }
02033 default:
02034 skip:
02035 in = '\0';
02036 skip2:
02037 while (*q && !ISDIGIT(*q)) {
02038 ++q;
02039 }
02040 }
02041 p = q;
02042 }
02043 if ((m & 7) > 1 && (m & 8)) {
02044
02045 if (p > str && ISDIGIT(*p)) {
02046 int nn, sign;
02047
02048 q = p - 1;
02049 if (*q != '+' && *q != '-') {
02050 goto done;
02051 }
02052 sign = *q == '+' ? -1 : 1;
02053 q = NULL;
02054 n = strtol(p, &q, 10);
02055 if (!q || *q++ != ':' || !ISDIGIT(*q)) {
02056 goto done;
02057 }
02058 p = q;
02059 q = NULL;
02060 nn = strtol(p, &q, 0);
02061 tss->minute += nn * sign;
02062 if ((SQLSMALLINT) tss->minute < 0) {
02063 tss->hour -= 1;
02064 tss->minute += 60;
02065 } else if (tss->minute >= 60) {
02066 tss->hour += 1;
02067 tss->minute -= 60;
02068 }
02069 tss->hour += n * sign;
02070 if ((SQLSMALLINT) tss->hour < 0) {
02071 tss->day -= 1;
02072 tss->hour += 24;
02073 } else if (tss->hour >= 24) {
02074 tss->day += 1;
02075 tss->hour -= 24;
02076 }
02077 if ((short) tss->day < 1 || tss->day >= 28) {
02078 int mday, pday, pmon;
02079
02080 mday = getmdays(tss->year, tss->month);
02081 pmon = tss->month - 1;
02082 if (pmon < 1) {
02083 pmon = 12;
02084 }
02085 pday = getmdays(tss->year, pmon);
02086 if ((SQLSMALLINT) tss->day < 1) {
02087 tss->month -= 1;
02088 tss->day = pday;
02089 } else if (tss->day > mday) {
02090 tss->month += 1;
02091 tss->day = 1;
02092 }
02093 if ((SQLSMALLINT) tss->month < 1) {
02094 tss->year -= 1;
02095 tss->month = 12;
02096 } else if (tss->month > 12) {
02097 tss->year += 1;
02098 tss->month = 1;
02099 }
02100 }
02101 }
02102 }
02103 done:
02104
02105 if (err ||
02106 tss->month < 1 || tss->month > 12 ||
02107 tss->day < 1 || tss->day > getmdays(tss->year, tss->month) ||
02108 tss->hour > 23 || tss->minute > 60 || tss->second > 60) {
02109 return -1;
02110 }
02111 return (m & 7) < 1 ? -1 : 0;
02112 }
02113
02120 static int
02121 getbool(char *string)
02122 {
02123 if (string) {
02124 return string[0] && strchr("Yy123456789Tt", string[0]) != NULL;
02125 }
02126 return 0;
02127 }
02128
02129 #if defined(HAVE_SQLITETRACE) && HAVE_SQLITETRACE
02130
02135 static void
02136 dbtrace(void *arg, const char *msg)
02137 {
02138 DBC *d = (DBC *) arg;
02139
02140 if (msg && d->trace) {
02141 int len = strlen(msg);
02142
02143 if (len > 0) {
02144 char *end = "\n";
02145
02146 if (msg[len - 1] != ';') {
02147 end = ";\n";
02148 }
02149 fprintf(d->trace, "%s%s", msg, end);
02150 fflush(d->trace);
02151 }
02152 }
02153 }
02154
02161 static void
02162 dbtracerc(DBC *d, int rc, char *err)
02163 {
02164 if (rc != SQLITE_OK && d->trace) {
02165 fprintf(d->trace, "-- SQLITE ERROR CODE %d", rc);
02166 fprintf(d->trace, err ? ": %s\n" : "\n", err);
02167 fflush(d->trace);
02168 }
02169 }
02170 #else
02171
02172 #define dbtracerc(a,b,c)
02173
02174 #endif
02175
02186 static SQLRETURN
02187 dbopen(DBC *d, char *name, char *dsn, char *sflag, char *busy)
02188 {
02189 char *errp = NULL, *endp = NULL;
02190 int tmp, busyto = 1000;
02191
02192 if (d->sqlite) {
02193 sqlite_close(d->sqlite);
02194 d->sqlite = NULL;
02195 }
02196 d->sqlite = sqlite_open(name, 0, &errp);
02197 if (d->sqlite == NULL) {
02198 connfail:
02199 setstatd(d, -1, errp ? errp : "connect failed",
02200 (*d->ov3) ? "HY000" : "S1000");
02201 if (errp) {
02202 sqlite_freemem(errp);
02203 errp = NULL;
02204 }
02205 return SQL_ERROR;
02206 }
02207 if (errp) {
02208 sqlite_freemem(errp);
02209 errp = NULL;
02210 }
02211 #if defined(HAVE_SQLITETRACE) && HAVE_SQLITETRACE
02212 if (d->trace) {
02213 sqlite_trace(d->sqlite, dbtrace, d);
02214 }
02215 #endif
02216 d->step_enable = getbool(sflag);
02217 d->curtype = d->step_enable ?
02218 SQL_CURSOR_FORWARD_ONLY : SQL_CURSOR_STATIC;
02219 tmp = strtol(busy, &endp, 0);
02220 if (endp && *endp == '\0' && endp != busy) {
02221 busyto = tmp;
02222 }
02223 if (busyto < 1 || busyto > 1000000) {
02224 busyto = 1000000;
02225 }
02226 d->timeout = busyto;
02227 if (setsqliteopts(d->sqlite, d) != SQLITE_OK) {
02228 sqlite_close(d->sqlite);
02229 d->sqlite = NULL;
02230 goto connfail;
02231 }
02232 freep(&d->dbname);
02233 d->dbname = xstrdup(name);
02234 freep(&d->dsn);
02235 d->dsn = xstrdup(dsn);
02236 return SQL_SUCCESS;
02237 }
02238
02245 static int
02246 vm_step(STMT *s)
02247 {
02248 DBC *d = (DBC *) s->dbc;
02249 char **rowd = NULL, *errp = NULL;
02250 const char **values, **cols;
02251 int i, ncols, rc;
02252
02253 if (s != d->vm_stmt || !s->vm) {
02254 setstat(s, -1, "stale statement", (*s->ov3) ? "HY000" : "S1000");
02255 return SQL_ERROR;
02256 }
02257 rc = sqlite_step(s->vm, &ncols, &values, &cols);
02258 if (rc == SQLITE_ROW || rc == SQLITE_DONE) {
02259 ++d->vm_rownum;
02260 if (d->vm_rownum == 0 && cols && ncols > 0) {
02261 int size;
02262 char *p;
02263 COL *dyncols;
02264
02265 for (i = size = 0; i < ncols; i++) {
02266 size += 3 + 3 * strlen(cols[i]);
02267 }
02268 dyncols = xmalloc(ncols * sizeof (COL) + size);
02269 if (!dyncols) {
02270 freedyncols(s);
02271 s->ncols = 0;
02272 sqlite_finalize(s->vm, NULL);
02273 s->vm = NULL;
02274 d->vm_stmt = NULL;
02275 return nomem(s);
02276 }
02277 p = (char *) (dyncols + ncols);
02278 for (i = 0; i < ncols; i++) {
02279 char *q;
02280
02281 dyncols[i].db = ((DBC *) (s->dbc))->dbname;
02282 strcpy(p, cols[i]);
02283 dyncols[i].label = p;
02284 p += strlen(p) + 1;
02285 q = strchr(cols[i], '.');
02286 if (q) {
02287 dyncols[i].table = p;
02288 strncpy(p, cols[i], q - cols[i]);
02289 p[q - cols[i]] = '\0';
02290 p += strlen(p) + 1;
02291 strcpy(p, q + 1);
02292 dyncols[i].column = p;
02293 p += strlen(p) + 1;
02294 } else {
02295 dyncols[i].table = "";
02296 strcpy(p, cols[i]);
02297 dyncols[i].column = p;
02298 p += strlen(p) + 1;
02299 }
02300 #ifdef SQL_LONGVARCHAR
02301 dyncols[i].type = SQL_LONGVARCHAR;
02302 dyncols[i].size = 65536;
02303 #else
02304 dyncols[i].type = SQL_VARCHAR;
02305 dyncols[i].size = 255;
02306 #endif
02307 dyncols[i].index = i;
02308 dyncols[i].scale = 0;
02309 dyncols[i].prec = 0;
02310 dyncols[i].nosign = 1;
02311 dyncols[i].autoinc = -1;
02312 dyncols[i].typename = NULL;
02313 }
02314 freedyncols(s);
02315 s->ncols = s->dcols = ncols;
02316 s->dyncols = s->cols = dyncols;
02317 fixupdyncols(s, d->sqlite, cols + ncols);
02318 mkbindcols(s, s->ncols);
02319 }
02320 if (!cols || ncols <= 0) {
02321 goto killvm;
02322 }
02323 if (!values) {
02324 if (rc == SQLITE_DONE) {
02325 freeresult(s, 0);
02326 s->nrows = 0;
02327 sqlite_finalize(s->vm, NULL);
02328 s->vm = NULL;
02329 d->vm_stmt = NULL;
02330 return SQL_SUCCESS;
02331 }
02332 goto killvm;
02333 }
02334 rowd = xmalloc((1 + 2 * ncols) * sizeof (char *));
02335 if (rowd) {
02336 rowd[0] = (char *) (ncols * 2);
02337 ++rowd;
02338 for (i = 0; i < ncols; i++) {
02339 rowd[i] = NULL;
02340 rowd[i + ncols] = xstrdup(values[i]);
02341 }
02342 for (i = 0; i < ncols; i++) {
02343 if (values[i] && !rowd[i + ncols]) {
02344 freerows(rowd);
02345 rowd = 0;
02346 break;
02347 }
02348 }
02349 }
02350 if (rowd) {
02351 freeresult(s, 0);
02352 s->nrows = 1;
02353 s->rows = rowd;
02354 if (rc == SQLITE_DONE) {
02355 sqlite_finalize(s->vm, NULL);
02356 s->vm = NULL;
02357 d->vm_stmt = NULL;
02358 }
02359 return SQL_SUCCESS;
02360 }
02361 }
02362 killvm:
02363 sqlite_finalize(s->vm, &errp);
02364 s->vm = NULL;
02365 d->vm_stmt = NULL;
02366 setstat(s, rc, "%s (%d)", (*s->ov3) ? "HY000" : "S1000",
02367 errp ? errp : "unknown error", rc);
02368 if (errp) {
02369 sqlite_freemem(errp);
02370 errp = NULL;
02371 }
02372 return SQL_ERROR;
02373 }
02374
02380 static void
02381 vm_end(STMT *s)
02382 {
02383 DBC *d;
02384
02385 if (!s || !s->vm) {
02386 return;
02387 }
02388 d = (DBC *) s->dbc;
02389 sqlite_finalize(s->vm, NULL);
02390 s->vm = NULL;
02391 d->vm_stmt = NULL;
02392 }
02393
02399 static void
02400 vm_end_if(STMT *s)
02401 {
02402 DBC *d = (DBC *) s->dbc;
02403
02404 if (d && d->vm_stmt == s) {
02405 vm_end(s);
02406 }
02407 }
02408
02416 static SQLRETURN
02417 vm_start(STMT *s, char **params)
02418 {
02419 DBC *d = (DBC *) s->dbc;
02420 char *errp = NULL, *sql = NULL;
02421 const char *endp;
02422 sqlite_vm *vm;
02423 int rc;
02424
02425 sql = sqlite_vmprintf(s->query, (char *) params);
02426 if (!sql) {
02427 return nomem(s);
02428 }
02429 rc = sqlite_compile(d->sqlite, sql, &endp, &vm, &errp);
02430 dbtracerc(d, rc, errp);
02431 sqlite_freemem(sql);
02432 if (rc != SQLITE_OK) {
02433 setstat(s, rc, "%s (%d)", (*s->ov3) ? "HY000" : "S1000",
02434 errp ? errp : "unknown error", rc);
02435 if (errp) {
02436 sqlite_freemem(errp);
02437 errp = NULL;
02438 }
02439 return SQL_ERROR;
02440 }
02441 s->vm = vm;
02442 d->vm_stmt = s;
02443 d->vm_rownum = -1;
02444 return SQL_SUCCESS;
02445 }
02446
02451 SQLRETURN SQL_API
02452 SQLBulkOperations(SQLHSTMT stmt, SQLSMALLINT oper)
02453 {
02454 return drvunimplstmt(stmt);
02455 }
02456
02457 #ifndef SQLITE_UTF8
02458
02462 SQLRETURN SQL_API
02463 SQLDataSources(SQLHENV env, SQLUSMALLINT dir, SQLCHAR *srvname,
02464 SQLSMALLINT buflen1, SQLSMALLINT *lenp1,
02465 SQLCHAR *desc, SQLSMALLINT buflen2, SQLSMALLINT *lenp2)
02466 {
02467 if (env == SQL_NULL_HENV) {
02468 return SQL_INVALID_HANDLE;
02469 }
02470 return SQL_ERROR;
02471 }
02472 #endif
02473
02474 #ifdef SQLITE_UTF8
02475
02479 SQLRETURN SQL_API
02480 SQLDataSourcesW(SQLHENV env, SQLUSMALLINT dir, SQLWCHAR *srvname,
02481 SQLSMALLINT buflen1, SQLSMALLINT *lenp1,
02482 SQLWCHAR *desc, SQLSMALLINT buflen2, SQLSMALLINT *lenp2)
02483 {
02484 if (env == SQL_NULL_HENV) {
02485 return SQL_INVALID_HANDLE;
02486 }
02487 return SQL_ERROR;
02488 }
02489 #endif
02490
02491 #ifndef SQLITE_UTF8
02492
02496 SQLRETURN SQL_API
02497 SQLDrivers(SQLHENV env, SQLUSMALLINT dir, SQLCHAR *drvdesc,
02498 SQLSMALLINT descmax, SQLSMALLINT *desclenp,
02499 SQLCHAR *drvattr, SQLSMALLINT attrmax, SQLSMALLINT *attrlenp)
02500 {
02501 if (env == SQL_NULL_HENV) {
02502 return SQL_INVALID_HANDLE;
02503 }
02504 return SQL_ERROR;
02505 }
02506 #endif
02507
02508 #ifdef SQLITE_UTF8
02509
02513 SQLRETURN SQL_API
02514 SQLDriversW(SQLHENV env, SQLUSMALLINT dir, SQLWCHAR *drvdesc,
02515 SQLSMALLINT descmax, SQLSMALLINT *desclenp,
02516 SQLWCHAR *drvattr, SQLSMALLINT attrmax, SQLSMALLINT *attrlenp)
02517 {
02518 if (env == SQL_NULL_HENV) {
02519 return SQL_INVALID_HANDLE;
02520 }
02521 return SQL_ERROR;
02522 }
02523 #endif
02524
02525 #ifndef SQLITE_UTF8
02526
02530 SQLRETURN SQL_API
02531 SQLBrowseConnect(SQLHDBC dbc, SQLCHAR *connin, SQLSMALLINT conninLen,
02532 SQLCHAR *connout, SQLSMALLINT connoutMax,
02533 SQLSMALLINT *connoutLen)
02534 {
02535 return drvunimpldbc(dbc);
02536 }
02537 #endif
02538
02539 #ifdef SQLITE_UTF8
02540
02544 SQLRETURN SQL_API
02545 SQLBrowseConnectW(SQLHDBC dbc, SQLWCHAR *connin, SQLSMALLINT conninLen,
02546 SQLWCHAR *connout, SQLSMALLINT connoutMax,
02547 SQLSMALLINT *connoutLen)
02548 {
02549 return drvunimpldbc(dbc);
02550 }
02551 #endif
02552
02560 static void
02561 time_func(sqlite_func *context, int argc, const char **argv)
02562 {
02563 char buf[128];
02564 int what = (int) sqlite_user_data(context);
02565 #ifdef _WIN32
02566 SYSTEMTIME st;
02567
02568 if (what & 1) {
02569 GetSystemTime(&st);
02570 } else {
02571 GetLocalTime(&st);
02572 }
02573 if (what & 4) {
02574 sprintf(buf, "%04d-%02d-%02d %02d:%02d:%02d",
02575 st.wYear, st.wMonth, st.wDay,
02576 st.wHour, st.wMinute, st.wSecond);
02577 } else if (what & 2) {
02578 sprintf(buf, "%04d-%02d-%02d", st.wYear, st.wMonth, st.wDay);
02579 } else {
02580 sprintf(buf, "%02d:%02d:%02d", st.wHour, st.wMinute, st.wSecond);
02581 }
02582 #else
02583 time_t t;
02584 struct tm tm;
02585
02586 time(&t);
02587 if (what & 1) {
02588 #ifdef HAVE_GMTIME_R
02589 gmtime_r(&t, &tm);
02590 #else
02591 tm = *gmtime(&t);
02592 #endif
02593 } else {
02594 #ifdef HAVE_LOCALTIME_R
02595 localtime_r(&t, &tm);
02596 #else
02597 tm = *localtime(&t);
02598 #endif
02599 }
02600 if (what & 4) {
02601 sprintf(buf, "%04d-%02d-%02d %02d:%02d:%02d",
02602 tm.tm_year + 1900, tm.tm_mon + 1, tm.tm_mday,
02603 tm.tm_hour, tm.tm_min, tm.tm_sec);
02604 } else if (what & 2) {
02605 sprintf(buf, "%04d-%02d-%02d",
02606 tm.tm_year + 1900, tm.tm_mon + 1, tm.tm_mday);
02607 } else {
02608 sprintf(buf, "%02d:%02d:%02d", tm.tm_hour, tm.tm_min, tm.tm_sec);
02609 }
02610 #endif
02611 sqlite_set_result_string(context, buf, -1);
02612 }
02613
02614 #if HAVE_ENCDEC
02615 static const char hexdigits[] = "0123456789ABCDEFabcdef";
02616
02624 static void
02625 hextobin_func(sqlite_func *context, int argc, const char **argv)
02626 {
02627 int i, len;
02628 char *bin, *p;
02629
02630 if (argc < 1) {
02631 return;
02632 }
02633 if (!argv[0]) {
02634 sqlite_set_result_string(context, "NULL", 4);
02635 return;
02636 }
02637 len = strlen(argv[0]) / 2;
02638 bin = xmalloc(len + 1);
02639 if (!bin) {
02640 oom:
02641 sqlite_set_result_error(context, "out of memory", -1);
02642 return;
02643 }
02644 if (len <= 0) {
02645 sqlite_set_result_string(context, bin, 0);
02646 freep(&bin);
02647 return;
02648 }
02649 for (i = 0, p = (char *) argv[0]; i < len; i++) {
02650 char *x;
02651 int v;
02652
02653 if (!*p || !(x = strchr(hexdigits, *p))) {
02654 goto converr;
02655 }
02656 v = x - hexdigits;
02657 bin[i] = (v >= 16) ? ((v - 6) << 4) : (v << 4);
02658 ++p;
02659 if (!*p || !(x = strchr(hexdigits, *p))) {
02660 converr:
02661 freep(&bin);
02662 sqlite_set_result_error(context, "conversion error", -1);
02663 return;
02664 }
02665 v = x - hexdigits;
02666 bin[i] |= (v >= 16) ? (v - 6) : v;
02667 ++p;
02668 }
02669 i = sqlite_encode_binary(bin, len, 0);
02670 p = xmalloc(i + 1);
02671 if (!p) {
02672 freep(&bin);
02673 goto oom;
02674 }
02675 i = sqlite_encode_binary(bin, len, p);
02676 sqlite_set_result_string(context, p, i);
02677 freep(&bin);
02678 freep(&p);
02679 }
02680
02688 static void
02689 bintohex_func(sqlite_func *context, int argc, const char **argv)
02690 {
02691 int i, k, len;
02692 char *bin, *p;
02693
02694 if (argc < 1) {
02695 return;
02696 }
02697 if (!argv[0]) {
02698 empty:
02699 sqlite_set_result_string(context, "", 0);
02700 return;
02701 }
02702 bin = xmalloc(strlen(argv[0]) + 1);
02703 if (!bin) {
02704 oom:
02705 sqlite_set_result_error(context, "out of memory", -1);
02706 return;
02707 }
02708 len = sqlite_decode_binary(argv[0], bin);
02709 if (len < 0) {
02710 freep(&bin);
02711 sqlite_set_result_error(context, "error decoding binary data", -1);
02712 return;
02713 }
02714 if (len == 0) {
02715 goto empty;
02716 }
02717 p = xmalloc(len * 2 + 1);
02718 if (!p) {
02719 goto oom;
02720 }
02721 for (i = 0, k = 0; i < len; i++) {
02722 p[k++] = hexdigits[(bin[i] >> 4) & 0x0f];
02723 p[k++] = hexdigits[bin[i] & 0x0f];
02724 }
02725 p[k] = '\0';
02726 sqlite_set_result_string(context, p, k);
02727 freep(&bin);
02728 freep(&p);
02729 }
02730
02738 static SQLRETURN
02739 hextobin(STMT *s, BINDPARM *p)
02740 {
02741 int i, len = strlen(p->param) / 2;
02742 char *bin = xmalloc(len + 1), *pp;
02743
02744 if (!bin) {
02745 return nomem(s);
02746 }
02747 if (len <= 0) {
02748 bin[0] = '\0';
02749 if (p->param == p->ind) {
02750 freep(&p->param);
02751 }
02752 p->param = p->ind = bin;
02753 p->len = 0;
02754 return SQL_SUCCESS;
02755 }
02756 for (i = 0, pp = (char *) p->param; i < len; i++) {
02757 char *x;
02758 int v;
02759
02760 if (!*pp || !(x = strchr(hexdigits, *pp))) {
02761 goto converr;
02762 }
02763 v = x - hexdigits;
02764 bin[i] = (v >= 16) ? ((v - 6) << 4) : (v << 4);
02765 ++pp;
02766 if (!*pp || !(x = strchr(hexdigits, *pp))) {
02767 converr:
02768 freep(&bin);
02769 setstat(s, -1, "conversion error", (*s->ov3) ? "HY000" : "S1000");
02770 return SQL_ERROR;
02771 }
02772 v = x - hexdigits;
02773 bin[i] |= (v >= 16) ? (v - 6) : v;
02774 ++pp;
02775 }
02776 i = sqlite_encode_binary(bin, len, 0);
02777 pp = xmalloc(i + 1);
02778 if (!pp) {
02779 freep(&bin);
02780 return nomem(s);
02781 }
02782 p->len = sqlite_encode_binary(bin, len, pp);
02783 if (p->param == p->ind) {
02784 freep(&p->param);
02785 }
02786 p->param = p->ind = pp;
02787 freep(&bin);
02788 return SQL_SUCCESS;
02789 }
02790 #endif
02791
02800 SQLRETURN SQL_API
02801 SQLPutData(SQLHSTMT stmt, SQLPOINTER data, SQLINTEGER len)
02802 {
02803 STMT *s;
02804 int i, dlen, done = 0;
02805 BINDPARM *p;
02806
02807 if (stmt == SQL_NULL_HSTMT) {
02808 return SQL_INVALID_HANDLE;
02809 }
02810 s = (STMT *) stmt;
02811 if (!s->query || s->nparams <= 0) {
02812 seqerr:
02813 setstat(s, -1, "sequence error", "HY010");
02814 return SQL_ERROR;
02815 }
02816 for (i = 0; i < s->nparams; i++) {
02817 p = &s->bindparms[i];
02818 if (p->need) {
02819 int type = mapdeftype(p->type, p->stype, -1, s->nowchar);
02820
02821 if (len == SQL_NULL_DATA) {
02822 freep(&p->param);
02823 p->ind = &p->len;
02824 p->len = SQL_NULL_DATA;
02825 p->need = 0;
02826 } else
02827 #if HAVE_ENCDEC
02828 if (type == SQL_C_BINARY) {
02829 if (len <= 0) {
02830 setstat(s, -1, "invalid length", "HY090");
02831 return SQL_ERROR;
02832 }
02833 goto putd;
02834 } else
02835 #endif
02836 #ifdef SQLITE_UTF8
02837 if (type != SQL_C_CHAR && type != SQL_C_WCHAR)
02838 #else
02839 if (type != SQL_C_CHAR)
02840 #endif
02841 {
02842 int size = 0;
02843
02844 switch (type) {
02845 case SQL_C_TINYINT:
02846 case SQL_C_UTINYINT:
02847 case SQL_C_STINYINT:
02848 size = sizeof (char);
02849 break;
02850 case SQL_C_SHORT:
02851 case SQL_C_USHORT:
02852 case SQL_C_SSHORT:
02853 size = sizeof (short);
02854 break;
02855 case SQL_C_LONG:
02856 case SQL_C_ULONG:
02857 case SQL_C_SLONG:
02858 size = sizeof (long);
02859 break;
02860 case SQL_C_FLOAT:
02861 size = sizeof (float);
02862 break;
02863 case SQL_C_DOUBLE:
02864 size = sizeof (double);
02865 break;
02866 #ifdef SQL_C_TYPE_DATE
02867 case SQL_C_TYPE_DATE:
02868 #endif
02869 case SQL_C_DATE:
02870 size = sizeof (DATE_STRUCT);
02871 break;
02872 #ifdef SQL_C_TYPE_DATE
02873 case SQL_C_TYPE_TIME:
02874 #endif
02875 case SQL_C_TIME:
02876 size = sizeof (TIME_STRUCT);
02877 break;
02878 #ifdef SQL_C_TYPE_DATE
02879 case SQL_C_TYPE_TIMESTAMP:
02880 #endif
02881 case SQL_C_TIMESTAMP:
02882 size = sizeof (TIMESTAMP_STRUCT);
02883 break;
02884 }
02885 freep(&p->param);
02886 p->param = xmalloc(size);
02887 if (!p->param) {
02888 return nomem(s);
02889 }
02890 memcpy(p->param, data, size);
02891 p->len = size;
02892 p->need = 0;
02893 } else if (len == SQL_NTS) {
02894 char *dp = data;
02895
02896 #ifdef SQLITE_UTF8
02897 if (p->type == SQL_C_WCHAR) {
02898 dp = uc_to_utf(data, len);
02899 if (!dp) {
02900 return nomem(s);
02901 }
02902 }
02903 #endif
02904 dlen = strlen(dp);
02905 freep(&p->param);
02906 p->param = xmalloc(dlen + 1);
02907 if (!p->param) {
02908 #ifdef SQLITE_UTF8
02909 if (dp != data) {
02910 uc_free(dp);
02911 }
02912 #endif
02913 return nomem(s);
02914 }
02915 strcpy(p->param, dp);
02916 #ifdef SQLITE_UTF8
02917 if (dp != data) {
02918 uc_free(dp);
02919 }
02920 #endif
02921 p->len = dlen;
02922 p->need = 0;
02923 } else if (len <= 0) {
02924 setstat(s, -1, "invalid length", "HY090");
02925 return SQL_ERROR;
02926 } else {
02927 #if HAVE_ENCDEC
02928 putd:
02929 #endif
02930 dlen = min(p->len - p->offs, len);
02931 if (!p->param) {
02932 setstat(s, -1, "no memory for parameter", "HY013");
02933 return SQL_ERROR;
02934 }
02935 memcpy((char *) p->param + p->offs, data, dlen);
02936 p->offs += dlen;
02937 if (p->offs >= p->len) {
02938 #ifdef SQLITE_UTF8
02939 if (p->type == SQL_C_WCHAR) {
02940 char *dp = uc_to_utf(p->param, p->len);
02941 char *np;
02942 int nlen;
02943
02944 if (!dp) {
02945 return nomem(s);
02946 }
02947 nlen = strlen(dp);
02948 np = xmalloc(nlen + 1);
02949 if (!np) {
02950 uc_free(dp);
02951 return nomem(s);
02952 }
02953 strcpy(np, dp);
02954 uc_free(dp);
02955 freep(&p->param);
02956 p->param = p->ind = np;
02957 p->len = nlen;
02958 } else {
02959 *((char *) p->param + p->len) = '\0';
02960 }
02961 #else
02962 *((char *) p->param + p->len) = '\0';
02963 #endif
02964 #if HAVE_ENCDEC
02965 if ((p->stype == SQL_BINARY ||
02966 p->stype == SQL_VARBINARY ||
02967 p->stype == SQL_LONGVARBINARY) &&
02968 #ifdef SQLITE_UTF8
02969 (type == SQL_C_CHAR || type == SQL_C_WCHAR)
02970 #else
02971 type == SQL_C_CHAR
02972 #endif
02973 ) {
02974 if (hextobin(s, p) != SQL_SUCCESS) {
02975 return SQL_ERROR;
02976 }
02977 } else if (type == SQL_C_BINARY) {
02978 int bsize;
02979 char *bin;
02980
02981 bsize = sqlite_encode_binary(p->param, p->len, 0);
02982 bin = xmalloc(bsize + 1);
02983 if (!bin) {
02984 return nomem(s);
02985 }
02986 p->len = sqlite_encode_binary(p->param, p->len, bin);
02987 freep(&p->param);
02988 p->param = p->ind = bin;
02989 }
02990 #endif
02991 p->need = 0;
02992 }
02993 }
02994 done = 1;
02995 break;
02996 }
02997 }
02998 if (!done) {
02999 goto seqerr;
03000 }
03001 for (i = 0; i < s->nparams; i++) {
03002 p = &s->bindparms[i];
03003 if (p->need) {
03004 return SQL_NEED_DATA;
03005 }
03006 }
03007 return drvexecute(stmt);
03008 }
03009
03015 static SQLRETURN
03016 freeparams(STMT *s)
03017 {
03018 if (s->bindparms) {
03019 int n;
03020
03021 for (n = 0; n < s->nbindparms; n++) {
03022 if (s->bindparms[n].ind && s->bindparms[n].param) {
03023 freep(&s->bindparms[n].param);
03024 }
03025 memset(&s->bindparms[n], 0, sizeof (BINDPARM));
03026 }
03027 }
03028 return SQL_SUCCESS;
03029 }
03030
03031
03032
03033 static SQLRETURN
03034 substparam(STMT *s, int pnum, char **out, int *size)
03035 {
03036 char buf[256];
03037 int type, len = 0;
03038 BINDPARM *p;
03039 double dval;
03040
03041 if (!s->bindparms || pnum < 0 || pnum >= s->nbindparms) {
03042 goto error;
03043 }
03044 p = &s->bindparms[pnum];
03045 type = mapdeftype(p->type, p->stype, -1, s->nowchar);
03046 if (p->need) {
03047 if (!p->param) {
03048 p->len = SQL_LEN_DATA_AT_EXEC(*p->lenp);
03049 if (p->len <= 0 && p->len != SQL_NTS && p->len != SQL_NULL_DATA) {
03050 setstat(s, -1, "invalid length", "HY009");
03051 return SQL_ERROR;
03052 }
03053 if (p->len > 0) {
03054 p->param = xmalloc(p->len + 1);
03055 if (!p->param) {
03056 return nomem(s);
03057 }
03058 }
03059 }
03060 return SQL_NEED_DATA;
03061 }
03062 if (!p->param || (p->lenp && *p->lenp == SQL_NULL_DATA)) {
03063 strcpy(buf, "NULL");
03064 goto bind;
03065 }
03066 switch (type) {
03067 case SQL_C_CHAR:
03068 #ifdef SQLITE_UTF8
03069 case SQL_C_WCHAR:
03070 #endif
03071 #if HAVE_ENCDEC
03072 case SQL_C_BINARY:
03073 #endif
03074 break;
03075 case SQL_C_UTINYINT:
03076 sprintf(buf, "%d", *((unsigned char *) p->param));
03077 goto bind;
03078 case SQL_C_TINYINT:
03079 case SQL_C_STINYINT:
03080 sprintf(buf, "%d", *((char *) p->param));
03081 goto bind;
03082 case SQL_C_USHORT:
03083 sprintf(buf, "%d", *((unsigned short *) p->param));
03084 goto bind;
03085 case SQL_C_SHORT:
03086 case SQL_C_SSHORT:
03087 sprintf(buf, "%d", *((short *) p->param));
03088 goto bind;
03089 case SQL_C_ULONG:
03090 case SQL_C_LONG:
03091 case SQL_C_SLONG:
03092 sprintf(buf, "%ld", *((long *) p->param));
03093 goto bind;
03094 case SQL_C_FLOAT:
03095 dval = *((float *) p->param);
03096 goto dodouble;
03097 case SQL_C_DOUBLE:
03098 dval = *((double *) p->param);
03099 dodouble:
03100 #if defined(HAVE_SQLITEMPRINTF) && HAVE_SQLITEMPRINTF
03101 {
03102 char *buf2 = sqlite_mprintf("%.16g", dval);
03103
03104 if (buf2) {
03105 strcpy(buf, buf2);
03106 sqlite_freemem(buf2);
03107 } else {
03108 strcpy(buf, "NULL");
03109 }
03110 }
03111 #else
03112 ln_sprintfg(buf, dval);
03113 #endif
03114 goto bind;
03115 #ifdef SQL_C_TYPE_DATE
03116 case SQL_C_TYPE_DATE:
03117 #endif
03118 case SQL_C_DATE:
03119 sprintf(buf, "%04d-%02d-%02d",
03120 ((DATE_STRUCT *) p->param)->year,
03121 ((DATE_STRUCT *) p->param)->month,
03122 ((DATE_STRUCT *) p->param)->day);
03123 goto bind;
03124 #ifdef SQL_C_TYPE_TIME
03125 case SQL_C_TYPE_TIME:
03126 #endif
03127 case SQL_C_TIME:
03128 sprintf(buf, "%02d:%02d:%02d",
03129 ((TIME_STRUCT *) p->param)->hour,
03130 ((TIME_STRUCT *) p->param)->minute,
03131 ((TIME_STRUCT *) p->param)->second);
03132 goto bind;
03133 #ifdef SQL_C_TYPE_TIMESTAMP
03134 case SQL_C_TYPE_TIMESTAMP:
03135 #endif
03136 case SQL_C_TIMESTAMP:
03137 sprintf(buf, "%04d-%02d-%02d %02d:%02d:%02d.%d",
03138 ((TIMESTAMP_STRUCT *) p->param)->year,
03139 ((TIMESTAMP_STRUCT *) p->param)->month,
03140 ((TIMESTAMP_STRUCT *) p->param)->day,
03141 ((TIMESTAMP_STRUCT *) p->param)->hour,
03142 ((TIMESTAMP_STRUCT *) p->param)->minute,
03143 ((TIMESTAMP_STRUCT *) p->param)->second,
03144 (int) ((TIMESTAMP_STRUCT *) p->param)->fraction);
03145 bind:
03146 if (out) {
03147 strcpy(*out, buf);
03148 *out += strlen(buf) + 1;
03149 }
03150 if (size) {
03151 *size += strlen(buf) + 1;
03152 }
03153 return SQL_SUCCESS;
03154 default:
03155 goto error;
03156 }
03157 if (p->ind) {
03158 len = p->len;
03159 } else if (!p->lenp) {
03160 if (!(p->max != SQL_NTS || p->max == SQL_SETPARAM_VALUE_MAX)) {
03161 error:
03162 setstat(s, -1, "invalid parameter", (*s->ov3) ? "07009" : "S1093");
03163 return SQL_ERROR;
03164 }
03165 } else {
03166 len = *p->lenp == SQL_NTS ? strlen(p->param) : *p->lenp;
03167 }
03168 if (out) {
03169 if (p->max == SQL_NTS || p->max == SQL_SETPARAM_VALUE_MAX) {
03170 strcpy(*out, p->param);
03171 *out += strlen(p->param) + 1;
03172 } else {
03173 if (len > 0) {
03174 memcpy(*out, p->param, len);
03175 *out += len;
03176 }
03177 **out = '\0';
03178 *out += 1;
03179 }
03180 }
03181 if (size) {
03182 if (p->max == SQL_NTS || p->max == SQL_SETPARAM_VALUE_MAX) {
03183 *size += strlen(p->param) + 1;
03184 } else {
03185 *size += len > 0 ? len + 1 : 1;
03186 }
03187 }
03188 return SQL_SUCCESS;
03189 }
03190
03206 static SQLRETURN
03207 drvbindparam(SQLHSTMT stmt, SQLUSMALLINT pnum, SQLSMALLINT iotype,
03208 SQLSMALLINT buftype, SQLSMALLINT ptype, SQLUINTEGER coldef,
03209 SQLSMALLINT scale,
03210 SQLPOINTER data, SQLINTEGER buflen, SQLINTEGER *len)
03211 {
03212 STMT *s;
03213 BINDPARM *p;
03214
03215 if (stmt == SQL_NULL_HSTMT) {
03216 return SQL_INVALID_HANDLE;
03217 }
03218 s = (STMT *) stmt;
03219 if (pnum == 0) {
03220 setstat(s, -1, "invalid parameter", (*s->ov3) ? "07009" : "S1093");
03221 return SQL_ERROR;
03222 }
03223 if (!data && (!len || (*len != SQL_NULL_DATA &&
03224 *len > SQL_LEN_DATA_AT_EXEC_OFFSET))) {
03225 setstat(s, -1, "invalid buffer", "HY003");
03226 return SQL_ERROR;
03227 }
03228 if (len && *len < 0 && *len > SQL_LEN_DATA_AT_EXEC_OFFSET &&
03229 *len != SQL_NTS && *len != SQL_NULL_DATA) {
03230 setstat(s, -1, "invalid length reference", "HY009");
03231 return SQL_ERROR;
03232 }
03233 #if 0
03234 if (iotype != SQL_PARAM_INPUT)
03235 return SQL_ERROR;
03236 #endif
03237 --pnum;
03238 if (s->bindparms) {
03239 if (pnum >= s->nbindparms) {
03240 BINDPARM *newparms;
03241
03242 newparms = xrealloc(s->bindparms,
03243 (pnum + 1) * sizeof (BINDPARM));
03244 if (!newparms) {
03245 outofmem:
03246 return nomem(s);
03247 }
03248 s->bindparms = newparms;
03249 memset(&s->bindparms[s->nbindparms], 0,
03250 (pnum - s->nbindparms) * sizeof (BINDPARM));
03251 s->nbindparms = pnum + 1;
03252 }
03253 } else {
03254 int npar = max(10, pnum + 1);
03255
03256 s->bindparms = xmalloc(npar * sizeof (BINDPARM));
03257 if (!s->bindparms) {
03258 goto outofmem;
03259 }
03260 memset(s->bindparms, 0, npar * sizeof (BINDPARM));
03261 s->nbindparms = npar;
03262 }
03263 p = &s->bindparms[pnum];
03264 p->type = buftype;
03265 p->stype = ptype;
03266 p->max = buflen;
03267 p->inc = buflen;
03268 p->lenp = (int *) len;
03269 p->offs = 0;
03270 p->len = 0;
03271 if (p->lenp) {
03272 #ifdef SQLITE_UTF8
03273 if (buftype == SQL_C_WCHAR) {
03274 if (*p->lenp == SQL_NTS) {
03275 p->max = buflen = uc_strlen(data);
03276 } else if (*p->lenp >= 0) {
03277 p->max = buflen = *p->lenp;
03278 }
03279 } else
03280 #endif
03281 if (buftype == SQL_C_CHAR) {
03282 if (*p->lenp == SQL_NTS) {
03283 p->len = p->max = buflen = strlen(data);
03284 } else if (*p->lenp >= 0) {
03285 p->len = p->max = buflen = *p->lenp;
03286 }
03287 }
03288 }
03289 if (p->lenp && *p->lenp <= SQL_LEN_DATA_AT_EXEC_OFFSET) {
03290 p->param = NULL;
03291 p->ind = data;
03292 p->need = 1;
03293 } else if (p->lenp && *p->lenp == SQL_NULL_DATA) {
03294 p->param = NULL;
03295 p->ind = NULL;
03296 p->need = 0;
03297 } else {
03298 #if HAVE_ENCDEC
03299 int chkbin = 1;
03300 #endif
03301
03302 #ifdef SQLITE_UTF8
03303 if (buftype == SQL_C_WCHAR) {
03304 p->ind = uc_to_utf(data, buflen);
03305 if (!p->ind) {
03306 goto outofmem;
03307 }
03308 p->param = p->ind;
03309 p->len = strlen(p->param);
03310 } else
03311 #endif
03312 #if HAVE_ENCDEC
03313 if (buftype == SQL_C_BINARY) {
03314 int bsize;
03315
03316 p->len = *p->lenp;
03317 if (p->len < 0) {
03318 setstat(s, -1, "invalid length reference", "HY009");
03319 return SQL_ERROR;
03320 }
03321 bsize = sqlite_encode_binary(data, p->len, 0);
03322 p->ind = xmalloc(bsize + 1);
03323 if (!p->ind) {
03324 goto outofmem;
03325 }
03326 p->param = p->ind;
03327 p->len = sqlite_encode_binary(data, p->len, p->param);
03328 chkbin = 0;
03329 } else
03330 #endif
03331 if (buftype == SQL_C_CHAR) {
03332 p->param = data;
03333 p->ind = NULL;
03334 } else {
03335 p->param = data;
03336 p->ind = NULL;
03337 #if HAVE_ENCDEC
03338 chkbin = 0;
03339 #endif
03340 }
03341 #if HAVE_ENCDEC
03342 if (chkbin) {
03343 if (ptype == SQL_BINARY ||
03344 ptype == SQL_VARBINARY ||
03345 ptype == SQL_LONGVARBINARY) {
03346 if (hextobin(s, p) != SQL_SUCCESS) {
03347 return SQL_ERROR;
03348 }
03349 }
03350 }
03351 #endif
03352 p->need = 0;
03353 }
03354 p->param0 = p->param;
03355 return SQL_SUCCESS;
03356 }
03357
03373 SQLRETURN SQL_API
03374 SQLBindParameter(SQLHSTMT stmt, SQLUSMALLINT pnum, SQLSMALLINT iotype,
03375 SQLSMALLINT buftype, SQLSMALLINT ptype, SQLUINTEGER coldef,
03376 SQLSMALLINT scale,
03377 SQLPOINTER data, SQLINTEGER buflen, SQLINTEGER *len)
03378 {
03379 return drvbindparam(stmt, pnum, iotype, buftype, ptype, coldef,
03380 scale, data, buflen, len);
03381 }
03382
03396 SQLRETURN SQL_API
03397 SQLBindParam(SQLHSTMT stmt, SQLUSMALLINT pnum, SQLSMALLINT vtype,
03398 SQLSMALLINT ptype, SQLUINTEGER lenprec,
03399 SQLSMALLINT scale, SQLPOINTER val,
03400 SQLINTEGER *lenp)
03401 {
03402 return drvbindparam(stmt, pnum, SQL_PARAM_INPUT, vtype, ptype,
03403 lenprec, scale, val, 0, lenp);
03404 }
03405
03413 SQLRETURN SQL_API
03414 SQLNumParams(SQLHSTMT stmt, SQLSMALLINT *nparam)
03415 {
03416 STMT *s;
03417 SQLSMALLINT dummy;
03418
03419 if (stmt == SQL_NULL_HSTMT) {
03420 return SQL_INVALID_HANDLE;
03421 }
03422 s = (STMT *) stmt;
03423 if (!nparam) {
03424 nparam = &dummy;
03425 }
03426 *nparam = s->nparams;
03427 return SQL_SUCCESS;
03428 }
03429
03437 SQLRETURN SQL_API
03438 SQLParamData(SQLHSTMT stmt, SQLPOINTER *p)
03439 {
03440 STMT *s;
03441 int i;
03442 SQLPOINTER dummy;
03443
03444 if (stmt == SQL_NULL_HSTMT) {
03445 return SQL_INVALID_HANDLE;
03446 }
03447 s = (STMT *) stmt;
03448 if (!p) {
03449 p = &dummy;
03450 }
03451 for (i = 0; i < s->nparams; i++) {
03452 if (s->bindparms[i].need) {
03453 *p = (SQLPOINTER) s->bindparms[i].ind;
03454 return SQL_NEED_DATA;
03455 }
03456 }
03457 return SQL_SUCCESS;
03458 }
03459
03471 SQLRETURN SQL_API
03472 SQLDescribeParam(SQLHSTMT stmt, UWORD pnum, SWORD *dtype, UDWORD *size,
03473 SWORD *decdigits, SWORD *nullable)
03474 {
03475 STMT *s;
03476
03477 if (stmt == SQL_NULL_HSTMT) {
03478 return SQL_INVALID_HANDLE;
03479 }
03480 s = (STMT *) stmt;
03481 --pnum;
03482 if (pnum >= s->nparams) {
03483 setstat(s, -1, "invalid parameter index",
03484 (*s->ov3) ? "HY000" : "S1000");
03485 return SQL_ERROR;
03486 }
03487 if (dtype) {
03488 #ifdef SQL_LONGVARCHAR
03489 #ifdef SQLITE_UTF8
03490 *dtype = s->nowchar ? SQL_LONGVARCHAR : SQL_WLONGVARCHAR;
03491 #else
03492 *dtype = SQL_LONGVARCHAR;
03493 #endif
03494 #else
03495 #ifdef SQLITE_UTF8
03496 *dtype = s->nowchar ? SQL_VARCHAR : SQL_WVARCHAR;
03497 #else
03498 *dtype = SQL_VARCHAR;
03499 #endif
03500 #endif
03501 }
03502 if (size) {
03503 #ifdef SQL_LONGVARCHAR
03504 *size = 65536;
03505 #else
03506 *size = 255;
03507 #endif
03508 }
03509 if (decdigits) {
03510 *decdigits = 0;
03511 }
03512 if (nullable) {
03513 *nullable = SQL_NULLABLE;
03514 }
03515 return SQL_SUCCESS;
03516 }
03517
03531 SQLRETURN SQL_API
03532 SQLSetParam(SQLHSTMT stmt, SQLUSMALLINT par, SQLSMALLINT type,
03533 SQLSMALLINT sqltype, SQLUINTEGER coldef,
03534 SQLSMALLINT scale, SQLPOINTER val, SQLINTEGER *nval)
03535 {
03536 return drvbindparam(stmt, par, SQL_PARAM_INPUT,
03537 type, sqltype, coldef, scale, val,
03538 SQL_SETPARAM_VALUE_MAX, nval);
03539 }
03540
03545 SQLRETURN SQL_API
03546 SQLParamOptions(SQLHSTMT stmt, UDWORD rows, UDWORD *rowp)
03547 {
03548 return drvunimplstmt(stmt);
03549 }
03550
03551 #ifndef SQLITE_UTF8
03552
03556 SQLRETURN SQL_API
03557 SQLGetDescField(SQLHDESC handle, SQLSMALLINT recno,
03558 SQLSMALLINT fieldid, SQLPOINTER value,
03559 SQLINTEGER buflen, SQLINTEGER *strlen)
03560 {
03561 return SQL_ERROR;
03562 }
03563 #endif
03564
03565 #ifdef SQLITE_UTF8
03566
03570 SQLRETURN SQL_API
03571 SQLGetDescFieldW(SQLHDESC handle, SQLSMALLINT recno,
03572 SQLSMALLINT fieldid, SQLPOINTER value,
03573 SQLINTEGER buflen, SQLINTEGER *strlen)
03574 {
03575 return SQL_ERROR;
03576 }
03577 #endif
03578
03579 #ifndef SQLITE_UTF8
03580
03584 SQLRETURN SQL_API
03585 SQLSetDescField(SQLHDESC handle, SQLSMALLINT recno,
03586 SQLSMALLINT fieldid, SQLPOINTER value,
03587 SQLINTEGER buflen)
03588 {
03589 return SQL_ERROR;
03590 }
03591 #endif
03592
03593 #ifdef SQLITE_UTF8
03594
03598 SQLRETURN SQL_API
03599 SQLSetDescFieldW(SQLHDESC handle, SQLSMALLINT recno,
03600 SQLSMALLINT fieldid, SQLPOINTER value,
03601 SQLINTEGER buflen)
03602 {
03603 return SQL_ERROR;
03604 }
03605 #endif
03606
03607 #ifndef SQLITE_UTF8
03608
03612 SQLRETURN SQL_API
03613 SQLGetDescRec(SQLHDESC handle, SQLSMALLINT recno,
03614 SQLCHAR *name, SQLSMALLINT buflen,
03615 SQLSMALLINT *strlen, SQLSMALLINT *type,
03616 SQLSMALLINT *subtype, SQLINTEGER *len,
03617 SQLSMALLINT *prec, SQLSMALLINT *scale,
03618 SQLSMALLINT *nullable)
03619 {
03620 return SQL_ERROR;
03621 }
03622 #endif
03623
03624 #ifdef SQLITE_UTF8
03625
03629 SQLRETURN SQL_API
03630 SQLGetDescRecW(SQLHDESC handle, SQLSMALLINT recno,
03631 SQLWCHAR *name, SQLSMALLINT buflen,
03632 SQLSMALLINT *strlen, SQLSMALLINT *type,
03633 SQLSMALLINT *subtype, SQLINTEGER *len,
03634 SQLSMALLINT *prec, SQLSMALLINT *scale,
03635 SQLSMALLINT *nullable)
03636 {
03637 return SQL_ERROR;
03638 }
03639 #endif
03640
03645 SQLRETURN SQL_API
03646 SQLSetDescRec(SQLHDESC handle, SQLSMALLINT recno,
03647 SQLSMALLINT type, SQLSMALLINT subtype,
03648 SQLINTEGER len, SQLSMALLINT prec,
03649 SQLSMALLINT scale, SQLPOINTER data,
03650 SQLINTEGER *strlen, SQLINTEGER *indicator)
03651 {
03652 return SQL_ERROR;
03653 }
03654
03663 static SQLRETURN
03664 mkresultset(HSTMT stmt, COL *colspec, int ncols)
03665 {
03666 STMT *s;
03667 DBC *d;
03668
03669 if (stmt == SQL_NULL_HSTMT) {
03670 return SQL_INVALID_HANDLE;
03671 }
03672 s = (STMT *) stmt;
03673 if (s->dbc == SQL_NULL_HDBC) {
03674 noconn:
03675 return noconn(s);
03676 }
03677 d = (DBC *) s->dbc;
03678 if (!d->sqlite) {
03679 goto noconn;
03680 }
03681 vm_end_if(s);
03682 freeresult(s, 0);
03683 s->ncols = ncols;
03684 s->cols = colspec;
03685 mkbindcols(s, s->ncols);
03686 s->nrows = 0;
03687 s->rowp = -1;
03688 return SQL_SUCCESS;
03689 }
03690
03695 static COL tablePrivSpec[] = {
03696 { "SYSTEM", "TABLEPRIV", "TABLE_QUALIFIER", SCOL_VARCHAR, 50 },
03697 { "SYSTEM", "TABLEPRIV", "TABLE_OWNER", SCOL_VARCHAR, 50 },
03698 { "SYSTEM", "TABLEPRIV", "TABLE_NAME", SCOL_VARCHAR, 255 },
03699 { "SYSTEM", "TABLEPRIV", "GRANTOR", SCOL_VARCHAR, 50 },
03700 { "SYSTEM", "TABLEPRIV", "GRANTEE", SCOL_VARCHAR, 50 },
03701 { "SYSTEM", "TABLEPRIV", "PRIVILEGE", SCOL_VARCHAR, 50 },
03702 { "SYSTEM", "TABLEPRIV", "IS_GRANTABLE", SCOL_VARCHAR, 50 }
03703 };
03704
03705 #ifndef SQLITE_UTF8
03706
03718 SQLRETURN SQL_API
03719 SQLTablePrivileges(SQLHSTMT stmt,
03720 SQLCHAR *catalog, SQLSMALLINT catalogLen,
03721 SQLCHAR *schema, SQLSMALLINT schemaLen,
03722 SQLCHAR *table, SQLSMALLINT tableLen)
03723 {
03724 return mkresultset(stmt, tablePrivSpec, array_size(tablePrivSpec));
03725 }
03726 #endif
03727
03728 #if !defined(HAVE_UNIXODBC) || !HAVE_UNIXODBC
03729 #ifdef SQLITE_UTF8
03730
03742 SQLRETURN SQL_API
03743 SQLTablePrivilegesW(SQLHSTMT stmt,
03744 SQLWCHAR *catalog, SQLSMALLINT catalogLen,
03745 SQLWCHAR *schema, SQLSMALLINT schemaLen,
03746 SQLWCHAR *table, SQLSMALLINT tableLen)
03747 {
03748 return mkresultset(stmt, tablePrivSpec, array_size(tablePrivSpec));
03749 }
03750 #endif
03751 #endif
03752
03757 static COL colPrivSpec[] = {
03758 { "SYSTEM", "COLPRIV", "TABLE_QUALIFIER", SCOL_VARCHAR, 50 },
03759 { "SYSTEM", "COLPRIV", "TABLE_OWNER", SCOL_VARCHAR, 50 },
03760 { "SYSTEM", "COLPRIV", "TABLE_NAME", SCOL_VARCHAR, 255 },
03761 { "SYSTEM", "COLPRIV", "GRANTOR", SCOL_VARCHAR, 50 },
03762 { "SYSTEM", "COLPRIV", "GRANTEE", SCOL_VARCHAR, 50 },
03763 { "SYSTEM", "COLPRIV", "PRIVILEGE", SCOL_VARCHAR, 50 },
03764 { "SYSTEM", "COLPRIV", "IS_GRANTABLE", SCOL_VARCHAR, 50 }
03765 };
03766
03767 #ifndef SQLITE_UTF8
03768
03782 SQLRETURN SQL_API
03783 SQLColumnPrivileges(SQLHSTMT stmt,
03784 SQLCHAR *catalog, SQLSMALLINT catalogLen,
03785 SQLCHAR *schema, SQLSMALLINT schemaLen,
03786 SQLCHAR *table, SQLSMALLINT tableLen,
03787 SQLCHAR *column, SQLSMALLINT columnLen)
03788 {
03789 return mkresultset(stmt, colPrivSpec, array_size(colPrivSpec));
03790 }
03791 #endif
03792
03793 #if !defined(HAVE_UNIXODBC) || !HAVE_UNIXODBC
03794 #ifdef SQLITE_UTF8
03795
03809 SQLRETURN SQL_API
03810 SQLColumnPrivilegesW(SQLHSTMT stmt,
03811 SQLWCHAR *catalog, SQLSMALLINT catalogLen,
03812 SQLWCHAR *schema, SQLSMALLINT schemaLen,
03813 SQLWCHAR *table, SQLSMALLINT tableLen,
03814 SQLWCHAR *column, SQLSMALLINT columnLen)
03815 {
03816 return mkresultset(stmt, colPrivSpec, array_size(colPrivSpec));
03817 }
03818 #endif
03819 #endif
03820
03825 static COL pkeySpec[] = {
03826 { "SYSTEM", "PRIMARYKEY", "TABLE_QUALIFIER", SCOL_VARCHAR, 50 },
03827 { "SYSTEM", "PRIMARYKEY", "TABLE_OWNER", SCOL_VARCHAR, 50 },
03828 { "SYSTEM", "PRIMARYKEY", "TABLE_NAME", SCOL_VARCHAR, 255 },
03829 { "SYSTEM", "PRIMARYKEY", "COLUMN_NAME", SCOL_VARCHAR, 255 },
03830 { "SYSTEM", "PRIMARYKEY", "KEY_SEQ", SQL_SMALLINT, 50 },
03831 { "SYSTEM", "PRIMARYKEY", "PK_NAME", SCOL_VARCHAR, 50 }
03832 };
03833
03846 static SQLRETURN
03847 drvprimarykeys(SQLHSTMT stmt,
03848 SQLCHAR *cat, SQLSMALLINT catLen,
03849 SQLCHAR *schema, SQLSMALLINT schemaLen,
03850 SQLCHAR *table, SQLSMALLINT tableLen)
03851 {
03852 STMT *s;
03853 DBC *d;
03854 SQLRETURN sret;
03855 int i, size, ret, nrows, ncols, offs, namec, uniquec;
03856 char **rowp, *errp = NULL, tname[512];
03857
03858 sret = mkresultset(stmt, pkeySpec, array_size(pkeySpec));
03859 if (sret != SQL_SUCCESS) {
03860 return sret;
03861 }
03862 s = (STMT *) stmt;
03863 d = (DBC *) s->dbc;
03864 if (!table || table[0] == '\0' || table[0] == '%') {
03865 setstat(s, -1, "need table name", (*s->ov3) ? "HY000" : "S1000");
03866 return SQL_ERROR;
03867 }
03868 if (tableLen == SQL_NTS) {
03869 size = sizeof (tname) - 1;
03870 } else {
03871 size = min(sizeof (tname) - 1, tableLen);
03872 }
03873 strncpy(tname, table, size);
03874 tname[size] = '\0';
03875 ret = sqlite_get_table_printf(d->sqlite,
03876 "PRAGMA index_list('%q')", &rowp,
03877 &nrows, &ncols, &errp, tname);
03878 if (ret != SQLITE_OK) {
03879 setstat(s, ret, "%s (%d)", (*s->ov3) ? "HY000" : "S1000",
03880 errp ? errp : "unknown error", ret);
03881 if (errp) {
03882 sqlite_freemem(errp);
03883 errp = NULL;
03884 }
03885 return SQL_ERROR;
03886 }
03887 if (errp) {
03888 sqlite_freemem(errp);
03889 errp = NULL;
03890 }
03891 if (ncols * nrows <= 0) {
03892 nodata:
03893 sqlite_free_table(rowp);
03894
03895 ret = sqlite_get_table_printf(d->sqlite,
03896 "PRAGMA table_info('%q')", &rowp,
03897 &nrows, &ncols, NULL, tname);
03898 if (ret == SQLITE_OK) {
03899 int typec, roffs;
03900
03901 namec = findcol(rowp, ncols, "name");
03902 uniquec = findcol(rowp, ncols, "pk");
03903 typec = findcol(rowp, ncols, "type");
03904 if (namec < 0 || uniquec < 0 || typec < 0) {
03905 goto nodata2;
03906 }
03907 for (i = 1; i <= nrows; i++) {
03908 if (*rowp[i * ncols + uniquec] != '0' &&
03909 strlen(rowp[i * ncols + typec]) == 7 &&
03910 strncasecmp(rowp[i * ncols + typec], "integer", 7) == 0) {
03911 break;
03912 }
03913 }
03914 if (i > nrows) {
03915 goto nodata2;
03916 }
03917 size = (1 + 1) * array_size(pkeySpec);
03918 s->rows = xmalloc((size + 1) * sizeof (char *));
03919 if (!s->rows) {
03920 s->nrows = 0;
03921 return nomem(s);
03922 }
03923 s->rows[0] = (char *) size;
03924 s->rows += 1;
03925 memset(s->rows, 0, sizeof (char *) * size);
03926 s->rowfree = freerows;
03927 s->nrows = 1;
03928 roffs = s->ncols;
03929 s->rows[roffs + 0] = xstrdup("");
03930 s->rows[roffs + 1] = xstrdup("");
03931 s->rows[roffs + 2] = xstrdup(tname);
03932 s->rows[roffs + 3] = xstrdup(rowp[i * ncols + namec]);
03933 s->rows[roffs + 4] = xstrdup("1");
03934 nodata2:
03935 sqlite_free_table(rowp);
03936 }
03937 return SQL_SUCCESS;
03938 }
03939 size = 0;
03940 namec = findcol(rowp, ncols, "name");
03941 uniquec = findcol(rowp, ncols, "unique");
03942 if (namec < 0 || uniquec < 0) {
03943 goto nodata;
03944 }
03945 for (i = 1; i <= nrows; i++) {
03946 int nnrows, nncols;
03947 char **rowpp;
03948
03949 if (*rowp[i * ncols + uniquec] != '0') {
03950 ret = sqlite_get_table_printf(d->sqlite,
03951 "PRAGMA index_info('%q')", &rowpp,
03952 &nnrows, &nncols, NULL,
03953 rowp[i * ncols + namec]);
03954 if (ret == SQLITE_OK) {
03955 size += nnrows;
03956 sqlite_free_table(rowpp);
03957 }
03958 }
03959 }
03960 if (size == 0) {
03961 goto nodata;
03962 }
03963 s->nrows = size;
03964 size = (size + 1) * array_size(pkeySpec);
03965 s->rows = xmalloc((size + 1) * sizeof (char *));
03966 if (!s->rows) {
03967 s->nrows = 0;
03968 return nomem(s);
03969 }
03970 s->rows[0] = (char *) size;
03971 s->rows += 1;
03972 memset(s->rows, 0, sizeof (char *) * size);
03973 s->rowfree = freerows;
03974 offs = 0;
03975 for (i = 1; i <= nrows; i++) {
03976 int nnrows, nncols;
03977 char **rowpp;
03978
03979 if (*rowp[i * ncols + uniquec] != '0') {
03980 int k;
03981
03982 ret = sqlite_get_table_printf(d->sqlite,
03983 "PRAGMA index_info('%q')", &rowpp,
03984 &nnrows, &nncols, NULL,
03985 rowp[i * ncols + namec]);
03986 if (ret != SQLITE_OK) {
03987 continue;
03988 }
03989 for (k = 0; nnrows && k < nncols; k++) {
03990 if (strcmp(rowpp[k], "name") == 0) {
03991 int m;
03992
03993 for (m = 1; m <= nnrows; m++) {
03994 int roffs = (offs + m) * s->ncols;
03995
03996 s->rows[roffs + 0] = xstrdup("");
03997 s->rows[roffs + 1] = xstrdup("");
03998 s->rows[roffs + 2] = xstrdup(tname);
03999 s->rows[roffs + 3] = xstrdup(rowpp[m * nncols + k]);
04000 s->rows[roffs + 5] = xstrdup(rowp[i * ncols + namec]);
04001 }
04002 } else if (strcmp(rowpp[k], "seqno") == 0) {
04003 int m;
04004
04005 for (m = 1; m <= nnrows; m++) {
04006 int roffs = (offs + m) * s->ncols;
04007 int pos = m - 1;
04008 char buf[32];
04009
04010 sscanf(rowpp[m * nncols + k], "%d", &pos);
04011 sprintf(buf, "%d", pos + 1);
04012 s->rows[roffs + 4] = xstrdup(buf);
04013 }
04014 }
04015 }
04016 offs += nnrows;
04017 sqlite_free_table(rowpp);
04018 }
04019 }
04020 sqlite_free_table(rowp);
04021 return SQL_SUCCESS;
04022 }
04023
04024 #ifndef SQLITE_UTF8
04025
04037 SQLRETURN SQL_API
04038 SQLPrimaryKeys(SQLHSTMT stmt,
04039 SQLCHAR *cat, SQLSMALLINT catLen,
04040 SQLCHAR *schema, SQLSMALLINT schemaLen,
04041 SQLCHAR *table, SQLSMALLINT tableLen)
04042 {
04043 return drvprimarykeys(stmt, cat, catLen, schema, schemaLen,
04044 table, tableLen);
04045 }
04046 #endif
04047
04048 #ifdef SQLITE_UTF8
04049
04061 SQLRETURN SQL_API
04062 SQLPrimaryKeysW(SQLHSTMT stmt,
04063 SQLWCHAR *cat, SQLSMALLINT catLen,
04064 SQLWCHAR *schema, SQLSMALLINT schemaLen,
04065 SQLWCHAR *table, SQLSMALLINT tableLen)
04066 {
04067 char *c = NULL, *s = NULL, *t = NULL;
04068 SQLRETURN ret;
04069
04070 if (cat) {
04071 c = uc_to_utf_c(cat, catLen);
04072 if (!c) {
04073 ret = nomem((STMT *) stmt);
04074 goto done;
04075 }
04076 }
04077 if (schema) {
04078 s = uc_to_utf_c(schema, schemaLen);
04079 if (!s) {
04080 ret = nomem((STMT *) stmt);
04081 goto done;
04082 }
04083 }
04084 if (table) {
04085 t = uc_to_utf_c(table, tableLen);
04086 if (!t) {
04087 ret = nomem((STMT *) stmt);
04088 goto done;
04089 }
04090 }
04091 ret = drvprimarykeys(stmt, c, SQL_NTS, s, SQL_NTS, t, SQL_NTS);
04092 done:
04093 uc_free(t);
04094 uc_free(s);
04095 uc_free(c);
04096 return ret;
04097 }
04098 #endif
04099
04104 static COL scolSpec[] = {
04105 { "SYSTEM", "COLUMN", "SCOPE", SQL_SMALLINT, 1 },
04106 { "SYSTEM", "COLUMN", "COLUMN_NAME", SCOL_VARCHAR, 255 },
04107 { "SYSTEM", "COLUMN", "DATA_TYPE", SQL_SMALLINT, 50 },
04108 { "SYSTEM", "COLUMN", "TYPE_NAME", SCOL_VARCHAR, 50 },
04109 { "SYSTEM", "COLUMN", "PRECISION", SQL_INTEGER, 50 },
04110 { "SYSTEM", "COLUMN", "LENGTH", SQL_INTEGER, 50 },
04111 { "SYSTEM", "COLUMN", "DECIMAL_DIGITS", SQL_INTEGER, 50 },
04112 { "SYSTEM", "COLUMN", "PSEUDO_COLUMN", SQL_SMALLINT, 1 },
04113 { "SYSTEM", "COLUMN", "NULLABLE", SQL_SMALLINT, 1 }
04114 };
04115
04131 static SQLRETURN
04132 drvspecialcolumns(SQLHSTMT stmt, SQLUSMALLINT id,
04133 SQLCHAR *cat, SQLSMALLINT catLen,
04134 SQLCHAR *schema, SQLSMALLINT schemaLen,
04135 SQLCHAR *table, SQLSMALLINT tableLen,
04136 SQLUSMALLINT scope, SQLUSMALLINT nullable)
04137 {
04138 STMT *s;
04139 DBC *d;
04140 SQLRETURN sret;
04141 int i, size, ret, nrows, ncols, nnnrows, nnncols, offs;
04142 int namec = -1, uniquec = -1, namecc = -1, typecc = -1;
04143 int notnullcc = -1, mkrowid = 0;
04144 char *errp = NULL, tname[512];
04145 char **rowp = NULL, **rowppp = NULL;
04146
04147 sret = mkresultset(stmt, scolSpec, array_size(scolSpec));
04148 if (sret != SQL_SUCCESS) {
04149 return sret;
04150 }
04151 s = (STMT *) stmt;
04152 d = (DBC *) s->dbc;
04153 if (!table || table[0] == '\0' || table[0] == '%') {
04154 setstat(s, -1, "need table name", (*s->ov3) ? "HY000" : "S1000");
04155 return SQL_ERROR;
04156 }
04157 if (tableLen == SQL_NTS) {
04158 size = sizeof (tname) - 1;
04159 } else {
04160 size = min(sizeof (tname) - 1, tableLen);
04161 }
04162 strncpy(tname, table, size);
04163 tname[size] = '\0';
04164 if (id != SQL_BEST_ROWID) {
04165 return SQL_SUCCESS;
04166 }
04167 ret = sqlite_get_table_printf(d->sqlite, "PRAGMA index_list('%q')",
04168 &rowp, &nrows, &ncols, &errp, tname);
04169 if (ret != SQLITE_OK) {
04170 doerr:
04171 setstat(s, ret, "%s (%d)", (*s->ov3) ? "HY000" : "S1000",
04172 errp ? errp : "unknown error", ret);
04173 if (errp) {
04174 sqlite_freemem(errp);
04175 errp = NULL;
04176 }
04177 return SQL_ERROR;
04178 }
04179 if (errp) {
04180 sqlite_freemem(errp);
04181 errp = NULL;
04182 }
04183 size = 0;
04184 if (ncols * nrows <= 0) {
04185 goto nodata_but_rowid;
04186 }
04187 ret = sqlite_get_table_printf(d->sqlite, "PRAGMA table_info('%q')",
04188 &rowppp, &nnnrows, &nnncols, &errp, tname);
04189 if (ret != SQLITE_OK) {
04190 sqlite_free_table(rowp);
04191 goto doerr;
04192 }
04193 if (errp) {
04194 sqlite_freemem(errp);
04195 errp = NULL;
04196 }
04197 namec = findcol(rowp, ncols, "name");
04198 uniquec = findcol(rowp, ncols, "unique");
04199 if (namec < 0 || uniquec < 0) {
04200 goto nodata_but_rowid;
04201 }
04202 namecc = findcol(rowppp, nnncols, "name");
04203 typecc = findcol(rowppp, nnncols, "type");
04204 notnullcc = findcol(rowppp, nnncols, "notnull");
04205 for (i = 1; i <= nrows; i++) {
04206 int nnrows, nncols;
04207 char **rowpp;
04208
04209 if (*rowp[i * ncols + uniquec] != '0') {
04210 ret = sqlite_get_table_printf(d->sqlite,
04211 "PRAGMA index_info('%q')", &rowpp,
04212 &nnrows, &nncols, NULL,
04213 rowp[i * ncols + namec]);
04214 if (ret == SQLITE_OK) {
04215 size += nnrows;
04216 sqlite_free_table(rowpp);
04217 }
04218 }
04219 }
04220 nodata_but_rowid:
04221 if (size == 0) {
04222 size = 1;
04223 mkrowid = 1;
04224 }
04225 s->nrows = size;
04226 size = (size + 1) * array_size(scolSpec);
04227 s->rows = xmalloc((size + 1) * sizeof (char *));
04228 if (!s->rows) {
04229 s->nrows = 0;
04230 sqlite_free_table(rowp);
04231 sqlite_free_table(rowppp);
04232 return nomem(s);
04233 }
04234 s->rows[0] = (char *) size;
04235 s->rows += 1;
04236 memset(s->rows, 0, sizeof (char *) * size);
04237 s->rowfree = freerows;
04238 if (mkrowid) {
04239 s->nrows = 0;
04240 goto mkrowid;
04241 }
04242 offs = 0;
04243 for (i = 1; i <= nrows; i++) {
04244 int nnrows, nncols;
04245 char **rowpp;
04246
04247 if (*rowp[i * ncols + uniquec] != '0') {
04248 int k;
04249
04250 ret = sqlite_get_table_printf(d->sqlite,
04251 "PRAGMA index_info('%q')", &rowpp,
04252 &nnrows, &nncols, NULL,
04253 rowp[i * ncols + namec]);
04254 if (ret != SQLITE_OK) {
04255 continue;
04256 }
04257 for (k = 0; nnrows && k < nncols; k++) {
04258 if (strcmp(rowpp[k], "name") == 0) {
04259 int m;
04260
04261 for (m = 1; m <= nnrows; m++) {
04262 int roffs = (offs + m) * s->ncols;
04263
04264 s->rows[roffs + 0] =
04265 xstrdup(stringify(SQL_SCOPE_SESSION));
04266 s->rows[roffs + 1] = xstrdup(rowpp[m * nncols + k]);
04267 s->rows[roffs + 4] = xstrdup("0");
04268 s->rows[roffs + 7] =
04269 xstrdup(stringify(SQL_PC_NOT_PSEUDO));
04270 if (namecc >= 0 && typecc >= 0) {
04271 int ii;
04272
04273 for (ii = 1; ii <= nnnrows; ii++) {
04274 if (strcmp(rowppp[ii * nnncols + namecc],
04275 rowpp[m * nncols + k]) == 0) {
04276 char *typen = rowppp[ii * nnncols + typecc];
04277 int sqltype, mm, dd, isnullable = 0;
04278 char buf[32];
04279
04280 s->rows[roffs + 3] = xstrdup(typen);
04281 sqltype = mapsqltype(typen, NULL, *s->ov3,
04282 s->nowchar);
04283 getmd(typen, sqltype, &mm, &dd);
04284 #ifdef SQL_LONGVARCHAR
04285 if (sqltype == SQL_VARCHAR && mm > 255) {
04286 sqltype = SQL_LONGVARCHAR;
04287 }
04288 #endif
04289 #ifdef SQLITE_UTF8
04290 #ifdef SQL_WLONGVARCHAR
04291 if (sqltype == SQL_WVARCHAR && mm > 255) {
04292 sqltype = SQL_WLONGVARCHAR;
04293 }
04294 #endif
04295 #endif
04296 #if HAVE_ENCDEC
04297 if (sqltype == SQL_VARBINARY && mm > 255) {
04298 sqltype = SQL_LONGVARBINARY;
04299 }
04300 #endif
04301 sprintf(buf, "%d", sqltype);
04302 s->rows[roffs + 2] = xstrdup(buf);
04303 sprintf(buf, "%d", mm);
04304 s->rows[roffs + 5] = xstrdup(buf);
04305 sprintf(buf, "%d", dd);
04306 s->rows[roffs + 6] = xstrdup(buf);
04307 if (notnullcc >= 0) {
04308 char *inp =
04309 rowppp[ii * nnncols + notnullcc];
04310
04311 isnullable = inp[0] != '0';
04312 }
04313 sprintf(buf, "%d", isnullable);
04314 s->rows[roffs + 8] = xstrdup(buf);
04315 }
04316 }
04317 }
04318 }
04319 }
04320 }
04321 offs += nnrows;
04322 sqlite_free_table(rowpp);
04323 }
04324 }
04325 if (nullable == SQL_NO_NULLS) {
04326 for (i = 1; i < s->nrows; i++) {
04327 if (s->rows[i * s->ncols + 8][0] == '0') {
04328 int m, i1 = i + 1;
04329
04330 for (m = 0; m < s->ncols; m++) {
04331 freep(&s->rows[i * s->ncols + m]);
04332 }
04333 size = s->ncols * sizeof (char *) * (s->nrows - i1);
04334 if (size > 0) {
04335 memmove(s->rows + i * s->ncols,
04336 s->rows + i1 * s->ncols,
04337 size);
04338 memset(s->rows + s->nrows * s->ncols, 0,
04339 s->ncols * sizeof (char *));
04340 }
04341 s->nrows--;
04342 --i;
04343 }
04344 }
04345 }
04346 mkrowid:
04347 sqlite_free_table(rowp);
04348 sqlite_free_table(rowppp);
04349 if (s->nrows == 0) {
04350 s->rows[s->ncols + 0] = xstrdup(stringify(SQL_SCOPE_SESSION));
04351 s->rows[s->ncols + 1] = xstrdup("_ROWID_");
04352 s->rows[s->ncols + 2] = xstrdup(stringify(SQL_INTEGER));
04353 s->rows[s->ncols + 3] = xstrdup("integer");
04354 s->rows[s->ncols + 4] = xstrdup("0");
04355 s->rows[s->ncols + 5] = xstrdup("10");
04356 s->rows[s->ncols + 6] = xstrdup("9");
04357 s->rows[s->ncols + 7] = xstrdup(stringify(SQL_PC_PSEUDO));
04358 s->rows[s->ncols + 8] = xstrdup(stringify(SQL_FALSE));
04359 s->nrows = 1;
04360 }
04361 return SQL_SUCCESS;
04362 }
04363
04364 #ifndef SQLITE_UTF8
04365
04380 SQLRETURN SQL_API
04381 SQLSpecialColumns(SQLHSTMT stmt, SQLUSMALLINT id,
04382 SQLCHAR *cat, SQLSMALLINT catLen,
04383 SQLCHAR *schema, SQLSMALLINT schemaLen,
04384 SQLCHAR *table, SQLSMALLINT tableLen,
04385 SQLUSMALLINT scope, SQLUSMALLINT nullable)
04386 {
04387 return drvspecialcolumns(stmt, id, cat, catLen, schema, schemaLen,
04388 table, tableLen, scope, nullable);
04389 }
04390 #endif
04391
04392 #ifdef SQLITE_UTF8
04393
04408 SQLRETURN SQL_API
04409 SQLSpecialColumnsW(SQLHSTMT stmt, SQLUSMALLINT id,
04410 SQLWCHAR *cat, SQLSMALLINT catLen,
04411 SQLWCHAR *schema, SQLSMALLINT schemaLen,
04412 SQLWCHAR *table, SQLSMALLINT tableLen,
04413 SQLUSMALLINT scope, SQLUSMALLINT nullable)
04414 {
04415 char *c = NULL, *s = NULL, *t = NULL;
04416 SQLRETURN ret;
04417
04418 if (cat) {
04419 c = uc_to_utf_c(cat, catLen);
04420 if (!c) {
04421 ret = nomem((STMT *) stmt);
04422 goto done;
04423 }
04424 }
04425 if (schema) {
04426 s = uc_to_utf_c(schema, schemaLen);
04427 if (!s) {
04428 ret = nomem((STMT *) stmt);
04429 goto done;
04430 }
04431 }
04432 if (table) {
04433 t = uc_to_utf_c(table, tableLen);
04434 if (!t) {
04435 ret = nomem((STMT *) stmt);
04436 goto done;
04437 }
04438 }
04439 ret = drvspecialcolumns(stmt, id, c, SQL_NTS, s, SQL_NTS, t, SQL_NTS,
04440 scope, nullable);
04441 done:
04442 uc_free(t);
04443 uc_free(s);
04444 uc_free(c);
04445 return ret;
04446 }
04447 #endif
04448
04453 static COL fkeySpec[] = {
04454 { "SYSTEM", "FOREIGNKEY", "PKTABLE_QUALIFIER", SCOL_VARCHAR, 50 },
04455 { "SYSTEM", "FOREIGNKEY", "PKTABLE_OWNER", SCOL_VARCHAR, 50 },
04456 { "SYSTEM", "FOREIGNKEY", "PKTABLE_NAME", SCOL_VARCHAR, 255 },
04457 { "SYSTEM", "FOREIGNKEY", "PKCOLUMN_NAME", SCOL_VARCHAR, 255 },
04458 { "SYSTEM", "FOREIGNKEY", "FKTABLE_QUALIFIER", SCOL_VARCHAR, 50 },
04459 { "SYSTEM", "FOREIGNKEY", "FKTABLE_OWNER", SCOL_VARCHAR, 50 },
04460 { "SYSTEM", "FOREIGNKEY", "FKTABLE_NAME", SCOL_VARCHAR, 255 },
04461 { "SYSTEM", "FOREIGNKEY", "FKCOLUMN_NAME", SCOL_VARCHAR, 255 },
04462 { "SYSTEM", "FOREIGNKEY", "KEY_SEQ", SQL_SMALLINT, 5 },
04463 { "SYSTEM", "FOREIGNKEY", "UPDATE_RULE", SQL_SMALLINT, 5 },
04464 { "SYSTEM", "FOREIGNKEY", "DELETE_RULE", SQL_SMALLINT, 5 },
04465 { "SYSTEM", "FOREIGNKEY", "FK_NAME", SCOL_VARCHAR, 255 },
04466 { "SYSTEM", "FOREIGNKEY", "PK_NAME", SCOL_VARCHAR, 255 },
04467 { "SYSTEM", "FOREIGNKEY", "DEFERRABILITY", SQL_SMALLINT, 5 }
04468 };
04469
04488 static SQLRETURN SQL_API
04489 drvforeignkeys(SQLHSTMT stmt,
04490 SQLCHAR *PKcatalog, SQLSMALLINT PKcatalogLen,
04491 SQLCHAR *PKschema, SQLSMALLINT PKschemaLen,
04492 SQLCHAR *PKtable, SQLSMALLINT PKtableLen,
04493 SQLCHAR *FKcatalog, SQLSMALLINT FKcatalogLen,
04494 SQLCHAR *FKschema, SQLSMALLINT FKschemaLen,
04495 SQLCHAR *FKtable, SQLSMALLINT FKtableLen)
04496 {
04497 STMT *s;
04498 DBC *d;
04499 SQLRETURN sret;
04500 int i, size, ret, nrows, ncols, offs, namec, seqc, fromc, toc;
04501 char **rowp, *errp = NULL, pname[512], fname[512];
04502
04503 sret = mkresultset(stmt, fkeySpec, array_size(fkeySpec));
04504 if (sret != SQL_SUCCESS) {
04505 return sret;
04506 }
04507 s = (STMT *) stmt;
04508 d = (DBC *) s->dbc;
04509 if ((!PKtable || PKtable[0] == '\0' || PKtable[0] == '%') &&
04510 (!FKtable || FKtable[0] == '\0' || FKtable[0] == '%')) {
04511 setstat(s, -1, "need table name", (*s->ov3) ? "HY000" : "S1000");
04512 return SQL_ERROR;
04513 }
04514 size = 0;
04515 if (PKtable) {
04516 if (PKtableLen == SQL_NTS) {
04517 size = sizeof (pname) - 1;
04518 } else {
04519 size = min(sizeof (pname) - 1, PKtableLen);
04520 }
04521 strncpy(pname, PKtable, size);
04522 }
04523 pname[size] = '\0';
04524 size = 0;
04525 if (FKtable) {
04526 if (FKtableLen == SQL_NTS) {
04527 size = sizeof (fname) - 1;
04528 } else {
04529 size = min(sizeof (fname) - 1, FKtableLen);
04530 }
04531 strncpy(fname, FKtable, size);
04532 }
04533 fname[size] = '\0';
04534 if (fname[0] != '\0') {
04535 int plen;
04536
04537 ret = sqlite_get_table_printf(d->sqlite,
04538 "PRAGMA foreign_key_list('%q')", &rowp,
04539 &nrows, &ncols, &errp, fname);
04540 if (ret != SQLITE_OK) {
04541 setstat(s, ret, "%s (%d)", (*s->ov3) ? "HY000" : "S1000",
04542 errp ? errp : "unknown error", ret);
04543 if (errp) {
04544 sqlite_freemem(errp);
04545 errp = NULL;
04546 }
04547 return SQL_ERROR;
04548 }
04549 if (errp) {
04550 sqlite_freemem(errp);
04551 errp = NULL;
04552 }
04553 if (ncols * nrows <= 0) {
04554 nodata:
04555 sqlite_free_table(rowp);
04556 return SQL_SUCCESS;
04557 }
04558 size = 0;
04559 namec = findcol(rowp, ncols, "table");
04560 seqc = findcol(rowp, ncols, "seq");
04561 fromc = findcol(rowp, ncols, "from");
04562 toc = findcol(rowp, ncols, "to");
04563 if (namec < 0 || seqc < 0 || fromc < 0 || toc < 0) {
04564 goto nodata;
04565 }
04566 plen = strlen(pname);
04567 for (i = 1; i <= nrows; i++) {
04568 char *ptab = rowp[i * ncols + namec];
04569
04570 if (plen && ptab) {
04571 int len = strlen(ptab);
04572
04573 if (plen != len || strncasecmp(pname, ptab, plen) != 0) {
04574 continue;
04575 }
04576 }
04577 size++;
04578 }
04579 if (size == 0) {
04580 goto nodata;
04581 }
04582 s->nrows = size;
04583 size = (size + 1) * array_size(fkeySpec);
04584 s->rows = xmalloc((size + 1) * sizeof (char *));
04585 if (!s->rows) {
04586 s->nrows = 0;
04587 return nomem(s);
04588 }
04589 s->rows[0] = (char *) size;
04590 s->rows += 1;
04591 memset(s->rows, 0, sizeof (char *) * size);
04592 s->rowfree = freerows;
04593 offs = 0;
04594 for (i = 1; i <= nrows; i++) {
04595 int pos = 0, roffs = (offs + 1) * s->ncols;
04596 char *ptab = rowp[i * ncols + namec];
04597 char buf[32];
04598
04599 if (plen && ptab) {
04600 int len = strlen(ptab);
04601
04602 if (plen != len || strncasecmp(pname, ptab, plen) != 0) {
04603 continue;
04604 }
04605 }
04606 s->rows[roffs + 0] = xstrdup("");
04607 s->rows[roffs + 1] = xstrdup("");
04608 s->rows[roffs + 2] = xstrdup(ptab);
04609 s->rows[roffs + 3] = xstrdup(rowp[i * ncols + toc]);
04610 s->rows[roffs + 4] = xstrdup("");
04611 s->rows[roffs + 5] = xstrdup("");
04612 s->rows[roffs + 6] = xstrdup(fname);
04613 s->rows[roffs + 7] = xstrdup(rowp[i * ncols + fromc]);
04614 sscanf(rowp[i * ncols + seqc], "%d", &pos);
04615 sprintf(buf, "%d", pos + 1);
04616 s->rows[roffs + 8] = xstrdup(buf);
04617 s->rows[roffs + 9] = xstrdup(stringify(SQL_NO_ACTION));
04618 s->rows[roffs + 10] = xstrdup(stringify(SQL_NO_ACTION));
04619 s->rows[roffs + 11] = NULL;
04620 s->rows[roffs + 12] = NULL;
04621 s->rows[roffs + 13] = xstrdup(stringify(SQL_NOT_DEFERRABLE));
04622 offs++;
04623 }
04624 sqlite_free_table(rowp);
04625 } else {
04626 int nnrows, nncols, plen = strlen(pname);
04627 char **rowpp;
04628
04629 ret = sqlite_get_table(d->sqlite,
04630 "select name from sqlite_master "
04631 "where type='table'", &rowp,
04632 &nrows, &ncols, &errp);
04633 if (ret != SQLITE_OK) {
04634 setstat(s, ret, "%s (%d)", (*s->ov3) ? "HY000" : "S1000",
04635 errp ? errp : "unknown error", ret);
04636 if (errp) {
04637 sqlite_freemem(errp);
04638 errp = NULL;
04639 }
04640 return SQL_ERROR;
04641 }
04642 if (errp) {
04643 sqlite_freemem(errp);
04644 errp = NULL;
04645 }
04646 if (ncols * nrows <= 0) {
04647 goto nodata;
04648 }
04649 size = 0;
04650 for (i = 1; i <= nrows; i++) {
04651 int k, len;
04652
04653 if (!rowp[i]) {
04654 continue;
04655 }
04656 len = strlen(rowp[i]);
04657 if (len == plen && strncasecmp(pname, rowp[i], plen) == 0) {
04658 continue;
04659 }
04660 ret = sqlite_get_table_printf(d->sqlite,
04661 "PRAGMA foreign_key_list('%q')",
04662 &rowpp,
04663 &nnrows, &nncols, NULL, rowp[i]);
04664 if (ret != SQLITE_OK || nncols * nnrows <= 0) {
04665 sqlite_free_table(rowpp);
04666 continue;
04667 }
04668 namec = findcol(rowpp, nncols, "table");
04669 seqc = findcol(rowpp, nncols, "seq");
04670 fromc = findcol(rowpp, nncols, "from");
04671 toc = findcol(rowpp, nncols, "to");
04672 if (namec < 0 || seqc < 0 || fromc < 0 || toc < 0) {
04673 sqlite_free_table(rowpp);
04674 continue;
04675 }
04676 for (k = 1; k <= nnrows; k++) {
04677 char *ptab = rowpp[k * nncols + namec];
04678
04679 if (plen && ptab) {
04680 len = strlen(ptab);
04681 if (len != plen || strncasecmp(pname, ptab, plen) != 0) {
04682 continue;
04683 }
04684 }
04685 size++;
04686 }
04687 sqlite_free_table(rowpp);
04688 }
04689 if (size == 0) {
04690 goto nodata;
04691 }
04692 s->nrows = size;
04693 size = (size + 1) * array_size(fkeySpec);
04694 s->rows = xmalloc((size + 1) * sizeof (char *));
04695 if (!s->rows) {
04696 s->nrows = 0;
04697 return nomem(s);
04698 }
04699 s->rows[0] = (char *) size;
04700 s->rows += 1;
04701 memset(s->rows, 0, sizeof (char *) * size);
04702 s->rowfree = freerows;
04703 offs = 0;
04704 for (i = 1; i <= nrows; i++) {
04705 int k, len;
04706
04707 if (!rowp[i]) {
04708 continue;
04709 }
04710 len = strlen(rowp[i]);
04711 if (len == plen && strncasecmp(pname, rowp[i], plen) == 0) {
04712 continue;
04713 }
04714 ret = sqlite_get_table_printf(d->sqlite,
04715 "PRAGMA foreign_key_list('%q')",
04716 &rowpp,
04717 &nnrows, &nncols, NULL, rowp[i]);
04718 if (ret != SQLITE_OK || nncols * nnrows <= 0) {
04719 sqlite_free_table(rowpp);
04720 continue;
04721 }
04722 namec = findcol(rowpp, nncols, "table");
04723 seqc = findcol(rowpp, nncols, "seq");
04724 fromc = findcol(rowpp, nncols, "from");
04725 toc = findcol(rowpp, nncols, "to");
04726 if (namec < 0 || seqc < 0 || fromc < 0 || toc < 0) {
04727 sqlite_free_table(rowpp);
04728 continue;
04729 }
04730 for (k = 1; k <= nnrows; k++) {
04731 int pos = 0, roffs = (offs + 1) * s->ncols;
04732 char *ptab = rowpp[k * nncols + namec];
04733 char buf[32];
04734
04735 if (plen && ptab) {
04736 len = strlen(ptab);
04737 if (len != plen || strncasecmp(pname, ptab, plen) != 0) {
04738 continue;
04739 }
04740 }
04741 s->rows[roffs + 0] = xstrdup("");
04742 s->rows[roffs + 1] = xstrdup("");
04743 s->rows[roffs + 2] = xstrdup(ptab);
04744 s->rows[roffs + 3] = xstrdup(rowpp[k * nncols + toc]);
04745 s->rows[roffs + 4] = xstrdup("");
04746 s->rows[roffs + 5] = xstrdup("");
04747 s->rows[roffs + 6] = xstrdup(rowp[i]);
04748 s->rows[roffs + 7] = xstrdup(rowpp[k * nncols + fromc]);
04749 sscanf(rowpp[k * nncols + seqc], "%d", &pos);
04750 sprintf(buf, "%d", pos + 1);
04751 s->rows[roffs + 8] = xstrdup(buf);
04752 s->rows[roffs + 9] = xstrdup(stringify(SQL_NO_ACTION));
04753 s->rows[roffs + 10] = xstrdup(stringify(SQL_NO_ACTION));
04754 s->rows[roffs + 11] = NULL;
04755 s->rows[roffs + 12] = NULL;
04756 s->rows[roffs + 13] = xstrdup(stringify(SQL_NOT_DEFERRABLE));
04757 offs++;
04758 }
04759 sqlite_free_table(rowpp);
04760 }
04761 sqlite_free_table(rowp);
04762 }
04763 return SQL_SUCCESS;
04764 }
04765
04766 #ifndef SQLITE_UTF8
04767
04785 SQLRETURN SQL_API
04786 SQLForeignKeys(SQLHSTMT stmt,
04787 SQLCHAR *PKcatalog, SQLSMALLINT PKcatalogLen,
04788 SQLCHAR *PKschema, SQLSMALLINT PKschemaLen,
04789 SQLCHAR *PKtable, SQLSMALLINT PKtableLen,
04790 SQLCHAR *FKcatalog, SQLSMALLINT FKcatalogLen,
04791 SQLCHAR *FKschema, SQLSMALLINT FKschemaLen,
04792 SQLCHAR *FKtable, SQLSMALLINT FKtableLen)
04793 {
04794 return drvforeignkeys(stmt,
04795 PKcatalog, PKcatalogLen,
04796 PKschema, PKschemaLen, PKtable, PKtableLen,
04797 FKcatalog, FKcatalogLen,
04798 FKschema, FKschemaLen,
04799 FKtable, FKtableLen);
04800 }
04801 #endif
04802
04803 #ifdef SQLITE_UTF8
04804
04822 SQLRETURN SQL_API
04823 SQLForeignKeysW(SQLHSTMT stmt,
04824 SQLWCHAR *PKcatalog, SQLSMALLINT PKcatalogLen,
04825 SQLWCHAR *PKschema, SQLSMALLINT PKschemaLen,
04826 SQLWCHAR *PKtable, SQLSMALLINT PKtableLen,
04827 SQLWCHAR *FKcatalog, SQLSMALLINT FKcatalogLen,
04828 SQLWCHAR *FKschema, SQLSMALLINT FKschemaLen,
04829 SQLWCHAR *FKtable, SQLSMALLINT FKtableLen)
04830 {
04831 char *pc = NULL, *ps = NULL, *pt = NULL;
04832 char *fc = NULL, *fs = NULL, *ft = NULL;
04833 SQLRETURN ret;
04834
04835 if (PKcatalog) {
04836 pc = uc_to_utf_c(PKcatalog, PKcatalogLen);
04837 if (!pc) {
04838 ret = nomem((STMT *) stmt);
04839 goto done;
04840 }
04841 }
04842 if (PKschema) {
04843 ps = uc_to_utf_c(PKschema, PKschemaLen);
04844 if (!ps) {
04845 ret = nomem((STMT *) stmt);
04846 goto done;
04847 }
04848 }
04849 if (PKtable) {
04850 pt = uc_to_utf_c(PKtable, PKtableLen);
04851 if (!pt) {
04852 ret = nomem((STMT *) stmt);
04853 goto done;
04854 }
04855 }
04856 if (FKcatalog) {
04857 fc = uc_to_utf_c(FKcatalog, FKcatalogLen);
04858 if (!fc) {
04859 ret = nomem((STMT *) stmt);
04860 goto done;
04861 }
04862 }
04863 if (FKschema) {
04864 fs = uc_to_utf_c(FKschema, FKschemaLen);
04865 if (!fs) {
04866 ret = nomem((STMT *) stmt);
04867 goto done;
04868 }
04869 }
04870 if (FKtable) {
04871 ft = uc_to_utf_c(FKtable, FKtableLen);
04872 if (!ft) {
04873 ret = nomem((STMT *) stmt);
04874 goto done;
04875 }
04876 }
04877 ret = drvforeignkeys(stmt, pc, SQL_NTS, ps, SQL_NTS, pt, SQL_NTS,
04878 fc, SQL_NTS, fs, SQL_NTS, ft, SQL_NTS);
04879 done:
04880 uc_free(ft);
04881 uc_free(fs);
04882 uc_free(fc);
04883 uc_free(pt);
04884 uc_free(ps);
04885 uc_free(pc);
04886 return ret;
04887 }
04888 #endif
04889
04897 static SQLRETURN
04898 endtran(DBC *d, SQLSMALLINT comptype)
04899 {
04900 int fail = 0, ret;
04901 char *sql, *errp = NULL;
04902
04903 if (!d->sqlite) {
04904 setstatd(d, -1, "not connected", (*d->ov3) ? "HY000" : "S1000");
04905 return SQL_ERROR;
04906 }
04907 if (d->autocommit || !d->intrans) {
04908 return SQL_SUCCESS;
04909 }
04910 switch (comptype) {
04911 case SQL_COMMIT:
04912 sql = "COMMIT TRANSACTION";
04913 goto doit;
04914 case SQL_ROLLBACK:
04915 rollback:
04916 sql = "ROLLBACK TRANSACTION";
04917 doit:
04918 d->intrans = 0;
04919 ret = sqlite_exec(d->sqlite, sql, NULL, NULL, &errp);
04920 dbtracerc(d, ret, errp);
04921 if (ret != SQLITE_OK) {
04922 if (!fail) {
04923 setstatd(d, ret, "%s", (*d->ov3) ? "HY000" : "S1000",
04924 errp ? errp : "transaction failed");
04925 if (errp) {
04926 sqlite_freemem(errp);
04927 errp = NULL;
04928 }
04929 fail = 1;
04930 goto rollback;
04931 }
04932 if (errp) {
04933 sqlite_freemem(errp);
04934 errp = NULL;
04935 }
04936 return SQL_ERROR;
04937 }
04938 if (errp) {
04939 sqlite_freemem(errp);
04940 errp = NULL;
04941 }
04942 return SQL_SUCCESS;
04943 }
04944 setstatd(d, -1, "invalid completion type", (*d->ov3) ? "HY000" : "S1000");
04945 return SQL_ERROR;
04946 }
04947
04956 static SQLRETURN
04957 drvendtran(SQLSMALLINT type, SQLHANDLE handle, SQLSMALLINT comptype)
04958 {
04959 DBC *d;
04960 int fail = 0;
04961
04962 switch (type) {
04963 case SQL_HANDLE_DBC:
04964 if (handle == SQL_NULL_HDBC) {
04965 return SQL_INVALID_HANDLE;
04966 }
04967 d = (DBC *) handle;
04968 return endtran(d, comptype);
04969 case SQL_HANDLE_ENV:
04970 if (handle == SQL_NULL_HENV) {
04971 return SQL_INVALID_HANDLE;
04972 }
04973 d = ((ENV *) handle)->dbcs;
04974 while (d) {
04975 SQLRETURN ret;
04976
04977 ret = endtran(d, comptype);
04978 if (ret != SQL_SUCCESS) {
04979 fail++;
04980 comptype = SQL_ROLLBACK;
04981 }
04982 d = d->next;
04983 }
04984 return fail ? SQL_ERROR : SQL_SUCCESS;
04985 }
04986 return SQL_INVALID_HANDLE;
04987 }
04988
04997 SQLRETURN SQL_API
04998 SQLEndTran(SQLSMALLINT type, SQLHANDLE handle, SQLSMALLINT comptype)
04999 {
05000 return drvendtran(type, handle, comptype);
05001 }
05002
05011 SQLRETURN SQL_API
05012 SQLTransact(SQLHENV env, SQLHDBC dbc, UWORD type)
05013 {
05014 if (env != SQL_NULL_HENV) {
05015 return drvendtran(SQL_HANDLE_ENV, (SQLHANDLE) env, type);
05016 }
05017 return drvendtran(SQL_HANDLE_DBC, (SQLHANDLE) dbc, type);
05018 }
05019
05024 SQLRETURN SQL_API
05025 SQLCopyDesc(SQLHDESC source, SQLHDESC target)
05026 {
05027 return SQL_ERROR;
05028 }
05029
05030 #ifndef SQLITE_UTF8
05031
05042 SQLRETURN SQL_API
05043 SQLNativeSql(SQLHSTMT stmt, SQLCHAR *sqlin, SQLINTEGER sqlinLen,
05044 SQLCHAR *sql, SQLINTEGER sqlMax, SQLINTEGER *sqlLen)
05045 {
05046 int outLen = 0;
05047
05048 if (sqlinLen == SQL_NTS) {
05049 sqlinLen = strlen(sqlin);
05050 }
05051 if (sql) {
05052 if (sqlMax > 0) {
05053 strncpy(sql, sqlin, sqlMax - 1);
05054 sqlin[sqlMax - 1] = '\0';
05055 outLen = min(sqlMax - 1, sqlinLen);
05056 }
05057 } else {
05058 outLen = sqlinLen;
05059 }
05060 if (sqlLen) {
05061 *sqlLen = outLen;
05062 }
05063 if (sql && outLen < sqlinLen) {
05064 setstat((STMT *) stmt, -1, "data right truncated", "01004");
05065 return SQL_SUCCESS_WITH_INFO;
05066 }
05067 return SQL_SUCCESS;
05068 }
05069 #endif
05070
05071 #ifdef SQLITE_UTF8
05072
05083 SQLRETURN SQL_API
05084 SQLNativeSqlW(SQLHSTMT stmt, SQLWCHAR *sqlin, SQLINTEGER sqlinLen,
05085 SQLWCHAR *sql, SQLINTEGER sqlMax, SQLINTEGER *sqlLen)
05086 {
05087 int outLen = 0;
05088
05089 if (sqlinLen == SQL_NTS) {
05090 sqlinLen = uc_strlen(sqlin);
05091 }
05092 if (sql) {
05093 if (sqlMax > 0) {
05094 uc_strncpy(sql, sqlin, sqlMax - 1);
05095 sqlin[sqlMax - 1] = 0;
05096 outLen = min(sqlMax - 1, sqlinLen);
05097 }
05098 } else {
05099 outLen = sqlinLen;
05100 }
05101 if (sqlLen) {
05102 *sqlLen = outLen;
05103 }
05104 if (sql && outLen < sqlinLen) {
05105 setstat((STMT *) stmt, -1, "data right truncated", "01004");
05106 return SQL_SUCCESS_WITH_INFO;
05107 }
05108 return SQL_SUCCESS;
05109 }
05110 #endif
05111
05116 static COL procSpec[] = {
05117 { "SYSTEM", "PROCEDURE", "PROCEDURE_QUALIFIER", SCOL_VARCHAR, 50 },
05118 { "SYSTEM", "PROCEDURE", "PROCEDURE_OWNER", SCOL_VARCHAR, 50 },
05119 { "SYSTEM", "PROCEDURE", "PROCEDURE_NAME", SCOL_VARCHAR, 255 },
05120 { "SYSTEM", "PROCEDURE", "NUM_INPUT_PARAMS", SQL_SMALLINT, 5 },
05121 { "SYSTEM", "PROCEDURE", "NUM_OUTPUT_PARAMS", SQL_SMALLINT, 5 },
05122 { "SYSTEM", "PROCEDURE", "NUM_RESULT_SETS", SQL_SMALLINT, 5 },
05123 { "SYSTEM", "PROCEDURE", "REMARKS", SCOL_VARCHAR, 255 },
05124 { "SYSTEM", "PROCEDURE", "PROCEDURE_TYPE", SQL_SMALLINT, 5 }
05125 };
05126
05127 #ifndef SQLITE_UTF8
05128
05140 SQLRETURN SQL_API
05141 SQLProcedures(SQLHSTMT stmt,
05142 SQLCHAR *catalog, SQLSMALLINT catalogLen,
05143 SQLCHAR *schema, SQLSMALLINT schemaLen,
05144 SQLCHAR *proc, SQLSMALLINT procLen)
05145 {
05146 return mkresultset(stmt, procSpec, array_size(procSpec));
05147 }
05148 #endif
05149
05150 #ifdef SQLITE_UTF8
05151
05163 SQLRETURN SQL_API
05164 SQLProceduresW(SQLHSTMT stmt,
05165 SQLWCHAR *catalog, SQLSMALLINT catalogLen,
05166 SQLWCHAR *schema, SQLSMALLINT schemaLen,
05167 SQLWCHAR *proc, SQLSMALLINT procLen)
05168 {
05169 return mkresultset(stmt, procSpec, array_size(procSpec));
05170 }
05171 #endif
05172
05177 static COL procColSpec[] = {
05178 { "SYSTEM", "PROCCOL", "PROCEDURE_QUALIFIER", SCOL_VARCHAR, 50 },
05179 { "SYSTEM", "PROCCOL", "PROCEDURE_OWNER", SCOL_VARCHAR, 50 },
05180 { "SYSTEM", "PROCCOL", "PROCEDURE_NAME", SCOL_VARCHAR, 255 },
05181 { "SYSTEM", "PROCCOL", "COLUMN_NAME", SCOL_VARCHAR, 255 },
05182 { "SYSTEM", "PROCCOL", "COLUMN_TYPE", SQL_SMALLINT, 5 },
05183 { "SYSTEM", "PROCCOL", "DATA_TYPE", SQL_SMALLINT, 5 },
05184 { "SYSTEM", "PROCCOL", "TYPE_NAME", SCOL_VARCHAR, 50 },
05185 { "SYSTEM", "PROCCOL", "PRECISION", SQL_INTEGER, 10 },
05186 { "SYSTEM", "PROCCOL", "LENGTH", SQL_INTEGER, 10 },
05187 { "SYSTEM", "PROCCOL", "RADIX", SQL_SMALLINT, 5 },
05188 { "SYSTEM", "PROCCOL", "SCALE", SQL_SMALLINT, 5 },
05189 { "SYSTEM", "PROCCOL", "NULLABLE", SQL_SMALLINT, 5 },
05190 { "SYSTEM", "PROCCOL", "REMARKS", SCOL_VARCHAR, 50 },
05191 { "SYSTEM", "PROCCOL", "COLUMN_DEF", SCOL_VARCHAR, 50 },
05192 { "SYSTEM", "PROCCOL", "SQL_DATA_TYPE", SQL_SMALLINT, 5 },
05193 { "SYSTEM", "PROCCOL", "SQL_DATETIME_SUB", SQL_SMALLINT, 5 },
05194 { "SYSTEM", "PROCCOL", "CHAR_OCTET_LENGTH", SQL_SMALLINT, 5 },
05195 { "SYSTEM", "PROCCOL", "ORDINAL_POSITION", SQL_SMALLINT, 5 },
05196 { "SYSTEM", "PROCCOL", "IS_NULLABLE", SCOL_VARCHAR, 50 }
05197 };
05198
05199 #ifndef SQLITE_UTF8
05200
05214 SQLRETURN SQL_API
05215 SQLProcedureColumns(SQLHSTMT stmt,
05216 SQLCHAR *catalog, SQLSMALLINT catalogLen,
05217 SQLCHAR *schema, SQLSMALLINT schemaLen,
05218 SQLCHAR *proc, SQLSMALLINT procLen,
05219 SQLCHAR *column, SQLSMALLINT columnLen)
05220 {
05221 return mkresultset(stmt, procColSpec, array_size(procColSpec));
05222
05223 }
05224 #endif
05225
05226 #ifdef SQLITE_UTF8
05227
05242 SQLRETURN SQL_API
05243 SQLProcedureColumnsW(SQLHSTMT stmt,
05244 SQLWCHAR *catalog, SQLSMALLINT catalogLen,
05245 SQLWCHAR *schema, SQLSMALLINT schemaLen,
05246 SQLWCHAR *proc, SQLSMALLINT procLen,
05247 SQLWCHAR *column, SQLSMALLINT columnLen)
05248 {
05249 return mkresultset(stmt, procColSpec, array_size(procColSpec));
05250 }
05251 #endif
05252
05263 SQLRETURN SQL_API
05264 SQLGetEnvAttr(SQLHENV env, SQLINTEGER attr, SQLPOINTER val,
05265 SQLINTEGER len, SQLINTEGER *lenp)
05266 {
05267 ENV *e;
05268
05269 if (env == SQL_NULL_HENV) {
05270 return SQL_INVALID_HANDLE;
05271 }
05272 e = (ENV *) env;
05273 if (!e || e->magic != ENV_MAGIC) {
05274 return SQL_INVALID_HANDLE;
05275 }
05276 switch (attr) {
05277 case SQL_ATTR_CONNECTION_POOLING:
05278 return SQL_ERROR;
05279 case SQL_ATTR_CP_MATCH:
05280 return SQL_NO_DATA;
05281 case SQL_ATTR_OUTPUT_NTS:
05282 if (val) {
05283 *((SQLINTEGER *) val) = SQL_TRUE;
05284 }
05285 if (lenp) {
05286 *lenp = sizeof (SQLINTEGER);
05287 }
05288 return SQL_SUCCESS;
05289 case SQL_ATTR_ODBC_VERSION:
05290 if (val) {
05291 *((SQLINTEGER *) val) = e->ov3 ? SQL_OV_ODBC3 : SQL_OV_ODBC2;
05292 }
05293 if (lenp) {
05294 *lenp = sizeof (SQLINTEGER);
05295 }
05296 return SQL_SUCCESS;
05297 }
05298 return SQL_ERROR;
05299 }
05300
05310 SQLRETURN SQL_API
05311 SQLSetEnvAttr(SQLHENV env, SQLINTEGER attr, SQLPOINTER val, SQLINTEGER len)
05312 {
05313 ENV *e;
05314
05315 if (env == SQL_NULL_HENV) {
05316 return SQL_INVALID_HANDLE;
05317 }
05318 e = (ENV *) env;
05319 if (!e || e->magic != ENV_MAGIC) {
05320 return SQL_INVALID_HANDLE;
05321 }
05322 switch (attr) {
05323 case SQL_ATTR_CONNECTION_POOLING:
05324 return SQL_SUCCESS;
05325 case SQL_ATTR_CP_MATCH:
05326 return SQL_NO_DATA;
05327 case SQL_ATTR_OUTPUT_NTS:
05328 if ((SQLINTEGER) val == SQL_TRUE) {
05329 return SQL_SUCCESS;
05330 }
05331 return SQL_ERROR;
05332 case SQL_ATTR_ODBC_VERSION:
05333 if (!val) {
05334 return SQL_ERROR;
05335 }
05336 if ((SQLINTEGER) val == SQL_OV_ODBC2) {
05337 e->ov3 = 0;
05338 return SQL_SUCCESS;
05339 }
05340 if ((SQLINTEGER) val == SQL_OV_ODBC3) {
05341 e->ov3 = 1;
05342 return SQL_SUCCESS;
05343 }
05344 return SQL_ERROR;
05345 }
05346 return SQL_ERROR;
05347 }
05348
05362 static SQLRETURN
05363 drvgetdiagrec(SQLSMALLINT htype, SQLHANDLE handle, SQLSMALLINT recno,
05364 SQLCHAR *sqlstate, SQLINTEGER *nativeerr, SQLCHAR *msg,
05365 SQLSMALLINT buflen, SQLSMALLINT *msglen)
05366 {
05367 DBC *d = NULL;
05368 STMT *s = NULL;
05369 int len, naterr;
05370 char *logmsg, *sqlst;
05371
05372 if (handle == SQL_NULL_HANDLE) {
05373 return SQL_INVALID_HANDLE;
05374 }
05375 if (sqlstate) {
05376 sqlstate[0] = '\0';
05377 }
05378 if (msg && buflen > 0) {
05379 msg[0] = '\0';
05380 }
05381 if (msglen) {
05382 *msglen = 0;
05383 }
05384 if (nativeerr) {
05385 *nativeerr = 0;
05386 }
05387 switch (htype) {
05388 case SQL_HANDLE_ENV:
05389 case SQL_HANDLE_DESC:
05390 return SQL_NO_DATA;
05391 case SQL_HANDLE_DBC:
05392 d = (DBC *) handle;
05393 logmsg = d->logmsg;
05394 sqlst = d->sqlstate;
05395 naterr = d->naterr;
05396 break;
05397 case SQL_HANDLE_STMT:
05398 s = (STMT *) handle;
05399 logmsg = s->logmsg;
05400 sqlst = s->sqlstate;
05401 naterr = s->naterr;
05402 break;
05403 default:
05404 return SQL_INVALID_HANDLE;
05405 }
05406 if (buflen < 0) {
05407 return SQL_ERROR;
05408 }
05409 if (recno > 1) {
05410 return SQL_NO_DATA;
05411 }
05412 len = strlen(logmsg);
05413 if (len == 0) {
05414 return SQL_NO_DATA;
05415 }
05416 if (nativeerr) {
05417 *nativeerr = naterr;
05418 }
05419 if (sqlstate) {
05420 strcpy(sqlstate, sqlst);
05421 }
05422 if (msglen) {
05423 *msglen = len;
05424 }
05425 if (len >= buflen) {
05426 if (msg && buflen > 0) {
05427 strncpy(msg, logmsg, buflen);
05428 msg[buflen - 1] = '\0';
05429 logmsg[0] = '\0';
05430 }
05431 } else if (msg) {
05432 strcpy(msg, logmsg);
05433 logmsg[0] = '\0';
05434 }
05435 return SQL_SUCCESS;
05436 }
05437
05438 #ifndef SQLITE_UTF8
05439
05452 SQLRETURN SQL_API
05453 SQLGetDiagRec(SQLSMALLINT htype, SQLHANDLE handle, SQLSMALLINT recno,
05454 SQLCHAR *sqlstate, SQLINTEGER *nativeerr, SQLCHAR *msg,
05455 SQLSMALLINT buflen, SQLSMALLINT *msglen)
05456 {
05457 return drvgetdiagrec(htype, handle, recno, sqlstate,
05458 nativeerr, msg, buflen, msglen);
05459 }
05460 #endif
05461
05462 #if !defined(HAVE_UNIXODBC) || !HAVE_UNIXODBC
05463 #ifdef SQLITE_UTF8
05464
05478 SQLRETURN SQL_API
05479 SQLGetDiagRecW(SQLSMALLINT htype, SQLHANDLE handle, SQLSMALLINT recno,
05480 SQLWCHAR *sqlstate, SQLINTEGER *nativeerr, SQLWCHAR *msg,
05481 SQLSMALLINT buflen, SQLSMALLINT *msglen)
05482 {
05483 char state[16];
05484 SQLSMALLINT len;
05485 SQLRETURN ret;
05486
05487 ret = drvgetdiagrec(htype, handle, recno, state,
05488 nativeerr, (char *) msg, buflen, &len);
05489 if (ret == SQL_SUCCESS) {
05490 if (sqlstate) {
05491 uc_from_utf_buf(state, sqlstate, 6 * sizeof (SQLWCHAR));
05492 }
05493 if (msg) {
05494 if (len > 0) {
05495 SQLWCHAR *m = NULL;
05496
05497 m = uc_from_utf((char *) msg, len);
05498 if (m) {
05499 if (buflen) {
05500 uc_strncpy(msg, m, buflen);
05501 len = min(buflen, uc_strlen(m));
05502 } else {
05503 len = uc_strlen(m);
05504 }
05505 uc_free(m);
05506 } else {
05507 len = 0;
05508 }
05509 }
05510 if (len <= 0) {
05511 len = 0;
05512 if (buflen > 0) {
05513 msg[0] = 0;
05514 }
05515 }
05516 } else {
05517 len = 0;
05518 }
05519 if (msglen) {
05520 *msglen = len;
05521 }
05522 } else if (ret == SQL_NO_DATA) {
05523 if (sqlstate) {
05524 sqlstate[0] = 0;
05525 }
05526 if (msg) {
05527 if (buflen > 0) {
05528 msg[0] = 0;
05529 }
05530 }
05531 if (msglen) {
05532 *msglen = 0;
05533 }
05534 }
05535 return ret;
05536 }
05537 #endif
05538 #endif
05539
05540 #ifndef SQLITE_UTF8
05541
05545 SQLRETURN SQL_API
05546 SQLGetDiagField(SQLSMALLINT htype, SQLHANDLE handle, SQLSMALLINT recno,
05547 SQLSMALLINT id, SQLPOINTER info,
05548 SQLSMALLINT buflen, SQLSMALLINT *strlen)
05549 {
05550 return SQL_ERROR;
05551 }
05552 #endif
05553
05554 #ifdef SQLITE_UTF8
05555
05559 SQLRETURN SQL_API
05560 SQLGetDiagFieldW(SQLSMALLINT htype, SQLHANDLE handle, SQLSMALLINT recno,
05561 SQLSMALLINT id, SQLPOINTER info,
05562 SQLSMALLINT buflen, SQLSMALLINT *strlen)
05563 {
05564 return SQL_ERROR;
05565 }
05566 #endif
05567
05578 static SQLRETURN
05579 drvgetstmtattr(SQLHSTMT stmt, SQLINTEGER attr, SQLPOINTER val,
05580 SQLINTEGER bufmax, SQLINTEGER *buflen)
05581 {
05582 STMT *s = (STMT *) stmt;
05583 SQLUINTEGER *uval = (SQLUINTEGER *) val;
05584
05585 switch (attr) {
05586 case SQL_QUERY_TIMEOUT:
05587 *uval = 0;
05588 return SQL_SUCCESS;
05589 case SQL_ATTR_CURSOR_TYPE:
05590 *uval = s->curtype;
05591 return SQL_SUCCESS;
05592 case SQL_ATTR_CURSOR_SCROLLABLE:
05593 *uval = s->curtype != SQL_CURSOR_FORWARD_ONLY ?
05594 SQL_SCROLLABLE : SQL_NONSCROLLABLE;
05595 return SQL_SUCCESS;
05596 #ifdef SQL_ATTR_CURSOR_SENSITIVITY
05597 case SQL_ATTR_CURSOR_SENSITIVITY:
05598 *uval = SQL_UNSPECIFIED;
05599 return SQL_SUCCESS;
05600 #endif
05601 case SQL_ATTR_ROW_NUMBER:
05602 {
05603 STMT *s = (STMT *) stmt;
05604 DBC *d = (DBC *) s->dbc;
05605
05606 if (s == d->vm_stmt) {
05607 *uval = d->vm_rownum < 0 ?
05608 SQL_ROW_NUMBER_UNKNOWN : d->vm_rownum;
05609 }
05610 }
05611 *uval = s->rowp < 0 ? SQL_ROW_NUMBER_UNKNOWN : s->rowp;
05612 return SQL_SUCCESS;
05613 case SQL_ATTR_ASYNC_ENABLE:
05614 *uval = SQL_ASYNC_ENABLE_OFF;
05615 return SQL_SUCCESS;
05616 case SQL_CONCURRENCY:
05617 *uval = SQL_CONCUR_LOCK;
05618 return SQL_SUCCESS;
05619 case SQL_ATTR_RETRIEVE_DATA:
05620 *uval = s->retr_data;
05621 return SQL_SUCCESS;
05622 case SQL_ROWSET_SIZE:
05623 case SQL_ATTR_ROW_ARRAY_SIZE:
05624 *uval = s->rowset_size;
05625 return SQL_SUCCESS;
05626
05627 case SQL_ATTR_IMP_ROW_DESC:
05628 case SQL_ATTR_APP_ROW_DESC:
05629 case SQL_ATTR_IMP_PARAM_DESC:
05630 case SQL_ATTR_APP_PARAM_DESC:
05631 *((SQLHDESC *) val) = (SQLHDESC) DEAD_MAGIC;
05632 return SQL_SUCCESS;
05633 case SQL_ATTR_ROW_STATUS_PTR:
05634 *((SQLUSMALLINT **) val) = s->row_status;
05635 return SQL_SUCCESS;
05636 case SQL_ATTR_ROWS_FETCHED_PTR:
05637 *((SQLUINTEGER **) val) = s->row_count;
05638 return SQL_SUCCESS;
05639 case SQL_ATTR_USE_BOOKMARKS: {
05640 STMT *s = (STMT *) stmt;
05641
05642 *(SQLUINTEGER *) val = s->bkmrk ? SQL_UB_ON : SQL_UB_OFF;
05643 return SQL_SUCCESS;
05644 }
05645 case SQL_ATTR_PARAM_BIND_OFFSET_PTR:
05646 *((SQLUINTEGER **) val) = s->parm_bind_offs;
05647 return SQL_SUCCESS;
05648 case SQL_ATTR_PARAM_BIND_TYPE:
05649 *((SQLUINTEGER *) val) = SQL_PARAM_BIND_BY_COLUMN;
05650 return SQL_SUCCESS;
05651 case SQL_ATTR_PARAM_OPERATION_PTR:
05652 *((SQLUSMALLINT **) val) = s->parm_oper;
05653 return SQL_SUCCESS;
05654 case SQL_ATTR_PARAM_STATUS_PTR:
05655 *((SQLUSMALLINT **) val) = s->parm_status;
05656 return SQL_SUCCESS;
05657 case SQL_ATTR_PARAMS_PROCESSED_PTR:
05658 *((SQLUINTEGER **) val) = s->parm_proc;
05659 return SQL_SUCCESS;
05660 case SQL_ATTR_PARAMSET_SIZE:
05661 *((SQLUINTEGER *) val) = s->paramset_size;
05662 return SQL_SUCCESS;
05663 case SQL_ATTR_ROW_BIND_TYPE:
05664 *(SQLUINTEGER *) val = s->bind_type;
05665 return SQL_SUCCESS;
05666 case SQL_ATTR_ROW_BIND_OFFSET_PTR:
05667 *((SQLUINTEGER **) val) = s->bind_offs;
05668 return SQL_SUCCESS;
05669 }
05670 return drvunimplstmt(stmt);
05671 }
05672
05673 #if (defined(HAVE_UNIXODBC) && HAVE_UNIXODBC) || !defined(SQLITE_UTF8)
05674
05684 SQLRETURN SQL_API
05685 SQLGetStmtAttr(SQLHSTMT stmt, SQLINTEGER attr, SQLPOINTER val,
05686 SQLINTEGER bufmax, SQLINTEGER *buflen)
05687 {
05688 return drvgetstmtattr(stmt, attr, val, bufmax, buflen);
05689 }
05690 #endif
05691
05692 #ifdef SQLITE_UTF8
05693
05703 SQLRETURN SQL_API
05704 SQLGetStmtAttrW(SQLHSTMT stmt, SQLINTEGER attr, SQLPOINTER val,
05705 SQLINTEGER bufmax, SQLINTEGER *buflen)
05706 {
05707 return drvgetstmtattr(stmt, attr, val, bufmax, buflen);
05708 }
05709 #endif
05710
05720 static SQLRETURN
05721 drvsetstmtattr(SQLHSTMT stmt, SQLINTEGER attr, SQLPOINTER val,
05722 SQLINTEGER buflen)
05723 {
05724 STMT *s = (STMT *) stmt;
05725
05726 switch (attr) {
05727 case SQL_ATTR_CURSOR_TYPE:
05728 if ((SQLUINTEGER) val == SQL_CURSOR_FORWARD_ONLY) {
05729 s->curtype = SQL_CURSOR_FORWARD_ONLY;
05730 } else {
05731 s->curtype = SQL_CURSOR_STATIC;
05732 }
05733 if ((SQLUINTEGER) val != SQL_CURSOR_FORWARD_ONLY &&
05734 (SQLUINTEGER) val != SQL_CURSOR_STATIC) {
05735 goto e01s02;
05736 }
05737 return SQL_SUCCESS;
05738 case SQL_ATTR_CURSOR_SCROLLABLE:
05739 if ((SQLUINTEGER) val == SQL_NONSCROLLABLE) {
05740 s->curtype = SQL_CURSOR_FORWARD_ONLY;
05741 } else {
05742 s->curtype = SQL_CURSOR_STATIC;
05743 }
05744 return SQL_SUCCESS;
05745 case SQL_ATTR_ASYNC_ENABLE:
05746 if ((SQLUINTEGER) val != SQL_ASYNC_ENABLE_OFF) {
05747 e01s02:
05748 setstat(s, -1, "option value changed", "01S02");
05749 return SQL_SUCCESS_WITH_INFO;
05750 }
05751 return SQL_SUCCESS;
05752 case SQL_CONCURRENCY:
05753 if ((SQLUINTEGER) val != SQL_CONCUR_LOCK) {
05754 goto e01s02;
05755 }
05756 return SQL_SUCCESS;
05757 case SQL_ATTR_QUERY_TIMEOUT:
05758 return SQL_SUCCESS;
05759 case SQL_ATTR_RETRIEVE_DATA:
05760 if ((SQLUINTEGER) val != SQL_RD_ON &&
05761 (SQLUINTEGER) val != SQL_RD_OFF) {
05762 goto e01s02;
05763 }
05764 s->retr_data = (int) val;
05765 return SQL_SUCCESS;
05766 case SQL_ROWSET_SIZE:
05767 case SQL_ATTR_ROW_ARRAY_SIZE:
05768 if ((SQLUINTEGER) val < 1) {
05769 setstat(s, -1, "invalid rowset size", "HY000");
05770 return SQL_ERROR;
05771 } else {
05772 SQLUSMALLINT *rst = &s->row_status1;
05773
05774 if ((SQLUINTEGER) val > 1) {
05775 rst = xmalloc(sizeof (SQLUSMALLINT) * (SQLUINTEGER) val);
05776 if (!rst) {
05777 return nomem(s);
05778 }
05779 }
05780 if (s->row_status0 != &s->row_status1) {
05781 freep(&s->row_status0);
05782 }
05783 s->row_status0 = rst;
05784 s->rowset_size = (SQLUINTEGER) val;
05785 }
05786 return SQL_SUCCESS;
05787 case SQL_ATTR_ROW_STATUS_PTR:
05788 s->row_status = (SQLUSMALLINT *) val;
05789 return SQL_SUCCESS;
05790 case SQL_ATTR_ROWS_FETCHED_PTR:
05791 s->row_count = (SQLUINTEGER *) val;
05792 return SQL_SUCCESS;
05793 case SQL_ATTR_PARAM_BIND_OFFSET_PTR:
05794 s->parm_bind_offs = (SQLUINTEGER *) val;
05795 return SQL_SUCCESS;
05796 case SQL_ATTR_PARAM_BIND_TYPE:
05797 if ((SQLUINTEGER) val != SQL_PARAM_BIND_BY_COLUMN) {
05798 goto e01s02;
05799 }
05800 return SQL_SUCCESS;
05801 case SQL_ATTR_PARAM_OPERATION_PTR:
05802 s->parm_oper = (SQLUSMALLINT *) val;
05803 return SQL_SUCCESS;
05804 case SQL_ATTR_PARAM_STATUS_PTR:
05805 s->parm_status = (SQLUSMALLINT *) val;
05806 return SQL_SUCCESS;
05807 case SQL_ATTR_PARAMS_PROCESSED_PTR:
05808 s->parm_proc = (SQLUINTEGER *) val;
05809 return SQL_SUCCESS;
05810 case SQL_ATTR_PARAMSET_SIZE:
05811 if ((SQLUINTEGER) val < 1) {
05812 goto e01s02;
05813 }
05814 s->paramset_size = (SQLUINTEGER) val;
05815 s->paramset_count = 0;
05816 return SQL_SUCCESS;
05817 case SQL_ATTR_ROW_BIND_TYPE:
05818 s->bind_type = (SQLUINTEGER) val;
05819 return SQL_SUCCESS;
05820 case SQL_ATTR_ROW_BIND_OFFSET_PTR:
05821 s->bind_offs = (SQLUINTEGER *) val;
05822 return SQL_SUCCESS;
05823 case SQL_ATTR_USE_BOOKMARKS:
05824 if ((SQLUINTEGER) val != SQL_UB_OFF &&
05825 (SQLUINTEGER) val != SQL_UB_ON) {
05826 goto e01s02;
05827 }
05828 s->bkmrk = (SQLUINTEGER) val == SQL_UB_ON;
05829 return SQL_SUCCESS;
05830 }
05831 return drvunimplstmt(stmt);
05832 }
05833
05834 #if (defined(HAVE_UNIXODBC) && HAVE_UNIXODBC) || !defined(SQLITE_UTF8)
05835
05844 SQLRETURN SQL_API
05845 SQLSetStmtAttr(SQLHSTMT stmt, SQLINTEGER attr, SQLPOINTER val,
05846 SQLINTEGER buflen)
05847 {
05848 return drvsetstmtattr(stmt, attr, val, buflen);
05849 }
05850 #endif
05851
05852 #ifdef SQLITE_UTF8
05853
05862 SQLRETURN SQL_API
05863 SQLSetStmtAttrW(SQLHSTMT stmt, SQLINTEGER attr, SQLPOINTER val,
05864 SQLINTEGER buflen)
05865 {
05866 return drvsetstmtattr(stmt, attr, val, buflen);
05867 }
05868 #endif
05869
05878 static SQLRETURN
05879 drvgetstmtoption(SQLHSTMT stmt, SQLUSMALLINT opt, SQLPOINTER param)
05880 {
05881 STMT *s = (STMT *) stmt;
05882 SQLUINTEGER *ret = (SQLUINTEGER *) param;
05883
05884 switch (opt) {
05885 case SQL_QUERY_TIMEOUT:
05886 *ret = 0;
05887 return SQL_SUCCESS;
05888 case SQL_CURSOR_TYPE:
05889 *ret = s->curtype;
05890 return SQL_SUCCESS;
05891 case SQL_ROW_NUMBER:
05892 {
05893 DBC *d = (DBC *) s->dbc;
05894
05895 if (s == d->vm_stmt) {
05896 *ret = d->vm_rownum < 0 ?
05897 SQL_ROW_NUMBER_UNKNOWN : d->vm_rownum;
05898 }
05899 }
05900 *ret = s->rowp < 0 ? SQL_ROW_NUMBER_UNKNOWN : s->rowp;
05901 return SQL_SUCCESS;
05902 case SQL_ASYNC_ENABLE:
05903 *ret = SQL_ASYNC_ENABLE_OFF;
05904 return SQL_SUCCESS;
05905 case SQL_CONCURRENCY:
05906 *ret = SQL_CONCUR_LOCK;
05907 return SQL_SUCCESS;
05908 case SQL_ATTR_RETRIEVE_DATA:
05909 *ret = s->retr_data;
05910 return SQL_SUCCESS;
05911 case SQL_ROWSET_SIZE:
05912 case SQL_ATTR_ROW_ARRAY_SIZE:
05913 *ret = s->rowset_size;
05914 return SQL_SUCCESS;
05915 }
05916 return drvunimplstmt(stmt);
05917 }
05918
05927 SQLRETURN SQL_API
05928 SQLGetStmtOption(SQLHSTMT stmt, SQLUSMALLINT opt, SQLPOINTER param)
05929 {
05930 return drvgetstmtoption(stmt, opt, param);
05931 }
05932
05933 #ifdef SQLITE_UTF8
05934
05942 SQLRETURN SQL_API
05943 SQLGetStmtOptionW(SQLHSTMT stmt, SQLUSMALLINT opt, SQLPOINTER param)
05944 {
05945 return drvgetstmtoption(stmt, opt, param);
05946 }
05947 #endif
05948
05957 static SQLRETURN
05958 drvsetstmtoption(SQLHSTMT stmt, SQLUSMALLINT opt, SQLUINTEGER param)
05959 {
05960 STMT *s = (STMT *) stmt;
05961
05962 switch (opt) {
05963 case SQL_CURSOR_TYPE:
05964 if (param == SQL_CURSOR_FORWARD_ONLY) {
05965 s->curtype = param;
05966 } else {
05967 s->curtype = SQL_CURSOR_STATIC;
05968 }
05969 if (param != SQL_CURSOR_FORWARD_ONLY &&
05970 param != SQL_CURSOR_STATIC) {
05971 goto e01s02;
05972 }
05973 return SQL_SUCCESS;
05974 case SQL_ASYNC_ENABLE:
05975 if (param != SQL_ASYNC_ENABLE_OFF) {
05976 goto e01s02;
05977 }
05978 return SQL_SUCCESS;
05979 case SQL_CONCURRENCY:
05980 if (param != SQL_CONCUR_LOCK) {
05981 goto e01s02;
05982 }
05983 return SQL_SUCCESS;
05984 case SQL_QUERY_TIMEOUT:
05985 return SQL_SUCCESS;
05986 case SQL_RETRIEVE_DATA:
05987 if (param != SQL_RD_ON && param != SQL_RD_OFF) {
05988 e01s02:
05989 setstat(s, -1, "option value changed", "01S02");
05990 return SQL_SUCCESS_WITH_INFO;
05991 }
05992 s->retr_data = (int) param;
05993 return SQL_SUCCESS;
05994 case SQL_ROWSET_SIZE:
05995 case SQL_ATTR_ROW_ARRAY_SIZE:
05996 if (param < 1) {
05997 setstat(s, -1, "invalid rowset size", "HY000");
05998 return SQL_ERROR;
05999 } else {
06000 SQLUSMALLINT *rst = &s->row_status1;
06001
06002 if (param > 1) {
06003 rst = xmalloc(sizeof (SQLUSMALLINT) * param);
06004 if (!rst) {
06005 return nomem(s);
06006 }
06007 }
06008 if (s->row_status0 != &s->row_status1) {
06009 freep(&s->row_status0);
06010 }
06011 s->row_status0 = rst;
06012 s->rowset_size = param;
06013 }
06014 return SQL_SUCCESS;
06015 }
06016 return drvunimplstmt(stmt);
06017 }
06018
06027 SQLRETURN SQL_API
06028 SQLSetStmtOption(SQLHSTMT stmt, SQLUSMALLINT opt, SQLUINTEGER param)
06029 {
06030 return drvsetstmtoption(stmt, opt, param);
06031 }
06032
06033 #ifdef SQLITE_UTF8
06034
06042 SQLRETURN SQL_API
06043 SQLSetStmtOptionW(SQLHSTMT stmt, SQLUSMALLINT opt, SQLUINTEGER param)
06044 {
06045 return drvsetstmtoption(stmt, opt, param);
06046 }
06047 #endif
06048
06053 SQLRETURN SQL_API
06054 SQLSetPos(SQLHSTMT stmt, SQLUSMALLINT row, SQLUSMALLINT op, SQLUSMALLINT lock)
06055 {
06056 return drvunimplstmt(stmt);
06057 }
06058
06063 SQLRETURN SQL_API
06064 SQLSetScrollOptions(SQLHSTMT stmt, SQLUSMALLINT concur, SQLINTEGER rowkeyset,
06065 SQLUSMALLINT rowset)
06066 {
06067 return drvunimplstmt(stmt);
06068 }
06069
06070 #define strmak(dst, src, max, lenp) { \
06071 int len = strlen(src); \
06072 int cnt = min(len + 1, max); \
06073 strncpy(dst, src, cnt); \
06074 *lenp = (cnt > len) ? len : cnt; \
06075 }
06076
06087 static SQLRETURN
06088 drvgetinfo(SQLHDBC dbc, SQLUSMALLINT type, SQLPOINTER val, SQLSMALLINT valMax,
06089 SQLSMALLINT *valLen)
06090 {
06091 DBC *d;
06092 char dummyc[16];
06093 SQLSMALLINT dummy;
06094 static char drvname[] =
06095 #ifdef _WIN32
06096 "sqliteodbc.dll";
06097 #else
06098 "sqliteodbc.so";
06099 #endif
06100
06101 if (dbc == SQL_NULL_HDBC) {
06102 return SQL_INVALID_HANDLE;
06103 }
06104 d = (DBC *) dbc;
06105 if (valMax) {
06106 valMax--;
06107 }
06108 if (!valLen) {
06109 valLen = &dummy;
06110 }
06111 if (!val) {
06112 val = dummyc;
06113 valMax = sizeof (dummyc) - 1;
06114 }
06115 switch (type) {
06116 case SQL_MAX_USER_NAME_LEN:
06117 *((SQLSMALLINT *) val) = 16;
06118 *valLen = sizeof (SQLSMALLINT);
06119 break;
06120 case SQL_USER_NAME:
06121 strmak(val, "", valMax, valLen);
06122 break;
06123 case SQL_DRIVER_ODBC_VER:
06124 #if 0
06125 strmak(val, (*d->ov3) ? "03.00" : "02.50", valMax, valLen);
06126 #else
06127 strmak(val, "03.00", valMax, valLen);
06128 #endif
06129 break;
06130 case SQL_ACTIVE_CONNECTIONS:
06131 case SQL_ACTIVE_STATEMENTS:
06132 *((SQLSMALLINT *) val) = 0;
06133 *valLen = sizeof (SQLSMALLINT);
06134 break;
06135 #ifdef SQL_ASYNC_MODE
06136 case SQL_ASYNC_MODE:
06137 *((SQLUINTEGER *) val) = SQL_AM_NONE;
06138 *valLen = sizeof (SQLUINTEGER);
06139 break;
06140 #endif
06141 #ifdef SQL_CREATE_TABLE
06142 case SQL_CREATE_TABLE:
06143 *((SQLUINTEGER *) val) = SQL_CT_CREATE_TABLE |
06144 SQL_CT_COLUMN_DEFAULT |
06145 SQL_CT_COLUMN_CONSTRAINT |
06146 SQL_CT_CONSTRAINT_NON_DEFERRABLE;
06147 *valLen = sizeof (SQLUINTEGER);
06148 break;
06149 #endif
06150 #ifdef SQL_CREATE_VIEW
06151 case SQL_CREATE_VIEW:
06152 *((SQLUINTEGER *) val) = SQL_CV_CREATE_VIEW;
06153 *valLen = sizeof (SQLUINTEGER);
06154 break;
06155 #endif
06156 #ifdef SQL_DDL_INDEX
06157 case SQL_DDL_INDEX:
06158 *((SQLUINTEGER *) val) = SQL_DI_CREATE_INDEX | SQL_DI_DROP_INDEX;
06159 *valLen = sizeof (SQLUINTEGER);
06160 break;
06161 #endif
06162 #ifdef SQL_DROP_TABLE
06163 case SQL_DROP_TABLE:
06164 *((SQLUINTEGER *) val) = SQL_DT_DROP_TABLE;
06165 *valLen = sizeof (SQLUINTEGER);
06166 break;
06167 #endif
06168 #ifdef SQL_DROP_VIEW
06169 case SQL_DROP_VIEW:
06170 *((SQLUINTEGER *) val) = SQL_DV_DROP_VIEW;
06171 *valLen = sizeof (SQLUINTEGER);
06172 break;
06173 #endif
06174 #ifdef SQL_INDEX_KEYWORDS
06175 case SQL_INDEX_KEYWORDS:
06176 *((SQLUINTEGER *) val) = SQL_IK_ALL;
06177 *valLen = sizeof (SQLUINTEGER);
06178 break;
06179 #endif
06180 case SQL_DATA_SOURCE_NAME:
06181 strmak(val, (d->dsn ? d->dsn : ""), valMax, valLen);
06182 break;
06183 case SQL_DRIVER_NAME:
06184 strmak(val, drvname, valMax, valLen);
06185 break;
06186 case SQL_DRIVER_VER:
06187 strmak(val, DRIVER_VER_INFO, valMax, valLen);
06188 break;
06189 case SQL_FETCH_DIRECTION:
06190 *((SQLUINTEGER *) val) = SQL_FD_FETCH_NEXT | SQL_FD_FETCH_FIRST |
06191 SQL_FD_FETCH_LAST | SQL_FD_FETCH_PRIOR | SQL_FD_FETCH_ABSOLUTE;
06192 *valLen = sizeof (SQLUINTEGER);
06193 break;
06194 case SQL_ODBC_VER:
06195 strmak(val, (*d->ov3) ? "03.00" : "02.50", valMax, valLen);
06196 break;
06197 case SQL_ODBC_SAG_CLI_CONFORMANCE:
06198 *((SQLSMALLINT *) val) = SQL_OSCC_NOT_COMPLIANT;
06199 *valLen = sizeof (SQLSMALLINT);
06200 break;
06201 case SQL_STANDARD_CLI_CONFORMANCE:
06202 *((SQLUINTEGER *) val) = SQL_SCC_XOPEN_CLI_VERSION1;
06203 *valLen = sizeof (SQLUINTEGER);
06204 break;
06205 case SQL_SERVER_NAME:
06206 case SQL_DATABASE_NAME:
06207 strmak(val, (d->dbname ? d->dbname : ""), valMax, valLen);
06208 break;
06209 case SQL_SEARCH_PATTERN_ESCAPE:
06210 strmak(val, "", valMax, valLen);
06211 break;
06212 case SQL_ODBC_SQL_CONFORMANCE:
06213 *((SQLSMALLINT *) val) = SQL_OSC_MINIMUM;
06214 *valLen = sizeof (SQLSMALLINT);
06215 break;
06216 case SQL_ODBC_API_CONFORMANCE:
06217 *((SQLSMALLINT *) val) = SQL_OAC_LEVEL1;
06218 *valLen = sizeof (SQLSMALLINT);
06219 break;
06220 case SQL_DBMS_NAME:
06221 strmak(val, "SQLite", valMax, valLen);
06222 break;
06223 case SQL_DBMS_VER:
06224 strmak(val, SQLITE_VERSION, valMax, valLen);
06225 break;
06226 case SQL_COLUMN_ALIAS:
06227 case SQL_NEED_LONG_DATA_LEN:
06228 strmak(val, "Y", valMax, valLen);
06229 break;
06230 case SQL_ROW_UPDATES:
06231 case SQL_ACCESSIBLE_PROCEDURES:
06232 case SQL_PROCEDURES:
06233 case SQL_EXPRESSIONS_IN_ORDERBY:
06234 case SQL_ODBC_SQL_OPT_IEF:
06235 case SQL_LIKE_ESCAPE_CLAUSE:
06236 case SQL_ORDER_BY_COLUMNS_IN_SELECT:
06237 case SQL_OUTER_JOINS:
06238 case SQL_ACCESSIBLE_TABLES:
06239 case SQL_MULT_RESULT_SETS:
06240 case SQL_MULTIPLE_ACTIVE_TXN:
06241 case SQL_MAX_ROW_SIZE_INCLUDES_LONG:
06242 strmak(val, "N", valMax, valLen);
06243 break;
06244 case SQL_DATA_SOURCE_READ_ONLY:
06245 strmak(val, "N", valMax, valLen);
06246 break;
06247 #ifdef SQL_OJ_CAPABILITIES
06248 case SQL_OJ_CAPABILITIES:
06249 *((SQLUINTEGER *) val) = 0;
06250 *valLen = sizeof (SQLUINTEGER);
06251 break;
06252 #endif
06253 #ifdef SQL_MAX_IDENTIFIER_LEN
06254 case SQL_MAX_IDENTIFIER_LEN:
06255 *((SQLUSMALLINT *) val) = 255;
06256 *valLen = sizeof (SQLUSMALLINT);
06257 break;
06258 #endif
06259 case SQL_CONCAT_NULL_BEHAVIOR:
06260 *((SQLSMALLINT *) val) = SQL_CB_NULL;
06261 *valLen = sizeof (SQLSMALLINT);
06262 break;
06263 case SQL_CURSOR_COMMIT_BEHAVIOR:
06264 case SQL_CURSOR_ROLLBACK_BEHAVIOR:
06265 *((SQLSMALLINT *) val) = SQL_CB_DELETE;
06266 *valLen = sizeof (SQLSMALLINT);
06267 break;
06268 #ifdef SQL_CURSOR_SENSITIVITY
06269 case SQL_CURSOR_SENSITIVITY:
06270 *((SQLUINTEGER *) val) = SQL_UNSPECIFIED;
06271 *valLen = sizeof (SQLUINTEGER);
06272 break;
06273 #endif
06274 case SQL_DEFAULT_TXN_ISOLATION:
06275 *((SQLUINTEGER *) val) = SQL_TXN_READ_UNCOMMITTED;
06276 *valLen = sizeof (SQLUINTEGER);
06277 break;
06278 #ifdef SQL_DESCRIBE_PARAMETER
06279 case SQL_DESCRIBE_PARAMETER:
06280 strmak(val, "Y", valMax, valLen);
06281 break;
06282 #endif
06283 case SQL_TXN_ISOLATION_OPTION:
06284 *((SQLUINTEGER *) val) = SQL_TXN_READ_UNCOMMITTED;
06285 *valLen = sizeof (SQLUINTEGER);
06286 break;
06287 case SQL_IDENTIFIER_CASE:
06288 *((SQLSMALLINT *) val) = SQL_IC_SENSITIVE;
06289 *valLen = sizeof (SQLSMALLINT);
06290 break;
06291 case SQL_IDENTIFIER_QUOTE_CHAR:
06292 strmak(val, "\"", valMax, valLen);
06293 break;
06294 case SQL_MAX_TABLE_NAME_LEN:
06295 case SQL_MAX_COLUMN_NAME_LEN:
06296 *((SQLSMALLINT *) val) = 255;
06297 *valLen = sizeof (SQLSMALLINT);
06298 break;
06299 case SQL_MAX_CURSOR_NAME_LEN:
06300 *((SWORD *) val) = 255;
06301 *valLen = sizeof (SWORD);
06302 break;
06303 case SQL_MAX_PROCEDURE_NAME_LEN:
06304 *((SQLSMALLINT *) val) = 0;
06305 break;
06306 case SQL_MAX_QUALIFIER_NAME_LEN:
06307 case SQL_MAX_OWNER_NAME_LEN:
06308 *((SQLSMALLINT *) val) = 255;
06309 break;
06310 case SQL_OWNER_TERM:
06311 strmak(val, "owner", valMax, valLen);
06312 break;
06313 case SQL_PROCEDURE_TERM:
06314 strmak(val, "procedure", valMax, valLen);
06315 break;
06316 case SQL_QUALIFIER_NAME_SEPARATOR:
06317 strmak(val, ".", valMax, valLen);
06318 break;
06319 case SQL_QUALIFIER_TERM:
06320 strmak(val, "database", valMax, valLen);
06321 break;
06322 case SQL_QUALIFIER_USAGE:
06323 *((SQLUINTEGER *) val) = 0;
06324 *valLen = sizeof (SQLUINTEGER);
06325 break;
06326 case SQL_SCROLL_CONCURRENCY:
06327 *((SQLUINTEGER *) val) = SQL_SCCO_LOCK;
06328 *valLen = sizeof (SQLUINTEGER);
06329 break;
06330 case SQL_SCROLL_OPTIONS:
06331 *((SQLUINTEGER *) val) = SQL_SO_STATIC | SQL_SO_FORWARD_ONLY;
06332 *valLen = sizeof (SQLUINTEGER);
06333 break;
06334 case SQL_TABLE_TERM:
06335 strmak(val, "table", valMax, valLen);
06336 break;
06337 case SQL_TXN_CAPABLE:
06338 *((SQLSMALLINT *) val) = SQL_TC_ALL;
06339 *valLen = sizeof (SQLSMALLINT);
06340 break;
06341 case SQL_CONVERT_FUNCTIONS:
06342 *((SQLUINTEGER *) val) = 0;
06343 *valLen = sizeof (SQLUINTEGER);
06344 break;
06345 case SQL_SYSTEM_FUNCTIONS:
06346 case SQL_NUMERIC_FUNCTIONS:
06347 case SQL_STRING_FUNCTIONS:
06348 case SQL_TIMEDATE_FUNCTIONS:
06349 *((SQLUINTEGER *) val) = 0;
06350 *valLen = sizeof (SQLUINTEGER);
06351 break;
06352 case SQL_CONVERT_BIGINT:
06353 case SQL_CONVERT_BIT:
06354 case SQL_CONVERT_CHAR:
06355 case SQL_CONVERT_DATE:
06356 case SQL_CONVERT_DECIMAL:
06357 case SQL_CONVERT_DOUBLE:
06358 case SQL_CONVERT_FLOAT:
06359 case SQL_CONVERT_INTEGER:
06360 case SQL_CONVERT_LONGVARCHAR:
06361 case SQL_CONVERT_NUMERIC:
06362 case SQL_CONVERT_REAL:
06363 case SQL_CONVERT_SMALLINT:
06364 case SQL_CONVERT_TIME:
06365 case SQL_CONVERT_TIMESTAMP:
06366 case SQL_CONVERT_TINYINT:
06367 case SQL_CONVERT_VARCHAR:
06368 *((SQLUINTEGER *) val) =
06369 SQL_CVT_CHAR | SQL_CVT_NUMERIC | SQL_CVT_DECIMAL |
06370 SQL_CVT_INTEGER | SQL_CVT_SMALLINT | SQL_CVT_FLOAT | SQL_CVT_REAL |
06371 SQL_CVT_DOUBLE | SQL_CVT_VARCHAR | SQL_CVT_LONGVARCHAR |
06372 SQL_CVT_BIT | SQL_CVT_TINYINT | SQL_CVT_BIGINT |
06373 SQL_CVT_DATE | SQL_CVT_TIME | SQL_CVT_TIMESTAMP;
06374 *valLen = sizeof (SQLUINTEGER);
06375 break;
06376 case SQL_CONVERT_BINARY:
06377 case SQL_CONVERT_VARBINARY:
06378 case SQL_CONVERT_LONGVARBINARY:
06379 *((SQLUINTEGER *) val) = 0;
06380 *valLen = sizeof (SQLUINTEGER);
06381 break;
06382 case SQL_POSITIONED_STATEMENTS:
06383 case SQL_LOCK_TYPES:
06384 *((SQLUINTEGER *) val) = 0;
06385 *valLen = sizeof (SQLUINTEGER);
06386 break;
06387 case SQL_BOOKMARK_PERSISTENCE:
06388 *((SQLUINTEGER *) val) = SQL_BP_SCROLL;
06389 *valLen = sizeof (SQLUINTEGER);
06390 break;
06391 case SQL_UNION:
06392 *((SQLUINTEGER *) val) = SQL_U_UNION;
06393 *valLen = sizeof (SQLUINTEGER);
06394 break;
06395 case SQL_OWNER_USAGE:
06396 case SQL_SUBQUERIES:
06397 case SQL_TIMEDATE_ADD_INTERVALS:
06398 case SQL_TIMEDATE_DIFF_INTERVALS:
06399 *((SQLUINTEGER *) val) = 0;
06400 *valLen = sizeof (SQLUINTEGER);
06401 break;
06402 case SQL_QUOTED_IDENTIFIER_CASE:
06403 *((SQLUSMALLINT *) val) = SQL_IC_SENSITIVE;
06404 *valLen = sizeof (SQLUSMALLINT);
06405 break;
06406 case SQL_POS_OPERATIONS:
06407 *((SQLUINTEGER *) val) = 0;
06408 *valLen = sizeof (SQLUINTEGER);
06409 break;
06410 case SQL_ALTER_TABLE:
06411 *((SQLUINTEGER *) val) = 0;
06412 *valLen = sizeof (SQLUINTEGER);
06413 break;
06414 case SQL_CORRELATION_NAME:
06415 *((SQLSMALLINT *) val) = SQL_CN_DIFFERENT;
06416 *valLen = sizeof (SQLSMALLINT);
06417 break;
06418 case SQL_NON_NULLABLE_COLUMNS:
06419 *((SQLSMALLINT *) val) = SQL_NNC_NON_NULL;
06420 *valLen = sizeof (SQLSMALLINT);
06421 break;
06422 case SQL_NULL_COLLATION:
06423 *((SQLSMALLINT *) val) = SQL_NC_START;
06424 *valLen = sizeof(SQLSMALLINT);
06425 break;
06426 case SQL_MAX_COLUMNS_IN_GROUP_BY:
06427 case SQL_MAX_COLUMNS_IN_ORDER_BY:
06428 case SQL_MAX_COLUMNS_IN_SELECT:
06429 case SQL_MAX_COLUMNS_IN_TABLE:
06430 case SQL_MAX_ROW_SIZE:
06431 case SQL_MAX_TABLES_IN_SELECT:
06432 *((SQLSMALLINT *) val) = 0;
06433 *valLen = sizeof (SQLSMALLINT);
06434 break;
06435 case SQL_MAX_BINARY_LITERAL_LEN:
06436 case SQL_MAX_CHAR_LITERAL_LEN:
06437 *((SQLUINTEGER *) val) = 0;
06438 *valLen = sizeof (SQLUINTEGER);
06439 break;
06440 case SQL_MAX_COLUMNS_IN_INDEX:
06441 *((SQLSMALLINT *) val) = 0;
06442 *valLen = sizeof (SQLSMALLINT);
06443 break;
06444 case SQL_MAX_INDEX_SIZE:
06445 *((SQLUINTEGER *) val) = 0;
06446 *valLen = sizeof(SQLUINTEGER);
06447 break;
06448 #ifdef SQL_MAX_IDENTIFIER_LENGTH
06449 case SQL_MAX_IDENTIFIER_LENGTH:
06450 *((SQLUINTEGER *) val) = 255;
06451 *valLen = sizeof (SQLUINTEGER);
06452 break;
06453 #endif
06454 case SQL_MAX_STATEMENT_LEN:
06455 *((SQLUINTEGER *) val) = 16384;
06456 *valLen = sizeof (SQLUINTEGER);
06457 break;
06458 case SQL_QUALIFIER_LOCATION:
06459 *((SQLSMALLINT *) val) = SQL_QL_START;
06460 *valLen = sizeof (SQLSMALLINT);
06461 break;
06462 case SQL_GETDATA_EXTENSIONS:
06463 *((SQLUINTEGER *) val) =
06464 SQL_GD_ANY_COLUMN | SQL_GD_ANY_ORDER | SQL_GD_BOUND;
06465 *valLen = sizeof (SQLUINTEGER);
06466 break;
06467 case SQL_STATIC_SENSITIVITY:
06468 *((SQLUINTEGER *) val) = 0;
06469 *valLen = sizeof (SQLUINTEGER);
06470 break;
06471 case SQL_FILE_USAGE:
06472 *((SQLSMALLINT *) val) = SQL_FILE_CATALOG;
06473 *valLen = sizeof (SQLSMALLINT);
06474 break;
06475 case SQL_GROUP_BY:
06476 *((SQLSMALLINT *) val) = 0;
06477 *valLen = sizeof (SQLSMALLINT);
06478 break;
06479 case SQL_KEYWORDS:
06480 strmak(val, "CREATE,SELECT,DROP,DELETE,UPDATE,INSERT,"
06481 "INTO,VALUES,TABLE,INDEX,FROM,SET,WHERE,AND,CURRENT,OF",
06482 valMax, valLen);
06483 break;
06484 case SQL_SPECIAL_CHARACTERS:
06485 strmak(val, "", valMax, valLen);
06486 break;
06487 case SQL_BATCH_SUPPORT:
06488 case SQL_BATCH_ROW_COUNT:
06489 case SQL_PARAM_ARRAY_ROW_COUNTS:
06490 *((SQLUINTEGER *) val) = 0;
06491 *valLen = sizeof (SQLUINTEGER);
06492 break;
06493 case SQL_FORWARD_ONLY_CURSOR_ATTRIBUTES1:
06494 *((SQLUINTEGER *) val) = SQL_CA1_NEXT | SQL_CA1_BOOKMARK;
06495 *valLen = sizeof (SQLUINTEGER);
06496 break;
06497 case SQL_STATIC_CURSOR_ATTRIBUTES1:
06498 *((SQLUINTEGER *) val) = SQL_CA1_NEXT | SQL_CA1_ABSOLUTE |
06499 SQL_CA1_RELATIVE | SQL_CA1_BOOKMARK;
06500 *valLen = sizeof (SQLUINTEGER);
06501 break;
06502 case SQL_FORWARD_ONLY_CURSOR_ATTRIBUTES2:
06503 case SQL_STATIC_CURSOR_ATTRIBUTES2:
06504 *((SQLUINTEGER *) val) = SQL_CA2_READ_ONLY_CONCURRENCY |
06505 SQL_CA2_LOCK_CONCURRENCY;
06506 *valLen = sizeof (SQLUINTEGER);
06507 break;
06508 case SQL_KEYSET_CURSOR_ATTRIBUTES1:
06509 case SQL_KEYSET_CURSOR_ATTRIBUTES2:
06510 case SQL_DYNAMIC_CURSOR_ATTRIBUTES1:
06511 case SQL_DYNAMIC_CURSOR_ATTRIBUTES2:
06512 *((SQLUINTEGER *) val) = 0;
06513 *valLen = sizeof (SQLUINTEGER);
06514 break;
06515 case SQL_ODBC_INTERFACE_CONFORMANCE:
06516 *((SQLUINTEGER *) val) = SQL_OIC_CORE;
06517 *valLen = sizeof (SQLUINTEGER);
06518 break;
06519 default:
06520 setstatd(d, -1, "unsupported info option %d",
06521 (*d->ov3) ? "HYC00" : "S1C00", type);
06522 return SQL_ERROR;
06523 }
06524 return SQL_SUCCESS;
06525 }
06526
06527 #if (defined(HAVE_UNIXODBC) && HAVE_UNIXODBC) || !defined(SQLITE_UTF8)
06528
06538 SQLRETURN SQL_API
06539 SQLGetInfo(SQLHDBC dbc, SQLUSMALLINT type, SQLPOINTER val, SQLSMALLINT valMax,
06540 SQLSMALLINT *valLen)
06541 {
06542 return drvgetinfo(dbc, type, val, valMax, valLen);
06543 }
06544 #endif
06545
06546 #ifdef SQLITE_UTF8
06547
06557 SQLRETURN SQL_API
06558 SQLGetInfoW(SQLHDBC dbc, SQLUSMALLINT type, SQLPOINTER val, SQLSMALLINT valMax,
06559 SQLSMALLINT *valLen)
06560 {
06561 SQLRETURN ret;
06562 SQLSMALLINT len;
06563
06564 ret = drvgetinfo(dbc, type, val, valMax, &len);
06565 if (ret == SQL_SUCCESS) {
06566 SQLWCHAR *v = NULL;
06567
06568 switch (type) {
06569 case SQL_USER_NAME:
06570 case SQL_DRIVER_ODBC_VER:
06571 case SQL_DATA_SOURCE_NAME:
06572 case SQL_DRIVER_NAME:
06573 case SQL_DRIVER_VER:
06574 case SQL_ODBC_VER:
06575 case SQL_SERVER_NAME:
06576 case SQL_DATABASE_NAME:
06577 case SQL_SEARCH_PATTERN_ESCAPE:
06578 case SQL_DBMS_NAME:
06579 case SQL_DBMS_VER:
06580 case SQL_NEED_LONG_DATA_LEN:
06581 case SQL_ROW_UPDATES:
06582 case SQL_ACCESSIBLE_PROCEDURES:
06583 case SQL_PROCEDURES:
06584 case SQL_EXPRESSIONS_IN_ORDERBY:
06585 case SQL_ODBC_SQL_OPT_IEF:
06586 case SQL_LIKE_ESCAPE_CLAUSE:
06587 case SQL_ORDER_BY_COLUMNS_IN_SELECT:
06588 case SQL_OUTER_JOINS:
06589 case SQL_COLUMN_ALIAS:
06590 case SQL_ACCESSIBLE_TABLES:
06591 case SQL_MULT_RESULT_SETS:
06592 case SQL_MULTIPLE_ACTIVE_TXN:
06593 case SQL_MAX_ROW_SIZE_INCLUDES_LONG:
06594 case SQL_DATA_SOURCE_READ_ONLY:
06595 #ifdef SQL_DESCRIBE_PARAMETER
06596 case SQL_DESCRIBE_PARAMETER:
06597 #endif
06598 case SQL_IDENTIFIER_QUOTE_CHAR:
06599 case SQL_OWNER_TERM:
06600 case SQL_PROCEDURE_TERM:
06601 case SQL_QUALIFIER_NAME_SEPARATOR:
06602 case SQL_QUALIFIER_TERM:
06603 case SQL_TABLE_TERM:
06604 case SQL_KEYWORDS:
06605 case SQL_SPECIAL_CHARACTERS:
06606 if (val) {
06607 if (len > 0) {
06608 v = uc_from_utf((char *) val, len);
06609 if (v) {
06610 int vmax = valMax / sizeof (SQLWCHAR);
06611
06612 uc_strncpy(val, v, vmax);
06613 len = min(vmax, uc_strlen(v));
06614 uc_free(v);
06615 len *= sizeof (SQLWCHAR);
06616 } else {
06617 len = 0;
06618 }
06619 }
06620 if (len <= 0) {
06621 len = 0;
06622 if (valMax >= sizeof (SQLWCHAR)) {
06623 *((SQLWCHAR *)val) = 0;
06624 }
06625 }
06626 } else {
06627 len = 0;
06628 }
06629 break;
06630 }
06631 if (valLen) {
06632 *valLen = len;
06633 }
06634 }
06635 return ret;
06636 }
06637 #endif
06638
06647 SQLRETURN SQL_API
06648 SQLGetFunctions(SQLHDBC dbc, SQLUSMALLINT func,
06649 SQLUSMALLINT *flags)
06650 {
06651 DBC *d;
06652 int i;
06653 SQLUSMALLINT exists[100];
06654
06655 if (dbc == SQL_NULL_HDBC) {
06656 return SQL_INVALID_HANDLE;
06657 }
06658 d = (DBC *) dbc;
06659 for (i = 0; i < array_size(exists); i++) {
06660 exists[i] = SQL_FALSE;
06661 }
06662 exists[SQL_API_SQLALLOCCONNECT] = SQL_TRUE;
06663 exists[SQL_API_SQLFETCH] = SQL_TRUE;
06664 exists[SQL_API_SQLALLOCENV] = SQL_TRUE;
06665 exists[SQL_API_SQLFREECONNECT] = SQL_TRUE;
06666 exists[SQL_API_SQLALLOCSTMT] = SQL_TRUE;
06667 exists[SQL_API_SQLFREEENV] = SQL_TRUE;
06668 exists[SQL_API_SQLBINDCOL] = SQL_TRUE;
06669 exists[SQL_API_SQLFREESTMT] = SQL_TRUE;
06670 exists[SQL_API_SQLCANCEL] = SQL_TRUE;
06671 exists[SQL_API_SQLGETCURSORNAME] = SQL_TRUE;
06672 exists[SQL_API_SQLCOLATTRIBUTES] = SQL_TRUE;
06673 exists[SQL_API_SQLNUMRESULTCOLS] = SQL_TRUE;
06674 exists[SQL_API_SQLCONNECT] = SQL_TRUE;
06675 exists[SQL_API_SQLPREPARE] = SQL_TRUE;
06676 exists[SQL_API_SQLDESCRIBECOL] = SQL_TRUE;
06677 exists[SQL_API_SQLROWCOUNT] = SQL_TRUE;
06678 exists[SQL_API_SQLDISCONNECT] = SQL_TRUE;
06679 exists[SQL_API_SQLSETCURSORNAME] = SQL_FALSE;
06680 exists[SQL_API_SQLERROR] = SQL_TRUE;
06681 exists[SQL_API_SQLSETPARAM] = SQL_TRUE;
06682 exists[SQL_API_SQLEXECDIRECT] = SQL_TRUE;
06683 exists[SQL_API_SQLTRANSACT] = SQL_TRUE;
06684 exists[SQL_API_SQLEXECUTE] = SQL_TRUE;
06685 exists[SQL_API_SQLBINDPARAMETER] = SQL_TRUE;
06686 exists[SQL_API_SQLGETTYPEINFO] = SQL_TRUE;
06687 exists[SQL_API_SQLCOLUMNS] = SQL_TRUE;
06688 exists[SQL_API_SQLPARAMDATA] = SQL_TRUE;
06689 exists[SQL_API_SQLDRIVERCONNECT] = SQL_TRUE;
06690 exists[SQL_API_SQLPUTDATA] = SQL_TRUE;
06691 exists[SQL_API_SQLGETCONNECTOPTION] = SQL_TRUE;
06692 exists[SQL_API_SQLSETCONNECTOPTION] = SQL_TRUE;
06693 exists[SQL_API_SQLGETDATA] = SQL_TRUE;
06694 exists[SQL_API_SQLSETSTMTOPTION] = SQL_TRUE;
06695 exists[SQL_API_SQLGETFUNCTIONS] = SQL_TRUE;
06696 exists[SQL_API_SQLSPECIALCOLUMNS] = SQL_TRUE;
06697 exists[SQL_API_SQLGETINFO] = SQL_TRUE;
06698 exists[SQL_API_SQLSTATISTICS] = SQL_TRUE;
06699 exists[SQL_API_SQLGETSTMTOPTION] = SQL_TRUE;
06700 exists[SQL_API_SQLTABLES] = SQL_TRUE;
06701 exists[SQL_API_SQLBROWSECONNECT] = SQL_FALSE;
06702 exists[SQL_API_SQLNUMPARAMS] = SQL_TRUE;
06703 exists[SQL_API_SQLCOLUMNPRIVILEGES] = SQL_FALSE;
06704 exists[SQL_API_SQLPARAMOPTIONS] = SQL_FALSE;
06705 exists[SQL_API_SQLDATASOURCES] = SQL_TRUE;
06706 exists[SQL_API_SQLPRIMARYKEYS] = SQL_TRUE;
06707 exists[SQL_API_SQLDESCRIBEPARAM] = SQL_TRUE;
06708 exists[SQL_API_SQLPROCEDURECOLUMNS] = SQL_TRUE;
06709 exists[SQL_API_SQLDRIVERS] = SQL_FALSE;
06710 exists[SQL_API_SQLPROCEDURES] = SQL_TRUE;
06711 exists[SQL_API_SQLEXTENDEDFETCH] = SQL_TRUE;
06712 exists[SQL_API_SQLSETPOS] = SQL_FALSE;
06713 exists[SQL_API_SQLFOREIGNKEYS] = SQL_TRUE;
06714 exists[SQL_API_SQLSETSCROLLOPTIONS] = SQL_TRUE;
06715 exists[SQL_API_SQLMORERESULTS] = SQL_TRUE;
06716 exists[SQL_API_SQLTABLEPRIVILEGES] = SQL_FALSE;
06717 exists[SQL_API_SQLNATIVESQL] = SQL_TRUE;
06718 if (func == SQL_API_ALL_FUNCTIONS) {
06719 memcpy(flags, exists, sizeof (exists));
06720 } else if (func == SQL_API_ODBC3_ALL_FUNCTIONS) {
06721 int i;
06722 #define SET_EXISTS(x) \
06723 flags[(x) >> 4] |= (1 << ((x) & 0xF))
06724 #define CLR_EXISTS(x) \
06725 flags[(x) >> 4] &= ~(1 << ((x) & 0xF))
06726
06727 memset(flags, 0,
06728 sizeof (SQLUSMALLINT) * SQL_API_ODBC3_ALL_FUNCTIONS_SIZE);
06729 for (i = 0; i < array_size(exists); i++) {
06730 if (exists[i]) {
06731 flags[i >> 4] |= (1 << (i & 0xF));
06732 }
06733 }
06734 SET_EXISTS(SQL_API_SQLALLOCHANDLE);
06735 SET_EXISTS(SQL_API_SQLFREEHANDLE);
06736 SET_EXISTS(SQL_API_SQLGETSTMTATTR);
06737 SET_EXISTS(SQL_API_SQLSETSTMTATTR);
06738 SET_EXISTS(SQL_API_SQLGETCONNECTATTR);
06739 SET_EXISTS(SQL_API_SQLSETCONNECTATTR);
06740 SET_EXISTS(SQL_API_SQLGETENVATTR);
06741 SET_EXISTS(SQL_API_SQLSETENVATTR);
06742 SET_EXISTS(SQL_API_SQLCLOSECURSOR);
06743 SET_EXISTS(SQL_API_SQLBINDPARAM);
06744 #if !defined(HAVE_UNIXODBC) || !HAVE_UNIXODBC
06745
06746
06747
06748
06749
06750 SET_EXISTS(SQL_API_SQLGETDIAGREC);
06751 #endif
06752 SET_EXISTS(SQL_API_SQLFETCHSCROLL);
06753 SET_EXISTS(SQL_API_SQLENDTRAN);
06754 } else {
06755 if (func < array_size(exists)) {
06756 *flags = exists[func];
06757 } else {
06758 switch (func) {
06759 case SQL_API_SQLALLOCHANDLE:
06760 case SQL_API_SQLFREEHANDLE:
06761 case SQL_API_SQLGETSTMTATTR:
06762 case SQL_API_SQLSETSTMTATTR:
06763 case SQL_API_SQLGETCONNECTATTR:
06764 case SQL_API_SQLSETCONNECTATTR:
06765 case SQL_API_SQLGETENVATTR:
06766 case SQL_API_SQLSETENVATTR:
06767 case SQL_API_SQLCLOSECURSOR:
06768 case SQL_API_SQLBINDPARAM:
06769 #if !defined(HAVE_UNIXODBC) || !HAVE_UNIXODBC
06770
06771
06772
06773
06774
06775 case SQL_API_SQLGETDIAGREC:
06776 #endif
06777 case SQL_API_SQLFETCHSCROLL:
06778 case SQL_API_SQLENDTRAN:
06779 *flags = SQL_TRUE;
06780 break;
06781 default:
06782 *flags = SQL_FALSE;
06783 }
06784 }
06785 }
06786 return SQL_SUCCESS;
06787 }
06788
06795 static SQLRETURN
06796 drvallocenv(SQLHENV *env)
06797 {
06798 ENV *e;
06799
06800 if (env == NULL) {
06801 return SQL_INVALID_HANDLE;
06802 }
06803 e = (ENV *) xmalloc(sizeof (ENV));
06804 if (e == NULL) {
06805 *env = SQL_NULL_HENV;
06806 return SQL_ERROR;
06807 }
06808 e->magic = ENV_MAGIC;
06809 e->ov3 = 0;
06810 e->dbcs = NULL;
06811 *env = (SQLHENV) e;
06812 return SQL_SUCCESS;
06813 }
06814
06821 SQLRETURN SQL_API
06822 SQLAllocEnv(SQLHENV *env)
06823 {
06824 return drvallocenv(env);
06825 }
06826
06833 static SQLRETURN
06834 drvfreeenv(SQLHENV env)
06835 {
06836 ENV *e;
06837
06838 if (env == SQL_NULL_HENV) {
06839 return SQL_INVALID_HANDLE;
06840 }
06841 e = (ENV *) env;
06842 if (e->magic != ENV_MAGIC) {
06843 return SQL_SUCCESS;
06844 }
06845 if (e->dbcs) {
06846 return SQL_ERROR;
06847 }
06848 e->magic = DEAD_MAGIC;
06849 xfree(e);
06850 return SQL_SUCCESS;
06851 }
06852
06859 SQLRETURN SQL_API
06860 SQLFreeEnv(SQLHENV env)
06861 {
06862 return drvfreeenv(env);
06863 }
06864
06872 static SQLRETURN
06873 drvallocconnect(SQLHENV env, SQLHDBC *dbc)
06874 {
06875 DBC *d;
06876 ENV *e;
06877 const char *verstr;
06878 int maj = 0, min = 0, lev = 0;
06879
06880 if (dbc == NULL) {
06881 return SQL_ERROR;
06882 }
06883 d = (DBC *) xmalloc(sizeof (DBC));
06884 if (d == NULL) {
06885 *dbc = SQL_NULL_HDBC;
06886 return SQL_ERROR;
06887 }
06888 memset(d, 0, sizeof (DBC));
06889 d->curtype = SQL_CURSOR_STATIC;
06890 #if HAVE_LIBVERSION
06891 verstr = sqlite_libversion();
06892 #else
06893 verstr = sqlite_version;
06894 #endif
06895 sscanf(verstr, "%d.%d.%d", &maj, &min, &lev);
06896 d->version = verinfo(maj & 0xFF, min & 0xFF, lev & 0xFF);
06897 if (d->version < verinfo(2, 8, 0)) {
06898 xfree(d);
06899 return SQL_ERROR;
06900 }
06901 d->ov3 = &d->ov3val;
06902 e = (ENV *) env;
06903 if (e->magic == ENV_MAGIC) {
06904 DBC *n, *p;
06905
06906 d->env = e;
06907 d->ov3 = &e->ov3;
06908 p = NULL;
06909 n = e->dbcs;
06910 while (n) {
06911 p = n;
06912 n = n->next;
06913 }
06914 if (p) {
06915 p->next = d;
06916 } else {
06917 e->dbcs = d;
06918 }
06919 }
06920 d->autocommit = 1;
06921 d->magic = DBC_MAGIC;
06922 *dbc = (SQLHDBC) d;
06923 drvgetgpps(d);
06924 return SQL_SUCCESS;
06925 }
06926
06934 SQLRETURN SQL_API
06935 SQLAllocConnect(SQLHENV env, SQLHDBC *dbc)
06936 {
06937 return drvallocconnect(env, dbc);
06938 }
06939
06946 static SQLRETURN
06947 drvfreeconnect(SQLHDBC dbc)
06948 {
06949 DBC *d;
06950 ENV *e;
06951
06952 if (dbc == SQL_NULL_HDBC) {
06953 return SQL_INVALID_HANDLE;
06954 }
06955 d = (DBC *) dbc;
06956 if (d->magic != DBC_MAGIC) {
06957 return SQL_INVALID_HANDLE;
06958 }
06959 if (d->sqlite) {
06960 setstatd(d, -1, "not disconnected", (*d->ov3) ? "HY000" : "S1000");
06961 return SQL_ERROR;
06962 }
06963 while (d->stmt) {
06964 freestmt((HSTMT) d->stmt);
06965 }
06966 e = d->env;
06967 if (e && e->magic == ENV_MAGIC) {
06968 DBC *n, *p;
06969
06970 p = NULL;
06971 n = e->dbcs;
06972 while (n) {
06973 if (n == d) {
06974 break;
06975 }
06976 p = n;
06977 n = n->next;
06978 }
06979 if (n) {
06980 if (p) {
06981 p->next = d->next;
06982 } else {
06983 e->dbcs = d->next;
06984 }
06985 }
06986 }
06987 drvrelgpps(d);
06988 d->magic = DEAD_MAGIC;
06989 #if defined(HAVE_SQLITETRACE) && HAVE_SQLITETRACE
06990 if (d->trace) {
06991 fclose(d->trace);
06992 }
06993 #endif
06994 xfree(d);
06995 return SQL_SUCCESS;
06996 }
06997
07004 SQLRETURN SQL_API
07005 SQLFreeConnect(SQLHDBC dbc)
07006 {
07007 return drvfreeconnect(dbc);
07008 }
07009
07020 static SQLRETURN
07021 drvgetconnectattr(SQLHDBC dbc, SQLINTEGER attr, SQLPOINTER val,
07022 SQLINTEGER bufmax, SQLINTEGER *buflen)
07023 {
07024 DBC *d;
07025 SQLINTEGER dummy;
07026
07027 if (dbc == SQL_NULL_HDBC) {
07028 return SQL_INVALID_HANDLE;
07029 }
07030 d = (DBC *) dbc;
07031 if (!val) {
07032 val = (SQLPOINTER) &dummy;
07033 }
07034 if (!buflen) {
07035 buflen = &dummy;
07036 }
07037 switch (attr) {
07038 case SQL_ATTR_CONNECTION_DEAD:
07039 *((SQLINTEGER *) val) = d->sqlite ? SQL_CD_FALSE : SQL_CD_TRUE;
07040 *buflen = sizeof (SQLINTEGER);
07041 break;
07042 case SQL_ATTR_ACCESS_MODE:
07043 *((SQLINTEGER *) val) = SQL_MODE_READ_WRITE;
07044 *buflen = sizeof (SQLINTEGER);
07045 break;
07046 case SQL_ATTR_AUTOCOMMIT:
07047 *((SQLINTEGER *) val) =
07048 d->autocommit ? SQL_AUTOCOMMIT_ON : SQL_AUTOCOMMIT_OFF;
07049 *buflen = sizeof (SQLINTEGER);
07050 break;
07051 case SQL_ATTR_LOGIN_TIMEOUT:
07052 *((SQLINTEGER *) val) = 100;
07053 *buflen = sizeof (SQLINTEGER);
07054 break;
07055 case SQL_ATTR_ODBC_CURSORS:
07056 *((SQLINTEGER *) val) = SQL_CUR_USE_DRIVER;
07057 *buflen = sizeof (SQLINTEGER);
07058 break;
07059 case SQL_ATTR_PACKET_SIZE:
07060 *((SQLINTEGER *) val) = 16384;
07061 *buflen = sizeof (SQLINTEGER);
07062 break;
07063 case SQL_ATTR_TXN_ISOLATION:
07064 *((SQLINTEGER *) val) = SQL_TXN_READ_UNCOMMITTED;
07065 *buflen = sizeof (SQLINTEGER);
07066 break;
07067 case SQL_ATTR_TRACE:
07068 case SQL_ATTR_TRACEFILE:
07069 case SQL_ATTR_QUIET_MODE:
07070 case SQL_ATTR_TRANSLATE_OPTION:
07071 case SQL_ATTR_KEYSET_SIZE:
07072 case SQL_ATTR_QUERY_TIMEOUT:
07073 case SQL_ATTR_PARAM_BIND_TYPE:
07074 case SQL_ATTR_CURRENT_CATALOG:
07075 *((SQLINTEGER *) val) = 0;
07076 *buflen = sizeof (SQLINTEGER);
07077 break;
07078 case SQL_ATTR_ROW_BIND_TYPE:
07079 *((SQLUINTEGER *) val) = SQL_BIND_BY_COLUMN;
07080 *buflen = sizeof (SQLUINTEGER);
07081 break;
07082 case SQL_ATTR_USE_BOOKMARKS:
07083 *((SQLINTEGER *) val) = SQL_UB_OFF;
07084 *buflen = sizeof (SQLINTEGER);
07085 break;
07086 case SQL_ATTR_ASYNC_ENABLE:
07087 *((SQLINTEGER *) val) = SQL_ASYNC_ENABLE_OFF;
07088 *buflen = sizeof (SQLINTEGER);
07089 break;
07090 case SQL_ATTR_NOSCAN:
07091 *((SQLINTEGER *) val) = SQL_NOSCAN_ON;
07092 *buflen = sizeof (SQLINTEGER);
07093 break;
07094 case SQL_ATTR_CONCURRENCY:
07095 *((SQLINTEGER *) val) = SQL_CONCUR_LOCK;
07096 *buflen = sizeof (SQLINTEGER);
07097 break;
07098 case SQL_ATTR_SIMULATE_CURSOR:
07099 *((SQLINTEGER *) val) = SQL_SC_NON_UNIQUE;
07100 *buflen = sizeof (SQLINTEGER);
07101 break;
07102 case SQL_ATTR_MAX_ROWS:
07103 case SQL_ATTR_MAX_LENGTH:
07104 *((SQLINTEGER *) val) = 1000000000;
07105 *buflen = sizeof (SQLINTEGER);
07106 break;
07107 case SQL_ATTR_CURSOR_TYPE:
07108 *((SQLINTEGER *) val) = d->curtype;
07109 *buflen = sizeof (SQLINTEGER);
07110 break;
07111 case SQL_ATTR_RETRIEVE_DATA:
07112 *((SQLINTEGER *) val) = SQL_RD_ON;
07113 *buflen = sizeof (SQLINTEGER);
07114 break;
07115 default:
07116 *((SQLINTEGER *) val) = 0;
07117 *buflen = sizeof (SQLINTEGER);
07118 setstatd(d, -1, "unsupported connect attribute %d",
07119 (*d->ov3) ? "HYC00" : "S1C00", (int) attr);
07120 return SQL_ERROR;
07121 }
07122 return SQL_SUCCESS;
07123 }
07124
07125 #ifndef SQLITE_UTF8
07126
07136 SQLRETURN SQL_API
07137 SQLGetConnectAttr(SQLHDBC dbc, SQLINTEGER attr, SQLPOINTER val,
07138 SQLINTEGER bufmax, SQLINTEGER *buflen)
07139 {
07140 return drvgetconnectattr(dbc, attr, val, bufmax, buflen);
07141 }
07142 #endif
07143
07144 #ifdef SQLITE_UTF8
07145
07155 SQLRETURN SQL_API
07156 SQLGetConnectAttrW(SQLHDBC dbc, SQLINTEGER attr, SQLPOINTER val,
07157 SQLINTEGER bufmax, SQLINTEGER *buflen)
07158 {
07159 return drvgetconnectattr(dbc, attr, val, bufmax, buflen);
07160 }
07161 #endif
07162
07172 static SQLRETURN
07173 drvsetconnectattr(SQLHDBC dbc, SQLINTEGER attr, SQLPOINTER val,
07174 SQLINTEGER len)
07175 {
07176 DBC *d;
07177
07178 if (dbc == SQL_NULL_HDBC) {
07179 return SQL_INVALID_HANDLE;
07180 }
07181 d = (DBC *) dbc;
07182 switch (attr) {
07183 case SQL_AUTOCOMMIT:
07184 if (len == SQL_IS_INTEGER) {
07185 d->autocommit = (SQLINTEGER) val == SQL_AUTOCOMMIT_ON;
07186 goto doit;
07187 }
07188 if (val && len >= sizeof (SQLINTEGER)) {
07189 d->autocommit = *((SQLINTEGER *) val) == SQL_AUTOCOMMIT_ON;
07190 doit:
07191 if (d->autocommit && d->intrans) {
07192 return endtran(d, SQL_COMMIT);
07193 } else if (!d->autocommit) {
07194 vm_end(d->vm_stmt);
07195 }
07196 }
07197 break;
07198 default:
07199 setstatd(d, -1, "option value changed", "01S02");
07200 return SQL_SUCCESS_WITH_INFO;
07201 }
07202 return SQL_SUCCESS;
07203 }
07204
07205 #ifndef SQLITE_UTF8
07206
07215 SQLRETURN SQL_API
07216 SQLSetConnectAttr(SQLHDBC dbc, SQLINTEGER attr, SQLPOINTER val,
07217 SQLINTEGER len)
07218 {
07219 return drvsetconnectattr(dbc, attr, val, len);
07220 }
07221 #endif
07222
07223 #ifdef SQLITE_UTF8
07224
07233 SQLRETURN SQL_API
07234 SQLSetConnectAttrW(SQLHDBC dbc, SQLINTEGER attr, SQLPOINTER val,
07235 SQLINTEGER len)
07236 {
07237 return drvsetconnectattr(dbc, attr, val, len);
07238 }
07239 #endif
07240
07249 static SQLRETURN
07250 drvgetconnectoption(SQLHDBC dbc, SQLUSMALLINT opt, SQLPOINTER param)
07251 {
07252 DBC *d;
07253 SQLINTEGER dummy;
07254
07255 if (dbc == SQL_NULL_HDBC) {
07256 return SQL_INVALID_HANDLE;
07257 }
07258 d = (DBC *) dbc;
07259 if (!param) {
07260 param = (SQLPOINTER) &dummy;
07261 }
07262 switch (opt) {
07263 case SQL_ACCESS_MODE:
07264 *((SQLINTEGER *) param) = SQL_MODE_READ_WRITE;
07265 break;
07266 case SQL_AUTOCOMMIT:
07267 *((SQLINTEGER *) param) =
07268 d->autocommit ? SQL_AUTOCOMMIT_ON : SQL_AUTOCOMMIT_OFF;
07269 break;
07270 case SQL_LOGIN_TIMEOUT:
07271 *((SQLINTEGER *) param) = 100;
07272 break;
07273 case SQL_ODBC_CURSORS:
07274 *((SQLINTEGER *) param) = SQL_CUR_USE_DRIVER;
07275 break;
07276 case SQL_PACKET_SIZE:
07277 *((SQLINTEGER *) param) = 16384;
07278 break;
07279 case SQL_TXN_ISOLATION:
07280 *((SQLINTEGER *) param) = SQL_TXN_READ_UNCOMMITTED;
07281 break;
07282 case SQL_OPT_TRACE:
07283 case SQL_OPT_TRACEFILE:
07284 case SQL_QUIET_MODE:
07285 case SQL_TRANSLATE_DLL:
07286 case SQL_TRANSLATE_OPTION:
07287 case SQL_KEYSET_SIZE:
07288 case SQL_QUERY_TIMEOUT:
07289 case SQL_BIND_TYPE:
07290 case SQL_CURRENT_QUALIFIER:
07291 *((SQLINTEGER *) param) = 0;
07292 break;
07293 case SQL_USE_BOOKMARKS:
07294 *((SQLINTEGER *) param) = SQL_UB_OFF;
07295 break;
07296 case SQL_ASYNC_ENABLE:
07297 *((SQLINTEGER *) param) = SQL_ASYNC_ENABLE_OFF;
07298 break;
07299 case SQL_NOSCAN:
07300 *((SQLINTEGER *) param) = SQL_NOSCAN_ON;
07301 break;
07302 case SQL_CONCURRENCY:
07303 *((SQLINTEGER *) param) = SQL_CONCUR_LOCK;
07304 break;
07305 case SQL_SIMULATE_CURSOR:
07306 *((SQLINTEGER *) param) = SQL_SC_NON_UNIQUE;
07307 break;
07308 case SQL_ROWSET_SIZE:
07309 case SQL_MAX_ROWS:
07310 case SQL_MAX_LENGTH:
07311 *((SQLINTEGER *) param) = 1000000000;
07312 break;
07313 case SQL_CURSOR_TYPE:
07314 *((SQLINTEGER *) param) = d->curtype;
07315 break;
07316 case SQL_RETRIEVE_DATA:
07317 *((SQLINTEGER *) param) = SQL_RD_ON;
07318 break;
07319 default:
07320 *((SQLINTEGER *) param) = 0;
07321 setstatd(d, -1, "unsupported connect option %d",
07322 (*d->ov3) ? "HYC00" : "S1C00", opt);
07323 return SQL_ERROR;
07324 }
07325 return SQL_SUCCESS;
07326 }
07327
07328 #ifndef SQLITE_UTF8
07329
07337 SQLRETURN SQL_API
07338 SQLGetConnectOption(SQLHDBC dbc, SQLUSMALLINT opt, SQLPOINTER param)
07339 {
07340 return drvgetconnectoption(dbc, opt, param);
07341 }
07342 #endif
07343
07344 #ifdef SQLITE_UTF8
07345
07353 SQLRETURN SQL_API
07354 SQLGetConnectOptionW(SQLHDBC dbc, SQLUSMALLINT opt, SQLPOINTER param)
07355 {
07356 return drvgetconnectoption(dbc, opt, param);
07357 }
07358 #endif
07359
07368 static SQLRETURN
07369 drvsetconnectoption(SQLHDBC dbc, SQLUSMALLINT opt, SQLUINTEGER param)
07370 {
07371 DBC *d;
07372
07373 if (dbc == SQL_NULL_HDBC) {
07374 return SQL_INVALID_HANDLE;
07375 }
07376 d = (DBC *) dbc;
07377 switch (opt) {
07378 case SQL_AUTOCOMMIT:
07379 d->autocommit = param == SQL_AUTOCOMMIT_ON;
07380 if (d->autocommit && d->intrans) {
07381 return endtran(d, SQL_COMMIT);
07382 } else if (!d->autocommit) {
07383 vm_end(d->vm_stmt);
07384 }
07385 break;
07386 default:
07387 setstatd(d, -1, "option value changed", "01S02");
07388 return SQL_SUCCESS_WITH_INFO;
07389 }
07390 return SQL_SUCCESS;
07391 }
07392
07393 #ifndef SQLITE_UTF8
07394
07402 SQLRETURN SQL_API
07403 SQLSetConnectOption(SQLHDBC dbc, SQLUSMALLINT opt, SQLUINTEGER param)
07404 {
07405 return drvsetconnectoption(dbc, opt, param);
07406 }
07407 #endif
07408
07409 #ifdef SQLITE_UTF8
07410
07418 SQLRETURN SQL_API
07419 SQLSetConnectOptionW(SQLHDBC dbc, SQLUSMALLINT opt, SQLUINTEGER param)
07420 {
07421 return drvsetconnectoption(dbc, opt, param);
07422 }
07423 #endif
07424
07425 #if defined(WITHOUT_DRIVERMGR) || !defined(_WIN32)
07426
07437 static int
07438 getdsnattr(char *dsn, char *attr, char *out, int outLen)
07439 {
07440 char *str = dsn, *start;
07441 int len = strlen(attr);
07442
07443 while (*str) {
07444 while (*str && *str == ';') {
07445 ++str;
07446 }
07447 start = str;
07448 if ((str = strchr(str, '=')) == NULL) {
07449 return 0;
07450 }
07451 if (str - start == len &&
07452 #ifdef _WIN32
07453 _strnicmp(start, attr, len) == 0
07454 #else
07455 strncasecmp(start, attr, len) == 0
07456 #endif
07457 ) {
07458 start = ++str;
07459 while (*str && *str != ';') {
07460 ++str;
07461 }
07462 len = min(outLen - 1, str - start);
07463 strncpy(out, start, len);
07464 out[len] = '\0';
07465 return 1;
07466 }
07467 while (*str && *str != ';') {
07468 ++str;
07469 }
07470 }
07471 return 0;
07472 }
07473 #endif
07474
07483 static SQLRETURN
07484 drvconnect(SQLHDBC dbc, SQLCHAR *dsn, SQLSMALLINT dsnLen)
07485 {
07486 DBC *d;
07487 int len;
07488 char buf[SQL_MAX_MESSAGE_LENGTH], dbname[SQL_MAX_MESSAGE_LENGTH / 4];
07489 char busy[SQL_MAX_MESSAGE_LENGTH / 4];
07490 char sflag[32], nwflag[32];
07491 #if defined(HAVE_SQLITETRACE) && HAVE_SQLITETRACE
07492 char tracef[SQL_MAX_MESSAGE_LENGTH];
07493 #endif
07494
07495 if (dbc == SQL_NULL_HDBC) {
07496 return SQL_INVALID_HANDLE;
07497 }
07498 d = (DBC *) dbc;
07499 if (d->magic != DBC_MAGIC) {
07500 return SQL_INVALID_HANDLE;
07501 }
07502 if (d->sqlite != NULL) {
07503 setstatd(d, -1, "connection already established", "08002");
07504 return SQL_ERROR;
07505 }
07506 buf[0] = '\0';
07507 if (dsnLen == SQL_NTS) {
07508 len = sizeof (buf) - 1;
07509 } else {
07510 len = min(sizeof (buf) - 1, dsnLen);
07511 }
07512 if (dsn != NULL) {
07513 strncpy(buf, dsn, len);
07514 }
07515 buf[len] = '\0';
07516 if (buf[0] == '\0') {
07517 setstatd(d, -1, "invalid DSN", (*d->ov3) ? "HY090" : "S1090");
07518 return SQL_ERROR;
07519 }
07520 busy[0] = '\0';
07521 dbname[0] = '\0';
07522 #ifdef WITHOUT_DRIVERMGR
07523 getdsnattr(buf, "database", dbname, sizeof (dbname));
07524 if (dbname[0] == '\0') {
07525 strncpy(dbname, buf, sizeof (dbname));
07526 dbname[sizeof (dbname) - 1] = '\0';
07527 }
07528 getdsnattr(buf, "timeout", busy, sizeof (busy));
07529 sflag[0] = '\0';
07530 nwflag[0] = '\0';
07531 getdsnattr(buf, "stepapi", sflag, sizeof (sflag));
07532 getdsnattr(buf, "nowchar", nwflag, sizeof (nwflag));
07533 #else
07534 SQLGetPrivateProfileString(buf, "timeout", "1000",
07535 busy, sizeof (busy), ODBC_INI);
07536 SQLGetPrivateProfileString(buf, "database", "",
07537 dbname, sizeof (dbname), ODBC_INI);
07538 SQLGetPrivateProfileString(buf, "stepapi", "",
07539 sflag, sizeof (sflag), ODBC_INI);
07540 SQLGetPrivateProfileString(buf, "nowchar", "",
07541 nwflag, sizeof (nwflag), ODBC_INI);
07542 #endif
07543 #if defined(HAVE_SQLITETRACE) && HAVE_SQLITETRACE
07544 tracef[0] = '\0';
07545 #ifdef WITHOUT_DRIVERMGR
07546 getdsnattr(buf, "tracefile", tracef, sizeof (tracef));
07547 #else
07548 SQLGetPrivateProfileString(buf, "tracefile", "",
07549 tracef, sizeof (tracef), ODBC_INI);
07550 #endif
07551 if (tracef[0] != '\0') {
07552 d->trace = fopen(tracef, "a");
07553 }
07554 #endif
07555 d->nowchar = getbool(nwflag);
07556 return dbopen(d, dbname, dsn, sflag, busy);
07557 }
07558
07559 #ifndef SQLITE_UTF8
07560
07572 SQLRETURN SQL_API
07573 SQLConnect(SQLHDBC dbc, SQLCHAR *dsn, SQLSMALLINT dsnLen,
07574 SQLCHAR *uid, SQLSMALLINT uidLen,
07575 SQLCHAR *pass, SQLSMALLINT passLen)
07576 {
07577 return drvconnect(dbc, dsn, dsnLen);
07578 }
07579 #endif
07580
07581 #ifdef SQLITE_UTF8
07582
07594 SQLRETURN SQL_API
07595 SQLConnectW(SQLHDBC dbc, SQLWCHAR *dsn, SQLSMALLINT dsnLen,
07596 SQLWCHAR *uid, SQLSMALLINT uidLen,
07597 SQLWCHAR *pass, SQLSMALLINT passLen)
07598 {
07599 char *dsna = NULL;
07600 SQLRETURN ret;
07601
07602 if (dsn) {
07603 dsna = uc_to_utf_c(dsn, dsnLen);
07604 if (!dsna) {
07605 DBC *d = (DBC *) dbc;
07606
07607 setstatd(d, -1, "out of memory", (*d->ov3) ? "HY000" : "S1000");
07608 return SQL_ERROR;
07609 }
07610 }
07611 ret = drvconnect(dbc, dsna, SQL_NTS);
07612 uc_free(dsna);
07613 return ret;
07614 }
07615 #endif
07616
07623 SQLRETURN SQL_API
07624 SQLDisconnect(SQLHDBC dbc)
07625 {
07626 DBC *d;
07627
07628 if (dbc == SQL_NULL_HDBC) {
07629 return SQL_INVALID_HANDLE;
07630 }
07631 d = (DBC *) dbc;
07632 if (d->magic != DBC_MAGIC) {
07633 return SQL_INVALID_HANDLE;
07634 }
07635 if (d->intrans) {
07636 setstatd(d, -1, "incomplete transaction", "25000");
07637 return SQL_ERROR;
07638 }
07639 if (d->vm_stmt) {
07640 vm_end(d->vm_stmt);
07641 }
07642 if (d->sqlite) {
07643 sqlite_close(d->sqlite);
07644 d->sqlite = NULL;
07645 }
07646 freep(&d->dbname);
07647 freep(&d->dsn);
07648 return SQL_SUCCESS;
07649 }
07650
07651 #if defined(WITHOUT_DRIVERMGR) || !defined(_WIN32)
07652
07666 static SQLRETURN
07667 drvdriverconnect(SQLHDBC dbc, SQLHWND hwnd,
07668 SQLCHAR *connIn, SQLSMALLINT connInLen,
07669 SQLCHAR *connOut, SQLSMALLINT connOutMax,
07670 SQLSMALLINT *connOutLen, SQLUSMALLINT drvcompl)
07671 {
07672 DBC *d;
07673 int len;
07674 char buf[SQL_MAX_MESSAGE_LENGTH], dbname[SQL_MAX_MESSAGE_LENGTH / 4];
07675 char dsn[SQL_MAX_MESSAGE_LENGTH / 4], busy[SQL_MAX_MESSAGE_LENGTH / 4];
07676 char sflag[32];
07677 #if defined(HAVE_SQLITETRACE) && HAVE_SQLITETRACE
07678 char tracef[SQL_MAX_MESSAGE_LENGTH];
07679 #endif
07680
07681 if (dbc == SQL_NULL_HDBC || hwnd != NULL) {
07682 return SQL_INVALID_HANDLE;
07683 }
07684 if (drvcompl != SQL_DRIVER_COMPLETE &&
07685 drvcompl != SQL_DRIVER_COMPLETE_REQUIRED &&
07686 drvcompl != SQL_DRIVER_PROMPT &&
07687 drvcompl != SQL_DRIVER_NOPROMPT) {
07688 return SQL_NO_DATA;
07689 }
07690 d = (DBC *) dbc;
07691 if (d->sqlite) {
07692 setstatd(d, -1, "connection already established", "08002");
07693 return SQL_ERROR;
07694 }
07695 buf[0] = '\0';
07696 if (connInLen == SQL_NTS) {
07697 len = sizeof (buf) - 1;
07698 } else {
07699 len = min(connInLen, sizeof (buf) - 1);
07700 }
07701 if (connIn != NULL) {
07702 strncpy(buf, connIn, len);
07703 }
07704 buf[len] = '\0';
07705 if (!buf[0]) {
07706 setstatd(d, -1, "invalid connect attributes",
07707 (*d->ov3) ? "HY090" : "S1090");
07708 return SQL_ERROR;
07709 }
07710 dsn[0] = '\0';
07711 getdsnattr(buf, "DSN", dsn, sizeof (dsn));
07712
07713
07714 if (!dsn[0] && !strchr(buf, ';') && !strchr(buf, '=')) {
07715 strncpy(dsn, buf, sizeof (dsn) - 1);
07716 dsn[sizeof (dsn) - 1] = '\0';
07717 }
07718
07719 busy[0] = '\0';
07720 getdsnattr(buf, "timeout", busy, sizeof (busy));
07721 #ifndef WITHOUT_DRIVERMGR
07722 if (dsn[0] && !busy[0]) {
07723 SQLGetPrivateProfileString(dsn, "timeout", "1000",
07724 busy, sizeof (busy), ODBC_INI);
07725 }
07726 #endif
07727 dbname[0] = '\0';
07728 getdsnattr(buf, "database", dbname, sizeof (dbname));
07729 #ifndef WITHOUT_DRIVERMGR
07730 if (dsn[0] && !dbname[0]) {
07731 SQLGetPrivateProfileString(dsn, "database", "",
07732 dbname, sizeof (dbname), ODBC_INI);
07733 }
07734 #endif
07735 sflag[0] = '\0';
07736 getdsnattr(buf, "stepapi", sflag, sizeof (sflag));
07737 #ifndef WITHOUT_DRIVERMGR
07738 if (dsn[0] && !sflag[0]) {
07739 SQLGetPrivateProfileString(dsn, "stepapi", "",
07740 sflag, sizeof (sflag), ODBC_INI);
07741 }
07742 #endif
07743 if (!dbname[0] && !dsn[0]) {
07744 strcpy(dsn, "SQLite");
07745 strncpy(dbname, buf, sizeof (dbname));
07746 dbname[sizeof (dbname) - 1] = '\0';
07747 }
07748 #if defined(HAVE_SQLITETRACE) && HAVE_SQLITETRACE
07749 tracef[0] = '\0';
07750 getdsnattr(buf, "tracefile", tracef, sizeof (tracef));
07751 #ifndef WITHOUT_DRIVERMGR
07752 if (dsn[0] && !tracef[0]) {
07753 SQLGetPrivateProfileString(dsn, "tracefile", "",
07754 tracef, sizeof (tracef), ODBC_INI);
07755 }
07756 #endif
07757 #endif
07758 if (connOut || connOutLen) {
07759 int count;
07760
07761 buf[0] = '\0';
07762 count = snprintf(buf, sizeof (buf),
07763 #if defined(HAVE_SQLITETRACE) && HAVE_SQLITETRACE
07764 "DSN=%s;Database=%s;StepAPI=%s;Timeout=%s;"
07765 "Tracefile=%s",
07766 dsn, dbname, sflag, busy, tracef
07767 #else
07768 "DSN=%s;Database=%s;StepAPI=%s;Timeout=%s",
07769 dsn, dbname, sflag, busy
07770 #endif
07771 );
07772 if (count < 0) {
07773 buf[sizeof (buf) - 1] = '\0';
07774 }
07775 len = min(connOutMax - 1, strlen(buf));
07776 if (connOut) {
07777 strncpy(connOut, buf, len);
07778 connOut[len] = '\0';
07779 }
07780 if (connOutLen) {
07781 *connOutLen = len;
07782 }
07783 }
07784 #if defined(HAVE_SQLITETRACE) && HAVE_SQLITETRACE
07785 if (tracef[0] != '\0') {
07786 d->trace = fopen(tracef, "a");
07787 }
07788 #endif
07789 return dbopen(d, dbname, dsn, sflag, busy);
07790 }
07791 #endif
07792
07793
07794
07795 static SQLRETURN
07796 freestmt(SQLHSTMT stmt)
07797 {
07798 STMT *s;
07799 DBC *d;
07800
07801 if (stmt == SQL_NULL_HSTMT) {
07802 return SQL_INVALID_HANDLE;
07803 }
07804 s = (STMT *) stmt;
07805 freeresult(s, 1);
07806 freep(&s->query);
07807 d = (DBC *) s->dbc;
07808 if (d && d->magic == DBC_MAGIC) {
07809 STMT *p, *n;
07810
07811 p = NULL;
07812 n = d->stmt;
07813 while (n) {
07814 if (n == s) {
07815 break;
07816 }
07817 p = n;
07818 n = n->next;
07819 }
07820 if (n) {
07821 if (p) {
07822 p->next = s->next;
07823 } else {
07824 d->stmt = s->next;
07825 }
07826 }
07827 }
07828 freeparams(s);
07829 freep(&s->bindparms);
07830 if (s->row_status0 != &s->row_status1) {
07831 freep(&s->row_status0);
07832 s->rowset_size = 1;
07833 s->row_status0 = &s->row_status1;
07834 }
07835 xfree(s);
07836 return SQL_SUCCESS;
07837 }
07838
07846 static SQLRETURN
07847 drvallocstmt(SQLHDBC dbc, SQLHSTMT *stmt)
07848 {
07849 DBC *d;
07850 STMT *s, *sl, *pl;
07851
07852 if (dbc == SQL_NULL_HDBC) {
07853 return SQL_INVALID_HANDLE;
07854 }
07855 d = (DBC *) dbc;
07856 if (d->magic != DBC_MAGIC || stmt == NULL) {
07857 return SQL_INVALID_HANDLE;
07858 }
07859 s = (STMT *) xmalloc(sizeof (STMT));
07860 if (s == NULL) {
07861 *stmt = SQL_NULL_HSTMT;
07862 return SQL_ERROR;
07863 }
07864 *stmt = (SQLHSTMT) s;
07865 memset(s, 0, sizeof (STMT));
07866 s->dbc = dbc;
07867 s->ov3 = d->ov3;
07868 s->nowchar = d->nowchar;
07869 s->curtype = d->curtype;
07870 s->row_status0 = &s->row_status1;
07871 s->rowset_size = 1;
07872 s->retr_data = SQL_RD_ON;
07873 s->bind_type = SQL_BIND_BY_COLUMN;
07874 s->bind_offs = NULL;
07875 s->paramset_size = 1;
07876 sprintf(s->cursorname, "CUR_%08lX", (long) *stmt);
07877 sl = d->stmt;
07878 pl = NULL;
07879 while (sl) {
07880 pl = sl;
07881 sl = sl->next;
07882 }
07883 if (pl) {
07884 pl->next = s;
07885 } else {
07886 d->stmt = s;
07887 }
07888 return SQL_SUCCESS;
07889 }
07890
07898 SQLRETURN SQL_API
07899 SQLAllocStmt(SQLHDBC dbc, SQLHSTMT *stmt)
07900 {
07901 return drvallocstmt(dbc, stmt);
07902 }
07903
07911 static SQLRETURN
07912 drvfreestmt(SQLHSTMT stmt, SQLUSMALLINT opt)
07913 {
07914 STMT *s;
07915
07916 if (stmt == SQL_NULL_HSTMT) {
07917 return SQL_INVALID_HANDLE;
07918 }
07919 s = (STMT *) stmt;
07920 switch (opt) {
07921 case SQL_RESET_PARAMS:
07922 freeparams(s);
07923 break;
07924 case SQL_UNBIND:
07925 unbindcols(s);
07926 break;
07927 case SQL_CLOSE:
07928 vm_end_if(s);
07929 freeresult(s, 0);
07930 break;
07931 case SQL_DROP:
07932 vm_end_if(s);
07933 return freestmt(stmt);
07934 default:
07935 setstat(s, -1, "unsupported option", (*s->ov3) ? "HYC00" : "S1C00");
07936 return SQL_ERROR;
07937 }
07938 return SQL_SUCCESS;
07939 }
07940
07948 SQLRETURN SQL_API
07949 SQLFreeStmt(SQLHSTMT stmt, SQLUSMALLINT opt)
07950 {
07951 return drvfreestmt(stmt, opt);
07952 }
07953
07960 SQLRETURN SQL_API
07961 SQLCancel(SQLHSTMT stmt)
07962 {
07963 return drvfreestmt(stmt, SQL_CLOSE);
07964 }
07965
07975 static SQLRETURN
07976 drvgetcursorname(SQLHSTMT stmt, SQLCHAR *cursor, SQLSMALLINT buflen,
07977 SQLSMALLINT *lenp)
07978 {
07979 STMT *s;
07980
07981 if (stmt == SQL_NULL_HSTMT) {
07982 return SQL_INVALID_HANDLE;
07983 }
07984 s = (STMT *) stmt;
07985 if (lenp && !cursor) {
07986 *lenp = strlen(s->cursorname);
07987 return SQL_SUCCESS;
07988 }
07989 if (cursor) {
07990 if (buflen > 0) {
07991 strncpy(cursor, s->cursorname, buflen - 1);
07992 cursor[buflen - 1] = '\0';
07993 }
07994 if (lenp) {
07995 *lenp = min(strlen(s->cursorname), buflen - 1);
07996 }
07997 }
07998 return SQL_SUCCESS;
07999 }
08000
08001 #ifndef SQLITE_UTF8
08002
08011 SQLRETURN SQL_API
08012 SQLGetCursorName(SQLHSTMT stmt, SQLCHAR *cursor, SQLSMALLINT buflen,
08013 SQLSMALLINT *lenp)
08014 {
08015 return drvgetcursorname(stmt, cursor, buflen, lenp);
08016 }
08017 #endif
08018
08019 #ifdef SQLITE_UTF8
08020
08029 SQLRETURN SQL_API
08030 SQLGetCursorNameW(SQLHSTMT stmt, SQLWCHAR *cursor, SQLSMALLINT buflen,
08031 SQLSMALLINT *lenp)
08032 {
08033 SQLRETURN ret;
08034 SQLSMALLINT len;
08035
08036 ret = drvgetcursorname(stmt, (SQLCHAR *) cursor, buflen, &len);
08037 if (ret == SQL_SUCCESS) {
08038 SQLWCHAR *c = NULL;
08039
08040 if (cursor) {
08041 c = uc_from_utf((char *) cursor, len);
08042 if (!c) {
08043 return nomem((STMT *) stmt);
08044 }
08045 len = uc_strlen(c);
08046 if (buflen > 0) {
08047 uc_strncpy(cursor, c, buflen - 1);
08048 cursor[buflen - 1] = 0;
08049 }
08050 uc_free(c);
08051 }
08052 if (lenp) {
08053 *lenp = min(len, buflen - 1);
08054 }
08055 }
08056 return ret;
08057 }
08058 #endif
08059
08068 static SQLRETURN
08069 drvsetcursorname(SQLHSTMT stmt, SQLCHAR *cursor, SQLSMALLINT len)
08070 {
08071 STMT *s;
08072
08073 if (stmt == SQL_NULL_HSTMT) {
08074 return SQL_INVALID_HANDLE;
08075 }
08076 s = (STMT *) stmt;
08077 if (!cursor ||
08078 !((cursor[0] >= 'A' && cursor[0] <= 'Z') ||
08079 (cursor[0] >= 'a' && cursor[0] <= 'z'))) {
08080 setstat(s, -1, "invalid cursor name", (*s->ov3) ? "HYC00" : "S1C00");
08081 return SQL_ERROR;
08082 }
08083 if (len == SQL_NTS) {
08084 len = sizeof (s->cursorname) - 1;
08085 } else {
08086 len = min(sizeof (s->cursorname) - 1, len);
08087 }
08088 strncpy(s->cursorname, cursor, len);
08089 s->cursorname[len] = '\0';
08090 return SQL_SUCCESS;
08091 }
08092
08093 #ifndef SQLITE_UTF8
08094
08102 SQLRETURN SQL_API
08103 SQLSetCursorName(SQLHSTMT stmt, SQLCHAR *cursor, SQLSMALLINT len)
08104 {
08105 return drvsetcursorname(stmt, cursor, len);
08106 }
08107 #endif
08108
08109 #ifdef SQLITE_UTF8
08110
08118 SQLRETURN SQL_API
08119 SQLSetCursorNameW(SQLHSTMT stmt, SQLWCHAR *cursor, SQLSMALLINT len)
08120 {
08121 char *c = NULL;
08122 SQLRETURN ret;
08123
08124 if (cursor) {
08125 c = uc_to_utf_c(cursor, len);
08126 if (!c) {
08127 return nomem((STMT *) stmt);
08128 }
08129 }
08130 ret = drvsetcursorname(stmt, c, SQL_NTS);
08131 uc_free(c);
08132 return ret;
08133 }
08134 #endif
08135
08142 SQLRETURN SQL_API
08143 SQLCloseCursor(SQLHSTMT stmt)
08144 {
08145 return drvfreestmt(stmt, SQL_CLOSE);
08146 }
08147
08148 #if defined(WITHOUT_DRIVERMGR) || !defined(HAVE_IODBC) || defined(_WIN32)
08149
08158 SQLRETURN SQL_API
08159 SQLAllocHandle(SQLSMALLINT type, SQLHANDLE input, SQLHANDLE *output)
08160 {
08161 SQLRETURN ret;
08162
08163 switch (type) {
08164 case SQL_HANDLE_ENV:
08165 ret = drvallocenv((SQLHENV *) output);
08166 if (ret == SQL_SUCCESS) {
08167 ENV *e = (ENV *) *output;
08168
08169 if (e && e->magic == ENV_MAGIC) {
08170 e->ov3 = 1;
08171 }
08172 }
08173 return ret;
08174 case SQL_HANDLE_DBC:
08175 return drvallocconnect((SQLHENV) input, (SQLHDBC *) output);
08176 case SQL_HANDLE_STMT:
08177 return drvallocstmt((SQLHDBC) input, (SQLHSTMT *) output);
08178 }
08179 return SQL_ERROR;
08180 }
08181 #endif
08182
08183 #if defined(WITHOUT_DRIVERMGR) || !defined(HAVE_IODBC) || defined(_WIN32)
08184
08192 SQLRETURN SQL_API
08193 SQLFreeHandle(SQLSMALLINT type, SQLHANDLE h)
08194 {
08195 switch (type) {
08196 case SQL_HANDLE_ENV:
08197 return drvfreeenv((SQLHENV) h);
08198 case SQL_HANDLE_DBC:
08199 return drvfreeconnect((SQLHDBC) h);
08200 case SQL_HANDLE_STMT:
08201 return drvfreestmt((SQLHSTMT) h, SQL_DROP);
08202 }
08203 return SQL_ERROR;
08204 }
08205 #endif
08206
08212 static void
08213 freedyncols(STMT *s)
08214 {
08215 if (s->dyncols) {
08216 int i;
08217
08218 for (i = 0; i < s->dcols; i++) {
08219 freep(&s->dyncols[i].typename);
08220 }
08221 if (s->cols == s->dyncols) {
08222 s->cols = NULL;
08223 s->ncols = 0;
08224 }
08225 freep(&s->dyncols);
08226 }
08227 s->dcols = 0;
08228 }
08229
08230
08231
08232 static void
08233 freeresult(STMT *s, int clrcols)
08234 {
08235 #if HAVE_ENCDEC
08236 freep(&s->bincache);
08237 freep(&s->hexcache);
08238 s->bincell = NULL;
08239 #endif
08240 if (s->rows) {
08241 if (s->rowfree) {
08242 s->rowfree(s->rows);
08243 s->rowfree = NULL;
08244 }
08245 s->rows = NULL;
08246 }
08247 s->nrows = -1;
08248 if (clrcols > 0) {
08249 freep(&s->bindcols);
08250 s->nbindcols = 0;
08251 }
08252 if (clrcols) {
08253 freedyncols(s);
08254 s->cols = NULL;
08255 s->ncols = 0;
08256 }
08257 }
08258
08259
08260
08261 static void
08262 unbindcols(STMT *s)
08263 {
08264 int i;
08265
08266 s->bkmrkcol.type = -1;
08267 s->bkmrkcol.max = 0;
08268 s->bkmrkcol.lenp = NULL;
08269 s->bkmrkcol.valp = NULL;
08270 s->bkmrkcol.index = 0;
08271 s->bkmrkcol.offs = 0;
08272 for (i = 0; s->bindcols && i < s->nbindcols; i++) {
08273 s->bindcols[i].type = -1;
08274 s->bindcols[i].max = 0;
08275 s->bindcols[i].lenp = NULL;
08276 s->bindcols[i].valp = NULL;
08277 s->bindcols[i].index = i;
08278 s->bindcols[i].offs = 0;
08279 }
08280 }
08281
08282
08283
08284 static SQLRETURN
08285 mkbindcols(STMT *s, int ncols)
08286 {
08287 if (s->bindcols) {
08288 if (s->nbindcols < ncols) {
08289 int i;
08290 BINDCOL *bindcols =
08291 xrealloc(s->bindcols, ncols * sizeof (BINDCOL));
08292
08293 if (!bindcols) {
08294 return nomem(s);
08295 }
08296 for (i = s->nbindcols; i < ncols; i++) {
08297 bindcols[i].type = -1;
08298 bindcols[i].max = 0;
08299 bindcols[i].lenp = NULL;
08300 bindcols[i].valp = NULL;
08301 bindcols[i].index = i;
08302 bindcols[i].offs = 0;
08303 }
08304 s->bindcols = bindcols;
08305 s->nbindcols = ncols;
08306 }
08307 } else if (ncols > 0) {
08308 s->bindcols = (BINDCOL *) xmalloc(ncols * sizeof (BINDCOL));
08309 if (!s->bindcols) {
08310 return nomem(s);
08311 }
08312 s->nbindcols = ncols;
08313 unbindcols(s);
08314 }
08315 return SQL_SUCCESS;
08316 }
08317
08331 static SQLRETURN
08332 getrowdata(STMT *s, SQLUSMALLINT col, SQLSMALLINT otype,
08333 SQLPOINTER val, SQLINTEGER len, SQLINTEGER *lenp, int partial)
08334 {
08335 char **data, valdummy[16];
08336 SQLINTEGER dummy;
08337 int valnull = 0;
08338 int type = otype;
08339
08340 if (!s->rows) {
08341 return SQL_NO_DATA;
08342 }
08343 if (col >= s->ncols) {
08344 setstat(s, -1, "invalid column", (*s->ov3) ? "07009" : "S1002");
08345 return SQL_ERROR;
08346 }
08347 if (s->rowp < 0 || s->rowp >= s->nrows) {
08348 return SQL_NO_DATA;
08349 }
08350 if (s->retr_data != SQL_RD_ON) {
08351 return SQL_SUCCESS;
08352 }
08353 type = mapdeftype(type, s->cols[col].type, s->cols[col].nosign ? 1 : 0,
08354 s->nowchar);
08355 #if HAVE_ENCDEC
08356 if (otype == SQL_C_CHAR) {
08357 switch (s->cols[col].type) {
08358 case SQL_BINARY:
08359 case SQL_VARBINARY:
08360 case SQL_LONGVARBINARY:
08361 type = SQL_C_BINARY;
08362 break;
08363 }
08364 #ifdef SQLITE_UTF8
08365 } else if (otype == SQL_C_WCHAR) {
08366 switch (s->cols[col].type) {
08367 case SQL_BINARY:
08368 case SQL_VARBINARY:
08369 case SQL_LONGVARBINARY:
08370 type = SQL_C_BINARY;
08371 break;
08372 }
08373 #endif
08374 }
08375 #endif
08376 data = s->rows + s->ncols + (s->rowp * s->ncols) + col;
08377 if (!lenp) {
08378 lenp = &dummy;
08379 }
08380 if (!val) {
08381 valnull = 1;
08382 val = (SQLPOINTER) valdummy;
08383 }
08384 if (*data == NULL) {
08385 *lenp = SQL_NULL_DATA;
08386 switch (type) {
08387 case SQL_C_UTINYINT:
08388 case SQL_C_TINYINT:
08389 case SQL_C_STINYINT:
08390 *((char *) val) = 0;
08391 break;
08392 case SQL_C_USHORT:
08393 case SQL_C_SHORT:
08394 case SQL_C_SSHORT:
08395 *((short *) val) = 0;
08396 break;
08397 case SQL_C_ULONG:
08398 case SQL_C_LONG:
08399 case SQL_C_SLONG:
08400 *((long *) val) = 0;
08401 break;
08402 case SQL_C_FLOAT:
08403 *((float *) val) = 0;
08404 break;
08405 case SQL_C_DOUBLE:
08406 *((double *) val) = 0;
08407 break;
08408 case SQL_C_BINARY:
08409 case SQL_C_CHAR:
08410 #ifdef SQLITE_UTF8
08411 case SQL_C_WCHAR:
08412 if (otype == SQL_C_WCHAR) {
08413 *((SQLWCHAR *) val) = '\0';
08414 } else {
08415 *((char *) val) = '\0';
08416 }
08417 #else
08418 *((char *) val) = '\0';
08419 #endif
08420 break;
08421 #ifdef SQL_C_TYPE_DATE
08422 case SQL_C_TYPE_DATE:
08423 #endif
08424 case SQL_C_DATE:
08425 memset((DATE_STRUCT *) val, 0, sizeof (DATE_STRUCT));
08426 break;
08427 #ifdef SQL_C_TYPE_TIME
08428 case SQL_C_TYPE_TIME:
08429 #endif
08430 case SQL_C_TIME:
08431 memset((TIME_STRUCT *) val, 0, sizeof (TIME_STRUCT));
08432 break;
08433 #ifdef SQL_C_TYPE_TIMESTAMP
08434 case SQL_C_TYPE_TIMESTAMP:
08435 #endif
08436 case SQL_C_TIMESTAMP:
08437 memset((TIMESTAMP_STRUCT *) val, 0, sizeof (TIMESTAMP_STRUCT));
08438 break;
08439 default:
08440 return SQL_ERROR;
08441 }
08442 } else {
08443 char *endp = NULL;
08444
08445 switch (type) {
08446 case SQL_C_UTINYINT:
08447 case SQL_C_TINYINT:
08448 case SQL_C_STINYINT:
08449 *((char *) val) = strtol(*data, &endp, 0);
08450 if (endp && endp == *data) {
08451 *lenp = SQL_NULL_DATA;
08452 } else {
08453 *lenp = sizeof (char);
08454 }
08455 break;
08456 case SQL_C_USHORT:
08457 case SQL_C_SHORT:
08458 case SQL_C_SSHORT:
08459 *((short *) val) = strtol(*data, &endp, 0);
08460 if (endp && endp == *data) {
08461 *lenp = SQL_NULL_DATA;
08462 } else {
08463 *lenp = sizeof (short);
08464 }
08465 break;
08466 case SQL_C_ULONG:
08467 case SQL_C_LONG:
08468 case SQL_C_SLONG:
08469 *((int *) val) = strtol(*data, &endp, 0);
08470 if (endp && endp == *data) {
08471 *lenp = SQL_NULL_DATA;
08472 } else {
08473 *lenp = sizeof (int);
08474 }
08475 break;
08476 case SQL_C_FLOAT:
08477 *((float *) val) = ln_strtod(*data, &endp);
08478 if (endp && endp == *data) {
08479 *lenp = SQL_NULL_DATA;
08480 } else {
08481 *lenp = sizeof (float);
08482 }
08483 break;
08484 case SQL_C_DOUBLE:
08485 *((double *) val) = ln_strtod(*data, &endp);
08486 if (endp && endp == *data) {
08487 *lenp = SQL_NULL_DATA;
08488 } else {
08489 *lenp = sizeof (double);
08490 }
08491 break;
08492 case SQL_C_BINARY:
08493 #if HAVE_ENCDEC
08494 {
08495 int dlen, offs = 0;
08496 char *bin, *hex = NULL;
08497
08498 if (*data == s->bincell && s->bincache) {
08499 bin = s->bincache;
08500 dlen = s->binlen;
08501 } else {
08502 freep(&s->bincache);
08503 freep(&s->hexcache);
08504 s->bincell = NULL;
08505 dlen = strlen(*data);
08506 bin = xmalloc(dlen + 1);
08507 if (!bin) {
08508 return nomem(s);
08509 }
08510 dlen = sqlite_decode_binary(*data, bin);
08511 if (dlen < 0) {
08512 freep(&bin);
08513 setstat(s, -1, "error decoding binary data",
08514 (*s->ov3) ? "HY000" : "S1000");
08515 return SQL_ERROR;
08516 }
08517 s->bincache = bin;
08518 s->binlen = dlen;
08519 s->bincell = *data;
08520 }
08521 #ifdef SQLITE_UTF8
08522 if (otype == SQL_C_CHAR || otype == SQL_C_WCHAR) {
08523 #else
08524 if (otype == SQL_C_CHAR) {
08525 #endif
08526 if (s->hexcache) {
08527 hex = s->hexcache;
08528 } else {
08529 int i, k;
08530
08531 hex = xmalloc(dlen * 2 + 1);
08532 if (!hex) {
08533 return nomem(s);
08534 }
08535 for (i = 0, k = 0; i < dlen; i++) {
08536 hex[k++] = hexdigits[(bin[i] >> 4) & 0x0f];
08537 hex[k++] = hexdigits[bin[i] & 0x0f];
08538 }
08539 hex[k] = '\0';
08540 s->hexcache = hex;
08541 }
08542 }
08543 if (otype == SQL_C_CHAR) {
08544 bin = hex;
08545 dlen = dlen * 2;
08546 }
08547 #ifdef SQLITE_UTF8
08548 else if (otype == SQL_C_WCHAR) {
08549 bin = hex;
08550 dlen = dlen * 2 * sizeof (SQLWCHAR);
08551 }
08552 #endif
08553 if (partial && len && s->bindcols) {
08554 if (dlen && s->bindcols[col].offs >= dlen) {
08555 s->bindcols[col].offs = 0;
08556 return SQL_NO_DATA;
08557 }
08558 offs = s->bindcols[col].offs;
08559 dlen -= offs;
08560 }
08561 if (val && !valnull && len) {
08562 int max = min(len, dlen);
08563
08564 #ifdef SQLITE_UTF8
08565 if (otype == SQL_C_WCHAR) {
08566 int i;
08567 SQLWCHAR *valw = (SQLWCHAR *) val;
08568
08569 for (i = 0; i < max; i++) {
08570 valw[i] = bin[i + offs];
08571 }
08572 } else
08573 #endif
08574 memcpy(val, bin + offs, max);
08575 }
08576 if (valnull || len < 1) {
08577 *lenp = dlen;
08578 } else {
08579 *lenp = min(len, dlen);
08580 if (*lenp == len && *lenp != dlen) {
08581 *lenp = SQL_NO_TOTAL;
08582 }
08583 }
08584 if (!valnull) {
08585 if (otype == SQL_C_CHAR) {
08586 ((char *) val)[len - 1] = '\0';
08587 }
08588 #ifdef SQLITE_UTF8
08589 else if (otype == SQL_C_WCHAR) {
08590 ((SQLWCHAR *) val)[len / sizeof (SQLWCHAR) - 1] = 0;
08591 }
08592 #endif
08593 }
08594 if (partial && len && s->bindcols) {
08595 if (*lenp == SQL_NO_TOTAL) {
08596 s->bindcols[col].offs += len;
08597 setstat(s, -1, "data right truncated", "01004");
08598 if (s->bindcols[col].lenp) {
08599 *s->bindcols[col].lenp = dlen;
08600 }
08601 return SQL_SUCCESS_WITH_INFO;
08602 }
08603 s->bindcols[col].offs += *lenp;
08604 }
08605 break;
08606 }
08607 #endif
08608 #ifdef SQLITE_UTF8
08609 case SQL_C_WCHAR:
08610 #endif
08611 case SQL_C_CHAR: {
08612 int doz;
08613 int dlen = strlen(*data);
08614 int offs = 0;
08615
08616 #ifdef SQLITE_UTF8
08617 SQLWCHAR *ucdata = NULL;
08618
08619 doz = (type == SQL_C_CHAR || type == SQL_C_WCHAR) ? 1 : 0;
08620 if (otype == SQL_C_WCHAR) {
08621 ucdata = uc_from_utf(*data, dlen);
08622 if (!ucdata) {
08623 return nomem(s);
08624 }
08625 dlen = uc_strlen(ucdata) * sizeof (SQLWCHAR);
08626 }
08627 #else
08628 doz = type == SQL_C_CHAR ? 1 : 0;
08629 #endif
08630 if (partial && len && s->bindcols) {
08631 if (dlen && s->bindcols[col].offs >= dlen) {
08632 s->bindcols[col].offs = 0;
08633 #ifdef SQLITE_UTF8
08634 uc_free(ucdata);
08635 #endif
08636 return SQL_NO_DATA;
08637 }
08638 offs = s->bindcols[col].offs;
08639 dlen -= offs;
08640 }
08641 if (val && !valnull && len) {
08642 #ifdef SQLITE_UTF8
08643 if (otype == SQL_C_WCHAR) {
08644 uc_strncpy(val, ucdata + offs / sizeof (SQLWCHAR),
08645 (len - doz) / sizeof (SQLWCHAR));
08646 } else {
08647 strncpy(val, *data + offs, len - doz);
08648 }
08649 #else
08650 strncpy(val, *data + offs, len - doz);
08651 #endif
08652 }
08653 if (valnull || len < 1) {
08654 *lenp = dlen;
08655 } else {
08656 *lenp = min(len - doz, dlen);
08657 if (*lenp == len - doz && *lenp != dlen) {
08658 *lenp = SQL_NO_TOTAL;
08659 }
08660 }
08661 if (len && !valnull && doz) {
08662 #ifdef SQLITE_UTF8
08663 if (otype == SQL_C_WCHAR) {
08664 ((SQLWCHAR *) val)[len / sizeof (SQLWCHAR) - 1] = 0;
08665 } else {
08666 ((char *) val)[len - 1] = '\0';
08667 }
08668 #else
08669 ((char *) val)[len - 1] = '\0';
08670 #endif
08671 }
08672 #ifdef SQLITE_UTF8
08673 uc_free(ucdata);
08674 #endif
08675 if (partial && len && s->bindcols) {
08676 if (*lenp == SQL_NO_TOTAL) {
08677 s->bindcols[col].offs += len - doz;
08678 setstat(s, -1, "data right truncated", "01004");
08679 if (s->bindcols[col].lenp) {
08680 *s->bindcols[col].lenp = dlen;
08681 }
08682 return SQL_SUCCESS_WITH_INFO;
08683 }
08684 s->bindcols[col].offs += *lenp;
08685 }
08686 break;
08687 }
08688 #ifdef SQL_C_TYPE_DATE
08689 case SQL_C_TYPE_DATE:
08690 #endif
08691 case SQL_C_DATE:
08692 if (str2date(*data, (DATE_STRUCT *) val) < 0) {
08693 *lenp = SQL_NULL_DATA;
08694 } else {
08695 *lenp = sizeof (DATE_STRUCT);
08696 }
08697 break;
08698 #ifdef SQL_C_TYPE_TIME
08699 case SQL_C_TYPE_TIME:
08700 #endif
08701 case SQL_C_TIME:
08702 if (str2time(*data, (TIME_STRUCT *) val) < 0) {
08703 *lenp = SQL_NULL_DATA;
08704 } else {
08705 *lenp = sizeof (TIME_STRUCT);
08706 }
08707 break;
08708 #ifdef SQL_C_TYPE_TIMESTAMP
08709 case SQL_C_TYPE_TIMESTAMP:
08710 #endif
08711 case SQL_C_TIMESTAMP:
08712 if (str2timestamp(*data, (TIMESTAMP_STRUCT *) val) < 0) {
08713 *lenp = SQL_NULL_DATA;
08714 } else {
08715 *lenp = sizeof (TIMESTAMP_STRUCT);
08716 }
08717 break;
08718 default:
08719 return SQL_ERROR;
08720 }
08721 }
08722 return SQL_SUCCESS;
08723 }
08724
08736 SQLRETURN SQL_API
08737 SQLBindCol(SQLHSTMT stmt, SQLUSMALLINT col, SQLSMALLINT type,
08738 SQLPOINTER val, SQLINTEGER max, SQLINTEGER *lenp)
08739 {
08740 STMT *s;
08741
08742 if (stmt == SQL_NULL_HSTMT) {
08743 return SQL_INVALID_HANDLE;
08744 }
08745 s = (STMT *) stmt;
08746 if (col < 1) {
08747 if (col == 0 && s->bkmrk && type == SQL_C_BOOKMARK) {
08748 s->bkmrkcol.type = type;
08749 s->bkmrkcol.max = max;
08750 s->bkmrkcol.lenp = lenp;
08751 s->bkmrkcol.valp = val;
08752 s->bkmrkcol.offs = 0;
08753 if (lenp) {
08754 *lenp = 0;
08755 }
08756 return SQL_SUCCESS;
08757 }
08758 setstat(s, -1, "invalid column", (*s->ov3) ? "07009" : "S1002");
08759 return SQL_ERROR;
08760 }
08761 if (mkbindcols(s, col) != SQL_SUCCESS) {
08762 return SQL_ERROR;
08763 }
08764 --col;
08765 if (type == SQL_C_DEFAULT) {
08766 type = mapdeftype(type, s->cols[col].type, 0, s->nowchar);
08767 } else {
08768 switch (type) {
08769 case SQL_C_LONG:
08770 case SQL_C_ULONG:
08771 case SQL_C_SLONG:
08772 case SQL_C_TINYINT:
08773 case SQL_C_UTINYINT:
08774 case SQL_C_STINYINT:
08775 case SQL_C_SHORT:
08776 case SQL_C_USHORT:
08777 case SQL_C_SSHORT:
08778 case SQL_C_FLOAT:
08779 case SQL_C_DOUBLE:
08780 case SQL_C_TIMESTAMP:
08781 case SQL_C_TIME:
08782 case SQL_C_DATE:
08783 case SQL_C_CHAR:
08784 #ifdef SQLITE_UTF8
08785 case SQL_C_WCHAR:
08786 #endif
08787 #ifdef SQL_C_TYPE_DATE
08788 case SQL_C_TYPE_DATE:
08789 #endif
08790 #ifdef SQL_C_TYPE_TIME
08791 case SQL_C_TYPE_TIME:
08792 #endif
08793 #ifdef SQL_C_TYPE_TIMESTAMP
08794 case SQL_C_TYPE_TIMESTAMP:
08795 #endif
08796 break;
08797 #if HAVE_ENCDEC
08798 case SQL_C_BINARY:
08799 break;
08800 #endif
08801 default:
08802 setstat(s, -1, "invalid type %d", "HY003", type);
08803 return SQL_ERROR;
08804 }
08805 }
08806 if (max < 0) {
08807 setstat(s, -1, "invalid length", "HY090");
08808 return SQL_ERROR;
08809 }
08810 s->bindcols[col].type = type;
08811 s->bindcols[col].max = max;
08812 s->bindcols[col].lenp = lenp;
08813 s->bindcols[col].valp = val;
08814 s->bindcols[col].offs = 0;
08815 if (lenp) {
08816 *lenp = 0;
08817 }
08818 return SQL_SUCCESS;
08819 }
08820
08825 static COL tableSpec[] = {
08826 { "SYSTEM", "COLUMN", "TABLE_QUALIFIER", SCOL_VARCHAR, 50 },
08827 { "SYSTEM", "COLUMN", "TABLE_OWNER", SCOL_VARCHAR, 50 },
08828 { "SYSTEM", "COLUMN", "TABLE_NAME", SCOL_VARCHAR, 255 },
08829 { "SYSTEM", "COLUMN", "TABLE_TYPE", SCOL_VARCHAR, 50 },
08830 { "SYSTEM", "COLUMN", "REMARKS", SCOL_VARCHAR, 50 }
08831 };
08832
08847 static SQLRETURN
08848 drvtables(SQLHSTMT stmt,
08849 SQLCHAR *cat, SQLSMALLINT catLen,
08850 SQLCHAR *schema, SQLSMALLINT schemaLen,
08851 SQLCHAR *table, SQLSMALLINT tableLen,
08852 SQLCHAR *type, SQLSMALLINT typeLen)
08853 {
08854 SQLRETURN ret;
08855 STMT *s;
08856 DBC *d;
08857 int ncols, rc;
08858 char *errp = NULL, tname[512];
08859 char *where = "(type = 'table' or type = 'view')";
08860
08861 ret = mkresultset(stmt, tableSpec, array_size(tableSpec));
08862 if (ret != SQL_SUCCESS) {
08863 return ret;
08864 }
08865 s = (STMT *) stmt;
08866 d = (DBC *) s->dbc;
08867 if (type && (typeLen > 0 || typeLen == SQL_NTS) && type[0] == '%') {
08868 int size = 3 * array_size(tableSpec);
08869
08870 s->rows = xmalloc(size * sizeof (char *));
08871 if (!s->rows) {
08872 s->nrows = 0;
08873 return nomem(s);
08874 }
08875 memset(s->rows, 0, sizeof (char *) * size);
08876 s->ncols = array_size(tableSpec);
08877 s->rows[s->ncols + 0] = "";
08878 s->rows[s->ncols + 1] = "";
08879 s->rows[s->ncols + 2] = "";
08880 s->rows[s->ncols + 3] = "TABLE";
08881 s->rows[s->ncols + 5] = "";
08882 s->rows[s->ncols + 6] = "";
08883 s->rows[s->ncols + 7] = "";
08884 s->rows[s->ncols + 8] = "VIEW";
08885 #ifdef MEMORY_DEBUG
08886 s->rowfree = xfree__;
08887 #else
08888 s->rowfree = free;
08889 #endif
08890 s->nrows = 2;
08891 s->rowp = -1;
08892 return SQL_SUCCESS;
08893 }
08894 if (cat && (catLen > 0 || catLen == SQL_NTS) && cat[0] == '%') {
08895 int size = 2 * array_size(tableSpec);
08896
08897 s->rows = xmalloc(size * sizeof (char *));
08898 if (!s->rows) {
08899 s->nrows = 0;
08900 return nomem(s);
08901 }
08902 memset(s->rows, 0, sizeof (char *) * size);
08903 s->ncols = array_size(tableSpec);
08904 s->rows[s->ncols + 0] = "";
08905 s->rows[s->ncols + 1] = "";
08906 s->rows[s->ncols + 2] = d->dbname;
08907 s->rows[s->ncols + 3] = "CATALOG";
08908 #ifdef MEMORY_DEBUG
08909 s->rowfree = xfree__;
08910 #else
08911 s->rowfree = free;
08912 #endif
08913 s->nrows = 1;
08914 s->rowp = -1;
08915 return SQL_SUCCESS;
08916 }
08917 if (schema && (schemaLen > 0 || schemaLen == SQL_NTS) &&
08918 schema[0] == '%') {
08919 if ((!cat || catLen == 0 || !cat[0]) &&
08920 (!table || tableLen == 0 || !table[0])) {
08921 int size = 2 * array_size(tableSpec);
08922
08923 s->rows = xmalloc(size * sizeof (char *));
08924 if (!s->rows) {
08925 s->nrows = 0;
08926 return nomem(s);
08927 }
08928 memset(s->rows, 0, sizeof (char *) * size);
08929 s->ncols = array_size(tableSpec);
08930 s->rows[s->ncols + 1] = "";
08931 #ifdef MEMORY_DEBUG
08932 s->rowfree = xfree__;
08933 #else
08934 s->rowfree = free;
08935 #endif
08936 s->nrows = 1;
08937 s->rowp = -1;
08938 return SQL_SUCCESS;
08939 }
08940 }
08941 if (type) {
08942 char tmp[256], *t;
08943 int with_view = 0, with_table = 0;
08944
08945 if (typeLen == SQL_NTS) {
08946 strncpy(tmp, type, sizeof (tmp));
08947 tmp[sizeof (tmp) - 1] = '\0';
08948 } else {
08949 int len = min(sizeof (tmp) - 1, typeLen);
08950
08951 strncpy(tmp, type, len);
08952 tmp[len] = '\0';
08953 }
08954 t = tmp;
08955 while (*t) {
08956 *t = TOLOWER(*t);
08957 t++;
08958 }
08959 t = tmp;
08960 while (t) {
08961 if (t[0] == '\'') {
08962 ++t;
08963 }
08964 if (strncmp(t, "table", 5) == 0) {
08965 with_table++;
08966 } else if (strncmp(t, "view", 4) == 0) {
08967 with_view++;
08968 }
08969 t = strchr(t, ',');
08970 if (t) {
08971 ++t;
08972 }
08973 }
08974 if (with_view && with_table) {
08975
08976 } else if (with_view && !with_table) {
08977 where = "type = 'view'";
08978 } else if (!with_view && with_table) {
08979 where = "type = 'table'";
08980 } else {
08981 s->rowp = -1;
08982 return SQL_SUCCESS;
08983 }
08984 }
08985 strcpy(tname, "%");
08986 if (table && (tableLen > 0 || tableLen == SQL_NTS) && table[0] != '%') {
08987 int size;
08988
08989 if (tableLen == SQL_NTS) {
08990 size = sizeof (tname) - 1;
08991 } else {
08992 size = min(sizeof (tname) - 1, tableLen);
08993 }
08994 strncpy(tname, table, size);
08995 tname[size] = '\0';
08996 }
08997 rc = sqlite_get_table_printf(d->sqlite,
08998 "select '' as 'TABLE_QUALIFIER', "
08999 "'' as 'TABLE_OWNER', "
09000 "tbl_name as 'TABLE_NAME', "
09001 "upper(type) as 'TABLE_TYPE', "
09002 "NULL as 'REMARKS' "
09003 "from sqlite_master where %s "
09004 "and tbl_name like '%q'",
09005 &s->rows, &s->nrows, &ncols, &errp,
09006 where, tname);
09007 if (rc == SQLITE_OK) {
09008 if (ncols != s->ncols) {
09009 freeresult(s, 0);
09010 s->nrows = 0;
09011 } else {
09012 s->rowfree = sqlite_free_table;
09013 }
09014 } else {
09015 s->nrows = 0;
09016 s->rows = NULL;
09017 s->rowfree = NULL;
09018 }
09019 if (errp) {
09020 sqlite_freemem(errp);
09021 errp = NULL;
09022 }
09023 s->rowp = -1;
09024 return SQL_SUCCESS;
09025 }
09026
09027 #ifndef SQLITE_UTF8
09028
09042 SQLRETURN SQL_API
09043 SQLTables(SQLHSTMT stmt,
09044 SQLCHAR *cat, SQLSMALLINT catLen,
09045 SQLCHAR *schema, SQLSMALLINT schemaLen,
09046 SQLCHAR *table, SQLSMALLINT tableLen,
09047 SQLCHAR *type, SQLSMALLINT typeLen)
09048 {
09049 return drvtables(stmt, cat, catLen, schema, schemaLen,
09050 table, tableLen, type, typeLen);
09051 }
09052 #endif
09053
09054 #ifdef SQLITE_UTF8
09055
09069 SQLRETURN SQL_API
09070 SQLTablesW(SQLHSTMT stmt,
09071 SQLWCHAR *cat, SQLSMALLINT catLen,
09072 SQLWCHAR *schema, SQLSMALLINT schemaLen,
09073 SQLWCHAR *table, SQLSMALLINT tableLen,
09074 SQLWCHAR *type, SQLSMALLINT typeLen)
09075 {
09076 char *c = NULL, *s = NULL, *t = NULL, *y = NULL;
09077 SQLRETURN ret;
09078
09079 if (cat) {
09080 c = uc_to_utf_c(cat, catLen);
09081 if (!c) {
09082 ret = nomem((STMT *) stmt);
09083 goto done;
09084 }
09085 }
09086 if (schema) {
09087 s = uc_to_utf_c(schema, schemaLen);
09088 if (!s) {
09089 ret = nomem((STMT *) stmt);
09090 goto done;
09091 }
09092 }
09093 if (table) {
09094 t = uc_to_utf_c(table, tableLen);
09095 if (!t) {
09096 ret = nomem((STMT *) stmt);
09097 goto done;
09098 }
09099 }
09100 if (type) {
09101 y = uc_to_utf_c(type, typeLen);
09102 if (!y) {
09103 ret = nomem((STMT *) stmt);
09104 goto done;
09105 }
09106 }
09107 ret = drvtables(stmt, c, SQL_NTS, s, SQL_NTS,
09108 t, SQL_NTS, y, SQL_NTS);
09109 done:
09110 uc_free(y);
09111 uc_free(t);
09112 uc_free(s);
09113 uc_free(c);
09114 return ret;
09115 }
09116 #endif
09117
09122 static COL colSpec[] = {
09123 { "SYSTEM", "COLUMN", "TABLE_QUALIFIER", SCOL_VARCHAR, 50 },
09124 { "SYSTEM", "COLUMN", "TABLE_OWNER", SCOL_VARCHAR, 50 },
09125 { "SYSTEM", "COLUMN", "TABLE_NAME", SCOL_VARCHAR, 255 },
09126 { "SYSTEM", "COLUMN", "COLUMN_NAME", SCOL_VARCHAR, 255 },
09127 { "SYSTEM", "COLUMN", "DATA_TYPE", SQL_SMALLINT, 50 },
09128 { "SYSTEM", "COLUMN", "TYPE_NAME", SCOL_VARCHAR, 50 },
09129 { "SYSTEM", "COLUMN", "PRECISION", SQL_INTEGER, 50 },
09130 { "SYSTEM", "COLUMN", "LENGTH", SQL_INTEGER, 50 },
09131 { "SYSTEM", "COLUMN", "RADIX", SQL_SMALLINT, 50 },
09132 { "SYSTEM", "COLUMN", "SCALE", SQL_SMALLINT, 50 },
09133 { "SYSTEM", "COLUMN", "NULLABLE", SQL_SMALLINT, 50 },
09134 { "SYSTEM", "COLUMN", "REMARKS", SCOL_VARCHAR, 50 },
09135 { "SYSTEM", "COLUMN", "COLUMN_DEF", SCOL_VARCHAR, 50 },
09136 { "SYSTEM", "COLUMN", "SQL_DATA_TYPE", SQL_SMALLINT, 50 },
09137 { "SYSTEM", "COLUMN", "SQL_DATETIME_SUB", SQL_SMALLINT, 50 },
09138 { "SYSTEM", "COLUMN", "CHAR_OCTET_LENGTH", SQL_SMALLINT, 50 },
09139 { "SYSTEM", "COLUMN", "ORDINAL_POSITION", SQL_SMALLINT, 50 },
09140 { "SYSTEM", "COLUMN", "IS_NULLABLE", SCOL_VARCHAR, 50 }
09141 };
09142
09157 static SQLRETURN
09158 drvcolumns(SQLHSTMT stmt,
09159 SQLCHAR *cat, SQLSMALLINT catLen,
09160 SQLCHAR *schema, SQLSMALLINT schemaLen,
09161 SQLCHAR *table, SQLSMALLINT tableLen,
09162 SQLCHAR *col, SQLSMALLINT colLen)
09163 {
09164 SQLRETURN sret;
09165 STMT *s;
09166 DBC *d;
09167 int ret, nrows, ncols, size, i, k;
09168 char *errp = NULL, tname[512], **rowp;
09169
09170 sret = mkresultset(stmt, colSpec, array_size(colSpec));
09171 if (sret != SQL_SUCCESS) {
09172 return sret;
09173 }
09174 s = (STMT *) stmt;
09175 d = (DBC *) s->dbc;
09176 if (!table || table[0] == '\0' || table[0] == '%') {
09177 setstat(s, -1, "need table name", (*s->ov3) ? "HY000" : "S1000");
09178 return SQL_ERROR;
09179 }
09180 if (tableLen == SQL_NTS) {
09181 size = sizeof (tname) - 1;
09182 } else {
09183 size = min(sizeof (tname) - 1, tableLen);
09184 }
09185 strncpy(tname, table, size);
09186 tname[size] = '\0';
09187 ret = sqlite_get_table_printf(d->sqlite, "PRAGMA table_info('%q')", &rowp,
09188 &nrows, &ncols, &errp, tname);
09189 if (ret != SQLITE_OK) {
09190 setstat(s, ret, "%s (%d)", (*s->ov3) ? "HY000" : "S1000",
09191 errp ? errp : "unknown error", ret);
09192 if (errp) {
09193 sqlite_freemem(errp);
09194 errp = NULL;
09195 }
09196 return SQL_ERROR;
09197 }
09198 if (errp) {
09199 sqlite_freemem(errp);
09200 errp = NULL;
09201 }
09202 if (ncols * nrows <= 0) {
09203 sqlite_free_table(rowp);
09204 return SQL_NO_DATA;
09205 }
09206 size = array_size(colSpec) * (nrows + 1);
09207 s->rows = xmalloc((size + 1) * sizeof (char *));
09208 if (!s->rows) {
09209 return nomem(s);
09210 }
09211 s->rows[0] = (char *) size;
09212 s->rows += 1;
09213 memset(s->rows, 0, sizeof (char *) * size);
09214 s->rowfree = freerows;
09215 s->nrows = nrows;
09216 for (i = 1; i <= s->nrows; i++) {
09217 s->rows[array_size(colSpec) * i + 0] = xstrdup("");
09218 s->rows[array_size(colSpec) * i + 1] = xstrdup("");
09219 s->rows[array_size(colSpec) * i + 2] = xstrdup(tname);
09220 s->rows[array_size(colSpec) * i + 8] = xstrdup("10");
09221 s->rows[array_size(colSpec) * i + 9] = xstrdup("0");
09222 s->rows[array_size(colSpec) * i + 15] = xstrdup("16384");
09223 }
09224 for (k = 0; k < ncols; k++) {
09225 if (strcmp(rowp[k], "cid") == 0) {
09226 for (i = 1; i <= s->nrows; i++) {
09227 char buf[256];
09228 int coln = i;
09229
09230 sscanf(rowp[i * ncols + k], "%d", &coln);
09231 sprintf(buf, "%d", coln + 1);
09232 s->rows[array_size(colSpec) * i + 16] = xstrdup(buf);
09233 }
09234 } else if (strcmp(rowp[k], "name") == 0) {
09235 for (i = 1; i <= s->nrows; i++) {
09236 s->rows[array_size(colSpec) * i + 3] =
09237 xstrdup(rowp[i * ncols + k]);
09238 }
09239 } else if (strcmp(rowp[k], "notnull") == 0) {
09240 for (i = 1; i <= s->nrows; i++) {
09241 if (*rowp[i * ncols + k] != '0') {
09242 s->rows[array_size(colSpec) * i + 10] =
09243 xstrdup(stringify(SQL_FALSE));
09244 } else {
09245 s->rows[array_size(colSpec) * i + 10] =
09246 xstrdup(stringify(SQL_TRUE));
09247 }
09248 s->rows[array_size(colSpec) * i + 17] =
09249 xstrdup(*rowp[i * ncols + k] != '0' ? "NO" : "YES");
09250 }
09251 } else if (strcmp(rowp[k], "dflt_value") == 0) {
09252 for (i = 1; i <= s->nrows; i++) {
09253 char *dflt = rowp[i * ncols + k];
09254
09255 s->rows[array_size(colSpec) * i + 12] =
09256 xstrdup(dflt ? dflt : "NULL");
09257 }
09258 } else if (strcmp(rowp[k], "type") == 0) {
09259 for (i = 1; i <= s->nrows; i++) {
09260 char *typename = rowp[i * ncols + k];
09261 int sqltype, m, d;
09262 char buf[256];
09263
09264 s->rows[array_size(colSpec) * i + 5] = xstrdup(typename);
09265 sqltype = mapsqltype(typename, NULL, *s->ov3, s->nowchar);
09266 getmd(typename, sqltype, &m, &d);
09267 #ifdef SQL_LONGVARCHAR
09268 if (sqltype == SQL_VARCHAR && m > 255) {
09269 sqltype = SQL_LONGVARCHAR;
09270 }
09271 #endif
09272 #ifdef SQLITE_UTF8
09273 #ifdef SQL_WLONGVARCHAR
09274 if (sqltype == SQL_WVARCHAR && m > 255) {
09275 sqltype = SQL_WLONGVARCHAR;
09276 }
09277 #endif
09278 #endif
09279 #if HAVE_ENCDEC
09280 if (sqltype == SQL_VARBINARY && m > 255) {
09281 sqltype = SQL_LONGVARBINARY;
09282 }
09283 #endif
09284 sprintf(buf, "%d", sqltype);
09285 s->rows[array_size(colSpec) * i + 4] = xstrdup(buf);
09286 s->rows[array_size(colSpec) * i + 13] = xstrdup(buf);
09287 sprintf(buf, "%d", m);
09288 s->rows[array_size(colSpec) * i + 7] = xstrdup(buf);
09289 sprintf(buf, "%d", d);
09290 s->rows[array_size(colSpec) * i + 6] = xstrdup(buf);
09291 }
09292 }
09293 }
09294 sqlite_free_table(rowp);
09295 return SQL_SUCCESS;
09296 }
09297
09298 #ifndef SQLITE_UTF8
09299
09313 SQLRETURN SQL_API
09314 SQLColumns(SQLHSTMT stmt,
09315 SQLCHAR *cat, SQLSMALLINT catLen,
09316 SQLCHAR *schema, SQLSMALLINT schemaLen,
09317 SQLCHAR *table, SQLSMALLINT tableLen,
09318 SQLCHAR *col, SQLSMALLINT colLen)
09319 {
09320 return drvcolumns(stmt, cat, catLen, schema, schemaLen,
09321 table, tableLen, col, colLen);
09322 }
09323 #endif
09324
09325 #ifdef SQLITE_UTF8
09326
09340 SQLRETURN SQL_API
09341 SQLColumnsW(SQLHSTMT stmt,
09342 SQLWCHAR *cat, SQLSMALLINT catLen,
09343 SQLWCHAR *schema, SQLSMALLINT schemaLen,
09344 SQLWCHAR *table, SQLSMALLINT tableLen,
09345 SQLWCHAR *col, SQLSMALLINT colLen)
09346 {
09347 char *c = NULL, *s = NULL, *t = NULL, *k = NULL;
09348 SQLRETURN ret;
09349
09350 if (cat) {
09351 c = uc_to_utf_c(cat, catLen);
09352 if (!c) {
09353 ret = nomem((STMT *) stmt);
09354 goto done;
09355 }
09356 }
09357 if (schema) {
09358 s = uc_to_utf_c(schema, schemaLen);
09359 if (!s) {
09360 ret = nomem((STMT *) stmt);
09361 goto done;
09362 }
09363 }
09364 if (table) {
09365 t = uc_to_utf_c(table, tableLen);
09366 if (!t) {
09367 ret = nomem((STMT *) stmt);
09368 goto done;
09369 }
09370 }
09371 if (col) {
09372 k = uc_to_utf_c(col, colLen);
09373 if (!k) {
09374 ret = nomem((STMT *) stmt);
09375 goto done;
09376 }
09377 }
09378 ret = drvcolumns(stmt, c, SQL_NTS, s, SQL_NTS,
09379 t, SQL_NTS, k, SQL_NTS);
09380 done:
09381 uc_free(k);
09382 uc_free(t);
09383 uc_free(s);
09384 uc_free(c);
09385 return ret;
09386
09387 }
09388 #endif
09389
09394 static COL typeSpec[] = {
09395 { "SYSTEM", "TYPE", "TYPE_NAME", SCOL_VARCHAR, 50 },
09396 { "SYSTEM", "TYPE", "DATA_TYPE", SQL_SMALLINT, 2 },
09397 { "SYSTEM", "TYPE", "PRECISION", SQL_INTEGER, 4 },
09398 { "SYSTEM", "TYPE", "LITERAL_PREFIX", SCOL_VARCHAR, 50 },
09399 { "SYSTEM", "TYPE", "LITERAL_SUFFIX", SCOL_VARCHAR, 50 },
09400 { "SYSTEM", "TYPE", "CREATE_PARAMS", SCOL_VARCHAR, 50 },
09401 { "SYSTEM", "TYPE", "NULLABLE", SQL_SMALLINT, 2 },
09402 { "SYSTEM", "TYPE", "CASE_SENSITIVE", SQL_SMALLINT, 2 },
09403 { "SYSTEM", "TYPE", "SEARCHABLE", SQL_SMALLINT, 2 },
09404 { "SYSTEM", "TYPE", "UNSIGNED_ATTRIBUTE", SQL_SMALLINT, 2 },
09405 { "SYSTEM", "TYPE", "MONEY", SQL_SMALLINT, 2 },
09406 { "SYSTEM", "TYPE", "AUTO_INCREMENT", SQL_SMALLINT, 2 },
09407 { "SYSTEM", "TYPE", "LOCAL_TYPE_NAME", SCOL_VARCHAR, 50 },
09408 { "SYSTEM", "TYPE", "MINIMUM_SCALE", SQL_SMALLINT, 2 },
09409 { "SYSTEM", "TYPE", "MAXIMUM_SCALE", SQL_SMALLINT, 2 }
09410 };
09411
09421 static void
09422 mktypeinfo(STMT *s, int row, char *typename, int type, int tind)
09423 {
09424 int offs = row * array_size(typeSpec);
09425 char *tcode, *crpar = NULL, *quote = NULL, *sign = stringify(SQL_FALSE);
09426 static char tcodes[32 * 32];
09427
09428 if (tind <= 0) {
09429 tind = row;
09430 }
09431 tcode = tcodes + tind * 32;
09432 sprintf(tcode, "%d", type);
09433 s->rows[offs + 0] = typename;
09434 s->rows[offs + 1] = tcode;
09435 switch (type) {
09436 default:
09437 #ifdef SQL_LONGVARCHAR
09438 case SQL_LONGVARCHAR:
09439 #ifdef SQLITE_UTF8
09440 case SQL_WLONGVARCHAR:
09441 #endif
09442 crpar = "length";
09443 quote = "'";
09444 sign = NULL;
09445 s->rows[offs + 2] = "65536";
09446 break;
09447 #endif
09448 case SQL_CHAR:
09449 case SQL_VARCHAR:
09450 #ifdef SQLITE_UTF8
09451 case SQL_WCHAR:
09452 case SQL_WVARCHAR:
09453 #endif
09454 s->rows[offs + 2] = "255";
09455 crpar = "length";
09456 quote = "'";
09457 sign = NULL;
09458 break;
09459 case SQL_TINYINT:
09460 s->rows[offs + 2] = "3";
09461 break;
09462 case SQL_SMALLINT:
09463 s->rows[offs + 2] = "5";
09464 break;
09465 case SQL_INTEGER:
09466 s->rows[offs + 2] = "7";
09467 break;
09468 case SQL_FLOAT:
09469 s->rows[offs + 2] = "7";
09470 break;
09471 case SQL_DOUBLE:
09472 s->rows[offs + 2] = "15";
09473 break;
09474 #ifdef SQL_TYPE_DATE
09475 case SQL_TYPE_DATE:
09476 #endif
09477 case SQL_DATE:
09478 s->rows[offs + 2] = "10";
09479 quote = "'";
09480 sign = NULL;
09481 break;
09482 #ifdef SQL_TYPE_TIME
09483 case SQL_TYPE_TIME:
09484 #endif
09485 case SQL_TIME:
09486 s->rows[offs + 2] = "8";
09487 quote = "'";
09488 sign = NULL;
09489 break;
09490 #ifdef SQL_TYPE_TIMESTAMP
09491 case SQL_TYPE_TIMESTAMP:
09492 #endif
09493 case SQL_TIMESTAMP:
09494 s->rows[offs + 2] = "32";
09495 quote = "'";
09496 sign = NULL;
09497 break;
09498 #if HAVE_ENCDEC
09499 case SQL_VARBINARY:
09500 sign = NULL;
09501 s->rows[offs + 2] = "255";
09502 break;
09503 case SQL_LONGVARBINARY:
09504 sign = NULL;
09505 s->rows[offs + 2] = "65536";
09506 break;
09507 #endif
09508 }
09509 s->rows[offs + 3] = s->rows[offs + 4] = quote;
09510 s->rows[offs + 5] = crpar;
09511 s->rows[offs + 6] = stringify(SQL_NULLABLE);
09512 s->rows[offs + 7] = stringify(SQL_FALSE);
09513 s->rows[offs + 8] = stringify(SQL_SEARCHABLE);
09514 s->rows[offs + 9] = sign;
09515 s->rows[offs + 10] = stringify(SQL_FALSE);
09516 s->rows[offs + 11] = stringify(SQL_FALSE);
09517 s->rows[offs + 12] = typename;
09518 s->rows[offs + 13] = NULL;
09519 s->rows[offs + 14] = NULL;
09520 }
09521
09530 static int
09531 typeinfosort(const void *a, const void *b)
09532 {
09533 char **pa = (char **) a;
09534 char **pb = (char **) b;
09535 int na, nb;
09536
09537 na = strtol(pa[1], NULL, 0);
09538 nb = strtol(pb[1], NULL, 0);
09539 return na - nb;
09540 }
09541
09549 static SQLRETURN
09550 drvgettypeinfo(SQLHSTMT stmt, SQLSMALLINT sqltype)
09551 {
09552 SQLRETURN ret;
09553 STMT *s;
09554 DBC *d;
09555
09556 ret = mkresultset(stmt, typeSpec, array_size(typeSpec));
09557 if (ret != SQL_SUCCESS) {
09558 return ret;
09559 }
09560 s = (STMT *) stmt;
09561 d = (DBC *) s->dbc;
09562 #ifdef SQLITE_UTF8
09563 #ifdef SQL_LONGVARCHAR
09564 #ifdef SQL_WLONGVARCHAR
09565 if (s->nowchar) {
09566 s->nrows = sqltype == SQL_ALL_TYPES ? 13 : 1;
09567 } else {
09568 s->nrows = sqltype == SQL_ALL_TYPES ? 17 : 1;
09569 }
09570 #else
09571 if (s->nowchar) {
09572 s->nrows = sqltype == SQL_ALL_TYPES ? 12 : 1;
09573 } else {
09574 s->nrows = sqltype == SQL_ALL_TYPES ? 16 : 1;
09575 }
09576 #endif
09577 #else
09578 s->nrows = sqltype == SQL_ALL_TYPES ? 15 : 1;
09579 #endif
09580 #else
09581 #ifdef SQL_LONGVARCHAR
09582 s->nrows = sqltype == SQL_ALL_TYPES ? 13 : 1;
09583 #else
09584 s->nrows = sqltype == SQL_ALL_TYPES ? 12 : 1;
09585 #endif
09586 #endif
09587 #if HAVE_ENCDEC
09588 if (sqltype == SQL_ALL_TYPES) {
09589 s->nrows += 2;
09590 }
09591 #endif
09592 s->rows = (char **) xmalloc(sizeof (char *) * (s->nrows + 1)
09593 * array_size(typeSpec));
09594 if (!s->rows) {
09595 s->nrows = 0;
09596 return nomem(s);
09597 }
09598 #ifdef MEMORY_DEBUG
09599 s->rowfree = xfree__;
09600 #else
09601 s->rowfree = free;
09602 #endif
09603 memset(s->rows, 0,
09604 sizeof (char *) * (s->nrows + 1) * array_size(typeSpec));
09605 if (sqltype == SQL_ALL_TYPES) {
09606 int cc = 1;
09607
09608 mktypeinfo(s, cc++, "varchar", SQL_VARCHAR, 0);
09609 mktypeinfo(s, cc++, "tinyint", SQL_TINYINT, 0);
09610 mktypeinfo(s, cc++, "smallint", SQL_SMALLINT, 0);
09611 mktypeinfo(s, cc++, "integer", SQL_INTEGER, 0);
09612 mktypeinfo(s, cc++, "float", SQL_FLOAT, 0);
09613 mktypeinfo(s, cc++, "double", SQL_DOUBLE, 0);
09614 #ifdef SQL_TYPE_DATE
09615 mktypeinfo(s, cc++, "date", (*s->ov3) ? SQL_TYPE_DATE : SQL_DATE, 0);
09616 #else
09617 mktypeinfo(s, cc++, "date", SQL_DATE, 0);
09618 #endif
09619 #ifdef SQL_TYPE_TIME
09620 mktypeinfo(s, cc++, "time", (*s->ov3) ? SQL_TYPE_TIME : SQL_TIME, 0);
09621 #else
09622 mktypeinfo(s, cc++, "time", SQL_TIME, 0);
09623 #endif
09624 #ifdef SQL_TYPE_TIMESTAMP
09625 mktypeinfo(s, cc++, "timestamp",
09626 (*s->ov3) ? SQL_TYPE_TIMESTAMP : SQL_TIMESTAMP, 0);
09627 #else
09628 mktypeinfo(s, cc++, "timestamp", SQL_TIMESTAMP, 0);
09629 #endif
09630 mktypeinfo(s, cc++, "char", SQL_CHAR, 0);
09631 mktypeinfo(s, cc++, "numeric", SQL_DOUBLE, 0);
09632 #ifdef SQL_LONGVARCHAR
09633 mktypeinfo(s, cc++, "text", SQL_LONGVARCHAR, 0);
09634 mktypeinfo(s, cc++, "longvarchar", SQL_LONGVARCHAR, 0);
09635 #else
09636 mktypeinfo(s, cc++, "text", SQL_VARCHAR, 0);
09637 #endif
09638 #ifdef SQLITE_UTF8
09639 if (!s->nowchar) {
09640 mktypeinfo(s, cc++, "wvarchar", SQL_WVARCHAR, 0);
09641 #ifdef SQL_LONGVARCHAR
09642 mktypeinfo(s, cc++, "wchar", SQL_WCHAR, 0);
09643 mktypeinfo(s, cc++, "wtext", SQL_WLONGVARCHAR, 0);
09644 #ifdef SQL_WLONGVARCHAR
09645 mktypeinfo(s, cc++, "longwvarchar", SQL_WLONGVARCHAR, 0);
09646 #endif
09647 #else
09648 mktypeinfo(s, cc++, "wvarchar", SQL_WVARCHAR, 0);
09649 mktypeinfo(s, cc++, "wchar", SQL_WCHAR, 0);
09650 mktypeinfo(s, cc++, "wtext", SQL_WVARCHAR, 0);
09651 #endif
09652 }
09653 #endif
09654 #if HAVE_ENCDEC
09655 mktypeinfo(s, cc++, "varbinary", SQL_VARBINARY, 0);
09656 mktypeinfo(s, cc++, "longvarbinary", SQL_LONGVARBINARY, 0);
09657 #endif
09658 qsort(s->rows + array_size(typeSpec), s->nrows,
09659 sizeof (char *) * array_size(typeSpec), typeinfosort);
09660 } else {
09661 switch (sqltype) {
09662 case SQL_CHAR:
09663 mktypeinfo(s, 1, "char", SQL_CHAR, 10);
09664 break;
09665 case SQL_VARCHAR:
09666 mktypeinfo(s, 1, "varchar", SQL_VARCHAR, 1);
09667 break;
09668 case SQL_TINYINT:
09669 mktypeinfo(s, 1, "tinyint", SQL_TINYINT, 2);
09670 break;
09671 case SQL_SMALLINT:
09672 mktypeinfo(s, 1, "smallint", SQL_SMALLINT, 3);
09673 break;
09674 case SQL_INTEGER:
09675 mktypeinfo(s, 1, "integer", SQL_INTEGER, 4);
09676 break;
09677 case SQL_FLOAT:
09678 mktypeinfo(s, 1, "float", SQL_FLOAT, 5);
09679 break;
09680 case SQL_DOUBLE:
09681 mktypeinfo(s, 1, "double", SQL_DOUBLE, 6);
09682 break;
09683 #ifdef SQL_TYPE_DATE
09684 case SQL_TYPE_DATE:
09685 mktypeinfo(s, 1, "date", SQL_TYPE_DATE, 25);
09686 break;
09687 #endif
09688 case SQL_DATE:
09689 mktypeinfo(s, 1, "date", SQL_DATE, 7);
09690 break;
09691 #ifdef SQL_TYPE_TIME
09692 case SQL_TYPE_TIME:
09693 mktypeinfo(s, 1, "date", SQL_TYPE_TIME, 26);
09694 break;
09695 #endif
09696 case SQL_TIME:
09697 mktypeinfo(s, 1, "time", SQL_TIME, 8);
09698 break;
09699 #ifdef SQL_TYPE_TIMESTAMP
09700 case SQL_TYPE_TIMESTAMP:
09701 mktypeinfo(s, 1, "date", SQL_TYPE_TIMESTAMP, 27);
09702 break;
09703 #endif
09704 case SQL_TIMESTAMP:
09705 mktypeinfo(s, 1, "timestamp", SQL_TIMESTAMP, 9);
09706 break;
09707 #ifdef SQL_LONGVARCHAR
09708 case SQL_LONGVARCHAR:
09709 mktypeinfo(s, 1, "longvarchar", SQL_LONGVARCHAR, 12);
09710 break;
09711 #endif
09712 #ifdef SQLITE_UTF8
09713 #ifdef SQL_WCHAR
09714 case SQL_WCHAR:
09715 mktypeinfo(s, 1, "wchar", SQL_WCHAR, 18);
09716 break;
09717 #endif
09718 #ifdef SQL_WVARCHAR
09719 case SQL_WVARCHAR:
09720 mktypeinfo(s, 1, "wvarchar", SQL_WVARCHAR, 19);
09721 break;
09722 #endif
09723 #ifdef SQL_WLONGVARCHAR
09724 case SQL_WLONGVARCHAR:
09725 mktypeinfo(s, 1, "longwvarchar", SQL_WLONGVARCHAR, 20);
09726 break;
09727 #endif
09728 #endif
09729 #if HAVE_ENCDEC
09730 case SQL_VARBINARY:
09731 mktypeinfo(s, 1, "varbinary", SQL_VARBINARY, 30);
09732 break;
09733 case SQL_LONGVARBINARY:
09734 mktypeinfo(s, 1, "longvarbinary", SQL_LONGVARBINARY, 31);
09735 break;
09736 #endif
09737 default:
09738 s->nrows = 0;
09739 return SQL_NO_DATA;
09740 }
09741 }
09742 return SQL_SUCCESS;
09743 }
09744
09745 #ifndef SQLITE_UTF8
09746
09753 SQLRETURN SQL_API
09754 SQLGetTypeInfo(SQLHSTMT stmt, SQLSMALLINT sqltype)
09755 {
09756 return drvgettypeinfo(stmt, sqltype);
09757 }
09758 #endif
09759
09760 #ifdef SQLITE_UTF8
09761
09768 SQLRETURN SQL_API
09769 SQLGetTypeInfoW(SQLHSTMT stmt, SQLSMALLINT sqltype)
09770 {
09771 return drvgettypeinfo(stmt, sqltype);
09772 }
09773 #endif
09774
09779 static COL statSpec[] = {
09780 { "SYSTEM", "STATISTICS", "TABLE_QUALIFIER", SCOL_VARCHAR, 50 },
09781 { "SYSTEM", "STATISTICS", "TABLE_OWNER", SCOL_VARCHAR, 50 },
09782 { "SYSTEM", "STATISTICS", "TABLE_NAME", SCOL_VARCHAR, 255 },
09783 { "SYSTEM", "STATISTICS", "NON_UNIQUE", SQL_SMALLINT, 50 },
09784 { "SYSTEM", "STATISTICS", "INDEX_QUALIFIER", SCOL_VARCHAR, 255 },
09785 { "SYSTEM", "STATISTICS", "INDEX_NAME", SCOL_VARCHAR, 255 },
09786 { "SYSTEM", "STATISTICS", "TYPE", SQL_SMALLINT, 50 },
09787 { "SYSTEM", "STATISTICS", "ORDINAL_POSITION", SQL_SMALLINT, 50 },
09788 { "SYSTEM", "STATISTICS", "COLUMN_NAME", SCOL_VARCHAR, 255 },
09789 { "SYSTEM", "STATISTICS", "ASC_OR_DESC", SCOL_CHAR, 1 },
09790 { "SYSTEM", "STATISTICS", "CARDINALITY", SQL_INTEGER, 50 },
09791 { "SYSTEM", "STATISTICS", "PAGES", SQL_INTEGER, 50 },
09792 { "SYSTEM", "STATISTICS", "FILTER_CONDITION", SCOL_VARCHAR, 255 }
09793 };
09794
09809 static SQLRETURN
09810 drvstatistics(SQLHSTMT stmt, SQLCHAR *cat, SQLSMALLINT catLen,
09811 SQLCHAR *schema, SQLSMALLINT schemaLen,
09812 SQLCHAR *table, SQLSMALLINT tableLen,
09813 SQLUSMALLINT itype, SQLUSMALLINT resv)
09814 {
09815 SQLRETURN sret;
09816 STMT *s;
09817 DBC *d;
09818 int i, size, ret, nrows, ncols, offs, namec, uniquec;
09819 char **rowp, *errp = NULL, tname[512];
09820
09821 sret = mkresultset(stmt, statSpec, array_size(statSpec));
09822 if (sret != SQL_SUCCESS) {
09823 return sret;
09824 }
09825 s = (STMT *) stmt;
09826 d = (DBC *) s->dbc;
09827 if (!table || table[0] == '\0' || table[0] == '%') {
09828 setstat(s, -1, "need table name", (*s->ov3) ? "HY000" : "S1000");
09829 return SQL_ERROR;
09830 }
09831 if (tableLen == SQL_NTS) {
09832 size = sizeof (tname) - 1;
09833 } else {
09834 size = min(sizeof (tname) - 1, tableLen);
09835 }
09836 strncpy(tname, table, size);
09837 tname[size] = '\0';
09838 ret = sqlite_get_table_printf(d->sqlite,
09839 "PRAGMA index_list('%q')", &rowp,
09840 &nrows, &ncols, &errp, tname);
09841 if (ret != SQLITE_OK) {
09842 setstat(s, ret, "%s (%d)", (*s->ov3) ? "HY000" : "S1000",
09843 errp ? errp : "unknown error", ret);
09844 if (errp) {
09845 sqlite_freemem(errp);
09846 errp = NULL;
09847 }
09848 return SQL_ERROR;
09849 }
09850 if (errp) {
09851 sqlite_freemem(errp);
09852 errp = NULL;
09853 }
09854 if (ncols * nrows <= 0) {
09855 nodata:
09856 sqlite_free_table(rowp);
09857
09858 if (itype == SQL_INDEX_UNIQUE) {
09859 ret = sqlite_get_table_printf(d->sqlite,
09860 "PRAGMA table_info('%q')", &rowp,
09861 &nrows, &ncols, NULL, tname);
09862 if (ret == SQLITE_OK) {
09863 int colid, typec, roffs;
09864
09865 namec = findcol(rowp, ncols, "name");
09866 uniquec = findcol(rowp, ncols, "pk");
09867 typec = findcol(rowp, ncols, "type");
09868 colid = findcol(rowp, ncols, "cid");
09869 if (namec < 0 || uniquec < 0 || typec < 0 || colid < 0) {
09870 goto nodata2;
09871 }
09872 for (i = 1; i <= nrows; i++) {
09873 if (*rowp[i * ncols + uniquec] != '0' &&
09874 strlen(rowp[i * ncols + typec]) == 7 &&
09875 strncasecmp(rowp[i * ncols + typec], "integer", 7)
09876 == 0) {
09877 break;
09878 }
09879 }
09880 if (i > nrows) {
09881 goto nodata2;
09882 }
09883 size = (1 + 1) * array_size(statSpec);
09884 s->rows = xmalloc((size + 1) * sizeof (char *));
09885 if (!s->rows) {
09886 s->nrows = 0;
09887 return nomem(s);
09888 }
09889 s->rows[0] = (char *) size;
09890 s->rows += 1;
09891 memset(s->rows, 0, sizeof (char *) * size);
09892 s->rowfree = freerows;
09893 s->nrows = 1;
09894 roffs = s->ncols;
09895 s->rows[roffs + 0] = xstrdup("");
09896 s->rows[roffs + 1] = xstrdup("");
09897 s->rows[roffs + 2] = xstrdup(tname);
09898 s->rows[roffs + 3] = xstrdup(stringify(SQL_FALSE));
09899 s->rows[roffs + 4] = xstrdup("");
09900 s->rows[roffs + 5] = xstrdup("");
09901 s->rows[roffs + 6] = xstrdup(stringify(SQL_INDEX_OTHER));
09902 s->rows[roffs + 7] = xstrdup("1");
09903 s->rows[roffs + 8] = xstrdup(rowp[i * ncols + namec]);
09904 s->rows[roffs + 9] = xstrdup("A");
09905 nodata2:
09906 sqlite_free_table(rowp);
09907 }
09908 }
09909 return SQL_SUCCESS;
09910 }
09911 size = 0;
09912 namec = findcol(rowp, ncols, "name");
09913 uniquec = findcol(rowp, ncols, "unique");
09914 if (namec < 0 || uniquec < 0) {
09915 goto nodata;
09916 }
09917 for (i = 1; i <= nrows; i++) {
09918 int nnrows, nncols;
09919 char **rowpp;
09920 int isuniq;
09921
09922 isuniq = *rowp[i * ncols + uniquec] != '0';
09923 if (isuniq || itype == SQL_INDEX_ALL) {
09924 ret = sqlite_get_table_printf(d->sqlite,
09925 "PRAGMA index_info('%q')", &rowpp,
09926 &nnrows, &nncols, NULL,
09927 rowp[i * ncols + namec]);
09928 if (ret == SQLITE_OK) {
09929 size += nnrows;
09930 sqlite_free_table(rowpp);
09931 }
09932 }
09933 }
09934 if (size == 0) {
09935 goto nodata;
09936 }
09937 s->nrows = size;
09938 size = (size + 1) * array_size(statSpec);
09939 s->rows = xmalloc((size + 1) * sizeof (char *));
09940 if (!s->rows) {
09941 s->nrows = 0;
09942 return nomem(s);
09943 }
09944 s->rows[0] = (char *) size;
09945 s->rows += 1;
09946 memset(s->rows, 0, sizeof (char *) * size);
09947 s->rowfree = freerows;
09948 offs = 0;
09949 for (i = 1; i <= nrows; i++) {
09950 int nnrows, nncols;
09951 char **rowpp;
09952
09953 if (*rowp[i * ncols + uniquec] != '0' || itype == SQL_INDEX_ALL) {
09954 int k;
09955
09956 ret = sqlite_get_table_printf(d->sqlite,
09957 "PRAGMA index_info('%q')", &rowpp,
09958 &nnrows, &nncols, NULL,
09959 rowp[i * ncols + namec]);
09960 if (ret != SQLITE_OK) {
09961 continue;
09962 }
09963 for (k = 0; nnrows && k < nncols; k++) {
09964 if (strcmp(rowpp[k], "name") == 0) {
09965 int m;
09966
09967 for (m = 1; m <= nnrows; m++) {
09968 int roffs = (offs + m) * s->ncols;
09969 int isuniq;
09970
09971 isuniq = *rowp[i * ncols + uniquec] != '0';
09972 s->rows[roffs + 0] = xstrdup("");
09973 s->rows[roffs + 1] = xstrdup("");
09974 s->rows[roffs + 2] = xstrdup(tname);
09975 if (isuniq) {
09976 s->rows[roffs + 3] = xstrdup(stringify(SQL_FALSE));
09977 } else {
09978 s->rows[roffs + 3] = xstrdup(stringify(SQL_TRUE));
09979 }
09980 s->rows[roffs + 4] = xstrdup("");
09981 s->rows[roffs + 5] = xstrdup(rowp[i * ncols + namec]);
09982 s->rows[roffs + 6] =
09983 xstrdup(stringify(SQL_INDEX_OTHER));
09984 s->rows[roffs + 8] = xstrdup(rowpp[m * nncols + k]);
09985 s->rows[roffs + 9] = xstrdup("A");
09986 }
09987 } else if (strcmp(rowpp[k], "seqno") == 0) {
09988 int m;
09989
09990 for (m = 1; m <= nnrows; m++) {
09991 int roffs = (offs + m) * s->ncols;
09992 int pos = m - 1;
09993 char buf[32];
09994
09995 sscanf(rowpp[m * nncols + k], "%d", &pos);
09996 sprintf(buf, "%d", pos + 1);
09997 s->rows[roffs + 7] = xstrdup(buf);
09998 }
09999 }
10000 }
10001 offs += nnrows;
10002 sqlite_free_table(rowpp);
10003 }
10004 }
10005 sqlite_free_table(rowp);
10006 return SQL_SUCCESS;
10007 }
10008
10009 #ifndef SQLITE_UTF8
10010
10024 SQLRETURN SQL_API
10025 SQLStatistics(SQLHSTMT stmt, SQLCHAR *cat, SQLSMALLINT catLen,
10026 SQLCHAR *schema, SQLSMALLINT schemaLen,
10027 SQLCHAR *table, SQLSMALLINT tableLen,
10028 SQLUSMALLINT itype, SQLUSMALLINT resv)
10029 {
10030 return drvstatistics(stmt, cat, catLen, schema, schemaLen,
10031 table, tableLen, itype, resv);
10032 }
10033 #endif
10034
10035 #ifdef SQLITE_UTF8
10036
10050 SQLRETURN SQL_API
10051 SQLStatisticsW(SQLHSTMT stmt, SQLWCHAR *cat, SQLSMALLINT catLen,
10052 SQLWCHAR *schema, SQLSMALLINT schemaLen,
10053 SQLWCHAR *table, SQLSMALLINT tableLen,
10054 SQLUSMALLINT itype, SQLUSMALLINT resv)
10055 {
10056 char *c = NULL, *s = NULL, *t = NULL;
10057 SQLRETURN ret;
10058
10059 if (cat) {
10060 c = uc_to_utf_c(cat, catLen);
10061 if (!c) {
10062 ret = nomem((STMT *) stmt);
10063 goto done;
10064 }
10065 }
10066 if (schema) {
10067 s = uc_to_utf_c(schema, schemaLen);
10068 if (!s) {
10069 ret = nomem((STMT *) stmt);
10070 goto done;
10071 }
10072 }
10073 if (table) {
10074 t = uc_to_utf_c(table, tableLen);
10075 if (!t) {
10076 ret = nomem((STMT *) stmt);
10077 goto done;
10078 }
10079 }
10080 ret = drvstatistics(stmt, c, SQL_NTS, s, SQL_NTS, t, SQL_NTS,
10081 itype, resv);
10082 done:
10083 uc_free(t);
10084 uc_free(s);
10085 uc_free(c);
10086 return ret;
10087 }
10088 #endif
10089
10101 SQLRETURN SQL_API
10102 SQLGetData(SQLHSTMT stmt, SQLUSMALLINT col, SQLSMALLINT type,
10103 SQLPOINTER val, SQLINTEGER len, SQLINTEGER *lenp)
10104 {
10105 STMT *s;
10106
10107 if (stmt == SQL_NULL_HSTMT) {
10108 return SQL_INVALID_HANDLE;
10109 }
10110 s = (STMT *) stmt;
10111 if (col == 0 && s->bkmrk && type == SQL_C_BOOKMARK) {
10112 *((long *) val) = s->rowp;
10113 if (lenp) {
10114 *lenp = sizeof (long);
10115 }
10116 return SQL_SUCCESS;
10117 }
10118 if (col < 1 || col > s->ncols) {
10119 setstat(s, -1, "invalid column", (*s->ov3) ? "07009" : "S1002");
10120 return SQL_ERROR;
10121 }
10122 --col;
10123 return getrowdata(s, col, type, val, len, lenp, 1);
10124 }
10125
10133 static SQLRETURN
10134 dofetchbind(STMT *s, int rsi)
10135 {
10136 int ret, i, withinfo = 0;
10137
10138 s->row_status0[rsi] = SQL_ROW_SUCCESS;
10139 if (s->bkmrk && s->bkmrkcol.valp) {
10140 long *val;
10141
10142 if (s->bind_type != SQL_BIND_BY_COLUMN) {
10143 val = (long *) ((char *) s->bkmrkcol.valp + s->bind_type * rsi);
10144 } else {
10145 val = (long *) s->bkmrkcol.valp + rsi;
10146 }
10147 if (s->bind_offs) {
10148 val = (long *) ((char *) val + *s->bind_offs);
10149 }
10150 *val = s->rowp;
10151 if (s->bkmrkcol.lenp) {
10152 SQLINTEGER *ival;
10153
10154 if (s->bind_type != SQL_BIND_BY_COLUMN) {
10155 ival = (SQLINTEGER *) ((char *) s->bkmrkcol.lenp +
10156 s->bind_type * rsi);
10157 } else {
10158 ival = &s->bkmrkcol.lenp[rsi];
10159 }
10160 if (s->bind_offs) {
10161 ival = (SQLINTEGER *) ((char *) ival + *s->bind_offs);
10162 }
10163 *ival = sizeof (long);
10164 }
10165 }
10166 ret = SQL_SUCCESS;
10167 for (i = 0; s->bindcols && i < s->ncols; i++) {
10168 BINDCOL *b = &s->bindcols[i];
10169 SQLPOINTER dp = 0;
10170 SQLINTEGER *lp = 0;
10171
10172 b->offs = 0;
10173 if (b->valp) {
10174 if (s->bind_type != SQL_BIND_BY_COLUMN) {
10175 dp = (SQLPOINTER) ((char *) b->valp + s->bind_type * rsi);
10176 } else {
10177 dp = (SQLPOINTER) ((char *) b->valp + b->max * rsi);
10178 }
10179 if (s->bind_offs) {
10180 dp = (SQLPOINTER) ((char *) dp + *s->bind_offs);
10181 }
10182 }
10183 if (b->lenp) {
10184 if (s->bind_type != SQL_BIND_BY_COLUMN) {
10185 lp = (SQLINTEGER *) ((char *) b->lenp + s->bind_type * rsi);
10186 } else {
10187 lp = b->lenp + rsi;
10188 }
10189 if (s->bind_offs) {
10190 lp = (SQLINTEGER *) ((char *) lp + *s->bind_offs);
10191 }
10192 }
10193 if (dp || lp) {
10194 ret = getrowdata(s, (SQLUSMALLINT) i, b->type, dp, b->max, lp, 0);
10195 if (!SQL_SUCCEEDED(ret)) {
10196 s->row_status0[rsi] = SQL_ROW_ERROR;
10197 break;
10198 }
10199 if (ret != SQL_SUCCESS) {
10200 withinfo = 1;
10201 #ifdef SQL_ROW_SUCCESS_WITH_INFO
10202 s->row_status0[rsi] = SQL_ROW_SUCCESS_WITH_INFO;
10203 #endif
10204 }
10205 }
10206 }
10207 if (SQL_SUCCEEDED(ret)) {
10208 ret = withinfo ? SQL_SUCCESS_WITH_INFO : SQL_SUCCESS;
10209 }
10210 return ret;
10211 }
10212
10221 static SQLRETURN
10222 drvfetchscroll(SQLHSTMT stmt, SQLSMALLINT orient, SQLINTEGER offset)
10223 {
10224 STMT *s;
10225 int i, withinfo = 0;
10226 SQLRETURN ret;
10227
10228 if (stmt == SQL_NULL_HSTMT) {
10229 return SQL_INVALID_HANDLE;
10230 }
10231 s = (STMT *) stmt;
10232 for (i = 0; i < s->rowset_size; i++) {
10233 s->row_status0[i] = SQL_ROW_NOROW;
10234 }
10235 if (s->row_status) {
10236 memcpy(s->row_status, s->row_status0,
10237 sizeof (SQLUSMALLINT) * s->rowset_size);
10238 }
10239 s->row_count0 = 0;
10240 if (s->row_count) {
10241 *s->row_count = s->row_count0;
10242 }
10243 if (!s->bindcols) {
10244 for (i = 0; i < s->rowset_size; i++) {
10245 s->row_status0[i] = SQL_ROW_ERROR;
10246 }
10247 ret = SQL_ERROR;
10248 i = 0;
10249 goto done2;
10250 }
10251 if (s->curtype == SQL_CURSOR_FORWARD_ONLY && orient != SQL_FETCH_NEXT) {
10252 setstat(s, -1, "wrong fetch direction", "01000");
10253 ret = SQL_ERROR;
10254 i = 0;
10255 goto done2;
10256 }
10257 ret = SQL_SUCCESS;
10258 i = 0;
10259 if (((DBC *) (s->dbc))->vm_stmt == s && s->vm) {
10260 s->rowp = 0;
10261 for (; i < s->rowset_size; i++) {
10262 ret = vm_step(s);
10263 if (ret != SQL_SUCCESS) {
10264 s->row_status0[i] = SQL_ROW_ERROR;
10265 break;
10266 }
10267 if (s->nrows < 1) {
10268 break;
10269 }
10270 ret = dofetchbind(s, i);
10271 if (!SQL_SUCCEEDED(ret)) {
10272 break;
10273 } else if (ret == SQL_SUCCESS_WITH_INFO) {
10274 withinfo = 1;
10275 }
10276 }
10277 } else if (s->rows) {
10278 switch (orient) {
10279 case SQL_FETCH_NEXT:
10280 if (s->nrows < 1) {
10281 return SQL_NO_DATA;
10282 }
10283 if (s->rowp < 0) {
10284 s->rowp = -1;
10285 }
10286 if (s->rowp >= s->nrows) {
10287 s->rowp = s->nrows;
10288 return SQL_NO_DATA;
10289 }
10290 break;
10291 case SQL_FETCH_PRIOR:
10292 if (s->nrows < 1) {
10293 s->rowp = -1;
10294 return SQL_NO_DATA;
10295 }
10296 s->rowp -= s->rowset_size + 1;
10297 if (s->rowp < -1) {
10298 s->rowp = -1;
10299 return SQL_NO_DATA;
10300 }
10301 break;
10302 case SQL_FETCH_FIRST:
10303 if (s->nrows < 1) {
10304 return SQL_NO_DATA;
10305 }
10306 s->rowp = -1;
10307 break;
10308 case SQL_FETCH_LAST:
10309 if (s->nrows < 1) {
10310 return SQL_NO_DATA;
10311 }
10312 s->rowp = s->nrows - s->rowset_size;
10313 if (--s->rowp < -1) {
10314 s->rowp = -1;
10315 }
10316 break;
10317 case SQL_FETCH_ABSOLUTE:
10318 if (offset == 0) {
10319 s->rowp = -1;
10320 return SQL_NO_DATA;
10321 } else if (offset < 0) {
10322 if (0 - offset <= s->nrows) {
10323 s->rowp = s->nrows + offset - 1;
10324 break;
10325 }
10326 s->rowp = -1;
10327 return SQL_NO_DATA;
10328 } else if (offset > s->nrows) {
10329 s->rowp = s->nrows;
10330 return SQL_NO_DATA;
10331 }
10332 s->rowp = offset - 1 - 1;
10333 break;
10334 case SQL_FETCH_RELATIVE:
10335 if (offset >= 0) {
10336 s->rowp += offset * s->rowset_size - 1;
10337 if (s->rowp >= s->nrows) {
10338 s->rowp = s->nrows;
10339 return SQL_NO_DATA;
10340 }
10341 } else {
10342 s->rowp += offset * s->rowset_size - 1;
10343 if (s->rowp < -1) {
10344 s->rowp = -1;
10345 return SQL_NO_DATA;
10346 }
10347 }
10348 break;
10349 case SQL_FETCH_BOOKMARK:
10350 if (s->bkmrk) {
10351 if (offset < 0 || offset >= s->nrows) {
10352 return SQL_NO_DATA;
10353 }
10354 s->rowp = offset - 1;
10355 break;
10356 }
10357
10358 default:
10359 s->row_status0[0] = SQL_ROW_ERROR;
10360 ret = SQL_ERROR;
10361 goto done;
10362 }
10363 for (; i < s->rowset_size; i++) {
10364 ++s->rowp;
10365 if (s->rowp < 0 || s->rowp >= s->nrows) {
10366 break;
10367 }
10368 ret = dofetchbind(s, i);
10369 if (!SQL_SUCCEEDED(ret)) {
10370 break;
10371 } else if (ret == SQL_SUCCESS_WITH_INFO) {
10372 withinfo = 1;
10373 }
10374 }
10375 }
10376 done:
10377 if (i == 0) {
10378 if (SQL_SUCCEEDED(ret)) {
10379 return SQL_NO_DATA;
10380 }
10381 return ret;
10382 }
10383 if (SQL_SUCCEEDED(ret)) {
10384 ret = withinfo ? SQL_SUCCESS_WITH_INFO : SQL_SUCCESS;
10385 }
10386 done2:
10387 if (s->row_status) {
10388 memcpy(s->row_status, s->row_status0,
10389 sizeof (SQLUSMALLINT) * s->rowset_size);
10390 }
10391 s->row_count0 = i;
10392 if (s->row_count) {
10393 *s->row_count = s->row_count0;
10394 }
10395 return ret;
10396 }
10397
10404 SQLRETURN SQL_API
10405 SQLFetch(SQLHSTMT stmt)
10406 {
10407 return drvfetchscroll(stmt, SQL_FETCH_NEXT, 0);
10408 }
10409
10418 SQLRETURN SQL_API
10419 SQLFetchScroll(SQLHSTMT stmt, SQLSMALLINT orient, SQLINTEGER offset)
10420 {
10421 return drvfetchscroll(stmt, orient, offset);
10422 }
10423
10434 SQLRETURN SQL_API
10435 SQLExtendedFetch(SQLHSTMT stmt, SQLUSMALLINT orient, SQLINTEGER offset,
10436 SQLUINTEGER *rowcount, SQLUSMALLINT *rowstatus)
10437 {
10438 STMT *s;
10439 SQLRETURN ret;
10440 SQLUSMALLINT *rst;
10441
10442 if (stmt == SQL_NULL_HSTMT) {
10443 return SQL_INVALID_HANDLE;
10444 }
10445 s = (STMT *) stmt;
10446
10447 rst = s->row_status;
10448 s->row_status = 0;
10449 ret = drvfetchscroll(stmt, orient, offset);
10450 s->row_status = rst;
10451 if (rowstatus) {
10452 memcpy(rowstatus, s->row_status0,
10453 sizeof (SQLUSMALLINT) * s->rowset_size);
10454 }
10455 if (rowcount) {
10456 *rowcount = s->row_count0;
10457 }
10458 return ret;
10459 }
10460
10468 SQLRETURN SQL_API
10469 SQLRowCount(SQLHSTMT stmt, SQLINTEGER *nrows)
10470 {
10471 STMT *s;
10472
10473 if (stmt == SQL_NULL_HSTMT) {
10474 return SQL_INVALID_HANDLE;
10475 }
10476 s = (STMT *) stmt;
10477 if (nrows) {
10478 *nrows = s->nrows;
10479 }
10480 return SQL_SUCCESS;
10481 }
10482
10490 SQLRETURN SQL_API
10491 SQLNumResultCols(SQLHSTMT stmt, SQLSMALLINT *ncols)
10492 {
10493 STMT *s;
10494
10495 if (stmt == SQL_NULL_HSTMT) {
10496 return SQL_INVALID_HANDLE;
10497 }
10498 s = (STMT *) stmt;
10499 if (ncols) {
10500 *ncols = s->ncols;
10501 }
10502 return SQL_SUCCESS;
10503 }
10504
10519 static SQLRETURN
10520 drvdescribecol(SQLHSTMT stmt, SQLUSMALLINT col, SQLCHAR *name,
10521 SQLSMALLINT nameMax, SQLSMALLINT *nameLen,
10522 SQLSMALLINT *type, SQLUINTEGER *size,
10523 SQLSMALLINT *digits, SQLSMALLINT *nullable)
10524 {
10525 STMT *s;
10526 COL *c;
10527 int didname = 0;
10528
10529 if (stmt == SQL_NULL_HSTMT) {
10530 return SQL_INVALID_HANDLE;
10531 }
10532 s = (STMT *) stmt;
10533 if (!s->cols) {
10534 setstat(s, -1, "no columns", (*s->ov3) ? "07009" : "S1002");
10535 return SQL_ERROR;
10536 }
10537 if (col < 1 || col > s->ncols) {
10538 setstat(s, -1, "invalid column", (*s->ov3) ? "07009" : "S1002");
10539 return SQL_ERROR;
10540 }
10541 c = s->cols + col - 1;
10542 if (name && nameMax > 0) {
10543 strncpy(name, c->column, nameMax);
10544 name[nameMax - 1] = '\0';
10545 didname = 1;
10546 }
10547 if (nameLen) {
10548 if (didname) {
10549 *nameLen = strlen(name);
10550 } else {
10551 *nameLen = strlen(c->column);
10552 }
10553 }
10554 if (type) {
10555 *type = c->type;
10556 #ifdef SQLITE_UTF8
10557 if (s->nowchar) {
10558 switch (c->type) {
10559 case SQL_WCHAR:
10560 *type = SQL_CHAR;
10561 break;
10562 case SQL_WVARCHAR:
10563 *type = SQL_VARCHAR;
10564 break;
10565 #ifdef SQL_LONGVARCHAR
10566 case SQL_WLONGVARCHAR:
10567 *type = SQL_LONGVARCHAR;
10568 break;
10569 #endif
10570 }
10571 }
10572 #endif
10573 }
10574 if (size) {
10575 *size = c->size;
10576 }
10577 if (digits) {
10578 *digits = 0;
10579 }
10580 if (nullable) {
10581 *nullable = 1;
10582 }
10583 return SQL_SUCCESS;
10584 }
10585
10586 #ifndef SQLITE_UTF8
10587
10601 SQLRETURN SQL_API
10602 SQLDescribeCol(SQLHSTMT stmt, SQLUSMALLINT col, SQLCHAR *name,
10603 SQLSMALLINT nameMax, SQLSMALLINT *nameLen,
10604 SQLSMALLINT *type, SQLUINTEGER *size,
10605 SQLSMALLINT *digits, SQLSMALLINT *nullable)
10606 {
10607 return drvdescribecol(stmt, col, name, nameMax, nameLen,
10608 type, size, digits, nullable);
10609 }
10610 #endif
10611
10612 #ifdef SQLITE_UTF8
10613
10627 SQLRETURN SQL_API
10628 SQLDescribeColW(SQLHSTMT stmt, SQLUSMALLINT col, SQLWCHAR *name,
10629 SQLSMALLINT nameMax, SQLSMALLINT *nameLen,
10630 SQLSMALLINT *type, SQLUINTEGER *size,
10631 SQLSMALLINT *digits, SQLSMALLINT *nullable)
10632 {
10633 SQLRETURN ret;
10634 SQLSMALLINT len;
10635
10636 ret = drvdescribecol(stmt, col, (char *) name,
10637 (SQLSMALLINT) (nameMax * sizeof (SQLWCHAR)),
10638 &len, type, size, digits, nullable);
10639 if (ret == SQL_SUCCESS) {
10640 if (name) {
10641 if (len > 0) {
10642 SQLWCHAR *n = NULL;
10643
10644 n = uc_from_utf((char *) name, len);
10645 if (n) {
10646 uc_strncpy(name, n, nameMax);
10647 len = min(nameMax, uc_strlen(n));
10648 uc_free(n);
10649 } else {
10650 len = 0;
10651 }
10652 }
10653 if (len <= 0) {
10654 len = 0;
10655 if (nameMax > 0) {
10656 name[0] = 0;
10657 }
10658 }
10659 } else {
10660 STMT *s = (STMT *) stmt;
10661 COL *c = s->cols + col - 1;
10662
10663 len = 0;
10664 if (c->column) {
10665 len = strlen(c->column);
10666 }
10667 }
10668 if (nameLen) {
10669 *nameLen = len;
10670 }
10671 }
10672 return ret;
10673 }
10674 #endif
10675
10688 static SQLRETURN
10689 drvcolattributes(SQLHSTMT stmt, SQLUSMALLINT col, SQLUSMALLINT id,
10690 SQLPOINTER val, SQLSMALLINT valMax, SQLSMALLINT *valLen,
10691 SQLINTEGER *val2)
10692 {
10693 STMT *s;
10694 COL *c;
10695 SQLSMALLINT dummy;
10696 char *valc = (char *) val;
10697
10698 if (stmt == SQL_NULL_HSTMT) {
10699 return SQL_INVALID_HANDLE;
10700 }
10701 s = (STMT *) stmt;
10702 if (!s->cols) {
10703 return SQL_ERROR;
10704 }
10705 if (!valLen) {
10706 valLen = &dummy;
10707 }
10708 if (id == SQL_COLUMN_COUNT) {
10709 if (val2) {
10710 *val2 = s->ncols;
10711 }
10712 *valLen = sizeof (int);
10713 return SQL_SUCCESS;
10714 }
10715 if (id == SQL_COLUMN_TYPE && col == 0) {
10716 if (val2) {
10717 *val2 = SQL_INTEGER;
10718 }
10719 *valLen = sizeof (int);
10720 return SQL_SUCCESS;
10721 }
10722 #ifdef SQL_DESC_OCTET_LENGTH
10723 if (id == SQL_DESC_OCTET_LENGTH && col == 0) {
10724 if (val2) {
10725 *val2 = 4;
10726 }
10727 *valLen = sizeof (int);
10728 return SQL_SUCCESS;
10729 }
10730 #endif
10731 if (col < 1 || col > s->ncols) {
10732 setstat(s, -1, "invalid column", (*s->ov3) ? "07009": "S1002");
10733 return SQL_ERROR;
10734 }
10735 c = s->cols + col - 1;
10736
10737 switch (id) {
10738 case SQL_COLUMN_LABEL:
10739 if (c->label) {
10740 if (valc && valMax > 0) {
10741 strncpy(valc, c->label, valMax);
10742 valc[valMax - 1] = '\0';
10743 }
10744 if (valLen) {
10745 *valLen = strlen(c->label);
10746 }
10747 goto checkLen;
10748 }
10749
10750 case SQL_COLUMN_NAME:
10751 case SQL_DESC_NAME:
10752 if (valc && valMax > 0) {
10753 strncpy(valc, c->column, valMax);
10754 valc[valMax - 1] = '\0';
10755 }
10756 *valLen = strlen(c->column);
10757 checkLen:
10758 if (*valLen >= valMax) {
10759 setstat(s, -1, "data right truncated", "01004");
10760 return SQL_SUCCESS_WITH_INFO;
10761 }
10762 return SQL_SUCCESS;
10763 case SQL_COLUMN_TYPE:
10764 case SQL_DESC_TYPE:
10765 #ifdef SQLITE_UTF8
10766 {
10767 int type = c->type;
10768
10769 if (s->nowchar) {
10770 switch (type) {
10771 case SQL_WCHAR:
10772 type = SQL_CHAR;
10773 break;
10774 case SQL_WVARCHAR:
10775 type = SQL_VARCHAR;
10776 break;
10777 #ifdef SQL_LONGVARCHAR
10778 case SQL_WLONGVARCHAR:
10779 type = SQL_LONGVARCHAR;
10780 break;
10781 }
10782 }
10783 if (val2) {
10784 *val2 = type;
10785 }
10786 #endif
10787 }
10788 #else
10789 if (val2) {
10790 *val2 = c->type;
10791 }
10792 #endif
10793 *valLen = sizeof (int);
10794 return SQL_SUCCESS;
10795 case SQL_COLUMN_DISPLAY_SIZE:
10796 if (val2) {
10797 *val2 = c->size;
10798 }
10799 *valLen = sizeof (int);
10800 return SQL_SUCCESS;
10801 case SQL_COLUMN_UNSIGNED:
10802 if (val2) {
10803 *val2 = c->nosign ? SQL_TRUE : SQL_FALSE;
10804 }
10805 *valLen = sizeof (int);
10806 return SQL_SUCCESS;
10807 case SQL_COLUMN_SCALE:
10808 case SQL_DESC_SCALE:
10809 if (val2) {
10810 *val2 = c->scale;
10811 }
10812 *valLen = sizeof (int);
10813 return SQL_SUCCESS;
10814 case SQL_COLUMN_PRECISION:
10815 case SQL_DESC_PRECISION:
10816 if (val2) {
10817 *val2 = c->prec;
10818 }
10819 *valLen = sizeof (int);
10820 return SQL_SUCCESS;
10821 case SQL_COLUMN_MONEY:
10822 if (val2) {
10823 *val2 = SQL_FALSE;
10824 }
10825 *valLen = sizeof (int);
10826 return SQL_SUCCESS;
10827 case SQL_COLUMN_AUTO_INCREMENT:
10828 if (val2) {
10829 *val2 = c->autoinc > 0 ? SQL_TRUE : SQL_FALSE;
10830 }
10831 *valLen = sizeof (int);
10832 return SQL_SUCCESS;
10833 case SQL_COLUMN_LENGTH:
10834 case SQL_DESC_LENGTH:
10835 if (val2) {
10836 *val2 = c->size;
10837 }
10838 *valLen = sizeof (int);
10839 return SQL_SUCCESS;
10840 case SQL_COLUMN_NULLABLE:
10841 case SQL_DESC_NULLABLE:
10842 if (val2) {
10843 *val2 = SQL_NULLABLE;
10844 }
10845 *valLen = sizeof (int);
10846 return SQL_SUCCESS;
10847 case SQL_COLUMN_SEARCHABLE:
10848 if (val2) {
10849 *val2 = SQL_SEARCHABLE;
10850 }
10851 *valLen = sizeof (int);
10852 return SQL_SUCCESS;
10853 case SQL_COLUMN_CASE_SENSITIVE:
10854 if (val2) {
10855 *val2 = SQL_TRUE;
10856 }
10857 *valLen = sizeof (int);
10858 return SQL_SUCCESS;
10859 case SQL_COLUMN_UPDATABLE:
10860 if (val2) {
10861 *val2 = SQL_TRUE;
10862 }
10863 *valLen = sizeof (int);
10864 return SQL_SUCCESS;
10865 case SQL_COLUMN_TYPE_NAME: {
10866 char *tn = c->typename ? c->typename : "varchar";
10867
10868 if (valc && valMax > 0) {
10869 strncpy(valc, tn, valMax);
10870 valc[valMax - 1] = '\0';
10871 }
10872 *valLen = strlen(tn);
10873 goto checkLen;
10874 }
10875 case SQL_COLUMN_OWNER_NAME:
10876 case SQL_COLUMN_QUALIFIER_NAME: {
10877 char *z = "";
10878
10879 if (valc && valMax > 0) {
10880 strncpy(valc, z, valMax);
10881 valc[valMax - 1] = '\0';
10882 }
10883 *valLen = strlen(z);
10884 goto checkLen;
10885 }
10886 case SQL_COLUMN_TABLE_NAME:
10887 #if (SQL_COLUMN_TABLE_NAME != SQL_DESC_TABLE_NAME)
10888 case SQL_DESC_TABLE_NAME:
10889 #endif
10890 if (valc && valMax > 0) {
10891 strncpy(valc, c->table, valMax);
10892 valc[valMax - 1] = '\0';
10893 }
10894 *valLen = strlen(c->table);
10895 goto checkLen;
10896 }
10897 setstat(s, -1, "unsupported column attributes %d", "HY091", id);
10898 return SQL_ERROR;
10899 }
10900
10901 #ifndef SQLITE_UTF8
10902
10914 SQLRETURN SQL_API
10915 SQLColAttributes(SQLHSTMT stmt, SQLUSMALLINT col, SQLUSMALLINT id,
10916 SQLPOINTER val, SQLSMALLINT valMax, SQLSMALLINT *valLen,
10917 SQLINTEGER *val2)
10918 {
10919 return drvcolattributes(stmt, col, id, val, valMax, valLen, val2);
10920 }
10921 #endif
10922
10923 #ifdef SQLITE_UTF8
10924
10936 SQLRETURN SQL_API
10937 SQLColAttributesW(SQLHSTMT stmt, SQLUSMALLINT col, SQLUSMALLINT id,
10938 SQLPOINTER val, SQLSMALLINT valMax, SQLSMALLINT *valLen,
10939 SQLINTEGER *val2)
10940 {
10941 SQLRETURN ret;
10942 SQLSMALLINT len;
10943
10944 ret = drvcolattributes(stmt, col, id, val, valMax, &len, val2);
10945 if (SQL_SUCCEEDED(ret)) {
10946 SQLWCHAR *v = NULL;
10947
10948 switch (id) {
10949 case SQL_COLUMN_LABEL:
10950 case SQL_COLUMN_NAME:
10951 case SQL_DESC_NAME:
10952 case SQL_COLUMN_TYPE_NAME:
10953 case SQL_COLUMN_OWNER_NAME:
10954 case SQL_COLUMN_QUALIFIER_NAME:
10955 case SQL_COLUMN_TABLE_NAME:
10956 #if (SQL_COLUMN_TABLE_NAME != SQL_DESC_TABLE_NAME)
10957 case SQL_DESC_TABLE_NAME:
10958 #endif
10959 if (val && valMax > 0) {
10960 int vmax = valMax / sizeof (SQLWCHAR);
10961
10962 v = uc_from_utf((char *) val, SQL_NTS);
10963 if (v) {
10964 uc_strncpy(val, v, vmax);
10965 len = min(vmax, uc_strlen(v));
10966 uc_free(v);
10967 }
10968 if (vmax > 0) {
10969 v = (SQLWCHAR *) val;
10970 v[vmax - 1] = '\0';
10971 }
10972 }
10973 if (len <= 0) {
10974 len = 0;
10975 }
10976 break;
10977 }
10978 if (valLen) {
10979 *valLen = len;
10980 }
10981 }
10982 return ret;
10983 }
10984 #endif
10985
10998 static SQLRETURN
10999 drvcolattribute(SQLHSTMT stmt, SQLUSMALLINT col, SQLUSMALLINT id,
11000 SQLPOINTER val, SQLSMALLINT valMax, SQLSMALLINT *valLen,
11001 SQLPOINTER val2)
11002 {
11003 STMT *s;
11004 COL *c;
11005 int v = 0;
11006 char *valc = (char *) val;
11007
11008 if (stmt == SQL_NULL_HSTMT) {
11009 return SQL_INVALID_HANDLE;
11010 }
11011 s = (STMT *) stmt;
11012 if (!s->cols) {
11013 return SQL_ERROR;
11014 }
11015 if (col < 1 || col > s->ncols) {
11016 setstat(s, -1, "invalid column", (*s->ov3) ? "07009" : "S1002");
11017 return SQL_ERROR;
11018 }
11019 c = s->cols + col - 1;
11020 switch (id) {
11021 case SQL_DESC_CATALOG_NAME:
11022 if (valc && valMax > 0) {
11023 strncpy(valc, c->db, valMax);
11024 valc[valMax - 1] = '\0';
11025 }
11026 if (valLen) {
11027 *valLen = strlen(c->db);
11028 }
11029 checkLen:
11030 if (valLen && *valLen >= valMax) {
11031 setstat(s, -1, "data right truncated", "01004");
11032 return SQL_SUCCESS_WITH_INFO;
11033 }
11034 break;
11035 case SQL_COLUMN_LENGTH:
11036 case SQL_DESC_LENGTH:
11037 v = c->size;
11038 break;
11039 case SQL_COLUMN_LABEL:
11040 if (c->label) {
11041 if (valc && valMax > 0) {
11042 strncpy(valc, c->label, valMax);
11043 valc[valMax - 1] = '\0';
11044 }
11045 if (valLen) {
11046 *valLen = strlen(c->label);
11047 }
11048 goto checkLen;
11049 }
11050
11051 case SQL_COLUMN_NAME:
11052 case SQL_DESC_NAME:
11053 if (valc && valMax > 0) {
11054 strncpy(valc, c->column, valMax);
11055 valc[valMax - 1] = '\0';
11056 }
11057 if (valLen) {
11058 *valLen = strlen(c->column);
11059 goto checkLen;
11060 }
11061 break;
11062 case SQL_DESC_TYPE_NAME: {
11063 char *tn = c->typename ? c->typename : "varchar";
11064
11065 if (valc && valMax > 0) {
11066 strncpy(valc, tn, valMax);
11067 valc[valMax - 1] = '\0';
11068 }
11069 if (valLen) {
11070 *valLen = strlen(tn);
11071 goto checkLen;
11072 }
11073 break;
11074 }
11075 case SQL_DESC_OCTET_LENGTH:
11076 v = c->size;
11077 break;
11078 #if (SQL_COLUMN_TABLE_NAME != SQL_DESC_TABLE_NAME)
11079 case SQL_COLUMN_TABLE_NAME:
11080 #endif
11081 case SQL_DESC_TABLE_NAME:
11082 if (valc && valMax > 0) {
11083 strncpy(valc, c->table, valMax);
11084 valc[valMax - 1] = '\0';
11085 }
11086 if (valLen) {
11087 *valLen = strlen(c->table);
11088 goto checkLen;
11089 }
11090 break;
11091 case SQL_DESC_TYPE:
11092 v = c->type;
11093 #ifdef SQLITE_UTF8
11094 if (s->nowchar) {
11095 switch (v) {
11096 case SQL_WCHAR:
11097 v = SQL_CHAR;
11098 break;
11099 case SQL_WVARCHAR:
11100 v = SQL_VARCHAR;
11101 break;
11102 #ifdef SQL_LONGVARCHAR
11103 case SQL_WLONGVARCHAR:
11104 v = SQL_LONGVARCHAR;
11105 break;
11106 #endif
11107 }
11108 }
11109 #endif
11110 break;
11111 case SQL_DESC_CONCISE_TYPE:
11112 switch (c->type) {
11113 case SQL_INTEGER:
11114 v = SQL_C_LONG;
11115 break;
11116 case SQL_TINYINT:
11117 v = SQL_C_TINYINT;
11118 break;
11119 case SQL_SMALLINT:
11120 v = SQL_C_SHORT;
11121 break;
11122 case SQL_FLOAT:
11123 v = SQL_C_FLOAT;
11124 break;
11125 case SQL_DOUBLE:
11126 v = SQL_C_DOUBLE;
11127 break;
11128 case SQL_TIMESTAMP:
11129 v = SQL_C_TIMESTAMP;
11130 break;
11131 case SQL_TIME:
11132 v = SQL_C_TIME;
11133 break;
11134 case SQL_DATE:
11135 v = SQL_C_DATE;
11136 break;
11137 #ifdef SQL_C_TYPE_TIMESTAMP
11138 case SQL_TYPE_TIMESTAMP:
11139 v = SQL_C_TYPE_TIMESTAMP;
11140 break;
11141 #endif
11142 #ifdef SQL_C_TYPE_TIME
11143 case SQL_TYPE_TIME:
11144 v = SQL_C_TYPE_TIME;
11145 break;
11146 #endif
11147 #ifdef SQL_C_TYPE_DATE
11148 case SQL_TYPE_DATE:
11149 v = SQL_C_TYPE_DATE;
11150 break;
11151 #endif
11152 default:
11153 #ifdef SQLITE_UTF8
11154 v = s->nowchar ? SQL_C_CHAR : SQL_C_WCHAR;
11155 #else
11156 v = SQL_C_CHAR;
11157 #endif
11158 break;
11159 }
11160 break;
11161 case SQL_DESC_UPDATABLE:
11162 v = SQL_TRUE;
11163 break;
11164 case SQL_COLUMN_DISPLAY_SIZE:
11165 v = c->size;
11166 break;
11167 case SQL_COLUMN_UNSIGNED:
11168 v = c->nosign ? SQL_TRUE : SQL_FALSE;
11169 break;
11170 case SQL_COLUMN_SEARCHABLE:
11171 v = SQL_SEARCHABLE;
11172 break;
11173 case SQL_COLUMN_SCALE:
11174 case SQL_DESC_SCALE:
11175 v = c->scale;
11176 break;
11177 case SQL_COLUMN_PRECISION:
11178 case SQL_DESC_PRECISION:
11179 v = c->prec;
11180 break;
11181 case SQL_COLUMN_MONEY:
11182 v = SQL_FALSE;
11183 break;
11184 case SQL_COLUMN_AUTO_INCREMENT:
11185 v = c->autoinc > 0 ? SQL_TRUE : SQL_FALSE;
11186 break;
11187 case SQL_DESC_NULLABLE:
11188 v = SQL_NULLABLE;
11189 break;
11190 default:
11191 setstat(s, -1, "unsupported column attribute %d", "HY091", id);
11192 return SQL_ERROR;
11193 }
11194 if (val2) {
11195 *(int *) val2 = v;
11196 }
11197 return SQL_SUCCESS;
11198 }
11199
11200 #ifndef SQLITE_UTF8
11201
11213 SQLRETURN SQL_API
11214 SQLColAttribute(SQLHSTMT stmt, SQLUSMALLINT col, SQLUSMALLINT id,
11215 SQLPOINTER val, SQLSMALLINT valMax, SQLSMALLINT *valLen,
11216 SQLPOINTER val2)
11217 {
11218 return drvcolattribute(stmt, col, id, val, valMax, valLen, val2);
11219 }
11220 #endif
11221
11222 #ifdef SQLITE_UTF8
11223
11235 SQLRETURN SQL_API
11236 SQLColAttributeW(SQLHSTMT stmt, SQLUSMALLINT col, SQLUSMALLINT id,
11237 SQLPOINTER val, SQLSMALLINT valMax, SQLSMALLINT *valLen,
11238 SQLPOINTER val2)
11239 {
11240 SQLRETURN ret;
11241 SQLSMALLINT len;
11242
11243 ret = drvcolattribute(stmt, col, id, val, valMax, &len, val2);
11244 if (SQL_SUCCEEDED(ret)) {
11245 SQLWCHAR *v = NULL;
11246
11247 switch (id) {
11248 case SQL_DESC_CATALOG_NAME:
11249 case SQL_COLUMN_LABEL:
11250 case SQL_DESC_NAME:
11251 case SQL_DESC_TABLE_NAME:
11252 case SQL_DESC_TYPE_NAME:
11253 if (val && valMax > 0) {
11254 int vmax = valMax / sizeof (SQLWCHAR);
11255
11256 v = uc_from_utf((char *) val, SQL_NTS);
11257 if (v) {
11258 uc_strncpy(val, v, vmax);
11259 len = min(vmax, uc_strlen(v));
11260 uc_free(v);
11261 }
11262 if (vmax > 0) {
11263 v = (SQLWCHAR *) val;
11264 v[vmax - 1] = '\0';
11265 }
11266 }
11267 if (len <= 0) {
11268 len = 0;
11269 }
11270 break;
11271 }
11272 if (valLen) {
11273 *valLen = len;
11274 }
11275 }
11276 return ret;
11277 }
11278 #endif
11279
11293 static SQLRETURN
11294 drverror(SQLHENV env, SQLHDBC dbc, SQLHSTMT stmt,
11295 SQLCHAR *sqlState, SQLINTEGER *nativeErr,
11296 SQLCHAR *errmsg, SQLSMALLINT errmax, SQLSMALLINT *errlen)
11297 {
11298 SQLCHAR dummy0[6];
11299 SQLINTEGER dummy1;
11300 SQLSMALLINT dummy2;
11301
11302 if (env == SQL_NULL_HENV &&
11303 dbc == SQL_NULL_HDBC &&
11304 stmt == SQL_NULL_HSTMT) {
11305 return SQL_INVALID_HANDLE;
11306 }
11307 if (sqlState) {
11308 sqlState[0] = '\0';
11309 } else {
11310 sqlState = dummy0;
11311 }
11312 if (!nativeErr) {
11313 nativeErr = &dummy1;
11314 }
11315 *nativeErr = 0;
11316 if (!errlen) {
11317 errlen = &dummy2;
11318 }
11319 *errlen = 0;
11320 if (errmsg) {
11321 if (errmax > 0) {
11322 errmsg[0] = '\0';
11323 }
11324 } else {
11325 errmsg = dummy0;
11326 errmax = 0;
11327 }
11328 if (stmt) {
11329 STMT *s = (STMT *) stmt;
11330
11331 if (s->logmsg[0] == '\0') {
11332 goto noerr;
11333 }
11334 *nativeErr = s->naterr;
11335 strcpy(sqlState, s->sqlstate);
11336 if (errmax == SQL_NTS) {
11337 strcpy(errmsg, "[SQLite]");
11338 strcat(errmsg, s->logmsg);
11339 *errlen = strlen(errmsg);
11340 } else {
11341 strncpy(errmsg, "[SQLite]", errmax);
11342 if (errmax - 8 > 0) {
11343 strncpy(errmsg + 8, s->logmsg, errmax - 8);
11344 }
11345 *errlen = min(strlen(s->logmsg) + 8, errmax);
11346 }
11347 s->logmsg[0] = '\0';
11348 return SQL_SUCCESS;
11349 }
11350 if (dbc) {
11351 DBC *d = (DBC *) dbc;
11352
11353 if (d->magic != DBC_MAGIC || d->logmsg[0] == '\0') {
11354 goto noerr;
11355 }
11356 *nativeErr = d->naterr;
11357 strcpy(sqlState, d->sqlstate);
11358 if (errmax == SQL_NTS) {
11359 strcpy(errmsg, "[SQLite]");
11360 strcat(errmsg, d->logmsg);
11361 *errlen = strlen(errmsg);
11362 } else {
11363 strncpy(errmsg, "[SQLite]", errmax);
11364 if (errmax - 8 > 0) {
11365 strncpy(errmsg + 8, d->logmsg, errmax - 8);
11366 }
11367 *errlen = min(strlen(d->logmsg) + 8, errmax);
11368 }
11369 d->logmsg[0] = '\0';
11370 return SQL_SUCCESS;
11371 }
11372 noerr:
11373 sqlState[0] = '\0';
11374 errmsg[0] = '\0';
11375 *nativeErr = 0;
11376 *errlen = 0;
11377 return SQL_NO_DATA_FOUND;
11378 }
11379
11380 #ifndef SQLITE_UTF8
11381
11394 SQLRETURN SQL_API
11395 SQLError(SQLHENV env, SQLHDBC dbc, SQLHSTMT stmt,
11396 SQLCHAR *sqlState, SQLINTEGER *nativeErr,
11397 SQLCHAR *errmsg, SQLSMALLINT errmax, SQLSMALLINT *errlen)
11398 {
11399 return drverror(env, dbc, stmt, sqlState, nativeErr,
11400 errmsg, errmax, errlen);
11401 }
11402 #endif
11403
11404 #ifdef SQLITE_UTF8
11405
11418 SQLRETURN SQL_API
11419 SQLErrorW(SQLHENV env, SQLHDBC dbc, SQLHSTMT stmt,
11420 SQLWCHAR *sqlState, SQLINTEGER *nativeErr,
11421 SQLWCHAR *errmsg, SQLSMALLINT errmax, SQLSMALLINT *errlen)
11422 {
11423 char state[16];
11424 SQLSMALLINT len;
11425 SQLRETURN ret;
11426
11427 ret = drverror(env, dbc, stmt, state, nativeErr,
11428 (char *) errmsg, errmax, &len);
11429 if (ret == SQL_SUCCESS) {
11430 if (sqlState) {
11431 uc_from_utf_buf(state, sqlState, 6 * sizeof (SQLWCHAR));
11432 }
11433 if (errmsg) {
11434 if (len > 0) {
11435 SQLWCHAR *e = NULL;
11436
11437 e = uc_from_utf((char *) errmsg, len);
11438 if (e) {
11439 if (errmax > 0) {
11440 uc_strncpy(errmsg, e, errmax);
11441 len = min(errmax, uc_strlen(e));
11442 } else {
11443 len = uc_strlen(e);
11444 }
11445 uc_free(e);
11446 } else {
11447 len = 0;
11448 }
11449 }
11450 if (len <= 0) {
11451 len = 0;
11452 if (errmax > 0) {
11453 errmsg[0] = 0;
11454 }
11455 }
11456 } else {
11457 len = 0;
11458 }
11459 if (errlen) {
11460 *errlen = len;
11461 }
11462 } else if (ret == SQL_NO_DATA) {
11463 if (sqlState) {
11464 sqlState[0] = 0;
11465 }
11466 if (errmsg) {
11467 if (errmax > 0) {
11468 errmsg[0] = 0;
11469 }
11470 }
11471 if (errlen) {
11472 *errlen = 0;
11473 }
11474 }
11475 return ret;
11476 }
11477 #endif
11478
11485 SQLRETURN SQL_API
11486 SQLMoreResults(SQLHSTMT stmt)
11487 {
11488 if (stmt == SQL_NULL_HSTMT) {
11489 return SQL_INVALID_HANDLE;
11490 }
11491 return SQL_NO_DATA;
11492 }
11493
11503 static int
11504 selcb(void *arg, int ncols, char **values, char **cols)
11505 {
11506 STMT *s = (STMT *) arg;
11507
11508 if (ncols > 0) {
11509 int i, size;
11510 char *p;
11511 COL *dyncols;
11512 DBC *d = (DBC *) s->dbc;
11513
11514 for (i = size = 0; i < ncols; i++) {
11515 size += 3 + 3 * strlen(cols[i]);
11516 }
11517 dyncols = xmalloc(ncols * sizeof (COL) + size);
11518 if (!dyncols) {
11519 freedyncols(s);
11520 s->ncols = 0;
11521 return 1;
11522 }
11523 p = (char *) (dyncols + ncols);
11524 for (i = 0; i < ncols; i++) {
11525 char *q;
11526
11527 dyncols[i].db = ((DBC *) (s->dbc))->dbname;
11528 strcpy(p, cols[i]);
11529 dyncols[i].label = p;
11530 p += strlen(p) + 1;
11531 q = strchr(cols[i], '.');
11532 if (q) {
11533 dyncols[i].table = p;
11534 strncpy(p, cols[i], q - cols[i]);
11535 p[q - cols[i]] = '\0';
11536 p += strlen(p) + 1;
11537 strcpy(p, q + 1);
11538 dyncols[i].column = p;
11539 p += strlen(p) + 1;
11540 } else {
11541 dyncols[i].table = "";
11542 strcpy(p, cols[i]);
11543 dyncols[i].column = p;
11544 p += strlen(p) + 1;
11545 }
11546 #ifdef SQL_LONGVARCHAR
11547 dyncols[i].type = SQL_LONGVARCHAR;
11548 dyncols[i].size = 65536;
11549 #else
11550 dyncols[i].type = SQL_VARCHAR;
11551 dyncols[i].size = 256;
11552 #endif
11553 dyncols[i].index = i;
11554 dyncols[i].scale = 0;
11555 dyncols[i].prec = 0;
11556 dyncols[i].nosign = 1;
11557 dyncols[i].autoinc = -1;
11558 dyncols[i].typename = NULL;
11559 }
11560 freedyncols(s);
11561 s->dyncols = s->cols = dyncols;
11562 s->dcols = ncols;
11563 fixupdyncols(s, d->sqlite, (const char **) cols + ncols);
11564 }
11565 s->ncols = ncols;
11566 return 1;
11567 }
11568
11577 static SQLRETURN
11578 drvprepare(SQLHSTMT stmt, SQLCHAR *query, SQLINTEGER queryLen)
11579 {
11580 STMT *s;
11581 DBC *d;
11582 char *errp = NULL;
11583
11584 if (stmt == SQL_NULL_HSTMT) {
11585 return SQL_INVALID_HANDLE;
11586 }
11587 s = (STMT *) stmt;
11588 if (s->dbc == SQL_NULL_HDBC) {
11589 noconn:
11590 return noconn(s);
11591 }
11592 d = s->dbc;
11593 if (!d->sqlite) {
11594 goto noconn;
11595 }
11596 vm_end(s);
11597 freep(&s->query);
11598 s->query = fixupsql(query, queryLen, &s->nparams, &s->isselect, &errp,
11599 d->version, &s->parmnames);
11600 if (!s->query) {
11601 if (errp) {
11602 setstat(s, -1, errp, (*s->ov3) ? "HY000" : "S1000");
11603 return SQL_ERROR;
11604 }
11605 return nomem(s);
11606 }
11607 errp = NULL;
11608 freeresult(s, -1);
11609 if (s->isselect) {
11610 int ret;
11611 char **params = NULL;
11612
11613 if (s->nparams) {
11614 int i;
11615
11616 params = xmalloc(s->nparams * sizeof (char *));
11617 if (!params) {
11618 return nomem(s);
11619 }
11620 for (i = 0; i < s->nparams; i++) {
11621 params[i] = NULL;
11622 }
11623 }
11624 ret = sqlite_exec_vprintf(d->sqlite, s->query, selcb, s,
11625 &errp, (char *) params);
11626 if (ret != SQLITE_ABORT && ret != SQLITE_OK) {
11627 dbtracerc(d, ret, errp);
11628 freep(¶ms);
11629 setstat(s, ret, "%s (%d)", (*s->ov3) ? "HY000" : "S1000",
11630 errp ? errp : "unknown error", ret);
11631 if (errp) {
11632 sqlite_freemem(errp);
11633 errp = NULL;
11634 }
11635 return SQL_ERROR;
11636 }
11637 freep(¶ms);
11638 if (errp) {
11639 sqlite_freemem(errp);
11640 errp = NULL;
11641 }
11642 }
11643 mkbindcols(s, s->ncols);
11644 if (s->nparams) {
11645 s->paramset_count = 0;
11646 }
11647 return SQL_SUCCESS;
11648 }
11649
11650
11651
11652 static SQLRETURN
11653 drvexecute(SQLHSTMT stmt)
11654 {
11655 STMT *s;
11656 DBC *d;
11657 char *errp = NULL, **params = NULL;
11658 int rc, i, size, ncols;
11659 SQLRETURN ret;
11660
11661 if (stmt == SQL_NULL_HSTMT) {
11662 return SQL_INVALID_HANDLE;
11663 }
11664 s = (STMT *) stmt;
11665 if (s->dbc == SQL_NULL_HDBC) {
11666 noconn:
11667 return noconn(s);
11668 }
11669 d = (DBC *) s->dbc;
11670 if (!d->sqlite) {
11671 goto noconn;
11672 }
11673 if (!s->query) {
11674 setstat(s, -1, "no query prepared", (*s->ov3) ? "HY000" : "S1000");
11675 return SQL_ERROR;
11676 }
11677 if (s->nbindparms < s->nparams) {
11678 setstat(s, -1, "unbound parameters in query",
11679 (*s->ov3) ? "HY000" : "S1000");
11680 return SQL_ERROR;
11681 }
11682 again:
11683 vm_end(s);
11684 for (i = size = 0; i < s->nparams; i++) {
11685 ret = substparam(s, i, NULL, &size);
11686 if (ret != SQL_SUCCESS) {
11687 goto cleanup;
11688 }
11689 }
11690 if (s->nparams) {
11691 char *p;
11692
11693 params = xmalloc(s->nparams * sizeof (char *) + size);
11694 if (!params) {
11695 ret = nomem(s);
11696 goto cleanup;
11697 }
11698 p = (char *) (params + s->nparams);
11699 for (i = 0; i < s->nparams; i++) {
11700 int len = 0;
11701
11702 params[i] = p;
11703 substparam(s, i, &p, NULL);
11704 if (s->bindparms[i].ind) {
11705 len = s->bindparms[i].len;
11706 } else if (s->bindparms[i].lenp) {
11707 len = *s->bindparms[i].lenp;
11708 }
11709 if (len == SQL_NULL_DATA) {
11710 params[i] = NULL;
11711 }
11712 }
11713 }
11714 freeresult(s, 0);
11715 if (!d->autocommit && !d->intrans) {
11716 rc = sqlite_exec(d->sqlite, "BEGIN TRANSACTION", NULL, NULL, &errp);
11717 dbtracerc(d, rc, errp);
11718 if (rc != SQLITE_OK) {
11719 freep(¶ms);
11720 setstat(s, rc, "%s (%d)", (*s->ov3) ? "HY000" : "S1000",
11721 errp ? errp : "unknown error", rc);
11722 if (errp) {
11723 sqlite_freemem(errp);
11724 errp = NULL;
11725 }
11726 ret = SQL_ERROR;
11727 goto cleanup;
11728 }
11729 d->intrans = 1;
11730 if (errp) {
11731 sqlite_freemem(errp);
11732 errp = NULL;
11733 }
11734 }
11735 if (s->isselect && !d->intrans &&
11736 s->curtype == SQL_CURSOR_FORWARD_ONLY &&
11737 d->step_enable && s->nparams == 0 && d->vm_stmt == NULL) {
11738 s->nrows = -1;
11739 ret = vm_start(s, params);
11740 if (ret == SQL_SUCCESS) {
11741 freep(¶ms);
11742 goto done2;
11743 }
11744 }
11745 rc = sqlite_get_table_vprintf(d->sqlite, s->query, &s->rows,
11746 &s->nrows, &ncols, &errp, (char *) params);
11747 dbtracerc(d, rc, errp);
11748 if (rc != SQLITE_OK) {
11749 freep(¶ms);
11750 setstat(s, rc, "%s (%d)", (*s->ov3) ? "HY000" : "S1000",
11751 errp ? errp : "unknown error", rc);
11752 if (errp) {
11753 sqlite_freemem(errp);
11754 errp = NULL;
11755 }
11756 ret = SQL_ERROR;
11757 goto cleanup;
11758 }
11759 freep(¶ms);
11760 if (errp) {
11761 sqlite_freemem(errp);
11762 errp = NULL;
11763 }
11764 s->rowfree = sqlite_free_table;
11765 if (ncols == 1 && !s->isselect) {
11766
11767
11768
11769
11770 if (strcmp(s->rows[0], "rows inserted") == 0 ||
11771 strcmp(s->rows[0], "rows updated") == 0 ||
11772 strcmp(s->rows[0], "rows deleted") == 0) {
11773 int nrows = 0;
11774
11775 nrows = strtol(s->rows[1], NULL, 0);
11776 freeresult(s, -1);
11777 s->nrows = nrows;
11778 goto done;
11779 }
11780 }
11781 if (s->ncols != ncols) {
11782 int size;
11783 char *p;
11784 COL *dyncols;
11785
11786 for (i = size = 0; i < ncols; i++) {
11787 size += 3 + 3 * strlen(s->rows[i]);
11788 }
11789 if (size == 0) {
11790 freeresult(s, -1);
11791 goto done;
11792 }
11793 dyncols = xmalloc(ncols * sizeof (COL) + size);
11794 if (!dyncols) {
11795 ret = nomem(s);
11796 goto cleanup;
11797 }
11798 p = (char *) (dyncols + ncols);
11799 for (i = 0; i < ncols; i++) {
11800 char *q;
11801
11802 dyncols[i].db = d->dbname;
11803 strcpy(p, s->rows[i]);
11804 dyncols[i].label = p;
11805 p += strlen(p) + 1;
11806 q = strchr(s->rows[i], '.');
11807 if (q) {
11808 dyncols[i].table = p;
11809 strncpy(p, s->rows[i], q - s->rows[i]);
11810 p[q - s->rows[i]] = '\0';
11811 p += strlen(p) + 1;
11812 dyncols[i].column = q + 1;
11813 } else {
11814 dyncols[i].table = "";
11815 dyncols[i].column = s->rows[i];
11816 }
11817 #ifdef SQL_LONGVARCHAR
11818 dyncols[i].type = SQL_LONGVARCHAR;
11819 dyncols[i].size = 65536;
11820 #else
11821 dyncols[i].type = SQL_VARCHAR;
11822 dyncols[i].size = 255;
11823 #endif
11824 dyncols[i].index = i;
11825 dyncols[i].scale = 0;
11826 dyncols[i].prec = 0;
11827 dyncols[i].nosign = 1;
11828 dyncols[i].autoinc = -1;
11829 dyncols[i].typename = NULL;
11830 }
11831 freedyncols(s);
11832 s->ncols = s->dcols = ncols;
11833 s->dyncols = s->cols = dyncols;
11834 fixupdyncols(s, d->sqlite, NULL);
11835 }
11836 done:
11837 mkbindcols(s, s->ncols);
11838 done2:
11839 ret = SQL_SUCCESS;
11840 s->rowp = -1;
11841 if (s->nparams) {
11842 s->paramset_count++;
11843 s->paramset_nrows += s->nrows;
11844 if (s->paramset_count < s->paramset_size) {
11845 for (i = 0; i < s->nparams; i++) {
11846 BINDPARM *p = &s->bindparms[i];
11847
11848 if (p->param && p->inc > 0) {
11849 p->param = (char *) p->param + p->inc;
11850 }
11851 }
11852 goto again;
11853 }
11854 }
11855 cleanup:
11856 if (s->nparams) {
11857 for (i = 0; i < s->nparams; i++) {
11858 BINDPARM *p = &s->bindparms[i];
11859
11860 p->param = p->param0;
11861 }
11862 s->nrows = s->paramset_nrows;
11863 s->paramset_count = 0;
11864 s->paramset_nrows = 0;
11865 }
11866 return ret;
11867 }
11868
11869 #ifndef SQLITE_UTF8
11870
11878 SQLRETURN SQL_API
11879 SQLPrepare(SQLHSTMT stmt, SQLCHAR *query, SQLINTEGER queryLen)
11880 {
11881 return drvprepare(stmt, query, queryLen);
11882 }
11883 #endif
11884
11885 #ifdef SQLITE_UTF8
11886
11894 SQLRETURN SQL_API
11895 SQLPrepareW(SQLHSTMT stmt, SQLWCHAR *query, SQLINTEGER queryLen)
11896 {
11897 SQLRETURN ret;
11898 char *q = uc_to_utf_c(query, queryLen);
11899
11900 if (!q) {
11901 return nomem((STMT *) stmt);
11902 }
11903 ret = drvprepare(stmt, q, SQL_NTS);
11904 uc_free(q);
11905 return ret;
11906 }
11907 #endif
11908
11915 SQLRETURN SQL_API
11916 SQLExecute(SQLHSTMT stmt)
11917 {
11918 return drvexecute(stmt);
11919 }
11920
11921 #ifndef SQLITE_UTF8
11922
11930 SQLRETURN SQL_API
11931 SQLExecDirect(SQLHSTMT stmt, SQLCHAR *query, SQLINTEGER queryLen)
11932 {
11933 if (drvprepare(stmt, query, queryLen) != SQL_SUCCESS) {
11934 return SQL_ERROR;
11935 }
11936 return drvexecute(stmt);
11937 }
11938 #endif
11939
11940 #ifdef SQLITE_UTF8
11941
11949 SQLRETURN SQL_API
11950 SQLExecDirectW(SQLHSTMT stmt, SQLWCHAR *query, SQLINTEGER queryLen)
11951 {
11952 SQLRETURN ret;
11953 char *q = uc_to_utf_c(query, queryLen);
11954
11955 if (!q) {
11956 return nomem((STMT *) stmt);
11957 }
11958 ret = drvprepare(stmt, q, SQL_NTS);
11959 uc_free(q);
11960 if (ret == SQL_SUCCESS) {
11961 return drvexecute(stmt);
11962 }
11963 return ret;
11964 }
11965 #endif
11966
11967 #ifdef _WIN32
11968 #ifndef WITHOUT_DRIVERMGR
11969
11970
11971
11972
11973
11974 #include <windowsx.h>
11975 #include <winuser.h>
11976
11977 #define stricmp _stricmp
11978
11979 static HINSTANCE NEAR hModule;
11980
11981 #define MAXPATHLEN (255+1)
11982 #define MAXKEYLEN (15+1)
11983 #define MAXDESC (255+1)
11984 #define MAXDSNAME (32+1)
11985 #define MAXTONAME (32+1)
11986 #define MAXDBNAME (255+1)
11987
11988
11989
11990 #define KEY_DSN 0
11991 #define KEY_DESC 1
11992 #define KEY_DBNAME 2
11993 #define KEY_BUSY 3
11994 #define KEY_DRIVER 4
11995 #define KEY_NOWCHAR 5
11996 #define KEY_STEPAPI 6
11997 #define NUMOFKEYS 7
11998
11999 typedef struct {
12000 BOOL supplied;
12001 char attr[MAXPATHLEN];
12002 } ATTR;
12003
12004 typedef struct {
12005 SQLHWND parent;
12006 LPCSTR driver;
12007 ATTR attr[NUMOFKEYS];
12008 char DSN[MAXDSNAME];
12009 BOOL newDSN;
12010 BOOL defDSN;
12011 } SETUPDLG;
12012
12013 static struct {
12014 char *key;
12015 int ikey;
12016 } attrLookup[] = {
12017 { "DSN", KEY_DSN },
12018 { "DESC", KEY_DESC },
12019 { "Description", KEY_DESC},
12020 { "Database", KEY_DBNAME },
12021 { "Timeout", KEY_BUSY },
12022 { "Driver", KEY_DRIVER },
12023 { "NoWCHAR", KEY_NOWCHAR },
12024 { "StepAPI", KEY_STEPAPI },
12025 { NULL, 0 }
12026 };
12027
12034 static void
12035 ParseAttributes(LPCSTR attribs, SETUPDLG *setupdlg)
12036 {
12037 char *str = (char *) attribs, *start, key[MAXKEYLEN];
12038 int elem, nkey;
12039
12040 while (*str) {
12041 start = str;
12042 if ((str = strchr(str, '=')) == NULL) {
12043 return;
12044 }
12045 elem = -1;
12046 nkey = str - start;
12047 if (nkey < sizeof (key)) {
12048 int i;
12049
12050 memcpy(key, start, nkey);
12051 key[nkey] = '\0';
12052 for (i = 0; attrLookup[i].key; i++) {
12053 if (stricmp(attrLookup[i].key, key) == 0) {
12054 elem = attrLookup[i].ikey;
12055 break;
12056 }
12057 }
12058 }
12059 start = ++str;
12060 while (*str && *str != ';') {
12061 ++str;
12062 }
12063 if (elem >= 0) {
12064 int end = min(str - start, sizeof (setupdlg->attr[elem].attr) - 1);
12065
12066 setupdlg->attr[elem].supplied = TRUE;
12067 memcpy(setupdlg->attr[elem].attr, start, end);
12068 setupdlg->attr[elem].attr[end] = '\0';
12069 }
12070 ++str;
12071 }
12072 }
12073
12081 static BOOL
12082 SetDSNAttributes(HWND parent, SETUPDLG *setupdlg)
12083 {
12084 char *dsn = setupdlg->attr[KEY_DSN].attr;
12085
12086 if (setupdlg->newDSN && strlen(dsn) == 0) {
12087 return FALSE;
12088 }
12089 if (!SQLWriteDSNToIni(dsn, setupdlg->driver)) {
12090 if (parent) {
12091 char buf[MAXPATHLEN], msg[MAXPATHLEN];
12092
12093 LoadString(hModule, IDS_BADDSN, buf, sizeof (buf));
12094 wsprintf(msg, buf, dsn);
12095 LoadString(hModule, IDS_MSGTITLE, buf, sizeof (buf));
12096 MessageBox(parent, msg, buf,
12097 MB_ICONEXCLAMATION | MB_OK | MB_TASKMODAL |
12098 MB_SETFOREGROUND);
12099 }
12100 return FALSE;
12101 }
12102 if (parent || setupdlg->attr[KEY_DESC].supplied) {
12103 SQLWritePrivateProfileString(dsn, "Description",
12104 setupdlg->attr[KEY_DESC].attr,
12105 ODBC_INI);
12106 }
12107 if (parent || setupdlg->attr[KEY_DBNAME].supplied) {
12108 SQLWritePrivateProfileString(dsn, "Database",
12109 setupdlg->attr[KEY_DBNAME].attr,
12110 ODBC_INI);
12111 }
12112 if (parent || setupdlg->attr[KEY_BUSY].supplied) {
12113 SQLWritePrivateProfileString(dsn, "Timeout",
12114 setupdlg->attr[KEY_BUSY].attr,
12115 ODBC_INI);
12116 }
12117 if (parent || setupdlg->attr[KEY_NOWCHAR].supplied) {
12118 SQLWritePrivateProfileString(dsn, "NoWCHAR",
12119 setupdlg->attr[KEY_NOWCHAR].attr,
12120 ODBC_INI);
12121 }
12122 if (parent || setupdlg->attr[KEY_STEPAPI].supplied) {
12123 SQLWritePrivateProfileString(dsn, "StepAPI",
12124 setupdlg->attr[KEY_STEPAPI].attr,
12125 ODBC_INI);
12126 }
12127 if (setupdlg->attr[KEY_DSN].supplied &&
12128 stricmp(setupdlg->DSN, setupdlg->attr[KEY_DSN].attr)) {
12129 SQLRemoveDSNFromIni(setupdlg->DSN);
12130 }
12131 return TRUE;
12132 }
12133
12139 static void
12140 GetAttributes(SETUPDLG *setupdlg)
12141 {
12142 char *dsn = setupdlg->attr[KEY_DSN].attr;
12143
12144 if (!setupdlg->attr[KEY_DESC].supplied) {
12145 SQLGetPrivateProfileString(dsn, "Description", "",
12146 setupdlg->attr[KEY_DESC].attr,
12147 sizeof (setupdlg->attr[KEY_DESC].attr),
12148 ODBC_INI);
12149 }
12150 if (!setupdlg->attr[KEY_DBNAME].supplied) {
12151 SQLGetPrivateProfileString(dsn, "Database", "",
12152 setupdlg->attr[KEY_DBNAME].attr,
12153 sizeof (setupdlg->attr[KEY_DBNAME].attr),
12154 ODBC_INI);
12155 }
12156 if (!setupdlg->attr[KEY_BUSY].supplied) {
12157 SQLGetPrivateProfileString(dsn, "Timeout", "1000",
12158 setupdlg->attr[KEY_BUSY].attr,
12159 sizeof (setupdlg->attr[KEY_BUSY].attr),
12160 ODBC_INI);
12161 }
12162 if (!setupdlg->attr[KEY_NOWCHAR].supplied) {
12163 SQLGetPrivateProfileString(dsn, "NoWCHAR", "",
12164 setupdlg->attr[KEY_NOWCHAR].attr,
12165 sizeof (setupdlg->attr[KEY_NOWCHAR].attr),
12166 ODBC_INI);
12167 }
12168 if (!setupdlg->attr[KEY_STEPAPI].supplied) {
12169 SQLGetPrivateProfileString(dsn, "StepAPI", "0",
12170 setupdlg->attr[KEY_STEPAPI].attr,
12171 sizeof (setupdlg->attr[KEY_STEPAPI].attr),
12172 ODBC_INI);
12173 }
12174 }
12175
12181 static void
12182 GetDBFile(HWND hdlg)
12183 {
12184 SETUPDLG *setupdlg = (SETUPDLG *) GetWindowLong(hdlg, DWL_USER);
12185 OPENFILENAME ofn;
12186
12187 memset(&ofn, 0, sizeof (ofn));
12188 ofn.lStructSize = sizeof (ofn);
12189 ofn.hwndOwner = hdlg;
12190 ofn.hInstance = (HINSTANCE) GetWindowLong(hdlg, GWL_HINSTANCE);
12191 ofn.lpstrFile = (LPTSTR) setupdlg->attr[KEY_DBNAME].attr;
12192 ofn.nMaxFile = MAXPATHLEN;
12193 ofn.Flags = OFN_HIDEREADONLY | OFN_PATHMUSTEXIST |
12194 OFN_NOCHANGEDIR | OFN_EXPLORER | OFN_FILEMUSTEXIST;
12195 if (GetOpenFileName(&ofn)) {
12196 SetDlgItemText(hdlg, IDC_DBNAME, setupdlg->attr[KEY_DBNAME].attr);
12197 setupdlg->attr[KEY_DBNAME].supplied = TRUE;
12198 }
12199 }
12200
12210 static BOOL CALLBACK
12211 ConfigDlgProc(HWND hdlg, WORD wmsg, WPARAM wparam, LPARAM lparam)
12212 {
12213 SETUPDLG *setupdlg = NULL;
12214
12215 switch (wmsg) {
12216 case WM_INITDIALOG:
12217 SetWindowLong(hdlg, DWL_USER, lparam);
12218 setupdlg = (SETUPDLG *) lparam;
12219 GetAttributes(setupdlg);
12220 SetDlgItemText(hdlg, IDC_DSNAME, setupdlg->attr[KEY_DSN].attr);
12221 SetDlgItemText(hdlg, IDC_DESC, setupdlg->attr[KEY_DESC].attr);
12222 SetDlgItemText(hdlg, IDC_DBNAME, setupdlg->attr[KEY_DBNAME].attr);
12223 SetDlgItemText(hdlg, IDC_TONAME, setupdlg->attr[KEY_BUSY].attr);
12224 CheckDlgButton(hdlg, IDC_NOWCHAR,
12225 getbool(setupdlg->attr[KEY_NOWCHAR].attr) ?
12226 BST_CHECKED : BST_UNCHECKED);
12227 CheckDlgButton(hdlg, IDC_STEPAPI,
12228 getbool(setupdlg->attr[KEY_STEPAPI].attr) ?
12229 BST_CHECKED : BST_UNCHECKED);
12230 if (setupdlg->defDSN) {
12231 EnableWindow(GetDlgItem(hdlg, IDC_DSNAME), FALSE);
12232 EnableWindow(GetDlgItem(hdlg, IDC_DSNAMETEXT), FALSE);
12233 } else {
12234 SendDlgItemMessage(hdlg, IDC_DSNAME,
12235 EM_LIMITTEXT, (WPARAM) (MAXDSNAME - 1), 0L);
12236 SendDlgItemMessage(hdlg, IDC_DESC,
12237 EM_LIMITTEXT, (WPARAM) (MAXDESC - 1), 0L);
12238 SendDlgItemMessage(hdlg, IDC_DBNAME,
12239 EM_LIMITTEXT, (WPARAM) (MAXDBNAME - 1), 0L);
12240 SendDlgItemMessage(hdlg, IDC_TONAME,
12241 EM_LIMITTEXT, (WPARAM) (MAXTONAME - 1), 0L);
12242 }
12243 return TRUE;
12244 case WM_COMMAND:
12245 switch (GET_WM_COMMAND_ID(wparam, lparam)) {
12246 case IDC_DSNAME:
12247 if (GET_WM_COMMAND_CMD(wparam, lparam) == EN_CHANGE) {
12248 char item[MAXDSNAME];
12249
12250 EnableWindow(GetDlgItem(hdlg, IDOK),
12251 GetDlgItemText(hdlg, IDC_DSNAME,
12252 item, sizeof (item)));
12253 return TRUE;
12254 }
12255 break;
12256 case IDC_BROWSE:
12257 GetDBFile(hdlg);
12258 break;
12259 case IDOK:
12260 setupdlg = (SETUPDLG *) GetWindowLong(hdlg, DWL_USER);
12261 if (!setupdlg->defDSN) {
12262 GetDlgItemText(hdlg, IDC_DSNAME,
12263 setupdlg->attr[KEY_DSN].attr,
12264 sizeof (setupdlg->attr[KEY_DSN].attr));
12265 }
12266 GetDlgItemText(hdlg, IDC_DESC,
12267 setupdlg->attr[KEY_DESC].attr,
12268 sizeof (setupdlg->attr[KEY_DESC].attr));
12269 GetDlgItemText(hdlg, IDC_DBNAME,
12270 setupdlg->attr[KEY_DBNAME].attr,
12271 sizeof (setupdlg->attr[KEY_DBNAME].attr));
12272 GetDlgItemText(hdlg, IDC_TONAME,
12273 setupdlg->attr[KEY_BUSY].attr,
12274 sizeof (setupdlg->attr[KEY_BUSY].attr));
12275 strcpy(setupdlg->attr[KEY_NOWCHAR].attr,
12276 IsDlgButtonChecked(hdlg, IDC_NOWCHAR) == BST_CHECKED ?
12277 "1" : "0");
12278 strcpy(setupdlg->attr[KEY_STEPAPI].attr,
12279 IsDlgButtonChecked(hdlg, IDC_STEPAPI) == BST_CHECKED ?
12280 "1" : "0");
12281 SetDSNAttributes(hdlg, setupdlg);
12282
12283 case IDCANCEL:
12284 EndDialog(hdlg, wparam);
12285 return TRUE;
12286 }
12287 break;
12288 }
12289 return FALSE;
12290 }
12291
12301 BOOL INSTAPI
12302 ConfigDSN(HWND hwnd, WORD request, LPCSTR driver, LPCSTR attribs)
12303 {
12304 BOOL success;
12305 SETUPDLG *setupdlg;
12306
12307 setupdlg = (SETUPDLG *) xmalloc(sizeof (SETUPDLG));
12308 if (setupdlg == NULL) {
12309 return FALSE;
12310 }
12311 memset(setupdlg, 0, sizeof (SETUPDLG));
12312 if (attribs) {
12313 ParseAttributes(attribs, setupdlg);
12314 }
12315 if (setupdlg->attr[KEY_DSN].supplied) {
12316 strcpy(setupdlg->DSN, setupdlg->attr[KEY_DSN].attr);
12317 } else {
12318 setupdlg->DSN[0] = '\0';
12319 }
12320 if (request == ODBC_REMOVE_DSN) {
12321 if (!setupdlg->attr[KEY_DSN].supplied) {
12322 success = FALSE;
12323 } else {
12324 success = SQLRemoveDSNFromIni(setupdlg->attr[KEY_DSN].attr);
12325 }
12326 } else {
12327 setupdlg->parent = hwnd;
12328 setupdlg->driver = driver;
12329 setupdlg->newDSN = request == ODBC_ADD_DSN;
12330 setupdlg->defDSN = stricmp(setupdlg->attr[KEY_DSN].attr,
12331 "Default") == 0;
12332 if (hwnd) {
12333 success = DialogBoxParam(hModule, MAKEINTRESOURCE(CONFIGDSN),
12334 hwnd, (DLGPROC) ConfigDlgProc,
12335 (LONG) setupdlg) == IDOK;
12336 } else if (setupdlg->attr[KEY_DSN].supplied) {
12337 success = SetDSNAttributes(hwnd, setupdlg);
12338 } else {
12339 success = FALSE;
12340 }
12341 }
12342 xfree(setupdlg);
12343 return success;
12344 }
12345
12355 static BOOL CALLBACK
12356 DriverConnectProc(HWND hdlg, WORD wmsg, WPARAM wparam, LPARAM lparam)
12357 {
12358 SETUPDLG *setupdlg;
12359
12360 switch (wmsg) {
12361 case WM_INITDIALOG:
12362 SetWindowLong(hdlg, DWL_USER, lparam);
12363 setupdlg = (SETUPDLG *) lparam;
12364 SetDlgItemText(hdlg, IDC_DSNAME, setupdlg->attr[KEY_DSN].attr);
12365 SetDlgItemText(hdlg, IDC_DESC, setupdlg->attr[KEY_DESC].attr);
12366 SetDlgItemText(hdlg, IDC_DBNAME, setupdlg->attr[KEY_DBNAME].attr);
12367 SetDlgItemText(hdlg, IDC_TONAME, setupdlg->attr[KEY_BUSY].attr);
12368 SendDlgItemMessage(hdlg, IDC_DSNAME,
12369 EM_LIMITTEXT, (WPARAM) (MAXDSNAME - 1), 0L);
12370 SendDlgItemMessage(hdlg, IDC_DESC,
12371 EM_LIMITTEXT, (WPARAM) (MAXDESC - 1), 0L);
12372 SendDlgItemMessage(hdlg, IDC_DBNAME,
12373 EM_LIMITTEXT, (WORD)(MAXDBNAME - 1), 0L);
12374 SendDlgItemMessage(hdlg, IDC_TONAME,
12375 EM_LIMITTEXT, (WORD)(MAXTONAME - 1), 0L);
12376 CheckDlgButton(hdlg, IDC_NOWCHAR,
12377 getbool(setupdlg->attr[KEY_NOWCHAR].attr) ?
12378 BST_CHECKED : BST_UNCHECKED);
12379 CheckDlgButton(hdlg, IDC_STEPAPI,
12380 getbool(setupdlg->attr[KEY_STEPAPI].attr) ?
12381 BST_CHECKED : BST_UNCHECKED);
12382 return TRUE;
12383 case WM_COMMAND:
12384 switch (GET_WM_COMMAND_ID(wparam, lparam)) {
12385 case IDC_BROWSE:
12386 GetDBFile(hdlg);
12387 break;
12388 case IDOK:
12389 setupdlg = (SETUPDLG *) GetWindowLong(hdlg, DWL_USER);
12390 GetDlgItemText(hdlg, IDC_DSNAME,
12391 setupdlg->attr[KEY_DSN].attr,
12392 sizeof (setupdlg->attr[KEY_DSN].attr));
12393 GetDlgItemText(hdlg, IDC_DBNAME,
12394 setupdlg->attr[KEY_DBNAME].attr,
12395 sizeof (setupdlg->attr[KEY_DBNAME].attr));
12396 GetDlgItemText(hdlg, IDC_TONAME,
12397 setupdlg->attr[KEY_BUSY].attr,
12398 sizeof (setupdlg->attr[KEY_BUSY].attr));
12399 strcpy(setupdlg->attr[KEY_NOWCHAR].attr,
12400 IsDlgButtonChecked(hdlg, IDC_NOWCHAR) == BST_CHECKED ?
12401 "1" : "0");
12402 strcpy(setupdlg->attr[KEY_STEPAPI].attr,
12403 IsDlgButtonChecked(hdlg, IDC_STEPAPI) == BST_CHECKED ?
12404 "1" : "0");
12405
12406 case IDCANCEL:
12407 EndDialog(hdlg, GET_WM_COMMAND_ID(wparam, lparam) == IDOK);
12408 return TRUE;
12409 }
12410 }
12411 return FALSE;
12412 }
12413
12427 static SQLRETURN
12428 drvdriverconnect(SQLHDBC dbc, SQLHWND hwnd,
12429 SQLCHAR *connIn, SQLSMALLINT connInLen,
12430 SQLCHAR *connOut, SQLSMALLINT connOutMax,
12431 SQLSMALLINT *connOutLen, SQLUSMALLINT drvcompl)
12432 {
12433 BOOL maybeprompt, prompt = FALSE;
12434 DBC *d;
12435 SETUPDLG *setupdlg;
12436 short ret;
12437 SQLRETURN rc;
12438
12439 if (dbc == SQL_NULL_HDBC) {
12440 return SQL_INVALID_HANDLE;
12441 }
12442 d = (DBC *) dbc;
12443 if (d->sqlite) {
12444 setstatd(d, -1, "connection already established", "08002");
12445 return SQL_ERROR;
12446 }
12447 setupdlg = (SETUPDLG *) xmalloc(sizeof (SETUPDLG));
12448 if (setupdlg == NULL) {
12449 return SQL_ERROR;
12450 }
12451 memset(setupdlg, 0, sizeof (SETUPDLG));
12452 maybeprompt = drvcompl == SQL_DRIVER_COMPLETE ||
12453 drvcompl == SQL_DRIVER_COMPLETE_REQUIRED;
12454 if (connIn == NULL || !connInLen ||
12455 (connInLen == SQL_NTS && !connIn[0])) {
12456 prompt = TRUE;
12457 } else {
12458 ParseAttributes(connIn, setupdlg);
12459 if (!setupdlg->attr[KEY_DSN].attr[0] &&
12460 drvcompl == SQL_DRIVER_COMPLETE_REQUIRED) {
12461 strcpy(setupdlg->attr[KEY_DSN].attr, "DEFAULT");
12462 }
12463 GetAttributes(setupdlg);
12464 if (drvcompl == SQL_DRIVER_PROMPT ||
12465 (maybeprompt &&
12466 !setupdlg->attr[KEY_DSN].attr[0] ||
12467 !setupdlg->attr[KEY_DBNAME].attr[0])) {
12468 prompt = TRUE;
12469 }
12470 }
12471 retry:
12472 if (prompt) {
12473 ret = DialogBoxParam(hModule, MAKEINTRESOURCE(DRIVERCONNECT),
12474 hwnd, (DLGPROC) DriverConnectProc,
12475 (LONG) setupdlg);
12476 if (!ret || ret == -1) {
12477 xfree(setupdlg);
12478 return SQL_NO_DATA_FOUND;
12479 }
12480 }
12481 if (connOut || connOutLen) {
12482 char buf[1024];
12483 int len, count;
12484 char dsn_0 = setupdlg->attr[KEY_DSN].attr[0];
12485 char drv_0 = setupdlg->attr[KEY_DRIVER].attr[0];
12486
12487 buf[0] = '\0';
12488 count = snprintf(buf, sizeof (buf),
12489 "%s%s%s%s%s%sDatabase=%s;StepAPI=%s;"
12490 "Timeout=%s;NoWCHAR=%s",
12491 dsn_0 ? "DSN=" : "",
12492 dsn_0 ? setupdlg->attr[KEY_DSN].attr : "",
12493 dsn_0 ? ";" : "",
12494 drv_0 ? "Driver=" : "",
12495 drv_0 ? setupdlg->attr[KEY_DRIVER].attr : "",
12496 drv_0 ? ";" : "",
12497 setupdlg->attr[KEY_DBNAME].attr,
12498 setupdlg->attr[KEY_STEPAPI].attr,
12499 setupdlg->attr[KEY_BUSY].attr,
12500 setupdlg->attr[KEY_NOWCHAR].attr);
12501 if (count < 0) {
12502 buf[sizeof (buf) - 1] = '\0';
12503 }
12504 len = min(connOutMax - 1, strlen(buf));
12505 if (connOut) {
12506 strncpy(connOut, buf, len);
12507 connOut[len] = '\0';
12508 }
12509 if (connOutLen) {
12510 *connOutLen = len;
12511 }
12512 }
12513 d->nowchar = getbool(setupdlg->attr[KEY_NOWCHAR].attr);
12514 rc = dbopen(d, setupdlg->attr[KEY_DBNAME].attr,
12515 setupdlg->attr[KEY_DSN].attr,
12516 setupdlg->attr[KEY_STEPAPI].attr,
12517 setupdlg->attr[KEY_BUSY].attr);
12518 if (rc != SQL_SUCCESS) {
12519 if (maybeprompt && !prompt) {
12520 prompt = TRUE;
12521 goto retry;
12522 }
12523 xfree(setupdlg);
12524 return rc;
12525 }
12526 xfree(setupdlg);
12527 return SQL_SUCCESS;
12528 }
12529
12530 #endif
12531 #endif
12532
12533 #ifndef WITHOUT_DRIVERMGR
12534
12535 #ifndef SQLITE_UTF8
12536
12549 SQLRETURN SQL_API
12550 SQLDriverConnect(SQLHDBC dbc, SQLHWND hwnd,
12551 SQLCHAR *connIn, SQLSMALLINT connInLen,
12552 SQLCHAR *connOut, SQLSMALLINT connOutMax,
12553 SQLSMALLINT *connOutLen, SQLUSMALLINT drvcompl)
12554 {
12555 return drvdriverconnect(dbc, hwnd, connIn, connInLen,
12556 connOut, connOutMax, connOutLen, drvcompl);
12557 }
12558 #endif
12559
12560 #ifdef SQLITE_UTF8
12561
12574 SQLRETURN SQL_API
12575 SQLDriverConnectW(SQLHDBC dbc, SQLHWND hwnd,
12576 SQLWCHAR *connIn, SQLSMALLINT connInLen,
12577 SQLWCHAR *connOut, SQLSMALLINT connOutMax,
12578 SQLSMALLINT *connOutLen, SQLUSMALLINT drvcompl)
12579 {
12580 SQLRETURN ret;
12581 char *ci = NULL;
12582 SQLSMALLINT len;
12583
12584 if (connIn) {
12585 ci = uc_to_utf_c(connIn, connInLen);
12586 if (!ci) {
12587 DBC *d = (DBC *) dbc;
12588
12589 setstatd(d, -1, "out of memory", (*d->ov3) ? "HY000" : "S1000");
12590 return SQL_ERROR;
12591 }
12592 }
12593 ret = drvdriverconnect(dbc, hwnd, ci, SQL_NTS,
12594 (char *) connOut, connOutMax, &len, drvcompl);
12595 uc_free(ci);
12596 if (ret == SQL_SUCCESS) {
12597 SQLWCHAR *co = NULL;
12598
12599 if (connOut) {
12600 if (len > 0) {
12601 co = uc_from_utf((char *) connOut, len);
12602 if (co) {
12603 uc_strncpy(connOut, co, connOutMax);
12604 len = min(connOutMax, uc_strlen(co));
12605 uc_free(co);
12606 } else {
12607 len = 0;
12608 }
12609 }
12610 if (len <= 0) {
12611 len = 0;
12612 connOut[0] = 0;
12613 }
12614 } else {
12615 len = 0;
12616 }
12617 if (connOutLen) {
12618 *connOutLen = len;
12619 }
12620 }
12621 return ret;
12622 }
12623 #endif
12624
12625 #endif
12626
12627 #ifdef _WIN32
12628
12637 BOOL APIENTRY
12638 LibMain(HANDLE hinst, DWORD reason, LPVOID reserved)
12639 {
12640 static int initialized = 0;
12641
12642 switch (reason) {
12643 case DLL_PROCESS_ATTACH:
12644 if (!initialized++) {
12645 hModule = hinst;
12646 }
12647 break;
12648 case DLL_THREAD_ATTACH:
12649 break;
12650 case DLL_PROCESS_DETACH:
12651 --initialized;
12652 break;
12653 case DLL_THREAD_DETACH:
12654 break;
12655 default:
12656 break;
12657 }
12658 return TRUE;
12659 }
12660
12669 int __stdcall
12670 DllMain(HANDLE hinst, DWORD reason, LPVOID reserved)
12671 {
12672 return LibMain(hinst, reason, reserved);
12673 }
12674
12675 #endif
12676
12677 #if defined(HAVE_ODBCINSTEXT_H) && HAVE_ODBCINSTEXT_H
12678
12679
12680
12681
12682
12683
12684 #include <odbcinstext.h>
12685
12686 int
12687 ODBCINSTGetProperties(HODBCINSTPROPERTY prop)
12688 {
12689 static const char *instYN[] = { "No", "Yes", NULL };
12690
12691 prop->pNext = (HODBCINSTPROPERTY) malloc(sizeof (ODBCINSTPROPERTY));
12692 prop = prop->pNext;
12693 memset(prop, 0, sizeof (ODBCINSTPROPERTY));
12694 prop->nPromptType = ODBCINST_PROMPTTYPE_FILENAME;
12695 strncpy(prop->szName, "Database", INI_MAX_PROPERTY_NAME);
12696 strncpy(prop->szValue, "", INI_MAX_PROPERTY_VALUE);
12697 prop->pNext = (HODBCINSTPROPERTY) malloc(sizeof (ODBCINSTPROPERTY));
12698 prop = prop->pNext;
12699 memset(prop, 0, sizeof (ODBCINSTPROPERTY));
12700 prop->nPromptType = ODBCINST_PROMPTTYPE_TEXTEDIT;
12701 strncpy(prop->szName, "Timeout", INI_MAX_PROPERTY_NAME);
12702 strncpy(prop->szValue, "1000", INI_MAX_PROPERTY_VALUE);
12703 prop->pNext = (HODBCINSTPROPERTY) malloc(sizeof (ODBCINSTPROPERTY));
12704 prop = prop->pNext;
12705 memset(prop, 0, sizeof (ODBCINSTPROPERTY));
12706 prop->nPromptType = ODBCINST_PROMPTTYPE_COMBOBOX;
12707 prop->aPromptData = malloc (sizeof (instYN));
12708 memcpy(prop->aPromptData, instYN, sizeof (instYN));
12709 strncpy(prop->szName, "StepAPI", INI_MAX_PROPERTY_NAME);
12710 strncpy(prop->szValue, "No", INI_MAX_PROPERTY_VALUE);
12711 #ifdef SQLITE_UTF8
12712 prop->pNext = (HODBCINSTPROPERTY) malloc(sizeof (ODBCINSTPROPERTY));
12713 prop = prop->pNext;
12714 memset(prop, 0, sizeof (ODBCINSTPROPERTY));
12715 prop->nPromptType = ODBCINST_PROMPTTYPE_COMBOBOX;
12716 prop->aPromptData = malloc (sizeof (instYN));
12717 memcpy(prop->aPromptData, instYN, sizeof (instYN));
12718 strncpy(prop->szName, "NoWCHAR", INI_MAX_PROPERTY_NAME);
12719 strncpy(prop->szValue, "No", INI_MAX_PROPERTY_VALUE);
12720 #endif
12721 return 1;
12722 }
12723
12724 #endif