00001
00014 #include "sqlite3odbc.h"
00015
00016 #ifdef _WIN32
00017 #include "resource3.h"
00018 #define ODBC_INI "ODBC.INI"
00019 #else
00020 #define ODBC_INI ".odbc.ini"
00021 #endif
00022
00023 #ifdef CANT_PASS_VALIST_AS_CHARPTR
00024 #define MAX_PARAMS_FOR_MPRINTF 32
00025 #endif
00026
00027 #ifndef DRIVER_VER_INFO
00028 #define DRIVER_VER_INFO "0.0"
00029 #endif
00030
00031 #ifndef COLATTRIBUTE_LAST_ARG_TYPE
00032 #define COLATTRIBUTE_LAST_ARG_TYPE SQLPOINTER
00033 #endif
00034
00035 #undef min
00036 #define min(a, b) ((a) < (b) ? (a) : (b))
00037 #undef max
00038 #define max(a, b) ((a) < (b) ? (b) : (a))
00039
00040 #define array_size(x) (sizeof (x) / sizeof (x[0]))
00041
00042 #define stringify1(s) #s
00043 #define stringify(s) stringify1(s)
00044
00045 #define verinfo(maj, min, lev) ((maj) << 16 | (min) << 8 | (lev))
00046
00047
00048
00049 #define SCOL_VARCHAR SQL_VARCHAR
00050 #define SCOL_CHAR SQL_CHAR
00051
00052 #define ENV_MAGIC 0x53544145
00053 #define DBC_MAGIC 0x53544144
00054 #define DEAD_MAGIC 0xdeadbeef
00055
00056 static const char *xdigits = "0123456789ABCDEFabcdef";
00057
00058 #ifdef MEMORY_DEBUG
00059
00060 static void *
00061 xmalloc_(int n, char *file, int line)
00062 {
00063 int nn = n + 4 * sizeof (long);
00064 long *p;
00065
00066 p = malloc(nn);
00067 if (!p) {
00068 #if (MEMORY_DEBUG > 1)
00069 fprintf(stderr, "malloc\t%d\tNULL\t%s:%d\n", n, file, line);
00070 #endif
00071 return NULL;
00072 }
00073 p[0] = 0xdead1234;
00074 nn = nn / sizeof (long) - 1;
00075 p[1] = n;
00076 p[nn] = 0xdead5678;
00077 #if (MEMORY_DEBUG > 1)
00078 fprintf(stderr, "malloc\t%d\t%p\t%s:%d\n", n, &p[2], file, line);
00079 #endif
00080 return (void *) &p[2];
00081 }
00082
00083 static void *
00084 xrealloc_(void *old, int n, char *file, int line)
00085 {
00086 int nn = n + 4 * sizeof (long), nnn;
00087 long *p, *pp;
00088
00089 if (n == 0) {
00090 return xmalloc_(n, file, line);
00091 }
00092 p = &((long *) old)[-2];
00093 if (p[0] != 0xdead1234) {
00094 fprintf(stderr, "*** low end corruption @ %p\n", old);
00095 abort();
00096 }
00097 nnn = p[1] + 4 * sizeof (long);
00098 nnn = nnn / sizeof (long) - 1;
00099 if (p[nnn] != 0xdead5678) {
00100 fprintf(stderr, "*** high end corruption @ %p\n", old);
00101 abort();
00102 }
00103 pp = realloc(p, nn);
00104 if (!pp) {
00105 #if (MEMORY_DEBUG > 1)
00106 fprintf(stderr, "realloc\t%p,%d\tNULL\t%s:%d\n", old, n, file, line);
00107 #endif
00108 return NULL;
00109 }
00110 #if (MEMORY_DEBUG > 1)
00111 fprintf(stderr, "realloc\t%p,%d\t%p\t%s:%d\n", old, n, &pp[2], file, line);
00112 #endif
00113 p = pp;
00114 if (n > p[1]) {
00115 memset(p + p[1], 0, 3 * sizeof (long));
00116 }
00117 p[1] = n;
00118 nn = nn / sizeof (long) - 1;
00119 p[nn] = 0xdead5678;
00120 return (void *) &p[2];
00121 }
00122
00123 static void
00124 xfree_(void *x, char *file, int line)
00125 {
00126 long *p;
00127 int n;
00128
00129 p = &((long *) x)[-2];
00130 if (p[0] != 0xdead1234) {
00131 fprintf(stderr, "*** low end corruption @ %p\n", x);
00132 abort();
00133 }
00134 n = p[1] + 4 * sizeof (long);
00135 n = n / sizeof (long) - 1;
00136 if (p[n] != 0xdead5678) {
00137 fprintf(stderr, "*** high end corruption @ %p\n", x);
00138 abort();
00139 }
00140 #if (MEMORY_DEBUG > 1)
00141 fprintf(stderr, "free\t%p\t\t%s:%d\n", x, file, line);
00142 #endif
00143 free(p);
00144 }
00145
00146 static void
00147 xfree__(void *x)
00148 {
00149 xfree_(x, "unknown location", 0);
00150 }
00151
00152 static char *
00153 xstrdup_(const char *str, char *file, int line)
00154 {
00155 char *p;
00156
00157 if (!str) {
00158 #if (MEMORY_DEBUG > 1)
00159 fprintf(stderr, "strdup\tNULL\tNULL\t%s:%d\n", file, line);
00160 #endif
00161 return NULL;
00162 }
00163 p = xmalloc_(strlen(str) + 1, file, line);
00164 if (p) {
00165 strcpy(p, str);
00166 }
00167 #if (MEMORY_DEBUG > 1)
00168 fprintf(stderr, "strdup\t%p\t%p\t%s:%d\n", str, p, file, line);
00169 #endif
00170 return p;
00171 }
00172
00173 #define xmalloc(x) xmalloc_(x, __FILE__, __LINE__)
00174 #define xrealloc(x,y) xrealloc_(x, y, __FILE__, __LINE__)
00175 #define xfree(x) xfree_(x, __FILE__, __LINE__)
00176 #define xstrdup(x) xstrdup_(x, __FILE__, __LINE__)
00177
00178 #else
00179
00180 #define xmalloc(x) malloc(x)
00181 #define xrealloc(x,y) realloc(x, y)
00182 #define xfree(x) free(x)
00183 #define xstrdup(x) strdup_(x)
00184
00185 #endif
00186
00187 #ifdef _WIN32
00188 #define vsnprintf _vsnprintf
00189 #define snprintf _snprintf
00190 #define strncasecmp _strnicmp
00191 #endif
00192
00193
00194
00195
00196
00197 static const char upper_chars[] = "ABCDEFGHIJKLMNOPQRSTUVWXYZ";
00198 static const char lower_chars[] = "abcdefghijklmnopqrstuvwxyz";
00199
00200 static int
00201 TOLOWER(int c)
00202 {
00203 if (c) {
00204 char *p = strchr(upper_chars, c);
00205
00206 if (p) {
00207 c = lower_chars[p - upper_chars];
00208 }
00209 }
00210 return c;
00211 }
00212
00213
00214
00215
00216
00217 static const char digit_chars[] = "0123456789";
00218
00219 #define ISDIGIT(c) \
00220 ((c) && strchr(digit_chars, (c)) != NULL)
00221
00222
00223
00224
00225
00226 static const char space_chars[] = " \f\n\r\t\v";
00227
00228 #define ISSPACE(c) \
00229 ((c) && strchr(space_chars, (c)) != NULL)
00230
00231
00232
00233
00234
00235 static const char id_chars[] = "ABCDEFGHIJKLMNOPQRSTUVWXYZ"
00236 "abcdefghijklmnopqrstuvwxyz"
00237 "_0123456789";
00238
00239 #define ISIDCHAR(c) \
00240 ((c) && strchr(id_chars, (c)) != NULL)
00241
00247 static void unbindcols(STMT *s);
00248
00256 static SQLRETURN mkbindcols(STMT *s, int ncols);
00257
00269 static void freeresult(STMT *s, int clrcols);
00270
00277 static SQLRETURN freestmt(HSTMT stmt);
00278
00296 static SQLRETURN substparam(STMT *s, char **sqlp, int pnum, char **outp);
00297
00303 static void freedyncols(STMT *s);
00304
00312 static SQLRETURN drvexecute(SQLHSTMT stmt, int initial);
00313
00320 static void dbtraceapi(DBC *d, char *fn, const char *sql);
00321
00322 #if (MEMORY_DEBUG < 1)
00323
00329 static char *
00330 strdup_(const char *str)
00331 {
00332 char *p = NULL;
00333
00334 if (str) {
00335 p = xmalloc(strlen(str) + 1);
00336 if (p) {
00337 strcpy(p, str);
00338 }
00339 }
00340 return p;
00341 }
00342 #endif
00343
00344 #ifdef USE_DLOPEN_FOR_GPPS
00345
00346 #include <dlfcn.h>
00347
00348 #define SQLGetPrivateProfileString(A,B,C,D,E,F) drvgpps(d,A,B,C,D,E,F)
00349
00350
00351
00352
00353
00354
00355
00356
00357 static void
00358 drvgetgpps(DBC *d)
00359 {
00360 void *lib;
00361 int (*gpps)();
00362
00363 lib = dlopen("libodbcinst.so", RTLD_LAZY);
00364 if (!lib) {
00365 lib = dlopen("libiodbcinst.so", RTLD_LAZY);
00366 }
00367 if (lib) {
00368 gpps = (int (*)()) dlsym(lib, "SQLGetPrivateProfileString");
00369 if (!gpps) {
00370 dlclose(lib);
00371 return;
00372 }
00373 d->instlib = lib;
00374 d->gpps = gpps;
00375 }
00376 }
00377
00378 static void
00379 drvrelgpps(DBC *d)
00380 {
00381 if (d->instlib) {
00382 dlclose(d->instlib);
00383 d->instlib = 0;
00384 }
00385 }
00386
00387 static int
00388 drvgpps(DBC *d, char *sect, char *ent, char *def, char *buf,
00389 int bufsiz, char *fname)
00390 {
00391 if (d->gpps) {
00392 return d->gpps(sect, ent, def, buf, bufsiz, fname);
00393 }
00394 strncpy(buf, def, bufsiz);
00395 buf[bufsiz - 1] = '\0';
00396 return 1;
00397 }
00398 #else
00399 #define drvgetgpps(d)
00400 #define drvrelgpps(d)
00401 #endif
00402
00412 static void freerows(char **rowp);
00413
00414
00415
00416
00417
00418
00419 typedef struct tblres {
00420 char **resarr;
00421 char *errmsg;
00422 sqlite3_stmt *stmt;
00423 int nres;
00424 int nalloc;
00425 int nrow;
00426 int ncol;
00427 int ndata;
00428 int rc;
00429 } TBLRES;
00430
00431
00432
00433
00434
00435
00436 static int
00437 drvgettable_row(TBLRES *t, int ncol, int rc)
00438 {
00439 int need;
00440 int i;
00441 char *p;
00442
00443 if (t->nrow == 0 && rc == SQLITE_ROW) {
00444 need = ncol * 2;
00445 } else {
00446 need = ncol;
00447 }
00448 if (t->ndata + need >= t->nalloc) {
00449 char **resnew;
00450 int nalloc = t->nalloc * 2 + need + 1;
00451
00452 nalloc = t->nalloc * 2 + need + 1;
00453 resnew = xrealloc(t->resarr, sizeof (char *) * nalloc);
00454 if (!resnew) {
00455 nomem:
00456 t->rc = SQLITE_NOMEM;
00457 return 1;
00458 }
00459 t->nalloc = nalloc;
00460 t->resarr = resnew;
00461 }
00462
00463 if (t->nrow == 0) {
00464 t->ncol = ncol;
00465 for (i = 0; i < ncol; i++) {
00466 p = (char *) sqlite3_column_name(t->stmt, i);
00467 if (p) {
00468 char *q = xmalloc(strlen(p) + 1);
00469
00470 if (!q) {
00471 goto nomem;
00472 }
00473 strcpy(q, p);
00474 p = q;
00475 }
00476 t->resarr[t->ndata++] = p;
00477 }
00478 } else if (t->ncol != ncol) {
00479 t->errmsg = sqlite3_mprintf("drvgettable() called with two or"
00480 " more incompatible queries");
00481 t->rc = SQLITE_ERROR;
00482 return 1;
00483 }
00484
00485 if (rc == SQLITE_ROW) {
00486 for (i = 0; i < ncol; i++) {
00487 int coltype = sqlite3_column_type(t->stmt, i);
00488
00489 p = NULL;
00490 if (coltype == SQLITE_BLOB) {
00491 int k, nbytes = sqlite3_column_bytes(t->stmt, i);
00492 char *qp;
00493 unsigned const char *bp;
00494
00495 bp = sqlite3_column_blob(t->stmt, i);
00496 qp = xmalloc(nbytes * 2 + 4);
00497 if (!qp) {
00498 goto nomem;
00499 }
00500 p = qp;
00501 *qp++ = 'X';
00502 *qp++ = '\'';
00503 for (k = 0; k < nbytes; k++) {
00504 *qp++ = xdigits[(bp[k] >> 4)];
00505 *qp++ = xdigits[(bp[k] & 0xF)];
00506 }
00507 *qp++ = '\'';
00508 *qp = '\0';
00509 } else if (coltype != SQLITE_NULL) {
00510 p = xstrdup(sqlite3_column_text(t->stmt, i));
00511 if (!p) {
00512 goto nomem;
00513 }
00514 }
00515 t->resarr[t->ndata++] = p;
00516 }
00517 t->nrow++;
00518 }
00519 return 0;
00520 }
00521
00522 static int
00523 drvgettable(DBC *d, const char *sql, char ***resp, int *nrowp,
00524 int *ncolp, char **errp)
00525 {
00526 int rc = SQLITE_OK;
00527 TBLRES tres;
00528 const char *sqlleft;
00529 int nretry = 0;
00530
00531 if (!resp) {
00532 return SQLITE_ERROR;
00533 }
00534 *resp = NULL;
00535 if (nrowp) {
00536 *nrowp = 0;
00537 }
00538 if (ncolp) {
00539 *ncolp = 0;
00540 }
00541 if (!sql) {
00542 return SQLITE_OK;
00543 }
00544 tres.errmsg = NULL;
00545 tres.nres = 0;
00546 tres.nrow = 0;
00547 tres.ncol = 0;
00548 tres.ndata = 1;
00549 tres.nalloc = 20;
00550 tres.rc = SQLITE_OK;
00551 tres.resarr = xmalloc(sizeof (char *) * tres.nalloc);
00552 tres.stmt = NULL;
00553 if (!tres.resarr) {
00554 return SQLITE_NOMEM;
00555 }
00556 tres.resarr[0] = 0;
00557 while (*sql && (rc == SQLITE_OK ||
00558 (rc == SQLITE_SCHEMA && (++nretry) < 2))) {
00559 int ncol;
00560
00561 tres.stmt = NULL;
00562 dbtraceapi(d, "sqlite3_prepare", sql);
00563 rc = sqlite3_prepare(d->sqlite, sql, -1, &tres.stmt, &sqlleft);
00564 if (rc != SQLITE_OK) {
00565 if (tres.stmt) {
00566 dbtraceapi(d, "sqlite3_finalize", 0);
00567 sqlite3_finalize(tres.stmt);
00568 tres.stmt = NULL;
00569 }
00570 continue;
00571 }
00572 if (!tres.stmt) {
00573
00574 sql = sqlleft;
00575 continue;
00576 }
00577 ncol = sqlite3_column_count(tres.stmt);
00578 while (1) {
00579 rc = sqlite3_step(tres.stmt);
00580 if (rc == SQLITE_ROW || rc == SQLITE_DONE) {
00581 if (drvgettable_row(&tres, ncol, rc)) {
00582 rc = SQLITE_ABORT;
00583 goto tbldone;
00584 }
00585 }
00586 if (rc != SQLITE_ROW) {
00587 dbtraceapi(d, "sqlite3_finalize", 0);
00588 rc = sqlite3_finalize(tres.stmt);
00589 tres.stmt = 0;
00590 if (rc != SQLITE_SCHEMA) {
00591 nretry = 0;
00592 sql = sqlleft;
00593 while (ISSPACE(*sql)) {
00594 sql++;
00595 }
00596 }
00597 break;
00598 }
00599 }
00600 }
00601 tbldone:
00602 if (tres.stmt) {
00603 dbtraceapi(d, "sqlite3_finalize", 0);
00604 sqlite3_finalize(tres.stmt);
00605 }
00606 if (rc != SQLITE_OK && rc == sqlite3_errcode(d->sqlite) && errp) {
00607 *errp = sqlite3_mprintf("%s", sqlite3_errmsg(d->sqlite));
00608 } else if (errp) {
00609 *errp = NULL;
00610 }
00611 if (tres.resarr) {
00612 tres.resarr[0] = (char *) (tres.ndata - 1);
00613 }
00614 if (rc == SQLITE_ABORT) {
00615 freerows(&tres.resarr[1]);
00616 if (tres.errmsg) {
00617 if (errp) {
00618 if (*errp) {
00619 sqlite3_free(*errp);
00620 }
00621 *errp = tres.errmsg;
00622 } else {
00623 sqlite3_free(tres.errmsg);
00624 }
00625 }
00626 return tres.rc;
00627 }
00628 sqlite3_free(tres.errmsg);
00629 if (rc != SQLITE_OK) {
00630 freerows(&tres.resarr[1]);
00631 return rc;
00632 }
00633 *resp = &tres.resarr[1];
00634 if (ncolp) {
00635 *ncolp = tres.ncol;
00636 }
00637 if (nrowp) {
00638 *nrowp = tres.nrow;
00639 }
00640 return rc;
00641 }
00642
00651 #if defined(__GNUC__) && (__GNUC__ >= 2)
00652 static void setstatd(DBC *, int, char *, char *, ...)
00653 __attribute__((format (printf, 3, 5)));
00654 #endif
00655
00656 static void
00657 setstatd(DBC *d, int naterr, char *msg, char *st, ...)
00658 {
00659 va_list ap;
00660
00661 if (!d) {
00662 return;
00663 }
00664 d->naterr = naterr;
00665 d->logmsg[0] = '\0';
00666 if (msg) {
00667 int count;
00668
00669 va_start(ap, st);
00670 count = vsnprintf((char *) d->logmsg, sizeof (d->logmsg), msg, ap);
00671 va_end(ap);
00672 if (count < 0) {
00673 d->logmsg[sizeof (d->logmsg) - 1] = '\0';
00674 }
00675 }
00676 if (!st) {
00677 st = "?????";
00678 }
00679 strncpy(d->sqlstate, st, 5);
00680 d->sqlstate[5] = '\0';
00681 }
00682
00691 #if defined(__GNUC__) && (__GNUC__ >= 2)
00692 static void setstat(STMT *, int, char *, char *, ...)
00693 __attribute__((format (printf, 3, 5)));
00694 #endif
00695
00696 static void
00697 setstat(STMT *s, int naterr, char *msg, char *st, ...)
00698 {
00699 va_list ap;
00700
00701 if (!s) {
00702 return;
00703 }
00704 s->naterr = naterr;
00705 s->logmsg[0] = '\0';
00706 if (msg) {
00707 int count;
00708
00709 va_start(ap, st);
00710 count = vsnprintf((char *) s->logmsg, sizeof (s->logmsg), msg, ap);
00711 va_end(ap);
00712 if (count < 0) {
00713 s->logmsg[sizeof (s->logmsg) - 1] = '\0';
00714 }
00715 }
00716 if (!st) {
00717 st = "?????";
00718 }
00719 strncpy(s->sqlstate, st, 5);
00720 s->sqlstate[5] = '\0';
00721 }
00722
00729 static SQLRETURN
00730 drvunimpldbc(HDBC dbc)
00731 {
00732 DBC *d;
00733
00734 if (dbc == SQL_NULL_HDBC) {
00735 return SQL_INVALID_HANDLE;
00736 }
00737 d = (DBC *) dbc;
00738 setstatd(d, -1, "not supported", "IM001");
00739 return SQL_ERROR;
00740 }
00741
00748 static SQLRETURN
00749 drvunimplstmt(HSTMT stmt)
00750 {
00751 STMT *s;
00752
00753 if (stmt == SQL_NULL_HSTMT) {
00754 return SQL_INVALID_HANDLE;
00755 }
00756 s = (STMT *) stmt;
00757 setstat(s, -1, "not supported", "IM001");
00758 return SQL_ERROR;
00759 }
00760
00766 static void
00767 freep(void *x)
00768 {
00769 if (x && ((char **) x)[0]) {
00770 xfree(((char **) x)[0]);
00771 ((char **) x)[0] = NULL;
00772 }
00773 }
00774
00781 static SQLRETURN
00782 nomem(STMT *s)
00783 {
00784 setstat(s, -1, "out of memory", (*s->ov3) ? "HY000" : "S1000");
00785 return SQL_ERROR;
00786 }
00787
00794 static SQLRETURN
00795 noconn(STMT *s)
00796 {
00797 setstat(s, -1, "not connected", (*s->ov3) ? "HY000" : "S1000");
00798 return SQL_ERROR;
00799 }
00800
00808 static double
00809 ln_strtod(const char *data, char **endp)
00810 {
00811 #if defined(HAVE_LOCALECONV) || defined(_WIN32)
00812 struct lconv *lc;
00813 char buf[128], *p, *end;
00814 double value;
00815
00816 lc = localeconv();
00817 if (lc && lc->decimal_point && lc->decimal_point[0] &&
00818 lc->decimal_point[0] != '.') {
00819 strncpy(buf, data, sizeof (buf) - 1);
00820 buf[sizeof (buf) - 1] = '\0';
00821 p = strchr(buf, '.');
00822 if (p) {
00823 *p = lc->decimal_point[0];
00824 }
00825 p = buf;
00826 } else {
00827 p = (char *) data;
00828 }
00829 value = strtod(p, &end);
00830 end = (char *) data + (end - p);
00831 if (endp) {
00832 *endp = end;
00833 }
00834 return value;
00835 #else
00836 return strtod(data, endp);
00837 #endif
00838 }
00839
00847 static int
00848 busy_handler(void *udata, int count)
00849 {
00850 DBC *d = (DBC *) udata;
00851 long t1;
00852 int ret = 0;
00853 #ifndef _WIN32
00854 struct timeval tv;
00855 #endif
00856
00857 if (d->timeout <= 0) {
00858 return ret;
00859 }
00860 if (count <= 1) {
00861 #ifdef _WIN32
00862 d->t0 = GetTickCount();
00863 #else
00864 gettimeofday(&tv, NULL);
00865 d->t0 = tv.tv_sec * 1000 + tv.tv_usec / 1000;
00866 #endif
00867 }
00868 #ifdef _WIN32
00869 t1 = GetTickCount();
00870 #else
00871 gettimeofday(&tv, NULL);
00872 t1 = tv.tv_sec * 1000 + tv.tv_usec / 1000;
00873 #endif
00874 if (t1 - d->t0 > d->timeout) {
00875 goto done;
00876 }
00877 #ifdef _WIN32
00878 Sleep(10);
00879 #else
00880 #ifdef HAVE_USLEEP
00881 usleep(10000);
00882 #else
00883 tv.tv_sec = 0;
00884 tv.tv_usec = 10000;
00885 select(0, NULL, NULL, NULL, &tv);
00886 #endif
00887 #endif
00888 ret = 1;
00889 done:
00890 return ret;
00891 }
00892
00903 static int
00904 setsqliteopts(sqlite3 *x, DBC *d)
00905 {
00906 int count = 0, step = 0, rc = SQLITE_ERROR;
00907
00908 while (step < 2) {
00909 if (step < 1) {
00910 rc = sqlite3_exec(x, "PRAGMA full_column_names = on;",
00911 NULL, NULL, NULL);
00912 } else if (step < 2) {
00913 rc = sqlite3_exec(x, "PRAGMA empty_result_callbacks = on;",
00914 NULL, NULL, NULL);
00915 }
00916 if (rc != SQLITE_OK) {
00917 if (rc != SQLITE_BUSY ||
00918 !busy_handler((void *) d, ++count)) {
00919 return rc;
00920 }
00921 continue;
00922 }
00923 count = 0;
00924 ++step;
00925 }
00926 sqlite3_busy_handler(x, busy_handler, (void *) d);
00927 return SQLITE_OK;
00928 }
00929
00930
00931
00932 static void
00933 freerows(char **rowp)
00934 {
00935 int size, i;
00936
00937 if (!rowp) {
00938 return;
00939 }
00940 --rowp;
00941 size = (int) rowp[0];
00942 for (i = 1; i <= size; i++) {
00943 freep(&rowp[i]);
00944 }
00945 freep(&rowp);
00946 }
00947
00956 static int
00957 mapsqltype(const char *typename, int *nosign, int ov3)
00958 {
00959 char *p, *q;
00960 int testsign = 0, result;
00961
00962 result = SQL_VARCHAR;
00963 if (!typename) {
00964 return result;
00965 }
00966 q = p = xmalloc(strlen(typename) + 1);
00967 if (!p) {
00968 return result;
00969 }
00970 strcpy(p, typename);
00971 while (*q) {
00972 *q = TOLOWER(*q);
00973 ++q;
00974 }
00975 if (strncmp(p, "inter", 5) == 0) {
00976 } else if (strncmp(p, "int", 3) == 0 ||
00977 strncmp(p, "mediumint", 9) == 0) {
00978 testsign = 1;
00979 result = SQL_INTEGER;
00980 } else if (strncmp(p, "numeric", 7) == 0) {
00981 result = SQL_DOUBLE;
00982 } else if (strncmp(p, "tinyint", 7) == 0) {
00983 testsign = 1;
00984 result = SQL_TINYINT;
00985 } else if (strncmp(p, "smallint", 8) == 0) {
00986 testsign = 1;
00987 result = SQL_SMALLINT;
00988 } else if (strncmp(p, "float", 5) == 0) {
00989 result = SQL_DOUBLE;
00990 } else if (strncmp(p, "double", 6) == 0 ||
00991 strncmp(p, "real", 4) == 0) {
00992 result = SQL_DOUBLE;
00993 } else if (strncmp(p, "timestamp", 9) == 0) {
00994 #ifdef SQL_TYPE_TIMESTAMP
00995 result = ov3 ? SQL_TYPE_TIMESTAMP : SQL_TIMESTAMP;
00996 #else
00997 result = SQL_TIMESTAMP;
00998 #endif
00999 } else if (strncmp(p, "datetime", 8) == 0) {
01000 #ifdef SQL_TYPE_TIMESTAMP
01001 result = ov3 ? SQL_TYPE_TIMESTAMP : SQL_TIMESTAMP;
01002 #else
01003 result = SQL_TIMESTAMP;
01004 #endif
01005 } else if (strncmp(p, "time", 4) == 0) {
01006 #ifdef SQL_TYPE_TIME
01007 result = ov3 ? SQL_TYPE_TIME : SQL_TIME;
01008 #else
01009 result = SQL_TIME;
01010 #endif
01011 } else if (strncmp(p, "date", 4) == 0) {
01012 #ifdef SQL_TYPE_DATE
01013 result = ov3 ? SQL_TYPE_DATE : SQL_DATE;
01014 #else
01015 result = SQL_DATE;
01016 #endif
01017 #ifdef SQL_LONGVARCHAR
01018 } else if (strncmp(p, "text", 4) == 0) {
01019 result = SQL_LONGVARCHAR;
01020 #endif
01021 #ifdef SQL_BIT
01022 } else if (strncmp(p, "bool", 4) == 0 ||
01023 strncmp(p, "bit", 3) == 0) {
01024 result = SQL_BIT;
01025 #endif
01026 #ifdef SQL_BIGINT
01027 } else if (strncmp(p, "bigint", 6) == 0) {
01028 result = SQL_BIGINT;
01029 #endif
01030 } else if (strncmp(p, "blob", 4) == 0) {
01031 result = SQL_BINARY;
01032 }
01033 if (nosign) {
01034 if (testsign) {
01035 *nosign = strstr(p, "unsigned") != NULL;
01036 } else {
01037 *nosign = 1;
01038 }
01039 }
01040 xfree(p);
01041 return result;
01042 }
01043
01053 static void
01054 getmd(const char *typename, int sqltype, int *mp, int *dp)
01055 {
01056 int m = 0, d = 0;
01057
01058 switch (sqltype) {
01059 case SQL_INTEGER: m = 10; d = 9; break;
01060 case SQL_TINYINT: m = 4; d = 3; break;
01061 case SQL_SMALLINT: m = 6; d = 5; break;
01062 case SQL_FLOAT: m = 25; d = 24; break;
01063 case SQL_DOUBLE: m = 54; d = 53; break;
01064 case SQL_VARCHAR: m = 255; d = 0; break;
01065 #ifdef SQL_TYPE_DATE
01066 case SQL_TYPE_DATE:
01067 #endif
01068 case SQL_DATE: m = 10; d = 0; break;
01069 #ifdef SQL_TYPE_TIME
01070 case SQL_TYPE_TIME:
01071 #endif
01072 case SQL_TIME: m = 8; d = 0; break;
01073 #ifdef SQL_TYPE_TIMESTAMP
01074 case SQL_TYPE_TIMESTAMP:
01075 #endif
01076 case SQL_TIMESTAMP: m = 32; d = 0; break;
01077 #ifdef SQL_LONGVARCHAR
01078 case SQL_LONGVARCHAR : m = 65536; d = 0; break;
01079 #endif
01080 case SQL_VARBINARY: m = 255; d = 0; break;
01081 case SQL_LONGVARBINARY: m = 65536; d = 0; break;
01082 #ifdef SQL_BIGINT
01083 case SQL_BIGINT: m = 20; d = 19; break;
01084 #endif
01085 }
01086 if (m && typename) {
01087 int mm, dd;
01088
01089 if (sscanf(typename, "%*[^(](%d)", &mm) == 1) {
01090 m = d = mm;
01091 } else if (sscanf(typename, "%*[^(](%d,%d)", &mm, &dd) == 2) {
01092 m = mm;
01093 d = dd;
01094 }
01095 }
01096 if (mp) {
01097 *mp = m;
01098 }
01099 if (dp) {
01100 *dp = d;
01101 }
01102 }
01103
01112 static int
01113 mapdeftype(int type, int stype, int nosign)
01114 {
01115 if (type == SQL_C_DEFAULT) {
01116 switch (stype) {
01117 case SQL_INTEGER:
01118 type = nosign > 0 ? SQL_C_ULONG : SQL_C_LONG;
01119 break;
01120 case SQL_TINYINT:
01121 type = nosign > 0 ? SQL_C_UTINYINT : SQL_C_TINYINT;
01122 break;
01123 case SQL_SMALLINT:
01124 type = nosign > 0 ? SQL_C_USHORT : SQL_C_SHORT;
01125 break;
01126 case SQL_FLOAT:
01127 type = SQL_C_FLOAT;
01128 break;
01129 case SQL_DOUBLE:
01130 type = SQL_C_DOUBLE;
01131 break;
01132 case SQL_TIMESTAMP:
01133 type = SQL_C_TIMESTAMP;
01134 break;
01135 case SQL_TIME:
01136 type = SQL_C_TIME;
01137 break;
01138 case SQL_DATE:
01139 type = SQL_C_DATE;
01140 break;
01141 #ifdef SQL_C_TYPE_TIMESTAMP
01142 case SQL_TYPE_TIMESTAMP:
01143 type = SQL_C_TYPE_TIMESTAMP;
01144 break;
01145 #endif
01146 #ifdef SQL_C_TYPE_TIME
01147 case SQL_TYPE_TIME:
01148 type = SQL_C_TYPE_TIME;
01149 break;
01150 #endif
01151 #ifdef SQL_C_TYPE_DATE
01152 case SQL_TYPE_DATE:
01153 type = SQL_C_TYPE_DATE;
01154 break;
01155 #endif
01156 case SQL_BINARY:
01157 case SQL_VARBINARY:
01158 case SQL_LONGVARBINARY:
01159 type = SQL_C_BINARY;
01160 break;
01161 #ifdef SQL_BIT
01162 case SQL_BIT:
01163 type = SQL_C_BIT;
01164 break;
01165 #endif
01166 #ifdef SQL_BIGINT
01167 case SQL_BIGINT:
01168 type = nosign > 0 ? SQL_C_UBIGINT : SQL_C_SBIGINT;
01169 break;
01170 #endif
01171 default:
01172 type = SQL_C_CHAR;
01173 }
01174 }
01175 return type;
01176 }
01177
01188 static char *
01189 fixupsql(char *sql, int sqlLen, int *nparam, int *isselect, char **errmsg)
01190 {
01191 char *q = sql, *qz = NULL, *p, *inq = NULL, *out;
01192 int np = 0, size;
01193
01194 *errmsg = NULL;
01195 if (sqlLen != SQL_NTS) {
01196 qz = q = xmalloc(sqlLen + 1);
01197 if (!qz) {
01198 return NULL;
01199 }
01200 memcpy(q, sql, sqlLen);
01201 q[sqlLen] = '\0';
01202 size = sqlLen * 4;
01203 } else {
01204 size = strlen(sql) * 4;
01205 }
01206 size += sizeof (char *) - 1;
01207 size &= ~(sizeof (char *) - 1);
01208 p = xmalloc(size);
01209 if (!p) {
01210 errout:
01211 freep(&qz);
01212 return NULL;
01213 }
01214 out = p;
01215 while (*q) {
01216 switch (*q) {
01217 case '\'':
01218 case '\"':
01219 if (q == inq) {
01220 inq = NULL;
01221 } else if (!inq) {
01222 inq = q + 1;
01223
01224 while (*inq) {
01225 if (*inq == *q) {
01226 if (inq[1] == *q) {
01227 inq++;
01228 } else {
01229 break;
01230 }
01231 }
01232 inq++;
01233 }
01234 }
01235 *p++ = *q;
01236 break;
01237 case '?':
01238 if (inq) {
01239 *p++ = *q;
01240 } else {
01241 *p++ = '%';
01242 *p++ = 'Q';
01243 np++;
01244 }
01245 break;
01246 case ';':
01247 if (inq) {
01248 *p++ = *q;
01249 } else {
01250 do {
01251 ++q;
01252 } while (*q && ISSPACE(*q));
01253 if (*q) {
01254 freep(&out);
01255 *errmsg = "only one SQL statement allowed";
01256 goto errout;
01257 }
01258 --q;
01259 }
01260 break;
01261 case '%':
01262 *p++ = '%';
01263 *p++ = '%';
01264 break;
01265 case '{':
01266
01267 if (!inq) {
01268 char *end = q + 1;
01269
01270 while (*end && *end != '}') {
01271 ++end;
01272 }
01273 if (*end == '}') {
01274 char *start = q + 1;
01275 char *end2 = end - 1;
01276
01277 while (start < end2 && *start != '\'') {
01278 ++start;
01279 }
01280 while (end2 > start && *end2 != '\'') {
01281 --end2;
01282 }
01283 if (*start == '\'' && *end2 == '\'') {
01284 while (start <= end2) {
01285 *p++ = *start;
01286 ++start;
01287 }
01288 q = end;
01289 break;
01290 }
01291 }
01292 }
01293
01294 default:
01295 *p++ = *q;
01296 }
01297 ++q;
01298 }
01299 freep(&qz);
01300 *p = '\0';
01301 if (nparam) {
01302 *nparam = np;
01303 }
01304 if (isselect) {
01305 p = out;
01306 while (*p && ISSPACE(*p)) {
01307 ++p;
01308 }
01309 *isselect = strncasecmp(p, "select", 6) == 0;
01310 }
01311 return out;
01312 }
01313
01322 static int
01323 findcol(char **cols, int ncols, char *name)
01324 {
01325 int i;
01326
01327 if (cols) {
01328 for (i = 0; i < ncols; i++) {
01329 if (strcmp(cols[i], name) == 0) {
01330 return i;
01331 }
01332 }
01333 }
01334 return -1;
01335 }
01336
01353 static void
01354 fixupdyncols(STMT *s, DBC *d)
01355 {
01356 int i, k, pk, t, r, nrows, ncols, doautoinc = 0;
01357 char **rowp, *flagp, flags[128];
01358
01359 if (!s->dyncols) {
01360 return;
01361 }
01362
01363 if (!s->longnames) {
01364 if (s->dcols > 1) {
01365 char *table = s->dyncols[0].table;
01366
01367 for (i = 1; table[0] && i < s->dcols; i++) {
01368 if (strcmp(s->dyncols[i].table, table)) {
01369 break;
01370 }
01371 }
01372 if (i >= s->dcols) {
01373 for (i = 0; i < s->dcols; i++) {
01374 s->dyncols[i].label = s->dyncols[i].column;
01375 }
01376 }
01377 } else if (s->dcols == 1) {
01378 s->dyncols[0].label = s->dyncols[0].column;
01379 }
01380 }
01381 for (i = 0; i < s->dcols; i++) {
01382 s->dyncols[i].type =
01383 mapsqltype(s->dyncols[i].typename, &s->dyncols[i].nosign, *s->ov3);
01384 getmd(s->dyncols[i].typename, s->dyncols[i].type,
01385 &s->dyncols[i].size, NULL);
01386 #ifdef SQL_LONGVARCHAR
01387 if (s->dyncols[i].type == SQL_VARCHAR &&
01388 s->dyncols[i].size > 255) {
01389 s->dyncols[i].type = SQL_LONGVARCHAR;
01390 }
01391 #endif
01392 if (s->dyncols[i].type == SQL_VARBINARY &&
01393 s->dyncols[i].size > 255) {
01394 s->dyncols[i].type = SQL_LONGVARBINARY;
01395 }
01396 if (s->dyncols[i].typename && strlen(s->dyncols[i].typename) == 7 &&
01397 strncasecmp(s->dyncols[i].typename, "integer", 7) == 0) {
01398 doautoinc++;
01399 s->dyncols[i].autoinc = -1;
01400 } else {
01401 s->dyncols[i].autoinc = 0;
01402 }
01403 }
01404 if (!doautoinc) {
01405 return;
01406 }
01407 if (s->dcols > array_size(flags)) {
01408 flagp = xmalloc(sizeof (flags[0]) * s->dcols);
01409 if (flagp == NULL) {
01410 return;
01411 }
01412 } else {
01413 flagp = flags;
01414 }
01415 memset(flagp, 0, sizeof (flags[0]) * s->dcols);
01416 for (i = 0; i < s->dcols; i++) {
01417 s->dyncols[i].autoinc = 0;
01418 }
01419 for (i = 0; i < s->dcols; i++) {
01420 int ret, lastpk = -1, autoinccount = 0;
01421 char *sql;
01422
01423 if (!s->dyncols[i].table[0]) {
01424 continue;
01425 }
01426 if (flagp[i]) {
01427 continue;
01428 }
01429 sql = sqlite3_mprintf("PRAGMA table_info('%q')", s->dyncols[i].table);
01430 if (!sql) {
01431 continue;
01432 }
01433 dbtraceapi(d, "sqlite3_get_table", sql);
01434 ret = sqlite3_get_table(d->sqlite, sql, &rowp, &nrows, &ncols, NULL);
01435 sqlite3_free(sql);
01436 if (ret != SQLITE_OK) {
01437 continue;
01438 }
01439 k = findcol(rowp, ncols, "name");
01440 t = findcol(rowp, ncols, "type");
01441 pk = findcol(rowp, ncols, "pk");
01442 if (k < 0 || t < 0) {
01443 goto freet;
01444 }
01445 for (r = 1; r <= nrows; r++) {
01446 int m;
01447
01448 for (m = i; m < s->dcols; m++) {
01449 if (!flagp[m] &&
01450 strcmp(s->dyncols[m].column, rowp[r * ncols + k]) == 0 &&
01451 strcmp(s->dyncols[m].table, s->dyncols[i].table) == 0) {
01452 char *typename = rowp[r * ncols + t];
01453
01454 flagp[m] = 1;
01455 freep(&s->dyncols[m].typename);
01456 s->dyncols[m].typename = xstrdup(typename);
01457 s->dyncols[m].type =
01458 mapsqltype(typename, &s->dyncols[m].nosign, *s->ov3);
01459 getmd(typename, s->dyncols[m].type, &s->dyncols[m].size,
01460 NULL);
01461 #ifdef SQL_LONGVARCHAR
01462 if (s->dyncols[m].type == SQL_VARCHAR &&
01463 s->dyncols[m].size > 255) {
01464 s->dyncols[m].type = SQL_LONGVARCHAR;
01465 }
01466 #endif
01467 if (s->dyncols[i].type == SQL_VARBINARY &&
01468 s->dyncols[i].size > 255) {
01469 s->dyncols[i].type = SQL_LONGVARBINARY;
01470 }
01471 if (pk >= 0 && strcmp(rowp[r * ncols + pk], "1") == 0) {
01472 if (++autoinccount > 1) {
01473 if (lastpk >= 0) {
01474 s->dyncols[lastpk].autoinc = 0;
01475 lastpk = -1;
01476 }
01477 } else {
01478 lastpk = m;
01479 if (strlen(typename) == 7 &&
01480 strncasecmp(typename, "integer", 7) == 0) {
01481 s->dyncols[m].autoinc = 1;
01482 }
01483 }
01484 }
01485 }
01486 }
01487 }
01488 freet:
01489 sqlite3_free_table(rowp);
01490 }
01491 if (flagp != flags) {
01492 freep(&flagp);
01493 }
01494 }
01495
01503 static int
01504 getmdays(int year, int month)
01505 {
01506 static const int mdays[] = {
01507 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31
01508 };
01509 int mday;
01510
01511 if (month < 1) {
01512 return 0;
01513 }
01514 mday = mdays[(month - 1) % 12];
01515 if (mday == 28 && year % 4 == 0 &&
01516 (!(year % 100 == 0) || year % 400 == 0)) {
01517 mday++;
01518 }
01519 return mday;
01520 }
01521
01532 static int
01533 str2date(char *str, DATE_STRUCT *ds)
01534 {
01535 int i, err = 0;
01536 char *p, *q;
01537
01538 ds->year = ds->month = ds->day = 0;
01539 p = str;
01540 while (*p && !ISDIGIT(*p)) {
01541 ++p;
01542 }
01543 q = p;
01544 i = 0;
01545 while (*q && !ISDIGIT(*q)) {
01546 ++i;
01547 ++q;
01548 }
01549 if (i >= 8) {
01550 char buf[8];
01551
01552 strncpy(buf, p + 0, 4); buf[4] = '\0';
01553 ds->year = strtol(buf, NULL, 10);
01554 strncpy(buf, p + 4, 2); buf[2] = '\0';
01555 ds->month = strtol(buf, NULL, 10);
01556 strncpy(buf, p + 6, 2); buf[2] = '\0';
01557 ds->day = strtol(buf, NULL, 10);
01558 goto done;
01559 }
01560 i = 0;
01561 while (i < 3) {
01562 int n;
01563
01564 q = NULL;
01565 n = strtol(p, &q, 10);
01566 if (!q || q == p) {
01567 if (*q == '\0') {
01568 if (i == 0) {
01569 err = 1;
01570 }
01571 goto done;
01572 }
01573 }
01574 if (*q == '-' || *q == '/' || *q == '\0' || i == 2) {
01575 switch (i) {
01576 case 0: ds->year = n; break;
01577 case 1: ds->month = n; break;
01578 case 2: ds->day = n; break;
01579 }
01580 ++i;
01581 if (*q) {
01582 ++q;
01583 }
01584 } else {
01585 i = 0;
01586 while (*q && !ISDIGIT(*q)) {
01587 ++q;
01588 }
01589 }
01590 p = q;
01591 }
01592 done:
01593
01594 if (err ||
01595 ds->month < 1 || ds->month > 12 ||
01596 ds->day < 1 || ds->day > getmdays(ds->year, ds->month)) {
01597 return -1;
01598 }
01599 return 0;
01600 }
01601
01612 static int
01613 str2time(char *str, TIME_STRUCT *ts)
01614 {
01615 int i, err = 0;
01616 char *p, *q;
01617
01618 ts->hour = ts->minute = ts->second = 0;
01619 p = str;
01620 while (*p && !ISDIGIT(*p)) {
01621 ++p;
01622 }
01623 q = p;
01624 i = 0;
01625 while (*q && ISDIGIT(*q)) {
01626 ++i;
01627 ++q;
01628 }
01629 if (i >= 6) {
01630 char buf[4];
01631
01632 strncpy(buf, p + 0, 2); buf[2] = '\0';
01633 ts->hour = strtol(buf, NULL, 10);
01634 strncpy(buf, p + 2, 2); buf[2] = '\0';
01635 ts->minute = strtol(buf, NULL, 10);
01636 strncpy(buf, p + 4, 2); buf[2] = '\0';
01637 ts->second = strtol(buf, NULL, 10);
01638 goto done;
01639 }
01640 i = 0;
01641 while (i < 3) {
01642 int n;
01643
01644 q = NULL;
01645 n = strtol(p, &q, 10);
01646 if (!q || q == p) {
01647 if (*q == '\0') {
01648 if (i == 0) {
01649 err = 1;
01650 }
01651 goto done;
01652 }
01653 }
01654 if (*q == ':' || *q == '\0' || i == 2) {
01655 switch (i) {
01656 case 0: ts->hour = n; break;
01657 case 1: ts->minute = n; break;
01658 case 2: ts->second = n; break;
01659 }
01660 ++i;
01661 if (*q) {
01662 ++q;
01663 }
01664 } else {
01665 i = 0;
01666 while (*q && !ISDIGIT(*q)) {
01667 ++q;
01668 }
01669 }
01670 p = q;
01671 }
01672 done:
01673
01674 if (err || ts->hour > 23 || ts->minute > 59 || ts->second > 59) {
01675 return -1;
01676 }
01677 return 0;
01678 }
01679
01695 static int
01696 str2timestamp(char *str, TIMESTAMP_STRUCT *tss)
01697 {
01698 int i, m, n, err = 0;
01699 char *p, *q, in = '\0';
01700
01701 tss->year = tss->month = tss->day = 0;
01702 tss->hour = tss->minute = tss->second = 0;
01703 tss->fraction = 0;
01704 p = str;
01705 while (*p && !ISDIGIT(*p)) {
01706 ++p;
01707 }
01708 q = p;
01709 i = 0;
01710 while (*q && ISDIGIT(*q)) {
01711 ++i;
01712 ++q;
01713 }
01714 if (i >= 14) {
01715 char buf[16];
01716
01717 strncpy(buf, p + 0, 4); buf[4] = '\0';
01718 tss->year = strtol(buf, NULL, 10);
01719 strncpy(buf, p + 4, 2); buf[2] = '\0';
01720 tss->month = strtol(buf, NULL, 10);
01721 strncpy(buf, p + 6, 2); buf[2] = '\0';
01722 tss->day = strtol(buf, NULL, 10);
01723 strncpy(buf, p + 8, 2); buf[2] = '\0';
01724 tss->hour = strtol(buf, NULL, 10);
01725 strncpy(buf, p + 10, 2); buf[2] = '\0';
01726 tss->minute = strtol(buf, NULL, 10);
01727 strncpy(buf, p + 12, 2); buf[2] = '\0';
01728 tss->second = strtol(buf, NULL, 10);
01729 if (i > 14) {
01730 m = i - 14;
01731 strncpy(buf, p + 14, m);
01732 while (m < 9) {
01733 buf[m] = '0';
01734 ++m;
01735 }
01736 buf[m] = '\0';
01737 tss->fraction = strtol(buf, NULL, 0);
01738 }
01739 m = 7;
01740 goto done;
01741 }
01742 m = i = 0;
01743 while ((m & 7) != 7) {
01744 q = NULL;
01745 n = strtol(p, &q, 10);
01746 if (!q || q == p) {
01747 if (*q == '\0') {
01748 if (m < 1) {
01749 err = 1;
01750 }
01751 goto done;
01752 }
01753 }
01754 if (in == '\0') {
01755 switch (*q) {
01756 case '-':
01757 case '/':
01758 if ((m & 1) == 0) {
01759 in = *q;
01760 i = 0;
01761 }
01762 break;
01763 case ':':
01764 if ((m & 2) == 0) {
01765 in = *q;
01766 i = 0;
01767 }
01768 break;
01769 case ' ':
01770 case '.':
01771 break;
01772 default:
01773 in = '\0';
01774 i = 0;
01775 break;
01776 }
01777 }
01778 switch (in) {
01779 case '-':
01780 case '/':
01781 switch (i) {
01782 case 0: tss->year = n; break;
01783 case 1: tss->month = n; break;
01784 case 2: tss->day = n; break;
01785 }
01786 if (++i >= 3) {
01787 i = 0;
01788 m |= 1;
01789 if (!(m & 2)) {
01790 m |= 8;
01791 }
01792 goto skip;
01793 } else {
01794 ++q;
01795 }
01796 break;
01797 case ':':
01798 switch (i) {
01799 case 0: tss->hour = n; break;
01800 case 1: tss->minute = n; break;
01801 case 2: tss->second = n; break;
01802 }
01803 if (++i >= 3) {
01804 i = 0;
01805 m |= 2;
01806 if (*q == '.') {
01807 in = '.';
01808 goto skip2;
01809 }
01810 if (*q == ' ') {
01811 if ((m & 1) == 0) {
01812 char *e = NULL;
01813
01814 strtol(q + 1, &e, 10);
01815 if (e && *e == '-') {
01816 goto skip;
01817 }
01818 }
01819 in = '.';
01820 goto skip2;
01821 }
01822 goto skip;
01823 } else {
01824 ++q;
01825 }
01826 break;
01827 case '.':
01828 if (++i >= 1) {
01829 int ndig = q - p;
01830
01831 if (p[0] == '+' || p[0] == '-') {
01832 ndig--;
01833 }
01834 while (ndig < 9) {
01835 n = n * 10;
01836 ++ndig;
01837 }
01838 tss->fraction = n;
01839 m |= 4;
01840 i = 0;
01841 }
01842 default:
01843 skip:
01844 in = '\0';
01845 skip2:
01846 while (*q && !ISDIGIT(*q)) {
01847 ++q;
01848 }
01849 }
01850 p = q;
01851 }
01852 if ((m & 7) > 1 && (m & 8)) {
01853
01854 if (p > str && ISDIGIT(*p)) {
01855 int nn, sign;
01856
01857 q = p - 1;
01858 if (*q != '+' && *q != '-') {
01859 goto done;
01860 }
01861 sign = *q == '+' ? -1 : 1;
01862 q = NULL;
01863 n = strtol(p, &q, 10);
01864 if (!q || *q++ != ':' || !ISDIGIT(*q)) {
01865 goto done;
01866 }
01867 p = q;
01868 q = NULL;
01869 nn = strtol(p, &q, 0);
01870 tss->minute += nn * sign;
01871 if ((SQLSMALLINT) tss->minute < 0) {
01872 tss->hour -= 1;
01873 tss->minute += 60;
01874 } else if (tss->minute >= 60) {
01875 tss->hour += 1;
01876 tss->minute -= 60;
01877 }
01878 tss->hour += n * sign;
01879 if ((SQLSMALLINT) tss->hour < 0) {
01880 tss->day -= 1;
01881 tss->hour += 24;
01882 } else if (tss->hour >= 24) {
01883 tss->day += 1;
01884 tss->hour -= 24;
01885 }
01886 if ((short) tss->day < 1 || tss->day >= 28) {
01887 int mday, pday, pmon;
01888
01889 mday = getmdays(tss->year, tss->month);
01890 pmon = tss->month - 1;
01891 if (pmon < 1) {
01892 pmon = 12;
01893 }
01894 pday = getmdays(tss->year, pmon);
01895 if ((SQLSMALLINT) tss->day < 1) {
01896 tss->month -= 1;
01897 tss->day = pday;
01898 } else if (tss->day > mday) {
01899 tss->month += 1;
01900 tss->day = 1;
01901 }
01902 if ((SQLSMALLINT) tss->month < 1) {
01903 tss->year -= 1;
01904 tss->month = 12;
01905 } else if (tss->month > 12) {
01906 tss->year += 1;
01907 tss->month = 1;
01908 }
01909 }
01910 }
01911 }
01912 done:
01913
01914 if (err ||
01915 tss->month < 1 || tss->month > 12 ||
01916 tss->day < 1 || tss->day > getmdays(tss->year, tss->month) ||
01917 tss->hour > 23 || tss->minute > 60 || tss->second > 60) {
01918 return -1;
01919 }
01920 return (m & 7) < 1 ? -1 : 0;
01921 }
01922
01929 static int
01930 getbool(char *string)
01931 {
01932 if (string) {
01933 return string[0] && strchr("Yy123456789Tt", string[0]) != NULL;
01934 }
01935 return 0;
01936 }
01937
01943 static void
01944 dbtrace(void *arg, const char *msg)
01945 {
01946 DBC *d = (DBC *) arg;
01947
01948 if (msg && d->trace) {
01949 int len = strlen(msg);
01950
01951 if (len > 0) {
01952 char *end = "\n";
01953
01954 if (msg[len - 1] != ';') {
01955 end = ";\n";
01956 }
01957 fprintf(d->trace, "%s%s", msg, end);
01958 fflush(d->trace);
01959 }
01960 }
01961 }
01962
01963
01964
01965 static void
01966 dbtraceapi(DBC *d, char *fn, const char *sql)
01967 {
01968 if (fn && d->trace) {
01969 if (sql) {
01970 fprintf(d->trace, "-- %s: %s\n", fn, sql);
01971 } else {
01972 fprintf(d->trace, "-- %s\n", fn);
01973 }
01974 fflush(d->trace);
01975 }
01976 }
01977
01984 static void
01985 dbtracerc(DBC *d, int rc, char *err)
01986 {
01987 if (rc != SQLITE_OK && d->trace) {
01988 fprintf(d->trace, "-- SQLITE ERROR CODE %d", rc);
01989 fprintf(d->trace, err ? ": %s\n" : "\n", err);
01990 fflush(d->trace);
01991 }
01992 }
01993
02006 static SQLRETURN
02007 dbopen(DBC *d, char *name, char *dsn, char *sflag, char *spflag, char *ntflag,
02008 char *busy)
02009 {
02010 char *endp = NULL;
02011 int rc, tmp, busyto = 1000;
02012
02013 if (d->sqlite) {
02014 if (d->trace) {
02015 fprintf(d->trace, "-- sqlite3_close (deferred): '%s'\n",
02016 d->dbname);
02017 fflush(d->trace);
02018 }
02019 sqlite3_close(d->sqlite);
02020 d->sqlite = NULL;
02021 }
02022 rc = sqlite3_open(name, &d->sqlite);
02023 if (rc != SQLITE_OK) {
02024 connfail:
02025 setstatd(d, rc, "connect failed", (*d->ov3) ? "HY000" : "S1000");
02026 return SQL_ERROR;
02027 }
02028 if (d->trace) {
02029 sqlite3_trace(d->sqlite, dbtrace, d);
02030 }
02031 d->step_enable = getbool(sflag);
02032 d->trans_disable = getbool(ntflag);
02033 d->curtype = d->step_enable ?
02034 SQL_CURSOR_FORWARD_ONLY : SQL_CURSOR_STATIC;
02035 tmp = strtol(busy, &endp, 0);
02036 if (endp && *endp == '\0' && endp != busy) {
02037 busyto = tmp;
02038 }
02039 if (busyto < 1 || busyto > 1000000) {
02040 busyto = 1000000;
02041 }
02042 d->timeout = busyto;
02043 if (setsqliteopts(d->sqlite, d) != SQLITE_OK) {
02044 if (d->trace) {
02045 fprintf(d->trace, "-- sqlite3_close: '%s'\n",
02046 d->dbname);
02047 fflush(d->trace);
02048 }
02049 sqlite3_close(d->sqlite);
02050 d->sqlite = NULL;
02051 goto connfail;
02052 }
02053 if (spflag && spflag[0] != '\0') {
02054 char syncp[128];
02055
02056 sprintf(syncp, "PRAGMA synchronous = %8.8s;", spflag);
02057 sqlite3_exec(d->sqlite, syncp, NULL, NULL, NULL);
02058 }
02059 freep(&d->dbname);
02060 d->dbname = xstrdup(name);
02061 freep(&d->dsn);
02062 d->dsn = xstrdup(dsn);
02063 if (d->trace) {
02064 fprintf(d->trace, "-- sqlite3_open: '%s'\n", d->dbname);
02065 fflush(d->trace);
02066 }
02067 return SQL_SUCCESS;
02068 }
02069
02078 static char *
02079 s3stmt_coltype(sqlite3_stmt *s3stmt, int col, DBC *d)
02080 {
02081 int guessed = 0;
02082 char *typename = (char *) sqlite3_column_decltype(s3stmt, col);
02083
02084 if (!typename) {
02085 guessed++;
02086 switch (sqlite3_column_type(s3stmt, col)) {
02087 case SQLITE_INTEGER: typename = "integer"; break;
02088 case SQLITE_FLOAT: typename = "double"; break;
02089 default:
02090 case SQLITE_TEXT: typename = "varchar"; break;
02091 case SQLITE_BLOB: typename = "blob"; break;
02092 #if 0
02093 case SQLITE_NULL: typename = "null"; break;
02094 #endif
02095 }
02096 }
02097 if (d->trace) {
02098 fprintf(d->trace, "-- column %d type%s: '%s'\n", col + 1,
02099 guessed ? " (guessed)" : "", typename);
02100 fflush(d->trace);
02101 }
02102 return typename;
02103 }
02104
02111 static int
02112 s3stmt_step(STMT *s)
02113 {
02114 DBC *d = (DBC *) s->dbc;
02115 char **rowd = NULL;
02116 const char *errp = NULL;
02117 int i, ncols, rc;
02118
02119 if (s != d->cur_s3stmt || !s->s3stmt) {
02120 setstat(s, -1, "stale statement", (*s->ov3) ? "HY000" : "S1000");
02121 return SQL_ERROR;
02122 }
02123 rc = sqlite3_step(s->s3stmt);
02124 if (rc == SQLITE_ROW || rc == SQLITE_DONE) {
02125 ++d->s3stmt_rownum;
02126 ncols = sqlite3_column_count(s->s3stmt);
02127 if (d->s3stmt_rownum == 0 && ncols > 0) {
02128 int size;
02129 char *p;
02130 COL *dyncols;
02131 const char *colname, *typename;
02132
02133 for (i = size = 0; i < ncols; i++) {
02134 colname = sqlite3_column_name(s->s3stmt, i);
02135 size += 3 + 3 * strlen(colname);
02136 }
02137 dyncols = xmalloc(ncols * sizeof (COL) + size);
02138 if (!dyncols) {
02139 freedyncols(s);
02140 s->ncols = 0;
02141 dbtraceapi(d, "sqlite3_finalize", 0);
02142 sqlite3_finalize(s->s3stmt);
02143 s->s3stmt = NULL;
02144 d->cur_s3stmt = NULL;
02145 return nomem(s);
02146 }
02147 p = (char *) (dyncols + ncols);
02148 for (i = 0; i < ncols; i++) {
02149 char *q;
02150
02151 colname = sqlite3_column_name(s->s3stmt, i);
02152 if (d->trace) {
02153 fprintf(d->trace, "-- column %d name: '%s'\n",
02154 i + 1, colname);
02155 fflush(d->trace);
02156 }
02157 typename = s3stmt_coltype(s->s3stmt, i, d);
02158 dyncols[i].db = ((DBC *) (s->dbc))->dbname;
02159 strcpy(p, colname);
02160 dyncols[i].label = p;
02161 p += strlen(p) + 1;
02162 q = strchr(colname, '.');
02163 if (q) {
02164 char *q2 = strchr(q + 1, '.');
02165
02166
02167 if (q2) {
02168 q = q2;
02169 }
02170 }
02171 if (q) {
02172 dyncols[i].table = p;
02173 strncpy(p, colname, q - colname);
02174 p[q - colname] = '\0';
02175 p += strlen(p) + 1;
02176 strcpy(p, q + 1);
02177 dyncols[i].column = p;
02178 p += strlen(p) + 1;
02179 } else {
02180 dyncols[i].table = "";
02181 strcpy(p, colname);
02182 dyncols[i].column = p;
02183 p += strlen(p) + 1;
02184 }
02185 if (s->longnames) {
02186 dyncols[i].column = dyncols[i].label;
02187 }
02188 #ifdef SQL_LONGVARCHAR
02189 dyncols[i].type = SQL_LONGVARCHAR;
02190 dyncols[i].size = 65536;
02191 #else
02192 dyncols[i].type = SQL_VARCHAR;
02193 dyncols[i].size = 255;
02194 #endif
02195 dyncols[i].index = i;
02196 dyncols[i].scale = 0;
02197 dyncols[i].prec = 0;
02198 dyncols[i].nosign = 1;
02199 dyncols[i].autoinc = -1;
02200 dyncols[i].typename = xstrdup(typename);
02201 }
02202 freedyncols(s);
02203 s->ncols = s->dcols = ncols;
02204 s->dyncols = s->cols = dyncols;
02205 fixupdyncols(s, d);
02206 mkbindcols(s, s->ncols);
02207 }
02208 if (ncols <= 0) {
02209 goto killstmt;
02210 }
02211 if (rc == SQLITE_DONE) {
02212 freeresult(s, 0);
02213 s->nrows = 0;
02214 dbtraceapi(d, "sqlite3_finalize", 0);
02215 sqlite3_finalize(s->s3stmt);
02216 s->s3stmt = NULL;
02217 d->cur_s3stmt = NULL;
02218 return SQL_SUCCESS;
02219 }
02220 rowd = xmalloc((1 + 2 * ncols) * sizeof (char *));
02221 if (rowd) {
02222 const unsigned char *value;
02223
02224 rowd[0] = (char *) (ncols * 2);
02225 ++rowd;
02226 for (i = 0; i < ncols; i++) {
02227 int coltype = sqlite3_column_type(s->s3stmt, i);
02228
02229 rowd[i] = NULL;
02230 if (coltype == SQLITE_BLOB) {
02231 int k, nbytes = sqlite3_column_bytes(s->s3stmt, i);
02232 char *qp;
02233 unsigned const char *bp;
02234
02235 bp = sqlite3_column_blob(s->s3stmt, i);
02236 qp = xmalloc(nbytes * 2 + 4);
02237 if (qp) {
02238 rowd[i + ncols] = qp;
02239 *qp++ = 'X';
02240 *qp++ = '\'';
02241 for (k = 0; k < nbytes; k++) {
02242 *qp++ = xdigits[(bp[k] >> 4)];
02243 *qp++ = xdigits[(bp[k] & 0xF)];
02244 }
02245 *qp++ = '\'';
02246 *qp = '\0';
02247 }
02248 } else if (coltype != SQLITE_NULL) {
02249 value = sqlite3_column_text(s->s3stmt, i);
02250 rowd[i + ncols] = xstrdup((char *) value);
02251 }
02252 }
02253 for (i = 0; i < ncols; i++) {
02254 int coltype = sqlite3_column_type(s->s3stmt, i);
02255
02256 value = NULL;
02257 if (coltype == SQLITE_BLOB) {
02258 value = sqlite3_column_blob(s->s3stmt, i);
02259 } else if (coltype != SQLITE_NULL) {
02260 value = sqlite3_column_text(s->s3stmt, i);
02261 }
02262 if (value && !rowd[i + ncols]) {
02263 freerows(rowd);
02264 rowd = 0;
02265 break;
02266 }
02267 }
02268 }
02269 if (rowd) {
02270 freeresult(s, 0);
02271 s->nrows = 1;
02272 s->rows = rowd;
02273 s->rowfree = freerows;
02274 if (rc == SQLITE_DONE) {
02275 dbtraceapi(d, "sqlite3_finalize", 0);
02276 sqlite3_finalize(s->s3stmt);
02277 s->s3stmt = NULL;
02278 d->cur_s3stmt = NULL;
02279 }
02280 return SQL_SUCCESS;
02281 }
02282 }
02283 killstmt:
02284 dbtraceapi(d, "sqlite3_finalize", 0);
02285 rc = sqlite3_finalize(s->s3stmt);
02286 errp = sqlite3_errmsg(d->sqlite);
02287 s->s3stmt = NULL;
02288 d->cur_s3stmt = NULL;
02289 setstat(s, rc, "%s (%d)", (*s->ov3) ? "HY000" : "S1000",
02290 errp ? errp : "unknown error", rc);
02291 return SQL_ERROR;
02292 }
02293
02299 static void
02300 s3stmt_end(STMT *s)
02301 {
02302 DBC *d;
02303
02304 if (!s || !s->s3stmt) {
02305 return;
02306 }
02307 d = (DBC *) s->dbc;
02308 dbtraceapi(d, "sqlite3_finalize", 0);
02309 sqlite3_finalize(s->s3stmt);
02310 s->s3stmt = NULL;
02311 d->cur_s3stmt = NULL;
02312 }
02313
02319 static void
02320 s3stmt_end_if(STMT *s)
02321 {
02322 DBC *d = (DBC *) s->dbc;
02323
02324 if (d && d->cur_s3stmt == s) {
02325 s3stmt_end(s);
02326 }
02327 }
02328
02336 static SQLRETURN
02337 s3stmt_start(STMT *s, char **params)
02338 {
02339 DBC *d = (DBC *) s->dbc;
02340 char *sql = NULL;
02341 const char *endp;
02342 sqlite3_stmt *s3stmt = NULL;
02343 int rc;
02344
02345 #ifdef CANT_PASS_VALIST_AS_CHARPTR
02346
02347 sql = sqlite3_mprintf(s->query,
02348 params[0], params[1],
02349 params[2], params[3],
02350 params[4], params[5],
02351 params[6], params[7],
02352 params[8], params[9],
02353 params[10], params[11],
02354 params[12], params[13],
02355 params[14], params[15],
02356 params[16], params[17],
02357 params[18], params[19],
02358 params[20], params[21],
02359 params[22], params[23],
02360 params[24], params[25],
02361 params[26], params[27],
02362 params[28], params[29],
02363 params[30], params[31]);
02364 #else
02365 sql = sqlite3_vmprintf((char *) s->query, (char *) params);
02366 #endif
02367 if (!sql) {
02368 return nomem(s);
02369 }
02370 dbtraceapi(d, "sqlite3_prepare", sql);
02371 rc = sqlite3_prepare(d->sqlite, sql, -1, &s3stmt, &endp);
02372 dbtracerc(d, rc, NULL);
02373 sqlite3_free(sql);
02374 if (rc != SQLITE_OK) {
02375 if (s3stmt) {
02376 dbtraceapi(d, "sqlite3_finalize", NULL);
02377 sqlite3_finalize(s3stmt);
02378 }
02379 setstat(s, rc, "%s (%d)", (*s->ov3) ? "HY000" : "S1000",
02380 sqlite3_errmsg(d->sqlite), rc);
02381 return SQL_ERROR;
02382 }
02383 s->s3stmt = s3stmt;
02384 d->cur_s3stmt = s;
02385 d->s3stmt_rownum = -1;
02386 return SQL_SUCCESS;
02387 }
02388
02393 SQLRETURN SQL_API
02394 SQLBulkOperations(SQLHSTMT stmt, SQLSMALLINT oper)
02395 {
02396 return drvunimplstmt(stmt);
02397 }
02398
02403 SQLRETURN SQL_API
02404 SQLDataSources(SQLHENV env, SQLUSMALLINT dir, SQLCHAR *srvname,
02405 SQLSMALLINT buflen1, SQLSMALLINT *lenp1,
02406 SQLCHAR *desc, SQLSMALLINT buflen2, SQLSMALLINT *lenp2)
02407 {
02408 if (env == SQL_NULL_HENV) {
02409 return SQL_INVALID_HANDLE;
02410 }
02411 return SQL_ERROR;
02412 }
02413
02418 SQLRETURN SQL_API
02419 SQLDrivers(SQLHENV env, SQLUSMALLINT dir, SQLCHAR *drvdesc,
02420 SQLSMALLINT descmax, SQLSMALLINT *desclenp,
02421 SQLCHAR *drvattr, SQLSMALLINT attrmax, SQLSMALLINT *attrlenp)
02422 {
02423 if (env == SQL_NULL_HENV) {
02424 return SQL_INVALID_HANDLE;
02425 }
02426 return SQL_ERROR;
02427 }
02428
02433 SQLRETURN SQL_API
02434 SQLBrowseConnect(SQLHDBC dbc, SQLCHAR *connin, SQLSMALLINT conninLen,
02435 SQLCHAR *connout, SQLSMALLINT connoutMax,
02436 SQLSMALLINT *connoutLen)
02437 {
02438 return drvunimpldbc(dbc);
02439 }
02440
02449 SQLRETURN SQL_API
02450 SQLPutData(SQLHSTMT stmt, SQLPOINTER data, SQLLEN len)
02451 {
02452 STMT *s;
02453 int i, dlen, done = 0;
02454 BINDPARM *p;
02455
02456 if (stmt == SQL_NULL_HSTMT) {
02457 return SQL_INVALID_HANDLE;
02458 }
02459 s = (STMT *) stmt;
02460 if (!s->query || s->nparams <= 0) {
02461 seqerr:
02462 setstat(s, -1, "sequence error", "HY010");
02463 return SQL_ERROR;
02464 }
02465 for (i = 0; i < s->nparams; i++) {
02466 p = &s->bindparms[i];
02467 if (p->need > 0) {
02468 int type = mapdeftype(p->type, p->stype, -1);
02469
02470 if (len == SQL_NULL_DATA) {
02471 freep(&p->parbuf);
02472 p->param = NULL;
02473 p->len = SQL_NULL_DATA;
02474 p->need = -1;
02475 } else if (type != SQL_C_CHAR && type != SQL_C_BINARY) {
02476 int size = 0;
02477
02478 switch (type) {
02479 case SQL_C_TINYINT:
02480 case SQL_C_UTINYINT:
02481 case SQL_C_STINYINT:
02482 #ifdef SQL_BIT
02483 case SQL_C_BIT:
02484 #endif
02485 size = sizeof (char);
02486 break;
02487 case SQL_C_SHORT:
02488 case SQL_C_USHORT:
02489 case SQL_C_SSHORT:
02490 size = sizeof (short);
02491 break;
02492 case SQL_C_LONG:
02493 case SQL_C_ULONG:
02494 case SQL_C_SLONG:
02495 size = sizeof (long);
02496 break;
02497 #ifdef SQL_BIGINT
02498 case SQL_C_UBIGINT:
02499 case SQL_C_SBIGINT:
02500 size = sizeof (SQLBIGINT);
02501 break;
02502 #endif
02503 case SQL_C_FLOAT:
02504 size = sizeof (float);
02505 break;
02506 case SQL_C_DOUBLE:
02507 size = sizeof (double);
02508 break;
02509 #ifdef SQL_C_TYPE_DATE
02510 case SQL_C_TYPE_DATE:
02511 #endif
02512 case SQL_C_DATE:
02513 size = sizeof (DATE_STRUCT);
02514 break;
02515 #ifdef SQL_C_TYPE_DATE
02516 case SQL_C_TYPE_TIME:
02517 #endif
02518 case SQL_C_TIME:
02519 size = sizeof (TIME_STRUCT);
02520 break;
02521 #ifdef SQL_C_TYPE_DATE
02522 case SQL_C_TYPE_TIMESTAMP:
02523 #endif
02524 case SQL_C_TIMESTAMP:
02525 size = sizeof (TIMESTAMP_STRUCT);
02526 break;
02527 }
02528 freep(&p->parbuf);
02529 p->parbuf = xmalloc(size);
02530 if (!p->parbuf) {
02531 return nomem(s);
02532 }
02533 p->param = p->parbuf;
02534 memcpy(p->param, data, size);
02535 p->len = size;
02536 p->need = -1;
02537 } else if (type == SQL_C_CHAR && len == SQL_NTS) {
02538 char *dp = data;
02539
02540 dlen = strlen(dp);
02541 freep(&p->parbuf);
02542 p->parbuf = xmalloc(dlen + 1);
02543 if (!p->parbuf) {
02544 return nomem(s);
02545 }
02546 p->param = p->parbuf;
02547 strcpy(p->param, dp);
02548 p->len = dlen;
02549 p->need = -1;
02550 } else if (len <= 0) {
02551 setstat(s, -1, "invalid length", "HY090");
02552 return SQL_ERROR;
02553 } else {
02554 dlen = min(p->len - p->offs, len);
02555 if (!p->param) {
02556 setstat(s, -1, "no memory for parameter", "HY013");
02557 return SQL_ERROR;
02558 }
02559 memcpy((char *) p->param + p->offs, data, dlen);
02560 p->offs += dlen;
02561 if (p->offs >= p->len) {
02562 *((char *) p->param + p->len) = '\0';
02563 p->need = (type == SQL_C_CHAR) ? -1 : 0;
02564 }
02565 }
02566 done = 1;
02567 break;
02568 }
02569 }
02570 if (!done) {
02571 goto seqerr;
02572 }
02573 return SQL_SUCCESS;
02574 }
02575
02581 static SQLRETURN
02582 freeparams(STMT *s)
02583 {
02584 if (s->bindparms) {
02585 int n;
02586
02587 for (n = 0; n < s->nbindparms; n++) {
02588 freep(&s->bindparms[n].parbuf);
02589 memset(&s->bindparms[n], 0, sizeof (BINDPARM));
02590 }
02591 }
02592 return SQL_SUCCESS;
02593 }
02594
02595
02596
02597 static SQLRETURN
02598 substparam(STMT *s, char **sqlp, int pnum, char **outp)
02599 {
02600 char *outdata = NULL, *sql = NULL;
02601 int type, len = 0, isnull = 0, needalloc = 0;
02602 BINDPARM *p;
02603 double dval;
02604
02605 if (!s->bindparms || pnum < 0 || pnum >= s->nbindparms) {
02606 goto error;
02607 }
02608 if (sqlp) {
02609 char *q;
02610
02611 sql = *sqlp;
02612 q = sql;
02613 while (1) {
02614 q = strchr(q, '%');
02615 if (!q) {
02616 sql = *sqlp = q;
02617 break;
02618 }
02619 ++q;
02620 if (*q == 'q' || *q == 'Q' || *q == 's') {
02621 sql = *sqlp = q;
02622 break;
02623 }
02624 }
02625 }
02626 p = &s->bindparms[pnum];
02627 type = mapdeftype(p->type, p->stype, -1);
02628 if (p->need > 0) {
02629 if (!p->parbuf) {
02630 p->len = SQL_LEN_DATA_AT_EXEC(*p->lenp);
02631 if (p->len <= 0 && p->len != SQL_NTS && p->len != SQL_NULL_DATA) {
02632 setstat(s, -1, "invalid length", "HY009");
02633 return SQL_ERROR;
02634 }
02635 if (p->len > 0) {
02636 p->parbuf = xmalloc(p->len + 1);
02637 if (!p->parbuf) {
02638 return nomem(s);
02639 }
02640 p->param = p->parbuf;
02641 } else {
02642 p->param = NULL;
02643 }
02644 }
02645 return SQL_NEED_DATA;
02646 }
02647 p->strbuf[0] = '\0';
02648 if (!p->param || (p->lenp && *p->lenp == SQL_NULL_DATA)) {
02649 isnull = 1;
02650 goto bind;
02651 }
02652 switch (type) {
02653 case SQL_C_BINARY: {
02654 char *param, *pp;
02655 int i;
02656
02657 if (p->need < 0 && p->parbuf == p->param) {
02658 outdata = p->param;
02659 if (sql) {
02660 *sql = 's';
02661 }
02662 goto putp;
02663 }
02664 if (p->param == p->parbuf) {
02665 param = p->param;
02666 len = p->len;
02667 if ((param[0] == 'x' || param[0] == 'X') &&
02668 param[1] == '\'' &&
02669 param[len - 1] == '\'') {
02670 break;
02671 }
02672 }
02673 if (!p->lenp) {
02674 len = p->len;
02675 } else {
02676 len = *p->lenp;
02677 if (len <= SQL_LEN_DATA_AT_EXEC_OFFSET) {
02678 len = SQL_LEN_DATA_AT_EXEC(len);
02679 }
02680 }
02681 if (len < 0) {
02682 setstat(s, -1, "invalid length", "HY009");
02683 return SQL_ERROR;
02684 }
02685 param = xmalloc(len * 2 + 4);
02686 if (!param) {
02687 return nomem(s);
02688 }
02689 pp = param;
02690 *pp++ = 'x';
02691 *pp++ = '\'';
02692 for (i = 0; i < len; i++) {
02693 *pp++ = xdigits[(((char *) p->param)[i] >> 4) & 0xF];
02694 *pp++ = xdigits[((char *) p->param)[i] & 0xF];
02695 }
02696 *pp++ = '\'';
02697 *pp++ = '\0';
02698 freep(&p->parbuf);
02699 p->parbuf = p->param = param;
02700 p->len = len * 2 + 4 - 1;
02701 p->max = p->len;
02702 p->need = -1;
02703 if (sql) {
02704 *sql = 's';
02705 }
02706 break;
02707 }
02708 case SQL_C_CHAR:
02709 if (sql) {
02710 *sql = 'Q';
02711 }
02712 break;
02713 case SQL_C_UTINYINT:
02714 sprintf(p->strbuf, "%d", *((unsigned char *) p->param));
02715 goto bind;
02716 case SQL_C_TINYINT:
02717 case SQL_C_STINYINT:
02718 sprintf(p->strbuf, "%d", *((char *) p->param));
02719 goto bind;
02720 case SQL_C_USHORT:
02721 sprintf(p->strbuf, "%d", *((unsigned short *) p->param));
02722 goto bind;
02723 case SQL_C_SHORT:
02724 case SQL_C_SSHORT:
02725 sprintf(p->strbuf, "%d", *((short *) p->param));
02726 goto bind;
02727 case SQL_C_ULONG:
02728 case SQL_C_LONG:
02729 case SQL_C_SLONG:
02730 sprintf(p->strbuf, "%ld", *((long *) p->param));
02731 goto bind;
02732 #ifdef SQL_BIT
02733 case SQL_C_BIT:
02734 strcpy(p->strbuf, (*((unsigned char *) p->param)) ? "1" : "0");
02735 goto bind;
02736 #endif
02737 #ifdef SQL_BIGINT
02738 case SQL_C_SBIGINT:
02739 #ifdef _WIN32
02740 sprintf(p->strbuf, "%I64d", *(SQLBIGINT *) p->param);
02741 #else
02742 sprintf(p->strbuf, "%lld", *(SQLBIGINT *) p->param);
02743 #endif
02744 goto bind;
02745 case SQL_C_UBIGINT:
02746 #ifdef _WIN32
02747 sprintf(p->strbuf, "%I64u", *(SQLUBIGINT *) p->param);
02748 #else
02749 sprintf(p->strbuf, "%llu", *(SQLUBIGINT *) p->param);
02750 #endif
02751 goto bind;
02752 #endif
02753 case SQL_C_FLOAT:
02754 dval = *((float *) p->param);
02755 goto dodouble;
02756 case SQL_C_DOUBLE:
02757 dval = *((double *) p->param);
02758 dodouble: {
02759 char *buf2 = sqlite3_mprintf("%.16g", dval);
02760
02761 if (buf2) {
02762 strcpy(p->strbuf, buf2);
02763 sqlite3_free(buf2);
02764 } else {
02765 isnull = 1;
02766 }
02767 goto bind;
02768 }
02769 #ifdef SQL_C_TYPE_DATE
02770 case SQL_C_TYPE_DATE:
02771 #endif
02772 case SQL_C_DATE:
02773 sprintf(p->strbuf, "%04d-%02d-%02d",
02774 ((DATE_STRUCT *) p->param)->year,
02775 ((DATE_STRUCT *) p->param)->month,
02776 ((DATE_STRUCT *) p->param)->day);
02777 goto bind;
02778 #ifdef SQL_C_TYPE_TIME
02779 case SQL_C_TYPE_TIME:
02780 #endif
02781 case SQL_C_TIME:
02782 sprintf(p->strbuf, "%02d:%02d:%02d",
02783 ((TIME_STRUCT *) p->param)->hour,
02784 ((TIME_STRUCT *) p->param)->minute,
02785 ((TIME_STRUCT *) p->param)->second);
02786 goto bind;
02787 #ifdef SQL_C_TYPE_TIMESTAMP
02788 case SQL_C_TYPE_TIMESTAMP:
02789 #endif
02790 case SQL_C_TIMESTAMP:
02791 sprintf(p->strbuf, "%04d-%02d-%02d %02d:%02d:%02d.%d",
02792 ((TIMESTAMP_STRUCT *) p->param)->year,
02793 ((TIMESTAMP_STRUCT *) p->param)->month,
02794 ((TIMESTAMP_STRUCT *) p->param)->day,
02795 ((TIMESTAMP_STRUCT *) p->param)->hour,
02796 ((TIMESTAMP_STRUCT *) p->param)->minute,
02797 ((TIMESTAMP_STRUCT *) p->param)->second,
02798 (int) ((TIMESTAMP_STRUCT *) p->param)->fraction);
02799 bind:
02800 if (sql) {
02801 *sql = 'Q';
02802 }
02803 if (outp) {
02804 *outp = isnull ? NULL : p->strbuf;
02805 }
02806 return SQL_SUCCESS;
02807 default:
02808 error:
02809 setstat(s, -1, "invalid parameter", (*s->ov3) ? "07009" : "S1093");
02810 return SQL_ERROR;
02811 }
02812 if (!p->parbuf && p->lenp) {
02813 if (p->type == SQL_C_CHAR) {
02814 if (*p->lenp == SQL_NTS) {
02815 p->len = p->max = strlen(p->param);
02816 } else if (*p->lenp >= 0) {
02817 p->len = p->max = *p->lenp;
02818 needalloc = 1;
02819 }
02820 }
02821 }
02822 if (p->need < 0 && p->parbuf == p->param) {
02823 outdata = p->param;
02824 goto putp;
02825 }
02826 if (p->type == SQL_C_CHAR) {
02827 outdata = p->param;
02828 if (needalloc) {
02829 char *dp;
02830
02831 freep(&p->parbuf);
02832 dp = xmalloc(p->len + 1);
02833 if (!dp) {
02834 return nomem(s);
02835 }
02836 memcpy(dp, p->param, p->len);
02837 dp[p->len] = '\0';
02838 p->parbuf = p->param = dp;
02839 outdata = p->param;
02840 }
02841 } else {
02842 outdata = p->param;
02843 }
02844 putp:
02845 if (outp) {
02846 *outp = outdata;
02847 }
02848 return SQL_SUCCESS;
02849 }
02850
02866 static SQLRETURN
02867 drvbindparam(SQLHSTMT stmt, SQLUSMALLINT pnum, SQLSMALLINT iotype,
02868 SQLSMALLINT buftype, SQLSMALLINT ptype, SQLUINTEGER coldef,
02869 SQLSMALLINT scale,
02870 SQLPOINTER data, SQLINTEGER buflen, SQLLEN *len)
02871 {
02872 STMT *s;
02873 BINDPARM *p;
02874
02875 if (stmt == SQL_NULL_HSTMT) {
02876 return SQL_INVALID_HANDLE;
02877 }
02878 s = (STMT *) stmt;
02879 if (pnum == 0) {
02880 setstat(s, -1, "invalid parameter", (*s->ov3) ? "07009" : "S1093");
02881 return SQL_ERROR;
02882 }
02883 if (!data && (!len || (*len != SQL_NULL_DATA &&
02884 *len > SQL_LEN_DATA_AT_EXEC_OFFSET))) {
02885 setstat(s, -1, "invalid buffer", "HY003");
02886 return SQL_ERROR;
02887 }
02888 if (len && *len < 0 && *len > SQL_LEN_DATA_AT_EXEC_OFFSET &&
02889 *len != SQL_NTS && *len != SQL_NULL_DATA) {
02890 setstat(s, -1, "invalid length reference", "HY009");
02891 return SQL_ERROR;
02892 }
02893 #if 0
02894 if (iotype != SQL_PARAM_INPUT)
02895 return SQL_ERROR;
02896 #endif
02897 --pnum;
02898 if (s->bindparms) {
02899 if (pnum >= s->nbindparms) {
02900 BINDPARM *newparms;
02901
02902 newparms = xrealloc(s->bindparms,
02903 (pnum + 1) * sizeof (BINDPARM));
02904 if (!newparms) {
02905 outofmem:
02906 return nomem(s);
02907 }
02908 s->bindparms = newparms;
02909 memset(&s->bindparms[s->nbindparms], 0,
02910 (pnum + 1 - s->nbindparms) * sizeof (BINDPARM));
02911 s->nbindparms = pnum + 1;
02912 }
02913 } else {
02914 int npar = max(10, pnum + 1);
02915
02916 s->bindparms = xmalloc(npar * sizeof (BINDPARM));
02917 if (!s->bindparms) {
02918 goto outofmem;
02919 }
02920 memset(s->bindparms, 0, npar * sizeof (BINDPARM));
02921 s->nbindparms = npar;
02922 }
02923 p = &s->bindparms[pnum];
02924 p->type = buftype;
02925 p->stype = ptype;
02926 p->max = buflen;
02927 p->inc = buflen;
02928 p->lenp = (int *) len;
02929 p->offs = 0;
02930 p->len = 0;
02931 p->param0 = p->param = data;
02932 freep(&p->parbuf);
02933 p->param = p->param0;
02934 p->need = 0;
02935 if (p->lenp && *p->lenp <= SQL_LEN_DATA_AT_EXEC_OFFSET) {
02936 p->need = 1;
02937 }
02938 return SQL_SUCCESS;
02939 }
02940 #if NOOOOOOOO
02941 if (p->lenp) {
02942 if (buftype == SQL_C_CHAR) {
02943 if (*p->lenp == SQL_NTS) {
02944 p->len = p->max = buflen = strlen(data);
02945 } else if (*p->lenp >= 0) {
02946 p->len = p->max = buflen = *p->lenp;
02947 }
02948 } else if (buftype == SQL_C_BINARY) {
02949 p->len = p->max = buflen = *p->lenp;
02950 }
02951 }
02952 if (p->lenp && *p->lenp <= SQL_LEN_DATA_AT_EXEC_OFFSET) {
02953 p->param = NULL;
02954 p->ind = p->param0;
02955 p->need = 1;
02956 } else if (p->lenp && *p->lenp == SQL_NULL_DATA) {
02957 p->param = NULL;
02958 p->ind = NULL;
02959 p->need = 0;
02960 } else {
02961 p->param = p->param0;
02962 p->ind = NULL;
02963 p->need = 0;
02964 }
02965 return SQL_SUCCESS;
02966 #endif
02967
02983 SQLRETURN SQL_API
02984 SQLBindParameter(SQLHSTMT stmt, SQLUSMALLINT pnum, SQLSMALLINT iotype,
02985 SQLSMALLINT buftype, SQLSMALLINT ptype, SQLULEN coldef,
02986 SQLSMALLINT scale,
02987 SQLPOINTER data, SQLLEN buflen, SQLLEN *len)
02988 {
02989 return drvbindparam(stmt, pnum, iotype, buftype, ptype, coldef,
02990 scale, data, buflen, len);
02991 }
02992
03006 SQLRETURN SQL_API
03007 SQLBindParam(SQLHSTMT stmt, SQLUSMALLINT pnum, SQLSMALLINT vtype,
03008 SQLSMALLINT ptype, SQLULEN lenprec,
03009 SQLSMALLINT scale, SQLPOINTER val,
03010 SQLLEN *lenp)
03011 {
03012 return drvbindparam(stmt, pnum, SQL_PARAM_INPUT, vtype, ptype,
03013 lenprec, scale, val, 0, lenp);
03014 }
03015
03023 SQLRETURN SQL_API
03024 SQLNumParams(SQLHSTMT stmt, SQLSMALLINT *nparam)
03025 {
03026 STMT *s;
03027 SQLSMALLINT dummy;
03028
03029 if (stmt == SQL_NULL_HSTMT) {
03030 return SQL_INVALID_HANDLE;
03031 }
03032 s = (STMT *) stmt;
03033 if (!nparam) {
03034 nparam = &dummy;
03035 }
03036 *nparam = s->nparams;
03037 return SQL_SUCCESS;
03038 }
03039
03047 SQLRETURN SQL_API
03048 SQLParamData(SQLHSTMT stmt, SQLPOINTER *p)
03049 {
03050 STMT *s;
03051 int i;
03052 SQLPOINTER dummy;
03053
03054 if (stmt == SQL_NULL_HSTMT) {
03055 return SQL_INVALID_HANDLE;
03056 }
03057 s = (STMT *) stmt;
03058 if (!p) {
03059 p = &dummy;
03060 }
03061 for (i = 0; i < s->nparams; i++) {
03062 if (s->bindparms[i].need > 0) {
03063 *p = (SQLPOINTER) s->bindparms[i].param0;
03064 return SQL_NEED_DATA;
03065 }
03066 }
03067 return drvexecute(stmt, 0);
03068 }
03069
03081 SQLRETURN SQL_API
03082 SQLDescribeParam(SQLHSTMT stmt, UWORD pnum, SWORD *dtype, UDWORD *size,
03083 SWORD *decdigits, SWORD *nullable)
03084 {
03085 STMT *s;
03086
03087 if (stmt == SQL_NULL_HSTMT) {
03088 return SQL_INVALID_HANDLE;
03089 }
03090 s = (STMT *) stmt;
03091 --pnum;
03092 if (pnum >= s->nparams) {
03093 setstat(s, -1, "invalid parameter index",
03094 (*s->ov3) ? "HY000" : "S1000");
03095 return SQL_ERROR;
03096 }
03097 if (dtype) {
03098 #ifdef SQL_LONGVARCHAR
03099 *dtype = SQL_LONGVARCHAR;
03100 #else
03101 *dtype = SQL_VARCHAR;
03102 #endif
03103 }
03104 if (size) {
03105 #ifdef SQL_LONGVARCHAR
03106 *size = 65536;
03107 #else
03108 *size = 255;
03109 #endif
03110 }
03111 if (decdigits) {
03112 *decdigits = 0;
03113 }
03114 if (nullable) {
03115 *nullable = SQL_NULLABLE;
03116 }
03117 return SQL_SUCCESS;
03118 }
03119
03133 SQLRETURN SQL_API
03134 SQLSetParam(SQLHSTMT stmt, SQLUSMALLINT par, SQLSMALLINT type,
03135 SQLSMALLINT sqltype, SQLULEN coldef,
03136 SQLSMALLINT scale, SQLPOINTER val, SQLLEN *nval)
03137 {
03138 return drvbindparam(stmt, par, SQL_PARAM_INPUT,
03139 type, sqltype, coldef, scale, val,
03140 SQL_SETPARAM_VALUE_MAX, nval);
03141 }
03142
03147 SQLRETURN SQL_API
03148 SQLParamOptions(SQLHSTMT stmt, UDWORD rows, UDWORD *rowp)
03149 {
03150 return drvunimplstmt(stmt);
03151 }
03152
03157 SQLRETURN SQL_API
03158 SQLGetDescField(SQLHDESC handle, SQLSMALLINT recno,
03159 SQLSMALLINT fieldid, SQLPOINTER value,
03160 SQLINTEGER buflen, SQLINTEGER *strlen)
03161 {
03162 return SQL_ERROR;
03163 }
03164
03169 SQLRETURN SQL_API
03170 SQLSetDescField(SQLHDESC handle, SQLSMALLINT recno,
03171 SQLSMALLINT fieldid, SQLPOINTER value,
03172 SQLINTEGER buflen)
03173 {
03174 return SQL_ERROR;
03175 }
03176
03181 SQLRETURN SQL_API
03182 SQLGetDescRec(SQLHDESC handle, SQLSMALLINT recno,
03183 SQLCHAR *name, SQLSMALLINT buflen,
03184 SQLSMALLINT *strlen, SQLSMALLINT *type,
03185 SQLSMALLINT *subtype, SQLLEN *len,
03186 SQLSMALLINT *prec, SQLSMALLINT *scale,
03187 SQLSMALLINT *nullable)
03188 {
03189 return SQL_ERROR;
03190 }
03191
03196 SQLRETURN SQL_API
03197 SQLSetDescRec(SQLHDESC handle, SQLSMALLINT recno,
03198 SQLSMALLINT type, SQLSMALLINT subtype,
03199 SQLLEN len, SQLSMALLINT prec,
03200 SQLSMALLINT scale, SQLPOINTER data,
03201 SQLLEN *strlen, SQLLEN *indicator)
03202 {
03203 return SQL_ERROR;
03204 }
03205
03214 static SQLRETURN
03215 mkresultset(HSTMT stmt, COL *colspec, int ncols)
03216 {
03217 STMT *s;
03218 DBC *d;
03219
03220 if (stmt == SQL_NULL_HSTMT) {
03221 return SQL_INVALID_HANDLE;
03222 }
03223 s = (STMT *) stmt;
03224 if (s->dbc == SQL_NULL_HDBC) {
03225 noconn:
03226 return noconn(s);
03227 }
03228 d = (DBC *) s->dbc;
03229 if (!d->sqlite) {
03230 goto noconn;
03231 }
03232 s3stmt_end_if(s);
03233 freeresult(s, 0);
03234 s->ncols = ncols;
03235 s->cols = colspec;
03236 mkbindcols(s, s->ncols);
03237 s->nrows = 0;
03238 s->rowp = -1;
03239 s->isselect = -1;
03240 return SQL_SUCCESS;
03241 }
03242
03247 static COL tablePrivSpec[] = {
03248 { "SYSTEM", "TABLEPRIV", "TABLE_QUALIFIER", SCOL_VARCHAR, 50 },
03249 { "SYSTEM", "TABLEPRIV", "TABLE_OWNER", SCOL_VARCHAR, 50 },
03250 { "SYSTEM", "TABLEPRIV", "TABLE_NAME", SCOL_VARCHAR, 255 },
03251 { "SYSTEM", "TABLEPRIV", "GRANTOR", SCOL_VARCHAR, 50 },
03252 { "SYSTEM", "TABLEPRIV", "GRANTEE", SCOL_VARCHAR, 50 },
03253 { "SYSTEM", "TABLEPRIV", "PRIVILEGE", SCOL_VARCHAR, 50 },
03254 { "SYSTEM", "TABLEPRIV", "IS_GRANTABLE", SCOL_VARCHAR, 50 }
03255 };
03256
03269 SQLRETURN SQL_API
03270 SQLTablePrivileges(SQLHSTMT stmt,
03271 SQLCHAR *catalog, SQLSMALLINT catalogLen,
03272 SQLCHAR *schema, SQLSMALLINT schemaLen,
03273 SQLCHAR *table, SQLSMALLINT tableLen)
03274 {
03275 return mkresultset(stmt, tablePrivSpec, array_size(tablePrivSpec));
03276 }
03277
03282 static COL colPrivSpec[] = {
03283 { "SYSTEM", "COLPRIV", "TABLE_QUALIFIER", SCOL_VARCHAR, 50 },
03284 { "SYSTEM", "COLPRIV", "TABLE_OWNER", SCOL_VARCHAR, 50 },
03285 { "SYSTEM", "COLPRIV", "TABLE_NAME", SCOL_VARCHAR, 255 },
03286 { "SYSTEM", "COLPRIV", "GRANTOR", SCOL_VARCHAR, 50 },
03287 { "SYSTEM", "COLPRIV", "GRANTEE", SCOL_VARCHAR, 50 },
03288 { "SYSTEM", "COLPRIV", "PRIVILEGE", SCOL_VARCHAR, 50 },
03289 { "SYSTEM", "COLPRIV", "IS_GRANTABLE", SCOL_VARCHAR, 50 }
03290 };
03291
03306 SQLRETURN SQL_API
03307 SQLColumnPrivileges(SQLHSTMT stmt,
03308 SQLCHAR *catalog, SQLSMALLINT catalogLen,
03309 SQLCHAR *schema, SQLSMALLINT schemaLen,
03310 SQLCHAR *table, SQLSMALLINT tableLen,
03311 SQLCHAR *column, SQLSMALLINT columnLen)
03312 {
03313 return mkresultset(stmt, colPrivSpec, array_size(colPrivSpec));
03314 }
03315
03320 static COL pkeySpec[] = {
03321 { "SYSTEM", "PRIMARYKEY", "TABLE_QUALIFIER", SCOL_VARCHAR, 50 },
03322 { "SYSTEM", "PRIMARYKEY", "TABLE_OWNER", SCOL_VARCHAR, 50 },
03323 { "SYSTEM", "PRIMARYKEY", "TABLE_NAME", SCOL_VARCHAR, 255 },
03324 { "SYSTEM", "PRIMARYKEY", "COLUMN_NAME", SCOL_VARCHAR, 255 },
03325 { "SYSTEM", "PRIMARYKEY", "KEY_SEQ", SQL_SMALLINT, 50 },
03326 { "SYSTEM", "PRIMARYKEY", "PK_NAME", SCOL_VARCHAR, 50 }
03327 };
03328
03341 static SQLRETURN
03342 drvprimarykeys(SQLHSTMT stmt,
03343 SQLCHAR *cat, SQLSMALLINT catLen,
03344 SQLCHAR *schema, SQLSMALLINT schemaLen,
03345 SQLCHAR *table, SQLSMALLINT tableLen)
03346 {
03347 STMT *s;
03348 DBC *d;
03349 SQLRETURN sret;
03350 int i, size, ret, nrows, ncols, offs, namec, uniquec;
03351 char **rowp, *errp = NULL, *sql, tname[512];
03352
03353 sret = mkresultset(stmt, pkeySpec, array_size(pkeySpec));
03354 if (sret != SQL_SUCCESS) {
03355 return sret;
03356 }
03357 s = (STMT *) stmt;
03358 d = (DBC *) s->dbc;
03359 if (!table || table[0] == '\0' || table[0] == '%') {
03360 setstat(s, -1, "need table name", (*s->ov3) ? "HY000" : "S1000");
03361 return SQL_ERROR;
03362 }
03363 if (tableLen == SQL_NTS) {
03364 size = sizeof (tname) - 1;
03365 } else {
03366 size = min(sizeof (tname) - 1, tableLen);
03367 }
03368 strncpy(tname, (char *) table, size);
03369 tname[size] = '\0';
03370 sql = sqlite3_mprintf("PRAGMA index_list('%q')", tname);
03371 if (!sql) {
03372 return nomem(s);
03373 }
03374 dbtraceapi(d, "sqlite3_get_table", sql);
03375 ret = sqlite3_get_table(d->sqlite, sql, &rowp, &nrows, &ncols, &errp);
03376 sqlite3_free(sql);
03377 if (ret != SQLITE_OK) {
03378 setstat(s, ret, "%s (%d)", (*s->ov3) ? "HY000" : "S1000",
03379 errp ? errp : "unknown error", ret);
03380 if (errp) {
03381 sqlite3_free(errp);
03382 errp = NULL;
03383 }
03384 return SQL_ERROR;
03385 }
03386 if (errp) {
03387 sqlite3_free(errp);
03388 errp = NULL;
03389 }
03390 if (ncols * nrows <= 0) {
03391 nodata:
03392 sqlite3_free_table(rowp);
03393
03394 ret = SQLITE_ERROR;
03395 sql = sqlite3_mprintf("PRAGMA table_info('%q')", tname);
03396 if (sql) {
03397 dbtraceapi(d, "sqlite3_get_table", sql);
03398 ret = sqlite3_get_table(d->sqlite, sql, &rowp,
03399 &nrows, &ncols, NULL);
03400 sqlite3_free(sql);
03401 }
03402 if (ret == SQLITE_OK) {
03403 int typec, roffs;
03404
03405 namec = findcol(rowp, ncols, "name");
03406 uniquec = findcol(rowp, ncols, "pk");
03407 typec = findcol(rowp, ncols, "type");
03408 if (namec < 0 || uniquec < 0 || typec < 0) {
03409 goto nodata2;
03410 }
03411 for (i = 1; i <= nrows; i++) {
03412 if (*rowp[i * ncols + uniquec] != '0' &&
03413 strlen(rowp[i * ncols + typec]) == 7 &&
03414 strncasecmp(rowp[i * ncols + typec], "integer", 7) == 0) {
03415 break;
03416 }
03417 }
03418 if (i > nrows) {
03419 goto nodata2;
03420 }
03421 size = (1 + 1) * array_size(pkeySpec);
03422 s->rows = xmalloc((size + 1) * sizeof (char *));
03423 if (!s->rows) {
03424 s->nrows = 0;
03425 return nomem(s);
03426 }
03427 s->rows[0] = (char *) size;
03428 s->rows += 1;
03429 memset(s->rows, 0, sizeof (char *) * size);
03430 s->rowfree = freerows;
03431 s->nrows = 1;
03432 roffs = s->ncols;
03433 s->rows[roffs + 0] = xstrdup("");
03434 s->rows[roffs + 1] = xstrdup("");
03435 s->rows[roffs + 2] = xstrdup(tname);
03436 s->rows[roffs + 3] = xstrdup(rowp[i * ncols + namec]);
03437 s->rows[roffs + 4] = xstrdup("1");
03438 nodata2:
03439 sqlite3_free_table(rowp);
03440 }
03441 return SQL_SUCCESS;
03442 }
03443 size = 0;
03444 namec = findcol(rowp, ncols, "name");
03445 uniquec = findcol(rowp, ncols, "unique");
03446 if (namec < 0 || uniquec < 0) {
03447 goto nodata;
03448 }
03449 for (i = 1; i <= nrows; i++) {
03450 int nnrows, nncols;
03451 char **rowpp;
03452
03453 if (*rowp[i * ncols + uniquec] != '0') {
03454 ret = SQLITE_ERROR;
03455 sql = sqlite3_mprintf("PRAGMA index_info('%q')",
03456 rowp[i * ncols + namec]);
03457 if (sql) {
03458 dbtraceapi(d, "sqlite3_get_table", sql);
03459 ret = sqlite3_get_table(d->sqlite, sql, &rowpp,
03460 &nnrows, &nncols, NULL);
03461 sqlite3_free(sql);
03462 }
03463 if (ret == SQLITE_OK) {
03464 size += nnrows;
03465 sqlite3_free_table(rowpp);
03466 }
03467 }
03468 }
03469 if (size == 0) {
03470 goto nodata;
03471 }
03472 s->nrows = size;
03473 size = (size + 1) * array_size(pkeySpec);
03474 s->rows = xmalloc((size + 1) * sizeof (char *));
03475 if (!s->rows) {
03476 s->nrows = 0;
03477 return nomem(s);
03478 }
03479 s->rows[0] = (char *) size;
03480 s->rows += 1;
03481 memset(s->rows, 0, sizeof (char *) * size);
03482 s->rowfree = freerows;
03483 offs = 0;
03484 for (i = 1; i <= nrows; i++) {
03485 int nnrows, nncols;
03486 char **rowpp;
03487
03488 if (*rowp[i * ncols + uniquec] != '0') {
03489 int k;
03490
03491 ret = SQLITE_ERROR;
03492 sql = sqlite3_mprintf("PRAGMA index_info('%q')",
03493 rowp[i * ncols + namec]);
03494 if (sql) {
03495 dbtraceapi(d, "sqlite3_get_table", sql);
03496 ret = sqlite3_get_table(d->sqlite, sql, &rowpp,
03497 &nnrows, &nncols, NULL);
03498 sqlite3_free(sql);
03499 }
03500 if (ret != SQLITE_OK) {
03501 continue;
03502 }
03503 for (k = 0; nnrows && k < nncols; k++) {
03504 if (strcmp(rowpp[k], "name") == 0) {
03505 int m;
03506
03507 for (m = 1; m <= nnrows; m++) {
03508 int roffs = (offs + m) * s->ncols;
03509
03510 s->rows[roffs + 0] = xstrdup("");
03511 s->rows[roffs + 1] = xstrdup("");
03512 s->rows[roffs + 2] = xstrdup(tname);
03513 s->rows[roffs + 3] = xstrdup(rowpp[m * nncols + k]);
03514 s->rows[roffs + 5] = xstrdup(rowp[i * ncols + namec]);
03515 }
03516 } else if (strcmp(rowpp[k], "seqno") == 0) {
03517 int m;
03518
03519 for (m = 1; m <= nnrows; m++) {
03520 int roffs = (offs + m) * s->ncols;
03521 int pos = m - 1;
03522 char buf[32];
03523
03524 sscanf(rowpp[m * nncols + k], "%d", &pos);
03525 sprintf(buf, "%d", pos + 1);
03526 s->rows[roffs + 4] = xstrdup(buf);
03527 }
03528 }
03529 }
03530 offs += nnrows;
03531 sqlite3_free_table(rowpp);
03532 }
03533 }
03534 sqlite3_free_table(rowp);
03535 return SQL_SUCCESS;
03536 }
03537
03550 SQLRETURN SQL_API
03551 SQLPrimaryKeys(SQLHSTMT stmt,
03552 SQLCHAR *cat, SQLSMALLINT catLen,
03553 SQLCHAR *schema, SQLSMALLINT schemaLen,
03554 SQLCHAR *table, SQLSMALLINT tableLen)
03555 {
03556 return drvprimarykeys(stmt, cat, catLen, schema, schemaLen,
03557 table, tableLen);
03558 }
03559
03564 static COL scolSpec[] = {
03565 { "SYSTEM", "COLUMN", "SCOPE", SQL_SMALLINT, 1 },
03566 { "SYSTEM", "COLUMN", "COLUMN_NAME", SCOL_VARCHAR, 255 },
03567 { "SYSTEM", "COLUMN", "DATA_TYPE", SQL_SMALLINT, 50 },
03568 { "SYSTEM", "COLUMN", "TYPE_NAME", SCOL_VARCHAR, 50 },
03569 { "SYSTEM", "COLUMN", "PRECISION", SQL_INTEGER, 50 },
03570 { "SYSTEM", "COLUMN", "LENGTH", SQL_INTEGER, 50 },
03571 { "SYSTEM", "COLUMN", "DECIMAL_DIGITS", SQL_INTEGER, 50 },
03572 { "SYSTEM", "COLUMN", "PSEUDO_COLUMN", SQL_SMALLINT, 1 },
03573 { "SYSTEM", "COLUMN", "NULLABLE", SQL_SMALLINT, 1 }
03574 };
03575
03591 static SQLRETURN
03592 drvspecialcolumns(SQLHSTMT stmt, SQLUSMALLINT id,
03593 SQLCHAR *cat, SQLSMALLINT catLen,
03594 SQLCHAR *schema, SQLSMALLINT schemaLen,
03595 SQLCHAR *table, SQLSMALLINT tableLen,
03596 SQLUSMALLINT scope, SQLUSMALLINT nullable)
03597 {
03598 STMT *s;
03599 DBC *d;
03600 SQLRETURN sret;
03601 int i, size, ret, nrows, ncols, nnnrows, nnncols, offs;
03602 int namec = -1, uniquec = -1, namecc = -1, typecc = -1;
03603 int notnullcc = -1, mkrowid = 0;
03604 char *errp = NULL, *sql, tname[512];
03605 char **rowp = NULL, **rowppp = NULL;
03606
03607 sret = mkresultset(stmt, scolSpec, array_size(scolSpec));
03608 if (sret != SQL_SUCCESS) {
03609 return sret;
03610 }
03611 s = (STMT *) stmt;
03612 d = (DBC *) s->dbc;
03613 if (!table || table[0] == '\0' || table[0] == '%') {
03614 setstat(s, -1, "need table name", (*s->ov3) ? "HY000" : "S1000");
03615 return SQL_ERROR;
03616 }
03617 if (tableLen == SQL_NTS) {
03618 size = sizeof (tname) - 1;
03619 } else {
03620 size = min(sizeof (tname) - 1, tableLen);
03621 }
03622 strncpy(tname, (char *) table, size);
03623 tname[size] = '\0';
03624 if (id != SQL_BEST_ROWID) {
03625 return SQL_SUCCESS;
03626 }
03627 sql = sqlite3_mprintf("PRAGMA index_list('%q')", tname);
03628 if (!sql) {
03629 return nomem(s);
03630 }
03631 dbtraceapi(d, "sqlite3_get_table", sql);
03632 ret = sqlite3_get_table(d->sqlite, sql, &rowp, &nrows, &ncols, &errp);
03633 sqlite3_free(sql);
03634 if (ret != SQLITE_OK) {
03635 doerr:
03636 setstat(s, ret, "%s (%d)", (*s->ov3) ? "HY000" : "S1000",
03637 errp ? errp : "unknown error", ret);
03638 if (errp) {
03639 sqlite3_free(errp);
03640 errp = NULL;
03641 }
03642 return SQL_ERROR;
03643 }
03644 if (errp) {
03645 sqlite3_free(errp);
03646 errp = NULL;
03647 }
03648 size = 0;
03649 if (ncols * nrows <= 0) {
03650 goto nodata_but_rowid;
03651 }
03652 sql = sqlite3_mprintf("PRAGMA table_info('%q')", tname);
03653 if (!sql) {
03654 return nomem(s);
03655 }
03656 dbtraceapi(d, "sqlite3_get_table", sql);
03657 ret = sqlite3_get_table(d->sqlite, sql, &rowppp, &nnnrows, &nnncols,
03658 &errp);
03659 sqlite3_free(sql);
03660 if (ret != SQLITE_OK) {
03661 sqlite3_free_table(rowp);
03662 goto doerr;
03663 }
03664 if (errp) {
03665 sqlite3_free(errp);
03666 errp = NULL;
03667 }
03668 namec = findcol(rowp, ncols, "name");
03669 uniquec = findcol(rowp, ncols, "unique");
03670 if (namec < 0 || uniquec < 0) {
03671 goto nodata_but_rowid;
03672 }
03673 namecc = findcol(rowppp, nnncols, "name");
03674 typecc = findcol(rowppp, nnncols, "type");
03675 notnullcc = findcol(rowppp, nnncols, "notnull");
03676 for (i = 1; i <= nrows; i++) {
03677 int nnrows, nncols;
03678 char **rowpp = NULL;
03679
03680 if (*rowp[i * ncols + uniquec] != '0') {
03681 ret = SQLITE_ERROR;
03682 sql = sqlite3_mprintf("PRAGMA index_info('%q')",
03683 rowp[i * ncols + namec]);
03684 if (sql) {
03685 dbtraceapi(d, "sqlite3_get_table", sql);
03686 ret = sqlite3_get_table(d->sqlite, sql, &rowpp,
03687 &nnrows, &nncols, NULL);
03688 sqlite3_free(sql);
03689 }
03690 if (ret == SQLITE_OK) {
03691 size += nnrows;
03692 sqlite3_free_table(rowpp);
03693 }
03694 }
03695 }
03696 nodata_but_rowid:
03697 if (size == 0) {
03698 size = 1;
03699 mkrowid = 1;
03700 }
03701 s->nrows = size;
03702 size = (size + 1) * array_size(scolSpec);
03703 s->rows = xmalloc((size + 1) * sizeof (char *));
03704 if (!s->rows) {
03705 s->nrows = 0;
03706 sqlite3_free_table(rowp);
03707 sqlite3_free_table(rowppp);
03708 return nomem(s);
03709 }
03710 s->rows[0] = (char *) size;
03711 s->rows += 1;
03712 memset(s->rows, 0, sizeof (char *) * size);
03713 s->rowfree = freerows;
03714 if (mkrowid) {
03715 s->nrows = 0;
03716 goto mkrowid;
03717 }
03718 offs = 0;
03719 for (i = 1; i <= nrows; i++) {
03720 int nnrows, nncols;
03721 char **rowpp = NULL;
03722
03723 if (*rowp[i * ncols + uniquec] != '0') {
03724 int k;
03725
03726 ret = SQLITE_ERROR;
03727 sql = sqlite3_mprintf("PRAGMA index_info('%q')",
03728 rowp[i * ncols + namec]);
03729 if (sql) {
03730 dbtraceapi(d, "sqlite3_get_table", sql);
03731 ret = sqlite3_get_table(d->sqlite, sql, &rowpp,
03732 &nnrows, &nncols, NULL);
03733 sqlite3_free(sql);
03734 }
03735 if (ret != SQLITE_OK) {
03736 continue;
03737 }
03738 for (k = 0; nnrows && k < nncols; k++) {
03739 if (strcmp(rowpp[k], "name") == 0) {
03740 int m;
03741
03742 for (m = 1; m <= nnrows; m++) {
03743 int roffs = (offs + m) * s->ncols;
03744
03745 s->rows[roffs + 0] =
03746 xstrdup(stringify(SQL_SCOPE_SESSION));
03747 s->rows[roffs + 1] = xstrdup(rowpp[m * nncols + k]);
03748 s->rows[roffs + 4] = xstrdup("0");
03749 s->rows[roffs + 7] =
03750 xstrdup(stringify(SQL_PC_NOT_PSEUDO));
03751 if (namecc >= 0 && typecc >= 0) {
03752 int ii;
03753
03754 for (ii = 1; ii <= nnnrows; ii++) {
03755 if (strcmp(rowppp[ii * nnncols + namecc],
03756 rowpp[m * nncols + k]) == 0) {
03757 char *typen = rowppp[ii * nnncols + typecc];
03758 int sqltype, mm, dd, isnullable = 0;
03759 char buf[32];
03760
03761 s->rows[roffs + 3] = xstrdup(typen);
03762 sqltype = mapsqltype(typen, NULL, *s->ov3);
03763 getmd(typen, sqltype, &mm, &dd);
03764 #ifdef SQL_LONGVARCHAR
03765 if (sqltype == SQL_VARCHAR && mm > 255) {
03766 sqltype = SQL_LONGVARCHAR;
03767 }
03768 #endif
03769 if (sqltype == SQL_VARBINARY && mm > 255) {
03770 sqltype = SQL_LONGVARBINARY;
03771 }
03772 sprintf(buf, "%d", sqltype);
03773 s->rows[roffs + 2] = xstrdup(buf);
03774 sprintf(buf, "%d", mm);
03775 s->rows[roffs + 5] = xstrdup(buf);
03776 sprintf(buf, "%d", dd);
03777 s->rows[roffs + 6] = xstrdup(buf);
03778 if (notnullcc >= 0) {
03779 char *inp =
03780 rowppp[ii * nnncols + notnullcc];
03781
03782 isnullable = inp[0] != '0';
03783 }
03784 sprintf(buf, "%d", isnullable);
03785 s->rows[roffs + 8] = xstrdup(buf);
03786 }
03787 }
03788 }
03789 }
03790 }
03791 }
03792 offs += nnrows;
03793 sqlite3_free_table(rowpp);
03794 }
03795 }
03796 if (nullable == SQL_NO_NULLS) {
03797 for (i = 1; i < s->nrows; i++) {
03798 if (s->rows[i * s->ncols + 8][0] == '0') {
03799 int m, i1 = i + 1;
03800
03801 for (m = 0; m < s->ncols; m++) {
03802 freep(&s->rows[i * s->ncols + m]);
03803 }
03804 size = s->ncols * sizeof (char *) * (s->nrows - i1);
03805 if (size > 0) {
03806 memmove(s->rows + i * s->ncols,
03807 s->rows + i1 * s->ncols,
03808 size);
03809 memset(s->rows + s->nrows * s->ncols, 0,
03810 s->ncols * sizeof (char *));
03811 }
03812 s->nrows--;
03813 --i;
03814 }
03815 }
03816 }
03817 mkrowid:
03818 sqlite3_free_table(rowp);
03819 sqlite3_free_table(rowppp);
03820 if (s->nrows == 0) {
03821 s->rows[s->ncols + 0] = xstrdup(stringify(SQL_SCOPE_SESSION));
03822 s->rows[s->ncols + 1] = xstrdup("_ROWID_");
03823 s->rows[s->ncols + 2] = xstrdup(stringify(SQL_INTEGER));
03824 s->rows[s->ncols + 3] = xstrdup("integer");
03825 s->rows[s->ncols + 4] = xstrdup("0");
03826 s->rows[s->ncols + 5] = xstrdup("10");
03827 s->rows[s->ncols + 6] = xstrdup("9");
03828 s->rows[s->ncols + 7] = xstrdup(stringify(SQL_PC_PSEUDO));
03829 s->rows[s->ncols + 8] = xstrdup(stringify(SQL_FALSE));
03830 s->nrows = 1;
03831 }
03832 return SQL_SUCCESS;
03833 }
03834
03850 SQLRETURN SQL_API
03851 SQLSpecialColumns(SQLHSTMT stmt, SQLUSMALLINT id,
03852 SQLCHAR *cat, SQLSMALLINT catLen,
03853 SQLCHAR *schema, SQLSMALLINT schemaLen,
03854 SQLCHAR *table, SQLSMALLINT tableLen,
03855 SQLUSMALLINT scope, SQLUSMALLINT nullable)
03856 {
03857 return drvspecialcolumns(stmt, id, cat, catLen, schema, schemaLen,
03858 table, tableLen, scope, nullable);
03859 }
03860
03865 static COL fkeySpec[] = {
03866 { "SYSTEM", "FOREIGNKEY", "PKTABLE_QUALIFIER", SCOL_VARCHAR, 50 },
03867 { "SYSTEM", "FOREIGNKEY", "PKTABLE_OWNER", SCOL_VARCHAR, 50 },
03868 { "SYSTEM", "FOREIGNKEY", "PKTABLE_NAME", SCOL_VARCHAR, 255 },
03869 { "SYSTEM", "FOREIGNKEY", "PKCOLUMN_NAME", SCOL_VARCHAR, 255 },
03870 { "SYSTEM", "FOREIGNKEY", "FKTABLE_QUALIFIER", SCOL_VARCHAR, 50 },
03871 { "SYSTEM", "FOREIGNKEY", "FKTABLE_OWNER", SCOL_VARCHAR, 50 },
03872 { "SYSTEM", "FOREIGNKEY", "FKTABLE_NAME", SCOL_VARCHAR, 255 },
03873 { "SYSTEM", "FOREIGNKEY", "FKCOLUMN_NAME", SCOL_VARCHAR, 255 },
03874 { "SYSTEM", "FOREIGNKEY", "KEY_SEQ", SQL_SMALLINT, 5 },
03875 { "SYSTEM", "FOREIGNKEY", "UPDATE_RULE", SQL_SMALLINT, 5 },
03876 { "SYSTEM", "FOREIGNKEY", "DELETE_RULE", SQL_SMALLINT, 5 },
03877 { "SYSTEM", "FOREIGNKEY", "FK_NAME", SCOL_VARCHAR, 255 },
03878 { "SYSTEM", "FOREIGNKEY", "PK_NAME", SCOL_VARCHAR, 255 },
03879 { "SYSTEM", "FOREIGNKEY", "DEFERRABILITY", SQL_SMALLINT, 5 }
03880 };
03881
03900 static SQLRETURN SQL_API
03901 drvforeignkeys(SQLHSTMT stmt,
03902 SQLCHAR *PKcatalog, SQLSMALLINT PKcatalogLen,
03903 SQLCHAR *PKschema, SQLSMALLINT PKschemaLen,
03904 SQLCHAR *PKtable, SQLSMALLINT PKtableLen,
03905 SQLCHAR *FKcatalog, SQLSMALLINT FKcatalogLen,
03906 SQLCHAR *FKschema, SQLSMALLINT FKschemaLen,
03907 SQLCHAR *FKtable, SQLSMALLINT FKtableLen)
03908 {
03909 STMT *s;
03910 DBC *d;
03911 SQLRETURN sret;
03912 int i, size, ret, nrows, ncols, offs, namec, seqc, fromc, toc;
03913 char **rowp, *errp = NULL, *sql, pname[512], fname[512];
03914
03915 sret = mkresultset(stmt, fkeySpec, array_size(fkeySpec));
03916 if (sret != SQL_SUCCESS) {
03917 return sret;
03918 }
03919 s = (STMT *) stmt;
03920 d = (DBC *) s->dbc;
03921 if ((!PKtable || PKtable[0] == '\0' || PKtable[0] == '%') &&
03922 (!FKtable || FKtable[0] == '\0' || FKtable[0] == '%')) {
03923 setstat(s, -1, "need table name", (*s->ov3) ? "HY000" : "S1000");
03924 return SQL_ERROR;
03925 }
03926 size = 0;
03927 if (PKtable) {
03928 if (PKtableLen == SQL_NTS) {
03929 size = sizeof (pname) - 1;
03930 } else {
03931 size = min(sizeof (pname) - 1, PKtableLen);
03932 }
03933 strncpy(pname, (char *) PKtable, size);
03934 }
03935 pname[size] = '\0';
03936 size = 0;
03937 if (FKtable) {
03938
03939 if (FKtableLen == SQL_NTS) {
03940 size = sizeof (fname) - 1;
03941 } else {
03942 size = min(sizeof (fname) - 1, FKtableLen);
03943 }
03944 strncpy(fname, (char *) FKtable, size);
03945 }
03946 fname[size] = '\0';
03947 if (fname[0] != '\0') {
03948 int plen;
03949
03950 ret = SQLITE_ERROR;
03951 sql = sqlite3_mprintf("PRAGMA foreign_key_list('%q')", fname);
03952 if (sql) {
03953 dbtraceapi(d, "sqlite3_get_table", sql);
03954 ret = sqlite3_get_table(d->sqlite, sql, &rowp,
03955 &nrows, &ncols, &errp);
03956 sqlite3_free(sql);
03957 }
03958 if (ret != SQLITE_OK) {
03959 setstat(s, ret, "%s (%d)", (*s->ov3) ? "HY000" : "S1000",
03960 errp ? errp : "unknown error", ret);
03961 if (errp) {
03962 sqlite3_free(errp);
03963 errp = NULL;
03964 }
03965 return SQL_ERROR;
03966 }
03967 if (errp) {
03968 sqlite3_free(errp);
03969 errp = NULL;
03970 }
03971 if (ncols * nrows <= 0) {
03972 nodata:
03973 sqlite3_free_table(rowp);
03974 return SQL_SUCCESS;
03975 }
03976 size = 0;
03977 namec = findcol(rowp, ncols, "table");
03978 seqc = findcol(rowp, ncols, "seq");
03979 fromc = findcol(rowp, ncols, "from");
03980 toc = findcol(rowp, ncols, "to");
03981 if (namec < 0 || seqc < 0 || fromc < 0 || toc < 0) {
03982 goto nodata;
03983 }
03984 plen = strlen(pname);
03985 for (i = 1; i <= nrows; i++) {
03986 char *ptab = rowp[i * ncols + namec];
03987
03988 if (plen && ptab) {
03989 int len = strlen(ptab);
03990
03991 if (plen != len || strncasecmp(pname, ptab, plen) != 0) {
03992 continue;
03993 }
03994 }
03995 size++;
03996 }
03997 if (size == 0) {
03998 goto nodata;
03999 }
04000 s->nrows = size;
04001 size = (size + 1) * array_size(fkeySpec);
04002 s->rows = xmalloc((size + 1) * sizeof (char *));
04003 if (!s->rows) {
04004 s->nrows = 0;
04005 return nomem(s);
04006 }
04007 s->rows[0] = (char *) size;
04008 s->rows += 1;
04009 memset(s->rows, 0, sizeof (char *) * size);
04010 s->rowfree = freerows;
04011 offs = 0;
04012 for (i = 1; i <= nrows; i++) {
04013 int pos = 0, roffs = (offs + 1) * s->ncols;
04014 char *ptab = rowp[i * ncols + namec];
04015 char buf[32];
04016
04017 if (plen && ptab) {
04018 int len = strlen(ptab);
04019
04020 if (plen != len || strncasecmp(pname, ptab, plen) != 0) {
04021 continue;
04022 }
04023 }
04024 s->rows[roffs + 0] = xstrdup("");
04025 s->rows[roffs + 1] = xstrdup("");
04026 s->rows[roffs + 2] = xstrdup(ptab);
04027 s->rows[roffs + 3] = xstrdup(rowp[i * ncols + toc]);
04028 s->rows[roffs + 4] = xstrdup("");
04029 s->rows[roffs + 5] = xstrdup("");
04030 s->rows[roffs + 6] = xstrdup(fname);
04031 s->rows[roffs + 7] = xstrdup(rowp[i * ncols + fromc]);
04032 sscanf(rowp[i * ncols + seqc], "%d", &pos);
04033 sprintf(buf, "%d", pos + 1);
04034 s->rows[roffs + 8] = xstrdup(buf);
04035 s->rows[roffs + 9] = xstrdup(stringify(SQL_NO_ACTION));
04036 s->rows[roffs + 10] = xstrdup(stringify(SQL_NO_ACTION));
04037 s->rows[roffs + 11] = NULL;
04038 s->rows[roffs + 12] = NULL;
04039 s->rows[roffs + 13] = xstrdup(stringify(SQL_NOT_DEFERRABLE));
04040 offs++;
04041 }
04042 sqlite3_free_table(rowp);
04043 } else {
04044 int nnrows, nncols, plen = strlen(pname);
04045 char **rowpp;
04046
04047 sql = "select name from sqlite_master where type='table'";
04048 dbtraceapi(d, "sqlite3_get_table", sql);
04049 ret = sqlite3_get_table(d->sqlite, sql, &rowp, &nrows, &ncols, &errp);
04050 if (ret != SQLITE_OK) {
04051 setstat(s, ret, "%s (%d)", (*s->ov3) ? "HY000" : "S1000",
04052 errp ? errp : "unknown error", ret);
04053 if (errp) {
04054 sqlite3_free(errp);
04055 errp = NULL;
04056 }
04057 return SQL_ERROR;
04058 }
04059 if (errp) {
04060 sqlite3_free(errp);
04061 errp = NULL;
04062 }
04063 if (ncols * nrows <= 0) {
04064 goto nodata;
04065 }
04066 size = 0;
04067 for (i = 1; i <= nrows; i++) {
04068 int k, len;
04069
04070 if (!rowp[i]) {
04071 continue;
04072 }
04073 len = strlen(rowp[i]);
04074 if (len == plen && strncasecmp(pname, rowp[i], plen) == 0) {
04075 continue;
04076 }
04077 rowpp = NULL;
04078 ret = SQLITE_ERROR;
04079 sql = sqlite3_mprintf("PRAGMA foreign_key_list('%q')", rowp[i]);
04080 if (sql) {
04081 dbtraceapi(d, "sqlite3_get_table", sql);
04082 ret = sqlite3_get_table(d->sqlite, sql, &rowpp,
04083 &nnrows, &nncols, NULL);
04084 sqlite3_free(sql);
04085 }
04086 if (ret != SQLITE_OK || nncols * nnrows <= 0) {
04087 sqlite3_free_table(rowpp);
04088 continue;
04089 }
04090 namec = findcol(rowpp, nncols, "table");
04091 seqc = findcol(rowpp, nncols, "seq");
04092 fromc = findcol(rowpp, nncols, "from");
04093 toc = findcol(rowpp, nncols, "to");
04094 if (namec < 0 || seqc < 0 || fromc < 0 || toc < 0) {
04095 sqlite3_free_table(rowpp);
04096 continue;
04097 }
04098 for (k = 1; k <= nnrows; k++) {
04099 char *ptab = rowpp[k * nncols + namec];
04100
04101 if (plen && ptab) {
04102 len = strlen(ptab);
04103 if (len != plen || strncasecmp(pname, ptab, plen) != 0) {
04104 continue;
04105 }
04106 }
04107 size++;
04108 }
04109 sqlite3_free_table(rowpp);
04110 }
04111 if (size == 0) {
04112 goto nodata;
04113 }
04114 s->nrows = size;
04115 size = (size + 1) * array_size(fkeySpec);
04116 s->rows = xmalloc((size + 1) * sizeof (char *));
04117 if (!s->rows) {
04118 s->nrows = 0;
04119 return nomem(s);
04120 }
04121 s->rows[0] = (char *) size;
04122 s->rows += 1;
04123 memset(s->rows, 0, sizeof (char *) * size);
04124 s->rowfree = freerows;
04125 offs = 0;
04126 for (i = 1; i <= nrows; i++) {
04127 int k, len;
04128
04129 if (!rowp[i]) {
04130 continue;
04131 }
04132 len = strlen(rowp[i]);
04133 if (len == plen && strncasecmp(pname, rowp[i], plen) == 0) {
04134 continue;
04135 }
04136 rowpp = NULL;
04137 ret = SQLITE_ERROR;
04138 sql = sqlite3_mprintf("PRAGMA foreign_key_list('%q')", rowp[i]);
04139 if (sql) {
04140 dbtraceapi(d, "sqlite3_get_table", sql);
04141 ret = sqlite3_get_table(d->sqlite, sql, &rowpp,
04142 &nnrows, &nncols, NULL);
04143 sqlite3_free(sql);
04144 }
04145 if (ret != SQLITE_OK || nncols * nnrows <= 0) {
04146 sqlite3_free_table(rowpp);
04147 continue;
04148 }
04149 namec = findcol(rowpp, nncols, "table");
04150 seqc = findcol(rowpp, nncols, "seq");
04151 fromc = findcol(rowpp, nncols, "from");
04152 toc = findcol(rowpp, nncols, "to");
04153 if (namec < 0 || seqc < 0 || fromc < 0 || toc < 0) {
04154 sqlite3_free_table(rowpp);
04155 continue;
04156 }
04157 for (k = 1; k <= nnrows; k++) {
04158 int pos = 0, roffs = (offs + 1) * s->ncols;
04159 char *ptab = rowpp[k * nncols + namec];
04160 char buf[32];
04161
04162 if (plen && ptab) {
04163 len = strlen(ptab);
04164 if (len != plen || strncasecmp(pname, ptab, plen) != 0) {
04165 continue;
04166 }
04167 }
04168 s->rows[roffs + 0] = xstrdup("");
04169 s->rows[roffs + 1] = xstrdup("");
04170 s->rows[roffs + 2] = xstrdup(ptab);
04171 s->rows[roffs + 3] = xstrdup(rowpp[k * nncols + toc]);
04172 s->rows[roffs + 4] = xstrdup("");
04173 s->rows[roffs + 5] = xstrdup("");
04174 s->rows[roffs + 6] = xstrdup(rowp[i]);
04175 s->rows[roffs + 7] = xstrdup(rowpp[k * nncols + fromc]);
04176 sscanf(rowpp[k * nncols + seqc], "%d", &pos);
04177 sprintf(buf, "%d", pos + 1);
04178 s->rows[roffs + 8] = xstrdup(buf);
04179 s->rows[roffs + 9] = xstrdup(stringify(SQL_NO_ACTION));
04180 s->rows[roffs + 10] = xstrdup(stringify(SQL_NO_ACTION));
04181 s->rows[roffs + 11] = NULL;
04182 s->rows[roffs + 12] = NULL;
04183 s->rows[roffs + 13] = xstrdup(stringify(SQL_NOT_DEFERRABLE));
04184 offs++;
04185 }
04186 sqlite3_free_table(rowpp);
04187 }
04188 sqlite3_free_table(rowp);
04189 }
04190 return SQL_SUCCESS;
04191 }
04192
04211 SQLRETURN SQL_API
04212 SQLForeignKeys(SQLHSTMT stmt,
04213 SQLCHAR *PKcatalog, SQLSMALLINT PKcatalogLen,
04214 SQLCHAR *PKschema, SQLSMALLINT PKschemaLen,
04215 SQLCHAR *PKtable, SQLSMALLINT PKtableLen,
04216 SQLCHAR *FKcatalog, SQLSMALLINT FKcatalogLen,
04217 SQLCHAR *FKschema, SQLSMALLINT FKschemaLen,
04218 SQLCHAR *FKtable, SQLSMALLINT FKtableLen)
04219 {
04220 return drvforeignkeys(stmt,
04221 PKcatalog, PKcatalogLen,
04222 PKschema, PKschemaLen, PKtable, PKtableLen,
04223 FKcatalog, FKcatalogLen,
04224 FKschema, FKschemaLen,
04225 FKtable, FKtableLen);
04226 }
04227
04235 static SQLRETURN
04236 endtran(DBC *d, SQLSMALLINT comptype)
04237 {
04238 int fail = 0, ret, busy_count = 0;
04239 char *sql, *errp = NULL;
04240
04241 if (!d->sqlite) {
04242 setstatd(d, -1, "not connected", (*d->ov3) ? "HY000" : "S1000");
04243 return SQL_ERROR;
04244 }
04245 if (d->autocommit || !d->intrans) {
04246 return SQL_SUCCESS;
04247 }
04248 switch (comptype) {
04249 case SQL_COMMIT:
04250 sql = "COMMIT TRANSACTION";
04251 goto doit;
04252 case SQL_ROLLBACK:
04253 rollback:
04254 sql = "ROLLBACK TRANSACTION";
04255 doit:
04256 ret = sqlite3_exec(d->sqlite, sql, NULL, NULL, &errp);
04257 dbtracerc(d, ret, errp);
04258 if (ret == SQLITE_BUSY && !fail && comptype == SQL_COMMIT) {
04259 if (busy_handler((void *) d, ++busy_count)) {
04260 if (errp) {
04261 sqlite3_free(errp);
04262 errp = NULL;
04263 }
04264 goto doit;
04265 }
04266 }
04267 d->intrans = 0;
04268 if (ret != SQLITE_OK) {
04269 if (!fail) {
04270 setstatd(d, ret, "%s", (*d->ov3) ? "HY000" : "S1000",
04271 errp ? errp : "transaction failed");
04272 if (errp) {
04273 sqlite3_free(errp);
04274 errp = NULL;
04275 }
04276 fail = 1;
04277 goto rollback;
04278 }
04279 if (errp) {
04280 sqlite3_free(errp);
04281 errp = NULL;
04282 }
04283 return SQL_ERROR;
04284 }
04285 if (errp) {
04286 sqlite3_free(errp);
04287 errp = NULL;
04288 }
04289 return SQL_SUCCESS;
04290 }
04291 setstatd(d, -1, "invalid completion type", (*d->ov3) ? "HY000" : "S1000");
04292 return SQL_ERROR;
04293 }
04294
04303 static SQLRETURN
04304 drvendtran(SQLSMALLINT type, SQLHANDLE handle, SQLSMALLINT comptype)
04305 {
04306 DBC *d;
04307 int fail = 0;
04308
04309 switch (type) {
04310 case SQL_HANDLE_DBC:
04311 if (handle == SQL_NULL_HDBC) {
04312 return SQL_INVALID_HANDLE;
04313 }
04314 d = (DBC *) handle;
04315 return endtran(d, comptype);
04316 case SQL_HANDLE_ENV:
04317 if (handle == SQL_NULL_HENV) {
04318 return SQL_INVALID_HANDLE;
04319 }
04320 d = ((ENV *) handle)->dbcs;
04321 while (d) {
04322 SQLRETURN ret;
04323
04324 ret = endtran(d, comptype);
04325 if (ret != SQL_SUCCESS) {
04326 fail++;
04327 comptype = SQL_ROLLBACK;
04328 }
04329 d = d->next;
04330 }
04331 return fail ? SQL_ERROR : SQL_SUCCESS;
04332 }
04333 return SQL_INVALID_HANDLE;
04334 }
04335
04344 SQLRETURN SQL_API
04345 SQLEndTran(SQLSMALLINT type, SQLHANDLE handle, SQLSMALLINT comptype)
04346 {
04347 return drvendtran(type, handle, comptype);
04348 }
04349
04358 SQLRETURN SQL_API
04359 SQLTransact(SQLHENV env, SQLHDBC dbc, UWORD type)
04360 {
04361 if (env != SQL_NULL_HENV) {
04362 return drvendtran(SQL_HANDLE_ENV, (SQLHANDLE) env, type);
04363 }
04364 return drvendtran(SQL_HANDLE_DBC, (SQLHANDLE) dbc, type);
04365 }
04366
04371 SQLRETURN SQL_API
04372 SQLCopyDesc(SQLHDESC source, SQLHDESC target)
04373 {
04374 return SQL_ERROR;
04375 }
04376
04388 SQLRETURN SQL_API
04389 SQLNativeSql(SQLHSTMT stmt, SQLCHAR *sqlin, SQLINTEGER sqlinLen,
04390 SQLCHAR *sql, SQLINTEGER sqlMax, SQLINTEGER *sqlLen)
04391 {
04392 int outLen = 0;
04393
04394 if (sqlinLen == SQL_NTS) {
04395 sqlinLen = strlen((char *) sqlin);
04396 }
04397 if (sql) {
04398 if (sqlMax > 0) {
04399 strncpy((char *) sql, (char *) sqlin, sqlMax - 1);
04400 sqlin[sqlMax - 1] = '\0';
04401 outLen = min(sqlMax - 1, sqlinLen);
04402 }
04403 } else {
04404 outLen = sqlinLen;
04405 }
04406 if (sqlLen) {
04407 *sqlLen = outLen;
04408 }
04409 if (sql && outLen < sqlinLen) {
04410 setstat((STMT *) stmt, -1, "data right truncated", "01004");
04411 return SQL_SUCCESS_WITH_INFO;
04412 }
04413 return SQL_SUCCESS;
04414 }
04415
04420 static COL procSpec[] = {
04421 { "SYSTEM", "PROCEDURE", "PROCEDURE_QUALIFIER", SCOL_VARCHAR, 50 },
04422 { "SYSTEM", "PROCEDURE", "PROCEDURE_OWNER", SCOL_VARCHAR, 50 },
04423 { "SYSTEM", "PROCEDURE", "PROCEDURE_NAME", SCOL_VARCHAR, 255 },
04424 { "SYSTEM", "PROCEDURE", "NUM_INPUT_PARAMS", SQL_SMALLINT, 5 },
04425 { "SYSTEM", "PROCEDURE", "NUM_OUTPUT_PARAMS", SQL_SMALLINT, 5 },
04426 { "SYSTEM", "PROCEDURE", "NUM_RESULT_SETS", SQL_SMALLINT, 5 },
04427 { "SYSTEM", "PROCEDURE", "REMARKS", SCOL_VARCHAR, 255 },
04428 { "SYSTEM", "PROCEDURE", "PROCEDURE_TYPE", SQL_SMALLINT, 5 }
04429 };
04430
04443 SQLRETURN SQL_API
04444 SQLProcedures(SQLHSTMT stmt,
04445 SQLCHAR *catalog, SQLSMALLINT catalogLen,
04446 SQLCHAR *schema, SQLSMALLINT schemaLen,
04447 SQLCHAR *proc, SQLSMALLINT procLen)
04448 {
04449 return mkresultset(stmt, procSpec, array_size(procSpec));
04450 }
04451
04456 static COL procColSpec[] = {
04457 { "SYSTEM", "PROCCOL", "PROCEDURE_QUALIFIER", SCOL_VARCHAR, 50 },
04458 { "SYSTEM", "PROCCOL", "PROCEDURE_OWNER", SCOL_VARCHAR, 50 },
04459 { "SYSTEM", "PROCCOL", "PROCEDURE_NAME", SCOL_VARCHAR, 255 },
04460 { "SYSTEM", "PROCCOL", "COLUMN_NAME", SCOL_VARCHAR, 255 },
04461 { "SYSTEM", "PROCCOL", "COLUMN_TYPE", SQL_SMALLINT, 5 },
04462 { "SYSTEM", "PROCCOL", "DATA_TYPE", SQL_SMALLINT, 5 },
04463 { "SYSTEM", "PROCCOL", "TYPE_NAME", SCOL_VARCHAR, 50 },
04464 { "SYSTEM", "PROCCOL", "PRECISION", SQL_INTEGER, 10 },
04465 { "SYSTEM", "PROCCOL", "LENGTH", SQL_INTEGER, 10 },
04466 { "SYSTEM", "PROCCOL", "RADIX", SQL_SMALLINT, 5 },
04467 { "SYSTEM", "PROCCOL", "SCALE", SQL_SMALLINT, 5 },
04468 { "SYSTEM", "PROCCOL", "NULLABLE", SQL_SMALLINT, 5 },
04469 { "SYSTEM", "PROCCOL", "REMARKS", SCOL_VARCHAR, 50 },
04470 { "SYSTEM", "PROCCOL", "COLUMN_DEF", SCOL_VARCHAR, 50 },
04471 { "SYSTEM", "PROCCOL", "SQL_DATA_TYPE", SQL_SMALLINT, 5 },
04472 { "SYSTEM", "PROCCOL", "SQL_DATETIME_SUB", SQL_SMALLINT, 5 },
04473 { "SYSTEM", "PROCCOL", "CHAR_OCTET_LENGTH", SQL_SMALLINT, 5 },
04474 { "SYSTEM", "PROCCOL", "ORDINAL_POSITION", SQL_SMALLINT, 5 },
04475 { "SYSTEM", "PROCCOL", "IS_NULLABLE", SCOL_VARCHAR, 50 }
04476 };
04477
04492 SQLRETURN SQL_API
04493 SQLProcedureColumns(SQLHSTMT stmt,
04494 SQLCHAR *catalog, SQLSMALLINT catalogLen,
04495 SQLCHAR *schema, SQLSMALLINT schemaLen,
04496 SQLCHAR *proc, SQLSMALLINT procLen,
04497 SQLCHAR *column, SQLSMALLINT columnLen)
04498 {
04499 return mkresultset(stmt, procColSpec, array_size(procColSpec));
04500
04501 }
04502
04513 SQLRETURN SQL_API
04514 SQLGetEnvAttr(SQLHENV env, SQLINTEGER attr, SQLPOINTER val,
04515 SQLINTEGER len, SQLINTEGER *lenp)
04516 {
04517 ENV *e;
04518
04519 if (env == SQL_NULL_HENV) {
04520 return SQL_INVALID_HANDLE;
04521 }
04522 e = (ENV *) env;
04523 if (!e || e->magic != ENV_MAGIC) {
04524 return SQL_INVALID_HANDLE;
04525 }
04526 switch (attr) {
04527 case SQL_ATTR_CONNECTION_POOLING:
04528 return SQL_ERROR;
04529 case SQL_ATTR_CP_MATCH:
04530 return SQL_NO_DATA;
04531 case SQL_ATTR_OUTPUT_NTS:
04532 if (val) {
04533 *((SQLINTEGER *) val) = SQL_TRUE;
04534 }
04535 if (lenp) {
04536 *lenp = sizeof (SQLINTEGER);
04537 }
04538 return SQL_SUCCESS;
04539 case SQL_ATTR_ODBC_VERSION:
04540 if (val) {
04541 *((SQLINTEGER *) val) = e->ov3 ? SQL_OV_ODBC3 : SQL_OV_ODBC2;
04542 }
04543 if (lenp) {
04544 *lenp = sizeof (SQLINTEGER);
04545 }
04546 return SQL_SUCCESS;
04547 }
04548 return SQL_ERROR;
04549 }
04550
04560 SQLRETURN SQL_API
04561 SQLSetEnvAttr(SQLHENV env, SQLINTEGER attr, SQLPOINTER val, SQLINTEGER len)
04562 {
04563 ENV *e;
04564
04565 if (env == SQL_NULL_HENV) {
04566 return SQL_INVALID_HANDLE;
04567 }
04568 e = (ENV *) env;
04569 if (!e || e->magic != ENV_MAGIC) {
04570 return SQL_INVALID_HANDLE;
04571 }
04572 switch (attr) {
04573 case SQL_ATTR_CONNECTION_POOLING:
04574 return SQL_SUCCESS;
04575 case SQL_ATTR_CP_MATCH:
04576 return SQL_NO_DATA;
04577 case SQL_ATTR_OUTPUT_NTS:
04578 if ((SQLINTEGER) val == SQL_TRUE) {
04579 return SQL_SUCCESS;
04580 }
04581 return SQL_ERROR;
04582 case SQL_ATTR_ODBC_VERSION:
04583 if (!val) {
04584 return SQL_ERROR;
04585 }
04586 if ((SQLINTEGER) val == SQL_OV_ODBC2) {
04587 e->ov3 = 0;
04588 return SQL_SUCCESS;
04589 }
04590 if ((SQLINTEGER) val == SQL_OV_ODBC3) {
04591 e->ov3 = 1;
04592 return SQL_SUCCESS;
04593 }
04594 return SQL_ERROR;
04595 }
04596 return SQL_ERROR;
04597 }
04598
04612 static SQLRETURN
04613 drvgetdiagrec(SQLSMALLINT htype, SQLHANDLE handle, SQLSMALLINT recno,
04614 SQLCHAR *sqlstate, SQLINTEGER *nativeerr, SQLCHAR *msg,
04615 SQLSMALLINT buflen, SQLSMALLINT *msglen)
04616 {
04617 DBC *d = NULL;
04618 STMT *s = NULL;
04619 int len, naterr;
04620 char *logmsg, *sqlst;
04621
04622 if (handle == SQL_NULL_HANDLE) {
04623 return SQL_INVALID_HANDLE;
04624 }
04625 if (sqlstate) {
04626 sqlstate[0] = '\0';
04627 }
04628 if (msg && buflen > 0) {
04629 msg[0] = '\0';
04630 }
04631 if (msglen) {
04632 *msglen = 0;
04633 }
04634 if (nativeerr) {
04635 *nativeerr = 0;
04636 }
04637 switch (htype) {
04638 case SQL_HANDLE_ENV:
04639 case SQL_HANDLE_DESC:
04640 return SQL_NO_DATA;
04641 case SQL_HANDLE_DBC:
04642 d = (DBC *) handle;
04643 logmsg = (char *) d->logmsg;
04644 sqlst = d->sqlstate;
04645 naterr = d->naterr;
04646 break;
04647 case SQL_HANDLE_STMT:
04648 s = (STMT *) handle;
04649 logmsg = (char *) s->logmsg;
04650 sqlst = s->sqlstate;
04651 naterr = s->naterr;
04652 break;
04653 default:
04654 return SQL_INVALID_HANDLE;
04655 }
04656 if (buflen < 0) {
04657 return SQL_ERROR;
04658 }
04659 if (recno > 1) {
04660 return SQL_NO_DATA;
04661 }
04662 len = strlen(logmsg);
04663 if (len == 0) {
04664 return SQL_NO_DATA;
04665 }
04666 if (nativeerr) {
04667 *nativeerr = naterr;
04668 }
04669 if (sqlstate) {
04670 strcpy((char *) sqlstate, sqlst);
04671 }
04672 if (msglen) {
04673 *msglen = len;
04674 }
04675 if (len >= buflen) {
04676 if (msg && buflen > 0) {
04677 strncpy((char *) msg, logmsg, buflen);
04678 msg[buflen - 1] = '\0';
04679 logmsg[0] = '\0';
04680 }
04681 } else if (msg) {
04682 strcpy((char *) msg, logmsg);
04683 logmsg[0] = '\0';
04684 }
04685 return SQL_SUCCESS;
04686 }
04687
04701 SQLRETURN SQL_API
04702 SQLGetDiagRec(SQLSMALLINT htype, SQLHANDLE handle, SQLSMALLINT recno,
04703 SQLCHAR *sqlstate, SQLINTEGER *nativeerr, SQLCHAR *msg,
04704 SQLSMALLINT buflen, SQLSMALLINT *msglen)
04705 {
04706 return drvgetdiagrec(htype, handle, recno, sqlstate,
04707 nativeerr, msg, buflen, msglen);
04708 }
04709
04714 SQLRETURN SQL_API
04715 SQLGetDiagField(SQLSMALLINT htype, SQLHANDLE handle, SQLSMALLINT recno,
04716 SQLSMALLINT id, SQLPOINTER info,
04717 SQLSMALLINT buflen, SQLSMALLINT *strlen)
04718 {
04719 return SQL_ERROR;
04720 }
04721
04732 static SQLRETURN
04733 drvgetstmtattr(SQLHSTMT stmt, SQLINTEGER attr, SQLPOINTER val,
04734 SQLINTEGER bufmax, SQLINTEGER *buflen)
04735 {
04736 STMT *s = (STMT *) stmt;
04737 SQLUINTEGER *uval = (SQLUINTEGER *) val;
04738
04739 switch (attr) {
04740 case SQL_QUERY_TIMEOUT:
04741 *uval = 0;
04742 return SQL_SUCCESS;
04743 case SQL_ATTR_CURSOR_TYPE:
04744 *uval = s->curtype;
04745 return SQL_SUCCESS;
04746 case SQL_ATTR_CURSOR_SCROLLABLE:
04747 *uval = s->curtype != SQL_CURSOR_FORWARD_ONLY ?
04748 SQL_SCROLLABLE : SQL_NONSCROLLABLE;
04749 return SQL_SUCCESS;
04750 #ifdef SQL_ATTR_CURSOR_SENSITIVITY
04751 case SQL_ATTR_CURSOR_SENSITIVITY:
04752 *uval = SQL_UNSPECIFIED;
04753 return SQL_SUCCESS;
04754 #endif
04755 case SQL_ATTR_ROW_NUMBER:
04756 {
04757 STMT *s = (STMT *) stmt;
04758 DBC *d = (DBC *) s->dbc;
04759
04760 if (s == d->cur_s3stmt) {
04761 *uval = d->s3stmt_rownum < 0 ?
04762 SQL_ROW_NUMBER_UNKNOWN : d->s3stmt_rownum;
04763 }
04764 }
04765 *uval = s->rowp < 0 ? SQL_ROW_NUMBER_UNKNOWN : s->rowp;
04766 return SQL_SUCCESS;
04767 case SQL_ATTR_ASYNC_ENABLE:
04768 *uval = SQL_ASYNC_ENABLE_OFF;
04769 return SQL_SUCCESS;
04770 case SQL_CONCURRENCY:
04771 *uval = SQL_CONCUR_LOCK;
04772 return SQL_SUCCESS;
04773 case SQL_ATTR_RETRIEVE_DATA:
04774 *uval = s->retr_data;
04775 return SQL_SUCCESS;
04776 case SQL_ROWSET_SIZE:
04777 case SQL_ATTR_ROW_ARRAY_SIZE:
04778 *uval = s->rowset_size;
04779 return SQL_SUCCESS;
04780
04781 case SQL_ATTR_IMP_ROW_DESC:
04782 case SQL_ATTR_APP_ROW_DESC:
04783 case SQL_ATTR_IMP_PARAM_DESC:
04784 case SQL_ATTR_APP_PARAM_DESC:
04785 *((SQLHDESC *) val) = (SQLHDESC) DEAD_MAGIC;
04786 return SQL_SUCCESS;
04787 case SQL_ATTR_ROW_STATUS_PTR:
04788 *((SQLUSMALLINT **) val) = s->row_status;
04789 return SQL_SUCCESS;
04790 case SQL_ATTR_ROWS_FETCHED_PTR:
04791 *((SQLUINTEGER **) val) = s->row_count;
04792 return SQL_SUCCESS;
04793 case SQL_ATTR_USE_BOOKMARKS: {
04794 STMT *s = (STMT *) stmt;
04795
04796 *(SQLUINTEGER *) val = s->bkmrk ? SQL_UB_ON : SQL_UB_OFF;
04797 return SQL_SUCCESS;
04798 }
04799 case SQL_ATTR_PARAM_BIND_OFFSET_PTR:
04800 *((SQLUINTEGER **) val) = s->parm_bind_offs;
04801 return SQL_SUCCESS;
04802 case SQL_ATTR_PARAM_BIND_TYPE:
04803 *((SQLUINTEGER *) val) = SQL_PARAM_BIND_BY_COLUMN;
04804 return SQL_SUCCESS;
04805 case SQL_ATTR_PARAM_OPERATION_PTR:
04806 *((SQLUSMALLINT **) val) = s->parm_oper;
04807 return SQL_SUCCESS;
04808 case SQL_ATTR_PARAM_STATUS_PTR:
04809 *((SQLUSMALLINT **) val) = s->parm_status;
04810 return SQL_SUCCESS;
04811 case SQL_ATTR_PARAMS_PROCESSED_PTR:
04812 *((SQLUINTEGER **) val) = s->parm_proc;
04813 return SQL_SUCCESS;
04814 case SQL_ATTR_PARAMSET_SIZE:
04815 *((SQLUINTEGER *) val) = s->paramset_size;
04816 return SQL_SUCCESS;
04817 case SQL_ATTR_ROW_BIND_TYPE:
04818 *(SQLUINTEGER *) val = s->bind_type;
04819 return SQL_SUCCESS;
04820 case SQL_ATTR_ROW_BIND_OFFSET_PTR:
04821 *((SQLUINTEGER **) val) = s->bind_offs;
04822 return SQL_SUCCESS;
04823 case SQL_ATTR_MAX_ROWS:
04824 case SQL_ATTR_MAX_LENGTH:
04825 *((SQLINTEGER *) val) = 1000000000;
04826 return SQL_SUCCESS;
04827 }
04828 return drvunimplstmt(stmt);
04829 }
04830
04841 SQLRETURN SQL_API
04842 SQLGetStmtAttr(SQLHSTMT stmt, SQLINTEGER attr, SQLPOINTER val,
04843 SQLINTEGER bufmax, SQLINTEGER *buflen)
04844 {
04845 return drvgetstmtattr(stmt, attr, val, bufmax, buflen);
04846 }
04847
04857 static SQLRETURN
04858 drvsetstmtattr(SQLHSTMT stmt, SQLINTEGER attr, SQLPOINTER val,
04859 SQLINTEGER buflen)
04860 {
04861 STMT *s = (STMT *) stmt;
04862
04863 switch (attr) {
04864 case SQL_ATTR_CURSOR_TYPE:
04865 if ((SQLUINTEGER) val == SQL_CURSOR_FORWARD_ONLY) {
04866 s->curtype = SQL_CURSOR_FORWARD_ONLY;
04867 } else {
04868 s->curtype = SQL_CURSOR_STATIC;
04869 }
04870 if ((SQLUINTEGER) val != SQL_CURSOR_FORWARD_ONLY &&
04871 (SQLUINTEGER) val != SQL_CURSOR_STATIC) {
04872 goto e01s02;
04873 }
04874 return SQL_SUCCESS;
04875 case SQL_ATTR_CURSOR_SCROLLABLE:
04876 if ((SQLUINTEGER) val == SQL_NONSCROLLABLE) {
04877 s->curtype = SQL_CURSOR_FORWARD_ONLY;
04878 } else {
04879 s->curtype = SQL_CURSOR_STATIC;
04880 }
04881 return SQL_SUCCESS;
04882 case SQL_ATTR_ASYNC_ENABLE:
04883 if ((SQLUINTEGER) val != SQL_ASYNC_ENABLE_OFF) {
04884 e01s02:
04885 setstat(s, -1, "option value changed", "01S02");
04886 return SQL_SUCCESS_WITH_INFO;
04887 }
04888 return SQL_SUCCESS;
04889 case SQL_CONCURRENCY:
04890 if ((SQLUINTEGER) val != SQL_CONCUR_LOCK) {
04891 goto e01s02;
04892 }
04893 return SQL_SUCCESS;
04894 case SQL_ATTR_QUERY_TIMEOUT:
04895 return SQL_SUCCESS;
04896 case SQL_ATTR_RETRIEVE_DATA:
04897 if ((SQLUINTEGER) val != SQL_RD_ON &&
04898 (SQLUINTEGER) val != SQL_RD_OFF) {
04899 goto e01s02;
04900 }
04901 s->retr_data = (int) val;
04902 return SQL_SUCCESS;
04903 case SQL_ROWSET_SIZE:
04904 case SQL_ATTR_ROW_ARRAY_SIZE:
04905 if ((SQLUINTEGER) val < 1) {
04906 setstat(s, -1, "invalid rowset size", "HY000");
04907 return SQL_ERROR;
04908 } else {
04909 SQLUSMALLINT *rst = &s->row_status1;
04910
04911 if ((SQLUINTEGER) val > 1) {
04912 rst = xmalloc(sizeof (SQLUSMALLINT) * (SQLUINTEGER) val);
04913 if (!rst) {
04914 return nomem(s);
04915 }
04916 }
04917 if (s->row_status0 != &s->row_status1) {
04918 freep(&s->row_status0);
04919 }
04920 s->row_status0 = rst;
04921 s->rowset_size = (SQLUINTEGER) val;
04922 }
04923 return SQL_SUCCESS;
04924 case SQL_ATTR_ROW_STATUS_PTR:
04925 s->row_status = (SQLUSMALLINT *) val;
04926 return SQL_SUCCESS;
04927 case SQL_ATTR_ROWS_FETCHED_PTR:
04928 s->row_count = (SQLUINTEGER *) val;
04929 return SQL_SUCCESS;
04930 case SQL_ATTR_PARAM_BIND_OFFSET_PTR:
04931 s->parm_bind_offs = (SQLUINTEGER *) val;
04932 return SQL_SUCCESS;
04933 case SQL_ATTR_PARAM_BIND_TYPE:
04934 if ((SQLUINTEGER) val != SQL_PARAM_BIND_BY_COLUMN) {
04935 goto e01s02;
04936 }
04937 return SQL_SUCCESS;
04938 case SQL_ATTR_PARAM_OPERATION_PTR:
04939 s->parm_oper = (SQLUSMALLINT *) val;
04940 return SQL_SUCCESS;
04941 case SQL_ATTR_PARAM_STATUS_PTR:
04942 s->parm_status = (SQLUSMALLINT *) val;
04943 return SQL_SUCCESS;
04944 case SQL_ATTR_PARAMS_PROCESSED_PTR:
04945 s->parm_proc = (SQLUINTEGER *) val;
04946 return SQL_SUCCESS;
04947 case SQL_ATTR_PARAMSET_SIZE:
04948 if ((SQLUINTEGER) val < 1) {
04949 goto e01s02;
04950 }
04951 s->paramset_size = (SQLUINTEGER) val;
04952 s->paramset_count = 0;
04953 return SQL_SUCCESS;
04954 case SQL_ATTR_ROW_BIND_TYPE:
04955 s->bind_type = (SQLUINTEGER) val;
04956 return SQL_SUCCESS;
04957 case SQL_ATTR_ROW_BIND_OFFSET_PTR:
04958 s->bind_offs = (SQLUINTEGER *) val;
04959 return SQL_SUCCESS;
04960 case SQL_ATTR_USE_BOOKMARKS:
04961 if ((SQLUINTEGER) val != SQL_UB_OFF &&
04962 (SQLUINTEGER) val != SQL_UB_ON) {
04963 goto e01s02;
04964 }
04965 s->bkmrk = (SQLUINTEGER) val == SQL_UB_ON;
04966 return SQL_SUCCESS;
04967 case SQL_ATTR_MAX_ROWS:
04968 case SQL_ATTR_MAX_LENGTH:
04969 if ((SQLINTEGER) val != 1000000000) {
04970 goto e01s02;
04971 }
04972 return SQL_SUCCESS;
04973 }
04974 return drvunimplstmt(stmt);
04975 }
04976
04986 SQLRETURN SQL_API
04987 SQLSetStmtAttr(SQLHSTMT stmt, SQLINTEGER attr, SQLPOINTER val,
04988 SQLINTEGER buflen)
04989 {
04990 return drvsetstmtattr(stmt, attr, val, buflen);
04991 }
04992
05001 static SQLRETURN
05002 drvgetstmtoption(SQLHSTMT stmt, SQLUSMALLINT opt, SQLPOINTER param)
05003 {
05004 STMT *s = (STMT *) stmt;
05005 SQLUINTEGER *ret = (SQLUINTEGER *) param;
05006
05007 switch (opt) {
05008 case SQL_QUERY_TIMEOUT:
05009 *ret = 0;
05010 return SQL_SUCCESS;
05011 case SQL_CURSOR_TYPE:
05012 *ret = s->curtype;
05013 return SQL_SUCCESS;
05014 case SQL_ROW_NUMBER:
05015 {
05016 DBC *d = (DBC *) s->dbc;
05017
05018 if (s == d->cur_s3stmt) {
05019 *ret = d->s3stmt_rownum < 0 ?
05020 SQL_ROW_NUMBER_UNKNOWN : d->s3stmt_rownum;
05021 }
05022 }
05023 *ret = s->rowp < 0 ? SQL_ROW_NUMBER_UNKNOWN : s->rowp;
05024 return SQL_SUCCESS;
05025 case SQL_ASYNC_ENABLE:
05026 *ret = SQL_ASYNC_ENABLE_OFF;
05027 return SQL_SUCCESS;
05028 case SQL_CONCURRENCY:
05029 *ret = SQL_CONCUR_LOCK;
05030 return SQL_SUCCESS;
05031 case SQL_ATTR_RETRIEVE_DATA:
05032 *ret = s->retr_data;
05033 return SQL_SUCCESS;
05034 case SQL_ROWSET_SIZE:
05035 case SQL_ATTR_ROW_ARRAY_SIZE:
05036 *ret = s->rowset_size;
05037 return SQL_SUCCESS;
05038 case SQL_ATTR_MAX_ROWS:
05039 case SQL_ATTR_MAX_LENGTH:
05040 *ret = 1000000000;
05041 return SQL_SUCCESS;
05042 }
05043 return drvunimplstmt(stmt);
05044 }
05045
05054 SQLRETURN SQL_API
05055 SQLGetStmtOption(SQLHSTMT stmt, SQLUSMALLINT opt, SQLPOINTER param)
05056 {
05057 return drvgetstmtoption(stmt, opt, param);
05058 }
05059
05068 static SQLRETURN
05069 drvsetstmtoption(SQLHSTMT stmt, SQLUSMALLINT opt, SQLUINTEGER param)
05070 {
05071 STMT *s = (STMT *) stmt;
05072
05073 switch (opt) {
05074 case SQL_CURSOR_TYPE:
05075 if (param == SQL_CURSOR_FORWARD_ONLY) {
05076 s->curtype = param;
05077 } else {
05078 s->curtype = SQL_CURSOR_STATIC;
05079 }
05080 if (param != SQL_CURSOR_FORWARD_ONLY &&
05081 param != SQL_CURSOR_STATIC) {
05082 goto e01s02;
05083 }
05084 return SQL_SUCCESS;
05085 case SQL_ASYNC_ENABLE:
05086 if (param != SQL_ASYNC_ENABLE_OFF) {
05087 goto e01s02;
05088 }
05089 return SQL_SUCCESS;
05090 case SQL_CONCURRENCY:
05091 if (param != SQL_CONCUR_LOCK) {
05092 goto e01s02;
05093 }
05094 return SQL_SUCCESS;
05095 case SQL_QUERY_TIMEOUT:
05096 return SQL_SUCCESS;
05097 case SQL_RETRIEVE_DATA:
05098 if (param != SQL_RD_ON && param != SQL_RD_OFF) {
05099 e01s02:
05100 setstat(s, -1, "option value changed", "01S02");
05101 return SQL_SUCCESS_WITH_INFO;
05102 }
05103 s->retr_data = (int) param;
05104 return SQL_SUCCESS;
05105 case SQL_ROWSET_SIZE:
05106 case SQL_ATTR_ROW_ARRAY_SIZE:
05107 if (param < 1) {
05108 setstat(s, -1, "invalid rowset size", "HY000");
05109 return SQL_ERROR;
05110 } else {
05111 SQLUSMALLINT *rst = &s->row_status1;
05112
05113 if (param > 1) {
05114 rst = xmalloc(sizeof (SQLUSMALLINT) * param);
05115 if (!rst) {
05116 return nomem(s);
05117 }
05118 }
05119 if (s->row_status0 != &s->row_status1) {
05120 freep(&s->row_status0);
05121 }
05122 s->row_status0 = rst;
05123 s->rowset_size = param;
05124 }
05125 return SQL_SUCCESS;
05126 case SQL_ATTR_MAX_ROWS:
05127 case SQL_ATTR_MAX_LENGTH:
05128 if (param != 1000000000) {
05129 goto e01s02;
05130 }
05131 return SQL_SUCCESS;
05132 }
05133 return drvunimplstmt(stmt);
05134 }
05135
05144 SQLRETURN SQL_API
05145 SQLSetStmtOption(SQLHSTMT stmt, SQLUSMALLINT opt, SQLROWCOUNT param)
05146 {
05147 return drvsetstmtoption(stmt, opt, param);
05148 }
05149
05154 SQLRETURN SQL_API
05155 SQLSetPos(SQLHSTMT stmt, SQLUSMALLINT row, SQLUSMALLINT op, SQLUSMALLINT lock)
05156 {
05157 return drvunimplstmt(stmt);
05158 }
05159
05164 SQLRETURN SQL_API
05165 SQLSetScrollOptions(SQLHSTMT stmt, SQLUSMALLINT concur, SQLLEN rowkeyset,
05166 SQLUSMALLINT rowset)
05167 {
05168 return drvunimplstmt(stmt);
05169 }
05170
05171 #define strmak(dst, src, max, lenp) { \
05172 int len = strlen(src); \
05173 int cnt = min(len + 1, max); \
05174 strncpy(dst, src, cnt); \
05175 *lenp = (cnt > len) ? len : cnt; \
05176 }
05177
05188 static SQLRETURN
05189 drvgetinfo(SQLHDBC dbc, SQLUSMALLINT type, SQLPOINTER val, SQLSMALLINT valMax,
05190 SQLSMALLINT *valLen)
05191 {
05192 DBC *d;
05193 char dummyc[16];
05194 SQLSMALLINT dummy;
05195 static char drvname[] =
05196 #ifdef _WIN32
05197 "sqlite3odbc.dll";
05198 #else
05199 "sqlite3odbc.so";
05200 #endif
05201
05202 if (dbc == SQL_NULL_HDBC) {
05203 return SQL_INVALID_HANDLE;
05204 }
05205 d = (DBC *) dbc;
05206 if (valMax) {
05207 valMax--;
05208 }
05209 if (!valLen) {
05210 valLen = &dummy;
05211 }
05212 if (!val) {
05213 val = dummyc;
05214 valMax = sizeof (dummyc) - 1;
05215 }
05216 switch (type) {
05217 case SQL_MAX_USER_NAME_LEN:
05218 *((SQLSMALLINT *) val) = 16;
05219 *valLen = sizeof (SQLSMALLINT);
05220 break;
05221 case SQL_USER_NAME:
05222 strmak(val, "", valMax, valLen);
05223 break;
05224 case SQL_DRIVER_ODBC_VER:
05225 #if 0
05226 strmak(val, (*d->ov3) ? "03.00" : "02.50", valMax, valLen);
05227 #else
05228 strmak(val, "03.00", valMax, valLen);
05229 #endif
05230 break;
05231 case SQL_ACTIVE_CONNECTIONS:
05232 case SQL_ACTIVE_STATEMENTS:
05233 *((SQLSMALLINT *) val) = 0;
05234 *valLen = sizeof (SQLSMALLINT);
05235 break;
05236 #ifdef SQL_ASYNC_MODE
05237 case SQL_ASYNC_MODE:
05238 *((SQLUINTEGER *) val) = SQL_AM_NONE;
05239 *valLen = sizeof (SQLUINTEGER);
05240 break;
05241 #endif
05242 #ifdef SQL_CREATE_TABLE
05243 case SQL_CREATE_TABLE:
05244 *((SQLUINTEGER *) val) = SQL_CT_CREATE_TABLE |
05245 SQL_CT_COLUMN_DEFAULT |
05246 SQL_CT_COLUMN_CONSTRAINT |
05247 SQL_CT_CONSTRAINT_NON_DEFERRABLE;
05248 *valLen = sizeof (SQLUINTEGER);
05249 break;
05250 #endif
05251 #ifdef SQL_CREATE_VIEW
05252 case SQL_CREATE_VIEW:
05253 *((SQLUINTEGER *) val) = SQL_CV_CREATE_VIEW;
05254 *valLen = sizeof (SQLUINTEGER);
05255 break;
05256 #endif
05257 #ifdef SQL_DDL_INDEX
05258 case SQL_DDL_INDEX:
05259 *((SQLUINTEGER *) val) = SQL_DI_CREATE_INDEX | SQL_DI_DROP_INDEX;
05260 *valLen = sizeof (SQLUINTEGER);
05261 break;
05262 #endif
05263 #ifdef SQL_DROP_TABLE
05264 case SQL_DROP_TABLE:
05265 *((SQLUINTEGER *) val) = SQL_DT_DROP_TABLE;
05266 *valLen = sizeof (SQLUINTEGER);
05267 break;
05268 #endif
05269 #ifdef SQL_DROP_VIEW
05270 case SQL_DROP_VIEW:
05271 *((SQLUINTEGER *) val) = SQL_DV_DROP_VIEW;
05272 *valLen = sizeof (SQLUINTEGER);
05273 break;
05274 #endif
05275 #ifdef SQL_INDEX_KEYWORDS
05276 case SQL_INDEX_KEYWORDS:
05277 *((SQLUINTEGER *) val) = SQL_IK_ALL;
05278 *valLen = sizeof (SQLUINTEGER);
05279 break;
05280 #endif
05281 case SQL_DATA_SOURCE_NAME:
05282 strmak(val, (d->dsn ? d->dsn : ""), valMax, valLen);
05283 break;
05284 case SQL_DRIVER_NAME:
05285 strmak(val, drvname, valMax, valLen);
05286 break;
05287 case SQL_DRIVER_VER:
05288 strmak(val, DRIVER_VER_INFO, valMax, valLen);
05289 break;
05290 case SQL_FETCH_DIRECTION:
05291 *((SQLUINTEGER *) val) = SQL_FD_FETCH_NEXT | SQL_FD_FETCH_FIRST |
05292 SQL_FD_FETCH_LAST | SQL_FD_FETCH_PRIOR | SQL_FD_FETCH_ABSOLUTE;
05293 *valLen = sizeof (SQLUINTEGER);
05294 break;
05295 case SQL_ODBC_VER:
05296 strmak(val, (*d->ov3) ? "03.00" : "02.50", valMax, valLen);
05297 break;
05298 case SQL_ODBC_SAG_CLI_CONFORMANCE:
05299 *((SQLSMALLINT *) val) = SQL_OSCC_NOT_COMPLIANT;
05300 *valLen = sizeof (SQLSMALLINT);
05301 break;
05302 case SQL_STANDARD_CLI_CONFORMANCE:
05303 *((SQLUINTEGER *) val) = SQL_SCC_XOPEN_CLI_VERSION1;
05304 *valLen = sizeof (SQLUINTEGER);
05305 break;
05306 case SQL_SERVER_NAME:
05307 case SQL_DATABASE_NAME:
05308 strmak(val, (d->dbname ? d->dbname : ""), valMax, valLen);
05309 break;
05310 case SQL_SEARCH_PATTERN_ESCAPE:
05311 strmak(val, "", valMax, valLen);
05312 break;
05313 case SQL_ODBC_SQL_CONFORMANCE:
05314 *((SQLSMALLINT *) val) = SQL_OSC_MINIMUM;
05315 *valLen = sizeof (SQLSMALLINT);
05316 break;
05317 case SQL_ODBC_API_CONFORMANCE:
05318 *((SQLSMALLINT *) val) = SQL_OAC_LEVEL1;
05319 *valLen = sizeof (SQLSMALLINT);
05320 break;
05321 case SQL_DBMS_NAME:
05322 strmak(val, "SQLite", valMax, valLen);
05323 break;
05324 case SQL_DBMS_VER:
05325 strmak(val, SQLITE_VERSION, valMax, valLen);
05326 break;
05327 case SQL_COLUMN_ALIAS:
05328 case SQL_NEED_LONG_DATA_LEN:
05329 strmak(val, "Y", valMax, valLen);
05330 break;
05331 case SQL_ROW_UPDATES:
05332 case SQL_ACCESSIBLE_PROCEDURES:
05333 case SQL_PROCEDURES:
05334 case SQL_EXPRESSIONS_IN_ORDERBY:
05335 case SQL_ODBC_SQL_OPT_IEF:
05336 case SQL_LIKE_ESCAPE_CLAUSE:
05337 case SQL_ORDER_BY_COLUMNS_IN_SELECT:
05338 case SQL_OUTER_JOINS:
05339 case SQL_ACCESSIBLE_TABLES:
05340 case SQL_MULT_RESULT_SETS:
05341 case SQL_MULTIPLE_ACTIVE_TXN:
05342 case SQL_MAX_ROW_SIZE_INCLUDES_LONG:
05343 strmak(val, "N", valMax, valLen);
05344 break;
05345 case SQL_DATA_SOURCE_READ_ONLY:
05346 strmak(val, "N", valMax, valLen);
05347 break;
05348 #ifdef SQL_OJ_CAPABILITIES
05349 case SQL_OJ_CAPABILITIES:
05350 *((SQLUINTEGER *) val) = 0;
05351 *valLen = sizeof (SQLUINTEGER);
05352 break;
05353 #endif
05354 #ifdef SQL_MAX_IDENTIFIER_LEN
05355 case SQL_MAX_IDENTIFIER_LEN:
05356 *((SQLUSMALLINT *) val) = 255;
05357 *valLen = sizeof (SQLUSMALLINT);
05358 break;
05359 #endif
05360 case SQL_CONCAT_NULL_BEHAVIOR:
05361 *((SQLSMALLINT *) val) = SQL_CB_NULL;
05362 *valLen = sizeof (SQLSMALLINT);
05363 break;
05364 case SQL_CURSOR_COMMIT_BEHAVIOR:
05365 case SQL_CURSOR_ROLLBACK_BEHAVIOR:
05366 *((SQLSMALLINT *) val) = SQL_CB_PRESERVE;
05367 *valLen = sizeof (SQLSMALLINT);
05368 break;
05369 #ifdef SQL_CURSOR_SENSITIVITY
05370 case SQL_CURSOR_SENSITIVITY:
05371 *((SQLUINTEGER *) val) = SQL_UNSPECIFIED;
05372 *valLen = sizeof (SQLUINTEGER);
05373 break;
05374 #endif
05375 case SQL_DEFAULT_TXN_ISOLATION:
05376 *((SQLUINTEGER *) val) = SQL_TXN_READ_UNCOMMITTED;
05377 *valLen = sizeof (SQLUINTEGER);
05378 break;
05379 #ifdef SQL_DESCRIBE_PARAMETER
05380 case SQL_DESCRIBE_PARAMETER:
05381 strmak(val, "Y", valMax, valLen);
05382 break;
05383 #endif
05384 case SQL_TXN_ISOLATION_OPTION:
05385 *((SQLUINTEGER *) val) = SQL_TXN_READ_UNCOMMITTED;
05386 *valLen = sizeof (SQLUINTEGER);
05387 break;
05388 case SQL_IDENTIFIER_CASE:
05389 *((SQLSMALLINT *) val) = SQL_IC_SENSITIVE;
05390 *valLen = sizeof (SQLSMALLINT);
05391 break;
05392 case SQL_IDENTIFIER_QUOTE_CHAR:
05393 strmak(val, "\"", valMax, valLen);
05394 break;
05395 case SQL_MAX_TABLE_NAME_LEN:
05396 case SQL_MAX_COLUMN_NAME_LEN:
05397 *((SQLSMALLINT *) val) = 255;
05398 *valLen = sizeof (SQLSMALLINT);
05399 break;
05400 case SQL_MAX_CURSOR_NAME_LEN:
05401 *((SWORD *) val) = 255;
05402 *valLen = sizeof (SWORD);
05403 break;
05404 case SQL_MAX_PROCEDURE_NAME_LEN:
05405 *((SQLSMALLINT *) val) = 0;
05406 break;
05407 case SQL_MAX_QUALIFIER_NAME_LEN:
05408 case SQL_MAX_OWNER_NAME_LEN:
05409 *((SQLSMALLINT *) val) = 255;
05410 break;
05411 case SQL_OWNER_TERM:
05412 strmak(val, "owner", valMax, valLen);
05413 break;
05414 case SQL_PROCEDURE_TERM:
05415 strmak(val, "procedure", valMax, valLen);
05416 break;
05417 case SQL_QUALIFIER_NAME_SEPARATOR:
05418 strmak(val, ".", valMax, valLen);
05419 break;
05420 case SQL_QUALIFIER_TERM:
05421 strmak(val, "database", valMax, valLen);
05422 break;
05423 case SQL_QUALIFIER_USAGE:
05424 *((SQLUINTEGER *) val) = 0;
05425 *valLen = sizeof (SQLUINTEGER);
05426 break;
05427 case SQL_SCROLL_CONCURRENCY:
05428 *((SQLUINTEGER *) val) = SQL_SCCO_LOCK;
05429 *valLen = sizeof (SQLUINTEGER);
05430 break;
05431 case SQL_SCROLL_OPTIONS:
05432 *((SQLUINTEGER *) val) = SQL_SO_STATIC | SQL_SO_FORWARD_ONLY;
05433 *valLen = sizeof (SQLUINTEGER);
05434 break;
05435 case SQL_TABLE_TERM:
05436 strmak(val, "table", valMax, valLen);
05437 break;
05438 case SQL_TXN_CAPABLE:
05439 *((SQLSMALLINT *) val) = SQL_TC_ALL;
05440 *valLen = sizeof (SQLSMALLINT);
05441 break;
05442 case SQL_CONVERT_FUNCTIONS:
05443 *((SQLUINTEGER *) val) = 0;
05444 *valLen = sizeof (SQLUINTEGER);
05445 break;
05446 case SQL_SYSTEM_FUNCTIONS:
05447 case SQL_NUMERIC_FUNCTIONS:
05448 case SQL_STRING_FUNCTIONS:
05449 case SQL_TIMEDATE_FUNCTIONS:
05450 *((SQLUINTEGER *) val) = 0;
05451 *valLen = sizeof (SQLUINTEGER);
05452 break;
05453 case SQL_CONVERT_BIGINT:
05454 case SQL_CONVERT_BIT:
05455 case SQL_CONVERT_CHAR:
05456 case SQL_CONVERT_DATE:
05457 case SQL_CONVERT_DECIMAL:
05458 case SQL_CONVERT_DOUBLE:
05459 case SQL_CONVERT_FLOAT:
05460 case SQL_CONVERT_INTEGER:
05461 case SQL_CONVERT_LONGVARCHAR:
05462 case SQL_CONVERT_NUMERIC:
05463 case SQL_CONVERT_REAL:
05464 case SQL_CONVERT_SMALLINT:
05465 case SQL_CONVERT_TIME:
05466 case SQL_CONVERT_TIMESTAMP:
05467 case SQL_CONVERT_TINYINT:
05468 case SQL_CONVERT_VARCHAR:
05469 *((SQLUINTEGER *) val) =
05470 SQL_CVT_CHAR | SQL_CVT_NUMERIC | SQL_CVT_DECIMAL |
05471 SQL_CVT_INTEGER | SQL_CVT_SMALLINT | SQL_CVT_FLOAT | SQL_CVT_REAL |
05472 SQL_CVT_DOUBLE | SQL_CVT_VARCHAR | SQL_CVT_LONGVARCHAR |
05473 SQL_CVT_BIT | SQL_CVT_TINYINT | SQL_CVT_BIGINT |
05474 SQL_CVT_DATE | SQL_CVT_TIME | SQL_CVT_TIMESTAMP;
05475 *valLen = sizeof (SQLUINTEGER);
05476 break;
05477 case SQL_CONVERT_BINARY:
05478 case SQL_CONVERT_VARBINARY:
05479 case SQL_CONVERT_LONGVARBINARY:
05480 *((SQLUINTEGER *) val) = 0;
05481 *valLen = sizeof (SQLUINTEGER);
05482 break;
05483 case SQL_POSITIONED_STATEMENTS:
05484 case SQL_LOCK_TYPES:
05485 *((SQLUINTEGER *) val) = 0;
05486 *valLen = sizeof (SQLUINTEGER);
05487 break;
05488 case SQL_BOOKMARK_PERSISTENCE:
05489 *((SQLUINTEGER *) val) = SQL_BP_SCROLL;
05490 *valLen = sizeof (SQLUINTEGER);
05491 break;
05492 case SQL_UNION:
05493 *((SQLUINTEGER *) val) = SQL_U_UNION;
05494 *valLen = sizeof (SQLUINTEGER);
05495 break;
05496 case SQL_OWNER_USAGE:
05497 case SQL_SUBQUERIES:
05498 case SQL_TIMEDATE_ADD_INTERVALS:
05499 case SQL_TIMEDATE_DIFF_INTERVALS:
05500 *((SQLUINTEGER *) val) = 0;
05501 *valLen = sizeof (SQLUINTEGER);
05502 break;
05503 case SQL_QUOTED_IDENTIFIER_CASE:
05504 *((SQLUSMALLINT *) val) = SQL_IC_SENSITIVE;
05505 *valLen = sizeof (SQLUSMALLINT);
05506 break;
05507 case SQL_POS_OPERATIONS:
05508 *((SQLUINTEGER *) val) = 0;
05509 *valLen = sizeof (SQLUINTEGER);
05510 break;
05511 case SQL_ALTER_TABLE:
05512 *((SQLUINTEGER *) val) = 0;
05513 *valLen = sizeof (SQLUINTEGER);
05514 break;
05515 case SQL_CORRELATION_NAME:
05516 *((SQLSMALLINT *) val) = SQL_CN_DIFFERENT;
05517 *valLen = sizeof (SQLSMALLINT);
05518 break;
05519 case SQL_NON_NULLABLE_COLUMNS:
05520 *((SQLSMALLINT *) val) = SQL_NNC_NON_NULL;
05521 *valLen = sizeof (SQLSMALLINT);
05522 break;
05523 case SQL_NULL_COLLATION:
05524 *((SQLSMALLINT *) val) = SQL_NC_START;
05525 *valLen = sizeof (SQLSMALLINT);
05526 break;
05527 case SQL_MAX_COLUMNS_IN_GROUP_BY:
05528 case SQL_MAX_COLUMNS_IN_ORDER_BY:
05529 case SQL_MAX_COLUMNS_IN_SELECT:
05530 case SQL_MAX_COLUMNS_IN_TABLE:
05531 case SQL_MAX_ROW_SIZE:
05532 case SQL_MAX_TABLES_IN_SELECT:
05533 *((SQLSMALLINT *) val) = 0;
05534 *valLen = sizeof (SQLSMALLINT);
05535 break;
05536 case SQL_MAX_BINARY_LITERAL_LEN:
05537 case SQL_MAX_CHAR_LITERAL_LEN:
05538 *((SQLUINTEGER *) val) = 0;
05539 *valLen = sizeof (SQLUINTEGER);
05540 break;
05541 case SQL_MAX_COLUMNS_IN_INDEX:
05542 *((SQLSMALLINT *) val) = 0;
05543 *valLen = sizeof (SQLSMALLINT);
05544 break;
05545 case SQL_MAX_INDEX_SIZE:
05546 *((SQLUINTEGER *) val) = 0;
05547 *valLen = sizeof (SQLUINTEGER);
05548 break;
05549 #ifdef SQL_MAX_IDENTIFIER_LENGTH
05550 case SQL_MAX_IDENTIFIER_LENGTH:
05551 *((SQLUINTEGER *) val) = 255;
05552 *valLen = sizeof (SQLUINTEGER);
05553 break;
05554 #endif
05555 case SQL_MAX_STATEMENT_LEN:
05556 *((SQLUINTEGER *) val) = 16384;
05557 *valLen = sizeof (SQLUINTEGER);
05558 break;
05559 case SQL_QUALIFIER_LOCATION:
05560 *((SQLSMALLINT *) val) = SQL_QL_START;
05561 *valLen = sizeof (SQLSMALLINT);
05562 break;
05563 case SQL_GETDATA_EXTENSIONS:
05564 *((SQLUINTEGER *) val) =
05565 SQL_GD_ANY_COLUMN | SQL_GD_ANY_ORDER | SQL_GD_BOUND;
05566 *valLen = sizeof (SQLUINTEGER);
05567 break;
05568 case SQL_STATIC_SENSITIVITY:
05569 *((SQLUINTEGER *) val) = 0;
05570 *valLen = sizeof (SQLUINTEGER);
05571 break;
05572 case SQL_FILE_USAGE:
05573 *((SQLSMALLINT *) val) = SQL_FILE_CATALOG;
05574 *valLen = sizeof (SQLSMALLINT);
05575 break;
05576 case SQL_GROUP_BY:
05577 *((SQLSMALLINT *) val) = 0;
05578 *valLen = sizeof (SQLSMALLINT);
05579 break;
05580 case SQL_KEYWORDS:
05581 strmak(val, "CREATE,SELECT,DROP,DELETE,UPDATE,INSERT,"
05582 "INTO,VALUES,TABLE,INDEX,FROM,SET,WHERE,AND,CURRENT,OF",
05583 valMax, valLen);
05584 break;
05585 case SQL_SPECIAL_CHARACTERS:
05586 strmak(val, "", valMax, valLen);
05587 break;
05588 case SQL_BATCH_SUPPORT:
05589 case SQL_BATCH_ROW_COUNT:
05590 case SQL_PARAM_ARRAY_ROW_COUNTS:
05591 *((SQLUINTEGER *) val) = 0;
05592 *valLen = sizeof (SQLUINTEGER);
05593 break;
05594 case SQL_FORWARD_ONLY_CURSOR_ATTRIBUTES1:
05595 *((SQLUINTEGER *) val) = SQL_CA1_NEXT | SQL_CA1_BOOKMARK;
05596 *valLen = sizeof (SQLUINTEGER);
05597 break;
05598 case SQL_STATIC_CURSOR_ATTRIBUTES1:
05599 *((SQLUINTEGER *) val) = SQL_CA1_NEXT | SQL_CA1_ABSOLUTE |
05600 SQL_CA1_RELATIVE | SQL_CA1_BOOKMARK;
05601 *valLen = sizeof (SQLUINTEGER);
05602 break;
05603 case SQL_FORWARD_ONLY_CURSOR_ATTRIBUTES2:
05604 case SQL_STATIC_CURSOR_ATTRIBUTES2:
05605 *((SQLUINTEGER *) val) = SQL_CA2_READ_ONLY_CONCURRENCY |
05606 SQL_CA2_LOCK_CONCURRENCY;
05607 *valLen = sizeof (SQLUINTEGER);
05608 break;
05609 case SQL_KEYSET_CURSOR_ATTRIBUTES1:
05610 case SQL_KEYSET_CURSOR_ATTRIBUTES2:
05611 case SQL_DYNAMIC_CURSOR_ATTRIBUTES1:
05612 case SQL_DYNAMIC_CURSOR_ATTRIBUTES2:
05613 *((SQLUINTEGER *) val) = 0;
05614 *valLen = sizeof (SQLUINTEGER);
05615 break;
05616 case SQL_ODBC_INTERFACE_CONFORMANCE:
05617 *((SQLUINTEGER *) val) = SQL_OIC_CORE;
05618 *valLen = sizeof (SQLUINTEGER);
05619 break;
05620 default:
05621 setstatd(d, -1, "unsupported info option %d",
05622 (*d->ov3) ? "HYC00" : "S1C00", type);
05623 return SQL_ERROR;
05624 }
05625 return SQL_SUCCESS;
05626 }
05627
05638 SQLRETURN SQL_API
05639 SQLGetInfo(SQLHDBC dbc, SQLUSMALLINT type, SQLPOINTER val, SQLSMALLINT valMax,
05640 SQLSMALLINT *valLen)
05641 {
05642 return drvgetinfo(dbc, type, val, valMax, valLen);
05643 }
05644
05653 SQLRETURN SQL_API
05654 SQLGetFunctions(SQLHDBC dbc, SQLUSMALLINT func,
05655 SQLUSMALLINT *flags)
05656 {
05657 DBC *d;
05658 int i;
05659 SQLUSMALLINT exists[100];
05660
05661 if (dbc == SQL_NULL_HDBC) {
05662 return SQL_INVALID_HANDLE;
05663 }
05664 d = (DBC *) dbc;
05665 for (i = 0; i < array_size(exists); i++) {
05666 exists[i] = SQL_FALSE;
05667 }
05668 exists[SQL_API_SQLALLOCCONNECT] = SQL_TRUE;
05669 exists[SQL_API_SQLFETCH] = SQL_TRUE;
05670 exists[SQL_API_SQLALLOCENV] = SQL_TRUE;
05671 exists[SQL_API_SQLFREECONNECT] = SQL_TRUE;
05672 exists[SQL_API_SQLALLOCSTMT] = SQL_TRUE;
05673 exists[SQL_API_SQLFREEENV] = SQL_TRUE;
05674 exists[SQL_API_SQLBINDCOL] = SQL_TRUE;
05675 exists[SQL_API_SQLFREESTMT] = SQL_TRUE;
05676 exists[SQL_API_SQLCANCEL] = SQL_TRUE;
05677 exists[SQL_API_SQLGETCURSORNAME] = SQL_TRUE;
05678 exists[SQL_API_SQLCOLATTRIBUTES] = SQL_TRUE;
05679 exists[SQL_API_SQLNUMRESULTCOLS] = SQL_TRUE;
05680 exists[SQL_API_SQLCONNECT] = SQL_TRUE;
05681 exists[SQL_API_SQLPREPARE] = SQL_TRUE;
05682 exists[SQL_API_SQLDESCRIBECOL] = SQL_TRUE;
05683 exists[SQL_API_SQLROWCOUNT] = SQL_TRUE;
05684 exists[SQL_API_SQLDISCONNECT] = SQL_TRUE;
05685 exists[SQL_API_SQLSETCURSORNAME] = SQL_FALSE;
05686 exists[SQL_API_SQLERROR] = SQL_TRUE;
05687 exists[SQL_API_SQLSETPARAM] = SQL_TRUE;
05688 exists[SQL_API_SQLEXECDIRECT] = SQL_TRUE;
05689 exists[SQL_API_SQLTRANSACT] = SQL_TRUE;
05690 exists[SQL_API_SQLEXECUTE] = SQL_TRUE;
05691 exists[SQL_API_SQLBINDPARAMETER] = SQL_TRUE;
05692 exists[SQL_API_SQLGETTYPEINFO] = SQL_TRUE;
05693 exists[SQL_API_SQLCOLUMNS] = SQL_TRUE;
05694 exists[SQL_API_SQLPARAMDATA] = SQL_TRUE;
05695 exists[SQL_API_SQLDRIVERCONNECT] = SQL_TRUE;
05696 exists[SQL_API_SQLPUTDATA] = SQL_TRUE;
05697 exists[SQL_API_SQLGETCONNECTOPTION] = SQL_TRUE;
05698 exists[SQL_API_SQLSETCONNECTOPTION] = SQL_TRUE;
05699 exists[SQL_API_SQLGETDATA] = SQL_TRUE;
05700 exists[SQL_API_SQLSETSTMTOPTION] = SQL_TRUE;
05701 exists[SQL_API_SQLGETFUNCTIONS] = SQL_TRUE;
05702 exists[SQL_API_SQLSPECIALCOLUMNS] = SQL_TRUE;
05703 exists[SQL_API_SQLGETINFO] = SQL_TRUE;
05704 exists[SQL_API_SQLSTATISTICS] = SQL_TRUE;
05705 exists[SQL_API_SQLGETSTMTOPTION] = SQL_TRUE;
05706 exists[SQL_API_SQLTABLES] = SQL_TRUE;
05707 exists[SQL_API_SQLBROWSECONNECT] = SQL_FALSE;
05708 exists[SQL_API_SQLNUMPARAMS] = SQL_TRUE;
05709 exists[SQL_API_SQLCOLUMNPRIVILEGES] = SQL_FALSE;
05710 exists[SQL_API_SQLPARAMOPTIONS] = SQL_FALSE;
05711 exists[SQL_API_SQLDATASOURCES] = SQL_TRUE;
05712 exists[SQL_API_SQLPRIMARYKEYS] = SQL_TRUE;
05713 exists[SQL_API_SQLDESCRIBEPARAM] = SQL_TRUE;
05714 exists[SQL_API_SQLPROCEDURECOLUMNS] = SQL_TRUE;
05715 exists[SQL_API_SQLDRIVERS] = SQL_FALSE;
05716 exists[SQL_API_SQLPROCEDURES] = SQL_TRUE;
05717 exists[SQL_API_SQLEXTENDEDFETCH] = SQL_TRUE;
05718 exists[SQL_API_SQLSETPOS] = SQL_FALSE;
05719 exists[SQL_API_SQLFOREIGNKEYS] = SQL_TRUE;
05720 exists[SQL_API_SQLSETSCROLLOPTIONS] = SQL_TRUE;
05721 exists[SQL_API_SQLMORERESULTS] = SQL_TRUE;
05722 exists[SQL_API_SQLTABLEPRIVILEGES] = SQL_FALSE;
05723 exists[SQL_API_SQLNATIVESQL] = SQL_TRUE;
05724 if (func == SQL_API_ALL_FUNCTIONS) {
05725 memcpy(flags, exists, sizeof (exists));
05726 } else if (func == SQL_API_ODBC3_ALL_FUNCTIONS) {
05727 int i;
05728 #define SET_EXISTS(x) \
05729 flags[(x) >> 4] |= (1 << ((x) & 0xF))
05730 #define CLR_EXISTS(x) \
05731 flags[(x) >> 4] &= ~(1 << ((x) & 0xF))
05732
05733 memset(flags, 0,
05734 sizeof (SQLUSMALLINT) * SQL_API_ODBC3_ALL_FUNCTIONS_SIZE);
05735 for (i = 0; i < array_size(exists); i++) {
05736 if (exists[i]) {
05737 flags[i >> 4] |= (1 << (i & 0xF));
05738 }
05739 }
05740 SET_EXISTS(SQL_API_SQLALLOCHANDLE);
05741 SET_EXISTS(SQL_API_SQLFREEHANDLE);
05742 SET_EXISTS(SQL_API_SQLGETSTMTATTR);
05743 SET_EXISTS(SQL_API_SQLSETSTMTATTR);
05744 SET_EXISTS(SQL_API_SQLGETCONNECTATTR);
05745 SET_EXISTS(SQL_API_SQLSETCONNECTATTR);
05746 SET_EXISTS(SQL_API_SQLGETENVATTR);
05747 SET_EXISTS(SQL_API_SQLSETENVATTR);
05748 SET_EXISTS(SQL_API_SQLCLOSECURSOR);
05749 SET_EXISTS(SQL_API_SQLBINDPARAM);
05750 #if !defined(HAVE_UNIXODBC) || !HAVE_UNIXODBC
05751
05752
05753
05754
05755
05756 SET_EXISTS(SQL_API_SQLGETDIAGREC);
05757 #endif
05758 SET_EXISTS(SQL_API_SQLFETCHSCROLL);
05759 SET_EXISTS(SQL_API_SQLENDTRAN);
05760 } else {
05761 if (func < array_size(exists)) {
05762 *flags = exists[func];
05763 } else {
05764 switch (func) {
05765 case SQL_API_SQLALLOCHANDLE:
05766 case SQL_API_SQLFREEHANDLE:
05767 case SQL_API_SQLGETSTMTATTR:
05768 case SQL_API_SQLSETSTMTATTR:
05769 case SQL_API_SQLGETCONNECTATTR:
05770 case SQL_API_SQLSETCONNECTATTR:
05771 case SQL_API_SQLGETENVATTR:
05772 case SQL_API_SQLSETENVATTR:
05773 case SQL_API_SQLCLOSECURSOR:
05774 case SQL_API_SQLBINDPARAM:
05775 #if !defined(HAVE_UNIXODBC) || !HAVE_UNIXODBC
05776
05777
05778
05779
05780
05781 case SQL_API_SQLGETDIAGREC:
05782 #endif
05783 case SQL_API_SQLFETCHSCROLL:
05784 case SQL_API_SQLENDTRAN:
05785 *flags = SQL_TRUE;
05786 break;
05787 default:
05788 *flags = SQL_FALSE;
05789 }
05790 }
05791 }
05792 return SQL_SUCCESS;
05793 }
05794
05801 static SQLRETURN
05802 drvallocenv(SQLHENV *env)
05803 {
05804 ENV *e;
05805
05806 if (env == NULL) {
05807 return SQL_INVALID_HANDLE;
05808 }
05809 e = (ENV *) xmalloc(sizeof (ENV));
05810 if (e == NULL) {
05811 *env = SQL_NULL_HENV;
05812 return SQL_ERROR;
05813 }
05814 e->magic = ENV_MAGIC;
05815 e->ov3 = 0;
05816 e->dbcs = NULL;
05817 *env = (SQLHENV) e;
05818 return SQL_SUCCESS;
05819 }
05820
05827 SQLRETURN SQL_API
05828 SQLAllocEnv(SQLHENV *env)
05829 {
05830 return drvallocenv(env);
05831 }
05832
05839 static SQLRETURN
05840 drvfreeenv(SQLHENV env)
05841 {
05842 ENV *e;
05843
05844 if (env == SQL_NULL_HENV) {
05845 return SQL_INVALID_HANDLE;
05846 }
05847 e = (ENV *) env;
05848 if (e->magic != ENV_MAGIC) {
05849 return SQL_SUCCESS;
05850 }
05851 if (e->dbcs) {
05852 return SQL_ERROR;
05853 }
05854 e->magic = DEAD_MAGIC;
05855 xfree(e);
05856 return SQL_SUCCESS;
05857 }
05858
05865 SQLRETURN SQL_API
05866 SQLFreeEnv(SQLHENV env)
05867 {
05868 return drvfreeenv(env);
05869 }
05870
05878 static SQLRETURN
05879 drvallocconnect(SQLHENV env, SQLHDBC *dbc)
05880 {
05881 DBC *d;
05882 ENV *e;
05883 const char *verstr;
05884 int maj = 0, min = 0, lev = 0;
05885
05886 if (dbc == NULL) {
05887 return SQL_ERROR;
05888 }
05889 d = (DBC *) xmalloc(sizeof (DBC));
05890 if (d == NULL) {
05891 *dbc = SQL_NULL_HDBC;
05892 return SQL_ERROR;
05893 }
05894 memset(d, 0, sizeof (DBC));
05895 d->curtype = SQL_CURSOR_STATIC;
05896 d->ov3 = &d->ov3val;
05897 verstr = sqlite3_libversion();
05898 sscanf(verstr, "%d.%d.%d", &maj, &min, &lev);
05899 d->version = verinfo(maj & 0xFF, min & 0xFF, lev & 0xFF);
05900 e = (ENV *) env;
05901 if (e->magic == ENV_MAGIC) {
05902 DBC *n, *p;
05903
05904 d->env = e;
05905 d->ov3 = &e->ov3;
05906 p = NULL;
05907 n = e->dbcs;
05908 while (n) {
05909 p = n;
05910 n = n->next;
05911 }
05912 if (p) {
05913 p->next = d;
05914 } else {
05915 e->dbcs = d;
05916 }
05917 }
05918 d->autocommit = 1;
05919 d->magic = DBC_MAGIC;
05920 *dbc = (SQLHDBC) d;
05921 drvgetgpps(d);
05922 return SQL_SUCCESS;
05923 }
05924
05932 SQLRETURN SQL_API
05933 SQLAllocConnect(SQLHENV env, SQLHDBC *dbc)
05934 {
05935 return drvallocconnect(env, dbc);
05936 }
05937
05944 static SQLRETURN
05945 drvfreeconnect(SQLHDBC dbc)
05946 {
05947 DBC *d;
05948 ENV *e;
05949
05950 if (dbc == SQL_NULL_HDBC) {
05951 return SQL_INVALID_HANDLE;
05952 }
05953 d = (DBC *) dbc;
05954 if (d->magic != DBC_MAGIC) {
05955 return SQL_INVALID_HANDLE;
05956 }
05957 if (d->sqlite) {
05958 setstatd(d, -1, "not disconnected", (*d->ov3) ? "HY000" : "S1000");
05959 return SQL_ERROR;
05960 }
05961 while (d->stmt) {
05962 freestmt((HSTMT) d->stmt);
05963 }
05964 e = d->env;
05965 if (e && e->magic == ENV_MAGIC) {
05966 DBC *n, *p;
05967
05968 p = NULL;
05969 n = e->dbcs;
05970 while (n) {
05971 if (n == d) {
05972 break;
05973 }
05974 p = n;
05975 n = n->next;
05976 }
05977 if (n) {
05978 if (p) {
05979 p->next = d->next;
05980 } else {
05981 e->dbcs = d->next;
05982 }
05983 }
05984 }
05985 drvrelgpps(d);
05986 d->magic = DEAD_MAGIC;
05987 if (d->trace) {
05988 fclose(d->trace);
05989 }
05990 xfree(d);
05991 return SQL_SUCCESS;
05992 }
05993
06000 SQLRETURN SQL_API
06001 SQLFreeConnect(SQLHDBC dbc)
06002 {
06003 return drvfreeconnect(dbc);
06004 }
06005
06016 static SQLRETURN
06017 drvgetconnectattr(SQLHDBC dbc, SQLINTEGER attr, SQLPOINTER val,
06018 SQLINTEGER bufmax, SQLINTEGER *buflen)
06019 {
06020 DBC *d;
06021 SQLINTEGER dummy;
06022
06023 if (dbc == SQL_NULL_HDBC) {
06024 return SQL_INVALID_HANDLE;
06025 }
06026 d = (DBC *) dbc;
06027 if (!val) {
06028 val = (SQLPOINTER) &dummy;
06029 }
06030 if (!buflen) {
06031 buflen = &dummy;
06032 }
06033 switch (attr) {
06034 case SQL_ATTR_CONNECTION_DEAD:
06035 *((SQLINTEGER *) val) = d->sqlite ? SQL_CD_FALSE : SQL_CD_TRUE;
06036 *buflen = sizeof (SQLINTEGER);
06037 break;
06038 case SQL_ATTR_ACCESS_MODE:
06039 *((SQLINTEGER *) val) = SQL_MODE_READ_WRITE;
06040 *buflen = sizeof (SQLINTEGER);
06041 break;
06042 case SQL_ATTR_AUTOCOMMIT:
06043 *((SQLINTEGER *) val) =
06044 d->autocommit ? SQL_AUTOCOMMIT_ON : SQL_AUTOCOMMIT_OFF;
06045 *buflen = sizeof (SQLINTEGER);
06046 break;
06047 case SQL_ATTR_LOGIN_TIMEOUT:
06048 *((SQLINTEGER *) val) = 100;
06049 *buflen = sizeof (SQLINTEGER);
06050 break;
06051 case SQL_ATTR_ODBC_CURSORS:
06052 *((SQLINTEGER *) val) = SQL_CUR_USE_DRIVER;
06053 *buflen = sizeof (SQLINTEGER);
06054 break;
06055 case SQL_ATTR_PACKET_SIZE:
06056 *((SQLINTEGER *) val) = 16384;
06057 *buflen = sizeof (SQLINTEGER);
06058 break;
06059 case SQL_ATTR_TXN_ISOLATION:
06060 *((SQLINTEGER *) val) = SQL_TXN_READ_UNCOMMITTED;
06061 *buflen = sizeof (SQLINTEGER);
06062 break;
06063 case SQL_ATTR_TRACE:
06064 case SQL_ATTR_TRACEFILE:
06065 case SQL_ATTR_QUIET_MODE:
06066 case SQL_ATTR_TRANSLATE_OPTION:
06067 case SQL_ATTR_KEYSET_SIZE:
06068 case SQL_ATTR_QUERY_TIMEOUT:
06069 case SQL_ATTR_PARAM_BIND_TYPE:
06070 case SQL_ATTR_CURRENT_CATALOG:
06071 *((SQLINTEGER *) val) = 0;
06072 *buflen = sizeof (SQLINTEGER);
06073 break;
06074 case SQL_ATTR_ROW_BIND_TYPE:
06075 *((SQLUINTEGER *) val) = SQL_BIND_BY_COLUMN;
06076 *buflen = sizeof (SQLUINTEGER);
06077 break;
06078 case SQL_ATTR_USE_BOOKMARKS:
06079 *((SQLINTEGER *) val) = SQL_UB_OFF;
06080 *buflen = sizeof (SQLINTEGER);
06081 break;
06082 case SQL_ATTR_ASYNC_ENABLE:
06083 *((SQLINTEGER *) val) = SQL_ASYNC_ENABLE_OFF;
06084 *buflen = sizeof (SQLINTEGER);
06085 break;
06086 case SQL_ATTR_NOSCAN:
06087 *((SQLINTEGER *) val) = SQL_NOSCAN_ON;
06088 *buflen = sizeof (SQLINTEGER);
06089 break;
06090 case SQL_ATTR_CONCURRENCY:
06091 *((SQLINTEGER *) val) = SQL_CONCUR_LOCK;
06092 *buflen = sizeof (SQLINTEGER);
06093 break;
06094 case SQL_ATTR_SIMULATE_CURSOR:
06095 *((SQLINTEGER *) val) = SQL_SC_NON_UNIQUE;
06096 *buflen = sizeof (SQLINTEGER);
06097 break;
06098 case SQL_ATTR_MAX_ROWS:
06099 case SQL_ATTR_MAX_LENGTH:
06100 *((SQLINTEGER *) val) = 1000000000;
06101 *buflen = sizeof (SQLINTEGER);
06102 break;
06103 case SQL_ATTR_CURSOR_TYPE:
06104 *((SQLINTEGER *) val) = d->curtype;
06105 *buflen = sizeof (SQLINTEGER);
06106 break;
06107 case SQL_ATTR_RETRIEVE_DATA:
06108 *((SQLINTEGER *) val) = SQL_RD_ON;
06109 *buflen = sizeof (SQLINTEGER);
06110 break;
06111 default:
06112 *((SQLINTEGER *) val) = 0;
06113 *buflen = sizeof (SQLINTEGER);
06114 setstatd(d, -1, "unsupported connect attribute %d",
06115 (*d->ov3) ? "HYC00" : "S1C00", (int) attr);
06116 return SQL_ERROR;
06117 }
06118 return SQL_SUCCESS;
06119 }
06120
06131 SQLRETURN SQL_API
06132 SQLGetConnectAttr(SQLHDBC dbc, SQLINTEGER attr, SQLPOINTER val,
06133 SQLINTEGER bufmax, SQLINTEGER *buflen)
06134 {
06135 return drvgetconnectattr(dbc, attr, val, bufmax, buflen);
06136 }
06137
06147 static SQLRETURN
06148 drvsetconnectattr(SQLHDBC dbc, SQLINTEGER attr, SQLPOINTER val,
06149 SQLINTEGER len)
06150 {
06151 DBC *d;
06152
06153 if (dbc == SQL_NULL_HDBC) {
06154 return SQL_INVALID_HANDLE;
06155 }
06156 d = (DBC *) dbc;
06157 switch (attr) {
06158 case SQL_AUTOCOMMIT:
06159 if (len == SQL_IS_INTEGER || len == SQL_IS_UINTEGER) {
06160 d->autocommit = (SQLINTEGER) val == SQL_AUTOCOMMIT_ON;
06161 goto doit;
06162 }
06163 if (val && len >= sizeof (SQLINTEGER)) {
06164 d->autocommit = *((SQLINTEGER *) val) == SQL_AUTOCOMMIT_ON;
06165 doit:
06166 if (d->autocommit && d->intrans) {
06167 return endtran(d, SQL_COMMIT);
06168 } else if (!d->autocommit) {
06169 s3stmt_end(d->cur_s3stmt);
06170 }
06171 }
06172 break;
06173 default:
06174 setstatd(d, -1, "option value changed", "01S02");
06175 return SQL_SUCCESS_WITH_INFO;
06176 }
06177 return SQL_SUCCESS;
06178 }
06179
06189 SQLRETURN SQL_API
06190 SQLSetConnectAttr(SQLHDBC dbc, SQLINTEGER attr, SQLPOINTER val,
06191 SQLINTEGER len)
06192 {
06193 return drvsetconnectattr(dbc, attr, val, len);
06194 }
06195
06204 static SQLRETURN
06205 drvgetconnectoption(SQLHDBC dbc, SQLUSMALLINT opt, SQLPOINTER param)
06206 {
06207 DBC *d;
06208 SQLINTEGER dummy;
06209
06210 if (dbc == SQL_NULL_HDBC) {
06211 return SQL_INVALID_HANDLE;
06212 }
06213 d = (DBC *) dbc;
06214 if (!param) {
06215 param = (SQLPOINTER) &dummy;
06216 }
06217 switch (opt) {
06218 case SQL_ACCESS_MODE:
06219 *((SQLINTEGER *) param) = SQL_MODE_READ_WRITE;
06220 break;
06221 case SQL_AUTOCOMMIT:
06222 *((SQLINTEGER *) param) =
06223 d->autocommit ? SQL_AUTOCOMMIT_ON : SQL_AUTOCOMMIT_OFF;
06224 break;
06225 case SQL_LOGIN_TIMEOUT:
06226 *((SQLINTEGER *) param) = 100;
06227 break;
06228 case SQL_ODBC_CURSORS:
06229 *((SQLINTEGER *) param) = SQL_CUR_USE_DRIVER;
06230 break;
06231 case SQL_PACKET_SIZE:
06232 *((SQLINTEGER *) param) = 16384;
06233 break;
06234 case SQL_TXN_ISOLATION:
06235 *((SQLINTEGER *) param) = SQL_TXN_READ_UNCOMMITTED;
06236 break;
06237 case SQL_OPT_TRACE:
06238 case SQL_OPT_TRACEFILE:
06239 case SQL_QUIET_MODE:
06240 case SQL_TRANSLATE_DLL:
06241 case SQL_TRANSLATE_OPTION:
06242 case SQL_KEYSET_SIZE:
06243 case SQL_QUERY_TIMEOUT:
06244 case SQL_BIND_TYPE:
06245 case SQL_CURRENT_QUALIFIER:
06246 *((SQLINTEGER *) param) = 0;
06247 break;
06248 case SQL_USE_BOOKMARKS:
06249 *((SQLINTEGER *) param) = SQL_UB_OFF;
06250 break;
06251 case SQL_ASYNC_ENABLE:
06252 *((SQLINTEGER *) param) = SQL_ASYNC_ENABLE_OFF;
06253 break;
06254 case SQL_NOSCAN:
06255 *((SQLINTEGER *) param) = SQL_NOSCAN_ON;
06256 break;
06257 case SQL_CONCURRENCY:
06258 *((SQLINTEGER *) param) = SQL_CONCUR_LOCK;
06259 break;
06260 case SQL_SIMULATE_CURSOR:
06261 *((SQLINTEGER *) param) = SQL_SC_NON_UNIQUE;
06262 break;
06263 case SQL_ROWSET_SIZE:
06264 case SQL_MAX_ROWS:
06265 case SQL_MAX_LENGTH:
06266 *((SQLINTEGER *) param) = 1000000000;
06267 break;
06268 case SQL_CURSOR_TYPE:
06269 *((SQLINTEGER *) param) = d->curtype;
06270 break;
06271 case SQL_RETRIEVE_DATA:
06272 *((SQLINTEGER *) param) = SQL_RD_ON;
06273 break;
06274 default:
06275 *((SQLINTEGER *) param) = 0;
06276 setstatd(d, -1, "unsupported connect option %d",
06277 (*d->ov3) ? "HYC00" : "S1C00", opt);
06278 return SQL_ERROR;
06279 }
06280 return SQL_SUCCESS;
06281 }
06282
06291 SQLRETURN SQL_API
06292 SQLGetConnectOption(SQLHDBC dbc, SQLUSMALLINT opt, SQLPOINTER param)
06293 {
06294 return drvgetconnectoption(dbc, opt, param);
06295 }
06296
06305 static SQLRETURN
06306 drvsetconnectoption(SQLHDBC dbc, SQLUSMALLINT opt, SQLUINTEGER param)
06307 {
06308 DBC *d;
06309
06310 if (dbc == SQL_NULL_HDBC) {
06311 return SQL_INVALID_HANDLE;
06312 }
06313 d = (DBC *) dbc;
06314 switch (opt) {
06315 case SQL_AUTOCOMMIT:
06316 d->autocommit = param == SQL_AUTOCOMMIT_ON;
06317 if (d->autocommit && d->intrans) {
06318 return endtran(d, SQL_COMMIT);
06319 } else if (!d->autocommit) {
06320 s3stmt_end(d->cur_s3stmt);
06321 }
06322 break;
06323 default:
06324 setstatd(d, -1, "option value changed", "01S02");
06325 return SQL_SUCCESS_WITH_INFO;
06326 }
06327 return SQL_SUCCESS;
06328 }
06329
06338 SQLRETURN SQL_API
06339 SQLSetConnectOption(SQLHDBC dbc, SQLUSMALLINT opt, SQLULEN param)
06340 {
06341 return drvsetconnectoption(dbc, opt, param);
06342 }
06343
06344 #if defined(WITHOUT_DRIVERMGR) || !defined(_WIN32)
06345
06356 static int
06357 getdsnattr(char *dsn, char *attr, char *out, int outLen)
06358 {
06359 char *str = dsn, *start;
06360 int len = strlen(attr);
06361
06362 while (*str) {
06363 while (*str && *str == ';') {
06364 ++str;
06365 }
06366 start = str;
06367 if ((str = strchr(str, '=')) == NULL) {
06368 return 0;
06369 }
06370 if (str - start == len &&
06371 #ifdef _WIN32
06372 _strnicmp(start, attr, len) == 0
06373 #else
06374 strncasecmp(start, attr, len) == 0
06375 #endif
06376 ) {
06377 start = ++str;
06378 while (*str && *str != ';') {
06379 ++str;
06380 }
06381 len = min(outLen - 1, str - start);
06382 strncpy(out, start, len);
06383 out[len] = '\0';
06384 return 1;
06385 }
06386 while (*str && *str != ';') {
06387 ++str;
06388 }
06389 }
06390 return 0;
06391 }
06392 #endif
06393
06402 static SQLRETURN
06403 drvconnect(SQLHDBC dbc, SQLCHAR *dsn, SQLSMALLINT dsnLen)
06404 {
06405 DBC *d;
06406 int len;
06407 char buf[SQL_MAX_MESSAGE_LENGTH], dbname[SQL_MAX_MESSAGE_LENGTH / 4];
06408 char busy[SQL_MAX_MESSAGE_LENGTH / 4], tracef[SQL_MAX_MESSAGE_LENGTH];
06409 char sflag[32], spflag[32], ntflag[32], lnflag[32];
06410
06411 if (dbc == SQL_NULL_HDBC) {
06412 return SQL_INVALID_HANDLE;
06413 }
06414 d = (DBC *) dbc;
06415 if (d->magic != DBC_MAGIC) {
06416 return SQL_INVALID_HANDLE;
06417 }
06418 if (d->sqlite != NULL) {
06419 setstatd(d, -1, "connection already established", "08002");
06420 return SQL_ERROR;
06421 }
06422 buf[0] = '\0';
06423 if (dsnLen == SQL_NTS) {
06424 len = sizeof (buf) - 1;
06425 } else {
06426 len = min(sizeof (buf) - 1, dsnLen);
06427 }
06428 if (dsn != NULL) {
06429 strncpy(buf, (char *) dsn, len);
06430 }
06431 buf[len] = '\0';
06432 if (buf[0] == '\0') {
06433 setstatd(d, -1, "invalid DSN", (*d->ov3) ? "HY090" : "S1090");
06434 return SQL_ERROR;
06435 }
06436 busy[0] = '\0';
06437 dbname[0] = '\0';
06438 #ifdef WITHOUT_DRIVERMGR
06439 getdsnattr(buf, "database", dbname, sizeof (dbname));
06440 if (dbname[0] == '\0') {
06441 strncpy(dbname, buf, sizeof (dbname));
06442 dbname[sizeof (dbname) - 1] = '\0';
06443 }
06444 getdsnattr(buf, "timeout", busy, sizeof (busy));
06445 sflag[0] = '\0';
06446 getdsnattr(buf, "stepapi", sflag, sizeof (sflag));
06447 spflag[0] = '\0';
06448 getdsnattr(buf, "syncpragma", spflag, sizeof (spflag));
06449 ntflag[0] = '\0';
06450 getdsnattr(buf, "notxn", ntflag, sizeof (ntflag));
06451 lnflag[0] = '\0';
06452 getdsnattr(buf, "longnames", lnflag, sizeof (lnflag));
06453 #else
06454 SQLGetPrivateProfileString(buf, "timeout", "1000",
06455 busy, sizeof (busy), ODBC_INI);
06456 SQLGetPrivateProfileString(buf, "database", "",
06457 dbname, sizeof (dbname), ODBC_INI);
06458 SQLGetPrivateProfileString(buf, "stepapi", "",
06459 sflag, sizeof (sflag), ODBC_INI);
06460 SQLGetPrivateProfileString(buf, "syncpragma", "NORMAL",
06461 spflag, sizeof (spflag), ODBC_INI);
06462 SQLGetPrivateProfileString(buf, "notxn", "",
06463 ntflag, sizeof (ntflag), ODBC_INI);
06464 SQLGetPrivateProfileString(buf, "longnames", "",
06465 lnflag, sizeof (lnflag), ODBC_INI);
06466 #endif
06467 tracef[0] = '\0';
06468 #ifdef WITHOUT_DRIVERMGR
06469 getdsnattr(buf, "tracefile", tracef, sizeof (tracef));
06470 #else
06471 SQLGetPrivateProfileString(buf, "tracefile", "",
06472 tracef, sizeof (tracef), ODBC_INI);
06473 #endif
06474 if (tracef[0] != '\0') {
06475 d->trace = fopen(tracef, "a");
06476 }
06477 d->longnames = getbool(lnflag);
06478 return dbopen(d, dbname, (char *) dsn, sflag, spflag, ntflag, busy);
06479 }
06480
06493 SQLRETURN SQL_API
06494 SQLConnect(SQLHDBC dbc, SQLCHAR *dsn, SQLSMALLINT dsnLen,
06495 SQLCHAR *uid, SQLSMALLINT uidLen,
06496 SQLCHAR *pass, SQLSMALLINT passLen)
06497 {
06498 return drvconnect(dbc, dsn, dsnLen);
06499 }
06500
06507 SQLRETURN SQL_API
06508 SQLDisconnect(SQLHDBC dbc)
06509 {
06510 DBC *d;
06511
06512 if (dbc == SQL_NULL_HDBC) {
06513 return SQL_INVALID_HANDLE;
06514 }
06515 d = (DBC *) dbc;
06516 if (d->magic != DBC_MAGIC) {
06517 return SQL_INVALID_HANDLE;
06518 }
06519 if (d->intrans) {
06520 setstatd(d, -1, "incomplete transaction", "25000");
06521 return SQL_ERROR;
06522 }
06523 if (d->cur_s3stmt) {
06524 s3stmt_end(d->cur_s3stmt);
06525 }
06526 if (d->sqlite) {
06527 if (d->trace) {
06528 fprintf(d->trace, "-- sqlite3_close: '%s'\n",
06529 d->dbname);
06530 fflush(d->trace);
06531 }
06532 sqlite3_close(d->sqlite);
06533 d->sqlite = NULL;
06534 }
06535 freep(&d->dbname);
06536 freep(&d->dsn);
06537 return SQL_SUCCESS;
06538 }
06539
06540 #if defined(WITHOUT_DRIVERMGR) || !defined(_WIN32)
06541
06555 static SQLRETURN
06556 drvdriverconnect(SQLHDBC dbc, SQLHWND hwnd,
06557 SQLCHAR *connIn, SQLSMALLINT connInLen,
06558 SQLCHAR *connOut, SQLSMALLINT connOutMax,
06559 SQLSMALLINT *connOutLen, SQLUSMALLINT drvcompl)
06560 {
06561 DBC *d;
06562 int len;
06563 char buf[SQL_MAX_MESSAGE_LENGTH], dbname[SQL_MAX_MESSAGE_LENGTH / 4];
06564 char dsn[SQL_MAX_MESSAGE_LENGTH / 4], busy[SQL_MAX_MESSAGE_LENGTH / 4];
06565 char tracef[SQL_MAX_MESSAGE_LENGTH];
06566 char sflag[32], spflag[32], ntflag[32], lnflag[32];
06567
06568 if (dbc == SQL_NULL_HDBC || hwnd != NULL) {
06569 return SQL_INVALID_HANDLE;
06570 }
06571 if (drvcompl != SQL_DRIVER_COMPLETE &&
06572 drvcompl != SQL_DRIVER_COMPLETE_REQUIRED &&
06573 drvcompl != SQL_DRIVER_PROMPT &&
06574 drvcompl != SQL_DRIVER_NOPROMPT) {
06575 return SQL_NO_DATA;
06576 }
06577 d = (DBC *) dbc;
06578 if (d->sqlite) {
06579 setstatd(d, -1, "connection already established", "08002");
06580 return SQL_ERROR;
06581 }
06582 buf[0] = '\0';
06583 if (connInLen == SQL_NTS) {
06584 len = sizeof (buf) - 1;
06585 } else {
06586 len = min(connInLen, sizeof (buf) - 1);
06587 }
06588 if (connIn != NULL) {
06589 strncpy(buf, (char *) connIn, len);
06590 }
06591 buf[len] = '\0';
06592 if (!buf[0]) {
06593 setstatd(d, -1, "invalid connect attributes",
06594 (*d->ov3) ? "HY090" : "S1090");
06595 return SQL_ERROR;
06596 }
06597 dsn[0] = '\0';
06598 getdsnattr(buf, "DSN", dsn, sizeof (dsn));
06599
06600
06601 if (!dsn[0] && !strchr(buf, ';') && !strchr(buf, '=')) {
06602 strncpy(dsn, buf, sizeof (dsn) - 1);
06603 dsn[sizeof (dsn) - 1] = '\0';
06604 }
06605
06606 busy[0] = '\0';
06607 getdsnattr(buf, "timeout", busy, sizeof (busy));
06608 #ifndef WITHOUT_DRIVERMGR
06609 if (dsn[0] && !busy[0]) {
06610 SQLGetPrivateProfileString(dsn, "timeout", "1000",
06611 busy, sizeof (busy), ODBC_INI);
06612 }
06613 #endif
06614 dbname[0] = '\0';
06615 getdsnattr(buf, "database", dbname, sizeof (dbname));
06616 #ifndef WITHOUT_DRIVERMGR
06617 if (dsn[0] && !dbname[0]) {
06618 SQLGetPrivateProfileString(dsn, "database", "",
06619 dbname, sizeof (dbname), ODBC_INI);
06620 }
06621 #endif
06622 sflag[0] = '\0';
06623 getdsnattr(buf, "stepapi", sflag, sizeof (sflag));
06624 #ifndef WITHOUT_DRIVERMGR
06625 if (dsn[0] && !sflag[0]) {
06626 SQLGetPrivateProfileString(dsn, "stepapi", "",
06627 sflag, sizeof (sflag), ODBC_INI);
06628 }
06629 #endif
06630 spflag[0] = '\0';
06631 getdsnattr(buf, "syncpragma", spflag, sizeof (spflag));
06632 #ifndef WITHOUT_DRIVERMGR
06633 if (dsn[0] && !spflag[0]) {
06634 SQLGetPrivateProfileString(dsn, "syncpragma", "NORMAL",
06635 spflag, sizeof (spflag), ODBC_INI);
06636 }
06637 #endif
06638 ntflag[0] = '\0';
06639 getdsnattr(buf, "notxn", ntflag, sizeof (ntflag));
06640 #ifndef WITHOUT_DRIVERMGR
06641 if (dsn[0] && !ntflag[0]) {
06642 SQLGetPrivateProfileString(dsn, "notxn", "",
06643 ntflag, sizeof (ntflag), ODBC_INI);
06644 }
06645 #endif
06646 lnflag[0] = '\0';
06647 getdsnattr(buf, "longnames", lnflag, sizeof (lnflag));
06648 #ifndef WITHOUT_DRIVERMGR
06649 if (dsn[0] && !lnflag[0]) {
06650 SQLGetPrivateProfileString(dsn, "longnames", "",
06651 lnflag, sizeof (lnflag), ODBC_INI);
06652 }
06653 #endif
06654 if (!dbname[0] && !dsn[0]) {
06655 strcpy(dsn, "SQLite");
06656 strncpy(dbname, buf, sizeof (dbname));
06657 dbname[sizeof (dbname) - 1] = '\0';
06658 }
06659 tracef[0] = '\0';
06660 getdsnattr(buf, "tracefile", tracef, sizeof (tracef));
06661 #ifndef WITHOUT_DRIVERMGR
06662 if (dsn[0] && !tracef[0]) {
06663 SQLGetPrivateProfileString(dsn, "tracefile", "",
06664 tracef, sizeof (tracef), ODBC_INI);
06665 }
06666 #endif
06667 if (connOut || connOutLen) {
06668 int count;
06669
06670 buf[0] = '\0';
06671 count = snprintf(buf, sizeof (buf),
06672 "DSN=%s;Database=%s;StepAPI=%s;Timeout=%s;"
06673 "SyncPragma=%s;NoTXN=%s;LongNames=%s;Tracefile=%s",
06674 dsn, dbname, sflag, busy, spflag, ntflag,
06675 lnflag, tracef);
06676 if (count < 0) {
06677 buf[sizeof (buf) - 1] = '\0';
06678 }
06679 len = min(connOutMax - 1, strlen(buf));
06680 if (connOut) {
06681 strncpy((char *) connOut, buf, len);
06682 connOut[len] = '\0';
06683 }
06684 if (connOutLen) {
06685 *connOutLen = len;
06686 }
06687 }
06688 if (tracef[0] != '\0') {
06689 d->trace = fopen(tracef, "a");
06690 }
06691 d->longnames = getbool(lnflag);
06692 return dbopen(d, dbname, dsn, sflag, spflag, ntflag, busy);
06693 }
06694 #endif
06695
06696
06697
06698 static SQLRETURN
06699 freestmt(SQLHSTMT stmt)
06700 {
06701 STMT *s;
06702 DBC *d;
06703
06704 if (stmt == SQL_NULL_HSTMT) {
06705 return SQL_INVALID_HANDLE;
06706 }
06707 s = (STMT *) stmt;
06708 freeresult(s, 1);
06709 freep(&s->query);
06710 d = (DBC *) s->dbc;
06711 if (d && d->magic == DBC_MAGIC) {
06712 STMT *p, *n;
06713
06714 p = NULL;
06715 n = d->stmt;
06716 while (n) {
06717 if (n == s) {
06718 break;
06719 }
06720 p = n;
06721 n = n->next;
06722 }
06723 if (n) {
06724 if (p) {
06725 p->next = s->next;
06726 } else {
06727 d->stmt = s->next;
06728 }
06729 }
06730 }
06731 freeparams(s);
06732 freep(&s->bindparms);
06733 if (s->row_status0 != &s->row_status1) {
06734 freep(&s->row_status0);
06735 s->rowset_size = 1;
06736 s->row_status0 = &s->row_status1;
06737 }
06738 xfree(s);
06739 return SQL_SUCCESS;
06740 }
06741
06749 static SQLRETURN
06750 drvallocstmt(SQLHDBC dbc, SQLHSTMT *stmt)
06751 {
06752 DBC *d;
06753 STMT *s, *sl, *pl;
06754
06755 if (dbc == SQL_NULL_HDBC) {
06756 return SQL_INVALID_HANDLE;
06757 }
06758 d = (DBC *) dbc;
06759 if (d->magic != DBC_MAGIC || stmt == NULL) {
06760 return SQL_INVALID_HANDLE;
06761 }
06762 s = (STMT *) xmalloc(sizeof (STMT));
06763 if (s == NULL) {
06764 *stmt = SQL_NULL_HSTMT;
06765 return SQL_ERROR;
06766 }
06767 *stmt = (SQLHSTMT) s;
06768 memset(s, 0, sizeof (STMT));
06769 s->dbc = dbc;
06770 s->ov3 = d->ov3;
06771 s->curtype = d->curtype;
06772 s->row_status0 = &s->row_status1;
06773 s->rowset_size = 1;
06774 s->longnames = d->longnames;
06775 s->retr_data = SQL_RD_ON;
06776 s->bind_type = SQL_BIND_BY_COLUMN;
06777 s->bind_offs = NULL;
06778 s->paramset_size = 1;
06779 sprintf((char *) s->cursorname, "CUR_%08lX", (long) *stmt);
06780 sl = d->stmt;
06781 pl = NULL;
06782 while (sl) {
06783 pl = sl;
06784 sl = sl->next;
06785 }
06786 if (pl) {
06787 pl->next = s;
06788 } else {
06789 d->stmt = s;
06790 }
06791 return SQL_SUCCESS;
06792 }
06793
06801 SQLRETURN SQL_API
06802 SQLAllocStmt(SQLHDBC dbc, SQLHSTMT *stmt)
06803 {
06804 return drvallocstmt(dbc, stmt);
06805 }
06806
06814 static SQLRETURN
06815 drvfreestmt(SQLHSTMT stmt, SQLUSMALLINT opt)
06816 {
06817 STMT *s;
06818
06819 if (stmt == SQL_NULL_HSTMT) {
06820 return SQL_INVALID_HANDLE;
06821 }
06822 s = (STMT *) stmt;
06823 switch (opt) {
06824 case SQL_RESET_PARAMS:
06825 freeparams(s);
06826 break;
06827 case SQL_UNBIND:
06828 unbindcols(s);
06829 break;
06830 case SQL_CLOSE:
06831 s3stmt_end_if(s);
06832 freeresult(s, 0);
06833 break;
06834 case SQL_DROP:
06835 s3stmt_end_if(s);
06836 return freestmt(stmt);
06837 default:
06838 setstat(s, -1, "unsupported option", (*s->ov3) ? "HYC00" : "S1C00");
06839 return SQL_ERROR;
06840 }
06841 return SQL_SUCCESS;
06842 }
06843
06851 SQLRETURN SQL_API
06852 SQLFreeStmt(SQLHSTMT stmt, SQLUSMALLINT opt)
06853 {
06854 return drvfreestmt(stmt, opt);
06855 }
06856
06863 SQLRETURN SQL_API
06864 SQLCancel(SQLHSTMT stmt)
06865 {
06866 return drvfreestmt(stmt, SQL_CLOSE);
06867 }
06868
06878 static SQLRETURN
06879 drvgetcursorname(SQLHSTMT stmt, SQLCHAR *cursor, SQLSMALLINT buflen,
06880 SQLSMALLINT *lenp)
06881 {
06882 STMT *s;
06883
06884 if (stmt == SQL_NULL_HSTMT) {
06885 return SQL_INVALID_HANDLE;
06886 }
06887 s = (STMT *) stmt;
06888 if (lenp && !cursor) {
06889 *lenp = strlen((char *) s->cursorname);
06890 return SQL_SUCCESS;
06891 }
06892 if (cursor) {
06893 if (buflen > 0) {
06894 strncpy((char *) cursor, (char *) s->cursorname, buflen - 1);
06895 cursor[buflen - 1] = '\0';
06896 }
06897 if (lenp) {
06898 *lenp = min(strlen((char *) s->cursorname), buflen - 1);
06899 }
06900 }
06901 return SQL_SUCCESS;
06902 }
06903
06913 SQLRETURN SQL_API
06914 SQLGetCursorName(SQLHSTMT stmt, SQLCHAR *cursor, SQLSMALLINT buflen,
06915 SQLSMALLINT *lenp)
06916 {
06917 return drvgetcursorname(stmt, cursor, buflen, lenp);
06918 }
06919
06928 static SQLRETURN
06929 drvsetcursorname(SQLHSTMT stmt, SQLCHAR *cursor, SQLSMALLINT len)
06930 {
06931 STMT *s;
06932
06933 if (stmt == SQL_NULL_HSTMT) {
06934 return SQL_INVALID_HANDLE;
06935 }
06936 s = (STMT *) stmt;
06937 if (!cursor ||
06938 !((cursor[0] >= 'A' && cursor[0] <= 'Z') ||
06939 (cursor[0] >= 'a' && cursor[0] <= 'z'))) {
06940 setstat(s, -1, "invalid cursor name", (*s->ov3) ? "HYC00" : "S1C00");
06941 return SQL_ERROR;
06942 }
06943 if (len == SQL_NTS) {
06944 len = sizeof (s->cursorname) - 1;
06945 } else {
06946 len = min(sizeof (s->cursorname) - 1, len);
06947 }
06948 strncpy((char *) s->cursorname, (char *) cursor, len);
06949 s->cursorname[len] = '\0';
06950 return SQL_SUCCESS;
06951 }
06952
06961 SQLRETURN SQL_API
06962 SQLSetCursorName(SQLHSTMT stmt, SQLCHAR *cursor, SQLSMALLINT len)
06963 {
06964 return drvsetcursorname(stmt, cursor, len);
06965 }
06966
06973 SQLRETURN SQL_API
06974 SQLCloseCursor(SQLHSTMT stmt)
06975 {
06976 return drvfreestmt(stmt, SQL_CLOSE);
06977 }
06978
06979 #if defined(WITHOUT_DRIVERMGR) || !defined(HAVE_IODBC) || defined(_WIN32)
06980
06989 SQLRETURN SQL_API
06990 SQLAllocHandle(SQLSMALLINT type, SQLHANDLE input, SQLHANDLE *output)
06991 {
06992 SQLRETURN ret;
06993
06994 switch (type) {
06995 case SQL_HANDLE_ENV:
06996 ret = drvallocenv((SQLHENV *) output);
06997 if (ret == SQL_SUCCESS) {
06998 ENV *e = (ENV *) *output;
06999
07000 if (e && e->magic == ENV_MAGIC) {
07001 e->ov3 = 1;
07002 }
07003 }
07004 return ret;
07005 case SQL_HANDLE_DBC:
07006 return drvallocconnect((SQLHENV) input, (SQLHDBC *) output);
07007 case SQL_HANDLE_STMT:
07008 return drvallocstmt((SQLHDBC) input, (SQLHSTMT *) output);
07009 }
07010 return SQL_ERROR;
07011 }
07012 #endif
07013
07014 #if defined(WITHOUT_DRIVERMGR) || !defined(HAVE_IODBC) || defined(_WIN32)
07015
07023 SQLRETURN SQL_API
07024 SQLFreeHandle(SQLSMALLINT type, SQLHANDLE h)
07025 {
07026 switch (type) {
07027 case SQL_HANDLE_ENV:
07028 return drvfreeenv((SQLHENV) h);
07029 case SQL_HANDLE_DBC:
07030 return drvfreeconnect((SQLHDBC) h);
07031 case SQL_HANDLE_STMT:
07032 return drvfreestmt((SQLHSTMT) h, SQL_DROP);
07033 }
07034 return SQL_ERROR;
07035 }
07036 #endif
07037
07043 static void
07044 freedyncols(STMT *s)
07045 {
07046 if (s->dyncols) {
07047 int i;
07048
07049 for (i = 0; i < s->dcols; i++) {
07050 freep(&s->dyncols[i].typename);
07051 }
07052 if (s->cols == s->dyncols) {
07053 s->cols = NULL;
07054 s->ncols = 0;
07055 }
07056 freep(&s->dyncols);
07057 }
07058 s->dcols = 0;
07059 }
07060
07061
07062
07063 static void
07064 freeresult(STMT *s, int clrcols)
07065 {
07066 freep(&s->bincache);
07067 s->bincell = NULL;
07068 s->binlen = 0;
07069 if (s->rows) {
07070 if (s->rowfree) {
07071 s->rowfree(s->rows);
07072 s->rowfree = NULL;
07073 }
07074 s->rows = NULL;
07075 }
07076 s->nrows = -1;
07077 if (clrcols > 0) {
07078 freep(&s->bindcols);
07079 s->nbindcols = 0;
07080 }
07081 if (clrcols) {
07082 freedyncols(s);
07083 s->cols = NULL;
07084 s->ncols = 0;
07085 }
07086 }
07087
07088
07089
07090 static void
07091 unbindcols(STMT *s)
07092 {
07093 int i;
07094
07095 s->bkmrkcol.type = -1;
07096 s->bkmrkcol.max = 0;
07097 s->bkmrkcol.lenp = NULL;
07098 s->bkmrkcol.valp = NULL;
07099 s->bkmrkcol.index = 0;
07100 s->bkmrkcol.offs = 0;
07101 for (i = 0; s->bindcols && i < s->nbindcols; i++) {
07102 s->bindcols[i].type = -1;
07103 s->bindcols[i].max = 0;
07104 s->bindcols[i].lenp = NULL;
07105 s->bindcols[i].valp = NULL;
07106 s->bindcols[i].index = i;
07107 s->bindcols[i].offs = 0;
07108 }
07109 }
07110
07111
07112
07113 static SQLRETURN
07114 mkbindcols(STMT *s, int ncols)
07115 {
07116 if (s->bindcols) {
07117 if (s->nbindcols < ncols) {
07118 int i;
07119 BINDCOL *bindcols =
07120 xrealloc(s->bindcols, ncols * sizeof (BINDCOL));
07121
07122 if (!bindcols) {
07123 return nomem(s);
07124 }
07125 for (i = s->nbindcols; i < ncols; i++) {
07126 bindcols[i].type = -1;
07127 bindcols[i].max = 0;
07128 bindcols[i].lenp = NULL;
07129 bindcols[i].valp = NULL;
07130 bindcols[i].index = i;
07131 bindcols[i].offs = 0;
07132 }
07133 s->bindcols = bindcols;
07134 s->nbindcols = ncols;
07135 }
07136 } else if (ncols > 0) {
07137 s->bindcols = (BINDCOL *) xmalloc(ncols * sizeof (BINDCOL));
07138 if (!s->bindcols) {
07139 return nomem(s);
07140 }
07141 s->nbindcols = ncols;
07142 unbindcols(s);
07143 }
07144 return SQL_SUCCESS;
07145 }
07146
07160 static SQLRETURN
07161 getrowdata(STMT *s, SQLUSMALLINT col, SQLSMALLINT otype,
07162 SQLPOINTER val, SQLINTEGER len, SQLLEN *lenp, int partial)
07163 {
07164 char **data, valdummy[16];
07165 SQLLEN dummy;
07166 int valnull = 0;
07167 int type = otype;
07168
07169 if (!s->rows) {
07170 return SQL_NO_DATA;
07171 }
07172 if (col >= s->ncols) {
07173 setstat(s, -1, "invalid column", (*s->ov3) ? "07009" : "S1002");
07174 return SQL_ERROR;
07175 }
07176 if (s->rowp < 0 || s->rowp >= s->nrows) {
07177 return SQL_NO_DATA;
07178 }
07179 if (s->retr_data != SQL_RD_ON) {
07180 return SQL_SUCCESS;
07181 }
07182 type = mapdeftype(type, s->cols[col].type, s->cols[col].nosign ? 1 : 0);
07183 #if 0
07184 if (otype == SQL_C_CHAR) {
07185 switch (s->cols[col].type) {
07186 case SQL_BINARY:
07187 case SQL_VARBINARY:
07188 case SQL_LONGVARBINARY:
07189 type = SQL_C_BINARY;
07190 break;
07191 }
07192 }
07193 #endif
07194 data = s->rows + s->ncols + (s->rowp * s->ncols) + col;
07195 if (!lenp) {
07196 lenp = &dummy;
07197 }
07198 if (!val) {
07199 valnull = 1;
07200 val = (SQLPOINTER) valdummy;
07201 }
07202 if (*data == NULL) {
07203 *lenp = SQL_NULL_DATA;
07204 switch (type) {
07205 case SQL_C_UTINYINT:
07206 case SQL_C_TINYINT:
07207 case SQL_C_STINYINT:
07208 #ifdef SQL_BIT
07209 case SQL_C_BIT:
07210 #endif
07211 *((char *) val) = 0;
07212 break;
07213 case SQL_C_USHORT:
07214 case SQL_C_SHORT:
07215 case SQL_C_SSHORT:
07216 *((short *) val) = 0;
07217 break;
07218 case SQL_C_ULONG:
07219 case SQL_C_LONG:
07220 case SQL_C_SLONG:
07221 *((long *) val) = 0;
07222 break;
07223 #ifdef SQL_BIGINT
07224 case SQL_C_SBIGINT:
07225 case SQL_C_UBIGINT:
07226 *((SQLBIGINT *) val) = 0;
07227 break;
07228 #endif
07229 case SQL_C_FLOAT:
07230 *((float *) val) = 0;
07231 break;
07232 case SQL_C_DOUBLE:
07233 *((double *) val) = 0;
07234 break;
07235 case SQL_C_BINARY:
07236 case SQL_C_CHAR:
07237 *((char *) val) = '\0';
07238 break;
07239 #ifdef SQL_C_TYPE_DATE
07240 case SQL_C_TYPE_DATE:
07241 #endif
07242 case SQL_C_DATE:
07243 memset((DATE_STRUCT *) val, 0, sizeof (DATE_STRUCT));
07244 break;
07245 #ifdef SQL_C_TYPE_TIME
07246 case SQL_C_TYPE_TIME:
07247 #endif
07248 case SQL_C_TIME:
07249 memset((TIME_STRUCT *) val, 0, sizeof (TIME_STRUCT));
07250 break;
07251 #ifdef SQL_C_TYPE_TIMESTAMP
07252 case SQL_C_TYPE_TIMESTAMP:
07253 #endif
07254 case SQL_C_TIMESTAMP:
07255 memset((TIMESTAMP_STRUCT *) val, 0, sizeof (TIMESTAMP_STRUCT));
07256 break;
07257 default:
07258 return SQL_ERROR;
07259 }
07260 } else {
07261 char *endp = NULL;
07262 #ifdef _WIN32
07263 #ifdef SQL_BIGINT
07264 char endc;
07265 #endif
07266 #endif
07267
07268 switch (type) {
07269 case SQL_C_UTINYINT:
07270 case SQL_C_TINYINT:
07271 case SQL_C_STINYINT:
07272 *((char *) val) = strtol(*data, &endp, 0);
07273 if (endp && endp == *data) {
07274 *lenp = SQL_NULL_DATA;
07275 } else {
07276 *lenp = sizeof (char);
07277 }
07278 break;
07279 #ifdef SQL_BIT
07280 case SQL_C_BIT:
07281 *((char *) val) = getbool(*data);
07282 *lenp = sizeof (char);
07283 break;
07284 #endif
07285 case SQL_C_USHORT:
07286 case SQL_C_SHORT:
07287 case SQL_C_SSHORT:
07288 *((short *) val) = strtol(*data, &endp, 0);
07289 if (endp && endp == *data) {
07290 *lenp = SQL_NULL_DATA;
07291 } else {
07292 *lenp = sizeof (short);
07293 }
07294 break;
07295 case SQL_C_ULONG:
07296 case SQL_C_LONG:
07297 case SQL_C_SLONG:
07298 *((int *) val) = strtol(*data, &endp, 0);
07299 if (endp && endp == *data) {
07300 *lenp = SQL_NULL_DATA;
07301 } else {
07302 *lenp = sizeof (int);
07303 }
07304 break;
07305 #ifdef SQL_BIGINT
07306 case SQL_C_UBIGINT:
07307 #ifdef _WIN32
07308 if (sscanf(*data, "%I64u%c", (SQLUBIGINT *) val, &endc) != 1) {
07309 *lenp = SQL_NULL_DATA;
07310 } else {
07311 *lenp = sizeof (SQLUBIGINT);
07312 }
07313 #else
07314 *((SQLUBIGINT *) val) = strtoull(*data, &endp, 0);
07315 if (endp && endp == *data) {
07316 *lenp = SQL_NULL_DATA;
07317 } else {
07318 *lenp = sizeof (SQLUBIGINT);
07319 }
07320 #endif
07321 break;
07322 case SQL_C_SBIGINT:
07323 #ifdef _WIN32
07324 if (sscanf(*data, "%I64d%c", (SQLBIGINT *) val, &endc) != 1) {
07325 *lenp = SQL_NULL_DATA;
07326 } else {
07327 *lenp = sizeof (SQLBIGINT);
07328 }
07329 #else
07330 *((SQLBIGINT *) val) = strtoll(*data, &endp, 0);
07331 if (endp && endp == *data) {
07332 *lenp = SQL_NULL_DATA;
07333 } else {
07334 *lenp = sizeof (int);
07335 }
07336 #endif
07337 break;
07338 #endif
07339 case SQL_C_FLOAT:
07340 *((float *) val) = ln_strtod(*data, &endp);
07341 if (endp && endp == *data) {
07342 *lenp = SQL_NULL_DATA;
07343 } else {
07344 *lenp = sizeof (float);
07345 }
07346 break;
07347 case SQL_C_DOUBLE:
07348 *((double *) val) = ln_strtod(*data, &endp);
07349 if (endp && endp == *data) {
07350 *lenp = SQL_NULL_DATA;
07351 } else {
07352 *lenp = sizeof (double);
07353 }
07354 break;
07355 case SQL_C_BINARY: {
07356 int dlen, offs = 0;
07357 char *bin;
07358
07359 if (valnull) {
07360 freep(&s->bincache);
07361 s->binlen = 0;
07362 goto doCHAR;
07363 }
07364 if (*data == s->bincell) {
07365 if (s->bincache) {
07366 bin = s->bincache;
07367 dlen = s->binlen;
07368 } else {
07369 goto doCHAR;
07370 }
07371 } else {
07372 char *dp;
07373 int i;
07374
07375 freep(&s->bincache);
07376 dp = *data;
07377 dlen = strlen(dp);
07378 s->bincell = dp;
07379 s->binlen = 0;
07380 if (!(dp[0] == 'x' || dp[0] == 'X') || dp[1] != '\'' ||
07381 dp[dlen - 1] != '\'') {
07382 goto doCHAR;
07383 }
07384 dlen -= 2;
07385 dp += 2;
07386 dlen = dlen / 2;
07387 s->bincache = bin = xmalloc(dlen);
07388 if (!bin) {
07389 return nomem(s);
07390 }
07391 s->binlen = dlen;
07392 memset(s->bincache, 0, dlen);
07393 for (i = 0; i < dlen; i++) {
07394 char *x;
07395 int v;
07396
07397 if (!*dp || !(x = strchr(xdigits, *dp))) {
07398 goto converr;
07399 }
07400 v = x - xdigits;
07401 bin[i] = (v >= 16) ? ((v - 6) << 4) : (v << 4);
07402 ++dp;
07403 if (!*dp || !(x = strchr(xdigits, *dp))) {
07404 converr:
07405 freep(&s->bincache);
07406 s->binlen = 0;
07407 setstat(s, -1, "conversion error",
07408 (*s->ov3) ? "HY000" : "S1000");
07409 return SQL_ERROR;
07410 }
07411 v = x - xdigits;
07412 bin[i] |= (v >= 16) ? (v - 6) : v;
07413 ++dp;
07414 }
07415 bin = s->bincache;
07416 }
07417 if (partial && len && s->bindcols) {
07418 if (dlen && s->bindcols[col].offs >= dlen) {
07419 s->bindcols[col].offs = 0;
07420 return SQL_NO_DATA;
07421 }
07422 offs = s->bindcols[col].offs;
07423 dlen -= offs;
07424 }
07425 if (val && len) {
07426 memcpy(val, bin + offs, len);
07427 }
07428 if (len < 1) {
07429 *lenp = dlen;
07430 } else {
07431 *lenp = min(len, dlen);
07432 if (*lenp == len && *lenp != dlen) {
07433 *lenp = SQL_NO_TOTAL;
07434 }
07435 }
07436 if (partial && len && s->bindcols) {
07437 if (*lenp == SQL_NO_TOTAL) {
07438 s->bindcols[col].offs += len;
07439 setstat(s, -1, "data right truncated", "01004");
07440 if (s->bindcols[col].lenp) {
07441 *s->bindcols[col].lenp = dlen;
07442 }
07443 return SQL_SUCCESS_WITH_INFO;
07444 }
07445 s->bindcols[col].offs += *lenp;
07446 }
07447 break;
07448 }
07449 doCHAR:
07450 case SQL_C_CHAR: {
07451 int doz;
07452 int dlen = strlen(*data);
07453 int offs = 0;
07454
07455 doz = type == SQL_C_CHAR ? 1 : 0;
07456 if (partial && len && s->bindcols) {
07457 if (dlen && s->bindcols[col].offs >= dlen) {
07458 s->bindcols[col].offs = 0;
07459 return SQL_NO_DATA;
07460 }
07461 offs = s->bindcols[col].offs;
07462 dlen -= offs;
07463 }
07464 if (val && !valnull && len) {
07465 strncpy(val, *data + offs, len - doz);
07466 }
07467 if (valnull || len < 1) {
07468 *lenp = dlen;
07469 } else {
07470 *lenp = min(len - doz, dlen);
07471 if (*lenp == len - doz && *lenp != dlen) {
07472 *lenp = SQL_NO_TOTAL;
07473 }
07474 }
07475 if (len && !valnull && doz) {
07476 ((char *) val)[len - 1] = '\0';
07477 }
07478 if (partial && len && s->bindcols) {
07479 if (*lenp == SQL_NO_TOTAL) {
07480 s->bindcols[col].offs += len - doz;
07481 setstat(s, -1, "data right truncated", "01004");
07482 if (s->bindcols[col].lenp) {
07483 *s->bindcols[col].lenp = dlen;
07484 }
07485 return SQL_SUCCESS_WITH_INFO;
07486 }
07487 s->bindcols[col].offs += *lenp;
07488 }
07489 break;
07490 }
07491 #ifdef SQL_C_TYPE_DATE
07492 case SQL_C_TYPE_DATE:
07493 #endif
07494 case SQL_C_DATE:
07495 if (str2date(*data, (DATE_STRUCT *) val) < 0) {
07496 *lenp = SQL_NULL_DATA;
07497 } else {
07498 *lenp = sizeof (DATE_STRUCT);
07499 }
07500 break;
07501 #ifdef SQL_C_TYPE_TIME
07502 case SQL_C_TYPE_TIME:
07503 #endif
07504 case SQL_C_TIME:
07505 if (str2time(*data, (TIME_STRUCT *) val) < 0) {
07506 *lenp = SQL_NULL_DATA;
07507 } else {
07508 *lenp = sizeof (TIME_STRUCT);
07509 }
07510 break;
07511 #ifdef SQL_C_TYPE_TIMESTAMP
07512 case SQL_C_TYPE_TIMESTAMP:
07513 #endif
07514 case SQL_C_TIMESTAMP:
07515 if (str2timestamp(*data, (TIMESTAMP_STRUCT *) val) < 0) {
07516 *lenp = SQL_NULL_DATA;
07517 } else {
07518 *lenp = sizeof (TIMESTAMP_STRUCT);
07519 }
07520 break;
07521 default:
07522 return SQL_ERROR;
07523 }
07524 }
07525 return SQL_SUCCESS;
07526 }
07527
07539 SQLRETURN SQL_API
07540 SQLBindCol(SQLHSTMT stmt, SQLUSMALLINT col, SQLSMALLINT type,
07541 SQLPOINTER val, SQLLEN max, SQLLEN *lenp)
07542 {
07543 STMT *s;
07544
07545 if (stmt == SQL_NULL_HSTMT) {
07546 return SQL_INVALID_HANDLE;
07547 }
07548 s = (STMT *) stmt;
07549 if (col < 1) {
07550 if (col == 0 && s->bkmrk && type == SQL_C_BOOKMARK) {
07551 s->bkmrkcol.type = type;
07552 s->bkmrkcol.max = max;
07553 s->bkmrkcol.lenp = lenp;
07554 s->bkmrkcol.valp = val;
07555 s->bkmrkcol.offs = 0;
07556 if (lenp) {
07557 *lenp = 0;
07558 }
07559 return SQL_SUCCESS;
07560 }
07561 setstat(s, -1, "invalid column", (*s->ov3) ? "07009" : "S1002");
07562 return SQL_ERROR;
07563 }
07564 if (mkbindcols(s, col) != SQL_SUCCESS) {
07565 return SQL_ERROR;
07566 }
07567 --col;
07568 if (type == SQL_C_DEFAULT) {
07569 type = mapdeftype(type, s->cols[col].type, 0);
07570 } else {
07571 switch (type) {
07572 case SQL_C_LONG:
07573 case SQL_C_ULONG:
07574 case SQL_C_SLONG:
07575 case SQL_C_TINYINT:
07576 case SQL_C_UTINYINT:
07577 case SQL_C_STINYINT:
07578 case SQL_C_SHORT:
07579 case SQL_C_USHORT:
07580 case SQL_C_SSHORT:
07581 case SQL_C_FLOAT:
07582 case SQL_C_DOUBLE:
07583 case SQL_C_TIMESTAMP:
07584 case SQL_C_TIME:
07585 case SQL_C_DATE:
07586 case SQL_C_CHAR:
07587 #ifdef SQL_C_TYPE_DATE
07588 case SQL_C_TYPE_DATE:
07589 #endif
07590 #ifdef SQL_C_TYPE_TIME
07591 case SQL_C_TYPE_TIME:
07592 #endif
07593 #ifdef SQL_C_TYPE_TIMESTAMP
07594 case SQL_C_TYPE_TIMESTAMP:
07595 #endif
07596 #ifdef SQL_BIT
07597 case SQL_C_BIT:
07598 #endif
07599 break;
07600 case SQL_C_BINARY:
07601 break;
07602 #ifdef SQL_BIGINT
07603 case SQL_C_SBIGINT:
07604 case SQL_C_UBIGINT:
07605 break;
07606 #endif
07607 default:
07608 setstat(s, -1, "invalid type %d", "HY003", type);
07609 return SQL_ERROR;
07610 }
07611 }
07612 if (max < 0) {
07613 setstat(s, -1, "invalid length", "HY090");
07614 return SQL_ERROR;
07615 }
07616 s->bindcols[col].type = type;
07617 s->bindcols[col].max = max;
07618 s->bindcols[col].lenp = lenp;
07619 s->bindcols[col].valp = val;
07620 s->bindcols[col].offs = 0;
07621 if (lenp) {
07622 *lenp = 0;
07623 }
07624 return SQL_SUCCESS;
07625 }
07626
07631 static COL tableSpec[] = {
07632 { "SYSTEM", "COLUMN", "TABLE_QUALIFIER", SCOL_VARCHAR, 50 },
07633 { "SYSTEM", "COLUMN", "TABLE_OWNER", SCOL_VARCHAR, 50 },
07634 { "SYSTEM", "COLUMN", "TABLE_NAME", SCOL_VARCHAR, 255 },
07635 { "SYSTEM", "COLUMN", "TABLE_TYPE", SCOL_VARCHAR, 50 },
07636 { "SYSTEM", "COLUMN", "REMARKS", SCOL_VARCHAR, 50 }
07637 };
07638
07653 static SQLRETURN
07654 drvtables(SQLHSTMT stmt,
07655 SQLCHAR *cat, SQLSMALLINT catLen,
07656 SQLCHAR *schema, SQLSMALLINT schemaLen,
07657 SQLCHAR *table, SQLSMALLINT tableLen,
07658 SQLCHAR *type, SQLSMALLINT typeLen)
07659 {
07660 SQLRETURN ret;
07661 STMT *s;
07662 DBC *d;
07663 int ncols, rc;
07664 char *errp = NULL, *sql, tname[512];
07665 char *where = "(type = 'table' or type = 'view')";
07666
07667 ret = mkresultset(stmt, tableSpec, array_size(tableSpec));
07668 if (ret != SQL_SUCCESS) {
07669 return ret;
07670 }
07671 s = (STMT *) stmt;
07672 d = (DBC *) s->dbc;
07673 if (type && (typeLen > 0 || typeLen == SQL_NTS) && type[0] == '%') {
07674 int size = 3 * array_size(tableSpec);
07675
07676 s->rows = xmalloc(size * sizeof (char *));
07677 if (!s->rows) {
07678 s->nrows = 0;
07679 return nomem(s);
07680 }
07681 memset(s->rows, 0, sizeof (char *) * size);
07682 s->ncols = array_size(tableSpec);
07683 s->rows[s->ncols + 0] = "";
07684 s->rows[s->ncols + 1] = "";
07685 s->rows[s->ncols + 2] = "";
07686 s->rows[s->ncols + 3] = "TABLE";
07687 s->rows[s->ncols + 5] = "";
07688 s->rows[s->ncols + 6] = "";
07689 s->rows[s->ncols + 7] = "";
07690 s->rows[s->ncols + 8] = "VIEW";
07691 #ifdef MEMORY_DEBUG
07692 s->rowfree = xfree__;
07693 #else
07694 s->rowfree = free;
07695 #endif
07696 s->nrows = 2;
07697 s->rowp = -1;
07698 return SQL_SUCCESS;
07699 }
07700 if (cat && (catLen > 0 || catLen == SQL_NTS) && cat[0] == '%') {
07701 int size = 2 * array_size(tableSpec);
07702
07703 s->rows = xmalloc(size * sizeof (char *));
07704 if (!s->rows) {
07705 s->nrows = 0;
07706 return nomem(s);
07707 }
07708 memset(s->rows, 0, sizeof (char *) * size);
07709 s->ncols = array_size(tableSpec);
07710 s->rows[s->ncols + 0] = "";
07711 s->rows[s->ncols + 1] = "";
07712 s->rows[s->ncols + 2] = d->dbname;
07713 s->rows[s->ncols + 3] = "CATALOG";
07714 #ifdef MEMORY_DEBUG
07715 s->rowfree = xfree__;
07716 #else
07717 s->rowfree = free;
07718 #endif
07719 s->nrows = 1;
07720 s->rowp = -1;
07721 return SQL_SUCCESS;
07722 }
07723 if (schema && (schemaLen > 0 || schemaLen == SQL_NTS) &&
07724 schema[0] == '%') {
07725 if ((!cat || catLen == 0 || !cat[0]) &&
07726 (!table || tableLen == 0 || !table[0])) {
07727 int size = 2 * array_size(tableSpec);
07728
07729 s->rows = xmalloc(size * sizeof (char *));
07730 if (!s->rows) {
07731 s->nrows = 0;
07732 return nomem(s);
07733 }
07734 memset(s->rows, 0, sizeof (char *) * size);
07735 s->ncols = array_size(tableSpec);
07736 s->rows[s->ncols + 1] = "";
07737 #ifdef MEMORY_DEBUG
07738 s->rowfree = xfree__;
07739 #else
07740 s->rowfree = free;
07741 #endif
07742 s->nrows = 1;
07743 s->rowp = -1;
07744 return SQL_SUCCESS;
07745 }
07746 }
07747 if (type) {
07748 char tmp[256], *t;
07749 int with_view = 0, with_table = 0;
07750
07751 if (typeLen == SQL_NTS) {
07752 strncpy(tmp, (char *) type, sizeof (tmp));
07753 tmp[sizeof (tmp) - 1] = '\0';
07754 } else {
07755 int len = min(sizeof (tmp) - 1, typeLen);
07756
07757 strncpy(tmp, (char *) type, len);
07758 tmp[len] = '\0';
07759 }
07760 t = tmp;
07761 while (*t) {
07762 *t = TOLOWER(*t);
07763 t++;
07764 }
07765 t = tmp;
07766 while (t) {
07767 if (t[0] == '\'') {
07768 ++t;
07769 }
07770 if (strncmp(t, "table", 5) == 0) {
07771 with_table++;
07772 } else if (strncmp(t, "view", 4) == 0) {
07773 with_view++;
07774 }
07775 t = strchr(t, ',');
07776 if (t) {
07777 ++t;
07778 }
07779 }
07780 if (with_view && with_table) {
07781
07782 } else if (with_view && !with_table) {
07783 where = "type = 'view'";
07784 } else if (!with_view && with_table) {
07785 where = "type = 'table'";
07786 } else {
07787 s->rowp = -1;
07788 return SQL_SUCCESS;
07789 }
07790 }
07791 strcpy(tname, "%");
07792 if (table && (tableLen > 0 || tableLen == SQL_NTS) && table[0] != '%') {
07793 int size;
07794
07795 if (tableLen == SQL_NTS) {
07796 size = sizeof (tname) - 1;
07797 } else {
07798 size = min(sizeof (tname) - 1, tableLen);
07799 }
07800 strncpy(tname, (char *) table, size);
07801 tname[size] = '\0';
07802 }
07803 sql = sqlite3_mprintf("select '' as 'TABLE_QUALIFIER', "
07804 "'' as 'TABLE_OWNER', "
07805 "tbl_name as 'TABLE_NAME', "
07806 "upper(type) as 'TABLE_TYPE', "
07807 "NULL as 'REMARKS' "
07808 "from sqlite_master where %s "
07809 "and tbl_name like '%q'", where, tname);
07810 if (!sql) {
07811 return nomem(s);
07812 }
07813 dbtraceapi(d, "sqlite3_get_table", sql);
07814 rc = sqlite3_get_table(d->sqlite, sql, &s->rows, &s->nrows, &ncols, &errp);
07815 sqlite3_free(sql);
07816 if (rc == SQLITE_OK) {
07817 if (ncols != s->ncols) {
07818 freeresult(s, 0);
07819 s->nrows = 0;
07820 } else {
07821 s->rowfree = sqlite3_free_table;
07822 }
07823 } else {
07824 s->nrows = 0;
07825 s->rows = NULL;
07826 s->rowfree = NULL;
07827 }
07828 if (errp) {
07829 sqlite3_free(errp);
07830 errp = NULL;
07831 }
07832 s->rowp = -1;
07833 return SQL_SUCCESS;
07834 }
07835
07850 SQLRETURN SQL_API
07851 SQLTables(SQLHSTMT stmt,
07852 SQLCHAR *cat, SQLSMALLINT catLen,
07853 SQLCHAR *schema, SQLSMALLINT schemaLen,
07854 SQLCHAR *table, SQLSMALLINT tableLen,
07855 SQLCHAR *type, SQLSMALLINT typeLen)
07856 {
07857 return drvtables(stmt, cat, catLen, schema, schemaLen,
07858 table, tableLen, type, typeLen);
07859 }
07860
07865 static COL colSpec[] = {
07866 { "SYSTEM", "COLUMN", "TABLE_QUALIFIER", SCOL_VARCHAR, 50 },
07867 { "SYSTEM", "COLUMN", "TABLE_OWNER", SCOL_VARCHAR, 50 },
07868 { "SYSTEM", "COLUMN", "TABLE_NAME", SCOL_VARCHAR, 255 },
07869 { "SYSTEM", "COLUMN", "COLUMN_NAME", SCOL_VARCHAR, 255 },
07870 { "SYSTEM", "COLUMN", "DATA_TYPE", SQL_SMALLINT, 50 },
07871 { "SYSTEM", "COLUMN", "TYPE_NAME", SCOL_VARCHAR, 50 },
07872 { "SYSTEM", "COLUMN", "PRECISION", SQL_INTEGER, 50 },
07873 { "SYSTEM", "COLUMN", "LENGTH", SQL_INTEGER, 50 },
07874 { "SYSTEM", "COLUMN", "RADIX", SQL_SMALLINT, 50 },
07875 { "SYSTEM", "COLUMN", "SCALE", SQL_SMALLINT, 50 },
07876 { "SYSTEM", "COLUMN", "NULLABLE", SQL_SMALLINT, 50 },
07877 { "SYSTEM", "COLUMN", "REMARKS", SCOL_VARCHAR, 50 },
07878 { "SYSTEM", "COLUMN", "COLUMN_DEF", SCOL_VARCHAR, 50 },
07879 { "SYSTEM", "COLUMN", "SQL_DATA_TYPE", SQL_SMALLINT, 50 },
07880 { "SYSTEM", "COLUMN", "SQL_DATETIME_SUB", SQL_SMALLINT, 50 },
07881 { "SYSTEM", "COLUMN", "CHAR_OCTET_LENGTH", SQL_SMALLINT, 50 },
07882 { "SYSTEM", "COLUMN", "ORDINAL_POSITION", SQL_SMALLINT, 50 },
07883 { "SYSTEM", "COLUMN", "IS_NULLABLE", SCOL_VARCHAR, 50 }
07884 };
07885
07900 static SQLRETURN
07901 drvcolumns(SQLHSTMT stmt,
07902 SQLCHAR *cat, SQLSMALLINT catLen,
07903 SQLCHAR *schema, SQLSMALLINT schemaLen,
07904 SQLCHAR *table, SQLSMALLINT tableLen,
07905 SQLCHAR *col, SQLSMALLINT colLen)
07906 {
07907 SQLRETURN sret;
07908 STMT *s;
07909 DBC *d;
07910 int ret, nrows, ncols, size, i, k;
07911 char *errp = NULL, *sql, tname[512], **rowp;
07912
07913 sret = mkresultset(stmt, colSpec, array_size(colSpec));
07914 if (sret != SQL_SUCCESS) {
07915 return sret;
07916 }
07917 s = (STMT *) stmt;
07918 d = (DBC *) s->dbc;
07919 if (!table || table[0] == '\0' || table[0] == '%') {
07920 setstat(s, -1, "need table name", (*s->ov3) ? "HY000" : "S1000");
07921 return SQL_ERROR;
07922 }
07923 if (tableLen == SQL_NTS) {
07924 size = sizeof (tname) - 1;
07925 } else {
07926 size = min(sizeof (tname) - 1, tableLen);
07927 }
07928 strncpy(tname, (char *) table, size);
07929 tname[size] = '\0';
07930 sql = sqlite3_mprintf("PRAGMA table_info('%q')", tname);
07931 if (!sql) {
07932 return nomem(s);
07933 }
07934 dbtraceapi(d, "sqlite3_get_table", sql);
07935 ret = sqlite3_get_table(d->sqlite, sql, &rowp, &nrows, &ncols, &errp);
07936 sqlite3_free(sql);
07937 if (ret != SQLITE_OK) {
07938 setstat(s, ret, "%s (%d)", (*s->ov3) ? "HY000" : "S1000",
07939 errp ? errp : "unknown error", ret);
07940 if (errp) {
07941 sqlite3_free(errp);
07942 errp = NULL;
07943 }
07944 return SQL_ERROR;
07945 }
07946 if (errp) {
07947 sqlite3_free(errp);
07948 errp = NULL;
07949 }
07950 if (ncols * nrows <= 0) {
07951 sqlite3_free_table(rowp);
07952 return SQL_NO_DATA;
07953 }
07954 size = array_size(colSpec) * (nrows + 1);
07955 s->rows = xmalloc((size + 1) * sizeof (char *));
07956 if (!s->rows) {
07957 return nomem(s);
07958 }
07959 s->rows[0] = (char *) size;
07960 s->rows += 1;
07961 memset(s->rows, 0, sizeof (char *) * size);
07962 s->rowfree = freerows;
07963 s->nrows = nrows;
07964 for (i = 1; i <= s->nrows; i++) {
07965 s->rows[array_size(colSpec) * i + 0] = xstrdup("");
07966 s->rows[array_size(colSpec) * i + 1] = xstrdup("");
07967 s->rows[array_size(colSpec) * i + 2] = xstrdup(tname);
07968 s->rows[array_size(colSpec) * i + 8] = xstrdup("10");
07969 s->rows[array_size(colSpec) * i + 9] = xstrdup("0");
07970 s->rows[array_size(colSpec) * i + 15] = xstrdup("16384");
07971 }
07972 for (k = 0; k < ncols; k++) {
07973 if (strcmp(rowp[k], "cid") == 0) {
07974 for (i = 1; i <= s->nrows; i++) {
07975 char buf[256];
07976 int coln = i;
07977
07978 sscanf(rowp[i * ncols + k], "%d", &coln);
07979 sprintf(buf, "%d", coln + 1);
07980 s->rows[array_size(colSpec) * i + 16] = xstrdup(buf);
07981 }
07982 } else if (strcmp(rowp[k], "name") == 0) {
07983 for (i = 1; i <= s->nrows; i++) {
07984 s->rows[array_size(colSpec) * i + 3] =
07985 xstrdup(rowp[i * ncols + k]);
07986 }
07987 } else if (strcmp(rowp[k], "notnull") == 0) {
07988 for (i = 1; i <= s->nrows; i++) {
07989 if (*rowp[i * ncols + k] != '0') {
07990 s->rows[array_size(colSpec) * i + 10] =
07991 xstrdup(stringify(SQL_FALSE));
07992 } else {
07993 s->rows[array_size(colSpec) * i + 10] =
07994 xstrdup(stringify(SQL_TRUE));
07995 }
07996 s->rows[array_size(colSpec) * i + 17] =
07997 xstrdup(*rowp[i * ncols + k] != '0' ? "NO" : "YES");
07998 }
07999 } else if (strcmp(rowp[k], "dflt_value") == 0) {
08000 for (i = 1; i <= s->nrows; i++) {
08001 char *dflt = rowp[i * ncols + k];
08002
08003 s->rows[array_size(colSpec) * i + 12] =
08004 xstrdup(dflt ? dflt : "NULL");
08005 }
08006 } else if (strcmp(rowp[k], "type") == 0) {
08007 for (i = 1; i <= s->nrows; i++) {
08008 char *typename = rowp[i * ncols + k];
08009 int sqltype, m, d;
08010 char buf[256];
08011
08012 s->rows[array_size(colSpec) * i + 5] = xstrdup(typename);
08013 sqltype = mapsqltype(typename, NULL, *s->ov3);
08014 getmd(typename, sqltype, &m, &d);
08015 #ifdef SQL_LONGVARCHAR
08016 if (sqltype == SQL_VARCHAR && m > 255) {
08017 sqltype = SQL_LONGVARCHAR;
08018 }
08019 #endif
08020 if (sqltype == SQL_VARBINARY && m > 255) {
08021 sqltype = SQL_LONGVARBINARY;
08022 }
08023 sprintf(buf, "%d", sqltype);
08024 s->rows[array_size(colSpec) * i + 4] = xstrdup(buf);
08025 s->rows[array_size(colSpec) * i + 13] = xstrdup(buf);
08026 sprintf(buf, "%d", m);
08027 s->rows[array_size(colSpec) * i + 7] = xstrdup(buf);
08028 sprintf(buf, "%d", d);
08029 s->rows[array_size(colSpec) * i + 6] = xstrdup(buf);
08030 }
08031 }
08032 }
08033 sqlite3_free_table(rowp);
08034 return SQL_SUCCESS;
08035 }
08036
08051 SQLRETURN SQL_API
08052 SQLColumns(SQLHSTMT stmt,
08053 SQLCHAR *cat, SQLSMALLINT catLen,
08054 SQLCHAR *schema, SQLSMALLINT schemaLen,
08055 SQLCHAR *table, SQLSMALLINT tableLen,
08056 SQLCHAR *col, SQLSMALLINT colLen)
08057 {
08058 return drvcolumns(stmt, cat, catLen, schema, schemaLen,
08059 table, tableLen, col, colLen);
08060 }
08061
08066 static COL typeSpec[] = {
08067 { "SYSTEM", "TYPE", "TYPE_NAME", SCOL_VARCHAR, 50 },
08068 { "SYSTEM", "TYPE", "DATA_TYPE", SQL_SMALLINT, 2 },
08069 { "SYSTEM", "TYPE", "PRECISION", SQL_INTEGER, 4 },
08070 { "SYSTEM", "TYPE", "LITERAL_PREFIX", SCOL_VARCHAR, 50 },
08071 { "SYSTEM", "TYPE", "LITERAL_SUFFIX", SCOL_VARCHAR, 50 },
08072 { "SYSTEM", "TYPE", "CREATE_PARAMS", SCOL_VARCHAR, 50 },
08073 { "SYSTEM", "TYPE", "NULLABLE", SQL_SMALLINT, 2 },
08074 { "SYSTEM", "TYPE", "CASE_SENSITIVE", SQL_SMALLINT, 2 },
08075 { "SYSTEM", "TYPE", "SEARCHABLE", SQL_SMALLINT, 2 },
08076 { "SYSTEM", "TYPE", "UNSIGNED_ATTRIBUTE", SQL_SMALLINT, 2 },
08077 { "SYSTEM", "TYPE", "MONEY", SQL_SMALLINT, 2 },
08078 { "SYSTEM", "TYPE", "AUTO_INCREMENT", SQL_SMALLINT, 2 },
08079 { "SYSTEM", "TYPE", "LOCAL_TYPE_NAME", SCOL_VARCHAR, 50 },
08080 { "SYSTEM", "TYPE", "MINIMUM_SCALE", SQL_SMALLINT, 2 },
08081 { "SYSTEM", "TYPE", "MAXIMUM_SCALE", SQL_SMALLINT, 2 }
08082 };
08083
08093 static void
08094 mktypeinfo(STMT *s, int row, char *typename, int type, int tind)
08095 {
08096 int offs = row * array_size(typeSpec);
08097 char *tcode, *crpar = NULL, *quote = NULL, *sign = stringify(SQL_FALSE);
08098 static char tcodes[32 * 32];
08099
08100 if (tind <= 0) {
08101 tind = row;
08102 }
08103 tcode = tcodes + tind * 32;
08104 sprintf(tcode, "%d", type);
08105 s->rows[offs + 0] = typename;
08106 s->rows[offs + 1] = tcode;
08107 switch (type) {
08108 default:
08109 #ifdef SQL_LONGVARCHAR
08110 case SQL_LONGVARCHAR:
08111 crpar = "length";
08112 quote = "'";
08113 sign = NULL;
08114 s->rows[offs + 2] = "65536";
08115 break;
08116 #endif
08117 #ifdef SQL_BIT
08118 case SQL_BIT:
08119 sign = NULL;
08120 s->rows[offs + 2] = "1";
08121 break;
08122 #endif
08123 case SQL_CHAR:
08124 case SQL_VARCHAR:
08125 s->rows[offs + 2] = "255";
08126 crpar = "length";
08127 quote = "'";
08128 sign = NULL;
08129 break;
08130 case SQL_TINYINT:
08131 s->rows[offs + 2] = "3";
08132 break;
08133 case SQL_SMALLINT:
08134 s->rows[offs + 2] = "5";
08135 break;
08136 case SQL_INTEGER:
08137 s->rows[offs + 2] = "7";
08138 break;
08139 #ifdef SQL_BIGINT
08140 case SQL_BIGINT:
08141 s->rows[offs + 2] = "19";
08142 break;
08143 #endif
08144 case SQL_FLOAT:
08145 s->rows[offs + 2] = "7";
08146 break;
08147 case SQL_DOUBLE:
08148 s->rows[offs + 2] = "15";
08149 break;
08150 #ifdef SQL_TYPE_DATE
08151 case SQL_TYPE_DATE:
08152 #endif
08153 case SQL_DATE:
08154 s->rows[offs + 2] = "10";
08155 quote = "'";
08156 sign = NULL;
08157 break;
08158 #ifdef SQL_TYPE_TIME
08159 case SQL_TYPE_TIME:
08160 #endif
08161 case SQL_TIME:
08162 s->rows[offs + 2] = "8";
08163 quote = "'";
08164 sign = NULL;
08165 break;
08166 #ifdef SQL_TYPE_TIMESTAMP
08167 case SQL_TYPE_TIMESTAMP:
08168 #endif
08169 case SQL_TIMESTAMP:
08170 s->rows[offs + 2] = "32";
08171 quote = "'";
08172 sign = NULL;
08173 break;
08174 case SQL_VARBINARY:
08175 sign = NULL;
08176 s->rows[offs + 2] = "255";
08177 break;
08178 case SQL_LONGVARBINARY:
08179 sign = NULL;
08180 s->rows[offs + 2] = "65536";
08181 break;
08182 }
08183 s->rows[offs + 3] = s->rows[offs + 4] = quote;
08184 s->rows[offs + 5] = crpar;
08185 s->rows[offs + 6] = stringify(SQL_NULLABLE);
08186 s->rows[offs + 7] = stringify(SQL_FALSE);
08187 s->rows[offs + 8] = stringify(SQL_SEARCHABLE);
08188 s->rows[offs + 9] = sign;
08189 s->rows[offs + 10] = stringify(SQL_FALSE);
08190 s->rows[offs + 11] = stringify(SQL_FALSE);
08191 s->rows[offs + 12] = typename;
08192 s->rows[offs + 13] = NULL;
08193 s->rows[offs + 14] = NULL;
08194 }
08195
08204 static int
08205 typeinfosort(const void *a, const void *b)
08206 {
08207 char **pa = (char **) a;
08208 char **pb = (char **) b;
08209 int na, nb;
08210
08211 na = strtol(pa[1], NULL, 0);
08212 nb = strtol(pb[1], NULL, 0);
08213 return na - nb;
08214 }
08215
08223 static SQLRETURN
08224 drvgettypeinfo(SQLHSTMT stmt, SQLSMALLINT sqltype)
08225 {
08226 SQLRETURN ret;
08227 STMT *s;
08228 DBC *d;
08229
08230 ret = mkresultset(stmt, typeSpec, array_size(typeSpec));
08231 if (ret != SQL_SUCCESS) {
08232 return ret;
08233 }
08234 s = (STMT *) stmt;
08235 d = (DBC *) s->dbc;
08236 #ifdef SQL_LONGVARCHAR
08237 s->nrows = sqltype == SQL_ALL_TYPES ? 13 : 1;
08238 #else
08239 s->nrows = sqltype == SQL_ALL_TYPES ? 12 : 1;
08240 #endif
08241 if (sqltype == SQL_ALL_TYPES) {
08242 s->nrows += 2;
08243 #ifdef SQL_BIT
08244 s->nrows += 1;
08245 #endif
08246 #ifdef SQL_BIGINT
08247 s->nrows += 1;
08248 #endif
08249 }
08250 s->rows = (char **) xmalloc(sizeof (char *) * (s->nrows + 1)
08251 * array_size(typeSpec));
08252 if (!s->rows) {
08253 s->nrows = 0;
08254 return nomem(s);
08255 }
08256 #ifdef MEMORY_DEBUG
08257 s->rowfree = xfree__;
08258 #else
08259 s->rowfree = free;
08260 #endif
08261 memset(s->rows, 0,
08262 sizeof (char *) * (s->nrows + 1) * array_size(typeSpec));
08263 if (sqltype == SQL_ALL_TYPES) {
08264 int cc = 1;
08265
08266 mktypeinfo(s, cc++, "varchar", SQL_VARCHAR, 0);
08267 mktypeinfo(s, cc++, "tinyint", SQL_TINYINT, 0);
08268 mktypeinfo(s, cc++, "smallint", SQL_SMALLINT, 0);
08269 mktypeinfo(s, cc++, "integer", SQL_INTEGER, 0);
08270 mktypeinfo(s, cc++, "float", SQL_FLOAT, 0);
08271 mktypeinfo(s, cc++, "double", SQL_DOUBLE, 0);
08272 #ifdef SQL_TYPE_DATE
08273 mktypeinfo(s, cc++, "date", (*s->ov3) ? SQL_TYPE_DATE : SQL_DATE, 0);
08274 #else
08275 mktypeinfo(s, cc++, "date", SQL_DATE, 0);
08276 #endif
08277 #ifdef SQL_TYPE_TIME
08278 mktypeinfo(s, cc++, "time", (*s->ov3) ? SQL_TYPE_TIME : SQL_TIME, 0);
08279 #else
08280 mktypeinfo(s, cc++, "time", SQL_TIME, 0);
08281 #endif
08282 #ifdef SQL_TYPE_TIMESTAMP
08283 mktypeinfo(s, cc++, "timestamp",
08284 (*s->ov3) ? SQL_TYPE_TIMESTAMP : SQL_TIMESTAMP, 0);
08285 #else
08286 mktypeinfo(s, cc++, "timestamp", SQL_TIMESTAMP, 0);
08287 #endif
08288 mktypeinfo(s, cc++, "char", SQL_CHAR, 0);
08289 mktypeinfo(s, cc++, "numeric", SQL_DOUBLE, 0);
08290 #ifdef SQL_LONGVARCHAR
08291 mktypeinfo(s, cc++, "text", SQL_LONGVARCHAR, 0);
08292 mktypeinfo(s, cc++, "longvarchar", SQL_LONGVARCHAR, 0);
08293 #else
08294 mktypeinfo(s, cc++, "text", SQL_VARCHAR, 0);
08295 #endif
08296 mktypeinfo(s, cc++, "varbinary", SQL_VARBINARY, 0);
08297 mktypeinfo(s, cc++, "longvarbinary", SQL_LONGVARBINARY, 0);
08298 #ifdef SQL_BIT
08299 mktypeinfo(s, cc++, "bit", SQL_BIT, 0);
08300 #endif
08301 #ifdef SQL_BIGINT
08302 mktypeinfo(s, cc++, "bigint", SQL_BIGINT, 0);
08303 #endif
08304 qsort(s->rows + array_size(typeSpec), s->nrows,
08305 sizeof (char *) * array_size(typeSpec), typeinfosort);
08306 } else {
08307 switch (sqltype) {
08308 case SQL_CHAR:
08309 mktypeinfo(s, 1, "char", SQL_CHAR, 10);
08310 break;
08311 case SQL_VARCHAR:
08312 mktypeinfo(s, 1, "varchar", SQL_VARCHAR, 1);
08313 break;
08314 case SQL_TINYINT:
08315 mktypeinfo(s, 1, "tinyint", SQL_TINYINT, 2);
08316 break;
08317 case SQL_SMALLINT:
08318 mktypeinfo(s, 1, "smallint", SQL_SMALLINT, 3);
08319 break;
08320 case SQL_INTEGER:
08321 mktypeinfo(s, 1, "integer", SQL_INTEGER, 4);
08322 break;
08323 case SQL_FLOAT:
08324 mktypeinfo(s, 1, "float", SQL_FLOAT, 5);
08325 break;
08326 case SQL_DOUBLE:
08327 mktypeinfo(s, 1, "double", SQL_DOUBLE, 6);
08328 break;
08329 #ifdef SQL_TYPE_DATE
08330 case SQL_TYPE_DATE:
08331 mktypeinfo(s, 1, "date", SQL_TYPE_DATE, 25);
08332 break;
08333 #endif
08334 case SQL_DATE:
08335 mktypeinfo(s, 1, "date", SQL_DATE, 7);
08336 break;
08337 #ifdef SQL_TYPE_TIME
08338 case SQL_TYPE_TIME:
08339 mktypeinfo(s, 1, "date", SQL_TYPE_TIME, 26);
08340 break;
08341 #endif
08342 case SQL_TIME:
08343 mktypeinfo(s, 1, "time", SQL_TIME, 8);
08344 break;
08345 #ifdef SQL_TYPE_TIMESTAMP
08346 case SQL_TYPE_TIMESTAMP:
08347 mktypeinfo(s, 1, "date", SQL_TYPE_TIMESTAMP, 27);
08348 break;
08349 #endif
08350 case SQL_TIMESTAMP:
08351 mktypeinfo(s, 1, "timestamp", SQL_TIMESTAMP, 9);
08352 break;
08353 #ifdef SQL_LONGVARCHAR
08354 case SQL_LONGVARCHAR:
08355 mktypeinfo(s, 1, "longvarchar", SQL_LONGVARCHAR, 12);
08356 break;
08357 #endif
08358 case SQL_VARBINARY:
08359 mktypeinfo(s, 1, "varbinary", SQL_VARBINARY, 30);
08360 break;
08361 case SQL_LONGVARBINARY:
08362 mktypeinfo(s, 1, "longvarbinary", SQL_LONGVARBINARY, 31);
08363 break;
08364 #ifdef SQL_BIT
08365 case SQL_BIT:
08366 mktypeinfo(s, 1, "bit", SQL_BIT, 29);
08367 break;
08368 #endif
08369 #ifdef SQL_BIGINT
08370 case SQL_BIGINT:
08371 mktypeinfo(s, 1, "bigint", SQL_BIGINT, 28);
08372 break;
08373 #endif
08374 default:
08375 s->nrows = 0;
08376 return SQL_NO_DATA;
08377 }
08378 }
08379 return SQL_SUCCESS;
08380 }
08381
08389 SQLRETURN SQL_API
08390 SQLGetTypeInfo(SQLHSTMT stmt, SQLSMALLINT sqltype)
08391 {
08392 return drvgettypeinfo(stmt, sqltype);
08393 }
08394
08399 static COL statSpec[] = {
08400 { "SYSTEM", "STATISTICS", "TABLE_QUALIFIER", SCOL_VARCHAR, 50 },
08401 { "SYSTEM", "STATISTICS", "TABLE_OWNER", SCOL_VARCHAR, 50 },
08402 { "SYSTEM", "STATISTICS", "TABLE_NAME", SCOL_VARCHAR, 255 },
08403 { "SYSTEM", "STATISTICS", "NON_UNIQUE", SQL_SMALLINT, 50 },
08404 { "SYSTEM", "STATISTICS", "INDEX_QUALIFIER", SCOL_VARCHAR, 255 },
08405 { "SYSTEM", "STATISTICS", "INDEX_NAME", SCOL_VARCHAR, 255 },
08406 { "SYSTEM", "STATISTICS", "TYPE", SQL_SMALLINT, 50 },
08407 { "SYSTEM", "STATISTICS", "ORDINAL_POSITION", SQL_SMALLINT, 50 },
08408 { "SYSTEM", "STATISTICS", "COLUMN_NAME", SCOL_VARCHAR, 255 },
08409 { "SYSTEM", "STATISTICS", "ASC_OR_DESC", SCOL_CHAR, 1 },
08410 { "SYSTEM", "STATISTICS", "CARDINALITY", SQL_INTEGER, 50 },
08411 { "SYSTEM", "STATISTICS", "PAGES", SQL_INTEGER, 50 },
08412 { "SYSTEM", "STATISTICS", "FILTER_CONDITION", SCOL_VARCHAR, 255 }
08413 };
08414
08429 static SQLRETURN
08430 drvstatistics(SQLHSTMT stmt, SQLCHAR *cat, SQLSMALLINT catLen,
08431 SQLCHAR *schema, SQLSMALLINT schemaLen,
08432 SQLCHAR *table, SQLSMALLINT tableLen,
08433 SQLUSMALLINT itype, SQLUSMALLINT resv)
08434 {
08435 SQLRETURN sret;
08436 STMT *s;
08437 DBC *d;
08438 int i, size, ret, nrows, ncols, offs, namec, uniquec;
08439 char **rowp, *errp = NULL, *sql, tname[512];
08440
08441 sret = mkresultset(stmt, statSpec, array_size(statSpec));
08442 if (sret != SQL_SUCCESS) {
08443 return sret;
08444 }
08445 s = (STMT *) stmt;
08446 d = (DBC *) s->dbc;
08447 if (!table || table[0] == '\0' || table[0] == '%') {
08448 setstat(s, -1, "need table name", (*s->ov3) ? "HY000" : "S1000");
08449 return SQL_ERROR;
08450 }
08451 if (tableLen == SQL_NTS) {
08452 size = sizeof (tname) - 1;
08453 } else {
08454 size = min(sizeof (tname) - 1, tableLen);
08455 }
08456 strncpy(tname, (char *) table, size);
08457 tname[size] = '\0';
08458 sql = sqlite3_mprintf("PRAGMA index_list('%q')", tname);
08459 if (!sql) {
08460 return nomem(s);
08461 }
08462 dbtraceapi(d, "sqlite3_get_table", sql);
08463 ret = sqlite3_get_table(d->sqlite, sql, &rowp, &nrows, &ncols, &errp);
08464 sqlite3_free(sql);
08465 if (ret != SQLITE_OK) {
08466 setstat(s, ret, "%s (%d)", (*s->ov3) ? "HY000" : "S1000",
08467 errp ? errp : "unknown error", ret);
08468 if (errp) {
08469 sqlite3_free(errp);
08470 errp = NULL;
08471 }
08472 return SQL_ERROR;
08473 }
08474 if (errp) {
08475 sqlite3_free(errp);
08476 errp = NULL;
08477 }
08478 if (ncols * nrows <= 0) {
08479 nodata:
08480 sqlite3_free_table(rowp);
08481
08482 if (itype == SQL_INDEX_UNIQUE) {
08483 ret = SQLITE_ERROR;
08484
08485 sql = sqlite3_mprintf("PRAGMA table_info('%q')", tname);
08486 if (sql) {
08487 dbtraceapi(d, "sqlite3_get_table", sql);
08488 ret = sqlite3_get_table(d->sqlite, sql, &rowp,
08489 &nrows, &ncols, NULL);
08490 sqlite3_free(sql);
08491 }
08492 if (ret == SQLITE_OK) {
08493 int colid, typec, roffs;
08494
08495 namec = findcol(rowp, ncols, "name");
08496 uniquec = findcol(rowp, ncols, "pk");
08497 typec = findcol(rowp, ncols, "type");
08498 colid = findcol(rowp, ncols, "cid");
08499 if (namec < 0 || uniquec < 0 || typec < 0 || colid < 0) {
08500 goto nodata2;
08501 }
08502 for (i = 1; i <= nrows; i++) {
08503 if (*rowp[i * ncols + uniquec] != '0' &&
08504 strlen(rowp[i * ncols + typec]) == 7 &&
08505 strncasecmp(rowp[i * ncols + typec], "integer", 7)
08506 == 0) {
08507 break;
08508 }
08509 }
08510 if (i > nrows) {
08511 goto nodata2;
08512 }
08513 size = (1 + 1) * array_size(statSpec);
08514 s->rows = xmalloc((size + 1) * sizeof (char *));
08515 if (!s->rows) {
08516 s->nrows = 0;
08517 return nomem(s);
08518 }
08519 s->rows[0] = (char *) size;
08520 s->rows += 1;
08521 memset(s->rows, 0, sizeof (char *) * size);
08522 s->rowfree = freerows;
08523 s->nrows = 1;
08524 roffs = s->ncols;
08525 s->rows[roffs + 0] = xstrdup("");
08526 s->rows[roffs + 1] = xstrdup("");
08527 s->rows[roffs + 2] = xstrdup(tname);
08528 s->rows[roffs + 3] = xstrdup(stringify(SQL_FALSE));
08529 s->rows[roffs + 4] = xstrdup("");
08530 s->rows[roffs + 5] = xstrdup("");
08531 s->rows[roffs + 6] = xstrdup(stringify(SQL_INDEX_OTHER));
08532 s->rows[roffs + 7] = xstrdup("1");
08533 s->rows[roffs + 8] = xstrdup(rowp[i * ncols + namec]);
08534 s->rows[roffs + 9] = xstrdup("A");
08535 nodata2:
08536 sqlite3_free_table(rowp);
08537 }
08538 }
08539 return SQL_SUCCESS;
08540 }
08541 size = 0;
08542 namec = findcol(rowp, ncols, "name");
08543 uniquec = findcol(rowp, ncols, "unique");
08544 if (namec < 0 || uniquec < 0) {
08545 goto nodata;
08546 }
08547 for (i = 1; i <= nrows; i++) {
08548 int nnrows, nncols;
08549 char **rowpp;
08550 int isuniq;
08551
08552 isuniq = *rowp[i * ncols + uniquec] != '0';
08553 if (isuniq || itype == SQL_INDEX_ALL) {
08554 ret = SQLITE_ERROR;
08555 sql = sqlite3_mprintf("PRAGMA index_info('%q')",
08556 rowp[i * ncols + namec]);
08557 if (sql) {
08558 dbtraceapi(d, "sqlite3_get_table", sql);
08559 ret = sqlite3_get_table(d->sqlite, sql, &rowpp,
08560 &nnrows, &nncols, NULL);
08561 sqlite3_free(sql);
08562 }
08563 if (ret == SQLITE_OK) {
08564 size += nnrows;
08565 sqlite3_free_table(rowpp);
08566 }
08567 }
08568 }
08569 if (size == 0) {
08570 goto nodata;
08571 }
08572 s->nrows = size;
08573 size = (size + 1) * array_size(statSpec);
08574 s->rows = xmalloc((size + 1) * sizeof (char *));
08575 if (!s->rows) {
08576 s->nrows = 0;
08577 return nomem(s);
08578 }
08579 s->rows[0] = (char *) size;
08580 s->rows += 1;
08581 memset(s->rows, 0, sizeof (char *) * size);
08582 s->rowfree = freerows;
08583 offs = 0;
08584 for (i = 1; i <= nrows; i++) {
08585 int nnrows, nncols;
08586 char **rowpp;
08587
08588 if (*rowp[i * ncols + uniquec] != '0' || itype == SQL_INDEX_ALL) {
08589 int k;
08590
08591 ret = SQLITE_ERROR;
08592 sql = sqlite3_mprintf("PRAGMA index_info('%q')",
08593 rowp[i * ncols + namec]);
08594 if (sql) {
08595 dbtraceapi(d, "sqlite3_get_table", sql);
08596 ret = sqlite3_get_table(d->sqlite, sql, &rowpp,
08597 &nnrows, &nncols, NULL);
08598 sqlite3_free(sql);
08599 }
08600 if (ret != SQLITE_OK) {
08601 continue;
08602 }
08603 for (k = 0; nnrows && k < nncols; k++) {
08604 if (strcmp(rowpp[k], "name") == 0) {
08605 int m;
08606
08607 for (m = 1; m <= nnrows; m++) {
08608 int roffs = (offs + m) * s->ncols;
08609 int isuniq;
08610
08611 isuniq = *rowp[i * ncols + uniquec] != '0';
08612 s->rows[roffs + 0] = xstrdup("");
08613 s->rows[roffs + 1] = xstrdup("");
08614 s->rows[roffs + 2] = xstrdup(tname);
08615 if (isuniq) {
08616 s->rows[roffs + 3] = xstrdup(stringify(SQL_FALSE));
08617 } else {
08618 s->rows[roffs + 3] = xstrdup(stringify(SQL_TRUE));
08619 }
08620 s->rows[roffs + 4] = xstrdup("");
08621 s->rows[roffs + 5] = xstrdup(rowp[i * ncols + namec]);
08622 s->rows[roffs + 6] =
08623 xstrdup(stringify(SQL_INDEX_OTHER));
08624 s->rows[roffs + 8] = xstrdup(rowpp[m * nncols + k]);
08625 s->rows[roffs + 9] = xstrdup("A");
08626 }
08627 } else if (strcmp(rowpp[k], "seqno") == 0) {
08628 int m;
08629
08630 for (m = 1; m <= nnrows; m++) {
08631 int roffs = (offs + m) * s->ncols;
08632 int pos = m - 1;
08633 char buf[32];
08634
08635 sscanf(rowpp[m * nncols + k], "%d", &pos);
08636 sprintf(buf, "%d", pos + 1);
08637 s->rows[roffs + 7] = xstrdup(buf);
08638 }
08639 }
08640 }
08641 offs += nnrows;
08642 sqlite3_free_table(rowpp);
08643 }
08644 }
08645 sqlite3_free_table(rowp);
08646 return SQL_SUCCESS;
08647 }
08648
08663 SQLRETURN SQL_API
08664 SQLStatistics(SQLHSTMT stmt, SQLCHAR *cat, SQLSMALLINT catLen,
08665 SQLCHAR *schema, SQLSMALLINT schemaLen,
08666 SQLCHAR *table, SQLSMALLINT tableLen,
08667 SQLUSMALLINT itype, SQLUSMALLINT resv)
08668 {
08669 return drvstatistics(stmt, cat, catLen, schema, schemaLen,
08670 table, tableLen, itype, resv);
08671 }
08672
08684 SQLRETURN SQL_API
08685 SQLGetData(SQLHSTMT stmt, SQLUSMALLINT col, SQLSMALLINT type,
08686 SQLPOINTER val, SQLLEN len, SQLLEN *lenp)
08687 {
08688 STMT *s;
08689
08690 if (stmt == SQL_NULL_HSTMT) {
08691 return SQL_INVALID_HANDLE;
08692 }
08693 s = (STMT *) stmt;
08694 if (col == 0 && s->bkmrk && type == SQL_C_BOOKMARK) {
08695 *((long *) val) = s->rowp;
08696 if (lenp) {
08697 *lenp = sizeof (long);
08698 }
08699 return SQL_SUCCESS;
08700 }
08701 if (col < 1 || col > s->ncols) {
08702 setstat(s, -1, "invalid column", (*s->ov3) ? "07009" : "S1002");
08703 return SQL_ERROR;
08704 }
08705 --col;
08706 return getrowdata(s, col, type, val, len, lenp, 1);
08707 }
08708
08716 static SQLRETURN
08717 dofetchbind(STMT *s, int rsi)
08718 {
08719 int ret, i, withinfo = 0;
08720
08721 s->row_status0[rsi] = SQL_ROW_SUCCESS;
08722 if (s->bkmrk && s->bkmrkcol.valp) {
08723 long *val;
08724
08725 if (s->bind_type != SQL_BIND_BY_COLUMN) {
08726 val = (long *) ((char *) s->bkmrkcol.valp + s->bind_type * rsi);
08727 } else {
08728 val = (long *) s->bkmrkcol.valp + rsi;
08729 }
08730 if (s->bind_offs) {
08731 val = (long *) ((char *) val + *s->bind_offs);
08732 }
08733 *val = s->rowp;
08734 if (s->bkmrkcol.lenp) {
08735 SQLLEN *ival;
08736
08737 if (s->bind_type != SQL_BIND_BY_COLUMN) {
08738 ival = (SQLLEN *)
08739 ((char *) s->bkmrkcol.lenp + s->bind_type * rsi);
08740 } else {
08741 ival = &s->bkmrkcol.lenp[rsi];
08742 }
08743 if (s->bind_offs) {
08744 ival = (SQLLEN *) ((char *) ival + *s->bind_offs);
08745 }
08746 *ival = sizeof (long);
08747 }
08748 }
08749 ret = SQL_SUCCESS;
08750 for (i = 0; s->bindcols && i < s->ncols; i++) {
08751 BINDCOL *b = &s->bindcols[i];
08752 SQLPOINTER dp = 0;
08753 SQLLEN *lp = 0;
08754
08755 b->offs = 0;
08756 if (b->valp) {
08757 if (s->bind_type != SQL_BIND_BY_COLUMN) {
08758 dp = (SQLPOINTER) ((char *) b->valp + s->bind_type * rsi);
08759 } else {
08760 dp = (SQLPOINTER) ((char *) b->valp + b->max * rsi);
08761 }
08762 if (s->bind_offs) {
08763 dp = (SQLPOINTER) ((char *) dp + *s->bind_offs);
08764 }
08765 }
08766 if (b->lenp) {
08767 if (s->bind_type != SQL_BIND_BY_COLUMN) {
08768 lp = (SQLLEN *) ((char *) b->lenp + s->bind_type * rsi);
08769 } else {
08770 lp = b->lenp + rsi;
08771 }
08772 if (s->bind_offs) {
08773 lp = (SQLLEN *) ((char *) lp + *s->bind_offs);
08774 }
08775 }
08776 if (dp || lp) {
08777 ret = getrowdata(s, (SQLUSMALLINT) i, b->type, dp, b->max, lp, 0);
08778 if (!SQL_SUCCEEDED(ret)) {
08779 s->row_status0[rsi] = SQL_ROW_ERROR;
08780 break;
08781 }
08782 if (ret != SQL_SUCCESS) {
08783 withinfo = 1;
08784 #ifdef SQL_ROW_SUCCESS_WITH_INFO
08785 s->row_status0[rsi] = SQL_ROW_SUCCESS_WITH_INFO;
08786 #endif
08787 }
08788 }
08789 }
08790 if (SQL_SUCCEEDED(ret)) {
08791 ret = withinfo ? SQL_SUCCESS_WITH_INFO : SQL_SUCCESS;
08792 }
08793 return ret;
08794 }
08795
08804 static SQLRETURN
08805 drvfetchscroll(SQLHSTMT stmt, SQLSMALLINT orient, SQLINTEGER offset)
08806 {
08807 STMT *s;
08808 int i, withinfo = 0;
08809 SQLRETURN ret;
08810
08811 if (stmt == SQL_NULL_HSTMT) {
08812 return SQL_INVALID_HANDLE;
08813 }
08814 s = (STMT *) stmt;
08815 for (i = 0; i < s->rowset_size; i++) {
08816 s->row_status0[i] = SQL_ROW_NOROW;
08817 }
08818 if (s->row_status) {
08819 memcpy(s->row_status, s->row_status0,
08820 sizeof (SQLUSMALLINT) * s->rowset_size);
08821 }
08822 s->row_count0 = 0;
08823 if (s->row_count) {
08824 *s->row_count = s->row_count0;
08825 }
08826 if (!s->bindcols) {
08827 for (i = 0; i < s->rowset_size; i++) {
08828 s->row_status0[i] = SQL_ROW_ERROR;
08829 }
08830 ret = SQL_ERROR;
08831 i = 0;
08832 goto done2;
08833 }
08834 if (!s->isselect) {
08835 setstat(s, -1, "no result set available", "24000");
08836 ret = SQL_ERROR;
08837 i = s->nrows;
08838 goto done2;
08839 }
08840 if (s->curtype == SQL_CURSOR_FORWARD_ONLY && orient != SQL_FETCH_NEXT) {
08841 setstat(s, -1, "wrong fetch direction", "01000");
08842 ret = SQL_ERROR;
08843 i = 0;
08844 goto done2;
08845 }
08846 ret = SQL_SUCCESS;
08847 i = 0;
08848 if (((DBC *) (s->dbc))->cur_s3stmt == s && s->s3stmt) {
08849 s->rowp = 0;
08850 for (; i < s->rowset_size; i++) {
08851 ret = s3stmt_step(s);
08852 if (ret != SQL_SUCCESS) {
08853 s->row_status0[i] = SQL_ROW_ERROR;
08854 break;
08855 }
08856 if (s->nrows < 1) {
08857 break;
08858 }
08859 ret = dofetchbind(s, i);
08860 if (!SQL_SUCCEEDED(ret)) {
08861 break;
08862 } else if (ret == SQL_SUCCESS_WITH_INFO) {
08863 withinfo = 1;
08864 }
08865 }
08866 } else if (s->rows) {
08867 switch (orient) {
08868 case SQL_FETCH_NEXT:
08869 if (s->nrows < 1) {
08870 return SQL_NO_DATA;
08871 }
08872 if (s->rowp < 0) {
08873 s->rowp = -1;
08874 }
08875 if (s->rowp >= s->nrows) {
08876 s->rowp = s->nrows;
08877 return SQL_NO_DATA;
08878 }
08879 break;
08880 case SQL_FETCH_PRIOR:
08881 if (s->nrows < 1) {
08882 s->rowp = -1;
08883 return SQL_NO_DATA;
08884 }
08885 s->rowp -= s->rowset_size + 1;
08886 if (s->rowp < -1) {
08887 s->rowp = -1;
08888 return SQL_NO_DATA;
08889 }
08890 break;
08891 case SQL_FETCH_FIRST:
08892 if (s->nrows < 1) {
08893 return SQL_NO_DATA;
08894 }
08895 s->rowp = -1;
08896 break;
08897 case SQL_FETCH_LAST:
08898 if (s->nrows < 1) {
08899 return SQL_NO_DATA;
08900 }
08901 s->rowp = s->nrows - s->rowset_size;
08902 if (--s->rowp < -1) {
08903 s->rowp = -1;
08904 }
08905 break;
08906 case SQL_FETCH_ABSOLUTE:
08907 if (offset == 0) {
08908 s->rowp = -1;
08909 return SQL_NO_DATA;
08910 } else if (offset < 0) {
08911 if (0 - offset <= s->nrows) {
08912 s->rowp = s->nrows + offset - 1;
08913 break;
08914 }
08915 s->rowp = -1;
08916 return SQL_NO_DATA;
08917 } else if (offset > s->nrows) {
08918 s->rowp = s->nrows;
08919 return SQL_NO_DATA;
08920 }
08921 s->rowp = offset - 1 - 1;
08922 break;
08923 case SQL_FETCH_RELATIVE:
08924 if (offset >= 0) {
08925 s->rowp += offset * s->rowset_size - 1;
08926 if (s->rowp >= s->nrows) {
08927 s->rowp = s->nrows;
08928 return SQL_NO_DATA;
08929 }
08930 } else {
08931 s->rowp += offset * s->rowset_size - 1;
08932 if (s->rowp < -1) {
08933 s->rowp = -1;
08934 return SQL_NO_DATA;
08935 }
08936 }
08937 break;
08938 case SQL_FETCH_BOOKMARK:
08939 if (s->bkmrk) {
08940 if (offset < 0 || offset >= s->nrows) {
08941 return SQL_NO_DATA;
08942 }
08943 s->rowp = offset - 1;
08944 break;
08945 }
08946
08947 default:
08948 s->row_status0[0] = SQL_ROW_ERROR;
08949 ret = SQL_ERROR;
08950 goto done;
08951 }
08952 for (; i < s->rowset_size; i++) {
08953 ++s->rowp;
08954 if (s->rowp < 0 || s->rowp >= s->nrows) {
08955 break;
08956 }
08957 ret = dofetchbind(s, i);
08958 if (!SQL_SUCCEEDED(ret)) {
08959 break;
08960 } else if (ret == SQL_SUCCESS_WITH_INFO) {
08961 withinfo = 1;
08962 }
08963 }
08964 }
08965 done:
08966 if (i == 0) {
08967 if (SQL_SUCCEEDED(ret)) {
08968 return SQL_NO_DATA;
08969 }
08970 return ret;
08971 }
08972 if (SQL_SUCCEEDED(ret)) {
08973 ret = withinfo ? SQL_SUCCESS_WITH_INFO : SQL_SUCCESS;
08974 }
08975 done2:
08976 if (s->row_status) {
08977 memcpy(s->row_status, s->row_status0,
08978 sizeof (SQLUSMALLINT) * s->rowset_size);
08979 }
08980 s->row_count0 = i;
08981 if (s->row_count) {
08982 *s->row_count = s->row_count0;
08983 }
08984 return ret;
08985 }
08986
08993 SQLRETURN SQL_API
08994 SQLFetch(SQLHSTMT stmt)
08995 {
08996 return drvfetchscroll(stmt, SQL_FETCH_NEXT, 0);
08997 }
08998
09007 SQLRETURN SQL_API
09008 SQLFetchScroll(SQLHSTMT stmt, SQLSMALLINT orient, SQLLEN offset)
09009 {
09010 return drvfetchscroll(stmt, orient, offset);
09011 }
09012
09023 SQLRETURN SQL_API
09024 SQLExtendedFetch(SQLHSTMT stmt, SQLUSMALLINT orient, SQLLEN offset,
09025 SQLULEN *rowcount, SQLUSMALLINT *rowstatus)
09026 {
09027 STMT *s;
09028 SQLRETURN ret;
09029 SQLUSMALLINT *rst;
09030
09031 if (stmt == SQL_NULL_HSTMT) {
09032 return SQL_INVALID_HANDLE;
09033 }
09034 s = (STMT *) stmt;
09035
09036 rst = s->row_status;
09037 s->row_status = 0;
09038 ret = drvfetchscroll(stmt, orient, offset);
09039 s->row_status = rst;
09040 if (rowstatus) {
09041 memcpy(rowstatus, s->row_status0,
09042 sizeof (SQLUSMALLINT) * s->rowset_size);
09043 }
09044 if (rowcount) {
09045 *rowcount = s->row_count0;
09046 }
09047 return ret;
09048 }
09049
09057 SQLRETURN SQL_API
09058 SQLRowCount(SQLHSTMT stmt, SQLLEN *nrows)
09059 {
09060 STMT *s;
09061
09062 if (stmt == SQL_NULL_HSTMT) {
09063 return SQL_INVALID_HANDLE;
09064 }
09065 s = (STMT *) stmt;
09066 if (nrows) {
09067 *nrows = s->nrows;
09068 }
09069 return SQL_SUCCESS;
09070 }
09071
09079 SQLRETURN SQL_API
09080 SQLNumResultCols(SQLHSTMT stmt, SQLSMALLINT *ncols)
09081 {
09082 STMT *s;
09083
09084 if (stmt == SQL_NULL_HSTMT) {
09085 return SQL_INVALID_HANDLE;
09086 }
09087 s = (STMT *) stmt;
09088 if (ncols) {
09089 *ncols = s->ncols;
09090 }
09091 return SQL_SUCCESS;
09092 }
09093
09108 static SQLRETURN
09109 drvdescribecol(SQLHSTMT stmt, SQLUSMALLINT col, SQLCHAR *name,
09110 SQLSMALLINT nameMax, SQLSMALLINT *nameLen,
09111 SQLSMALLINT *type, SQLULEN *size,
09112 SQLSMALLINT *digits, SQLSMALLINT *nullable)
09113 {
09114 STMT *s;
09115 COL *c;
09116 int didname = 0;
09117
09118 if (stmt == SQL_NULL_HSTMT) {
09119 return SQL_INVALID_HANDLE;
09120 }
09121 s = (STMT *) stmt;
09122 if (!s->cols) {
09123 setstat(s, -1, "no columns", (*s->ov3) ? "07009" : "S1002");
09124 return SQL_ERROR;
09125 }
09126 if (col < 1 || col > s->ncols) {
09127 setstat(s, -1, "invalid column", (*s->ov3) ? "07009" : "S1002");
09128 return SQL_ERROR;
09129 }
09130 c = s->cols + col - 1;
09131 if (name && nameMax > 0) {
09132 strncpy((char *) name, c->column, nameMax);
09133 name[nameMax - 1] = '\0';
09134 didname = 1;
09135 }
09136 if (nameLen) {
09137 if (didname) {
09138 *nameLen = strlen((char *) name);
09139 } else {
09140 *nameLen = strlen(c->column);
09141 }
09142 }
09143 if (type) {
09144 *type = c->type;
09145 }
09146 if (size) {
09147 *size = c->size;
09148 }
09149 if (digits) {
09150 *digits = 0;
09151 }
09152 if (nullable) {
09153 *nullable = 1;
09154 }
09155 return SQL_SUCCESS;
09156 }
09157
09172 SQLRETURN SQL_API
09173 SQLDescribeCol(SQLHSTMT stmt, SQLUSMALLINT col, SQLCHAR *name,
09174 SQLSMALLINT nameMax, SQLSMALLINT *nameLen,
09175 SQLSMALLINT *type, SQLULEN *size,
09176 SQLSMALLINT *digits, SQLSMALLINT *nullable)
09177 {
09178 return drvdescribecol(stmt, col, name, nameMax, nameLen,
09179 type, size, digits, nullable);
09180 }
09181
09194 static SQLRETURN
09195 drvcolattributes(SQLHSTMT stmt, SQLUSMALLINT col, SQLUSMALLINT id,
09196 SQLPOINTER val, SQLSMALLINT valMax, SQLSMALLINT *valLen,
09197 SQLLEN *val2)
09198 {
09199 STMT *s;
09200 COL *c;
09201 SQLSMALLINT dummy;
09202 char *valc = (char *) val;
09203
09204 if (stmt == SQL_NULL_HSTMT) {
09205 return SQL_INVALID_HANDLE;
09206 }
09207 s = (STMT *) stmt;
09208 if (!s->cols) {
09209 return SQL_ERROR;
09210 }
09211 if (!valLen) {
09212 valLen = &dummy;
09213 }
09214 if (id == SQL_COLUMN_COUNT) {
09215 if (val2) {
09216 *val2 = s->ncols;
09217 }
09218 *valLen = sizeof (int);
09219 return SQL_SUCCESS;
09220 }
09221 if (id == SQL_COLUMN_TYPE && col == 0) {
09222 if (val2) {
09223 *val2 = SQL_INTEGER;
09224 }
09225 *valLen = sizeof (int);
09226 return SQL_SUCCESS;
09227 }
09228 #ifdef SQL_DESC_OCTET_LENGTH
09229 if (id == SQL_DESC_OCTET_LENGTH && col == 0) {
09230 if (val2) {
09231 *val2 = 4;
09232 }
09233 *valLen = sizeof (int);
09234 return SQL_SUCCESS;
09235 }
09236 #endif
09237 if (col < 1 || col > s->ncols) {
09238 setstat(s, -1, "invalid column", (*s->ov3) ? "07009": "S1002");
09239 return SQL_ERROR;
09240 }
09241 c = s->cols + col - 1;
09242
09243 switch (id) {
09244 case SQL_COLUMN_LABEL:
09245 if (c->label) {
09246 if (valc && valMax > 0) {
09247 strncpy(valc, c->label, valMax);
09248 valc[valMax - 1] = '\0';
09249 }
09250 *valLen = strlen(c->label);
09251 goto checkLen;
09252 }
09253
09254 case SQL_COLUMN_NAME:
09255 case SQL_DESC_NAME:
09256 if (valc && valMax > 0) {
09257 strncpy(valc, c->column, valMax);
09258 valc[valMax - 1] = '\0';
09259 }
09260 *valLen = strlen(c->column);
09261 checkLen:
09262 if (*valLen >= valMax) {
09263 setstat(s, -1, "data right truncated", "01004");
09264 return SQL_SUCCESS_WITH_INFO;
09265 }
09266 return SQL_SUCCESS;
09267 #ifdef SQL_DESC_BASE_COLUMN_NAME
09268 if (strchr(c->column, '(') || strchr(c->column, ')')) {
09269 valc[0] = '\0';
09270 *valLen = 0;
09271 } else if (valc && valMax > 0) {
09272 strncpy(valc, c->column, valMax);
09273 valc[valMax - 1] = '\0';
09274 *valLen = strlen(c->column);
09275 }
09276 goto checkLen;
09277 #endif
09278 case SQL_COLUMN_TYPE:
09279 case SQL_DESC_TYPE:
09280 if (val2) {
09281 *val2 = c->type;
09282 }
09283 *valLen = sizeof (int);
09284 return SQL_SUCCESS;
09285 case SQL_COLUMN_DISPLAY_SIZE:
09286 if (val2) {
09287 *val2 = c->size;
09288 }
09289 *valLen = sizeof (int);
09290 return SQL_SUCCESS;
09291 case SQL_COLUMN_UNSIGNED:
09292 if (val2) {
09293 *val2 = c->nosign ? SQL_TRUE : SQL_FALSE;
09294 }
09295 *valLen = sizeof (int);
09296 return SQL_SUCCESS;
09297 case SQL_COLUMN_SCALE:
09298 case SQL_DESC_SCALE:
09299 if (val2) {
09300 *val2 = c->scale;
09301 }
09302 *valLen = sizeof (int);
09303 return SQL_SUCCESS;
09304 case SQL_COLUMN_PRECISION:
09305 case SQL_DESC_PRECISION:
09306 if (val2) {
09307 *val2 = c->prec;
09308 }
09309 *valLen = sizeof (int);
09310 return SQL_SUCCESS;
09311 case SQL_COLUMN_MONEY:
09312 if (val2) {
09313 *val2 = SQL_FALSE;
09314 }
09315 *valLen = sizeof (int);
09316 return SQL_SUCCESS;
09317 case SQL_COLUMN_AUTO_INCREMENT:
09318 if (val2) {
09319 *val2 = c->autoinc > 0 ? SQL_TRUE : SQL_FALSE;
09320 }
09321 *valLen = sizeof (int);
09322 return SQL_SUCCESS;
09323 case SQL_COLUMN_LENGTH:
09324 case SQL_DESC_LENGTH:
09325 if (val2) {
09326 *val2 = c->size;
09327 }
09328 *valLen = sizeof (int);
09329 return SQL_SUCCESS;
09330 case SQL_COLUMN_NULLABLE:
09331 case SQL_DESC_NULLABLE:
09332 if (val2) {
09333 *val2 = SQL_NULLABLE;
09334 }
09335 *valLen = sizeof (int);
09336 return SQL_SUCCESS;
09337 case SQL_COLUMN_SEARCHABLE:
09338 if (val2) {
09339 *val2 = SQL_SEARCHABLE;
09340 }
09341 *valLen = sizeof (int);
09342 return SQL_SUCCESS;
09343 case SQL_COLUMN_CASE_SENSITIVE:
09344 if (val2) {
09345 *val2 = SQL_TRUE;
09346 }
09347 *valLen = sizeof (int);
09348 return SQL_SUCCESS;
09349 case SQL_COLUMN_UPDATABLE:
09350 if (val2) {
09351 *val2 = SQL_TRUE;
09352 }
09353 *valLen = sizeof (int);
09354 return SQL_SUCCESS;
09355 case SQL_DESC_COUNT:
09356 if (val2) {
09357 *val2 = s->ncols;
09358 }
09359 *valLen = sizeof (int);
09360 return SQL_SUCCESS;
09361 case SQL_COLUMN_TYPE_NAME: {
09362 char *tn = c->typename ? c->typename : "varchar";
09363
09364 if (valc && valMax > 0) {
09365 strncpy(valc, tn, valMax);
09366 valc[valMax - 1] = '\0';
09367 }
09368 *valLen = strlen(tn);
09369 goto checkLen;
09370 }
09371 case SQL_COLUMN_OWNER_NAME:
09372 case SQL_COLUMN_QUALIFIER_NAME: {
09373 char *z = "";
09374
09375 if (valc && valMax > 0) {
09376 strncpy(valc, z, valMax);
09377 valc[valMax - 1] = '\0';
09378 }
09379 *valLen = strlen(z);
09380 goto checkLen;
09381 }
09382 case SQL_COLUMN_TABLE_NAME:
09383 #if (SQL_COLUMN_TABLE_NAME != SQL_DESC_TABLE_NAME)
09384 case SQL_DESC_TABLE_NAME:
09385 #endif
09386 #ifdef SQL_DESC_BASE_TABLE_NAME
09387 case SQL_DESC_BASE_TABLE_NAME:
09388 #endif
09389 if (valc && valMax > 0) {
09390 strncpy(valc, c->table, valMax);
09391 valc[valMax - 1] = '\0';
09392 }
09393 *valLen = strlen(c->table);
09394 goto checkLen;
09395 }
09396 setstat(s, -1, "unsupported column attributes %d", "HY091", id);
09397 return SQL_ERROR;
09398 }
09399
09412 SQLRETURN SQL_API
09413 SQLColAttributes(SQLHSTMT stmt, SQLUSMALLINT col, SQLUSMALLINT id,
09414 SQLPOINTER val, SQLSMALLINT valMax, SQLSMALLINT *valLen,
09415 SQLLEN *val2)
09416 {
09417 return drvcolattributes(stmt, col, id, val, valMax, valLen, val2);
09418 }
09419
09432 static SQLRETURN
09433 drvcolattribute(SQLHSTMT stmt, SQLUSMALLINT col, SQLUSMALLINT id,
09434 SQLPOINTER val, SQLSMALLINT valMax, SQLSMALLINT *valLen,
09435 SQLPOINTER val2)
09436 {
09437 STMT *s;
09438 COL *c;
09439 int v = 0;
09440 char *valc = (char *) val;
09441
09442 if (stmt == SQL_NULL_HSTMT) {
09443 return SQL_INVALID_HANDLE;
09444 }
09445 s = (STMT *) stmt;
09446 if (!s->cols) {
09447 return SQL_ERROR;
09448 }
09449 if (col < 1 || col > s->ncols) {
09450 setstat(s, -1, "invalid column", (*s->ov3) ? "07009" : "S1002");
09451 return SQL_ERROR;
09452 }
09453 c = s->cols + col - 1;
09454 switch (id) {
09455 case SQL_DESC_COUNT:
09456 v = s->ncols;
09457 break;
09458 case SQL_DESC_CATALOG_NAME:
09459 if (valc && valMax > 0) {
09460 strncpy(valc, c->db, valMax);
09461 valc[valMax - 1] = '\0';
09462 }
09463 if (valLen) {
09464 *valLen = strlen(c->db);
09465 }
09466 checkLen:
09467 if (valLen && *valLen >= valMax) {
09468 setstat(s, -1, "data right truncated", "01004");
09469 return SQL_SUCCESS_WITH_INFO;
09470 }
09471 break;
09472 case SQL_COLUMN_LENGTH:
09473 case SQL_DESC_LENGTH:
09474 v = c->size;
09475 break;
09476 case SQL_COLUMN_LABEL:
09477 if (c->label) {
09478 if (valc && valMax > 0) {
09479 strncpy(valc, c->label, valMax);
09480 valc[valMax - 1] = '\0';
09481 }
09482 if (valLen) {
09483 *valLen = strlen(c->label);
09484 }
09485 goto checkLen;
09486 }
09487
09488 case SQL_COLUMN_NAME:
09489 case SQL_DESC_NAME:
09490 if (valc && valMax > 0) {
09491 strncpy(valc, c->column, valMax);
09492 valc[valMax - 1] = '\0';
09493 }
09494 if (valLen) {
09495 *valLen = strlen(c->column);
09496 goto checkLen;
09497 }
09498 break;
09499 #ifdef SQL_DESC_BASE_COLUMN_NAME
09500 case SQL_DESC_BASE_COLUMN_NAME:
09501 if (strchr(c->column, '(') || strchr(c->column, ')')) {
09502 valc[0] = '\0';
09503 if (valLen) {
09504 *valLen = 0;
09505 goto checkLen;
09506 }
09507 } else if (valc && valMax > 0) {
09508 strncpy(valc, c->column, valMax);
09509 valc[valMax - 1] = '\0';
09510 if (valLen) {
09511 *valLen = strlen(c->column);
09512 goto checkLen;
09513 }
09514 }
09515 break;
09516 #endif
09517 case SQL_DESC_TYPE_NAME: {
09518 char *tn = c->typename ? c->typename : "varchar";
09519
09520 if (valc && valMax > 0) {
09521 strncpy(valc, tn, valMax);
09522 valc[valMax - 1] = '\0';
09523 }
09524 if (valLen) {
09525 *valLen = strlen(tn);
09526 goto checkLen;
09527 }
09528 break;
09529 }
09530 case SQL_DESC_OCTET_LENGTH:
09531 v = c->size;
09532 break;
09533 #if (SQL_COLUMN_TABLE_NAME != SQL_DESC_TABLE_NAME)
09534 case SQL_COLUMN_TABLE_NAME:
09535 #endif
09536 #ifdef SQL_DESC_BASE_TABLE_NAME
09537 case SQL_DESC_BASE_TABLE_NAME:
09538 #endif
09539 case SQL_DESC_TABLE_NAME:
09540 if (valc && valMax > 0) {
09541 strncpy(valc, c->table, valMax);
09542 valc[valMax - 1] = '\0';
09543 }
09544 if (valLen) {
09545 *valLen = strlen(c->table);
09546 goto checkLen;
09547 }
09548 break;
09549 case SQL_DESC_TYPE:
09550 v = c->type;
09551 break;
09552 case SQL_DESC_CONCISE_TYPE:
09553 switch (c->type) {
09554 case SQL_INTEGER:
09555 v = SQL_C_LONG;
09556 break;
09557 case SQL_TINYINT:
09558 v = SQL_C_TINYINT;
09559 break;
09560 case SQL_SMALLINT:
09561 v = SQL_C_SHORT;
09562 break;
09563 case SQL_FLOAT:
09564 v = SQL_C_FLOAT;
09565 break;
09566 case SQL_DOUBLE:
09567 v = SQL_C_DOUBLE;
09568 break;
09569 case SQL_TIMESTAMP:
09570 v = SQL_C_TIMESTAMP;
09571 break;
09572 case SQL_TIME:
09573 v = SQL_C_TIME;
09574 break;
09575 case SQL_DATE:
09576 v = SQL_C_DATE;
09577 break;
09578 #ifdef SQL_C_TYPE_TIMESTAMP
09579 case SQL_TYPE_TIMESTAMP:
09580 v = SQL_C_TYPE_TIMESTAMP;
09581 break;
09582 #endif
09583 #ifdef SQL_C_TYPE_TIME
09584 case SQL_TYPE_TIME:
09585 v = SQL_C_TYPE_TIME;
09586 break;
09587 #endif
09588 #ifdef SQL_C_TYPE_DATE
09589 case SQL_TYPE_DATE:
09590 v = SQL_C_TYPE_DATE;
09591 break;
09592 #endif
09593 #ifdef SQL_BIT
09594 case SQL_BIT:
09595 v = SQL_C_BIT;
09596 break;
09597 #endif
09598 #ifdef SQL_BIGINT
09599 case SQL_BIGINT:
09600 v = SQL_C_SBIGINT;
09601 break;
09602 #endif
09603 default:
09604 v = SQL_C_CHAR;
09605 break;
09606 }
09607 break;
09608 case SQL_DESC_UPDATABLE:
09609 v = SQL_TRUE;
09610 break;
09611 case SQL_COLUMN_DISPLAY_SIZE:
09612 v = c->size;
09613 break;
09614 case SQL_COLUMN_UNSIGNED:
09615 v = c->nosign ? SQL_TRUE : SQL_FALSE;
09616 break;
09617 case SQL_COLUMN_SEARCHABLE:
09618 v = SQL_SEARCHABLE;
09619 break;
09620 case SQL_COLUMN_SCALE:
09621 case SQL_DESC_SCALE:
09622 v = c->scale;
09623 break;
09624 case SQL_COLUMN_PRECISION:
09625 case SQL_DESC_PRECISION:
09626 v = c->prec;
09627 break;
09628 case SQL_COLUMN_MONEY:
09629 v = SQL_FALSE;
09630 break;
09631 case SQL_COLUMN_AUTO_INCREMENT:
09632 v = c->autoinc > 0 ? SQL_TRUE : SQL_FALSE;
09633 break;
09634 case SQL_DESC_NULLABLE:
09635 v = SQL_NULLABLE;
09636 break;
09637 default:
09638 setstat(s, -1, "unsupported column attribute %d", "HY091", id);
09639 return SQL_ERROR;
09640 }
09641 if (val2) {
09642 *(int *) val2 = v;
09643 }
09644 return SQL_SUCCESS;
09645 }
09646
09659 SQLRETURN SQL_API
09660 SQLColAttribute(SQLHSTMT stmt, SQLUSMALLINT col, SQLUSMALLINT id,
09661 SQLPOINTER val, SQLSMALLINT valMax, SQLSMALLINT *valLen,
09662 COLATTRIBUTE_LAST_ARG_TYPE val2)
09663 {
09664 return drvcolattribute(stmt, col, id, val, valMax, valLen,
09665 (SQLPOINTER) val2);
09666 }
09667
09681 static SQLRETURN
09682 drverror(SQLHENV env, SQLHDBC dbc, SQLHSTMT stmt,
09683 SQLCHAR *sqlState, SQLINTEGER *nativeErr,
09684 SQLCHAR *errmsg, SQLSMALLINT errmax, SQLSMALLINT *errlen)
09685 {
09686 SQLCHAR dummy0[6];
09687 SQLINTEGER dummy1;
09688 SQLSMALLINT dummy2;
09689
09690 if (env == SQL_NULL_HENV &&
09691 dbc == SQL_NULL_HDBC &&
09692 stmt == SQL_NULL_HSTMT) {
09693 return SQL_INVALID_HANDLE;
09694 }
09695 if (sqlState) {
09696 sqlState[0] = '\0';
09697 } else {
09698 sqlState = dummy0;
09699 }
09700 if (!nativeErr) {
09701 nativeErr = &dummy1;
09702 }
09703 *nativeErr = 0;
09704 if (!errlen) {
09705 errlen = &dummy2;
09706 }
09707 *errlen = 0;
09708 if (errmsg) {
09709 if (errmax > 0) {
09710 errmsg[0] = '\0';
09711 }
09712 } else {
09713 errmsg = dummy0;
09714 errmax = 0;
09715 }
09716 if (stmt) {
09717 STMT *s = (STMT *) stmt;
09718
09719 if (s->logmsg[0] == '\0') {
09720 goto noerr;
09721 }
09722 *nativeErr = s->naterr;
09723 strcpy((char *) sqlState, s->sqlstate);
09724 if (errmax == SQL_NTS) {
09725 strcpy((char *) errmsg, "[SQLite]");
09726 strcat((char *) errmsg, (char *) s->logmsg);
09727 *errlen = strlen((char *) errmsg);
09728 } else {
09729 strncpy((char *) errmsg, "[SQLite]", errmax);
09730 if (errmax - 8 > 0) {
09731 strncpy((char *) errmsg + 8, (char *) s->logmsg, errmax - 8);
09732 }
09733 *errlen = min(strlen((char *) s->logmsg) + 8, errmax);
09734 }
09735 s->logmsg[0] = '\0';
09736 return SQL_SUCCESS;
09737 }
09738 if (dbc) {
09739 DBC *d = (DBC *) dbc;
09740
09741 if (d->magic != DBC_MAGIC || d->logmsg[0] == '\0') {
09742 goto noerr;
09743 }
09744 *nativeErr = d->naterr;
09745 strcpy((char *) sqlState, d->sqlstate);
09746 if (errmax == SQL_NTS) {
09747 strcpy((char *) errmsg, "[SQLite]");
09748 strcat((char *) errmsg, (char *) d->logmsg);
09749 *errlen = strlen((char *) errmsg);
09750 } else {
09751 strncpy((char *) errmsg, "[SQLite]", errmax);
09752 if (errmax - 8 > 0) {
09753 strncpy((char *) errmsg + 8, (char *) d->logmsg, errmax - 8);
09754 }
09755 *errlen = min(strlen((char *) d->logmsg) + 8, errmax);
09756 }
09757 d->logmsg[0] = '\0';
09758 return SQL_SUCCESS;
09759 }
09760 noerr:
09761 sqlState[0] = '\0';
09762 errmsg[0] = '\0';
09763 *nativeErr = 0;
09764 *errlen = 0;
09765 return SQL_NO_DATA_FOUND;
09766 }
09767
09781 SQLRETURN SQL_API
09782 SQLError(SQLHENV env, SQLHDBC dbc, SQLHSTMT stmt,
09783 SQLCHAR *sqlState, SQLINTEGER *nativeErr,
09784 SQLCHAR *errmsg, SQLSMALLINT errmax, SQLSMALLINT *errlen)
09785 {
09786 return drverror(env, dbc, stmt, sqlState, nativeErr,
09787 errmsg, errmax, errlen);
09788 }
09789
09796 SQLRETURN SQL_API
09797 SQLMoreResults(SQLHSTMT stmt)
09798 {
09799 if (stmt == SQL_NULL_HSTMT) {
09800 return SQL_INVALID_HANDLE;
09801 }
09802 return SQL_NO_DATA;
09803 }
09804
09813 static SQLRETURN
09814 drvprepare(SQLHSTMT stmt, SQLCHAR *query, SQLINTEGER queryLen)
09815 {
09816 STMT *s;
09817 DBC *d;
09818 char *errp = NULL;
09819
09820 if (stmt == SQL_NULL_HSTMT) {
09821 return SQL_INVALID_HANDLE;
09822 }
09823 s = (STMT *) stmt;
09824 if (s->dbc == SQL_NULL_HDBC) {
09825 noconn:
09826 return noconn(s);
09827 }
09828 d = s->dbc;
09829 if (!d->sqlite) {
09830 goto noconn;
09831 }
09832 s3stmt_end(s);
09833 freep(&s->query);
09834 s->query = (SQLCHAR *) fixupsql((char *) query, queryLen,
09835 &s->nparams, &s->isselect, &errp);
09836 if (!s->query) {
09837 if (errp) {
09838 setstat(s, -1, errp, (*s->ov3) ? "HY000" : "S1000");
09839 return SQL_ERROR;
09840 }
09841 return nomem(s);
09842 }
09843 #ifdef CANT_PASS_VALIST_AS_CHARPTR
09844 if (s->nparams > MAX_PARAMS_FOR_MPRINTF) {
09845 freep(&s->query);
09846 setstat(s, -1, "too much parameters in query",
09847 (*s->ov3) ? "HY000" : "S1000");
09848 return SQL_ERROR;
09849 }
09850 #endif
09851 errp = NULL;
09852 freeresult(s, -1);
09853 if (s->isselect > 0) {
09854 int ret, ncols;
09855 const char *rest;
09856 char *sql, *sqltofree = NULL, **params = NULL;
09857 sqlite3_stmt *s3stmt = NULL;
09858
09859 if (s->nparams) {
09860 int i, maxp;
09861
09862 #ifdef CANT_PASS_VALIST_AS_CHARPTR
09863 maxp = MAX_PARAMS_FOR_MPRINTF;
09864 #else
09865 maxp = s->nparams;
09866 #endif
09867 params = xmalloc(maxp * sizeof (char *));
09868 if (!params) {
09869 return nomem(s);
09870 }
09871 for (i = 0; i < maxp; i++) {
09872 params[i] = NULL;
09873 }
09874 #ifdef CANT_PASS_VALIST_AS_CHARPTR
09875 sql = sqlite3_mprintf(s->query,
09876 params[0], params[1],
09877 params[2], params[3],
09878 params[4], params[5],
09879 params[6], params[7],
09880 params[8], params[9],
09881 params[10], params[11],
09882 params[12], params[13],
09883 params[14], params[15],
09884 params[16], params[17],
09885 params[18], params[19],
09886 params[20], params[21],
09887 params[22], params[23],
09888 params[24], params[25],
09889 params[26], params[27],
09890 params[28], params[29],
09891 params[30], params[31]);
09892 #else
09893 sql = sqlite3_vmprintf((char *) s->query, (char *) params);
09894 #endif
09895 sqltofree = sql;
09896 } else {
09897 sql = s->query;
09898 }
09899 freep(¶ms);
09900 if (!sql && s->nparams) {
09901 return nomem(s);
09902 }
09903 dbtraceapi(d, "sqlite3_prepare", sql);
09904 ret = sqlite3_prepare(d->sqlite, sql, -1, &s3stmt, &rest);
09905 dbtracerc(d, ret, NULL);
09906 if (sqltofree) {
09907 sqlite3_free(sql);
09908 }
09909 if (ret != SQLITE_OK) {
09910 if (s3stmt) {
09911 dbtraceapi(d, "sqlite3_finalize", 0);
09912 sqlite3_finalize(s3stmt);
09913 }
09914 setstat(s, ret, "%s (%d)", (*s->ov3) ? "HY000" : "S1000",
09915 sqlite3_errmsg(d->sqlite), ret);
09916 return SQL_ERROR;
09917 }
09918 ncols = sqlite3_column_count(s3stmt);
09919 if (ncols > 0) {
09920 int i, size;
09921 char *p;
09922 COL *dyncols;
09923 DBC *d = (DBC *) s->dbc;
09924 const char *colname, *typename;
09925
09926 for (i = size = 0; i < ncols; i++) {
09927 colname = sqlite3_column_name(s3stmt, i);
09928 size += 3 + 3 * strlen(colname);
09929 }
09930 dyncols = xmalloc(ncols * sizeof (COL) + size);
09931 if (!dyncols) {
09932 freedyncols(s);
09933 ncols = 0;
09934 } else {
09935 p = (char *) (dyncols + ncols);
09936 for (i = 0; i < ncols; i++) {
09937 char *q;
09938
09939 colname = sqlite3_column_name(s3stmt, i);
09940 if (d->trace) {
09941 fprintf(d->trace, "-- column %d name: '%s'\n",
09942 i + 1, colname);
09943 fflush(d->trace);
09944 }
09945 typename = s3stmt_coltype(s3stmt, i, d);
09946 dyncols[i].db = ((DBC *) (s->dbc))->dbname;
09947 strcpy(p, colname);
09948 dyncols[i].label = p;
09949 p += strlen(p) + 1;
09950 q = strchr(colname, '.');
09951 if (q) {
09952 char *q2 = strchr(q + 1, '.');
09953
09954
09955 if (q2) {
09956 q = q2;
09957 }
09958 }
09959 if (q) {
09960 dyncols[i].table = p;
09961 strncpy(p, colname, q - colname);
09962 p[q - colname] = '\0';
09963 p += strlen(p) + 1;
09964 strcpy(p, q + 1);
09965 dyncols[i].column = p;
09966 p += strlen(p) + 1;
09967 } else {
09968 dyncols[i].table = "";
09969 strcpy(p, colname);
09970 dyncols[i].column = p;
09971 p += strlen(p) + 1;
09972 }
09973 if (s->longnames) {
09974 dyncols[i].column = dyncols[i].label;
09975 }
09976 #ifdef SQL_LONGVARCHAR
09977 dyncols[i].type = SQL_LONGVARCHAR;
09978 dyncols[i].size = 65536;
09979 #else
09980 dyncols[i].type = SQL_VARCHAR;
09981 dyncols[i].size = 256;
09982 #endif
09983 dyncols[i].index = i;
09984 dyncols[i].scale = 0;
09985 dyncols[i].prec = 0;
09986 dyncols[i].nosign = 1;
09987 dyncols[i].autoinc = -1;
09988 dyncols[i].typename = xstrdup(typename);
09989 }
09990 freedyncols(s);
09991 s->dyncols = s->cols = dyncols;
09992 s->dcols = ncols;
09993 fixupdyncols(s, d);
09994 }
09995 }
09996 s->ncols = ncols;
09997 dbtraceapi(d, "sqlite3_finalize", 0);
09998 sqlite3_finalize(s3stmt);
09999 }
10000 mkbindcols(s, s->ncols);
10001 if (s->nparams) {
10002 s->paramset_count = 0;
10003 }
10004 return SQL_SUCCESS;
10005 }
10006
10007
10008
10009 static SQLRETURN
10010 drvexecute(SQLHSTMT stmt, int initial)
10011 {
10012 STMT *s;
10013 DBC *d;
10014 char *errp = NULL, **params = NULL, *sql, *sqltofree = NULL;
10015 int rc, i, ncols, busy_count, start_trans;
10016 SQLRETURN ret;
10017
10018 if (stmt == SQL_NULL_HSTMT) {
10019 return SQL_INVALID_HANDLE;
10020 }
10021 s = (STMT *) stmt;
10022 if (s->dbc == SQL_NULL_HDBC) {
10023 noconn:
10024 return noconn(s);
10025 }
10026 d = (DBC *) s->dbc;
10027 if (!d->sqlite) {
10028 goto noconn;
10029 }
10030 if (!s->query) {
10031 setstat(s, -1, "no query prepared", (*s->ov3) ? "HY000" : "S1000");
10032 return SQL_ERROR;
10033 }
10034 if (s->nbindparms < s->nparams) {
10035 setstat(s, -1, "unbound parameters in query",
10036 (*s->ov3) ? "HY000" : "S1000");
10037 return SQL_ERROR;
10038 }
10039 busy_count = 0;
10040 start_trans = !d->autocommit && !d->intrans && !d->trans_disable;
10041 again:
10042 s3stmt_end(s);
10043 if (initial) {
10044
10045 for (i = 0; i < s->nparams; i++) {
10046 BINDPARM *p = &s->bindparms[i];
10047
10048 if (p->param == p->parbuf) {
10049 p->param = NULL;
10050 }
10051 freep(&p->parbuf);
10052 if (p->need <= 0 &&
10053 p->lenp && *p->lenp <= SQL_LEN_DATA_AT_EXEC_OFFSET) {
10054 p->need = 1;
10055 p->offs = 0;
10056 p->len = 0;
10057 }
10058 }
10059 }
10060 if (s->nparams) {
10061 char *p;
10062 int maxp;
10063
10064 #ifdef CANT_PASS_VALIST_AS_CHARPTR
10065 maxp = MAX_PARAMS_FOR_MPRINTF;
10066 #else
10067 maxp = s->nparams;
10068 #endif
10069 params = xmalloc(maxp * sizeof (char *));
10070 if (!params) {
10071 ret = nomem(s);
10072 goto cleanup;
10073 }
10074 for (i = 0; i < maxp; i++) {
10075 params[i] = NULL;
10076 }
10077 sql = s->query;
10078 for (i = 0; i < s->nparams; i++) {
10079 params[i] = p;
10080 ret = substparam(s, &sql, i, ¶ms[i]);
10081 if (ret != SQL_SUCCESS) {
10082 freep(¶ms);
10083 goto cleanup;
10084 }
10085 }
10086 }
10087 freeresult(s, 0);
10088 if (!d->autocommit && !d->intrans && !d->trans_disable) {
10089 begin_again:
10090 rc = sqlite3_exec(d->sqlite, (d->version < verinfo(3, 0, 8)) ?
10091 "BEGIN TRANSACTION" : "BEGIN EXCLUSIVE TRANSACTION",
10092 NULL, NULL, &errp);
10093 if (rc == SQLITE_BUSY) {
10094 if (busy_handler((void *) d, ++busy_count)) {
10095 if (errp) {
10096 sqlite3_free(errp);
10097 errp = NULL;
10098 }
10099 goto begin_again;
10100 }
10101 }
10102 dbtracerc(d, rc, errp);
10103 if (rc != SQLITE_OK) {
10104 freep(¶ms);
10105 setstat(s, rc, "%s (%d)", (*s->ov3) ? "HY000" : "S1000",
10106 errp ? errp : "unknown error", rc);
10107 if (errp) {
10108 sqlite3_free(errp);
10109 errp = NULL;
10110 }
10111 ret = SQL_ERROR;
10112 goto cleanup;
10113 }
10114 d->intrans = 1;
10115 if (errp) {
10116 sqlite3_free(errp);
10117 errp = NULL;
10118 }
10119 }
10120 if (s->isselect > 0 && !d->intrans &&
10121 s->curtype == SQL_CURSOR_FORWARD_ONLY &&
10122 d->step_enable && s->nparams == 0 && d->cur_s3stmt == NULL) {
10123 s->nrows = -1;
10124 ret = s3stmt_start(s, params);
10125 if (ret == SQL_SUCCESS) {
10126 freep(¶ms);
10127 goto done2;
10128 }
10129 }
10130 if (s->nparams) {
10131 #ifdef CANT_PASS_VALIST_AS_CHARPTR
10132
10133 sql = sqlite3_mprintf(s->query,
10134 params[0], params[1],
10135 params[2], params[3],
10136 params[4], params[5],
10137 params[6], params[7],
10138 params[8], params[9],
10139 params[10], params[11],
10140 params[12], params[13],
10141 params[14], params[15],
10142 params[16], params[17],
10143 params[18], params[19],
10144 params[20], params[21],
10145 params[22], params[23],
10146 params[24], params[25],
10147 params[26], params[27],
10148 params[28], params[29],
10149 params[30], params[31]);
10150 #else
10151 sql = sqlite3_vmprintf((char *) s->query, (char *) params);
10152 #endif
10153 if (!sql) {
10154 freep(¶ms);
10155 ret = nomem(s);
10156 goto cleanup;
10157 }
10158 sqltofree = sql;
10159 } else {
10160 sql = s->query;
10161 }
10162 rc = drvgettable(d, sql, &s->rows, &s->nrows, &ncols, &errp);
10163 dbtracerc(d, rc, errp);
10164 if (sqltofree) {
10165 sqlite3_free(sql);
10166 }
10167 if (rc == SQLITE_BUSY) {
10168 if (busy_handler((void *) d, ++busy_count)) {
10169 freep(¶ms);
10170 if (errp) {
10171 sqlite3_free(errp);
10172 errp = NULL;
10173 }
10174 if (start_trans) {
10175 sqlite3_exec(d->sqlite, "ROLLBACK TRANSACTION;",
10176 NULL, NULL, NULL);
10177 d->intrans = 0;
10178 }
10179 if (s->nparams) {
10180 for (i = 0; i < s->nparams; i++) {
10181 BINDPARM *p = &s->bindparms[i];
10182
10183 if (p->param == p->parbuf) {
10184 p->param = NULL;
10185 }
10186 freep(&p->parbuf);
10187 if (!p->lenp || *p->lenp > SQL_LEN_DATA_AT_EXEC_OFFSET) {
10188 p->param = p->param0;
10189 }
10190 }
10191 s->paramset_count = 0;
10192 s->paramset_nrows = 0;
10193 }
10194 s->nrows = 0;
10195 goto again;
10196 }
10197 }
10198 if (rc != SQLITE_OK) {
10199 freep(¶ms);
10200 setstat(s, rc, "%s (%d)", (*s->ov3) ? "HY000" : "S1000",
10201 errp ? errp : "unknown error", rc);
10202 if (errp) {
10203 sqlite3_free(errp);
10204 errp = NULL;
10205 }
10206 ret = SQL_ERROR;
10207 goto cleanup;
10208 }
10209 freep(¶ms);
10210 if (errp) {
10211 sqlite3_free(errp);
10212 errp = NULL;
10213 }
10214 s->rowfree = freerows;
10215 if (!s->isselect) {
10216
10217
10218
10219 freeresult(s, -1);
10220 s->nrows = sqlite3_changes(d->sqlite);
10221 goto done;
10222 }
10223 if (s->ncols != ncols) {
10224
10225
10226
10227 setstat(s, -1, "broken result set %d/%d",
10228 (*s->ov3) ? "HY000" : "S1000", s->ncols, ncols);
10229 ret = SQL_ERROR;
10230 goto cleanup;
10231 }
10232 done:
10233 mkbindcols(s, s->ncols);
10234 done2:
10235 ret = SQL_SUCCESS;
10236 s->rowp = -1;
10237 if (s->nparams) {
10238 s->paramset_count++;
10239 s->paramset_nrows += s->nrows;
10240 if (s->paramset_count < s->paramset_size) {
10241 for (i = 0; i < s->nparams; i++) {
10242 BINDPARM *p = &s->bindparms[i];
10243
10244 if (p->param == p->parbuf) {
10245 p->param = NULL;
10246 }
10247 freep(&p->parbuf);
10248 if (!p->lenp || *p->lenp > SQL_LEN_DATA_AT_EXEC_OFFSET) {
10249 if (p->param0 && p->inc > 0) {
10250 p->param = (char *) p->param0 +
10251 s->paramset_count * p->inc;
10252 }
10253 }
10254 }
10255 goto again;
10256 }
10257 }
10258 cleanup:
10259 if (ret != SQL_NEED_DATA && s->nparams) {
10260 for (i = 0; i < s->nparams; i++) {
10261 BINDPARM *p = &s->bindparms[i];
10262
10263 if (p->param == p->parbuf) {
10264 p->param = NULL;
10265 }
10266 freep(&p->parbuf);
10267 if (!p->lenp || *p->lenp > SQL_LEN_DATA_AT_EXEC_OFFSET) {
10268 p->param = p->param0;
10269 }
10270 }
10271 s->nrows = s->paramset_nrows;
10272 s->paramset_count = 0;
10273 s->paramset_nrows = 0;
10274 }
10275 return ret;
10276 }
10277
10286 SQLRETURN SQL_API
10287 SQLPrepare(SQLHSTMT stmt, SQLCHAR *query, SQLINTEGER queryLen)
10288 {
10289 return drvprepare(stmt, query, queryLen);
10290 }
10291
10298 SQLRETURN SQL_API
10299 SQLExecute(SQLHSTMT stmt)
10300 {
10301 return drvexecute(stmt, 1);
10302 }
10303
10312 SQLRETURN SQL_API
10313 SQLExecDirect(SQLHSTMT stmt, SQLCHAR *query, SQLINTEGER queryLen)
10314 {
10315 if (drvprepare(stmt, query, queryLen) != SQL_SUCCESS) {
10316 return SQL_ERROR;
10317 }
10318 return drvexecute(stmt, 1);
10319 }
10320
10321 #ifdef _WIN32
10322 #ifndef WITHOUT_DRIVERMGR
10323
10324
10325
10326
10327
10328 #include <windowsx.h>
10329 #include <winuser.h>
10330
10331 #define stricmp _stricmp
10332
10333 static HINSTANCE NEAR hModule;
10334
10335 #define MAXPATHLEN (255+1)
10336 #define MAXKEYLEN (15+1)
10337 #define MAXDESC (255+1)
10338 #define MAXDSNAME (32+1)
10339 #define MAXTONAME (32+1)
10340 #define MAXDBNAME (255+1)
10341
10342
10343
10344 #define KEY_DSN 0
10345 #define KEY_DESC 1
10346 #define KEY_DBNAME 2
10347 #define KEY_BUSY 3
10348 #define KEY_DRIVER 4
10349 #define KEY_STEPAPI 5
10350 #define KEY_SYNCP 6
10351 #define KEY_NOTXN 7
10352 #define KEY_LONGNAM 8
10353 #define NUMOFKEYS 9
10354
10355 typedef struct {
10356 BOOL supplied;
10357 char attr[MAXPATHLEN];
10358 } ATTR;
10359
10360 typedef struct {
10361 SQLHWND parent;
10362 LPCSTR driver;
10363 ATTR attr[NUMOFKEYS];
10364 char DSN[MAXDSNAME];
10365 BOOL newDSN;
10366 BOOL defDSN;
10367 } SETUPDLG;
10368
10369 static struct {
10370 char *key;
10371 int ikey;
10372 } attrLookup[] = {
10373 { "DSN", KEY_DSN },
10374 { "DESC", KEY_DESC },
10375 { "Description", KEY_DESC},
10376 { "Database", KEY_DBNAME },
10377 { "Timeout", KEY_BUSY },
10378 { "Driver", KEY_DRIVER },
10379 { "StepAPI", KEY_STEPAPI },
10380 { "SyncPragma", KEY_SYNCP },
10381 { "NoTXN", KEY_NOTXN },
10382 { "LongNames", KEY_LONGNAM },
10383 { NULL, 0 }
10384 };
10385
10392 static void
10393 ParseAttributes(LPCSTR attribs, SETUPDLG *setupdlg)
10394 {
10395 char *str = (char *) attribs, *start, key[MAXKEYLEN];
10396 int elem, nkey;
10397
10398 while (*str) {
10399 start = str;
10400 if ((str = strchr(str, '=')) == NULL) {
10401 return;
10402 }
10403 elem = -1;
10404 nkey = str - start;
10405 if (nkey < sizeof (key)) {
10406 int i;
10407
10408 memcpy(key, start, nkey);
10409 key[nkey] = '\0';
10410 for (i = 0; attrLookup[i].key; i++) {
10411 if (stricmp(attrLookup[i].key, key) == 0) {
10412 elem = attrLookup[i].ikey;
10413 break;
10414 }
10415 }
10416 }
10417 start = ++str;
10418 while (*str && *str != ';') {
10419 ++str;
10420 }
10421 if (elem >= 0) {
10422 int end = min(str - start, sizeof (setupdlg->attr[elem].attr) - 1);
10423
10424 setupdlg->attr[elem].supplied = TRUE;
10425 memcpy(setupdlg->attr[elem].attr, start, end);
10426 setupdlg->attr[elem].attr[end] = '\0';
10427 }
10428 ++str;
10429 }
10430 }
10431
10439 static BOOL
10440 SetDSNAttributes(HWND parent, SETUPDLG *setupdlg)
10441 {
10442 char *dsn = setupdlg->attr[KEY_DSN].attr;
10443
10444 if (setupdlg->newDSN && strlen(dsn) == 0) {
10445 return FALSE;
10446 }
10447 if (!SQLWriteDSNToIni(dsn, setupdlg->driver)) {
10448 if (parent) {
10449 char buf[MAXPATHLEN], msg[MAXPATHLEN];
10450
10451 LoadString(hModule, IDS_BADDSN, buf, sizeof (buf));
10452 wsprintf(msg, buf, dsn);
10453 LoadString(hModule, IDS_MSGTITLE, buf, sizeof (buf));
10454 MessageBox(parent, msg, buf,
10455 MB_ICONEXCLAMATION | MB_OK | MB_TASKMODAL |
10456 MB_SETFOREGROUND);
10457 }
10458 return FALSE;
10459 }
10460 if (parent || setupdlg->attr[KEY_DESC].supplied) {
10461 SQLWritePrivateProfileString(dsn, "Description",
10462 setupdlg->attr[KEY_DESC].attr,
10463 ODBC_INI);
10464 }
10465 if (parent || setupdlg->attr[KEY_DBNAME].supplied) {
10466 SQLWritePrivateProfileString(dsn, "Database",
10467 setupdlg->attr[KEY_DBNAME].attr,
10468 ODBC_INI);
10469 }
10470 if (parent || setupdlg->attr[KEY_BUSY].supplied) {
10471 SQLWritePrivateProfileString(dsn, "Timeout",
10472 setupdlg->attr[KEY_BUSY].attr,
10473 ODBC_INI);
10474 }
10475 if (parent || setupdlg->attr[KEY_STEPAPI].supplied) {
10476 SQLWritePrivateProfileString(dsn, "StepAPI",
10477 setupdlg->attr[KEY_STEPAPI].attr,
10478 ODBC_INI);
10479 }
10480 if (parent || setupdlg->attr[KEY_SYNCP].supplied) {
10481 SQLWritePrivateProfileString(dsn, "SyncPragma",
10482 setupdlg->attr[KEY_SYNCP].attr,
10483 ODBC_INI);
10484 }
10485 if (parent || setupdlg->attr[KEY_NOTXN].supplied) {
10486 SQLWritePrivateProfileString(dsn, "NoTXN",
10487 setupdlg->attr[KEY_NOTXN].attr,
10488 ODBC_INI);
10489 }
10490 if (parent || setupdlg->attr[KEY_LONGNAM].supplied) {
10491 SQLWritePrivateProfileString(dsn, "LongNames",
10492 setupdlg->attr[KEY_LONGNAM].attr,
10493 ODBC_INI);
10494 }
10495 if (setupdlg->attr[KEY_DSN].supplied &&
10496 stricmp(setupdlg->DSN, setupdlg->attr[KEY_DSN].attr)) {
10497 SQLRemoveDSNFromIni(setupdlg->DSN);
10498 }
10499 return TRUE;
10500 }
10501
10507 static void
10508 GetAttributes(SETUPDLG *setupdlg)
10509 {
10510 char *dsn = setupdlg->attr[KEY_DSN].attr;
10511
10512 if (!setupdlg->attr[KEY_DESC].supplied) {
10513 SQLGetPrivateProfileString(dsn, "Description", "",
10514 setupdlg->attr[KEY_DESC].attr,
10515 sizeof (setupdlg->attr[KEY_DESC].attr),
10516 ODBC_INI);
10517 }
10518 if (!setupdlg->attr[KEY_DBNAME].supplied) {
10519 SQLGetPrivateProfileString(dsn, "Database", "",
10520 setupdlg->attr[KEY_DBNAME].attr,
10521 sizeof (setupdlg->attr[KEY_DBNAME].attr),
10522 ODBC_INI);
10523 }
10524 if (!setupdlg->attr[KEY_BUSY].supplied) {
10525 SQLGetPrivateProfileString(dsn, "Timeout", "1000",
10526 setupdlg->attr[KEY_BUSY].attr,
10527 sizeof (setupdlg->attr[KEY_BUSY].attr),
10528 ODBC_INI);
10529 }
10530 if (!setupdlg->attr[KEY_STEPAPI].supplied) {
10531 SQLGetPrivateProfileString(dsn, "StepAPI", "0",
10532 setupdlg->attr[KEY_STEPAPI].attr,
10533 sizeof (setupdlg->attr[KEY_STEPAPI].attr),
10534 ODBC_INI);
10535 }
10536 if (!setupdlg->attr[KEY_SYNCP].supplied) {
10537 SQLGetPrivateProfileString(dsn, "SyncPragma", "NORMAL",
10538 setupdlg->attr[KEY_SYNCP].attr,
10539 sizeof (setupdlg->attr[KEY_SYNCP].attr),
10540 ODBC_INI);
10541 }
10542 if (!setupdlg->attr[KEY_NOTXN].supplied) {
10543 SQLGetPrivateProfileString(dsn, "NoTXN", "",
10544 setupdlg->attr[KEY_NOTXN].attr,
10545 sizeof (setupdlg->attr[KEY_NOTXN].attr),
10546 ODBC_INI);
10547 }
10548 if (!setupdlg->attr[KEY_LONGNAM].supplied) {
10549 SQLGetPrivateProfileString(dsn, "LongNames", "",
10550 setupdlg->attr[KEY_LONGNAM].attr,
10551 sizeof (setupdlg->attr[KEY_LONGNAM].attr),
10552 ODBC_INI);
10553 }
10554 }
10555
10561 static void
10562 GetDBFile(HWND hdlg)
10563 {
10564 SETUPDLG *setupdlg = (SETUPDLG *) GetWindowLong(hdlg, DWL_USER);
10565 OPENFILENAME ofn;
10566
10567 memset(&ofn, 0, sizeof (ofn));
10568 ofn.lStructSize = sizeof (ofn);
10569 ofn.hwndOwner = hdlg;
10570 ofn.hInstance = (HINSTANCE) GetWindowLong(hdlg, GWL_HINSTANCE);
10571 ofn.lpstrFile = (LPTSTR) setupdlg->attr[KEY_DBNAME].attr;
10572 ofn.nMaxFile = MAXPATHLEN;
10573 ofn.Flags = OFN_HIDEREADONLY | OFN_PATHMUSTEXIST |
10574 OFN_NOCHANGEDIR | OFN_EXPLORER | OFN_FILEMUSTEXIST;
10575 if (GetOpenFileName(&ofn)) {
10576 SetDlgItemText(hdlg, IDC_DBNAME, setupdlg->attr[KEY_DBNAME].attr);
10577 setupdlg->attr[KEY_DBNAME].supplied = TRUE;
10578 }
10579 }
10580
10590 static BOOL CALLBACK
10591 ConfigDlgProc(HWND hdlg, WORD wmsg, WPARAM wparam, LPARAM lparam)
10592 {
10593 SETUPDLG *setupdlg = NULL;
10594 WORD index;
10595
10596 switch (wmsg) {
10597 case WM_INITDIALOG:
10598 SetWindowLong(hdlg, DWL_USER, lparam);
10599 setupdlg = (SETUPDLG *) lparam;
10600 GetAttributes(setupdlg);
10601 SetDlgItemText(hdlg, IDC_DSNAME, setupdlg->attr[KEY_DSN].attr);
10602 SetDlgItemText(hdlg, IDC_DESC, setupdlg->attr[KEY_DESC].attr);
10603 SetDlgItemText(hdlg, IDC_DBNAME, setupdlg->attr[KEY_DBNAME].attr);
10604 SetDlgItemText(hdlg, IDC_TONAME, setupdlg->attr[KEY_BUSY].attr);
10605 CheckDlgButton(hdlg, IDC_STEPAPI,
10606 getbool(setupdlg->attr[KEY_STEPAPI].attr) ?
10607 BST_CHECKED : BST_UNCHECKED);
10608 CheckDlgButton(hdlg, IDC_NOTXN,
10609 getbool(setupdlg->attr[KEY_NOTXN].attr) ?
10610 BST_CHECKED : BST_UNCHECKED);
10611 CheckDlgButton(hdlg, IDC_LONGNAM,
10612 getbool(setupdlg->attr[KEY_LONGNAM].attr) ?
10613 BST_CHECKED : BST_UNCHECKED);
10614 SendDlgItemMessage(hdlg, IDC_SYNCP,
10615 CB_LIMITTEXT, (WPARAM) 10, 0);
10616 SendDlgItemMessage(hdlg, IDC_SYNCP,
10617 CB_ADDSTRING, 0, (LONG) "NORMAL");
10618 SendDlgItemMessage(hdlg, IDC_SYNCP,
10619 CB_ADDSTRING, 0, (LONG) "OFF");
10620 SendDlgItemMessage(hdlg, IDC_SYNCP,
10621 CB_ADDSTRING, 0, (LONG) "FULL");
10622 SendDlgItemMessage(hdlg, IDC_SYNCP,
10623 CB_SELECTSTRING, (WORD) -1,
10624 (LONG) setupdlg->attr[KEY_SYNCP].attr);
10625 if (setupdlg->defDSN) {
10626 EnableWindow(GetDlgItem(hdlg, IDC_DSNAME), FALSE);
10627 EnableWindow(GetDlgItem(hdlg, IDC_DSNAMETEXT), FALSE);
10628 } else {
10629 SendDlgItemMessage(hdlg, IDC_DSNAME,
10630 EM_LIMITTEXT, (WPARAM) (MAXDSNAME - 1), 0L);
10631 SendDlgItemMessage(hdlg, IDC_DESC,
10632 EM_LIMITTEXT, (WPARAM) (MAXDESC - 1), 0L);
10633 SendDlgItemMessage(hdlg, IDC_DBNAME,
10634 EM_LIMITTEXT, (WPARAM) (MAXDBNAME - 1), 0L);
10635 SendDlgItemMessage(hdlg, IDC_TONAME,
10636 EM_LIMITTEXT, (WPARAM) (MAXTONAME - 1), 0L);
10637 }
10638 return TRUE;
10639 case WM_COMMAND:
10640 switch (GET_WM_COMMAND_ID(wparam, lparam)) {
10641 case IDC_DSNAME:
10642 if (GET_WM_COMMAND_CMD(wparam, lparam) == EN_CHANGE) {
10643 char item[MAXDSNAME];
10644
10645 EnableWindow(GetDlgItem(hdlg, IDOK),
10646 GetDlgItemText(hdlg, IDC_DSNAME,
10647 item, sizeof (item)));
10648 return TRUE;
10649 }
10650 break;
10651 case IDC_BROWSE:
10652 GetDBFile(hdlg);
10653 break;
10654 case IDOK:
10655 setupdlg = (SETUPDLG *) GetWindowLong(hdlg, DWL_USER);
10656 if (!setupdlg->defDSN) {
10657 GetDlgItemText(hdlg, IDC_DSNAME,
10658 setupdlg->attr[KEY_DSN].attr,
10659 sizeof (setupdlg->attr[KEY_DSN].attr));
10660 }
10661 GetDlgItemText(hdlg, IDC_DESC,
10662 setupdlg->attr[KEY_DESC].attr,
10663 sizeof (setupdlg->attr[KEY_DESC].attr));
10664 GetDlgItemText(hdlg, IDC_DBNAME,
10665 setupdlg->attr[KEY_DBNAME].attr,
10666 sizeof (setupdlg->attr[KEY_DBNAME].attr));
10667 GetDlgItemText(hdlg, IDC_TONAME,
10668 setupdlg->attr[KEY_BUSY].attr,
10669 sizeof (setupdlg->attr[KEY_BUSY].attr));
10670 index = SendDlgItemMessage(hdlg, IDC_SYNCP,
10671 CB_GETCURSEL, (WORD) 0, (LONG) 0);
10672 if (index != (WORD) CB_ERR) {
10673 SendDlgItemMessage(hdlg, IDC_SYNCP,
10674 CB_GETLBTEXT, index,
10675 (LONG) setupdlg->attr[KEY_SYNCP].attr);
10676 }
10677 strcpy(setupdlg->attr[KEY_STEPAPI].attr,
10678 IsDlgButtonChecked(hdlg, IDC_STEPAPI) == BST_CHECKED ?
10679 "1" : "0");
10680 strcpy(setupdlg->attr[KEY_NOTXN].attr,
10681 IsDlgButtonChecked(hdlg, IDC_NOTXN) == BST_CHECKED ?
10682 "1" : "0");
10683 strcpy(setupdlg->attr[KEY_LONGNAM].attr,
10684 IsDlgButtonChecked(hdlg, IDC_LONGNAM) == BST_CHECKED ?
10685 "1" : "0");
10686 SetDSNAttributes(hdlg, setupdlg);
10687
10688 case IDCANCEL:
10689 EndDialog(hdlg, wparam);
10690 return TRUE;
10691 }
10692 break;
10693 }
10694 return FALSE;
10695 }
10696
10706 BOOL INSTAPI
10707 ConfigDSN(HWND hwnd, WORD request, LPCSTR driver, LPCSTR attribs)
10708 {
10709 BOOL success;
10710 SETUPDLG *setupdlg;
10711
10712 setupdlg = (SETUPDLG *) xmalloc(sizeof (SETUPDLG));
10713 if (setupdlg == NULL) {
10714 return FALSE;
10715 }
10716 memset(setupdlg, 0, sizeof (SETUPDLG));
10717 if (attribs) {
10718 ParseAttributes(attribs, setupdlg);
10719 }
10720 if (setupdlg->attr[KEY_DSN].supplied) {
10721 strcpy(setupdlg->DSN, setupdlg->attr[KEY_DSN].attr);
10722 } else {
10723 setupdlg->DSN[0] = '\0';
10724 }
10725 if (request == ODBC_REMOVE_DSN) {
10726 if (!setupdlg->attr[KEY_DSN].supplied) {
10727 success = FALSE;
10728 } else {
10729 success = SQLRemoveDSNFromIni(setupdlg->attr[KEY_DSN].attr);
10730 }
10731 } else {
10732 setupdlg->parent = hwnd;
10733 setupdlg->driver = driver;
10734 setupdlg->newDSN = request == ODBC_ADD_DSN;
10735 setupdlg->defDSN = stricmp(setupdlg->attr[KEY_DSN].attr,
10736 "Default") == 0;
10737 if (hwnd) {
10738 success = DialogBoxParam(hModule, MAKEINTRESOURCE(CONFIGDSN),
10739 hwnd, (DLGPROC) ConfigDlgProc,
10740 (LONG) setupdlg) == IDOK;
10741 } else if (setupdlg->attr[KEY_DSN].supplied) {
10742 success = SetDSNAttributes(hwnd, setupdlg);
10743 } else {
10744 success = FALSE;
10745 }
10746 }
10747 xfree(setupdlg);
10748 return success;
10749 }
10750
10760 static BOOL CALLBACK
10761 DriverConnectProc(HWND hdlg, WORD wmsg, WPARAM wparam, LPARAM lparam)
10762 {
10763 SETUPDLG *setupdlg;
10764 WORD index;
10765
10766 switch (wmsg) {
10767 case WM_INITDIALOG:
10768 SetWindowLong(hdlg, DWL_USER, lparam);
10769 setupdlg = (SETUPDLG *) lparam;
10770 SetDlgItemText(hdlg, IDC_DSNAME, setupdlg->attr[KEY_DSN].attr);
10771 SetDlgItemText(hdlg, IDC_DESC, setupdlg->attr[KEY_DESC].attr);
10772 SetDlgItemText(hdlg, IDC_DBNAME, setupdlg->attr[KEY_DBNAME].attr);
10773 SetDlgItemText(hdlg, IDC_TONAME, setupdlg->attr[KEY_BUSY].attr);
10774 SendDlgItemMessage(hdlg, IDC_DSNAME,
10775 EM_LIMITTEXT, (WPARAM) (MAXDSNAME - 1), 0L);
10776 SendDlgItemMessage(hdlg, IDC_DESC,
10777 EM_LIMITTEXT, (WPARAM) (MAXDESC - 1), 0L);
10778 SendDlgItemMessage(hdlg, IDC_DBNAME,
10779 EM_LIMITTEXT, (WORD)(MAXDBNAME - 1), 0L);
10780 SendDlgItemMessage(hdlg, IDC_TONAME,
10781 EM_LIMITTEXT, (WORD)(MAXTONAME - 1), 0L);
10782 CheckDlgButton(hdlg, IDC_STEPAPI,
10783 getbool(setupdlg->attr[KEY_STEPAPI].attr) ?
10784 BST_CHECKED : BST_UNCHECKED);
10785 CheckDlgButton(hdlg, IDC_NOTXN,
10786 getbool(setupdlg->attr[KEY_NOTXN].attr) ?
10787 BST_CHECKED : BST_UNCHECKED);
10788 CheckDlgButton(hdlg, IDC_LONGNAM,
10789 getbool(setupdlg->attr[KEY_LONGNAM].attr) ?
10790 BST_CHECKED : BST_UNCHECKED);
10791 SendDlgItemMessage(hdlg, IDC_SYNCP,
10792 CB_LIMITTEXT, (WPARAM) 10, 0);
10793 SendDlgItemMessage(hdlg, IDC_SYNCP,
10794 CB_ADDSTRING, 0, (LONG) "NORMAL");
10795 SendDlgItemMessage(hdlg, IDC_SYNCP,
10796 CB_ADDSTRING, 0, (LONG) "OFF");
10797 SendDlgItemMessage(hdlg, IDC_SYNCP,
10798 CB_ADDSTRING, 0, (LONG) "FULL");
10799 SendDlgItemMessage(hdlg, IDC_SYNCP,
10800 CB_SELECTSTRING, (WORD) -1,
10801 (LONG) setupdlg->attr[KEY_SYNCP].attr);
10802 return TRUE;
10803 case WM_COMMAND:
10804 switch (GET_WM_COMMAND_ID(wparam, lparam)) {
10805 case IDC_BROWSE:
10806 GetDBFile(hdlg);
10807 break;
10808 case IDOK:
10809 setupdlg = (SETUPDLG *) GetWindowLong(hdlg, DWL_USER);
10810 GetDlgItemText(hdlg, IDC_DSNAME,
10811 setupdlg->attr[KEY_DSN].attr,
10812 sizeof (setupdlg->attr[KEY_DSN].attr));
10813 GetDlgItemText(hdlg, IDC_DBNAME,
10814 setupdlg->attr[KEY_DBNAME].attr,
10815 sizeof (setupdlg->attr[KEY_DBNAME].attr));
10816 GetDlgItemText(hdlg, IDC_TONAME,
10817 setupdlg->attr[KEY_BUSY].attr,
10818 sizeof (setupdlg->attr[KEY_BUSY].attr));
10819 index = SendDlgItemMessage(hdlg, IDC_SYNCP,
10820 CB_GETCURSEL, (WORD) 0, (LONG) 0);
10821 if (index != (WORD) CB_ERR) {
10822 SendDlgItemMessage(hdlg, IDC_SYNCP,
10823 CB_GETLBTEXT, index,
10824 (LONG) setupdlg->attr[KEY_SYNCP].attr);
10825 }
10826 strcpy(setupdlg->attr[KEY_STEPAPI].attr,
10827 IsDlgButtonChecked(hdlg, IDC_STEPAPI) == BST_CHECKED ?
10828 "1" : "0");
10829 strcpy(setupdlg->attr[KEY_NOTXN].attr,
10830 IsDlgButtonChecked(hdlg, IDC_NOTXN) == BST_CHECKED ?
10831 "1" : "0");
10832 strcpy(setupdlg->attr[KEY_LONGNAM].attr,
10833 IsDlgButtonChecked(hdlg, IDC_LONGNAM) == BST_CHECKED ?
10834 "1" : "0");
10835
10836 case IDCANCEL:
10837 EndDialog(hdlg, GET_WM_COMMAND_ID(wparam, lparam) == IDOK);
10838 return TRUE;
10839 }
10840 }
10841 return FALSE;
10842 }
10843
10857 static SQLRETURN
10858 drvdriverconnect(SQLHDBC dbc, SQLHWND hwnd,
10859 SQLCHAR *connIn, SQLSMALLINT connInLen,
10860 SQLCHAR *connOut, SQLSMALLINT connOutMax,
10861 SQLSMALLINT *connOutLen, SQLUSMALLINT drvcompl)
10862 {
10863 BOOL maybeprompt, prompt = FALSE;
10864 DBC *d;
10865 SETUPDLG *setupdlg;
10866 short ret;
10867 SQLRETURN rc;
10868
10869 if (dbc == SQL_NULL_HDBC) {
10870 return SQL_INVALID_HANDLE;
10871 }
10872 d = (DBC *) dbc;
10873 if (d->sqlite) {
10874 setstatd(d, -1, "connection already established", "08002");
10875 return SQL_ERROR;
10876 }
10877 setupdlg = (SETUPDLG *) xmalloc(sizeof (SETUPDLG));
10878 if (setupdlg == NULL) {
10879 return SQL_ERROR;
10880 }
10881 memset(setupdlg, 0, sizeof (SETUPDLG));
10882 maybeprompt = drvcompl == SQL_DRIVER_COMPLETE ||
10883 drvcompl == SQL_DRIVER_COMPLETE_REQUIRED;
10884 if (connIn == NULL || !connInLen ||
10885 (connInLen == SQL_NTS && !connIn[0])) {
10886 prompt = TRUE;
10887 } else {
10888 ParseAttributes(connIn, setupdlg);
10889 if (!setupdlg->attr[KEY_DSN].attr[0] &&
10890 drvcompl == SQL_DRIVER_COMPLETE_REQUIRED) {
10891 strcpy(setupdlg->attr[KEY_DSN].attr, "DEFAULT");
10892 }
10893 GetAttributes(setupdlg);
10894 if (drvcompl == SQL_DRIVER_PROMPT ||
10895 (maybeprompt &&
10896 (!setupdlg->attr[KEY_DSN].attr[0] ||
10897 !setupdlg->attr[KEY_DBNAME].attr[0]))) {
10898 prompt = TRUE;
10899 }
10900 }
10901 retry:
10902 if (prompt) {
10903 ret = DialogBoxParam(hModule, MAKEINTRESOURCE(DRIVERCONNECT),
10904 hwnd, (DLGPROC) DriverConnectProc,
10905 (LONG) setupdlg);
10906 if (!ret || ret == -1) {
10907 xfree(setupdlg);
10908 return SQL_NO_DATA_FOUND;
10909 }
10910 }
10911 if (connOut || connOutLen) {
10912 char buf[1024];
10913 int len, count;
10914 char dsn_0 = setupdlg->attr[KEY_DSN].attr[0];
10915 char drv_0 = setupdlg->attr[KEY_DRIVER].attr[0];
10916
10917 buf[0] = '\0';
10918 count = snprintf(buf, sizeof (buf),
10919 "%s%s%s%s%s%sDatabase=%s;StepAPI=%s;"
10920 "SyncPragma=%s;NoTXN=%s;Timeout=%s;LongNames=%s",
10921 dsn_0 ? "DSN=" : "",
10922 dsn_0 ? setupdlg->attr[KEY_DSN].attr : "",
10923 dsn_0 ? ";" : "",
10924 drv_0 ? "Driver=" : "",
10925 drv_0 ? setupdlg->attr[KEY_DRIVER].attr : "",
10926 drv_0 ? ";" : "",
10927 setupdlg->attr[KEY_DBNAME].attr,
10928 setupdlg->attr[KEY_STEPAPI].attr,
10929 setupdlg->attr[KEY_SYNCP].attr,
10930 setupdlg->attr[KEY_NOTXN].attr,
10931 setupdlg->attr[KEY_BUSY].attr,
10932 setupdlg->attr[KEY_LONGNAM].attr);
10933 if (count < 0) {
10934 buf[sizeof (buf) - 1] = '\0';
10935 }
10936 len = min(connOutMax - 1, strlen(buf));
10937 if (connOut) {
10938 strncpy(connOut, buf, len);
10939 connOut[len] = '\0';
10940 }
10941 if (connOutLen) {
10942 *connOutLen = len;
10943 }
10944 }
10945 d->longnames = getbool(setupdlg->attr[KEY_LONGNAM].attr);
10946 rc = dbopen(d, setupdlg->attr[KEY_DBNAME].attr,
10947 setupdlg->attr[KEY_DSN].attr,
10948 setupdlg->attr[KEY_STEPAPI].attr,
10949 setupdlg->attr[KEY_SYNCP].attr,
10950 setupdlg->attr[KEY_NOTXN].attr,
10951 setupdlg->attr[KEY_BUSY].attr);
10952 if (rc != SQL_SUCCESS) {
10953 if (maybeprompt && !prompt) {
10954 prompt = TRUE;
10955 goto retry;
10956 }
10957 xfree(setupdlg);
10958 return rc;
10959 }
10960 xfree(setupdlg);
10961 return SQL_SUCCESS;
10962 }
10963
10964 #endif
10965 #endif
10966
10967 #ifndef WITHOUT_DRIVERMGR
10968
10982 SQLRETURN SQL_API
10983 SQLDriverConnect(SQLHDBC dbc, SQLHWND hwnd,
10984 SQLCHAR *connIn, SQLSMALLINT connInLen,
10985 SQLCHAR *connOut, SQLSMALLINT connOutMax,
10986 SQLSMALLINT *connOutLen, SQLUSMALLINT drvcompl)
10987 {
10988 return drvdriverconnect(dbc, hwnd, connIn, connInLen,
10989 connOut, connOutMax, connOutLen, drvcompl);
10990 }
10991
10992 #endif
10993
10994 #ifdef _WIN32
10995
11004 BOOL APIENTRY
11005 LibMain(HANDLE hinst, DWORD reason, LPVOID reserved)
11006 {
11007 static int initialized = 0;
11008
11009 switch (reason) {
11010 case DLL_PROCESS_ATTACH:
11011 if (!initialized++) {
11012 #ifndef _MSC_VER
11013
11014 sqlite3_complete("");
11015 #endif
11016 hModule = hinst;
11017 }
11018 break;
11019 case DLL_THREAD_ATTACH:
11020 break;
11021 case DLL_PROCESS_DETACH:
11022 --initialized;
11023 break;
11024 case DLL_THREAD_DETACH:
11025 break;
11026 default:
11027 break;
11028 }
11029 return TRUE;
11030 }
11031
11040 int __stdcall
11041 DllMain(HANDLE hinst, DWORD reason, LPVOID reserved)
11042 {
11043 return LibMain(hinst, reason, reserved);
11044 }
11045
11046 #endif
11047
11048 #if defined(HAVE_ODBCINSTEXT_H) && HAVE_ODBCINSTEXT_H
11049
11050
11051
11052
11053
11054
11055 #include <odbcinstext.h>
11056
11057 int
11058 ODBCINSTGetProperties(HODBCINSTPROPERTY prop)
11059 {
11060 static const char *instYN[] = { "No", "Yes", NULL };
11061 static const char *syncPragma[] = { "NORMAL", "OFF", "FULL", NULL };
11062
11063 prop->pNext = (HODBCINSTPROPERTY) malloc(sizeof (ODBCINSTPROPERTY));
11064 prop = prop->pNext;
11065 memset(prop, 0, sizeof (ODBCINSTPROPERTY));
11066 prop->nPromptType = ODBCINST_PROMPTTYPE_FILENAME;
11067 strncpy(prop->szName, "Database", INI_MAX_PROPERTY_NAME);
11068 strncpy(prop->szValue, "", INI_MAX_PROPERTY_VALUE);
11069 prop->pNext = (HODBCINSTPROPERTY) malloc(sizeof (ODBCINSTPROPERTY));
11070 prop = prop->pNext;
11071 memset(prop, 0, sizeof (ODBCINSTPROPERTY));
11072 prop->nPromptType = ODBCINST_PROMPTTYPE_TEXTEDIT;
11073 strncpy(prop->szName, "Timeout", INI_MAX_PROPERTY_NAME);
11074 strncpy(prop->szValue, "1000", INI_MAX_PROPERTY_VALUE);
11075 prop->pNext = (HODBCINSTPROPERTY) malloc(sizeof (ODBCINSTPROPERTY));
11076 prop = prop->pNext;
11077 memset(prop, 0, sizeof (ODBCINSTPROPERTY));
11078 prop->nPromptType = ODBCINST_PROMPTTYPE_COMBOBOX;
11079 prop->aPromptData = malloc(sizeof (instYN));
11080 memcpy(prop->aPromptData, instYN, sizeof (instYN));
11081 strncpy(prop->szName, "StepAPI", INI_MAX_PROPERTY_NAME);
11082 strncpy(prop->szValue, "No", INI_MAX_PROPERTY_VALUE);
11083 prop->pNext = (HODBCINSTPROPERTY) malloc(sizeof (ODBCINSTPROPERTY));
11084 prop = prop->pNext;
11085 memset(prop, 0, sizeof (ODBCINSTPROPERTY));
11086 prop->nPromptType = ODBCINST_PROMPTTYPE_COMBOBOX;
11087 prop->aPromptData = malloc(sizeof (instYN));
11088 memcpy(prop->aPromptData, instYN, sizeof (instYN));
11089 strncpy(prop->szName, "LongNames", INI_MAX_PROPERTY_NAME);
11090 strncpy(prop->szValue, "No", INI_MAX_PROPERTY_VALUE);
11091 prop->pNext = (HODBCINSTPROPERTY) malloc(sizeof (ODBCINSTPROPERTY));
11092 prop = prop->pNext;
11093 memset(prop, 0, sizeof (ODBCINSTPROPERTY));
11094 prop->nPromptType = ODBCINST_PROMPTTYPE_COMBOBOX;
11095 prop->aPromptData = malloc(sizeof (syncPragma));
11096 memcpy(prop->aPromptData, syncPragma, sizeof (syncPragma));
11097 strncpy(prop->szName, "SyncPragma", INI_MAX_PROPERTY_NAME);
11098 strncpy(prop->szValue, "NORMAL", INI_MAX_PROPERTY_VALUE);
11099 return 1;
11100 }
11101
11102 #endif