Main Page | Alphabetical List | Data Structures | File List | Data Fields | Globals

sqliteodbc.c

Go to the documentation of this file.
00001 00014 #include "sqliteodbc.h" 00015 00016 #ifdef SQLITE_UTF8 00017 #include <sqlucode.h> 00018 #endif 00019 00020 #ifdef _WIN32 00021 #define ODBC_INI "ODBC.INI" 00022 #else 00023 #define ODBC_INI ".odbc.ini" 00024 #endif 00025 00026 #undef min 00027 #define min(a, b) ((a) < (b) ? (a) : (b)) 00028 #undef max 00029 #define max(a, b) ((a) < (b) ? (b) : (a)) 00030 00031 #define array_size(x) (sizeof (x) / sizeof (x[0])) 00032 00033 #define stringify1(s) #s 00034 #define stringify(s) stringify1(s) 00035 00036 #define verinfo(maj, min, lev) ((maj) << 16 | (min) << 8 | (lev)) 00037 00038 /* Column types for static string column descriptions (SQLTables etc.) */ 00039 00040 #ifdef SQLITE_UTF8 00041 #define SCOL_VARCHAR SQL_WVARCHAR 00042 #define SCOL_CHAR SQL_WCHAR 00043 #else 00044 #define SCOL_VARCHAR SQL_VARCHAR 00045 #define SCOL_CHAR SQL_CHAR 00046 #endif 00047 00048 #define ENV_MAGIC 0x53544145 00049 #define DBC_MAGIC 0x53544144 00050 #define DEAD_MAGIC 0xdeadbeef 00051 00052 #ifdef MEMORY_DEBUG 00053 00054 static void * 00055 xmalloc_(int n, char *file, int line) 00056 { 00057 int nn = n + 4 * sizeof (long); 00058 long *p; 00059 00060 p = malloc(nn); 00061 if (!p) { 00062 #if (MEMORY_DEBUG > 1) 00063 fprintf(stderr, "malloc\t%d\tNULL\t%s:%d\n", n, file, line); 00064 #endif 00065 return NULL; 00066 } 00067 p[0] = 0xdead1234; 00068 nn = nn / sizeof (long) - 1; 00069 p[1] = n; 00070 p[nn] = 0xdead5678; 00071 #if (MEMORY_DEBUG > 1) 00072 fprintf(stderr, "malloc\t%d\t%p\t%s:%d\n", n, &p[2], file, line); 00073 #endif 00074 return (void *) &p[2]; 00075 } 00076 00077 static void * 00078 xrealloc_(void *old, int n, char *file, int line) 00079 { 00080 int nn = n + 4 * sizeof (long), nnn; 00081 long *p, *pp; 00082 00083 if (n == 0) { 00084 return xmalloc_(n, file, line); 00085 } 00086 p = &((long *) old)[-2]; 00087 if (p[0] != 0xdead1234) { 00088 fprintf(stderr, "*** low end corruption @ %p\n", old); 00089 abort(); 00090 } 00091 nnn = p[1] + 4 * sizeof (long); 00092 nnn = nnn / sizeof (long) - 1; 00093 if (p[nnn] != 0xdead5678) { 00094 fprintf(stderr, "*** high end corruption @ %p\n", old); 00095 abort(); 00096 } 00097 pp = realloc(p, nn); 00098 if (!pp) { 00099 #if (MEMORY_DEBUG > 1) 00100 fprintf(stderr, "realloc\t%p,%d\tNULL\t%s:%d\n", old, n, file, line); 00101 #endif 00102 return NULL; 00103 } 00104 #if (MEMORY_DEBUG > 1) 00105 fprintf(stderr, "realloc\t%p,%d\t%p\t%s:%d\n", old, n, &pp[2], file, line); 00106 #endif 00107 p = pp; 00108 if (n > p[1]) { 00109 memset(p + p[1], 0, 3 * sizeof (long)); 00110 } 00111 p[1] = n; 00112 nn = nn / sizeof (long) - 1; 00113 p[nn] = 0xdead5678; 00114 return (void *) &p[2]; 00115 } 00116 00117 static void 00118 xfree_(void *x, char *file, int line) 00119 { 00120 long *p; 00121 int n; 00122 00123 p = &((long *) x)[-2]; 00124 if (p[0] != 0xdead1234) { 00125 fprintf(stderr, "*** low end corruption @ %p\n", x); 00126 abort(); 00127 } 00128 n = p[1] + 4 * sizeof (long); 00129 n = n / sizeof (long) - 1; 00130 if (p[n] != 0xdead5678) { 00131 fprintf(stderr, "*** high end corruption @ %p\n", x); 00132 abort(); 00133 } 00134 #if (MEMORY_DEBUG > 1) 00135 fprintf(stderr, "free\t%p\t\t%s:%d\n", x, file, line); 00136 #endif 00137 free(p); 00138 } 00139 00140 static void 00141 xfree__(void *x) 00142 { 00143 xfree_(x, "unknown location", 0); 00144 } 00145 00146 static char * 00147 xstrdup_(char *str, char *file, int line) 00148 { 00149 char *p; 00150 00151 if (!str) { 00152 #if (MEMORY_DEBUG > 1) 00153 fprintf(stderr, "strdup\tNULL\tNULL\t%s:%d\n", file, line); 00154 #endif 00155 return NULL; 00156 } 00157 p = xmalloc_(strlen(str) + 1, file, line); 00158 if (p) { 00159 strcpy(p, str); 00160 } 00161 #if (MEMORY_DEBUG > 1) 00162 fprintf(stderr, "strdup\t%p\t%p\t%s:%d\n", str, p, file, line); 00163 #endif 00164 return p; 00165 } 00166 00167 #define xmalloc(x) xmalloc_(x, __FILE__, __LINE__) 00168 #define xrealloc(x,y) xrealloc_(x, y, __FILE__, __LINE__) 00169 #define xfree(x) xfree_(x, __FILE__, __LINE__) 00170 #define xstrdup(x) xstrdup_(x, __FILE__, __LINE__) 00171 00172 #else 00173 00174 #define xmalloc(x) malloc(x) 00175 #define xrealloc(x,y) realloc(x, y) 00176 #define xfree(x) free(x) 00177 #define xstrdup(x) strdup_(x) 00178 00179 #endif 00180 00181 #ifdef _WIN32 00182 #define vsnprintf _vsnprintf 00183 #define snprintf _snprintf 00184 #define strncasecmp _strnicmp 00185 #endif 00186 00187 /* 00188 * tolower() replacement w/o locale 00189 */ 00190 00191 static const char upper_chars[] = "ABCDEFGHIJKLMNOPQRSTUVWXYZ"; 00192 static const char lower_chars[] = "abcdefghijklmnopqrstuvwxyz"; 00193 00194 static int 00195 TOLOWER(int c) 00196 { 00197 if (c) { 00198 char *p = strchr(upper_chars, c); 00199 00200 if (p) { 00201 c = lower_chars[p - upper_chars]; 00202 } 00203 } 00204 return c; 00205 } 00206 00207 /* 00208 * isdigit() replacement w/o ctype.h 00209 */ 00210 00211 static const char digit_chars[] = "0123456789"; 00212 00213 #define ISDIGIT(c) \ 00214 ((c) && strchr(digit_chars, (c)) != NULL) 00215 00216 /* 00217 * isspace() replacement w/o ctype.h 00218 */ 00219 00220 static const char space_chars[] = " \f\n\r\t\v"; 00221 00222 #define ISSPACE(c) \ 00223 ((c) && strchr(space_chars, (c)) != NULL) 00224 00225 /* 00226 * Characters in named parameters 00227 */ 00228 00229 static const char id_chars[] = "ABCDEFGHIJKLMNOPQRSTUVWXYZ" 00230 "abcdefghijklmnopqrstuvwxyz" 00231 "_0123456789"; 00232 00233 #define ISIDCHAR(c) \ 00234 ((c) && strchr(id_chars, (c)) != NULL) 00235 00241 static void unbindcols(STMT *s); 00242 00250 static SQLRETURN mkbindcols(STMT *s, int ncols); 00251 00263 static void freeresult(STMT *s, int clrcols); 00264 00271 static SQLRETURN freestmt(HSTMT stmt); 00272 00287 static SQLRETURN substparam(STMT *s, int pnum, char **out, int *size); 00288 00294 static void freedyncols(STMT *s); 00295 00302 static SQLRETURN drvexecute(SQLHSTMT stmt); 00303 00310 static char * 00311 strdup_(const char *str) 00312 { 00313 char *p = NULL; 00314 00315 if (str) { 00316 p = xmalloc(strlen(str) + 1); 00317 if (p) { 00318 strcpy(p, str); 00319 } 00320 } 00321 return p; 00322 } 00323 00324 #ifdef SQLITE_UTF8 00325 00331 static int 00332 uc_strlen(SQLWCHAR *str) 00333 { 00334 int len = 0; 00335 00336 if (str) { 00337 while (*str) { 00338 ++len; 00339 ++str; 00340 } 00341 } 00342 return len; 00343 } 00344 00353 static SQLWCHAR * 00354 uc_strncpy(SQLWCHAR *dest, SQLWCHAR *src, int len) 00355 { 00356 int i = 0; 00357 00358 while (i < len) { 00359 if (!src[i]) { 00360 break; 00361 } 00362 dest[i] = src[i]; 00363 ++i; 00364 } 00365 if (i < len) { 00366 dest[i] = 0; 00367 } 00368 return dest; 00369 } 00370 00378 static void 00379 uc_from_utf_buf(unsigned char *str, SQLWCHAR *uc, int ucLen) 00380 { 00381 ucLen = ucLen / sizeof (SQLWCHAR); 00382 if (!uc || ucLen < 0) { 00383 return; 00384 } 00385 uc[0] = 0; 00386 if (str) { 00387 int i = 0; 00388 00389 while (*str && i < ucLen) { 00390 unsigned char c = str[0]; 00391 00392 if (c < 0xc0) { 00393 uc[i++] = c; 00394 ++str; 00395 } else if (c < 0xe0) { 00396 if ((str[1] & 0xc0) == 0x80) { 00397 unsigned long t = ((c & 0x1f) << 6) | (str[1] & 0x3f); 00398 00399 uc[i++] = t; 00400 str += 2; 00401 } else { 00402 uc[i++] = c; 00403 ++str; 00404 } 00405 } else if (c < 0xf0) { 00406 if ((str[1] & 0xc0) == 0x80 && (str[2] & 0xc0) == 0x80) { 00407 unsigned long t = ((c & 0x0f) << 12) | 00408 ((str[1] & 0x3f) << 6) | (str[2] & 0x3f); 00409 00410 uc[i++] = t; 00411 str += 3; 00412 } else { 00413 uc[i++] = c; 00414 ++str; 00415 } 00416 } else if (c < 0xf8) { 00417 if ((str[1] & 0xc0) == 0x80 && (str[2] & 0xc0) == 0x80 && 00418 (str[3] & 0xc0) == 0x80) { 00419 unsigned long t = ((c & 0x03) << 18) | 00420 ((str[1] & 0x3f) << 12) | ((str[2] & 0x3f) << 6) | 00421 (str[4] & 0x3f); 00422 00423 uc[i++] = t; 00424 str += 4; 00425 } else { 00426 uc[i++] = c; 00427 ++str; 00428 } 00429 } else if (c < 0xfc) { 00430 if ((str[1] & 0xc0) == 0x80 && (str[2] & 0xc0) == 0x80 && 00431 (str[3] & 0xc0) == 0x80 && (str[4] & 0xc0) == 0x80) { 00432 unsigned long t = ((c & 0x01) << 24) | 00433 ((str[1] & 0x3f) << 18) | ((str[2] & 0x3f) << 12) | 00434 ((str[4] & 0x3f) << 6) | (str[5] & 0x3f); 00435 00436 uc[i++] = t; 00437 str += 5; 00438 } else { 00439 uc[i++] = c; 00440 ++str; 00441 } 00442 } else { 00443 /* ignore */ 00444 ++str; 00445 } 00446 } 00447 if (i < ucLen) { 00448 uc[i] = 0; 00449 } 00450 } 00451 } 00452 00460 static SQLWCHAR * 00461 uc_from_utf(unsigned char *str, int len) 00462 { 00463 SQLWCHAR *uc = NULL; 00464 00465 if (str) { 00466 if (len == SQL_NTS) { 00467 len = strlen(str); 00468 } 00469 len = sizeof (SQLWCHAR) * (len + 1); 00470 uc = xmalloc(len); 00471 if (uc) { 00472 uc_from_utf_buf(str, uc, len); 00473 } 00474 } 00475 return uc; 00476 } 00477 00485 static char * 00486 uc_to_utf(SQLWCHAR *str, int len) 00487 { 00488 int i; 00489 char *cp, *ret = NULL; 00490 00491 if (!str) { 00492 return ret; 00493 } 00494 if (len == SQL_NTS) { 00495 len = uc_strlen(str); 00496 } else { 00497 len = len / sizeof (SQLWCHAR); 00498 } 00499 cp = xmalloc(len * 6 + 1); 00500 if (!cp) { 00501 return ret; 00502 } 00503 ret = cp; 00504 for (i = 0; i < len; i++) { 00505 unsigned long c = str[i]; 00506 00507 if (c < 0xc0) { 00508 *cp++ = c; 00509 } else if (c < 0x800) { 00510 *cp++ = 0xc0 | ((c >> 6) & 0x1f); 00511 *cp++ = 0x80 | (c & 0x3f); 00512 } else if (c < 0x10000) { 00513 *cp++ = 0xe0 | ((c >> 12) & 0x0f); 00514 *cp++ = 0x80 | ((c >> 6) & 0x3f); 00515 *cp++ = 0x80 | (c & 0x3f); 00516 } else if (c < 0x200000) { 00517 *cp++ = 0xf0 | ((c >> 18) & 0x07); 00518 *cp++ = 0x80 | ((c >> 12) & 0x3f); 00519 *cp++ = 0x80 | ((c >> 6) & 0x3f); 00520 *cp++ = 0x80 | (c & 0x3f); 00521 } else if (c < 0x4000000) { 00522 *cp++ = 0xf8 | ((c >> 24) & 0x03); 00523 *cp++ = 0x80 | ((c >> 18) & 0x3f); 00524 *cp++ = 0x80 | ((c >> 12) & 0x3f); 00525 *cp++ = 0x80 | ((c >> 6) & 0x3f); 00526 *cp++ = 0x80 | (c & 0x3f); 00527 } else if (c < 0x80000000) { 00528 *cp++ = 0xfc | ((c >> 31) & 0x01); 00529 *cp++ = 0x80 | ((c >> 24) & 0x3f); 00530 *cp++ = 0x80 | ((c >> 18) & 0x3f); 00531 *cp++ = 0x80 | ((c >> 12) & 0x3f); 00532 *cp++ = 0x80 | ((c >> 6) & 0x3f); 00533 *cp++ = 0x80 | (c & 0x3f); 00534 } 00535 } 00536 *cp = '\0'; 00537 return ret; 00538 } 00539 00547 static char * 00548 uc_to_utf_c(SQLWCHAR *str, int len) 00549 { 00550 if (len != SQL_NTS) { 00551 len = len * sizeof (SQLWCHAR); 00552 } 00553 return uc_to_utf(str, len); 00554 } 00555 00560 static void 00561 uc_free(void *str) 00562 { 00563 if (str) { 00564 xfree(str); 00565 } 00566 } 00567 #endif 00568 00569 #ifdef USE_DLOPEN_FOR_GPPS 00570 00571 #include <dlfcn.h> 00572 00573 #define SQLGetPrivateProfileString(A,B,C,D,E,F) drvgpps(d,A,B,C,D,E,F) 00574 00575 /* 00576 * EXPERIMENTAL: SQLGetPrivateProfileString infrastructure using 00577 * dlopen(), in theory this makes the driver independent from the 00578 * driver manager, i.e. the same driver binary can run with iODBC 00579 * and unixODBC. 00580 */ 00581 00582 static void 00583 drvgetgpps(DBC *d) 00584 { 00585 void *lib; 00586 int (*gpps)(); 00587 00588 lib = dlopen("libodbcinst.so", RTLD_LAZY); 00589 if (!lib) { 00590 lib = dlopen("libiodbcinst.so", RTLD_LAZY); 00591 } 00592 if (lib) { 00593 gpps = (int (*)()) dlsym(lib, "SQLGetPrivateProfileString"); 00594 if (!gpps) { 00595 dlclose(lib); 00596 return; 00597 } 00598 d->instlib = lib; 00599 d->gpps = gpps; 00600 } 00601 } 00602 00603 static void 00604 drvrelgpps(DBC *d) 00605 { 00606 if (d->instlib) { 00607 dlclose(d->instlib); 00608 d->instlib = 0; 00609 } 00610 } 00611 00612 static int 00613 drvgpps(DBC *d, char *sect, char *ent, char *def, char *buf, 00614 int bufsiz, char *fname) 00615 { 00616 if (d->gpps) { 00617 return d->gpps(sect, ent, def, buf, bufsiz, fname); 00618 } 00619 strncpy(buf, def, bufsiz); 00620 buf[bufsiz - 1] = '\0'; 00621 return 1; 00622 } 00623 #else 00624 #define drvgetgpps(d) 00625 #define drvrelgpps(d) 00626 #endif 00627 00636 #if defined(__GNUC__) && (__GNUC__ >= 2) 00637 static void setstatd(DBC *, int, char *, char *, ...) 00638 __attribute__((format (printf, 3, 5))); 00639 #endif 00640 00641 static void 00642 setstatd(DBC *d, int naterr, char *msg, char *st, ...) 00643 { 00644 va_list ap; 00645 00646 if (!d) { 00647 return; 00648 } 00649 d->naterr = naterr; 00650 d->logmsg[0] = '\0'; 00651 if (msg) { 00652 int count; 00653 00654 va_start(ap, st); 00655 count = vsnprintf(d->logmsg, sizeof (d->logmsg), msg, ap); 00656 va_end(ap); 00657 if (count < 0) { 00658 d->logmsg[sizeof (d->logmsg) - 1] = '\0'; 00659 } 00660 } 00661 if (!st) { 00662 st = "?????"; 00663 } 00664 strncpy(d->sqlstate, st, 5); 00665 d->sqlstate[5] = '\0'; 00666 } 00667 00676 #if defined(__GNUC__) && (__GNUC__ >= 2) 00677 static void setstat(STMT *, int, char *, char *, ...) 00678 __attribute__((format (printf, 3, 5))); 00679 #endif 00680 00681 static void 00682 setstat(STMT *s, int naterr, char *msg, char *st, ...) 00683 { 00684 va_list ap; 00685 00686 if (!s) { 00687 return; 00688 } 00689 s->naterr = naterr; 00690 s->logmsg[0] = '\0'; 00691 if (msg) { 00692 int count; 00693 00694 va_start(ap, st); 00695 count = vsnprintf(s->logmsg, sizeof (s->logmsg), msg, ap); 00696 va_end(ap); 00697 if (count < 0) { 00698 s->logmsg[sizeof (s->logmsg) - 1] = '\0'; 00699 } 00700 } 00701 if (!st) { 00702 st = "?????"; 00703 } 00704 strncpy(s->sqlstate, st, 5); 00705 s->sqlstate[5] = '\0'; 00706 } 00707 00714 static SQLRETURN 00715 drvunimpldbc(HDBC dbc) 00716 { 00717 DBC *d; 00718 00719 if (dbc == SQL_NULL_HDBC) { 00720 return SQL_INVALID_HANDLE; 00721 } 00722 d = (DBC *) dbc; 00723 setstatd(d, -1, "not supported", "IM001"); 00724 return SQL_ERROR; 00725 } 00726 00733 static SQLRETURN 00734 drvunimplstmt(HSTMT stmt) 00735 { 00736 STMT *s; 00737 00738 if (stmt == SQL_NULL_HSTMT) { 00739 return SQL_INVALID_HANDLE; 00740 } 00741 s = (STMT *) stmt; 00742 setstat(s, -1, "not supported", "IM001"); 00743 return SQL_ERROR; 00744 } 00745 00751 static void 00752 freep(void *x) 00753 { 00754 if (x && ((char **) x)[0]) { 00755 xfree(((char **) x)[0]); 00756 ((char **) x)[0] = NULL; 00757 } 00758 } 00759 00766 static SQLRETURN 00767 nomem(STMT *s) 00768 { 00769 setstat(s, -1, "out of memory", (*s->ov3) ? "HY000" : "S1000"); 00770 return SQL_ERROR; 00771 } 00772 00779 static SQLRETURN 00780 noconn(STMT *s) 00781 { 00782 setstat(s, -1, "not connected", (*s->ov3) ? "HY000" : "S1000"); 00783 return SQL_ERROR; 00784 } 00785 00793 #if defined(HAVE_SQLITEATOF) && HAVE_SQLITEATOF 00794 00795 extern double sqliteAtoF(char *data, char **endp); 00796 00797 #define ln_strtod sqliteAtoF 00798 00799 #else 00800 00801 static double 00802 ln_strtod(const char *data, char **endp) 00803 { 00804 #if defined(HAVE_LOCALECONV) || defined(_WIN32) 00805 struct lconv *lc; 00806 char buf[128], *p, *end; 00807 double value; 00808 00809 lc = localeconv(); 00810 if (lc && lc->decimal_point && lc->decimal_point[0] && 00811 lc->decimal_point[0] != '.') { 00812 strncpy(buf, data, sizeof (buf) - 1); 00813 buf[sizeof (buf) - 1] = '\0'; 00814 p = strchr(buf, '.'); 00815 if (p) { 00816 *p = lc->decimal_point[0]; 00817 } 00818 p = buf; 00819 } else { 00820 p = (char *) data; 00821 } 00822 value = strtod(p, &end); 00823 end = (char *) data + (end - p); 00824 if (endp) { 00825 *endp = end; 00826 } 00827 return value; 00828 #else 00829 return strtod(data, endp); 00830 #endif 00831 } 00832 00833 #endif 00834 00835 #if !defined(HAVE_SQLITEMPRINTF) || !HAVE_SQLITEMPRINTF 00836 00842 static void 00843 ln_sprintfg(char *buf, double value) 00844 { 00845 #if defined(HAVE_LOCALECONV) || defined(_WIN32) 00846 struct lconv *lc; 00847 char *p; 00848 00849 sprintf(buf, "%.16g", value); 00850 lc = localeconv(); 00851 if (lc && lc->decimal_point && lc->decimal_point[0] && 00852 lc->decimal_point[0] != '.') { 00853 p = strchr(buf, lc->decimal_point[0]); 00854 if (p) { 00855 *p = '.'; 00856 } 00857 } 00858 #else 00859 sprintf(buf, "%.16g", value); 00860 #endif 00861 } 00862 #endif 00863 00872 static int 00873 busy_handler(void *udata, const char *table, int count) 00874 { 00875 DBC *d = (DBC *) udata; 00876 long t1; 00877 int ret = 0; 00878 #ifndef _WIN32 00879 struct timeval tv; 00880 #endif 00881 00882 if (d->timeout <= 0) { 00883 return ret; 00884 } 00885 if (count <= 1) { 00886 #ifdef _WIN32 00887 d->t0 = GetTickCount(); 00888 #else 00889 gettimeofday(&tv, NULL); 00890 d->t0 = tv.tv_sec * 1000 + tv.tv_usec / 1000; 00891 #endif 00892 } 00893 #ifdef _WIN32 00894 t1 = GetTickCount(); 00895 #else 00896 gettimeofday(&tv, NULL); 00897 t1 = tv.tv_sec * 1000 + tv.tv_usec / 1000; 00898 #endif 00899 if (t1 - d->t0 > d->timeout) { 00900 goto done; 00901 return 0; 00902 } 00903 #ifdef _WIN32 00904 Sleep(10); 00905 #else 00906 #ifdef HAVE_USLEEP 00907 usleep(10000); 00908 #else 00909 tv.tv_sec = 0; 00910 tv.tv_usec = 10000; 00911 select(0, NULL, NULL, NULL, &tv); 00912 #endif 00913 #endif 00914 ret = 1; 00915 done: 00916 return ret; 00917 } 00918 00935 static int 00936 setsqliteopts(sqlite *x, DBC *d) 00937 { 00938 int count = 0, step = 0, rc; 00939 00940 while (step < 4) { 00941 if (step < 1) { 00942 rc = sqlite_exec(x, "PRAGMA full_column_names = on;", 00943 NULL, NULL, NULL); 00944 } else if (step < 2) { 00945 rc = sqlite_exec(x, "PRAGMA count_changes = on;", 00946 NULL, NULL, NULL); 00947 } else if (step < 3) { 00948 rc = sqlite_exec(x, "PRAGMA empty_result_callbacks = on;", 00949 NULL, NULL, NULL); 00950 } else { 00951 rc = sqlite_exec(x, "PRAGMA show_datatypes = on;", 00952 NULL, NULL, NULL); 00953 } 00954 if (rc != SQLITE_OK) { 00955 if (rc != SQLITE_BUSY || 00956 !busy_handler((void *) d, NULL, ++count)) { 00957 return rc; 00958 } 00959 continue; 00960 } 00961 count = 0; 00962 ++step; 00963 } 00964 sqlite_busy_handler(x, busy_handler, (void *) d); 00965 #if HAVE_ENCDEC 00966 { 00967 char *fname; 00968 static void hextobin_func(sqlite_func *context, 00969 int argc, const char **argv); 00970 static void bintohex_func(sqlite_func *context, 00971 int argc, const char **argv); 00972 00973 fname = "hextobin"; 00974 sqlite_create_function(x, fname, 1, hextobin_func, 0); 00975 sqlite_function_type(x, fname, SQLITE_TEXT); 00976 fname = "bintohex"; 00977 sqlite_create_function(x, fname, 1, bintohex_func, 0); 00978 sqlite_function_type(x, fname, SQLITE_TEXT); 00979 } 00980 #endif 00981 { 00982 char *fname; 00983 static void time_func(sqlite_func *context, 00984 int argc, const char **argv); 00985 00986 fname = "current_time_local"; 00987 sqlite_create_function(x, fname, 0, time_func, (void *) 0); 00988 sqlite_function_type(x, fname, SQLITE_TEXT); 00989 fname = "current_time_utc"; 00990 sqlite_create_function(x, fname, 0, time_func, (void *) 1); 00991 sqlite_function_type(x, fname, SQLITE_TEXT); 00992 fname = "current_date_local"; 00993 sqlite_create_function(x, fname, 0, time_func, (void *) 2); 00994 sqlite_function_type(x, fname, SQLITE_TEXT); 00995 fname = "current_date_utc"; 00996 sqlite_create_function(x, fname, 0, time_func, (void *) 3); 00997 sqlite_function_type(x, fname, SQLITE_TEXT); 00998 fname = "current_datetime_local"; 00999 sqlite_create_function(x, fname, 0, time_func, (void *) 4); 01000 sqlite_function_type(x, fname, SQLITE_TEXT); 01001 fname = "current_datetime_utc"; 01002 sqlite_create_function(x, fname, 0, time_func, (void *) 5); 01003 sqlite_function_type(x, fname, SQLITE_TEXT); 01004 fname = "current_timestamp_local"; 01005 sqlite_create_function(x, fname, 0, time_func, (void *) 4); 01006 sqlite_function_type(x, fname, SQLITE_TEXT); 01007 fname = "current_timestamp_utc"; 01008 sqlite_create_function(x, fname, 0, time_func, (void *) 5); 01009 sqlite_function_type(x, fname, SQLITE_TEXT); 01010 } 01011 return SQLITE_OK; 01012 } 01013 01023 static void 01024 freerows(char **rowp) 01025 { 01026 int size, i; 01027 01028 if (!rowp) { 01029 return; 01030 } 01031 --rowp; 01032 size = (int) rowp[0]; 01033 for (i = 1; i <= size; i++) { 01034 freep(&rowp[i]); 01035 } 01036 freep(&rowp); 01037 } 01038 01048 static int 01049 mapsqltype(const char *typename, int *nosign, int ov3, int nowchar) 01050 { 01051 char *p, *q; 01052 int testsign = 0, result; 01053 01054 #ifdef SQLITE_UTF8 01055 result = nowchar ? SQL_VARCHAR : SQL_WVARCHAR; 01056 #else 01057 result = SQL_VARCHAR; 01058 #endif 01059 if (!typename) { 01060 return result; 01061 } 01062 q = p = xmalloc(strlen(typename) + 1); 01063 if (!p) { 01064 return result; 01065 } 01066 strcpy(p, typename); 01067 while (*q) { 01068 *q = TOLOWER(*q); 01069 ++q; 01070 } 01071 if (strncmp(p, "inter", 5) == 0) { 01072 } else if (strncmp(p, "int", 3) == 0 || 01073 strncmp(p, "mediumint", 9) == 0) { 01074 testsign = 1; 01075 result = SQL_INTEGER; 01076 } else if (strncmp(p, "numeric", 7) == 0) { 01077 result = SQL_DOUBLE; 01078 } else if (strncmp(p, "tinyint", 7) == 0) { 01079 testsign = 1; 01080 result = SQL_TINYINT; 01081 } else if (strncmp(p, "smallint", 8) == 0) { 01082 testsign = 1; 01083 result = SQL_SMALLINT; 01084 } else if (strncmp(p, "float", 5) == 0) { 01085 result = SQL_DOUBLE; 01086 } else if (strncmp(p, "double", 6) == 0 || 01087 strncmp(p, "real", 4) == 0) { 01088 result = SQL_DOUBLE; 01089 } else if (strncmp(p, "timestamp", 9) == 0) { 01090 #ifdef SQL_TYPE_TIMESTAMP 01091 result = ov3 ? SQL_TYPE_TIMESTAMP : SQL_TIMESTAMP; 01092 #else 01093 result = SQL_TIMESTAMP; 01094 #endif 01095 } else if (strncmp(p, "datetime", 8) == 0) { 01096 #ifdef SQL_TYPE_TIMESTAMP 01097 result = ov3 ? SQL_TYPE_TIMESTAMP : SQL_TIMESTAMP; 01098 #else 01099 result = SQL_TIMESTAMP; 01100 #endif 01101 } else if (strncmp(p, "time", 4) == 0) { 01102 #ifdef SQL_TYPE_TIME 01103 result = ov3 ? SQL_TYPE_TIME : SQL_TIME; 01104 #else 01105 result = SQL_TIME; 01106 #endif 01107 } else if (strncmp(p, "date", 4) == 0) { 01108 #ifdef SQL_TYPE_DATE 01109 result = ov3 ? SQL_TYPE_DATE : SQL_DATE; 01110 #else 01111 result = SQL_DATE; 01112 #endif 01113 #ifdef SQL_LONGVARCHAR 01114 } else if (strncmp(p, "text", 4) == 0) { 01115 #ifdef SQLITE_UTF8 01116 result = nowchar ? SQL_LONGVARCHAR : SQL_WLONGVARCHAR; 01117 #else 01118 result = SQL_LONGVARCHAR; 01119 #endif 01120 #ifdef SQLITE_UTF8 01121 } else if (strncmp(p, "wtext", 5) == 0 || 01122 strncmp(p, "wvarchar", 8) == 0 || 01123 strncmp(p, "longwvarchar", 12) == 0) { 01124 result = SQL_WLONGVARCHAR; 01125 #endif 01126 #endif 01127 #if HAVE_ENCDEC 01128 } else if (strncmp(p, "binary", 6) == 0 || 01129 strncmp(p, "varbinary", 9) == 0 || 01130 strncmp(p, "bytea", 5) == 0 || 01131 strncmp(p, "blob", 4) == 0 || 01132 strncmp(p, "tinyblob", 8) == 0 || 01133 strncmp(p, "mediumblob", 10) == 0) { 01134 result = SQL_VARBINARY; 01135 } else if (strncmp(p, "longbinary", 10) == 0 || 01136 strncmp(p, "longvarbinary", 13) == 0 || 01137 strncmp(p, "longblob", 8) == 0) { 01138 result = SQL_LONGVARBINARY; 01139 #endif 01140 } 01141 if (nosign) { 01142 if (testsign) { 01143 *nosign = strstr(p, "unsigned") != NULL; 01144 } else { 01145 *nosign = 1; 01146 } 01147 } 01148 xfree(p); 01149 return result; 01150 } 01151 01161 static void 01162 getmd(const char *typename, int sqltype, int *mp, int *dp) 01163 { 01164 int m = 0, d = 0; 01165 01166 switch (sqltype) { 01167 case SQL_INTEGER: m = 10; d = 9; break; 01168 case SQL_TINYINT: m = 4; d = 3; break; 01169 case SQL_SMALLINT: m = 6; d = 5; break; 01170 case SQL_FLOAT: m = 25; d = 24; break; 01171 case SQL_DOUBLE: m = 54; d = 53; break; 01172 case SQL_VARCHAR: m = 255; d = 0; break; 01173 #ifdef SQLITE_UTF8 01174 #ifdef SQL_WVARCHAR 01175 case SQL_WVARCHAR: m = 255; d = 0; break; 01176 #endif 01177 #endif 01178 #ifdef SQL_TYPE_DATE 01179 case SQL_TYPE_DATE: 01180 #endif 01181 case SQL_DATE: m = 10; d = 0; break; 01182 #ifdef SQL_TYPE_TIME 01183 case SQL_TYPE_TIME: 01184 #endif 01185 case SQL_TIME: m = 8; d = 0; break; 01186 #ifdef SQL_TYPE_TIMESTAMP 01187 case SQL_TYPE_TIMESTAMP: 01188 #endif 01189 case SQL_TIMESTAMP: m = 32; d = 0; break; 01190 #ifdef SQL_LONGVARCHAR 01191 case SQL_LONGVARCHAR : m = 65536; d = 0; break; 01192 #endif 01193 #ifdef SQLITE_UTF8 01194 #ifdef SQL_WLONGVARCHAR 01195 case SQL_WLONGVARCHAR: m = 65536; d = 0; break; 01196 #endif 01197 #endif 01198 #if HAVE_ENCDEC 01199 case SQL_VARBINARY: m = 255; d = 0; break; 01200 case SQL_LONGVARBINARY: m = 65536; d = 0; break; 01201 #endif 01202 } 01203 if (m && typename) { 01204 int mm, dd; 01205 01206 if (sscanf(typename, "%*[^(](%d)", &mm) == 1) { 01207 m = d = mm; 01208 } else if (sscanf(typename, "%*[^(](%d,%d)", &mm, &dd) == 2) { 01209 m = mm; 01210 d = dd; 01211 } 01212 } 01213 if (mp) { 01214 *mp = m; 01215 } 01216 if (dp) { 01217 *dp = d; 01218 } 01219 } 01220 01230 static int 01231 mapdeftype(int type, int stype, int nosign, int nowchar) 01232 { 01233 if (type == SQL_C_DEFAULT) { 01234 switch (stype) { 01235 case SQL_INTEGER: 01236 type = nosign > 0 ? SQL_C_ULONG : SQL_C_LONG; 01237 break; 01238 case SQL_TINYINT: 01239 type = nosign > 0 ? SQL_C_UTINYINT : SQL_C_TINYINT; 01240 break; 01241 case SQL_SMALLINT: 01242 type = nosign > 0 ? SQL_C_USHORT : SQL_C_SHORT; 01243 break; 01244 case SQL_FLOAT: 01245 type = SQL_C_FLOAT; 01246 break; 01247 case SQL_DOUBLE: 01248 type = SQL_C_DOUBLE; 01249 break; 01250 case SQL_TIMESTAMP: 01251 type = SQL_C_TIMESTAMP; 01252 break; 01253 case SQL_TIME: 01254 type = SQL_C_TIME; 01255 break; 01256 case SQL_DATE: 01257 type = SQL_C_DATE; 01258 break; 01259 #ifdef SQL_C_TYPE_TIMESTAMP 01260 case SQL_TYPE_TIMESTAMP: 01261 type = SQL_C_TYPE_TIMESTAMP; 01262 break; 01263 #endif 01264 #ifdef SQL_C_TYPE_TIME 01265 case SQL_TYPE_TIME: 01266 type = SQL_C_TYPE_TIME; 01267 break; 01268 #endif 01269 #ifdef SQL_C_TYPE_DATE 01270 case SQL_TYPE_DATE: 01271 type = SQL_C_TYPE_DATE; 01272 break; 01273 #endif 01274 #ifdef SQLITE_UTF8 01275 case SQL_WVARCHAR: 01276 case SQL_WCHAR: 01277 #ifdef SQL_WLONGVARCHAR 01278 case SQL_WLONGVARCHAR: 01279 #endif 01280 type = nowchar ? SQL_C_CHAR : SQL_C_WCHAR; 01281 break; 01282 #endif 01283 #if HAVE_ENCDEC 01284 case SQL_BINARY: 01285 case SQL_VARBINARY: 01286 case SQL_LONGVARBINARY: 01287 type = SQL_C_BINARY; 01288 break; 01289 #endif 01290 default: 01291 type = SQL_C_CHAR; 01292 } 01293 } 01294 #ifdef SQLITE_UTF8 01295 if (nowchar) { 01296 switch (type) { 01297 case SQL_C_WCHAR: 01298 type = SQL_C_CHAR; 01299 break; 01300 } 01301 } 01302 #endif 01303 return type; 01304 } 01305 01318 static char * 01319 fixupsql(char *sql, int sqlLen, int *nparam, int *isselect, char **errmsg, 01320 int version, char ***namepp) 01321 { 01322 char *q = sql, *qz = NULL, *p, *inq = NULL, *out; 01323 int np = 0, size; 01324 char **npp = NULL, *ncp = NULL; 01325 01326 *errmsg = NULL; 01327 if (sqlLen != SQL_NTS) { 01328 qz = q = xmalloc(sqlLen + 1); 01329 if (!qz) { 01330 return NULL; 01331 } 01332 memcpy(q, sql, sqlLen); 01333 q[sqlLen] = '\0'; 01334 size = sqlLen * 4; 01335 } else { 01336 size = strlen(sql) * 4; 01337 } 01338 size += sizeof (char *) - 1; 01339 size &= ~(sizeof (char *) - 1); 01340 p = xmalloc(2 * size + size * sizeof (char *) / 2); 01341 if (!p) { 01342 errout: 01343 freep(&qz); 01344 return NULL; 01345 } 01346 out = p; 01347 npp = (char **) (out + size); 01348 ncp = (char *) npp + size * sizeof (char *) / 2; 01349 while (*q) { 01350 switch (*q) { 01351 case '\'': 01352 case '\"': 01353 if (q == inq) { 01354 inq = NULL; 01355 } else if (!inq) { 01356 inq = q + 1; 01357 01358 while (*inq) { 01359 if (*inq == *q) { 01360 if (inq[1] == *q) { 01361 inq++; 01362 } else { 01363 break; 01364 } 01365 } 01366 inq++; 01367 } 01368 } 01369 *p++ = *q; 01370 break; 01371 case '?': 01372 if (inq) { 01373 *p++ = *q; 01374 } else { 01375 *p++ = '%'; 01376 *p++ = 'Q'; 01377 npp[np] = ncp; 01378 *ncp = '\0'; 01379 ++ncp; 01380 np++; 01381 } 01382 break; 01383 case ':': /* ORACLE-style named parameter */ 01384 case '@': /* ADO.NET-style named parameter */ 01385 if (inq) { 01386 *p++ = *q; 01387 } else { 01388 int n = -1; 01389 01390 do { 01391 ++q; 01392 ++n; 01393 } while (*q && ISIDCHAR(*q)); 01394 if (n > 0) { 01395 *p++ = '%'; 01396 *p++ = 'Q'; 01397 npp[np] = ncp; 01398 memcpy(ncp, q - n, n); 01399 ncp[n] = '\0'; 01400 ncp += n + 1; 01401 np++; 01402 } 01403 --q; 01404 } 01405 break; 01406 case ';': 01407 if (inq) { 01408 *p++ = *q; 01409 } else { 01410 do { 01411 ++q; 01412 } while (*q && ISSPACE(*q)); 01413 if (*q) { 01414 freep(&out); 01415 *errmsg = "only one SQL statement allowed"; 01416 goto errout; 01417 } 01418 --q; 01419 } 01420 break; 01421 case '%': 01422 *p++ = '%'; 01423 *p++ = '%'; 01424 break; 01425 case '{': 01426 /* deal with {d 'YYYY-MM-DD'}, {t ...}, and {ts ...} */ 01427 if (!inq) { 01428 char *end = q + 1; 01429 01430 while (*end && *end != '}') { 01431 ++end; 01432 } 01433 if (*end == '}') { 01434 char *start = q + 1; 01435 char *end2 = end - 1; 01436 01437 while (start < end2 && *start != '\'') { 01438 ++start; 01439 } 01440 while (end2 > start && *end2 != '\'') { 01441 --end2; 01442 } 01443 if (*start == '\'' && *end2 == '\'') { 01444 while (start <= end2) { 01445 *p++ = *start; 01446 ++start; 01447 } 01448 q = end; 01449 break; 01450 } 01451 } 01452 } 01453 /* FALL THROUGH */ 01454 default: 01455 *p++ = *q; 01456 } 01457 ++q; 01458 } 01459 freep(&qz); 01460 *p = '\0'; 01461 if (nparam) { 01462 *nparam = np; 01463 } 01464 if (isselect) { 01465 p = out; 01466 while (*p && ISSPACE(*q)) { 01467 ++p; 01468 } 01469 *isselect = strncasecmp(p, "select", 6) == 0; 01470 } 01471 if (namepp) { 01472 *namepp = npp; 01473 } 01474 return out; 01475 } 01476 01485 static int 01486 findcol(char **cols, int ncols, char *name) 01487 { 01488 int i; 01489 01490 if (cols) { 01491 for (i = 0; i < ncols; i++) { 01492 if (strcmp(cols[i], name) == 0) { 01493 return i; 01494 } 01495 } 01496 } 01497 return -1; 01498 } 01499 01517 static void 01518 fixupdyncols(STMT *s, sqlite *sqlite, const char **types) 01519 { 01520 int i, k, pk, t, r, nrows, ncols, doautoinc = 0; 01521 char **rowp, *flagp, flags[128]; 01522 01523 if (!s->dyncols) { 01524 return; 01525 } 01526 /* fixup labels */ 01527 if (s->dcols > 1) { 01528 char *table = s->dyncols[0].table; 01529 01530 for (i = 1; table[0] && i < s->dcols; i++) { 01531 if (strcmp(s->dyncols[i].table, table)) { 01532 break; 01533 } 01534 } 01535 if (i >= s->dcols) { 01536 for (i = 0; i < s->dcols; i++) { 01537 s->dyncols[i].label = s->dyncols[i].column; 01538 } 01539 } 01540 } else if (s->dcols == 1) { 01541 s->dyncols[0].label = s->dyncols[0].column; 01542 } 01543 if (types) { 01544 for (i = 0; i < s->dcols; i++) { 01545 freep(&s->dyncols[i].typename); 01546 s->dyncols[i].typename = xstrdup(types[i] ? types[i] : "text"); 01547 s->dyncols[i].type = 01548 mapsqltype(types[i], &s->dyncols[i].nosign, *s->ov3, 01549 s->nowchar); 01550 getmd(types[i], s->dyncols[i].type, &s->dyncols[i].size, NULL); 01551 #ifdef SQL_LONGVARCHAR 01552 if (s->dyncols[i].type == SQL_VARCHAR && 01553 s->dyncols[i].size > 255) { 01554 s->dyncols[i].type = SQL_LONGVARCHAR; 01555 } 01556 #endif 01557 #ifdef SQLITE_UTF8 01558 #ifdef SQL_WLONGVARCHAR 01559 if (s->dyncols[i].type == SQL_WVARCHAR && 01560 s->dyncols[i].size > 255) { 01561 s->dyncols[i].type = SQL_WLONGVARCHAR; 01562 } 01563 #endif 01564 #endif 01565 #if HAVE_ENCDEC 01566 if (s->dyncols[i].type == SQL_VARBINARY && 01567 s->dyncols[i].size > 255) { 01568 s->dyncols[i].type = SQL_LONGVARBINARY; 01569 } 01570 #endif 01571 if (types[i] && strlen(types[i]) == 7 && 01572 strncasecmp(types[i], "integer", 7) == 0) { 01573 doautoinc++; 01574 s->dyncols[i].autoinc = -1; 01575 } else { 01576 s->dyncols[i].autoinc = 0; 01577 } 01578 } 01579 if (!doautoinc) { 01580 return; 01581 } 01582 } 01583 if (s->dcols > array_size(flags)) { 01584 flagp = xmalloc(sizeof (flags[0]) * s->dcols); 01585 if (flagp == NULL) { 01586 return; 01587 } 01588 } else { 01589 flagp = flags; 01590 } 01591 memset(flagp, 0, sizeof (flags[0]) * s->dcols); 01592 for (i = 0; i < s->dcols; i++) { 01593 s->dyncols[i].autoinc = 0; 01594 } 01595 for (i = 0; i < s->dcols; i++) { 01596 int ret, lastpk = -1, autoinccount = 0; 01597 01598 if (!s->dyncols[i].table[0]) { 01599 continue; 01600 } 01601 if (flagp[i]) { 01602 continue; 01603 } 01604 ret = sqlite_get_table_printf(sqlite, 01605 "PRAGMA table_info('%q')", &rowp, 01606 &nrows, &ncols, NULL, 01607 s->dyncols[i].table); 01608 if (ret != SQLITE_OK) { 01609 continue; 01610 } 01611 k = findcol(rowp, ncols, "name"); 01612 t = findcol(rowp, ncols, "type"); 01613 pk = findcol(rowp, ncols, "pk"); 01614 if (k < 0 || t < 0) { 01615 goto freet; 01616 } 01617 for (r = 1; r <= nrows; r++) { 01618 int m; 01619 01620 for (m = i; m < s->dcols; m++) { 01621 if (!flagp[m] && 01622 strcmp(s->dyncols[m].column, rowp[r * ncols + k]) == 0 && 01623 strcmp(s->dyncols[m].table, s->dyncols[i].table) == 0) { 01624 char *typename = rowp[r * ncols + t]; 01625 01626 flagp[m] = 1; 01627 freep(&s->dyncols[m].typename); 01628 s->dyncols[m].typename = xstrdup(typename); 01629 s->dyncols[m].type = 01630 mapsqltype(typename, &s->dyncols[m].nosign, *s->ov3, 01631 s->nowchar); 01632 getmd(typename, s->dyncols[m].type, &s->dyncols[m].size, 01633 NULL); 01634 #ifdef SQL_LONGVARCHAR 01635 if (s->dyncols[m].type == SQL_VARCHAR && 01636 s->dyncols[m].size > 255) { 01637 s->dyncols[m].type = SQL_LONGVARCHAR; 01638 } 01639 #endif 01640 #ifdef SQLITE_UTF8 01641 #ifdef SQL_WLONGVARCHAR 01642 if (s->dyncols[i].type == SQL_WVARCHAR && 01643 s->dyncols[i].size > 255) { 01644 s->dyncols[i].type = SQL_WLONGVARCHAR; 01645 } 01646 #endif 01647 #endif 01648 #if HAVE_ENCDEC 01649 if (s->dyncols[i].type == SQL_VARBINARY && 01650 s->dyncols[i].size > 255) { 01651 s->dyncols[i].type = SQL_LONGVARBINARY; 01652 } 01653 #endif 01654 if (pk >= 0 && strcmp(rowp[r * ncols + pk], "1") == 0) { 01655 if (++autoinccount > 1) { 01656 if (lastpk >= 0) { 01657 s->dyncols[lastpk].autoinc = 0; 01658 lastpk = -1; 01659 } 01660 } else { 01661 lastpk = m; 01662 if (strlen(typename) == 7 && 01663 strncasecmp(typename, "integer", 7) == 0) { 01664 s->dyncols[m].autoinc = 1; 01665 } 01666 } 01667 } 01668 } 01669 } 01670 } 01671 freet: 01672 sqlite_free_table(rowp); 01673 } 01674 if (flagp != flags) { 01675 freep(&flagp); 01676 } 01677 } 01678 01686 static int 01687 getmdays(int year, int month) 01688 { 01689 static const int mdays[] = { 01690 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 01691 }; 01692 int mday; 01693 01694 if (month < 1) { 01695 return 0; 01696 } 01697 mday = mdays[(month - 1) % 12]; 01698 if (mday == 28 && year % 4 == 0 && 01699 (!(year % 100 == 0) || year % 400 == 0)) { 01700 mday++; 01701 } 01702 return mday; 01703 } 01704 01715 static int 01716 str2date(char *str, DATE_STRUCT *ds) 01717 { 01718 int i, err = 0; 01719 char *p, *q; 01720 01721 ds->year = ds->month = ds->day = 0; 01722 p = str; 01723 while (*p && !ISDIGIT(*p)) { 01724 ++p; 01725 } 01726 q = p; 01727 i = 0; 01728 while (*q && !ISDIGIT(*q)) { 01729 ++i; 01730 ++q; 01731 } 01732 if (i >= 8) { 01733 char buf[8]; 01734 01735 strncpy(buf, p + 0, 4); buf[4] = '\0'; 01736 ds->year = strtol(buf, NULL, 10); 01737 strncpy(buf, p + 4, 2); buf[2] = '\0'; 01738 ds->month = strtol(buf, NULL, 10); 01739 strncpy(buf, p + 6, 2); buf[2] = '\0'; 01740 ds->day = strtol(buf, NULL, 10); 01741 goto done; 01742 } 01743 i = 0; 01744 while (i < 3) { 01745 int n; 01746 01747 q = NULL; 01748 n = strtol(p, &q, 10); 01749 if (!q || q == p) { 01750 if (*q == '\0') { 01751 if (i == 0) { 01752 err = 1; 01753 } 01754 goto done; 01755 } 01756 } 01757 if (*q == '-' || *q == '/' || *q == '\0' || i == 2) { 01758 switch (i) { 01759 case 0: ds->year = n; break; 01760 case 1: ds->month = n; break; 01761 case 2: ds->day = n; break; 01762 } 01763 ++i; 01764 if (*q) { 01765 ++q; 01766 } 01767 } else { 01768 i = 0; 01769 while (*q && !ISDIGIT(*q)) { 01770 ++q; 01771 } 01772 } 01773 p = q; 01774 } 01775 done: 01776 /* final check for overflow */ 01777 if (err || 01778 ds->month < 1 || ds->month > 12 || 01779 ds->day < 1 || ds->day > getmdays(ds->year, ds->month)) { 01780 return -1; 01781 } 01782 return 0; 01783 } 01784 01795 static int 01796 str2time(char *str, TIME_STRUCT *ts) 01797 { 01798 int i, err = 0; 01799 char *p, *q; 01800 01801 ts->hour = ts->minute = ts->second = 0; 01802 p = str; 01803 while (*p && !ISDIGIT(*p)) { 01804 ++p; 01805 } 01806 q = p; 01807 i = 0; 01808 while (*q && ISDIGIT(*q)) { 01809 ++i; 01810 ++q; 01811 } 01812 if (i >= 6) { 01813 char buf[4]; 01814 01815 strncpy(buf, p + 0, 2); buf[2] = '\0'; 01816 ts->hour = strtol(buf, NULL, 10); 01817 strncpy(buf, p + 2, 2); buf[2] = '\0'; 01818 ts->minute = strtol(buf, NULL, 10); 01819 strncpy(buf, p + 4, 2); buf[2] = '\0'; 01820 ts->second = strtol(buf, NULL, 10); 01821 goto done; 01822 } 01823 i = 0; 01824 while (i < 3) { 01825 int n; 01826 01827 q = NULL; 01828 n = strtol(p, &q, 10); 01829 if (!q || q == p) { 01830 if (*q == '\0') { 01831 if (i == 0) { 01832 err = 1; 01833 } 01834 goto done; 01835 } 01836 } 01837 if (*q == ':' || *q == '\0' || i == 2) { 01838 switch (i) { 01839 case 0: ts->hour = n; break; 01840 case 1: ts->minute = n; break; 01841 case 2: ts->second = n; break; 01842 } 01843 ++i; 01844 if (*q) { 01845 ++q; 01846 } 01847 } else { 01848 i = 0; 01849 while (*q && !ISDIGIT(*q)) { 01850 ++q; 01851 } 01852 } 01853 p = q; 01854 } 01855 done: 01856 /* final check for overflow */ 01857 if (err || ts->hour > 23 || ts->minute > 59 || ts->second > 59) { 01858 return -1; 01859 } 01860 return 0; 01861 } 01862 01878 static int 01879 str2timestamp(char *str, TIMESTAMP_STRUCT *tss) 01880 { 01881 int i, m, n, err = 0; 01882 char *p, *q, in = '\0'; 01883 01884 tss->year = tss->month = tss->day = 0; 01885 tss->hour = tss->minute = tss->second = 0; 01886 tss->fraction = 0; 01887 p = str; 01888 while (*p && !ISDIGIT(*p)) { 01889 ++p; 01890 } 01891 q = p; 01892 i = 0; 01893 while (*q && ISDIGIT(*q)) { 01894 ++i; 01895 ++q; 01896 } 01897 if (i >= 14) { 01898 char buf[16]; 01899 01900 strncpy(buf, p + 0, 4); buf[4] = '\0'; 01901 tss->year = strtol(buf, NULL, 10); 01902 strncpy(buf, p + 4, 2); buf[2] = '\0'; 01903 tss->month = strtol(buf, NULL, 10); 01904 strncpy(buf, p + 6, 2); buf[2] = '\0'; 01905 tss->day = strtol(buf, NULL, 10); 01906 strncpy(buf, p + 8, 2); buf[2] = '\0'; 01907 tss->hour = strtol(buf, NULL, 10); 01908 strncpy(buf, p + 10, 2); buf[2] = '\0'; 01909 tss->minute = strtol(buf, NULL, 10); 01910 strncpy(buf, p + 12, 2); buf[2] = '\0'; 01911 tss->second = strtol(buf, NULL, 10); 01912 if (i > 14) { 01913 m = i - 14; 01914 strncpy(buf, p + 14, m); 01915 while (m < 9) { 01916 buf[m] = '0'; 01917 ++m; 01918 } 01919 buf[m] = '\0'; 01920 tss->fraction = strtol(buf, NULL, 0); 01921 } 01922 m = 7; 01923 goto done; 01924 } 01925 m = i = 0; 01926 while ((m & 7) != 7) { 01927 q = NULL; 01928 n = strtol(p, &q, 10); 01929 if (!q || q == p) { 01930 if (*q == '\0') { 01931 if (m < 1) { 01932 err = 1; 01933 } 01934 goto done; 01935 } 01936 } 01937 if (in == '\0') { 01938 switch (*q) { 01939 case '-': 01940 case '/': 01941 if ((m & 1) == 0) { 01942 in = *q; 01943 i = 0; 01944 } 01945 break; 01946 case ':': 01947 if ((m & 2) == 0) { 01948 in = *q; 01949 i = 0; 01950 } 01951 break; 01952 case ' ': 01953 case '.': 01954 break; 01955 default: 01956 in = '\0'; 01957 i = 0; 01958 break; 01959 } 01960 } 01961 switch (in) { 01962 case '-': 01963 case '/': 01964 switch (i) { 01965 case 0: tss->year = n; break; 01966 case 1: tss->month = n; break; 01967 case 2: tss->day = n; break; 01968 } 01969 if (++i >= 3) { 01970 i = 0; 01971 m |= 1; 01972 if (!(m & 2)) { 01973 m |= 8; 01974 } 01975 goto skip; 01976 } else { 01977 ++q; 01978 } 01979 break; 01980 case ':': 01981 switch (i) { 01982 case 0: tss->hour = n; break; 01983 case 1: tss->minute = n; break; 01984 case 2: tss->second = n; break; 01985 } 01986 if (++i >= 3) { 01987 i = 0; 01988 m |= 2; 01989 if (*q == '.') { 01990 in = '.'; 01991 goto skip2; 01992 } 01993 if (*q == ' ') { 01994 if ((m & 1) == 0) { 01995 char *e = NULL; 01996 01997 strtol(q + 1, &e, 10); 01998 if (e && *e == '-') { 01999 goto skip; 02000 } 02001 } 02002 in = '.'; 02003 goto skip2; 02004 } 02005 goto skip; 02006 } else { 02007 ++q; 02008 } 02009 break; 02010 case '.': 02011 if (++i >= 1) { 02012 int ndig = q - p; 02013 02014 if (p[0] == '+' || p[0] == '-') { 02015 ndig--; 02016 } 02017 while (ndig < 9) { 02018 n = n * 10; 02019 ++ndig; 02020 } 02021 tss->fraction = n; 02022 m |= 4; 02023 i = 0; 02024 } 02025 default: 02026 skip: 02027 in = '\0'; 02028 skip2: 02029 while (*q && !ISDIGIT(*q)) { 02030 ++q; 02031 } 02032 } 02033 p = q; 02034 } 02035 if ((m & 7) > 1 && (m & 8)) { 02036 /* ISO8601 timezone */ 02037 if (p > str && ISDIGIT(*p)) { 02038 int nn, sign; 02039 02040 q = p - 1; 02041 if (*q != '+' && *q != '-') { 02042 goto done; 02043 } 02044 sign = *q == '+' ? -1 : 1; 02045 q = NULL; 02046 n = strtol(p, &q, 10); 02047 if (!q || *q++ != ':' || !ISDIGIT(*q)) { 02048 goto done; 02049 } 02050 p = q; 02051 q = NULL; 02052 nn = strtol(p, &q, 0); 02053 tss->minute += nn * sign; 02054 if ((SQLSMALLINT) tss->minute < 0) { 02055 tss->hour -= 1; 02056 tss->minute += 60; 02057 } else if (tss->minute >= 60) { 02058 tss->hour += 1; 02059 tss->minute -= 60; 02060 } 02061 tss->hour += n * sign; 02062 if ((SQLSMALLINT) tss->hour < 0) { 02063 tss->day -= 1; 02064 tss->hour += 24; 02065 } else if (tss->hour >= 24) { 02066 tss->day += 1; 02067 tss->hour -= 24; 02068 } 02069 if ((short) tss->day < 1 || tss->day >= 28) { 02070 int mday, pday, pmon; 02071 02072 mday = getmdays(tss->year, tss->month); 02073 pmon = tss->month - 1; 02074 if (pmon < 1) { 02075 pmon = 12; 02076 } 02077 pday = getmdays(tss->year, pmon); 02078 if ((SQLSMALLINT) tss->day < 1) { 02079 tss->month -= 1; 02080 tss->day = pday; 02081 } else if (tss->day > mday) { 02082 tss->month += 1; 02083 tss->day = 1; 02084 } 02085 if ((SQLSMALLINT) tss->month < 1) { 02086 tss->year -= 1; 02087 tss->month = 12; 02088 } else if (tss->month > 12) { 02089 tss->year += 1; 02090 tss->month = 1; 02091 } 02092 } 02093 } 02094 } 02095 done: 02096 /* final check for overflow */ 02097 if (err || 02098 tss->month < 1 || tss->month > 12 || 02099 tss->day < 1 || tss->day > getmdays(tss->year, tss->month) || 02100 tss->hour > 23 || tss->minute > 60 || tss->second > 60) { 02101 return -1; 02102 } 02103 return (m & 7) < 1 ? -1 : 0; 02104 } 02105 02112 static int 02113 getbool(char *string) 02114 { 02115 if (string) { 02116 return string[0] && strchr("Yy123456789Tt", string[0]) != NULL; 02117 } 02118 return 0; 02119 } 02120 02121 #if defined(HAVE_SQLITETRACE) && HAVE_SQLITETRACE 02122 02127 static void 02128 dbtrace(void *arg, const char *msg) 02129 { 02130 DBC *d = (DBC *) arg; 02131 02132 if (msg && d->trace) { 02133 int len = strlen(msg); 02134 02135 if (len > 0) { 02136 char *end = "\n"; 02137 02138 if (msg[len - 1] != ';') { 02139 end = ";\n"; 02140 } 02141 fprintf(d->trace, "%s%s", msg, end); 02142 fflush(d->trace); 02143 } 02144 } 02145 } 02146 02153 static void 02154 dbtracerc(DBC *d, int rc, char *err) 02155 { 02156 if (rc != SQLITE_OK && d->trace) { 02157 fprintf(d->trace, "-- SQLITE ERROR CODE %d", rc); 02158 fprintf(d->trace, err ? ": %s\n" : "\n", err); 02159 fflush(d->trace); 02160 } 02161 } 02162 #else 02163 02164 #define dbtracerc(a,b,c) 02165 02166 #endif 02167 02178 static SQLRETURN 02179 dbopen(DBC *d, char *name, char *dsn, char *sflag, char *busy) 02180 { 02181 char *errp = NULL, *endp = NULL; 02182 int tmp, busyto = 1000; 02183 02184 if (d->sqlite) { 02185 sqlite_close(d->sqlite); 02186 d->sqlite = NULL; 02187 } 02188 d->sqlite = sqlite_open(name, 0, &errp); 02189 if (d->sqlite == NULL) { 02190 connfail: 02191 setstatd(d, -1, errp ? errp : "connect failed", 02192 (*d->ov3) ? "HY000" : "S1000"); 02193 if (errp) { 02194 sqlite_freemem(errp); 02195 errp = NULL; 02196 } 02197 return SQL_ERROR; 02198 } 02199 if (errp) { 02200 sqlite_freemem(errp); 02201 errp = NULL; 02202 } 02203 #if defined(HAVE_SQLITETRACE) && HAVE_SQLITETRACE 02204 if (d->trace) { 02205 sqlite_trace(d->sqlite, dbtrace, d); 02206 } 02207 #endif 02208 d->step_enable = getbool(sflag); 02209 d->curtype = d->step_enable ? 02210 SQL_CURSOR_FORWARD_ONLY : SQL_CURSOR_STATIC; 02211 tmp = strtol(busy, &endp, 0); 02212 if (endp && *endp == '\0' && endp != busy) { 02213 busyto = tmp; 02214 } 02215 if (busyto < 1 || busyto > 1000000) { 02216 busyto = 1000000; 02217 } 02218 d->timeout = busyto; 02219 if (setsqliteopts(d->sqlite, d) != SQLITE_OK) { 02220 sqlite_close(d->sqlite); 02221 d->sqlite = NULL; 02222 goto connfail; 02223 } 02224 freep(&d->dbname); 02225 d->dbname = xstrdup(name); 02226 freep(&d->dsn); 02227 d->dsn = xstrdup(dsn); 02228 return SQL_SUCCESS; 02229 } 02230 02237 static int 02238 vm_step(STMT *s) 02239 { 02240 DBC *d = (DBC *) s->dbc; 02241 char **rowd = NULL, *errp = NULL; 02242 const char **values, **cols; 02243 int i, ncols, rc; 02244 02245 if (s != d->vm_stmt || !s->vm) { 02246 setstat(s, -1, "stale statement", (*s->ov3) ? "HY000" : "S1000"); 02247 return SQL_ERROR; 02248 } 02249 rc = sqlite_step(s->vm, &ncols, &values, &cols); 02250 if (rc == SQLITE_ROW || rc == SQLITE_DONE) { 02251 ++d->vm_rownum; 02252 if (d->vm_rownum == 0 && cols && ncols > 0) { 02253 int size; 02254 char *p; 02255 COL *dyncols; 02256 02257 for (i = size = 0; i < ncols; i++) { 02258 size += 3 + 3 * strlen(cols[i]); 02259 } 02260 dyncols = xmalloc(ncols * sizeof (COL) + size); 02261 if (!dyncols) { 02262 freedyncols(s); 02263 s->ncols = 0; 02264 sqlite_finalize(s->vm, NULL); 02265 s->vm = NULL; 02266 d->vm_stmt = NULL; 02267 return nomem(s); 02268 } 02269 p = (char *) (dyncols + ncols); 02270 for (i = 0; i < ncols; i++) { 02271 char *q; 02272 02273 dyncols[i].db = ((DBC *) (s->dbc))->dbname; 02274 strcpy(p, cols[i]); 02275 dyncols[i].label = p; 02276 p += strlen(p) + 1; 02277 q = strchr(cols[i], '.'); 02278 if (q) { 02279 dyncols[i].table = p; 02280 strncpy(p, cols[i], q - cols[i]); 02281 p[q - cols[i]] = '\0'; 02282 p += strlen(p) + 1; 02283 strcpy(p, q + 1); 02284 dyncols[i].column = p; 02285 p += strlen(p) + 1; 02286 } else { 02287 dyncols[i].table = ""; 02288 strcpy(p, cols[i]); 02289 dyncols[i].column = p; 02290 p += strlen(p) + 1; 02291 } 02292 #ifdef SQL_LONGVARCHAR 02293 dyncols[i].type = SQL_LONGVARCHAR; 02294 dyncols[i].size = 65536; 02295 #else 02296 dyncols[i].type = SQL_VARCHAR; 02297 dyncols[i].size = 255; 02298 #endif 02299 dyncols[i].index = i; 02300 dyncols[i].scale = 0; 02301 dyncols[i].prec = 0; 02302 dyncols[i].nosign = 1; 02303 dyncols[i].autoinc = -1; 02304 dyncols[i].typename = NULL; 02305 } 02306 freedyncols(s); 02307 s->ncols = s->dcols = ncols; 02308 s->dyncols = s->cols = dyncols; 02309 fixupdyncols(s, d->sqlite, cols + ncols); 02310 mkbindcols(s, s->ncols); 02311 } 02312 if (!cols || ncols <= 0) { 02313 goto killvm; 02314 } 02315 if (!values) { 02316 if (rc == SQLITE_DONE) { 02317 freeresult(s, 0); 02318 s->nrows = 0; 02319 sqlite_finalize(s->vm, NULL); 02320 s->vm = NULL; 02321 d->vm_stmt = NULL; 02322 return SQL_SUCCESS; 02323 } 02324 goto killvm; 02325 } 02326 rowd = xmalloc((1 + 2 * ncols) * sizeof (char *)); 02327 if (rowd) { 02328 rowd[0] = (char *) (ncols * 2); 02329 ++rowd; 02330 for (i = 0; i < ncols; i++) { 02331 rowd[i] = NULL; 02332 rowd[i + ncols] = xstrdup(values[i]); 02333 } 02334 for (i = 0; i < ncols; i++) { 02335 if (values[i] && !rowd[i + ncols]) { 02336 freerows(rowd); 02337 rowd = 0; 02338 break; 02339 } 02340 } 02341 } 02342 if (rowd) { 02343 freeresult(s, 0); 02344 s->nrows = 1; 02345 s->rows = rowd; 02346 if (rc == SQLITE_DONE) { 02347 sqlite_finalize(s->vm, NULL); 02348 s->vm = NULL; 02349 d->vm_stmt = NULL; 02350 } 02351 return SQL_SUCCESS; 02352 } 02353 } 02354 killvm: 02355 sqlite_finalize(s->vm, &errp); 02356 s->vm = NULL; 02357 d->vm_stmt = NULL; 02358 setstat(s, rc, "%s (%d)", (*s->ov3) ? "HY000" : "S1000", 02359 errp ? errp : "unknown error", rc); 02360 if (errp) { 02361 sqlite_freemem(errp); 02362 errp = NULL; 02363 } 02364 return SQL_ERROR; 02365 } 02366 02372 static void 02373 vm_end(STMT *s) 02374 { 02375 DBC *d; 02376 02377 if (!s || !s->vm) { 02378 return; 02379 } 02380 d = (DBC *) s->dbc; 02381 sqlite_finalize(s->vm, NULL); 02382 s->vm = NULL; 02383 d->vm_stmt = NULL; 02384 } 02385 02391 static void 02392 vm_end_if(STMT *s) 02393 { 02394 DBC *d = (DBC *) s->dbc; 02395 02396 if (d && d->vm_stmt == s) { 02397 vm_end(s); 02398 } 02399 } 02400 02408 static SQLRETURN 02409 vm_start(STMT *s, char **params) 02410 { 02411 DBC *d = (DBC *) s->dbc; 02412 char *errp = NULL, *sql = NULL; 02413 const char *endp; 02414 sqlite_vm *vm; 02415 int rc; 02416 02417 sql = sqlite_vmprintf(s->query, (char *) params); 02418 if (!sql) { 02419 return nomem(s); 02420 } 02421 rc = sqlite_compile(d->sqlite, sql, &endp, &vm, &errp); 02422 dbtracerc(d, rc, errp); 02423 sqlite_freemem(sql); 02424 if (rc != SQLITE_OK) { 02425 setstat(s, rc, "%s (%d)", (*s->ov3) ? "HY000" : "S1000", 02426 errp ? errp : "unknown error", rc); 02427 if (errp) { 02428 sqlite_freemem(errp); 02429 errp = NULL; 02430 } 02431 return SQL_ERROR; 02432 } 02433 s->vm = vm; 02434 d->vm_stmt = s; 02435 d->vm_rownum = -1; 02436 return SQL_SUCCESS; 02437 } 02438 02443 SQLRETURN SQL_API 02444 SQLBulkOperations(SQLHSTMT stmt, SQLSMALLINT oper) 02445 { 02446 return drvunimplstmt(stmt); 02447 } 02448 02449 #ifndef SQLITE_UTF8 02450 02454 SQLRETURN SQL_API 02455 SQLDataSources(SQLHENV env, SQLUSMALLINT dir, SQLCHAR *srvname, 02456 SQLSMALLINT buflen1, SQLSMALLINT *lenp1, 02457 SQLCHAR *desc, SQLSMALLINT buflen2, SQLSMALLINT *lenp2) 02458 { 02459 if (env == SQL_NULL_HENV) { 02460 return SQL_INVALID_HANDLE; 02461 } 02462 return SQL_ERROR; 02463 } 02464 #endif 02465 02466 #ifdef SQLITE_UTF8 02467 02471 SQLRETURN SQL_API 02472 SQLDataSourcesW(SQLHENV env, SQLUSMALLINT dir, SQLWCHAR *srvname, 02473 SQLSMALLINT buflen1, SQLSMALLINT *lenp1, 02474 SQLWCHAR *desc, SQLSMALLINT buflen2, SQLSMALLINT *lenp2) 02475 { 02476 if (env == SQL_NULL_HENV) { 02477 return SQL_INVALID_HANDLE; 02478 } 02479 return SQL_ERROR; 02480 } 02481 #endif 02482 02483 #ifndef SQLITE_UTF8 02484 02488 SQLRETURN SQL_API 02489 SQLDrivers(SQLHENV env, SQLUSMALLINT dir, SQLCHAR *drvdesc, 02490 SQLSMALLINT descmax, SQLSMALLINT *desclenp, 02491 SQLCHAR *drvattr, SQLSMALLINT attrmax, SQLSMALLINT *attrlenp) 02492 { 02493 if (env == SQL_NULL_HENV) { 02494 return SQL_INVALID_HANDLE; 02495 } 02496 return SQL_ERROR; 02497 } 02498 #endif 02499 02500 #ifdef SQLITE_UTF8 02501 02505 SQLRETURN SQL_API 02506 SQLDriversW(SQLHENV env, SQLUSMALLINT dir, SQLWCHAR *drvdesc, 02507 SQLSMALLINT descmax, SQLSMALLINT *desclenp, 02508 SQLWCHAR *drvattr, SQLSMALLINT attrmax, SQLSMALLINT *attrlenp) 02509 { 02510 if (env == SQL_NULL_HENV) { 02511 return SQL_INVALID_HANDLE; 02512 } 02513 return SQL_ERROR; 02514 } 02515 #endif 02516 02517 #ifndef SQLITE_UTF8 02518 02522 SQLRETURN SQL_API 02523 SQLBrowseConnect(SQLHDBC dbc, SQLCHAR *connin, SQLSMALLINT conninLen, 02524 SQLCHAR *connout, SQLSMALLINT connoutMax, 02525 SQLSMALLINT *connoutLen) 02526 { 02527 return drvunimpldbc(dbc); 02528 } 02529 #endif 02530 02531 #ifdef SQLITE_UTF8 02532 02536 SQLRETURN SQL_API 02537 SQLBrowseConnectW(SQLHDBC dbc, SQLWCHAR *connin, SQLSMALLINT conninLen, 02538 SQLWCHAR *connout, SQLSMALLINT connoutMax, 02539 SQLSMALLINT *connoutLen) 02540 { 02541 return drvunimpldbc(dbc); 02542 } 02543 #endif 02544 02552 static void 02553 time_func(sqlite_func *context, int argc, const char **argv) 02554 { 02555 char buf[128]; 02556 int what = (int) sqlite_user_data(context); 02557 #ifdef _WIN32 02558 SYSTEMTIME st; 02559 02560 if (what & 1) { 02561 GetSystemTime(&st); 02562 } else { 02563 GetLocalTime(&st); 02564 } 02565 if (what & 4) { 02566 sprintf(buf, "%04d-%02d-%02d %02d:%02d:%02d", 02567 st.wYear, st.wMonth, st.wDay, 02568 st.wHour, st.wMinute, st.wSecond); 02569 } else if (what & 2) { 02570 sprintf(buf, "%04d-%02d-%02d", st.wYear, st.wMonth, st.wDay); 02571 } else { 02572 sprintf(buf, "%02d:%02d:%02d", st.wHour, st.wMinute, st.wSecond); 02573 } 02574 #else 02575 time_t t; 02576 struct tm tm; 02577 02578 time(&t); 02579 if (what & 1) { 02580 #ifdef HAVE_GMTIME_R 02581 gmtime_r(&t, &tm); 02582 #else 02583 tm = *gmtime(&t); 02584 #endif 02585 } else { 02586 #ifdef HAVE_LOCALTIME_R 02587 localtime_r(&t, &tm); 02588 #else 02589 tm = *localtime(&t); 02590 #endif 02591 } 02592 if (what & 4) { 02593 sprintf(buf, "%04d-%02d-%02d %02d:%02d:%02d", 02594 tm.tm_year + 1900, tm.tm_mon + 1, tm.tm_mday, 02595 tm.tm_hour, tm.tm_min, tm.tm_sec); 02596 } else if (what & 2) { 02597 sprintf(buf, "%04d-%02d-%02d", 02598 tm.tm_year + 1900, tm.tm_mon + 1, tm.tm_mday); 02599 } else { 02600 sprintf(buf, "%02d:%02d:%02d", tm.tm_hour, tm.tm_min, tm.tm_sec); 02601 } 02602 #endif 02603 sqlite_set_result_string(context, buf, -1); 02604 } 02605 02606 #if HAVE_ENCDEC 02607 static const char hexdigits[] = "0123456789ABCDEFabcdef"; 02608 02616 static void 02617 hextobin_func(sqlite_func *context, int argc, const char **argv) 02618 { 02619 int i, len; 02620 char *bin, *p; 02621 02622 if (argc < 1) { 02623 return; 02624 } 02625 if (!argv[0]) { 02626 sqlite_set_result_string(context, "NULL", 4); 02627 return; 02628 } 02629 len = strlen(argv[0]) / 2; 02630 bin = xmalloc(len + 1); 02631 if (!bin) { 02632 oom: 02633 sqlite_set_result_error(context, "out of memory", -1); 02634 return; 02635 } 02636 if (len <= 0) { 02637 sqlite_set_result_string(context, bin, 0); 02638 freep(&bin); 02639 return; 02640 } 02641 for (i = 0, p = (char *) argv[0]; i < len; i++) { 02642 char *x; 02643 int v; 02644 02645 if (!*p || !(x = strchr(hexdigits, *p))) { 02646 goto converr; 02647 } 02648 v = x - hexdigits; 02649 bin[i] = (v >= 16) ? ((v - 6) << 4) : (v << 4); 02650 ++p; 02651 if (!*p || !(x = strchr(hexdigits, *p))) { 02652 converr: 02653 freep(&bin); 02654 sqlite_set_result_error(context, "conversion error", -1); 02655 return; 02656 } 02657 v = x - hexdigits; 02658 bin[i] |= (v >= 16) ? (v - 6) : v; 02659 ++p; 02660 } 02661 i = sqlite_encode_binary(bin, len, 0); 02662 p = xmalloc(i + 1); 02663 if (!p) { 02664 freep(&bin); 02665 goto oom; 02666 } 02667 i = sqlite_encode_binary(bin, len, p); 02668 sqlite_set_result_string(context, p, i); 02669 freep(&bin); 02670 freep(&p); 02671 } 02672 02680 static void 02681 bintohex_func(sqlite_func *context, int argc, const char **argv) 02682 { 02683 int i, k, len; 02684 char *bin, *p; 02685 02686 if (argc < 1) { 02687 return; 02688 } 02689 if (!argv[0]) { 02690 empty: 02691 sqlite_set_result_string(context, "", 0); 02692 return; 02693 } 02694 bin = xmalloc(strlen(argv[0]) + 1); 02695 if (!bin) { 02696 oom: 02697 sqlite_set_result_error(context, "out of memory", -1); 02698 return; 02699 } 02700 len = sqlite_decode_binary(argv[0], bin); 02701 if (len < 0) { 02702 freep(&bin); 02703 sqlite_set_result_error(context, "error decoding binary data", -1); 02704 return; 02705 } 02706 if (len == 0) { 02707 goto empty; 02708 } 02709 p = xmalloc(len * 2 + 1); 02710 if (!p) { 02711 goto oom; 02712 } 02713 for (i = 0, k = 0; i < len; i++) { 02714 p[k++] = hexdigits[(bin[i] >> 4) & 0x0f]; 02715 p[k++] = hexdigits[bin[i] & 0x0f]; 02716 } 02717 p[k] = '\0'; 02718 sqlite_set_result_string(context, p, k); 02719 freep(&bin); 02720 freep(&p); 02721 } 02722 02730 static SQLRETURN 02731 hextobin(STMT *s, BINDPARM *p) 02732 { 02733 int i, len = strlen(p->param) / 2; 02734 char *bin = xmalloc(len + 1), *pp; 02735 02736 if (!bin) { 02737 return nomem(s); 02738 } 02739 if (len <= 0) { 02740 bin[0] = '\0'; 02741 if (p->param == p->ind) { 02742 freep(&p->param); 02743 } 02744 p->param = p->ind = bin; 02745 p->len = 0; 02746 return SQL_SUCCESS; 02747 } 02748 for (i = 0, pp = (char *) p->param; i < len; i++) { 02749 char *x; 02750 int v; 02751 02752 if (!*pp || !(x = strchr(hexdigits, *pp))) { 02753 goto converr; 02754 } 02755 v = x - hexdigits; 02756 bin[i] = (v >= 16) ? ((v - 6) << 4) : (v << 4); 02757 ++pp; 02758 if (!*pp || !(x = strchr(hexdigits, *pp))) { 02759 converr: 02760 freep(&bin); 02761 setstat(s, -1, "conversion error", (*s->ov3) ? "HY000" : "S1000"); 02762 return SQL_ERROR; 02763 } 02764 v = x - hexdigits; 02765 bin[i] |= (v >= 16) ? (v - 6) : v; 02766 ++pp; 02767 } 02768 i = sqlite_encode_binary(bin, len, 0); 02769 pp = xmalloc(i + 1); 02770 if (!pp) { 02771 freep(&bin); 02772 return nomem(s); 02773 } 02774 p->len = sqlite_encode_binary(bin, len, pp); 02775 if (p->param == p->ind) { 02776 freep(&p->param); 02777 } 02778 p->param = p->ind = pp; 02779 freep(&bin); 02780 return SQL_SUCCESS; 02781 } 02782 #endif 02783 02792 SQLRETURN SQL_API 02793 SQLPutData(SQLHSTMT stmt, SQLPOINTER data, SQLINTEGER len) 02794 { 02795 STMT *s; 02796 int i, dlen, done = 0; 02797 BINDPARM *p; 02798 02799 if (stmt == SQL_NULL_HSTMT) { 02800 return SQL_INVALID_HANDLE; 02801 } 02802 s = (STMT *) stmt; 02803 if (!s->query || s->nparams <= 0) { 02804 seqerr: 02805 setstat(s, -1, "sequence error", "HY010"); 02806 return SQL_ERROR; 02807 } 02808 for (i = 0; i < s->nparams; i++) { 02809 p = &s->bindparms[i]; 02810 if (p->need) { 02811 int type = mapdeftype(p->type, p->stype, -1, s->nowchar); 02812 02813 if (len == SQL_NULL_DATA) { 02814 freep(&p->param); 02815 p->ind = &p->len; 02816 p->len = SQL_NULL_DATA; 02817 p->need = 0; 02818 } else 02819 #if HAVE_ENCDEC 02820 if (type == SQL_C_BINARY) { 02821 if (len <= 0) { 02822 setstat(s, -1, "invalid length", "HY090"); 02823 return SQL_ERROR; 02824 } 02825 goto putd; 02826 } else 02827 #endif 02828 #ifdef SQLITE_UTF8 02829 if (type != SQL_C_CHAR && type != SQL_C_WCHAR) 02830 #else 02831 if (type != SQL_C_CHAR) 02832 #endif 02833 { 02834 int size = 0; 02835 02836 switch (type) { 02837 case SQL_C_TINYINT: 02838 case SQL_C_UTINYINT: 02839 case SQL_C_STINYINT: 02840 size = sizeof (char); 02841 break; 02842 case SQL_C_SHORT: 02843 case SQL_C_USHORT: 02844 case SQL_C_SSHORT: 02845 size = sizeof (short); 02846 break; 02847 case SQL_C_LONG: 02848 case SQL_C_ULONG: 02849 case SQL_C_SLONG: 02850 size = sizeof (long); 02851 break; 02852 case SQL_C_FLOAT: 02853 size = sizeof (float); 02854 break; 02855 case SQL_C_DOUBLE: 02856 size = sizeof (double); 02857 break; 02858 #ifdef SQL_C_TYPE_DATE 02859 case SQL_C_TYPE_DATE: 02860 #endif 02861 case SQL_C_DATE: 02862 size = sizeof (DATE_STRUCT); 02863 break; 02864 #ifdef SQL_C_TYPE_DATE 02865 case SQL_C_TYPE_TIME: 02866 #endif 02867 case SQL_C_TIME: 02868 size = sizeof (TIME_STRUCT); 02869 break; 02870 #ifdef SQL_C_TYPE_DATE 02871 case SQL_C_TYPE_TIMESTAMP: 02872 #endif 02873 case SQL_C_TIMESTAMP: 02874 size = sizeof (TIMESTAMP_STRUCT); 02875 break; 02876 } 02877 freep(&p->param); 02878 p->param = xmalloc(size); 02879 if (!p->param) { 02880 return nomem(s); 02881 } 02882 memcpy(p->param, data, size); 02883 p->len = size; 02884 p->need = 0; 02885 } else if (len == SQL_NTS) { 02886 char *dp = data; 02887 02888 #ifdef SQLITE_UTF8 02889 if (p->type == SQL_C_WCHAR) { 02890 dp = uc_to_utf(data, len); 02891 if (!dp) { 02892 return nomem(s); 02893 } 02894 } 02895 #endif 02896 dlen = strlen(dp); 02897 freep(&p->param); 02898 p->param = xmalloc(dlen + 1); 02899 if (!p->param) { 02900 #ifdef SQLITE_UTF8 02901 if (dp != data) { 02902 uc_free(dp); 02903 } 02904 #endif 02905 return nomem(s); 02906 } 02907 strcpy(p->param, dp); 02908 #ifdef SQLITE_UTF8 02909 if (dp != data) { 02910 uc_free(dp); 02911 } 02912 #endif 02913 p->len = dlen; 02914 p->need = 0; 02915 } else if (len <= 0) { 02916 setstat(s, -1, "invalid length", "HY090"); 02917 return SQL_ERROR; 02918 } else { 02919 #if HAVE_ENCDEC 02920 putd: 02921 #endif 02922 dlen = min(p->len - p->offs, len); 02923 if (!p->param) { 02924 setstat(s, -1, "no memory for parameter", "HY013"); 02925 return SQL_ERROR; 02926 } 02927 memcpy((char *) p->param + p->offs, data, dlen); 02928 p->offs += dlen; 02929 if (p->offs >= p->len) { 02930 #ifdef SQLITE_UTF8 02931 if (p->type == SQL_C_WCHAR) { 02932 char *dp = uc_to_utf(p->param, p->len); 02933 char *np; 02934 int nlen; 02935 02936 if (!dp) { 02937 return nomem(s); 02938 } 02939 nlen = strlen(dp); 02940 np = xmalloc(nlen + 1); 02941 if (!np) { 02942 uc_free(dp); 02943 return nomem(s); 02944 } 02945 strcpy(np, dp); 02946 uc_free(dp); 02947 freep(&p->param); 02948 p->param = p->ind = np; 02949 p->len = nlen; 02950 } else { 02951 *((char *) p->param + p->len) = '\0'; 02952 } 02953 #else 02954 *((char *) p->param + p->len) = '\0'; 02955 #endif 02956 #if HAVE_ENCDEC 02957 if ((p->stype == SQL_BINARY || 02958 p->stype == SQL_VARBINARY || 02959 p->stype == SQL_LONGVARBINARY) && 02960 #ifdef SQLITE_UTF8 02961 (type == SQL_C_CHAR || type == SQL_C_WCHAR) 02962 #else 02963 type == SQL_C_CHAR 02964 #endif 02965 ) { 02966 if (hextobin(s, p) != SQL_SUCCESS) { 02967 return SQL_ERROR; 02968 } 02969 } else if (type == SQL_C_BINARY) { 02970 int bsize; 02971 char *bin; 02972 02973 bsize = sqlite_encode_binary(p->param, p->len, 0); 02974 bin = xmalloc(bsize + 1); 02975 if (!bin) { 02976 return nomem(s); 02977 } 02978 p->len = sqlite_encode_binary(p->param, p->len, bin); 02979 freep(&p->param); 02980 p->param = p->ind = bin; 02981 } 02982 #endif 02983 p->need = 0; 02984 } 02985 } 02986 done = 1; 02987 break; 02988 } 02989 } 02990 if (!done) { 02991 goto seqerr; 02992 } 02993 for (i = 0; i < s->nparams; i++) { 02994 p = &s->bindparms[i]; 02995 if (p->need) { 02996 return SQL_NEED_DATA; 02997 } 02998 } 02999 return drvexecute(stmt); 03000 } 03001 03007 static SQLRETURN 03008 freeparams(STMT *s) 03009 { 03010 if (s->bindparms) { 03011 int n; 03012 03013 for (n = 0; n < s->nbindparms; n++) { 03014 if (s->bindparms[n].ind && s->bindparms[n].param) { 03015 freep(&s->bindparms[n].param); 03016 } 03017 memset(&s->bindparms[n], 0, sizeof (BINDPARM)); 03018 } 03019 } 03020 return SQL_SUCCESS; 03021 } 03022 03023 /* see doc on top */ 03024 03025 static SQLRETURN 03026 substparam(STMT *s, int pnum, char **out, int *size) 03027 { 03028 char buf[256]; 03029 int type, len = 0; 03030 BINDPARM *p; 03031 double dval; 03032 03033 if (!s->bindparms || pnum < 0 || pnum >= s->nbindparms) { 03034 goto error; 03035 } 03036 p = &s->bindparms[pnum]; 03037 type = mapdeftype(p->type, p->stype, -1, s->nowchar); 03038 if (p->need) { 03039 if (!p->param) { 03040 p->len = SQL_LEN_DATA_AT_EXEC(*p->lenp); 03041 if (p->len <= 0 && p->len != SQL_NTS && p->len != SQL_NULL_DATA) { 03042 setstat(s, -1, "invalid length", "HY009"); 03043 return SQL_ERROR; 03044 } 03045 if (p->len > 0) { 03046 p->param = xmalloc(p->len + 1); 03047 if (!p->param) { 03048 return nomem(s); 03049 } 03050 } 03051 } 03052 return SQL_NEED_DATA; 03053 } 03054 if (!p->param || (p->lenp && *p->lenp == SQL_NULL_DATA)) { 03055 strcpy(buf, "NULL"); 03056 goto bind; 03057 } 03058 switch (type) { 03059 case SQL_C_CHAR: 03060 #ifdef SQLITE_UTF8 03061 case SQL_C_WCHAR: 03062 #endif 03063 #if HAVE_ENCDEC 03064 case SQL_C_BINARY: 03065 #endif 03066 break; 03067 case SQL_C_UTINYINT: 03068 sprintf(buf, "%d", *((unsigned char *) p->param)); 03069 goto bind; 03070 case SQL_C_TINYINT: 03071 case SQL_C_STINYINT: 03072 sprintf(buf, "%d", *((char *) p->param)); 03073 goto bind; 03074 case SQL_C_USHORT: 03075 sprintf(buf, "%d", *((unsigned short *) p->param)); 03076 goto bind; 03077 case SQL_C_SHORT: 03078 case SQL_C_SSHORT: 03079 sprintf(buf, "%d", *((short *) p->param)); 03080 goto bind; 03081 case SQL_C_ULONG: 03082 case SQL_C_LONG: 03083 case SQL_C_SLONG: 03084 sprintf(buf, "%ld", *((long *) p->param)); 03085 goto bind; 03086 case SQL_C_FLOAT: 03087 dval = *((float *) p->param); 03088 goto dodouble; 03089 case SQL_C_DOUBLE: 03090 dval = *((double *) p->param); 03091 dodouble: 03092 #if defined(HAVE_SQLITEMPRINTF) && HAVE_SQLITEMPRINTF 03093 { 03094 char *buf2 = sqlite_mprintf("%.16g", dval); 03095 03096 if (buf2) { 03097 strcpy(buf, buf2); 03098 sqlite_freemem(buf2); 03099 } else { 03100 strcpy(buf, "NULL"); 03101 } 03102 } 03103 #else 03104 ln_sprintfg(buf, dval); 03105 #endif 03106 goto bind; 03107 #ifdef SQL_C_TYPE_DATE 03108 case SQL_C_TYPE_DATE: 03109 #endif 03110 case SQL_C_DATE: 03111 sprintf(buf, "%04d-%02d-%02d", 03112 ((DATE_STRUCT *) p->param)->year, 03113 ((DATE_STRUCT *) p->param)->month, 03114 ((DATE_STRUCT *) p->param)->day); 03115 goto bind; 03116 #ifdef SQL_C_TYPE_TIME 03117 case SQL_C_TYPE_TIME: 03118 #endif 03119 case SQL_C_TIME: 03120 sprintf(buf, "%02d:%02d:%02d", 03121 ((TIME_STRUCT *) p->param)->hour, 03122 ((TIME_STRUCT *) p->param)->minute, 03123 ((TIME_STRUCT *) p->param)->second); 03124 goto bind; 03125 #ifdef SQL_C_TYPE_TIMESTAMP 03126 case SQL_C_TYPE_TIMESTAMP: 03127 #endif 03128 case SQL_C_TIMESTAMP: 03129 sprintf(buf, "%04d-%02d-%02d %02d:%02d:%02d.%d", 03130 ((TIMESTAMP_STRUCT *) p->param)->year, 03131 ((TIMESTAMP_STRUCT *) p->param)->month, 03132 ((TIMESTAMP_STRUCT *) p->param)->day, 03133 ((TIMESTAMP_STRUCT *) p->param)->hour, 03134 ((TIMESTAMP_STRUCT *) p->param)->minute, 03135 ((TIMESTAMP_STRUCT *) p->param)->second, 03136 (int) ((TIMESTAMP_STRUCT *) p->param)->fraction); 03137 bind: 03138 if (out) { 03139 strcpy(*out, buf); 03140 *out += strlen(buf) + 1; 03141 } 03142 if (size) { 03143 *size += strlen(buf) + 1; 03144 } 03145 return SQL_SUCCESS; 03146 default: 03147 goto error; 03148 } 03149 if (p->ind) { 03150 len = p->len; 03151 } else if (!p->lenp) { 03152 if (!(p->max != SQL_NTS || p->max == SQL_SETPARAM_VALUE_MAX)) { 03153 error: 03154 setstat(s, -1, "invalid parameter", (*s->ov3) ? "07009" : "S1093"); 03155 return SQL_ERROR; 03156 } 03157 } else { 03158 len = *p->lenp == SQL_NTS ? strlen(p->param) : *p->lenp; 03159 } 03160 if (out) { 03161 if (p->max == SQL_NTS || p->max == SQL_SETPARAM_VALUE_MAX) { 03162 strcpy(*out, p->param); 03163 *out += strlen(p->param) + 1; 03164 } else { 03165 if (len > 0) { 03166 memcpy(*out, p->param, len); 03167 *out += len; 03168 } 03169 **out = '\0'; 03170 *out += 1; 03171 } 03172 } 03173 if (size) { 03174 if (p->max == SQL_NTS || p->max == SQL_SETPARAM_VALUE_MAX) { 03175 *size += strlen(p->param) + 1; 03176 } else { 03177 *size += len > 0 ? len + 1 : 1; 03178 } 03179 } 03180 return SQL_SUCCESS; 03181 } 03182 03198 static SQLRETURN 03199 drvbindparam(SQLHSTMT stmt, SQLUSMALLINT pnum, SQLSMALLINT iotype, 03200 SQLSMALLINT buftype, SQLSMALLINT ptype, SQLUINTEGER coldef, 03201 SQLSMALLINT scale, 03202 SQLPOINTER data, SQLINTEGER buflen, SQLINTEGER *len) 03203 { 03204 STMT *s; 03205 BINDPARM *p; 03206 03207 if (stmt == SQL_NULL_HSTMT) { 03208 return SQL_INVALID_HANDLE; 03209 } 03210 s = (STMT *) stmt; 03211 if (pnum == 0) { 03212 setstat(s, -1, "invalid parameter", (*s->ov3) ? "07009" : "S1093"); 03213 return SQL_ERROR; 03214 } 03215 if (!data && (!len || (*len != SQL_NULL_DATA && 03216 *len > SQL_LEN_DATA_AT_EXEC_OFFSET))) { 03217 setstat(s, -1, "invalid buffer", "HY003"); 03218 return SQL_ERROR; 03219 } 03220 if (len && *len < 0 && *len > SQL_LEN_DATA_AT_EXEC_OFFSET && 03221 *len != SQL_NTS && *len != SQL_NULL_DATA) { 03222 setstat(s, -1, "invalid length reference", "HY009"); 03223 return SQL_ERROR; 03224 } 03225 #if 0 03226 if (iotype != SQL_PARAM_INPUT) 03227 return SQL_ERROR; 03228 #endif 03229 --pnum; 03230 if (s->bindparms) { 03231 if (pnum >= s->nbindparms) { 03232 BINDPARM *newparms; 03233 03234 newparms = xrealloc(s->bindparms, 03235 (pnum + 1) * sizeof (BINDPARM)); 03236 if (!newparms) { 03237 outofmem: 03238 return nomem(s); 03239 } 03240 s->bindparms = newparms; 03241 memset(&s->bindparms[s->nbindparms], 0, 03242 (pnum - s->nbindparms) * sizeof (BINDPARM)); 03243 s->nbindparms = pnum + 1; 03244 } 03245 } else { 03246 int npar = max(10, pnum + 1); 03247 03248 s->bindparms = xmalloc(npar * sizeof (BINDPARM)); 03249 if (!s->bindparms) { 03250 goto outofmem; 03251 } 03252 memset(s->bindparms, 0, npar * sizeof (BINDPARM)); 03253 s->nbindparms = npar; 03254 } 03255 p = &s->bindparms[pnum]; 03256 p->type = buftype; 03257 p->stype = ptype; 03258 p->max = buflen; 03259 p->inc = buflen; 03260 p->lenp = (int *) len; 03261 p->offs = 0; 03262 p->len = 0; 03263 if (p->lenp) { 03264 #ifdef SQLITE_UTF8 03265 if (buftype == SQL_C_WCHAR) { 03266 if (*p->lenp == SQL_NTS) { 03267 p->max = buflen = uc_strlen(data); 03268 } else if (*p->lenp >= 0) { 03269 p->max = buflen = *p->lenp; 03270 } 03271 } else 03272 #endif 03273 if (buftype == SQL_C_CHAR) { 03274 if (*p->lenp == SQL_NTS) { 03275 p->len = p->max = buflen = strlen(data); 03276 } else if (*p->lenp >= 0) { 03277 p->len = p->max = buflen = *p->lenp; 03278 } 03279 } 03280 } 03281 if (p->lenp && *p->lenp <= SQL_LEN_DATA_AT_EXEC_OFFSET) { 03282 p->param = NULL; 03283 p->ind = data; 03284 p->need = 1; 03285 } else if (p->lenp && *p->lenp == SQL_NULL_DATA) { 03286 p->param = NULL; 03287 p->ind = NULL; 03288 p->need = 0; 03289 } else { 03290 #if HAVE_ENCDEC 03291 int chkbin = 1; 03292 #endif 03293 03294 #ifdef SQLITE_UTF8 03295 if (buftype == SQL_C_WCHAR) { 03296 p->ind = uc_to_utf(data, buflen); 03297 if (!p->ind) { 03298 goto outofmem; 03299 } 03300 p->param = p->ind; 03301 p->len = strlen(p->param); 03302 } else 03303 #endif 03304 #if HAVE_ENCDEC 03305 if (buftype == SQL_C_BINARY) { 03306 int bsize; 03307 03308 p->len = *p->lenp; 03309 if (p->len < 0) { 03310 setstat(s, -1, "invalid length reference", "HY009"); 03311 return SQL_ERROR; 03312 } 03313 bsize = sqlite_encode_binary(data, p->len, 0); 03314 p->ind = xmalloc(bsize + 1); 03315 if (!p->ind) { 03316 goto outofmem; 03317 } 03318 p->param = p->ind; 03319 p->len = sqlite_encode_binary(data, p->len, p->param); 03320 chkbin = 0; 03321 } else 03322 #endif 03323 if (buftype == SQL_C_CHAR) { 03324 p->param = data; 03325 p->ind = NULL; 03326 } else { 03327 p->param = data; 03328 p->ind = NULL; 03329 #if HAVE_ENCDEC 03330 chkbin = 0; 03331 #endif 03332 } 03333 #if HAVE_ENCDEC 03334 if (chkbin) { 03335 if (ptype == SQL_BINARY || 03336 ptype == SQL_VARBINARY || 03337 ptype == SQL_LONGVARBINARY) { 03338 if (hextobin(s, p) != SQL_SUCCESS) { 03339 return SQL_ERROR; 03340 } 03341 } 03342 } 03343 #endif 03344 p->need = 0; 03345 } 03346 p->param0 = p->param; 03347 return SQL_SUCCESS; 03348 } 03349 03365 SQLRETURN SQL_API 03366 SQLBindParameter(SQLHSTMT stmt, SQLUSMALLINT pnum, SQLSMALLINT iotype, 03367 SQLSMALLINT buftype, SQLSMALLINT ptype, SQLUINTEGER coldef, 03368 SQLSMALLINT scale, 03369 SQLPOINTER data, SQLINTEGER buflen, SQLINTEGER *len) 03370 { 03371 return drvbindparam(stmt, pnum, iotype, buftype, ptype, coldef, 03372 scale, data, buflen, len); 03373 } 03374 03388 SQLRETURN SQL_API 03389 SQLBindParam(SQLHSTMT stmt, SQLUSMALLINT pnum, SQLSMALLINT vtype, 03390 SQLSMALLINT ptype, SQLUINTEGER lenprec, 03391 SQLSMALLINT scale, SQLPOINTER val, 03392 SQLINTEGER *lenp) 03393 { 03394 return drvbindparam(stmt, pnum, SQL_PARAM_INPUT, vtype, ptype, 03395 lenprec, scale, val, 0, lenp); 03396 } 03397 03405 SQLRETURN SQL_API 03406 SQLNumParams(SQLHSTMT stmt, SQLSMALLINT *nparam) 03407 { 03408 STMT *s; 03409 SQLSMALLINT dummy; 03410 03411 if (stmt == SQL_NULL_HSTMT) { 03412 return SQL_INVALID_HANDLE; 03413 } 03414 s = (STMT *) stmt; 03415 if (!nparam) { 03416 nparam = &dummy; 03417 } 03418 *nparam = s->nparams; 03419 return SQL_SUCCESS; 03420 } 03421 03429 SQLRETURN SQL_API 03430 SQLParamData(SQLHSTMT stmt, SQLPOINTER *p) 03431 { 03432 STMT *s; 03433 int i; 03434 SQLPOINTER dummy; 03435 03436 if (stmt == SQL_NULL_HSTMT) { 03437 return SQL_INVALID_HANDLE; 03438 } 03439 s = (STMT *) stmt; 03440 if (!p) { 03441 p = &dummy; 03442 } 03443 for (i = 0; i < s->nparams; i++) { 03444 if (s->bindparms[i].need) { 03445 *p = (SQLPOINTER) s->bindparms[i].ind; 03446 return SQL_NEED_DATA; 03447 } 03448 } 03449 return SQL_SUCCESS; 03450 } 03451 03463 SQLRETURN SQL_API 03464 SQLDescribeParam(SQLHSTMT stmt, UWORD pnum, SWORD *dtype, UDWORD *size, 03465 SWORD *decdigits, SWORD *nullable) 03466 { 03467 STMT *s; 03468 03469 if (stmt == SQL_NULL_HSTMT) { 03470 return SQL_INVALID_HANDLE; 03471 } 03472 s = (STMT *) stmt; 03473 --pnum; 03474 if (pnum >= s->nparams) { 03475 setstat(s, -1, "invalid parameter index", 03476 (*s->ov3) ? "HY000" : "S1000"); 03477 return SQL_ERROR; 03478 } 03479 if (dtype) { 03480 #ifdef SQL_LONGVARCHAR 03481 #ifdef SQLITE_UTF8 03482 *dtype = s->nowchar ? SQL_LONGVARCHAR : SQL_WLONGVARCHAR; 03483 #else 03484 *dtype = SQL_LONGVARCHAR; 03485 #endif 03486 #else 03487 #ifdef SQLITE_UTF8 03488 *dtype = s->nowchar ? SQL_VARCHAR : SQL_WVARCHAR; 03489 #else 03490 *dtype = SQL_VARCHAR; 03491 #endif 03492 #endif 03493 } 03494 if (size) { 03495 #ifdef SQL_LONGVARCHAR 03496 *size = 65536; 03497 #else 03498 *size = 255; 03499 #endif 03500 } 03501 if (decdigits) { 03502 *decdigits = 0; 03503 } 03504 if (nullable) { 03505 *nullable = SQL_NULLABLE; 03506 } 03507 return SQL_SUCCESS; 03508 } 03509 03523 SQLRETURN SQL_API 03524 SQLSetParam(SQLHSTMT stmt, SQLUSMALLINT par, SQLSMALLINT type, 03525 SQLSMALLINT sqltype, SQLUINTEGER coldef, 03526 SQLSMALLINT scale, SQLPOINTER val, SQLINTEGER *nval) 03527 { 03528 return drvbindparam(stmt, par, SQL_PARAM_INPUT, 03529 type, sqltype, coldef, scale, val, 03530 SQL_SETPARAM_VALUE_MAX, nval); 03531 } 03532 03537 SQLRETURN SQL_API 03538 SQLParamOptions(SQLHSTMT stmt, UDWORD rows, UDWORD *rowp) 03539 { 03540 return drvunimplstmt(stmt); 03541 } 03542 03543 #ifndef SQLITE_UTF8 03544 03548 SQLRETURN SQL_API 03549 SQLGetDescField(SQLHDESC handle, SQLSMALLINT recno, 03550 SQLSMALLINT fieldid, SQLPOINTER value, 03551 SQLINTEGER buflen, SQLINTEGER *strlen) 03552 { 03553 return SQL_ERROR; 03554 } 03555 #endif 03556 03557 #ifdef SQLITE_UTF8 03558 03562 SQLRETURN SQL_API 03563 SQLGetDescFieldW(SQLHDESC handle, SQLSMALLINT recno, 03564 SQLSMALLINT fieldid, SQLPOINTER value, 03565 SQLINTEGER buflen, SQLINTEGER *strlen) 03566 { 03567 return SQL_ERROR; 03568 } 03569 #endif 03570 03571 #ifndef SQLITE_UTF8 03572 03576 SQLRETURN SQL_API 03577 SQLSetDescField(SQLHDESC handle, SQLSMALLINT recno, 03578 SQLSMALLINT fieldid, SQLPOINTER value, 03579 SQLINTEGER buflen) 03580 { 03581 return SQL_ERROR; 03582 } 03583 #endif 03584 03585 #ifdef SQLITE_UTF8 03586 03590 SQLRETURN SQL_API 03591 SQLSetDescFieldW(SQLHDESC handle, SQLSMALLINT recno, 03592 SQLSMALLINT fieldid, SQLPOINTER value, 03593 SQLINTEGER buflen) 03594 { 03595 return SQL_ERROR; 03596 } 03597 #endif 03598 03599 #ifndef SQLITE_UTF8 03600 03604 SQLRETURN SQL_API 03605 SQLGetDescRec(SQLHDESC handle, SQLSMALLINT recno, 03606 SQLCHAR *name, SQLSMALLINT buflen, 03607 SQLSMALLINT *strlen, SQLSMALLINT *type, 03608 SQLSMALLINT *subtype, SQLINTEGER *len, 03609 SQLSMALLINT *prec, SQLSMALLINT *scale, 03610 SQLSMALLINT *nullable) 03611 { 03612 return SQL_ERROR; 03613 } 03614 #endif 03615 03616 #ifdef SQLITE_UTF8 03617 03621 SQLRETURN SQL_API 03622 SQLGetDescRecW(SQLHDESC handle, SQLSMALLINT recno, 03623 SQLWCHAR *name, SQLSMALLINT buflen, 03624 SQLSMALLINT *strlen, SQLSMALLINT *type, 03625 SQLSMALLINT *subtype, SQLINTEGER *len, 03626 SQLSMALLINT *prec, SQLSMALLINT *scale, 03627 SQLSMALLINT *nullable) 03628 { 03629 return SQL_ERROR; 03630 } 03631 #endif 03632 03637 SQLRETURN SQL_API 03638 SQLSetDescRec(SQLHDESC handle, SQLSMALLINT recno, 03639 SQLSMALLINT type, SQLSMALLINT subtype, 03640 SQLINTEGER len, SQLSMALLINT prec, 03641 SQLSMALLINT scale, SQLPOINTER data, 03642 SQLINTEGER *strlen, SQLINTEGER *indicator) 03643 { 03644 return SQL_ERROR; 03645 } 03646 03655 static SQLRETURN 03656 mkresultset(HSTMT stmt, COL *colspec, int ncols) 03657 { 03658 STMT *s; 03659 DBC *d; 03660 03661 if (stmt == SQL_NULL_HSTMT) { 03662 return SQL_INVALID_HANDLE; 03663 } 03664 s = (STMT *) stmt; 03665 if (s->dbc == SQL_NULL_HDBC) { 03666 noconn: 03667 return noconn(s); 03668 } 03669 d = (DBC *) s->dbc; 03670 if (!d->sqlite) { 03671 goto noconn; 03672 } 03673 vm_end_if(s); 03674 freeresult(s, 0); 03675 s->ncols = ncols; 03676 s->cols = colspec; 03677 mkbindcols(s, s->ncols); 03678 s->nrows = 0; 03679 s->rowp = -1; 03680 return SQL_SUCCESS; 03681 } 03682 03687 static COL tablePrivSpec[] = { 03688 { "SYSTEM", "TABLEPRIV", "TABLE_QUALIFIER", SCOL_VARCHAR, 50 }, 03689 { "SYSTEM", "TABLEPRIV", "TABLE_OWNER", SCOL_VARCHAR, 50 }, 03690 { "SYSTEM", "TABLEPRIV", "TABLE_NAME", SCOL_VARCHAR, 255 }, 03691 { "SYSTEM", "TABLEPRIV", "GRANTOR", SCOL_VARCHAR, 50 }, 03692 { "SYSTEM", "TABLEPRIV", "GRANTEE", SCOL_VARCHAR, 50 }, 03693 { "SYSTEM", "TABLEPRIV", "PRIVILEGE", SCOL_VARCHAR, 50 }, 03694 { "SYSTEM", "TABLEPRIV", "IS_GRANTABLE", SCOL_VARCHAR, 50 } 03695 }; 03696 03697 #ifndef SQLITE_UTF8 03698 03710 SQLRETURN SQL_API 03711 SQLTablePrivileges(SQLHSTMT stmt, 03712 SQLCHAR *catalog, SQLSMALLINT catalogLen, 03713 SQLCHAR *schema, SQLSMALLINT schemaLen, 03714 SQLCHAR *table, SQLSMALLINT tableLen) 03715 { 03716 return mkresultset(stmt, tablePrivSpec, array_size(tablePrivSpec)); 03717 } 03718 #endif 03719 03720 #if !defined(HAVE_UNIXODBC) || !HAVE_UNIXODBC 03721 #ifdef SQLITE_UTF8 03722 03734 SQLRETURN SQL_API 03735 SQLTablePrivilegesW(SQLHSTMT stmt, 03736 SQLWCHAR *catalog, SQLSMALLINT catalogLen, 03737 SQLWCHAR *schema, SQLSMALLINT schemaLen, 03738 SQLWCHAR *table, SQLSMALLINT tableLen) 03739 { 03740 return mkresultset(stmt, tablePrivSpec, array_size(tablePrivSpec)); 03741 } 03742 #endif 03743 #endif 03744 03749 static COL colPrivSpec[] = { 03750 { "SYSTEM", "COLPRIV", "TABLE_QUALIFIER", SCOL_VARCHAR, 50 }, 03751 { "SYSTEM", "COLPRIV", "TABLE_OWNER", SCOL_VARCHAR, 50 }, 03752 { "SYSTEM", "COLPRIV", "TABLE_NAME", SCOL_VARCHAR, 255 }, 03753 { "SYSTEM", "COLPRIV", "GRANTOR", SCOL_VARCHAR, 50 }, 03754 { "SYSTEM", "COLPRIV", "GRANTEE", SCOL_VARCHAR, 50 }, 03755 { "SYSTEM", "COLPRIV", "PRIVILEGE", SCOL_VARCHAR, 50 }, 03756 { "SYSTEM", "COLPRIV", "IS_GRANTABLE", SCOL_VARCHAR, 50 } 03757 }; 03758 03759 #ifndef SQLITE_UTF8 03760 03774 SQLRETURN SQL_API 03775 SQLColumnPrivileges(SQLHSTMT stmt, 03776 SQLCHAR *catalog, SQLSMALLINT catalogLen, 03777 SQLCHAR *schema, SQLSMALLINT schemaLen, 03778 SQLCHAR *table, SQLSMALLINT tableLen, 03779 SQLCHAR *column, SQLSMALLINT columnLen) 03780 { 03781 return mkresultset(stmt, colPrivSpec, array_size(colPrivSpec)); 03782 } 03783 #endif 03784 03785 #if !defined(HAVE_UNIXODBC) || !HAVE_UNIXODBC 03786 #ifdef SQLITE_UTF8 03787 03801 SQLRETURN SQL_API 03802 SQLColumnPrivilegesW(SQLHSTMT stmt, 03803 SQLWCHAR *catalog, SQLSMALLINT catalogLen, 03804 SQLWCHAR *schema, SQLSMALLINT schemaLen, 03805 SQLWCHAR *table, SQLSMALLINT tableLen, 03806 SQLWCHAR *column, SQLSMALLINT columnLen) 03807 { 03808 return mkresultset(stmt, colPrivSpec, array_size(colPrivSpec)); 03809 } 03810 #endif 03811 #endif 03812 03817 static COL pkeySpec[] = { 03818 { "SYSTEM", "PRIMARYKEY", "TABLE_QUALIFIER", SCOL_VARCHAR, 50 }, 03819 { "SYSTEM", "PRIMARYKEY", "TABLE_OWNER", SCOL_VARCHAR, 50 }, 03820 { "SYSTEM", "PRIMARYKEY", "TABLE_NAME", SCOL_VARCHAR, 255 }, 03821 { "SYSTEM", "PRIMARYKEY", "COLUMN_NAME", SCOL_VARCHAR, 255 }, 03822 { "SYSTEM", "PRIMARYKEY", "KEY_SEQ", SQL_SMALLINT, 50 }, 03823 { "SYSTEM", "PRIMARYKEY", "PK_NAME", SCOL_VARCHAR, 50 } 03824 }; 03825 03838 static SQLRETURN 03839 drvprimarykeys(SQLHSTMT stmt, 03840 SQLCHAR *cat, SQLSMALLINT catLen, 03841 SQLCHAR *schema, SQLSMALLINT schemaLen, 03842 SQLCHAR *table, SQLSMALLINT tableLen) 03843 { 03844 STMT *s; 03845 DBC *d; 03846 SQLRETURN sret; 03847 int i, size, ret, nrows, ncols, offs, namec, uniquec; 03848 char **rowp, *errp = NULL, tname[512]; 03849 03850 sret = mkresultset(stmt, pkeySpec, array_size(pkeySpec)); 03851 if (sret != SQL_SUCCESS) { 03852 return sret; 03853 } 03854 s = (STMT *) stmt; 03855 d = (DBC *) s->dbc; 03856 if (!table || table[0] == '\0' || table[0] == '%') { 03857 setstat(s, -1, "need table name", (*s->ov3) ? "HY000" : "S1000"); 03858 return SQL_ERROR; 03859 } 03860 if (tableLen == SQL_NTS) { 03861 size = sizeof (tname) - 1; 03862 } else { 03863 size = min(sizeof (tname) - 1, tableLen); 03864 } 03865 strncpy(tname, table, size); 03866 tname[size] = '\0'; 03867 ret = sqlite_get_table_printf(d->sqlite, 03868 "PRAGMA index_list('%q')", &rowp, 03869 &nrows, &ncols, &errp, tname); 03870 if (ret != SQLITE_OK) { 03871 setstat(s, ret, "%s (%d)", (*s->ov3) ? "HY000" : "S1000", 03872 errp ? errp : "unknown error", ret); 03873 if (errp) { 03874 sqlite_freemem(errp); 03875 errp = NULL; 03876 } 03877 return SQL_ERROR; 03878 } 03879 if (errp) { 03880 sqlite_freemem(errp); 03881 errp = NULL; 03882 } 03883 if (ncols * nrows <= 0) { 03884 nodata: 03885 sqlite_free_table(rowp); 03886 /* try table_info for integer primary keys */ 03887 ret = sqlite_get_table_printf(d->sqlite, 03888 "PRAGMA table_info('%q')", &rowp, 03889 &nrows, &ncols, NULL, tname); 03890 if (ret == SQLITE_OK) { 03891 int typec, roffs; 03892 03893 namec = findcol(rowp, ncols, "name"); 03894 uniquec = findcol(rowp, ncols, "pk"); 03895 typec = findcol(rowp, ncols, "type"); 03896 if (namec < 0 || uniquec < 0 || typec < 0) { 03897 goto nodata2; 03898 } 03899 for (i = 1; i <= nrows; i++) { 03900 if (*rowp[i * ncols + uniquec] != '0' && 03901 strlen(rowp[i * ncols + typec]) == 7 && 03902 strncasecmp(rowp[i * ncols + typec], "integer", 7) == 0) { 03903 break; 03904 } 03905 } 03906 if (i > nrows) { 03907 goto nodata2; 03908 } 03909 size = (1 + 1) * array_size(pkeySpec); 03910 s->rows = xmalloc((size + 1) * sizeof (char *)); 03911 if (!s->rows) { 03912 s->nrows = 0; 03913 return nomem(s); 03914 } 03915 s->rows[0] = (char *) size; 03916 s->rows += 1; 03917 memset(s->rows, 0, sizeof (char *) * size); 03918 s->rowfree = freerows; 03919 s->nrows = 1; 03920 roffs = s->ncols; 03921 s->rows[roffs + 0] = xstrdup(""); 03922 s->rows[roffs + 1] = xstrdup(""); 03923 s->rows[roffs + 2] = xstrdup(tname); 03924 s->rows[roffs + 3] = xstrdup(rowp[i * ncols + namec]); 03925 s->rows[roffs + 4] = xstrdup("1"); 03926 nodata2: 03927 sqlite_free_table(rowp); 03928 } 03929 return SQL_SUCCESS; 03930 } 03931 size = 0; 03932 namec = findcol(rowp, ncols, "name"); 03933 uniquec = findcol(rowp, ncols, "unique"); 03934 if (namec < 0 || uniquec < 0) { 03935 goto nodata; 03936 } 03937 for (i = 1; i <= nrows; i++) { 03938 int nnrows, nncols; 03939 char **rowpp; 03940 03941 if (*rowp[i * ncols + uniquec] != '0') { 03942 ret = sqlite_get_table_printf(d->sqlite, 03943 "PRAGMA index_info('%q')", &rowpp, 03944 &nnrows, &nncols, NULL, 03945 rowp[i * ncols + namec]); 03946 if (ret == SQLITE_OK) { 03947 size += nnrows; 03948 sqlite_free_table(rowpp); 03949 } 03950 } 03951 } 03952 if (size == 0) { 03953 goto nodata; 03954 } 03955 s->nrows = size; 03956 size = (size + 1) * array_size(pkeySpec); 03957 s->rows = xmalloc((size + 1) * sizeof (char *)); 03958 if (!s->rows) { 03959 s->nrows = 0; 03960 return nomem(s); 03961 } 03962 s->rows[0] = (char *) size; 03963 s->rows += 1; 03964 memset(s->rows, 0, sizeof (char *) * size); 03965 s->rowfree = freerows; 03966 offs = 0; 03967 for (i = 1; i <= nrows; i++) { 03968 int nnrows, nncols; 03969 char **rowpp; 03970 03971 if (*rowp[i * ncols + uniquec] != '0') { 03972 int k; 03973 03974 ret = sqlite_get_table_printf(d->sqlite, 03975 "PRAGMA index_info('%q')", &rowpp, 03976 &nnrows, &nncols, NULL, 03977 rowp[i * ncols + namec]); 03978 if (ret != SQLITE_OK) { 03979 continue; 03980 } 03981 for (k = 0; nnrows && k < nncols; k++) { 03982 if (strcmp(rowpp[k], "name") == 0) { 03983 int m; 03984 03985 for (m = 1; m <= nnrows; m++) { 03986 int roffs = (offs + m) * s->ncols; 03987 03988 s->rows[roffs + 0] = xstrdup(""); 03989 s->rows[roffs + 1] = xstrdup(""); 03990 s->rows[roffs + 2] = xstrdup(tname); 03991 s->rows[roffs + 3] = xstrdup(rowpp[m * nncols + k]); 03992 s->rows[roffs + 5] = xstrdup(rowp[i * ncols + namec]); 03993 } 03994 } else if (strcmp(rowpp[k], "seqno") == 0) { 03995 int m; 03996 03997 for (m = 1; m <= nnrows; m++) { 03998 int roffs = (offs + m) * s->ncols; 03999 int pos = m - 1; 04000 char buf[32]; 04001 04002 sscanf(rowpp[m * nncols + k], "%d", &pos); 04003 sprintf(buf, "%d", pos + 1); 04004 s->rows[roffs + 4] = xstrdup(buf); 04005 } 04006 } 04007 } 04008 offs += nnrows; 04009 sqlite_free_table(rowpp); 04010 } 04011 } 04012 sqlite_free_table(rowp); 04013 return SQL_SUCCESS; 04014 } 04015 04016 #ifndef SQLITE_UTF8 04017 04029 SQLRETURN SQL_API 04030 SQLPrimaryKeys(SQLHSTMT stmt, 04031 SQLCHAR *cat, SQLSMALLINT catLen, 04032 SQLCHAR *schema, SQLSMALLINT schemaLen, 04033 SQLCHAR *table, SQLSMALLINT tableLen) 04034 { 04035 return drvprimarykeys(stmt, cat, catLen, schema, schemaLen, 04036 table, tableLen); 04037 } 04038 #endif 04039 04040 #ifdef SQLITE_UTF8 04041 04053 SQLRETURN SQL_API 04054 SQLPrimaryKeysW(SQLHSTMT stmt, 04055 SQLWCHAR *cat, SQLSMALLINT catLen, 04056 SQLWCHAR *schema, SQLSMALLINT schemaLen, 04057 SQLWCHAR *table, SQLSMALLINT tableLen) 04058 { 04059 char *c = NULL, *s = NULL, *t = NULL; 04060 SQLRETURN ret; 04061 04062 if (cat) { 04063 c = uc_to_utf_c(cat, catLen); 04064 if (!c) { 04065 ret = nomem((STMT *) stmt); 04066 goto done; 04067 } 04068 } 04069 if (schema) { 04070 s = uc_to_utf_c(schema, schemaLen); 04071 if (!s) { 04072 ret = nomem((STMT *) stmt); 04073 goto done; 04074 } 04075 } 04076 if (table) { 04077 t = uc_to_utf_c(table, tableLen); 04078 if (!t) { 04079 ret = nomem((STMT *) stmt); 04080 goto done; 04081 } 04082 } 04083 ret = drvprimarykeys(stmt, c, SQL_NTS, s, SQL_NTS, t, SQL_NTS); 04084 done: 04085 uc_free(t); 04086 uc_free(s); 04087 uc_free(c); 04088 return ret; 04089 } 04090 #endif 04091 04096 static COL scolSpec[] = { 04097 { "SYSTEM", "COLUMN", "SCOPE", SQL_SMALLINT, 1 }, 04098 { "SYSTEM", "COLUMN", "COLUMN_NAME", SCOL_VARCHAR, 255 }, 04099 { "SYSTEM", "COLUMN", "DATA_TYPE", SQL_SMALLINT, 50 }, 04100 { "SYSTEM", "COLUMN", "TYPE_NAME", SCOL_VARCHAR, 50 }, 04101 { "SYSTEM", "COLUMN", "PRECISION", SQL_INTEGER, 50 }, 04102 { "SYSTEM", "COLUMN", "LENGTH", SQL_INTEGER, 50 }, 04103 { "SYSTEM", "COLUMN", "DECIMAL_DIGITS", SQL_INTEGER, 50 }, 04104 { "SYSTEM", "COLUMN", "PSEUDO_COLUMN", SQL_SMALLINT, 1 }, 04105 { "SYSTEM", "COLUMN", "NULLABLE", SQL_SMALLINT, 1 } 04106 }; 04107 04123 static SQLRETURN 04124 drvspecialcolumns(SQLHSTMT stmt, SQLUSMALLINT id, 04125 SQLCHAR *cat, SQLSMALLINT catLen, 04126 SQLCHAR *schema, SQLSMALLINT schemaLen, 04127 SQLCHAR *table, SQLSMALLINT tableLen, 04128 SQLUSMALLINT scope, SQLUSMALLINT nullable) 04129 { 04130 STMT *s; 04131 DBC *d; 04132 SQLRETURN sret; 04133 int i, size, ret, nrows, ncols, nnnrows, nnncols, offs; 04134 int namec = -1, uniquec = -1, namecc = -1, typecc = -1; 04135 int notnullcc = -1, mkrowid = 0; 04136 char *errp = NULL, tname[512]; 04137 char **rowp = NULL, **rowppp = NULL; 04138 04139 sret = mkresultset(stmt, scolSpec, array_size(scolSpec)); 04140 if (sret != SQL_SUCCESS) { 04141 return sret; 04142 } 04143 s = (STMT *) stmt; 04144 d = (DBC *) s->dbc; 04145 if (!table || table[0] == '\0' || table[0] == '%') { 04146 setstat(s, -1, "need table name", (*s->ov3) ? "HY000" : "S1000"); 04147 return SQL_ERROR; 04148 } 04149 if (tableLen == SQL_NTS) { 04150 size = sizeof (tname) - 1; 04151 } else { 04152 size = min(sizeof (tname) - 1, tableLen); 04153 } 04154 strncpy(tname, table, size); 04155 tname[size] = '\0'; 04156 if (id != SQL_BEST_ROWID) { 04157 return SQL_SUCCESS; 04158 } 04159 ret = sqlite_get_table_printf(d->sqlite, "PRAGMA index_list('%q')", 04160 &rowp, &nrows, &ncols, &errp, tname); 04161 if (ret != SQLITE_OK) { 04162 doerr: 04163 setstat(s, ret, "%s (%d)", (*s->ov3) ? "HY000" : "S1000", 04164 errp ? errp : "unknown error", ret); 04165 if (errp) { 04166 sqlite_freemem(errp); 04167 errp = NULL; 04168 } 04169 return SQL_ERROR; 04170 } 04171 if (errp) { 04172 sqlite_freemem(errp); 04173 errp = NULL; 04174 } 04175 size = 0; /* number result rows */ 04176 if (ncols * nrows <= 0) { 04177 goto nodata_but_rowid; 04178 } 04179 ret = sqlite_get_table_printf(d->sqlite, "PRAGMA table_info('%q')", 04180 &rowppp, &nnnrows, &nnncols, &errp, tname); 04181 if (ret != SQLITE_OK) { 04182 sqlite_free_table(rowp); 04183 goto doerr; 04184 } 04185 if (errp) { 04186 sqlite_freemem(errp); 04187 errp = NULL; 04188 } 04189 namec = findcol(rowp, ncols, "name"); 04190 uniquec = findcol(rowp, ncols, "unique"); 04191 if (namec < 0 || uniquec < 0) { 04192 goto nodata_but_rowid; 04193 } 04194 namecc = findcol(rowppp, nnncols, "name"); 04195 typecc = findcol(rowppp, nnncols, "type"); 04196 notnullcc = findcol(rowppp, nnncols, "notnull"); 04197 for (i = 1; i <= nrows; i++) { 04198 int nnrows, nncols; 04199 char **rowpp; 04200 04201 if (*rowp[i * ncols + uniquec] != '0') { 04202 ret = sqlite_get_table_printf(d->sqlite, 04203 "PRAGMA index_info('%q')", &rowpp, 04204 &nnrows, &nncols, NULL, 04205 rowp[i * ncols + namec]); 04206 if (ret == SQLITE_OK) { 04207 size += nnrows; 04208 sqlite_free_table(rowpp); 04209 } 04210 } 04211 } 04212 nodata_but_rowid: 04213 if (size == 0) { 04214 size = 1; 04215 mkrowid = 1; 04216 } 04217 s->nrows = size; 04218 size = (size + 1) * array_size(scolSpec); 04219 s->rows = xmalloc((size + 1) * sizeof (char *)); 04220 if (!s->rows) { 04221 s->nrows = 0; 04222 sqlite_free_table(rowp); 04223 sqlite_free_table(rowppp); 04224 return nomem(s); 04225 } 04226 s->rows[0] = (char *) size; 04227 s->rows += 1; 04228 memset(s->rows, 0, sizeof (char *) * size); 04229 s->rowfree = freerows; 04230 if (mkrowid) { 04231 s->nrows = 0; 04232 goto mkrowid; 04233 } 04234 offs = 0; 04235 for (i = 1; i <= nrows; i++) { 04236 int nnrows, nncols; 04237 char **rowpp; 04238 04239 if (*rowp[i * ncols + uniquec] != '0') { 04240 int k; 04241 04242 ret = sqlite_get_table_printf(d->sqlite, 04243 "PRAGMA index_info('%q')", &rowpp, 04244 &nnrows, &nncols, NULL, 04245 rowp[i * ncols + namec]); 04246 if (ret != SQLITE_OK) { 04247 continue; 04248 } 04249 for (k = 0; nnrows && k < nncols; k++) { 04250 if (strcmp(rowpp[k], "name") == 0) { 04251 int m; 04252 04253 for (m = 1; m <= nnrows; m++) { 04254 int roffs = (offs + m) * s->ncols; 04255 04256 s->rows[roffs + 0] = 04257 xstrdup(stringify(SQL_SCOPE_SESSION)); 04258 s->rows[roffs + 1] = xstrdup(rowpp[m * nncols + k]); 04259 s->rows[roffs + 4] = xstrdup("0"); 04260 s->rows[roffs + 7] = 04261 xstrdup(stringify(SQL_PC_NOT_PSEUDO)); 04262 if (namecc >= 0 && typecc >= 0) { 04263 int ii; 04264 04265 for (ii = 1; ii <= nnnrows; ii++) { 04266 if (strcmp(rowppp[ii * nnncols + namecc], 04267 rowpp[m * nncols + k]) == 0) { 04268 char *typen = rowppp[ii * nnncols + typecc]; 04269 int sqltype, mm, dd, isnullable = 0; 04270 char buf[32]; 04271 04272 s->rows[roffs + 3] = xstrdup(typen); 04273 sqltype = mapsqltype(typen, NULL, *s->ov3, 04274 s->nowchar); 04275 getmd(typen, sqltype, &mm, &dd); 04276 #ifdef SQL_LONGVARCHAR 04277 if (sqltype == SQL_VARCHAR && mm > 255) { 04278 sqltype = SQL_LONGVARCHAR; 04279 } 04280 #endif 04281 #ifdef SQLITE_UTF8 04282 #ifdef SQL_WLONGVARCHAR 04283 if (sqltype == SQL_WVARCHAR && mm > 255) { 04284 sqltype = SQL_WLONGVARCHAR; 04285 } 04286 #endif 04287 #endif 04288 #if HAVE_ENCDEC 04289 if (sqltype == SQL_VARBINARY && mm > 255) { 04290 sqltype = SQL_LONGVARBINARY; 04291 } 04292 #endif 04293 sprintf(buf, "%d", sqltype); 04294 s->rows[roffs + 2] = xstrdup(buf); 04295 sprintf(buf, "%d", mm); 04296 s->rows[roffs + 5] = xstrdup(buf); 04297 sprintf(buf, "%d", dd); 04298 s->rows[roffs + 6] = xstrdup(buf); 04299 if (notnullcc >= 0) { 04300 char *inp = 04301 rowppp[ii * nnncols + notnullcc]; 04302 04303 isnullable = inp[0] != '0'; 04304 } 04305 sprintf(buf, "%d", isnullable); 04306 s->rows[roffs + 8] = xstrdup(buf); 04307 } 04308 } 04309 } 04310 } 04311 } 04312 } 04313 offs += nnrows; 04314 sqlite_free_table(rowpp); 04315 } 04316 } 04317 if (nullable == SQL_NO_NULLS) { 04318 for (i = 1; i < s->nrows; i++) { 04319 if (s->rows[i * s->ncols + 8][0] == '0') { 04320 int m, i1 = i + 1; 04321 04322 for (m = 0; m < s->ncols; m++) { 04323 freep(&s->rows[i * s->ncols + m]); 04324 } 04325 size = s->ncols * sizeof (char *) * (s->nrows - i1); 04326 if (size > 0) { 04327 memmove(s->rows + i * s->ncols, 04328 s->rows + i1 * s->ncols, 04329 size); 04330 memset(s->rows + s->nrows * s->ncols, 0, 04331 s->ncols * sizeof (char *)); 04332 } 04333 s->nrows--; 04334 --i; 04335 } 04336 } 04337 } 04338 mkrowid: 04339 sqlite_free_table(rowp); 04340 sqlite_free_table(rowppp); 04341 if (s->nrows == 0) { 04342 s->rows[s->ncols + 0] = xstrdup(stringify(SQL_SCOPE_SESSION)); 04343 s->rows[s->ncols + 1] = xstrdup("_ROWID_"); 04344 s->rows[s->ncols + 2] = xstrdup(stringify(SQL_INTEGER)); 04345 s->rows[s->ncols + 3] = xstrdup("integer"); 04346 s->rows[s->ncols + 4] = xstrdup("0"); 04347 s->rows[s->ncols + 5] = xstrdup("10"); 04348 s->rows[s->ncols + 6] = xstrdup("9"); 04349 s->rows[s->ncols + 7] = xstrdup(stringify(SQL_PC_PSEUDO)); 04350 s->rows[s->ncols + 8] = xstrdup(stringify(SQL_FALSE)); 04351 s->nrows = 1; 04352 } 04353 return SQL_SUCCESS; 04354 } 04355 04356 #ifndef SQLITE_UTF8 04357 04372 SQLRETURN SQL_API 04373 SQLSpecialColumns(SQLHSTMT stmt, SQLUSMALLINT id, 04374 SQLCHAR *cat, SQLSMALLINT catLen, 04375 SQLCHAR *schema, SQLSMALLINT schemaLen, 04376 SQLCHAR *table, SQLSMALLINT tableLen, 04377 SQLUSMALLINT scope, SQLUSMALLINT nullable) 04378 { 04379 return drvspecialcolumns(stmt, id, cat, catLen, schema, schemaLen, 04380 table, tableLen, scope, nullable); 04381 } 04382 #endif 04383 04384 #ifdef SQLITE_UTF8 04385 04400 SQLRETURN SQL_API 04401 SQLSpecialColumnsW(SQLHSTMT stmt, SQLUSMALLINT id, 04402 SQLWCHAR *cat, SQLSMALLINT catLen, 04403 SQLWCHAR *schema, SQLSMALLINT schemaLen, 04404 SQLWCHAR *table, SQLSMALLINT tableLen, 04405 SQLUSMALLINT scope, SQLUSMALLINT nullable) 04406 { 04407 char *c = NULL, *s = NULL, *t = NULL; 04408 SQLRETURN ret; 04409 04410 if (cat) { 04411 c = uc_to_utf_c(cat, catLen); 04412 if (!c) { 04413 ret = nomem((STMT *) stmt); 04414 goto done; 04415 } 04416 } 04417 if (schema) { 04418 s = uc_to_utf_c(schema, schemaLen); 04419 if (!s) { 04420 ret = nomem((STMT *) stmt); 04421 goto done; 04422 } 04423 } 04424 if (table) { 04425 t = uc_to_utf_c(table, tableLen); 04426 if (!t) { 04427 ret = nomem((STMT *) stmt); 04428 goto done; 04429 } 04430 } 04431 ret = drvspecialcolumns(stmt, id, c, SQL_NTS, s, SQL_NTS, t, SQL_NTS, 04432 scope, nullable); 04433 done: 04434 uc_free(t); 04435 uc_free(s); 04436 uc_free(c); 04437 return ret; 04438 } 04439 #endif 04440 04445 static COL fkeySpec[] = { 04446 { "SYSTEM", "FOREIGNKEY", "PKTABLE_QUALIFIER", SCOL_VARCHAR, 50 }, 04447 { "SYSTEM", "FOREIGNKEY", "PKTABLE_OWNER", SCOL_VARCHAR, 50 }, 04448 { "SYSTEM", "FOREIGNKEY", "PKTABLE_NAME", SCOL_VARCHAR, 255 }, 04449 { "SYSTEM", "FOREIGNKEY", "PKCOLUMN_NAME", SCOL_VARCHAR, 255 }, 04450 { "SYSTEM", "FOREIGNKEY", "FKTABLE_QUALIFIER", SCOL_VARCHAR, 50 }, 04451 { "SYSTEM", "FOREIGNKEY", "FKTABLE_OWNER", SCOL_VARCHAR, 50 }, 04452 { "SYSTEM", "FOREIGNKEY", "FKTABLE_NAME", SCOL_VARCHAR, 255 }, 04453 { "SYSTEM", "FOREIGNKEY", "FKCOLUMN_NAME", SCOL_VARCHAR, 255 }, 04454 { "SYSTEM", "FOREIGNKEY", "KEY_SEQ", SQL_SMALLINT, 5 }, 04455 { "SYSTEM", "FOREIGNKEY", "UPDATE_RULE", SQL_SMALLINT, 5 }, 04456 { "SYSTEM", "FOREIGNKEY", "DELETE_RULE", SQL_SMALLINT, 5 }, 04457 { "SYSTEM", "FOREIGNKEY", "FK_NAME", SCOL_VARCHAR, 255 }, 04458 { "SYSTEM", "FOREIGNKEY", "PK_NAME", SCOL_VARCHAR, 255 }, 04459 { "SYSTEM", "FOREIGNKEY", "DEFERRABILITY", SQL_SMALLINT, 5 } 04460 }; 04461 04480 static SQLRETURN SQL_API 04481 drvforeignkeys(SQLHSTMT stmt, 04482 SQLCHAR *PKcatalog, SQLSMALLINT PKcatalogLen, 04483 SQLCHAR *PKschema, SQLSMALLINT PKschemaLen, 04484 SQLCHAR *PKtable, SQLSMALLINT PKtableLen, 04485 SQLCHAR *FKcatalog, SQLSMALLINT FKcatalogLen, 04486 SQLCHAR *FKschema, SQLSMALLINT FKschemaLen, 04487 SQLCHAR *FKtable, SQLSMALLINT FKtableLen) 04488 { 04489 STMT *s; 04490 DBC *d; 04491 SQLRETURN sret; 04492 int i, size, ret, nrows, ncols, offs, namec, seqc, fromc, toc; 04493 char **rowp, *errp = NULL, pname[512], fname[512]; 04494 04495 sret = mkresultset(stmt, fkeySpec, array_size(fkeySpec)); 04496 if (sret != SQL_SUCCESS) { 04497 return sret; 04498 } 04499 s = (STMT *) stmt; 04500 d = (DBC *) s->dbc; 04501 if ((!PKtable || PKtable[0] == '\0' || PKtable[0] == '%') && 04502 (!FKtable || FKtable[0] == '\0' || FKtable[0] == '%')) { 04503 setstat(s, -1, "need table name", (*s->ov3) ? "HY000" : "S1000"); 04504 return SQL_ERROR; 04505 } 04506 size = 0; 04507 if (PKtable) { 04508 if (PKtableLen == SQL_NTS) { 04509 size = sizeof (pname) - 1; 04510 } else { 04511 size = min(sizeof (pname) - 1, PKtableLen); 04512 } 04513 strncpy(pname, PKtable, size); 04514 } 04515 pname[size] = '\0'; 04516 size = 0; 04517 if (FKtable) { 04518 if (FKtableLen == SQL_NTS) { 04519 size = sizeof (fname) - 1; 04520 } else { 04521 size = min(sizeof (fname) - 1, FKtableLen); 04522 } 04523 strncpy(fname, FKtable, size); 04524 } 04525 fname[size] = '\0'; 04526 if (fname[0] != '\0') { 04527 int plen; 04528 04529 ret = sqlite_get_table_printf(d->sqlite, 04530 "PRAGMA foreign_key_list('%q')", &rowp, 04531 &nrows, &ncols, &errp, fname); 04532 if (ret != SQLITE_OK) { 04533 setstat(s, ret, "%s (%d)", (*s->ov3) ? "HY000" : "S1000", 04534 errp ? errp : "unknown error", ret); 04535 if (errp) { 04536 sqlite_freemem(errp); 04537 errp = NULL; 04538 } 04539 return SQL_ERROR; 04540 } 04541 if (errp) { 04542 sqlite_freemem(errp); 04543 errp = NULL; 04544 } 04545 if (ncols * nrows <= 0) { 04546 nodata: 04547 sqlite_free_table(rowp); 04548 return SQL_SUCCESS; 04549 } 04550 size = 0; 04551 namec = findcol(rowp, ncols, "table"); 04552 seqc = findcol(rowp, ncols, "seq"); 04553 fromc = findcol(rowp, ncols, "from"); 04554 toc = findcol(rowp, ncols, "to"); 04555 if (namec < 0 || seqc < 0 || fromc < 0 || toc < 0) { 04556 goto nodata; 04557 } 04558 plen = strlen(pname); 04559 for (i = 1; i <= nrows; i++) { 04560 char *ptab = rowp[i * ncols + namec]; 04561 04562 if (plen && ptab) { 04563 int len = strlen(ptab); 04564 04565 if (plen != len || strncasecmp(pname, ptab, plen) != 0) { 04566 continue; 04567 } 04568 } 04569 size++; 04570 } 04571 if (size == 0) { 04572 goto nodata; 04573 } 04574 s->nrows = size; 04575 size = (size + 1) * array_size(fkeySpec); 04576 s->rows = xmalloc((size + 1) * sizeof (char *)); 04577 if (!s->rows) { 04578 s->nrows = 0; 04579 return nomem(s); 04580 } 04581 s->rows[0] = (char *) size; 04582 s->rows += 1; 04583 memset(s->rows, 0, sizeof (char *) * size); 04584 s->rowfree = freerows; 04585 offs = 0; 04586 for (i = 1; i <= nrows; i++) { 04587 int pos = 0, roffs = (offs + 1) * s->ncols; 04588 char *ptab = rowp[i * ncols + namec]; 04589 char buf[32]; 04590 04591 if (plen && ptab) { 04592 int len = strlen(ptab); 04593 04594 if (plen != len || strncasecmp(pname, ptab, plen) != 0) { 04595 continue; 04596 } 04597 } 04598 s->rows[roffs + 0] = xstrdup(""); 04599 s->rows[roffs + 1] = xstrdup(""); 04600 s->rows[roffs + 2] = xstrdup(ptab); 04601 s->rows[roffs + 3] = xstrdup(rowp[i * ncols + toc]); 04602 s->rows[roffs + 4] = xstrdup(""); 04603 s->rows[roffs + 5] = xstrdup(""); 04604 s->rows[roffs + 6] = xstrdup(fname); 04605 s->rows[roffs + 7] = xstrdup(rowp[i * ncols + fromc]); 04606 sscanf(rowp[i * ncols + seqc], "%d", &pos); 04607 sprintf(buf, "%d", pos + 1); 04608 s->rows[roffs + 8] = xstrdup(buf); 04609 s->rows[roffs + 9] = xstrdup(stringify(SQL_NO_ACTION)); 04610 s->rows[roffs + 10] = xstrdup(stringify(SQL_NO_ACTION)); 04611 s->rows[roffs + 11] = NULL; 04612 s->rows[roffs + 12] = NULL; 04613 s->rows[roffs + 13] = xstrdup(stringify(SQL_NOT_DEFERRABLE)); 04614 offs++; 04615 } 04616 sqlite_free_table(rowp); 04617 } else { 04618 int nnrows, nncols, plen = strlen(pname); 04619 char **rowpp; 04620 04621 ret = sqlite_get_table(d->sqlite, 04622 "select name from sqlite_master " 04623 "where type='table'", &rowp, 04624 &nrows, &ncols, &errp); 04625 if (ret != SQLITE_OK) { 04626 setstat(s, ret, "%s (%d)", (*s->ov3) ? "HY000" : "S1000", 04627 errp ? errp : "unknown error", ret); 04628 if (errp) { 04629 sqlite_freemem(errp); 04630 errp = NULL; 04631 } 04632 return SQL_ERROR; 04633 } 04634 if (errp) { 04635 sqlite_freemem(errp); 04636 errp = NULL; 04637 } 04638 if (ncols * nrows <= 0) { 04639 goto nodata; 04640 } 04641 size = 0; 04642 for (i = 1; i <= nrows; i++) { 04643 int k, len; 04644 04645 if (!rowp[i]) { 04646 continue; 04647 } 04648 len = strlen(rowp[i]); 04649 if (len == plen && strncasecmp(pname, rowp[i], plen) == 0) { 04650 continue; 04651 } 04652 ret = sqlite_get_table_printf(d->sqlite, 04653 "PRAGMA foreign_key_list('%q')", 04654 &rowpp, 04655 &nnrows, &nncols, NULL, rowp[i]); 04656 if (ret != SQLITE_OK || nncols * nnrows <= 0) { 04657 sqlite_free_table(rowpp); 04658 continue; 04659 } 04660 namec = findcol(rowpp, nncols, "table"); 04661 seqc = findcol(rowpp, nncols, "seq"); 04662 fromc = findcol(rowpp, nncols, "from"); 04663 toc = findcol(rowpp, nncols, "to"); 04664 if (namec < 0 || seqc < 0 || fromc < 0 || toc < 0) { 04665 sqlite_free_table(rowpp); 04666 continue; 04667 } 04668 for (k = 1; k <= nnrows; k++) { 04669 char *ptab = rowpp[k * nncols + namec]; 04670 04671 if (plen && ptab) { 04672 len = strlen(ptab); 04673 if (len != plen || strncasecmp(pname, ptab, plen) != 0) { 04674 continue; 04675 } 04676 } 04677 size++; 04678 } 04679 sqlite_free_table(rowpp); 04680 } 04681 if (size == 0) { 04682 goto nodata; 04683 } 04684 s->nrows = size; 04685 size = (size + 1) * array_size(fkeySpec); 04686 s->rows = xmalloc((size + 1) * sizeof (char *)); 04687 if (!s->rows) { 04688 s->nrows = 0; 04689 return nomem(s); 04690 } 04691 s->rows[0] = (char *) size; 04692 s->rows += 1; 04693 memset(s->rows, 0, sizeof (char *) * size); 04694 s->rowfree = freerows; 04695 offs = 0; 04696 for (i = 1; i <= nrows; i++) { 04697 int k, len; 04698 04699 if (!rowp[i]) { 04700 continue; 04701 } 04702 len = strlen(rowp[i]); 04703 if (len == plen && strncasecmp(pname, rowp[i], plen) == 0) { 04704 continue; 04705 } 04706 ret = sqlite_get_table_printf(d->sqlite, 04707 "PRAGMA foreign_key_list('%q')", 04708 &rowpp, 04709 &nnrows, &nncols, NULL, rowp[i]); 04710 if (ret != SQLITE_OK || nncols * nnrows <= 0) { 04711 sqlite_free_table(rowpp); 04712 continue; 04713 } 04714 namec = findcol(rowpp, nncols, "table"); 04715 seqc = findcol(rowpp, nncols, "seq"); 04716 fromc = findcol(rowpp, nncols, "from"); 04717 toc = findcol(rowpp, nncols, "to"); 04718 if (namec < 0 || seqc < 0 || fromc < 0 || toc < 0) { 04719 sqlite_free_table(rowpp); 04720 continue; 04721 } 04722 for (k = 1; k <= nnrows; k++) { 04723 int pos = 0, roffs = (offs + 1) * s->ncols; 04724 char *ptab = rowpp[k * nncols + namec]; 04725 char buf[32]; 04726 04727 if (plen && ptab) { 04728 len = strlen(ptab); 04729 if (len != plen || strncasecmp(pname, ptab, plen) != 0) { 04730 continue; 04731 } 04732 } 04733 s->rows[roffs + 0] = xstrdup(""); 04734 s->rows[roffs + 1] = xstrdup(""); 04735 s->rows[roffs + 2] = xstrdup(ptab); 04736 s->rows[roffs + 3] = xstrdup(rowpp[k * nncols + toc]); 04737 s->rows[roffs + 4] = xstrdup(""); 04738 s->rows[roffs + 5] = xstrdup(""); 04739 s->rows[roffs + 6] = xstrdup(rowp[i]); 04740 s->rows[roffs + 7] = xstrdup(rowpp[k * nncols + fromc]); 04741 sscanf(rowpp[k * nncols + seqc], "%d", &pos); 04742 sprintf(buf, "%d", pos + 1); 04743 s->rows[roffs + 8] = xstrdup(buf); 04744 s->rows[roffs + 9] = xstrdup(stringify(SQL_NO_ACTION)); 04745 s->rows[roffs + 10] = xstrdup(stringify(SQL_NO_ACTION)); 04746 s->rows[roffs + 11] = NULL; 04747 s->rows[roffs + 12] = NULL; 04748 s->rows[roffs + 13] = xstrdup(stringify(SQL_NOT_DEFERRABLE)); 04749 offs++; 04750 } 04751 sqlite_free_table(rowpp); 04752 } 04753 sqlite_free_table(rowp); 04754 } 04755 return SQL_SUCCESS; 04756 } 04757 04758 #ifndef SQLITE_UTF8 04759 04777 SQLRETURN SQL_API 04778 SQLForeignKeys(SQLHSTMT stmt, 04779 SQLCHAR *PKcatalog, SQLSMALLINT PKcatalogLen, 04780 SQLCHAR *PKschema, SQLSMALLINT PKschemaLen, 04781 SQLCHAR *PKtable, SQLSMALLINT PKtableLen, 04782 SQLCHAR *FKcatalog, SQLSMALLINT FKcatalogLen, 04783 SQLCHAR *FKschema, SQLSMALLINT FKschemaLen, 04784 SQLCHAR *FKtable, SQLSMALLINT FKtableLen) 04785 { 04786 return drvforeignkeys(stmt, 04787 PKcatalog, PKcatalogLen, 04788 PKschema, PKschemaLen, PKtable, PKtableLen, 04789 FKcatalog, FKcatalogLen, 04790 FKschema, FKschemaLen, 04791 FKtable, FKtableLen); 04792 } 04793 #endif 04794 04795 #ifdef SQLITE_UTF8 04796 04814 SQLRETURN SQL_API 04815 SQLForeignKeysW(SQLHSTMT stmt, 04816 SQLWCHAR *PKcatalog, SQLSMALLINT PKcatalogLen, 04817 SQLWCHAR *PKschema, SQLSMALLINT PKschemaLen, 04818 SQLWCHAR *PKtable, SQLSMALLINT PKtableLen, 04819 SQLWCHAR *FKcatalog, SQLSMALLINT FKcatalogLen, 04820 SQLWCHAR *FKschema, SQLSMALLINT FKschemaLen, 04821 SQLWCHAR *FKtable, SQLSMALLINT FKtableLen) 04822 { 04823 char *pc = NULL, *ps = NULL, *pt = NULL; 04824 char *fc = NULL, *fs = NULL, *ft = NULL; 04825 SQLRETURN ret; 04826 04827 if (PKcatalog) { 04828 pc = uc_to_utf_c(PKcatalog, PKcatalogLen); 04829 if (!pc) { 04830 ret = nomem((STMT *) stmt); 04831 goto done; 04832 } 04833 } 04834 if (PKschema) { 04835 ps = uc_to_utf_c(PKschema, PKschemaLen); 04836 if (!ps) { 04837 ret = nomem((STMT *) stmt); 04838 goto done; 04839 } 04840 } 04841 if (PKtable) { 04842 pt = uc_to_utf_c(PKtable, PKtableLen); 04843 if (!pt) { 04844 ret = nomem((STMT *) stmt); 04845 goto done; 04846 } 04847 } 04848 if (FKcatalog) { 04849 fc = uc_to_utf_c(FKcatalog, FKcatalogLen); 04850 if (!fc) { 04851 ret = nomem((STMT *) stmt); 04852 goto done; 04853 } 04854 } 04855 if (FKschema) { 04856 fs = uc_to_utf_c(FKschema, FKschemaLen); 04857 if (!fs) { 04858 ret = nomem((STMT *) stmt); 04859 goto done; 04860 } 04861 } 04862 if (FKtable) { 04863 ft = uc_to_utf_c(FKtable, FKtableLen); 04864 if (!ft) { 04865 ret = nomem((STMT *) stmt); 04866 goto done; 04867 } 04868 } 04869 ret = drvforeignkeys(stmt, pc, SQL_NTS, ps, SQL_NTS, pt, SQL_NTS, 04870 fc, SQL_NTS, fs, SQL_NTS, ft, SQL_NTS); 04871 done: 04872 uc_free(ft); 04873 uc_free(fs); 04874 uc_free(fc); 04875 uc_free(pt); 04876 uc_free(ps); 04877 uc_free(pc); 04878 return ret; 04879 } 04880 #endif 04881 04889 static SQLRETURN 04890 endtran(DBC *d, SQLSMALLINT comptype) 04891 { 04892 int fail = 0, ret; 04893 char *sql, *errp = NULL; 04894 04895 if (!d->sqlite) { 04896 setstatd(d, -1, "not connected", (*d->ov3) ? "HY000" : "S1000"); 04897 return SQL_ERROR; 04898 } 04899 if (d->autocommit || !d->intrans) { 04900 return SQL_SUCCESS; 04901 } 04902 switch (comptype) { 04903 case SQL_COMMIT: 04904 sql = "COMMIT TRANSACTION"; 04905 goto doit; 04906 case SQL_ROLLBACK: 04907 rollback: 04908 sql = "ROLLBACK TRANSACTION"; 04909 doit: 04910 d->intrans = 0; 04911 ret = sqlite_exec(d->sqlite, sql, NULL, NULL, &errp); 04912 dbtracerc(d, ret, errp); 04913 if (ret != SQLITE_OK) { 04914 if (!fail) { 04915 setstatd(d, ret, "%s", (*d->ov3) ? "HY000" : "S1000", 04916 errp ? errp : "transaction failed"); 04917 if (errp) { 04918 sqlite_freemem(errp); 04919 errp = NULL; 04920 } 04921 fail = 1; 04922 goto rollback; 04923 } 04924 if (errp) { 04925 sqlite_freemem(errp); 04926 errp = NULL; 04927 } 04928 return SQL_ERROR; 04929 } 04930 if (errp) { 04931 sqlite_freemem(errp); 04932 errp = NULL; 04933 } 04934 return SQL_SUCCESS; 04935 } 04936 setstatd(d, -1, "invalid completion type", (*d->ov3) ? "HY000" : "S1000"); 04937 return SQL_ERROR; 04938 } 04939 04948 static SQLRETURN 04949 drvendtran(SQLSMALLINT type, SQLHANDLE handle, SQLSMALLINT comptype) 04950 { 04951 DBC *d; 04952 int fail = 0; 04953 04954 switch (type) { 04955 case SQL_HANDLE_DBC: 04956 if (handle == SQL_NULL_HDBC) { 04957 return SQL_INVALID_HANDLE; 04958 } 04959 d = (DBC *) handle; 04960 return endtran(d, comptype); 04961 case SQL_HANDLE_ENV: 04962 if (handle == SQL_NULL_HENV) { 04963 return SQL_INVALID_HANDLE; 04964 } 04965 d = ((ENV *) handle)->dbcs; 04966 while (d) { 04967 SQLRETURN ret; 04968 04969 ret = endtran(d, comptype); 04970 if (ret != SQL_SUCCESS) { 04971 fail++; 04972 comptype = SQL_ROLLBACK; 04973 } 04974 d = d->next; 04975 } 04976 return fail ? SQL_ERROR : SQL_SUCCESS; 04977 } 04978 return SQL_INVALID_HANDLE; 04979 } 04980 04989 SQLRETURN SQL_API 04990 SQLEndTran(SQLSMALLINT type, SQLHANDLE handle, SQLSMALLINT comptype) 04991 { 04992 return drvendtran(type, handle, comptype); 04993 } 04994 05003 SQLRETURN SQL_API 05004 SQLTransact(SQLHENV env, SQLHDBC dbc, UWORD type) 05005 { 05006 if (env != SQL_NULL_HENV) { 05007 return drvendtran(SQL_HANDLE_ENV, (SQLHANDLE) env, type); 05008 } 05009 return drvendtran(SQL_HANDLE_DBC, (SQLHANDLE) dbc, type); 05010 } 05011 05016 SQLRETURN SQL_API 05017 SQLCopyDesc(SQLHDESC source, SQLHDESC target) 05018 { 05019 return SQL_ERROR; 05020 } 05021 05022 #ifndef SQLITE_UTF8 05023 05034 SQLRETURN SQL_API 05035 SQLNativeSql(SQLHSTMT stmt, SQLCHAR *sqlin, SQLINTEGER sqlinLen, 05036 SQLCHAR *sql, SQLINTEGER sqlMax, SQLINTEGER *sqlLen) 05037 { 05038 int outLen = 0; 05039 05040 if (sqlinLen == SQL_NTS) { 05041 sqlinLen = strlen(sqlin); 05042 } 05043 if (sql) { 05044 if (sqlMax > 0) { 05045 strncpy(sql, sqlin, sqlMax - 1); 05046 sqlin[sqlMax - 1] = '\0'; 05047 outLen = min(sqlMax - 1, sqlinLen); 05048 } 05049 } else { 05050 outLen = sqlinLen; 05051 } 05052 if (sqlLen) { 05053 *sqlLen = outLen; 05054 } 05055 if (sql && outLen < sqlinLen) { 05056 setstat((STMT *) stmt, -1, "data right truncated", "01004"); 05057 return SQL_SUCCESS_WITH_INFO; 05058 } 05059 return SQL_SUCCESS; 05060 } 05061 #endif 05062 05063 #ifdef SQLITE_UTF8 05064 05075 SQLRETURN SQL_API 05076 SQLNativeSqlW(SQLHSTMT stmt, SQLWCHAR *sqlin, SQLINTEGER sqlinLen, 05077 SQLWCHAR *sql, SQLINTEGER sqlMax, SQLINTEGER *sqlLen) 05078 { 05079 int outLen = 0; 05080 05081 if (sqlinLen == SQL_NTS) { 05082 sqlinLen = uc_strlen(sqlin); 05083 } 05084 if (sql) { 05085 if (sqlMax > 0) { 05086 uc_strncpy(sql, sqlin, sqlMax - 1); 05087 sqlin[sqlMax - 1] = 0; 05088 outLen = min(sqlMax - 1, sqlinLen); 05089 } 05090 } else { 05091 outLen = sqlinLen; 05092 } 05093 if (sqlLen) { 05094 *sqlLen = outLen; 05095 } 05096 if (sql && outLen < sqlinLen) { 05097 setstat((STMT *) stmt, -1, "data right truncated", "01004"); 05098 return SQL_SUCCESS_WITH_INFO; 05099 } 05100 return SQL_SUCCESS; 05101 } 05102 #endif 05103 05108 static COL procSpec[] = { 05109 { "SYSTEM", "PROCEDURE", "PROCEDURE_QUALIFIER", SCOL_VARCHAR, 50 }, 05110 { "SYSTEM", "PROCEDURE", "PROCEDURE_OWNER", SCOL_VARCHAR, 50 }, 05111 { "SYSTEM", "PROCEDURE", "PROCEDURE_NAME", SCOL_VARCHAR, 255 }, 05112 { "SYSTEM", "PROCEDURE", "NUM_INPUT_PARAMS", SQL_SMALLINT, 5 }, 05113 { "SYSTEM", "PROCEDURE", "NUM_OUTPUT_PARAMS", SQL_SMALLINT, 5 }, 05114 { "SYSTEM", "PROCEDURE", "NUM_RESULT_SETS", SQL_SMALLINT, 5 }, 05115 { "SYSTEM", "PROCEDURE", "REMARKS", SCOL_VARCHAR, 255 }, 05116 { "SYSTEM", "PROCEDURE", "PROCEDURE_TYPE", SQL_SMALLINT, 5 } 05117 }; 05118 05119 #ifndef SQLITE_UTF8 05120 05132 SQLRETURN SQL_API 05133 SQLProcedures(SQLHSTMT stmt, 05134 SQLCHAR *catalog, SQLSMALLINT catalogLen, 05135 SQLCHAR *schema, SQLSMALLINT schemaLen, 05136 SQLCHAR *proc, SQLSMALLINT procLen) 05137 { 05138 return mkresultset(stmt, procSpec, array_size(procSpec)); 05139 } 05140 #endif 05141 05142 #ifdef SQLITE_UTF8 05143 05155 SQLRETURN SQL_API 05156 SQLProceduresW(SQLHSTMT stmt, 05157 SQLWCHAR *catalog, SQLSMALLINT catalogLen, 05158 SQLWCHAR *schema, SQLSMALLINT schemaLen, 05159 SQLWCHAR *proc, SQLSMALLINT procLen) 05160 { 05161 return mkresultset(stmt, procSpec, array_size(procSpec)); 05162 } 05163 #endif 05164 05169 static COL procColSpec[] = { 05170 { "SYSTEM", "PROCCOL", "PROCEDURE_QUALIFIER", SCOL_VARCHAR, 50 }, 05171 { "SYSTEM", "PROCCOL", "PROCEDURE_OWNER", SCOL_VARCHAR, 50 }, 05172 { "SYSTEM", "PROCCOL", "PROCEDURE_NAME", SCOL_VARCHAR, 255 }, 05173 { "SYSTEM", "PROCCOL", "COLUMN_NAME", SCOL_VARCHAR, 255 }, 05174 { "SYSTEM", "PROCCOL", "COLUMN_TYPE", SQL_SMALLINT, 5 }, 05175 { "SYSTEM", "PROCCOL", "DATA_TYPE", SQL_SMALLINT, 5 }, 05176 { "SYSTEM", "PROCCOL", "TYPE_NAME", SCOL_VARCHAR, 50 }, 05177 { "SYSTEM", "PROCCOL", "PRECISION", SQL_INTEGER, 10 }, 05178 { "SYSTEM", "PROCCOL", "LENGTH", SQL_INTEGER, 10 }, 05179 { "SYSTEM", "PROCCOL", "RADIX", SQL_SMALLINT, 5 }, 05180 { "SYSTEM", "PROCCOL", "SCALE", SQL_SMALLINT, 5 }, 05181 { "SYSTEM", "PROCCOL", "NULLABLE", SQL_SMALLINT, 5 }, 05182 { "SYSTEM", "PROCCOL", "REMARKS", SCOL_VARCHAR, 50 }, 05183 { "SYSTEM", "PROCCOL", "COLUMN_DEF", SCOL_VARCHAR, 50 }, 05184 { "SYSTEM", "PROCCOL", "SQL_DATA_TYPE", SQL_SMALLINT, 5 }, 05185 { "SYSTEM", "PROCCOL", "SQL_DATETIME_SUB", SQL_SMALLINT, 5 }, 05186 { "SYSTEM", "PROCCOL", "CHAR_OCTET_LENGTH", SQL_SMALLINT, 5 }, 05187 { "SYSTEM", "PROCCOL", "ORDINAL_POSITION", SQL_SMALLINT, 5 }, 05188 { "SYSTEM", "PROCCOL", "IS_NULLABLE", SCOL_VARCHAR, 50 } 05189 }; 05190 05191 #ifndef SQLITE_UTF8 05192 05206 SQLRETURN SQL_API 05207 SQLProcedureColumns(SQLHSTMT stmt, 05208 SQLCHAR *catalog, SQLSMALLINT catalogLen, 05209 SQLCHAR *schema, SQLSMALLINT schemaLen, 05210 SQLCHAR *proc, SQLSMALLINT procLen, 05211 SQLCHAR *column, SQLSMALLINT columnLen) 05212 { 05213 return mkresultset(stmt, procColSpec, array_size(procColSpec)); 05214 05215 } 05216 #endif 05217 05218 #ifdef SQLITE_UTF8 05219 05234 SQLRETURN SQL_API 05235 SQLProcedureColumnsW(SQLHSTMT stmt, 05236 SQLWCHAR *catalog, SQLSMALLINT catalogLen, 05237 SQLWCHAR *schema, SQLSMALLINT schemaLen, 05238 SQLWCHAR *proc, SQLSMALLINT procLen, 05239 SQLWCHAR *column, SQLSMALLINT columnLen) 05240 { 05241 return mkresultset(stmt, procColSpec, array_size(procColSpec)); 05242 } 05243 #endif 05244 05255 SQLRETURN SQL_API 05256 SQLGetEnvAttr(SQLHENV env, SQLINTEGER attr, SQLPOINTER val, 05257 SQLINTEGER len, SQLINTEGER *lenp) 05258 { 05259 ENV *e; 05260 05261 if (env == SQL_NULL_HENV) { 05262 return SQL_INVALID_HANDLE; 05263 } 05264 e = (ENV *) env; 05265 if (!e || e->magic != ENV_MAGIC) { 05266 return SQL_INVALID_HANDLE; 05267 } 05268 switch (attr) { 05269 case SQL_ATTR_CONNECTION_POOLING: 05270 return SQL_ERROR; 05271 case SQL_ATTR_CP_MATCH: 05272 return SQL_NO_DATA; 05273 case SQL_ATTR_OUTPUT_NTS: 05274 if (val) { 05275 *((SQLINTEGER *) val) = SQL_TRUE; 05276 } 05277 if (lenp) { 05278 *lenp = sizeof (SQLINTEGER); 05279 } 05280 return SQL_SUCCESS; 05281 case SQL_ATTR_ODBC_VERSION: 05282 if (val) { 05283 *((SQLINTEGER *) val) = e->ov3 ? SQL_OV_ODBC3 : SQL_OV_ODBC2; 05284 } 05285 if (lenp) { 05286 *lenp = sizeof (SQLINTEGER); 05287 } 05288 return SQL_SUCCESS; 05289 } 05290 return SQL_ERROR; 05291 } 05292 05302 SQLRETURN SQL_API 05303 SQLSetEnvAttr(SQLHENV env, SQLINTEGER attr, SQLPOINTER val, SQLINTEGER len) 05304 { 05305 ENV *e; 05306 05307 if (env == SQL_NULL_HENV) { 05308 return SQL_INVALID_HANDLE; 05309 } 05310 e = (ENV *) env; 05311 if (!e || e->magic != ENV_MAGIC) { 05312 return SQL_INVALID_HANDLE; 05313 } 05314 switch (attr) { 05315 case SQL_ATTR_CONNECTION_POOLING: 05316 return SQL_SUCCESS; 05317 case SQL_ATTR_CP_MATCH: 05318 return SQL_NO_DATA; 05319 case SQL_ATTR_OUTPUT_NTS: 05320 if ((SQLINTEGER) val == SQL_TRUE) { 05321 return SQL_SUCCESS; 05322 } 05323 return SQL_ERROR; 05324 case SQL_ATTR_ODBC_VERSION: 05325 if (!val) { 05326 return SQL_ERROR; 05327 } 05328 if ((SQLINTEGER) val == SQL_OV_ODBC2) { 05329 e->ov3 = 0; 05330 return SQL_SUCCESS; 05331 } 05332 if ((SQLINTEGER) val == SQL_OV_ODBC3) { 05333 e->ov3 = 1; 05334 return SQL_SUCCESS; 05335 } 05336 return SQL_ERROR; 05337 } 05338 return SQL_ERROR; 05339 } 05340 05354 static SQLRETURN 05355 drvgetdiagrec(SQLSMALLINT htype, SQLHANDLE handle, SQLSMALLINT recno, 05356 SQLCHAR *sqlstate, SQLINTEGER *nativeerr, SQLCHAR *msg, 05357 SQLSMALLINT buflen, SQLSMALLINT *msglen) 05358 { 05359 DBC *d = NULL; 05360 STMT *s = NULL; 05361 int len, naterr; 05362 char *logmsg, *sqlst; 05363 05364 if (handle == SQL_NULL_HANDLE) { 05365 return SQL_INVALID_HANDLE; 05366 } 05367 if (sqlstate) { 05368 sqlstate[0] = '\0'; 05369 } 05370 if (msg && buflen > 0) { 05371 msg[0] = '\0'; 05372 } 05373 if (msglen) { 05374 *msglen = 0; 05375 } 05376 if (nativeerr) { 05377 *nativeerr = 0; 05378 } 05379 switch (htype) { 05380 case SQL_HANDLE_ENV: 05381 case SQL_HANDLE_DESC: 05382 return SQL_NO_DATA; 05383 case SQL_HANDLE_DBC: 05384 d = (DBC *) handle; 05385 logmsg = d->logmsg; 05386 sqlst = d->sqlstate; 05387 naterr = d->naterr; 05388 break; 05389 case SQL_HANDLE_STMT: 05390 s = (STMT *) handle; 05391 logmsg = s->logmsg; 05392 sqlst = s->sqlstate; 05393 naterr = s->naterr; 05394 break; 05395 default: 05396 return SQL_INVALID_HANDLE; 05397 } 05398 if (buflen < 0) { 05399 return SQL_ERROR; 05400 } 05401 if (recno > 1) { 05402 return SQL_NO_DATA; 05403 } 05404 len = strlen(logmsg); 05405 if (len == 0) { 05406 return SQL_NO_DATA; 05407 } 05408 if (nativeerr) { 05409 *nativeerr = naterr; 05410 } 05411 if (sqlstate) { 05412 strcpy(sqlstate, sqlst); 05413 } 05414 if (msglen) { 05415 *msglen = len; 05416 } 05417 if (len >= buflen) { 05418 if (msg && buflen > 0) { 05419 strncpy(msg, logmsg, buflen); 05420 msg[buflen - 1] = '\0'; 05421 logmsg[0] = '\0'; 05422 } 05423 } else if (msg) { 05424 strcpy(msg, logmsg); 05425 logmsg[0] = '\0'; 05426 } 05427 return SQL_SUCCESS; 05428 } 05429 05430 #ifndef SQLITE_UTF8 05431 05444 SQLRETURN SQL_API 05445 SQLGetDiagRec(SQLSMALLINT htype, SQLHANDLE handle, SQLSMALLINT recno, 05446 SQLCHAR *sqlstate, SQLINTEGER *nativeerr, SQLCHAR *msg, 05447 SQLSMALLINT buflen, SQLSMALLINT *msglen) 05448 { 05449 return drvgetdiagrec(htype, handle, recno, sqlstate, 05450 nativeerr, msg, buflen, msglen); 05451 } 05452 #endif 05453 05454 #if !defined(HAVE_UNIXODBC) || !HAVE_UNIXODBC 05455 #ifdef SQLITE_UTF8 05456 05470 SQLRETURN SQL_API 05471 SQLGetDiagRecW(SQLSMALLINT htype, SQLHANDLE handle, SQLSMALLINT recno, 05472 SQLWCHAR *sqlstate, SQLINTEGER *nativeerr, SQLWCHAR *msg, 05473 SQLSMALLINT buflen, SQLSMALLINT *msglen) 05474 { 05475 char state[16]; 05476 SQLSMALLINT len; 05477 SQLRETURN ret; 05478 05479 ret = drvgetdiagrec(htype, handle, recno, state, 05480 nativeerr, (char *) msg, buflen, &len); 05481 if (ret == SQL_SUCCESS) { 05482 if (sqlstate) { 05483 uc_from_utf_buf(state, sqlstate, 6 * sizeof (SQLWCHAR)); 05484 } 05485 if (msg) { 05486 if (len > 0) { 05487 SQLWCHAR *m = NULL; 05488 05489 m = uc_from_utf((char *) msg, len); 05490 if (m) { 05491 if (buflen) { 05492 uc_strncpy(msg, m, buflen); 05493 len = min(buflen, uc_strlen(m)); 05494 } else { 05495 len = uc_strlen(m); 05496 } 05497 uc_free(m); 05498 } else { 05499 len = 0; 05500 } 05501 } 05502 if (len <= 0) { 05503 len = 0; 05504 if (buflen > 0) { 05505 msg[0] = 0; 05506 } 05507 } 05508 } else { 05509 len = 0; 05510 } 05511 if (msglen) { 05512 *msglen = len; 05513 } 05514 } else if (ret == SQL_NO_DATA) { 05515 if (sqlstate) { 05516 sqlstate[0] = 0; 05517 } 05518 if (msg) { 05519 if (buflen > 0) { 05520 msg[0] = 0; 05521 } 05522 } 05523 if (msglen) { 05524 *msglen = 0; 05525 } 05526 } 05527 return ret; 05528 } 05529 #endif 05530 #endif 05531 05532 #ifndef SQLITE_UTF8 05533 05537 SQLRETURN SQL_API 05538 SQLGetDiagField(SQLSMALLINT htype, SQLHANDLE handle, SQLSMALLINT recno, 05539 SQLSMALLINT id, SQLPOINTER info, 05540 SQLSMALLINT buflen, SQLSMALLINT *strlen) 05541 { 05542 return SQL_ERROR; 05543 } 05544 #endif 05545 05546 #ifdef SQLITE_UTF8 05547 05551 SQLRETURN SQL_API 05552 SQLGetDiagFieldW(SQLSMALLINT htype, SQLHANDLE handle, SQLSMALLINT recno, 05553 SQLSMALLINT id, SQLPOINTER info, 05554 SQLSMALLINT buflen, SQLSMALLINT *strlen) 05555 { 05556 return SQL_ERROR; 05557 } 05558 #endif 05559 05570 static SQLRETURN 05571 drvgetstmtattr(SQLHSTMT stmt, SQLINTEGER attr, SQLPOINTER val, 05572 SQLINTEGER bufmax, SQLINTEGER *buflen) 05573 { 05574 STMT *s = (STMT *) stmt; 05575 SQLUINTEGER *uval = (SQLUINTEGER *) val; 05576 05577 switch (attr) { 05578 case SQL_ATTR_CURSOR_TYPE: 05579 *uval = s->curtype; 05580 return SQL_SUCCESS; 05581 case SQL_ATTR_CURSOR_SCROLLABLE: 05582 *uval = s->curtype != SQL_CURSOR_FORWARD_ONLY ? 05583 SQL_SCROLLABLE : SQL_NONSCROLLABLE; 05584 return SQL_SUCCESS; 05585 #ifdef SQL_ATTR_CURSOR_SENSITIVITY 05586 case SQL_ATTR_CURSOR_SENSITIVITY: 05587 *uval = SQL_UNSPECIFIED; 05588 return SQL_SUCCESS; 05589 #endif 05590 case SQL_ATTR_ROW_NUMBER: 05591 { 05592 STMT *s = (STMT *) stmt; 05593 DBC *d = (DBC *) s->dbc; 05594 05595 if (s == d->vm_stmt) { 05596 *uval = d->vm_rownum < 0 ? 05597 SQL_ROW_NUMBER_UNKNOWN : d->vm_rownum; 05598 } 05599 } 05600 *uval = s->rowp < 0 ? SQL_ROW_NUMBER_UNKNOWN : s->rowp; 05601 return SQL_SUCCESS; 05602 case SQL_ATTR_ASYNC_ENABLE: 05603 *uval = SQL_ASYNC_ENABLE_OFF; 05604 return SQL_SUCCESS; 05605 case SQL_CONCURRENCY: 05606 *uval = SQL_CONCUR_LOCK; 05607 return SQL_SUCCESS; 05608 case SQL_ATTR_RETRIEVE_DATA: 05609 *uval = SQL_RD_ON; 05610 return SQL_SUCCESS; 05611 case SQL_ROWSET_SIZE: 05612 case SQL_ATTR_ROW_ARRAY_SIZE: 05613 *uval = s->rowset_size; 05614 return SQL_SUCCESS; 05615 /* Needed for some driver managers, but dummies for now */ 05616 case SQL_ATTR_IMP_ROW_DESC: 05617 case SQL_ATTR_APP_ROW_DESC: 05618 case SQL_ATTR_IMP_PARAM_DESC: 05619 case SQL_ATTR_APP_PARAM_DESC: 05620 *((SQLHDESC *) val) = (SQLHDESC) DEAD_MAGIC; 05621 return SQL_SUCCESS; 05622 case SQL_ATTR_ROW_STATUS_PTR: 05623 *((SQLUSMALLINT **) val) = s->row_status; 05624 return SQL_SUCCESS; 05625 case SQL_ATTR_ROWS_FETCHED_PTR: 05626 *((SQLUINTEGER **) val) = s->row_count; 05627 return SQL_SUCCESS; 05628 case SQL_ATTR_USE_BOOKMARKS: { 05629 STMT *s = (STMT *) stmt; 05630 05631 *(SQLUINTEGER *) val = s->bkmrk ? SQL_UB_ON : SQL_UB_OFF; 05632 return SQL_SUCCESS; 05633 } 05634 case SQL_ATTR_PARAM_BIND_OFFSET_PTR: 05635 *((SQLUINTEGER **) val) = s->bind_offs; 05636 return SQL_SUCCESS; 05637 case SQL_ATTR_PARAM_BIND_TYPE: 05638 *((SQLUINTEGER *) val) = SQL_PARAM_BIND_BY_COLUMN; 05639 return SQL_SUCCESS; 05640 case SQL_ATTR_PARAM_OPERATION_PTR: 05641 *((SQLUSMALLINT **) val) = s->parm_oper; 05642 return SQL_SUCCESS; 05643 case SQL_ATTR_PARAM_STATUS_PTR: 05644 *((SQLUSMALLINT **) val) = s->parm_status; 05645 return SQL_SUCCESS; 05646 case SQL_ATTR_PARAMS_PROCESSED_PTR: 05647 *((SQLUINTEGER **) val) = s->parm_proc; 05648 return SQL_SUCCESS; 05649 case SQL_ATTR_PARAMSET_SIZE: 05650 *((SQLUINTEGER *) val) = s->paramset_size; 05651 return SQL_SUCCESS; 05652 case SQL_ATTR_ROW_BIND_TYPE: 05653 *(SQLUINTEGER *) val = s->bind_type; 05654 return SQL_SUCCESS; 05655 } 05656 return drvunimplstmt(stmt); 05657 } 05658 05659 #if (defined(HAVE_UNIXODBC) && HAVE_UNIXODBC) || !defined(SQLITE_UTF8) 05660 05670 SQLRETURN SQL_API 05671 SQLGetStmtAttr(SQLHSTMT stmt, SQLINTEGER attr, SQLPOINTER val, 05672 SQLINTEGER bufmax, SQLINTEGER *buflen) 05673 { 05674 return drvgetstmtattr(stmt, attr, val, bufmax, buflen); 05675 } 05676 #endif 05677 05678 #ifdef SQLITE_UTF8 05679 05689 SQLRETURN SQL_API 05690 SQLGetStmtAttrW(SQLHSTMT stmt, SQLINTEGER attr, SQLPOINTER val, 05691 SQLINTEGER bufmax, SQLINTEGER *buflen) 05692 { 05693 return drvgetstmtattr(stmt, attr, val, bufmax, buflen); 05694 } 05695 #endif 05696 05706 static SQLRETURN 05707 drvsetstmtattr(SQLHSTMT stmt, SQLINTEGER attr, SQLPOINTER val, 05708 SQLINTEGER buflen) 05709 { 05710 STMT *s = (STMT *) stmt; 05711 05712 switch (attr) { 05713 case SQL_ATTR_CURSOR_TYPE: 05714 if ((SQLUINTEGER) val == SQL_CURSOR_FORWARD_ONLY) { 05715 s->curtype = SQL_CURSOR_FORWARD_ONLY; 05716 } else { 05717 s->curtype = SQL_CURSOR_STATIC; 05718 } 05719 if ((SQLUINTEGER) val != SQL_CURSOR_FORWARD_ONLY && 05720 (SQLUINTEGER) val != SQL_CURSOR_STATIC) { 05721 goto e01s02; 05722 } 05723 return SQL_SUCCESS; 05724 case SQL_ATTR_CURSOR_SCROLLABLE: 05725 if ((SQLUINTEGER) val == SQL_NONSCROLLABLE) { 05726 s->curtype = SQL_CURSOR_FORWARD_ONLY; 05727 } else { 05728 s->curtype = SQL_CURSOR_STATIC; 05729 } 05730 return SQL_SUCCESS; 05731 case SQL_ATTR_ASYNC_ENABLE: 05732 if ((SQLUINTEGER) val != SQL_ASYNC_ENABLE_OFF) { 05733 e01s02: 05734 setstat(s, -1, "option value changed", "01S02"); 05735 return SQL_SUCCESS_WITH_INFO; 05736 } 05737 return SQL_SUCCESS; 05738 case SQL_CONCURRENCY: 05739 if ((SQLUINTEGER) val != SQL_CONCUR_LOCK) { 05740 goto e01s02; 05741 } 05742 return SQL_SUCCESS; 05743 case SQL_ATTR_QUERY_TIMEOUT: 05744 return SQL_SUCCESS; 05745 case SQL_ATTR_RETRIEVE_DATA: 05746 if ((SQLUINTEGER) val != SQL_RD_ON && 05747 (SQLUINTEGER) val != SQL_RD_OFF) { 05748 goto e01s02; 05749 } 05750 return SQL_SUCCESS; 05751 case SQL_ROWSET_SIZE: 05752 case SQL_ATTR_ROW_ARRAY_SIZE: 05753 if ((SQLUINTEGER) val < 1) { 05754 setstat(s, -1, "invalid rowset size", "HY000"); 05755 return SQL_ERROR; 05756 } else { 05757 SQLUSMALLINT *rst = &s->row_status1; 05758 05759 if ((SQLUINTEGER) val > 1) { 05760 rst = xmalloc(sizeof (SQLUSMALLINT) * (SQLUINTEGER) val); 05761 if (!rst) { 05762 return nomem(s); 05763 } 05764 } 05765 if (s->row_status0 != &s->row_status1) { 05766 freep(&s->row_status0); 05767 } 05768 s->row_status0 = rst; 05769 s->rowset_size = (SQLUINTEGER) val; 05770 } 05771 return SQL_SUCCESS; 05772 case SQL_ATTR_ROW_STATUS_PTR: 05773 s->row_status = (SQLUSMALLINT *) val; 05774 return SQL_SUCCESS; 05775 case SQL_ATTR_ROWS_FETCHED_PTR: 05776 s->row_count = (SQLUINTEGER *) val; 05777 return SQL_SUCCESS; 05778 case SQL_ATTR_PARAM_BIND_OFFSET_PTR: 05779 s->bind_offs = (SQLUINTEGER *) val; 05780 return SQL_SUCCESS; 05781 case SQL_ATTR_PARAM_BIND_TYPE: 05782 if ((SQLUINTEGER) val != SQL_PARAM_BIND_BY_COLUMN) { 05783 goto e01s02; 05784 } 05785 return SQL_SUCCESS; 05786 case SQL_ATTR_PARAM_OPERATION_PTR: 05787 s->parm_oper = (SQLUSMALLINT *) val; 05788 return SQL_SUCCESS; 05789 case SQL_ATTR_PARAM_STATUS_PTR: 05790 s->parm_status = (SQLUSMALLINT *) val; 05791 return SQL_SUCCESS; 05792 case SQL_ATTR_PARAMS_PROCESSED_PTR: 05793 s->parm_proc = (SQLUINTEGER *) val; 05794 return SQL_SUCCESS; 05795 case SQL_ATTR_PARAMSET_SIZE: 05796 if ((SQLUINTEGER) val < 1) { 05797 goto e01s02; 05798 } 05799 s->paramset_size = (SQLUINTEGER) val; 05800 s->paramset_count = 0; 05801 return SQL_SUCCESS; 05802 case SQL_ATTR_ROW_BIND_TYPE: 05803 s->bind_type = (SQLUINTEGER) val; 05804 return SQL_SUCCESS; 05805 case SQL_ATTR_USE_BOOKMARKS: 05806 if ((SQLUINTEGER) val != SQL_UB_OFF && 05807 (SQLUINTEGER) val != SQL_UB_ON) { 05808 goto e01s02; 05809 } 05810 s->bkmrk = (SQLUINTEGER) val == SQL_UB_ON; 05811 return SQL_SUCCESS; 05812 } 05813 return drvunimplstmt(stmt); 05814 } 05815 05816 #if (defined(HAVE_UNIXODBC) && HAVE_UNIXODBC) || !defined(SQLITE_UTF8) 05817 05826 SQLRETURN SQL_API 05827 SQLSetStmtAttr(SQLHSTMT stmt, SQLINTEGER attr, SQLPOINTER val, 05828 SQLINTEGER buflen) 05829 { 05830 return drvsetstmtattr(stmt, attr, val, buflen); 05831 } 05832 #endif 05833 05834 #ifdef SQLITE_UTF8 05835 05844 SQLRETURN SQL_API 05845 SQLSetStmtAttrW(SQLHSTMT stmt, SQLINTEGER attr, SQLPOINTER val, 05846 SQLINTEGER buflen) 05847 { 05848 return drvsetstmtattr(stmt, attr, val, buflen); 05849 } 05850 #endif 05851 05860 static SQLRETURN 05861 drvgetstmtoption(SQLHSTMT stmt, SQLUSMALLINT opt, SQLPOINTER param) 05862 { 05863 STMT *s = (STMT *) stmt; 05864 SQLUINTEGER *ret = (SQLUINTEGER *) param; 05865 05866 switch (opt) { 05867 case SQL_CURSOR_TYPE: 05868 *ret = s->curtype; 05869 return SQL_SUCCESS; 05870 case SQL_ROW_NUMBER: 05871 { 05872 DBC *d = (DBC *) s->dbc; 05873 05874 if (s == d->vm_stmt) { 05875 *ret = d->vm_rownum < 0 ? 05876 SQL_ROW_NUMBER_UNKNOWN : d->vm_rownum; 05877 } 05878 } 05879 *ret = s->rowp < 0 ? SQL_ROW_NUMBER_UNKNOWN : s->rowp; 05880 return SQL_SUCCESS; 05881 case SQL_ASYNC_ENABLE: 05882 *ret = SQL_ASYNC_ENABLE_OFF; 05883 return SQL_SUCCESS; 05884 case SQL_CONCURRENCY: 05885 *ret = SQL_CONCUR_LOCK; 05886 return SQL_SUCCESS; 05887 case SQL_ATTR_RETRIEVE_DATA: 05888 *ret = SQL_RD_ON; 05889 return SQL_SUCCESS; 05890 case SQL_ROWSET_SIZE: 05891 case SQL_ATTR_ROW_ARRAY_SIZE: 05892 *ret = s->rowset_size; 05893 return SQL_SUCCESS; 05894 } 05895 return drvunimplstmt(stmt); 05896 } 05897 05906 SQLRETURN SQL_API 05907 SQLGetStmtOption(SQLHSTMT stmt, SQLUSMALLINT opt, SQLPOINTER param) 05908 { 05909 return drvgetstmtoption(stmt, opt, param); 05910 } 05911 05912 #ifdef SQLITE_UTF8 05913 05921 SQLRETURN SQL_API 05922 SQLGetStmtOptionW(SQLHSTMT stmt, SQLUSMALLINT opt, SQLPOINTER param) 05923 { 05924 return drvgetstmtoption(stmt, opt, param); 05925 } 05926 #endif 05927 05936 static SQLRETURN 05937 drvsetstmtoption(SQLHSTMT stmt, SQLUSMALLINT opt, SQLUINTEGER param) 05938 { 05939 STMT *s = (STMT *) stmt; 05940 05941 switch (opt) { 05942 case SQL_CURSOR_TYPE: 05943 if (param == SQL_CURSOR_FORWARD_ONLY) { 05944 s->curtype = param; 05945 } else { 05946 s->curtype = SQL_CURSOR_STATIC; 05947 } 05948 if (param != SQL_CURSOR_FORWARD_ONLY && 05949 param != SQL_CURSOR_STATIC) { 05950 goto e01s02; 05951 } 05952 return SQL_SUCCESS; 05953 case SQL_ASYNC_ENABLE: 05954 if (param != SQL_ASYNC_ENABLE_OFF) { 05955 goto e01s02; 05956 } 05957 return SQL_SUCCESS; 05958 case SQL_CONCURRENCY: 05959 if (param != SQL_CONCUR_LOCK) { 05960 goto e01s02; 05961 } 05962 return SQL_SUCCESS; 05963 case SQL_QUERY_TIMEOUT: 05964 return SQL_SUCCESS; 05965 case SQL_RETRIEVE_DATA: 05966 if (param != SQL_RD_ON && param != SQL_RD_OFF) { 05967 e01s02: 05968 setstat(s, -1, "option value changed", "01S02"); 05969 return SQL_SUCCESS_WITH_INFO; 05970 } 05971 return SQL_SUCCESS; 05972 case SQL_ROWSET_SIZE: 05973 case SQL_ATTR_ROW_ARRAY_SIZE: 05974 if (param < 1) { 05975 setstat(s, -1, "invalid rowset size", "HY000"); 05976 return SQL_ERROR; 05977 } else { 05978 SQLUSMALLINT *rst = &s->row_status1; 05979 05980 if (param > 1) { 05981 rst = xmalloc(sizeof (SQLUSMALLINT) * param); 05982 if (!rst) { 05983 return nomem(s); 05984 } 05985 } 05986 if (s->row_status0 != &s->row_status1) { 05987 freep(&s->row_status0); 05988 } 05989 s->row_status0 = rst; 05990 s->rowset_size = param; 05991 } 05992 return SQL_SUCCESS; 05993 } 05994 return drvunimplstmt(stmt); 05995 } 05996 06005 SQLRETURN SQL_API 06006 SQLSetStmtOption(SQLHSTMT stmt, SQLUSMALLINT opt, SQLUINTEGER param) 06007 { 06008 return drvsetstmtoption(stmt, opt, param); 06009 } 06010 06011 #ifdef SQLITE_UTF8 06012 06020 SQLRETURN SQL_API 06021 SQLSetStmtOptionW(SQLHSTMT stmt, SQLUSMALLINT opt, SQLUINTEGER param) 06022 { 06023 return drvsetstmtoption(stmt, opt, param); 06024 } 06025 #endif 06026 06031 SQLRETURN SQL_API 06032 SQLSetPos(SQLHSTMT stmt, SQLUSMALLINT row, SQLUSMALLINT op, SQLUSMALLINT lock) 06033 { 06034 return drvunimplstmt(stmt); 06035 } 06036 06041 SQLRETURN SQL_API 06042 SQLSetScrollOptions(SQLHSTMT stmt, SQLUSMALLINT concur, SQLINTEGER rowkeyset, 06043 SQLUSMALLINT rowset) 06044 { 06045 return drvunimplstmt(stmt); 06046 } 06047 06048 #define strmak(dst, src, max, lenp) { \ 06049 int len = strlen(src); \ 06050 int cnt = min(len + 1, max); \ 06051 strncpy(dst, src, cnt); \ 06052 *lenp = (cnt > len) ? len : cnt; \ 06053 } 06054 06065 static SQLRETURN 06066 drvgetinfo(SQLHDBC dbc, SQLUSMALLINT type, SQLPOINTER val, SQLSMALLINT valMax, 06067 SQLSMALLINT *valLen) 06068 { 06069 DBC *d; 06070 char dummyc[16]; 06071 SQLSMALLINT dummy; 06072 static char drvname[] = 06073 #ifdef _WIN32 06074 "sqliteodbc.dll"; 06075 #else 06076 "sqliteodbc.so"; 06077 #endif 06078 06079 if (dbc == SQL_NULL_HDBC) { 06080 return SQL_INVALID_HANDLE; 06081 } 06082 d = (DBC *) dbc; 06083 if (valMax) { 06084 valMax--; 06085 } 06086 if (!valLen) { 06087 valLen = &dummy; 06088 } 06089 if (!val) { 06090 val = dummyc; 06091 valMax = sizeof (dummyc) - 1; 06092 } 06093 switch (type) { 06094 case SQL_MAX_USER_NAME_LEN: 06095 *((SQLSMALLINT *) val) = 16; 06096 *valLen = sizeof (SQLSMALLINT); 06097 break; 06098 case SQL_USER_NAME: 06099 strmak(val, "", valMax, valLen); 06100 break; 06101 case SQL_DRIVER_ODBC_VER: 06102 #if 0 06103 strmak(val, (*d->ov3) ? "03.00" : "02.50", valMax, valLen); 06104 #else 06105 strmak(val, "03.00", valMax, valLen); 06106 #endif 06107 break; 06108 case SQL_ACTIVE_CONNECTIONS: 06109 case SQL_ACTIVE_STATEMENTS: 06110 *((SQLSMALLINT *) val) = 0; 06111 *valLen = sizeof (SQLSMALLINT); 06112 break; 06113 #ifdef SQL_ASYNC_MODE 06114 case SQL_ASYNC_MODE: 06115 *((SQLUINTEGER *) val) = SQL_AM_NONE; 06116 *valLen = sizeof (SQLUINTEGER); 06117 break; 06118 #endif 06119 #ifdef SQL_CREATE_TABLE 06120 case SQL_CREATE_TABLE: 06121 *((SQLUINTEGER *) val) = 0; 06122 *valLen = sizeof (SQLUINTEGER); 06123 break; 06124 #endif 06125 #ifdef SQL_CREATE_VIEW 06126 case SQL_CREATE_VIEW: 06127 *((SQLUINTEGER *) val) = 0; 06128 *valLen = sizeof (SQLUINTEGER); 06129 break; 06130 #endif 06131 case SQL_DATA_SOURCE_NAME: 06132 strmak(val, (d->dsn ? d->dsn : ""), valMax, valLen); 06133 break; 06134 case SQL_DRIVER_NAME: 06135 strmak(val, drvname, valMax, valLen); 06136 break; 06137 case SQL_DRIVER_VER: 06138 strmak(val, "02.50", valMax, valLen); 06139 break; 06140 case SQL_FETCH_DIRECTION: 06141 *((SQLUINTEGER *) val) = SQL_FD_FETCH_NEXT | SQL_FD_FETCH_FIRST | 06142 SQL_FD_FETCH_LAST | SQL_FD_FETCH_PRIOR | SQL_FD_FETCH_ABSOLUTE; 06143 *valLen = sizeof (SQLUINTEGER); 06144 break; 06145 case SQL_ODBC_VER: 06146 strmak(val, (*d->ov3) ? "03.00" : "02.50", valMax, valLen); 06147 break; 06148 case SQL_ODBC_SAG_CLI_CONFORMANCE: 06149 *((SQLSMALLINT *) val) = SQL_OSCC_NOT_COMPLIANT; 06150 *valLen = sizeof (SQLSMALLINT); 06151 break; 06152 case SQL_STANDARD_CLI_CONFORMANCE: 06153 *((SQLUINTEGER *) val) = SQL_SCC_XOPEN_CLI_VERSION1; 06154 *valLen = sizeof (SQLUINTEGER); 06155 break; 06156 case SQL_SERVER_NAME: 06157 case SQL_DATABASE_NAME: 06158 strmak(val, (d->dbname ? d->dbname : ""), valMax, valLen); 06159 break; 06160 case SQL_SEARCH_PATTERN_ESCAPE: 06161 strmak(val, "", valMax, valLen); 06162 break; 06163 case SQL_ODBC_SQL_CONFORMANCE: 06164 *((SQLSMALLINT *) val) = SQL_OSC_MINIMUM; 06165 *valLen = sizeof (SQLSMALLINT); 06166 break; 06167 case SQL_ODBC_API_CONFORMANCE: 06168 *((SQLSMALLINT *) val) = SQL_OAC_LEVEL1; 06169 *valLen = sizeof (SQLSMALLINT); 06170 break; 06171 case SQL_DBMS_NAME: 06172 strmak(val, "SQLite", valMax, valLen); 06173 break; 06174 case SQL_DBMS_VER: 06175 strmak(val, SQLITE_VERSION, valMax, valLen); 06176 break; 06177 case SQL_NEED_LONG_DATA_LEN: 06178 strmak(val, "Y", valMax, valLen); 06179 break; 06180 case SQL_ROW_UPDATES: 06181 case SQL_ACCESSIBLE_PROCEDURES: 06182 case SQL_PROCEDURES: 06183 case SQL_EXPRESSIONS_IN_ORDERBY: 06184 case SQL_ODBC_SQL_OPT_IEF: 06185 case SQL_LIKE_ESCAPE_CLAUSE: 06186 case SQL_ORDER_BY_COLUMNS_IN_SELECT: 06187 case SQL_OUTER_JOINS: 06188 case SQL_COLUMN_ALIAS: 06189 case SQL_ACCESSIBLE_TABLES: 06190 case SQL_MULT_RESULT_SETS: 06191 case SQL_MULTIPLE_ACTIVE_TXN: 06192 case SQL_MAX_ROW_SIZE_INCLUDES_LONG: 06193 strmak(val, "N", valMax, valLen); 06194 break; 06195 case SQL_DATA_SOURCE_READ_ONLY: 06196 strmak(val, "N", valMax, valLen); 06197 break; 06198 #ifdef SQL_OJ_CAPABILITIES 06199 case SQL_OJ_CAPABILITIES: 06200 *((SQLUINTEGER *) val) = 0; 06201 *valLen = sizeof (SQLUINTEGER); 06202 break; 06203 #endif 06204 #ifdef SQL_MAX_IDENTIFIER_LEN 06205 case SQL_MAX_IDENTIFIER_LEN: 06206 *((SQLUSMALLINT *) val) = 255; 06207 *valLen = sizeof (SQLUSMALLINT); 06208 break; 06209 #endif 06210 case SQL_CONCAT_NULL_BEHAVIOR: 06211 *((SQLSMALLINT *) val) = SQL_CB_NULL; 06212 *valLen = sizeof (SQLSMALLINT); 06213 break; 06214 case SQL_CURSOR_COMMIT_BEHAVIOR: 06215 case SQL_CURSOR_ROLLBACK_BEHAVIOR: 06216 *((SQLSMALLINT *) val) = SQL_CB_DELETE; 06217 *valLen = sizeof (SQLSMALLINT); 06218 break; 06219 #ifdef SQL_CURSOR_SENSITIVITY 06220 case SQL_CURSOR_SENSITIVITY: 06221 *((SQLUINTEGER *) val) = SQL_UNSPECIFIED; 06222 *valLen = sizeof (SQLUINTEGER); 06223 break; 06224 #endif 06225 case SQL_DEFAULT_TXN_ISOLATION: 06226 *((SQLUINTEGER *) val) = SQL_TXN_READ_UNCOMMITTED; 06227 *valLen = sizeof (SQLUINTEGER); 06228 break; 06229 #ifdef SQL_DESCRIBE_PARAMETER 06230 case SQL_DESCRIBE_PARAMETER: 06231 strmak(val, "Y", valMax, valLen); 06232 break; 06233 #endif 06234 case SQL_TXN_ISOLATION_OPTION: 06235 *((SQLUINTEGER *) val) = SQL_TXN_READ_UNCOMMITTED; 06236 *valLen = sizeof (SQLUINTEGER); 06237 break; 06238 case SQL_IDENTIFIER_CASE: 06239 *((SQLSMALLINT *) val) = SQL_IC_SENSITIVE; 06240 *valLen = sizeof (SQLSMALLINT); 06241 break; 06242 case SQL_IDENTIFIER_QUOTE_CHAR: 06243 strmak(val, "\"", valMax, valLen); 06244 break; 06245 case SQL_MAX_TABLE_NAME_LEN: 06246 case SQL_MAX_COLUMN_NAME_LEN: 06247 *((SQLSMALLINT *) val) = 255; 06248 *valLen = sizeof (SQLSMALLINT); 06249 break; 06250 case SQL_MAX_CURSOR_NAME_LEN: 06251 *((SWORD *) val) = 255; 06252 *valLen = sizeof (SWORD); 06253 break; 06254 case SQL_MAX_PROCEDURE_NAME_LEN: 06255 *((SQLSMALLINT *) val) = 0; 06256 break; 06257 case SQL_MAX_QUALIFIER_NAME_LEN: 06258 case SQL_MAX_OWNER_NAME_LEN: 06259 *((SQLSMALLINT *) val) = 255; 06260 break; 06261 case SQL_OWNER_TERM: 06262 strmak(val, "owner", valMax, valLen); 06263 break; 06264 case SQL_PROCEDURE_TERM: 06265 strmak(val, "procedure", valMax, valLen); 06266 break; 06267 case SQL_QUALIFIER_NAME_SEPARATOR: 06268 strmak(val, ".", valMax, valLen); 06269 break; 06270 case SQL_QUALIFIER_TERM: 06271 strmak(val, "database", valMax, valLen); 06272 break; 06273 case SQL_QUALIFIER_USAGE: 06274 *((SQLUINTEGER *) val) = 0; 06275 *valLen = sizeof (SQLUINTEGER); 06276 break; 06277 case SQL_SCROLL_CONCURRENCY: 06278 *((SQLUINTEGER *) val) = SQL_SCCO_LOCK; 06279 *valLen = sizeof (SQLUINTEGER); 06280 break; 06281 case SQL_SCROLL_OPTIONS: 06282 *((SQLUINTEGER *) val) = SQL_SO_STATIC | SQL_SO_FORWARD_ONLY; 06283 *valLen = sizeof (SQLUINTEGER); 06284 break; 06285 case SQL_TABLE_TERM: 06286 strmak(val, "table", valMax, valLen); 06287 break; 06288 case SQL_TXN_CAPABLE: 06289 *((SQLSMALLINT *) val) = SQL_TC_ALL; 06290 *valLen = sizeof (SQLSMALLINT); 06291 break; 06292 case SQL_CONVERT_FUNCTIONS: 06293 *((SQLUINTEGER *) val) = 0; 06294 *valLen = sizeof (SQLUINTEGER); 06295 break; 06296 case SQL_SYSTEM_FUNCTIONS: 06297 case SQL_NUMERIC_FUNCTIONS: 06298 case SQL_STRING_FUNCTIONS: 06299 case SQL_TIMEDATE_FUNCTIONS: 06300 *((SQLUINTEGER *) val) = 0; 06301 *valLen = sizeof (SQLUINTEGER); 06302 break; 06303 case SQL_CONVERT_BIGINT: 06304 case SQL_CONVERT_BIT: 06305 case SQL_CONVERT_CHAR: 06306 case SQL_CONVERT_DATE: 06307 case SQL_CONVERT_DECIMAL: 06308 case SQL_CONVERT_DOUBLE: 06309 case SQL_CONVERT_FLOAT: 06310 case SQL_CONVERT_INTEGER: 06311 case SQL_CONVERT_LONGVARCHAR: 06312 case SQL_CONVERT_NUMERIC: 06313 case SQL_CONVERT_REAL: 06314 case SQL_CONVERT_SMALLINT: 06315 case SQL_CONVERT_TIME: 06316 case SQL_CONVERT_TIMESTAMP: 06317 case SQL_CONVERT_TINYINT: 06318 case SQL_CONVERT_VARCHAR: 06319 *((SQLUINTEGER *) val) = 06320 SQL_CVT_CHAR | SQL_CVT_NUMERIC | SQL_CVT_DECIMAL | 06321 SQL_CVT_INTEGER | SQL_CVT_SMALLINT | SQL_CVT_FLOAT | SQL_CVT_REAL | 06322 SQL_CVT_DOUBLE | SQL_CVT_VARCHAR | SQL_CVT_LONGVARCHAR | 06323 SQL_CVT_BIT | SQL_CVT_TINYINT | SQL_CVT_BIGINT | 06324 SQL_CVT_DATE | SQL_CVT_TIME | SQL_CVT_TIMESTAMP; 06325 *valLen = sizeof (SQLUINTEGER); 06326 break; 06327 case SQL_CONVERT_BINARY: 06328 case SQL_CONVERT_VARBINARY: 06329 case SQL_CONVERT_LONGVARBINARY: 06330 *((SQLUINTEGER *) val) = 0; 06331 *valLen = sizeof (SQLUINTEGER); 06332 break; 06333 case SQL_POSITIONED_STATEMENTS: 06334 case SQL_LOCK_TYPES: 06335 *((SQLUINTEGER *) val) = 0; 06336 *valLen = sizeof (SQLUINTEGER); 06337 break; 06338 case SQL_BOOKMARK_PERSISTENCE: 06339 *((SQLUINTEGER *) val) = SQL_BP_SCROLL; 06340 *valLen = sizeof (SQLUINTEGER); 06341 break; 06342 case SQL_OWNER_USAGE: 06343 case SQL_SUBQUERIES: 06344 case SQL_UNION: 06345 case SQL_TIMEDATE_ADD_INTERVALS: 06346 case SQL_TIMEDATE_DIFF_INTERVALS: 06347 *((SQLUINTEGER *) val) = 0; 06348 *valLen = sizeof (SQLUINTEGER); 06349 break; 06350 case SQL_QUOTED_IDENTIFIER_CASE: 06351 *((SQLUSMALLINT *) val) = SQL_IC_SENSITIVE; 06352 *valLen = sizeof (SQLUSMALLINT); 06353 break; 06354 case SQL_POS_OPERATIONS: 06355 *((SQLUINTEGER *) val) = 0; 06356 *valLen = sizeof (SQLUINTEGER); 06357 break; 06358 case SQL_ALTER_TABLE: 06359 *((SQLUINTEGER *) val) = 0; 06360 *valLen = sizeof (SQLUINTEGER); 06361 break; 06362 case SQL_CORRELATION_NAME: 06363 *((SQLSMALLINT *) val) = SQL_CN_DIFFERENT; 06364 *valLen = sizeof (SQLSMALLINT); 06365 break; 06366 case SQL_NON_NULLABLE_COLUMNS: 06367 *((SQLSMALLINT *) val) = SQL_NNC_NON_NULL; 06368 *valLen = sizeof (SQLSMALLINT); 06369 break; 06370 case SQL_NULL_COLLATION: 06371 *((SQLSMALLINT *) val) = SQL_NC_START; 06372 *valLen = sizeof(SQLSMALLINT); 06373 break; 06374 case SQL_MAX_COLUMNS_IN_GROUP_BY: 06375 case SQL_MAX_COLUMNS_IN_ORDER_BY: 06376 case SQL_MAX_COLUMNS_IN_SELECT: 06377 case SQL_MAX_COLUMNS_IN_TABLE: 06378 case SQL_MAX_ROW_SIZE: 06379 case SQL_MAX_TABLES_IN_SELECT: 06380 *((SQLSMALLINT *) val) = 0; 06381 *valLen = sizeof (SQLSMALLINT); 06382 break; 06383 case SQL_MAX_BINARY_LITERAL_LEN: 06384 case SQL_MAX_CHAR_LITERAL_LEN: 06385 *((SQLUINTEGER *) val) = 0; 06386 *valLen = sizeof (SQLUINTEGER); 06387 break; 06388 case SQL_MAX_COLUMNS_IN_INDEX: 06389 *((SQLSMALLINT *) val) = 0; 06390 *valLen = sizeof (SQLSMALLINT); 06391 break; 06392 case SQL_MAX_INDEX_SIZE: 06393 *((SQLUINTEGER *) val) = 0; 06394 *valLen = sizeof(SQLUINTEGER); 06395 break; 06396 #ifdef SQL_MAX_IDENTIFIER_LENGTH 06397 case SQL_MAX_IDENTIFIER_LENGTH: 06398 *((SQLUINTEGER *) val) = 255; 06399 *valLen = sizeof (SQLUINTEGER); 06400 break; 06401 #endif 06402 case SQL_MAX_STATEMENT_LEN: 06403 *((SQLUINTEGER *) val) = 16384; 06404 *valLen = sizeof (SQLUINTEGER); 06405 break; 06406 case SQL_QUALIFIER_LOCATION: 06407 *((SQLSMALLINT *) val) = SQL_QL_START; 06408 *valLen = sizeof (SQLSMALLINT); 06409 break; 06410 case SQL_GETDATA_EXTENSIONS: 06411 *((SQLUINTEGER *) val) = 06412 SQL_GD_ANY_COLUMN | SQL_GD_ANY_ORDER | SQL_GD_BOUND; 06413 *valLen = sizeof (SQLUINTEGER); 06414 break; 06415 case SQL_STATIC_SENSITIVITY: 06416 *((SQLUINTEGER *) val) = 0; 06417 *valLen = sizeof (SQLUINTEGER); 06418 break; 06419 case SQL_FILE_USAGE: 06420 *((SQLSMALLINT *) val) = SQL_FILE_NOT_SUPPORTED; 06421 *valLen = sizeof (SQLSMALLINT); 06422 break; 06423 case SQL_GROUP_BY: 06424 *((SQLSMALLINT *) val) = 0; 06425 *valLen = sizeof (SQLSMALLINT); 06426 break; 06427 case SQL_KEYWORDS: 06428 strmak(val, "SELECT,DROP,DELETE,UPDATE,INSERT," 06429 "INTO,VALUES,TABLE,FROM,SET,WHERE,AND,CURRENT,OF", 06430 valMax, valLen); 06431 break; 06432 case SQL_SPECIAL_CHARACTERS: 06433 strmak(val, "", valMax, valLen); 06434 break; 06435 case SQL_BATCH_SUPPORT: 06436 case SQL_BATCH_ROW_COUNT: 06437 case SQL_PARAM_ARRAY_ROW_COUNTS: 06438 *((SQLUINTEGER *) val) = 0; 06439 *valLen = sizeof (SQLUINTEGER); 06440 break; 06441 case SQL_FORWARD_ONLY_CURSOR_ATTRIBUTES1: 06442 *((SQLUINTEGER *) val) = SQL_CA1_NEXT | SQL_CA1_BOOKMARK; 06443 *valLen = sizeof (SQLUINTEGER); 06444 break; 06445 case SQL_STATIC_CURSOR_ATTRIBUTES1: 06446 *((SQLUINTEGER *) val) = SQL_CA1_NEXT | SQL_CA1_ABSOLUTE | 06447 SQL_CA1_RELATIVE | SQL_CA1_BOOKMARK; 06448 *valLen = sizeof (SQLUINTEGER); 06449 break; 06450 case SQL_FORWARD_ONLY_CURSOR_ATTRIBUTES2: 06451 case SQL_STATIC_CURSOR_ATTRIBUTES2: 06452 *((SQLUINTEGER *) val) = SQL_CA2_READ_ONLY_CONCURRENCY | 06453 SQL_CA2_LOCK_CONCURRENCY; 06454 *valLen = sizeof (SQLUINTEGER); 06455 break; 06456 case SQL_KEYSET_CURSOR_ATTRIBUTES1: 06457 case SQL_KEYSET_CURSOR_ATTRIBUTES2: 06458 case SQL_DYNAMIC_CURSOR_ATTRIBUTES1: 06459 case SQL_DYNAMIC_CURSOR_ATTRIBUTES2: 06460 *((SQLUINTEGER *) val) = 0; 06461 *valLen = sizeof (SQLUINTEGER); 06462 break; 06463 case SQL_ODBC_INTERFACE_CONFORMANCE: 06464 *((SQLUINTEGER *) val) = SQL_OIC_CORE; 06465 *valLen = sizeof (SQLUINTEGER); 06466 break; 06467 default: 06468 setstatd(d, -1, "unsupported info option %d", 06469 (*d->ov3) ? "HYC00" : "S1C00", type); 06470 return SQL_ERROR; 06471 } 06472 return SQL_SUCCESS; 06473 } 06474 06475 #if (defined(HAVE_UNIXODBC) && HAVE_UNIXODBC) || !defined(SQLITE_UTF8) 06476 06486 SQLRETURN SQL_API 06487 SQLGetInfo(SQLHDBC dbc, SQLUSMALLINT type, SQLPOINTER val, SQLSMALLINT valMax, 06488 SQLSMALLINT *valLen) 06489 { 06490 return drvgetinfo(dbc, type, val, valMax, valLen); 06491 } 06492 #endif 06493 06494 #ifdef SQLITE_UTF8 06495 06505 SQLRETURN SQL_API 06506 SQLGetInfoW(SQLHDBC dbc, SQLUSMALLINT type, SQLPOINTER val, SQLSMALLINT valMax, 06507 SQLSMALLINT *valLen) 06508 { 06509 SQLRETURN ret; 06510 SQLSMALLINT len; 06511 06512 ret = drvgetinfo(dbc, type, val, valMax, &len); 06513 if (ret == SQL_SUCCESS) { 06514 SQLWCHAR *v = NULL; 06515 06516 switch (type) { 06517 case SQL_USER_NAME: 06518 case SQL_DRIVER_ODBC_VER: 06519 case SQL_DATA_SOURCE_NAME: 06520 case SQL_DRIVER_NAME: 06521 case SQL_DRIVER_VER: 06522 case SQL_ODBC_VER: 06523 case SQL_SERVER_NAME: 06524 case SQL_DATABASE_NAME: 06525 case SQL_SEARCH_PATTERN_ESCAPE: 06526 case SQL_DBMS_NAME: 06527 case SQL_DBMS_VER: 06528 case SQL_NEED_LONG_DATA_LEN: 06529 case SQL_ROW_UPDATES: 06530 case SQL_ACCESSIBLE_PROCEDURES: 06531 case SQL_PROCEDURES: 06532 case SQL_EXPRESSIONS_IN_ORDERBY: 06533 case SQL_ODBC_SQL_OPT_IEF: 06534 case SQL_LIKE_ESCAPE_CLAUSE: 06535 case SQL_ORDER_BY_COLUMNS_IN_SELECT: 06536 case SQL_OUTER_JOINS: 06537 case SQL_COLUMN_ALIAS: 06538 case SQL_ACCESSIBLE_TABLES: 06539 case SQL_MULT_RESULT_SETS: 06540 case SQL_MULTIPLE_ACTIVE_TXN: 06541 case SQL_MAX_ROW_SIZE_INCLUDES_LONG: 06542 case SQL_DATA_SOURCE_READ_ONLY: 06543 #ifdef SQL_DESCRIBE_PARAMETER 06544 case SQL_DESCRIBE_PARAMETER: 06545 #endif 06546 case SQL_IDENTIFIER_QUOTE_CHAR: 06547 case SQL_OWNER_TERM: 06548 case SQL_PROCEDURE_TERM: 06549 case SQL_QUALIFIER_NAME_SEPARATOR: 06550 case SQL_QUALIFIER_TERM: 06551 case SQL_TABLE_TERM: 06552 case SQL_KEYWORDS: 06553 case SQL_SPECIAL_CHARACTERS: 06554 if (val) { 06555 if (len > 0) { 06556 v = uc_from_utf((char *) val, len); 06557 if (v) { 06558 int vmax = valMax / sizeof (SQLWCHAR); 06559 06560 uc_strncpy(val, v, vmax); 06561 len = min(vmax, uc_strlen(v)); 06562 uc_free(v); 06563 } else { 06564 len = 0; 06565 } 06566 } 06567 if (len <= 0) { 06568 len = 0; 06569 if (valMax >= sizeof (SQLWCHAR)) { 06570 *((SQLWCHAR *)val) = 0; 06571 } 06572 } 06573 } else { 06574 len = 0; 06575 } 06576 break; 06577 } 06578 if (valLen) { 06579 *valLen = len; 06580 } 06581 } 06582 return ret; 06583 } 06584 #endif 06585 06594 SQLRETURN SQL_API 06595 SQLGetFunctions(SQLHDBC dbc, SQLUSMALLINT func, 06596 SQLUSMALLINT *flags) 06597 { 06598 DBC *d; 06599 int i; 06600 SQLUSMALLINT exists[100]; 06601 06602 if (dbc == SQL_NULL_HDBC) { 06603 return SQL_INVALID_HANDLE; 06604 } 06605 d = (DBC *) dbc; 06606 for (i = 0; i < array_size(exists); i++) { 06607 exists[i] = SQL_FALSE; 06608 } 06609 exists[SQL_API_SQLALLOCCONNECT] = SQL_TRUE; 06610 exists[SQL_API_SQLFETCH] = SQL_TRUE; 06611 exists[SQL_API_SQLALLOCENV] = SQL_TRUE; 06612 exists[SQL_API_SQLFREECONNECT] = SQL_TRUE; 06613 exists[SQL_API_SQLALLOCSTMT] = SQL_TRUE; 06614 exists[SQL_API_SQLFREEENV] = SQL_TRUE; 06615 exists[SQL_API_SQLBINDCOL] = SQL_TRUE; 06616 exists[SQL_API_SQLFREESTMT] = SQL_TRUE; 06617 exists[SQL_API_SQLCANCEL] = SQL_TRUE; 06618 exists[SQL_API_SQLGETCURSORNAME] = SQL_TRUE; 06619 exists[SQL_API_SQLCOLATTRIBUTES] = SQL_TRUE; 06620 exists[SQL_API_SQLNUMRESULTCOLS] = SQL_TRUE; 06621 exists[SQL_API_SQLCONNECT] = SQL_TRUE; 06622 exists[SQL_API_SQLPREPARE] = SQL_TRUE; 06623 exists[SQL_API_SQLDESCRIBECOL] = SQL_TRUE; 06624 exists[SQL_API_SQLROWCOUNT] = SQL_TRUE; 06625 exists[SQL_API_SQLDISCONNECT] = SQL_TRUE; 06626 exists[SQL_API_SQLSETCURSORNAME] = SQL_FALSE; 06627 exists[SQL_API_SQLERROR] = SQL_TRUE; 06628 exists[SQL_API_SQLSETPARAM] = SQL_TRUE; 06629 exists[SQL_API_SQLEXECDIRECT] = SQL_TRUE; 06630 exists[SQL_API_SQLTRANSACT] = SQL_TRUE; 06631 exists[SQL_API_SQLEXECUTE] = SQL_TRUE; 06632 exists[SQL_API_SQLBINDPARAMETER] = SQL_TRUE; 06633 exists[SQL_API_SQLGETTYPEINFO] = SQL_TRUE; 06634 exists[SQL_API_SQLCOLUMNS] = SQL_TRUE; 06635 exists[SQL_API_SQLPARAMDATA] = SQL_TRUE; 06636 exists[SQL_API_SQLDRIVERCONNECT] = SQL_TRUE; 06637 exists[SQL_API_SQLPUTDATA] = SQL_TRUE; 06638 exists[SQL_API_SQLGETCONNECTOPTION] = SQL_TRUE; 06639 exists[SQL_API_SQLSETCONNECTOPTION] = SQL_TRUE; 06640 exists[SQL_API_SQLGETDATA] = SQL_TRUE; 06641 exists[SQL_API_SQLSETSTMTOPTION] = SQL_TRUE; 06642 exists[SQL_API_SQLGETFUNCTIONS] = SQL_TRUE; 06643 exists[SQL_API_SQLSPECIALCOLUMNS] = SQL_TRUE; 06644 exists[SQL_API_SQLGETINFO] = SQL_TRUE; 06645 exists[SQL_API_SQLSTATISTICS] = SQL_TRUE; 06646 exists[SQL_API_SQLGETSTMTOPTION] = SQL_TRUE; 06647 exists[SQL_API_SQLTABLES] = SQL_TRUE; 06648 exists[SQL_API_SQLBROWSECONNECT] = SQL_FALSE; 06649 exists[SQL_API_SQLNUMPARAMS] = SQL_TRUE; 06650 exists[SQL_API_SQLCOLUMNPRIVILEGES] = SQL_FALSE; 06651 exists[SQL_API_SQLPARAMOPTIONS] = SQL_FALSE; 06652 exists[SQL_API_SQLDATASOURCES] = SQL_TRUE; 06653 exists[SQL_API_SQLPRIMARYKEYS] = SQL_TRUE; 06654 exists[SQL_API_SQLDESCRIBEPARAM] = SQL_TRUE; 06655 exists[SQL_API_SQLPROCEDURECOLUMNS] = SQL_TRUE; 06656 exists[SQL_API_SQLDRIVERS] = SQL_FALSE; 06657 exists[SQL_API_SQLPROCEDURES] = SQL_TRUE; 06658 exists[SQL_API_SQLEXTENDEDFETCH] = SQL_TRUE; 06659 exists[SQL_API_SQLSETPOS] = SQL_FALSE; 06660 exists[SQL_API_SQLFOREIGNKEYS] = SQL_TRUE; 06661 exists[SQL_API_SQLSETSCROLLOPTIONS] = SQL_TRUE; 06662 exists[SQL_API_SQLMORERESULTS] = SQL_TRUE; 06663 exists[SQL_API_SQLTABLEPRIVILEGES] = SQL_FALSE; 06664 exists[SQL_API_SQLNATIVESQL] = SQL_TRUE; 06665 if (func == SQL_API_ALL_FUNCTIONS) { 06666 memcpy(flags, exists, sizeof (exists)); 06667 } else if (func == SQL_API_ODBC3_ALL_FUNCTIONS) { 06668 int i; 06669 #define SET_EXISTS(x) \ 06670 flags[(x) >> 4] |= (1 << ((x) & 0xF)) 06671 #define CLR_EXISTS(x) \ 06672 flags[(x) >> 4] &= ~(1 << ((x) & 0xF)) 06673 06674 memset(flags, 0, 06675 sizeof (SQLUSMALLINT) * SQL_API_ODBC3_ALL_FUNCTIONS_SIZE); 06676 for (i = 0; i < array_size(exists); i++) { 06677 if (exists[i]) { 06678 flags[i >> 4] |= (1 << (i & 0xF)); 06679 } 06680 } 06681 SET_EXISTS(SQL_API_SQLALLOCHANDLE); 06682 SET_EXISTS(SQL_API_SQLFREEHANDLE); 06683 SET_EXISTS(SQL_API_SQLGETSTMTATTR); 06684 SET_EXISTS(SQL_API_SQLSETSTMTATTR); 06685 SET_EXISTS(SQL_API_SQLGETCONNECTATTR); 06686 SET_EXISTS(SQL_API_SQLSETCONNECTATTR); 06687 SET_EXISTS(SQL_API_SQLGETENVATTR); 06688 SET_EXISTS(SQL_API_SQLSETENVATTR); 06689 SET_EXISTS(SQL_API_SQLCLOSECURSOR); 06690 SET_EXISTS(SQL_API_SQLBINDPARAM); 06691 #if !defined(HAVE_UNIXODBC) || !HAVE_UNIXODBC 06692 /* 06693 * Some unixODBC versions have problems with 06694 * SQLError() vs. SQLGetDiagRec() with loss 06695 * of error/warning messages. 06696 */ 06697 SET_EXISTS(SQL_API_SQLGETDIAGREC); 06698 #endif 06699 SET_EXISTS(SQL_API_SQLFETCHSCROLL); 06700 SET_EXISTS(SQL_API_SQLENDTRAN); 06701 } else { 06702 if (func < array_size(exists)) { 06703 *flags = exists[func]; 06704 } else { 06705 switch (func) { 06706 case SQL_API_SQLALLOCHANDLE: 06707 case SQL_API_SQLFREEHANDLE: 06708 case SQL_API_SQLGETSTMTATTR: 06709 case SQL_API_SQLSETSTMTATTR: 06710 case SQL_API_SQLGETCONNECTATTR: 06711 case SQL_API_SQLSETCONNECTATTR: 06712 case SQL_API_SQLGETENVATTR: 06713 case SQL_API_SQLSETENVATTR: 06714 case SQL_API_SQLCLOSECURSOR: 06715 case SQL_API_SQLBINDPARAM: 06716 #if !defined(HAVE_UNIXODBC) || !HAVE_UNIXODBC 06717 /* 06718 * Some unixODBC versions have problems with 06719 * SQLError() vs. SQLGetDiagRec() with loss 06720 * of error/warning messages. 06721 */ 06722 case SQL_API_SQLGETDIAGREC: 06723 #endif 06724 case SQL_API_SQLFETCHSCROLL: 06725 case SQL_API_SQLENDTRAN: 06726 *flags = SQL_TRUE; 06727 break; 06728 default: 06729 *flags = SQL_FALSE; 06730 } 06731 } 06732 } 06733 return SQL_SUCCESS; 06734 } 06735 06742 static SQLRETURN 06743 drvallocenv(SQLHENV *env) 06744 { 06745 ENV *e; 06746 06747 if (env == NULL) { 06748 return SQL_INVALID_HANDLE; 06749 } 06750 e = (ENV *) xmalloc(sizeof (ENV)); 06751 if (e == NULL) { 06752 *env = SQL_NULL_HENV; 06753 return SQL_ERROR; 06754 } 06755 e->magic = ENV_MAGIC; 06756 e->ov3 = 0; 06757 e->dbcs = NULL; 06758 *env = (SQLHENV) e; 06759 return SQL_SUCCESS; 06760 } 06761 06768 SQLRETURN SQL_API 06769 SQLAllocEnv(SQLHENV *env) 06770 { 06771 return drvallocenv(env); 06772 } 06773 06780 static SQLRETURN 06781 drvfreeenv(SQLHENV env) 06782 { 06783 ENV *e; 06784 06785 if (env == SQL_NULL_HENV) { 06786 return SQL_INVALID_HANDLE; 06787 } 06788 e = (ENV *) env; 06789 if (e->magic != ENV_MAGIC) { 06790 return SQL_SUCCESS; 06791 } 06792 if (e->dbcs) { 06793 return SQL_ERROR; 06794 } 06795 e->magic = DEAD_MAGIC; 06796 xfree(e); 06797 return SQL_SUCCESS; 06798 } 06799 06806 SQLRETURN SQL_API 06807 SQLFreeEnv(SQLHENV env) 06808 { 06809 return drvfreeenv(env); 06810 } 06811 06819 static SQLRETURN 06820 drvallocconnect(SQLHENV env, SQLHDBC *dbc) 06821 { 06822 DBC *d; 06823 ENV *e; 06824 const char *verstr; 06825 int maj = 0, min = 0, lev = 0; 06826 06827 if (dbc == NULL) { 06828 return SQL_ERROR; 06829 } 06830 d = (DBC *) xmalloc(sizeof (DBC)); 06831 if (d == NULL) { 06832 *dbc = SQL_NULL_HDBC; 06833 return SQL_ERROR; 06834 } 06835 memset(d, 0, sizeof (DBC)); 06836 d->curtype = SQL_CURSOR_STATIC; 06837 #if HAVE_LIBVERSION 06838 verstr = sqlite_libversion(); 06839 #else 06840 verstr = sqlite_version; 06841 #endif 06842 sscanf(verstr, "%d.%d.%d", &maj, &min, &lev); 06843 d->version = verinfo(maj & 0xFF, min & 0xFF, lev & 0xFF); 06844 if (d->version < verinfo(2, 8, 0)) { 06845 xfree(d); 06846 return SQL_ERROR; 06847 } 06848 d->ov3 = &d->ov3val; 06849 e = (ENV *) env; 06850 if (e->magic == ENV_MAGIC) { 06851 DBC *n, *p; 06852 06853 d->env = e; 06854 d->ov3 = &e->ov3; 06855 p = NULL; 06856 n = e->dbcs; 06857 while (n) { 06858 p = n; 06859 n = n->next; 06860 } 06861 if (p) { 06862 p->next = d; 06863 } else { 06864 e->dbcs = d; 06865 } 06866 } 06867 d->autocommit = 1; 06868 d->magic = DBC_MAGIC; 06869 *dbc = (SQLHDBC) d; 06870 drvgetgpps(d); 06871 return SQL_SUCCESS; 06872 } 06873 06881 SQLRETURN SQL_API 06882 SQLAllocConnect(SQLHENV env, SQLHDBC *dbc) 06883 { 06884 return drvallocconnect(env, dbc); 06885 } 06886 06893 static SQLRETURN 06894 drvfreeconnect(SQLHDBC dbc) 06895 { 06896 DBC *d; 06897 ENV *e; 06898 06899 if (dbc == SQL_NULL_HDBC) { 06900 return SQL_INVALID_HANDLE; 06901 } 06902 d = (DBC *) dbc; 06903 if (d->magic != DBC_MAGIC) { 06904 return SQL_INVALID_HANDLE; 06905 } 06906 if (d->sqlite) { 06907 setstatd(d, -1, "not disconnected", (*d->ov3) ? "HY000" : "S1000"); 06908 return SQL_ERROR; 06909 } 06910 while (d->stmt) { 06911 freestmt((HSTMT) d->stmt); 06912 } 06913 e = d->env; 06914 if (e && e->magic == ENV_MAGIC) { 06915 DBC *n, *p; 06916 06917 p = NULL; 06918 n = e->dbcs; 06919 while (n) { 06920 if (n == d) { 06921 break; 06922 } 06923 p = n; 06924 n = n->next; 06925 } 06926 if (n) { 06927 if (p) { 06928 p->next = d->next; 06929 } else { 06930 e->dbcs = d->next; 06931 } 06932 } 06933 } 06934 drvrelgpps(d); 06935 d->magic = DEAD_MAGIC; 06936 #if defined(HAVE_SQLITETRACE) && HAVE_SQLITETRACE 06937 if (d->trace) { 06938 fclose(d->trace); 06939 } 06940 #endif 06941 xfree(d); 06942 return SQL_SUCCESS; 06943 } 06944 06951 SQLRETURN SQL_API 06952 SQLFreeConnect(SQLHDBC dbc) 06953 { 06954 return drvfreeconnect(dbc); 06955 } 06956 06967 static SQLRETURN 06968 drvgetconnectattr(SQLHDBC dbc, SQLINTEGER attr, SQLPOINTER val, 06969 SQLINTEGER bufmax, SQLINTEGER *buflen) 06970 { 06971 DBC *d; 06972 SQLINTEGER dummy; 06973 06974 if (dbc == SQL_NULL_HDBC) { 06975 return SQL_INVALID_HANDLE; 06976 } 06977 d = (DBC *) dbc; 06978 if (!val) { 06979 val = (SQLPOINTER) &dummy; 06980 } 06981 if (!buflen) { 06982 buflen = &dummy; 06983 } 06984 switch (attr) { 06985 case SQL_ATTR_CONNECTION_DEAD: 06986 *((SQLINTEGER *) val) = d->sqlite ? SQL_CD_FALSE : SQL_CD_TRUE; 06987 *buflen = sizeof (SQLINTEGER); 06988 break; 06989 case SQL_ATTR_ACCESS_MODE: 06990 *((SQLINTEGER *) val) = SQL_MODE_READ_WRITE; 06991 *buflen = sizeof (SQLINTEGER); 06992 break; 06993 case SQL_ATTR_AUTOCOMMIT: 06994 *((SQLINTEGER *) val) = 06995 d->autocommit ? SQL_AUTOCOMMIT_ON : SQL_AUTOCOMMIT_OFF; 06996 *buflen = sizeof (SQLINTEGER); 06997 break; 06998 case SQL_ATTR_LOGIN_TIMEOUT: 06999 *((SQLINTEGER *) val) = 100; 07000 *buflen = sizeof (SQLINTEGER); 07001 break; 07002 case SQL_ATTR_ODBC_CURSORS: 07003 *((SQLINTEGER *) val) = SQL_CUR_USE_DRIVER; 07004 *buflen = sizeof (SQLINTEGER); 07005 break; 07006 case SQL_ATTR_PACKET_SIZE: 07007 *((SQLINTEGER *) val) = 16384; 07008 *buflen = sizeof (SQLINTEGER); 07009 break; 07010 case SQL_ATTR_TXN_ISOLATION: 07011 *((SQLINTEGER *) val) = SQL_TXN_READ_UNCOMMITTED; 07012 *buflen = sizeof (SQLINTEGER); 07013 break; 07014 case SQL_ATTR_TRACE: 07015 case SQL_ATTR_TRACEFILE: 07016 case SQL_ATTR_QUIET_MODE: 07017 case SQL_ATTR_TRANSLATE_OPTION: 07018 case SQL_ATTR_KEYSET_SIZE: 07019 case SQL_ATTR_QUERY_TIMEOUT: 07020 case SQL_ATTR_PARAM_BIND_TYPE: 07021 case SQL_ATTR_CURRENT_CATALOG: 07022 *((SQLINTEGER *) val) = 0; 07023 *buflen = sizeof (SQLINTEGER); 07024 break; 07025 case SQL_ATTR_ROW_BIND_TYPE: 07026 *((SQLUINTEGER *) val) = SQL_BIND_BY_COLUMN; 07027 *buflen = sizeof (SQLUINTEGER); 07028 break; 07029 case SQL_ATTR_USE_BOOKMARKS: 07030 *((SQLINTEGER *) val) = SQL_UB_OFF; 07031 *buflen = sizeof (SQLINTEGER); 07032 break; 07033 case SQL_ATTR_ASYNC_ENABLE: 07034 *((SQLINTEGER *) val) = SQL_ASYNC_ENABLE_OFF; 07035 *buflen = sizeof (SQLINTEGER); 07036 break; 07037 case SQL_ATTR_NOSCAN: 07038 *((SQLINTEGER *) val) = SQL_NOSCAN_ON; 07039 *buflen = sizeof (SQLINTEGER); 07040 break; 07041 case SQL_ATTR_CONCURRENCY: 07042 *((SQLINTEGER *) val) = SQL_CONCUR_LOCK; 07043 *buflen = sizeof (SQLINTEGER); 07044 break; 07045 case SQL_ATTR_SIMULATE_CURSOR: 07046 *((SQLINTEGER *) val) = SQL_SC_NON_UNIQUE; 07047 *buflen = sizeof (SQLINTEGER); 07048 break; 07049 case SQL_ATTR_MAX_ROWS: 07050 case SQL_ATTR_MAX_LENGTH: 07051 *((SQLINTEGER *) val) = 1000000000; 07052 *buflen = sizeof (SQLINTEGER); 07053 break; 07054 case SQL_ATTR_CURSOR_TYPE: 07055 *((SQLINTEGER *) val) = d->curtype; 07056 *buflen = sizeof (SQLINTEGER); 07057 break; 07058 case SQL_ATTR_RETRIEVE_DATA: 07059 *((SQLINTEGER *) val) = SQL_RD_ON; 07060 *buflen = sizeof (SQLINTEGER); 07061 break; 07062 default: 07063 *((SQLINTEGER *) val) = 0; 07064 *buflen = sizeof (SQLINTEGER); 07065 setstatd(d, -1, "unsupported connect attribute %d", 07066 (*d->ov3) ? "HYC00" : "S1C00", (int) attr); 07067 return SQL_ERROR; 07068 } 07069 return SQL_SUCCESS; 07070 } 07071 07072 #ifndef SQLITE_UTF8 07073 07083 SQLRETURN SQL_API 07084 SQLGetConnectAttr(SQLHDBC dbc, SQLINTEGER attr, SQLPOINTER val, 07085 SQLINTEGER bufmax, SQLINTEGER *buflen) 07086 { 07087 return drvgetconnectattr(dbc, attr, val, bufmax, buflen); 07088 } 07089 #endif 07090 07091 #ifdef SQLITE_UTF8 07092 07102 SQLRETURN SQL_API 07103 SQLGetConnectAttrW(SQLHDBC dbc, SQLINTEGER attr, SQLPOINTER val, 07104 SQLINTEGER bufmax, SQLINTEGER *buflen) 07105 { 07106 return drvgetconnectattr(dbc, attr, val, bufmax, buflen); 07107 } 07108 #endif 07109 07119 static SQLRETURN 07120 drvsetconnectattr(SQLHDBC dbc, SQLINTEGER attr, SQLPOINTER val, 07121 SQLINTEGER len) 07122 { 07123 DBC *d; 07124 07125 if (dbc == SQL_NULL_HDBC) { 07126 return SQL_INVALID_HANDLE; 07127 } 07128 d = (DBC *) dbc; 07129 switch (attr) { 07130 case SQL_AUTOCOMMIT: 07131 if (len == SQL_IS_INTEGER) { 07132 d->autocommit = (SQLINTEGER) val == SQL_AUTOCOMMIT_ON; 07133 goto doit; 07134 } 07135 if (val && len >= sizeof (SQLINTEGER)) { 07136 d->autocommit = *((SQLINTEGER *) val) == SQL_AUTOCOMMIT_ON; 07137 doit: 07138 if (d->autocommit && d->intrans) { 07139 return endtran(d, SQL_COMMIT); 07140 } else if (!d->autocommit) { 07141 vm_end(d->vm_stmt); 07142 } 07143 } 07144 break; 07145 default: 07146 setstatd(d, -1, "option value changed", "01S02"); 07147 return SQL_SUCCESS_WITH_INFO; 07148 } 07149 return SQL_SUCCESS; 07150 } 07151 07152 #ifndef SQLITE_UTF8 07153 07162 SQLRETURN SQL_API 07163 SQLSetConnectAttr(SQLHDBC dbc, SQLINTEGER attr, SQLPOINTER val, 07164 SQLINTEGER len) 07165 { 07166 return drvsetconnectattr(dbc, attr, val, len); 07167 } 07168 #endif 07169 07170 #ifdef SQLITE_UTF8 07171 07180 SQLRETURN SQL_API 07181 SQLSetConnectAttrW(SQLHDBC dbc, SQLINTEGER attr, SQLPOINTER val, 07182 SQLINTEGER len) 07183 { 07184 return drvsetconnectattr(dbc, attr, val, len); 07185 } 07186 #endif 07187 07196 static SQLRETURN 07197 drvgetconnectoption(SQLHDBC dbc, SQLUSMALLINT opt, SQLPOINTER param) 07198 { 07199 DBC *d; 07200 SQLINTEGER dummy; 07201 07202 if (dbc == SQL_NULL_HDBC) { 07203 return SQL_INVALID_HANDLE; 07204 } 07205 d = (DBC *) dbc; 07206 if (!param) { 07207 param = (SQLPOINTER) &dummy; 07208 } 07209 switch (opt) { 07210 case SQL_ACCESS_MODE: 07211 *((SQLINTEGER *) param) = SQL_MODE_READ_WRITE; 07212 break; 07213 case SQL_AUTOCOMMIT: 07214 *((SQLINTEGER *) param) = 07215 d->autocommit ? SQL_AUTOCOMMIT_ON : SQL_AUTOCOMMIT_OFF; 07216 break; 07217 case SQL_LOGIN_TIMEOUT: 07218 *((SQLINTEGER *) param) = 100; 07219 break; 07220 case SQL_ODBC_CURSORS: 07221 *((SQLINTEGER *) param) = SQL_CUR_USE_DRIVER; 07222 break; 07223 case SQL_PACKET_SIZE: 07224 *((SQLINTEGER *) param) = 16384; 07225 break; 07226 case SQL_TXN_ISOLATION: 07227 *((SQLINTEGER *) param) = SQL_TXN_READ_UNCOMMITTED; 07228 break; 07229 case SQL_OPT_TRACE: 07230 case SQL_OPT_TRACEFILE: 07231 case SQL_QUIET_MODE: 07232 case SQL_TRANSLATE_DLL: 07233 case SQL_TRANSLATE_OPTION: 07234 case SQL_KEYSET_SIZE: 07235 case SQL_QUERY_TIMEOUT: 07236 case SQL_BIND_TYPE: 07237 case SQL_CURRENT_QUALIFIER: 07238 *((SQLINTEGER *) param) = 0; 07239 break; 07240 case SQL_USE_BOOKMARKS: 07241 *((SQLINTEGER *) param) = SQL_UB_OFF; 07242 break; 07243 case SQL_ASYNC_ENABLE: 07244 *((SQLINTEGER *) param) = SQL_ASYNC_ENABLE_OFF; 07245 break; 07246 case SQL_NOSCAN: 07247 *((SQLINTEGER *) param) = SQL_NOSCAN_ON; 07248 break; 07249 case SQL_CONCURRENCY: 07250 *((SQLINTEGER *) param) = SQL_CONCUR_LOCK; 07251 break; 07252 case SQL_SIMULATE_CURSOR: 07253 *((SQLINTEGER *) param) = SQL_SC_NON_UNIQUE; 07254 break; 07255 case SQL_ROWSET_SIZE: 07256 case SQL_MAX_ROWS: 07257 case SQL_MAX_LENGTH: 07258 *((SQLINTEGER *) param) = 1000000000; 07259 break; 07260 case SQL_CURSOR_TYPE: 07261 *((SQLINTEGER *) param) = d->curtype; 07262 break; 07263 case SQL_RETRIEVE_DATA: 07264 *((SQLINTEGER *) param) = SQL_RD_ON; 07265 break; 07266 default: 07267 *((SQLINTEGER *) param) = 0; 07268 setstatd(d, -1, "unsupported connect option %d", 07269 (*d->ov3) ? "HYC00" : "S1C00", opt); 07270 return SQL_ERROR; 07271 } 07272 return SQL_SUCCESS; 07273 } 07274 07275 #ifndef SQLITE_UTF8 07276 07284 SQLRETURN SQL_API 07285 SQLGetConnectOption(SQLHDBC dbc, SQLUSMALLINT opt, SQLPOINTER param) 07286 { 07287 return drvgetconnectoption(dbc, opt, param); 07288 } 07289 #endif 07290 07291 #ifdef SQLITE_UTF8 07292 07300 SQLRETURN SQL_API 07301 SQLGetConnectOptionW(SQLHDBC dbc, SQLUSMALLINT opt, SQLPOINTER param) 07302 { 07303 return drvgetconnectoption(dbc, opt, param); 07304 } 07305 #endif 07306 07315 static SQLRETURN 07316 drvsetconnectoption(SQLHDBC dbc, SQLUSMALLINT opt, SQLUINTEGER param) 07317 { 07318 DBC *d; 07319 07320 if (dbc == SQL_NULL_HDBC) { 07321 return SQL_INVALID_HANDLE; 07322 } 07323 d = (DBC *) dbc; 07324 switch (opt) { 07325 case SQL_AUTOCOMMIT: 07326 d->autocommit = param == SQL_AUTOCOMMIT_ON; 07327 if (d->autocommit && d->intrans) { 07328 return endtran(d, SQL_COMMIT); 07329 } else if (!d->autocommit) { 07330 vm_end(d->vm_stmt); 07331 } 07332 break; 07333 default: 07334 setstatd(d, -1, "option value changed", "01S02"); 07335 return SQL_SUCCESS_WITH_INFO; 07336 } 07337 return SQL_SUCCESS; 07338 } 07339 07340 #ifndef SQLITE_UTF8 07341 07349 SQLRETURN SQL_API 07350 SQLSetConnectOption(SQLHDBC dbc, SQLUSMALLINT opt, SQLUINTEGER param) 07351 { 07352 return drvsetconnectoption(dbc, opt, param); 07353 } 07354 #endif 07355 07356 #ifdef SQLITE_UTF8 07357 07365 SQLRETURN SQL_API 07366 SQLSetConnectOptionW(SQLHDBC dbc, SQLUSMALLINT opt, SQLUINTEGER param) 07367 { 07368 return drvsetconnectoption(dbc, opt, param); 07369 } 07370 #endif 07371 07372 #if defined(WITHOUT_DRIVERMGR) || !defined(_WIN32) 07373 07384 static int 07385 getdsnattr(char *dsn, char *attr, char *out, int outLen) 07386 { 07387 char *str = dsn, *start; 07388 int len = strlen(attr); 07389 07390 while (*str) { 07391 while (*str && *str == ';') { 07392 ++str; 07393 } 07394 start = str; 07395 if ((str = strchr(str, '=')) == NULL) { 07396 return 0; 07397 } 07398 if (str - start == len && 07399 #ifdef _WIN32 07400 _strnicmp(start, attr, len) == 0 07401 #else 07402 strncasecmp(start, attr, len) == 0 07403 #endif 07404 ) { 07405 start = ++str; 07406 while (*str && *str != ';') { 07407 ++str; 07408 } 07409 len = min(outLen - 1, str - start); 07410 strncpy(out, start, len); 07411 out[len] = '\0'; 07412 return 1; 07413 } 07414 while (*str && *str != ';') { 07415 ++str; 07416 } 07417 } 07418 return 0; 07419 } 07420 #endif 07421 07430 static SQLRETURN 07431 drvconnect(SQLHDBC dbc, SQLCHAR *dsn, SQLSMALLINT dsnLen) 07432 { 07433 DBC *d; 07434 int len; 07435 char buf[SQL_MAX_MESSAGE_LENGTH], dbname[SQL_MAX_MESSAGE_LENGTH / 4]; 07436 char busy[SQL_MAX_MESSAGE_LENGTH / 4]; 07437 char sflag[32], nwflag[32]; 07438 #if defined(HAVE_SQLITETRACE) && HAVE_SQLITETRACE 07439 char tracef[SQL_MAX_MESSAGE_LENGTH]; 07440 #endif 07441 07442 if (dbc == SQL_NULL_HDBC) { 07443 return SQL_INVALID_HANDLE; 07444 } 07445 d = (DBC *) dbc; 07446 if (d->magic != DBC_MAGIC) { 07447 return SQL_INVALID_HANDLE; 07448 } 07449 if (d->sqlite != NULL) { 07450 setstatd(d, -1, "connection already established", "08002"); 07451 return SQL_ERROR; 07452 } 07453 buf[0] = '\0'; 07454 if (dsnLen == SQL_NTS) { 07455 len = sizeof (buf) - 1; 07456 } else { 07457 len = min(sizeof (buf) - 1, dsnLen); 07458 } 07459 if (dsn != NULL) { 07460 strncpy(buf, dsn, len); 07461 } 07462 buf[len] = '\0'; 07463 if (buf[0] == '\0') { 07464 setstatd(d, -1, "invalid DSN", (*d->ov3) ? "HY090" : "S1090"); 07465 return SQL_ERROR; 07466 } 07467 busy[0] = '\0'; 07468 dbname[0] = '\0'; 07469 #ifdef WITHOUT_DRIVERMGR 07470 getdsnattr(buf, "database", dbname, sizeof (dbname)); 07471 if (dbname[0] == '\0') { 07472 strncpy(dbname, buf, sizeof (dbname)); 07473 dbname[sizeof (dbname) - 1] = '\0'; 07474 } 07475 getdsnattr(buf, "timeout", busy, sizeof (busy)); 07476 sflag[0] = '\0'; 07477 nwflag[0] = '\0'; 07478 getdsnattr(buf, "stepapi", sflag, sizeof (sflag)); 07479 getdsnattr(buf, "nowchar", nwflag, sizeof (nwflag)); 07480 #else 07481 SQLGetPrivateProfileString(buf, "timeout", "1000", 07482 busy, sizeof (busy), ODBC_INI); 07483 SQLGetPrivateProfileString(buf, "database", "", 07484 dbname, sizeof (dbname), ODBC_INI); 07485 SQLGetPrivateProfileString(buf, "stepapi", "", 07486 sflag, sizeof (sflag), ODBC_INI); 07487 SQLGetPrivateProfileString(buf, "nowchar", "", 07488 nwflag, sizeof (nwflag), ODBC_INI); 07489 #endif 07490 #if defined(HAVE_SQLITETRACE) && HAVE_SQLITETRACE 07491 tracef[0] = '\0'; 07492 #ifdef WITHOUT_DRIVERMGR 07493 getsdnattr(buf, "tracefile", tracef, sizeof (tracef)); 07494 #else 07495 SQLGetPrivateProfileString(buf, "tracefile", "", 07496 tracef, sizeof (tracef), ODBC_INI); 07497 #endif 07498 if (tracef[0] != '\0') { 07499 d->trace = fopen(tracef, "a"); 07500 } 07501 #endif 07502 d->nowchar = getbool(nwflag); 07503 return dbopen(d, dbname, dsn, sflag, busy); 07504 } 07505 07506 #ifndef SQLITE_UTF8 07507 07519 SQLRETURN SQL_API 07520 SQLConnect(SQLHDBC dbc, SQLCHAR *dsn, SQLSMALLINT dsnLen, 07521 SQLCHAR *uid, SQLSMALLINT uidLen, 07522 SQLCHAR *pass, SQLSMALLINT passLen) 07523 { 07524 return drvconnect(dbc, dsn, dsnLen); 07525 } 07526 #endif 07527 07528 #ifdef SQLITE_UTF8 07529 07541 SQLRETURN SQL_API 07542 SQLConnectW(SQLHDBC dbc, SQLWCHAR *dsn, SQLSMALLINT dsnLen, 07543 SQLWCHAR *uid, SQLSMALLINT uidLen, 07544 SQLWCHAR *pass, SQLSMALLINT passLen) 07545 { 07546 char *dsna = NULL; 07547 SQLRETURN ret; 07548 07549 if (dsn) { 07550 dsna = uc_to_utf_c(dsn, dsnLen); 07551 if (!dsna) { 07552 DBC *d = (DBC *) dbc; 07553 07554 setstatd(d, -1, "out of memory", (*d->ov3) ? "HY000" : "S1000"); 07555 return SQL_ERROR; 07556 } 07557 } 07558 ret = drvconnect(dbc, dsna, SQL_NTS); 07559 uc_free(dsna); 07560 return ret; 07561 } 07562 #endif 07563 07570 SQLRETURN SQL_API 07571 SQLDisconnect(SQLHDBC dbc) 07572 { 07573 DBC *d; 07574 07575 if (dbc == SQL_NULL_HDBC) { 07576 return SQL_INVALID_HANDLE; 07577 } 07578 d = (DBC *) dbc; 07579 if (d->magic != DBC_MAGIC) { 07580 return SQL_INVALID_HANDLE; 07581 } 07582 if (d->intrans) { 07583 setstatd(d, -1, "incomplete transaction", "25000"); 07584 return SQL_ERROR; 07585 } 07586 if (d->vm_stmt) { 07587 vm_end(d->vm_stmt); 07588 } 07589 if (d->sqlite) { 07590 sqlite_close(d->sqlite); 07591 d->sqlite = NULL; 07592 } 07593 freep(&d->dbname); 07594 freep(&d->dsn); 07595 return SQL_SUCCESS; 07596 } 07597 07598 #if defined(WITHOUT_DRIVERMGR) || !defined(_WIN32) 07599 07613 static SQLRETURN 07614 drvdriverconnect(SQLHDBC dbc, SQLHWND hwnd, 07615 SQLCHAR *connIn, SQLSMALLINT connInLen, 07616 SQLCHAR *connOut, SQLSMALLINT connOutMax, 07617 SQLSMALLINT *connOutLen, SQLUSMALLINT drvcompl) 07618 { 07619 DBC *d; 07620 int len; 07621 char buf[SQL_MAX_MESSAGE_LENGTH], dbname[SQL_MAX_MESSAGE_LENGTH / 4]; 07622 char dsn[SQL_MAX_MESSAGE_LENGTH / 4], busy[SQL_MAX_MESSAGE_LENGTH / 4]; 07623 char sflag[32]; 07624 #if defined(HAVE_SQLITETRACE) && HAVE_SQLITETRACE 07625 char tracef[SQL_MAX_MESSAGE_LENGTH]; 07626 #endif 07627 07628 if (dbc == SQL_NULL_HDBC || hwnd != NULL) { 07629 return SQL_INVALID_HANDLE; 07630 } 07631 if (drvcompl != SQL_DRIVER_COMPLETE && 07632 drvcompl != SQL_DRIVER_COMPLETE_REQUIRED && 07633 drvcompl != SQL_DRIVER_PROMPT && 07634 drvcompl != SQL_DRIVER_NOPROMPT) { 07635 return SQL_NO_DATA; 07636 } 07637 d = (DBC *) dbc; 07638 if (d->sqlite) { 07639 setstatd(d, -1, "connection already established", "08002"); 07640 return SQL_ERROR; 07641 } 07642 buf[0] = '\0'; 07643 if (connInLen == SQL_NTS) { 07644 len = sizeof (buf) - 1; 07645 } else { 07646 len = min(connInLen, sizeof (buf) - 1); 07647 } 07648 if (connIn != NULL) { 07649 strncpy(buf, connIn, len); 07650 } 07651 buf[len] = '\0'; 07652 if (!buf[0]) { 07653 setstatd(d, -1, "invalid connect attributes", 07654 (*d->ov3) ? "HY090" : "S1090"); 07655 return SQL_ERROR; 07656 } 07657 dsn[0] = '\0'; 07658 getdsnattr(buf, "DSN", dsn, sizeof (dsn)); 07659 07660 /* special case: connIn is sole DSN value without keywords */ 07661 if (!dsn[0] && !strchr(buf, ';') && !strchr(buf, '=')) { 07662 strncpy(dsn, buf, sizeof (dsn) - 1); 07663 dsn[sizeof (dsn) - 1] = '\0'; 07664 } 07665 07666 busy[0] = '\0'; 07667 getdsnattr(buf, "timeout", busy, sizeof (busy)); 07668 #ifndef WITHOUT_DRIVERMGR 07669 if (dsn[0] && !busy[0]) { 07670 SQLGetPrivateProfileString(dsn, "timeout", "1000", 07671 busy, sizeof (busy), ODBC_INI); 07672 } 07673 #endif 07674 dbname[0] = '\0'; 07675 getdsnattr(buf, "database", dbname, sizeof (dbname)); 07676 #ifndef WITHOUT_DRIVERMGR 07677 if (dsn[0] && !dbname[0]) { 07678 SQLGetPrivateProfileString(dsn, "database", "", 07679 dbname, sizeof (dbname), ODBC_INI); 07680 } 07681 #endif 07682 sflag[0] = '\0'; 07683 getdsnattr(buf, "stepapi", sflag, sizeof (sflag)); 07684 #ifndef WITHOUT_DRIVERMGR 07685 if (dsn[0] && !sflag[0]) { 07686 SQLGetPrivateProfileString(dsn, "stepapi", "", 07687 sflag, sizeof (sflag), ODBC_INI); 07688 } 07689 #endif 07690 if (!dbname[0] && !dsn[0]) { 07691 strcpy(dsn, "SQLite"); 07692 strncpy(dbname, buf, sizeof (dbname)); 07693 dbname[sizeof (dbname) - 1] = '\0'; 07694 } 07695 #if defined(HAVE_SQLITETRACE) && HAVE_SQLITETRACE 07696 tracef[0] = '\0'; 07697 getdsnattr(buf, "tracefile", tracef, sizeof (tracef)); 07698 #ifndef WITHOUT_DRIVERMGR 07699 if (dsn[0] && !tracef[0]) { 07700 SQLGetPrivateProfileString(dsn, "tracefile", "", 07701 tracef, sizeof (tracef), ODBC_INI); 07702 } 07703 #endif 07704 #endif 07705 if (connOut || connOutLen) { 07706 int count; 07707 07708 buf[0] = '\0'; 07709 count = snprintf(buf, sizeof (buf), 07710 #if defined(HAVE_SQLITETRACE) && HAVE_SQLITETRACE 07711 "DSN=%s;Database=%s;StepAPI=%s;Timeout=%s;" 07712 "Tracefile=%s", 07713 dsn, dbname, sflag, busy, tracef 07714 #else 07715 "DSN=%s;Database=%s;StepAPI=%s;Timeout=%s", 07716 dsn, dbname, sflag, busy 07717 #endif 07718 ); 07719 if (count < 0) { 07720 buf[sizeof (buf) - 1] = '\0'; 07721 } 07722 len = min(connOutMax - 1, strlen(buf)); 07723 if (connOut) { 07724 strncpy(connOut, buf, len); 07725 connOut[len] = '\0'; 07726 } 07727 if (connOutLen) { 07728 *connOutLen = len; 07729 } 07730 } 07731 #if defined(HAVE_SQLITETRACE) && HAVE_SQLITETRACE 07732 if (tracef[0] != '\0') { 07733 d->trace = fopen(tracef, "a"); 07734 } 07735 #endif 07736 return dbopen(d, dbname, dsn, sflag, busy); 07737 } 07738 #endif 07739 07740 /* see doc on top */ 07741 07742 static SQLRETURN 07743 freestmt(SQLHSTMT stmt) 07744 { 07745 STMT *s; 07746 DBC *d; 07747 07748 if (stmt == SQL_NULL_HSTMT) { 07749 return SQL_INVALID_HANDLE; 07750 } 07751 s = (STMT *) stmt; 07752 freeresult(s, 1); 07753 freep(&s->query); 07754 d = (DBC *) s->dbc; 07755 if (d && d->magic == DBC_MAGIC) { 07756 STMT *p, *n; 07757 07758 p = NULL; 07759 n = d->stmt; 07760 while (n) { 07761 if (n == s) { 07762 break; 07763 } 07764 p = n; 07765 n = n->next; 07766 } 07767 if (n) { 07768 if (p) { 07769 p->next = s->next; 07770 } else { 07771 d->stmt = s->next; 07772 } 07773 } 07774 } 07775 freeparams(s); 07776 freep(&s->bindparms); 07777 if (s->row_status0 != &s->row_status1) { 07778 freep(&s->row_status0); 07779 s->rowset_size = 1; 07780 s->row_status0 = &s->row_status1; 07781 } 07782 xfree(s); 07783 return SQL_SUCCESS; 07784 } 07785 07793 static SQLRETURN 07794 drvallocstmt(SQLHDBC dbc, SQLHSTMT *stmt) 07795 { 07796 DBC *d; 07797 STMT *s, *sl, *pl; 07798 07799 if (dbc == SQL_NULL_HDBC) { 07800 return SQL_INVALID_HANDLE; 07801 } 07802 d = (DBC *) dbc; 07803 if (d->magic != DBC_MAGIC || stmt == NULL) { 07804 return SQL_INVALID_HANDLE; 07805 } 07806 s = (STMT *) xmalloc(sizeof (STMT)); 07807 if (s == NULL) { 07808 *stmt = SQL_NULL_HSTMT; 07809 return SQL_ERROR; 07810 } 07811 *stmt = (SQLHSTMT) s; 07812 memset(s, 0, sizeof (STMT)); 07813 s->dbc = dbc; 07814 s->ov3 = d->ov3; 07815 s->nowchar = d->nowchar; 07816 s->curtype = d->curtype; 07817 s->row_status0 = &s->row_status1; 07818 s->rowset_size = 1; 07819 s->bind_type = SQL_BIND_BY_COLUMN; 07820 s->paramset_size = 1; 07821 sprintf(s->cursorname, "CUR_%08lX", (long) *stmt); 07822 sl = d->stmt; 07823 pl = NULL; 07824 while (sl) { 07825 pl = sl; 07826 sl = sl->next; 07827 } 07828 if (pl) { 07829 pl->next = s; 07830 } else { 07831 d->stmt = s; 07832 } 07833 return SQL_SUCCESS; 07834 } 07835 07843 SQLRETURN SQL_API 07844 SQLAllocStmt(SQLHDBC dbc, SQLHSTMT *stmt) 07845 { 07846 return drvallocstmt(dbc, stmt); 07847 } 07848 07856 static SQLRETURN 07857 drvfreestmt(SQLHSTMT stmt, SQLUSMALLINT opt) 07858 { 07859 STMT *s; 07860 07861 if (stmt == SQL_NULL_HSTMT) { 07862 return SQL_INVALID_HANDLE; 07863 } 07864 s = (STMT *) stmt; 07865 switch (opt) { 07866 case SQL_RESET_PARAMS: 07867 freeparams(s); 07868 break; 07869 case SQL_UNBIND: 07870 unbindcols(s); 07871 break; 07872 case SQL_CLOSE: 07873 vm_end_if(s); 07874 freeresult(s, 0); 07875 break; 07876 case SQL_DROP: 07877 vm_end_if(s); 07878 return freestmt(stmt); 07879 default: 07880 setstat(s, -1, "unsupported option", (*s->ov3) ? "HYC00" : "S1C00"); 07881 return SQL_ERROR; 07882 } 07883 return SQL_SUCCESS; 07884 } 07885 07893 SQLRETURN SQL_API 07894 SQLFreeStmt(SQLHSTMT stmt, SQLUSMALLINT opt) 07895 { 07896 return drvfreestmt(stmt, opt); 07897 } 07898 07905 SQLRETURN SQL_API 07906 SQLCancel(SQLHSTMT stmt) 07907 { 07908 return drvfreestmt(stmt, SQL_CLOSE); 07909 } 07910 07920 static SQLRETURN 07921 drvgetcursorname(SQLHSTMT stmt, SQLCHAR *cursor, SQLSMALLINT buflen, 07922 SQLSMALLINT *lenp) 07923 { 07924 STMT *s; 07925 07926 if (stmt == SQL_NULL_HSTMT) { 07927 return SQL_INVALID_HANDLE; 07928 } 07929 s = (STMT *) stmt; 07930 if (lenp && !cursor) { 07931 *lenp = strlen(s->cursorname); 07932 return SQL_SUCCESS; 07933 } 07934 if (cursor) { 07935 if (buflen > 0) { 07936 strncpy(cursor, s->cursorname, buflen - 1); 07937 cursor[buflen - 1] = '\0'; 07938 } 07939 if (lenp) { 07940 *lenp = min(strlen(s->cursorname), buflen - 1); 07941 } 07942 } 07943 return SQL_SUCCESS; 07944 } 07945 07946 #ifndef SQLITE_UTF8 07947 07956 SQLRETURN SQL_API 07957 SQLGetCursorName(SQLHSTMT stmt, SQLCHAR *cursor, SQLSMALLINT buflen, 07958 SQLSMALLINT *lenp) 07959 { 07960 return drvgetcursorname(stmt, cursor, buflen, lenp); 07961 } 07962 #endif 07963 07964 #ifdef SQLITE_UTF8 07965 07974 SQLRETURN SQL_API 07975 SQLGetCursorNameW(SQLHSTMT stmt, SQLWCHAR *cursor, SQLSMALLINT buflen, 07976 SQLSMALLINT *lenp) 07977 { 07978 SQLRETURN ret; 07979 SQLSMALLINT len; 07980 07981 ret = drvgetcursorname(stmt, (SQLCHAR *) cursor, buflen, &len); 07982 if (ret == SQL_SUCCESS) { 07983 SQLWCHAR *c = NULL; 07984 07985 if (cursor) { 07986 c = uc_from_utf((char *) cursor, len); 07987 if (!c) { 07988 return nomem((STMT *) stmt); 07989 } 07990 len = uc_strlen(c); 07991 if (buflen > 0) { 07992 uc_strncpy(cursor, c, buflen - 1); 07993 cursor[buflen - 1] = 0; 07994 } 07995 uc_free(c); 07996 } 07997 if (lenp) { 07998 *lenp = min(len, buflen - 1); 07999 } 08000 } 08001 return ret; 08002 } 08003 #endif 08004 08013 static SQLRETURN 08014 drvsetcursorname(SQLHSTMT stmt, SQLCHAR *cursor, SQLSMALLINT len) 08015 { 08016 STMT *s; 08017 08018 if (stmt == SQL_NULL_HSTMT) { 08019 return SQL_INVALID_HANDLE; 08020 } 08021 s = (STMT *) stmt; 08022 if (!cursor || 08023 !((cursor[0] >= 'A' && cursor[0] <= 'Z') || 08024 (cursor[0] >= 'a' && cursor[0] <= 'z'))) { 08025 setstat(s, -1, "invalid cursor name", (*s->ov3) ? "HYC00" : "S1C00"); 08026 return SQL_ERROR; 08027 } 08028 if (len == SQL_NTS) { 08029 len = sizeof (s->cursorname) - 1; 08030 } else { 08031 len = min(sizeof (s->cursorname) - 1, len); 08032 } 08033 strncpy(s->cursorname, cursor, len); 08034 s->cursorname[len] = '\0'; 08035 return SQL_SUCCESS; 08036 } 08037 08038 #ifndef SQLITE_UTF8 08039 08047 SQLRETURN SQL_API 08048 SQLSetCursorName(SQLHSTMT stmt, SQLCHAR *cursor, SQLSMALLINT len) 08049 { 08050 return drvsetcursorname(stmt, cursor, len); 08051 } 08052 #endif 08053 08054 #ifdef SQLITE_UTF8 08055 08063 SQLRETURN SQL_API 08064 SQLSetCursorNameW(SQLHSTMT stmt, SQLWCHAR *cursor, SQLSMALLINT len) 08065 { 08066 char *c = NULL; 08067 SQLRETURN ret; 08068 08069 if (cursor) { 08070 c = uc_to_utf_c(cursor, len); 08071 if (!c) { 08072 return nomem((STMT *) stmt); 08073 } 08074 } 08075 ret = drvsetcursorname(stmt, c, SQL_NTS); 08076 uc_free(c); 08077 return ret; 08078 } 08079 #endif 08080 08087 SQLRETURN SQL_API 08088 SQLCloseCursor(SQLHSTMT stmt) 08089 { 08090 return drvfreestmt(stmt, SQL_CLOSE); 08091 } 08092 08093 #if defined(WITHOUT_DRIVERMGR) || !defined(HAVE_IODBC) || defined(_WIN32) 08094 08103 SQLRETURN SQL_API 08104 SQLAllocHandle(SQLSMALLINT type, SQLHANDLE input, SQLHANDLE *output) 08105 { 08106 SQLRETURN ret; 08107 08108 switch (type) { 08109 case SQL_HANDLE_ENV: 08110 ret = drvallocenv((SQLHENV *) output); 08111 if (ret == SQL_SUCCESS) { 08112 ENV *e = (ENV *) *output; 08113 08114 if (e && e->magic == ENV_MAGIC) { 08115 e->ov3 = 1; 08116 } 08117 } 08118 return ret; 08119 case SQL_HANDLE_DBC: 08120 return drvallocconnect((SQLHENV) input, (SQLHDBC *) output); 08121 case SQL_HANDLE_STMT: 08122 return drvallocstmt((SQLHDBC) input, (SQLHSTMT *) output); 08123 } 08124 return SQL_ERROR; 08125 } 08126 #endif 08127 08128 #if defined(WITHOUT_DRIVERMGR) || !defined(HAVE_IODBC) || defined(_WIN32) 08129 08137 SQLRETURN SQL_API 08138 SQLFreeHandle(SQLSMALLINT type, SQLHANDLE h) 08139 { 08140 switch (type) { 08141 case SQL_HANDLE_ENV: 08142 return drvfreeenv((SQLHENV) h); 08143 case SQL_HANDLE_DBC: 08144 return drvfreeconnect((SQLHDBC) h); 08145 case SQL_HANDLE_STMT: 08146 return drvfreestmt((SQLHSTMT) h, SQL_DROP); 08147 } 08148 return SQL_ERROR; 08149 } 08150 #endif 08151 08157 static void 08158 freedyncols(STMT *s) 08159 { 08160 if (s->dyncols) { 08161 int i; 08162 08163 for (i = 0; i < s->dcols; i++) { 08164 freep(&s->dyncols[i].typename); 08165 } 08166 if (s->cols == s->dyncols) { 08167 s->cols = NULL; 08168 s->ncols = 0; 08169 } 08170 freep(&s->dyncols); 08171 } 08172 s->dcols = 0; 08173 } 08174 08175 /* see doc on top */ 08176 08177 static void 08178 freeresult(STMT *s, int clrcols) 08179 { 08180 #if HAVE_ENCDEC 08181 freep(&s->bincache); 08182 freep(&s->hexcache); 08183 s->bincell = NULL; 08184 #endif 08185 if (s->rows) { 08186 if (s->rowfree) { 08187 s->rowfree(s->rows); 08188 s->rowfree = NULL; 08189 } 08190 s->rows = NULL; 08191 } 08192 s->nrows = -1; 08193 if (clrcols > 0) { 08194 freep(&s->bindcols); 08195 s->nbindcols = 0; 08196 } 08197 if (clrcols) { 08198 freedyncols(s); 08199 s->cols = NULL; 08200 s->ncols = 0; 08201 } 08202 } 08203 08204 /* see doc on top */ 08205 08206 static void 08207 unbindcols(STMT *s) 08208 { 08209 int i; 08210 08211 s->bkmrkcol.type = -1; 08212 s->bkmrkcol.max = 0; 08213 s->bkmrkcol.lenp = NULL; 08214 s->bkmrkcol.valp = NULL; 08215 s->bkmrkcol.index = 0; 08216 s->bkmrkcol.offs = 0; 08217 for (i = 0; s->bindcols && i < s->nbindcols; i++) { 08218 s->bindcols[i].type = -1; 08219 s->bindcols[i].max = 0; 08220 s->bindcols[i].lenp = NULL; 08221 s->bindcols[i].valp = NULL; 08222 s->bindcols[i].index = i; 08223 s->bindcols[i].offs = 0; 08224 } 08225 } 08226 08227 /* see doc on top */ 08228 08229 static SQLRETURN 08230 mkbindcols(STMT *s, int ncols) 08231 { 08232 if (s->bindcols) { 08233 if (s->nbindcols < ncols) { 08234 int i; 08235 BINDCOL *bindcols = 08236 xrealloc(s->bindcols, ncols * sizeof (BINDCOL)); 08237 08238 if (!bindcols) { 08239 return nomem(s); 08240 } 08241 for (i = s->nbindcols; i < ncols; i++) { 08242 bindcols[i].type = -1; 08243 bindcols[i].max = 0; 08244 bindcols[i].lenp = NULL; 08245 bindcols[i].valp = NULL; 08246 bindcols[i].index = i; 08247 bindcols[i].offs = 0; 08248 } 08249 s->bindcols = bindcols; 08250 s->nbindcols = ncols; 08251 } 08252 } else if (ncols > 0) { 08253 s->bindcols = (BINDCOL *) xmalloc(ncols * sizeof (BINDCOL)); 08254 if (!s->bindcols) { 08255 return nomem(s); 08256 } 08257 s->nbindcols = ncols; 08258 unbindcols(s); 08259 } 08260 return SQL_SUCCESS; 08261 } 08262 08276 static SQLRETURN 08277 getrowdata(STMT *s, SQLUSMALLINT col, SQLSMALLINT otype, 08278 SQLPOINTER val, SQLINTEGER len, SQLINTEGER *lenp, int partial) 08279 { 08280 char **data, valdummy[16]; 08281 SQLINTEGER dummy; 08282 int valnull = 0; 08283 int type = otype; 08284 08285 if (!s->rows) { 08286 return SQL_NO_DATA; 08287 } 08288 if (col >= s->ncols) { 08289 setstat(s, -1, "invalid column", (*s->ov3) ? "07009" : "S1002"); 08290 return SQL_ERROR; 08291 } 08292 if (s->rowp < 0 || s->rowp >= s->nrows) { 08293 return SQL_NO_DATA; 08294 } 08295 type = mapdeftype(type, s->cols[col].type, s->cols[col].nosign ? 1 : 0, 08296 s->nowchar); 08297 #if HAVE_ENCDEC 08298 if (otype == SQL_C_CHAR) { 08299 switch (s->cols[col].type) { 08300 case SQL_BINARY: 08301 case SQL_VARBINARY: 08302 case SQL_LONGVARBINARY: 08303 type = SQL_C_BINARY; 08304 break; 08305 } 08306 #ifdef SQLITE_UTF8 08307 } else if (otype == SQL_C_WCHAR) { 08308 switch (s->cols[col].type) { 08309 case SQL_BINARY: 08310 case SQL_VARBINARY: 08311 case SQL_LONGVARBINARY: 08312 type = SQL_C_BINARY; 08313 break; 08314 } 08315 #endif 08316 } 08317 #endif 08318 data = s->rows + s->ncols + (s->rowp * s->ncols) + col; 08319 if (!lenp) { 08320 lenp = &dummy; 08321 } 08322 if (!val) { 08323 valnull = 1; 08324 val = (SQLPOINTER) valdummy; 08325 } 08326 if (*data == NULL) { 08327 *lenp = SQL_NULL_DATA; 08328 switch (type) { 08329 case SQL_C_UTINYINT: 08330 case SQL_C_TINYINT: 08331 case SQL_C_STINYINT: 08332 *((char *) val) = 0; 08333 break; 08334 case SQL_C_USHORT: 08335 case SQL_C_SHORT: 08336 case SQL_C_SSHORT: 08337 *((short *) val) = 0; 08338 break; 08339 case SQL_C_ULONG: 08340 case SQL_C_LONG: 08341 case SQL_C_SLONG: 08342 *((long *) val) = 0; 08343 break; 08344 case SQL_C_FLOAT: 08345 *((float *) val) = 0; 08346 break; 08347 case SQL_C_DOUBLE: 08348 *((double *) val) = 0; 08349 break; 08350 case SQL_C_BINARY: 08351 case SQL_C_CHAR: 08352 #ifdef SQLITE_UTF8 08353 case SQL_C_WCHAR: 08354 if (otype == SQL_C_WCHAR) { 08355 *((SQLWCHAR *) val) = '\0'; 08356 } else { 08357 *((char *) val) = '\0'; 08358 } 08359 #else 08360 *((char *) val) = '\0'; 08361 #endif 08362 break; 08363 #ifdef SQL_C_TYPE_DATE 08364 case SQL_C_TYPE_DATE: 08365 #endif 08366 case SQL_C_DATE: 08367 memset((DATE_STRUCT *) val, 0, sizeof (DATE_STRUCT)); 08368 break; 08369 #ifdef SQL_C_TYPE_TIME 08370 case SQL_C_TYPE_TIME: 08371 #endif 08372 case SQL_C_TIME: 08373 memset((TIME_STRUCT *) val, 0, sizeof (TIME_STRUCT)); 08374 break; 08375 #ifdef SQL_C_TYPE_TIMESTAMP 08376 case SQL_C_TYPE_TIMESTAMP: 08377 #endif 08378 case SQL_C_TIMESTAMP: 08379 memset((TIMESTAMP_STRUCT *) val, 0, sizeof (TIMESTAMP_STRUCT)); 08380 break; 08381 default: 08382 return SQL_ERROR; 08383 } 08384 } else { 08385 char *endp = NULL; 08386 08387 switch (type) { 08388 case SQL_C_UTINYINT: 08389 case SQL_C_TINYINT: 08390 case SQL_C_STINYINT: 08391 *((char *) val) = strtol(*data, &endp, 0); 08392 if (endp && endp == *data) { 08393 *lenp = SQL_NULL_DATA; 08394 } else { 08395 *lenp = sizeof (char); 08396 } 08397 break; 08398 case SQL_C_USHORT: 08399 case SQL_C_SHORT: 08400 case SQL_C_SSHORT: 08401 *((short *) val) = strtol(*data, &endp, 0); 08402 if (endp && endp == *data) { 08403 *lenp = SQL_NULL_DATA; 08404 } else { 08405 *lenp = sizeof (short); 08406 } 08407 break; 08408 case SQL_C_ULONG: 08409 case SQL_C_LONG: 08410 case SQL_C_SLONG: 08411 *((int *) val) = strtol(*data, &endp, 0); 08412 if (endp && endp == *data) { 08413 *lenp = SQL_NULL_DATA; 08414 } else { 08415 *lenp = sizeof (int); 08416 } 08417 break; 08418 case SQL_C_FLOAT: 08419 *((float *) val) = ln_strtod(*data, &endp); 08420 if (endp && endp == *data) { 08421 *lenp = SQL_NULL_DATA; 08422 } else { 08423 *lenp = sizeof (float); 08424 } 08425 break; 08426 case SQL_C_DOUBLE: 08427 *((double *) val) = ln_strtod(*data, &endp); 08428 if (endp && endp == *data) { 08429 *lenp = SQL_NULL_DATA; 08430 } else { 08431 *lenp = sizeof (double); 08432 } 08433 break; 08434 case SQL_C_BINARY: 08435 #if HAVE_ENCDEC 08436 { 08437 int dlen, offs = 0; 08438 char *bin, *hex = NULL; 08439 08440 if (*data == s->bincell && s->bincache) { 08441 bin = s->bincache; 08442 dlen = s->binlen; 08443 } else { 08444 freep(&s->bincache); 08445 freep(&s->hexcache); 08446 s->bincell = NULL; 08447 dlen = strlen(*data); 08448 bin = xmalloc(dlen + 1); 08449 if (!bin) { 08450 return nomem(s); 08451 } 08452 dlen = sqlite_decode_binary(*data, bin); 08453 if (dlen < 0) { 08454 freep(&bin); 08455 setstat(s, -1, "error decoding binary data", 08456 (*s->ov3) ? "HY000" : "S1000"); 08457 return SQL_ERROR; 08458 } 08459 s->bincache = bin; 08460 s->binlen = dlen; 08461 s->bincell = *data; 08462 } 08463 #ifdef SQLITE_UTF8 08464 if (otype == SQL_C_CHAR || otype == SQL_C_WCHAR) { 08465 #else 08466 if (otype == SQL_C_CHAR) { 08467 #endif 08468 if (s->hexcache) { 08469 hex = s->hexcache; 08470 } else { 08471 int i, k; 08472 08473 hex = xmalloc(dlen * 2 + 1); 08474 if (!hex) { 08475 return nomem(s); 08476 } 08477 for (i = 0, k = 0; i < dlen; i++) { 08478 hex[k++] = hexdigits[(bin[i] >> 4) & 0x0f]; 08479 hex[k++] = hexdigits[bin[i] & 0x0f]; 08480 } 08481 hex[k] = '\0'; 08482 s->hexcache = hex; 08483 } 08484 } 08485 if (otype == SQL_C_CHAR) { 08486 bin = hex; 08487 dlen = dlen * 2; 08488 } 08489 #ifdef SQLITE_UTF8 08490 else if (otype == SQL_C_WCHAR) { 08491 bin = hex; 08492 dlen = dlen * 2 * sizeof (SQLWCHAR); 08493 } 08494 #endif 08495 if (partial && len && s->bindcols) { 08496 if (dlen && s->bindcols[col].offs >= dlen) { 08497 s->bindcols[col].offs = 0; 08498 return SQL_NO_DATA; 08499 } 08500 offs = s->bindcols[col].offs; 08501 dlen -= offs; 08502 } 08503 if (val && !valnull && len) { 08504 int max = min(len, dlen); 08505 08506 #ifdef SQLITE_UTF8 08507 if (otype == SQL_C_WCHAR) { 08508 int i; 08509 SQLWCHAR *valw = (SQLWCHAR *) val; 08510 08511 for (i = 0; i < max; i++) { 08512 valw[i] = bin[i + offs]; 08513 } 08514 } else 08515 #endif 08516 memcpy(val, bin + offs, max); 08517 } 08518 if (valnull || len < 1) { 08519 *lenp = dlen; 08520 } else { 08521 *lenp = min(len, dlen); 08522 if (*lenp == len && *lenp != dlen) { 08523 *lenp = SQL_NO_TOTAL; 08524 } 08525 } 08526 if (!valnull) { 08527 if (otype == SQL_C_CHAR) { 08528 ((char *) val)[len - 1] = '\0'; 08529 } 08530 #ifdef SQLITE_UTF8 08531 else if (otype == SQL_C_WCHAR) { 08532 ((SQLWCHAR *) val)[len / sizeof (SQLWCHAR) - 1] = 0; 08533 } 08534 #endif 08535 } 08536 if (partial && len && s->bindcols) { 08537 if (*lenp == SQL_NO_TOTAL) { 08538 s->bindcols[col].offs += len; 08539 setstat(s, -1, "data right truncated", "01004"); 08540 if (s->bindcols[col].lenp) { 08541 *s->bindcols[col].lenp = dlen; 08542 } 08543 return SQL_SUCCESS_WITH_INFO; 08544 } 08545 s->bindcols[col].offs += *lenp; 08546 } 08547 break; 08548 } 08549 #endif 08550 #ifdef SQLITE_UTF8 08551 case SQL_C_WCHAR: 08552 #endif 08553 case SQL_C_CHAR: { 08554 int doz; 08555 int dlen = strlen(*data); 08556 int offs = 0; 08557 08558 #ifdef SQLITE_UTF8 08559 SQLWCHAR *ucdata = NULL; 08560 08561 doz = (type == SQL_C_CHAR || type == SQL_C_WCHAR) ? 1 : 0; 08562 if (otype == SQL_C_WCHAR) { 08563 ucdata = uc_from_utf(*data, dlen); 08564 if (!ucdata) { 08565 return nomem(s); 08566 } 08567 dlen = uc_strlen(ucdata) * sizeof (SQLWCHAR); 08568 } 08569 #else 08570 doz = type == SQL_C_CHAR ? 1 : 0; 08571 #endif 08572 if (partial && len && s->bindcols) { 08573 if (dlen && s->bindcols[col].offs >= dlen) { 08574 s->bindcols[col].offs = 0; 08575 #ifdef SQLITE_UTF8 08576 uc_free(ucdata); 08577 #endif 08578 return SQL_NO_DATA; 08579 } 08580 offs = s->bindcols[col].offs; 08581 dlen -= offs; 08582 } 08583 if (val && !valnull && len) { 08584 #ifdef SQLITE_UTF8 08585 if (otype == SQL_C_WCHAR) { 08586 uc_strncpy(val, ucdata + offs / sizeof (SQLWCHAR), 08587 (len - doz) / sizeof (SQLWCHAR)); 08588 } else { 08589 strncpy(val, *data + offs, len - doz); 08590 } 08591 #else 08592 strncpy(val, *data + offs, len - doz); 08593 #endif 08594 } 08595 if (valnull || len < 1) { 08596 *lenp = dlen; 08597 } else { 08598 *lenp = min(len - doz, dlen); 08599 if (*lenp == len - doz && *lenp != dlen) { 08600 *lenp = SQL_NO_TOTAL; 08601 } 08602 } 08603 if (len && !valnull && doz) { 08604 #ifdef SQLITE_UTF8 08605 if (otype == SQL_C_WCHAR) { 08606 ((SQLWCHAR *) val)[len / sizeof (SQLWCHAR) - 1] = 0; 08607 } else { 08608 ((char *) val)[len - 1] = '\0'; 08609 } 08610 #else 08611 ((char *) val)[len - 1] = '\0'; 08612 #endif 08613 } 08614 #ifdef SQLITE_UTF8 08615 uc_free(ucdata); 08616 #endif 08617 if (partial && len && s->bindcols) { 08618 if (*lenp == SQL_NO_TOTAL) { 08619 s->bindcols[col].offs += len - doz; 08620 setstat(s, -1, "data right truncated", "01004"); 08621 if (s->bindcols[col].lenp) { 08622 *s->bindcols[col].lenp = dlen; 08623 } 08624 return SQL_SUCCESS_WITH_INFO; 08625 } 08626 s->bindcols[col].offs += *lenp; 08627 } 08628 break; 08629 } 08630 #ifdef SQL_C_TYPE_DATE 08631 case SQL_C_TYPE_DATE: 08632 #endif 08633 case SQL_C_DATE: 08634 if (str2date(*data, (DATE_STRUCT *) val) < 0) { 08635 *lenp = SQL_NULL_DATA; 08636 } else { 08637 *lenp = sizeof (DATE_STRUCT); 08638 } 08639 break; 08640 #ifdef SQL_C_TYPE_TIME 08641 case SQL_C_TYPE_TIME: 08642 #endif 08643 case SQL_C_TIME: 08644 if (str2time(*data, (TIME_STRUCT *) val) < 0) { 08645 *lenp = SQL_NULL_DATA; 08646 } else { 08647 *lenp = sizeof (TIME_STRUCT); 08648 } 08649 break; 08650 #ifdef SQL_C_TYPE_TIMESTAMP 08651 case SQL_C_TYPE_TIMESTAMP: 08652 #endif 08653 case SQL_C_TIMESTAMP: 08654 if (str2timestamp(*data, (TIMESTAMP_STRUCT *) val) < 0) { 08655 *lenp = SQL_NULL_DATA; 08656 } else { 08657 *lenp = sizeof (TIMESTAMP_STRUCT); 08658 } 08659 break; 08660 default: 08661 return SQL_ERROR; 08662 } 08663 } 08664 return SQL_SUCCESS; 08665 } 08666 08678 SQLRETURN SQL_API 08679 SQLBindCol(SQLHSTMT stmt, SQLUSMALLINT col, SQLSMALLINT type, 08680 SQLPOINTER val, SQLINTEGER max, SQLINTEGER *lenp) 08681 { 08682 STMT *s; 08683 08684 if (stmt == SQL_NULL_HSTMT) { 08685 return SQL_INVALID_HANDLE; 08686 } 08687 s = (STMT *) stmt; 08688 if (col < 1) { 08689 if (col == 0 && s->bkmrk && type == SQL_C_BOOKMARK) { 08690 s->bkmrkcol.type = type; 08691 s->bkmrkcol.max = max; 08692 s->bkmrkcol.lenp = lenp; 08693 s->bkmrkcol.valp = val; 08694 s->bkmrkcol.offs = 0; 08695 if (lenp) { 08696 *lenp = 0; 08697 } 08698 return SQL_SUCCESS; 08699 } 08700 setstat(s, -1, "invalid column", (*s->ov3) ? "07009" : "S1002"); 08701 return SQL_ERROR; 08702 } 08703 if (mkbindcols(s, col) != SQL_SUCCESS) { 08704 return SQL_ERROR; 08705 } 08706 --col; 08707 if (type == SQL_C_DEFAULT) { 08708 type = mapdeftype(type, s->cols[col].type, 0, s->nowchar); 08709 } else { 08710 switch (type) { 08711 case SQL_C_LONG: 08712 case SQL_C_ULONG: 08713 case SQL_C_SLONG: 08714 case SQL_C_TINYINT: 08715 case SQL_C_UTINYINT: 08716 case SQL_C_STINYINT: 08717 case SQL_C_SHORT: 08718 case SQL_C_USHORT: 08719 case SQL_C_SSHORT: 08720 case SQL_C_FLOAT: 08721 case SQL_C_DOUBLE: 08722 case SQL_C_TIMESTAMP: 08723 case SQL_C_TIME: 08724 case SQL_C_DATE: 08725 case SQL_C_CHAR: 08726 #ifdef SQLITE_UTF8 08727 case SQL_C_WCHAR: 08728 #endif 08729 #ifdef SQL_C_TYPE_DATE 08730 case SQL_C_TYPE_DATE: 08731 #endif 08732 #ifdef SQL_C_TYPE_TIME 08733 case SQL_C_TYPE_TIME: 08734 #endif 08735 #ifdef SQL_C_TYPE_TIMESTAMP 08736 case SQL_C_TYPE_TIMESTAMP: 08737 #endif 08738 break; 08739 #if HAVE_ENCDEC 08740 case SQL_C_BINARY: 08741 break; 08742 #endif 08743 default: 08744 setstat(s, -1, "invalid type %d", "HY003", type); 08745 return SQL_ERROR; 08746 } 08747 } 08748 if (max < 0) { 08749 setstat(s, -1, "invalid length", "HY090"); 08750 return SQL_ERROR; 08751 } 08752 s->bindcols[col].type = type; 08753 s->bindcols[col].max = max; 08754 s->bindcols[col].lenp = lenp; 08755 s->bindcols[col].valp = val; 08756 s->bindcols[col].offs = 0; 08757 if (lenp) { 08758 *lenp = 0; 08759 } 08760 return SQL_SUCCESS; 08761 } 08762 08767 static COL tableSpec[] = { 08768 { "SYSTEM", "COLUMN", "TABLE_QUALIFIER", SCOL_VARCHAR, 50 }, 08769 { "SYSTEM", "COLUMN", "TABLE_OWNER", SCOL_VARCHAR, 50 }, 08770 { "SYSTEM", "COLUMN", "TABLE_NAME", SCOL_VARCHAR, 255 }, 08771 { "SYSTEM", "COLUMN", "TABLE_TYPE", SCOL_VARCHAR, 50 }, 08772 { "SYSTEM", "COLUMN", "REMARKS", SCOL_VARCHAR, 50 } 08773 }; 08774 08789 static SQLRETURN 08790 drvtables(SQLHSTMT stmt, 08791 SQLCHAR *cat, SQLSMALLINT catLen, 08792 SQLCHAR *schema, SQLSMALLINT schemaLen, 08793 SQLCHAR *table, SQLSMALLINT tableLen, 08794 SQLCHAR *type, SQLSMALLINT typeLen) 08795 { 08796 SQLRETURN ret; 08797 STMT *s; 08798 DBC *d; 08799 int ncols, rc; 08800 char *errp = NULL, tname[512]; 08801 char *where = "(type = 'table' or type = 'view')"; 08802 08803 ret = mkresultset(stmt, tableSpec, array_size(tableSpec)); 08804 if (ret != SQL_SUCCESS) { 08805 return ret; 08806 } 08807 s = (STMT *) stmt; 08808 d = (DBC *) s->dbc; 08809 if (type && (typeLen > 0 || typeLen == SQL_NTS) && type[0] == '%') { 08810 int size = 3 * array_size(tableSpec); 08811 08812 s->rows = xmalloc(size * sizeof (char *)); 08813 if (!s->rows) { 08814 s->nrows = 0; 08815 return nomem(s); 08816 } 08817 memset(s->rows, 0, sizeof (char *) * size); 08818 s->ncols = array_size(tableSpec); 08819 s->rows[s->ncols + 0] = ""; 08820 s->rows[s->ncols + 1] = ""; 08821 s->rows[s->ncols + 2] = ""; 08822 s->rows[s->ncols + 3] = "TABLE"; 08823 s->rows[s->ncols + 5] = ""; 08824 s->rows[s->ncols + 6] = ""; 08825 s->rows[s->ncols + 7] = ""; 08826 s->rows[s->ncols + 8] = "VIEW"; 08827 #ifdef MEMORY_DEBUG 08828 s->rowfree = xfree__; 08829 #else 08830 s->rowfree = free; 08831 #endif 08832 s->nrows = 2; 08833 s->rowp = -1; 08834 return SQL_SUCCESS; 08835 } 08836 if (cat && (catLen > 0 || catLen == SQL_NTS) && cat[0] == '%') { 08837 int size = 2 * array_size(tableSpec); 08838 08839 s->rows = xmalloc(size * sizeof (char *)); 08840 if (!s->rows) { 08841 s->nrows = 0; 08842 return nomem(s); 08843 } 08844 memset(s->rows, 0, sizeof (char *) * size); 08845 s->ncols = array_size(tableSpec); 08846 s->rows[s->ncols + 0] = ""; 08847 s->rows[s->ncols + 1] = ""; 08848 s->rows[s->ncols + 2] = d->dbname; 08849 s->rows[s->ncols + 3] = "CATALOG"; 08850 #ifdef MEMORY_DEBUG 08851 s->rowfree = xfree__; 08852 #else 08853 s->rowfree = free; 08854 #endif 08855 s->nrows = 1; 08856 s->rowp = -1; 08857 return SQL_SUCCESS; 08858 } 08859 if (schema && (schemaLen > 0 || schemaLen == SQL_NTS) && 08860 schema[0] == '%') { 08861 if ((!cat || catLen == 0 || !cat[0]) && 08862 (!table || tableLen == 0 || !table[0])) { 08863 int size = 2 * array_size(tableSpec); 08864 08865 s->rows = xmalloc(size * sizeof (char *)); 08866 if (!s->rows) { 08867 s->nrows = 0; 08868 return nomem(s); 08869 } 08870 memset(s->rows, 0, sizeof (char *) * size); 08871 s->ncols = array_size(tableSpec); 08872 s->rows[s->ncols + 1] = ""; 08873 #ifdef MEMORY_DEBUG 08874 s->rowfree = xfree__; 08875 #else 08876 s->rowfree = free; 08877 #endif 08878 s->nrows = 1; 08879 s->rowp = -1; 08880 return SQL_SUCCESS; 08881 } 08882 } 08883 if (type) { 08884 char tmp[256], *t; 08885 int with_view = 0, with_table = 0; 08886 08887 if (typeLen == SQL_NTS) { 08888 strncpy(tmp, type, sizeof (tmp)); 08889 tmp[sizeof (tmp) - 1] = '\0'; 08890 } else { 08891 int len = min(sizeof (tmp) - 1, typeLen); 08892 08893 strncpy(tmp, type, len); 08894 tmp[len] = '\0'; 08895 } 08896 t = tmp; 08897 while (*t) { 08898 *t = TOLOWER(*t); 08899 t++; 08900 } 08901 t = tmp; 08902 while (t) { 08903 if (t[0] == '\'') { 08904 ++t; 08905 } 08906 if (strncmp(t, "table", 5) == 0) { 08907 with_table++; 08908 } else if (strncmp(t, "view", 4) == 0) { 08909 with_view++; 08910 } 08911 t = strchr(t, ','); 08912 if (t) { 08913 ++t; 08914 } 08915 } 08916 if (with_view && with_table) { 08917 /* where is already preset */ 08918 } else if (with_view && !with_table) { 08919 where = "type = 'view'"; 08920 } else if (!with_view && with_table) { 08921 where = "type = 'table'"; 08922 } else { 08923 s->rowp = -1; 08924 return SQL_SUCCESS; 08925 } 08926 } 08927 strcpy(tname, "%"); 08928 if (table && (tableLen > 0 || tableLen == SQL_NTS) && table[0] != '%') { 08929 int size; 08930 08931 if (tableLen == SQL_NTS) { 08932 size = sizeof (tname) - 1; 08933 } else { 08934 size = min(sizeof (tname) - 1, tableLen); 08935 } 08936 strncpy(tname, table, size); 08937 tname[size] = '\0'; 08938 } 08939 rc = sqlite_get_table_printf(d->sqlite, 08940 "select '' as 'TABLE_QUALIFIER', " 08941 "'' as 'TABLE_OWNER', " 08942 "tbl_name as 'TABLE_NAME', " 08943 "upper(type) as 'TABLE_TYPE', " 08944 "NULL as 'REMARKS' " 08945 "from sqlite_master where %s" 08946 "and tbl_name like '%q'", 08947 &s->rows, &s->nrows, &ncols, &errp, 08948 where, tname); 08949 if (rc == SQLITE_OK) { 08950 if (ncols != s->ncols) { 08951 freeresult(s, 0); 08952 s->nrows = 0; 08953 } else { 08954 s->rowfree = sqlite_free_table; 08955 } 08956 } else { 08957 s->nrows = 0; 08958 s->rows = NULL; 08959 s->rowfree = NULL; 08960 } 08961 if (errp) { 08962 sqlite_freemem(errp); 08963 errp = NULL; 08964 } 08965 s->rowp = -1; 08966 return SQL_SUCCESS; 08967 } 08968 08969 #ifndef SQLITE_UTF8 08970 08984 SQLRETURN SQL_API 08985 SQLTables(SQLHSTMT stmt, 08986 SQLCHAR *cat, SQLSMALLINT catLen, 08987 SQLCHAR *schema, SQLSMALLINT schemaLen, 08988 SQLCHAR *table, SQLSMALLINT tableLen, 08989 SQLCHAR *type, SQLSMALLINT typeLen) 08990 { 08991 return drvtables(stmt, cat, catLen, schema, schemaLen, 08992 table, tableLen, type, typeLen); 08993 } 08994 #endif 08995 08996 #ifdef SQLITE_UTF8 08997 09011 SQLRETURN SQL_API 09012 SQLTablesW(SQLHSTMT stmt, 09013 SQLWCHAR *cat, SQLSMALLINT catLen, 09014 SQLWCHAR *schema, SQLSMALLINT schemaLen, 09015 SQLWCHAR *table, SQLSMALLINT tableLen, 09016 SQLWCHAR *type, SQLSMALLINT typeLen) 09017 { 09018 char *c = NULL, *s = NULL, *t = NULL, *y = NULL; 09019 SQLRETURN ret; 09020 09021 if (cat) { 09022 c = uc_to_utf_c(cat, catLen); 09023 if (!c) { 09024 ret = nomem((STMT *) stmt); 09025 goto done; 09026 } 09027 } 09028 if (schema) { 09029 s = uc_to_utf_c(schema, schemaLen); 09030 if (!s) { 09031 ret = nomem((STMT *) stmt); 09032 goto done; 09033 } 09034 } 09035 if (table) { 09036 t = uc_to_utf_c(table, tableLen); 09037 if (!t) { 09038 ret = nomem((STMT *) stmt); 09039 goto done; 09040 } 09041 } 09042 if (type) { 09043 y = uc_to_utf_c(type, typeLen); 09044 if (!y) { 09045 ret = nomem((STMT *) stmt); 09046 goto done; 09047 } 09048 } 09049 ret = drvtables(stmt, c, SQL_NTS, s, SQL_NTS, 09050 t, SQL_NTS, y, SQL_NTS); 09051 done: 09052 uc_free(y); 09053 uc_free(t); 09054 uc_free(s); 09055 uc_free(c); 09056 return ret; 09057 } 09058 #endif 09059 09064 static COL colSpec[] = { 09065 { "SYSTEM", "COLUMN", "TABLE_QUALIFIER", SCOL_VARCHAR, 50 }, 09066 { "SYSTEM", "COLUMN", "TABLE_OWNER", SCOL_VARCHAR, 50 }, 09067 { "SYSTEM", "COLUMN", "TABLE_NAME", SCOL_VARCHAR, 255 }, 09068 { "SYSTEM", "COLUMN", "COLUMN_NAME", SCOL_VARCHAR, 255 }, 09069 { "SYSTEM", "COLUMN", "DATA_TYPE", SQL_SMALLINT, 50 }, 09070 { "SYSTEM", "COLUMN", "TYPE_NAME", SCOL_VARCHAR, 50 }, 09071 { "SYSTEM", "COLUMN", "PRECISION", SQL_INTEGER, 50 }, 09072 { "SYSTEM", "COLUMN", "LENGTH", SQL_INTEGER, 50 }, 09073 { "SYSTEM", "COLUMN", "RADIX", SQL_SMALLINT, 50 }, 09074 { "SYSTEM", "COLUMN", "SCALE", SQL_SMALLINT, 50 }, 09075 { "SYSTEM", "COLUMN", "NULLABLE", SQL_SMALLINT, 50 }, 09076 { "SYSTEM", "COLUMN", "REMARKS", SCOL_VARCHAR, 50 }, 09077 { "SYSTEM", "COLUMN", "COLUMN_DEF", SCOL_VARCHAR, 50 }, 09078 { "SYSTEM", "COLUMN", "SQL_DATA_TYPE", SQL_SMALLINT, 50 }, 09079 { "SYSTEM", "COLUMN", "SQL_DATETIME_SUB", SQL_SMALLINT, 50 }, 09080 { "SYSTEM", "COLUMN", "CHAR_OCTET_LENGTH", SQL_SMALLINT, 50 }, 09081 { "SYSTEM", "COLUMN", "ORDINAL_POSITION", SQL_SMALLINT, 50 }, 09082 { "SYSTEM", "COLUMN", "IS_NULLABLE", SCOL_VARCHAR, 50 } 09083 }; 09084 09099 static SQLRETURN 09100 drvcolumns(SQLHSTMT stmt, 09101 SQLCHAR *cat, SQLSMALLINT catLen, 09102 SQLCHAR *schema, SQLSMALLINT schemaLen, 09103 SQLCHAR *table, SQLSMALLINT tableLen, 09104 SQLCHAR *col, SQLSMALLINT colLen) 09105 { 09106 SQLRETURN sret; 09107 STMT *s; 09108 DBC *d; 09109 int ret, nrows, ncols, size, i, k; 09110 char *errp = NULL, tname[512], **rowp; 09111 09112 sret = mkresultset(stmt, colSpec, array_size(colSpec)); 09113 if (sret != SQL_SUCCESS) { 09114 return sret; 09115 } 09116 s = (STMT *) stmt; 09117 d = (DBC *) s->dbc; 09118 if (!table || table[0] == '\0' || table[0] == '%') { 09119 setstat(s, -1, "need table name", (*s->ov3) ? "HY000" : "S1000"); 09120 return SQL_ERROR; 09121 } 09122 if (tableLen == SQL_NTS) { 09123 size = sizeof (tname) - 1; 09124 } else { 09125 size = min(sizeof (tname) - 1, tableLen); 09126 } 09127 strncpy(tname, table, size); 09128 tname[size] = '\0'; 09129 ret = sqlite_get_table_printf(d->sqlite, "PRAGMA table_info('%q')", &rowp, 09130 &nrows, &ncols, &errp, tname); 09131 if (ret != SQLITE_OK) { 09132 setstat(s, ret, "%s (%d)", (*s->ov3) ? "HY000" : "S1000", 09133 errp ? errp : "unknown error", ret); 09134 if (errp) { 09135 sqlite_freemem(errp); 09136 errp = NULL; 09137 } 09138 return SQL_ERROR; 09139 } 09140 if (errp) { 09141 sqlite_freemem(errp); 09142 errp = NULL; 09143 } 09144 if (ncols * nrows <= 0) { 09145 sqlite_free_table(rowp); 09146 return SQL_NO_DATA; 09147 } 09148 size = array_size(colSpec) * (nrows + 1); 09149 s->rows = xmalloc((size + 1) * sizeof (char *)); 09150 if (!s->rows) { 09151 return nomem(s); 09152 } 09153 s->rows[0] = (char *) size; 09154 s->rows += 1; 09155 memset(s->rows, 0, sizeof (char *) * size); 09156 s->rowfree = freerows; 09157 s->nrows = nrows; 09158 for (i = 1; i <= s->nrows; i++) { 09159 s->rows[array_size(colSpec) * i + 0] = xstrdup(""); 09160 s->rows[array_size(colSpec) * i + 1] = xstrdup(""); 09161 s->rows[array_size(colSpec) * i + 2] = xstrdup(tname); 09162 s->rows[array_size(colSpec) * i + 8] = xstrdup("10"); 09163 s->rows[array_size(colSpec) * i + 9] = xstrdup("0"); 09164 s->rows[array_size(colSpec) * i + 15] = xstrdup("16384"); 09165 } 09166 for (k = 0; k < ncols; k++) { 09167 if (strcmp(rowp[k], "cid") == 0) { 09168 for (i = 1; i <= s->nrows; i++) { 09169 char buf[256]; 09170 int coln = i; 09171 09172 sscanf(rowp[i * ncols + k], "%d", &coln); 09173 sprintf(buf, "%d", coln + 1); 09174 s->rows[array_size(colSpec) * i + 16] = xstrdup(buf); 09175 } 09176 } else if (strcmp(rowp[k], "name") == 0) { 09177 for (i = 1; i <= s->nrows; i++) { 09178 s->rows[array_size(colSpec) * i + 3] = 09179 xstrdup(rowp[i * ncols + k]); 09180 } 09181 } else if (strcmp(rowp[k], "notnull") == 0) { 09182 for (i = 1; i <= s->nrows; i++) { 09183 if (*rowp[i * ncols + k] != '0') { 09184 s->rows[array_size(colSpec) * i + 10] = 09185 xstrdup(stringify(SQL_FALSE)); 09186 } else { 09187 s->rows[array_size(colSpec) * i + 10] = 09188 xstrdup(stringify(SQL_TRUE)); 09189 } 09190 s->rows[array_size(colSpec) * i + 17] = 09191 xstrdup(*rowp[i * ncols + k] != '0' ? "NO" : "YES"); 09192 } 09193 } else if (strcmp(rowp[k], "dflt_value") == 0) { 09194 for (i = 1; i <= s->nrows; i++) { 09195 char *dflt = rowp[i * ncols + k]; 09196 09197 s->rows[array_size(colSpec) * i + 12] = 09198 xstrdup(dflt ? dflt : "NULL"); 09199 } 09200 } else if (strcmp(rowp[k], "type") == 0) { 09201 for (i = 1; i <= s->nrows; i++) { 09202 char *typename = rowp[i * ncols + k]; 09203 int sqltype, m, d; 09204 char buf[256]; 09205 09206 s->rows[array_size(colSpec) * i + 5] = xstrdup(typename); 09207 sqltype = mapsqltype(typename, NULL, *s->ov3, s->nowchar); 09208 getmd(typename, sqltype, &m, &d); 09209 #ifdef SQL_LONGVARCHAR 09210 if (sqltype == SQL_VARCHAR && m > 255) { 09211 sqltype = SQL_LONGVARCHAR; 09212 } 09213 #endif 09214 #ifdef SQLITE_UTF8 09215 #ifdef SQL_WLONGVARCHAR 09216 if (sqltype == SQL_WVARCHAR && m > 255) { 09217 sqltype = SQL_WLONGVARCHAR; 09218 } 09219 #endif 09220 #endif 09221 #if HAVE_ENCDEC 09222 if (sqltype == SQL_VARBINARY && m > 255) { 09223 sqltype = SQL_LONGVARBINARY; 09224 } 09225 #endif 09226 sprintf(buf, "%d", sqltype); 09227 s->rows[array_size(colSpec) * i + 4] = xstrdup(buf); 09228 s->rows[array_size(colSpec) * i + 13] = xstrdup(buf); 09229 sprintf(buf, "%d", m); 09230 s->rows[array_size(colSpec) * i + 7] = xstrdup(buf); 09231 sprintf(buf, "%d", d); 09232 s->rows[array_size(colSpec) * i + 6] = xstrdup(buf); 09233 } 09234 } 09235 } 09236 sqlite_free_table(rowp); 09237 return SQL_SUCCESS; 09238 } 09239 09240 #ifndef SQLITE_UTF8 09241 09255 SQLRETURN SQL_API 09256 SQLColumns(SQLHSTMT stmt, 09257 SQLCHAR *cat, SQLSMALLINT catLen, 09258 SQLCHAR *schema, SQLSMALLINT schemaLen, 09259 SQLCHAR *table, SQLSMALLINT tableLen, 09260 SQLCHAR *col, SQLSMALLINT colLen) 09261 { 09262 return drvcolumns(stmt, cat, catLen, schema, schemaLen, 09263 table, tableLen, col, colLen); 09264 } 09265 #endif 09266 09267 #ifdef SQLITE_UTF8 09268 09282 SQLRETURN SQL_API 09283 SQLColumnsW(SQLHSTMT stmt, 09284 SQLWCHAR *cat, SQLSMALLINT catLen, 09285 SQLWCHAR *schema, SQLSMALLINT schemaLen, 09286 SQLWCHAR *table, SQLSMALLINT tableLen, 09287 SQLWCHAR *col, SQLSMALLINT colLen) 09288 { 09289 char *c = NULL, *s = NULL, *t = NULL, *k = NULL; 09290 SQLRETURN ret; 09291 09292 if (cat) { 09293 c = uc_to_utf_c(cat, catLen); 09294 if (!c) { 09295 ret = nomem((STMT *) stmt); 09296 goto done; 09297 } 09298 } 09299 if (schema) { 09300 s = uc_to_utf_c(schema, schemaLen); 09301 if (!s) { 09302 ret = nomem((STMT *) stmt); 09303 goto done; 09304 } 09305 } 09306 if (table) { 09307 t = uc_to_utf_c(table, tableLen); 09308 if (!t) { 09309 ret = nomem((STMT *) stmt); 09310 goto done; 09311 } 09312 } 09313 if (col) { 09314 k = uc_to_utf_c(col, colLen); 09315 if (!k) { 09316 ret = nomem((STMT *) stmt); 09317 goto done; 09318 } 09319 } 09320 ret = drvcolumns(stmt, c, SQL_NTS, s, SQL_NTS, 09321 t, SQL_NTS, k, SQL_NTS); 09322 done: 09323 uc_free(k); 09324 uc_free(t); 09325 uc_free(s); 09326 uc_free(c); 09327 return ret; 09328 09329 } 09330 #endif 09331 09336 static COL typeSpec[] = { 09337 { "SYSTEM", "TYPE", "TYPE_NAME", SCOL_VARCHAR, 50 }, 09338 { "SYSTEM", "TYPE", "DATA_TYPE", SQL_SMALLINT, 2 }, 09339 { "SYSTEM", "TYPE", "PRECISION", SQL_INTEGER, 4 }, 09340 { "SYSTEM", "TYPE", "LITERAL_PREFIX", SCOL_VARCHAR, 50 }, 09341 { "SYSTEM", "TYPE", "LITERAL_SUFFIX", SCOL_VARCHAR, 50 }, 09342 { "SYSTEM", "TYPE", "CREATE_PARAMS", SCOL_VARCHAR, 50 }, 09343 { "SYSTEM", "TYPE", "NULLABLE", SQL_SMALLINT, 2 }, 09344 { "SYSTEM", "TYPE", "CASE_SENSITIVE", SQL_SMALLINT, 2 }, 09345 { "SYSTEM", "TYPE", "SEARCHABLE", SQL_SMALLINT, 2 }, 09346 { "SYSTEM", "TYPE", "UNSIGNED_ATTRIBUTE", SQL_SMALLINT, 2 }, 09347 { "SYSTEM", "TYPE", "MONEY", SQL_SMALLINT, 2 }, 09348 { "SYSTEM", "TYPE", "AUTO_INCREMENT", SQL_SMALLINT, 2 }, 09349 { "SYSTEM", "TYPE", "LOCAL_TYPE_NAME", SCOL_VARCHAR, 50 }, 09350 { "SYSTEM", "TYPE", "MINIMUM_SCALE", SQL_SMALLINT, 2 }, 09351 { "SYSTEM", "TYPE", "MAXIMUM_SCALE", SQL_SMALLINT, 2 } 09352 }; 09353 09363 static void 09364 mktypeinfo(STMT *s, int row, char *typename, int type, int tind) 09365 { 09366 int offs = row * array_size(typeSpec); 09367 char *tcode, *crpar = NULL, *quote = NULL, *sign = stringify(SQL_FALSE); 09368 static char tcodes[32 * 32]; 09369 09370 if (tind <= 0) { 09371 tind = row; 09372 } 09373 tcode = tcodes + tind * 32; 09374 sprintf(tcode, "%d", type); 09375 s->rows[offs + 0] = typename; 09376 s->rows[offs + 1] = tcode; 09377 switch (type) { 09378 default: 09379 #ifdef SQL_LONGVARCHAR 09380 case SQL_LONGVARCHAR: 09381 #ifdef SQLITE_UTF8 09382 case SQL_WLONGVARCHAR: 09383 #endif 09384 crpar = "length"; 09385 quote = "'"; 09386 sign = NULL; 09387 s->rows[offs + 2] = "65536"; 09388 break; 09389 #endif 09390 case SQL_CHAR: 09391 case SQL_VARCHAR: 09392 #ifdef SQLITE_UTF8 09393 case SQL_WCHAR: 09394 case SQL_WVARCHAR: 09395 #endif 09396 s->rows[offs + 2] = "255"; 09397 crpar = "length"; 09398 quote = "'"; 09399 sign = NULL; 09400 break; 09401 case SQL_TINYINT: 09402 s->rows[offs + 2] = "3"; 09403 break; 09404 case SQL_SMALLINT: 09405 s->rows[offs + 2] = "5"; 09406 break; 09407 case SQL_INTEGER: 09408 s->rows[offs + 2] = "7"; 09409 break; 09410 case SQL_FLOAT: 09411 s->rows[offs + 2] = "7"; 09412 break; 09413 case SQL_DOUBLE: 09414 s->rows[offs + 2] = "15"; 09415 break; 09416 #ifdef SQL_TYPE_DATE 09417 case SQL_TYPE_DATE: 09418 #endif 09419 case SQL_DATE: 09420 s->rows[offs + 2] = "10"; 09421 quote = "'"; 09422 sign = NULL; 09423 break; 09424 #ifdef SQL_TYPE_TIME 09425 case SQL_TYPE_TIME: 09426 #endif 09427 case SQL_TIME: 09428 s->rows[offs + 2] = "8"; 09429 quote = "'"; 09430 sign = NULL; 09431 break; 09432 #ifdef SQL_TYPE_TIMESTAMP 09433 case SQL_TYPE_TIMESTAMP: 09434 #endif 09435 case SQL_TIMESTAMP: 09436 s->rows[offs + 2] = "32"; 09437 quote = "'"; 09438 sign = NULL; 09439 break; 09440 #if HAVE_ENCDEC 09441 case SQL_VARBINARY: 09442 sign = NULL; 09443 s->rows[offs + 2] = "255"; 09444 break; 09445 case SQL_LONGVARBINARY: 09446 sign = NULL; 09447 s->rows[offs + 2] = "65536"; 09448 break; 09449 #endif 09450 } 09451 s->rows[offs + 3] = s->rows[offs + 4] = quote; 09452 s->rows[offs + 5] = crpar; 09453 s->rows[offs + 6] = stringify(SQL_NULLABLE); 09454 s->rows[offs + 7] = stringify(SQL_FALSE); 09455 s->rows[offs + 8] = stringify(SQL_SEARCHABLE); 09456 s->rows[offs + 9] = sign; 09457 s->rows[offs + 10] = stringify(SQL_FALSE); 09458 s->rows[offs + 11] = stringify(SQL_FALSE); 09459 s->rows[offs + 12] = typename; 09460 s->rows[offs + 13] = NULL; 09461 s->rows[offs + 14] = NULL; 09462 } 09463 09472 static int 09473 typeinfosort(const void *a, const void *b) 09474 { 09475 char **pa = (char **) a; 09476 char **pb = (char **) b; 09477 int na, nb; 09478 09479 na = strtol(pa[1], NULL, 0); 09480 nb = strtol(pb[1], NULL, 0); 09481 return na - nb; 09482 } 09483 09491 static SQLRETURN 09492 drvgettypeinfo(SQLHSTMT stmt, SQLSMALLINT sqltype) 09493 { 09494 SQLRETURN ret; 09495 STMT *s; 09496 DBC *d; 09497 09498 ret = mkresultset(stmt, typeSpec, array_size(typeSpec)); 09499 if (ret != SQL_SUCCESS) { 09500 return ret; 09501 } 09502 s = (STMT *) stmt; 09503 d = (DBC *) s->dbc; 09504 #ifdef SQLITE_UTF8 09505 #ifdef SQL_LONGVARCHAR 09506 #ifdef SQL_WLONGVARCHAR 09507 if (s->nowchar) { 09508 s->nrows = sqltype == SQL_ALL_TYPES ? 13 : 1; 09509 } else { 09510 s->nrows = sqltype == SQL_ALL_TYPES ? 17 : 1; 09511 } 09512 #else 09513 if (s->nowchar) { 09514 s->nrows = sqltype == SQL_ALL_TYPES ? 12 : 1; 09515 } else { 09516 s->nrows = sqltype == SQL_ALL_TYPES ? 16 : 1; 09517 } 09518 #endif 09519 #else 09520 s->nrows = sqltype == SQL_ALL_TYPES ? 15 : 1; 09521 #endif 09522 #else 09523 #ifdef SQL_LONGVARCHAR 09524 s->nrows = sqltype == SQL_ALL_TYPES ? 13 : 1; 09525 #else 09526 s->nrows = sqltype == SQL_ALL_TYPES ? 12 : 1; 09527 #endif 09528 #endif 09529 #if HAVE_ENCDEC 09530 if (sqltype == SQL_ALL_TYPES) { 09531 s->nrows += 2; 09532 } 09533 #endif 09534 s->rows = (char **) xmalloc(sizeof (char *) * (s->nrows + 1) 09535 * array_size(typeSpec)); 09536 if (!s->rows) { 09537 s->nrows = 0; 09538 return nomem(s); 09539 } 09540 #ifdef MEMORY_DEBUG 09541 s->rowfree = xfree__; 09542 #else 09543 s->rowfree = free; 09544 #endif 09545 memset(s->rows, 0, 09546 sizeof (char *) * (s->nrows + 1) * array_size(typeSpec)); 09547 if (sqltype == SQL_ALL_TYPES) { 09548 int cc = 1; 09549 09550 mktypeinfo(s, cc++, "varchar", SQL_VARCHAR, 0); 09551 mktypeinfo(s, cc++, "tinyint", SQL_TINYINT, 0); 09552 mktypeinfo(s, cc++, "smallint", SQL_SMALLINT, 0); 09553 mktypeinfo(s, cc++, "integer", SQL_INTEGER, 0); 09554 mktypeinfo(s, cc++, "float", SQL_FLOAT, 0); 09555 mktypeinfo(s, cc++, "double", SQL_DOUBLE, 0); 09556 #ifdef SQL_TYPE_DATE 09557 mktypeinfo(s, cc++, "date", (*s->ov3) ? SQL_TYPE_DATE : SQL_DATE, 0); 09558 #else 09559 mktypeinfo(s, cc++, "date", SQL_DATE, 0); 09560 #endif 09561 #ifdef SQL_TYPE_TIME 09562 mktypeinfo(s, cc++, "time", (*s->ov3) ? SQL_TYPE_TIME : SQL_TIME, 0); 09563 #else 09564 mktypeinfo(s, cc++, "time", SQL_TIME, 0); 09565 #endif 09566 #ifdef SQL_TYPE_TIMESTAMP 09567 mktypeinfo(s, cc++, "timestamp", 09568 (*s->ov3) ? SQL_TYPE_TIMESTAMP : SQL_TIMESTAMP, 0); 09569 #else 09570 mktypeinfo(s, cc++, "timestamp", SQL_TIMESTAMP, 0); 09571 #endif 09572 mktypeinfo(s, cc++, "char", SQL_CHAR, 0); 09573 mktypeinfo(s, cc++, "numeric", SQL_DOUBLE, 0); 09574 #ifdef SQL_LONGVARCHAR 09575 mktypeinfo(s, cc++, "text", SQL_LONGVARCHAR, 0); 09576 mktypeinfo(s, cc++, "longvarchar", SQL_LONGVARCHAR, 0); 09577 #else 09578 mktypeinfo(s, cc++, "text", SQL_VARCHAR, 0); 09579 #endif 09580 #ifdef SQLITE_UTF8 09581 if (!s->nowchar) { 09582 mktypeinfo(s, cc++, "wvarchar", SQL_WVARCHAR, 0); 09583 #ifdef SQL_LONGVARCHAR 09584 mktypeinfo(s, cc++, "wchar", SQL_WCHAR, 0); 09585 mktypeinfo(s, cc++, "wtext", SQL_WLONGVARCHAR, 0); 09586 #ifdef SQL_WLONGVARCHAR 09587 mktypeinfo(s, cc++, "longwvarchar", SQL_WLONGVARCHAR, 0); 09588 #endif 09589 #else 09590 mktypeinfo(s, cc++, "wvarchar", SQL_WVARCHAR, 0); 09591 mktypeinfo(s, cc++, "wchar", SQL_WCHAR, 0); 09592 mktypeinfo(s, cc++, "wtext", SQL_WVARCHAR, 0); 09593 #endif 09594 } 09595 #endif 09596 #if HAVE_ENCDEC 09597 mktypeinfo(s, cc++, "varbinary", SQL_VARBINARY, 0); 09598 mktypeinfo(s, cc++, "longvarbinary", SQL_LONGVARBINARY, 0); 09599 #endif 09600 qsort(s->rows + array_size(typeSpec), s->nrows, 09601 sizeof (char *) * array_size(typeSpec), typeinfosort); 09602 } else { 09603 switch (sqltype) { 09604 case SQL_CHAR: 09605 mktypeinfo(s, 1, "char", SQL_CHAR, 10); 09606 break; 09607 case SQL_VARCHAR: 09608 mktypeinfo(s, 1, "varchar", SQL_VARCHAR, 1); 09609 break; 09610 case SQL_TINYINT: 09611 mktypeinfo(s, 1, "tinyint", SQL_TINYINT, 2); 09612 break; 09613 case SQL_SMALLINT: 09614 mktypeinfo(s, 1, "smallint", SQL_SMALLINT, 3); 09615 break; 09616 case SQL_INTEGER: 09617 mktypeinfo(s, 1, "integer", SQL_INTEGER, 4); 09618 break; 09619 case SQL_FLOAT: 09620 mktypeinfo(s, 1, "float", SQL_FLOAT, 5); 09621 break; 09622 case SQL_DOUBLE: 09623 mktypeinfo(s, 1, "double", SQL_DOUBLE, 6); 09624 break; 09625 #ifdef SQL_TYPE_DATE 09626 case SQL_TYPE_DATE: 09627 mktypeinfo(s, 1, "date", SQL_TYPE_DATE, 25); 09628 break; 09629 #endif 09630 case SQL_DATE: 09631 mktypeinfo(s, 1, "date", SQL_DATE, 7); 09632 break; 09633 #ifdef SQL_TYPE_TIME 09634 case SQL_TYPE_TIME: 09635 mktypeinfo(s, 1, "date", SQL_TYPE_TIME, 26); 09636 break; 09637 #endif 09638 case SQL_TIME: 09639 mktypeinfo(s, 1, "time", SQL_TIME, 8); 09640 break; 09641 #ifdef SQL_TYPE_TIMESTAMP 09642 case SQL_TYPE_TIMESTAMP: 09643 mktypeinfo(s, 1, "date", SQL_TYPE_TIMESTAMP, 27); 09644 break; 09645 #endif 09646 case SQL_TIMESTAMP: 09647 mktypeinfo(s, 1, "timestamp", SQL_TIMESTAMP, 9); 09648 break; 09649 #ifdef SQL_LONGVARCHAR 09650 case SQL_LONGVARCHAR: 09651 mktypeinfo(s, 1, "longvarchar", SQL_LONGVARCHAR, 12); 09652 break; 09653 #endif 09654 #ifdef SQLITE_UTF8 09655 #ifdef SQL_WCHAR 09656 case SQL_WCHAR: 09657 mktypeinfo(s, 1, "wchar", SQL_WCHAR, 18); 09658 break; 09659 #endif 09660 #ifdef SQL_WVARCHAR 09661 case SQL_WVARCHAR: 09662 mktypeinfo(s, 1, "wvarchar", SQL_WVARCHAR, 19); 09663 break; 09664 #endif 09665 #ifdef SQL_WLONGVARCHAR 09666 case SQL_WLONGVARCHAR: 09667 mktypeinfo(s, 1, "longwvarchar", SQL_WLONGVARCHAR, 20); 09668 break; 09669 #endif 09670 #endif 09671 #if HAVE_ENCDEC 09672 case SQL_VARBINARY: 09673 mktypeinfo(s, 1, "varbinary", SQL_VARBINARY, 30); 09674 break; 09675 case SQL_LONGVARBINARY: 09676 mktypeinfo(s, 1, "longvarbinary", SQL_LONGVARBINARY, 31); 09677 break; 09678 #endif 09679 default: 09680 s->nrows = 0; 09681 return SQL_NO_DATA; 09682 } 09683 } 09684 return SQL_SUCCESS; 09685 } 09686 09687 #ifndef SQLITE_UTF8 09688 09695 SQLRETURN SQL_API 09696 SQLGetTypeInfo(SQLHSTMT stmt, SQLSMALLINT sqltype) 09697 { 09698 return drvgettypeinfo(stmt, sqltype); 09699 } 09700 #endif 09701 09702 #ifdef SQLITE_UTF8 09703 09710 SQLRETURN SQL_API 09711 SQLGetTypeInfoW(SQLHSTMT stmt, SQLSMALLINT sqltype) 09712 { 09713 return drvgettypeinfo(stmt, sqltype); 09714 } 09715 #endif 09716 09721 static COL statSpec[] = { 09722 { "SYSTEM", "STATISTICS", "TABLE_QUALIFIER", SCOL_VARCHAR, 50 }, 09723 { "SYSTEM", "STATISTICS", "TABLE_OWNER", SCOL_VARCHAR, 50 }, 09724 { "SYSTEM", "STATISTICS", "TABLE_NAME", SCOL_VARCHAR, 255 }, 09725 { "SYSTEM", "STATISTICS", "NON_UNIQUE", SQL_SMALLINT, 50 }, 09726 { "SYSTEM", "STATISTICS", "INDEX_QUALIFIER", SCOL_VARCHAR, 255 }, 09727 { "SYSTEM", "STATISTICS", "INDEX_NAME", SCOL_VARCHAR, 255 }, 09728 { "SYSTEM", "STATISTICS", "TYPE", SQL_SMALLINT, 50 }, 09729 { "SYSTEM", "STATISTICS", "ORDINAL_POSITION", SQL_SMALLINT, 50 }, 09730 { "SYSTEM", "STATISTICS", "COLUMN_NAME", SCOL_VARCHAR, 255 }, 09731 { "SYSTEM", "STATISTICS", "ASC_OR_DESC", SCOL_CHAR, 1 }, 09732 { "SYSTEM", "STATISTICS", "CARDINALITY", SQL_INTEGER, 50 }, 09733 { "SYSTEM", "STATISTICS", "PAGES", SQL_INTEGER, 50 }, 09734 { "SYSTEM", "STATISTICS", "FILTER_CONDITION", SCOL_VARCHAR, 255 } 09735 }; 09736 09751 static SQLRETURN 09752 drvstatistics(SQLHSTMT stmt, SQLCHAR *cat, SQLSMALLINT catLen, 09753 SQLCHAR *schema, SQLSMALLINT schemaLen, 09754 SQLCHAR *table, SQLSMALLINT tableLen, 09755 SQLUSMALLINT itype, SQLUSMALLINT resv) 09756 { 09757 SQLRETURN sret; 09758 STMT *s; 09759 DBC *d; 09760 int i, size, ret, nrows, ncols, offs, namec, uniquec; 09761 char **rowp, *errp = NULL, tname[512]; 09762 09763 sret = mkresultset(stmt, statSpec, array_size(statSpec)); 09764 if (sret != SQL_SUCCESS) { 09765 return sret; 09766 } 09767 s = (STMT *) stmt; 09768 d = (DBC *) s->dbc; 09769 if (!table || table[0] == '\0' || table[0] == '%') { 09770 setstat(s, -1, "need table name", (*s->ov3) ? "HY000" : "S1000"); 09771 return SQL_ERROR; 09772 } 09773 if (tableLen == SQL_NTS) { 09774 size = sizeof (tname) - 1; 09775 } else { 09776 size = min(sizeof (tname) - 1, tableLen); 09777 } 09778 strncpy(tname, table, size); 09779 tname[size] = '\0'; 09780 ret = sqlite_get_table_printf(d->sqlite, 09781 "PRAGMA index_list('%q')", &rowp, 09782 &nrows, &ncols, &errp, tname); 09783 if (ret != SQLITE_OK) { 09784 setstat(s, ret, "%s (%d)", (*s->ov3) ? "HY000" : "S1000", 09785 errp ? errp : "unknown error", ret); 09786 if (errp) { 09787 sqlite_freemem(errp); 09788 errp = NULL; 09789 } 09790 return SQL_ERROR; 09791 } 09792 if (errp) { 09793 sqlite_freemem(errp); 09794 errp = NULL; 09795 } 09796 if (ncols * nrows <= 0) { 09797 nodata: 09798 sqlite_free_table(rowp); 09799 /* try table_info for integer primary keys */ 09800 if (itype == SQL_INDEX_UNIQUE) { 09801 ret = sqlite_get_table_printf(d->sqlite, 09802 "PRAGMA table_info('%q')", &rowp, 09803 &nrows, &ncols, NULL, tname); 09804 if (ret == SQLITE_OK) { 09805 int colid, typec, roffs; 09806 09807 namec = findcol(rowp, ncols, "name"); 09808 uniquec = findcol(rowp, ncols, "pk"); 09809 typec = findcol(rowp, ncols, "type"); 09810 colid = findcol(rowp, ncols, "cid"); 09811 if (namec < 0 || uniquec < 0 || typec < 0 || colid < 0) { 09812 goto nodata2; 09813 } 09814 for (i = 1; i <= nrows; i++) { 09815 if (*rowp[i * ncols + uniquec] != '0' && 09816 strlen(rowp[i * ncols + typec]) == 7 && 09817 strncasecmp(rowp[i * ncols + typec], "integer", 7) 09818 == 0) { 09819 break; 09820 } 09821 } 09822 if (i > nrows) { 09823 goto nodata2; 09824 } 09825 size = (1 + 1) * array_size(statSpec); 09826 s->rows = xmalloc((size + 1) * sizeof (char *)); 09827 if (!s->rows) { 09828 s->nrows = 0; 09829 return nomem(s); 09830 } 09831 s->rows[0] = (char *) size; 09832 s->rows += 1; 09833 memset(s->rows, 0, sizeof (char *) * size); 09834 s->rowfree = freerows; 09835 s->nrows = 1; 09836 roffs = s->ncols; 09837 s->rows[roffs + 0] = xstrdup(""); 09838 s->rows[roffs + 1] = xstrdup(""); 09839 s->rows[roffs + 2] = xstrdup(tname); 09840 s->rows[roffs + 3] = xstrdup(stringify(SQL_FALSE)); 09841 s->rows[roffs + 4] = xstrdup(""); 09842 s->rows[roffs + 5] = xstrdup(""); 09843 s->rows[roffs + 6] = xstrdup(stringify(SQL_INDEX_OTHER)); 09844 s->rows[roffs + 7] = xstrdup("1"); 09845 s->rows[roffs + 8] = xstrdup(rowp[i * ncols + namec]); 09846 s->rows[roffs + 9] = xstrdup("A"); 09847 nodata2: 09848 sqlite_free_table(rowp); 09849 } 09850 } 09851 return SQL_SUCCESS; 09852 } 09853 size = 0; 09854 namec = findcol(rowp, ncols, "name"); 09855 uniquec = findcol(rowp, ncols, "unique"); 09856 if (namec < 0 || uniquec < 0) { 09857 goto nodata; 09858 } 09859 for (i = 1; i <= nrows; i++) { 09860 int nnrows, nncols; 09861 char **rowpp; 09862 int isuniq; 09863 09864 isuniq = *rowp[i * ncols + uniquec] != '0'; 09865 if (isuniq || itype == SQL_INDEX_ALL) { 09866 ret = sqlite_get_table_printf(d->sqlite, 09867 "PRAGMA index_info('%q')", &rowpp, 09868 &nnrows, &nncols, NULL, 09869 rowp[i * ncols + namec]); 09870 if (ret == SQLITE_OK) { 09871 size += nnrows; 09872 sqlite_free_table(rowpp); 09873 } 09874 } 09875 } 09876 if (size == 0) { 09877 goto nodata; 09878 } 09879 s->nrows = size; 09880 size = (size + 1) * array_size(statSpec); 09881 s->rows = xmalloc((size + 1) * sizeof (char *)); 09882 if (!s->rows) { 09883 s->nrows = 0; 09884 return nomem(s); 09885 } 09886 s->rows[0] = (char *) size; 09887 s->rows += 1; 09888 memset(s->rows, 0, sizeof (char *) * size); 09889 s->rowfree = freerows; 09890 offs = 0; 09891 for (i = 1; i <= nrows; i++) { 09892 int nnrows, nncols; 09893 char **rowpp; 09894 09895 if (*rowp[i * ncols + uniquec] != '0' || itype == SQL_INDEX_ALL) { 09896 int k; 09897 09898 ret = sqlite_get_table_printf(d->sqlite, 09899 "PRAGMA index_info('%q')", &rowpp, 09900 &nnrows, &nncols, NULL, 09901 rowp[i * ncols + namec]); 09902 if (ret != SQLITE_OK) { 09903 continue; 09904 } 09905 for (k = 0; nnrows && k < nncols; k++) { 09906 if (strcmp(rowpp[k], "name") == 0) { 09907 int m; 09908 09909 for (m = 1; m <= nnrows; m++) { 09910 int roffs = (offs + m) * s->ncols; 09911 int isuniq; 09912 09913 isuniq = *rowp[i * ncols + uniquec] != '0'; 09914 s->rows[roffs + 0] = xstrdup(""); 09915 s->rows[roffs + 1] = xstrdup(""); 09916 s->rows[roffs + 2] = xstrdup(tname); 09917 if (isuniq) { 09918 s->rows[roffs + 3] = xstrdup(stringify(SQL_FALSE)); 09919 } else { 09920 s->rows[roffs + 3] = xstrdup(stringify(SQL_TRUE)); 09921 } 09922 s->rows[roffs + 4] = xstrdup(""); 09923 s->rows[roffs + 5] = xstrdup(rowp[i * ncols + namec]); 09924 s->rows[roffs + 6] = 09925 xstrdup(stringify(SQL_INDEX_OTHER)); 09926 s->rows[roffs + 8] = xstrdup(rowpp[m * nncols + k]); 09927 s->rows[roffs + 9] = xstrdup("A"); 09928 } 09929 } else if (strcmp(rowpp[k], "seqno") == 0) { 09930 int m; 09931 09932 for (m = 1; m <= nnrows; m++) { 09933 int roffs = (offs + m) * s->ncols; 09934 int pos = m - 1; 09935 char buf[32]; 09936 09937 sscanf(rowpp[m * nncols + k], "%d", &pos); 09938 sprintf(buf, "%d", pos + 1); 09939 s->rows[roffs + 7] = xstrdup(buf); 09940 } 09941 } 09942 } 09943 offs += nnrows; 09944 sqlite_free_table(rowpp); 09945 } 09946 } 09947 sqlite_free_table(rowp); 09948 return SQL_SUCCESS; 09949 } 09950 09951 #ifndef SQLITE_UTF8 09952 09966 SQLRETURN SQL_API 09967 SQLStatistics(SQLHSTMT stmt, SQLCHAR *cat, SQLSMALLINT catLen, 09968 SQLCHAR *schema, SQLSMALLINT schemaLen, 09969 SQLCHAR *table, SQLSMALLINT tableLen, 09970 SQLUSMALLINT itype, SQLUSMALLINT resv) 09971 { 09972 return drvstatistics(stmt, cat, catLen, schema, schemaLen, 09973 table, tableLen, itype, resv); 09974 } 09975 #endif 09976 09977 #ifdef SQLITE_UTF8 09978 09992 SQLRETURN SQL_API 09993 SQLStatisticsW(SQLHSTMT stmt, SQLWCHAR *cat, SQLSMALLINT catLen, 09994 SQLWCHAR *schema, SQLSMALLINT schemaLen, 09995 SQLWCHAR *table, SQLSMALLINT tableLen, 09996 SQLUSMALLINT itype, SQLUSMALLINT resv) 09997 { 09998 char *c = NULL, *s = NULL, *t = NULL; 09999 SQLRETURN ret; 10000 10001 if (cat) { 10002 c = uc_to_utf_c(cat, catLen); 10003 if (!c) { 10004 ret = nomem((STMT *) stmt); 10005 goto done; 10006 } 10007 } 10008 if (schema) { 10009 s = uc_to_utf_c(schema, schemaLen); 10010 if (!s) { 10011 ret = nomem((STMT *) stmt); 10012 goto done; 10013 } 10014 } 10015 if (table) { 10016 t = uc_to_utf_c(table, tableLen); 10017 if (!t) { 10018 ret = nomem((STMT *) stmt); 10019 goto done; 10020 } 10021 } 10022 ret = drvstatistics(stmt, c, SQL_NTS, s, SQL_NTS, t, SQL_NTS, 10023 itype, resv); 10024 done: 10025 uc_free(t); 10026 uc_free(s); 10027 uc_free(c); 10028 return ret; 10029 } 10030 #endif 10031 10043 SQLRETURN SQL_API 10044 SQLGetData(SQLHSTMT stmt, SQLUSMALLINT col, SQLSMALLINT type, 10045 SQLPOINTER val, SQLINTEGER len, SQLINTEGER *lenp) 10046 { 10047 STMT *s; 10048 10049 if (stmt == SQL_NULL_HSTMT) { 10050 return SQL_INVALID_HANDLE; 10051 } 10052 s = (STMT *) stmt; 10053 if (col == 0 && s->bkmrk && type == SQL_C_BOOKMARK) { 10054 *((long *) val) = s->rowp; 10055 if (lenp) { 10056 *lenp = sizeof (long); 10057 } 10058 return SQL_SUCCESS; 10059 } 10060 if (col < 1 || col > s->ncols) { 10061 setstat(s, -1, "invalid column", (*s->ov3) ? "07009" : "S1002"); 10062 return SQL_ERROR; 10063 } 10064 --col; 10065 return getrowdata(s, col, type, val, len, lenp, 1); 10066 } 10067 10075 static SQLRETURN 10076 dofetchbind(STMT *s, int rsi) 10077 { 10078 int ret, i, withinfo = 0; 10079 10080 s->row_status0[rsi] = SQL_ROW_SUCCESS; 10081 if (s->bkmrk && s->bkmrkcol.valp) { 10082 long *val; 10083 10084 if (s->bind_type != SQL_BIND_BY_COLUMN) { 10085 val = (long *) ((char *) s->bkmrkcol.valp + s->bind_type * rsi); 10086 } else { 10087 val = (long *) s->bkmrkcol.valp + rsi; 10088 } 10089 *val = s->rowp; 10090 if (s->bkmrkcol.lenp) { 10091 if (s->bind_type != SQL_BIND_BY_COLUMN) { 10092 SQLINTEGER *ival = (SQLINTEGER *) 10093 ((char *) s->bkmrkcol.lenp + s->bind_type * rsi); 10094 *ival = sizeof (long); 10095 } else { 10096 s->bkmrkcol.lenp[rsi] = sizeof (long); 10097 } 10098 } 10099 } 10100 ret = SQL_SUCCESS; 10101 for (i = 0; s->bindcols && i < s->ncols; i++) { 10102 BINDCOL *b = &s->bindcols[i]; 10103 SQLPOINTER dp = 0; 10104 SQLINTEGER *lp = 0; 10105 10106 b->offs = 0; 10107 if (b->valp) { 10108 if (s->bind_type != SQL_BIND_BY_COLUMN) { 10109 dp = (SQLPOINTER) ((char *) b->valp + s->bind_type * rsi); 10110 } else { 10111 dp = (SQLPOINTER) ((char *) b->valp + b->max * rsi); 10112 } 10113 } 10114 if (b->lenp) { 10115 if (s->bind_type != SQL_BIND_BY_COLUMN) { 10116 lp = (SQLINTEGER *) ((char *) b->lenp + s->bind_type * rsi); 10117 } else { 10118 lp = b->lenp + rsi; 10119 } 10120 } 10121 if (dp || lp) { 10122 ret = getrowdata(s, (SQLUSMALLINT) i, b->type, dp, b->max, lp, 0); 10123 if (!SQL_SUCCEEDED(ret)) { 10124 s->row_status0[rsi] = SQL_ROW_ERROR; 10125 break; 10126 } 10127 if (ret != SQL_SUCCESS) { 10128 withinfo = 1; 10129 #ifdef SQL_ROW_SUCCESS_WITH_INFO 10130 s->row_status0[rsi] = SQL_ROW_SUCCESS_WITH_INFO; 10131 #endif 10132 } 10133 } 10134 } 10135 if (SQL_SUCCEEDED(ret)) { 10136 ret = withinfo ? SQL_SUCCESS_WITH_INFO : SQL_SUCCESS; 10137 } 10138 return ret; 10139 } 10140 10147 SQLRETURN SQL_API 10148 SQLFetch(SQLHSTMT stmt) 10149 { 10150 STMT *s; 10151 int i, withinfo = 0; 10152 SQLRETURN ret; 10153 10154 if (stmt == SQL_NULL_HSTMT) { 10155 return SQL_INVALID_HANDLE; 10156 } 10157 s = (STMT *) stmt; 10158 for (i = 0; i < s->rowset_size; i++) { 10159 s->row_status0[i] = SQL_ROW_NOROW; 10160 } 10161 if (s->row_status) { 10162 memcpy(s->row_status, s->row_status0, 10163 sizeof (SQLUSMALLINT) * s->rowset_size); 10164 } 10165 s->row_count0 = 0; 10166 if (s->row_count) { 10167 *s->row_count = s->row_count0; 10168 } 10169 if (!s->bindcols) { 10170 for (i = 0; i < s->rowset_size; i++) { 10171 s->row_status0[i] = SQL_ROW_ERROR; 10172 } 10173 return SQL_ERROR; 10174 } 10175 ret = SQL_SUCCESS; 10176 i = 0; 10177 if (((DBC *) (s->dbc))->vm_stmt == s && s->vm) { 10178 s->rowp = 0; 10179 for (; i < s->rowset_size; i++) { 10180 ret = vm_step(s); 10181 if (ret != SQL_SUCCESS) { 10182 s->row_status0[i] = SQL_ROW_ERROR; 10183 break; 10184 } 10185 if (s->nrows < 1) { 10186 break; 10187 } 10188 ret = dofetchbind(s, i); 10189 if (!SQL_SUCCEEDED(ret)) { 10190 break; 10191 } else if (ret == SQL_SUCCESS_WITH_INFO) { 10192 withinfo = 1; 10193 } 10194 } 10195 } else if (s->rows && s->nrows > 0) { 10196 for (; i < s->rowset_size; i++) { 10197 ++s->rowp; 10198 if (s->rowp < 0 || s->rowp >= s->nrows) { 10199 break; 10200 } 10201 ret = dofetchbind(s, i); 10202 if (!SQL_SUCCEEDED(ret)) { 10203 break; 10204 } else if (ret == SQL_SUCCESS_WITH_INFO) { 10205 withinfo = 1; 10206 } 10207 } 10208 } 10209 if (i == 0) { 10210 if (SQL_SUCCEEDED(ret)) { 10211 return SQL_NO_DATA; 10212 } 10213 return ret; 10214 } 10215 if (SQL_SUCCEEDED(ret)) { 10216 ret = withinfo ? SQL_SUCCESS_WITH_INFO : SQL_SUCCESS; 10217 } 10218 if (s->row_status) { 10219 memcpy(s->row_status, s->row_status0, 10220 sizeof (SQLUSMALLINT) * s->rowset_size); 10221 } 10222 s->row_count0 = i; 10223 if (s->row_count) { 10224 *s->row_count = s->row_count0; 10225 } 10226 return ret; 10227 } 10228 10237 static SQLRETURN 10238 drvfetchscroll(SQLHSTMT stmt, SQLSMALLINT orient, SQLINTEGER offset) 10239 { 10240 STMT *s; 10241 int i, withinfo = 0; 10242 SQLRETURN ret; 10243 10244 if (stmt == SQL_NULL_HSTMT) { 10245 return SQL_INVALID_HANDLE; 10246 } 10247 s = (STMT *) stmt; 10248 for (i = 0; i < s->rowset_size; i++) { 10249 s->row_status0[i] = SQL_ROW_NOROW; 10250 } 10251 if (s->row_status) { 10252 memcpy(s->row_status, s->row_status0, 10253 sizeof (SQLUSMALLINT) * s->rowset_size); 10254 } 10255 s->row_count0 = 0; 10256 if (s->row_count) { 10257 *s->row_count = s->row_count0; 10258 } 10259 if (!s->bindcols) { 10260 for (i = 0; i < s->rowset_size; i++) { 10261 s->row_status0[i] = SQL_ROW_ERROR; 10262 } 10263 ret = SQL_ERROR; 10264 goto done; 10265 } 10266 if (s->curtype == SQL_CURSOR_FORWARD_ONLY && orient != SQL_FETCH_NEXT) { 10267 setstat(s, -1, "wrong fetch direction", "01000"); 10268 return SQL_ERROR; 10269 } 10270 ret = SQL_SUCCESS; 10271 i = 0; 10272 if (((DBC *) (s->dbc))->vm_stmt == s && s->vm) { 10273 s->rowp = 0; 10274 for (; i < s->rowset_size; i++) { 10275 ret = vm_step(s); 10276 if (ret != SQL_SUCCESS) { 10277 s->row_status0[i] = SQL_ROW_ERROR; 10278 break; 10279 } 10280 if (s->nrows < 1) { 10281 break; 10282 } 10283 ret = dofetchbind(s, i); 10284 if (!SQL_SUCCEEDED(ret)) { 10285 break; 10286 } else if (ret == SQL_SUCCESS_WITH_INFO) { 10287 withinfo = 1; 10288 } 10289 } 10290 } else if (s->rows) { 10291 switch (orient) { 10292 case SQL_FETCH_NEXT: 10293 if (s->nrows < 1) { 10294 return SQL_NO_DATA; 10295 } 10296 if (s->rowp < 0) { 10297 s->rowp = -1; 10298 } else { 10299 s->rowp += s->rowset_size - 1; 10300 } 10301 if (s->rowp >= s->nrows) { 10302 s->rowp = s->nrows; 10303 return SQL_NO_DATA; 10304 } 10305 break; 10306 case SQL_FETCH_PRIOR: 10307 if (s->nrows < 1) { 10308 s->rowp = -1; 10309 return SQL_NO_DATA; 10310 } 10311 s->rowp -= s->rowset_size + 1; 10312 if (s->rowp < 0) { 10313 s->rowp = -1; 10314 return SQL_NO_DATA; 10315 } 10316 break; 10317 case SQL_FETCH_FIRST: 10318 if (s->nrows < 1) { 10319 return SQL_NO_DATA; 10320 } 10321 s->rowp = -1; 10322 break; 10323 case SQL_FETCH_LAST: 10324 if (s->nrows < 1) { 10325 return SQL_NO_DATA; 10326 } 10327 s->rowp = s->nrows - s->rowset_size - 1; 10328 if (--s->rowp < -1) { 10329 s->rowp = -1; 10330 } 10331 break; 10332 case SQL_FETCH_ABSOLUTE: 10333 if (offset == 0) { 10334 s->rowp = -1; 10335 return SQL_NO_DATA; 10336 } else if (offset < 0) { 10337 if (0 - offset <= s->nrows) { 10338 s->rowp = s->nrows + offset + 1; 10339 break; 10340 } 10341 s->rowp = 0; 10342 return SQL_NO_DATA; 10343 } else if (offset > s->nrows) { 10344 s->rowp = s->nrows; 10345 return SQL_NO_DATA; 10346 } 10347 s->rowp = offset - 1; 10348 break; 10349 case SQL_FETCH_RELATIVE: 10350 if (offset >= 0) { 10351 s->rowp += offset - 1; 10352 if (s->rowp + offset > s->nrows) { 10353 s->rowp = s->nrows; 10354 return SQL_NO_DATA; 10355 } 10356 } else { 10357 if (s->rowp + offset < 0) { 10358 s->rowp = 0; 10359 return SQL_NO_DATA; 10360 } 10361 s->rowp += offset - 1; 10362 } 10363 break; 10364 case SQL_FETCH_BOOKMARK: 10365 if (s->bkmrk) { 10366 if (offset < 0 || offset >= s->nrows) { 10367 return SQL_NO_DATA; 10368 } 10369 s->rowp = offset - 1; 10370 break; 10371 } 10372 /* fall through */ 10373 default: 10374 s->row_status0[0] = SQL_ROW_ERROR; 10375 ret = SQL_ERROR; 10376 goto done; 10377 } 10378 for (; i < s->rowset_size; i++) { 10379 ++s->rowp; 10380 if (s->rowp < 0 || s->rowp >= s->nrows) { 10381 break; 10382 } 10383 ret = dofetchbind(s, i); 10384 if (!SQL_SUCCEEDED(ret)) { 10385 break; 10386 } else if (ret == SQL_SUCCESS_WITH_INFO) { 10387 withinfo = 1; 10388 } 10389 } 10390 } 10391 done: 10392 if (i == 0) { 10393 if (SQL_SUCCEEDED(ret)) { 10394 return SQL_NO_DATA; 10395 } 10396 return ret; 10397 } 10398 if (SQL_SUCCEEDED(ret)) { 10399 ret = withinfo ? SQL_SUCCESS_WITH_INFO : SQL_SUCCESS; 10400 } 10401 if (s->row_status) { 10402 memcpy(s->row_status, s->row_status0, 10403 sizeof (SQLUSMALLINT) * s->rowset_size); 10404 } 10405 s->row_count0 = i; 10406 if (s->row_count) { 10407 *s->row_count = s->row_count0; 10408 } 10409 return ret; 10410 } 10411 10420 SQLRETURN SQL_API 10421 SQLFetchScroll(SQLHSTMT stmt, SQLSMALLINT orient, SQLINTEGER offset) 10422 { 10423 return drvfetchscroll(stmt, orient, offset); 10424 } 10425 10436 SQLRETURN SQL_API 10437 SQLExtendedFetch(SQLHSTMT stmt, SQLUSMALLINT orient, SQLINTEGER offset, 10438 SQLUINTEGER *rowcount, SQLUSMALLINT *rowstatus) 10439 { 10440 STMT *s; 10441 SQLRETURN ret; 10442 SQLUSMALLINT *rst; 10443 10444 if (stmt == SQL_NULL_HSTMT) { 10445 return SQL_INVALID_HANDLE; 10446 } 10447 s = (STMT *) stmt; 10448 /* temporarily turn off SQL_ATTR_ROW_STATUS_PTR */ 10449 rst = s->row_status; 10450 s->row_status = 0; 10451 ret = drvfetchscroll(stmt, orient, offset); 10452 s->row_status = rst; 10453 if (rowstatus) { 10454 memcpy(rowstatus, s->row_status0, 10455 sizeof (SQLUSMALLINT) * s->rowset_size); 10456 } 10457 if (rowcount) { 10458 *rowcount = s->row_count0; 10459 } 10460 return ret; 10461 } 10462 10470 SQLRETURN SQL_API 10471 SQLRowCount(SQLHSTMT stmt, SQLINTEGER *nrows) 10472 { 10473 STMT *s; 10474 10475 if (stmt == SQL_NULL_HSTMT) { 10476 return SQL_INVALID_HANDLE; 10477 } 10478 s = (STMT *) stmt; 10479 if (nrows) { 10480 *nrows = s->nrows; 10481 } 10482 return SQL_SUCCESS; 10483 } 10484 10492 SQLRETURN SQL_API 10493 SQLNumResultCols(SQLHSTMT stmt, SQLSMALLINT *ncols) 10494 { 10495 STMT *s; 10496 10497 if (stmt == SQL_NULL_HSTMT) { 10498 return SQL_INVALID_HANDLE; 10499 } 10500 s = (STMT *) stmt; 10501 if (ncols) { 10502 *ncols = s->ncols; 10503 } 10504 return SQL_SUCCESS; 10505 } 10506 10521 static SQLRETURN 10522 drvdescribecol(SQLHSTMT stmt, SQLUSMALLINT col, SQLCHAR *name, 10523 SQLSMALLINT nameMax, SQLSMALLINT *nameLen, 10524 SQLSMALLINT *type, SQLUINTEGER *size, 10525 SQLSMALLINT *digits, SQLSMALLINT *nullable) 10526 { 10527 STMT *s; 10528 COL *c; 10529 int didname = 0; 10530 10531 if (stmt == SQL_NULL_HSTMT) { 10532 return SQL_INVALID_HANDLE; 10533 } 10534 s = (STMT *) stmt; 10535 if (!s->cols) { 10536 setstat(s, -1, "no columns", (*s->ov3) ? "07009" : "S1002"); 10537 return SQL_ERROR; 10538 } 10539 if (col < 1 || col > s->ncols) { 10540 setstat(s, -1, "invalid column", (*s->ov3) ? "07009" : "S1002"); 10541 return SQL_ERROR; 10542 } 10543 c = s->cols + col - 1; 10544 if (name && nameMax > 0) { 10545 strncpy(name, c->column, nameMax); 10546 name[nameMax - 1] = '\0'; 10547 didname = 1; 10548 } 10549 if (nameLen) { 10550 if (didname) { 10551 *nameLen = strlen(name); 10552 } else { 10553 *nameLen = strlen(c->column); 10554 } 10555 } 10556 if (type) { 10557 *type = c->type; 10558 #ifdef SQLITE_UTF8 10559 if (s->nowchar) { 10560 switch (c->type) { 10561 case SQL_WCHAR: 10562 *type = SQL_CHAR; 10563 break; 10564 case SQL_WVARCHAR: 10565 *type = SQL_VARCHAR; 10566 break; 10567 #ifdef SQL_LONGVARCHAR 10568 case SQL_WLONGVARCHAR: 10569 *type = SQL_LONGVARCHAR; 10570 break; 10571 #endif 10572 } 10573 } 10574 #endif 10575 } 10576 if (size) { 10577 *size = c->size; 10578 } 10579 if (digits) { 10580 *digits = 0; 10581 } 10582 if (nullable) { 10583 *nullable = 1; 10584 } 10585 return SQL_SUCCESS; 10586 } 10587 10588 #ifndef SQLITE_UTF8 10589 10603 SQLRETURN SQL_API 10604 SQLDescribeCol(SQLHSTMT stmt, SQLUSMALLINT col, SQLCHAR *name, 10605 SQLSMALLINT nameMax, SQLSMALLINT *nameLen, 10606 SQLSMALLINT *type, SQLUINTEGER *size, 10607 SQLSMALLINT *digits, SQLSMALLINT *nullable) 10608 { 10609 return drvdescribecol(stmt, col, name, nameMax, nameLen, 10610 type, size, digits, nullable); 10611 } 10612 #endif 10613 10614 #ifdef SQLITE_UTF8 10615 10629 SQLRETURN SQL_API 10630 SQLDescribeColW(SQLHSTMT stmt, SQLUSMALLINT col, SQLWCHAR *name, 10631 SQLSMALLINT nameMax, SQLSMALLINT *nameLen, 10632 SQLSMALLINT *type, SQLUINTEGER *size, 10633 SQLSMALLINT *digits, SQLSMALLINT *nullable) 10634 { 10635 SQLRETURN ret; 10636 SQLSMALLINT len; 10637 10638 ret = drvdescribecol(stmt, col, (char *) name, nameMax, &len, 10639 type, size, digits, nullable); 10640 if (ret == SQL_SUCCESS) { 10641 if (name) { 10642 if (len > 0) { 10643 SQLWCHAR *n = NULL; 10644 10645 n = uc_from_utf((char *) name, len); 10646 if (n) { 10647 uc_strncpy(name, n, nameMax); 10648 len = min(nameMax, uc_strlen(n)); 10649 uc_free(n); 10650 } else { 10651 len = 0; 10652 } 10653 } 10654 if (len <= 0) { 10655 len = 0; 10656 if (nameMax > 0) { 10657 name[0] = 0; 10658 } 10659 } 10660 } else { 10661 len = 0; 10662 } 10663 if (nameLen) { 10664 *nameLen = len; 10665 } 10666 } 10667 return ret; 10668 } 10669 #endif 10670 10683 static SQLRETURN 10684 drvcolattributes(SQLHSTMT stmt, SQLUSMALLINT col, SQLUSMALLINT id, 10685 SQLPOINTER val, SQLSMALLINT valMax, SQLSMALLINT *valLen, 10686 SQLINTEGER *val2) 10687 { 10688 STMT *s; 10689 COL *c; 10690 SQLSMALLINT dummy; 10691 char *valc = (char *) val; 10692 10693 if (stmt == SQL_NULL_HSTMT) { 10694 return SQL_INVALID_HANDLE; 10695 } 10696 s = (STMT *) stmt; 10697 if (!s->cols) { 10698 return SQL_ERROR; 10699 } 10700 if (!valLen) { 10701 valLen = &dummy; 10702 } 10703 if (id == SQL_COLUMN_COUNT) { 10704 if (val2) { 10705 *val2 = s->ncols; 10706 } 10707 *valLen = sizeof (int); 10708 return SQL_SUCCESS; 10709 } 10710 if (id == SQL_COLUMN_TYPE && col == 0) { 10711 if (val2) { 10712 *val2 = SQL_INTEGER; 10713 } 10714 *valLen = sizeof (int); 10715 return SQL_SUCCESS; 10716 } 10717 #ifdef SQL_DESC_OCTET_LENGTH 10718 if (id == SQL_DESC_OCTET_LENGTH && col == 0) { 10719 if (val2) { 10720 *val2 = 4; 10721 } 10722 *valLen = sizeof (int); 10723 return SQL_SUCCESS; 10724 } 10725 #endif 10726 if (col < 1 || col > s->ncols) { 10727 setstat(s, -1, "invalid column", (*s->ov3) ? "07009": "S1002"); 10728 return SQL_ERROR; 10729 } 10730 c = s->cols + col - 1; 10731 10732 switch (id) { 10733 case SQL_COLUMN_LABEL: 10734 if (c->label) { 10735 if (valc && valMax > 0) { 10736 strncpy(valc, c->label, valMax); 10737 valc[valMax - 1] = '\0'; 10738 } 10739 if (valLen) { 10740 *valLen = strlen(c->label); 10741 } 10742 goto checkLen; 10743 } 10744 /* fall through */ 10745 case SQL_COLUMN_NAME: 10746 case SQL_DESC_NAME: 10747 if (valc && valMax > 0) { 10748 strncpy(valc, c->column, valMax); 10749 valc[valMax - 1] = '\0'; 10750 } 10751 *valLen = strlen(c->column); 10752 checkLen: 10753 if (*valLen >= valMax) { 10754 setstat(s, -1, "data right truncated", "01004"); 10755 return SQL_SUCCESS_WITH_INFO; 10756 } 10757 return SQL_SUCCESS; 10758 case SQL_COLUMN_TYPE: 10759 case SQL_DESC_TYPE: 10760 #ifdef SQLITE_UTF8 10761 { 10762 int type = c->type; 10763 10764 if (s->nowchar) { 10765 switch (type) { 10766 case SQL_WCHAR: 10767 type = SQL_CHAR; 10768 break; 10769 case SQL_WVARCHAR: 10770 type = SQL_VARCHAR; 10771 break; 10772 #ifdef SQL_LONGVARCHAR 10773 case SQL_WLONGVARCHAR: 10774 type = SQL_LONGVARCHAR; 10775 break; 10776 } 10777 } 10778 if (val2) { 10779 *val2 = type; 10780 } 10781 #endif 10782 } 10783 #else 10784 if (val2) { 10785 *val2 = c->type; 10786 } 10787 #endif 10788 *valLen = sizeof (int); 10789 return SQL_SUCCESS; 10790 case SQL_COLUMN_DISPLAY_SIZE: 10791 if (val2) { 10792 *val2 = c->size; 10793 } 10794 *valLen = sizeof (int); 10795 return SQL_SUCCESS; 10796 case SQL_COLUMN_UNSIGNED: 10797 if (val2) { 10798 *val2 = c->nosign ? SQL_TRUE : SQL_FALSE; 10799 } 10800 *valLen = sizeof (int); 10801 return SQL_SUCCESS; 10802 case SQL_COLUMN_SCALE: 10803 case SQL_DESC_SCALE: 10804 if (val2) { 10805 *val2 = c->scale; 10806 } 10807 *valLen = sizeof (int); 10808 return SQL_SUCCESS; 10809 case SQL_COLUMN_PRECISION: 10810 case SQL_DESC_PRECISION: 10811 if (val2) { 10812 *val2 = c->prec; 10813 } 10814 *valLen = sizeof (int); 10815 return SQL_SUCCESS; 10816 case SQL_COLUMN_MONEY: 10817 if (val2) { 10818 *val2 = SQL_FALSE; 10819 } 10820 *valLen = sizeof (int); 10821 return SQL_SUCCESS; 10822 case SQL_COLUMN_AUTO_INCREMENT: 10823 if (val2) { 10824 *val2 = c->autoinc > 0 ? SQL_TRUE : SQL_FALSE; 10825 } 10826 *valLen = sizeof (int); 10827 return SQL_SUCCESS; 10828 case SQL_COLUMN_LENGTH: 10829 case SQL_DESC_LENGTH: 10830 if (val2) { 10831 *val2 = c->size; 10832 } 10833 *valLen = sizeof (int); 10834 return SQL_SUCCESS; 10835 case SQL_COLUMN_NULLABLE: 10836 case SQL_DESC_NULLABLE: 10837 if (val2) { 10838 *val2 = SQL_NULLABLE; 10839 } 10840 *valLen = sizeof (int); 10841 return SQL_SUCCESS; 10842 case SQL_COLUMN_SEARCHABLE: 10843 if (val2) { 10844 *val2 = SQL_SEARCHABLE; 10845 } 10846 *valLen = sizeof (int); 10847 return SQL_SUCCESS; 10848 case SQL_COLUMN_CASE_SENSITIVE: 10849 if (val2) { 10850 *val2 = SQL_TRUE; 10851 } 10852 *valLen = sizeof (int); 10853 return SQL_SUCCESS; 10854 case SQL_COLUMN_UPDATABLE: 10855 if (val2) { 10856 *val2 = SQL_TRUE; 10857 } 10858 *valLen = sizeof (int); 10859 return SQL_SUCCESS; 10860 case SQL_COLUMN_TYPE_NAME: { 10861 char *tn = c->typename ? c->typename : "varchar"; 10862 10863 if (valc && valMax > 0) { 10864 strncpy(valc, tn, valMax); 10865 valc[valMax - 1] = '\0'; 10866 } 10867 *valLen = strlen(tn); 10868 goto checkLen; 10869 } 10870 case SQL_COLUMN_OWNER_NAME: 10871 case SQL_COLUMN_QUALIFIER_NAME: { 10872 char *z = ""; 10873 10874 if (valc && valMax > 0) { 10875 strncpy(valc, z, valMax); 10876 valc[valMax - 1] = '\0'; 10877 } 10878 *valLen = strlen(z); 10879 goto checkLen; 10880 } 10881 case SQL_COLUMN_TABLE_NAME: 10882 #if (SQL_COLUMN_TABLE_NAME != SQL_DESC_TABLE_NAME) 10883 case SQL_DESC_TABLE_NAME: 10884 #endif 10885 if (valc && valMax > 0) { 10886 strncpy(valc, c->table, valMax); 10887 valc[valMax - 1] = '\0'; 10888 } 10889 *valLen = strlen(c->table); 10890 goto checkLen; 10891 } 10892 setstat(s, -1, "unsupported column attributes %d", "HY091", id); 10893 return SQL_ERROR; 10894 } 10895 10896 #ifndef SQLITE_UTF8 10897 10909 SQLRETURN SQL_API 10910 SQLColAttributes(SQLHSTMT stmt, SQLUSMALLINT col, SQLUSMALLINT id, 10911 SQLPOINTER val, SQLSMALLINT valMax, SQLSMALLINT *valLen, 10912 SQLINTEGER *val2) 10913 { 10914 return drvcolattributes(stmt, col, id, val, valMax, valLen, val2); 10915 } 10916 #endif 10917 10918 #ifdef SQLITE_UTF8 10919 10931 SQLRETURN SQL_API 10932 SQLColAttributesW(SQLHSTMT stmt, SQLUSMALLINT col, SQLUSMALLINT id, 10933 SQLPOINTER val, SQLSMALLINT valMax, SQLSMALLINT *valLen, 10934 SQLINTEGER *val2) 10935 { 10936 SQLRETURN ret; 10937 SQLSMALLINT len; 10938 10939 ret = drvcolattributes(stmt, col, id, val, valMax, &len, val2); 10940 if (ret == SQL_SUCCESS) { 10941 SQLWCHAR *v = NULL; 10942 10943 switch (id) { 10944 case SQL_COLUMN_LABEL: 10945 case SQL_COLUMN_NAME: 10946 case SQL_DESC_NAME: 10947 case SQL_COLUMN_TYPE_NAME: 10948 case SQL_COLUMN_OWNER_NAME: 10949 case SQL_COLUMN_QUALIFIER_NAME: 10950 case SQL_COLUMN_TABLE_NAME: 10951 #if (SQL_COLUMN_TABLE_NAME != SQL_DESC_TABLE_NAME) 10952 case SQL_DESC_TABLE_NAME: 10953 #endif 10954 if (val && valMax > 0) { 10955 int vmax = valMax / sizeof (SQLWCHAR); 10956 10957 v = uc_from_utf((char *) val, SQL_NTS); 10958 if (v) { 10959 uc_strncpy(val, v, vmax); 10960 uc_free(v); 10961 } 10962 if (vmax > 0) { 10963 v = (SQLWCHAR *) val; 10964 v[vmax - 1] = '\0'; 10965 } 10966 } 10967 if (len <= 0) { 10968 len = 0; 10969 } 10970 break; 10971 } 10972 if (valLen) { 10973 *valLen = len; 10974 } 10975 } 10976 return ret; 10977 } 10978 #endif 10979 10992 static SQLRETURN 10993 drvcolattribute(SQLHSTMT stmt, SQLUSMALLINT col, SQLUSMALLINT id, 10994 SQLPOINTER val, SQLSMALLINT valMax, SQLSMALLINT *valLen, 10995 SQLPOINTER val2) 10996 { 10997 STMT *s; 10998 COL *c; 10999 int v = 0; 11000 char *valc = (char *) val; 11001 11002 if (stmt == SQL_NULL_HSTMT) { 11003 return SQL_INVALID_HANDLE; 11004 } 11005 s = (STMT *) stmt; 11006 if (!s->cols) { 11007 return SQL_ERROR; 11008 } 11009 if (col < 1 || col > s->ncols) { 11010 setstat(s, -1, "invalid column", (*s->ov3) ? "07009" : "S1002"); 11011 return SQL_ERROR; 11012 } 11013 c = s->cols + col - 1; 11014 switch (id) { 11015 case SQL_DESC_CATALOG_NAME: 11016 if (valc && valMax > 0) { 11017 strncpy(valc, c->db, valMax); 11018 valc[valMax - 1] = '\0'; 11019 } 11020 if (valLen) { 11021 *valLen = strlen(c->db); 11022 } 11023 checkLen: 11024 if (valLen && *valLen >= valMax) { 11025 setstat(s, -1, "data right truncated", "01004"); 11026 return SQL_SUCCESS_WITH_INFO; 11027 } 11028 break; 11029 case SQL_COLUMN_LENGTH: 11030 case SQL_DESC_LENGTH: 11031 v = c->size; 11032 break; 11033 case SQL_COLUMN_LABEL: 11034 if (c->label) { 11035 if (valc && valMax > 0) { 11036 strncpy(valc, c->label, valMax); 11037 valc[valMax - 1] = '\0'; 11038 } 11039 if (valLen) { 11040 *valLen = strlen(c->label); 11041 } 11042 goto checkLen; 11043 } 11044 /* fall through */ 11045 case SQL_COLUMN_NAME: 11046 case SQL_DESC_NAME: 11047 if (valc && valMax > 0) { 11048 strncpy(valc, c->column, valMax); 11049 valc[valMax - 1] = '\0'; 11050 } 11051 if (valLen) { 11052 *valLen = strlen(c->column); 11053 goto checkLen; 11054 } 11055 break; 11056 case SQL_DESC_TYPE_NAME: { 11057 char *tn = c->typename ? c->typename : "varchar"; 11058 11059 if (valc && valMax > 0) { 11060 strncpy(valc, tn, valMax); 11061 valc[valMax - 1] = '\0'; 11062 } 11063 if (valLen) { 11064 *valLen = strlen(tn); 11065 goto checkLen; 11066 } 11067 break; 11068 } 11069 case SQL_DESC_OCTET_LENGTH: 11070 v = c->size; 11071 break; 11072 #if (SQL_COLUMN_TABLE_NAME != SQL_DESC_TABLE_NAME) 11073 case SQL_COLUMN_TABLE_NAME: 11074 #endif 11075 case SQL_DESC_TABLE_NAME: 11076 if (valc && valMax > 0) { 11077 strncpy(valc, c->table, valMax); 11078 valc[valMax - 1] = '\0'; 11079 } 11080 if (valLen) { 11081 *valLen = strlen(c->table); 11082 goto checkLen; 11083 } 11084 break; 11085 case SQL_DESC_TYPE: 11086 v = c->type; 11087 #ifdef SQLITE_UTF8 11088 if (s->nowchar) { 11089 switch (v) { 11090 case SQL_WCHAR: 11091 v = SQL_CHAR; 11092 break; 11093 case SQL_WVARCHAR: 11094 v = SQL_VARCHAR; 11095 break; 11096 #ifdef SQL_LONGVARCHAR 11097 case SQL_WLONGVARCHAR: 11098 v = SQL_LONGVARCHAR; 11099 break; 11100 #endif 11101 } 11102 } 11103 #endif 11104 break; 11105 case SQL_DESC_CONCISE_TYPE: 11106 switch (c->type) { 11107 case SQL_INTEGER: 11108 v = SQL_C_LONG; 11109 break; 11110 case SQL_TINYINT: 11111 v = SQL_C_TINYINT; 11112 break; 11113 case SQL_SMALLINT: 11114 v = SQL_C_SHORT; 11115 break; 11116 case SQL_FLOAT: 11117 v = SQL_C_FLOAT; 11118 break; 11119 case SQL_DOUBLE: 11120 v = SQL_C_DOUBLE; 11121 break; 11122 case SQL_TIMESTAMP: 11123 v = SQL_C_TIMESTAMP; 11124 break; 11125 case SQL_TIME: 11126 v = SQL_C_TIME; 11127 break; 11128 case SQL_DATE: 11129 v = SQL_C_DATE; 11130 break; 11131 #ifdef SQL_C_TYPE_TIMESTAMP 11132 case SQL_TYPE_TIMESTAMP: 11133 v = SQL_C_TYPE_TIMESTAMP; 11134 break; 11135 #endif 11136 #ifdef SQL_C_TYPE_TIME 11137 case SQL_TYPE_TIME: 11138 v = SQL_C_TYPE_TIME; 11139 break; 11140 #endif 11141 #ifdef SQL_C_TYPE_DATE 11142 case SQL_TYPE_DATE: 11143 v = SQL_C_TYPE_DATE; 11144 break; 11145 #endif 11146 default: 11147 #ifdef SQLITE_UTF8 11148 v = s->nowchar ? SQL_C_CHAR : SQL_C_WCHAR; 11149 #else 11150 v = SQL_C_CHAR; 11151 #endif 11152 break; 11153 } 11154 break; 11155 case SQL_DESC_UPDATABLE: 11156 v = SQL_TRUE; 11157 break; 11158 case SQL_COLUMN_DISPLAY_SIZE: 11159 v = c->size; 11160 break; 11161 case SQL_COLUMN_UNSIGNED: 11162 v = c->nosign ? SQL_TRUE : SQL_FALSE; 11163 break; 11164 case SQL_COLUMN_SEARCHABLE: 11165 v = SQL_SEARCHABLE; 11166 break; 11167 case SQL_COLUMN_SCALE: 11168 case SQL_DESC_SCALE: 11169 v = c->scale; 11170 break; 11171 case SQL_COLUMN_PRECISION: 11172 case SQL_DESC_PRECISION: 11173 v = c->prec; 11174 break; 11175 case SQL_COLUMN_MONEY: 11176 v = SQL_FALSE; 11177 break; 11178 case SQL_COLUMN_AUTO_INCREMENT: 11179 v = c->autoinc > 0 ? SQL_TRUE : SQL_FALSE; 11180 break; 11181 case SQL_DESC_NULLABLE: 11182 v = SQL_NULLABLE; 11183 break; 11184 default: 11185 setstat(s, -1, "unsupported column attribute %d", "HY091", id); 11186 return SQL_ERROR; 11187 } 11188 if (val2) { 11189 *(int *) val2 = v; 11190 } 11191 return SQL_SUCCESS; 11192 } 11193 11194 #ifndef SQLITE_UTF8 11195 11207 SQLRETURN SQL_API 11208 SQLColAttribute(SQLHSTMT stmt, SQLUSMALLINT col, SQLUSMALLINT id, 11209 SQLPOINTER val, SQLSMALLINT valMax, SQLSMALLINT *valLen, 11210 SQLPOINTER val2) 11211 { 11212 return drvcolattribute(stmt, col, id, val, valMax, valLen, val2); 11213 } 11214 #endif 11215 11216 #ifdef SQLITE_UTF8 11217 11229 SQLRETURN SQL_API 11230 SQLColAttributeW(SQLHSTMT stmt, SQLUSMALLINT col, SQLUSMALLINT id, 11231 SQLPOINTER val, SQLSMALLINT valMax, SQLSMALLINT *valLen, 11232 SQLPOINTER val2) 11233 { 11234 SQLRETURN ret; 11235 SQLSMALLINT len; 11236 11237 ret = drvcolattribute(stmt, col, id, val, valMax, &len, val2); 11238 if (ret == SQL_SUCCESS) { 11239 SQLWCHAR *v = NULL; 11240 11241 switch (id) { 11242 case SQL_DESC_CATALOG_NAME: 11243 case SQL_COLUMN_LABEL: 11244 case SQL_DESC_NAME: 11245 case SQL_DESC_TABLE_NAME: 11246 case SQL_DESC_TYPE_NAME: 11247 if (val && valMax > 0) { 11248 int vmax = valMax / sizeof (SQLWCHAR); 11249 11250 v = uc_from_utf((char *) val, SQL_NTS); 11251 if (v) { 11252 uc_strncpy(val, v, vmax); 11253 uc_free(v); 11254 } 11255 if (vmax > 0) { 11256 v = (SQLWCHAR *) val; 11257 v[vmax - 1] = '\0'; 11258 } 11259 } 11260 if (len <= 0) { 11261 len = 0; 11262 } 11263 break; 11264 } 11265 if (valLen) { 11266 *valLen = len; 11267 } 11268 } 11269 return ret; 11270 } 11271 #endif 11272 11286 static SQLRETURN 11287 drverror(SQLHENV env, SQLHDBC dbc, SQLHSTMT stmt, 11288 SQLCHAR *sqlState, SQLINTEGER *nativeErr, 11289 SQLCHAR *errmsg, SQLSMALLINT errmax, SQLSMALLINT *errlen) 11290 { 11291 SQLCHAR dummy0[6]; 11292 SQLINTEGER dummy1; 11293 SQLSMALLINT dummy2; 11294 11295 if (env == SQL_NULL_HENV && 11296 dbc == SQL_NULL_HDBC && 11297 stmt == SQL_NULL_HSTMT) { 11298 return SQL_INVALID_HANDLE; 11299 } 11300 if (sqlState) { 11301 sqlState[0] = '\0'; 11302 } else { 11303 sqlState = dummy0; 11304 } 11305 if (!nativeErr) { 11306 nativeErr = &dummy1; 11307 } 11308 *nativeErr = 0; 11309 if (!errlen) { 11310 errlen = &dummy2; 11311 } 11312 *errlen = 0; 11313 if (errmsg) { 11314 if (errmax > 0) { 11315 errmsg[0] = '\0'; 11316 } 11317 } else { 11318 errmsg = dummy0; 11319 errmax = 0; 11320 } 11321 if (stmt) { 11322 STMT *s = (STMT *) stmt; 11323 11324 if (s->logmsg[0] == '\0') { 11325 goto noerr; 11326 } 11327 *nativeErr = s->naterr; 11328 strcpy(sqlState, s->sqlstate); 11329 if (errmax == SQL_NTS) { 11330 strcpy(errmsg, "[SQLite]"); 11331 strcat(errmsg, s->logmsg); 11332 *errlen = strlen(errmsg); 11333 } else { 11334 strncpy(errmsg, "[SQLite]", errmax); 11335 if (errmax - 8 > 0) { 11336 strncpy(errmsg + 8, s->logmsg, errmax - 8); 11337 } 11338 *errlen = min(strlen(s->logmsg) + 8, errmax); 11339 } 11340 s->logmsg[0] = '\0'; 11341 return SQL_SUCCESS; 11342 } 11343 if (dbc) { 11344 DBC *d = (DBC *) dbc; 11345 11346 if (d->magic != DBC_MAGIC || d->logmsg[0] == '\0') { 11347 goto noerr; 11348 } 11349 *nativeErr = d->naterr; 11350 strcpy(sqlState, d->sqlstate); 11351 if (errmax == SQL_NTS) { 11352 strcpy(errmsg, "[SQLite]"); 11353 strcat(errmsg, d->logmsg); 11354 *errlen = strlen(errmsg); 11355 } else { 11356 strncpy(errmsg, "[SQLite]", errmax); 11357 if (errmax - 8 > 0) { 11358 strncpy(errmsg + 8, d->logmsg, errmax - 8); 11359 } 11360 *errlen = min(strlen(d->logmsg) + 8, errmax); 11361 } 11362 d->logmsg[0] = '\0'; 11363 return SQL_SUCCESS; 11364 } 11365 noerr: 11366 sqlState[0] = '\0'; 11367 errmsg[0] = '\0'; 11368 *nativeErr = 0; 11369 *errlen = 0; 11370 return SQL_NO_DATA_FOUND; 11371 } 11372 11373 #ifndef SQLITE_UTF8 11374 11387 SQLRETURN SQL_API 11388 SQLError(SQLHENV env, SQLHDBC dbc, SQLHSTMT stmt, 11389 SQLCHAR *sqlState, SQLINTEGER *nativeErr, 11390 SQLCHAR *errmsg, SQLSMALLINT errmax, SQLSMALLINT *errlen) 11391 { 11392 return drverror(env, dbc, stmt, sqlState, nativeErr, 11393 errmsg, errmax, errlen); 11394 } 11395 #endif 11396 11397 #ifdef SQLITE_UTF8 11398 11411 SQLRETURN SQL_API 11412 SQLErrorW(SQLHENV env, SQLHDBC dbc, SQLHSTMT stmt, 11413 SQLWCHAR *sqlState, SQLINTEGER *nativeErr, 11414 SQLWCHAR *errmsg, SQLSMALLINT errmax, SQLSMALLINT *errlen) 11415 { 11416 char state[16]; 11417 SQLSMALLINT len; 11418 SQLRETURN ret; 11419 11420 ret = drverror(env, dbc, stmt, state, nativeErr, 11421 (char *) errmsg, errmax, &len); 11422 if (ret == SQL_SUCCESS) { 11423 if (sqlState) { 11424 uc_from_utf_buf(state, sqlState, 6 * sizeof (SQLWCHAR)); 11425 } 11426 if (errmsg) { 11427 if (len > 0) { 11428 SQLWCHAR *e = NULL; 11429 11430 e = uc_from_utf((char *) errmsg, len); 11431 if (e) { 11432 if (errmax > 0) { 11433 uc_strncpy(errmsg, e, errmax); 11434 len = min(errmax, uc_strlen(e)); 11435 } else { 11436 len = uc_strlen(e); 11437 } 11438 uc_free(e); 11439 } else { 11440 len = 0; 11441 } 11442 } 11443 if (len <= 0) { 11444 len = 0; 11445 if (errmax > 0) { 11446 errmsg[0] = 0; 11447 } 11448 } 11449 } else { 11450 len = 0; 11451 } 11452 if (errlen) { 11453 *errlen = len; 11454 } 11455 } else if (ret == SQL_NO_DATA) { 11456 if (sqlState) { 11457 sqlState[0] = 0; 11458 } 11459 if (errmsg) { 11460 if (errmax > 0) { 11461 errmsg[0] = 0; 11462 } 11463 } 11464 if (errlen) { 11465 *errlen = 0; 11466 } 11467 } 11468 return ret; 11469 } 11470 #endif 11471 11478 SQLRETURN SQL_API 11479 SQLMoreResults(SQLHSTMT stmt) 11480 { 11481 if (stmt == SQL_NULL_HSTMT) { 11482 return SQL_INVALID_HANDLE; 11483 } 11484 return SQL_NO_DATA; 11485 } 11486 11496 static int 11497 selcb(void *arg, int ncols, char **values, char **cols) 11498 { 11499 STMT *s = (STMT *) arg; 11500 11501 if (ncols > 0) { 11502 int i, size; 11503 char *p; 11504 COL *dyncols; 11505 DBC *d = (DBC *) s->dbc; 11506 11507 for (i = size = 0; i < ncols; i++) { 11508 size += 3 + 3 * strlen(cols[i]); 11509 } 11510 dyncols = xmalloc(ncols * sizeof (COL) + size); 11511 if (!dyncols) { 11512 freedyncols(s); 11513 s->ncols = 0; 11514 return 1; 11515 } 11516 p = (char *) (dyncols + ncols); 11517 for (i = 0; i < ncols; i++) { 11518 char *q; 11519 11520 dyncols[i].db = ((DBC *) (s->dbc))->dbname; 11521 strcpy(p, cols[i]); 11522 dyncols[i].label = p; 11523 p += strlen(p) + 1; 11524 q = strchr(cols[i], '.'); 11525 if (q) { 11526 dyncols[i].table = p; 11527 strncpy(p, cols[i], q - cols[i]); 11528 p[q - cols[i]] = '\0'; 11529 p += strlen(p) + 1; 11530 strcpy(p, q + 1); 11531 dyncols[i].column = p; 11532 p += strlen(p) + 1; 11533 } else { 11534 dyncols[i].table = ""; 11535 strcpy(p, cols[i]); 11536 dyncols[i].column = p; 11537 p += strlen(p) + 1; 11538 } 11539 #ifdef SQL_LONGVARCHAR 11540 dyncols[i].type = SQL_LONGVARCHAR; 11541 dyncols[i].size = 65536; 11542 #else 11543 dyncols[i].type = SQL_VARCHAR; 11544 dyncols[i].size = 256; 11545 #endif 11546 dyncols[i].index = i; 11547 dyncols[i].scale = 0; 11548 dyncols[i].prec = 0; 11549 dyncols[i].nosign = 1; 11550 dyncols[i].autoinc = -1; 11551 dyncols[i].typename = NULL; 11552 } 11553 freedyncols(s); 11554 s->dyncols = s->cols = dyncols; 11555 s->dcols = ncols; 11556 fixupdyncols(s, d->sqlite, (const char **) cols + ncols); 11557 } 11558 s->ncols = ncols; 11559 return 1; 11560 } 11561 11570 static SQLRETURN 11571 drvprepare(SQLHSTMT stmt, SQLCHAR *query, SQLINTEGER queryLen) 11572 { 11573 STMT *s; 11574 DBC *d; 11575 char *errp = NULL; 11576 11577 if (stmt == SQL_NULL_HSTMT) { 11578 return SQL_INVALID_HANDLE; 11579 } 11580 s = (STMT *) stmt; 11581 if (s->dbc == SQL_NULL_HDBC) { 11582 noconn: 11583 return noconn(s); 11584 } 11585 d = s->dbc; 11586 if (!d->sqlite) { 11587 goto noconn; 11588 } 11589 vm_end(s); 11590 freep(&s->query); 11591 s->query = fixupsql(query, queryLen, &s->nparams, &s->isselect, &errp, 11592 d->version, &s->parmnames); 11593 if (!s->query) { 11594 if (errp) { 11595 setstat(s, -1, errp, (*s->ov3) ? "HY000" : "S1000"); 11596 return SQL_ERROR; 11597 } 11598 return nomem(s); 11599 } 11600 errp = NULL; 11601 freeresult(s, -1); 11602 if (s->isselect) { 11603 int ret; 11604 char **params = NULL; 11605 11606 if (s->nparams) { 11607 int i; 11608 11609 params = xmalloc(s->nparams * sizeof (char *)); 11610 if (!params) { 11611 return nomem(s); 11612 } 11613 for (i = 0; i < s->nparams; i++) { 11614 params[i] = NULL; 11615 } 11616 } 11617 ret = sqlite_exec_vprintf(d->sqlite, s->query, selcb, s, 11618 &errp, (char *) params); 11619 if (ret != SQLITE_ABORT && ret != SQLITE_OK) { 11620 dbtracerc(d, ret, errp); 11621 freep(&params); 11622 setstat(s, ret, "%s (%d)", (*s->ov3) ? "HY000" : "S1000", 11623 errp ? errp : "unknown error", ret); 11624 if (errp) { 11625 sqlite_freemem(errp); 11626 errp = NULL; 11627 } 11628 return SQL_ERROR; 11629 } 11630 freep(&params); 11631 if (errp) { 11632 sqlite_freemem(errp); 11633 errp = NULL; 11634 } 11635 } 11636 mkbindcols(s, s->ncols); 11637 if (s->nparams) { 11638 s->paramset_count = 0; 11639 } 11640 return SQL_SUCCESS; 11641 } 11642 11643 /* see doc on top */ 11644 11645 static SQLRETURN 11646 drvexecute(SQLHSTMT stmt) 11647 { 11648 STMT *s; 11649 DBC *d; 11650 char *errp = NULL, **params = NULL; 11651 int rc, i, size, ncols; 11652 SQLRETURN ret; 11653 11654 if (stmt == SQL_NULL_HSTMT) { 11655 return SQL_INVALID_HANDLE; 11656 } 11657 s = (STMT *) stmt; 11658 if (s->dbc == SQL_NULL_HDBC) { 11659 noconn: 11660 return noconn(s); 11661 } 11662 d = (DBC *) s->dbc; 11663 if (!d->sqlite) { 11664 goto noconn; 11665 } 11666 if (!s->query) { 11667 setstat(s, -1, "no query prepared", (*s->ov3) ? "HY000" : "S1000"); 11668 return SQL_ERROR; 11669 } 11670 if (s->nbindparms < s->nparams) { 11671 setstat(s, -1, "unbound parameters in query", 11672 (*s->ov3) ? "HY000" : "S1000"); 11673 return SQL_ERROR; 11674 } 11675 again: 11676 vm_end(s); 11677 for (i = size = 0; i < s->nparams; i++) { 11678 ret = substparam(s, i, NULL, &size); 11679 if (ret != SQL_SUCCESS) { 11680 goto cleanup; 11681 } 11682 } 11683 if (s->nparams) { 11684 char *p; 11685 11686 params = xmalloc(s->nparams * sizeof (char *) + size); 11687 if (!params) { 11688 ret = nomem(s); 11689 goto cleanup; 11690 } 11691 p = (char *) (params + s->nparams); 11692 for (i = 0; i < s->nparams; i++) { 11693 int len = 0; 11694 11695 params[i] = p; 11696 substparam(s, i, &p, NULL); 11697 if (s->bindparms[i].ind) { 11698 len = s->bindparms[i].len; 11699 } else if (s->bindparms[i].lenp) { 11700 len = *s->bindparms[i].lenp; 11701 } 11702 if (len == SQL_NULL_DATA) { 11703 params[i] = NULL; 11704 } 11705 } 11706 } 11707 freeresult(s, 0); 11708 if (!d->autocommit && !d->intrans) { 11709 rc = sqlite_exec(d->sqlite, "BEGIN TRANSACTION", NULL, NULL, &errp); 11710 dbtracerc(d, rc, errp); 11711 if (rc != SQLITE_OK) { 11712 freep(&params); 11713 setstat(s, rc, "%s (%d)", (*s->ov3) ? "HY000" : "S1000", 11714 errp ? errp : "unknown error", rc); 11715 if (errp) { 11716 sqlite_freemem(errp); 11717 errp = NULL; 11718 } 11719 ret = SQL_ERROR; 11720 goto cleanup; 11721 } 11722 d->intrans = 1; 11723 if (errp) { 11724 sqlite_freemem(errp); 11725 errp = NULL; 11726 } 11727 } 11728 if (s->isselect && !d->intrans && 11729 s->curtype == SQL_CURSOR_FORWARD_ONLY && 11730 d->step_enable && s->nparams == 0 && d->vm_stmt == NULL) { 11731 s->nrows = -1; 11732 ret = vm_start(s, params); 11733 if (ret == SQL_SUCCESS) { 11734 freep(&params); 11735 goto done2; 11736 } 11737 } 11738 rc = sqlite_get_table_vprintf(d->sqlite, s->query, &s->rows, 11739 &s->nrows, &ncols, &errp, (char *) params); 11740 dbtracerc(d, rc, errp); 11741 if (rc != SQLITE_OK) { 11742 freep(&params); 11743 setstat(s, rc, "%s (%d)", (*s->ov3) ? "HY000" : "S1000", 11744 errp ? errp : "unknown error", rc); 11745 if (errp) { 11746 sqlite_freemem(errp); 11747 errp = NULL; 11748 } 11749 ret = SQL_ERROR; 11750 goto cleanup; 11751 } 11752 freep(&params); 11753 if (errp) { 11754 sqlite_freemem(errp); 11755 errp = NULL; 11756 } 11757 s->rowfree = sqlite_free_table; 11758 if (ncols == 1 && !s->isselect) { 11759 /* 11760 * INSERT/UPDATE/DELETE results are immediately released, 11761 * but the row count is retained for SQLRowCount(). 11762 */ 11763 if (strcmp(s->rows[0], "rows inserted") == 0 || 11764 strcmp(s->rows[0], "rows updated") == 0 || 11765 strcmp(s->rows[0], "rows deleted") == 0) { 11766 int nrows = 0; 11767 11768 nrows = strtol(s->rows[1], NULL, 0); 11769 freeresult(s, -1); 11770 s->nrows = nrows; 11771 goto done; 11772 } 11773 } 11774 if (s->ncols != ncols) { 11775 int size; 11776 char *p; 11777 COL *dyncols; 11778 11779 for (i = size = 0; i < ncols; i++) { 11780 size += 3 + 3 * strlen(s->rows[i]); 11781 } 11782 if (size == 0) { 11783 freeresult(s, -1); 11784 goto done; 11785 } 11786 dyncols = xmalloc(ncols * sizeof (COL) + size); 11787 if (!dyncols) { 11788 ret = nomem(s); 11789 goto cleanup; 11790 } 11791 p = (char *) (dyncols + ncols); 11792 for (i = 0; i < ncols; i++) { 11793 char *q; 11794 11795 dyncols[i].db = d->dbname; 11796 strcpy(p, s->rows[i]); 11797 dyncols[i].label = p; 11798 p += strlen(p) + 1; 11799 q = strchr(s->rows[i], '.'); 11800 if (q) { 11801 dyncols[i].table = p; 11802 strncpy(p, s->rows[i], q - s->rows[i]); 11803 p[q - s->rows[i]] = '\0'; 11804 p += strlen(p) + 1; 11805 dyncols[i].column = q + 1; 11806 } else { 11807 dyncols[i].table = ""; 11808 dyncols[i].column = s->rows[i]; 11809 } 11810 #ifdef SQL_LONGVARCHAR 11811 dyncols[i].type = SQL_LONGVARCHAR; 11812 dyncols[i].size = 65536; 11813 #else 11814 dyncols[i].type = SQL_VARCHAR; 11815 dyncols[i].size = 255; 11816 #endif 11817 dyncols[i].index = i; 11818 dyncols[i].scale = 0; 11819 dyncols[i].prec = 0; 11820 dyncols[i].nosign = 1; 11821 dyncols[i].autoinc = -1; 11822 dyncols[i].typename = NULL; 11823 } 11824 freedyncols(s); 11825 s->ncols = s->dcols = ncols; 11826 s->dyncols = s->cols = dyncols; 11827 fixupdyncols(s, d->sqlite, NULL); 11828 } 11829 done: 11830 mkbindcols(s, s->ncols); 11831 done2: 11832 ret = SQL_SUCCESS; 11833 s->rowp = -1; 11834 if (s->nparams) { 11835 s->paramset_count++; 11836 s->paramset_nrows += s->nrows; 11837 if (s->paramset_count < s->paramset_size) { 11838 for (i = 0; i < s->nparams; i++) { 11839 BINDPARM *p = &s->bindparms[i]; 11840 11841 if (p->param && p->inc > 0) { 11842 p->param = (char *) p->param + p->inc; 11843 } 11844 } 11845 goto again; 11846 } 11847 } 11848 cleanup: 11849 if (s->nparams) { 11850 for (i = 0; i < s->nparams; i++) { 11851 BINDPARM *p = &s->bindparms[i]; 11852 11853 p->param = p->param0; 11854 } 11855 s->nrows = s->paramset_nrows; 11856 s->paramset_count = 0; 11857 s->paramset_nrows = 0; 11858 } 11859 return ret; 11860 } 11861 11862 #ifndef SQLITE_UTF8 11863 11871 SQLRETURN SQL_API 11872 SQLPrepare(SQLHSTMT stmt, SQLCHAR *query, SQLINTEGER queryLen) 11873 { 11874 return drvprepare(stmt, query, queryLen); 11875 } 11876 #endif 11877 11878 #ifdef SQLITE_UTF8 11879 11887 SQLRETURN SQL_API 11888 SQLPrepareW(SQLHSTMT stmt, SQLWCHAR *query, SQLINTEGER queryLen) 11889 { 11890 SQLRETURN ret; 11891 char *q = uc_to_utf_c(query, queryLen); 11892 11893 if (!q) { 11894 return nomem((STMT *) stmt); 11895 } 11896 ret = drvprepare(stmt, q, SQL_NTS); 11897 uc_free(q); 11898 return ret; 11899 } 11900 #endif 11901 11908 SQLRETURN SQL_API 11909 SQLExecute(SQLHSTMT stmt) 11910 { 11911 return drvexecute(stmt); 11912 } 11913 11914 #ifndef SQLITE_UTF8 11915 11923 SQLRETURN SQL_API 11924 SQLExecDirect(SQLHSTMT stmt, SQLCHAR *query, SQLINTEGER queryLen) 11925 { 11926 if (drvprepare(stmt, query, queryLen) != SQL_SUCCESS) { 11927 return SQL_ERROR; 11928 } 11929 return drvexecute(stmt); 11930 } 11931 #endif 11932 11933 #ifdef SQLITE_UTF8 11934 11942 SQLRETURN SQL_API 11943 SQLExecDirectW(SQLHSTMT stmt, SQLWCHAR *query, SQLINTEGER queryLen) 11944 { 11945 SQLRETURN ret; 11946 char *q = uc_to_utf_c(query, queryLen); 11947 11948 if (!q) { 11949 return nomem((STMT *) stmt); 11950 } 11951 ret = drvprepare(stmt, q, SQL_NTS); 11952 uc_free(q); 11953 if (ret == SQL_SUCCESS) { 11954 return drvexecute(stmt); 11955 } 11956 return ret; 11957 } 11958 #endif 11959 11960 #ifdef _WIN32 11961 #ifndef WITHOUT_DRIVERMGR 11962 11963 /* 11964 * Windows configuration dialog stuff. 11965 */ 11966 11967 #include <windowsx.h> 11968 #include <winuser.h> 11969 #include "resource.h" 11970 11971 #define stricmp _stricmp 11972 11973 static HINSTANCE NEAR hModule; /* Saved module handle for resources */ 11974 11975 #define MAXPATHLEN (255+1) /* Max path length */ 11976 #define MAXKEYLEN (15+1) /* Max keyword length */ 11977 #define MAXDESC (255+1) /* Max description length */ 11978 #define MAXDSNAME (32+1) /* Max data source name length */ 11979 #define MAXTONAME (32+1) /* Max timeout length */ 11980 #define MAXDBNAME (255+1) 11981 11982 /* Attribute key indexes into an array of Attr structs, see below */ 11983 11984 #define KEY_DSN 0 11985 #define KEY_DESC 1 11986 #define KEY_DBNAME 2 11987 #define KEY_BUSY 3 11988 #define KEY_DRIVER 4 11989 #define KEY_NOWCHAR 5 11990 #define KEY_STEPAPI 6 11991 #define NUMOFKEYS 7 11992 11993 typedef struct { 11994 BOOL supplied; 11995 char attr[MAXPATHLEN]; 11996 } ATTR; 11997 11998 typedef struct { 11999 SQLHWND parent; 12000 LPCSTR driver; 12001 ATTR attr[NUMOFKEYS]; 12002 char DSN[MAXDSNAME]; 12003 BOOL newDSN; 12004 BOOL defDSN; 12005 } SETUPDLG; 12006 12007 static struct { 12008 char *key; 12009 int ikey; 12010 } attrLookup[] = { 12011 { "DSN", KEY_DSN }, 12012 { "DESC", KEY_DESC }, 12013 { "Description", KEY_DESC}, 12014 { "Database", KEY_DBNAME }, 12015 { "Timeout", KEY_BUSY }, 12016 { "Driver", KEY_DRIVER }, 12017 { "NoWCHAR", KEY_NOWCHAR }, 12018 { "StepAPI", KEY_STEPAPI }, 12019 { NULL, 0 } 12020 }; 12021 12028 static void 12029 ParseAttributes(LPCSTR attribs, SETUPDLG *setupdlg) 12030 { 12031 char *str = (char *) attribs, *start, key[MAXKEYLEN]; 12032 int elem, nkey; 12033 12034 while (*str) { 12035 start = str; 12036 if ((str = strchr(str, '=')) == NULL) { 12037 return; 12038 } 12039 elem = -1; 12040 nkey = str - start; 12041 if (nkey < sizeof (key)) { 12042 int i; 12043 12044 memcpy(key, start, nkey); 12045 key[nkey] = '\0'; 12046 for (i = 0; attrLookup[i].key; i++) { 12047 if (stricmp(attrLookup[i].key, key) == 0) { 12048 elem = attrLookup[i].ikey; 12049 break; 12050 } 12051 } 12052 } 12053 start = ++str; 12054 while (*str && *str != ';') { 12055 ++str; 12056 } 12057 if (elem >= 0) { 12058 int end = min(str - start, sizeof (setupdlg->attr[elem].attr) - 1); 12059 12060 setupdlg->attr[elem].supplied = TRUE; 12061 memcpy(setupdlg->attr[elem].attr, start, end); 12062 setupdlg->attr[elem].attr[end] = '\0'; 12063 } 12064 ++str; 12065 } 12066 } 12067 12075 static BOOL 12076 SetDSNAttributes(HWND parent, SETUPDLG *setupdlg) 12077 { 12078 char *dsn = setupdlg->attr[KEY_DSN].attr; 12079 12080 if (setupdlg->newDSN && strlen(dsn) == 0) { 12081 return FALSE; 12082 } 12083 if (!SQLWriteDSNToIni(dsn, setupdlg->driver)) { 12084 if (parent) { 12085 char buf[MAXPATHLEN], msg[MAXPATHLEN]; 12086 12087 LoadString(hModule, IDS_BADDSN, buf, sizeof (buf)); 12088 wsprintf(msg, buf, dsn); 12089 LoadString(hModule, IDS_MSGTITLE, buf, sizeof (buf)); 12090 MessageBox(parent, msg, buf, 12091 MB_ICONEXCLAMATION | MB_OK | MB_TASKMODAL | 12092 MB_SETFOREGROUND); 12093 } 12094 return FALSE; 12095 } 12096 if (parent || setupdlg->attr[KEY_DESC].supplied) { 12097 SQLWritePrivateProfileString(dsn, "Description", 12098 setupdlg->attr[KEY_DESC].attr, 12099 ODBC_INI); 12100 } 12101 if (parent || setupdlg->attr[KEY_DBNAME].supplied) { 12102 SQLWritePrivateProfileString(dsn, "Database", 12103 setupdlg->attr[KEY_DBNAME].attr, 12104 ODBC_INI); 12105 } 12106 if (parent || setupdlg->attr[KEY_BUSY].supplied) { 12107 SQLWritePrivateProfileString(dsn, "Timeout", 12108 setupdlg->attr[KEY_BUSY].attr, 12109 ODBC_INI); 12110 } 12111 if (parent || setupdlg->attr[KEY_NOWCHAR].supplied) { 12112 SQLWritePrivateProfileString(dsn, "NoWCHAR", 12113 setupdlg->attr[KEY_NOWCHAR].attr, 12114 ODBC_INI); 12115 } 12116 if (parent || setupdlg->attr[KEY_STEPAPI].supplied) { 12117 SQLWritePrivateProfileString(dsn, "StepAPI", 12118 setupdlg->attr[KEY_STEPAPI].attr, 12119 ODBC_INI); 12120 } 12121 if (setupdlg->attr[KEY_DSN].supplied && 12122 stricmp(setupdlg->DSN, setupdlg->attr[KEY_DSN].attr)) { 12123 SQLRemoveDSNFromIni(setupdlg->DSN); 12124 } 12125 return TRUE; 12126 } 12127 12133 static void 12134 GetAttributes(SETUPDLG *setupdlg) 12135 { 12136 char *dsn = setupdlg->attr[KEY_DSN].attr; 12137 12138 if (!setupdlg->attr[KEY_DESC].supplied) { 12139 SQLGetPrivateProfileString(dsn, "Description", "", 12140 setupdlg->attr[KEY_DESC].attr, 12141 sizeof (setupdlg->attr[KEY_DESC].attr), 12142 ODBC_INI); 12143 } 12144 if (!setupdlg->attr[KEY_DBNAME].supplied) { 12145 SQLGetPrivateProfileString(dsn, "Database", "", 12146 setupdlg->attr[KEY_DBNAME].attr, 12147 sizeof (setupdlg->attr[KEY_DBNAME].attr), 12148 ODBC_INI); 12149 } 12150 if (!setupdlg->attr[KEY_BUSY].supplied) { 12151 SQLGetPrivateProfileString(dsn, "Timeout", "1000", 12152 setupdlg->attr[KEY_BUSY].attr, 12153 sizeof (setupdlg->attr[KEY_BUSY].attr), 12154 ODBC_INI); 12155 } 12156 if (!setupdlg->attr[KEY_NOWCHAR].supplied) { 12157 SQLGetPrivateProfileString(dsn, "NoWCHAR", "", 12158 setupdlg->attr[KEY_NOWCHAR].attr, 12159 sizeof (setupdlg->attr[KEY_NOWCHAR].attr), 12160 ODBC_INI); 12161 } 12162 if (!setupdlg->attr[KEY_STEPAPI].supplied) { 12163 SQLGetPrivateProfileString(dsn, "StepAPI", "0", 12164 setupdlg->attr[KEY_STEPAPI].attr, 12165 sizeof (setupdlg->attr[KEY_STEPAPI].attr), 12166 ODBC_INI); 12167 } 12168 } 12169 12175 static void 12176 GetDBFile(HWND hdlg) 12177 { 12178 SETUPDLG *setupdlg = (SETUPDLG *) GetWindowLong(hdlg, DWL_USER); 12179 OPENFILENAME ofn; 12180 12181 memset(&ofn, 0, sizeof (ofn)); 12182 ofn.lStructSize = sizeof (ofn); 12183 ofn.hwndOwner = hdlg; 12184 ofn.hInstance = (HINSTANCE) GetWindowLong(hdlg, GWL_HINSTANCE); 12185 ofn.lpstrFile = (LPTSTR) setupdlg->attr[KEY_DBNAME].attr; 12186 ofn.nMaxFile = MAXPATHLEN; 12187 ofn.Flags = OFN_HIDEREADONLY | OFN_PATHMUSTEXIST | 12188 OFN_NOCHANGEDIR | OFN_EXPLORER | OFN_FILEMUSTEXIST; 12189 if (GetOpenFileName(&ofn)) { 12190 SetDlgItemText(hdlg, IDC_DBNAME, setupdlg->attr[KEY_DBNAME].attr); 12191 setupdlg->attr[KEY_DBNAME].supplied = TRUE; 12192 } 12193 } 12194 12204 static BOOL CALLBACK 12205 ConfigDlgProc(HWND hdlg, WORD wmsg, WPARAM wparam, LPARAM lparam) 12206 { 12207 SETUPDLG *setupdlg = NULL; 12208 12209 switch (wmsg) { 12210 case WM_INITDIALOG: 12211 SetWindowLong(hdlg, DWL_USER, lparam); 12212 setupdlg = (SETUPDLG *) lparam; 12213 GetAttributes(setupdlg); 12214 SetDlgItemText(hdlg, IDC_DSNAME, setupdlg->attr[KEY_DSN].attr); 12215 SetDlgItemText(hdlg, IDC_DESC, setupdlg->attr[KEY_DESC].attr); 12216 SetDlgItemText(hdlg, IDC_DBNAME, setupdlg->attr[KEY_DBNAME].attr); 12217 SetDlgItemText(hdlg, IDC_TONAME, setupdlg->attr[KEY_BUSY].attr); 12218 CheckDlgButton(hdlg, IDC_NOWCHAR, 12219 getbool(setupdlg->attr[KEY_NOWCHAR].attr) ? 12220 BST_CHECKED : BST_UNCHECKED); 12221 CheckDlgButton(hdlg, IDC_STEPAPI, 12222 getbool(setupdlg->attr[KEY_STEPAPI].attr) ? 12223 BST_CHECKED : BST_UNCHECKED); 12224 if (setupdlg->defDSN) { 12225 EnableWindow(GetDlgItem(hdlg, IDC_DSNAME), FALSE); 12226 EnableWindow(GetDlgItem(hdlg, IDC_DSNAMETEXT), FALSE); 12227 } else { 12228 SendDlgItemMessage(hdlg, IDC_DSNAME, 12229 EM_LIMITTEXT, (WPARAM) (MAXDSNAME - 1), 0L); 12230 SendDlgItemMessage(hdlg, IDC_DESC, 12231 EM_LIMITTEXT, (WPARAM) (MAXDESC - 1), 0L); 12232 SendDlgItemMessage(hdlg, IDC_DBNAME, 12233 EM_LIMITTEXT, (WPARAM) (MAXDBNAME - 1), 0L); 12234 SendDlgItemMessage(hdlg, IDC_TONAME, 12235 EM_LIMITTEXT, (WPARAM) (MAXTONAME - 1), 0L); 12236 } 12237 return TRUE; 12238 case WM_COMMAND: 12239 switch (GET_WM_COMMAND_ID(wparam, lparam)) { 12240 case IDC_DSNAME: 12241 if (GET_WM_COMMAND_CMD(wparam, lparam) == EN_CHANGE) { 12242 char item[MAXDSNAME]; 12243 12244 EnableWindow(GetDlgItem(hdlg, IDOK), 12245 GetDlgItemText(hdlg, IDC_DSNAME, 12246 item, sizeof (item))); 12247 return TRUE; 12248 } 12249 break; 12250 case IDC_BROWSE: 12251 GetDBFile(hdlg); 12252 break; 12253 case IDOK: 12254 setupdlg = (SETUPDLG *) GetWindowLong(hdlg, DWL_USER); 12255 if (!setupdlg->defDSN) { 12256 GetDlgItemText(hdlg, IDC_DSNAME, 12257 setupdlg->attr[KEY_DSN].attr, 12258 sizeof (setupdlg->attr[KEY_DSN].attr)); 12259 } 12260 GetDlgItemText(hdlg, IDC_DESC, 12261 setupdlg->attr[KEY_DESC].attr, 12262 sizeof (setupdlg->attr[KEY_DESC].attr)); 12263 GetDlgItemText(hdlg, IDC_DBNAME, 12264 setupdlg->attr[KEY_DBNAME].attr, 12265 sizeof (setupdlg->attr[KEY_DBNAME].attr)); 12266 GetDlgItemText(hdlg, IDC_TONAME, 12267 setupdlg->attr[KEY_BUSY].attr, 12268 sizeof (setupdlg->attr[KEY_BUSY].attr)); 12269 strcpy(setupdlg->attr[KEY_NOWCHAR].attr, 12270 IsDlgButtonChecked(hdlg, IDC_NOWCHAR) == BST_CHECKED ? 12271 "1" : "0"); 12272 strcpy(setupdlg->attr[KEY_STEPAPI].attr, 12273 IsDlgButtonChecked(hdlg, IDC_STEPAPI) == BST_CHECKED ? 12274 "1" : "0"); 12275 SetDSNAttributes(hdlg, setupdlg); 12276 /* FALL THROUGH */ 12277 case IDCANCEL: 12278 EndDialog(hdlg, wparam); 12279 return TRUE; 12280 } 12281 break; 12282 } 12283 return FALSE; 12284 } 12285 12295 BOOL INSTAPI 12296 ConfigDSN(HWND hwnd, WORD request, LPCSTR driver, LPCSTR attribs) 12297 { 12298 BOOL success; 12299 SETUPDLG *setupdlg; 12300 12301 setupdlg = (SETUPDLG *) xmalloc(sizeof (SETUPDLG)); 12302 if (setupdlg == NULL) { 12303 return FALSE; 12304 } 12305 memset(setupdlg, 0, sizeof (SETUPDLG)); 12306 if (attribs) { 12307 ParseAttributes(attribs, setupdlg); 12308 } 12309 if (setupdlg->attr[KEY_DSN].supplied) { 12310 strcpy(setupdlg->DSN, setupdlg->attr[KEY_DSN].attr); 12311 } else { 12312 setupdlg->DSN[0] = '\0'; 12313 } 12314 if (request == ODBC_REMOVE_DSN) { 12315 if (!setupdlg->attr[KEY_DSN].supplied) { 12316 success = FALSE; 12317 } else { 12318 success = SQLRemoveDSNFromIni(setupdlg->attr[KEY_DSN].attr); 12319 } 12320 } else { 12321 setupdlg->parent = hwnd; 12322 setupdlg->driver = driver; 12323 setupdlg->newDSN = request == ODBC_ADD_DSN; 12324 setupdlg->defDSN = stricmp(setupdlg->attr[KEY_DSN].attr, 12325 "Default") == 0; 12326 if (hwnd) { 12327 success = DialogBoxParam(hModule, MAKEINTRESOURCE(CONFIGDSN), 12328 hwnd, (DLGPROC) ConfigDlgProc, 12329 (LONG) setupdlg) == IDOK; 12330 } else if (setupdlg->attr[KEY_DSN].supplied) { 12331 success = SetDSNAttributes(hwnd, setupdlg); 12332 } else { 12333 success = FALSE; 12334 } 12335 } 12336 xfree(setupdlg); 12337 return success; 12338 } 12339 12349 static BOOL CALLBACK 12350 DriverConnectProc(HWND hdlg, WORD wmsg, WPARAM wparam, LPARAM lparam) 12351 { 12352 SETUPDLG *setupdlg; 12353 12354 switch (wmsg) { 12355 case WM_INITDIALOG: 12356 SetWindowLong(hdlg, DWL_USER, lparam); 12357 setupdlg = (SETUPDLG *) lparam; 12358 SetDlgItemText(hdlg, IDC_DSNAME, setupdlg->attr[KEY_DSN].attr); 12359 SetDlgItemText(hdlg, IDC_DESC, setupdlg->attr[KEY_DESC].attr); 12360 SetDlgItemText(hdlg, IDC_DBNAME, setupdlg->attr[KEY_DBNAME].attr); 12361 SetDlgItemText(hdlg, IDC_TONAME, setupdlg->attr[KEY_BUSY].attr); 12362 SendDlgItemMessage(hdlg, IDC_DSNAME, 12363 EM_LIMITTEXT, (WPARAM) (MAXDSNAME - 1), 0L); 12364 SendDlgItemMessage(hdlg, IDC_DESC, 12365 EM_LIMITTEXT, (WPARAM) (MAXDESC - 1), 0L); 12366 SendDlgItemMessage(hdlg, IDC_DBNAME, 12367 EM_LIMITTEXT, (WORD)(MAXDBNAME - 1), 0L); 12368 SendDlgItemMessage(hdlg, IDC_TONAME, 12369 EM_LIMITTEXT, (WORD)(MAXTONAME - 1), 0L); 12370 CheckDlgButton(hdlg, IDC_NOWCHAR, 12371 getbool(setupdlg->attr[KEY_NOWCHAR].attr) ? 12372 BST_CHECKED : BST_UNCHECKED); 12373 CheckDlgButton(hdlg, IDC_STEPAPI, 12374 getbool(setupdlg->attr[KEY_STEPAPI].attr) ? 12375 BST_CHECKED : BST_UNCHECKED); 12376 return TRUE; 12377 case WM_COMMAND: 12378 switch (GET_WM_COMMAND_ID(wparam, lparam)) { 12379 case IDC_BROWSE: 12380 GetDBFile(hdlg); 12381 break; 12382 case IDOK: 12383 setupdlg = (SETUPDLG *) GetWindowLong(hdlg, DWL_USER); 12384 GetDlgItemText(hdlg, IDC_DSNAME, 12385 setupdlg->attr[KEY_DSN].attr, 12386 sizeof (setupdlg->attr[KEY_DSN].attr)); 12387 GetDlgItemText(hdlg, IDC_DBNAME, 12388 setupdlg->attr[KEY_DBNAME].attr, 12389 sizeof (setupdlg->attr[KEY_DBNAME].attr)); 12390 GetDlgItemText(hdlg, IDC_TONAME, 12391 setupdlg->attr[KEY_BUSY].attr, 12392 sizeof (setupdlg->attr[KEY_BUSY].attr)); 12393 strcpy(setupdlg->attr[KEY_NOWCHAR].attr, 12394 IsDlgButtonChecked(hdlg, IDC_NOWCHAR) == BST_CHECKED ? 12395 "1" : "0"); 12396 strcpy(setupdlg->attr[KEY_STEPAPI].attr, 12397 IsDlgButtonChecked(hdlg, IDC_STEPAPI) == BST_CHECKED ? 12398 "1" : "0"); 12399 /* FALL THROUGH */ 12400 case IDCANCEL: 12401 EndDialog(hdlg, GET_WM_COMMAND_ID(wparam, lparam) == IDOK); 12402 return TRUE; 12403 } 12404 } 12405 return FALSE; 12406 } 12407 12421 static SQLRETURN 12422 drvdriverconnect(SQLHDBC dbc, SQLHWND hwnd, 12423 SQLCHAR *connIn, SQLSMALLINT connInLen, 12424 SQLCHAR *connOut, SQLSMALLINT connOutMax, 12425 SQLSMALLINT *connOutLen, SQLUSMALLINT drvcompl) 12426 { 12427 BOOL maybeprompt, prompt = FALSE; 12428 DBC *d; 12429 SETUPDLG *setupdlg; 12430 short ret; 12431 SQLRETURN rc; 12432 12433 if (dbc == SQL_NULL_HDBC) { 12434 return SQL_INVALID_HANDLE; 12435 } 12436 d = (DBC *) dbc; 12437 if (d->sqlite) { 12438 setstatd(d, -1, "connection already established", "08002"); 12439 return SQL_ERROR; 12440 } 12441 setupdlg = (SETUPDLG *) xmalloc(sizeof (SETUPDLG)); 12442 if (setupdlg == NULL) { 12443 return SQL_ERROR; 12444 } 12445 memset(setupdlg, 0, sizeof (SETUPDLG)); 12446 maybeprompt = drvcompl == SQL_DRIVER_COMPLETE || 12447 drvcompl == SQL_DRIVER_COMPLETE_REQUIRED; 12448 if (connIn == NULL || !connInLen || 12449 (connInLen == SQL_NTS && !connIn[0])) { 12450 prompt = TRUE; 12451 } else { 12452 ParseAttributes(connIn, setupdlg); 12453 if (!setupdlg->attr[KEY_DSN].attr[0] && 12454 drvcompl == SQL_DRIVER_COMPLETE_REQUIRED) { 12455 strcpy(setupdlg->attr[KEY_DSN].attr, "DEFAULT"); 12456 } 12457 GetAttributes(setupdlg); 12458 if (drvcompl == SQL_DRIVER_PROMPT || 12459 (maybeprompt && 12460 !setupdlg->attr[KEY_DSN].attr[0] || 12461 !setupdlg->attr[KEY_DBNAME].attr[0])) { 12462 prompt = TRUE; 12463 } 12464 } 12465 retry: 12466 if (prompt) { 12467 ret = DialogBoxParam(hModule, MAKEINTRESOURCE(DRIVERCONNECT), 12468 hwnd, (DLGPROC) DriverConnectProc, 12469 (LONG) setupdlg); 12470 if (!ret || ret == -1) { 12471 xfree(setupdlg); 12472 return SQL_NO_DATA_FOUND; 12473 } 12474 } 12475 if (connOut || connOutLen) { 12476 char buf[1024]; 12477 int len, count; 12478 char dsn_0 = setupdlg->attr[KEY_DSN].attr[0]; 12479 char drv_0 = setupdlg->attr[KEY_DRIVER].attr[0]; 12480 12481 buf[0] = '\0'; 12482 count = snprintf(buf, sizeof (buf), 12483 "%s%s%s%s%s%sDatabase=%s;StepAPI=%s;" 12484 "Timeout=%s;NoWCHAR=%s", 12485 dsn_0 ? "DSN=" : "", 12486 dsn_0 ? setupdlg->attr[KEY_DSN].attr : "", 12487 dsn_0 ? ";" : "", 12488 drv_0 ? "Driver=" : "", 12489 drv_0 ? setupdlg->attr[KEY_DRIVER].attr : "", 12490 drv_0 ? ";" : "", 12491 setupdlg->attr[KEY_DBNAME].attr, 12492 setupdlg->attr[KEY_STEPAPI].attr, 12493 setupdlg->attr[KEY_BUSY].attr, 12494 setupdlg->attr[KEY_NOWCHAR].attr); 12495 if (count < 0) { 12496 buf[sizeof (buf) - 1] = '\0'; 12497 } 12498 len = min(connOutMax - 1, strlen(buf)); 12499 if (connOut) { 12500 strncpy(connOut, buf, len); 12501 connOut[len] = '\0'; 12502 } 12503 if (connOutLen) { 12504 *connOutLen = len; 12505 } 12506 } 12507 d->nowchar = getbool(setupdlg->attr[KEY_NOWCHAR].attr); 12508 rc = dbopen(d, setupdlg->attr[KEY_DBNAME].attr, 12509 setupdlg->attr[KEY_DSN].attr, 12510 setupdlg->attr[KEY_STEPAPI].attr, 12511 setupdlg->attr[KEY_BUSY].attr); 12512 if (rc != SQL_SUCCESS) { 12513 if (maybeprompt && !prompt) { 12514 prompt = TRUE; 12515 goto retry; 12516 } 12517 xfree(setupdlg); 12518 return rc; 12519 } 12520 xfree(setupdlg); 12521 return SQL_SUCCESS; 12522 } 12523 12524 #endif /* WITHOUT_DRIVERMGR */ 12525 #endif /* _WIN32 */ 12526 12527 #ifndef WITHOUT_DRIVERMGR 12528 12529 #ifndef SQLITE_UTF8 12530 12543 SQLRETURN SQL_API 12544 SQLDriverConnect(SQLHDBC dbc, SQLHWND hwnd, 12545 SQLCHAR *connIn, SQLSMALLINT connInLen, 12546 SQLCHAR *connOut, SQLSMALLINT connOutMax, 12547 SQLSMALLINT *connOutLen, SQLUSMALLINT drvcompl) 12548 { 12549 return drvdriverconnect(dbc, hwnd, connIn, connInLen, 12550 connOut, connOutMax, connOutLen, drvcompl); 12551 } 12552 #endif 12553 12554 #ifdef SQLITE_UTF8 12555 12568 SQLRETURN SQL_API 12569 SQLDriverConnectW(SQLHDBC dbc, SQLHWND hwnd, 12570 SQLWCHAR *connIn, SQLSMALLINT connInLen, 12571 SQLWCHAR *connOut, SQLSMALLINT connOutMax, 12572 SQLSMALLINT *connOutLen, SQLUSMALLINT drvcompl) 12573 { 12574 SQLRETURN ret; 12575 char *ci = NULL; 12576 SQLSMALLINT len; 12577 12578 if (connIn) { 12579 ci = uc_to_utf_c(connIn, connInLen); 12580 if (!ci) { 12581 DBC *d = (DBC *) dbc; 12582 12583 setstatd(d, -1, "out of memory", (*d->ov3) ? "HY000" : "S1000"); 12584 return SQL_ERROR; 12585 } 12586 } 12587 ret = drvdriverconnect(dbc, hwnd, ci, SQL_NTS, 12588 (char *) connOut, connOutMax, &len, drvcompl); 12589 uc_free(ci); 12590 if (ret == SQL_SUCCESS) { 12591 SQLWCHAR *co = NULL; 12592 12593 if (connOut) { 12594 if (len > 0) { 12595 co = uc_from_utf((char *) connOut, len); 12596 if (co) { 12597 uc_strncpy(connOut, co, connOutMax); 12598 len = min(connOutMax, uc_strlen(co)); 12599 uc_free(co); 12600 } else { 12601 len = 0; 12602 } 12603 } 12604 if (len <= 0) { 12605 len = 0; 12606 connOut[0] = 0; 12607 } 12608 } else { 12609 len = 0; 12610 } 12611 if (connOutLen) { 12612 *connOutLen = len; 12613 } 12614 } 12615 return ret; 12616 } 12617 #endif 12618 12619 #endif /* WITHOUT_DRIVERMGR */ 12620 12621 #ifdef _WIN32 12622 12631 BOOL APIENTRY 12632 LibMain(HANDLE hinst, DWORD reason, LPVOID reserved) 12633 { 12634 static int initialized = 0; 12635 12636 switch (reason) { 12637 case DLL_PROCESS_ATTACH: 12638 if (!initialized++) { 12639 hModule = hinst; 12640 } 12641 break; 12642 case DLL_THREAD_ATTACH: 12643 break; 12644 case DLL_PROCESS_DETACH: 12645 --initialized; 12646 break; 12647 case DLL_THREAD_DETACH: 12648 break; 12649 default: 12650 break; 12651 } 12652 return TRUE; 12653 } 12654 12663 int __stdcall 12664 DllMain(HANDLE hinst, DWORD reason, LPVOID reserved) 12665 { 12666 return LibMain(hinst, reason, reserved); 12667 } 12668 12669 #endif /* _WIN32 */ 12670 12671 #if defined(HAVE_ODBCINSTEXT_H) && HAVE_ODBCINSTEXT_H 12672 12673 /* 12674 * unixODBC property page for this driver, 12675 * may or may not work depending on unixODBC version. 12676 */ 12677 12678 #include <odbcinstext.h> 12679 12680 int 12681 ODBCINSTGetProperties(HODBCINSTPROPERTY prop) 12682 { 12683 static const char *instYN[] = { "No", "Yes", NULL }; 12684 12685 prop->pNext = (HODBCINSTPROPERTY) malloc(sizeof (ODBCINSTPROPERTY)); 12686 prop = prop->pNext; 12687 memset(prop, 0, sizeof (ODBCINSTPROPERTY)); 12688 prop->nPromptType = ODBCINST_PROMPTTYPE_FILENAME; 12689 strncpy(prop->szName, "Database", INI_MAX_PROPERTY_NAME); 12690 strncpy(prop->szValue, "", INI_MAX_PROPERTY_VALUE); 12691 prop->pNext = (HODBCINSTPROPERTY) malloc(sizeof (ODBCINSTPROPERTY)); 12692 prop = prop->pNext; 12693 memset(prop, 0, sizeof (ODBCINSTPROPERTY)); 12694 prop->nPromptType = ODBCINST_PROMPTTYPE_TEXTEDIT; 12695 strncpy(prop->szName, "Timeout", INI_MAX_PROPERTY_NAME); 12696 strncpy(prop->szValue, "1000", 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_COMBOBOX; 12701 prop->aPromptData = malloc (sizeof (instYN)); 12702 memcpy(prop->aPromptData, instYN, sizeof (instYN)); 12703 strncpy(prop->szName, "StepAPI", INI_MAX_PROPERTY_NAME); 12704 strncpy(prop->szValue, "No", INI_MAX_PROPERTY_VALUE); 12705 #ifdef SQLITE_UTF8 12706 prop->pNext = (HODBCINSTPROPERTY) malloc(sizeof (ODBCINSTPROPERTY)); 12707 prop = prop->pNext; 12708 memset(prop, 0, sizeof (ODBCINSTPROPERTY)); 12709 prop->nPromptType = ODBCINST_PROMPTTYPE_COMBOBOX; 12710 prop->aPromptData = malloc (sizeof (instYN)); 12711 memcpy(prop->aPromptData, instYN, sizeof (instYN)); 12712 strncpy(prop->szName, "NoWCHAR", INI_MAX_PROPERTY_NAME); 12713 strncpy(prop->szValue, "No", INI_MAX_PROPERTY_VALUE); 12714 #endif 12715 return 1; 12716 } 12717 12718 #endif /* HAVE_ODBCINSTEXT_H */

Generated on 9 Oct 2004 by doxygen.
Contact: chw@ch-werner.de