00001
00014 #include "sqlite3odbc.h"
00015
00016 #ifndef WITHOUT_WINTERFACE
00017 #define WINTERFACE
00018 #endif
00019
00020 #ifdef WINTERFACE
00021 #include <sqlucode.h>
00022 #endif
00023
00024 #if defined(_WIN32) || defined(_WIN64)
00025 #include "resource3.h"
00026 #define ODBC_INI "ODBC.INI"
00027 #else
00028 #define ODBC_INI ".odbc.ini"
00029 #endif
00030
00031 #ifndef DRIVER_VER_INFO
00032 #define DRIVER_VER_INFO "0.0"
00033 #endif
00034
00035 #ifndef COLATTRIBUTE_LAST_ARG_TYPE
00036 #ifdef _WIN64
00037 #define COLATTRIBUTE_LAST_ARG_TYPE SQLLEN *
00038 #else
00039 #define COLATTRIBUTE_LAST_ARG_TYPE SQLPOINTER
00040 #endif
00041 #endif
00042
00043 #ifndef SETSTMTOPTION_LAST_ARG_TYPE
00044 #define SETSTMTOPTION_LAST_ARG_TYPE SQLROWCOUNT
00045 #endif
00046
00047 #undef min
00048 #define min(a, b) ((a) < (b) ? (a) : (b))
00049 #undef max
00050 #define max(a, b) ((a) < (b) ? (b) : (a))
00051
00052 #ifndef PTRDIFF_T
00053 #define PTRDIFF_T int
00054 #endif
00055
00056 #define array_size(x) (sizeof (x) / sizeof (x[0]))
00057
00058 #define stringify1(s) #s
00059 #define stringify(s) stringify1(s)
00060
00061 #define verinfo(maj, min, lev) ((maj) << 16 | (min) << 8 | (lev))
00062
00063
00064
00065 #if defined(WINTERFACE) && !defined(_WIN32) && !defined(_WIN64)
00066 #define SCOL_VARCHAR SQL_WVARCHAR
00067 #define SCOL_CHAR SQL_WCHAR
00068 #else
00069 #define SCOL_VARCHAR SQL_VARCHAR
00070 #define SCOL_CHAR SQL_CHAR
00071 #endif
00072
00073 #define ENV_MAGIC 0x53544145
00074 #define DBC_MAGIC 0x53544144
00075 #define DEAD_MAGIC 0xdeadbeef
00076
00077 static const char *xdigits = "0123456789ABCDEFabcdef";
00078
00079 #ifdef MEMORY_DEBUG
00080
00081 static void *
00082 xmalloc_(int n, char *file, int line)
00083 {
00084 int nn = n + 4 * sizeof (long);
00085 long *p;
00086
00087 p = malloc(nn);
00088 if (!p) {
00089 #if (MEMORY_DEBUG > 1)
00090 fprintf(stderr, "malloc\t%d\tNULL\t%s:%d\n", n, file, line);
00091 #endif
00092 return NULL;
00093 }
00094 p[0] = 0xdead1234;
00095 nn = nn / sizeof (long) - 1;
00096 p[1] = n;
00097 p[nn] = 0xdead5678;
00098 #if (MEMORY_DEBUG > 1)
00099 fprintf(stderr, "malloc\t%d\t%p\t%s:%d\n", n, &p[2], file, line);
00100 #endif
00101 return (void *) &p[2];
00102 }
00103
00104 static void *
00105 xrealloc_(void *old, int n, char *file, int line)
00106 {
00107 int nn = n + 4 * sizeof (long), nnn;
00108 long *p, *pp;
00109
00110 if (n == 0 || !old) {
00111 return xmalloc_(n, file, line);
00112 }
00113 p = &((long *) old)[-2];
00114 if (p[0] != 0xdead1234) {
00115 fprintf(stderr, "*** low end corruption @ %p\n", old);
00116 abort();
00117 }
00118 nnn = p[1] + 4 * sizeof (long);
00119 nnn = nnn / sizeof (long) - 1;
00120 if (p[nnn] != 0xdead5678) {
00121 fprintf(stderr, "*** high end corruption @ %p\n", old);
00122 abort();
00123 }
00124 pp = realloc(p, nn);
00125 if (!pp) {
00126 #if (MEMORY_DEBUG > 1)
00127 fprintf(stderr, "realloc\t%p,%d\tNULL\t%s:%d\n", old, n, file, line);
00128 #endif
00129 return NULL;
00130 }
00131 #if (MEMORY_DEBUG > 1)
00132 fprintf(stderr, "realloc\t%p,%d\t%p\t%s:%d\n", old, n, &pp[2], file, line);
00133 #endif
00134 p = pp;
00135 p[1] = n;
00136 nn = nn / sizeof (long) - 1;
00137 p[nn] = 0xdead5678;
00138 return (void *) &p[2];
00139 }
00140
00141 static void
00142 xfree_(void *x, char *file, int line)
00143 {
00144 long *p;
00145 int n;
00146
00147 if (!x) {
00148 return;
00149 }
00150 p = &((long *) x)[-2];
00151 if (p[0] != 0xdead1234) {
00152 fprintf(stderr, "*** low end corruption @ %p\n", x);
00153 abort();
00154 }
00155 n = p[1] + 4 * sizeof (long);
00156 n = n / sizeof (long) - 1;
00157 if (p[n] != 0xdead5678) {
00158 fprintf(stderr, "*** high end corruption @ %p\n", x);
00159 abort();
00160 }
00161 #if (MEMORY_DEBUG > 1)
00162 fprintf(stderr, "free\t%p\t\t%s:%d\n", x, file, line);
00163 #endif
00164 free(p);
00165 }
00166
00167 static void
00168 xfree__(void *x)
00169 {
00170 xfree_(x, "unknown location", 0);
00171 }
00172
00173 static char *
00174 xstrdup_(const char *str, char *file, int line)
00175 {
00176 char *p;
00177
00178 if (!str) {
00179 #if (MEMORY_DEBUG > 1)
00180 fprintf(stderr, "strdup\tNULL\tNULL\t%s:%d\n", file, line);
00181 #endif
00182 return NULL;
00183 }
00184 p = xmalloc_(strlen(str) + 1, file, line);
00185 if (p) {
00186 strcpy(p, str);
00187 }
00188 #if (MEMORY_DEBUG > 1)
00189 fprintf(stderr, "strdup\t%p\t%p\t%s:%d\n", str, p, file, line);
00190 #endif
00191 return p;
00192 }
00193
00194 #define xmalloc(x) xmalloc_(x, __FILE__, __LINE__)
00195 #define xrealloc(x,y) xrealloc_(x, y, __FILE__, __LINE__)
00196 #define xfree(x) xfree_(x, __FILE__, __LINE__)
00197 #define xstrdup(x) xstrdup_(x, __FILE__, __LINE__)
00198
00199 #else
00200
00201 #define xmalloc(x) malloc(x)
00202 #define xrealloc(x,y) realloc(x, y)
00203 #define xfree(x) free(x)
00204 #define xstrdup(x) strdup_(x)
00205
00206 #endif
00207
00208 #if defined(_WIN32) || defined(_WIN64)
00209
00210 #define vsnprintf _vsnprintf
00211 #define snprintf _snprintf
00212 #define strcasecmp _stricmp
00213 #define strncasecmp _strnicmp
00214
00215 static HINSTANCE NEAR hModule;
00216
00217 #endif
00218
00219 #if defined(_WIN32) || defined(_WIN64)
00220
00221
00222
00223
00224
00225
00226 #define HDBC_LOCK(hdbc) \
00227 { \
00228 DBC *d; \
00229 \
00230 if ((hdbc) == SQL_NULL_HDBC) { \
00231 return SQL_INVALID_HANDLE; \
00232 } \
00233 d = (DBC *) (hdbc); \
00234 if (d->magic != DBC_MAGIC || !d->env) { \
00235 return SQL_INVALID_HANDLE; \
00236 } \
00237 if (d->env->magic != ENV_MAGIC) { \
00238 return SQL_INVALID_HANDLE; \
00239 } \
00240 EnterCriticalSection(&d->env->cs); \
00241 d->env->owner = GetCurrentThreadId(); \
00242 }
00243
00244 #define HDBC_UNLOCK(hdbc) \
00245 if ((hdbc) != SQL_NULL_HDBC) { \
00246 DBC *d; \
00247 \
00248 d = (DBC *) (hdbc); \
00249 if (d->magic == DBC_MAGIC && d->env && \
00250 d->env->magic == ENV_MAGIC) { \
00251 d->env->owner = 0; \
00252 LeaveCriticalSection(&d->env->cs); \
00253 } \
00254 }
00255
00256 #define HSTMT_LOCK(hstmt) \
00257 { \
00258 DBC *d; \
00259 \
00260 if ((hstmt) == SQL_NULL_HSTMT) { \
00261 return SQL_INVALID_HANDLE; \
00262 } \
00263 d = (DBC *) ((STMT *) (hstmt))->dbc; \
00264 if (d->magic != DBC_MAGIC || !d->env) { \
00265 return SQL_INVALID_HANDLE; \
00266 } \
00267 if (d->env->magic != ENV_MAGIC) { \
00268 return SQL_INVALID_HANDLE; \
00269 } \
00270 EnterCriticalSection(&d->env->cs); \
00271 d->env->owner = GetCurrentThreadId(); \
00272 }
00273
00274 #define HSTMT_UNLOCK(hstmt) \
00275 if ((hstmt) != SQL_NULL_HSTMT) { \
00276 DBC *d; \
00277 \
00278 d = (DBC *) ((STMT *) (hstmt))->dbc; \
00279 if (d->magic == DBC_MAGIC && d->env && \
00280 d->env->magic == ENV_MAGIC) { \
00281 d->env->owner = 0; \
00282 LeaveCriticalSection(&d->env->cs); \
00283 } \
00284 }
00285
00286 #else
00287
00288
00289
00290
00291
00292
00293
00294
00295
00296
00297
00298
00299
00300
00301
00302
00303
00304
00305
00306
00307
00308 #define HDBC_LOCK(hdbc)
00309 #define HDBC_UNLOCK(hdbc)
00310 #define HSTMT_LOCK(hdbc)
00311 #define HSTMT_UNLOCK(hdbc)
00312
00313 #endif
00314
00315 #if defined(ENABLE_NVFS) && ENABLE_NVFS
00316 extern void nvfs_init(void);
00317 extern const char *nvfs_makevfs(const char *);
00318 #endif
00319
00320
00321
00322
00323
00324 static const char upper_chars[] = "ABCDEFGHIJKLMNOPQRSTUVWXYZ";
00325 static const char lower_chars[] = "abcdefghijklmnopqrstuvwxyz";
00326
00327 static int
00328 TOLOWER(int c)
00329 {
00330 if (c) {
00331 char *p = strchr(upper_chars, c);
00332
00333 if (p) {
00334 c = lower_chars[p - upper_chars];
00335 }
00336 }
00337 return c;
00338 }
00339
00340
00341
00342
00343
00344 static const char digit_chars[] = "0123456789";
00345
00346 #define ISDIGIT(c) \
00347 ((c) && strchr(digit_chars, (c)) != NULL)
00348
00349
00350
00351
00352
00353 static const char space_chars[] = " \f\n\r\t\v";
00354
00355 #define ISSPACE(c) \
00356 ((c) && strchr(space_chars, (c)) != NULL)
00357
00358
00359
00360
00361
00362
00363 static void dbtraceapi(DBC *d, char *fn, const char *sql);
00364 static void freedyncols(STMT *s);
00365 static void freeresult(STMT *s, int clrcols);
00366 static void freerows(char **rowp);
00367 static void unbindcols(STMT *s);
00368 static void s3stmt_drop(STMT *s);
00369
00370 static SQLRETURN drvexecute(SQLHSTMT stmt, int initial);
00371 static SQLRETURN freestmt(HSTMT stmt);
00372 static SQLRETURN mkbindcols(STMT *s, int ncols);
00373 static SQLRETURN setupdyncols(STMT *s, sqlite3_stmt *s3stmt, int *ncolsp);
00374 static SQLRETURN setupparbuf(STMT *s, BINDPARM *p);
00375 static SQLRETURN starttran(STMT *s);
00376 static SQLRETURN setupparam(STMT *s, char *sql, int pnum);
00377
00378 #if (defined(_WIN32) || defined(_WIN64)) && defined(WINTERFACE)
00379
00380 static COL *statSpec2P, *statSpec3P;
00381 #endif
00382
00383 #if (MEMORY_DEBUG < 1)
00384
00390 static char *
00391 strdup_(const char *str)
00392 {
00393 char *p = NULL;
00394
00395 if (str) {
00396 p = xmalloc(strlen(str) + 1);
00397 if (p) {
00398 strcpy(p, str);
00399 }
00400 }
00401 return p;
00402 }
00403 #endif
00404
00405 #ifdef WINTERFACE
00406
00413 static int
00414 uc_strlen(SQLWCHAR *str)
00415 {
00416 int len = 0;
00417
00418 if (str) {
00419 while (*str) {
00420 ++len;
00421 ++str;
00422 }
00423 }
00424 return len;
00425 }
00426
00435 static SQLWCHAR *
00436 uc_strncpy(SQLWCHAR *dest, SQLWCHAR *src, int len)
00437 {
00438 int i = 0;
00439
00440 while (i < len) {
00441 if (!src[i]) {
00442 break;
00443 }
00444 dest[i] = src[i];
00445 ++i;
00446 }
00447 if (i < len) {
00448 dest[i] = 0;
00449 }
00450 return dest;
00451 }
00452
00461 static void
00462 uc_from_utf_buf(unsigned char *str, int len, SQLWCHAR *uc, int ucLen)
00463 {
00464 ucLen = ucLen / sizeof (SQLWCHAR);
00465 if (!uc || ucLen < 0) {
00466 return;
00467 }
00468 if (len < 0) {
00469 len = ucLen * 5;
00470 }
00471 uc[0] = 0;
00472 if (str) {
00473 int i = 0;
00474
00475 while (i < len && *str && i < ucLen) {
00476 unsigned char c = str[0];
00477
00478 if (c < 0xc0) {
00479 uc[i++] = c;
00480 ++str;
00481 } else if (c < 0xe0) {
00482 if ((str[1] & 0xc0) == 0x80) {
00483 unsigned long t = ((c & 0x1f) << 6) | (str[1] & 0x3f);
00484
00485 uc[i++] = t;
00486 str += 2;
00487 } else {
00488 uc[i++] = c;
00489 ++str;
00490 }
00491 } else if (c < 0xf0) {
00492 if ((str[1] & 0xc0) == 0x80 && (str[2] & 0xc0) == 0x80) {
00493 unsigned long t = ((c & 0x0f) << 12) |
00494 ((str[1] & 0x3f) << 6) | (str[2] & 0x3f);
00495
00496 uc[i++] = t;
00497 str += 3;
00498 } else {
00499 uc[i++] = c;
00500 ++str;
00501 }
00502 } else if (c < 0xf8) {
00503 if ((str[1] & 0xc0) == 0x80 && (str[2] & 0xc0) == 0x80 &&
00504 (str[3] & 0xc0) == 0x80) {
00505 unsigned long t = ((c & 0x03) << 18) |
00506 ((str[1] & 0x3f) << 12) | ((str[2] & 0x3f) << 6) |
00507 (str[4] & 0x3f);
00508
00509 if (sizeof (SQLWCHAR) == 2 * sizeof (char) &&
00510 t >= 0x10000) {
00511 t -= 0x10000;
00512 uc[i++] = 0xd800 | (t & 0x3ff);
00513 if (i >= ucLen) {
00514 break;
00515 }
00516 t = 0xdc00 | ((t >> 10) & 0x3ff);
00517 }
00518 uc[i++] = t;
00519 str += 4;
00520 } else {
00521 uc[i++] = c;
00522 ++str;
00523 }
00524 } else if (c < 0xfc) {
00525 if ((str[1] & 0xc0) == 0x80 && (str[2] & 0xc0) == 0x80 &&
00526 (str[3] & 0xc0) == 0x80 && (str[4] & 0xc0) == 0x80) {
00527 unsigned long t = ((c & 0x01) << 24) |
00528 ((str[1] & 0x3f) << 18) | ((str[2] & 0x3f) << 12) |
00529 ((str[4] & 0x3f) << 6) | (str[5] & 0x3f);
00530
00531 if (sizeof (SQLWCHAR) == 2 * sizeof (char) &&
00532 t >= 0x10000) {
00533 t -= 0x10000;
00534 uc[i++] = 0xd800 | (t & 0x3ff);
00535 if (i >= ucLen) {
00536 break;
00537 }
00538 t = 0xdc00 | ((t >> 10) & 0x3ff);
00539 }
00540 uc[i++] = t;
00541 str += 5;
00542 } else {
00543 uc[i++] = c;
00544 ++str;
00545 }
00546 } else {
00547
00548 ++str;
00549 }
00550 }
00551 if (i < ucLen) {
00552 uc[i] = 0;
00553 }
00554 }
00555 }
00556
00564 static SQLWCHAR *
00565 uc_from_utf(unsigned char *str, int len)
00566 {
00567 SQLWCHAR *uc = NULL;
00568 int ucLen;
00569
00570 if (str) {
00571 if (len == SQL_NTS) {
00572 len = strlen((char *) str);
00573 }
00574 ucLen = sizeof (SQLWCHAR) * (len + 1);
00575 uc = xmalloc(ucLen);
00576 if (uc) {
00577 uc_from_utf_buf(str, len, uc, ucLen);
00578 }
00579 }
00580 return uc;
00581 }
00582
00590 static char *
00591 uc_to_utf(SQLWCHAR *str, int len)
00592 {
00593 int i;
00594 char *cp, *ret = NULL;
00595
00596 if (!str) {
00597 return ret;
00598 }
00599 if (len == SQL_NTS) {
00600 len = uc_strlen(str);
00601 } else {
00602 len = len / sizeof (SQLWCHAR);
00603 }
00604 cp = xmalloc(len * 6 + 1);
00605 if (!cp) {
00606 return ret;
00607 }
00608 ret = cp;
00609 for (i = 0; i < len; i++) {
00610 unsigned long c = str[i];
00611
00612 if (sizeof (SQLWCHAR) == 2 * sizeof (char)) {
00613 c &= 0xffff;
00614 }
00615 if (c < 0xc0) {
00616 *cp++ = c;
00617 } else if (c < 0x800) {
00618 *cp++ = 0xc0 | ((c >> 6) & 0x1f);
00619 *cp++ = 0x80 | (c & 0x3f);
00620 } else if (c < 0x10000) {
00621 if (sizeof (SQLWCHAR) == 2 * sizeof (char) &&
00622 c >= 0xd800 && c <= 0xdbff && i + 1 < len) {
00623 unsigned long c2 = str[i + 1] & 0xffff;
00624
00625 if (c2 >= 0xdc00 && c <= 0xdfff) {
00626 c = ((c & 0x3ff) | ((c2 & 0x3ff) << 10)) + 0x10000;
00627 *cp++ = 0xf0 | ((c >> 18) & 0x07);
00628 *cp++ = 0x80 | ((c >> 12) & 0x3f);
00629 *cp++ = 0x80 | ((c >> 6) & 0x3f);
00630 *cp++ = 0x80 | (c & 0x3f);
00631 ++i;
00632 continue;
00633 }
00634 }
00635 *cp++ = 0xe0 | ((c >> 12) & 0x0f);
00636 *cp++ = 0x80 | ((c >> 6) & 0x3f);
00637 *cp++ = 0x80 | (c & 0x3f);
00638 } else if (c < 0x200000) {
00639 *cp++ = 0xf0 | ((c >> 18) & 0x07);
00640 *cp++ = 0x80 | ((c >> 12) & 0x3f);
00641 *cp++ = 0x80 | ((c >> 6) & 0x3f);
00642 *cp++ = 0x80 | (c & 0x3f);
00643 } else if (c < 0x4000000) {
00644 *cp++ = 0xf8 | ((c >> 24) & 0x03);
00645 *cp++ = 0x80 | ((c >> 18) & 0x3f);
00646 *cp++ = 0x80 | ((c >> 12) & 0x3f);
00647 *cp++ = 0x80 | ((c >> 6) & 0x3f);
00648 *cp++ = 0x80 | (c & 0x3f);
00649 } else if (c < 0x80000000) {
00650 *cp++ = 0xfc | ((c >> 31) & 0x01);
00651 *cp++ = 0x80 | ((c >> 24) & 0x3f);
00652 *cp++ = 0x80 | ((c >> 18) & 0x3f);
00653 *cp++ = 0x80 | ((c >> 12) & 0x3f);
00654 *cp++ = 0x80 | ((c >> 6) & 0x3f);
00655 *cp++ = 0x80 | (c & 0x3f);
00656 }
00657 }
00658 *cp = '\0';
00659 return ret;
00660 }
00661
00669 static char *
00670 uc_to_utf_c(SQLWCHAR *str, int len)
00671 {
00672 if (len != SQL_NTS) {
00673 len = len * sizeof (SQLWCHAR);
00674 }
00675 return uc_to_utf(str, len);
00676 }
00677
00678 #endif
00679
00680 #if defined(WINTERFACE) || defined(_WIN32) || defined(_WIN64)
00681
00687 static void
00688 uc_free(void *str)
00689 {
00690 if (str) {
00691 xfree(str);
00692 }
00693 }
00694
00695 #endif
00696
00697 #if defined(_WIN32) || defined(_WIN64)
00698
00706 static char *
00707 wmb_to_utf(char *str, int len)
00708 {
00709 WCHAR *wstr;
00710 OSVERSIONINFO ovi;
00711 int nchar, is2k, cp = CP_OEMCP;
00712
00713 ovi.dwOSVersionInfoSize = sizeof (ovi);
00714 GetVersionEx(&ovi);
00715 is2k = ovi.dwPlatformId == VER_PLATFORM_WIN32_NT && ovi.dwMajorVersion > 4;
00716 if (AreFileApisANSI()) {
00717 cp = is2k ? CP_THREAD_ACP : CP_ACP;
00718 }
00719 nchar = MultiByteToWideChar(cp, 0, str, len, NULL, 0);
00720 wstr = xmalloc((nchar + 1) * sizeof (WCHAR));
00721 if (!wstr) {
00722 return NULL;
00723 }
00724 wstr[0] = 0;
00725 nchar = MultiByteToWideChar(cp, 0, str, len, wstr, nchar);
00726 wstr[nchar] = 0;
00727 str = xmalloc((nchar + 1) * 7);
00728 if (!str) {
00729 xfree(wstr);
00730 return NULL;
00731 }
00732 str[0] = '\0';
00733 nchar = WideCharToMultiByte(CP_UTF8, 0, wstr, -1, str, nchar * 7, 0, 0);
00734 str[nchar] = '\0';
00735 xfree(wstr);
00736 return str;
00737 }
00738
00746 static char *
00747 utf_to_wmb(char *str, int len)
00748 {
00749 WCHAR *wstr;
00750 OSVERSIONINFO ovi;
00751 int nchar, is2k, cp = CP_OEMCP;
00752
00753 ovi.dwOSVersionInfoSize = sizeof (ovi);
00754 GetVersionEx(&ovi);
00755 is2k = ovi.dwPlatformId == VER_PLATFORM_WIN32_NT && ovi.dwMajorVersion > 4;
00756 if (AreFileApisANSI()) {
00757 cp = is2k ? CP_THREAD_ACP : CP_ACP;
00758 }
00759 nchar = MultiByteToWideChar(CP_UTF8, 0, str, len, NULL, 0);
00760 wstr = xmalloc((nchar + 1) * sizeof (WCHAR));
00761 if (!wstr) {
00762 return NULL;
00763 }
00764 wstr[0] = 0;
00765 nchar = MultiByteToWideChar(CP_UTF8, 0, str, len, wstr, nchar);
00766 wstr[nchar] = 0;
00767 str = xmalloc((nchar + 1) * 7);
00768 if (!str) {
00769 xfree(wstr);
00770 return NULL;
00771 }
00772 str[0] = '\0';
00773 nchar = WideCharToMultiByte(cp, 0, wstr, -1, str, nchar * 7, 0, 0);
00774 str[nchar] = '\0';
00775 xfree(wstr);
00776 return str;
00777 }
00778
00779 #ifdef WINTERFACE
00780
00788 static WCHAR *
00789 wmb_to_uc(char *str, int len)
00790 {
00791 WCHAR *wstr;
00792 OSVERSIONINFO ovi;
00793 int nchar, is2k, cp = CP_OEMCP;
00794
00795 ovi.dwOSVersionInfoSize = sizeof (ovi);
00796 GetVersionEx(&ovi);
00797 is2k = ovi.dwPlatformId == VER_PLATFORM_WIN32_NT && ovi.dwMajorVersion > 4;
00798 if (AreFileApisANSI()) {
00799 cp = is2k ? CP_THREAD_ACP : CP_ACP;
00800 }
00801 nchar = MultiByteToWideChar(cp, 0, str, len, NULL, 0);
00802 wstr = xmalloc((nchar + 1) * sizeof (WCHAR));
00803 if (!wstr) {
00804 return NULL;
00805 }
00806 wstr[0] = 0;
00807 nchar = MultiByteToWideChar(cp, 0, str, len, wstr, nchar);
00808 wstr[nchar] = 0;
00809 return wstr;
00810 }
00811
00819 static char *
00820 uc_to_wmb(WCHAR *wstr, int len)
00821 {
00822 char *str;
00823 OSVERSIONINFO ovi;
00824 int nchar, is2k, cp = CP_OEMCP;
00825
00826 ovi.dwOSVersionInfoSize = sizeof (ovi);
00827 GetVersionEx(&ovi);
00828 is2k = ovi.dwPlatformId == VER_PLATFORM_WIN32_NT && ovi.dwMajorVersion > 4;
00829 if (AreFileApisANSI()) {
00830 cp = is2k ? CP_THREAD_ACP : CP_ACP;
00831 }
00832 nchar = WideCharToMultiByte(cp, 0, wstr, len, NULL, 0, 0, 0);
00833 str = xmalloc((nchar + 1) * 2);
00834 if (!str) {
00835 return NULL;
00836 }
00837 str[0] = '\0';
00838 nchar = WideCharToMultiByte(cp, 0, wstr, len, str, nchar * 2, 0, 0);
00839 str[nchar] = '\0';
00840 return str;
00841 }
00842
00843 #endif
00844
00845 #endif
00846
00847
00848 #ifdef USE_DLOPEN_FOR_GPPS
00849
00850 #include <dlfcn.h>
00851
00852 #define SQLGetPrivateProfileString(A,B,C,D,E,F) drvgpps(d,A,B,C,D,E,F)
00853
00854
00855
00856
00857
00858
00859
00860
00861 static void
00862 drvgetgpps(DBC *d)
00863 {
00864 void *lib;
00865 int (*gpps)();
00866
00867 lib = dlopen("libodbcinst.so.1", RTLD_LAZY);
00868 if (!lib) {
00869 lib = dlopen("libodbcinst.so", RTLD_LAZY);
00870 }
00871 if (!lib) {
00872 lib = dlopen("libiodbcinst.so.2", RTLD_LAZY);
00873 }
00874 if (!lib) {
00875 lib = dlopen("libiodbcinst.so", RTLD_LAZY);
00876 }
00877 if (lib) {
00878 gpps = (int (*)()) dlsym(lib, "SQLGetPrivateProfileString");
00879 if (!gpps) {
00880 dlclose(lib);
00881 return;
00882 }
00883 d->instlib = lib;
00884 d->gpps = gpps;
00885 }
00886 }
00887
00888 static void
00889 drvrelgpps(DBC *d)
00890 {
00891 if (d->instlib) {
00892 dlclose(d->instlib);
00893 d->instlib = 0;
00894 }
00895 }
00896
00897 static int
00898 drvgpps(DBC *d, char *sect, char *ent, char *def, char *buf,
00899 int bufsiz, char *fname)
00900 {
00901 if (d->gpps) {
00902 return d->gpps(sect, ent, def, buf, bufsiz, fname);
00903 }
00904 strncpy(buf, def, bufsiz);
00905 buf[bufsiz - 1] = '\0';
00906 return 1;
00907 }
00908 #else
00909 #include <odbcinst.h>
00910 #define drvgetgpps(d)
00911 #define drvrelgpps(d)
00912 #endif
00913
00914
00915
00916
00917
00918 static void
00919 s3bind(DBC *d, sqlite3_stmt *stmt, int nparams, BINDPARM *p)
00920 {
00921 int i;
00922
00923 if (stmt && p && nparams > 0) {
00924 for (i = 0; i < nparams; i++, p++) {
00925 switch (p->s3type) {
00926 default:
00927 case SQLITE_NULL:
00928 sqlite3_bind_null(stmt, i + 1);
00929 if (d->trace) {
00930 fprintf(d->trace, "-- parameter %d: NULL\n", i + 1);
00931 fflush(d->trace);
00932 }
00933 break;
00934 case SQLITE_TEXT:
00935 sqlite3_bind_text(stmt, i + 1, p->s3val, p->s3size,
00936 SQLITE_STATIC);
00937 if (d->trace) {
00938 fprintf(d->trace, "-- parameter %d: '%*s'\n", i + 1,
00939 p->s3size, (char *) p->s3val);
00940 fflush(d->trace);
00941 }
00942 break;
00943 case SQLITE_BLOB:
00944 sqlite3_bind_blob(stmt, i + 1, p->s3val, p->s3size,
00945 SQLITE_STATIC);
00946 if (d->trace) {
00947 fprintf(d->trace, "-- parameter %d: [BLOB]'\n", i + 1);
00948 fflush(d->trace);
00949 }
00950 break;
00951 case SQLITE_FLOAT:
00952 sqlite3_bind_double(stmt, i + 1, p->s3dval);
00953 if (d->trace) {
00954 fprintf(d->trace, "-- parameter %d: %g\n",
00955 i + 1, p->s3dval);
00956 fflush(d->trace);
00957 }
00958 break;
00959 case SQLITE_INTEGER:
00960 if (p->s3size > sizeof (int)) {
00961 sqlite3_bind_int64(stmt, i + 1, p->s3lival);
00962 if (d->trace) {
00963 fprintf(d->trace,
00964 #ifdef _WIN32
00965 "-- parameter %d: %I64d\n",
00966 #else
00967 "-- parameter %d: %lld\n",
00968 #endif
00969 i + 1, p->s3lival);
00970 fflush(d->trace);
00971 }
00972 } else {
00973 sqlite3_bind_int(stmt, i + 1, p->s3ival);
00974 if (d->trace) {
00975 fprintf(d->trace, "-- parameter %d: %d\n",
00976 i + 1, p->s3ival);
00977 fflush(d->trace);
00978 }
00979 }
00980 break;
00981 }
00982 }
00983 }
00984 }
00985
00986
00987
00988
00989
00990
00991 typedef struct tblres {
00992 char **resarr;
00993 char *errmsg;
00994 sqlite3_stmt *stmt;
00995 STMT *s;
00996 int nres;
00997 int nalloc;
00998 int nrow;
00999 int ncol;
01000 PTRDIFF_T ndata;
01001 int rc;
01002 } TBLRES;
01003
01004
01005
01006
01007
01008
01009 static int
01010 drvgettable_row(TBLRES *t, int ncol, int rc)
01011 {
01012 int need;
01013 int i;
01014 char *p;
01015
01016 if (t->nrow == 0 && rc == SQLITE_ROW) {
01017 need = ncol * 2;
01018 } else {
01019 need = ncol;
01020 }
01021 if (t->ndata + need >= t->nalloc) {
01022 char **resnew;
01023 int nalloc = t->nalloc * 2 + need + 1;
01024
01025 resnew = xrealloc(t->resarr, sizeof (char *) * nalloc);
01026 if (!resnew) {
01027 nomem:
01028 t->rc = SQLITE_NOMEM;
01029 return 1;
01030 }
01031 t->nalloc = nalloc;
01032 t->resarr = resnew;
01033 }
01034
01035 if (t->nrow == 0) {
01036 t->ncol = ncol;
01037 for (i = 0; i < ncol; i++) {
01038 p = (char *) sqlite3_column_name(t->stmt, i);
01039 if (p) {
01040 char *q = xmalloc(strlen(p) + 1);
01041
01042 if (!q) {
01043 goto nomem;
01044 }
01045 strcpy(q, p);
01046 p = q;
01047 }
01048 t->resarr[t->ndata++] = p;
01049 }
01050 if (t->s && t->s->guessed_types) {
01051 int ncol2 = ncol;
01052
01053 setupdyncols(t->s, t->stmt, &ncol2);
01054 t->s->guessed_types = 0;
01055 t->s->ncols = ncol;
01056 }
01057 } else if (t->ncol != ncol) {
01058 t->errmsg = sqlite3_mprintf("drvgettable() called with two or"
01059 " more incompatible queries");
01060 t->rc = SQLITE_ERROR;
01061 return 1;
01062 }
01063
01064 if (rc == SQLITE_ROW) {
01065 for (i = 0; i < ncol; i++) {
01066 int coltype = sqlite3_column_type(t->stmt, i);
01067
01068 p = NULL;
01069 if (coltype == SQLITE_BLOB) {
01070 int k, nbytes = sqlite3_column_bytes(t->stmt, i);
01071 char *qp;
01072 unsigned const char *bp;
01073
01074 bp = sqlite3_column_blob(t->stmt, i);
01075 qp = xmalloc(nbytes * 2 + 4);
01076 if (!qp) {
01077 goto nomem;
01078 }
01079 p = qp;
01080 *qp++ = 'X';
01081 *qp++ = '\'';
01082 for (k = 0; k < nbytes; k++) {
01083 *qp++ = xdigits[(bp[k] >> 4)];
01084 *qp++ = xdigits[(bp[k] & 0xF)];
01085 }
01086 *qp++ = '\'';
01087 *qp = '\0';
01088 } else if (coltype != SQLITE_NULL) {
01089 p = xstrdup((char *) sqlite3_column_text(t->stmt, i));
01090 if (!p) {
01091 goto nomem;
01092 }
01093 }
01094 t->resarr[t->ndata++] = p;
01095 }
01096 t->nrow++;
01097 }
01098 return 0;
01099 }
01100
01101 static int
01102 drvgettable(STMT *s, const char *sql, char ***resp, int *nrowp,
01103 int *ncolp, char **errp, int nparam, BINDPARM *p)
01104 {
01105 DBC *d = (DBC *) s->dbc;
01106 int rc = SQLITE_OK, keep = sql == NULL;
01107 TBLRES tres;
01108 const char *sqlleft = 0;
01109 int nretry = 0, haveerr = 0;
01110
01111 if (!resp) {
01112 return SQLITE_ERROR;
01113 }
01114 *resp = NULL;
01115 if (nrowp) {
01116 *nrowp = 0;
01117 }
01118 if (ncolp) {
01119 *ncolp = 0;
01120 }
01121 tres.errmsg = NULL;
01122 tres.nres = 0;
01123 tres.nrow = 0;
01124 tres.ncol = 0;
01125 tres.ndata = 1;
01126 tres.nalloc = 20;
01127 tres.rc = SQLITE_OK;
01128 tres.resarr = xmalloc(sizeof (char *) * tres.nalloc);
01129 tres.stmt = NULL;
01130 tres.s = s;
01131 if (!tres.resarr) {
01132 return SQLITE_NOMEM;
01133 }
01134 tres.resarr[0] = 0;
01135 if (sql == NULL) {
01136 tres.stmt = s->s3stmt;
01137 if (tres.stmt == NULL) {
01138 return SQLITE_NOMEM;
01139 }
01140 goto retrieve;
01141 }
01142 while (sql && *sql && (rc == SQLITE_OK ||
01143 (rc == SQLITE_SCHEMA && (++nretry) < 2))) {
01144 int ncol;
01145
01146 tres.stmt = NULL;
01147 #if defined(HAVE_SQLITE3PREPAREV2) && HAVE_SQLITE3PREPAREV2
01148 dbtraceapi(d, "sqlite3_prepare_v2", sql);
01149 rc = sqlite3_prepare_v2(d->sqlite, sql, -1, &tres.stmt, &sqlleft);
01150 #else
01151 dbtraceapi(d, "sqlite3_prepare", sql);
01152 rc = sqlite3_prepare(d->sqlite, sql, -1, &tres.stmt, &sqlleft);
01153 #endif
01154 if (rc != SQLITE_OK) {
01155 if (tres.stmt) {
01156 dbtraceapi(d, "sqlite3_finalize", 0);
01157 sqlite3_finalize(tres.stmt);
01158 tres.stmt = NULL;
01159 }
01160 continue;
01161 }
01162 if (!tres.stmt) {
01163
01164 sql = sqlleft;
01165 continue;
01166 }
01167 retrieve:
01168 if (sqlite3_bind_parameter_count(tres.stmt) != nparam) {
01169 if (errp) {
01170 *errp =
01171 sqlite3_mprintf("%s", "parameter marker count incorrect");
01172 }
01173 haveerr = 1;
01174 rc = SQLITE_ERROR;
01175 goto tbldone;
01176 }
01177 s3bind(d, tres.stmt, nparam, p);
01178 ncol = sqlite3_column_count(tres.stmt);
01179 while (1) {
01180 if (s->max_rows && tres.nrow >= s->max_rows) {
01181 rc = SQLITE_OK;
01182 break;
01183 }
01184 rc = sqlite3_step(tres.stmt);
01185 if (rc == SQLITE_ROW || rc == SQLITE_DONE) {
01186 if (drvgettable_row(&tres, ncol, rc)) {
01187 rc = SQLITE_ABORT;
01188 goto tbldone;
01189 }
01190 }
01191 if (rc != SQLITE_ROW) {
01192 if (keep) {
01193 dbtraceapi(d, "sqlite3_reset", 0);
01194 rc = sqlite3_reset(tres.stmt);
01195 s->s3stmt_noreset = 1;
01196 } else {
01197 dbtraceapi(d, "sqlite3_finalize", 0);
01198 rc = sqlite3_finalize(tres.stmt);
01199 }
01200 tres.stmt = 0;
01201 if (rc != SQLITE_SCHEMA) {
01202 nretry = 0;
01203 sql = sqlleft;
01204 while (sql && ISSPACE(*sql)) {
01205 sql++;
01206 }
01207 }
01208 if (rc == SQLITE_DONE) {
01209 rc = SQLITE_OK;
01210 }
01211 break;
01212 }
01213 }
01214 }
01215 tbldone:
01216 if (tres.stmt) {
01217 if (keep) {
01218 if (!s->s3stmt_noreset) {
01219 dbtraceapi(d, "sqlite3_reset", 0);
01220 sqlite3_reset(tres.stmt);
01221 s->s3stmt_noreset = 1;
01222 }
01223 } else {
01224 dbtraceapi(d, "sqlite3_finalize", 0);
01225 sqlite3_finalize(tres.stmt);
01226 }
01227 }
01228 if (haveerr) {
01229
01230 } else if (rc != SQLITE_OK && rc == sqlite3_errcode(d->sqlite) && errp) {
01231 *errp = sqlite3_mprintf("%s", sqlite3_errmsg(d->sqlite));
01232 } else if (errp) {
01233 *errp = NULL;
01234 }
01235 if (tres.resarr) {
01236 tres.resarr[0] = (char *) (tres.ndata - 1);
01237 }
01238 if (rc == SQLITE_ABORT) {
01239 freerows(&tres.resarr[1]);
01240 if (tres.errmsg) {
01241 if (errp) {
01242 if (*errp) {
01243 sqlite3_free(*errp);
01244 }
01245 *errp = tres.errmsg;
01246 } else {
01247 sqlite3_free(tres.errmsg);
01248 }
01249 }
01250 return tres.rc;
01251 }
01252 sqlite3_free(tres.errmsg);
01253 if (rc != SQLITE_OK) {
01254 freerows(&tres.resarr[1]);
01255 return rc;
01256 }
01257 *resp = &tres.resarr[1];
01258 if (ncolp) {
01259 *ncolp = tres.ncol;
01260 }
01261 if (nrowp) {
01262 *nrowp = tres.nrow;
01263 }
01264 return rc;
01265 }
01266
01275 #if defined(__GNUC__) && (__GNUC__ >= 2)
01276 static void setstatd(DBC *, int, char *, char *, ...)
01277 __attribute__((format (printf, 3, 5)));
01278 #endif
01279
01280 static void
01281 setstatd(DBC *d, int naterr, char *msg, char *st, ...)
01282 {
01283 va_list ap;
01284
01285 if (!d) {
01286 return;
01287 }
01288 d->naterr = naterr;
01289 d->logmsg[0] = '\0';
01290 if (msg) {
01291 int count;
01292
01293 va_start(ap, st);
01294 count = vsnprintf((char *) d->logmsg, sizeof (d->logmsg), msg, ap);
01295 va_end(ap);
01296 if (count < 0) {
01297 d->logmsg[sizeof (d->logmsg) - 1] = '\0';
01298 }
01299 }
01300 if (!st) {
01301 st = "?????";
01302 }
01303 strncpy(d->sqlstate, st, 5);
01304 d->sqlstate[5] = '\0';
01305 }
01306
01315 #if defined(__GNUC__) && (__GNUC__ >= 2)
01316 static void setstat(STMT *, int, char *, char *, ...)
01317 __attribute__((format (printf, 3, 5)));
01318 #endif
01319
01320 static void
01321 setstat(STMT *s, int naterr, char *msg, char *st, ...)
01322 {
01323 va_list ap;
01324
01325 if (!s) {
01326 return;
01327 }
01328 s->naterr = naterr;
01329 s->logmsg[0] = '\0';
01330 if (msg) {
01331 int count;
01332
01333 va_start(ap, st);
01334 count = vsnprintf((char *) s->logmsg, sizeof (s->logmsg), msg, ap);
01335 va_end(ap);
01336 if (count < 0) {
01337 s->logmsg[sizeof (s->logmsg) - 1] = '\0';
01338 }
01339 }
01340 if (!st) {
01341 st = "?????";
01342 }
01343 strncpy(s->sqlstate, st, 5);
01344 s->sqlstate[5] = '\0';
01345 }
01346
01353 static SQLRETURN
01354 drvunimpldbc(HDBC dbc)
01355 {
01356 DBC *d;
01357
01358 if (dbc == SQL_NULL_HDBC) {
01359 return SQL_INVALID_HANDLE;
01360 }
01361 d = (DBC *) dbc;
01362 setstatd(d, -1, "not supported", "IM001");
01363 return SQL_ERROR;
01364 }
01365
01372 static SQLRETURN
01373 drvunimplstmt(HSTMT stmt)
01374 {
01375 STMT *s;
01376
01377 if (stmt == SQL_NULL_HSTMT) {
01378 return SQL_INVALID_HANDLE;
01379 }
01380 s = (STMT *) stmt;
01381 setstat(s, -1, "not supported", "IM001");
01382 return SQL_ERROR;
01383 }
01384
01390 static void
01391 freep(void *x)
01392 {
01393 if (x && ((char **) x)[0]) {
01394 xfree(((char **) x)[0]);
01395 ((char **) x)[0] = NULL;
01396 }
01397 }
01398
01405 static SQLRETURN
01406 nomem(STMT *s)
01407 {
01408 setstat(s, -1, "out of memory", (*s->ov3) ? "HY000" : "S1000");
01409 return SQL_ERROR;
01410 }
01411
01418 static SQLRETURN
01419 noconn(STMT *s)
01420 {
01421 setstat(s, -1, "not connected", (*s->ov3) ? "HY000" : "S1000");
01422 return SQL_ERROR;
01423 }
01424
01432 static double
01433 ln_strtod(const char *data, char **endp)
01434 {
01435 #if defined(HAVE_LOCALECONV) || defined(_WIN32) || defined(_WIN64)
01436 struct lconv *lc;
01437 char buf[128], *p, *end;
01438 double value;
01439
01440 lc = localeconv();
01441 if (lc && lc->decimal_point && lc->decimal_point[0] &&
01442 lc->decimal_point[0] != '.') {
01443 strncpy(buf, data, sizeof (buf) - 1);
01444 buf[sizeof (buf) - 1] = '\0';
01445 p = strchr(buf, '.');
01446 if (p) {
01447 *p = lc->decimal_point[0];
01448 }
01449 p = buf;
01450 } else {
01451 p = (char *) data;
01452 }
01453 value = strtod(p, &end);
01454 end = (char *) data + (end - p);
01455 if (endp) {
01456 *endp = end;
01457 }
01458 return value;
01459 #else
01460 return strtod(data, endp);
01461 #endif
01462 }
01463
01469 static char *
01470 unquote(char *str)
01471 {
01472 if (str) {
01473 int len = strlen(str);
01474
01475 if (len > 1) {
01476 if ((str[0] == '\'' && str[len - 1] == '\'') ||
01477 (str[0] == '"' && str[len - 1] == '"') ||
01478 (str[0] == '[' && str[len - 1] == ']')) {
01479 str[len - 1] = '\0';
01480 strcpy(str, str + 1);
01481 }
01482 }
01483 }
01484 return str;
01485 }
01486
01494 static int
01495 unescpat(char *str)
01496 {
01497 char *p, *q;
01498 int count = 0;
01499
01500 p = str;
01501 while ((q = strchr(p, '_')) != NULL) {
01502 if (q == str || q[-1] != '\\') {
01503 count++;
01504 }
01505 p = q + 1;
01506 }
01507 p = str;
01508 while ((q = strchr(p, '%')) != NULL) {
01509 if (q == str || q[-1] != '\\') {
01510 count++;
01511 }
01512 p = q + 1;
01513 }
01514 p = str;
01515 while ((q = strchr(p, '\\')) != NULL) {
01516 if (q[1] == '\\' || q[1] == '_' || q[1] == '%') {
01517 strcpy(q, q + 1);
01518 }
01519 p = q + 1;
01520 }
01521 return count;
01522 }
01523
01532 static int
01533 namematch(char *str, char *pat, int esc)
01534 {
01535 int cp, ch;
01536
01537 while (1) {
01538 cp = TOLOWER(*pat);
01539 if (cp == '\0') {
01540 if (*str != '\0') {
01541 goto nomatch;
01542 }
01543 break;
01544 }
01545 if (*str == '\0' && cp != '%') {
01546 goto nomatch;
01547 }
01548 if (cp == '%') {
01549 while (*pat == '%') {
01550 ++pat;
01551 }
01552 cp = TOLOWER(*pat);
01553 if (cp == '\0') {
01554 break;
01555 }
01556 while (1) {
01557 if (cp != '_' && cp != '\\') {
01558 while (*str) {
01559 ch = TOLOWER(*str);
01560 if (ch == cp) {
01561 break;
01562 }
01563 ++str;
01564 }
01565 }
01566 if (namematch(str, pat, esc)) {
01567 goto match;
01568 }
01569 if (*str == '\0') {
01570 goto nomatch;
01571 }
01572 ch = TOLOWER(*str);
01573 ++str;
01574 }
01575 }
01576 if (cp == '_') {
01577 pat++;
01578 str++;
01579 continue;
01580 }
01581 if (esc && cp == '\\' &&
01582 (pat[1] == '\\' || pat[1] == '%' || pat[1] == '_')) {
01583 ++pat;
01584 cp = TOLOWER(*pat);
01585 }
01586 ch = TOLOWER(*str++);
01587 ++pat;
01588 if (ch != cp) {
01589 goto nomatch;
01590 }
01591 }
01592 match:
01593 return 1;
01594 nomatch:
01595 return 0;
01596 }
01597
01605 static int
01606 busy_handler(void *udata, int count)
01607 {
01608 DBC *d = (DBC *) udata;
01609 long t1;
01610 int ret = 0;
01611 #if !defined(_WIN32) && !defined(_WIN64)
01612 struct timeval tv;
01613 #endif
01614
01615 if (d->busyint) {
01616 d->busyint = 0;
01617 return ret;
01618 }
01619 if (d->timeout <= 0) {
01620 return ret;
01621 }
01622 if (count <= 1) {
01623 #if defined(_WIN32) || defined(_WIN64)
01624 d->t0 = GetTickCount();
01625 #else
01626 gettimeofday(&tv, NULL);
01627 d->t0 = tv.tv_sec * 1000 + tv.tv_usec / 1000;
01628 #endif
01629 }
01630 #if defined(_WIN32) || defined(_WIN64)
01631 t1 = GetTickCount();
01632 #else
01633 gettimeofday(&tv, NULL);
01634 t1 = tv.tv_sec * 1000 + tv.tv_usec / 1000;
01635 #endif
01636 if (t1 - d->t0 > d->timeout) {
01637 goto done;
01638 }
01639 #if defined(_WIN32) || defined(_WIN64)
01640 Sleep(10);
01641 #else
01642 #ifdef HAVE_USLEEP
01643 usleep(10000);
01644 #else
01645 tv.tv_sec = 0;
01646 tv.tv_usec = 10000;
01647 select(0, NULL, NULL, NULL, &tv);
01648 #endif
01649 #endif
01650 ret = 1;
01651 done:
01652 return ret;
01653 }
01654
01666 static int
01667 setsqliteopts(sqlite3 *x, DBC *d)
01668 {
01669 int count = 0, step = 0, max, rc = SQLITE_ERROR;
01670
01671 #if defined(HAVE_SQLITE3COLUMNTABLENAME) && (HAVE_SQLITE3COLUMNTABLENAME)
01672 max = d->longnames ? 3 : 1;
01673 #else
01674 max = 3;
01675 #endif
01676 if (d->shortnames) {
01677 max = 3;
01678 }
01679 while (step < max) {
01680 if (step < 1) {
01681 rc = sqlite3_exec(x, "PRAGMA empty_result_callbacks = on;",
01682 NULL, NULL, NULL);
01683 } else if (step < 2) {
01684 rc = sqlite3_exec(x, d->shortnames ?
01685 "PRAGMA full_column_names = off;" :
01686 "PRAGMA full_column_names = on;",
01687 NULL, NULL, NULL);
01688 } else if (step < 3) {
01689 rc = sqlite3_exec(x, d->shortnames ?
01690 "PRAGMA short_column_names = on;" :
01691 "PRAGMA short_column_names = off;",
01692 NULL, NULL, NULL);
01693 }
01694 if (rc != SQLITE_OK) {
01695 if (rc != SQLITE_BUSY ||
01696 !busy_handler((void *) d, ++count)) {
01697 return rc;
01698 }
01699 continue;
01700 }
01701 count = 0;
01702 ++step;
01703 }
01704 sqlite3_busy_handler(x, busy_handler, (void *) d);
01705 return SQLITE_OK;
01706 }
01707
01717 static void
01718 freerows(char **rowp)
01719 {
01720 PTRDIFF_T size, i;
01721
01722 if (!rowp) {
01723 return;
01724 }
01725 --rowp;
01726 size = (PTRDIFF_T) rowp[0];
01727 for (i = 1; i <= size; i++) {
01728 freep(&rowp[i]);
01729 }
01730 freep(&rowp);
01731 }
01732
01742 static int
01743 mapsqltype(const char *typename, int *nosign, int ov3, int nowchar)
01744 {
01745 char *p, *q;
01746 int testsign = 0, result;
01747
01748 #ifdef WINTERFACE
01749 result = nowchar ? SQL_VARCHAR : SQL_WVARCHAR;
01750 #else
01751 result = SQL_VARCHAR;
01752 #endif
01753 if (!typename) {
01754 return result;
01755 }
01756 q = p = xmalloc(strlen(typename) + 1);
01757 if (!p) {
01758 return result;
01759 }
01760 strcpy(p, typename);
01761 while (*q) {
01762 *q = TOLOWER(*q);
01763 ++q;
01764 }
01765 if (strncmp(p, "inter", 5) == 0) {
01766 } else if (strncmp(p, "int", 3) == 0 ||
01767 strncmp(p, "mediumint", 9) == 0) {
01768 testsign = 1;
01769 result = SQL_INTEGER;
01770 } else if (strncmp(p, "numeric", 7) == 0) {
01771 result = SQL_DOUBLE;
01772 } else if (strncmp(p, "tinyint", 7) == 0) {
01773 testsign = 1;
01774 result = SQL_TINYINT;
01775 } else if (strncmp(p, "smallint", 8) == 0) {
01776 testsign = 1;
01777 result = SQL_SMALLINT;
01778 } else if (strncmp(p, "float", 5) == 0) {
01779 result = SQL_DOUBLE;
01780 } else if (strncmp(p, "double", 6) == 0 ||
01781 strncmp(p, "real", 4) == 0) {
01782 result = SQL_DOUBLE;
01783 } else if (strncmp(p, "timestamp", 9) == 0) {
01784 #ifdef SQL_TYPE_TIMESTAMP
01785 result = ov3 ? SQL_TYPE_TIMESTAMP : SQL_TIMESTAMP;
01786 #else
01787 result = SQL_TIMESTAMP;
01788 #endif
01789 } else if (strncmp(p, "datetime", 8) == 0) {
01790 #ifdef SQL_TYPE_TIMESTAMP
01791 result = ov3 ? SQL_TYPE_TIMESTAMP : SQL_TIMESTAMP;
01792 #else
01793 result = SQL_TIMESTAMP;
01794 #endif
01795 } else if (strncmp(p, "time", 4) == 0) {
01796 #ifdef SQL_TYPE_TIME
01797 result = ov3 ? SQL_TYPE_TIME : SQL_TIME;
01798 #else
01799 result = SQL_TIME;
01800 #endif
01801 } else if (strncmp(p, "date", 4) == 0) {
01802 #ifdef SQL_TYPE_DATE
01803 result = ov3 ? SQL_TYPE_DATE : SQL_DATE;
01804 #else
01805 result = SQL_DATE;
01806 #endif
01807 #ifdef SQL_LONGVARCHAR
01808 } else if (strncmp(p, "text", 4) == 0 ||
01809 strncmp(p, "memo", 4) == 0) {
01810 #ifdef WINTERFACE
01811 result = nowchar ? SQL_LONGVARCHAR : SQL_WLONGVARCHAR;
01812 #else
01813 result = SQL_LONGVARCHAR;
01814 #endif
01815 #ifdef WINTERFACE
01816 } else if (strncmp(p, "wtext", 5) == 0 ||
01817 strncmp(p, "wvarchar", 8) == 0 ||
01818 strncmp(p, "longwvarchar", 12) == 0) {
01819 result = SQL_WLONGVARCHAR;
01820 #endif
01821 #endif
01822 #ifdef SQL_BIT
01823 } else if (strncmp(p, "bool", 4) == 0 ||
01824 strncmp(p, "bit", 3) == 0) {
01825 result = SQL_BIT;
01826 #endif
01827 #ifdef SQL_BIGINT
01828 } else if (strncmp(p, "bigint", 6) == 0) {
01829 result = SQL_BIGINT;
01830 #endif
01831 } else if (strncmp(p, "blob", 4) == 0) {
01832 result = SQL_BINARY;
01833 } else if (strncmp(p, "varbinary", 9) == 0) {
01834 result = SQL_VARBINARY;
01835 } else if (strncmp(p, "longvarbinary", 13) == 0) {
01836 result = SQL_LONGVARBINARY;
01837 }
01838 if (nosign) {
01839 if (testsign) {
01840 *nosign = strstr(p, "unsigned") != NULL;
01841 } else {
01842 *nosign = 1;
01843 }
01844 }
01845 xfree(p);
01846 return result;
01847 }
01848
01858 static void
01859 getmd(const char *typename, int sqltype, int *mp, int *dp)
01860 {
01861 int m = 0, d = 0;
01862
01863 switch (sqltype) {
01864 case SQL_INTEGER: m = 10; d = 9; break;
01865 case SQL_TINYINT: m = 4; d = 3; break;
01866 case SQL_SMALLINT: m = 6; d = 5; break;
01867 case SQL_FLOAT: m = 25; d = 24; break;
01868 case SQL_DOUBLE: m = 54; d = 53; break;
01869 case SQL_VARCHAR: m = 255; d = 0; break;
01870 #ifdef WINTERFACE
01871 #ifdef SQL_WVARCHAR
01872 case SQL_WVARCHAR: m = 255; d = 0; break;
01873 #endif
01874 #endif
01875 #ifdef SQL_TYPE_DATE
01876 case SQL_TYPE_DATE:
01877 #endif
01878 case SQL_DATE: m = 10; d = 0; break;
01879 #ifdef SQL_TYPE_TIME
01880 case SQL_TYPE_TIME:
01881 #endif
01882 case SQL_TIME: m = 8; d = 0; break;
01883 #ifdef SQL_TYPE_TIMESTAMP
01884 case SQL_TYPE_TIMESTAMP:
01885 #endif
01886 case SQL_TIMESTAMP: m = 32; d = 0; break;
01887 #ifdef SQL_LONGVARCHAR
01888 case SQL_LONGVARCHAR : m = 65536; d = 0; break;
01889 #endif
01890 #ifdef WINTERFACE
01891 #ifdef SQL_WLONGVARCHAR
01892 case SQL_WLONGVARCHAR: m = 65536; d = 0; break;
01893 #endif
01894 #endif
01895 case SQL_VARBINARY: m = 255; d = 0; break;
01896 case SQL_LONGVARBINARY: m = 65536; d = 0; break;
01897 #ifdef SQL_BIGINT
01898 case SQL_BIGINT: m = 20; d = 19; break;
01899 #endif
01900 #ifdef SQL_BIT
01901 case SQL_BIT: m = 1; d = 1; break;
01902 #endif
01903 }
01904 if (m && typename) {
01905 int mm, dd;
01906
01907 if (sscanf(typename, "%*[^(](%d)", &mm) == 1) {
01908 m = d = mm;
01909 } else if (sscanf(typename, "%*[^(](%d,%d)", &mm, &dd) == 2) {
01910 m = mm;
01911 d = dd;
01912 }
01913 }
01914 if (mp) {
01915 *mp = m;
01916 }
01917 if (dp) {
01918 *dp = d;
01919 }
01920 }
01921
01931 static int
01932 mapdeftype(int type, int stype, int nosign, int nowchar)
01933 {
01934 if (type == SQL_C_DEFAULT) {
01935 switch (stype) {
01936 case SQL_INTEGER:
01937 type = (nosign > 0) ? SQL_C_ULONG : SQL_C_LONG;
01938 break;
01939 case SQL_TINYINT:
01940 type = (nosign > 0) ? SQL_C_UTINYINT : SQL_C_TINYINT;
01941 break;
01942 case SQL_SMALLINT:
01943 type = (nosign > 0) ? SQL_C_USHORT : SQL_C_SHORT;
01944 break;
01945 case SQL_FLOAT:
01946 type = SQL_C_FLOAT;
01947 break;
01948 case SQL_DOUBLE:
01949 type = SQL_C_DOUBLE;
01950 break;
01951 case SQL_TIMESTAMP:
01952 type = SQL_C_TIMESTAMP;
01953 break;
01954 case SQL_TIME:
01955 type = SQL_C_TIME;
01956 break;
01957 case SQL_DATE:
01958 type = SQL_C_DATE;
01959 break;
01960 #ifdef SQL_C_TYPE_TIMESTAMP
01961 case SQL_TYPE_TIMESTAMP:
01962 type = SQL_C_TYPE_TIMESTAMP;
01963 break;
01964 #endif
01965 #ifdef SQL_C_TYPE_TIME
01966 case SQL_TYPE_TIME:
01967 type = SQL_C_TYPE_TIME;
01968 break;
01969 #endif
01970 #ifdef SQL_C_TYPE_DATE
01971 case SQL_TYPE_DATE:
01972 type = SQL_C_TYPE_DATE;
01973 break;
01974 #endif
01975 #ifdef WINTERFACE
01976 case SQL_WVARCHAR:
01977 case SQL_WCHAR:
01978 #ifdef SQL_WLONGVARCHAR
01979 case SQL_WLONGVARCHAR:
01980 #endif
01981 type = nowchar ? SQL_C_CHAR : SQL_C_WCHAR;
01982 break;
01983 #endif
01984 case SQL_BINARY:
01985 case SQL_VARBINARY:
01986 case SQL_LONGVARBINARY:
01987 type = SQL_C_BINARY;
01988 break;
01989 #ifdef SQL_BIT
01990 case SQL_BIT:
01991 type = SQL_C_BIT;
01992 break;
01993 #endif
01994 #ifdef SQL_BIGINT
01995 case SQL_BIGINT:
01996 type = (nosign > 0) ? SQL_C_UBIGINT : SQL_C_SBIGINT;
01997 break;
01998 #endif
01999 default:
02000 #ifdef WINTERFACE
02001 type = nowchar ? SQL_C_CHAR : SQL_C_WCHAR;
02002 #else
02003 type = SQL_C_CHAR;
02004 #endif
02005 break;
02006 }
02007 }
02008 return type;
02009 }
02010
02021 static char *
02022 fixupsql(char *sql, int sqlLen, int *nparam, int *isselect, char **errmsg)
02023 {
02024 char *q = sql, *qz = NULL, *p, *inq = NULL, *out;
02025 int np = 0, isddl = -1, size;
02026
02027 *errmsg = NULL;
02028 if (sqlLen != SQL_NTS) {
02029 qz = q = xmalloc(sqlLen + 1);
02030 if (!qz) {
02031 return NULL;
02032 }
02033 memcpy(q, sql, sqlLen);
02034 q[sqlLen] = '\0';
02035 size = sqlLen * 4;
02036 } else {
02037 size = strlen(sql) * 4;
02038 }
02039 size += sizeof (char *) - 1;
02040 size &= ~(sizeof (char *) - 1);
02041 p = xmalloc(size);
02042 if (!p) {
02043 errout:
02044 freep(&qz);
02045 return NULL;
02046 }
02047 memset(p, 0, size);
02048 out = p;
02049 while (*q) {
02050 switch (*q) {
02051 case '\'':
02052 case '\"':
02053 if (q == inq) {
02054 inq = NULL;
02055 } else if (!inq) {
02056 inq = q + 1;
02057
02058 while (*inq) {
02059 if (*inq == *q) {
02060 if (inq[1] == *q) {
02061 inq++;
02062 } else {
02063 break;
02064 }
02065 }
02066 inq++;
02067 }
02068 }
02069 *p++ = *q;
02070 break;
02071 case '?':
02072 *p++ = *q;
02073 if (!inq) {
02074 np++;
02075 }
02076 break;
02077 case ';':
02078 if (!inq) {
02079 if (isddl < 0) {
02080 char *qq = out;
02081
02082 while (*qq && ISSPACE(*qq)) {
02083 ++qq;
02084 }
02085 if (*qq && *qq != ';') {
02086 size = strlen(qq);
02087 if ((size >= 5) &&
02088 (strncasecmp(qq, "create", 5) == 0)) {
02089 isddl = 1;
02090 } else if ((size >= 4) &&
02091 (strncasecmp(qq, "drop", 4) == 0)) {
02092 isddl = 1;
02093 } else {
02094 isddl = 0;
02095 }
02096 }
02097 }
02098 if (isddl == 0) {
02099 char *qq = q;
02100
02101 do {
02102 ++qq;
02103 } while (*qq && ISSPACE(*qq));
02104 if (*qq && *qq != ';') {
02105 freep(&out);
02106 *errmsg = "only one SQL statement allowed";
02107 goto errout;
02108 }
02109 }
02110 }
02111 *p++ = *q;
02112 break;
02113 case '{':
02114
02115 if (!inq) {
02116 char *end = q + 1;
02117
02118 while (*end && *end != '}') {
02119 ++end;
02120 }
02121 if (*end == '}') {
02122 char *start = q + 1;
02123 char *end2 = end - 1;
02124
02125 while (start < end2 && *start != '\'') {
02126 ++start;
02127 }
02128 while (end2 > start && *end2 != '\'') {
02129 --end2;
02130 }
02131 if (*start == '\'' && *end2 == '\'') {
02132 while (start <= end2) {
02133 *p++ = *start;
02134 ++start;
02135 }
02136 q = end;
02137 break;
02138 }
02139 }
02140 }
02141
02142 default:
02143 *p++ = *q;
02144 }
02145 ++q;
02146 }
02147 freep(&qz);
02148 *p = '\0';
02149 if (nparam) {
02150 *nparam = np;
02151 }
02152 if (isselect) {
02153 if (isddl > 0) {
02154 *isselect = 0;
02155 } else {
02156 p = out;
02157 while (*p && ISSPACE(*p)) {
02158 ++p;
02159 }
02160 size = strlen(p);
02161 *isselect = (size >= 6) && (strncasecmp(p, "select", 6) == 0);
02162 }
02163 }
02164 return out;
02165 }
02166
02175 static int
02176 findcol(char **cols, int ncols, char *name)
02177 {
02178 int i;
02179
02180 if (cols) {
02181 for (i = 0; i < ncols; i++) {
02182 if (strcmp(cols[i], name) == 0) {
02183 return i;
02184 }
02185 }
02186 }
02187 return -1;
02188 }
02189
02206 static void
02207 fixupdyncols(STMT *s, DBC *d)
02208 {
02209 int i, k;
02210 #if !defined(HAVE_SQLITE3TABLECOLUMNMETADATA) || !HAVE_SQLITE3TABLECOLUMNMETADATA
02211 int pk, nn, t, r, nrows, ncols;
02212 char **rowp, *flagp, flags[128];
02213 #endif
02214
02215 if (!s->dyncols) {
02216 return;
02217 }
02218
02219 if (!s->longnames) {
02220 if (s->dcols > 1) {
02221 char *table = s->dyncols[0].table;
02222
02223 for (i = 1; table[0] && i < s->dcols; i++) {
02224 if (strcmp(s->dyncols[i].table, table)) {
02225 break;
02226 }
02227 }
02228 if (i >= s->dcols) {
02229 for (i = 0; i < s->dcols; i++) {
02230 s->dyncols[i].label = s->dyncols[i].column;
02231 }
02232 }
02233 } else if (s->dcols == 1) {
02234 s->dyncols[0].label = s->dyncols[0].column;
02235 }
02236 }
02237 for (i = 0; i < s->dcols; i++) {
02238 s->dyncols[i].type =
02239 mapsqltype(s->dyncols[i].typename, &s->dyncols[i].nosign, *s->ov3,
02240 s->nowchar[0] || s->nowchar[1]);
02241 getmd(s->dyncols[i].typename, s->dyncols[i].type,
02242 &s->dyncols[i].size, NULL);
02243 #ifdef SQL_LONGVARCHAR
02244 if (s->dyncols[i].type == SQL_VARCHAR &&
02245 s->dyncols[i].size > 255) {
02246 s->dyncols[i].type = SQL_LONGVARCHAR;
02247 }
02248 #endif
02249 #ifdef WINTERFACE
02250 #ifdef SQL_WLONGVARCHAR
02251 if (s->dyncols[i].type == SQL_WVARCHAR &&
02252 s->dyncols[i].size > 255) {
02253 s->dyncols[i].type = SQL_WLONGVARCHAR;
02254 }
02255 #endif
02256 #endif
02257 if (s->dyncols[i].type == SQL_VARBINARY &&
02258 s->dyncols[i].size > 255) {
02259 s->dyncols[i].type = SQL_LONGVARBINARY;
02260 }
02261 }
02262 #if !defined(HAVE_SQLITE3TABLECOLUMNMETADATA) || !HAVE_SQLITE3TABLECOLUMNMETADATA
02263 if (s->dcols > array_size(flags)) {
02264 flagp = xmalloc(sizeof (flags[0]) * s->dcols);
02265 if (flagp == NULL) {
02266 return;
02267 }
02268 } else {
02269 flagp = flags;
02270 }
02271 memset(flagp, 0, sizeof (flags[0]) * s->dcols);
02272 for (i = 0; i < s->dcols; i++) {
02273 s->dyncols[i].autoinc = SQL_FALSE;
02274 s->dyncols[i].notnull = SQL_NULLABLE;
02275 }
02276 for (i = 0; i < s->dcols; i++) {
02277 int ret, lastpk = -1, autoinccount = 0;
02278 char *sql;
02279
02280 if (!s->dyncols[i].table[0]) {
02281 continue;
02282 }
02283 if (flagp[i]) {
02284 continue;
02285 }
02286 sql = sqlite3_mprintf("PRAGMA table_info(%Q)", s->dyncols[i].table);
02287 if (!sql) {
02288 continue;
02289 }
02290 dbtraceapi(d, "sqlite3_get_table", sql);
02291 ret = sqlite3_get_table(d->sqlite, sql, &rowp, &nrows, &ncols, NULL);
02292 sqlite3_free(sql);
02293 if (ret != SQLITE_OK) {
02294 continue;
02295 }
02296 k = findcol(rowp, ncols, "name");
02297 t = findcol(rowp, ncols, "type");
02298 pk = findcol(rowp, ncols, "pk");
02299 nn = findcol(rowp, ncols, "notnull");
02300 if (k < 0 || t < 0) {
02301 goto freet;
02302 }
02303 for (r = 1; r <= nrows; r++) {
02304 int m;
02305
02306 for (m = i; m < s->dcols; m++) {
02307 char *colname = s->dyncols[m].column;
02308
02309 if (s->longnames) {
02310 char *dotp = strchr(colname, '.');
02311
02312 if (dotp) {
02313 colname = dotp + 1;
02314 }
02315 }
02316 if (!flagp[m] &&
02317 strcmp(colname, rowp[r * ncols + k]) == 0 &&
02318 strcmp(s->dyncols[m].table, s->dyncols[i].table) == 0) {
02319 char *typename = rowp[r * ncols + t];
02320
02321 flagp[m] = 1;
02322 freep(&s->dyncols[m].typename);
02323 s->dyncols[m].typename = xstrdup(typename);
02324 s->dyncols[m].type =
02325 mapsqltype(typename, &s->dyncols[m].nosign, *s->ov3,
02326 s->nowchar[0] || s->nowchar[1]);
02327 getmd(typename, s->dyncols[m].type, &s->dyncols[m].size,
02328 NULL);
02329 #ifdef SQL_LONGVARCHAR
02330 if (s->dyncols[m].type == SQL_VARCHAR &&
02331 s->dyncols[m].size > 255) {
02332 s->dyncols[m].type = SQL_LONGVARCHAR;
02333 }
02334 #endif
02335 #ifdef WINTERFACE
02336 #ifdef SQL_WLONGVARCHAR
02337 if (s->dyncols[i].type == SQL_WVARCHAR &&
02338 s->dyncols[i].size > 255) {
02339 s->dyncols[i].type = SQL_WLONGVARCHAR;
02340 }
02341 #endif
02342 #endif
02343 if (s->dyncols[i].type == SQL_VARBINARY &&
02344 s->dyncols[i].size > 255) {
02345 s->dyncols[i].type = SQL_LONGVARBINARY;
02346 }
02347 if (pk >= 0 && strcmp(rowp[r * ncols + pk], "1") == 0) {
02348 if (++autoinccount > 1) {
02349 if (lastpk >= 0) {
02350 s->dyncols[lastpk].autoinc = SQL_FALSE;
02351 lastpk = -1;
02352 }
02353 } else {
02354 lastpk = m;
02355 if (strlen(typename) == 7 &&
02356 strncasecmp(typename, "integer", 7) == 0) {
02357 s->dyncols[m].autoinc = SQL_TRUE;
02358 }
02359 }
02360 }
02361 if (nn >= 0 && rowp[r * ncols + nn][0] != '0') {
02362 s->dyncols[m].notnull = SQL_NO_NULLS;
02363 }
02364 }
02365 }
02366 }
02367 freet:
02368 sqlite3_free_table(rowp);
02369 }
02370 if (flagp != flags) {
02371 freep(&flagp);
02372 }
02373 #endif
02374 }
02375
02383 static int
02384 getmdays(int year, int month)
02385 {
02386 static const int mdays[] = {
02387 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31
02388 };
02389 int mday;
02390
02391 if (month < 1) {
02392 return 0;
02393 }
02394 mday = mdays[(month - 1) % 12];
02395 if (mday == 28 && year % 4 == 0 &&
02396 (!(year % 100 == 0) || year % 400 == 0)) {
02397 mday++;
02398 }
02399 return mday;
02400 }
02401
02412 static int
02413 str2date(char *str, DATE_STRUCT *ds)
02414 {
02415 int i, err = 0;
02416 char *p, *q;
02417
02418 ds->year = ds->month = ds->day = 0;
02419 p = str;
02420 while (*p && !ISDIGIT(*p)) {
02421 ++p;
02422 }
02423 q = p;
02424 i = 0;
02425 while (*q && !ISDIGIT(*q)) {
02426 ++i;
02427 ++q;
02428 }
02429 if (i >= 8) {
02430 char buf[8];
02431
02432 strncpy(buf, p + 0, 4); buf[4] = '\0';
02433 ds->year = strtol(buf, NULL, 10);
02434 strncpy(buf, p + 4, 2); buf[2] = '\0';
02435 ds->month = strtol(buf, NULL, 10);
02436 strncpy(buf, p + 6, 2); buf[2] = '\0';
02437 ds->day = strtol(buf, NULL, 10);
02438 goto done;
02439 }
02440 i = 0;
02441 while (i < 3) {
02442 int n;
02443
02444 q = NULL;
02445 n = strtol(p, &q, 10);
02446 if (!q || q == p) {
02447 if (*q == '\0') {
02448 if (i == 0) {
02449 err = 1;
02450 }
02451 goto done;
02452 }
02453 }
02454 if (*q == '-' || *q == '/' || *q == '\0' || i == 2) {
02455 switch (i) {
02456 case 0: ds->year = n; break;
02457 case 1: ds->month = n; break;
02458 case 2: ds->day = n; break;
02459 }
02460 ++i;
02461 if (*q) {
02462 ++q;
02463 }
02464 } else {
02465 i = 0;
02466 while (*q && !ISDIGIT(*q)) {
02467 ++q;
02468 }
02469 }
02470 p = q;
02471 }
02472 done:
02473
02474 if (err ||
02475 ds->month < 1 || ds->month > 12 ||
02476 ds->day < 1 || ds->day > getmdays(ds->year, ds->month)) {
02477 return -1;
02478 }
02479 return 0;
02480 }
02481
02492 static int
02493 str2time(char *str, TIME_STRUCT *ts)
02494 {
02495 int i, err = 0;
02496 char *p, *q;
02497
02498 ts->hour = ts->minute = ts->second = 0;
02499 p = str;
02500 while (*p && !ISDIGIT(*p)) {
02501 ++p;
02502 }
02503 q = p;
02504 i = 0;
02505 while (*q && ISDIGIT(*q)) {
02506 ++i;
02507 ++q;
02508 }
02509 if (i >= 6) {
02510 char buf[4];
02511
02512 strncpy(buf, p + 0, 2); buf[2] = '\0';
02513 ts->hour = strtol(buf, NULL, 10);
02514 strncpy(buf, p + 2, 2); buf[2] = '\0';
02515 ts->minute = strtol(buf, NULL, 10);
02516 strncpy(buf, p + 4, 2); buf[2] = '\0';
02517 ts->second = strtol(buf, NULL, 10);
02518 goto done;
02519 }
02520 i = 0;
02521 while (i < 3) {
02522 int n;
02523
02524 q = NULL;
02525 n = strtol(p, &q, 10);
02526 if (!q || q == p) {
02527 if (*q == '\0') {
02528 if (i == 0) {
02529 err = 1;
02530 }
02531 goto done;
02532 }
02533 }
02534 if (*q == ':' || *q == '\0' || i == 2) {
02535 switch (i) {
02536 case 0: ts->hour = n; break;
02537 case 1: ts->minute = n; break;
02538 case 2: ts->second = n; break;
02539 }
02540 ++i;
02541 if (*q) {
02542 ++q;
02543 }
02544 } else {
02545 i = 0;
02546 while (*q && !ISDIGIT(*q)) {
02547 ++q;
02548 }
02549 }
02550 p = q;
02551 }
02552 done:
02553
02554 if (err || ts->hour > 23 || ts->minute > 59 || ts->second > 59) {
02555 return -1;
02556 }
02557 return 0;
02558 }
02559
02575 static int
02576 str2timestamp(char *str, TIMESTAMP_STRUCT *tss)
02577 {
02578 int i, m, n, err = 0;
02579 char *p, *q, in = '\0';
02580
02581 tss->year = tss->month = tss->day = 0;
02582 tss->hour = tss->minute = tss->second = 0;
02583 tss->fraction = 0;
02584 p = str;
02585 while (*p && !ISDIGIT(*p)) {
02586 ++p;
02587 }
02588 q = p;
02589 i = 0;
02590 while (*q && ISDIGIT(*q)) {
02591 ++i;
02592 ++q;
02593 }
02594 if (i >= 14) {
02595 char buf[16];
02596
02597 strncpy(buf, p + 0, 4); buf[4] = '\0';
02598 tss->year = strtol(buf, NULL, 10);
02599 strncpy(buf, p + 4, 2); buf[2] = '\0';
02600 tss->month = strtol(buf, NULL, 10);
02601 strncpy(buf, p + 6, 2); buf[2] = '\0';
02602 tss->day = strtol(buf, NULL, 10);
02603 strncpy(buf, p + 8, 2); buf[2] = '\0';
02604 tss->hour = strtol(buf, NULL, 10);
02605 strncpy(buf, p + 10, 2); buf[2] = '\0';
02606 tss->minute = strtol(buf, NULL, 10);
02607 strncpy(buf, p + 12, 2); buf[2] = '\0';
02608 tss->second = strtol(buf, NULL, 10);
02609 if (i > 14) {
02610 m = i - 14;
02611 strncpy(buf, p + 14, m);
02612 while (m < 9) {
02613 buf[m] = '0';
02614 ++m;
02615 }
02616 buf[m] = '\0';
02617 tss->fraction = strtol(buf, NULL, 0);
02618 }
02619 m = 7;
02620 goto done;
02621 }
02622 m = i = 0;
02623 while ((m & 7) != 7) {
02624 q = NULL;
02625 n = strtol(p, &q, 10);
02626 if (!q || q == p) {
02627 if (*q == '\0') {
02628 if (m < 1) {
02629 err = 1;
02630 }
02631 goto done;
02632 }
02633 }
02634 if (in == '\0') {
02635 switch (*q) {
02636 case '-':
02637 case '/':
02638 if ((m & 1) == 0) {
02639 in = *q;
02640 i = 0;
02641 }
02642 break;
02643 case ':':
02644 if ((m & 2) == 0) {
02645 in = *q;
02646 i = 0;
02647 }
02648 break;
02649 case ' ':
02650 case '.':
02651 break;
02652 default:
02653 in = '\0';
02654 i = 0;
02655 break;
02656 }
02657 }
02658 switch (in) {
02659 case '-':
02660 case '/':
02661 switch (i) {
02662 case 0: tss->year = n; break;
02663 case 1: tss->month = n; break;
02664 case 2: tss->day = n; break;
02665 }
02666 if (++i >= 3) {
02667 i = 0;
02668 m |= 1;
02669 if (!(m & 2)) {
02670 m |= 8;
02671 }
02672 goto skip;
02673 } else {
02674 ++q;
02675 }
02676 break;
02677 case ':':
02678 switch (i) {
02679 case 0: tss->hour = n; break;
02680 case 1: tss->minute = n; break;
02681 case 2: tss->second = n; break;
02682 }
02683 if (++i >= 3) {
02684 i = 0;
02685 m |= 2;
02686 if (*q == '.') {
02687 in = '.';
02688 goto skip2;
02689 }
02690 if (*q == ' ') {
02691 if ((m & 1) == 0) {
02692 char *e = NULL;
02693 int dummy;
02694
02695 dummy = strtol(q + 1, &e, 10);
02696 if (e && *e == '-') {
02697 goto skip;
02698 }
02699 }
02700 in = '.';
02701 goto skip2;
02702 }
02703 goto skip;
02704 } else {
02705 ++q;
02706 }
02707 break;
02708 case '.':
02709 if (++i >= 1) {
02710 int ndig = q - p;
02711
02712 if (p[0] == '+' || p[0] == '-') {
02713 ndig--;
02714 }
02715 while (ndig < 9) {
02716 n = n * 10;
02717 ++ndig;
02718 }
02719 tss->fraction = n;
02720 m |= 4;
02721 i = 0;
02722 }
02723 default:
02724 skip:
02725 in = '\0';
02726 skip2:
02727 while (*q && !ISDIGIT(*q)) {
02728 ++q;
02729 }
02730 }
02731 p = q;
02732 }
02733 if ((m & 7) > 1 && (m & 8)) {
02734
02735 if (p > str && ISDIGIT(*p)) {
02736 int nn, sign;
02737
02738 q = p - 1;
02739 if (*q != '+' && *q != '-') {
02740 goto done;
02741 }
02742 sign = (*q == '+') ? -1 : 1;
02743 q = NULL;
02744 n = strtol(p, &q, 10);
02745 if (!q || *q++ != ':' || !ISDIGIT(*q)) {
02746 goto done;
02747 }
02748 p = q;
02749 q = NULL;
02750 nn = strtol(p, &q, 0);
02751 tss->minute += nn * sign;
02752 if ((SQLSMALLINT) tss->minute < 0) {
02753 tss->hour -= 1;
02754 tss->minute += 60;
02755 } else if (tss->minute >= 60) {
02756 tss->hour += 1;
02757 tss->minute -= 60;
02758 }
02759 tss->hour += n * sign;
02760 if ((SQLSMALLINT) tss->hour < 0) {
02761 tss->day -= 1;
02762 tss->hour += 24;
02763 } else if (tss->hour >= 24) {
02764 tss->day += 1;
02765 tss->hour -= 24;
02766 }
02767 if ((short) tss->day < 1 || tss->day >= 28) {
02768 int mday, pday, pmon;
02769
02770 mday = getmdays(tss->year, tss->month);
02771 pmon = tss->month - 1;
02772 if (pmon < 1) {
02773 pmon = 12;
02774 }
02775 pday = getmdays(tss->year, pmon);
02776 if ((SQLSMALLINT) tss->day < 1) {
02777 tss->month -= 1;
02778 tss->day = pday;
02779 } else if (tss->day > mday) {
02780 tss->month += 1;
02781 tss->day = 1;
02782 }
02783 if ((SQLSMALLINT) tss->month < 1) {
02784 tss->year -= 1;
02785 tss->month = 12;
02786 } else if (tss->month > 12) {
02787 tss->year += 1;
02788 tss->month = 1;
02789 }
02790 }
02791 }
02792 }
02793 done:
02794
02795 if (!err && (m & 1) == 0) {
02796 #ifdef _WIN32
02797 SYSTEMTIME t;
02798
02799 GetLocalTime(&t);
02800 tss->year = t.wYear;
02801 tss->month = t.wMonth;
02802 tss->day = t.wDay;
02803 #else
02804 struct timeval tv;
02805 struct tm tm;
02806
02807 gettimeofday(&tv, NULL);
02808 tm = *localtime(&tv.tv_sec);
02809 tss->year = tm.tm_year + 1900;
02810 tss->month = tm.tm_mon + 1;
02811 tss->day = tm.tm_mday;
02812 #endif
02813 }
02814
02815 if (err ||
02816 tss->month < 1 || tss->month > 12 ||
02817 tss->day < 1 || tss->day > getmdays(tss->year, tss->month) ||
02818 tss->hour > 23 || tss->minute > 59 || tss->second > 59) {
02819 return -1;
02820 }
02821 return ((m & 7) < 1) ? -1 : 0;
02822 }
02823
02830 static int
02831 getbool(char *string)
02832 {
02833 if (string) {
02834 return string[0] && strchr("Yy123456789Tt", string[0]) != NULL;
02835 }
02836 return 0;
02837 }
02838
02845 static void
02846 dbtrace(void *arg, const char *msg)
02847 {
02848 DBC *d = (DBC *) arg;
02849
02850 if (msg && d->trace) {
02851 int len = strlen(msg);
02852
02853 if (len > 0) {
02854 char *end = "\n";
02855
02856 if (msg[len - 1] != ';') {
02857 end = ";\n";
02858 }
02859 fprintf(d->trace, "%s%s", msg, end);
02860 fflush(d->trace);
02861 }
02862 }
02863 }
02864
02872 static void
02873 dbtraceapi(DBC *d, char *fn, const char *sql)
02874 {
02875 if (fn && d->trace) {
02876 if (sql) {
02877 fprintf(d->trace, "-- %s: %s\n", fn, sql);
02878 } else {
02879 fprintf(d->trace, "-- %s\n", fn);
02880 }
02881 fflush(d->trace);
02882 }
02883 }
02884
02892 static void
02893 dbtracerc(DBC *d, int rc, char *err)
02894 {
02895 if (rc != SQLITE_OK && d->trace) {
02896 fprintf(d->trace, "-- SQLITE ERROR CODE %d", rc);
02897 fprintf(d->trace, err ? ": %s\n" : "\n", err);
02898 fflush(d->trace);
02899 }
02900 }
02901
02916 static SQLRETURN
02917 dbopen(DBC *d, char *name, int isu, char *dsn, char *sflag,
02918 char *spflag, char *ntflag, char *jmode, char *busy)
02919 {
02920 char *endp = NULL;
02921 int rc, tmp, busyto = 100000;
02922 #if defined(HAVE_SQLITE3VFS) && HAVE_SQLITE3VFS
02923 int flags = SQLITE_OPEN_READWRITE | SQLITE_OPEN_CREATE;
02924 char *uname = name;
02925 const char *vfs_name = NULL;
02926 #endif
02927
02928 if (d->sqlite) {
02929 if (d->trace) {
02930 fprintf(d->trace, "-- sqlite3_close (deferred): '%s'\n",
02931 d->dbname);
02932 fflush(d->trace);
02933 }
02934 sqlite3_close(d->sqlite);
02935 d->sqlite = NULL;
02936 }
02937 #if defined(HAVE_SQLITE3VFS) && HAVE_SQLITE3VFS
02938 if (d->nocreat) {
02939 flags &= ~ SQLITE_OPEN_CREATE;
02940 }
02941 #if defined(_WIN32) || defined(_WIN64)
02942 if (!isu) {
02943 uname = wmb_to_utf(name, -1);
02944 if (!uname) {
02945 rc = SQLITE_NOMEM;
02946 setstatd(d, rc, "out of memory", (*d->ov3) ? "HY000" : "S1000");
02947 return SQL_ERROR;
02948 }
02949 }
02950 #endif
02951 #if defined(ENABLE_NVFS) && ENABLE_NVFS
02952 vfs_name = nvfs_makevfs(uname);
02953 #endif
02954 rc = sqlite3_open_v2(uname, &d->sqlite, flags, vfs_name);
02955 #if defined(WINTERFACE) || defined(_WIN32) || defined(_WIN64)
02956 if (uname != name) {
02957 uc_free(uname);
02958 }
02959 #endif
02960 #else
02961 #if defined(_WIN32) || defined(_WIN64)
02962 if (d->nocreat) {
02963 char *cname = NULL;
02964
02965 if (isu) {
02966 cname = utf_to_wmb(name, -1);
02967 }
02968 if (GetFileAttributesA(cname ? cname : name) == 0xffffffff) {
02969 uc_free(cname);
02970 rc = SQLITE_CANTOPEN;
02971 setstatd(d, rc, "cannot open database",
02972 (*d->ov3) ? "HY000" : "S1000");
02973 return SQL_ERROR;
02974 }
02975 uc_free(cname);
02976 }
02977 #else
02978 if (d->nocreat && access(name, 004) < 0) {
02979 rc = SQLITE_CANTOPEN;
02980 setstatd(d, rc, "cannot open database", (*d->ov3) ? "HY000" : "S1000");
02981 return SQL_ERROR;
02982 }
02983 #endif
02984 #if defined(_WIN32) || defined(_WIN64)
02985 if (!isu) {
02986 WCHAR *wname = wmb_to_uc(name, -1);
02987
02988 if (!wname) {
02989 rc = SQLITE_NOMEM;
02990 setstatd(d, rc, "out of memory", (*d->ov3) ? "HY000" : "S1000");
02991 return SQL_ERROR;
02992 }
02993 rc = sqlite3_open16(wname, &d->sqlite);
02994 uc_free(wname);
02995 } else
02996 #endif
02997 rc = sqlite3_open(name, &d->sqlite);
02998 #endif
02999 if (rc != SQLITE_OK) {
03000 connfail:
03001 setstatd(d, rc, "connect failed", (*d->ov3) ? "HY000" : "S1000");
03002 if (d->sqlite) {
03003 sqlite3_close(d->sqlite);
03004 d->sqlite = NULL;
03005 }
03006 return SQL_ERROR;
03007 }
03008 if (d->trace) {
03009 sqlite3_trace(d->sqlite, dbtrace, d);
03010 }
03011 d->step_enable = getbool(sflag);
03012 d->trans_disable = getbool(ntflag);
03013 d->curtype = d->step_enable ?
03014 SQL_CURSOR_FORWARD_ONLY : SQL_CURSOR_STATIC;
03015 tmp = strtol(busy, &endp, 0);
03016 if (endp && *endp == '\0' && endp != busy) {
03017 busyto = tmp;
03018 }
03019 if (busyto < 1 || busyto > 1000000) {
03020 busyto = 1000000;
03021 }
03022 d->timeout = busyto;
03023 if ((rc = setsqliteopts(d->sqlite, d)) != SQLITE_OK) {
03024 if (d->trace) {
03025 fprintf(d->trace, "-- sqlite3_close: '%s'\n",
03026 d->dbname);
03027 fflush(d->trace);
03028 }
03029 sqlite3_close(d->sqlite);
03030 d->sqlite = NULL;
03031 goto connfail;
03032 }
03033 if (!spflag || spflag[0] == '\0') {
03034 spflag = "NORMAL";
03035 }
03036 if (spflag[0] != '\0') {
03037 char syncp[128];
03038
03039 sprintf(syncp, "PRAGMA synchronous = %8.8s;", spflag);
03040 sqlite3_exec(d->sqlite, syncp, NULL, NULL, NULL);
03041 }
03042 if (jmode[0] != '\0') {
03043 char jourp[128];
03044
03045 sprintf(jourp, "PRAGMA journal_mode = %16.16s;", jmode);
03046 sqlite3_exec(d->sqlite, jourp, NULL, NULL, NULL);
03047 }
03048 freep(&d->dbname);
03049 d->dbname = xstrdup(name);
03050 freep(&d->dsn);
03051 d->dsn = xstrdup(dsn);
03052 if (d->trace) {
03053 fprintf(d->trace, "-- sqlite3_open: '%s'\n", d->dbname);
03054 fflush(d->trace);
03055 }
03056 #if defined(_WIN32) || defined(_WIN64)
03057 {
03058 char pname[MAX_PATH];
03059 HANDLE h = OpenProcess(PROCESS_QUERY_INFORMATION | PROCESS_VM_READ,
03060 FALSE, GetCurrentProcessId());
03061
03062 pname[0] = '\0';
03063 if (h) {
03064 HMODULE m = NULL, l = LoadLibrary("psapi.dll");
03065 DWORD need;
03066 typedef BOOL (WINAPI *epmfunc)(HANDLE, HMODULE *, DWORD, LPDWORD);
03067 typedef BOOL (WINAPI *gmbfunc)(HANDLE, HMODULE, LPSTR, DWORD);
03068 epmfunc epm;
03069 gmbfunc gmb;
03070
03071 if (l) {
03072 epm = (epmfunc) GetProcAddress(l, "EnumProcessModules");
03073 gmb = (gmbfunc) GetProcAddress(l, "GetModuleBaseNameA");
03074 if (epm && gmb && epm(h, &m, sizeof (m), &need)) {
03075 gmb(h, m, pname, sizeof (pname));
03076 }
03077 FreeLibrary(l);
03078 }
03079 CloseHandle(h);
03080 }
03081 d->xcelqrx = strncasecmp(pname, "EXCEL", 5) == 0 ||
03082 strncasecmp(pname, "MSQRY", 5) == 0;
03083 if (d->trace && d->xcelqrx) {
03084 fprintf(d->trace, "-- enabled EXCEL quirks\n");
03085 fflush(d->trace);
03086 }
03087 }
03088 #endif
03089 return SQL_SUCCESS;
03090 }
03091
03098 static void
03099 dbloadext(DBC *d, char *exts)
03100 {
03101 #if defined(HAVE_SQLITE3LOADEXTENSION) && HAVE_SQLITE3LOADEXTENSION
03102 char *p;
03103 char path[SQL_MAX_MESSAGE_LENGTH];
03104 int plen = 0;
03105
03106 if (!d->sqlite) {
03107 return;
03108 }
03109 sqlite3_enable_load_extension(d->sqlite, 1);
03110 #if defined(_WIN32) || defined(_WIN64)
03111 GetModuleFileName(hModule, path, sizeof (path));
03112 p = strrchr(path, '\\');
03113 plen = p ? ((p + 1) - path) : 0;
03114 #endif
03115 do {
03116 p = strchr(exts, ',');
03117 if (p) {
03118 strncpy(path + plen, exts, p - exts);
03119 path[plen + (p - exts)] = '\0';
03120 } else {
03121 strcpy(path + plen, exts);
03122 }
03123 if (exts[0]) {
03124 char *errmsg = NULL;
03125 int rc;
03126 #if defined(_WIN32) || defined(_WIN64)
03127 char *q;
03128
03129 q = path + plen;
03130 if (!(q[0] &&
03131 ((q[1] == ':' && (q[2] == '\\' || q[2] == '/')) ||
03132 q[0] == '\\' || q[0] == '/' || q[0] == '.'))) {
03133 q = path;
03134 }
03135 rc = sqlite3_load_extension(d->sqlite, q, 0, &errmsg);
03136 #else
03137 rc = sqlite3_load_extension(d->sqlite, path, 0, &errmsg);
03138 #endif
03139 if (rc != SQLITE_OK) {
03140 #if defined(_WIN32) || defined(_WIN64)
03141 char buf[512], msg[512];
03142
03143 LoadString(hModule, IDS_EXTERR, buf, sizeof (buf));
03144 wsprintf(msg, buf, q, errmsg ?
03145 errmsg : "no error info available");
03146 LoadString(hModule, IDS_EXTTITLE, buf, sizeof (buf));
03147 MessageBox(NULL, msg, buf,
03148 MB_ICONEXCLAMATION | MB_OK | MB_TASKMODAL |
03149 MB_SETFOREGROUND);
03150 #else
03151 fprintf(stderr, "extension '%s' did not load%s%s\n",
03152 path, errmsg ? ": " : "", errmsg ? errmsg : "");
03153 #endif
03154 }
03155 }
03156 if (p) {
03157 exts = p + 1;
03158 }
03159 } while (p);
03160 #endif
03161 }
03162
03172 static char *
03173 s3stmt_coltype(sqlite3_stmt *s3stmt, int col, DBC *d, int *guessed_types)
03174 {
03175 char *typename = (char *) sqlite3_column_decltype(s3stmt, col);
03176 char guess[64];
03177
03178 guess[0] = '\0';
03179 if (!typename) {
03180 int coltype = sqlite3_column_type(s3stmt, col);
03181
03182 if (guessed_types) {
03183 guessed_types[0]++;
03184 }
03185 if (d->trace) {
03186 sprintf(guess, " (guessed from %d)", coltype);
03187 }
03188 switch (coltype) {
03189 case SQLITE_INTEGER: typename = "integer"; break;
03190 case SQLITE_FLOAT: typename = "double"; break;
03191 default:
03192 case SQLITE_TEXT: typename = "varchar"; break;
03193 case SQLITE_BLOB: typename = "blob"; break;
03194 #if 0
03195 case SQLITE_NULL: typename = "null"; break;
03196 #endif
03197 }
03198 }
03199 if (d->trace) {
03200 fprintf(d->trace, "-- column %d type%s: '%s'\n", col + 1,
03201 guess, typename);
03202 fflush(d->trace);
03203 }
03204 return typename;
03205 }
03206
03207 #if defined(HAVE_SQLITE3TABLECOLUMNMETADATA) && HAVE_SQLITE3TABLECOLUMNMETADATA
03208
03217 static void
03218 s3stmt_addmeta(sqlite3_stmt *s3stmt, int col, DBC *d, COL *ci)
03219 {
03220 int nn = 0, pk = 0, ai = 0;
03221 const char *dn, *tn, *cn, *dummy1, *dummy2;
03222
03223 dn = sqlite3_column_database_name(s3stmt, col);
03224 tn = sqlite3_column_table_name(s3stmt, col);
03225 cn = sqlite3_column_origin_name(s3stmt, col);
03226 sqlite3_table_column_metadata(d->sqlite, dn, tn, cn,
03227 &dummy1, &dummy2,
03228 &nn, &pk, &ai);
03229 ci->autoinc = ai ? SQL_TRUE: SQL_FALSE;
03230 ci->notnull = nn ? SQL_NO_NULLS : SQL_NULLABLE;
03231 if (d->trace) {
03232 fprintf(d->trace, "-- column %d %s\n",
03233 col + 1, nn ? "notnull" : "nullable");
03234 if (ai) {
03235 fprintf(d->trace, "-- column %d autoincrement\n", col + 1);
03236 }
03237 fflush(d->trace);
03238 }
03239 }
03240
03241 #endif
03242
03249 static int
03250 s3stmt_step(STMT *s)
03251 {
03252 DBC *d = (DBC *) s->dbc;
03253 char **rowd = NULL;
03254 const char *errp = NULL;
03255 int i, ncols, rc;
03256
03257 if (s != d->cur_s3stmt || !s->s3stmt) {
03258 setstat(s, -1, "stale statement", (*s->ov3) ? "HY000" : "S1000");
03259 return SQL_ERROR;
03260 }
03261 rc = sqlite3_step(s->s3stmt);
03262 if (rc == SQLITE_ROW || rc == SQLITE_DONE) {
03263 ++s->s3stmt_rownum;
03264 ncols = sqlite3_column_count(s->s3stmt);
03265 if (d->s3stmt_needmeta && s->s3stmt_rownum == 0 && ncols > 0) {
03266 PTRDIFF_T size;
03267 char *p;
03268 COL *dyncols;
03269 const char *colname, *typename;
03270 #if defined(HAVE_SQLITE3COLUMNTABLENAME) && (HAVE_SQLITE3COLUMNTABLENAME)
03271 char *tblname;
03272 #endif
03273
03274 for (i = size = 0; i < ncols; i++) {
03275 colname = sqlite3_column_name(s->s3stmt, i);
03276 size += 3 + 3 * strlen(colname);
03277 }
03278 #if defined(HAVE_SQLITE3COLUMNTABLENAME) && (HAVE_SQLITE3COLUMNTABLENAME)
03279 tblname = (char *) size;
03280 for (i = 0; i < ncols; i++) {
03281 p = (char *) sqlite3_column_table_name(s->s3stmt, i);
03282 size += 2 + (p ? strlen(p) : 0);
03283 }
03284 #endif
03285 dyncols = xmalloc(ncols * sizeof (COL) + size);
03286 if (!dyncols) {
03287 freedyncols(s);
03288 s->ncols = 0;
03289 dbtraceapi(d, "sqlite3_finalize", 0);
03290 sqlite3_finalize(s->s3stmt);
03291 s->s3stmt = NULL;
03292 d->cur_s3stmt = NULL;
03293 return nomem(s);
03294 }
03295 p = (char *) (dyncols + ncols);
03296 #if defined(HAVE_SQLITE3COLUMNTABLENAME) && (HAVE_SQLITE3COLUMNTABLENAME)
03297 tblname = p + (PTRDIFF_T) tblname;
03298 #endif
03299 for (i = 0; i < ncols; i++) {
03300 char *q;
03301
03302 colname = sqlite3_column_name(s->s3stmt, i);
03303 if (d->trace) {
03304 fprintf(d->trace, "-- column %d name: '%s'\n",
03305 i + 1, colname);
03306 fflush(d->trace);
03307 }
03308 #if defined(HAVE_SQLITE3COLUMNTABLENAME) && (HAVE_SQLITE3COLUMNTABLENAME)
03309 q = (char *) sqlite3_column_table_name(s->s3stmt, i);
03310 strcpy(tblname, q ? q : "");
03311 if (d->trace) {
03312 fprintf(d->trace, "-- table %d name: '%s'\n",
03313 i + 1, tblname);
03314 fflush(d->trace);
03315 }
03316 dyncols[i].table = tblname;
03317 tblname += strlen(tblname) + 1;
03318 #endif
03319 typename = s3stmt_coltype(s->s3stmt, i, d, 0);
03320 dyncols[i].db = ((DBC *) (s->dbc))->dbname;
03321 strcpy(p, colname);
03322 dyncols[i].label = p;
03323 p += strlen(p) + 1;
03324 q = strchr(colname, '.');
03325 if (q) {
03326 char *q2 = strchr(q + 1, '.');
03327
03328
03329 if (q2) {
03330 q = q2;
03331 }
03332 }
03333 if (q) {
03334 #if !defined(HAVE_SQLITE3COLUMNTABLENAME) || !(HAVE_SQLITE3COLUMNTABLENAME)
03335 dyncols[i].table = p;
03336 #endif
03337 strncpy(p, colname, q - colname);
03338 p[q - colname] = '\0';
03339 p += strlen(p) + 1;
03340 strcpy(p, q + 1);
03341 dyncols[i].column = p;
03342 p += strlen(p) + 1;
03343 } else {
03344 #if !defined(HAVE_SQLITE3COLUMNTABLENAME) || !(HAVE_SQLITE3COLUMNTABLENAME)
03345 dyncols[i].table = "";
03346 #endif
03347 strcpy(p, colname);
03348 dyncols[i].column = p;
03349 p += strlen(p) + 1;
03350 }
03351 if (s->longnames) {
03352 dyncols[i].column = dyncols[i].label;
03353 }
03354 #ifdef SQL_LONGVARCHAR
03355 dyncols[i].type = SQL_LONGVARCHAR;
03356 dyncols[i].size = 65535;
03357 #else
03358 dyncols[i].type = SQL_VARCHAR;
03359 dyncols[i].size = 255;
03360 #endif
03361 dyncols[i].index = i;
03362 dyncols[i].scale = 0;
03363 dyncols[i].prec = 0;
03364 dyncols[i].nosign = 1;
03365 #if defined(HAVE_SQLITE3TABLECOLUMNMETADATA) && HAVE_SQLITE3TABLECOLUMNMETADATA
03366 s3stmt_addmeta(s->s3stmt, i, d, &dyncols[i]);
03367 #else
03368 dyncols[i].autoinc = SQL_FALSE;
03369 dyncols[i].notnull = SQL_NULLABLE;
03370 #endif
03371 dyncols[i].typename = xstrdup(typename);
03372 }
03373 freedyncols(s);
03374 s->ncols = s->dcols = ncols;
03375 s->dyncols = s->cols = dyncols;
03376 fixupdyncols(s, d);
03377 mkbindcols(s, s->ncols);
03378 d->s3stmt_needmeta = 0;
03379 }
03380 if (ncols <= 0) {
03381 goto killstmt;
03382 }
03383 if (rc == SQLITE_DONE) {
03384 freeresult(s, 0);
03385 s->nrows = 0;
03386 dbtraceapi(d, "sqlite3_finalize", 0);
03387 sqlite3_finalize(s->s3stmt);
03388 s->s3stmt = NULL;
03389 d->cur_s3stmt = NULL;
03390 return SQL_SUCCESS;
03391 }
03392 rowd = xmalloc((1 + 2 * ncols) * sizeof (char *));
03393 if (rowd) {
03394 const unsigned char *value;
03395
03396 rowd[0] = (char *) ((PTRDIFF_T) (ncols * 2));
03397 ++rowd;
03398 for (i = 0; i < ncols; i++) {
03399 int coltype = sqlite3_column_type(s->s3stmt, i);
03400
03401 rowd[i] = rowd[i + ncols] = NULL;
03402 if (coltype == SQLITE_BLOB) {
03403 int k, nbytes = sqlite3_column_bytes(s->s3stmt, i);
03404 char *qp;
03405 unsigned const char *bp;
03406
03407 bp = sqlite3_column_blob(s->s3stmt, i);
03408 qp = xmalloc(nbytes * 2 + 4);
03409 if (qp) {
03410 rowd[i + ncols] = qp;
03411 *qp++ = 'X';
03412 *qp++ = '\'';
03413 for (k = 0; k < nbytes; k++) {
03414 *qp++ = xdigits[(bp[k] >> 4)];
03415 *qp++ = xdigits[(bp[k] & 0xF)];
03416 }
03417 *qp++ = '\'';
03418 *qp = '\0';
03419 }
03420 } else if (coltype != SQLITE_NULL) {
03421 value = sqlite3_column_text(s->s3stmt, i);
03422 rowd[i + ncols] = xstrdup((char *) value);
03423 }
03424 }
03425 for (i = 0; i < ncols; i++) {
03426 int coltype = sqlite3_column_type(s->s3stmt, i);
03427
03428 value = NULL;
03429 if (coltype == SQLITE_BLOB) {
03430 value = sqlite3_column_blob(s->s3stmt, i);
03431 } else if (coltype != SQLITE_NULL) {
03432 value = sqlite3_column_text(s->s3stmt, i);
03433 }
03434 if (value && !rowd[i + ncols]) {
03435 freerows(rowd);
03436 rowd = 0;
03437 break;
03438 }
03439 }
03440 }
03441 if (rowd) {
03442 freeresult(s, 0);
03443 s->nrows = 1;
03444 s->rows = rowd;
03445 s->rowfree = freerows;
03446 if (rc == SQLITE_DONE) {
03447 dbtraceapi(d, "sqlite3_finalize", 0);
03448 sqlite3_finalize(s->s3stmt);
03449 s->s3stmt = NULL;
03450 d->cur_s3stmt = NULL;
03451 }
03452 return SQL_SUCCESS;
03453 }
03454 }
03455 killstmt:
03456 dbtraceapi(d, "sqlite3_reset", 0);
03457 rc = sqlite3_reset(s->s3stmt);
03458 s->s3stmt_noreset = 1;
03459 errp = sqlite3_errmsg(d->sqlite);
03460 if (d->cur_s3stmt == s) {
03461 d->cur_s3stmt = NULL;
03462 }
03463 setstat(s, rc, "%s (%d)", (*s->ov3) ? "HY000" : "S1000",
03464 errp ? errp : "unknown error", rc);
03465 return SQL_ERROR;
03466 }
03467
03473 static void
03474 s3stmt_end(STMT *s)
03475 {
03476 DBC *d;
03477
03478 if (!s || !s->s3stmt) {
03479 return;
03480 }
03481 d = (DBC *) s->dbc;
03482 if (d) {
03483 d->busyint = 0;
03484 }
03485 if (!s->s3stmt_noreset) {
03486 dbtraceapi(d, "sqlite3_reset", 0);
03487 sqlite3_reset(s->s3stmt);
03488 s->s3stmt_noreset = 1;
03489 s->s3stmt_rownum = -1;
03490 }
03491 if (d->cur_s3stmt == s) {
03492 d->cur_s3stmt = NULL;
03493 }
03494 }
03495
03501 static void
03502 s3stmt_end_if(STMT *s)
03503 {
03504 DBC *d = (DBC *) s->dbc;
03505
03506 if (d) {
03507 d->busyint = 0;
03508 }
03509 if (d && d->cur_s3stmt == s) {
03510 s3stmt_end(s);
03511 }
03512 }
03513
03519 static void
03520 s3stmt_drop(STMT *s)
03521 {
03522 if (s->s3stmt) {
03523 DBC *d = (DBC *) s->dbc;
03524
03525 if (d) {
03526 dbtraceapi(d, "sqlite3_finalize", 0);
03527 }
03528 sqlite3_finalize(s->s3stmt);
03529 s->s3stmt = NULL;
03530 s->s3stmt_rownum = 0;
03531 }
03532 }
03533
03540 static SQLRETURN
03541 s3stmt_start(STMT *s)
03542 {
03543 DBC *d = (DBC *) s->dbc;
03544 const char *endp;
03545 sqlite3_stmt *s3stmt = NULL;
03546 int rc, nretry = 0;
03547
03548 d->s3stmt_needmeta = 0;
03549 if (!s->s3stmt) {
03550 #if defined(HAVE_SQLITE3PREPAREV2) && HAVE_SQLITE3PREPAREV2
03551 dbtraceapi(d, "sqlite3_prepare_v2", (char *) s->query);
03552 #else
03553 dbtraceapi(d, "sqlite3_prepare", (char *) s->query);
03554 #endif
03555 do {
03556 s3stmt = NULL;
03557 #if defined(HAVE_SQLITE3PREPAREV2) && HAVE_SQLITE3PREPAREV2
03558 rc = sqlite3_prepare_v2(d->sqlite, (char *) s->query, -1,
03559 &s3stmt, &endp);
03560 #else
03561 rc = sqlite3_prepare(d->sqlite, (char *) s->query, -1,
03562 &s3stmt, &endp);
03563 #endif
03564 if (rc != SQLITE_OK) {
03565 if (s3stmt) {
03566 sqlite3_finalize(s3stmt);
03567 s3stmt = NULL;
03568 }
03569 }
03570 } while (rc == SQLITE_SCHEMA && (++nretry) < 2);
03571 dbtracerc(d, rc, NULL);
03572 if (rc != SQLITE_OK) {
03573 if (s3stmt) {
03574 dbtraceapi(d, "sqlite3_finalize", NULL);
03575 sqlite3_finalize(s3stmt);
03576 }
03577 setstat(s, rc, "%s (%d)", (*s->ov3) ? "HY000" : "S1000",
03578 sqlite3_errmsg(d->sqlite), rc);
03579 return SQL_ERROR;
03580 }
03581 if (sqlite3_bind_parameter_count(s3stmt) != s->nparams) {
03582 dbtraceapi(d, "sqlite3_finalize", 0);
03583 sqlite3_finalize(s3stmt);
03584 setstat(s, SQLITE_ERROR, "parameter marker count incorrect",
03585 (*s->ov3) ? "HY000" : "S1000");
03586 return SQL_ERROR;
03587 }
03588 s->s3stmt = s3stmt;
03589 s->s3stmt_noreset = 1;
03590 d->s3stmt_needmeta = 1;
03591 }
03592 d->cur_s3stmt = s;
03593 s->s3stmt_rownum = -1;
03594 s3bind(d, s->s3stmt, s->nparams, s->bindparms);
03595 return SQL_SUCCESS;
03596 }
03597
03602 SQLRETURN SQL_API
03603 SQLBulkOperations(SQLHSTMT stmt, SQLSMALLINT oper)
03604 {
03605 SQLRETURN ret;
03606
03607 HSTMT_LOCK(stmt);
03608 ret = drvunimplstmt(stmt);
03609 HSTMT_UNLOCK(stmt);
03610 return ret;
03611 }
03612
03613 #ifndef WINTERFACE
03614
03618 SQLRETURN SQL_API
03619 SQLDataSources(SQLHENV env, SQLUSMALLINT dir, SQLCHAR *srvname,
03620 SQLSMALLINT buflen1, SQLSMALLINT *lenp1,
03621 SQLCHAR *desc, SQLSMALLINT buflen2, SQLSMALLINT *lenp2)
03622 {
03623 if (env == SQL_NULL_HENV) {
03624 return SQL_INVALID_HANDLE;
03625 }
03626 return SQL_ERROR;
03627 }
03628 #endif
03629
03630 #ifdef WINTERFACE
03631
03635 SQLRETURN SQL_API
03636 SQLDataSourcesW(SQLHENV env, SQLUSMALLINT dir, SQLWCHAR *srvname,
03637 SQLSMALLINT buflen1, SQLSMALLINT *lenp1,
03638 SQLWCHAR *desc, SQLSMALLINT buflen2, SQLSMALLINT *lenp2)
03639 {
03640 if (env == SQL_NULL_HENV) {
03641 return SQL_INVALID_HANDLE;
03642 }
03643 return SQL_ERROR;
03644 }
03645 #endif
03646
03647 #ifndef WINTERFACE
03648
03652 SQLRETURN SQL_API
03653 SQLDrivers(SQLHENV env, SQLUSMALLINT dir, SQLCHAR *drvdesc,
03654 SQLSMALLINT descmax, SQLSMALLINT *desclenp,
03655 SQLCHAR *drvattr, SQLSMALLINT attrmax, SQLSMALLINT *attrlenp)
03656 {
03657 if (env == SQL_NULL_HENV) {
03658 return SQL_INVALID_HANDLE;
03659 }
03660 return SQL_ERROR;
03661 }
03662 #endif
03663
03664 #ifdef WINTERFACE
03665
03669 SQLRETURN SQL_API
03670 SQLDriversW(SQLHENV env, SQLUSMALLINT dir, SQLWCHAR *drvdesc,
03671 SQLSMALLINT descmax, SQLSMALLINT *desclenp,
03672 SQLWCHAR *drvattr, SQLSMALLINT attrmax, SQLSMALLINT *attrlenp)
03673 {
03674 if (env == SQL_NULL_HENV) {
03675 return SQL_INVALID_HANDLE;
03676 }
03677 return SQL_ERROR;
03678 }
03679 #endif
03680
03681 #ifndef WINTERFACE
03682
03686 SQLRETURN SQL_API
03687 SQLBrowseConnect(SQLHDBC dbc, SQLCHAR *connin, SQLSMALLINT conninLen,
03688 SQLCHAR *connout, SQLSMALLINT connoutMax,
03689 SQLSMALLINT *connoutLen)
03690 {
03691 SQLRETURN ret;
03692
03693 HDBC_LOCK(dbc);
03694 ret = drvunimpldbc(dbc);
03695 HDBC_UNLOCK(dbc);
03696 return ret;
03697 }
03698 #endif
03699
03700 #ifdef WINTERFACE
03701
03705 SQLRETURN SQL_API
03706 SQLBrowseConnectW(SQLHDBC dbc, SQLWCHAR *connin, SQLSMALLINT conninLen,
03707 SQLWCHAR *connout, SQLSMALLINT connoutMax,
03708 SQLSMALLINT *connoutLen)
03709 {
03710 SQLRETURN ret;
03711
03712 HDBC_LOCK(dbc);
03713 ret = drvunimpldbc(dbc);
03714 HDBC_UNLOCK(dbc);
03715 return ret;
03716 }
03717 #endif
03718
03727 static SQLRETURN
03728 drvputdata(SQLHSTMT stmt, SQLPOINTER data, SQLLEN len)
03729 {
03730 STMT *s;
03731 int i, dlen, done = 0;
03732 BINDPARM *p;
03733
03734 if (stmt == SQL_NULL_HSTMT) {
03735 return SQL_INVALID_HANDLE;
03736 }
03737 s = (STMT *) stmt;
03738 if (!s->query || s->nparams <= 0) {
03739 seqerr:
03740 setstat(s, -1, "sequence error", "HY010");
03741 return SQL_ERROR;
03742 }
03743 for (i = 0; i < s->nparams; i++) {
03744 p = &s->bindparms[i];
03745 if (p->need > 0) {
03746 int type = mapdeftype(p->type, p->stype, -1, s->nowchar[0]);
03747
03748 if (len == SQL_NULL_DATA) {
03749 freep(&p->parbuf);
03750 p->param = NULL;
03751 p->len = SQL_NULL_DATA;
03752 p->need = -1;
03753 } else if (type != SQL_C_CHAR
03754 #ifdef WINTERFACE
03755 && type != SQL_C_WCHAR
03756 #endif
03757 && type != SQL_C_BINARY) {
03758 int size = 0;
03759
03760 switch (type) {
03761 case SQL_C_TINYINT:
03762 case SQL_C_UTINYINT:
03763 case SQL_C_STINYINT:
03764 #ifdef SQL_BIT
03765 case SQL_C_BIT:
03766 #endif
03767 size = sizeof (char);
03768 break;
03769 case SQL_C_SHORT:
03770 case SQL_C_USHORT:
03771 case SQL_C_SSHORT:
03772 size = sizeof (short);
03773 break;
03774 case SQL_C_LONG:
03775 case SQL_C_ULONG:
03776 case SQL_C_SLONG:
03777 size = sizeof (long);
03778 break;
03779 #ifdef SQL_BIGINT
03780 case SQL_C_UBIGINT:
03781 case SQL_C_SBIGINT:
03782 size = sizeof (SQLBIGINT);
03783 break;
03784 #endif
03785 case SQL_C_FLOAT:
03786 size = sizeof (float);
03787 break;
03788 case SQL_C_DOUBLE:
03789 size = sizeof (double);
03790 break;
03791 #ifdef SQL_C_TYPE_DATE
03792 case SQL_C_TYPE_DATE:
03793 #endif
03794 case SQL_C_DATE:
03795 size = sizeof (DATE_STRUCT);
03796 break;
03797 #ifdef SQL_C_TYPE_DATE
03798 case SQL_C_TYPE_TIME:
03799 #endif
03800 case SQL_C_TIME:
03801 size = sizeof (TIME_STRUCT);
03802 break;
03803 #ifdef SQL_C_TYPE_DATE
03804 case SQL_C_TYPE_TIMESTAMP:
03805 #endif
03806 case SQL_C_TIMESTAMP:
03807 size = sizeof (TIMESTAMP_STRUCT);
03808 break;
03809 }
03810 freep(&p->parbuf);
03811 p->parbuf = xmalloc(size);
03812 if (!p->parbuf) {
03813 return nomem(s);
03814 }
03815 p->param = p->parbuf;
03816 memcpy(p->param, data, size);
03817 p->len = size;
03818 p->need = -1;
03819 } else if (len == SQL_NTS && (
03820 type == SQL_C_CHAR
03821 #ifdef WINTERFACE
03822 || type == SQL_C_WCHAR
03823 #endif
03824 )) {
03825 char *dp = data;
03826
03827 #ifdef WINTERFACE
03828 if (type == SQL_C_WCHAR) {
03829 dp = uc_to_utf(data, len);
03830 if (!dp) {
03831 return nomem(s);
03832 }
03833 }
03834 #endif
03835 dlen = strlen(dp);
03836 freep(&p->parbuf);
03837 p->parbuf = xmalloc(dlen + 1);
03838 if (!p->parbuf) {
03839 #ifdef WINTERFACE
03840 if (dp != data) {
03841 uc_free(dp);
03842 }
03843 #endif
03844 return nomem(s);
03845 }
03846 p->param = p->parbuf;
03847 strcpy(p->param, dp);
03848 #ifdef WINTERFACE
03849 if (dp != data) {
03850 uc_free(dp);
03851 }
03852 #endif
03853 p->len = dlen;
03854 p->need = -1;
03855 } else if (len < 0) {
03856 setstat(s, -1, "invalid length", "HY090");
03857 return SQL_ERROR;
03858 } else {
03859 dlen = min(p->len - p->offs, len);
03860 if (!p->param) {
03861 setstat(s, -1, "no memory for parameter", "HY013");
03862 return SQL_ERROR;
03863 }
03864 memcpy((char *) p->param + p->offs, data, dlen);
03865 p->offs += dlen;
03866 if (p->offs >= p->len) {
03867 #ifdef WINTERFACE
03868 if (type == SQL_C_WCHAR) {
03869 char *dp = uc_to_utf(p->param, p->len);
03870 char *np;
03871 int nlen;
03872
03873 if (!dp) {
03874 return nomem(s);
03875 }
03876 nlen = strlen(dp);
03877 np = xmalloc(nlen + 1);
03878 if (!np) {
03879 uc_free(dp);
03880 return nomem(s);
03881 }
03882 strcpy(np, dp);
03883 uc_free(dp);
03884 if (p->param == p->parbuf) {
03885 freep(&p->parbuf);
03886 }
03887 p->parbuf = p->param = np;
03888 p->len = nlen;
03889 } else {
03890 *((char *) p->param + p->len) = '\0';
03891 }
03892 p->need = (type == SQL_C_CHAR || type == SQL_C_WCHAR)
03893 ? -1 : 0;
03894 #else
03895 *((char *) p->param + p->len) = '\0';
03896 p->need = (type == SQL_C_CHAR) ? -1 : 0;
03897 #endif
03898 #if defined(_WIN32) || defined(_WIN64)
03899 if (p->type == SQL_C_WCHAR &&
03900 (p->stype == SQL_VARCHAR ||
03901 p->stype == SQL_LONGVARCHAR) &&
03902 p->len == p->coldef * sizeof (SQLWCHAR)) {
03903
03904 p->len = p->coldef;
03905 }
03906 #endif
03907 }
03908 }
03909 done = 1;
03910 break;
03911 }
03912 }
03913 if (!done) {
03914 goto seqerr;
03915 }
03916 return SQL_SUCCESS;
03917 }
03918
03927 SQLRETURN SQL_API
03928 SQLPutData(SQLHSTMT stmt, SQLPOINTER data, SQLLEN len)
03929 {
03930 SQLRETURN ret;
03931
03932 HSTMT_LOCK(stmt);
03933 ret = drvputdata(stmt, data, len);
03934 HSTMT_UNLOCK(stmt);
03935 return ret;
03936 }
03937
03943 static SQLRETURN
03944 freeparams(STMT *s)
03945 {
03946 if (s->bindparms) {
03947 int n;
03948
03949 for (n = 0; n < s->nbindparms; n++) {
03950 freep(&s->bindparms[n].parbuf);
03951 memset(&s->bindparms[n], 0, sizeof (BINDPARM));
03952 }
03953 }
03954 return SQL_SUCCESS;
03955 }
03956
03968 static SQLRETURN
03969 setupparam(STMT *s, char *sql, int pnum)
03970 {
03971 int type, len = 0, needalloc = 0;
03972 BINDPARM *p;
03973
03974 if (!s->bindparms || pnum < 0 || pnum >= s->nbindparms) {
03975 goto error;
03976 }
03977 p = &s->bindparms[pnum];
03978 type = mapdeftype(p->type, p->stype, -1, s->nowchar[0]);
03979 if (p->need > 0) {
03980 return setupparbuf(s, p);
03981 }
03982 p->strbuf[0] = '\0';
03983 if (!p->param || (p->lenp && *p->lenp == SQL_NULL_DATA)) {
03984 p->s3type = SQLITE_NULL;
03985 p->s3size = 0;
03986 return SQL_SUCCESS;
03987 }
03988 switch (type) {
03989 case SQL_C_BINARY:
03990 p->s3type = SQLITE_BLOB;
03991 p->s3size = p->len;
03992 p->s3val = p->param;
03993 if (p->need < 0) {
03994 break;
03995 }
03996 if (!p->lenp) {
03997 len = p->len;
03998 } else {
03999 len = *p->lenp;
04000 if (len <= SQL_LEN_DATA_AT_EXEC_OFFSET) {
04001 len = SQL_LEN_DATA_AT_EXEC(len);
04002 }
04003 }
04004 if (len < 0) {
04005 setstat(s, -1, "invalid length", "HY009");
04006 return SQL_ERROR;
04007 }
04008 p->len = len;
04009 p->max = p->len;
04010 p->need = -1;
04011 p->s3size = len;
04012 break;
04013 #ifdef WINTERFACE
04014 case SQL_C_WCHAR:
04015 #endif
04016 case SQL_C_CHAR:
04017 p->s3type = SQLITE_TEXT;
04018 p->s3size = -1;
04019 p->s3val = p->param;
04020 if (!p->parbuf && p->lenp) {
04021 #ifdef WINTERFACE
04022 if (type == SQL_C_WCHAR) {
04023 if (*p->lenp == SQL_NTS) {
04024 p->max = uc_strlen(p->param) * sizeof (SQLWCHAR);
04025 } else if (*p->lenp >= 0) {
04026 p->max = *p->lenp;
04027 }
04028 } else
04029 #endif
04030 if (type == SQL_C_CHAR) {
04031 if (*p->lenp == SQL_NTS) {
04032 p->len = p->max = strlen(p->param);
04033 } else if (*p->lenp >= 0) {
04034 p->len = p->max = *p->lenp;
04035 needalloc = 1;
04036 }
04037 }
04038 }
04039 if (p->need < 0 && p->parbuf == p->param) {
04040 break;
04041 }
04042 #ifdef WINTERFACE
04043 if (type == SQL_C_WCHAR) {
04044 char *dp = uc_to_utf(p->param, p->max);
04045
04046 if (!dp) {
04047 return nomem(s);
04048 }
04049 if (p->param == p->parbuf) {
04050 freep(&p->parbuf);
04051 }
04052 p->parbuf = p->param = dp;
04053 p->len = strlen(p->param);
04054 p->s3val = p->param;
04055 p->s3size = p->len;
04056 } else
04057 #endif
04058 if (type == SQL_C_CHAR) {
04059 p->s3val = p->param;
04060 if (needalloc) {
04061 char *dp;
04062
04063 freep(&p->parbuf);
04064 dp = xmalloc(p->len + 1);
04065 if (!dp) {
04066 return nomem(s);
04067 }
04068 memcpy(dp, p->param, p->len);
04069 dp[p->len] = '\0';
04070 p->parbuf = p->param = dp;
04071 p->s3val = p->param;
04072 p->s3size = p->len;
04073 }
04074 }
04075 break;
04076 case SQL_C_UTINYINT:
04077 p->s3type = SQLITE_INTEGER;
04078 p->s3size = sizeof (int);
04079 p->s3ival = *((unsigned char *) p->param);
04080 break;
04081 case SQL_C_TINYINT:
04082 case SQL_C_STINYINT:
04083 p->s3type = SQLITE_INTEGER;
04084 p->s3size = sizeof (int);
04085 p->s3ival = *((char *) p->param);
04086 break;
04087 case SQL_C_USHORT:
04088 p->s3type = SQLITE_INTEGER;
04089 p->s3size = sizeof (int);
04090 p->s3ival = *((unsigned short *) p->param);
04091 break;
04092 case SQL_C_SHORT:
04093 case SQL_C_SSHORT:
04094 p->s3type = SQLITE_INTEGER;
04095 p->s3size = sizeof (int);
04096 p->s3ival = *((short *) p->param);
04097 break;
04098 case SQL_C_ULONG:
04099 p->s3type = SQLITE_INTEGER;
04100 p->s3size = sizeof (int);
04101 p->s3ival = *((unsigned int *) p->param);
04102 break;
04103 case SQL_C_LONG:
04104 case SQL_C_SLONG:
04105 p->s3type = SQLITE_INTEGER;
04106 p->s3size = sizeof (int);
04107 p->s3ival = *((int *) p->param);
04108 break;
04109 #ifdef SQL_BIT
04110 case SQL_C_BIT:
04111 p->s3type = SQLITE_INTEGER;
04112 p->s3size = sizeof (int);
04113 p->s3ival = (*((unsigned char *) p->param)) ? 1 : 0;
04114 break;
04115 #endif
04116 #ifdef SQL_BIGINT
04117 case SQL_C_SBIGINT:
04118 p->s3type = SQLITE_INTEGER;
04119 p->s3size = sizeof (sqlite_int64);
04120 p->s3lival = *((sqlite_int64 *) p->param);
04121 break;
04122 case SQL_C_UBIGINT:
04123 p->s3type = SQLITE_INTEGER;
04124 p->s3size = sizeof (sqlite_int64);
04125 p->s3lival = *((sqlite_uint64 *) p->param);
04126 break;
04127 #endif
04128 case SQL_C_FLOAT:
04129 p->s3type = SQLITE_FLOAT;
04130 p->s3size = sizeof (double);
04131 p->s3dval = *((float *) p->param);
04132 break;
04133 case SQL_C_DOUBLE:
04134 p->s3type = SQLITE_FLOAT;
04135 p->s3size = sizeof (double);
04136 p->s3dval = *((double *) p->param);
04137 break;
04138 #ifdef SQL_C_TYPE_DATE
04139 case SQL_C_TYPE_DATE:
04140 #endif
04141 case SQL_C_DATE:
04142 sprintf(p->strbuf, "%04d-%02d-%02d",
04143 ((DATE_STRUCT *) p->param)->year,
04144 ((DATE_STRUCT *) p->param)->month,
04145 ((DATE_STRUCT *) p->param)->day);
04146 p->s3type = SQLITE_TEXT;
04147 p->s3size = -1;
04148 p->s3val = p->strbuf;
04149 break;
04150 #ifdef SQL_C_TYPE_TIME
04151 case SQL_C_TYPE_TIME:
04152 #endif
04153 case SQL_C_TIME:
04154 sprintf(p->strbuf, "%02d:%02d:%02d",
04155 ((TIME_STRUCT *) p->param)->hour,
04156 ((TIME_STRUCT *) p->param)->minute,
04157 ((TIME_STRUCT *) p->param)->second);
04158 p->s3type = SQLITE_TEXT;
04159 p->s3size = -1;
04160 p->s3val = p->strbuf;
04161 break;
04162 #ifdef SQL_C_TYPE_TIMESTAMP
04163 case SQL_C_TYPE_TIMESTAMP:
04164 #endif
04165 case SQL_C_TIMESTAMP:
04166 sprintf(p->strbuf, "%04d-%02d-%02d %02d:%02d:%02d.%d",
04167 ((TIMESTAMP_STRUCT *) p->param)->year,
04168 ((TIMESTAMP_STRUCT *) p->param)->month,
04169 ((TIMESTAMP_STRUCT *) p->param)->day,
04170 ((TIMESTAMP_STRUCT *) p->param)->hour,
04171 ((TIMESTAMP_STRUCT *) p->param)->minute,
04172 ((TIMESTAMP_STRUCT *) p->param)->second,
04173 (int) ((TIMESTAMP_STRUCT *) p->param)->fraction);
04174 p->s3type = SQLITE_TEXT;
04175 p->s3size = -1;
04176 p->s3val = p->strbuf;
04177 break;
04178 default:
04179 error:
04180 setstat(s, -1, "unsupported parameter type",
04181 (*s->ov3) ? "07009" : "S1093");
04182 return SQL_ERROR;
04183 }
04184 return SQL_SUCCESS;
04185 }
04186
04202 static SQLRETURN
04203 drvbindparam(SQLHSTMT stmt, SQLUSMALLINT pnum, SQLSMALLINT iotype,
04204 SQLSMALLINT buftype, SQLSMALLINT ptype, SQLUINTEGER coldef,
04205 SQLSMALLINT scale,
04206 SQLPOINTER data, SQLINTEGER buflen, SQLLEN *len)
04207 {
04208 STMT *s;
04209 BINDPARM *p;
04210
04211 if (stmt == SQL_NULL_HSTMT) {
04212 return SQL_INVALID_HANDLE;
04213 }
04214 s = (STMT *) stmt;
04215 if (pnum == 0) {
04216 setstat(s, -1, "invalid parameter", (*s->ov3) ? "07009" : "S1093");
04217 return SQL_ERROR;
04218 }
04219 if (!data && (!len || (*len != SQL_NULL_DATA &&
04220 *len > SQL_LEN_DATA_AT_EXEC_OFFSET))) {
04221 setstat(s, -1, "invalid buffer", "HY003");
04222 return SQL_ERROR;
04223 }
04224 if (len && *len < 0 && *len > SQL_LEN_DATA_AT_EXEC_OFFSET &&
04225 *len != SQL_NTS && *len != SQL_NULL_DATA) {
04226 setstat(s, -1, "invalid length reference", "HY009");
04227 return SQL_ERROR;
04228 }
04229 --pnum;
04230 if (s->bindparms) {
04231 if (pnum >= s->nbindparms) {
04232 BINDPARM *newparms;
04233
04234 newparms = xrealloc(s->bindparms,
04235 (pnum + 1) * sizeof (BINDPARM));
04236 if (!newparms) {
04237 outofmem:
04238 return nomem(s);
04239 }
04240 s->bindparms = newparms;
04241 memset(&s->bindparms[s->nbindparms], 0,
04242 (pnum + 1 - s->nbindparms) * sizeof (BINDPARM));
04243 s->nbindparms = pnum + 1;
04244 }
04245 } else {
04246 int npar = max(10, pnum + 1);
04247
04248 s->bindparms = xmalloc(npar * sizeof (BINDPARM));
04249 if (!s->bindparms) {
04250 goto outofmem;
04251 }
04252 memset(s->bindparms, 0, npar * sizeof (BINDPARM));
04253 s->nbindparms = npar;
04254 }
04255 p = &s->bindparms[pnum];
04256 p->type = buftype;
04257 p->stype = ptype;
04258 p->coldef = coldef;
04259 p->scale = scale;
04260 p->max = buflen;
04261 p->inc = buflen;
04262 p->lenp = p->lenp0 = len;
04263 p->offs = 0;
04264 p->len = 0;
04265 p->param0 = data;
04266 freep(&p->parbuf);
04267 p->param = p->param0;
04268 p->bound = 1;
04269 p->need = 0;
04270 if (p->lenp && *p->lenp <= SQL_LEN_DATA_AT_EXEC_OFFSET) {
04271 p->need = 1;
04272 }
04273 return SQL_SUCCESS;
04274 }
04275
04291 SQLRETURN SQL_API
04292 SQLBindParameter(SQLHSTMT stmt, SQLUSMALLINT pnum, SQLSMALLINT iotype,
04293 SQLSMALLINT buftype, SQLSMALLINT ptype, SQLULEN coldef,
04294 SQLSMALLINT scale,
04295 SQLPOINTER data, SQLLEN buflen, SQLLEN *len)
04296 {
04297 SQLRETURN ret;
04298
04299 HSTMT_LOCK(stmt);
04300 ret = drvbindparam(stmt, pnum, iotype, buftype, ptype, coldef,
04301 scale, data, buflen, len);
04302 HSTMT_UNLOCK(stmt);
04303 return ret;
04304 }
04305
04319 SQLRETURN SQL_API
04320 SQLBindParam(SQLHSTMT stmt, SQLUSMALLINT pnum, SQLSMALLINT vtype,
04321 SQLSMALLINT ptype, SQLULEN lenprec,
04322 SQLSMALLINT scale, SQLPOINTER val,
04323 SQLLEN *lenp)
04324 {
04325 SQLRETURN ret;
04326
04327 HSTMT_LOCK(stmt);
04328 ret = drvbindparam(stmt, pnum, SQL_PARAM_INPUT, vtype, ptype,
04329 lenprec, scale, val, 0, lenp);
04330 HSTMT_UNLOCK(stmt);
04331 return ret;
04332 }
04333
04341 SQLRETURN SQL_API
04342 SQLNumParams(SQLHSTMT stmt, SQLSMALLINT *nparam)
04343 {
04344 STMT *s;
04345 SQLSMALLINT dummy;
04346
04347 HSTMT_LOCK(stmt);
04348 if (stmt == SQL_NULL_HSTMT) {
04349 return SQL_INVALID_HANDLE;
04350 }
04351 s = (STMT *) stmt;
04352 if (!nparam) {
04353 nparam = &dummy;
04354 }
04355 *nparam = s->nparams;
04356 HSTMT_UNLOCK(stmt);
04357 return SQL_SUCCESS;
04358 }
04359
04367 static SQLRETURN
04368 setupparbuf(STMT *s, BINDPARM *p)
04369 {
04370 if (!p->parbuf) {
04371 p->len = SQL_LEN_DATA_AT_EXEC(*p->lenp);
04372 if (p->len < 0 && p->len != SQL_NTS &&
04373 p->len != SQL_NULL_DATA) {
04374 setstat(s, -1, "invalid length", "HY009");
04375 return SQL_ERROR;
04376 }
04377 if (p->len >= 0) {
04378 p->parbuf = xmalloc(p->len + 1);
04379 if (!p->parbuf) {
04380 return nomem(s);
04381 }
04382 p->param = p->parbuf;
04383 } else {
04384 p->param = NULL;
04385 }
04386 }
04387 return SQL_NEED_DATA;
04388 }
04389
04397 SQLRETURN SQL_API
04398 SQLParamData(SQLHSTMT stmt, SQLPOINTER *pind)
04399 {
04400 STMT *s;
04401 int i;
04402 SQLPOINTER dummy;
04403 SQLRETURN ret;
04404
04405 HSTMT_LOCK(stmt);
04406 if (stmt == SQL_NULL_HSTMT) {
04407 return SQL_INVALID_HANDLE;
04408 }
04409 s = (STMT *) stmt;
04410 if (!pind) {
04411 pind = &dummy;
04412 }
04413 for (i = 0; i < s->nparams; i++) {
04414 BINDPARM *p = &s->bindparms[i];
04415
04416 if (p->need > 0) {
04417 *pind = (SQLPOINTER) p->param0;
04418 ret = setupparbuf(s, p);
04419 goto done;
04420 }
04421 }
04422 ret = drvexecute(stmt, 0);
04423 done:
04424 HSTMT_UNLOCK(stmt);
04425 return ret;
04426 }
04427
04439 SQLRETURN SQL_API
04440 SQLDescribeParam(SQLHSTMT stmt, SQLUSMALLINT pnum, SQLSMALLINT *dtype,
04441 SQLULEN *size, SQLSMALLINT *decdigits, SQLSMALLINT *nullable)
04442 {
04443 STMT *s;
04444 SQLRETURN ret = SQL_ERROR;
04445
04446 HSTMT_LOCK(stmt);
04447 if (stmt == SQL_NULL_HSTMT) {
04448 return SQL_INVALID_HANDLE;
04449 }
04450 s = (STMT *) stmt;
04451 --pnum;
04452 if (pnum >= s->nparams) {
04453 setstat(s, -1, "invalid parameter index",
04454 (*s->ov3) ? "HY000" : "S1000");
04455 goto done;
04456 }
04457 if (dtype) {
04458 #ifdef SQL_LONGVARCHAR
04459 #ifdef WINTERFACE
04460 *dtype = s->nowchar[0] ? SQL_LONGVARCHAR : SQL_WLONGVARCHAR;
04461 #else
04462 *dtype = SQL_LONGVARCHAR;
04463 #endif
04464 #else
04465 #ifdef WINTERFACE
04466 *dtype = s->nowchar[0] ? SQL_VARCHAR : SQL_WVARCHAR;
04467 #else
04468 *dtype = SQL_VARCHAR;
04469 #endif
04470 #endif
04471 }
04472 if (size) {
04473 #ifdef SQL_LONGVARCHAR
04474 *size = 65536;
04475 #else
04476 *size = 255;
04477 #endif
04478 }
04479 if (decdigits) {
04480 *decdigits = 0;
04481 }
04482 if (nullable) {
04483 *nullable = SQL_NULLABLE;
04484 }
04485 ret = SQL_SUCCESS;
04486 done:
04487 HSTMT_UNLOCK(stmt);
04488 return ret;
04489 }
04490
04504 SQLRETURN SQL_API
04505 SQLSetParam(SQLHSTMT stmt, SQLUSMALLINT par, SQLSMALLINT type,
04506 SQLSMALLINT sqltype, SQLULEN coldef,
04507 SQLSMALLINT scale, SQLPOINTER val, SQLLEN *nval)
04508 {
04509 SQLRETURN ret;
04510
04511 HSTMT_LOCK(stmt);
04512 ret = drvbindparam(stmt, par, SQL_PARAM_INPUT,
04513 type, sqltype, coldef, scale, val,
04514 SQL_SETPARAM_VALUE_MAX, nval);
04515 HSTMT_UNLOCK(stmt);
04516 return ret;
04517 }
04518
04523 SQLRETURN SQL_API
04524 SQLParamOptions(SQLHSTMT stmt, SQLULEN rows, SQLULEN *rowp)
04525 {
04526 SQLRETURN ret;
04527
04528 HSTMT_LOCK(stmt);
04529 ret = drvunimplstmt(stmt);
04530 HSTMT_UNLOCK(stmt);
04531 return ret;
04532 }
04533
04534 #ifndef WINTERFACE
04535
04539 SQLRETURN SQL_API
04540 SQLGetDescField(SQLHDESC handle, SQLSMALLINT recno,
04541 SQLSMALLINT fieldid, SQLPOINTER value,
04542 SQLINTEGER buflen, SQLINTEGER *strlen)
04543 {
04544 return SQL_ERROR;
04545 }
04546 #endif
04547
04548 #ifdef WINTERFACE
04549
04553 SQLRETURN SQL_API
04554 SQLGetDescFieldW(SQLHDESC handle, SQLSMALLINT recno,
04555 SQLSMALLINT fieldid, SQLPOINTER value,
04556 SQLINTEGER buflen, SQLINTEGER *strlen)
04557 {
04558 return SQL_ERROR;
04559 }
04560 #endif
04561
04562 #ifndef WINTERFACE
04563
04567 SQLRETURN SQL_API
04568 SQLSetDescField(SQLHDESC handle, SQLSMALLINT recno,
04569 SQLSMALLINT fieldid, SQLPOINTER value,
04570 SQLINTEGER buflen)
04571 {
04572 return SQL_ERROR;
04573 }
04574 #endif
04575
04576 #ifdef WINTERFACE
04577
04581 SQLRETURN SQL_API
04582 SQLSetDescFieldW(SQLHDESC handle, SQLSMALLINT recno,
04583 SQLSMALLINT fieldid, SQLPOINTER value,
04584 SQLINTEGER buflen)
04585 {
04586 return SQL_ERROR;
04587 }
04588 #endif
04589
04590 #ifndef WINTERFACE
04591
04595 SQLRETURN SQL_API
04596 SQLGetDescRec(SQLHDESC handle, SQLSMALLINT recno,
04597 SQLCHAR *name, SQLSMALLINT buflen,
04598 SQLSMALLINT *strlen, SQLSMALLINT *type,
04599 SQLSMALLINT *subtype, SQLLEN *len,
04600 SQLSMALLINT *prec, SQLSMALLINT *scale,
04601 SQLSMALLINT *nullable)
04602 {
04603 return SQL_ERROR;
04604 }
04605 #endif
04606
04607 #ifdef WINTERFACE
04608
04612 SQLRETURN SQL_API
04613 SQLGetDescRecW(SQLHDESC handle, SQLSMALLINT recno,
04614 SQLWCHAR *name, SQLSMALLINT buflen,
04615 SQLSMALLINT *strlen, SQLSMALLINT *type,
04616 SQLSMALLINT *subtype, SQLLEN *len,
04617 SQLSMALLINT *prec, SQLSMALLINT *scale,
04618 SQLSMALLINT *nullable)
04619 {
04620 return SQL_ERROR;
04621 }
04622 #endif
04623
04628 SQLRETURN SQL_API
04629 SQLSetDescRec(SQLHDESC handle, SQLSMALLINT recno,
04630 SQLSMALLINT type, SQLSMALLINT subtype,
04631 SQLLEN len, SQLSMALLINT prec,
04632 SQLSMALLINT scale, SQLPOINTER data,
04633 SQLLEN *strlen, SQLLEN *indicator)
04634 {
04635 return SQL_ERROR;
04636 }
04637
04649 static SQLRETURN
04650 mkresultset(HSTMT stmt, COL *colspec, int ncols, COL *colspec3,
04651 int ncols3, int *nret)
04652 {
04653 STMT *s;
04654 DBC *d;
04655
04656 if (stmt == SQL_NULL_HSTMT) {
04657 return SQL_INVALID_HANDLE;
04658 }
04659 s = (STMT *) stmt;
04660 if (s->dbc == SQL_NULL_HDBC) {
04661 noconn:
04662 return noconn(s);
04663 }
04664 d = (DBC *) s->dbc;
04665 if (!d->sqlite) {
04666 goto noconn;
04667 }
04668 s3stmt_end_if(s);
04669 freeresult(s, 0);
04670 if (colspec3 && *s->ov3) {
04671 s->ncols = ncols3;
04672 s->cols = colspec3;
04673 } else {
04674 s->ncols = ncols;
04675 s->cols = colspec;
04676 }
04677 mkbindcols(s, s->ncols);
04678 s->nowchar[1] = 1;
04679 s->nrows = 0;
04680 s->rowp = -1;
04681 s->isselect = -1;
04682 if (nret) {
04683 *nret = s->ncols;
04684 }
04685 return SQL_SUCCESS;
04686 }
04687
04692 static COL tablePrivSpec2[] = {
04693 { "SYSTEM", "TABLEPRIV", "TABLE_QUALIFIER", SCOL_VARCHAR, 50 },
04694 { "SYSTEM", "TABLEPRIV", "TABLE_OWNER", SCOL_VARCHAR, 50 },
04695 { "SYSTEM", "TABLEPRIV", "TABLE_NAME", SCOL_VARCHAR, 255 },
04696 { "SYSTEM", "TABLEPRIV", "GRANTOR", SCOL_VARCHAR, 50 },
04697 { "SYSTEM", "TABLEPRIV", "GRANTEE", SCOL_VARCHAR, 50 },
04698 { "SYSTEM", "TABLEPRIV", "PRIVILEGE", SCOL_VARCHAR, 50 },
04699 { "SYSTEM", "TABLEPRIV", "IS_GRANTABLE", SCOL_VARCHAR, 50 }
04700 };
04701
04702 static COL tablePrivSpec3[] = {
04703 { "SYSTEM", "TABLEPRIV", "TABLE_CAT", SCOL_VARCHAR, 50 },
04704 { "SYSTEM", "TABLEPRIV", "TABLE_SCHEM", SCOL_VARCHAR, 50 },
04705 { "SYSTEM", "TABLEPRIV", "TABLE_NAME", SCOL_VARCHAR, 255 },
04706 { "SYSTEM", "TABLEPRIV", "GRANTOR", SCOL_VARCHAR, 50 },
04707 { "SYSTEM", "TABLEPRIV", "GRANTEE", SCOL_VARCHAR, 50 },
04708 { "SYSTEM", "TABLEPRIV", "PRIVILEGE", SCOL_VARCHAR, 50 },
04709 { "SYSTEM", "TABLEPRIV", "IS_GRANTABLE", SCOL_VARCHAR, 50 }
04710 };
04711
04712 #if !defined(WINTERFACE) || (defined(HAVE_UNIXODBC) && HAVE_UNIXODBC)
04713
04725 SQLRETURN SQL_API
04726 SQLTablePrivileges(SQLHSTMT stmt,
04727 SQLCHAR *catalog, SQLSMALLINT catalogLen,
04728 SQLCHAR *schema, SQLSMALLINT schemaLen,
04729 SQLCHAR *table, SQLSMALLINT tableLen)
04730 {
04731 SQLRETURN ret;
04732
04733 HSTMT_LOCK(stmt);
04734 ret = mkresultset(stmt, tablePrivSpec2, array_size(tablePrivSpec2),
04735 tablePrivSpec3, array_size(tablePrivSpec3), NULL);
04736 HSTMT_UNLOCK(stmt);
04737 return ret;
04738 }
04739 #endif
04740
04741 #if !defined(HAVE_UNIXODBC) || !HAVE_UNIXODBC
04742 #ifdef WINTERFACE
04743
04755 SQLRETURN SQL_API
04756 SQLTablePrivilegesW(SQLHSTMT stmt,
04757 SQLWCHAR *catalog, SQLSMALLINT catalogLen,
04758 SQLWCHAR *schema, SQLSMALLINT schemaLen,
04759 SQLWCHAR *table, SQLSMALLINT tableLen)
04760 {
04761 SQLRETURN ret;
04762
04763 HSTMT_LOCK(stmt);
04764 ret = mkresultset(stmt, tablePrivSpec2, array_size(tablePrivSpec2),
04765 tablePrivSpec3, array_size(tablePrivSpec3), NULL);
04766 HSTMT_UNLOCK(stmt);
04767 return ret;
04768 }
04769 #endif
04770 #endif
04771
04776 static COL colPrivSpec2[] = {
04777 { "SYSTEM", "COLPRIV", "TABLE_QUALIFIER", SCOL_VARCHAR, 50 },
04778 { "SYSTEM", "COLPRIV", "TABLE_OWNER", SCOL_VARCHAR, 50 },
04779 { "SYSTEM", "COLPRIV", "TABLE_NAME", SCOL_VARCHAR, 255 },
04780 { "SYSTEM", "COLPRIV", "COLUMN_NAME", SCOL_VARCHAR, 255 },
04781 { "SYSTEM", "COLPRIV", "GRANTOR", SCOL_VARCHAR, 50 },
04782 { "SYSTEM", "COLPRIV", "GRANTEE", SCOL_VARCHAR, 50 },
04783 { "SYSTEM", "COLPRIV", "PRIVILEGE", SCOL_VARCHAR, 50 }
04784 };
04785
04786 static COL colPrivSpec3[] = {
04787 { "SYSTEM", "COLPRIV", "TABLE_CAT", SCOL_VARCHAR, 50 },
04788 { "SYSTEM", "COLPRIV", "TABLE_SCHEM", SCOL_VARCHAR, 50 },
04789 { "SYSTEM", "COLPRIV", "TABLE_NAME", SCOL_VARCHAR, 255 },
04790 { "SYSTEM", "COLPRIV", "COLUMN_NAME", SCOL_VARCHAR, 255 },
04791 { "SYSTEM", "COLPRIV", "GRANTOR", SCOL_VARCHAR, 50 },
04792 { "SYSTEM", "COLPRIV", "GRANTEE", SCOL_VARCHAR, 50 },
04793 { "SYSTEM", "COLPRIV", "PRIVILEGE", SCOL_VARCHAR, 50 }
04794 };
04795
04796 #if !defined(WINTERFACE) || (defined(HAVE_UNIXODBC) && HAVE_UNIXODBC)
04797
04811 SQLRETURN SQL_API
04812 SQLColumnPrivileges(SQLHSTMT stmt,
04813 SQLCHAR *catalog, SQLSMALLINT catalogLen,
04814 SQLCHAR *schema, SQLSMALLINT schemaLen,
04815 SQLCHAR *table, SQLSMALLINT tableLen,
04816 SQLCHAR *column, SQLSMALLINT columnLen)
04817 {
04818 SQLRETURN ret;
04819
04820 HSTMT_LOCK(stmt);
04821 ret = mkresultset(stmt, colPrivSpec2, array_size(colPrivSpec2),
04822 colPrivSpec3, array_size(colPrivSpec3), NULL);
04823 HSTMT_UNLOCK(stmt);
04824 return ret;
04825 }
04826 #endif
04827
04828 #if !defined(HAVE_UNIXODBC) || !HAVE_UNIXODBC
04829 #ifdef WINTERFACE
04830
04844 SQLRETURN SQL_API
04845 SQLColumnPrivilegesW(SQLHSTMT stmt,
04846 SQLWCHAR *catalog, SQLSMALLINT catalogLen,
04847 SQLWCHAR *schema, SQLSMALLINT schemaLen,
04848 SQLWCHAR *table, SQLSMALLINT tableLen,
04849 SQLWCHAR *column, SQLSMALLINT columnLen)
04850 {
04851 SQLRETURN ret;
04852
04853 HSTMT_LOCK(stmt);
04854 ret = mkresultset(stmt, colPrivSpec2, array_size(colPrivSpec2),
04855 colPrivSpec3, array_size(colPrivSpec3), NULL);
04856 HSTMT_UNLOCK(stmt);
04857 return ret;
04858 }
04859 #endif
04860 #endif
04861
04866 static COL pkeySpec2[] = {
04867 { "SYSTEM", "PRIMARYKEY", "TABLE_QUALIFIER", SCOL_VARCHAR, 50 },
04868 { "SYSTEM", "PRIMARYKEY", "TABLE_OWNER", SCOL_VARCHAR, 50 },
04869 { "SYSTEM", "PRIMARYKEY", "TABLE_NAME", SCOL_VARCHAR, 255 },
04870 { "SYSTEM", "PRIMARYKEY", "COLUMN_NAME", SCOL_VARCHAR, 255 },
04871 { "SYSTEM", "PRIMARYKEY", "KEY_SEQ", SQL_SMALLINT, 50 },
04872 { "SYSTEM", "PRIMARYKEY", "PK_NAME", SCOL_VARCHAR, 50 }
04873 };
04874
04875 static COL pkeySpec3[] = {
04876 { "SYSTEM", "PRIMARYKEY", "TABLE_CAT", SCOL_VARCHAR, 50 },
04877 { "SYSTEM", "PRIMARYKEY", "TABLE_SCHEM", SCOL_VARCHAR, 50 },
04878 { "SYSTEM", "PRIMARYKEY", "TABLE_NAME", SCOL_VARCHAR, 255 },
04879 { "SYSTEM", "PRIMARYKEY", "COLUMN_NAME", SCOL_VARCHAR, 255 },
04880 { "SYSTEM", "PRIMARYKEY", "KEY_SEQ", SQL_SMALLINT, 50 },
04881 { "SYSTEM", "PRIMARYKEY", "PK_NAME", SCOL_VARCHAR, 50 }
04882 };
04883
04896 static SQLRETURN
04897 drvprimarykeys(SQLHSTMT stmt,
04898 SQLCHAR *cat, SQLSMALLINT catLen,
04899 SQLCHAR *schema, SQLSMALLINT schemaLen,
04900 SQLCHAR *table, SQLSMALLINT tableLen)
04901 {
04902 STMT *s;
04903 DBC *d;
04904 SQLRETURN sret;
04905 int i, asize, ret, nrows, ncols, nrows2 = 0, ncols2 = 0;
04906 int namec = -1, uniquec = -1, namec2 = -1, uniquec2 = -1, offs, seq = 1;
04907 PTRDIFF_T size;
04908 char **rowp = NULL, **rowp2 = NULL, *errp = NULL, *sql, tname[512];
04909
04910 sret = mkresultset(stmt, pkeySpec2, array_size(pkeySpec2),
04911 pkeySpec3, array_size(pkeySpec3), &asize);
04912 if (sret != SQL_SUCCESS) {
04913 return sret;
04914 }
04915 s = (STMT *) stmt;
04916 d = (DBC *) s->dbc;
04917 if (!table || table[0] == '\0' || table[0] == '%') {
04918 setstat(s, -1, "need table name", (*s->ov3) ? "HY000" : "S1000");
04919 return SQL_ERROR;
04920 }
04921 if (tableLen == SQL_NTS) {
04922 size = sizeof (tname) - 1;
04923 } else {
04924 size = min(sizeof (tname) - 1, tableLen);
04925 }
04926 strncpy(tname, (char *) table, size);
04927 tname[size] = '\0';
04928 unescpat(tname);
04929 sql = sqlite3_mprintf("PRAGMA table_info(%Q)", tname);
04930 if (!sql) {
04931 return nomem(s);
04932 }
04933 sret = starttran(s);
04934 if (sret != SQL_SUCCESS) {
04935 sqlite3_free(sql);
04936 return sret;
04937 }
04938 dbtraceapi(d, "sqlite3_get_table", sql);
04939 ret = sqlite3_get_table(d->sqlite, sql, &rowp, &nrows, &ncols, &errp);
04940 sqlite3_free(sql);
04941 if (ret != SQLITE_OK) {
04942 setstat(s, ret, "%s (%d)", (*s->ov3) ? "HY000" : "S1000",
04943 errp ? errp : "unknown error", ret);
04944 if (errp) {
04945 sqlite3_free(errp);
04946 errp = NULL;
04947 }
04948 return SQL_ERROR;
04949 }
04950 if (errp) {
04951 sqlite3_free(errp);
04952 errp = NULL;
04953 }
04954 size = 0;
04955 if (ncols * nrows > 0) {
04956 int typec;
04957
04958 namec = findcol(rowp, ncols, "name");
04959 uniquec = findcol(rowp, ncols, "pk");
04960 typec = findcol(rowp, ncols, "type");
04961 if (namec >= 0 && uniquec >= 0 && typec >= 0) {
04962 for (i = 1; i <= nrows; i++) {
04963 if (*rowp[i * ncols + uniquec] != '0') {
04964 size++;
04965 }
04966 }
04967 }
04968 }
04969 if (size == 0) {
04970 sql = sqlite3_mprintf("PRAGMA index_list(%Q)", tname);
04971 if (!sql) {
04972 sqlite3_free_table(rowp);
04973 return nomem(s);
04974 }
04975 dbtraceapi(d, "sqlite3_get_table", sql);
04976 ret = sqlite3_get_table(d->sqlite, sql, &rowp2, &nrows2, &ncols2,
04977 &errp);
04978 sqlite3_free(sql);
04979 if (ret != SQLITE_OK) {
04980 sqlite3_free_table(rowp);
04981 sqlite3_free_table(rowp2);
04982 setstat(s, ret, "%s (%d)", (*s->ov3) ? "HY000" : "S1000",
04983 errp ? errp : "unknown error", ret);
04984 if (errp) {
04985 sqlite3_free(errp);
04986 errp = NULL;
04987 }
04988 return SQL_ERROR;
04989 }
04990 if (errp) {
04991 sqlite3_free(errp);
04992 errp = NULL;
04993 }
04994 }
04995 if (ncols2 * nrows2 > 0) {
04996 namec2 = findcol(rowp2, ncols2, "name");
04997 uniquec2 = findcol(rowp2, ncols2, "unique");
04998 if (namec2 >= 0 && uniquec2 >= 0) {
04999 for (i = 1; i <= nrows2; i++) {
05000 int nnrows, nncols, nlen = 0;
05001 char **rowpp;
05002
05003 if (rowp2[i * ncols2 + namec2]) {
05004 nlen = strlen(rowp2[i * ncols2 + namec2]);
05005 }
05006 if (nlen < 17 ||
05007 strncmp(rowp2[i * ncols2 + namec2],
05008 "sqlite_autoindex_", 17)) {
05009 continue;
05010 }
05011 if (*rowp2[i * ncols2 + uniquec2] != '0') {
05012 ret = SQLITE_ERROR;
05013 sql = sqlite3_mprintf("PRAGMA index_info(%Q)",
05014 rowp2[i * ncols2 + namec2]);
05015 if (sql) {
05016 dbtraceapi(d, "sqlite3_get_table", sql);
05017 ret = sqlite3_get_table(d->sqlite, sql, &rowpp,
05018 &nnrows, &nncols, NULL);
05019 sqlite3_free(sql);
05020 }
05021 if (ret == SQLITE_OK) {
05022 size += nnrows;
05023 sqlite3_free_table(rowpp);
05024 }
05025 }
05026 }
05027 }
05028 }
05029 if (size == 0) {
05030 sqlite3_free_table(rowp);
05031 sqlite3_free_table(rowp2);
05032 return SQL_SUCCESS;
05033 }
05034 s->nrows = size;
05035 size = (size + 1) * asize;
05036 s->rows = xmalloc((size + 1) * sizeof (char *));
05037 if (!s->rows) {
05038 s->nrows = 0;
05039 sqlite3_free_table(rowp);
05040 sqlite3_free_table(rowp2);
05041 return nomem(s);
05042 }
05043 s->rows[0] = (char *) size;
05044 s->rows += 1;
05045 memset(s->rows, 0, sizeof (char *) * size);
05046 s->rowfree = freerows;
05047 offs = s->ncols;
05048 if (rowp) {
05049 for (i = 1; i <= nrows; i++) {
05050 if (*rowp[i * ncols + uniquec] != '0') {
05051 char buf[32];
05052
05053 s->rows[offs + 0] = xstrdup("");
05054 #if defined(_WIN32) || defined(_WIN64)
05055 s->rows[offs + 1] = xstrdup(d->xcelqrx ? "main" : "");
05056 #else
05057 s->rows[offs + 1] = xstrdup("");
05058 #endif
05059 s->rows[offs + 2] = xstrdup(tname);
05060 s->rows[offs + 3] = xstrdup(rowp[i * ncols + namec]);
05061 sprintf(buf, "%d", seq++);
05062 s->rows[offs + 4] = xstrdup(buf);
05063 offs += s->ncols;
05064 }
05065 }
05066 }
05067 if (rowp2) {
05068 for (i = 1; i <= nrows2; i++) {
05069 int nnrows, nncols, nlen = 0;
05070 char **rowpp;
05071
05072 if (rowp2[i * ncols2 + namec2]) {
05073 nlen = strlen(rowp2[i * ncols2 + namec2]);
05074 }
05075 if (nlen < 17 ||
05076 strncmp(rowp2[i * ncols2 + namec2], "sqlite_autoindex_", 17)) {
05077 continue;
05078 }
05079 if (*rowp2[i * ncols2 + uniquec2] != '0') {
05080 int k;
05081
05082 ret = SQLITE_ERROR;
05083 sql = sqlite3_mprintf("PRAGMA index_info(%Q)",
05084 rowp2[i * ncols2 + namec2]);
05085 if (sql) {
05086 dbtraceapi(d, "sqlite3_get_table", sql);
05087 ret = sqlite3_get_table(d->sqlite, sql, &rowpp,
05088 &nnrows, &nncols, NULL);
05089 sqlite3_free(sql);
05090 }
05091 if (ret != SQLITE_OK) {
05092 continue;
05093 }
05094 for (k = 0; nnrows && k < nncols; k++) {
05095 if (strcmp(rowpp[k], "name") == 0) {
05096 int m;
05097
05098 for (m = 1; m <= nnrows; m++) {
05099 int roffs = offs + (m - 1) * s->ncols;
05100
05101 s->rows[roffs + 0] = xstrdup("");
05102 #if defined(_WIN32) || defined(_WIN64)
05103 s->rows[roffs + 1] =
05104 xstrdup(d->xcelqrx ? "main" : "");
05105 #else
05106 s->rows[roffs + 1] = xstrdup("");
05107 #endif
05108 s->rows[roffs + 2] = xstrdup(tname);
05109 s->rows[roffs + 3] =
05110 xstrdup(rowpp[m * nncols + k]);
05111 s->rows[roffs + 5] =
05112 xstrdup(rowp2[i * ncols2 + namec2]);
05113 }
05114 } else if (strcmp(rowpp[k], "seqno") == 0) {
05115 int m;
05116
05117 for (m = 1; m <= nnrows; m++) {
05118 int roffs = offs + (m - 1) * s->ncols;
05119 int pos = m - 1;
05120 char buf[32];
05121
05122 sscanf(rowpp[m * nncols + k], "%d", &pos);
05123 sprintf(buf, "%d", pos + 1);
05124 s->rows[roffs + 4] = xstrdup(buf);
05125 }
05126 }
05127 }
05128 offs += nnrows * s->ncols;
05129 sqlite3_free_table(rowpp);
05130 }
05131 }
05132 }
05133 sqlite3_free_table(rowp);
05134 sqlite3_free_table(rowp2);
05135 return SQL_SUCCESS;
05136 }
05137
05138 #ifndef WINTERFACE
05139
05151 SQLRETURN SQL_API
05152 SQLPrimaryKeys(SQLHSTMT stmt,
05153 SQLCHAR *cat, SQLSMALLINT catLen,
05154 SQLCHAR *schema, SQLSMALLINT schemaLen,
05155 SQLCHAR *table, SQLSMALLINT tableLen)
05156 {
05157 SQLRETURN ret;
05158
05159 HSTMT_LOCK(stmt);
05160 ret = drvprimarykeys(stmt, cat, catLen, schema, schemaLen,
05161 table, tableLen);
05162 HSTMT_UNLOCK(stmt);
05163 return ret;
05164 }
05165 #endif
05166
05167 #ifdef WINTERFACE
05168
05180 SQLRETURN SQL_API
05181 SQLPrimaryKeysW(SQLHSTMT stmt,
05182 SQLWCHAR *cat, SQLSMALLINT catLen,
05183 SQLWCHAR *schema, SQLSMALLINT schemaLen,
05184 SQLWCHAR *table, SQLSMALLINT tableLen)
05185 {
05186 char *c = NULL, *s = NULL, *t = NULL;
05187 SQLRETURN ret;
05188
05189 HSTMT_LOCK(stmt);
05190 if (cat) {
05191 c = uc_to_utf_c(cat, catLen);
05192 if (!c) {
05193 ret = nomem((STMT *) stmt);
05194 goto done;
05195 }
05196 }
05197 if (schema) {
05198 s = uc_to_utf_c(schema, schemaLen);
05199 if (!s) {
05200 ret = nomem((STMT *) stmt);
05201 goto done;
05202 }
05203 }
05204 if (table) {
05205 t = uc_to_utf_c(table, tableLen);
05206 if (!t) {
05207 ret = nomem((STMT *) stmt);
05208 goto done;
05209 }
05210 }
05211 ret = drvprimarykeys(stmt, (SQLCHAR *) c, SQL_NTS,
05212 (SQLCHAR *) s, SQL_NTS, (SQLCHAR *) t, SQL_NTS);
05213 done:
05214 HSTMT_UNLOCK(stmt);
05215 uc_free(t);
05216 uc_free(s);
05217 uc_free(c);
05218 return ret;
05219 }
05220 #endif
05221
05226 static COL scolSpec2[] = {
05227 { "SYSTEM", "COLUMN", "SCOPE", SQL_SMALLINT, 1 },
05228 { "SYSTEM", "COLUMN", "COLUMN_NAME", SCOL_VARCHAR, 255 },
05229 { "SYSTEM", "COLUMN", "DATA_TYPE", SQL_SMALLINT, 50 },
05230 { "SYSTEM", "COLUMN", "TYPE_NAME", SCOL_VARCHAR, 50 },
05231 { "SYSTEM", "COLUMN", "PRECISION", SQL_INTEGER, 50 },
05232 { "SYSTEM", "COLUMN", "LENGTH", SQL_INTEGER, 50 },
05233 { "SYSTEM", "COLUMN", "DECIMAL_DIGITS", SQL_INTEGER, 50 },
05234 { "SYSTEM", "COLUMN", "PSEUDO_COLUMN", SQL_SMALLINT, 1 },
05235 { "SYSTEM", "COLUMN", "NULLABLE", SQL_SMALLINT, 1 }
05236 };
05237
05238 static COL scolSpec3[] = {
05239 { "SYSTEM", "COLUMN", "SCOPE", SQL_SMALLINT, 1 },
05240 { "SYSTEM", "COLUMN", "COLUMN_NAME", SCOL_VARCHAR, 255 },
05241 { "SYSTEM", "COLUMN", "DATA_TYPE", SQL_SMALLINT, 50 },
05242 { "SYSTEM", "COLUMN", "TYPE_NAME", SCOL_VARCHAR, 50 },
05243 { "SYSTEM", "COLUMN", "COLUMN_SIZE", SQL_INTEGER, 50 },
05244 { "SYSTEM", "COLUMN", "BUFFER_LENGTH", SQL_INTEGER, 50 },
05245 { "SYSTEM", "COLUMN", "DECIMAL_DIGITS", SQL_INTEGER, 50 },
05246 { "SYSTEM", "COLUMN", "PSEUDO_COLUMN", SQL_SMALLINT, 1 },
05247 { "SYSTEM", "COLUMN", "NULLABLE", SQL_SMALLINT, 1 }
05248 };
05249
05265 static SQLRETURN
05266 drvspecialcolumns(SQLHSTMT stmt, SQLUSMALLINT id,
05267 SQLCHAR *cat, SQLSMALLINT catLen,
05268 SQLCHAR *schema, SQLSMALLINT schemaLen,
05269 SQLCHAR *table, SQLSMALLINT tableLen,
05270 SQLUSMALLINT scope, SQLUSMALLINT nullable)
05271 {
05272 STMT *s;
05273 DBC *d;
05274 SQLRETURN sret;
05275 int i, asize, ret, nrows, ncols, nnnrows, nnncols, offs;
05276 PTRDIFF_T size;
05277 int namec = -1, uniquec = -1, namecc = -1, typecc = -1;
05278 int notnullcc = -1, mkrowid = 0;
05279 char *errp = NULL, *sql, tname[512];
05280 char **rowp = NULL, **rowppp = NULL;
05281
05282 sret = mkresultset(stmt, scolSpec2, array_size(scolSpec2),
05283 scolSpec3, array_size(scolSpec3), &asize);
05284 if (sret != SQL_SUCCESS) {
05285 return sret;
05286 }
05287 s = (STMT *) stmt;
05288 d = (DBC *) s->dbc;
05289 if (!table || table[0] == '\0' || table[0] == '%') {
05290 setstat(s, -1, "need table name", (*s->ov3) ? "HY000" : "S1000");
05291 return SQL_ERROR;
05292 }
05293 if (tableLen == SQL_NTS) {
05294 size = sizeof (tname) - 1;
05295 } else {
05296 size = min(sizeof (tname) - 1, tableLen);
05297 }
05298 strncpy(tname, (char *) table, size);
05299 tname[size] = '\0';
05300 unescpat(tname);
05301 if (id != SQL_BEST_ROWID) {
05302 return SQL_SUCCESS;
05303 }
05304 sql = sqlite3_mprintf("PRAGMA index_list(%Q)", tname);
05305 if (!sql) {
05306 return nomem(s);
05307 }
05308 sret = starttran(s);
05309 if (sret != SQL_SUCCESS) {
05310 sqlite3_free(sql);
05311 return sret;
05312 }
05313 dbtraceapi(d, "sqlite3_get_table", sql);
05314 ret = sqlite3_get_table(d->sqlite, sql, &rowp, &nrows, &ncols, &errp);
05315 sqlite3_free(sql);
05316 if (ret != SQLITE_OK) {
05317 doerr:
05318 setstat(s, ret, "%s (%d)", (*s->ov3) ? "HY000" : "S1000",
05319 errp ? errp : "unknown error", ret);
05320 if (errp) {
05321 sqlite3_free(errp);
05322 errp = NULL;
05323 }
05324 return SQL_ERROR;
05325 }
05326 if (errp) {
05327 sqlite3_free(errp);
05328 errp = NULL;
05329 }
05330 size = 0;
05331 if (ncols * nrows <= 0) {
05332 goto nodata_but_rowid;
05333 }
05334 sql = sqlite3_mprintf("PRAGMA table_info(%Q)", tname);
05335 if (!sql) {
05336 return nomem(s);
05337 }
05338 dbtraceapi(d, "sqlite3_get_table", sql);
05339 ret = sqlite3_get_table(d->sqlite, sql, &rowppp, &nnnrows, &nnncols,
05340 &errp);
05341 sqlite3_free(sql);
05342 if (ret != SQLITE_OK) {
05343 sqlite3_free_table(rowp);
05344 goto doerr;
05345 }
05346 if (errp) {
05347 sqlite3_free(errp);
05348 errp = NULL;
05349 }
05350 namec = findcol(rowp, ncols, "name");
05351 uniquec = findcol(rowp, ncols, "unique");
05352 if (namec < 0 || uniquec < 0) {
05353 goto nodata_but_rowid;
05354 }
05355 namecc = findcol(rowppp, nnncols, "name");
05356 typecc = findcol(rowppp, nnncols, "type");
05357 notnullcc = findcol(rowppp, nnncols, "notnull");
05358 for (i = 1; i <= nrows; i++) {
05359 int nnrows, nncols;
05360 char **rowpp = NULL;
05361
05362 if (*rowp[i * ncols + uniquec] != '0') {
05363 ret = SQLITE_ERROR;
05364 sql = sqlite3_mprintf("PRAGMA index_info(%Q)",
05365 rowp[i * ncols + namec]);
05366 if (sql) {
05367 dbtraceapi(d, "sqlite3_get_table", sql);
05368 ret = sqlite3_get_table(d->sqlite, sql, &rowpp,
05369 &nnrows, &nncols, NULL);
05370 sqlite3_free(sql);
05371 }
05372 if (ret == SQLITE_OK) {
05373 size += nnrows;
05374 sqlite3_free_table(rowpp);
05375 }
05376 }
05377 }
05378 nodata_but_rowid:
05379 if (size == 0) {
05380 size = 1;
05381 mkrowid = 1;
05382 }
05383 s->nrows = size;
05384 size = (size + 1) * asize;
05385 s->rows = xmalloc((size + 1) * sizeof (char *));
05386 if (!s->rows) {
05387 s->nrows = 0;
05388 sqlite3_free_table(rowp);
05389 sqlite3_free_table(rowppp);
05390 return nomem(s);
05391 }
05392 s->rows[0] = (char *) size;
05393 s->rows += 1;
05394 memset(s->rows, 0, sizeof (char *) * size);
05395 s->rowfree = freerows;
05396 if (mkrowid) {
05397 s->nrows = 0;
05398 goto mkrowid;
05399 }
05400 offs = 0;
05401 for (i = 1; i <= nrows; i++) {
05402 int nnrows, nncols;
05403 char **rowpp = NULL;
05404
05405 if (*rowp[i * ncols + uniquec] != '0') {
05406 int k;
05407
05408 ret = SQLITE_ERROR;
05409 sql = sqlite3_mprintf("PRAGMA index_info(%Q)",
05410 rowp[i * ncols + namec]);
05411 if (sql) {
05412 dbtraceapi(d, "sqlite3_get_table", sql);
05413 ret = sqlite3_get_table(d->sqlite, sql, &rowpp,
05414 &nnrows, &nncols, NULL);
05415 sqlite3_free(sql);
05416 }
05417 if (ret != SQLITE_OK) {
05418 continue;
05419 }
05420 for (k = 0; nnrows && k < nncols; k++) {
05421 if (strcmp(rowpp[k], "name") == 0) {
05422 int m;
05423
05424 for (m = 1; m <= nnrows; m++) {
05425 int roffs = (offs + m) * s->ncols;
05426
05427 s->rows[roffs + 0] =
05428 xstrdup(stringify(SQL_SCOPE_SESSION));
05429 s->rows[roffs + 1] = xstrdup(rowpp[m * nncols + k]);
05430 s->rows[roffs + 4] = xstrdup("0");
05431 s->rows[roffs + 7] =
05432 xstrdup(stringify(SQL_PC_NOT_PSEUDO));
05433 if (namecc >= 0 && typecc >= 0) {
05434 int ii;
05435
05436 for (ii = 1; ii <= nnnrows; ii++) {
05437 if (strcmp(rowppp[ii * nnncols + namecc],
05438 rowpp[m * nncols + k]) == 0) {
05439 char *typen = rowppp[ii * nnncols + typecc];
05440 int sqltype, mm, dd, isnullable = 0;
05441 char buf[32];
05442
05443 s->rows[roffs + 3] = xstrdup(typen);
05444 sqltype = mapsqltype(typen, NULL, *s->ov3,
05445 s->nowchar[0]);
05446 getmd(typen, sqltype, &mm, &dd);
05447 #ifdef SQL_LONGVARCHAR
05448 if (sqltype == SQL_VARCHAR && mm > 255) {
05449 sqltype = SQL_LONGVARCHAR;
05450 }
05451 #endif
05452 #ifdef WINTERFACE
05453 #ifdef SQL_WLONGVARCHAR
05454 if (sqltype == SQL_WVARCHAR && mm > 255) {
05455 sqltype = SQL_WLONGVARCHAR;
05456 }
05457 #endif
05458 #endif
05459 if (sqltype == SQL_VARBINARY && mm > 255) {
05460 sqltype = SQL_LONGVARBINARY;
05461 }
05462 sprintf(buf, "%d", sqltype);
05463 s->rows[roffs + 2] = xstrdup(buf);
05464 sprintf(buf, "%d", mm);
05465 s->rows[roffs + 5] = xstrdup(buf);
05466 sprintf(buf, "%d", dd);
05467 s->rows[roffs + 6] = xstrdup(buf);
05468 if (notnullcc >= 0) {
05469 char *inp =
05470 rowppp[ii * nnncols + notnullcc];
05471
05472 isnullable = inp[0] != '0';
05473 }
05474 sprintf(buf, "%d", isnullable);
05475 s->rows[roffs + 8] = xstrdup(buf);
05476 }
05477 }
05478 }
05479 }
05480 }
05481 }
05482 offs += nnrows;
05483 sqlite3_free_table(rowpp);
05484 }
05485 }
05486 if (nullable == SQL_NO_NULLS) {
05487 for (i = 1; i < s->nrows; i++) {
05488 if (s->rows[i * s->ncols + 8][0] == '0') {
05489 int m, i1 = i + 1;
05490
05491 for (m = 0; m < s->ncols; m++) {
05492 freep(&s->rows[i * s->ncols + m]);
05493 }
05494 size = s->ncols * sizeof (char *) * (s->nrows - i1);
05495 if (size > 0) {
05496 memmove(s->rows + i * s->ncols,
05497 s->rows + i1 * s->ncols,
05498 size);
05499 memset(s->rows + s->nrows * s->ncols, 0,
05500 s->ncols * sizeof (char *));
05501 }
05502 s->nrows--;
05503 --i;
05504 }
05505 }
05506 }
05507 mkrowid:
05508 sqlite3_free_table(rowp);
05509 sqlite3_free_table(rowppp);
05510 if (s->nrows == 0) {
05511 s->rows[s->ncols + 0] = xstrdup(stringify(SQL_SCOPE_SESSION));
05512 s->rows[s->ncols + 1] = xstrdup("_ROWID_");
05513 s->rows[s->ncols + 2] = xstrdup(stringify(SQL_INTEGER));
05514 s->rows[s->ncols + 3] = xstrdup("integer");
05515 s->rows[s->ncols + 4] = xstrdup("0");
05516 s->rows[s->ncols + 5] = xstrdup("10");
05517 s->rows[s->ncols + 6] = xstrdup("9");
05518 s->rows[s->ncols + 7] = xstrdup(stringify(SQL_PC_PSEUDO));
05519 s->rows[s->ncols + 8] = xstrdup(stringify(SQL_FALSE));
05520 s->nrows = 1;
05521 }
05522 return SQL_SUCCESS;
05523 }
05524
05525 #ifndef WINTERFACE
05526
05541 SQLRETURN SQL_API
05542 SQLSpecialColumns(SQLHSTMT stmt, SQLUSMALLINT id,
05543 SQLCHAR *cat, SQLSMALLINT catLen,
05544 SQLCHAR *schema, SQLSMALLINT schemaLen,
05545 SQLCHAR *table, SQLSMALLINT tableLen,
05546 SQLUSMALLINT scope, SQLUSMALLINT nullable)
05547 {
05548 SQLRETURN ret;
05549
05550 HSTMT_LOCK(stmt);
05551 ret = drvspecialcolumns(stmt, id, cat, catLen, schema, schemaLen,
05552 table, tableLen, scope, nullable);
05553 HSTMT_UNLOCK(stmt);
05554 return ret;
05555 }
05556 #endif
05557
05558 #ifdef WINTERFACE
05559
05574 SQLRETURN SQL_API
05575 SQLSpecialColumnsW(SQLHSTMT stmt, SQLUSMALLINT id,
05576 SQLWCHAR *cat, SQLSMALLINT catLen,
05577 SQLWCHAR *schema, SQLSMALLINT schemaLen,
05578 SQLWCHAR *table, SQLSMALLINT tableLen,
05579 SQLUSMALLINT scope, SQLUSMALLINT nullable)
05580 {
05581 char *c = NULL, *s = NULL, *t = NULL;
05582 SQLRETURN ret;
05583
05584 HSTMT_LOCK(stmt);
05585 if (cat) {
05586 c = uc_to_utf_c(cat, catLen);
05587 if (!c) {
05588 ret = nomem((STMT *) stmt);
05589 goto done;
05590 }
05591 }
05592 if (schema) {
05593 s = uc_to_utf_c(schema, schemaLen);
05594 if (!s) {
05595 ret = nomem((STMT *) stmt);
05596 goto done;
05597 }
05598 }
05599 if (table) {
05600 t = uc_to_utf_c(table, tableLen);
05601 if (!t) {
05602 ret = nomem((STMT *) stmt);
05603 goto done;
05604 }
05605 }
05606 ret = drvspecialcolumns(stmt, id, (SQLCHAR *) c, SQL_NTS,
05607 (SQLCHAR *) s, SQL_NTS, (SQLCHAR *) t, SQL_NTS,
05608 scope, nullable);
05609 done:
05610 HSTMT_UNLOCK(stmt);
05611 uc_free(t);
05612 uc_free(s);
05613 uc_free(c);
05614 return ret;
05615 }
05616 #endif
05617
05622 static COL fkeySpec2[] = {
05623 { "SYSTEM", "FOREIGNKEY", "PKTABLE_QUALIFIER", SCOL_VARCHAR, 50 },
05624 { "SYSTEM", "FOREIGNKEY", "PKTABLE_OWNER", SCOL_VARCHAR, 50 },
05625 { "SYSTEM", "FOREIGNKEY", "PKTABLE_NAME", SCOL_VARCHAR, 255 },
05626 { "SYSTEM", "FOREIGNKEY", "PKCOLUMN_NAME", SCOL_VARCHAR, 255 },
05627 { "SYSTEM", "FOREIGNKEY", "FKTABLE_QUALIFIER", SCOL_VARCHAR, 50 },
05628 { "SYSTEM", "FOREIGNKEY", "FKTABLE_OWNER", SCOL_VARCHAR, 50 },
05629 { "SYSTEM", "FOREIGNKEY", "FKTABLE_NAME", SCOL_VARCHAR, 255 },
05630 { "SYSTEM", "FOREIGNKEY", "FKCOLUMN_NAME", SCOL_VARCHAR, 255 },
05631 { "SYSTEM", "FOREIGNKEY", "KEY_SEQ", SQL_SMALLINT, 5 },
05632 { "SYSTEM", "FOREIGNKEY", "UPDATE_RULE", SQL_SMALLINT, 5 },
05633 { "SYSTEM", "FOREIGNKEY", "DELETE_RULE", SQL_SMALLINT, 5 },
05634 { "SYSTEM", "FOREIGNKEY", "FK_NAME", SCOL_VARCHAR, 255 },
05635 { "SYSTEM", "FOREIGNKEY", "PK_NAME", SCOL_VARCHAR, 255 },
05636 { "SYSTEM", "FOREIGNKEY", "DEFERRABILITY", SQL_SMALLINT, 5 }
05637 };
05638
05639 static COL fkeySpec3[] = {
05640 { "SYSTEM", "FOREIGNKEY", "PKTABLE_CAT", SCOL_VARCHAR, 50 },
05641 { "SYSTEM", "FOREIGNKEY", "PKTABLE_SCHEM", SCOL_VARCHAR, 50 },
05642 { "SYSTEM", "FOREIGNKEY", "PKTABLE_NAME", SCOL_VARCHAR, 255 },
05643 { "SYSTEM", "FOREIGNKEY", "PKCOLUMN_NAME", SCOL_VARCHAR, 255 },
05644 { "SYSTEM", "FOREIGNKEY", "FKTABLE_CAT", SCOL_VARCHAR, 50 },
05645 { "SYSTEM", "FOREIGNKEY", "FKTABLE_SCHEM", SCOL_VARCHAR, 50 },
05646 { "SYSTEM", "FOREIGNKEY", "FKTABLE_NAME", SCOL_VARCHAR, 255 },
05647 { "SYSTEM", "FOREIGNKEY", "FKCOLUMN_NAME", SCOL_VARCHAR, 255 },
05648 { "SYSTEM", "FOREIGNKEY", "KEY_SEQ", SQL_SMALLINT, 5 },
05649 { "SYSTEM", "FOREIGNKEY", "UPDATE_RULE", SQL_SMALLINT, 5 },
05650 { "SYSTEM", "FOREIGNKEY", "DELETE_RULE", SQL_SMALLINT, 5 },
05651 { "SYSTEM", "FOREIGNKEY", "FK_NAME", SCOL_VARCHAR, 255 },
05652 { "SYSTEM", "FOREIGNKEY", "PK_NAME", SCOL_VARCHAR, 255 },
05653 { "SYSTEM", "FOREIGNKEY", "DEFERRABILITY", SQL_SMALLINT, 5 }
05654 };
05655
05674 static SQLRETURN SQL_API
05675 drvforeignkeys(SQLHSTMT stmt,
05676 SQLCHAR *PKcatalog, SQLSMALLINT PKcatalogLen,
05677 SQLCHAR *PKschema, SQLSMALLINT PKschemaLen,
05678 SQLCHAR *PKtable, SQLSMALLINT PKtableLen,
05679 SQLCHAR *FKcatalog, SQLSMALLINT FKcatalogLen,
05680 SQLCHAR *FKschema, SQLSMALLINT FKschemaLen,
05681 SQLCHAR *FKtable, SQLSMALLINT FKtableLen)
05682 {
05683 STMT *s;
05684 DBC *d;
05685 SQLRETURN sret;
05686 int i, asize, ret, nrows, ncols, offs, namec, seqc, fromc, toc;
05687 PTRDIFF_T size;
05688 char **rowp, *errp = NULL, *sql, pname[512], fname[512];
05689
05690 sret = mkresultset(stmt, fkeySpec2, array_size(fkeySpec2),
05691 fkeySpec3, array_size(fkeySpec3), &asize);
05692 if (sret != SQL_SUCCESS) {
05693 return sret;
05694 }
05695 s = (STMT *) stmt;
05696 sret = starttran(s);
05697 if (sret != SQL_SUCCESS) {
05698 return sret;
05699 }
05700 d = (DBC *) s->dbc;
05701 if ((!PKtable || PKtable[0] == '\0' || PKtable[0] == '%') &&
05702 (!FKtable || FKtable[0] == '\0' || FKtable[0] == '%')) {
05703 setstat(s, -1, "need table name", (*s->ov3) ? "HY000" : "S1000");
05704 return SQL_ERROR;
05705 }
05706 size = 0;
05707 if (PKtable) {
05708 if (PKtableLen == SQL_NTS) {
05709 size = sizeof (pname) - 1;
05710 } else {
05711 size = min(sizeof (pname) - 1, PKtableLen);
05712 }
05713 strncpy(pname, (char *) PKtable, size);
05714 }
05715 pname[size] = '\0';
05716 size = 0;
05717 if (FKtable) {
05718
05719 if (FKtableLen == SQL_NTS) {
05720 size = sizeof (fname) - 1;
05721 } else {
05722 size = min(sizeof (fname) - 1, FKtableLen);
05723 }
05724 strncpy(fname, (char *) FKtable, size);
05725 }
05726 fname[size] = '\0';
05727 if (fname[0] != '\0') {
05728 int plen;
05729
05730 ret = SQLITE_ERROR;
05731 sql = sqlite3_mprintf("PRAGMA foreign_key_list(%Q)", fname);
05732 if (sql) {
05733 dbtraceapi(d, "sqlite3_get_table", sql);
05734 ret = sqlite3_get_table(d->sqlite, sql, &rowp,
05735 &nrows, &ncols, &errp);
05736 sqlite3_free(sql);
05737 }
05738 if (ret != SQLITE_OK) {
05739 setstat(s, ret, "%s (%d)", (*s->ov3) ? "HY000" : "S1000",
05740 errp ? errp : "unknown error", ret);
05741 if (errp) {
05742 sqlite3_free(errp);
05743 errp = NULL;
05744 }
05745 return SQL_ERROR;
05746 }
05747 if (errp) {
05748 sqlite3_free(errp);
05749 errp = NULL;
05750 }
05751 if (ncols * nrows <= 0) {
05752 nodata:
05753 sqlite3_free_table(rowp);
05754 return SQL_SUCCESS;
05755 }
05756 size = 0;
05757 namec = findcol(rowp, ncols, "table");
05758 seqc = findcol(rowp, ncols, "seq");
05759 fromc = findcol(rowp, ncols, "from");
05760 toc = findcol(rowp, ncols, "to");
05761 if (namec < 0 || seqc < 0 || fromc < 0 || toc < 0) {
05762 goto nodata;
05763 }
05764 plen = strlen(pname);
05765 for (i = 1; i <= nrows; i++) {
05766 char *ptab = unquote(rowp[i * ncols + namec]);
05767
05768 if (plen && ptab) {
05769 int len = strlen(ptab);
05770
05771 if (plen != len || strncasecmp(pname, ptab, plen) != 0) {
05772 continue;
05773 }
05774 }
05775 size++;
05776 }
05777 if (size == 0) {
05778 goto nodata;
05779 }
05780 s->nrows = size;
05781 size = (size + 1) * asize;
05782 s->rows = xmalloc((size + 1) * sizeof (char *));
05783 if (!s->rows) {
05784 s->nrows = 0;
05785 return nomem(s);
05786 }
05787 s->rows[0] = (char *) size;
05788 s->rows += 1;
05789 memset(s->rows, 0, sizeof (char *) * size);
05790 s->rowfree = freerows;
05791 offs = 0;
05792 for (i = 1; i <= nrows; i++) {
05793 int pos = 0, roffs = (offs + 1) * s->ncols;
05794 char *ptab = rowp[i * ncols + namec];
05795 char buf[32];
05796
05797 if (plen && ptab) {
05798 int len = strlen(ptab);
05799
05800 if (plen != len || strncasecmp(pname, ptab, plen) != 0) {
05801 continue;
05802 }
05803 }
05804 s->rows[roffs + 0] = xstrdup("");
05805 #if defined(_WIN32) || defined(_WIN64)
05806 s->rows[roffs + 1] = xstrdup(d->xcelqrx ? "main" : "");
05807 #else
05808 s->rows[roffs + 1] = xstrdup("");
05809 #endif
05810 s->rows[roffs + 2] = xstrdup(ptab);
05811 s->rows[roffs + 3] = xstrdup(rowp[i * ncols + toc]);
05812 s->rows[roffs + 4] = xstrdup("");
05813 s->rows[roffs + 5] = xstrdup("");
05814 s->rows[roffs + 6] = xstrdup(fname);
05815 s->rows[roffs + 7] = xstrdup(rowp[i * ncols + fromc]);
05816 sscanf(rowp[i * ncols + seqc], "%d", &pos);
05817 sprintf(buf, "%d", pos + 1);
05818 s->rows[roffs + 8] = xstrdup(buf);
05819 s->rows[roffs + 9] = xstrdup(stringify(SQL_NO_ACTION));
05820 s->rows[roffs + 10] = xstrdup(stringify(SQL_NO_ACTION));
05821 s->rows[roffs + 11] = NULL;
05822 s->rows[roffs + 12] = NULL;
05823 s->rows[roffs + 13] = xstrdup(stringify(SQL_NOT_DEFERRABLE));
05824 offs++;
05825 }
05826 sqlite3_free_table(rowp);
05827 } else {
05828 int nnrows, nncols, plen = strlen(pname);
05829 char **rowpp;
05830
05831 sql = "select name from sqlite_master where type='table'";
05832 dbtraceapi(d, "sqlite3_get_table", sql);
05833 ret = sqlite3_get_table(d->sqlite, sql, &rowp, &nrows, &ncols, &errp);
05834 if (ret != SQLITE_OK) {
05835 setstat(s, ret, "%s (%d)", (*s->ov3) ? "HY000" : "S1000",
05836 errp ? errp : "unknown error", ret);
05837 if (errp) {
05838 sqlite3_free(errp);
05839 errp = NULL;
05840 }
05841 return SQL_ERROR;
05842 }
05843 if (errp) {
05844 sqlite3_free(errp);
05845 errp = NULL;
05846 }
05847 if (ncols * nrows <= 0) {
05848 goto nodata;
05849 }
05850 size = 0;
05851 for (i = 1; i <= nrows; i++) {
05852 int k, len;
05853
05854 if (!rowp[i]) {
05855 continue;
05856 }
05857 len = strlen(rowp[i]);
05858 if (len == plen && strncasecmp(pname, rowp[i], plen) == 0) {
05859 continue;
05860 }
05861 rowpp = NULL;
05862 ret = SQLITE_ERROR;
05863 sql = sqlite3_mprintf("PRAGMA foreign_key_list(%Q)", rowp[i]);
05864 if (sql) {
05865 dbtraceapi(d, "sqlite3_get_table", sql);
05866 ret = sqlite3_get_table(d->sqlite, sql, &rowpp,
05867 &nnrows, &nncols, NULL);
05868 sqlite3_free(sql);
05869 }
05870 if (ret != SQLITE_OK || nncols * nnrows <= 0) {
05871 sqlite3_free_table(rowpp);
05872 continue;
05873 }
05874 namec = findcol(rowpp, nncols, "table");
05875 seqc = findcol(rowpp, nncols, "seq");
05876 fromc = findcol(rowpp, nncols, "from");
05877 toc = findcol(rowpp, nncols, "to");
05878 if (namec < 0 || seqc < 0 || fromc < 0 || toc < 0) {
05879 sqlite3_free_table(rowpp);
05880 continue;
05881 }
05882 for (k = 1; k <= nnrows; k++) {
05883 char *ptab = unquote(rowpp[k * nncols + namec]);
05884
05885 if (plen && ptab) {
05886 len = strlen(ptab);
05887 if (len != plen || strncasecmp(pname, ptab, plen) != 0) {
05888 continue;
05889 }
05890 }
05891 size++;
05892 }
05893 sqlite3_free_table(rowpp);
05894 }
05895 if (size == 0) {
05896 goto nodata;
05897 }
05898 s->nrows = size;
05899 size = (size + 1) * asize;
05900 s->rows = xmalloc((size + 1) * sizeof (char *));
05901 if (!s->rows) {
05902 s->nrows = 0;
05903 return nomem(s);
05904 }
05905 s->rows[0] = (char *) size;
05906 s->rows += 1;
05907 memset(s->rows, 0, sizeof (char *) * size);
05908 s->rowfree = freerows;
05909 offs = 0;
05910 for (i = 1; i <= nrows; i++) {
05911 int k, len;
05912
05913 if (!rowp[i]) {
05914 continue;
05915 }
05916 len = strlen(rowp[i]);
05917 if (len == plen && strncasecmp(pname, rowp[i], plen) == 0) {
05918 continue;
05919 }
05920 rowpp = NULL;
05921 ret = SQLITE_ERROR;
05922 sql = sqlite3_mprintf("PRAGMA foreign_key_list(%Q)", rowp[i]);
05923 if (sql) {
05924 dbtraceapi(d, "sqlite3_get_table", sql);
05925 ret = sqlite3_get_table(d->sqlite, sql, &rowpp,
05926 &nnrows, &nncols, NULL);
05927 sqlite3_free(sql);
05928 }
05929 if (ret != SQLITE_OK || nncols * nnrows <= 0) {
05930 sqlite3_free_table(rowpp);
05931 continue;
05932 }
05933 namec = findcol(rowpp, nncols, "table");
05934 seqc = findcol(rowpp, nncols, "seq");
05935 fromc = findcol(rowpp, nncols, "from");
05936 toc = findcol(rowpp, nncols, "to");
05937 if (namec < 0 || seqc < 0 || fromc < 0 || toc < 0) {
05938 sqlite3_free_table(rowpp);
05939 continue;
05940 }
05941 for (k = 1; k <= nnrows; k++) {
05942 int pos = 0, roffs = (offs + 1) * s->ncols;
05943 char *ptab = unquote(rowpp[k * nncols + namec]);
05944 char buf[32];
05945
05946 if (plen && ptab) {
05947 len = strlen(ptab);
05948 if (len != plen || strncasecmp(pname, ptab, plen) != 0) {
05949 continue;
05950 }
05951 }
05952 s->rows[roffs + 0] = xstrdup("");
05953 #if defined(_WIN32) || defined(_WIN64)
05954 s->rows[roffs + 1] = xstrdup(d->xcelqrx ? "main" : "");
05955 #else
05956 s->rows[roffs + 1] = xstrdup("");
05957 #endif
05958 s->rows[roffs + 2] = xstrdup(ptab);
05959 s->rows[roffs + 3] = xstrdup(rowpp[k * nncols + toc]);
05960 s->rows[roffs + 4] = xstrdup("");
05961 s->rows[roffs + 5] = xstrdup("");
05962 s->rows[roffs + 6] = xstrdup(rowp[i]);
05963 s->rows[roffs + 7] = xstrdup(rowpp[k * nncols + fromc]);
05964 sscanf(rowpp[k * nncols + seqc], "%d", &pos);
05965 sprintf(buf, "%d", pos + 1);
05966 s->rows[roffs + 8] = xstrdup(buf);
05967 s->rows[roffs + 9] = xstrdup(stringify(SQL_NO_ACTION));
05968 s->rows[roffs + 10] = xstrdup(stringify(SQL_NO_ACTION));
05969 s->rows[roffs + 11] = NULL;
05970 s->rows[roffs + 12] = NULL;
05971 s->rows[roffs + 13] = xstrdup(stringify(SQL_NOT_DEFERRABLE));
05972 offs++;
05973 }
05974 sqlite3_free_table(rowpp);
05975 }
05976 sqlite3_free_table(rowp);
05977 }
05978 return SQL_SUCCESS;
05979 }
05980
05981 #ifndef WINTERFACE
05982
06000 SQLRETURN SQL_API
06001 SQLForeignKeys(SQLHSTMT stmt,
06002 SQLCHAR *PKcatalog, SQLSMALLINT PKcatalogLen,
06003 SQLCHAR *PKschema, SQLSMALLINT PKschemaLen,
06004 SQLCHAR *PKtable, SQLSMALLINT PKtableLen,
06005 SQLCHAR *FKcatalog, SQLSMALLINT FKcatalogLen,
06006 SQLCHAR *FKschema, SQLSMALLINT FKschemaLen,
06007 SQLCHAR *FKtable, SQLSMALLINT FKtableLen)
06008 {
06009 SQLRETURN ret;
06010
06011 HSTMT_LOCK(stmt);
06012 ret = drvforeignkeys(stmt,
06013 PKcatalog, PKcatalogLen,
06014 PKschema, PKschemaLen, PKtable, PKtableLen,
06015 FKcatalog, FKcatalogLen,
06016 FKschema, FKschemaLen,
06017 FKtable, FKtableLen);
06018 HSTMT_UNLOCK(stmt);
06019 return ret;
06020 }
06021 #endif
06022
06023 #ifdef WINTERFACE
06024
06042 SQLRETURN SQL_API
06043 SQLForeignKeysW(SQLHSTMT stmt,
06044 SQLWCHAR *PKcatalog, SQLSMALLINT PKcatalogLen,
06045 SQLWCHAR *PKschema, SQLSMALLINT PKschemaLen,
06046 SQLWCHAR *PKtable, SQLSMALLINT PKtableLen,
06047 SQLWCHAR *FKcatalog, SQLSMALLINT FKcatalogLen,
06048 SQLWCHAR *FKschema, SQLSMALLINT FKschemaLen,
06049 SQLWCHAR *FKtable, SQLSMALLINT FKtableLen)
06050 {
06051 char *pc = NULL, *ps = NULL, *pt = NULL;
06052 char *fc = NULL, *fs = NULL, *ft = NULL;
06053 SQLRETURN ret;
06054
06055 HSTMT_LOCK(stmt);
06056 if (PKcatalog) {
06057 pc = uc_to_utf_c(PKcatalog, PKcatalogLen);
06058 if (!pc) {
06059 ret = nomem((STMT *) stmt);
06060 goto done;
06061 }
06062 }
06063 if (PKschema) {
06064 ps = uc_to_utf_c(PKschema, PKschemaLen);
06065 if (!ps) {
06066 ret = nomem((STMT *) stmt);
06067 goto done;
06068 }
06069 }
06070 if (PKtable) {
06071 pt = uc_to_utf_c(PKtable, PKtableLen);
06072 if (!pt) {
06073 ret = nomem((STMT *) stmt);
06074 goto done;
06075 }
06076 }
06077 if (FKcatalog) {
06078 fc = uc_to_utf_c(FKcatalog, FKcatalogLen);
06079 if (!fc) {
06080 ret = nomem((STMT *) stmt);
06081 goto done;
06082 }
06083 }
06084 if (FKschema) {
06085 fs = uc_to_utf_c(FKschema, FKschemaLen);
06086 if (!fs) {
06087 ret = nomem((STMT *) stmt);
06088 goto done;
06089 }
06090 }
06091 if (FKtable) {
06092 ft = uc_to_utf_c(FKtable, FKtableLen);
06093 if (!ft) {
06094 ret = nomem((STMT *) stmt);
06095 goto done;
06096 }
06097 }
06098 ret = drvforeignkeys(stmt, (SQLCHAR *) pc, SQL_NTS,
06099 (SQLCHAR *) ps, SQL_NTS, (SQLCHAR *) pt, SQL_NTS,
06100 (SQLCHAR *) fc, SQL_NTS, (SQLCHAR *) fs, SQL_NTS,
06101 (SQLCHAR *) ft, SQL_NTS);
06102 done:
06103 HSTMT_UNLOCK(stmt);
06104 uc_free(ft);
06105 uc_free(fs);
06106 uc_free(fc);
06107 uc_free(pt);
06108 uc_free(ps);
06109 uc_free(pc);
06110 return ret;
06111 }
06112 #endif
06113
06120 static SQLRETURN
06121 starttran(STMT *s)
06122 {
06123 int ret = SQL_SUCCESS, rc, busy_count = 0;
06124 char *errp = NULL;
06125 DBC *d = (DBC *) s->dbc;
06126
06127 if (!d->autocommit && !d->intrans && !d->trans_disable) {
06128 begin_again:
06129 rc = sqlite3_exec(d->sqlite, "BEGIN TRANSACTION", NULL, NULL, &errp);
06130 if (rc == SQLITE_BUSY) {
06131 if (busy_handler((void *) d, ++busy_count)) {
06132 if (errp) {
06133 sqlite3_free(errp);
06134 errp = NULL;
06135 }
06136 goto begin_again;
06137 }
06138 }
06139 dbtracerc(d, rc, errp);
06140 if (rc != SQLITE_OK) {
06141 setstat(s, rc, "%s (%d)", (*s->ov3) ? "HY000" : "S1000",
06142 errp ? errp : "unknown error", rc);
06143 ret = SQL_ERROR;
06144 } else {
06145 d->intrans = 1;
06146 }
06147 if (errp) {
06148 sqlite3_free(errp);
06149 errp = NULL;
06150 }
06151 }
06152 return ret;
06153 }
06154
06163 static SQLRETURN
06164 endtran(DBC *d, SQLSMALLINT comptype, int force)
06165 {
06166 int fail = 0, ret, busy_count = 0;
06167 char *sql, *errp = NULL;
06168
06169 if (!d->sqlite) {
06170 setstatd(d, -1, "not connected", (*d->ov3) ? "HY000" : "S1000");
06171 return SQL_ERROR;
06172 }
06173 if ((!force && d->autocommit) || !d->intrans) {
06174 return SQL_SUCCESS;
06175 }
06176 switch (comptype) {
06177 case SQL_COMMIT:
06178 sql = "COMMIT TRANSACTION";
06179 goto doit;
06180 case SQL_ROLLBACK:
06181 rollback:
06182 sql = "ROLLBACK TRANSACTION";
06183 doit:
06184 ret = sqlite3_exec(d->sqlite, sql, NULL, NULL, &errp);
06185 dbtracerc(d, ret, errp);
06186 if (ret == SQLITE_BUSY && !fail && comptype == SQL_COMMIT) {
06187 if (busy_handler((void *) d, ++busy_count)) {
06188 if (errp) {
06189 sqlite3_free(errp);
06190 errp = NULL;
06191 }
06192 goto doit;
06193 }
06194 }
06195 d->intrans = 0;
06196 if (ret != SQLITE_OK) {
06197 if (!fail) {
06198 setstatd(d, ret, "%s", (*d->ov3) ? "HY000" : "S1000",
06199 errp ? errp : "transaction failed");
06200 if (errp) {
06201 sqlite3_free(errp);
06202 errp = NULL;
06203 }
06204 fail = 1;
06205 goto rollback;
06206 }
06207 if (errp) {
06208 sqlite3_free(errp);
06209 errp = NULL;
06210 }
06211 return SQL_ERROR;
06212 }
06213 if (errp) {
06214 sqlite3_free(errp);
06215 errp = NULL;
06216 }
06217 return SQL_SUCCESS;
06218 }
06219 setstatd(d, -1, "invalid completion type", (*d->ov3) ? "HY000" : "S1000");
06220 return SQL_ERROR;
06221 }
06222
06231 static SQLRETURN
06232 drvendtran(SQLSMALLINT type, SQLHANDLE handle, SQLSMALLINT comptype)
06233 {
06234 DBC *d;
06235 int fail = 0;
06236 SQLRETURN ret;
06237 #if defined(_WIN32) || defined(_WIN64)
06238 ENV *e;
06239 #endif
06240
06241 switch (type) {
06242 case SQL_HANDLE_DBC:
06243 HDBC_LOCK((SQLHDBC) handle);
06244 if (handle == SQL_NULL_HDBC) {
06245 return SQL_INVALID_HANDLE;
06246 }
06247 d = (DBC *) handle;
06248 ret = endtran(d, comptype, 0);
06249 HDBC_UNLOCK((SQLHDBC) handle);
06250 return ret;
06251 case SQL_HANDLE_ENV:
06252 if (handle == SQL_NULL_HENV) {
06253 return SQL_INVALID_HANDLE;
06254 }
06255 #if defined(_WIN32) || defined(_WIN64)
06256 e = (ENV *) handle;
06257 if (e->magic != ENV_MAGIC) {
06258 return SQL_INVALID_HANDLE;
06259 }
06260 EnterCriticalSection(&e->cs);
06261 e->owner = GetCurrentThreadId();
06262 #endif
06263 d = ((ENV *) handle)->dbcs;
06264 while (d) {
06265 ret = endtran(d, comptype, 0);
06266 if (ret != SQL_SUCCESS) {
06267 fail++;
06268 comptype = SQL_ROLLBACK;
06269 }
06270 d = d->next;
06271 }
06272 #if defined(_WIN32) || defined(_WIN64)
06273 e->owner = 0;
06274 LeaveCriticalSection(&e->cs);
06275 #endif
06276 return fail ? SQL_ERROR : SQL_SUCCESS;
06277 }
06278 return SQL_INVALID_HANDLE;
06279 }
06280
06289 SQLRETURN SQL_API
06290 SQLEndTran(SQLSMALLINT type, SQLHANDLE handle, SQLSMALLINT comptype)
06291 {
06292 return drvendtran(type, handle, comptype);
06293 }
06294
06303 SQLRETURN SQL_API
06304 SQLTransact(SQLHENV env, SQLHDBC dbc, SQLUSMALLINT type)
06305 {
06306 if (env != SQL_NULL_HENV) {
06307 return drvendtran(SQL_HANDLE_ENV, (SQLHANDLE) env, type);
06308 }
06309 return drvendtran(SQL_HANDLE_DBC, (SQLHANDLE) dbc, type);
06310 }
06311
06316 SQLRETURN SQL_API
06317 SQLCopyDesc(SQLHDESC source, SQLHDESC target)
06318 {
06319 return SQL_ERROR;
06320 }
06321
06322 #ifndef WINTERFACE
06323
06334 SQLRETURN SQL_API
06335 SQLNativeSql(SQLHSTMT stmt, SQLCHAR *sqlin, SQLINTEGER sqlinLen,
06336 SQLCHAR *sql, SQLINTEGER sqlMax, SQLINTEGER *sqlLen)
06337 {
06338 int outLen = 0;
06339 SQLRETURN ret = SQL_SUCCESS;
06340
06341 HSTMT_LOCK(stmt);
06342 if (sqlinLen == SQL_NTS) {
06343 sqlinLen = strlen((char *) sqlin);
06344 }
06345 if (sql) {
06346 if (sqlMax > 0) {
06347 strncpy((char *) sql, (char *) sqlin, sqlMax - 1);
06348 sqlin[sqlMax - 1] = '\0';
06349 outLen = min(sqlMax - 1, sqlinLen);
06350 }
06351 } else {
06352 outLen = sqlinLen;
06353 }
06354 if (sqlLen) {
06355 *sqlLen = outLen;
06356 }
06357 if (sql && outLen < sqlinLen) {
06358 setstat((STMT *) stmt, -1, "data right truncated", "01004");
06359 ret = SQL_SUCCESS_WITH_INFO;
06360 }
06361 HSTMT_UNLOCK(stmt);
06362 return ret;
06363 }
06364 #endif
06365
06366 #ifdef WINTERFACE
06367
06378 SQLRETURN SQL_API
06379 SQLNativeSqlW(SQLHSTMT stmt, SQLWCHAR *sqlin, SQLINTEGER sqlinLen,
06380 SQLWCHAR *sql, SQLINTEGER sqlMax, SQLINTEGER *sqlLen)
06381 {
06382 int outLen = 0;
06383 SQLRETURN ret = SQL_SUCCESS;
06384
06385 HSTMT_LOCK(stmt);
06386 if (sqlinLen == SQL_NTS) {
06387 sqlinLen = uc_strlen(sqlin);
06388 }
06389 if (sql) {
06390 if (sqlMax > 0) {
06391 uc_strncpy(sql, sqlin, sqlMax - 1);
06392 sqlin[sqlMax - 1] = 0;
06393 outLen = min(sqlMax - 1, sqlinLen);
06394 }
06395 } else {
06396 outLen = sqlinLen;
06397 }
06398 if (sqlLen) {
06399 *sqlLen = outLen;
06400 }
06401 if (sql && outLen < sqlinLen) {
06402 setstat((STMT *) stmt, -1, "data right truncated", "01004");
06403 ret = SQL_SUCCESS_WITH_INFO;
06404 }
06405 HSTMT_UNLOCK(stmt);
06406 return ret;
06407 }
06408 #endif
06409
06414 static COL procSpec2[] = {
06415 { "SYSTEM", "PROCEDURE", "PROCEDURE_QUALIFIER", SCOL_VARCHAR, 50 },
06416 { "SYSTEM", "PROCEDURE", "PROCEDURE_OWNER", SCOL_VARCHAR, 50 },
06417 { "SYSTEM", "PROCEDURE", "PROCEDURE_NAME", SCOL_VARCHAR, 255 },
06418 { "SYSTEM", "PROCEDURE", "NUM_INPUT_PARAMS", SQL_SMALLINT, 5 },
06419 { "SYSTEM", "PROCEDURE", "NUM_OUTPUT_PARAMS", SQL_SMALLINT, 5 },
06420 { "SYSTEM", "PROCEDURE", "NUM_RESULT_SETS", SQL_SMALLINT, 5 },
06421 { "SYSTEM", "PROCEDURE", "REMARKS", SCOL_VARCHAR, 255 },
06422 { "SYSTEM", "PROCEDURE", "PROCEDURE_TYPE", SQL_SMALLINT, 5 }
06423 };
06424
06425 static COL procSpec3[] = {
06426 { "SYSTEM", "PROCEDURE", "PROCEDURE_CAT", SCOL_VARCHAR, 50 },
06427 { "SYSTEM", "PROCEDURE", "PROCEDURE_SCHEM", SCOL_VARCHAR, 50 },
06428 { "SYSTEM", "PROCEDURE", "PROCEDURE_NAME", SCOL_VARCHAR, 255 },
06429 { "SYSTEM", "PROCEDURE", "NUM_INPUT_PARAMS", SQL_SMALLINT, 5 },
06430 { "SYSTEM", "PROCEDURE", "NUM_OUTPUT_PARAMS", SQL_SMALLINT, 5 },
06431 { "SYSTEM", "PROCEDURE", "NUM_RESULT_SETS", SQL_SMALLINT, 5 },
06432 { "SYSTEM", "PROCEDURE", "REMARKS", SCOL_VARCHAR, 255 },
06433 { "SYSTEM", "PROCEDURE", "PROCEDURE_TYPE", SQL_SMALLINT, 5 }
06434 };
06435
06436 #ifndef WINTERFACE
06437
06449 SQLRETURN SQL_API
06450 SQLProcedures(SQLHSTMT stmt,
06451 SQLCHAR *catalog, SQLSMALLINT catalogLen,
06452 SQLCHAR *schema, SQLSMALLINT schemaLen,
06453 SQLCHAR *proc, SQLSMALLINT procLen)
06454 {
06455 SQLRETURN ret;
06456
06457 HSTMT_LOCK(stmt);
06458 ret = mkresultset(stmt, procSpec2, array_size(procSpec2),
06459 procSpec3, array_size(procSpec3), NULL);
06460 HSTMT_UNLOCK(stmt);
06461 return ret;
06462 }
06463 #endif
06464
06465 #ifdef WINTERFACE
06466
06478 SQLRETURN SQL_API
06479 SQLProceduresW(SQLHSTMT stmt,
06480 SQLWCHAR *catalog, SQLSMALLINT catalogLen,
06481 SQLWCHAR *schema, SQLSMALLINT schemaLen,
06482 SQLWCHAR *proc, SQLSMALLINT procLen)
06483 {
06484 SQLRETURN ret;
06485
06486 HSTMT_LOCK(stmt);
06487 ret = mkresultset(stmt, procSpec2, array_size(procSpec2),
06488 procSpec3, array_size(procSpec3), NULL);
06489 HSTMT_UNLOCK(stmt);
06490 return ret;
06491 }
06492 #endif
06493
06498 static COL procColSpec2[] = {
06499 { "SYSTEM", "PROCCOL", "PROCEDURE_QUALIFIER", SCOL_VARCHAR, 50 },
06500 { "SYSTEM", "PROCCOL", "PROCEDURE_OWNER", SCOL_VARCHAR, 50 },
06501 { "SYSTEM", "PROCCOL", "PROCEDURE_NAME", SCOL_VARCHAR, 255 },
06502 { "SYSTEM", "PROCCOL", "COLUMN_NAME", SCOL_VARCHAR, 255 },
06503 { "SYSTEM", "PROCCOL", "COLUMN_TYPE", SQL_SMALLINT, 5 },
06504 { "SYSTEM", "PROCCOL", "DATA_TYPE", SQL_SMALLINT, 5 },
06505 { "SYSTEM", "PROCCOL", "TYPE_NAME", SCOL_VARCHAR, 50 },
06506 { "SYSTEM", "PROCCOL", "PRECISION", SQL_INTEGER, 10 },
06507 { "SYSTEM", "PROCCOL", "LENGTH", SQL_INTEGER, 10 },
06508 { "SYSTEM", "PROCCOL", "SCALE", SQL_SMALLINT, 5 },
06509 { "SYSTEM", "PROCCOL", "RADIX", SQL_SMALLINT, 5 },
06510 { "SYSTEM", "PROCCOL", "NULLABLE", SQL_SMALLINT, 5 },
06511 { "SYSTEM", "PROCCOL", "REMARKS", SCOL_VARCHAR, 50 },
06512 { "SYSTEM", "PROCCOL", "COLUMN_DEF", SCOL_VARCHAR, 50 },
06513 { "SYSTEM", "PROCCOL", "SQL_DATA_TYPE", SQL_SMALLINT, 5 },
06514 { "SYSTEM", "PROCCOL", "SQL_DATETIME_SUB", SQL_SMALLINT, 5 },
06515 { "SYSTEM", "PROCCOL", "CHAR_OCTET_LENGTH", SQL_SMALLINT, 5 },
06516 { "SYSTEM", "PROCCOL", "ORDINAL_POSITION", SQL_SMALLINT, 5 },
06517 { "SYSTEM", "PROCCOL", "IS_NULLABLE", SCOL_VARCHAR, 50 }
06518 };
06519
06520 static COL procColSpec3[] = {
06521 { "SYSTEM", "PROCCOL", "PROCEDURE_CAT", SCOL_VARCHAR, 50 },
06522 { "SYSTEM", "PROCCOL", "PROCEDURE_SCHEM", SCOL_VARCHAR, 50 },
06523 { "SYSTEM", "PROCCOL", "PROCEDURE_NAME", SCOL_VARCHAR, 255 },
06524 { "SYSTEM", "PROCCOL", "COLUMN_NAME", SCOL_VARCHAR, 255 },
06525 { "SYSTEM", "PROCCOL", "COLUMN_TYPE", SQL_SMALLINT, 5 },
06526 { "SYSTEM", "PROCCOL", "DATA_TYPE", SQL_SMALLINT, 5 },
06527 { "SYSTEM", "PROCCOL", "TYPE_NAME", SCOL_VARCHAR, 50 },
06528 { "SYSTEM", "PROCCOL", "COLUMN_SIZE", SQL_INTEGER, 10 },
06529 { "SYSTEM", "PROCCOL", "BUFFER_LENGTH", SQL_INTEGER, 10 },
06530 { "SYSTEM", "PROCCOL", "DECIMAL_DIGITS", SQL_SMALLINT, 5 },
06531 { "SYSTEM", "PROCCOL", "NUM_PREC_RADIX", SQL_SMALLINT, 5 },
06532 { "SYSTEM", "PROCCOL", "NULLABLE", SQL_SMALLINT, 5 },
06533 { "SYSTEM", "PROCCOL", "REMARKS", SCOL_VARCHAR, 50 },
06534 { "SYSTEM", "PROCCOL", "COLUMN_DEF", SCOL_VARCHAR, 50 },
06535 { "SYSTEM", "PROCCOL", "SQL_DATA_TYPE", SQL_SMALLINT, 5 },
06536 { "SYSTEM", "PROCCOL", "SQL_DATETIME_SUB", SQL_SMALLINT, 5 },
06537 { "SYSTEM", "PROCCOL", "CHAR_OCTET_LENGTH", SQL_SMALLINT, 5 },
06538 { "SYSTEM", "PROCCOL", "ORDINAL_POSITION", SQL_SMALLINT, 5 },
06539 { "SYSTEM", "PROCCOL", "IS_NULLABLE", SCOL_VARCHAR, 50 }
06540 };
06541
06542 #ifndef WINTERFACE
06543
06557 SQLRETURN SQL_API
06558 SQLProcedureColumns(SQLHSTMT stmt,
06559 SQLCHAR *catalog, SQLSMALLINT catalogLen,
06560 SQLCHAR *schema, SQLSMALLINT schemaLen,
06561 SQLCHAR *proc, SQLSMALLINT procLen,
06562 SQLCHAR *column, SQLSMALLINT columnLen)
06563 {
06564 SQLRETURN ret;
06565
06566 HSTMT_LOCK(stmt);
06567 ret = mkresultset(stmt, procColSpec2, array_size(procColSpec2),
06568 procColSpec3, array_size(procColSpec3), NULL);
06569 HSTMT_UNLOCK(stmt);
06570 return ret;
06571 }
06572 #endif
06573
06574 #ifdef WINTERFACE
06575
06590 SQLRETURN SQL_API
06591 SQLProcedureColumnsW(SQLHSTMT stmt,
06592 SQLWCHAR *catalog, SQLSMALLINT catalogLen,
06593 SQLWCHAR *schema, SQLSMALLINT schemaLen,
06594 SQLWCHAR *proc, SQLSMALLINT procLen,
06595 SQLWCHAR *column, SQLSMALLINT columnLen)
06596 {
06597 SQLRETURN ret;
06598
06599 HSTMT_LOCK(stmt);
06600 ret = mkresultset(stmt, procColSpec2, array_size(procColSpec2),
06601 procColSpec3, array_size(procColSpec3), NULL);
06602 HSTMT_UNLOCK(stmt);
06603 return ret;
06604 }
06605 #endif
06606
06617 SQLRETURN SQL_API
06618 SQLGetEnvAttr(SQLHENV env, SQLINTEGER attr, SQLPOINTER val,
06619 SQLINTEGER len, SQLINTEGER *lenp)
06620 {
06621 ENV *e;
06622 SQLRETURN ret = SQL_ERROR;
06623
06624 if (env == SQL_NULL_HENV) {
06625 return SQL_INVALID_HANDLE;
06626 }
06627 e = (ENV *) env;
06628 if (!e || e->magic != ENV_MAGIC) {
06629 return SQL_INVALID_HANDLE;
06630 }
06631 #if defined(_WIN32) || defined(_WIN64)
06632 EnterCriticalSection(&e->cs);
06633 e->owner = GetCurrentThreadId();
06634 #endif
06635 switch (attr) {
06636 case SQL_ATTR_CONNECTION_POOLING:
06637 ret = SQL_ERROR;
06638 break;
06639 case SQL_ATTR_CP_MATCH:
06640 ret = SQL_NO_DATA;
06641 break;
06642 case SQL_ATTR_OUTPUT_NTS:
06643 if (val) {
06644 *((SQLINTEGER *) val) = SQL_TRUE;
06645 }
06646 if (lenp) {
06647 *lenp = sizeof (SQLINTEGER);
06648 }
06649 ret = SQL_SUCCESS;
06650 break;
06651 case SQL_ATTR_ODBC_VERSION:
06652 if (val) {
06653 *((SQLINTEGER *) val) = e->ov3 ? SQL_OV_ODBC3 : SQL_OV_ODBC2;
06654 }
06655 if (lenp) {
06656 *lenp = sizeof (SQLINTEGER);
06657 }
06658 ret = SQL_SUCCESS;
06659 break;
06660 }
06661 #if defined(_WIN32) || defined(_WIN64)
06662 e->owner = 0;
06663 LeaveCriticalSection(&e->cs);
06664 #endif
06665 return ret;
06666 }
06667
06677 SQLRETURN SQL_API
06678 SQLSetEnvAttr(SQLHENV env, SQLINTEGER attr, SQLPOINTER val, SQLINTEGER len)
06679 {
06680 ENV *e;
06681 SQLRETURN ret = SQL_ERROR;
06682
06683 if (env == SQL_NULL_HENV) {
06684 return SQL_INVALID_HANDLE;
06685 }
06686 e = (ENV *) env;
06687 if (!e || e->magic != ENV_MAGIC) {
06688 return SQL_INVALID_HANDLE;
06689 }
06690 #if defined(_WIN32) || defined(_WIN64)
06691 EnterCriticalSection(&e->cs);
06692 e->owner = GetCurrentThreadId();
06693 #endif
06694 switch (attr) {
06695 case SQL_ATTR_CONNECTION_POOLING:
06696 ret = SQL_SUCCESS;
06697 break;
06698 case SQL_ATTR_CP_MATCH:
06699 ret = SQL_NO_DATA;
06700 break;
06701 case SQL_ATTR_OUTPUT_NTS:
06702 if (val == (SQLPOINTER) SQL_TRUE) {
06703 ret = SQL_SUCCESS;
06704 }
06705 break;
06706 case SQL_ATTR_ODBC_VERSION:
06707 if (!val) {
06708 break;
06709 }
06710 if (val == (SQLPOINTER) SQL_OV_ODBC2) {
06711 e->ov3 = 0;
06712 ret = SQL_SUCCESS;
06713 }
06714 if (val == (SQLPOINTER) SQL_OV_ODBC3) {
06715 e->ov3 = 1;
06716 ret = SQL_SUCCESS;
06717 }
06718 break;
06719 }
06720 #if defined(_WIN32) || defined(_WIN64)
06721 e->owner = 0;
06722 LeaveCriticalSection(&e->cs);
06723 #endif
06724 return ret;
06725 }
06726
06740 static SQLRETURN
06741 drvgetdiagrec(SQLSMALLINT htype, SQLHANDLE handle, SQLSMALLINT recno,
06742 SQLCHAR *sqlstate, SQLINTEGER *nativeerr, SQLCHAR *msg,
06743 SQLSMALLINT buflen, SQLSMALLINT *msglen)
06744 {
06745 DBC *d = NULL;
06746 STMT *s = NULL;
06747 int len, naterr;
06748 char *logmsg, *sqlst;
06749 SQLRETURN ret = SQL_ERROR;
06750
06751 if (handle == SQL_NULL_HANDLE) {
06752 return SQL_INVALID_HANDLE;
06753 }
06754 if (sqlstate) {
06755 sqlstate[0] = '\0';
06756 }
06757 if (msg && buflen > 0) {
06758 msg[0] = '\0';
06759 }
06760 if (msglen) {
06761 *msglen = 0;
06762 }
06763 if (nativeerr) {
06764 *nativeerr = 0;
06765 }
06766 switch (htype) {
06767 case SQL_HANDLE_ENV:
06768 case SQL_HANDLE_DESC:
06769 return SQL_NO_DATA;
06770 case SQL_HANDLE_DBC:
06771 HDBC_LOCK((SQLHDBC) handle);
06772 d = (DBC *) handle;
06773 logmsg = (char *) d->logmsg;
06774 sqlst = d->sqlstate;
06775 naterr = d->naterr;
06776 break;
06777 case SQL_HANDLE_STMT:
06778 HSTMT_LOCK((SQLHSTMT) handle);
06779 s = (STMT *) handle;
06780 logmsg = (char *) s->logmsg;
06781 sqlst = s->sqlstate;
06782 naterr = s->naterr;
06783 break;
06784 default:
06785 return SQL_INVALID_HANDLE;
06786 }
06787 if (buflen < 0) {
06788 goto done;
06789 }
06790 if (recno > 1) {
06791 ret = SQL_NO_DATA;
06792 goto done;
06793 }
06794 len = strlen(logmsg);
06795 if (len == 0) {
06796 ret = SQL_NO_DATA;
06797 goto done;
06798 }
06799 if (nativeerr) {
06800 *nativeerr = naterr;
06801 }
06802 if (sqlstate) {
06803 strcpy((char *) sqlstate, sqlst);
06804 }
06805 if (msglen) {
06806 *msglen = len;
06807 }
06808 if (len >= buflen) {
06809 if (msg && buflen > 0) {
06810 strncpy((char *) msg, logmsg, buflen);
06811 msg[buflen - 1] = '\0';
06812 logmsg[0] = '\0';
06813 }
06814 } else if (msg) {
06815 strcpy((char *) msg, logmsg);
06816 logmsg[0] = '\0';
06817 }
06818 ret = SQL_SUCCESS;
06819 done:
06820 switch (htype) {
06821 case SQL_HANDLE_DBC:
06822 HDBC_UNLOCK((SQLHDBC) handle);
06823 break;
06824 case SQL_HANDLE_STMT:
06825 HSTMT_UNLOCK((SQLHSTMT) handle);
06826 break;
06827 }
06828 return ret;
06829 }
06830
06831 #if !defined(WINTERFACE) || (defined(HAVE_UNIXODBC) && HAVE_UNIXODBC)
06832
06845 SQLRETURN SQL_API
06846 SQLGetDiagRec(SQLSMALLINT htype, SQLHANDLE handle, SQLSMALLINT recno,
06847 SQLCHAR *sqlstate, SQLINTEGER *nativeerr, SQLCHAR *msg,
06848 SQLSMALLINT buflen, SQLSMALLINT *msglen)
06849 {
06850 return drvgetdiagrec(htype, handle, recno, sqlstate,
06851 nativeerr, msg, buflen, msglen);
06852 }
06853 #endif
06854
06855 #if !defined(HAVE_UNIXODBC) || !HAVE_UNIXODBC
06856 #ifdef WINTERFACE
06857
06871 SQLRETURN SQL_API
06872 SQLGetDiagRecW(SQLSMALLINT htype, SQLHANDLE handle, SQLSMALLINT recno,
06873 SQLWCHAR *sqlstate, SQLINTEGER *nativeerr, SQLWCHAR *msg,
06874 SQLSMALLINT buflen, SQLSMALLINT *msglen)
06875 {
06876 char state[16];
06877 SQLSMALLINT len;
06878 SQLRETURN ret;
06879
06880 ret = drvgetdiagrec(htype, handle, recno, (SQLCHAR *) state,
06881 nativeerr, (SQLCHAR *) msg, buflen, &len);
06882 if (ret == SQL_SUCCESS) {
06883 if (sqlstate) {
06884 uc_from_utf_buf((SQLCHAR *) state, -1, sqlstate,
06885 6 * sizeof (SQLWCHAR));
06886 }
06887 if (msg) {
06888 if (len > 0) {
06889 SQLWCHAR *m = NULL;
06890
06891 m = uc_from_utf((unsigned char *) msg, len);
06892 if (m) {
06893 if (buflen) {
06894 buflen /= sizeof (SQLWCHAR);
06895 uc_strncpy(msg, m, buflen);
06896 m[len] = 0;
06897 len = min(buflen, uc_strlen(m));
06898 } else {
06899 len = uc_strlen(m);
06900 }
06901 uc_free(m);
06902 } else {
06903 len = 0;
06904 }
06905 }
06906 if (len <= 0) {
06907 len = 0;
06908 if (buflen > 0) {
06909 msg[0] = 0;
06910 }
06911 }
06912 } else {
06913
06914 len *= sizeof (SQLWCHAR);
06915 }
06916 if (msglen) {
06917 *msglen = len;
06918 }
06919 } else if (ret == SQL_NO_DATA) {
06920 if (sqlstate) {
06921 sqlstate[0] = 0;
06922 }
06923 if (msg) {
06924 if (buflen > 0) {
06925 msg[0] = 0;
06926 }
06927 }
06928 if (msglen) {
06929 *msglen = 0;
06930 }
06931 }
06932 return ret;
06933 }
06934 #endif
06935 #endif
06936
06949 static SQLRETURN
06950 drvgetdiagfield(SQLSMALLINT htype, SQLHANDLE handle, SQLSMALLINT recno,
06951 SQLSMALLINT id, SQLPOINTER info,
06952 SQLSMALLINT buflen, SQLSMALLINT *stringlen)
06953 {
06954 DBC *d = NULL;
06955 STMT *s = NULL;
06956 int len, naterr;
06957 char *logmsg, *sqlst, *clrmsg = NULL;
06958 SQLRETURN ret = SQL_ERROR;
06959
06960 if (handle == SQL_NULL_HANDLE) {
06961 return SQL_INVALID_HANDLE;
06962 }
06963 if (stringlen) {
06964 *stringlen = 0;
06965 }
06966 switch (htype) {
06967 case SQL_HANDLE_ENV:
06968 case SQL_HANDLE_DESC:
06969 return SQL_NO_DATA;
06970 case SQL_HANDLE_DBC:
06971 HDBC_LOCK((SQLHDBC) handle);
06972 d = (DBC *) handle;
06973 logmsg = (char *) d->logmsg;
06974 sqlst = d->sqlstate;
06975 naterr = d->naterr;
06976 break;
06977 case SQL_HANDLE_STMT:
06978 HSTMT_LOCK((SQLHSTMT) handle);
06979 s = (STMT *) handle;
06980 d = (DBC *) s->dbc;
06981 logmsg = (char *) s->logmsg;
06982 sqlst = s->sqlstate;
06983 naterr = s->naterr;
06984 break;
06985 default:
06986 return SQL_INVALID_HANDLE;
06987 }
06988 if (buflen < 0) {
06989 goto done;
06990 }
06991 if (recno > 1) {
06992 ret = SQL_NO_DATA;
06993 goto done;
06994 }
06995 switch (id) {
06996 case SQL_DIAG_CLASS_ORIGIN:
06997 logmsg = "ISO 9075";
06998 if (sqlst[0] == 'I' && sqlst[1] == 'M') {
06999 logmsg = "ODBC 3.0";
07000 }
07001 break;
07002 case SQL_DIAG_SUBCLASS_ORIGIN:
07003 logmsg = "ISO 9075";
07004 if (sqlst[0] == 'I' && sqlst[1] == 'M') {
07005 logmsg = "ODBC 3.0";
07006 } else if (sqlst[0] == 'H' && sqlst[1] == 'Y') {
07007 logmsg = "ODBC 3.0";
07008 } else if (sqlst[0] == '2' || sqlst[0] == '0' || sqlst[0] == '4') {
07009 logmsg = "ODBC 3.0";
07010 }
07011 break;
07012 case SQL_DIAG_CONNECTION_NAME:
07013 case SQL_DIAG_SERVER_NAME:
07014 logmsg = d->dsn ? d->dsn : "No DSN";
07015 break;
07016 case SQL_DIAG_SQLSTATE:
07017 logmsg = sqlst;
07018 break;
07019 case SQL_DIAG_MESSAGE_TEXT:
07020 clrmsg = logmsg;
07021 break;
07022 case SQL_DIAG_NUMBER:
07023 naterr = 1;
07024
07025 case SQL_DIAG_NATIVE:
07026 len = strlen(logmsg);
07027 if (len == 0) {
07028 ret = SQL_NO_DATA;
07029 goto done;
07030 }
07031 if (info) {
07032 *((SQLINTEGER *) info) = naterr;
07033 }
07034 ret = SQL_SUCCESS;
07035 goto done;
07036 default:
07037 goto done;
07038 }
07039 if (info && buflen > 0) {
07040 ((char *) info)[0] = '\0';
07041 }
07042 len = strlen(logmsg);
07043 if (len == 0) {
07044 ret = SQL_NO_DATA;
07045 goto done;
07046 }
07047 if (stringlen) {
07048 *stringlen = len;
07049 }
07050 if (len >= buflen) {
07051 if (info && buflen > 0) {
07052 if (stringlen) {
07053 *stringlen = buflen - 1;
07054 }
07055 strncpy((char *) info, logmsg, buflen);
07056 ((char *) info)[buflen - 1] = '\0';
07057 }
07058 } else if (info) {
07059 strcpy((char *) info, logmsg);
07060 }
07061 if (clrmsg) {
07062 *clrmsg = '\0';
07063 }
07064 ret = SQL_SUCCESS;
07065 done:
07066 switch (htype) {
07067 case SQL_HANDLE_DBC:
07068 HDBC_UNLOCK((SQLHDBC) handle);
07069 break;
07070 case SQL_HANDLE_STMT:
07071 HSTMT_UNLOCK((SQLHSTMT) handle);
07072 break;
07073 }
07074 return ret;
07075 }
07076
07077 #ifndef WINTERFACE
07078
07090 SQLRETURN SQL_API
07091 SQLGetDiagField(SQLSMALLINT htype, SQLHANDLE handle, SQLSMALLINT recno,
07092 SQLSMALLINT id, SQLPOINTER info,
07093 SQLSMALLINT buflen, SQLSMALLINT *stringlen)
07094 {
07095 return drvgetdiagfield(htype, handle, recno, id, info, buflen, stringlen);
07096 }
07097 #endif
07098
07099 #ifdef WINTERFACE
07100
07112 SQLRETURN SQL_API
07113 SQLGetDiagFieldW(SQLSMALLINT htype, SQLHANDLE handle, SQLSMALLINT recno,
07114 SQLSMALLINT id, SQLPOINTER info,
07115 SQLSMALLINT buflen, SQLSMALLINT *stringlen)
07116 {
07117 SQLSMALLINT len;
07118 SQLRETURN ret;
07119
07120 ret = drvgetdiagfield(htype, handle, recno, id, info, buflen, &len);
07121 if (ret == SQL_SUCCESS) {
07122 if (info) {
07123 switch (id) {
07124 case SQL_DIAG_CLASS_ORIGIN:
07125 case SQL_DIAG_SUBCLASS_ORIGIN:
07126 case SQL_DIAG_CONNECTION_NAME:
07127 case SQL_DIAG_SERVER_NAME:
07128 case SQL_DIAG_SQLSTATE:
07129 case SQL_DIAG_MESSAGE_TEXT:
07130 if (len > 0) {
07131 SQLWCHAR *m = NULL;
07132
07133 m = uc_from_utf((unsigned char *) info, len);
07134 if (m) {
07135 if (buflen) {
07136 buflen /= sizeof (SQLWCHAR);
07137 uc_strncpy(info, m, buflen);
07138 m[len] = 0;
07139 len = min(buflen, uc_strlen(m));
07140 } else {
07141 len = uc_strlen(m);
07142 }
07143 uc_free(m);
07144 len *= sizeof (SQLWCHAR);
07145 } else {
07146 len = 0;
07147 }
07148 }
07149 if (len <= 0) {
07150 len = 0;
07151 if (buflen > 0) {
07152 ((SQLWCHAR *) info)[0] = 0;
07153 }
07154 }
07155 }
07156 } else {
07157 switch (id) {
07158 case SQL_DIAG_CLASS_ORIGIN:
07159 case SQL_DIAG_SUBCLASS_ORIGIN:
07160 case SQL_DIAG_CONNECTION_NAME:
07161 case SQL_DIAG_SERVER_NAME:
07162 case SQL_DIAG_SQLSTATE:
07163 case SQL_DIAG_MESSAGE_TEXT:
07164 len *= sizeof (SQLWCHAR);
07165 break;
07166 }
07167 }
07168 if (stringlen) {
07169 *stringlen = len;
07170 }
07171 }
07172 return ret;
07173 }
07174 #endif
07175
07186 static SQLRETURN
07187 drvgetstmtattr(SQLHSTMT stmt, SQLINTEGER attr, SQLPOINTER val,
07188 SQLINTEGER bufmax, SQLINTEGER *buflen)
07189 {
07190 STMT *s = (STMT *) stmt;
07191 SQLUINTEGER *uval = (SQLUINTEGER *) val;
07192
07193 switch (attr) {
07194 case SQL_QUERY_TIMEOUT:
07195 *uval = 0;
07196 return SQL_SUCCESS;
07197 case SQL_ATTR_CURSOR_TYPE:
07198 *uval = s->curtype;
07199 return SQL_SUCCESS;
07200 case SQL_ATTR_CURSOR_SCROLLABLE:
07201 *uval = (s->curtype != SQL_CURSOR_FORWARD_ONLY) ?
07202 SQL_SCROLLABLE : SQL_NONSCROLLABLE;
07203 return SQL_SUCCESS;
07204 #ifdef SQL_ATTR_CURSOR_SENSITIVITY
07205 case SQL_ATTR_CURSOR_SENSITIVITY:
07206 *uval = SQL_UNSPECIFIED;
07207 return SQL_SUCCESS;
07208 #endif
07209 case SQL_ATTR_ROW_NUMBER:
07210 if (s->s3stmt) {
07211 *uval = (s->s3stmt_rownum < 0) ?
07212 SQL_ROW_NUMBER_UNKNOWN : (s->s3stmt_rownum + 1);
07213 } else {
07214 *uval = (s->rowp < 0) ? SQL_ROW_NUMBER_UNKNOWN : (s->rowp + 1);
07215 }
07216 return SQL_SUCCESS;
07217 case SQL_ATTR_ASYNC_ENABLE:
07218 *uval = SQL_ASYNC_ENABLE_OFF;
07219 return SQL_SUCCESS;
07220 case SQL_CONCURRENCY:
07221 *uval = SQL_CONCUR_LOCK;
07222 return SQL_SUCCESS;
07223 case SQL_ATTR_RETRIEVE_DATA:
07224 *uval = s->retr_data;
07225 return SQL_SUCCESS;
07226 case SQL_ROWSET_SIZE:
07227 case SQL_ATTR_ROW_ARRAY_SIZE:
07228 *uval = s->rowset_size;
07229 return SQL_SUCCESS;
07230
07231 case SQL_ATTR_IMP_ROW_DESC:
07232 case SQL_ATTR_APP_ROW_DESC:
07233 case SQL_ATTR_IMP_PARAM_DESC:
07234 case SQL_ATTR_APP_PARAM_DESC:
07235 *((SQLHDESC *) val) = (SQLHDESC) DEAD_MAGIC;
07236 return SQL_SUCCESS;
07237 case SQL_ATTR_ROW_STATUS_PTR:
07238 *((SQLUSMALLINT **) val) = s->row_status;
07239 return SQL_SUCCESS;
07240 case SQL_ATTR_ROWS_FETCHED_PTR:
07241 *((SQLUINTEGER **) val) = s->row_count;
07242 return SQL_SUCCESS;
07243 case SQL_ATTR_USE_BOOKMARKS: {
07244 STMT *s = (STMT *) stmt;
07245
07246 *(SQLUINTEGER *) val = s->bkmrk ? SQL_UB_ON : SQL_UB_OFF;
07247 return SQL_SUCCESS;
07248 }
07249 case SQL_ATTR_PARAM_BIND_OFFSET_PTR:
07250 *((SQLUINTEGER **) val) = s->parm_bind_offs;
07251 return SQL_SUCCESS;
07252 case SQL_ATTR_PARAM_BIND_TYPE:
07253 *((SQLUINTEGER *) val) = s->parm_bind_type;
07254 return SQL_SUCCESS;
07255 case SQL_ATTR_PARAM_OPERATION_PTR:
07256 *((SQLUSMALLINT **) val) = s->parm_oper;
07257 return SQL_SUCCESS;
07258 case SQL_ATTR_PARAM_STATUS_PTR:
07259 *((SQLUSMALLINT **) val) = s->parm_status;
07260 return SQL_SUCCESS;
07261 case SQL_ATTR_PARAMS_PROCESSED_PTR:
07262 *((SQLUINTEGER **) val) = s->parm_proc;
07263 return SQL_SUCCESS;
07264 case SQL_ATTR_PARAMSET_SIZE:
07265 *((SQLUINTEGER *) val) = s->paramset_size;
07266 return SQL_SUCCESS;
07267 case SQL_ATTR_ROW_BIND_TYPE:
07268 *(SQLUINTEGER *) val = s->bind_type;
07269 return SQL_SUCCESS;
07270 case SQL_ATTR_ROW_BIND_OFFSET_PTR:
07271 *((SQLUINTEGER **) val) = s->bind_offs;
07272 return SQL_SUCCESS;
07273 case SQL_ATTR_MAX_ROWS:
07274 *((SQLUINTEGER *) val) = s->max_rows;
07275 case SQL_ATTR_MAX_LENGTH:
07276 *((SQLINTEGER *) val) = 1000000000;
07277 return SQL_SUCCESS;
07278 }
07279 return drvunimplstmt(stmt);
07280 }
07281
07282 #if (defined(HAVE_UNIXODBC) && HAVE_UNIXODBC) || !defined(WINTERFACE)
07283
07293 SQLRETURN SQL_API
07294 SQLGetStmtAttr(SQLHSTMT stmt, SQLINTEGER attr, SQLPOINTER val,
07295 SQLINTEGER bufmax, SQLINTEGER *buflen)
07296 {
07297 SQLRETURN ret;
07298
07299 HSTMT_LOCK(stmt);
07300 ret = drvgetstmtattr(stmt, attr, val, bufmax, buflen);
07301 HSTMT_UNLOCK(stmt);
07302 return ret;
07303 }
07304 #endif
07305
07306 #ifdef WINTERFACE
07307
07317 SQLRETURN SQL_API
07318 SQLGetStmtAttrW(SQLHSTMT stmt, SQLINTEGER attr, SQLPOINTER val,
07319 SQLINTEGER bufmax, SQLINTEGER *buflen)
07320 {
07321 SQLRETURN ret;
07322
07323 HSTMT_LOCK(stmt);
07324 ret = drvgetstmtattr(stmt, attr, val, bufmax, buflen);
07325 HSTMT_UNLOCK(stmt);
07326 return ret;
07327 }
07328 #endif
07329
07339 static SQLRETURN
07340 drvsetstmtattr(SQLHSTMT stmt, SQLINTEGER attr, SQLPOINTER val,
07341 SQLINTEGER buflen)
07342 {
07343 STMT *s = (STMT *) stmt;
07344
07345 switch (attr) {
07346 case SQL_ATTR_CURSOR_TYPE:
07347 if (val == (SQLPOINTER) SQL_CURSOR_FORWARD_ONLY) {
07348 s->curtype = SQL_CURSOR_FORWARD_ONLY;
07349 } else {
07350 s->curtype = SQL_CURSOR_STATIC;
07351 }
07352 if (val != (SQLPOINTER) SQL_CURSOR_FORWARD_ONLY &&
07353 val != (SQLPOINTER) SQL_CURSOR_STATIC) {
07354 goto e01s02;
07355 }
07356 return SQL_SUCCESS;
07357 case SQL_ATTR_CURSOR_SCROLLABLE:
07358 if (val == (SQLPOINTER) SQL_NONSCROLLABLE) {
07359 s->curtype = SQL_CURSOR_FORWARD_ONLY;
07360 } else {
07361 s->curtype = SQL_CURSOR_STATIC;
07362 }
07363 return SQL_SUCCESS;
07364 case SQL_ATTR_ASYNC_ENABLE:
07365 if (val != (SQLPOINTER) SQL_ASYNC_ENABLE_OFF) {
07366 e01s02:
07367 setstat(s, -1, "option value changed", "01S02");
07368 return SQL_SUCCESS_WITH_INFO;
07369 }
07370 return SQL_SUCCESS;
07371 case SQL_CONCURRENCY:
07372 if (val != (SQLPOINTER) SQL_CONCUR_LOCK) {
07373 goto e01s02;
07374 }
07375 return SQL_SUCCESS;
07376 #ifdef SQL_ATTR_CURSOR_SENSITIVITY
07377 case SQL_ATTR_CURSOR_SENSITIVITY:
07378 if (val != (SQLPOINTER) SQL_UNSPECIFIED) {
07379 goto e01s02;
07380 }
07381 return SQL_SUCCESS;
07382 #endif
07383 case SQL_ATTR_QUERY_TIMEOUT:
07384 return SQL_SUCCESS;
07385 case SQL_ATTR_RETRIEVE_DATA:
07386 if (val != (SQLPOINTER) SQL_RD_ON &&
07387 val != (SQLPOINTER) SQL_RD_OFF) {
07388 goto e01s02;
07389 }
07390 s->retr_data = (PTRDIFF_T) val;
07391 return SQL_SUCCESS;
07392 case SQL_ROWSET_SIZE:
07393 case SQL_ATTR_ROW_ARRAY_SIZE:
07394 if ((PTRDIFF_T) val < 1) {
07395 setstat(s, -1, "invalid rowset size", "HY000");
07396 return SQL_ERROR;
07397 } else {
07398 SQLUSMALLINT *rst = &s->row_status1;
07399
07400 if ((PTRDIFF_T) val > 1) {
07401 rst = xmalloc(sizeof (SQLUSMALLINT) * (PTRDIFF_T) val);
07402 if (!rst) {
07403 return nomem(s);
07404 }
07405 }
07406 if (s->row_status0 != &s->row_status1) {
07407 freep(&s->row_status0);
07408 }
07409 s->row_status0 = rst;
07410 s->rowset_size = (PTRDIFF_T) val;
07411 }
07412 return SQL_SUCCESS;
07413 case SQL_ATTR_ROW_STATUS_PTR:
07414 s->row_status = (SQLUSMALLINT *) val;
07415 return SQL_SUCCESS;
07416 case SQL_ATTR_ROWS_FETCHED_PTR:
07417 s->row_count = (SQLUINTEGER *) val;
07418 return SQL_SUCCESS;
07419 case SQL_ATTR_PARAM_BIND_OFFSET_PTR:
07420 s->parm_bind_offs = (SQLUINTEGER *) val;
07421 return SQL_SUCCESS;
07422 case SQL_ATTR_PARAM_BIND_TYPE:
07423 s->parm_bind_type = (PTRDIFF_T) val;
07424 return SQL_SUCCESS;
07425 case SQL_ATTR_PARAM_OPERATION_PTR:
07426 s->parm_oper = (SQLUSMALLINT *) val;
07427 return SQL_SUCCESS;
07428 case SQL_ATTR_PARAM_STATUS_PTR:
07429 s->parm_status = (SQLUSMALLINT *) val;
07430 return SQL_SUCCESS;
07431 case SQL_ATTR_PARAMS_PROCESSED_PTR:
07432 s->parm_proc = (SQLUINTEGER *) val;
07433 return SQL_SUCCESS;
07434 case SQL_ATTR_PARAMSET_SIZE:
07435 if ((PTRDIFF_T) val < 1) {
07436 goto e01s02;
07437 }
07438 s->paramset_size = (PTRDIFF_T) val;
07439 s->paramset_count = 0;
07440 return SQL_SUCCESS;
07441 case SQL_ATTR_ROW_BIND_TYPE:
07442 s->bind_type = (PTRDIFF_T) val;
07443 return SQL_SUCCESS;
07444 case SQL_ATTR_ROW_BIND_OFFSET_PTR:
07445 s->bind_offs = (SQLUINTEGER *) val;
07446 return SQL_SUCCESS;
07447 case SQL_ATTR_USE_BOOKMARKS:
07448 if (val != (SQLPOINTER) SQL_UB_OFF &&
07449 val != (SQLPOINTER) SQL_UB_ON) {
07450 goto e01s02;
07451 }
07452 s->bkmrk = val == (SQLPOINTER) SQL_UB_ON;
07453 return SQL_SUCCESS;
07454 case SQL_ATTR_MAX_ROWS:
07455 s->max_rows = (PTRDIFF_T) val;
07456 return SQL_SUCCESS;
07457 case SQL_ATTR_MAX_LENGTH:
07458 if (val != (SQLPOINTER) 1000000000) {
07459 goto e01s02;
07460 }
07461 return SQL_SUCCESS;
07462 }
07463 return drvunimplstmt(stmt);
07464 }
07465
07466 #if (defined(HAVE_UNIXODBC) && HAVE_UNIXODBC) || !defined(WINTERFACE)
07467
07476 SQLRETURN SQL_API
07477 SQLSetStmtAttr(SQLHSTMT stmt, SQLINTEGER attr, SQLPOINTER val,
07478 SQLINTEGER buflen)
07479 {
07480 SQLRETURN ret;
07481
07482 HSTMT_LOCK(stmt);
07483 ret = drvsetstmtattr(stmt, attr, val, buflen);
07484 HSTMT_UNLOCK(stmt);
07485 return ret;
07486 }
07487 #endif
07488
07489 #ifdef WINTERFACE
07490
07499 SQLRETURN SQL_API
07500 SQLSetStmtAttrW(SQLHSTMT stmt, SQLINTEGER attr, SQLPOINTER val,
07501 SQLINTEGER buflen)
07502 {
07503 SQLRETURN ret;
07504
07505 HSTMT_LOCK(stmt);
07506 ret = drvsetstmtattr(stmt, attr, val, buflen);
07507 HSTMT_UNLOCK(stmt);
07508 return ret;
07509 }
07510 #endif
07511
07520 static SQLRETURN
07521 drvgetstmtoption(SQLHSTMT stmt, SQLUSMALLINT opt, SQLPOINTER param)
07522 {
07523 STMT *s = (STMT *) stmt;
07524 SQLUINTEGER *ret = (SQLUINTEGER *) param;
07525
07526 switch (opt) {
07527 case SQL_QUERY_TIMEOUT:
07528 *ret = 0;
07529 return SQL_SUCCESS;
07530 case SQL_CURSOR_TYPE:
07531 *ret = s->curtype;
07532 return SQL_SUCCESS;
07533 case SQL_ROW_NUMBER:
07534 if (s->s3stmt) {
07535 *ret = (s->s3stmt_rownum < 0) ?
07536 SQL_ROW_NUMBER_UNKNOWN : (s->s3stmt_rownum + 1);
07537 } else {
07538 *ret = (s->rowp < 0) ? SQL_ROW_NUMBER_UNKNOWN : (s->rowp + 1);
07539 }
07540 return SQL_SUCCESS;
07541 case SQL_ASYNC_ENABLE:
07542 *ret = SQL_ASYNC_ENABLE_OFF;
07543 return SQL_SUCCESS;
07544 case SQL_CONCURRENCY:
07545 *ret = SQL_CONCUR_LOCK;
07546 return SQL_SUCCESS;
07547 case SQL_ATTR_RETRIEVE_DATA:
07548 *ret = s->retr_data;
07549 return SQL_SUCCESS;
07550 case SQL_ROWSET_SIZE:
07551 case SQL_ATTR_ROW_ARRAY_SIZE:
07552 *ret = s->rowset_size;
07553 return SQL_SUCCESS;
07554 case SQL_ATTR_MAX_ROWS:
07555 *ret = s->max_rows;
07556 return SQL_SUCCESS;
07557 case SQL_ATTR_MAX_LENGTH:
07558 *ret = 1000000000;
07559 return SQL_SUCCESS;
07560 }
07561 return drvunimplstmt(stmt);
07562 }
07563
07572 SQLRETURN SQL_API
07573 SQLGetStmtOption(SQLHSTMT stmt, SQLUSMALLINT opt, SQLPOINTER param)
07574 {
07575 SQLRETURN ret;
07576
07577 HSTMT_LOCK(stmt);
07578 ret = drvgetstmtoption(stmt, opt, param);
07579 HSTMT_UNLOCK(stmt);
07580 return ret;
07581 }
07582
07583 #ifdef WINTERFACE
07584
07592 SQLRETURN SQL_API
07593 SQLGetStmtOptionW(SQLHSTMT stmt, SQLUSMALLINT opt, SQLPOINTER param)
07594 {
07595 SQLRETURN ret;
07596
07597 HSTMT_LOCK(stmt);
07598 ret = drvgetstmtoption(stmt, opt, param);
07599 HSTMT_UNLOCK(stmt);
07600 return ret;
07601 }
07602 #endif
07603
07612 static SQLRETURN
07613 drvsetstmtoption(SQLHSTMT stmt, SQLUSMALLINT opt, SQLUINTEGER param)
07614 {
07615 STMT *s = (STMT *) stmt;
07616
07617 switch (opt) {
07618 case SQL_CURSOR_TYPE:
07619 if (param == SQL_CURSOR_FORWARD_ONLY) {
07620 s->curtype = param;
07621 } else {
07622 s->curtype = SQL_CURSOR_STATIC;
07623 }
07624 if (param != SQL_CURSOR_FORWARD_ONLY &&
07625 param != SQL_CURSOR_STATIC) {
07626 goto e01s02;
07627 }
07628 return SQL_SUCCESS;
07629 case SQL_ASYNC_ENABLE:
07630 if (param != SQL_ASYNC_ENABLE_OFF) {
07631 goto e01s02;
07632 }
07633 return SQL_SUCCESS;
07634 case SQL_CONCURRENCY:
07635 if (param != SQL_CONCUR_LOCK) {
07636 goto e01s02;
07637 }
07638 return SQL_SUCCESS;
07639 case SQL_QUERY_TIMEOUT:
07640 return SQL_SUCCESS;
07641 case SQL_RETRIEVE_DATA:
07642 if (param != SQL_RD_ON && param != SQL_RD_OFF) {
07643 e01s02:
07644 setstat(s, -1, "option value changed", "01S02");
07645 return SQL_SUCCESS_WITH_INFO;
07646 }
07647 s->retr_data = (int) param;
07648 return SQL_SUCCESS;
07649 case SQL_ROWSET_SIZE:
07650 case SQL_ATTR_ROW_ARRAY_SIZE:
07651 if (param < 1) {
07652 setstat(s, -1, "invalid rowset size", "HY000");
07653 return SQL_ERROR;
07654 } else {
07655 SQLUSMALLINT *rst = &s->row_status1;
07656
07657 if (param > 1) {
07658 rst = xmalloc(sizeof (SQLUSMALLINT) * param);
07659 if (!rst) {
07660 return nomem(s);
07661 }
07662 }
07663 if (s->row_status0 != &s->row_status1) {
07664 freep(&s->row_status0);
07665 }
07666 s->row_status0 = rst;
07667 s->rowset_size = param;
07668 }
07669 return SQL_SUCCESS;
07670 case SQL_ATTR_MAX_ROWS:
07671 s->max_rows = param;
07672 return SQL_SUCCESS;
07673 case SQL_ATTR_MAX_LENGTH:
07674 if (param != 1000000000) {
07675 goto e01s02;
07676 }
07677 return SQL_SUCCESS;
07678 }
07679 return drvunimplstmt(stmt);
07680 }
07681
07690 SQLRETURN SQL_API
07691 SQLSetStmtOption(SQLHSTMT stmt, SQLUSMALLINT opt,
07692 SETSTMTOPTION_LAST_ARG_TYPE param)
07693 {
07694 SQLRETURN ret;
07695
07696 HSTMT_LOCK(stmt);
07697 ret = drvsetstmtoption(stmt, opt, (SQLUINTEGER) param);
07698 HSTMT_UNLOCK(stmt);
07699 return ret;
07700 }
07701
07702 #ifdef WINTERFACE
07703
07711 SQLRETURN SQL_API
07712 SQLSetStmtOptionW(SQLHSTMT stmt, SQLUSMALLINT opt,
07713 SETSTMTOPTION_LAST_ARG_TYPE param)
07714 {
07715 SQLRETURN ret;
07716
07717 HSTMT_LOCK(stmt);
07718 ret = drvsetstmtoption(stmt, opt, (SQLUINTEGER) param);
07719 HSTMT_UNLOCK(stmt);
07720 return ret;
07721 }
07722 #endif
07723
07733 static SQLRETURN
07734 drvsetpos(SQLHSTMT stmt, SQLSETPOSIROW row, SQLUSMALLINT op, SQLUSMALLINT lock)
07735 {
07736 STMT *s = (STMT *) stmt;
07737
07738 if (op != SQL_POSITION) {
07739 return drvunimplstmt(stmt);
07740 }
07741 if (!s->rows || row <= 0 || row > s->nrows) {
07742 setstat(s, -1, "row out of range", (*s->ov3) ? "HY107" : "S1107");
07743 return SQL_ERROR;
07744 }
07745 s->rowp = row - 1;
07746 return SQL_SUCCESS;
07747 }
07748
07758 SQLRETURN SQL_API
07759 SQLSetPos(SQLHSTMT stmt, SQLSETPOSIROW row, SQLUSMALLINT op, SQLUSMALLINT lock)
07760 {
07761 SQLRETURN ret;
07762
07763 HSTMT_LOCK(stmt);
07764 ret = drvsetpos(stmt, row, op, lock);
07765 HSTMT_UNLOCK(stmt);
07766 return ret;
07767 }
07768
07773 SQLRETURN SQL_API
07774 SQLSetScrollOptions(SQLHSTMT stmt, SQLUSMALLINT concur, SQLLEN rowkeyset,
07775 SQLUSMALLINT rowset)
07776 {
07777 SQLRETURN ret;
07778
07779 HSTMT_LOCK(stmt);
07780 ret = drvunimplstmt(stmt);
07781 HSTMT_UNLOCK(stmt);
07782 return ret;
07783 }
07784
07785 #define strmak(dst, src, max, lenp) { \
07786 int len = strlen(src); \
07787 int cnt = min(len + 1, max); \
07788 strncpy(dst, src, cnt); \
07789 *lenp = (cnt > len) ? len : cnt; \
07790 }
07791
07802 static SQLRETURN
07803 drvgetinfo(SQLHDBC dbc, SQLUSMALLINT type, SQLPOINTER val, SQLSMALLINT valMax,
07804 SQLSMALLINT *valLen)
07805 {
07806 DBC *d;
07807 char dummyc[16];
07808 SQLSMALLINT dummy;
07809 #if defined(_WIN32) || defined(_WIN64)
07810 char drvname[301];
07811 #else
07812 static char drvname[] = "sqlite3odbc.so";
07813 #endif
07814
07815 if (dbc == SQL_NULL_HDBC) {
07816 return SQL_INVALID_HANDLE;
07817 }
07818 d = (DBC *) dbc;
07819 if (valMax) {
07820 valMax--;
07821 }
07822 if (!valLen) {
07823 valLen = &dummy;
07824 }
07825 if (!val) {
07826 val = dummyc;
07827 valMax = sizeof (dummyc) - 1;
07828 }
07829 switch (type) {
07830 case SQL_MAX_USER_NAME_LEN:
07831 *((SQLSMALLINT *) val) = 16;
07832 *valLen = sizeof (SQLSMALLINT);
07833 break;
07834 case SQL_USER_NAME:
07835 strmak(val, "", valMax, valLen);
07836 break;
07837 case SQL_DRIVER_ODBC_VER:
07838 #if 0
07839 strmak(val, (*d->ov3) ? "03.00" : "02.50", valMax, valLen);
07840 #else
07841 strmak(val, "03.00", valMax, valLen);
07842 #endif
07843 break;
07844 case SQL_ACTIVE_CONNECTIONS:
07845 case SQL_ACTIVE_STATEMENTS:
07846 *((SQLSMALLINT *) val) = 0;
07847 *valLen = sizeof (SQLSMALLINT);
07848 break;
07849 #ifdef SQL_ASYNC_MODE
07850 case SQL_ASYNC_MODE:
07851 *((SQLUINTEGER *) val) = SQL_AM_NONE;
07852 *valLen = sizeof (SQLUINTEGER);
07853 break;
07854 #endif
07855 #ifdef SQL_CREATE_TABLE
07856 case SQL_CREATE_TABLE:
07857 *((SQLUINTEGER *) val) = SQL_CT_CREATE_TABLE |
07858 SQL_CT_COLUMN_DEFAULT |
07859 SQL_CT_COLUMN_CONSTRAINT |
07860 SQL_CT_CONSTRAINT_NON_DEFERRABLE;
07861 *valLen = sizeof (SQLUINTEGER);
07862 break;
07863 #endif
07864 #ifdef SQL_CREATE_VIEW
07865 case SQL_CREATE_VIEW:
07866 *((SQLUINTEGER *) val) = SQL_CV_CREATE_VIEW;
07867 *valLen = sizeof (SQLUINTEGER);
07868 break;
07869 #endif
07870 #ifdef SQL_DDL_INDEX
07871 case SQL_DDL_INDEX:
07872 *((SQLUINTEGER *) val) = SQL_DI_CREATE_INDEX | SQL_DI_DROP_INDEX;
07873 *valLen = sizeof (SQLUINTEGER);
07874 break;
07875 #endif
07876 #ifdef SQL_DROP_TABLE
07877 case SQL_DROP_TABLE:
07878 *((SQLUINTEGER *) val) = SQL_DT_DROP_TABLE;
07879 *valLen = sizeof (SQLUINTEGER);
07880 break;
07881 #endif
07882 #ifdef SQL_DROP_VIEW
07883 case SQL_DROP_VIEW:
07884 *((SQLUINTEGER *) val) = SQL_DV_DROP_VIEW;
07885 *valLen = sizeof (SQLUINTEGER);
07886 break;
07887 #endif
07888 #ifdef SQL_INDEX_KEYWORDS
07889 case SQL_INDEX_KEYWORDS:
07890 *((SQLUINTEGER *) val) = SQL_IK_ALL;
07891 *valLen = sizeof (SQLUINTEGER);
07892 break;
07893 #endif
07894 case SQL_DATA_SOURCE_NAME:
07895 strmak(val, d->dsn ? d->dsn : "", valMax, valLen);
07896 break;
07897 case SQL_DRIVER_NAME:
07898 #if defined(_WIN32) || defined(_WIN64)
07899 GetModuleFileName(hModule, drvname, sizeof (drvname));
07900 #endif
07901 strmak(val, drvname, valMax, valLen);
07902 break;
07903 case SQL_DRIVER_VER:
07904 strmak(val, DRIVER_VER_INFO, valMax, valLen);
07905 break;
07906 case SQL_FETCH_DIRECTION:
07907 *((SQLUINTEGER *) val) = SQL_FD_FETCH_NEXT | SQL_FD_FETCH_FIRST |
07908 SQL_FD_FETCH_LAST | SQL_FD_FETCH_PRIOR | SQL_FD_FETCH_ABSOLUTE;
07909 *valLen = sizeof (SQLUINTEGER);
07910 break;
07911 case SQL_ODBC_VER:
07912 strmak(val, (*d->ov3) ? "03.00" : "02.50", valMax, valLen);
07913 break;
07914 case SQL_ODBC_SAG_CLI_CONFORMANCE:
07915 *((SQLSMALLINT *) val) = SQL_OSCC_NOT_COMPLIANT;
07916 *valLen = sizeof (SQLSMALLINT);
07917 break;
07918 case SQL_STANDARD_CLI_CONFORMANCE:
07919 *((SQLUINTEGER *) val) = SQL_SCC_XOPEN_CLI_VERSION1;
07920 *valLen = sizeof (SQLUINTEGER);
07921 break;
07922 case SQL_SERVER_NAME:
07923 case SQL_DATABASE_NAME:
07924 strmak(val, d->dbname ? d->dbname : "", valMax, valLen);
07925 break;
07926 case SQL_SEARCH_PATTERN_ESCAPE:
07927 strmak(val, "\\", valMax, valLen);
07928 break;
07929 case SQL_ODBC_SQL_CONFORMANCE:
07930 *((SQLSMALLINT *) val) = SQL_OSC_MINIMUM;
07931 *valLen = sizeof (SQLSMALLINT);
07932 break;
07933 case SQL_ODBC_API_CONFORMANCE:
07934 *((SQLSMALLINT *) val) = SQL_OAC_LEVEL1;
07935 *valLen = sizeof (SQLSMALLINT);
07936 break;
07937 case SQL_DBMS_NAME:
07938 strmak(val, "SQLite", valMax, valLen);
07939 break;
07940 case SQL_DBMS_VER:
07941 strmak(val, SQLITE_VERSION, valMax, valLen);
07942 break;
07943 case SQL_COLUMN_ALIAS:
07944 case SQL_NEED_LONG_DATA_LEN:
07945 strmak(val, "Y", valMax, valLen);
07946 break;
07947 case SQL_ROW_UPDATES:
07948 case SQL_ACCESSIBLE_PROCEDURES:
07949 case SQL_PROCEDURES:
07950 case SQL_EXPRESSIONS_IN_ORDERBY:
07951 case SQL_ODBC_SQL_OPT_IEF:
07952 case SQL_LIKE_ESCAPE_CLAUSE:
07953 case SQL_ORDER_BY_COLUMNS_IN_SELECT:
07954 case SQL_OUTER_JOINS:
07955 case SQL_ACCESSIBLE_TABLES:
07956 case SQL_MULT_RESULT_SETS:
07957 case SQL_MULTIPLE_ACTIVE_TXN:
07958 case SQL_MAX_ROW_SIZE_INCLUDES_LONG:
07959 strmak(val, "N", valMax, valLen);
07960 break;
07961 #ifdef SQL_CATALOG_NAME
07962 case SQL_CATALOG_NAME:
07963 #if defined(_WIN32) || defined(_WIN64)
07964 strmak(val, d->xcelqrx ? "Y" : "N", valMax, valLen);
07965 #else
07966 strmak(val, "N", valMax, valLen);
07967 #endif
07968 break;
07969 #endif
07970 case SQL_DATA_SOURCE_READ_ONLY:
07971 strmak(val, "N", valMax, valLen);
07972 break;
07973 #ifdef SQL_OJ_CAPABILITIES
07974 case SQL_OJ_CAPABILITIES:
07975 *((SQLUINTEGER *) val) = 0;
07976 *valLen = sizeof (SQLUINTEGER);
07977 break;
07978 #endif
07979 #ifdef SQL_MAX_IDENTIFIER_LEN
07980 case SQL_MAX_IDENTIFIER_LEN:
07981 *((SQLUSMALLINT *) val) = 255;
07982 *valLen = sizeof (SQLUSMALLINT);
07983 break;
07984 #endif
07985 case SQL_CONCAT_NULL_BEHAVIOR:
07986 *((SQLSMALLINT *) val) = SQL_CB_NULL;
07987 *valLen = sizeof (SQLSMALLINT);
07988 break;
07989 case SQL_CURSOR_COMMIT_BEHAVIOR:
07990 case SQL_CURSOR_ROLLBACK_BEHAVIOR:
07991 *((SQLSMALLINT *) val) = SQL_CB_PRESERVE;
07992 *valLen = sizeof (SQLSMALLINT);
07993 break;
07994 #ifdef SQL_CURSOR_SENSITIVITY
07995 case SQL_CURSOR_SENSITIVITY:
07996 *((SQLUINTEGER *) val) = SQL_UNSPECIFIED;
07997 *valLen = sizeof (SQLUINTEGER);
07998 break;
07999 #endif
08000 case SQL_DEFAULT_TXN_ISOLATION:
08001 *((SQLUINTEGER *) val) = SQL_TXN_SERIALIZABLE;
08002 *valLen = sizeof (SQLUINTEGER);
08003 break;
08004 #ifdef SQL_DESCRIBE_PARAMETER
08005 case SQL_DESCRIBE_PARAMETER:
08006 strmak(val, "Y", valMax, valLen);
08007 break;
08008 #endif
08009 case SQL_TXN_ISOLATION_OPTION:
08010 *((SQLUINTEGER *) val) = SQL_TXN_SERIALIZABLE;
08011 *valLen = sizeof (SQLUINTEGER);
08012 break;
08013 case SQL_IDENTIFIER_CASE:
08014 *((SQLSMALLINT *) val) = SQL_IC_SENSITIVE;
08015 *valLen = sizeof (SQLSMALLINT);
08016 break;
08017 case SQL_IDENTIFIER_QUOTE_CHAR:
08018 strmak(val, "\"", valMax, valLen);
08019 break;
08020 case SQL_MAX_TABLE_NAME_LEN:
08021 case SQL_MAX_COLUMN_NAME_LEN:
08022 *((SQLSMALLINT *) val) = 255;
08023 *valLen = sizeof (SQLSMALLINT);
08024 break;
08025 case SQL_MAX_CURSOR_NAME_LEN:
08026 *((SQLSMALLINT *) val) = 255;
08027 *valLen = sizeof (SQLSMALLINT);
08028 break;
08029 case SQL_MAX_PROCEDURE_NAME_LEN:
08030 *((SQLSMALLINT *) val) = 0;
08031 break;
08032 case SQL_MAX_QUALIFIER_NAME_LEN:
08033 case SQL_MAX_OWNER_NAME_LEN:
08034 *((SQLSMALLINT *) val) = 255;
08035 break;
08036 case